target/ppc: Use probe_access for LMW, STMW
Use a minimum number of mmu lookups for the contiguous bytes that are accessed. If the lookup succeeds, we can finish the operation with host addresses only. Reported-by: Howard Spoelstra <hsp.cat7@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20200129235040.24022-3-richard.henderson@linaro.org> Tested-by: Howard Spoelstra <hsp.cat7@gmail.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
bb99b39189
commit
2ca2ef4994
@ -84,26 +84,45 @@ static void *probe_contiguous(CPUPPCState *env, target_ulong addr, uint32_t nb,
|
|||||||
|
|
||||||
void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
|
void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
|
||||||
{
|
{
|
||||||
for (; reg < 32; reg++) {
|
uintptr_t raddr = GETPC();
|
||||||
if (needs_byteswap(env)) {
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC()));
|
void *host = probe_contiguous(env, addr, (32 - reg) * 4,
|
||||||
} else {
|
MMU_DATA_LOAD, mmu_idx, raddr);
|
||||||
env->gpr[reg] = cpu_ldl_data_ra(env, addr, GETPC());
|
|
||||||
|
if (likely(host)) {
|
||||||
|
/* Fast path -- the entire operation is in RAM at host. */
|
||||||
|
for (; reg < 32; reg++) {
|
||||||
|
env->gpr[reg] = (uint32_t)ldl_be_p(host);
|
||||||
|
host += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Slow path -- at least some of the operation requires i/o. */
|
||||||
|
for (; reg < 32; reg++) {
|
||||||
|
env->gpr[reg] = cpu_ldl_mmuidx_ra(env, addr, mmu_idx, raddr);
|
||||||
|
addr = addr_add(env, addr, 4);
|
||||||
}
|
}
|
||||||
addr = addr_add(env, addr, 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
|
void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
|
||||||
{
|
{
|
||||||
for (; reg < 32; reg++) {
|
uintptr_t raddr = GETPC();
|
||||||
if (needs_byteswap(env)) {
|
int mmu_idx = cpu_mmu_index(env, false);
|
||||||
cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]),
|
void *host = probe_contiguous(env, addr, (32 - reg) * 4,
|
||||||
GETPC());
|
MMU_DATA_STORE, mmu_idx, raddr);
|
||||||
} else {
|
|
||||||
cpu_stl_data_ra(env, addr, (uint32_t)env->gpr[reg], GETPC());
|
if (likely(host)) {
|
||||||
|
/* Fast path -- the entire operation is in RAM at host. */
|
||||||
|
for (; reg < 32; reg++) {
|
||||||
|
stl_be_p(host, env->gpr[reg]);
|
||||||
|
host += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Slow path -- at least some of the operation requires i/o. */
|
||||||
|
for (; reg < 32; reg++) {
|
||||||
|
cpu_stl_mmuidx_ra(env, addr, env->gpr[reg], mmu_idx, raddr);
|
||||||
|
addr = addr_add(env, addr, 4);
|
||||||
}
|
}
|
||||||
addr = addr_add(env, addr, 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user