// This file is included by srve_core.h to define the structures for either a // 64-bit or 32-bit core. It is only included once for each bit size. // Some definitions in here are still common to both 64-bit and 32-bit code so // they are only defined once. #ifndef SRVE_CORE_H_COMMON #define SRVE_CORE_H_COMMON // This is similar to the rv_bus_cb type in Max Nurzia's RISC-V emulator. typedef int (*srve_memfunc_t)(void* memory, uint64_t address, void* buffer, unsigned int storing, unsigned int size); typedef struct srve_debugsymbol srve_debugsymbol_t; struct srve_debugsymbol { uint64_t addr; char* name; srve_debugsymbol_t* next; }; #endif typedef STRUCT_SRVE_CORE SRVE_CORE_T; // Type of a function which handles an instruction, returning 0 on success or // non-zero on failure. These functions are called inbetween fetching and // incrementing the instruction pointer, and there is generally one function // per major instruction (per instruction-group) with the function pointers // stored in the core structure. This allows for easy replacement of functions // for special debugging purposes (e.g. for tracking jump instructions only or // for checking load/store instructions for alignment). typedef int (*SRVE_CORE_INSTRFUNC_T)(SRVE_CORE_T* core, uint32_t instr); STRUCT_SRVE_CORE { void* memory; srve_memfunc_t memfunc; srve_debugsymbol_t* symbols; // This is managed externally, but is a sorted list that can be checked for debug names SRVE_UREG_T ip; // Instruction pointer SRVE_UREG_T ip_next; // Next instruction pointer SRVE_UREG_T pagetable; // Address of the page table (not quite the same format as when accessed in satp) SRVE_UREG_T mepc; // Stored machine mode instruction pointer (program counter) SRVE_UREG_T sepc; // System mode exception instruction pointer SRVE_UREG_T stvec; // Vector handler address (& flags in bottom two bits) SRVE_UREG_T sscratch; // Scratch register SRVE_UREG_T scause; SRVE_UREG_T tracing; SRVE_SREG_T registers[32]; SRVE_CORE_INSTRFUNC_T instrfuncs[128]; // There are 128 possible major instructions }; int SRVE_CORE_INIT(SRVE_CORE_T* core, srve_memfunc_t memfunc, void* memdata, SRVE_UREG_T ip); // This instruction function is invoked for any unimplemented functions. int SRVE_CORE_INSTR_BAD(SRVE_CORE_T* core, uint32_t instr); // The main ALU instructions are divided between two major opcodes, one dealing // with registers only and the other where immediate values are combined with // registers. int SRVE_CORE_INSTR_REGALU(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_IMMALU(SRVE_CORE_T* core, uint32_t instr); // The typical memory-to-register load instructions are all one major opcode int SRVE_CORE_INSTR_LOAD(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_STORE(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_LUI(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_AUIPC(SRVE_CORE_T* core, uint32_t instr); // The syscall instruction seems to be extended for other "system" features too int SRVE_CORE_INSTR_SYSTEM(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_BRANCH(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_JAL(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_INSTR_JALR(SRVE_CORE_T* core, uint32_t instr); int SRVE_CORE_DOALU(SRVE_CORE_T* core, SRVE_SREG_T* outputvar, SRVE_SREG_T lhs, int op, SRVE_SREG_T rhs, int modifier); // Returns the "physical" address of the given "virtual" address. SRVE_UREG_T SRVE_CORE_TRANSLATE(SRVE_CORE_T* core, SRVE_UREG_T vaddr); int SRVE_CORE_LOAD(SRVE_CORE_T* core, uint64_t addr, void* buffer, unsigned int size); int SRVE_CORE_STORE(SRVE_CORE_T* core, uint64_t addr, void* buffer, unsigned int size); int SRVE_CORE_READCSR(SRVE_CORE_T* core, int addr, SRVE_UREG_T* outputvar); int SRVE_CORE_WRITECSR(SRVE_CORE_T* core, int addr, SRVE_UREG_T value); int SRVE_CORE_FETCH(SRVE_CORE_T* core, uint32_t* instrvar); // Looks through debug symbols to find a function name, returns the associated // symbol or a dummy string if the symbol table or function doesn't exist. This // is usually called with the instruction pointer as the address to reveal where // the program is currently at. const char* SRVE_CORE_FUNCNAME(SRVE_CORE_T* core, SRVE_UREG_T addr); SRVE_SREG_T SRVE_CORE_DOINSTR(SRVE_CORE_T* core);