X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=disassembler%2Fmain.c;h=cf716df8fb9b21bb14812a8428f9549965d792f3;hb=6741c3e236e8a3cb812c2028d18d7a7f91bab5f5;hp=43415a1d003575c4b92add7de4e7a5d9cb2368f3;hpb=7ff7a760aa92b63ed4af8aabddb621cc9483e67f;p=b43-tools.git diff --git a/disassembler/main.c b/disassembler/main.c index 43415a1..cf716df 100644 --- a/disassembler/main.c +++ b/disassembler/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 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 @@ -68,12 +68,31 @@ const char *infile_name; 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; - ret = xmalloc(5); - snprintf(ret, 5, "@%03X", operand); + ret = xmalloc(6); + snprintf(ret, 6, "@%X", operand); return ret; } @@ -91,10 +110,22 @@ static const char * disasm_mem_operand(unsigned int operand) static const char * disasm_indirect_mem_operand(unsigned int operand) { char *ret; + unsigned int offset, reg; + switch (cmdargs.arch) { + case 5: + offset = (operand & 0x3F); + reg = ((operand >> 6) & 0x7); + break; + case 15: + offset = (operand & 0x7F); + reg = ((operand >> 7) & 0x7); + break; + default: + dasm_int_error("disasm_indirect_mem_operand invalid arch"); + } ret = xmalloc(12); - snprintf(ret, 12, "[0x%02X,off%u]", - (operand & 0x3F), ((operand >> 6) & 0x7)); //FIXME r15? + snprintf(ret, 12, "[0x%02X,off%u]", offset, reg); return ret; } @@ -115,8 +146,7 @@ static const char * disasm_imm_operand(unsigned int operand) 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; @@ -142,8 +172,7 @@ static const char * disasm_spr_operand(unsigned int operand) 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); @@ -165,8 +194,7 @@ static const char * disasm_gpr_operand(unsigned int operand) 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); @@ -175,15 +203,20 @@ static const char * disasm_gpr_operand(unsigned int operand) 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: @@ -223,20 +256,26 @@ static void disasm_std_operand(struct statement *stmt, } 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, @@ -247,203 +286,203 @@ 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.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.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.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.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.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.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.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.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.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.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: stmt->u.insn.name = "jl"; stmt->u.insn.is_labelref = 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.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.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.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; @@ -459,7 +498,7 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, 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; @@ -476,6 +515,31 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, 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.is_labelref = 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; @@ -487,8 +551,7 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, 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]; @@ -506,12 +569,10 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, 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: { @@ -526,25 +587,27 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, 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; } } @@ -576,9 +639,9 @@ static void disasm_opcodes(struct disassembler_context *ctx) 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"; @@ -590,9 +653,9 @@ static void disasm_opcodes(struct disassembler_context *ctx) 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"; @@ -604,8 +667,8 @@ static void disasm_opcodes(struct disassembler_context *ctx) 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, 0, 2); + disasm_std_operand(stmt, 1, 3); stmt->u.insn.is_labelref = 4; stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2]; break; @@ -619,8 +682,8 @@ static void disasm_opcodes(struct disassembler_context *ctx) 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, 0, 2); + disasm_std_operand(stmt, 1, 3); stmt->u.insn.is_labelref = 4; stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2]; break; @@ -633,8 +696,8 @@ static void disasm_opcodes(struct disassembler_context *ctx) /* 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); + * disasm_std_operand(stmt, 0, 1); + * disasm_std_operand(stmt, 1, 2); * stmt->u.insn.is_labelref = 3; */ stmt->u.insn.is_labelref = 1; @@ -649,8 +712,8 @@ static void disasm_opcodes(struct disassembler_context *ctx) /* 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); + * disasm_std_operand(stmt, 0, 1); + * disasm_std_operand(stmt, 1, 2); * stmt->u.insn.is_labelref = 3; */ stmt->u.insn.is_labelref = 1; @@ -707,11 +770,8 @@ static void resolve_labels(struct disassembler_context *ctx) continue; 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; } @@ -736,28 +796,32 @@ static void emit_asm(struct disassembler_context *ctx) 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.is_labelref != 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.is_labelref == i) { + fprintf(outfile, "%s", + stmt->u.insn.labelref->u.label.name); + } else { + fprintf(outfile, "%s", + stmt->u.insn.operands[i]); + } } fprintf(outfile, "\n"); addr++;