.TITLE MOSPM -- MICRO OPERATING SYSTEM PROCESSOR MANAGEMENT .INSRT ../moscnf-1.sml .INSRT ../mosmac.sml .INSRT ../mostbl.sml .ENABL ISD $CNFIG ;DEFINE SYSTEM CONFIGURATION $DFIOR $DFPCT $DFDCT $DFMQE $DFTQE .PAGE .GLOBL $BEGIN ;CODE START LOCATION .GLOBL $START ;SYSTEM INITIAL ENTRY POINT .GLOBL $MOS .GLOBL DSCHD ;SYSTEM SCHEDULER ENTRY POINT .GLOBL TYPE ;PRINT SYSTEM ERROR MESSAGES .GLOBL TYPEN ;PRINT NUMBERS IN DEBUGGING MESSAGES .GLOBL BITTBL ;BIT TABLE .GLOBL $IOCMP ;I/O COMPLETION ENTRY POINT .GLOBL $APCT, APCT ;ADDRESS OF ACTIVE PCT .GLOBL $APID, APID ;ACTIVE PROCESS' PID .GLOBL $APFLG ;ADDR OF ACTIVE PROCESS' CAP FLAGS .GLOBL SCHDFLG ;MARK SCHEDULER AS BEING NEEDED .GLOBL $TOD, TOD ;TIME-OF-DAY DOUBLE WORD .GLOBL $TIMQ ;TIMER QUEUE .GLOBL $INIPL ;STORAGE POOL INITIALIZER .GLOBL $GTBLK ;GET KERNEL STORAGE BLOCK .GLOBL $RLBLK ;RELEASE KERMEL STORAGE BLOCK .GLOBL $AVS ;ALLOCATE SYSTEM STORAGE .GLOBL $ALS ; ALLOCATE STORAGE(NO WAIT) .GLOBL $SCK ; STORAGE CHECK .GLOBL $FVS ;RELEASE SYSTEM STORAGE .GLOBL $MSTAT ;GATHER MEMORY STATISTICS .GLOBL $SIO ;ASYNCHRONOUS START I/O .GLOBL $SIN ;SYNC STRING INPUT FROM PRIMARY DEV .GLOBL $SOUT ;SYNC STRING OUTPUT TO PRIMARY DEV .GLOBL $BIN ;SYNC BYTE INPUT FROM PRMARY DEV .GLOBL $BOUT ;SYNC BYTE OUTPUT TO PRIMARY DEV .GLOBL $SPRIO ;SET PRIMARY I/O DEVICES .GLOBL $STI ;SIMULATE TERMINAL INPUT .GLOBL $DCTVT ;DEVICE CONTROL TABLE VECTOR TABLE .GLOBL $PCTVT ;PCT VECTOR TABLE .GLOBL $CVPCT ;PID => PCT ADDR CONVERSION .GLOBL $ENQ,$DEQ,$QDEL .GLOBL $NETID ; STORED NETWORK ID .GLOBL $HSTID ; STORED TERMINAL ID .GLOBL BHTRST ;RESTART ON BUGHALT FLAG .GLOBL LSTMSG ;LAST BUGHALT MESSAGE STORED HERE .IF NE, KF.DDT .GLOBL MOSDDT ;DDT LINKED FLAG .GLOBL DDT ;DEFINE DDT ENTRY POINT .GLOBL D.ERRT, D.NXMT ;To set up the vectors .GLOBL D.ILGT, D.BRK .ENDC .IF NE, KF.CSM .GLOBL $CHKSM ;CODE SPACE CHECKSUMMER .ENDC .IF NE, KF.TRC .GLOBL TRCFLG ;TRACING ENABLED FLAG .GLOBL TRCADR ;TRACE ADDRESS .GLOBL TRCVAL ; AND ITS VALUE .ENDC .GLOBL $ERRA ;NO PROCESS WITH STK ROOM FOR INT HALT .GLOBL $ERR0 ;RETURN FROM MAIN ROUTINE HALT .GLOBL $ERR1 ;STACK OVERFLOW ERROR HALT .GLOBL $ERR2 ;UNDEFINED EMT EXIT ERROR HALT .GLOBL $ERR3 ;INVALID EMT CODE ERROR HALT .GLOBL $ERR4 ;BAD DCT ADDRESS ERROR HALT .GLOBL $ERR5 ;KERNEL STORAGE EXHAUSTED ERROR HALT .GLOBL $ERR6 ;INVALID PID ERROR HALT .GLOBL $ERR7 ;NO FREE STORAGE ERROR .IF NE, KF.DBG ;IF SUPPORTS PROCESS DEBUGGING .GLOBL $ERR8 ;INVALID SET/REMOVE EXIT CALL .GLOBL $ERR9 ;INVALID BREAKPOINT/TRACE TRAP .ENDC .GLOBL $MPMTP,$MPMBT ;TOP AND BOTTOM OF MOS CODE SPACE HIPRI = 340 ;High priority ROBNID = 175002 ;ROBUSTNESS CARD REGISTER ADDRS ROBHID = 175000 ;NETWORK ID - HOST ID (BYTE) STKGRD = 123456 ;STACK GUARD WORD VALUE .PAGE .SBTTL OPERATING SYSTEM INITIALIZER .CSECT MOS $MPMTP: $BEGIN: .IF NE, KF.DDT ;IF DEBUGGING W/ DDT TST MOSDDT ;ARE WE LINKED W/ DDT? BEQ $START ;IF NOT, ENTER MOS INITIALIZER JMP @(PC)+ ;ELSE ENTER DDT MOSDDT: .WORD DDT ;START ADDRESS OF DDT, IF LINKED IN .ENDC $START: $MOS: $DSABL ;TURN OFF INTERRUPTS WHILE INITIALIZING RESET MOV $PCTVT+2,SP ;SET-UP TEMPORARY STACK IN ADD #PCTLEN-2,SP ; PCT #1 .IF NE, KF.CSM JSR PC,$CHKSM ;CALCULATE INITIAL CODE SPACE CHKSUM .ENDC ; INITIALIZE SYSTEM TRAP LOCATIONS .IF NE, KF.DBG MOV #ERR9,BPTSAV ;RESET BPT HANDLER ADDR .ENDC CLR R0 ;INIT POINTER TO BOTTOM OF CORE .IF NE, KF.DDT ;IF DEBUGGING W/ DDT TST MOSDDT ;LINKED IN WITH DDT? BEQ 11$ ;IF NOT, CLEAR STARTING FROM 0 MOV #HIPRI,R1 ;Else set up DDT's vectors in case sys MOV #D.ERRT,(R0)+ ;was started directly and not by DDT MOV R1,(R0)+ ;Bad trap MOV #D.NXMT,(R0)+ ;NXM MOV R1,(R0)+ MOV #D.ILGT,(R0)+ ;Ill inst MOV R1,(R0)+ MOV #D.BRK,(R0)+ ;BPT/single step MOV R1,(R0)+ .IF NE, KF.DBG MOV @#14,BPTSAV ;REMEMBER DDTS BPT HANDLER ADDR .ENDC 11$: .ENDC MOV R0,R1 ;R0 POINTS TO FIRST PC/PS PAIR ADD #2,R1 ;NEW PC WORD WILL POINT TO PS WORD .IF NE, KF.DDT MOV #BPT,R2 ;EXECUTE A BREAKPOINT TST MOSDDT ;IF DDT THERE BNE 12$ .ENDC MOV #HALT,R2 ;IF NOT, JUST HALT 12$: MOV R1,(R0)+ ;POINT NEW PC WORD TOWARDS PS WORD MOV R2,(R0)+ ADD #4,R1 ;ADVANCE COUNTER CMP R0,#$BEGIN ;REACHED END OF VECTOR AREA? BLO 12$ ;IF NOT, LOOP .IF NE, KF.DBG MOV #$BPT,@#14 ;INIT 'BPT' VECTOR TO HANDLER MOV #340,@#16 .ENDC .IF NE, KF.PWR MOV #$PWRDN,@#24 ;INIT POWER-FAIL VECTOR MOV #340,@#26 .ENDC MOV #$EMT,@#30 ;INIT 'EMT' VECTOR TO DISPATCH ROUTINE MOV #340,@#32 ;DON'T ALLOW OTHER INTERRUPTS MOV #$BUGHT,@#34 ;INIT 'TRAP' VECTOR TO ERROR HANDLER MOV #340,@#36 ;DON'T ALLOW OTHER INTERRUPTS .IF NE, KF.TRC TST TRCADR BEQ 13$ BIS #20,@#32 ;AND SET TRACE FLAG MOV #$TRACE,@#14 ;OVERRIDE BPT HANDLER FOR TRACING .ENDC ; INITIALIZE THE TIMER 13$: CLR $TOD ;RESET TIME-OF-DAY COUNTER CLR $TOD+2 CLR $TIMQ ;RESET TIMER QUEUE HEAD MOV #$TIMQ,$TIMQ+2 ; AND POINT TAIL AT HEAD POINTER MOV #3600.,MINTIM ;RESET TIMER COUNTERS MOV MINTIM,TIMLFT ; AND DOWN COUNTER MOV #$TIMER,@#100 ;INIT LINE CLOCK VECTOR MOV #340,@#102 .IF NE, KF.TRC TST TRCADR BEQ 14$ BIS #20,@#102 ;AND SET TRACE FLAG 14$: .ENDC .IF EQ, P1103 ;IF RUNNING ON ANYTHING BUT LSI-11 BIS #100,@#177546 ;ENABLE KW-11L INTERRUPTS .ENDC ; INITIALIZE HSTID AND NETID FROM HARDWARE SWITCHES $PUSH @#4,@#6 ; SAVE TIMEOUT VECTOR WORDS MOV #NOROB,@#4 ; NEW TIMEOUT VADDR MOV #340,@#6 ; NEW TIMEOUT PS MOV @#ROBNID,$NETID ; GET NETID CLR $HSTID ; LO BYTE ONLY MOVB @#ROBHID,$HSTID ; GET TIUID SWAB $NETID ; YECCHHHHHH! MOST NATURAL WAY SWAB $HSTID ; TO USE SWITCHES IS REVERSED BR IDIN ; SKIP DEFAULTING CODE NOROB: CMP (SP)+,(SP)+ ; POP INT PS AND PC IDIN: $POP @#6,@#4 ; RESTORE TIMEOUT VECTOR WORDS ; INITIALIZE THE PACKET FREE STORAGE POOL JSR PC,$INIPL ;INITIALIZE PACKET STORAGE POOL ; INITIALIZE THE DEVICE CONTROL TABLES MOV #$DCTVT,R2 ;ADDRESS OF VECTOR TABLE MOV (R2)+,R0 ; AND NUMBER OF DCTS 1$: MOV (R2)+,R1 ;GET POINTER TO DCT TABLE CLR DCTQH(R1) ;RESET HEAD POINTER MOV R1,DCTQT(R1) ADD #DCTQH,DCTQT(R1) ; AND TAIL POINTER MOV #DF.OFL,DCTFLG(R1) ;MARK DEVICE AS UN-INITED $LOOP R0,1$ ;AND HIT ALL OF THEM ; INITIALIZE THE USER EMT EXIT TABLE MOV #$UMTBL,R2 ;GET POINTER TO USER TABLE MOV (R2)+,R1 ;AND THE NUMBER OF ENTRIES 2$: MOV #ERR2,(R2)+ ;RESET POINTER TO ERROR TRAP $LOOP R1,2$ ; NOW INITIALIZE THE PROCESS CONTROL TABLES INIPCT: MOV #$PCTVT,R2 ;INIT POINTER TO PCT AREA MOV (R2)+,R0 ;GET NUMBER OF PCTS ALLOCATED ININXT: MOV (R2)+,R1 ;GET PCT CLR PCTMQH(R1) ;RESET MESSAGE QUEUE HEAD POINTER MOV R1,PCTMQT(R1) ADD #PCTMQH,PCTMQT(R1) ; AND TAIL POINTER MOV PCTDPI(R1),PCTPRI(R1) ;SET INITIAL PRIMARY INPUT MOV PCTDPO(R1),PCTPRO(R1) ; AND OUTPUT DEVICES MOV #STKGRD,PCTSGD(R1) ;SET THE STACK GUARD WORD MOV R1,SP ADD #PCTSTK+STKLEN,SP ;ADV STACK POINTER TO END OF SAVE AREA $PUSH #ERR0 ;INCLUDE FAULT CATCHER AS CUSHION CLR -(SP) ;PUSH INITIAL PS OF ZERO .IF NE, KF.TRC TST TRCADR BEQ 1$ BIS #20,(SP) ;AND SET TRACE FLAG .ENDC 1$: BIS #PS.RDY!PS.NDB,PCTFLG(R1) ;FLAG PROCESS AS 'READY,' ; NOT BEING DEBUGGED, BIC #PS.NPL!PS.SPN,PCTFLG(R1) ; AND NOT INSIDE SYSTEM CALL ; AND NOT SUSPENDED MOV PCTENT(R1),-(SP) ;PUSH START PC AS THE ENTRY POINT BNE 2$ ;IF PC = 0, DON'T RUN PROCESS BIS #PS.FZN,PCTFLG(R1) ;INDICATE PROCESS FROZEN 2$: MOV #EXIT,-(SP) ;RESUME ADDRESS IS AN RTT SUB #6*2,SP ;ADJUST STACK FOR REGISTERS R0 - R5 MOV SP,PCTSP(R1) ;REMEMBER RESUME STACK POINTER CLR PCTDBG(R1) ;RESET PID/OPC OF DEBUGGING PROCESS $LOOP R0,ININXT ;FOR ALL ALLOCATED PCTS MOV R1,R5 ;POINT TO LINK TO FIRST PROC CLR $APCT ;NO PREVIOUS PROCESS BR FNDNXT ;ENTER SCHEDULER WHEN DONE EXIT: $RTT ;ENTER PROCESS DIRECTLY FIRST TIME ERR0: BUGHLT ;RETURN FROM MAIN ERROR $ERR0: NOP .PAGE .SBTTL SYSTEM ERROR HANDLER ; CALLED WITH: (SP) - START OF ASCIZ ERROR MESSAGE $BUGHT: $PUSH R0,R1 MOV #BUGHMS,R0 ;GET ADDR OF ERROR MSG JSR PC,TYPE ;TYPE "BUGHLT: " MOV 4(SP),R0 ;GET RETURN ADDR, START OF ERR TXT MOV #LSTMSG,R1 ;STORE MESSAGE AT LSTMSG 3$: MOVB (R0)+,(R1)+ BNE 3$ MOV 4(SP),R0 ;GET RETURN ADDR, START OF ERR TXT JSR PC,TYPE ;TYPE ERROR MESSAGE TEXT INC R0 ;ROUND UP, MAKING REAL RETURN ADDR BIC #1,R0 ; AFTER END OF MSG STRING MOV R0,4(SP) ;AND PATCH RETURN ADDR MOV #CRLF,R0 JSR PC,TYPE ;TYPE CR/LF $POP R1,R0 TST BHTRST ;RESTART AFTER BUGHALTS BEQ 2$ ;IF TOO MANY, STOP DEC BHTRST ;ONLY RESART SO MANY TIMES JMP $MOS ;START OVER 2$: .IF NE, KF.DDT TST MOSDDT ;LINKED WITH DDT? BEQ 1$ ;IF NOT, SKIP JMP @14 ;AND ENTER DDT'S BREAKPOINT HANDLER .ENDC 1$: HALT ;HALT BR 1$ .CSECT MOSDAT, STATIC BUGHMS: .BYTE 15,12,177,177,177 .ASCIZ /BUGHLT: / LSTMSG: .ASCIZ /Reloaded/ ;Initial message .BLKB 55. ;Room for a longer message CRLF: .BYTE 15,12,0 .EVEN .CSECT MOS ; Printing subroutines; the first prints .ASICZ strings and the ; second prints octal numbers. TYPE: $PUSH R3 MOV #DLLOC+4,R3 ;POINTER TO REGS 1$: TSTB @R3 ;OUTPUT IDLE? BPL 1$ ;IF NOT, WAIT $PUSH @R3 ;SAVE STATE CLR @R3 ;RUN IN BUSY-LOOP MODE TYPEP: MOVB (R0)+,2(R3) ;TRANSFER DATA BYTE 1$: TSTB @R3 ;OUTPUT FINISHED? BPL 1$ ;NOPE, WAIT TSTB @R0 ;NULL BYTE? BNE TYPEP ;NO, NOT DONE YET $POP @R3,R3 ;RESTORE STATE RTS PC TYPEN: $PUSH R1,R2,R3 MOV #6,R2 ; Six digits max MOV #DLLOC+4,R3 ; POINTER TO REGS 1$: TSTB @R3 ; OUTPUT IDLE? BPL 1$ ; IF NOT, WAIT $PUSH @R3 ; SAVE STATE CLR @R3 ; RUN IN BUSY-LOOP MODE TYPENL: MOV R0,R1 ; Get remainder mod 8 BIC #-10,R1 ADD #60,R1 ; Convert to ASCII digit $PUSH R1 ; and save it $ASH -3,R0 ; Divide by 8 DEC R2 ; Last digit? BNE 1$ ; No, maybe go round again? BIC #6,@SP ; Yes, patch last digit to 1 BR TYPENP ; And type the whole thing 1$: TST R0 ; Any bits left? BEQ TYPENP ; No, type the ones I have CALL TYPENL ; Call self recursively TYPENP: $POP 2(R3) ; Print char 1$: TSTB @R3 ; Printer done? BPL 1$ ; No, wait INC R2 CMP R2,#6 ; Done? BNE TYPENP ; No, next char $POP @R3,R3,R2,R1 ; Restore state RET .PAGE .SBTTL OPERATING SYSTEM SCHEDULER DSCHD: $PUSH R0,R1,R2,R3,R4,R5 MOV $APCT,R5 ;GET POINTER TO PROCESS CONTROL TABLE CMP PCTSGD(R5),#STKGRD ;OVERFLOW DETECT WORD STILL INTACT? BNE ERR1 ;IF NOT, BRANCH TO ERROR HALT MOV SP,PCTSP(R5) ;SAVE AWAY STACK POINTER MOV R5,R4 ;FALL THROUGH TO CHECK NEXT PROC FIRST FNDNXT: MOV PCTLNK(R5),R5 ;GET LINK TO NEXT PCT BIT #PS.RDY,PCTFLG(R5) ;READY TO BE AWAKENED? BEQ 1$ ;IF NOT, DON'T RUN BIT #PS.SPN,PCTFLG(R5) ;PROCESS SUSPENDED FOR ANY REASON? BEQ RUNPR ;IF NOT, RUNNABLE 1$: CMP R5,R4 ;GONE AROUND PROCESS LOOP? BNE FNDNXT ;NO, KEEP LOOKING ;FALL THROUGH TO IDLE PROCESSOR GETSTK: MOV SP,R0 ;MAKE SURE THERE'S ROOM IN THIS STACK SUB R5,R0 ;TO RUN AN INTERRUPT CMP R0,#PCTSTK+STKINT BGE ACTWT ;IF SO, WAIT FOR ACTIVITY MOV PCTLNK(R5),R5 ;IF NOT, TRY ANOTHER PROCESS' STACK CMP R5,R4 ;BACK TO ORIGINAL PROCESS? BEQ ERRA ;YES, NOBODY WITH ENOUGH ROOM, CROAK MOV PCTSP(R5),SP ;NO, TRY HIS ON FOR SIZE BR GETSTK ACTWT: CLR SCHDFLG ;GET READY TO SEE INT'S AS I EXIT $ENABL ;ALLOW INTERRUPTS TST SCHDFLG ;IN AN INT HAPPENED AFTER THE LAST BNE 10$ ;INST, THAT WOULD BE NON-ZERO .IF NE, KF.SCD $DSABL MOV #SWT,R0 ;SAY GOING TO SLEEP CALL TYPE $ENABL ;SAME RIGMAROLE ALL OVER AGAIN TST SCHDFLG ;SINCE I/O MAY HAVE HAPPENED BNE 1$ ;WHILE PRINTING OUT .ENDC WAIT ;WAIT FOR I/O ACTIVITY 10$: $DSABL ;AND TRY TO RUN SOMEONE BR FNDNXT RUNPR: MOV R5,$APCT ;REMEMBER ACTIVE PCT ADDRESS MOV R5,$APFLG ;GET ADDR OF NEW PCT ADD #PCTFLG,$APFLG ; AND CALCULATE ADDR OF FLAG BYTE MOVB PCTPID(R5),$APID ;SET ACTIVE PROCESS ID BEQ ERR1 ;CAN'T BE ZERO, PCT MUST BE BAD .IF NE, KF.SCD MOVB PCTPID(R5),R0 ;PRINT PROCID CALL TYPEN MOV #SSC,R0 ;AND MESSAGE ABOUT RUNNING HIM CALL TYPE .ENDC MOV PCTSP(R5),SP ;RESTORE STACK POINTER $POP R5,R4,R3,R2,R1,R0 ;RELOAD SAVED REGISTERS RTS PC ;AND RESUME INSIDE SYSTEM CALL ERR1: BUGHLT ;STACK OVERFLOW ERROR $ERR1: NOP ERRA: BUGHLT ;STACK OVERFLOW ERROR $ERRA: NOP .IF NE, KF.SCD .CSECT MOSDAT SWT: .ASCIZ /Wt/<12> SSC: .ASCIZ / Rn/<12> .EVEN .CSECT MOS .ENDC .IF NE, KF.PWR .PAGE .SBTTL POWER-FAIL INTERRUPT ROUTINES $PWRDN: .IF EQ, KF.PWR-2 ;IF CONTINUE ON POWER FAIL $PUSH R0,R1,R2,R3,R4,R5 ;SAVE REGISTERS MOV $APCT,R5 ;GET POINTER TO ACTIVE PCT MOV SP,PCTSP(R5) ;AND SAVE STACK POINTER .ENDC MOV #$PWRUP,@#24 ;POINT VECTOR TOWARDS POWER UP ROUTINE HALT ;WAIT FOR POWER TO COME ON $PWRUP: MOV #$PWRDN,@#24 ;POINT VECTOR TOWARDS PWR-DOWN ROUTINE .IF EQ, KF.PWR-1 ;IF RESTART ON POWER RESTORATION JMP $START ; JUMP TO OS INITIALIZATION ROUTINE .ENDC .IF EQ, KF.PWR-2 ;IF CONTINUE ON POWER RESTORATION MOV $APCT,R5 ;GET POINTER TO ACTIVE PCT MOV PCTSP(R5),SP ;GET SAVED STACK POINTER $POP R5,R4,R3,R2,R1,R0 ;RECOVER REGISTERS $RTT ;AND CONTINUE FROM INTERRUPTION .ENDC .ENDC .IF NE, KF.TRC .PAGE .SBTTL $TRACE - LOCATION MODIFICATION TRACE FACILITY $TRACE: TST TRCFLG ;CHECK TRACE FLAG BEQ TRCRTN CMP @TRCADR,TRCVAL ;LOCATION BEEN MODIFIED? BNE TRCRTN ;IF NOT, SKIP HALT TRCRTN: $RTT .CSECT MOSDAT TRCFLG: .WORD 0 TRCADR: .WORD 0 ;LOCATION TO MONITOR TRCVAL: .WORD 0 ; AND ITS CORRECT VALUE .CSECT MOS .ENDC .IF NE, KF.DBG .PAGE .SBTTL $BPT - BREAKPOINT/TRACE TRAP HANDLER $BPT: $PUSH R0,R1 MOV 4(SP),R1 ;GET ADDRESS OF TRAP MOV $APCT,R0 ;GET ACTIVE PCT BIT #PS.NDB,@$APFLG ;ANY ONE DEBUGGING THIS PROCESS BNE 2$ ;IF SET, NO ONE DEBUGGING IT BIS #PS.BPT,@$APFLG ;MARK AS SUSPENDED AT BPT MOV PCTDBG(R0),R0 ;GET OPC/PID OF DEBUGGING PROCESS BIT #20,6(SP) ;CHECK FOR TRACE TRAP BNE 1$ ;IF SO, SKIP SUB #2,R1 ;ELSE, BACK UP PC MOV R1,4(SP) ;AND PUT IT BACK ON THE STACK 1$: $SGNLI R0,R0,R1 ;NOTIFY DEBUGGING PROCESS $POP R1 JSR PC,SAVREG ;SAVE USER REGS IN SAVE AREA $POP R0 JSR PC,DSCHD ;AND ENTER SCHEDULER $RTT ;AND RESUME AFTER BREAKPOINT 2$: $POP R1,R0 MOV BPTSAV,PC ;AND ENTER BREAKPOINT HANDLER ERR9: BUGHLT ;INVALID BREAKPOINT/TRACE TRAP $ERR9: NOP ;FOR ADDRESS IN DDT .ENDC .PAGE .SBTTL $EMT - EMT TRAP HANDLER $EMT: $PUSH R0 ;SAVE R0 MOV 2(SP),R0 ;ADDRESS OF EMT INSTRUCTION + 2 MOV -(R0),R0 ;AND INSTRUCTION ITSELF BIC #377*400,R0 ;LEAVING EMT OPCODE TSTB R0 ;CHECK FOR SYSTEM OR USER EMT BPL USREMT ;IF <200, USER EMT CMP R0,$EMTBL ;CHECK VS MAX EMT DEFINED BGE ERR3 ;IF TOO BIG, ERROR .IF NE, KF.DBG BIT #PS.NDB!PS.NPL,@$APFLG ;NOT BEING DEBUGGED OR INSIDE EMT BNE 1$ ;IF SO, SKIP SAVING REGISTERS JSR PC,SAVREG ;COPY USER REGISTERS INTO SAVE AREA .ENDC 1$: ASL R0 ;CONVERT TO WRD INDEX MOV $EMTBL-376(R0),R0 ;AND GET ADDRESS OF HANDLER RTS R0 ;CALL HANDLER & RESTORE R0 USREMT: CMP R0,$UMTBL ;CHECK VS MAX EMT DEFINED BGE ERR2 ;IF TOO LARGE, NOT DEFINED ASL R0 ;CONVERT TO WORD INDEX MOV $UMTBL+2(R0),R0 ;AND GET ADDRESS OF HANDLER RTS R0 ;CALL HANDLER & RESTORE R0 .PAGE .CSECT MOSDAT $EMTBL: .WORD 0 ;NUMBER OF SYSTEM ENTRIES .WORD $WAIT ;$WAIT - EMT 200 .WORD $WAITS ;$WAITS - EMT 201 .WORD $WAITM ;$WAITM - EMT 202 .WORD $SGNLI ;$SGNLI - EMT 203 .WORD $SIO ;$SIO - EMT 204 .WORD $STIME ;$STIME - EMT 205 .WORD $ITIME ;$ITIME - EMT 206 .WORD $GETOD ;$GETOD - EMT 207 .WORD $SETOD ;$SETOD - EMT 210 .WORD $AVS ;$AVS - EMT 211 .WORD $FVS ;$FVS - EMT 212 .WORD $GAPID ;$GAPID - EMT 213 .WORD $SEMTX ;$SEMTX - EMT 214 .IF NE, KF.DBG .WORD $SEXIT ;$SEXIT - EMT 215 .WORD $REXIT ;$REXIT - EMT 216 .IFF .REPT 2 .WORD ERR2 .ENDR .ENDC .WORD $GPSTS ;$GPSTS - EMT 217 .IF NE, KF.DBG .WORD $GPREG ;$GPREG - EMT 220 .WORD $SPREG ;$SPREG - EMT 221 .WORD $THAWP ;$THAWP - EMT 222 .WORD $SUSPR ;$SUSPR - EMT 223 .IFF .REPT 4 .WORD ERR2 ;UNDEFINED SYSTEM CALL .ENDR .ENDC .WORD $SIN ;$SIN - EMT 224 .WORD $SOUT ;$SOUT - EMT 225 .WORD $BIN ;$BIN - EMT 226 .WORD $BOUT ;$BOUT - EMT 227 .WORD $SPRIO ;$SPRIO - EMT 230 .WORD $STI ;$STI - EMT 231 .WORD $GPNAM ;$GPNAM - EMT 232 .WORD $MSTAT ;$MSTAT - EMT 233 .WORD $ALS ;$ALS - EMT 234 .WORD $SCK ;$SCK - EMT 235 .TEMP=. .=$EMTBL .WORD 200+<.TEMP-$EMTBL/2> ;NUMBER OF ENTRIES IN $EMTBL .=.TEMP $UMTBL: .WORD NUEMTS ;NUMBER OF USER ENTRIES .REPT NUEMTS ;FOR REST OF THE TABLE .WORD ERR2 ;UNDEFINED EMT EXIT ERROR .ENDR .CSECT MOS ERR2: BUGHLT ;UNDEFINED EMT EXIT ERROR HALT $ERR2: NOP ERR3: BUGHLT ;INVALID EMT HALT $ERR3: NOP .IF NE, KF.DBG .PAGE .SBTTL SAVREG - SAVE PROCESS' OUTER-LEVEL REGISTERS ; ; CALLED WITH: 0(SP) - USER'S R0 ; 2(SP) - USER'S RETURN ADDRESS ; 4(SP) - AND PROGRAM STATUS ; SAVREG: $PUSH R0 MOV $APCT,R0 ;GET PCT ADDRESS BIS #PS.NPL,@$APFLG ;INDICATE INSIDE SYSTEM CALL ADD #PCTREG,R0 ;AND POINT TO REGISTER SAVE AREA MOV 4(SP),(R0)+ ;COPY USER'S R0 INTO IT MOV R1,(R0)+ ;R1.... MOV R2,(R0)+ MOV R3,(R0)+ MOV R4,(R0)+ MOV R5,(R0)+ ;THRU R5 MOV SP,(R0) ;GET STACK POINTER ADD #12,(R0)+ ;ADJUST FOR JUNK ON STACK MOV 6(SP),(R0)+ ;GET OUTER LEVEL PC MOV 10(SP),(R0)+ ; AND PS MOV #SYSEXT,6(SP) ;CHANGE RETURN PC TO REGISTER MOV #340,10(SP) ; RESTORE ROUTINE $POP R0 RTS PC .PAGE .SBTTL SYSEXT - OUTER-LEVEL REGISTER RESTORE SYSEXT: SUB #4,SP ;MAKE ROOM FOR RETURN PC/PS $PUSH R0 MOV $APCT,R0 ;GET PCT ADDRESS BIC #PS.NPL,@$APFLG ;INDICATE RETURNING TO USER LEVEL MOV PCTREG+<7*2>(R0),2(SP) ;SET PC OF USER PROCESS MOV PCTREG+<10*2>(R0),4(SP) ; AND RETURN PS $PUSH R1 MOV PCTDBF(R0),R1 ;GET 'REG CHANGE' FLAGS BIC #^C77,R1 ;AND CLEAR OTHER GARBAGE BEQ 3$ ;NONE CHANGED, EXIT $PUSH R2,R3,R4,R5 ;SAVE REST OF REGISTERS MOV SP,R2 ;GET STACK POINTER ADD #10.,R2 ;AND POINT TO R0 ON STACK MOV R0,R3 ;GET PCT ADD #PCTREG,R3 ; AND ADVANCE TO REG SAVE AREA 1$: ASR R1 ;TEST MASK BIT BCC 2$ ;SKIP IF REG NOT MODIFIED MOV (R3),(R2) ;ELSE, MOVE REG FROM AC BLOCK 2$: CMP (R3)+,-(R2) ;ADVANCE POINTERS TST R1 ;FINISHED? BNE 1$ ;IF NOT, TRY AGAIN $POP R5,R4,R3,R2 3$: $POP R1 BIC #77,PCTDBF(R0) ;CLEAR REGISTER MOD FLAGS $POP R0 $RTT ;AND RETURN .ENDC