.TITLE SAV RT-11 ABSOLUTE LOADER .NLIST BEX .ENABL LC ; ; Pdp11/dcn basic operating system - rt-11 absolute loader ; ; This program reads an rt-11 background program file (.sav extension) and ; loads it into the user area allocated to this process. It also sets the ; initial starting address (loc 40), intiial stack address (loc 42) and ; highest program address (loc 50) in the cache area. Note: this program only ; works with rt-11 version 3 or later files. ; ; Programs can be loaded in three ways: (1) in the ordinary rt-11 way at the ; beginning of the user area in the background process, (2) at the beginning ; of the user area in a foreground process (position-independent only) and (3) ; at the end of the user area in either the background process or a foreground ; process (position-independent only). ; ; External symbols ; .GLOBL SRESET,TRPENB ; ; Entry symbols ; .GLOBL $LOAD,CHAIN ; ; System definitions ; .ASECT .MCALL .COM,.ERR,.CLP,.FLG,.IOD ;dcn definitions .MCALL .EXIT,.LOOKU,.PURGE,.READW ;rt-11 macros .COM ;common definitions .ERR ;.exit return codes .CLP ;rt-11 monitor area definitions .FLG ;flag bit definitions .IOD ;user process monitor area extension ; ; Module definitions ; FIDGET = 100 ;slop for stack pigs ; ; Stack frame area (lod) ; . = 0 BUFFER: .BLKW 256. ;(r3) buffer AREA: .BLKW 5 ;(r4) argument block FLAGS: .BLKW 1 ;modifier bits CHNADR: .BLKW 1 ;chain area pointer (r0 to prog) ARGEND = . ;end of stack dsect .PAGE ; ; Procedure segment ; .PSECT $USEI,RO,I ; ; Absolute loader ; ; Note: this routine is activated by the rt-11 emulator either as the ; Result of a $load or .chain programmed request. it exits either to ; The loaded program or via .exit back to the cli or telnet server. ; ; Arguments: file name in rad50: locs chnadr-chnadr+7 ; ; Modifier bits (r0 at call for $load) ; 100000 do not load chain area (locs chnadr-c(42)) ; 040000 do not load cache area (locs 34-52) ; 020000 do not start program after loading ; ; Jsw bits ; Virt$ position independent ; CHAIN: MOV #100000,@#JSW ;do not load chain area $LOAD: JSR PC,SRESET ;reset program CLR IOHERR(R5) ;.trpse CLR IOHFPA(R5) ;.sfpa CLR IOHNCA(R5) ;.snca CLR IOHSCC(R5) ;.scca BIC #SERBIT,IOHFLG(R5) ;.herr JSR PC,TRPENB ;enter user mode MOV @#SYSPTR,R5 ;get addressability MOV IOHBRK(R5),SP ;reset sp MOV IOHBOT(R5),R1 ;get chain info pointer BNE 1$ ;branch if foreground MOV #500,R1 ;background. use official address 1$: MOV R1,R2 ;is there enough room for temps ADD #ARGEND+FIDGET,R2 ;(allow for stack fidget) CMP R2,SP BHIS LDR12 ;branch if no SUB #ARGEND,SP ;yes. make room on stack MOV SP,R3 ;buffer pointer MOV R3,R4 ADD #AREA,R4 ;rt-11 argument area pointer MOV @#JSW,FLAGS(R3) ;save modifier bits MOV R1,CHNADR(R3) ;save chain address .PURGE #17 ;blast former resident TST 2(R1) ;is this a real file BEQ 2$ ;branch if no .LOOKU R4,#17,R1 ;(use channel 17 for safety) BCC LDR13 ;branch if no error 2$: MOVB #ER.FNF,@#ERRBYT+1 ;file not found .EXIT ; ; Read block zero and decode control information ; LDR13: .READW R4,#17,R3,#256.,#0. ;read control block BCC 1$ ;branch if no error JMP LDR23 ; 1$: MOV USRTOP(R3),R2 ;compute size of load module ADD #2,R2 CMP USERPC(R3),R2 BHIS 5$ ;branch if invalid start address CMP USERSP(R3),R2 BHIS 5$ ;branch if invalid stack address TST SYSPTR(R3) BNE 5$ ;branch if invalid system pointer MOV JSW(R3),R0 ;get jsw BIT #CHAIN$,R0 ;is override bit set in jsw BEQ 2$ ;branch if no BIC #CHAIN$,R0 ;yes. don't do that BIC #100000,FLAGS(R3) ;make sure load chain area 2$: TST FLAGS(R3) ;is chain indicated BPL 3$ ;branch if no BIS #CHAIN$,R0 ;yes. so indicate 3$: MOV R0,@#JSW BIT #VIRT$,R0 ;is this position independent BEQ 4$ ;branch if no BIS #140000,FLAGS(R3) ;yes. do the right thing MOV IOHBRK(R5),R1 ;use upper program break CMP R2,R1 ;will it fit BHI LDR12 ;branch if no SUB R2,R1 ;maybe. relocate downward CMP R1,IOHBOT(R5) ;will it fit BLO LDR12 ;branch if no MOV R1,R0 ;yes. reset program break ADD USERSP(R3),R0 MOV R0,IOHBRK(R5) CMP R1,SP ;move sp down if necessary BHIS LDR11 MOV R1,SP BR LDR11 ; 4$: MOV IOHBOT(R5),R1 ;non-virtual. is this background proc BEQ 6$ ;branch if yes 5$: MOVB #ER.FMT,@#ERRBYT+1 ;bad file format .EXIT ; 6$: MOV R2,R0 ;compute high limit ADD R1,R0 ADD #FIDGET,R0 ;(allow for stack fidget) CMP R0,SP ;is it too large BLO LDR11 ;branch if no LDR12: MOVB #ER.BIG,@#ERRBYT+1 ;program too large .EXIT ; LDR11: MOV #500,R0 ;get loading offset ROL FLAGS(R3) ;is suppress load chain area set BCC 1$ ;branch if no MOV #1000,R0 ;yes. start at end of chain area 1$: ADD R1,USERPC(R3) ;relocate start address ADD R1,USERSP(R3) ;relocate stack address ADD R1,USRTOP(R3) ;relocate highest address ROL FLAGS(R3) ;is cache load requested BCS LDR10 ;branch if no MOV TRPVEC(R3),@#TRPVEC ;initialize trap vector BEQ 2$ ADD R1,@#TRPVEC 2$: MOV TRPVEC+2(R3),@#TRPVEC+2 MOV USERPC(R3),@#USERPC ;initialize start address MOV USERSP(R3),@#USERSP ;initialize stack address MOV USRBGN(R3),@#USRBGN ;initialize usr address (not used) BEQ 3$ ADD R1,@#USRBGN 3$: MOV USRTOP(R3),@#USRTOP ;initialize highest address ; ; Load file into memory region ; LDR10: ADD R0,R1 ;compute initial load address SUB R0,R2 ;compute size (words) INC R2 CLC ROR R2 ADD R3,R0 1$: CMP R0,R4 ;is block zero loaded BHIS 2$ ;branch if yes MOV (R0)+,(R1)+ ;no. copy next word DEC R2 BEQ LDR17 ;branch if odd (weird) BR 1$ ; 2$: MOV USERSP(R3),-(SP) ;save stack address MOV CHNADR(R3),-(SP) ;save chain area pointer MOV USERPC(R3),-(SP) ;save start address MOV FLAGS(R3),-(SP) ;save modifier bits .READW R4,#17,R1,R2,#1. ;read root segment BCC LDR17 ;branch if no error LDR23: .PURGE #17 ;leave no trash about MOVB #ER.INP,@#ERRBYT+1 ;input error .EXIT ; LDR17: ROL (SP)+ ;is start requested BCS 2$ ;branch if no MOV (SP)+,R1 ;yes. is start address valid BIT #1,R1 BNE 1$ ;branch if no MOV (SP)+,R0 ;yes. set up and dive in MOV @SP,SP JMP @R1 ;bonzai!! ; 1$: MOVB #ER.STR,@#ERRBYT+1 ;invalid start address 2$: .EXIT ; .END