]> Git Repo - qemu.git/blob - target-arm/neon_helper.c
target-arm: Fix VQSHL of signed 64 bit values
[qemu.git] / target-arm / neon_helper.c
1 /*
2  * ARM NEON vector operations.
3  *
4  * Copyright (c) 2007, 2008 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licenced under the GNU GPL v2.
8  */
9 #include <stdlib.h>
10 #include <stdio.h>
11
12 #include "cpu.h"
13 #include "exec-all.h"
14 #include "helpers.h"
15
16 #define SIGNBIT (uint32_t)0x80000000
17 #define SIGNBIT64 ((uint64_t)1 << 63)
18
19 #define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] = CPSR_Q
20
21 static float_status neon_float_status;
22 #define NFS &neon_float_status
23
24 /* Helper routines to perform bitwise copies between float and int.  */
25 static inline float32 vfp_itos(uint32_t i)
26 {
27     union {
28         uint32_t i;
29         float32 s;
30     } v;
31
32     v.i = i;
33     return v.s;
34 }
35
36 static inline uint32_t vfp_stoi(float32 s)
37 {
38     union {
39         uint32_t i;
40         float32 s;
41     } v;
42
43     v.s = s;
44     return v.i;
45 }
46
47 #define NEON_TYPE1(name, type) \
48 typedef struct \
49 { \
50     type v1; \
51 } neon_##name;
52 #ifdef HOST_WORDS_BIGENDIAN
53 #define NEON_TYPE2(name, type) \
54 typedef struct \
55 { \
56     type v2; \
57     type v1; \
58 } neon_##name;
59 #define NEON_TYPE4(name, type) \
60 typedef struct \
61 { \
62     type v4; \
63     type v3; \
64     type v2; \
65     type v1; \
66 } neon_##name;
67 #else
68 #define NEON_TYPE2(name, type) \
69 typedef struct \
70 { \
71     type v1; \
72     type v2; \
73 } neon_##name;
74 #define NEON_TYPE4(name, type) \
75 typedef struct \
76 { \
77     type v1; \
78     type v2; \
79     type v3; \
80     type v4; \
81 } neon_##name;
82 #endif
83
84 NEON_TYPE4(s8, int8_t)
85 NEON_TYPE4(u8, uint8_t)
86 NEON_TYPE2(s16, int16_t)
87 NEON_TYPE2(u16, uint16_t)
88 NEON_TYPE1(s32, int32_t)
89 NEON_TYPE1(u32, uint32_t)
90 #undef NEON_TYPE4
91 #undef NEON_TYPE2
92 #undef NEON_TYPE1
93
94 /* Copy from a uint32_t to a vector structure type.  */
95 #define NEON_UNPACK(vtype, dest, val) do { \
96     union { \
97         vtype v; \
98         uint32_t i; \
99     } conv_u; \
100     conv_u.i = (val); \
101     dest = conv_u.v; \
102     } while(0)
103
104 /* Copy from a vector structure type to a uint32_t.  */
105 #define NEON_PACK(vtype, dest, val) do { \
106     union { \
107         vtype v; \
108         uint32_t i; \
109     } conv_u; \
110     conv_u.v = (val); \
111     dest = conv_u.i; \
112     } while(0)
113
114 #define NEON_DO1 \
115     NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1);
116 #define NEON_DO2 \
117     NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1); \
118     NEON_FN(vdest.v2, vsrc1.v2, vsrc2.v2);
119 #define NEON_DO4 \
120     NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1); \
121     NEON_FN(vdest.v2, vsrc1.v2, vsrc2.v2); \
122     NEON_FN(vdest.v3, vsrc1.v3, vsrc2.v3); \
123     NEON_FN(vdest.v4, vsrc1.v4, vsrc2.v4);
124
125 #define NEON_VOP_BODY(vtype, n) \
126 { \
127     uint32_t res; \
128     vtype vsrc1; \
129     vtype vsrc2; \
130     vtype vdest; \
131     NEON_UNPACK(vtype, vsrc1, arg1); \
132     NEON_UNPACK(vtype, vsrc2, arg2); \
133     NEON_DO##n; \
134     NEON_PACK(vtype, res, vdest); \
135     return res; \
136 }
137
138 #define NEON_VOP(name, vtype, n) \
139 uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \
140 NEON_VOP_BODY(vtype, n)
141
142 #define NEON_VOP_ENV(name, vtype, n) \
143 uint32_t HELPER(glue(neon_,name))(CPUState *env, uint32_t arg1, uint32_t arg2) \
144 NEON_VOP_BODY(vtype, n)
145
146 /* Pairwise operations.  */
147 /* For 32-bit elements each segment only contains a single element, so
148    the elementwise and pairwise operations are the same.  */
149 #define NEON_PDO2 \
150     NEON_FN(vdest.v1, vsrc1.v1, vsrc1.v2); \
151     NEON_FN(vdest.v2, vsrc2.v1, vsrc2.v2);
152 #define NEON_PDO4 \
153     NEON_FN(vdest.v1, vsrc1.v1, vsrc1.v2); \
154     NEON_FN(vdest.v2, vsrc1.v3, vsrc1.v4); \
155     NEON_FN(vdest.v3, vsrc2.v1, vsrc2.v2); \
156     NEON_FN(vdest.v4, vsrc2.v3, vsrc2.v4); \
157
158 #define NEON_POP(name, vtype, n) \
159 uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \
160 { \
161     uint32_t res; \
162     vtype vsrc1; \
163     vtype vsrc2; \
164     vtype vdest; \
165     NEON_UNPACK(vtype, vsrc1, arg1); \
166     NEON_UNPACK(vtype, vsrc2, arg2); \
167     NEON_PDO##n; \
168     NEON_PACK(vtype, res, vdest); \
169     return res; \
170 }
171
172 /* Unary operators.  */
173 #define NEON_VOP1(name, vtype, n) \
174 uint32_t HELPER(glue(neon_,name))(uint32_t arg) \
175 { \
176     vtype vsrc1; \
177     vtype vdest; \
178     NEON_UNPACK(vtype, vsrc1, arg); \
179     NEON_DO##n; \
180     NEON_PACK(vtype, arg, vdest); \
181     return arg; \
182 }
183
184
185 #define NEON_USAT(dest, src1, src2, type) do { \
186     uint32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
187     if (tmp != (type)tmp) { \
188         SET_QC(); \
189         dest = ~0; \
190     } else { \
191         dest = tmp; \
192     }} while(0)
193 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
194 NEON_VOP_ENV(qadd_u8, neon_u8, 4)
195 #undef NEON_FN
196 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
197 NEON_VOP_ENV(qadd_u16, neon_u16, 2)
198 #undef NEON_FN
199 #undef NEON_USAT
200
201 #define NEON_SSAT(dest, src1, src2, type) do { \
202     int32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
203     if (tmp != (type)tmp) { \
204         SET_QC(); \
205         if (src2 > 0) { \
206             tmp = (1 << (sizeof(type) * 8 - 1)) - 1; \
207         } else { \
208             tmp = 1 << (sizeof(type) * 8 - 1); \
209         } \
210     } \
211     dest = tmp; \
212     } while(0)
213 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
214 NEON_VOP_ENV(qadd_s8, neon_s8, 4)
215 #undef NEON_FN
216 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
217 NEON_VOP_ENV(qadd_s16, neon_s16, 2)
218 #undef NEON_FN
219 #undef NEON_SSAT
220
221 #define NEON_USAT(dest, src1, src2, type) do { \
222     uint32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
223     if (tmp != (type)tmp) { \
224         SET_QC(); \
225         dest = 0; \
226     } else { \
227         dest = tmp; \
228     }} while(0)
229 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
230 NEON_VOP_ENV(qsub_u8, neon_u8, 4)
231 #undef NEON_FN
232 #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
233 NEON_VOP_ENV(qsub_u16, neon_u16, 2)
234 #undef NEON_FN
235 #undef NEON_USAT
236
237 #define NEON_SSAT(dest, src1, src2, type) do { \
238     int32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
239     if (tmp != (type)tmp) { \
240         SET_QC(); \
241         if (src2 < 0) { \
242             tmp = (1 << (sizeof(type) * 8 - 1)) - 1; \
243         } else { \
244             tmp = 1 << (sizeof(type) * 8 - 1); \
245         } \
246     } \
247     dest = tmp; \
248     } while(0)
249 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
250 NEON_VOP_ENV(qsub_s8, neon_s8, 4)
251 #undef NEON_FN
252 #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
253 NEON_VOP_ENV(qsub_s16, neon_s16, 2)
254 #undef NEON_FN
255 #undef NEON_SSAT
256
257 #define NEON_FN(dest, src1, src2) dest = (src1 + src2) >> 1
258 NEON_VOP(hadd_s8, neon_s8, 4)
259 NEON_VOP(hadd_u8, neon_u8, 4)
260 NEON_VOP(hadd_s16, neon_s16, 2)
261 NEON_VOP(hadd_u16, neon_u16, 2)
262 #undef NEON_FN
263
264 int32_t HELPER(neon_hadd_s32)(int32_t src1, int32_t src2)
265 {
266     int32_t dest;
267
268     dest = (src1 >> 1) + (src2 >> 1);
269     if (src1 & src2 & 1)
270         dest++;
271     return dest;
272 }
273
274 uint32_t HELPER(neon_hadd_u32)(uint32_t src1, uint32_t src2)
275 {
276     uint32_t dest;
277
278     dest = (src1 >> 1) + (src2 >> 1);
279     if (src1 & src2 & 1)
280         dest++;
281     return dest;
282 }
283
284 #define NEON_FN(dest, src1, src2) dest = (src1 + src2 + 1) >> 1
285 NEON_VOP(rhadd_s8, neon_s8, 4)
286 NEON_VOP(rhadd_u8, neon_u8, 4)
287 NEON_VOP(rhadd_s16, neon_s16, 2)
288 NEON_VOP(rhadd_u16, neon_u16, 2)
289 #undef NEON_FN
290
291 int32_t HELPER(neon_rhadd_s32)(int32_t src1, int32_t src2)
292 {
293     int32_t dest;
294
295     dest = (src1 >> 1) + (src2 >> 1);
296     if ((src1 | src2) & 1)
297         dest++;
298     return dest;
299 }
300
301 uint32_t HELPER(neon_rhadd_u32)(uint32_t src1, uint32_t src2)
302 {
303     uint32_t dest;
304
305     dest = (src1 >> 1) + (src2 >> 1);
306     if ((src1 | src2) & 1)
307         dest++;
308     return dest;
309 }
310
311 #define NEON_FN(dest, src1, src2) dest = (src1 - src2) >> 1
312 NEON_VOP(hsub_s8, neon_s8, 4)
313 NEON_VOP(hsub_u8, neon_u8, 4)
314 NEON_VOP(hsub_s16, neon_s16, 2)
315 NEON_VOP(hsub_u16, neon_u16, 2)
316 #undef NEON_FN
317
318 int32_t HELPER(neon_hsub_s32)(int32_t src1, int32_t src2)
319 {
320     int32_t dest;
321
322     dest = (src1 >> 1) - (src2 >> 1);
323     if ((~src1) & src2 & 1)
324         dest--;
325     return dest;
326 }
327
328 uint32_t HELPER(neon_hsub_u32)(uint32_t src1, uint32_t src2)
329 {
330     uint32_t dest;
331
332     dest = (src1 >> 1) - (src2 >> 1);
333     if ((~src1) & src2 & 1)
334         dest--;
335     return dest;
336 }
337
338 #define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? ~0 : 0
339 NEON_VOP(cgt_s8, neon_s8, 4)
340 NEON_VOP(cgt_u8, neon_u8, 4)
341 NEON_VOP(cgt_s16, neon_s16, 2)
342 NEON_VOP(cgt_u16, neon_u16, 2)
343 NEON_VOP(cgt_s32, neon_s32, 1)
344 NEON_VOP(cgt_u32, neon_u32, 1)
345 #undef NEON_FN
346
347 #define NEON_FN(dest, src1, src2) dest = (src1 >= src2) ? ~0 : 0
348 NEON_VOP(cge_s8, neon_s8, 4)
349 NEON_VOP(cge_u8, neon_u8, 4)
350 NEON_VOP(cge_s16, neon_s16, 2)
351 NEON_VOP(cge_u16, neon_u16, 2)
352 NEON_VOP(cge_s32, neon_s32, 1)
353 NEON_VOP(cge_u32, neon_u32, 1)
354 #undef NEON_FN
355
356 #define NEON_FN(dest, src1, src2) dest = (src1 < src2) ? src1 : src2
357 NEON_VOP(min_s8, neon_s8, 4)
358 NEON_VOP(min_u8, neon_u8, 4)
359 NEON_VOP(min_s16, neon_s16, 2)
360 NEON_VOP(min_u16, neon_u16, 2)
361 NEON_VOP(min_s32, neon_s32, 1)
362 NEON_VOP(min_u32, neon_u32, 1)
363 NEON_POP(pmin_s8, neon_s8, 4)
364 NEON_POP(pmin_u8, neon_u8, 4)
365 NEON_POP(pmin_s16, neon_s16, 2)
366 NEON_POP(pmin_u16, neon_u16, 2)
367 #undef NEON_FN
368
369 #define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? src1 : src2
370 NEON_VOP(max_s8, neon_s8, 4)
371 NEON_VOP(max_u8, neon_u8, 4)
372 NEON_VOP(max_s16, neon_s16, 2)
373 NEON_VOP(max_u16, neon_u16, 2)
374 NEON_VOP(max_s32, neon_s32, 1)
375 NEON_VOP(max_u32, neon_u32, 1)
376 NEON_POP(pmax_s8, neon_s8, 4)
377 NEON_POP(pmax_u8, neon_u8, 4)
378 NEON_POP(pmax_s16, neon_s16, 2)
379 NEON_POP(pmax_u16, neon_u16, 2)
380 #undef NEON_FN
381
382 #define NEON_FN(dest, src1, src2) \
383     dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
384 NEON_VOP(abd_s8, neon_s8, 4)
385 NEON_VOP(abd_u8, neon_u8, 4)
386 NEON_VOP(abd_s16, neon_s16, 2)
387 NEON_VOP(abd_u16, neon_u16, 2)
388 NEON_VOP(abd_s32, neon_s32, 1)
389 NEON_VOP(abd_u32, neon_u32, 1)
390 #undef NEON_FN
391
392 #define NEON_FN(dest, src1, src2) do { \
393     int8_t tmp; \
394     tmp = (int8_t)src2; \
395     if (tmp >= (ssize_t)sizeof(src1) * 8 || \
396         tmp <= -(ssize_t)sizeof(src1) * 8) { \
397         dest = 0; \
398     } else if (tmp < 0) { \
399         dest = src1 >> -tmp; \
400     } else { \
401         dest = src1 << tmp; \
402     }} while (0)
403 NEON_VOP(shl_u8, neon_u8, 4)
404 NEON_VOP(shl_u16, neon_u16, 2)
405 NEON_VOP(shl_u32, neon_u32, 1)
406 #undef NEON_FN
407
408 uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop)
409 {
410     int8_t shift = (int8_t)shiftop;
411     if (shift >= 64 || shift <= -64) {
412         val = 0;
413     } else if (shift < 0) {
414         val >>= -shift;
415     } else {
416         val <<= shift;
417     }
418     return val;
419 }
420
421 #define NEON_FN(dest, src1, src2) do { \
422     int8_t tmp; \
423     tmp = (int8_t)src2; \
424     if (tmp >= (ssize_t)sizeof(src1) * 8) { \
425         dest = 0; \
426     } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
427         dest = src1 >> (sizeof(src1) * 8 - 1); \
428     } else if (tmp < 0) { \
429         dest = src1 >> -tmp; \
430     } else { \
431         dest = src1 << tmp; \
432     }} while (0)
433 NEON_VOP(shl_s8, neon_s8, 4)
434 NEON_VOP(shl_s16, neon_s16, 2)
435 NEON_VOP(shl_s32, neon_s32, 1)
436 #undef NEON_FN
437
438 uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
439 {
440     int8_t shift = (int8_t)shiftop;
441     int64_t val = valop;
442     if (shift >= 64) {
443         val = 0;
444     } else if (shift <= -64) {
445         val >>= 63;
446     } else if (shift < 0) {
447         val >>= -shift;
448     } else {
449         val <<= shift;
450     }
451     return val;
452 }
453
454 #define NEON_FN(dest, src1, src2) do { \
455     int8_t tmp; \
456     tmp = (int8_t)src2; \
457     if (tmp >= (ssize_t)sizeof(src1) * 8) { \
458         dest = 0; \
459     } else if (tmp < -(ssize_t)sizeof(src1) * 8) { \
460         dest = src1 >> (sizeof(src1) * 8 - 1); \
461     } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \
462         dest = src1 >> (tmp - 1); \
463         dest++; \
464         dest >>= 1; \
465     } else if (tmp < 0) { \
466         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
467     } else { \
468         dest = src1 << tmp; \
469     }} while (0)
470 NEON_VOP(rshl_s8, neon_s8, 4)
471 NEON_VOP(rshl_s16, neon_s16, 2)
472 NEON_VOP(rshl_s32, neon_s32, 1)
473 #undef NEON_FN
474
475 uint64_t HELPER(neon_rshl_s64)(uint64_t valop, uint64_t shiftop)
476 {
477     int8_t shift = (int8_t)shiftop;
478     int64_t val = valop;
479     if (shift >= 64) {
480         val = 0;
481     } else if (shift < -64) {
482         val >>= 63;
483     } else if (shift == -63) {
484         val >>= 63;
485         val++;
486         val >>= 1;
487     } else if (shift < 0) {
488         val = (val + ((int64_t)1 << (-1 - shift))) >> -shift;
489     } else {
490         val <<= shift;
491     }
492     return val;
493 }
494
495 #define NEON_FN(dest, src1, src2) do { \
496     int8_t tmp; \
497     tmp = (int8_t)src2; \
498     if (tmp >= (ssize_t)sizeof(src1) * 8 || \
499         tmp < -(ssize_t)sizeof(src1) * 8) { \
500         dest = 0; \
501     } else if (tmp == -(ssize_t)sizeof(src1) * 8) { \
502         dest = src1 >> (tmp - 1); \
503     } else if (tmp < 0) { \
504         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
505     } else { \
506         dest = src1 << tmp; \
507     }} while (0)
508 NEON_VOP(rshl_u8, neon_u8, 4)
509 NEON_VOP(rshl_u16, neon_u16, 2)
510 NEON_VOP(rshl_u32, neon_u32, 1)
511 #undef NEON_FN
512
513 uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop)
514 {
515     int8_t shift = (uint8_t)shiftop;
516     if (shift >= 64 || shift < 64) {
517         val = 0;
518     } else if (shift == -64) {
519         /* Rounding a 1-bit result just preserves that bit.  */
520         val >>= 63;
521     } if (shift < 0) {
522         val = (val + ((uint64_t)1 << (-1 - shift))) >> -shift;
523         val >>= -shift;
524     } else {
525         val <<= shift;
526     }
527     return val;
528 }
529
530 #define NEON_FN(dest, src1, src2) do { \
531     int8_t tmp; \
532     tmp = (int8_t)src2; \
533     if (tmp >= (ssize_t)sizeof(src1) * 8) { \
534         if (src1) { \
535             SET_QC(); \
536             dest = ~0; \
537         } else { \
538             dest = 0; \
539         } \
540     } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
541         dest = 0; \
542     } else if (tmp < 0) { \
543         dest = src1 >> -tmp; \
544     } else { \
545         dest = src1 << tmp; \
546         if ((dest >> tmp) != src1) { \
547             SET_QC(); \
548             dest = ~0; \
549         } \
550     }} while (0)
551 NEON_VOP_ENV(qshl_u8, neon_u8, 4)
552 NEON_VOP_ENV(qshl_u16, neon_u16, 2)
553 NEON_VOP_ENV(qshl_u32, neon_u32, 1)
554 #undef NEON_FN
555
556 uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
557 {
558     int8_t shift = (int8_t)shiftop;
559     if (shift >= 64) {
560         if (val) {
561             val = ~(uint64_t)0;
562             SET_QC();
563         } else {
564             val = 0;
565         }
566     } else if (shift <= -64) {
567         val = 0;
568     } else if (shift < 0) {
569         val >>= -shift;
570     } else {
571         uint64_t tmp = val;
572         val <<= shift;
573         if ((val >> shift) != tmp) {
574             SET_QC();
575             val = ~(uint64_t)0;
576         }
577     }
578     return val;
579 }
580
581 #define NEON_FN(dest, src1, src2) do { \
582     int8_t tmp; \
583     tmp = (int8_t)src2; \
584     if (tmp >= (ssize_t)sizeof(src1) * 8) { \
585         if (src1) \
586             SET_QC(); \
587         dest = src1 >> 31; \
588     } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
589         dest = src1 >> 31; \
590     } else if (tmp < 0) { \
591         dest = src1 >> -tmp; \
592     } else { \
593         dest = src1 << tmp; \
594         if ((dest >> tmp) != src1) { \
595             SET_QC(); \
596             dest = src2 >> 31; \
597         } \
598     }} while (0)
599 NEON_VOP_ENV(qshl_s8, neon_s8, 4)
600 NEON_VOP_ENV(qshl_s16, neon_s16, 2)
601 NEON_VOP_ENV(qshl_s32, neon_s32, 1)
602 #undef NEON_FN
603
604 uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
605 {
606     int8_t shift = (uint8_t)shiftop;
607     int64_t val = valop;
608     if (shift >= 64) {
609         if (val) {
610             SET_QC();
611             val = (val >> 63) & ~SIGNBIT64;
612         }
613     } else if (shift <= -64) {
614         val >>= 63;
615     } else if (shift < 0) {
616         val >>= -shift;
617     } else {
618         int64_t tmp = val;
619         val <<= shift;
620         if ((val >> shift) != tmp) {
621             SET_QC();
622             val = (tmp >> 63) ^ ~SIGNBIT64;
623         }
624     }
625     return val;
626 }
627
628
629 /* FIXME: This is wrong.  */
630 #define NEON_FN(dest, src1, src2) do { \
631     int8_t tmp; \
632     tmp = (int8_t)src2; \
633     if (tmp < 0) { \
634         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
635     } else { \
636         dest = src1 << tmp; \
637         if ((dest >> tmp) != src1) { \
638             SET_QC(); \
639             dest = ~0; \
640         } \
641     }} while (0)
642 NEON_VOP_ENV(qrshl_u8, neon_u8, 4)
643 NEON_VOP_ENV(qrshl_u16, neon_u16, 2)
644 NEON_VOP_ENV(qrshl_u32, neon_u32, 1)
645 #undef NEON_FN
646
647 uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
648 {
649     int8_t shift = (int8_t)shiftop;
650     if (shift < 0) {
651         val = (val + (1 << (-1 - shift))) >> -shift;
652     } else { \
653         uint64_t tmp = val;
654         val <<= shift;
655         if ((val >> shift) != tmp) {
656             SET_QC();
657             val = ~0;
658         }
659     }
660     return val;
661 }
662
663 #define NEON_FN(dest, src1, src2) do { \
664     int8_t tmp; \
665     tmp = (int8_t)src2; \
666     if (tmp < 0) { \
667         dest = (src1 + (1 << (-1 - tmp))) >> -tmp; \
668     } else { \
669         dest = src1 << tmp; \
670         if ((dest >> tmp) != src1) { \
671             SET_QC(); \
672             dest = src1 >> 31; \
673         } \
674     }} while (0)
675 NEON_VOP_ENV(qrshl_s8, neon_s8, 4)
676 NEON_VOP_ENV(qrshl_s16, neon_s16, 2)
677 NEON_VOP_ENV(qrshl_s32, neon_s32, 1)
678 #undef NEON_FN
679
680 uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
681 {
682     int8_t shift = (uint8_t)shiftop;
683     int64_t val = valop;
684
685     if (shift < 0) {
686         val = (val + (1 << (-1 - shift))) >> -shift;
687     } else {
688         int64_t tmp = val;;
689         val <<= shift;
690         if ((val >> shift) != tmp) {
691             SET_QC();
692             val = tmp >> 31;
693         }
694     }
695     return val;
696 }
697
698 uint32_t HELPER(neon_add_u8)(uint32_t a, uint32_t b)
699 {
700     uint32_t mask;
701     mask = (a ^ b) & 0x80808080u;
702     a &= ~0x80808080u;
703     b &= ~0x80808080u;
704     return (a + b) ^ mask;
705 }
706
707 uint32_t HELPER(neon_add_u16)(uint32_t a, uint32_t b)
708 {
709     uint32_t mask;
710     mask = (a ^ b) & 0x80008000u;
711     a &= ~0x80008000u;
712     b &= ~0x80008000u;
713     return (a + b) ^ mask;
714 }
715
716 #define NEON_FN(dest, src1, src2) dest = src1 + src2
717 NEON_POP(padd_u8, neon_u8, 4)
718 NEON_POP(padd_u16, neon_u16, 2)
719 #undef NEON_FN
720
721 #define NEON_FN(dest, src1, src2) dest = src1 - src2
722 NEON_VOP(sub_u8, neon_u8, 4)
723 NEON_VOP(sub_u16, neon_u16, 2)
724 #undef NEON_FN
725
726 #define NEON_FN(dest, src1, src2) dest = src1 * src2
727 NEON_VOP(mul_u8, neon_u8, 4)
728 NEON_VOP(mul_u16, neon_u16, 2)
729 #undef NEON_FN
730
731 /* Polynomial multiplication is like integer multiplication except the
732    partial products are XORed, not added.  */
733 uint32_t HELPER(neon_mul_p8)(uint32_t op1, uint32_t op2)
734 {
735     uint32_t mask;
736     uint32_t result;
737     result = 0;
738     while (op1) {
739         mask = 0;
740         if (op1 & 1)
741             mask |= 0xff;
742         if (op1 & (1 << 8))
743             mask |= (0xff << 8);
744         if (op1 & (1 << 16))
745             mask |= (0xff << 16);
746         if (op1 & (1 << 24))
747             mask |= (0xff << 24);
748         result ^= op2 & mask;
749         op1 = (op1 >> 1) & 0x7f7f7f7f;
750         op2 = (op2 << 1) & 0xfefefefe;
751     }
752     return result;
753 }
754
755 #define NEON_FN(dest, src1, src2) dest = (src1 & src2) ? -1 : 0
756 NEON_VOP(tst_u8, neon_u8, 4)
757 NEON_VOP(tst_u16, neon_u16, 2)
758 NEON_VOP(tst_u32, neon_u32, 1)
759 #undef NEON_FN
760
761 #define NEON_FN(dest, src1, src2) dest = (src1 == src2) ? -1 : 0
762 NEON_VOP(ceq_u8, neon_u8, 4)
763 NEON_VOP(ceq_u16, neon_u16, 2)
764 NEON_VOP(ceq_u32, neon_u32, 1)
765 #undef NEON_FN
766
767 #define NEON_FN(dest, src, dummy) dest = (src < 0) ? -src : src
768 NEON_VOP1(abs_s8, neon_s8, 4)
769 NEON_VOP1(abs_s16, neon_s16, 2)
770 #undef NEON_FN
771
772 /* Count Leading Sign/Zero Bits.  */
773 static inline int do_clz8(uint8_t x)
774 {
775     int n;
776     for (n = 8; x; n--)
777         x >>= 1;
778     return n;
779 }
780
781 static inline int do_clz16(uint16_t x)
782 {
783     int n;
784     for (n = 16; x; n--)
785         x >>= 1;
786     return n;
787 }
788
789 #define NEON_FN(dest, src, dummy) dest = do_clz8(src)
790 NEON_VOP1(clz_u8, neon_u8, 4)
791 #undef NEON_FN
792
793 #define NEON_FN(dest, src, dummy) dest = do_clz16(src)
794 NEON_VOP1(clz_u16, neon_u16, 2)
795 #undef NEON_FN
796
797 #define NEON_FN(dest, src, dummy) dest = do_clz8((src < 0) ? ~src : src) - 1
798 NEON_VOP1(cls_s8, neon_s8, 4)
799 #undef NEON_FN
800
801 #define NEON_FN(dest, src, dummy) dest = do_clz16((src < 0) ? ~src : src) - 1
802 NEON_VOP1(cls_s16, neon_s16, 2)
803 #undef NEON_FN
804
805 uint32_t HELPER(neon_cls_s32)(uint32_t x)
806 {
807     int count;
808     if ((int32_t)x < 0)
809         x = ~x;
810     for (count = 32; x; count--)
811         x = x >> 1;
812     return count - 1;
813 }
814
815 /* Bit count.  */
816 uint32_t HELPER(neon_cnt_u8)(uint32_t x)
817 {
818     x = (x & 0x55555555) + ((x >>  1) & 0x55555555);
819     x = (x & 0x33333333) + ((x >>  2) & 0x33333333);
820     x = (x & 0x0f0f0f0f) + ((x >>  4) & 0x0f0f0f0f);
821     return x;
822 }
823
824 #define NEON_QDMULH16(dest, src1, src2, round) do { \
825     uint32_t tmp = (int32_t)(int16_t) src1 * (int16_t) src2; \
826     if ((tmp ^ (tmp << 1)) & SIGNBIT) { \
827         SET_QC(); \
828         tmp = (tmp >> 31) ^ ~SIGNBIT; \
829     } \
830     tmp <<= 1; \
831     if (round) { \
832         int32_t old = tmp; \
833         tmp += 1 << 15; \
834         if ((int32_t)tmp < old) { \
835             SET_QC(); \
836             tmp = SIGNBIT - 1; \
837         } \
838     } \
839     dest = tmp >> 16; \
840     } while(0)
841 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 0)
842 NEON_VOP_ENV(qdmulh_s16, neon_s16, 2)
843 #undef NEON_FN
844 #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 1)
845 NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2)
846 #undef NEON_FN
847 #undef NEON_QDMULH16
848
849 #define NEON_QDMULH32(dest, src1, src2, round) do { \
850     uint64_t tmp = (int64_t)(int32_t) src1 * (int32_t) src2; \
851     if ((tmp ^ (tmp << 1)) & SIGNBIT64) { \
852         SET_QC(); \
853         tmp = (tmp >> 63) ^ ~SIGNBIT64; \
854     } else { \
855         tmp <<= 1; \
856     } \
857     if (round) { \
858         int64_t old = tmp; \
859         tmp += (int64_t)1 << 31; \
860         if ((int64_t)tmp < old) { \
861             SET_QC(); \
862             tmp = SIGNBIT64 - 1; \
863         } \
864     } \
865     dest = tmp >> 32; \
866     } while(0)
867 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 0)
868 NEON_VOP_ENV(qdmulh_s32, neon_s32, 1)
869 #undef NEON_FN
870 #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 1)
871 NEON_VOP_ENV(qrdmulh_s32, neon_s32, 1)
872 #undef NEON_FN
873 #undef NEON_QDMULH32
874
875 uint32_t HELPER(neon_narrow_u8)(uint64_t x)
876 {
877     return (x & 0xffu) | ((x >> 8) & 0xff00u) | ((x >> 16) & 0xff0000u)
878            | ((x >> 24) & 0xff000000u);
879 }
880
881 uint32_t HELPER(neon_narrow_u16)(uint64_t x)
882 {
883     return (x & 0xffffu) | ((x >> 16) & 0xffff0000u);
884 }
885
886 uint32_t HELPER(neon_narrow_high_u8)(uint64_t x)
887 {
888     return ((x >> 8) & 0xff) | ((x >> 16) & 0xff00)
889             | ((x >> 24) & 0xff0000) | ((x >> 32) & 0xff000000);
890 }
891
892 uint32_t HELPER(neon_narrow_high_u16)(uint64_t x)
893 {
894     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
895 }
896
897 uint32_t HELPER(neon_narrow_round_high_u8)(uint64_t x)
898 {
899     x &= 0xff80ff80ff80ff80ull;
900     x += 0x0080008000800080ull;
901     return ((x >> 8) & 0xff) | ((x >> 16) & 0xff00)
902             | ((x >> 24) & 0xff0000) | ((x >> 32) & 0xff000000);
903 }
904
905 uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
906 {
907     x &= 0xffff8000ffff8000ull;
908     x += 0x0000800000008000ull;
909     return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
910 }
911
912 uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
913 {
914     uint16_t s;
915     uint8_t d;
916     uint32_t res = 0;
917 #define SAT8(n) \
918     s = x >> n; \
919     if (s > 0xff) { \
920         d = 0xff; \
921         SET_QC(); \
922     } else  { \
923         d = s; \
924     } \
925     res |= (uint32_t)d << (n / 2);
926
927     SAT8(0);
928     SAT8(16);
929     SAT8(32);
930     SAT8(48);
931 #undef SAT8
932     return res;
933 }
934
935 uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
936 {
937     int16_t s;
938     uint8_t d;
939     uint32_t res = 0;
940 #define SAT8(n) \
941     s = x >> n; \
942     if (s != (int8_t)s) { \
943         d = (s >> 15) ^ 0x7f; \
944         SET_QC(); \
945     } else  { \
946         d = s; \
947     } \
948     res |= (uint32_t)d << (n / 2);
949
950     SAT8(0);
951     SAT8(16);
952     SAT8(32);
953     SAT8(48);
954 #undef SAT8
955     return res;
956 }
957
958 uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
959 {
960     uint32_t high;
961     uint32_t low;
962     low = x;
963     if (low > 0xffff) {
964         low = 0xffff;
965         SET_QC();
966     }
967     high = x >> 32;
968     if (high > 0xffff) {
969         high = 0xffff;
970         SET_QC();
971     }
972     return low | (high << 16);
973 }
974
975 uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
976 {
977     int32_t low;
978     int32_t high;
979     low = x;
980     if (low != (int16_t)low) {
981         low = (low >> 31) ^ 0x7fff;
982         SET_QC();
983     }
984     high = x >> 32;
985     if (high != (int16_t)high) {
986         high = (high >> 31) ^ 0x7fff;
987         SET_QC();
988     }
989     return (uint16_t)low | (high << 16);
990 }
991
992 uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
993 {
994     if (x > 0xffffffffu) {
995         SET_QC();
996         return 0xffffffffu;
997     }
998     return x;
999 }
1000
1001 uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
1002 {
1003     if ((int64_t)x != (int32_t)x) {
1004         SET_QC();
1005         return (x >> 63) ^ 0x7fffffff;
1006     }
1007     return x;
1008 }
1009
1010 uint64_t HELPER(neon_widen_u8)(uint32_t x)
1011 {
1012     uint64_t tmp;
1013     uint64_t ret;
1014     ret = (uint8_t)x;
1015     tmp = (uint8_t)(x >> 8);
1016     ret |= tmp << 16;
1017     tmp = (uint8_t)(x >> 16);
1018     ret |= tmp << 32;
1019     tmp = (uint8_t)(x >> 24);
1020     ret |= tmp << 48;
1021     return ret;
1022 }
1023
1024 uint64_t HELPER(neon_widen_s8)(uint32_t x)
1025 {
1026     uint64_t tmp;
1027     uint64_t ret;
1028     ret = (uint16_t)(int8_t)x;
1029     tmp = (uint16_t)(int8_t)(x >> 8);
1030     ret |= tmp << 16;
1031     tmp = (uint16_t)(int8_t)(x >> 16);
1032     ret |= tmp << 32;
1033     tmp = (uint16_t)(int8_t)(x >> 24);
1034     ret |= tmp << 48;
1035     return ret;
1036 }
1037
1038 uint64_t HELPER(neon_widen_u16)(uint32_t x)
1039 {
1040     uint64_t high = (uint16_t)(x >> 16);
1041     return ((uint16_t)x) | (high << 32);
1042 }
1043
1044 uint64_t HELPER(neon_widen_s16)(uint32_t x)
1045 {
1046     uint64_t high = (int16_t)(x >> 16);
1047     return ((uint32_t)(int16_t)x) | (high << 32);
1048 }
1049
1050 uint64_t HELPER(neon_addl_u16)(uint64_t a, uint64_t b)
1051 {
1052     uint64_t mask;
1053     mask = (a ^ b) & 0x8000800080008000ull;
1054     a &= ~0x8000800080008000ull;
1055     b &= ~0x8000800080008000ull;
1056     return (a + b) ^ mask;
1057 }
1058
1059 uint64_t HELPER(neon_addl_u32)(uint64_t a, uint64_t b)
1060 {
1061     uint64_t mask;
1062     mask = (a ^ b) & 0x8000000080000000ull;
1063     a &= ~0x8000000080000000ull;
1064     b &= ~0x8000000080000000ull;
1065     return (a + b) ^ mask;
1066 }
1067
1068 uint64_t HELPER(neon_paddl_u16)(uint64_t a, uint64_t b)
1069 {
1070     uint64_t tmp;
1071     uint64_t tmp2;
1072
1073     tmp = a & 0x0000ffff0000ffffull;
1074     tmp += (a >> 16) & 0x0000ffff0000ffffull;
1075     tmp2 = b & 0xffff0000ffff0000ull;
1076     tmp2 += (b << 16) & 0xffff0000ffff0000ull;
1077     return    ( tmp         & 0xffff)
1078             | ((tmp  >> 16) & 0xffff0000ull)
1079             | ((tmp2 << 16) & 0xffff00000000ull)
1080             | ( tmp2        & 0xffff000000000000ull);
1081 }
1082
1083 uint64_t HELPER(neon_paddl_u32)(uint64_t a, uint64_t b)
1084 {
1085     uint32_t low = a + (a >> 32);
1086     uint32_t high = b + (b >> 32);
1087     return low + ((uint64_t)high << 32);
1088 }
1089
1090 uint64_t HELPER(neon_subl_u16)(uint64_t a, uint64_t b)
1091 {
1092     uint64_t mask;
1093     mask = (a ^ ~b) & 0x8000800080008000ull;
1094     a |= 0x8000800080008000ull;
1095     b &= ~0x8000800080008000ull;
1096     return (a - b) ^ mask;
1097 }
1098
1099 uint64_t HELPER(neon_subl_u32)(uint64_t a, uint64_t b)
1100 {
1101     uint64_t mask;
1102     mask = (a ^ ~b) & 0x8000000080000000ull;
1103     a |= 0x8000000080000000ull;
1104     b &= ~0x8000000080000000ull;
1105     return (a - b) ^ mask;
1106 }
1107
1108 uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b)
1109 {
1110     uint32_t x, y;
1111     uint32_t low, high;
1112
1113     x = a;
1114     y = b;
1115     low = x + y;
1116     if (((low ^ x) & SIGNBIT) && !((x ^ y) & SIGNBIT)) {
1117         SET_QC();
1118         low = ((int32_t)x >> 31) ^ ~SIGNBIT;
1119     }
1120     x = a >> 32;
1121     y = b >> 32;
1122     high = x + y;
1123     if (((high ^ x) & SIGNBIT) && !((x ^ y) & SIGNBIT)) {
1124         SET_QC();
1125         high = ((int32_t)x >> 31) ^ ~SIGNBIT;
1126     }
1127     return low | ((uint64_t)high << 32);
1128 }
1129
1130 uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b)
1131 {
1132     uint64_t result;
1133
1134     result = a + b;
1135     if (((result ^ a) & SIGNBIT64) && !((a ^ b) & SIGNBIT64)) {
1136         SET_QC();
1137         result = ((int64_t)a >> 63) ^ ~SIGNBIT64;
1138     }
1139     return result;
1140 }
1141
1142 #define DO_ABD(dest, x, y, type) do { \
1143     type tmp_x = x; \
1144     type tmp_y = y; \
1145     dest = ((tmp_x > tmp_y) ? tmp_x - tmp_y : tmp_y - tmp_x); \
1146     } while(0)
1147
1148 uint64_t HELPER(neon_abdl_u16)(uint32_t a, uint32_t b)
1149 {
1150     uint64_t tmp;
1151     uint64_t result;
1152     DO_ABD(result, a, b, uint8_t);
1153     DO_ABD(tmp, a >> 8, b >> 8, uint8_t);
1154     result |= tmp << 16;
1155     DO_ABD(tmp, a >> 16, b >> 16, uint8_t);
1156     result |= tmp << 32;
1157     DO_ABD(tmp, a >> 24, b >> 24, uint8_t);
1158     result |= tmp << 48;
1159     return result;
1160 }
1161
1162 uint64_t HELPER(neon_abdl_s16)(uint32_t a, uint32_t b)
1163 {
1164     uint64_t tmp;
1165     uint64_t result;
1166     DO_ABD(result, a, b, int8_t);
1167     DO_ABD(tmp, a >> 8, b >> 8, int8_t);
1168     result |= tmp << 16;
1169     DO_ABD(tmp, a >> 16, b >> 16, int8_t);
1170     result |= tmp << 32;
1171     DO_ABD(tmp, a >> 24, b >> 24, int8_t);
1172     result |= tmp << 48;
1173     return result;
1174 }
1175
1176 uint64_t HELPER(neon_abdl_u32)(uint32_t a, uint32_t b)
1177 {
1178     uint64_t tmp;
1179     uint64_t result;
1180     DO_ABD(result, a, b, uint16_t);
1181     DO_ABD(tmp, a >> 16, b >> 16, uint16_t);
1182     return result | (tmp << 32);
1183 }
1184
1185 uint64_t HELPER(neon_abdl_s32)(uint32_t a, uint32_t b)
1186 {
1187     uint64_t tmp;
1188     uint64_t result;
1189     DO_ABD(result, a, b, int16_t);
1190     DO_ABD(tmp, a >> 16, b >> 16, int16_t);
1191     return result | (tmp << 32);
1192 }
1193
1194 uint64_t HELPER(neon_abdl_u64)(uint32_t a, uint32_t b)
1195 {
1196     uint64_t result;
1197     DO_ABD(result, a, b, uint32_t);
1198     return result;
1199 }
1200
1201 uint64_t HELPER(neon_abdl_s64)(uint32_t a, uint32_t b)
1202 {
1203     uint64_t result;
1204     DO_ABD(result, a, b, int32_t);
1205     return result;
1206 }
1207 #undef DO_ABD
1208
1209 /* Widening multiply. Named type is the source type.  */
1210 #define DO_MULL(dest, x, y, type1, type2) do { \
1211     type1 tmp_x = x; \
1212     type1 tmp_y = y; \
1213     dest = (type2)((type2)tmp_x * (type2)tmp_y); \
1214     } while(0)
1215
1216 uint64_t HELPER(neon_mull_u8)(uint32_t a, uint32_t b)
1217 {
1218     uint64_t tmp;
1219     uint64_t result;
1220
1221     DO_MULL(result, a, b, uint8_t, uint16_t);
1222     DO_MULL(tmp, a >> 8, b >> 8, uint8_t, uint16_t);
1223     result |= tmp << 16;
1224     DO_MULL(tmp, a >> 16, b >> 16, uint8_t, uint16_t);
1225     result |= tmp << 32;
1226     DO_MULL(tmp, a >> 24, b >> 24, uint8_t, uint16_t);
1227     result |= tmp << 48;
1228     return result;
1229 }
1230
1231 uint64_t HELPER(neon_mull_s8)(uint32_t a, uint32_t b)
1232 {
1233     uint64_t tmp;
1234     uint64_t result;
1235
1236     DO_MULL(result, a, b, int8_t, uint16_t);
1237     DO_MULL(tmp, a >> 8, b >> 8, int8_t, uint16_t);
1238     result |= tmp << 16;
1239     DO_MULL(tmp, a >> 16, b >> 16, int8_t, uint16_t);
1240     result |= tmp << 32;
1241     DO_MULL(tmp, a >> 24, b >> 24, int8_t, uint16_t);
1242     result |= tmp << 48;
1243     return result;
1244 }
1245
1246 uint64_t HELPER(neon_mull_u16)(uint32_t a, uint32_t b)
1247 {
1248     uint64_t tmp;
1249     uint64_t result;
1250
1251     DO_MULL(result, a, b, uint16_t, uint32_t);
1252     DO_MULL(tmp, a >> 16, b >> 16, uint16_t, uint32_t);
1253     return result | (tmp << 32);
1254 }
1255
1256 uint64_t HELPER(neon_mull_s16)(uint32_t a, uint32_t b)
1257 {
1258     uint64_t tmp;
1259     uint64_t result;
1260
1261     DO_MULL(result, a, b, int16_t, uint32_t);
1262     DO_MULL(tmp, a >> 16, b >> 16, int16_t, uint32_t);
1263     return result | (tmp << 32);
1264 }
1265
1266 uint64_t HELPER(neon_negl_u16)(uint64_t x)
1267 {
1268     uint16_t tmp;
1269     uint64_t result;
1270     result = (uint16_t)-x;
1271     tmp = -(x >> 16);
1272     result |= (uint64_t)tmp << 16;
1273     tmp = -(x >> 32);
1274     result |= (uint64_t)tmp << 32;
1275     tmp = -(x >> 48);
1276     result |= (uint64_t)tmp << 48;
1277     return result;
1278 }
1279
1280 #include <stdio.h>
1281 uint64_t HELPER(neon_negl_u32)(uint64_t x)
1282 {
1283     uint32_t low = -x;
1284     uint32_t high = -(x >> 32);
1285     return low | ((uint64_t)high << 32);
1286 }
1287
1288 /* FIXME:  There should be a native op for this.  */
1289 uint64_t HELPER(neon_negl_u64)(uint64_t x)
1290 {
1291     return -x;
1292 }
1293
1294 /* Saturnating sign manuipulation.  */
1295 /* ??? Make these use NEON_VOP1 */
1296 #define DO_QABS8(x) do { \
1297     if (x == (int8_t)0x80) { \
1298         x = 0x7f; \
1299         SET_QC(); \
1300     } else if (x < 0) { \
1301         x = -x; \
1302     }} while (0)
1303 uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x)
1304 {
1305     neon_s8 vec;
1306     NEON_UNPACK(neon_s8, vec, x);
1307     DO_QABS8(vec.v1);
1308     DO_QABS8(vec.v2);
1309     DO_QABS8(vec.v3);
1310     DO_QABS8(vec.v4);
1311     NEON_PACK(neon_s8, x, vec);
1312     return x;
1313 }
1314 #undef DO_QABS8
1315
1316 #define DO_QNEG8(x) do { \
1317     if (x == (int8_t)0x80) { \
1318         x = 0x7f; \
1319         SET_QC(); \
1320     } else { \
1321         x = -x; \
1322     }} while (0)
1323 uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x)
1324 {
1325     neon_s8 vec;
1326     NEON_UNPACK(neon_s8, vec, x);
1327     DO_QNEG8(vec.v1);
1328     DO_QNEG8(vec.v2);
1329     DO_QNEG8(vec.v3);
1330     DO_QNEG8(vec.v4);
1331     NEON_PACK(neon_s8, x, vec);
1332     return x;
1333 }
1334 #undef DO_QNEG8
1335
1336 #define DO_QABS16(x) do { \
1337     if (x == (int16_t)0x8000) { \
1338         x = 0x7fff; \
1339         SET_QC(); \
1340     } else if (x < 0) { \
1341         x = -x; \
1342     }} while (0)
1343 uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x)
1344 {
1345     neon_s16 vec;
1346     NEON_UNPACK(neon_s16, vec, x);
1347     DO_QABS16(vec.v1);
1348     DO_QABS16(vec.v2);
1349     NEON_PACK(neon_s16, x, vec);
1350     return x;
1351 }
1352 #undef DO_QABS16
1353
1354 #define DO_QNEG16(x) do { \
1355     if (x == (int16_t)0x8000) { \
1356         x = 0x7fff; \
1357         SET_QC(); \
1358     } else { \
1359         x = -x; \
1360     }} while (0)
1361 uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x)
1362 {
1363     neon_s16 vec;
1364     NEON_UNPACK(neon_s16, vec, x);
1365     DO_QNEG16(vec.v1);
1366     DO_QNEG16(vec.v2);
1367     NEON_PACK(neon_s16, x, vec);
1368     return x;
1369 }
1370 #undef DO_QNEG16
1371
1372 uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x)
1373 {
1374     if (x == SIGNBIT) {
1375         SET_QC();
1376         x = ~SIGNBIT;
1377     } else if ((int32_t)x < 0) {
1378         x = -x;
1379     }
1380     return x;
1381 }
1382
1383 uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x)
1384 {
1385     if (x == SIGNBIT) {
1386         SET_QC();
1387         x = ~SIGNBIT;
1388     } else {
1389         x = -x;
1390     }
1391     return x;
1392 }
1393
1394 /* NEON Float helpers.  */
1395 uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b)
1396 {
1397     float32 f0 = vfp_itos(a);
1398     float32 f1 = vfp_itos(b);
1399     return (float32_compare_quiet(f0, f1, NFS) == -1) ? a : b;
1400 }
1401
1402 uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b)
1403 {
1404     float32 f0 = vfp_itos(a);
1405     float32 f1 = vfp_itos(b);
1406     return (float32_compare_quiet(f0, f1, NFS) == 1) ? a : b;
1407 }
1408
1409 uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b)
1410 {
1411     float32 f0 = vfp_itos(a);
1412     float32 f1 = vfp_itos(b);
1413     return vfp_stoi((float32_compare_quiet(f0, f1, NFS) == 1)
1414                     ? float32_sub(f0, f1, NFS)
1415                     : float32_sub(f1, f0, NFS));
1416 }
1417
1418 uint32_t HELPER(neon_add_f32)(uint32_t a, uint32_t b)
1419 {
1420     return vfp_stoi(float32_add(vfp_itos(a), vfp_itos(b), NFS));
1421 }
1422
1423 uint32_t HELPER(neon_sub_f32)(uint32_t a, uint32_t b)
1424 {
1425     return vfp_stoi(float32_sub(vfp_itos(a), vfp_itos(b), NFS));
1426 }
1427
1428 uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b)
1429 {
1430     return vfp_stoi(float32_mul(vfp_itos(a), vfp_itos(b), NFS));
1431 }
1432
1433 /* Floating point comparisons produce an integer result.  */
1434 #define NEON_VOP_FCMP(name, cmp) \
1435 uint32_t HELPER(neon_##name)(uint32_t a, uint32_t b) \
1436 { \
1437     if (float32_compare_quiet(vfp_itos(a), vfp_itos(b), NFS) cmp 0) \
1438         return ~0; \
1439     else \
1440         return 0; \
1441 }
1442
1443 NEON_VOP_FCMP(ceq_f32, ==)
1444 NEON_VOP_FCMP(cge_f32, >=)
1445 NEON_VOP_FCMP(cgt_f32, >)
1446
1447 uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b)
1448 {
1449     float32 f0 = float32_abs(vfp_itos(a));
1450     float32 f1 = float32_abs(vfp_itos(b));
1451     return (float32_compare_quiet(f0, f1,NFS) >= 0) ? ~0 : 0;
1452 }
1453
1454 uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b)
1455 {
1456     float32 f0 = float32_abs(vfp_itos(a));
1457     float32 f1 = float32_abs(vfp_itos(b));
1458     return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0;
1459 }
This page took 0.10113 seconds and 4 git commands to generate.