commit 66b6e2a37d9700a1c985389a3821cee7b7ec702b
parent dbc30add151d6e0254e031dfa8ead70c8f9e42b0
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 23 Oct 2019 02:26:42 -0700
rvsim: csrrx instructions
- only support mscratch for now
- passing 50/55 compliance tests
Diffstat:
M | riscv.h | | | 23 | +++++++++++++++++++++++ |
M | rvsim.c | | | 47 | +++++++++++++++++++++++++++++++++++++++++++++-- |
2 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/riscv.h b/riscv.h
@@ -45,6 +45,9 @@ static inline uint32_t get_fn7(uint32_t ins) {
static inline uint32_t get_ic(uint32_t ins) {
return (ins >> 15) & 0x1F;
}
+static inline uint32_t get_iC(uint32_t ins) {
+ return ins >> 20;
+}
// opcode constants (6:0)
#define OC_LOAD 0b0000011
@@ -109,6 +112,26 @@ static inline uint32_t get_ic(uint32_t ins) {
#define F3_CSRRS 0b10
#define F3_CSRRC 0b11
+// CSR values
+#define CSR_MVENDORID 0xF11
+#define CSR_MARCHID 0xF12
+#define CSR_MIMPID 0xF13
+#define CSR_MHARTID 0xF14
+
+#define CSR_MSTATUS 0x300
+#define CSR_MISA 0x301
+#define CSR_MEDELEG 0x302
+#define CSR_MIDELEG 0x303
+#define CSR_MIE 0x304
+#define CSR_MTVEC 0x305
+#define CSR_MCOUNTEREN 0x306
+
+#define CSR_MSCRATCH 0x340
+#define CSR_MEPC 0x341
+#define CSR_MCAUSE 0x342
+#define CSR_MTVAL 0x343
+#define CSR_MIP 0x344
+
void rvdis(uint32_t pc, uint32_t ins, char *out);
const char* rvregname(uint32_t n);
diff --git a/rvsim.c b/rvsim.c
@@ -89,6 +89,7 @@ void wr8(uint32_t addr, uint32_t val) {
typedef struct {
uint32_t x[32];
uint32_t pc;
+ uint32_t mscratch;
} rvstate_t;
static inline uint32_t rreg(rvstate_t* s, uint32_t n) {
@@ -98,6 +99,21 @@ static inline void wreg(rvstate_t* s, uint32_t n, uint32_t v) {
s->x[n] = v;
}
+static void put_csr(rvstate_t* s, uint32_t csr, uint32_t v) {
+ switch (csr) {
+ case CSR_MSCRATCH:
+ s->mscratch = v;
+ break;
+ }
+}
+static uint32_t get_csr(rvstate_t* s, uint32_t csr) {
+ switch (csr) {
+ case CSR_MSCRATCH:
+ return s->mscratch;
+ default:
+ return 0;
+ }
+}
#define RdR1() rreg(s, get_r1(ins))
#define RdR2() rreg(s, get_r2(ins))
@@ -264,8 +280,35 @@ void rvsim(rvstate_t* s) {
trace_reg_wr(next);
next = pc + get_ij(ins);
break;
- case OC_SYSTEM:
- goto inval;
+ case OC_SYSTEM: {
+ uint32_t fn = get_fn3(ins);
+ if (fn == 0) {
+ goto inval;
+ }
+ uint32_t c = get_iC(ins);
+ uint32_t nv = (fn & 4) ? get_ic(ins) : RdR1();
+ uint32_t ov = 0;
+ switch (fn & 3) {
+ case F3_CSRRW:
+ // only reads of Rd != x0
+ if (get_rd(ins)) ov = get_csr(s, c);
+ put_csr(s, c, nv);
+ break;
+ case F3_CSRRS:
+ // only writes if nv != 0
+ ov = get_csr(s, c);
+ if (nv) put_csr(s, c, ov | nv);
+ WrRd(ov);
+ break;
+ case F3_CSRRC:
+ // only writes if nv != 0
+ ov = get_csr(s, c);
+ if (nv) put_csr(s, c, ov & (~nv));
+ break;
+ }
+ WrRd(ov);
+ break;
+ }
default:
inval:
return;