xref: /netbsd-src/sys/arch/m68k/fpsp/bindec.sa (revision c869df6afb6340aa888ce50a803c068283b84d8b)
1*c869df6aSbriggs*	$NetBSD: bindec.sa,v 1.5 2001/12/09 01:43:13 briggs Exp $
257fb77a1Scgd
322ef5fa9Smycroft*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
422ef5fa9Smycroft*	M68000 Hi-Performance Microprocessor Division
522ef5fa9Smycroft*	M68040 Software Package
622ef5fa9Smycroft*
722ef5fa9Smycroft*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
822ef5fa9Smycroft*	All rights reserved.
922ef5fa9Smycroft*
1022ef5fa9Smycroft*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
1122ef5fa9Smycroft*	To the maximum extent permitted by applicable law,
1222ef5fa9Smycroft*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
1322ef5fa9Smycroft*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
1422ef5fa9Smycroft*	PARTICULAR PURPOSE and any warranty against infringement with
1522ef5fa9Smycroft*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
1622ef5fa9Smycroft*	and any accompanying written materials.
1722ef5fa9Smycroft*
1822ef5fa9Smycroft*	To the maximum extent permitted by applicable law,
1922ef5fa9Smycroft*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
2022ef5fa9Smycroft*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
2122ef5fa9Smycroft*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
2222ef5fa9Smycroft*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
2322ef5fa9Smycroft*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
2422ef5fa9Smycroft*	and support of the SOFTWARE.
2522ef5fa9Smycroft*
2622ef5fa9Smycroft*	You are hereby granted a copyright license to use, modify, and
2722ef5fa9Smycroft*	distribute the SOFTWARE so long as this entire notice is retained
2822ef5fa9Smycroft*	without alteration in any modified and/or redistributed versions,
2922ef5fa9Smycroft*	and that such modified versions are clearly identified as such.
3022ef5fa9Smycroft*	No licenses are granted by implication, estoppel or otherwise
3122ef5fa9Smycroft*	under any patents or trademarks of Motorola, Inc.
3222ef5fa9Smycroft
3322ef5fa9Smycroft*
3422ef5fa9Smycroft*	bindec.sa 3.4 1/3/91
3522ef5fa9Smycroft*
3622ef5fa9Smycroft*	bindec
3722ef5fa9Smycroft*
3822ef5fa9Smycroft*	Description:
3922ef5fa9Smycroft*		Converts an input in extended precision format
4022ef5fa9Smycroft*		to bcd format.
4122ef5fa9Smycroft*
4222ef5fa9Smycroft*	Input:
4322ef5fa9Smycroft*		a0 points to the input extended precision value
4422ef5fa9Smycroft*		value in memory; d0 contains the k-factor sign-extended
4522ef5fa9Smycroft*		to 32-bits.  The input may be either normalized,
4622ef5fa9Smycroft*		unnormalized, or denormalized.
4722ef5fa9Smycroft*
4822ef5fa9Smycroft*	Output:	result in the FP_SCR1 space on the stack.
4922ef5fa9Smycroft*
5022ef5fa9Smycroft*	Saves and Modifies: D2-D7,A2,FP2
5122ef5fa9Smycroft*
5222ef5fa9Smycroft*	Algorithm:
5322ef5fa9Smycroft*
5422ef5fa9Smycroft*	A1.	Set RM and size ext;  Set SIGMA = sign of input.
5522ef5fa9Smycroft*		The k-factor is saved for use in d7. Clear the
5622ef5fa9Smycroft*		BINDEC_FLG for separating normalized/denormalized
5722ef5fa9Smycroft*		input.  If input is unnormalized or denormalized,
5822ef5fa9Smycroft*		normalize it.
5922ef5fa9Smycroft*
6022ef5fa9Smycroft*	A2.	Set X = abs(input).
6122ef5fa9Smycroft*
6222ef5fa9Smycroft*	A3.	Compute ILOG.
6322ef5fa9Smycroft*		ILOG is the log base 10 of the input value.  It is
6422ef5fa9Smycroft*		approximated by adding e + 0.f when the original
6522ef5fa9Smycroft*		value is viewed as 2^^e * 1.f in extended precision.
6622ef5fa9Smycroft*		This value is stored in d6.
6722ef5fa9Smycroft*
6822ef5fa9Smycroft*	A4.	Clr INEX bit.
6922ef5fa9Smycroft*		The operation in A3 above may have set INEX2.
7022ef5fa9Smycroft*
7122ef5fa9Smycroft*	A5.	Set ICTR = 0;
7222ef5fa9Smycroft*		ICTR is a flag used in A13.  It must be set before the
7322ef5fa9Smycroft*		loop entry A6.
7422ef5fa9Smycroft*
7522ef5fa9Smycroft*	A6.	Calculate LEN.
7622ef5fa9Smycroft*		LEN is the number of digits to be displayed.  The
7722ef5fa9Smycroft*		k-factor can dictate either the total number of digits,
7822ef5fa9Smycroft*		if it is a positive number, or the number of digits
7922ef5fa9Smycroft*		after the decimal point which are to be included as
8022ef5fa9Smycroft*		significant.  See the 68882 manual for examples.
8122ef5fa9Smycroft*		If LEN is computed to be greater than 17, set OPERR in
8222ef5fa9Smycroft*		USER_FPSR.  LEN is stored in d4.
8322ef5fa9Smycroft*
8422ef5fa9Smycroft*	A7.	Calculate SCALE.
8522ef5fa9Smycroft*		SCALE is equal to 10^ISCALE, where ISCALE is the number
8622ef5fa9Smycroft*		of decimal places needed to insure LEN integer digits
8722ef5fa9Smycroft*		in the output before conversion to bcd. LAMBDA is the
8822ef5fa9Smycroft*		sign of ISCALE, used in A9. Fp1 contains
8922ef5fa9Smycroft*		10^^(abs(ISCALE)) using a rounding mode which is a
9022ef5fa9Smycroft*		function of the original rounding mode and the signs
9122ef5fa9Smycroft*		of ISCALE and X.  A table is given in the code.
9222ef5fa9Smycroft*
9322ef5fa9Smycroft*	A8.	Clr INEX; Force RZ.
9422ef5fa9Smycroft*		The operation in A3 above may have set INEX2.
9522ef5fa9Smycroft*		RZ mode is forced for the scaling operation to insure
9622ef5fa9Smycroft*		only one rounding error.  The grs bits are collected in
9722ef5fa9Smycroft*		the INEX flag for use in A10.
9822ef5fa9Smycroft*
9922ef5fa9Smycroft*	A9.	Scale X -> Y.
10022ef5fa9Smycroft*		The mantissa is scaled to the desired number of
10122ef5fa9Smycroft*		significant digits.  The excess digits are collected
10222ef5fa9Smycroft*		in INEX2.
10322ef5fa9Smycroft*
10422ef5fa9Smycroft*	A10.	Or in INEX.
105456dff6cSwiz*		If INEX is set, round error occurred.  This is
10622ef5fa9Smycroft*		compensated for by 'or-ing' in the INEX2 flag to
10722ef5fa9Smycroft*		the lsb of Y.
10822ef5fa9Smycroft*
10922ef5fa9Smycroft*	A11.	Restore original FPCR; set size ext.
11022ef5fa9Smycroft*		Perform FINT operation in the user's rounding mode.
11122ef5fa9Smycroft*		Keep the size to extended.
11222ef5fa9Smycroft*
11322ef5fa9Smycroft*	A12.	Calculate YINT = FINT(Y) according to user's rounding
11422ef5fa9Smycroft*		mode.  The FPSP routine sintd0 is used.  The output
11522ef5fa9Smycroft*		is in fp0.
11622ef5fa9Smycroft*
11722ef5fa9Smycroft*	A13.	Check for LEN digits.
11822ef5fa9Smycroft*		If the int operation results in more than LEN digits,
11922ef5fa9Smycroft*		or less than LEN -1 digits, adjust ILOG and repeat from
12022ef5fa9Smycroft*		A6.  This test occurs only on the first pass.  If the
12122ef5fa9Smycroft*		result is exactly 10^LEN, decrement ILOG and divide
12222ef5fa9Smycroft*		the mantissa by 10.
12322ef5fa9Smycroft*
12422ef5fa9Smycroft*	A14.	Convert the mantissa to bcd.
12522ef5fa9Smycroft*		The binstr routine is used to convert the LEN digit
12622ef5fa9Smycroft*		mantissa to bcd in memory.  The input to binstr is
12722ef5fa9Smycroft*		to be a fraction; i.e. (mantissa)/10^LEN and adjusted
12822ef5fa9Smycroft*		such that the decimal point is to the left of bit 63.
12922ef5fa9Smycroft*		The bcd digits are stored in the correct position in
13022ef5fa9Smycroft*		the final string area in memory.
13122ef5fa9Smycroft*
13222ef5fa9Smycroft*	A15.	Convert the exponent to bcd.
13322ef5fa9Smycroft*		As in A14 above, the exp is converted to bcd and the
13422ef5fa9Smycroft*		digits are stored in the final string.
13522ef5fa9Smycroft*		Test the length of the final exponent string.  If the
13622ef5fa9Smycroft*		length is 4, set operr.
13722ef5fa9Smycroft*
13822ef5fa9Smycroft*	A16.	Write sign bits to final string.
13922ef5fa9Smycroft*
14022ef5fa9Smycroft*	Implementation Notes:
14122ef5fa9Smycroft*
14222ef5fa9Smycroft*	The registers are used as follows:
14322ef5fa9Smycroft*
14422ef5fa9Smycroft*		d0: scratch; LEN input to binstr
14522ef5fa9Smycroft*		d1: scratch
14622ef5fa9Smycroft*		d2: upper 32-bits of mantissa for binstr
14722ef5fa9Smycroft*		d3: scratch;lower 32-bits of mantissa for binstr
14822ef5fa9Smycroft*		d4: LEN
14922ef5fa9Smycroft*      		d5: LAMBDA/ICTR
15022ef5fa9Smycroft*		d6: ILOG
15122ef5fa9Smycroft*		d7: k-factor
15222ef5fa9Smycroft*		a0: ptr for original operand/final result
15322ef5fa9Smycroft*		a1: scratch pointer
15422ef5fa9Smycroft*		a2: pointer to FP_X; abs(original value) in ext
15522ef5fa9Smycroft*		fp0: scratch
15622ef5fa9Smycroft*		fp1: scratch
15722ef5fa9Smycroft*		fp2: scratch
15822ef5fa9Smycroft*		F_SCR1:
15922ef5fa9Smycroft*		F_SCR2:
16022ef5fa9Smycroft*		L_SCR1:
16122ef5fa9Smycroft*		L_SCR2:
16222ef5fa9Smycroft*
16322ef5fa9Smycroft
16422ef5fa9SmycroftBINDEC    IDNT    2,1 Motorola 040 Floating Point Software Package
16522ef5fa9Smycroft
16622ef5fa9Smycroft	include	fpsp.h
16722ef5fa9Smycroft
16822ef5fa9Smycroft	section	8
16922ef5fa9Smycroft
17022ef5fa9Smycroft* Constants in extended precision
17122ef5fa9SmycroftLOG2 	dc.l	$3FFD0000,$9A209A84,$FBCFF798,$00000000
17222ef5fa9SmycroftLOG2UP1	dc.l	$3FFD0000,$9A209A84,$FBCFF799,$00000000
17322ef5fa9Smycroft
17422ef5fa9Smycroft* Constants in single precision
17522ef5fa9SmycroftFONE 	dc.l	$3F800000,$00000000,$00000000,$00000000
17622ef5fa9SmycroftFTWO	dc.l	$40000000,$00000000,$00000000,$00000000
17722ef5fa9SmycroftFTEN 	dc.l	$41200000,$00000000,$00000000,$00000000
17822ef5fa9SmycroftF4933	dc.l	$459A2800,$00000000,$00000000,$00000000
17922ef5fa9Smycroft
18022ef5fa9SmycroftRBDTBL 	dc.b	0,0,0,0
18122ef5fa9Smycroft	dc.b	3,3,2,2
18222ef5fa9Smycroft	dc.b	3,2,2,3
18322ef5fa9Smycroft	dc.b	2,3,3,2
18422ef5fa9Smycroft
18522ef5fa9Smycroft	xref	binstr
18622ef5fa9Smycroft	xref	sintdo
18722ef5fa9Smycroft	xref	ptenrn,ptenrm,ptenrp
18822ef5fa9Smycroft
18922ef5fa9Smycroft	xdef	bindec
19022ef5fa9Smycroft	xdef	sc_mul
19122ef5fa9Smycroftbindec:
19222ef5fa9Smycroft	movem.l	d2-d7/a2,-(a7)
19322ef5fa9Smycroft	fmovem.x fp0-fp2,-(a7)
19422ef5fa9Smycroft
19522ef5fa9Smycroft* A1. Set RM and size ext. Set SIGMA = sign input;
19622ef5fa9Smycroft*     The k-factor is saved for use in d7.  Clear BINDEC_FLG for
19722ef5fa9Smycroft*     separating  normalized/denormalized input.  If the input
19822ef5fa9Smycroft*     is a denormalized number, set the BINDEC_FLG memory word
19922ef5fa9Smycroft*     to signal denorm.  If the input is unnormalized, normalize
20022ef5fa9Smycroft*     the input and test for denormalized result.
20122ef5fa9Smycroft*
20222ef5fa9Smycroft	fmove.l	#rm_mode,FPCR	;set RM and ext
20322ef5fa9Smycroft	move.l	(a0),L_SCR2(a6)	;save exponent for sign check
20422ef5fa9Smycroft	move.l	d0,d7		;move k-factor to d7
20522ef5fa9Smycroft	clr.b	BINDEC_FLG(a6)	;clr norm/denorm flag
20622ef5fa9Smycroft	move.w	STAG(a6),d0	;get stag
20722ef5fa9Smycroft	andi.w	#$e000,d0	;isolate stag bits
20822ef5fa9Smycroft	beq	A2_str		;if zero, input is norm
20922ef5fa9Smycroft*
21022ef5fa9Smycroft* Normalize the denorm
21122ef5fa9Smycroft*
21222ef5fa9Smycroftun_de_norm:
21322ef5fa9Smycroft	move.w	(a0),d0
21422ef5fa9Smycroft	andi.w	#$7fff,d0	;strip sign of normalized exp
21522ef5fa9Smycroft	move.l	4(a0),d1
21622ef5fa9Smycroft	move.l	8(a0),d2
21722ef5fa9Smycroftnorm_loop:
21822ef5fa9Smycroft	sub.w	#1,d0
219eddb30abSmycroft	add.l	d2,d2
220eddb30abSmycroft	addx.l	d1,d1
22122ef5fa9Smycroft	tst.l	d1
22222ef5fa9Smycroft	bge.b	norm_loop
22322ef5fa9Smycroft*
22422ef5fa9Smycroft* Test if the normalized input is denormalized
22522ef5fa9Smycroft*
22622ef5fa9Smycroft	tst.w	d0
22722ef5fa9Smycroft	bgt.b	pos_exp		;if greater than zero, it is a norm
22822ef5fa9Smycroft	st	BINDEC_FLG(a6)	;set flag for denorm
22922ef5fa9Smycroftpos_exp:
23022ef5fa9Smycroft	andi.w	#$7fff,d0	;strip sign of normalized exp
23122ef5fa9Smycroft	move.w	d0,(a0)
23222ef5fa9Smycroft	move.l	d1,4(a0)
23322ef5fa9Smycroft	move.l	d2,8(a0)
23422ef5fa9Smycroft
23522ef5fa9Smycroft* A2. Set X = abs(input).
23622ef5fa9Smycroft*
23722ef5fa9SmycroftA2_str:
23822ef5fa9Smycroft	move.l	(a0),FP_SCR2(a6) ; move input to work space
23922ef5fa9Smycroft	move.l	4(a0),FP_SCR2+4(a6) ; move input to work space
24022ef5fa9Smycroft	move.l	8(a0),FP_SCR2+8(a6) ; move input to work space
24122ef5fa9Smycroft	andi.l	#$7fffffff,FP_SCR2(a6) ;create abs(X)
24222ef5fa9Smycroft
24322ef5fa9Smycroft* A3. Compute ILOG.
24422ef5fa9Smycroft*     ILOG is the log base 10 of the input value.  It is approx-
24522ef5fa9Smycroft*     imated by adding e + 0.f when the original value is viewed
24622ef5fa9Smycroft*     as 2^^e * 1.f in extended precision.  This value is stored
24722ef5fa9Smycroft*     in d6.
24822ef5fa9Smycroft*
24922ef5fa9Smycroft* Register usage:
25022ef5fa9Smycroft*	Input/Output
25122ef5fa9Smycroft*	d0: k-factor/exponent
25222ef5fa9Smycroft*	d2: x/x
25322ef5fa9Smycroft*	d3: x/x
25422ef5fa9Smycroft*	d4: x/x
25522ef5fa9Smycroft*	d5: x/x
25622ef5fa9Smycroft*	d6: x/ILOG
25722ef5fa9Smycroft*	d7: k-factor/Unchanged
25822ef5fa9Smycroft*	a0: ptr for original operand/final result
25922ef5fa9Smycroft*	a1: x/x
26022ef5fa9Smycroft*	a2: x/x
26122ef5fa9Smycroft*	fp0: x/float(ILOG)
26222ef5fa9Smycroft*	fp1: x/x
26322ef5fa9Smycroft*	fp2: x/x
26422ef5fa9Smycroft*	F_SCR1:x/x
26522ef5fa9Smycroft*	F_SCR2:Abs(X)/Abs(X) with $3fff exponent
26622ef5fa9Smycroft*	L_SCR1:x/x
26722ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
26822ef5fa9Smycroft
26922ef5fa9Smycroft	tst.b	BINDEC_FLG(a6)	;check for denorm
27022ef5fa9Smycroft	beq.b	A3_cont		;if clr, continue with norm
27122ef5fa9Smycroft	move.l	#-4933,d6	;force ILOG = -4933
27222ef5fa9Smycroft	bra.b	A4_str
27322ef5fa9SmycroftA3_cont:
27422ef5fa9Smycroft	move.w	FP_SCR2(a6),d0	;move exp to d0
27522ef5fa9Smycroft	move.w	#$3fff,FP_SCR2(a6) ;replace exponent with 0x3fff
27622ef5fa9Smycroft	fmove.x	FP_SCR2(a6),fp0	;now fp0 has 1.f
27722ef5fa9Smycroft	sub.w	#$3fff,d0	;strip off bias
27822ef5fa9Smycroft	fadd.w	d0,fp0		;add in exp
27922ef5fa9Smycroft	fsub.s	FONE,fp0	;subtract off 1.0
28022ef5fa9Smycroft	fbge.w	pos_res		;if pos, branch
28122ef5fa9Smycroft	fmul.x	LOG2UP1,fp0	;if neg, mul by LOG2UP1
28222ef5fa9Smycroft	fmove.l	fp0,d6		;put ILOG in d6 as a lword
28322ef5fa9Smycroft	bra.b	A4_str		;go move out ILOG
28422ef5fa9Smycroftpos_res:
28522ef5fa9Smycroft	fmul.x	LOG2,fp0	;if pos, mul by LOG2
28622ef5fa9Smycroft	fmove.l	fp0,d6		;put ILOG in d6 as a lword
28722ef5fa9Smycroft
28822ef5fa9Smycroft
28922ef5fa9Smycroft* A4. Clr INEX bit.
29022ef5fa9Smycroft*     The operation in A3 above may have set INEX2.
29122ef5fa9Smycroft
29222ef5fa9SmycroftA4_str:
29322ef5fa9Smycroft	fmove.l	#0,FPSR		;zero all of fpsr - nothing needed
29422ef5fa9Smycroft
29522ef5fa9Smycroft
29622ef5fa9Smycroft* A5. Set ICTR = 0;
29722ef5fa9Smycroft*     ICTR is a flag used in A13.  It must be set before the
29822ef5fa9Smycroft*     loop entry A6. The lower word of d5 is used for ICTR.
29922ef5fa9Smycroft
30022ef5fa9Smycroft	clr.w	d5		;clear ICTR
30122ef5fa9Smycroft
30222ef5fa9Smycroft
30322ef5fa9Smycroft* A6. Calculate LEN.
30422ef5fa9Smycroft*     LEN is the number of digits to be displayed.  The k-factor
30522ef5fa9Smycroft*     can dictate either the total number of digits, if it is
30622ef5fa9Smycroft*     a positive number, or the number of digits after the
30722ef5fa9Smycroft*     original decimal point which are to be included as
30822ef5fa9Smycroft*     significant.  See the 68882 manual for examples.
30922ef5fa9Smycroft*     If LEN is computed to be greater than 17, set OPERR in
31022ef5fa9Smycroft*     USER_FPSR.  LEN is stored in d4.
31122ef5fa9Smycroft*
31222ef5fa9Smycroft* Register usage:
31322ef5fa9Smycroft*	Input/Output
31422ef5fa9Smycroft*	d0: exponent/Unchanged
31522ef5fa9Smycroft*	d2: x/x/scratch
31622ef5fa9Smycroft*	d3: x/x
31722ef5fa9Smycroft*	d4: exc picture/LEN
31822ef5fa9Smycroft*	d5: ICTR/Unchanged
31922ef5fa9Smycroft*	d6: ILOG/Unchanged
32022ef5fa9Smycroft*	d7: k-factor/Unchanged
32122ef5fa9Smycroft*	a0: ptr for original operand/final result
32222ef5fa9Smycroft*	a1: x/x
32322ef5fa9Smycroft*	a2: x/x
32422ef5fa9Smycroft*	fp0: float(ILOG)/Unchanged
32522ef5fa9Smycroft*	fp1: x/x
32622ef5fa9Smycroft*	fp2: x/x
32722ef5fa9Smycroft*	F_SCR1:x/x
32822ef5fa9Smycroft*	F_SCR2:Abs(X) with $3fff exponent/Unchanged
32922ef5fa9Smycroft*	L_SCR1:x/x
33022ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
33122ef5fa9Smycroft
33222ef5fa9SmycroftA6_str:
33322ef5fa9Smycroft	tst.l	d7		;branch on sign of k
33422ef5fa9Smycroft	ble.b	k_neg		;if k <= 0, LEN = ILOG + 1 - k
33522ef5fa9Smycroft	move.l	d7,d4		;if k > 0, LEN = k
33622ef5fa9Smycroft	bra.b	len_ck		;skip to LEN check
33722ef5fa9Smycroftk_neg:
33822ef5fa9Smycroft	move.l	d6,d4		;first load ILOG to d4
33922ef5fa9Smycroft	sub.l	d7,d4		;subtract off k
34022ef5fa9Smycroft	addq.l	#1,d4		;add in the 1
34122ef5fa9Smycroftlen_ck:
34222ef5fa9Smycroft	tst.l	d4		;LEN check: branch on sign of LEN
34322ef5fa9Smycroft	ble.b	LEN_ng		;if neg, set LEN = 1
34422ef5fa9Smycroft	cmp.l	#17,d4		;test if LEN > 17
34522ef5fa9Smycroft	ble.b	A7_str		;if not, forget it
34622ef5fa9Smycroft	move.l	#17,d4		;set max LEN = 17
34722ef5fa9Smycroft	tst.l	d7		;if negative, never set OPERR
34822ef5fa9Smycroft	ble.b	A7_str		;if positive, continue
34922ef5fa9Smycroft	or.l	#opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR
35022ef5fa9Smycroft	bra.b	A7_str		;finished here
35122ef5fa9SmycroftLEN_ng:
35222ef5fa9Smycroft	moveq.l	#1,d4		;min LEN is 1
35322ef5fa9Smycroft
35422ef5fa9Smycroft
35522ef5fa9Smycroft* A7. Calculate SCALE.
35622ef5fa9Smycroft*     SCALE is equal to 10^ISCALE, where ISCALE is the number
35722ef5fa9Smycroft*     of decimal places needed to insure LEN integer digits
35822ef5fa9Smycroft*     in the output before conversion to bcd. LAMBDA is the sign
35922ef5fa9Smycroft*     of ISCALE, used in A9.  Fp1 contains 10^^(abs(ISCALE)) using
36022ef5fa9Smycroft*     the rounding mode as given in the following table (see
36122ef5fa9Smycroft*     Coonen, p. 7.23 as ref.; however, the SCALE variable is
36222ef5fa9Smycroft*     of opposite sign in bindec.sa from Coonen).
36322ef5fa9Smycroft*
36422ef5fa9Smycroft*	Initial					USE
36522ef5fa9Smycroft*	FPCR[6:5]	LAMBDA	SIGN(X)		FPCR[6:5]
36622ef5fa9Smycroft*	----------------------------------------------
36722ef5fa9Smycroft*	 RN	00	   0	   0		00/0	RN
36822ef5fa9Smycroft*	 RN	00	   0	   1		00/0	RN
36922ef5fa9Smycroft*	 RN	00	   1	   0		00/0	RN
37022ef5fa9Smycroft*	 RN	00	   1	   1		00/0	RN
37122ef5fa9Smycroft*	 RZ	01	   0	   0		11/3	RP
37222ef5fa9Smycroft*	 RZ	01	   0	   1		11/3	RP
37322ef5fa9Smycroft*	 RZ	01	   1	   0		10/2	RM
37422ef5fa9Smycroft*	 RZ	01	   1	   1		10/2	RM
37522ef5fa9Smycroft*	 RM	10	   0	   0		11/3	RP
37622ef5fa9Smycroft*	 RM	10	   0	   1		10/2	RM
37722ef5fa9Smycroft*	 RM	10	   1	   0		10/2	RM
37822ef5fa9Smycroft*	 RM	10	   1	   1		11/3	RP
37922ef5fa9Smycroft*	 RP	11	   0	   0		10/2	RM
38022ef5fa9Smycroft*	 RP	11	   0	   1		11/3	RP
38122ef5fa9Smycroft*	 RP	11	   1	   0		11/3	RP
38222ef5fa9Smycroft*	 RP	11	   1	   1		10/2	RM
38322ef5fa9Smycroft*
38422ef5fa9Smycroft* Register usage:
38522ef5fa9Smycroft*	Input/Output
38622ef5fa9Smycroft*	d0: exponent/scratch - final is 0
38722ef5fa9Smycroft*	d2: x/0 or 24 for A9
38822ef5fa9Smycroft*	d3: x/scratch - offset ptr into PTENRM array
38922ef5fa9Smycroft*	d4: LEN/Unchanged
39022ef5fa9Smycroft*	d5: 0/ICTR:LAMBDA
39122ef5fa9Smycroft*	d6: ILOG/ILOG or k if ((k<=0)&(ILOG<k))
39222ef5fa9Smycroft*	d7: k-factor/Unchanged
39322ef5fa9Smycroft*	a0: ptr for original operand/final result
39422ef5fa9Smycroft*	a1: x/ptr to PTENRM array
39522ef5fa9Smycroft*	a2: x/x
39622ef5fa9Smycroft*	fp0: float(ILOG)/Unchanged
39722ef5fa9Smycroft*	fp1: x/10^ISCALE
39822ef5fa9Smycroft*	fp2: x/x
39922ef5fa9Smycroft*	F_SCR1:x/x
40022ef5fa9Smycroft*	F_SCR2:Abs(X) with $3fff exponent/Unchanged
40122ef5fa9Smycroft*	L_SCR1:x/x
40222ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
40322ef5fa9Smycroft
40422ef5fa9SmycroftA7_str:
40522ef5fa9Smycroft	tst.l	d7		;test sign of k
40622ef5fa9Smycroft	bgt.b	k_pos		;if pos and > 0, skip this
40722ef5fa9Smycroft	cmp.l	d6,d7		;test k - ILOG
40822ef5fa9Smycroft	blt.b	k_pos		;if ILOG >= k, skip this
40922ef5fa9Smycroft	move.l	d7,d6		;if ((k<0) & (ILOG < k)) ILOG = k
41022ef5fa9Smycroftk_pos:
41122ef5fa9Smycroft	move.l	d6,d0		;calc ILOG + 1 - LEN in d0
41222ef5fa9Smycroft	addq.l	#1,d0		;add the 1
41322ef5fa9Smycroft	sub.l	d4,d0		;sub off LEN
41422ef5fa9Smycroft	swap	d5		;use upper word of d5 for LAMBDA
41522ef5fa9Smycroft	clr.w	d5		;set it zero initially
41622ef5fa9Smycroft	clr.w	d2		;set up d2 for very small case
41722ef5fa9Smycroft	tst.l	d0		;test sign of ISCALE
41822ef5fa9Smycroft	bge.b	iscale		;if pos, skip next inst
41922ef5fa9Smycroft	addq.w	#1,d5		;if neg, set LAMBDA true
42022ef5fa9Smycroft	cmp.l	#$ffffecd4,d0	;test iscale <= -4908
42122ef5fa9Smycroft	bgt.b	no_inf		;if false, skip rest
42222ef5fa9Smycroft	addi.l	#24,d0		;add in 24 to iscale
42322ef5fa9Smycroft	move.l	#24,d2		;put 24 in d2 for A9
42422ef5fa9Smycroftno_inf:
42522ef5fa9Smycroft	neg.l	d0		;and take abs of ISCALE
42622ef5fa9Smycroftiscale:
42722ef5fa9Smycroft	fmove.s	FONE,fp1	;init fp1 to 1
42822ef5fa9Smycroft	bfextu	USER_FPCR(a6){26:2},d1 ;get initial rmode bits
429eddb30abSmycroft	add.w	d1,d1		;put them in bits 2:1
43022ef5fa9Smycroft	add.w	d5,d1		;add in LAMBDA
431eddb30abSmycroft	add.w	d1,d1		;put them in bits 3:1
43222ef5fa9Smycroft	tst.l	L_SCR2(a6)	;test sign of original x
43322ef5fa9Smycroft	bge.b	x_pos		;if pos, don't set bit 0
43422ef5fa9Smycroft	addq.l	#1,d1		;if neg, set bit 0
43522ef5fa9Smycroftx_pos:
43622ef5fa9Smycroft	lea.l	RBDTBL,a2	;load rbdtbl base
43722ef5fa9Smycroft	move.b	(a2,d1),d3	;load d3 with new rmode
43822ef5fa9Smycroft	lsl.l	#4,d3		;put bits in proper position
43922ef5fa9Smycroft	fmove.l	d3,fpcr		;load bits into fpu
44022ef5fa9Smycroft	lsr.l	#4,d3		;put bits in proper position
44122ef5fa9Smycroft	tst.b	d3		;decode new rmode for pten table
44222ef5fa9Smycroft	bne.b	not_rn		;if zero, it is RN
44322ef5fa9Smycroft	lea.l	PTENRN,a1	;load a1 with RN table base
44422ef5fa9Smycroft	bra.b	rmode		;exit decode
44522ef5fa9Smycroftnot_rn:
44622ef5fa9Smycroft	lsr.b	#1,d3		;get lsb in carry
44722ef5fa9Smycroft	bcc.b	not_rp		;if carry clear, it is RM
44822ef5fa9Smycroft	lea.l	PTENRP,a1	;load a1 with RP table base
44922ef5fa9Smycroft	bra.b	rmode		;exit decode
45022ef5fa9Smycroftnot_rp:
45122ef5fa9Smycroft	lea.l	PTENRM,a1	;load a1 with RM table base
45222ef5fa9Smycroftrmode:
45322ef5fa9Smycroft	clr.l	d3		;clr table index
45422ef5fa9Smycrofte_loop:
45522ef5fa9Smycroft	lsr.l	#1,d0		;shift next bit into carry
45622ef5fa9Smycroft	bcc.b	e_next		;if zero, skip the mul
45722ef5fa9Smycroft	fmul.x	(a1,d3),fp1	;mul by 10**(d3_bit_no)
45822ef5fa9Smycrofte_next:
45922ef5fa9Smycroft	add.l	#12,d3		;inc d3 to next pwrten table entry
46022ef5fa9Smycroft	tst.l	d0		;test if ISCALE is zero
46122ef5fa9Smycroft	bne.b	e_loop		;if not, loop
46222ef5fa9Smycroft
46322ef5fa9Smycroft
46422ef5fa9Smycroft* A8. Clr INEX; Force RZ.
46522ef5fa9Smycroft*     The operation in A3 above may have set INEX2.
46622ef5fa9Smycroft*     RZ mode is forced for the scaling operation to insure
46722ef5fa9Smycroft*     only one rounding error.  The grs bits are collected in
46822ef5fa9Smycroft*     the INEX flag for use in A10.
46922ef5fa9Smycroft*
47022ef5fa9Smycroft* Register usage:
47122ef5fa9Smycroft*	Input/Output
47222ef5fa9Smycroft
47322ef5fa9Smycroft	fmove.l	#0,FPSR		;clr INEX
47422ef5fa9Smycroft	fmove.l	#rz_mode,FPCR	;set RZ rounding mode
47522ef5fa9Smycroft
47622ef5fa9Smycroft
47722ef5fa9Smycroft* A9. Scale X -> Y.
47822ef5fa9Smycroft*     The mantissa is scaled to the desired number of significant
47922ef5fa9Smycroft*     digits.  The excess digits are collected in INEX2. If mul,
48022ef5fa9Smycroft*     Check d2 for excess 10 exponential value.  If not zero,
48122ef5fa9Smycroft*     the iscale value would have caused the pwrten calculation
48222ef5fa9Smycroft*     to overflow.  Only a negative iscale can cause this, so
48322ef5fa9Smycroft*     multiply by 10^(d2), which is now only allowed to be 24,
48422ef5fa9Smycroft*     with a multiply by 10^8 and 10^16, which is exact since
48522ef5fa9Smycroft*     10^24 is exact.  If the input was denormalized, we must
48622ef5fa9Smycroft*     create a busy stack frame with the mul command and the
48722ef5fa9Smycroft*     two operands, and allow the fpu to complete the multiply.
48822ef5fa9Smycroft*
48922ef5fa9Smycroft* Register usage:
49022ef5fa9Smycroft*	Input/Output
49122ef5fa9Smycroft*	d0: FPCR with RZ mode/Unchanged
49222ef5fa9Smycroft*	d2: 0 or 24/unchanged
49322ef5fa9Smycroft*	d3: x/x
49422ef5fa9Smycroft*	d4: LEN/Unchanged
49522ef5fa9Smycroft*	d5: ICTR:LAMBDA
49622ef5fa9Smycroft*	d6: ILOG/Unchanged
49722ef5fa9Smycroft*	d7: k-factor/Unchanged
49822ef5fa9Smycroft*	a0: ptr for original operand/final result
49922ef5fa9Smycroft*	a1: ptr to PTENRM array/Unchanged
50022ef5fa9Smycroft*	a2: x/x
50122ef5fa9Smycroft*	fp0: float(ILOG)/X adjusted for SCALE (Y)
50222ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
50322ef5fa9Smycroft*	fp2: x/x
50422ef5fa9Smycroft*	F_SCR1:x/x
50522ef5fa9Smycroft*	F_SCR2:Abs(X) with $3fff exponent/Unchanged
50622ef5fa9Smycroft*	L_SCR1:x/x
50722ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
50822ef5fa9Smycroft
50922ef5fa9SmycroftA9_str:
51022ef5fa9Smycroft	fmove.x	(a0),fp0	;load X from memory
51122ef5fa9Smycroft	fabs.x	fp0		;use abs(X)
51222ef5fa9Smycroft	tst.w	d5		;LAMBDA is in lower word of d5
513*c869df6aSbriggs	bne.b	short_sc_mul	;if neg (LAMBDA = 1), scale by mul
51422ef5fa9Smycroft	fdiv.x	fp1,fp0		;calculate X / SCALE -> Y to fp0
51522ef5fa9Smycroft	bra.b	A10_st		;branch to A10
51622ef5fa9Smycroft
51722ef5fa9Smycroftsc_mul:
518*c869df6aSbriggsshort_sc_mul:
51922ef5fa9Smycroft	tst.b	BINDEC_FLG(a6)	;check for denorm
52022ef5fa9Smycroft	beq.b	A9_norm		;if norm, continue with mul
52122ef5fa9Smycroft	fmovem.x fp1,-(a7)	;load ETEMP with 10^ISCALE
52222ef5fa9Smycroft	move.l	8(a0),-(a7)	;load FPTEMP with input arg
52322ef5fa9Smycroft	move.l	4(a0),-(a7)
52422ef5fa9Smycroft	move.l	(a0),-(a7)
52522ef5fa9Smycroft	move.l	#18,d3		;load count for busy stack
52622ef5fa9SmycroftA9_loop:
52722ef5fa9Smycroft	clr.l	-(a7)		;clear lword on stack
52822ef5fa9Smycroft	dbf.w	d3,A9_loop
52922ef5fa9Smycroft	move.b	VER_TMP(a6),(a7) ;write current version number
53022ef5fa9Smycroft	move.b	#BUSY_SIZE-4,1(a7) ;write current busy size
53122ef5fa9Smycroft	move.b	#$10,$44(a7)	;set fcefpte[15] bit
53222ef5fa9Smycroft	move.w	#$0023,$40(a7)	;load cmdreg1b with mul command
53322ef5fa9Smycroft	move.b	#$fe,$8(a7)	;load all 1s to cu savepc
53422ef5fa9Smycroft	frestore (a7)+		;restore frame to fpu for completion
53522ef5fa9Smycroft	fmul.x	36(a1),fp0	;multiply fp0 by 10^8
53622ef5fa9Smycroft	fmul.x	48(a1),fp0	;multiply fp0 by 10^16
53722ef5fa9Smycroft	bra.b	A10_st
53822ef5fa9SmycroftA9_norm:
53922ef5fa9Smycroft	tst.w	d2		;test for small exp case
54022ef5fa9Smycroft	beq.b	A9_con		;if zero, continue as normal
54122ef5fa9Smycroft	fmul.x	36(a1),fp0	;multiply fp0 by 10^8
54222ef5fa9Smycroft	fmul.x	48(a1),fp0	;multiply fp0 by 10^16
54322ef5fa9SmycroftA9_con:
54422ef5fa9Smycroft	fmul.x	fp1,fp0		;calculate X * SCALE -> Y to fp0
54522ef5fa9Smycroft
54622ef5fa9Smycroft
54722ef5fa9Smycroft* A10. Or in INEX.
548456dff6cSwiz*      If INEX is set, round error occurred.  This is compensated
54922ef5fa9Smycroft*      for by 'or-ing' in the INEX2 flag to the lsb of Y.
55022ef5fa9Smycroft*
55122ef5fa9Smycroft* Register usage:
55222ef5fa9Smycroft*	Input/Output
55322ef5fa9Smycroft*	d0: FPCR with RZ mode/FPSR with INEX2 isolated
55422ef5fa9Smycroft*	d2: x/x
55522ef5fa9Smycroft*	d3: x/x
55622ef5fa9Smycroft*	d4: LEN/Unchanged
55722ef5fa9Smycroft*	d5: ICTR:LAMBDA
55822ef5fa9Smycroft*	d6: ILOG/Unchanged
55922ef5fa9Smycroft*	d7: k-factor/Unchanged
56022ef5fa9Smycroft*	a0: ptr for original operand/final result
56122ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
56222ef5fa9Smycroft*	a2: x/ptr to FP_SCR2(a6)
56322ef5fa9Smycroft*	fp0: Y/Y with lsb adjusted
56422ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
56522ef5fa9Smycroft*	fp2: x/x
56622ef5fa9Smycroft
56722ef5fa9SmycroftA10_st:
56822ef5fa9Smycroft	fmove.l	FPSR,d0		;get FPSR
56922ef5fa9Smycroft	fmove.x	fp0,FP_SCR2(a6)	;move Y to memory
57022ef5fa9Smycroft	lea.l	FP_SCR2(a6),a2	;load a2 with ptr to FP_SCR2
57122ef5fa9Smycroft	btst.l	#9,d0		;check if INEX2 set
57222ef5fa9Smycroft	beq.b	A11_st		;if clear, skip rest
57322ef5fa9Smycroft	ori.l	#1,8(a2)	;or in 1 to lsb of mantissa
57422ef5fa9Smycroft	fmove.x	FP_SCR2(a6),fp0	;write adjusted Y back to fpu
57522ef5fa9Smycroft
57622ef5fa9Smycroft
57722ef5fa9Smycroft* A11. Restore original FPCR; set size ext.
57822ef5fa9Smycroft*      Perform FINT operation in the user's rounding mode.  Keep
57922ef5fa9Smycroft*      the size to extended.  The sintdo entry point in the sint
58022ef5fa9Smycroft*      routine expects the FPCR value to be in USER_FPCR for
58122ef5fa9Smycroft*      mode and precision.  The original FPCR is saved in L_SCR1.
58222ef5fa9Smycroft
58322ef5fa9SmycroftA11_st:
58422ef5fa9Smycroft	move.l	USER_FPCR(a6),L_SCR1(a6) ;save it for later
58522ef5fa9Smycroft	andi.l	#$00000030,USER_FPCR(a6) ;set size to ext,
58622ef5fa9Smycroft*					;block exceptions
58722ef5fa9Smycroft
58822ef5fa9Smycroft
58922ef5fa9Smycroft* A12. Calculate YINT = FINT(Y) according to user's rounding mode.
59022ef5fa9Smycroft*      The FPSP routine sintd0 is used.  The output is in fp0.
59122ef5fa9Smycroft*
59222ef5fa9Smycroft* Register usage:
59322ef5fa9Smycroft*	Input/Output
59422ef5fa9Smycroft*	d0: FPSR with AINEX cleared/FPCR with size set to ext
59522ef5fa9Smycroft*	d2: x/x/scratch
59622ef5fa9Smycroft*	d3: x/x
59722ef5fa9Smycroft*	d4: LEN/Unchanged
59822ef5fa9Smycroft*	d5: ICTR:LAMBDA/Unchanged
59922ef5fa9Smycroft*	d6: ILOG/Unchanged
60022ef5fa9Smycroft*	d7: k-factor/Unchanged
60122ef5fa9Smycroft*	a0: ptr for original operand/src ptr for sintdo
60222ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
60322ef5fa9Smycroft*	a2: ptr to FP_SCR2(a6)/Unchanged
60422ef5fa9Smycroft*	a6: temp pointer to FP_SCR2(a6) - orig value saved and restored
60522ef5fa9Smycroft*	fp0: Y/YINT
60622ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
60722ef5fa9Smycroft*	fp2: x/x
60822ef5fa9Smycroft*	F_SCR1:x/x
60922ef5fa9Smycroft*	F_SCR2:Y adjusted for inex/Y with original exponent
61022ef5fa9Smycroft*	L_SCR1:x/original USER_FPCR
61122ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
61222ef5fa9Smycroft
61322ef5fa9SmycroftA12_st:
61422ef5fa9Smycroft	movem.l	d0-d1/a0-a1,-(a7)	;save regs used by sintd0
61522ef5fa9Smycroft	move.l	L_SCR1(a6),-(a7)
61622ef5fa9Smycroft	move.l	L_SCR2(a6),-(a7)
61722ef5fa9Smycroft	lea.l	FP_SCR2(a6),a0		;a0 is ptr to F_SCR2(a6)
61822ef5fa9Smycroft	fmove.x	fp0,(a0)		;move Y to memory at FP_SCR2(a6)
61922ef5fa9Smycroft	tst.l	L_SCR2(a6)		;test sign of original operand
62022ef5fa9Smycroft	bge.b	do_fint			;if pos, use Y
62122ef5fa9Smycroft	or.l	#$80000000,(a0)		;if neg, use -Y
62222ef5fa9Smycroftdo_fint:
62322ef5fa9Smycroft	move.l	USER_FPSR(a6),-(a7)
62422ef5fa9Smycroft	bsr	sintdo			;sint routine returns int in fp0
62522ef5fa9Smycroft	move.b	(a7),USER_FPSR(a6)
62622ef5fa9Smycroft	add.l	#4,a7
62722ef5fa9Smycroft	move.l	(a7)+,L_SCR2(a6)
62822ef5fa9Smycroft	move.l	(a7)+,L_SCR1(a6)
62922ef5fa9Smycroft	movem.l	(a7)+,d0-d1/a0-a1	;restore regs used by sint
63022ef5fa9Smycroft	move.l	L_SCR2(a6),FP_SCR2(a6)	;restore original exponent
63122ef5fa9Smycroft	move.l	L_SCR1(a6),USER_FPCR(a6) ;restore user's FPCR
63222ef5fa9Smycroft
63322ef5fa9Smycroft
63422ef5fa9Smycroft* A13. Check for LEN digits.
63522ef5fa9Smycroft*      If the int operation results in more than LEN digits,
63622ef5fa9Smycroft*      or less than LEN -1 digits, adjust ILOG and repeat from
63722ef5fa9Smycroft*      A6.  This test occurs only on the first pass.  If the
63822ef5fa9Smycroft*      result is exactly 10^LEN, decrement ILOG and divide
63922ef5fa9Smycroft*      the mantissa by 10.  The calculation of 10^LEN cannot
64022ef5fa9Smycroft*      be inexact, since all powers of ten upto 10^27 are exact
64122ef5fa9Smycroft*      in extended precision, so the use of a previous power-of-ten
64222ef5fa9Smycroft*      table will introduce no error.
64322ef5fa9Smycroft*
64422ef5fa9Smycroft*
64522ef5fa9Smycroft* Register usage:
64622ef5fa9Smycroft*	Input/Output
64722ef5fa9Smycroft*	d0: FPCR with size set to ext/scratch final = 0
64822ef5fa9Smycroft*	d2: x/x
64922ef5fa9Smycroft*	d3: x/scratch final = x
65022ef5fa9Smycroft*	d4: LEN/LEN adjusted
65122ef5fa9Smycroft*	d5: ICTR:LAMBDA/LAMBDA:ICTR
65222ef5fa9Smycroft*	d6: ILOG/ILOG adjusted
65322ef5fa9Smycroft*	d7: k-factor/Unchanged
65422ef5fa9Smycroft*	a0: pointer into memory for packed bcd string formation
65522ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
65622ef5fa9Smycroft*	a2: ptr to FP_SCR2(a6)/Unchanged
65722ef5fa9Smycroft*	fp0: int portion of Y/abs(YINT) adjusted
65822ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
65922ef5fa9Smycroft*	fp2: x/10^LEN
66022ef5fa9Smycroft*	F_SCR1:x/x
66122ef5fa9Smycroft*	F_SCR2:Y with original exponent/Unchanged
66222ef5fa9Smycroft*	L_SCR1:original USER_FPCR/Unchanged
66322ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
66422ef5fa9Smycroft
66522ef5fa9SmycroftA13_st:
66622ef5fa9Smycroft	swap	d5		;put ICTR in lower word of d5
66722ef5fa9Smycroft	tst.w	d5		;check if ICTR = 0
66822ef5fa9Smycroft	bne	not_zr		;if non-zero, go to second test
66922ef5fa9Smycroft*
67022ef5fa9Smycroft* Compute 10^(LEN-1)
67122ef5fa9Smycroft*
67222ef5fa9Smycroft	fmove.s	FONE,fp2	;init fp2 to 1.0
67322ef5fa9Smycroft	move.l	d4,d0		;put LEN in d0
67422ef5fa9Smycroft	subq.l	#1,d0		;d0 = LEN -1
67522ef5fa9Smycroft	clr.l	d3		;clr table index
67622ef5fa9Smycroftl_loop:
67722ef5fa9Smycroft	lsr.l	#1,d0		;shift next bit into carry
67822ef5fa9Smycroft	bcc.b	l_next		;if zero, skip the mul
67922ef5fa9Smycroft	fmul.x	(a1,d3),fp2	;mul by 10**(d3_bit_no)
68022ef5fa9Smycroftl_next:
68122ef5fa9Smycroft	add.l	#12,d3		;inc d3 to next pwrten table entry
68222ef5fa9Smycroft	tst.l	d0		;test if LEN is zero
68322ef5fa9Smycroft	bne.b	l_loop		;if not, loop
68422ef5fa9Smycroft*
68522ef5fa9Smycroft* 10^LEN-1 is computed for this test and A14.  If the input was
68622ef5fa9Smycroft* denormalized, check only the case in which YINT > 10^LEN.
68722ef5fa9Smycroft*
68822ef5fa9Smycroft	tst.b	BINDEC_FLG(a6)	;check if input was norm
68922ef5fa9Smycroft	beq.b	A13_con		;if norm, continue with checking
69022ef5fa9Smycroft	fabs.x	fp0		;take abs of YINT
69122ef5fa9Smycroft	bra	test_2
69222ef5fa9Smycroft*
69322ef5fa9Smycroft* Compare abs(YINT) to 10^(LEN-1) and 10^LEN
69422ef5fa9Smycroft*
69522ef5fa9SmycroftA13_con:
69622ef5fa9Smycroft	fabs.x	fp0		;take abs of YINT
69722ef5fa9Smycroft	fcmp.x	fp2,fp0		;compare abs(YINT) with 10^(LEN-1)
69822ef5fa9Smycroft	fbge.w	test_2		;if greater, do next test
69922ef5fa9Smycroft	subq.l	#1,d6		;subtract 1 from ILOG
70022ef5fa9Smycroft	move.w	#1,d5		;set ICTR
70122ef5fa9Smycroft	fmove.l	#rm_mode,FPCR	;set rmode to RM
70222ef5fa9Smycroft	fmul.s	FTEN,fp2	;compute 10^LEN
70322ef5fa9Smycroft	bra.w	A6_str		;return to A6 and recompute YINT
70422ef5fa9Smycrofttest_2:
70522ef5fa9Smycroft	fmul.s	FTEN,fp2	;compute 10^LEN
70622ef5fa9Smycroft	fcmp.x	fp2,fp0		;compare abs(YINT) with 10^LEN
70722ef5fa9Smycroft	fblt.w	A14_st		;if less, all is ok, go to A14
70822ef5fa9Smycroft	fbgt.w	fix_ex		;if greater, fix and redo
70922ef5fa9Smycroft	fdiv.s	FTEN,fp0	;if equal, divide by 10
71022ef5fa9Smycroft	addq.l	#1,d6		; and inc ILOG
71122ef5fa9Smycroft	bra.b	A14_st		; and continue elsewhere
71222ef5fa9Smycroftfix_ex:
71322ef5fa9Smycroft	addq.l	#1,d6		;increment ILOG by 1
71422ef5fa9Smycroft	move.w	#1,d5		;set ICTR
71522ef5fa9Smycroft	fmove.l	#rm_mode,FPCR	;set rmode to RM
71622ef5fa9Smycroft	bra.w	A6_str		;return to A6 and recompute YINT
71722ef5fa9Smycroft*
71822ef5fa9Smycroft* Since ICTR <> 0, we have already been through one adjustment,
71922ef5fa9Smycroft* and shouldn't have another; this is to check if abs(YINT) = 10^LEN
72022ef5fa9Smycroft* 10^LEN is again computed using whatever table is in a1 since the
72122ef5fa9Smycroft* value calculated cannot be inexact.
72222ef5fa9Smycroft*
72322ef5fa9Smycroftnot_zr:
72422ef5fa9Smycroft	fmove.s	FONE,fp2	;init fp2 to 1.0
72522ef5fa9Smycroft	move.l	d4,d0		;put LEN in d0
72622ef5fa9Smycroft	clr.l	d3		;clr table index
72722ef5fa9Smycroftz_loop:
72822ef5fa9Smycroft	lsr.l	#1,d0		;shift next bit into carry
72922ef5fa9Smycroft	bcc.b	z_next		;if zero, skip the mul
73022ef5fa9Smycroft	fmul.x	(a1,d3),fp2	;mul by 10**(d3_bit_no)
73122ef5fa9Smycroftz_next:
73222ef5fa9Smycroft	add.l	#12,d3		;inc d3 to next pwrten table entry
73322ef5fa9Smycroft	tst.l	d0		;test if LEN is zero
73422ef5fa9Smycroft	bne.b	z_loop		;if not, loop
73522ef5fa9Smycroft	fabs.x	fp0		;get abs(YINT)
73622ef5fa9Smycroft	fcmp.x	fp2,fp0		;check if abs(YINT) = 10^LEN
73722ef5fa9Smycroft	fbne.w	A14_st		;if not, skip this
73822ef5fa9Smycroft	fdiv.s	FTEN,fp0	;divide abs(YINT) by 10
73922ef5fa9Smycroft	addq.l	#1,d6		;and inc ILOG by 1
74022ef5fa9Smycroft	addq.l	#1,d4		; and inc LEN
74122ef5fa9Smycroft	fmul.s	FTEN,fp2	; if LEN++, the get 10^^LEN
74222ef5fa9Smycroft
74322ef5fa9Smycroft
74422ef5fa9Smycroft* A14. Convert the mantissa to bcd.
74522ef5fa9Smycroft*      The binstr routine is used to convert the LEN digit
74622ef5fa9Smycroft*      mantissa to bcd in memory.  The input to binstr is
74722ef5fa9Smycroft*      to be a fraction; i.e. (mantissa)/10^LEN and adjusted
74822ef5fa9Smycroft*      such that the decimal point is to the left of bit 63.
74922ef5fa9Smycroft*      The bcd digits are stored in the correct position in
75022ef5fa9Smycroft*      the final string area in memory.
75122ef5fa9Smycroft*
75222ef5fa9Smycroft*
75322ef5fa9Smycroft* Register usage:
75422ef5fa9Smycroft*	Input/Output
75522ef5fa9Smycroft*	d0: x/LEN call to binstr - final is 0
75622ef5fa9Smycroft*	d1: x/0
75722ef5fa9Smycroft*	d2: x/ms 32-bits of mant of abs(YINT)
75822ef5fa9Smycroft*	d3: x/ls 32-bits of mant of abs(YINT)
75922ef5fa9Smycroft*	d4: LEN/Unchanged
76022ef5fa9Smycroft*	d5: ICTR:LAMBDA/LAMBDA:ICTR
76122ef5fa9Smycroft*	d6: ILOG
76222ef5fa9Smycroft*	d7: k-factor/Unchanged
76322ef5fa9Smycroft*	a0: pointer into memory for packed bcd string formation
76422ef5fa9Smycroft*	    /ptr to first mantissa byte in result string
76522ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
76622ef5fa9Smycroft*	a2: ptr to FP_SCR2(a6)/Unchanged
76722ef5fa9Smycroft*	fp0: int portion of Y/abs(YINT) adjusted
76822ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
76922ef5fa9Smycroft*	fp2: 10^LEN/Unchanged
77022ef5fa9Smycroft*	F_SCR1:x/Work area for final result
77122ef5fa9Smycroft*	F_SCR2:Y with original exponent/Unchanged
77222ef5fa9Smycroft*	L_SCR1:original USER_FPCR/Unchanged
77322ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
77422ef5fa9Smycroft
77522ef5fa9SmycroftA14_st:
77622ef5fa9Smycroft	fmove.l	#rz_mode,FPCR	;force rz for conversion
77722ef5fa9Smycroft	fdiv.x	fp2,fp0		;divide abs(YINT) by 10^LEN
77822ef5fa9Smycroft	lea.l	FP_SCR1(a6),a0
77922ef5fa9Smycroft	fmove.x	fp0,(a0)	;move abs(YINT)/10^LEN to memory
78022ef5fa9Smycroft	move.l	4(a0),d2	;move 2nd word of FP_RES to d2
78122ef5fa9Smycroft	move.l	8(a0),d3	;move 3rd word of FP_RES to d3
78222ef5fa9Smycroft	clr.l	4(a0)		;zero word 2 of FP_RES
78322ef5fa9Smycroft	clr.l	8(a0)		;zero word 3 of FP_RES
78422ef5fa9Smycroft	move.l	(a0),d0		;move exponent to d0
78522ef5fa9Smycroft	swap	d0		;put exponent in lower word
78622ef5fa9Smycroft	beq.b	no_sft		;if zero, don't shift
78722ef5fa9Smycroft	subi.l	#$3ffd,d0	;sub bias less 2 to make fract
78822ef5fa9Smycroft	tst.l	d0		;check if > 1
78922ef5fa9Smycroft	bgt.b	no_sft		;if so, don't shift
79022ef5fa9Smycroft	neg.l	d0		;make exp positive
79122ef5fa9Smycroftm_loop:
79222ef5fa9Smycroft	lsr.l	#1,d2		;shift d2:d3 right, add 0s
79322ef5fa9Smycroft	roxr.l	#1,d3		;the number of places
79422ef5fa9Smycroft	dbf.w	d0,m_loop	;given in d0
79522ef5fa9Smycroftno_sft:
79622ef5fa9Smycroft	tst.l	d2		;check for mantissa of zero
79722ef5fa9Smycroft	bne.b	no_zr		;if not, go on
79822ef5fa9Smycroft	tst.l	d3		;continue zero check
79922ef5fa9Smycroft	beq.b	zer_m		;if zero, go directly to binstr
80022ef5fa9Smycroftno_zr:
80122ef5fa9Smycroft	clr.l	d1		;put zero in d1 for addx
80222ef5fa9Smycroft	addi.l	#$00000080,d3	;inc at bit 7
80322ef5fa9Smycroft	addx.l	d1,d2		;continue inc
80422ef5fa9Smycroft	andi.l	#$ffffff80,d3	;strip off lsb not used by 882
80522ef5fa9Smycroftzer_m:
80622ef5fa9Smycroft	move.l	d4,d0		;put LEN in d0 for binstr call
80722ef5fa9Smycroft	addq.l	#3,a0		;a0 points to M16 byte in result
80822ef5fa9Smycroft	bsr	binstr		;call binstr to convert mant
80922ef5fa9Smycroft
81022ef5fa9Smycroft
81122ef5fa9Smycroft* A15. Convert the exponent to bcd.
81222ef5fa9Smycroft*      As in A14 above, the exp is converted to bcd and the
81322ef5fa9Smycroft*      digits are stored in the final string.
81422ef5fa9Smycroft*
81522ef5fa9Smycroft*      Digits are stored in L_SCR1(a6) on return from BINDEC as:
81622ef5fa9Smycroft*
81722ef5fa9Smycroft*  	 32               16 15                0
81822ef5fa9Smycroft*	-----------------------------------------
81922ef5fa9Smycroft*  	|  0 | e3 | e2 | e1 | e4 |  X |  X |  X |
82022ef5fa9Smycroft*	-----------------------------------------
82122ef5fa9Smycroft*
82222ef5fa9Smycroft* And are moved into their proper places in FP_SCR1.  If digit e4
82322ef5fa9Smycroft* is non-zero, OPERR is signaled.  In all cases, all 4 digits are
82422ef5fa9Smycroft* written as specified in the 881/882 manual for packed decimal.
82522ef5fa9Smycroft*
82622ef5fa9Smycroft* Register usage:
82722ef5fa9Smycroft*	Input/Output
82822ef5fa9Smycroft*	d0: x/LEN call to binstr - final is 0
82922ef5fa9Smycroft*	d1: x/scratch (0);shift count for final exponent packing
83022ef5fa9Smycroft*	d2: x/ms 32-bits of exp fraction/scratch
83122ef5fa9Smycroft*	d3: x/ls 32-bits of exp fraction
83222ef5fa9Smycroft*	d4: LEN/Unchanged
83322ef5fa9Smycroft*	d5: ICTR:LAMBDA/LAMBDA:ICTR
83422ef5fa9Smycroft*	d6: ILOG
83522ef5fa9Smycroft*	d7: k-factor/Unchanged
83622ef5fa9Smycroft*	a0: ptr to result string/ptr to L_SCR1(a6)
83722ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
83822ef5fa9Smycroft*	a2: ptr to FP_SCR2(a6)/Unchanged
83922ef5fa9Smycroft*	fp0: abs(YINT) adjusted/float(ILOG)
84022ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
84122ef5fa9Smycroft*	fp2: 10^LEN/Unchanged
84222ef5fa9Smycroft*	F_SCR1:Work area for final result/BCD result
84322ef5fa9Smycroft*	F_SCR2:Y with original exponent/ILOG/10^4
84422ef5fa9Smycroft*	L_SCR1:original USER_FPCR/Exponent digits on return from binstr
84522ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
84622ef5fa9Smycroft
84722ef5fa9SmycroftA15_st:
84822ef5fa9Smycroft	tst.b	BINDEC_FLG(a6)	;check for denorm
84922ef5fa9Smycroft	beq.b	not_denorm
85022ef5fa9Smycroft	ftst.x	fp0		;test for zero
85122ef5fa9Smycroft	fbeq.w	den_zero	;if zero, use k-factor or 4933
85222ef5fa9Smycroft	fmove.l	d6,fp0		;float ILOG
85322ef5fa9Smycroft	fabs.x	fp0		;get abs of ILOG
85422ef5fa9Smycroft	bra.b	convrt
85522ef5fa9Smycroftden_zero:
85622ef5fa9Smycroft	tst.l	d7		;check sign of the k-factor
85722ef5fa9Smycroft	blt.b	use_ilog	;if negative, use ILOG
85822ef5fa9Smycroft	fmove.s	F4933,fp0	;force exponent to 4933
85922ef5fa9Smycroft	bra.b	convrt		;do it
86022ef5fa9Smycroftuse_ilog:
86122ef5fa9Smycroft	fmove.l	d6,fp0		;float ILOG
86222ef5fa9Smycroft	fabs.x	fp0		;get abs of ILOG
86322ef5fa9Smycroft	bra.b	convrt
86422ef5fa9Smycroftnot_denorm:
86522ef5fa9Smycroft	ftst.x	fp0		;test for zero
86622ef5fa9Smycroft	fbne.w	not_zero	;if zero, force exponent
86722ef5fa9Smycroft	fmove.s	FONE,fp0	;force exponent to 1
86822ef5fa9Smycroft	bra.b	convrt		;do it
86922ef5fa9Smycroftnot_zero:
87022ef5fa9Smycroft	fmove.l	d6,fp0		;float ILOG
87122ef5fa9Smycroft	fabs.x	fp0		;get abs of ILOG
87222ef5fa9Smycroftconvrt:
87322ef5fa9Smycroft	fdiv.x	24(a1),fp0	;compute ILOG/10^4
87422ef5fa9Smycroft	fmove.x	fp0,FP_SCR2(a6)	;store fp0 in memory
87522ef5fa9Smycroft	move.l	4(a2),d2	;move word 2 to d2
87622ef5fa9Smycroft	move.l	8(a2),d3	;move word 3 to d3
87722ef5fa9Smycroft	move.w	(a2),d0		;move exp to d0
87822ef5fa9Smycroft	beq.b	x_loop_fin	;if zero, skip the shift
87922ef5fa9Smycroft	subi.w	#$3ffd,d0	;subtract off bias
88022ef5fa9Smycroft	neg.w	d0		;make exp positive
88122ef5fa9Smycroftx_loop:
88222ef5fa9Smycroft	lsr.l	#1,d2		;shift d2:d3 right
88322ef5fa9Smycroft	roxr.l	#1,d3		;the number of places
88422ef5fa9Smycroft	dbf.w	d0,x_loop	;given in d0
88522ef5fa9Smycroftx_loop_fin:
88622ef5fa9Smycroft	clr.l	d1		;put zero in d1 for addx
88722ef5fa9Smycroft	addi.l	#$00000080,d3	;inc at bit 6
88822ef5fa9Smycroft	addx.l	d1,d2		;continue inc
88922ef5fa9Smycroft	andi.l	#$ffffff80,d3	;strip off lsb not used by 882
89022ef5fa9Smycroft	move.l	#4,d0		;put 4 in d0 for binstr call
89122ef5fa9Smycroft	lea.l	L_SCR1(a6),a0	;a0 is ptr to L_SCR1 for exp digits
89222ef5fa9Smycroft	bsr	binstr		;call binstr to convert exp
89322ef5fa9Smycroft	move.l	L_SCR1(a6),d0	;load L_SCR1 lword to d0
89422ef5fa9Smycroft	move.l	#12,d1		;use d1 for shift count
89522ef5fa9Smycroft	lsr.l	d1,d0		;shift d0 right by 12
89622ef5fa9Smycroft	bfins	d0,FP_SCR1(a6){4:12} ;put e3:e2:e1 in FP_SCR1
89722ef5fa9Smycroft	lsr.l	d1,d0		;shift d0 right by 12
89822ef5fa9Smycroft	bfins	d0,FP_SCR1(a6){16:4} ;put e4 in FP_SCR1
89922ef5fa9Smycroft	tst.b	d0		;check if e4 is zero
90022ef5fa9Smycroft	beq.b	A16_st		;if zero, skip rest
90122ef5fa9Smycroft	or.l	#opaop_mask,USER_FPSR(a6) ;set OPERR & AIOP in USER_FPSR
90222ef5fa9Smycroft
90322ef5fa9Smycroft
90422ef5fa9Smycroft* A16. Write sign bits to final string.
90522ef5fa9Smycroft*	   Sigma is bit 31 of initial value; RHO is bit 31 of d6 (ILOG).
90622ef5fa9Smycroft*
90722ef5fa9Smycroft* Register usage:
90822ef5fa9Smycroft*	Input/Output
90922ef5fa9Smycroft*	d0: x/scratch - final is x
91022ef5fa9Smycroft*	d2: x/x
91122ef5fa9Smycroft*	d3: x/x
91222ef5fa9Smycroft*	d4: LEN/Unchanged
91322ef5fa9Smycroft*	d5: ICTR:LAMBDA/LAMBDA:ICTR
91422ef5fa9Smycroft*	d6: ILOG/ILOG adjusted
91522ef5fa9Smycroft*	d7: k-factor/Unchanged
91622ef5fa9Smycroft*	a0: ptr to L_SCR1(a6)/Unchanged
91722ef5fa9Smycroft*	a1: ptr to PTENxx array/Unchanged
91822ef5fa9Smycroft*	a2: ptr to FP_SCR2(a6)/Unchanged
91922ef5fa9Smycroft*	fp0: float(ILOG)/Unchanged
92022ef5fa9Smycroft*	fp1: 10^ISCALE/Unchanged
92122ef5fa9Smycroft*	fp2: 10^LEN/Unchanged
92222ef5fa9Smycroft*	F_SCR1:BCD result with correct signs
92322ef5fa9Smycroft*	F_SCR2:ILOG/10^4
92422ef5fa9Smycroft*	L_SCR1:Exponent digits on return from binstr
92522ef5fa9Smycroft*	L_SCR2:first word of X packed/Unchanged
92622ef5fa9Smycroft
92722ef5fa9SmycroftA16_st:
92822ef5fa9Smycroft	clr.l	d0		;clr d0 for collection of signs
92922ef5fa9Smycroft	andi.b	#$0f,FP_SCR1(a6) ;clear first nibble of FP_SCR1
93022ef5fa9Smycroft	tst.l	L_SCR2(a6)	;check sign of original mantissa
93122ef5fa9Smycroft	bge.b	mant_p		;if pos, don't set SM
93222ef5fa9Smycroft	moveq.l	#2,d0		;move 2 in to d0 for SM
93322ef5fa9Smycroftmant_p:
93422ef5fa9Smycroft	tst.l	d6		;check sign of ILOG
93522ef5fa9Smycroft	bge.b	wr_sgn		;if pos, don't set SE
93622ef5fa9Smycroft	addq.l	#1,d0		;set bit 0 in d0 for SE
93722ef5fa9Smycroftwr_sgn:
93822ef5fa9Smycroft	bfins	d0,FP_SCR1(a6){0:2} ;insert SM and SE into FP_SCR1
93922ef5fa9Smycroft
94022ef5fa9Smycroft* Clean up and restore all registers used.
94122ef5fa9Smycroft
94222ef5fa9Smycroft	fmove.l	#0,FPSR		;clear possible inex2/ainex bits
94322ef5fa9Smycroft	fmovem.x (a7)+,fp0-fp2
94422ef5fa9Smycroft	movem.l	(a7)+,d2-d7/a2
94522ef5fa9Smycroft	rts
94622ef5fa9Smycroft
94722ef5fa9Smycroft	end
948