6502: first cut at signal handler logic
authorAlan Cox <alan@linux.intel.com>
Fri, 23 Jan 2015 00:03:11 +0000 (00:03 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 23 Jan 2015 00:03:11 +0000 (00:03 +0000)
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

Kernel/cpu-6502/cpu.h
Kernel/cpu-z80/cpu.h
Kernel/lowlevel-6502.s
Kernel/platform-tgl6502/kernel.def
Kernel/platform-tgl6502/tgl6502.s
Library/libs/crt0_6502.s

index a8aece3..a2610df 100644 (file)
@@ -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
 
index e841ecf..d399e1f 100644 (file)
@@ -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 */
index 7ad1297..9291572 100644 (file)
@@ -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
index 8d4734e..237aad9 100644 (file)
@@ -5,3 +5,4 @@ U_DATA                      .set $0200
 ; 256+256+256 bytes.
 U_DATA__TOTALSIZE           .set $300        
 
+PROGLOAD                   .set $2000
index 8479c5e..455d137 100644 (file)
@@ -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 #<irqout
+           pha                         ; stack a return vector
+           tya
+           pha                         ; stack signal number
+           ldx #0
+           stx U_DATA__U_CURSIG
+           asl a
+           tay
+           lda U_DATA__U_SIGVEC,y      ; Our vector (low)
+           pha                         ; stack half of vector
+           lda U_DATA__U_SIGVEC+1,y    ; High half
+           pha                         ; stack rest of vector
+           txa
+           sta U_DATA__U_SIGVEC,y      ; Wipe the vector
+           sta U_DATA__U_SIGVEC+1,y
+           lda #<PROGLOAD + 20
+           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 #<sigret
+           pha
+
+           tya
+           pha                         ; signal
+           ldx #0
+           stx U_DATA__U_CURSIG
+           asl a
+           tay
+           lda U_DATA__U_SIGVEC,y      ; Our vector
+           pha
+           lda U_DATA__U_SIGVEC+1,y
+           pha
+           txa
+           sta U_DATA__U_SIGVEC,y      ; Wipe the vector
+           sta U_DATA__U_SIGVEC+1,y
+
+           ; Invoke the helper with signal and vector stacked
+           ; it will then return to syscout and recover the original
+           ; frame. If the handler made syscalls then
+           jmp (PROGLOAD + 20)
+
+           ;
+           ; FIXME: should loop for more signals if appropriate
+           ;
+sigret:
+           pla         ; Unstack the syscall return pieces
+           tax
+           pla
+           tay
+           pla
+           plp         ; from original stack frame
+           rts
+
+syscout:
 ;      We may be in decimal mode beyond this line.. take care
 ;
            plp
index 5a0ad8f..fcc580c 100644 (file)
@@ -11,7 +11,7 @@
        .export         _environ
        .export         initmainargs
        .import         _main
-       .import         popax
+       .import         popax, pushax
        .import         ___stdio_init_vars
 
        .export __STARTUP__ : absolute = 1;
        .word   __DATA_SIZE__
        .word   __BSS_SIZE__
        .word   0
+       .word   0       ; padding
+       .word   __sighandler            ; IRQ path signal handling helper
 
-
+;
+;      First cut at sighandling stubs, horrible on 6502!
+;
+;      The user stack may be invalid. If we hit mid update then the low
+;      byte may be updated but the carry into the high byte not done.
+;
+;      I think therefore that providing we dec sp+1 we are always ok and
+;      will be somewhere between 0 and 255 bytes of valid
+;
+;
+__sighandler:
+       jsr     stash_zp        ; saves sp etc
+       dec     sp+1            ; ensure we are safe C stack wise
+       pla
+       sta     ptr1            ; ZP was swapped
+       pla
+       sta     ptr1+1          ; ptr1 is now the function
+       pla
+       ldx     #0
+       jsr     pushax          ; signal(int sig)
+       jsr     jptr1           ; no jsr (x) so fake it
+       jsr     stash_zp        ; recovers sp
+initmainargs:                  ; Hardcoded compiler dumbness
+       rts                     ; will return via the kernel stub
+                               ; to user space
+jptr1: jmp     (ptr1)
+;
 ;
 ;      On entry sp/sp+1 have been set up by the kernel (this has to be
 ;      done in kernel as we might take a signal very early on). Above the
@@ -48,6 +76,9 @@ start:
 ;
 ; Need to save the environment ptr. The rest of the stack should be
 ; fine.
+;
+;
+;      FIXME: sort out some sort of constructor mechanism for this
 ;
        jsr     ___stdio_init_vars
        lda     sp
@@ -67,8 +98,30 @@ l1:  sta     _environ
        jmp     _exit           ; exit cleanup, AX holds our return code
                                ; for a fastcall return to nowhere.
 
-initmainargs:                  ; Hardcoded compiler dumbness
-       rts
+;
+;      The following is taken from the debugger example as referenced in
+;      the compiler documentation. We swap a stashed ZP in our commondata
+;      with an IRQ handler one. The commondata is per process and we depend
+;      upon this to make it all work
+;
+; Swap the C temporaries
+;
+stash_zp:
+        ldy     #zpsavespace-1
+Swap1:  ldx     CTemp,y
+        lda     <sp,y
+        sta     CTemp,y
+        txa
+        sta     sp,y
+        dey
+        bpl     Swap1
+        rts
+
 
        .bss
-_environ:      .word   0
+_environ:      .res    2
+oldsp:         .res    2
+CTemp:
+               .res    2               ; sp
+               .res    2               ; sreg
+               .res    (zpsavespace-4) ; Other stuff