summaryrefslogtreecommitdiff
path: root/utils/ka/a.y
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ka/a.y')
-rw-r--r--utils/ka/a.y734
1 files changed, 734 insertions, 0 deletions
diff --git a/utils/ka/a.y b/utils/ka/a.y
new file mode 100644
index 00000000..4d927203
--- /dev/null
+++ b/utils/ka/a.y
@@ -0,0 +1,734 @@
+%{
+#include "a.h"
+%}
+%union
+{
+ Sym *sym;
+ long lval;
+ double dval;
+ char sval[8];
+ Gen gen;
+}
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+%token <lval> LMOVW LMOVD LMOVB LSWAP LADDW LCMP
+%token <lval> LBRA LFMOV LFCONV LFADD LCPOP LTRAP LJMPL LXORW
+%token <lval> LNOP LEND LRETT LUNIMP LTEXT LDATA LRETRN
+%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
+%token <lval> LREG LFREG LR LC LF
+%token <lval> LFSR LFPQ LPSR LSCHED
+%token <dval> LFCONST
+%token <sval> LSCONST
+%token <sym> LNAME LLAB LVAR
+%type <lval> con expr pointer offset sreg
+%type <gen> addr rreg name psr creg freg
+%type <gen> imm ximm fimm rel fsr fpq
+%%
+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:
+/*
+ * B.1 load integer instructions
+ */
+ LMOVW rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW addr ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD addr ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVB rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVB addr ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.2 load floating instructions
+ * includes CSR
+ */
+| LMOVD addr ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFMOV addr ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFMOV fimm ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFMOV freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFMOV freg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW addr ',' fsr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.3 load coprocessor instructions
+ * excludes CSR
+ */
+| LMOVW addr ',' creg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD addr ',' creg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.4 store integer instructions
+ */
+| LMOVW rreg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW imm ',' addr
+ {
+ if($2.offset != 0)
+ yyerror("constant must be zero");
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD rreg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVB rreg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVB imm ',' addr
+ {
+ if($2.offset != 0)
+ yyerror("constant must be zero");
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.5 store floating instructions
+ * includes CSR and CQ
+ */
+| LMOVW freg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD freg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW fsr ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD fpq ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.6 store coprocessor instructions
+ * excludes CSR and CQ
+ */
+| LMOVW creg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD creg ',' addr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.7 atomic load unsigned byte (TAS)
+ * B.8 swap
+ */
+| LSWAP addr ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.9 add instructions
+ * B.10 tagged add instructions
+ * B.11 subtract instructions
+ * B.12 tagged subtract instructions
+ * B.13 multiply step instruction
+ * B.14 logical instructions
+ * B.15 shift instructions
+ * B.17 save/restore
+ */
+| LADDW rreg ',' sreg ',' rreg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LADDW imm ',' sreg ',' rreg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LADDW rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LADDW imm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LXORW rreg ',' sreg ',' rreg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LXORW imm ',' sreg ',' rreg
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LXORW rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LXORW imm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.16 set hi
+ * other pseudo moves
+ */
+| LMOVW imm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD imm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW ximm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVD ximm ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.18 branch on integer condition
+ * B.19 floating point branch on condition
+ * B.20 coprocessor branch on condition
+ */
+| LBRA comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+/*
+ * B.21 call instruction
+ * B.22 jump and link instruction
+ */
+| LJMPL comma rel
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LJMPL comma addr
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LJMPL comma sreg ',' rel
+ {
+ outcode($1, &nullgen, $3, &$5);
+ }
+| LJMPL comma sreg ',' addr
+ {
+ outcode($1, &nullgen, $3, &$5);
+ }
+/*
+ * B.23 return from trap
+ */
+| LRETT rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.28 instruction cache flush
+ */
+| LFLUSH rel comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+| LFLUSH addr comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+/*
+ * B.24 trap on condition
+ */
+| LTRAP rreg ',' sreg
+ {
+ outcode($1, &$2, $4, &nullgen);
+ }
+| LTRAP imm ',' sreg
+ {
+ outcode($1, &$2, $4, &nullgen);
+ }
+| LTRAP rreg comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+| LTRAP comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+/*
+ * B.25 read state register instructions
+ */
+| LMOVW psr ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * B.26 write state register instructions BOTCH XOR
+ */
+| LMOVW rreg ',' psr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LMOVW imm ',' psr
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LXORW rreg ',' sreg ',' psr
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LXORW imm ',' sreg ',' psr
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * B.27 unimplemented trap
+ */
+| LUNIMP comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+| LUNIMP imm comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+/*
+ * B.29 floating point operate
+ */
+| LFCONV freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFADD freg ',' freg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LFADD freg ',' freg ',' freg
+ {
+ outcode($1, &$2, $4.reg, &$6);
+ }
+/*
+ * B.30 coprocessor operate
+ */
+| LCPOP creg ',' creg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LCPOP creg ',' creg ',' creg
+ {
+ outcode($1, &$2, $4.reg, &$6);
+ }
+/*
+ * CMP
+ */
+| LCMP rreg ',' rreg
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LCMP rreg ',' imm
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+/*
+ * NOP
+ */
+| LNOP comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+| LNOP rreg comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+| LNOP freg comma
+ {
+ outcode($1, &$2, NREG, &nullgen);
+ }
+| LNOP ',' rreg
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+| LNOP ',' freg
+ {
+ outcode($1, &nullgen, NREG, &$3);
+ }
+/*
+ * END
+ */
+| LEND comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+/*
+ * TEXT/GLOBL
+ */
+| LTEXT name ',' imm
+ {
+ outcode($1, &$2, NREG, &$4);
+ }
+| LTEXT name ',' con ',' imm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * DATA
+ */
+| LDATA name '/' con ',' imm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LDATA name '/' con ',' ximm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+| LDATA name '/' con ',' fimm
+ {
+ outcode($1, &$2, $4, &$6);
+ }
+/*
+ * RETURN
+ */
+| LRETRN comma
+ {
+ outcode($1, &nullgen, NREG, &nullgen);
+ }
+
+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;
+ }
+
+rreg:
+ sreg
+ {
+ $$ = nullgen;
+ $$.type = D_REG;
+ $$.reg = $1;
+ }
+
+fsr:
+ LFSR
+ {
+ $$ = nullgen;
+ $$.type = D_PREG;
+ $$.reg = $1;
+ }
+
+fpq:
+ LFPQ
+ {
+ $$ = nullgen;
+ $$.type = D_PREG;
+ $$.reg = $1;
+ }
+
+psr:
+ LPSR
+ {
+ $$ = nullgen;
+ $$.type = D_PREG;
+ $$.reg = $1;
+ }
+
+creg:
+ LCREG
+ {
+ $$ = nullgen;
+ $$.type = D_CREG;
+ $$.reg = $1;
+ }
+| LC '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_CREG;
+ $$.reg = $3;
+ }
+
+freg:
+ LFREG
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $1;
+ }
+| LF '(' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_FREG;
+ $$.reg = $3;
+ }
+
+ximm:
+ '$' addr
+ {
+ $$ = $2;
+ $$.type = D_CONST;
+ }
+| '$' LSCONST
+ {
+ $$ = nullgen;
+ $$.type = D_SCONST;
+ memcpy($$.sval, $2, sizeof($$.sval));
+ }
+
+fimm:
+ '$' LFCONST
+ {
+ $$ = nullgen;
+ $$.type = D_FCONST;
+ $$.dval = $2;
+ }
+| '$' '-' LFCONST
+ {
+ $$ = nullgen;
+ $$.type = D_FCONST;
+ $$.dval = -$3;
+ }
+
+imm: '$' con
+ {
+ $$ = nullgen;
+ $$.type = D_CONST;
+ $$.offset = $2;
+ }
+
+sreg:
+ LREG
+| LR '(' con ')'
+ {
+ if($$ < 0 || $$ >= NREG)
+ print("register value out of range\n");
+ $$ = $3;
+ }
+
+addr:
+ '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $2;
+ $$.offset = 0;
+ }
+| '(' sreg ',' con ')'
+ {
+ $$ = nullgen;
+ $$.type = D_ASI;
+ $$.reg = $2;
+ $$.offset = $4;
+ }
+| '(' sreg '+' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $2;
+ $$.xreg = $4;
+ $$.offset = 0;
+ }
+| name
+| con '(' sreg ')'
+ {
+ $$ = nullgen;
+ $$.type = D_OREG;
+ $$.reg = $3;
+ $$.offset = $1;
+ }
+
+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;
+ }
+
+comma:
+| ','
+
+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;
+ }