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