disassembler: Emit %start directive. This avoids a warning when re-assembling
[b43-tools.git] / disassembler / main.c
index b3ba68612f8bf7441d543b6b58f81dd791f2d1c2..76295fd5eb2a836b91c1692827c7fb50405e8033 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   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
@@ -72,8 +72,8 @@ 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 +91,23 @@ 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:
+               fprintf(stderr, "Internal error: disasm_indirect_mem_operand invalid arch\n");
+               exit(1);
+       }
        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;
 }
@@ -230,6 +243,15 @@ 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 +461,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: {
@@ -529,10 +557,7 @@ static void disasm_constant_opcodes(struct disassembler_context *ctx,
                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;
        }
 }
@@ -724,7 +749,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: