nexmon – Rev 1
?pathlinks?
%{
/*
* 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
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "main.h"
#include "initvals.h"
#include "util.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
extern char *yytext;
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;
/* Pointer to the current initvals section data structure. */
extern struct initvals_sect *cur_initvals_sect;
%}
%token SECTION_TEXT SECTION_IVALS
%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 EQUAL NOT_EQUAL LOGICAL_OR LOGICAL_AND PLUS MINUS MULTIPLY DIVIDE BITW_OR BITW_AND BITW_XOR BITW_NOT LEFTSHIFT RIGHTSHIFT
%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_SRXH OP_SL OP_RL OP_RR OP_NAND OP_ORX OP_ORXH 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_JZXH OP_JNZX OP_JNZXH OP_JEXT OP_JNEXT OP_JDN OP_JDPZ OP_JDP OP_JDNZ OP_JBOH OP_JNBOH OP_CALL OP_CALLS OP_RET OP_RETS OP_TKIPH OP_TKIPHS OP_TKIPL OP_TKIPLS OP_NAP OP_NAP2 RAW_CODE
%token IVAL_MMIO16 IVAL_MMIO32 IVAL_PHY IVAL_RADIO IVAL_SHM16 IVAL_SHM32 IVAL_TRAM
%start line
%%
line : line_terminator {
/* empty */
}
| line statement line_terminator {
struct statement *s = $2;
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 {
}
| line ivals_write line_terminator {
struct initval_op *io = $2;
if (section != SECTION_IVALS)
yyerror("InitVals write in non .initvals section");
memcpy(&io->info, &cur_lineinfo, sizeof(struct lineinfo));
INIT_LIST_HEAD(&io->list);
list_add_tail(&io->list, &cur_initvals_sect->ops);
}
;
/* Allow terminating lines with the ";" char */
line_terminator : /* Nothing */
| SEMICOLON line_terminator
;
section_switch : SECTION_TEXT {
section = SECTION_TEXT;
}
| SECTION_IVALS PAREN_OPEN identifier PAREN_CLOSE {
const char *sectname = $3;
struct initvals_sect *s;
cur_initvals_sect = NULL;
/* Search if there already is a section by that name. */
list_for_each_entry(s, &infile.ivals, list) {
if (strcmp(sectname, s->name) == 0)
cur_initvals_sect = s;
}
if (!cur_initvals_sect) {
/* Not found, create a new one. */
s = xmalloc(sizeof(struct initvals_sect));
s->name = sectname;
INIT_LIST_HEAD(&s->ops);
INIT_LIST_HEAD(&s->list);
list_add_tail(&s->list, &infile.ivals);
cur_initvals_sect = s;
}
section = SECTION_IVALS;
}
;
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 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 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 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 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[1] = (unsigned int)(unsigned long)$4;
iop->args[2] = (unsigned int)(unsigned long)$6;
$$ = iop;
}
| 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[1] = (unsigned int)(unsigned long)$4;
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 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));
INIT_LIST_HEAD(&s->list);
s->type = STMT_LABEL;
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->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_addsc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_addc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_addscc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_sub {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_subsc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_subc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_subscc {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_sra {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_or {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_and {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_xor {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_sr {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_srx {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_srxh {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_sl {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_rl {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_rr {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_nand {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_orx {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_orxh {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_mov {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jmp {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jand {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jnand {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_js {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jns {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_je {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jne {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jls {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jges {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jgs {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jles {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
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_jboh {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jnboh {
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->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jge {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jg {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jle {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jzx {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jzxh {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jnzx {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jnzxh {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jext {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_jnext {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_call {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
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->type = STMT_INSN;
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);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_tkiphs {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_tkipl {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_tkipls {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_nap {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_nap2 {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
| insn_raw {
struct statement *s = xmalloc(sizeof(struct statement));
INIT_LIST_HEAD(&s->list);
s->type = STMT_INSN;
s->u.insn = $1;
$$ = s;
}
;
/* ASM directives */
asmdir : ASM_ARCH hexnum_decnum {
struct asmdir *ad = xmalloc(sizeof(struct asmdir));
ad->type = ADIR_ARCH;
ad->u.arch = (unsigned int)(unsigned long)$2;
$$ = ad;
}
| ASM_START identifier {
struct asmdir *ad = xmalloc(sizeof(struct asmdir));
struct label *label = xmalloc(sizeof(struct label));
label->name = $2;
label->direction = LABELREF_ABSOLUTE;
ad->type = ADIR_START;
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 {
struct label *label = xmalloc(sizeof(struct label));
char *l;
l = xstrdup(yytext);
l[strlen(l) - 1] = '\0';
label->name = l;
$$ = 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->op = OP_ADD;
insn->operands = $2;
$$ = insn;
}
;
/* add. */
insn_addsc : OP_ADDSC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_ADDSC;
insn->operands = $2;
$$ = insn;
}
;
/* addc */
insn_addc : OP_ADDC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_ADDC;
insn->operands = $2;
$$ = insn;
}
;
/* addc. */
insn_addscc : OP_ADDSCC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_ADDSCC;
insn->operands = $2;
$$ = insn;
}
;
/* sub */
insn_sub : OP_SUB operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SUB;
insn->operands = $2;
$$ = insn;
}
;
/* sub. */
insn_subsc : OP_SUBSC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SUBSC;
insn->operands = $2;
$$ = insn;
}
;
/* subc */
insn_subc : OP_SUBC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SUBC;
insn->operands = $2;
$$ = insn;
}
;
/* subc. */
insn_subscc : OP_SUBSCC operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SUBSCC;
insn->operands = $2;
$$ = insn;
}
;
insn_sra : OP_SRA operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SRA;
insn->operands = $2;
$$ = insn;
}
;
insn_or : OP_OR operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_OR;
insn->operands = $2;
$$ = insn;
}
;
insn_and : OP_AND operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_AND;
insn->operands = $2;
$$ = insn;
}
;
insn_xor : OP_XOR operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_XOR;
insn->operands = $2;
$$ = insn;
}
;
insn_sr : OP_SR operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SR;
insn->operands = $2;
$$ = insn;
}
;
insn_srx : OP_SRX extended_operlist {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SRX;
insn->operands = $2;
$$ = insn;
}
;
insn_srxh : OP_SRXH operlist_2_human {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SRXH;
insn->operands = $2;
$$ = insn;
}
;
insn_sl : OP_SL operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_SL;
insn->operands = $2;
$$ = insn;
}
;
insn_rl : OP_RL operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_RL;
insn->operands = $2;
$$ = insn;
}
;
insn_rr : OP_RR operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_RR;
insn->operands = $2;
$$ = insn;
}
;
insn_nand : OP_NAND operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_NAND;
insn->operands = $2;
$$ = insn;
}
;
insn_orx : OP_ORX extended_operlist {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_ORX;
insn->operands = $2;
$$ = insn;
}
;
insn_orxh : OP_ORXH operlist_3_human {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_ORXH;
insn->operands = $2;
$$ = insn;
}
;
insn_mov : OP_MOV operlist_2 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_MOV;
insn->operands = $2;
$$ = insn;
}
;
insn_jmp : OP_JMP labelref {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = xmalloc(sizeof(struct operlist));
ol->oper[0] = $2;
insn->op = OP_JMP;
insn->operands = ol;
$$ = insn;
}
;
insn_jand : OP_JAND operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JAND;
insn->operands = $2;
$$ = insn;
}
;
insn_jnand : OP_JNAND operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNAND;
insn->operands = $2;
$$ = insn;
}
;
insn_js : OP_JS operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JS;
insn->operands = $2;
$$ = insn;
}
;
insn_jns : OP_JNS operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNS;
insn->operands = $2;
$$ = insn;
}
;
insn_je : OP_JE operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JE;
insn->operands = $2;
$$ = insn;
}
;
insn_jne : OP_JNE operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNE;
insn->operands = $2;
$$ = insn;
}
;
insn_jls : OP_JLS operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JLS;
insn->operands = $2;
$$ = insn;
}
;
insn_jges : OP_JGES operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JGES;
insn->operands = $2;
$$ = insn;
}
;
insn_jgs : OP_JGS operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JGS;
insn->operands = $2;
$$ = insn;
}
;
insn_jles : OP_JLES operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JLES;
insn->operands = $2;
$$ = insn;
}
;
insn_jl : OP_JL operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JL;
insn->operands = $2;
$$ = insn;
}
;
insn_jge : OP_JGE operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JGE;
insn->operands = $2;
$$ = insn;
}
;
insn_jg : OP_JG operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JG;
insn->operands = $2;
$$ = insn;
}
;
insn_jle : OP_JLE operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JLE;
insn->operands = $2;
$$ = insn;
}
;
insn_jzx : OP_JZX extended_operlist {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JZX;
insn->operands = $2;
$$ = insn;
}
;
insn_jzxh : OP_JZXH operlist_2_jump_human {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JZXH;
insn->operands = $2;
$$ = insn;
}
;
insn_jnzx : OP_JNZX extended_operlist {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNZX;
insn->operands = $2;
$$ = insn;
}
;
insn_jnzxh : OP_JNZXH operlist_2_jump_human {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNZXH;
insn->operands = $2;
$$ = insn;
}
;
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_jboh : OP_JBOH operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JBOH;
insn->operands = $2;
$$ = insn;
}
;
insn_jnboh : OP_JNBOH operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNBOH;
insn->operands = $2;
$$ = insn;
}
;
insn_jext : OP_JEXT external_jump_operands {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JEXT;
insn->operands = $2;
$$ = insn;
}
;
insn_jnext : OP_JNEXT external_jump_operands {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = OP_JNEXT;
insn->operands = $2;
$$ = insn;
}
;
linkreg : LR regnr {
$$ = $2;
}
;
insn_call : OP_CALL linkreg COMMA labelref {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct operand *oper_lr = xmalloc(sizeof(struct operand));
struct operand *oper_zero = xmalloc(sizeof(struct operand));
oper_zero->type = OPER_RAW;
oper_zero->u.raw = 0;
oper_lr->type = OPER_RAW;
oper_lr->u.raw = (unsigned long)$2;
ol->oper[0] = oper_lr;
ol->oper[1] = oper_zero;
ol->oper[2] = $4;
insn->op = OP_CALL;
insn->operands = ol;
$$ = insn;
}
;
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));
struct operand *oper_lr0 = xmalloc(sizeof(struct operand));
struct operand *oper_lr1 = xmalloc(sizeof(struct operand));
struct operand *oper_zero = xmalloc(sizeof(struct operand));
oper_zero->type = OPER_RAW;
oper_zero->u.raw = 0;
oper_lr0->type = OPER_RAW;
oper_lr0->u.raw = (unsigned long)$2;
oper_lr1->type = OPER_RAW;
oper_lr1->u.raw = (unsigned long)$4;
ol->oper[0] = oper_lr0;
ol->oper[1] = oper_zero;
ol->oper[2] = oper_lr1;
insn->op = OP_RET;
insn->operands = ol;
$$ = insn;
}
;
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;
struct operand *flags = xmalloc(sizeof(struct operand));
struct immediate *imm = xmalloc(sizeof(struct immediate));
imm->imm = 0x1;
flags->type = OPER_IMM;
flags->u.imm = imm;
ol->oper[2] = ol->oper[1];
ol->oper[1] = flags;
insn->op = OP_TKIPH;
insn->operands = ol;
$$ = insn;
}
;
insn_tkiphs : OP_TKIPHS operlist_2 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = $2;
struct operand *flags = xmalloc(sizeof(struct operand));
struct immediate *imm = xmalloc(sizeof(struct immediate));
imm->imm = 0x1 | 0x2;
flags->type = OPER_IMM;
flags->u.imm = imm;
ol->oper[2] = ol->oper[1];
ol->oper[1] = flags;
insn->op = OP_TKIPH;
insn->operands = ol;
$$ = insn;
}
;
insn_tkipl : OP_TKIPL operlist_2 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = $2;
struct operand *flags = xmalloc(sizeof(struct operand));
struct immediate *imm = xmalloc(sizeof(struct immediate));
imm->imm = 0x0;
flags->type = OPER_IMM;
flags->u.imm = imm;
ol->oper[2] = ol->oper[1];
ol->oper[1] = flags;
insn->op = OP_TKIPH;
insn->operands = ol;
$$ = insn;
}
;
insn_tkipls : OP_TKIPLS operlist_2 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = $2;
struct operand *flags = xmalloc(sizeof(struct operand));
struct immediate *imm = xmalloc(sizeof(struct immediate));
imm->imm = 0x0 | 0x2;
flags->type = OPER_IMM;
flags->u.imm = imm;
ol->oper[2] = ol->oper[1];
ol->oper[1] = flags;
insn->op = OP_TKIPH;
insn->operands = ol;
$$ = insn;
}
;
insn_nap : OP_NAP {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct operand *regop = xmalloc(sizeof(struct operand));
struct operand *zeroop = xmalloc(sizeof(struct operand));
struct registr *r0 = xmalloc(sizeof(struct registr));
r0->type = GPR;
r0->nr = 0;
regop->type = OPER_REG;
regop->u.reg = r0;
zeroop->type = OPER_RAW;
zeroop->u.raw = 0x000;
ol->oper[0] = regop;
ol->oper[1] = regop;
ol->oper[2] = zeroop;
insn->op = OP_NAP;
insn->operands = ol;
$$ = insn;
}
;
insn_nap2 : OP_NAP2 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct operand *regop = xmalloc(sizeof(struct operand));
struct operand *zeroop = xmalloc(sizeof(struct operand));
struct registr *r0 = xmalloc(sizeof(struct registr));
r0->type = GPR;
r0->nr = 0;
regop->type = OPER_REG;
regop->u.reg = r0;
zeroop->type = OPER_RAW;
zeroop->u.raw = 0x000;
ol->oper[0] = regop;
ol->oper[1] = regop;
ol->oper[2] = zeroop;
insn->op = OP_NAP2;
insn->operands = ol;
$$ = insn;
}
;
insn_raw : raw_code operlist_3 {
struct instruction *insn = xmalloc(sizeof(struct instruction));
insn->op = RAW_CODE;
insn->operands = $2;
insn->opcode = (unsigned long)$1;
$$ = insn;
}
;
raw_code : RAW_CODE {
yytext++; /* skip @ */
$$ = (void *)(unsigned long)strtoul(yytext, NULL, 16);
}
;
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));
mask_oper->type = OPER_RAW;
mask_oper->u.raw = (unsigned long)$1;
shift_oper->type = OPER_RAW;
shift_oper->u.raw = (unsigned long)$3;
ol->oper[0] = mask_oper;
ol->oper[1] = shift_oper;
ol->oper[2] = $5;
ol->oper[3] = $7;
ol->oper[4] = store_oper_sanity($9);
$$ = ol;
}
;
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;
}
;
operlist_2 : operand COMMA operand {
struct operlist *ol = xmalloc(sizeof(struct operlist));
ol->oper[0] = $1;
ol->oper[1] = store_oper_sanity($3);
$$ = ol;
}
;
operlist_3 : operand COMMA operand COMMA operand {
struct operlist *ol = xmalloc(sizeof(struct operlist));
ol->oper[0] = $1;
ol->oper[1] = $3;
ol->oper[2] = store_oper_sanity($5);
$$ = ol;
}
;
operlist_2_jump_human : operand_shift_operand_mask COMMA operand {
struct operlist *ol = $1;
ol->oper[3] = store_oper_sanity($3);
$$ = ol;
}
;
operlist_2_human : operand_shift_mask2 COMMA operand {
struct operlist *ol = $1;
ol->oper[3] = store_oper_sanity($3);
$$ = ol;
}
;
/* all the following could be implemented:
Y => implemented N => raise error
N 0xabcdefgh
N 0xabcdefgh & BITMASK
Y REG12 & BITMASK
Y (REG12 << 16) & BITMASK
Y (REG31 << 16 | REG12) & BITMASK
N (REG12 << 16| 0xabcd) & BITMASK
N (0xabcd0000 | REG12) & BITMASK
*/
operand_shift_operand_mask : imm {
yyerror("Human expression not yet implemented");
}
| operandh BITW_AND imm {
struct operlist *ol = xmalloc(sizeof(struct operlist));
ol->oper[0] = $1;
ol->oper[1] = xmalloc(sizeof(struct operand));
ol->oper[1]->type = OPER_IMM;
ol->oper[1]->u.imm = xmalloc(sizeof(struct immediate));
ol->oper[1]->u.imm->imm = 0;
ol->oper[2] = xmalloc(sizeof(struct operand));
ol->oper[2]->type = OPER_IMM;
ol->oper[2]->u.imm = $3;
$$ = ol;
}
| PAREN_OPEN operandh LEFTSHIFT imm PAREN_CLOSE BITW_AND imm {
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct immediate *imm = $4;
if(imm->imm != 16)
yyerror("Only 16 bit shift allowed here");
ol->oper[0] = xmalloc(sizeof(struct operand));
ol->oper[0]->type = OPER_IMM;
ol->oper[0]->u.imm = xmalloc(sizeof(struct immediate));
ol->oper[0]->u.imm->imm = 0;
ol->oper[1] = $2;
ol->oper[2] = xmalloc(sizeof(struct operand));
ol->oper[2]->type = OPER_IMM;
ol->oper[2]->u.imm = $7;
$$ = ol;
}
| PAREN_OPEN PAREN_OPEN operandh LEFTSHIFT imm PAREN_CLOSE BITW_OR operandh PAREN_CLOSE BITW_AND imm {
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct immediate *imm = $5;
if(imm->imm != 16)
yyerror("Only 16 bit shift allowed here");
ol->oper[0] = $8;
ol->oper[1] = $3;
ol->oper[2] = xmalloc(sizeof(struct operand));
ol->oper[2]->type = OPER_IMM;
ol->oper[2]->u.imm = $11;
$$ = ol;
}
| PAREN_OPEN PAREN_OPEN operandh LEFTSHIFT imm PAREN_CLOSE BITW_OR imm PAREN_CLOSE BITW_AND imm {
yyerror("Human expression not yet implemented");
}
| PAREN_OPEN operandh BITW_OR imm PAREN_CLOSE BITW_AND imm {
yyerror("Human expression not yet implemented");
}
;
/* only the simplest two are implemented:
(xxx >> S) & mask
xxx & mask
*/
operand_shift_mask2 : imm {
yyerror("Human expression not yet implemented");
}
| operandh BITW_AND imm {
struct operlist *ol = xmalloc(sizeof(struct operlist));
ol->oper[0] = $1;
ol->oper[1] = xmalloc(sizeof(struct operand));
ol->oper[1]->type = OPER_IMM;
ol->oper[1]->u.imm = xmalloc(sizeof(struct immediate));
ol->oper[1]->u.imm->imm = 0;
ol->oper[2] = xmalloc(sizeof(struct operand));
ol->oper[2]->type = OPER_IMM;
ol->oper[2]->u.imm = $3;
$$ = ol;
}
| PAREN_OPEN operandh RIGHTSHIFT imm PAREN_CLOSE BITW_AND imm {
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct immediate *shift_imm = $4;
ol->oper[0] = $2;
ol->oper[1] = xmalloc(sizeof(struct operand));
ol->oper[1]->type = OPER_IMM;
ol->oper[1]->u.imm = xmalloc(sizeof(struct immediate));
ol->oper[1]->u.imm->imm = 0;
ol->oper[2] = xmalloc(sizeof(struct operand));
ol->oper[2]->type = OPER_IMM;
ol->oper[2]->u.imm = $7;
ol->oper[2]->u.imm->imm <<= shift_imm->imm;
free(shift_imm);
$$ = ol;
}
;
operlist_3_human : operand_shift_mask COMMA operand_shift_mask COMMA operand {
struct operlist *ol = xmalloc(sizeof(struct operlist));
struct operand_shift_mask *xxx = $1;
struct operand *shift_xxx = xmalloc(sizeof(struct operand));
struct operand *mask_xxx = xmalloc(sizeof(struct operand));
struct operand_shift_mask *yyy = $3;
struct operand *shift_yyy = xmalloc(sizeof(struct operand));
struct operand *mask_yyy = xmalloc(sizeof(struct operand));
shift_xxx->type = OPER_RAW;
shift_xxx->u.raw = (unsigned long) xxx->shift;
mask_xxx->type = OPER_RAW;
mask_xxx->u.raw = (unsigned long) xxx->mask;
shift_yyy->type = OPER_RAW;
shift_yyy->u.raw = (unsigned long) yyy->shift;
mask_yyy->type = OPER_RAW;
mask_yyy->u.raw = (unsigned long) yyy->mask;
ol->oper[0] = xxx->op;
ol->oper[1] = shift_xxx;
ol->oper[2] = mask_xxx;
ol->oper[3] = yyy->op;
ol->oper[4] = shift_yyy;
ol->oper[5] = mask_yyy;
ol->oper[6] = store_oper_sanity($5);
free(xxx);
free(yyy);
$$ = ol;
}
;
/* duplicate some complex_imm rules to avoid parentheses
The following are implemented:
0x143 || 0x143 & 0x12 || 0x143 & ~0x12
REG12 || REG12 & 0x12 || REG12 & ~0x12
(REG12 << 0x12) || (REG12 << 0x12) & 0x12 || (REG12 << 0x12) & ~0x12
*/
operand_shift_mask : imm {
struct operand_shift_mask *oper = xmalloc(sizeof(struct operand_shift_mask));
struct operand *oper_imm = xmalloc(sizeof(struct operand));
oper_imm->type = OPER_IMM;
oper_imm->u.imm = $1;
oper->op = oper_imm;
oper->mask = 0xFFFF;
oper->shift = 0;
$$ = oper;
}
| operand_wwo_shift {
struct operand_shift_mask *oper = $1;
oper->mask = 0xFFFF;
$$ = oper;
}
| operand_wwo_shift BITW_AND imm {
struct operand_shift_mask *oper = $1;
struct immediate *mask_imm = $3;
oper->mask = mask_imm->imm;
free(mask_imm);
$$ = oper;
}
;
operand_wwo_shift : operandh {
struct operand_shift_mask *oper = xmalloc(sizeof(struct operand_shift_mask));
oper->op = $1;
oper->shift = 0;
$$ = oper;
}
| PAREN_OPEN operandh LEFTSHIFT imm PAREN_CLOSE {
struct operand_shift_mask *oper = xmalloc(sizeof(struct operand_shift_mask));
struct immediate *shift_imm = $4;
oper->op = $2;
oper->shift = shift_imm->imm;
free(shift_imm);
$$ = oper;
}
;
operandh : reg {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_REG;
oper->u.reg = $1;
$$ = oper;
}
| mem {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_MEM;
oper->u.mem = $1;
$$ = oper;
}
;
operand : reg {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_REG;
oper->u.reg = $1;
$$ = oper;
}
| mem {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_MEM;
oper->u.mem = $1;
$$ = oper;
}
| raw_code {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_RAW;
oper->u.raw = (unsigned long)$1;
$$ = oper;
}
| imm {
struct operand *oper = xmalloc(sizeof(struct operand));
oper->type = OPER_IMM;
oper->u.imm = $1;
$$ = oper;
}
| labelref {
$$ = $1;
}
;
reg : GPR regnr {
struct registr *reg = xmalloc(sizeof(struct registr));
reg->type = GPR;
reg->nr = (unsigned long)$2;
$$ = reg;
}
| SPR {
struct registr *reg = xmalloc(sizeof(struct registr));
reg->type = SPR;
yytext += 3; /* skip "spr" */
reg->nr = strtoul(yytext, NULL, 16);
$$ = reg;
}
| OFFR regnr {
struct registr *reg = xmalloc(sizeof(struct registr));
reg->type = OFFR;
reg->nr = (unsigned long)$2;
$$ = reg;
}
;
mem : BRACK_OPEN imm BRACK_CLOSE {
struct memory *mem = xmalloc(sizeof(struct memory));
struct immediate *offset_imm = $2;
mem->type = MEM_DIRECT;
mem->offset = offset_imm->imm;
free(offset_imm);
$$ = mem;
}
| 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 = offset_imm->imm;
free(offset_imm);
mem->offr_nr = (unsigned long)$5;
$$ = mem;
}
;
imm : imm_value {
struct immediate *imm = xmalloc(sizeof(struct immediate));
imm->imm = (unsigned long)$1;
$$ = imm;
}
;
imm_value : hexnum_decnum {
$$ = $1;
}
| hexnum_decnum imm_oper imm_value {
unsigned long a = (unsigned long)$1;
unsigned long b = (unsigned long)$3;
unsigned long operation = (unsigned long)$2;
unsigned long res = 31337;
switch (operation) {
case PLUS:
res = a + b;
break;
case MINUS:
res = a - b;
break;
case MULTIPLY:
res = a * b;
break;
case DIVIDE:
res = a / b;
break;
case BITW_OR:
res = a | b;
break;
case BITW_AND:
res = a & b;
break;
case BITW_XOR:
res = a ^ b;
break;
case LEFTSHIFT:
res = a << b;
break;
case RIGHTSHIFT:
res = a >> b;
break;
default:
yyerror("Internal parser BUG. imm oper unknown");
}
$$ = (void *)res;
}
| PAREN_OPEN imm_value PAREN_CLOSE {
$$ = $2;
}
| PAREN_OPEN imm_value PAREN_CLOSE imm_oper imm_value {
unsigned long a = (unsigned long)$2;
unsigned long b = (unsigned long)$5;
unsigned long operation = (unsigned long)$4;
unsigned long res = 31337;
switch (operation) {
case PLUS:
res = a + b;
break;
case MINUS:
res = a - b;
break;
case MULTIPLY:
res = a * b;
break;
case DIVIDE:
res = a / b;
break;
case BITW_OR:
res = a | b;
break;
case BITW_AND:
res = a & b;
break;
case BITW_XOR:
res = a ^ b;
break;
case LEFTSHIFT:
res = a << b;
break;
case RIGHTSHIFT:
res = a >> b;
break;
default:
yyerror("Internal parser BUG. complex_imm oper unknown");
}
$$ = (void *)res;
}
| BITW_NOT imm_value {
unsigned long n = (unsigned long)$2;
n = ~n;
$$ = (void *)n;
}
| asm_assert {
// Inline assertion. Always return zero
$$ = (void *)(unsigned long)(unsigned int)0;
}
;
imm_oper : PLUS {
$$ = (void *)(unsigned long)PLUS;
}
| MINUS {
$$ = (void *)(unsigned long)MINUS;
}
| MULTIPLY {
$$ = (void *)(unsigned long)MULTIPLY;
}
| DIVIDE {
$$ = (void *)(unsigned long)DIVIDE;
}
| BITW_OR {
$$ = (void *)(unsigned long)BITW_OR;
}
| BITW_AND {
$$ = (void *)(unsigned long)BITW_AND;
}
| BITW_XOR {
$$ = (void *)(unsigned long)BITW_XOR;
}
| LEFTSHIFT {
$$ = (void *)(unsigned long)LEFTSHIFT;
}
| RIGHTSHIFT {
$$ = (void *)(unsigned long)RIGHTSHIFT;
}
;
hexnum : HEXNUM {
while (yytext[0] != 'x') {
if (yytext[0] == '\0')
yyerror("Internal HEXNUM parser error");
yytext++;
}
yytext++;
$$ = (void *)(unsigned long)strtoul(yytext, NULL, 16);
}
;
decnum : DECNUM {
$$ = (void *)(unsigned long)strtol(yytext, NULL, 10);
}
;
hexnum_decnum : hexnum {
$$ = $1;
}
| decnum {
$$ = $1;
}
;
labelref : identifier {
struct operand *oper = xmalloc(sizeof(struct operand));
struct label *label = xmalloc(sizeof(struct label));
label->name = $1;
label->direction = LABELREF_ABSOLUTE;
oper->type = OPER_LABEL;
oper->u.label = label;
$$ = oper;
}
| identifier MINUS {
struct operand *oper = xmalloc(sizeof(struct operand));
struct label *label = xmalloc(sizeof(struct label));
label->name = $1;
label->direction = LABELREF_RELATIVE_BACK;
oper->type = OPER_LABEL;
oper->u.label = label;
$$ = oper;
}
| identifier PLUS {
struct operand *oper = xmalloc(sizeof(struct operand));
struct label *label = xmalloc(sizeof(struct label));
label->name = $1;
label->direction = LABELREF_RELATIVE_FORWARD;
oper->type = OPER_LABEL;
oper->u.label = label;
$$ = oper;
}
;
regnr : DECNUM {
$$ = (void *)(unsigned long)strtoul(yytext, NULL, 10);
}
;
identifier : IDENT {
$$ = xstrdup(yytext);
}
;
%%
int section = SECTION_TEXT; /* default to .text section */
struct initvals_sect *cur_initvals_sect;
void yyerror(const char *str)
{
unsigned int i;
fprintf(stderr,
"Parser ERROR (file \"%s\", line %u, col %u):\n",
cur_lineinfo.file,
cur_lineinfo.lineno,
cur_lineinfo.column);
fprintf(stderr, "%s\n", cur_lineinfo.linecopy);
for (i = 0; i < cur_lineinfo.column - 1; i++)
fprintf(stderr, " ");
fprintf(stderr, "^\n");
fprintf(stderr, "%s\n", str);
exit(1);
}
static struct operand * store_oper_sanity(struct operand *oper)
{
if (oper->type == OPER_IMM &&
oper->u.imm->imm != 0) {
yyerror("Only 0x000 Immediate is allowed for "
"Output operands");
}
return oper;
}
static void assembler_assertion_failed(void)
{
yyerror("Assembler %assert failed");
}