Commit Diff


commit - f0641b653b40f7b88979351e4bc56a32816ef84e
commit + d355a3cd49599ad11a27e39768a744d7bff86154
blob - c2068da3cd85736b579c59c2db99a0c031bf4e85
blob + 51a56ec2de32959b9d7afa52c129b70dc937538b
--- rvvm/rvhart.c
+++ rvvm/rvhart.c
@@ -3,13 +3,13 @@
 
 #include "rvhart.h"
 #include "rvram.h"
+#include "rvhandler.h"
 
 struct rv_instr
 rv_decode(uint32_t word)
 {
-	struct rv_instr	i;
+	struct rv_instr	i = {0};
 
-	i		= {0};
 	i.opcode	= word & 0x7f;
 	i.rd		= (word >> 7) & 0x1f;
 	i.rs1		= (word >> 15) & 0x1f;
@@ -63,55 +63,28 @@ rv_decode(uint32_t word)
 void
 rv_execute(struct rv_hart *h, struct rv_ram *m, struct rv_instr i)
 {
-	uint64_t 	next_pc = h->pc + RV_STEP_SIZE;
+	uint8_t idx;
+	uint8_t funct7_bit;
+	rv_handler handler;
+	
+	funct7_bit	= (i.funct7 >> 5) & 0x1;
+	idx		= (funct7_bit << 8) | ((i.opcode >> 2) << 3) | i.funct3;
+	handler		= jump_table[idx];
 
-	switch (i.opcode) {
-	case 0x13:
-		switch (i.funct3) {
-		case 0x0: // ADDI
-			h->rfile[i.rd] = h->rfile[i.rs1] + i.imm;
-			break;
-		case 0x4: // XORI
-			h->rfile[i.rd] = h-rfile[i.rs1] ^ i.imm;
-			break;
-		case 0x6: // ORI
-			h->rfile[i.rd] = h->rfile[i.rs1] | i.imm;
-			break;
-		case 0x7: // ANDI
-			h->rfile[i.rd] = h->rfile[i.rs1] & i.imm;
-			break;
-		default:
-			err(1, "rv_execute(): unknown funct3 %x for OP-IMM", i.funct3);
-		}
-		break;
-	case 0x33:
-		switch (i.funct3) {
-		case 0x0:
-			if (i.funct7 == 0x20)
-				h->rfile[i.rd] = h->rfile[i.rs1] - h->rfile[i.rs2];
-			else
-				h->rfile[i.rd] = h->rfile[i.rs1] + h->rfile[i.rs2];
-			break;
-		case 0x7:
-			h->rfile[i.rd] = h->rfile[i.rs1] & h->rfile[i.rs2];
-			break;
-		default:
-			err(1, "rv_execute(): unknown funct3 %x for OP", i.funct3);
-		}
-		break;
-	case 0x37: // LUI
-		h->rfile[i.rd] = i.imm;
-		break;
-	default:
-		err(1, "rv_execute(): unknown opcode %x", i.opcode);
-	}
+	h->next_pc = h->pc + RV_STEP_SIZE; 
+
+	if (rv_handler_lookup_table[idx])
+		rv_handler_lookup_table[idx](h, i);
+	else
+		errx(1, "rv_execute(): unknown instruction: op=0x%x, funct3=0x%x", i.opcode, i.funct3);
 	
 	h->rfile[0]	= 0;
-	h->pc		= next_pc;
+	h->pc		= h->next_pc;
 }
 
 void
-rv_step(struct rv_hart *h, struct rv_ram *m) {
+rv_step(struct rv_hart *h, struct rv_ram *m)
+{
 	uint32_t	word;
 	struct rv_instr	i;
 	
@@ -119,3 +92,14 @@ rv_step(struct rv_hart *h, struct rv_ram *m) {
 	i 	= rv_decode(word);
 	rv_execute(h, m, i);
 }
+
+void
+rv_simple_step(struct rv_hart *h, uint32_t *prog)
+{
+	uint32_t	word;
+	struct rv_instr	i;
+
+	word	= prog[h->pc / RV_STEP_SIZE];
+	i	= rv_decode(word);
+	rv_execute(h, NULL, i);
+}
blob - /dev/null
blob + 758e9bd133624527bd2988b1e37dfbe8183d51a9 (mode 644)
--- /dev/null
+++ rvvm/rvhandler.c
@@ -0,0 +1,4 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include "rvhandler.h"
blob - dc3aee9e339cb3ba5f080fc76655ebe2ce253379
blob + 3d24458936cf5f2198dc1e4fa0ea097fd5af06bd
--- rvvm/rvhart.h
+++ rvvm/rvhart.h
@@ -32,6 +32,7 @@ struct rv_instr {
 
 struct rv_hart {
 	uint64_t pc;
+	uint64_t next_pc;
 	uint64_t rfile[RV_RFILE_SIZE];
 };
 
blob - /dev/null
blob + 11683da307fb8ee7a22722c04b0658b12abed16b (mode 644)
--- /dev/null
+++ rvvm/rvhandler.h
@@ -0,0 +1,58 @@
+#ifndef _RVHANDLER_H_
+#define _RVHANDLER_H_
+typedef void (*rv_handler)(struct rv_hart *h, struct rv_ram *m, struct rv_instr i);
+
+#define RV_IDX(funct7_bit, opcode, funct3) ((((uint16_t)(funct7_bit)) << 8) | (((opcode) >> 2) << 3) | (funct3))
+
+void	exec_addi(struct rv_hart *h, struct rv_instr i);
+void	exec_xori(struct rv_hart *h, struct rv_instr i);
+void	exec_ori(struct rv_hart *h, struct rv_instr i);
+void	exec_andi(struct rv_hart *h, struct rv_instr i);
+void	exec_slli(struct rv_hart *h, struct rv_instr i);
+void	exec_srli(struct rv_hart *h, struct rv_instr i);
+void	exec_srai(struct rv_hart *h, struct rv_instr i);
+
+void	exec_add(struct rv_hart *h, struct rv_instr i);
+void	exec_sub(struct rv_hart *h, struct rv_instr i);
+void	exec_and(struct rv_hart *h, struct rv_instr i);
+void	exec_or(struct rv_hart *h, struct rv_instr i);
+void	exec_xor(struct rv_hart *h, struct rv_instr i);
+
+void	exec_beq(struct rv_hart *h, struct rv_instr i);
+void	exec_bne(struct rv_hart *h, struct rv_instr i);
+
+void	exec_ld(struct rv_hart *h, struct rv_instr i);
+void	exec_sd(struct rv_hart *h, struct rv_instr i);
+
+void	exec_lui(struct rv_hart *h, struct rv_instr i);
+void	exec_auipc(struct rv_hart *h, struct rv_instr i);
+void	exec_jal(struct rv_hart *h, struct rv_instr i);
+void	exec_jalr(struct rv_hart *h, struct rv_instr i);
+
+static const rv_handler rv_handler_lookup_table[512] = {
+	[RV_IDX(0, 0x13, 0x0)] = exec_addi,
+	[RV_IDX(0, 0x13, 0x4)] = exec_xori,
+	[RV_IDX(0, 0x13, 0x6)] = exec_ori,
+	[RV_IDX(0, 0x13, 0x7)] = exec_andi,
+	[RV_IDX(0, 0x13, 0x1)] = exec_slli,
+	[RV_IDX(0, 0x13, 0x5)] = exec_srli,
+	[RV_IDX(1, 0x13, 0x5)] = exec_srai,
+
+	[RV_IDX(0, 0x33, 0x0)] = exec_add,
+	[RV_IDX(1, 0x33, 0x0)] = exec_sub,
+	[RV_IDX(0, 0x33, 0x7)] = exec_and,
+	[RV_IDX(0, 0x33, 0x6)] = exec_or,
+	[RV_IDX(0, 0x33, 0x4)] = exec_xor,
+
+	[RV_IDX(0, 0x63, 0x0)] = exec_beq,
+	[RV_IDX(0, 0x63, 0x1)] = exec_bne,
+
+	[RV_IDX(0, 0x03, 0x3)] = exec_ld,
+	[RV_IDX(0, 0x23, 0x3)] = exec_sd,
+
+	[RV_IDX(0, 0x37, 0x0)] = exec_lui,
+	[RV_IDX(0, 0x17, 0x0)] = exec_auipc,
+	[RV_IDX(0, 0x6f, 0x0)] = exec_jal,
+	[RV_IDX(0, 0x67, 0x0)] = exec_jalr,
+};
+#endif