spl

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

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:
Msoftrisc32/Makefile | 8++++----
Rsoftrisc32/src/sr32asm.c -> softrisc32/src/assemble-sr32.c | 0
Asoftrisc32/src/cpu-sr32.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsoftrisc32/src/sr32dis.c -> softrisc32/src/disassemble-sr32.c | 0
Asoftrisc32/src/emulator-sr32.c | 231+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rsoftrisc32/src/sr32emu.h -> softrisc32/src/emulator-sr32.h | 0
Dsoftrisc32/src/sr32cpu.c | 126-------------------------------------------------------------------------------
Dsoftrisc32/src/sr32emu.c | 231-------------------------------------------------------------------------------
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; -}