*	$OpenBSD: binstr.sa,v 1.2 1996/05/29 21:05:25 niklas Exp $
*	$NetBSD: binstr.sa,v 1.3 1994/10/26 07:48:53 cgd Exp $

*	MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
*	M68000 Hi-Performance Microprocessor Division
*	M68040 Software Package 
*
*	M68040 Software Package Copyright (c) 1993, 1994 Motorola Inc.
*	All rights reserved.
*
*	THE SOFTWARE is provided on an "AS IS" basis and without warranty.
*	To the maximum extent permitted by applicable law,
*	MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
*	INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A
*	PARTICULAR PURPOSE and any warranty against infringement with
*	regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
*	and any accompanying written materials. 
*
*	To the maximum extent permitted by applicable law,
*	IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
*	(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS
*	PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR
*	OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE
*	SOFTWARE.  Motorola assumes no responsibility for the maintenance
*	and support of the SOFTWARE.  
*
*	You are hereby granted a copyright license to use, modify, and
*	distribute the SOFTWARE so long as this entire notice is retained
*	without alteration in any modified and/or redistributed versions,
*	and that such modified versions are clearly identified as such.
*	No licenses are granted by implication, estoppel or otherwise
*	under any patents or trademarks of Motorola, Inc.

*
*	binstr.sa 3.3 12/19/90
*
*
*	Description: Converts a 64-bit binary integer to bcd.
*
*	Input: 64-bit binary integer in d2:d3, desired length (LEN) in
*          d0, and a  pointer to start in memory for bcd characters
*          in d0. (This pointer must point to byte 4 of the first
*          lword of the packed decimal memory string.)
*
*	Output:	LEN bcd digits representing the 64-bit integer.
*
*	Algorithm:
*		The 64-bit binary is assumed to have a decimal point before
*		bit 63.  The fraction is multiplied by 10 using a mul by 2
*		shift and a mul by 8 shift.  The bits shifted out of the
*		msb form a decimal digit.  This process is iterated until
*		LEN digits are formed.
*
*	A1. Init d7 to 1.  D7 is the byte digit counter, and if 1, the
*		digit formed will be assumed the least significant.  This is
*		to force the first byte formed to have a 0 in the upper 4 bits.
*
*	A2. Beginning of the loop:
*		Copy the fraction in d2:d3 to d4:d5.
*
*	A3. Multiply the fraction in d2:d3 by 8 using bit-field
*		extracts and shifts.  The three msbs from d2 will go into
*		d1.
*
*	A4. Multiply the fraction in d4:d5 by 2 using shifts.  The msb
*		will be collected by the carry.
*
*	A5. Add using the carry the 64-bit quantities in d2:d3 and d4:d5
*		into d2:d3.  D1 will contain the bcd digit formed.
*
*	A6. Test d7.  If zero, the digit formed is the ms digit.  If non-
*		zero, it is the ls digit.  Put the digit in its place in the
*		upper word of d0.  If it is the ls digit, write the word
*		from d0 to memory.
*
*	A7. Decrement d6 (LEN counter) and repeat the loop until zero.
*
*	Implementation Notes:
*
*	The registers are used as follows:
*
*		d0: LEN counter
*		d1: temp used to form the digit
*		d2: upper 32-bits of fraction for mul by 8
*		d3: lower 32-bits of fraction for mul by 8
*		d4: upper 32-bits of fraction for mul by 2
*		d5: lower 32-bits of fraction for mul by 2
*		d6: temp for bit-field extracts
*		d7: byte digit formation word;digit count {0,1}
*		a0: pointer into memory for packed bcd string formation
*

BINSTR    IDNT    2,1 Motorola 040 Floating Point Software Package

	section	8

	include	fpsp.h

	xdef	binstr
binstr:
	movem.l	d0-d7,-(a7)
*
* A1: Init d7
*
	moveq.l	#1,d7			;init d7 for second digit
	subq.l	#1,d0			;for dbf d0 would have LEN+1 passes
*
* A2. Copy d2:d3 to d4:d5.  Start loop.
*
loop:
	move.l	d2,d4			;copy the fraction before muls
	move.l	d3,d5			;to d4:d5
*
* A3. Multiply d2:d3 by 8; extract msbs into d1.
*
	bfextu	d2{0:3},d1		;copy 3 msbs of d2 into d1
	asl.l	#3,d2			;shift d2 left by 3 places
	bfextu	d3{0:3},d6		;copy 3 msbs of d3 into d6
	asl.l	#3,d3			;shift d3 left by 3 places
	or.l	d6,d2			;or in msbs from d3 into d2
*
* A4. Multiply d4:d5 by 2; add carry out to d1.
*
	add.l	d5,d5			;mul d5 by 2
	addx.l	d4,d4			;mul d4 by 2
	swap	d6			;put 0 in d6 lower word
	addx.w	d6,d1			;add in extend from mul by 2
*
* A5. Add mul by 8 to mul by 2.  D1 contains the digit formed.
*
	add.l	d5,d3			;add lower 32 bits
	nop				;ERRATA FIX #13 (Rev. 1.2 6/6/90)
	addx.l	d4,d2			;add with extend upper 32 bits
	nop				;ERRATA FIX #13 (Rev. 1.2 6/6/90)
	addx.w	d6,d1			;add in extend from add to d1
	swap	d6			;with d6 = 0; put 0 in upper word
*
* A6. Test d7 and branch.
*
	tst.w	d7			;if zero, store digit & to loop
	beq.b	first_d			;if non-zero, form byte & write
sec_d:
	swap	d7			;bring first digit to word d7b
	asl.w	#4,d7			;first digit in upper 4 bits d7b
	add.w	d1,d7			;add in ls digit to d7b
	move.b	d7,(a0)+		;store d7b byte in memory
	swap	d7			;put LEN counter in word d7a
	clr.w	d7			;set d7a to signal no digits done
	dbf.w	d0,loop			;do loop some more!
	bra.b	end_bstr		;finished, so exit
first_d:
	swap	d7			;put digit word in d7b
	move.w	d1,d7			;put new digit in d7b
	swap	d7			;put LEN counter in word d7a
	addq.w	#1,d7			;set d7a to signal first digit done
	dbf.w	d0,loop			;do loop some more!
	swap	d7			;put last digit in string
	lsl.w	#4,d7			;move it to upper 4 bits
	move.b	d7,(a0)+		;store it in memory string
*
* Clean up and return with result in fp0.
*
end_bstr:
	movem.l	(a7)+,d0-d7
	rts
	end