Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

%{
#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;
        }