From: Alan Cox Date: Fri, 23 Jan 2015 00:03:11 +0000 (+0000) Subject: 6502: first cut at signal handler logic X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=b80bf4ed9e97c7d6dcd7166c4ad18f3d03d2aa6a;p=FUZIX.git 6502: first cut at signal handler logic This is quite ugly because the C stack may not be consistent during an IRQ event. Punt most of the mess to the C app and require 6502 apps all have a signal handling stub vectored at base + 20 --- diff --git a/Kernel/cpu-6502/cpu.h b/Kernel/cpu-6502/cpu.h index a8aece37..a2610dfd 100644 --- a/Kernel/cpu-6502/cpu.h +++ b/Kernel/cpu-6502/cpu.h @@ -22,7 +22,9 @@ extern void * __fastcall__ memset(void *, int, size_t); extern size_t __fastcall__ strlen(const char *); #define EMAGIC 0x4C /* Header of executable (JMP) */ -#define brk_limit() ramtop /* Stack is preallocated */ +/* High byte is saved, low byte is a mystery so take worst case. Also allow + a bit less as C stack is not return stack */ +#define brk_limit() ((udata.u_syscall_sp | 0xFF) - 384) #define staticfast static diff --git a/Kernel/cpu-z80/cpu.h b/Kernel/cpu-z80/cpu.h index e841ecf8..d399e1f8 100644 --- a/Kernel/cpu-z80/cpu.h +++ b/Kernel/cpu-z80/cpu.h @@ -33,9 +33,7 @@ extern void irqrestore(irqflags_t f); extern int16_t strlen(const char *p); -#define staticfast static - -/* User's structure for times() system call */ +#define staticfast static/* User's structure for times() system call */ typedef unsigned long clock_t; /* Must match native ordering of long long */ diff --git a/Kernel/lowlevel-6502.s b/Kernel/lowlevel-6502.s index 7ad12971..92915720 100644 --- a/Kernel/lowlevel-6502.s +++ b/Kernel/lowlevel-6502.s @@ -10,6 +10,7 @@ .export outnewline .export outcharhex .export outxa + .export stash_zp .import outchar .import _kernel_flag @@ -88,7 +89,7 @@ _doexec: ; properly restored! ; interrupt_handler: - jsr stash_zp ; Save zero page bits +; Our caller will deal with ZP via stash_sp and any platform magic jsr map_save jsr map_kernel lda #1 @@ -103,7 +104,6 @@ interrupt_handler: interrupt_k: jsr map_restore int_switch: - jsr stash_zp ; Zero page stuff reverse lda #0 sta _inint rts diff --git a/Kernel/platform-tgl6502/kernel.def b/Kernel/platform-tgl6502/kernel.def index 8d4734e0..237aad96 100644 --- a/Kernel/platform-tgl6502/kernel.def +++ b/Kernel/platform-tgl6502/kernel.def @@ -5,3 +5,4 @@ U_DATA .set $0200 ; 256+256+256 bytes. U_DATA__TOTALSIZE .set $300 +PROGLOAD .set $2000 diff --git a/Kernel/platform-tgl6502/tgl6502.s b/Kernel/platform-tgl6502/tgl6502.s index 8479c5e0..455d1374 100644 --- a/Kernel/platform-tgl6502/tgl6502.s +++ b/Kernel/platform-tgl6502/tgl6502.s @@ -35,6 +35,8 @@ .import _unix_syscall .import _platform_interrupt .import _kernel_flag + .import stash_zp + .import pushax .import outcharhex .import outxa @@ -307,13 +309,6 @@ outchar: ; we can use the shorter one for the CMOS chip ; vector: - lda #')' - sta $FF03 - pla - tax - pla - jsr outxa - jmp _trap_monitor pha txa pha @@ -321,12 +316,12 @@ vector: pha cld ; +; Q: do we want to spot brk() instructions and signal them ? +; +; ; Save the old stack ptr ; - lda sp ; put the C stack - pha ; on the 6502 stack - lda sp+1 - pha + jsr stash_zp ; Save zero page bits tsx ; and save the 6502 stack ptr stx istack_switched_sp ; in uarea/stacks ; @@ -347,18 +342,61 @@ vector: ; ldx istack_switched_sp txs ; recover 6502 stack - pla ; recover C stack - sta sp+1 ; from 6502 stack - pla - sta sp+1 + jsr stash_zp ; restore zero page bits +; +; Signal handling on 6502 is foul as the C stack may be inconsistent +; during an IRQ. We push a new complete rti frame below the official +; one, along with a vector and the signal number. The glue in the +; app is expected to switch to a signal stack or similar, pop the +; values, invoke the signal handler and then return. +; +; FIXME: at the moment the irqout path will not check for multiple +; signals so the next one gets delivered next irq. +; +; + lda U_DATA__U_CURSIG + beq irqout + tay + tsx + txa + sec + sbc #6 ; move down past the existing rti + tax + txs + lda #>irqout + pha + lda #PROGLOAD + 20 + lda #0 + pha ; dummy flags, with irq enable + rti ; return on the fake frame + ; if the handler returns + ; rather than doing a longjmp + ; we'll end up at irqout and pop the + ; real frame irqout: pla - tya + tay pla - txa + tax pla rti - ; ; sp/sp+1 are the C stack of the userspace ; with the syscall number in X @@ -455,10 +493,63 @@ noargs: sta sp+1 pla sta sp -; -; FIXME: do signal dispatch - this will need C stack fixing, and -; basically signal dispatch is __interrupt. -; + lda U_DATA__U_CURSIG + beq syscout + tay + + tsx ; Move past existing return stack + dex + dex + dex + txs + + ; + ; The signal handler might make syscalls so we need to get + ; our return saved and return the right value! + ; + lda U_DATA__U_ERROR + pha + lda U_DATA__U_RETVAL + pha + lda U_DATA__U_RETVAL+1 + pha + lda #>sigret ; Return address + pha + lda #