summaryrefslogtreecommitdiff
path: root/utils/0a/a.y
diff options
context:
space:
mode:
Diffstat (limited to 'utils/0a/a.y')
-rw-r--r--utils/0a/a.y588
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;
+ }