MACSYM.DOC -- Version 5 October 1981 COPYRIGHT (C) 1976,1978,1982 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. 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. MACSYM.DOC Page 2 MACSYM.DOC -- Version 5 October 1981 1.0 SUMMARY MACSYM is a file containing macro definitions and object-time support code which implement a number of useful machine-language coding facilities used in the monitor and system program sources. These facilities include variable naming and storage conventions and data structure techniques similar in principle to capabilities found in some implementation languages. MACSYM is not an executable program. It may be assembled by and used with MACRO version 53A. MACSYM requires MONSYM.UNV for assembly and use. 2.0 EXTERNAL CHANGES A new set of structured programming macros has been added to MACSYM. A memo describing their use has been appended to this DOC file. A set of macros providing extended addressing support, particularly with byte pointers, has been added. Their use is documented in MACSYM. 3.0 KNOWN BUGS AND DEFICIENCES There are no known bugs or deficiencies in MACSYM. 4.0 INSTALLATION INSTRUCTIONS 4.1 Files Needed for MACSYM Use MACSYM.UNV - Universal file for MACRO assemblies. MACREL.REL - Object-time support routines. MACSYM.DOC Page 3 4.2 Instructions for Loading and Installing MACSYM Mount the tape labeled Installation Tape on MTA0: and type the following commands: SKIP MTA0:5 FILES R DUMPER TAPE MTA0: REWIND DENSITY 1600-BPI SKIP 1 RESTORE <*>MACSYM.* (TO) SYS:*.*.-1,<*>MACREL.* (TO) <SUBSYS>*.*.-1 REWIND 4.3 Files Needed to Build MACSYM MACSYM is built from the following files: MACSYM.MAC REL1.MAC In addition, the following file must be on SYS: MONSYM.UNV 4.4 Instructions for Building MACSYM Mount the tape labeled Distribution Tape on MTA0: and type the following commands: R DUMPER TAPE MTA0: REWIND DENSITY 1600-BPI SKIP 1 RESTORE <*>*.*.* (TO) <self>*.*.* REWIND ^C SUBMIT MACSYM.CTL/TIME/UNIQ:0/REST Once the batch job has successfully completed, the files MACSYM.UNV and MACREL.REL should be copied into SYS:. 4.5 Special Considerations MACSYM is not an executable program. Hence, there is no .EXE file of it ever created. MACSYM.DOC Page 4 5.0 INTERNAL CHANGES FLDDB. and FLDBK. have been changed to allow "" in help messages. 6.0 SUGGESTIONS None. [End of MACSYM.DOC] [APPENDIX A is appended as an integral part of MACSYM] APPENDIX A 1.0 STRUCTURED PROGRAMMING MACROS 1.1 BLISS-style Subroutine Calls MACSYM now has macros which implement Bliss-style subroutine calls and which are otherwise compatible with the usual TOPS-20 conventions. "Bliss-style" means that they push their arguments onto the stack and then do a PUSHJ. They are not exactly compatible with actual BLISS conventions in order to be fully compatible with TOPS-20 conventions. The general format is this: At routine entry, you say: NAME: BLSUB. <sym,sym,...,sym> Each symbol becomes defined as -n(P) much like symbols defined with STKVAR. At runtime, they will address the stack locations setup by the caller. A frame pointer is setup in .FP (P6) the same as with TRVAR. Hence, STKVAR, SAVEAC and local calls can be used within a BLSUB., but TRVAR cannot. To call a routine defined as a BLSUB., you say: BLCAL. NAME,<arg,arg,...,arg> where the number of args must be the same as expected by the subroutine. Each arg can be one of several things: 1. a normal effective address optionally including indexing and indirection; 2. a structure reference; 3. an immediate address written as <.,adr>. This address is computed with an XMOVEI, so section information will be determined and retained at call time. The difference between 1 and 2 isn't always syntactically obvious, but the macro "figures it out". Be careful to use brackets if the structure reference contains a comma however. E.g., if you would say LOAD T1,FOO,(T2) the call should look like BLCAL. ZOT,<<FOO,(T2)>> Page 2 Here's a complete example: BLCAL. ZOT,<FOO,@FIE(X),<.,FUM>,<AAA,(T2)>> This call has 4 args: 1. The contents of FOO as would be loaded by MOVE AC,FOO. 2. The contents of @FIE(X) as would be loaded by MOVE AC,@FIE(X) 3. The address FUM as would be loaded by XMOVEI AC,FUM 4. The contents of a defined structure as loaded by LOAD AC,AAA,(T2) Skip returns can be used as usual. No ac's are automatically preserved by BLSUB.. Hence, you must save any preserved ac's that you use in the subroutine. Seems like a good idea to preserve the T's as well. The benefit of these kinds of subroutines is that the calls are a lot cleaner. You avoid a lot of juggling of ac's, particularly where several arguments are involved. Also, it is obvious exactly what is being passed to the subroutine, and the reader doesn't have to guess what ac's are needed or merely incidental. So far, this has been used in only one place; as an alternate way of calling DTEQ in TTYSRV. The original DTEQ takes arguments in 5 (count 'em 5) ac's, and it's more like 8 arguments in total since some of the ac's have independent LH and RH. Each call in the original is typically preceded by a hideous mess of Hxxx, EXCH, MOVE, etc. The calls to the new routine (TTDTEQ) are always a neat single line. BLSUB. can also takes a second list of symbols which will be defined as local dynamic variables ala TRVAR. E.g., BLSUB. <AA,BB,CC>,<TT,UU,VV> This means that AA, BB, and CC are arguments supplied by the caller, and TT, UU, and VV are local stack variables. 1.2 Block-structured Macros General format: The beginning of a block is identified by one of the IFx macros. The end of the block is identified by ENDIF. ELSE. may be used exactly once within the block to indicate alternative code. The 'and' macros (ANx.) may be used between the beginning of the block and the ELSE. Page 3 1.2.1 Skip Conditionals (Single Condition) - IFNSK., IFSKP. - "IF NO SKIP", "IF SKIP" These macros cause the following code to be conditionally executed depending on whether the preceding instruction(s) skipped or not. The following code is ended with ENDIF., and ELSE. is optional within the range. Note: both of these result in the same or fewer instructions than the use of literals to handle the same cases. Also, since the code is not in literals, the binary appears in the listing, and the code is easier to follow with DDT. If the preceding skip can be written in either sense, it is better to use IFSKP. because one fewer instructions will be generated. IFSKP. and IFNSK. have an alternate form where the consequence code is given as a macro argument. In the normal case, no macro argument is given. If this form is used, the consequence code is the first argument. A second argument, the alternative code, may be given only with IFNSK. "IF NO SKIP" If the instruction(s) preceding the macro does not skip, the 'consequence code' will be executed; otherwise (i.e. if the instruction skips) the 'alternative code' will be executed. "IF SKIP" If the instruction(s) preceding the macro skips, the 'consequence code' will be executed; otherwise (i.e. if the instruction does not skip) the 'alternative code' will be executed. Example: CALL TSOBEX ;OUTBUF EMPTY? IFNSK. MOVEI T1,TTOBET ;NO, RETURN TEST TO WAIT FOR IT TXO T1,1B0 RET ENDIF. ;Example: shows both THEN and ELSE cases. TQNN <TTSAL,TTHPO>,(T2) ;SPECIAL OUTPUT GOING? IFSKP. TDCALL D,<<FE,TTXON1>>> ;YES, RESTART THE LINE ELSE. TDCALL D,<<FE,TTCHI3>> ;NO, STOP THE LINE ENDIF. RET Page 4 ;Same as the preceding but using alternate form. TQNN <TTSAL,TTHPO>,(T2) ;SPECIAL OUTPUT GOING? IFNSK. < TDCALL D,<<FE,TTCHI3>> ;NO, STOP THE LINE **the THEN case** >,< TDCALL D,<<FE,TTXON1>>> ;YES, RESTART THE LINE **the ELSE case** RET ;Example: shows both explicit END and bracketted cases TTDOBE::CALL SKCOE ;SKIP IF CTRL-O INTERRUPT ENABLED SKIPN CTRLOF ;NEW STYLE? IFSKP. MOVEI T1,TTOMRK ;YES, JUST PUT MARKER IN OUTPUT STREAM CALL TCOUM RETSKP ENDIF. CALL TSOBED ;SEE IF OUTPUT IN PIPE IFSKP. <RETSKP> ;NO, RETURN OK ; .. ;Example: shows nested useage TTSOBE::CALL SKCOE ;SKIP IF CTRL-O INTERRUPT ENABLED SKIPN CTRLOF ;NEW STYLE? IFSKP. CALL OWNTTY ;JOB OWN TTY? IFSKP. MOVEI T1,TTOMRK ;YES, JUST PUT MARKER IN STREAM CALL TCOUM SETZ T1, RETSKP ;SAY OUTBUF EMPTY ENDIF. ENDIF. JN TTOTP,(T2),R ;RETURN NOSKIP IF OUTPUT IS STILL ACTIVE ; .. Page 5 ;More complex example TQNE TTNXO,(T2) ;END-OF-PAGE MODE? CAME T1,T3 ;AND UNPAUSE ON PAGE CHARACTER? IFSKP. TQNN TTSFG,(T2) ;ALREADY PAUSING? IFSKP. CALL TTXONP ;YES, RESTART OUTPUT RETSKP ;RETURN NOW, LOSE CHARACTER ENDIF. LOAD T3,TTPPC,(T2) ;NOT PAUSING NOW, CAME T1,T3 ;THIS THE PAUSE CHARACTER TOO? RETSKP ;NO, JUST LOSE THE CHARACTER CALL TTXOFP ;YES, MAYBE PAUSE NOW IFSKP. <RETSKP> ;RETURN NOW IF PAUSED ENDIF. LOAD T3,TTPPC,(T2) ;GET PAGE PAUSE CHARACTER ; .. 1.2.2 Skip Conditionals (Multiple Conditions) - Multiple conditions can be specified for IFSKP. and IFNSK. with the macros ANSKP. and ANNSK.. (Read "and skip", "and noskip".) Both "and" macros may be used with either IFSKP. and IFNSK. The general form is: first test condition IFSKP./IFNSK. second test condition ANSKP./ANNSK. third test condition ANSKP./ANNSK. .. consequence code ELSE. .. ENDIF. That is, you get to "consequence" only if first test AND second test AND third test are successful. Note that any code can be present as the second and subsequent test conditions; each test will be executed until one is reached which does not satisfy its following macro, whereupon control will branch to the ELSE. or ENDIF. as appropriate. Example: TXNE F,FLAG1 IFSKP. MOVE T1,FLAGS2 TXNN T1,AF ANSKP. SETZM FOO ;THIS ONLY IF FLAG1=0 AND AF=1 ENDIF. Page 6 1.2.3 Branch Conditionals - The following may be used in cases where a jump instruction is available to test the condition. IFx. ac consequence code ENDIF. where 'x' is one of: L, LE, E, N, GE, G, and 'ac' is the ac to be tested. Example: IFG. T1 MOVE T2,FOO MOVEM T2, FIE ENDIF. This reads: "If T1 is greater than 0, move FOO to FIE". Four additional cases of IFx. are supported. They are: IFXE. and IFXN. which take AC and MASK (ala TXNE/TXNN), and IFQE. and IFQN. which take a structure identifier (ala TQNE/TQNN). Example: IFQE. FOOFG,(X) MOVE T2,AA MOVEM T2,BB ENDIF. IFXN. T2,GS%EOF MOVE T1,JFN CLOSF ERJMP LOSE ENDIF. ANDx. macros are available for all the same cases as IFx., that is, ANDE., ANDN., ANDG., ANDGE., ANDLE., ANDL., ANDXE., ANDXN., ANDQE., ANDQN.. They can be intermixed arbitrarily in conditionals started by any IFx. Example: IFN. T1 ANDQN. FLG,(XX) CALL MUMBLE ANSKP. TMSG <HALLELUJAH!> ELSE. TMSG <NOT ALL CONDITIONS MET> ENDIF. The above types "hallelujah!" if T1 is non-0 and FLG(XX) is on and the call to MUMBLE skips, otherwise it types "not all ...". Page 7 1.2.4 Loop Control - DO. - Loop block. As with the other block macros, the use of DO. facilitates making structure apparent and reduces the need for tags. DO. begins a loop block; the matching OD. ends it. Neither generates any code, only tags. LOOP. assembles into a single instruction to jump to the top of the loop. EXIT. assembles into a single instruction to jump out of the loop. TOP. assembles as the address of the top of the loop for jumps, e.g. SOJG T4,TOP. ENDLP. assembles as the address at the end of the loop for jumps out, e.g. SOJL T4,ENDLP. Example: .. MOVEI T4,COUNT ;SETUP COUNT FOR LOOP DO. ;TOP OF LOOP SKIPN T1,TABLE(T4) ;SOMETHING HERE? EXIT. ;NO, DONE SUBI T4,1 ;COUNTDOWN ENTRIES MOVE T2,0(T1) ;FOLLOW POINTER JUMPE T2,TOP. ;NOTHING HERE, LOOP BLCAL. XYOUT,<T2> ;DO SOMETHING WITH IT JUMPE T1,ENDLP. ;NO GOOD, QUIT LOOP. ;GO ON TO THE NEXT OD. .. ;HERE WHEN DONE [End of APPENDIX A]