mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-05-05 05:02:14 +00:00
target-m68k: Split gen_lea and gen_ea
Provide gen_lea_mode and gen_ea_mode, where the mode can be specified manually, rather than taken from the instruction. Backports commit f84aab269ddab8509b77408b886e9071bf5c48fb from qemu
This commit is contained in:
parent
5541553e8d
commit
e6ca471dda
|
@ -696,8 +696,8 @@ static void gen_partset_reg(DisasContext *s, int opsize, TCGv reg, TCGv val)
|
||||||
|
|
||||||
/* Generate code for an "effective address". Does not adjust the base
|
/* Generate code for an "effective address". Does not adjust the base
|
||||||
register for autoincrement addressing modes. */
|
register for autoincrement addressing modes. */
|
||||||
static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s,
|
||||||
int opsize)
|
int mode, int reg0, int opsize)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv reg;
|
TCGv reg;
|
||||||
|
@ -705,29 +705,29 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
uint16_t ext;
|
uint16_t ext;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
switch ((insn >> 3) & 7) {
|
switch (mode) {
|
||||||
case 0: /* Data register direct. */
|
case 0: /* Data register direct. */
|
||||||
case 1: /* Address register direct. */
|
case 1: /* Address register direct. */
|
||||||
return tcg_ctx->NULL_QREG;
|
return tcg_ctx->NULL_QREG;
|
||||||
case 2: /* Indirect register */
|
case 2: /* Indirect register */
|
||||||
case 3: /* Indirect postincrement. */
|
case 3: /* Indirect postincrement. */
|
||||||
return AREG(insn, 0);
|
return get_areg(s, reg0);
|
||||||
case 4: /* Indirect predecrememnt. */
|
case 4: /* Indirect predecrememnt. */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
tmp = tcg_temp_new(tcg_ctx);
|
tmp = tcg_temp_new(tcg_ctx);
|
||||||
tcg_gen_subi_i32(tcg_ctx, tmp, reg, opsize_bytes(opsize));
|
tcg_gen_subi_i32(tcg_ctx, tmp, reg, opsize_bytes(opsize));
|
||||||
return tmp;
|
return tmp;
|
||||||
case 5: /* Indirect displacement. */
|
case 5: /* Indirect displacement. */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
tmp = tcg_temp_new(tcg_ctx);
|
tmp = tcg_temp_new(tcg_ctx);
|
||||||
ext = read_im16(env, s);
|
ext = read_im16(env, s);
|
||||||
tcg_gen_addi_i32(tcg_ctx, tmp, reg, (int16_t)ext);
|
tcg_gen_addi_i32(tcg_ctx, tmp, reg, (int16_t)ext);
|
||||||
return tmp;
|
return tmp;
|
||||||
case 6: /* Indirect index + displacement. */
|
case 6: /* Indirect index + displacement. */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
return gen_lea_indexed(env, s, reg);
|
return gen_lea_indexed(env, s, reg);
|
||||||
case 7: /* Other */
|
case 7: /* Other */
|
||||||
switch (insn & 7) {
|
switch (reg0) {
|
||||||
case 0: /* Absolute short. */
|
case 0: /* Absolute short. */
|
||||||
offset = (int16_t)read_im16(env, s);
|
offset = (int16_t)read_im16(env, s);
|
||||||
return tcg_const_i32(tcg_ctx, offset);
|
return tcg_const_i32(tcg_ctx, offset);
|
||||||
|
@ -749,41 +749,27 @@ static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
return tcg_ctx->NULL_QREG;
|
return tcg_ctx->NULL_QREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function for gen_ea. Reuse the computed address between the
|
static TCGv gen_lea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
for read/write operands. */
|
int opsize)
|
||||||
static inline TCGv gen_ea_once(CPUM68KState *env, DisasContext *s,
|
|
||||||
uint16_t insn, int opsize, TCGv val,
|
|
||||||
TCGv *addrp, ea_what what)
|
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
int mode = extract32(insn, 3, 3);
|
||||||
TCGv tmp;
|
int reg0 = REG(insn, 0);
|
||||||
|
return gen_lea_mode(env, s, mode, reg0, opsize);
|
||||||
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;
|
|
||||||
}
|
|
||||||
return gen_ldst(s, opsize, tmp, val, what);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate code to load/store a value from/into an EA. If VAL > 0 this is
|
/* Generate code to load/store a value from/into an EA. If WHAT > 0 this is
|
||||||
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
|
a write otherwise it is a read (0 == sign extend, -1 == zero extend).
|
||||||
ADDRP is non-null for readwrite operands. */
|
ADDRP is non-null for readwrite operands. */
|
||||||
static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0,
|
||||||
int opsize, TCGv val, TCGv *addrp, ea_what what)
|
int opsize, TCGv val, TCGv *addrp, ea_what what)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
TCGv reg;
|
TCGv reg, tmp, result;
|
||||||
TCGv result;
|
int32_t offset;
|
||||||
uint32_t offset;
|
|
||||||
|
|
||||||
switch ((insn >> 3) & 7) {
|
switch (mode) {
|
||||||
case 0: /* Data register direct. */
|
case 0: /* Data register direct. */
|
||||||
reg = DREG(insn, 0);
|
reg = tcg_ctx->cpu_dregs[reg0];
|
||||||
if (what == EA_STORE) {
|
if (what == EA_STORE) {
|
||||||
gen_partset_reg(s, opsize, reg, val);
|
gen_partset_reg(s, opsize, reg, val);
|
||||||
return tcg_ctx->store_dummy;
|
return tcg_ctx->store_dummy;
|
||||||
|
@ -791,7 +777,7 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
return gen_extend(s, reg, opsize, what == EA_LOADS);
|
return gen_extend(s, reg, opsize, what == EA_LOADS);
|
||||||
}
|
}
|
||||||
case 1: /* Address register direct. */
|
case 1: /* Address register direct. */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
if (what == EA_STORE) {
|
if (what == EA_STORE) {
|
||||||
tcg_gen_mov_i32(tcg_ctx, reg, val);
|
tcg_gen_mov_i32(tcg_ctx, reg, val);
|
||||||
return tcg_ctx->store_dummy;
|
return tcg_ctx->store_dummy;
|
||||||
|
@ -799,45 +785,56 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
return gen_extend(s, reg, opsize, what == EA_LOADS);
|
return gen_extend(s, reg, opsize, what == EA_LOADS);
|
||||||
}
|
}
|
||||||
case 2: /* Indirect register */
|
case 2: /* Indirect register */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
return gen_ldst(s, opsize, reg, val, what);
|
return gen_ldst(s, opsize, reg, val, what);
|
||||||
case 3: /* Indirect postincrement. */
|
case 3: /* Indirect postincrement. */
|
||||||
reg = AREG(insn, 0);
|
reg = get_areg(s, reg0);
|
||||||
result = gen_ldst(s, opsize, reg, val, what);
|
result = gen_ldst(s, opsize, reg, val, what);
|
||||||
if (what == EA_STORE || !addrp) {
|
if (what == EA_STORE || !addrp) {
|
||||||
TCGv tmp = tcg_temp_new(tcg_ctx);
|
TCGv tmp = tcg_temp_new(tcg_ctx);
|
||||||
tcg_gen_addi_i32(tcg_ctx, tmp, reg, opsize_bytes(opsize));
|
tcg_gen_addi_i32(tcg_ctx, tmp, reg, opsize_bytes(opsize));
|
||||||
delay_set_areg(s, REG(insn, 0), tmp, true);
|
delay_set_areg(s, reg0, tmp, true);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
case 4: /* Indirect predecrememnt. */
|
case 4: /* Indirect predecrememnt. */
|
||||||
{
|
|
||||||
TCGv tmp;
|
|
||||||
if (addrp && what == EA_STORE) {
|
if (addrp && what == EA_STORE) {
|
||||||
tmp = *addrp;
|
tmp = *addrp;
|
||||||
} else {
|
} else {
|
||||||
tmp = gen_lea(env, s, insn, opsize);
|
tmp = gen_lea_mode(env, s, mode, reg0, opsize);
|
||||||
if (IS_NULL_QREG(tmp))
|
if (IS_NULL_QREG(tmp)) {
|
||||||
return tmp;
|
return tmp;
|
||||||
if (addrp)
|
}
|
||||||
|
if (addrp) {
|
||||||
*addrp = tmp;
|
*addrp = tmp;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
result = gen_ldst(s, opsize, tmp, val, what);
|
result = gen_ldst(s, opsize, tmp, val, what);
|
||||||
if (what == EA_STORE || !addrp) {
|
if (what == EA_STORE || !addrp) {
|
||||||
delay_set_areg(s, REG(insn, 0), tmp, false);
|
delay_set_areg(s, reg0, tmp, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
case 5: /* Indirect displacement. */
|
case 5: /* Indirect displacement. */
|
||||||
case 6: /* Indirect index + displacement. */
|
case 6: /* Indirect index + displacement. */
|
||||||
return gen_ea_once(env, s, insn, opsize, val, addrp, what);
|
do_indirect:
|
||||||
|
if (addrp && what == EA_STORE) {
|
||||||
|
tmp = *addrp;
|
||||||
|
} else {
|
||||||
|
tmp = gen_lea_mode(env, s, mode, reg0, opsize);
|
||||||
|
if (IS_NULL_QREG(tmp)) {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
if (addrp) {
|
||||||
|
*addrp = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gen_ldst(s, opsize, tmp, val, what);
|
||||||
case 7: /* Other */
|
case 7: /* Other */
|
||||||
switch (insn & 7) {
|
switch (reg0) {
|
||||||
case 0: /* Absolute short. */
|
case 0: /* Absolute short. */
|
||||||
case 1: /* Absolute long. */
|
case 1: /* Absolute long. */
|
||||||
case 2: /* pc displacement */
|
case 2: /* pc displacement */
|
||||||
case 3: /* pc index+displacement. */
|
case 3: /* pc index+displacement. */
|
||||||
return gen_ea_once(env, s, insn, opsize, val, addrp, what);
|
goto do_indirect;
|
||||||
case 4: /* Immediate. */
|
case 4: /* Immediate. */
|
||||||
/* Sign extend values for consistency. */
|
/* Sign extend values for consistency. */
|
||||||
switch (opsize) {
|
switch (opsize) {
|
||||||
|
@ -870,6 +867,14 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
return tcg_ctx->NULL_QREG;
|
return tcg_ctx->NULL_QREG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
|
int opsize, TCGv val, TCGv *addrp, ea_what what)
|
||||||
|
{
|
||||||
|
int mode = extract32(insn, 3, 3);
|
||||||
|
int reg0 = REG(insn, 0);
|
||||||
|
return gen_ea_mode(env, s, mode, reg0, opsize, val, addrp, what);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TCGCond tcond;
|
TCGCond tcond;
|
||||||
bool g1;
|
bool g1;
|
||||||
|
|
Loading…
Reference in a new issue