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:
| M | Makefile | | | 6 | +++++- |
| M | decode.h | | | 48 | +++++++++++++++++++++++++++++++++++------------- |
| M | main.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;
}
/***/