;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; ; M16.SmartStacks ; ; Stack frame macros ; ; ; Written by Bryan Pietrzak, derived from macros by Lou Infeld ; Copyright 1991-92, Zak Enterprises ; All Rights Reserved ; ; ; Stack macros: ; ; alias defines an equate to the current PC ; BeginStack used after the stack frame has been defined ; BegParms indicates that passed parameters follows ; DefineStack first macro used in defining a stack frame ; DSect begin defining local equates ; EndLocals indicates that there are no more local variables ; EndParms indicates that there are no more passed parameters ; EndRecord define the size of a record to a label ; EndStack used before returing from the routine to clean up stack ; FixStack fixes dummy PC for return address, direct page & databank ; GlobalDSect begin defining global equates ; Record begin defining global equates ; ; byte defines a equate representing a byte at current dummyPC ; word defines a equate representing a word at current dummyPC ; int defines a equate representing an integer at current dummyPC ; longword defines a equate representing a long at current dummyPC ; real defines a equate representing a real at current dummyPC ; double defines a equate representing a double at current dummyPC ; block defines a equate representing n bytes at current dummyPC ; ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; ; Revision History: ; ; 12/4/2004 - kws: long changed to longword. ; 12/4/2004 - kws: don't sbc #sizeLocals if 0. ; ; 7/1/92 - added record and endrecord macros ; - removed previous record macro (alias took over for it) ; 5/14/92 - added alias macros ; 3/25/92 - added int, real, double and record macros ; 1/2/92 - fixed EndLocals and EndParms to be backwards compatible with ; code that already has the labels defined ; 7/25/91 - user no longer has to specify labels in endParms and endLocals ; - no longer dependent on other macros (eg, tkb) ; 7/10/91 - added GlobalDSect ; - modified equate macros to work with either equ or gequ ; - removed DSectSize since I never used it ; - modified all macros to check prior definition of globals ; 4/14/91 - added FixStack macro ; - added support for "short" subroutines (via jsr) ; 3/28/91 - initial creation ; - modified equate macros to be work without labels ; - added BeginStack and EndStack ; - added proc macro and debugSymbols usage for NiftyList! ; ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ;............................................................... ; ; alias ; ; This macro creates a duplicate label for the current direct ; page variable. Aliases must come *before* the actual label ; definition: ; ; DirectPage GlobalDSect 0 ; userID alias ; memoryID word ;............................................................... macro &lab alias aif &gequ,.global &lab equ &dummyPC mexit .global &lab gequ &dummyPC mend ;............................................................... ; ; &lab BeginStack ; ; Sets up everything for entry into your subroutine. ; ; This macro will only generate the code necessary to support your ; stack frame. If you are not using local storage or passing ; parameters (or both) it will generate less code. ; ; The macro saves the current DP and PBR. These are restored ; when the EndStack macro is used. ; ; - &lab is optional. ;............................................................... macro &lab BeginStack &lab anop phd ; save the direct page aif "&JSn"="jsr",.ifLocals phb ; save the bank phk ; set PBR accordingly plb aif &dummyPC>7,.begin mexit .ifLocals aif &dummyPC=5,.exit .begin tsc aif t:sizeLocals<>"G",.NoLocals aif sizeLocals=0,.NoLocals aif sizeLocals=1,.dec1 aif sizeLocals=2,.dec2 aif sizeLocals=3,.dec3 aif sizeLocals=4,.dec4 ago .sbc .dec4 dec a .dec3 dec a .dec2 dec a .dec1 dec a tcs ago .NoLocals .sbc sec sbc #sizeLocals ; subtract room for local storage tcs ; set new SP .NoLocals tcd ; map Direct Page onto Stack .exit mend ;............................................................... ; ; BegParms ; ; used it indicate following equates represent the passed paramters. ;............................................................... macro BegParms aif c:&begParmsPC>0,.skip gbla &begParmsPC .skip &begParmsPC seta &dummyPC mend ;............................................................... ; ; DefineStack type ; ; This macro sets up a dummy program counter starting at 1 ; and is used in conjunction with endlocals, FixStack, begParms, ; endParms, BeginStack and EndStack to define a stack frame. ; ; For routines that are called via a jsr, you should specify ; either 'jsr' or 'short' as the type, for long routines, this ; can be left blank, or specified as long or jsl. ;............................................................... macro DefineStack &howCalled aif c:&JSn>0,.skip0 gblc &JSn .skip0 &JSn setc "jsl" aif c:&howCalled=0,.begin aif "&howCalled"="jsr",.jsr aif "&howCalled"="short",.jsr aif "&howCalled"<>"JSR",.begin .jsr &JSn setc "jsr" .begin aif c:&dummyPC>0,.skip1 gbla &dummyPC .skip1 &dummyPC seta 1 aif c:&gequ>0,.skip2 gblb &gequ .skip2 &gequ setb 0 mend ;............................................................... ; ; DSect offset ; ; This macro will allow you to define local equates starting with ; whatever offset you specify (or $00 if none). To actually ; create the local equates, use the 'byte', 'word', 'long', and ; 'block' macros. ;............................................................... macro DSect &offset aif c:&gequ>0,.skip1 gblb &gequ .skip1 &gequ setb 0 aif c:&dummyPC>0,.skip2 gbla &dummyPC .skip2 aif c:&offset<>0,.doIt &dummyPC seta 0 mexit .doIt &dummyPC seta &offset mend ;............................................................... ; ; EndDSect ; ; This macro equates the size of the direct page section ; definition to a label. ; ;............................................................... macro &lab endDSect aif &gequ,.global &lab equ &dummyPC mexit .global &lab gequ &dummyPC mend ;............................................................... ; ; EndLocals ; ; This macro indicates that there are no more local variables to ; be declared. ;............................................................... macro &lab endLocals aif l:&lab<>0,.continue &lab setc sizeLocals .continue &lab equ &dummyPC-1 mend ;............................................................... ; ; EndParms ; ; This macro indicates that the definition of passed ; parameters is complete. Any definitions remaining after ; this macro indicate that the parameter is to be left on ; the stack by EndStack. ; ;............................................................... macro &lab endParms aif l:&lab<>0,.continue &lab setc sizeParms .continue &lab equ &dummyPC-&begParmsPC mend ;............................................................... ; ; endrecord ; ; This macro equates the size of a record to a label ; ;............................................................... macro &lab endrecord aif &gequ,.global &lab equ &dummyPC mexit .global &lab gequ &dummyPC mend ;.................................................Zak........... ; ; &lab EndStack ; ; This macro restores the PBR and DP upon entry to the routine ; and cleans up the stack according to the stack frame macros. ; ; - &lab is optional. ;............................................................... macro &lab EndStack &lab anop aif t:sizeLocals<>"G",.NoLocals aif sizeLocals=0,.NoLocals tsc clc adc #sizeLocals tcs .NoLocals aif "&JSn"="jsr",.restoreDP plb .restoreDP pld aif t:sizeParms<>"G",.NoParms aif "&JSn"="jsr",.continue lda 2,s sta 2+sizeParms,s .continue lda 1,s sta 1+sizeParms,s ; aif t:sizeLocals="G",.CarryCleared clc ;.CarryCleared tsc adc #sizeParms tcs .NoParms mend ;............................................................... ; ; FixStack ; ; This macro must be used right before the definition of passed ; parameters to make up for the fact that the return address, ; databank (in long routines only), and directpage are on the ; stack. The dummy program counter must be appropiately ; incremented. ;............................................................... macro FixStack &dummyPC seta &dummyPC+4 aif "&JSn"="jsr",.exit &dummyPC seta &dummyPC+2 .exit mend ;............................................................... ; ; GlobalDSect offset ; ; This macro will allow you to define global equates starting with ; whatever offset you specify (or $00 if none). To actually ; create the global equates, use the 'byte', 'word', 'long', and ; 'block' macros. ;............................................................... macro GlobalDSect &offset aif c:&gequ>0,.skip1 gblb &gequ .skip1 &gequ setb 1 aif c:&dummyPC>0,.skip2 gbla &dummyPC .skip2 aif c:&offset<>0,.doIt &dummyPC seta 0 mexit .doIt &dummyPC seta &offset mend ;............................................................... ; ; Record offset ; ; This macro will allow you to define global equates starting with ; whatever offset you specify (or $00 if none). To actually ; create the global equates, use the 'byte', 'word', 'long', and ; 'block' macros. ;............................................................... macro Record &offset aif c:&gequ>0,.skip1 gblb &gequ .skip1 &gequ setb 1 aif c:&dummyPC>0,.skip2 gbla &dummyPC .skip2 aif c:&offset<>0,.doIt &dummyPC seta 0 mexit .doIt &dummyPC seta &offset mend ;............................................................... ; ; &lab byte ; ; equate the given label with the current dummyPC (defined by ; DSect, GlobalDSect or DefineStack), and then increments the ; dummyPC by one byte. ; ; - &lab is optional ;............................................................... macro &lab byte aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+1 mend ;............................................................... ; ; &lab word ; &lab int ; ; equate the given label with the current dummyPC (defined by ; DSect, GlobalDSect or DefineStack), and then increments the ; dummyPC by two bytes. ; ; - &lab is optional. ;............................................................... macro &lab word aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+2 mend macro &lab int aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+2 mend ;............................................................... ; ; &lab longword ; &lab real ; ; equate the given label with the current dummyPC (defined by ; DSect, GlobalDSect or DefineStack), and then increments the ; dummyPC by four bytes. ; - &lab is optional. ;............................................................... macro &lab longword aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+4 mend macro &lab real aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+4 mend ;............................................................... ; ; &lab double ; ; equate the given label with the current dummyPC (defined by ; DSect, GlobalDSect or DefineStack), and then increments the ; dummyPC by eight bytes. ; - &lab is optional. ;............................................................... macro &lab double aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+8 mend ;............................................................... ; ; &lab block byteCount ; ; equate the given label with the current dummyPC (defined by ; DSect, GlobalDSect or DefineStack), and then increments the ; dummyPC by the appropiate number of bytes bytes. ; ; - &lab is optional. ;............................................................... macro &lab block &byteCount aif l:&lab=0,.increment aif &gequ,.global &lab equ &dummyPC ago .increment .global &lab gequ &dummyPC .increment &dummyPC seta &dummyPC+&byteCount mend