mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 16:53:55 -06:00
SH: Improve movca.l/ocbi emulation.
Author: Vladimir Prus <vladimir@codesourcery.com> Fix movcal.l/ocbi emulation. * target-sh4/cpu.h (memory_content): New. (CPUSH4State): New fields movcal_backup and movcal_backup_tail. * target-sh4/helper.h (helper_movcal) (helper_discard_movcal_backup, helper_ocbi): New. * target-sh4/op_helper.c (helper_movcal) (helper_discard_movcal_backup, helper_ocbi): New. * target-sh4/translate.c (DisasContext): New field has_movcal. (sh4_defs): Update CVS for SH7785. (cpu_sh4_init): Initialize env->movcal_backup_tail. (_decode_opc): Discard movca.l-backup. Make use of helper_movcal and helper_ocbi. (gen_intermediate_code_internal): Initialize has_movcal to 1. Thanks to Shin-ichiro KAWASAKI and Paul Mundt for valuable feedback. Acked-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6966 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
714fa308a3
commit
852d481faf
5 changed files with 156 additions and 5 deletions
|
@ -50,6 +50,7 @@ typedef struct DisasContext {
|
|||
uint32_t delayed_pc;
|
||||
int singlestep_enabled;
|
||||
uint32_t features;
|
||||
int has_movcal;
|
||||
} DisasContext;
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
@ -283,6 +284,7 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
|
|||
env = qemu_mallocz(sizeof(CPUSH4State));
|
||||
env->features = def->features;
|
||||
cpu_exec_init(env);
|
||||
env->movcal_backup_tail = &(env->movcal_backup);
|
||||
sh4_translate_init();
|
||||
env->cpu_model_str = cpu_model;
|
||||
cpu_sh4_reset(env);
|
||||
|
@ -495,6 +497,37 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
|
|||
|
||||
static void _decode_opc(DisasContext * ctx)
|
||||
{
|
||||
/* This code tries to make movcal emulation sufficiently
|
||||
accurate for Linux purposes. This instruction writes
|
||||
memory, and prior to that, always allocates a cache line.
|
||||
It is used in two contexts:
|
||||
- in memcpy, where data is copied in blocks, the first write
|
||||
of to a block uses movca.l for performance.
|
||||
- in arch/sh/mm/cache-sh4.c, movcal.l + ocbi combination is used
|
||||
to flush the cache. Here, the data written by movcal.l is never
|
||||
written to memory, and the data written is just bogus.
|
||||
|
||||
To simulate this, we simulate movcal.l, we store the value to memory,
|
||||
but we also remember the previous content. If we see ocbi, we check
|
||||
if movcal.l for that address was done previously. If so, the write should
|
||||
not have hit the memory, so we restore the previous content.
|
||||
When we see an instruction that is neither movca.l
|
||||
nor ocbi, the previous content is discarded.
|
||||
|
||||
To optimize, we only try to flush stores when we're at the start of
|
||||
TB, or if we already saw movca.l in this TB and did not flush stores
|
||||
yet. */
|
||||
if (ctx->has_movcal)
|
||||
{
|
||||
int opcode = ctx->opcode & 0xf0ff;
|
||||
if (opcode != 0x0093 /* ocbi */
|
||||
&& opcode != 0x00c3 /* movca.l */)
|
||||
{
|
||||
gen_helper_discard_movcal_backup ();
|
||||
ctx->has_movcal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "Translating opcode 0x%04x\n", ctx->opcode);
|
||||
#endif
|
||||
|
@ -1545,7 +1578,13 @@ static void _decode_opc(DisasContext * ctx)
|
|||
}
|
||||
return;
|
||||
case 0x00c3: /* movca.l R0,@Rm */
|
||||
tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
|
||||
{
|
||||
TCGv val = tcg_temp_new();
|
||||
tcg_gen_qemu_ld32u(val, REG(B11_8), ctx->memidx);
|
||||
gen_helper_movcal (REG(B11_8), val);
|
||||
tcg_gen_qemu_st32(REG(0), REG(B11_8), ctx->memidx);
|
||||
}
|
||||
ctx->has_movcal = 1;
|
||||
return;
|
||||
case 0x40a9:
|
||||
/* MOVUA.L @Rm,R0 (Rm) -> R0
|
||||
|
@ -1594,9 +1633,7 @@ static void _decode_opc(DisasContext * ctx)
|
|||
break;
|
||||
case 0x0093: /* ocbi @Rn */
|
||||
{
|
||||
TCGv dummy = tcg_temp_new();
|
||||
tcg_gen_qemu_ld32s(dummy, REG(B11_8), ctx->memidx);
|
||||
tcg_temp_free(dummy);
|
||||
gen_helper_ocbi (REG(B11_8));
|
||||
}
|
||||
return;
|
||||
case 0x00a3: /* ocbp @Rn */
|
||||
|
@ -1876,6 +1913,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
|
|||
ctx.tb = tb;
|
||||
ctx.singlestep_enabled = env->singlestep_enabled;
|
||||
ctx.features = env->features;
|
||||
ctx.has_movcal = (tb->flags & TB_FLAG_PENDING_MOVCA);
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
qemu_log_mask(CPU_LOG_TB_CPU,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue