Compare commits
2 commits
3e27882a75
...
c9ad69a32d
Author | SHA1 | Date | |
---|---|---|---|
c9ad69a32d | |||
385d448746 |
23 changed files with 238 additions and 89 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -4,4 +4,4 @@
|
||||||
branch = dev
|
branch = dev
|
||||||
[submodule "diffu"]
|
[submodule "diffu"]
|
||||||
path = diffu
|
path = diffu
|
||||||
url = https://git.xinyang.life/xin/diffu.git
|
url = git@github.com:xinyangli/diffu.git
|
||||||
|
|
|
@ -76,7 +76,8 @@ target_include_directories(
|
||||||
INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/include>
|
INTERFACE $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/include>
|
||||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/src>
|
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/src>
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||||
target_compile_definitions(am_interface INTERFACE ARCH_H=<arch/${ISA}.h>)
|
target_compile_definitions(am_interface INTERFACE ARCH_H=<arch/${ISA}.h>
|
||||||
|
"__ISA__=\"${ISA}\"")
|
||||||
file(GLOB_RECURSE AM_HEADERS "${CMAKE_SOURCE_DIR}/am/include/*.h")
|
file(GLOB_RECURSE AM_HEADERS "${CMAKE_SOURCE_DIR}/am/include/*.h")
|
||||||
target_sources(
|
target_sources(
|
||||||
am_interface
|
am_interface
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#ifndef ARCH_H__
|
#ifndef ARCH_H__
|
||||||
#define ARCH_H__
|
#define ARCH_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __riscv_e
|
#ifdef __riscv_e
|
||||||
#define NR_REGS 16
|
#define NR_REGS 16
|
||||||
|
@ -9,10 +10,13 @@
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
// TODO: fix the order of these members to match trap.S
|
// TODO: fix the order of these members to match trap.S
|
||||||
uintptr_t mepc, mcause, gpr[NR_REGS], mstatus;
|
uintptr_t gpr[NR_REGS];
|
||||||
|
uintptr_t mcause, mstatus, mepc;
|
||||||
void *pdir;
|
void *pdir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Cause { CauseEnvironmentCallFromMMode = 11 };
|
||||||
|
|
||||||
#ifdef __riscv_e
|
#ifdef __riscv_e
|
||||||
#define GPR1 gpr[15] // a5
|
#define GPR1 gpr[15] // a5
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -6,7 +6,7 @@ int main(const char *args);
|
||||||
|
|
||||||
Area heap = RANGE(&_heap_start, PMEM_END);
|
Area heap = RANGE(&_heap_start, PMEM_END);
|
||||||
#ifndef MAINARGS
|
#ifndef MAINARGS
|
||||||
#define MAINARGS "5"
|
#define MAINARGS "i"
|
||||||
#endif
|
#endif
|
||||||
static const char mainargs[] = MAINARGS;
|
static const char mainargs[] = MAINARGS;
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
|
#include "arch/riscv.h"
|
||||||
#include <am.h>
|
#include <am.h>
|
||||||
#include <riscv/riscv.h>
|
|
||||||
#include <klib.h>
|
#include <klib.h>
|
||||||
|
#include <riscv/riscv.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
static Context* (*user_handler)(Event, Context*) = NULL;
|
static Context *(*user_handler)(Event, Context *) = NULL;
|
||||||
|
|
||||||
Context* __am_irq_handle(Context *c) {
|
Context *__am_irq_handle(Context *c) {
|
||||||
if (user_handler) {
|
if (user_handler) {
|
||||||
Event ev = {0};
|
Event ev = {0};
|
||||||
switch (c->mcause) {
|
switch (c->mcause) {
|
||||||
default: ev.event = EVENT_ERROR; break;
|
case CauseEnvironmentCallFromMMode:
|
||||||
|
ev.event = EVENT_YIELD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ev.event = EVENT_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
c = user_handler(ev, c);
|
c = user_handler(ev, c);
|
||||||
|
@ -20,7 +27,7 @@ Context* __am_irq_handle(Context *c) {
|
||||||
|
|
||||||
extern void __am_asm_trap(void);
|
extern void __am_asm_trap(void);
|
||||||
|
|
||||||
bool cte_init(Context*(*handler)(Event, Context*)) {
|
bool cte_init(Context *(*handler)(Event, Context *)) {
|
||||||
// initialize exception entry
|
// initialize exception entry
|
||||||
asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));
|
asm volatile("csrw mtvec, %0" : : "r"(__am_asm_trap));
|
||||||
|
|
||||||
|
@ -31,7 +38,10 @@ bool cte_init(Context*(*handler)(Event, Context*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
Context *kcontext(Area kstack, void (*entry)(void *), void *arg) {
|
||||||
return NULL;
|
Context *c = kstack.end - sizeof(Context);
|
||||||
|
c->mepc = (uintptr_t)entry;
|
||||||
|
c->gpr[10] = (uintptr_t)arg;
|
||||||
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield() {
|
void yield() {
|
||||||
|
@ -42,9 +52,6 @@ void yield() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ienabled() {
|
bool ienabled() { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iset(bool enable) {
|
void iset(bool enable) {}
|
||||||
}
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ __am_asm_trap:
|
||||||
mv a0, sp
|
mv a0, sp
|
||||||
jal __am_irq_handle
|
jal __am_irq_handle
|
||||||
|
|
||||||
|
mv sp, a0
|
||||||
|
|
||||||
LOAD t1, OFFSET_STATUS(sp)
|
LOAD t1, OFFSET_STATUS(sp)
|
||||||
LOAD t2, OFFSET_EPC(sp)
|
LOAD t2, OFFSET_EPC(sp)
|
||||||
csrw mstatus, t1
|
csrw mstatus, t1
|
||||||
|
|
|
@ -15,6 +15,9 @@ stdenv.mkDerivation {
|
||||||
(lib.cmakeFeature "ISA" isa)
|
(lib.cmakeFeature "ISA" isa)
|
||||||
] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform;
|
] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform;
|
||||||
|
|
||||||
|
cmakeBuildType = "Debug";
|
||||||
|
dontStrip = true;
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
cmake
|
cmake
|
||||||
];
|
];
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 02b38e7b44f673f808abcb3bf9464811f8c58d4b
|
Subproject commit 8c4ea046225e2dce599dc36aeef6c4c857996d00
|
|
@ -128,11 +128,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1721457008,
|
"lastModified": 1721891452,
|
||||||
"narHash": "sha256-ekpve0om5hzC1Ntd3zm1cZ9oS5pnr7a2n/tueyqFOsg=",
|
"narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "e7aa3319d52fa987ac2192f63aef3dcb1b057e3a",
|
"rev": "de8ad578fc4fe527772cec23a7f660bde14c8570",
|
||||||
"revCount": 151,
|
"revCount": 152,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.xinyang.life/xin/nur.git"
|
"url": "https://git.xinyang.life/xin/nur.git"
|
||||||
},
|
},
|
||||||
|
|
|
@ -64,13 +64,14 @@
|
||||||
abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; };
|
abstract-machine = rv32CrossConfig.callPackage ./abstract-machine { isa = "riscv"; platform = [ "nemu" "npc" ]; };
|
||||||
am-kernels-npc = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-npc"; };
|
am-kernels-npc = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-npc"; };
|
||||||
am-kernels-nemu = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-nemu"; };
|
am-kernels-nemu = rv32CrossConfig.callPackage ./am-kernels { inherit abstract-machine; arch = "riscv-nemu"; };
|
||||||
|
am-kernels = rv32CrossConfig.callPackage ./am-kernels { abstract-machine = abstract-machine; arch = "riscv"; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells.nemu = pkgs.mkShell {
|
devShells.nemu = pkgs.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
clang-tools
|
clang-tools
|
||||||
gdb
|
gef
|
||||||
SDL2
|
SDL2
|
||||||
gnumake
|
gnumake
|
||||||
pkg-config
|
pkg-config
|
||||||
|
|
1
nemu/.gitignore
vendored
1
nemu/.gitignore
vendored
|
@ -9,6 +9,7 @@ build/
|
||||||
.envrc
|
.envrc
|
||||||
.metals/
|
.metals/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.zed/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
||||||
### C ###
|
### C ###
|
||||||
|
|
|
@ -20,7 +20,14 @@
|
||||||
|
|
||||||
// ----------- state -----------
|
// ----------- state -----------
|
||||||
|
|
||||||
enum { NEMU_RUNNING, NEMU_STOP, NEMU_END, NEMU_ABORT, NEMU_QUIT };
|
enum {
|
||||||
|
NEMU_RUNNING,
|
||||||
|
NEMU_GDB_INTERRUPT,
|
||||||
|
NEMU_STOP,
|
||||||
|
NEMU_END,
|
||||||
|
NEMU_ABORT,
|
||||||
|
NEMU_QUIT
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int state;
|
int state;
|
||||||
|
@ -56,16 +63,16 @@ uint64_t get_time();
|
||||||
|
|
||||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE
|
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE
|
||||||
|
|
||||||
#define log_write(...) IFDEF(CONFIG_TARGET_NATIVE_ELF, \
|
#define log_write(...) \
|
||||||
do { \
|
IFDEF( \
|
||||||
extern FILE* log_fp; \
|
CONFIG_TARGET_NATIVE_ELF, do { \
|
||||||
|
extern FILE *log_fp; \
|
||||||
extern bool log_enable(); \
|
extern bool log_enable(); \
|
||||||
if (log_enable()) { \
|
if (log_enable()) { \
|
||||||
fprintf(log_fp, __VA_ARGS__); \
|
fprintf(log_fp, __VA_ARGS__); \
|
||||||
fflush(log_fp); \
|
fflush(log_fp); \
|
||||||
} \
|
} \
|
||||||
} while (0) \
|
} while (0))
|
||||||
)
|
|
||||||
|
|
||||||
#define _Log(...) \
|
#define _Log(...) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -73,5 +80,4 @@ uint64_t get_time();
|
||||||
log_write(__VA_ARGS__); \
|
log_write(__VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -158,8 +158,6 @@ breakpoint_t *cpu_exec_with_bp(uint64_t n, breakpoint_t *bp, size_t len) {
|
||||||
static Decode s;
|
static Decode s;
|
||||||
nemu_state.state = NEMU_RUNNING;
|
nemu_state.state = NEMU_RUNNING;
|
||||||
do {
|
do {
|
||||||
exec_once(&s, cpu.pc);
|
|
||||||
g_nr_guest_inst++;
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
size_t addr = bp[i].addr;
|
size_t addr = bp[i].addr;
|
||||||
bp_type_t bptype = bp[i].type;
|
bp_type_t bptype = bp[i].type;
|
||||||
|
@ -176,6 +174,8 @@ breakpoint_t *cpu_exec_with_bp(uint64_t n, breakpoint_t *bp, size_t len) {
|
||||||
return bp + i;
|
return bp + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exec_once(&s, cpu.pc);
|
||||||
|
g_nr_guest_inst++;
|
||||||
if (nemu_state.state != NEMU_RUNNING)
|
if (nemu_state.state != NEMU_RUNNING)
|
||||||
return NULL;
|
return NULL;
|
||||||
} while (--n);
|
} while (--n);
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <debug.h>
|
||||||
#include <device/map.h>
|
#include <device/map.h>
|
||||||
|
#include <generated/autoconf.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
#define KEYDOWN_MASK 0x8000
|
#define KEYDOWN_MASK 0x8000
|
||||||
|
@ -23,27 +26,26 @@
|
||||||
|
|
||||||
// Note that this is not the standard
|
// Note that this is not the standard
|
||||||
#define NEMU_KEYS(f) \
|
#define NEMU_KEYS(f) \
|
||||||
f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) f(F11) f(F12) \
|
f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) \
|
||||||
f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) f(MINUS) f(EQUALS) f(BACKSPACE) \
|
f(F11) f(F12) f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) \
|
||||||
f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
|
f(MINUS) f(EQUALS) f(BACKSPACE) f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) \
|
||||||
f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) f(SEMICOLON) f(APOSTROPHE) f(RETURN) \
|
f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
|
||||||
f(LSHIFT) f(Z) f(X) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) f(RSHIFT) \
|
f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) \
|
||||||
f(LCTRL) f(APPLICATION) f(LALT) f(SPACE) f(RALT) f(RCTRL) \
|
f(SEMICOLON) f(APOSTROPHE) f(RETURN) f(LSHIFT) f(Z) f(X) \
|
||||||
f(UP) f(DOWN) f(LEFT) f(RIGHT) f(INSERT) f(DELETE) f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)
|
f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) \
|
||||||
|
f(RSHIFT) f(LCTRL) f(APPLICATION) f(LALT) \
|
||||||
|
f(SPACE) f(RALT) f(RCTRL) f(UP) f(DOWN) \
|
||||||
|
f(LEFT) f(RIGHT) f(INSERT) f(DELETE) \
|
||||||
|
f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)
|
||||||
|
|
||||||
#define NEMU_KEY_NAME(k) NEMU_KEY_ ## k,
|
#define NEMU_KEY_NAME(k) NEMU_KEY_##k,
|
||||||
|
|
||||||
enum {
|
enum { NEMU_KEY_NONE = 0, MAP(NEMU_KEYS, NEMU_KEY_NAME) };
|
||||||
NEMU_KEY_NONE = 0,
|
|
||||||
MAP(NEMU_KEYS, NEMU_KEY_NAME)
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SDL_KEYMAP(k) keymap[SDL_SCANCODE_ ## k] = NEMU_KEY_ ## k;
|
#define SDL_KEYMAP(k) keymap[SDL_SCANCODE_##k] = NEMU_KEY_##k;
|
||||||
static uint32_t keymap[256] = {};
|
static uint32_t keymap[256] = {};
|
||||||
|
|
||||||
static void init_keymap() {
|
static void init_keymap() { MAP(NEMU_KEYS, SDL_KEYMAP) }
|
||||||
MAP(NEMU_KEYS, SDL_KEYMAP)
|
|
||||||
}
|
|
||||||
|
|
||||||
#define KEY_QUEUE_LEN 1024
|
#define KEY_QUEUE_LEN 1024
|
||||||
static int key_queue[KEY_QUEUE_LEN] = {};
|
static int key_queue[KEY_QUEUE_LEN] = {};
|
||||||
|
@ -92,9 +94,11 @@ void init_i8042() {
|
||||||
i8042_data_port_base = (uint32_t *)new_space(4);
|
i8042_data_port_base = (uint32_t *)new_space(4);
|
||||||
i8042_data_port_base[0] = NEMU_KEY_NONE;
|
i8042_data_port_base[0] = NEMU_KEY_NONE;
|
||||||
#ifdef CONFIG_HAS_PORT_IO
|
#ifdef CONFIG_HAS_PORT_IO
|
||||||
add_pio_map ("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4, i8042_data_io_handler);
|
add_pio_map("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4,
|
||||||
|
i8042_data_io_handler);
|
||||||
#else
|
#else
|
||||||
add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4, i8042_data_io_handler);
|
add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4,
|
||||||
|
i8042_data_io_handler);
|
||||||
#endif
|
#endif
|
||||||
IFNDEF(CONFIG_TARGET_AM, init_keymap());
|
IFNDEF(CONFIG_TARGET_AM, init_keymap());
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <device/map.h>
|
#include <device/map.h>
|
||||||
|
#include <generated/autoconf.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <device/alarm.h>
|
#include <device/alarm.h>
|
||||||
#include <device/map.h>
|
#include <device/map.h>
|
||||||
|
#include <generated/autoconf.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
static uint32_t *rtc_port_base = NULL;
|
static uint32_t *rtc_port_base = NULL;
|
||||||
|
|
18
nemu/src/isa/riscv32/csr.c
Normal file
18
nemu/src/isa/riscv32/csr.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <csr.h>
|
||||||
|
|
||||||
|
void init_csr(csr_t csr) { memset(csr, 0, sizeof(word_t)); }
|
||||||
|
|
||||||
|
void write_csr(csr_t csr, csr_addr_t csrnum, word_t value) {
|
||||||
|
switch (csrnum) {
|
||||||
|
default:
|
||||||
|
csr[csrnum] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
word_t read_csr(csr_t csr, csr_addr_t csrnum) {
|
||||||
|
switch (csrnum) {
|
||||||
|
// TODO: Implement csr read checks
|
||||||
|
default:
|
||||||
|
return csr[csrnum];
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,13 @@
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
|
#define CSR_SIZE (0x1000)
|
||||||
|
|
||||||
|
typedef word_t csr_t[CSR_SIZE];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)];
|
word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)];
|
||||||
// word_t csr[MUXDEF(CONFIG_RVE, )]
|
csr_t csr;
|
||||||
vaddr_t pc;
|
vaddr_t pc;
|
||||||
} MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state);
|
} MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#include "isa.h"
|
||||||
#include "local-include/reg.h"
|
#include "local-include/reg.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
#include <cpu/cpu.h>
|
#include <cpu/cpu.h>
|
||||||
#include <cpu/decode.h>
|
#include <cpu/decode.h>
|
||||||
#include <cpu/ifetch.h>
|
#include <cpu/ifetch.h>
|
||||||
|
#include <csr.h>
|
||||||
#include <ftrace.h>
|
#include <ftrace.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
||||||
|
@ -33,6 +35,8 @@ enum {
|
||||||
TYPE_S,
|
TYPE_S,
|
||||||
TYPE_B,
|
TYPE_B,
|
||||||
TYPE_J,
|
TYPE_J,
|
||||||
|
TYPE_CSR,
|
||||||
|
TYPE_CSRI,
|
||||||
TYPE_N, // none
|
TYPE_N, // none
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,6 +70,14 @@ enum {
|
||||||
*imm = SEXT(BITS(i, 31, 31), 1) << 20 | BITS(i, 30, 21) << 1 | \
|
*imm = SEXT(BITS(i, 31, 31), 1) << 20 | BITS(i, 30, 21) << 1 | \
|
||||||
BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; \
|
BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define csr() \
|
||||||
|
do { \
|
||||||
|
*src2 = BITS(i, 31, 20); \
|
||||||
|
} while (0)
|
||||||
|
#define uimm() \
|
||||||
|
do { \
|
||||||
|
*imm = BITS(i, 19, 15); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
|
static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
|
||||||
word_t *imm, int type) {
|
word_t *imm, int type) {
|
||||||
|
@ -98,6 +110,14 @@ static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
|
||||||
src2R();
|
src2R();
|
||||||
immB();
|
immB();
|
||||||
break;
|
break;
|
||||||
|
case TYPE_CSR:
|
||||||
|
src1R();
|
||||||
|
csr();
|
||||||
|
break;
|
||||||
|
case TYPE_CSRI:
|
||||||
|
csr();
|
||||||
|
uimm();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +269,44 @@ static int decode_exec(Decode *s) {
|
||||||
INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu, R,
|
INSTPAT("0000001 ????? ????? 111 ????? 01100 11", remu, R,
|
||||||
R(rd) = src1 % src2);
|
R(rd) = src1 % src2);
|
||||||
|
|
||||||
|
// "Previledge"
|
||||||
|
// -- CSR instructions
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 001 ????? 11100 11", csrrw, CSR, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
write_csr(cpu.csr, src2, src1);
|
||||||
|
} while (0););
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 010 ????? 11100 11", csrrs, CSR, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
set_csr_bits(cpu.csr, src2, src1);
|
||||||
|
} while (0););
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 011 ????? 11100 11", csrrc, CSR, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
clear_csr_bits(cpu.csr, src2, src1);
|
||||||
|
} while (0););
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 101 ????? 11100 11", csrrwi, CSRI, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
write_csr(cpu.csr, src2, imm);
|
||||||
|
} while (0););
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 110 ????? 11100 11", csrrsi, CSRI, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
set_csr_bits(cpu.csr, src2, imm);
|
||||||
|
} while (0););
|
||||||
|
INSTPAT(
|
||||||
|
"??????? ????? ????? 111 ????? 11100 11", csrrci, CSRI, do {
|
||||||
|
R(rd) = read_csr(cpu.csr, src2);
|
||||||
|
clear_csr_bits(cpu.csr, src2, imm);
|
||||||
|
} while (0););
|
||||||
|
// -- Machine level
|
||||||
|
INSTPAT("0000000 00000 00000 000 00000 11100 11", ecall, N,
|
||||||
|
s->dnpc = isa_raise_intr(CauseEnvironmentCallFromMMode, cpu.pc));
|
||||||
|
INSTPAT("0011000 00010 00000 000 00000 11100 11", mret, N,
|
||||||
|
s->dnpc = read_csr(cpu.csr, MEPC));
|
||||||
|
|
||||||
INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv, N, INV(s->pc));
|
INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv, N, INV(s->pc));
|
||||||
INSTPAT_END();
|
INSTPAT_END();
|
||||||
|
|
||||||
|
|
29
nemu/src/isa/riscv32/local-include/csr.h
Normal file
29
nemu/src/isa/riscv32/local-include/csr.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef __NEMU_CSR_H__
|
||||||
|
#define __NEMU_CSR_H__
|
||||||
|
#include <isa-def.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
#define MSTATUS 0x300
|
||||||
|
#define MISA 0x301
|
||||||
|
#define MIE 0x304
|
||||||
|
#define MTVEC 0x305
|
||||||
|
#define MEPC 0x341
|
||||||
|
#define MCAUSE 0x342
|
||||||
|
|
||||||
|
enum { CauseEnvironmentCallFromMMode = 11 };
|
||||||
|
|
||||||
|
typedef uint16_t csr_addr_t;
|
||||||
|
|
||||||
|
void init_csr(csr_t csr);
|
||||||
|
|
||||||
|
/* macro for setting and clearing csr bits */
|
||||||
|
#define set_csr_bits(csr, reg, mask) \
|
||||||
|
write_csr(csr, reg, read_csr(csr, reg) | (mask))
|
||||||
|
|
||||||
|
#define clear_csr_bits(csr, reg, mask) \
|
||||||
|
write_csr(csr, reg, read_csr(csr, reg) & ~(mask))
|
||||||
|
|
||||||
|
void write_csr(csr_t csr, csr_addr_t csrnum, word_t value);
|
||||||
|
word_t read_csr(csr_t csr, csr_addr_t csrnum);
|
||||||
|
|
||||||
|
#endif // __NEMU_CSR_H__
|
|
@ -14,6 +14,7 @@
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
#include "local-include/reg.h"
|
#include "local-include/reg.h"
|
||||||
|
#include "csr.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <gdbstub.h>
|
#include <gdbstub.h>
|
||||||
|
@ -51,11 +52,13 @@ word_t isa_reg_str2val(const char *s, bool *success) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int isa_read_reg(void *args, int regno, size_t *reg_value) {
|
int isa_read_reg(void *args, int regno, size_t *reg_value) {
|
||||||
if (regno > 32) {
|
if (regno > 33) {
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regno == 32) {
|
if (regno == 33) {
|
||||||
|
*reg_value = cpu.csr[MTVEC];
|
||||||
|
} else if (regno == 32) {
|
||||||
*reg_value = cpu.pc;
|
*reg_value = cpu.pc;
|
||||||
} else {
|
} else {
|
||||||
*reg_value = cpu.gpr[regno];
|
*reg_value = cpu.gpr[regno];
|
||||||
|
@ -64,11 +67,13 @@ int isa_read_reg(void *args, int regno, size_t *reg_value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int isa_write_reg(void *args, int regno, size_t data) {
|
int isa_write_reg(void *args, int regno, size_t data) {
|
||||||
if (regno > 32) {
|
if (regno > 33) {
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regno == 32) {
|
if (regno == 33) {
|
||||||
|
cpu.csr[MTVEC] = data;
|
||||||
|
} else if (regno == 32) {
|
||||||
cpu.pc = data;
|
cpu.pc = data;
|
||||||
} else {
|
} else {
|
||||||
cpu.gpr[regno] = data;
|
cpu.gpr[regno] = data;
|
||||||
|
@ -76,6 +81,6 @@ int isa_write_reg(void *args, int regno, size_t data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT arch_info_t isa_arch_info = {.reg_num = 32,
|
__EXPORT arch_info_t isa_arch_info = {.reg_num = 33,
|
||||||
.reg_byte = MUXDEF(CONFIG_RV64, 8, 4),
|
.reg_byte = MUXDEF(CONFIG_RV64, 8, 4),
|
||||||
.target_desc = TARGET_RV32};
|
.target_desc = TARGET_RV32};
|
||||||
|
|
|
@ -13,16 +13,14 @@
|
||||||
* See the Mulan PSL v2 for more details.
|
* See the Mulan PSL v2 for more details.
|
||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#include <csr.h>
|
||||||
#include <isa.h>
|
#include <isa.h>
|
||||||
|
|
||||||
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
||||||
/* TODO: Trigger an interrupt/exception with ``NO''.
|
write_csr(cpu.csr, MEPC, epc);
|
||||||
* Then return the address of the interrupt/exception vector.
|
write_csr(cpu.csr, MCAUSE, NO);
|
||||||
*/
|
|
||||||
|
|
||||||
return 0;
|
return read_csr(cpu.csr, MTVEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
word_t isa_query_intr() {
|
word_t isa_query_intr() { return INTR_EMPTY; }
|
||||||
return INTR_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
|
@ -59,6 +59,11 @@ static void nemu_is_stopped(gdb_action_t *act, breakpoint_t *stopped_at) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NEMU_GDB_INTERRUPT:
|
||||||
|
act->reason = gdb_action_t::ACT_BREAKPOINT;
|
||||||
|
act->data = cpu.pc;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
act->reason = gdb_action_t::ACT_SHUTDOWN;
|
act->reason = gdb_action_t::ACT_SHUTDOWN;
|
||||||
act->data = nemu_state.halt_ret;
|
act->data = nemu_state.halt_ret;
|
||||||
|
@ -103,7 +108,7 @@ __EXPORT bool nemu_del_bp(void *args, size_t addr, bp_type_t type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT void nemu_on_interrupt(void *args) {
|
__EXPORT void nemu_on_interrupt(void *args) {
|
||||||
// fputs("Not implemented", stderr);
|
nemu_state.state = NEMU_GDB_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT int nemu_read_reg(void *args, int regno, size_t *data) {
|
__EXPORT int nemu_read_reg(void *args, int regno, size_t *data) {
|
||||||
|
@ -121,7 +126,8 @@ static struct target_ops nemu_gdbstub_ops = {.cont = nemu_cont,
|
||||||
.write_mem = nemu_write_mem,
|
.write_mem = nemu_write_mem,
|
||||||
.set_bp = nemu_set_bp,
|
.set_bp = nemu_set_bp,
|
||||||
.del_bp = nemu_del_bp,
|
.del_bp = nemu_del_bp,
|
||||||
.on_interrupt = NULL};
|
.on_interrupt = nemu_on_interrupt,
|
||||||
|
.monitor = NULL};
|
||||||
static DbgState *pdbg;
|
static DbgState *pdbg;
|
||||||
static gdbstub_t gdbstub_priv;
|
static gdbstub_t gdbstub_priv;
|
||||||
const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock";
|
const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock";
|
||||||
|
@ -152,7 +158,7 @@ __EXPORT void nemu_init(void *args) {
|
||||||
|
|
||||||
int gdbstub_loop() {
|
int gdbstub_loop() {
|
||||||
if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops,
|
if (!gdbstub_init(&gdbstub_priv, &nemu_gdbstub_ops,
|
||||||
(arch_info_t)isa_arch_info, SOCKET_ADDR)) {
|
(arch_info_t)isa_arch_info, NULL, SOCKET_ADDR)) {
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
printf("Waiting for gdb connection at %s", SOCKET_ADDR);
|
printf("Waiting for gdb connection at %s", SOCKET_ADDR);
|
||||||
|
|
Loading…
Reference in a new issue