Commit 2ca2ef49 authored by Richard Henderson's avatar Richard Henderson Committed by David Gibson
Browse files

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: default avatarHoward Spoelstra <hsp.cat7@gmail.com>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-Id: <20200129235040.24022-3-richard.henderson@linaro.org>
Tested-by: default avatarHoward Spoelstra <hsp.cat7@gmail.com>
Signed-off-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
parent bb99b391
Loading
Loading
Loading
Loading
+32 −13
Original line number Diff line number Diff line
@@ -84,28 +84,47 @@ static void *probe_contiguous(CPUPPCState *env, target_ulong addr, uint32_t nb,

void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
    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++) {
        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());
            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);
        }
    }
}

void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
    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++) {
        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());
            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);
        }
    }
}

static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
                   uint32_t reg, uintptr_t raddr)