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