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
|
||||
[submodule "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>
|
||||
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/am/src>
|
||||
$<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")
|
||||
target_sources(
|
||||
am_interface
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef ARCH_H__
|
||||
#define ARCH_H__
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __riscv_e
|
||||
#define NR_REGS 16
|
||||
|
@ -9,10 +10,13 @@
|
|||
|
||||
struct Context {
|
||||
// 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;
|
||||
};
|
||||
|
||||
enum Cause { CauseEnvironmentCallFromMMode = 11 };
|
||||
|
||||
#ifdef __riscv_e
|
||||
#define GPR1 gpr[15] // a5
|
||||
#else
|
||||
|
|
|
@ -6,7 +6,7 @@ int main(const char *args);
|
|||
|
||||
Area heap = RANGE(&_heap_start, PMEM_END);
|
||||
#ifndef MAINARGS
|
||||
#define MAINARGS "5"
|
||||
#define MAINARGS "i"
|
||||
#endif
|
||||
static const char mainargs[] = MAINARGS;
|
||||
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
#include "arch/riscv.h"
|
||||
#include <am.h>
|
||||
#include <riscv/riscv.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) {
|
||||
Event ev = {0};
|
||||
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);
|
||||
|
@ -20,7 +27,7 @@ Context* __am_irq_handle(Context *c) {
|
|||
|
||||
extern void __am_asm_trap(void);
|
||||
|
||||
bool cte_init(Context*(*handler)(Event, Context*)) {
|
||||
bool cte_init(Context *(*handler)(Event, Context *)) {
|
||||
// initialize exception entry
|
||||
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) {
|
||||
return NULL;
|
||||
Context *c = kstack.end - sizeof(Context);
|
||||
c->mepc = (uintptr_t)entry;
|
||||
c->gpr[10] = (uintptr_t)arg;
|
||||
return c;
|
||||
}
|
||||
|
||||
void yield() {
|
||||
|
@ -42,9 +52,6 @@ void yield() {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool ienabled() {
|
||||
return false;
|
||||
}
|
||||
bool ienabled() { return false; }
|
||||
|
||||
void iset(bool enable) {
|
||||
}
|
||||
void iset(bool enable) {}
|
||||
|
|
|
@ -60,6 +60,8 @@ __am_asm_trap:
|
|||
mv a0, sp
|
||||
jal __am_irq_handle
|
||||
|
||||
mv sp, a0
|
||||
|
||||
LOAD t1, OFFSET_STATUS(sp)
|
||||
LOAD t2, OFFSET_EPC(sp)
|
||||
csrw mstatus, t1
|
||||
|
|
|
@ -15,6 +15,9 @@ stdenv.mkDerivation {
|
|||
(lib.cmakeFeature "ISA" isa)
|
||||
] ++ map (p: (lib.cmakeBool "__PLATFORM_${lib.strings.toUpper p}__" true)) platform;
|
||||
|
||||
cmakeBuildType = "Debug";
|
||||
dontStrip = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
];
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 02b38e7b44f673f808abcb3bf9464811f8c58d4b
|
||||
Subproject commit 8c4ea046225e2dce599dc36aeef6c4c857996d00
|
|
@ -128,11 +128,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1721457008,
|
||||
"narHash": "sha256-ekpve0om5hzC1Ntd3zm1cZ9oS5pnr7a2n/tueyqFOsg=",
|
||||
"lastModified": 1721891452,
|
||||
"narHash": "sha256-2c9nDuXXARzoRXE67lte5kKBeFb1XmTNsvdiIbRUEgE=",
|
||||
"ref": "refs/heads/master",
|
||||
"rev": "e7aa3319d52fa987ac2192f63aef3dcb1b057e3a",
|
||||
"revCount": 151,
|
||||
"rev": "de8ad578fc4fe527772cec23a7f660bde14c8570",
|
||||
"revCount": 152,
|
||||
"type": "git",
|
||||
"url": "https://git.xinyang.life/xin/nur.git"
|
||||
},
|
||||
|
|
|
@ -64,13 +64,14 @@
|
|||
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-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 {
|
||||
packages = with pkgs; [
|
||||
clang-tools
|
||||
gdb
|
||||
gef
|
||||
SDL2
|
||||
gnumake
|
||||
pkg-config
|
||||
|
|
1
nemu/.gitignore
vendored
1
nemu/.gitignore
vendored
|
@ -9,6 +9,7 @@ build/
|
|||
.envrc
|
||||
.metals/
|
||||
.vscode/
|
||||
.zed/
|
||||
compile_commands.json
|
||||
|
||||
### C ###
|
||||
|
|
|
@ -20,7 +20,14 @@
|
|||
|
||||
// ----------- 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 {
|
||||
int state;
|
||||
|
@ -36,42 +43,41 @@ uint64_t get_time();
|
|||
|
||||
// ----------- log -----------
|
||||
|
||||
#define ANSI_FG_BLACK "\33[1;30m"
|
||||
#define ANSI_FG_RED "\33[1;31m"
|
||||
#define ANSI_FG_GREEN "\33[1;32m"
|
||||
#define ANSI_FG_YELLOW "\33[1;33m"
|
||||
#define ANSI_FG_BLUE "\33[1;34m"
|
||||
#define ANSI_FG_BLACK "\33[1;30m"
|
||||
#define ANSI_FG_RED "\33[1;31m"
|
||||
#define ANSI_FG_GREEN "\33[1;32m"
|
||||
#define ANSI_FG_YELLOW "\33[1;33m"
|
||||
#define ANSI_FG_BLUE "\33[1;34m"
|
||||
#define ANSI_FG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_FG_CYAN "\33[1;36m"
|
||||
#define ANSI_FG_WHITE "\33[1;37m"
|
||||
#define ANSI_BG_BLACK "\33[1;40m"
|
||||
#define ANSI_BG_RED "\33[1;41m"
|
||||
#define ANSI_BG_GREEN "\33[1;42m"
|
||||
#define ANSI_BG_YELLOW "\33[1;43m"
|
||||
#define ANSI_BG_BLUE "\33[1;44m"
|
||||
#define ANSI_FG_CYAN "\33[1;36m"
|
||||
#define ANSI_FG_WHITE "\33[1;37m"
|
||||
#define ANSI_BG_BLACK "\33[1;40m"
|
||||
#define ANSI_BG_RED "\33[1;41m"
|
||||
#define ANSI_BG_GREEN "\33[1;42m"
|
||||
#define ANSI_BG_YELLOW "\33[1;43m"
|
||||
#define ANSI_BG_BLUE "\33[1;44m"
|
||||
#define ANSI_BG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_BG_CYAN "\33[1;46m"
|
||||
#define ANSI_BG_WHITE "\33[1;47m"
|
||||
#define ANSI_NONE "\33[0m"
|
||||
#define ANSI_BG_CYAN "\33[1;46m"
|
||||
#define ANSI_BG_WHITE "\33[1;47m"
|
||||
#define ANSI_NONE "\33[0m"
|
||||
|
||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE
|
||||
|
||||
#define log_write(...) IFDEF(CONFIG_TARGET_NATIVE_ELF, \
|
||||
do { \
|
||||
extern FILE* log_fp; \
|
||||
extern bool log_enable(); \
|
||||
if (log_enable()) { \
|
||||
fprintf(log_fp, __VA_ARGS__); \
|
||||
fflush(log_fp); \
|
||||
} \
|
||||
} while (0) \
|
||||
)
|
||||
#define log_write(...) \
|
||||
IFDEF( \
|
||||
CONFIG_TARGET_NATIVE_ELF, do { \
|
||||
extern FILE *log_fp; \
|
||||
extern bool log_enable(); \
|
||||
if (log_enable()) { \
|
||||
fprintf(log_fp, __VA_ARGS__); \
|
||||
fflush(log_fp); \
|
||||
} \
|
||||
} while (0))
|
||||
|
||||
#define _Log(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
log_write(__VA_ARGS__); \
|
||||
#define _Log(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
log_write(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -158,8 +158,6 @@ breakpoint_t *cpu_exec_with_bp(uint64_t n, breakpoint_t *bp, size_t len) {
|
|||
static Decode s;
|
||||
nemu_state.state = NEMU_RUNNING;
|
||||
do {
|
||||
exec_once(&s, cpu.pc);
|
||||
g_nr_guest_inst++;
|
||||
for (int i = 0; i < len; i++) {
|
||||
size_t addr = bp[i].addr;
|
||||
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;
|
||||
}
|
||||
}
|
||||
exec_once(&s, cpu.pc);
|
||||
g_nr_guest_inst++;
|
||||
if (nemu_state.state != NEMU_RUNNING)
|
||||
return NULL;
|
||||
} while (--n);
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <device/map.h>
|
||||
#include <generated/autoconf.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define KEYDOWN_MASK 0x8000
|
||||
|
@ -22,28 +25,27 @@
|
|||
#include <SDL2/SDL.h>
|
||||
|
||||
// Note that this is not the standard
|
||||
#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(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(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(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(LSHIFT) f(Z) f(X) 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_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(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(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(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(LSHIFT) f(Z) f(X) \
|
||||
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 {
|
||||
NEMU_KEY_NONE = 0,
|
||||
MAP(NEMU_KEYS, NEMU_KEY_NAME)
|
||||
};
|
||||
enum { 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 void init_keymap() {
|
||||
MAP(NEMU_KEYS, SDL_KEYMAP)
|
||||
}
|
||||
static void init_keymap() { MAP(NEMU_KEYS, SDL_KEYMAP) }
|
||||
|
||||
#define KEY_QUEUE_LEN 1024
|
||||
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[0] = NEMU_KEY_NONE;
|
||||
#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
|
||||
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
|
||||
IFNDEF(CONFIG_TARGET_AM, init_keymap());
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <device/map.h>
|
||||
#include <generated/autoconf.h>
|
||||
#include <utils.h>
|
||||
|
||||
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <assert.h>
|
||||
#include <device/alarm.h>
|
||||
#include <device/map.h>
|
||||
#include <generated/autoconf.h>
|
||||
#include <utils.h>
|
||||
|
||||
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>
|
||||
|
||||
#define CSR_SIZE (0x1000)
|
||||
|
||||
typedef word_t csr_t[CSR_SIZE];
|
||||
|
||||
typedef struct {
|
||||
word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)];
|
||||
// word_t csr[MUXDEF(CONFIG_RVE, )]
|
||||
csr_t csr;
|
||||
vaddr_t pc;
|
||||
} MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include "isa.h"
|
||||
#include "local-include/reg.h"
|
||||
#include "macro.h"
|
||||
#include "types.h"
|
||||
|
@ -20,6 +21,7 @@
|
|||
#include <cpu/cpu.h>
|
||||
#include <cpu/decode.h>
|
||||
#include <cpu/ifetch.h>
|
||||
#include <csr.h>
|
||||
#include <ftrace.h>
|
||||
#include <utils.h>
|
||||
|
||||
|
@ -33,6 +35,8 @@ enum {
|
|||
TYPE_S,
|
||||
TYPE_B,
|
||||
TYPE_J,
|
||||
TYPE_CSR,
|
||||
TYPE_CSRI,
|
||||
TYPE_N, // none
|
||||
};
|
||||
|
||||
|
@ -66,6 +70,14 @@ enum {
|
|||
*imm = SEXT(BITS(i, 31, 31), 1) << 20 | BITS(i, 30, 21) << 1 | \
|
||||
BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; \
|
||||
} 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,
|
||||
word_t *imm, int type) {
|
||||
|
@ -98,6 +110,14 @@ static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2,
|
|||
src2R();
|
||||
immB();
|
||||
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,
|
||||
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_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 "csr.h"
|
||||
#include "macro.h"
|
||||
#include <errno.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) {
|
||||
if (regno > 32) {
|
||||
if (regno > 33) {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
if (regno == 32) {
|
||||
if (regno == 33) {
|
||||
*reg_value = cpu.csr[MTVEC];
|
||||
} else if (regno == 32) {
|
||||
*reg_value = cpu.pc;
|
||||
} else {
|
||||
*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) {
|
||||
if (regno > 32) {
|
||||
if (regno > 33) {
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
if (regno == 32) {
|
||||
if (regno == 33) {
|
||||
cpu.csr[MTVEC] = data;
|
||||
} else if (regno == 32) {
|
||||
cpu.pc = data;
|
||||
} else {
|
||||
cpu.gpr[regno] = data;
|
||||
|
@ -76,6 +81,6 @@ int isa_write_reg(void *args, int regno, size_t data) {
|
|||
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),
|
||||
.target_desc = TARGET_RV32};
|
||||
|
|
|
@ -13,16 +13,14 @@
|
|||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <csr.h>
|
||||
#include <isa.h>
|
||||
|
||||
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
||||
/* TODO: Trigger an interrupt/exception with ``NO''.
|
||||
* Then return the address of the interrupt/exception vector.
|
||||
*/
|
||||
write_csr(cpu.csr, MEPC, epc);
|
||||
write_csr(cpu.csr, MCAUSE, NO);
|
||||
|
||||
return 0;
|
||||
return read_csr(cpu.csr, MTVEC);
|
||||
}
|
||||
|
||||
word_t isa_query_intr() {
|
||||
return INTR_EMPTY;
|
||||
}
|
||||
word_t isa_query_intr() { return INTR_EMPTY; }
|
||||
|
|
|
@ -59,6 +59,11 @@ static void nemu_is_stopped(gdb_action_t *act, breakpoint_t *stopped_at) {
|
|||
}
|
||||
break;
|
||||
|
||||
case NEMU_GDB_INTERRUPT:
|
||||
act->reason = gdb_action_t::ACT_BREAKPOINT;
|
||||
act->data = cpu.pc;
|
||||
break;
|
||||
|
||||
default:
|
||||
act->reason = gdb_action_t::ACT_SHUTDOWN;
|
||||
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) {
|
||||
// fputs("Not implemented", stderr);
|
||||
nemu_state.state = NEMU_GDB_INTERRUPT;
|
||||
}
|
||||
|
||||
__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,
|
||||
.set_bp = nemu_set_bp,
|
||||
.del_bp = nemu_del_bp,
|
||||
.on_interrupt = NULL};
|
||||
.on_interrupt = nemu_on_interrupt,
|
||||
.monitor = NULL};
|
||||
static DbgState *pdbg;
|
||||
static gdbstub_t gdbstub_priv;
|
||||
const char SOCKET_ADDR[] = "/tmp/gdbstub-nemu.sock";
|
||||
|
@ -152,7 +158,7 @@ __EXPORT void nemu_init(void *args) {
|
|||
|
||||
int gdbstub_loop() {
|
||||
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;
|
||||
}
|
||||
printf("Waiting for gdb connection at %s", SOCKET_ADDR);
|
||||
|
|
Loading…
Reference in a new issue