History

riscv64-asm: implement CSR pseudo-instructions

Add handlers for csrr, csrw, csrwi, csrsi, csrci as pseudo-instructions: csrr rd, csr -> csrrs rd, csr, x0 csrw csr, rs -> csrrw x0, csr, rs csrwi csr, uimm -> csrrwi x0, csr, uimm csrsi csr, uimm -> csrrsi x0, csr, uimm csrci csr, uimm -> csrrci x0, csr, uimm Tokens were already defined in riscv64-tok.h. Tested on Spacemit X100 using fcsr (0x003) which is accessible in user mode. cycle/instret CSRs are privileged and not accessible from Linux user mode on this hardware.

Meng Zhuo committed 6 months ago

Commit f8011ea1 parent 199369b4 files · +89 −1Browse files

Unified · Split

4 files
  1. riscv64-asm.c +26 −0
  2. tests/tests2/144_riscv_csr_pseudo.c +49 −0
  3. tests/tests2/144_riscv_csr_pseudo.expect +1 −0
  4. tests/tests2/Makefile +13 −1
riscv64-asm.c+26−0
@@ -738,6 +738,15 @@ static void asm_binary_opcode(TCCState* s1, int token) · 737 unmodified lines
738738 asm_emit_f(token, 0x53 | (4 << 27) | (0 << 25) | (2 << 12), &ops[0], &ops[1], &ops[1]);
739739 return;
740740
741+ /* CSR pseudo-instructions */
742+ case TOK_ASM_csrr:
743+ /* csrrs rd, csr, x0 */
744+ asm_emit_opcode(0x73 | (2 << 12) | (ops[1].e.v << 20) | ENCODE_RD(ops[0].reg));
745+ return;
746+ case TOK_ASM_csrw:
747+ /* csrrw x0, csr, rs */
748+ asm_emit_opcode(0x73 | (1 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg));
749+ return;
741750 case TOK_ASM_csrs:
742751 /* csrrs x0, csr, rs */
743752 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) · 10 unmodified lines
754763 /* csrrw rd, fcsr, rs */
755764 asm_emit_opcode(0x73 | (1 << 12) | (3 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg));
756765 return;
766+ case TOK_ASM_csrwi:
767+ /* csrrwi x0, csr, uimm */
768+ asm_emit_opcode(0x73 | (5 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v));
769+ return;
770+ case TOK_ASM_csrsi:
771+ /* csrrsi x0, csr, uimm */
772+ asm_emit_opcode(0x73 | (6 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v));
773+ return;
774+ case TOK_ASM_csrci:
775+ /* csrrci x0, csr, uimm */
776+ asm_emit_opcode(0x73 | (7 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].e.v));
777+ return;
757778 default:
758779 expect("binary instruction");
759780 }
@@ -1695,6 +1716,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int token) · 935 unmodified lines
16951716 case TOK_ASM_fneg_d:
16961717 case TOK_ASM_csrc:
16971718 case TOK_ASM_csrs:
1719+ case TOK_ASM_csrr:
1720+ case TOK_ASM_csrw:
1721+ case TOK_ASM_csrwi:
1722+ case TOK_ASM_csrsi:
1723+ case TOK_ASM_csrci:
16981724 case TOK_ASM_fsrm:
16991725 case TOK_ASM_fscsr:
17001726 asm_binary_opcode(s1, token);
tests/tests2/144_riscv_csr_pseudo.c+49−0
@@ -0,0 +1,49 @@
1+#include <stdio.h>
2+
3+#ifdef __riscv
4+
5+int main(void)
6+{
7+ int ok = 1;
8+ int old, tmp;
9+
10+ asm volatile("csrr %0, 0x003" : "=r"(old));
11+
12+ asm volatile("csrr %0, 0x003" : "=r"(tmp));
13+ printf("csrr fcsr=%x\n", (unsigned)tmp);
14+
15+ asm volatile("csrw 0x003, %0" : : "r"(0xE0));
16+ asm volatile("csrr %0, 0x003" : "=r"(tmp));
17+ printf("csrw: wrote e0 got %x\n", (unsigned)tmp);
18+ if (tmp != 0xE0) { printf("FAIL: csrw\n"); ok = 0; }
19+ asm volatile("csrw 0x003, %0" : : "r"(old));
20+
21+ asm volatile("csrwi 0x003, 0x10");
22+ asm volatile("csrr %0, 0x003" : "=r"(tmp));
23+ printf("csrwi: wrote 0x10 got %x\n", (unsigned)tmp);
24+ if (tmp != 0x10) { printf("FAIL: csrwi\n"); ok = 0; }
25+ asm volatile("csrw 0x003, %0" : : "r"(old));
26+
27+ asm volatile("csrsi 0x003, 0x03");
28+ asm volatile("csrr %0, 0x003" : "=r"(tmp));
29+ printf("csrsi: old|3=%x\n", (unsigned)tmp);
30+ if ((old | 0x03) != tmp) { printf("FAIL: csrsi\n"); ok = 0; }
31+ asm volatile("csrw 0x003, %0" : : "r"(old));
32+
33+ asm volatile("csrci 0x003, 0x03");
34+ asm volatile("csrr %0, 0x003" : "=r"(tmp));
35+ printf("csrci: old&~3=%x\n", (unsigned)tmp);
36+ if ((old & ~0x03) != tmp) { printf("FAIL: csrci\n"); ok = 0; }
37+ asm volatile("csrw 0x003, %0" : : "r"(old));
38+
39+ printf("%s\n", ok ? "PASS" : "FAIL");
40+ return ok ? 0 : 1;
41+}
42+
43+#else
44+int main(void)
45+{
46+ printf("SKIP\n");
47+ return 0;
48+}
49+#endif
tests/tests2/144_riscv_csr_pseudo.expect+1−0
@@ -0,0 +1 @@
1+SKIP
tests/tests2/Makefile+13−1
@@ -23,6 +23,10 @@ ifeq (,$(filter riscv64,$(ARCH))) · 22 unmodified lines
2323 SKIP += 141_riscv_asm_pseudo.test # riscv64 asm
2424 SKIP += 142_riscv_asm_longlong.test # riscv64 asm
2525 SKIP += 143_riscv_asm_farith.test # riscv64 asm
26+ SKIP += 144_riscv_csr_pseudo.test # riscv64 asm
27+ SKIP += 145_riscv_fp_cmp_cvt.test # riscv64 asm
28+ SKIP += 146_riscv_amo.test # riscv64 asm
29+ SKIP += 147_riscv_fcvt_round.test # riscv64 asm
2630 endif
2731 ifeq ($(CONFIG_backtrace),no)
2832 SKIP += 113_btdll.test
@@ -72,6 +76,9 @@ ARGS = · 43 unmodified lines
7276 # And some tests don't test the right thing with -run
7377 NORUN =
7478 42_function_pointer.test : NORUN = true
79+# riscv64 asm tests validate encoding, raw regs may crash at runtime
80+145_riscv_fp_cmp_cvt.test : NORUN = true
81+146_riscv_amo.test : NORUN = true
7582
7683 # Some tests might need different flags
7784 FLAGS =
@@ -86,7 +93,12 @@ endif · 8 unmodified lines
8693 96_nodata_wanted.test : FLAGS += -dt
8794 139_arm64_errors.test : FLAGS += -dt
8895
89−# Always generate certain .expects (don't put these in the GIT),
96+GEN-ALWAYS =
97+# GEN-ALWAYS += 95_bitfields.expect # does not work
98+
99+# fcvt rounding 3-dot names not supported by host binutils, use TCC
100+147_riscv_fcvt_round.test : GEN = $(GEN-TCC)
101+147_riscv_fcvt_round.test : NORUN = true
90102 GEN-ALWAYS =
91103 # GEN-ALWAYS += 95_bitfields.expect # does not work
92104

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t