/*
- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2006-2010 Michael Buesch <mb@bu3sch.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
const char *name;
const char *operands[5];
- int is_labelref;
+ int labelref_operand;
unsigned int labeladdr;
struct statement *labelref;
} insn;
const char *outfile_name;
+#define _msg_helper(type, msg, x...) do { \
+ fprintf(stderr, "Disassembler " type \
+ ":\n " msg "\n" ,##x); \
+ } while (0)
+
+#define dasm_error(msg, x...) do { \
+ _msg_helper("ERROR", msg ,##x); \
+ exit(1); \
+ } while (0)
+
+#define dasm_int_error(msg, x...) \
+ dasm_error("Internal error (bug): " msg ,##x)
+
+#define dasm_warn(msg, x...) \
+ _msg_helper("warning", msg ,##x)
+
+#define asm_info(msg, x...) \
+ _msg_helper("info", msg ,##x)
+
static const char * gen_raw_code(unsigned int operand)
{
char *ret;
reg = ((operand >> 7) & 0x7);
break;
default:
- fprintf(stderr, "Internal error: disasm_indirect_mem_operand invalid arch\n");
- exit(1);
+ dasm_int_error("disasm_indirect_mem_operand invalid arch");
}
ret = xmalloc(12);
snprintf(ret, 12, "[0x%02X,off%u]", offset, reg);
mask = 0x7FF;
break;
default:
- fprintf(stderr, "Internal error: disasm_imm_operand invalid arch\n");
- exit(1);
+ dasm_int_error("disasm_imm_operand invalid arch");
}
operand &= mask;
mask = 0x7FF;
break;
default:
- fprintf(stderr, "Internal error: disasm_spr_operand invalid arch\n");
- exit(1);
+ dasm_int_error("disasm_spr_operand invalid arch");
}
ret = xmalloc(8);
mask = 0x7F;
break;
default:
- fprintf(stderr, "Internal error: disasm_gpr_operand invalid arch\n");
- exit(1);
+ dasm_int_error("disasm_gpr_operand invalid arch");
}
ret = xmalloc(5);
return ret;
}
-static void disasm_std_operand(struct statement *stmt,
+static void disasm_raw_operand(struct statement *stmt,
int oper_idx,
- int out_idx,
- int forceraw)
+ int out_idx)
{
unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
- if (forceraw)
- goto raw;
+ stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
+}
+
+static void disasm_std_operand(struct statement *stmt,
+ int oper_idx,
+ int out_idx)
+{
+ unsigned int operand = stmt->u.insn.bin->operands[oper_idx];
switch (cmdargs.arch) {
case 5:
}
break;
default:
- fprintf(stderr, "Internal error: disasm_std_operand invalid arch\n");
- exit(1);
+ dasm_int_error("disasm_std_operand invalid arch");
}
-raw:
- stmt->u.insn.operands[out_idx] = gen_raw_code(operand);
+ /* No luck. Disassemble to raw operand. */
+ disasm_raw_operand(stmt, oper_idx, out_idx);
}
static void disasm_opcode_raw(struct disassembler_context *ctx,
- struct statement *stmt)
+ struct statement *stmt,
+ int raw_operands)
{
stmt->u.insn.name = gen_raw_code(stmt->u.insn.bin->opcode);
- disasm_std_operand(stmt, 0, 0, 1);
- disasm_std_operand(stmt, 1, 1, 1);
- disasm_std_operand(stmt, 2, 2, 1);
+ if (raw_operands) {
+ disasm_raw_operand(stmt, 0, 0);
+ disasm_raw_operand(stmt, 1, 1);
+ disasm_raw_operand(stmt, 2, 2);
+ } else {
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
+ }
}
static void disasm_constant_opcodes(struct disassembler_context *ctx,
switch (bin->opcode) {
case 0x1C0:
stmt->u.insn.name = "add";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1C2:
stmt->u.insn.name = "add.";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1C1:
stmt->u.insn.name = "addc";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1C3:
stmt->u.insn.name = "addc.";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1D0:
stmt->u.insn.name = "sub";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1D2:
stmt->u.insn.name = "sub.";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1D1:
stmt->u.insn.name = "subc";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1D3:
stmt->u.insn.name = "subc.";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x130:
stmt->u.insn.name = "sra";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x160:
stmt->u.insn.name = "or";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x140:
stmt->u.insn.name = "and";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x170:
stmt->u.insn.name = "xor";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x120:
stmt->u.insn.name = "sr";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x110:
stmt->u.insn.name = "sl";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1A0:
stmt->u.insn.name = "rl";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x1B0:
stmt->u.insn.name = "rr";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x150:
stmt->u.insn.name = "nand";
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ disasm_std_operand(stmt, 2, 2);
break;
case 0x040:
stmt->u.insn.name = "jand";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x040 | 0x1):
stmt->u.insn.name = "jnand";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x050:
stmt->u.insn.name = "js";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x050 | 0x1):
stmt->u.insn.name = "jns";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x0D0:
stmt->u.insn.name = "je";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x0D0 | 0x1):
stmt->u.insn.name = "jne";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x0D2:
stmt->u.insn.name = "jls";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x0D2 | 0x1):
stmt->u.insn.name = "jges";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x0D4:
stmt->u.insn.name = "jgs";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x0D4 | 0x1):
stmt->u.insn.name = "jles";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
+ stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ break;
+ case 0x0D6:
+ stmt->u.insn.name = "@D6"; /* FIXME */
+ stmt->u.insn.labelref_operand = 2;
+ stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ break;
+ case (0x0D6 | 0x1):
+ stmt->u.insn.name = "@D7"; /* FIXME */
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ break;
+ case 0x0D8:
+ stmt->u.insn.name = "@D8"; /* FIXME */
+ stmt->u.insn.labelref_operand = 2;
+ stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
+ break;
+ case (0x0D8 | 0x1):
+ stmt->u.insn.name = "@D9"; /* FIXME */
+ stmt->u.insn.labelref_operand = 2;
+ stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x0DA:
stmt->u.insn.name = "jl";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x0DA | 0x1):
stmt->u.insn.name = "jge";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x0DC:
stmt->u.insn.name = "jg";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case (0x0DC | 0x1):
stmt->u.insn.name = "jle";
- stmt->u.insn.is_labelref = 2;
+ stmt->u.insn.labelref_operand = 2;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 1, 1, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 1, 1);
break;
case 0x002: {
char *str;
switch (cmdargs.arch) {
case 5:
stmt->u.insn.name = "call";
- stmt->u.insn.is_labelref = 1;
+ stmt->u.insn.labelref_operand = 1;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
str = xmalloc(4);
snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]);
break;
case 15:
//FIXME: This opcode is different on r15. Decode raw for now.
- disasm_opcode_raw(ctx, stmt);
+ disasm_opcode_raw(ctx, stmt, 1);
break;
}
break;
stmt->u.insn.operands[2] = str;
break;
}
+ case 0x004: {
+ if (cmdargs.arch != 15) {
+ dasm_error("arch 15 'calls' instruction found in arch %d binary",
+ cmdargs.arch);
+ }
+ stmt->u.insn.name = "calls";
+ stmt->u.insn.labelref_operand = 0;
+ stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
+ if (stmt->u.insn.bin->operands[0] != 0x1780 ||
+ stmt->u.insn.bin->operands[1] != 0x1780)
+ dasm_warn("r15 calls: Invalid first or second argument");
+ break;
+ }
+ case 0x005: {
+ if (cmdargs.arch != 15) {
+ dasm_error("arch 15 'rets' instruction found in arch %d binary",
+ cmdargs.arch);
+ }
+ stmt->u.insn.name = "rets";
+ if (stmt->u.insn.bin->operands[0] != 0x1780 ||
+ stmt->u.insn.bin->operands[1] != 0x1780 ||
+ stmt->u.insn.bin->operands[2] != 0)
+ dasm_warn("r15 rets: Invalid argument(s)");
+ break;
+ }
case 0x1E0: {
unsigned int flags, mask;
mask = 0x7FF;
break;
default:
- fprintf(stderr, "Internal error: TKIP invalid arch\n");
- exit(1);
+ dasm_int_error("TKIP invalid arch");
}
flags = stmt->u.insn.bin->operands[1];
stmt->u.insn.name = "tkipls";
break;
default:
- fprintf(stderr, "Invalid TKIP flags %X\n",
- flags);
- exit(1);
+ dasm_error("Invalid TKIP flags %X", flags);
}
- disasm_std_operand(stmt, 0, 0, 0);
- disasm_std_operand(stmt, 2, 2, 0);
+ disasm_std_operand(stmt, 0, 0);
+ disasm_std_operand(stmt, 2, 2);
break;
}
case 0x001: {
mask = 0x1780;
break;
default:
- fprintf(stderr, "Internal error: NAP invalid arch\n");
- exit(1);
+ dasm_int_error("NAP invalid arch");
}
if (stmt->u.insn.bin->operands[0] != mask) {
- fprintf(stderr, "NAP: invalid first argument 0x%04X\n",
- stmt->u.insn.bin->operands[0]);
+ dasm_warn("NAP: invalid first argument 0x%04X\n",
+ stmt->u.insn.bin->operands[0]);
}
if (stmt->u.insn.bin->operands[1] != mask) {
- fprintf(stderr, "NAP: invalid second argument 0x%04X\n",
- stmt->u.insn.bin->operands[1]);
+ dasm_warn("NAP: invalid second argument 0x%04X\n",
+ stmt->u.insn.bin->operands[1]);
}
if (stmt->u.insn.bin->operands[2] != 0) {
- fprintf(stderr, "NAP: invalid third argument 0x%04X\n",
- stmt->u.insn.bin->operands[2]);
+ dasm_warn("NAP: invalid third argument 0x%04X\n",
+ stmt->u.insn.bin->operands[2]);
}
break;
}
+ case 0x000:
+ disasm_opcode_raw(ctx, stmt, 1);
+ break;
default:
- disasm_opcode_raw(ctx, stmt);
+ disasm_opcode_raw(ctx, stmt, (cmdargs.unknown_decode == 0));
break;
}
}
stmt->type = STMT_INSN;
INIT_LIST_HEAD(&stmt->list);
stmt->u.insn.bin = bin;
- stmt->u.insn.is_labelref = -1;
+ stmt->u.insn.labelref_operand = -1; /* none */
switch (bin->opcode & 0xF00) {
case 0x200:
snprintf(str, 3, "%d", (bin->opcode & 0x00F));
stmt->u.insn.operands[1] = str;
- disasm_std_operand(stmt, 0, 2, 0);
- disasm_std_operand(stmt, 1, 3, 0);
- disasm_std_operand(stmt, 2, 4, 0);
+ disasm_std_operand(stmt, 0, 2);
+ disasm_std_operand(stmt, 1, 3);
+ disasm_std_operand(stmt, 2, 4);
break;
case 0x300:
stmt->u.insn.name = "orx";
snprintf(str, 3, "%d", (bin->opcode & 0x00F));
stmt->u.insn.operands[1] = str;
- disasm_std_operand(stmt, 0, 2, 0);
- disasm_std_operand(stmt, 1, 3, 0);
- disasm_std_operand(stmt, 2, 4, 0);
+ disasm_std_operand(stmt, 0, 2);
+ disasm_std_operand(stmt, 1, 3);
+ disasm_std_operand(stmt, 2, 4);
break;
case 0x400:
stmt->u.insn.name = "jzx";
snprintf(str, 3, "%d", (bin->opcode & 0x00F));
stmt->u.insn.operands[1] = str;
- disasm_std_operand(stmt, 0, 2, 0);
- disasm_std_operand(stmt, 1, 3, 0);
- stmt->u.insn.is_labelref = 4;
+ disasm_std_operand(stmt, 0, 2);
+ disasm_std_operand(stmt, 1, 3);
+ stmt->u.insn.labelref_operand = 4;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
break;
case 0x500:
snprintf(str, 3, "%d", (bin->opcode & 0x00F));
stmt->u.insn.operands[1] = str;
- disasm_std_operand(stmt, 0, 2, 0);
- disasm_std_operand(stmt, 1, 3, 0);
- stmt->u.insn.is_labelref = 4;
+ disasm_std_operand(stmt, 0, 2);
+ disasm_std_operand(stmt, 1, 3);
+ stmt->u.insn.labelref_operand = 4;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
break;
case 0x600:
/* We don't disassemble the first and second operand, as
* that always is a dummy r0 operand.
- * disasm_std_operand(stmt, 0, 1, 0);
- * disasm_std_operand(stmt, 1, 2, 0);
- * stmt->u.insn.is_labelref = 3;
+ * disasm_std_operand(stmt, 0, 1);
+ * disasm_std_operand(stmt, 1, 2);
+ * stmt->u.insn.labelref_operand = 3;
*/
- stmt->u.insn.is_labelref = 1;
+ stmt->u.insn.labelref_operand = 1;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
break;
case 0x700:
/* We don't disassemble the first and second operand, as
* that always is a dummy r0 operand.
- * disasm_std_operand(stmt, 0, 1, 0);
- * disasm_std_operand(stmt, 1, 2, 0);
- * stmt->u.insn.is_labelref = 3;
+ * disasm_std_operand(stmt, 0, 1);
+ * disasm_std_operand(stmt, 1, 2);
+ * stmt->u.insn.labelref_operand = 3;
*/
- stmt->u.insn.is_labelref = 1;
+ stmt->u.insn.labelref_operand = 1;
stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2];
break;
default:
list_for_each_entry_safe(stmt, n, &ctx->stmt_list, list) {
if (stmt->type != STMT_INSN)
continue;
- if (stmt->u.insn.is_labelref == -1)
- continue;
+ if (stmt->u.insn.labelref_operand < 0)
+ continue; /* Doesn't have label reference operand. */
labeladdr = stmt->u.insn.labeladdr;
label = get_label_at(ctx, labeladdr);
- if (!label) {
- fprintf(stderr, "Labeladdress %X out of bounds\n",
- labeladdr);
- exit(1);
- }
+ if (!label)
+ dasm_error("Labeladdress %X out of bounds", labeladdr);
stmt->u.insn.labelref = label;
}
static void emit_asm(struct disassembler_context *ctx)
{
struct statement *stmt;
- int first, i;
+ int first;
int err;
- unsigned int addr = 0;
+ unsigned int i, addr = 0;
err = open_output_file();
if (err)
exit(1);
- fprintf(outfile, "%%arch %u\n\n", ctx->arch);
+ fprintf(outfile, "%%arch %u\n", ctx->arch);
+ fprintf(outfile, "%%start entry\n\n");
+ fprintf(outfile, "entry:\n");
list_for_each_entry(stmt, &ctx->stmt_list, list) {
switch (stmt->type) {
case STMT_INSN:
if (cmdargs.print_addresses)
- fprintf(outfile, "/* %03X */", addr);
+ fprintf(outfile, "/* %04X */", addr);
fprintf(outfile, "\t%s", stmt->u.insn.name);
first = 1;
for (i = 0; i < ARRAY_SIZE(stmt->u.insn.operands); i++) {
- if (stmt->u.insn.is_labelref == i) {
- fprintf(outfile, ", %s",
- stmt->u.insn.labelref->u.label.name);
- }
- if (!stmt->u.insn.operands[i])
+ if (!stmt->u.insn.operands[i] &&
+ (stmt->u.insn.labelref_operand < 0 ||
+ (unsigned int)stmt->u.insn.labelref_operand != i))
continue;
if (first)
fprintf(outfile, "\t");
if (!first)
fprintf(outfile, ", ");
first = 0;
- fprintf(outfile, "%s",
- stmt->u.insn.operands[i]);
+ if (stmt->u.insn.labelref_operand >= 0 &&
+ (unsigned int)stmt->u.insn.labelref_operand == i) {
+ fprintf(outfile, "%s",
+ stmt->u.insn.labelref->u.label.name);
+ } else {
+ fprintf(outfile, "%s",
+ stmt->u.insn.operands[i]);
+ }
}
fprintf(outfile, "\n");
addr++;
case FMT_B43:
ret = fread(&hdr, 1, sizeof(hdr), infile);
if (ret != sizeof(hdr)) {
- fprintf(stderr, "Corrupt input file (not fwcutter output)\n");
+ fprintf(stderr, "Corrupt input file (no b43 header found)\n");
goto err_close;
}
if (hdr.type != FW_TYPE_UCODE) {
- fprintf(stderr, "Corrupt input file. Not a microcode image.\n");
+ fprintf(stderr, "Corrupt input file. Not a b43 microcode image.\n");
goto err_close;
}
if (hdr.ver != FW_HDR_VER) {