gprh is only needed for TARGET_RISCV64 when modeling 128-bit registers, fixing their size to 64 bits makes sense.
gpr is also fixed to 64 bits since all direct uses of env->gpr correctly zero extend/truncate to/from target_ulong, meaning !TARGET_RISCV64 will behave as expected. We do however need to be a bit careful when mapping 64-bit fields to 32-bit TCGv globals on big endian hosts. Signed-off-by: Anton Johansson <[email protected]> --- target/riscv/cpu.h | 4 ++-- target/riscv/cpu.c | 2 +- target/riscv/machine.c | 4 ++-- target/riscv/translate.c | 17 +++++++++++++++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b0d6e74ea3..2cd69fa150 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -212,8 +212,8 @@ typedef struct PMUFixedCtrState { } PMUFixedCtrState; struct CPUArchState { - target_ulong gpr[32]; - target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */ + uint64_t gpr[32]; + uint64_t gprh[32]; /* 64 top bits of the 128-bit registers */ /* vector coprocessor state. */ uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d055ddf462..3c910e44cd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -584,7 +584,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) for (i = 0; i < 32; i++) { qemu_fprintf(f, " %-8s " TARGET_FMT_lx, - riscv_int_regnames[i], env->gpr[i]); + riscv_int_regnames[i], (target_ulong) env->gpr[i]); if ((i & 3) == 3) { qemu_fprintf(f, "\n"); } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 7b00cb4804..9a14a805ef 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -180,7 +180,7 @@ static const VMStateDescription vmstate_rv128 = { .minimum_version_id = 1, .needed = rv128_needed, .fields = (const VMStateField[]) { - VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32), + VMSTATE_UINT64_ARRAY(env.gprh, RISCVCPU, 32), VMSTATE_UINT64(env.mscratchh, RISCVCPU), VMSTATE_UINT64(env.sscratchh, RISCVCPU), VMSTATE_END_OF_LIST() @@ -404,7 +404,7 @@ const VMStateDescription vmstate_riscv_cpu = { .minimum_version_id = 10, .post_load = riscv_cpu_post_load, .fields = (const VMStateField[]) { - VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), + VMSTATE_UINT64_ARRAY(env.gpr, RISCVCPU, 32), VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64), VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64), diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 9ddef2d6e2..2f8c7a6465 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -26,6 +26,7 @@ #include "exec/translator.h" #include "exec/translation-block.h" #include "exec/log.h" +#include "exec/tswap.h" #include "semihosting/semihost.h" #include "internals.h" @@ -1427,12 +1428,24 @@ void riscv_translate_init(void) */ cpu_gpr[0] = NULL; cpu_gprh[0] = NULL; + /* + * Be careful with big endian hosts when mapping 64-bit CPUArchState fields + * to 32-bit TCGv globals. An offset of 4 bytes is applied so the least + * significant bytes are correctly written to. + */ +#if HOST_BIG_ENDIAN && !defined(TARGET_RISCV64) + size_t field_offset = 4; +#else + size_t field_offset = 0; +#endif for (i = 1; i < 32; i++) { cpu_gpr[i] = tcg_global_mem_new(tcg_env, - offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]); + offsetof(CPURISCVState, gpr[i]) + field_offset, + riscv_int_regnames[i]); cpu_gprh[i] = tcg_global_mem_new(tcg_env, - offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]); + offsetof(CPURISCVState, gprh[i]) + field_offset, + riscv_int_regnamesh[i]); } for (i = 0; i < 32; i++) { -- 2.51.0
