diff --git a/riscv64-asm.c b/riscv64-asm.c index 0e957a90..b3849c55 100644 --- a/riscv64-asm.c +++ b/riscv64-asm.c @@ -683,6 +683,26 @@ static void asm_binary_opcode(TCCState* s1, int token) /* subw rd, x0, rs2 */ asm_emit_r(token, (0xE << 2) | 3 | (32 << 25), &ops[0], &zero, &ops[1]); return; + case TOK_ASM_sext_w: + /* addiw rd, rs, 0 */ + asm_emit_i(token, 0x1b, &ops[0], &ops[1], &zimm); + return; + case TOK_ASM_fneg_s: + /* fsgnjn.s rd, rs, rs */ + asm_emit_f(token, 0x53 | (1 << 12) | (0 << 25) | (4 << 27), &ops[0], &ops[1], &ops[1]); + return; + case TOK_ASM_fneg_d: + /* fsgnjn.d rd, rs, rs */ + asm_emit_f(token, 0x53 | (1 << 12) | (1 << 25) | (4 << 27), &ops[0], &ops[1], &ops[1]); + return; + case TOK_ASM_fmv_s: + /* fsgnj.s rd, rs, rs */ + asm_emit_f(token, 0x53 | (0 << 12) | (0 << 25) | (4 << 27), &ops[0], &ops[1], &ops[1]); + return; + case TOK_ASM_fmv_d: + /* fsgnj.d rd, rs, rs */ + asm_emit_f(token, 0x53 | (0 << 12) | (1 << 25) | (4 << 27), &ops[0], &ops[1], &ops[1]); + return; case TOK_ASM_jump: /* auipc x5, 0 */ asm_emit_opcode(3 | (5 << 2) | ENCODE_RD(5)); @@ -1634,8 +1654,13 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_not: case TOK_ASM_neg: case TOK_ASM_negw: + case TOK_ASM_sext_w: case TOK_ASM_fabs_s: case TOK_ASM_fabs_d: + case TOK_ASM_fmv_s: + case TOK_ASM_fmv_d: + case TOK_ASM_fneg_s: + case TOK_ASM_fneg_d: case TOK_ASM_csrc: case TOK_ASM_csrs: case TOK_ASM_fsrm: diff --git a/tests/tests2/141_riscv_asm_pseudo.c b/tests/tests2/141_riscv_asm_pseudo.c new file mode 100644 index 00000000..cf45836b --- /dev/null +++ b/tests/tests2/141_riscv_asm_pseudo.c @@ -0,0 +1,100 @@ +#include + +/* 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 diff --git a/tests/tests2/141_riscv_asm_pseudo.expect b/tests/tests2/141_riscv_asm_pseudo.expect new file mode 100644 index 00000000..7ef22e9a --- /dev/null +++ b/tests/tests2/141_riscv_asm_pseudo.expect @@ -0,0 +1 @@ +PASS