diff --git a/riscv64-asm.c b/riscv64-asm.c index b3849c55..6754724d 100644 --- a/riscv64-asm.c +++ b/riscv64-asm.c @@ -1229,6 +1229,30 @@ static void asm_ternary_opcode(TCCState *s1, int token) return; /* 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: asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2); return; @@ -1549,6 +1573,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_csrrw: case TOK_ASM_csrrwi: /* 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_s: case TOK_ASM_fmax_s: diff --git a/riscv64-tok.h b/riscv64-tok.h index 0d48bb8f..fe5c28f5 100644 --- a/riscv64-tok.h +++ b/riscv64-tok.h @@ -270,6 +270,14 @@ /* enough implemented for musl */ DEF_ASM_WITH_SUFFIX(fsgnj, s) 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, d) DEF_ASM_WITH_SUFFIX(fmax, s) diff --git a/tests/tests2/143_riscv_asm_farith.c b/tests/tests2/143_riscv_asm_farith.c new file mode 100644 index 00000000..85844a81 --- /dev/null +++ b/tests/tests2/143_riscv_asm_farith.c @@ -0,0 +1,112 @@ +#include + +/* 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 diff --git a/tests/tests2/143_riscv_asm_farith.expect b/tests/tests2/143_riscv_asm_farith.expect new file mode 100644 index 00000000..7ef22e9a --- /dev/null +++ b/tests/tests2/143_riscv_asm_farith.expect @@ -0,0 +1 @@ +PASS