riscv

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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:
Mriscv.h | 23+++++++++++++++++++++++
Mrvsim.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;