;
;
;PDP-11 FLOATING POINT PACKAGE
;
RND00:	MOV	R0,-(SP)	;SAVE THE DESTINATION
	MOV	M.I,R0		;GET THE LAST NUMBER
	MOV	M.K,R1		;GET THE GENERATOR
	IMUL
	BIC	#100000,R0	;CLEAR SIGN BIT
	MOV	R0,M.I		;SAVE FOR NEXT TIME
	MOV	R0,R1
	MOV	@SP,R0		;SETUP TO FLOAT
	FLT
	MOV	(SP)+,R0	;POP THE DESTINATION
	SUB	#17,4(R0)	;ADJUST FOR FIXED POINT ON THE RIGHT
	RTS	PC
M.I:	.WORD	13507
M.K:	.WORD	403		;=64*8+3
;
; RANDOMIZE STATEMENT
;
RND01:	MOV	RNDM,M.I	;GET THE RANDOM WORD
	BIS	#1,M.I		;MAKE IT ODD
	JMP	INIT02
ATOF00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,-(SP)	;SAVE THE DEFA
	CLR	(R0)+		;CLEAR HIGH ORDER FRACTION
	CLR	(R0)+		;CLEAR LOW ORDER FRACTION
	CLR	@R0		;CLEAR THE EXPONENT
	CLR	-(SP)		;CLEAR EXP1
	CLR	-(SP)		;CLEAR EXP2
	CLR	-(SP)		;CLEAR THE SWITCHES
M.AFXN:	SKIP			;GET A CHARACTER FRON THE INPUT STRING
	CMPB	#105,R2		;LOOK FOR AN E
	BEQ	M.AFE		;BRANCH IF AN E IS FOUND
	CMPB	#55,R2		;LOOK FOR A MINUS
	BEQ	M.AFMI		;BRANCH IF A MINUS SIGN
	CMPB	#53,R2		;LOOK FOR A PLUS
	BEQ	M.AFPL		;BRANCH IF A PLUS SIGN
	CMPB	#56,R2		;LOOK FOR A DECIMAL POINT
	BEQ	M.AFD		;BRANCH IF A DECIMAL POINT
	TSTCH			;MAKE SURE IT IS NUMERIC
	BNE	M.AFXT		;ERROR IF NOT NUMERIC
	SUB	#60,R2		;CONVERT TO A BINARY NUMBER
	MOV	R1,-(SP)	;SAVE THE SEFA
	BIT	#4,2(SP)	;TEST THE E SWITCH
	BNE	M.AFXP		;BRANCH IF COLLECTING EXPONENT
	SUB	#6,SP		;PUT A FLOATING POINT NUMBER ON STACK
	MOV	SP,R0		;SET UP THE DEFA FOR FLT
	MOV	R2,R1
	FLT			;FLOAT THE INTEGER
	MOV	16(SP),R0	;GET THE DEFA
	MOV	#M.TEN,R1	;GET THE ADDRESS OF 10.
	MULF			;MULTIPLY BY 10.
	BVS	M.AFVT		;OVERFLOW IS A NO-NO
	MOV	16(SP),R0	;FIX UP THE DEFA POINTER
	MOV	SP,R1		;SET UP THE SEFA POINTER
	ADDF			;ADD THE CURRENT DIGIT
	BIT	#10,10(SP)	;TEST THE D SWITCH
	BEQ	.+6	;->	;IF ZERO DON'T TOUCH EXP2
	DEC	12(SP)	;  I	;DECREMENT EXP2
	ADD	#6,SP	;<-	;CLEAR UP THE STACK
M.AFSS:	MOV	(SP)+,R1	;PICK UP THE SEFA
	BIS	#1,@SP		;SET THE S SWITCH
	BR	M.AFNX		;GO GET MORE STUFF
M.AFXP:	MOV	R2,-(SP)	;PUSH THE CURRENT DIGIT
	MOV	10(SP),R3	;GET THE OLD EXPONENT
	MOV	#12,R5		;PUT DECIMAL 10 IN R5
	CLR	R2		;CLEAR REGISTERS FOR
	CLR	R4		;THE BIG MULTIPLY
	CMP	R3,#980.
	BGT	M.AFVU
	M.DPIM			;MULTIPLY BY TEN
	ADD	(SP)+,R3	;ADD THE CURRENT DIGIT
	MOV	R3,6(SP)	;SAVE IT BACK ON THE STACK
	BR	M.AFSS		;SET S SWITCH
M.AFE:	BIT	#4,@SP		;SEE IF THSI IS THE FIRST E
	BNE	M.AFVS		;ERROR IF MORE THAN ONE E
	BIS	#4,@SP		;SET THE E SWITCH
	BIC	#1,@SP		;CLEAR THE S SWITCH
	BR	M.AFNX		;GET THE NEXT CHARACTER
M.AFD:	BIT	#14,@SP		;TEST E AND D SWITCHES
	BNE	M.AFVS		;EITHER ONE SET IS AN ERRROR
	BIS	#10,@SP		;SET THE D SWITCH
	BR	M.AFNX		;SET START OF SIGNIFICANCE
M.AFPL:	BIC	#400,@SP	;CLEAR THE M SWITCH
	BR	.+4	;->	;SKIP THE NEXT INSTRUCTION
M.AFMI:	BIS	#400,@SP;  I	;SET THE M SWITCH
	BIT	#4,@SP	;<-	;TEST THE E SWITCH
	BNE	M.AFSE		;BRANCH IF SIGN OF THE EXPONENT
	BIT	#1,@SP
	BNE	M.AFXT
	BIT	#30,@SP		;TEST THE A, D, AND S SWITCHES
	BNE	M.AFVS		;IF EITHER IS SET AN ERROR IS HERE
	BIS	#20,@SP		;SET THE A SWITCH
	BIT	#400,@SP	;TEST IF A MINUS SIGN
	BEQ	M.AFNX		;RETURN IF PLUS SIGN
	BIS	#100,@SP	;SET MINUS SIGN
	BR	M.AFNX		;GET THE NEXT CHARACTER
M.AFXT:	BR	M.AFTX		;DARN 11 BRANCHES THAT GO NO
M.AFNX:	BR	M.AFXN		;FURTHER THAN 128 WORDS
M.AFSE:	BIT	#01,@SP		;TEST B AND S SWITCHES
	BNE	M.AFXT		;ERROR IF EITHER IS SET
	BIT	@SP,#40
	BNE	M.AFVS
	BIS	#40,@SP		;SET THE B SWITCH
	BIT	#400,@SP	;TEST FOR A MINUS SIGN
	BEQ	M.AFNX		;EXIT IF A PLUS
	BIS	#200,@SP	;SET MINUS EXPONENT
	BR	M.AFNX		;GET NEXT CHARACTER
M.AFVS:	BIS	#2,@SP		;SET V SWITCH
	BR	M.AFXT
M.AFVT:	ADD	#10,SP		;REMOVE 8 WORDS FROM THE STACK
	MOV	(SP)+,R1	;RESTORE POINTER TO TEXT
	BR	M.AFVS		;SET V AND EXIT
M.AFVU:	CMP	(SP)+,(SP)+	;POP ONE WORD OFF THE STACK
	BR	M.AFVS		;SET V AND EXIT
M.AFTX:	MOV	R1,-(SP)	;SAVE THE SOURCE POINTER
	BIT	#100,2(SP)	;SEE IF IT SHOULD BE NEGATIVE
	BEQ	M.AFX2		;BRANCH OF NO CONVERSION
	MOV	10(SP),R0	;PICK UP DEFA
	MOV	R0,R1		;MAKE SEFA=DEFA
	NEGF			;NEGATE THE NUMBER
M.AFX2:	BIT	#200,2(SP)	;SEE IF A NEGATIVE EXPONENT
	BEQ	M.AFX3		;BRANCH IF NO NEGATION
	NEG	6(SP)		;NEGATE THE EXPONENT
	BVC	M.AFX3		;TEST FOR VALID EXPONTNE
	BIS	#2,2(SP)		;SET THE V BIT
	BR	M.AFX5		;EXIT WITH ERROR
M.AFX3:	ADD	4(SP),6(SP)	;REMEMBER ANY DECIMAL PLACES
	BEQ	M.AFX5		;BRANCH IF NO CONVERSION
	BLT	M.AFDV		;IF LESS THEN ZERO DIVIDE
M.AFX4:	MOV	10(SP),R0	;SET UP DEFA=#
	MOV	#M.TEN,R1	;SET UP SEFA=10.
	MULF			;MULTIPLY BY 10.
	DEC	6(SP)		;DECREMENT AND TEST
	BGT	M.AFX4		;FOR DONE
	BR	M.AFX5		;BYPAS DIVIDE SECTION
M.AFDV:	MOV	10(SP),R0	;SET UP DEFA=#
	MOV	#M.TEN,R1	;SET UP SEFA=10.
	DIVF			;DIVIDE BY 10.
	INC	6(SP)		;INCREMENT AND TEST
	BLT	M.AFDV		;FOR COMPLETION 
M.AFX5:	MOV	(SP)+,R1	;RESTORE THE SOURCE POINTER
	DEC	R1		;POINT TO DELIMITER
	MOV	(SP)+,R4	;SAVE THE SIWTCHES
	ADD	#6,SP		;REMOVE 3 MORE WORDS FORM THE STACK
	MOV	(SP)+,R5	;RESTORE R5
	BIT	#2,R4		;TEST FOR V SETTING
	BEQ	.+4	;->
	SEV			;ASCII ERROR
	RTS	PC
M.TEN:	.WORD	000000,050000,100004	;FLOATING POINT 10.
M.ONE:	.WORD	000000,040000,100001	;FLOATING POINT 1.
M.TEN6:	.WORD	000000,075022,100024	;FLOATING POINT 10.^6
M.TEN7:	.WORD	040000,046113,100030	;FLOATING POINT 10.^7
M.FIVE:	.WORD	000000,40000,100000	;FLOATING POINT .5
FTOA00:	MOV	#12,R0		;PUT SOME WORDS ON THE STACK
	CLR	-(SP)		;CLEAR A WORD OF STACK
	DEC	R0		;DECREMENT THE COUNTER
	BGT	.-4		;LOOP IF MORE TO DO
	MOVSTK
	MOV	#030040,10(SP)	;MOVE A SP 0 TO THE OUTPUT
	MOVB	#040,12(SP)	;FOLLOW WITH A SPACE
	TST	R3		;TEST THE SIGN OF THE NUMBER
	BEQ	M.XAXT		;IF 0 WE'RE DONE ALREADY
	BGT	M.XA1		;IF NEGATIVE MAKE POSITIVE
	MOV	SP,R0		;POINT TO OUR NUMBER FOR
	MOV	R0,R1		;BOTH SOURCE AND DESTINATION
	NEGF
	MOVB	#55,10(SP)	;MOVE IN A - SIGN
M.XA1:	MOV	#M.TEN6,R1	;START THE RANGING PROCESS
	MOV	SP,R0		;COMPARE 10^6:#
	CMPF
	BGT	M.XA3		;BRANCH IF TOO SMALL
M.XA2:	MOV	#M.TEN7,R0	;OK LN THE LOW COMPARE
	MOV	SP,R1		;COMPARE #:10^7
	CMPF
	BLT	M.XA4		;BRANCH IF RANGING IS DONE
	MOV	#M.TEN,R1
	MOV	SP,R0		;DIVIDE BY 10
	DIVF
	INC	6(SP)		;MAKE THE EXPONENT LARGER
	BR	M.XA2		;SEE IF IT'S IN RANGE YET
M.XA3:	MOV	#M.TEN,R1
	MOV	SP,R0		;MULTIPLY BY 10
	MULF
	DEC	6(SP)		;MAKE THE EXPONENT SMALLER
	BR	M.XA1		;SEE IF IT'S BIG ENOUGH
M.XA4:	MOV	#M.FIVE,R1	;ROUND UP WITH .5
	MOV	SP,R0
	ADDF
	SUB	#100037,4(SP)
M.XA6:	ASR	2(SP)
	ROR	(SP)
	INC	4(SP)
	BNE	M.XA6
	MOV	SP,R0
	ADD	#16,R0		;POINT TO THE OUTPUT AREA
	MOV	SP,R1		;CONVERT TO ASCII
	MOV	R0,-(SP)	;SAVE R0 FOR LATER
	JTOA
	MOV	(SP)+,R0	;GET THE OUTPUT AREA ADDRESS
	ADD	#3,R0		;POSSIBLE START OF SIGNIFICANCE
	CMPB	#40,@R0
	BEQ	M.XA5		;BRANCH IF ALL'S WELL
	INC	6(SP)		;SIGNIFANCE STARTS HERE
	BR	M.XA5+2		;OMIT STANDARD CORRECTION
M.XA5:	INC	R0		;GO TO THE NEXT POSITION
	ADD	#7,6(SP)	;DO A FINAL ADJUSTMENT TO THE EXPONENT
	MOV	#10,R1		;USE R1 TO COUNT SIGFIGS
	MOV	R0,R2		;SAVE R0 FOR LATTER
	ADD	#7,R2		;POINT TO LAST DIGIT+1
	DEC	R1		;REDUCE THE SIG FIG COUNT
	CMPB	#60,-(R2)	;SEE IF IT'S SIGNIFICANT
	BEQ	.-6		;LOOP IF INSIGNIFICANT
	MOV	SP,R4
	ADD	#11,R4		;MOVE TO THE REAL OUTPUT AREA
	CMP	#10,6(SP)	;SEE WHAT FORMAT TO USE
	BLE	M.XAE		;BRANCH IF E FORMAT
	CMP	#-10,6(SP)	;CHECK THE LOWER LIMIT TOO
	BGE	M.XAE		;BRANCH IF E FORMAT
	MOV	R1,R3		;USE A TEMPORARY REGISTER
	NEG	R3
	ADD	6(SP),R3	;ADD THE EXPONENT
	ADD	#7,R3		;ADD CONSTANT OFFSET
	BLT	M.XAE		;BRANCH IF READY FOR E FORMAT
	MOV	6(SP),R3	;F FORMAT FOR SURE
	BLT	M.FA1		;IF NEGATIVE SHIFT RIGHT
	BGT	M.FA3		;IF POSITIVE MOVE DEC PT RIGHT
M.FA4:	MOVB	#56,(R4)+	;OUTPUT A DEC PT
M.FA0:	MOVB	(R0)+,(R4)+	;MOVE A DIGIT
	CMP	R0,R2		;SEE IF WE ARE DONE
	BLOS	M.FA0		;LOOP IF NOT
M.FA5:	MOVB	#040,(R4)+	;INSERT A TRAILING SPACE
	CLRB	@R4		;FOLLOW WITH A NULL FOR PRINTL
M.XAXT:	ADD	#10,SP		;CLEAN UP THE STACK
	MOV	22(SP),PC	;RETURN
M.FA1:	MOVB	#56,(R4)+	;OUTPUT A DECIMAL PT
M.FA2:	MOVB	#60,(R4)+	;OUTPUT A LEADING 0
	INC	R3		;DECREMENT NEGATIVE COUNTER
	BLT	M.FA2		;SEE IF DONE INSERTING
	BR	M.FA0		;GO OUTPUT THE SIGNIFICANT DIGITS
M.FA3:	MOVB	(R0)+,(R4)+	;MOVE A DIGIT
	DEC	R3		;REDUCE THE COUNT
	BGT	M.FA3		;LOOP IF NOT DONE
	CMP	R0,R2		;SEE IF THERE IS ANY MORE SIGNIFICANCE
	BLOS	M.FA4		;IF MORE CONTINUE
	BR	M.FA5		;ELSE EXIT

M.XAE:	MOVB	#56,(R4)+	;OUTPUT A DEC PT
M.EA0:	MOVB	(R0)+,(R4)+	;OUTPUT A DIGIT
	CMP	R0,R2		;SEE IF ALL THE GOOD ONES ARE OUT
	BLOS	M.EA0		;LOOP IF NOT
	MOVB	#105,(R4)+	;OUTPUT AND E
	ADD	#6,SP		;REMOVE UNUSED STACK SPACE
	MOV	@SP,R1		;GET THE EXPONENT
	MOV	SP,R0		;GO TO THE OUTPUT AREA
	ADD	#14,R0
	MOV	R0,-(SP)	;SAVE R0 THE DESTINATION
	MOV	R4,-(SP)	;SAVE R4 THE OUTPUT AREA
	ITOA
	MOV	(SP)+,R4	;REASORE R4
	MOV	(SP)+,R0	;GET BACK ALL THE GOODIES
M.EA1:	CMPB	(R0)+,#40	;COMPARE WITH A SPACE
	BEQ	M.EA1		;LOOP IF A SPACE
	CMPB	-(R0),#55	;SEE IF ITS -
	BEQ	M.EA2
	MOVB	#40,(R4)+	;OUTPUT A SPACE FOR A SIGN
M.EA2:	MOVB	(R0)+,(R4)+	;OUTPUT A DIGIT
	CMPB	@R0,#40		;LOOK FOR THE TRAILING SPACE
	BNE	M.EA2		;LOOP IF NOT DONE
	MOVB	#040,(R4)+	;FOLLOW THE NUMBER WITH A SPACE
	CLRB	@R4		;FOLLOW WITH A NULL
	TST	(SP)+		;CLEAN UP THE STACK
	MOV	22(SP),PC	;RETURN
ATOI00:	CLR	R0		;PUT THE NUMBER IN R0
M.AINX:	JSR	PC,SKIP00	;GET A CHARACTER FROM THE INPUT STREAM
	JSR	PC,TST00	;SEE IF IT IS IN RANGE FOR A DIGIT
	BNE	M.AIXT		;ALL DONE IF NON-NUMERIC
	SUB	#60,R2		;REDUCE TO A BINARY VALUE
	ASL	R0		;MULTIPLY THE CURRENT NUMBER BY
	ADD	R0,R2		;10 VIA X*2+X*8+CURRENT DIGIT
	ASL	R0
	ASL	R0
	ADD	R2,R0
	BIT	#160000,R0	;TEST FOR TOO BIG
	BEQ	M.AINX		;OK IF IN RANGE
	LNNERR			;LINE NUMBER IS REALLY BAD
M.AIXT:	DEC	R1		;RESET POINTER BACK ONE CHAR.
	RTS	PC
ITOA00:	MOV	R0,-(SP)	;SAVE THE DEFA
	CLR	-(SP)		;CLEAR HIGH ORDER WORD
	MOV	R1,-(SP)	;MOVE THE WORD
	BGE	.+6	;->	;BRANCH IF HIGH ORDER BIT 0
	COM	2(SP)	;  I	;SET ALL BITS IN THE WORD
	MOV	SP,R1	;<-	;SET UP THE SEFA FOR JTOA CALL
	SUB	#14,SP		;EXPAND THE STACK FOR A DESTINATION
	MOV	SP,R0		;LET THE STACK BE THE DESTINATION
	JTOA			;CALL JTOA FOR THE REAL CONVERSION
	MOV	SP,R1		;SET UP FOR A MOVE TO REAL DEFA
	MOV	20(SP),R0	;RESTORE THE USER'S DEFA
	ADD	#5,R1		;THE FIRST FIVE ARE SPACES
	MOV	#7,R2		;TOTAL OF SEVEN CHARACTERS TO BE MOVED
	MOVB	(R1)+,(R0)+	;<-	;MOVE A CHARACTER
	DEC	R2		;  I	;DECREMENT COUNTER
	BGT	.-4		;->	;BRANCH IF MORE TO DO
	ADD	#22,SP		;REMOVE ALL JUNK FORM THE STACK
	RTS	PC
JTOA00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,-(SP)	;SAVE THE DEFA
	CLR	-(SP)		;THIS IS A SIGN CONTROL WORD
	MOV	(R1)+,R3	;GET THE INTEGER LOW ORDER
	MOV	@R1,R2		;AND HIGH ORDER
	BGE	.+12	;->	;IF NEGATIVE
	NEG	R2	;  I	;REVERSE THE SIGN
	NEG	R3	;  I	;AND ZOT THE SIGN CONTROL
	SBC	R2	;  I	;WORD ON THE STACK
	INC	@SP	;  I
	MOV	#12,R5	;<-
	CLR	R4
	MOV	#-1,-(SP)	;A NEGITIVE NUMBER FOR LATER
M.JA01:	CLR	R0		;ZERO OUT A BUNCH OF REGISTERS
	CLR	R1
	M.DPID			;DIVIDE BY TEN
	MOV	R1,-(SP)	;PUSH THE REMAINDER
	BIS	R2,R0		;PUT ALL THE BITS
	BIS	R3,R0		;IN ONE REGISTER
	TST	R0		;TEST THE QUOTIENT FOR ZERO
	BNE	M.JA01		;BRANCH IF MORE TO DO
	MOV	SP,R5		;NOW COUNT THE MUMBER OF DIGITS
	INC	R4	;<-
	TST	(R5)+	;  I	;WE HAVE A NEGATIVE NUMBER SOMEWHERE
	BGE	.-4	;->
	DEC	R4		;BE REAL ACCURATE ABOUT THIS
	MOV	#13,R3		;ELEVEN
	SUB	R4,R3		;R3 HAS THE NUMBER OF LEADING SPACES
	DEC	R3		;SAVE ROOM FOR A SIGN
	MOV	2(R5),R0	;RESTORE THE LOST DEFA
M.JA02:	TST	R3		;IS THE COUNT EXAUSTED
	BLE	M.JA03
	MOVB	#40,(R0)+	;INSERT A SPACE (ASCII 040)
	DEC	R3
	BR	M.JA02		;BACK FOR SOME MORE
M.JA03:	TST	@R5
	BEQ	M.JA04
	MOVB	#55,(R0)+	;INSERT MINUS SIGN (ASCII 055)
	BR	M.JA05
M.JA04:	MOVB	#40,(R0)+	;OR A SPACE FOR A SIGN
M.JA05:	ADD	#60,@SP	;<-	;CONVERT TO ASCII
	MOVB	(SP)+,(R0)+;  I	;MOVE TO OUTPUT AREA
	TST	@SP	;  I	;SEE IF WE ARE DONE
	BGE	.-10	;->	;BRANCH IF MORE TO DO
	MOVB	#40,@R0		;FOLLOW BY A TRAILING SPACE
	ADD	#6,SP
	MOV	(SP)+,R5	;RESTORE R5
	RTS	PC
;SINGLE PRECISION INTEGER MULTIPLY
;LENGTH =     BYTES
;EXECUTION TIME =       CYCLES-TYPICAL
;
IMUL00:	MOV	R5,-(SP)	;SAVE R5
	MOV	R0,R3		;PICK UP ONE OPERAND
	MOV	R1,R5	;<-	;PICK UP THE OTHER OPERAND
	CLR	R2	;<-	;PREPARE TO
	CLR	R4		;MULTIPLY
	M.DPIM			;GO-GO-GO-ZAP
	MOV	R3,R0	;MOVE THE RESULT TO 
	MOV	R2,R1		;THE DESTINATION
	MOV	(SP)+,R5	;RESTORE R5
	RTS	PC
;	SUBROUTINE TO MULTIPLY TWO DOUBLE PRECISION INTEGERS
;	USES ALL REGISTERS (R0-R5)
;
;	ENTER EITH JSR  PC,M.DPIM
;		MULTIPLIER IN R2-R3
;		MULTIPLICAND IN R4-R5
;		RESULT RETURNED IN R0-R1-R2-R3
;
MDPIM:	CLR	R0		;CLEAR HIGH ORDER WORDS
	CLR	R1
	MOV	#41,-(SP)	;MOVE 33 DEC TO COUNTER
M.DP01:	ROR	R0
	ROR	R1
	ROR	R2		;SHIFT TO ADD
	ROR	R3
	BCC	M.DP02		;NO CARRY NO ADD
	ADD	R5,R1
	ADC	R0		;ADD DOUBLE PRECISION TO OBTAIN NEW PARTIAL 
	ADD	R4,R0		;PRODUCT
M.DP02:	DEC	@SP		;DECREMENT COUNTER
	BNE	M.DP01
	TST	(SP)+		;REMOVE THE COUNTER
	RTS	PC
	.EOT			;END OF TAPE 6
