summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-05-11 19:08:19 +0200
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-05-11 19:08:19 +0200
commit1f48837af82e5bc226b62b509d61986c2b82f11b (patch)
tree81e42b73a97c9d0b37bfbceb46d43ac14226727b /main.c
parent5d09caaf02005b8f508bfe84057b5aeeb57c9ba4 (diff)
Finish I
Diffstat (limited to 'main.c')
-rw-r--r--main.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/main.c b/main.c
index feba3b9..223403a 100644
--- a/main.c
+++ b/main.c
@@ -206,10 +206,130 @@ void execute_branch(struct Hart* hart, uint32_t instruction)
}
}
+uint32_t load_byte(struct Hart* hart, uint32_t address)
+{
+ return 0;
+}
+
+uint32_t load_half(struct Hart* hart, uint32_t address)
+{
+ return 0;
+}
+
+uint32_t load_word(struct Hart* hart, uint32_t address)
+{
+ return 0;
+}
+
+void store_byte(struct Hart* hart, uint32_t address, uint8_t value) {}
+void store_half(struct Hart* hart, uint32_t address, uint16_t value) {}
+void store_word(struct Hart* hart, uint32_t address, uint32_t value) {}
+
+void execute_op_load(struct Hart* hart, uint32_t instruction)
+{
+ const struct Instruction inst = decode_i_type(instruction);
+ const uint32_t address = hart->regs[inst.rs1] + inst.imm;
+
+ uint32_t value = 0;
+
+ switch (inst.funct3 & 0x03)
+ {
+ case 0:
+ value = load_byte(hart, address);
+ if ((inst.funct3 & 0x40) == 0)
+ {
+ value = sign_extend(value, 8);
+ }
+ break;
+ case 1:
+ value = load_half(hart, address);
+ if ((inst.funct3 & 0x40) == 0)
+ {
+ value = sign_extend(value, 16);
+ }
+ break;
+ case 2:
+ value = load_byte(hart, address);
+ break;
+ default:
+ assert(!"Unhandled load size");
+ break;
+ }
+
+ if (inst.rd != 0)
+ {
+ hart->regs[inst.rd] = value;
+ }
+}
+
+void execute_op_store(struct Hart* hart, uint32_t instruction)
+{
+ const struct Instruction inst = decode_s_type(instruction);
+ const uint32_t address = hart->regs[inst.rs1] + inst.imm;
+ const uint32_t value = hart->regs[inst.rs2];
+
+ switch (inst.funct3 & 0x03)
+ {
+ case 0: store_byte(hart, address, value & 0xFF); break;
+ case 1: store_half(hart, address, value & 0xFFFF); break;
+ case 2: store_word(hart, address, value); break;
+ default:
+ assert(!"Unhandled store size");
+ break;
+ }
+}
+
+void execute_misc_mem(struct Hart* hart, uint32_t instruction)
+{
+ const struct Instruction inst = decode_i_type(instruction);
+
+ if (inst.funct3 == 0)
+ {
+ // FENCE
+ }
+ else
+ {
+ assert(!"Unhandled MISC-MEM instruction");
+ }
+}
+
+void execute_system(struct Hart* hart, uint32_t instruction)
+{
+ const struct Instruction inst = decode_i_type(instruction);
+
+ if (inst.funct3 == 0 && inst.rs1 == 0 && inst.rd == 0)
+ {
+ if (inst.imm == 0)
+ {
+ // ECALL
+ }
+ else if (inst.imm == 1)
+ {
+ // EBREAK
+ }
+ else
+ {
+ assert(!"Unhandled SYSTEM/PRIV instruction");
+ }
+ }
+ else
+ {
+ assert(!"Unhandled SYSTEM instruction");
+ }
+}
+
void execute(struct Hart* hart, uint32_t instruction)
{
switch (instruction & 0x7f)
{
+ case 0x03:
+ execute_op_load(hart, instruction);
+ hart->pc += 4;
+ break;
+ case 0x0F:
+ execute_misc_mem(hart, instruction);
+ hart->pc += 4;
+ break;
case 0x13:
execute_op_imm(hart, instruction);
hart->pc += 4;
@@ -224,6 +344,10 @@ void execute(struct Hart* hart, uint32_t instruction)
hart->pc += 4;
break;
}
+ case 0x23:
+ execute_op_store(hart, instruction);
+ hart->pc += 4;
+ break;
case 0x33:
execute_op(hart, instruction);
hart->pc += 4;
@@ -262,6 +386,12 @@ void execute(struct Hart* hart, uint32_t instruction)
hart->pc += inst.imm;
break;
}
+ case 0x73:
+ {
+ execute_system(hart, instruction);
+ hart->pc += 4;
+ break;
+ }
default:
assert(!"Unhandled opcode");
}