mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-04 10:28:45 +08:00
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.
This commit is contained in:
parent
199369bb17
commit
f8011ea9b7
@ -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]);
|
asm_emit_f(token, 0x53 | (4 << 27) | (0 << 25) | (2 << 12), &ops[0], &ops[1], &ops[1]);
|
||||||
return;
|
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:
|
case TOK_ASM_csrs:
|
||||||
/* csrrs x0, csr, rs */
|
/* csrrs x0, csr, rs */
|
||||||
asm_emit_opcode(0x73 | (2 << 12) | (ops[0].e.v << 20) | ENCODE_RS1(ops[1].reg));
|
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 */
|
/* csrrw rd, fcsr, rs */
|
||||||
asm_emit_opcode(0x73 | (1 << 12) | (3 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg));
|
asm_emit_opcode(0x73 | (1 << 12) | (3 << 20) | ENCODE_RD(ops[0].reg) | ENCODE_RS1(ops[1].reg));
|
||||||
return;
|
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:
|
default:
|
||||||
expect("binary instruction");
|
expect("binary instruction");
|
||||||
}
|
}
|
||||||
@ -1695,6 +1716,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int token)
|
|||||||
case TOK_ASM_fneg_d:
|
case TOK_ASM_fneg_d:
|
||||||
case TOK_ASM_csrc:
|
case TOK_ASM_csrc:
|
||||||
case TOK_ASM_csrs:
|
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_fsrm:
|
||||||
case TOK_ASM_fscsr:
|
case TOK_ASM_fscsr:
|
||||||
asm_binary_opcode(s1, token);
|
asm_binary_opcode(s1, token);
|
||||||
|
|||||||
49
tests/tests2/144_riscv_csr_pseudo.c
Normal file
49
tests/tests2/144_riscv_csr_pseudo.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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
|
||||||
1
tests/tests2/144_riscv_csr_pseudo.expect
Normal file
1
tests/tests2/144_riscv_csr_pseudo.expect
Normal file
@ -0,0 +1 @@
|
|||||||
|
SKIP
|
||||||
@ -23,6 +23,10 @@ ifeq (,$(filter riscv64,$(ARCH)))
|
|||||||
SKIP += 141_riscv_asm_pseudo.test # riscv64 asm
|
SKIP += 141_riscv_asm_pseudo.test # riscv64 asm
|
||||||
SKIP += 142_riscv_asm_longlong.test # riscv64 asm
|
SKIP += 142_riscv_asm_longlong.test # riscv64 asm
|
||||||
SKIP += 143_riscv_asm_farith.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
|
endif
|
||||||
ifeq ($(CONFIG_backtrace),no)
|
ifeq ($(CONFIG_backtrace),no)
|
||||||
SKIP += 113_btdll.test
|
SKIP += 113_btdll.test
|
||||||
@ -72,6 +76,9 @@ ARGS =
|
|||||||
# And some tests don't test the right thing with -run
|
# And some tests don't test the right thing with -run
|
||||||
NORUN =
|
NORUN =
|
||||||
42_function_pointer.test : NORUN = true
|
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
|
# Some tests might need different flags
|
||||||
FLAGS =
|
FLAGS =
|
||||||
@ -86,7 +93,12 @@ endif
|
|||||||
96_nodata_wanted.test : FLAGS += -dt
|
96_nodata_wanted.test : FLAGS += -dt
|
||||||
139_arm64_errors.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 =
|
||||||
# GEN-ALWAYS += 95_bitfields.expect # does not work
|
# GEN-ALWAYS += 95_bitfields.expect # does not work
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user