1*0b57cec5SDimitry Andric//===----------------------Hexagon builtin routine ------------------------===// 2*0b57cec5SDimitry Andric// 3*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric// 7*0b57cec5SDimitry Andric//===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric/* ==================================================================== * 9*0b57cec5SDimitry Andric 10*0b57cec5SDimitry Andricfast2_QLDOUBLE fast2_ldadd(fast2_QLDOUBLE a,fast2_QLDOUBLE b) { 11*0b57cec5SDimitry Andric fast2_QLDOUBLE c; 12*0b57cec5SDimitry Andric lint manta = a & MANTMASK; 13*0b57cec5SDimitry Andric int expa = Q6_R_sxth_R(a) ; 14*0b57cec5SDimitry Andric lint mantb = b & MANTMASK; 15*0b57cec5SDimitry Andric int expb = Q6_R_sxth_R(b) ; 16*0b57cec5SDimitry Andric int exp, expdiff, j, k, hi, lo, cn; 17*0b57cec5SDimitry Andric lint mant; 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric expdiff = (int) Q6_P_vabsdiffh_PP(a, b); 20*0b57cec5SDimitry Andric expdiff = Q6_R_sxth_R(expdiff) ; 21*0b57cec5SDimitry Andric if (expdiff > 63) { expdiff = 62;} 22*0b57cec5SDimitry Andric if (expa > expb) { 23*0b57cec5SDimitry Andric exp = expa + 1; 24*0b57cec5SDimitry Andric expa = 1; 25*0b57cec5SDimitry Andric expb = expdiff + 1; 26*0b57cec5SDimitry Andric } else { 27*0b57cec5SDimitry Andric exp = expb + 1; 28*0b57cec5SDimitry Andric expb = 1; 29*0b57cec5SDimitry Andric expa = expdiff + 1; 30*0b57cec5SDimitry Andric } 31*0b57cec5SDimitry Andric mant = (manta>>expa) + (mantb>>expb); 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric hi = (int) (mant>>32); 34*0b57cec5SDimitry Andric lo = (int) (mant); 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric k = Q6_R_normamt_R(hi); 37*0b57cec5SDimitry Andric if(hi == 0 || hi == -1) k = 31+Q6_R_normamt_R(lo); 38*0b57cec5SDimitry Andric 39*0b57cec5SDimitry Andric mant = (mant << k); 40*0b57cec5SDimitry Andric cn = (mant == 0x8000000000000000LL); 41*0b57cec5SDimitry Andric exp = exp - k + cn; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric if (mant == 0 || mant == -1) exp = 0x8001; 44*0b57cec5SDimitry Andric c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK); 45*0b57cec5SDimitry Andric return(c); 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric * ==================================================================== */ 48*0b57cec5SDimitry Andric .text 49*0b57cec5SDimitry Andric .global fast2_ldadd_asm 50*0b57cec5SDimitry Andric .type fast2_ldadd_asm, @function 51*0b57cec5SDimitry Andricfast2_ldadd_asm: 52*0b57cec5SDimitry Andric#define manta R1:0 53*0b57cec5SDimitry Andric#define lmanta R1:0 54*0b57cec5SDimitry Andric#define mantb R3:2 55*0b57cec5SDimitry Andric#define lmantb R3:2 56*0b57cec5SDimitry Andric#define expa R4 57*0b57cec5SDimitry Andric#define expb R5 58*0b57cec5SDimitry Andric#define expd R6 59*0b57cec5SDimitry Andric#define exp R8 60*0b57cec5SDimitry Andric#define c63 R9 61*0b57cec5SDimitry Andric#define lmant R1:0 62*0b57cec5SDimitry Andric#define k R4 63*0b57cec5SDimitry Andric#define ce P0 64*0b57cec5SDimitry Andric#define zero R3:2 65*0b57cec5SDimitry Andric .falign 66*0b57cec5SDimitry Andric { 67*0b57cec5SDimitry Andric expa = memw(r29+#8) 68*0b57cec5SDimitry Andric expb = memw(r29+#24) 69*0b57cec5SDimitry Andric r7 = r0 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric { 72*0b57cec5SDimitry Andric expd = sub(expa, expb):sat 73*0b57cec5SDimitry Andric ce = CMP.GT(expa, expb); 74*0b57cec5SDimitry Andric if ( ce.new) exp = add(expa, #1) 75*0b57cec5SDimitry Andric if (!ce.new) exp = add(expb, #1) 76*0b57cec5SDimitry Andric } { 77*0b57cec5SDimitry Andric expd = abs(expd):sat 78*0b57cec5SDimitry Andric if ( ce) expa = #1 79*0b57cec5SDimitry Andric if (!ce) expb = #1 80*0b57cec5SDimitry Andric c63 = #62 81*0b57cec5SDimitry Andric } { 82*0b57cec5SDimitry Andric expd = MIN(expd, c63) 83*0b57cec5SDimitry Andric manta = memd(r29+#0) 84*0b57cec5SDimitry Andric mantb = memd(r29+#16) 85*0b57cec5SDimitry Andric } { 86*0b57cec5SDimitry Andric if (!ce) expa = add(expd, #1) 87*0b57cec5SDimitry Andric if ( ce) expb = add(expd, #1) 88*0b57cec5SDimitry Andric } { 89*0b57cec5SDimitry Andric lmanta = ASR(lmanta, expa) 90*0b57cec5SDimitry Andric lmantb = ASR(lmantb, expb) 91*0b57cec5SDimitry Andric } { 92*0b57cec5SDimitry Andric lmant = add(lmanta, lmantb) 93*0b57cec5SDimitry Andric zero = #0 94*0b57cec5SDimitry Andric } { 95*0b57cec5SDimitry Andric k = clb(lmant) 96*0b57cec5SDimitry Andric c63.L =#0x0001 97*0b57cec5SDimitry Andric } { 98*0b57cec5SDimitry Andric exp -= add(k, #-1) //exp = exp - (k-1) 99*0b57cec5SDimitry Andric k = add(k, #-1) 100*0b57cec5SDimitry Andric p0 = cmp.gt(k, #58) 101*0b57cec5SDimitry Andric c63.H =#0x8000 102*0b57cec5SDimitry Andric } { 103*0b57cec5SDimitry Andric if(!p0)memw(r7+#8) = exp 104*0b57cec5SDimitry Andric lmant = ASL(lmant, k) 105*0b57cec5SDimitry Andric if(p0) jump .Ldenorma 106*0b57cec5SDimitry Andric } { 107*0b57cec5SDimitry Andric memd(r7+#0) = lmant 108*0b57cec5SDimitry Andric jumpr r31 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric.Ldenorma: 111*0b57cec5SDimitry Andric memd(r7+#0) = zero 112*0b57cec5SDimitry Andric { 113*0b57cec5SDimitry Andric memw(r7+#8) = c63 114*0b57cec5SDimitry Andric jumpr r31 115*0b57cec5SDimitry Andric } 116*0b57cec5SDimitry Andric/* =================================================================== * 117*0b57cec5SDimitry Andric fast2_QLDOUBLE fast2_ldsub(fast2_QLDOUBLE a,fast2_QLDOUBLE b) { 118*0b57cec5SDimitry Andric fast2_QLDOUBLE c; 119*0b57cec5SDimitry Andric lint manta = a & MANTMASK; 120*0b57cec5SDimitry Andric int expa = Q6_R_sxth_R(a) ; 121*0b57cec5SDimitry Andric lint mantb = b & MANTMASK; 122*0b57cec5SDimitry Andric int expb = Q6_R_sxth_R(b) ; 123*0b57cec5SDimitry Andric int exp, expdiff, j, k; 124*0b57cec5SDimitry Andric lint mant; 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric expdiff = (int) Q6_P_vabsdiffh_PP(a, b); 127*0b57cec5SDimitry Andric expdiff = Q6_R_sxth_R(expdiff) ; 128*0b57cec5SDimitry Andric if (expdiff > 63) { expdiff = 62;} 129*0b57cec5SDimitry Andric if (expa > expb) { 130*0b57cec5SDimitry Andric exp = expa + 1; 131*0b57cec5SDimitry Andric expa = 1; 132*0b57cec5SDimitry Andric expb = expdiff + 1; 133*0b57cec5SDimitry Andric } else { 134*0b57cec5SDimitry Andric exp = expb + 1; 135*0b57cec5SDimitry Andric expb = 1; 136*0b57cec5SDimitry Andric expa = expdiff + 1; 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric mant = (manta>>expa) - (mantb>>expb); 139*0b57cec5SDimitry Andric k = Q6_R_clb_P(mant)-1; 140*0b57cec5SDimitry Andric mant = (mant << k); 141*0b57cec5SDimitry Andric exp = exp - k; 142*0b57cec5SDimitry Andric if (mant == 0 || mant == -1) exp = 0x8001; 143*0b57cec5SDimitry Andric c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK); 144*0b57cec5SDimitry Andric return(c); 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric * ==================================================================== */ 147*0b57cec5SDimitry Andric .text 148*0b57cec5SDimitry Andric .global fast2_ldsub_asm 149*0b57cec5SDimitry Andric .type fast2_ldsub_asm, @function 150*0b57cec5SDimitry Andricfast2_ldsub_asm: 151*0b57cec5SDimitry Andric#define manta R1:0 152*0b57cec5SDimitry Andric#define lmanta R1:0 153*0b57cec5SDimitry Andric#define mantb R3:2 154*0b57cec5SDimitry Andric#define lmantb R3:2 155*0b57cec5SDimitry Andric#define expa R4 156*0b57cec5SDimitry Andric#define expb R5 157*0b57cec5SDimitry Andric#define expd R6 158*0b57cec5SDimitry Andric#define exp R8 159*0b57cec5SDimitry Andric#define c63 R9 160*0b57cec5SDimitry Andric#define lmant R1:0 161*0b57cec5SDimitry Andric#define k R4 162*0b57cec5SDimitry Andric#define ce P0 163*0b57cec5SDimitry Andric#define zero R3:2 164*0b57cec5SDimitry Andric .falign 165*0b57cec5SDimitry Andric { 166*0b57cec5SDimitry Andric expa = memw(r29+#8) 167*0b57cec5SDimitry Andric expb = memw(r29+#24) 168*0b57cec5SDimitry Andric r7 = r0 169*0b57cec5SDimitry Andric } 170*0b57cec5SDimitry Andric { 171*0b57cec5SDimitry Andric expd = sub(expa, expb):sat 172*0b57cec5SDimitry Andric ce = CMP.GT(expa, expb); 173*0b57cec5SDimitry Andric if ( ce.new) exp = add(expa, #1) 174*0b57cec5SDimitry Andric if (!ce.new) exp = add(expb, #1) 175*0b57cec5SDimitry Andric } { 176*0b57cec5SDimitry Andric expd = abs(expd):sat 177*0b57cec5SDimitry Andric if ( ce) expa = #1 178*0b57cec5SDimitry Andric if (!ce) expb = #1 179*0b57cec5SDimitry Andric c63 = #62 180*0b57cec5SDimitry Andric } { 181*0b57cec5SDimitry Andric expd = min(expd, c63) 182*0b57cec5SDimitry Andric manta = memd(r29+#0) 183*0b57cec5SDimitry Andric mantb = memd(r29+#16) 184*0b57cec5SDimitry Andric } { 185*0b57cec5SDimitry Andric if (!ce) expa = add(expd, #1) 186*0b57cec5SDimitry Andric if ( ce) expb = add(expd, #1) 187*0b57cec5SDimitry Andric } { 188*0b57cec5SDimitry Andric lmanta = ASR(lmanta, expa) 189*0b57cec5SDimitry Andric lmantb = ASR(lmantb, expb) 190*0b57cec5SDimitry Andric } { 191*0b57cec5SDimitry Andric lmant = sub(lmanta, lmantb) 192*0b57cec5SDimitry Andric zero = #0 193*0b57cec5SDimitry Andric } { 194*0b57cec5SDimitry Andric k = clb(lmant) 195*0b57cec5SDimitry Andric c63.L =#0x0001 196*0b57cec5SDimitry Andric } { 197*0b57cec5SDimitry Andric exp -= add(k, #-1) //exp = exp - (k+1) 198*0b57cec5SDimitry Andric k = add(k, #-1) 199*0b57cec5SDimitry Andric p0 = cmp.gt(k, #58) 200*0b57cec5SDimitry Andric c63.H =#0x8000 201*0b57cec5SDimitry Andric } { 202*0b57cec5SDimitry Andric if(!p0)memw(r7+#8) = exp 203*0b57cec5SDimitry Andric lmant = asl(lmant, k) 204*0b57cec5SDimitry Andric if(p0) jump .Ldenorma_s 205*0b57cec5SDimitry Andric } { 206*0b57cec5SDimitry Andric memd(r7+#0) = lmant 207*0b57cec5SDimitry Andric jumpr r31 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric.Ldenorma_s: 210*0b57cec5SDimitry Andric memd(r7+#0) = zero 211*0b57cec5SDimitry Andric { 212*0b57cec5SDimitry Andric memw(r7+#8) = c63 213*0b57cec5SDimitry Andric jumpr r31 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric/* ==================================================================== * 217*0b57cec5SDimitry Andric fast2_QLDOUBLE fast2_ldmpy(fast2_QLDOUBLE a,fast2_QLDOUBLE b) { 218*0b57cec5SDimitry Andric fast2_QLDOUBLE c; 219*0b57cec5SDimitry Andric lint manta = a & MANTMASK; 220*0b57cec5SDimitry Andric int expa = Q6_R_sxth_R(a) ; 221*0b57cec5SDimitry Andric lint mantb = b & MANTMASK; 222*0b57cec5SDimitry Andric int expb = Q6_R_sxth_R(b) ; 223*0b57cec5SDimitry Andric int exp, k; 224*0b57cec5SDimitry Andric lint mant; 225*0b57cec5SDimitry Andric int hia, hib, hi, lo; 226*0b57cec5SDimitry Andric unsigned int loa, lob; 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andric hia = (int)(a >> 32); 229*0b57cec5SDimitry Andric loa = Q6_R_extractu_RII((int)manta, 31, 1); 230*0b57cec5SDimitry Andric hib = (int)(b >> 32); 231*0b57cec5SDimitry Andric lob = Q6_R_extractu_RII((int)mantb, 31, 1); 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric mant = Q6_P_mpy_RR(hia, lob); 234*0b57cec5SDimitry Andric mant = Q6_P_mpyacc_RR(mant,hib, loa); 235*0b57cec5SDimitry Andric mant = (mant >> 30) + (Q6_P_mpy_RR(hia, hib)<<1); 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric hi = (int) (mant>>32); 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric k = Q6_R_normamt_R(hi); 240*0b57cec5SDimitry Andric mant = mant << k; 241*0b57cec5SDimitry Andric exp = expa + expb - k; 242*0b57cec5SDimitry Andric if (mant == 0 || mant == -1) exp = 0x8001; 243*0b57cec5SDimitry Andric c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK); 244*0b57cec5SDimitry Andric return(c); 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric * ==================================================================== */ 247*0b57cec5SDimitry Andric .text 248*0b57cec5SDimitry Andric .global fast2_ldmpy_asm 249*0b57cec5SDimitry Andric .type fast2_ldmpy_asm, @function 250*0b57cec5SDimitry Andricfast2_ldmpy_asm: 251*0b57cec5SDimitry Andric 252*0b57cec5SDimitry Andric#define mantxl_ R9 253*0b57cec5SDimitry Andric#define mantxl R14 254*0b57cec5SDimitry Andric#define mantxh R15 255*0b57cec5SDimitry Andric#define mantx R15:14 256*0b57cec5SDimitry Andric#define mantbl R2 257*0b57cec5SDimitry Andric#define mantbl_ R8 258*0b57cec5SDimitry Andric#define mantbh R3 259*0b57cec5SDimitry Andric#define mantb R3:2 260*0b57cec5SDimitry Andric#define expa R4 261*0b57cec5SDimitry Andric#define expb R5 262*0b57cec5SDimitry Andric#define c8001 R8 263*0b57cec5SDimitry Andric#define mantd R7:6 264*0b57cec5SDimitry Andric#define lmantc R11:10 265*0b57cec5SDimitry Andric#define kp R9 266*0b57cec5SDimitry Andric#define min R13:12 267*0b57cec5SDimitry Andric#define minh R13 268*0b57cec5SDimitry Andric#define max R13:12 269*0b57cec5SDimitry Andric#define maxh R13 270*0b57cec5SDimitry Andric#define ret R0 271*0b57cec5SDimitry Andric 272*0b57cec5SDimitry Andric .falign 273*0b57cec5SDimitry Andric { 274*0b57cec5SDimitry Andric mantx = memd(r29+#0) 275*0b57cec5SDimitry Andric mantb = memd(r29+#16) 276*0b57cec5SDimitry Andric min = #0 277*0b57cec5SDimitry Andric } 278*0b57cec5SDimitry Andric { 279*0b57cec5SDimitry Andric mantbl_= extractu(mantbl, #31, #1) 280*0b57cec5SDimitry Andric mantxl_= extractu(mantxl, #31, #1) 281*0b57cec5SDimitry Andric minh.H = #0x8000 282*0b57cec5SDimitry Andric } 283*0b57cec5SDimitry Andric { 284*0b57cec5SDimitry Andric lmantc = mpy(mantxh, mantbh) 285*0b57cec5SDimitry Andric mantd = mpy(mantxh, mantbl_) 286*0b57cec5SDimitry Andric expa = memw(r29+#8) 287*0b57cec5SDimitry Andric expb = memw(r29+#24) 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric { 290*0b57cec5SDimitry Andric lmantc = add(lmantc, lmantc) 291*0b57cec5SDimitry Andric mantd += mpy(mantbh, mantxl_) 292*0b57cec5SDimitry Andric } 293*0b57cec5SDimitry Andric { 294*0b57cec5SDimitry Andric mantd = asr(mantd, #30) 295*0b57cec5SDimitry Andric c8001.L = #0x0001 296*0b57cec5SDimitry Andric p1 = cmp.eq(mantx, mantb) 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric { 299*0b57cec5SDimitry Andric mantd = add(mantd, lmantc) 300*0b57cec5SDimitry Andric expa= add(expa, expb) 301*0b57cec5SDimitry Andric p2 = cmp.eq(mantb, min) 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric { 304*0b57cec5SDimitry Andric kp = clb(mantd) 305*0b57cec5SDimitry Andric c8001.H = #0x8000 306*0b57cec5SDimitry Andric p1 = and(p1, p2) 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric { 309*0b57cec5SDimitry Andric expa-= add(kp, #-1) 310*0b57cec5SDimitry Andric kp = add(kp, #-1) 311*0b57cec5SDimitry Andric if(p1) jump .Lsat 312*0b57cec5SDimitry Andric } 313*0b57cec5SDimitry Andric { 314*0b57cec5SDimitry Andric mantd = asl(mantd, kp) 315*0b57cec5SDimitry Andric memw(ret+#8) = expa 316*0b57cec5SDimitry Andric p0 = cmp.gt(kp, #58) 317*0b57cec5SDimitry Andric if(p0.new) jump:NT .Ldenorm //rarely happens 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric { 320*0b57cec5SDimitry Andric memd(ret+#0) = mantd 321*0b57cec5SDimitry Andric jumpr r31 322*0b57cec5SDimitry Andric } 323*0b57cec5SDimitry Andric.Lsat: 324*0b57cec5SDimitry Andric { 325*0b57cec5SDimitry Andric max = #0 326*0b57cec5SDimitry Andric expa+= add(kp, #1) 327*0b57cec5SDimitry Andric } 328*0b57cec5SDimitry Andric { 329*0b57cec5SDimitry Andric maxh.H = #0x4000 330*0b57cec5SDimitry Andric memw(ret+#8) = expa 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric { 333*0b57cec5SDimitry Andric memd(ret+#0) = max 334*0b57cec5SDimitry Andric jumpr r31 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric.Ldenorm: 337*0b57cec5SDimitry Andric { 338*0b57cec5SDimitry Andric memw(ret+#8) = c8001 339*0b57cec5SDimitry Andric mantx = #0 340*0b57cec5SDimitry Andric } 341*0b57cec5SDimitry Andric { 342*0b57cec5SDimitry Andric memd(ret+#0) = mantx 343*0b57cec5SDimitry Andric jumpr r31 344*0b57cec5SDimitry Andric } 345