summaryrefslogtreecommitdiff
path: root/asm/asm.y
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /asm/asm.y
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'asm/asm.y')
-rw-r--r--asm/asm.y385
1 files changed, 385 insertions, 0 deletions
diff --git a/asm/asm.y b/asm/asm.y
new file mode 100644
index 00000000..8a94c99b
--- /dev/null
+++ b/asm/asm.y
@@ -0,0 +1,385 @@
+%{
+#include "asm.h"
+union {
+ uvlong l;
+ double d;
+} u;
+%}
+
+%union
+{
+ Inst* inst;
+ Addr* addr;
+ vlong ival;
+ double fval;
+ String* string;
+ Sym* sym;
+ List* list;
+}
+
+%left '|'
+%left '^'
+%left '&'
+%left '<' '>'
+%left '+' '-'
+%left '*' '/' '%'
+
+%type<inst> label ilist inst
+%type<ival> con expr heapid
+%type<addr> addr raddr mem roff
+%type<list> elist
+%type<string> ptrs
+%token<ival> TOKI0 TOKI1 TOKI2 TOKI3 TCONST
+%token TOKSB TOKFP TOKHEAP TOKDB TOKDW TOKDL TOKDF TOKDS TOKVAR
+%token TOKEXT TOKMOD TOKLINK TOKENTRY TOKARRAY TOKINDIR TOKAPOP TOKLDTS TOKEXCS TOKEXC TOKETAB TOKSRC
+%token<sym> TID
+%token<fval> TFCONST
+%token<string> TSTRING
+
+%%
+prog : ilist
+ {
+ assem($1);
+ }
+ ;
+
+ilist :
+ { $$ = nil; }
+ | ilist label
+ {
+ if($2 != nil) {
+ $2->link = $1;
+ $$ = $2;
+ }
+ else
+ $$ = $1;
+ }
+ ;
+
+label : TID ':' inst
+ {
+ $3->sym = $1;
+ $$ = $3;
+ }
+ | TOKHEAP heapid ',' expr ptrs
+ {
+ heap($2, $4, $5);
+ $$ = nil;
+ }
+ | data
+ {
+ $$ = nil;
+ }
+ | inst
+ ;
+
+heapid : '$' expr
+ {
+ $$ = $2;
+ }
+ | TID
+ {
+ $1->value = heapid++;
+ $$ = $1->value;
+ }
+ ;
+
+ptrs :
+ { $$ = nil; }
+ | ',' TSTRING
+ {
+ $$ = $2;
+ }
+ ;
+
+elist : expr
+ {
+ $$ = newi($1, nil);
+ }
+ | elist ',' expr
+ {
+ $$ = newi($3, $1);
+ }
+ ;
+
+inst : TOKI3 addr ',' addr
+ {
+ $$ = ai($1);
+ $$->src = $2;
+ $$->dst = $4;
+ }
+ | TOKI3 addr ',' raddr ',' addr
+ {
+ $$ = ai($1);
+ $$->src = $2;
+ $$->reg = $4;
+ $$->dst = $6;
+ }
+ | TOKI2 addr ',' addr
+ {
+ $$ = ai($1);
+ $$->src = $2;
+ $$->dst = $4;
+ }
+ | TOKI1 addr
+ {
+ $$ = ai($1);
+ $$->dst = $2;
+ }
+ | TOKI0
+ {
+ $$ = ai($1);
+ }
+ ;
+
+data : TOKDB expr ',' elist
+ {
+ data(DEFB, $2, $4);
+ }
+ | TOKDW expr ',' elist
+ {
+ data(DEFW, $2, $4);
+ }
+ | TOKDL expr ',' elist
+ {
+ data(DEFL, $2, $4);
+ }
+ | TOKDF expr ',' TCONST
+ {
+ data(DEFF, $2, newi(dtocanon((double)$4), nil));
+ }
+ | TOKDF expr ',' TFCONST
+ {
+ data(DEFF, $2, newi(dtocanon($4), nil));
+ }
+ | TOKDF expr ',' TID
+ {
+ if(strcmp($4->name, "Inf") == 0 || strcmp($4->name, "Infinity") == 0) {
+ u.l = 0x7ff0000000000000;
+ data(DEFF, $2, newi(dtocanon(u.d), nil));
+ } else if(strcmp($4->name, "NaN") == 0) {
+ u.l = 0x7fffffffffffffff;
+ data(DEFF, $2, newi(dtocanon(u.d), nil));
+ } else
+ diag("bad value for real: %s", $4->name);
+ }
+ | TOKDF expr ',' '-' TCONST
+ {
+ data(DEFF, $2, newi(dtocanon(-(double)$5), nil));
+ }
+ | TOKDF expr ',' '-' TFCONST
+ {
+ data(DEFF, $2, newi(dtocanon(-$5), nil));
+ }
+ | TOKDF expr ',' '-' TID
+ {
+ if(strcmp($5->name, "Inf") == 0 || strcmp($5->name, "Infinity") == 0) {
+ u.l = 0xfff0000000000000;
+ data(DEFF, $2, newi(dtocanon(u.d), nil));
+ } else
+ diag("bad value for real: %s", $5->name);
+ }
+ | TOKDS expr ',' TSTRING
+ {
+ data(DEFS, $2, news($4, nil));
+ }
+ | TOKVAR TID ',' expr
+ {
+ if($2->ds != 0)
+ diag("%s declared twice", $2->name);
+ $2->ds = $4;
+ $2->value = dseg;
+ dseg += $4;
+ }
+ | TOKEXT expr ',' expr ',' TSTRING
+ {
+ ext($2, $4, $6);
+ }
+ | TOKLINK expr ',' expr ',' expr ',' TSTRING
+ {
+ mklink($2, $4, $6, $8);
+ }
+ | TOKMOD TID
+ {
+ if(module != nil)
+ diag("this module already defined as %s", $2->name);
+ else
+ module = $2;
+ }
+ | TOKENTRY expr ',' expr
+ {
+ if(pcentry >= 0)
+ diag("this module already has entry point %d, %d" , pcentry, dentry);
+ pcentry = $2;
+ dentry = $4;
+ }
+ | TOKARRAY expr ',' heapid ',' expr
+ {
+ data(DEFA, $2, newa($4, $6));
+ }
+ | TOKINDIR expr ',' expr
+ {
+ data(DIND, $2, newa($4, 0));
+ }
+ | TOKAPOP
+ {
+ data(DAPOP, 0, newa(0, 0));
+ }
+ | TOKLDTS TID ',' expr
+ {
+ ldts($4);
+ }
+ | TOKEXCS expr
+ {
+ excs($2);
+ }
+ | TOKEXC expr ',' expr ',' expr ',' expr ',' expr ',' expr
+ {
+ exc($2, $4, $6, $8, $10, $12);
+ }
+ | TOKETAB TSTRING ',' expr
+ {
+ etab($2, $4);
+ }
+ | TOKETAB '*' ',' expr
+ {
+ etab(nil, $4);
+ }
+ | TOKSRC TSTRING
+ {
+ source($2);
+ }
+ ;
+
+raddr : '$' expr
+ {
+ $$ = aa($2);
+ $$->mode = AXIMM;
+ if($$->val > 0x7FFF || $$->val < -0x8000)
+ diag("immediate %d too large for middle operand", $$->val);
+ }
+ | roff
+ {
+ if($1->mode == AMP)
+ $1->mode = AXINM;
+ else
+ $1->mode = AXINF;
+ if($1->mode == AXINM && (ulong)$1->val > 0xFFFF)
+ diag("register offset %d(mp) too large", $1->val);
+ if($1->mode == AXINF && (ulong)$1->val > 0xFFFF)
+ diag("register offset %d(fp) too large", $1->val);
+ $$ = $1;
+ }
+ ;
+
+addr : '$' expr
+ {
+ $$ = aa($2);
+ $$->mode = AIMM;
+ }
+ | TID
+ {
+ $$ = aa(0);
+ $$->sym = $1;
+ }
+ | mem
+ ;
+
+mem : '*' roff
+ {
+ $2->mode |= AIND;
+ $$ = $2;
+ }
+ | expr '(' roff ')'
+ {
+ $3->mode |= AIND;
+ if($3->val & 3)
+ diag("indirect offset must be word size");
+ if($3->mode == (AMP|AIND) && ((ulong)$3->val > 0xFFFF || (ulong)$1 > 0xFFFF))
+ diag("indirect offset %d(%d(mp)) too large", $1, $3->val);
+ if($3->mode == (AFP|AIND) && ((ulong)$3->val > 0xFFFF || (ulong)$1 > 0xFFFF))
+ diag("indirect offset %d(%d(fp)) too large", $1, $3->val);
+ $3->off = $3->val;
+ $3->val = $1;
+ $$ = $3;
+ }
+ | roff
+ ;
+
+roff : expr '(' TOKSB ')'
+ {
+ $$ = aa($1);
+ $$->mode = AMP;
+ }
+ | expr '(' TOKFP ')'
+ {
+ $$ = aa($1);
+ $$->mode = AFP;
+ }
+ ;
+
+con : TCONST
+ | TID
+ {
+ $$ = $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;
+ }
+ ;