%{ /************************************************************************* * 56002.y - 56002 assembly parser * *-----------------------------------------------------------------------* * Jake Janovetz 1995 * * University of Illinois * ************************************************************************* * * * This file contains the yacc (bison) code that implements the 56002 * * assembly parser. It requires a lexer (56002.l) to hand it tokens for * * opcodes, labels, numbers, registers, etc. * * * * No truly fancy tricks are used in this parser, so, assuming knowledge * * of both yacc and the 56002 assembly language, this parser should be * * relatively simple to understand. * ************************************************************************/ /* * 2 reduce/reduce conflicts due to last two cases of mv_xymemreg. */ unsigned int w0, w1, wn; unsigned int pptr, xptr, yptr; unsigned int last_wn, last_w0, last_w1; unsigned int last_pptr, last_xptr, last_yptr; unsigned int pass; extern char *errtxt; extern int errflag; int yyerror(char *txt); int yylex(); %} %union { char str[128]; int ival; int cond; double fval; } /* 56002 opcode tokens */ %token OP_ABS OP_ADC OP_ADD OP_ADDL OP_ADDR OP_AND OP_ANDI %token OP_ASL OP_ASR %token OP_BCHG OP_BCLR OP_BSET OP_BTST %token OP_CLR OP_CMP OP_CMPM %token OP_DEBUG OP_DEBUGCC OP_DEC OP_DIV OP_DO %token OP_ENDDO OP_EOR %token OP_ILLEGAL OP_INC %token OP_JCC OP_JCLR OP_JMP OP_JSCC OP_JSCLR OP_JSET OP_JSR %token OP_JSSET %token OP_LSL OP_LSR OP_LUA %token OP_MAC OP_MACR OP_MOVE OP_MOVEP OP_MPY OP_MPYR %token OP_NEG OP_NOP OP_NORM OP_NOT %token OP_OR OP_ORI %token OP_REP OP_RESET OP_RND OP_ROL OP_ROR OP_RTI OP_RTS %token OP_SBC OP_STOP OP_SUB OP_SUBL OP_SUBR OP_SWI %token OP_TCC OP_TFR OP_TST %token OP_WAIT /* 56002 register tokens */ %token REG_Rn REG_Mn REG_Nn %token REG_A10 REG_B10 REG_AB REG_BA %token REG_A REG_A0 REG_A1 REG_A2 REG_B REG_B0 REG_B1 REG_B2 %token REG_X REG_X0 REG_X1 REG_Y REG_Y0 REG_Y1 %token REG_SR REG_OMR REG_SP REG_SSH REG_SSL REG_LA REG_LC %token REG_MR REG_CCR %token MEM_X MEM_Y MEM_P %token SHL %token DUMMY /* Other */ %token INTEGER %token FLOAT %token LABEL %token EOL /* end of line */ %type OP_TCC; %type OP_JCC; %type OP_JSCC; %type OP_DEBUGCC; %type reg_ab; %type reg_xy; %type reg_abba; %type reg_dataALU; %type reg_accum; %type reg_arith1; %type reg_arith2; %type reg_ctrl reg_ctrls; %type reg_all; %type ea_regs; %type mem_spc; %type movec_args movem_args movep_args; %type bit_args; %type rep_args; %type short_addr io_addr long_addr do_addr; %type lua_srcs; %type immed immed_short immed_long; %type immed_bit; %type jmp_args bit_jmp_args; %type mpy_dataALU mpy_srcs mpy_sign; %type mv_regs mv_xreg mv_yreg reg_x0x1 reg_y0y1; %type iexpr; %type fexpr; %left '-' '+' %left '*' '/' %start listing %% listing: statement_list { } ; statement_list: | statement_list statement ; statement: label EOL | DUMMY iexpr { printf("val: %d\n", $2); } | DUMMY fexpr { printf("val: %f\n", $2); } | label assembly EOL { #ifndef LINEASM printf("P:%04X %06X\n", pptr, w0); if (wn == 2) printf(" %06X\n", w1); #endif last_w0 = w0; last_w1 = w1; last_wn = wn; last_pptr = pptr++; last_xptr = xptr; last_yptr = yptr; if (wn == 2) { pptr++; } w0 = w1 = 0; wn = 1; } ; label: { } | LABEL { printf("label: %s\n", $1); } ; assembly: no_parallel | parallel_op parallel_move ; /* Instructions which don't allow parallel moves */ no_parallel: OP_DEBUG { w0 |= 0x000200; } | OP_ENDDO { w0 |= 0x00008c; } | OP_ILLEGAL { w0 |= 0x000005; } | OP_NOP { w0 |= 0x000000; } | OP_RESET { w0 |= 0x000084; } | OP_RTI { w0 |= 0x000004; } | OP_RTS { w0 |= 0x00000c; } | OP_STOP { w0 |= 0x000087; } | OP_SWI { w0 |= 0x000006; } | OP_WAIT { w0 |= 0x000086; } | OP_DEC reg_ab { w0 |= 0x00000a | $2; } | OP_INC reg_ab { w0 |= 0x000008 | $2; } | OP_MOVE movec_args { w0 |= $2; } | OP_MOVE movem_args { w0 |= $2; } | OP_MOVE movep_args { w0 |= $2; } | OP_LUA lua_srcs ',' REG_Rn { w0 |= 0x044010 | $2 << 8 | $4; } | OP_LUA lua_srcs ',' REG_Nn { w0 |= 0x044018 | $2 << 8 | $4; } | OP_BCLR bit_args { w0 |= 0x0a0000 | $2; } | OP_BSET bit_args { w0 |= 0x0a0020 | $2; } | OP_BCHG bit_args { w0 |= 0x0b0000 | $2; } | OP_BTST bit_args { w0 |= 0x0b0020 | $2; } | OP_ANDI immed_ctrl { w0 |= 0x0000b8; } | OP_ORI immed_ctrl { w0 |= 0x0000f8; } | OP_DIV reg_dataALU ',' reg_ab { w0 |= 0x018040 | $2 << 4 | $4 << 3; } | OP_NORM REG_Rn ',' reg_ab { w0 |= 0x01d815 | $2 << 8 | $4 << 3; } | OP_MPY mpy_sign mpy_dataALU immed ',' reg_ab { w0 |= 0x0100c0 | $2 << 2 | $3 << 4 | $4 << 8 | $6 << 3; } | OP_MPYR mpy_sign mpy_dataALU immed ',' reg_ab { w0 |= 0x0100c1 | $2 << 2 | $3 << 4 | $4 << 8 | $6 << 3; } | OP_MAC mpy_sign mpy_dataALU immed ',' reg_ab { w0 |= 0x0100c2 | $2 << 2 | $3 << 4 | $4 << 8 | $6 << 3; } | OP_MACR mpy_sign mpy_dataALU immed ',' reg_ab { w0 |= 0x0100c3 | $2 << 2 | $3 << 4 | $4 << 8 | $6 << 3; } | OP_DO rep_args ',' do_addr { w0 |= 0x060000 | $2; w1 = $4; wn = 2; } | OP_REP rep_args { w0 |= 0x060020 | $2; } | OP_DEBUGCC {w0 |= 0x000300 | $1; } | OP_TCC reg_arith2 { w0 |= 0x020000 | $1 << 12 | $2 << 3; } | OP_TCC reg_arith2 REG_Rn ',' REG_Rn { w0 |= 0x030000 | $1 << 12 | $2 << 3 | $3 << 8 | $5; } | jumps ; jumps: OP_JCC ea_regs {w0 |= 0x0ac0a0 | $1 | $2 << 8; } | OP_JSCC ea_regs {w0 |= 0x0bc0a0 | $1 | $2 << 8; } | OP_JCC short_addr { w0 |= 0x0e0000 | $1 << 12 | ($2 & 0x3f); if ($2 > 0x3f) { yyerror("W: Short address truncated to 6 bits"); } } | OP_JSCC short_addr { w0 |= 0x0f0000 | $1 << 12 | ($2 & 0x3f); if ($2 > 0x3f) { yyerror("W: Short address truncated to 6 bits"); } } | OP_JCC INTEGER { if (($2 < 0) || ($2 > 0xffff)) { yyerror("Jump addres out of range"); } else if ($2 < 4096) { w0 |= 0x0e0000 | $1 << 12 | $2; } else { w0 |= 0x0af0a0 | $1; w1 = $2; wn = 2; } } | OP_JSCC INTEGER { if (($2 < 0) || ($2 > 0xffff)) { yyerror("Jump addres out of range"); } else if ($2 < 4096) { w0 |= 0x0f0000 | $1 << 12 | $2; } else { w0 |= 0x0bf0a0 | $1; w1 = $2; wn = 2; } } | OP_JMP jmp_args {w0 |= 0x000000 | $2; } | OP_JSR jmp_args {w0 |= 0x010000 | $2; } | OP_JCLR bit_jmp_args {w0 |= 0x0a0000 | $2; } | OP_JSCLR bit_jmp_args {w0 |= 0x0b0000 | $2; } | OP_JSET bit_jmp_args {w0 |= 0x0a0020 | $2; } | OP_JSSET bit_jmp_args {w0 |= 0x0b0020 | $2; } ; jmp_args: ea_regs { $$ = 0x0ac080 | $1 << 8; } | short_addr { $$ = 0x0c0000 | ($1 & 0xfff); if ($1 > 0xfff) { yyerror("W: Short address truncated to 12 bits"); } } | long_addr { $$ = 0x0af080; w1 = ($1 & 0xffff); wn = 2; if ($1 > 0xffff) { yyerror("W: Long address truncated to 16 bits"); } } | INTEGER { if ($1 < 0x1000) /* 12-bit address? */ { $$ = 0x0c0000 | $1; } else /* long address */ { $$ = 0x0af080; w1 = ($1 & 0xffff); wn = 2; if ($1 > 0xffff) { yyerror("W: Long address truncated to 16 bits"); } } } ; bit_jmp_args: immed_bit ',' mem_spc ea_regs ',' INTEGER { if (($6 < 0) || ($6 > 0xffff)) { yyerror("Jump addres out of range"); } $$ = 0x004080 | $1 | $3 << 6 | $4 << 8; w1 = $6; wn = 2; } | immed_bit ',' mem_spc INTEGER ',' INTEGER { if (($6 < 0) || ($6 > 0xffff)) { yyerror("Jump addres out of range"); } if (($4 >= 0) && ($4 <= 0x3f)) { $$ = 0x000080 | $1 | $3 << 6 | $4 << 8; } else if (($4 >= 0xffc0) && ($4 <= 0xffff)) { $$ = 0x008080 | $1 | $3 << 6 | ($4 - 0xffc0) << 8; } else { yyerror("Jump addres out of range"); } w1 = $6; wn = 2; } ; rep_args: mem_spc ea_regs { $$ = 0x004000 | $1 << 6 | $2 << 8; } | reg_all { $$ = 0x00c000 | $1 << 8; } | mem_spc short_addr { $$ = 0x000000 | $1 << 6 | ($2 & 0x3f) << 8; if ($2 > 0x3f) { yyerror("W: Short address truncated to 6 bits"); } } | mem_spc INTEGER { $$ = 0x000000 | $1 << 6 | ($2 & 0x3f) << 8; if ($2 > 0x3f) { yyerror("W: Short address truncated to 6 bits"); } } | immed { $$ = 0x000080 | (($1 & 0x0ff) << 8) | (($1 & 0xf00) >> 8); if ($1 > 0xfff) { yyerror("W: Immediate repeat value truncated to 12 bits"); } } ; /* Instructions which allow parallel moves */ parallel_op: OP_ABS reg_ab { w0 |= 0x000026 | $2 << 3; } | OP_ASL reg_ab { w0 |= 0x000032 | $2 << 3; } | OP_ASR reg_ab { w0 |= 0x000022 | $2 << 3; } | OP_CLR reg_ab { w0 |= 0x000013 | $2 << 3; } | OP_LSL reg_ab { w0 |= 0x000033 | $2 << 3; } | OP_LSR reg_ab { w0 |= 0x000023 | $2 << 3; } | OP_NEG reg_ab { w0 |= 0x000036 | $2 << 3; } | OP_NOT reg_ab { w0 |= 0x000017 | $2 << 3; } | OP_RND reg_ab { w0 |= 0x000011 | $2 << 3; } | OP_ROL reg_ab { w0 |= 0x000037 | $2 << 3; } | OP_ROR reg_ab { w0 |= 0x000027 | $2 << 3; } | OP_TST reg_ab { w0 |= 0x000003 | $2 << 3; } | OP_ADDL reg_abba { w0 |= 0x000012 | $2 << 3; } | OP_ADDR reg_abba { w0 |= 0x000002 | $2 << 3; } | OP_SUBL reg_abba { w0 |= 0x000016 | $2 << 3; } | OP_SUBR reg_abba { w0 |= 0x000006 | $2 << 3; } | OP_ADD reg_arith1 { w0 |= 0x000000 | $2 << 3; } | OP_SUB reg_arith1 { w0 |= 0x000004 | $2 << 3; } | OP_TFR reg_arith2 { w0 |= 0x000001 | $2 << 3; } | OP_CMP reg_arith2 { w0 |= 0x000005 | $2 << 3; } | OP_CMPM reg_arith2 { w0 |= 0x000007 | $2 << 3; } | OP_ADC reg_xy ',' reg_ab { w0 |= 0x000021 | $2 << 4 | $4 << 3; } | OP_SBC reg_xy ',' reg_ab { w0 |= 0x000025 | $2 << 4 | $4 << 3; } | OP_AND reg_dataALU ',' reg_ab { w0 |= 0x000046 | $2 << 4 | $4 << 3; } | OP_EOR reg_dataALU ',' reg_ab { w0 |= 0x000043 | $2 << 4 | $4 << 3; } | OP_OR reg_dataALU ',' reg_ab { w0 |= 0x000042 | $2 << 4 | $4 << 3; } | OP_MOVE | OP_MPY mpy_sign mpy_srcs ',' reg_ab { w0 |= 0x000080 | $2 << 2 | $3 << 4 | $5 << 3; } | OP_MPYR mpy_sign mpy_srcs ',' reg_ab { w0 |= 0x000081 | $2 << 2 | $3 << 4 | $5 << 3; } | OP_MAC mpy_sign mpy_srcs ',' reg_ab { w0 |= 0x000082 | $2 << 2 | $3 << 4 | $5 << 3; } | OP_MACR mpy_sign mpy_srcs ',' reg_ab { w0 |= 0x000083 | $2 << 2 | $3 << 4 | $5 << 3; } ; parallel_move: { w0 |= 0x200000; } | mv_immed | mv_regreg | lua_srcs { w0 |= 0x204000 | $1 << 8; } | mv_xymem | mv_xymemreg ; mv_regreg: mv_regs ',' mv_regs { w0 |= 0x200000 | $1 << 13 | $3 << 8; } ; mv_immed: immed ',' mv_regs { if ($1 < 0x100) { w0 |= 0x200000 | ($1 & 0xff) << 8 | $3 << 16; } else { w0 |= 0x40f400 | ($3 & 0x18) << 17 | ($3 & 0x7) << 16; w1 = $1; wn = 2; } } | immed_long ',' mv_regs { w0 |= 0x40f400 | ($3 & 0x18) << 17 | ($3 & 0x7) << 16; w1 = $1; wn = 2; } | immed_short ',' mv_regs { w0 |= 0x200000 | ($1 & 0xff) << 8 | $3 << 16; if ($1 > 0xff) { yyerror("W: Immediate data truncated to 8 bits"); } } ; mv_xymemreg: immed ',' mv_xreg reg_ab ',' reg_y0y1 { w0 |= 0x10b400 | $3 << 18 | $4 << 17 | $6 << 16; w1 = $1; wn = 2; } | immed_long ',' mv_xreg reg_ab ',' reg_y0y1 { w0 |= 0x10b400 | $3 << 18 | $4 << 17 | $6 << 16; w1 = $1; wn = 2; } | reg_ab ',' reg_x0x1 immed ',' mv_yreg { w0 |= 0x10f400 | $1 << 19 | $3 << 18 | $6 << 16; w1 = $4; wn = 2; } | reg_ab ',' reg_x0x1 immed_long ',' mv_yreg { w0 |= 0x10f400 | $1 << 19 | $3 << 18 | $6 << 16; w1 = $4; wn = 2; } ; mv_xymem: mem_spc ea_regs ',' mv_regs { w0 |= 0x40c000 | $1 << 19 | $2 << 8 | ($4 & 0x18) << 17 | ($4 & 0x7) << 16; } | mv_regs ',' mem_spc ea_regs { w0 |= 0x404000 | $3 << 19 | $4 << 8 | ($1 & 0x18) << 17 | ($1 & 0x7) << 16; } ; reg_x0x1: REG_X0 { $$ = 0x0; } | REG_X1 { $$ = 0x1; } ; reg_y0y1: REG_Y0 { $$ = 0x0; } | REG_Y1 { $$ = 0x1; } ; mv_xreg: REG_X0 { $$ = 0x0; } | REG_X1 { $$ = 0x1; } | REG_A { $$ = 0x2; } | REG_B { $$ = 0x3; } ; mv_yreg: REG_Y0 { $$ = 0x0; } | REG_Y1 { $$ = 0x1; } | REG_A { $$ = 0x2; } | REG_B { $$ = 0x3; } ; mv_regs: REG_X0 { $$ = 0x4; } | REG_X1 { $$ = 0x5; } | REG_Y0 { $$ = 0x6; } | REG_Y1 { $$ = 0x7; } | reg_accum { $$ = 0x08 | $1; } | REG_Rn { $$ = 0x10 | $1; } | REG_Nn { $$ = 0x18 | $1; } ; bit_args: immed ',' mem_spc ea_regs { $$ = 0x004000 | $1 | $3 << 6 | $4 << 8; } | immed ',' reg_all { $$ = 0x00c040 | $1 | $3 << 8; } | immed ',' mem_spc short_addr { $$ = $1 | $3 << 6 | ($4 & 0x3f) << 8; if ($4 > 0x3f) { yyerror("W: Short address truncated to 6 bits"); } } | immed ',' mem_spc io_addr { $$ = 0x008000 | $1 | $3 << 6 | $4 << 8; } | immed ',' mem_spc long_addr { $$ = 0x007000 | $1 | ($3 & 0xffff) << 6; w1 = $4; wn = 2; if ($4 > 0xffff) { yyerror("W: Long address truncated to 16 bits"); } } | immed ',' mem_spc INTEGER { if ($4 < 0x40) /* Absolute Short Address */ { $$ = $1 | $4 << 8; } else if ($4 > 0xffbf) /* I/O Short Address */ { $$ = 0x008000 | $1 | ($4 - 0xffc0) << 8; } else /* Absolute Address */ { $$ = 0x007000 | $1 | $3 << 6; w1 = ($4 & 0xffff); wn = 2; if ($4 > 0xffff) { yyerror("W: Long address truncated to 16 bits"); } } } ; long_addr: '>' INTEGER { $$ = $2; } ; short_addr: '<' INTEGER { $$ = $2; } ; do_addr: INTEGER { if (($1 < 1) || ($1 > 0xffff)) { yyerror("Address out of range for DO"); } else { $$ = $1 - 1; } } ; io_addr: '<' '<' INTEGER { if (($3 < 0xffc0) || ($3 > 0xffff)) { yyerror("I/O Short Address is outside range"); } else { $$ = $3 - 0xffc0; } } ; lua_srcs: '(' REG_Rn ')' '-' REG_Nn { if ($2 != $5) yyerror("Register and offset numbers must match."); else $$ = 0x00 | $2; } | '(' REG_Rn ')' '+' REG_Nn { if ($2 != $5) yyerror("Register and offset numbers must match."); else $$ = 0x08 | $2; } | '(' REG_Rn ')' '-' { $$ = 0x10 | $2; } | '(' REG_Rn ')' '+' { $$ = 0x18 | $2; } ; movec_args: '1' INTEGER { $$ = 1; } ; movem_args: '2' INTEGER { $$ = 1; } ; movep_args: '3' INTEGER { $$ = 1; } ; /* Immediate Arguments */ immed: '#' INTEGER { $$ = $2; } ; immed_short: '#' '<' INTEGER { $$ = $3; } ; immed_long: '#' '>' INTEGER { $$ = $3; } ; immed_bit: '#' INTEGER { if ($2 < 0) { yyerror("Immediate value out of range"); } else if ($2 > 23) { yyerror("Immediate value out of range"); } else { $$ = $2; } } ; /* Logic ops: immediate with control regs (andi, ori) */ immed_ctrl: immed ',' reg_ctrl { if (($1 < 0) || ($1 > 0xff)) { yyerror("Immediate value out of range"); } else { w0 |= $1 << 8 | $3; } } ; /* Register Arguments */ reg_ab: REG_A { $$ = 0; } | REG_B { $$ = 1; } ; reg_xy: REG_X { $$ = 0; } | REG_Y { $$ = 1; } ; reg_abba: REG_B ',' REG_A { $$ = 0; } | REG_A ',' REG_B { $$ = 1; } ; reg_dataALU: REG_X0 { $$ = 0x0; } | REG_Y0 { $$ = 0x1; } | REG_X1 { $$ = 0x2; } | REG_Y1 { $$ = 0x3; } ; /* The comma is required after the register to avoid shift/reduce * conflicts between the "mpy reg,reg,reg" and "mpy reg,immed,reg" * -- Kind of a kludge, but it works */ mpy_dataALU: /* mpy functions have strange ordering */ REG_Y1 ',' { $$ = 0x0; } | REG_X0 ',' { $$ = 0x1; } | REG_Y0 ',' { $$ = 0x2; } | REG_X1 ',' { $$ = 0x3; } ; reg_ctrl: REG_MR { $$ = 0x0; } | REG_CCR { $$ = 0x1; } | REG_OMR { $$ = 0x2; } ; reg_ctrls: REG_SR { $$ = 0x1; } | REG_OMR { $$ = 0x2; } | REG_SP { $$ = 0x3; } | REG_SSH { $$ = 0x4; } | REG_SSL { $$ = 0x5; } | REG_LA { $$ = 0x6; } | REG_LC { $$ = 0x7; } ; reg_accum: REG_A0 { $$ = 0x0; } | REG_B0 { $$ = 0x1; } | REG_A2 { $$ = 0x2; } | REG_B2 { $$ = 0x3; } | REG_A1 { $$ = 0x4; } | REG_B1 { $$ = 0x5; } | REG_A { $$ = 0x6; } | REG_B { $$ = 0x7; } ; reg_all: reg_dataALU { $$ = 0x04 | $1; } | reg_accum { $$ = 0x08 | $1; } | REG_Rn { $$ = 0x10 | $1; } | REG_Nn { $$ = 0x18 | $1; } | REG_Mn { $$ = 0x20 | $1; } | reg_ctrls { $$ = 0x38 | $1; } ; ea_regs: '(' REG_Rn ')' '-' REG_Nn { if ($2 != $5) yyerror("Register and offset numbers must match."); else $$ = 0x00 | $2; } | '(' REG_Rn ')' '+' REG_Nn { if ($2 != $5) yyerror("Register and offset numbers must match."); else $$ = 0x08 | $2; } | '(' REG_Rn '+' REG_Nn ')' { if ($2 != $4) yyerror("Register and offset numbers must match."); else $$ = 0x28 | $2; } | '(' REG_Rn ')' '-' { $$ = 0x10 | $2; } | '(' REG_Rn ')' '+' { $$ = 0x18 | $2; } | '(' REG_Rn ')' { $$ = 0x20 | $2; } | '-' '(' REG_Rn ')' { $$ = 0x38 | $3; } ; reg_arith1: reg_abba { $$ = 0x2 | $1; } | reg_xy ',' reg_ab { $$ = 0x4 | $1 << 1 | $3; } | reg_dataALU ',' reg_ab { $$ = 0x8 | $1 << 1 | $3; } ; reg_arith2: reg_abba { $$ = $1; } | reg_dataALU ',' reg_ab { $$ = 0x8 | $1 << 1 | $3; } ; mem_spc: MEM_X { $$ = 0x0; } | MEM_Y { $$ = 0x1; } ; mpy_srcs: REG_X0 ',' REG_X0 { $$ = 0x0; } | REG_Y0 ',' REG_Y0 { $$ = 0x1; } | REG_X1 ',' REG_X0 { $$ = 0x2; } | REG_X0 ',' REG_X1 { $$ = 0x2; } | REG_Y1 ',' REG_Y0 { $$ = 0x3; } | REG_Y0 ',' REG_Y1 { $$ = 0x3; } | REG_X0 ',' REG_Y1 { $$ = 0x4; } | REG_Y1 ',' REG_X0 { $$ = 0x4; } | REG_Y0 ',' REG_X0 { $$ = 0x5; } | REG_X0 ',' REG_Y0 { $$ = 0x5; } | REG_X1 ',' REG_Y0 { $$ = 0x6; } | REG_Y0 ',' REG_X1 { $$ = 0x6; } | REG_Y1 ',' REG_X1 { $$ = 0x7; } | REG_X1 ',' REG_Y1 { $$ = 0x7; } ; mpy_sign: { $$ = 0x0; } | '+' { $$ = 0x0; } | '-' { $$ = 0x1; } ; iexpr: iexpr '+' iexpr { $$ = $1 + $3; printf("addi %d\n", $$); } | INTEGER ; fexpr: fexpr '+' fexpr { $$ = $1 + $3; printf("addf %f\n", $$); } | FLOAT ; %%