[BACK]Return to srem_mod.sa CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / fpsp

File: [local] / sys / arch / m68k / fpsp / srem_mod.sa (download)

Revision 1.1, Tue Mar 4 16:07:07 2008 UTC (16 years, 2 months ago) by nbrk
Branch point for: MAIN

Initial revision

*	$OpenBSD: srem_mod.sa,v 1.2 1996/05/29 21:05:41 niklas Exp $
*	$NetBSD: srem_mod.sa,v 1.3 1994/10/26 07:49:58 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.

*
*	srem_mod.sa 3.1 12/10/90
*
*      The entry point sMOD computes the floating point MOD of the
*      input values X and Y. The entry point sREM computes the floating
*      point (IEEE) REM of the input values X and Y.
*
*      INPUT
*      -----
*      Double-extended value Y is pointed to by address in register
*      A0. Double-extended value X is located in -12(A0). The values
*      of X and Y are both nonzero and finite; although either or both
*      of them can be denormalized. The special cases of zeros, NaNs,
*      and infinities are handled elsewhere.
*
*      OUTPUT
*      ------
*      FREM(X,Y) or FMOD(X,Y), depending on entry point.
*
*       ALGORITHM
*       ---------
*
*       Step 1.  Save and strip signs of X and Y: signX := sign(X),
*                signY := sign(Y), X := |X|, Y := |Y|, 
*                signQ := signX EOR signY. Record whether MOD or REM
*                is requested.
*
*       Step 2.  Set L := expo(X)-expo(Y), k := 0, Q := 0.
*                If (L < 0) then
*                   R := X, go to Step 4.
*                else
*                   R := 2^(-L)X, j := L.
*                endif
*
*       Step 3.  Perform MOD(X,Y)
*            3.1 If R = Y, go to Step 9.
*            3.2 If R > Y, then { R := R - Y, Q := Q + 1}
*            3.3 If j = 0, go to Step 4.
*            3.4 k := k + 1, j := j - 1, Q := 2Q, R := 2R. Go to
*                Step 3.1.
*
*       Step 4.  At this point, R = X - QY = MOD(X,Y). Set
*                Last_Subtract := false (used in Step 7 below). If
*                MOD is requested, go to Step 6. 
*
*       Step 5.  R = MOD(X,Y), but REM(X,Y) is requested.
*            5.1 If R < Y/2, then R = MOD(X,Y) = REM(X,Y). Go to
*                Step 6.
*            5.2 If R > Y/2, then { set Last_Subtract := true,
*                Q := Q + 1, Y := signY*Y }. Go to Step 6.
*            5.3 This is the tricky case of R = Y/2. If Q is odd,
*                then { Q := Q + 1, signX := -signX }.
*
*       Step 6.  R := signX*R.
*
*       Step 7.  If Last_Subtract = true, R := R - Y.
*
*       Step 8.  Return signQ, last 7 bits of Q, and R as required.
*
*       Step 9.  At this point, R = 2^(-j)*X - Q Y = Y. Thus,
*                X = 2^(j)*(Q+1)Y. set Q := 2^(j)*(Q+1),
*                R := 0. Return signQ, last 7 bits of Q, and R.
*                

SREM_MOD    IDNT    2,1 Motorola 040 Floating Point Software Package

	section    8

	include	fpsp.h

Mod_Flag  equ	L_SCR3
SignY     equ	FP_SCR3+4
SignX     equ	FP_SCR3+8
SignQ     equ	FP_SCR3+12
Sc_Flag   equ	FP_SCR4

Y         equ	FP_SCR1
Y_Hi      equ	Y+4
Y_Lo      equ	Y+8

R         equ	FP_SCR2
R_Hi      equ	R+4
R_Lo      equ	R+8


Scale     DC.L	$00010000,$80000000,$00000000,$00000000

	xref	t_avoid_unsupp

        xdef        smod
smod:

   Clr.L                Mod_Flag(a6)
   BRA.B                Mod_Rem

        xdef        srem
srem:

   Move.L               #1,Mod_Flag(a6)

Mod_Rem:
*..Save sign of X and Y
   MoveM.L              D2-D7,-(A7)     ...save data registers
   Move.W               (A0),D3
   Move.W               D3,SignY(a6)
   AndI.L               #$00007FFF,D3   ...Y := |Y|

*
   Move.L               4(A0),D4
   Move.L               8(A0),D5        ...(D3,D4,D5) is |Y|

   Tst.L                D3
   BNE.B                Y_Normal

   Move.L               #$00003FFE,D3	...$3FFD + 1
   Tst.L                D4
   BNE.B                HiY_not0

HiY_0:
   Move.L               D5,D4
   CLR.L                D5
   SubI.L               #32,D3
   CLR.L                D6
   BFFFO                D4{0:32},D6
   LSL.L                D6,D4
   Sub.L                D6,D3           ...(D3,D4,D5) is normalized
*                                       ...with bias $7FFD
   BRA.B                Chk_X

HiY_not0:
   CLR.L                D6
   BFFFO                D4{0:32},D6
   Sub.L                D6,D3
   LSL.L                D6,D4
   Move.L               D5,D7           ...a copy of D5
   LSL.L                D6,D5
   Neg.L                D6
   AddI.L               #32,D6
   LSR.L                D6,D7
   Or.L                 D7,D4           ...(D3,D4,D5) normalized
*                                       ...with bias $7FFD
   BRA.B                Chk_X

Y_Normal:
   AddI.L               #$00003FFE,D3   ...(D3,D4,D5) normalized
*                                       ...with bias $7FFD

Chk_X:
   Move.W               -12(A0),D0
   Move.W               D0,SignX(a6)
   Move.W               SignY(a6),D1
   EOr.L                D0,D1
   AndI.L               #$00008000,D1
   Move.W               D1,SignQ(a6)	...sign(Q) obtained
   AndI.L               #$00007FFF,D0
   Move.L               -8(A0),D1
   Move.L               -4(A0),D2       ...(D0,D1,D2) is |X|
   Tst.L                D0
   BNE.B                X_Normal
   Move.L               #$00003FFE,D0
   Tst.L                D1
   BNE.B                HiX_not0

HiX_0:
   Move.L               D2,D1
   CLR.L                D2
   SubI.L               #32,D0
   CLR.L                D6
   BFFFO                D1{0:32},D6
   LSL.L                D6,D1
   Sub.L                D6,D0           ...(D0,D1,D2) is normalized
*                                       ...with bias $7FFD
   BRA.B                Init

HiX_not0:
   CLR.L                D6
   BFFFO                D1{0:32},D6
   Sub.L                D6,D0
   LSL.L                D6,D1
   Move.L               D2,D7           ...a copy of D2
   LSL.L                D6,D2
   Neg.L                D6
   AddI.L               #32,D6
   LSR.L                D6,D7
   Or.L                 D7,D1           ...(D0,D1,D2) normalized
*                                       ...with bias $7FFD
   BRA.B                Init

X_Normal:
   AddI.L               #$00003FFE,D0   ...(D0,D1,D2) normalized
*                                       ...with bias $7FFD

Init:
*
   Move.L               D3,L_SCR1(a6)   ...save biased expo(Y)
   move.l		d0,L_SCR2(a6)	;save d0
   Sub.L                D3,D0           ...L := expo(X)-expo(Y)
*   Move.L               D0,L            ...D0 is j
   CLR.L                D6              ...D6 := carry <- 0
   CLR.L                D3              ...D3 is Q
   MoveA.L              #0,A1           ...A1 is k; j+k=L, Q=0

*..(Carry,D1,D2) is R
   Tst.L                D0
   BGE.B                Mod_Loop

*..expo(X) < expo(Y). Thus X = mod(X,Y)
*
   move.l		L_SCR2(a6),d0	;restore d0
   BRA.W                Get_Mod

*..At this point  R = 2^(-L)X; Q = 0; k = 0; and  k+j = L


Mod_Loop:
   Tst.L                D6              ...test carry bit
   BGT.B                R_GT_Y

*..At this point carry = 0, R = (D1,D2), Y = (D4,D5)
   Cmp.L                D4,D1           ...compare hi(R) and hi(Y)
   BNE.B                R_NE_Y
   Cmp.L                D5,D2           ...compare lo(R) and lo(Y)
   BNE.B                R_NE_Y

*..At this point, R = Y
   BRA.W                Rem_is_0

R_NE_Y:
*..use the borrow of the previous compare
   BCS.B                R_LT_Y          ...borrow is set iff R < Y

R_GT_Y:
*..If Carry is set, then Y < (Carry,D1,D2) < 2Y. Otherwise, Carry = 0
*..and Y < (D1,D2) < 2Y. Either way, perform R - Y
   Sub.L                D5,D2           ...lo(R) - lo(Y)
   SubX.L               D4,D1           ...hi(R) - hi(Y)
   CLR.L                D6              ...clear carry
   AddQ.L               #1,D3           ...Q := Q + 1

R_LT_Y:
*..At this point, Carry=0, R < Y. R = 2^(k-L)X - QY; k+j = L; j >= 0.
   Tst.L                D0              ...see if j = 0.
   BEQ.B                PostLoop

   Add.L                D3,D3           ...Q := 2Q
   Add.L                D2,D2           ...lo(R) = 2lo(R)
   AddX.L               D1,D1           ...hi(R) = 2hi(R) + carry
   SCS                  D6              ...set Carry if 2(R) overflows
   AddQ.L               #1,A1           ...k := k+1
   SubQ.L               #1,D0           ...j := j - 1
*..At this point, R=(Carry,D1,D2) = 2^(k-L)X - QY, j+k=L, j >= 0, R < 2Y.

   BRA.B                Mod_Loop

PostLoop:
*..k = L, j = 0, Carry = 0, R = (D1,D2) = X - QY, R < Y.

*..normalize R.
   Move.L               L_SCR1(a6),D0           ...new biased expo of R
   Tst.L                D1
   BNE.B                HiR_not0

HiR_0:
   Move.L               D2,D1
   CLR.L                D2
   SubI.L               #32,D0
   CLR.L                D6
   BFFFO                D1{0:32},D6
   LSL.L                D6,D1
   Sub.L                D6,D0           ...(D0,D1,D2) is normalized
*                                       ...with bias $7FFD
   BRA.B                Get_Mod

HiR_not0:
   CLR.L                D6
   BFFFO                D1{0:32},D6
   BMI.B                Get_Mod         ...already normalized
   Sub.L                D6,D0
   LSL.L                D6,D1
   Move.L               D2,D7           ...a copy of D2
   LSL.L                D6,D2
   Neg.L                D6
   AddI.L               #32,D6
   LSR.L                D6,D7
   Or.L                 D7,D1           ...(D0,D1,D2) normalized

*
Get_Mod:
   CmpI.L		#$000041FE,D0
   BGE.B		No_Scale
Do_Scale:
   Move.W		D0,R(a6)
   clr.w		R+2(a6)
   Move.L		D1,R_Hi(a6)
   Move.L		D2,R_Lo(a6)
   Move.L		L_SCR1(a6),D6
   Move.W		D6,Y(a6)
   clr.w		Y+2(a6)
   Move.L		D4,Y_Hi(a6)
   Move.L		D5,Y_Lo(a6)
   FMove.X		R(a6),fp0		...no exception
   Move.L		#1,Sc_Flag(a6)
   BRA.B		ModOrRem
No_Scale:
   Move.L		D1,R_Hi(a6)
   Move.L		D2,R_Lo(a6)
   SubI.L		#$3FFE,D0
   Move.W		D0,R(a6)
   clr.w		R+2(a6)
   Move.L		L_SCR1(a6),D6
   SubI.L		#$3FFE,D6
   Move.L		D6,L_SCR1(a6)
   FMove.X		R(a6),fp0
   Move.W		D6,Y(a6)
   Move.L		D4,Y_Hi(a6)
   Move.L		D5,Y_Lo(a6)
   Clr.L		Sc_Flag(a6)

*


ModOrRem:
   Move.L               Mod_Flag(a6),D6
   BEQ.B                Fix_Sign

   Move.L               L_SCR1(a6),D6           ...new biased expo(Y)
   SubQ.L               #1,D6           ...biased expo(Y/2)
   Cmp.L                D6,D0
   BLT.B                Fix_Sign
   BGT.B                Last_Sub

   Cmp.L                D4,D1
   BNE.B                Not_EQ
   Cmp.L                D5,D2
   BNE.B                Not_EQ
   BRA.W                Tie_Case

Not_EQ:
   BCS.B                Fix_Sign

Last_Sub:
*
   FSub.X		Y(a6),fp0		...no exceptions
   AddQ.L               #1,D3           ...Q := Q + 1

*

Fix_Sign:
*..Get sign of X
   Move.W               SignX(a6),D6
   BGE.B		Get_Q
   FNeg.X		fp0

*..Get Q
*
Get_Q:
   clr.l		d6		
   Move.W               SignQ(a6),D6        ...D6 is sign(Q)
   Move.L               #8,D7
   LSR.L                D7,D6           
   AndI.L               #$0000007F,D3   ...7 bits of Q
   Or.L                 D6,D3           ...sign and bits of Q
   Swap                 D3
   FMove.L              fpsr,D6
   AndI.L               #$FF00FFFF,D6
   Or.L                 D3,D6
   FMove.L              D6,fpsr         ...put Q in fpsr

*
Restore:
   MoveM.L              (A7)+,D2-D7
   FMove.L              USER_FPCR(a6),fpcr
   Move.L               Sc_Flag(a6),D0
   BEQ.B                Finish
   FMul.X		Scale(pc),fp0	...may cause underflow
   bra			t_avoid_unsupp	;check for denorm as a
*					;result of the scaling

Finish:
	fmove.x		fp0,fp0		;capture exceptions & round
	rts

Rem_is_0:
*..R = 2^(-j)X - Q Y = Y, thus R = 0 and quotient = 2^j (Q+1)
   AddQ.L               #1,D3
   CmpI.L               #8,D0           ...D0 is j 
   BGE.B                Q_Big

   LSL.L                D0,D3
   BRA.B                Set_R_0

Q_Big:
   CLR.L                D3

Set_R_0:
   FMove.S		#:00000000,fp0
   Clr.L		Sc_Flag(a6)
   BRA.W                Fix_Sign

Tie_Case:
*..Check parity of Q
   Move.L               D3,D6
   AndI.L               #$00000001,D6
   Tst.L                D6
   BEq.W                Fix_Sign	...Q is even

*..Q is odd, Q := Q + 1, signX := -signX
   AddQ.L               #1,D3
   Move.W               SignX(a6),D6
   EOrI.L               #$00008000,D6
   Move.W               D6,SignX(a6)
   BRA.W                Fix_Sign

   End