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 <anjo@rev.ng>
---
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