mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
riscv64: implement gen_cvt_sxtw with addiw instruction
Replaces the empty stub that relied on 'RV64 registers are always sign-extended' assumption. Now emits addiw rd, rs, 0 for proper 32-to-64 bit sign extension, matching arm64's sxtw behavior. Verified on Spacemit X100: tests2 pass (125_atomic_misc has a pre-existing intermittent segfault, not caused by this change).
This commit is contained in:
parent
9f0915a506
commit
ff917c09aa
@ -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)
|
||||
|
||||
43
tests/tests2/140_int_sign_extension.c
Normal file
43
tests/tests2/140_int_sign_extension.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
4
tests/tests2/140_int_sign_extension.expect
Normal file
4
tests/tests2/140_int_sign_extension.expect
Normal file
@ -0,0 +1,4 @@
|
||||
y=ffffffff80000000
|
||||
y=40000000
|
||||
uy=ffffffff80000000
|
||||
PASS
|
||||
Loading…
Reference in New Issue
Block a user