aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-01-29 15:50:38 -0800
committerDavid Gibson <david@gibson.dropbear.id.au>2020-02-03 11:33:11 +1100
commit2ca2ef49940de375696074f36c977af9fd414e25 (patch)
tree268edd6127aa6c625db7ea732a53b96a440399f7
parentbb99b391896f3c7a477777e3d47a2524fd795357 (diff)
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>
-rw-r--r--target/ppc/mem_helper.c45
1 files changed, 32 insertions, 13 deletions
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
index 508d472a2f..e7d3a79d96 100644
--- a/target/ppc/mem_helper.c
+++ b/target/ppc/mem_helper.c
@@ -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)
{
- for (; reg < 32; reg++) {
- if (needs_byteswap(env)) {
- env->gpr[reg] = bswap32(cpu_ldl_data_ra(env, addr, GETPC()));
- } else {
- env->gpr[reg] = cpu_ldl_data_ra(env, addr, GETPC());
+ uintptr_t raddr = GETPC();
+ int mmu_idx = cpu_mmu_index(env, false);
+ void *host = probe_contiguous(env, addr, (32 - reg) * 4,
+ MMU_DATA_LOAD, mmu_idx, raddr);
+
+ 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)
{
- for (; reg < 32; reg++) {
- if (needs_byteswap(env)) {
- cpu_stl_data_ra(env, addr, bswap32((uint32_t)env->gpr[reg]),
- GETPC());
- } else {
- cpu_stl_data_ra(env, addr, (uint32_t)env->gpr[reg], GETPC());
+ uintptr_t raddr = GETPC();
+ int mmu_idx = cpu_mmu_index(env, false);
+ void *host = probe_contiguous(env, addr, (32 - reg) * 4,
+ MMU_DATA_STORE, mmu_idx, raddr);
+
+ 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);
}
}