commit 35a56d75b4612c7ee70e5819c6cdf87a98facd14
parent 6528e9a009a40807ed4e97a6a3fd806feb2c4b50
Author: Brian Swetland <swetland@frotz.net>
Date: Sun, 29 Jun 2025 15:58:24 -0700
softrisc32: rename source files for clarity and autocompletion
Diffstat:
8 files changed, 361 insertions(+), 361 deletions(-)
diff --git a/softrisc32/Makefile b/softrisc32/Makefile
@@ -11,13 +11,13 @@ bin/mkinstab: src/mkinstab.c
@mkdir -p bin
gcc $(CFLAGS) -o $@ src/mkinstab.c
-bin/asm: src/sr32asm.c src/sr32dis.c src/sr32.h gen/instab.h
+bin/asm: src/assemble-sr32.c src/disassemble-sr32.c src/sr32.h gen/instab.h
@mkdir -p bin
- gcc $(CFLAGS) -o $@ src/sr32asm.c src/sr32dis.c
+ gcc $(CFLAGS) -o $@ src/assemble-sr32.c src/disassemble-sr32.c
-bin/emu: src/sr32emu.c src/sr32cpu.c src/sr32emu.h src/sr32.h
+bin/emu: src/emulator-sr32.c src/cpu-sr32.c src/emulator-sr32.h src/sr32.h
@mkdir -p bin
- gcc $(CFLAGS) -o $@ src/sr32emu.c src/sr32cpu.c
+ gcc $(CFLAGS) -o $@ src/emulator-sr32.c src/cpu-sr32.c
clean:
rm -rf gen bin
diff --git a/softrisc32/src/sr32asm.c b/softrisc32/src/assemble-sr32.c
diff --git a/softrisc32/src/cpu-sr32.c b/softrisc32/src/cpu-sr32.c
@@ -0,0 +1,126 @@
+// Copyright 2025, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include <emulator-sr32.h>
+
+#define WITH_TRACE 1
+
+void sr32core(CpuState *s) {
+ int32_t a, b, n;
+ uint32_t pc = s->pc;
+ for (;;) {
+ int32_t ins = mem_rd32(pc);
+#if WITH_TRACE
+ if (s->flags & F_TRACE_FETCH) {
+ fprintf(stderr,"%08x %08x\n", pc, ins);
+ }
+#endif
+ pc += 4;
+ switch ((ins >> 3) & 7) {
+ case 0b000:
+ case 0b001:
+ case 0b010:
+ case 0b011: // I/R
+ a = s->r[(ins >> 11) & 31];
+ b = ins >> 16;
+ if (ins & 0b010000) b = s->r[b & 31];
+ switch (ins & 15) {
+ case 0x0: n = a + b; break;
+ case 0x1: n = a - b; break;
+ case 0x2: n = a & b; break;
+ case 0x3: n = a | b; break;
+ case 0x4: n = a ^ b; break;
+ case 0x5: n = a << (b & 31); break;
+ case 0x6: n = ((uint32_t)a) >> (b & 31); break;
+ case 0x7: n = a >> (b & 31); break;
+ case 0x8: n = (a < b) ? 1 : 0; break;
+ case 0x9: n = (((uint32_t)a) < ((uint32_t)b)) ? 1 : 0; break;
+ case 0xa: n = a * b; break;
+ case 0xb: n = a / b; break;
+ case 0xf: n = pc; pc = a + b; break;
+ default: goto undef;
+ }
+ b = (ins >> 6) & 31;
+ if (b) {
+ s->r[b] = n;
+#if WITH_TRACE
+ if (s->flags & F_TRACE_REGS) {
+ fprintf(stderr,"%08x -> X%d\n", n, b);
+ }
+#endif
+ }
+ break;
+ case 0b100: // L
+ a = s->r[(ins >> 11) & 31] + (ins >> 16);
+ switch (ins & 7) {
+ case 0: n = mem_rd32(a); break;
+ case 1: n = mem_rd16(a); if (n & 0x8000) n |= 0xFFFF0000; break;
+ case 2: n = mem_rd8(a); if (n & 0x80) n |= 0xFFFFFF00; break;
+ case 3: n = io_rd32(a); break;
+ case 4: n = ins & 0xFFFF0000; break;
+ case 5: n = mem_rd16(a); break;
+ case 6: n = mem_rd8(a); break;
+ case 7: n = pc + (ins & 0xFFFF0000); break;
+ }
+ b = (ins >> 6) & 31;
+ if (b) {
+ s->r[b] = n;
+#if WITH_TRACE
+ if (s->flags & F_TRACE_REGS) {
+ fprintf(stderr,"%08x -> X%d\n", n, b);
+ }
+#endif
+ }
+ break;
+ case 0b101: // S
+ a = s->r[(ins >> 11) & 31] + (ins >> 16);
+ b = s->r[(ins >> 6) & 31];
+ switch (ins & 7) {
+ case 0: mem_wr32(a, b); break;
+ case 1: mem_wr16(a, b); break;
+ case 2: mem_wr8(a, b); break;
+ case 3: io_wr32(a, b); break;
+ default: goto undef;
+ }
+ break;
+ case 0b110: // B
+ a = s->r[(ins >> 11) & 31];
+ b = s->r[(ins >> 6) & 31];
+ switch (ins & 7) {
+ case 0: n = (a == b); break;
+ case 1: n = (a != b); break;
+ case 2: n = (a < b); break;
+ case 3: n = (((uint32_t)a) < ((uint32_t)b)); break;
+ case 4: n = (a >= b); break;
+ case 5: n = (((uint32_t)a) >= ((uint32_t)b)); break;
+ default: goto undef;
+ }
+ if (n) pc = pc + (ins >> 16);
+ break;
+ case 0b111: // J
+ switch (ins & 7) {
+ case 0:
+ a = ins >> 11;
+ b = (ins >> 6) & 31;
+ if (b) s->r[b] = pc;
+ pc = pc + a;
+ break;
+ case 1: s->pc = pc; do_syscall(s, ins >> 11); break;
+ //case 1: s->xpc = pc; pc = s->vec_syscall; break;
+ //case 2: s->xpc = pc; pc = s->vec_break; break;
+ //case 3: pc = s->xpc;
+ default: /* undefined instruction */
+undef:
+ s->pc = pc;
+ do_undef(s, ins);
+ return;
+ //s->xpc = pc; pc = s->vec_undef;
+ }
+ break;
+ }
+ }
+}
+
diff --git a/softrisc32/src/sr32dis.c b/softrisc32/src/disassemble-sr32.c
diff --git a/softrisc32/src/emulator-sr32.c b/softrisc32/src/emulator-sr32.c
@@ -0,0 +1,231 @@
+// Copyright 2025, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <emulator-sr32.h>
+
+#define MAXDATA 1024
+uint32_t indata[MAXDATA];
+uint32_t incount = 0;
+uint32_t innext = 0;
+
+uint32_t outdata[MAXDATA];
+uint32_t outcount = 0;
+uint32_t outnext = 0;
+
+#define RAMSIZE (8*1024*1024)
+#define RAMMASK8 (RAMSIZE - 1)
+#define RAMMASK32 (RAMMASK8 & (~3))
+#define RAMMASK16 (RAMMASK8 & (~1))
+uint8_t emu_ram[RAMSIZE];
+
+uint32_t mem_rd32(uint32_t addr) {
+ return *((uint32_t*) (emu_ram + (addr & RAMMASK32)));
+}
+uint32_t mem_rd16(uint32_t addr) {
+ return *((uint16_t*) (emu_ram + (addr & RAMMASK16)));
+}
+uint32_t mem_rd8(uint32_t addr) {
+ return *((uint8_t*) (emu_ram + (addr & RAMMASK8)));
+}
+
+void mem_wr32(uint32_t addr, uint32_t val) {
+ *((uint32_t*) (emu_ram + (addr & RAMMASK32))) = val;
+}
+void mem_wr16(uint32_t addr, uint32_t val) {
+ *((uint16_t*) (emu_ram + (addr & RAMMASK16))) = val;
+}
+void mem_wr8(uint32_t addr, uint32_t val) {
+ *((uint8_t*) (emu_ram + (addr & RAMMASK8))) = val;
+}
+
+void *mem_dma(uint32_t addr, uint32_t len) {
+ if (addr >= RAMSIZE) return 0;
+ if ((RAMSIZE - addr) < len) return 0;
+ return emu_ram + addr;
+}
+
+uint32_t io_rd32(uint32_t addr) {
+ if (addr == -1) {
+ if (innext == incount) {
+ fprintf(stderr, "FAIL: input data exhausted\n");
+ exit(1);
+ }
+ return indata[innext++];
+ }
+ return 0;
+}
+
+void io_wr32(uint32_t addr, uint32_t val) {
+ switch (addr) {
+ case -1:
+ if (outnext == outcount) {
+ fprintf(stderr, "FAIL: output data overrun\n");
+ exit(1);
+ }
+ uint32_t data = outdata[outnext++];
+ if (data != val) {
+ fprintf(stderr, "FAIL: output data %08x should be %08x\n", val, data);
+ exit(1);
+ }
+ break;
+ case -2: {
+ uint8_t x = val;
+ if (write(2, &x, 1) != 1) ;
+ break;
+ }
+ case -3:
+ exit(0);
+ }
+}
+
+void do_syscall(CpuState *s, uint32_t n) {
+}
+
+void do_undef(CpuState *s, uint32_t ins) {
+ fprintf(stderr, "UNDEF INSTR (PC=%08x INS=%08x)\n", s->pc, ins);
+ exit(1);
+}
+
+void load_hex_image(const char* fn) {
+ char line[1024];
+ FILE *fp = fopen(fn, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "emu: cannot open: %s\n", fn);
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if ((line[0] == '#') || (line[0] == '/')) {
+ continue;
+ }
+ if ((strlen(line) > 18) && (line[8] == ':')) {
+ uint32_t addr = strtoul(line, 0, 16);
+ uint32_t val = strtoul(line + 10, 0, 16);
+ mem_wr32(addr, val);
+ }
+ }
+ fclose(fp);
+}
+
+void load_test_data(const char *fn) {
+ char line[1024];
+ FILE *fp = fopen(fn, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "emu: cannot open: %s\n", fn);
+ exit(1);
+ }
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ char *x;
+ uint32_t n;
+ if ((x = strstr(line, "//>"))) {
+ x += 3;
+ for (;;) {
+ n = strtoul(x, &x, 0);
+ outdata[outcount++] = n;
+ x = strchr(x, ',');
+ if (x == NULL) break;
+ x++;
+ }
+ }
+ if ((x = strstr(line, "//<"))) {
+ x += 3;
+ for (;;) {
+ n = strtoul(x, &x, 0);
+ indata[incount++] = n;
+ x = strchr(x, ',');
+ if (x == NULL) break;
+ x++;
+ }
+ }
+ }
+ fclose(fp);
+}
+
+void usage(int status) {
+ fprintf(stderr,
+ "usage: emu <options> <image.hex> <arguments>\n"
+ "options: -x <datafile> Load Test Vector Data\n"
+ " -tf Trace Instruction Fetches\n"
+ " -tr Trace Register Writes\n"
+ " -tb Trace Branches\n");
+ exit(status);
+}
+
+int main(int argc, char** argv) {
+ uint32_t entry = 0x100000;
+ const char* fn = NULL;
+ int args = 0;
+
+ CpuState cs;
+ memset(&cs, 0, sizeof(cs));
+ memset(emu_ram, 0, sizeof(emu_ram));
+
+ while (argc > 1) {
+ if (!strcmp(argv[1], "-x")) {
+ if (argc < 3) usage(1);
+ load_test_data(argv[2]);
+ argc--;
+ argv++;
+ } else if (!strcmp(argv[1], "-tf")) {
+ cs.flags |= F_TRACE_FETCH;
+ } else if (!strcmp(argv[1], "-tr")) {
+ cs.flags |= F_TRACE_REGS;
+ } else if (!strcmp(argv[1], "-tb")) {
+ cs.flags |= F_TRACE_BRANCH;
+ } else if (argv[1][0] == '-') {
+ fprintf(stderr, "emu: unknown option: %s\n", argv[1]);
+ return -1;
+ } else {
+ fn = argv[1];
+ // arguments after the image file belong to the guest
+ args = argc - 2;
+ argv += 2;
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ if (fn == NULL) {
+ usage(1);
+ }
+
+ load_hex_image(fn);
+
+ uint32_t sp = entry - 16;
+ uint32_t lr = sp;
+ mem_wr32(lr + 0, 0xfffd006b);
+
+ uint32_t guest_argc = args;
+ uint32_t guest_argv = 0;
+ if (args) {
+ sp -= (args + 1) * 4;
+ uint32_t p = sp;
+ guest_argv = p;
+ while (args > 0) {
+ uint32_t n = strlen(argv[0]) + 1;
+ sp -= (n + 3) & (~3);
+ for (uint32_t i = 0; i < n; i++) {
+ mem_wr8(sp + i, argv[0][i]);
+ }
+ mem_wr32(p, sp);
+ p += 4;
+ args--;
+ argv++;
+ }
+ mem_wr32(p, 0);
+ }
+
+ cs.pc = entry;
+ cs.r[1] = lr;
+ cs.r[2] = sp;
+ cs.r[4] = guest_argc;
+ cs.r[5] = guest_argv;
+
+ sr32core(&cs);
+ return 0;
+}
diff --git a/softrisc32/src/sr32emu.h b/softrisc32/src/emulator-sr32.h
diff --git a/softrisc32/src/sr32cpu.c b/softrisc32/src/sr32cpu.c
@@ -1,126 +0,0 @@
-// Copyright 2025, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <unistd.h>
-
-#include "sr32emu.h"
-
-#define WITH_TRACE 1
-
-void sr32core(CpuState *s) {
- int32_t a, b, n;
- uint32_t pc = s->pc;
- for (;;) {
- int32_t ins = mem_rd32(pc);
-#if WITH_TRACE
- if (s->flags & F_TRACE_FETCH) {
- fprintf(stderr,"%08x %08x\n", pc, ins);
- }
-#endif
- pc += 4;
- switch ((ins >> 3) & 7) {
- case 0b000:
- case 0b001:
- case 0b010:
- case 0b011: // I/R
- a = s->r[(ins >> 11) & 31];
- b = ins >> 16;
- if (ins & 0b010000) b = s->r[b & 31];
- switch (ins & 15) {
- case 0x0: n = a + b; break;
- case 0x1: n = a - b; break;
- case 0x2: n = a & b; break;
- case 0x3: n = a | b; break;
- case 0x4: n = a ^ b; break;
- case 0x5: n = a << (b & 31); break;
- case 0x6: n = ((uint32_t)a) >> (b & 31); break;
- case 0x7: n = a >> (b & 31); break;
- case 0x8: n = (a < b) ? 1 : 0; break;
- case 0x9: n = (((uint32_t)a) < ((uint32_t)b)) ? 1 : 0; break;
- case 0xa: n = a * b; break;
- case 0xb: n = a / b; break;
- case 0xf: n = pc; pc = a + b; break;
- default: goto undef;
- }
- b = (ins >> 6) & 31;
- if (b) {
- s->r[b] = n;
-#if WITH_TRACE
- if (s->flags & F_TRACE_REGS) {
- fprintf(stderr,"%08x -> X%d\n", n, b);
- }
-#endif
- }
- break;
- case 0b100: // L
- a = s->r[(ins >> 11) & 31] + (ins >> 16);
- switch (ins & 7) {
- case 0: n = mem_rd32(a); break;
- case 1: n = mem_rd16(a); if (n & 0x8000) n |= 0xFFFF0000; break;
- case 2: n = mem_rd8(a); if (n & 0x80) n |= 0xFFFFFF00; break;
- case 3: n = io_rd32(a); break;
- case 4: n = ins & 0xFFFF0000; break;
- case 5: n = mem_rd16(a); break;
- case 6: n = mem_rd8(a); break;
- case 7: n = pc + (ins & 0xFFFF0000); break;
- }
- b = (ins >> 6) & 31;
- if (b) {
- s->r[b] = n;
-#if WITH_TRACE
- if (s->flags & F_TRACE_REGS) {
- fprintf(stderr,"%08x -> X%d\n", n, b);
- }
-#endif
- }
- break;
- case 0b101: // S
- a = s->r[(ins >> 11) & 31] + (ins >> 16);
- b = s->r[(ins >> 6) & 31];
- switch (ins & 7) {
- case 0: mem_wr32(a, b); break;
- case 1: mem_wr16(a, b); break;
- case 2: mem_wr8(a, b); break;
- case 3: io_wr32(a, b); break;
- default: goto undef;
- }
- break;
- case 0b110: // B
- a = s->r[(ins >> 11) & 31];
- b = s->r[(ins >> 6) & 31];
- switch (ins & 7) {
- case 0: n = (a == b); break;
- case 1: n = (a != b); break;
- case 2: n = (a < b); break;
- case 3: n = (((uint32_t)a) < ((uint32_t)b)); break;
- case 4: n = (a >= b); break;
- case 5: n = (((uint32_t)a) >= ((uint32_t)b)); break;
- default: goto undef;
- }
- if (n) pc = pc + (ins >> 16);
- break;
- case 0b111: // J
- switch (ins & 7) {
- case 0:
- a = ins >> 11;
- b = (ins >> 6) & 31;
- if (b) s->r[b] = pc;
- pc = pc + a;
- break;
- case 1: s->pc = pc; do_syscall(s, ins >> 11); break;
- //case 1: s->xpc = pc; pc = s->vec_syscall; break;
- //case 2: s->xpc = pc; pc = s->vec_break; break;
- //case 3: pc = s->xpc;
- default: /* undefined instruction */
-undef:
- s->pc = pc;
- do_undef(s, ins);
- return;
- //s->xpc = pc; pc = s->vec_undef;
- }
- break;
- }
- }
-}
-
diff --git a/softrisc32/src/sr32emu.c b/softrisc32/src/sr32emu.c
@@ -1,231 +0,0 @@
-// Copyright 2025, Brian Swetland <swetland@frotz.net>
-// Licensed under the Apache License, Version 2.0.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "sr32emu.h"
-
-#define MAXDATA 1024
-uint32_t indata[MAXDATA];
-uint32_t incount = 0;
-uint32_t innext = 0;
-
-uint32_t outdata[MAXDATA];
-uint32_t outcount = 0;
-uint32_t outnext = 0;
-
-#define RAMSIZE (8*1024*1024)
-#define RAMMASK8 (RAMSIZE - 1)
-#define RAMMASK32 (RAMMASK8 & (~3))
-#define RAMMASK16 (RAMMASK8 & (~1))
-uint8_t emu_ram[RAMSIZE];
-
-uint32_t mem_rd32(uint32_t addr) {
- return *((uint32_t*) (emu_ram + (addr & RAMMASK32)));
-}
-uint32_t mem_rd16(uint32_t addr) {
- return *((uint16_t*) (emu_ram + (addr & RAMMASK16)));
-}
-uint32_t mem_rd8(uint32_t addr) {
- return *((uint8_t*) (emu_ram + (addr & RAMMASK8)));
-}
-
-void mem_wr32(uint32_t addr, uint32_t val) {
- *((uint32_t*) (emu_ram + (addr & RAMMASK32))) = val;
-}
-void mem_wr16(uint32_t addr, uint32_t val) {
- *((uint16_t*) (emu_ram + (addr & RAMMASK16))) = val;
-}
-void mem_wr8(uint32_t addr, uint32_t val) {
- *((uint8_t*) (emu_ram + (addr & RAMMASK8))) = val;
-}
-
-void *mem_dma(uint32_t addr, uint32_t len) {
- if (addr >= RAMSIZE) return 0;
- if ((RAMSIZE - addr) < len) return 0;
- return emu_ram + addr;
-}
-
-uint32_t io_rd32(uint32_t addr) {
- if (addr == -1) {
- if (innext == incount) {
- fprintf(stderr, "FAIL: input data exhausted\n");
- exit(1);
- }
- return indata[innext++];
- }
- return 0;
-}
-
-void io_wr32(uint32_t addr, uint32_t val) {
- switch (addr) {
- case -1:
- if (outnext == outcount) {
- fprintf(stderr, "FAIL: output data overrun\n");
- exit(1);
- }
- uint32_t data = outdata[outnext++];
- if (data != val) {
- fprintf(stderr, "FAIL: output data %08x should be %08x\n", val, data);
- exit(1);
- }
- break;
- case -2: {
- uint8_t x = val;
- if (write(2, &x, 1) != 1) ;
- break;
- }
- case -3:
- exit(0);
- }
-}
-
-void do_syscall(CpuState *s, uint32_t n) {
-}
-
-void do_undef(CpuState *s, uint32_t ins) {
- fprintf(stderr, "UNDEF INSTR (PC=%08x INS=%08x)\n", s->pc, ins);
- exit(1);
-}
-
-void load_hex_image(const char* fn) {
- char line[1024];
- FILE *fp = fopen(fn, "r");
- if (fp == NULL) {
- fprintf(stderr, "emu: cannot open: %s\n", fn);
- exit(1);
- }
- while (fgets(line, sizeof(line), fp) != NULL) {
- if ((line[0] == '#') || (line[0] == '/')) {
- continue;
- }
- if ((strlen(line) > 18) && (line[8] == ':')) {
- uint32_t addr = strtoul(line, 0, 16);
- uint32_t val = strtoul(line + 10, 0, 16);
- mem_wr32(addr, val);
- }
- }
- fclose(fp);
-}
-
-void load_test_data(const char *fn) {
- char line[1024];
- FILE *fp = fopen(fn, "r");
- if (fp == NULL) {
- fprintf(stderr, "emu: cannot open: %s\n", fn);
- exit(1);
- }
- while (fgets(line, sizeof(line), fp) != NULL) {
- char *x;
- uint32_t n;
- if ((x = strstr(line, "//>"))) {
- x += 3;
- for (;;) {
- n = strtoul(x, &x, 0);
- outdata[outcount++] = n;
- x = strchr(x, ',');
- if (x == NULL) break;
- x++;
- }
- }
- if ((x = strstr(line, "//<"))) {
- x += 3;
- for (;;) {
- n = strtoul(x, &x, 0);
- indata[incount++] = n;
- x = strchr(x, ',');
- if (x == NULL) break;
- x++;
- }
- }
- }
- fclose(fp);
-}
-
-void usage(int status) {
- fprintf(stderr,
- "usage: emu <options> <image.hex> <arguments>\n"
- "options: -x <datafile> Load Test Vector Data\n"
- " -tf Trace Instruction Fetches\n"
- " -tr Trace Register Writes\n"
- " -tb Trace Branches\n");
- exit(status);
-}
-
-int main(int argc, char** argv) {
- uint32_t entry = 0x100000;
- const char* fn = NULL;
- int args = 0;
-
- CpuState cs;
- memset(&cs, 0, sizeof(cs));
- memset(emu_ram, 0, sizeof(emu_ram));
-
- while (argc > 1) {
- if (!strcmp(argv[1], "-x")) {
- if (argc < 3) usage(1);
- load_test_data(argv[2]);
- argc--;
- argv++;
- } else if (!strcmp(argv[1], "-tf")) {
- cs.flags |= F_TRACE_FETCH;
- } else if (!strcmp(argv[1], "-tr")) {
- cs.flags |= F_TRACE_REGS;
- } else if (!strcmp(argv[1], "-tb")) {
- cs.flags |= F_TRACE_BRANCH;
- } else if (argv[1][0] == '-') {
- fprintf(stderr, "emu: unknown option: %s\n", argv[1]);
- return -1;
- } else {
- fn = argv[1];
- // arguments after the image file belong to the guest
- args = argc - 2;
- argv += 2;
- break;
- }
- argc--;
- argv++;
- }
- if (fn == NULL) {
- usage(1);
- }
-
- load_hex_image(fn);
-
- uint32_t sp = entry - 16;
- uint32_t lr = sp;
- mem_wr32(lr + 0, 0xfffd006b);
-
- uint32_t guest_argc = args;
- uint32_t guest_argv = 0;
- if (args) {
- sp -= (args + 1) * 4;
- uint32_t p = sp;
- guest_argv = p;
- while (args > 0) {
- uint32_t n = strlen(argv[0]) + 1;
- sp -= (n + 3) & (~3);
- for (uint32_t i = 0; i < n; i++) {
- mem_wr8(sp + i, argv[0][i]);
- }
- mem_wr32(p, sp);
- p += 4;
- args--;
- argv++;
- }
- mem_wr32(p, 0);
- }
-
- cs.pc = entry;
- cs.r[1] = lr;
- cs.r[2] = sp;
- cs.r[4] = guest_argc;
- cs.r[5] = guest_argv;
-
- sr32core(&cs);
- return 0;
-}