; IBMMAC - IBMSPL specific macros and definitions ; ; ; COPYRIGHT (c) 1979, 1980, 1981, 1982 ; DIGITAL EQUIPMENT CORPORATION ; ; This software is furnished under a license and may be used ; and copied only in accordance with the terms of such license ; and with the inclusion of the above copyright notice. This ; software or any other copies thereof may not be provided or ; otherwise made available to any other person. No title to ; and ownership of the software is hereby transferred. ; ; The information in this software is subject to change ; without notice and should not be construed as a commitment ; by DIGITAL EQUIPMENT CORPORATION. ; ; DIGITAL assumes no responsibility for the use or reliability ; of its software on equipment which is not supplied by ; DIGITAL. ; SUBTTL IBMMAC Version UNIVERSAL IBMMAC SEARCH GLXMAC IMCVER==1 ; Major version number IMCMIN==0 ; Minor version number IMCEDT==30 ; Edit number IMCWHO==0 ; Who edited last (0=DEC) %%.IMC=: SUBTTL Revision history COMMENT & Edit Date Who What 1-16 27-Apr-79 K. Reti Initial program development 17 4-May-79 KR Move NULL to IBMMAC, add REGS to it 20 15-May-79 KR Add NOTRACE support to NULL comment some early macros 21 15-May-79 KR make pattern matching macros more defensive about negative remaining counts (happens, but I don't know why yet) 22 19-May-79 KR Don't preserve as many AC's on patterns (try to lessen overhead 23 19-May-79 KR Undo edit 22 -- it didn't work 24 19-May-79 KR change version numbering symbol to not conflict with GLXMAC's MACEDT 25 4-Jun-79 KR Add symbol for structure block value (.IBMST) 26 15-Jun-79 KR Add version number cracking macro 27 1-Nov-79 SMJ Heave subroutine documention macros and version macros, replace version macros with something more efficient. 30 6-Oct-80 KR Add PEND macro to match end of character string. & SUBTTL DYNAMIC DATA STRUCTURE MACROS COMMENT & The following macros allow easy definition of indexed data structures; they are used in IBMSPL to define the format of the line blocks, the task blocks, the active task list entries, and the port list entries. The fields within a block are identified by a common prefix, e.g. T.ACS, T.ATE (from the task block). The body of the symbol is limited to three characters by the fact that the structure definition macros in GLXMAC generate their "structure" macro by appending a character to the end of the symbol (surely the worst way for creating ambiguity!) The definition of a block has two parts -- a start (DATAST macro) and one or more entries ($ and $. macros). The DATAST macro specifies the prefix to use on all entries that follow as well as an index register (which is presumed to point to the beginning of the block). The $ and $. macros generate symbols of the following forms: prfx.body which is the structure definition symbol (see DEFSTR or MSKSTR in GLXMAC); as such, its value is the mask of the position of this element within a word. prfx.body% which is the structure macro (again see DEFSTR or MSKSTR) and contains the positioning information (including the index register). Because the index register is included, LOAD and STORE (and other structure-invoking macros) should leave their position fields blank, e.g. LOAD S1,,T.FOO. prfx%body is a macro containing "merely offset(index reg)", so that instructions which do not have structure manipulating equivalents can be coded without reference to the index register, e.g. IMUL S1,T%FOO. prfx$body is a symbol containing just the word offset of this particular entry based on the index register; this is useful if you are using another register to do the indexing; it can be used with the prfx.body mask in structure references the hard way (i.e. by hand) for example LOAD S1,T$FOO(P1),QQ where QQ was previously equated to T.FOO. [The more obvious construct LOAD S1,T$FOO(P1),T.FOO doesn't work because, since T.FOO% exists, the structure macro appends the supplied position info (T$FOO(P1)) to the stored position info (T$FOO(R1)) with a "+" to achieve an undesired result.] The $ and $. macros are identical except that $. entries merely redefine previous $ entries; thus a fullword can be given a name, and then the two halfwords comprising it can likewise be named. Unfortunately, only one level of subsetting exists at the moment. & DEFINE DATAST(PRE,IDX)< DEFINE $ (NAM,SIZ,CNT,LVL) < $$ PRE,NAM,\..WD,IDX,\..BT,SIZ,CNT,LVL >;end DEFINE $ DEFINE $$. (NAM,SIZ,OB,OW,BT,WD,CNT) < $$$. PRE,NAM,OB,OW,BT,WD,IDX,SIZ,CNT >;end DEFINE $$. DEFINE $$$$ (NAM,BIT,SIZ,WRD) < $$$$$ PRE,NAM,BIT,SIZ,IDX,WRD >;end DEFINE $$$$ ..WD==0 ..BT==-1 >;end DEFINE DATAST DEFINE $$ (P,N,W,I,B,S,C,L) < ..TM==0 IFB ,< IFB ,< IFGE ..BT,< ..WD==..WD+1 ..BT==-1 >;end IFN ..BT ..TM==1 >;end IFB N >;end IFB S IFE ..TM,< ..CT==1 IFNB ,<..CT==C> ..SZ=^D36 IFNB ,<..SZ==S> ..OB==..BT ..OW==..WD REPEAT ..CT,< ..BT=..BT+..SZ IFG <..BT-^D35>,< ..WD=..WD+1 ..BT=..SZ-1 >;end IFG <..BT-^D35> IFNB ,< IFE ..TM,< $$$$ N,\..BT,\..SZ,\..WD ..RX==10 RADIX ^D10 DEFSTR (P'.'N,P'$'N'('I),\..BT,\..SZ) RADIX ..RX >;end IFE ..TM ..TM==..TM+1 >;End IFNB N IFNB ,<$$$ L,\..OB,\..OW,\..BT,\..WD> >;End Repeat ..CT >;End IFE ..TM >;End DEFINE $$ DEFINE $$$ (L,OB,OW,BT,WD) < DEFINE $. (NAM,SIZ,CNT) < $$. NAM,SIZ,OB,OW,BT,WD,CNT >;end DEFINE $. ..BT1==OB ..WD1==OW >;end DEFINE $$$ DEFINE $$$. (P,N,OB,OW,B,W,I,S,C) < ..TM1==0 IFB ,< IFB ,< ..WD1==..WD1+1 IFG <..WD1-W>, ..BT1==0 IFE <..WD1-W>,< IFG <..BT1-B>, >;end IFE <..WD1-W> ..TM1==1 >;end IFB, >;end IFB, IFE ..TM1,< ..CT1==1 ..SZ1==^D36 IFNB ,<..CT1==C> IFNB ,<..SZ1==S> REPEAT ..CT1,< ..BT1==..BT1+..SZ1 IFG <..BT1-^D35>,< ..WD1==..WD1+1 IFG <..WD1-W>, ..BT1==..SZ1-1 IFE <..WD1-W>,< IFG <..BT1-B>, >;end IFE <..WD1-W> >;end IFG <..BT1-^D35> IFNB ,< IFE ..TM1,< $$$$ N,\..BT1,\..SZ1,\..WD1 ..RX==10 RADIX ^D10 DEFSTR (P'.'N,P'$'N'('I),\..BT1,\..SZ1) RADIX ..RX >;end IFE ..TM1 ..TM1==..TM1+1 >;end IFNB >;end REPEAT ..CT1 >;end IFE ..TM1 >;end DEFINE $$$. DEFINE $$$$$ (P,N,B,S,I,W) < P'$'N=='W DEFINE P'%'N >;end DEFINE $$$$$ SUBTTL STRUCTURE SKIP MACROS DEFINE .SKP (CND,AC,Y,STR,%NO) < CAIA JRST %NO LOAD .SAC,Y,STR IFNB ,< SKIP'CND AC,.SAC >;end IFNB IFB ,< SKIP'CND .SAC >;end IFB %NO: >;end DEFINE .SKP DEFINE .SKPGN (CND) < IRP CND,< DEFINE SKP'CND (AC,Y,STR) < .SKP (CND,AC,Y,STR) >;end DEFINE SKP'CND >;end IRP CND >;end DEFINE .SKPGN .SKPGN SUBTTL Miscellaneous Macros ; Macro to make a cross reference entry DEFINE REF(ARG) < IRP ARG,< ..RF==ARG >;end IRP ARG PURGE ..RF >;end DEFINE REF COMMENT & In the following macros T1 generally holds the displacement (in bytes) within the string of where to start matching; T2 holds number of characters left in string (from T1); T3 holds, when calling a pattern, the number of characters that the pattern must match (minimum) to succeed and P4 holds the address of the start of the string (off which T1 is the displacement). The macro PAT defines a "pattern", which is really a subroutine which returns true or false (and as a side-effect stores some values of what matched what) based on whether the pattern matches the string pointed to by T2 and P4. Its single argument is a list of pattern "elements". The first element must be either PBEG or PFLT, for an anchored or non-anchored (floating) pattern match, respectively. Successive elements can be any combination of the following: PEX This is an element that causes an exact match of a pattern PARB This is an element that causes any number of occurences of a pattern to match PSPN This is an element which matches as many characters as possible from a string (in any order). Note this does not work on patterns at the moment POR This is an element which matches any of a list of patterns. There are also several macros to make primitive patterns which can be the arguments to some of the "pattern elements" listed above: PCHR Makes a pattern that matches 1 character (the argument is the character) PSTR Makes a pattern that matches a character string (the argument is the address of a word whose LH=length of string, and RH=address of string) & DEFINE PAT (LIST) < ZZZ==ZZZ+1 ZZ==0 $SAVE ;;save registers we need PUSH P,T1 ;;save start position for success MOVE P-1,P ;;save current position of stack PATGO INIT ;;go to the first pattern POP P,T1 ;;clean up stack JRST .RETF ;;if we get here, we have failed IRP LIST < ;;generate all the elements PAT. LIST >;;end IRP LIST PATTG ;;generate tag for last PATGO MOVE P,P-1 ;;restore stack MOVE T3,T1 ;;get current position POP P,T1 ;;restore original position SUB T3,T1 ;;subtract start to get chars matched ADD T2,T3 ;;fix count remaining also JRST .RETT ;;and indicate success >;end DEFINE PAT DEFINE PATGO (SPEC) < ;;macro to go to next pattern element PATGO. \ZZ,\ZZZ,SPEC ;;generate call to ..Pn >;end DEFINE PATGO DEFINE PATGO. (PNUM,NUM,SPEC) < ;;macro to PUSHJ to next pattern element IFB ,< PUSHJ P,.PSTR2 ;;update pointers >;END IFB IFNB ,< PUSHJ P,.PSTR3 >;END IFNB PUSHJ P,%'PNUM'P'NUM ;;call next element >;end DEFINE PATGO. DEFINE PAT. (ENTRY) < ;;macro to build body of pattern element PAT.. ENTRY >;end DEFINE PAT. DEFINE PAT.. (TYPE,ARG) < ;;macro to generate call to element PATTG TYPE ARG >;end PAT. DEFINE PATTG < ;;defines label of current element and increments counter (so PATGO will go to next) PATTG. \ZZ,\ZZZ ZZ==ZZ+1 >;end DEFINE PATTG DEFINE PATTG. (PNUM,NUM) < ;;actually build the tag %'PNUM'P'NUM: >;end DEFINE PATTG. DEFINE PBEG (A) < ;;Anchored match beginning element PATGO ;;go to first pattern $RET ;;if we get here, we're not going to match >;end PBEG DEFINE PFLT (A) < ;;Unanchored match beginning element PATGO ;;go to first pattern QQ==. ;;save address right after last PUSHJ to next pattern SOS T2 ;;if we fail, decrement count remaining JUMPLE T2,.RETF ;;if we are all done, return failure AOS T1 ;;increment starting position IFDEF FTDEBUG < SKIPG T1 ;;make sure position is positive HALT ;;error if not >;end IFDEF FTDEBUG JRST QQ-1 ;;else try again at next character position >;end DEFINE PFLT DEFINE PEX (A,VAL) < ;;Exact match of pattern element $SAVE ;;save registers we need MOVE P3,T3 ;;save must match count SETZ T3, ;;clear must match for this call PUSHJ P,A ;;call pattern JUMPF .RET ;;if it fails, propagate failure CAMGE T3,P3 ;;did we match enough? $RET ;;no, propagate error PVALSV VAL ;;yes, store value info if necessary ; ADD T1,T3 ;;otherwise bump starting point ; SUB T2,T3 ;;and decrement count remaining PATGO ;;and go to next element $RET ;;propagate failure >;end DEFINE PEX DEFINE PSTR (A) < ;;make a pattern to match a string $SAVE ;;save registers MOVE P2,A ;;copy address of string pointer HLRZ P3,P2 ;;get length into P3 CAMLE T3,P3 ;;is must match greater than length? JRST .RETF ;;yes, too bad MOVE T4,P3 ;;copy length again HRLI P2,440700 ;;make P2 a byte pointer to string PUSHJ P,.PSTR0 ;;setup byte pointer to test string ILDB S1,P1 ;;get character from test string ILDB S2,P2 ;;and one from constant string CAME S1,S2 ;;skip if they are equal JRST .RETF ;;failure if not SOJG P3,.-4 ;;loop over all characters of constant string MOVE T3,T4 ;;copy how many we matched JRST .RETT ;;and return success >;end DEFINE PSTR DEFINE PCHR (A) < ;;make pattern to match a character CAILE T3,1 ;;do we have to match more than 1 JRST .RETF ;;yes, too bad $SAVE ;;save registers PUSHJ P,.PSTR0 ;;set up byte pointer to source ILDB S1,P1 ;;get current character CAIE S1,"A" ;;is it ours? JRST .RETF ;;no, fail MOVEI T3,1 ;;yes, we matched 1 JRST .RETT ;;return success >;end DEFINE PCHR DEFINE PARB (A,B<0>,C<-1>,VAL) < ;;arbitrary number of occurences of a pattern $SAVE ;;save registers MOVEI T3,B ;;get minimum to match QQ==0 IFNB , JUMPE T3,.+3+QQ ;;if we don't have to, don't try PUSHJ P,A ;;try to match some JUMPF .RET ;;propagate failure if cannot PVALSV VAL ;;store value if necessary ; ADD T1,T3 ;;new start ; SUB T2,T3 ;; and count PUSH P,T1 PUSH P,T2 PUSH P,T3 PATGO POP P,T3 POP P,T2 POP P,T1 AOS T3 QQ==0 IFG C,< QQ==2 CAILE T3,C $RET> CAMLE T3,T2 $RET JRST .-<15+QQ> >;end DEFINE PARB DEFINE PSPN (A,B<-1>,VAL) < ;;maximum number of characters selected from set CAMLE T3,T2 ;;must we match more than left in string? JRST .RETF ;;yes, fail $SAVE ;;save some registers PUSHJ P,.PSTR0 ;;set up input byte pointer SETZ T4, ;;initialize counter MOVE P2,A ;;get address of string and length HLRZ P3,P2 ;;copy length to P3 HRLI P2,440700 ;;make into byte pointer PUSH P,P3 ;;save count PUSH P,P2 ;;save byte pointer QQ==0 ;;how much the next two instructions add ;; if not included IFG B,< CAIL T4,B ;;have we reached upper limit? JRST .+10 ;;yes, don't add any more QQ==2> ;;how much these instructions add if included ILDB S1,P1 ;;get byte from string MOVE P2,0(P) ;;get initial byte pointer for span characters MOVE P3,-1(P) ;;get count of span characters ILDB S2,P2 ;;get a span character CAMN S1,S2 ;;see if this character fits AOJA T4,.-<5+QQ> ;;yes, increment count and get another string character SOJG P3,.-3 ;;no, get another span character POP P,S1 POP P,S1 SKIPE T4 ;;if none, fail CAMGE T4,T3 ;;was number we got less than desired? JRST .RETF ;;yes, fail MOVE T3,T4 ;;no, get number we matched PVALSV VAL ;;save value matched ; ADD T1,T3 ;;update start by length ; SUB T2,T3 ;;calculate new length PATGO ;;go to next element JRST .RET ;;if it fails, propagate failure >;end DEFINE PSPN DEFINE POR (A,B,VAL) < ;;match any of a set of patterns $SAVE ;;save some registers ?? S1 only to test IFNB , ;;if index given, set to -1 MOVE P3,T3 ;;copy must match DMOVE P1,T1 ;; as well as start and length IRP A,< DMOVE T1,P1 ;;for each pattern, start at beginning MOVE T3,P3 ;; with appropriate length PUSHJ P,A ;;test that pattern IFNB , ;;keep track of index QQ==0 ;;assume no extra code IFNB , ;;if extra code included, count it JUMPF .+3+QQ ;;if it failed, go to next pattern PVALSV VAL ;;save value that matched ; ADD T1,T3 ;;update start ; SUB T2,T3 ;; and length remaining PATGO ;;go to next pattern >;end IRP A JRST .RETF ;;if we get here, fail >;end DEFINE POR DEFINE PEND < JUMPN T2,.RETF PATGO >;end DEFINE PEND DEFINE PVALSV (ARG) < ;;macro to save matched string address PVALSZ==2 ;;words of code generated by this macro IFNB ,< HRLM T3,ARG ;;save length in LH HRRM T1,ARG ;; and address in RH >;end IFNB >;end DEFINE PVALSV SUBTTL . REGS -- standard register names macro DEFINE REGS < DEFINE R(N) < ;;Macro to generate R0,R1,... R'N==N >;end DEFINE R ..==0 ;Counter REPEAT 20,< R \.. ;generate register name ..==..+1 >;end REPEAT 20 >;end DEFINE REGS SUBTTL . Global Symbols .IBMST==400000 ;code to identify structure block in ; queue info file END