target-arm: A64: Implement AdvSIMD reciprocal estimate insns URECPE, FRECPE
[qemu.git] / target-arm / translate.c
1 /*
2 * ARM translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 */
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
26
27 #include "cpu.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30 #include "qemu/log.h"
31 #include "qemu/bitops.h"
32
33 #include "helper.h"
34 #define GEN_HELPER 1
35 #include "helper.h"
36
37 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
38 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
39 /* currently all emulated v5 cores are also v5TE, so don't bother */
40 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
41 #define ENABLE_ARCH_5J 0
42 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
43 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
44 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
45 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
47
48 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
49
50 #include "translate.h"
51 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
52
53 #if defined(CONFIG_USER_ONLY)
54 #define IS_USER(s) 1
55 #else
56 #define IS_USER(s) (s->user)
57 #endif
58
59 TCGv_ptr cpu_env;
60 /* We reuse the same 64-bit temporaries for efficiency. */
61 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
62 static TCGv_i32 cpu_R[16];
63 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
64 static TCGv_i64 cpu_exclusive_addr;
65 static TCGv_i64 cpu_exclusive_val;
66 #ifdef CONFIG_USER_ONLY
67 static TCGv_i64 cpu_exclusive_test;
68 static TCGv_i32 cpu_exclusive_info;
69 #endif
70
71 /* FIXME: These should be removed. */
72 static TCGv_i32 cpu_F0s, cpu_F1s;
73 static TCGv_i64 cpu_F0d, cpu_F1d;
74
75 #include "exec/gen-icount.h"
76
77 static const char *regnames[] =
78 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
79 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
80
81 /* initialize TCG globals. */
82 void arm_translate_init(void)
83 {
84 int i;
85
86 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
87
88 for (i = 0; i < 16; i++) {
89 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
90 offsetof(CPUARMState, regs[i]),
91 regnames[i]);
92 }
93 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
94 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
95 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
96 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
97
98 cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
99 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
100 cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
101 offsetof(CPUARMState, exclusive_val), "exclusive_val");
102 #ifdef CONFIG_USER_ONLY
103 cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
104 offsetof(CPUARMState, exclusive_test), "exclusive_test");
105 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
106 offsetof(CPUARMState, exclusive_info), "exclusive_info");
107 #endif
108
109 a64_translate_init();
110 }
111
112 static inline TCGv_i32 load_cpu_offset(int offset)
113 {
114 TCGv_i32 tmp = tcg_temp_new_i32();
115 tcg_gen_ld_i32(tmp, cpu_env, offset);
116 return tmp;
117 }
118
119 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
120
121 static inline void store_cpu_offset(TCGv_i32 var, int offset)
122 {
123 tcg_gen_st_i32(var, cpu_env, offset);
124 tcg_temp_free_i32(var);
125 }
126
127 #define store_cpu_field(var, name) \
128 store_cpu_offset(var, offsetof(CPUARMState, name))
129
130 /* Set a variable to the value of a CPU register. */
131 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
132 {
133 if (reg == 15) {
134 uint32_t addr;
135 /* normally, since we updated PC, we need only to add one insn */
136 if (s->thumb)
137 addr = (long)s->pc + 2;
138 else
139 addr = (long)s->pc + 4;
140 tcg_gen_movi_i32(var, addr);
141 } else {
142 tcg_gen_mov_i32(var, cpu_R[reg]);
143 }
144 }
145
146 /* Create a new temporary and set it to the value of a CPU register. */
147 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
148 {
149 TCGv_i32 tmp = tcg_temp_new_i32();
150 load_reg_var(s, tmp, reg);
151 return tmp;
152 }
153
154 /* Set a CPU register. The source must be a temporary and will be
155 marked as dead. */
156 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
157 {
158 if (reg == 15) {
159 tcg_gen_andi_i32(var, var, ~1);
160 s->is_jmp = DISAS_JUMP;
161 }
162 tcg_gen_mov_i32(cpu_R[reg], var);
163 tcg_temp_free_i32(var);
164 }
165
166 /* Value extensions. */
167 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
168 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
169 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
170 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
171
172 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
173 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
174
175
176 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
177 {
178 TCGv_i32 tmp_mask = tcg_const_i32(mask);
179 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
180 tcg_temp_free_i32(tmp_mask);
181 }
182 /* Set NZCV flags from the high 4 bits of var. */
183 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
184
185 static void gen_exception(int excp)
186 {
187 TCGv_i32 tmp = tcg_temp_new_i32();
188 tcg_gen_movi_i32(tmp, excp);
189 gen_helper_exception(cpu_env, tmp);
190 tcg_temp_free_i32(tmp);
191 }
192
193 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
194 {
195 TCGv_i32 tmp1 = tcg_temp_new_i32();
196 TCGv_i32 tmp2 = tcg_temp_new_i32();
197 tcg_gen_ext16s_i32(tmp1, a);
198 tcg_gen_ext16s_i32(tmp2, b);
199 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
200 tcg_temp_free_i32(tmp2);
201 tcg_gen_sari_i32(a, a, 16);
202 tcg_gen_sari_i32(b, b, 16);
203 tcg_gen_mul_i32(b, b, a);
204 tcg_gen_mov_i32(a, tmp1);
205 tcg_temp_free_i32(tmp1);
206 }
207
208 /* Byteswap each halfword. */
209 static void gen_rev16(TCGv_i32 var)
210 {
211 TCGv_i32 tmp = tcg_temp_new_i32();
212 tcg_gen_shri_i32(tmp, var, 8);
213 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
214 tcg_gen_shli_i32(var, var, 8);
215 tcg_gen_andi_i32(var, var, 0xff00ff00);
216 tcg_gen_or_i32(var, var, tmp);
217 tcg_temp_free_i32(tmp);
218 }
219
220 /* Byteswap low halfword and sign extend. */
221 static void gen_revsh(TCGv_i32 var)
222 {
223 tcg_gen_ext16u_i32(var, var);
224 tcg_gen_bswap16_i32(var, var);
225 tcg_gen_ext16s_i32(var, var);
226 }
227
228 /* Unsigned bitfield extract. */
229 static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
230 {
231 if (shift)
232 tcg_gen_shri_i32(var, var, shift);
233 tcg_gen_andi_i32(var, var, mask);
234 }
235
236 /* Signed bitfield extract. */
237 static void gen_sbfx(TCGv_i32 var, int shift, int width)
238 {
239 uint32_t signbit;
240
241 if (shift)
242 tcg_gen_sari_i32(var, var, shift);
243 if (shift + width < 32) {
244 signbit = 1u << (width - 1);
245 tcg_gen_andi_i32(var, var, (1u << width) - 1);
246 tcg_gen_xori_i32(var, var, signbit);
247 tcg_gen_subi_i32(var, var, signbit);
248 }
249 }
250
251 /* Return (b << 32) + a. Mark inputs as dead */
252 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
253 {
254 TCGv_i64 tmp64 = tcg_temp_new_i64();
255
256 tcg_gen_extu_i32_i64(tmp64, b);
257 tcg_temp_free_i32(b);
258 tcg_gen_shli_i64(tmp64, tmp64, 32);
259 tcg_gen_add_i64(a, tmp64, a);
260
261 tcg_temp_free_i64(tmp64);
262 return a;
263 }
264
265 /* Return (b << 32) - a. Mark inputs as dead. */
266 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
267 {
268 TCGv_i64 tmp64 = tcg_temp_new_i64();
269
270 tcg_gen_extu_i32_i64(tmp64, b);
271 tcg_temp_free_i32(b);
272 tcg_gen_shli_i64(tmp64, tmp64, 32);
273 tcg_gen_sub_i64(a, tmp64, a);
274
275 tcg_temp_free_i64(tmp64);
276 return a;
277 }
278
279 /* 32x32->64 multiply. Marks inputs as dead. */
280 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
281 {
282 TCGv_i32 lo = tcg_temp_new_i32();
283 TCGv_i32 hi = tcg_temp_new_i32();
284 TCGv_i64 ret;
285
286 tcg_gen_mulu2_i32(lo, hi, a, b);
287 tcg_temp_free_i32(a);
288 tcg_temp_free_i32(b);
289
290 ret = tcg_temp_new_i64();
291 tcg_gen_concat_i32_i64(ret, lo, hi);
292 tcg_temp_free_i32(lo);
293 tcg_temp_free_i32(hi);
294
295 return ret;
296 }
297
298 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
299 {
300 TCGv_i32 lo = tcg_temp_new_i32();
301 TCGv_i32 hi = tcg_temp_new_i32();
302 TCGv_i64 ret;
303
304 tcg_gen_muls2_i32(lo, hi, a, b);
305 tcg_temp_free_i32(a);
306 tcg_temp_free_i32(b);
307
308 ret = tcg_temp_new_i64();
309 tcg_gen_concat_i32_i64(ret, lo, hi);
310 tcg_temp_free_i32(lo);
311 tcg_temp_free_i32(hi);
312
313 return ret;
314 }
315
316 /* Swap low and high halfwords. */
317 static void gen_swap_half(TCGv_i32 var)
318 {
319 TCGv_i32 tmp = tcg_temp_new_i32();
320 tcg_gen_shri_i32(tmp, var, 16);
321 tcg_gen_shli_i32(var, var, 16);
322 tcg_gen_or_i32(var, var, tmp);
323 tcg_temp_free_i32(tmp);
324 }
325
326 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
327 tmp = (t0 ^ t1) & 0x8000;
328 t0 &= ~0x8000;
329 t1 &= ~0x8000;
330 t0 = (t0 + t1) ^ tmp;
331 */
332
333 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
334 {
335 TCGv_i32 tmp = tcg_temp_new_i32();
336 tcg_gen_xor_i32(tmp, t0, t1);
337 tcg_gen_andi_i32(tmp, tmp, 0x8000);
338 tcg_gen_andi_i32(t0, t0, ~0x8000);
339 tcg_gen_andi_i32(t1, t1, ~0x8000);
340 tcg_gen_add_i32(t0, t0, t1);
341 tcg_gen_xor_i32(t0, t0, tmp);
342 tcg_temp_free_i32(tmp);
343 tcg_temp_free_i32(t1);
344 }
345
346 /* Set CF to the top bit of var. */
347 static void gen_set_CF_bit31(TCGv_i32 var)
348 {
349 tcg_gen_shri_i32(cpu_CF, var, 31);
350 }
351
352 /* Set N and Z flags from var. */
353 static inline void gen_logic_CC(TCGv_i32 var)
354 {
355 tcg_gen_mov_i32(cpu_NF, var);
356 tcg_gen_mov_i32(cpu_ZF, var);
357 }
358
359 /* T0 += T1 + CF. */
360 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
361 {
362 tcg_gen_add_i32(t0, t0, t1);
363 tcg_gen_add_i32(t0, t0, cpu_CF);
364 }
365
366 /* dest = T0 + T1 + CF. */
367 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
368 {
369 tcg_gen_add_i32(dest, t0, t1);
370 tcg_gen_add_i32(dest, dest, cpu_CF);
371 }
372
373 /* dest = T0 - T1 + CF - 1. */
374 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
375 {
376 tcg_gen_sub_i32(dest, t0, t1);
377 tcg_gen_add_i32(dest, dest, cpu_CF);
378 tcg_gen_subi_i32(dest, dest, 1);
379 }
380
381 /* dest = T0 + T1. Compute C, N, V and Z flags */
382 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
383 {
384 TCGv_i32 tmp = tcg_temp_new_i32();
385 tcg_gen_movi_i32(tmp, 0);
386 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
387 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
388 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
389 tcg_gen_xor_i32(tmp, t0, t1);
390 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
391 tcg_temp_free_i32(tmp);
392 tcg_gen_mov_i32(dest, cpu_NF);
393 }
394
395 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
396 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
397 {
398 TCGv_i32 tmp = tcg_temp_new_i32();
399 if (TCG_TARGET_HAS_add2_i32) {
400 tcg_gen_movi_i32(tmp, 0);
401 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
402 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
403 } else {
404 TCGv_i64 q0 = tcg_temp_new_i64();
405 TCGv_i64 q1 = tcg_temp_new_i64();
406 tcg_gen_extu_i32_i64(q0, t0);
407 tcg_gen_extu_i32_i64(q1, t1);
408 tcg_gen_add_i64(q0, q0, q1);
409 tcg_gen_extu_i32_i64(q1, cpu_CF);
410 tcg_gen_add_i64(q0, q0, q1);
411 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
412 tcg_temp_free_i64(q0);
413 tcg_temp_free_i64(q1);
414 }
415 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
416 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
417 tcg_gen_xor_i32(tmp, t0, t1);
418 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
419 tcg_temp_free_i32(tmp);
420 tcg_gen_mov_i32(dest, cpu_NF);
421 }
422
423 /* dest = T0 - T1. Compute C, N, V and Z flags */
424 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
425 {
426 TCGv_i32 tmp;
427 tcg_gen_sub_i32(cpu_NF, t0, t1);
428 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
429 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
430 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
431 tmp = tcg_temp_new_i32();
432 tcg_gen_xor_i32(tmp, t0, t1);
433 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
434 tcg_temp_free_i32(tmp);
435 tcg_gen_mov_i32(dest, cpu_NF);
436 }
437
438 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
439 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
440 {
441 TCGv_i32 tmp = tcg_temp_new_i32();
442 tcg_gen_not_i32(tmp, t1);
443 gen_adc_CC(dest, t0, tmp);
444 tcg_temp_free_i32(tmp);
445 }
446
447 #define GEN_SHIFT(name) \
448 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
449 { \
450 TCGv_i32 tmp1, tmp2, tmp3; \
451 tmp1 = tcg_temp_new_i32(); \
452 tcg_gen_andi_i32(tmp1, t1, 0xff); \
453 tmp2 = tcg_const_i32(0); \
454 tmp3 = tcg_const_i32(0x1f); \
455 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
456 tcg_temp_free_i32(tmp3); \
457 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
458 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
459 tcg_temp_free_i32(tmp2); \
460 tcg_temp_free_i32(tmp1); \
461 }
462 GEN_SHIFT(shl)
463 GEN_SHIFT(shr)
464 #undef GEN_SHIFT
465
466 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
467 {
468 TCGv_i32 tmp1, tmp2;
469 tmp1 = tcg_temp_new_i32();
470 tcg_gen_andi_i32(tmp1, t1, 0xff);
471 tmp2 = tcg_const_i32(0x1f);
472 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
473 tcg_temp_free_i32(tmp2);
474 tcg_gen_sar_i32(dest, t0, tmp1);
475 tcg_temp_free_i32(tmp1);
476 }
477
478 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
479 {
480 TCGv_i32 c0 = tcg_const_i32(0);
481 TCGv_i32 tmp = tcg_temp_new_i32();
482 tcg_gen_neg_i32(tmp, src);
483 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
484 tcg_temp_free_i32(c0);
485 tcg_temp_free_i32(tmp);
486 }
487
488 static void shifter_out_im(TCGv_i32 var, int shift)
489 {
490 if (shift == 0) {
491 tcg_gen_andi_i32(cpu_CF, var, 1);
492 } else {
493 tcg_gen_shri_i32(cpu_CF, var, shift);
494 if (shift != 31) {
495 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
496 }
497 }
498 }
499
500 /* Shift by immediate. Includes special handling for shift == 0. */
501 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
502 int shift, int flags)
503 {
504 switch (shiftop) {
505 case 0: /* LSL */
506 if (shift != 0) {
507 if (flags)
508 shifter_out_im(var, 32 - shift);
509 tcg_gen_shli_i32(var, var, shift);
510 }
511 break;
512 case 1: /* LSR */
513 if (shift == 0) {
514 if (flags) {
515 tcg_gen_shri_i32(cpu_CF, var, 31);
516 }
517 tcg_gen_movi_i32(var, 0);
518 } else {
519 if (flags)
520 shifter_out_im(var, shift - 1);
521 tcg_gen_shri_i32(var, var, shift);
522 }
523 break;
524 case 2: /* ASR */
525 if (shift == 0)
526 shift = 32;
527 if (flags)
528 shifter_out_im(var, shift - 1);
529 if (shift == 32)
530 shift = 31;
531 tcg_gen_sari_i32(var, var, shift);
532 break;
533 case 3: /* ROR/RRX */
534 if (shift != 0) {
535 if (flags)
536 shifter_out_im(var, shift - 1);
537 tcg_gen_rotri_i32(var, var, shift); break;
538 } else {
539 TCGv_i32 tmp = tcg_temp_new_i32();
540 tcg_gen_shli_i32(tmp, cpu_CF, 31);
541 if (flags)
542 shifter_out_im(var, 0);
543 tcg_gen_shri_i32(var, var, 1);
544 tcg_gen_or_i32(var, var, tmp);
545 tcg_temp_free_i32(tmp);
546 }
547 }
548 };
549
550 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
551 TCGv_i32 shift, int flags)
552 {
553 if (flags) {
554 switch (shiftop) {
555 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
556 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
557 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
558 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
559 }
560 } else {
561 switch (shiftop) {
562 case 0:
563 gen_shl(var, var, shift);
564 break;
565 case 1:
566 gen_shr(var, var, shift);
567 break;
568 case 2:
569 gen_sar(var, var, shift);
570 break;
571 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
572 tcg_gen_rotr_i32(var, var, shift); break;
573 }
574 }
575 tcg_temp_free_i32(shift);
576 }
577
578 #define PAS_OP(pfx) \
579 switch (op2) { \
580 case 0: gen_pas_helper(glue(pfx,add16)); break; \
581 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
582 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
583 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
584 case 4: gen_pas_helper(glue(pfx,add8)); break; \
585 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
586 }
587 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
588 {
589 TCGv_ptr tmp;
590
591 switch (op1) {
592 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
593 case 1:
594 tmp = tcg_temp_new_ptr();
595 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
596 PAS_OP(s)
597 tcg_temp_free_ptr(tmp);
598 break;
599 case 5:
600 tmp = tcg_temp_new_ptr();
601 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
602 PAS_OP(u)
603 tcg_temp_free_ptr(tmp);
604 break;
605 #undef gen_pas_helper
606 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
607 case 2:
608 PAS_OP(q);
609 break;
610 case 3:
611 PAS_OP(sh);
612 break;
613 case 6:
614 PAS_OP(uq);
615 break;
616 case 7:
617 PAS_OP(uh);
618 break;
619 #undef gen_pas_helper
620 }
621 }
622 #undef PAS_OP
623
624 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
625 #define PAS_OP(pfx) \
626 switch (op1) { \
627 case 0: gen_pas_helper(glue(pfx,add8)); break; \
628 case 1: gen_pas_helper(glue(pfx,add16)); break; \
629 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
630 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
631 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
632 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
633 }
634 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
635 {
636 TCGv_ptr tmp;
637
638 switch (op2) {
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
640 case 0:
641 tmp = tcg_temp_new_ptr();
642 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
643 PAS_OP(s)
644 tcg_temp_free_ptr(tmp);
645 break;
646 case 4:
647 tmp = tcg_temp_new_ptr();
648 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
649 PAS_OP(u)
650 tcg_temp_free_ptr(tmp);
651 break;
652 #undef gen_pas_helper
653 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
654 case 1:
655 PAS_OP(q);
656 break;
657 case 2:
658 PAS_OP(sh);
659 break;
660 case 5:
661 PAS_OP(uq);
662 break;
663 case 6:
664 PAS_OP(uh);
665 break;
666 #undef gen_pas_helper
667 }
668 }
669 #undef PAS_OP
670
671 /*
672 * generate a conditional branch based on ARM condition code cc.
673 * This is common between ARM and Aarch64 targets.
674 */
675 void arm_gen_test_cc(int cc, int label)
676 {
677 TCGv_i32 tmp;
678 int inv;
679
680 switch (cc) {
681 case 0: /* eq: Z */
682 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
683 break;
684 case 1: /* ne: !Z */
685 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
686 break;
687 case 2: /* cs: C */
688 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
689 break;
690 case 3: /* cc: !C */
691 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
692 break;
693 case 4: /* mi: N */
694 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
695 break;
696 case 5: /* pl: !N */
697 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
698 break;
699 case 6: /* vs: V */
700 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
701 break;
702 case 7: /* vc: !V */
703 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
704 break;
705 case 8: /* hi: C && !Z */
706 inv = gen_new_label();
707 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
708 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
709 gen_set_label(inv);
710 break;
711 case 9: /* ls: !C || Z */
712 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
713 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
714 break;
715 case 10: /* ge: N == V -> N ^ V == 0 */
716 tmp = tcg_temp_new_i32();
717 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
718 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
719 tcg_temp_free_i32(tmp);
720 break;
721 case 11: /* lt: N != V -> N ^ V != 0 */
722 tmp = tcg_temp_new_i32();
723 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
724 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
725 tcg_temp_free_i32(tmp);
726 break;
727 case 12: /* gt: !Z && N == V */
728 inv = gen_new_label();
729 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
730 tmp = tcg_temp_new_i32();
731 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
732 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
733 tcg_temp_free_i32(tmp);
734 gen_set_label(inv);
735 break;
736 case 13: /* le: Z || N != V */
737 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
738 tmp = tcg_temp_new_i32();
739 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
740 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
741 tcg_temp_free_i32(tmp);
742 break;
743 default:
744 fprintf(stderr, "Bad condition code 0x%x\n", cc);
745 abort();
746 }
747 }
748
749 static const uint8_t table_logic_cc[16] = {
750 1, /* and */
751 1, /* xor */
752 0, /* sub */
753 0, /* rsb */
754 0, /* add */
755 0, /* adc */
756 0, /* sbc */
757 0, /* rsc */
758 1, /* andl */
759 1, /* xorl */
760 0, /* cmp */
761 0, /* cmn */
762 1, /* orr */
763 1, /* mov */
764 1, /* bic */
765 1, /* mvn */
766 };
767
768 /* Set PC and Thumb state from an immediate address. */
769 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
770 {
771 TCGv_i32 tmp;
772
773 s->is_jmp = DISAS_UPDATE;
774 if (s->thumb != (addr & 1)) {
775 tmp = tcg_temp_new_i32();
776 tcg_gen_movi_i32(tmp, addr & 1);
777 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
778 tcg_temp_free_i32(tmp);
779 }
780 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
781 }
782
783 /* Set PC and Thumb state from var. var is marked as dead. */
784 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
785 {
786 s->is_jmp = DISAS_UPDATE;
787 tcg_gen_andi_i32(cpu_R[15], var, ~1);
788 tcg_gen_andi_i32(var, var, 1);
789 store_cpu_field(var, thumb);
790 }
791
792 /* Variant of store_reg which uses branch&exchange logic when storing
793 to r15 in ARM architecture v7 and above. The source must be a temporary
794 and will be marked as dead. */
795 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
796 int reg, TCGv_i32 var)
797 {
798 if (reg == 15 && ENABLE_ARCH_7) {
799 gen_bx(s, var);
800 } else {
801 store_reg(s, reg, var);
802 }
803 }
804
805 /* Variant of store_reg which uses branch&exchange logic when storing
806 * to r15 in ARM architecture v5T and above. This is used for storing
807 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
808 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
809 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
810 int reg, TCGv_i32 var)
811 {
812 if (reg == 15 && ENABLE_ARCH_5) {
813 gen_bx(s, var);
814 } else {
815 store_reg(s, reg, var);
816 }
817 }
818
819 /* Abstractions of "generate code to do a guest load/store for
820 * AArch32", where a vaddr is always 32 bits (and is zero
821 * extended if we're a 64 bit core) and data is also
822 * 32 bits unless specifically doing a 64 bit access.
823 * These functions work like tcg_gen_qemu_{ld,st}* except
824 * that the address argument is TCGv_i32 rather than TCGv.
825 */
826 #if TARGET_LONG_BITS == 32
827
828 #define DO_GEN_LD(SUFF, OPC) \
829 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
830 { \
831 tcg_gen_qemu_ld_i32(val, addr, index, OPC); \
832 }
833
834 #define DO_GEN_ST(SUFF, OPC) \
835 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
836 { \
837 tcg_gen_qemu_st_i32(val, addr, index, OPC); \
838 }
839
840 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
841 {
842 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
843 }
844
845 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
846 {
847 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
848 }
849
850 #else
851
852 #define DO_GEN_LD(SUFF, OPC) \
853 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
854 { \
855 TCGv addr64 = tcg_temp_new(); \
856 tcg_gen_extu_i32_i64(addr64, addr); \
857 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
858 tcg_temp_free(addr64); \
859 }
860
861 #define DO_GEN_ST(SUFF, OPC) \
862 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
863 { \
864 TCGv addr64 = tcg_temp_new(); \
865 tcg_gen_extu_i32_i64(addr64, addr); \
866 tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
867 tcg_temp_free(addr64); \
868 }
869
870 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
871 {
872 TCGv addr64 = tcg_temp_new();
873 tcg_gen_extu_i32_i64(addr64, addr);
874 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
875 tcg_temp_free(addr64);
876 }
877
878 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
879 {
880 TCGv addr64 = tcg_temp_new();
881 tcg_gen_extu_i32_i64(addr64, addr);
882 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
883 tcg_temp_free(addr64);
884 }
885
886 #endif
887
888 DO_GEN_LD(8s, MO_SB)
889 DO_GEN_LD(8u, MO_UB)
890 DO_GEN_LD(16s, MO_TESW)
891 DO_GEN_LD(16u, MO_TEUW)
892 DO_GEN_LD(32u, MO_TEUL)
893 DO_GEN_ST(8, MO_UB)
894 DO_GEN_ST(16, MO_TEUW)
895 DO_GEN_ST(32, MO_TEUL)
896
897 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
898 {
899 tcg_gen_movi_i32(cpu_R[15], val);
900 }
901
902 /* Force a TB lookup after an instruction that changes the CPU state. */
903 static inline void gen_lookup_tb(DisasContext *s)
904 {
905 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
906 s->is_jmp = DISAS_UPDATE;
907 }
908
909 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
910 TCGv_i32 var)
911 {
912 int val, rm, shift, shiftop;
913 TCGv_i32 offset;
914
915 if (!(insn & (1 << 25))) {
916 /* immediate */
917 val = insn & 0xfff;
918 if (!(insn & (1 << 23)))
919 val = -val;
920 if (val != 0)
921 tcg_gen_addi_i32(var, var, val);
922 } else {
923 /* shift/register */
924 rm = (insn) & 0xf;
925 shift = (insn >> 7) & 0x1f;
926 shiftop = (insn >> 5) & 3;
927 offset = load_reg(s, rm);
928 gen_arm_shift_im(offset, shiftop, shift, 0);
929 if (!(insn & (1 << 23)))
930 tcg_gen_sub_i32(var, var, offset);
931 else
932 tcg_gen_add_i32(var, var, offset);
933 tcg_temp_free_i32(offset);
934 }
935 }
936
937 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
938 int extra, TCGv_i32 var)
939 {
940 int val, rm;
941 TCGv_i32 offset;
942
943 if (insn & (1 << 22)) {
944 /* immediate */
945 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
946 if (!(insn & (1 << 23)))
947 val = -val;
948 val += extra;
949 if (val != 0)
950 tcg_gen_addi_i32(var, var, val);
951 } else {
952 /* register */
953 if (extra)
954 tcg_gen_addi_i32(var, var, extra);
955 rm = (insn) & 0xf;
956 offset = load_reg(s, rm);
957 if (!(insn & (1 << 23)))
958 tcg_gen_sub_i32(var, var, offset);
959 else
960 tcg_gen_add_i32(var, var, offset);
961 tcg_temp_free_i32(offset);
962 }
963 }
964
965 static TCGv_ptr get_fpstatus_ptr(int neon)
966 {
967 TCGv_ptr statusptr = tcg_temp_new_ptr();
968 int offset;
969 if (neon) {
970 offset = offsetof(CPUARMState, vfp.standard_fp_status);
971 } else {
972 offset = offsetof(CPUARMState, vfp.fp_status);
973 }
974 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
975 return statusptr;
976 }
977
978 #define VFP_OP2(name) \
979 static inline void gen_vfp_##name(int dp) \
980 { \
981 TCGv_ptr fpst = get_fpstatus_ptr(0); \
982 if (dp) { \
983 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
984 } else { \
985 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
986 } \
987 tcg_temp_free_ptr(fpst); \
988 }
989
990 VFP_OP2(add)
991 VFP_OP2(sub)
992 VFP_OP2(mul)
993 VFP_OP2(div)
994
995 #undef VFP_OP2
996
997 static inline void gen_vfp_F1_mul(int dp)
998 {
999 /* Like gen_vfp_mul() but put result in F1 */
1000 TCGv_ptr fpst = get_fpstatus_ptr(0);
1001 if (dp) {
1002 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1003 } else {
1004 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1005 }
1006 tcg_temp_free_ptr(fpst);
1007 }
1008
1009 static inline void gen_vfp_F1_neg(int dp)
1010 {
1011 /* Like gen_vfp_neg() but put result in F1 */
1012 if (dp) {
1013 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1014 } else {
1015 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1016 }
1017 }
1018
1019 static inline void gen_vfp_abs(int dp)
1020 {
1021 if (dp)
1022 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1023 else
1024 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1025 }
1026
1027 static inline void gen_vfp_neg(int dp)
1028 {
1029 if (dp)
1030 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1031 else
1032 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1033 }
1034
1035 static inline void gen_vfp_sqrt(int dp)
1036 {
1037 if (dp)
1038 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1039 else
1040 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1041 }
1042
1043 static inline void gen_vfp_cmp(int dp)
1044 {
1045 if (dp)
1046 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1047 else
1048 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1049 }
1050
1051 static inline void gen_vfp_cmpe(int dp)
1052 {
1053 if (dp)
1054 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1055 else
1056 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1057 }
1058
1059 static inline void gen_vfp_F1_ld0(int dp)
1060 {
1061 if (dp)
1062 tcg_gen_movi_i64(cpu_F1d, 0);
1063 else
1064 tcg_gen_movi_i32(cpu_F1s, 0);
1065 }
1066
1067 #define VFP_GEN_ITOF(name) \
1068 static inline void gen_vfp_##name(int dp, int neon) \
1069 { \
1070 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1071 if (dp) { \
1072 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1073 } else { \
1074 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1075 } \
1076 tcg_temp_free_ptr(statusptr); \
1077 }
1078
1079 VFP_GEN_ITOF(uito)
1080 VFP_GEN_ITOF(sito)
1081 #undef VFP_GEN_ITOF
1082
1083 #define VFP_GEN_FTOI(name) \
1084 static inline void gen_vfp_##name(int dp, int neon) \
1085 { \
1086 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1087 if (dp) { \
1088 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1089 } else { \
1090 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1091 } \
1092 tcg_temp_free_ptr(statusptr); \
1093 }
1094
1095 VFP_GEN_FTOI(toui)
1096 VFP_GEN_FTOI(touiz)
1097 VFP_GEN_FTOI(tosi)
1098 VFP_GEN_FTOI(tosiz)
1099 #undef VFP_GEN_FTOI
1100
1101 #define VFP_GEN_FIX(name, round) \
1102 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1103 { \
1104 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1105 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1106 if (dp) { \
1107 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1108 statusptr); \
1109 } else { \
1110 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1111 statusptr); \
1112 } \
1113 tcg_temp_free_i32(tmp_shift); \
1114 tcg_temp_free_ptr(statusptr); \
1115 }
1116 VFP_GEN_FIX(tosh, _round_to_zero)
1117 VFP_GEN_FIX(tosl, _round_to_zero)
1118 VFP_GEN_FIX(touh, _round_to_zero)
1119 VFP_GEN_FIX(toul, _round_to_zero)
1120 VFP_GEN_FIX(shto, )
1121 VFP_GEN_FIX(slto, )
1122 VFP_GEN_FIX(uhto, )
1123 VFP_GEN_FIX(ulto, )
1124 #undef VFP_GEN_FIX
1125
1126 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1127 {
1128 if (dp) {
1129 gen_aa32_ld64(cpu_F0d, addr, IS_USER(s));
1130 } else {
1131 gen_aa32_ld32u(cpu_F0s, addr, IS_USER(s));
1132 }
1133 }
1134
1135 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1136 {
1137 if (dp) {
1138 gen_aa32_st64(cpu_F0d, addr, IS_USER(s));
1139 } else {
1140 gen_aa32_st32(cpu_F0s, addr, IS_USER(s));
1141 }
1142 }
1143
1144 static inline long
1145 vfp_reg_offset (int dp, int reg)
1146 {
1147 if (dp)
1148 return offsetof(CPUARMState, vfp.regs[reg]);
1149 else if (reg & 1) {
1150 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1151 + offsetof(CPU_DoubleU, l.upper);
1152 } else {
1153 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1154 + offsetof(CPU_DoubleU, l.lower);
1155 }
1156 }
1157
1158 /* Return the offset of a 32-bit piece of a NEON register.
1159 zero is the least significant end of the register. */
1160 static inline long
1161 neon_reg_offset (int reg, int n)
1162 {
1163 int sreg;
1164 sreg = reg * 2 + n;
1165 return vfp_reg_offset(0, sreg);
1166 }
1167
1168 static TCGv_i32 neon_load_reg(int reg, int pass)
1169 {
1170 TCGv_i32 tmp = tcg_temp_new_i32();
1171 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1172 return tmp;
1173 }
1174
1175 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1176 {
1177 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1178 tcg_temp_free_i32(var);
1179 }
1180
1181 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1182 {
1183 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1184 }
1185
1186 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1187 {
1188 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1189 }
1190
1191 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1192 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1193 #define tcg_gen_st_f32 tcg_gen_st_i32
1194 #define tcg_gen_st_f64 tcg_gen_st_i64
1195
1196 static inline void gen_mov_F0_vreg(int dp, int reg)
1197 {
1198 if (dp)
1199 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1200 else
1201 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1202 }
1203
1204 static inline void gen_mov_F1_vreg(int dp, int reg)
1205 {
1206 if (dp)
1207 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1208 else
1209 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1210 }
1211
1212 static inline void gen_mov_vreg_F0(int dp, int reg)
1213 {
1214 if (dp)
1215 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1216 else
1217 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1218 }
1219
1220 #define ARM_CP_RW_BIT (1 << 20)
1221
1222 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1223 {
1224 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1225 }
1226
1227 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1228 {
1229 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1230 }
1231
1232 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1233 {
1234 TCGv_i32 var = tcg_temp_new_i32();
1235 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1236 return var;
1237 }
1238
1239 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1240 {
1241 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1242 tcg_temp_free_i32(var);
1243 }
1244
1245 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1246 {
1247 iwmmxt_store_reg(cpu_M0, rn);
1248 }
1249
1250 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1251 {
1252 iwmmxt_load_reg(cpu_M0, rn);
1253 }
1254
1255 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1256 {
1257 iwmmxt_load_reg(cpu_V1, rn);
1258 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1259 }
1260
1261 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1262 {
1263 iwmmxt_load_reg(cpu_V1, rn);
1264 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1265 }
1266
1267 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1268 {
1269 iwmmxt_load_reg(cpu_V1, rn);
1270 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1271 }
1272
1273 #define IWMMXT_OP(name) \
1274 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1275 { \
1276 iwmmxt_load_reg(cpu_V1, rn); \
1277 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1278 }
1279
1280 #define IWMMXT_OP_ENV(name) \
1281 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1282 { \
1283 iwmmxt_load_reg(cpu_V1, rn); \
1284 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1285 }
1286
1287 #define IWMMXT_OP_ENV_SIZE(name) \
1288 IWMMXT_OP_ENV(name##b) \
1289 IWMMXT_OP_ENV(name##w) \
1290 IWMMXT_OP_ENV(name##l)
1291
1292 #define IWMMXT_OP_ENV1(name) \
1293 static inline void gen_op_iwmmxt_##name##_M0(void) \
1294 { \
1295 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1296 }
1297
1298 IWMMXT_OP(maddsq)
1299 IWMMXT_OP(madduq)
1300 IWMMXT_OP(sadb)
1301 IWMMXT_OP(sadw)
1302 IWMMXT_OP(mulslw)
1303 IWMMXT_OP(mulshw)
1304 IWMMXT_OP(mululw)
1305 IWMMXT_OP(muluhw)
1306 IWMMXT_OP(macsw)
1307 IWMMXT_OP(macuw)
1308
1309 IWMMXT_OP_ENV_SIZE(unpackl)
1310 IWMMXT_OP_ENV_SIZE(unpackh)
1311
1312 IWMMXT_OP_ENV1(unpacklub)
1313 IWMMXT_OP_ENV1(unpackluw)
1314 IWMMXT_OP_ENV1(unpacklul)
1315 IWMMXT_OP_ENV1(unpackhub)
1316 IWMMXT_OP_ENV1(unpackhuw)
1317 IWMMXT_OP_ENV1(unpackhul)
1318 IWMMXT_OP_ENV1(unpacklsb)
1319 IWMMXT_OP_ENV1(unpacklsw)
1320 IWMMXT_OP_ENV1(unpacklsl)
1321 IWMMXT_OP_ENV1(unpackhsb)
1322 IWMMXT_OP_ENV1(unpackhsw)
1323 IWMMXT_OP_ENV1(unpackhsl)
1324
1325 IWMMXT_OP_ENV_SIZE(cmpeq)
1326 IWMMXT_OP_ENV_SIZE(cmpgtu)
1327 IWMMXT_OP_ENV_SIZE(cmpgts)
1328
1329 IWMMXT_OP_ENV_SIZE(mins)
1330 IWMMXT_OP_ENV_SIZE(minu)
1331 IWMMXT_OP_ENV_SIZE(maxs)
1332 IWMMXT_OP_ENV_SIZE(maxu)
1333
1334 IWMMXT_OP_ENV_SIZE(subn)
1335 IWMMXT_OP_ENV_SIZE(addn)
1336 IWMMXT_OP_ENV_SIZE(subu)
1337 IWMMXT_OP_ENV_SIZE(addu)
1338 IWMMXT_OP_ENV_SIZE(subs)
1339 IWMMXT_OP_ENV_SIZE(adds)
1340
1341 IWMMXT_OP_ENV(avgb0)
1342 IWMMXT_OP_ENV(avgb1)
1343 IWMMXT_OP_ENV(avgw0)
1344 IWMMXT_OP_ENV(avgw1)
1345
1346 IWMMXT_OP(msadb)
1347
1348 IWMMXT_OP_ENV(packuw)
1349 IWMMXT_OP_ENV(packul)
1350 IWMMXT_OP_ENV(packuq)
1351 IWMMXT_OP_ENV(packsw)
1352 IWMMXT_OP_ENV(packsl)
1353 IWMMXT_OP_ENV(packsq)
1354
1355 static void gen_op_iwmmxt_set_mup(void)
1356 {
1357 TCGv_i32 tmp;
1358 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1359 tcg_gen_ori_i32(tmp, tmp, 2);
1360 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1361 }
1362
1363 static void gen_op_iwmmxt_set_cup(void)
1364 {
1365 TCGv_i32 tmp;
1366 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1367 tcg_gen_ori_i32(tmp, tmp, 1);
1368 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1369 }
1370
1371 static void gen_op_iwmmxt_setpsr_nz(void)
1372 {
1373 TCGv_i32 tmp = tcg_temp_new_i32();
1374 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1375 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1376 }
1377
1378 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1379 {
1380 iwmmxt_load_reg(cpu_V1, rn);
1381 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1382 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1383 }
1384
1385 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1386 TCGv_i32 dest)
1387 {
1388 int rd;
1389 uint32_t offset;
1390 TCGv_i32 tmp;
1391
1392 rd = (insn >> 16) & 0xf;
1393 tmp = load_reg(s, rd);
1394
1395 offset = (insn & 0xff) << ((insn >> 7) & 2);
1396 if (insn & (1 << 24)) {
1397 /* Pre indexed */
1398 if (insn & (1 << 23))
1399 tcg_gen_addi_i32(tmp, tmp, offset);
1400 else
1401 tcg_gen_addi_i32(tmp, tmp, -offset);
1402 tcg_gen_mov_i32(dest, tmp);
1403 if (insn & (1 << 21))
1404 store_reg(s, rd, tmp);
1405 else
1406 tcg_temp_free_i32(tmp);
1407 } else if (insn & (1 << 21)) {
1408 /* Post indexed */
1409 tcg_gen_mov_i32(dest, tmp);
1410 if (insn & (1 << 23))
1411 tcg_gen_addi_i32(tmp, tmp, offset);
1412 else
1413 tcg_gen_addi_i32(tmp, tmp, -offset);
1414 store_reg(s, rd, tmp);
1415 } else if (!(insn & (1 << 23)))
1416 return 1;
1417 return 0;
1418 }
1419
1420 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1421 {
1422 int rd = (insn >> 0) & 0xf;
1423 TCGv_i32 tmp;
1424
1425 if (insn & (1 << 8)) {
1426 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1427 return 1;
1428 } else {
1429 tmp = iwmmxt_load_creg(rd);
1430 }
1431 } else {
1432 tmp = tcg_temp_new_i32();
1433 iwmmxt_load_reg(cpu_V0, rd);
1434 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1435 }
1436 tcg_gen_andi_i32(tmp, tmp, mask);
1437 tcg_gen_mov_i32(dest, tmp);
1438 tcg_temp_free_i32(tmp);
1439 return 0;
1440 }
1441
1442 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1443 (ie. an undefined instruction). */
1444 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1445 {
1446 int rd, wrd;
1447 int rdhi, rdlo, rd0, rd1, i;
1448 TCGv_i32 addr;
1449 TCGv_i32 tmp, tmp2, tmp3;
1450
1451 if ((insn & 0x0e000e00) == 0x0c000000) {
1452 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1453 wrd = insn & 0xf;
1454 rdlo = (insn >> 12) & 0xf;
1455 rdhi = (insn >> 16) & 0xf;
1456 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1457 iwmmxt_load_reg(cpu_V0, wrd);
1458 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1459 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1460 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1461 } else { /* TMCRR */
1462 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1463 iwmmxt_store_reg(cpu_V0, wrd);
1464 gen_op_iwmmxt_set_mup();
1465 }
1466 return 0;
1467 }
1468
1469 wrd = (insn >> 12) & 0xf;
1470 addr = tcg_temp_new_i32();
1471 if (gen_iwmmxt_address(s, insn, addr)) {
1472 tcg_temp_free_i32(addr);
1473 return 1;
1474 }
1475 if (insn & ARM_CP_RW_BIT) {
1476 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1477 tmp = tcg_temp_new_i32();
1478 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1479 iwmmxt_store_creg(wrd, tmp);
1480 } else {
1481 i = 1;
1482 if (insn & (1 << 8)) {
1483 if (insn & (1 << 22)) { /* WLDRD */
1484 gen_aa32_ld64(cpu_M0, addr, IS_USER(s));
1485 i = 0;
1486 } else { /* WLDRW wRd */
1487 tmp = tcg_temp_new_i32();
1488 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1489 }
1490 } else {
1491 tmp = tcg_temp_new_i32();
1492 if (insn & (1 << 22)) { /* WLDRH */
1493 gen_aa32_ld16u(tmp, addr, IS_USER(s));
1494 } else { /* WLDRB */
1495 gen_aa32_ld8u(tmp, addr, IS_USER(s));
1496 }
1497 }
1498 if (i) {
1499 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1500 tcg_temp_free_i32(tmp);
1501 }
1502 gen_op_iwmmxt_movq_wRn_M0(wrd);
1503 }
1504 } else {
1505 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1506 tmp = iwmmxt_load_creg(wrd);
1507 gen_aa32_st32(tmp, addr, IS_USER(s));
1508 } else {
1509 gen_op_iwmmxt_movq_M0_wRn(wrd);
1510 tmp = tcg_temp_new_i32();
1511 if (insn & (1 << 8)) {
1512 if (insn & (1 << 22)) { /* WSTRD */
1513 gen_aa32_st64(cpu_M0, addr, IS_USER(s));
1514 } else { /* WSTRW wRd */
1515 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1516 gen_aa32_st32(tmp, addr, IS_USER(s));
1517 }
1518 } else {
1519 if (insn & (1 << 22)) { /* WSTRH */
1520 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1521 gen_aa32_st16(tmp, addr, IS_USER(s));
1522 } else { /* WSTRB */
1523 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1524 gen_aa32_st8(tmp, addr, IS_USER(s));
1525 }
1526 }
1527 }
1528 tcg_temp_free_i32(tmp);
1529 }
1530 tcg_temp_free_i32(addr);
1531 return 0;
1532 }
1533
1534 if ((insn & 0x0f000000) != 0x0e000000)
1535 return 1;
1536
1537 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1538 case 0x000: /* WOR */
1539 wrd = (insn >> 12) & 0xf;
1540 rd0 = (insn >> 0) & 0xf;
1541 rd1 = (insn >> 16) & 0xf;
1542 gen_op_iwmmxt_movq_M0_wRn(rd0);
1543 gen_op_iwmmxt_orq_M0_wRn(rd1);
1544 gen_op_iwmmxt_setpsr_nz();
1545 gen_op_iwmmxt_movq_wRn_M0(wrd);
1546 gen_op_iwmmxt_set_mup();
1547 gen_op_iwmmxt_set_cup();
1548 break;
1549 case 0x011: /* TMCR */
1550 if (insn & 0xf)
1551 return 1;
1552 rd = (insn >> 12) & 0xf;
1553 wrd = (insn >> 16) & 0xf;
1554 switch (wrd) {
1555 case ARM_IWMMXT_wCID:
1556 case ARM_IWMMXT_wCASF:
1557 break;
1558 case ARM_IWMMXT_wCon:
1559 gen_op_iwmmxt_set_cup();
1560 /* Fall through. */
1561 case ARM_IWMMXT_wCSSF:
1562 tmp = iwmmxt_load_creg(wrd);
1563 tmp2 = load_reg(s, rd);
1564 tcg_gen_andc_i32(tmp, tmp, tmp2);
1565 tcg_temp_free_i32(tmp2);
1566 iwmmxt_store_creg(wrd, tmp);
1567 break;
1568 case ARM_IWMMXT_wCGR0:
1569 case ARM_IWMMXT_wCGR1:
1570 case ARM_IWMMXT_wCGR2:
1571 case ARM_IWMMXT_wCGR3:
1572 gen_op_iwmmxt_set_cup();
1573 tmp = load_reg(s, rd);
1574 iwmmxt_store_creg(wrd, tmp);
1575 break;
1576 default:
1577 return 1;
1578 }
1579 break;
1580 case 0x100: /* WXOR */
1581 wrd = (insn >> 12) & 0xf;
1582 rd0 = (insn >> 0) & 0xf;
1583 rd1 = (insn >> 16) & 0xf;
1584 gen_op_iwmmxt_movq_M0_wRn(rd0);
1585 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1586 gen_op_iwmmxt_setpsr_nz();
1587 gen_op_iwmmxt_movq_wRn_M0(wrd);
1588 gen_op_iwmmxt_set_mup();
1589 gen_op_iwmmxt_set_cup();
1590 break;
1591 case 0x111: /* TMRC */
1592 if (insn & 0xf)
1593 return 1;
1594 rd = (insn >> 12) & 0xf;
1595 wrd = (insn >> 16) & 0xf;
1596 tmp = iwmmxt_load_creg(wrd);
1597 store_reg(s, rd, tmp);
1598 break;
1599 case 0x300: /* WANDN */
1600 wrd = (insn >> 12) & 0xf;
1601 rd0 = (insn >> 0) & 0xf;
1602 rd1 = (insn >> 16) & 0xf;
1603 gen_op_iwmmxt_movq_M0_wRn(rd0);
1604 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1605 gen_op_iwmmxt_andq_M0_wRn(rd1);
1606 gen_op_iwmmxt_setpsr_nz();
1607 gen_op_iwmmxt_movq_wRn_M0(wrd);
1608 gen_op_iwmmxt_set_mup();
1609 gen_op_iwmmxt_set_cup();
1610 break;
1611 case 0x200: /* WAND */
1612 wrd = (insn >> 12) & 0xf;
1613 rd0 = (insn >> 0) & 0xf;
1614 rd1 = (insn >> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0);
1616 gen_op_iwmmxt_andq_M0_wRn(rd1);
1617 gen_op_iwmmxt_setpsr_nz();
1618 gen_op_iwmmxt_movq_wRn_M0(wrd);
1619 gen_op_iwmmxt_set_mup();
1620 gen_op_iwmmxt_set_cup();
1621 break;
1622 case 0x810: case 0xa10: /* WMADD */
1623 wrd = (insn >> 12) & 0xf;
1624 rd0 = (insn >> 0) & 0xf;
1625 rd1 = (insn >> 16) & 0xf;
1626 gen_op_iwmmxt_movq_M0_wRn(rd0);
1627 if (insn & (1 << 21))
1628 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1629 else
1630 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 break;
1634 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 16) & 0xf;
1637 rd1 = (insn >> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 switch ((insn >> 22) & 3) {
1640 case 0:
1641 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1642 break;
1643 case 1:
1644 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1645 break;
1646 case 2:
1647 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1648 break;
1649 case 3:
1650 return 1;
1651 }
1652 gen_op_iwmmxt_movq_wRn_M0(wrd);
1653 gen_op_iwmmxt_set_mup();
1654 gen_op_iwmmxt_set_cup();
1655 break;
1656 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1657 wrd = (insn >> 12) & 0xf;
1658 rd0 = (insn >> 16) & 0xf;
1659 rd1 = (insn >> 0) & 0xf;
1660 gen_op_iwmmxt_movq_M0_wRn(rd0);
1661 switch ((insn >> 22) & 3) {
1662 case 0:
1663 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1664 break;
1665 case 1:
1666 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1667 break;
1668 case 2:
1669 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1670 break;
1671 case 3:
1672 return 1;
1673 }
1674 gen_op_iwmmxt_movq_wRn_M0(wrd);
1675 gen_op_iwmmxt_set_mup();
1676 gen_op_iwmmxt_set_cup();
1677 break;
1678 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1679 wrd = (insn >> 12) & 0xf;
1680 rd0 = (insn >> 16) & 0xf;
1681 rd1 = (insn >> 0) & 0xf;
1682 gen_op_iwmmxt_movq_M0_wRn(rd0);
1683 if (insn & (1 << 22))
1684 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1685 else
1686 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1687 if (!(insn & (1 << 20)))
1688 gen_op_iwmmxt_addl_M0_wRn(wrd);
1689 gen_op_iwmmxt_movq_wRn_M0(wrd);
1690 gen_op_iwmmxt_set_mup();
1691 break;
1692 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1693 wrd = (insn >> 12) & 0xf;
1694 rd0 = (insn >> 16) & 0xf;
1695 rd1 = (insn >> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0);
1697 if (insn & (1 << 21)) {
1698 if (insn & (1 << 20))
1699 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1700 else
1701 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1702 } else {
1703 if (insn & (1 << 20))
1704 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1705 else
1706 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1707 }
1708 gen_op_iwmmxt_movq_wRn_M0(wrd);
1709 gen_op_iwmmxt_set_mup();
1710 break;
1711 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1712 wrd = (insn >> 12) & 0xf;
1713 rd0 = (insn >> 16) & 0xf;
1714 rd1 = (insn >> 0) & 0xf;
1715 gen_op_iwmmxt_movq_M0_wRn(rd0);
1716 if (insn & (1 << 21))
1717 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1718 else
1719 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1720 if (!(insn & (1 << 20))) {
1721 iwmmxt_load_reg(cpu_V1, wrd);
1722 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1723 }
1724 gen_op_iwmmxt_movq_wRn_M0(wrd);
1725 gen_op_iwmmxt_set_mup();
1726 break;
1727 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1728 wrd = (insn >> 12) & 0xf;
1729 rd0 = (insn >> 16) & 0xf;
1730 rd1 = (insn >> 0) & 0xf;
1731 gen_op_iwmmxt_movq_M0_wRn(rd0);
1732 switch ((insn >> 22) & 3) {
1733 case 0:
1734 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1735 break;
1736 case 1:
1737 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1738 break;
1739 case 2:
1740 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1741 break;
1742 case 3:
1743 return 1;
1744 }
1745 gen_op_iwmmxt_movq_wRn_M0(wrd);
1746 gen_op_iwmmxt_set_mup();
1747 gen_op_iwmmxt_set_cup();
1748 break;
1749 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1750 wrd = (insn >> 12) & 0xf;
1751 rd0 = (insn >> 16) & 0xf;
1752 rd1 = (insn >> 0) & 0xf;
1753 gen_op_iwmmxt_movq_M0_wRn(rd0);
1754 if (insn & (1 << 22)) {
1755 if (insn & (1 << 20))
1756 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1757 else
1758 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1759 } else {
1760 if (insn & (1 << 20))
1761 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1762 else
1763 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1764 }
1765 gen_op_iwmmxt_movq_wRn_M0(wrd);
1766 gen_op_iwmmxt_set_mup();
1767 gen_op_iwmmxt_set_cup();
1768 break;
1769 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1770 wrd = (insn >> 12) & 0xf;
1771 rd0 = (insn >> 16) & 0xf;
1772 rd1 = (insn >> 0) & 0xf;
1773 gen_op_iwmmxt_movq_M0_wRn(rd0);
1774 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1775 tcg_gen_andi_i32(tmp, tmp, 7);
1776 iwmmxt_load_reg(cpu_V1, rd1);
1777 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1778 tcg_temp_free_i32(tmp);
1779 gen_op_iwmmxt_movq_wRn_M0(wrd);
1780 gen_op_iwmmxt_set_mup();
1781 break;
1782 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1783 if (((insn >> 6) & 3) == 3)
1784 return 1;
1785 rd = (insn >> 12) & 0xf;
1786 wrd = (insn >> 16) & 0xf;
1787 tmp = load_reg(s, rd);
1788 gen_op_iwmmxt_movq_M0_wRn(wrd);
1789 switch ((insn >> 6) & 3) {
1790 case 0:
1791 tmp2 = tcg_const_i32(0xff);
1792 tmp3 = tcg_const_i32((insn & 7) << 3);
1793 break;
1794 case 1:
1795 tmp2 = tcg_const_i32(0xffff);
1796 tmp3 = tcg_const_i32((insn & 3) << 4);
1797 break;
1798 case 2:
1799 tmp2 = tcg_const_i32(0xffffffff);
1800 tmp3 = tcg_const_i32((insn & 1) << 5);
1801 break;
1802 default:
1803 TCGV_UNUSED_I32(tmp2);
1804 TCGV_UNUSED_I32(tmp3);
1805 }
1806 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1807 tcg_temp_free_i32(tmp3);
1808 tcg_temp_free_i32(tmp2);
1809 tcg_temp_free_i32(tmp);
1810 gen_op_iwmmxt_movq_wRn_M0(wrd);
1811 gen_op_iwmmxt_set_mup();
1812 break;
1813 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1814 rd = (insn >> 12) & 0xf;
1815 wrd = (insn >> 16) & 0xf;
1816 if (rd == 15 || ((insn >> 22) & 3) == 3)
1817 return 1;
1818 gen_op_iwmmxt_movq_M0_wRn(wrd);
1819 tmp = tcg_temp_new_i32();
1820 switch ((insn >> 22) & 3) {
1821 case 0:
1822 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1823 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1824 if (insn & 8) {
1825 tcg_gen_ext8s_i32(tmp, tmp);
1826 } else {
1827 tcg_gen_andi_i32(tmp, tmp, 0xff);
1828 }
1829 break;
1830 case 1:
1831 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1832 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1833 if (insn & 8) {
1834 tcg_gen_ext16s_i32(tmp, tmp);
1835 } else {
1836 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1837 }
1838 break;
1839 case 2:
1840 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1841 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1842 break;
1843 }
1844 store_reg(s, rd, tmp);
1845 break;
1846 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1847 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1848 return 1;
1849 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1850 switch ((insn >> 22) & 3) {
1851 case 0:
1852 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1853 break;
1854 case 1:
1855 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1856 break;
1857 case 2:
1858 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1859 break;
1860 }
1861 tcg_gen_shli_i32(tmp, tmp, 28);
1862 gen_set_nzcv(tmp);
1863 tcg_temp_free_i32(tmp);
1864 break;
1865 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1866 if (((insn >> 6) & 3) == 3)
1867 return 1;
1868 rd = (insn >> 12) & 0xf;
1869 wrd = (insn >> 16) & 0xf;
1870 tmp = load_reg(s, rd);
1871 switch ((insn >> 6) & 3) {
1872 case 0:
1873 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1874 break;
1875 case 1:
1876 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1877 break;
1878 case 2:
1879 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1880 break;
1881 }
1882 tcg_temp_free_i32(tmp);
1883 gen_op_iwmmxt_movq_wRn_M0(wrd);
1884 gen_op_iwmmxt_set_mup();
1885 break;
1886 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1887 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1888 return 1;
1889 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1890 tmp2 = tcg_temp_new_i32();
1891 tcg_gen_mov_i32(tmp2, tmp);
1892 switch ((insn >> 22) & 3) {
1893 case 0:
1894 for (i = 0; i < 7; i ++) {
1895 tcg_gen_shli_i32(tmp2, tmp2, 4);
1896 tcg_gen_and_i32(tmp, tmp, tmp2);
1897 }
1898 break;
1899 case 1:
1900 for (i = 0; i < 3; i ++) {
1901 tcg_gen_shli_i32(tmp2, tmp2, 8);
1902 tcg_gen_and_i32(tmp, tmp, tmp2);
1903 }
1904 break;
1905 case 2:
1906 tcg_gen_shli_i32(tmp2, tmp2, 16);
1907 tcg_gen_and_i32(tmp, tmp, tmp2);
1908 break;
1909 }
1910 gen_set_nzcv(tmp);
1911 tcg_temp_free_i32(tmp2);
1912 tcg_temp_free_i32(tmp);
1913 break;
1914 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1915 wrd = (insn >> 12) & 0xf;
1916 rd0 = (insn >> 16) & 0xf;
1917 gen_op_iwmmxt_movq_M0_wRn(rd0);
1918 switch ((insn >> 22) & 3) {
1919 case 0:
1920 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1921 break;
1922 case 1:
1923 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1924 break;
1925 case 2:
1926 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1927 break;
1928 case 3:
1929 return 1;
1930 }
1931 gen_op_iwmmxt_movq_wRn_M0(wrd);
1932 gen_op_iwmmxt_set_mup();
1933 break;
1934 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1935 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1936 return 1;
1937 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1938 tmp2 = tcg_temp_new_i32();
1939 tcg_gen_mov_i32(tmp2, tmp);
1940 switch ((insn >> 22) & 3) {
1941 case 0:
1942 for (i = 0; i < 7; i ++) {
1943 tcg_gen_shli_i32(tmp2, tmp2, 4);
1944 tcg_gen_or_i32(tmp, tmp, tmp2);
1945 }
1946 break;
1947 case 1:
1948 for (i = 0; i < 3; i ++) {
1949 tcg_gen_shli_i32(tmp2, tmp2, 8);
1950 tcg_gen_or_i32(tmp, tmp, tmp2);
1951 }
1952 break;
1953 case 2:
1954 tcg_gen_shli_i32(tmp2, tmp2, 16);
1955 tcg_gen_or_i32(tmp, tmp, tmp2);
1956 break;
1957 }
1958 gen_set_nzcv(tmp);
1959 tcg_temp_free_i32(tmp2);
1960 tcg_temp_free_i32(tmp);
1961 break;
1962 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1963 rd = (insn >> 12) & 0xf;
1964 rd0 = (insn >> 16) & 0xf;
1965 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1966 return 1;
1967 gen_op_iwmmxt_movq_M0_wRn(rd0);
1968 tmp = tcg_temp_new_i32();
1969 switch ((insn >> 22) & 3) {
1970 case 0:
1971 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1972 break;
1973 case 1:
1974 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1975 break;
1976 case 2:
1977 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1978 break;
1979 }
1980 store_reg(s, rd, tmp);
1981 break;
1982 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1983 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1984 wrd = (insn >> 12) & 0xf;
1985 rd0 = (insn >> 16) & 0xf;
1986 rd1 = (insn >> 0) & 0xf;
1987 gen_op_iwmmxt_movq_M0_wRn(rd0);
1988 switch ((insn >> 22) & 3) {
1989 case 0:
1990 if (insn & (1 << 21))
1991 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1992 else
1993 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1994 break;
1995 case 1:
1996 if (insn & (1 << 21))
1997 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1998 else
1999 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2000 break;
2001 case 2:
2002 if (insn & (1 << 21))
2003 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2004 else
2005 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2006 break;
2007 case 3:
2008 return 1;
2009 }
2010 gen_op_iwmmxt_movq_wRn_M0(wrd);
2011 gen_op_iwmmxt_set_mup();
2012 gen_op_iwmmxt_set_cup();
2013 break;
2014 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2015 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2016 wrd = (insn >> 12) & 0xf;
2017 rd0 = (insn >> 16) & 0xf;
2018 gen_op_iwmmxt_movq_M0_wRn(rd0);
2019 switch ((insn >> 22) & 3) {
2020 case 0:
2021 if (insn & (1 << 21))
2022 gen_op_iwmmxt_unpacklsb_M0();
2023 else
2024 gen_op_iwmmxt_unpacklub_M0();
2025 break;
2026 case 1:
2027 if (insn & (1 << 21))
2028 gen_op_iwmmxt_unpacklsw_M0();
2029 else
2030 gen_op_iwmmxt_unpackluw_M0();
2031 break;
2032 case 2:
2033 if (insn & (1 << 21))
2034 gen_op_iwmmxt_unpacklsl_M0();
2035 else
2036 gen_op_iwmmxt_unpacklul_M0();
2037 break;
2038 case 3:
2039 return 1;
2040 }
2041 gen_op_iwmmxt_movq_wRn_M0(wrd);
2042 gen_op_iwmmxt_set_mup();
2043 gen_op_iwmmxt_set_cup();
2044 break;
2045 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2046 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2047 wrd = (insn >> 12) & 0xf;
2048 rd0 = (insn >> 16) & 0xf;
2049 gen_op_iwmmxt_movq_M0_wRn(rd0);
2050 switch ((insn >> 22) & 3) {
2051 case 0:
2052 if (insn & (1 << 21))
2053 gen_op_iwmmxt_unpackhsb_M0();
2054 else
2055 gen_op_iwmmxt_unpackhub_M0();
2056 break;
2057 case 1:
2058 if (insn & (1 << 21))
2059 gen_op_iwmmxt_unpackhsw_M0();
2060 else
2061 gen_op_iwmmxt_unpackhuw_M0();
2062 break;
2063 case 2:
2064 if (insn & (1 << 21))
2065 gen_op_iwmmxt_unpackhsl_M0();
2066 else
2067 gen_op_iwmmxt_unpackhul_M0();
2068 break;
2069 case 3:
2070 return 1;
2071 }
2072 gen_op_iwmmxt_movq_wRn_M0(wrd);
2073 gen_op_iwmmxt_set_mup();
2074 gen_op_iwmmxt_set_cup();
2075 break;
2076 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2077 case 0x214: case 0x614: case 0xa14: case 0xe14:
2078 if (((insn >> 22) & 3) == 0)
2079 return 1;
2080 wrd = (insn >> 12) & 0xf;
2081 rd0 = (insn >> 16) & 0xf;
2082 gen_op_iwmmxt_movq_M0_wRn(rd0);
2083 tmp = tcg_temp_new_i32();
2084 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2085 tcg_temp_free_i32(tmp);
2086 return 1;
2087 }
2088 switch ((insn >> 22) & 3) {
2089 case 1:
2090 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2091 break;
2092 case 2:
2093 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2094 break;
2095 case 3:
2096 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2097 break;
2098 }
2099 tcg_temp_free_i32(tmp);
2100 gen_op_iwmmxt_movq_wRn_M0(wrd);
2101 gen_op_iwmmxt_set_mup();
2102 gen_op_iwmmxt_set_cup();
2103 break;
2104 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2105 case 0x014: case 0x414: case 0x814: case 0xc14:
2106 if (((insn >> 22) & 3) == 0)
2107 return 1;
2108 wrd = (insn >> 12) & 0xf;
2109 rd0 = (insn >> 16) & 0xf;
2110 gen_op_iwmmxt_movq_M0_wRn(rd0);
2111 tmp = tcg_temp_new_i32();
2112 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2113 tcg_temp_free_i32(tmp);
2114 return 1;
2115 }
2116 switch ((insn >> 22) & 3) {
2117 case 1:
2118 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2119 break;
2120 case 2:
2121 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2122 break;
2123 case 3:
2124 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2125 break;
2126 }
2127 tcg_temp_free_i32(tmp);
2128 gen_op_iwmmxt_movq_wRn_M0(wrd);
2129 gen_op_iwmmxt_set_mup();
2130 gen_op_iwmmxt_set_cup();
2131 break;
2132 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2133 case 0x114: case 0x514: case 0x914: case 0xd14:
2134 if (((insn >> 22) & 3) == 0)
2135 return 1;
2136 wrd = (insn >> 12) & 0xf;
2137 rd0 = (insn >> 16) & 0xf;
2138 gen_op_iwmmxt_movq_M0_wRn(rd0);
2139 tmp = tcg_temp_new_i32();
2140 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2141 tcg_temp_free_i32(tmp);
2142 return 1;
2143 }
2144 switch ((insn >> 22) & 3) {
2145 case 1:
2146 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2147 break;
2148 case 2:
2149 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2150 break;
2151 case 3:
2152 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2153 break;
2154 }
2155 tcg_temp_free_i32(tmp);
2156 gen_op_iwmmxt_movq_wRn_M0(wrd);
2157 gen_op_iwmmxt_set_mup();
2158 gen_op_iwmmxt_set_cup();
2159 break;
2160 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2161 case 0x314: case 0x714: case 0xb14: case 0xf14:
2162 if (((insn >> 22) & 3) == 0)
2163 return 1;
2164 wrd = (insn >> 12) & 0xf;
2165 rd0 = (insn >> 16) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0);
2167 tmp = tcg_temp_new_i32();
2168 switch ((insn >> 22) & 3) {
2169 case 1:
2170 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2171 tcg_temp_free_i32(tmp);
2172 return 1;
2173 }
2174 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2175 break;
2176 case 2:
2177 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2178 tcg_temp_free_i32(tmp);
2179 return 1;
2180 }
2181 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2182 break;
2183 case 3:
2184 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2185 tcg_temp_free_i32(tmp);
2186 return 1;
2187 }
2188 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2189 break;
2190 }
2191 tcg_temp_free_i32(tmp);
2192 gen_op_iwmmxt_movq_wRn_M0(wrd);
2193 gen_op_iwmmxt_set_mup();
2194 gen_op_iwmmxt_set_cup();
2195 break;
2196 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2197 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2198 wrd = (insn >> 12) & 0xf;
2199 rd0 = (insn >> 16) & 0xf;
2200 rd1 = (insn >> 0) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0);
2202 switch ((insn >> 22) & 3) {
2203 case 0:
2204 if (insn & (1 << 21))
2205 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_minub_M0_wRn(rd1);
2208 break;
2209 case 1:
2210 if (insn & (1 << 21))
2211 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2212 else
2213 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2214 break;
2215 case 2:
2216 if (insn & (1 << 21))
2217 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2218 else
2219 gen_op_iwmmxt_minul_M0_wRn(rd1);
2220 break;
2221 case 3:
2222 return 1;
2223 }
2224 gen_op_iwmmxt_movq_wRn_M0(wrd);
2225 gen_op_iwmmxt_set_mup();
2226 break;
2227 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2228 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2229 wrd = (insn >> 12) & 0xf;
2230 rd0 = (insn >> 16) & 0xf;
2231 rd1 = (insn >> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0);
2233 switch ((insn >> 22) & 3) {
2234 case 0:
2235 if (insn & (1 << 21))
2236 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2237 else
2238 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2239 break;
2240 case 1:
2241 if (insn & (1 << 21))
2242 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2243 else
2244 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2245 break;
2246 case 2:
2247 if (insn & (1 << 21))
2248 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2249 else
2250 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2251 break;
2252 case 3:
2253 return 1;
2254 }
2255 gen_op_iwmmxt_movq_wRn_M0(wrd);
2256 gen_op_iwmmxt_set_mup();
2257 break;
2258 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2259 case 0x402: case 0x502: case 0x602: case 0x702:
2260 wrd = (insn >> 12) & 0xf;
2261 rd0 = (insn >> 16) & 0xf;
2262 rd1 = (insn >> 0) & 0xf;
2263 gen_op_iwmmxt_movq_M0_wRn(rd0);
2264 tmp = tcg_const_i32((insn >> 20) & 3);
2265 iwmmxt_load_reg(cpu_V1, rd1);
2266 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2267 tcg_temp_free_i32(tmp);
2268 gen_op_iwmmxt_movq_wRn_M0(wrd);
2269 gen_op_iwmmxt_set_mup();
2270 break;
2271 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2272 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2273 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2274 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2275 wrd = (insn >> 12) & 0xf;
2276 rd0 = (insn >> 16) & 0xf;
2277 rd1 = (insn >> 0) & 0xf;
2278 gen_op_iwmmxt_movq_M0_wRn(rd0);
2279 switch ((insn >> 20) & 0xf) {
2280 case 0x0:
2281 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2282 break;
2283 case 0x1:
2284 gen_op_iwmmxt_subub_M0_wRn(rd1);
2285 break;
2286 case 0x3:
2287 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2288 break;
2289 case 0x4:
2290 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2291 break;
2292 case 0x5:
2293 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2294 break;
2295 case 0x7:
2296 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2297 break;
2298 case 0x8:
2299 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2300 break;
2301 case 0x9:
2302 gen_op_iwmmxt_subul_M0_wRn(rd1);
2303 break;
2304 case 0xb:
2305 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2306 break;
2307 default:
2308 return 1;
2309 }
2310 gen_op_iwmmxt_movq_wRn_M0(wrd);
2311 gen_op_iwmmxt_set_mup();
2312 gen_op_iwmmxt_set_cup();
2313 break;
2314 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2315 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2316 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2317 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2318 wrd = (insn >> 12) & 0xf;
2319 rd0 = (insn >> 16) & 0xf;
2320 gen_op_iwmmxt_movq_M0_wRn(rd0);
2321 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2322 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2323 tcg_temp_free_i32(tmp);
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 gen_op_iwmmxt_set_cup();
2327 break;
2328 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2329 case 0x418: case 0x518: case 0x618: case 0x718:
2330 case 0x818: case 0x918: case 0xa18: case 0xb18:
2331 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2332 wrd = (insn >> 12) & 0xf;
2333 rd0 = (insn >> 16) & 0xf;
2334 rd1 = (insn >> 0) & 0xf;
2335 gen_op_iwmmxt_movq_M0_wRn(rd0);
2336 switch ((insn >> 20) & 0xf) {
2337 case 0x0:
2338 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2339 break;
2340 case 0x1:
2341 gen_op_iwmmxt_addub_M0_wRn(rd1);
2342 break;
2343 case 0x3:
2344 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2345 break;
2346 case 0x4:
2347 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2348 break;
2349 case 0x5:
2350 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2351 break;
2352 case 0x7:
2353 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2354 break;
2355 case 0x8:
2356 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2357 break;
2358 case 0x9:
2359 gen_op_iwmmxt_addul_M0_wRn(rd1);
2360 break;
2361 case 0xb:
2362 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2363 break;
2364 default:
2365 return 1;
2366 }
2367 gen_op_iwmmxt_movq_wRn_M0(wrd);
2368 gen_op_iwmmxt_set_mup();
2369 gen_op_iwmmxt_set_cup();
2370 break;
2371 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2372 case 0x408: case 0x508: case 0x608: case 0x708:
2373 case 0x808: case 0x908: case 0xa08: case 0xb08:
2374 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2375 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2376 return 1;
2377 wrd = (insn >> 12) & 0xf;
2378 rd0 = (insn >> 16) & 0xf;
2379 rd1 = (insn >> 0) & 0xf;
2380 gen_op_iwmmxt_movq_M0_wRn(rd0);
2381 switch ((insn >> 22) & 3) {
2382 case 1:
2383 if (insn & (1 << 21))
2384 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2385 else
2386 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2387 break;
2388 case 2:
2389 if (insn & (1 << 21))
2390 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2391 else
2392 gen_op_iwmmxt_packul_M0_wRn(rd1);
2393 break;
2394 case 3:
2395 if (insn & (1 << 21))
2396 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2397 else
2398 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2399 break;
2400 }
2401 gen_op_iwmmxt_movq_wRn_M0(wrd);
2402 gen_op_iwmmxt_set_mup();
2403 gen_op_iwmmxt_set_cup();
2404 break;
2405 case 0x201: case 0x203: case 0x205: case 0x207:
2406 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2407 case 0x211: case 0x213: case 0x215: case 0x217:
2408 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2409 wrd = (insn >> 5) & 0xf;
2410 rd0 = (insn >> 12) & 0xf;
2411 rd1 = (insn >> 0) & 0xf;
2412 if (rd0 == 0xf || rd1 == 0xf)
2413 return 1;
2414 gen_op_iwmmxt_movq_M0_wRn(wrd);
2415 tmp = load_reg(s, rd0);
2416 tmp2 = load_reg(s, rd1);
2417 switch ((insn >> 16) & 0xf) {
2418 case 0x0: /* TMIA */
2419 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2420 break;
2421 case 0x8: /* TMIAPH */
2422 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2423 break;
2424 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2425 if (insn & (1 << 16))
2426 tcg_gen_shri_i32(tmp, tmp, 16);
2427 if (insn & (1 << 17))
2428 tcg_gen_shri_i32(tmp2, tmp2, 16);
2429 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2430 break;
2431 default:
2432 tcg_temp_free_i32(tmp2);
2433 tcg_temp_free_i32(tmp);
2434 return 1;
2435 }
2436 tcg_temp_free_i32(tmp2);
2437 tcg_temp_free_i32(tmp);
2438 gen_op_iwmmxt_movq_wRn_M0(wrd);
2439 gen_op_iwmmxt_set_mup();
2440 break;
2441 default:
2442 return 1;
2443 }
2444
2445 return 0;
2446 }
2447
2448 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2449 (ie. an undefined instruction). */
2450 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2451 {
2452 int acc, rd0, rd1, rdhi, rdlo;
2453 TCGv_i32 tmp, tmp2;
2454
2455 if ((insn & 0x0ff00f10) == 0x0e200010) {
2456 /* Multiply with Internal Accumulate Format */
2457 rd0 = (insn >> 12) & 0xf;
2458 rd1 = insn & 0xf;
2459 acc = (insn >> 5) & 7;
2460
2461 if (acc != 0)
2462 return 1;
2463
2464 tmp = load_reg(s, rd0);
2465 tmp2 = load_reg(s, rd1);
2466 switch ((insn >> 16) & 0xf) {
2467 case 0x0: /* MIA */
2468 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2469 break;
2470 case 0x8: /* MIAPH */
2471 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2472 break;
2473 case 0xc: /* MIABB */
2474 case 0xd: /* MIABT */
2475 case 0xe: /* MIATB */
2476 case 0xf: /* MIATT */
2477 if (insn & (1 << 16))
2478 tcg_gen_shri_i32(tmp, tmp, 16);
2479 if (insn & (1 << 17))
2480 tcg_gen_shri_i32(tmp2, tmp2, 16);
2481 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2482 break;
2483 default:
2484 return 1;
2485 }
2486 tcg_temp_free_i32(tmp2);
2487 tcg_temp_free_i32(tmp);
2488
2489 gen_op_iwmmxt_movq_wRn_M0(acc);
2490 return 0;
2491 }
2492
2493 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2494 /* Internal Accumulator Access Format */
2495 rdhi = (insn >> 16) & 0xf;
2496 rdlo = (insn >> 12) & 0xf;
2497 acc = insn & 7;
2498
2499 if (acc != 0)
2500 return 1;
2501
2502 if (insn & ARM_CP_RW_BIT) { /* MRA */
2503 iwmmxt_load_reg(cpu_V0, acc);
2504 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2505 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2506 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2507 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2508 } else { /* MAR */
2509 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2510 iwmmxt_store_reg(cpu_V0, acc);
2511 }
2512 return 0;
2513 }
2514
2515 return 1;
2516 }
2517
2518 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2519 #define VFP_SREG(insn, bigbit, smallbit) \
2520 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2521 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2522 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2523 reg = (((insn) >> (bigbit)) & 0x0f) \
2524 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2525 } else { \
2526 if (insn & (1 << (smallbit))) \
2527 return 1; \
2528 reg = ((insn) >> (bigbit)) & 0x0f; \
2529 }} while (0)
2530
2531 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2532 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2533 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2534 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2535 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2536 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2537
2538 /* Move between integer and VFP cores. */
2539 static TCGv_i32 gen_vfp_mrs(void)
2540 {
2541 TCGv_i32 tmp = tcg_temp_new_i32();
2542 tcg_gen_mov_i32(tmp, cpu_F0s);
2543 return tmp;
2544 }
2545
2546 static void gen_vfp_msr(TCGv_i32 tmp)
2547 {
2548 tcg_gen_mov_i32(cpu_F0s, tmp);
2549 tcg_temp_free_i32(tmp);
2550 }
2551
2552 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2553 {
2554 TCGv_i32 tmp = tcg_temp_new_i32();
2555 if (shift)
2556 tcg_gen_shri_i32(var, var, shift);
2557 tcg_gen_ext8u_i32(var, var);
2558 tcg_gen_shli_i32(tmp, var, 8);
2559 tcg_gen_or_i32(var, var, tmp);
2560 tcg_gen_shli_i32(tmp, var, 16);
2561 tcg_gen_or_i32(var, var, tmp);
2562 tcg_temp_free_i32(tmp);
2563 }
2564
2565 static void gen_neon_dup_low16(TCGv_i32 var)
2566 {
2567 TCGv_i32 tmp = tcg_temp_new_i32();
2568 tcg_gen_ext16u_i32(var, var);
2569 tcg_gen_shli_i32(tmp, var, 16);
2570 tcg_gen_or_i32(var, var, tmp);
2571 tcg_temp_free_i32(tmp);
2572 }
2573
2574 static void gen_neon_dup_high16(TCGv_i32 var)
2575 {
2576 TCGv_i32 tmp = tcg_temp_new_i32();
2577 tcg_gen_andi_i32(var, var, 0xffff0000);
2578 tcg_gen_shri_i32(tmp, var, 16);
2579 tcg_gen_or_i32(var, var, tmp);
2580 tcg_temp_free_i32(tmp);
2581 }
2582
2583 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2584 {
2585 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2586 TCGv_i32 tmp = tcg_temp_new_i32();
2587 switch (size) {
2588 case 0:
2589 gen_aa32_ld8u(tmp, addr, IS_USER(s));
2590 gen_neon_dup_u8(tmp, 0);
2591 break;
2592 case 1:
2593 gen_aa32_ld16u(tmp, addr, IS_USER(s));
2594 gen_neon_dup_low16(tmp);
2595 break;
2596 case 2:
2597 gen_aa32_ld32u(tmp, addr, IS_USER(s));
2598 break;
2599 default: /* Avoid compiler warnings. */
2600 abort();
2601 }
2602 return tmp;
2603 }
2604
2605 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2606 uint32_t dp)
2607 {
2608 uint32_t cc = extract32(insn, 20, 2);
2609
2610 if (dp) {
2611 TCGv_i64 frn, frm, dest;
2612 TCGv_i64 tmp, zero, zf, nf, vf;
2613
2614 zero = tcg_const_i64(0);
2615
2616 frn = tcg_temp_new_i64();
2617 frm = tcg_temp_new_i64();
2618 dest = tcg_temp_new_i64();
2619
2620 zf = tcg_temp_new_i64();
2621 nf = tcg_temp_new_i64();
2622 vf = tcg_temp_new_i64();
2623
2624 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2625 tcg_gen_ext_i32_i64(nf, cpu_NF);
2626 tcg_gen_ext_i32_i64(vf, cpu_VF);
2627
2628 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2629 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2630 switch (cc) {
2631 case 0: /* eq: Z */
2632 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2633 frn, frm);
2634 break;
2635 case 1: /* vs: V */
2636 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2637 frn, frm);
2638 break;
2639 case 2: /* ge: N == V -> N ^ V == 0 */
2640 tmp = tcg_temp_new_i64();
2641 tcg_gen_xor_i64(tmp, vf, nf);
2642 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2643 frn, frm);
2644 tcg_temp_free_i64(tmp);
2645 break;
2646 case 3: /* gt: !Z && N == V */
2647 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2648 frn, frm);
2649 tmp = tcg_temp_new_i64();
2650 tcg_gen_xor_i64(tmp, vf, nf);
2651 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2652 dest, frm);
2653 tcg_temp_free_i64(tmp);
2654 break;
2655 }
2656 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2657 tcg_temp_free_i64(frn);
2658 tcg_temp_free_i64(frm);
2659 tcg_temp_free_i64(dest);
2660
2661 tcg_temp_free_i64(zf);
2662 tcg_temp_free_i64(nf);
2663 tcg_temp_free_i64(vf);
2664
2665 tcg_temp_free_i64(zero);
2666 } else {
2667 TCGv_i32 frn, frm, dest;
2668 TCGv_i32 tmp, zero;
2669
2670 zero = tcg_const_i32(0);
2671
2672 frn = tcg_temp_new_i32();
2673 frm = tcg_temp_new_i32();
2674 dest = tcg_temp_new_i32();
2675 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2676 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2677 switch (cc) {
2678 case 0: /* eq: Z */
2679 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2680 frn, frm);
2681 break;
2682 case 1: /* vs: V */
2683 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2684 frn, frm);
2685 break;
2686 case 2: /* ge: N == V -> N ^ V == 0 */
2687 tmp = tcg_temp_new_i32();
2688 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2689 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2690 frn, frm);
2691 tcg_temp_free_i32(tmp);
2692 break;
2693 case 3: /* gt: !Z && N == V */
2694 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2695 frn, frm);
2696 tmp = tcg_temp_new_i32();
2697 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2698 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2699 dest, frm);
2700 tcg_temp_free_i32(tmp);
2701 break;
2702 }
2703 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2704 tcg_temp_free_i32(frn);
2705 tcg_temp_free_i32(frm);
2706 tcg_temp_free_i32(dest);
2707
2708 tcg_temp_free_i32(zero);
2709 }
2710
2711 return 0;
2712 }
2713
2714 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2715 uint32_t rm, uint32_t dp)
2716 {
2717 uint32_t vmin = extract32(insn, 6, 1);
2718 TCGv_ptr fpst = get_fpstatus_ptr(0);
2719
2720 if (dp) {
2721 TCGv_i64 frn, frm, dest;
2722
2723 frn = tcg_temp_new_i64();
2724 frm = tcg_temp_new_i64();
2725 dest = tcg_temp_new_i64();
2726
2727 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2728 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2729 if (vmin) {
2730 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2731 } else {
2732 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2733 }
2734 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2735 tcg_temp_free_i64(frn);
2736 tcg_temp_free_i64(frm);
2737 tcg_temp_free_i64(dest);
2738 } else {
2739 TCGv_i32 frn, frm, dest;
2740
2741 frn = tcg_temp_new_i32();
2742 frm = tcg_temp_new_i32();
2743 dest = tcg_temp_new_i32();
2744
2745 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2746 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2747 if (vmin) {
2748 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2749 } else {
2750 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2751 }
2752 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2753 tcg_temp_free_i32(frn);
2754 tcg_temp_free_i32(frm);
2755 tcg_temp_free_i32(dest);
2756 }
2757
2758 tcg_temp_free_ptr(fpst);
2759 return 0;
2760 }
2761
2762 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2763 int rounding)
2764 {
2765 TCGv_ptr fpst = get_fpstatus_ptr(0);
2766 TCGv_i32 tcg_rmode;
2767
2768 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2769 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2770
2771 if (dp) {
2772 TCGv_i64 tcg_op;
2773 TCGv_i64 tcg_res;
2774 tcg_op = tcg_temp_new_i64();
2775 tcg_res = tcg_temp_new_i64();
2776 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2777 gen_helper_rintd(tcg_res, tcg_op, fpst);
2778 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2779 tcg_temp_free_i64(tcg_op);
2780 tcg_temp_free_i64(tcg_res);
2781 } else {
2782 TCGv_i32 tcg_op;
2783 TCGv_i32 tcg_res;
2784 tcg_op = tcg_temp_new_i32();
2785 tcg_res = tcg_temp_new_i32();
2786 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2787 gen_helper_rints(tcg_res, tcg_op, fpst);
2788 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2789 tcg_temp_free_i32(tcg_op);
2790 tcg_temp_free_i32(tcg_res);
2791 }
2792
2793 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2794 tcg_temp_free_i32(tcg_rmode);
2795
2796 tcg_temp_free_ptr(fpst);
2797 return 0;
2798 }
2799
2800 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2801 int rounding)
2802 {
2803 bool is_signed = extract32(insn, 7, 1);
2804 TCGv_ptr fpst = get_fpstatus_ptr(0);
2805 TCGv_i32 tcg_rmode, tcg_shift;
2806
2807 tcg_shift = tcg_const_i32(0);
2808
2809 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2810 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2811
2812 if (dp) {
2813 TCGv_i64 tcg_double, tcg_res;
2814 TCGv_i32 tcg_tmp;
2815 /* Rd is encoded as a single precision register even when the source
2816 * is double precision.
2817 */
2818 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2819 tcg_double = tcg_temp_new_i64();
2820 tcg_res = tcg_temp_new_i64();
2821 tcg_tmp = tcg_temp_new_i32();
2822 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2823 if (is_signed) {
2824 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2825 } else {
2826 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2827 }
2828 tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2829 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2830 tcg_temp_free_i32(tcg_tmp);
2831 tcg_temp_free_i64(tcg_res);
2832 tcg_temp_free_i64(tcg_double);
2833 } else {
2834 TCGv_i32 tcg_single, tcg_res;
2835 tcg_single = tcg_temp_new_i32();
2836 tcg_res = tcg_temp_new_i32();
2837 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2838 if (is_signed) {
2839 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2840 } else {
2841 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2842 }
2843 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2844 tcg_temp_free_i32(tcg_res);
2845 tcg_temp_free_i32(tcg_single);
2846 }
2847
2848 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2849 tcg_temp_free_i32(tcg_rmode);
2850
2851 tcg_temp_free_i32(tcg_shift);
2852
2853 tcg_temp_free_ptr(fpst);
2854
2855 return 0;
2856 }
2857
2858 /* Table for converting the most common AArch32 encoding of
2859 * rounding mode to arm_fprounding order (which matches the
2860 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2861 */
2862 static const uint8_t fp_decode_rm[] = {
2863 FPROUNDING_TIEAWAY,
2864 FPROUNDING_TIEEVEN,
2865 FPROUNDING_POSINF,
2866 FPROUNDING_NEGINF,
2867 };
2868
2869 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2870 {
2871 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2872
2873 if (!arm_feature(env, ARM_FEATURE_V8)) {
2874 return 1;
2875 }
2876
2877 if (dp) {
2878 VFP_DREG_D(rd, insn);
2879 VFP_DREG_N(rn, insn);
2880 VFP_DREG_M(rm, insn);
2881 } else {
2882 rd = VFP_SREG_D(insn);
2883 rn = VFP_SREG_N(insn);
2884 rm = VFP_SREG_M(insn);
2885 }
2886
2887 if ((insn & 0x0f800e50) == 0x0e000a00) {
2888 return handle_vsel(insn, rd, rn, rm, dp);
2889 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2890 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2891 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2892 /* VRINTA, VRINTN, VRINTP, VRINTM */
2893 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2894 return handle_vrint(insn, rd, rm, dp, rounding);
2895 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2896 /* VCVTA, VCVTN, VCVTP, VCVTM */
2897 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2898 return handle_vcvt(insn, rd, rm, dp, rounding);
2899 }
2900 return 1;
2901 }
2902
2903 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2904 (ie. an undefined instruction). */
2905 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2906 {
2907 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2908 int dp, veclen;
2909 TCGv_i32 addr;
2910 TCGv_i32 tmp;
2911 TCGv_i32 tmp2;
2912
2913 if (!arm_feature(env, ARM_FEATURE_VFP))
2914 return 1;
2915
2916 if (!s->vfp_enabled) {
2917 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2918 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2919 return 1;
2920 rn = (insn >> 16) & 0xf;
2921 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2922 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2923 return 1;
2924 }
2925
2926 if (extract32(insn, 28, 4) == 0xf) {
2927 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2928 * only used in v8 and above.
2929 */
2930 return disas_vfp_v8_insn(env, s, insn);
2931 }
2932
2933 dp = ((insn & 0xf00) == 0xb00);
2934 switch ((insn >> 24) & 0xf) {
2935 case 0xe:
2936 if (insn & (1 << 4)) {
2937 /* single register transfer */
2938 rd = (insn >> 12) & 0xf;
2939 if (dp) {
2940 int size;
2941 int pass;
2942
2943 VFP_DREG_N(rn, insn);
2944 if (insn & 0xf)
2945 return 1;
2946 if (insn & 0x00c00060
2947 && !arm_feature(env, ARM_FEATURE_NEON))
2948 return 1;
2949
2950 pass = (insn >> 21) & 1;
2951 if (insn & (1 << 22)) {
2952 size = 0;
2953 offset = ((insn >> 5) & 3) * 8;
2954 } else if (insn & (1 << 5)) {
2955 size = 1;
2956 offset = (insn & (1 << 6)) ? 16 : 0;
2957 } else {
2958 size = 2;
2959 offset = 0;
2960 }
2961 if (insn & ARM_CP_RW_BIT) {
2962 /* vfp->arm */
2963 tmp = neon_load_reg(rn, pass);
2964 switch (size) {
2965 case 0:
2966 if (offset)
2967 tcg_gen_shri_i32(tmp, tmp, offset);
2968 if (insn & (1 << 23))
2969 gen_uxtb(tmp);
2970 else
2971 gen_sxtb(tmp);
2972 break;
2973 case 1:
2974 if (insn & (1 << 23)) {
2975 if (offset) {
2976 tcg_gen_shri_i32(tmp, tmp, 16);
2977 } else {
2978 gen_uxth(tmp);
2979 }
2980 } else {
2981 if (offset) {
2982 tcg_gen_sari_i32(tmp, tmp, 16);
2983 } else {
2984 gen_sxth(tmp);
2985 }
2986 }
2987 break;
2988 case 2:
2989 break;
2990 }
2991 store_reg(s, rd, tmp);
2992 } else {
2993 /* arm->vfp */
2994 tmp = load_reg(s, rd);
2995 if (insn & (1 << 23)) {
2996 /* VDUP */
2997 if (size == 0) {
2998 gen_neon_dup_u8(tmp, 0);
2999 } else if (size == 1) {
3000 gen_neon_dup_low16(tmp);
3001 }
3002 for (n = 0; n <= pass * 2; n++) {
3003 tmp2 = tcg_temp_new_i32();
3004 tcg_gen_mov_i32(tmp2, tmp);
3005 neon_store_reg(rn, n, tmp2);
3006 }
3007 neon_store_reg(rn, n, tmp);
3008 } else {
3009 /* VMOV */
3010 switch (size) {
3011 case 0:
3012 tmp2 = neon_load_reg(rn, pass);
3013 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3014 tcg_temp_free_i32(tmp2);
3015 break;
3016 case 1:
3017 tmp2 = neon_load_reg(rn, pass);
3018 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3019 tcg_temp_free_i32(tmp2);
3020 break;
3021 case 2:
3022 break;
3023 }
3024 neon_store_reg(rn, pass, tmp);
3025 }
3026 }
3027 } else { /* !dp */
3028 if ((insn & 0x6f) != 0x00)
3029 return 1;
3030 rn = VFP_SREG_N(insn);
3031 if (insn & ARM_CP_RW_BIT) {
3032 /* vfp->arm */
3033 if (insn & (1 << 21)) {
3034 /* system register */
3035 rn >>= 1;
3036
3037 switch (rn) {
3038 case ARM_VFP_FPSID:
3039 /* VFP2 allows access to FSID from userspace.
3040 VFP3 restricts all id registers to privileged
3041 accesses. */
3042 if (IS_USER(s)
3043 && arm_feature(env, ARM_FEATURE_VFP3))
3044 return 1;
3045 tmp = load_cpu_field(vfp.xregs[rn]);
3046 break;
3047 case ARM_VFP_FPEXC:
3048 if (IS_USER(s))
3049 return 1;
3050 tmp = load_cpu_field(vfp.xregs[rn]);
3051 break;
3052 case ARM_VFP_FPINST:
3053 case ARM_VFP_FPINST2:
3054 /* Not present in VFP3. */
3055 if (IS_USER(s)
3056 || arm_feature(env, ARM_FEATURE_VFP3))
3057 return 1;
3058 tmp = load_cpu_field(vfp.xregs[rn]);
3059 break;
3060 case ARM_VFP_FPSCR:
3061 if (rd == 15) {
3062 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3063 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3064 } else {
3065 tmp = tcg_temp_new_i32();
3066 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3067 }
3068 break;
3069 case ARM_VFP_MVFR0:
3070 case ARM_VFP_MVFR1:
3071 if (IS_USER(s)
3072 || !arm_feature(env, ARM_FEATURE_MVFR))
3073 return 1;
3074 tmp = load_cpu_field(vfp.xregs[rn]);
3075 break;
3076 default:
3077 return 1;
3078 }
3079 } else {
3080 gen_mov_F0_vreg(0, rn);
3081 tmp = gen_vfp_mrs();
3082 }
3083 if (rd == 15) {
3084 /* Set the 4 flag bits in the CPSR. */
3085 gen_set_nzcv(tmp);
3086 tcg_temp_free_i32(tmp);
3087 } else {
3088 store_reg(s, rd, tmp);
3089 }
3090 } else {
3091 /* arm->vfp */
3092 if (insn & (1 << 21)) {
3093 rn >>= 1;
3094 /* system register */
3095 switch (rn) {
3096 case ARM_VFP_FPSID:
3097 case ARM_VFP_MVFR0:
3098 case ARM_VFP_MVFR1:
3099 /* Writes are ignored. */
3100 break;
3101 case ARM_VFP_FPSCR:
3102 tmp = load_reg(s, rd);
3103 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3104 tcg_temp_free_i32(tmp);
3105 gen_lookup_tb(s);
3106 break;
3107 case ARM_VFP_FPEXC:
3108 if (IS_USER(s))
3109 return 1;
3110 /* TODO: VFP subarchitecture support.
3111 * For now, keep the EN bit only */
3112 tmp = load_reg(s, rd);
3113 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3114 store_cpu_field(tmp, vfp.xregs[rn]);
3115 gen_lookup_tb(s);
3116 break;
3117 case ARM_VFP_FPINST:
3118 case ARM_VFP_FPINST2:
3119 tmp = load_reg(s, rd);
3120 store_cpu_field(tmp, vfp.xregs[rn]);
3121 break;
3122 default:
3123 return 1;
3124 }
3125 } else {
3126 tmp = load_reg(s, rd);
3127 gen_vfp_msr(tmp);
3128 gen_mov_vreg_F0(0, rn);
3129 }
3130 }
3131 }
3132 } else {
3133 /* data processing */
3134 /* The opcode is in bits 23, 21, 20 and 6. */
3135 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3136 if (dp) {
3137 if (op == 15) {
3138 /* rn is opcode */
3139 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3140 } else {