Zicrs
This commit is contained in:
@ -4,15 +4,11 @@ SET BUILD_OPTS= -std=c11 -D_CRT_SECURE_NO_WARNINGS -I.
|
||||
|
||||
IF NOT EXIST build mkdir build
|
||||
|
||||
echo emulator.lib
|
||||
clang emulator/lib.c -o build/emulator.lib %BUILD_OPTS% -fuse-ld=llvm-lib
|
||||
|
||||
echo emulator.exe
|
||||
clang emulator/main.c build/emulator.lib -o build/emulator.exe %BUILD_OPTS%
|
||||
|
||||
echo hart_test.exe
|
||||
clang emulator/hart_test.c build/emulator.lib -o build/hart_test.exe %BUILD_OPTS%
|
||||
|
||||
echo main.bin
|
||||
clang --target=riscv32 -march=rv32i -e _main -nostdlib main.asm -o build/main.bin
|
||||
|
||||
|
216
emulator/hart.c
216
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct Hart
|
||||
{
|
||||
uint32_t pc;
|
||||
uint32_t regs[32];
|
||||
|
||||
char* mem;
|
||||
uint32_t mem_size;
|
||||
|
||||
bool halted;
|
||||
};
|
||||
typedef struct Hart Hart;
|
||||
|
||||
void execute(Hart* hart, uint32_t instruction);
|
||||
void execute_from(Hart* hart, uint32_t start_address);
|
||||
|
||||
|
Reference in New Issue
Block a user