brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.6 KiB · 202965e Raw
492 lines · plain
1//===----------------------Hexagon builtin routine ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// Double Precision Divide10 11#define A r1:012#define AH r113#define AL r014 15#define B r3:216#define BH r317#define BL r218 19#define Q r5:420#define QH r521#define QL r422 23#define PROD r7:624#define PRODHI r725#define PRODLO r626 27#define SFONE r828#define SFDEN r929#define SFERROR r1030#define SFRECIP r1131 32#define EXPBA r13:1233#define EXPB r1334#define EXPA r1235 36#define REMSUB2 r15:1437 38 39 40#define SIGN r2841 42#define Q_POSITIVE p343#define NORMAL p244#define NO_OVF_UNF p145#define P_TMP p046 47#define RECIPEST_SHIFT 348#define QADJ 6149 50#define DFCLASS_NORMAL 0x0251#define DFCLASS_NUMBER 0x0F52#define DFCLASS_INFINITE 0x0853#define DFCLASS_ZERO 0x0154#define DFCLASS_NONZERO (DFCLASS_NUMBER ^ DFCLASS_ZERO)55#define DFCLASS_NONINFINITE (DFCLASS_NUMBER ^ DFCLASS_INFINITE)56 57#define DF_MANTBITS 5258#define DF_EXPBITS 1159#define SF_MANTBITS 2360#define SF_EXPBITS 861#define DF_BIAS 0x3ff62 63#define SR_ROUND_OFF 2264 65#define Q6_ALIAS(TAG) .global __qdsp_##TAG ; .set __qdsp_##TAG, __hexagon_##TAG66#define FAST_ALIAS(TAG) .global __hexagon_fast_##TAG ; .set __hexagon_fast_##TAG, __hexagon_##TAG67#define FAST2_ALIAS(TAG) .global __hexagon_fast2_##TAG ; .set __hexagon_fast2_##TAG, __hexagon_##TAG68#define END(TAG) .size TAG,.-TAG69 70	.text71	.global __hexagon_divdf372	.type __hexagon_divdf3,@function73	Q6_ALIAS(divdf3)74        FAST_ALIAS(divdf3)75        FAST2_ALIAS(divdf3)76	.p2align 577__hexagon_divdf3:78	{79		NORMAL = dfclass(A,#DFCLASS_NORMAL)80		NORMAL = dfclass(B,#DFCLASS_NORMAL)81		EXPBA = combine(BH,AH)82		SIGN = xor(AH,BH)83	}84#undef A85#undef AH86#undef AL87#undef B88#undef BH89#undef BL90#define REM r1:091#define REMHI r192#define REMLO r093#define DENOM r3:294#define DENOMHI r395#define DENOMLO r296	{97		if (!NORMAL) jump .Ldiv_abnormal98		PROD = extractu(DENOM,#SF_MANTBITS,#DF_MANTBITS-SF_MANTBITS)99		SFONE = ##0x3f800001100	}101	{102		SFDEN = or(SFONE,PRODLO)103		EXPB = extractu(EXPB,#DF_EXPBITS,#DF_MANTBITS-32)104		EXPA = extractu(EXPA,#DF_EXPBITS,#DF_MANTBITS-32)105		Q_POSITIVE = cmp.gt(SIGN,#-1)106	}107#undef SIGN108#define ONE r28109.Ldenorm_continue:110	{111		SFRECIP,P_TMP = sfrecipa(SFONE,SFDEN)112		SFERROR = and(SFONE,#-2)113		ONE = #1114		EXPA = sub(EXPA,EXPB)115	}116#undef EXPB117#define RECIPEST r13118	{119		SFERROR -= sfmpy(SFRECIP,SFDEN):lib120		REMHI = insert(ONE,#DF_EXPBITS+1,#DF_MANTBITS-32)121		RECIPEST = ##0x00800000 << RECIPEST_SHIFT122	}123	{124		SFRECIP += sfmpy(SFRECIP,SFERROR):lib125		DENOMHI = insert(ONE,#DF_EXPBITS+1,#DF_MANTBITS-32)126		SFERROR = and(SFONE,#-2)127	}128	{129		SFERROR -= sfmpy(SFRECIP,SFDEN):lib130		QH = #-DF_BIAS+1131		QL = #DF_BIAS-1132	}133	{134		SFRECIP += sfmpy(SFRECIP,SFERROR):lib135		NO_OVF_UNF = cmp.gt(EXPA,QH)136		NO_OVF_UNF = !cmp.gt(EXPA,QL)137	}138	{139		RECIPEST = insert(SFRECIP,#SF_MANTBITS,#RECIPEST_SHIFT)140		Q = #0141		EXPA = add(EXPA,#-QADJ)142	}143#undef SFERROR144#undef SFRECIP145#define TMP r10146#define TMP1 r11147	{148		RECIPEST = add(RECIPEST,#((-3) << RECIPEST_SHIFT))149	}150 151#define DIV_ITER1B(QSHIFTINSN,QSHIFT,REMSHIFT,EXTRA) \152	{ \153		PROD = mpyu(RECIPEST,REMHI); \154		REM = asl(REM,# ## ( REMSHIFT )); \155	}; \156	{ \157		PRODLO = # ## 0; \158		REM -= mpyu(PRODHI,DENOMLO); \159		REMSUB2 = mpyu(PRODHI,DENOMHI); \160	}; \161	{ \162		Q += QSHIFTINSN(PROD, # ## ( QSHIFT )); \163		REM -= asl(REMSUB2, # ## 32); \164		EXTRA \165	}166 167 168	DIV_ITER1B(ASL,14,15,)169	DIV_ITER1B(ASR,1,15,)170	DIV_ITER1B(ASR,16,15,)171	DIV_ITER1B(ASR,31,15,PROD=# ( 0 );)172 173#undef REMSUB2174#define TMPPAIR r15:14175#define TMPPAIRHI r15176#define TMPPAIRLO r14177#undef RECIPEST178#define EXPB r13179	{180		// compare or sub with carry181		TMPPAIR = sub(REM,DENOM)182		P_TMP = cmp.gtu(DENOM,REM)183		// set up amt to add to q184		if (!P_TMP.new) PRODLO  = #2185	}186	{187		Q = add(Q,PROD)188		if (!P_TMP) REM = TMPPAIR189		TMPPAIR = #0190	}191	{192		P_TMP = cmp.eq(REM,TMPPAIR)193		if (!P_TMP.new) QL = or(QL,ONE)194	}195	{196		PROD = neg(Q)197	}198	{199		if (!Q_POSITIVE) Q = PROD200	}201#undef REM202#undef REMHI203#undef REMLO204#undef DENOM205#undef DENOMLO206#undef DENOMHI207#define A r1:0208#define AH r1209#define AL r0210#define B r3:2211#define BH r3212#define BL r2213	{214		A = convert_d2df(Q)215		if (!NO_OVF_UNF) jump .Ldiv_ovf_unf216	}217	{218		AH += asl(EXPA,#DF_MANTBITS-32)219		jumpr r31220	}221 222.Ldiv_ovf_unf:223	{224		AH += asl(EXPA,#DF_MANTBITS-32)225		EXPB = extractu(AH,#DF_EXPBITS,#DF_MANTBITS-32)226	}227	{228		PROD = abs(Q)229		EXPA = add(EXPA,EXPB)230	}231	{232		P_TMP = cmp.gt(EXPA,##DF_BIAS+DF_BIAS)		// overflow233		if (P_TMP.new) jump:nt .Ldiv_ovf234	}235	{236		P_TMP = cmp.gt(EXPA,#0)237		if (P_TMP.new) jump:nt .Lpossible_unf		// round up to normal possible...238	}239	// Underflow240	// We know what the infinite range exponent should be (EXPA)241	// Q is 2's complement, PROD is abs(Q)242	// Normalize Q, shift right, add a high bit, convert, change exponent243 244#define FUDGE1 7	// how much to shift right245#define FUDGE2 4	// how many guard/round to keep at lsbs246 247	{248		EXPB = add(clb(PROD),#-1)			// doesn't need to be added in since249		EXPA = sub(#FUDGE1,EXPA)			// we extract post-converted exponent250		TMP = USR251		TMP1 = #63252	}253	{254		EXPB = min(EXPA,TMP1)255		TMP1 = or(TMP,#0x030)256		PROD = asl(PROD,EXPB)257		EXPA = #0258	}259	{260		TMPPAIR = extractu(PROD,EXPBA)				// bits that will get shifted out261		PROD = lsr(PROD,EXPB)					// shift out bits262		B = #1263	}264	{265		P_TMP = cmp.gtu(B,TMPPAIR)266		if (!P_TMP.new) PRODLO = or(BL,PRODLO)267		PRODHI = setbit(PRODHI,#DF_MANTBITS-32+FUDGE2)268	}269	{270		Q = neg(PROD)271		P_TMP = bitsclr(PRODLO,#(1<<FUDGE2)-1)272		if (!P_TMP.new) TMP = TMP1273	}274	{275		USR = TMP276		if (Q_POSITIVE) Q = PROD277		TMP = #-DF_BIAS-(DF_MANTBITS+FUDGE2)278	}279	{280		A = convert_d2df(Q)281	}282	{283		AH += asl(TMP,#DF_MANTBITS-32)284		jumpr r31285	}286 287 288.Lpossible_unf:289	// If upper parts of Q were all F's, but abs(A) == 0x00100000_00000000, we rounded up to min_normal290	// The answer is correct, but we need to raise Underflow291	{292		B = extractu(A,#63,#0)293		TMPPAIR = combine(##0x00100000,#0)		// min normal294		TMP = #0x7FFF295	}296	{297		P_TMP = dfcmp.eq(TMPPAIR,B)		// Is everything zero in the rounded value...298		P_TMP = bitsset(PRODHI,TMP)		// but a bunch of bits set in the unrounded abs(quotient)?299	}300 301#if (__HEXAGON_ARCH__ == 60)302		TMP = USR		// If not, just return303		if (!P_TMP) jumpr r31   // Else, we want to set Unf+Inexact304					// Note that inexact is already set...305#else306	{307		if (!P_TMP) jumpr r31			// If not, just return308		TMP = USR				// Else, we want to set Unf+Inexact309	}						// Note that inexact is already set...310#endif311	{312		TMP = or(TMP,#0x30)313	}314	{315		USR = TMP316	}317	{318		p0 = dfcmp.eq(A,A)319		jumpr r31320	}321 322.Ldiv_ovf:323 324	// Raise Overflow, and choose the correct overflow value (saturated normal or infinity)325 326	{327		TMP = USR328		B = combine(##0x7fefffff,#-1)329		AH = mux(Q_POSITIVE,#0,#-1)330	}331	{332		PROD = combine(##0x7ff00000,#0)333		QH = extractu(TMP,#2,#SR_ROUND_OFF)334		TMP = or(TMP,#0x28)335	}336	{337		USR = TMP338		QH ^= lsr(AH,#31)339		QL = QH340	}341	{342		p0 = !cmp.eq(QL,#1)		// if not round-to-zero343		p0 = !cmp.eq(QH,#2)		// and not rounding the other way344		if (p0.new) B = PROD		// go to inf345		p0 = dfcmp.eq(B,B)		// get exceptions346	}347	{348		A = insert(B,#63,#0)349		jumpr r31350	}351 352#undef ONE353#define SIGN r28354#undef NORMAL355#undef NO_OVF_UNF356#define P_INF p1357#define P_ZERO p2358.Ldiv_abnormal:359	{360		P_TMP = dfclass(A,#DFCLASS_NUMBER)361		P_TMP = dfclass(B,#DFCLASS_NUMBER)362		Q_POSITIVE = cmp.gt(SIGN,#-1)363	}364	{365		P_INF = dfclass(A,#DFCLASS_INFINITE)366		P_INF = dfclass(B,#DFCLASS_INFINITE)367	}368	{369		P_ZERO = dfclass(A,#DFCLASS_ZERO)370		P_ZERO = dfclass(B,#DFCLASS_ZERO)371	}372	{373		if (!P_TMP) jump .Ldiv_nan374		if (P_INF) jump .Ldiv_invalid375	}376	{377		if (P_ZERO) jump .Ldiv_invalid378	}379	{380		P_ZERO = dfclass(A,#DFCLASS_NONZERO)		// nonzero381		P_ZERO = dfclass(B,#DFCLASS_NONINFINITE)	// non-infinite382	}383	{384		P_INF = dfclass(A,#DFCLASS_NONINFINITE)	// non-infinite385		P_INF = dfclass(B,#DFCLASS_NONZERO)	// nonzero386	}387	{388		if (!P_ZERO) jump .Ldiv_zero_result389		if (!P_INF) jump .Ldiv_inf_result390	}391	// Now we've narrowed it down to (de)normal / (de)normal392	// Set up A/EXPA B/EXPB and go back393#undef P_ZERO394#undef P_INF395#define P_TMP2 p1396	{397		P_TMP = dfclass(A,#DFCLASS_NORMAL)398		P_TMP2 = dfclass(B,#DFCLASS_NORMAL)399		TMP = ##0x00100000400	}401	{402		EXPBA = combine(BH,AH)403		AH = insert(TMP,#DF_EXPBITS+1,#DF_MANTBITS-32)		// clear out hidden bit, sign bit404		BH = insert(TMP,#DF_EXPBITS+1,#DF_MANTBITS-32)		// clear out hidden bit, sign bit405	}406	{407		if (P_TMP) AH = or(AH,TMP)				// if normal, add back in hidden bit408		if (P_TMP2) BH = or(BH,TMP)				// if normal, add back in hidden bit409	}410	{411		QH = add(clb(A),#-DF_EXPBITS)412		QL = add(clb(B),#-DF_EXPBITS)413		TMP = #1414	}415	{416		EXPA = extractu(EXPA,#DF_EXPBITS,#DF_MANTBITS-32)417		EXPB = extractu(EXPB,#DF_EXPBITS,#DF_MANTBITS-32)418	}419	{420		A = asl(A,QH)421		B = asl(B,QL)422		if (!P_TMP) EXPA = sub(TMP,QH)423		if (!P_TMP2) EXPB = sub(TMP,QL)424	}	// recreate values needed by resume coke425	{426		PROD = extractu(B,#SF_MANTBITS,#DF_MANTBITS-SF_MANTBITS)427	}428	{429		SFDEN = or(SFONE,PRODLO)430		jump .Ldenorm_continue431	}432 433.Ldiv_zero_result:434	{435		AH = xor(AH,BH)436		B = #0437	}438	{439		A = insert(B,#63,#0)440		jumpr r31441	}442.Ldiv_inf_result:443	{444		p2 = dfclass(B,#DFCLASS_ZERO)445		p2 = dfclass(A,#DFCLASS_NONINFINITE)446	}447	{448		TMP = USR449		if (!p2) jump 1f450		AH = xor(AH,BH)451	}452	{453		TMP = or(TMP,#0x04)		// DBZ454	}455	{456		USR = TMP457	}4581:459	{460		B = combine(##0x7ff00000,#0)461		p0 = dfcmp.uo(B,B)		// take possible exception462	}463	{464		A = insert(B,#63,#0)465		jumpr r31466	}467.Ldiv_nan:468	{469		p0 = dfclass(A,#0x10)470		p1 = dfclass(B,#0x10)471		if (!p0.new) A = B472		if (!p1.new) B = A473	}474	{475		QH = convert_df2sf(A)	// get possible invalid exceptions476		QL = convert_df2sf(B)477	}478	{479		A = #-1480		jumpr r31481	}482 483.Ldiv_invalid:484	{485		TMP = ##0x7f800001486	}487	{488		A = convert_sf2df(TMP)		// get invalid, get DF qNaN489		jumpr r31490	}491END(__hexagon_divdf3)492