PIC Microcontroller Math Method

24 Bit Floating Point Square Root

;**********************************************************************
;By Nikolai Golovchenko
;24 BIT FLOATING POINT SQARE ROOT
;Input:
;AARGB0 - high byte with sign bit
;AARGB1 - low byte
;AEXP - exponent 2^(AEXP - 127)
;FPFLAGS, RND - rounding/truncating (not used)
;Result:
;AARGB0-1, AEXP - 24 bit floating point
;Used:
;BARGB0-1, BEXP - temporary for result
;TEMPB0-1
;LOOPCOUNT - counter
;Memory used
;91 instructions
;9 RAM bytes
;Timing (includes call and return)
;6 cycles best case
;5+21+8*25-1+4+8*26-1+12= 445 cycles worst case
;**********************************************************************
;NOTES:	1)Square root is taken on absolute value of the number
;	(sign bit is ignored)
;	2)Rounding not implemented yet	
;**********************************************************************
FPSQRT24	
;Normalize input
;1)Check for zero input - if zero then exit
;2)Change sign to 1 and use sign bit as explicit MSB
;3)BEXP = AEXP - 127
;4)If AEXP can be divided by 2 (AEXP<0>=1) then bexp = bexp/2,
;BARGB2 = 1, AARGB<0-2> << 1 and find 23 more bits 
;5)Else bexp=(bexp-1)/2, find 24 more bits
;6)BEXP = BEXP + 127

	movf AEXP, w	;if zero input then return
	btfsc 0x03, 2
	 retlw 0x00

	clrf BARGB0	;set up all used
	clrf BARGB1	;temporary registers
	clrf TEMPB0	;
	clrf TEMPB1	;
	
	bsf AARGB0, 7	;make MSB explicit and ignore mantissa sign 

	addlw -127	;BEXP = aexp - 127 or aexp - 128
	btfss AEXP, 0
	 addlw -1
	movwf BEXP
	
	rlf BEXP, w	;arithmetic right shift of BEXP
	rrf BEXP, f	
	 
	btfss AEXP, 0	;shift input left if exp can be divided by two
	 goto FPSQRT24a
	bcf 0x03, 0
	rlf AARGB1, f
	rlf AARGB0, f
	bsf BARGB1, 0
FPSQRT24a
	movlw 127	;BEXP = BEXP + 127
	addwf BEXP, f	

;First find 8 bits of result. This will shift AARGB0 - AARGB1 to TEMPB1
;Then only zeros will be fed instead of AARGB0
	movlw 8			;loop counter
	movwf LOOPCOUNT	;
FPSQRT24b
	movlw 0x40	;substract test bit from 
	subwf AARGB0, f	;current lowest byte
	movf BARGB1, w	;and substract current result
	btfss 0x03, 0	;from higher bytes
	 incfsz BARGB1, w
	  subwf TEMPB1, w

	btfsc 0x03, 0	;if result = 1 then
	 movwf TEMPB1	;store substraction result

	rlf BARGB1, f	;shift result into result bytes
	rlf BARGB0, f	;
	
	movlw 0x40	;
	btfss BARGB1, 0	;if result bit = 1 then skip restoration
	 addwf AARGB0, f	;

	bcf 0x03, 0
	rlf AARGB1, f	;Shift out next two bits of input
	rlf AARGB0, f	;
	rlf TEMPB1, f	;
	rlf TEMPB0, f	;
	rlf AARGB1, f	;
	rlf AARGB0, f	;
	rlf TEMPB1, f	;
	rlf TEMPB0, f	;
	
	decfsz LOOPCOUNT, f	;repeat untill all 12 bits will be found
	 goto FPSQRT24b
	

;Find other 7 or 8 bits. Only zeros are fed instead of AARGB0
	movlw 7	;loop counter
	btfss AEXP, 0
	 movlw 8
	movwf LOOPCOUNT	;
FPSQRT24d
	movf TEMPB1, w	;store one byte of input
	movwf AARGB1
	bcf 0x03, 0		;simulate borrow (0x00 - 0x40 = 0xC0)
	incfsz BARGB1, w
	 subwf TEMPB1, f
	movf BARGB0, w
	btfss 0x03, 0
	 incfsz BARGB0, w
	  subwf TEMPB0, w

	btfsc 0x03, 0	;if result = 1 then
	 movwf TEMPB0	;store substraction result

	rlf BARGB1, f	;shift result into result bytes
	rlf BARGB0, f
	
	btfsc BARGB1, 0	;if result bit = 1 then skip restoration
	 goto FPSQRT24e
	movf AARGB1, w  ;restore previous data
	movwf TEMPB1	;
FPSQRT24e
	rrf BARGB1, w	;Shift out next two bits of input
	rlf TEMPB1, f	;
	rlf TEMPB0, f	;
	rrf BARGB1, w	;
	rlf TEMPB1, f	;
	rlf TEMPB0, f	;
	
	decfsz LOOPCOUNT, f	;repeat untill all 12 bits will be found
	 goto FPSQRT24d

;flag C, TEMPB1 - TEMPB0 contain current input that may be used to find 17th bit for rounding

;Copy BARG to AARG
	movf BEXP, w
	movwf AEXP
	movf BARGB0, w
	movwf AARGB0
	movf BARGB1, w
	movwf AARGB1
	bcf AARGB0, 7	;clear sign bit (overwrites explicit MSB, which is always one)
	
	retlw 0x00
;**********************************************************************
;Last updated 02Jan00