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 | |
10 | fast2_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 |
51 | fast2_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 |
150 | fast2_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 |
250 | fast2_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 | |