brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · 1b0d345 Raw
397 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 Multiply10 11#define A r1:012#define AH r113#define AL r014#define B r3:215#define BH r316#define BL r217 18#define EXPA r419#define EXPB r520#define EXPB_A r5:421 22#define ZTMP r7:623#define ZTMPH r724#define ZTMPL r625 26#define ATMP r13:1227#define ATMPH r1328#define ATMPL r1229 30#define BTMP r9:831#define BTMPH r932#define BTMPL r833 34#define ATMP2 r11:1035#define ATMP2H r1136#define ATMP2L r1037 38#define EXPDIFF r1539#define EXTRACTOFF r1440#define EXTRACTAMT r15:1441 42#define TMP r2843 44#define MANTBITS 5245#define HI_MANTBITS 2046#define EXPBITS 1147#define BIAS 102448#define MANTISSA_TO_INT_BIAS 5249#define SR_BIT_INEXACT 550 51#ifndef SR_ROUND_OFF52#define SR_ROUND_OFF 2253#endif54 55#define NORMAL p356#define BIGB p257 58#define Q6_ALIAS(TAG) .global __qdsp_##TAG ; .set __qdsp_##TAG, __hexagon_##TAG59#define FAST_ALIAS(TAG) .global __hexagon_fast_##TAG ; .set __hexagon_fast_##TAG, __hexagon_##TAG60#define FAST2_ALIAS(TAG) .global __hexagon_fast2_##TAG ; .set __hexagon_fast2_##TAG, __hexagon_##TAG61#define END(TAG) .size TAG,.-TAG62 63	.text64	.global __hexagon_adddf365	.global __hexagon_subdf366	.type __hexagon_adddf3, @function67	.type __hexagon_subdf3, @function68 69Q6_ALIAS(adddf3)70FAST_ALIAS(adddf3)71FAST2_ALIAS(adddf3)72Q6_ALIAS(subdf3)73FAST_ALIAS(subdf3)74FAST2_ALIAS(subdf3)75 76	.p2align 577__hexagon_adddf3:78	{79		EXPA = extractu(AH,#EXPBITS,#HI_MANTBITS)80		EXPB = extractu(BH,#EXPBITS,#HI_MANTBITS)81		ATMP = combine(##0x20000000,#0)82	}83	{84		NORMAL = dfclass(A,#2)85		NORMAL = dfclass(B,#2)86		BTMP = ATMP87		BIGB = cmp.gtu(EXPB,EXPA)			// Is B substantially greater than A?88	}89	{90		if (!NORMAL) jump .Ladd_abnormal		// If abnormal, go to special code91		if (BIGB) A = B				// if B >> A, swap A and B92		if (BIGB) B = A				// If B >> A, swap A and B93		if (BIGB) EXPB_A = combine(EXPA,EXPB)	// swap exponents94	}95	{96		ATMP = insert(A,#MANTBITS,#EXPBITS-2)	// Q1.6297		BTMP = insert(B,#MANTBITS,#EXPBITS-2)	// Q1.6298		EXPDIFF = sub(EXPA,EXPB)99		ZTMP = combine(#62,#1)100	}101#undef BIGB102#undef NORMAL103#define B_POS p3104#define A_POS p2105#define NO_STICKIES p1106.Ladd_continue:107	{108		EXPDIFF = min(EXPDIFF,ZTMPH)		// If exponent difference >= ~60,109							// will collapse to sticky bit110		ATMP2 = neg(ATMP)111		A_POS = cmp.gt(AH,#-1)112		EXTRACTOFF = #0113	}114	{115		if (!A_POS) ATMP = ATMP2116		ATMP2 = extractu(BTMP,EXTRACTAMT)117		BTMP = ASR(BTMP,EXPDIFF)118#undef EXTRACTAMT119#undef EXPDIFF120#undef EXTRACTOFF121#define ZERO r15:14122		ZERO = #0123	}124	{125		NO_STICKIES = cmp.eq(ATMP2,ZERO)126		if (!NO_STICKIES.new) BTMPL = or(BTMPL,ZTMPL)127		EXPB = add(EXPA,#-BIAS-60)128		B_POS = cmp.gt(BH,#-1)129	}130	{131		ATMP = add(ATMP,BTMP)			// ADD!!!132		ATMP2 = sub(ATMP,BTMP)			// Negate and ADD --> SUB!!!133		ZTMP = combine(#54,##2045)134	}135	{136		p0 = cmp.gtu(EXPA,ZTMPH)		// must be pretty high in case of large cancellation137		p0 = !cmp.gtu(EXPA,ZTMPL)138		if (!p0.new) jump:nt .Ladd_ovf_unf139		if (!B_POS) ATMP = ATMP2		// if B neg, pick difference140	}141	{142		A = convert_d2df(ATMP)			// Convert to Double Precision, taking care of flags, etc.  So nice!143		p0 = cmp.eq(ATMPH,#0)144		p0 = cmp.eq(ATMPL,#0)145		if (p0.new) jump:nt .Ladd_zero		// or maybe conversion handles zero case correctly?146	}147	{148		AH += asl(EXPB,#HI_MANTBITS)149		jumpr r31150	}151	.falign152__hexagon_subdf3:153	{154		BH = togglebit(BH,#31)155		jump __qdsp_adddf3156	}157 158 159	.falign160.Ladd_zero:161	// True zero, full cancellation162	// +0 unless round towards negative infinity163	{164		TMP = USR165		A = #0166		BH = #1167	}168	{169		TMP = extractu(TMP,#2,#22)170		BH = asl(BH,#31)171	}172	{173		p0 = cmp.eq(TMP,#2)174		if (p0.new) AH = xor(AH,BH)175		jumpr r31176	}177	.falign178.Ladd_ovf_unf:179	// Overflow or Denormal is possible180	// Good news: Underflow flag is not possible!181 182	// ATMP has 2's complement value183	//184	// EXPA has A's exponent, EXPB has EXPA-BIAS-60185	//186	// Convert, extract exponent, add adjustment.187	// If > 2046, overflow188	// If <= 0, denormal189	//190	// Note that we've not done our zero check yet, so do that too191 192	{193		A = convert_d2df(ATMP)194		p0 = cmp.eq(ATMPH,#0)195		p0 = cmp.eq(ATMPL,#0)196		if (p0.new) jump:nt .Ladd_zero197	}198	{199		TMP = extractu(AH,#EXPBITS,#HI_MANTBITS)200		AH += asl(EXPB,#HI_MANTBITS)201	}202	{203		EXPB = add(EXPB,TMP)204		B = combine(##0x00100000,#0)205	}206	{207		p0 = cmp.gt(EXPB,##BIAS+BIAS-2)208		if (p0.new) jump:nt .Ladd_ovf209	}210	{211		p0 = cmp.gt(EXPB,#0)212		if (p0.new) jumpr:t r31213		TMP = sub(#1,EXPB)214	}215	{216		B = insert(A,#MANTBITS,#0)217		A = ATMP218	}219	{220		B = lsr(B,TMP)221	}222	{223		A = insert(B,#63,#0)224		jumpr r31225	}226	.falign227.Ladd_ovf:228	// We get either max finite value or infinity.  Either way, overflow+inexact229	{230		A = ATMP				// 2's complement value231		TMP = USR232		ATMP = combine(##0x7fefffff,#-1)	// positive max finite233	}234	{235		EXPB = extractu(TMP,#2,#SR_ROUND_OFF)	// rounding bits236		TMP = or(TMP,#0x28)			// inexact + overflow237		BTMP = combine(##0x7ff00000,#0)		// positive infinity238	}239	{240		USR = TMP241		EXPB ^= lsr(AH,#31)			// Does sign match rounding?242		TMP = EXPB				// unmodified rounding mode243	}244	{245		p0 = !cmp.eq(TMP,#1)			// If not round-to-zero and246		p0 = !cmp.eq(EXPB,#2)			// Not rounding the other way,247		if (p0.new) ATMP = BTMP			// we should get infinity248	}249	{250		A = insert(ATMP,#63,#0)			// insert inf/maxfinite, leave sign251	}252	{253		p0 = dfcmp.eq(A,A)254		jumpr r31255	}256 257.Ladd_abnormal:258	{259		ATMP = extractu(A,#63,#0)		// strip off sign260		BTMP = extractu(B,#63,#0)		// strip off sign261	}262	{263		p3 = cmp.gtu(ATMP,BTMP)264		if (!p3.new) A = B			// sort values265		if (!p3.new) B = A			// sort values266	}267	{268		// Any NaN --> NaN, possibly raise invalid if sNaN269		p0 = dfclass(A,#0x0f)		// A not NaN?270		if (!p0.new) jump:nt .Linvalid_nan_add271		if (!p3) ATMP = BTMP272		if (!p3) BTMP = ATMP273	}274	{275		// Infinity + non-infinity number is infinity276		// Infinity + infinity --> inf or nan277		p1 = dfclass(A,#0x08)		// A is infinity278		if (p1.new) jump:nt .Linf_add279	}280	{281		p2 = dfclass(B,#0x01)		// B is zero282		if (p2.new) jump:nt .LB_zero	// so return A or special 0+0283		ATMP = #0284	}285	// We are left with adding one or more subnormals286	{287		p0 = dfclass(A,#4)288		if (p0.new) jump:nt .Ladd_two_subnormal289		ATMP = combine(##0x20000000,#0)290	}291	{292		EXPA = extractu(AH,#EXPBITS,#HI_MANTBITS)293		EXPB = #1294		// BTMP already ABS(B)295		BTMP = asl(BTMP,#EXPBITS-2)296	}297#undef ZERO298#define EXTRACTOFF r14299#define EXPDIFF r15300	{301		ATMP = insert(A,#MANTBITS,#EXPBITS-2)302		EXPDIFF = sub(EXPA,EXPB)303		ZTMP = combine(#62,#1)304		jump .Ladd_continue305	}306 307.Ladd_two_subnormal:308	{309		ATMP = extractu(A,#63,#0)310		BTMP = extractu(B,#63,#0)311	}312	{313		ATMP = neg(ATMP)314		BTMP = neg(BTMP)315		p0 = cmp.gt(AH,#-1)316		p1 = cmp.gt(BH,#-1)317	}318	{319		if (p0) ATMP = A320		if (p1) BTMP = B321	}322	{323		ATMP = add(ATMP,BTMP)324	}325	{326		BTMP = neg(ATMP)327		p0 = cmp.gt(ATMPH,#-1)328		B = #0329	}330	{331		if (!p0) A = BTMP332		if (p0) A = ATMP333		BH = ##0x80000000334	}335	{336		if (!p0) AH = or(AH,BH)337		p0 = dfcmp.eq(A,B)338		if (p0.new) jump:nt .Lzero_plus_zero339	}340	{341		jumpr r31342	}343 344.Linvalid_nan_add:345	{346		TMP = convert_df2sf(A)			// will generate invalid if sNaN347		p0 = dfclass(B,#0x0f)			// if B is not NaN348		if (p0.new) B = A 			// make it whatever A is349	}350	{351		BL = convert_df2sf(B)			// will generate invalid if sNaN352		A = #-1353		jumpr r31354	}355	.falign356.LB_zero:357	{358		p0 = dfcmp.eq(ATMP,A)			// is A also zero?359		if (!p0.new) jumpr:t r31		// If not, just return A360	}361	// 0 + 0 is special362	// if equal integral values, they have the same sign, which is fine for all rounding363	// modes.364	// If unequal in sign, we get +0 for all rounding modes except round down365.Lzero_plus_zero:366	{367		p0 = cmp.eq(A,B)368		if (p0.new) jumpr:t r31369	}370	{371		TMP = USR372	}373	{374		TMP = extractu(TMP,#2,#SR_ROUND_OFF)375		A = #0376	}377	{378		p0 = cmp.eq(TMP,#2)379		if (p0.new) AH = ##0x80000000380		jumpr r31381	}382.Linf_add:383	// adding infinities is only OK if they are equal384	{385		p0 = !cmp.eq(AH,BH)			// Do they have different signs386		p0 = dfclass(B,#8)			// And is B also infinite?387		if (!p0.new) jumpr:t r31		// If not, just a normal inf388	}389	{390		BL = ##0x7f800001			// sNAN391	}392	{393		A = convert_sf2df(BL)			// trigger invalid, set NaN394		jumpr r31395	}396END(__hexagon_adddf3)397