target/riscv: Fix size of gpr and gprh
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. Note, the cpu/rv128 VMSTATE version is bumped, breaking migration from older versions. Signed-off-by: Anton Johansson <anjo@rev.ng> Acked-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Message-ID: <20260520125406.28693-2-anjo@rev.ng> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Anton Johansson committed
May 20, 2026 at 14:53 UTC
c4e6bc63853c7831737d41b7ff83333f8aa9fe52
5 files changed
+22
-10
target/riscv/cpu.c
+1
-1
@@ -612,7 +612,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
612
#endif
613
614
for (i = 0; i < 32; i++) {
615
- qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
615
+ qemu_fprintf(f, " %-8s %" PRIx64,
616
riscv_int_regnames[i], env->gpr[i]);
617
if ((i & 3) == 3) {
618
qemu_fprintf(f, "\n");
target/riscv/cpu.h
+2
-2
@@ -214,8 +214,8 @@ typedef struct PMUFixedCtrState {
214
} PMUFixedCtrState;
215
216
struct CPUArchState {
217
- target_ulong gpr[32];
218
- target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
217
+ uint64_t gpr[32];
218
+ uint64_t gprh[32]; /* 64 top bits of the 128-bit registers */
219
220
/* vector coprocessor state. */
221
uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16);
target/riscv/machine.c
+4
-4
@@ -178,11 +178,11 @@ static bool rv128_needed(void *opaque)
178
179
static const VMStateDescription vmstate_rv128 = {
180
.name = "cpu/rv128",
181
- .version_id = 1,
182
- .minimum_version_id = 1,
181
+ .version_id = 2,
182
+ .minimum_version_id = 2,
183
.needed = rv128_needed,
184
.fields = (const VMStateField[]) {
185
- VMSTATE_UINTTL_ARRAY(env.gprh, RISCVCPU, 32),
185
+ VMSTATE_UINT64_ARRAY(env.gprh, RISCVCPU, 32),
186
VMSTATE_UINT64(env.mscratchh, RISCVCPU),
187
VMSTATE_UINT64(env.sscratchh, RISCVCPU),
188
VMSTATE_END_OF_LIST()
@@ -449,7 +449,7 @@ const VMStateDescription vmstate_riscv_cpu = {
449
.minimum_version_id = 11,
450
.post_load = riscv_cpu_post_load,
451
.fields = (const VMStateField[]) {
452
- VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
452
+ VMSTATE_UINT64_ARRAY(env.gpr, RISCVCPU, 32),
453
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
454
VMSTATE_UINT8_ARRAY(env.miprio, RISCVCPU, 64),
455
VMSTATE_UINT8_ARRAY(env.siprio, RISCVCPU, 64),
target/riscv/monitor.c
+1
-1
@@ -248,7 +248,7 @@ static bool reg_is_ulong_integer(CPURISCVState *env, const char *name,
248
target_ulong *val, bool is_gprh)
249
{
250
const char * const *reg_names;
251
- target_ulong *vals;
251
+ uint64_t *vals;
252
253
if (is_gprh) {
254
reg_names = riscv_int_regnamesh;
target/riscv/translate.c
+14
-2
@@ -1469,12 +1469,24 @@ void riscv_translate_init(void)
1469
*/
1470
cpu_gpr[0] = NULL;
1471
cpu_gprh[0] = NULL;
1472
+ /*
1473
+ * Be careful with big endian hosts when mapping 64-bit CPUArchState fields
1474
+ * to 32-bit TCGv globals. An offset of 4 bytes is applied so the least
1475
+ * significant bytes are correctly written to.
1476
+ */
1477
+#if HOST_BIG_ENDIAN && !defined(TARGET_RISCV64)
1478
+ size_t field_offset = 4;
1479
+#else
1480
+ size_t field_offset = 0;
1481
+#endif
1482
1483
for (i = 1; i < 32; i++) {
1484
cpu_gpr[i] = tcg_global_mem_new(tcg_env,
1475
- offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
1485
+ offsetof(CPURISCVState, gpr[i]) + field_offset,
1486
+ riscv_int_regnames[i]);
1487
cpu_gprh[i] = tcg_global_mem_new(tcg_env,
1477
- offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
1488
+ offsetof(CPURISCVState, gprh[i]) + field_offset,
1489
+ riscv_int_regnamesh[i]);
1490
}
1491
1492
for (i = 0; i < 32; i++) {