commit d355a3cd49599ad11a27e39768a744d7bff86154 from: Gleb Nesterov date: Sun Mar 22 15:25:37 2026 UTC Refactor rv_execute in rvhart.c 1. Add rv_handler for handling CPU instructions 2. Add rv_handler_lookup_table for search rv_handler functions in rv_execute 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 +#include + +#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