diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-05-12 14:26:38 +0200 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-05-12 14:26:38 +0200 |
commit | 822fd8616cf3d960cb2df1d2f25452ef57ea854b (patch) | |
tree | a94bc668d1c70d8f6e3079f1abfdcbd46c73bd58 /emulator/hart.c | |
parent | 49b39288133272578b8be86e3ced4468927fce5b (diff) |
Zicrs
Diffstat (limited to 'emulator/hart.c')
-rw-r--r-- | emulator/hart.c | 216 |
1 files changed, 202 insertions, 14 deletions
diff --git a/emulator/hart.c b/emulator/hart.c index cfca837..db43cd1 100644 --- a/emulator/hart.c +++ b/emulator/hart.c @@ -6,6 +6,39 @@ #include <stdbool.h>
#include <string.h>
+#define REG_ZERO 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_GP 3
+#define REG_TP 4
+#define REG_T0 5
+#define REG_T1 6
+#define REG_T2 7
+#define REG_S0 8
+#define REG_S1 9
+#define REG_A0 10
+#define REG_A1 11
+#define REG_A2 12
+#define REG_A3 13
+#define REG_A4 14
+#define REG_A5 15
+#define REG_A6 16
+#define REG_A7 17
+#define REG_S2 18
+#define REG_S3 19
+#define REG_S4 20
+#define REG_S5 21
+#define REG_S6 22
+#define REG_S7 23
+#define REG_S8 24
+#define REG_S9 25
+#define REG_S10 26
+#define REG_S11 27
+#define REG_T3 28
+#define REG_T4 29
+#define REG_T5 30
+#define REG_T6 31
+
static inline uint32_t sign_extend(uint32_t word, uint32_t size)
{
const uint32_t mask = 1U << (size - 1);
@@ -327,28 +360,183 @@ static void execute_misc_mem(Hart* hart, uint32_t instruction) }
}
+static void handle_ecall(Hart* hart)
+{
+ if (hart->regs[REG_A0] == 0)
+ {
+ hart->halted = true;
+ }
+}
+
+static uint32_t crs_read(Hart* hart, uint16_t id)
+{
+ // @Todo
+ return 0;
+}
+
+static void crs_write(Hart* hart, uint16_t id, uint32_t new_value)
+{
+ // @Todo
+}
+
+static uint32_t crs_read_write(Hart* hart, uint16_t id, uint32_t new_value)
+{
+ // @Todo
+ return 0;
+}
+
+static uint32_t crs_read_clear(Hart* hart, uint16_t id, uint32_t mask)
+{
+ // @Todo
+ return 0;
+}
+
+static uint32_t crs_read_set(Hart* hart, uint16_t id, uint32_t mask)
+{
+ // @Todo
+ return 0;
+}
+
static void execute_system(Hart* hart, uint32_t instruction)
{
const Instruction inst = decode_i_type(instruction);
-
- if (inst.funct3 == 0 && inst.rs1 == 0 && inst.rd == 0)
+
+ switch (inst.funct3)
{
- if (inst.imm == 0)
+ case 0:
{
- // ECALL
+ if (inst.rs1 == 0 && inst.rd == 0)
+ {
+ if (inst.imm == 0)
+ {
+ handle_ecall(hart);
+ }
+ else if (inst.imm == 1)
+ {
+ // EBREAK
+ }
+ else
+ {
+ assert(!"Unhandled SYSTEM/PRIV instruction");
+ }
+ }
+ else
+ {
+ assert(!"Unhandled SYSTEM/PRIV instruction");
+ }
+ break;
}
- else if (inst.imm == 1)
+ case 1: // CRSRW
{
- // EBREAK
+ uint16_t crs_id = inst.imm & 0xFFF;
+
+ if (inst.rd == 0)
+ {
+ crs_write(hart, crs_id, hart->regs[inst.rs1]);
+ }
+ else
+ {
+ hart->regs[inst.rd] = crs_read_write(hart, crs_id, hart->regs[inst.rs1]);
+ }
+ break;
}
- else
+ case 2: // CRSRS
{
- assert(!"Unhandled SYSTEM/PRIV instruction");
+ uint16_t crs_id = inst.imm & 0xFFF;
+ uint32_t value = 0;
+
+ if (inst.rs1 == 0)
+ {
+ value = crs_read(hart, crs_id);
+ }
+ else
+ {
+ value = crs_read_set(hart, crs_id, hart->regs[inst.rs1]);
+ }
+
+ if (inst.rd != 0)
+ {
+ hart->regs[inst.rd] = value;
+ }
+ break;
}
- }
- else
- {
- assert(!"Unhandled SYSTEM instruction");
+ case 3: // CRSRC
+ {
+ uint16_t crs_id = inst.imm & 0xFFF;
+ uint32_t value = 0;
+
+ if (inst.rs1 == 0)
+ {
+ value = crs_read(hart, crs_id);
+ }
+ else
+ {
+ value = crs_read_clear(hart, crs_id, hart->regs[inst.rs1]);
+ }
+
+ if (inst.rd != 0)
+ {
+ hart->regs[inst.rd] = value;
+ }
+ break;
+ }
+ case 5: // CRSRWI
+ {
+ uint16_t crs_id = inst.imm & 0xFFF;
+
+ if (inst.rd == 0)
+ {
+ crs_write(hart, crs_id, inst.rs1);
+ }
+ else
+ {
+ hart->regs[inst.rd] = crs_read_write(hart, crs_id, inst.rs1);
+ }
+ break;
+ }
+ case 6: // CRSRSI
+ {
+ uint16_t crs_id = inst.imm & 0xFFF;
+ uint32_t value = 0;
+
+ if (inst.rs1 == 0)
+ {
+ value = crs_read(hart, crs_id);
+ }
+ else
+ {
+ value = crs_read_set(hart, crs_id, inst.rs1);
+ }
+
+ if (inst.rd != 0)
+ {
+ hart->regs[inst.rd] = value;
+ }
+ break;
+ }
+ case 7: // CRSRCI
+ {
+ uint16_t crs_id = inst.imm & 0xFFF;
+ uint32_t value = 0;
+
+ if (inst.rs1 == 0)
+ {
+ value = crs_read(hart, crs_id);
+ }
+ else
+ {
+ value = crs_read_clear(hart, crs_id, inst.rs1);
+ }
+
+ if (inst.rd != 0)
+ {
+ hart->regs[inst.rd] = value;
+ }
+ break;
+ }
+ default:
+ assert(!"Unhandled SYSTEM instruction");
+ break;
}
}
@@ -436,11 +624,11 @@ void execute(Hart* hart, uint32_t instruction) void execute_from(Hart* hart, uint32_t start_address)
{
hart->pc = start_address;
+ hart->halted = false;
- while (true)
+ while (!hart->halted)
{
uint32_t instruction = load_word(hart, hart->pc);
execute(hart, instruction);
}
}
-
|