This commit is contained in:
2024-05-12 14:26:38 +02:00
parent 49b3928813
commit 822fd8616c
4 changed files with 210 additions and 20 deletions

View File

@ -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

View File

@ -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,15 +360,56 @@ 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)
{
case 0:
{
if (inst.rs1 == 0 && inst.rd == 0)
{
if (inst.imm == 0)
{
// ECALL
handle_ecall(hart);
}
else if (inst.imm == 1)
{
@ -348,7 +422,121 @@ static void execute_system(Hart* hart, uint32_t instruction)
}
else
{
assert(!"Unhandled SYSTEM/PRIV instruction");
}
break;
}
case 1: // CRSRW
{
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;
}
case 2: // CRSRS
{
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;
}
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);
}
}

View File

@ -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);

View File

@ -13,10 +13,13 @@ l1:
ret
_main:
csrr a0, mhartid
la a0, my_str
call print
halt: j halt
li a0, 0
ecall
.section .rodata
my_str: .string "Hello, world!\n"