diff options
Diffstat (limited to 'emulator')
-rw-r--r-- | emulator/bits.h | 15 | ||||
-rw-r--r-- | emulator/csr.c | 51 | ||||
-rw-r--r-- | emulator/csr.h | 36 | ||||
-rw-r--r-- | emulator/csr_machine_information.c | 21 | ||||
-rw-r--r-- | emulator/csr_machine_trap_setup.c | 19 | ||||
-rw-r--r-- | emulator/csr_unpriv_counter_timer.c | 33 | ||||
-rw-r--r-- | emulator/hart.c | 348 | ||||
-rw-r--r-- | emulator/hart.h | 25 | ||||
-rw-r--r-- | emulator/instruction.h | 80 | ||||
-rw-r--r-- | emulator/lib.c | 4 | ||||
-rw-r--r-- | emulator/main.c | 3 |
11 files changed, 407 insertions, 228 deletions
diff --git a/emulator/bits.h b/emulator/bits.h new file mode 100644 index 0000000..8d4bdff --- /dev/null +++ b/emulator/bits.h @@ -0,0 +1,15 @@ +#pragma once
+
+#include <stdint.h>
+
+static inline uint32_t sign_extend(uint32_t word, uint32_t size)
+{
+ const uint32_t mask = 1U << (size - 1);
+ return (word ^ mask) - mask;
+}
+
+static inline uint64_t sign_extend_64(uint64_t word, uint32_t size)
+{
+ const uint64_t mask = 1ULL << (size - 1);
+ return (word ^ mask) - mask;
+}
diff --git a/emulator/csr.c b/emulator/csr.c new file mode 100644 index 0000000..d2527cf --- /dev/null +++ b/emulator/csr.c @@ -0,0 +1,51 @@ +#include "emulator/csr.h"
+
+#include "emulator/hart.h"
+
+#include <stdbool.h>
+
+static inline uint8_t csr_priv(uint16_t id)
+{
+ return (id & 0x300) >> 8;
+}
+
+static inline bool csr_writable(uint16_t id)
+{
+ return (id & 0xC00) == 0xC00;
+}
+
+uint32_t csr_action(Hart* hart, uint16_t id, uint32_t value, enum CsrAction action)
+{
+ // @Todo exceptions (bad access (rw, level), non existent, etc)
+ if (id > 4096 || hart->csrs[id].action)
+ {
+ // @Todo
+ return 0;
+ }
+
+ if (action > CSR_R && csr_writable(id))
+ {
+ // @Todo
+ return 0;
+ }
+
+ if (csr_priv(id) > hart->priv)
+ {
+ // @Todo
+ return 0;
+ }
+
+ return hart->csrs[id].action(hart, value, action);
+}
+
+void csr_init_unpriv_counter_timer(Hart* hart);
+void csr_init_machine_trap_setup(Hart* hart);
+void csr_init_machine_information(Hart* hart);
+
+void csr_init(Hart* hart)
+{
+ csr_init_unpriv_counter_timer(hart);
+ csr_init_machine_trap_setup(hart);
+ csr_init_machine_information(hart);
+}
+
diff --git a/emulator/csr.h b/emulator/csr.h new file mode 100644 index 0000000..89452b0 --- /dev/null +++ b/emulator/csr.h @@ -0,0 +1,36 @@ +#pragma once
+
+#include <stdint.h>
+
+typedef struct Hart Hart;
+
+#define CSR_CYCLE 0xC00
+#define CSR_CYCLEH 0xC80
+#define CSR_INSTRET 0xC02
+#define CSR_INSTRETH 0xC82
+#define CSR_TIME 0xC01
+#define CSR_TIMEH 0xC81
+
+#define CSR_MVENDORID 0xF11
+#define CSR_MARCHID 0xF12
+#define CSR_MIMPID 0xF13
+#define CSR_MHARTID 0xF14
+
+#define CSR_MISA 0x301
+
+enum CsrAction
+{
+ CSR_R = 0,
+ CSR_W = 1,
+ CSR_RW = 3,
+ CSR_RC = 5,
+ CSR_RS = 7,
+};
+
+struct Csr
+{
+ uint32_t (*action)(Hart* hart, uint32_t value_mask, enum CsrAction action);
+};
+typedef struct Csr Csr;
+
+uint32_t csr_action(Hart* hart, uint16_t id, uint32_t value, enum CsrAction action);
diff --git a/emulator/csr_machine_information.c b/emulator/csr_machine_information.c new file mode 100644 index 0000000..38a33a1 --- /dev/null +++ b/emulator/csr_machine_information.c @@ -0,0 +1,21 @@ +#include "emulator/csr.h"
+
+#include "emulator/hart.h"
+
+static uint32_t csr_minfo_zero(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return 0;
+}
+
+static uint32_t csr_mhartid(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return hart->hartid;
+}
+
+void csr_init_machine_information(Hart* hart)
+{
+ hart->csrs[CSR_MVENDORID].action = csr_minfo_zero;
+ hart->csrs[CSR_MARCHID].action = csr_minfo_zero;
+ hart->csrs[CSR_MIMPID].action = csr_minfo_zero;
+ hart->csrs[CSR_MHARTID].action = csr_mhartid;
+}
diff --git a/emulator/csr_machine_trap_setup.c b/emulator/csr_machine_trap_setup.c new file mode 100644 index 0000000..385460f --- /dev/null +++ b/emulator/csr_machine_trap_setup.c @@ -0,0 +1,19 @@ +#include "emulator/csr.h"
+
+#include "emulator/hart.h"
+
+static uint32_t csr_misa(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ uint32_t misa = 0;
+ misa |= 1 << 30; // 32-bit
+ misa |= 1 << 8; // Base ISA
+ misa |= 1 << 12; // M extension
+ misa |= 1 << 18; // Supervisor mode
+ misa |= 1 << 20; // User mode
+ return misa;
+}
+
+void csr_init_machine_trap_setup(Hart* hart)
+{
+ hart->csrs[CSR_MISA].action = csr_misa;
+}
diff --git a/emulator/csr_unpriv_counter_timer.c b/emulator/csr_unpriv_counter_timer.c new file mode 100644 index 0000000..e474520 --- /dev/null +++ b/emulator/csr_unpriv_counter_timer.c @@ -0,0 +1,33 @@ +#include "emulator/csr.h"
+
+#include "emulator/hart.h"
+
+static uint32_t csr_cycle(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return hart->instret & 0xFFFFFFFF;
+}
+
+static uint32_t csr_cycleh(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return hart->instret >> 32;
+}
+
+static uint32_t csr_time(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return hart->time & 0xFFFFFFFF;
+}
+
+static uint32_t csr_timeh(Hart* hart, uint32_t v, enum CsrAction a)
+{
+ return hart->time >> 32;
+}
+
+void csr_init_unpriv_counter_timer(Hart* hart)
+{
+ hart->csrs[CSR_CYCLE].action = csr_cycle;
+ hart->csrs[CSR_CYCLEH].action = csr_cycleh;
+ hart->csrs[CSR_INSTRET].action = csr_cycle;
+ hart->csrs[CSR_INSTRETH].action = csr_cycleh;
+ hart->csrs[CSR_TIME].action = csr_time;
+ hart->csrs[CSR_TIMEH].action = csr_timeh;
+}
diff --git a/emulator/hart.c b/emulator/hart.c index 297148b..efa0556 100644 --- a/emulator/hart.c +++ b/emulator/hart.c @@ -1,129 +1,106 @@ #include "emulator/hart.h"
+#include "emulator/bits.h"
+#include "emulator/instruction.h"
+#include "emulator/csr.h"
+
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#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)
+#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 void handle_ecall(Hart* hart)
{
- const uint32_t mask = 1U << (size - 1);
- return (word ^ mask) - mask;
}
-static inline uint64_t sign_extend_64(uint64_t word, uint32_t size)
+static inline uint32_t load_size(Hart* hart, uint32_t address, uint32_t size)
{
- const uint64_t mask = 1ULL << (size - 1);
- return (word ^ mask) - mask;
+ if ((address & 0x80000000) == 0)
+ {
+ assert(address + size < hart->mem_size);
+ uint32_t value = 0;
+ memcpy(&value, hart->mem + address, size);
+ return value;
+ }
+
+ return 0;
}
-struct Instruction
+static uint32_t load_byte(Hart* hart, uint32_t address)
{
- uint8_t opcode;
- uint8_t rs1;
- uint8_t rs2;
- uint8_t rd;
- uint8_t funct3;
- uint8_t funct7;
- uint32_t imm;
-};
-typedef struct Instruction Instruction;
-
-static Instruction decode_r_type(uint32_t word)
+ return load_size(hart, address, 1);
+}
+
+static uint32_t load_half(Hart* hart, uint32_t address)
{
- Instruction instruction = {0};
- instruction.opcode = word & 0x7F;
- instruction.rd = (word >> 7) & 0x1F;
- instruction.funct3 = (word >> 12) & 0x07;
- instruction.rs1 = (word >> 15) & 0x1F;
- instruction.rs2 = (word >> 20) & 0x1F;
- instruction.funct7 = word >> 25;
- return instruction;
-};
-
-static Instruction decode_i_type(uint32_t word)
+ return load_size(hart, address, 2);
+}
+
+static uint32_t load_word(Hart* hart, uint32_t address)
{
- Instruction instruction = {0};
- instruction.opcode = word & 0x7F;
- instruction.rd = (word >> 7) & 0x1F;
- instruction.funct3 = (word >> 12) & 0x07;
- instruction.rs1 = (word >> 15) & 0x1F;
- instruction.imm = sign_extend(word >> 20, 12);
- return instruction;
-};
-
-static Instruction decode_s_type(uint32_t word)
+ return load_size(hart, address, 4);
+}
+
+static inline void store_size(Hart* hart, uint32_t address, uint32_t value, uint32_t size)
{
- Instruction instruction = {0};
- instruction.opcode = word & 0x7F;
- instruction.funct3 = (word >> 12) & 0x07;
- instruction.rs1 = (word >> 15) & 0x1F;
- instruction.rs2 = (word >> 20) & 0x1F;
- instruction.imm = sign_extend(((word >> 7) & 0x1F) | (word >> 25), 12);
- return instruction;
-};
-
-static Instruction decode_b_type(uint32_t word)
+ if ((address & 0x80000000) == 0)
+ {
+ assert(address + size < hart->mem_size);
+ memcpy(hart->mem + address, &value, size);
+ }
+ else if (address == 0x80000000)
+ {
+ fwrite(&value, 1, size, stdout);
+ }
+}
+
+static void store_byte(Hart* hart, uint32_t address, uint8_t value)
{
- Instruction instruction = decode_s_type(word);
- instruction.imm = ((instruction.imm << 11) & 0x800) | (instruction.imm & 0xfffff7ff);
- return instruction;
-};
+ store_size(hart, address, value, 1);
+}
-static Instruction decode_u_type(uint32_t word)
+static void store_half(Hart* hart, uint32_t address, uint16_t value)
{
- Instruction instruction = {0};
- instruction.opcode = word & 0x7F;
- instruction.rd = (word >> 7) & 0x1F;
- instruction.imm = word & 0xFFFFF000;
- return instruction;
-};
-
-static Instruction decode_j_type(uint32_t word)
+ store_size(hart, address, value, 2);
+}
+
+static void store_word(Hart* hart, uint32_t address, uint32_t value)
{
- Instruction instruction = {0};
- instruction.opcode = word & 0x7F;
- instruction.rd = (word >> 7) & 0x1F;
- instruction.imm = sign_extend(
- ((word & 0x80000000) >> 11) |
- ((word & 0x000FF000) >> 0) |
- ((word & 0x00100000) >> 9) |
- ((word & 0x7FE00000) >> 20), 21);
- return instruction;
+ store_size(hart, address, value, 4);
}
static void execute_op_imm(Hart* hart, uint32_t instruction)
@@ -338,62 +315,6 @@ static void execute_branch(Hart* hart, uint32_t instruction) }
}
-static inline uint32_t load_size(Hart* hart, uint32_t address, uint32_t size)
-{
- if ((address & 0x80000000) == 0)
- {
- assert(address + size < hart->mem_size);
- uint32_t value = 0;
- memcpy(&value, hart->mem + address, size);
- return value;
- }
-
- return 0;
-}
-
-static uint32_t load_byte(Hart* hart, uint32_t address)
-{
- return load_size(hart, address, 1);
-}
-
-static uint32_t load_half(Hart* hart, uint32_t address)
-{
- return load_size(hart, address, 2);
-}
-
-static uint32_t load_word(Hart* hart, uint32_t address)
-{
- return load_size(hart, address, 4);
-}
-
-static inline void store_size(Hart* hart, uint32_t address, uint32_t value, uint32_t size)
-{
- if ((address & 0x80000000) == 0)
- {
- assert(address + size < hart->mem_size);
- memcpy(hart->mem + address, &value, size);
- }
- else if (address == 0x80000000)
- {
- fwrite(&value, 1, size, stdout);
- }
-}
-
-static void store_byte(Hart* hart, uint32_t address, uint8_t value)
-{
- store_size(hart, address, value, 1);
-}
-
-static void store_half(Hart* hart, uint32_t address, uint16_t value)
-{
- store_size(hart, address, value, 2);
-}
-
-static void store_word(Hart* hart, uint32_t address, uint32_t value)
-{
- store_size(hart, address, value, 4);
-}
-
static void execute_load(Hart* hart, uint32_t instruction)
{
const Instruction inst = decode_i_type(instruction);
@@ -462,43 +383,6 @@ 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);
@@ -528,32 +412,32 @@ static void execute_system(Hart* hart, uint32_t instruction) }
break;
}
- case 1: // CRSRW
+ case 1: // CSRRW
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
if (inst.rd == 0)
{
- crs_write(hart, crs_id, hart->regs[inst.rs1]);
+ csr_action(hart, csr_id, hart->regs[inst.rs1], CSR_W);
}
else
{
- hart->regs[inst.rd] = crs_read_write(hart, crs_id, hart->regs[inst.rs1]);
+ hart->regs[inst.rd] = csr_action(hart, csr_id, hart->regs[inst.rs1], CSR_RW);
}
break;
}
- case 2: // CRSRS
+ case 2: // CSRRS
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
uint32_t value = 0;
if (inst.rs1 == 0)
{
- value = crs_read(hart, crs_id);
+ value = csr_action(hart, csr_id, 0, CSR_R);
}
else
{
- value = crs_read_set(hart, crs_id, hart->regs[inst.rs1]);
+ value = csr_action(hart, csr_id, hart->regs[inst.rs1], CSR_RS);
}
if (inst.rd != 0)
@@ -562,18 +446,18 @@ static void execute_system(Hart* hart, uint32_t instruction) }
break;
}
- case 3: // CRSRC
+ case 3: // CSRRC
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
uint32_t value = 0;
if (inst.rs1 == 0)
{
- value = crs_read(hart, crs_id);
+ value = csr_action(hart, csr_id, 0, CSR_R);
}
else
{
- value = crs_read_clear(hart, crs_id, hart->regs[inst.rs1]);
+ value = csr_action(hart, csr_id, hart->regs[inst.rs1], CSR_RC);
}
if (inst.rd != 0)
@@ -582,32 +466,32 @@ static void execute_system(Hart* hart, uint32_t instruction) }
break;
}
- case 5: // CRSRWI
+ case 5: // CSRRWI
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
if (inst.rd == 0)
{
- crs_write(hart, crs_id, inst.rs1);
+ csr_action(hart, csr_id, inst.rs1, CSR_W);
}
else
{
- hart->regs[inst.rd] = crs_read_write(hart, crs_id, inst.rs1);
+ hart->regs[inst.rd] = csr_action(hart, csr_id, inst.rs1, CSR_RW);
}
break;
}
- case 6: // CRSRSI
+ case 6: // CSRRSI
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
uint32_t value = 0;
if (inst.rs1 == 0)
{
- value = crs_read(hart, crs_id);
+ value = csr_action(hart, csr_id, 0, CSR_R);
}
else
{
- value = crs_read_set(hart, crs_id, inst.rs1);
+ value = csr_action(hart, csr_id, inst.rs1, CSR_RS);
}
if (inst.rd != 0)
@@ -616,18 +500,18 @@ static void execute_system(Hart* hart, uint32_t instruction) }
break;
}
- case 7: // CRSRCI
+ case 7: // CSRRCI
{
- uint16_t crs_id = inst.imm & 0xFFF;
+ uint16_t csr_id = inst.imm & 0xFFF;
uint32_t value = 0;
if (inst.rs1 == 0)
{
- value = crs_read(hart, crs_id);
+ value = csr_action(hart, csr_id, 0, CSR_R);
}
else
{
- value = crs_read_clear(hart, crs_id, inst.rs1);
+ value = csr_action(hart, csr_id, inst.rs1, CSR_RC);
}
if (inst.rd != 0)
@@ -644,6 +528,10 @@ static void execute_system(Hart* hart, uint32_t instruction) void execute(Hart* hart, uint32_t instruction)
{
+ // @Todo Better time (same on all cores)
+ // @Todo Memory-map mtime and mtimecmp
+ hart->time = __rdtsc();
+
switch (instruction & 0x7f)
{
case 0x03:
@@ -721,16 +609,30 @@ void execute(Hart* hart, uint32_t instruction) }
assert(hart->regs[0] == 0);
+
+ hart->instret += 1;
}
void execute_from(Hart* hart, uint32_t start_address)
{
hart->pc = start_address;
- hart->halted = false;
- while (!hart->halted)
+ while (true)
{
uint32_t instruction = load_word(hart, hart->pc);
execute(hart, instruction);
}
}
+
+void csr_init(Hart* hart);
+
+void hart_init(Hart* hart, uint32_t id, char* mem, uint32_t mem_size)
+{
+ memset(hart, 0, sizeof(Hart));
+ hart->hartid = id;
+ hart->priv = PRIV_M;
+ hart->mem = mem;
+ hart->mem_size = mem_size;
+
+ csr_init(hart);
+}
diff --git a/emulator/hart.h b/emulator/hart.h index 8e04d19..7135ed7 100644 --- a/emulator/hart.h +++ b/emulator/hart.h @@ -1,19 +1,38 @@ #pragma once
+#include "emulator/csr.h"
+
#include <stdint.h>
#include <stdbool.h>
+#define PRIV_U 0
+#define PRIV_S 1
+#define PRIV_M 3
+
struct Hart
{
- uint32_t pc;
+ uint32_t hartid;
+
uint32_t regs[32];
+
+ uint32_t pc;
+ uint8_t priv;
+ // @Todo Proper memory system
char* mem;
uint32_t mem_size;
-
- bool halted;
+
+ // @Todo Deduplicate per machine
+ Csr csrs[4096];
+
+ uint64_t instret;
+
+ // @Todo Deduplicate per machine
+ uint64_t time;
};
typedef struct Hart Hart;
+void hart_init(Hart* hart, uint32_t id, char* mem, uint32_t mem_size);
+
void execute(Hart* hart, uint32_t instruction);
void execute_from(Hart* hart, uint32_t start_address);
diff --git a/emulator/instruction.h b/emulator/instruction.h new file mode 100644 index 0000000..97c9fe9 --- /dev/null +++ b/emulator/instruction.h @@ -0,0 +1,80 @@ +#pragma once
+
+#include <stdint.h>
+
+#include "emulator/bits.h"
+
+struct Instruction
+{
+ uint8_t opcode;
+ uint8_t rs1;
+ uint8_t rs2;
+ uint8_t rd;
+ uint8_t funct3;
+ uint8_t funct7;
+ uint32_t imm;
+};
+typedef struct Instruction Instruction;
+
+static Instruction decode_r_type(uint32_t word)
+{
+ Instruction instruction = {0};
+ instruction.opcode = word & 0x7F;
+ instruction.rd = (word >> 7) & 0x1F;
+ instruction.funct3 = (word >> 12) & 0x07;
+ instruction.rs1 = (word >> 15) & 0x1F;
+ instruction.rs2 = (word >> 20) & 0x1F;
+ instruction.funct7 = word >> 25;
+ return instruction;
+};
+
+static Instruction decode_i_type(uint32_t word)
+{
+ Instruction instruction = {0};
+ instruction.opcode = word & 0x7F;
+ instruction.rd = (word >> 7) & 0x1F;
+ instruction.funct3 = (word >> 12) & 0x07;
+ instruction.rs1 = (word >> 15) & 0x1F;
+ instruction.imm = sign_extend(word >> 20, 12);
+ return instruction;
+};
+
+static Instruction decode_s_type(uint32_t word)
+{
+ Instruction instruction = {0};
+ instruction.opcode = word & 0x7F;
+ instruction.funct3 = (word >> 12) & 0x07;
+ instruction.rs1 = (word >> 15) & 0x1F;
+ instruction.rs2 = (word >> 20) & 0x1F;
+ instruction.imm = sign_extend(((word >> 7) & 0x1F) | (word >> 25), 12);
+ return instruction;
+};
+
+static Instruction decode_b_type(uint32_t word)
+{
+ Instruction instruction = decode_s_type(word);
+ instruction.imm = ((instruction.imm << 11) & 0x800) | (instruction.imm & 0xfffff7ff);
+ return instruction;
+};
+
+static Instruction decode_u_type(uint32_t word)
+{
+ Instruction instruction = {0};
+ instruction.opcode = word & 0x7F;
+ instruction.rd = (word >> 7) & 0x1F;
+ instruction.imm = word & 0xFFFFF000;
+ return instruction;
+};
+
+static Instruction decode_j_type(uint32_t word)
+{
+ Instruction instruction = {0};
+ instruction.opcode = word & 0x7F;
+ instruction.rd = (word >> 7) & 0x1F;
+ instruction.imm = sign_extend(
+ ((word & 0x80000000) >> 11) |
+ ((word & 0x000FF000) >> 0) |
+ ((word & 0x00100000) >> 9) |
+ ((word & 0x7FE00000) >> 20), 21);
+ return instruction;
+}
diff --git a/emulator/lib.c b/emulator/lib.c index 453a3f9..6c3c7d9 100644 --- a/emulator/lib.c +++ b/emulator/lib.c @@ -1,3 +1,7 @@ #include "hart.c"
#include "elf.c"
+#include "csr.c"
+#include "csr_unpriv_counter_timer.c"
+#include "csr_machine_trap_setup.c"
+#include "csr_machine_information.c"
diff --git a/emulator/main.c b/emulator/main.c index 4bf99a3..5cfbd53 100644 --- a/emulator/main.c +++ b/emulator/main.c @@ -24,8 +24,7 @@ int main(int argc, char* argv[]) }
struct Hart hart = {0};
- hart.mem = mem;
- hart.mem_size = mem_size;
+ hart_init(&hart, 0, mem, mem_size);
execute_from(&hart, start_address);
|