commit 58dc93d516ee655d43250e283d455b3e59e7f12b
parent 57eaef5ec609fa7e243fca6494754866004db66b
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date: Fri, 24 Jul 2026 00:04:54 +0300
Branch target calculation and bug fix
Diffstat:
| M | main.c | | | 207 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
1 file changed, 96 insertions(+), 111 deletions(-)
diff --git a/main.c b/main.c
@@ -1,4 +1,5 @@
#include <stdint.h>
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,6 +32,13 @@ typedef struct {
uint8_t funct3;
} stype_t;
+typedef struct {
+ uint8_t opcode;
+ uint8_t rs1, rs2;
+ int16_t imm;
+ uint8_t funct3;
+} btype_t;
+
void print_bin16(uint16_t x) {
for (int i = 15; i >= 0; i--) {
putchar((x >> i) & 1 ? '1' : '0');
@@ -50,6 +58,23 @@ void print_binless(uint32_t x, int a) {
}
}
+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 (candidate < 0)
+ return -1;
+
+ if (candidate > (int64_t)MEMSIZE-4)
+ return -1;
+
+ if ((candidate & 0x3) != 0)
+ return -1;
+
+ *target = (uint32_t)candidate;
+ return 0;
+}
+
/*
I-TYPE INSTRUCTION FORMAT
31 20 19 15 14 12 11 7 6 0
@@ -414,22 +439,28 @@ B-TYPE INSTRUCTION FORMAT
+---------------+--------+--------+--------+------------+--------+
| imm[12|10:5] | rs2 | rs1 | funct3 |imm[4:1|11] | opcode |
+---------------+--------+--------+--------+------------+--------+
-opcode 0x63 1100010
+opcode 0x63 1100011
*/
void exec_btype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
+ (void)mem; /* suppressing unused parameters warning */
printf("TYPE B\n");
- stype_t b;
+ btype_t b;
uint32_t imm_10_5 = (inst >> 25) & 63;
uint32_t imm_11 = (inst >> 7) & 1;
uint32_t imm_4_1 = (inst >> 8) & 15;
uint32_t imm_12 = (inst >> 31) & 1;
- b.imm = 0 | (imm_4_1 << 1) | (imm_10_5 << 5) | (imm_11 << 11) | (imm_12 << 12);
+
+ /**/uint32_t raw_imm = (imm_12 << 12) | (imm_11 << 11) | (imm_10_5 << 5) | (imm_4_1 << 1);
+ /**/if (raw_imm & (1U << 12))
+ /**/ raw_imm |= 0xffffe000U;
+ b.imm = (int32_t)(0 | (imm_4_1 << 1) | (imm_10_5 << 5) | (imm_11 << 11) | (imm_12 << 12));
b.funct3 = (inst >> 12) & 7;
b.rs1 = (inst >> 15) & 31;
b.rs2 = (inst >> 20) & 31;
+ /**/printf("imm: %" PRId32 "\n", b.imm);
printf("\nimm:%x\n", b.imm);
/**print**/
@@ -449,19 +480,25 @@ void exec_btype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
printf("\n");
/*********/
- printf("PC:%d\n", cpu->pc);
+ //printf("PC:%d\n", cpu->pc);
+ /**/printf("PC before: %" PRIu32 "\n", cpu->pc);
switch (b.funct3) {
case 0x0:
if (cpu->x[b.rs1] == cpu->x[b.rs2]) {
- if (b.imm >= MEMSIZE) {
- fprintf(stderr, "Illegal address\n");
+ uint32_t target;
+ if (get_valid_branch_target(cpu->pc, b.imm, &target) != 0) {
+ //fprintf(stderr, "Illegal branch target\n");
+ /**/fprintf(stderr, "Illegal BEQ target: pc=%" PRIu32 ", offset=%" PRId32 "\n", cpu->pc, b.imm);
return;
}
- cpu->pc += b.imm;
+ cpu->pc = target;
}
+ case 0x0:
}
- printf("PC:%d\n", cpu->pc);
+ //printf("PC:%d\n", cpu->pc);
+ /**/printf("PC after: %" PRIu32 "\n", cpu->pc);
+
}
int main() {
@@ -478,122 +515,70 @@ int main() {
/*opcode_table[0x13] = exec_rtype_imm;
opcode_table[0x73] = exec_system;*/
-
- /*0000000111110000011100000110011*/
- //uint32_t inst = 0x01F07033;
- /*0000000111110000000000000110011*/
- uint32_t inst = 0x01F00033;
-
- // f7 rs2 rs1 f3 rd opcode
- // 0000000 00001 00010 000 00011 0110011
- inst = 0x00110033; /* failed add because rd=0 */
-
- // f7 rs2 rs1 f3 rd opcode
- // 0000000 00001 00010 000 00011 0110011
- inst = 0x001101B3; /* successful add */
-
- // f7 rs2 rs1 f3 rd opcode
- // 0100000 00001 00010 000 00011 0110011
- inst = 0x401101B3; /* successful sub */
-
- // f7 rs2 rs1 f3 rd opcode
- // 0000000 00001 00010 011 00011 0110011
- inst = 0x1131B3; /* SLT */
-
- // f7 rs2 rs1 f3 rd opcode
- // 0000000 00001 00010 100 00011 0110011
- inst = 0x1141B3; /* XOR */
-
- // imm rs1 f3 rd opcode
- // 000000000101 00010 000 00011 0010011
- inst = 0x510193; /* ADDi 5 */
-
- // imm rs1 f3 rd opcode
- // 000000000101 00010 111 00011 0010011
- inst = 0x517193; /* ANDi 101 */
-
- // imm rs1 f3 rd opcode
- // 000000000001 00010 101 00011 0010011
- inst = 0x115193; /* shift logical right i 1*/
-
- // imm rs1 f3 rd opcode
- // 011111111111 00000 000 00011 0000011
- inst = 0x100183; /* LOAD Byte from address 0x3*/
-
- // imm rs1 f3 rd opcode
- // 000000000000 00000 001 00011 0000011
- inst = 0x1183; /* LOAD half from address 0x0*/
-
- // imm rs1 f3 rd opcode
- // 000000000000 00000 010 00011 0000011
- inst = 0x2183; /* LOAD word from address 0x0*/
-
- // imm rs1 rs2 f3 imm opcode
- // [11:5] [4:0]
- // 0000000 00000 00000 000 00000 0100011
- inst = 0x23; /* STORE rs2 contents to mem 0x0*/
-
- // imm rs2 rs1 f3 imm opcode
- // [11:5] [4:0]
- // 0000000 00000 00000 000 00010 0100011
- inst = 0xA3; /* STORE rs2 contents to mem 0x0*/
-
- // imm rs2 rs1 f3 imm opcode
- // [11:5] [4:0]
- // 0000000 00000 00000 010 00100 0100011
- inst = 0x2223; /* STORE rs2 contents to mem 0x04 (word)*/
-
- // imm rs2 rs1 f3 imm opcode
- // [11:5] [4:0]
- // 0000000 00000 00000 010 00011 0100011
- inst = 0x21A3; /* STORE rs2 contents to mem 0x03, FAIL (word)*/
-
- // imm rs2 rs1 f3 imm opcode
- // [12|10:5] [4:1|11]
- // 0000000 00000 00000 000 00010 1100011
- inst = 0x163; /* branch to 2 if rs1 == rs2*/
-
- print_bin32(inst);
- printf("\n");
-
- /* decode instruction */
- uint16_t opcode = inst & 127;
- printf("opcode: ");
- print_binless(opcode,7);
- printf("\n");
-
- exec_fn fn = opcode_table[opcode];
-
/* init cpu state */
cpu_state_t cpu;
for (int i=0; i<32; i++) {
cpu.x[i] = 0;
}
cpu.pc = 0;
- /* */
-
- cpu.x[1] = 51;
- cpu.x[2] = 00;
-
uint8_t mem[MEMSIZE] = {0};
+
/* set mem for test */
for (int i=0; i<2056; i++) {
- mem[i] = (uint8_t)i;
- }
- for (int i=0; i<32; i++) {
- printf("0x%x: 0x%x\n", i, mem[i]);
+ mem[i] = (uint8_t)0; //i;
}
+ /* PROGRAM */
+ uint32_t arr[] = {
+ 0x500193,
+ 0x600093,
+ 0x118263,
+ 0x728263
+ };
+ size_t len = sizeof(arr) / sizeof(arr[0]);
+
+ /* fetch & run */
+ for (size_t i = 0; i < len; i++) {
+ /*printf("\n>");
+ scanf("%s\n", &a);
+ char line[256];
+ int i;
+ if (fgets(line, sizeof(line), stdin)) {
+
+
+ }*/
+
+ /* execute next instruction */
+ uint32_t inst = arr[i];
+
+ printf("------------INST%d------\n", i);
+ print_bin32(inst);
+ printf("\n");
+
+ /* decode opcode */
+ uint16_t opcode = inst & 127;
+ printf("opcode: ");
+ print_binless(opcode,7);
+ printf("\n");
+
+ exec_fn fn = opcode_table[opcode];
+
+ if (!fn) {
+ //illegal(NULL, inst);
+ fprintf(stderr, "Illegal opcode\n");
+ return EXIT_FAILURE;
+ }
- if (!fn) {
- //illegal(NULL, inst);
- fprintf(stderr, "Illegal opcode\n");
- return EXIT_FAILURE;
- }
+ fn(&cpu,inst,mem);
+ //printf("Memory:\n");
+ //for (int i=0; i<32; i++) {
+ // printf("0x%x: 0x%x\n", i, mem[i]);
+ //}
- fn(&cpu,inst,mem);
- for (int i=0; i<32; i++) {
- printf("0x%x: 0x%x\n", i, mem[i]);
+ printf("Registers:\n");
+ for (int i=0; i<32; i++) {
+ printf("0x%x: 0x%x\n", i, cpu.x[i]);
+ }
}
return 0;