/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#include <chips/ARM/func.h>

/*
*	The function calculates the reciprocal of a 32-bit number
*
*	The argument is in 0.32 format, in the range of (0.25,1.0)
*	The result is in 2.30 format, in the range of [1.0,4.0)
*
*	The function uses Newton-Raphson iteration. The initial estimate is:
*
*		r0 = 1.5 + sqrt(2) - 2 * x
*
*	then successive steps are calculated by the
*
*		r' = r * ( 2.0 - x * r )
*
*	formula. If x is at least 0.5, then 4 iterations are executed, if x is
*	less than 0.5, then 5 iterations are used. If x is less than or equal to
*	0.25, the returned value is garbage.
*/

	afunc	rec32
	mov		r1,r0
	ldr		r0,const
	sub		r0,r0,r1,lsr #1
	.rept	4
	umull	r2,r3,r1,r0					// r3:r2 	x * r
	rsbs	r2,r2,#0
	rsc		r3,r3,#0x80000000			// r3:r2 	2.0 - x * r
	umull	r12,r2,r2,r0				// r2:r12	r * LO( 2.0 - x * r )
	add		r2,r2,r12,lsr #31			// r2 rounded up. There can't be ovf.
	mov		r12,#0
	umlal	r2,r12,r3,r0				// r12:r2 is the upper 64 bits
	movs	r0,r2,lsr #30
	adc		r0,r0,r12,lsl #2
	.endr
	tst		r1,#0x80000000
	bxne	lr
	umull	r2,r3,r1,r0
	rsbs	r2,r2,#0
	rsc		r3,r3,#0x80000000
	umull	r12,r2,r2,r0
	add		r2,r2,r12,lsr #31
	mov		r12,#0
	umlal	r2,r12,r3,r0
	movs	r0,r2,lsr #30
	adc		r0,r0,r12,lsl #2
	bx		lr
const:
	.word	0xba8240b7

