X-Git-Url: https://jxself.org/git/?a=blobdiff_plain;f=assembler%2Fmain.c;h=309d7c5fed1f95536345efe4f26354d70b97eeb0;hb=7ff7a760aa92b63ed4af8aabddb621cc9483e67f;hp=f2d2826aa5b2e804bf75506347d8b3b8a0f63aed;hpb=f981680e63cf6efb80b270d5ba2d30ffcbbf0ef4;p=b43-tools.git diff --git a/assembler/main.c b/assembler/main.c index f2d2826..309d7c5 100644 --- a/assembler/main.c +++ b/assembler/main.c @@ -325,9 +325,21 @@ static unsigned int generate_mem_operand(struct assembler_context *ctx, case MEM_DIRECT: /* format: 0b0mmm mmmm mmmm */ off = mem->offset; - if (off & ~0x7FF) { //FIXME 4096 words for v15 arch possible? - asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off); - off &= 0x7FF; + switch (ctx->arch) { + case 5: + if (off & ~0x7FF) { + asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 11 bits)", off); + off &= 0x7FF; + } + break; + case 15: + if (off & ~0xFFF) { + asm_warn(ctx, "DIRECT memoffset 0x%X too long (> 12 bits)", off); + off &= 0xFFF; + } + break; + default: + asm_error(ctx, "Internal error: generate_mem_operand invalid arch"); } val |= off; break; @@ -341,8 +353,14 @@ static unsigned int generate_mem_operand(struct assembler_context *ctx, asm_warn(ctx, "INDIRECT memoffset 0x%X too long (> 6 bits)", off); off &= 0x3F; } - if (reg & ~0x7) + if (reg > 6) { + /* Assembler bug. The parser shouldn't pass this value. */ asm_error(ctx, "OFFR-nr too big"); + } + if (reg == 6 && ctx->arch == 5) { + asm_warn(ctx, "Using offset register 6. This register is broken " + "on architecture 5 devices. Use off0 to off5 only."); + } val |= off; val |= (reg << 6); break; @@ -488,8 +506,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 +589,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 +835,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_warn(ctx, "RET instruction directly after " + "jump instruction. The hardware won't like this."); + } + break; } } do_assemble_insn(ctx, insn, 0x003); @@ -1022,21 +1044,17 @@ does_not_exist: static void emit_code(struct assembler_context *ctx) { FILE *fd; - char *fn; - size_t fn_len; + const char *fn; struct code_output *c; uint64_t code; unsigned char outbuf[8]; unsigned int insn_count = 0; struct fw_header hdr; - fn_len = strlen(outfile_name) + 20; - fn = xmalloc(fn_len); - snprintf(fn, fn_len, "%s.ucode", outfile_name); + fn = outfile_name; fd = fopen(fn, "w+"); if (!fd) { fprintf(stderr, "Could not open microcode output file \"%s\"\n", fn); - free(fn); exit(1); } if (IS_VERBOSE_DEBUG) @@ -1121,8 +1139,14 @@ static void emit_code(struct assembler_context *ctx) break; } } + + if (arg_print_sizes) { + printf("%s: text = %u instructions (%u bytes)\n", + fn, insn_count, + (unsigned int)(insn_count * sizeof(uint64_t))); + } + fclose(fd); - free(fn); } static void assemble(void)