diff --git a/riscv64-gen.c b/riscv64-gen.c index 8356f595..22789660 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -1268,8 +1268,8 @@ ST_FUNC void gen_cvt_csti(int t) ST_FUNC void gen_cvt_sxtw(void) { - /* XXX on risc-v the registers are usually sign-extended already. - Let's try to not do anything here. */ + int r = ireg(gv(RC_INT)); + EI(0x1b, 0, r, r, 0); // addiw r, r, 0 } ST_FUNC void gen_cvt_itof(int t) diff --git a/tests/tests2/140_int_sign_extension.c b/tests/tests2/140_int_sign_extension.c new file mode 100644 index 00000000..433a3e47 --- /dev/null +++ b/tests/tests2/140_int_sign_extension.c @@ -0,0 +1,43 @@ +#include + +/* gen_cvt_sxtw test: verify sign-extension from 32-bit int to 64-bit long long. + Without the fix, the riscv64 backend had an empty stub for gen_cvt_sxtw, + leaving upper 32 bits unmodified (containing whatever was in the register + before), so (long long)(int)x produced wrong results for negative values. */ + +int main(void) +{ + int ok = 1; + int x = 0x80000000; + long long y = (long long)x; + + printf("y=%llx\n", (unsigned long long)y); + + if (y != 0xffffffff80000000LL) { + printf("FAIL: int→long long sign-extension\n"); + ok = 0; + } + + /* Also test positive value. */ + x = 0x40000000; + y = (long long)x; + printf("y=%llx\n", (unsigned long long)y); + + if (y != 0x40000000LL) { + printf("FAIL: int→long long positive value\n"); + ok = 0; + } + + /* Test via unsigned int to catch zero-extension vs sign-extension. */ + unsigned int ux = 0x80000000; + long long uy = (long long)(int)ux; + printf("uy=%llx\n", (unsigned long long)uy); + + if (uy != 0xffffffff80000000LL) { + printf("FAIL: unsigned→int→long long sign-extension\n"); + ok = 0; + } + + printf("%s\n", ok ? "PASS" : "FAIL"); + return ok ? 0 : 1; +} diff --git a/tests/tests2/140_int_sign_extension.expect b/tests/tests2/140_int_sign_extension.expect new file mode 100644 index 00000000..72a5df87 --- /dev/null +++ b/tests/tests2/140_int_sign_extension.expect @@ -0,0 +1,4 @@ +y=ffffffff80000000 +y=40000000 +uy=ffffffff80000000 +PASS