mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
riscv64: implement gen_cvt_csti for narrow int promotion
Add sign/zero extension for char/short to int casts using slli+srai (signed) or slli+srli/andi (unsigned) sequences. Also adds RISCV64 to the gen_cvt_csti fast-path conditional in tccgen.c:3466, matching arm64/i386/x86_64. Verified on Spacemit X100: all tests2 pass, no regressions.
This commit is contained in:
parent
69c8e92566
commit
9f0915a506
@ -1245,6 +1245,27 @@ ST_FUNC void gen_opf(int op)
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_cvt_csti(int t)
|
||||
{
|
||||
int r = ireg(gv(RC_INT));
|
||||
if ((t & VT_BTYPE) == VT_SHORT) {
|
||||
if (t & VT_UNSIGNED) {
|
||||
EI(0x13, 1, r, r, 48); // slli r, r, 48
|
||||
EI(0x13, 5, r, r, 48); // srli r, r, 48
|
||||
} else {
|
||||
EI(0x13, 1, r, r, 48); // slli r, r, 48
|
||||
EIu(0x13, 5, r, r, 0x400 | 48); // srai r, r, 48
|
||||
}
|
||||
} else {
|
||||
if (t & VT_UNSIGNED) {
|
||||
EI(0x13, 7, r, r, 0xff); // andi r, r, 0xff
|
||||
} else {
|
||||
EI(0x13, 1, r, r, 56); // slli r, r, 56
|
||||
EIu(0x13, 5, r, r, 0x400 | 56); // srai r, r, 56
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ST_FUNC void gen_cvt_sxtw(void)
|
||||
{
|
||||
/* XXX on risc-v the registers are usually sign-extended already.
|
||||
|
||||
2
tcc.h
2
tcc.h
@ -1725,10 +1725,10 @@ ST_FUNC void gen_increment_tcov (SValue *sv);
|
||||
/* ------------ riscv64-gen.c ------------ */
|
||||
#ifdef TCC_TARGET_RISCV64
|
||||
ST_FUNC void gen_opl(int op);
|
||||
//ST_FUNC void gfunc_return(CType *func_type);
|
||||
ST_FUNC void gen_va_start(void);
|
||||
ST_FUNC void arch_transfer_ret_regs(int);
|
||||
ST_FUNC void gen_cvt_sxtw(void);
|
||||
ST_FUNC void gen_cvt_csti(int t);
|
||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
||||
#endif
|
||||
|
||||
|
||||
10
tccgen.c
10
tccgen.c
@ -3471,11 +3471,11 @@ error:
|
||||
|
||||
if (ds >= ss)
|
||||
goto done;
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
|
||||
if (ss == 4) {
|
||||
gen_cvt_csti(dbt);
|
||||
goto done;
|
||||
}
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
|
||||
if (ss == 4) {
|
||||
gen_cvt_csti(dbt);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
bits = (ss - ds) * 8;
|
||||
/* for unsigned, gen_op will convert SAR to SHR */
|
||||
|
||||
42
tests/tests2/139_narrow_type_conversion.c
Normal file
42
tests/tests2/139_narrow_type_conversion.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* gen_cvt_csti test: verify narrow-type conversions in expressions.
|
||||
Without the fix, TCC's riscv64 backend could miss the conversion
|
||||
step when promoting a narrow result back to int, producing wrong
|
||||
values (e.g., treating a char as still 32-bit). */
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ok = 1;
|
||||
int x = 0x12345678;
|
||||
|
||||
/* Cast to char then add 1 — result must be 8-bit. */
|
||||
char c = (char)x + 1;
|
||||
unsigned char uc = (unsigned char)x + 1;
|
||||
short s = (short)x + 1;
|
||||
unsigned short us = (unsigned short)x + 1;
|
||||
|
||||
printf("c=%x uc=%x s=%x us=%x\n",
|
||||
(unsigned char)c, (unsigned)uc,
|
||||
(unsigned short)s, (unsigned)us);
|
||||
|
||||
if (c != (char)0x78 + 1) {
|
||||
printf("FAIL: char conversion\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (uc != (unsigned char)0x78 + 1) {
|
||||
printf("FAIL: unsigned char conversion\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (s != (short)0x5678 + 1) {
|
||||
printf("FAIL: short conversion\n");
|
||||
ok = 0;
|
||||
}
|
||||
if (us != (unsigned short)0x5678 + 1) {
|
||||
printf("FAIL: unsigned short conversion\n");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
printf("%s\n", ok ? "PASS" : "FAIL");
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
2
tests/tests2/139_narrow_type_conversion.expect
Normal file
2
tests/tests2/139_narrow_type_conversion.expect
Normal file
@ -0,0 +1,2 @@
|
||||
c=79 uc=79 s=5679 us=5679
|
||||
PASS
|
||||
Loading…
Reference in New Issue
Block a user