Statistics
| Branch: | Revision:

root / target-arm / op_neon.h @ 8f8e3aa4

History | View | Annotate | Download (34.6 kB)

1 9ee6e8bb pbrook
/*
2 9ee6e8bb pbrook
 * ARM NEON vector operations.
3 9ee6e8bb pbrook
 *
4 9ee6e8bb pbrook
 * Copyright (c) 2007 CodeSourcery.
5 9ee6e8bb pbrook
 * Written by Paul Brook
6 9ee6e8bb pbrook
 *
7 9ee6e8bb pbrook
 * This code is licenced under the GPL.
8 9ee6e8bb pbrook
 */
9 9ee6e8bb pbrook
/* Note that for NEON an "l" prefix means it is a wide operation, unlike
10 9ee6e8bb pbrook
   scalar arm ops where it means a word size operation.  */
11 9ee6e8bb pbrook
12 1497c961 pbrook
#define SIGNBIT (uint32_t)0x80000000
13 9ee6e8bb pbrook
/* ??? NEON ops should probably have their own float status.  */
14 9ee6e8bb pbrook
#define NFS &env->vfp.fp_status
15 9ee6e8bb pbrook
#define NEON_OP(name) void OPPROTO op_neon_##name (void)
16 9ee6e8bb pbrook
17 4373f3ce pbrook
/* Helper routines to perform bitwise copies between float and int.  */
18 4373f3ce pbrook
static inline float32 vfp_itos(uint32_t i)
19 4373f3ce pbrook
{
20 4373f3ce pbrook
    union {
21 4373f3ce pbrook
        uint32_t i;
22 4373f3ce pbrook
        float32 s;
23 4373f3ce pbrook
    } v;
24 4373f3ce pbrook
25 4373f3ce pbrook
    v.i = i;
26 4373f3ce pbrook
    return v.s;
27 4373f3ce pbrook
}
28 4373f3ce pbrook
29 4373f3ce pbrook
static inline uint32_t vfp_stoi(float32 s)
30 4373f3ce pbrook
{
31 4373f3ce pbrook
    union {
32 4373f3ce pbrook
        uint32_t i;
33 4373f3ce pbrook
        float32 s;
34 4373f3ce pbrook
    } v;
35 4373f3ce pbrook
36 4373f3ce pbrook
    v.s = s;
37 4373f3ce pbrook
    return v.i;
38 4373f3ce pbrook
}
39 4373f3ce pbrook
40 9ee6e8bb pbrook
NEON_OP(getreg_T0)
41 9ee6e8bb pbrook
{
42 9ee6e8bb pbrook
    T0 = *(uint32_t *)((char *) env + PARAM1);
43 9ee6e8bb pbrook
}
44 9ee6e8bb pbrook
45 9ee6e8bb pbrook
NEON_OP(getreg_T1)
46 9ee6e8bb pbrook
{
47 9ee6e8bb pbrook
    T1 = *(uint32_t *)((char *) env + PARAM1);
48 9ee6e8bb pbrook
}
49 9ee6e8bb pbrook
50 9ee6e8bb pbrook
NEON_OP(setreg_T0)
51 9ee6e8bb pbrook
{
52 9ee6e8bb pbrook
    *(uint32_t *)((char *) env + PARAM1) = T0;
53 9ee6e8bb pbrook
}
54 9ee6e8bb pbrook
55 9ee6e8bb pbrook
NEON_OP(setreg_T1)
56 9ee6e8bb pbrook
{
57 9ee6e8bb pbrook
    *(uint32_t *)((char *) env + PARAM1) = T1;
58 9ee6e8bb pbrook
}
59 9ee6e8bb pbrook
60 9ee6e8bb pbrook
#define NEON_TYPE1(name, type) \
61 9ee6e8bb pbrook
typedef struct \
62 9ee6e8bb pbrook
{ \
63 9ee6e8bb pbrook
    type v1; \
64 9ee6e8bb pbrook
} neon_##name;
65 9ee6e8bb pbrook
#ifdef WORDS_BIGENDIAN
66 9ee6e8bb pbrook
#define NEON_TYPE2(name, type) \
67 9ee6e8bb pbrook
typedef struct \
68 9ee6e8bb pbrook
{ \
69 9ee6e8bb pbrook
    type v2; \
70 9ee6e8bb pbrook
    type v1; \
71 9ee6e8bb pbrook
} neon_##name;
72 9ee6e8bb pbrook
#define NEON_TYPE4(name, type) \
73 9ee6e8bb pbrook
typedef struct \
74 9ee6e8bb pbrook
{ \
75 9ee6e8bb pbrook
    type v4; \
76 9ee6e8bb pbrook
    type v3; \
77 9ee6e8bb pbrook
    type v2; \
78 9ee6e8bb pbrook
    type v1; \
79 9ee6e8bb pbrook
} neon_##name;
80 9ee6e8bb pbrook
#else
81 9ee6e8bb pbrook
#define NEON_TYPE2(name, type) \
82 9ee6e8bb pbrook
typedef struct \
83 9ee6e8bb pbrook
{ \
84 9ee6e8bb pbrook
    type v1; \
85 9ee6e8bb pbrook
    type v2; \
86 9ee6e8bb pbrook
} neon_##name;
87 9ee6e8bb pbrook
#define NEON_TYPE4(name, type) \
88 9ee6e8bb pbrook
typedef struct \
89 9ee6e8bb pbrook
{ \
90 9ee6e8bb pbrook
    type v1; \
91 9ee6e8bb pbrook
    type v2; \
92 9ee6e8bb pbrook
    type v3; \
93 9ee6e8bb pbrook
    type v4; \
94 9ee6e8bb pbrook
} neon_##name;
95 9ee6e8bb pbrook
#endif
96 9ee6e8bb pbrook
97 9ee6e8bb pbrook
NEON_TYPE4(s8, int8_t)
98 9ee6e8bb pbrook
NEON_TYPE4(u8, uint8_t)
99 9ee6e8bb pbrook
NEON_TYPE2(s16, int16_t)
100 9ee6e8bb pbrook
NEON_TYPE2(u16, uint16_t)
101 9ee6e8bb pbrook
NEON_TYPE1(s32, int32_t)
102 9ee6e8bb pbrook
NEON_TYPE1(u32, uint32_t)
103 9ee6e8bb pbrook
#undef NEON_TYPE4
104 9ee6e8bb pbrook
#undef NEON_TYPE2
105 9ee6e8bb pbrook
#undef NEON_TYPE1
106 9ee6e8bb pbrook
107 9ee6e8bb pbrook
/* Copy from a uint32_t to a vector structure type.  */
108 9ee6e8bb pbrook
#define NEON_UNPACK(vtype, dest, val) do { \
109 9ee6e8bb pbrook
    union { \
110 9ee6e8bb pbrook
        vtype v; \
111 9ee6e8bb pbrook
        uint32_t i; \
112 9ee6e8bb pbrook
    } conv_u; \
113 9ee6e8bb pbrook
    conv_u.i = (val); \
114 9ee6e8bb pbrook
    dest = conv_u.v; \
115 9ee6e8bb pbrook
    } while(0)
116 9ee6e8bb pbrook
117 9ee6e8bb pbrook
/* Copy from a vector structure type to a uint32_t.  */
118 9ee6e8bb pbrook
#define NEON_PACK(vtype, dest, val) do { \
119 9ee6e8bb pbrook
    union { \
120 9ee6e8bb pbrook
        vtype v; \
121 9ee6e8bb pbrook
        uint32_t i; \
122 9ee6e8bb pbrook
    } conv_u; \
123 9ee6e8bb pbrook
    conv_u.v = (val); \
124 9ee6e8bb pbrook
    dest = conv_u.i; \
125 9ee6e8bb pbrook
    } while(0)
126 9ee6e8bb pbrook
127 9ee6e8bb pbrook
#define NEON_DO1 \
128 9ee6e8bb pbrook
    NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1);
129 9ee6e8bb pbrook
#define NEON_DO2 \
130 9ee6e8bb pbrook
    NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1); \
131 9ee6e8bb pbrook
    NEON_FN(vdest.v2, vsrc1.v2, vsrc2.v2);
132 9ee6e8bb pbrook
#define NEON_DO4 \
133 9ee6e8bb pbrook
    NEON_FN(vdest.v1, vsrc1.v1, vsrc2.v1); \
134 9ee6e8bb pbrook
    NEON_FN(vdest.v2, vsrc1.v2, vsrc2.v2); \
135 9ee6e8bb pbrook
    NEON_FN(vdest.v3, vsrc1.v3, vsrc2.v3); \
136 9ee6e8bb pbrook
    NEON_FN(vdest.v4, vsrc1.v4, vsrc2.v4);
137 9ee6e8bb pbrook
138 9ee6e8bb pbrook
#define NEON_VOP(name, vtype, n) \
139 9ee6e8bb pbrook
NEON_OP(name) \
140 9ee6e8bb pbrook
{ \
141 9ee6e8bb pbrook
    vtype vsrc1; \
142 9ee6e8bb pbrook
    vtype vsrc2; \
143 9ee6e8bb pbrook
    vtype vdest; \
144 9ee6e8bb pbrook
    NEON_UNPACK(vtype, vsrc1, T0); \
145 9ee6e8bb pbrook
    NEON_UNPACK(vtype, vsrc2, T1); \
146 9ee6e8bb pbrook
    NEON_DO##n; \
147 9ee6e8bb pbrook
    NEON_PACK(vtype, T0, vdest); \
148 9ee6e8bb pbrook
    FORCE_RET(); \
149 9ee6e8bb pbrook
}
150 9ee6e8bb pbrook
151 9ee6e8bb pbrook
#define NEON_VOP1(name, vtype, n) \
152 9ee6e8bb pbrook
NEON_OP(name) \
153 9ee6e8bb pbrook
{ \
154 9ee6e8bb pbrook
    vtype vsrc1; \
155 9ee6e8bb pbrook
    vtype vdest; \
156 9ee6e8bb pbrook
    NEON_UNPACK(vtype, vsrc1, T0); \
157 9ee6e8bb pbrook
    NEON_DO##n; \
158 9ee6e8bb pbrook
    NEON_PACK(vtype, T0, vdest); \
159 9ee6e8bb pbrook
    FORCE_RET(); \
160 9ee6e8bb pbrook
}
161 9ee6e8bb pbrook
162 9ee6e8bb pbrook
/* Pairwise operations.  */
163 9ee6e8bb pbrook
/* For 32-bit elements each segment only contains a single element, so
164 9ee6e8bb pbrook
   the elementwise and pairwise operations are the same.  */
165 9ee6e8bb pbrook
#define NEON_PDO2 \
166 9ee6e8bb pbrook
    NEON_FN(vdest.v1, vsrc1.v1, vsrc1.v2); \
167 9ee6e8bb pbrook
    NEON_FN(vdest.v2, vsrc2.v1, vsrc2.v2);
168 9ee6e8bb pbrook
#define NEON_PDO4 \
169 9ee6e8bb pbrook
    NEON_FN(vdest.v1, vsrc1.v1, vsrc1.v2); \
170 9ee6e8bb pbrook
    NEON_FN(vdest.v2, vsrc1.v3, vsrc1.v4); \
171 9ee6e8bb pbrook
    NEON_FN(vdest.v3, vsrc2.v1, vsrc2.v2); \
172 9ee6e8bb pbrook
    NEON_FN(vdest.v4, vsrc2.v3, vsrc2.v4); \
173 9ee6e8bb pbrook
174 9ee6e8bb pbrook
#define NEON_POP(name, vtype, n) \
175 9ee6e8bb pbrook
NEON_OP(name) \
176 9ee6e8bb pbrook
{ \
177 9ee6e8bb pbrook
    vtype vsrc1; \
178 9ee6e8bb pbrook
    vtype vsrc2; \
179 9ee6e8bb pbrook
    vtype vdest; \
180 9ee6e8bb pbrook
    NEON_UNPACK(vtype, vsrc1, T0); \
181 9ee6e8bb pbrook
    NEON_UNPACK(vtype, vsrc2, T1); \
182 9ee6e8bb pbrook
    NEON_PDO##n; \
183 9ee6e8bb pbrook
    NEON_PACK(vtype, T0, vdest); \
184 9ee6e8bb pbrook
    FORCE_RET(); \
185 9ee6e8bb pbrook
}
186 9ee6e8bb pbrook
187 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 + src2) >> 1
188 9ee6e8bb pbrook
NEON_VOP(hadd_s8, neon_s8, 4)
189 9ee6e8bb pbrook
NEON_VOP(hadd_u8, neon_u8, 4)
190 9ee6e8bb pbrook
NEON_VOP(hadd_s16, neon_s16, 2)
191 9ee6e8bb pbrook
NEON_VOP(hadd_u16, neon_u16, 2)
192 9ee6e8bb pbrook
#undef NEON_FN
193 9ee6e8bb pbrook
194 9ee6e8bb pbrook
NEON_OP(hadd_s32)
195 9ee6e8bb pbrook
{
196 9ee6e8bb pbrook
    int32_t src1 = T0;
197 9ee6e8bb pbrook
    int32_t src2 = T1;
198 9ee6e8bb pbrook
    int32_t dest;
199 9ee6e8bb pbrook
200 9ee6e8bb pbrook
    dest = (src1 >> 1) + (src2 >> 1);
201 9ee6e8bb pbrook
    if (src1 & src2 & 1)
202 9ee6e8bb pbrook
        dest++;
203 9ee6e8bb pbrook
    T0 = dest;
204 9ee6e8bb pbrook
    FORCE_RET();
205 9ee6e8bb pbrook
}
206 9ee6e8bb pbrook
207 9ee6e8bb pbrook
NEON_OP(hadd_u32)
208 9ee6e8bb pbrook
{
209 9ee6e8bb pbrook
    uint32_t src1 = T0;
210 9ee6e8bb pbrook
    uint32_t src2 = T1;
211 9ee6e8bb pbrook
    uint32_t dest;
212 9ee6e8bb pbrook
213 9ee6e8bb pbrook
    dest = (src1 >> 1) + (src2 >> 1);
214 9ee6e8bb pbrook
    if (src1 & src2 & 1)
215 9ee6e8bb pbrook
        dest++;
216 9ee6e8bb pbrook
    T0 = dest;
217 9ee6e8bb pbrook
    FORCE_RET();
218 9ee6e8bb pbrook
}
219 9ee6e8bb pbrook
220 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 + src2 + 1) >> 1
221 9ee6e8bb pbrook
NEON_VOP(rhadd_s8, neon_s8, 4)
222 9ee6e8bb pbrook
NEON_VOP(rhadd_u8, neon_u8, 4)
223 9ee6e8bb pbrook
NEON_VOP(rhadd_s16, neon_s16, 2)
224 9ee6e8bb pbrook
NEON_VOP(rhadd_u16, neon_u16, 2)
225 9ee6e8bb pbrook
#undef NEON_FN
226 9ee6e8bb pbrook
227 9ee6e8bb pbrook
NEON_OP(rhadd_s32)
228 9ee6e8bb pbrook
{
229 9ee6e8bb pbrook
    int32_t src1 = T0;
230 9ee6e8bb pbrook
    int32_t src2 = T1;
231 9ee6e8bb pbrook
    int32_t dest;
232 9ee6e8bb pbrook
233 9ee6e8bb pbrook
    dest = (src1 >> 1) + (src2 >> 1);
234 9ee6e8bb pbrook
    if ((src1 | src2) & 1)
235 9ee6e8bb pbrook
        dest++;
236 9ee6e8bb pbrook
    T0 = dest;
237 9ee6e8bb pbrook
    FORCE_RET();
238 9ee6e8bb pbrook
}
239 9ee6e8bb pbrook
240 9ee6e8bb pbrook
NEON_OP(rhadd_u32)
241 9ee6e8bb pbrook
{
242 9ee6e8bb pbrook
    uint32_t src1 = T0;
243 9ee6e8bb pbrook
    uint32_t src2 = T1;
244 9ee6e8bb pbrook
    uint32_t dest;
245 9ee6e8bb pbrook
246 9ee6e8bb pbrook
    dest = (src1 >> 1) + (src2 >> 1);
247 9ee6e8bb pbrook
    if ((src1 | src2) & 1)
248 9ee6e8bb pbrook
        dest++;
249 9ee6e8bb pbrook
    T0 = dest;
250 9ee6e8bb pbrook
    FORCE_RET();
251 9ee6e8bb pbrook
}
252 9ee6e8bb pbrook
253 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 - src2) >> 1
254 9ee6e8bb pbrook
NEON_VOP(hsub_s8, neon_s8, 4)
255 9ee6e8bb pbrook
NEON_VOP(hsub_u8, neon_u8, 4)
256 9ee6e8bb pbrook
NEON_VOP(hsub_s16, neon_s16, 2)
257 9ee6e8bb pbrook
NEON_VOP(hsub_u16, neon_u16, 2)
258 9ee6e8bb pbrook
#undef NEON_FN
259 9ee6e8bb pbrook
260 9ee6e8bb pbrook
NEON_OP(hsub_s32)
261 9ee6e8bb pbrook
{
262 9ee6e8bb pbrook
    int32_t src1 = T0;
263 9ee6e8bb pbrook
    int32_t src2 = T1;
264 9ee6e8bb pbrook
    int32_t dest;
265 9ee6e8bb pbrook
266 9ee6e8bb pbrook
    dest = (src1 >> 1) - (src2 >> 1);
267 9ee6e8bb pbrook
    if ((~src1) & src2 & 1)
268 9ee6e8bb pbrook
        dest--;
269 9ee6e8bb pbrook
    T0 = dest;
270 9ee6e8bb pbrook
    FORCE_RET();
271 9ee6e8bb pbrook
}
272 9ee6e8bb pbrook
273 9ee6e8bb pbrook
NEON_OP(hsub_u32)
274 9ee6e8bb pbrook
{
275 9ee6e8bb pbrook
    uint32_t src1 = T0;
276 9ee6e8bb pbrook
    uint32_t src2 = T1;
277 9ee6e8bb pbrook
    uint32_t dest;
278 9ee6e8bb pbrook
279 9ee6e8bb pbrook
    dest = (src1 >> 1) - (src2 >> 1);
280 9ee6e8bb pbrook
    if ((~src1) & src2 & 1)
281 9ee6e8bb pbrook
        dest--;
282 9ee6e8bb pbrook
    T0 = dest;
283 9ee6e8bb pbrook
    FORCE_RET();
284 9ee6e8bb pbrook
}
285 9ee6e8bb pbrook
286 9ee6e8bb pbrook
#define NEON_USAT(dest, src1, src2, type) do { \
287 9ee6e8bb pbrook
    uint32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
288 9ee6e8bb pbrook
    if (tmp != (type)tmp) { \
289 9ee6e8bb pbrook
        env->QF = 1; \
290 9ee6e8bb pbrook
        dest = ~0; \
291 9ee6e8bb pbrook
    } else { \
292 9ee6e8bb pbrook
        dest = tmp; \
293 9ee6e8bb pbrook
    }} while(0)
294 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
295 9ee6e8bb pbrook
NEON_VOP(qadd_u8, neon_u8, 4)
296 9ee6e8bb pbrook
#undef NEON_FN
297 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
298 9ee6e8bb pbrook
NEON_VOP(qadd_u16, neon_u16, 2)
299 9ee6e8bb pbrook
#undef NEON_FN
300 9ee6e8bb pbrook
#undef NEON_USAT
301 9ee6e8bb pbrook
302 9ee6e8bb pbrook
#define NEON_SSAT(dest, src1, src2, type) do { \
303 9ee6e8bb pbrook
    int32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
304 9ee6e8bb pbrook
    if (tmp != (type)tmp) { \
305 9ee6e8bb pbrook
        env->QF = 1; \
306 9ee6e8bb pbrook
        if (src2 > 0) { \
307 9ee6e8bb pbrook
            tmp = (1 << (sizeof(type) * 8 - 1)) - 1; \
308 9ee6e8bb pbrook
        } else { \
309 9ee6e8bb pbrook
            tmp = 1 << (sizeof(type) * 8 - 1); \
310 9ee6e8bb pbrook
        } \
311 9ee6e8bb pbrook
    } \
312 9ee6e8bb pbrook
    dest = tmp; \
313 9ee6e8bb pbrook
    } while(0)
314 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
315 9ee6e8bb pbrook
NEON_VOP(qadd_s8, neon_s8, 4)
316 9ee6e8bb pbrook
#undef NEON_FN
317 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
318 9ee6e8bb pbrook
NEON_VOP(qadd_s16, neon_s16, 2)
319 9ee6e8bb pbrook
#undef NEON_FN
320 9ee6e8bb pbrook
#undef NEON_SSAT
321 9ee6e8bb pbrook
322 9ee6e8bb pbrook
#define NEON_USAT(dest, src1, src2, type) do { \
323 9ee6e8bb pbrook
    uint32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
324 9ee6e8bb pbrook
    if (tmp != (type)tmp) { \
325 9ee6e8bb pbrook
        env->QF = 1; \
326 9ee6e8bb pbrook
        dest = 0; \
327 9ee6e8bb pbrook
    } else { \
328 9ee6e8bb pbrook
        dest = tmp; \
329 9ee6e8bb pbrook
    }} while(0)
330 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t)
331 9ee6e8bb pbrook
NEON_VOP(qsub_u8, neon_u8, 4)
332 9ee6e8bb pbrook
#undef NEON_FN
333 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t)
334 9ee6e8bb pbrook
NEON_VOP(qsub_u16, neon_u16, 2)
335 9ee6e8bb pbrook
#undef NEON_FN
336 9ee6e8bb pbrook
#undef NEON_USAT
337 9ee6e8bb pbrook
338 9ee6e8bb pbrook
#define NEON_SSAT(dest, src1, src2, type) do { \
339 9ee6e8bb pbrook
    int32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
340 9ee6e8bb pbrook
    if (tmp != (type)tmp) { \
341 9ee6e8bb pbrook
        env->QF = 1; \
342 9ee6e8bb pbrook
        if (src2 < 0) { \
343 9ee6e8bb pbrook
            tmp = (1 << (sizeof(type) * 8 - 1)) - 1; \
344 9ee6e8bb pbrook
        } else { \
345 9ee6e8bb pbrook
            tmp = 1 << (sizeof(type) * 8 - 1); \
346 9ee6e8bb pbrook
        } \
347 9ee6e8bb pbrook
    } \
348 9ee6e8bb pbrook
    dest = tmp; \
349 9ee6e8bb pbrook
    } while(0)
350 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t)
351 9ee6e8bb pbrook
NEON_VOP(qsub_s8, neon_s8, 4)
352 9ee6e8bb pbrook
#undef NEON_FN
353 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t)
354 9ee6e8bb pbrook
NEON_VOP(qsub_s16, neon_s16, 2)
355 9ee6e8bb pbrook
#undef NEON_FN
356 9ee6e8bb pbrook
#undef NEON_SSAT
357 9ee6e8bb pbrook
358 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? ~0 : 0
359 9ee6e8bb pbrook
NEON_VOP(cgt_s8, neon_s8, 4)
360 9ee6e8bb pbrook
NEON_VOP(cgt_u8, neon_u8, 4)
361 9ee6e8bb pbrook
NEON_VOP(cgt_s16, neon_s16, 2)
362 9ee6e8bb pbrook
NEON_VOP(cgt_u16, neon_u16, 2)
363 9ee6e8bb pbrook
NEON_VOP(cgt_s32, neon_s32, 1)
364 9ee6e8bb pbrook
NEON_VOP(cgt_u32, neon_u32, 1)
365 9ee6e8bb pbrook
#undef NEON_FN
366 9ee6e8bb pbrook
367 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 >= src2) ? ~0 : 0
368 9ee6e8bb pbrook
NEON_VOP(cge_s8, neon_s8, 4)
369 9ee6e8bb pbrook
NEON_VOP(cge_u8, neon_u8, 4)
370 9ee6e8bb pbrook
NEON_VOP(cge_s16, neon_s16, 2)
371 9ee6e8bb pbrook
NEON_VOP(cge_u16, neon_u16, 2)
372 9ee6e8bb pbrook
NEON_VOP(cge_s32, neon_s32, 1)
373 9ee6e8bb pbrook
NEON_VOP(cge_u32, neon_u32, 1)
374 9ee6e8bb pbrook
#undef NEON_FN
375 9ee6e8bb pbrook
376 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
377 9ee6e8bb pbrook
    int8_t tmp; \
378 9ee6e8bb pbrook
    tmp = (int8_t)src2; \
379 9ee6e8bb pbrook
    if (tmp < 0) { \
380 9ee6e8bb pbrook
        dest = src1 >> -tmp; \
381 9ee6e8bb pbrook
    } else { \
382 9ee6e8bb pbrook
        dest = src1 << tmp; \
383 9ee6e8bb pbrook
    }} while (0)
384 9ee6e8bb pbrook
NEON_VOP(shl_s8, neon_s8, 4)
385 9ee6e8bb pbrook
NEON_VOP(shl_u8, neon_u8, 4)
386 9ee6e8bb pbrook
NEON_VOP(shl_s16, neon_s16, 2)
387 9ee6e8bb pbrook
NEON_VOP(shl_u16, neon_u16, 2)
388 9ee6e8bb pbrook
NEON_VOP(shl_s32, neon_s32, 1)
389 9ee6e8bb pbrook
NEON_VOP(shl_u32, neon_u32, 1)
390 9ee6e8bb pbrook
#undef NEON_FN
391 9ee6e8bb pbrook
392 9ee6e8bb pbrook
NEON_OP(shl_u64)
393 9ee6e8bb pbrook
{
394 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
395 9ee6e8bb pbrook
    uint64_t val = T0 | ((uint64_t)T1 << 32);
396 9ee6e8bb pbrook
    if (shift < 0) {
397 9ee6e8bb pbrook
        val >>= -shift;
398 9ee6e8bb pbrook
    } else {
399 9ee6e8bb pbrook
        val <<= shift;
400 9ee6e8bb pbrook
    }
401 9ee6e8bb pbrook
    T0 = val;
402 9ee6e8bb pbrook
    T1 = val >> 32;
403 9ee6e8bb pbrook
    FORCE_RET();
404 9ee6e8bb pbrook
}
405 9ee6e8bb pbrook
406 9ee6e8bb pbrook
NEON_OP(shl_s64)
407 9ee6e8bb pbrook
{
408 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
409 9ee6e8bb pbrook
    int64_t val = T0 | ((uint64_t)T1 << 32);
410 9ee6e8bb pbrook
    if (shift < 0) {
411 9ee6e8bb pbrook
        val >>= -shift;
412 9ee6e8bb pbrook
    } else {
413 9ee6e8bb pbrook
        val <<= shift;
414 9ee6e8bb pbrook
    }
415 9ee6e8bb pbrook
    T0 = val;
416 9ee6e8bb pbrook
    T1 = val >> 32;
417 9ee6e8bb pbrook
    FORCE_RET();
418 9ee6e8bb pbrook
}
419 9ee6e8bb pbrook
420 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
421 9ee6e8bb pbrook
    int8_t tmp; \
422 9ee6e8bb pbrook
    tmp = (int8_t)src1; \
423 9ee6e8bb pbrook
    if (tmp < 0) { \
424 9ee6e8bb pbrook
        dest = (src2 + (1 << (-1 - tmp))) >> -tmp; \
425 9ee6e8bb pbrook
    } else { \
426 9ee6e8bb pbrook
        dest = src2 << tmp; \
427 9ee6e8bb pbrook
    }} while (0)
428 9ee6e8bb pbrook
429 9ee6e8bb pbrook
NEON_VOP(rshl_s8, neon_s8, 4)
430 9ee6e8bb pbrook
NEON_VOP(rshl_u8, neon_u8, 4)
431 9ee6e8bb pbrook
NEON_VOP(rshl_s16, neon_s16, 2)
432 9ee6e8bb pbrook
NEON_VOP(rshl_u16, neon_u16, 2)
433 9ee6e8bb pbrook
NEON_VOP(rshl_s32, neon_s32, 1)
434 9ee6e8bb pbrook
NEON_VOP(rshl_u32, neon_u32, 1)
435 9ee6e8bb pbrook
#undef NEON_FN
436 9ee6e8bb pbrook
437 9ee6e8bb pbrook
NEON_OP(rshl_u64)
438 9ee6e8bb pbrook
{
439 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
440 9ee6e8bb pbrook
    uint64_t val = T0 | ((uint64_t)T1 << 32);
441 9ee6e8bb pbrook
    if (shift < 0) {
442 9ee6e8bb pbrook
        val = (val + ((uint64_t)1 << (-1 - shift))) >> -shift;
443 9ee6e8bb pbrook
        val >>= -shift;
444 9ee6e8bb pbrook
    } else {
445 9ee6e8bb pbrook
        val <<= shift;
446 9ee6e8bb pbrook
    }
447 9ee6e8bb pbrook
    T0 = val;
448 9ee6e8bb pbrook
    T1 = val >> 32;
449 9ee6e8bb pbrook
    FORCE_RET();
450 9ee6e8bb pbrook
}
451 9ee6e8bb pbrook
452 9ee6e8bb pbrook
NEON_OP(rshl_s64)
453 9ee6e8bb pbrook
{
454 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
455 9ee6e8bb pbrook
    int64_t val = T0 | ((uint64_t)T1 << 32);
456 9ee6e8bb pbrook
    if (shift < 0) {
457 9ee6e8bb pbrook
        val = (val + ((int64_t)1 << (-1 - shift))) >> -shift;
458 9ee6e8bb pbrook
    } else {
459 9ee6e8bb pbrook
        val <<= shift;
460 9ee6e8bb pbrook
    }
461 9ee6e8bb pbrook
    T0 = val;
462 9ee6e8bb pbrook
    T1 = val >> 32;
463 9ee6e8bb pbrook
    FORCE_RET();
464 9ee6e8bb pbrook
}
465 9ee6e8bb pbrook
466 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
467 9ee6e8bb pbrook
    int8_t tmp; \
468 9ee6e8bb pbrook
    tmp = (int8_t)src1; \
469 9ee6e8bb pbrook
    if (tmp < 0) { \
470 9ee6e8bb pbrook
        dest = src2 >> -tmp; \
471 9ee6e8bb pbrook
    } else { \
472 9ee6e8bb pbrook
        dest = src2 << tmp; \
473 9ee6e8bb pbrook
        if ((dest >> tmp) != src2) { \
474 9ee6e8bb pbrook
            env->QF = 1; \
475 9ee6e8bb pbrook
            dest = ~0; \
476 9ee6e8bb pbrook
        } \
477 9ee6e8bb pbrook
    }} while (0)
478 9ee6e8bb pbrook
NEON_VOP(qshl_s8, neon_s8, 4)
479 9ee6e8bb pbrook
NEON_VOP(qshl_s16, neon_s16, 2)
480 9ee6e8bb pbrook
NEON_VOP(qshl_s32, neon_s32, 1)
481 9ee6e8bb pbrook
#undef NEON_FN
482 9ee6e8bb pbrook
483 9ee6e8bb pbrook
NEON_OP(qshl_s64)
484 9ee6e8bb pbrook
{
485 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
486 9ee6e8bb pbrook
    int64_t val = T0 | ((uint64_t)T1 << 32);
487 9ee6e8bb pbrook
    if (shift < 0) {
488 9ee6e8bb pbrook
        val >>= -shift;
489 9ee6e8bb pbrook
    } else {
490 9ee6e8bb pbrook
        int64_t tmp = val;
491 9ee6e8bb pbrook
        val <<= shift;
492 9ee6e8bb pbrook
        if ((val >> shift) != tmp) {
493 9ee6e8bb pbrook
            env->QF = 1;
494 9ee6e8bb pbrook
            val = (tmp >> 63) ^ 0x7fffffffffffffffULL;
495 9ee6e8bb pbrook
        }
496 9ee6e8bb pbrook
    }
497 9ee6e8bb pbrook
    T0 = val;
498 9ee6e8bb pbrook
    T1 = val >> 32;
499 9ee6e8bb pbrook
    FORCE_RET();
500 9ee6e8bb pbrook
}
501 9ee6e8bb pbrook
502 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
503 9ee6e8bb pbrook
    int8_t tmp; \
504 9ee6e8bb pbrook
    tmp = (int8_t)src1; \
505 9ee6e8bb pbrook
    if (tmp < 0) { \
506 9ee6e8bb pbrook
        dest = src2 >> -tmp; \
507 9ee6e8bb pbrook
    } else { \
508 9ee6e8bb pbrook
        dest = src2 << tmp; \
509 9ee6e8bb pbrook
        if ((dest >> tmp) != src2) { \
510 9ee6e8bb pbrook
            env->QF = 1; \
511 9ee6e8bb pbrook
            dest = src2 >> 31; \
512 9ee6e8bb pbrook
        } \
513 9ee6e8bb pbrook
    }} while (0)
514 9ee6e8bb pbrook
NEON_VOP(qshl_u8, neon_u8, 4)
515 9ee6e8bb pbrook
NEON_VOP(qshl_u16, neon_u16, 2)
516 9ee6e8bb pbrook
NEON_VOP(qshl_u32, neon_u32, 1)
517 9ee6e8bb pbrook
#undef NEON_FN
518 9ee6e8bb pbrook
519 9ee6e8bb pbrook
NEON_OP(qshl_u64)
520 9ee6e8bb pbrook
{
521 8f8e3aa4 pbrook
    int8_t shift = env->vfp.scratch[0];
522 9ee6e8bb pbrook
    uint64_t val = T0 | ((uint64_t)T1 << 32);
523 9ee6e8bb pbrook
    if (shift < 0) {
524 9ee6e8bb pbrook
        val >>= -shift;
525 9ee6e8bb pbrook
    } else {
526 9ee6e8bb pbrook
        uint64_t tmp = val;
527 9ee6e8bb pbrook
        val <<= shift;
528 9ee6e8bb pbrook
        if ((val >> shift) != tmp) {
529 9ee6e8bb pbrook
            env->QF = 1;
530 9ee6e8bb pbrook
            val = ~(uint64_t)0;
531 9ee6e8bb pbrook
        }
532 9ee6e8bb pbrook
    }
533 9ee6e8bb pbrook
    T0 = val;
534 9ee6e8bb pbrook
    T1 = val >> 32;
535 9ee6e8bb pbrook
    FORCE_RET();
536 9ee6e8bb pbrook
}
537 9ee6e8bb pbrook
538 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
539 9ee6e8bb pbrook
    int8_t tmp; \
540 9ee6e8bb pbrook
    tmp = (int8_t)src1; \
541 9ee6e8bb pbrook
    if (tmp < 0) { \
542 9ee6e8bb pbrook
        dest = (src2 + (1 << (-1 - tmp))) >> -tmp; \
543 9ee6e8bb pbrook
    } else { \
544 9ee6e8bb pbrook
        dest = src2 << tmp; \
545 9ee6e8bb pbrook
        if ((dest >> tmp) != src2) { \
546 9ee6e8bb pbrook
            dest = ~0; \
547 9ee6e8bb pbrook
        } \
548 9ee6e8bb pbrook
    }} while (0)
549 9ee6e8bb pbrook
NEON_VOP(qrshl_s8, neon_s8, 4)
550 9ee6e8bb pbrook
NEON_VOP(qrshl_s16, neon_s16, 2)
551 9ee6e8bb pbrook
NEON_VOP(qrshl_s32, neon_s32, 1)
552 9ee6e8bb pbrook
#undef NEON_FN
553 9ee6e8bb pbrook
554 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) do { \
555 9ee6e8bb pbrook
    int8_t tmp; \
556 9ee6e8bb pbrook
    tmp = (int8_t)src1; \
557 9ee6e8bb pbrook
    if (tmp < 0) { \
558 9ee6e8bb pbrook
        dest = (src2 + (1 << (-1 - tmp))) >> -tmp; \
559 9ee6e8bb pbrook
    } else { \
560 9ee6e8bb pbrook
        dest = src2 << tmp; \
561 9ee6e8bb pbrook
        if ((dest >> tmp) != src2) { \
562 9ee6e8bb pbrook
            env->QF = 1; \
563 9ee6e8bb pbrook
            dest = src2 >> 31; \
564 9ee6e8bb pbrook
        } \
565 9ee6e8bb pbrook
    }} while (0)
566 9ee6e8bb pbrook
NEON_VOP(qrshl_u8, neon_u8, 4)
567 9ee6e8bb pbrook
NEON_VOP(qrshl_u16, neon_u16, 2)
568 9ee6e8bb pbrook
NEON_VOP(qrshl_u32, neon_u32, 1)
569 9ee6e8bb pbrook
#undef NEON_FN
570 9ee6e8bb pbrook
571 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 > src2) ? src1 : src2
572 9ee6e8bb pbrook
NEON_VOP(max_s8, neon_s8, 4)
573 9ee6e8bb pbrook
NEON_VOP(max_u8, neon_u8, 4)
574 9ee6e8bb pbrook
NEON_VOP(max_s16, neon_s16, 2)
575 9ee6e8bb pbrook
NEON_VOP(max_u16, neon_u16, 2)
576 9ee6e8bb pbrook
NEON_VOP(max_s32, neon_s32, 1)
577 9ee6e8bb pbrook
NEON_VOP(max_u32, neon_u32, 1)
578 9ee6e8bb pbrook
NEON_POP(pmax_s8, neon_s8, 4)
579 9ee6e8bb pbrook
NEON_POP(pmax_u8, neon_u8, 4)
580 9ee6e8bb pbrook
NEON_POP(pmax_s16, neon_s16, 2)
581 9ee6e8bb pbrook
NEON_POP(pmax_u16, neon_u16, 2)
582 9ee6e8bb pbrook
#undef NEON_FN
583 9ee6e8bb pbrook
584 9ee6e8bb pbrook
NEON_OP(max_f32)
585 9ee6e8bb pbrook
{
586 9ee6e8bb pbrook
    float32 f0 = vfp_itos(T0);
587 9ee6e8bb pbrook
    float32 f1 = vfp_itos(T1);
588 9ee6e8bb pbrook
    T0 = (float32_compare_quiet(f0, f1, NFS) == 1) ? T0 : T1;
589 9ee6e8bb pbrook
    FORCE_RET();
590 9ee6e8bb pbrook
}
591 9ee6e8bb pbrook
592 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 < src2) ? src1 : src2
593 9ee6e8bb pbrook
NEON_VOP(min_s8, neon_s8, 4)
594 9ee6e8bb pbrook
NEON_VOP(min_u8, neon_u8, 4)
595 9ee6e8bb pbrook
NEON_VOP(min_s16, neon_s16, 2)
596 9ee6e8bb pbrook
NEON_VOP(min_u16, neon_u16, 2)
597 9ee6e8bb pbrook
NEON_VOP(min_s32, neon_s32, 1)
598 9ee6e8bb pbrook
NEON_VOP(min_u32, neon_u32, 1)
599 9ee6e8bb pbrook
NEON_POP(pmin_s8, neon_s8, 4)
600 9ee6e8bb pbrook
NEON_POP(pmin_u8, neon_u8, 4)
601 9ee6e8bb pbrook
NEON_POP(pmin_s16, neon_s16, 2)
602 9ee6e8bb pbrook
NEON_POP(pmin_u16, neon_u16, 2)
603 9ee6e8bb pbrook
#undef NEON_FN
604 9ee6e8bb pbrook
605 9ee6e8bb pbrook
NEON_OP(min_f32)
606 9ee6e8bb pbrook
{
607 9ee6e8bb pbrook
    float32 f0 = vfp_itos(T0);
608 9ee6e8bb pbrook
    float32 f1 = vfp_itos(T1);
609 9ee6e8bb pbrook
    T0 = (float32_compare_quiet(f0, f1, NFS) == -1) ? T0 : T1;
610 9ee6e8bb pbrook
    FORCE_RET();
611 9ee6e8bb pbrook
}
612 9ee6e8bb pbrook
613 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) \
614 9ee6e8bb pbrook
    dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
615 9ee6e8bb pbrook
NEON_VOP(abd_s8, neon_s8, 4)
616 9ee6e8bb pbrook
NEON_VOP(abd_u8, neon_u8, 4)
617 9ee6e8bb pbrook
NEON_VOP(abd_s16, neon_s16, 2)
618 9ee6e8bb pbrook
NEON_VOP(abd_u16, neon_u16, 2)
619 9ee6e8bb pbrook
NEON_VOP(abd_s32, neon_s32, 1)
620 9ee6e8bb pbrook
NEON_VOP(abd_u32, neon_u32, 1)
621 9ee6e8bb pbrook
#undef NEON_FN
622 9ee6e8bb pbrook
623 9ee6e8bb pbrook
NEON_OP(abd_f32)
624 9ee6e8bb pbrook
{
625 9ee6e8bb pbrook
    float32 f0 = vfp_itos(T0);
626 9ee6e8bb pbrook
    float32 f1 = vfp_itos(T1);
627 9ee6e8bb pbrook
    T0 = vfp_stoi((float32_compare_quiet(f0, f1, NFS) == 1)
628 9ee6e8bb pbrook
                  ? float32_sub(f0, f1, NFS)
629 9ee6e8bb pbrook
                  : float32_sub(f1, f0, NFS));
630 9ee6e8bb pbrook
    FORCE_RET();
631 9ee6e8bb pbrook
}
632 9ee6e8bb pbrook
633 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = src1 + src2
634 9ee6e8bb pbrook
NEON_VOP(add_u8, neon_u8, 4)
635 9ee6e8bb pbrook
NEON_VOP(add_u16, neon_u16, 2)
636 9ee6e8bb pbrook
NEON_POP(padd_u8, neon_u8, 4)
637 9ee6e8bb pbrook
NEON_POP(padd_u16, neon_u16, 2)
638 9ee6e8bb pbrook
#undef NEON_FN
639 9ee6e8bb pbrook
640 9ee6e8bb pbrook
NEON_OP(add_f32)
641 9ee6e8bb pbrook
{
642 9ee6e8bb pbrook
    T0 = vfp_stoi(float32_add(vfp_itos(T0), vfp_itos(T1), NFS));
643 9ee6e8bb pbrook
    FORCE_RET();
644 9ee6e8bb pbrook
}
645 9ee6e8bb pbrook
646 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = src1 - src2
647 9ee6e8bb pbrook
NEON_VOP(sub_u8, neon_u8, 4)
648 9ee6e8bb pbrook
NEON_VOP(sub_u16, neon_u16, 2)
649 9ee6e8bb pbrook
#undef NEON_FN
650 9ee6e8bb pbrook
651 9ee6e8bb pbrook
NEON_OP(sub_f32)
652 9ee6e8bb pbrook
{
653 9ee6e8bb pbrook
    T0 = vfp_stoi(float32_sub(vfp_itos(T0), vfp_itos(T1), NFS));
654 9ee6e8bb pbrook
    FORCE_RET();
655 9ee6e8bb pbrook
}
656 9ee6e8bb pbrook
657 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = src2 - src1
658 9ee6e8bb pbrook
NEON_VOP(rsb_u8, neon_u8, 4)
659 9ee6e8bb pbrook
NEON_VOP(rsb_u16, neon_u16, 2)
660 9ee6e8bb pbrook
#undef NEON_FN
661 9ee6e8bb pbrook
662 9ee6e8bb pbrook
NEON_OP(rsb_f32)
663 9ee6e8bb pbrook
{
664 9ee6e8bb pbrook
    T0 = vfp_stoi(float32_sub(vfp_itos(T1), vfp_itos(T0), NFS));
665 9ee6e8bb pbrook
    FORCE_RET();
666 9ee6e8bb pbrook
}
667 9ee6e8bb pbrook
668 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = src1 * src2
669 9ee6e8bb pbrook
NEON_VOP(mul_u8, neon_u8, 4)
670 9ee6e8bb pbrook
NEON_VOP(mul_u16, neon_u16, 2)
671 9ee6e8bb pbrook
#undef NEON_FN
672 9ee6e8bb pbrook
673 9ee6e8bb pbrook
NEON_OP(mul_f32)
674 9ee6e8bb pbrook
{
675 9ee6e8bb pbrook
    T0 = vfp_stoi(float32_mul(vfp_itos(T0), vfp_itos(T1), NFS));
676 9ee6e8bb pbrook
    FORCE_RET();
677 9ee6e8bb pbrook
}
678 9ee6e8bb pbrook
679 9ee6e8bb pbrook
NEON_OP(mul_p8)
680 9ee6e8bb pbrook
{
681 9ee6e8bb pbrook
    T0 = helper_neon_mul_p8(T0, T1);
682 9ee6e8bb pbrook
}
683 9ee6e8bb pbrook
684 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 & src2) ? -1 : 0
685 9ee6e8bb pbrook
NEON_VOP(tst_u8, neon_u8, 4)
686 9ee6e8bb pbrook
NEON_VOP(tst_u16, neon_u16, 2)
687 9ee6e8bb pbrook
NEON_VOP(tst_u32, neon_u32, 1)
688 9ee6e8bb pbrook
#undef NEON_FN
689 9ee6e8bb pbrook
690 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) dest = (src1 == src2) ? -1 : 0
691 9ee6e8bb pbrook
NEON_VOP(ceq_u8, neon_u8, 4)
692 9ee6e8bb pbrook
NEON_VOP(ceq_u16, neon_u16, 2)
693 9ee6e8bb pbrook
NEON_VOP(ceq_u32, neon_u32, 1)
694 9ee6e8bb pbrook
#undef NEON_FN
695 9ee6e8bb pbrook
696 9ee6e8bb pbrook
#define NEON_QDMULH16(dest, src1, src2, round) do { \
697 9ee6e8bb pbrook
    uint32_t tmp = (int32_t)(int16_t) src1 * (int16_t) src2; \
698 9ee6e8bb pbrook
    if ((tmp ^ (tmp << 1)) & SIGNBIT) { \
699 9ee6e8bb pbrook
        env->QF = 1; \
700 9ee6e8bb pbrook
        tmp = (tmp >> 31) ^ ~SIGNBIT; \
701 9ee6e8bb pbrook
    } \
702 9ee6e8bb pbrook
    tmp <<= 1; \
703 9ee6e8bb pbrook
    if (round) { \
704 9ee6e8bb pbrook
        int32_t old = tmp; \
705 9ee6e8bb pbrook
        tmp += 1 << 15; \
706 9ee6e8bb pbrook
        if ((int32_t)tmp < old) { \
707 9ee6e8bb pbrook
            env->QF = 1; \
708 9ee6e8bb pbrook
            tmp = SIGNBIT - 1; \
709 9ee6e8bb pbrook
        } \
710 9ee6e8bb pbrook
    } \
711 9ee6e8bb pbrook
    dest = tmp >> 16; \
712 9ee6e8bb pbrook
    } while(0)
713 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 0)
714 9ee6e8bb pbrook
NEON_VOP(qdmulh_s16, neon_s16, 2)
715 9ee6e8bb pbrook
#undef NEON_FN
716 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 1)
717 9ee6e8bb pbrook
NEON_VOP(qrdmulh_s16, neon_s16, 2)
718 9ee6e8bb pbrook
#undef NEON_FN
719 9ee6e8bb pbrook
#undef NEON_QDMULH16
720 9ee6e8bb pbrook
721 9ee6e8bb pbrook
#define SIGNBIT64 ((uint64_t)1 << 63)
722 9ee6e8bb pbrook
#define NEON_QDMULH32(dest, src1, src2, round) do { \
723 9ee6e8bb pbrook
    uint64_t tmp = (int64_t)(int32_t) src1 * (int32_t) src2; \
724 9ee6e8bb pbrook
    if ((tmp ^ (tmp << 1)) & SIGNBIT64) { \
725 9ee6e8bb pbrook
        env->QF = 1; \
726 9ee6e8bb pbrook
        tmp = (tmp >> 63) ^ ~SIGNBIT64; \
727 9ee6e8bb pbrook
    } else { \
728 9ee6e8bb pbrook
        tmp <<= 1; \
729 9ee6e8bb pbrook
    } \
730 9ee6e8bb pbrook
    if (round) { \
731 9ee6e8bb pbrook
        int64_t old = tmp; \
732 9ee6e8bb pbrook
        tmp += (int64_t)1 << 31; \
733 9ee6e8bb pbrook
        if ((int64_t)tmp < old) { \
734 9ee6e8bb pbrook
            env->QF = 1; \
735 9ee6e8bb pbrook
            tmp = SIGNBIT64 - 1; \
736 9ee6e8bb pbrook
        } \
737 9ee6e8bb pbrook
    } \
738 9ee6e8bb pbrook
    dest = tmp >> 32; \
739 9ee6e8bb pbrook
    } while(0)
740 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 0)
741 9ee6e8bb pbrook
NEON_VOP(qdmulh_s32, neon_s32, 1)
742 9ee6e8bb pbrook
#undef NEON_FN
743 9ee6e8bb pbrook
#define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 1)
744 9ee6e8bb pbrook
NEON_VOP(qrdmulh_s32, neon_s32, 1)
745 9ee6e8bb pbrook
#undef NEON_FN
746 9ee6e8bb pbrook
#undef NEON_QDMULH32
747 9ee6e8bb pbrook
748 9ee6e8bb pbrook
/* Floating point comparisons produce an integer result.  */
749 9ee6e8bb pbrook
#define NEON_VOP_FCMP(name, cmp) \
750 9ee6e8bb pbrook
NEON_OP(name) \
751 9ee6e8bb pbrook
{ \
752 9ee6e8bb pbrook
    if (float32_compare_quiet(vfp_itos(T0), vfp_itos(T1), NFS) cmp 0) \
753 9ee6e8bb pbrook
        T0 = -1; \
754 9ee6e8bb pbrook
    else \
755 9ee6e8bb pbrook
        T0 = 0; \
756 9ee6e8bb pbrook
    FORCE_RET(); \
757 9ee6e8bb pbrook
}
758 9ee6e8bb pbrook
759 9ee6e8bb pbrook
NEON_VOP_FCMP(ceq_f32, ==)
760 9ee6e8bb pbrook
NEON_VOP_FCMP(cge_f32, >=)
761 9ee6e8bb pbrook
NEON_VOP_FCMP(cgt_f32, >)
762 9ee6e8bb pbrook
763 9ee6e8bb pbrook
NEON_OP(acge_f32)
764 9ee6e8bb pbrook
{
765 9ee6e8bb pbrook
    float32 f0 = float32_abs(vfp_itos(T0));
766 9ee6e8bb pbrook
    float32 f1 = float32_abs(vfp_itos(T1));
767 9ee6e8bb pbrook
    T0 = (float32_compare_quiet(f0, f1,NFS) >= 0) ? -1 : 0;
768 9ee6e8bb pbrook
    FORCE_RET();
769 9ee6e8bb pbrook
}
770 9ee6e8bb pbrook
771 9ee6e8bb pbrook
NEON_OP(acgt_f32)
772 9ee6e8bb pbrook
{
773 9ee6e8bb pbrook
    float32 f0 = float32_abs(vfp_itos(T0));
774 9ee6e8bb pbrook
    float32 f1 = float32_abs(vfp_itos(T1));
775 9ee6e8bb pbrook
    T0 = (float32_compare_quiet(f0, f1, NFS) > 0) ? -1 : 0;
776 9ee6e8bb pbrook
    FORCE_RET();
777 9ee6e8bb pbrook
}
778 9ee6e8bb pbrook
779 9ee6e8bb pbrook
/* Narrowing instructions.  The named type is the destination type.  */
780 9ee6e8bb pbrook
NEON_OP(narrow_u8)
781 9ee6e8bb pbrook
{
782 9ee6e8bb pbrook
    T0 = (T0 & 0xff) | ((T0 >> 8) & 0xff00)
783 9ee6e8bb pbrook
         | ((T1 << 16) & 0xff0000) | (T1 << 24);
784 9ee6e8bb pbrook
    FORCE_RET();
785 9ee6e8bb pbrook
}
786 9ee6e8bb pbrook
787 9ee6e8bb pbrook
NEON_OP(narrow_sat_u8)
788 9ee6e8bb pbrook
{
789 9ee6e8bb pbrook
    neon_u16 src;
790 9ee6e8bb pbrook
    neon_u8 dest;
791 9ee6e8bb pbrook
#define SAT8(d, s) \
792 9ee6e8bb pbrook
    if (s > 0xff) { \
793 9ee6e8bb pbrook
        d = 0xff; \
794 9ee6e8bb pbrook
        env->QF = 1; \
795 9ee6e8bb pbrook
    } else  { \
796 9ee6e8bb pbrook
        d = s; \
797 9ee6e8bb pbrook
    }
798 9ee6e8bb pbrook
799 9ee6e8bb pbrook
    NEON_UNPACK(neon_u16, src, T0);
800 9ee6e8bb pbrook
    SAT8(dest.v1, src.v1);
801 9ee6e8bb pbrook
    SAT8(dest.v2, src.v2);
802 9ee6e8bb pbrook
    NEON_UNPACK(neon_u16, src, T1);
803 9ee6e8bb pbrook
    SAT8(dest.v3, src.v1);
804 9ee6e8bb pbrook
    SAT8(dest.v4, src.v2);
805 9ee6e8bb pbrook
    NEON_PACK(neon_u8, T0, dest);
806 9ee6e8bb pbrook
    FORCE_RET();
807 9ee6e8bb pbrook
#undef SAT8
808 9ee6e8bb pbrook
}
809 9ee6e8bb pbrook
810 9ee6e8bb pbrook
NEON_OP(narrow_sat_s8)
811 9ee6e8bb pbrook
{
812 9ee6e8bb pbrook
    neon_s16 src;
813 9ee6e8bb pbrook
    neon_s8 dest;
814 9ee6e8bb pbrook
#define SAT8(d, s) \
815 9ee6e8bb pbrook
    if (s != (uint8_t)s) { \
816 9ee6e8bb pbrook
        d = (s >> 15) ^ 0x7f; \
817 9ee6e8bb pbrook
        env->QF = 1; \
818 9ee6e8bb pbrook
    } else  { \
819 9ee6e8bb pbrook
        d = s; \
820 9ee6e8bb pbrook
    }
821 9ee6e8bb pbrook
822 9ee6e8bb pbrook
    NEON_UNPACK(neon_s16, src, T0);
823 9ee6e8bb pbrook
    SAT8(dest.v1, src.v1);
824 9ee6e8bb pbrook
    SAT8(dest.v2, src.v2);
825 9ee6e8bb pbrook
    NEON_UNPACK(neon_s16, src, T1);
826 9ee6e8bb pbrook
    SAT8(dest.v3, src.v1);
827 9ee6e8bb pbrook
    SAT8(dest.v4, src.v2);
828 9ee6e8bb pbrook
    NEON_PACK(neon_s8, T0, dest);
829 9ee6e8bb pbrook
    FORCE_RET();
830 9ee6e8bb pbrook
#undef SAT8
831 9ee6e8bb pbrook
}
832 9ee6e8bb pbrook
833 9ee6e8bb pbrook
NEON_OP(narrow_u16)
834 9ee6e8bb pbrook
{
835 9ee6e8bb pbrook
    T0 = (T0 & 0xffff) | (T1 << 16);
836 9ee6e8bb pbrook
}
837 9ee6e8bb pbrook
838 9ee6e8bb pbrook
NEON_OP(narrow_sat_u16)
839 9ee6e8bb pbrook
{
840 9ee6e8bb pbrook
    if (T0 > 0xffff) {
841 9ee6e8bb pbrook
        T0 = 0xffff;
842 9ee6e8bb pbrook
        env->QF = 1;
843 9ee6e8bb pbrook
    }
844 9ee6e8bb pbrook
    if (T1 > 0xffff) {
845 9ee6e8bb pbrook
        T1 = 0xffff;
846 9ee6e8bb pbrook
        env->QF = 1;
847 9ee6e8bb pbrook
    }
848 9ee6e8bb pbrook
    T0 |= T1 << 16;
849 9ee6e8bb pbrook
    FORCE_RET();
850 9ee6e8bb pbrook
}
851 9ee6e8bb pbrook
852 9ee6e8bb pbrook
NEON_OP(narrow_sat_s16)
853 9ee6e8bb pbrook
{
854 9ee6e8bb pbrook
    if ((int32_t)T0 != (int16_t)T0) {
855 9ee6e8bb pbrook
        T0 = ((int32_t)T0 >> 31) ^ 0x7fff;
856 9ee6e8bb pbrook
        env->QF = 1;
857 9ee6e8bb pbrook
    }
858 9ee6e8bb pbrook
    if ((int32_t)T1 != (int16_t) T1) {
859 9ee6e8bb pbrook
        T1 = ((int32_t)T1 >> 31) ^ 0x7fff;
860 9ee6e8bb pbrook
        env->QF = 1;
861 9ee6e8bb pbrook
    }
862 9ee6e8bb pbrook
    T0 = (uint16_t)T0 | (T1 << 16);
863 9ee6e8bb pbrook
    FORCE_RET();
864 9ee6e8bb pbrook
}
865 9ee6e8bb pbrook
866 9ee6e8bb pbrook
NEON_OP(narrow_sat_u32)
867 9ee6e8bb pbrook
{
868 9ee6e8bb pbrook
    if (T1) {
869 9ee6e8bb pbrook
        T0 = 0xffffffffu;
870 9ee6e8bb pbrook
        env->QF = 1;
871 9ee6e8bb pbrook
    }
872 9ee6e8bb pbrook
    FORCE_RET();
873 9ee6e8bb pbrook
}
874 9ee6e8bb pbrook
875 9ee6e8bb pbrook
NEON_OP(narrow_sat_s32)
876 9ee6e8bb pbrook
{
877 9ee6e8bb pbrook
    int32_t sign = (int32_t)T1 >> 31;
878 9ee6e8bb pbrook
879 9ee6e8bb pbrook
    if ((int32_t)T1 != sign) {
880 9ee6e8bb pbrook
        T0 = sign ^ 0x7fffffff;
881 9ee6e8bb pbrook
        env->QF = 1;
882 9ee6e8bb pbrook
    }
883 9ee6e8bb pbrook
    FORCE_RET();
884 9ee6e8bb pbrook
}
885 9ee6e8bb pbrook
886 9ee6e8bb pbrook
/* Narrowing instructions.  Named type is the narrow type.  */
887 9ee6e8bb pbrook
NEON_OP(narrow_high_u8)
888 9ee6e8bb pbrook
{
889 9ee6e8bb pbrook
    T0 = ((T0 >> 8) & 0xff) | ((T0 >> 16) & 0xff00)
890 9ee6e8bb pbrook
        | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000);
891 9ee6e8bb pbrook
    FORCE_RET();
892 9ee6e8bb pbrook
}
893 9ee6e8bb pbrook
894 9ee6e8bb pbrook
NEON_OP(narrow_high_u16)
895 9ee6e8bb pbrook
{
896 9ee6e8bb pbrook
    T0 = (T0 >> 16) | (T1 & 0xffff0000);
897 9ee6e8bb pbrook
    FORCE_RET();
898 9ee6e8bb pbrook
}
899 9ee6e8bb pbrook
900 9ee6e8bb pbrook
NEON_OP(narrow_high_round_u8)
901 9ee6e8bb pbrook
{
902 9ee6e8bb pbrook
    T0 = (((T0 + 0x80) >> 8) & 0xff) | (((T0 + 0x800000) >> 16) & 0xff00)
903 9ee6e8bb pbrook
        | (((T1 + 0x80) << 8) & 0xff0000) | ((T1 + 0x800000) & 0xff000000);
904 9ee6e8bb pbrook
    FORCE_RET();
905 9ee6e8bb pbrook
}
906 9ee6e8bb pbrook
907 9ee6e8bb pbrook
NEON_OP(narrow_high_round_u16)
908 9ee6e8bb pbrook
{
909 9ee6e8bb pbrook
    T0 = ((T0 + 0x8000) >> 16) | ((T1 + 0x8000) & 0xffff0000);
910 9ee6e8bb pbrook
    FORCE_RET();
911 9ee6e8bb pbrook
}
912 9ee6e8bb pbrook
913 9ee6e8bb pbrook
NEON_OP(narrow_high_round_u32)
914 9ee6e8bb pbrook
{
915 9ee6e8bb pbrook
    if (T0 >= 0x80000000u)
916 9ee6e8bb pbrook
        T0 = T1 + 1;
917 9ee6e8bb pbrook
    else
918 9ee6e8bb pbrook
        T0 = T1;
919 9ee6e8bb pbrook
    FORCE_RET();
920 9ee6e8bb pbrook
}
921 9ee6e8bb pbrook
922 9ee6e8bb pbrook
/* Widening instructions.  Named type is source type.  */
923 9ee6e8bb pbrook
NEON_OP(widen_s8)
924 9ee6e8bb pbrook
{
925 9ee6e8bb pbrook
    uint32_t src;
926 9ee6e8bb pbrook
927 9ee6e8bb pbrook
    src = T0;
928 9ee6e8bb pbrook
    T0 = (uint16_t)(int8_t)src | ((int8_t)(src >> 8) << 16);
929 9ee6e8bb pbrook
    T1 = (uint16_t)(int8_t)(src >> 16) | ((int8_t)(src >> 24) << 16);
930 9ee6e8bb pbrook
}
931 9ee6e8bb pbrook
932 9ee6e8bb pbrook
NEON_OP(widen_u8)
933 9ee6e8bb pbrook
{
934 9ee6e8bb pbrook
    T1 = ((T0 >> 8) & 0xff0000) | ((T0 >> 16) & 0xff);
935 9ee6e8bb pbrook
    T0 = ((T0 << 8) & 0xff0000) | (T0 & 0xff);
936 9ee6e8bb pbrook
}
937 9ee6e8bb pbrook
938 9ee6e8bb pbrook
NEON_OP(widen_s16)
939 9ee6e8bb pbrook
{
940 9ee6e8bb pbrook
    int32_t src;
941 9ee6e8bb pbrook
942 9ee6e8bb pbrook
    src = T0;
943 9ee6e8bb pbrook
    T0 = (int16_t)src;
944 9ee6e8bb pbrook
    T1 = src >> 16;
945 9ee6e8bb pbrook
}
946 9ee6e8bb pbrook
947 9ee6e8bb pbrook
NEON_OP(widen_u16)
948 9ee6e8bb pbrook
{
949 9ee6e8bb pbrook
    T1 = T0 >> 16;
950 9ee6e8bb pbrook
    T0 &= 0xffff;
951 9ee6e8bb pbrook
}
952 9ee6e8bb pbrook
953 9ee6e8bb pbrook
NEON_OP(widen_s32)
954 9ee6e8bb pbrook
{
955 9ee6e8bb pbrook
    T1 = (int32_t)T0 >> 31;
956 9ee6e8bb pbrook
    FORCE_RET();
957 9ee6e8bb pbrook
}
958 9ee6e8bb pbrook
959 9ee6e8bb pbrook
NEON_OP(widen_high_u8)
960 9ee6e8bb pbrook
{
961 9ee6e8bb pbrook
    T1 = (T0 & 0xff000000) | ((T0 >> 8) & 0xff00);
962 9ee6e8bb pbrook
    T0 = ((T0 << 16) & 0xff000000) | ((T0 << 8) & 0xff00);
963 9ee6e8bb pbrook
}
964 9ee6e8bb pbrook
965 9ee6e8bb pbrook
NEON_OP(widen_high_u16)
966 9ee6e8bb pbrook
{
967 9ee6e8bb pbrook
    T1 = T0 & 0xffff0000;
968 9ee6e8bb pbrook
    T0 <<= 16;
969 9ee6e8bb pbrook
}
970 9ee6e8bb pbrook
971 9ee6e8bb pbrook
/* Long operations.  The type is the wide type.  */
972 9ee6e8bb pbrook
NEON_OP(shll_u16)
973 9ee6e8bb pbrook
{
974 9ee6e8bb pbrook
    int shift = PARAM1;
975 9ee6e8bb pbrook
    uint32_t mask;
976 9ee6e8bb pbrook
977 9ee6e8bb pbrook
    mask = 0xffff >> (16 - shift);
978 9ee6e8bb pbrook
    mask |= mask << 16;
979 9ee6e8bb pbrook
    mask = ~mask;
980 9ee6e8bb pbrook
981 9ee6e8bb pbrook
    T0 = (T0 << shift) & mask;
982 9ee6e8bb pbrook
    T1 = (T1 << shift) & mask;
983 9ee6e8bb pbrook
    FORCE_RET();
984 9ee6e8bb pbrook
}
985 9ee6e8bb pbrook
986 9ee6e8bb pbrook
NEON_OP(shll_u64)
987 9ee6e8bb pbrook
{
988 9ee6e8bb pbrook
    int shift = PARAM1;
989 9ee6e8bb pbrook
990 9ee6e8bb pbrook
    T1 <<= shift;
991 9ee6e8bb pbrook
    T1 |= T0 >> (32 - shift);
992 9ee6e8bb pbrook
    T0 <<= shift;
993 9ee6e8bb pbrook
    FORCE_RET();
994 9ee6e8bb pbrook
}
995 9ee6e8bb pbrook
996 9ee6e8bb pbrook
NEON_OP(addl_u16)
997 9ee6e8bb pbrook
{
998 9ee6e8bb pbrook
    uint32_t tmp;
999 9ee6e8bb pbrook
    uint32_t high;
1000 9ee6e8bb pbrook
1001 9ee6e8bb pbrook
    tmp = env->vfp.scratch[0];
1002 9ee6e8bb pbrook
    high = (T0 >> 16) + (tmp >> 16);
1003 9ee6e8bb pbrook
    T0 = (uint16_t)(T0 + tmp);
1004 9ee6e8bb pbrook
    T0 |= (high << 16);
1005 9ee6e8bb pbrook
    tmp = env->vfp.scratch[1];
1006 9ee6e8bb pbrook
    high = (T1 >> 16) + (tmp >> 16);
1007 9ee6e8bb pbrook
    T1 = (uint16_t)(T1 + tmp);
1008 9ee6e8bb pbrook
    T1 |= (high << 16);
1009 9ee6e8bb pbrook
    FORCE_RET();
1010 9ee6e8bb pbrook
}
1011 9ee6e8bb pbrook
1012 9ee6e8bb pbrook
NEON_OP(addl_u32)
1013 9ee6e8bb pbrook
{
1014 9ee6e8bb pbrook
    T0 += env->vfp.scratch[0];
1015 9ee6e8bb pbrook
    T1 += env->vfp.scratch[1];
1016 9ee6e8bb pbrook
    FORCE_RET();
1017 9ee6e8bb pbrook
}
1018 9ee6e8bb pbrook
1019 9ee6e8bb pbrook
NEON_OP(addl_u64)
1020 9ee6e8bb pbrook
{
1021 9ee6e8bb pbrook
    uint64_t tmp;
1022 9ee6e8bb pbrook
    tmp = T0 | ((uint64_t)T1 << 32);
1023 9ee6e8bb pbrook
    tmp += env->vfp.scratch[0];
1024 9ee6e8bb pbrook
    tmp += (uint64_t)env->vfp.scratch[1] << 32;
1025 9ee6e8bb pbrook
    T0 = tmp;
1026 9ee6e8bb pbrook
    T1 = tmp >> 32;
1027 9ee6e8bb pbrook
    FORCE_RET();
1028 9ee6e8bb pbrook
}
1029 9ee6e8bb pbrook
1030 9ee6e8bb pbrook
NEON_OP(subl_u16)
1031 9ee6e8bb pbrook
{
1032 9ee6e8bb pbrook
    uint32_t tmp;
1033 9ee6e8bb pbrook
    uint32_t high;
1034 9ee6e8bb pbrook
1035 9ee6e8bb pbrook
    tmp = env->vfp.scratch[0];
1036 9ee6e8bb pbrook
    high = (T0 >> 16) - (tmp >> 16);
1037 9ee6e8bb pbrook
    T0 = (uint16_t)(T0 - tmp);
1038 9ee6e8bb pbrook
    T0 |= (high << 16);
1039 9ee6e8bb pbrook
    tmp = env->vfp.scratch[1];
1040 9ee6e8bb pbrook
    high = (T1 >> 16) - (tmp >> 16);
1041 9ee6e8bb pbrook
    T1 = (uint16_t)(T1 - tmp);
1042 9ee6e8bb pbrook
    T1 |= (high << 16);
1043 9ee6e8bb pbrook
    FORCE_RET();
1044 9ee6e8bb pbrook
}
1045 9ee6e8bb pbrook
1046 9ee6e8bb pbrook
NEON_OP(subl_u32)
1047 9ee6e8bb pbrook
{
1048 9ee6e8bb pbrook
    T0 -= env->vfp.scratch[0];
1049 9ee6e8bb pbrook
    T1 -= env->vfp.scratch[1];
1050 9ee6e8bb pbrook
    FORCE_RET();
1051 9ee6e8bb pbrook
}
1052 9ee6e8bb pbrook
1053 9ee6e8bb pbrook
NEON_OP(subl_u64)
1054 9ee6e8bb pbrook
{
1055 9ee6e8bb pbrook
    uint64_t tmp;
1056 9ee6e8bb pbrook
    tmp = T0 | ((uint64_t)T1 << 32);
1057 9ee6e8bb pbrook
    tmp -= env->vfp.scratch[0];
1058 9ee6e8bb pbrook
    tmp -= (uint64_t)env->vfp.scratch[1] << 32;
1059 9ee6e8bb pbrook
    T0 = tmp;
1060 9ee6e8bb pbrook
    T1 = tmp >> 32;
1061 9ee6e8bb pbrook
    FORCE_RET();
1062 9ee6e8bb pbrook
}
1063 9ee6e8bb pbrook
1064 9ee6e8bb pbrook
#define DO_ABD(dest, x, y, type) do { \
1065 9ee6e8bb pbrook
    type tmp_x = x; \
1066 9ee6e8bb pbrook
    type tmp_y = y; \
1067 9ee6e8bb pbrook
    dest = ((tmp_x > tmp_y) ? tmp_x - tmp_y : tmp_y - tmp_x); \
1068 9ee6e8bb pbrook
    } while(0)
1069 9ee6e8bb pbrook
1070 9ee6e8bb pbrook
NEON_OP(abdl_u16)
1071 9ee6e8bb pbrook
{
1072 9ee6e8bb pbrook
    uint32_t tmp;
1073 9ee6e8bb pbrook
    uint32_t low;
1074 9ee6e8bb pbrook
    uint32_t high;
1075 9ee6e8bb pbrook
1076 9ee6e8bb pbrook
    DO_ABD(low, T0, T1, uint8_t);
1077 9ee6e8bb pbrook
    DO_ABD(tmp, T0 >> 8, T1 >> 8, uint8_t);
1078 9ee6e8bb pbrook
    low |= tmp << 16;
1079 9ee6e8bb pbrook
    DO_ABD(high, T0 >> 16, T1 >> 16, uint8_t);
1080 9ee6e8bb pbrook
    DO_ABD(tmp, T0 >> 24, T1 >> 24, uint8_t);
1081 9ee6e8bb pbrook
    high |= tmp << 16;
1082 9ee6e8bb pbrook
    T0 = low;
1083 9ee6e8bb pbrook
    T1 = high;
1084 9ee6e8bb pbrook
    FORCE_RET();
1085 9ee6e8bb pbrook
}
1086 9ee6e8bb pbrook
1087 9ee6e8bb pbrook
NEON_OP(abdl_s16)
1088 9ee6e8bb pbrook
{
1089 9ee6e8bb pbrook
    uint32_t tmp;
1090 9ee6e8bb pbrook
    uint32_t low;
1091 9ee6e8bb pbrook
    uint32_t high;
1092 9ee6e8bb pbrook
1093 9ee6e8bb pbrook
    DO_ABD(low, T0, T1, int8_t);
1094 9ee6e8bb pbrook
    DO_ABD(tmp, T0 >> 8, T1 >> 8, int8_t);
1095 9ee6e8bb pbrook
    low |= tmp << 16;
1096 9ee6e8bb pbrook
    DO_ABD(high, T0 >> 16, T1 >> 16, int8_t);
1097 9ee6e8bb pbrook
    DO_ABD(tmp, T0 >> 24, T1 >> 24, int8_t);
1098 9ee6e8bb pbrook
    high |= tmp << 16;
1099 9ee6e8bb pbrook
    T0 = low;
1100 9ee6e8bb pbrook
    T1 = high;
1101 9ee6e8bb pbrook
    FORCE_RET();
1102 9ee6e8bb pbrook
}
1103 9ee6e8bb pbrook
1104 9ee6e8bb pbrook
NEON_OP(abdl_u32)
1105 9ee6e8bb pbrook
{
1106 9ee6e8bb pbrook
    uint32_t low;
1107 9ee6e8bb pbrook
    uint32_t high;
1108 9ee6e8bb pbrook
1109 9ee6e8bb pbrook
    DO_ABD(low, T0, T1, uint16_t);
1110 9ee6e8bb pbrook
    DO_ABD(high, T0 >> 16, T1 >> 16, uint16_t);
1111 9ee6e8bb pbrook
    T0 = low;
1112 9ee6e8bb pbrook
    T1 = high;
1113 9ee6e8bb pbrook
    FORCE_RET();
1114 9ee6e8bb pbrook
}
1115 9ee6e8bb pbrook
1116 9ee6e8bb pbrook
NEON_OP(abdl_s32)
1117 9ee6e8bb pbrook
{
1118 9ee6e8bb pbrook
    uint32_t low;
1119 9ee6e8bb pbrook
    uint32_t high;
1120 9ee6e8bb pbrook
1121 9ee6e8bb pbrook
    DO_ABD(low, T0, T1, int16_t);
1122 9ee6e8bb pbrook
    DO_ABD(high, T0 >> 16, T1 >> 16, int16_t);
1123 9ee6e8bb pbrook
    T0 = low;
1124 9ee6e8bb pbrook
    T1 = high;
1125 9ee6e8bb pbrook
    FORCE_RET();
1126 9ee6e8bb pbrook
}
1127 9ee6e8bb pbrook
1128 9ee6e8bb pbrook
NEON_OP(abdl_u64)
1129 9ee6e8bb pbrook
{
1130 9ee6e8bb pbrook
    DO_ABD(T0, T0, T1, uint32_t);
1131 9ee6e8bb pbrook
    T1 = 0;
1132 9ee6e8bb pbrook
}
1133 9ee6e8bb pbrook
1134 9ee6e8bb pbrook
NEON_OP(abdl_s64)
1135 9ee6e8bb pbrook
{
1136 9ee6e8bb pbrook
    DO_ABD(T0, T0, T1, int32_t);
1137 9ee6e8bb pbrook
    T1 = 0;
1138 9ee6e8bb pbrook
}
1139 9ee6e8bb pbrook
#undef DO_ABD
1140 9ee6e8bb pbrook
1141 9ee6e8bb pbrook
/* Widening multiple. Named type is the source type.  */
1142 9ee6e8bb pbrook
#define DO_MULL(dest, x, y, type1, type2) do { \
1143 9ee6e8bb pbrook
    type1 tmp_x = x; \
1144 9ee6e8bb pbrook
    type1 tmp_y = y; \
1145 9ee6e8bb pbrook
    dest = (type2)((type2)tmp_x * (type2)tmp_y); \
1146 9ee6e8bb pbrook
    } while(0)
1147 9ee6e8bb pbrook
1148 9ee6e8bb pbrook
NEON_OP(mull_u8)
1149 9ee6e8bb pbrook
{
1150 9ee6e8bb pbrook
    uint32_t tmp;
1151 9ee6e8bb pbrook
    uint32_t low;
1152 9ee6e8bb pbrook
    uint32_t high;
1153 9ee6e8bb pbrook
1154 9ee6e8bb pbrook
    DO_MULL(low, T0, T1, uint8_t, uint16_t);
1155 9ee6e8bb pbrook
    DO_MULL(tmp, T0 >> 8, T1 >> 8, uint8_t, uint16_t);
1156 9ee6e8bb pbrook
    low |= tmp << 16;
1157 9ee6e8bb pbrook
    DO_MULL(high, T0 >> 16, T1 >> 16, uint8_t, uint16_t);
1158 9ee6e8bb pbrook
    DO_MULL(tmp, T0 >> 24, T1 >> 24, uint8_t, uint16_t);
1159 9ee6e8bb pbrook
    high |= tmp << 16;
1160 9ee6e8bb pbrook
    T0 = low;
1161 9ee6e8bb pbrook
    T1 = high;
1162 9ee6e8bb pbrook
    FORCE_RET();
1163 9ee6e8bb pbrook
}
1164 9ee6e8bb pbrook
1165 9ee6e8bb pbrook
NEON_OP(mull_s8)
1166 9ee6e8bb pbrook
{
1167 9ee6e8bb pbrook
    uint32_t tmp;
1168 9ee6e8bb pbrook
    uint32_t low;
1169 9ee6e8bb pbrook
    uint32_t high;
1170 9ee6e8bb pbrook
1171 9ee6e8bb pbrook
    DO_MULL(low, T0, T1, int8_t, uint16_t);
1172 9ee6e8bb pbrook
    DO_MULL(tmp, T0 >> 8, T1 >> 8, int8_t, uint16_t);
1173 9ee6e8bb pbrook
    low |= tmp << 16;
1174 9ee6e8bb pbrook
    DO_MULL(high, T0 >> 16, T1 >> 16, int8_t, uint16_t);
1175 9ee6e8bb pbrook
    DO_MULL(tmp, T0 >> 24, T1 >> 24, int8_t, uint16_t);
1176 9ee6e8bb pbrook
    high |= tmp << 16;
1177 9ee6e8bb pbrook
    T0 = low;
1178 9ee6e8bb pbrook
    T1 = high;
1179 9ee6e8bb pbrook
    FORCE_RET();
1180 9ee6e8bb pbrook
}
1181 9ee6e8bb pbrook
1182 9ee6e8bb pbrook
NEON_OP(mull_u16)
1183 9ee6e8bb pbrook
{
1184 9ee6e8bb pbrook
    uint32_t low;
1185 9ee6e8bb pbrook
    uint32_t high;
1186 9ee6e8bb pbrook
1187 9ee6e8bb pbrook
    DO_MULL(low, T0, T1, uint16_t, uint32_t);
1188 9ee6e8bb pbrook
    DO_MULL(high, T0 >> 16, T1 >> 16, uint16_t, uint32_t);
1189 9ee6e8bb pbrook
    T0 = low;
1190 9ee6e8bb pbrook
    T1 = high;
1191 9ee6e8bb pbrook
    FORCE_RET();
1192 9ee6e8bb pbrook
}
1193 9ee6e8bb pbrook
1194 9ee6e8bb pbrook
NEON_OP(mull_s16)
1195 9ee6e8bb pbrook
{
1196 9ee6e8bb pbrook
    uint32_t low;
1197 9ee6e8bb pbrook
    uint32_t high;
1198 9ee6e8bb pbrook
1199 9ee6e8bb pbrook
    DO_MULL(low, T0, T1, int16_t, uint32_t);
1200 9ee6e8bb pbrook
    DO_MULL(high, T0 >> 16, T1 >> 16, int16_t, uint32_t);
1201 9ee6e8bb pbrook
    T0 = low;
1202 9ee6e8bb pbrook
    T1 = high;
1203 9ee6e8bb pbrook
    FORCE_RET();
1204 9ee6e8bb pbrook
}
1205 9ee6e8bb pbrook
1206 9ee6e8bb pbrook
NEON_OP(addl_saturate_s32)
1207 9ee6e8bb pbrook
{
1208 9ee6e8bb pbrook
    uint32_t tmp;
1209 9ee6e8bb pbrook
    uint32_t res;
1210 9ee6e8bb pbrook
1211 9ee6e8bb pbrook
    tmp = env->vfp.scratch[0];
1212 9ee6e8bb pbrook
    res = T0 + tmp;
1213 9ee6e8bb pbrook
    if (((res ^ T0) & SIGNBIT) && !((T0 ^ tmp) & SIGNBIT)) {
1214 9ee6e8bb pbrook
        env->QF = 1;
1215 9ee6e8bb pbrook
        T0 = (T0 >> 31) ^ 0x7fffffff;
1216 9ee6e8bb pbrook
    } else {
1217 9ee6e8bb pbrook
      T0 = res;
1218 9ee6e8bb pbrook
    }
1219 9ee6e8bb pbrook
    tmp = env->vfp.scratch[1];
1220 9ee6e8bb pbrook
    res = T1 + tmp;
1221 9ee6e8bb pbrook
    if (((res ^ T1) & SIGNBIT) && !((T1 ^ tmp) & SIGNBIT)) {
1222 9ee6e8bb pbrook
        env->QF = 1;
1223 9ee6e8bb pbrook
        T1 = (T1 >> 31) ^ 0x7fffffff;
1224 9ee6e8bb pbrook
    } else {
1225 9ee6e8bb pbrook
      T1 = res;
1226 9ee6e8bb pbrook
    }
1227 9ee6e8bb pbrook
    FORCE_RET();
1228 9ee6e8bb pbrook
}
1229 9ee6e8bb pbrook
1230 9ee6e8bb pbrook
NEON_OP(addl_saturate_s64)
1231 9ee6e8bb pbrook
{
1232 9ee6e8bb pbrook
    uint64_t src1;
1233 9ee6e8bb pbrook
    uint64_t src2;
1234 9ee6e8bb pbrook
    uint64_t res;
1235 9ee6e8bb pbrook
1236 9ee6e8bb pbrook
    src1 = T0 + ((uint64_t)T1 << 32);
1237 9ee6e8bb pbrook
    src2 = env->vfp.scratch[0] + ((uint64_t)env->vfp.scratch[1] << 32);
1238 9ee6e8bb pbrook
    res = src1 + src2;
1239 9ee6e8bb pbrook
    if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
1240 9ee6e8bb pbrook
        env->QF = 1;
1241 9ee6e8bb pbrook
        T0 = ~(int64_t)src1 >> 63;
1242 9ee6e8bb pbrook
        T1 = T0 ^ 0x80000000;
1243 9ee6e8bb pbrook
    } else {
1244 9ee6e8bb pbrook
      T0 = res;
1245 9ee6e8bb pbrook
      T1 = res >> 32;
1246 9ee6e8bb pbrook
    }
1247 9ee6e8bb pbrook
    FORCE_RET();
1248 9ee6e8bb pbrook
}
1249 9ee6e8bb pbrook
1250 9ee6e8bb pbrook
NEON_OP(addl_saturate_u64)
1251 9ee6e8bb pbrook
{
1252 9ee6e8bb pbrook
    uint64_t src1;
1253 9ee6e8bb pbrook
    uint64_t src2;
1254 9ee6e8bb pbrook
    uint64_t res;
1255 9ee6e8bb pbrook
1256 9ee6e8bb pbrook
    src1 = T0 + ((uint64_t)T1 << 32);
1257 9ee6e8bb pbrook
    src2 = env->vfp.scratch[0] + ((uint64_t)env->vfp.scratch[1] << 32);
1258 9ee6e8bb pbrook
    res = src1 + src2;
1259 9ee6e8bb pbrook
    if (res < src1) {
1260 9ee6e8bb pbrook
        env->QF = 1;
1261 9ee6e8bb pbrook
        T0 = 0xffffffff;
1262 9ee6e8bb pbrook
        T1 = 0xffffffff;
1263 9ee6e8bb pbrook
    } else {
1264 9ee6e8bb pbrook
      T0 = res;
1265 9ee6e8bb pbrook
      T1 = res >> 32;
1266 9ee6e8bb pbrook
    }
1267 9ee6e8bb pbrook
    FORCE_RET();
1268 9ee6e8bb pbrook
}
1269 9ee6e8bb pbrook
1270 9ee6e8bb pbrook
NEON_OP(subl_saturate_s64)
1271 9ee6e8bb pbrook
{
1272 9ee6e8bb pbrook
    uint64_t src1;
1273 9ee6e8bb pbrook
    uint64_t src2;
1274 9ee6e8bb pbrook
    uint64_t res;
1275 9ee6e8bb pbrook
1276 9ee6e8bb pbrook
    src1 = T0 + ((uint64_t)T1 << 32);
1277 9ee6e8bb pbrook
    src2 = env->vfp.scratch[0] + ((uint64_t)env->vfp.scratch[1] << 32);
1278 9ee6e8bb pbrook
    res = src1 - src2;
1279 9ee6e8bb pbrook
    if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
1280 9ee6e8bb pbrook
        env->QF = 1;
1281 9ee6e8bb pbrook
        T0 = ~(int64_t)src1 >> 63;
1282 9ee6e8bb pbrook
        T1 = T0 ^ 0x80000000;
1283 9ee6e8bb pbrook
    } else {
1284 9ee6e8bb pbrook
      T0 = res;
1285 9ee6e8bb pbrook
      T1 = res >> 32;
1286 9ee6e8bb pbrook
    }
1287 9ee6e8bb pbrook
    FORCE_RET();
1288 9ee6e8bb pbrook
}
1289 9ee6e8bb pbrook
1290 9ee6e8bb pbrook
NEON_OP(subl_saturate_u64)
1291 9ee6e8bb pbrook
{
1292 9ee6e8bb pbrook
    uint64_t src1;
1293 9ee6e8bb pbrook
    uint64_t src2;
1294 9ee6e8bb pbrook
    uint64_t res;
1295 9ee6e8bb pbrook
1296 9ee6e8bb pbrook
    src1 = T0 + ((uint64_t)T1 << 32);
1297 9ee6e8bb pbrook
    src2 = env->vfp.scratch[0] + ((uint64_t)env->vfp.scratch[1] << 32);
1298 9ee6e8bb pbrook
    if (src1 < src2) {
1299 9ee6e8bb pbrook
        env->QF = 1;
1300 9ee6e8bb pbrook
        T0 = 0;
1301 9ee6e8bb pbrook
        T1 = 0;
1302 9ee6e8bb pbrook
    } else {
1303 9ee6e8bb pbrook
      res = src1 - src2;
1304 9ee6e8bb pbrook
      T0 = res;
1305 9ee6e8bb pbrook
      T1 = res >> 32;
1306 9ee6e8bb pbrook
    }
1307 9ee6e8bb pbrook
    FORCE_RET();
1308 9ee6e8bb pbrook
}
1309 9ee6e8bb pbrook
1310 9ee6e8bb pbrook
NEON_OP(negl_u16)
1311 9ee6e8bb pbrook
{
1312 9ee6e8bb pbrook
    uint32_t tmp;
1313 9ee6e8bb pbrook
    tmp = T0 >> 16;
1314 9ee6e8bb pbrook
    tmp = -tmp;
1315 9ee6e8bb pbrook
    T0 = (-T0 & 0xffff) | (tmp << 16);
1316 9ee6e8bb pbrook
    tmp = T1 >> 16;
1317 9ee6e8bb pbrook
    tmp = -tmp;
1318 9ee6e8bb pbrook
    T1 = (-T1 & 0xffff) | (tmp << 16);
1319 9ee6e8bb pbrook
    FORCE_RET();
1320 9ee6e8bb pbrook
}
1321 9ee6e8bb pbrook
1322 9ee6e8bb pbrook
NEON_OP(negl_u32)
1323 9ee6e8bb pbrook
{
1324 9ee6e8bb pbrook
    T0 = -T0;
1325 9ee6e8bb pbrook
    T1 = -T1;
1326 9ee6e8bb pbrook
    FORCE_RET();
1327 9ee6e8bb pbrook
}
1328 9ee6e8bb pbrook
1329 9ee6e8bb pbrook
NEON_OP(negl_u64)
1330 9ee6e8bb pbrook
{
1331 9ee6e8bb pbrook
    uint64_t val;
1332 9ee6e8bb pbrook
1333 9ee6e8bb pbrook
    val = T0 | ((uint64_t)T1 << 32);
1334 9ee6e8bb pbrook
    val = -val;
1335 9ee6e8bb pbrook
    T0 = val;
1336 9ee6e8bb pbrook
    T1 = val >> 32;
1337 9ee6e8bb pbrook
    FORCE_RET();
1338 9ee6e8bb pbrook
}
1339 9ee6e8bb pbrook
1340 9ee6e8bb pbrook
/* Scalar operations.  */
1341 9ee6e8bb pbrook
NEON_OP(dup_low16)
1342 9ee6e8bb pbrook
{
1343 9ee6e8bb pbrook
    T0 = (T0 & 0xffff) | (T0 << 16);
1344 9ee6e8bb pbrook
    FORCE_RET();
1345 9ee6e8bb pbrook
}
1346 9ee6e8bb pbrook
1347 9ee6e8bb pbrook
NEON_OP(dup_high16)
1348 9ee6e8bb pbrook
{
1349 9ee6e8bb pbrook
    T0 = (T0 >> 16) | (T0 & 0xffff0000);
1350 9ee6e8bb pbrook
    FORCE_RET();
1351 9ee6e8bb pbrook
}
1352 9ee6e8bb pbrook
1353 9ee6e8bb pbrook
/* Helper for VEXT */
1354 9ee6e8bb pbrook
NEON_OP(extract)
1355 9ee6e8bb pbrook
{
1356 9ee6e8bb pbrook
    int shift = PARAM1;
1357 9ee6e8bb pbrook
    T0 = (T0 >> shift) | (T1 << (32 - shift));
1358 9ee6e8bb pbrook
    FORCE_RET();
1359 9ee6e8bb pbrook
}
1360 9ee6e8bb pbrook
1361 9ee6e8bb pbrook
/* Pairwise add long.  Named type is source type.  */
1362 9ee6e8bb pbrook
NEON_OP(paddl_s8)
1363 9ee6e8bb pbrook
{
1364 9ee6e8bb pbrook
    int8_t src1;
1365 9ee6e8bb pbrook
    int8_t src2;
1366 9ee6e8bb pbrook
    uint16_t result;
1367 9ee6e8bb pbrook
    src1 = T0 >> 24;
1368 9ee6e8bb pbrook
    src2 = T0 >> 16;
1369 9ee6e8bb pbrook
    result = (uint16_t)src1 + src2;
1370 9ee6e8bb pbrook
    src1 = T0 >> 8;
1371 9ee6e8bb pbrook
    src2 = T0;
1372 9ee6e8bb pbrook
    T0 = (uint16_t)((uint16_t)src1 + src2) | ((uint32_t)result << 16);
1373 9ee6e8bb pbrook
    FORCE_RET();
1374 9ee6e8bb pbrook
}
1375 9ee6e8bb pbrook
1376 9ee6e8bb pbrook
NEON_OP(paddl_u8)
1377 9ee6e8bb pbrook
{
1378 9ee6e8bb pbrook
    uint8_t src1;
1379 9ee6e8bb pbrook
    uint8_t src2;
1380 9ee6e8bb pbrook
    uint16_t result;
1381 9ee6e8bb pbrook
    src1 = T0 >> 24;
1382 9ee6e8bb pbrook
    src2 = T0 >> 16;
1383 9ee6e8bb pbrook
    result = (uint16_t)src1 + src2;
1384 9ee6e8bb pbrook
    src1 = T0 >> 8;
1385 9ee6e8bb pbrook
    src2 = T0;
1386 9ee6e8bb pbrook
    T0 = (uint16_t)((uint16_t)src1 + src2) | ((uint32_t)result << 16);
1387 9ee6e8bb pbrook
    FORCE_RET();
1388 9ee6e8bb pbrook
}
1389 9ee6e8bb pbrook
1390 9ee6e8bb pbrook
NEON_OP(paddl_s16)
1391 9ee6e8bb pbrook
{
1392 9ee6e8bb pbrook
    T0 = (uint32_t)(int16_t)T0 + (uint32_t)(int16_t)(T0 >> 16);
1393 9ee6e8bb pbrook
    FORCE_RET();
1394 9ee6e8bb pbrook
}
1395 9ee6e8bb pbrook
1396 9ee6e8bb pbrook
NEON_OP(paddl_u16)
1397 9ee6e8bb pbrook
{
1398 9ee6e8bb pbrook
    T0 = (uint32_t)(uint16_t)T0 + (uint32_t)(uint16_t)(T0 >> 16);
1399 9ee6e8bb pbrook
    FORCE_RET();
1400 9ee6e8bb pbrook
}
1401 9ee6e8bb pbrook
1402 9ee6e8bb pbrook
NEON_OP(paddl_s32)
1403 9ee6e8bb pbrook
{
1404 9ee6e8bb pbrook
    int64_t tmp;
1405 9ee6e8bb pbrook
    tmp = (int64_t)(int32_t)T0 + (int64_t)(int32_t)T1;
1406 9ee6e8bb pbrook
    T0 = tmp;
1407 9ee6e8bb pbrook
    T1 = tmp >> 32;
1408 9ee6e8bb pbrook
    FORCE_RET();
1409 9ee6e8bb pbrook
}
1410 9ee6e8bb pbrook
1411 9ee6e8bb pbrook
NEON_OP(paddl_u32)
1412 9ee6e8bb pbrook
{
1413 9ee6e8bb pbrook
    uint64_t tmp;
1414 9ee6e8bb pbrook
    tmp = (uint64_t)T0 + (uint64_t)T1;
1415 9ee6e8bb pbrook
    T0 = tmp;
1416 9ee6e8bb pbrook
    T1 = tmp >> 32;
1417 9ee6e8bb pbrook
    FORCE_RET();
1418 9ee6e8bb pbrook
}
1419 9ee6e8bb pbrook
1420 9ee6e8bb pbrook
/* Count Leading Sign/Zero Bits.  */
1421 9ee6e8bb pbrook
static inline int do_clz8(uint8_t x)
1422 9ee6e8bb pbrook
{
1423 9ee6e8bb pbrook
    int n;
1424 9ee6e8bb pbrook
    for (n = 8; x; n--)
1425 9ee6e8bb pbrook
        x >>= 1;
1426 9ee6e8bb pbrook
    return n;
1427 9ee6e8bb pbrook
}
1428 9ee6e8bb pbrook
1429 9ee6e8bb pbrook
static inline int do_clz16(uint16_t x)
1430 9ee6e8bb pbrook
{
1431 9ee6e8bb pbrook
    int n;
1432 9ee6e8bb pbrook
    for (n = 16; x; n--)
1433 9ee6e8bb pbrook
        x >>= 1;
1434 9ee6e8bb pbrook
    return n;
1435 9ee6e8bb pbrook
}
1436 9ee6e8bb pbrook
1437 9ee6e8bb pbrook
NEON_OP(clz_u8)
1438 9ee6e8bb pbrook
{
1439 9ee6e8bb pbrook
    uint32_t result;
1440 9ee6e8bb pbrook
    uint32_t tmp;
1441 9ee6e8bb pbrook
1442 9ee6e8bb pbrook
    tmp = T0;
1443 9ee6e8bb pbrook
    result = do_clz8(tmp);
1444 9ee6e8bb pbrook
    result |= do_clz8(tmp >> 8) << 8;
1445 9ee6e8bb pbrook
    result |= do_clz8(tmp >> 16) << 16;
1446 9ee6e8bb pbrook
    result |= do_clz8(tmp >> 24) << 24;
1447 9ee6e8bb pbrook
    T0 = result;
1448 9ee6e8bb pbrook
    FORCE_RET();
1449 9ee6e8bb pbrook
}
1450 9ee6e8bb pbrook
1451 9ee6e8bb pbrook
NEON_OP(clz_u16)
1452 9ee6e8bb pbrook
{
1453 9ee6e8bb pbrook
    uint32_t result;
1454 9ee6e8bb pbrook
    uint32_t tmp;
1455 9ee6e8bb pbrook
    tmp = T0;
1456 9ee6e8bb pbrook
    result = do_clz16(tmp);
1457 9ee6e8bb pbrook
    result |= do_clz16(tmp >> 16) << 16;
1458 9ee6e8bb pbrook
    T0 = result;
1459 9ee6e8bb pbrook
    FORCE_RET();
1460 9ee6e8bb pbrook
}
1461 9ee6e8bb pbrook
1462 9ee6e8bb pbrook
NEON_OP(cls_s8)
1463 9ee6e8bb pbrook
{
1464 9ee6e8bb pbrook
    uint32_t result;
1465 9ee6e8bb pbrook
    int8_t tmp;
1466 9ee6e8bb pbrook
    tmp = T0;
1467 9ee6e8bb pbrook
    result = do_clz8((tmp < 0) ? ~tmp : tmp) - 1;
1468 9ee6e8bb pbrook
    tmp = T0 >> 8;
1469 9ee6e8bb pbrook
    result |= (do_clz8((tmp < 0) ? ~tmp : tmp) - 1) << 8;
1470 9ee6e8bb pbrook
    tmp = T0 >> 16;
1471 9ee6e8bb pbrook
    result |= (do_clz8((tmp < 0) ? ~tmp : tmp) - 1) << 16;
1472 9ee6e8bb pbrook
    tmp = T0 >> 24;
1473 9ee6e8bb pbrook
    result |= (do_clz8((tmp < 0) ? ~tmp : tmp) - 1) << 24;
1474 9ee6e8bb pbrook
    T0 = result;
1475 9ee6e8bb pbrook
    FORCE_RET();
1476 9ee6e8bb pbrook
}
1477 9ee6e8bb pbrook
1478 9ee6e8bb pbrook
NEON_OP(cls_s16)
1479 9ee6e8bb pbrook
{
1480 9ee6e8bb pbrook
    uint32_t result;
1481 9ee6e8bb pbrook
    int16_t tmp;
1482 9ee6e8bb pbrook
    tmp = T0;
1483 9ee6e8bb pbrook
    result = do_clz16((tmp < 0) ? ~tmp : tmp) - 1;
1484 9ee6e8bb pbrook
    tmp = T0 >> 16;
1485 9ee6e8bb pbrook
    result |= (do_clz16((tmp < 0) ? ~tmp : tmp) - 1) << 16;
1486 9ee6e8bb pbrook
    T0 = result;
1487 9ee6e8bb pbrook
    FORCE_RET();
1488 9ee6e8bb pbrook
}
1489 9ee6e8bb pbrook
1490 9ee6e8bb pbrook
NEON_OP(cls_s32)
1491 9ee6e8bb pbrook
{
1492 9ee6e8bb pbrook
    int count;
1493 9ee6e8bb pbrook
    if ((int32_t)T0 < 0)
1494 9ee6e8bb pbrook
        T0 = ~T0;
1495 9ee6e8bb pbrook
    for (count = 32; T0 > 0; count--)
1496 9ee6e8bb pbrook
        T0 = T0 >> 1;
1497 9ee6e8bb pbrook
    T0 = count - 1;
1498 9ee6e8bb pbrook
    FORCE_RET();
1499 9ee6e8bb pbrook
}
1500 9ee6e8bb pbrook
1501 9ee6e8bb pbrook
/* Bit count.  */
1502 9ee6e8bb pbrook
NEON_OP(cnt_u8)
1503 9ee6e8bb pbrook
{
1504 9ee6e8bb pbrook
    T0 = (T0 & 0x55555555) + ((T0 >>  1) & 0x55555555);
1505 9ee6e8bb pbrook
    T0 = (T0 & 0x33333333) + ((T0 >>  2) & 0x33333333);
1506 9ee6e8bb pbrook
    T0 = (T0 & 0x0f0f0f0f) + ((T0 >>  4) & 0x0f0f0f0f);
1507 9ee6e8bb pbrook
    FORCE_RET();
1508 9ee6e8bb pbrook
}
1509 9ee6e8bb pbrook
1510 9ee6e8bb pbrook
/* Saturnating negation.  */
1511 9ee6e8bb pbrook
/* ??? Make these use NEON_VOP1 */
1512 9ee6e8bb pbrook
#define DO_QABS8(x) do { \
1513 9ee6e8bb pbrook
    if (x == (int8_t)0x80) { \
1514 9ee6e8bb pbrook
        x = 0x7f; \
1515 9ee6e8bb pbrook
        env->QF = 1; \
1516 9ee6e8bb pbrook
    } else if (x < 0) { \
1517 9ee6e8bb pbrook
        x = -x; \
1518 9ee6e8bb pbrook
    }} while (0)
1519 9ee6e8bb pbrook
NEON_OP(qabs_s8)
1520 9ee6e8bb pbrook
{
1521 9ee6e8bb pbrook
    neon_s8 vec;
1522 9ee6e8bb pbrook
    NEON_UNPACK(neon_s8, vec, T0);
1523 9ee6e8bb pbrook
    DO_QABS8(vec.v1);
1524 9ee6e8bb pbrook
    DO_QABS8(vec.v2);
1525 9ee6e8bb pbrook
    DO_QABS8(vec.v3);
1526 9ee6e8bb pbrook
    DO_QABS8(vec.v4);
1527 9ee6e8bb pbrook
    NEON_PACK(neon_s8, T0, vec);
1528 9ee6e8bb pbrook
    FORCE_RET();
1529 9ee6e8bb pbrook
}
1530 9ee6e8bb pbrook
#undef DO_QABS8
1531 9ee6e8bb pbrook
1532 9ee6e8bb pbrook
#define DO_QNEG8(x) do { \
1533 9ee6e8bb pbrook
    if (x == (int8_t)0x80) { \
1534 9ee6e8bb pbrook
        x = 0x7f; \
1535 9ee6e8bb pbrook
        env->QF = 1; \
1536 9ee6e8bb pbrook
    } else { \
1537 9ee6e8bb pbrook
        x = -x; \
1538 9ee6e8bb pbrook
    }} while (0)
1539 9ee6e8bb pbrook
NEON_OP(qneg_s8)
1540 9ee6e8bb pbrook
{
1541 9ee6e8bb pbrook
    neon_s8 vec;
1542 9ee6e8bb pbrook
    NEON_UNPACK(neon_s8, vec, T0);
1543 9ee6e8bb pbrook
    DO_QNEG8(vec.v1);
1544 9ee6e8bb pbrook
    DO_QNEG8(vec.v2);
1545 9ee6e8bb pbrook
    DO_QNEG8(vec.v3);
1546 9ee6e8bb pbrook
    DO_QNEG8(vec.v4);
1547 9ee6e8bb pbrook
    NEON_PACK(neon_s8, T0, vec);
1548 9ee6e8bb pbrook
    FORCE_RET();
1549 9ee6e8bb pbrook
}
1550 9ee6e8bb pbrook
#undef DO_QNEG8
1551 9ee6e8bb pbrook
1552 9ee6e8bb pbrook
#define DO_QABS16(x) do { \
1553 9ee6e8bb pbrook
    if (x == (int16_t)0x8000) { \
1554 9ee6e8bb pbrook
        x = 0x7fff; \
1555 9ee6e8bb pbrook
        env->QF = 1; \
1556 9ee6e8bb pbrook
    } else if (x < 0) { \
1557 9ee6e8bb pbrook
        x = -x; \
1558 9ee6e8bb pbrook
    }} while (0)
1559 9ee6e8bb pbrook
NEON_OP(qabs_s16)
1560 9ee6e8bb pbrook
{
1561 9ee6e8bb pbrook
    neon_s16 vec;
1562 9ee6e8bb pbrook
    NEON_UNPACK(neon_s16, vec, T0);
1563 9ee6e8bb pbrook
    DO_QABS16(vec.v1);
1564 9ee6e8bb pbrook
    DO_QABS16(vec.v2);
1565 9ee6e8bb pbrook
    NEON_PACK(neon_s16, T0, vec);
1566 9ee6e8bb pbrook
    FORCE_RET();
1567 9ee6e8bb pbrook
}
1568 9ee6e8bb pbrook
#undef DO_QABS16
1569 9ee6e8bb pbrook
1570 9ee6e8bb pbrook
#define DO_QNEG16(x) do { \
1571 9ee6e8bb pbrook
    if (x == (int16_t)0x8000) { \
1572 9ee6e8bb pbrook
        x = 0x7fff; \
1573 9ee6e8bb pbrook
        env->QF = 1; \
1574 9ee6e8bb pbrook
    } else { \
1575 9ee6e8bb pbrook
        x = -x; \
1576 9ee6e8bb pbrook
    }} while (0)
1577 9ee6e8bb pbrook
NEON_OP(qneg_s16)
1578 9ee6e8bb pbrook
{
1579 9ee6e8bb pbrook
    neon_s16 vec;
1580 9ee6e8bb pbrook
    NEON_UNPACK(neon_s16, vec, T0);
1581 9ee6e8bb pbrook
    DO_QNEG16(vec.v1);
1582 9ee6e8bb pbrook
    DO_QNEG16(vec.v2);
1583 9ee6e8bb pbrook
    NEON_PACK(neon_s16, T0, vec);
1584 9ee6e8bb pbrook
    FORCE_RET();
1585 9ee6e8bb pbrook
}
1586 9ee6e8bb pbrook
#undef DO_QNEG16
1587 9ee6e8bb pbrook
1588 9ee6e8bb pbrook
NEON_OP(qabs_s32)
1589 9ee6e8bb pbrook
{
1590 9ee6e8bb pbrook
    if (T0 == 0x80000000) {
1591 9ee6e8bb pbrook
        T0 = 0x7fffffff;
1592 9ee6e8bb pbrook
        env->QF = 1;
1593 9ee6e8bb pbrook
    } else if ((int32_t)T0 < 0) {
1594 9ee6e8bb pbrook
        T0 = -T0;
1595 9ee6e8bb pbrook
    }
1596 9ee6e8bb pbrook
    FORCE_RET();
1597 9ee6e8bb pbrook
}
1598 9ee6e8bb pbrook
1599 9ee6e8bb pbrook
NEON_OP(qneg_s32)
1600 9ee6e8bb pbrook
{
1601 9ee6e8bb pbrook
    if (T0 == 0x80000000) {
1602 9ee6e8bb pbrook
        T0 = 0x7fffffff;
1603 9ee6e8bb pbrook
        env->QF = 1;
1604 9ee6e8bb pbrook
    } else {
1605 9ee6e8bb pbrook
        T0 = -T0;
1606 9ee6e8bb pbrook
    }
1607 9ee6e8bb pbrook
    FORCE_RET();
1608 9ee6e8bb pbrook
}
1609 9ee6e8bb pbrook
1610 9ee6e8bb pbrook
/* Unary opperations */
1611 9ee6e8bb pbrook
#define NEON_FN(dest, src, dummy) dest = (src < 0) ? -src : src
1612 9ee6e8bb pbrook
NEON_VOP1(abs_s8, neon_s8, 4)
1613 9ee6e8bb pbrook
NEON_VOP1(abs_s16, neon_s16, 2)
1614 9ee6e8bb pbrook
NEON_OP(abs_s32)
1615 9ee6e8bb pbrook
{
1616 9ee6e8bb pbrook
    if ((int32_t)T0 < 0)
1617 9ee6e8bb pbrook
        T0 = -T0;
1618 9ee6e8bb pbrook
    FORCE_RET();
1619 9ee6e8bb pbrook
}
1620 9ee6e8bb pbrook
#undef NEON_FN
1621 9ee6e8bb pbrook
1622 9ee6e8bb pbrook
/* Transpose.  Argument order is rather strange to avoid special casing
1623 9ee6e8bb pbrook
   the tranlation code.
1624 9ee6e8bb pbrook
   On input T0 = rm, T1 = rd.  On output T0 = rd, T1 = rm  */
1625 9ee6e8bb pbrook
NEON_OP(trn_u8)
1626 9ee6e8bb pbrook
{
1627 9ee6e8bb pbrook
    uint32_t rd;
1628 9ee6e8bb pbrook
    uint32_t rm;
1629 9ee6e8bb pbrook
    rd = ((T0 & 0x00ff00ff) << 8) | (T1 & 0x00ff00ff);
1630 9ee6e8bb pbrook
    rm = ((T1 & 0xff00ff00) >> 8) | (T0 & 0xff00ff00);
1631 9ee6e8bb pbrook
    T0 = rd;
1632 9ee6e8bb pbrook
    T1 = rm;
1633 9ee6e8bb pbrook
    FORCE_RET();
1634 9ee6e8bb pbrook
}
1635 9ee6e8bb pbrook
1636 9ee6e8bb pbrook
NEON_OP(trn_u16)
1637 9ee6e8bb pbrook
{
1638 9ee6e8bb pbrook
    uint32_t rd;
1639 9ee6e8bb pbrook
    uint32_t rm;
1640 9ee6e8bb pbrook
    rd = (T0 << 16) | (T1 & 0xffff);
1641 9ee6e8bb pbrook
    rm = (T1 >> 16) | (T0 & 0xffff0000);
1642 9ee6e8bb pbrook
    T0 = rd;
1643 9ee6e8bb pbrook
    T1 = rm;
1644 9ee6e8bb pbrook
    FORCE_RET();
1645 9ee6e8bb pbrook
}
1646 9ee6e8bb pbrook
1647 9ee6e8bb pbrook
/* Worker routines for zip and unzip.  */
1648 9ee6e8bb pbrook
NEON_OP(unzip_u8)
1649 9ee6e8bb pbrook
{
1650 9ee6e8bb pbrook
    uint32_t rd;
1651 9ee6e8bb pbrook
    uint32_t rm;
1652 9ee6e8bb pbrook
    rd = (T0 & 0xff) | ((T0 >> 8) & 0xff00)
1653 9ee6e8bb pbrook
         | ((T1 << 16) & 0xff0000) | ((T1 << 8) & 0xff000000);
1654 9ee6e8bb pbrook
    rm = ((T0 >> 8) & 0xff) | ((T0 >> 16) & 0xff00)
1655 9ee6e8bb pbrook
         | ((T1 << 8) & 0xff0000) | (T1 & 0xff000000);
1656 9ee6e8bb pbrook
    T0 = rd;
1657 9ee6e8bb pbrook
    T1 = rm;
1658 9ee6e8bb pbrook
    FORCE_RET();
1659 9ee6e8bb pbrook
}
1660 9ee6e8bb pbrook
1661 9ee6e8bb pbrook
NEON_OP(zip_u8)
1662 9ee6e8bb pbrook
{
1663 9ee6e8bb pbrook
    uint32_t rd;
1664 9ee6e8bb pbrook
    uint32_t rm;
1665 9ee6e8bb pbrook
    rd = (T0 & 0xff) | ((T1 << 8) & 0xff00)
1666 9ee6e8bb pbrook
         | ((T0 << 16) & 0xff0000) | ((T1 << 24) & 0xff000000);
1667 9ee6e8bb pbrook
    rm = ((T0 >> 16) & 0xff) | ((T1 >> 8) & 0xff00)
1668 9ee6e8bb pbrook
         | ((T0 >> 8) & 0xff0000) | (T1 & 0xff000000);
1669 9ee6e8bb pbrook
    T0 = rd;
1670 9ee6e8bb pbrook
    T1 = rm;
1671 9ee6e8bb pbrook
    FORCE_RET();
1672 9ee6e8bb pbrook
}
1673 9ee6e8bb pbrook
1674 9ee6e8bb pbrook
NEON_OP(zip_u16)
1675 9ee6e8bb pbrook
{
1676 9ee6e8bb pbrook
    uint32_t tmp;
1677 9ee6e8bb pbrook
1678 9ee6e8bb pbrook
    tmp = (T0 & 0xffff) | (T1 << 16);
1679 9ee6e8bb pbrook
    T1 = (T1 & 0xffff0000) | (T0 >> 16);
1680 9ee6e8bb pbrook
    T0 = tmp;
1681 9ee6e8bb pbrook
    FORCE_RET();
1682 9ee6e8bb pbrook
}
1683 9ee6e8bb pbrook
1684 9ee6e8bb pbrook
NEON_OP(dup_u8)
1685 9ee6e8bb pbrook
{
1686 9ee6e8bb pbrook
    T0 = (T0 >> PARAM1) & 0xff;
1687 9ee6e8bb pbrook
    T0 |= T0 << 8;
1688 9ee6e8bb pbrook
    T0 |= T0 << 16;
1689 9ee6e8bb pbrook
    FORCE_RET();
1690 9ee6e8bb pbrook
}