#include #include #include #include struct MiniRV32IMAState; void ecall_handler(struct MiniRV32IMAState *state); #define ECALL_HANDLER(state) ecall_handler(state) #define MINIRV32WARN( x... ) printf( x ); #define MINIRV32_DECORATE static #define MINI_RV32_RAM_SIZE (32 * 1024 * 1024) #define MINIRV32_IMPLEMENTATION #define MINIRV32_RAM_IMAGE_OFFSET 0x0 #include "mini-rv32ima.h" #define SYSCALL(num) (1025 + num) void ecall_handler(struct MiniRV32IMAState *state) { uint32_t a0 = REG(10); uint32_t a1 = REG(11); switch (state->regs[17]) // x17 | a7 { case 1: // PrintInt printf("%d", a0); break; case 4: // PrintString printf("%s", a0); break; case 10: fprintf(stderr, "\nexit: %d\n", a0); exit(a0); case 11: // PrintChar printf("%c", a0); break; case 93: fprintf(stderr, "\nmain return code: %d\n", a0); exit(a0); case SYSCALL(0): // getchar(); REGSET(10, getchar()); case SYSCALL(1): // putchar putchar(a0); break; case SYSCALL(4): // input int scanf("%d", &a0); REGSET(10, a0); break; case SYSCALL(5): // input string scanf("%s", a0); REGSET(10, a0); break; default: MINIRV32WARN("Unhandled ECALL: %d\n", state->regs[17]); exit(1); break; } } int main(int argc, char *argv[]) { // gcc -DDEFAULT_FILE='\"flat.bin\"' .\ripes-vm.c -o rv32-vm.exe struct MiniRV32IMAState state; uint8_t *image = (uint8_t *)malloc(MINI_RV32_RAM_SIZE); // 初始化状态 memset(&state, 0, sizeof(state)); state.pc = 0; // 程序计数器从0开始 state.mstatus = 0x80000000; // 设置机器模式 state.mtvec = 0x1000; state.mie = 0x7; // 启用所有中断 // 初始化内存 memset(image, 0, MINI_RV32_RAM_SIZE); #ifndef DEFAULT_FILE #define DEFAULT_FILE "../ccompiler/backend/test_rv.bin" #endif const char* filename = DEFAULT_FILE; // 加载 flatbin 文件 if (argc == 2) { filename = argv[1]; } FILE *file = fopen(filename, "rb"); if (!file) { fprintf(stderr, "Usage: %s \n", argv[0]); printf("Failed to open file %s\n", filename); return 1; } fseek(file, 0, SEEK_END); long flen = ftell(file); fseek(file, 0, SEEK_SET); if (flen > MINI_RV32_RAM_SIZE) { fprintf(stderr, "Flatbin file is too large\n"); fclose(file); return 1; } fread(image, flen, 1, file); fclose(file); // 运行模拟器 while (1) { int32_t ret = MiniRV32IMAStep(&state, image, MINIRV32_RAM_IMAGE_OFFSET, 0, 1); if (ret != 0) { printf("Exception or interrupt occurred at PC: %d\n", state.pc); return ret; } } free(image); return 0; } // static void DumpState( struct MiniRV32IMAState * core, uint8_t * ram_image ) // { // uint32_t pc = core->pc; // uint32_t pc_offset = pc - MINIRV32_RAM_IMAGE_OFFSET; // uint32_t ir = 0; // printf( "PC: %08x ", pc ); // if( pc_offset >= 0 && pc_offset < ram_amt - 3 ) // { // ir = *((uint32_t*)(&((uint8_t*)ram_image)[pc_offset])); // printf( "[0x%08x] ", ir ); // } // else // printf( "[xxxxxxxxxx] " ); // uint32_t * regs = core->regs; // printf( "Z:%08x ra:%08x sp:%08x gp:%08x tp:%08x t0:%08x t1:%08x t2:%08x s0:%08x s1:%08x a0:%08x a1:%08x a2:%08x a3:%08x a4:%08x a5:%08x ", // regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], // regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15] ); // printf( "a6:%08x a7:%08x s2:%08x s3:%08x s4:%08x s5:%08x s6:%08x s7:%08x s8:%08x s9:%08x s10:%08x s11:%08x t3:%08x t4:%08x t5:%08x t6:%08x\n", // regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23], // regs[24], regs[25], regs[26], regs[27], regs[28], regs[29], regs[30], regs[31] ); // }