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) {
+ asm_warn(ctx, "Using offset register 6. This register is broken "
+ "on certain devices. Use off0 to off5 only.");
+ }
val |= off;
val |= (reg << 6);
break;
/* 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;
{
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 */
}
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);
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)
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)