541 lines
6.6 KiB
Plaintext
541 lines
6.6 KiB
Plaintext
%{
|
|
#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;
|
|
$$.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;
|
|
}
|
|
|
|
gen:
|
|
type
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $1;
|
|
}
|
|
| '$' con
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_CONST;
|
|
$$.offset = $2;
|
|
}
|
|
| '$' name
|
|
{
|
|
$$ = nullgen;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*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;
|
|
$$.offset = $3;
|
|
}
|
|
| LTOS '-' con
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_STACK;
|
|
$$.offset = -$3;
|
|
}
|
|
| con
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_CONST | I_INDIR;
|
|
$$.offset = $1;
|
|
}
|
|
| '-' '(' LAREG ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $3 | I_INDDEC;
|
|
}
|
|
| '(' LAREG ')' '+'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $2 | I_INDINC;
|
|
}
|
|
| areg
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $1.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*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 = &$$;
|
|
*a = $1;
|
|
}
|
|
$$.index = $2.type | I_INDEX1;
|
|
$$.scale = $2.offset;
|
|
}
|
|
| '(' areg ')' xreg
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $2.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*a = $2;
|
|
}
|
|
$$.index = $4.type | I_INDEX2;
|
|
$$.scale = $4.offset;
|
|
$$.displace = 0;
|
|
}
|
|
| con '(' areg ')' xreg
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $3.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*a = $3;
|
|
}
|
|
$$.index = $5.type | I_INDEX2;
|
|
$$.scale = $5.offset;
|
|
$$.displace = $1;
|
|
}
|
|
| '(' areg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $2.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*a = $2;
|
|
}
|
|
$$.index = D_NONE | I_INDEX3;
|
|
$$.scale = 0;
|
|
$$.displace = 0;
|
|
}
|
|
| con '(' areg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $3.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*a = $3;
|
|
}
|
|
$$.index = D_NONE | I_INDEX3;
|
|
$$.scale = 0;
|
|
$$.displace = $1;
|
|
}
|
|
| '(' areg xreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $2.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*a = $2;
|
|
}
|
|
$$.index = $3.type | I_INDEX3;
|
|
$$.scale = $3.offset;
|
|
$$.displace = 0;
|
|
}
|
|
| con '(' areg xreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $3.type;
|
|
{
|
|
Addr *a;
|
|
a = &$$;
|
|
*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;
|
|
}
|