;C02 stack module assembly language subroutines ;Requires external zero page variables ;STKLO, STKHI, DSTLO, DSTHI, SRCLO, SRCHI ;external variables ;STKSLO, STKSHI, STKELO, STKEHI, TEMP0, TEMP1, TEMP2 ;external routines ;MEMCPL, SETDST, SETSRC ;Implementation Notes: ;Stack starts at STKSLO,STKSHI and builds upward tp STKELO, STKEHI ;Each entry on the stack consists of the entry data followed ;by a single byte containing the length of the entry data ;stkbgn(&b) - Set Stack Start Address ;Args: X,Y = Address ;Sets: STKSLO, STKSHI = Stack Start Address ;Affects: Z, N STKBGN: STX STKSLO ;Save Stack Start LSB STY STKSHI ;Save Stack Start MSB RTS ;stkend(&b) - Set Stack End Address (+1) ;Args: X,Y = Address ;Sets: STKELO, STKEHI = Stack End Address ;Affects: Z, N STKEND: STX STKELO ;Save Stack End LSB STY STKEHI ;Save Stack End MSB RTS ;stkptr() - Get Stack Pointer ;Uses: STKLO,STKHI = Stack Pointer ;Affects: N,Z ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKPTR: LDX STKLO ;Load Stack Pointer LSB LDY STKHI ;Load Stack Pointer MSB RTS ;stkssp() - Save Stack Pointer ;Uses: STKLO,STKHI = Stack Pointer ;Sets: TEMP1.TEMP2 = Stack Pointer ;Affects: N,Z ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKSSP: JSR STKPTR ;Get Stack Pointer JMP SAVRXY ;Save in TEMP1, TEMP2 ;stksrc() - Set Source Pointer to Stack Pointer ;Uses: STKLO,STKHI = Stack Pointer ;Sets: SRCLO,SRCHI = Source Array Pointer ;Affects: X,N,Z ;Returns: Y = 0 STKSRC: JSR STKPTR ;Get Stack Pointer Address JMP SETSRC ;Set Source/ an/d Return ;stkdst() - Set Destination Pointer to Stack Pointer ;Uses: STKLO,STKHI = Stack Pointer ;Sets: DSTLO,DSTHI = Destination Array Pointer ;Affects: N,Z ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKDST: JSR STKPTR ;Get Stack Pointer Address JMP SETDST ;Set Destination and Return ;stkrst() - Reset Stack Pointer to Start Address ;Uses: STKSLO, STKSHI = Stack Start Address ;Sets: STKLO, STKHI = Stack Pointer ;Affects: Z, N ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKRST: LDX STKSLO ;Load X with Stack Start LSB LDY STKSHI ;Load X with Stack Start MSB JMP STKSET ;Store in Stack Pointer ;stkrsp() - Restore Stack Pointer ;Uses: TEMP1.TEMP2 = Stack Pointer ;Sets: STKLO,STKHI = Stack Pointer ;Affects: N,Z ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKRSP: JSR RESRXY ;Get TEMP1, TEMP2 ;and fall into STKSET ;stkset() - Set Stack Pointer Address ;Args: X,Y = Address ;Sets: STKLO, STKHI = Stack Pointer Address ;Affects: Z, N ;Returns: X = Stack Pointer LSB ; Y = Stack Pointer MSB STKSET: STX STKLO ;Store X in Stack Pointer LSB STY STKHI ;Store Y in Stack Pointer MSB RTS ;Exit Routine ;stkpsh(n, &m) - Push n Bytes of m onto Stack ;Args: A = Number of Bytes to Append ; Y,X = Address of Source Array ;Uses: STKELO, STKEHI = Stack End Address ;Sets: DSTLO, DSTHI = Pointer to Stack Entry ; SRCHI, SRCLO = Pointer to Source Array ; TEMP0 = Number of Bytes to Append ;Updates: STKLO, STKHI = Stack Pointer ;Returns: A=Number of Bytes Pushed ; 0 = Error: Stack Underflow STKPSH: JSR SETSRC ;Set Source Address STKPSA: STA TEMP0 ;Save Number of Bytes JSR STKDST ;Set Destination to Stack Pointer JSR STKALC ;Allocate Space on Stack JMP MEMCPL ;Copy Bytes and Return ;stkadd(n) - Add N Bytes to Stack Pointer ;Args: A=Number of Bytes to Allocate ;Updates: STKLO, STKHI = Stack Pointer ;Affects: A,C,N,Z STKADD: CLC STKADC: ADC STKLO ;Add to Stack Pointer LSB STA STKLO ;and Save LDA STKHI ;Add Carry ADC #0 ;to Stack Pointer MSB STA STKHI ;and Save RTS ;stkalc(n) - Allocate Space on Stack ;Args: A=Number of Bytes to Allocate ;Updates: STKLO, STKHI = Stack Pointer ;Affects: C,N,Z ;Returns: A = Number of Bytes Allocated ; 0 if Error: Pointer Overflow or Length 0 ; Y=0 STKALC: JSR STKSSP ;Save Stack Pointer LDA TEMP0 ;If No Bytes BEQ STKABT ; Abort Calling Routine JSR STKADD ;Add to Stack Pointer LDA STKEHI ;If Stack End MSB CMP STKHI ; < Stack Pointer MSB BCC STKRPA ; Abort Calling Routine BNE STKALX ;Else if Not Equal LDA STKELO ;and Stack End LSB CMP STKLO ; < Stack Pointer LSB BCC STKRPA ; Abort Calling Routine STKALX: LDA TEMP0 ;Get Number of Bytes from X Register LDY #0 ;Initialize Index STA (STKLO),Y ;Store after Allocated Area ;and fall inro STKINC ;stkinc(n) - Increment Stack Pointer ;Sets: STKLO, STKHI = Stack Pointer Address ;Affects: Y,Z,N STKINC: INC STKLO ;Increment LSB BNE STKINX ;If Zero INC STKHI ; Increment MSB STKINX: RTS ;stkcmp - Compare Stack Pointer to Stack Start Address ;Uses: STKLO, STKHI = Stack Pointer Address ; STKSLO, STKSHI = Stack Start Address ;Returns: C=1,Z=1 if Stack Pointer = Stack Start ; C=1,Z=0 if Stack Pointer > Stack Start ; C=0,Z=0 if Stack Pointer < Stack Start STKCMP: LDA STKHI ;Compare MSB CMP STKSHI BCC STKRTS ;If PointerStart Return C=1. Z=0 LDA STKLO ;If MSB Equal CMP STKSLO ;Compare LSB STKRTS: RTS ;stkdec(n) - Decrement Stack Pointer ;Sets: STKLO, STKHI = Stack Pointer Address ;Affects: X,Z,N STKDEC: LDX STKLO ;If LSB BNE STKDEL ; is Zero DEC STKHI ; Decrement MSB STKDEL: DEC STKLO ; Decrement LSB STKDER: RTS ;stksiz() - Get Stack Size in Bytes ;Uses: STKLO,STKHI = Stack Pointer ;Sets: STKSLO, STKSHI = Stack Start Address ;Returns: A = $FF if Stack Size is Non-Zero ; $00 if Stack is Empty ; Y,X = Stack Size (MSB, LSB) STKSIZ: LDA STKLO ;Subtract SEC ;Start Address LSB SBC STKSLO ;from Pointer LSB TAX ;and Copy to X LDA STKHI ;Subtract Start MSB SBC STKSHI ;from Pointer MSB TAY ;and Copy to Y BCC STKZRO ;Return FALSE if <=0 BNE STKTRU ;Return TRUE if MSB <> 0 TXA ;Else BEQ STKRTS ;Return FALSE if LSB = 0 STKTRU: LDA #$FF ;Else Return TRUE RTS ;stkdrp(&m) - Drop Top Entry from Stack ;Note: Aborts Calling Routine if Error ;Uses: STKSLO, STKSHI = Stack Start Address ;Sets: TEMP1, TEMP2 = Original Stack Pointer ;Updates: STKLO, STKHI = Stack Pointer ;Affects: Y,C,N,Z ;Returns: A=Number of Bytes in Entry ; 0=Error: Stack Underflow ; Y=0 STKDRP: JSR STKSSP ;Save Stack Pointer STKDRN: JSR STKCMP ;If Stack Pointer BCC STKRPA ; <= Stack Start BEQ STKRPA ; Return 0 JSR STKDEC ;Decrement Stack Pointer LDY #0 ;Initialize Index LDA (STKLO),Y ;Get Number of Bytes in Entry ;and fall into STKSUB ;stksub(n) - Reduce Stack Pointer by A STKSUB: STA TEMP0 ;Save Number in TEMP0 LDA STKLO SEC ;Subtract A from LSB SBC TEMP0 STA STKLO LDA STKHI ;Subtract 0 from LSB SBC #0 ;For Borrow STA STKHI JSR STKCMP ;If Stack Pointer < Start BCC STKRPA ; Restore Pointer and Return 0 STKSUE: LDA TEMP0 ;Retrieve Number of Bytes RTS STKRPA: JSR STKRSP ;Restore Stack Pointer STKABT: PLA ;Drop Return Address from Stack PLA ; Aborting Calling Routine STKZRO: LDA #0 ;Set A to 0 RTS ;stkpop(&m) - Pop Top Entry off Stack ;Args: Y,X = Address of Source Array ;Uses: STKSLO, STKSHI = Stack Start Address ;Updates: STKLO, STKHI = Stack Pointer ;Affects: C,N,Z ;Returns: A,Y = Number of Bytes in Entry ; 0 = Error: Stack Underflow STKPOP: JSR SETDST ;Set Destination Address JSR STKDRP ;Deallocate Stack Entry STKPOS: JSR STKSRC ;Set Source Address to Stack Pointer JMP MEMCPL ;Copy Bytes and Return