commit - 1029a1177da1c59d6d27ba7c5dd653202c0ce313
commit + c8a2c51f80c364d04ff8b86b55c8fa0444ab1391
blob - /dev/null
blob + dd689e20d4964ff3c5f13cea619551d57872c0e8 (mode 644)
--- /dev/null
+++ rvvm/rvhart.c
+#include <err.h>
+#include <stdint.h>
+
+#include "rvhart.h"
+#include "rvram.h"
+
+struct rv_instr
+rv_decode(uint32_t word)
+{
+ struct rv_instr i;
+
+ i = {0};
+ i.opcode = word & 0x7f;
+ i.rd = (word >> 7) & 0x1f;
+ i.rs1 = (word >> 15) & 0x1f;
+ i.rs2 = (word >> 20) & 0x1f;
+ i.funct3 = (word >> 12) & 0x7;
+ i.funct7 = (word >> 25) & 0x7f;
+
+ switch (i.opcode) {
+ case 0x33:
+ i.fmt = R_FMT;
+ break;
+ case 0x13:
+ case 0x03:
+ case 0x67:
+ case 0x73:
+ i.fmt = I_FMT;
+ i.imm = SE(word >> 20, 12);
+ break;
+ case 0x23:
+ i.fmt = S_FMT;
+ i.imm = SE((((word >> 25) & 0x7f) << 5) | ((word >> 7) & 0x1f), 12);
+ break;
+ case 0x63:
+ i.fmt = B_FMT;
+ i.imm = SE(((word & 0x80000000) >> 19) |
+ ((word & 0x00000080) << 4) |
+ ((word & 0x7e000000) >> 20) |
+ ((word & 0x00000f00) >> 7),
+ 13);
+ break;
+ case 0x37:
+ case 0x17:
+ i.fmt = U_FMT;
+ i.imm = SE(word >> 12, 20) << 12;
+ break;
+ case 0x6f:
+ i.fmt = J_FMT;
+ i.imm = SE(((word & 0x80000000) >> 11) |
+ (word & 0x000ff000) |
+ ((word & 0x00100000) >> 9) |
+ ((word & 0x7fe00000) >> 20),
+ 21);
+ break;
+ default:
+ err(1, "rv_decode(): unknown opcode %x", i.opcode);
+ }
+
+ return (i);
+}
+
+void
+rv_execute(struct rv_hart *h, struct rv_ram *m, struct rv_instr i)
+{
+ uint64_t next_pc = h->pc + RV_STEP_SIZE;
+
+ switch (i.opcode) {
+ // TODO: Implement execution logic.
+ default:
+ err(1, "rv_execute(): unknown opcode %x", i.opcode);
+ }
+
+ h->rfile[0] = 0;
+ h->pc = next_pc;
+}
+
+void
+rv_step(struct rv_hart *h, struct rv_ram *m) {
+ uint32_t word;
+ struct rv_instr i;
+
+ word = (uint32_t)rv_ram_read(m, h->pc);
+ i = rv_decode(word);
+ rv_execute(h, i);
+}
blob - /dev/null
blob + dc3aee9e339cb3ba5f080fc76655ebe2ce253379 (mode 644)
--- /dev/null
+++ rvvm/rvhart.h
+#ifndef _RVHART_H_
+#define _RVHART_H_
+
+#include <stdint.h>
+
+#include "rvram.h"
+
+#define RV_RFILE_SIZE 32
+#define RV_STEP_SIZE 4
+
+#define SE(val, bits) (((int64_t)(val) << (64 - (bits))) >> (64 - (bits)))
+
+enum rv_instrfmt {
+ R_FMT,
+ I_FMT,
+ S_FMT,
+ B_FMT,
+ U_FMT,
+ J_FMT
+};
+
+struct rv_instr {
+ enum rv_instrfmt fmt;
+ uint8_t opcode;
+ uint8_t rd;
+ uint8_t rs1;
+ uint8_t rs2;
+ uint8_t funct3;
+ uint8_t funct7;
+ int64_t imm;
+};
+
+struct rv_hart {
+ uint64_t pc;
+ uint64_t rfile[RV_RFILE_SIZE];
+};
+
+struct rv_instr rv_decode(uint32_t word);
+void rv_execute(struct rv_hart *h, struct rv_ram *m, struct rv_instr i);
+void rv_step(struct rv_hart *h, struct rv_ram *m);
+#endif