History

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).

Meng Zhuo committed 6 months ago

Commit ff917c01 parent 9f0915a3 files · +49 −2Browse files

Unified · Split

3 files
  1. riscv64-gen.c +2 −2
  2. tests/tests2/140_int_sign_extension.c +43 −0
  3. tests/tests2/140_int_sign_extension.expect +4 −0
riscv64-gen.c+2−2
@@ -1268,8 +1268,8 @@ ST_FUNC void gen_cvt_csti(int t) · 1267 unmodified lines
1268 1268
1269ST_FUNC void gen_cvt_sxtw(void)1269ST_FUNC void gen_cvt_sxtw(void)
1270{1270{
1271 /* XXX on risc-v the registers are usually sign-extended already.1271 int r = ireg(gv(RC_INT));
1272 Let's try to not do anything here. */1272 EI(0x1b, 0, r, r, 0); // addiw r, r, 0
1273}1273}
1274 1274
1275ST_FUNC void gen_cvt_itof(int t)1275ST_FUNC void gen_cvt_itof(int t)
tests/tests2/140_int_sign_extension.c+43−0
@@ -0,0 +1,43 @@
1#include <stdio.h>
2
3/* gen_cvt_sxtw test: verify sign-extension from 32-bit int to 64-bit long long.
4 Without the fix, the riscv64 backend had an empty stub for gen_cvt_sxtw,
5 leaving upper 32 bits unmodified (containing whatever was in the register
6 before), so (long long)(int)x produced wrong results for negative values. */
7
8int main(void)
9{
10 int ok = 1;
11 int x = 0x80000000;
12 long long y = (long long)x;
13
14 printf("y=%llx\n", (unsigned long long)y);
15
16 if (y != 0xffffffff80000000LL) {
17 printf("FAIL: int→long long sign-extension\n");
18 ok = 0;
19 }
20
21 /* Also test positive value. */
22 x = 0x40000000;
23 y = (long long)x;
24 printf("y=%llx\n", (unsigned long long)y);
25
26 if (y != 0x40000000LL) {
27 printf("FAIL: int→long long positive value\n");
28 ok = 0;
29 }
30
31 /* Test via unsigned int to catch zero-extension vs sign-extension. */
32 unsigned int ux = 0x80000000;
33 long long uy = (long long)(int)ux;
34 printf("uy=%llx\n", (unsigned long long)uy);
35
36 if (uy != 0xffffffff80000000LL) {
37 printf("FAIL: unsigned→int→long long sign-extension\n");
38 ok = 0;
39 }
40
41 printf("%s\n", ok ? "PASS" : "FAIL");
42 return ok ? 0 : 1;
43}
tests/tests2/140_int_sign_extension.expect+4−0
@@ -0,0 +1,4 @@
1y=ffffffff80000000
2y=40000000
3uy=ffffffff80000000
4PASS

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t