summaryrefslogtreecommitdiff
path: root/easm
diff options
context:
space:
mode:
authorMarcin Kościelnicki <koriakin@0x04.net>2012-07-27 03:14:39 +0200
committerMarcin Kościelnicki <koriakin@0x04.net>2012-07-27 03:15:16 +0200
commit955a14781b82921007b6fa94dcc0682fb4edbe20 (patch)
tree95cb9791739899cffef3ffb20211caf908626fb1 /easm
parent0181c3e13fba4dcb5fcf0e0b979c35fc1f731bb9 (diff)
easm: Split to separate subdirectory.
Diffstat (limited to 'easm')
-rw-r--r--easm/.gitignore5
-rw-r--r--easm/CMakeLists.txt22
-rw-r--r--easm/easm.c193
-rw-r--r--easm/easm_lex.l77
-rw-r--r--easm/easm_parse.y222
-rw-r--r--easm/easm_print.c234
6 files changed, 753 insertions, 0 deletions
diff --git a/easm/.gitignore b/easm/.gitignore
new file mode 100644
index 00000000..bef29b69
--- /dev/null
+++ b/easm/.gitignore
@@ -0,0 +1,5 @@
+easm_lex.c
+easm_lex.h
+easm_parse.c
+easm_parse.h
+libeasm.a
diff --git a/easm/CMakeLists.txt b/easm/CMakeLists.txt
new file mode 100644
index 00000000..0bf9b0d5
--- /dev/null
+++ b/easm/CMakeLists.txt
@@ -0,0 +1,22 @@
+project(ENVYTOOLS C)
+cmake_minimum_required(VERSION 2.6)
+
+find_package(FLEX REQUIRED)
+find_package(BISON REQUIRED)
+
+include_directories(../include)
+
+flex_target(easm_lex easm_lex.l ${CMAKE_CURRENT_BINARY_DIR}/easm_lex.c)
+bison_target(easm_parse easm_parse.y ${CMAKE_CURRENT_BINARY_DIR}/easm_parse.c)
+add_flex_bison_dependency(easm_lex easm_parse)
+
+include_directories(.)
+
+add_library(easm easm.c ${FLEX_easm_lex_OUTPUTS} ${BISON_easm_parse_OUTPUTS} easm_print.c)
+
+target_link_libraries(easm envyutil)
+
+install(TARGETS easm
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib${LIB_SUFFIX}
+ ARCHIVE DESTINATION lib${LIB_SUFFIX})
diff --git a/easm/easm.c b/easm/easm.c
new file mode 100644
index 00000000..e591413a
--- /dev/null
+++ b/easm/easm.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2011-2012 Marcin Kościelnicki <koriakin@0x04.net>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "easm.h"
+#include <stdlib.h>
+
+struct easm_expr *easm_expr_bin(enum easm_expr_type type, struct easm_expr *e1, struct easm_expr *e2) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = type;
+ res->e1 = e1;
+ res->e2 = e2;
+ return res;
+}
+
+struct easm_expr *easm_expr_un(enum easm_expr_type type, struct easm_expr *e1) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = type;
+ res->e1 = e1;
+ return res;
+}
+
+struct easm_expr *easm_expr_num(enum easm_expr_type type, uint64_t num) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = type;
+ res->num = num;
+ return res;
+}
+
+struct easm_expr *easm_expr_str(enum easm_expr_type type, char *str) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = type;
+ res->str = str;
+ return res;
+}
+
+struct easm_expr *easm_expr_astr(struct astr astr) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = EASM_EXPR_STR;
+ res->astr = astr;
+ return res;
+}
+
+struct easm_expr *easm_expr_sinsn(struct easm_sinsn *sinsn) {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = EASM_EXPR_SINSN;
+ res->sinsn = sinsn;
+ return res;
+}
+
+struct easm_expr *easm_expr_discard() {
+ struct easm_expr *res = calloc(sizeof *res, 1);
+ res->type = EASM_EXPR_DISCARD;
+ return res;
+}
+
+void easm_del_mods(struct easm_mods *mods) {
+ if (!mods) return;
+ int i;
+ for (i = 0; i < mods->modsnum; i++)
+ free(mods->mods[i]);
+ free(mods->mods);
+ free(mods);
+}
+
+void easm_del_operand(struct easm_operand *operand) {
+ if (!operand) return;
+ easm_del_mods(operand->mods);
+ int i;
+ for (i = 0; i < operand->exprsnum; i++)
+ easm_del_expr(operand->exprs[i]);
+ free(operand->exprs);
+ free(operand);
+}
+
+void easm_del_expr(struct easm_expr *expr) {
+ if (!expr) return;
+ int i;
+ for (i = 0; i < expr->swizzlesnum; i++)
+ free(expr->swizzles[i].str);
+ free(expr->swizzles);
+ easm_del_expr(expr->e1);
+ easm_del_expr(expr->e2);
+ free(expr->astr.str);
+ free(expr->str);
+ easm_del_sinsn(expr->sinsn);
+ easm_del_mods(expr->mods);
+ free(expr);
+}
+
+void easm_del_sinsn(struct easm_sinsn *sinsn) {
+ if (!sinsn) return;
+ int i;
+ for (i = 0; i < sinsn->operandsnum; i++)
+ easm_del_operand(sinsn->operands[i]);
+ free(sinsn->operands);
+ free(sinsn->str);
+ easm_del_mods(sinsn->mods);
+ free(sinsn);
+}
+
+void easm_del_directive(struct easm_directive *directive) {
+ if (!directive) return;
+ int i;
+ for (i = 0; i < directive->paramsnum; i++)
+ easm_del_expr(directive->params[i]);
+ free(directive->params);
+ free(directive->str);
+ free(directive);
+}
+
+void easm_del_subinsn(struct easm_subinsn *subinsn) {
+ if (!subinsn) return;
+ int i;
+ for (i = 0; i < subinsn->prefsnum; i++)
+ easm_del_expr(subinsn->prefs[i]);
+ free(subinsn->prefs);
+ easm_del_sinsn(subinsn->sinsn);
+ free(subinsn);
+}
+
+void easm_del_insn(struct easm_insn *insn) {
+ if (!insn) return;
+ int i;
+ for (i = 0; i < insn->subinsnsnum; i++)
+ easm_del_subinsn(insn->subinsns[i]);
+ free(insn->subinsns);
+ free(insn);
+}
+
+void easm_del_line(struct easm_line *line) {
+ if (!line) return;
+ free(line->lname);
+ easm_del_insn(line->insn);
+ easm_del_directive(line->directive);
+ free(line);
+}
+
+void easm_del_file(struct easm_file *file) {
+ if (!file) return;
+ int i;
+ for (i = 0; i < file->linesnum; i++)
+ easm_del_line(file->lines[i]);
+ free(file->lines);
+ free(file);
+}
+
+int easm_isimm(struct easm_expr *expr) {
+ switch (expr->type) {
+ case EASM_EXPR_LOR:
+ case EASM_EXPR_LAND:
+ case EASM_EXPR_OR:
+ case EASM_EXPR_XOR:
+ case EASM_EXPR_AND:
+ case EASM_EXPR_SHL:
+ case EASM_EXPR_SHR:
+ case EASM_EXPR_ADD:
+ case EASM_EXPR_SUB:
+ case EASM_EXPR_MUL:
+ case EASM_EXPR_DIV:
+ case EASM_EXPR_MOD:
+ return easm_isimm(expr->e1) && easm_isimm(expr->e2);
+ case EASM_EXPR_NEG:
+ case EASM_EXPR_NOT:
+ case EASM_EXPR_LNOT:
+ return easm_isimm(expr->e1);
+ case EASM_EXPR_NUM:
+ case EASM_EXPR_LABEL:
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/easm/easm_lex.l b/easm/easm_lex.l
new file mode 100644
index 00000000..4725b00d
--- /dev/null
+++ b/easm/easm_lex.l
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 Marcin Kościelnicki <koriakin@0x04.net>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+%{
+#include "yy.h"
+#include "easm.h"
+#include "easm_parse.h"
+%}
+
+%option bison-bridge
+%option bison-locations
+%option reentrant
+%option noyywrap
+%option prefix="easm_"
+%option header-file="easm_lex.h"
+%option extra-type="struct yy_lex_intern"
+%option noinput
+%option nounput
+
+%s normal
+%x ncomment
+
+%%
+
+"/*"([^*]|"*"+[^/])*"*"+"/" { }
+"/+" { yyextra.nest++; BEGIN ncomment; }
+[ \t] { yyextra.ws = 1; }
+\n { yyextra.ws = 1; return '\n'; }
+"//".*\n { yyextra.ws = 1; return '\n'; }
+[a-z][a-zA-Z_0-9]* { yyextra.ws = 0; yylval->str = strdup(yytext); return T_WORD; }
+[a-zA-Z_][a-zA-Z_0-9]*: { yyextra.ws = 1; yytext[strlen(yytext)-1] = 0; yylval->str = strdup(yytext); return T_WORDC; }
+[a-zA-Z_][a-zA-Z_0-9]*"[" { yyextra.ws = 1; yytext[strlen(yytext)-1] = 0; yylval->str = strdup(yytext); return T_WORDLB; }
+\.[a-zA-Z_][a-zA-Z_0-9]* { yyextra.ws = 0; yylval->str = strdup(yytext+1); return T_DOTWORD; }
+\$[a-zA-Z_][a-zA-Z_0-9]* { yyextra.ws = 0; yylval->str = strdup(yytext+1); return T_DOLWORD; }
+\#[a-zA-Z_][a-zA-Z_0-9]* { yyextra.ws = 0; yylval->str = strdup(yytext+1); return T_HASHWORD; }
+\.(0[0-7]*|[1-9][0-9]*|0[xX][0-9a-fA-F]+) { yyextra.ws = 0; yylval->num = strtoull(yytext+1, 0, 0); return T_DOTNUM; }
+0[0-7]*|[1-9][0-9]*|0[xX][0-9a-fA-F]+ { yyextra.ws = 0; yylval->num = strtoull(yytext, 0, 0); return T_NUM; }
+"++" { yyextra.ws = 0; return T_PLUSPLUS; }
+"+=" { yyextra.ws = 0; return T_PLUSEQ; }
+"-"/[ \t] { if (yyextra.ws) { yyextra.ws = 0; return '-'; } else { yyextra.ws = 0; return T_ERR; } }
+"-"/[^-= \t] { if (yyextra.ws) { yyextra.ws = 0; return T_UMINUS; } else { yyextra.ws = 0; return '-'; } }
+"--" { yyextra.ws = 0; return T_MINUSMINUS; }
+"-=" { yyextra.ws = 0; return T_MINUSEQ; }
+"||" { yyextra.ws = 0; return T_LOR; }
+"&&" { yyextra.ws = 0; return T_LAND; }
+".(" { yyextra.ws = 0; return T_DOTLP; }
+"<<" { yyextra.ws = 0; return T_SHL; }
+">>" { yyextra.ws = 0; return T_SHR; }
+[[({] { yyextra.ws = 1; return yytext[0]; }
+[*/%+&|^~!)}\]:;#.] { yyextra.ws = 0; return yytext[0]; }
+\"([^\\"]|\\[\\"'nrtafv]|\\x[0-9a-fA-F][0-9a-fA-F])*\" { yyextra.ws = 0; yy_str_deescape(yytext, &yylval->astr); return T_STR; }
+. { return T_ERR; }
+<ncomment>"+/" { yyextra.nest--; if (!yyextra.nest) BEGIN normal; }
+<ncomment>"/+" { yyextra.nest++; }
+<ncomment>. { }
+<ncomment>\n { }
diff --git a/easm/easm_parse.y b/easm/easm_parse.y
new file mode 100644
index 00000000..d8aafbcc
--- /dev/null
+++ b/easm/easm_parse.y
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2010-2012 Marcin Kościelnicki <koriakin@0x04.net>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+%{
+#include "easm.h"
+#include "yy.h"
+#include "easm_parse.h"
+#include "easm_lex.h"
+void easm_error(YYLTYPE *loc, yyscan_t lex_state, struct easm_file **res, const char *err) {
+ fprintf(stderr, LOC_FORMAT(*loc, "%s\n"), err);
+}
+%}
+
+%locations
+%define api.pure
+%name-prefix "easm_"
+%lex-param { yyscan_t lex_state }
+%parse-param { yyscan_t lex_state }
+%parse-param { struct easm_file **res }
+/* XXX */
+
+%union {
+ uint64_t num;
+ char *str;
+ struct astr astr;
+ struct easm_file *file;
+ struct easm_line *line;
+ struct easm_insn *insn;
+ struct easm_sinsn *sinsn;
+ struct easm_subinsn *subinsn;
+ struct easm_directive *direct;
+ struct easm_expr *expr;
+ struct easm_mods *mods;
+ struct easm_operand *operand;
+}
+
+/* XXX: numeric labels */
+%token T_SHL
+%token T_SHR
+%token T_LOR
+%token T_LAND
+%token T_UMINUS
+%token T_PLUSPLUS
+%token T_MINUSMINUS
+%token T_PLUSEQ
+%token T_MINUSEQ
+%token T_DOTLP
+%token T_ERR
+%token <num> T_NUM
+%token <num> T_DOTNUM
+%token <str> T_WORD
+%token <str> T_WORDC
+%token <str> T_WORDLB
+%token <str> T_DOTWORD
+%token <str> T_HASHWORD
+%token <str> T_DOLWORD
+%token <astr> T_STR
+
+/* XXX: %type */
+%type <file> file
+%type <line> line
+%type <insn> insn
+%type <sinsn> sinsn operands
+%type <subinsn> subinsn prefs
+%type <direct> direct
+%type <expr> expr expr0 expr1 expr2 expr3 expr4 expr5 sexpr sexpr0 sexpr1 pexpr aexpr lswizzle membody
+%type <mods> mods
+%type <operand> operand
+
+/* XXX: destructors */
+
+%destructor { } <num>
+%destructor { free($$); } <str>
+%destructor { free($$.str); } <astr>
+%destructor { easm_del_mods($$); } <mods>
+%destructor { easm_del_operand($$); } <operand>
+%destructor { easm_del_expr($$); } <expr>
+%destructor { easm_del_insn($$); } <insn>
+%destructor { easm_del_subinsn($$); } <subinsn>
+%destructor { easm_del_sinsn($$); } <sinsn>
+%destructor { easm_del_directive($$); } <direct>
+%destructor { easm_del_line($$); } <line>
+%destructor { easm_del_file($$); } <file>
+
+%%
+
+start: file { *res = $1; }
+
+file: file line { $$ = $1; if ($2) ADDARRAY($$->lines, $2); }
+file: /**/ { $$ = calloc(sizeof *$$, 1); }
+
+line: direct eol { $$ = calloc(sizeof *$$, 1); $$->loc = @$; $$->type = EASM_LINE_DIRECTIVE; $$->directive = $1; }
+line: insn eol { $$ = calloc(sizeof *$$, 1); $$->loc = @$; $$->type = EASM_LINE_INSN; $$->insn = $1; }
+line: T_WORDC { $$ = calloc(sizeof *$$, 1); $$->loc = @$; $$->type = EASM_LINE_LABEL; $$->lname = $1; }
+line: '\n' { $$ = 0; }
+
+eol: '\n'
+eol: ';'
+
+direct: T_DOTWORD { $$ = calloc(sizeof *$$, 1); $$->loc = @$; $$->str = $1; }
+direct: direct expr { $$ = $1; $$->loc = @$; ADDARRAY($$->params, $2); }
+
+insn: subinsn { $$ = calloc(sizeof *$$, 1); $$->loc = @$; ADDARRAY($$->subinsns, $1); }
+insn: insn '&' subinsn { $$ = $1; $$->loc = @$; ADDARRAY($$->subinsns, $3); }
+insn: insn '\n' '&' subinsn { $$ = $1; $$->loc = @$; ADDARRAY($$->subinsns, $4); }
+insn: insn '&' '\n' subinsn { $$ = $1; $$->loc = @$; ADDARRAY($$->subinsns, $4); }
+
+subinsn: prefs sinsn { $$ = $1; $$->loc = @$; $$->sinsn = $2; }
+
+prefs: prefs pexpr { $$ = $1; ADDARRAY($$->prefs, $2); }
+prefs: /**/ { $$ = calloc(sizeof *$$, 1); }
+
+sinsn: T_WORD operands mods { $$ = $2; $$->loc = @$; $$->str = $1; $$->mods = $3; }
+
+operands: operands operand { $$ = $1; ADDARRAY($$->operands, $2); }
+operands: /**/ { $$ = calloc(sizeof *$$, 1); }
+
+operand: mods sexpr { $$ = calloc(sizeof *$$, 1); $$->loc = @$; $$->mods = $1; ADDARRAY($$->exprs, $2); }
+operand: operand '|' sexpr { $$ = $1; $$->loc = @$; ADDARRAY($$->exprs, $3); }
+
+mods: mods T_WORD { $$ = $1; ADDARRAY($$->mods, $2); $$->loc = @$; }
+mods: /**/ { $$ = calloc(sizeof *$$, 1); $$->loc = @$; }
+
+expr: expr ':' expr0 { $$ = easm_expr_bin(EASM_EXPR_VEC, $1, $3); $$->loc = @$; }
+expr: expr0
+
+expr0: expr0 T_LOR expr1 { $$ = easm_expr_bin(EASM_EXPR_LOR, $1, $3); $$->loc = @$; }
+expr0: expr1
+
+expr1: expr1 T_LAND expr2 { $$ = easm_expr_bin(EASM_EXPR_LAND, $1, $3); $$->loc = @$; }
+expr1: expr2
+
+expr2: expr2 '|' expr3 { $$ = easm_expr_bin(EASM_EXPR_OR, $1, $3); $$->loc = @$; }
+expr2: expr3
+
+expr3: expr3 '^' expr4 { $$ = easm_expr_bin(EASM_EXPR_XOR, $1, $3); $$->loc = @$; }
+expr3: expr4
+
+expr4: expr4 '&' expr5 { $$ = easm_expr_bin(EASM_EXPR_AND, $1, $3); $$->loc = @$; }
+expr4: expr5
+
+expr5: expr5 T_SHL sexpr0 { $$ = easm_expr_bin(EASM_EXPR_SHL, $1, $3); $$->loc = @$; }
+expr5: expr5 T_SHR sexpr0 { $$ = easm_expr_bin(EASM_EXPR_SHR, $1, $3); $$->loc = @$; }
+expr5: sexpr0
+
+sexpr: sexpr ':' sexpr0 { $$ = easm_expr_bin(EASM_EXPR_VEC, $1, $3); $$->loc = @$; }
+sexpr: sexpr0
+
+sexpr0: sexpr0 '+' sexpr1 { $$ = easm_expr_bin(EASM_EXPR_ADD, $1, $3); $$->loc = @$; }
+sexpr0: sexpr0 '-' sexpr1 { $$ = easm_expr_bin(EASM_EXPR_SUB, $1, $3); $$->loc = @$; }
+sexpr0: sexpr1
+
+sexpr1: sexpr1 '*' pexpr { $$ = easm_expr_bin(EASM_EXPR_MUL, $1, $3); $$->loc = @$; }
+sexpr1: sexpr1 '/' pexpr { $$ = easm_expr_bin(EASM_EXPR_DIV, $1, $3); $$->loc = @$; }
+sexpr1: sexpr1 '%' pexpr { $$ = easm_expr_bin(EASM_EXPR_MOD, $1, $3); $$->loc = @$; }
+sexpr1: pexpr
+
+pexpr: T_UMINUS pexpr { $$ = easm_expr_un(EASM_EXPR_NEG, $2); $$->loc = @$; }
+pexpr: '~' pexpr { $$ = easm_expr_un(EASM_EXPR_NOT, $2); $$->loc = @$; }
+pexpr: '!' pexpr { $$ = easm_expr_un(EASM_EXPR_LNOT, $2); $$->loc = @$; }
+pexpr: aexpr
+
+aexpr: '(' expr ')' { $$ = $2; }
+aexpr: T_NUM { $$ = easm_expr_num(EASM_EXPR_NUM, $1); $$->loc = @$; }
+aexpr: T_HASHWORD { $$ = easm_expr_str(EASM_EXPR_LABEL, $1); $$->loc = @$; }
+aexpr: T_DOLWORD { $$ = easm_expr_str(EASM_EXPR_REG, $1); $$->loc = @$; }
+aexpr: '[' membody ']' { $$ = $2; $$->loc = @$; }
+aexpr: T_WORDLB membody ']' { $$ = $2; $$->str = $1; $$->loc = @$; }
+aexpr: aexpr T_DOTWORD { $$ = easm_expr_un(EASM_EXPR_SWIZZLE, $1); ADDARRAY($$->swizzles, ((struct easm_swizzle){$2, 0})); $$->loc = @$; }
+aexpr: aexpr T_DOTNUM { $$ = easm_expr_un(EASM_EXPR_SWIZZLE, $1); ADDARRAY($$->swizzles, ((struct easm_swizzle){0, $2})); $$->loc = @$; }
+aexpr: lswizzle ')' { $$ = $1; $$->loc = @$; }
+aexpr: '(' sinsn ')' { $$ = easm_expr_sinsn($2); $$->loc = @$; }
+aexpr: '#' { $$ = easm_expr_discard(); $$->loc = @$; }
+aexpr: T_STR { $$ = easm_expr_astr($1); $$->loc = @$; }
+
+lswizzle: aexpr T_DOTLP { $$ = easm_expr_un(EASM_EXPR_SWIZZLE, $1); }
+lswizzle: lswizzle T_WORD { $$ = $1; ADDARRAY($$->swizzles, ((struct easm_swizzle){$2, 0})); }
+lswizzle: lswizzle T_NUM { $$ = $1; ADDARRAY($$->swizzles, ((struct easm_swizzle){0, $2})); }
+
+membody: mods expr { $$ = easm_expr_un(EASM_EXPR_MEM, $2); $$->mods = $1; }
+membody: mods expr T_PLUSPLUS expr { $$ = easm_expr_bin(EASM_EXPR_MEMPP, $2, $4); $$->mods = $1; }
+membody: mods expr T_MINUSMINUS expr { $$ = easm_expr_bin(EASM_EXPR_MEMMM, $2, $4); $$->mods = $1; }
+membody: mods expr T_PLUSEQ expr { $$ = easm_expr_bin(EASM_EXPR_MEMPE, $2, $4); $$->mods = $1; }
+membody: mods expr T_MINUSEQ expr { $$ = easm_expr_bin(EASM_EXPR_MEMME, $2, $4); $$->mods = $1; }
+
+%%
+
+int easm_read_file(FILE *file, const char *filename, struct easm_file **res) {
+ yyscan_t lex_state;
+ struct yy_lex_intern lex_extra;
+ lex_extra.line = 1;
+ lex_extra.pos = 1;
+ lex_extra.ws = 0;
+ lex_extra.file = filename;
+ lex_extra.nest = 0;
+ easm_lex_init_extra(lex_extra, &lex_state);
+ easm_set_in(file, lex_state);
+ int ret = easm_parse(lex_state, res);
+ easm_lex_destroy(lex_state);
+ return ret;
+}
diff --git a/easm/easm_print.c b/easm/easm_print.c
new file mode 100644
index 00000000..0a703d18
--- /dev/null
+++ b/easm/easm_print.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2012 Marcin Kościelnicki <koriakin@0x04.net>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "easm.h"
+
+void easm_print_expr(FILE *out, const struct envy_colors *cols, struct easm_expr *expr, int lvl) {
+ if (lvl <= -1 && expr->type == EASM_EXPR_VEC) {
+ easm_print_expr(out, cols, expr->e1, -1);
+ fprintf(out, "%s:%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 0);
+ } else if (lvl <= 0 && expr->type == EASM_EXPR_LOR) {
+ easm_print_expr(out, cols, expr->e1, 0);
+ fprintf(out, "%s||%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 1);
+ } else if (lvl <= 1 && expr->type == EASM_EXPR_LAND) {
+ easm_print_expr(out, cols, expr->e1, 1);
+ fprintf(out, "%s&&%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 2);
+ } else if (lvl <= 2 && expr->type == EASM_EXPR_OR) {
+ easm_print_expr(out, cols, expr->e1, 2);
+ fprintf(out, "%s|%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 3);
+ } else if (lvl <= 3 && expr->type == EASM_EXPR_XOR) {
+ easm_print_expr(out, cols, expr->e1, 3);
+ fprintf(out, "%s^%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 4);
+ } else if (lvl <= 4 && expr->type == EASM_EXPR_AND) {
+ easm_print_expr(out, cols, expr->e1, 4);
+ fprintf(out, "%s&%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 5);
+ } else if (lvl <= 5 && expr->type == EASM_EXPR_SHL) {
+ easm_print_expr(out, cols, expr->e1, 5);
+ fprintf(out, "%s<<%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 6);
+ } else if (lvl <= 5 && expr->type == EASM_EXPR_SHR) {
+ easm_print_expr(out, cols, expr->e1, 5);
+ fprintf(out, "%s>>%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr->e2, 6);
+ } else {
+ easm_print_sexpr(out, cols, expr, 0);
+ }
+}
+
+void easm_print_sexpr(FILE *out, const struct envy_colors *cols, struct easm_expr *expr, int lvl) {
+ const char *scol = 0;
+ switch (expr->special) {
+ case EASM_SPEC_NONE:
+ break;
+ case EASM_SPEC_ERR:
+ scol = cols->err;
+ break;
+ case EASM_SPEC_BTARG:
+ scol = cols->btarg;
+ break;
+ case EASM_SPEC_CTARG:
+ scol = cols->ctarg;
+ break;
+ case EASM_SPEC_MEM:
+ scol = cols->mem;
+ break;
+ case EASM_SPEC_REGSP:
+ scol = cols->regsp;
+ break;
+ default:
+ abort();
+ }
+ if (lvl <= -1 && expr->type == EASM_EXPR_VEC) {
+ easm_print_sexpr(out, cols, expr->e1, -1);
+ fprintf(out, "%s:%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 0);
+ } else if (lvl <= 0 && expr->type == EASM_EXPR_ADD) {
+ easm_print_sexpr(out, cols, expr->e1, 0);
+ fprintf(out, "%s+%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 1);
+ } else if (lvl <= 0 && expr->type == EASM_EXPR_SUB) {
+ easm_print_sexpr(out, cols, expr->e1, 0);
+ fprintf(out, "%s-%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 1);
+ } else if (lvl <= 1 && expr->type == EASM_EXPR_MUL) {
+ easm_print_sexpr(out, cols, expr->e1, 1);
+ fprintf(out, "%s*%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 2);
+ } else if (lvl <= 1 && expr->type == EASM_EXPR_DIV) {
+ easm_print_sexpr(out, cols, expr->e1, 1);
+ fprintf(out, "%s/%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 2);
+ } else if (lvl <= 1 && expr->type == EASM_EXPR_MOD) {
+ easm_print_sexpr(out, cols, expr->e1, 1);
+ fprintf(out, "%s%%%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e2, 2);
+ } else if (lvl <= 2 && expr->type == EASM_EXPR_NEG) {
+ fprintf(out, "%s-%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e1, 2);
+ } else if (lvl <= 2 && expr->type == EASM_EXPR_NOT) {
+ fprintf(out, "%s~%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e1, 2);
+ } else if (lvl <= 2 && expr->type == EASM_EXPR_LNOT) {
+ fprintf(out, "%s!%s", cols->sym, cols->reset);
+ easm_print_sexpr(out, cols, expr->e1, 2);
+ } else if (expr->type == EASM_EXPR_NUM) {
+ fprintf(out, "%s0x%"PRIx64"%s", scol?scol:cols->num, expr->num, cols->reset);
+ } else if (expr->type == EASM_EXPR_REG) {
+ fprintf(out, "%s$%s%s", scol?scol:cols->reg, expr->str, cols->reset);
+ } else if (expr->type == EASM_EXPR_LABEL) {
+ fprintf(out, "%s#%s%s", scol?scol:cols->num, expr->str, cols->reset);
+ } else if (expr->type == EASM_EXPR_STR) {
+ fprintf(out, "%s", scol?scol:cols->num);
+ print_escaped_astr(out, &expr->astr);
+ fprintf(out, "%s", cols->reset);
+ } else if (expr->type == EASM_EXPR_DISCARD) {
+ fprintf(out, "%s#%s", cols->sym, cols->reset);
+ } else if (expr->type == EASM_EXPR_SINSN) {
+ fprintf(out, "%s(%s", cols->sym, cols->reset);
+ easm_print_sinsn(out, cols, expr->sinsn);
+ fprintf(out, "%s)%s", cols->sym, cols->reset);
+ } else if (expr->type == EASM_EXPR_SWIZZLE) {
+ int i;
+ easm_print_sexpr(out, cols, expr->e1, 3);
+ fprintf(out, "%s.", cols->rname);
+ if (expr->swizzlesnum != 1) {
+ fprintf(out, "(");
+ }
+ for (i = 0; i < expr->swizzlesnum; i++) {
+ if (i)
+ fprintf(out, " ");
+ if (expr->swizzles[i].str) {
+ fprintf(out, "%s", expr->swizzles[i].str);
+ } else {
+ fprintf(out, "%"PRIu64, expr->swizzles[i].num);
+ }
+ }
+ if (expr->swizzlesnum != 1) {
+ fprintf(out, ")");
+ }
+ fprintf(out, "%s", cols->reset);
+ } else if (expr->type >= EASM_EXPR_MEM && expr->type <= EASM_EXPR_MEMME) {
+ fprintf(out, "%s%s[%s", cols->mem, expr->str?expr->str:"", cols->reset);
+ easm_print_mods(out, cols, expr->mods, 1);
+ easm_print_expr(out, cols, expr->e1, -1);
+ if (expr->type != EASM_EXPR_MEM) {
+ switch(expr->type) {
+ case EASM_EXPR_MEMPP:
+ fprintf(out, "%s++%s", cols->mem, cols->reset);
+ break;
+ case EASM_EXPR_MEMMM:
+ fprintf(out, "%s--%s", cols->mem, cols->reset);
+ break;
+ case EASM_EXPR_MEMPE:
+ fprintf(out, "%s+=%s", cols->mem, cols->reset);
+ break;
+ case EASM_EXPR_MEMME:
+ fprintf(out, "%s-=%s", cols->mem, cols->reset);
+ break;
+ default:
+ abort();
+ }
+ easm_print_expr(out, cols, expr->e2, -1);
+ }
+ fprintf(out, "%s]%s", cols->mem, cols->reset);
+ } else {
+ fprintf(out, "%s(%s", cols->sym, cols->reset);
+ easm_print_expr(out, cols, expr, -1);
+ fprintf(out, "%s)%s", cols->sym, cols->reset);
+ }
+}
+
+void easm_print_mods(FILE *out, const struct envy_colors *cols, struct easm_mods *mods, int spcafter) {
+ int i;
+ for (i = 0; i < mods->modsnum; i++) {
+ if (spcafter)
+ fprintf(out, "%s%s%s ", cols->mod, mods->mods[i], cols->reset);
+ else
+ fprintf(out, " %s%s%s", cols->mod, mods->mods[i], cols->reset);
+ }
+}
+
+void easm_print_operand(FILE *out, const struct envy_colors *cols, struct easm_operand *operand) {
+ int i;
+ easm_print_mods(out, cols, operand->mods, 0);
+ for (i = 0; i < operand->exprsnum; i++) {
+ if (i)
+ fprintf(out, " %s|%s", cols->sym, cols->reset);
+ fprintf(out, " ");
+ easm_print_sexpr(out, cols, operand->exprs[i], -1);
+ }
+}
+
+void easm_print_sinsn(FILE *out, const struct envy_colors *cols, struct easm_sinsn *sinsn) {
+ int i;
+ fprintf(out, "%s%s%s", cols->iname, sinsn->str, cols->reset);
+ for (i = 0; i < sinsn->operandsnum; i++) {
+ easm_print_operand(out, cols, sinsn->operands[i]);
+ }
+ easm_print_mods(out, cols, sinsn->mods, 0);
+}
+
+void easm_print_subinsn(FILE *out, const struct envy_colors *cols, struct easm_subinsn *subinsn) {
+ int i;
+ for (i = 0; i < subinsn->prefsnum; i++) {
+ easm_print_sexpr(out, cols, subinsn->prefs[i], 2);
+ fprintf(out, " ");
+ }
+ easm_print_sinsn(out, cols, subinsn->sinsn);
+}
+
+void easm_print_insn(FILE *out, struct envy_colors *cols, struct easm_insn *insn) {
+ int i;
+ for (i = 0; i < insn->subinsnsnum; i++) {
+ if (i)
+ fprintf(out, " %s&%s ", cols->sym, cols->reset);
+ easm_print_subinsn(out, cols, insn->subinsns[i]);
+ }
+}