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
12681268
12691269 ST_FUNC void gen_cvt_sxtw(void)
12701270 {
1271− /* XXX on risc-v the registers are usually sign-extended already.
1272− Let's try to not do anything here. */
1271+ int r = ireg(gv(RC_INT));
1272+ EI(0x1b, 0, r, r, 0); // addiw r, r, 0
12731273 }
12741274
12751275 ST_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+
8+int 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 @@
1+y=ffffffff80000000
2+y=40000000
3+uy=ffffffff80000000
4+PASS

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