Google
 

Trailing-Edge - PDP-10 Archives - klu2_442 - extexp.mic
There are 5 other files named extexp.mic in the archive. Click here to see a list.
.TOC	"GFLT DOUBLE PRECISION ARITHMETIC"

.IF/EXTEXP

	.DCODE
102:	R,	B/0,	J/EDFLOT	;GFAD
103:	R,	B/2,	J/EDFLOT	;GFSB
106:	R,	B/4,	J/EDFLOT	;GFMP
107:	R,	B/6,	J/EDFLOT	;GFDV
	.UCODE

=0****00**0*
EDFLOT:	VMA_VMA+1, LOAD ARX,
		MQ_0.S, CALL [XFERW]
	FM[E0]_AR, ARX_ARX*2, B DISP	;mem high to E0, do instruction
=

=000
EDFL1:	SKP AR0, CALL [ISOEXP]		;save mem high word in E0.
	FM[T2]_AR, J/EF1		;save mem exp in T2.
	AR_-AR LONG			;subtract now same as add.
	FM[E0]_AR, J/EDFL1		;save "positive" exponent
=100	SKP AR0, CALL [ISOEXP]		;isolate mem exp in AR.
	BR/AR, GEN ARX, SKP AD NE,	;start test for sticky bits.
		J/EFMP
=110	BR/AR, GEN AR, SKP AD0, 	;save mem high in br.
		CALL [ISOEXP]		;get mem exp
	FM[T2]_AR, AR_0S, J/EFDV0	;save mem exp in T2. No sticky bits.
=0
EF1:	AR_AC0, SKP AD0, CALL [ISOEXP]	;get AC op
	FM[E1]_AR, BR/AR		;save AC exp in E1
		
;Now have positive mem exponent in T2, pos AC exp in E1.
;Save larger exp in T2 and exp diff if less than 340 in SC.
	[AR]_[AR]*FM[T2], AD/A-B,	;AR gets exp diff.
		SKP AD0			;AR get exp diff, BRX gets exp.
=00	SC_#, #/3, CALL [EXPDIF]	;test for exp diff >72.
	BR/AR, J/EF3A			;mem op larger.
	AR_BR, J/EF5			;restore exp to AR.
	[AR]_FM[E1], CLR FE, J/ACNORM	;exp diff too large, norm AC op.
=00
EF3A:	AR_-BR, SC_#, #/3, CALL [EXPDIF];mem larger, get positive diff.
=10	AR_BR, J/EF3B			;restore exponent to AR.
	[AR]_FM[T2], CLR FE, J/MEMNRM	;exp diff > 72. norm mem op.
EF3B:	AR_AR*8				;move exp difference into AR0-8.
	FE_AR0-8,			;mem larger, op doable.
		AR_AC0			;save smaller AC op in T0,T1
=0	FM[T0]_AR, CALL [EF5B]
	FM[T1]_AR
	[AR]_FM[E0]			;save larger mem op in AC0,AC1
	AC0_AR, AR_ARX
	AC1_AR, J/EF5A			;all set to shift and add.

EF5:	AR_AR*8				;move exp difference into AR0-8.
	FE_AR0-8, [AR]_FM[E0]		;smaller mem op to T0,T1
	FM[T0]_AR, AR_ARX
=0	FM[T1]_AR, CALL [EF5B]
	AC1_AR				;we expect AC1*2 to be saved.
	[AR]_FM[E1]			;save larger AC exp in T2
	FM[T2]_AR, J/EF5A

EF5B:	AR_AC1*2, RETURN1

;EXPDIF determines if the exponent difference is too large-ie >110 oct.
;The largest allowed value for shifting is 72 decimal. This is 110 octal.
;Since the exponent is in AR1-11, 110 octal has the value 11 in AR1-8.
;It expects the exponent difference in AR0-8.
;It uses AR0-8 and the BR.
;Returns 2 if the difference is ok (<=110).
;Returns 3 if the difference is too large (>110).
EXPDIF:	BR/AR, CLR AR			;zero all of those bits.
	AR0-8_#, #/10			;put in 100 in AR0-11.
	GEN AR-BR, SKP AD0, RETURN2	;<max diff>-<actual diff>

;We now have:
; AC0	/ larger op high
; AC1	/ larger op low
; T0	/ smaller op high
; T1	/ smaller op low
; T2	/ larger exponent
; FE	/ exp difference
;We must now sign extend both high ops.
=0
EF5A:	AR_AC0, SKP AD0, CALL [SGNEXT]	;get larger high op
	AC0_AR				;save larger extended op in AC0
=0	[AR]_FM[T0], SKP AD0,		;get smaller high op
		CALL [SGNEXT]		; and sign extend into AR1-11.
	FM[T0]_AR			;save smaller extended op in T0
;We are now set to shift the smaller op to align it with the larger op.
	[AR]_FM[T1]
	[AR]_FM[T0], ARX_AR, SC_FE	;move diff to SC for next line.
	SC_#-SC, #/36., SKP SCAD0
=0	ARX_AR, AR_SIGN, J/EF10		;FE < 37.
	BR/AR, BRX/ARX, SC_FE
	AR_SIGN, ARX_AR
	SC_#-SC, #/72.
	ARX_SHIFT			;high is sign, low is sign,,high.
=01	AR_BR LONG, BR/AR, BRX/ARX,	;save new stuff in BR long.
		CALL [EF12]		;MQ gets lowest word.
	FM[E1]_AR			;save sticky bits.
	AR_AC1, J/EF11			;now prepare to add.
EF10:	AR_SHIFT, [ARX]_FM[T1]		;shift high op, load low word.
	BR/AR, [AR]_FM[T0]		;shift low op, load high word.
	AR_ARX (AD), ARX_SHIFT		;get shifted low word into ARX.
=01	BRX/ARX, CLR ARX, CALL [EF12]	;save low word, shift end bits.
	FM[E1]_AR			;save sticky bits. (word 4 of sum).
	AR_AC1, J/EF11			;prepare to add.
	BR/AR, BRX/ARX, AR_AC1		;get larger op in AR,ARX
EF11:	ARX_AR, AR_AC0, FE_#, #/0	;smaller op in BR,BRX
	AR_AR+BR, ARX/ADX, SC_#, #/3,	;operation done, now normalize.
		NORM, J/ENORM

EF12:	MQ_SHIFT, AR_ARX (AD), CLR ARX,J/SHIFT
.IF/GFTCNV		;[273]
EF12A:	AR_SHIFT, RETURN10
.ENDIF/GFTCNV		;[273]
.ENDIF/EXTEXP
.TOC	"GFLT MULTIPLY"
.IF/EXTEXP
=0
EFMP:	CLR AR, J/EFMP1			;mem low op is zero, no sticky bits.
	AR_AC1*2, SKP AD NE		;is AC low op non-zero as well ?
=0	CLR AR				;yes, no sticky bits today.
EFMP1:	FM[E1]_AR, AR_0S		;set sticky bits.
	AR0-8_#, #/200			;subtract 200.
	BR/AR, AR_BR			;swap around exp and 2000.
	AR_AR-BR, CLR SC		;done, and SC is cleared.
=0	BR/AR, AR_AC0, SKP AD0,		;save exp-2000 in BR.
		CALL [ISOEXP]		;get AC high and isolate exp.
	AR_AR+BR			;add exponents together.
	FM[T2]_AR			;and store the sum in T2.
=0	[AR]_FM[E0], SKP AD0,		;get mem high op sign extended.
		CALL [SGNEXT]
	FE_#, #/-18.			;
	BR/AR, BRX/ARX, AR_AC1		;move mem ops to BR!BRX.
=000	MQ_AR, AR_0S, ARX_0S,		;multiply by low word.
		CALL [MULREE]
=100	AR_AR+BR LONG			;low sign was set, add results.
=110	MQ_AR, AR_AC0, FE_#, #/-13.,	;now continue with high part.
		SKP AD0, CALL [SGNEXT]	;sign extend the ac high op.
	FM[T0]_AR			;save sign extended AC op.
;	SKP AR0				;test sign bit to adjust FE.
=0
EFMPP1:	MQ_AR, AR_MQ, J/EFMPP2		;swap AR+MQ.
	FE_FE+1, J/EFMPP1		;inc the FE if number is neg.
=000
EFMPP2:	AD/0S, FE_FE+1, DISP/MUL,	;now multiply by the high word.
		MQ/MQ*.25, CALL [MULP]
;Since our last multiply step used 2 signs bits instead of a sign bit
;and the MSB, our answer is too low by a power of two for positive numbers
;and too low by a power of 4 for negative numbers.
=100	(AR+ARX+MQ)*2, J/EFMPP3		;try this correction factor.
=101	(AR+ARX+MQ)*.25, J/EFMPP3	;shouldn't ever get here.
=110	(AR+ARX+MQ)*2			;and this for postive numbers.
=
EFMPP3:	BR_AR LONG, AR_0.C, ARX_1S	;result to BR!BRX. Build mask.
=01	SC_#, #/10.,			;load SC with shift count.
		CALL [SHIFT]		;Now have mask of 0,,1777
	AR_BR LONG, BR_AR LONG		;mask to BR, result TO AR!ARX.
	MQ_MQ*BR, AD/ANDCB		;clear the last 10 MQ bits.
	GEN AR, SC_#, #/3,		;generate NORM bits.
		NORM, J/ENORM		;conditions set for EE norm.
.ENDIF/EXTEXP
.TOC	"GFLT DIVIDE"
.IF/EXTEXP
EFDV0:	FM[E1]_AR			;no sticky bits on divide.
=0	AR_BR, SKP AD0, CALL [SGNEXT]	;sign extend mem high.
	GEN AR*AC0, AD/XOR, SKP AD0,	;determine sign of result.
		BR_AR LONG		;mem op to BR!BRX.
=000	AR_AC1*2, CALL [EFDV1]		;start division.
	SR_1, AR_AC1*2, CALL [EFDV1]	;note result if negative.

=011	AC1_AR, AR_MQ, ARL/AD, FE_FE+1,	;set step count to 35-2.
		MQ_0.M, CALL [DIV+]	
=101	AC1_AR, AR_MQ, ARL/AD, FE_FE+1,
		MQ_0.M, CALL [DIV-]
=111	CLR AR, CLR FE			;exp must be adjusted-
	AR0-8_#, #/200			;  it is currently 2000 too low
	[AR]_[AR]*FM[T2], AD/A+B	;add in the correction.
	FM[T2]_AR			;store the corrected exp in T2.
	AR_AC1, ARX/MQ, SC_#, #/3,	;get answer ready for norm.
		NORM, J/ENORM

=00
EFDV1:	ARX_AR, AR_AC0, SKP AD0, FE_#,	;AC low*2 to ARX, AC high to AR.
		#/23., CALL [EDVCHK]
=10	SKP BR0, J/DDVSUB
	SET FL NO DIV, J/IFNOP		;no division this time.

=0
EDVCHK:	MQ_AR, J/EDVCH1			;go to an even address.
	AR_-AR LONG, J/EDVCHK		;make ac op positive.

=0
EDVCH1:	SKP AR0, CALL [ISOEXP]		;op saved in MQ, get exp in AR.
	[AR]_[AR]*FM[T2], AD/A-B,	;subtract exponents.
		SKP AD0			;did this cause an underflow ?
=0
	SET SR2 			;no, let SR2 denote this.
EDVCH2:	FM[T2]_AR			;yes, save exponent in T2 for ENORM.

=0
EDVCH3:	AR_MQ, SKP AD0, CALL [SGNEXT]	;now sign extend the op.
	SKP BR0, MQ_0.M, J/FDVCK1
.ENDIF/EXTEXP
.TOC	"GFLT NORMALIZATION"
.IF/EXTEXP
;Normalization is done here.
;	The are 8 addresses the can be reached when doing a
;	NORM dispatch. The following table describes the
;	dispatching and how to normalize the fraction and
;	exponent.
;
;	=000	AR=0			AR is zero, check ARX,MQ
;	=001	AR00=1			sign bit on, complement
;	=010	MSB in AR 1-6		shf 4 rt.(a guess)
;	=011	MSB in AR07		sht 2 rt.
;	=100	MSB in AR08		sht 3 rt.
;	=101	MSB in AR09		right on!
;	=110	MSB in AR10		sht 1 lf.
;	=111	MSB in AR 11-35		sht 4 lf.(a guess)
;
;The normalization routine for double precision assumes that
;	the exponent can be found in the FE. As it goes through
;	the normalization process, it adjusts the fraction and
;	the FE by the correct amounts to normalize the number.
;	In GFLT numbers, the exponent may not fit
;	into the FE, so it has to be saved in an accumulator.
;	However, if one assumes initially that the exponent is
;	zero and that it is in the FE, then the same normalization
;	algorithm can be used as in double precision numbers
;	with the realization that at the end of the normalization
;	process the FE contains the correction (EC)  that must be
;	added into the saved exponent (ES)  to produce a 'bit-9'
;	normalized number. Once this correction value is obtained,
;	the 'bit-12' normalized exponent (EN)  is given by
;			EN = ES + EC + 3

MEMNRM:	FM[T2]_AR			;save larger exponent.
	[AR]_FM[E0], SKP AD0, J/ACNRM1	;get high word, sign extend it

ACNORM:	FM[T2]_AR			;save larger exponent.
	AR_AC1*2, CLR FE		;get low word*2 into AR.
	ARX_AR, AR_AC0, SKP AD0		;get high word, sign extend it.
=0
ACNRM1:	[AR]_[AR]*FM[EXPMSK], AD/AND,	;sign extend with 0's.
	NORM, J/ENORM
	[AR]_[AR]*FM[EXPMSK], AD/ORCB,	;sign extend with 1's.
		NORM			;fall into the normalize routine.

=000
ENORM:	SKP ARX+MQ NE, SC_#, #/35.,	;AR=0,check ARX,+MQ.
		J/ENZERO
	BR/AR, BRX/ARX, AR_MQ COMP,	;result neg, complement.
		SET SR3, J/ENNEG	;flag negative seen.
	AR_AR*.25 LONG, MQ_MQ*.25,	;MSB in AR 1-6.
		FE_FE+#, #/4, J/ENHI
	AR_AR*.25 LONG, FE_FE+#,	;MSB in AR07.
		#/2, J/EROUND		;
	AR_AR*.5 LONG, FE_FE+1		;MSB in AR08.
EROUND:	BR_AR LONG, AR+MQ_0.S,	 	;MSB in AR09, where we want it.
		J/ERND1			;put result in BR!BRX.
	(AR+ARX+MQ)*2, FE_FE-1,		;MSB in AR10.
		J/EROUND
	AR_SHIFT, FE_FE-SC		;MSB somewhere in AR 11-35.

ENSHFT:	BR/AR, AR_ARX, ARX/MQ		;shift everyone.
	MQ_SHIFT, AR_ARX (ADX), CLR ARX
	MQ_SHIFT, ARX/MQ, AR_BR,	;go aroung again.
		SC_#, #/10.,
		NORM, J/ENORM

ENNEG:	GEN E1, SKP AD NE		;any sticky bits left around?
=0	AR_AR+1, SKP CRY0, J/ENNEG1	;no, 2's comp MQ.
	MQ_AR, AR_BR COMP, ARX_BRX COMP,
		NORM, J/ENORM		;one's complement to finish.
=0
ENNEG1:	MQ_AR, AR_BR COMP, ARX_BRX COMP,
		NORM, J/ENORM		;one's complement to finish.
	MQ_AR, AR_-BR, ARX/ADX,		;carry happened, do two's comp.
		NORM, J/ENORM

ENHI:	(AR+ARX+MQ)*.25, J/ENTRY	;go try again after setting SC.
=0
ENZERO:	SR_0,AR_0S,ARX_0S,I FETCH,J/DLOAD;[413] result 0, store in AC,AC+1
	AR_SHIFT, FE_FE-SC, J/ENSHFT	;not zero, try next 35 bits.

ERND1:	ARX_2+MQ0			;[407] build rounding constant.
	ARX_ARX*4			;gen a 10 in the ARX for rounding.
	AR_AR+BR, ARX/ADX, NORM		;do the rounding and test norm.
=110	AR_AR*.5 LONG, FE_FE+1		;rounding blew norm, correct it.

; When we get here the number is 'bit-9' normalized
; in the AR,ARX.  Add the FE + 3 to the exponent
; saved in T2.
; At this point the Extended Exponent must be put
; into the AR after everything is shifted right 3 bits.
; The double precision norm routine does this by:
; EXP_FE TST, SR DISP, CLR MQ, BRX/ARX, ARX_1


ERND2:	AR_AR*.25 LONG,		;shift everything 2 bits right.
		MQ_MQ*.25,	;	"	"	"
		SC_#, #/3	;add in correction to FE.
	AR_AR*.5 LONG,		;now shift the final bit position.
		SC_FE+SC	;total exponent correction.
	BR/AR, BRX/ARX, CLR AR	;save answer in BR,BRX.
	EXP_SC.MS		;get exp corr in AR.
	ARX_AR, AR_SIGN,	;get exp into ARX 1-8.
		SC_#,#/33.	;prepare to shift 3 places.
	ARX_SHIFT,		;move exponent into ARX 1-11.
		[AR]_FM[EXPMSK]	;prepare to build mask in AR.
	AR0-8_#, #/400		;include AR00 in EXPMSK==>400077,,-1
	AR_AR*BR, AD/AND,	;zero AR1-11 to make room for exp.
		SC_#, #/35.

; I am sure a few lines of code can be saved around here.

	[AR]_FM[T2], BR/AR	;save high word in BR, load larger exp.
	AR_BR, BR/AR		;swap around so we can add.
	AR_ARX+BR, BR/AR,	;have final exponent, check for problems.
		SC_#,#/0
	SH DISP			;any exponent problems ?
=0011	ARX_AR, SC_#, #/35.,	; no problems.
		J/ENFNL1
ENFNL0:	ARX_AR, SC_#, #/35.,	; no problems.
		J/ENFNL1
	SET FLOV,  J/EEOV	; an overflow occurred.
		
	SR DISP			;floating underflow - is it real ?
=1101	;test SR2.
	SET FXU, J/EEOV		;yes, it is a real underflow.
	SET FLOV		;no, GFDV saw an overflow before.

EEOV:	P_P AND #, #/37,	;turn off AR00.
		J/ENFNL0

ENFNL1:	AR_ARX*BR, AD/OR	;AR now has high word, BRX has low.
	ARX_1, MQ_0.M, SR DISP	;incase negation of lower word needed.
=10	AC0_AR, AR_SHIFT,	;store high word,
		ARX_BRX,	;move low word to ARX.
		I FETCH, J/STD1	;prepare to store low word and exit.
	ARX_ARX*BRX, AD/ANDCA,	; clear rounding bit.
		SR_0,J/CDBLST	;negate result and store double result.

ENTRY:	SC_#, #/3, GEN AR, NORM, J/ENORM; go normalize again.
.ENDIF/EXTEXP
.TOC	"GFLT TO INTEGER CONVERSION"
.IF/EXTEXP
.IF/GFTCNV		;[273]

;ETXIX routine is used when converting extended exponent data to
;single/double precision integers with rounding/truncation.
;This routine assumes that the AR/ARX contain the extended exponent
;data. It also assumes that the maximum exponent value + 1 of either
;36 or 70 (decimal) are already in the FE. This is the positive exponent
;maximum; the code adjusts for the fact that a negative number can have
;an exponent one greater than a positive number. 
;It uses all of the registers in the EBOX and returns 4 if the
;result is positive and returns 5 if the result is negative
;with the AR/ARX containing the double word integer. It is the
;responsibility of the calling routine to determine whether
;rounding or truncation should be performed and how many words
;to store.

ETXIX:	ARX_ARX*2		;get low word*2 into ARX.
=0	MQ_AR, SKP AR0,		; get a positive exp in AR.
		CALL [ISOEXP]
	CLR AR, BR/AR		;clear extraneous bits, save exp.
	AR0-8_#, #/200		;test for positive exp.
	GEN AR+BR, SKP AD0,	;skip on positive exponent(sum has AD0 on).
		AR_0.M		;so exponent test has a clean register.
=0	MEM/ARL IND, CLR/AR+ARX,;exponent must be positive.
		RETURN4		;return to caller.
	AR0-8_#, #/212, J/ET1	;start range check of positive exponent

;At this point the exponent is in BR 1-11 and it is positive.
;Now we must determine if it is a small enough positive number
;to make the conversion to integer meaningful.
ET1:	GEN AR-BR, SKP AD0	;do the exponent test.
=0	AR_BR*4, J/ET2		;exp fits in AR0-8, now for final test!
	SET AROV, I FETCH, J/NOP;exponent out of range.
ET2:	AR_AR*2			;finish moving exponent into AR0-8.
	SC_AR0-8, GEN MQ,	;exponent to SC.
		SKP AD0		;max neg exponent is 1 gtr than max pos exp.
=0
ET2A:	AR_MQ, GEN FE-SC,	;shift low word into ARX00-34, caller
		SKP SCAD0,	;put max exponent+1 in FE. range check.
		J/ET2B
	FE_FE+1, J/ET2A		;max neg exp is 1 gtr than max pos exp.
=0
ET2B:	FE_SC, J/ET3		;save exp in FE.
	SET AROV, I FETCH, J/NOP;exponent is too large.
ET3:	SC_#, #/12.		;prepare to map AR12 into AR00.

;We now have the high word in the AR and
;the low word*2 in the ARX. The SC has 12 (dec) to let the
;shifter strip off the sign and exponent of the high word.
	AR_SIGN, MQ_SHIFT	;put high 36 integer bits into MQ.
	AR_ARX, BR/AR, CLR ARX	;generate low 36 integer bits and
	AR_BR, ARX/MQ, MQ_SHIFT,;  put in MQ. High bits to ARX.
		SC_FE-#, #/36.,	;check the size of the exponent.
		SKP SCAD0	;if exp<36. then high result is sign.
=0	GEN SC, SKP SCAD NE,	;is exponent gtr or geq to 36 ?
		J/ET3A
	SC_#+SC, #/37., J/ET5	;exponent less than 36.
=0
ET3A:	(AR+ARX+MQ)*2, J/ET3B	;must shift left 1 bit.
	BRX/ARX, SC_#+SC, #/1,	;adjust exp, save low word in BRX.
		J/ET4
ET3B:	BR_AR LONG, AR_ARX,	;high and low to BR!BRX
		SC_#, #/35.,	;get a good exponent for final shifting.
		ARX/MQ, J/ET4A	;rest of fraction to ARX.
ET4:	AR_ARX (AD), ARX/MQ,	;exp gtr 36. High result has integer bits.
		MQ_SHIFT	;high result to MQ.
	AR_MQ, ARX_SHIFT	;put integer bits into ARX.
	BR_AR LONG, AR_ARX (AD),;now compute fraction.
		CLR ARX		;low integer to AR, pad with zeros in ARX.
ET4A:	AR_BR LONG, MQ_SHIFT,	;restore integer to AR!ARX, fraction to MQ.
		SC_#, #/35.,	;low word must have bit 0 same as high.
		SKP AD0, RET[4]	;  and return on sign of integer.
=01
ET5:	FM[T0]_AR, AR_ARX (AD),	;sign is high 36 bit result. Save in T0.
		ARX/MQ,		;high 36 bits of frac to AR, low 23 to ARX.
		MQ_SHIFT,	;low integer result to MQ.
		CALL [SHIFT]	;high half of fraction to AR.

;Now we have the high 36 bits of mantissa in AR, the low 23 bits if mantissa
;in the ARX, the high 36 bit result (the sign bits) in T0 and the low 36 bit
;result in the MQ. Now we compute the fraction to store.
	BR/AR, AR_ARX, CLR ARX	;high frac to BR. Now gen low fraction bits.
	ARX_SHIFT,		;low fraction bits to ARX.
		SC_#, #/35.	;low word must have same sign as high.
	GEN ARX*BR, AD/OR,	;gen composite OR of fraction into 1 word.
		MQ_AD,		;put this funny fraction in the MQ.
		ARX/MQ		;low integer result to ARX.
	[AR]_FM[T0], SKP AD0,	;get high result (Sign) back in AR.
		RET[4]		;and return to caller.
.ENDIF/GFTCNV		;[273]
;ISOEXP will isolate the exponent in an extended exponent data word.
;It will return the positive representation of the exponent.
;Call with AR containing high order word with "SKP AR0" to do
;correct things with one's complemented exponent in negative numbers.
;It returns 1 with the positive exponent in the AR.
=0
ISOEXP:	[AR]_[AR]*FM[EXPMSK],AD/ANDCB,RET[1] ;isolate pos exp in AR1-11.
	[AR]_[AR]*FM[EXPMSK],AD/NOR,RET[1]   ;isolate neg exp in AR1-11.

;SGNEXT will extend the sign bit of the AR into AR1-11. Call with
;SKP AR0 so the correct actions are taken for negative numbers.
;It will do a return 1 with either ones or zeroes in AR1-11.
=0
SGNEXT:	[AR]_[AR]*FM[EXPMSK], AD/AND, RET[1]  ;extend 0s into AR1-11.
	[AR]_[AR]*FM[EXPMSK], AD/ORCB, RET[1] ;extend ones into AR1-11.

;OVTEST will determine if the high order word of a double integer,
;as stored in the AR is all sign bits, ie either it is all zeroes
;or all ones. The call is via "GEN AR, SKP AD NE, J/OVTEST".
;It assumes that the double integer is in the AR/ARX and the SC
;contains 35 decimal.
;OVTEST will store the ARX*.5 and exit if the AR is all sign bits. 
;It will set AROV and jump to NOP if it finds some data bits.
OVTST1:	AR_MQ, SKP AD NE		;get the sign bits from the MQ.
=0
OVTEST:	AR_SHIFT, I FETCH, J/OVTST2	;the high word is all zeros - ok.
	GEN AR+1, SKP AD NE		;check to see if it is all ones.
=0	AR_SHIFT, I FETCH, J/OVTST2 	;this is simply a negative number.
	SET AROV, I FETCH, J/NOP	;sorry, we found some data bits.
OVTST2:	AC0_AR, J/NOP			;finish the store.
.ENDIF/EXTEXP
.TOC	"GFLT DATA CONVERSION INSTRUCTIONS"

.IF/EXTEXP
	.DCODE
021:	EA,	AC,	J/L-GTPI	;GSNGL--Must mate with EXTEND
	EA,		J/L-SFTE	;GDBLE
.IF/GFTCNV
	EA,	B/0,	J/L-GTDI	;GDFIX
024:	EA,	B/2,	J/L-GTSI	;GFIX
	EA,	B/4,	J/L-GTDR	;GDFIXR
	EA,	B/6,	J/L-GTSR	;GFIXR
.ENDIF/GFTCNV
027:	EA,		J/L-DITE	;DGFLTR
030:	EA,		J/L-SITE	;GFLTR
	EA,		J/L-EFSC	;GFSC
	.UCODE

3116:	[AR]_FM[E1], J/L-GTSP	; -21-	GSNGL
3114:	[AR]_FM[E1], J/L-EDBL	; -22-	GDBLE
.IF/GFTCNV		;[273]
3105:	[AR]_FM[E1], J/L-GTIN	; -23-	DGFIX
3106:	[AR]_FM[E1], J/L-GTIN	; -24-	GFIX
3107:	[AR]_FM[E1], J/L-GTIN	; -25-	DGFIXR
3110:	[AR]_FM[E1], J/L-GTIN	; -26-	GFIXR
.ENDIF/GFTCNV		;[273]
3111:	[AR]_FM[E1], J/L-FLTR	; -27-	DGFLTR
3112:	[AR]_FM[E1], J/L-DFLT	; -30-	GFLTR
3113:	[AR]_FM[E1], J/L-DFSC	; -31-	GFSC

L-GTSP:	VMA_AR, LOAD AR		;-21- GSNGL EDPFP TO SPFP
	AR_MEM, MQ_0.S		;load high word into AR.
	GEN AR, SKP AD NE	;check for zeroes.
=0	I FETCH, J/STORAC	;high word zero, store it.
	VMA_VMA+1		;point to mem low word.
=0	ARX_AR, SKP AR0,	;save high word in ARX.
		CALL [ISOEXP]	;get the excess-2000 exponent.
	CLR AR, BR/AR		;exp to BR.
	AR0-8_#, #/220		;largest exponent allowed is 2200.
	GEN AR-BR-1, SKP AD0	;range check exponent.
=0	AR0-8_#, #/157, J/L-GTS1;do lower range check now.(actually too low)
	SET FLOV, I FETCH, J/NOP;tough
L-GTS1:	BR/AR, AR_BR		;swap values around for next subtract.
	GEN AR-BR, SKP AD0	;do lower range check.
=0	BR/AR, CLR AR, J/L-GTS6	;passed. 10 bit path to do last checks.
	SET FXU, I FETCH, J/NOP	;too low.
L-GTS6:	AR0-8_#, #/160		;subtract 1600 to get excess 200 exp.
	AR_BR, BR/AR		;swap around to do subtract.
	AR_AR-BR		;got it.
	AR_AR*8			;move excess-200 exponent over.
	FE_AR0-8, AR_ARX,	;put some exponent in FE. High word to AR.
		LOAD ARX	;low word to ARX.
;This next test determines the relative size of the exponent. If the expo-
;nent is less than 401 then it is a positive exponent and all will be well.
;If the exponent is greater than 400 (actually 700), then the exponent is
;really negative but bit 0 of the FE is off. To correct the sign of the
;exponent and to prevent undeserved FXU later because of the incorrect sign
;bit, we must examine the value of the exponent so as to always get the
;correct sign during normalization.
	ARX_MEM, GEN FE-#,	;undeserved FXU happens when FE00 should be
		#/500, SKP SCAD0;set from previous subtract of 1600.
=0	FE_FE+#, #/777,		;set FE00. Later add will clear it.
		ARX_ARX*2,	;low word * 2.
		J/L-GTS7	;continue.
	FE_FE-1, ARX_ARX*2	;adjust FE so later add gets right exp.
=0
L-GTS7:	SKP AR0, CALL [SGNEXT]	;sign extend high word.
	AR_AR*.25 LONG,		;prepare for normalization
		FE_FE+#, #/6,	;adjust exponent.
		NORM, J/SNORM	;finish up.

L-EDBL:	VMA_AR, LOAD AR		;-22- GDBLE SPFP to EXTENDED EXPONENT
	AR_MEM, CLR MQ
	SC_EXP, ARX_AR, CLR AR	;correct the expoent, save a copy in the ARX
	FM[E1]_AR		;no sticky bits here.
	EXP_SC			;put the "positive" exponent back IN THE AR.
	AR_AR*.5		;must move exponent into AR4-11
	AR_AR*.25		;  done.
	BR/AR, CLR AR		;exp to BR.
	AR0-8_#, #/160		;put 1600 in the AR for exp conversion
	AR_AR+BR, FE_#, #/-3	;convert exp, set initial exp correction
	FM[T2]_AR, AR_ARX	;save exp for ENORM, frac to AR
	EXP_SIGN.C, ARX_0.M	;get rid of exp, clear low word
	GEN AR, SC_#, #/3, NORM,;normalize an extended exponent number
		J/ENORM
.IF/GFTCNV		;[273]
L-GTIN:	VMA_AR, LOAD AR		;23-26. fetch high word.
	AR_MEM, MQ_0.S,		;word in AR, init MQ.
		VMA_VMA+1	;prepare to fetch low word.
	GEN AR, SKP AD NE	;is high word all zeroes ?
=0	CLR ARX, EXIT DBL	;high word zero, store zeroes.
	LOAD ARX, B DISP	;fetch low word, call appropriate routine.

=000	ARX_MEM, J/L-G23	;do GDP to DP integer, truncate.
=010	ARX_MEM, J/L-G24	;do GDP to SP integer, truncate.
=100	ARX_MEM, J/L-G25	;do GDP to DP integer, rounded.
=110	ARX_MEM, J/L-G26	;do GDP to SP integer, rounded.
=				;terminate this dispatch block.

;DGFIX needs the sticky bit fix.
=0010
L-G23:	FE_#, #/70.,		;-23- DGFIX GDP to double integer, truncate.
		CALL [ETXIX]	;do the conversion
=0110	EXIT DBL		;store results.
=0111	BR_AR LONG, AR_ARX,	;save high 2 words in BR!BRX, MSB of
		ARX/MQ,		;fraction to AR35. Rest of fraction to ARX.
		SC_#, #/35.,	;get fraction all together.
		CALL [EF12A]
=1111	GEN AR, SKP AD NE,	;any fraction bits on ?
		MQ_0.S		;[240]CLEAR MQ00 FOR ARX_2 MACRO.
=0	AR_BR LONG, J/ST2AC	;no, leave answer alone.
	CLR AR, ARX_2		;yes, add 1 to integer part.
	AR_AR+BR LONG, J/ST2AC	;store result.

;GFIX needs the sticky bit fix.
=0010
L-G24:	FE_#, #/35.,		;-24- GFIX GDP to single integer, truncate.
		CALL [ETXIX]	;do the conversion
=0110
L-GTS2:	SKP AR NE, J/OVTEST	;test for sign bits in AR and store.
=0111	BR_AR LONG, AR_ARX,	;save in BR!BRX.
		ARX/MQ,		;add one to integer part of negative number
		SC_#, #/35.,	;if fraction is not zero.
		CALL [EF12A]
=1111	GEN AR, SKP AD NE,	;is fraction zero ?
		MQ_0.S		;[240]CLEAR MQ00 FOR ARX_2 MACRO.
=0	AR_BR LONG, SKP AD NE,	;yes, try to store the result.
		J/OVTEST
	CLR AR, ARX_2		;no, add one to integer part.
	AR_AR+BR LONG, SKP AD NE,; do the add and test that the high
		J/OVTEST	;word is all sign bits.

=011
L-G25:	FE_#, #/70.,		;-25- DGFIXR GDP to double integer, rounded.
		CALL [ETXIX]	;do the conversion
=111	BR_AR LONG, CLR AR,	;save in BR!BRX, round by adding one half
		ARX_1,		;to result. Remember that the MSB of the
		SC_#, #/35.	;store routine expects this.
	AR_AR+BR LONG, AD FLAGS	;fraction is on ARX35.  Do the rounding and
;=0	; replace SKP CRY0 with AD FLAGS. Eliminates extra word.
	EXIT DBL		;  store the double result.
;	SET AROV, I FETCH, J/NOP;rounding caused an overflow - too bad!

=011
L-G26:	FE_#, #/35.,		;-26- GFIXR GDP to single integer, rounded.
		CALL [ETXIX]	;do the conversion.
=111	BR_AR LONG, CLR AR,	;save in CR!BRX, round by adding one half
		ARX_1,		;to result. MSB of the fraction is in ARX35.
		SC_#, #/35.	;store routine expects this.
	AR_AR+BR LONG, SKP AD NE,;do the rounding.
		J/OVTEST	;figure out what, if any, to store.
.ENDIF/GFTCNV		;[273]
L-FLTR:	VMA_AR, LOAD AR,	;-27- DGFLTR DP INTEGER to EDPFP
		FE_#, #/137	;inital fugde factor for exp
	AR_MEM, MQ_0.S		;get high word into the AR.
=0*	VMA_VMA+1, LOAD ARX,	;get the low word into the ARX,
		BR/AR, CALL [XFERW]; and save the high word in the BR.
=1*	ARX_ARX*2, CLR AR	;ignore the sign copy.
	FM[E1]_AR		;no sticky bits here.
	AR0-8_#, #/200		;ENORM expects the exponent in T2.
	FM[T2]_AR, AR_BR,	;and save it in T2.
		ARX/AD, MQ_ARX	;sign to AR, high to ARX, low to MQ.
	AR_SIGN 		;
	GEN AR, NORM, J/ENORM	;restore high word and normalize.
L-DFLT:	VMA_AR, LOAD AR,	;-30- GFLTRSP INTEGER to EDPFP
		FE_#, #/4	;initial fudge factor for exp.
	AR_MEM, CLR MQ		;get the single precision op.
	AR_SIGN, ARX_AR		;build a dummy high word of all sign.
	BR/AR, CLR AR		;save sign, prepare for exponent.
	FM[E1]_AR		;no sticky bits here.
	AR0-8_#, #/207		;build an initial exp of 207 for ENORM
	FM[T2]_AR, AR_BR,	;save exp for ENORM, restore sign word.
		NORM, J/ENORM	;and normalize it.

=0
L-DFSC:	AR_AC0, BR/AR, SKP AD0,	;-31- GFSC EDPFP SCALE
		CALL [ISOEXP]	;get the exponent into the AR.
	BR/AR, AR_BR		;put exp in BR, scale factor to AR.
	AR_AR SWAP, GEN AC0,	;put scale in left half of AR.
		SKP AD NE	;is high word zero ?
=0	AR+ARX+MQ_0.M, J/ST2AC	;yes, store zero as double result.
	AR_SIGN, ARX_AR, SC_#,	;no, move sign and scale factor together.
		#/34.
	AR_SHIFT, CLR FE	;sign now in AR00, scale in AR 9-19.
	EXP_SIGN		;scale sign is in AR00; extend it.
	SC_#, #/8.		;move scale factor into AR 1-11 and
	AR_SHIFT, ARX_AC1	; put the sign to left of scale factor.
	AR_AR+BR, CLR MQ	;add exponent and scale factor.
	SH/AR, DISP/SH0-3	;check for over and under flovs.
=0011
L-FSC2:	[AR]_[AR]*FM[EXPMSK],	;clear out non-exponent bits.
		AD/ANDCB,	;and AR00 in the over or under flow case.
		J/L-FSC3	; and continue
=0111	[AR]_[AR]*FM[EXPMSK],	;clear out non-exponent bits.
		AD/ANDCB,	;
		J/L-FSC3	; and continue
=1011	SET FLOV, J/L-FSC2	;you lose
=1111	SET FXU, J/L-FSC2	;ditto

L-FSC3:	FM[T2]_AR, ARX_ARX*2	;save new exponent fofr ENORM.
=0	AR_AC0, SKP AD0,	;get the high word.
		SC_#, #/3,	;for ENORM.
		CALL [SGNEXT]	;and sign extend it for ENORM as well.
	GEN AR, NORM, J/ENORM	;put the result back together.

.ENDIF/EXTEXP