spl

systems programming language
git clone http://frotz.net/git/spl.git
Log | Files | Refs | README | LICENSE

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 }