diff options
author | Marcin Kościelnicki <koriakin@0x04.net> | 2012-07-27 03:14:39 +0200 |
---|---|---|
committer | Marcin Kościelnicki <koriakin@0x04.net> | 2012-07-27 03:15:16 +0200 |
commit | 955a14781b82921007b6fa94dcc0682fb4edbe20 (patch) | |
tree | 95cb9791739899cffef3ffb20211caf908626fb1 /easm | |
parent | 0181c3e13fba4dcb5fcf0e0b979c35fc1f731bb9 (diff) |
easm: Split to separate subdirectory.
Diffstat (limited to 'easm')
-rw-r--r-- | easm/.gitignore | 5 | ||||
-rw-r--r-- | easm/CMakeLists.txt | 22 | ||||
-rw-r--r-- | easm/easm.c | 193 | ||||
-rw-r--r-- | easm/easm_lex.l | 77 | ||||
-rw-r--r-- | easm/easm_parse.y | 222 | ||||
-rw-r--r-- | easm/easm_print.c | 234 |
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]); + } +} |