rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

commit 51338a4f65ca4f32e7c62461d0b0c59ea670af1c
parent e2aa4903fefda539540b4dc39619291196c02159
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date:   Wed,  2 Sep 2026 16:26:51 +0300

Added jump address and 0 reg invariance checks

Diffstat:
Mmain.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 61 insertions(+), 17 deletions(-)

diff --git a/main.c b/main.c @@ -33,18 +33,39 @@ static inline void print_binless(uint32_t x, int a) { } } -static int32_t get_valid_branch_target(uint32_t pc, int32_t offset, uint32_t *target) +static inline int is_instruction_address_valid(int64_t addr) { - int64_t candidate = (int64_t)pc + (int64_t)offset; - - if (candidate < 0) - return -1; + if (addr < 0) + return 0; - if (candidate > (int64_t)MEMSIZE-4) - return -1; + if (addr > (int64_t)MEMSIZE-4) + return 0; - if ((candidate & 0x3) != 0) - return -1; + if ((addr & 0x3) != 0) + return 0; + + return 1; +} + +static int32_t get_valid_branch_target(uint32_t pc, int32_t offset, + uint32_t *target) +{ + int64_t candidate = (int64_t)pc + (int64_t)offset; + if (!is_instruction_address_valid(candidate)) + return 1; + + *target = (uint32_t)candidate; + + return 0; +} + +static int32_t get_valid_jalr_target(uint32_t base, int32_t offset, + uint32_t *target) +{ + int64_t candidate = ((int64_t)base + (int64_t)offset) + & ~INT64_C(1); + if (!is_instruction_address_valid(candidate)) + return 1; *target = (uint32_t)candidate; return 0; @@ -460,16 +481,25 @@ static void exec_itype_jalr(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { /*********/ uint32_t x; - if (i.funct3 == 0x0) { - x = cpu->pc + 4; - cpu->pc = i.rs1 + i.imm; - } else { + if (i.funct3 != 0x0) { fprintf(stderr, "Illegal funct3\n"); + return; + } + + x = cpu->pc + 4; + + uint32_t target; + if (get_valid_jalr_target(cpu->x[i.rs1], i.imm, &target) == 0) { + cpu->pc = target; + } else { + fprintf(stderr, "Illegal branch target: base=%" + PRIu32 ", offset=%" PRId32 "\n", + cpu->x[i.rs1], i.imm); + return; } printf("rs1:%u imm:%u rd:%u\n",cpu->x[i.rs1],i.imm,cpu->x[i.rd]); if (i.rd != 0) { - /* TODO: calculate & check addr */ cpu->x[i.rd] = x; } @@ -494,9 +524,18 @@ static void exec_jtype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { x = cpu->pc + 4; cpu->pc += j.imm; + uint32_t target; + if (get_valid_branch_target(cpu->pc, (int32_t)j.imm, &target) == 0) { + cpu->pc = target; + } else { + fprintf(stderr, "Illegal branch target: base=%" + PRIu32 ", offset=%" PRId32 "\n", + cpu->pc, j.imm); + return; + } + printf("imm:%u rd:%u\n",j.imm,cpu->x[j.rd]); if (j.rd != 0) { - /* TODO: calculate & check addr */ cpu->x[j.rd] = x; } @@ -517,9 +556,12 @@ static void exec_utype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { printf("\n"); /*********/ - cpu->x[u.rd] = u.imm << 12; + if (u.rd != 0) + cpu->x[u.rd] = u.imm << 12; + cpu->pc += 4; + printf("rd:%u\n", cpu->x[u.rd]); printf("rd:%x\n", cpu->x[u.rd]); } @@ -538,7 +580,9 @@ static void exec_utype_auipc(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { printf("\n"); /*********/ - cpu->x[u.rd] = cpu->pc + (u.imm << 12); + if (u.rd != 0) + cpu->x[u.rd] = cpu->pc + (u.imm << 12); + cpu->pc += 4; printf("rd:%u\n", cpu->x[u.rd]);