mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-28 23:58:41 +08:00
riscv64-asm: add basic F/D extension instructions (fadd/fsub/fmul/fdiv)
Adds the 8 most essential floating-point arithmetic instructions: fadd.s/d, fsub.s/d, fmul.s/d, fdiv.s/d, for both single and double precision. These complement the existing fsgnj/fmax/fmin/fsqrt set. Comparison (feq/flt/fle) and conversion (fcvt) instructions remain as future work.
This commit is contained in:
parent
273978b927
commit
3935c3bb55
@ -1229,6 +1229,30 @@ static void asm_ternary_opcode(TCCState *s1, int token)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* F/D extension */
|
/* F/D extension */
|
||||||
|
case TOK_ASM_fadd_d:
|
||||||
|
asm_emit_f(token, 0x53 | (0 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fadd_s:
|
||||||
|
asm_emit_f(token, 0x53 | (0 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fsub_d:
|
||||||
|
asm_emit_f(token, 0x53 | (1 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fsub_s:
|
||||||
|
asm_emit_f(token, 0x53 | (1 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fmul_d:
|
||||||
|
asm_emit_f(token, 0x53 | (2 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fmul_s:
|
||||||
|
asm_emit_f(token, 0x53 | (2 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fdiv_d:
|
||||||
|
asm_emit_f(token, 0x53 | (3 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
|
case TOK_ASM_fdiv_s:
|
||||||
|
asm_emit_f(token, 0x53 | (3 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2);
|
||||||
|
return;
|
||||||
case TOK_ASM_fsgnj_d:
|
case TOK_ASM_fsgnj_d:
|
||||||
asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2);
|
asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2);
|
||||||
return;
|
return;
|
||||||
@ -1549,6 +1573,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_csrrw:
|
case TOK_ASM_csrrw:
|
||||||
case TOK_ASM_csrrwi:
|
case TOK_ASM_csrrwi:
|
||||||
/* F/D extension */
|
/* F/D extension */
|
||||||
|
case TOK_ASM_fadd_s:
|
||||||
|
case TOK_ASM_fadd_d:
|
||||||
|
case TOK_ASM_fsub_s:
|
||||||
|
case TOK_ASM_fsub_d:
|
||||||
|
case TOK_ASM_fmul_s:
|
||||||
|
case TOK_ASM_fmul_d:
|
||||||
|
case TOK_ASM_fdiv_s:
|
||||||
|
case TOK_ASM_fdiv_d:
|
||||||
case TOK_ASM_fsgnj_d:
|
case TOK_ASM_fsgnj_d:
|
||||||
case TOK_ASM_fsgnj_s:
|
case TOK_ASM_fsgnj_s:
|
||||||
case TOK_ASM_fmax_s:
|
case TOK_ASM_fmax_s:
|
||||||
|
|||||||
@ -270,6 +270,14 @@
|
|||||||
/* enough implemented for musl */
|
/* enough implemented for musl */
|
||||||
DEF_ASM_WITH_SUFFIX(fsgnj, s)
|
DEF_ASM_WITH_SUFFIX(fsgnj, s)
|
||||||
DEF_ASM_WITH_SUFFIX(fsgnj, d)
|
DEF_ASM_WITH_SUFFIX(fsgnj, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fadd, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fadd, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsub, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fsub, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmul, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fmul, d)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fdiv, s)
|
||||||
|
DEF_ASM_WITH_SUFFIX(fdiv, d)
|
||||||
DEF_ASM_WITH_SUFFIX(fmadd, s)
|
DEF_ASM_WITH_SUFFIX(fmadd, s)
|
||||||
DEF_ASM_WITH_SUFFIX(fmadd, d)
|
DEF_ASM_WITH_SUFFIX(fmadd, d)
|
||||||
DEF_ASM_WITH_SUFFIX(fmax, s)
|
DEF_ASM_WITH_SUFFIX(fmax, s)
|
||||||
|
|||||||
112
tests/tests2/143_riscv_asm_farith.c
Normal file
112
tests/tests2/143_riscv_asm_farith.c
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
#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
|
||||||
1
tests/tests2/143_riscv_asm_farith.expect
Normal file
1
tests/tests2/143_riscv_asm_farith.expect
Normal file
@ -0,0 +1 @@
|
|||||||
|
PASS
|
||||||
Loading…
Reference in New Issue
Block a user