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