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 | |
14 | QDOUBLE 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 |
55 | dadd_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 |
190 | dsub_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 |
319 | dmpy_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 | |