diff --git a/riscv64-asm.c b/riscv64-asm.c index 6754724d..574132f7 100644 --- a/riscv64-asm.c +++ b/riscv64-asm.c @@ -738,6 +738,15 @@ static void asm_binary_opcode(TCCState* s1, int token) asm_emit_f(token, 0x53 | (4 << 27) | (0 << 25) | (2 << 12), &ops[0], &ops[1], &ops[1]); return; + /* CSR pseudo-instructions */ + case TOK_ASM_csrr: + /* csrrs rd, csr, x0 */ + asm_emit_opcode(0x73 | (2 << 12) | (ops[1].e.v << 20) | ENCODE_RD(ops[0].reg)); + return; + case TOK_ASM_csrw: + /* csrrw x0, csr, rs */ + asm_emit_opcode(0x73 | (1 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg)); + return; case TOK_ASM_csrs: /* csrrs x0, csr, rs */ asm_emit_opcode(0x73 | (2 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg)); @@ -754,6 +763,18 @@ static void asm_binary_opcode(TCCState* s1, int token) /* csrrw rd, fcsr, rs */ asm_emit_opcode(0x73 | (1 << 12) | (3 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg)); return; + case TOK_ASM_csrwi: + /* csrrwi x0, csr, uimm */ + asm_emit_opcode(0x73 | (5 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v)); + return; + case TOK_ASM_csrsi: + /* csrrsi x0, csr, uimm */ + asm_emit_opcode(0x73 | (6 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v)); + return; + case TOK_ASM_csrci: + /* csrrci x0, csr, uimm */ + asm_emit_opcode(0x73 | (7 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v)); + return; default: expect("binary instruction"); } @@ -1695,6 +1716,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) case TOK_ASM_fneg_d: case TOK_ASM_csrc: case TOK_ASM_csrs: + case TOK_ASM_csrr: + case TOK_ASM_csrw: + case TOK_ASM_csrwi: + case TOK_ASM_csrsi: + case TOK_ASM_csrci: case TOK_ASM_fsrm: case TOK_ASM_fscsr: asm_binary_opcode(s1, token); diff --git a/tests/tests2/144_riscv_csr_pseudo.c b/tests/tests2/144_riscv_csr_pseudo.c new file mode 100644 index 00000000..e1176151 --- /dev/null +++ b/tests/tests2/144_riscv_csr_pseudo.c @@ -0,0 +1,49 @@ +#include + +#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 diff --git a/tests/tests2/144_riscv_csr_pseudo.expect b/tests/tests2/144_riscv_csr_pseudo.expect new file mode 100644 index 00000000..cc2ecb63 --- /dev/null +++ b/tests/tests2/144_riscv_csr_pseudo.expect @@ -0,0 +1 @@ +SKIP diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 40ed4238..d3bf1134 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -23,6 +23,10 @@ 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 @@ -72,6 +76,9 @@ ARGS = # And some tests don't test the right thing with -run NORUN = 42_function_pointer.test : NORUN = true +# riscv64 asm tests validate encoding, raw regs may crash at runtime +145_riscv_fp_cmp_cvt.test : NORUN = true +146_riscv_amo.test : NORUN = true # Some tests might need different flags FLAGS = @@ -86,7 +93,12 @@ endif 96_nodata_wanted.test : FLAGS += -dt 139_arm64_errors.test : FLAGS += -dt -# Always generate certain .expects (don't put these in the GIT), +GEN-ALWAYS = +# GEN-ALWAYS += 95_bitfields.expect # does not work + +# fcvt rounding 3-dot names not supported by host binutils, use TCC +147_riscv_fcvt_round.test : GEN = $(GEN-TCC) +147_riscv_fcvt_round.test : NORUN = true GEN-ALWAYS = # GEN-ALWAYS += 95_bitfields.expect # does not work