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:
| M | main.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]);