Release 6 requires misaligned memory access support for all ordinary memory access instructions (for example, LW/SW, LWC1/SWC1). However misaligned support is not provided for certain special memory accesses such as atomics (for example, LL/SC).
In the mips_cpu_do_unaligned_access() callback, if it is R6 core it checks further whether the address is valid. Signed-off-by: Yongbok Kim <yongbok....@imgtec.com> --- target-mips/cpu.h | 2 ++ target-mips/helper.c | 36 ++++++++++++++++++++++++++++++++++++ target-mips/op_helper.c | 13 +++++++++++++ target-mips/translate_init.c | 2 +- 4 files changed, 52 insertions(+), 1 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index f9d2b4c..6586d89 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -760,6 +760,8 @@ int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra); hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, int rw); +bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address, + target_ulong badvaddr, unsigned data_size, int rw); #endif target_ulong exception_resume_pc (CPUMIPSState *env); diff --git a/target-mips/helper.c b/target-mips/helper.c index 8e3204a..6c44124 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -391,6 +391,42 @@ hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, int r } } +bool cpu_mips_validate_access(CPUMIPSState *env, target_ulong address, + target_ulong badvaddr, unsigned data_size, int rw) +{ + hwaddr physical; + int prot; + int access_type = ACCESS_INT; + int ret; + target_ulong addr; + + addr = address & ~((target_ulong) data_size - 1); + ret = get_physical_address(env, &physical, &prot, + addr, rw, access_type); + if (ret != TLBRET_MATCH) { + if (ret != TLBRET_BADADDR && addr > badvaddr) { + badvaddr = addr; + } + raise_mmu_exception(env, badvaddr, rw, ret); + return false; + } + if ((data_size > 1) + && unlikely(((address & ~TARGET_PAGE_MASK) + data_size - 1) + >= TARGET_PAGE_SIZE)) { + addr += data_size; + ret = get_physical_address(env, &physical, &prot, addr, rw, + access_type); + if (ret != TLBRET_MATCH) { + if (ret != TLBRET_BADADDR) { + badvaddr = addr; + } + raise_mmu_exception(env, badvaddr, rw, ret); + return false; + } + } + return true; +} + static const char * const excp_names[EXCP_LAST + 1] = { [EXCP_RESET] = "reset", [EXCP_SRESET] = "soft reset", diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index ca5fe43..dacc92b 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2215,6 +2215,19 @@ void mips_cpu_do_unaligned_access(CPUState *cs, vaddr addr, int error_code = 0; int excp; + if (env->insn_flags & ISA_MIPS32R6) { + /* Release 6 provides support for misaligned memory access for + * all ordinary memory reference instructions + * */ + if (!cpu_mips_validate_access(env, addr, addr, size, access_type)) { + CPUState *cs = CPU(mips_env_get_cpu(env)); + do_raise_exception_err(env, cs->exception_index, + env->error_code, retaddr); + return; + } + return; + } + env->CP0_BadVAddr = addr; if (access_type == MMU_DATA_STORE) { diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 85a65e7..ec54fef 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -607,7 +607,7 @@ static const mips_def_t mips_defs[] = }, { /* A generic CPU supporting MIPS64 Release 6 ISA. - FIXME: Support IEEE 754-2008 FP and misaligned memory accesses. + FIXME: Support IEEE 754-2008 FP. Eventually this should be replaced by a real CPU model. */ .name = "MIPS64R6-generic", .CP0_PRid = 0x00010000, -- 1.7.5.4