b43-asm: Add an option to print the code sizes after assembling.
[b43-tools.git] / assembler / main.c
index f2d2826aa5b2e804bf75506347d8b3b8a0f63aed..255cabc88c74b6966d0c0a4262e374d2048cdf14 100644 (file)
@@ -488,8 +488,8 @@ static unsigned int merge_external_jmp_into_opcode(struct assembler_context *ctx
 
        /* This instruction has two fake r0 operands
         * at position 0 and 1. */
-       fake = xmalloc(sizeof(struct operand));
-       fake_reg = xmalloc(sizeof(struct operand));
+       fake = xmalloc(sizeof(*fake));
+       fake_reg = xmalloc(sizeof(*fake_reg));
        fake->type = OPER_REG;
        fake->u.reg = fake_reg;
        fake_reg->type = GPR;
@@ -571,19 +571,20 @@ static void emulate_jmp_insn(struct assembler_context *ctx,
 {
        struct instruction em_insn;
        struct operlist em_ol;
-       struct operand em_op;
-       struct immediate em_imm;
-
-       /* This is a pseudo-OP. We emulate it by JE */
-
-       em_insn.op = OP_JE;
-       em_imm.imm = 1;
-       em_op.type = OPER_IMM;
-       em_op.u.imm = &em_imm;
-       em_ol.oper[0] = &em_op;
-       em_ol.oper[1] = &em_op;
-       em_ol.oper[2] = insn->operands->oper[0];
+       struct immediate em_condition;
+       struct operand em_cond_op;
+
+       /* This is a pseudo-OP. We emulate it with
+        * JEXT 0x7F, target */
+
+       em_insn.op = OP_JEXT;
+       em_condition.imm = 0x7F; /* Ext cond: Always true */
+       em_cond_op.type = OPER_IMM;
+       em_cond_op.u.imm = &em_condition;
+       em_ol.oper[0] = &em_cond_op;
+       em_ol.oper[1] = insn->operands->oper[0]; /* Target */
        em_insn.operands = &em_ol;
+
        assemble_instruction(ctx, &em_insn); /* recurse */
 }
 
@@ -816,13 +817,16 @@ static void assemble_instruction(struct assembler_context *ctx,
                do_assemble_insn(ctx, insn, 0x002);
                break;
        case OP_RET:
-               if (!list_empty(&ctx->output)) {
-                       /* Get the previous instruction and check whether it
-                        * is a jump instruction. */
-                       out = list_entry(ctx->output.prev, struct code_output, list);
-                       if (out->is_jump_insn) {
-                               asm_error(ctx, "RET instruction directly after "
-                                         "jump instruction. The hardware won't like this.");
+               /* Get the previous instruction and check whether it
+                * is a jump instruction. */
+               list_for_each_entry_reverse(out, &ctx->output, list) {
+                       /* Search the last insn. */
+                       if (out->type == OUT_INSN) {
+                               if (out->is_jump_insn) {
+                                       asm_error(ctx, "RET instruction directly after "
+                                                 "jump instruction. The hardware won't like this.");
+                               }
+                               break;
                        }
                }
                do_assemble_insn(ctx, insn, 0x003);
@@ -1121,6 +1125,12 @@ static void emit_code(struct assembler_context *ctx)
                        break;
                }
        }
+
+       if (arg_print_sizes) {
+               printf("%s:  text = %u instructions (%u bytes)\n",
+                      fn, insn_count, insn_count * sizeof(uint64_t));
+       }
+
        fclose(fd);
        free(fn);
 }