999 lines
13 KiB
Plaintext
999 lines
13 KiB
Plaintext
%{
|
|
#include "a.h"
|
|
%}
|
|
%union
|
|
{
|
|
Sym *sym;
|
|
long lval;
|
|
double dval;
|
|
char sval[8];
|
|
Gen gen;
|
|
}
|
|
%left '|'
|
|
%left '^'
|
|
%left '&'
|
|
%left '<' '>'
|
|
%left '+' '-'
|
|
%left '*' '/' '%'
|
|
%token <lval> LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
|
|
%token <lval> LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
|
|
%token <lval> LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
|
|
%token <lval> LCONST LSP LSB LFP LPC LCREG LFLUSH
|
|
%token <lval> LREG LFREG LR LCR LF LFPSCR
|
|
%token <lval> LLR LCTR LSPR LSPREG LSEG LMSR LDCR
|
|
%token <lval> LSCHED LXLD LXST LXOP LXMV
|
|
%token <lval> LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA LFMOVX
|
|
%token <dval> LFCONST
|
|
%token <sval> LSCONST
|
|
%token <sym> LNAME LLAB LVAR
|
|
%type <lval> con expr pointer offset sreg
|
|
%type <gen> addr rreg regaddr name creg freg xlreg lr ctr
|
|
%type <gen> imm ximm fimm rel psr lcr cbit fpscr fpscrf seg msr mask
|
|
%%
|
|
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:
|
|
/*
|
|
* load ints and bytes
|
|
*/
|
|
LMOVW rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW addr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW regaddr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVB rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVB addr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVB regaddr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* load and store floats
|
|
*/
|
|
| LFMOV addr ',' freg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LFMOV regaddr ',' 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);
|
|
}
|
|
| LFMOV freg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* load and store floats, indexed only
|
|
*/
|
|
| LFMOVX regaddr ',' freg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LFMOVX freg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* store ints and bytes
|
|
*/
|
|
| LMOVW rreg ',' addr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW rreg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVB rreg ',' addr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVB rreg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* store floats
|
|
*/
|
|
| LMOVW freg ',' addr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW freg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* floating point status
|
|
*/
|
|
| LMOVW fpscr ',' freg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW freg ',' fpscr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW freg ',' imm ',' fpscr
|
|
{
|
|
outgcode($1, &$2, NREG, &$4, &$6);
|
|
}
|
|
| LMOVW fpscr ',' creg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW imm ',' fpscrf
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMTFSB imm ',' con
|
|
{
|
|
outcode($1, &$2, $4, &nullgen);
|
|
}
|
|
/*
|
|
* field moves (mtcrf)
|
|
*/
|
|
| LMOVW rreg ',' imm ',' lcr
|
|
{
|
|
outgcode($1, &$2, NREG, &$4, &$6);
|
|
}
|
|
| LMOVW rreg ',' creg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW rreg ',' lcr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* integer operations
|
|
* logical instructions
|
|
* shift instructions
|
|
* unary instructions
|
|
*/
|
|
| LADDW rreg ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
| LADDW imm ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
| LADDW rreg ',' imm ',' rreg
|
|
{
|
|
outgcode($1, &$2, NREG, &$4, &$6);
|
|
}
|
|
| LADDW rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LADDW imm ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LLOGW rreg ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
| LLOGW rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LSHW rreg ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
| LSHW rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LSHW imm ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
| LSHW imm ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LABS rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LABS rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$2);
|
|
}
|
|
/*
|
|
* multiply-accumulate
|
|
*/
|
|
| LMA rreg ',' sreg ',' rreg
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
/*
|
|
* move immediate: macro for cau+or, addi, addis, and other combinations
|
|
*/
|
|
| LMOVW imm ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW ximm ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* condition register operations
|
|
*/
|
|
| LCROP cbit ',' cbit
|
|
{
|
|
outcode($1, &$2, $4.reg, &$4);
|
|
}
|
|
| LCROP cbit ',' con ',' cbit
|
|
{
|
|
outcode($1, &$2, $4, &$6);
|
|
}
|
|
/*
|
|
* condition register moves
|
|
* move from machine state register
|
|
*/
|
|
| LMOVW creg ',' creg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW psr ',' creg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW lcr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW psr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW seg ',' rreg
|
|
{
|
|
int r;
|
|
r = $2.offset;
|
|
$2.offset = 0;
|
|
outcode($1, &$2, r, &$4);
|
|
}
|
|
| LMOVW rreg ',' seg
|
|
{
|
|
int r;
|
|
r = $4.offset;
|
|
$4.offset = 0;
|
|
outcode($1, &$2, r, &$4);
|
|
}
|
|
| LMOVW xlreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW rreg ',' xlreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW creg ',' psr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVW rreg ',' psr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* branch, branch conditional
|
|
* branch conditional register
|
|
* branch conditional to count register
|
|
*/
|
|
| LBRA rel
|
|
{
|
|
outcode($1, &nullgen, NREG, &$2);
|
|
}
|
|
| LBRA addr
|
|
{
|
|
outcode($1, &nullgen, NREG, &$2);
|
|
}
|
|
| LBRA '(' xlreg ')'
|
|
{
|
|
outcode($1, &nullgen, NREG, &$3);
|
|
}
|
|
| LBRA ',' rel
|
|
{
|
|
outcode($1, &nullgen, NREG, &$3);
|
|
}
|
|
| LBRA ',' addr
|
|
{
|
|
outcode($1, &nullgen, NREG, &$3);
|
|
}
|
|
| LBRA ',' '(' xlreg ')'
|
|
{
|
|
outcode($1, &nullgen, NREG, &$4);
|
|
}
|
|
| LBRA creg ',' rel
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LBRA creg ',' addr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LBRA creg ',' '(' xlreg ')'
|
|
{
|
|
outcode($1, &$2, NREG, &$5);
|
|
}
|
|
| LBRA con ',' rel
|
|
{
|
|
outcode($1, &nullgen, $2, &$4);
|
|
}
|
|
| LBRA con ',' addr
|
|
{
|
|
outcode($1, &nullgen, $2, &$4);
|
|
}
|
|
| LBRA con ',' '(' xlreg ')'
|
|
{
|
|
outcode($1, &nullgen, $2, &$5);
|
|
}
|
|
| LBRA con ',' con ',' rel
|
|
{
|
|
Gen g;
|
|
g = nullgen;
|
|
g.type = D_CONST;
|
|
g.offset = $2;
|
|
outcode($1, &g, $4, &$6);
|
|
}
|
|
| LBRA con ',' con ',' addr
|
|
{
|
|
Gen g;
|
|
g = nullgen;
|
|
g.type = D_CONST;
|
|
g.offset = $2;
|
|
outcode($1, &g, $4, &$6);
|
|
}
|
|
| LBRA con ',' con ',' '(' xlreg ')'
|
|
{
|
|
Gen g;
|
|
g = nullgen;
|
|
g.type = D_CONST;
|
|
g.offset = $2;
|
|
outcode($1, &g, $4, &$7);
|
|
}
|
|
/*
|
|
* conditional trap
|
|
*/
|
|
| 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);
|
|
}
|
|
/*
|
|
* 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);
|
|
}
|
|
| LFMA freg ',' freg ',' freg ',' freg
|
|
{
|
|
outgcode($1, &$2, $4.reg, &$6, &$8);
|
|
}
|
|
| LFCMP freg ',' freg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LFCMP freg ',' freg ',' creg
|
|
{
|
|
outcode($1, &$2, $6.reg, &$4);
|
|
}
|
|
/*
|
|
* CMP
|
|
*/
|
|
| LCMP rreg ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LCMP rreg ',' imm
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LCMP rreg ',' rreg ',' creg
|
|
{
|
|
outcode($1, &$2, $6.reg, &$4);
|
|
}
|
|
| LCMP rreg ',' imm ',' creg
|
|
{
|
|
outcode($1, &$2, $6.reg, &$4);
|
|
}
|
|
/*
|
|
* rotate and mask
|
|
*/
|
|
| LRLWM imm ',' rreg ',' imm ',' rreg
|
|
{
|
|
outgcode($1, &$2, $4.reg, &$6, &$8);
|
|
}
|
|
| LRLWM imm ',' rreg ',' mask ',' rreg
|
|
{
|
|
outgcode($1, &$2, $4.reg, &$6, &$8);
|
|
}
|
|
| LRLWM rreg ',' rreg ',' imm ',' rreg
|
|
{
|
|
outgcode($1, &$2, $4.reg, &$6, &$8);
|
|
}
|
|
| LRLWM rreg ',' rreg ',' mask ',' rreg
|
|
{
|
|
outgcode($1, &$2, $4.reg, &$6, &$8);
|
|
}
|
|
/*
|
|
* load/store multiple
|
|
*/
|
|
| LMOVMW addr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LMOVMW rreg ',' addr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
/*
|
|
* various indexed load/store
|
|
* indexed unary (eg, cache clear)
|
|
*/
|
|
| LXLD regaddr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LXLD regaddr ',' imm ',' rreg
|
|
{
|
|
outgcode($1, &$2, NREG, &$4, &$6);
|
|
}
|
|
| LXST rreg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LXST rreg ',' imm ',' regaddr
|
|
{
|
|
outgcode($1, &$2, NREG, &$4, &$6);
|
|
}
|
|
| LXMV regaddr ',' rreg
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LXMV rreg ',' regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &$4);
|
|
}
|
|
| LXOP regaddr
|
|
{
|
|
outcode($1, &$2, NREG, &nullgen);
|
|
}
|
|
/*
|
|
* 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);
|
|
}
|
|
/*
|
|
* word
|
|
*/
|
|
| LWORD imm comma
|
|
{
|
|
outcode($1, &$2, NREG, &nullgen);
|
|
}
|
|
| LWORD ximm comma
|
|
{
|
|
outcode($1, &$2, NREG, &nullgen);
|
|
}
|
|
/*
|
|
* 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);
|
|
}
|
|
| LTEXT name ',' imm ':' imm
|
|
{
|
|
outgcode($1, &$2, NREG, &$6, &$4);
|
|
}
|
|
| LTEXT name ',' con ',' imm ':' imm
|
|
{
|
|
outgcode($1, &$2, $4, &$8, &$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;
|
|
}
|
|
|
|
xlreg:
|
|
lr
|
|
| ctr
|
|
|
|
lr:
|
|
LLR
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_SPR;
|
|
$$.offset = $1;
|
|
}
|
|
|
|
lcr:
|
|
LCR
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_CREG;
|
|
$$.reg = NREG; /* whole register */
|
|
}
|
|
|
|
ctr:
|
|
LCTR
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_SPR;
|
|
$$.offset = $1;
|
|
}
|
|
|
|
msr:
|
|
LMSR
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_MSR;
|
|
}
|
|
|
|
psr:
|
|
LSPREG
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_SPR;
|
|
$$.offset = $1;
|
|
}
|
|
| LSPR '(' con ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $1;
|
|
$$.offset = $3;
|
|
}
|
|
| LDCR '(' con ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $1;
|
|
$$.offset = $3;
|
|
}
|
|
| LDCR '(' sreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = $1;
|
|
$$.reg = $3;
|
|
$$.offset = 0;
|
|
}
|
|
| msr
|
|
|
|
seg:
|
|
LSEG '(' con ')'
|
|
{
|
|
if($3 < 0 || $3 > 15)
|
|
yyerror("segment register number out of range");
|
|
$$ = nullgen;
|
|
$$.type = D_SREG;
|
|
$$.reg = $3;
|
|
$$.offset = NREG;
|
|
}
|
|
| LSEG '(' sreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_SREG;
|
|
$$.reg = NREG;
|
|
$$.offset = $3;
|
|
}
|
|
|
|
fpscr:
|
|
LFPSCR
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_FPSCR;
|
|
$$.reg = NREG;
|
|
}
|
|
|
|
fpscrf:
|
|
LFPSCR '(' con ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_FPSCR;
|
|
$$.reg = $3;
|
|
}
|
|
|
|
freg:
|
|
LFREG
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_FREG;
|
|
$$.reg = $1;
|
|
}
|
|
| LF '(' con ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_FREG;
|
|
$$.reg = $3;
|
|
}
|
|
|
|
creg:
|
|
LCREG
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_CREG;
|
|
$$.reg = $1;
|
|
}
|
|
| LCR '(' con ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_CREG;
|
|
$$.reg = $3;
|
|
}
|
|
|
|
|
|
cbit: con
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_REG;
|
|
$$.reg = $1;
|
|
}
|
|
|
|
mask:
|
|
con ',' con
|
|
{
|
|
int mb, me;
|
|
ulong v;
|
|
|
|
$$ = nullgen;
|
|
$$.type = D_CONST;
|
|
mb = $1;
|
|
me = $3;
|
|
if(mb < 0 || mb > 31 || me < 0 || me > 31){
|
|
yyerror("illegal mask start/end value(s)");
|
|
mb = me = 0;
|
|
}
|
|
if(mb <= me)
|
|
v = ((ulong)~0L>>mb) & (~0L<<(31-me));
|
|
else
|
|
v = ~(((ulong)~0L>>(me+1)) & (~0L<<(31-(mb-1))));
|
|
$$.offset = v;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
regaddr:
|
|
'(' sreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_OREG;
|
|
$$.reg = $2;
|
|
$$.offset = 0;
|
|
}
|
|
| '(' sreg '+' sreg ')'
|
|
{
|
|
$$ = nullgen;
|
|
$$.type = D_OREG;
|
|
$$.reg = $2;
|
|
$$.xreg = $4;
|
|
$$.offset = 0;
|
|
}
|
|
|
|
addr:
|
|
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;
|
|
}
|