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