1 //===----------------------Hexagon builtin routine ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /* Double Precision Multiply */
40 #define EXTRACTOFF r14
41 #define EXTRACTAMT r15:14
46 #define HI_MANTBITS 20
49 #define MANTISSA_TO_INT_BIAS 52
50 #define SR_BIT_INEXACT 5
53 #define SR_ROUND_OFF 22
59 #define Q6_ALIAS(TAG) .global __qdsp_##TAG ; .set __qdsp_##TAG, __hexagon_##TAG
60 #define FAST_ALIAS(TAG) .global __hexagon_fast_##TAG ; .set __hexagon_fast_##TAG, __hexagon_##TAG
61 #define FAST2_ALIAS(TAG) .global __hexagon_fast2_##TAG ; .set __hexagon_fast2_##TAG, __hexagon_##TAG
62 #define END(TAG) .size TAG,.-TAG
65 .global __hexagon_adddf3
66 .global __hexagon_subdf3
67 .type __hexagon_adddf3, @function
68 .type __hexagon_subdf3, @function
80 EXPA = extractu(AH,#EXPBITS,#HI_MANTBITS)
81 EXPB = extractu(BH,#EXPBITS,#HI_MANTBITS)
82 ATMP = combine(##0x20000000,#0)
85 NORMAL = dfclass(A,#2)
86 NORMAL = dfclass(B,#2)
88 BIGB = cmp.gtu(EXPB,EXPA) // Is B substantially greater than A?
91 if (!NORMAL) jump .Ladd_abnormal // If abnormal, go to special code
92 if (BIGB) A = B // if B >> A, swap A and B
93 if (BIGB) B = A // If B >> A, swap A and B
94 if (BIGB) EXPB_A = combine(EXPA,EXPB) // swap exponents
97 ATMP = insert(A,#MANTBITS,#EXPBITS-2) // Q1.62
98 BTMP = insert(B,#MANTBITS,#EXPBITS-2) // Q1.62
99 EXPDIFF = sub(EXPA,EXPB)
100 ZTMP = combine(#62,#1)
106 #define NO_STICKIES p1
109 EXPDIFF = min(EXPDIFF,ZTMPH) // If exponent difference >= ~60,
110 // will collapse to sticky bit
112 A_POS = cmp.gt(AH,#-1)
116 if (!A_POS) ATMP = ATMP2
117 ATMP2 = extractu(BTMP,EXTRACTAMT)
118 BTMP = ASR(BTMP,EXPDIFF)
126 NO_STICKIES = cmp.eq(ATMP2,ZERO)
127 if (!NO_STICKIES.new) BTMPL = or(BTMPL,ZTMPL)
128 EXPB = add(EXPA,#-BIAS-60)
129 B_POS = cmp.gt(BH,#-1)
132 ATMP = add(ATMP,BTMP) // ADD!!!
133 ATMP2 = sub(ATMP,BTMP) // Negate and ADD --> SUB!!!
134 ZTMP = combine(#54,##2045)
137 p0 = cmp.gtu(EXPA,ZTMPH) // must be pretty high in case of large cancellation
138 p0 = !cmp.gtu(EXPA,ZTMPL)
139 if (!p0.new) jump:nt .Ladd_ovf_unf
140 if (!B_POS) ATMP = ATMP2 // if B neg, pick difference
143 A = convert_d2df(ATMP) // Convert to Double Precision, taking care of flags, etc. So nice!
144 p0 = cmp.eq(ATMPH,#0)
145 p0 = cmp.eq(ATMPL,#0)
146 if (p0.new) jump:nt .Ladd_zero // or maybe conversion handles zero case correctly?
149 AH += asl(EXPB,#HI_MANTBITS)
155 BH = togglebit(BH,#31)
162 // True zero, full cancellation
163 // +0 unless round towards negative infinity
170 TMP = extractu(TMP,#2,#22)
175 if (p0.new) AH = xor(AH,BH)
180 // Overflow or Denormal is possible
181 // Good news: Underflow flag is not possible!
183 * ATMP has 2's complement value
185 * EXPA has A's exponent, EXPB has EXPA-BIAS-60
187 * Convert, extract exponent, add adjustment.
188 * If > 2046, overflow
191 * Note that we've not done our zero check yet, so do that too
195 A = convert_d2df(ATMP)
196 p0 = cmp.eq(ATMPH,#0)
197 p0 = cmp.eq(ATMPL,#0)
198 if (p0.new) jump:nt .Ladd_zero
201 TMP = extractu(AH,#EXPBITS,#HI_MANTBITS)
202 AH += asl(EXPB,#HI_MANTBITS)
206 B = combine(##0x00100000,#0)
209 p0 = cmp.gt(EXPB,##BIAS+BIAS-2)
210 if (p0.new) jump:nt .Ladd_ovf
214 if (p0.new) jumpr:t r31
218 B = insert(A,#MANTBITS,#0)
230 // We get either max finite value or infinity. Either way, overflow+inexact
232 A = ATMP // 2's complement value
234 ATMP = combine(##0x7fefffff,#-1) // positive max finite
237 EXPB = extractu(TMP,#2,#SR_ROUND_OFF) // rounding bits
238 TMP = or(TMP,#0x28) // inexact + overflow
239 BTMP = combine(##0x7ff00000,#0) // positive infinity
243 EXPB ^= lsr(AH,#31) // Does sign match rounding?
244 TMP = EXPB // unmodified rounding mode
247 p0 = !cmp.eq(TMP,#1) // If not round-to-zero and
248 p0 = !cmp.eq(EXPB,#2) // Not rounding the other way,
249 if (p0.new) ATMP = BTMP // we should get infinity
252 A = insert(ATMP,#63,#0) // insert inf/maxfinite, leave sign
261 ATMP = extractu(A,#63,#0) // strip off sign
262 BTMP = extractu(B,#63,#0) // strip off sign
265 p3 = cmp.gtu(ATMP,BTMP)
266 if (!p3.new) A = B // sort values
267 if (!p3.new) B = A // sort values
270 // Any NaN --> NaN, possibly raise invalid if sNaN
271 p0 = dfclass(A,#0x0f) // A not NaN?
272 if (!p0.new) jump:nt .Linvalid_nan_add
277 // Infinity + non-infinity number is infinity
278 // Infinity + infinity --> inf or nan
279 p1 = dfclass(A,#0x08) // A is infinity
280 if (p1.new) jump:nt .Linf_add
283 p2 = dfclass(B,#0x01) // B is zero
284 if (p2.new) jump:nt .LB_zero // so return A or special 0+0
287 // We are left with adding one or more subnormals
290 if (p0.new) jump:nt .Ladd_two_subnormal
291 ATMP = combine(##0x20000000,#0)
294 EXPA = extractu(AH,#EXPBITS,#HI_MANTBITS)
296 // BTMP already ABS(B)
297 BTMP = asl(BTMP,#EXPBITS-2)
300 #define EXTRACTOFF r14
303 ATMP = insert(A,#MANTBITS,#EXPBITS-2)
304 EXPDIFF = sub(EXPA,EXPB)
305 ZTMP = combine(#62,#1)
311 ATMP = extractu(A,#63,#0)
312 BTMP = extractu(B,#63,#0)
325 ATMP = add(ATMP,BTMP)
329 p0 = cmp.gt(ATMPH,#-1)
338 if (!p0) AH = or(AH,BH)
340 if (p0.new) jump:nt .Lzero_plus_zero
348 TMP = convert_df2sf(A) // will generate invalid if sNaN
349 p0 = dfclass(B,#0x0f) // if B is not NaN
350 if (p0.new) B = A // make it whatever A is
353 BL = convert_df2sf(B) // will generate invalid if sNaN
360 p0 = dfcmp.eq(ATMP,A) // is A also zero?
361 if (!p0.new) jumpr:t r31 // If not, just return A
364 // if equal integral values, they have the same sign, which is fine for all rounding
366 // If unequal in sign, we get +0 for all rounding modes except round down
370 if (p0.new) jumpr:t r31
376 TMP = extractu(TMP,#2,#SR_ROUND_OFF)
381 if (p0.new) AH = ##0x80000000
385 // adding infinities is only OK if they are equal
387 p0 = !cmp.eq(AH,BH) // Do they have different signs
388 p0 = dfclass(B,#8) // And is B also infinite?
389 if (!p0.new) jumpr:t r31 // If not, just a normal inf
392 BL = ##0x7f800001 // sNAN
395 A = convert_sf2df(BL) // trigger invalid, set NaN
398 END(__hexagon_adddf3)