rvemu

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Mmain.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;