1336817Sdim//===----------------------Hexagon builtin routine ------------------------===//
2336817Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6336817Sdim//
7336817Sdim//===----------------------------------------------------------------------===//
8336817Sdim/* ==================================================================== *
9336817Sdim
10336817Sdimfast2_QLDOUBLE fast2_ldadd(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
11336817Sdim      fast2_QLDOUBLE c;
12336817Sdim      lint manta = a & MANTMASK;
13336817Sdim      int  expa  = Q6_R_sxth_R(a) ;
14336817Sdim      lint mantb = b & MANTMASK;
15336817Sdim      int  expb  = Q6_R_sxth_R(b) ;
16336817Sdim      int  exp, expdiff, j, k, hi, lo, cn;
17336817Sdim      lint mant;
18336817Sdim
19336817Sdim        expdiff = (int) Q6_P_vabsdiffh_PP(a, b);
20336817Sdim        expdiff = Q6_R_sxth_R(expdiff) ;
21336817Sdim        if (expdiff > 63) { expdiff = 62;}
22336817Sdim        if (expa > expb) {
23336817Sdim          exp = expa + 1;
24336817Sdim          expa = 1;
25336817Sdim          expb = expdiff + 1;
26336817Sdim        } else {
27336817Sdim          exp = expb + 1;
28336817Sdim          expb = 1;
29336817Sdim          expa = expdiff + 1;
30336817Sdim        }
31336817Sdim        mant = (manta>>expa) + (mantb>>expb);
32336817Sdim
33336817Sdim        hi = (int) (mant>>32);
34336817Sdim        lo = (int) (mant);
35336817Sdim
36336817Sdim        k =  Q6_R_normamt_R(hi);
37336817Sdim        if(hi == 0 || hi == -1) k = 31+Q6_R_normamt_R(lo);
38336817Sdim
39336817Sdim        mant = (mant << k);
40336817Sdim        cn  = (mant == 0x8000000000000000LL);
41336817Sdim        exp = exp - k + cn;
42336817Sdim
43336817Sdim        if (mant ==  0 || mant == -1)  exp = 0x8001;
44336817Sdim        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
45336817Sdim      return(c);
46336817Sdim }
47336817Sdim * ==================================================================== */
48336817Sdim        .text
49336817Sdim        .global fast2_ldadd_asm
50336817Sdim        .type fast2_ldadd_asm, @function
51336817Sdimfast2_ldadd_asm:
52336817Sdim#define manta      R1:0
53336817Sdim#define lmanta     R1:0
54336817Sdim#define mantb      R3:2
55336817Sdim#define lmantb     R3:2
56336817Sdim#define expa       R4
57336817Sdim#define expb       R5
58336817Sdim#define expd       R6
59336817Sdim#define exp        R8
60336817Sdim#define c63        R9
61336817Sdim#define lmant      R1:0
62336817Sdim#define k          R4
63336817Sdim#define ce         P0
64336817Sdim#define zero       R3:2
65336817Sdim        .falign
66336817Sdim      {
67336817Sdim        expa = memw(r29+#8)
68336817Sdim        expb = memw(r29+#24)
69336817Sdim        r7 = r0
70336817Sdim      }
71336817Sdim      {
72336817Sdim        expd = sub(expa, expb):sat
73336817Sdim        ce = CMP.GT(expa, expb);
74336817Sdim        if ( ce.new) exp = add(expa, #1)
75336817Sdim        if (!ce.new) exp = add(expb, #1)
76336817Sdim      } {
77336817Sdim        expd = abs(expd):sat
78336817Sdim        if ( ce) expa = #1
79336817Sdim        if (!ce) expb = #1
80336817Sdim        c63 = #62
81336817Sdim      } {
82336817Sdim        expd = MIN(expd, c63)
83336817Sdim        manta = memd(r29+#0)
84336817Sdim        mantb = memd(r29+#16)
85336817Sdim      } {
86336817Sdim        if (!ce) expa = add(expd, #1)
87336817Sdim        if ( ce) expb = add(expd, #1)
88336817Sdim      } {
89336817Sdim        lmanta = ASR(lmanta, expa)
90336817Sdim        lmantb = ASR(lmantb, expb)
91336817Sdim      } {
92336817Sdim        lmant = add(lmanta, lmantb)
93336817Sdim        zero = #0
94336817Sdim      } {
95336817Sdim        k  = clb(lmant)
96336817Sdim        c63.L =#0x0001
97336817Sdim      } {
98336817Sdim        exp -= add(k, #-1)  //exp =  exp - (k-1)
99336817Sdim        k = add(k, #-1)
100336817Sdim        p0 = cmp.gt(k, #58)
101336817Sdim        c63.H =#0x8000
102336817Sdim      } {
103336817Sdim        if(!p0)memw(r7+#8) = exp
104336817Sdim        lmant = ASL(lmant, k)
105336817Sdim        if(p0) jump .Ldenorma
106336817Sdim      } {
107336817Sdim        memd(r7+#0) = lmant
108336817Sdim        jumpr  r31
109336817Sdim      }
110336817Sdim.Ldenorma:
111336817Sdim        memd(r7+#0) = zero
112336817Sdim      {
113336817Sdim        memw(r7+#8) = c63
114336817Sdim        jumpr  r31
115336817Sdim      }
116336817Sdim/* =================================================================== *
117336817Sdim fast2_QLDOUBLE fast2_ldsub(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
118336817Sdim      fast2_QLDOUBLE c;
119336817Sdim      lint manta = a & MANTMASK;
120336817Sdim      int  expa  = Q6_R_sxth_R(a) ;
121336817Sdim      lint mantb = b & MANTMASK;
122336817Sdim      int  expb  = Q6_R_sxth_R(b) ;
123336817Sdim      int  exp, expdiff, j, k;
124336817Sdim      lint mant;
125336817Sdim
126336817Sdim        expdiff = (int) Q6_P_vabsdiffh_PP(a, b);
127336817Sdim        expdiff = Q6_R_sxth_R(expdiff) ;
128336817Sdim        if (expdiff > 63) { expdiff = 62;}
129336817Sdim        if (expa > expb) {
130336817Sdim          exp = expa + 1;
131336817Sdim          expa = 1;
132336817Sdim          expb = expdiff + 1;
133336817Sdim        } else {
134336817Sdim          exp = expb + 1;
135336817Sdim          expb = 1;
136336817Sdim          expa = expdiff + 1;
137336817Sdim        }
138336817Sdim        mant = (manta>>expa) - (mantb>>expb);
139336817Sdim        k =  Q6_R_clb_P(mant)-1;
140336817Sdim        mant = (mant << k);
141336817Sdim        exp = exp - k;
142336817Sdim        if (mant ==  0 || mant == -1)  exp = 0x8001;
143336817Sdim        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
144336817Sdim      return(c);
145336817Sdim }
146336817Sdim * ==================================================================== */
147336817Sdim        .text
148336817Sdim        .global fast2_ldsub_asm
149336817Sdim        .type fast2_ldsub_asm, @function
150336817Sdimfast2_ldsub_asm:
151336817Sdim#define manta      R1:0
152336817Sdim#define lmanta     R1:0
153336817Sdim#define mantb      R3:2
154336817Sdim#define lmantb     R3:2
155336817Sdim#define expa       R4
156336817Sdim#define expb       R5
157336817Sdim#define expd       R6
158336817Sdim#define exp        R8
159336817Sdim#define c63        R9
160336817Sdim#define lmant      R1:0
161336817Sdim#define k          R4
162336817Sdim#define ce         P0
163336817Sdim#define zero       R3:2
164336817Sdim        .falign
165336817Sdim      {
166336817Sdim        expa = memw(r29+#8)
167336817Sdim        expb = memw(r29+#24)
168336817Sdim        r7 = r0
169336817Sdim      }
170336817Sdim      {
171336817Sdim        expd = sub(expa, expb):sat
172336817Sdim        ce = CMP.GT(expa, expb);
173336817Sdim        if ( ce.new) exp = add(expa, #1)
174336817Sdim        if (!ce.new) exp = add(expb, #1)
175336817Sdim      } {
176336817Sdim        expd = abs(expd):sat
177336817Sdim        if ( ce) expa = #1
178336817Sdim        if (!ce) expb = #1
179336817Sdim        c63 = #62
180336817Sdim      } {
181336817Sdim        expd = min(expd, c63)
182336817Sdim        manta = memd(r29+#0)
183336817Sdim        mantb = memd(r29+#16)
184336817Sdim      } {
185336817Sdim        if (!ce) expa = add(expd, #1)
186336817Sdim        if ( ce) expb = add(expd, #1)
187336817Sdim      } {
188336817Sdim        lmanta = ASR(lmanta, expa)
189336817Sdim        lmantb = ASR(lmantb, expb)
190336817Sdim      } {
191336817Sdim        lmant = sub(lmanta, lmantb)
192336817Sdim        zero = #0
193336817Sdim      } {
194336817Sdim        k  = clb(lmant)
195336817Sdim        c63.L =#0x0001
196336817Sdim      } {
197336817Sdim        exp -= add(k, #-1)  //exp =  exp - (k+1)
198336817Sdim        k = add(k, #-1)
199336817Sdim        p0 = cmp.gt(k, #58)
200336817Sdim        c63.H =#0x8000
201336817Sdim      } {
202336817Sdim        if(!p0)memw(r7+#8) = exp
203336817Sdim        lmant = asl(lmant, k)
204336817Sdim        if(p0) jump .Ldenorma_s
205336817Sdim      } {
206336817Sdim        memd(r7+#0) = lmant
207336817Sdim        jumpr  r31
208336817Sdim      }
209336817Sdim.Ldenorma_s:
210336817Sdim        memd(r7+#0) = zero
211336817Sdim      {
212336817Sdim        memw(r7+#8) = c63
213336817Sdim        jumpr  r31
214336817Sdim      }
215336817Sdim
216336817Sdim/* ==================================================================== *
217336817Sdim fast2_QLDOUBLE fast2_ldmpy(fast2_QLDOUBLE a,fast2_QLDOUBLE b) {
218336817Sdim        fast2_QLDOUBLE c;
219336817Sdim        lint manta = a & MANTMASK;
220336817Sdim        int  expa  = Q6_R_sxth_R(a) ;
221336817Sdim        lint mantb = b & MANTMASK;
222336817Sdim        int  expb  = Q6_R_sxth_R(b) ;
223336817Sdim        int exp, k;
224336817Sdim        lint mant;
225336817Sdim        int          hia, hib, hi, lo;
226336817Sdim        unsigned int loa, lob;
227336817Sdim
228336817Sdim        hia = (int)(a >> 32);
229336817Sdim        loa = Q6_R_extractu_RII((int)manta, 31, 1);
230336817Sdim        hib = (int)(b >> 32);
231336817Sdim        lob = Q6_R_extractu_RII((int)mantb, 31, 1);
232336817Sdim
233336817Sdim        mant = Q6_P_mpy_RR(hia, lob);
234336817Sdim        mant = Q6_P_mpyacc_RR(mant,hib, loa);
235336817Sdim        mant = (mant >> 30) + (Q6_P_mpy_RR(hia, hib)<<1);
236336817Sdim
237336817Sdim        hi = (int) (mant>>32);
238336817Sdim
239336817Sdim        k =  Q6_R_normamt_R(hi);
240336817Sdim        mant = mant << k;
241336817Sdim        exp = expa + expb - k;
242336817Sdim        if (mant ==  0 || mant == -1)  exp = 0x8001;
243336817Sdim        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
244336817Sdim        return(c);
245336817Sdim }
246336817Sdim * ==================================================================== */
247336817Sdim        .text
248336817Sdim        .global fast2_ldmpy_asm
249336817Sdim        .type fast2_ldmpy_asm, @function
250336817Sdimfast2_ldmpy_asm:
251336817Sdim
252336817Sdim#define mantxl_    R9
253336817Sdim#define mantxl     R14
254336817Sdim#define mantxh     R15
255336817Sdim#define mantx      R15:14
256336817Sdim#define mantbl     R2
257336817Sdim#define mantbl_    R8
258336817Sdim#define mantbh     R3
259336817Sdim#define mantb      R3:2
260336817Sdim#define expa       R4
261336817Sdim#define expb       R5
262336817Sdim#define c8001      R8
263336817Sdim#define mantd      R7:6
264336817Sdim#define lmantc     R11:10
265336817Sdim#define kp         R9
266336817Sdim#define min        R13:12
267336817Sdim#define minh       R13
268336817Sdim#define max        R13:12
269336817Sdim#define maxh       R13
270336817Sdim#define ret        R0
271336817Sdim
272336817Sdim        .falign
273336817Sdim      {
274336817Sdim        mantx = memd(r29+#0)
275336817Sdim        mantb = memd(r29+#16)
276336817Sdim        min = #0
277336817Sdim      }
278336817Sdim      {
279336817Sdim        mantbl_= extractu(mantbl, #31, #1)
280336817Sdim        mantxl_= extractu(mantxl, #31, #1)
281336817Sdim        minh.H = #0x8000
282336817Sdim      }
283336817Sdim      {
284336817Sdim        lmantc = mpy(mantxh, mantbh)
285336817Sdim        mantd = mpy(mantxh, mantbl_)
286336817Sdim        expa = memw(r29+#8)
287336817Sdim        expb = memw(r29+#24)
288336817Sdim      }
289336817Sdim      {
290336817Sdim        lmantc = add(lmantc, lmantc)
291336817Sdim        mantd += mpy(mantbh, mantxl_)
292336817Sdim      }
293336817Sdim      {
294336817Sdim        mantd = asr(mantd, #30)
295336817Sdim        c8001.L =  #0x0001
296336817Sdim        p1 = cmp.eq(mantx, mantb)
297336817Sdim      }
298336817Sdim      {
299336817Sdim        mantd = add(mantd, lmantc)
300336817Sdim        expa= add(expa, expb)
301336817Sdim        p2 = cmp.eq(mantb, min)
302336817Sdim      }
303336817Sdim      {
304336817Sdim        kp  = clb(mantd)
305336817Sdim        c8001.H =  #0x8000
306336817Sdim        p1 = and(p1, p2)
307336817Sdim      }
308336817Sdim      {
309336817Sdim        expa-= add(kp, #-1)
310336817Sdim        kp = add(kp, #-1)
311336817Sdim        if(p1) jump .Lsat
312336817Sdim      }
313336817Sdim      {
314336817Sdim        mantd = asl(mantd, kp)
315336817Sdim        memw(ret+#8) = expa
316336817Sdim	p0 = cmp.gt(kp, #58)
317336817Sdim        if(p0.new) jump:NT .Ldenorm   //rarely happens
318336817Sdim      }
319336817Sdim      {
320336817Sdim        memd(ret+#0) = mantd
321336817Sdim        jumpr  r31
322336817Sdim      }
323336817Sdim.Lsat:
324336817Sdim      {
325336817Sdim        max = #0
326336817Sdim        expa+= add(kp, #1)
327336817Sdim      }
328336817Sdim      {
329336817Sdim        maxh.H = #0x4000
330336817Sdim        memw(ret+#8) = expa
331336817Sdim      }
332336817Sdim      {
333336817Sdim        memd(ret+#0) = max
334336817Sdim        jumpr  r31
335336817Sdim      }
336336817Sdim.Ldenorm:
337336817Sdim      {
338336817Sdim        memw(ret+#8) = c8001
339336817Sdim        mantx = #0
340336817Sdim      }
341336817Sdim      {
342336817Sdim        memd(ret+#0) = mantx
343336817Sdim        jumpr  r31
344336817Sdim      }
345