mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-06 03:18:41 +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)
|
ST_FUNC void gen_cvt_sxtw(void)
|
||||||
{
|
{
|
||||||
/* XXX on risc-v the registers are usually sign-extended already.
|
/* 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 ------------ */
|
/* ------------ riscv64-gen.c ------------ */
|
||||||
#ifdef TCC_TARGET_RISCV64
|
#ifdef TCC_TARGET_RISCV64
|
||||||
ST_FUNC void gen_opl(int op);
|
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 gen_va_start(void);
|
||||||
ST_FUNC void arch_transfer_ret_regs(int);
|
ST_FUNC void arch_transfer_ret_regs(int);
|
||||||
ST_FUNC void gen_cvt_sxtw(void);
|
ST_FUNC void gen_cvt_sxtw(void);
|
||||||
|
ST_FUNC void gen_cvt_csti(int t);
|
||||||
ST_FUNC void gen_increment_tcov (SValue *sv);
|
ST_FUNC void gen_increment_tcov (SValue *sv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
10
tccgen.c
10
tccgen.c
@ -3471,11 +3471,11 @@ error:
|
|||||||
|
|
||||||
if (ds >= ss)
|
if (ds >= ss)
|
||||||
goto done;
|
goto done;
|
||||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
|
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
|
||||||
if (ss == 4) {
|
if (ss == 4) {
|
||||||
gen_cvt_csti(dbt);
|
gen_cvt_csti(dbt);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bits = (ss - ds) * 8;
|
bits = (ss - ds) * 8;
|
||||||
/* for unsigned, gen_op will convert SAR to SHR */
|
/* 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