From c0f6dea21373ff1c1e69f30e1196b52777adf7f5 Mon Sep 17 00:00:00 2001 From: cuz Date: Thu, 21 Apr 2005 01:41:50 +0000 Subject: [PATCH] Startup code with interruptor support by Oliver Schmidt git-svn-id: svn://svn.cc65.org/cc65/trunk@3479 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- libsrc/apple2/crt0.s | 241 +++++++++++++++++++++++++------------------ 1 file changed, 140 insertions(+), 101 deletions(-) diff --git a/libsrc/apple2/crt0.s b/libsrc/apple2/crt0.s index 106642d79..074e592ed 100644 --- a/libsrc/apple2/crt0.s +++ b/libsrc/apple2/crt0.s @@ -4,129 +4,168 @@ ; This must be the *first* file on the linker command line ; - .export _exit, __Exit - .import initlib, donelib - .import zerobss - .import __STARTUP_LOAD__, __BSS_LOAD__ ; Linker generated - .import callmain + .export _exit, __Exit + .import zerobss + .import initlib, donelib + .import callmain, callirq + .import __STARTUP_LOAD__, __BSS_LOAD__ ; Linker generated + .import __INTERRUPTOR_COUNT__ ; Linker generated .include "zeropage.inc" - .include "apple2.inc" + .include "apple2.inc" + .include "mli.inc" ; ------------------------------------------------------------------------ -; The executable header -.segment "EXEHDR" + .segment "EXEHDR" - .word __STARTUP_LOAD__ ; Start address - .word __BSS_LOAD__ - __STARTUP_LOAD__ ; Size + .addr __STARTUP_LOAD__ ; Start address + .word __BSS_LOAD__ - __STARTUP_LOAD__ ; Size ; ------------------------------------------------------------------------ -; Place the startup code in a special segment. -.segment "STARTUP" + .segment "STARTUP" + + ; ProDOS TechRefMan, chapter 5.2.1: + ; "For maximum interrupt efficiency, a system program should not + ; use more than the upper 3/4 of the stack." + ldx #$FF + txs ; Init stack pointer + + ; Delegate all further processing to keep STARTUP small + jsr init + + ; Avoid re-entrance of donelib. This is also the _exit entry +_exit: ldx #<__Exit + lda #>__Exit + jsr reset ; Setup RESET vector + + ; Check for valid interrrupt vector table entry number + lda intnum + beq :+ + + ; Deallocate interrupt vector table entry + dec params ; Adjust parameter count + jsr ENTRY + .byte $41 ; Dealloc interrupt + .addr params + + ; Call module destructors +: jsr donelib + + ; Restore the original RESET vector. This is also the __Exit entry +__Exit: ldx #$02 +: lda rvsave,x + sta SOFTEV,x + dex + bpl :- + + ; Copy back the zero page stuff + ldx #zpspace-1 +: lda zpsave,x + sta sp,x + dex + bpl :- + + ; ProDOS TechRefMan, chapter 5.2.1: + ; "System programs should set the stack pointer to $FF at the + ; warm-start entry point." + ldx #$FF + txs ; Re-init stack pointer + + ; Back to DOS + jmp DOSWARM -; ProDOS TechRefMan, chapter 5.2.1: -; "For maximum interrupt efficiency, a system program should not use more -; than the upper 3/4 of the stack." - - ldx #$FF - txs ; Init stack pointer - -; Save the zero page locations we need - - ldx #zpspace-1 -: lda sp,x - sta zpsave,x - dex - bpl :- - -; Save the original RESET vector - - ldx #$02 -: lda SOFTEV,x - sta rvsave,x - dex - bpl :- - -; ProDOS TechRefMan, chapter 5.3.5: -; "Your system program should place in the RESET vector the address of a -; routine that ... closes the files." - - ldx #<_exit - lda #>_exit - jsr reset ; Setup RESET vector - -; Clear the BSS data - - jsr zerobss - -; Setup the stack - - lda HIMEM - sta sp - lda HIMEM+1 - sta sp+1 ; Set argument stack ptr - -; Call module constructors - - jsr initlib - -; Push arguments and call main() - - jsr callmain - -; Avoid re-entrance of donelib. This is also the _exit entry - -_exit: ldx #<__Exit - lda #>__Exit - jsr reset ; Setup RESET vector - -; Call module destructors +; ------------------------------------------------------------------------ - jsr donelib + .segment "INIT" + + ; Save the zero page locations we need +init: ldx #zpspace-1 +: lda sp,x + sta zpsave,x + dex + bpl :- + + ; Save the original RESET vector + ldx #$02 +: lda SOFTEV,x + sta rvsave,x + dex + bpl :- + + ; ProDOS TechRefMan, chapter 5.3.5: + ; "Your system program should place in the RESET vector the + ; address of a routine that ... closes the files." + ldx #<_exit + lda #>_exit + jsr reset ; Setup RESET vector + + ; Clear the BSS data + jsr zerobss + + ; Setup the stack + lda HIMEM + sta sp + lda HIMEM+1 + sta sp+1 ; Set argument stack ptr + + ; Call module constructors + jsr initlib + + ; Check for interruptors + lda #<__INTERRUPTOR_COUNT__ + beq :+ + + ; Check for ProDOS + lda ENTRY + cmp #$4C ; Is MLI present? (JMP opcode) + bne :+ + + ; Allocate interrupt vector table entry + jsr ENTRY + .byte $40 ; Alloc interrupt + .addr params + + ; Push arguments and call main() +: jmp callmain -; Restore the original RESET vector. This is also the __Exit entry +; ------------------------------------------------------------------------ -__Exit: ldx #$02 -: lda rvsave,x - sta SOFTEV,x - dex - bpl :- + .segment "LOWCODE" -; Copy back the zero page stuff + ; ProDOS TechRefMan, chapter 6.2: + ; "Each installed routine must begin with a CLD instruction" +intrpt: cld - ldx #zpspace-1 -: lda zpsave,x - sta sp,x - dex - bpl :- + ; Call interruptors + jsr callirq -; ProDOS TechRefMan, chapter 5.2.1: -; "System programs should set the stack pointer to $FF at the warm-start -; entry point." + ; ProDOS TechRefMan, chapter 6.2: + ; "When the routine that can process the interrupt is called, it + ; should ... return (via an RTS) with the carry flag clear." + clc + rts - ldx #$FF - txs ; Re-init stack pointer +; ------------------------------------------------------------------------ -; Back to DOS + .code - jmp DOSWARM + ; Setup RESET vector +reset: stx SOFTEV + sta SOFTEV+1 + eor #$A5 + sta PWREDUP + rts ; ------------------------------------------------------------------------ -; Setup RESET vector -reset: stx SOFTEV - sta SOFTEV+1 - eor #$A5 - sta PWREDUP - rts - -; ------------------------------------------------------------------------ -; Data + .data -.data +zpsave: .res zpspace -zpsave: .res zpspace +rvsave: .res 3 -rvsave: .res 3 +params: .byte $02 ; Parameter count +intnum: .byte $00 ; Interrupt number + .addr intrpt ; Interrupt handler -- 2.39.5