Use helpers and address_space_ld/st instead of inline loads and stores. This allows us to perform operations on physical addresses wider than virtual addresses.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/microblaze/helper.h | 16 ++++-- target/microblaze/op_helper.c | 99 +++++++++++++++++++++++++++++++++++ target/microblaze/translate.c | 42 ++++++++++----- 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/target/microblaze/helper.h b/target/microblaze/helper.h index f740835fcb..f3ef5a3150 100644 --- a/target/microblaze/helper.h +++ b/target/microblaze/helper.h @@ -20,12 +20,18 @@ DEF_HELPER_FLAGS_3(fcmp_ne, TCG_CALL_NO_WG, i32, env, i32, i32) DEF_HELPER_FLAGS_3(fcmp_ge, TCG_CALL_NO_WG, i32, env, i32, i32) DEF_HELPER_FLAGS_2(pcmpbf, TCG_CALL_NO_RWG_SE, i32, i32, i32) -#if !defined(CONFIG_USER_ONLY) -DEF_HELPER_FLAGS_3(mmu_read, TCG_CALL_NO_RWG, i32, env, i32, i32) -DEF_HELPER_FLAGS_4(mmu_write, TCG_CALL_NO_RWG, void, env, i32, i32, i32) -#endif - DEF_HELPER_FLAGS_2(stackprot, TCG_CALL_NO_WG, void, env, tl) DEF_HELPER_FLAGS_2(get, TCG_CALL_NO_RWG, i32, i32, i32) DEF_HELPER_FLAGS_3(put, TCG_CALL_NO_RWG, void, i32, i32, i32) + +#if !defined(CONFIG_USER_ONLY) +DEF_HELPER_FLAGS_3(mmu_read, TCG_CALL_NO_RWG, i32, env, i32, i32) +DEF_HELPER_FLAGS_4(mmu_write, TCG_CALL_NO_RWG, void, env, i32, i32, i32) +DEF_HELPER_FLAGS_2(lbuea, TCG_CALL_NO_WG, i32, env, i64) +DEF_HELPER_FLAGS_2(lhuea, TCG_CALL_NO_WG, i32, env, i64) +DEF_HELPER_FLAGS_2(lwea, TCG_CALL_NO_WG, i32, env, i64) +DEF_HELPER_FLAGS_3(sbea, TCG_CALL_NO_WG, void, env, i32, i64) +DEF_HELPER_FLAGS_3(shea, TCG_CALL_NO_WG, void, env, i32, i64) +DEF_HELPER_FLAGS_3(swea, TCG_CALL_NO_WG, void, env, i32, i64) +#endif diff --git a/target/microblaze/op_helper.c b/target/microblaze/op_helper.c index 6019c5b2eb..722810cb9c 100644 --- a/target/microblaze/op_helper.c +++ b/target/microblaze/op_helper.c @@ -25,6 +25,7 @@ #include "qemu/host-utils.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "exec/memory.h" #include "fpu/softfloat.h" void helper_put(uint32_t id, uint32_t ctrl, uint32_t data) @@ -442,4 +443,102 @@ void mb_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr, mb_transaction_failed_internal(cs, physaddr, addr, size, access_type, retaddr); } + +uint32_t HELPER(lbuea)(CPUMBState *env, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + uint8_t ret; + + ret = address_space_ldub(cs->as, ea, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 1, MMU_DATA_LOAD, ra); + } + return ret; +} + +uint32_t HELPER(lhuea)(CPUMBState *env, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + uint16_t ret; + + if (unlikely(ea & 1) + && (env->msr & MSR_EE) + && env_archcpu(env)->cfg.unaligned_exceptions) { + mb_unaligned_access_internal(cs, ea, MMU_DATA_LOAD, ra); + } + ret = address_space_lduw(cs->as, ea, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 2, MMU_DATA_LOAD, ra); + } + return ret; +} + +uint32_t HELPER(lwea)(CPUMBState *env, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + uint32_t ret; + + if (unlikely(ea & 3) + && (env->msr & MSR_EE) + && env_archcpu(env)->cfg.unaligned_exceptions) { + mb_unaligned_access_internal(cs, ea, MMU_DATA_LOAD, ra); + } + ret = address_space_ldl(cs->as, ea, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 4, MMU_DATA_LOAD, ra); + } + return ret; +} + +void HELPER(sbea)(CPUMBState *env, uint32_t data, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + + address_space_stb(cs->as, ea, data, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 1, MMU_DATA_STORE, ra); + } +} + +void HELPER(shea)(CPUMBState *env, uint32_t data, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + + if (unlikely(ea & 1) + && (env->msr & MSR_EE) + && env_archcpu(env)->cfg.unaligned_exceptions) { + mb_unaligned_access_internal(cs, ea, MMU_DATA_STORE, ra); + } + address_space_stw(cs->as, ea, data, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 2, MMU_DATA_STORE, ra); + } +} + +void HELPER(swea)(CPUMBState *env, uint32_t data, uint64_t ea) +{ + CPUState *cs = env_cpu(env); + uintptr_t ra = GETPC(); + MemTxResult txres; + + if (unlikely(ea & 3) + && (env->msr & MSR_EE) + && env_archcpu(env)->cfg.unaligned_exceptions) { + mb_unaligned_access_internal(cs, ea, MMU_DATA_STORE, ra); + } + address_space_stl(cs->as, ea, data, MEMTXATTRS_UNSPECIFIED, &txres); + if (unlikely(txres != MEMTX_OK)) { + mb_transaction_failed_internal(cs, ea, ea, 4, MMU_DATA_STORE, ra); + } +} #endif diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 24005f05b2..d5c5e650e0 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -764,10 +764,11 @@ static bool trans_lbuea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_load(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); + gen_helper_lbuea(reg_for_write(dc, arg->rd), tcg_env, addr); + return true; #endif } @@ -795,10 +796,14 @@ static bool trans_lhuea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false); + if ((dc->tb_flags & MSR_EE) && dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, arg->rd, MO_16, false); + } + gen_helper_lhuea(reg_for_write(dc, arg->rd), tcg_env, addr); + return true; #endif } @@ -826,10 +831,14 @@ static bool trans_lwea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false); + if ((dc->tb_flags & MSR_EE) && dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, arg->rd, MO_32, false); + } + gen_helper_lwea(reg_for_write(dc, arg->rd), tcg_env, addr); + return true; #endif } @@ -914,10 +923,11 @@ static bool trans_sbea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_store(dc, arg->rd, addr, MO_UB, MMU_NOMMU_IDX, false); + gen_helper_sbea(tcg_env, reg_for_read(dc, arg->rd), addr); + return true; #endif } @@ -945,10 +955,14 @@ static bool trans_shea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false); + if ((dc->tb_flags & MSR_EE) && dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, arg->rd, MO_16, true); + } + gen_helper_shea(tcg_env, reg_for_read(dc, arg->rd), addr); + return true; #endif } @@ -976,10 +990,14 @@ static bool trans_swea(DisasContext *dc, arg_typea *arg) return true; } #ifdef CONFIG_USER_ONLY - return true; + g_assert_not_reached(); #else TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb); - return do_store(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false); + if ((dc->tb_flags & MSR_EE) && dc->cfg->unaligned_exceptions) { + record_unaligned_ess(dc, arg->rd, MO_32, true); + } + gen_helper_swea(tcg_env, reg_for_read(dc, arg->rd), addr); + return true; #endif } -- 2.43.0