summaryrefslogtreecommitdiff
path: root/utils/1a/a.y
diff options
context:
space:
mode:
Diffstat (limited to 'utils/1a/a.y')
-rw-r--r--utils/1a/a.y402
1 files changed, 402 insertions, 0 deletions
diff --git a/utils/1a/a.y b/utils/1a/a.y
new file mode 100644
index 00000000..626154d5
--- /dev/null
+++ b/utils/1a/a.y
@@ -0,0 +1,402 @@
+%{
+#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
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr type pointer reg offset
+%type <addr> name areg
+%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;
+ }
+ }
+
+type:
+ reg
+| LFREG
+
+reg:
+ LAREG
+| LDREG
+| LTOS
+
+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;
+ }