mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-03 09:58:41 +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)
|
ST_FUNC void gen_cvt_sxtw(void)
|
||||||
{
|
{
|
||||||
/* XXX on risc-v the registers are usually sign-extended already.
|
int r = ireg(gv(RC_INT));
|
||||||
Let's try to not do anything here. */
|
EI(0x1b, 0, r, r, 0); // addiw r, r, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
ST_FUNC void gen_cvt_itof(int t)
|
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