-
Notifications
You must be signed in to change notification settings - Fork 0
/
M16.SmartStacks
505 lines (499 loc) · 15.6 KB
/
M16.SmartStacks
1
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::;; 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