1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-23 19:07:45 +00:00
PDP-10.its/src/syseng/calret.30
2016-12-03 16:19:19 -08:00

397 lines
8.7 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; CALRET - Call Return routines. DAM.
;;; This facility is based on a similar one by Michael Spier
;;;** NOTE FORMAT OF CERTAIN MACROS HAS BEEN CHANGED SINCE CALRET 8
;;;** Rewritten to make literals etc. work. Max 10 arguments.
;;; This is entirely due to the losiness of IRP wrt brackets.
;;; FORMAT OF STACK FRAME CHANGED - VERSION 16
IF1,[ ;STUFF THAT ONLY NEEDS TO BE DONE ONCE
; MACRO TO TELL WHAT VERSION INSERT FILE THIS IS
DEFINE TELLVERSION
IF1,[
.TYO6 .IFNM1
PRINTX " "
.TYO6 .IFNM2
PRINTX " Included in this assembly.
"
]
TERMIN
TELLVERSION
;;; Registers
;;; Temporary Registers - destroyed by calls, may not be passed as arg.
;;; Note: T0 is not an index register; The order may be relied upon
T0=0
T1=1
T=2
TT=3
;;; Registers Used Internally by the System
P=17 ;PushDown List Pointer
.CF.=16 ;Current Stack Frame Pointer
.PF.=15 ;Previous Stack Frame Pointer
.AP.=14 ;Argument List Pointer
;;; Registers which may be used as variables and passed as arg,
;;; by means of a REGISTER declaration.
.PRSVA=4 ;First Preserved Register
.PRSVZ=13 ;Last Preserved Register
;;; Format of the Stack Frame
;;;
;;; Return Address (Previous Routine's PC)
;;; Previous Routine's Registers, i.e.
;;; .CF. -> .PRSVA - .PRSVZ, .AP., .PF.
;;; User's LOCAL variables + System Generated Locals
;;; Temporaries Pushed
;;; P -> on the Stack
;;; next Frame will begin here
;;; Macro used at start of program to set up environment
DEFINE PROGRAM NAME,SPEC
SPEC ;SET STACK SIZE IF USER SAID TO
IFNDEF STACK, STACK=100 ;DEFAULT TO 100 WORDS
IFNDEF PDL, PDL: BLOCK STACK
NAME: .BEGIN NAME
IF2 .STZZ.==.STSZ.-1 ;final stack size
.STSZ.==1 ;minimum size frame
.REGS.==.PRSVA-1
MOVE .CF., [-STACK,,PDL-1] ;SET UP PDL
MOVE P, [.STZZ.-STACK,,PDL+.STZZ.-1]
IF1 EXPUNGE PDL
TERMIN
;;; Macro to define a Procedure
; NAME: PROCEDURE ARG1,ARG2,...
DEFINE PROCEDURE -PARAMS
.BEGIN ;Name picked from tag
IF2 .STZZ.==.STSZ.-1 ;final stack size
.STSZ.==1 ;minimum size frame
.REGS.==.PRSVA-1
ENTRY PARAMS
TERMIN
DEFINE ENTRY -PARAMZ ;you will lose unless .U"NAME: ENTRY
.PARM.==0
IRPW PARAMS,,[PARAMZ]
IRP PARAM,,[PARAMS] ;declare the formal parameters
.DEF. PARAM,.AP.,\.PARM.,@
.PARM.==.PARM.+1
TERMIN
TERMIN
JSP T, .ENTR. ;invoke entry operator
.STZZ.,,.STZZ. ;on 2nd pass, becomes stack adjustment
TERMIN
DEFINE .DEF. NAME,BASE,OFFS,MOD
DEFINE NAME
MOD!OFFS(BASE)TERMIN
TERMIN
; To end a procedure, just use .END
;;; Macro to declare variables that reside in registers
DEFINE REGISTER -NAMES1
IRPW NAMES,,[NAMES1]
IRPS NAME,,[NAMES]
.REGS.==.REGS.+1
IFG .REGS.-.PRSVZ, INFORM TOO MANY REGISTERS DECLARED - ,NAME
NAME=.REGS.
TERMIN
TERMIN
TERMIN
;;; Macro to declare local variables
;;; for a multiword var, follow name by length in parentheses.
;;; the length must be a number or constant symbol (no A+1, etc.)
DEFINE LOCAL -NAMES1
IRPW NAMES,,[NAMES1]
.ARG.==0 ;FLAG FOR LENGTH FROB
IRPS NAME,DELIM,[NAMES]
IFN .ARG.,[ .STSZ.==.STSZ.+NAME-1 ;LENGTH OF PREV VAR
.ARG.==0
]
.ELSE [ ;NORMAL VAR
IFSE [DELIM](, .ARG.==1 ;LENGTH FOLLOWS
.DEF. NAME,.CF.,\.STSZ.
.STSZ.==.STSZ.+1
]
TERMIN
TERMIN
TERMIN
;;; Macro to generate a call
DEFINE CALL ROUTINE?A,B,C,D,E,F,G,H,I,J
.NARG.==0 ;count arguments
.NFRM.==0 ;count formals passed as arg, which require kludgery
IRP ARG,,[[A],[B],[C],[D],[E],[F],[G],[H],[I],[J]]
IFSE [ARG], .ISTOP
.NARG.==.NARG.+1
.ARG.==<ARG>
IFNDEF .ARG.,.STOP ;undef skip it
.TAG.==<.ARG._-18.>&17
IFN <.TAG.>*<.TAG.-.CF.>,[ ;have to copy it
MOVEI T0, ARG
MOVEM T0, .STSZ.(.CF.)
.STSZ.==.STSZ.+1
.NFRM.==.NFRM.+1
]
TERMIN
IFN .NARG.,[ ;create argument list
MOVEI T1, [ IRP ARG,,[[A],[B],[C],[D],[E],[F],[G],[H],[I],[J]]
IFSE [ARG], .ISTOP
.ARG.==<ARG> ;evaluate the argument's address
IF1 IFNDEF .ARG., .ARG.==. ;PASS 1 UNDEFINED
.TAG.==<.ARG._-18.>&17
.IND.==.ARG.&<@>
.ARG.==.ARG.&777777
IFE .TAG.-.CF., .ARG.==0 .ARG.(.PF.) ;passing local
IFE .TAG.,[
IFE .ARG.&777760, .ARG.==0 .ARG.-.PF.(.CF.) ;reg
.ELSE ;passing a static variable
]
IFN <.TAG.>*<.TAG.-.CF.>,[ ;passing via copy
.IND.==<@>
.ARG.==0 .STSZ.-.NFRM.(.PF.)
.NFRM.==.NFRM.-1
]
.ARG.+.IND. ;now generate the argument pointer
TERMIN
]]
PUSHJ P, ROUTINE
TERMIN
;;; Macro to generate a return
DEFINE RETURN
JRST .RETN.
TERMIN
;;; Error Macro
DEFINE INFORM A,B,C,D,E,F,G,H,I,J
PRINTX\A!B!C!D!E!F!G!H!I!J
\
TERMIN
];END MOBY IF1
;;; Entry Operator
.ENTR.: MOVEI TT, 1(P) ;save registers between frames
HRLI TT, .PRSVA
ADD P, [.PF.-.PRSVA+1,,.PF.-.PRSVA+1] ;protect reg save area
BLT TT, 0(P)
MOVE .AP., T1 ;set called routine's registers
MOVE .PF., .CF.
MOVE .CF., P
ADD P, 0(T) ;adjust stack
JUMPL P, 1(T) ;and go to called routine
.SUSET [.SIPIRQ,,[%PIPDL]]
JRST 1(T)
;;; Return Operator
.RETN.: MOVE P, .CF. ;pop frame off
MOVE .CF., .PF.
MOVSI TT, -<.PF.-.PRSVA>(P) ;restore registers
HRRI TT, .PRSVA
BLT TT, .PF.
SUB P, [.PF.-.PRSVA+1,,.PF.-.PRSVA+1] ;pop regs off
POPJ P, ;and return
CONSTANTS
IF1,[ ;MORE ONCE-ONLY STUFF
;;; Conditional-Jump Generator Used Internally.
;;; COND may be a skip or a JUMP or an AOJ or a SOJ, if condition true.
;;; COND may also be several instructions - the last is looked at
;;; to see whether it is a skip or a jump - all are assembled in.
;;; Generates code to jump to TAG if the condition is false.
DEFINE .COND. COND,TAG
.JUMP.==0 ;condition type flag
.CRGL.==004000,, ;opcode sense inverter
IRPW CND,,[COND]
IRPS CN,,[CND]
.OPCD.==770000000000&<CN>
IFSE CN,AOBJN,[ .JUMP.==1 ? .CRGL.==1000,,]
IFSE CN,AOBJP,[ .JUMP.==1 ? .CRGL.==1000,,]
.ISTOP
TERMIN
.ICNT.==.IRPCNT ;count instructions
TERMIN
IFE .OPCD.-JUMP, .JUMP.==1
IFE .OPCD.-AOJ, .JUMP.==1
IFE .OPCD.-SOJ, .JUMP.==1
IFE .JUMP.,[ ; skip - code it followed by JRST
COND
JRST TAG
]
IFN .JUMP.,[ ; jump - alter sense of last instr (the jump)
IRPW CND,,[COND]
IFN .IRPCNT-.ICNT., CND
.ELSE <<CND>#.CRGL.>+TAG
TERMIN
]
TERMIN
;;; Iteration Macros
DEFINE WHILE COND,BODY\EAT,BTAG,ETAG
DEFINE EXITLOOP
JRST ETAG
TERMIN
BTAG: .COND. [COND]ETAG
BODY
JRST BTAG
ETAG:
.XCREF BTAG,ETAG,EXITLOOP
TERMIN
DEFINE UNTIL COND,BODY\EAT,BTAG,ETAG
DEFINE EXITLOOP
JRST ETAG
TERMIN
BTAG: BODY
.COND. [COND]BTAG
ETAG:
.XCREF BTAG,ETAG,EXITLOOP
TERMIN
;;; If - Then - Else Macros
DEFINE IF COND,THENCLAUSE\EAT,TAG
DEFINE .IFTG.
TAG==.
TERMIN ;remember TAG for redefinition
.COND. [COND]TAG ;if false, skip THEN clause
THENCLAUSE
TAG==.
TERMIN
DEFINE ELSE ELSECLAUSE\EAT,TAG
JRST TAG ;make THEN clause skip ELSE clause
.IFTG. ;redefine tag generated by IF
ELSECLAUSE
TAG:
TERMIN
DEFINE ELSEIF COND,THENCLAUSE
ELSE [IF [COND][THENCLAUSE]]
TERMIN
;;; System-Call Macro.
DEFINE .CALL PROC,IN,OUT,CTLB
;COUNT ARGUMENTS
.CLST.==0
.CLCT. IN
.CLCT. OUT
.CLCT. CTLB
043000,,[SETZ
.1STWD SIXBIT/PROC/
.CLAG. 4000,CTLB
.CLAG. 0,IN
.CLAG. 2000,OUT
IFN .CLST.,INFORM BAD FORMAT SYSTEM CALL - PROC
]
TERMIN
DEFINE .CLCT. ?A,B,C,D,E,F,G,H ;CROCK DUE TO IRP LOSS
IFNB [A] .CLST.==.CLST.+1
IFNB [B] .CLST.==.CLST.+1
IFNB [C] .CLST.==.CLST.+1
IFNB [D] .CLST.==.CLST.+1
IFNB [E] .CLST.==.CLST.+1
IFNB [F] .CLST.==.CLST.+1
IFNB [G] .CLST.==.CLST.+1
IFNB [H] .CLST.==.CLST.+1
TERMIN
;;; ARGUMENT POINTER GENERATOR FOR ABOVE
;;; A # INDICATES AN IMMEDIATE ARGUMENT
DEFINE .CLAG. BITS?A,B,C,D,E,F,G,H
IFNB [A] .CLG1. BITS,A
IFNB [B] .CLG1. BITS,B
IFNB [C] .CLG1. BITS,C
IFNB [D] .CLG1. BITS,D
IFNB [E] .CLG1. BITS,E
IFNB [F] .CLG1. BITS,F
IFNB [G] .CLG1. BITS,G
IFNB [H] .CLG1. BITS,H
TERMIN
DEFINE .CLG1. BITS?ARG
.CLST.==.CLST.-1 ;COUNT ARGS
.CLG2.==0
IRPNC 0,1,-1,CH,REST,[ARG]
IFE "CH-"#,[ <IFE .CLST.,[400000]+BITS+1000>,,0*"CH+REST
.CLG2.==1 ;the 0 times is per order rms
] ;Immediate
IFE "CH-"?,[ <IFE .CLST.,[400000]+3000>,,0*"CH+REST
.CLG2.==1
] ;Error-code argument
IFN "CH-40, .ISTOP ;STOP ON FIRST NON BLANK
TERMIN
IFE .CLG2., <IFE .CLST.,[400000]+BITS>,,ARG
TERMIN
];END MOBY IF1
;;; Interrupt Facilities
DEFINE INTSET ?Z\IB ;arg is one line per interrupt, usual four things
IB: P
IRPW X,,Z
IRP Y,,[X]
ZZ==.IRPCNT
IFN ZZ-4, Y
.ELSE [ 0,,[ PUSHJ P, .INTR. ? Y ] ]
TERMIN
IFN ZZ-4, INFORM ERROR: INTSET - NOT FIVE THINGS - ,[X]
TERMIN
;end interrupt list
ZZ==.
LOC 42
IB-ZZ,,IB
LOC ZZ
; Interrupt Interface Routine - allows Standard Procedures as handlers
.INTR.: PUSH P, T ;save temporary registers
PUSH P, T1
PUSH P, T0
EXCH TT, -3(P) ;saves TT and gets call addr
PUSHJ P, @0(TT) ;invoke handler. Entry seq saves rest of regs
POP P, T0 ;restore regs
POP P, T1
POP P, T
POP P, TT
.CALL DISMISS,P ;and dismiss interrupt
TERMIN
;;; End of CALRET