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.
Unified · Split
| @@ -1229,6 +1229,30 @@ static void asm_ternary_opcode(TCCState *s1, int token) · 1228 unmodified lines | ||
| 1229 | 1229 | return; |
| 1230 | 1230 | |
| 1231 | 1231 | /* F/D extension */ |
| 1232 | + case TOK_ASM_fadd_d: | |
| 1233 | + asm_emit_f(token, 0x53 | (0 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1234 | + return; | |
| 1235 | + case TOK_ASM_fadd_s: | |
| 1236 | + asm_emit_f(token, 0x53 | (0 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1237 | + return; | |
| 1238 | + case TOK_ASM_fsub_d: | |
| 1239 | + asm_emit_f(token, 0x53 | (1 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1240 | + return; | |
| 1241 | + case TOK_ASM_fsub_s: | |
| 1242 | + asm_emit_f(token, 0x53 | (1 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1243 | + return; | |
| 1244 | + case TOK_ASM_fmul_d: | |
| 1245 | + asm_emit_f(token, 0x53 | (2 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1246 | + return; | |
| 1247 | + case TOK_ASM_fmul_s: | |
| 1248 | + asm_emit_f(token, 0x53 | (2 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1249 | + return; | |
| 1250 | + case TOK_ASM_fdiv_d: | |
| 1251 | + asm_emit_f(token, 0x53 | (3 << 27) | (1 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1252 | + return; | |
| 1253 | + case TOK_ASM_fdiv_s: | |
| 1254 | + asm_emit_f(token, 0x53 | (3 << 27) | (0 << 25) | (7 << 12), ops, ops + 1, ops + 2); | |
| 1255 | + return; | |
| 1232 | 1256 | case TOK_ASM_fsgnj_d: |
| 1233 | 1257 | asm_emit_f(token, 0x53 | (4 << 27) | (1 << 25) | (0 << 12), ops, ops + 1, ops + 2); |
| 1234 | 1258 | return; |
| @@ -1549,6 +1573,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 314 unmodified lines | ||
| 1549 | 1573 | case TOK_ASM_csrrw: |
| 1550 | 1574 | case TOK_ASM_csrrwi: |
| 1551 | 1575 | /* F/D extension */ |
| 1576 | + case TOK_ASM_fadd_s: | |
| 1577 | + case TOK_ASM_fadd_d: | |
| 1578 | + case TOK_ASM_fsub_s: | |
| 1579 | + case TOK_ASM_fsub_d: | |
| 1580 | + case TOK_ASM_fmul_s: | |
| 1581 | + case TOK_ASM_fmul_d: | |
| 1582 | + case TOK_ASM_fdiv_s: | |
| 1583 | + case TOK_ASM_fdiv_d: | |
| 1552 | 1584 | case TOK_ASM_fsgnj_d: |
| 1553 | 1585 | case TOK_ASM_fsgnj_s: |
| 1554 | 1586 | case TOK_ASM_fmax_s: |
| @@ -270,6 +270,14 @@ · 269 unmodified lines | ||
| 270 | 270 | /* enough implemented for musl */ |
| 271 | 271 | DEF_ASM_WITH_SUFFIX(fsgnj, s) |
| 272 | 272 | DEF_ASM_WITH_SUFFIX(fsgnj, d) |
| 273 | + DEF_ASM_WITH_SUFFIX(fadd, s) | |
| 274 | + DEF_ASM_WITH_SUFFIX(fadd, d) | |
| 275 | + DEF_ASM_WITH_SUFFIX(fsub, s) | |
| 276 | + DEF_ASM_WITH_SUFFIX(fsub, d) | |
| 277 | + DEF_ASM_WITH_SUFFIX(fmul, s) | |
| 278 | + DEF_ASM_WITH_SUFFIX(fmul, d) | |
| 279 | + DEF_ASM_WITH_SUFFIX(fdiv, s) | |
| 280 | + DEF_ASM_WITH_SUFFIX(fdiv, d) | |
| 273 | 281 | DEF_ASM_WITH_SUFFIX(fmadd, s) |
| 274 | 282 | DEF_ASM_WITH_SUFFIX(fmadd, d) |
| 275 | 283 | DEF_ASM_WITH_SUFFIX(fmax, s) |
| @@ -0,0 +1,112 @@ | ||
| 1 | +#include <stdio.h> | |
| 2 | + | |
| 3 | +/* P1.3: riscv64 F/D extension arithmetic instructions. | |
| 4 | + Tests fadd/fsub/fmul/fdiv for both single and double precision. */ | |
| 5 | + | |
| 6 | +#ifdef __riscv | |
| 7 | + | |
| 8 | +float test_fadd_s(float a, float b) | |
| 9 | +{ | |
| 10 | + float r; | |
| 11 | + asm("fadd.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 12 | + return r; | |
| 13 | +} | |
| 14 | + | |
| 15 | +float test_fsub_s(float a, float b) | |
| 16 | +{ | |
| 17 | + float r; | |
| 18 | + asm("fsub.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 19 | + return r; | |
| 20 | +} | |
| 21 | + | |
| 22 | +float test_fmul_s(float a, float b) | |
| 23 | +{ | |
| 24 | + float r; | |
| 25 | + asm("fmul.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 26 | + return r; | |
| 27 | +} | |
| 28 | + | |
| 29 | +float test_fdiv_s(float a, float b) | |
| 30 | +{ | |
| 31 | + float r; | |
| 32 | + asm("fdiv.s %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 33 | + return r; | |
| 34 | +} | |
| 35 | + | |
| 36 | +double test_fadd_d(double a, double b) | |
| 37 | +{ | |
| 38 | + double r; | |
| 39 | + asm("fadd.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 40 | + return r; | |
| 41 | +} | |
| 42 | + | |
| 43 | +double test_fsub_d(double a, double b) | |
| 44 | +{ | |
| 45 | + double r; | |
| 46 | + asm("fsub.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 47 | + return r; | |
| 48 | +} | |
| 49 | + | |
| 50 | +double test_fmul_d(double a, double b) | |
| 51 | +{ | |
| 52 | + double r; | |
| 53 | + asm("fmul.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 54 | + return r; | |
| 55 | +} | |
| 56 | + | |
| 57 | +double test_fdiv_d(double a, double b) | |
| 58 | +{ | |
| 59 | + double r; | |
| 60 | + asm("fdiv.d %0, %1, %2" : "=f"(r) : "f"(a), "f"(b)); | |
| 61 | + return r; | |
| 62 | +} | |
| 63 | + | |
| 64 | +int main(void) | |
| 65 | +{ | |
| 66 | + int ok = 1; | |
| 67 | + | |
| 68 | + if (test_fadd_s(1.5f, 2.5f) != 4.0f) { | |
| 69 | + printf("FAIL: fadd.s\n"); | |
| 70 | + ok = 0; | |
| 71 | + } | |
| 72 | + if (test_fsub_s(5.0f, 2.0f) != 3.0f) { | |
| 73 | + printf("FAIL: fsub.s\n"); | |
| 74 | + ok = 0; | |
| 75 | + } | |
| 76 | + if (test_fmul_s(3.0f, 4.0f) != 12.0f) { | |
| 77 | + printf("FAIL: fmul.s\n"); | |
| 78 | + ok = 0; | |
| 79 | + } | |
| 80 | + if (test_fdiv_s(12.0f, 4.0f) != 3.0f) { | |
| 81 | + printf("FAIL: fdiv.s\n"); | |
| 82 | + ok = 0; | |
| 83 | + } | |
| 84 | + | |
| 85 | + if (test_fadd_d(1.5, 2.5) != 4.0) { | |
| 86 | + printf("FAIL: fadd.d\n"); | |
| 87 | + ok = 0; | |
| 88 | + } | |
| 89 | + if (test_fsub_d(5.0, 2.0) != 3.0) { | |
| 90 | + printf("FAIL: fsub.d\n"); | |
| 91 | + ok = 0; | |
| 92 | + } | |
| 93 | + if (test_fmul_d(3.0, 4.0) != 12.0) { | |
| 94 | + printf("FAIL: fmul.d\n"); | |
| 95 | + ok = 0; | |
| 96 | + } | |
| 97 | + if (test_fdiv_d(12.0, 4.0) != 3.0) { | |
| 98 | + printf("FAIL: fdiv.d\n"); | |
| 99 | + ok = 0; | |
| 100 | + } | |
| 101 | + | |
| 102 | + printf("%s\n", ok ? "PASS" : "FAIL"); | |
| 103 | + return ok ? 0 : 1; | |
| 104 | +} | |
| 105 | + | |
| 106 | +#else | |
| 107 | +int main(void) | |
| 108 | +{ | |
| 109 | + printf("SKIP\n"); | |
| 110 | + return 0; | |
| 111 | +} | |
| 112 | +#endif | |
| @@ -0,0 +1 @@ | ||
| 1 | +PASS | |