diff options
Diffstat (limited to 'utils/0a/a.y')
| -rw-r--r-- | utils/0a/a.y | 588 |
1 files changed, 588 insertions, 0 deletions
diff --git a/utils/0a/a.y b/utils/0a/a.y new file mode 100644 index 00000000..4f72a892 --- /dev/null +++ b/utils/0a/a.y @@ -0,0 +1,588 @@ +%{ +#include "a.h" +%} +%union +{ + Sym *sym; + long lval; + double dval; + char sval[8]; + Gen gen; +} +%left '|' +%left '^' +%left '&' +%left '<' '>' +%left '+' '-' +%left '*' '/' '%' +%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5 +%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA +%token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF +%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK +%token <lval> LCONST LSP LSB LFP LPC LHI LLO LMREG +%token <lval> LTYPEX LREG LFREG LFCREG LR LM LF +%token <lval> LFCR LSCHED +%token <dval> LFCONST +%token <sval> LSCONST +%token <sym> LNAME LLAB LVAR +%type <lval> con expr pointer offset sreg +%type <gen> gen vgen lgen vlgen rel reg freg mreg fcreg +%type <gen> imm ximm ireg name oreg imr nireg fgen +%% +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 +| LNAME '=' expr ';' + { + $1->type = LVAR; + $1->value = $3; + } +| LVAR '=' expr ';' + { + if($1->value != $3) + yyerror("redeclaration of %s", $1->name); + $1->value = $3; + } +| LSCHED ';' + { + nosched = $1; + } +| ';' +| inst ';' +| error ';' + +inst: +/* + * Immed-type + */ + LTYPE1 imr ',' sreg ',' reg + { + outcode($1, &$2, $4, &$6); + } +| LTYPE1 imr ',' reg + { + outcode($1, &$2, NREG, &$4); + } +/* + * NOR + */ +| LTYPE2 imr ',' sreg ',' imr + { + outcode($1, &$2, $4, &$6); + } +| LTYPE2 imr ',' imr + { + outcode($1, &$2, NREG, &$4); + } +/* + * LOAD/STORE, but not MOVW + */ +| LTYPE3 lgen ',' gen + { + if(!isreg(&$2) && !isreg(&$4)) + print("one side must be register\n"); + outcode($1, &$2, NREG, &$4); + } +/* + * SPECIAL + */ +| LTYPE4 comma + { + outcode($1, &nullgen, NREG, &nullgen); + } +/* + * MOVW + */ +| LTYPE5 vlgen ',' vgen + { + if(!isreg(&$2) && !isreg(&$4)) + print("one side must be register\n"); + outcode($1, &$2, NREG, &$4); + } +/* + * MUL/DIV + */ +| LTYPE6 reg ',' sreg comma + { + outcode($1, &$2, $4, &nullgen); + } +| LTYPE6 reg ',' sreg ',' reg + { + outcode($1, &$2, $4, &$6); + } +/* + * JMP/JAL + */ +| LTYPE7 comma rel + { + outcode($1, &nullgen, NREG, &$3); + } +| LTYPE7 comma nireg + { + outcode($1, &nullgen, NREG, &$3); + } +| LTYPE8 comma rel + { + outcode($1, &nullgen, NREG, &$3); + } +| LTYPE8 comma nireg + { + outcode($1, &nullgen, NREG, &$3); + } +| LTYPE8 sreg ',' nireg + { + outcode($1, &nullgen, $2, &$4); + } +/* + * BEQ/BNE + */ +| LTYPE9 gen ',' rel + { + if(!isreg(&$2)) + print("left side must be register\n"); + outcode($1, &$2, NREG, &$4); + } +| LTYPE9 gen ',' sreg ',' rel + { + if(!isreg(&$2)) + print("left side must be register\n"); + outcode($1, &$2, $4, &$6); + } +/* + * B-other + */ +| LTYPEA gen ',' rel + { + if(!isreg(&$2)) + print("left side must be register\n"); + outcode($1, &$2, NREG, &$4); + } +/* + * TEXT/GLOBL + */ +| LTYPEB name ',' imm + { + outcode($1, &$2, NREG, &$4); + } +| LTYPEB name ',' con ',' imm + { + outcode($1, &$2, $4, &$6); + } +/* + * DATA + */ +| LTYPEC name '/' con ',' ximm + { + outcode($1, &$2, $4, &$6); + } +/* + * floating-type + */ +| LTYPED freg ',' freg + { + outcode($1, &$2, NREG, &$4); + } +| LTYPEE freg ',' freg + { + outcode($1, &$2, NREG, &$4); + } +| LTYPEE freg ',' LFREG ',' freg + { + outcode($1, &$2, $4, &$6); + } +| LTYPEF freg ',' LFREG comma + { + outcode($1, &$2, $4, &nullgen); + } +/* + * coprocessor branch + */ +| LTYPEG comma rel + { + outcode($1, &nullgen, NREG, &$3); + } +/* + * word + */ +| LTYPEH comma ximm + { + outcode($1, &nullgen, NREG, &$3); + } +/* + * NOP + */ +| LTYPEI comma + { + outcode($1, &nullgen, NREG, &nullgen); + } +| LTYPEI ',' vgen + { + outcode($1, &nullgen, NREG, &$3); + } +| LTYPEI vgen comma + { + outcode($1, &$2, NREG, &nullgen); + } +/* + * BREAK -- overloaded with CACHE opcode + */ +| LTYPEJ comma + { + outcode($1, &nullgen, NREG, &nullgen); + } +| LTYPEJ vgen ',' vgen + { + outcode($1, &$2, NREG, &$4); + } + +comma: +| ',' + +rel: + con '(' LPC ')' + { + $$ = nullgen; + $$.type = D_BRANCH; + $$.offset = $1 + pc; + } +| LNAME offset + { + $$ = nullgen; + if(pass == 2) + yyerror("undefined label: %s", $1->name); + $$.type = D_BRANCH; + $$.sym = $1; + $$.offset = $2; + } +| LLAB offset + { + $$ = nullgen; + $$.type = D_BRANCH; + $$.sym = $1; + $$.offset = $1->value + $2; + } + +vlgen: + lgen +| fgen +| mreg +| fcreg +| LHI + { + $$ = nullgen; + $$.type = D_HI; + } +| LLO + { + $$ = nullgen; + $$.type = D_LO; + } + +vgen: + gen +| fgen +| mreg +| fcreg +| LHI + { + $$ = nullgen; + $$.type = D_HI; + } +| LLO + { + $$ = nullgen; + $$.type = D_LO; + } + +lgen: + gen +| ximm + +fgen: + freg + +mreg: + LMREG + { + $$ = nullgen; + $$.type = D_MREG; + $$.reg = $1; + } +| LM '(' con ')' + { + $$ = nullgen; + $$.type = D_MREG; + $$.reg = $3; + } + +fcreg: + LFCREG + { + $$ = nullgen; + $$.type = D_FCREG; + $$.reg = $1; + } +| LFCR '(' con ')' + { + $$ = nullgen; + $$.type = D_FCREG; + $$.reg = $3; + } + +freg: + LFREG + { + $$ = nullgen; + $$.type = D_FREG; + $$.reg = $1; + } +| LF '(' con ')' + { + $$ = nullgen; + $$.type = D_FREG; + $$.reg = $3; + } + +ximm: '$' con + { + $$ = nullgen; + $$.type = D_CONST; + $$.offset = $2; + } +| '$' oreg + { + $$ = $2; + $$.type = D_CONST; + } +| '$' '*' '$' oreg + { + $$ = $4; + $$.type = D_OCONST; + } +| '$' LSCONST + { + $$ = nullgen; + $$.type = D_SCONST; + memcpy($$.sval, $2, sizeof($$.sval)); + } +| '$' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.dval = $2; + } +| '$' '-' LFCONST + { + $$ = nullgen; + $$.type = D_FCONST; + $$.dval = -$3; + } + +nireg: + ireg +| con ireg + { + if($1 != 0) + yyerror("offset must be zero"); + $$ = $2; + } +| name + { + $$ = $1; + if($1.name != D_EXTERN && $1.name != D_STATIC) { + } + } + +ireg: + '(' sreg ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.reg = $2; + $$.offset = 0; + } + +gen: + reg +| con + { + $$ = nullgen; + $$.type = D_OREG; + $$.offset = $1; + } +| oreg + +oreg: + name +| name '(' sreg ')' + { + $$ = $1; + $$.type = D_OREG; + $$.reg = $3; + } +| '(' sreg ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.reg = $2; + $$.offset = 0; + } +| con '(' sreg ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.reg = $3; + $$.offset = $1; + } + +imr: + reg +| imm + +imm: '$' con + { + $$ = nullgen; + $$.type = D_CONST; + $$.offset = $2; + } + +reg: + sreg + { + $$ = nullgen; + $$.type = D_REG; + $$.reg = $1; + } + +sreg: + LREG +| LR '(' expr ')' + { + if($$ < 0 || $$ >= NREG) + print("register value out of range\n"); + $$ = $3; + } + +name: + con '(' pointer ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.name = $3; + $$.sym = S; + $$.offset = $1; + } +| LNAME offset '(' pointer ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.name = $4; + $$.sym = $1; + $$.offset = $2; + } +| LNAME '<' '>' offset '(' LSB ')' + { + $$ = nullgen; + $$.type = D_OREG; + $$.name = 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; + } |
