mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:15:07 +00:00
target-m68k: Delay autoinc writeback
Backports commit 8a1e52b69d2cd1c633f3c473a213d575931bf46d from qemu
This commit is contained in:
parent
c7ab1e782b
commit
5541553e8d
|
@ -37,12 +37,12 @@
|
||||||
#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
|
#define tcg_gen_qemu_ldf64 tcg_gen_qemu_ld64
|
||||||
#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
|
#define tcg_gen_qemu_stf64 tcg_gen_qemu_st64
|
||||||
|
|
||||||
#define REG(insn, pos) (((insn) >> (pos)) & 7)
|
#define REG(insn, pos) (((insn) >> (pos)) & 7)
|
||||||
#define DREG(insn, pos) tcg_ctx->cpu_dregs[REG(insn, pos)]
|
#define DREG(insn, pos) tcg_ctx->cpu_dregs[REG(insn, pos)]
|
||||||
#define AREG(insn, pos) tcg_ctx->cpu_aregs[REG(insn, pos)]
|
#define AREG(insn, pos) get_areg(s, REG(insn, pos))
|
||||||
#define FREG(insn, pos) tcg_ctx->cpu_fregs[REG(insn, pos)]
|
#define FREG(insn, pos) tcg_ctx->cpu_fregs[REG(insn, pos)]
|
||||||
#define MACREG(acc) tcg_ctx->cpu_macc[acc]
|
#define MACREG(acc) tcg_ctx->cpu_macc[acc]
|
||||||
#define QREG_SP tcg_ctx->cpu_aregs[7]
|
#define QREG_SP tcg_ctx->cpu_aregs[7]
|
||||||
|
|
||||||
#define IS_NULL_QREG(t) (TCGV_EQUAL(t, tcg_ctx->NULL_QREG))
|
#define IS_NULL_QREG(t) (TCGV_EQUAL(t, tcg_ctx->NULL_QREG))
|
||||||
|
|
||||||
|
@ -113,11 +113,64 @@ typedef struct DisasContext {
|
||||||
int singlestep_enabled;
|
int singlestep_enabled;
|
||||||
TCGv_i64 mactmp;
|
TCGv_i64 mactmp;
|
||||||
int done_mac;
|
int done_mac;
|
||||||
|
int writeback_mask;
|
||||||
|
TCGv writeback[8];
|
||||||
|
|
||||||
// Unicorn engine
|
// Unicorn engine
|
||||||
struct uc_struct *uc;
|
struct uc_struct *uc;
|
||||||
} DisasContext;
|
} DisasContext;
|
||||||
|
|
||||||
|
static TCGv get_areg(DisasContext *s, unsigned regno)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
||||||
|
if (s->writeback_mask & (1 << regno)) {
|
||||||
|
return s->writeback[regno];
|
||||||
|
} else {
|
||||||
|
return tcg_ctx->cpu_aregs[regno];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void delay_set_areg(DisasContext *s, unsigned regno,
|
||||||
|
TCGv val, bool give_temp)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
||||||
|
if (s->writeback_mask & (1 << regno)) {
|
||||||
|
if (give_temp) {
|
||||||
|
tcg_temp_free(tcg_ctx, s->writeback[regno]);
|
||||||
|
s->writeback[regno] = val;
|
||||||
|
} else {
|
||||||
|
tcg_gen_mov_i32(tcg_ctx, s->writeback[regno], val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s->writeback_mask |= 1 << regno;
|
||||||
|
if (give_temp) {
|
||||||
|
s->writeback[regno] = val;
|
||||||
|
} else {
|
||||||
|
TCGv tmp = tcg_temp_new(tcg_ctx);
|
||||||
|
s->writeback[regno] = tmp;
|
||||||
|
tcg_gen_mov_i32(tcg_ctx, tmp, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_writebacks(DisasContext *s)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
|
|
||||||
|
unsigned mask = s->writeback_mask;
|
||||||
|
if (mask) {
|
||||||
|
s->writeback_mask = 0;
|
||||||
|
do {
|
||||||
|
unsigned regno = ctz32(mask);
|
||||||
|
tcg_gen_mov_i32(tcg_ctx, tcg_ctx->cpu_aregs[regno], s->writeback[regno]);
|
||||||
|
tcg_temp_free(tcg_ctx, s->writeback[regno]);
|
||||||
|
mask &= mask - 1;
|
||||||
|
} while (mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define DISAS_JUMP_NEXT 4
|
#define DISAS_JUMP_NEXT 4
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
@ -751,10 +804,11 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
case 3: /* Indirect postincrement. */
|
case 3: /* Indirect postincrement. */
|
||||||
reg = AREG(insn, 0);
|
reg = AREG(insn, 0);
|
||||||
result = gen_ldst(s, opsize, reg, val, what);
|
result = gen_ldst(s, opsize, reg, val, what);
|
||||||
/* ??? This is not exception safe. The instruction may still
|
if (what == EA_STORE || !addrp) {
|
||||||
fault after this point. */
|
TCGv tmp = tcg_temp_new(tcg_ctx);
|
||||||
if (what == EA_STORE || !addrp)
|
tcg_gen_addi_i32(tcg_ctx, tmp, reg, opsize_bytes(opsize));
|
||||||
tcg_gen_addi_i32(tcg_ctx, reg, reg, opsize_bytes(opsize));
|
delay_set_areg(s, REG(insn, 0), tmp, true);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
case 4: /* Indirect predecrememnt. */
|
case 4: /* Indirect predecrememnt. */
|
||||||
{
|
{
|
||||||
|
@ -769,11 +823,8 @@ static TCGv gen_ea(CPUM68KState *env, DisasContext *s, uint16_t insn,
|
||||||
*addrp = tmp;
|
*addrp = tmp;
|
||||||
}
|
}
|
||||||
result = gen_ldst(s, opsize, tmp, val, what);
|
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) {
|
if (what == EA_STORE || !addrp) {
|
||||||
reg = AREG(insn, 0);
|
delay_set_areg(s, REG(insn, 0), tmp, false);
|
||||||
tcg_gen_mov_i32(tcg_ctx, reg, tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -3558,7 +3609,6 @@ void register_m68k_insns (CPUM68KState *env)
|
||||||
static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
|
static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
TCGContext *tcg_ctx = s->uc->tcg_ctx;
|
||||||
uint16_t insn;
|
|
||||||
|
|
||||||
// Unicorn: end address tells us to stop emulation
|
// Unicorn: end address tells us to stop emulation
|
||||||
if (s->pc == s->uc->addr_end) {
|
if (s->pc == s->uc->addr_end) {
|
||||||
|
@ -3573,9 +3623,9 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
|
||||||
check_exit_request(tcg_ctx);
|
check_exit_request(tcg_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
insn = read_im16(env, s);
|
uint16_t insn = read_im16(env, s);
|
||||||
|
|
||||||
((disas_proc)tcg_ctx->opcode_table[insn])(env, s, insn);
|
((disas_proc)tcg_ctx->opcode_table[insn])(env, s, insn);
|
||||||
|
do_writebacks(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
|
@ -3606,6 +3656,7 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
|
||||||
dc->fpcr = env->fpcr;
|
dc->fpcr = env->fpcr;
|
||||||
dc->user = (env->sr & SR_S) == 0;
|
dc->user = (env->sr & SR_S) == 0;
|
||||||
dc->done_mac = 0;
|
dc->done_mac = 0;
|
||||||
|
dc->writeback_mask = 0;
|
||||||
num_insns = 0;
|
num_insns = 0;
|
||||||
max_insns = tb->cflags & CF_COUNT_MASK;
|
max_insns = tb->cflags & CF_COUNT_MASK;
|
||||||
if (max_insns == 0) {
|
if (max_insns == 0) {
|
||||||
|
|
Loading…
Reference in a new issue