tcctest: restore & combine

Revert 199369bb17
- generating test.ref with tcc makes little sense.
- combine riscv_asm & conversion tests into only two files.
  (too many files are bad ...)
This commit is contained in:
grischka 2026-05-06 10:26:41 +02:00
parent 6daf1617ef
commit 44977b0de8
28 changed files with 510 additions and 570 deletions

View File

@ -336,7 +336,7 @@ FORCE:
# some versions of gnu-make do not recognize 'command' as a shell builtin
WHICH = sh -c 'command -v $1'
run-if = $(if $(shell $(call WHICH,$1)),$S $1 $2,@echo "(skipping $@ - no $1)")
run-if = $(if $(shell $(call WHICH,$1x)),$S $1 $2,@true||echo "(skipping $@ - no $1)")
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
# --------------------------------------------------------------------------

View File

@ -114,7 +114,7 @@ ST_FUNC void tccelf_new(TCCState *s)
#ifndef ELF_OBJ_ONLY
if (NULL == s->elfint && s1->output_type != TCC_OUTPUT_OBJ) {
const char *p = CONFIG_TCC_ELFINTERP;
#ifdef TCC_TARGET_ARM
#if defined TCC_TARGET_ARM && defined CONFIG_TCC_ELFINTERP_ARMHF
if (s->float_abi == ARM_HARD_FLOAT)
p = CONFIG_TCC_ELFINTERP_ARMHF;
#endif

View File

@ -110,8 +110,8 @@ libtcc_test_mt$(EXESUF): libtcc_test_mt.c
# test.ref - generate using cc
test.ref: tcctest.c
$(TCC) $(TCCFLAGS) -w -o tcctest.tcc$(EXESUF) $<
./tcctest.tcc$(EXESUF) > $@
$(CC) -o tcctest.gcc$(EXESUF) $< $(CFLAGS) -w -O0 -std=gnu99 -fno-omit-frame-pointer
./tcctest.gcc$(EXESUF) > $@
# auto test
test1 test1b: tcctest.c test.ref

View File

@ -1175,7 +1175,7 @@ void char_short_test()
var4 = 0x11223344aa998877ULL;
printf("promote char/short assign VA %d %d\n", var3 = var1 + 1, var3 = var4 + 1);
printf("promote char/short cast VA %d %d\n", (signed char)(var1 + 1), (signed char)(var4 + 1));
#if !defined(__arm__)
#if !defined __arm__ && !defined __riscv
/* We can't really express GCC behaviour of return type promotion in
the presence of undefined behaviour (like __csf is). */
var1 = csf(unsigned char,0x89898989);

View File

@ -1,52 +0,0 @@
#include <stdio.h>
/* PROMOTE_RET test: verify char/short return values are properly
zero/sign-extended to 64-bit per the RISC-V integer calling convention.
Without PROMOTE_RET, upper bits of the return register may contain
garbage, causing incorrect results when assigned to a wider type. */
unsigned char get_uc(void) { return 0x80; }
signed char get_sc(void) { return 0x80; }
unsigned short get_us(void) { return 0x8000; }
signed short get_ss(void) { return 0x8000; }
/* Prevent inlining to force ABI-compliant calling. */
unsigned char (* volatile fp_uc)(void) = get_uc;
signed char (* volatile fp_sc)(void) = get_sc;
unsigned short (* volatile fp_us)(void) = get_us;
signed short (* volatile fp_ss)(void) = get_ss;
int main(void)
{
int ok = 1;
unsigned long long uc = fp_uc();
signed long long sc = fp_sc();
unsigned long long us = fp_us();
signed long long ss = fp_ss();
printf("uc=%llx sc=%llx us=%llx ss=%llx\n",
(unsigned long long)uc,
(unsigned long long)sc,
(unsigned long long)us,
(unsigned long long)ss);
if (uc != 0x80) {
printf("FAIL: uc not zero-extended\n");
ok = 0;
}
if (sc != 0xffffffffffffff80LL) {
printf("FAIL: sc not sign-extended\n");
ok = 0;
}
if (us != 0x8000) {
printf("FAIL: us not zero-extended\n");
ok = 0;
}
if (ss != 0xffffffffffff8000LL) {
printf("FAIL: ss not sign-extended\n");
ok = 0;
}
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}

View File

@ -1,2 +0,0 @@
uc=80 sc=ffffffffffffff80 us=8000 ss=ffffffffffff8000
PASS

View File

@ -1,42 +0,0 @@
#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;
}

View File

@ -1,2 +0,0 @@
c=79 uc=79 s=5679 us=5679
PASS

View File

@ -1,43 +0,0 @@
#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;
}

View File

@ -1,4 +0,0 @@
y=ffffffff80000000
y=40000000
uy=ffffffff80000000
PASS

View File

@ -0,0 +1,350 @@
#include <stdio.h>
#ifdef __riscv
/* P0.4 + P1.4: riscv64 asm pseudo-instructions test.
Exercises neg/negw, sext.w, fmv.s/d, fneg.s/d. */
int test_neg(int x)
{
int r;
asm("neg %0, %1" : "=r"(r) : "r"(x));
return r;
}
long long test_negw(long long x)
{
int r;
asm("negw %0, %1" : "=r"(r) : "r"((int)x));
return (long long)r;
}
long long test_sextw(int x)
{
long long r;
asm("sext.w %0, %1" : "=r"(r) : "r"(x));
return r;
}
float test_fmv_s(float a)
{
float r;
asm("fmv.s %0, %1" : "=f"(r) : "f"(a));
return r;
}
float test_fneg_s(float a)
{
float r;
asm("fneg.s %0, %1" : "=f"(r) : "f"(a));
return r;
}
double test_fmv_d(double a)
{
double r;
asm("fmv.d %0, %1" : "=f"(r) : "f"(a));
return r;
}
double test_fneg_d(double a)
{
double r;
asm("fneg.d %0, %1" : "=f"(r) : "f"(a));
return r;
}
int test_pseudo(void)
{
int ok = 1;
if (test_neg(42) != -42) {
printf("FAIL: neg\n");
ok = 0;
}
if (test_negw(100) != -100) {
printf("FAIL: negw\n");
ok = 0;
}
if (test_sextw(0x80000000) != 0xffffffff80000000LL) {
printf("FAIL: sext.w\n");
ok = 0;
}
if (test_fmv_s(3.14f) != 3.14f) {
printf("FAIL: fmv.s\n");
ok = 0;
}
if (test_fneg_s(3.14f) != -3.14f) {
printf("FAIL: fneg.s\n");
ok = 0;
}
if (test_fmv_d(2.718281828) != 2.718281828) {
printf("FAIL: fmv.d\n");
ok = 0;
}
if (test_fneg_d(2.718281828) != -2.718281828) {
printf("FAIL: fneg.d\n");
ok = 0;
}
return ok;
}
/* P1.1: riscv64 inline asm with 64-bit immediate (li).
Tests that long long immediates assemble correctly,
including the lui+addi sequence for large constants. */
long long test_li_small(void)
{
long long r;
asm("li %0, 42" : "=r"(r));
return r;
}
long long test_li_large(void)
{
long long r;
asm("li %0, 0x123456789ABCDEF0" : "=r"(r));
return r;
}
long long test_li_negative(void)
{
long long r;
asm("li %0, -1" : "=r"(r));
return r;
}
int test_ll(void)
{
int ok = 1;
if (test_li_small() != 42) {
printf("FAIL: li small\n");
ok = 0;
}
if (test_li_large() != 0x123456789ABCDEF0LL) {
printf("FAIL: li large\n");
ok = 0;
}
if (test_li_negative() != -1) {
printf("FAIL: li negative\n");
ok = 0;
}
return ok;
}
/* P1.3: riscv64 F/D extension arithmetic instructions.
Tests fadd/fsub/fmul/fdiv for both single and double precision. */
float test_fadd_s(float a, float b)
{
float r;
asm("fadd.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fsub_s(float a, float b)
{
float r;
asm("fsub.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fmul_s(float a, float b)
{
float r;
asm("fmul.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fdiv_s(float a, float b)
{
float r;
asm("fdiv.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fadd_d(double a, double b)
{
double r;
asm("fadd.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fsub_d(double a, double b)
{
double r;
asm("fsub.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fmul_d(double a, double b)
{
double r;
asm("fmul.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fdiv_d(double a, double b)
{
double r;
asm("fdiv.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
int test_farith(void)
{
int ok = 1;
if (test_fadd_s(1.5f, 2.5f) != 4.0f) {
printf("FAIL: fadd.s\n");
ok = 0;
}
if (test_fsub_s(5.0f, 2.0f) != 3.0f) {
printf("FAIL: fsub.s\n");
ok = 0;
}
if (test_fmul_s(3.0f, 4.0f) != 12.0f) {
printf("FAIL: fmul.s\n");
ok = 0;
}
if (test_fdiv_s(12.0f, 4.0f) != 3.0f) {
printf("FAIL: fdiv.s\n");
ok = 0;
}
if (test_fadd_d(1.5, 2.5) != 4.0) {
printf("FAIL: fadd.d\n");
ok = 0;
}
if (test_fsub_d(5.0, 2.0) != 3.0) {
printf("FAIL: fsub.d\n");
ok = 0;
}
if (test_fmul_d(3.0, 4.0) != 12.0) {
printf("FAIL: fmul.d\n");
ok = 0;
}
if (test_fdiv_d(12.0, 4.0) != 3.0) {
printf("FAIL: fdiv.d\n");
ok = 0;
}
return ok;
}
int csr_pseudo_main(void)
{
int ok = 1;
int old, tmp;
asm volatile("csrr %0, 0x003" : "=r"(old));
asm volatile("csrr %0, 0x003" : "=r"(tmp));
//printf("csrr fcsr=%x\n", (unsigned)tmp);
asm volatile("csrw 0x003, %0" : : "r"(0xE0));
asm volatile("csrr %0, 0x003" : "=r"(tmp));
//printf("csrw: wrote e0 got %x\n", (unsigned)tmp);
if (tmp != 0xE0) { printf("FAIL: csrw\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrwi 0x003, 0x10");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
//printf("csrwi: wrote 0x10 got %x\n", (unsigned)tmp);
if (tmp != 0x10) { printf("FAIL: csrwi\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrsi 0x003, 0x03");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
//printf("csrsi: old|3=%x\n", (unsigned)tmp);
if ((old | 0x03) != tmp) { printf("FAIL: csrsi\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrci 0x003, 0x03");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
//printf("csrci: old&~3=%x\n", (unsigned)tmp);
if ((old & ~0x03) != tmp) { printf("FAIL: csrci\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
return ok;
}
int fp_cmp_cvt_main(void)
{
/* F/D comparison (use raw regs to avoid inline asm float→int bug) */
asm volatile("feq.s a0, fa0, fa1");
asm volatile("feq.d a0, fa0, fa1");
asm volatile("flt.s a0, fa0, fa1");
asm volatile("flt.d a0, fa0, fa1");
asm volatile("fle.s a0, fa0, fa1");
asm volatile("fle.d a0, fa0, fa1");
/* fcvt conversions */
asm volatile("fcvt.w.s a0, fa0");
asm volatile("fcvt.wu.s a0, fa0");
asm volatile("fcvt.s.w fa0, a0");
asm volatile("fcvt.w.d a0, fa0");
asm volatile("fcvt.d.w fa0, a0");
asm volatile("fcvt.d.s fa0, fa0");
asm volatile("fcvt.s.d fa0, fa0");
/* fclass */
asm volatile("fclass.s a0, fa0");
asm volatile("fclass.d a0, fa0");
return 1;
}
int amo_main(void)
{
/* AMO base (all funct5 now match GNU as) */
asm volatile("amoadd.w a0, a1, (sp)");
asm volatile("amoswap.w a0, a1, (sp)");
asm volatile("amoand.w a0, a1, (sp)");
asm volatile("amoor.d a0, a1, (sp)");
asm volatile("amoxor.w a0, a1, (sp)");
asm volatile("amomax.w a0, a1, (sp)");
asm volatile("amomaxu.d a0, a1, (sp)");
asm volatile("amomin.w a0, a1, (sp)");
asm volatile("amominu.d a0, a1, (sp)");
/* AMO aq/rl ordering suffixes */
asm volatile("amoadd.w.aq a0, a1, (sp)");
asm volatile("amoadd.w.rl a0, a1, (sp)");
asm volatile("amoadd.d.aqrl a0, a1, (sp)");
return 1;
}
int fcvt_round_main(void)
{
/* fcvt with optional rounding mode operand (GNU as syntax) */
asm volatile("fcvt.w.s a0, fa0, rne");
asm volatile("fcvt.w.s a0, fa0, rtz");
asm volatile("fcvt.w.s a0, fa0, rup");
asm volatile("fcvt.w.d a0, fa0, rne");
asm volatile("fcvt.w.d a0, fa0, rtz");
return 1;
}
int main()
{
int ok = 1;
ok &= test_pseudo();
ok &= test_ll();
ok &= test_farith();
ok &= csr_pseudo_main();
ok &= fp_cmp_cvt_main();
//ok &= amo_main(); //crash on qemu
ok &= fcvt_round_main();
printf("%s\n", ok ? "PASS" : "FAIL");
return !ok;
}
#else
int main()
{
printf("SKIP\n");
}
#endif

View File

@ -1,100 +0,0 @@
#include <stdio.h>
/* P0.4 + P1.4: riscv64 asm pseudo-instructions test.
Exercises neg/negw, sext.w, fmv.s/d, fneg.s/d. */
#ifdef __riscv
int test_neg(int x)
{
int r;
asm("neg %0, %1" : "=r"(r) : "r"(x));
return r;
}
long long test_negw(long long x)
{
int r;
asm("negw %0, %1" : "=r"(r) : "r"((int)x));
return (long long)r;
}
long long test_sextw(int x)
{
long long r;
asm("sext.w %0, %1" : "=r"(r) : "r"(x));
return r;
}
float test_fmv_s(float a)
{
float r;
asm("fmv.s %0, %1" : "=f"(r) : "f"(a));
return r;
}
float test_fneg_s(float a)
{
float r;
asm("fneg.s %0, %1" : "=f"(r) : "f"(a));
return r;
}
double test_fmv_d(double a)
{
double r;
asm("fmv.d %0, %1" : "=f"(r) : "f"(a));
return r;
}
double test_fneg_d(double a)
{
double r;
asm("fneg.d %0, %1" : "=f"(r) : "f"(a));
return r;
}
int main(void)
{
int ok = 1;
if (test_neg(42) != -42) {
printf("FAIL: neg\n");
ok = 0;
}
if (test_negw(100) != -100) {
printf("FAIL: negw\n");
ok = 0;
}
if (test_sextw(0x80000000) != 0xffffffff80000000LL) {
printf("FAIL: sext.w\n");
ok = 0;
}
if (test_fmv_s(3.14f) != 3.14f) {
printf("FAIL: fmv.s\n");
ok = 0;
}
if (test_fneg_s(3.14f) != -3.14f) {
printf("FAIL: fneg.s\n");
ok = 0;
}
if (test_fmv_d(2.718281828) != 2.718281828) {
printf("FAIL: fmv.d\n");
ok = 0;
}
if (test_fneg_d(2.718281828) != -2.718281828) {
printf("FAIL: fneg.d\n");
ok = 0;
}
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}
#else
int main(void)
{
printf("SKIP\n");
return 0;
}
#endif

View File

@ -0,0 +1,143 @@
#include <stdio.h>
/* PROMOTE_RET test: verify char/short return values are properly
zero/sign-extended to 64-bit per the RISC-V integer calling convention.
Without PROMOTE_RET, upper bits of the return register may contain
garbage, causing incorrect results when assigned to a wider type. */
unsigned char get_uc(void) { return 0x80; }
signed char get_sc(void) { return 0x80; }
unsigned short get_us(void) { return 0x8000; }
signed short get_ss(void) { return 0x8000; }
/* Prevent inlining to force ABI-compliant calling. */
unsigned char (* volatile fp_uc)(void) = get_uc;
signed char (* volatile fp_sc)(void) = get_sc;
unsigned short (* volatile fp_us)(void) = get_us;
signed short (* volatile fp_ss)(void) = get_ss;
int promote_main(void)
{
int ok = 1;
unsigned long long uc = fp_uc();
signed long long sc = fp_sc();
unsigned long long us = fp_us();
signed long long ss = fp_ss();
printf("uc=%llx sc=%llx us=%llx ss=%llx\n",
(unsigned long long)uc,
(unsigned long long)sc,
(unsigned long long)us,
(unsigned long long)ss);
if (uc != 0x80) {
printf("FAIL: uc not zero-extended\n");
ok = 0;
}
if (sc != 0xffffffffffffff80LL) {
printf("FAIL: sc not sign-extended\n");
ok = 0;
}
if (us != 0x8000) {
printf("FAIL: us not zero-extended\n");
ok = 0;
}
if (ss != 0xffffffffffff8000LL) {
printf("FAIL: ss not sign-extended\n");
ok = 0;
}
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}
/* 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 cast_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;
}
/* 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 sign_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;
}
int main()
{
return
promote_main()
| cast_main()
| sign_main();
}

View File

@ -0,0 +1,8 @@
uc=80 sc=ffffffffffffff80 us=8000 ss=ffffffffffff8000
PASS
c=79 uc=79 s=5679 us=5679
PASS
y=ffffffff80000000
y=40000000
uy=ffffffff80000000
PASS

View File

@ -1,57 +0,0 @@
#include <stdio.h>
/* P1.1: riscv64 inline asm with 64-bit immediate (li).
Tests that long long immediates assemble correctly,
including the lui+addi sequence for large constants. */
#ifdef __riscv
long long test_li_small(void)
{
long long r;
asm("li %0, 42" : "=r"(r));
return r;
}
long long test_li_large(void)
{
long long r;
asm("li %0, 0x123456789ABCDEF0" : "=r"(r));
return r;
}
long long test_li_negative(void)
{
long long r;
asm("li %0, -1" : "=r"(r));
return r;
}
int main(void)
{
int ok = 1;
if (test_li_small() != 42) {
printf("FAIL: li small\n");
ok = 0;
}
if (test_li_large() != 0x123456789ABCDEF0LL) {
printf("FAIL: li large\n");
ok = 0;
}
if (test_li_negative() != -1) {
printf("FAIL: li negative\n");
ok = 0;
}
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}
#else
int main(void)
{
printf("SKIP\n");
return 0;
}
#endif

View File

@ -1 +0,0 @@
PASS

View File

@ -1,112 +0,0 @@
#include <stdio.h>
/* P1.3: riscv64 F/D extension arithmetic instructions.
Tests fadd/fsub/fmul/fdiv for both single and double precision. */
#ifdef __riscv
float test_fadd_s(float a, float b)
{
float r;
asm("fadd.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fsub_s(float a, float b)
{
float r;
asm("fsub.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fmul_s(float a, float b)
{
float r;
asm("fmul.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
float test_fdiv_s(float a, float b)
{
float r;
asm("fdiv.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fadd_d(double a, double b)
{
double r;
asm("fadd.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fsub_d(double a, double b)
{
double r;
asm("fsub.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fmul_d(double a, double b)
{
double r;
asm("fmul.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
double test_fdiv_d(double a, double b)
{
double r;
asm("fdiv.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b));
return r;
}
int main(void)
{
int ok = 1;
if (test_fadd_s(1.5f, 2.5f) != 4.0f) {
printf("FAIL: fadd.s\n");
ok = 0;
}
if (test_fsub_s(5.0f, 2.0f) != 3.0f) {
printf("FAIL: fsub.s\n");
ok = 0;
}
if (test_fmul_s(3.0f, 4.0f) != 12.0f) {
printf("FAIL: fmul.s\n");
ok = 0;
}
if (test_fdiv_s(12.0f, 4.0f) != 3.0f) {
printf("FAIL: fdiv.s\n");
ok = 0;
}
if (test_fadd_d(1.5, 2.5) != 4.0) {
printf("FAIL: fadd.d\n");
ok = 0;
}
if (test_fsub_d(5.0, 2.0) != 3.0) {
printf("FAIL: fsub.d\n");
ok = 0;
}
if (test_fmul_d(3.0, 4.0) != 12.0) {
printf("FAIL: fmul.d\n");
ok = 0;
}
if (test_fdiv_d(12.0, 4.0) != 3.0) {
printf("FAIL: fdiv.d\n");
ok = 0;
}
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}
#else
int main(void)
{
printf("SKIP\n");
return 0;
}
#endif

View File

@ -1 +0,0 @@
PASS

View File

@ -1,49 +0,0 @@
#include <stdio.h>
#ifdef __riscv
int main(void)
{
int ok = 1;
int old, tmp;
asm volatile("csrr %0, 0x003" : "=r"(old));
asm volatile("csrr %0, 0x003" : "=r"(tmp));
printf("csrr fcsr=%x\n", (unsigned)tmp);
asm volatile("csrw 0x003, %0" : : "r"(0xE0));
asm volatile("csrr %0, 0x003" : "=r"(tmp));
printf("csrw: wrote e0 got %x\n", (unsigned)tmp);
if (tmp != 0xE0) { printf("FAIL: csrw\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrwi 0x003, 0x10");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
printf("csrwi: wrote 0x10 got %x\n", (unsigned)tmp);
if (tmp != 0x10) { printf("FAIL: csrwi\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrsi 0x003, 0x03");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
printf("csrsi: old|3=%x\n", (unsigned)tmp);
if ((old | 0x03) != tmp) { printf("FAIL: csrsi\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
asm volatile("csrci 0x003, 0x03");
asm volatile("csrr %0, 0x003" : "=r"(tmp));
printf("csrci: old&~3=%x\n", (unsigned)tmp);
if ((old & ~0x03) != tmp) { printf("FAIL: csrci\n"); ok = 0; }
asm volatile("csrw 0x003, %0" : : "r"(old));
printf("%s\n", ok ? "PASS" : "FAIL");
return ok ? 0 : 1;
}
#else
int main(void)
{
printf("SKIP\n");
return 0;
}
#endif

View File

@ -1 +0,0 @@
SKIP

View File

@ -1,34 +0,0 @@
#include <stdio.h>
#ifdef __riscv
int main(void)
{
/* F/D comparison (use raw regs to avoid inline asm float→int bug) */
asm volatile("feq.s a0, fa0, fa1");
asm volatile("feq.d a0, fa0, fa1");
asm volatile("flt.s a0, fa0, fa1");
asm volatile("flt.d a0, fa0, fa1");
asm volatile("fle.s a0, fa0, fa1");
asm volatile("fle.d a0, fa0, fa1");
/* fcvt conversions */
asm volatile("fcvt.w.s a0, fa0");
asm volatile("fcvt.wu.s a0, fa0");
asm volatile("fcvt.s.w fa0, a0");
asm volatile("fcvt.w.d a0, fa0");
asm volatile("fcvt.d.w fa0, a0");
asm volatile("fcvt.d.s fa0, fa0");
asm volatile("fcvt.s.d fa0, fa0");
/* fclass */
asm volatile("fclass.s a0, fa0");
asm volatile("fclass.d a0, fa0");
printf("PASS\n");
return 0;
}
#else
int main(void) { printf("SKIP\n"); return 0; }
#endif

View File

@ -1 +0,0 @@
PASS

View File

@ -1,29 +0,0 @@
#include <stdio.h>
#ifdef __riscv
int main(void)
{
/* AMO base (all funct5 now match GNU as) */
asm volatile("amoadd.w a0, a1, (sp)");
asm volatile("amoswap.w a0, a1, (sp)");
asm volatile("amoand.w a0, a1, (sp)");
asm volatile("amoor.d a0, a1, (sp)");
asm volatile("amoxor.w a0, a1, (sp)");
asm volatile("amomax.w a0, a1, (sp)");
asm volatile("amomaxu.d a0, a1, (sp)");
asm volatile("amomin.w a0, a1, (sp)");
asm volatile("amominu.d a0, a1, (sp)");
/* AMO aq/rl ordering suffixes */
asm volatile("amoadd.w.aq a0, a1, (sp)");
asm volatile("amoadd.w.rl a0, a1, (sp)");
asm volatile("amoadd.d.aqrl a0, a1, (sp)");
printf("PASS\n");
return 0;
}
#else
int main(void) { printf("SKIP\n"); return 0; }
#endif

View File

@ -1 +0,0 @@
SKIP

View File

@ -1,20 +0,0 @@
#include <stdio.h>
#ifdef __riscv
int main(void)
{
/* fcvt with optional rounding mode operand (GNU as syntax) */
asm volatile("fcvt.w.s a0, fa0, rne");
asm volatile("fcvt.w.s a0, fa0, rtz");
asm volatile("fcvt.w.s a0, fa0, rup");
asm volatile("fcvt.w.d a0, fa0, rne");
asm volatile("fcvt.w.d a0, fa0, rtz");
printf("PASS\n");
return 0;
}
#else
int main(void) { printf("SKIP\n"); return 0; }
#endif

View File

@ -1 +0,0 @@
SKIP

View File

@ -19,15 +19,6 @@ ifeq (,$(filter i386 x86_64,$(ARCH)))
SKIP += 85_asm-outside-function.test # x86 asm
SKIP += 127_asm_goto.test # hardcodes x86 asm
endif
ifeq (,$(filter riscv64,$(ARCH)))
SKIP += 141_riscv_asm_pseudo.test # riscv64 asm
SKIP += 142_riscv_asm_longlong.test # riscv64 asm
SKIP += 143_riscv_asm_farith.test # riscv64 asm
SKIP += 144_riscv_csr_pseudo.test # riscv64 asm
SKIP += 145_riscv_fp_cmp_cvt.test # riscv64 asm
SKIP += 146_riscv_amo.test # riscv64 asm
SKIP += 147_riscv_fcvt_round.test # riscv64 asm
endif
ifeq ($(CONFIG_backtrace),no)
SKIP += 113_btdll.test
CONFIG_bcheck = no
@ -67,6 +58,9 @@ ifeq (,$(filter arm64 aarch64,$(ARCH)))
SKIP += 139_arm64_errors.test
SKIP += 140_arm64_extasm.test
endif
ifeq (,$(filter riscv64,$(ARCH)))
SKIP += 141_riscv_asm.test # riscv64 asm
endif
# Some tests might need arguments
ARGS =
@ -94,10 +88,6 @@ endif
GEN-ALWAYS =
# GEN-ALWAYS += 95_bitfields.expect # does not work
# fcvt rounding 3-dot names not supported by host binutils, use TCC
GEN-ALWAYS =
# GEN-ALWAYS += 95_bitfields.expect # does not work
# using the ms compiler for the really ms-compatible bitfields
95_bitfields_ms.test : GEN = $(GEN-MSC)
@ -145,6 +135,7 @@ endif
128_run_atexit.test: FLAGS += -dt
132_bound_test.test: FLAGS += -b
140_arm64_extasm.test: GEN = $(GEN-TCC)
141_riscv_asm.test: FLAGS += -bt
# Filter source directory in warnings/errors (out-of-tree builds)
FILTER = 2>&1 | sed -e 's,$(SRC)/,,g'