%{
/*
- * Copyright (C) 2006-2007 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2006-2010 Michael Buesch <m@bues.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
#include <stdint.h>
extern char *yytext;
-extern void yyerror(char *);
+extern void yyerror(const char *);
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;
%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
}
| 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 {
}
}
;
-/* 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 {
}
;
-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;
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;
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));
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);
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);
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);
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);
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 {
}
;
+/* 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));
}
;
+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;
}
;
+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));
}
;
+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;
}
;
-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));
}
;
-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;
}
;
}
;
-imm : hexnum_decnum {
+imm : imm_value {
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;
}
;
| 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;
int section = SECTION_TEXT; /* default to .text section */
struct initvals_sect *cur_initvals_sect;
-void yyerror(char *str)
+void yyerror(const char *str)
{
unsigned int i;
}
return oper;
}
+
+static void assembler_assertion_failed(void)
+{
+ yyerror("Assembler %assert failed");
+}