disassembler: Add new call/ret
[b43-tools.git] / disassembler / main.c
index 43415a1d003575c4b92add7de4e7a5d9cb2368f3..f833f8b2cb01ec96f076840001f5eb8dab098fae 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)); //FIXME r15?
+       snprintf(ret, 12, "[0x%02X,off%u]", offset, reg);
 
        return ret;
 }
@@ -476,6 +489,33 @@ 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) {
+                       fprintf(stderr, "Error: arch 15 call instruction found in arch %d binary\n",
+                               cmdargs.arch);
+                       exit(1);
+               }
+               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) {
+                       fprintf(stderr, "r15 call: Invalid first or second argument\n");
+               }
+               break;
+       }
+       case 0x005: {
+               if (cmdargs.arch != 15) {
+                       fprintf(stderr, "Error: arch 15 ret instruction found in arch %d binary\n",
+                               cmdargs.arch);
+                       exit(1);
+               }
+               stmt->u.insn.name = "ret";
+               break;
+       }
+#endif
        case 0x1E0: {
                unsigned int flags, mask;
 
@@ -736,7 +776,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:
@@ -745,19 +787,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++;