1*3cab2bb3Spatrick//===----------------------Hexagon builtin routine ------------------------===//
2*3cab2bb3Spatrick//
3*3cab2bb3Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*3cab2bb3Spatrick// See https://llvm.org/LICENSE.txt for license information.
5*3cab2bb3Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*3cab2bb3Spatrick//
7*3cab2bb3Spatrick//===----------------------------------------------------------------------===//
8*3cab2bb3Spatrick
9*3cab2bb3Spatrick// Double Precision Divide
10*3cab2bb3Spatrick
11*3cab2bb3Spatrick#define A r1:0
12*3cab2bb3Spatrick#define AH r1
13*3cab2bb3Spatrick#define AL r0
14*3cab2bb3Spatrick
15*3cab2bb3Spatrick#define B r3:2
16*3cab2bb3Spatrick#define BH r3
17*3cab2bb3Spatrick#define BL r2
18*3cab2bb3Spatrick
19*3cab2bb3Spatrick#define Q r5:4
20*3cab2bb3Spatrick#define QH r5
21*3cab2bb3Spatrick#define QL r4
22*3cab2bb3Spatrick
23*3cab2bb3Spatrick#define PROD r7:6
24*3cab2bb3Spatrick#define PRODHI r7
25*3cab2bb3Spatrick#define PRODLO r6
26*3cab2bb3Spatrick
27*3cab2bb3Spatrick#define SFONE r8
28*3cab2bb3Spatrick#define SFDEN r9
29*3cab2bb3Spatrick#define SFERROR r10
30*3cab2bb3Spatrick#define SFRECIP r11
31*3cab2bb3Spatrick
32*3cab2bb3Spatrick#define EXPBA r13:12
33*3cab2bb3Spatrick#define EXPB r13
34*3cab2bb3Spatrick#define EXPA r12
35*3cab2bb3Spatrick
36*3cab2bb3Spatrick#define REMSUB2 r15:14
37*3cab2bb3Spatrick
38*3cab2bb3Spatrick
39*3cab2bb3Spatrick
40*3cab2bb3Spatrick#define SIGN r28
41*3cab2bb3Spatrick
42*3cab2bb3Spatrick#define Q_POSITIVE p3
43*3cab2bb3Spatrick#define NORMAL p2
44*3cab2bb3Spatrick#define NO_OVF_UNF p1
45*3cab2bb3Spatrick#define P_TMP p0
46*3cab2bb3Spatrick
47*3cab2bb3Spatrick#define RECIPEST_SHIFT 3
48*3cab2bb3Spatrick#define QADJ 61
49*3cab2bb3Spatrick
50*3cab2bb3Spatrick#define DFCLASS_NORMAL 0x02
51*3cab2bb3Spatrick#define DFCLASS_NUMBER 0x0F
52*3cab2bb3Spatrick#define DFCLASS_INFINITE 0x08
53*3cab2bb3Spatrick#define DFCLASS_ZERO 0x01
54*3cab2bb3Spatrick#define DFCLASS_NONZERO (DFCLASS_NUMBER ^ DFCLASS_ZERO)
55*3cab2bb3Spatrick#define DFCLASS_NONINFINITE (DFCLASS_NUMBER ^ DFCLASS_INFINITE)
56*3cab2bb3Spatrick
57*3cab2bb3Spatrick#define DF_MANTBITS 52
58*3cab2bb3Spatrick#define DF_EXPBITS 11
59*3cab2bb3Spatrick#define SF_MANTBITS 23
60*3cab2bb3Spatrick#define SF_EXPBITS 8
61*3cab2bb3Spatrick#define DF_BIAS 0x3ff
62*3cab2bb3Spatrick
63*3cab2bb3Spatrick#define SR_ROUND_OFF 22
64*3cab2bb3Spatrick
65*3cab2bb3Spatrick#define Q6_ALIAS(TAG) .global __qdsp_##TAG ; .set __qdsp_##TAG, __hexagon_##TAG
66*3cab2bb3Spatrick#define FAST_ALIAS(TAG) .global __hexagon_fast_##TAG ; .set __hexagon_fast_##TAG, __hexagon_##TAG
67*3cab2bb3Spatrick#define FAST2_ALIAS(TAG) .global __hexagon_fast2_##TAG ; .set __hexagon_fast2_##TAG, __hexagon_##TAG
68*3cab2bb3Spatrick#define END(TAG) .size TAG,.-TAG
69*3cab2bb3Spatrick
70*3cab2bb3Spatrick	.text
71*3cab2bb3Spatrick	.global __hexagon_divdf3
72*3cab2bb3Spatrick	.type __hexagon_divdf3,@function
73*3cab2bb3Spatrick	Q6_ALIAS(divdf3)
74*3cab2bb3Spatrick        FAST_ALIAS(divdf3)
75*3cab2bb3Spatrick        FAST2_ALIAS(divdf3)
76*3cab2bb3Spatrick	.p2align 5
77*3cab2bb3Spatrick__hexagon_divdf3:
78*3cab2bb3Spatrick	{
79*3cab2bb3Spatrick		NORMAL = dfclass(A,#DFCLASS_NORMAL)
80*3cab2bb3Spatrick		NORMAL = dfclass(B,#DFCLASS_NORMAL)
81*3cab2bb3Spatrick		EXPBA = combine(BH,AH)
82*3cab2bb3Spatrick		SIGN = xor(AH,BH)
83*3cab2bb3Spatrick	}
84*3cab2bb3Spatrick#undef A
85*3cab2bb3Spatrick#undef AH
86*3cab2bb3Spatrick#undef AL
87*3cab2bb3Spatrick#undef B
88*3cab2bb3Spatrick#undef BH
89*3cab2bb3Spatrick#undef BL
90*3cab2bb3Spatrick#define REM r1:0
91*3cab2bb3Spatrick#define REMHI r1
92*3cab2bb3Spatrick#define REMLO r0
93*3cab2bb3Spatrick#define DENOM r3:2
94*3cab2bb3Spatrick#define DENOMHI r3
95*3cab2bb3Spatrick#define DENOMLO r2
96*3cab2bb3Spatrick	{
97*3cab2bb3Spatrick		if (!NORMAL) jump .Ldiv_abnormal
98*3cab2bb3Spatrick		PROD = extractu(DENOM,#SF_MANTBITS,#DF_MANTBITS-SF_MANTBITS)
99*3cab2bb3Spatrick		SFONE = ##0x3f800001
100*3cab2bb3Spatrick	}
101*3cab2bb3Spatrick	{
102*3cab2bb3Spatrick		SFDEN = or(SFONE,PRODLO)
103*3cab2bb3Spatrick		EXPB = extractu(EXPB,#DF_EXPBITS,#DF_MANTBITS-32)
104*3cab2bb3Spatrick		EXPA = extractu(EXPA,#DF_EXPBITS,#DF_MANTBITS-32)
105*3cab2bb3Spatrick		Q_POSITIVE = cmp.gt(SIGN,#-1)
106*3cab2bb3Spatrick	}
107*3cab2bb3Spatrick#undef SIGN
108*3cab2bb3Spatrick#define ONE r28
109*3cab2bb3Spatrick.Ldenorm_continue:
110*3cab2bb3Spatrick	{
111*3cab2bb3Spatrick		SFRECIP,P_TMP = sfrecipa(SFONE,SFDEN)
112*3cab2bb3Spatrick		SFERROR = and(SFONE,#-2)
113*3cab2bb3Spatrick		ONE = #1
114*3cab2bb3Spatrick		EXPA = sub(EXPA,EXPB)
115*3cab2bb3Spatrick	}
116*3cab2bb3Spatrick#undef EXPB
117*3cab2bb3Spatrick#define RECIPEST r13
118*3cab2bb3Spatrick	{
119*3cab2bb3Spatrick		SFERROR -= sfmpy(SFRECIP,SFDEN):lib
120*3cab2bb3Spatrick		REMHI = insert(ONE,#DF_EXPBITS+1,#DF_MANTBITS-32)
121*3cab2bb3Spatrick		RECIPEST = ##0x00800000 << RECIPEST_SHIFT
122*3cab2bb3Spatrick	}
123*3cab2bb3Spatrick	{
124*3cab2bb3Spatrick		SFRECIP += sfmpy(SFRECIP,SFERROR):lib
125*3cab2bb3Spatrick		DENOMHI = insert(ONE,#DF_EXPBITS+1,#DF_MANTBITS-32)
126*3cab2bb3Spatrick		SFERROR = and(SFONE,#-2)
127*3cab2bb3Spatrick	}
128*3cab2bb3Spatrick	{
129*3cab2bb3Spatrick		SFERROR -= sfmpy(SFRECIP,SFDEN):lib
130*3cab2bb3Spatrick		QH = #-DF_BIAS+1
131*3cab2bb3Spatrick		QL = #DF_BIAS-1
132*3cab2bb3Spatrick	}
133*3cab2bb3Spatrick	{
134*3cab2bb3Spatrick		SFRECIP += sfmpy(SFRECIP,SFERROR):lib
135*3cab2bb3Spatrick		NO_OVF_UNF = cmp.gt(EXPA,QH)
136*3cab2bb3Spatrick		NO_OVF_UNF = !cmp.gt(EXPA,QL)
137*3cab2bb3Spatrick	}
138*3cab2bb3Spatrick	{
139*3cab2bb3Spatrick		RECIPEST = insert(SFRECIP,#SF_MANTBITS,#RECIPEST_SHIFT)
140*3cab2bb3Spatrick		Q = #0
141*3cab2bb3Spatrick		EXPA = add(EXPA,#-QADJ)
142*3cab2bb3Spatrick	}
143*3cab2bb3Spatrick#undef SFERROR
144*3cab2bb3Spatrick#undef SFRECIP
145*3cab2bb3Spatrick#define TMP r10
146*3cab2bb3Spatrick#define TMP1 r11
147*3cab2bb3Spatrick	{
148*3cab2bb3Spatrick		RECIPEST = add(RECIPEST,#((-3) << RECIPEST_SHIFT))
149*3cab2bb3Spatrick	}
150*3cab2bb3Spatrick
151*3cab2bb3Spatrick#define DIV_ITER1B(QSHIFTINSN,QSHIFT,REMSHIFT,EXTRA) \
152*3cab2bb3Spatrick	{ \
153*3cab2bb3Spatrick		PROD = mpyu(RECIPEST,REMHI); \
154*3cab2bb3Spatrick		REM = asl(REM,# ## ( REMSHIFT )); \
155*3cab2bb3Spatrick	}; \
156*3cab2bb3Spatrick	{ \
157*3cab2bb3Spatrick		PRODLO = # ## 0; \
158*3cab2bb3Spatrick		REM -= mpyu(PRODHI,DENOMLO); \
159*3cab2bb3Spatrick		REMSUB2 = mpyu(PRODHI,DENOMHI); \
160*3cab2bb3Spatrick	}; \
161*3cab2bb3Spatrick	{ \
162*3cab2bb3Spatrick		Q += QSHIFTINSN(PROD, # ## ( QSHIFT )); \
163*3cab2bb3Spatrick		REM -= asl(REMSUB2, # ## 32); \
164*3cab2bb3Spatrick		EXTRA \
165*3cab2bb3Spatrick	}
166*3cab2bb3Spatrick
167*3cab2bb3Spatrick
168*3cab2bb3Spatrick	DIV_ITER1B(ASL,14,15,)
169*3cab2bb3Spatrick	DIV_ITER1B(ASR,1,15,)
170*3cab2bb3Spatrick	DIV_ITER1B(ASR,16,15,)
171*3cab2bb3Spatrick	DIV_ITER1B(ASR,31,15,PROD=# ( 0 );)
172*3cab2bb3Spatrick
173*3cab2bb3Spatrick#undef REMSUB2
174*3cab2bb3Spatrick#define TMPPAIR r15:14
175*3cab2bb3Spatrick#define TMPPAIRHI r15
176*3cab2bb3Spatrick#define TMPPAIRLO r14
177*3cab2bb3Spatrick#undef RECIPEST
178*3cab2bb3Spatrick#define EXPB r13
179*3cab2bb3Spatrick	{
180*3cab2bb3Spatrick		// compare or sub with carry
181*3cab2bb3Spatrick		TMPPAIR = sub(REM,DENOM)
182*3cab2bb3Spatrick		P_TMP = cmp.gtu(DENOM,REM)
183*3cab2bb3Spatrick		// set up amt to add to q
184*3cab2bb3Spatrick		if (!P_TMP.new) PRODLO  = #2
185*3cab2bb3Spatrick	}
186*3cab2bb3Spatrick	{
187*3cab2bb3Spatrick		Q = add(Q,PROD)
188*3cab2bb3Spatrick		if (!P_TMP) REM = TMPPAIR
189*3cab2bb3Spatrick		TMPPAIR = #0
190*3cab2bb3Spatrick	}
191*3cab2bb3Spatrick	{
192*3cab2bb3Spatrick		P_TMP = cmp.eq(REM,TMPPAIR)
193*3cab2bb3Spatrick		if (!P_TMP.new) QL = or(QL,ONE)
194*3cab2bb3Spatrick	}
195*3cab2bb3Spatrick	{
196*3cab2bb3Spatrick		PROD = neg(Q)
197*3cab2bb3Spatrick	}
198*3cab2bb3Spatrick	{
199*3cab2bb3Spatrick		if (!Q_POSITIVE) Q = PROD
200*3cab2bb3Spatrick	}
201*3cab2bb3Spatrick#undef REM
202*3cab2bb3Spatrick#undef REMHI
203*3cab2bb3Spatrick#undef REMLO
204*3cab2bb3Spatrick#undef DENOM
205*3cab2bb3Spatrick#undef DENOMLO
206*3cab2bb3Spatrick#undef DENOMHI
207*3cab2bb3Spatrick#define A r1:0
208*3cab2bb3Spatrick#define AH r1
209*3cab2bb3Spatrick#define AL r0
210*3cab2bb3Spatrick#define B r3:2
211*3cab2bb3Spatrick#define BH r3
212*3cab2bb3Spatrick#define BL r2
213*3cab2bb3Spatrick	{
214*3cab2bb3Spatrick		A = convert_d2df(Q)
215*3cab2bb3Spatrick		if (!NO_OVF_UNF) jump .Ldiv_ovf_unf
216*3cab2bb3Spatrick	}
217*3cab2bb3Spatrick	{
218*3cab2bb3Spatrick		AH += asl(EXPA,#DF_MANTBITS-32)
219*3cab2bb3Spatrick		jumpr r31
220*3cab2bb3Spatrick	}
221*3cab2bb3Spatrick
222*3cab2bb3Spatrick.Ldiv_ovf_unf:
223*3cab2bb3Spatrick	{
224*3cab2bb3Spatrick		AH += asl(EXPA,#DF_MANTBITS-32)
225*3cab2bb3Spatrick		EXPB = extractu(AH,#DF_EXPBITS,#DF_MANTBITS-32)
226*3cab2bb3Spatrick	}
227*3cab2bb3Spatrick	{
228*3cab2bb3Spatrick		PROD = abs(Q)
229*3cab2bb3Spatrick		EXPA = add(EXPA,EXPB)
230*3cab2bb3Spatrick	}
231*3cab2bb3Spatrick	{
232*3cab2bb3Spatrick		P_TMP = cmp.gt(EXPA,##DF_BIAS+DF_BIAS)		// overflow
233*3cab2bb3Spatrick		if (P_TMP.new) jump:nt .Ldiv_ovf
234*3cab2bb3Spatrick	}
235*3cab2bb3Spatrick	{
236*3cab2bb3Spatrick		P_TMP = cmp.gt(EXPA,#0)
237*3cab2bb3Spatrick		if (P_TMP.new) jump:nt .Lpossible_unf		// round up to normal possible...
238*3cab2bb3Spatrick	}
239*3cab2bb3Spatrick	// Underflow
240*3cab2bb3Spatrick	// We know what the infinite range exponent should be (EXPA)
241*3cab2bb3Spatrick	// Q is 2's complement, PROD is abs(Q)
242*3cab2bb3Spatrick	// Normalize Q, shift right, add a high bit, convert, change exponent
243*3cab2bb3Spatrick
244*3cab2bb3Spatrick#define FUDGE1 7	// how much to shift right
245*3cab2bb3Spatrick#define FUDGE2 4	// how many guard/round to keep at lsbs
246*3cab2bb3Spatrick
247*3cab2bb3Spatrick	{
248*3cab2bb3Spatrick		EXPB = add(clb(PROD),#-1)			// doesn't need to be added in since
249*3cab2bb3Spatrick		EXPA = sub(#FUDGE1,EXPA)			// we extract post-converted exponent
250*3cab2bb3Spatrick		TMP = USR
251*3cab2bb3Spatrick		TMP1 = #63
252*3cab2bb3Spatrick	}
253*3cab2bb3Spatrick	{
254*3cab2bb3Spatrick		EXPB = min(EXPA,TMP1)
255*3cab2bb3Spatrick		TMP1 = or(TMP,#0x030)
256*3cab2bb3Spatrick		PROD = asl(PROD,EXPB)
257*3cab2bb3Spatrick		EXPA = #0
258*3cab2bb3Spatrick	}
259*3cab2bb3Spatrick	{
260*3cab2bb3Spatrick		TMPPAIR = extractu(PROD,EXPBA)				// bits that will get shifted out
261*3cab2bb3Spatrick		PROD = lsr(PROD,EXPB)					// shift out bits
262*3cab2bb3Spatrick		B = #1
263*3cab2bb3Spatrick	}
264*3cab2bb3Spatrick	{
265*3cab2bb3Spatrick		P_TMP = cmp.gtu(B,TMPPAIR)
266*3cab2bb3Spatrick		if (!P_TMP.new) PRODLO = or(BL,PRODLO)
267*3cab2bb3Spatrick		PRODHI = setbit(PRODHI,#DF_MANTBITS-32+FUDGE2)
268*3cab2bb3Spatrick	}
269*3cab2bb3Spatrick	{
270*3cab2bb3Spatrick		Q = neg(PROD)
271*3cab2bb3Spatrick		P_TMP = bitsclr(PRODLO,#(1<<FUDGE2)-1)
272*3cab2bb3Spatrick		if (!P_TMP.new) TMP = TMP1
273*3cab2bb3Spatrick	}
274*3cab2bb3Spatrick	{
275*3cab2bb3Spatrick		USR = TMP
276*3cab2bb3Spatrick		if (Q_POSITIVE) Q = PROD
277*3cab2bb3Spatrick		TMP = #-DF_BIAS-(DF_MANTBITS+FUDGE2)
278*3cab2bb3Spatrick	}
279*3cab2bb3Spatrick	{
280*3cab2bb3Spatrick		A = convert_d2df(Q)
281*3cab2bb3Spatrick	}
282*3cab2bb3Spatrick	{
283*3cab2bb3Spatrick		AH += asl(TMP,#DF_MANTBITS-32)
284*3cab2bb3Spatrick		jumpr r31
285*3cab2bb3Spatrick	}
286*3cab2bb3Spatrick
287*3cab2bb3Spatrick
288*3cab2bb3Spatrick.Lpossible_unf:
289*3cab2bb3Spatrick	// If upper parts of Q were all F's, but abs(A) == 0x00100000_00000000, we rounded up to min_normal
290*3cab2bb3Spatrick	// The answer is correct, but we need to raise Underflow
291*3cab2bb3Spatrick	{
292*3cab2bb3Spatrick		B = extractu(A,#63,#0)
293*3cab2bb3Spatrick		TMPPAIR = combine(##0x00100000,#0)		// min normal
294*3cab2bb3Spatrick		TMP = #0x7FFF
295*3cab2bb3Spatrick	}
296*3cab2bb3Spatrick	{
297*3cab2bb3Spatrick		P_TMP = dfcmp.eq(TMPPAIR,B)		// Is everything zero in the rounded value...
298*3cab2bb3Spatrick		P_TMP = bitsset(PRODHI,TMP)		// but a bunch of bits set in the unrounded abs(quotient)?
299*3cab2bb3Spatrick	}
300*3cab2bb3Spatrick
301*3cab2bb3Spatrick#if (__HEXAGON_ARCH__ == 60)
302*3cab2bb3Spatrick		TMP = USR		// If not, just return
303*3cab2bb3Spatrick		if (!P_TMP) jumpr r31   // Else, we want to set Unf+Inexact
304*3cab2bb3Spatrick					// Note that inexact is already set...
305*3cab2bb3Spatrick#else
306*3cab2bb3Spatrick	{
307*3cab2bb3Spatrick		if (!P_TMP) jumpr r31			// If not, just return
308*3cab2bb3Spatrick		TMP = USR				// Else, we want to set Unf+Inexact
309*3cab2bb3Spatrick	}						// Note that inexact is already set...
310*3cab2bb3Spatrick#endif
311*3cab2bb3Spatrick	{
312*3cab2bb3Spatrick		TMP = or(TMP,#0x30)
313*3cab2bb3Spatrick	}
314*3cab2bb3Spatrick	{
315*3cab2bb3Spatrick		USR = TMP
316*3cab2bb3Spatrick	}
317*3cab2bb3Spatrick	{
318*3cab2bb3Spatrick		p0 = dfcmp.eq(A,A)
319*3cab2bb3Spatrick		jumpr r31
320*3cab2bb3Spatrick	}
321*3cab2bb3Spatrick
322*3cab2bb3Spatrick.Ldiv_ovf:
323*3cab2bb3Spatrick
324*3cab2bb3Spatrick	// Raise Overflow, and choose the correct overflow value (saturated normal or infinity)
325*3cab2bb3Spatrick
326*3cab2bb3Spatrick	{
327*3cab2bb3Spatrick		TMP = USR
328*3cab2bb3Spatrick		B = combine(##0x7fefffff,#-1)
329*3cab2bb3Spatrick		AH = mux(Q_POSITIVE,#0,#-1)
330*3cab2bb3Spatrick	}
331*3cab2bb3Spatrick	{
332*3cab2bb3Spatrick		PROD = combine(##0x7ff00000,#0)
333*3cab2bb3Spatrick		QH = extractu(TMP,#2,#SR_ROUND_OFF)
334*3cab2bb3Spatrick		TMP = or(TMP,#0x28)
335*3cab2bb3Spatrick	}
336*3cab2bb3Spatrick	{
337*3cab2bb3Spatrick		USR = TMP
338*3cab2bb3Spatrick		QH ^= lsr(AH,#31)
339*3cab2bb3Spatrick		QL = QH
340*3cab2bb3Spatrick	}
341*3cab2bb3Spatrick	{
342*3cab2bb3Spatrick		p0 = !cmp.eq(QL,#1)		// if not round-to-zero
343*3cab2bb3Spatrick		p0 = !cmp.eq(QH,#2)		// and not rounding the other way
344*3cab2bb3Spatrick		if (p0.new) B = PROD		// go to inf
345*3cab2bb3Spatrick		p0 = dfcmp.eq(B,B)		// get exceptions
346*3cab2bb3Spatrick	}
347*3cab2bb3Spatrick	{
348*3cab2bb3Spatrick		A = insert(B,#63,#0)
349*3cab2bb3Spatrick		jumpr r31
350*3cab2bb3Spatrick	}
351*3cab2bb3Spatrick
352*3cab2bb3Spatrick#undef ONE
353*3cab2bb3Spatrick#define SIGN r28
354*3cab2bb3Spatrick#undef NORMAL
355*3cab2bb3Spatrick#undef NO_OVF_UNF
356*3cab2bb3Spatrick#define P_INF p1
357*3cab2bb3Spatrick#define P_ZERO p2
358*3cab2bb3Spatrick.Ldiv_abnormal:
359*3cab2bb3Spatrick	{
360*3cab2bb3Spatrick		P_TMP = dfclass(A,#DFCLASS_NUMBER)
361*3cab2bb3Spatrick		P_TMP = dfclass(B,#DFCLASS_NUMBER)
362*3cab2bb3Spatrick		Q_POSITIVE = cmp.gt(SIGN,#-1)
363*3cab2bb3Spatrick	}
364*3cab2bb3Spatrick	{
365*3cab2bb3Spatrick		P_INF = dfclass(A,#DFCLASS_INFINITE)
366*3cab2bb3Spatrick		P_INF = dfclass(B,#DFCLASS_INFINITE)
367*3cab2bb3Spatrick	}
368*3cab2bb3Spatrick	{
369*3cab2bb3Spatrick		P_ZERO = dfclass(A,#DFCLASS_ZERO)
370*3cab2bb3Spatrick		P_ZERO = dfclass(B,#DFCLASS_ZERO)
371*3cab2bb3Spatrick	}
372*3cab2bb3Spatrick	{
373*3cab2bb3Spatrick		if (!P_TMP) jump .Ldiv_nan
374*3cab2bb3Spatrick		if (P_INF) jump .Ldiv_invalid
375*3cab2bb3Spatrick	}
376*3cab2bb3Spatrick	{
377*3cab2bb3Spatrick		if (P_ZERO) jump .Ldiv_invalid
378*3cab2bb3Spatrick	}
379*3cab2bb3Spatrick	{
380*3cab2bb3Spatrick		P_ZERO = dfclass(A,#DFCLASS_NONZERO)		// nonzero
381*3cab2bb3Spatrick		P_ZERO = dfclass(B,#DFCLASS_NONINFINITE)	// non-infinite
382*3cab2bb3Spatrick	}
383*3cab2bb3Spatrick	{
384*3cab2bb3Spatrick		P_INF = dfclass(A,#DFCLASS_NONINFINITE)	// non-infinite
385*3cab2bb3Spatrick		P_INF = dfclass(B,#DFCLASS_NONZERO)	// nonzero
386*3cab2bb3Spatrick	}
387*3cab2bb3Spatrick	{
388*3cab2bb3Spatrick		if (!P_ZERO) jump .Ldiv_zero_result
389*3cab2bb3Spatrick		if (!P_INF) jump .Ldiv_inf_result
390*3cab2bb3Spatrick	}
391*3cab2bb3Spatrick	// Now we've narrowed it down to (de)normal / (de)normal
392*3cab2bb3Spatrick	// Set up A/EXPA B/EXPB and go back
393*3cab2bb3Spatrick#undef P_ZERO
394*3cab2bb3Spatrick#undef P_INF
395*3cab2bb3Spatrick#define P_TMP2 p1
396*3cab2bb3Spatrick	{
397*3cab2bb3Spatrick		P_TMP = dfclass(A,#DFCLASS_NORMAL)
398*3cab2bb3Spatrick		P_TMP2 = dfclass(B,#DFCLASS_NORMAL)
399*3cab2bb3Spatrick		TMP = ##0x00100000
400*3cab2bb3Spatrick	}
401*3cab2bb3Spatrick	{
402*3cab2bb3Spatrick		EXPBA = combine(BH,AH)
403*3cab2bb3Spatrick		AH = insert(TMP,#DF_EXPBITS+1,#DF_MANTBITS-32)		// clear out hidden bit, sign bit
404*3cab2bb3Spatrick		BH = insert(TMP,#DF_EXPBITS+1,#DF_MANTBITS-32)		// clear out hidden bit, sign bit
405*3cab2bb3Spatrick	}
406*3cab2bb3Spatrick	{
407*3cab2bb3Spatrick		if (P_TMP) AH = or(AH,TMP)				// if normal, add back in hidden bit
408*3cab2bb3Spatrick		if (P_TMP2) BH = or(BH,TMP)				// if normal, add back in hidden bit
409*3cab2bb3Spatrick	}
410*3cab2bb3Spatrick	{
411*3cab2bb3Spatrick		QH = add(clb(A),#-DF_EXPBITS)
412*3cab2bb3Spatrick		QL = add(clb(B),#-DF_EXPBITS)
413*3cab2bb3Spatrick		TMP = #1
414*3cab2bb3Spatrick	}
415*3cab2bb3Spatrick	{
416*3cab2bb3Spatrick		EXPA = extractu(EXPA,#DF_EXPBITS,#DF_MANTBITS-32)
417*3cab2bb3Spatrick		EXPB = extractu(EXPB,#DF_EXPBITS,#DF_MANTBITS-32)
418*3cab2bb3Spatrick	}
419*3cab2bb3Spatrick	{
420*3cab2bb3Spatrick		A = asl(A,QH)
421*3cab2bb3Spatrick		B = asl(B,QL)
422*3cab2bb3Spatrick		if (!P_TMP) EXPA = sub(TMP,QH)
423*3cab2bb3Spatrick		if (!P_TMP2) EXPB = sub(TMP,QL)
424*3cab2bb3Spatrick	}	// recreate values needed by resume coke
425*3cab2bb3Spatrick	{
426*3cab2bb3Spatrick		PROD = extractu(B,#SF_MANTBITS,#DF_MANTBITS-SF_MANTBITS)
427*3cab2bb3Spatrick	}
428*3cab2bb3Spatrick	{
429*3cab2bb3Spatrick		SFDEN = or(SFONE,PRODLO)
430*3cab2bb3Spatrick		jump .Ldenorm_continue
431*3cab2bb3Spatrick	}
432*3cab2bb3Spatrick
433*3cab2bb3Spatrick.Ldiv_zero_result:
434*3cab2bb3Spatrick	{
435*3cab2bb3Spatrick		AH = xor(AH,BH)
436*3cab2bb3Spatrick		B = #0
437*3cab2bb3Spatrick	}
438*3cab2bb3Spatrick	{
439*3cab2bb3Spatrick		A = insert(B,#63,#0)
440*3cab2bb3Spatrick		jumpr r31
441*3cab2bb3Spatrick	}
442*3cab2bb3Spatrick.Ldiv_inf_result:
443*3cab2bb3Spatrick	{
444*3cab2bb3Spatrick		p2 = dfclass(B,#DFCLASS_ZERO)
445*3cab2bb3Spatrick		p2 = dfclass(A,#DFCLASS_NONINFINITE)
446*3cab2bb3Spatrick	}
447*3cab2bb3Spatrick	{
448*3cab2bb3Spatrick		TMP = USR
449*3cab2bb3Spatrick		if (!p2) jump 1f
450*3cab2bb3Spatrick		AH = xor(AH,BH)
451*3cab2bb3Spatrick	}
452*3cab2bb3Spatrick	{
453*3cab2bb3Spatrick		TMP = or(TMP,#0x04)		// DBZ
454*3cab2bb3Spatrick	}
455*3cab2bb3Spatrick	{
456*3cab2bb3Spatrick		USR = TMP
457*3cab2bb3Spatrick	}
458*3cab2bb3Spatrick1:
459*3cab2bb3Spatrick	{
460*3cab2bb3Spatrick		B = combine(##0x7ff00000,#0)
461*3cab2bb3Spatrick		p0 = dfcmp.uo(B,B)		// take possible exception
462*3cab2bb3Spatrick	}
463*3cab2bb3Spatrick	{
464*3cab2bb3Spatrick		A = insert(B,#63,#0)
465*3cab2bb3Spatrick		jumpr r31
466*3cab2bb3Spatrick	}
467*3cab2bb3Spatrick.Ldiv_nan:
468*3cab2bb3Spatrick	{
469*3cab2bb3Spatrick		p0 = dfclass(A,#0x10)
470*3cab2bb3Spatrick		p1 = dfclass(B,#0x10)
471*3cab2bb3Spatrick		if (!p0.new) A = B
472*3cab2bb3Spatrick		if (!p1.new) B = A
473*3cab2bb3Spatrick	}
474*3cab2bb3Spatrick	{
475*3cab2bb3Spatrick		QH = convert_df2sf(A)	// get possible invalid exceptions
476*3cab2bb3Spatrick		QL = convert_df2sf(B)
477*3cab2bb3Spatrick	}
478*3cab2bb3Spatrick	{
479*3cab2bb3Spatrick		A = #-1
480*3cab2bb3Spatrick		jumpr r31
481*3cab2bb3Spatrick	}
482*3cab2bb3Spatrick
483*3cab2bb3Spatrick.Ldiv_invalid:
484*3cab2bb3Spatrick	{
485*3cab2bb3Spatrick		TMP = ##0x7f800001
486*3cab2bb3Spatrick	}
487*3cab2bb3Spatrick	{
488*3cab2bb3Spatrick		A = convert_sf2df(TMP)		// get invalid, get DF qNaN
489*3cab2bb3Spatrick		jumpr r31
490*3cab2bb3Spatrick	}
491*3cab2bb3SpatrickEND(__hexagon_divdf3)
492