xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/builtins/hexagon/fastmath2_ldlib_asm.S (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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