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/*   FUNCTIONS Optimized double floating point operators                */
10/* ==================================================================== */
11/*      c = dadd_asm(a, b)                                              */
12/* ====================================================================
13
14QDOUBLE dadd(QDOUBLE a,QDOUBLE b) {
15      QDOUBLE c;
16      lint manta = a & MANTMASK;
17      int  expa  = HEXAGON_R_sxth_R(a) ;
18      lint mantb = b & MANTMASK;
19      int  expb  = HEXAGON_R_sxth_R(b) ;
20      int  exp, expdiff, j, k, hi, lo, cn;
21      lint mant;
22
23        expdiff = (int) HEXAGON_P_vabsdiffh_PP(a, b);
24        expdiff = HEXAGON_R_sxth_R(expdiff) ;
25        if (expdiff > 63) { expdiff = 62;}
26        if (expa > expb) {
27          exp = expa + 1;
28          expa = 1;
29          expb = expdiff + 1;
30        } else {
31          exp = expb + 1;
32          expb = 1;
33          expa = expdiff + 1;
34        }
35        mant = (manta>>expa) + (mantb>>expb);
36
37        hi = (int) (mant>>32);
38        lo = (int) (mant);
39
40        k =  HEXAGON_R_normamt_R(hi);
41        if(hi == 0 || hi == -1) k =  31+HEXAGON_R_normamt_R(lo);
42
43        mant = (mant << k);
44        cn  = (mant == 0x8000000000000000LL);
45        exp = exp - k + cn;
46
47        if (mant ==  0 || mant == -1)  exp = 0x8001;
48        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
49      return(c);
50 }
51 * ==================================================================== */
52        .text
53        .global dadd_asm
54        .type dadd_asm, @function
55dadd_asm:
56
57#define manta      R0
58#define mantexpa   R1:0
59#define lmanta     R1:0
60#define mantb      R2
61#define mantexpb   R3:2
62#define lmantb     R3:2
63#define expa       R4
64#define expb       R5
65#define mantexpd   R7:6
66#define expd       R6
67#define exp        R8
68#define c63        R9
69#define lmant      R1:0
70#define manth      R1
71#define mantl      R0
72#define zero       R7:6
73#define zerol      R6
74#define minus      R3:2
75#define minusl     R2
76#define maxneg     R9
77#define minmin     R11:10  // exactly 0x800000000000000000LL
78#define minminh    R11
79#define k          R4
80#define kl         R5
81#define ce         P0
82        .falign
83      {
84        mantexpd = VABSDIFFH(mantexpa, mantexpb) //represented as 0x08001LL
85        c63 = #62
86        expa = SXTH(manta)
87        expb = SXTH(mantb)
88      } {
89        expd = SXTH(expd)
90        ce = CMP.GT(expa, expb);
91        if ( ce.new) exp = add(expa, #1)
92        if (!ce.new) exp = add(expb, #1)
93      } {
94        if ( ce) expa = #1
95        if (!ce) expb = #1
96        manta.L = #0
97        expd = MIN(expd, c63)
98      } {
99        if (!ce) expa = add(expd, #1)
100        if ( ce) expb = add(expd, #1)
101        mantb.L = #0
102        zero = #0
103      } {
104        lmanta = ASR(lmanta, expa)
105        lmantb = ASR(lmantb, expb)
106        minmin = #0
107      } {
108        lmant = add(lmanta, lmantb)
109        minus = #-1
110        minminh.H = #0x8000
111      } {
112        k  = NORMAMT(manth)
113        kl = NORMAMT(mantl)
114        p0 = cmp.eq(manth, zerol)
115        p1 = cmp.eq(manth, minusl)
116      } {
117        p0 = OR(p0, p1)
118        if(p0.new) k = add(kl, #31)
119        maxneg.H = #0
120      } {
121        mantexpa = ASL(lmant, k)
122        exp = SUB(exp, k)
123        maxneg.L = #0x8001
124      } {
125        p0 = cmp.eq(mantexpa, zero)
126        p1 = cmp.eq(mantexpa, minus)
127        manta.L = #0
128        exp = ZXTH(exp)
129      } {
130        p2 = cmp.eq(mantexpa, minmin)    //is result 0x80....0
131        if(p2.new) exp = add(exp, #1)
132      }
133#if (__HEXAGON_ARCH__ == 60)
134      {
135        p0 = OR(p0, p1)
136        if( p0.new) manta = OR(manta,maxneg)
137        if(!p0.new) manta = OR(manta,exp)
138      }
139        jumpr  r31
140#else
141      {
142        p0 = OR(p0, p1)
143        if( p0.new) manta = OR(manta,maxneg)
144        if(!p0.new) manta = OR(manta,exp)
145        jumpr  r31
146      }
147#endif
148/* =================================================================== *
149 QDOUBLE dsub(QDOUBLE a,QDOUBLE b) {
150      QDOUBLE c;
151      lint manta = a & MANTMASK;
152      int  expa  = HEXAGON_R_sxth_R(a) ;
153      lint mantb = b & MANTMASK;
154      int  expb  = HEXAGON_R_sxth_R(b) ;
155      int  exp, expdiff, j, k, hi, lo, cn;
156      lint mant;
157
158        expdiff = (int) HEXAGON_P_vabsdiffh_PP(a, b);
159        expdiff = HEXAGON_R_sxth_R(expdiff) ;
160        if (expdiff > 63) { expdiff = 62;}
161        if (expa > expb) {
162          exp = expa + 1;
163          expa = 1;
164          expb = expdiff + 1;
165        } else {
166          exp = expb + 1;
167          expb = 1;
168          expa = expdiff + 1;
169        }
170        mant = (manta>>expa) - (mantb>>expb);
171
172        hi = (int) (mant>>32);
173        lo = (int) (mant);
174
175        k =  HEXAGON_R_normamt_R(hi);
176        if(hi == 0 || hi == -1) k =  31+HEXAGON_R_normamt_R(lo);
177
178        mant = (mant << k);
179        cn  = (mant == 0x8000000000000000LL);
180        exp = exp - k + cn;
181
182        if (mant ==  0 || mant == -1)  exp = 0x8001;
183        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
184      return(c);
185 }
186 * ==================================================================== */
187        .text
188        .global dsub_asm
189        .type dsub_asm, @function
190dsub_asm:
191
192#define manta      R0
193#define mantexpa   R1:0
194#define lmanta     R1:0
195#define mantb      R2
196#define mantexpb   R3:2
197#define lmantb     R3:2
198#define expa       R4
199#define expb       R5
200#define mantexpd   R7:6
201#define expd       R6
202#define exp        R8
203#define c63        R9
204#define lmant      R1:0
205#define manth      R1
206#define mantl      R0
207#define zero       R7:6
208#define zerol      R6
209#define minus      R3:2
210#define minusl     R2
211#define maxneg     R9
212#define minmin     R11:10  // exactly 0x800000000000000000LL
213#define minminh    R11
214#define k          R4
215#define kl         R5
216#define ce         P0
217        .falign
218      {
219        mantexpd = VABSDIFFH(mantexpa, mantexpb) //represented as 0x08001LL
220        c63 = #62
221        expa = SXTH(manta)
222        expb = SXTH(mantb)
223      } {
224        expd = SXTH(expd)
225        ce = CMP.GT(expa, expb);
226        if ( ce.new) exp = add(expa, #1)
227        if (!ce.new) exp = add(expb, #1)
228      } {
229        if ( ce) expa = #1
230        if (!ce) expb = #1
231        manta.L = #0
232        expd = MIN(expd, c63)
233      } {
234        if (!ce) expa = add(expd, #1)
235        if ( ce) expb = add(expd, #1)
236        mantb.L = #0
237        zero = #0
238      } {
239        lmanta = ASR(lmanta, expa)
240        lmantb = ASR(lmantb, expb)
241        minmin = #0
242      } {
243        lmant = sub(lmanta, lmantb)
244        minus = #-1
245        minminh.H = #0x8000
246      } {
247        k  = NORMAMT(manth)
248        kl = NORMAMT(mantl)
249        p0 = cmp.eq(manth, zerol)
250        p1 = cmp.eq(manth, minusl)
251      } {
252        p0 = OR(p0, p1)
253        if(p0.new) k = add(kl, #31)
254        maxneg.H = #0
255      } {
256        mantexpa = ASL(lmant, k)
257        exp = SUB(exp, k)
258        maxneg.L = #0x8001
259      } {
260        p0 = cmp.eq(mantexpa, zero)
261        p1 = cmp.eq(mantexpa, minus)
262        manta.L = #0
263        exp = ZXTH(exp)
264      } {
265        p2 = cmp.eq(mantexpa, minmin)    //is result 0x80....0
266        if(p2.new) exp = add(exp, #1)
267      }
268#if (__HEXAGON_ARCH__ == 60)
269      {
270        p0 = OR(p0, p1)
271        if( p0.new) manta = OR(manta,maxneg)
272        if(!p0.new) manta = OR(manta,exp)
273      }
274        jumpr  r31
275#else
276      {
277        p0 = OR(p0, p1)
278        if( p0.new) manta = OR(manta,maxneg)
279        if(!p0.new) manta = OR(manta,exp)
280        jumpr  r31
281      }
282#endif
283/* ==================================================================== *
284 QDOUBLE dmpy(QDOUBLE a,QDOUBLE b) {
285        QDOUBLE c;
286        lint manta = a & MANTMASK;
287        int  expa  = HEXAGON_R_sxth_R(a) ;
288        lint mantb = b & MANTMASK;
289        int  expb  = HEXAGON_R_sxth_R(b) ;
290        int exp, k;
291        lint mant;
292        int          hia, hib, hi, lo;
293        unsigned int loa, lob;
294
295        hia = (int)(a >> 32);
296        loa = HEXAGON_R_extractu_RII((int)manta, 31, 1);
297        hib = (int)(b >> 32);
298        lob = HEXAGON_R_extractu_RII((int)mantb, 31, 1);
299
300        mant = HEXAGON_P_mpy_RR(hia, lob);
301        mant = HEXAGON_P_mpyacc_RR(mant,hib, loa);
302        mant = (mant >> 30) + (HEXAGON_P_mpy_RR(hia, hib)<<1);
303
304        hi = (int) (mant>>32);
305        lo = (int) (mant);
306
307        k =  HEXAGON_R_normamt_R(hi);
308        if(hi == 0 || hi == -1) k =  31+HEXAGON_R_normamt_R(lo);
309        mant = mant << k;
310        exp = expa + expb - k;
311        if (mant ==  0 || mant == -1)  exp = 0x8001;
312        c = (mant & MANTMASK) | (((lint) exp) & EXP_MASK);
313        return(c);
314 }
315 * ==================================================================== */
316        .text
317        .global dmpy_asm
318        .type dmpy_asm, @function
319dmpy_asm:
320
321#define mantal     R0
322#define mantah     R1
323#define mantexpa   R1:0
324#define mantbl     R2
325#define mantbh     R3
326#define mantexpb   R3:2
327#define expa       R4
328#define expb       R5
329#define mantexpd   R7:6
330#define exp        R8
331#define lmantc     R11:10
332#define mantch     R11
333#define mantcl     R10
334#define zero0      R7:6
335#define zero0l     R6
336#define minus1     R3:2
337#define minus1l    R2
338#define maxneg     R9
339#define k          R4
340#define kl         R5
341
342        .falign
343      {
344        mantbl = lsr(mantbl, #16)
345        mantal = lsr(mantal, #16)
346        expa = sxth(mantal)
347        expb = sxth(mantbl)
348      }
349      {
350        lmantc = mpy(mantah, mantbh)
351        mantexpd = mpy(mantah, mantbl)
352      }
353      {
354        lmantc = add(lmantc, lmantc) //<<1
355        mantexpd+= mpy(mantbh, mantal)
356      }
357      {
358        lmantc += asr(mantexpd, #15)
359        exp = add(expa, expb)
360        zero0 = #0
361        minus1 = #-1
362      }
363      {
364        k  = normamt(mantch)
365        kl = normamt(mantcl)
366        p0 = cmp.eq(mantch, zero0l)
367        p1 = cmp.eq(mantch, minus1l)
368      }
369      {
370        p0 = or(p0, p1)
371        if(p0.new) k = add(kl, #31)
372        maxneg.H = #0
373      }
374      {
375        mantexpa = asl(lmantc, k)
376        exp = sub(exp, k)
377        maxneg.L = #0x8001
378      }
379      {
380        p0 = cmp.eq(mantexpa, zero0)
381        p1 = cmp.eq(mantexpa, minus1)
382        mantal.L = #0
383        exp = zxth(exp)
384      }
385#if (__HEXAGON_ARCH__ == 60)
386      {
387        p0 = or(p0, p1)
388        if( p0.new) mantal = or(mantal,maxneg)
389        if(!p0.new) mantal = or(mantal,exp)
390      }
391        jumpr  r31
392#else
393      {
394        p0 = or(p0, p1)
395        if( p0.new) mantal = or(mantal,maxneg)
396        if(!p0.new) mantal = or(mantal,exp)
397        jumpr  r31
398      }
399#endif
400