emulator-sr32.c (3915B)
1 // Copyright 2025, Brian Swetland <swetland@frotz.net> 2 // Licensed under the Apache License, Version 2.0. 3 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <unistd.h> 8 #include <fcntl.h> 9 10 #include <emulator-sr32.h> 11 12 #define RAMSIZE (8*1024*1024) 13 #define RAMMASK8 (RAMSIZE - 1) 14 #define RAMMASK32 (RAMMASK8 & (~3)) 15 #define RAMMASK16 (RAMMASK8 & (~1)) 16 uint8_t emu_ram[RAMSIZE]; 17 18 uint32_t mem_rd32(uint32_t addr) { 19 return *((uint32_t*) (emu_ram + (addr & RAMMASK32))); 20 } 21 uint32_t mem_rd16(uint32_t addr) { 22 return *((uint16_t*) (emu_ram + (addr & RAMMASK16))); 23 } 24 uint32_t mem_rd8(uint32_t addr) { 25 return *((uint8_t*) (emu_ram + (addr & RAMMASK8))); 26 } 27 28 void mem_wr32(uint32_t addr, uint32_t val) { 29 *((uint32_t*) (emu_ram + (addr & RAMMASK32))) = val; 30 } 31 void mem_wr16(uint32_t addr, uint32_t val) { 32 *((uint16_t*) (emu_ram + (addr & RAMMASK16))) = val; 33 } 34 void mem_wr8(uint32_t addr, uint32_t val) { 35 *((uint8_t*) (emu_ram + (addr & RAMMASK8))) = val; 36 } 37 38 void *mem_dma(uint32_t addr, uint32_t len) { 39 if (addr >= RAMSIZE) return 0; 40 if ((RAMSIZE - addr) < len) return 0; 41 return emu_ram + addr; 42 } 43 44 uint32_t io_rd32(CpuState *cs, uint32_t addr) { 45 return 0; 46 } 47 48 void io_wr32(CpuState *cs, uint32_t addr, uint32_t val) { 49 switch (addr) { 50 case -1: 51 uint8_t x = val; 52 if (write(2, &x, 1) != 1) ; 53 break; 54 case -2: 55 break; 56 case -3: 57 if (val) { 58 fprintf(stderr, "%08x %08x %08x %08x\n", 59 cs->r[20], cs->r[21], cs->r[22], cs->r[23]); 60 fprintf(stderr, "FAIL: CODE: %08x\n", val); 61 exit(1); 62 } 63 exit(0); 64 } 65 } 66 67 void do_syscall(CpuState *s, uint32_t n) { 68 } 69 70 void do_undef(CpuState *s, uint32_t ins) { 71 fprintf(stderr, "UNDEF INSTR (PC=%08x INS=%08x)\n", s->pc, ins); 72 exit(1); 73 } 74 75 void load_hex_image(const char* fn) { 76 char line[1024]; 77 FILE *fp = fopen(fn, "r"); 78 if (fp == NULL) { 79 fprintf(stderr, "emu: cannot open: %s\n", fn); 80 exit(1); 81 } 82 while (fgets(line, sizeof(line), fp) != NULL) { 83 if ((line[0] == '#') || (line[0] == '/')) { 84 continue; 85 } 86 if ((strlen(line) > 18) && (line[8] == ':')) { 87 uint32_t addr = strtoul(line, 0, 16); 88 uint32_t val = strtoul(line + 10, 0, 16); 89 mem_wr32(addr, val); 90 } 91 } 92 fclose(fp); 93 } 94 95 void usage(int status) { 96 fprintf(stderr, 97 "usage: emu <options> <image.hex> <arguments>\n" 98 "options: -x <datafile> Load Test Vector Data\n" 99 " -tf Trace Instruction Fetches\n" 100 " -tr Trace Register Writes\n" 101 " -tb Trace Branches\n" 102 " -ti Trace IO Reads & Writes\n"); 103 exit(status); 104 } 105 106 int main(int argc, char** argv) { 107 uint32_t entry = 0x100000; 108 const char* fn = NULL; 109 int args = 0; 110 111 CpuState cs; 112 memset(&cs, 0, sizeof(cs)); 113 memset(emu_ram, 0, sizeof(emu_ram)); 114 115 while (argc > 1) { 116 if (!strcmp(argv[1], "-tf")) { 117 cs.flags |= F_TRACE_FETCH; 118 } else if (!strcmp(argv[1], "-tr")) { 119 cs.flags |= F_TRACE_REGS; 120 } else if (!strcmp(argv[1], "-tb")) { 121 cs.flags |= F_TRACE_BRANCH; 122 } else if (!strcmp(argv[1], "-ti")) { 123 cs.flags |= F_TRACE_IO; 124 } else if (argv[1][0] == '-') { 125 fprintf(stderr, "emu: unknown option: %s\n", argv[1]); 126 return -1; 127 } else { 128 fn = argv[1]; 129 // arguments after the image file belong to the guest 130 args = argc - 2; 131 argv += 2; 132 break; 133 } 134 argc--; 135 argv++; 136 } 137 if (fn == NULL) { 138 usage(1); 139 } 140 141 load_hex_image(fn); 142 143 uint32_t sp = entry - 16; 144 uint32_t lr = sp; 145 mem_wr32(lr + 0, 0xfffd002b); 146 147 uint32_t guest_argc = args; 148 uint32_t guest_argv = 0; 149 if (args) { 150 sp -= (args + 1) * 4; 151 uint32_t p = sp; 152 guest_argv = p; 153 while (args > 0) { 154 uint32_t n = strlen(argv[0]) + 1; 155 sp -= (n + 3) & (~3); 156 for (uint32_t i = 0; i < n; i++) { 157 mem_wr8(sp + i, argv[0][i]); 158 } 159 mem_wr32(p, sp); 160 p += 4; 161 args--; 162 argv++; 163 } 164 mem_wr32(p, 0); 165 } 166 167 cs.pc = entry; 168 cs.r[1] = lr; 169 cs.r[2] = sp; 170 cs.r[10] = guest_argc; 171 cs.r[11] = guest_argv; 172 173 sr32core(&cs); 174 return 0; 175 }