From: Matheus Tavares Bernardino <[email protected]>
Will be used for semihosting. Reviewed-by: Pierrick Bouvier <[email protected]> Signed-off-by: Matheus Tavares Bernardino <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/cpu_helper.h | 6 +++ target/hexagon/cpu_helper.c | 100 ++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h index d1767503156..ca2e13ab1d1 100644 --- a/target/hexagon/cpu_helper.h +++ b/target/hexagon/cpu_helper.h @@ -7,6 +7,12 @@ #ifndef HEXAGON_CPU_HELPER_H #define HEXAGON_CPU_HELPER_H +void hexagon_read_memory(CPUHexagonState *env, target_ulong vaddr, int size, + void *retptr, uintptr_t retaddr); +void hexagon_write_memory(CPUHexagonState *env, target_ulong vaddr, + int size, uint64_t data, uintptr_t retaddr); +void hexagon_peek_memory_range(CPUHexagonState *env, uint32_t start_addr, + uint32_t length, uintptr_t retaddr); uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index); void hexagon_modify_ssr(CPUHexagonState *env, uint32_t new, uint32_t old); int get_cpu_mode(CPUHexagonState *env); diff --git a/target/hexagon/cpu_helper.c b/target/hexagon/cpu_helper.c index 64c5746c6d9..fab9a9d7b12 100644 --- a/target/hexagon/cpu_helper.c +++ b/target/hexagon/cpu_helper.c @@ -25,6 +25,106 @@ #include "sys_macros.h" #include "arch.h" +#ifndef CONFIG_USER_ONLY + +static bool hexagon_read_memory_small(CPUHexagonState *env, target_ulong addr, + int byte_count, uint64_t *data, + int mmu_idx, uintptr_t retaddr) + { + /* handle small sizes */ + switch (byte_count) { + case 1: + *data = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, retaddr); + return true; + + case 2: + *data = cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, retaddr); + return true; + + case 4: + *data = cpu_ldl_le_mmuidx_ra(env, addr, mmu_idx, retaddr); + return true; + + case 8: + *data = cpu_ldq_le_mmuidx_ra(env, addr, mmu_idx, retaddr); + return true; + + default: + /* larger request, handle elsewhere */ + return false; + } +} + +void hexagon_read_memory(CPUHexagonState *env, target_ulong vaddr, int size, + void *retptr, uintptr_t retaddr) +{ + BQL_LOCK_GUARD(); + CPUState *cs = env_cpu(env); + unsigned mmu_idx = cpu_mmu_index(cs, false); + uint64_t data; + if (hexagon_read_memory_small(env, vaddr, size, &data, mmu_idx, retaddr)) { + stn_he_p(retptr, size, data); + } else { + cpu_abort(cs, "%s: ERROR: bad size = %d!\n", __func__, size); + } +} + +static bool hexagon_write_memory_small(CPUHexagonState *env, target_ulong addr, + int byte_count, uint64_t data, + int mmu_idx, uintptr_t retaddr) +{ + /* handle small sizes */ + switch (byte_count) { + case 1: + cpu_stb_mmuidx_ra(env, addr, (uint8_t)data, mmu_idx, retaddr); + return true; + + case 2: + cpu_stw_le_mmuidx_ra(env, addr, (uint16_t)data, mmu_idx, retaddr); + return true; + + case 4: + cpu_stl_le_mmuidx_ra(env, addr, (uint32_t)data, mmu_idx, retaddr); + return true; + + case 8: + cpu_stq_le_mmuidx_ra(env, addr, (uint64_t)data, mmu_idx, retaddr); + return true; + + default: + /* larger request, handle elsewhere */ + return false; + } +} + +void hexagon_write_memory(CPUHexagonState *env, target_ulong vaddr, + int size, uint64_t data, uintptr_t retaddr) +{ + CPUState *cs = env_cpu(env); + unsigned mmu_idx = cpu_mmu_index(cs, false); + if (!hexagon_write_memory_small(env, vaddr, size, data, mmu_idx, retaddr)) { + cpu_abort(cs, "%s: ERROR: bad size = %d!\n", __func__, size); + } +} + +static inline uint32_t page_start(uint32_t addr) +{ + uint32_t page_align = ~(TARGET_PAGE_SIZE - 1); + return addr & page_align; +} + +void hexagon_peek_memory_range(CPUHexagonState *env, uint32_t start_addr, + uint32_t length, uintptr_t retaddr) +{ + unsigned int warm; + uint32_t first = page_start(start_addr); + uint32_t last = page_start(start_addr + length - 1); + for (uint32_t page = first; page <= last; page += TARGET_PAGE_SIZE) { + hexagon_read_memory(env, page, 1, &warm, retaddr); + } +} + +#endif uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index) { -- 2.34.1
