diff options
Diffstat (limited to 'utils/2a/a.y')
| -rw-r--r-- | utils/2a/a.y | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/utils/2a/a.y b/utils/2a/a.y new file mode 100644 index 00000000..2a5d5c96 --- /dev/null +++ b/utils/2a/a.y @@ -0,0 +1,540 @@ +%{ +#include "a.h" +%} +%union { + Sym *sym; + long lval; + double dval; + char sval[8]; + Addr addr; + Gen gen; + Gen2 gen2; +} +%left '|' +%left '^' +%left '&' +%left '<' '>' +%left '+' '-' +%left '*' '/' '%' +%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5 +%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA LTYPEB +%token <lval> LCONST LSP LSB LFP LPC LTOS LAREG LDREG LFREG LWID +%token <dval> LFCONST +%token <sval> LSCONST +%token <sym> LNAME LLAB LVAR +%type <lval> con expr scale type pointer reg offset +%type <addr> name areg xreg +%type <gen> gen rel +%type <gen2> noaddr gengen dstgen spec1 spec2 spec3 srcgen dstrel genrel +%% +prog: +| prog line + +line: + LLAB ':' + { + if($1->value != pc) + yyerror("redeclaration of %s", $1->name); + $1->value = pc; + } + line +| LNAME ':' + { + $1->type = LLAB; + $1->value = pc; + } + line +| ';' +| inst ';' +| error ';' + +inst: + LNAME '=' expr + { + $1->type = LVAR; + $1->value = $3; + } +| LVAR '=' expr + { + if($1->value != $3) + yyerror("redeclaration of %s", $1->name); + $1->value = $3; + } +| LTYPE1 gengen { outcode($1, &$2); } +| LTYPE2 noaddr { outcode($1, &$2); } +| LTYPE3 dstgen { outcode($1, &$2); } +| LTYPE4 spec1 { outcode($1, &$2); } +| LTYPE5 srcgen { outcode($1, &$2); } +| LTYPE6 dstrel { outcode($1, &$2); } +| LTYPE7 genrel { outcode($1, &$2); } +| LTYPE8 dstgen { outcode($1, &$2); } +| LTYPE8 gengen { outcode($1, &$2); } +| LTYPE9 noaddr { outcode($1, &$2); } +| LTYPE9 dstgen { outcode($1, &$2); } +| LTYPEA spec2 { outcode($1, &$2); } +| LTYPEB spec3 { outcode($1, &$2); } + +noaddr: + { + $$.from = nullgen; + $$.to = nullgen; + } +| ',' + { + $$.from = nullgen; + $$.to = nullgen; + } + +srcgen: + gen + { + $$.from = $1; + $$.to = nullgen; + } +| gen ',' + { + $$.from = $1; + $$.to = nullgen; + } + +dstgen: + gen + { + $$.from = nullgen; + $$.to = $1; + } +| ',' gen + { + $$.from = nullgen; + $$.to = $2; + } + +gengen: + gen ',' gen + { + $$.from = $1; + $$.to = $3; + } + +dstrel: + rel + { + $$.from = nullgen; + $$.to = $1; + } +| ',' rel + { + $$.from = nullgen; + $$.to = $2; + } + +genrel: + gen ',' rel + { + $$.from = $1; + $$.to = $3; + } + +spec1: /* DATA opcode */ + gen '/' con ',' gen + { + $1.displace = $3; + $$.from = $1; + $$.to = $5; + } + +spec2: /* bit field opcodes */ + gen ',' gen ',' con ',' con + { + $1.field = $7; + $3.field = $5; + $$.from = $1; + $$.to = $3; + } + +spec3: /* TEXT opcode */ + gengen +| gen ',' con ',' gen + { + $1.displace = $3; + $$.from = $1; + $$.to = $5; + } + +rel: + con '(' LPC ')' + { + $$ = nullgen; + $$.type = D_BRANCH; + $$.s0.offset = $1 + pc; + } +| LNAME offset + { + $$ = nullgen; + if(pass == 2) + yyerror("undefined label: %s", $1->name); + $$.type = D_BRANCH; + $$.s0.sym = $1; + $$.s0.offset = $2; + } +| LLAB offset + { + $$ = nullgen; + $$.type = D_BRANCH; + $$.s0.sym = $1; + $$.s0.offset = $1->value + $2; + } + +gen: + type + { + $$ = nullgen; + $$.type = $1; + } +| '$' con + { + $$ = nullgen; + $$.type = D_CONST; + $$.s0.offset = $2; + } +| '$' name + { + $$ = nullgen; + { + Addr *a; + a = &$$.s0; + *a = $2; + } + if($2.type == D_AUTO || $2.type == D_PARAM) + yyerror("constant cannot be automatic: %s", + $2.sym->name); + $$.type = $2.type | I_ADDR; + } +| '$' LSCONST + { + $$ = nullgen; + $$.type = D_SCONST; + memcpy($$.sval, $2, sizeof($$.sval)); + } +| '$' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.dval = $2; + } +| '$' '-' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.dval = -$3; + } +| LTOS '+' con + { + $$ = nullgen; + $$.type = D_STACK; + $$.s0.offset = $3; + } +| LTOS '-' con + { + $$ = nullgen; + $$.type = D_STACK; + $$.s0.offset = -$3; + } +| con + { + $$ = nullgen; + $$.type = D_CONST | I_INDIR; + $$.s0.offset = $1; + } +| '-' '(' LAREG ')' + { + $$ = nullgen; + $$.type = $3 | I_INDDEC; + } +| '(' LAREG ')' '+' + { + $$ = nullgen; + $$.type = $2 | I_INDINC; + } +| areg + { + $$ = nullgen; + $$.type = $1.type; + { + Addr *a; + a = &$$.s0; + *a = $1; + } + if(($$.type & D_MASK) == D_NONE) { + $$.index = D_NONE | I_INDEX1; + $$.scale = 0; + $$.displace = 0; + } + } +| areg xreg + { + $$ = nullgen; + $$.type = $1.type; + { + Addr *a; + a = &$$.s0; + *a = $1; + } + $$.index = $2.type | I_INDEX1; + $$.scale = $2.offset; + } +| '(' areg ')' xreg + { + $$ = nullgen; + $$.type = $2.type; + { + Addr *a; + a = &$$.s0; + *a = $2; + } + $$.index = $4.type | I_INDEX2; + $$.scale = $4.offset; + $$.displace = 0; + } +| con '(' areg ')' xreg + { + $$ = nullgen; + $$.type = $3.type; + { + Addr *a; + a = &$$.s0; + *a = $3; + } + $$.index = $5.type | I_INDEX2; + $$.scale = $5.offset; + $$.displace = $1; + } +| '(' areg ')' + { + $$ = nullgen; + $$.type = $2.type; + { + Addr *a; + a = &$$.s0; + *a = $2; + } + $$.index = D_NONE | I_INDEX3; + $$.scale = 0; + $$.displace = 0; + } +| con '(' areg ')' + { + $$ = nullgen; + $$.type = $3.type; + { + Addr *a; + a = &$$.s0; + *a = $3; + } + $$.index = D_NONE | I_INDEX3; + $$.scale = 0; + $$.displace = $1; + } +| '(' areg xreg ')' + { + $$ = nullgen; + $$.type = $2.type; + { + Addr *a; + a = &$$.s0; + *a = $2; + } + $$.index = $3.type | I_INDEX3; + $$.scale = $3.offset; + $$.displace = 0; + } +| con '(' areg xreg ')' + { + $$ = nullgen; + $$.type = $3.type; + { + Addr *a; + a = &$$.s0; + *a = $3; + } + $$.index = $4.type | I_INDEX3; + $$.scale = $4.offset; + $$.displace = $1; + } + +type: + reg +| LFREG + +xreg: + /* + * .W*1 0 + * .W*2 1 + * .W*4 2 + * .W*8 3 + * .L*1 4 + * .L*2 5 + * .L*4 6 + * .L*8 7 + */ + '(' reg LWID scale ')' + { + $$.type = $2; + $$.offset = $3+$4; + $$.sym = S; + } + +reg: + LAREG +| LDREG +| LTOS + +scale: + '*' con + { + switch($2) { + case 1: + $$ = 0; + break; + + case 2: + $$ = 1; + break; + + default: + yyerror("bad scale: %ld", $2); + + case 4: + $$ = 2; + break; + + case 8: + $$ = 3; + break; + } + } + +areg: + '(' LAREG ')' + { + $$.type = $2 | I_INDIR; + $$.sym = S; + $$.offset = 0; + } +| con '(' LAREG ')' + { + $$.type = $3 | I_INDIR; + $$.sym = S; + $$.offset = $1; + } +| '(' ')' + { + $$.type = D_NONE | I_INDIR; + $$.sym = S; + $$.offset = 0; + } +| con '(' ')' + { + $$.type = D_NONE | I_INDIR; + $$.sym = S; + $$.offset = $1; + } +| name + +name: + LNAME offset '(' pointer ')' + { + $$.type = $4; + $$.sym = $1; + $$.offset = $2; + } +| LNAME '<' '>' offset '(' LSB ')' + { + $$.type = D_STATIC; + $$.sym = $1; + $$.offset = $4; + } + +offset: + { + $$ = 0; + } +| '+' con + { + $$ = $2; + } +| '-' con + { + $$ = -$2; + } + +pointer: + LSB +| LSP +| LFP + +con: + LCONST +| LVAR + { + $$ = $1->value; + } +| '-' con + { + $$ = -$2; + } +| '+' con + { + $$ = $2; + } +| '~' con + { + $$ = ~$2; + } +| '(' expr ')' + { + $$ = $2; + } + +expr: + con +| expr '+' expr + { + $$ = $1 + $3; + } +| expr '-' expr + { + $$ = $1 - $3; + } +| expr '*' expr + { + $$ = $1 * $3; + } +| expr '/' expr + { + $$ = $1 / $3; + } +| expr '%' expr + { + $$ = $1 % $3; + } +| expr '<' '<' expr + { + $$ = $1 << $4; + } +| expr '>' '>' expr + { + $$ = $1 >> $4; + } +| expr '&' expr + { + $$ = $1 & $3; + } +| expr '^' expr + { + $$ = $1 ^ $3; + } +| expr '|' expr + { + $$ = $1 | $3; + } |
