TITLE IMPRUN	IMP DRIVER PROGRAM
SUBTTL DEFINITIONS

	ENTRY	.$INIT,.$CCIN
	INTERNAL	%%TRAP,MONITOR
	ENTRY	$IMPXT
	INTERNAL	RUNDEV,RUNFILE,RUNPPN
	INTERNAL	CCL,BATCH
	ENTRY	PDEC

	EXTERNAL	ERRMSG
	EXTERNAL	$SIGNAL,%GO,$FINIT
	EXTERNAL	$INITIO,$INITSTACK,$INITHEAP,CPU
	EXTERNAL	STACKSIZE,STACKTOP,STACKBASE

	TWOSEG	400000

	SEARCH	IMPPRM,C

IFNDEF FTAND20,<FTAND20=-1>


SUBTTL DRIVING CODE


; THIS SETS UP THE STACK, CALLS I/O INITIALISATION, THE MAIN PROGRAM AND
; THE I/O CLOSING ROUTINE BEFORE EXITING.

.$INIT:	TDZA	T1,T1		;START ADDRESS
.$CCIN:	SETO	T1,		;FOR CCL ENTRY
	MOVEM	T1,CCL		;SET CCL EXTERNAL
IFN FTAND20,<
	MOVEM	0,RUNFILE		;SAVE FILE NAME
	MOVEM	7,RUNPPN		;SAVE DIRECTORY
	MOVEM	11,RUNDEV		;SAVE DEVICE
>;END FTAND20
	SETZB	T3,CPU		;SET CPU INDICATOR
	MOVNI	T1,1		;DETERMINE PROCESSOR TYPE
	AOBJN	T1,.+1
	JUMPN	T1,CONT	;KA10 
	BLT	T1,0
	HRRZM	T1,CPU	;KL10 T1=1,1   ;  KI10 T1=0
	AOS	CPU		;SO KL10=2, KI10=1
CONT:
IFN FTAND20,<
	MOVEI	T1,677777
	MOVEM	T1,.JBREL	;FOR KL20
>;END FTAND20
	SETZM	BATCH		;SET BATCH INDICATOR
	MOVNI	T1,-1
	CTLJOB	T1,
	SETOM	BATCH		;A BATCH JOB
	RESET
	MOVE	T1,[XWD 34,11]	;MONITOR VERSION
	GETTAB	T1,
	  SETZ	T1,
	HRRZ	T1,T1
	LSH	T1,-6		;GET JUST MAIN RELEASE NUMBER
IFN FTAND20,<
	MOVEM	T1,MONITOR
	JUMPN	T1,CONT1	;CONTINUE IF NON-ZERO
	MOVE	T1,CPU
	CAIN	T1,2		;IF ZERO AND CPU=KL THEN A DEC-20
	JRST	[AOS	CPU
		JRST	CONT2]
>;END FTAND20
IFE FTAND20,<
	SKIPN	T1
>;END FTAND20
	MOVEI	T1,503
	MOVEM	T1,MONITOR	;OTHERWISE A 503 OR PREVIOUS MONITOR
IFN FTAND20,<
CONT1:	MOVE	T1,.JBFF
	MOVEM	T1,.JBREL	;RESET JBREL IF NOT KL-20
CONT2:
>;END FTAND20
	SETZ	T1,		;FOR THIS JOB
	RUNTIME	T1,		;GET RUNTIME
	MOVEM	T1,.RUN	;STORE
	MOVE	T3,CPU		;GET CPU INDICATOR
	SUBI	T3,3
	JUMPE	T3,[MSTIME	T1,
		 JRST	CONT3]
	MOVE	T1,[XWD 53,11]  ;UNIVERSAL DATE-TIME
	GETTAB	T1,
	  SETZ  T1,
CONT3:	MOVEM	T1,.ELAP	;STORE ELAPSED TIME
	MOVEI	T1,%%TRAP	;GET THE CORE EXPANSION TRAP ADDRESS
	MOVEM	T1,.JBAPR	;AND SAVE
IFE FTAND20,<
	MOVEI	T1,AP.REN!AP.POV!AP.FOV!AP.AOV!AP.ILM	;GET ERROR CONDITIONS
>;END FTAND20
IFN FTAND20,<
	MOVEI	T1,AP.REN!AP.POV!AP.FOV!AP.AOV ;GET THE ERROR CONDITIONS
	SKIPE	T3		;SKIP IF DEC-20
	IORI	T1,AP.ILM	;ADD TRAP FOR ILL. MEM. REFS
>;END FTAND20
	APRENB	T1,		;AND ENABLE TRAPPING
	MOVEI	T1,.$REEN	;SET UP REENTER CODE
	MOVEM	T1,.JBREN	;AND STORE IT
	MOVE	P,[-^D25,,.WORK];GET TEMPORARY WORK PDL
	SETZ	BASE1,		;NOTE ZERO RETURN
	CALL	$INITIO		;SET UP INPUT OUTPUT STREAMS
	CALL	$INITSTACK	;SET UP STACK
	CALL	$INITHEAP	;AND HEAP
	CALL	%GO		;GO TO IMP PROGRAM

$IMPXT:	CALL	$FINIT		;FINISH UP ROUTINE TO CLOSE FILES
;NOW PRINT RUN AND ELAPSED TIME
	SETZ	T1,		;FOR THIS JOB
	RUNTIM	T1,		;GET RUNTIME
	SUBB	T1,.RUN	;MAKE INCREMENTAL AND STORE
	OUTSTR	[ASCIZ/
IMP: Cpu time /]
	MOVE	P,[-^D25,,.WORK] ;SET UP STACK
	IDIVI	T1,^D1000	;GET NUMBER OF SECS
	CAIG	T1,^D60		;IS IT MORE THAN A MINUTE?
	JRST	[PUSHJ	P,PDEC	;JUST PRINT SECONDS
		 JRST	XT0]
	PUSHJ	P,PTIME		;PRINT IT
XT0:	OUTCHR	["."]		;DECIMAL POINT
	MOVE	T1,.RUN
	IDIVI	T1,^D1000
	MOVE	T1,T2		;GET FRACT PART
	ADDI	T1,5
	IDIVI	T1,^D10		;ACCURATE TO 2 DECIMAL PLACES
	PUSHJ	P,PDEC2		;PRINT IT
	OUTSTR	[ASCIZ/ Elapsed /]
IFN FTAND20,<
	MOVE	T3,CPU		;GET CPU INDICATOR
	SUBI	T3,3
	JUMPE	T3,[MSTIME	T1,	;FOR KL-20 GET TIME OF DAY
		 SUBB	T1,.ELAP	;MAKE INCREMENTAL AND STORE
		 IDIVI	T1,^D1000	;MAKE INTO SECONDS
		 JRST	XT1]
>;END FTAND20
	MOVE	T1,[XWD 53,11]	;UNIVERSAL DATE TIME
	GETTAB	T1,
	  SETZ	T1,
	SUBB	T1,.ELAP		;STORE IT
	IMULI	T1,^D24		;GET HOURS
	HLRZ	T2,T1			;SAVE
	HRRZ	T1,T1			;KEEP SECS AND MINS
	IMULI	T2,^D3600		;GET HOURS AS SECS
	IMULI	T1,^D3600		;AND HOURS AND MINS
	HLRZ	T1,T1
	ADD	T1,T2			;ADD THEM TOGETHER
XT1:	MOVEM	T1,.ELAP		;SAVE NUMBER OF SECONDS
	PUSHJ	P,PTIME			;PRINT IT
	EXIT	0,		;CLOSE THE FILES


%%TRAP:	MOVEM	T1,SAVAC	;SAVE THE T1 CONTENTS
	MOVE	T1,.JBCNI	;GET ERROR CONDITION
	TRNE	T1,AP.ILM	;IS IT AN ILL MEM REF?
	JFCL	17,%ILM		;YES
	TRNE	T1,AP.POV	;IS IT PDL OV?
	JFCL	17,%POV		;YES
	TRNE	T1,AP.AOV	;IS IT ARITH OVERFLOW?
	JRST	%ARITH		;YES
;THIS CODE LATER FOR CORE ALLOC
;	MOVE	T1,.JBTPC	;GET PC
;	MOVE	T1,(T1)	;GET THE INSTRUCTION TRAPPED ON
; **** CHECK FOR BLT, OR SETMM
;	CAMN	T1,[ SETMM P,(P) ]	;IS IT SPECIAL PLANTED INSTRUCTION
;	JFCL	17,%ALLOC		;YES, GET SOME CORE
ILM:	OUTSTR	[ ASCIZ/
?IMP: Ill Mem Ref at user pc /]
	JRST	ABORT
POV:	OUTSTR[ASCIZ/
?IMP: PDL Overflow at user pc /]
ABORT:
	MOVE	T1,SAVAC	;GET OLD VALUE
	MOVEM	17,ST17
	MOVEI	17,SAC0
	BLT	17,ST16	;SAVE ACS
	HRRZ	T1,.JBTPC
	MOVE	P,[-^D25,,.WORK] ;SET UP STACK
	PUSHJ	P,POCT		;PRINT LOCATION
	HRLZI	17,SAC0
	BLT	17,17		;RESTORE ACS
	EXIT	1,

%ILM:	MOVE	T1,.JBTPC	;GET PC
	HLRZ	T1,(T1)	;GET LH OF INSTRUCTION
	CAIN	T1,416017	;IS IT A SETMM N(P)  - I.E.A PLANT
	JRST	ILM1		;YEP- GET ADDRESS
	MOVE	T1,.JBTPC	;GET IT AGAIN
	LDB	T1,[POINT 4,(T1),17]; GET INDEX REGISTER
	CAIE	T1,P		;IS IT THE STACK POINTER?
	JRST	ILM	;NO, GENUINE ERROR
	HRR	T1,P	;GET LOC
	JRST ILM2	;CARRY ON
ILM1:	MOVE	T1,.JBTPC	;GET PC
	MOVEI	T1,@(T1)	;GET REQUIRED ADDRESS
ILM2:	SKIPLE	STACKSIZE	;HAS STACKSIZE BEEN SET?
	  JRST	ILM		;YES SO DO NOT EXPAND
	CAMLE	T1,STACKBASE	;<=THAN CURRENT BASE OF STACK?
	JRST	%ALLOC		;NO, GO GET IT
	JRST	ILM		;ERROR

%POV:	
	JRST	%ILM		;**TEMP**
	MOVE	T1,.JBTPC	;GET PC
	LDB	T1,[POINT 4,(T1),12];GET AC NUMBER
	CAIE	T1,P		;IS IT OF THE PROCEDURE STACK
	JRST	POV		;NO DIFFERENT PDL- ERROR
	ERROR	2,2,0,IMPSTR<Procedure stack full>

%ARITH:	 OUTSTR [ASCIZ/?Arithmetic overflow at user PC /]
	MOVE	T1,SAVAC	;GET OLD VALUE
	MOVEM	17,ST17
	MOVEI	17,SAC0
	BLT	17,ST16	;SAVE ACS
	HRRZ	T1,.JBTPC
	MOVE	P,[-^D25,,.WORK] ;SET UP STACK
	PUSHJ	P,POCT		;PRINT LOCATION
	HRLZI	17,SAC0
	BLT	17,17		;RESTORE ACS
	OUTSTR	[ASCIZ/
/]
	JRSTF	@.JBTPC		;RETURN
	MOVE	ARG3,.JBTPC
	ERROR	1,1,ARG3,IMPSTR<?Arithmetic overflow at user PC >


%ALLOC:	LSH	T1,-11		;MAKE INTO P
	MOVEM	T1,.TOPPAGE	;SAVE VALUE
	SETZM	.PARGS
	AOS	.PARGS		;1 ARGUMENT
	MOVE	T1,STACKTOP	;GET CURRENT TOP OF STACK
	LSH	T1,-11		;MAKE INTO PAGES
	MOVEM	T1,.PARGS+1	;SAVE IT
GETPAGE:AOS	.PARGS+1	;NEW PAGE REQUIRED
	MOVE	T1,[ 1,,.PARGS]
	PAGE.	T1,		;GET IT
	  JRST	NOCORE		;FAILED
	HRRZ	T1,.PARGS+1
	CAME	T1,.TOPPAGE	;GOT THEM ALL?
	JRST	GETPAGE		;NO, GET ANOTHER
	LSH	T1,11		;CONVERT TO WORDS
	IORI	T1,777		;END OF PAGE ADDR
	MOVEM	T1,STACKTOP	;SAVE NEW VALUE
	MOVE	T1,SAVAC	;RESTORE AC
	JRSTF	@.JBTPC		;CARRY ON

GOVIRT:MOVE	T1,.PARGS+1	;GET PAGE NUM
	TLO	T1,200000	;SET VIRT BIT
	SOJ	T1,
	MOVEM	T1,.PARGS+1	;FOR SAME PAGE
	JRST	GETPAGE		;TRY AGAIN

NOCORE:	CAIN	T1,12		;RUN OUT OF CORE?
	JRST	GOVIRT		;YES
	ERROR	2,1,T1,IMPSTR<Stack space full>

;THE REENTER CODE HAS TO STEP ON TILL IT KNOWS IT IS IN THE BODY OF A
;BLOCK, WHICH IT KNOWS AS SOON AS IT FINDS A JUMP TYPE INSTRUCTION
.$REEN:	HRRZS	.JBOPC		;GET JUST THE ADDRESS
$REELP:	MOVEM	T1,ST1		;SAVE A WORK REGISTER
	LDB	T1,[POINT 9,@.JBOPC,8]; GET THE OP CODE OF THE INSTRUCTION
	CAIL	T1,252		;IS IT ANY OF THE JUMP
	CAILE	T1,377		;INSTRUCTIONS
	JRST	$XCTIT		;NO, THEN EXECUTE IT
	CAIGE	T1,277		;UNLESS IT IS AN ADD?
	CAIL	T1,270		;TYPE
	JRST	$XCTIT		;YES, DO IT
	CAIN	T1,263		;IS IT A POPJ - A RETURN
	HRRZM	P,.JBOPC	;YES, SAVE THE PREVIOUS PC
	HRRZ	J,.JBOPC	;GET THE PC THEN AND SIGNAL
	SETZ	AC,
	PRMERROR 0,-2,AC,IMPSTR<Program REENTERed>
$XCTIT:	MOVE	T1,ST1		;RESTORE T1
	XCT	@.JBOPC		;EXECUTE INTRUCTION
	AOS	.JBOPC		;STEP ON THROUGH THE PROGRAM
	JRST	$REELP		;AND CONTINUE

;	PTIME PRINTS THE TIME AS HRS:MINS:SECS
;	T1=TIME IN SECONDS

PTIME:	PUSH	P,T1		;SAVE TIME ON STACK
	IDIVI	T1,^D3600	;GET HOURS
	PUSHJ	P,PDEC		;PRINT IT
	OUTCHR	[":"]
	MOVE	T1,(P)
	IDIVI	T1,^D3600
	MOVE	T1,T2
	IDIVI	T1,^D60	;GET MINUTES
	PUSHJ	P,PDEC2	;PRINT IT
	OUTCHR	[":"]
	POP	P,T1
	IDIVI	T1,^D60
	MOVE	T1,T2
	PJRST	PDEC2	;PRINT IT

;	POCT	OUTPUTS A SIGNED OCTAL NUMBER TO THE TERMINAL
;	PDEC	OUTPUTS A SIGNED DECIMAL NUMBER TO THE TERMINAL
;	THE NUMBER IS PASSED IN AC AND IT ZAPS T1,T2,T3
;	PDEC2	OUTPUTS 2 DECIMAL DIGITS


PDEC2:	MOVEI	T3,^D10
	CAMGE	T1,T3
	OUTCHR	["0"]		;OUTPUT A LEADING ZERO IF NECESSARY
	JRST	PNUML

PDEC:	SKIPA	T3,[^D10]
POCT:	MOVEI	T3,^D8
	JUMPGE	T1,PNUML
	OUTCHR	["-"]
	MOVN	T1,T1
PNUML:	IDIV	T1,T3
	HRLM	T2,(P)
	SKIPE	T1
	PUSHJ	P,PNUML
	HLRZ	T1,(P)
	ADDI	T1,"0"
	OUTCHR	T1
	POPJ	P,

SUBTTL STORAGE


	RELOC	0


;GENERAL AC SAVING AREA

SAC0:	Z
ST1:	Z
SAC2:	Z
SAC3:	Z
SAC4:	Z
SAC5:	Z
SAC6:	Z
SAC7:	Z
ST10:	Z
ST11:	Z
ST12:	Z
ST13:	Z
ST14:	Z
ST15:	Z
ST16:	Z
ST17:	Z

;STORAGE FOR %%TRAP

SAVAC:	Z	;SAVE THE AC
.TOPPAGE:	Z	;TOP PAGE OF REQUIRED STACK
.PARGS:	BLOCK	2	;PAGE ARGUMENT BLOCK

;GLOBALS

CCL:	Z	;SET TO -1 IF PROGRAM ENTERED AT CCL ENTRY
BATCH:	Z	;SET TO -1 IF PROGRAM RUN UNDER BATCH
MONITOR: Z	;MONITOR NUMBER
RUNFILE:	Z	;RUN PROGRAMS FILE NAME
RUNDEV:	Z	;AND DEVICE NAME
RUNPPN:	Z	;AND DIRECTORY
.RUN:	Z	;STORE RUNTIME IN MILISECS
.ELAP:	Z	;STORE ELAPSED TIME IN MILISECS
.WORK: BLOCK ^D25	;WORK SPACE

	LIT

	END

