RISC-V: incorrect emulation of load and store on big-endian systems
For TCG emulation of load and store operations where the endianness of host and target differ, byte swapping is needed. This is controlled by passing the flag MO_TE to the code generating functions.
Unfortunately this has only incompletely observed when implementing new extensions for the RISC-V ISA. Here is just one example. There is a long and a compressed form of the lhu opcode. While the long form implementation of lhu correctly passes MO_TE via usage of MO_TEUW the implementation of c.lhu does not:
static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
{
return gen_load(ctx, a, MO_TEUW);
}
static bool trans_c_lhu(DisasContext *ctx, arg_c_lhu *a)
{
REQUIRE_ZCB(ctx);
return gen_load(ctx, a, MO_UW);
}
As reported in Launchpad issue https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/2123828 this leads to failures when emulating RISC-V on a big endian platform like IBM System/390 (s390x).
c.lhu is just an example of this problem. At least the following includes are affected:
- target/riscv/insn_trans/trans_rvi.c.inc
- target/riscv/insn_trans/trans_rvzce.c.inc
- target/riscv/insn_trans/trans_xthead.c.inc
- target/riscv/insn_trans/trans_rvzabha.c.inc
Best regards
Heinrich
Host environment
- Operating system: Ubuntu 25.10
- Architecture: s390x
- QEMU flavor: qemu-riscv64
- QEMU version: 9.2, 10.1
- QEMU command line: qemu-riscv64 hello
Emulated/Virtualized environment
- Operating system: Ubuntu 25.10
- Architecture: riscv64
Minimal reproducer:
$ sudo apt update && sudo apt install qemu-user
$ dpkg -l | grep libc6
ii libc6:s390x 2.42-0ubuntu3
$ dpkg -l | grep qemu-user
ii qemu-user 1:10.1.0+ds-5ubuntu1
$ dpkg --print-architecture
s390x
$ sudo dpkg --add-architecture riscv64
$ sudo apt update
$ sudo apt install hello:riscv64
$ /usr/bin/qemu-riscv64 /usr/bin/hello
/usr/bin/hello: /lib/ld-linux-riscv64-lp64d.so.1: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/riscv64-linux-gnu/libc.so.6: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/riscv64-linux-gnu/libc.so.6: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/riscv64-linux-gnu/libc.so.6: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/ld-linux-riscv64-lp64d.so.1: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/ld-linux-riscv64-lp64d.so.1: unsupported version 256 of Verdef record
/usr/bin/hello: /lib/ld-linux-riscv64-lp64d.so.1: unsupported version 256 of Verdef record