From 8178aec97ca8d0d4ff1ef98742608395ec15f4e0 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 31 Oct 2023 23:00:28 +0000 Subject: [PATCH] searle: convert to new toolchain Builds but not yet tested --- Kernel/platform/platform-searle/Makefile | 59 +- Kernel/platform/platform-searle/commonmem.S | 8 + Kernel/platform/platform-searle/commonmem.s | 65 +- Kernel/platform/platform-searle/config.h | 2 +- Kernel/platform/platform-searle/crt0.S | 38 + Kernel/platform/platform-searle/crt0.s | 91 +-- Kernel/platform/platform-searle/devtty.c | 26 +- Kernel/platform/platform-searle/devtty.h | 2 +- .../platform/platform-searle/{ide.c => ide.S} | 49 +- .../{kernel.def => kernelu.def} | 4 +- .../platform-searle/{loader.s => loader.S} | 151 ++-- Kernel/platform/platform-searle/main.c | 7 +- Kernel/platform/platform-searle/plt_ide.h | 23 +- Kernel/platform/platform-searle/rules.mk | 1 + Kernel/platform/platform-searle/searle.S | 495 +++++++++++ Kernel/platform/platform-searle/searle.h | 10 +- Kernel/platform/platform-searle/searle.s | 773 +++++++++--------- Kernel/platform/platform-searle/target.mk | 4 +- Kernel/platform/platform-searle/tricks.S | 4 + Kernel/platform/platform-searle/tricks.s | 295 ++++++- Kernel/platform/platform-searle/usermem.S | 180 ++++ Kernel/platform/platform-searle/usermem.s | 309 ++++--- 22 files changed, 1860 insertions(+), 736 deletions(-) create mode 100644 Kernel/platform/platform-searle/commonmem.S create mode 100644 Kernel/platform/platform-searle/crt0.S rename Kernel/platform/platform-searle/{ide.c => ide.S} (68%) rename Kernel/platform/platform-searle/{kernel.def => kernelu.def} (91%) rename Kernel/platform/platform-searle/{loader.s => loader.S} (60%) create mode 100644 Kernel/platform/platform-searle/searle.S create mode 100644 Kernel/platform/platform-searle/tricks.S create mode 100644 Kernel/platform/platform-searle/usermem.S diff --git a/Kernel/platform/platform-searle/Makefile b/Kernel/platform/platform-searle/Makefile index 459ca6df0d..62f0ad9337 100644 --- a/Kernel/platform/platform-searle/Makefile +++ b/Kernel/platform/platform-searle/Makefile @@ -1,57 +1,72 @@ -ASRCS = crt0.s tricks.s commonmem.s searle.s usermem.s -CSRCS = devices.c main.c devtty.c ide.c +ASRCS = crt0.S tricks.S commonmem.S searle.S usermem.S ide.S +CSRCS = devices.c main.c devtty.c DISCARD_CSRCS = discard.c DISCARD_DSRCS = ../../dev/tinyide_discard.c DSRCS = ../../dev/tinyide.c ../../dev/tinydisk.c ../../dev/tinydisk_discard.c DASRCS = NSRCS = -AOBJS = $(ASRCS:.s=.rel) -COBJS = $(CSRCS:.c=.rel) -DISCARD_COBJS = $(DISCARD_CSRCS:.c=.rel) -DISCARD_DOBJS = $(patsubst ../../dev/%.c,%.rel, $(DISCARD_DSRCS)) -DOBJS = $(patsubst ../../dev/%.c,%.rel, $(DSRCS)) -DAOBJS = $(patsubst ../../dev/%.s,%.rel, $(DASRCS)) -NOBJS = $(patsubst ../../dev/net/%.c,%.rel, $(NSRCS)) +AOBJS = $(ASRCS:.S=.o) +COBJS = $(CSRCS:.c=.o) +DISCARD_COBJS = $(DISCARD_CSRCS:.c=.o) +DISCARD_DOBJS = $(patsubst ../../dev/%.c,%.o, $(DISCARD_DSRCS)) +DOBJS = $(patsubst ../../dev/%.c,%.o, $(DSRCS)) +DAOBJS = $(patsubst ../../dev/%.S,%.o, $(DASRCS)) +NOBJS = $(patsubst ../../dev/net/%.c,%.o, $(NSRCS)) OBJS = $(AOBJS) $(COBJS) $(DOBJS) $(DAOBJS) $(DISCARD_DOBJS) $(DISCARD_COBJS) $(NOBJS) CROSS_CCOPTS += -I../../dev/ -I../../dev/net/ -JUNK = *.rel *.lst *.asm *.sym *.rst *.map *.ihx *.bin +JUNK = *.o all: $(OBJS) -$(AOBJS): %.rel: %.s +$(AOBJS): %.o: %.S $(CROSS_AS) $(ASOPTS) $< -$(COBJS): %.rel: %.c +$(COBJS): %.o: %.c $(CROSS_CC) $(CROSS_CCOPTS) -c $< -$(DOBJS): %.rel: ../../dev/%.c +$(DOBJS): %.o: ../../dev/%.c $(CROSS_CC) $(CROSS_CCOPTS) -c $< -$(DAOBJS): %.rel: ../../dev/%.s +$(DAOBJS): %.o: ../../dev/%.S $(CROSS_AS) $(ASOPTS) $@ $< -$(DISCARD_COBJS): %.rel: %.c +$(DISCARD_COBJS): %.o: %.c $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< -$(DISCARD_DOBJS): %.rel: ../../dev/%.c +$(DISCARD_DOBJS): %.o: ../../dev/%.c $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< -$(NOBJS): %.rel: ../../dev/net/%.c +$(NOBJS): %.o: ../../dev/net/%.c $(CROSS_CC) $(CROSS_CCOPTS) -c $< clean: rm -f $(OBJS) $(JUNK) core *~ loader.tmp loader.bin image: loader.bin - -loader.bin: loader.s - sdasz80 -o loader.s - sdldz80 -i loader.rel - makebin -s 65536 loader.ihx loader.tmp + $(CROSS_LD) -b -C 0x0100 -S 0xF000 -f CLDBbXSs -o fuzix.bin \ + crt0.o commonmem.o searle.o ../../start.o \ + ../../version.o ../../cpu-z80u/lowlevel-z80u-thunked.o \ + ../../usermem.o usermem.o tricks.o main.o discard.o \ + ../../timer.o ../../kdata.o devices.o ../../devio.o \ + ../../filesys.o ../../blk512.o ../../process.o \ + ../../inode.o ../../syscall_exec.o ../../syscall_exec16.o \ + ../../syscall_fs.o ../../syscall_fs2.o ../../syscall_fs3.o \ + ../../syscall_proc.o ../../syscall_other.o ../../syscall_net.o \ + ../../network.o ../../tty.o ../../mm.o ../../mm/memalloc_none.o \ + ../../swap.o ../../mm/simple.o ../../devsys.o \ + devtty.o ../../dev/tinydisk.o ../../dev/tinydisk_discard.o \ + ../../dev/tinyide.o ../../dev/tinyide_discard.o ide.o \ + /opt/ccz80/lib/libz80.a -m fuzix.tmpmap + perl -lpe '$$_=hex' fuzix.tmpmap | paste -d" " - fuzix.tmpmap | sort -n | cut -d" " -f 2- >../../fuzix.map + ../../tools/pack85 <../../fuzix.map fuzix.bin ../../fuzix.bin + +loader.bin: loader.S + asz80 loader.S -o loader.o + ldz80 -b -C 0 loader.o -o loader.tmp dd if=loader.tmp bs=256 skip=208 of=loader.bin diff --git a/Kernel/platform/platform-searle/commonmem.S b/Kernel/platform/platform-searle/commonmem.S new file mode 100644 index 0000000000..42472843f3 --- /dev/null +++ b/Kernel/platform/platform-searle/commonmem.S @@ -0,0 +1,8 @@ +; +; Standard common. Nothing special here except to remember that writes +; to common space won't write through all banks +; + .common + +#include "../../cpu-z80u/std-commonmem.s" + diff --git a/Kernel/platform/platform-searle/commonmem.s b/Kernel/platform/platform-searle/commonmem.s index fc8452be3d..8acdd9c8f7 100644 --- a/Kernel/platform/platform-searle/commonmem.s +++ b/Kernel/platform/platform-searle/commonmem.s @@ -1,10 +1,65 @@ +# 0 "commonmem.S" +# 0 "" +# 0 "" +# 1 "commonmem.S" ; -; Standard common. Nothing special here except to remember that writes -; to common space won't write through all banks +; Standard common. Nothing special here except to remember that writes +; to common space won't write through all banks ; - .module commonmem + .common + +# 1 "../../cpu-z80u/std-commonmem.s" 1 +# 0 "../../cpu-z80u/std-commonmem.S" +# 0 "" +# 0 "" +# 1 "/usr/include/stdc-predef.h" 1 3 4 +# 0 "" 2 +# 1 "../../cpu-z80u/std-commonmem.S" +; +; +; Standard Z80 common memory area blocks. +; +; Must remain a multiple of 256 bytes +; + ; exported symbols + .export _ub + .export _udata + .export kstack_top + .export istack_top + .export istack_switched_sp - .area _COMMONMEM - .include "../../cpu-z80/std-commonmem.s" +_ub: ; first 512 bytes: starts with struct u_block, with the kernel stack working down from above +_udata: +kstack_base: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +kstack_top: + ; next 256 bytes: 254 byte interrupt stack, then 2 byte saved stack pointer +istack_base: + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +istack_top: +istack_switched_sp: .word 0 +# 8 "commonmem.S" 2 diff --git a/Kernel/platform/platform-searle/config.h b/Kernel/platform/platform-searle/config.h index 47c4f94479..b29aa901f8 100644 --- a/Kernel/platform/platform-searle/config.h +++ b/Kernel/platform/platform-searle/config.h @@ -52,8 +52,8 @@ extern uint16_t swap_dev; #define CONFIG_TD_NUM 2 #define CONFIG_TD_IDE -#define CONFIG_TINYIDE_SDCCPIO #define CONFIG_TINYIDE_8BIT +#define CONFIG_TINYIDE_INDIRECT #define IDE_IS_8BIT(x) 1 /* Device parameters */ diff --git a/Kernel/platform/platform-searle/crt0.S b/Kernel/platform/platform-searle/crt0.S new file mode 100644 index 0000000000..202c942f79 --- /dev/null +++ b/Kernel/platform/platform-searle/crt0.S @@ -0,0 +1,38 @@ +; 2015-02-20 Sergey Kiselev +; 2013-12-18 William R Sowerbutts + +#include "kernelu.def" + + ; startup code (0x100) + .code +init: + di + ; switch to stack in high memory + ld sp, kstack_top + + ; move the common memory where it belongs + ld hl, __bss + ld de, __common + ld bc, __common_size + ldir + ; and the discard + ld de, __discard + ld bc, __discard_size + ldir + + ld hl, __bss + ld de, __bss + 1 + ld bc, __bss_size - 1 + ld (hl), 0 + ldir + + ; Hardware setup + call init_hardware + + ; Call the C main routine + call _fuzix_main + + ; fuzix_main() shouldn't return, but if it does... + di +stop: halt + jr stop diff --git a/Kernel/platform/platform-searle/crt0.s b/Kernel/platform/platform-searle/crt0.s index 398acba836..8ee8aab815 100644 --- a/Kernel/platform/platform-searle/crt0.s +++ b/Kernel/platform/platform-searle/crt0.s @@ -1,71 +1,56 @@ +# 0 "crt0.S" +# 0 "" +# 0 "" +# 1 "crt0.S" ; 2015-02-20 Sergey Kiselev ; 2013-12-18 William R Sowerbutts - .module crt0 +# 1 "kernelu.def" 1 +; FUZIX mnemonics for memory addresses etc - ; Ordering of segments for the linker. - ; WRS: Note we list all our segments here, even though - ; we don't use them all, because their ordering is set - ; when they are first seen. - .area _CODE - .area _HOME ; compiler stores __mullong etc in here if you use them - .area _CODE2 - .area _CONST - .area _INITIALIZED - .area _DATA - .area _BSEG - .area _BSS - .area _HEAP - ; note that areas below here may be overwritten by the heap at runtime, so - ; put initialisation stuff in here - .area _BUFFERS ; _BUFFERS grows to consume all before it (up to KERNTOP) - .area _INITIALIZER ; binman copies this to the right place for us - .area _GSINIT ; unused - .area _GSFINAL ; unused - .area _DISCARD - .area _DISCARDL - .area _DISCARDH - .area _COMMONMEM +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes @ F000 +Z80_TYPE .equ 0 ; CMOS - ; exported symbols - .globl init +Z80_MMU_HOOKS .equ 0 - ; imported symbols - .globl _fuzix_main - .globl init_hardware - .globl s__INITIALIZER - .globl s__COMMONMEM - .globl l__COMMONMEM - .globl s__DISCARD - .globl l__DISCARD - .globl s__DATA - .globl l__DATA - .globl kstack_top +CONFIG_SWAP .equ 1 - .include "kernel.def" +PROGBASE .equ 0x0000 +PROGLOAD .equ 0x0100 + +NBUFS .equ 4 + +; +; Select where to put the high code - in our case we need this +; in common +; - ; startup code (0x100) - .area _CODE +HIGHPAGE .equ 0 ; We only have 1 page byte and the low page + ; isn't used +# 5 "crt0.S" 2 + + ; startup code (0x100) + .code init: di ; switch to stack in high memory - ld sp, #kstack_top + ld sp, kstack_top - ; move the common memory where it belongs - ld hl, #s__DATA - ld de, #s__COMMONMEM - ld bc, #l__COMMONMEM + ; move the common memory where it belongs + ld hl, __bss + ld de, __common + ld bc, __common_size ldir ; and the discard - ld de, #s__DISCARD - ld bc, #l__DISCARD + ld de, __discard + ld bc, __discard_size ldir - ld hl, #s__DATA - ld de, #s__DATA + 1 - ld bc, #l__DATA - 1 - ld (hl), #0 + ld hl, __bss + ld de, __bss + 1 + ld bc, __bss_size - 1 + ld (hl), 0 ldir ; Hardware setup @@ -73,8 +58,8 @@ init: ; Call the C main routine call _fuzix_main - + ; fuzix_main() shouldn't return, but if it does... di -stop: halt +stop: halt jr stop diff --git a/Kernel/platform/platform-searle/devtty.c b/Kernel/platform/platform-searle/devtty.c index 2b3d75cd7c..502ed76bd9 100644 --- a/Kernel/platform/platform-searle/devtty.c +++ b/Kernel/platform/platform-searle/devtty.c @@ -31,7 +31,7 @@ uint8_t sio_r[] = { static void sio2_setup(uint_fast8_t minor, uint_fast8_t flags) { - struct termios *t = &ttydata[minor].termios; + register struct termios *t = &ttydata[minor].termios; uint8_t r; used(flags); @@ -86,24 +86,24 @@ void tty_pollirq_sio0(void) uint8_t progress; /* Check for an interrupt */ - SIOA_C = 0; - if (!(SIOA_C & 2)) + out(SIOA_C, 0); + if (!(in(SIOA_C) & 2)) return; do { progress = 0; - SIOA_C = 0; // read register 0 - ca = SIOA_C; + out(SIOA_C, 0); // read register 0 + ca = in(SIOA_C); /* Input pending */ if (ca & 1) { progress = 1; - tty_inproc(1, SIOA_D); + tty_inproc(1, in(SIOA_D)); } /* Output pending */ if ((ca & 4) && (sleeping & 2)) { tty_outproc(2); sleeping &= ~2; - SIOA_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + out(SIOA_C, 5 << 3); // reg 0 CMD 5 - reset transmit interrupt pending } /* Carrier changed on A: this is a timer interrupt from the external square wave generator */ @@ -113,22 +113,22 @@ void tty_pollirq_sio0(void) old_ca = ca; } /* ACK any break or error events */ - SIOA_C = 2 << 3; + out(SIOA_C, 2 << 3); - SIOB_C = 0; // read register 0 - cb = SIOB_C; + out(SIOB_C, 0); // read register 0 + cb = in(SIOB_C); if (cb & 1) { - tty_inproc(2, SIOB_D); + tty_inproc(2, in(SIOB_D)); progress = 1; } if ((cb & 4) && (sleeping & 8)) { tty_outproc(3); sleeping &= ~8; - SIOB_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending + out(SIOB_C, 5 << 3); // reg 0 CMD 5 - reset transmit interrupt pending } /* ACK any break or error events */ - SIOB_C = 2 << 3; + out(SIOB_C, 2 << 3); } while(progress); } diff --git a/Kernel/platform/platform-searle/devtty.h b/Kernel/platform/platform-searle/devtty.h index 463d20ca45..11c1680b3b 100644 --- a/Kernel/platform/platform-searle/devtty.h +++ b/Kernel/platform/platform-searle/devtty.h @@ -1,7 +1,7 @@ #ifndef __DEVTTY_DOT_H__ #define __DEVTTY_DOT_H__ -void tty_putc(uint8_t minor, uint_fast8_t c); +void tty_putc(uint_fast8_t minor, uint_fast8_t c); void tty_pollirq_sio0(void); void tty_pollirq_sio1(void); void tty_pollirq_acia(void); diff --git a/Kernel/platform/platform-searle/ide.c b/Kernel/platform/platform-searle/ide.S similarity index 68% rename from Kernel/platform/platform-searle/ide.c rename to Kernel/platform/platform-searle/ide.S index adb5c7ce52..c7ba695327 100644 --- a/Kernel/platform/platform-searle/ide.c +++ b/Kernel/platform/platform-searle/ide.S @@ -1,10 +1,6 @@ -#include -#include -#include -#include -#include -#include -#include +#include "kernelu.def" + +#define IDE_REG_DATA 0x10 /* * We need slightly custom transfer routines for the IDE controller @@ -13,71 +9,62 @@ * As we only have one bank of user it's a bit simpler */ -COMMON_MEMORY - -#undef ei -#undef di + .common + .export _devide_read_data + .export _devide_write_data -void devide_read_data(uint8_t *data) __naked -{ - __asm +_devide_read_data: pop de pop hl push hl push de ld a, (_td_raw) - ld bc, #IDE_REG_DATA ; setup port number + ld bc, IDE_REG_DATA ; setup port number ; and count or a jr z, via_kernel di - ld a,#0x01 + ld a, 0x01 out (0x03),a - ld a,#0x58 + ld a, 0x58 out (0x03),a via_kernel: inir ; transfer first 256 bytes inir ; transfer second 256 bytes - ld a,#0x01 + ld a, 0x01 out (0x03),a - ld a,#0x18 + ld a, 0x18 out (0x03),a ld a,(_int_disabled) or a ret z ei ret - __endasm; -} -void devide_write_data(uint8_t *data) __naked -{ - __asm +_devide_write_data: pop de pop hl push hl push de ld a, (_td_raw) - ld bc, #IDE_REG_DATA ; setup port number + ld bc, IDE_REG_DATA ; setup port number ; and count or a jr z, wvia_kernel di - ld a,#0x01 + ld a, 0x01 out (0x03),a - ld a,#0x58 + ld a, 0x58 out (0x03),a wvia_kernel: otir ; transfer first 256 bytes otir ; transfer second 256 bytes - ld a,#0x01 + ld a, 0x01 out (0x03),a - ld a,#0x18 + ld a, 0x18 out (0x03),a ld a,(_int_disabled) or a ret z ei ret - __endasm; -} diff --git a/Kernel/platform/platform-searle/kernel.def b/Kernel/platform/platform-searle/kernelu.def similarity index 91% rename from Kernel/platform/platform-searle/kernel.def rename to Kernel/platform/platform-searle/kernelu.def index f8515d4798..34a4f7e755 100644 --- a/Kernel/platform/platform-searle/kernel.def +++ b/Kernel/platform/platform-searle/kernelu.def @@ -16,9 +16,7 @@ NBUFS .equ 4 ; Select where to put the high code - in our case we need this ; in common ; -.macro HIGH - .area _COMMONMEM -.endm +#define HIGH .common HIGHPAGE .equ 0 ; We only have 1 page byte and the low page ; isn't used diff --git a/Kernel/platform/platform-searle/loader.s b/Kernel/platform/platform-searle/loader.S similarity index 60% rename from Kernel/platform/platform-searle/loader.s rename to Kernel/platform/platform-searle/loader.S index 2a337e03e6..3c85b44ef3 100644 --- a/Kernel/platform/platform-searle/loader.s +++ b/Kernel/platform/platform-searle/loader.S @@ -3,76 +3,71 @@ ; top 12K and then runs whatever is indicated at 0xFFFE/FFFF ; -DATA .equ 0x10 -ERROR .equ 0x11 -FEATURES .equ 0x11 -COUNT .equ 0x12 -LBA_0 .equ 0x13 -LBA_1 .equ 0x14 -LBA_2 .equ 0x15 -LBA_3 .equ 0x16 -STATUS .equ 0x17 -CMD .equ 0x17 - -ERR .equ 0 -DRQ .equ 3 -READY .equ 6 -BUSY .equ 7 - -ATA_READ .equ 0x20 - -SIOA_C .equ 0x02 -SIOA_D .equ 0x00 -SIOB_C .equ 0x03 -SIOB_D .equ 0x01 - - .area VECTOR(ABS) - - .org 0xFFFE - .word start - - .area BANKHELPER(ABS) - +DATA equ 0x10 +ERROR equ 0x11 +FEATURES equ 0x11 +COUNT equ 0x12 +LBA_0 equ 0x13 +LBA_1 equ 0x14 +LBA_2 equ 0x15 +LBA_3 equ 0x16 +STATUS equ 0x17 +CMD equ 0x17 + +ERR equ 0 +DRQ equ 3 +READY equ 6 +BUSY equ 7 + +ATA_READ equ 0x20 + +SIOA_C equ 0x02 +SIOA_D equ 0x00 +SIOB_C equ 0x03 +SIOB_D equ 0x01 + + .abs + + .abs .org 0xFF00 ; ; Must exactly match the ROM (ugly but really we just need to write ; a new better ROM anyway) ; -STUBS: - JP DO_PUT_FAR - JP DO_GET_FAR - -DO_PUT_FAR: - LD C,#SIOB_C - LD B,A - LD A,#1 - OUT (C),A - LD A,#0x58 - OUT (C),A - LD (HL),B - LD A,#1 - OUT (C),A - LD A,#0x18 - OUT (C),A - RET -DO_GET_FAR: - LD C,#SIOB_C - LD A,#1 - OUT (C),A - LD A,#0x58 - OUT (C),A - LD B,(HL) - LD A,#1 - OUT (C),A - LD A,#0x18 - OUT (C),A - LD A,B - RET - - - .area LOADER(ABS) +stubs: + jp do_put_far + jp do_get_far + +do_put_far: + ld c,SIOB_C + ld b,a + ld a,1 + out (c),a + ld a,0x58 + out (c),a + ld (hl),b + ld a,1 + out (c),a + ld a,0x18 + out (c),a + ret +do_get_far: + ld c,SIOB_C + ld a,1 + out (c),a + ld a,0x58 + out (c),a + ld b,(hl) + ld a,1 + out (c),a + ld a,0x18 + out (c),a + ld a,b + ret + + .abs .org 0xD000 @@ -84,41 +79,41 @@ start: ; because of the FFFE/FFFF thing. ld sp, #0xFE00 - ld hl,#hello + ld hl, hello call serstr xor a out (0x38),a call ide_ready - ld a,#0xE0 + ld a, 0xE0 out (LBA_3),a call ide_ready xor a out (LBA_2),a out (LBA_1),a - ld de,#0x7C18 ; sectors 24-119 - ld hl,#0x0100 ; load address + ld de, 0x7C18 ; sectors 24-119 + ld hl, 0x0100 ; load address load_loop: call ide_ready ld a,e out (LBA_0),a - ld a,#1 + ld a, 1 out (COUNT),a - ld a,#ATA_READ + ld a, ATA_READ out (CMD),a nop call ide_wait_drq - ld bc,#DATA + ld bc, DATA inir inir - ld a,#'.' + ld a, '.' call serout inc e dec d jr nz, load_loop - ld hl,#gogogo + ld hl, gogogo call serstr jp 0x0100 @@ -159,6 +154,14 @@ serstr: jr serstr hello: - .asciz 'Grant Searle SBC LOADER 0.1\r\n\r\n' + .ascii 'Grant Searle SBC LOADER 0.1' + .byte 13,10,13,10 + .byte 0 gogogo: - .asciz '\r\nExecuting FUZIX...\r\n' + .byte 13,10 + .ascii 'Executing FUZIX...' + .byte 13,10,0 + + .org 0xFFFE + .word start + diff --git a/Kernel/platform/platform-searle/main.c b/Kernel/platform/platform-searle/main.c index 09650ddb01..94771d60f5 100644 --- a/Kernel/platform/platform-searle/main.c +++ b/Kernel/platform/platform-searle/main.c @@ -23,12 +23,7 @@ void plt_discard(void) kprintf("Buffers available: %d\n", bufpool_end - bufpool); } -void plt_idle(void) -{ - __asm halt __endasm; -} - -uint8_t plt_param(unsigned char *p) +uint_fast8_t plt_param(unsigned char *p) { used(p); return 0; diff --git a/Kernel/platform/platform-searle/plt_ide.h b/Kernel/platform/platform-searle/plt_ide.h index 39c488ee77..0271fe583b 100644 --- a/Kernel/platform/platform-searle/plt_ide.h +++ b/Kernel/platform/platform-searle/plt_ide.h @@ -1,14 +1,17 @@ -__sfr __at 0x10 data; -__sfr __at 0x11 error; -__sfr __at 0x12 count; -__sfr __at 0x13 sec; -__sfr __at 0x14 cyll; -__sfr __at 0x15 cylh; -__sfr __at 0x16 devh; -__sfr __at 0x17 cmd; -__sfr __at 0x17 status; +#define data 0x10 +#define error 0x11 +#define count 0x12 +#define sec 0x13 +#define cyll 0x14 +#define cylh 0x15 +#define devh 0x16 +#define cmd 0x17 +#define status 0x17 -#define IDE_REG_DATA 0x0010 +#define IDE_REG_DATA 0x10 /* Due to our strange banking needs */ #define IDE_NONSTANDARD_XFER + +#define ide_read(x) in(x) +#define ide_write(x,y) out(x,y) diff --git a/Kernel/platform/platform-searle/rules.mk b/Kernel/platform/platform-searle/rules.mk index c3701b0582..2a2fd1bf76 100644 --- a/Kernel/platform/platform-searle/rules.mk +++ b/Kernel/platform/platform-searle/rules.mk @@ -1 +1,2 @@ export BANKED=-thunked +#CROSS_CCOPTS += -Os diff --git a/Kernel/platform/platform-searle/searle.S b/Kernel/platform/platform-searle/searle.S new file mode 100644 index 0000000000..a189214497 --- /dev/null +++ b/Kernel/platform/platform-searle/searle.S @@ -0,0 +1,495 @@ +; +; Grant Searle SBC with timer hack and A16 wired for SIO control +; Also requires the revised boot rom that places the initial bank flip +; helper at 0xFFxx in both banks before the ROM is paged out (as it +; can't be paged back in). +; + + ; exported symbols + .export init_hardware + .export _program_vectors + .export _kernel_flag + .export map_page_low + .export map_kernel_low + .export map_user_low + .export map_save_low + .export map_restore_low + .export _plt_doexec + .export _plt_reboot + .export _int_disabled + .export syscall_platform + + ; exported debugging tools + .export _plt_monitor + .export outchar + +#include "kernelu.def" +#include "../../cpu-z80u/kernel-z80.def" + + +; Base address of SIO/2 chip 0x00 + +SIOA_D equ 0x00 +SIOB_D equ 0x01 +SIOA_C equ 0x02 +SIOB_C equ 0x03 + + + +; +; Buffers (we use asm to set this up as we need them in a special segment +; so we can recover the discard memory into the buffer pool +; + + .export _bufpool + + .buffers +_bufpool: + .ds BUFSIZE * NBUFS + +; ----------------------------------------------------------------------------- +; +; Because of the weird memory model this is a bit different to the +; usual Z80 setup. +; +; ----------------------------------------------------------------------------- + .common + +_plt_monitor: +_plt_reboot: + di ; No way back to the ROM + halt + +_int_disabled: + .byte 1 + +; ----------------------------------------------------------------------------- +; +; Our MMU is write only, but if we put a value in each bank in a fixed +; place we have a fast way to see which bank is which +; +; ----------------------------------------------------------------------------- + +banknum: + .byte 0x01 ; copied into far bank then set to 0 + +; ----------------------------------------------------------------------------- +; All of discard gets reclaimed when init is run +; +; Discard must be above 0x8000 as we need some of it when the ROM +; is paged in during init_hardware +; ----------------------------------------------------------------------------- + .discard + +init_hardware: + ld hl, sio_setup + ld bc, 0x0A00 + SIOA_C ; 10 bytes to SIOA_C + otir + + ld hl, sio_setup + ld bc, 0x0A00 + SIOB_C ; and to SIOB_C + otir + + ld hl, #128 + ld (_ramsize), hl + ld hl, 60 ; We lose 4K to common space + ld (_procmem), hl + + ld hl, bankhelper + call outstring + + ld hl, __common + ld de, __common_size + + ; This is run once so can be slow and simple +farput: + ld a,(hl) + call 0xFF00 ; put byte in a into (HL) in far memory + ; uses BC/HL/AF + inc hl + dec de + ld a,d + or e + jr nz,farput + + + xor a + ld (banknum),a ; and correct page + + ; We now have our common in place. We can do the rest ourselves + + ; Put the low stubs into place in the kernel + ld hl, stubs_low + ld de, 0 + ld bc, 0x68 + ldir + ld hl, stubs_low + ld ix, 0 + ld bc, 0x68 + call ldir_to_user + + im 1 ; set Z80 CPU interrupt mode 1 + + ret + +bankhelper: + .ascii 'Invoking bank helper\r\n' + .byte 0 + + +RTS_LOW equ 0xEA + +sio_setup: + .byte 0x00 + .byte 0x18 ; Reset + .byte 0x04 + .byte 0xC4 + .byte 0x01 + .byte 0x19 ; We want carrier events + .byte 0x03 + .byte 0xE1 + .byte 0x05 + .byte RTS_LOW + + +; +; Our memory setup is weird and common is kind of meaningless here +; + .code +_kernel_flag: + .byte 1 ; We start in kernel mode +map_save_low: +map_kernel_low: +map_restore_low: +map_user_low: +map_page_low: + ret + +_program_vectors: + ret + + .export _plt_idle + +_plt_idle: + halt + ret +; +; A little SIO helper +; + .export _sio2_otir + +_sio2_otir: + pop de + pop hl + push hl + push de + push bc + ld b, 0x06 + ld c,l + ld hl, _sio_r + otir + pop bc + ret + + .common +; +; outchar: Wait for UART TX idle, then print the char in A +; destroys: AF +; +outchar: + push af + ; wait for transmitter to be idle +ocloop_sio: + xor a ; read register 0 + out (SIOA_C), a + in a,(SIOA_C) ; read Line Status Register + and #0x04 ; get THRE bit + jr z,ocloop_sio + ; now output the char to serial port + pop af + out (SIOA_D),a + ret + + +; Don't be tempted to put the symbol in the code below ..it's relocated +; to zero. Instead define where it ends up. + + .abs + .org 0x18 +_plt_doexec: + + .discard + + .export rst38 + .export stubs_low +; This exists at the bottom of each page. We move these into place +; from discard. +; +stubs_low: + .byte 0 +stub0: .word 0 ; cp/m emu changes this + .byte 0 ; cp/m emu I/O byte + .byte 0 ; cp/m emu drive and user + jp 0 ; cp/m emu bdos entry point +rst8: + ret + nop + nop + nop + nop + nop + nop + nop +rst10: + ret + nop + nop + nop + nop + nop + nop + nop +rst18: + ld a, 0x01 + out (0x03),a + ld a, 0x58 + out (0x03),a +rst20: ei + jp (hl) + nop + nop + nop + nop + nop + nop +rst28: ret + nop + nop + nop + nop + nop + nop + nop +rst30: jp syscall_platform + nop + nop + nop + nop + nop +; +; We only have 38-4F available for this in low space +; +rst38: jp interrupt_high ; Interrupt handling stub + nop + nop + nop + nop + nop + .ds 0x26 +nmi_handler: ; Should be at 0x66 + retn + +; +; This stuff needs to live somewhere, anywhere out of the way (so we +; use common). We need to copy it to the same address on both banks +; so place it in common as we will put common into both banks +; + + .common + + .export ldir_to_user + .export ldir_from_user + +ldir_to_user: + ld de, 0x1858 ; from bank 0 to bank 1 +ldir_far: + push bc + ld bc, 0x0103 + exx + pop bc ; get BC into alt bank + di ; annoyingly : FIXME +far_ldir_1: + exx + out (c),b + out (c),d + ld a,(hl) + inc hl + out (c),b + out (c),e + ld (ix + 0),a + inc ix + exx + dec bc + ld a,b + or c + jr nz, far_ldir_1 + exx + out (c),b + ld b, 0x18 + out (c),b + exx + ret +ldir_from_user: + ld de, 0x5818 + jr ldir_far +; +; High stubs. Present in each bank in the top 256 bytes +; +interrupt_high: + push af + push de + push hl + ex af,af' + push af + push bc + exx + push bc + push de + push hl + push ix + push iy + ld a,(banknum) + ld c,a + ; + ; Switch to kernel + ; + ld a, 0x01 + out (0x03),a + ld a, 0x18 + out (0x03),a + ld (istack_switched_sp),sp ; istack is positioned to be valid + ld sp, istack_top ; in both banks. We just have to + ; + ; interrupt_handler may come back on a different stack in + ; which case bc is junk. Fortuntely we never pre-empt in + ; kernel so the case we care about bc is always safe. This is + ; not a good way to write code and should be fixed! FIXME + ; + push bc + call interrupt_handler ; switch on the right SP + pop bc + ; Restore stack pointer to user. This leaves us with an invalid + ; stack pointer if called from user but interrupts are off anyway + ld sp,(istack_switched_sp) + ; On return HL = signal vector E= signal (if any) A = page for + ; high + or a + jr z, kernout + ; Returning to user space + ld a, 0x01 ; User bank + out (0x03),a + ld a, 0x58 + out (0x03),a + ; User stack is now valid + ; back on user stack + xor a + cp e + call nz, sigpath +pops: + ex af,af' + exx + pop iy + pop ix + pop hl + pop de + pop bc + exx + pop bc + pop af + ex af,af' + pop hl + pop de + pop af + ei + ret +kernout: + ; restore bank - if we interrupt mid user copy or similar we + ; have to put the right bank back + ld a, 1 + out (0x03),a + ld a,c + out (0x03),a + jr pops + +sigpath: + push de ; signal number + ld de, irqsigret + push de ; clean up + ex de,hl + ld hl,(PROGLOAD+16) ; helper vector + jp (hl) +irqsigret: + inc sp ; drop signal number + inc sp + ret + +syscall_platform: + push ix + ld ix, 0 + add ix,sp + push bc + ld c,(ix + 6) + ld b,(ix + 7) + ld e,(ix + 8) + ld d,(ix + 9) + ld l,(ix + 10) + ld h,(ix + 11) + push hl + ld l,(ix + 12) + ld h,(ix + 13) + pop ix + di + ; BUG: syscall corrupts AF' - should we just define some + ; alt register corruptors for new API - would be sanest fix + ex af, af' ; Ick - find a better way to do this bit ! + ld a, 1 + out (0x03),a + ld a, 0x18 + out (0x03),a + ex af,af' + ; Stack now invalid + ld (_udata + U_DATA__U_SYSCALL_SP),sp + ld sp, kstack_top + call unix_syscall_entry + ; FIXME check di rules + ; stack now invalid. Grab the new sp before we unbank the + ; memory holding it + ld sp,(_udata + U_DATA__U_SYSCALL_SP) + ld a, 0x01 ; back to the user page + out (0x03),a + ld a, 0x58 + out (0x03),a + xor a + cp h + call nz, syscall_sigret + ; FIXME for now do the grungy C flag HL DE stuff from + ; lowlevel-z80 until we fix the ABI + pop bc + ld a,h + or l + jr nz, error + ex de,hl + pop ix + ei + ret +error: scf + pop ix + ei + ret +syscall_sigret: + ld a,l ; DEBUG + push hl ; save errno + push de ; save retval + ld l,h + ld h, 0 + push hl ; signal + ld hl, syscall_sighelp + push hl ; vector + push bc + ret +syscall_sighelp: + pop de ; discard signal + pop de ; recover error info + pop hl + ld h, 0 ; clear signal bit + ret diff --git a/Kernel/platform/platform-searle/searle.h b/Kernel/platform/platform-searle/searle.h index 87f30560d7..48249f3050 100644 --- a/Kernel/platform/platform-searle/searle.h +++ b/Kernel/platform/platform-searle/searle.h @@ -8,11 +8,11 @@ /* SIO 2 ports */ #define SIO0_BASE 0x00 -__sfr __at (SIO0_BASE + 0) SIOA_D; -__sfr __at (SIO0_BASE + 1) SIOB_D; -__sfr __at (SIO0_BASE + 2) SIOA_C; -__sfr __at (SIO0_BASE + 3) SIOB_C; +#define SIOA_D (SIO0_BASE + 0) +#define SIOB_D (SIO0_BASE + 1) +#define SIOA_C (SIO0_BASE + 2) +#define SIOB_C (SIO0_BASE + 3) -extern void sio2_otir(uint8_t port) __z88dk_fastcall; +extern void sio2_otir(uint8_t port); #endif diff --git a/Kernel/platform/platform-searle/searle.s b/Kernel/platform/platform-searle/searle.s index c7246b02da..2a19fdba20 100644 --- a/Kernel/platform/platform-searle/searle.s +++ b/Kernel/platform/platform-searle/searle.s @@ -1,54 +1,66 @@ +# 0 "searle.S" +# 0 "" +# 0 "" +# 1 "searle.S" ; -; Grant Searle SBC with timer hack and A16 wired for SIO control -; Also requires the revised boot rom that places the initial bank flip -; helper at 0xFFxx in both banks before the ROM is paged out (as it -; can't be paged back in). +; Grant Searle SBC with timer hack and A16 wired for SIO control +; Also requires the revised boot rom that places the initial bank flip +; helper at 0xFFxx in both banks before the ROM is paged out (as it +; can't be paged back in). ; - .module searle - ; exported symbols - .globl init_hardware - .globl interrupt_handler - .globl _program_vectors - .globl _kernel_flag - .globl map_page_low - .globl map_kernel_low - .globl map_user_low - .globl map_save_low - .globl map_restore_low - .globl _plt_doexec - .globl _plt_reboot - .globl _int_disabled - .globl syscall_platform + .export init_hardware + .export _program_vectors + .export _kernel_flag + .export map_page_low + .export map_kernel_low + .export map_user_low + .export map_save_low + .export map_restore_low + .export _plt_doexec + .export _plt_reboot + .export _int_disabled + .export syscall_platform ; exported debugging tools - .globl _plt_monitor - .globl outchar + .export _plt_monitor + .export outchar + +# 1 "kernelu.def" 1 +; FUZIX mnemonics for memory addresses etc + +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes @ F000 +Z80_TYPE .equ 0 ; CMOS + +Z80_MMU_HOOKS .equ 0 + +CONFIG_SWAP .equ 1 + +PROGBASE .equ 0x0000 +PROGLOAD .equ 0x0100 + +NBUFS .equ 4 - ; imported symbols - .globl _ramsize - .globl _procmem - .globl istack_top - .globl istack_switched_sp - .globl kstack_top - .globl unix_syscall_entry - .globl outcharhex - .globl outstring +; +; Select where to put the high code - in our case we need this +; in common +; - .globl s__COMMONMEM - .globl l__COMMONMEM - .include "kernel.def" - .include "../../cpu-z80/kernel-z80.def" +HIGHPAGE .equ 0 ; We only have 1 page byte and the low page + ; isn't used +# 27 "searle.S" 2 +# 1 "../../cpu-z80u/kernel-z80.def" 1 +# 28 "searle.S" 2 ; Base address of SIO/2 chip 0x00 -SIOA_D .EQU 0x00 -SIOB_D .EQU 0x01 -SIOA_C .EQU 0x02 -SIOB_C .EQU 0x03 +SIOA_D equ 0x00 +SIOB_D equ 0x01 +SIOA_C equ 0x02 +SIOB_C equ 0x03 @@ -57,444 +69,455 @@ SIOB_C .EQU 0x03 ; so we can recover the discard memory into the buffer pool ; - .globl _bufpool - .area _BUFFERS + .export _bufpool + .buffers _bufpool: - .ds BUFSIZE * NBUFS + .ds 520 * NBUFS ; ----------------------------------------------------------------------------- ; -; Because of the weird memory model this is a bit different to the -; usual Z80 setup. +; Because of the weird memory model this is a bit different to the +; usual Z80 setup. ; ; ----------------------------------------------------------------------------- - .area _COMMONMEM + .common _plt_monitor: _plt_reboot: - di ; No way back to the ROM - halt + di ; No way back to the ROM + halt _int_disabled: - .db 1 + .byte 1 ; ----------------------------------------------------------------------------- ; -; Our MMU is write only, but if we put a value in each bank in a fixed -; place we have a fast way to see which bank is which +; Our MMU is write only, but if we put a value in each bank in a fixed +; place we have a fast way to see which bank is which ; ; ----------------------------------------------------------------------------- banknum: - .byte 0x01 ; copied into far bank then set to 0 + .byte 0x01 ; copied into far bank then set to 0 ; ----------------------------------------------------------------------------- -; All of discard gets reclaimed when init is run +; All of discard gets reclaimed when init is run ; -; Discard must be above 0x8000 as we need some of it when the ROM -; is paged in during init_hardware +; Discard must be above 0x8000 as we need some of it when the ROM +; is paged in during init_hardware ; ----------------------------------------------------------------------------- - .area _DISCARD + .discard init_hardware: - ld hl,#sio_setup - ld bc,#0x0A00 + SIOA_C ; 10 bytes to SIOA_C - otir + ld hl, sio_setup + ld bc, 0x0A00 + SIOA_C ; 10 bytes to SIOA_C + otir - ld hl,#sio_setup - ld bc,#0x0A00 + SIOB_C ; and to SIOB_C - otir + ld hl, sio_setup + ld bc, 0x0A00 + SIOB_C ; and to SIOB_C + otir - ld hl, #128 + ld hl, #128 ld (_ramsize), hl - ld hl,#60 ; We lose 4K to common space + ld hl, 60 ; We lose 4K to common space ld (_procmem), hl - ld hl,#bankhelper - call outstring + ld hl, bankhelper + call outstring - ld hl,#s__COMMONMEM - ld de,#l__COMMONMEM + ld hl, __common + ld de, __common_size - ; This is run once so can be slow and simple + ; This is run once so can be slow and simple farput: - ld a,(hl) - call 0xFF00 ; put byte in a into (HL) in far memory - ; uses BC/HL/AF - inc hl - dec de - ld a,d - or e - jr nz,farput + ld a,(hl) + call 0xFF00 ; put byte in a into (HL) in far memory + ; uses BC/HL/AF + inc hl + dec de + ld a,d + or e + jr nz,farput - xor a - ld (banknum),a ; and correct page + xor a + ld (banknum),a ; and correct page - ; We now have our common in place. We can do the rest ourselves + ; We now have our common in place. We can do the rest ourselves - ; Put the low stubs into place in the kernel - ld hl,#stubs_low - ld de,#0 - ld bc,#0x68 - ldir - ld hl,#stubs_low - ld ix,#0 - ld bc,#0x68 - call ldir_to_user + ; Put the low stubs into place in the kernel + ld hl, stubs_low + ld de, 0 + ld bc, 0x68 + ldir + ld hl, stubs_low + ld ix, 0 + ld bc, 0x68 + call ldir_to_user - im 1 ; set Z80 CPU interrupt mode 1 + im 1 ; set Z80 CPU interrupt mode 1 - ret + ret bankhelper: - .asciz 'Invoking bank helper\r\n' + .ascii 'Invoking bank helper\r\n' + .byte 0 -RTS_LOW .EQU 0xEA +RTS_LOW equ 0xEA sio_setup: - .byte 0x00 - .byte 0x18 ; Reset - .byte 0x04 - .byte 0xC4 - .byte 0x01 - .byte 0x19 ; We want carrier events - .byte 0x03 - .byte 0xE1 - .byte 0x05 - .byte RTS_LOW + .byte 0x00 + .byte 0x18 ; Reset + .byte 0x04 + .byte 0xC4 + .byte 0x01 + .byte 0x19 ; We want carrier events + .byte 0x03 + .byte 0xE1 + .byte 0x05 + .byte RTS_LOW ; -; Our memory setup is weird and common is kind of meaningless here +; Our memory setup is weird and common is kind of meaningless here ; - .area _CODE - + .code _kernel_flag: - .db 1 ; We start in kernel mode + .byte 1 ; We start in kernel mode map_save_low: map_kernel_low: map_restore_low: map_user_low: map_page_low: - ret + ret _program_vectors: - ret + ret + + .export _plt_idle +_plt_idle: + halt + ret ; -; A little SIO helper +; A little SIO helper ; - .globl _sio_r - .globl _sio2_otir + .export _sio2_otir _sio2_otir: - ld b,#0x06 - ld c,l - ld hl,#_sio_r - otir - ret - - .area _COMMONMEM + pop de + pop hl + push hl + push de + push bc + ld b, 0x06 + ld c,l + ld hl, _sio_r + otir + pop bc + ret + + .common ; ; outchar: Wait for UART TX idle, then print the char in A ; destroys: AF ; outchar: - push af - ; wait for transmitter to be idle + push af + ; wait for transmitter to be idle ocloop_sio: - xor a ; read register 0 + xor a ; read register 0 out (SIOA_C), a - in a,(SIOA_C) ; read Line Status Register - and #0x04 ; get THRE bit - jr z,ocloop_sio - ; now output the char to serial port - pop af - out (SIOA_D),a - ret + in a,(SIOA_C) ; read Line Status Register + and #0x04 ; get THRE bit + jr z,ocloop_sio + ; now output the char to serial port + pop af + out (SIOA_D),a + ret ; Don't be tempted to put the symbol in the code below ..it's relocated ; to zero. Instead define where it ends up. -_plt_doexec .equ 0x18 + .abs + .org 0x18 +_plt_doexec: - .area _DISCARD + .discard - .globl rst38 - .globl stubs_low -; This exists at the bottom of each page. We move these into place -; from discard. + .export rst38 + .export stubs_low +; This exists at the bottom of each page. We move these into place +; from discard. ; stubs_low: - .byte 0 -stub0: .word 0 ; cp/m emu changes this - .byte 0 ; cp/m emu I/O byte - .byte 0 ; cp/m emu drive and user - jp 0 ; cp/m emu bdos entry point + .byte 0 +stub0: .word 0 ; cp/m emu changes this + .byte 0 ; cp/m emu I/O byte + .byte 0 ; cp/m emu drive and user + jp 0 ; cp/m emu bdos entry point rst8: - ret - nop - nop - nop - nop - nop - nop - nop + ret + nop + nop + nop + nop + nop + nop + nop rst10: - ret - nop - nop - nop - nop - nop - nop - nop + ret + nop + nop + nop + nop + nop + nop + nop rst18: - ld a,#0x01 - out (0x03),a - ld a,#0x58 - out (0x03),a -rst20: ei - jp (hl) - nop - nop - nop - nop - nop - nop -rst28: ret - nop - nop - nop - nop - nop - nop - nop -rst30: jp syscall_platform - nop - nop - nop - nop - nop + ld a, 0x01 + out (0x03),a + ld a, 0x58 + out (0x03),a +rst20: ei + jp (hl) + nop + nop + nop + nop + nop + nop +rst28: ret + nop + nop + nop + nop + nop + nop + nop +rst30: jp syscall_platform + nop + nop + nop + nop + nop ; -; We only have 38-4F available for this in low space +; We only have 38-4F available for this in low space ; -rst38: jp interrupt_high ; Interrupt handling stub - nop - nop - nop - nop - nop - .ds 0x26 -nmi_handler: ; Should be at 0x66 - retn +rst38: jp interrupt_high ; Interrupt handling stub + nop + nop + nop + nop + nop + .ds 0x26 +nmi_handler: ; Should be at 0x66 + retn ; -; This stuff needs to live somewhere, anywhere out of the way (so we -; use common). We need to copy it to the same address on both banks -; so place it in common as we will put common into both banks +; This stuff needs to live somewhere, anywhere out of the way (so we +; use common). We need to copy it to the same address on both banks +; so place it in common as we will put common into both banks ; - .area _COMMONMEM + .common - .globl ldir_to_user - .globl ldir_from_user + .export ldir_to_user + .export ldir_from_user ldir_to_user: - ld de,#0x1858 ; from bank 0 to bank 1 + ld de, 0x1858 ; from bank 0 to bank 1 ldir_far: - push bc - ld bc,#0x0103 - exx - pop bc ; get BC into alt bank - di ; annoyingly : FIXME + push bc + ld bc, 0x0103 + exx + pop bc ; get BC into alt bank + di ; annoyingly : FIXME far_ldir_1: - exx - out (c),b - out (c),d - ld a,(hl) - inc hl - out (c),b - out (c),e - ld (ix),a - inc ix - exx - dec bc - ld a,b - or c - jr nz, far_ldir_1 - exx - out (c),b - ld b,#0x18 - out (c),b - exx - ret + exx + out (c),b + out (c),d + ld a,(hl) + inc hl + out (c),b + out (c),e + ld (ix + 0),a + inc ix + exx + dec bc + ld a,b + or c + jr nz, far_ldir_1 + exx + out (c),b + ld b, 0x18 + out (c),b + exx + ret ldir_from_user: - ld de,#0x5818 - jr ldir_far + ld de, 0x5818 + jr ldir_far ; -; High stubs. Present in each bank in the top 256 bytes +; High stubs. Present in each bank in the top 256 bytes ; interrupt_high: - push af - push de - push hl - ex af,af' - push af - push bc - exx - push bc - push de - push hl - push ix - push iy - ld a,(banknum) - ld c,a - ; - ; Switch to kernel - ; - ld a,#0x01 - out (0x03),a - ld a,#0x18 - out (0x03),a - ld (istack_switched_sp),sp ; istack is positioned to be valid - ld sp,#istack_top ; in both banks. We just have to - ; - ; interrupt_handler may come back on a different stack in - ; which case bc is junk. Fortuntely we never pre-empt in - ; kernel so the case we care about bc is always safe. This is - ; not a good way to write code and should be fixed! FIXME - ; - push bc - call interrupt_handler ; switch on the right SP - pop bc - ; Restore stack pointer to user. This leaves us with an invalid - ; stack pointer if called from user but interrupts are off anyway - ld sp,(istack_switched_sp) - ; On return HL = signal vector E= signal (if any) A = page for - ; high - or a - jr z, kernout - ; Returning to user space - ld a,#0x01 ; User bank - out (0x03),a - ld a,#0x58 - out (0x03),a - ; User stack is now valid - ; back on user stack - xor a - cp e - call nz, sigpath + push af + push de + push hl + ex af,af' + push af + push bc + exx + push bc + push de + push hl + push ix + push iy + ld a,(banknum) + ld c,a + ; + ; Switch to kernel + ; + ld a, 0x01 + out (0x03),a + ld a, 0x18 + out (0x03),a + ld (istack_switched_sp),sp ; istack is positioned to be valid + ld sp, istack_top ; in both banks. We just have to + ; + ; interrupt_handler may come back on a different stack in + ; which case bc is junk. Fortuntely we never pre-empt in + ; kernel so the case we care about bc is always safe. This is + ; not a good way to write code and should be fixed! FIXME + ; + push bc + call interrupt_handler ; switch on the right SP + pop bc + ; Restore stack pointer to user. This leaves us with an invalid + ; stack pointer if called from user but interrupts are off anyway + ld sp,(istack_switched_sp) + ; On return HL = signal vector E= signal (if any) A = page for + ; high + or a + jr z, kernout + ; Returning to user space + ld a, 0x01 ; User bank + out (0x03),a + ld a, 0x58 + out (0x03),a + ; User stack is now valid + ; back on user stack + xor a + cp e + call nz, sigpath pops: - ex af,af' - exx - pop iy - pop ix - pop hl - pop de - pop bc - exx - pop bc - pop af - ex af,af' - pop hl - pop de - pop af - ei - ret + ex af,af' + exx + pop iy + pop ix + pop hl + pop de + pop bc + exx + pop bc + pop af + ex af,af' + pop hl + pop de + pop af + ei + ret kernout: - ; restore bank - if we interrupt mid user copy or similar we - ; have to put the right bank back - ld a,#1 - out (0x03),a - ld a,c - out (0x03),a - jr pops - + ; restore bank - if we interrupt mid user copy or similar we + ; have to put the right bank back + ld a, 1 + out (0x03),a + ld a,c + out (0x03),a + jr pops + sigpath: - push de ; signal number - ld de,#irqsigret - push de ; clean up - ex de,hl - ld hl,(PROGLOAD+16) ; helper vector - jp (hl) + push de ; signal number + ld de, irqsigret + push de ; clean up + ex de,hl + ld hl,(PROGLOAD+16) ; helper vector + jp (hl) irqsigret: - inc sp ; drop signal number - inc sp - ret + inc sp ; drop signal number + inc sp + ret syscall_platform: - push ix - ld ix,#0 - add ix,sp - push bc - ld c,6(ix) - ld b,7(ix) - ld e,8(ix) - ld d,9(ix) - ld l,10(ix) - ld h,11(ix) - push hl - ld l,12(ix) - ld h,13(ix) - pop ix - di - ; BUG: syscall corrupts AF' - should we just define some - ; alt register corruptors for new API - would be sanest fix - ex af, af' ; Ick - find a better way to do this bit ! - ld a,#1 - out (0x03),a - ld a,#0x18 - out (0x03),a - ex af,af' - ; Stack now invalid - ld (_udata + U_DATA__U_SYSCALL_SP),sp - ld sp,#kstack_top - call unix_syscall_entry - ; FIXME check di rules - ; stack now invalid. Grab the new sp before we unbank the - ; memory holding it - ld sp,(_udata + U_DATA__U_SYSCALL_SP) - ld a,#0x01 ; back to the user page - out (0x03),a - ld a,#0x58 - out (0x03),a - xor a - cp h - call nz, syscall_sigret - ; FIXME for now do the grungy C flag HL DE stuff from - ; lowlevel-z80 until we fix the ABI - pop bc - ld a,h - or l - jr nz, error - ex de,hl - pop ix - ei - ret -error: scf - pop ix - ei - ret + push ix + ld ix, 0 + add ix,sp + push bc + ld c,(ix + 6) + ld b,(ix + 7) + ld e,(ix + 8) + ld d,(ix + 9) + ld l,(ix + 10) + ld h,(ix + 11) + push hl + ld l,(ix + 12) + ld h,(ix + 13) + pop ix + di + ; BUG: syscall corrupts AF' - should we just define some + ; alt register corruptors for new API - would be sanest fix + ex af, af' ; Ick - find a better way to do this bit ! + ld a, 1 + out (0x03),a + ld a, 0x18 + out (0x03),a + ex af,af' + ; Stack now invalid + ld (_udata + 8),sp + ld sp, kstack_top + call unix_syscall_entry + ; FIXME check di rules + ; stack now invalid. Grab the new sp before we unbank the + ; memory holding it + ld sp,(_udata + 8) + ld a, 0x01 ; back to the user page + out (0x03),a + ld a, 0x58 + out (0x03),a + xor a + cp h + call nz, syscall_sigret + ; FIXME for now do the grungy C flag HL DE stuff from + ; lowlevel-z80 until we fix the ABI + pop bc + ld a,h + or l + jr nz, error + ex de,hl + pop ix + ei + ret +error: scf + pop ix + ei + ret syscall_sigret: - ld a,l ; DEBUG - push hl ; save errno - push de ; save retval - ld l,h - ld h,#0 - push hl ; signal - ld hl,#syscall_sighelp - push hl ; vector - push bc - ret + ld a,l ; DEBUG + push hl ; save errno + push de ; save retval + ld l,h + ld h, 0 + push hl ; signal + ld hl, syscall_sighelp + push hl ; vector + push bc + ret syscall_sighelp: - pop de ; discard signal - pop de ; recover error info - pop hl - ld h,#0 ; clear signal bit - ret - + pop de ; discard signal + pop de ; recover error info + pop hl + ld h, 0 ; clear signal bit + ret diff --git a/Kernel/platform/platform-searle/target.mk b/Kernel/platform/platform-searle/target.mk index 3bffcde0c7..3db0aba6a0 100644 --- a/Kernel/platform/platform-searle/target.mk +++ b/Kernel/platform/platform-searle/target.mk @@ -1 +1,3 @@ -export CPU = z80 +export CPU = z80u +export USERCPU = z80 + diff --git a/Kernel/platform/platform-searle/tricks.S b/Kernel/platform/platform-searle/tricks.S new file mode 100644 index 0000000000..2280dbecba --- /dev/null +++ b/Kernel/platform/platform-searle/tricks.S @@ -0,0 +1,4 @@ +#include "kernelu.def" +#include "../../cpu-z80u/kernel-z80.def" + +#include "../../lib/z80usingle.S" diff --git a/Kernel/platform/platform-searle/tricks.s b/Kernel/platform/platform-searle/tricks.s index 2d02424493..4c8d755fc2 100644 --- a/Kernel/platform/platform-searle/tricks.s +++ b/Kernel/platform/platform-searle/tricks.s @@ -1,5 +1,294 @@ - .include "kernel.def" - .include "../../cpu-z80/kernel-z80.def" +# 0 "tricks.S" +# 0 "" +# 0 "" +# 1 "tricks.S" +# 1 "kernelu.def" 1 +; FUZIX mnemonics for memory addresses etc - .include "../../lib/z80single.s" +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes @ F000 +Z80_TYPE .equ 0 ; CMOS +Z80_MMU_HOOKS .equ 0 + +CONFIG_SWAP .equ 1 + +PROGBASE .equ 0x0000 +PROGLOAD .equ 0x0100 + +NBUFS .equ 4 + +; +; Select where to put the high code - in our case we need this +; in common +; + + +HIGHPAGE .equ 0 ; We only have 1 page byte and the low page + ; isn't used +# 2 "tricks.S" 2 +# 1 "../../cpu-z80u/kernel-z80.def" 1 +# 3 "tricks.S" 2 + +# 1 "../../lib/z80usingle.S" 1 +; +; Generic handling for single process in memory Z80 systems. +; +; This code could really do with some optimizing. +; +; FIXME: IRQ enable logic during swap +; + .export _plt_switchout + .export _switchin + .export _dofork + + .common + +; Switchout switches out the current process, finds another that is READY, +; possibly the same process, and switches it in. When a process is +; restarted after calling switchout, it thinks it has just returned +; from switchout(). +; +; This function can have no arguments or auto variables. +_plt_switchout: + di + ; save machine state + + ld hl, 0 ; return code set here is ignored, but _switchin can + + ; return from either _switchout OR _dofork, so they must both write + ; 14 with the following on the stack: + push hl ; return code + push ix + push iy + ld (_udata + 14), sp ; this is where the SP is restored in _switchin + + ; find another process to run (may select this one again) + call _getproc + + push hl + call _switchin + + ; we should never get here + call _plt_monitor + +badswitchmsg: .ascii "_switchin: FAIL" + .byte 13, 10, 0 +swapped: .ascii "_switchin: SWAPPED" + .byte 13, 10, 0 + +_switchin: + di + ld a,#1 + ld (_int_disabled),a + pop bc ; return address + pop de ; new process pointer +; +; FIXME: do we actually *need* to restore the stack ! +; + push de ; restore stack + push bc ; restore stack + + push de + ld hl, 15 + add hl, de ; process ptr + pop de + + ld a, (hl) + + or a + jr nz, not_swapped + ; + ; We are still on the departing processes stack, which is + ; fine for now. + ; + ld sp, _swapstack + ; + ; The process we are switching from is not resident. In + ; practice that means it exited. We don't need to write + ; it back out as it's dead. + ; + ld ix,(_udata + 0) + ld a, (ix + 15) + + or a + jr z, not_resident + ; + ; DE = process we are switching to + ; + push de ; save process + ; We will always swap out the current process + ld hl, (_udata + 0) + push hl + call _swapout + pop hl + pop de ; process to swap to +not_resident: + push de ; called function may modify on stack arg so make + push de ; two copies + call _swapper + pop de + pop de + +not_swapped: + ; check u_data->u_ptab matches what we wanted + ld hl, (_udata + 0) ; u_data->u_ptab + or a ; clear carry flag + sbc hl, de ; subtract, result will be zero if DE==HL + jr nz, switchinfail + + ; wants optimising up a bit + ld ix, (_udata + 0) + ; next_process->p_status = 1 + ld (ix + 0), 1 + + ; Fix the moved page pointers + ; Just do one byte as that is all we use on this platform + ld a, (ix + 15) + ld (_udata + 2), a + ; runticks = 0 + ld hl, 0 + ld (_runticks), hl + + ; restore machine state -- note we may be returning from either + ; _switchout or _dofork + ld sp, (_udata + 14) + + pop iy + pop ix + pop hl ; return code + + ; enable interrupts, if the ISR isn't already running + ld a, (_udata + 16) + ; put th einterrupt status flag back correctly + ld (_int_disabled),a + or a + ret nz ; in ISR, leave interrupts off + ei + ret ; return with interrupts on + +switchinfail: + call outhl + ld hl, badswitchmsg + call outstring + ; something went wrong and we didn't switch in what we asked for + jp _plt_monitor + +fork_proc_ptr: + .word 0 ; (C type is struct p_tab *) -- address of child process p_tab entry + +; +; Called from _fork. We are in a syscall, the uarea is live as the +; parent uarea. The kernel is the mapped object. +; +_dofork: + ; always disconnect the vehicle battery before performing maintenance + di ; should already be the case ... belt and braces. + + pop de ; return address + pop hl ; new process p_tab* + push hl + push de + + ld (fork_proc_ptr), hl + + ; Save the stack pointer and critical registers. + ; When this process (the parent) is switched back in, it will be as if + ; it returns with the value of the child's pid. + ld hl,#0 + push hl ; #0 child + push ix + push iy + + ; save kernel stack pointer -- when it comes back in the child we'll be in + ; _switchin which will immediately return (appearing to be _dofork() + ; returning) and with HL (ie return code) containing the child PID. + ; Hurray. + ld (_udata + 14), sp + + ; now we're in a safe state for _switchin to return in the parent + ; process. + + + ; Make a new process table entry, etc. + + ; Copy the parent properties into the temporary udata copy + call _tmpbuf + ld a,h + or l + jp z,ohpoo + push hl + ex de,hl + ld hl, _udata + ld bc, U_DATA__TOTALSIZE + ldir + + ; Recover the buffer pointer + pop hl + push hl + + ; Make the child udata out of the temporary buffer + push hl + ld hl, (fork_proc_ptr) + push hl + call _makeproc + pop bc + pop bc + + ; in the child process, fork() returns zero. + ; + ; And we exit, with the kernel mapped, the child assembled in the + ; copy area as if it had done a switchout, the parent meanwhile + ; continues happily on + + ; now we're in a safe state for _switchin to return in the child + ; process swap out the image and the new udata + + ; Stack the buffer as a second argument + pop hl + push hl + push hl + + ld hl, (fork_proc_ptr) + push hl + call _swapout_new + pop hl + pop hl + + ; Buffer pointer is sitting top of stack still + ; so use it as an argument to tmpfree + call _tmpfree + + pop hl + + ld hl, (fork_proc_ptr) + ; prepare return value in parent process -- HL = p->p_pid; + ld de, 3 + add hl, de + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + ; now the copy operation is complete we can get rid of the stuff + ; _switchin will be expecting from our copy of the stack. + pop bc + pop bc + pop bc + ; Return pid of child we forked into swap + ret + +ohpoo: + ld hl,#nobufs + call outstring + jp _plt_monitor + +nobufs: + .ascii 'nobufs' + .byte 0 +; +; We can keep a stack in common because we will complete our +; use of it before we switch common block. In this case we have +; a true common so it's even easier. +; + .ds 128 +_swapstack: +# 5 "tricks.S" 2 diff --git a/Kernel/platform/platform-searle/usermem.S b/Kernel/platform/platform-searle/usermem.S new file mode 100644 index 0000000000..8fc48378de --- /dev/null +++ b/Kernel/platform/platform-searle/usermem.S @@ -0,0 +1,180 @@ +; +; We have a custom implementation of usermem. We really need +; to optimize ldir_to/from_user. +; +#include "kernelu.def" +#include "../../cpu-z80u/kernel-z80.def" + + ; exported symbols + .export __uget + .export __ugetc + .export __ugetw + + .export __uput + .export __uputc + .export __uputw + .export __uzero + + .common + +uputget: + ; load DE with the byte count + ld c, (ix + 8) ; byte count + ld b, (ix + 9) + ld a, b + or c + ret z ; no work + ; load HL with the source address + ld l, (ix + 4) ; src address + ld h, (ix + 5) + ; load DE with destination address + ld e, (ix + 6) + ld d, (ix + 7) + ret + +__uget: + push ix + ld ix,0 + add ix, sp + push bc + call uputget + jr z, uget_out + push de + pop ix + call ldir_from_user +uget_out: + pop bc + pop ix + ld hl,0 + ret + +__uput: + push ix + ld ix,0 + add ix,sp + push bc + call uputget + jr z, uget_out + push de + pop ix + call ldir_to_user + jr uget_out + +; +; The kernel IRQ code will restore the bank if it interrupts this +; logic +; +__uzero: + ld hl,2 + add hl,sp + push bc + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ld c,(hl) + inc hl + ld b,(hl) + ld a,b + or c + jr z,zout + di + ld a,1 + out (0x03),a ; Port B WR 1 + ld a,0x58 + out (0x03),a ; port B WR 1 to 0x58 + ld (hl),0 + ld a,(_int_disabled) + or a + jr nz, noteiz + ei +noteiz: + dec bc + ld a,b + or c + jr z, uout + ld e,l + ld d,h + inc de + ldir +uout: + di + ld a,1 ; port B WR 1 + out (0x03),a + ld a,0x18 + out (0x03),a ; back to kernel +zout: + pop bc + ld a,(_int_disabled) + or a + ret nz + ei + ret + +__ugetc: + push bc + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld l,(hl) + ld h,0 + jr uout + +__ugetw: + push bc + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jr uout + +__uputc: + ld hl,2 + add hl,sp + push bc + ld c,(hl) + inc hl + inc hl + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld (hl),c + ld hl,0 + jr uout + +__uputw: + ld hl,2 + add hl,sp + push bc + ld c,(hl) + inc hl + ld b,(hl) + inc hl + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + ld e,a + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld (hl),c + inc hl + ld (hl),b + ld hl,0 + jr uout diff --git a/Kernel/platform/platform-searle/usermem.s b/Kernel/platform/platform-searle/usermem.s index 19d121c9da..188fae2383 100644 --- a/Kernel/platform/platform-searle/usermem.s +++ b/Kernel/platform/platform-searle/usermem.s @@ -1,165 +1,208 @@ +# 0 "usermem.S" +# 0 "" +# 0 "" +# 1 "usermem.S" ; -; We have a custom implementation of usermem. We really need -; to optimize ldir_to/from_user. +; We have a custom implementation of usermem. We really need +; to optimize ldir_to/from_user. ; - .module usermem +# 1 "kernelu.def" 1 +; FUZIX mnemonics for memory addresses etc - .include "kernel.def" - .include "../../cpu-z80/kernel-z80.def" +U_DATA__TOTALSIZE .equ 0x200 ; 256+256 bytes @ F000 +Z80_TYPE .equ 0 ; CMOS - ; exported symbols - .globl __uget - .globl __ugetc - .globl __ugetw +Z80_MMU_HOOKS .equ 0 - .globl __uput - .globl __uputc - .globl __uputw - .globl __uzero +CONFIG_SWAP .equ 1 - .globl ldir_from_user - .globl ldir_to_user +PROGBASE .equ 0x0000 +PROGLOAD .equ 0x0100 - .globl _int_disabled +NBUFS .equ 4 - .area _COMMONMEM +; +; Select where to put the high code - in our case we need this +; in common +; +HIGHPAGE .equ 0 ; We only have 1 page byte and the low page + ; isn't used +# 6 "usermem.S" 2 +# 1 "../../cpu-z80u/kernel-z80.def" 1 +# 7 "usermem.S" 2 + + ; exported symbols + .export __uget + .export __ugetc + .export __ugetw + + .export __uput + .export __uputc + .export __uputw + .export __uzero + + .common + uputget: ; load DE with the byte count - ld c, 8(ix) ; byte count - ld b, 9(ix) - ld a, b - or c - ret z ; no work + ld c, (ix + 8) ; byte count + ld b, (ix + 9) + ld a, b + or c + ret z ; no work ; load HL with the source address - ld l, 4(ix) ; src address - ld h, 5(ix) + ld l, (ix + 4) ; src address + ld h, (ix + 5) ; load DE with destination address - ld e, 6(ix) - ld d, 7(ix) - ret + ld e, (ix + 6) + ld d, (ix + 7) + ret __uget: - push ix - ld ix,#0 - add ix, sp - call uputget - jr z, uget_out - push de - pop ix - call ldir_from_user + push ix + ld ix,0 + add ix, sp + push bc + call uputget + jr z, uget_out + push de + pop ix + call ldir_from_user uget_out: - pop ix - ld hl,#0 - ret + pop bc + pop ix + ld hl,0 + ret __uput: - push ix - ld ix,#0 - add ix,sp - call uputget - jr z, uget_out - push de - pop ix - call ldir_to_user - jr uget_out + push ix + ld ix,0 + add ix,sp + push bc + call uputget + jr z, uget_out + push de + pop ix + call ldir_to_user + jr uget_out ; -; The kernel IRQ code will restore the bank if it interrupts this -; logic +; The kernel IRQ code will restore the bank if it interrupts this +; logic ; __uzero: - pop de - pop hl - pop bc - push bc - push hl - push de - ld a,b - or c - ret z - di - ld a,#1 - out (0x03),a ; Port B WR 1 - ld a,#0x58 - out (0x03),a ; port B WR 1 to 0x58 - ld (hl),#0 - ld a,(_int_disabled) - or a - jr nz, noteiz - ei + ld hl,2 + add hl,sp + push bc + ld e,(hl) + inc hl + ld d,(hl) + inc hl + ld c,(hl) + inc hl + ld b,(hl) + ld a,b + or c + jr z,zout + di + ld a,1 + out (0x03),a ; Port B WR 1 + ld a,0x58 + out (0x03),a ; port B WR 1 to 0x58 + ld (hl),0 + ld a,(_int_disabled) + or a + jr nz, noteiz + ei noteiz: - dec bc - ld a,b - or c - jr z, uout - ld e,l - ld d,h - inc de - ldir + dec bc + ld a,b + or c + jr z, uout + ld e,l + ld d,h + inc de + ldir uout: - di - ld a,#1 ; port B WR 1 - out (0x03),a - ld a,#0x18 - out (0x03),a ; back to kernel - ld a,(_int_disabled) - or a - ret nz - ei - ret + di + ld a,1 ; port B WR 1 + out (0x03),a + ld a,0x18 + out (0x03),a ; back to kernel +zout: + pop bc + ld a,(_int_disabled) + or a + ret nz + ei + ret __ugetc: - di - ld a,#1 - out (0x03),a - ld a,#0x58 - out (0x03),a - ld l,(hl) - ld h,#0 - jr uout + push bc + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld l,(hl) + ld h,0 + jr uout __ugetw: - di - ld a,#1 - out (0x03),a - ld a,#0x58 - out (0x03),a - ld a,(hl) - inc hl - ld h,(hl) - ld l,a - jr uout - + push bc + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld a,(hl) + inc hl + ld h,(hl) + ld l,a + jr uout + __uputc: - pop bc - pop de - pop hl - push hl - push de - push bc - di - ld a,#1 - out (0x03),a - ld a,#0x58 - out (0x03),a - ld (hl),e - jr uout + ld hl,2 + add hl,sp + push bc + ld c,(hl) + inc hl + inc hl + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld (hl),c + ld hl,0 + jr uout __uputw: - pop bc - pop de - pop hl - push hl - push de - push bc - di - ld a,#1 - out (0x03),a - ld a,#0x58 - out (0x03),a - ld (hl),e - inc hl - ld (hl),d - jr uout + ld hl,2 + add hl,sp + push bc + ld c,(hl) + inc hl + ld b,(hl) + inc hl + ld e,(hl) + inc hl + ld d,(hl) + ex de,hl + ld e,a + di + ld a,1 + out (0x03),a + ld a,0x58 + out (0x03),a + ld (hl),c + inc hl + ld (hl),b + ld hl,0 + jr uout