riscv

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

commit 3292d1830178f0c241f6d33718662d29d04a528a
parent 90a954dd1ca4cce3846c5fde6e7b6c2bc9595e01
Author: Brian Swetland <swetland@frotz.net>
Date:   Sat,  2 Nov 2019 04:36:28 -0700

rvsim: support RV32IM

- add mul and div instructions

Diffstat:
MMakefile | 4++--
Minstab.txt | 8++++++++
Mriscv.h | 32++++++++++++++++++++++----------
Mrvsim.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
4 files changed, 87 insertions(+), 30 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,7 +5,7 @@ CC := $(TOOLCHAIN)gcc OBJDUMP := $(TOOLCHAIN)objdump OBJCOPY := $(TOOLCHAIN)objcopy -CFLAGS := -march=rv32i -mabi=ilp32 -O2 +CFLAGS := -march=rv32i -mabi=ilp32 -O3 CFLAGS += -ffreestanding -nostdlib CFLAGS += -Wl,-Bstatic,-T,simple.ld @@ -27,7 +27,7 @@ out/hello.elf: $(HELLO_SRCS) Makefile RVSIM_SRCS := rvmain.c rvsim.c rvdis.c bin/rvsim: $(RVSIM_SRCS) Makefile gen/instab.h @mkdir -p bin - gcc -O3 -Wall -o $@ $(RVSIM_SRCS) + gcc -g -O3 -Wall -o $@ $(RVSIM_SRCS) bin/mkinstab: mkinstab.c @mkdir -p bin diff --git a/instab.txt b/instab.txt @@ -60,6 +60,14 @@ 0100000----------101-----0110011 sra %d, %1, %2 0000000----------110-----0110011 or %d, %1, %2 0000000----------111-----0110011 and %d, %1, %2 +0000001----------000-----0110011 mul %d, %1, %2 +0000001----------001-----0110011 mulh %d, %1, %2 +0000001----------010-----0110011 mulhsu %d, %1, %2 +0000001----------011-----0110011 mulhu %d, %1, %2 +0000001----------100-----0110011 div %d, %1, %2 +0000001----------101-----0110011 divu %d, %1, %2 +0000001----------110-----0110011 rem %d, %1, %2 +0000001----------111-----0110011 remu %d, %1, %2 -----------------000-----0001111 fence -----------------000-----0001011 _exiti %i -----------------100-----0001011 _exit %1 diff --git a/riscv.h b/riscv.h @@ -52,6 +52,7 @@ static inline uint32_t get_iC(uint32_t ins) { return ins >> 20; } + // opcode constants (6:0) #define OC_LOAD 0b0000011 #define OC_CUSTOM_0 0b0001011 @@ -90,17 +91,28 @@ static inline uint32_t get_iC(uint32_t ins) { #define F3_SW 0b010 // further discrimination of OC_OP (14:12) (fn7==0) -#define F3_ADD 0b0000 -#define F3_SLL 0b0001 -#define F3_SLT 0b0010 -#define F3_SLTU 0b0011 -#define F3_XOR 0b0100 -#define F3_SRL 0b0101 -#define F3_OR 0b0110 -#define F3_AND 0b0111 +#define F3_ADD 0b000 +#define F3_SLL 0b001 +#define F3_SLT 0b010 +#define F3_SLTU 0b011 +#define F3_XOR 0b100 +#define F3_SRL 0b101 +#define F3_OR 0b110 +#define F3_AND 0b111 + // OC_OP (14:12) (fn7==0b0100000) -#define F3_SUB 0b1000 -#define F3_SRA 0b1101 +#define F3_SUB 0b000 +#define F3_SRA 0b101 + +// OC_OP (14:12) (fn7==0b0000001) +#define F3_MUL 0b000 +#define F3_MULH 0b001 +#define F3_MULHSU 0b010 +#define F3_MULHU 0b011 +#define F3_DIV 0b100 +#define F3_DIVU 0b101 +#define F3_REM 0b110 +#define F3_REMU 0b111 // further discrimination of OC_BRANCH #define F3_BEQ 0b000 diff --git a/rvsim.c b/rvsim.c @@ -9,10 +9,10 @@ #include "riscv.h" #include "rvsim.h" -#define DO_TRACE_INS 0 -#define DO_TRACE_TRAPS 0 -#define DO_TRACE_MEM_WR 0 -#define DO_TRACE_REG_WR 0 +#define DO_TRACE_INS 1 +#define DO_TRACE_TRAPS 1 +#define DO_TRACE_MEM_WR 1 +#define DO_TRACE_REG_WR 1 #define RVMEMBASE 0x80000000 #define RVMEMSIZE 32768 @@ -280,20 +280,53 @@ int rvsim_exec(rvstate_t* s, uint32_t _pc) { case OC_OP: { uint32_t a = RdR1(); uint32_t b = RdR2(); - uint32_t n; - if (ins & 0xBE000000) goto inval; - switch (get_fn3(ins) | (ins >> 27)) { - case F3_ADD: n = a + b; break; - case F3_SLL: n = a << (b & 31); break; - case F3_SLT: n = ((int32_t)a) < ((int32_t)b); break; - case F3_SLTU: n = a < b; break; - case F3_XOR: n = a ^ b; break; - case F3_SRL: n = a >> (b & 31); break; - case F3_OR: n = a | b; break; - case F3_AND: n = a & b; break; - case F3_SUB: n = a - b; break; - case F3_SRA: n = ((int32_t)a) >> (b & 31); break; - default: goto inval; + uint32_t n = get_fn3(ins); + switch (ins >> 25) { + case 0b0000000: + switch (n) { + case F3_ADD: n = a + b; break; + case F3_SLL: n = a << (b & 31); break; + case F3_SLT: n = ((int32_t)a) < ((int32_t)b); break; + case F3_SLTU: n = a < b; break; + case F3_XOR: n = a ^ b; break; + case F3_SRL: n = a >> (b & 31); break; + case F3_OR: n = a | b; break; + case F3_AND: n = a & b; break; + } + break; + case 0b0000001: + switch (n) { + case F3_MUL: n = a * b; break; + case F3_MULH: n = ((int64_t)(int32_t)a * (int64_t)(int32_t)b) >> 32; break; + case F3_MULHSU: n = ((int64_t)(int32_t)a * (uint64_t)b) >> 32; break; + case F3_MULHU: n = ((uint64_t)a * (uint64_t)b) >> 32; break; + case F3_DIV: + if (b == 0) { n = 0xffffffff; } + else if ((a == 0x80000000) && (b == 0xffffffff)) { n = a; } + else { n = ((int32_t)a / (int32_t)b); } + break; + case F3_DIVU: + if (b == 0) { n = 0xffffffff; } + else { n = a / b; } + break; + case F3_REM: + if (b == 0) { n = a; } + else if ((a == 0x80000000) && (b == 0xffffffff)) { n = 0; } + else { n = ((int32_t)a % (int32_t)b); } + break; + case F3_REMU: + if (b == 0) { n = a; } + else { n = a % b; } + break; + } + break; + case 0b0100000: + switch (n) { + case F3_SUB: n = a - b; break; + case F3_SRA: n = ((int32_t)a) >> (b & 31); break; + default: goto inval; + } + break; } WrRd(n); trace_reg_wr(n); @@ -392,6 +425,10 @@ trap_pc_align: inval: s->mcause = EC_I_ILLEGAL; s->mtval = ins; +#if DO_ABORT_INVAL + fprintf(stderr," (TRAP ILLEGAL %08x)\n", ins); + return -1; +#endif trap_common: s->mepc = pc; next = s->mtvec & 0xFFFFFFFD;