static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn, int opsize, TCGv val, TCGv *addrp, ea_what what) { TCGv reg; TCGv result; uint32_t offset; switch ((insn >> 3) & 7) { case 0: /* Data register direct. */ reg = DREG(insn, 0); if (what == EA_STORE) { gen_partset_reg(opsize, reg, val); return store_dummy; } else { return gen_extend(reg, opsize, what == EA_LOADS); } case 1: /* Address register direct. */ reg = AREG(insn, 0); if (what == EA_STORE) { tcg_gen_mov_i32(reg, val); return store_dummy; } else { return gen_extend(reg, opsize, what == EA_LOADS); } case 2: /* Indirect register */ reg = AREG(insn, 0); return gen_ldst(s, opsize, reg, val, what); case 3: /* Indirect postincrement. */ reg = AREG(insn, 0); result = gen_ldst(s, opsize, reg, val, what); /* ??? This is not exception safe. The instruction may still fault after this point. */ if (what == EA_STORE || !addrp) tcg_gen_addi_i32(reg, reg, opsize_bytes(opsize)); return result; case 4: /* Indirect predecrememnt. */ { TCGv tmp; if (addrp && what == EA_STORE) { tmp = *addrp; } else { tmp = gen_lea(env, s, insn, opsize); if (IS_NULL_QREG(tmp)) return tmp; if (addrp) *addrp = tmp; } result = gen_ldst(s, opsize, tmp, val, what); /* ??? This is not exception safe. The instruction may still fault after this point. */ if (what == EA_STORE || !addrp) { reg = AREG(insn, 0); tcg_gen_mov_i32(reg, tmp); } } return result; case 5: /* Indirect displacement. */ case 6: /* Indirect index + displacement. */ return gen_ea_once(env, s, insn, opsize, val, addrp, what); case 7: /* Other */ switch (insn & 7) { case 0: /* Absolute short. */ case 1: /* Absolute long. */ case 2: /* pc displacement */ case 3: /* pc index+displacement. */ return gen_ea_once(env, s, insn, opsize, val, addrp, what); case 4: /* Immediate. */ /* Sign extend values for consistency. */ switch (opsize) { case OS_BYTE: if (what == EA_LOADS) { offset = cpu_ldsb_code(env, s->pc + 1); } else { offset = cpu_ldub_code(env, s->pc + 1); } s->pc += 2; break; case OS_WORD: if (what == EA_LOADS) { offset = cpu_ldsw_code(env, s->pc); } else { offset = cpu_lduw_code(env, s->pc); } s->pc += 2; break; case OS_LONG: offset = read_im32(env, s); break; default: qemu_assert(0, "Bad immediate operand"); } return tcg_const_i32(offset); default: return NULL_QREG; } } /* Should never happen. */ return NULL_QREG; }