On 7/13/2026 1:07 PM, Matheus Tavares Bernardino wrote:
> From: Matheus Tavares Bernardino <[email protected]>
>
> Will be used for semihosting.
>
> 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 | 133 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 139 insertions(+)
>
> diff --git a/target/hexagon/cpu_helper.h b/target/hexagon/cpu_helper.h
> index d1767503156..f6a31ecbab0 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_touch_memory(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..1ab2564e3dc 100644
> --- a/target/hexagon/cpu_helper.c
> +++ b/target/hexagon/cpu_helper.c
> @@ -25,6 +25,139 @@
> #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, unsigned char *dstbuf,
> + int mmu_idx, uintptr_t retaddr)
> + {
> + /* handle small sizes */
> + switch (byte_count) {
> + case 1:
> + *dstbuf = cpu_ldub_mmuidx_ra(env, addr, mmu_idx, retaddr);
> + return true;
> +
> + case 2:
> + if (QEMU_IS_ALIGNED(addr, 2)) {
> + *(unsigned short *)dstbuf =
> + cpu_lduw_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
> + return true;
> + }
> + break;
> +
> + case 4:
> + if (QEMU_IS_ALIGNED(addr, 4)) {
> + *(uint32_t *)dstbuf =
> + cpu_ldl_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
> + return true;
> + }
> + break;
> +
> + case 8:
> + if (QEMU_IS_ALIGNED(addr, 8)) {
> + *(uint64_t *)dstbuf =
> + cpu_ldq_le_mmuidx_ra(env, addr, mmu_idx, retaddr);
> + return true;
> + }
> + break;
> +
> + default:
> + /* larger request, handle elsewhere */
> + return false;
> + }
> +
> + /* not aligned, copy bytes */
> + for (int i = 0; i < byte_count; ++i) {
> + *dstbuf++ = cpu_ldub_mmuidx_ra(env, addr++, mmu_idx, retaddr);
> + }
> + return true;
> +}
> +
> +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);
> + if (!hexagon_read_memory_small(env, vaddr, size, retptr, mmu_idx,
> + retaddr)) {
> + 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, unsigned char *srcbuf,
> + int mmu_idx, uintptr_t retaddr)
> +{
> + /* handle small sizes */
> + switch (byte_count) {
> + case 1:
> + cpu_stb_mmuidx_ra(env, addr, *srcbuf, mmu_idx, retaddr);
> + return true;
> +
> + case 2:
> + if (QEMU_IS_ALIGNED(addr, 2)) {
> + cpu_stw_le_mmuidx_ra(env, addr, *(uint16_t *)srcbuf, mmu_idx,
> retaddr);
> + return true;
> + }
> + break;
> +
> + case 4:
> + if (QEMU_IS_ALIGNED(addr, 4)) {
> + cpu_stl_le_mmuidx_ra(env, addr, *(uint32_t *)srcbuf, mmu_idx,
> retaddr);
> + return true;
> + }
> + break;
> +
> + case 8:
> + if (QEMU_IS_ALIGNED(addr, 8)) {
> + cpu_stq_le_mmuidx_ra(env, addr, *(uint64_t *)srcbuf, mmu_idx,
> retaddr);
> + return true;
> + }
> + break;
> +
> + default:
> + /* larger request, handle elsewhere */
> + return false;
> + }
> +
> + /* not aligned, copy bytes */
> + for (int i = 0; i < byte_count; ++i) {
> + cpu_stb_mmuidx_ra(env, addr++, *srcbuf++, mmu_idx, retaddr);
> + }
> +
> + return true;
> +}
> +
> +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, (unsigned char *)&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_touch_memory(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);
> + }
> +}
> +
Name could be misleading, I would be expectng to see a read/write
sequence in each page instead of just reading.
Maybe hexagon_peek_memory_range?
> +#endif
>
> uint32_t hexagon_get_pmu_counter(CPUHexagonState *cur_env, int index)
> {
Reviewed-by: Pierrick Bouvier <[email protected]>
Regards,
Pierrick