;~W TACO!ins MP/PRI=65./prm="ti:+TACO./nl/ni" ;~!ins MP/prm="ti:+TACO./nl/ni" ;~!ins MP/prm="ti:+maclibcon/nl/ni/un" ;~!ins MP/prm="ti:=TACO111+maclibcon/ni/un" ; 1ST-- change to mc form: 5,$c-^-MC <- c-$->-3y ; change back: 5,$g;mc <;c/mc $;; ; find comments and fix: 5,$g/mc <;/c/mc <;/;/c/>$// ; This shortens up $macro lines but is not reversible ~5,$g/\$macro/c3/ /> ;/ ; This library supports the c calls to the Conroy's runtime system ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - ; currently defined symbols ; $top$ set to relative zero of a file (for odt use) ; $auto$ counts local storage ; $auto. for local storage counting ; $type$ routine in main lib to type out a line to lun 5 ; $buf$ a 140. byte scratch buffer i main (for printf usage ) ; ; ; The stack is used as follows: ; ; If (stack 1) ; tos branch to on false ; nos go here one done (after elseif's etc) ; ; case (stack 2) ; tos break to label ; nos variable to test ; 3os skip over to next case test label ; 4os case or label ; ; Do while/forever (stack 2) ; tos break to ; nos jmp back to test or continue in loop label ; ; loop (stack 2) ; tos break to ; nos jmp back to test for more looping label ; 3os loop index ; 4os step amount ; ; Note!!! all of these macros which test strings test for them in ; upper case only. Thus you must use upper case for everything in ; the program that is significant to these expansions. This makes ; the program more readable if everything else is in lower case. ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO IF A = B ?? 19,17,18 ?- #@I ?- #@J BR. #@2 #@1 ; ; Note that the below causes right to left evaluation of ; relations. IF a = b and c = d or d = f ; is ; equiv to IF (a = b and (c =d and (d = f))) ; in a paren'd expression (not permitted of course) ; ?+ 16,,25 I%IDN OR,#@4,> CMP. #@{1},#@{3} B#@G #@J I%IDN OR,#@4,<#@H=.> I%IDN AND,#@4, > $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO IFB A = B ?? 19,17,18 ?- #@I ?- #@J BR. #@2 #@1 ; ; Note that the below causes right to left evaluation of ; relations. IFB a = b and c = d or d = f ; is ; equiv to IFB (a = b and (c =d and (d = f))) ; in a paren'd expression (not permitted of course) ; ?+ 16,,25 I%IDN OR,#@4,> CMPB. #@{1},#@{3} B#@G #@J I%IDN OR,#@4,<#@H=.> I%IDN AND,#@4, > $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO O%R BR.TO #@2 BR #@1 ?+ 16 #@G=. ?+ $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO A%ND A = B ... #@2 ?? 15 BR #@F ?+ 16 #@G=. ?+ BR #@1 #@F=. $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO FI COMMENT ?+ 2 #@2=. ; #@1 ?+ 2 #@2=. $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO ELSE COMMENT ?? 6 ?+ 5 ?- #@6 JMP #@6 #@5=. ; #@1 $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO ELSEIF ... ;get nos ?+ 17,2 JMP #@H ?+ 15 #@F=. ?+ 16 IF #@*(1_Z) ?- #@H,2 $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO ELSEIFB ... ;get nos ?+ 17,2 JMP #@H ?+ 15 #@F=. ?+ 16 IFB #@*(1_Z) ?- #@H,2 $ENDM ; ------------------------------------------ $MACRO . just a short way to do functions C R0 = <#@*(1"Z)> $ENDM ; ------------------------------------------ $MACRO $NOP $ENDM ; ------------------------------------------ ;specialized add and sub macros, they test for #1 and do increments ; note they only check parameter 2 (i.e. sub* a,b is backwards to ; what the sub machine code is (I can't remember why). ; at any rate, the Let statement knows this. ; $MACRO SUB* I%IN <#@2> <#1> << DEC #@1>> < SUB #@2,#@1> $ENDM ; ------------------------------------------ $MACRO ADD* I%IN <#@2> <#1> << INC #@1>> < ADD #@2,#@1> $ENDM ; ------------------------------------------ ; NEW let macro, allows functions, & operator, and . array operator ; for example: ; LET a = b[d,e] + f[g,h] / #20. * g[i,j,k] - .array[index] ; note that a function must have at least 1 parm for this to work ; $MACRO LET 1 = 3 * 5 ; I%IDN <#@1> <#@5> > I%NB <#@E> > I%DF <#@1> <#@3> < M%OV #@{1},#@{3}> I%IN <#@4> <+ * - / <>> < > > ?+ 14,,25 $%% #@E #@{1},#@{5} I%NB <#@6> > $ENDM ; ------------------------------------------ $MACRO $" ?? 5,6 BR #@6 #@5=. .ASCIZ _#@1_ .EVEN ?- ##@5 #@6=. $ENDM ; ------------------------------------------ $MACRO $& ?- (SP)+ MOV ##@1,-(SP) ;push offset ADD R5,(SP) ;and compute address of #@1 $ENDM ; ------------------------------------------ $MACRO $%% I%B <#@4> <** <> <#@1 #@2,#@3> > I%NB <#@4> > I%NB <#@4> <#@1 #@2,R0> $ENDM ; ------------------------------------------ $MACRO M%OV S%SW 14 ?- #@2 ?+ 2 S%SW -14 I%IN <#@3> <> << MOV #@2,#@1>> ]> $ENDM ; ------------------------------------------ $MACRO END ?+ 2 I%NB <#@1> <#@2> >> $ENDM ; ------------------------------------------ $MACRO BEGIN name I%DF <#@2>
?- <#@1> ; ; allow for a name here. This is only here ; to check mismatched begin/ends ; $ENDM ; ------------------------------------------ $MACRO BEGIN$$ ?? 1,3 BR #@1 ?+ 2 ?- <#@3> #@2: JMP #@3 #@1: $ENDM ; ------------------------------------------ $MACRO PROGRAM NAME $top$=. S%SW 15 $auto$=-4 .enabl lc I%DOUT <; Mp version as of: 12-oct-80> I%NB <#@1> $ENDM ; ------------------------------------------ $MACRO POP MOV (SP)+,#@{1} $ENDM $MACRO PUSH S%SW 14 ?- #@{1} ?+ 1 I%DF <#@1> <(SP)+> < MOV #@1,-(SP)> S%SW -14 $ENDM ; ------------------------------------------ $MACRO call JSR PC,#@1 $ENDM ; ------------------------------------------ $MACRO LOOP FOR I = FROM TO "TO" ; watch out for which portions of the statement is lower case ; and the loop index must match in case with the next statement also. I%IN <#@8> <> <> ?+ 12,,25 ?-- #@C ?? 10,11 ?-- #@2 ?-- #@A ?-- #@B MOV #@{4},#@{2} ;Init loop index #@A=. CMP #@{2},#@{6} ;done loop? I%IN <#@5> < > > ?+ 12,,25 B#@C #@B ;yes if #@C $ENDM ; ------------------------------------------ ; New do macro, recurs with if(b) macro - needs lots of stack space. $MACRO DO WHILE(B) THIS IS THAT ; 1 2 3 4 ?? 16,17 ?-- #@G ; push the two labels such that the top is the place to break to ; and the next on stack is the loop back place ?-- #@H ; This is the loop back label #@G=. ; test the condition I%IDN <#@1> I%IDN <#@1> I%DF <#@1> FOREVER I%DF <#@1> FOREVER < JMP #@H ;else end while loop> I%DF <#@1> FOREVER $ENDM ; ------------------------------------------ $MACRO OD end of do loop (while or forever) ; Get next to tos (nos) ?++ 1,2 JMP #@1 ;Repeat loop ?++ 1 #@1=. ?++ $ENDM ; ------------------------------------------ $MACRO NEXT INDEX ?++ 2,4 ADD* #@{1},#@{2} ?++ 2,2 JMP #@2 ;back to top ?++ 2,1 ?++ ?++ #@2=. ?++ 2 I%DF <#@1> <#@2> > ?++ $ENDM ; ------------------------------------------ $MACRO BR. sets str 25 to inverse branch I%IN <#@1><= EQ NE LT GT GE LE CC CS><> I%IN <#@1><> $ENDM ; ------------------------------------------ $MACRO ! Simply sets str 25 to its first parm so the above fits on 2 lines. ?- #@1,,25 $ENDM ; ------------------------------------------ ; special case compare, checks for second arg being #0 and gens a test ; $MACRO CMP. A,B I%NB <#@2>>< CMP #@1,#@2>> $ENDM ; ------------------------------------------ $MACRO CMPB. A,B I%NB <#@2>>< CMPB #@1,#@2>> $ENDM ; ------------------------------------------ ; 1 2 3 $MACRO SELECT case var of ... ;Make 2 labels ?? 1,3 ;Put no or indicator onto stack ?-- -nor- ?-- #@1 ?-- #@{2} ?-- #@3 $ENDM ; ------------------------------------------ ; 1 from stack $MACRO CASE var (label newlabel) ; ; Case construct is as follows: ; ; Multiple cases going to the same code is by using the OR parameter ; of the case statement. example: ; ; CASE 1 OR ; CASE 2 OR ; ... ; CASE N ; ; if an "or" ; if -nor- ; if label ; if not "or" ; if -nor- do nothing ; if label ; ; ; ; ?? 3,5 ;put string in 3os (3rd from top of stack) into parm-4 ?++ 4,3 #@4=. ;place new label into 3os ?-- #@3,3 ;get var into parm4 ?++ 4,2 CMP. #@4,#@{1}, BNE #@3 ;get -nor- or label if present into parm4 from 4os ?++ 4,4 S%SW -20 I%IDN <#@2> OR -nor- > ?-- #@5,4,,20 ?++ 4,4 I%IDN <#@2> OR < BR #@4> ;I%SW 20 S%SW -20 I%DF <#@2> -nor- > I%SW 20 <#@4=.> ?-- -nor-,4,,20 $ENDM ; ------------------------------------------ ; 1 from stack $MACRO DEFAULT var (label newlabel) ?? 3 ;put string in 3os into parm-2 ?++ 2,3 #@2=. ;place new label into 3os ?-- #@3,3 ;get var into parm-2 ?++ 2,2 $ENDM ; ------------------------------------------ ; 1 from stack $MACRO CASEB var (label newlabel) ; ; Case construct is as follows: ; ; Multiple cases going to the same code is by using the OR parameter ; of the case statement. example: ; ; CASEB 1 OR ; CASEB 2 OR ; ... ; CASEB N ; ; if an "or" ; if -nor- ; if label ; if not "or" ; if -nor- do nothing ; if label ; ; ; ; ?? 3,5 ;put string in 3os (3rd from top of stack) into parm-4 ?++ 4,3 #@4=. ;place new label into 3os ?-- #@3,3 ;get var into parm4 ?++ 4,2 CMPB. #@4,#@{1}, BNE #@3 ;get -nor- or label if present into parm4 from 4os ?++ 4,4 S%SW -20 I%IDN <#@2> OR -nor- > ?-- #@5,4,,20 ?++ 4,4 I%IDN <#@2> OR < BR #@4> ;I%SW 20 S%SW -20 I%DF <#@2> -nor- > I%SW 20 <#@4=.> ?-- -nor-,4,,20 $ENDM ; ------------------------------------------ $MACRO ESAC VAR1 ?++ 2 ?++ 3 ?++ 4 ?++ ;XXXXX -#@1-1 -#@2-2 -#@3-3 -#@4-4 I%NB <#@1> ,#@3,>> #@2=. #@4=. $ENDM ; ------------------------------------------ $MACRO BREAK ;get top string into parm-15 ?++ 15,1 I%NB <#@1> <#@1 #@*(2,C)> JMP #@F ;break I%NB <#@1> FI $ENDM ; ------------------------------------------ $MACRO P%SH S%SW 14 ?- #@{1} ?+ 1 S%SW -14 ?++ 12,1 ?-- #@C+2,1 I%DF <#@1> <(SP)+> < M%-OV <#@*(1"Z)>> $ENDM $MACRO M%-OV ** <> I%IN <#@2> <- + / * <>> <> I%SW 20 > I%SW 21 < MOV #@1,-(SP)> I%SW 22 >> I%NB <#@2> < MOV -2(R5),-(SP)> $ENDM ; - - - - - $MACRO PEEK ?+ 1,,#@1 [#@1] $ENDM ; - - - - - $MACRO CL ARRAY/FUN P1 P2 P3... I%IN <#@=1(1:1)> . <> > S%SW -9 $ENDM ; ------------------------------------------ $MACRO CL@ ARRAY P1 P2 P3 M%OV R1,#@{2} I%DF <#@3> B < ASL R1> T%YP T #@1 25 ?+ 10,,25 I%IN <#@A> <0 1 2> << ADD ##@1,R1> < ADD ##@1,R1> < ADD #@1(R5),R1>> I%IDN <#@A> 1 < ADD R5,R1> MOV#@3 (R1),R0 $ENDM ; ------------------------------------------ $MACRO CL% NAME P1 P2... ?-- 0 ** P%SH <#@A>,<#@9>,<#@8>,<#@7>,<#@6>,<#@5>,<#@4>,<#@3>,<#@2> JSR PC,#@1 ?++ 1 ADD ##@1,SP ;Clean up stack $ENDM ; - - - - - ; uses the xxx[yyy] feature and permits calls to either c routines ; or routines set up via a func/ret macro pair. ; $MACRO C Call a c prog as: C var = name[abc] CL #@3 I%DF <#@1> < mov r0,#@1> $ENDM ; - - - - - ; Function sets up offsets according to how the Conroy save and restore ; routines allocate storage off the stack ; it also allocates storage for locals. Then it clears ; the local (auto) storage counter for the next function later on. ; ; Usage of C function compatible routines ; ; program lab |used once ; |------------ ; auto l1 l2 l3 ... | Function 1 ;FUNCTION entry[p1,p2 ...] | ; ... | code is here ; ret [value] | ; | ; |------------- ; auto l1 l2 l3 ... | Function 2 ;FUNCTION entry2[p1,p2 ...] | ; ... | code is here ; ret [value] | ; |------------- ; ; ; All variables are referenced as xxx(r5) ; and are call by value as in C. ; ; $MACRO FUNCTION A[B,C,D] ; trace will cause the function name and argument values to be printed ; on entry. The top of the file (for odt use) is also output. The odt ; option will cause an iot trap to odt. ; trace is switch 17, (x7) odt entry is 18 (x8) F%UNC #@1 I%SW 17 I%SW 18 S%SW -18 $ENDM ; ------------------------------------------ $MACRO T%% LET r1 = "#@1:%6o Top=%6o #@2=%o #@3=%o #@4=%o #@5=%o #@6=%o #@7=%o" PRINTF r1,##@1,#$top$ #@*(2,Z) $ENDM ; ------------------------------------------ $MACRO F%UNC A,B,C,D... #@1:: FUNC #@*(2_Z) $ENDM ; ------------------------------------------ ; func used to be the only macro (i.e. no Function) ; some older programs specify this macro instead - so it remains. ; it also is the only way to have a function without the name being ; declared global. $MACRO FUNC P1 P2 P3... Use Conroys runtime here. I%NB <#@1> <#@1= 12> I%NB <#@2> <#@2= 14> I%NB <#@3> <#@3= 16> I%NB <#@4> <#@4= 20> I%NB <#@5> <#@5= 22> I%NB <#@6> <#@6= 24> I%NB <#@7> <#@7= 26> I%NB <#@8> <#@8= 30> ** E%%S <#@*(1"Z)> I%NB <#@*(9:Z)> > ;note that $auto$ is negative, thus we ADD to sub from stack ; save current $auto$ in $auto. for the return ; but re-init $auto$ in case there is no return statement ; jsr r0,$$csav ;get stack frame add #$auto$,sp ;allocate space on stack for autos $auto.=$auto$ $auto$=-4 ;re-init $ENDM ; - - - - - $MACRO E%%S E%S #@1 2 $ENDM ; - - - - - $MACRO RET ; The below does not < > the parameters so that any function references ; will cause an error (since they would clobber r0 and we accumulate ; into r0). I%NB <#@1> I%SW 17 sub #$auto.,sp ;de-allocate locals jmp $$cret $ENDM ; - - - - - ;$MACRO RET This version will have to wait till we have better temp alloc ;I%NB <#@1> > ;I%NB <#@1> < MOV -2(R5),R0> ; sub #$auto.,sp ;de-allocate locals ; jmp $$cret ;$ENDM ; - - - - - ; Auto is used to generate offsets which are applied to labels and ; compute how much local storage is needed to allocate from the stack ; ; Usage: AUTO a,b,c... if [n] not specified, then its 2 ; AUTO a[n],b[n],c,d... if odd values are supplied, user ; must do the allignment ; The Program statement must appear first (at least once in the program) ; it initializes $auto$. Multiple Autos are permitted. The auto's must ; be followed by a Func statement which allocates (and must be the entry) ; storage. After it allocates storage it also re-initializes $auto$ ; so a subsuquent function can re use it properly. Note that variables ; defined in this manner can be reused locally in another function with ; diffenent offsets, but nuthing is going to detect using a variable ; defined locally to another function which is intended to be redefined ; and is inadvertantly left out of a Auto statement ; $MACRO AUTO var1 var2 ... ** AUTO% <#@*(1"N)> $ENDM ;- - - - - $MACRO AUTO% var [size] (size defaults to 2) I%IN <#@2> <> <> ?+ 2,,28 $auto$=$auto$-#@2 #@1= $auto$ E%S <#@1> 1 $ENDM ; - - - - - ;+ ; These macros are used when writing privel'd tasks (or ones which ; simply must be small - can't afford the overhead of the C library). ; ; type buf-addr [car-control] ;qiow to lun5 buffer (no jsr) ; len buf-addr ;sets r0=len of str ; tty bufaddr [car-control] ;like type, but jsr's to $type$ ; ; All assume that r0 and r1 are available to be ; destroyed without saving. (all c callable stuff is like this) ; car-control defaults to #40 ;- ; - - - - - $MACRO LEN string ?? 2 mov #@{1},r0 #@2=. tstb (r0)+ bne #@2 sub #@{1},r0 dec r0 $ENDM ; - - - - - $MACRO TYPE string-addr types asciz string LEN #@1 I%IN <#@2> <> <> ?+ 2,,28 ;qiow$s #io.wvb,#5,#5,,,,<#BUF,r0,#40> THIS IS TOO DAMN SLOW CLR -(SP) CLR -(SP) CLR -(SP) MOV #@{2},-(SP) MOV r0,-(SP) MOV #@{1},-(SP) CLR -(SP) CLR -(SP) CLR -(SP) MOVB #5,(SP) MOV #5,-(SP) MOV #io.wvb,-(SP) MOV (PC)+,-(SP) .BYTE 3,12. EMT ^O<377> $ENDM ; - - - - - $MACRO TTY quoted string or address of asciz string mov #@1,-(sp) jsr pc,$type$ $ENDM ; - - - - - ; Printf Like the unix or C routine. It does not understand \x type ; of stuff and allways assumes a \n at the end of the string. ; Usage: printf "string" p1 p2 p3 ... ; String may be literal or just a variable which points to a string. ; Pn may be functions[arg] registers strings etc. ; basically anything in the LET statement. ; To just format the buffer, use the sprint function directly. ; note that $buf$ is used for formatting and if an argument ; is a function which recursively calls printf it will clobber ; $buf$. $MACRO PRINTF mov r0,-(sp) mov r1,-(sp) C R0 = sprint[#$buf$,<#@*(1"Z)>] mov #$buf$,-(sp) jsr pc,$type$ mov (sp)+,r1 mov (sp)+,r0 $ENDM ; - - - - - ; Finally these are defined. They clobber r0 and/or r1 (mul uses r1 ; div uses both) ; BE careful with these. $MACRO MUL45 A * B A = A * B mov #@2,r1 mul #@1,r1 mov r1,#@1 $ENDM ; $MACRO DIV45 A B A = A / B clr r0 mov #@1,r1 div #@2,r0 mov r0,#@1 $ENDM ; $MACRO FOR INIT-1 CONDITION-2 REINIT-3 ; This is a for loop like C or ratfor ; I%IN <#@2> <> <> > ?+ 2,,25 #@1 DO #@2 ?- <#@3> $ENDM ; $MACRO ROF ; the ending statement in a for loop ?+ 1 #@1 OD $ENDM ; ------------------------------------------ ; ------------------------------------------ $MACRO DMPSTR ?- <-----1-----> ?-- <-----2-----> ?+ ?++ ** $%D 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 25 29 ** $%D2 30 31 32 33 34 35 36 37 38 39 ** $%D2 40 41 42 43 44 ?- <> ?-- <> ?+ ?++ $ENDM ; $MACRO $%D ?+ 2,,#@1 I%NB <#@2> $ENDM ; $MACRO $%D2 ?++ 2,,#@1 I%NB <#@2> $ENDM ; $MACRO DMPSW ** S%%W 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ** S%%W 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 $ENDM ; $MACRO S%%W I%SW <#@1> $ENDM ; $MACRO DUMP S%SW -9 DMPSW DMPSTR I%IN <#@1> < > $ENDM ; $MACRO POKE STACK STRING ?- <#@2>,,#@1 $ENDM ;------------------------------------------------------------------------ $MACRO SETLAB LAB ;This allows one to set the label used for generating labels ?- #@1,,29 $ENDM ; - - - - - ; The following trap the .end statement and verify all constructs ; have been terminated. It checks the current level of the stack ; by pushing .end and verifying that they are in position 1 of ; both stacks. $MACRO .end .END #@1 $ENDM $MACRO .END ?- .END ?-- .END ?+ 5,,1 ?+ 6,,31 I%DF <#@5#@6> <.END.END> > ?+ ?++ I%DOUT <.END #@1> $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO STRUCT name ?- #@1 #@1=0 $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO END-STRUCT ?+ 2 I%NB <#@1> >> $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO FIELD name1,name2... ** F%%D <#@*(1"N)> $ENDM ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - $MACRO F%%D ?+ 10,1 #@1=#@A I%IN <#@2> <> << #@A=#@A+2>> < #@A=#@A+#@2> $ENDM ; LST--