.title segload .ENABLE LSB ; .IDENT /GCE000/ ; G. EVERHART 5/13/85 VERSION 00 UNTRIED YET ; THE idea here is that overlays are a LOT simpler where there is one ; large overlay area and a root, with all overlays coming into the ; one area. A typical configuration might have 16K of root and as many 16K ; overlay segments as needed, each with perhaps 1 overlay subroutine in ; it. ; This allows routines in any overlay to call routines in any other ; overlay freely in this sort of task. ; There are 2 problems with this using normal DEC code: ; 1. If the overlays are disk based, an overlay that calls another ; overlay into its space gets clobbered by loading the second ; overlay. This means you can't get back to your caller code ; because it's been overwritten. Local variables in the caller ; area generally make a reload of the area not work too well. That's ; a problem no matter what code (including this) you try. ; 2. DEC autoload code does not save the old mapping context and restore ; it on return, so it can't get you back either. This code is meant ; to address the latter problem. ; ; If the task is memory-resident-overlays only, local variables actually ; remain across calls so problem 1 is eliminated (at the cost of coarse ; granularity in sizes of regions). This code should be used only for ; memory resident overlays. ; ; Another problem is that data areas in argument lists must be kept ; in addressable space. We will try to address this here. The ; symbol HIGHVA must be defined as the top of the root's virtual ; address space to ensure that addresses are legal. ; ; ASSUME I SPACE MAPPING THIS VERSION. ; SEE TKB MANUAL FOR D SPACE CALL .PSECT DATA,RW,D PBLK: .BYTE 3,0 ;SYNCH LOAD LSTSEG: .WORD 0,0 ;LAST SEGMENT NAME (FOR STACK PUSH) ; NEXT MACRO DEFINES DATA STRUCTURES WE USE .MACRO GENTRY SEGNAM,ENTADR,?A .PSECT SEGS,RO,D,GBL,CON A: .RAD50 /SEGNAM/ .=A+4 ;ENSURE 2 WORDS SEGMENT NAME .WORD ENTADR ;ENTRY ADDRESS .PSECT CODE,RO,I MOV R0,-(SP) ;PUSH A REG MOV #A,R0 ;SAVE ADDRESS THIS DATA STRUCT IN R0 JMP CMN ;GO PROCESS .ENDM ;NOW HAVE REAL GLOBAL ENTRIES CALL THE GENTRY MACRO ; NOTE THAT THIS DEFINES THE ENTRY POINTS AS ALL IN THE ROOT ; SO WE CAN REALLY USE THEM. USE SEGMENT NAMES USED IN ODL AND ; EDIT SUBROUTINE NAMES ACCORDINGLY XQTCMD:: GENTRY GXQTCM,GXQTCM RECALC:: GENTRY RECALC,GRECAL FNAME:: GENTRY RECALC,GFNAME DOENTR:: GENTRY RECALC,GDOENT DOMFCN:: GENTRY RECALC,GDOMFC HELP:: GENTRY GHELP,GHELP CALC:: GENTRY CALC,GCALC ERRCX:: GENTRY ERRCX,GERRCX CMND:: GENTRY GCMND,GCMND AT:: GENTRY AT,GAT BASCNG:: GENTRY AT,GBASCN DECLR:: GENTRY AT,GDECLR USRFCT:: GENTRY GUSRFC,GUSRFC POSTVL:: GENTRY POSTVL,GPOSTV CALUN:: GENTRY CALUN,GCALUN CONTYP:: GENTRY CALUN,GCONTY WRKFIL:: GENTRY WRKFIL,GWRKFI MULCON:: GENTRY CALUN,GMULCO CALBIN:: GENTRY CALBIN,GCALBI MULADD:: GENTRY MULADD,GMULAD MULDIV:: GENTRY MULADD,GMULDI MULMUL:: GENTRY MULADD,GMULMU VAROUT:: GENTRY VAROUT,GVAROU MOUT:: GENTRY VAROUT,GMOUT INPOST:: GENTRY INPOST,GINPOS NEXTEL:: GENTRY INPOST,GNEXTE LIST:: GENTRY LIST,GLIST USRCMD:: GENTRY USRCMD,GUSRCM UVT100:: GENTRY UVT100,GUVT10,S$Q1 RELVBL:: GENTRY GRELVB,GRELVB,S$Q2 CMDMUN:: GENTRY GRELVB,GCMDMU,S$Q3 GETTTL:: GENTRY GRELVB,GGETTT,S$Q4 DSPSHT:: GENTRY DSPSHT,GDSPSH,S$Q5 INITA1:: GENTRY GINIA1,GINIA1,S$Q6 INITA2:: GENTRY GINIA2,GINIA2,S$Q7 INITB:: GENTRY GINITB,GINITB PMTX2:: GENTRY GPMTX2,GPMTX2 GMTX:: GENTRY GPMTX2,GGMTX VVARY:: GENTRY GVVARY,GVVARY RNDF:: GENTRY RND,GRNDF ERRMSG:: GENTRY ERRMSG,GERRMS GMADD:: GENTRY GMSUBS,GGMADD GMPRD:: GENTRY GMSUBS,GGMPRD GMSUB:: GENTRY GMSUBS,GGMSUB GTPRD:: GENTRY GMSUBS,GGTPRD MTXEQU:: GENTRY MTXEQU,GMTXEQ MDET:: GENTRY MDET,GMDET SED:: GENTRY GSED,GSED SSCMP:: GENTRY GSED,GSSCMP SVBL:: GENTRY GSVBL,GSVBL SSTR:: GENTRY GSSTR,GSSTR PGET:: GENTRY GPGET,GPGET PGGET:: GENTRY GPGGET,GPGGET JULIAN:: GENTRY JULIAN,GJULIA JULMDY:: GENTRY JULIAN,GJULMD JULASC:: GENTRY JULIAN,GJULAS FRMEDT:: GENTRY FRMEDT,GFRMED WSSET:: GENTRY GWSSET,GWSSET FLIP:: GENTRY FLIP,GFLIP SLEND:: GENTRY SLEND,GSLEND STRCMP:: GENTRY SLEND,GSTRCM TTYINI:: GENTRY GTTYIN,GTTYIN TTYDEI:: GENTRY FLIP,GTTYDE ZERO:: GENTRY FLIP,GZERO ZNEG:: GENTRY FLIP,GZNEG VARSCN:: GENTRY SLEND,GVARSC,VS1$$ GN:: GENTRY SLEND,GGN,VS2$$ SCMP:: GENTRY FLIP,GSCMP,VS3$$ GETNNB:: GENTRY SLEND,GGETNN,VS4$$ ; END OF TABLE OF GLOBAL ENTRIES AND THEIR REAL OVERLAID ONES. .PSECT CODE,RO,I CMN:; MOV R0,-(SP) ;SAVE A REG ; Note we save all registers. Most DEC languages assume subroutine ; calls trash the regs but save them for any macro-11 users who ; really want them preserved. ; If you only use a HOL you can bag the push and pop of R2 through R4. MOV R1,-(SP) MOV R2,-(SP) ;NEED COUPLE EXTRA REGS CLR -(SP) ;SAVE CARRY ROR (SP) MOVB @R5,R1 ;SEE HOW MANY ARGS NEED TO BE PUSHED CMPB R1,#37 ;LIMIT FOR REASONABLENESS BHI BADARG INC R1 ;STORE COUNTER TOO ASL R1 ;MAKE WORD POINTER MOV SP,R2 ;R2 IS FRAME POINTER FOR NOW SUB R1,SP ;MAKE ROOM FOR ARGS AND MOV R1,-(SP) ;PUSH COUNTER ;NEED TO HAVE COUNTER PUSHED SO WE CAN TELL WHERE STUFF IS... MOV R0,-(SP) ;LOCAL REG SAVE MOV R1,-(SP) MOV R3,-(SP) MOV SP,R0 ;POINT AT SAVED ARG AREA ADD #10,R0 ;PASSING PUSHED STUFF ASR R1 ;GET NUMBER OF ARGS BEQ 36$ ;BE SURE NONZERO MOV R5,R3 ;GET INPUT ARG LIST .IF DF,HIGHVA 37$: MOV (R3)+,(R0) ;COPY AN ARG CMP (R0)+,#HIGHVA ;SEE IF OK BLOS 38$ ;IF LOS ALL RIGHT EMT 370 ;ELSE ILLEGAL TRAP 38$: SOB R1,37$ ;LOOP OVER ALL ARGS .IFF 37$: MOV (R3)+,(R0)+ ;COPY ARG LIST W/O CHECK SOB R1,37$ .ENDC 36$: MOV SP,R5 ADD #10,R5 ;POINT R5 AT COPY OF ARG LIST MOV (SP)+,R3 MOV (SP)+,R1 MOV (SP)+,R0 ;LOCAL RESTORE REGS ; ; NOW FIX UP UPPER PART OF STACK MOV 4(R2),R1 ;RESTORE R1 MOV 6(R2),R0 ;AND R0 ROL (R2) ;RETRIEVE C BIT MOV 2(R2),R2 ;GRAB SAVED R2 ON STACK ALSO. MOV R0,-(SP) ; POP THIS JUNK OFF AT THE END WITHOUT MODS SO THE INNER LOOP IS ;UNCHANGED. BR OKARG ;GO AHEAD BADARG: CMP (SP)+,(SP)+ ;POP STACK CMP (SP)+,(SP)+ RTS PC ; HERE WE HAVE ARG LIST POINTED AT BY R5 AS COPIED TO STACK AND ; THE OTHER REGS ON TOP OF STACK. ; ; SAVED JUNKABLE R0 ; SAVED JUNKABLE R1 ; SAVED JUNKABLE R2 ; SAVED JUNKABLE C BIT ; ARG LIST COPY (N WORDS) ; SAVED COUNTER OF WORDS IN ARG LIST COPY (N) ; SAVED R0 <-- SP ; AT THIS POINT. OKARG: MOV R1,-(SP) ;OR 2 MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) ;OR ALL OF THEM MOV R5,-(SP) MOV LSTSEG,-(SP) ;PUSH LAST SEG ADDRESS MOV LSTSEG+2,-(SP) ;ALL 32 BITS OF NAME CLR -(SP) ;SAVE CARRY BIT ROR (SP) ;BY ROTATE INTO A STACK CELL ; $LOAD CLOBBERS CARRY BIT) MOV 4(R0),R1 ;GET ENTRY ADDRESS CMP (R0),LSTSEG BNE 11$ ;CHECK CHANGE CMP 2(R0),LSTSEG+2 ;AND IF EQUAL NAME BEQ 10$ ;THEN SKIP THE LOAD 11$: MOV (R0),LSTSEG ;COPY NAME MOV 2(R0),LSTSEG+2 ;WHICH IS 2 WORDS LONG MOV R1,-(SP) MOV #PBLK,R0 ;GET READY TO LOAD JSR PC,$LOAD ;LOAD THE SEGMENT MOV (SP)+,R1 ;RESTORE ENTRY ADDRESS 10$: MOV 6(SP),R5 ;RESTORE CALLING R5 (JUST IN CASE) JSR PC,@R1 ;CALL DESIRED SUBROUTINE ;SAVE R0 AND R1 IN CASE IT WAS A FUNCTION CALL. ALSO R2,R3 CLR (SP) ;C BIT SAVE ROR (SP) ;HERE MOV R0,20(SP) MOV R1,16(SP) MOV R2,14(SP) MOV R3,12(SP) ;RESTORES SUBROUTINE'S RETURN R0-R3 ;TO OUR CALLER. ;NOW RESTORE OLD MAPPING AND LEAVE ;THIS IS KEY: THE RETURN RESTORES OLD MAPPING TST 2(SP) ;SEE IF SAVED SEG IS NULL BNE 20$ ;IF NE NO, POP OLD ONE TST 4(SP) ;CHECK BOTH WORDS OF NAME BNE 20$ MOV (SP),4(SP) ;SAVE C BIT AREA CMP (SP)+,(SP)+ ;NULL NAME; POP 2 STACK WORDS BR 21$ ;and skip RESTORE... 20$: MOV 2(SP),LSTSEG+2 MOV 4(SP),LSTSEG ;GET BACK TO CALLING MAPPING MOV (SP),4(SP) CMP (SP)+,(SP)+ ;FIX STACK 21$: MOV LSTSEG,R0 BIS LSTSEG+2,R0 ;CHECK FOR NONZERO SEG NAME BEQ 1$ ;SKIP LOAD IF NONE THERE 2$: MOV #PBLK,R0 ;MAP IT AGAIN JSR PC,$LOAD .GLOBL $LOAD ;NOW HAVE IT ALL BACK 1$: ROL (SP)+ ;RESTORE CARRY BIT MOV (SP)+,R5 ;POP ALL REGS BACK MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 BCC 41$ ;RESTORE C BIT VIA BRANCH HERE ADD (SP),SP ;ADD # WORDS IN ARGLIST TO STACK TST (SP)+ ;POP OFF LAST ALSO INC (SP)+ ;GET SAVED C BIT SEC ;C BIT WAS SET SO SET IT BR 42$ 41$: ADD (SP),SP TST (SP)+ INC (SP)+ CLC ;C BIT WAS CLEAR SO CLEAR IT 42$: MOV (SP)+,(SP)+ ;JUNK 3 STACK WORDS LEAVING C ALONE INC (SP)+ ;JUNK LAST WITHOUT DISTURBING C BIT RTS PC ;AND RETURN TO CALLER .END