X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=assembler%2Fparser.y;h=317af05a282488cee207c729b60fe400f2500135;hb=62ac5a230d3e0d3bf92d1d4a1ce0a82189010e86;hp=f00b2da4dec31266d2e64b6e6599514525ace4e8;hpb=be06ecf2322ad87005e2d3f18eb6dbb08da7e92c;p=b43-tools.git diff --git a/assembler/parser.y b/assembler/parser.y index f00b2da..317af05 100644 --- a/assembler/parser.y +++ b/assembler/parser.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (C) 2006-2007 Michael Buesch + * Copyright (C) 2006-2010 Michael Buesch * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -28,6 +28,7 @@ extern int yyparse(void); extern int yylex(void); static struct operand * store_oper_sanity(struct operand *oper); +static void assembler_assertion_failed(void); /* The current .section */ extern int section; @@ -38,13 +39,13 @@ extern struct initvals_sect *cur_initvals_sect; %token SECTION_TEXT SECTION_IVALS -%token ASM_ARCH ASM_START SPR GPR OFFR LR COMMA BRACK_OPEN BRACK_CLOSE PAREN_OPEN PAREN_CLOSE HEXNUM DECNUM ARCH_NEWWORLD ARCH_OLDWORLD LABEL IDENT LABELREF +%token ASM_ARCH ASM_START ASM_ASSERT SPR GPR OFFR LR COMMA SEMICOLON BRACK_OPEN BRACK_CLOSE PAREN_OPEN PAREN_CLOSE HEXNUM DECNUM ARCH_NEWWORLD ARCH_OLDWORLD LABEL IDENT LABELREF -%token PLUS MINUS MULTIPLY DIVIDE BITW_OR BITW_AND BITW_XOR BITW_NOT LEFTSHIFT RIGHTSHIFT +%token EQUAL NOT_EQUAL LOGICAL_OR LOGICAL_AND PLUS MINUS MULTIPLY DIVIDE BITW_OR BITW_AND BITW_XOR BITW_NOT LEFTSHIFT RIGHTSHIFT -%token OP_ADD OP_ADDSC OP_ADDC OP_ADDSCC OP_SUB OP_SUBSC OP_SUBC OP_SUBSCC OP_SRA OP_OR OP_AND OP_XOR OP_SR OP_SRX OP_SL OP_RL OP_RR OP_NAND OP_ORX OP_MOV OP_JMP OP_JAND OP_JNAND OP_JS OP_JNS OP_JE OP_JNE OP_JLS OP_JGES OP_JGS OP_JLES OP_JL OP_JGE OP_JG OP_JLE OP_JZX OP_JNZX OP_JEXT OP_JNEXT OP_CALL OP_RET OP_TKIPH OP_TKIPHS OP_TKIPL OP_TKIPLS OP_NAP RAW_CODE +%token OP_MUL OP_ADD OP_ADDSC OP_ADDC OP_ADDSCC OP_SUB OP_SUBSC OP_SUBC OP_SUBSCC OP_SRA OP_OR OP_AND OP_XOR OP_SR OP_SRX OP_SL OP_RL OP_RR OP_NAND OP_ORX OP_MOV OP_JMP OP_JAND OP_JNAND OP_JS OP_JNS OP_JE OP_JNE OP_JLS OP_JGES OP_JGS OP_JLES OP_JL OP_JGE OP_JG OP_JLE OP_JZX OP_JNZX OP_JEXT OP_JNEXT OP_JDN OP_JDPZ OP_JDP OP_JDNZ OP_CALL OP_CALLS OP_RET OP_RETS OP_TKIPH OP_TKIPHS OP_TKIPL OP_TKIPLS OP_NAP RAW_CODE -%token IVAL_MMIO16 IVAL_MMIO32 IVAL_PHY IVAL_RADIO IVAL_SHM16 IVAL_SHM32 +%token IVAL_MMIO16 IVAL_MMIO32 IVAL_PHY IVAL_RADIO IVAL_SHM16 IVAL_SHM32 IVAL_TRAM %start line @@ -55,10 +56,12 @@ line : line_terminator { } | line statement line_terminator { struct statement *s = $2; - if (section != SECTION_TEXT) - yyerror("Microcode text instruction in non .text section"); - memcpy(&s->info, &cur_lineinfo, sizeof(struct lineinfo)); - list_add_tail(&s->list, &infile.sl); + if (s) { + if (section != SECTION_TEXT) + yyerror("Microcode text instruction in non .text section"); + memcpy(&s->info, &cur_lineinfo, sizeof(struct lineinfo)); + list_add_tail(&s->list, &infile.sl); + } } | line section_switch line_terminator { } @@ -72,9 +75,10 @@ line : line_terminator { } ; -/* Allow terminating lines with the "|" char */ +/* Allow terminating lines with the ";" char */ line_terminator : /* Nothing */ - | BITW_OR line_terminator + | SEMICOLON line_terminator + ; section_switch : SECTION_TEXT { section = SECTION_TEXT; @@ -101,35 +105,35 @@ section_switch : SECTION_TEXT { } ; -ivals_write : IVAL_MMIO16 hexnum_decnum COMMA hexnum_decnum { +ivals_write : IVAL_MMIO16 imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_MMIO16; iop->args[0] = (unsigned int)(unsigned long)$2; iop->args[1] = (unsigned int)(unsigned long)$4; $$ = iop; } - | IVAL_MMIO32 hexnum_decnum COMMA hexnum_decnum { + | IVAL_MMIO32 imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_MMIO32; iop->args[0] = (unsigned int)(unsigned long)$2; iop->args[1] = (unsigned int)(unsigned long)$4; $$ = iop; } - | IVAL_PHY hexnum_decnum COMMA hexnum_decnum { + | IVAL_PHY imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_PHY; iop->args[0] = (unsigned int)(unsigned long)$2; iop->args[1] = (unsigned int)(unsigned long)$4; $$ = iop; } - | IVAL_RADIO hexnum_decnum COMMA hexnum_decnum { + | IVAL_RADIO imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_RADIO; iop->args[0] = (unsigned int)(unsigned long)$2; iop->args[1] = (unsigned int)(unsigned long)$4; $$ = iop; } - | IVAL_SHM16 hexnum_decnum COMMA hexnum_decnum COMMA hexnum_decnum { + | IVAL_SHM16 imm_value COMMA imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_SHM16; iop->args[0] = (unsigned int)(unsigned long)$2; @@ -137,7 +141,7 @@ ivals_write : IVAL_MMIO16 hexnum_decnum COMMA hexnum_decnum { iop->args[2] = (unsigned int)(unsigned long)$6; $$ = iop; } - | IVAL_SHM32 hexnum_decnum COMMA hexnum_decnum COMMA hexnum_decnum { + | IVAL_SHM32 imm_value COMMA imm_value COMMA imm_value { struct initval_op *iop = xmalloc(sizeof(struct initval_op)); iop->type = IVAL_W_SHM32; iop->args[0] = (unsigned int)(unsigned long)$2; @@ -145,14 +149,25 @@ ivals_write : IVAL_MMIO16 hexnum_decnum COMMA hexnum_decnum { iop->args[2] = (unsigned int)(unsigned long)$6; $$ = iop; } + | IVAL_TRAM imm_value COMMA imm_value { + struct initval_op *iop = xmalloc(sizeof(struct initval_op)); + iop->type = IVAL_W_TRAM; + iop->args[0] = (unsigned int)(unsigned long)$2; + iop->args[1] = (unsigned int)(unsigned long)$4; + $$ = iop; + } ; statement : asmdir { - struct statement *s = xmalloc(sizeof(struct statement)); - INIT_LIST_HEAD(&s->list); - s->type = STMT_ASMDIR; - s->u.asmdir = $1; - $$ = s; + struct asmdir *ad = $1; + if (ad) { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_ASMDIR; + s->u.asmdir = $1; + $$ = s; + } else + $$ = NULL; } | label { struct statement *s = xmalloc(sizeof(struct statement)); @@ -161,6 +176,13 @@ statement : asmdir { s->u.label = $1; $$ = s; } + | insn_mul { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } | insn_add { struct statement *s = xmalloc(sizeof(struct statement)); INIT_LIST_HEAD(&s->list); @@ -378,6 +400,34 @@ statement : asmdir { s->u.insn = $1; $$ = s; } + | insn_jdn { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } + | insn_jdpz { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } + | insn_jdp { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } + | insn_jdnz { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } | insn_jl { struct statement *s = xmalloc(sizeof(struct statement)); INIT_LIST_HEAD(&s->list); @@ -441,6 +491,13 @@ statement : asmdir { s->u.insn = $1; $$ = s; } + | insn_calls { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } | insn_ret { struct statement *s = xmalloc(sizeof(struct statement)); INIT_LIST_HEAD(&s->list); @@ -448,6 +505,13 @@ statement : asmdir { s->u.insn = $1; $$ = s; } + | insn_rets { + struct statement *s = xmalloc(sizeof(struct statement)); + INIT_LIST_HEAD(&s->list); + s->type = STMT_INSN; + s->u.insn = $1; + $$ = s; + } | insn_tkiph { struct statement *s = xmalloc(sizeof(struct statement)); INIT_LIST_HEAD(&s->list); @@ -508,6 +572,48 @@ asmdir : ASM_ARCH hexnum_decnum { ad->u.start = label; $$ = ad; } + | asm_assert { + $$ = NULL; + } + ; + +asm_assert : ASM_ASSERT assertion { + unsigned int ok = (unsigned int)(unsigned long)$2; + if (!ok) + assembler_assertion_failed(); + $$ = NULL; + } + ; + +assertion : PAREN_OPEN assert_expr PAREN_CLOSE { + $$ = $2; + } + | PAREN_OPEN assertion LOGICAL_OR assertion PAREN_CLOSE { + unsigned int a = (unsigned int)(unsigned long)$2; + unsigned int b = (unsigned int)(unsigned long)$4; + unsigned int result = (a || b); + $$ = (void *)(unsigned long)result; + } + | PAREN_OPEN assertion LOGICAL_AND assertion PAREN_CLOSE { + unsigned int a = (unsigned int)(unsigned long)$2; + unsigned int b = (unsigned int)(unsigned long)$4; + unsigned int result = (a && b); + $$ = (void *)(unsigned long)result; + } + ; + +assert_expr : imm_value EQUAL imm_value { + unsigned int a = (unsigned int)(unsigned long)$1; + unsigned int b = (unsigned int)(unsigned long)$3; + unsigned int result = (a == b); + $$ = (void *)(unsigned long)result; + } + | imm_value NOT_EQUAL imm_value { + unsigned int a = (unsigned int)(unsigned long)$1; + unsigned int b = (unsigned int)(unsigned long)$3; + unsigned int result = (a != b); + $$ = (void *)(unsigned long)result; + } ; label : LABEL { @@ -520,6 +626,15 @@ label : LABEL { } ; +/* multiply */ +insn_mul : OP_MUL operlist_3 { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + insn->op = OP_MUL; + insn->operands = $2; + $$ = insn; + } + ; + /* add */ insn_add : OP_ADD operlist_3 { struct instruction *insn = xmalloc(sizeof(struct instruction)); @@ -826,6 +941,38 @@ insn_jnzx : OP_JNZX extended_operlist { } ; +insn_jdn : OP_JDN operlist_3 { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + insn->op = OP_JDN; + insn->operands = $2; + $$ = insn; + } + ; + +insn_jdpz : OP_JDPZ operlist_3 { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + insn->op = OP_JDPZ; + insn->operands = $2; + $$ = insn; + } + ; + +insn_jdp : OP_JDP operlist_3 { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + insn->op = OP_JDP; + insn->operands = $2; + $$ = insn; + } + ; + +insn_jdnz : OP_JDNZ operlist_3 { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + insn->op = OP_JDNZ; + insn->operands = $2; + $$ = insn; + } + ; + insn_jext : OP_JEXT external_jump_operands { struct instruction *insn = xmalloc(sizeof(struct instruction)); insn->op = OP_JEXT; @@ -865,6 +1012,24 @@ insn_call : OP_CALL linkreg COMMA labelref { } ; +insn_calls : OP_CALLS labelref { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + struct operlist *ol = xmalloc(sizeof(struct operlist)); + struct operand *oper_r0 = xmalloc(sizeof(struct operand)); + struct registr *r0 = xmalloc(sizeof(struct registr)); + r0->type = GPR; + r0->nr = 0; + oper_r0->type = OPER_REG; + oper_r0->u.reg = r0; + ol->oper[0] = oper_r0; + ol->oper[1] = oper_r0; + ol->oper[2] = $2; + insn->op = OP_CALLS; + insn->operands = ol; + $$ = insn; + } + ; + insn_ret : OP_RET linkreg COMMA linkreg { struct instruction *insn = xmalloc(sizeof(struct instruction)); struct operlist *ol = xmalloc(sizeof(struct operlist)); @@ -886,6 +1051,27 @@ insn_ret : OP_RET linkreg COMMA linkreg { } ; +insn_rets : OP_RETS { + struct instruction *insn = xmalloc(sizeof(struct instruction)); + struct operlist *ol = xmalloc(sizeof(struct operlist)); + struct operand *oper_r0 = xmalloc(sizeof(struct operand)); + struct operand *oper_zero = xmalloc(sizeof(struct operand)); + struct registr *r0 = xmalloc(sizeof(struct registr)); + oper_zero->type = OPER_RAW; + oper_zero->u.raw = 0; + r0->type = GPR; + r0->nr = 0; + oper_r0->type = OPER_REG; + oper_r0->u.reg = r0; + ol->oper[0] = oper_r0; + ol->oper[1] = oper_r0; + ol->oper[2] = oper_zero; + insn->op = OP_RETS; + insn->operands = ol; + $$ = insn; + } + ; + insn_tkiph : OP_TKIPH operlist_2 { struct instruction *insn = xmalloc(sizeof(struct instruction)); struct operlist *ol = $2; @@ -986,7 +1172,7 @@ raw_code : RAW_CODE { } ; -extended_operlist : decnum COMMA decnum COMMA operand COMMA operand COMMA operand { +extended_operlist : imm_value COMMA imm_value COMMA operand COMMA operand COMMA operand { struct operlist *ol = xmalloc(sizeof(struct operlist)); struct operand *mask_oper = xmalloc(sizeof(struct operand)); struct operand *shift_oper = xmalloc(sizeof(struct operand)); @@ -1003,15 +1189,13 @@ extended_operlist : decnum COMMA decnum COMMA operand COMMA operand COMMA operan } ; -external_jump_operands : imm COMMA operand COMMA operand COMMA labelref { +external_jump_operands : imm COMMA labelref { struct operlist *ol = xmalloc(sizeof(struct operlist)); struct operand *cond = xmalloc(sizeof(struct operand)); cond->type = OPER_IMM; cond->u.imm = $1; ol->oper[0] = cond; ol->oper[1] = $3; - ol->oper[2] = $5; - ol->oper[3] = $7; $$ = ol; } ; @@ -1083,35 +1267,37 @@ reg : GPR regnr { } ; -mem : BRACK_OPEN hexnum_decnum BRACK_CLOSE { +mem : BRACK_OPEN imm BRACK_CLOSE { struct memory *mem = xmalloc(sizeof(struct memory)); + struct immediate *offset_imm = $2; mem->type = MEM_DIRECT; - mem->offset = (unsigned long)$2; + mem->offset = offset_imm->imm; + free(offset_imm); $$ = mem; } - | BRACK_OPEN hexnum_decnum COMMA OFFR regnr BRACK_CLOSE { + | BRACK_OPEN imm COMMA OFFR regnr BRACK_CLOSE { struct memory *mem = xmalloc(sizeof(struct memory)); + struct immediate *offset_imm = $2; mem->type = MEM_INDIRECT; - mem->offset = (unsigned long)$2; + mem->offset = offset_imm->imm; + free(offset_imm); mem->offr_nr = (unsigned long)$5; $$ = mem; } ; -imm : hexnum { +imm : imm_value { struct immediate *imm = xmalloc(sizeof(struct immediate)); imm->imm = (unsigned long)$1; $$ = imm; } - | decnum { - struct immediate *imm = xmalloc(sizeof(struct immediate)); - imm->imm = (unsigned long)$1; - $$ = imm; + ; + +imm_value : hexnum_decnum { + $$ = $1; } | complex_imm { - struct immediate *imm = xmalloc(sizeof(struct immediate)); - imm->imm = (unsigned long)$1; - $$ = imm; + $$ = $1; } ; @@ -1156,6 +1342,10 @@ complex_imm : PAREN_OPEN complex_imm_arg complex_imm_oper complex_imm_arg PAREN_ | PAREN_OPEN complex_imm PAREN_CLOSE { $$ = $2; } + | PAREN_OPEN asm_assert PAREN_CLOSE { + /* Inline assertion. Always return zero */ + $$ = (void *)(unsigned long)(unsigned int)0; + } | PAREN_OPEN BITW_NOT complex_imm PAREN_CLOSE { unsigned long n = (unsigned long)$3; n = ~n; @@ -1307,3 +1497,8 @@ static struct operand * store_oper_sanity(struct operand *oper) } return oper; } + +static void assembler_assertion_failed(void) +{ + yyerror("Assembler %assert failed"); +}