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