rvemu

RISC-V RV32I execution engine
git clone git://mcdim.xyz/revemu.git
Log | Files | Refs

main.c (4394B)


      1 #include <stdint.h>
      2 #include <inttypes.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 //#include "disasm.h"
      8 #include "exec.h"
      9 #include "mem.h"
     10 #include "disasm.h"
     11 
     12 typedef enum {
     13 	MODE_RUN,
     14 	MODE_STEP
     15 } emu_mode_t;
     16 
     17 static void
     18 load_program(uint8_t *mem)
     19 {
     20 	/* program */
     21 	uint32_t arr[] = {
     22 	0xfff00093,  // addi  x1, x0, -1
     23 	0xfff04113,  // xori  x2, x0, -1
     24 	0xfff06193,  // ori   x3, x0, -1
     25 	0xfff17213,  // andi  x4, x2, -1
     26 	0xfff02293,  // slti  x5, x0, -1
     27 	0xfff03313   // sltiu x6, x0, -1
     28 /*
     29 	0xfff00093,	// li      ra,-1
     30 	0xfff04113,	// not     sp,zero
     31 	0xfff06193,	// ori     gp,zero,-1
     32 	0xfff17213,	// andi    tp,sp,-1
     33 	0xfff02293,	// slti    t0,zero,-1
     34 	0xfff03313,	// sltiu   t1,zero,-1
     35 	0x00100073 	// ebreak
     36 */
     37 /*
     38       0x00700513,  // addi x10, x0, 7
     39       0x00451513,  // slli x10, x10, 4
     40       0x00d50513,  // addi x10, x10, 13
     41       0x05554513,  // xori x10, x10, 0x55
     42       0xff750513,  // addi x10, x10, -9
     43       0x00100073   // ebreak
     44 */
     45 /*
     46 0x10000593,	//li      a1,256
     47 0xfff00513,	//li      a0,-1
     48 0x00a58023,	//sb      a0,0(a1)
     49 0x0005c503,	//lbu     a0,0(a1)
     50 0x00150513,	//addi    a0,a0,1
     51 0x00a59123,	//sh      a0,2(a1)
     52 0x00259503,	//lh      a0,2(a1)
     53 0xeff50513,	//addi    a0,a0,-257
     54 0x00a58223,	//sb      a0,4(a1)
     55 0x00458503,	//lb      a0,4(a1)
     56 0x00a59323,	//sh      a0,6(a1)
     57 0x00659503,	//lh      a0,6(a1)
     58 0x0065d503,	//lhu     a0,6(a1)
     59 0x00150513,	//addi    a0,a0,1
     60 0x00a5a423,	//sw      a0,8(a1)
     61 0x00000513,	//li      a0,0
     62 0x0085a503,	//lw      a0,8(a1)
     63 0x00000593,	//li      a1,0
     64 0x00100073	//ebreak
     65 */
     66 /*
     67       0x00200093,  // addi x1, x0, 2
     68       0x00000113,  // addi x2, x0, 0
     69       0x05c00193,  // addi x3, x0, 0x5c
     70       0x00110113,  // addi x2, x2, 1
     71       0x0021a023,  // sw   x2, 0(x3)
     72       0x00418193,  // addi x3, x3, 4
     73       0xfff08093,  // addi x1, x1, -1
     74       0xfe0098e3,  // bne  x1, x0, -16
     75       0x00100073   // ebreak
     76 */
     77 
     78 	};
     79 
     80 	size_t len = sizeof(arr) / sizeof(arr[0]);
     81 
     82 	int b = 0; /*byte*/
     83 	for (size_t i=0; i<len; i++) {
     84 		
     85 		mem[b+0] = (uint8_t)(arr[i] >> 0);
     86 		mem[b+1] = (uint8_t)(arr[i] >> 8);
     87 		mem[b+2] = (uint8_t)(arr[i] >> 16);
     88 		mem[b+3] = (uint8_t)(arr[i] >> 24);
     89 
     90 		b+=4;
     91 	}
     92 }
     93 
     94 static emu_mode_t
     95 trap_handler(cpu_state_t *cpu)
     96 {
     97 	if (cpu->status == CPU_TRAPPED) {
     98 		printf("CPU trapped\n");
     99 		switch(cpu->trap.cause) {
    100 		case TRAP_EBREAK:
    101 			printf("Code reached breakpoint\n");
    102 			break;
    103 		case TRAP_ECALL:
    104 			printf("Code ECALL\n");
    105 			break;
    106 		case TRAP_ILLEGAL_INSTRUCTION:
    107 			printf("Illegal instruction\n");
    108 			break;
    109 		case TRAP_INSTRUCTION_MISALIGNED: 
    110 			printf("Instruction misaligned\n");
    111 			break;
    112 		case TRAP_INSTRUCTION_ACCESS_FAULT: 
    113 			printf("Instruction access fault\n");
    114 			break;
    115 		case TRAP_NONE:
    116 			printf("No trap cause\n");
    117 			break;
    118 		}
    119 		return MODE_STEP;
    120 	}
    121 	return MODE_RUN;
    122 }
    123 
    124 static emu_mode_t
    125 debugger(cpu_state_t *cpu, uint8_t *mem)
    126 {
    127 	printf("PC 0x%x>", cpu->pc);
    128 	char line[256];
    129 	if (!fgets(line, sizeof(line), stdin)) {
    130 		fprintf(stderr, "Error reading"
    131 			"interactive input\n");
    132 	}
    133 
    134 	if (strncmp(line, "s", 1) == 0 ||
    135 	    strncmp(line, "step", 4) == 0  ||
    136 	    strncmp(line, "n", 1) == 0 ||
    137 	    strncmp(line, "next", 4) == 0) {
    138 
    139 		uint32_t inst = load_u32_le(mem, cpu->pc); /* load little endian */
    140 		disassemble_instruction(inst);
    141 		cpu_step(cpu, mem);
    142 
    143 		trap_handler(cpu);
    144 
    145 	} else if (strncmp(line, "r", 1) == 0 ||
    146 		   strncmp(line, "registers", 9) == 0) {
    147 		printf("Registers:\n");
    148 		for (int i=0; i<32; i++) {
    149 			printf("0x%x: 0x%x\n", i, cpu->x[i]);
    150 		}
    151 	} else if (strncmp(line, "m", 1) == 0 ||
    152 		   strncmp(line, "memory", 6) == 0) {
    153 		printf("Memory:\n");
    154 		for (uint32_t i=0; i<128; i+=4) {
    155 			if (cpu->pc == i) {
    156 				printf("-> ");
    157 			} else {
    158 				printf("   ");
    159 			}
    160 			printf("0x%.8x: 0x%.2x 0x%.2x 0x%.2x 0x%.2x     ",
    161 			       i, mem[i], mem[i+1], mem[i+2], mem[i+3]);
    162 			disassemble_instruction(load_u32_le(mem,i));
    163 		}
    164 	} else if (strncmp(line, "ip", 2) == 0 ||
    165 		   strncmp(line, "pc", 2) == 0) {
    166 		printf("Instruction poiter:\n");
    167 		printf("PC: %" PRIu32 "\n", cpu->pc);
    168 	} else if (strncmp(line, "e", 1) == 0) {
    169 		return MODE_RUN;
    170 	}
    171 
    172 	return MODE_STEP;
    173 }
    174 
    175 int
    176 main()
    177 {
    178 	cpu_state_t cpu = {0};
    179 
    180 	uint8_t mem[MEMSIZE] = {0};
    181 
    182 	load_program(mem);
    183 	
    184 	/* fetch & run */
    185 	emu_mode_t mode = MODE_STEP;	
    186 
    187 	while (1) {
    188 		if (mode == MODE_RUN) {
    189 			cpu_step(&cpu, mem);
    190 			mode = trap_handler(&cpu);
    191 		} else {
    192 			mode = debugger(&cpu, mem);
    193 		}
    194 	}
    195 
    196 	return 0;
    197 }