main.c (4622B)
1 #include <stdint.h> 2 #include <inttypes.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 #ifdef HAVE_READLINE 8 #include <readline/history.h> 9 #include <readline/readline.h> 10 #endif 11 12 //#include "disasm.h" 13 #include "exec.h" 14 #include "mem.h" 15 #include "disasm.h" 16 17 typedef enum { 18 MODE_RUN, 19 MODE_STEP 20 } emu_mode_t; 21 22 static void 23 load_program(uint8_t *mem) 24 { 25 /* PROGRAM */ 26 uint32_t arr[] = { 27 0x10000593, //li a1,256 28 0xfff00513, //li a0,-1 29 0x00a58023, //sb a0,0(a1) 30 0x0005c503, //lbu a0,0(a1) 31 0x00150513, //addi a0,a0,1 32 0x00a59123, //sh a0,2(a1) 33 0x00259503, //lh a0,2(a1) 34 0xeff50513, //addi a0,a0,-257 35 0x00a58223, //sb a0,4(a1) 36 0x00458503, //lb a0,4(a1) 37 0x00a59323, //sh a0,6(a1) 38 0x00659503, //lh a0,6(a1) 39 0x0065d503, //lhu a0,6(a1) 40 0x00150513, //addi a0,a0,1 41 0x00a5a423, //sw a0,8(a1) 42 0x00000513, //li a0,0 43 0x0085a503, //lw a0,8(a1) 44 0x00000593, //li a1,0 45 0x00100073 //ebreak 46 /* 47 0x20400093, // addi x1,x0,0x204 48 0x12300113, // addi x2,x0,0x123 49 0xfe20ae23, // sw x2,-4(x1) -> address 0x200 50 0xffc0a183, // lw x3,-4(x1) 51 0x00100073, // ebreak 52 */ 53 }; 54 55 size_t len = sizeof(arr) / sizeof(arr[0]); 56 57 int b = 0; /*byte*/ 58 for (size_t i=0; i<len; i++) { 59 60 mem[b+0] = (uint8_t)(arr[i] >> 0); 61 mem[b+1] = (uint8_t)(arr[i] >> 8); 62 mem[b+2] = (uint8_t)(arr[i] >> 16); 63 mem[b+3] = (uint8_t)(arr[i] >> 24); 64 65 b+=4; 66 } 67 } 68 69 static emu_mode_t 70 trap_handler(cpu_state_t *cpu) 71 { 72 if (cpu->status == CPU_TRAPPED) { 73 printf("CPU trapped\n"); 74 switch(cpu->trap.cause) { 75 case TRAP_EBREAK: 76 printf("Code reached breakpoint\n"); 77 break; 78 case TRAP_ECALL: 79 printf("Code ECALL\n"); 80 break; 81 case TRAP_ILLEGAL_INSTRUCTION: 82 printf("Illegal instruction\n"); 83 break; 84 case TRAP_INSTRUCTION_MISALIGNED: 85 printf("Instruction misaligned\n"); 86 break; 87 case TRAP_INSTRUCTION_ACCESS_FAULT: 88 printf("Instruction access fault\n"); 89 break; 90 case TRAP_LOAD_MISALIGNED: 91 printf("Load misaligned\n"); 92 break; 93 case TRAP_LOAD_ACCESS_FAULT: 94 printf("Load access fault\n"); 95 break; 96 case TRAP_STORE_MISALIGNED: 97 printf("Store misaligned\n"); 98 break; 99 case TRAP_STORE_ACCESS_FAULT: 100 printf("Store access fault\n"); 101 break; 102 case TRAP_NONE: 103 printf("No trap cause\n"); 104 break; 105 } 106 return MODE_STEP; 107 } 108 return MODE_RUN; 109 } 110 111 static emu_mode_t 112 debugger(cpu_state_t *cpu, uint8_t *mem) 113 { 114 #ifdef HAVE_READLINE 115 char prompt[10]; 116 snprintf(prompt, 10, "PC 0x%x>", cpu->pc); 117 char *line; 118 line = readline(prompt); 119 rl_bind_key('\t', rl_complete); 120 121 if (!line) { 122 free(line); 123 return MODE_STEP; 124 } 125 126 add_history(line); 127 #else 128 printf("PC 0x%x>", cpu->pc); 129 char line[256]; 130 if (!fgets(line, sizeof(line), stdin)) { 131 fprintf(stderr, "Error reading" 132 "interactive input\n"); 133 } 134 #endif 135 136 if (strncmp(line, "s", 1) == 0 || 137 strncmp(line, "step", 4) == 0 || 138 strncmp(line, "n", 1) == 0 || 139 strncmp(line, "next", 4) == 0) { 140 141 uint32_t inst = load_u32_le(mem, cpu->pc); /* load little endian */ 142 disassemble_instruction(inst); 143 cpu_step(cpu, mem); 144 145 trap_handler(cpu); 146 147 } else if (strncmp(line, "r", 1) == 0 || 148 strncmp(line, "registers", 9) == 0) { 149 printf("Registers:\n"); 150 for (int i=0; i<32; i++) { 151 printf("x%d: 0x%x\n", i, cpu->x[i]); 152 } 153 } else if (strncmp(line, "x", 1) == 0) { 154 uint32_t from_addr = 0; 155 uint32_t count = 1; 156 sscanf(line, "x/%" SCNu32 " %" SCNx32, &count, &from_addr); 157 158 uint32_t xtarget = count*4 + from_addr; 159 /* TODO: probably some kind or helper or something */ 160 /* if (xtarget+3 > MEMSIZE) { 161 printf("Out of bounds\n"); 162 #ifdef HAVE_READLINE 163 free(line); 164 #endif 165 return MODE_RUN; 166 } 167 */ 168 169 for (uint32_t i=from_addr; i<xtarget; i+=4) { 170 if (cpu->pc == i) { 171 printf("-> "); 172 } else { 173 printf(" "); 174 } 175 printf("0x%.8x: 0x%.2x 0x%.2x 0x%.2x 0x%.2x ", 176 i, mem[i], mem[i+1], mem[i+2], mem[i+3]); 177 disassemble_instruction(load_u32_le(mem,i)); 178 } 179 } else if (strncmp(line, "ip", 2) == 0 || 180 strncmp(line, "pc", 2) == 0) { 181 printf("Instruction poiter:\n"); 182 printf("PC: %" PRIu32 "\n", cpu->pc); 183 } else if (strncmp(line, "e", 1) == 0) { 184 #ifdef HAVE_READLINE 185 free(line); 186 #endif 187 return MODE_RUN; 188 } 189 190 #ifdef HAVE_READLINE 191 free(line); 192 #endif 193 return MODE_STEP; 194 } 195 196 int 197 main() 198 { 199 cpu_state_t cpu = {0}; 200 201 uint8_t mem[MEMSIZE] = {0}; 202 203 load_program(mem); 204 205 /* fetch & run */ 206 emu_mode_t mode = MODE_STEP; 207 208 while (1) { 209 if (mode == MODE_RUN) { 210 cpu_step(&cpu, mem); 211 mode = trap_handler(&cpu); 212 } else { 213 mode = debugger(&cpu, mem); 214 } 215 } 216 217 return 0; 218 }