commit feb123c9c5c8b0cdcee6cb11bcf14344a44adf98
parent 2960ee19a669a70430c0ccdb7b21ec3b2f4f5729
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date: Sat, 5 Sep 2026 23:09:56 +0300
Added store/load checks and traps
Diffstat:
| M | exec.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
| M | exec.h | | | 2 | +- |
| M | main.c | | | 12 | ++++++++++++ |
| M | trap.h | | | 2 | -- |
4 files changed, 72 insertions(+), 7 deletions(-)
diff --git a/exec.c b/exec.c
@@ -216,13 +216,38 @@ static void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
uint32_t x;
switch(i.funct3) {
case 0x0:
+ if (addr > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_LOAD_ACCESS_FAULT, inst);
+ return;
+ }
+
x = (uint32_t)(int32_t)(int8_t)mem[addr];
break;
case 0x1:
+ if ((addr & UINT32_C(0x1)) != 0) {
+ raise_trap(cpu, TRAP_LOAD_MISALIGNED, inst);
+ return;
+ }
+
+ if (addr + 1 > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_LOAD_ACCESS_FAULT, inst);
+ return;
+ }
+
uint16_t half = (uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8);
x = (uint32_t)(int32_t)(int16_t)half;
break;
case 0x2:
+ if ((addr & UINT32_C(0x3)) != 0) {
+ raise_trap(cpu, TRAP_LOAD_MISALIGNED, inst);
+ return;
+ }
+
+ if (addr + 3 > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_LOAD_ACCESS_FAULT, inst);
+ return;
+ }
+
/* TODO: clean up */
x = (uint32_t)(int32_t)(
((uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8))
@@ -232,9 +257,24 @@ static void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
);
break;
case 0x4:
+ if (addr > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_LOAD_ACCESS_FAULT, inst);
+ return;
+ }
+
x = (uint32_t)(uint8_t)mem[addr];
break;
case 0x5:
+ if ((addr & UINT32_C(0x1)) != 0) {
+ raise_trap(cpu, TRAP_LOAD_MISALIGNED, inst);
+ return;
+ }
+
+ if (addr + 1 > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_LOAD_ACCESS_FAULT, inst);
+ return;
+ }
+
uint16_t uhalf = (uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8);
x = (uint32_t)uhalf;
break;
@@ -258,11 +298,21 @@ static void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
/* TODO: helpers, better checks */
switch(s.funct3) {
case 0x0:
+ if (addr > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_STORE_ACCESS_FAULT, inst);
+ return;
+ }
+
mem[addr] = cpu->x[s.rs2] & 255;
break;
case 0x1:
- if (addr+1 > MEMSIZE-1) {
- fprintf(stderr, "Illegal addr\n");
+ if ((addr & UINT32_C(0x1)) != 0) {
+ raise_trap(cpu, TRAP_STORE_MISALIGNED, inst);
+ return;
+ }
+
+ if (addr + 1 > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_STORE_ACCESS_FAULT, inst);
return;
}
@@ -272,8 +322,13 @@ static void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
}
break;
case 0x2:
- if (addr+3 > MEMSIZE-1) {
- fprintf(stderr, "Illegal addr\n");
+ if ((addr & UINT32_C(0x3)) != 0) {
+ raise_trap(cpu, TRAP_STORE_MISALIGNED, inst);
+ return;
+ }
+
+ if (addr + 3 > MEMSIZE - 1) {
+ raise_trap(cpu, TRAP_STORE_ACCESS_FAULT, inst);
return;
}
if (addr % 4 == 0) {
diff --git a/exec.h b/exec.h
@@ -3,7 +3,7 @@
#include "trap.h"
-#define MEMSIZE 4128
+#define MEMSIZE 4096
typedef enum {
CPU_RUNNING = 0,
diff --git a/main.c b/main.c
@@ -75,6 +75,18 @@ trap_handler(cpu_state_t *cpu)
case TRAP_INSTRUCTION_ACCESS_FAULT:
printf("Instruction access fault\n");
break;
+ case TRAP_LOAD_MISALIGNED:
+ printf("Load misaligned\n");
+ break;
+ case TRAP_LOAD_ACCESS_FAULT:
+ printf("Load access fault\n");
+ break;
+ case TRAP_STORE_MISALIGNED:
+ printf("Store misaligned\n");
+ break;
+ case TRAP_STORE_ACCESS_FAULT:
+ printf("Store access fault\n");
+ break;
case TRAP_NONE:
printf("No trap cause\n");
break;
diff --git a/trap.h b/trap.h
@@ -8,12 +8,10 @@ typedef enum {
TRAP_ILLEGAL_INSTRUCTION,
TRAP_INSTRUCTION_MISALIGNED,
TRAP_INSTRUCTION_ACCESS_FAULT,
-/*
TRAP_LOAD_MISALIGNED,
TRAP_LOAD_ACCESS_FAULT,
TRAP_STORE_MISALIGNED,
TRAP_STORE_ACCESS_FAULT
-*/
} trap_cause_t;
typedef struct {