unsigned int opbase,
struct instruction *insn)
{
+ struct operand *fake;
+ struct registr *fake_reg;
+ struct operand *target;
struct operlist *ol;
unsigned int cond;
unsigned int opcode;
if (cond & ~0xFF)
asm_error(ctx, "External jump condition value too big (> 0xFF)");
opcode |= cond;
- ol->oper[0] = ol->oper[1];
- ol->oper[1] = ol->oper[2];
- ol->oper[2] = ol->oper[3];
+ target = ol->oper[1];
+ memset(ol->oper, 0, sizeof(ol->oper));
+
+ /* This instruction has two fake r0 operands
+ * at position 0 and 1. */
+ fake = xmalloc(sizeof(*fake));
+ fake_reg = xmalloc(sizeof(*fake_reg));
+ fake->type = OPER_REG;
+ fake->u.reg = fake_reg;
+ fake_reg->type = GPR;
+ fake_reg->nr = 0;
+
+ ol->oper[0] = fake;
+ ol->oper[1] = fake;
+ ol->oper[2] = target;
return opcode;
}
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);