rvemu

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

commit 01f7641b70f741df2279b57364a784bded02bb0b
parent 5b14406c061bd7ba6193feba733e2eb8650598bc
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date:   Thu, 27 Aug 2026 17:24:51 +0300

Added jumps, strict compiling & fixed warnings

Diffstat:
MMakefile | 6+++++-
Mdecode.h | 48+++++++++++++++++++++++++++++++++++-------------
Mmain.c | 111++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 131 insertions(+), 34 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,2 +1,6 @@ all: - gcc -g main.c + gcc -g main.c \ + -Wall -Wextra -Wpedantic \ + -Wconversion -Wsign-conversion \ + -Wshadow -Wstrict-prototypes \ + -Wmissing-prototypes -Wformat=2 diff --git a/decode.h b/decode.h @@ -22,13 +22,13 @@ typedef struct { static inline void decode_itype(itype_t *i, uint32_t inst) { - i->rd = (inst >> 7) & 31; - i->funct3 = (inst >> 12) & 7; - i->rs1 = (inst >> 15) & 31; - i->imm = (inst >> 20) & 2047; + i->rd = (uint8_t)((inst >> 7) & 31); + i->funct3 = (uint8_t)((inst >> 12) & 7); + i->rs1 = (uint8_t)((inst >> 15) & 31); + i->imm = (uint16_t)((inst >> 20) & 2047); - i->inimm = i->imm & 31; - i->funct7 = (i->imm >> 5) & 127; + i->inimm = (uint8_t)(i->imm & 31); + i->funct7 = (uint8_t)((i->imm >> 5) & 127); } /* @@ -49,11 +49,11 @@ typedef struct { static inline void decode_rtype(rtype_t *r, uint32_t inst) { - r->rd = (inst >> 7) & 31; - r->funct3 = (inst >> 12) & 7; - r->rs1 = (inst >> 15) & 31; - r->rs2 = (inst >> 20) & 31; - r->funct7 = (inst >> 25) & 127; + r->rd = (uint8_t)((inst >> 7) & 31); + r->funct3 = (uint8_t)((inst >> 12) & 7); + r->rs1 = (uint8_t)((inst >> 15) & 31); + r->rs2 = (uint8_t)((inst >> 20) & 31); + r->funct7 = (uint8_t)((inst >> 25) & 127); } /* @@ -77,7 +77,7 @@ decode_stype(stype_t *s, uint32_t inst) { uint32_t imm_11_5 = (inst >> 25) & 127; uint32_t imm_4_0 = (inst >> 7) & 31; - s->imm = (imm_4_0) | (imm_11_5 << 5); + s->imm = (uint16_t)((imm_4_0) | (imm_11_5 << 5)); s->funct3 = (inst >> 12) & 7; s->rs1 = (inst >> 15) & 31; @@ -111,11 +111,33 @@ decode_btype(btype_t *b, uint32_t inst) (imm_10_5 << 5) | (imm_4_1 << 1); if (raw_imm & (1U << 12)) raw_imm |= 0xffffe000U; - b->imm = (int32_t)raw_imm; + b->imm = (int16_t)raw_imm; b->funct3 = (inst >> 12) & 7; b->rs1 = (inst >> 15) & 31; b->rs2 = (inst >> 20) & 31; } +/* +J-TYPE INSTRUCTION FORMAT +31 12 11 7 6 0 ++---------------------------------------+---------+--------+ +| imm[31:12] | rd | opcode | ++---------------------------------------+---------+--------+ +opcode 0x13 0010011 immediates +*/ + +typedef struct { + uint8_t opcode; + uint8_t rd, rs1; + uint32_t imm; +} jtype_t; + +static inline void +decode_jtype(jtype_t *j, uint32_t inst) +{ + j->rd = (uint8_t)((inst >> 7) & 31); + j->imm = (uint32_t)((inst >> 11) & 0xfffff); +} + #endif diff --git a/main.c b/main.c @@ -14,20 +14,20 @@ typedef struct { uint32_t pc; } cpu_state_t; -void print_bin16(uint16_t x) { +static inline void print_bin16(uint16_t x) { for (int i = 15; i >= 0; i--) { putchar((x >> i) & 1 ? '1' : '0'); /*if (i % 4 == 0) putchar(' '); grouping */ } } -void print_bin32(uint32_t x) { +static inline void print_bin32(uint32_t x) { for (int i = 31; i >= 0; i--) { putchar((x >> i) & 1 ? '1' : '0'); } } -void print_binless(uint32_t x, int a) { +static inline void print_binless(uint32_t x, int a) { for (int i = a-1; i >= 0; i--) { putchar((x >> i) & 1 ? '1' : '0'); } @@ -50,7 +50,8 @@ static int32_t get_valid_branch_target(uint32_t pc, int32_t offset, uint32_t *ta return 0; } -void exec_itype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { +static void exec_itype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { + (void)mem; /* suppressing unused parameters warning */ printf("TYPE I\n"); itype_t i; decode_itype(&i, inst); @@ -140,7 +141,8 @@ void exec_itype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { cpu->pc += 4; } -void exec_rtype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { +static void exec_rtype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { + (void)mem; /* suppressing unused parameters warning */ printf("TYPE R\n"); rtype_t r; decode_rtype(&r, inst); @@ -233,7 +235,7 @@ void exec_rtype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { cpu->pc += 4; } -void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { +static void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { printf("TYPE L\n"); itype_t i; decode_itype(&i, inst); @@ -250,11 +252,11 @@ void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { printf("\n"); /*********/ - int32_t addr = i.imm + cpu->x[i.rs1]; + uint32_t addr = (uint32_t)i.imm + cpu->x[i.rs1]; /* TODO: do I need to check before loading halves and words */ - int32_t x; + uint32_t x; switch(i.funct3) { case 0x0: printf("Load byte\n"); @@ -267,6 +269,7 @@ void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { break; case 0x2: printf("Load word, little endian"); + /* TODO: clean up */ x = (uint32_t)(int32_t)( ((uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8)) | @@ -276,7 +279,7 @@ void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { break; case 0x4: printf("Load byte (U) zero-extends\n"); - x = (uint32_t)(uint32_t)(uint8_t)mem[addr]; + x = (uint32_t)(uint8_t)mem[addr]; break; case 0x5: @@ -299,7 +302,7 @@ void exec_itype_loads(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { } -void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { +static void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { printf("TYPE S\n"); stype_t s; decode_stype(&s, inst); @@ -338,8 +341,8 @@ void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { } if (addr % 2 == 0) { - mem[addr] = cpu->x[s.rs2]; - mem[addr+1] = cpu->x[s.rs2] >> 8; + mem[addr] = (uint8_t)cpu->x[s.rs2]; + mem[addr+1] = (uint8_t)cpu->x[s.rs2] >> 8; } break; case 0x2: @@ -349,10 +352,10 @@ void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { return; } if (addr % 4 == 0) { - mem[addr] = cpu->x[s.rs2]; - mem[addr+1] = cpu->x[s.rs2] >> 8; - mem[addr+2] = cpu->x[s.rs2] >> 16; - mem[addr+3] = cpu->x[s.rs2] >> 24; + mem[addr] = (uint8_t)cpu->x[s.rs2]; + mem[addr+1] = (uint8_t)cpu->x[s.rs2] >> 8; + mem[addr+2] = (uint8_t)cpu->x[s.rs2] >> 16; + mem[addr+3] = (uint8_t)cpu->x[s.rs2] >> 24; } break; default: @@ -363,7 +366,7 @@ void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { cpu->pc += 4; } -void exec_btype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { +static void exec_btype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { (void)mem; /* suppressing unused parameters warning */ printf("TYPE B\n"); btype_t b; @@ -435,7 +438,73 @@ void exec_btype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { } -void +static void exec_itype_jalr(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { + (void)mem; /* suppressing unused parameters warning */ + printf("TYPE I\n"); + itype_t i; + decode_itype(&i, inst); + + /**print**/ + printf("f7 rs2 rs1 f3 rd opcode\n"); + print_binless(i.imm, 12); + printf(" "); + print_binless(i.rs1, 5); + printf(" "); + print_binless(i.funct3, 3); + printf(" "); + print_binless(i.rd, 5); + printf("\nf7 in\n"); + print_binless(i.funct7, 7); + printf(" "); + print_binless(i.inimm, 5); + printf("\n"); + /*********/ + + uint32_t x; + if (i.funct3 == 0x0) { + x = cpu->pc + 4; + cpu->pc = i.rs1 + i.imm; + } else { + fprintf(stderr, "Illegal funct3\n"); + } + + 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; + } + + printf("rd:%u\n", cpu->x[i.rd]); +} + +static void exec_jtype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) { + (void)mem; /* suppressing unused parameters warning */ + printf("TYPE J\n"); + jtype_t j; + decode_jtype(&j, inst); + + /**print**/ + printf("imm rd opcode\n"); + print_binless(j.imm, 20); + printf(" "); + print_binless(j.rd, 5); + printf("\n"); + /*********/ + + uint32_t x; + x = cpu->pc + 4; + cpu->pc += j.imm; + + printf("rs1:%u imm:%u rd:%u\n",cpu->x[j.rs1],j.imm,cpu->x[j.rd]); + if (j.rd != 0) { + /* TODO: calculate & check addr */ + cpu->x[j.rd] = x; + } + + printf("rd:%u\n", cpu->x[j.rd]); +} + +static void load_program(uint8_t *mem) { /* PROGRAM */ @@ -456,7 +525,7 @@ load_program(uint8_t *mem) size_t len = sizeof(arr) / sizeof(arr[0]); int b = 0; /*byte*/ - for (int i=0; i<len; i++) { + for (size_t i=0; i<len; i++) { mem[b+0] = (uint8_t)(arr[i] >> 0); mem[b+1] = (uint8_t)(arr[i] >> 8); @@ -468,7 +537,7 @@ load_program(uint8_t *mem) } static inline uint32_t -make_instruction(uint8_t *mem, int index) +make_instruction(uint8_t *mem, uint32_t index) { uint32_t inst = 0; inst |= (uint32_t)(mem[index+0]) << 0; @@ -490,8 +559,10 @@ init_opcode_table(void) opcode_table[0x33] = exec_rtype; opcode_table[0x13] = exec_itype; opcode_table[0x03] = exec_itype_loads; + opcode_table[0x67] = exec_itype_jalr; opcode_table[0x23] = exec_stype; opcode_table[0x63] = exec_btype; + opcode_table[0x6f] = exec_jtype; } /***/