X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=disassembler%2Fmain.c;h=2e10012bb90f3b7c4d653885efda55e24a4cb498;hb=1a8718d7ef605cdbcd19965317f5758f1a8d5f1d;hp=b3ba68612f8bf7441d543b6b58f81dd791f2d1c2;hpb=f85d6d1ed19b4307c330e8c85eac3bc04a8d8f5a;p=b43-tools.git diff --git a/disassembler/main.c b/disassembler/main.c index b3ba686..2e10012 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)); + 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); @@ -223,13 +251,21 @@ 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); } +static void disasm_opcode_raw(struct disassembler_context *ctx, + struct statement *stmt) +{ + 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); +} + static void disasm_constant_opcodes(struct disassembler_context *ctx, struct statement *stmt) { @@ -439,14 +475,20 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, case 0x002: { char *str; - //FIXME: Broken for r15 - stmt->u.insn.name = "call"; - stmt->u.insn.is_labelref = 1; -//printf("CALL 0x%X 0x%X 0x%X\n", stmt->u.insn.bin->operands[0], stmt->u.insn.bin->operands[1], stmt->u.insn.bin->operands[2]); - stmt->u.insn.labeladdr = stmt->u.insn.bin->operands[2]; - str = xmalloc(4); - snprintf(str, 4, "lr%u", stmt->u.insn.bin->operands[0]); - stmt->u.insn.operands[0] = str; + switch (cmdargs.arch) { + case 5: + stmt->u.insn.name = "call"; + stmt->u.insn.is_labelref = 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]); + stmt->u.insn.operands[0] = str; + break; + case 15: + //FIXME: This opcode is different on r15. Decode raw for now. + disasm_opcode_raw(ctx, stmt); + break; + } break; } case 0x003: { @@ -461,6 +503,30 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx, stmt->u.insn.operands[2] = str; break; } +//TODO also implement it in the assembler +#if 0 + case 0x004: { + if (cmdargs.arch != 15) { + dasm_error("arch 15 call instruction found in arch %d binary", + cmdargs.arch); + } + stmt->u.insn.name = "call"; + 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 call: Invalid first or second argument"); + break; + } + case 0x005: { + if (cmdargs.arch != 15) { + dasm_error("arch 15 ret instruction found in arch %d binary", + cmdargs.arch); + } + stmt->u.insn.name = "ret"; + break; + } +#endif case 0x1E0: { unsigned int flags, mask; @@ -472,8 +538,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]; @@ -491,9 +556,7 @@ 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); @@ -511,28 +574,24 @@ 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; } default: - stmt->u.insn.name = gen_raw_code(bin->opcode); - disasm_std_operand(stmt, 0, 0, 1); - disasm_std_operand(stmt, 1, 1, 1); - disasm_std_operand(stmt, 2, 2, 1); + disasm_opcode_raw(ctx, stmt); break; } } @@ -695,11 +754,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; } @@ -724,7 +780,9 @@ 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: @@ -733,19 +791,21 @@ static void emit_asm(struct disassembler_context *ctx) 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++;