]> git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
target-arm: fix TANDC and TORC instructions
[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 "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
32
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
36
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
42
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
44
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 } DisasContext;
63
64 #if defined(CONFIG_USER_ONLY)
65 #define IS_USER(s) 1
66 #else
67 #define IS_USER(s) (s->user)
68 #endif
69
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72 #define DISAS_WFI 4
73 #define DISAS_SWI 5
74
75 static TCGv_ptr cpu_env;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
78 static TCGv_i32 cpu_R[16];
79
80 /* FIXME: These should be removed. */
81 static TCGv cpu_T[2];
82 static TCGv cpu_F0s, cpu_F1s;
83 static TCGv_i64 cpu_F0d, cpu_F1d;
84
85 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h"
87
88 static const char *regnames[] =
89 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
91
92 /* initialize TCG globals. */
93 void arm_translate_init(void)
94 {
95 int i;
96
97 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
98
99 cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
100 cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
101
102 for (i = 0; i < 16; i++) {
103 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUState, regs[i]),
105 regnames[i]);
106 }
107
108 #define GEN_HELPER 2
109 #include "helpers.h"
110 }
111
112 static int num_temps;
113
114 /* Allocate a temporary variable. */
115 static TCGv_i32 new_tmp(void)
116 {
117 num_temps++;
118 return tcg_temp_new_i32();
119 }
120
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp)
123 {
124 tcg_temp_free(tmp);
125 num_temps--;
126 }
127
128 static inline TCGv load_cpu_offset(int offset)
129 {
130 TCGv tmp = new_tmp();
131 tcg_gen_ld_i32(tmp, cpu_env, offset);
132 return tmp;
133 }
134
135 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
136
137 static inline void store_cpu_offset(TCGv var, int offset)
138 {
139 tcg_gen_st_i32(var, cpu_env, offset);
140 dead_tmp(var);
141 }
142
143 #define store_cpu_field(var, name) \
144 store_cpu_offset(var, offsetof(CPUState, name))
145
146 /* Set a variable to the value of a CPU register. */
147 static void load_reg_var(DisasContext *s, TCGv var, int reg)
148 {
149 if (reg == 15) {
150 uint32_t addr;
151 /* normaly, since we updated PC, we need only to add one insn */
152 if (s->thumb)
153 addr = (long)s->pc + 2;
154 else
155 addr = (long)s->pc + 4;
156 tcg_gen_movi_i32(var, addr);
157 } else {
158 tcg_gen_mov_i32(var, cpu_R[reg]);
159 }
160 }
161
162 /* Create a new temporary and set it to the value of a CPU register. */
163 static inline TCGv load_reg(DisasContext *s, int reg)
164 {
165 TCGv tmp = new_tmp();
166 load_reg_var(s, tmp, reg);
167 return tmp;
168 }
169
170 /* Set a CPU register. The source must be a temporary and will be
171 marked as dead. */
172 static void store_reg(DisasContext *s, int reg, TCGv var)
173 {
174 if (reg == 15) {
175 tcg_gen_andi_i32(var, var, ~1);
176 s->is_jmp = DISAS_JUMP;
177 }
178 tcg_gen_mov_i32(cpu_R[reg], var);
179 dead_tmp(var);
180 }
181
182
183 /* Basic operations. */
184 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
185 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
187
188 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
190 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
191 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
192
193 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
194 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
195 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
196 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
197 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
198
199 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
200 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
201 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
203 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
204 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
205 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
206
207 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
208 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
209
210 /* Value extensions. */
211 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
212 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
213 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
214 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
215
216 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
217 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
218
219 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
220
221 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
222 /* Set NZCV flags from the high 4 bits of var. */
223 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
224
225 static void gen_exception(int excp)
226 {
227 TCGv tmp = new_tmp();
228 tcg_gen_movi_i32(tmp, excp);
229 gen_helper_exception(tmp);
230 dead_tmp(tmp);
231 }
232
233 static void gen_smul_dual(TCGv a, TCGv b)
234 {
235 TCGv tmp1 = new_tmp();
236 TCGv tmp2 = new_tmp();
237 tcg_gen_ext16s_i32(tmp1, a);
238 tcg_gen_ext16s_i32(tmp2, b);
239 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
240 dead_tmp(tmp2);
241 tcg_gen_sari_i32(a, a, 16);
242 tcg_gen_sari_i32(b, b, 16);
243 tcg_gen_mul_i32(b, b, a);
244 tcg_gen_mov_i32(a, tmp1);
245 dead_tmp(tmp1);
246 }
247
248 /* Byteswap each halfword. */
249 static void gen_rev16(TCGv var)
250 {
251 TCGv tmp = new_tmp();
252 tcg_gen_shri_i32(tmp, var, 8);
253 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
254 tcg_gen_shli_i32(var, var, 8);
255 tcg_gen_andi_i32(var, var, 0xff00ff00);
256 tcg_gen_or_i32(var, var, tmp);
257 dead_tmp(tmp);
258 }
259
260 /* Byteswap low halfword and sign extend. */
261 static void gen_revsh(TCGv var)
262 {
263 TCGv tmp = new_tmp();
264 tcg_gen_shri_i32(tmp, var, 8);
265 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
266 tcg_gen_shli_i32(var, var, 8);
267 tcg_gen_ext8s_i32(var, var);
268 tcg_gen_or_i32(var, var, tmp);
269 dead_tmp(tmp);
270 }
271
272 /* Unsigned bitfield extract. */
273 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
274 {
275 if (shift)
276 tcg_gen_shri_i32(var, var, shift);
277 tcg_gen_andi_i32(var, var, mask);
278 }
279
280 /* Signed bitfield extract. */
281 static void gen_sbfx(TCGv var, int shift, int width)
282 {
283 uint32_t signbit;
284
285 if (shift)
286 tcg_gen_sari_i32(var, var, shift);
287 if (shift + width < 32) {
288 signbit = 1u << (width - 1);
289 tcg_gen_andi_i32(var, var, (1u << width) - 1);
290 tcg_gen_xori_i32(var, var, signbit);
291 tcg_gen_subi_i32(var, var, signbit);
292 }
293 }
294
295 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
296 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
297 {
298 tcg_gen_andi_i32(val, val, mask);
299 tcg_gen_shli_i32(val, val, shift);
300 tcg_gen_andi_i32(base, base, ~(mask << shift));
301 tcg_gen_or_i32(dest, base, val);
302 }
303
304 /* Round the top 32 bits of a 64-bit value. */
305 static void gen_roundqd(TCGv a, TCGv b)
306 {
307 tcg_gen_shri_i32(a, a, 31);
308 tcg_gen_add_i32(a, a, b);
309 }
310
311 /* FIXME: Most targets have native widening multiplication.
312 It would be good to use that instead of a full wide multiply. */
313 /* 32x32->64 multiply. Marks inputs as dead. */
314 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
315 {
316 TCGv_i64 tmp1 = tcg_temp_new_i64();
317 TCGv_i64 tmp2 = tcg_temp_new_i64();
318
319 tcg_gen_extu_i32_i64(tmp1, a);
320 dead_tmp(a);
321 tcg_gen_extu_i32_i64(tmp2, b);
322 dead_tmp(b);
323 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
324 return tmp1;
325 }
326
327 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
328 {
329 TCGv_i64 tmp1 = tcg_temp_new_i64();
330 TCGv_i64 tmp2 = tcg_temp_new_i64();
331
332 tcg_gen_ext_i32_i64(tmp1, a);
333 dead_tmp(a);
334 tcg_gen_ext_i32_i64(tmp2, b);
335 dead_tmp(b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 return tmp1;
338 }
339
340 /* Unsigned 32x32->64 multiply. */
341 static void gen_op_mull_T0_T1(void)
342 {
343 TCGv_i64 tmp1 = tcg_temp_new_i64();
344 TCGv_i64 tmp2 = tcg_temp_new_i64();
345
346 tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
347 tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
348 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
349 tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
350 tcg_gen_shri_i64(tmp1, tmp1, 32);
351 tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
352 }
353
354 /* Signed 32x32->64 multiply. */
355 static void gen_imull(TCGv a, TCGv b)
356 {
357 TCGv_i64 tmp1 = tcg_temp_new_i64();
358 TCGv_i64 tmp2 = tcg_temp_new_i64();
359
360 tcg_gen_ext_i32_i64(tmp1, a);
361 tcg_gen_ext_i32_i64(tmp2, b);
362 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
363 tcg_gen_trunc_i64_i32(a, tmp1);
364 tcg_gen_shri_i64(tmp1, tmp1, 32);
365 tcg_gen_trunc_i64_i32(b, tmp1);
366 }
367
368 /* Swap low and high halfwords. */
369 static void gen_swap_half(TCGv var)
370 {
371 TCGv tmp = new_tmp();
372 tcg_gen_shri_i32(tmp, var, 16);
373 tcg_gen_shli_i32(var, var, 16);
374 tcg_gen_or_i32(var, var, tmp);
375 dead_tmp(tmp);
376 }
377
378 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
379 tmp = (t0 ^ t1) & 0x8000;
380 t0 &= ~0x8000;
381 t1 &= ~0x8000;
382 t0 = (t0 + t1) ^ tmp;
383 */
384
385 static void gen_add16(TCGv t0, TCGv t1)
386 {
387 TCGv tmp = new_tmp();
388 tcg_gen_xor_i32(tmp, t0, t1);
389 tcg_gen_andi_i32(tmp, tmp, 0x8000);
390 tcg_gen_andi_i32(t0, t0, ~0x8000);
391 tcg_gen_andi_i32(t1, t1, ~0x8000);
392 tcg_gen_add_i32(t0, t0, t1);
393 tcg_gen_xor_i32(t0, t0, tmp);
394 dead_tmp(tmp);
395 dead_tmp(t1);
396 }
397
398 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
399
400 /* Set CF to the top bit of var. */
401 static void gen_set_CF_bit31(TCGv var)
402 {
403 TCGv tmp = new_tmp();
404 tcg_gen_shri_i32(tmp, var, 31);
405 gen_set_CF(tmp);
406 dead_tmp(tmp);
407 }
408
409 /* Set N and Z flags from var. */
410 static inline void gen_logic_CC(TCGv var)
411 {
412 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
413 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
414 }
415
416 /* T0 += T1 + CF. */
417 static void gen_adc_T0_T1(void)
418 {
419 TCGv tmp;
420 gen_op_addl_T0_T1();
421 tmp = load_cpu_field(CF);
422 tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
423 dead_tmp(tmp);
424 }
425
426 /* dest = T0 + T1 + CF. */
427 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
428 {
429 TCGv tmp;
430 tcg_gen_add_i32(dest, t0, t1);
431 tmp = load_cpu_field(CF);
432 tcg_gen_add_i32(dest, dest, tmp);
433 dead_tmp(tmp);
434 }
435
436 /* dest = T0 - T1 + CF - 1. */
437 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
438 {
439 TCGv tmp;
440 tcg_gen_sub_i32(dest, t0, t1);
441 tmp = load_cpu_field(CF);
442 tcg_gen_add_i32(dest, dest, tmp);
443 tcg_gen_subi_i32(dest, dest, 1);
444 dead_tmp(tmp);
445 }
446
447 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
448 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
449
450 /* T0 &= ~T1. Clobbers T1. */
451 /* FIXME: Implement bic natively. */
452 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
453 {
454 TCGv tmp = new_tmp();
455 tcg_gen_not_i32(tmp, t1);
456 tcg_gen_and_i32(dest, t0, tmp);
457 dead_tmp(tmp);
458 }
459 static inline void gen_op_bicl_T0_T1(void)
460 {
461 gen_op_notl_T1();
462 gen_op_andl_T0_T1();
463 }
464
465 /* FIXME: Implement this natively. */
466 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
467
468 /* FIXME: Implement this natively. */
469 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
470 {
471 TCGv tmp;
472
473 if (i == 0)
474 return;
475
476 tmp = new_tmp();
477 tcg_gen_shri_i32(tmp, t1, i);
478 tcg_gen_shli_i32(t1, t1, 32 - i);
479 tcg_gen_or_i32(t0, t1, tmp);
480 dead_tmp(tmp);
481 }
482
483 static void shifter_out_im(TCGv var, int shift)
484 {
485 TCGv tmp = new_tmp();
486 if (shift == 0) {
487 tcg_gen_andi_i32(tmp, var, 1);
488 } else {
489 tcg_gen_shri_i32(tmp, var, shift);
490 if (shift != 31)
491 tcg_gen_andi_i32(tmp, tmp, 1);
492 }
493 gen_set_CF(tmp);
494 dead_tmp(tmp);
495 }
496
497 /* Shift by immediate. Includes special handling for shift == 0. */
498 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
499 {
500 switch (shiftop) {
501 case 0: /* LSL */
502 if (shift != 0) {
503 if (flags)
504 shifter_out_im(var, 32 - shift);
505 tcg_gen_shli_i32(var, var, shift);
506 }
507 break;
508 case 1: /* LSR */
509 if (shift == 0) {
510 if (flags) {
511 tcg_gen_shri_i32(var, var, 31);
512 gen_set_CF(var);
513 }
514 tcg_gen_movi_i32(var, 0);
515 } else {
516 if (flags)
517 shifter_out_im(var, shift - 1);
518 tcg_gen_shri_i32(var, var, shift);
519 }
520 break;
521 case 2: /* ASR */
522 if (shift == 0)
523 shift = 32;
524 if (flags)
525 shifter_out_im(var, shift - 1);
526 if (shift == 32)
527 shift = 31;
528 tcg_gen_sari_i32(var, var, shift);
529 break;
530 case 3: /* ROR/RRX */
531 if (shift != 0) {
532 if (flags)
533 shifter_out_im(var, shift - 1);
534 tcg_gen_rori_i32(var, var, shift); break;
535 } else {
536 TCGv tmp = load_cpu_field(CF);
537 if (flags)
538 shifter_out_im(var, 0);
539 tcg_gen_shri_i32(var, var, 1);
540 tcg_gen_shli_i32(tmp, tmp, 31);
541 tcg_gen_or_i32(var, var, tmp);
542 dead_tmp(tmp);
543 }
544 }
545 };
546
547 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
548 TCGv shift, int flags)
549 {
550 if (flags) {
551 switch (shiftop) {
552 case 0: gen_helper_shl_cc(var, var, shift); break;
553 case 1: gen_helper_shr_cc(var, var, shift); break;
554 case 2: gen_helper_sar_cc(var, var, shift); break;
555 case 3: gen_helper_ror_cc(var, var, shift); break;
556 }
557 } else {
558 switch (shiftop) {
559 case 0: gen_helper_shl(var, var, shift); break;
560 case 1: gen_helper_shr(var, var, shift); break;
561 case 2: gen_helper_sar(var, var, shift); break;
562 case 3: gen_helper_ror(var, var, shift); break;
563 }
564 }
565 dead_tmp(shift);
566 }
567
568 #define PAS_OP(pfx) \
569 switch (op2) { \
570 case 0: gen_pas_helper(glue(pfx,add16)); break; \
571 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
572 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
573 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
574 case 4: gen_pas_helper(glue(pfx,add8)); break; \
575 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
576 }
577 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
578 {
579 TCGv_ptr tmp;
580
581 switch (op1) {
582 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
583 case 1:
584 tmp = tcg_temp_new_ptr();
585 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
586 PAS_OP(s)
587 break;
588 case 5:
589 tmp = tcg_temp_new_ptr();
590 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
591 PAS_OP(u)
592 break;
593 #undef gen_pas_helper
594 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
595 case 2:
596 PAS_OP(q);
597 break;
598 case 3:
599 PAS_OP(sh);
600 break;
601 case 6:
602 PAS_OP(uq);
603 break;
604 case 7:
605 PAS_OP(uh);
606 break;
607 #undef gen_pas_helper
608 }
609 }
610 #undef PAS_OP
611
612 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
613 #define PAS_OP(pfx) \
614 switch (op2) { \
615 case 0: gen_pas_helper(glue(pfx,add8)); break; \
616 case 1: gen_pas_helper(glue(pfx,add16)); break; \
617 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
618 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
619 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
620 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
621 }
622 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
623 {
624 TCGv_ptr tmp;
625
626 switch (op1) {
627 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
628 case 0:
629 tmp = tcg_temp_new_ptr();
630 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
631 PAS_OP(s)
632 break;
633 case 4:
634 tmp = tcg_temp_new_ptr();
635 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
636 PAS_OP(u)
637 break;
638 #undef gen_pas_helper
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
640 case 1:
641 PAS_OP(q);
642 break;
643 case 2:
644 PAS_OP(sh);
645 break;
646 case 5:
647 PAS_OP(uq);
648 break;
649 case 6:
650 PAS_OP(uh);
651 break;
652 #undef gen_pas_helper
653 }
654 }
655 #undef PAS_OP
656
657 static void gen_test_cc(int cc, int label)
658 {
659 TCGv tmp;
660 TCGv tmp2;
661 int inv;
662
663 switch (cc) {
664 case 0: /* eq: Z */
665 tmp = load_cpu_field(ZF);
666 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
667 break;
668 case 1: /* ne: !Z */
669 tmp = load_cpu_field(ZF);
670 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
671 break;
672 case 2: /* cs: C */
673 tmp = load_cpu_field(CF);
674 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
675 break;
676 case 3: /* cc: !C */
677 tmp = load_cpu_field(CF);
678 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
679 break;
680 case 4: /* mi: N */
681 tmp = load_cpu_field(NF);
682 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
683 break;
684 case 5: /* pl: !N */
685 tmp = load_cpu_field(NF);
686 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
687 break;
688 case 6: /* vs: V */
689 tmp = load_cpu_field(VF);
690 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
691 break;
692 case 7: /* vc: !V */
693 tmp = load_cpu_field(VF);
694 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
695 break;
696 case 8: /* hi: C && !Z */
697 inv = gen_new_label();
698 tmp = load_cpu_field(CF);
699 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
700 dead_tmp(tmp);
701 tmp = load_cpu_field(ZF);
702 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
703 gen_set_label(inv);
704 break;
705 case 9: /* ls: !C || Z */
706 tmp = load_cpu_field(CF);
707 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
708 dead_tmp(tmp);
709 tmp = load_cpu_field(ZF);
710 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
711 break;
712 case 10: /* ge: N == V -> N ^ V == 0 */
713 tmp = load_cpu_field(VF);
714 tmp2 = load_cpu_field(NF);
715 tcg_gen_xor_i32(tmp, tmp, tmp2);
716 dead_tmp(tmp2);
717 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
718 break;
719 case 11: /* lt: N != V -> N ^ V != 0 */
720 tmp = load_cpu_field(VF);
721 tmp2 = load_cpu_field(NF);
722 tcg_gen_xor_i32(tmp, tmp, tmp2);
723 dead_tmp(tmp2);
724 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
725 break;
726 case 12: /* gt: !Z && N == V */
727 inv = gen_new_label();
728 tmp = load_cpu_field(ZF);
729 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
730 dead_tmp(tmp);
731 tmp = load_cpu_field(VF);
732 tmp2 = load_cpu_field(NF);
733 tcg_gen_xor_i32(tmp, tmp, tmp2);
734 dead_tmp(tmp2);
735 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
736 gen_set_label(inv);
737 break;
738 case 13: /* le: Z || N != V */
739 tmp = load_cpu_field(ZF);
740 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
741 dead_tmp(tmp);
742 tmp = load_cpu_field(VF);
743 tmp2 = load_cpu_field(NF);
744 tcg_gen_xor_i32(tmp, tmp, tmp2);
745 dead_tmp(tmp2);
746 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
747 break;
748 default:
749 fprintf(stderr, "Bad condition code 0x%x\n", cc);
750 abort();
751 }
752 dead_tmp(tmp);
753 }
754
755 static const uint8_t table_logic_cc[16] = {
756 1, /* and */
757 1, /* xor */
758 0, /* sub */
759 0, /* rsb */
760 0, /* add */
761 0, /* adc */
762 0, /* sbc */
763 0, /* rsc */
764 1, /* andl */
765 1, /* xorl */
766 0, /* cmp */
767 0, /* cmn */
768 1, /* orr */
769 1, /* mov */
770 1, /* bic */
771 1, /* mvn */
772 };
773
774 /* Set PC and Thumb state from an immediate address. */
775 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
776 {
777 TCGv tmp;
778
779 s->is_jmp = DISAS_UPDATE;
780 if (s->thumb != (addr & 1)) {
781 tmp = new_tmp();
782 tcg_gen_movi_i32(tmp, addr & 1);
783 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
784 dead_tmp(tmp);
785 }
786 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
787 }
788
789 /* Set PC and Thumb state from var. var is marked as dead. */
790 static inline void gen_bx(DisasContext *s, TCGv var)
791 {
792 s->is_jmp = DISAS_UPDATE;
793 tcg_gen_andi_i32(cpu_R[15], var, ~1);
794 tcg_gen_andi_i32(var, var, 1);
795 store_cpu_field(var, thumb);
796 }
797
798 /* Variant of store_reg which uses branch&exchange logic when storing
799 to r15 in ARM architecture v7 and above. The source must be a temporary
800 and will be marked as dead. */
801 static inline void store_reg_bx(CPUState *env, DisasContext *s,
802 int reg, TCGv var)
803 {
804 if (reg == 15 && ENABLE_ARCH_7) {
805 gen_bx(s, var);
806 } else {
807 store_reg(s, reg, var);
808 }
809 }
810
811 static inline TCGv gen_ld8s(TCGv addr, int index)
812 {
813 TCGv tmp = new_tmp();
814 tcg_gen_qemu_ld8s(tmp, addr, index);
815 return tmp;
816 }
817 static inline TCGv gen_ld8u(TCGv addr, int index)
818 {
819 TCGv tmp = new_tmp();
820 tcg_gen_qemu_ld8u(tmp, addr, index);
821 return tmp;
822 }
823 static inline TCGv gen_ld16s(TCGv addr, int index)
824 {
825 TCGv tmp = new_tmp();
826 tcg_gen_qemu_ld16s(tmp, addr, index);
827 return tmp;
828 }
829 static inline TCGv gen_ld16u(TCGv addr, int index)
830 {
831 TCGv tmp = new_tmp();
832 tcg_gen_qemu_ld16u(tmp, addr, index);
833 return tmp;
834 }
835 static inline TCGv gen_ld32(TCGv addr, int index)
836 {
837 TCGv tmp = new_tmp();
838 tcg_gen_qemu_ld32u(tmp, addr, index);
839 return tmp;
840 }
841 static inline void gen_st8(TCGv val, TCGv addr, int index)
842 {
843 tcg_gen_qemu_st8(val, addr, index);
844 dead_tmp(val);
845 }
846 static inline void gen_st16(TCGv val, TCGv addr, int index)
847 {
848 tcg_gen_qemu_st16(val, addr, index);
849 dead_tmp(val);
850 }
851 static inline void gen_st32(TCGv val, TCGv addr, int index)
852 {
853 tcg_gen_qemu_st32(val, addr, index);
854 dead_tmp(val);
855 }
856
857 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
858 {
859 load_reg_var(s, cpu_T[0], reg);
860 }
861
862 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
863 {
864 load_reg_var(s, cpu_T[1], reg);
865 }
866
867 static inline void gen_set_pc_im(uint32_t val)
868 {
869 tcg_gen_movi_i32(cpu_R[15], val);
870 }
871
872 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
873 {
874 TCGv tmp;
875 if (reg == 15) {
876 tmp = new_tmp();
877 tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
878 } else {
879 tmp = cpu_T[t];
880 }
881 tcg_gen_mov_i32(cpu_R[reg], tmp);
882 if (reg == 15) {
883 dead_tmp(tmp);
884 s->is_jmp = DISAS_JUMP;
885 }
886 }
887
888 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
889 {
890 gen_movl_reg_TN(s, reg, 0);
891 }
892
893 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
894 {
895 gen_movl_reg_TN(s, reg, 1);
896 }
897
898 /* Force a TB lookup after an instruction that changes the CPU state. */
899 static inline void gen_lookup_tb(DisasContext *s)
900 {
901 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
902 s->is_jmp = DISAS_UPDATE;
903 }
904
905 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
906 TCGv var)
907 {
908 int val, rm, shift, shiftop;
909 TCGv offset;
910
911 if (!(insn & (1 << 25))) {
912 /* immediate */
913 val = insn & 0xfff;
914 if (!(insn & (1 << 23)))
915 val = -val;
916 if (val != 0)
917 tcg_gen_addi_i32(var, var, val);
918 } else {
919 /* shift/register */
920 rm = (insn) & 0xf;
921 shift = (insn >> 7) & 0x1f;
922 shiftop = (insn >> 5) & 3;
923 offset = load_reg(s, rm);
924 gen_arm_shift_im(offset, shiftop, shift, 0);
925 if (!(insn & (1 << 23)))
926 tcg_gen_sub_i32(var, var, offset);
927 else
928 tcg_gen_add_i32(var, var, offset);
929 dead_tmp(offset);
930 }
931 }
932
933 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
934 int extra, TCGv var)
935 {
936 int val, rm;
937 TCGv offset;
938
939 if (insn & (1 << 22)) {
940 /* immediate */
941 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
942 if (!(insn & (1 << 23)))
943 val = -val;
944 val += extra;
945 if (val != 0)
946 tcg_gen_addi_i32(var, var, val);
947 } else {
948 /* register */
949 if (extra)
950 tcg_gen_addi_i32(var, var, extra);
951 rm = (insn) & 0xf;
952 offset = load_reg(s, rm);
953 if (!(insn & (1 << 23)))
954 tcg_gen_sub_i32(var, var, offset);
955 else
956 tcg_gen_add_i32(var, var, offset);
957 dead_tmp(offset);
958 }
959 }
960
961 #define VFP_OP2(name) \
962 static inline void gen_vfp_##name(int dp) \
963 { \
964 if (dp) \
965 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
966 else \
967 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
968 }
969
970 VFP_OP2(add)
971 VFP_OP2(sub)
972 VFP_OP2(mul)
973 VFP_OP2(div)
974
975 #undef VFP_OP2
976
977 static inline void gen_vfp_abs(int dp)
978 {
979 if (dp)
980 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
981 else
982 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
983 }
984
985 static inline void gen_vfp_neg(int dp)
986 {
987 if (dp)
988 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
989 else
990 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
991 }
992
993 static inline void gen_vfp_sqrt(int dp)
994 {
995 if (dp)
996 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
997 else
998 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
999 }
1000
1001 static inline void gen_vfp_cmp(int dp)
1002 {
1003 if (dp)
1004 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1005 else
1006 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1007 }
1008
1009 static inline void gen_vfp_cmpe(int dp)
1010 {
1011 if (dp)
1012 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1013 else
1014 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1015 }
1016
1017 static inline void gen_vfp_F1_ld0(int dp)
1018 {
1019 if (dp)
1020 tcg_gen_movi_i64(cpu_F1d, 0);
1021 else
1022 tcg_gen_movi_i32(cpu_F1s, 0);
1023 }
1024
1025 static inline void gen_vfp_uito(int dp)
1026 {
1027 if (dp)
1028 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1029 else
1030 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1031 }
1032
1033 static inline void gen_vfp_sito(int dp)
1034 {
1035 if (dp)
1036 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1037 else
1038 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1039 }
1040
1041 static inline void gen_vfp_toui(int dp)
1042 {
1043 if (dp)
1044 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1045 else
1046 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1047 }
1048
1049 static inline void gen_vfp_touiz(int dp)
1050 {
1051 if (dp)
1052 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1053 else
1054 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1055 }
1056
1057 static inline void gen_vfp_tosi(int dp)
1058 {
1059 if (dp)
1060 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1061 else
1062 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1063 }
1064
1065 static inline void gen_vfp_tosiz(int dp)
1066 {
1067 if (dp)
1068 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1069 else
1070 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1071 }
1072
1073 #define VFP_GEN_FIX(name) \
1074 static inline void gen_vfp_##name(int dp, int shift) \
1075 { \
1076 if (dp) \
1077 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1078 else \
1079 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1080 }
1081 VFP_GEN_FIX(tosh)
1082 VFP_GEN_FIX(tosl)
1083 VFP_GEN_FIX(touh)
1084 VFP_GEN_FIX(toul)
1085 VFP_GEN_FIX(shto)
1086 VFP_GEN_FIX(slto)
1087 VFP_GEN_FIX(uhto)
1088 VFP_GEN_FIX(ulto)
1089 #undef VFP_GEN_FIX
1090
1091 static inline void gen_vfp_ld(DisasContext *s, int dp)
1092 {
1093 if (dp)
1094 tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1095 else
1096 tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1097 }
1098
1099 static inline void gen_vfp_st(DisasContext *s, int dp)
1100 {
1101 if (dp)
1102 tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1103 else
1104 tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1105 }
1106
1107 static inline long
1108 vfp_reg_offset (int dp, int reg)
1109 {
1110 if (dp)
1111 return offsetof(CPUARMState, vfp.regs[reg]);
1112 else if (reg & 1) {
1113 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1114 + offsetof(CPU_DoubleU, l.upper);
1115 } else {
1116 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1117 + offsetof(CPU_DoubleU, l.lower);
1118 }
1119 }
1120
1121 /* Return the offset of a 32-bit piece of a NEON register.
1122 zero is the least significant end of the register. */
1123 static inline long
1124 neon_reg_offset (int reg, int n)
1125 {
1126 int sreg;
1127 sreg = reg * 2 + n;
1128 return vfp_reg_offset(0, sreg);
1129 }
1130
1131 /* FIXME: Remove these. */
1132 #define neon_T0 cpu_T[0]
1133 #define neon_T1 cpu_T[1]
1134 #define NEON_GET_REG(T, reg, n) \
1135 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1136 #define NEON_SET_REG(T, reg, n) \
1137 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1138
1139 static TCGv neon_load_reg(int reg, int pass)
1140 {
1141 TCGv tmp = new_tmp();
1142 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1143 return tmp;
1144 }
1145
1146 static void neon_store_reg(int reg, int pass, TCGv var)
1147 {
1148 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1149 dead_tmp(var);
1150 }
1151
1152 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1153 {
1154 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1155 }
1156
1157 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1158 {
1159 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1160 }
1161
1162 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1163 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1164 #define tcg_gen_st_f32 tcg_gen_st_i32
1165 #define tcg_gen_st_f64 tcg_gen_st_i64
1166
1167 static inline void gen_mov_F0_vreg(int dp, int reg)
1168 {
1169 if (dp)
1170 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1171 else
1172 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1173 }
1174
1175 static inline void gen_mov_F1_vreg(int dp, int reg)
1176 {
1177 if (dp)
1178 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1179 else
1180 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1181 }
1182
1183 static inline void gen_mov_vreg_F0(int dp, int reg)
1184 {
1185 if (dp)
1186 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1187 else
1188 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1189 }
1190
1191 #define ARM_CP_RW_BIT (1 << 20)
1192
1193 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1194 {
1195 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1196 }
1197
1198 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1199 {
1200 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1201 }
1202
1203 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1204 {
1205 tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1206 }
1207
1208 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1209 {
1210 tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1211 }
1212
1213 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1214 {
1215 tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1216 }
1217
1218 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1219 {
1220 iwmmxt_store_reg(cpu_M0, rn);
1221 }
1222
1223 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1224 {
1225 iwmmxt_load_reg(cpu_M0, rn);
1226 }
1227
1228 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1229 {
1230 iwmmxt_load_reg(cpu_V1, rn);
1231 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1232 }
1233
1234 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1235 {
1236 iwmmxt_load_reg(cpu_V1, rn);
1237 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1238 }
1239
1240 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1241 {
1242 iwmmxt_load_reg(cpu_V1, rn);
1243 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1244 }
1245
1246 #define IWMMXT_OP(name) \
1247 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1248 { \
1249 iwmmxt_load_reg(cpu_V1, rn); \
1250 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1251 }
1252
1253 #define IWMMXT_OP_ENV(name) \
1254 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1255 { \
1256 iwmmxt_load_reg(cpu_V1, rn); \
1257 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1258 }
1259
1260 #define IWMMXT_OP_ENV_SIZE(name) \
1261 IWMMXT_OP_ENV(name##b) \
1262 IWMMXT_OP_ENV(name##w) \
1263 IWMMXT_OP_ENV(name##l)
1264
1265 #define IWMMXT_OP_ENV1(name) \
1266 static inline void gen_op_iwmmxt_##name##_M0(void) \
1267 { \
1268 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1269 }
1270
1271 IWMMXT_OP(maddsq)
1272 IWMMXT_OP(madduq)
1273 IWMMXT_OP(sadb)
1274 IWMMXT_OP(sadw)
1275 IWMMXT_OP(mulslw)
1276 IWMMXT_OP(mulshw)
1277 IWMMXT_OP(mululw)
1278 IWMMXT_OP(muluhw)
1279 IWMMXT_OP(macsw)
1280 IWMMXT_OP(macuw)
1281
1282 IWMMXT_OP_ENV_SIZE(unpackl)
1283 IWMMXT_OP_ENV_SIZE(unpackh)
1284
1285 IWMMXT_OP_ENV1(unpacklub)
1286 IWMMXT_OP_ENV1(unpackluw)
1287 IWMMXT_OP_ENV1(unpacklul)
1288 IWMMXT_OP_ENV1(unpackhub)
1289 IWMMXT_OP_ENV1(unpackhuw)
1290 IWMMXT_OP_ENV1(unpackhul)
1291 IWMMXT_OP_ENV1(unpacklsb)
1292 IWMMXT_OP_ENV1(unpacklsw)
1293 IWMMXT_OP_ENV1(unpacklsl)
1294 IWMMXT_OP_ENV1(unpackhsb)
1295 IWMMXT_OP_ENV1(unpackhsw)
1296 IWMMXT_OP_ENV1(unpackhsl)
1297
1298 IWMMXT_OP_ENV_SIZE(cmpeq)
1299 IWMMXT_OP_ENV_SIZE(cmpgtu)
1300 IWMMXT_OP_ENV_SIZE(cmpgts)
1301
1302 IWMMXT_OP_ENV_SIZE(mins)
1303 IWMMXT_OP_ENV_SIZE(minu)
1304 IWMMXT_OP_ENV_SIZE(maxs)
1305 IWMMXT_OP_ENV_SIZE(maxu)
1306
1307 IWMMXT_OP_ENV_SIZE(subn)
1308 IWMMXT_OP_ENV_SIZE(addn)
1309 IWMMXT_OP_ENV_SIZE(subu)
1310 IWMMXT_OP_ENV_SIZE(addu)
1311 IWMMXT_OP_ENV_SIZE(subs)
1312 IWMMXT_OP_ENV_SIZE(adds)
1313
1314 IWMMXT_OP_ENV(avgb0)
1315 IWMMXT_OP_ENV(avgb1)
1316 IWMMXT_OP_ENV(avgw0)
1317 IWMMXT_OP_ENV(avgw1)
1318
1319 IWMMXT_OP(msadb)
1320
1321 IWMMXT_OP_ENV(packuw)
1322 IWMMXT_OP_ENV(packul)
1323 IWMMXT_OP_ENV(packuq)
1324 IWMMXT_OP_ENV(packsw)
1325 IWMMXT_OP_ENV(packsl)
1326 IWMMXT_OP_ENV(packsq)
1327
1328 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1329 {
1330 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1331 }
1332
1333 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1334 {
1335 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1336 }
1337
1338 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1339 {
1340 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1341 }
1342
1343 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1344 {
1345 iwmmxt_load_reg(cpu_V1, rn);
1346 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1347 }
1348
1349 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1350 {
1351 TCGv tmp = tcg_const_i32(shift);
1352 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1353 }
1354
1355 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1356 {
1357 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1358 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1359 tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1360 }
1361
1362 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1363 {
1364 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1365 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1366 tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1367 }
1368
1369 static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1370 {
1371 tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1372 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1373 if (mask != ~0u)
1374 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1375 }
1376
1377 static void gen_op_iwmmxt_set_mup(void)
1378 {
1379 TCGv tmp;
1380 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1381 tcg_gen_ori_i32(tmp, tmp, 2);
1382 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1383 }
1384
1385 static void gen_op_iwmmxt_set_cup(void)
1386 {
1387 TCGv tmp;
1388 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1389 tcg_gen_ori_i32(tmp, tmp, 1);
1390 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1391 }
1392
1393 static void gen_op_iwmmxt_setpsr_nz(void)
1394 {
1395 TCGv tmp = new_tmp();
1396 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1397 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1398 }
1399
1400 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1401 {
1402 iwmmxt_load_reg(cpu_V1, rn);
1403 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1404 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1405 }
1406
1407
1408 static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1409 {
1410 iwmmxt_load_reg(cpu_V0, rn);
1411 tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1412 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1413 tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1414 }
1415
1416 static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1417 {
1418 tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1419 iwmmxt_store_reg(cpu_V0, rn);
1420 }
1421
1422 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1423 {
1424 int rd;
1425 uint32_t offset;
1426
1427 rd = (insn >> 16) & 0xf;
1428 gen_movl_T1_reg(s, rd);
1429
1430 offset = (insn & 0xff) << ((insn >> 7) & 2);
1431 if (insn & (1 << 24)) {
1432 /* Pre indexed */
1433 if (insn & (1 << 23))
1434 gen_op_addl_T1_im(offset);
1435 else
1436 gen_op_addl_T1_im(-offset);
1437
1438 if (insn & (1 << 21))
1439 gen_movl_reg_T1(s, rd);
1440 } else if (insn & (1 << 21)) {
1441 /* Post indexed */
1442 if (insn & (1 << 23))
1443 gen_op_movl_T0_im(offset);
1444 else
1445 gen_op_movl_T0_im(- offset);
1446 gen_op_addl_T0_T1();
1447 gen_movl_reg_T0(s, rd);
1448 } else if (!(insn & (1 << 23)))
1449 return 1;
1450 return 0;
1451 }
1452
1453 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1454 {
1455 int rd = (insn >> 0) & 0xf;
1456
1457 if (insn & (1 << 8))
1458 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1459 return 1;
1460 else
1461 gen_op_iwmmxt_movl_T0_wCx(rd);
1462 else
1463 gen_iwmmxt_movl_T0_T1_wRn(rd);
1464
1465 gen_op_movl_T1_im(mask);
1466 gen_op_andl_T0_T1();
1467 return 0;
1468 }
1469
1470 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1471 (ie. an undefined instruction). */
1472 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1473 {
1474 int rd, wrd;
1475 int rdhi, rdlo, rd0, rd1, i;
1476 TCGv tmp;
1477
1478 if ((insn & 0x0e000e00) == 0x0c000000) {
1479 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1480 wrd = insn & 0xf;
1481 rdlo = (insn >> 12) & 0xf;
1482 rdhi = (insn >> 16) & 0xf;
1483 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1484 gen_iwmmxt_movl_T0_T1_wRn(wrd);
1485 gen_movl_reg_T0(s, rdlo);
1486 gen_movl_reg_T1(s, rdhi);
1487 } else { /* TMCRR */
1488 gen_movl_T0_reg(s, rdlo);
1489 gen_movl_T1_reg(s, rdhi);
1490 gen_iwmmxt_movl_wRn_T0_T1(wrd);
1491 gen_op_iwmmxt_set_mup();
1492 }
1493 return 0;
1494 }
1495
1496 wrd = (insn >> 12) & 0xf;
1497 if (gen_iwmmxt_address(s, insn))
1498 return 1;
1499 if (insn & ARM_CP_RW_BIT) {
1500 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1501 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1502 tcg_gen_mov_i32(cpu_T[0], tmp);
1503 dead_tmp(tmp);
1504 gen_op_iwmmxt_movl_wCx_T0(wrd);
1505 } else {
1506 i = 1;
1507 if (insn & (1 << 8)) {
1508 if (insn & (1 << 22)) { /* WLDRD */
1509 tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1510 i = 0;
1511 } else { /* WLDRW wRd */
1512 tmp = gen_ld32(cpu_T[1], IS_USER(s));
1513 }
1514 } else {
1515 if (insn & (1 << 22)) { /* WLDRH */
1516 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1517 } else { /* WLDRB */
1518 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1519 }
1520 }
1521 if (i) {
1522 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1523 dead_tmp(tmp);
1524 }
1525 gen_op_iwmmxt_movq_wRn_M0(wrd);
1526 }
1527 } else {
1528 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1529 gen_op_iwmmxt_movl_T0_wCx(wrd);
1530 tmp = new_tmp();
1531 tcg_gen_mov_i32(tmp, cpu_T[0]);
1532 gen_st32(tmp, cpu_T[1], IS_USER(s));
1533 } else {
1534 gen_op_iwmmxt_movq_M0_wRn(wrd);
1535 tmp = new_tmp();
1536 if (insn & (1 << 8)) {
1537 if (insn & (1 << 22)) { /* WSTRD */
1538 dead_tmp(tmp);
1539 tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1540 } else { /* WSTRW wRd */
1541 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1542 gen_st32(tmp, cpu_T[1], IS_USER(s));
1543 }
1544 } else {
1545 if (insn & (1 << 22)) { /* WSTRH */
1546 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1547 gen_st16(tmp, cpu_T[1], IS_USER(s));
1548 } else { /* WSTRB */
1549 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1550 gen_st8(tmp, cpu_T[1], IS_USER(s));
1551 }
1552 }
1553 }
1554 }
1555 return 0;
1556 }
1557
1558 if ((insn & 0x0f000000) != 0x0e000000)
1559 return 1;
1560
1561 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1562 case 0x000: /* WOR */
1563 wrd = (insn >> 12) & 0xf;
1564 rd0 = (insn >> 0) & 0xf;
1565 rd1 = (insn >> 16) & 0xf;
1566 gen_op_iwmmxt_movq_M0_wRn(rd0);
1567 gen_op_iwmmxt_orq_M0_wRn(rd1);
1568 gen_op_iwmmxt_setpsr_nz();
1569 gen_op_iwmmxt_movq_wRn_M0(wrd);
1570 gen_op_iwmmxt_set_mup();
1571 gen_op_iwmmxt_set_cup();
1572 break;
1573 case 0x011: /* TMCR */
1574 if (insn & 0xf)
1575 return 1;
1576 rd = (insn >> 12) & 0xf;
1577 wrd = (insn >> 16) & 0xf;
1578 switch (wrd) {
1579 case ARM_IWMMXT_wCID:
1580 case ARM_IWMMXT_wCASF:
1581 break;
1582 case ARM_IWMMXT_wCon:
1583 gen_op_iwmmxt_set_cup();
1584 /* Fall through. */
1585 case ARM_IWMMXT_wCSSF:
1586 gen_op_iwmmxt_movl_T0_wCx(wrd);
1587 gen_movl_T1_reg(s, rd);
1588 gen_op_bicl_T0_T1();
1589 gen_op_iwmmxt_movl_wCx_T0(wrd);
1590 break;
1591 case ARM_IWMMXT_wCGR0:
1592 case ARM_IWMMXT_wCGR1:
1593 case ARM_IWMMXT_wCGR2:
1594 case ARM_IWMMXT_wCGR3:
1595 gen_op_iwmmxt_set_cup();
1596 gen_movl_reg_T0(s, rd);
1597 gen_op_iwmmxt_movl_wCx_T0(wrd);
1598 break;
1599 default:
1600 return 1;
1601 }
1602 break;
1603 case 0x100: /* WXOR */
1604 wrd = (insn >> 12) & 0xf;
1605 rd0 = (insn >> 0) & 0xf;
1606 rd1 = (insn >> 16) & 0xf;
1607 gen_op_iwmmxt_movq_M0_wRn(rd0);
1608 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1609 gen_op_iwmmxt_setpsr_nz();
1610 gen_op_iwmmxt_movq_wRn_M0(wrd);
1611 gen_op_iwmmxt_set_mup();
1612 gen_op_iwmmxt_set_cup();
1613 break;
1614 case 0x111: /* TMRC */
1615 if (insn & 0xf)
1616 return 1;
1617 rd = (insn >> 12) & 0xf;
1618 wrd = (insn >> 16) & 0xf;
1619 gen_op_iwmmxt_movl_T0_wCx(wrd);
1620 gen_movl_reg_T0(s, rd);
1621 break;
1622 case 0x300: /* WANDN */
1623 wrd = (insn >> 12) & 0xf;
1624 rd0 = (insn >> 0) & 0xf;
1625 rd1 = (insn >> 16) & 0xf;
1626 gen_op_iwmmxt_movq_M0_wRn(rd0);
1627 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1628 gen_op_iwmmxt_andq_M0_wRn(rd1);
1629 gen_op_iwmmxt_setpsr_nz();
1630 gen_op_iwmmxt_movq_wRn_M0(wrd);
1631 gen_op_iwmmxt_set_mup();
1632 gen_op_iwmmxt_set_cup();
1633 break;
1634 case 0x200: /* WAND */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 0) & 0xf;
1637 rd1 = (insn >> 16) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 gen_op_iwmmxt_andq_M0_wRn(rd1);
1640 gen_op_iwmmxt_setpsr_nz();
1641 gen_op_iwmmxt_movq_wRn_M0(wrd);
1642 gen_op_iwmmxt_set_mup();
1643 gen_op_iwmmxt_set_cup();
1644 break;
1645 case 0x810: case 0xa10: /* WMADD */
1646 wrd = (insn >> 12) & 0xf;
1647 rd0 = (insn >> 0) & 0xf;
1648 rd1 = (insn >> 16) & 0xf;
1649 gen_op_iwmmxt_movq_M0_wRn(rd0);
1650 if (insn & (1 << 21))
1651 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1652 else
1653 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1654 gen_op_iwmmxt_movq_wRn_M0(wrd);
1655 gen_op_iwmmxt_set_mup();
1656 break;
1657 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1658 wrd = (insn >> 12) & 0xf;
1659 rd0 = (insn >> 16) & 0xf;
1660 rd1 = (insn >> 0) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0);
1662 switch ((insn >> 22) & 3) {
1663 case 0:
1664 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1665 break;
1666 case 1:
1667 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1668 break;
1669 case 2:
1670 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1671 break;
1672 case 3:
1673 return 1;
1674 }
1675 gen_op_iwmmxt_movq_wRn_M0(wrd);
1676 gen_op_iwmmxt_set_mup();
1677 gen_op_iwmmxt_set_cup();
1678 break;
1679 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1680 wrd = (insn >> 12) & 0xf;
1681 rd0 = (insn >> 16) & 0xf;
1682 rd1 = (insn >> 0) & 0xf;
1683 gen_op_iwmmxt_movq_M0_wRn(rd0);
1684 switch ((insn >> 22) & 3) {
1685 case 0:
1686 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1687 break;
1688 case 1:
1689 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1690 break;
1691 case 2:
1692 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1693 break;
1694 case 3:
1695 return 1;
1696 }
1697 gen_op_iwmmxt_movq_wRn_M0(wrd);
1698 gen_op_iwmmxt_set_mup();
1699 gen_op_iwmmxt_set_cup();
1700 break;
1701 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1702 wrd = (insn >> 12) & 0xf;
1703 rd0 = (insn >> 16) & 0xf;
1704 rd1 = (insn >> 0) & 0xf;
1705 gen_op_iwmmxt_movq_M0_wRn(rd0);
1706 if (insn & (1 << 22))
1707 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1708 else
1709 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1710 if (!(insn & (1 << 20)))
1711 gen_op_iwmmxt_addl_M0_wRn(wrd);
1712 gen_op_iwmmxt_movq_wRn_M0(wrd);
1713 gen_op_iwmmxt_set_mup();
1714 break;
1715 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1716 wrd = (insn >> 12) & 0xf;
1717 rd0 = (insn >> 16) & 0xf;
1718 rd1 = (insn >> 0) & 0xf;
1719 gen_op_iwmmxt_movq_M0_wRn(rd0);
1720 if (insn & (1 << 21)) {
1721 if (insn & (1 << 20))
1722 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1723 else
1724 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1725 } else {
1726 if (insn & (1 << 20))
1727 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1728 else
1729 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1730 }
1731 gen_op_iwmmxt_movq_wRn_M0(wrd);
1732 gen_op_iwmmxt_set_mup();
1733 break;
1734 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1735 wrd = (insn >> 12) & 0xf;
1736 rd0 = (insn >> 16) & 0xf;
1737 rd1 = (insn >> 0) & 0xf;
1738 gen_op_iwmmxt_movq_M0_wRn(rd0);
1739 if (insn & (1 << 21))
1740 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1741 else
1742 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1743 if (!(insn & (1 << 20))) {
1744 iwmmxt_load_reg(cpu_V1, wrd);
1745 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1746 }
1747 gen_op_iwmmxt_movq_wRn_M0(wrd);
1748 gen_op_iwmmxt_set_mup();
1749 break;
1750 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1751 wrd = (insn >> 12) & 0xf;
1752 rd0 = (insn >> 16) & 0xf;
1753 rd1 = (insn >> 0) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0);
1755 switch ((insn >> 22) & 3) {
1756 case 0:
1757 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1758 break;
1759 case 1:
1760 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1761 break;
1762 case 2:
1763 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1764 break;
1765 case 3:
1766 return 1;
1767 }
1768 gen_op_iwmmxt_movq_wRn_M0(wrd);
1769 gen_op_iwmmxt_set_mup();
1770 gen_op_iwmmxt_set_cup();
1771 break;
1772 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1773 wrd = (insn >> 12) & 0xf;
1774 rd0 = (insn >> 16) & 0xf;
1775 rd1 = (insn >> 0) & 0xf;
1776 gen_op_iwmmxt_movq_M0_wRn(rd0);
1777 if (insn & (1 << 22)) {
1778 if (insn & (1 << 20))
1779 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1780 else
1781 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1782 } else {
1783 if (insn & (1 << 20))
1784 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1785 else
1786 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1787 }
1788 gen_op_iwmmxt_movq_wRn_M0(wrd);
1789 gen_op_iwmmxt_set_mup();
1790 gen_op_iwmmxt_set_cup();
1791 break;
1792 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1793 wrd = (insn >> 12) & 0xf;
1794 rd0 = (insn >> 16) & 0xf;
1795 rd1 = (insn >> 0) & 0xf;
1796 gen_op_iwmmxt_movq_M0_wRn(rd0);
1797 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1798 gen_op_movl_T1_im(7);
1799 gen_op_andl_T0_T1();
1800 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1801 gen_op_iwmmxt_movq_wRn_M0(wrd);
1802 gen_op_iwmmxt_set_mup();
1803 break;
1804 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1805 rd = (insn >> 12) & 0xf;
1806 wrd = (insn >> 16) & 0xf;
1807 gen_movl_T0_reg(s, rd);
1808 gen_op_iwmmxt_movq_M0_wRn(wrd);
1809 switch ((insn >> 6) & 3) {
1810 case 0:
1811 gen_op_movl_T1_im(0xff);
1812 gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1813 break;
1814 case 1:
1815 gen_op_movl_T1_im(0xffff);
1816 gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1817 break;
1818 case 2:
1819 gen_op_movl_T1_im(0xffffffff);
1820 gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1821 break;
1822 case 3:
1823 return 1;
1824 }
1825 gen_op_iwmmxt_movq_wRn_M0(wrd);
1826 gen_op_iwmmxt_set_mup();
1827 break;
1828 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1829 rd = (insn >> 12) & 0xf;
1830 wrd = (insn >> 16) & 0xf;
1831 if (rd == 15)
1832 return 1;
1833 gen_op_iwmmxt_movq_M0_wRn(wrd);
1834 switch ((insn >> 22) & 3) {
1835 case 0:
1836 if (insn & 8)
1837 gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1838 else {
1839 gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1840 }
1841 break;
1842 case 1:
1843 if (insn & 8)
1844 gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1845 else {
1846 gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1847 }
1848 break;
1849 case 2:
1850 gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1851 break;
1852 case 3:
1853 return 1;
1854 }
1855 gen_movl_reg_T0(s, rd);
1856 break;
1857 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1858 if ((insn & 0x000ff008) != 0x0003f000)
1859 return 1;
1860 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1861 switch ((insn >> 22) & 3) {
1862 case 0:
1863 gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1864 break;
1865 case 1:
1866 gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1867 break;
1868 case 2:
1869 gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1870 break;
1871 case 3:
1872 return 1;
1873 }
1874 gen_op_shll_T1_im(28);
1875 gen_set_nzcv(cpu_T[1]);
1876 break;
1877 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1878 rd = (insn >> 12) & 0xf;
1879 wrd = (insn >> 16) & 0xf;
1880 gen_movl_T0_reg(s, rd);
1881 switch ((insn >> 6) & 3) {
1882 case 0:
1883 gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1884 break;
1885 case 1:
1886 gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1887 break;
1888 case 2:
1889 gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1890 break;
1891 case 3:
1892 return 1;
1893 }
1894 gen_op_iwmmxt_movq_wRn_M0(wrd);
1895 gen_op_iwmmxt_set_mup();
1896 break;
1897 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1898 if ((insn & 0x000ff00f) != 0x0003f000)
1899 return 1;
1900 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1901 gen_op_movl_T0_T1();
1902 switch ((insn >> 22) & 3) {
1903 case 0:
1904 for (i = 0; i < 7; i ++) {
1905 gen_op_shll_T1_im(4);
1906 gen_op_andl_T0_T1();
1907 }
1908 break;
1909 case 1:
1910 for (i = 0; i < 3; i ++) {
1911 gen_op_shll_T1_im(8);
1912 gen_op_andl_T0_T1();
1913 }
1914 break;
1915 case 2:
1916 gen_op_shll_T1_im(16);
1917 gen_op_andl_T0_T1();
1918 break;
1919 case 3:
1920 return 1;
1921 }
1922 gen_set_nzcv(cpu_T[0]);
1923 break;
1924 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1925 wrd = (insn >> 12) & 0xf;
1926 rd0 = (insn >> 16) & 0xf;
1927 gen_op_iwmmxt_movq_M0_wRn(rd0);
1928 switch ((insn >> 22) & 3) {
1929 case 0:
1930 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1931 break;
1932 case 1:
1933 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1934 break;
1935 case 2:
1936 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1937 break;
1938 case 3:
1939 return 1;
1940 }
1941 gen_op_iwmmxt_movq_wRn_M0(wrd);
1942 gen_op_iwmmxt_set_mup();
1943 break;
1944 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1945 if ((insn & 0x000ff00f) != 0x0003f000)
1946 return 1;
1947 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1948 gen_op_movl_T0_T1();
1949 switch ((insn >> 22) & 3) {
1950 case 0:
1951 for (i = 0; i < 7; i ++) {
1952 gen_op_shll_T1_im(4);
1953 gen_op_orl_T0_T1();
1954 }
1955 break;
1956 case 1:
1957 for (i = 0; i < 3; i ++) {
1958 gen_op_shll_T1_im(8);
1959 gen_op_orl_T0_T1();
1960 }
1961 break;
1962 case 2:
1963 gen_op_shll_T1_im(16);
1964 gen_op_orl_T0_T1();
1965 break;
1966 case 3:
1967 return 1;
1968 }
1969 gen_set_nzcv(cpu_T[0]);
1970 break;
1971 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1972 rd = (insn >> 12) & 0xf;
1973 rd0 = (insn >> 16) & 0xf;
1974 if ((insn & 0xf) != 0)
1975 return 1;
1976 gen_op_iwmmxt_movq_M0_wRn(rd0);
1977 switch ((insn >> 22) & 3) {
1978 case 0:
1979 gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
1980 break;
1981 case 1:
1982 gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
1983 break;
1984 case 2:
1985 gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
1986 break;
1987 case 3:
1988 return 1;
1989 }
1990 gen_movl_reg_T0(s, rd);
1991 break;
1992 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1993 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1994 wrd = (insn >> 12) & 0xf;
1995 rd0 = (insn >> 16) & 0xf;
1996 rd1 = (insn >> 0) & 0xf;
1997 gen_op_iwmmxt_movq_M0_wRn(rd0);
1998 switch ((insn >> 22) & 3) {
1999 case 0:
2000 if (insn & (1 << 21))
2001 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2002 else
2003 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2004 break;
2005 case 1:
2006 if (insn & (1 << 21))
2007 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2008 else
2009 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2010 break;
2011 case 2:
2012 if (insn & (1 << 21))
2013 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2014 else
2015 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2016 break;
2017 case 3:
2018 return 1;
2019 }
2020 gen_op_iwmmxt_movq_wRn_M0(wrd);
2021 gen_op_iwmmxt_set_mup();
2022 gen_op_iwmmxt_set_cup();
2023 break;
2024 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2025 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2026 wrd = (insn >> 12) & 0xf;
2027 rd0 = (insn >> 16) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0);
2029 switch ((insn >> 22) & 3) {
2030 case 0:
2031 if (insn & (1 << 21))
2032 gen_op_iwmmxt_unpacklsb_M0();
2033 else
2034 gen_op_iwmmxt_unpacklub_M0();
2035 break;
2036 case 1:
2037 if (insn & (1 << 21))
2038 gen_op_iwmmxt_unpacklsw_M0();
2039 else
2040 gen_op_iwmmxt_unpackluw_M0();
2041 break;
2042 case 2:
2043 if (insn & (1 << 21))
2044 gen_op_iwmmxt_unpacklsl_M0();
2045 else
2046 gen_op_iwmmxt_unpacklul_M0();
2047 break;
2048 case 3:
2049 return 1;
2050 }
2051 gen_op_iwmmxt_movq_wRn_M0(wrd);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2054 break;
2055 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2056 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2057 wrd = (insn >> 12) & 0xf;
2058 rd0 = (insn >> 16) & 0xf;
2059 gen_op_iwmmxt_movq_M0_wRn(rd0);
2060 switch ((insn >> 22) & 3) {
2061 case 0:
2062 if (insn & (1 << 21))
2063 gen_op_iwmmxt_unpackhsb_M0();
2064 else
2065 gen_op_iwmmxt_unpackhub_M0();
2066 break;
2067 case 1:
2068 if (insn & (1 << 21))
2069 gen_op_iwmmxt_unpackhsw_M0();
2070 else
2071 gen_op_iwmmxt_unpackhuw_M0();
2072 break;
2073 case 2:
2074 if (insn & (1 << 21))
2075 gen_op_iwmmxt_unpackhsl_M0();
2076 else
2077 gen_op_iwmmxt_unpackhul_M0();
2078 break;
2079 case 3:
2080 return 1;
2081 }
2082 gen_op_iwmmxt_movq_wRn_M0(wrd);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2085 break;
2086 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2087 case 0x214: case 0x614: case 0xa14: case 0xe14:
2088 wrd = (insn >> 12) & 0xf;
2089 rd0 = (insn >> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0);
2091 if (gen_iwmmxt_shift(insn, 0xff))
2092 return 1;
2093 switch ((insn >> 22) & 3) {
2094 case 0:
2095 return 1;
2096 case 1:
2097 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2098 break;
2099 case 2:
2100 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2101 break;
2102 case 3:
2103 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2104 break;
2105 }
2106 gen_op_iwmmxt_movq_wRn_M0(wrd);
2107 gen_op_iwmmxt_set_mup();
2108 gen_op_iwmmxt_set_cup();
2109 break;
2110 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2111 case 0x014: case 0x414: case 0x814: case 0xc14:
2112 wrd = (insn >> 12) & 0xf;
2113 rd0 = (insn >> 16) & 0xf;
2114 gen_op_iwmmxt_movq_M0_wRn(rd0);
2115 if (gen_iwmmxt_shift(insn, 0xff))
2116 return 1;
2117 switch ((insn >> 22) & 3) {
2118 case 0:
2119 return 1;
2120 case 1:
2121 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2122 break;
2123 case 2:
2124 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2125 break;
2126 case 3:
2127 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2128 break;
2129 }
2130 gen_op_iwmmxt_movq_wRn_M0(wrd);
2131 gen_op_iwmmxt_set_mup();
2132 gen_op_iwmmxt_set_cup();
2133 break;
2134 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2135 case 0x114: case 0x514: case 0x914: case 0xd14:
2136 wrd = (insn >> 12) & 0xf;
2137 rd0 = (insn >> 16) & 0xf;
2138 gen_op_iwmmxt_movq_M0_wRn(rd0);
2139 if (gen_iwmmxt_shift(insn, 0xff))
2140 return 1;
2141 switch ((insn >> 22) & 3) {
2142 case 0:
2143 return 1;
2144 case 1:
2145 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2146 break;
2147 case 2:
2148 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2149 break;
2150 case 3:
2151 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2152 break;
2153 }
2154 gen_op_iwmmxt_movq_wRn_M0(wrd);
2155 gen_op_iwmmxt_set_mup();
2156 gen_op_iwmmxt_set_cup();
2157 break;
2158 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2159 case 0x314: case 0x714: case 0xb14: case 0xf14:
2160 wrd = (insn >> 12) & 0xf;
2161 rd0 = (insn >> 16) & 0xf;
2162 gen_op_iwmmxt_movq_M0_wRn(rd0);
2163 switch ((insn >> 22) & 3) {
2164 case 0:
2165 return 1;
2166 case 1:
2167 if (gen_iwmmxt_shift(insn, 0xf))
2168 return 1;
2169 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2170 break;
2171 case 2:
2172 if (gen_iwmmxt_shift(insn, 0x1f))
2173 return 1;
2174 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2175 break;
2176 case 3:
2177 if (gen_iwmmxt_shift(insn, 0x3f))
2178 return 1;
2179 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2180 break;
2181 }
2182 gen_op_iwmmxt_movq_wRn_M0(wrd);
2183 gen_op_iwmmxt_set_mup();
2184 gen_op_iwmmxt_set_cup();
2185 break;
2186 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2187 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2188 wrd = (insn >> 12) & 0xf;
2189 rd0 = (insn >> 16) & 0xf;
2190 rd1 = (insn >> 0) & 0xf;
2191 gen_op_iwmmxt_movq_M0_wRn(rd0);
2192 switch ((insn >> 22) & 3) {
2193 case 0:
2194 if (insn & (1 << 21))
2195 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2196 else
2197 gen_op_iwmmxt_minub_M0_wRn(rd1);
2198 break;
2199 case 1:
2200 if (insn & (1 << 21))
2201 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2202 else
2203 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2204 break;
2205 case 2:
2206 if (insn & (1 << 21))
2207 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2208 else
2209 gen_op_iwmmxt_minul_M0_wRn(rd1);
2210 break;
2211 case 3:
2212 return 1;
2213 }
2214 gen_op_iwmmxt_movq_wRn_M0(wrd);
2215 gen_op_iwmmxt_set_mup();
2216 break;
2217 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2218 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2219 wrd = (insn >> 12) & 0xf;
2220 rd0 = (insn >> 16) & 0xf;
2221 rd1 = (insn >> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0);
2223 switch ((insn >> 22) & 3) {
2224 case 0:
2225 if (insn & (1 << 21))
2226 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2227 else
2228 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2229 break;
2230 case 1:
2231 if (insn & (1 << 21))
2232 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2233 else
2234 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2235 break;
2236 case 2:
2237 if (insn & (1 << 21))
2238 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2239 else
2240 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2241 break;
2242 case 3:
2243 return 1;
2244 }
2245 gen_op_iwmmxt_movq_wRn_M0(wrd);
2246 gen_op_iwmmxt_set_mup();
2247 break;
2248 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2249 case 0x402: case 0x502: case 0x602: case 0x702:
2250 wrd = (insn >> 12) & 0xf;
2251 rd0 = (insn >> 16) & 0xf;
2252 rd1 = (insn >> 0) & 0xf;
2253 gen_op_iwmmxt_movq_M0_wRn(rd0);
2254 gen_op_movl_T0_im((insn >> 20) & 3);
2255 gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2256 gen_op_iwmmxt_movq_wRn_M0(wrd);
2257 gen_op_iwmmxt_set_mup();
2258 break;
2259 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2260 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2261 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2262 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2263 wrd = (insn >> 12) & 0xf;
2264 rd0 = (insn >> 16) & 0xf;
2265 rd1 = (insn >> 0) & 0xf;
2266 gen_op_iwmmxt_movq_M0_wRn(rd0);
2267 switch ((insn >> 20) & 0xf) {
2268 case 0x0:
2269 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2270 break;
2271 case 0x1:
2272 gen_op_iwmmxt_subub_M0_wRn(rd1);
2273 break;
2274 case 0x3:
2275 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2276 break;
2277 case 0x4:
2278 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2279 break;
2280 case 0x5:
2281 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2282 break;
2283 case 0x7:
2284 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2285 break;
2286 case 0x8:
2287 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2288 break;
2289 case 0x9:
2290 gen_op_iwmmxt_subul_M0_wRn(rd1);
2291 break;
2292 case 0xb:
2293 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2294 break;
2295 default:
2296 return 1;
2297 }
2298 gen_op_iwmmxt_movq_wRn_M0(wrd);
2299 gen_op_iwmmxt_set_mup();
2300 gen_op_iwmmxt_set_cup();
2301 break;
2302 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2303 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2304 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2305 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2306 wrd = (insn >> 12) & 0xf;
2307 rd0 = (insn >> 16) & 0xf;
2308 gen_op_iwmmxt_movq_M0_wRn(rd0);
2309 gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2310 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2311 gen_op_iwmmxt_movq_wRn_M0(wrd);
2312 gen_op_iwmmxt_set_mup();
2313 gen_op_iwmmxt_set_cup();
2314 break;
2315 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2316 case 0x418: case 0x518: case 0x618: case 0x718:
2317 case 0x818: case 0x918: case 0xa18: case 0xb18:
2318 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2319 wrd = (insn >> 12) & 0xf;
2320 rd0 = (insn >> 16) & 0xf;
2321 rd1 = (insn >> 0) & 0xf;
2322 gen_op_iwmmxt_movq_M0_wRn(rd0);
2323 switch ((insn >> 20) & 0xf) {
2324 case 0x0:
2325 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2326 break;
2327 case 0x1:
2328 gen_op_iwmmxt_addub_M0_wRn(rd1);
2329 break;
2330 case 0x3:
2331 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2332 break;
2333 case 0x4:
2334 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2335 break;
2336 case 0x5:
2337 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2338 break;
2339 case 0x7:
2340 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2341 break;
2342 case 0x8:
2343 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2344 break;
2345 case 0x9:
2346 gen_op_iwmmxt_addul_M0_wRn(rd1);
2347 break;
2348 case 0xb:
2349 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2350 break;
2351 default:
2352 return 1;
2353 }
2354 gen_op_iwmmxt_movq_wRn_M0(wrd);
2355 gen_op_iwmmxt_set_mup();
2356 gen_op_iwmmxt_set_cup();
2357 break;
2358 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2359 case 0x408: case 0x508: case 0x608: case 0x708:
2360 case 0x808: case 0x908: case 0xa08: case 0xb08:
2361 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2362 wrd = (insn >> 12) & 0xf;
2363 rd0 = (insn >> 16) & 0xf;
2364 rd1 = (insn >> 0) & 0xf;
2365 gen_op_iwmmxt_movq_M0_wRn(rd0);
2366 if (!(insn & (1 << 20)))
2367 return 1;
2368 switch ((insn >> 22) & 3) {
2369 case 0:
2370 return 1;
2371 case 1:
2372 if (insn & (1 << 21))
2373 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2374 else
2375 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2376 break;
2377 case 2:
2378 if (insn & (1 << 21))
2379 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2380 else
2381 gen_op_iwmmxt_packul_M0_wRn(rd1);
2382 break;
2383 case 3:
2384 if (insn & (1 << 21))
2385 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2386 else
2387 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2388 break;
2389 }
2390 gen_op_iwmmxt_movq_wRn_M0(wrd);
2391 gen_op_iwmmxt_set_mup();
2392 gen_op_iwmmxt_set_cup();
2393 break;
2394 case 0x201: case 0x203: case 0x205: case 0x207:
2395 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2396 case 0x211: case 0x213: case 0x215: case 0x217:
2397 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2398 wrd = (insn >> 5) & 0xf;
2399 rd0 = (insn >> 12) & 0xf;
2400 rd1 = (insn >> 0) & 0xf;
2401 if (rd0 == 0xf || rd1 == 0xf)
2402 return 1;
2403 gen_op_iwmmxt_movq_M0_wRn(wrd);
2404 switch ((insn >> 16) & 0xf) {
2405 case 0x0: /* TMIA */
2406 gen_movl_T0_reg(s, rd0);
2407 gen_movl_T1_reg(s, rd1);
2408 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2409 break;
2410 case 0x8: /* TMIAPH */
2411 gen_movl_T0_reg(s, rd0);
2412 gen_movl_T1_reg(s, rd1);
2413 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2414 break;
2415 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2416 gen_movl_T1_reg(s, rd0);
2417 if (insn & (1 << 16))
2418 gen_op_shrl_T1_im(16);
2419 gen_op_movl_T0_T1();
2420 gen_movl_T1_reg(s, rd1);
2421 if (insn & (1 << 17))
2422 gen_op_shrl_T1_im(16);
2423 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2424 break;
2425 default:
2426 return 1;
2427 }
2428 gen_op_iwmmxt_movq_wRn_M0(wrd);
2429 gen_op_iwmmxt_set_mup();
2430 break;
2431 default:
2432 return 1;
2433 }
2434
2435 return 0;
2436 }
2437
2438 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2439 (ie. an undefined instruction). */
2440 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2441 {
2442 int acc, rd0, rd1, rdhi, rdlo;
2443
2444 if ((insn & 0x0ff00f10) == 0x0e200010) {
2445 /* Multiply with Internal Accumulate Format */
2446 rd0 = (insn >> 12) & 0xf;
2447 rd1 = insn & 0xf;
2448 acc = (insn >> 5) & 7;
2449
2450 if (acc != 0)
2451 return 1;
2452
2453 switch ((insn >> 16) & 0xf) {
2454 case 0x0: /* MIA */
2455 gen_movl_T0_reg(s, rd0);
2456 gen_movl_T1_reg(s, rd1);
2457 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2458 break;
2459 case 0x8: /* MIAPH */
2460 gen_movl_T0_reg(s, rd0);
2461 gen_movl_T1_reg(s, rd1);
2462 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2463 break;
2464 case 0xc: /* MIABB */
2465 case 0xd: /* MIABT */
2466 case 0xe: /* MIATB */
2467 case 0xf: /* MIATT */
2468 gen_movl_T1_reg(s, rd0);
2469 if (insn & (1 << 16))
2470 gen_op_shrl_T1_im(16);
2471 gen_op_movl_T0_T1();
2472 gen_movl_T1_reg(s, rd1);
2473 if (insn & (1 << 17))
2474 gen_op_shrl_T1_im(16);
2475 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2476 break;
2477 default:
2478 return 1;
2479 }
2480
2481 gen_op_iwmmxt_movq_wRn_M0(acc);
2482 return 0;
2483 }
2484
2485 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2486 /* Internal Accumulator Access Format */
2487 rdhi = (insn >> 16) & 0xf;
2488 rdlo = (insn >> 12) & 0xf;
2489 acc = insn & 7;
2490
2491 if (acc != 0)
2492 return 1;
2493
2494 if (insn & ARM_CP_RW_BIT) { /* MRA */
2495 gen_iwmmxt_movl_T0_T1_wRn(acc);
2496 gen_movl_reg_T0(s, rdlo);
2497 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2498 gen_op_andl_T0_T1();
2499 gen_movl_reg_T0(s, rdhi);
2500 } else { /* MAR */
2501 gen_movl_T0_reg(s, rdlo);
2502 gen_movl_T1_reg(s, rdhi);
2503 gen_iwmmxt_movl_wRn_T0_T1(acc);
2504 }
2505 return 0;
2506 }
2507
2508 return 1;
2509 }
2510
2511 /* Disassemble system coprocessor instruction. Return nonzero if
2512 instruction is not defined. */
2513 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2514 {
2515 TCGv tmp;
2516 uint32_t rd = (insn >> 12) & 0xf;
2517 uint32_t cp = (insn >> 8) & 0xf;
2518 if (IS_USER(s)) {
2519 return 1;
2520 }
2521
2522 if (insn & ARM_CP_RW_BIT) {
2523 if (!env->cp[cp].cp_read)
2524 return 1;
2525 gen_set_pc_im(s->pc);
2526 tmp = new_tmp();
2527 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2528 store_reg(s, rd, tmp);
2529 } else {
2530 if (!env->cp[cp].cp_write)
2531 return 1;
2532 gen_set_pc_im(s->pc);
2533 tmp = load_reg(s, rd);
2534 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2535 dead_tmp(tmp);
2536 }
2537 return 0;
2538 }
2539
2540 static int cp15_user_ok(uint32_t insn)
2541 {
2542 int cpn = (insn >> 16) & 0xf;
2543 int cpm = insn & 0xf;
2544 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2545
2546 if (cpn == 13 && cpm == 0) {
2547 /* TLS register. */
2548 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2549 return 1;
2550 }
2551 if (cpn == 7) {
2552 /* ISB, DSB, DMB. */
2553 if ((cpm == 5 && op == 4)
2554 || (cpm == 10 && (op == 4 || op == 5)))
2555 return 1;
2556 }
2557 return 0;
2558 }
2559
2560 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2561 instruction is not defined. */
2562 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2563 {
2564 uint32_t rd;
2565 TCGv tmp;
2566
2567 /* M profile cores use memory mapped registers instead of cp15. */
2568 if (arm_feature(env, ARM_FEATURE_M))
2569 return 1;
2570
2571 if ((insn & (1 << 25)) == 0) {
2572 if (insn & (1 << 20)) {
2573 /* mrrc */
2574 return 1;
2575 }
2576 /* mcrr. Used for block cache operations, so implement as no-op. */
2577 return 0;
2578 }
2579 if ((insn & (1 << 4)) == 0) {
2580 /* cdp */
2581 return 1;
2582 }
2583 if (IS_USER(s) && !cp15_user_ok(insn)) {
2584 return 1;
2585 }
2586 if ((insn & 0x0fff0fff) == 0x0e070f90
2587 || (insn & 0x0fff0fff) == 0x0e070f58) {
2588 /* Wait for interrupt. */
2589 gen_set_pc_im(s->pc);
2590 s->is_jmp = DISAS_WFI;
2591 return 0;
2592 }
2593 rd = (insn >> 12) & 0xf;
2594 if (insn & ARM_CP_RW_BIT) {
2595 tmp = new_tmp();
2596 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2597 /* If the destination register is r15 then sets condition codes. */
2598 if (rd != 15)
2599 store_reg(s, rd, tmp);
2600 else
2601 dead_tmp(tmp);
2602 } else {
2603 tmp = load_reg(s, rd);
2604 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2605 dead_tmp(tmp);
2606 /* Normally we would always end the TB here, but Linux
2607 * arch/arm/mach-pxa/sleep.S expects two instructions following
2608 * an MMU enable to execute from cache. Imitate this behaviour. */
2609 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2610 (insn & 0x0fff0fff) != 0x0e010f10)
2611 gen_lookup_tb(s);
2612 }
2613 return 0;
2614 }
2615
2616 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2617 #define VFP_SREG(insn, bigbit, smallbit) \
2618 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2619 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2620 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2621 reg = (((insn) >> (bigbit)) & 0x0f) \
2622 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2623 } else { \
2624 if (insn & (1 << (smallbit))) \
2625 return 1; \
2626 reg = ((insn) >> (bigbit)) & 0x0f; \
2627 }} while (0)
2628
2629 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2630 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2631 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2632 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2633 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2634 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2635
2636 /* Move between integer and VFP cores. */
2637 static TCGv gen_vfp_mrs(void)
2638 {
2639 TCGv tmp = new_tmp();
2640 tcg_gen_mov_i32(tmp, cpu_F0s);
2641 return tmp;
2642 }
2643
2644 static void gen_vfp_msr(TCGv tmp)
2645 {
2646 tcg_gen_mov_i32(cpu_F0s, tmp);
2647 dead_tmp(tmp);
2648 }
2649
2650 static inline int
2651 vfp_enabled(CPUState * env)
2652 {
2653 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2654 }
2655
2656 static void gen_neon_dup_u8(TCGv var, int shift)
2657 {
2658 TCGv tmp = new_tmp();
2659 if (shift)
2660 tcg_gen_shri_i32(var, var, shift);
2661 tcg_gen_ext8u_i32(var, var);
2662 tcg_gen_shli_i32(tmp, var, 8);
2663 tcg_gen_or_i32(var, var, tmp);
2664 tcg_gen_shli_i32(tmp, var, 16);
2665 tcg_gen_or_i32(var, var, tmp);
2666 dead_tmp(tmp);
2667 }
2668
2669 static void gen_neon_dup_low16(TCGv var)
2670 {
2671 TCGv tmp = new_tmp();
2672 tcg_gen_ext16u_i32(var, var);
2673 tcg_gen_shli_i32(tmp, var, 16);
2674 tcg_gen_or_i32(var, var, tmp);
2675 dead_tmp(tmp);
2676 }
2677
2678 static void gen_neon_dup_high16(TCGv var)
2679 {
2680 TCGv tmp = new_tmp();
2681 tcg_gen_andi_i32(var, var, 0xffff0000);
2682 tcg_gen_shri_i32(tmp, var, 16);
2683 tcg_gen_or_i32(var, var, tmp);
2684 dead_tmp(tmp);
2685 }
2686
2687 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2688 (ie. an undefined instruction). */
2689 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2690 {
2691 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2692 int dp, veclen;
2693 TCGv tmp;
2694 TCGv tmp2;
2695
2696 if (!arm_feature(env, ARM_FEATURE_VFP))
2697 return 1;
2698
2699 if (!vfp_enabled(env)) {
2700 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2701 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2702 return 1;
2703 rn = (insn >> 16) & 0xf;
2704 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2705 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2706 return 1;
2707 }
2708 dp = ((insn & 0xf00) == 0xb00);
2709 switch ((insn >> 24) & 0xf) {
2710 case 0xe:
2711 if (insn & (1 << 4)) {
2712 /* single register transfer */
2713 rd = (insn >> 12) & 0xf;
2714 if (dp) {
2715 int size;
2716 int pass;
2717
2718 VFP_DREG_N(rn, insn);
2719 if (insn & 0xf)
2720 return 1;
2721 if (insn & 0x00c00060
2722 && !arm_feature(env, ARM_FEATURE_NEON))
2723 return 1;
2724
2725 pass = (insn >> 21) & 1;
2726 if (insn & (1 << 22)) {
2727 size = 0;
2728 offset = ((insn >> 5) & 3) * 8;
2729 } else if (insn & (1 << 5)) {
2730 size = 1;
2731 offset = (insn & (1 << 6)) ? 16 : 0;
2732 } else {
2733 size = 2;
2734 offset = 0;
2735 }
2736 if (insn & ARM_CP_RW_BIT) {
2737 /* vfp->arm */
2738 tmp = neon_load_reg(rn, pass);
2739 switch (size) {
2740 case 0:
2741 if (offset)
2742 tcg_gen_shri_i32(tmp, tmp, offset);
2743 if (insn & (1 << 23))
2744 gen_uxtb(tmp);
2745 else
2746 gen_sxtb(tmp);
2747 break;
2748 case 1:
2749 if (insn & (1 << 23)) {
2750 if (offset) {
2751 tcg_gen_shri_i32(tmp, tmp, 16);
2752 } else {
2753 gen_uxth(tmp);
2754 }
2755 } else {
2756 if (offset) {
2757 tcg_gen_sari_i32(tmp, tmp, 16);
2758 } else {
2759 gen_sxth(tmp);
2760 }
2761 }
2762 break;
2763 case 2:
2764 break;
2765 }
2766 store_reg(s, rd, tmp);
2767 } else {
2768 /* arm->vfp */
2769 tmp = load_reg(s, rd);
2770 if (insn & (1 << 23)) {
2771 /* VDUP */
2772 if (size == 0) {
2773 gen_neon_dup_u8(tmp, 0);
2774 } else if (size == 1) {
2775 gen_neon_dup_low16(tmp);
2776 }
2777 for (n = 0; n <= pass * 2; n++) {
2778 tmp2 = new_tmp();
2779 tcg_gen_mov_i32(tmp2, tmp);
2780 neon_store_reg(rn, n, tmp2);
2781 }
2782 neon_store_reg(rn, n, tmp);
2783 } else {
2784 /* VMOV */
2785 switch (size) {
2786 case 0:
2787 tmp2 = neon_load_reg(rn, pass);
2788 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2789 dead_tmp(tmp2);
2790 break;
2791 case 1:
2792 tmp2 = neon_load_reg(rn, pass);
2793 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2794 dead_tmp(tmp2);
2795 break;
2796 case 2:
2797 break;
2798 }
2799 neon_store_reg(rn, pass, tmp);
2800 }
2801 }
2802 } else { /* !dp */
2803 if ((insn & 0x6f) != 0x00)
2804 return 1;
2805 rn = VFP_SREG_N(insn);
2806 if (insn & ARM_CP_RW_BIT) {
2807 /* vfp->arm */
2808 if (insn & (1 << 21)) {
2809 /* system register */
2810 rn >>= 1;
2811
2812 switch (rn) {
2813 case ARM_VFP_FPSID:
2814 /* VFP2 allows access to FSID from userspace.
2815 VFP3 restricts all id registers to privileged
2816 accesses. */
2817 if (IS_USER(s)
2818 && arm_feature(env, ARM_FEATURE_VFP3))
2819 return 1;
2820 tmp = load_cpu_field(vfp.xregs[rn]);
2821 break;
2822 case ARM_VFP_FPEXC:
2823 if (IS_USER(s))
2824 return 1;
2825 tmp = load_cpu_field(vfp.xregs[rn]);
2826 break;
2827 case ARM_VFP_FPINST:
2828 case ARM_VFP_FPINST2:
2829 /* Not present in VFP3. */
2830 if (IS_USER(s)
2831 || arm_feature(env, ARM_FEATURE_VFP3))
2832 return 1;
2833 tmp = load_cpu_field(vfp.xregs[rn]);
2834 break;
2835 case ARM_VFP_FPSCR:
2836 if (rd == 15) {
2837 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2838 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2839 } else {
2840 tmp = new_tmp();
2841 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2842 }
2843 break;
2844 case ARM_VFP_MVFR0:
2845 case ARM_VFP_MVFR1:
2846 if (IS_USER(s)
2847 || !arm_feature(env, ARM_FEATURE_VFP3))
2848 return 1;
2849 tmp = load_cpu_field(vfp.xregs[rn]);
2850 break;
2851 default:
2852 return 1;
2853 }
2854 } else {
2855 gen_mov_F0_vreg(0, rn);
2856 tmp = gen_vfp_mrs();
2857 }
2858 if (rd == 15) {
2859 /* Set the 4 flag bits in the CPSR. */
2860 gen_set_nzcv(tmp);
2861 dead_tmp(tmp);
2862 } else {
2863 store_reg(s, rd, tmp);
2864 }
2865 } else {
2866 /* arm->vfp */
2867 tmp = load_reg(s, rd);
2868 if (insn & (1 << 21)) {
2869 rn >>= 1;
2870 /* system register */
2871 switch (rn) {
2872 case ARM_VFP_FPSID:
2873 case ARM_VFP_MVFR0:
2874 case ARM_VFP_MVFR1:
2875 /* Writes are ignored. */
2876 break;
2877 case ARM_VFP_FPSCR:
2878 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2879 dead_tmp(tmp);
2880 gen_lookup_tb(s);
2881 break;
2882 case ARM_VFP_FPEXC:
2883 if (IS_USER(s))
2884 return 1;
2885 store_cpu_field(tmp, vfp.xregs[rn]);
2886 gen_lookup_tb(s);
2887 break;
2888 case ARM_VFP_FPINST:
2889 case ARM_VFP_FPINST2:
2890 store_cpu_field(tmp, vfp.xregs[rn]);
2891 break;
2892 default:
2893 return 1;
2894 }
2895 } else {
2896 gen_vfp_msr(tmp);
2897 gen_mov_vreg_F0(0, rn);
2898 }
2899 }
2900 }
2901 } else {
2902 /* data processing */
2903 /* The opcode is in bits 23, 21, 20 and 6. */
2904 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2905 if (dp) {
2906 if (op == 15) {
2907 /* rn is opcode */
2908 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2909 } else {
2910 /* rn is register number */
2911 VFP_DREG_N(rn, insn);
2912 }
2913
2914 if (op == 15 && (rn == 15 || rn > 17)) {
2915 /* Integer or single precision destination. */
2916 rd = VFP_SREG_D(insn);
2917 } else {
2918 VFP_DREG_D(rd, insn);
2919 }
2920
2921 if (op == 15 && (rn == 16 || rn == 17)) {
2922 /* Integer source. */
2923 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2924 } else {
2925 VFP_DREG_M(rm, insn);
2926 }
2927 } else {
2928 rn = VFP_SREG_N(insn);
2929 if (op == 15 && rn == 15) {
2930 /* Double precision destination. */
2931 VFP_DREG_D(rd, insn);
2932 } else {
2933 rd = VFP_SREG_D(insn);
2934 }
2935 rm = VFP_SREG_M(insn);
2936 }
2937
2938 veclen = env->vfp.vec_len;
2939 if (op == 15 && rn > 3)
2940 veclen = 0;
2941
2942 /* Shut up compiler warnings. */
2943 delta_m = 0;
2944 delta_d = 0;
2945 bank_mask = 0;
2946
2947 if (veclen > 0) {
2948 if (dp)
2949 bank_mask = 0xc;
2950 else
2951 bank_mask = 0x18;
2952
2953 /* Figure out what type of vector operation this is. */
2954 if ((rd & bank_mask) == 0) {
2955 /* scalar */
2956 veclen = 0;
2957 } else {
2958 if (dp)
2959 delta_d = (env->vfp.vec_stride >> 1) + 1;
2960 else
2961 delta_d = env->vfp.vec_stride + 1;
2962
2963 if ((rm & bank_mask) == 0) {
2964 /* mixed scalar/vector */
2965 delta_m = 0;
2966 } else {
2967 /* vector */
2968 delta_m = delta_d;
2969 }
2970 }
2971 }
2972
2973 /* Load the initial operands. */
2974 if (op == 15) {
2975 switch (rn) {
2976 case 16:
2977 case 17:
2978 /* Integer source */
2979 gen_mov_F0_vreg(0, rm);
2980 break;
2981 case 8:
2982 case 9:
2983 /* Compare */
2984 gen_mov_F0_vreg(dp, rd);
2985 gen_mov_F1_vreg(dp, rm);
2986 break;
2987 case 10:
2988 case 11:
2989 /* Compare with zero */
2990 gen_mov_F0_vreg(dp, rd);
2991 gen_vfp_F1_ld0(dp);
2992 break;
2993 case 20:
2994 case 21:
2995 case 22:
2996 case 23:
2997 case 28:
2998 case 29:
2999 case 30:
3000 case 31:
3001 /* Source and destination the same. */
3002 gen_mov_F0_vreg(dp, rd);
3003 break;
3004 default:
3005 /* One source operand. */
3006 gen_mov_F0_vreg(dp, rm);
3007 break;
3008 }
3009 } else {
3010 /* Two source operands. */
3011 gen_mov_F0_vreg(dp, rn);
3012 gen_mov_F1_vreg(dp, rm);
3013 }
3014
3015 for (;;) {
3016 /* Perform the calculation. */
3017 switch (op) {
3018 case 0: /* mac: fd + (fn * fm) */
3019 gen_vfp_mul(dp);
3020 gen_mov_F1_vreg(dp, rd);
3021 gen_vfp_add(dp);
3022 break;
3023 case 1: /* nmac: fd - (fn * fm) */
3024 gen_vfp_mul(dp);
3025 gen_vfp_neg(dp);
3026 gen_mov_F1_vreg(dp, rd);
3027 gen_vfp_add(dp);
3028 break;
3029 case 2: /* msc: -fd + (fn * fm) */
3030 gen_vfp_mul(dp);
3031 gen_mov_F1_vreg(dp, rd);
3032 gen_vfp_sub(dp);
3033 break;
3034 case 3: /* nmsc: -fd - (fn * fm) */
3035 gen_vfp_mul(dp);
3036 gen_vfp_neg(dp);
3037 gen_mov_F1_vreg(dp, rd);
3038 gen_vfp_sub(dp);
3039 break;
3040 case 4: /* mul: fn * fm */
3041 gen_vfp_mul(dp);
3042 break;
3043 case 5: /* nmul: -(fn * fm) */
3044 gen_vfp_mul(dp);
3045 gen_vfp_neg(dp);
3046 break;
3047 case 6: /* add: fn + fm */
3048 gen_vfp_add(dp);
3049 break;
3050 case 7: /* sub: fn - fm */
3051 gen_vfp_sub(dp);
3052 break;
3053 case 8: /* div: fn / fm */
3054 gen_vfp_div(dp);
3055 break;
3056 case 14: /* fconst */
3057 if (!arm_feature(env, ARM_FEATURE_VFP3))
3058 return 1;
3059
3060 n = (insn << 12) & 0x80000000;
3061 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3062 if (dp) {
3063 if (i & 0x40)
3064 i |= 0x3f80;
3065 else
3066 i |= 0x4000;
3067 n |= i << 16;
3068 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3069 } else {
3070 if (i & 0x40)
3071 i |= 0x780;
3072 else
3073 i |= 0x800;
3074 n |= i << 19;
3075 tcg_gen_movi_i32(cpu_F0s, n);
3076 }
3077 break;
3078 case 15: /* extension space */
3079 switch (rn) {
3080 case 0: /* cpy */
3081 /* no-op */
3082 break;
3083 case 1: /* abs */
3084 gen_vfp_abs(dp);
3085 break;
3086 case 2: /* neg */
3087 gen_vfp_neg(dp);
3088 break;
3089 case 3: /* sqrt */
3090 gen_vfp_sqrt(dp);
3091 break;
3092 case 8: /* cmp */
3093 gen_vfp_cmp(dp);
3094 break;
3095 case 9: /* cmpe */
3096 gen_vfp_cmpe(dp);
3097 break;
3098 case 10: /* cmpz */
3099 gen_vfp_cmp(dp);
3100 break;
3101 case 11: /* cmpez */
3102 gen_vfp_F1_ld0(dp);
3103 gen_vfp_cmpe(dp);
3104 break;
3105 case 15: /* single<->double conversion */
3106 if (dp)
3107 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3108 else
3109 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3110 break;
3111 case 16: /* fuito */
3112 gen_vfp_uito(dp);
3113 break;
3114 case 17: /* fsito */
3115 gen_vfp_sito(dp);
3116 break;
3117 case 20: /* fshto */
3118 if (!arm_feature(env, ARM_FEATURE_VFP3))
3119 return 1;
3120 gen_vfp_shto(dp, 16 - rm);
3121 break;
3122 case 21: /* fslto */
3123 if (!arm_feature(env, ARM_FEATURE_VFP3))
3124 return 1;
3125 gen_vfp_slto(dp, 32 - rm);
3126 break;
3127 case 22: /* fuhto */
3128 if (!arm_feature(env, ARM_FEATURE_VFP3))
3129 return 1;
3130 gen_vfp_uhto(dp, 16 - rm);
3131 break;
3132 case 23: /* fulto */
3133 if (!arm_feature(env, ARM_FEATURE_VFP3))
3134 return 1;
3135 gen_vfp_ulto(dp, 32 - rm);
3136 break;
3137 case 24: /* ftoui */
3138 gen_vfp_toui(dp);
3139 break;
3140 case 25: /* ftouiz */
3141 gen_vfp_touiz(dp);
3142 break;
3143 case 26: /* ftosi */
3144 gen_vfp_tosi(dp);
3145 break;
3146 case 27: /* ftosiz */
3147 gen_vfp_tosiz(dp);
3148 break;
3149 case 28: /* ftosh */
3150 if (!arm_feature(env, ARM_FEATURE_VFP3))
3151 return 1;
3152 gen_vfp_tosh(dp, 16 - rm);
3153 break;
3154 case 29: /* ftosl */
3155 if (!arm_feature(env, ARM_FEATURE_VFP3))
3156 return 1;
3157 gen_vfp_tosl(dp, 32 - rm);
3158 break;
3159 case 30: /* ftouh */
3160 if (!arm_feature(env, ARM_FEATURE_VFP3))
3161 return 1;
3162 gen_vfp_touh(dp, 16 - rm);
3163 break;
3164 case 31: /* ftoul */
3165 if (!arm_feature(env, ARM_FEATURE_VFP3))
3166 return 1;
3167 gen_vfp_toul(dp, 32 - rm);
3168 break;
3169 default: /* undefined */
3170 printf ("rn:%d\n", rn);
3171 return 1;
3172 }
3173 break;
3174 default: /* undefined */
3175 printf ("op:%d\n", op);
3176 return 1;
3177 }
3178
3179 /* Write back the result. */
3180 if (op == 15 && (rn >= 8 && rn <= 11))
3181 ; /* Comparison, do nothing. */
3182 else if (op == 15 && rn > 17)
3183 /* Integer result. */
3184 gen_mov_vreg_F0(0, rd);
3185 else if (op == 15 && rn == 15)
3186 /* conversion */
3187 gen_mov_vreg_F0(!dp, rd);
3188 else
3189 gen_mov_vreg_F0(dp, rd);
3190
3191 /* break out of the loop if we have finished */
3192 if (veclen == 0)
3193 break;
3194
3195 if (op == 15 && delta_m == 0) {
3196 /* single source one-many */
3197 while (veclen--) {
3198 rd = ((rd + delta_d) & (bank_mask - 1))
3199 | (rd & bank_mask);
3200 gen_mov_vreg_F0(dp, rd);
3201 }
3202 break;
3203 }
3204 /* Setup the next operands. */
3205 veclen--;
3206 rd = ((rd + delta_d) & (bank_mask - 1))
3207 | (rd & bank_mask);
3208
3209 if (op == 15) {
3210 /* One source operand. */
3211 rm = ((rm + delta_m) & (bank_mask - 1))
3212 | (rm & bank_mask);
3213 gen_mov_F0_vreg(dp, rm);
3214 } else {
3215 /* Two source operands. */
3216 rn = ((rn + delta_d) & (bank_mask - 1))
3217 | (rn & bank_mask);
3218 gen_mov_F0_vreg(dp, rn);
3219 if (delta_m) {
3220 rm = ((rm + delta_m) & (bank_mask - 1))
3221 | (rm & bank_mask);
3222 gen_mov_F1_vreg(dp, rm);
3223 }
3224 }
3225 }
3226 }
3227 break;
3228 case 0xc:
3229 case 0xd:
3230 if (dp && (insn & 0x03e00000) == 0x00400000) {
3231 /* two-register transfer */
3232 rn = (insn >> 16) & 0xf;
3233 rd = (insn >> 12) & 0xf;
3234 if (dp) {
3235 VFP_DREG_M(rm, insn);
3236 } else {
3237 rm = VFP_SREG_M(insn);
3238 }
3239
3240 if (insn & ARM_CP_RW_BIT) {
3241 /* vfp->arm */
3242 if (dp) {
3243 gen_mov_F0_vreg(0, rm * 2);
3244 tmp = gen_vfp_mrs();
3245 store_reg(s, rd, tmp);
3246 gen_mov_F0_vreg(0, rm * 2 + 1);
3247 tmp = gen_vfp_mrs();
3248 store_reg(s, rn, tmp);
3249 } else {
3250 gen_mov_F0_vreg(0, rm);
3251 tmp = gen_vfp_mrs();
3252 store_reg(s, rn, tmp);
3253 gen_mov_F0_vreg(0, rm + 1);
3254 tmp = gen_vfp_mrs();
3255 store_reg(s, rd, tmp);
3256 }
3257 } else {
3258 /* arm->vfp */
3259 if (dp) {
3260 tmp = load_reg(s, rd);
3261 gen_vfp_msr(tmp);
3262 gen_mov_vreg_F0(0, rm * 2);
3263 tmp = load_reg(s, rn);
3264 gen_vfp_msr(tmp);
3265 gen_mov_vreg_F0(0, rm * 2 + 1);
3266 } else {
3267 tmp = load_reg(s, rn);
3268 gen_vfp_msr(tmp);
3269 gen_mov_vreg_F0(0, rm);
3270 tmp = load_reg(s, rd);
3271 gen_vfp_msr(tmp);
3272 gen_mov_vreg_F0(0, rm + 1);
3273 }
3274 }
3275 } else {
3276 /* Load/store */
3277 rn = (insn >> 16) & 0xf;
3278 if (dp)
3279 VFP_DREG_D(rd, insn);
3280 else
3281 rd = VFP_SREG_D(insn);
3282 if (s->thumb && rn == 15) {
3283 gen_op_movl_T1_im(s->pc & ~2);
3284 } else {
3285 gen_movl_T1_reg(s, rn);
3286 }
3287 if ((insn & 0x01200000) == 0x01000000) {
3288 /* Single load/store */
3289 offset = (insn & 0xff) << 2;
3290 if ((insn & (1 << 23)) == 0)
3291 offset = -offset;
3292 gen_op_addl_T1_im(offset);
3293 if (insn & (1 << 20)) {
3294 gen_vfp_ld(s, dp);
3295 gen_mov_vreg_F0(dp, rd);
3296 } else {
3297 gen_mov_F0_vreg(dp, rd);
3298 gen_vfp_st(s, dp);
3299 }
3300 } else {
3301 /* load/store multiple */
3302 if (dp)
3303 n = (insn >> 1) & 0x7f;
3304 else
3305 n = insn & 0xff;
3306
3307 if (insn & (1 << 24)) /* pre-decrement */
3308 gen_op_addl_T1_im(-((insn & 0xff) << 2));
3309
3310 if (dp)
3311 offset = 8;
3312 else
3313 offset = 4;
3314 for (i = 0; i < n; i++) {
3315 if (insn & ARM_CP_RW_BIT) {
3316 /* load */
3317 gen_vfp_ld(s, dp);
3318 gen_mov_vreg_F0(dp, rd + i);
3319 } else {
3320 /* store */
3321 gen_mov_F0_vreg(dp, rd + i);
3322 gen_vfp_st(s, dp);
3323 }
3324 gen_op_addl_T1_im(offset);
3325 }
3326 if (insn & (1 << 21)) {
3327 /* writeback */
3328 if (insn & (1 << 24))
3329 offset = -offset * n;
3330 else if (dp && (insn & 1))
3331 offset = 4;
3332 else
3333 offset = 0;
3334
3335 if (offset != 0)
3336 gen_op_addl_T1_im(offset);
3337 gen_movl_reg_T1(s, rn);
3338 }
3339 }
3340 }
3341 break;
3342 default:
3343 /* Should never happen. */
3344 return 1;
3345 }
3346 return 0;
3347 }
3348
3349 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3350 {
3351 TranslationBlock *tb;
3352
3353 tb = s->tb;
3354 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3355 tcg_gen_goto_tb(n);
3356 gen_set_pc_im(dest);
3357 tcg_gen_exit_tb((long)tb + n);
3358 } else {
3359 gen_set_pc_im(dest);
3360 tcg_gen_exit_tb(0);
3361 }
3362 }
3363
3364 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3365 {
3366 if (unlikely(s->singlestep_enabled)) {
3367 /* An indirect jump so that we still trigger the debug exception. */
3368 if (s->thumb)
3369 dest |= 1;
3370 gen_bx_im(s, dest);
3371 } else {
3372 gen_goto_tb(s, 0, dest);
3373 s->is_jmp = DISAS_TB_JUMP;
3374 }
3375 }
3376
3377 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3378 {
3379 if (x)
3380 tcg_gen_sari_i32(t0, t0, 16);
3381 else
3382 gen_sxth(t0);
3383 if (y)
3384 tcg_gen_sari_i32(t1, t1, 16);
3385 else
3386 gen_sxth(t1);
3387 tcg_gen_mul_i32(t0, t0, t1);
3388 }
3389
3390 /* Return the mask of PSR bits set by a MSR instruction. */
3391 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3392 uint32_t mask;
3393
3394 mask = 0;
3395 if (flags & (1 << 0))
3396 mask |= 0xff;
3397 if (flags & (1 << 1))
3398 mask |= 0xff00;
3399 if (flags & (1 << 2))
3400 mask |= 0xff0000;
3401 if (flags & (1 << 3))
3402 mask |= 0xff000000;
3403
3404 /* Mask out undefined bits. */
3405 mask &= ~CPSR_RESERVED;
3406 if (!arm_feature(env, ARM_FEATURE_V6))
3407 mask &= ~(CPSR_E | CPSR_GE);
3408 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3409 mask &= ~CPSR_IT;
3410 /* Mask out execution state bits. */
3411 if (!spsr)
3412 mask &= ~CPSR_EXEC;
3413 /* Mask out privileged bits. */
3414 if (IS_USER(s))
3415 mask &= CPSR_USER;
3416 return mask;
3417 }
3418
3419 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3420 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3421 {
3422 TCGv tmp;
3423 if (spsr) {
3424 /* ??? This is also undefined in system mode. */
3425 if (IS_USER(s))
3426 return 1;
3427
3428 tmp = load_cpu_field(spsr);
3429 tcg_gen_andi_i32(tmp, tmp, ~mask);
3430 tcg_gen_andi_i32(t0, t0, mask);
3431 tcg_gen_or_i32(tmp, tmp, t0);
3432 store_cpu_field(tmp, spsr);
3433 } else {
3434 gen_set_cpsr(t0, mask);
3435 }
3436 dead_tmp(t0);
3437 gen_lookup_tb(s);
3438 return 0;
3439 }
3440
3441 /* Returns nonzero if access to the PSR is not permitted. */
3442 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3443 {
3444 TCGv tmp;
3445 tmp = new_tmp();
3446 tcg_gen_movi_i32(tmp, val);
3447 return gen_set_psr(s, mask, spsr, tmp);
3448 }
3449
3450 /* Generate an old-style exception return. Marks pc as dead. */
3451 static void gen_exception_return(DisasContext *s, TCGv pc)
3452 {
3453 TCGv tmp;
3454 store_reg(s, 15, pc);
3455 tmp = load_cpu_field(spsr);
3456 gen_set_cpsr(tmp, 0xffffffff);
3457 dead_tmp(tmp);
3458 s->is_jmp = DISAS_UPDATE;
3459 }
3460
3461 /* Generate a v6 exception return. Marks both values as dead. */
3462 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3463 {
3464 gen_set_cpsr(cpsr, 0xffffffff);
3465 dead_tmp(cpsr);
3466 store_reg(s, 15, pc);
3467 s->is_jmp = DISAS_UPDATE;
3468 }
3469
3470 static inline void
3471 gen_set_condexec (DisasContext *s)
3472 {
3473 if (s->condexec_mask) {
3474 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3475 TCGv tmp = new_tmp();
3476 tcg_gen_movi_i32(tmp, val);
3477 store_cpu_field(tmp, condexec_bits);
3478 }
3479 }
3480
3481 static void gen_nop_hint(DisasContext *s, int val)
3482 {
3483 switch (val) {
3484 case 3: /* wfi */
3485 gen_set_pc_im(s->pc);
3486 s->is_jmp = DISAS_WFI;
3487 break;
3488 case 2: /* wfe */
3489 case 4: /* sev */
3490 /* TODO: Implement SEV and WFE. May help SMP performance. */
3491 default: /* nop */
3492 break;
3493 }
3494 }
3495
3496 /* These macros help make the code more readable when migrating from the
3497 old dyngen helpers. They should probably be removed when
3498 T0/T1 are removed. */
3499 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3500 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3501
3502 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3503
3504 static inline int gen_neon_add(int size)
3505 {
3506 switch (size) {
3507 case 0: gen_helper_neon_add_u8(CPU_T001); break;
3508 case 1: gen_helper_neon_add_u16(CPU_T001); break;
3509 case 2: gen_op_addl_T0_T1(); break;
3510 default: return 1;
3511 }
3512 return 0;
3513 }
3514
3515 static inline void gen_neon_rsb(int size)
3516 {
3517 switch (size) {
3518 case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3519 case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3520 case 2: gen_op_rsbl_T0_T1(); break;
3521 default: return;
3522 }
3523 }
3524
3525 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3526 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3527 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3528 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3529 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3530
3531 /* FIXME: This is wrong. They set the wrong overflow bit. */
3532 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3533 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3534 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3535 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3536
3537 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3538 switch ((size << 1) | u) { \
3539 case 0: \
3540 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3541 break; \
3542 case 1: \
3543 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3544 break; \
3545 case 2: \
3546 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3547 break; \
3548 case 3: \
3549 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3550 break; \
3551 case 4: \
3552 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3553 break; \
3554 case 5: \
3555 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3556 break; \
3557 default: return 1; \
3558 }} while (0)
3559
3560 #define GEN_NEON_INTEGER_OP(name) do { \
3561 switch ((size << 1) | u) { \
3562 case 0: \
3563 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3564 break; \
3565 case 1: \
3566 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3567 break; \
3568 case 2: \
3569 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3570 break; \
3571 case 3: \
3572 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3573 break; \
3574 case 4: \
3575 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3576 break; \
3577 case 5: \
3578 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3579 break; \
3580 default: return 1; \
3581 }} while (0)
3582
3583 static inline void
3584 gen_neon_movl_scratch_T0(int scratch)
3585 {
3586 uint32_t offset;
3587
3588 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3589 tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3590 }
3591
3592 static inline void
3593 gen_neon_movl_scratch_T1(int scratch)
3594 {
3595 uint32_t offset;
3596
3597 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3598 tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3599 }
3600
3601 static inline void
3602 gen_neon_movl_T0_scratch(int scratch)
3603 {
3604 uint32_t offset;
3605
3606 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3607 tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3608 }
3609
3610 static inline void
3611 gen_neon_movl_T1_scratch(int scratch)
3612 {
3613 uint32_t offset;
3614
3615 offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3616 tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3617 }
3618
3619 static inline void gen_neon_get_scalar(int size, int reg)
3620 {
3621 if (size == 1) {
3622 NEON_GET_REG(T0, reg >> 1, reg & 1);
3623 } else {
3624 NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3625 if (reg & 1)
3626 gen_neon_dup_low16(cpu_T[0]);
3627 else
3628 gen_neon_dup_high16(cpu_T[0]);
3629 }
3630 }
3631
3632 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3633 {
3634 TCGv rd, rm, tmp;
3635
3636 rd = new_tmp();
3637 rm = new_tmp();
3638 tmp = new_tmp();
3639
3640 tcg_gen_andi_i32(rd, t0, 0xff);
3641 tcg_gen_shri_i32(tmp, t0, 8);
3642 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3643 tcg_gen_or_i32(rd, rd, tmp);
3644 tcg_gen_shli_i32(tmp, t1, 16);
3645 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3646 tcg_gen_or_i32(rd, rd, tmp);
3647 tcg_gen_shli_i32(tmp, t1, 8);
3648 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3649 tcg_gen_or_i32(rd, rd, tmp);
3650
3651 tcg_gen_shri_i32(rm, t0, 8);
3652 tcg_gen_andi_i32(rm, rm, 0xff);
3653 tcg_gen_shri_i32(tmp, t0, 16);
3654 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3655 tcg_gen_or_i32(rm, rm, tmp);
3656 tcg_gen_shli_i32(tmp, t1, 8);
3657 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3658 tcg_gen_or_i32(rm, rm, tmp);
3659 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3660 tcg_gen_or_i32(t1, rm, tmp);
3661 tcg_gen_mov_i32(t0, rd);
3662
3663 dead_tmp(tmp);
3664 dead_tmp(rm);
3665 dead_tmp(rd);
3666 }
3667
3668 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3669 {
3670 TCGv rd, rm, tmp;
3671
3672 rd = new_tmp();
3673 rm = new_tmp();
3674 tmp = new_tmp();
3675
3676 tcg_gen_andi_i32(rd, t0, 0xff);
3677 tcg_gen_shli_i32(tmp, t1, 8);
3678 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3679 tcg_gen_or_i32(rd, rd, tmp);
3680 tcg_gen_shli_i32(tmp, t0, 16);
3681 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3682 tcg_gen_or_i32(rd, rd, tmp);
3683 tcg_gen_shli_i32(tmp, t1, 24);
3684 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3685 tcg_gen_or_i32(rd, rd, tmp);
3686
3687 tcg_gen_andi_i32(rm, t1, 0xff000000);
3688 tcg_gen_shri_i32(tmp, t0, 8);
3689 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3690 tcg_gen_or_i32(rm, rm, tmp);
3691 tcg_gen_shri_i32(tmp, t1, 8);
3692 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3693 tcg_gen_or_i32(rm, rm, tmp);
3694 tcg_gen_shri_i32(tmp, t0, 16);
3695 tcg_gen_andi_i32(tmp, tmp, 0xff);
3696 tcg_gen_or_i32(t1, rm, tmp);
3697 tcg_gen_mov_i32(t0, rd);
3698
3699 dead_tmp(tmp);
3700 dead_tmp(rm);
3701 dead_tmp(rd);
3702 }
3703
3704 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3705 {
3706 TCGv tmp, tmp2;
3707
3708 tmp = new_tmp();
3709 tmp2 = new_tmp();
3710
3711 tcg_gen_andi_i32(tmp, t0, 0xffff);
3712 tcg_gen_shli_i32(tmp2, t1, 16);
3713 tcg_gen_or_i32(tmp, tmp, tmp2);
3714 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3715 tcg_gen_shri_i32(tmp2, t0, 16);
3716 tcg_gen_or_i32(t1, t1, tmp2);
3717 tcg_gen_mov_i32(t0, tmp);
3718
3719 dead_tmp(tmp2);
3720 dead_tmp(tmp);
3721 }
3722
3723 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3724 {
3725 int n;
3726
3727 for (n = 0; n < q + 1; n += 2) {
3728 NEON_GET_REG(T0, reg, n);
3729 NEON_GET_REG(T1, reg, n + 1);
3730 switch (size) {
3731 case 0: gen_neon_unzip_u8(cpu_T[0], cpu_T[1]); break;
3732 case 1: gen_neon_zip_u16(cpu_T[0], cpu_T[1]); break; /* zip and unzip are the same. */
3733 case 2: /* no-op */; break;
3734 default: abort();
3735 }
3736 gen_neon_movl_T0_scratch(tmp + n);
3737 gen_neon_movl_T1_scratch(tmp + n + 1);
3738 }
3739 }
3740
3741 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3742 {
3743 TCGv rd, tmp;
3744
3745 rd = new_tmp();
3746 tmp = new_tmp();
3747
3748 tcg_gen_shli_i32(rd, t0, 8);
3749 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3750 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3751 tcg_gen_or_i32(rd, rd, tmp);
3752
3753 tcg_gen_shri_i32(t1, t1, 8);
3754 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3755 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3756 tcg_gen_or_i32(t1, t1, tmp);
3757 tcg_gen_mov_i32(t0, rd);
3758
3759 dead_tmp(tmp);
3760 dead_tmp(rd);
3761 }
3762
3763 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3764 {
3765 TCGv rd, tmp;
3766
3767 rd = new_tmp();
3768 tmp = new_tmp();
3769
3770 tcg_gen_shli_i32(rd, t0, 16);
3771 tcg_gen_andi_i32(tmp, t1, 0xffff);
3772 tcg_gen_or_i32(rd, rd, tmp);
3773 tcg_gen_shri_i32(t1, t1, 16);
3774 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3775 tcg_gen_or_i32(t1, t1, tmp);
3776 tcg_gen_mov_i32(t0, rd);
3777
3778 dead_tmp(tmp);
3779 dead_tmp(rd);
3780 }
3781
3782
3783 static struct {
3784 int nregs;
3785 int interleave;
3786 int spacing;
3787 } neon_ls_element_type[11] = {
3788 {4, 4, 1},
3789 {4, 4, 2},
3790 {4, 1, 1},
3791 {4, 2, 1},
3792 {3, 3, 1},
3793 {3, 3, 2},
3794 {3, 1, 1},
3795 {1, 1, 1},
3796 {2, 2, 1},
3797 {2, 2, 2},
3798 {2, 1, 1}
3799 };
3800
3801 /* Translate a NEON load/store element instruction. Return nonzero if the
3802 instruction is invalid. */
3803 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3804 {
3805 int rd, rn, rm;
3806 int op;
3807 int nregs;
3808 int interleave;
3809 int stride;
3810 int size;
3811 int reg;
3812 int pass;
3813 int load;
3814 int shift;
3815 int n;
3816 TCGv tmp;
3817 TCGv tmp2;
3818
3819 if (!vfp_enabled(env))
3820 return 1;
3821 VFP_DREG_D(rd, insn);
3822 rn = (insn >> 16) & 0xf;
3823 rm = insn & 0xf;
3824 load = (insn & (1 << 21)) != 0;
3825 if ((insn & (1 << 23)) == 0) {
3826 /* Load store all elements. */
3827 op = (insn >> 8) & 0xf;
3828 size = (insn >> 6) & 3;
3829 if (op > 10 || size == 3)
3830 return 1;
3831 nregs = neon_ls_element_type[op].nregs;
3832 interleave = neon_ls_element_type[op].interleave;
3833 gen_movl_T1_reg(s, rn);
3834 stride = (1 << size) * interleave;
3835 for (reg = 0; reg < nregs; reg++) {
3836 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3837 gen_movl_T1_reg(s, rn);
3838 gen_op_addl_T1_im((1 << size) * reg);
3839 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3840 gen_movl_T1_reg(s, rn);
3841 gen_op_addl_T1_im(1 << size);
3842 }
3843 for (pass = 0; pass < 2; pass++) {
3844 if (size == 2) {
3845 if (load) {
3846 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3847 neon_store_reg(rd, pass, tmp);
3848 } else {
3849 tmp = neon_load_reg(rd, pass);
3850 gen_st32(tmp, cpu_T[1], IS_USER(s));
3851 }
3852 gen_op_addl_T1_im(stride);
3853 } else if (size == 1) {
3854 if (load) {
3855 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3856 gen_op_addl_T1_im(stride);
3857 tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3858 gen_op_addl_T1_im(stride);
3859 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3860 dead_tmp(tmp2);
3861 neon_store_reg(rd, pass, tmp);
3862 } else {
3863 tmp = neon_load_reg(rd, pass);
3864 tmp2 = new_tmp();
3865 tcg_gen_shri_i32(tmp2, tmp, 16);
3866 gen_st16(tmp, cpu_T[1], IS_USER(s));
3867 gen_op_addl_T1_im(stride);
3868 gen_st16(tmp2, cpu_T[1], IS_USER(s));
3869 gen_op_addl_T1_im(stride);
3870 }
3871 } else /* size == 0 */ {
3872 if (load) {
3873 TCGV_UNUSED(tmp2);
3874 for (n = 0; n < 4; n++) {
3875 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3876 gen_op_addl_T1_im(stride);
3877 if (n == 0) {
3878 tmp2 = tmp;
3879 } else {
3880 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3881 dead_tmp(tmp);
3882 }
3883 }
3884 neon_store_reg(rd, pass, tmp2);
3885 } else {
3886 tmp2 = neon_load_reg(rd, pass);
3887 for (n = 0; n < 4; n++) {
3888 tmp = new_tmp();
3889 if (n == 0) {
3890 tcg_gen_mov_i32(tmp, tmp2);
3891 } else {
3892 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3893 }
3894 gen_st8(tmp, cpu_T[1], IS_USER(s));
3895 gen_op_addl_T1_im(stride);
3896 }
3897 dead_tmp(tmp2);
3898 }
3899 }
3900 }
3901 rd += neon_ls_element_type[op].spacing;
3902 }
3903 stride = nregs * 8;
3904 } else {
3905 size = (insn >> 10) & 3;
3906 if (size == 3) {
3907 /* Load single element to all lanes. */
3908 if (!load)
3909 return 1;
3910 size = (insn >> 6) & 3;
3911 nregs = ((insn >> 8) & 3) + 1;
3912 stride = (insn & (1 << 5)) ? 2 : 1;
3913 gen_movl_T1_reg(s, rn);
3914 for (reg = 0; reg < nregs; reg++) {
3915 switch (size) {
3916 case 0:
3917 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3918 gen_neon_dup_u8(tmp, 0);
3919 break;
3920 case 1:
3921 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3922 gen_neon_dup_low16(tmp);
3923 break;
3924 case 2:
3925 tmp = gen_ld32(cpu_T[0], IS_USER(s));
3926 break;
3927 case 3:
3928 return 1;
3929 default: /* Avoid compiler warnings. */
3930 abort();
3931 }
3932 gen_op_addl_T1_im(1 << size);
3933 tmp2 = new_tmp();
3934 tcg_gen_mov_i32(tmp2, tmp);
3935 neon_store_reg(rd, 0, tmp2);
3936 neon_store_reg(rd, 1, tmp);
3937 rd += stride;
3938 }
3939 stride = (1 << size) * nregs;
3940 } else {
3941 /* Single element. */
3942 pass = (insn >> 7) & 1;
3943 switch (size) {
3944 case 0:
3945 shift = ((insn >> 5) & 3) * 8;
3946 stride = 1;
3947 break;
3948 case 1:
3949 shift = ((insn >> 6) & 1) * 16;
3950 stride = (insn & (1 << 5)) ? 2 : 1;
3951 break;
3952 case 2:
3953 shift = 0;
3954 stride = (insn & (1 << 6)) ? 2 : 1;
3955 break;
3956 default:
3957 abort();
3958 }
3959 nregs = ((insn >> 8) & 3) + 1;
3960 gen_movl_T1_reg(s, rn);
3961 for (reg = 0; reg < nregs; reg++) {
3962 if (load) {
3963 switch (size) {
3964 case 0:
3965 tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3966 break;
3967 case 1:
3968 tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3969 break;
3970 case 2:
3971 tmp = gen_ld32(cpu_T[1], IS_USER(s));
3972 break;
3973 default: /* Avoid compiler warnings. */
3974 abort();
3975 }
3976 if (size != 2) {
3977 tmp2 = neon_load_reg(rd, pass);
3978 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3979 dead_tmp(tmp2);
3980 }
3981 neon_store_reg(rd, pass, tmp);
3982 } else { /* Store */
3983 tmp = neon_load_reg(rd, pass);
3984 if (shift)
3985 tcg_gen_shri_i32(tmp, tmp, shift);
3986 switch (size) {
3987 case 0:
3988 gen_st8(tmp, cpu_T[1], IS_USER(s));
3989 break;
3990 case 1:
3991 gen_st16(tmp, cpu_T[1], IS_USER(s));
3992 break;
3993 case 2:
3994 gen_st32(tmp, cpu_T[1], IS_USER(s));
3995 break;
3996 }
3997 }
3998 rd += stride;
3999 gen_op_addl_T1_im(1 << size);
4000 }
4001 stride = nregs * (1 << size);
4002 }
4003 }
4004 if (rm != 15) {
4005 TCGv base;
4006
4007 base = load_reg(s, rn);
4008 if (rm == 13) {
4009 tcg_gen_addi_i32(base, base, stride);
4010 } else {
4011 TCGv index;
4012 index = load_reg(s, rm);
4013 tcg_gen_add_i32(base, base, index);
4014 dead_tmp(index);
4015 }
4016 store_reg(s, rn, base);
4017 }
4018 return 0;
4019 }
4020
4021 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4022 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4023 {
4024 tcg_gen_and_i32(t, t, c);
4025 tcg_gen_bic_i32(f, f, c);
4026 tcg_gen_or_i32(dest, t, f);
4027 }
4028
4029 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4030 {
4031 switch (size) {
4032 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4033 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4034 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4035 default: abort();
4036 }
4037 }
4038
4039 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4040 {
4041 switch (size) {
4042 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4043 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4044 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4045 default: abort();
4046 }
4047 }
4048
4049 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4050 {
4051 switch (size) {
4052 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4053 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4054 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4055 default: abort();
4056 }
4057 }
4058
4059 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4060 int q, int u)
4061 {
4062 if (q) {
4063 if (u) {
4064 switch (size) {
4065 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4066 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4067 default: abort();
4068 }
4069 } else {
4070 switch (size) {
4071 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4072 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4073 default: abort();
4074 }
4075 }
4076 } else {
4077 if (u) {
4078 switch (size) {
4079 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4080 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4081 default: abort();
4082 }
4083 } else {
4084 switch (size) {
4085 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4086 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4087 default: abort();
4088 }
4089 }
4090 }
4091 }
4092
4093 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4094 {
4095 if (u) {
4096 switch (size) {
4097 case 0: gen_helper_neon_widen_u8(dest, src); break;
4098 case 1: gen_helper_neon_widen_u16(dest, src); break;
4099 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4100 default: abort();
4101 }
4102 } else {
4103 switch (size) {
4104 case 0: gen_helper_neon_widen_s8(dest, src); break;
4105 case 1: gen_helper_neon_widen_s16(dest, src); break;
4106 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4107 default: abort();
4108 }
4109 }
4110 dead_tmp(src);
4111 }
4112
4113 static inline void gen_neon_addl(int size)
4114 {
4115 switch (size) {
4116 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4117 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4118 case 2: tcg_gen_add_i64(CPU_V001); break;
4119 default: abort();
4120 }
4121 }
4122
4123 static inline void gen_neon_subl(int size)
4124 {
4125 switch (size) {
4126 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4127 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4128 case 2: tcg_gen_sub_i64(CPU_V001); break;
4129 default: abort();
4130 }
4131 }
4132
4133 static inline void gen_neon_negl(TCGv_i64 var, int size)
4134 {
4135 switch (size) {
4136 case 0: gen_helper_neon_negl_u16(var, var); break;
4137 case 1: gen_helper_neon_negl_u32(var, var); break;
4138 case 2: gen_helper_neon_negl_u64(var, var); break;
4139 default: abort();
4140 }
4141 }
4142
4143 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4144 {
4145 switch (size) {
4146 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4147 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4148 default: abort();
4149 }
4150 }
4151
4152 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4153 {
4154 TCGv_i64 tmp;
4155
4156 switch ((size << 1) | u) {
4157 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4158 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4159 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4160 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4161 case 4:
4162 tmp = gen_muls_i64_i32(a, b);
4163 tcg_gen_mov_i64(dest, tmp);
4164 break;
4165 case 5:
4166 tmp = gen_mulu_i64_i32(a, b);
4167 tcg_gen_mov_i64(dest, tmp);
4168 break;
4169 default: abort();
4170 }
4171 if (size < 2) {
4172 dead_tmp(b);
4173 dead_tmp(a);
4174 }
4175 }
4176
4177 /* Translate a NEON data processing instruction. Return nonzero if the
4178 instruction is invalid.
4179 We process data in a mixture of 32-bit and 64-bit chunks.
4180 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4181
4182 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4183 {
4184 int op;
4185 int q;
4186 int rd, rn, rm;
4187 int size;
4188 int shift;
4189 int pass;
4190 int count;
4191 int pairwise;
4192 int u;
4193 int n;
4194 uint32_t imm;
4195 TCGv tmp;
4196 TCGv tmp2;
4197 TCGv tmp3;
4198 TCGv_i64 tmp64;
4199
4200 if (!vfp_enabled(env))
4201 return 1;
4202 q = (insn & (1 << 6)) != 0;
4203 u = (insn >> 24) & 1;
4204 VFP_DREG_D(rd, insn);
4205 VFP_DREG_N(rn, insn);
4206 VFP_DREG_M(rm, insn);
4207 size = (insn >> 20) & 3;
4208 if ((insn & (1 << 23)) == 0) {
4209 /* Three register same length. */
4210 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4211 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4212 || op == 10 || op == 11 || op == 16)) {
4213 /* 64-bit element instructions. */
4214 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4215 neon_load_reg64(cpu_V0, rn + pass);
4216 neon_load_reg64(cpu_V1, rm + pass);
4217 switch (op) {
4218 case 1: /* VQADD */
4219 if (u) {
4220 gen_helper_neon_add_saturate_u64(CPU_V001);
4221 } else {
4222 gen_helper_neon_add_saturate_s64(CPU_V001);
4223 }
4224 break;
4225 case 5: /* VQSUB */
4226 if (u) {
4227 gen_helper_neon_sub_saturate_u64(CPU_V001);
4228 } else {
4229 gen_helper_neon_sub_saturate_s64(CPU_V001);
4230 }
4231 break;
4232 case 8: /* VSHL */
4233 if (u) {
4234 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4235 } else {
4236 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4237 }
4238 break;
4239 case 9: /* VQSHL */
4240 if (u) {
4241 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4242 cpu_V0, cpu_V0);
4243 } else {
4244 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4245 cpu_V1, cpu_V0);
4246 }
4247 break;
4248 case 10: /* VRSHL */
4249 if (u) {
4250 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4251 } else {
4252 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4253 }
4254 break;
4255 case 11: /* VQRSHL */
4256 if (u) {
4257 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4258 cpu_V1, cpu_V0);
4259 } else {
4260 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4261 cpu_V1, cpu_V0);
4262 }
4263 break;
4264 case 16:
4265 if (u) {
4266 tcg_gen_sub_i64(CPU_V001);
4267 } else {
4268 tcg_gen_add_i64(CPU_V001);
4269 }
4270 break;
4271 default:
4272 abort();
4273 }
4274 neon_store_reg64(cpu_V0, rd + pass);
4275 }
4276 return 0;
4277 }
4278 switch (op) {
4279 case 8: /* VSHL */
4280 case 9: /* VQSHL */
4281 case 10: /* VRSHL */
4282 case 11: /* VQRSHL */
4283 {
4284 int rtmp;
4285 /* Shift instruction operands are reversed. */
4286 rtmp = rn;
4287 rn = rm;
4288 rm = rtmp;
4289 pairwise = 0;
4290 }
4291 break;
4292 case 20: /* VPMAX */
4293 case 21: /* VPMIN */
4294 case 23: /* VPADD */
4295 pairwise = 1;
4296 break;
4297 case 26: /* VPADD (float) */
4298 pairwise = (u && size < 2);
4299 break;
4300 case 30: /* VPMIN/VPMAX (float) */
4301 pairwise = u;
4302 break;
4303 default:
4304 pairwise = 0;
4305 break;
4306 }
4307 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4308
4309 if (pairwise) {
4310 /* Pairwise. */
4311 if (q)
4312 n = (pass & 1) * 2;
4313 else
4314 n = 0;
4315 if (pass < q + 1) {
4316 NEON_GET_REG(T0, rn, n);
4317 NEON_GET_REG(T1, rn, n + 1);
4318 } else {
4319 NEON_GET_REG(T0, rm, n);
4320 NEON_GET_REG(T1, rm, n + 1);
4321 }
4322 } else {
4323 /* Elementwise. */
4324 NEON_GET_REG(T0, rn, pass);
4325 NEON_GET_REG(T1, rm, pass);
4326 }
4327 switch (op) {
4328 case 0: /* VHADD */
4329 GEN_NEON_INTEGER_OP(hadd);
4330 break;
4331 case 1: /* VQADD */
4332 GEN_NEON_INTEGER_OP_ENV(qadd);
4333 break;
4334 case 2: /* VRHADD */
4335 GEN_NEON_INTEGER_OP(rhadd);
4336 break;
4337 case 3: /* Logic ops. */
4338 switch ((u << 2) | size) {
4339 case 0: /* VAND */
4340 gen_op_andl_T0_T1();
4341 break;
4342 case 1: /* BIC */
4343 gen_op_bicl_T0_T1();
4344 break;
4345 case 2: /* VORR */
4346 gen_op_orl_T0_T1();
4347 break;
4348 case 3: /* VORN */
4349 gen_op_notl_T1();
4350 gen_op_orl_T0_T1();
4351 break;
4352 case 4: /* VEOR */
4353 gen_op_xorl_T0_T1();
4354 break;
4355 case 5: /* VBSL */
4356 tmp = neon_load_reg(rd, pass);
4357 gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4358 dead_tmp(tmp);
4359 break;
4360 case 6: /* VBIT */
4361 tmp = neon_load_reg(rd, pass);
4362 gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4363 dead_tmp(tmp);
4364 break;
4365 case 7: /* VBIF */
4366 tmp = neon_load_reg(rd, pass);
4367 gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4368 dead_tmp(tmp);
4369 break;
4370 }
4371 break;
4372 case 4: /* VHSUB */
4373 GEN_NEON_INTEGER_OP(hsub);
4374 break;
4375 case 5: /* VQSUB */
4376 GEN_NEON_INTEGER_OP_ENV(qsub);
4377 break;
4378 case 6: /* VCGT */
4379 GEN_NEON_INTEGER_OP(cgt);
4380 break;
4381 case 7: /* VCGE */
4382 GEN_NEON_INTEGER_OP(cge);
4383 break;
4384 case 8: /* VSHL */
4385 GEN_NEON_INTEGER_OP(shl);
4386 break;
4387 case 9: /* VQSHL */
4388 GEN_NEON_INTEGER_OP_ENV(qshl);
4389 break;
4390 case 10: /* VRSHL */
4391 GEN_NEON_INTEGER_OP(rshl);
4392 break;
4393 case 11: /* VQRSHL */
4394 GEN_NEON_INTEGER_OP_ENV(qrshl);
4395 break;
4396 case 12: /* VMAX */
4397 GEN_NEON_INTEGER_OP(max);
4398 break;
4399 case 13: /* VMIN */
4400 GEN_NEON_INTEGER_OP(min);
4401 break;
4402 case 14: /* VABD */
4403 GEN_NEON_INTEGER_OP(abd);
4404 break;
4405 case 15: /* VABA */
4406 GEN_NEON_INTEGER_OP(abd);
4407 NEON_GET_REG(T1, rd, pass);
4408 gen_neon_add(size);
4409 break;
4410 case 16:
4411 if (!u) { /* VADD */
4412 if (gen_neon_add(size))
4413 return 1;
4414 } else { /* VSUB */
4415 switch (size) {
4416 case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4417 case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4418 case 2: gen_op_subl_T0_T1(); break;
4419 default: return 1;
4420 }
4421 }
4422 break;
4423 case 17:
4424 if (!u) { /* VTST */
4425 switch (size) {
4426 case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4427 case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4428 case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4429 default: return 1;
4430 }
4431 } else { /* VCEQ */
4432 switch (size) {
4433 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4434 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4435 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4436 default: return 1;
4437 }
4438 }
4439 break;
4440 case 18: /* Multiply. */
4441 switch (size) {
4442 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4443 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4444 case 2: gen_op_mul_T0_T1(); break;
4445 default: return 1;
4446 }
4447 NEON_GET_REG(T1, rd, pass);
4448 if (u) { /* VMLS */
4449 gen_neon_rsb(size);
4450 } else { /* VMLA */
4451 gen_neon_add(size);
4452 }
4453 break;
4454 case 19: /* VMUL */
4455 if (u) { /* polynomial */
4456 gen_helper_neon_mul_p8(CPU_T001);
4457 } else { /* Integer */
4458 switch (size) {
4459 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4460 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4461 case 2: gen_op_mul_T0_T1(); break;
4462 default: return 1;
4463 }
4464 }
4465 break;
4466 case 20: /* VPMAX */
4467 GEN_NEON_INTEGER_OP(pmax);
4468 break;
4469 case 21: /* VPMIN */
4470 GEN_NEON_INTEGER_OP(pmin);
4471 break;
4472 case 22: /* Hultiply high. */
4473 if (!u) { /* VQDMULH */
4474 switch (size) {
4475 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4476 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4477 default: return 1;
4478 }
4479 } else { /* VQRDHMUL */
4480 switch (size) {
4481 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4482 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4483 default: return 1;
4484 }
4485 }
4486 break;
4487 case 23: /* VPADD */
4488 if (u)
4489 return 1;
4490 switch (size) {
4491 case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4492 case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4493 case 2: gen_op_addl_T0_T1(); break;
4494 default: return 1;
4495 }
4496 break;
4497 case 26: /* Floating point arithnetic. */
4498 switch ((u << 2) | size) {
4499 case 0: /* VADD */
4500 gen_helper_neon_add_f32(CPU_T001);
4501 break;
4502 case 2: /* VSUB */
4503 gen_helper_neon_sub_f32(CPU_T001);
4504 break;
4505 case 4: /* VPADD */
4506 gen_helper_neon_add_f32(CPU_T001);
4507 break;
4508 case 6: /* VABD */
4509 gen_helper_neon_abd_f32(CPU_T001);
4510 break;
4511 default:
4512 return 1;
4513 }
4514 break;
4515 case 27: /* Float multiply. */
4516 gen_helper_neon_mul_f32(CPU_T001);
4517 if (!u) {
4518 NEON_GET_REG(T1, rd, pass);
4519 if (size == 0) {
4520 gen_helper_neon_add_f32(CPU_T001);
4521 } else {
4522 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4523 }
4524 }
4525 break;
4526 case 28: /* Float compare. */
4527 if (!u) {
4528 gen_helper_neon_ceq_f32(CPU_T001);
4529 } else {
4530 if (size == 0)
4531 gen_helper_neon_cge_f32(CPU_T001);
4532 else
4533 gen_helper_neon_cgt_f32(CPU_T001);
4534 }
4535 break;
4536 case 29: /* Float compare absolute. */
4537 if (!u)
4538 return 1;
4539 if (size == 0)
4540 gen_helper_neon_acge_f32(CPU_T001);
4541 else
4542 gen_helper_neon_acgt_f32(CPU_T001);
4543 break;
4544 case 30: /* Float min/max. */
4545 if (size == 0)
4546 gen_helper_neon_max_f32(CPU_T001);
4547 else
4548 gen_helper_neon_min_f32(CPU_T001);
4549 break;
4550 case 31:
4551 if (size == 0)
4552 gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4553 else
4554 gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4555 break;
4556 default:
4557 abort();
4558 }
4559 /* Save the result. For elementwise operations we can put it
4560 straight into the destination register. For pairwise operations
4561 we have to be careful to avoid clobbering the source operands. */
4562 if (pairwise && rd == rm) {
4563 gen_neon_movl_scratch_T0(pass);
4564 } else {
4565 NEON_SET_REG(T0, rd, pass);
4566 }
4567
4568 } /* for pass */
4569 if (pairwise && rd == rm) {
4570 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4571 gen_neon_movl_T0_scratch(pass);
4572 NEON_SET_REG(T0, rd, pass);
4573 }
4574 }
4575 /* End of 3 register same size operations. */
4576 } else if (insn & (1 << 4)) {
4577 if ((insn & 0x00380080) != 0) {
4578 /* Two registers and shift. */
4579 op = (insn >> 8) & 0xf;
4580 if (insn & (1 << 7)) {
4581 /* 64-bit shift. */
4582 size = 3;
4583 } else {
4584 size = 2;
4585 while ((insn & (1 << (size + 19))) == 0)
4586 size--;
4587 }
4588 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4589 /* To avoid excessive dumplication of ops we implement shift
4590 by immediate using the variable shift operations. */
4591 if (op < 8) {
4592 /* Shift by immediate:
4593 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4594 /* Right shifts are encoded as N - shift, where N is the
4595 element size in bits. */
4596 if (op <= 4)
4597 shift = shift - (1 << (size + 3));
4598 if (size == 3) {
4599 count = q + 1;
4600 } else {
4601 count = q ? 4: 2;
4602 }
4603 switch (size) {
4604 case 0:
4605 imm = (uint8_t) shift;
4606 imm |= imm << 8;
4607 imm |= imm << 16;
4608 break;
4609 case 1:
4610 imm = (uint16_t) shift;
4611 imm |= imm << 16;
4612 break;
4613 case 2:
4614 case 3:
4615 imm = shift;
4616 break;
4617 default:
4618 abort();
4619 }
4620
4621 for (pass = 0; pass < count; pass++) {
4622 if (size == 3) {
4623 neon_load_reg64(cpu_V0, rm + pass);
4624 tcg_gen_movi_i64(cpu_V1, imm);
4625 switch (op) {
4626 case 0: /* VSHR */
4627 case 1: /* VSRA */
4628 if (u)
4629 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4630 else
4631 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4632 break;
4633 case 2: /* VRSHR */
4634 case 3: /* VRSRA */
4635 if (u)
4636 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4637 else
4638 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4639 break;
4640 case 4: /* VSRI */
4641 if (!u)
4642 return 1;
4643 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4644 break;
4645 case 5: /* VSHL, VSLI */
4646 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4647 break;
4648 case 6: /* VQSHL */
4649 if (u)
4650 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4651 else
4652 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4653 break;
4654 case 7: /* VQSHLU */
4655 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4656 break;
4657 }
4658 if (op == 1 || op == 3) {
4659 /* Accumulate. */
4660 neon_load_reg64(cpu_V0, rd + pass);
4661 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4662 } else if (op == 4 || (op == 5 && u)) {
4663 /* Insert */
4664 cpu_abort(env, "VS[LR]I.64 not implemented");
4665 }
4666 neon_store_reg64(cpu_V0, rd + pass);
4667 } else { /* size < 3 */
4668 /* Operands in T0 and T1. */
4669 gen_op_movl_T1_im(imm);
4670 NEON_GET_REG(T0, rm, pass);
4671 switch (op) {
4672 case 0: /* VSHR */
4673 case 1: /* VSRA */
4674 GEN_NEON_INTEGER_OP(shl);
4675 break;
4676 case 2: /* VRSHR */
4677 case 3: /* VRSRA */
4678 GEN_NEON_INTEGER_OP(rshl);
4679 break;
4680 case 4: /* VSRI */
4681 if (!u)
4682 return 1;
4683 GEN_NEON_INTEGER_OP(shl);
4684 break;
4685 case 5: /* VSHL, VSLI */
4686 switch (size) {
4687 case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4688 case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4689 case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4690 default: return 1;
4691 }
4692 break;
4693 case 6: /* VQSHL */
4694 GEN_NEON_INTEGER_OP_ENV(qshl);
4695 break;
4696 case 7: /* VQSHLU */
4697 switch (size) {
4698 case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4699 case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4700 case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4701 default: return 1;
4702 }
4703 break;
4704 }
4705
4706 if (op == 1 || op == 3) {
4707 /* Accumulate. */
4708 NEON_GET_REG(T1, rd, pass);
4709 gen_neon_add(size);
4710 } else if (op == 4 || (op == 5 && u)) {
4711 /* Insert */
4712 switch (size) {
4713 case 0:
4714 if (op == 4)
4715 imm = 0xff >> -shift;
4716 else
4717 imm = (uint8_t)(0xff << shift);
4718 imm |= imm << 8;
4719 imm |= imm << 16;
4720 break;
4721 case 1:
4722 if (op == 4)
4723 imm = 0xffff >> -shift;
4724 else
4725 imm = (uint16_t)(0xffff << shift);
4726 imm |= imm << 16;
4727 break;
4728 case 2:
4729 if (op == 4)
4730 imm = 0xffffffffu >> -shift;
4731 else
4732 imm = 0xffffffffu << shift;
4733 break;
4734 default:
4735 abort();
4736 }
4737 tmp = neon_load_reg(rd, pass);
4738 tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4739 tcg_gen_andi_i32(tmp, tmp, ~imm);
4740 tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4741 }
4742 NEON_SET_REG(T0, rd, pass);
4743 }
4744 } /* for pass */
4745 } else if (op < 10) {
4746 /* Shift by immediate and narrow:
4747 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4748 shift = shift - (1 << (size + 3));
4749 size++;
4750 switch (size) {
4751 case 1:
4752 imm = (uint16_t)shift;
4753 imm |= imm << 16;
4754 tmp2 = tcg_const_i32(imm);
4755 TCGV_UNUSED_I64(tmp64);
4756 break;
4757 case 2:
4758 imm = (uint32_t)shift;
4759 tmp2 = tcg_const_i32(imm);
4760 TCGV_UNUSED_I64(tmp64);
4761 break;
4762 case 3:
4763 tmp64 = tcg_const_i64(shift);
4764 TCGV_UNUSED(tmp2);
4765 break;
4766 default:
4767 abort();
4768 }
4769
4770 for (pass = 0; pass < 2; pass++) {
4771 if (size == 3) {
4772 neon_load_reg64(cpu_V0, rm + pass);
4773 if (q) {
4774 if (u)
4775 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4776 else
4777 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4778 } else {
4779 if (u)
4780 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4781 else
4782 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4783 }
4784 } else {
4785 tmp = neon_load_reg(rm + pass, 0);
4786 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4787 tmp3 = neon_load_reg(rm + pass, 1);
4788 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4789 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4790 dead_tmp(tmp);
4791 dead_tmp(tmp3);
4792 }
4793 tmp = new_tmp();
4794 if (op == 8 && !u) {
4795 gen_neon_narrow(size - 1, tmp, cpu_V0);
4796 } else {
4797 if (op == 8)
4798 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4799 else
4800 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4801 }
4802 if (pass == 0) {
4803 tmp2 = tmp;
4804 } else {
4805 neon_store_reg(rd, 0, tmp2);
4806 neon_store_reg(rd, 1, tmp);
4807 }
4808 } /* for pass */
4809 } else if (op == 10) {
4810 /* VSHLL */
4811 if (q || size == 3)
4812 return 1;
4813 tmp = neon_load_reg(rm, 0);
4814 tmp2 = neon_load_reg(rm, 1);
4815 for (pass = 0; pass < 2; pass++) {
4816 if (pass == 1)
4817 tmp = tmp2;
4818
4819 gen_neon_widen(cpu_V0, tmp, size, u);
4820
4821 if (shift != 0) {
4822 /* The shift is less than the width of the source
4823 type, so we can just shift the whole register. */
4824 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4825 if (size < 2 || !u) {
4826 uint64_t imm64;
4827 if (size == 0) {
4828 imm = (0xffu >> (8 - shift));
4829 imm |= imm << 16;
4830 } else {
4831 imm = 0xffff >> (16 - shift);
4832 }
4833 imm64 = imm | (((uint64_t)imm) << 32);
4834 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4835 }
4836 }
4837 neon_store_reg64(cpu_V0, rd + pass);
4838 }
4839 } else if (op == 15 || op == 16) {
4840 /* VCVT fixed-point. */
4841 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4842 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4843 if (op & 1) {
4844 if (u)
4845 gen_vfp_ulto(0, shift);
4846 else
4847 gen_vfp_slto(0, shift);
4848 } else {
4849 if (u)
4850 gen_vfp_toul(0, shift);
4851 else
4852 gen_vfp_tosl(0, shift);
4853 }
4854 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4855 }
4856 } else {
4857 return 1;
4858 }
4859 } else { /* (insn & 0x00380080) == 0 */
4860 int invert;
4861
4862 op = (insn >> 8) & 0xf;
4863 /* One register and immediate. */
4864 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4865 invert = (insn & (1 << 5)) != 0;
4866 switch (op) {
4867 case 0: case 1:
4868 /* no-op */
4869 break;
4870 case 2: case 3:
4871 imm <<= 8;
4872 break;
4873 case 4: case 5:
4874 imm <<= 16;
4875 break;
4876 case 6: case 7:
4877 imm <<= 24;
4878 break;
4879 case 8: case 9:
4880 imm |= imm << 16;
4881 break;
4882 case 10: case 11:
4883 imm = (imm << 8) | (imm << 24);
4884 break;
4885 case 12:
4886 imm = (imm < 8) | 0xff;
4887 break;
4888 case 13:
4889 imm = (imm << 16) | 0xffff;
4890 break;
4891 case 14:
4892 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4893 if (invert)
4894 imm = ~imm;
4895 break;
4896 case 15:
4897 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4898 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4899 break;
4900 }
4901 if (invert)
4902 imm = ~imm;
4903
4904 if (op != 14 || !invert)
4905 gen_op_movl_T1_im(imm);
4906
4907 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4908 if (op & 1 && op < 12) {
4909 tmp = neon_load_reg(rd, pass);
4910 if (invert) {
4911 /* The immediate value has already been inverted, so
4912 BIC becomes AND. */
4913 tcg_gen_andi_i32(tmp, tmp, imm);
4914 } else {
4915 tcg_gen_ori_i32(tmp, tmp, imm);
4916 }
4917 } else {
4918 /* VMOV, VMVN. */
4919 tmp = new_tmp();
4920 if (op == 14 && invert) {
4921 uint32_t val;
4922 val = 0;
4923 for (n = 0; n < 4; n++) {
4924 if (imm & (1 << (n + (pass & 1) * 4)))
4925 val |= 0xff << (n * 8);
4926 }
4927 tcg_gen_movi_i32(tmp, val);
4928 } else {
4929 tcg_gen_movi_i32(tmp, imm);
4930 }
4931 }
4932 neon_store_reg(rd, pass, tmp);
4933 }
4934 }
4935 } else { /* (insn & 0x00800010 == 0x00800000) */
4936 if (size != 3) {
4937 op = (insn >> 8) & 0xf;
4938 if ((insn & (1 << 6)) == 0) {
4939 /* Three registers of different lengths. */
4940 int src1_wide;
4941 int src2_wide;
4942 int prewiden;
4943 /* prewiden, src1_wide, src2_wide */
4944 static const int neon_3reg_wide[16][3] = {
4945 {1, 0, 0}, /* VADDL */
4946 {1, 1, 0}, /* VADDW */
4947 {1, 0, 0}, /* VSUBL */
4948 {1, 1, 0}, /* VSUBW */
4949 {0, 1, 1}, /* VADDHN */
4950 {0, 0, 0}, /* VABAL */
4951 {0, 1, 1}, /* VSUBHN */
4952 {0, 0, 0}, /* VABDL */
4953 {0, 0, 0}, /* VMLAL */
4954 {0, 0, 0}, /* VQDMLAL */
4955 {0, 0, 0}, /* VMLSL */
4956 {0, 0, 0}, /* VQDMLSL */
4957 {0, 0, 0}, /* Integer VMULL */
4958 {0, 0, 0}, /* VQDMULL */
4959 {0, 0, 0} /* Polynomial VMULL */
4960 };
4961
4962 prewiden = neon_3reg_wide[op][0];
4963 src1_wide = neon_3reg_wide[op][1];
4964 src2_wide = neon_3reg_wide[op][2];
4965
4966 if (size == 0 && (op == 9 || op == 11 || op == 13))
4967 return 1;
4968
4969 /* Avoid overlapping operands. Wide source operands are
4970 always aligned so will never overlap with wide
4971 destinations in problematic ways. */
4972 if (rd == rm && !src2_wide) {
4973 NEON_GET_REG(T0, rm, 1);
4974 gen_neon_movl_scratch_T0(2);
4975 } else if (rd == rn && !src1_wide) {
4976 NEON_GET_REG(T0, rn, 1);
4977 gen_neon_movl_scratch_T0(2);
4978 }
4979 TCGV_UNUSED(tmp3);
4980 for (pass = 0; pass < 2; pass++) {
4981 if (src1_wide) {
4982 neon_load_reg64(cpu_V0, rn + pass);
4983 TCGV_UNUSED(tmp);
4984 } else {
4985 if (pass == 1 && rd == rn) {
4986 gen_neon_movl_T0_scratch(2);
4987 tmp = new_tmp();
4988 tcg_gen_mov_i32(tmp, cpu_T[0]);
4989 } else {
4990 tmp = neon_load_reg(rn, pass);
4991 }
4992 if (prewiden) {
4993 gen_neon_widen(cpu_V0, tmp, size, u);
4994 }
4995 }
4996 if (src2_wide) {
4997 neon_load_reg64(cpu_V1, rm + pass);
4998 TCGV_UNUSED(tmp2);
4999 } else {
5000 if (pass == 1 && rd == rm) {
5001 gen_neon_movl_T0_scratch(2);
5002 tmp2 = new_tmp();
5003 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5004 } else {
5005 tmp2 = neon_load_reg(rm, pass);
5006 }
5007 if (prewiden) {
5008 gen_neon_widen(cpu_V1, tmp2, size, u);
5009 }
5010 }
5011 switch (op) {
5012 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5013 gen_neon_addl(size);
5014 break;
5015 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
5016 gen_neon_subl(size);
5017 break;
5018 case 5: case 7: /* VABAL, VABDL */
5019 switch ((size << 1) | u) {
5020 case 0:
5021 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5022 break;
5023 case 1:
5024 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5025 break;
5026 case 2:
5027 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5028 break;
5029 case 3:
5030 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5031 break;
5032 case 4:
5033 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5034 break;
5035 case 5:
5036 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5037 break;
5038 default: abort();
5039 }
5040 dead_tmp(tmp2);
5041 dead_tmp(tmp);
5042 break;
5043 case 8: case 9: case 10: case 11: case 12: case 13:
5044 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5045 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5046 break;
5047 case 14: /* Polynomial VMULL */
5048 cpu_abort(env, "Polynomial VMULL not implemented");
5049
5050 default: /* 15 is RESERVED. */
5051 return 1;
5052 }
5053 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
5054 /* Accumulate. */
5055 if (op == 10 || op == 11) {
5056 gen_neon_negl(cpu_V0, size);
5057 }
5058
5059 if (op != 13) {
5060 neon_load_reg64(cpu_V1, rd + pass);
5061 }
5062
5063 switch (op) {
5064 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5065 gen_neon_addl(size);
5066 break;
5067 case 9: case 11: /* VQDMLAL, VQDMLSL */
5068 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5069 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5070 break;
5071 /* Fall through. */
5072 case 13: /* VQDMULL */
5073 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5074 break;
5075 default:
5076 abort();
5077 }
5078 neon_store_reg64(cpu_V0, rd + pass);
5079 } else if (op == 4 || op == 6) {
5080 /* Narrowing operation. */
5081 tmp = new_tmp();
5082 if (u) {
5083 switch (size) {
5084 case 0:
5085 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5086 break;
5087 case 1:
5088 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5089 break;
5090 case 2:
5091 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5092 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5093 break;
5094 default: abort();
5095 }
5096 } else {
5097 switch (size) {
5098 case 0:
5099 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5100 break;
5101 case 1:
5102 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5103 break;
5104 case 2:
5105 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5106 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5107 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5108 break;
5109 default: abort();
5110 }
5111 }
5112 if (pass == 0) {
5113 tmp3 = tmp;
5114 } else {
5115 neon_store_reg(rd, 0, tmp3);
5116 neon_store_reg(rd, 1, tmp);
5117 }
5118 } else {
5119 /* Write back the result. */
5120 neon_store_reg64(cpu_V0, rd + pass);
5121 }
5122 }
5123 } else {
5124 /* Two registers and a scalar. */
5125 switch (op) {
5126 case 0: /* Integer VMLA scalar */
5127 case 1: /* Float VMLA scalar */
5128 case 4: /* Integer VMLS scalar */
5129 case 5: /* Floating point VMLS scalar */
5130 case 8: /* Integer VMUL scalar */
5131 case 9: /* Floating point VMUL scalar */
5132 case 12: /* VQDMULH scalar */
5133 case 13: /* VQRDMULH scalar */
5134 gen_neon_get_scalar(size, rm);
5135 gen_neon_movl_scratch_T0(0);
5136 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5137 if (pass != 0)
5138 gen_neon_movl_T0_scratch(0);
5139 NEON_GET_REG(T1, rn, pass);
5140 if (op == 12) {
5141 if (size == 1) {
5142 gen_helper_neon_qdmulh_s16(CPU_T0E01);
5143 } else {
5144 gen_helper_neon_qdmulh_s32(CPU_T0E01);
5145 }
5146 } else if (op == 13) {
5147 if (size == 1) {
5148 gen_helper_neon_qrdmulh_s16(CPU_T0E01);
5149 } else {
5150 gen_helper_neon_qrdmulh_s32(CPU_T0E01);
5151 }
5152 } else if (op & 1) {
5153 gen_helper_neon_mul_f32(CPU_T001);
5154 } else {
5155 switch (size) {
5156 case 0: gen_helper_neon_mul_u8(CPU_T001); break;
5157 case 1: gen_helper_neon_mul_u16(CPU_T001); break;
5158 case 2: gen_op_mul_T0_T1(); break;
5159 default: return 1;
5160 }
5161 }
5162 if (op < 8) {
5163 /* Accumulate. */
5164 NEON_GET_REG(T1, rd, pass);
5165 switch (op) {
5166 case 0:
5167 gen_neon_add(size);
5168 break;
5169 case 1:
5170 gen_helper_neon_add_f32(CPU_T001);
5171 break;
5172 case 4:
5173 gen_neon_rsb(size);
5174 break;
5175 case 5:
5176 gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
5177 break;
5178 default:
5179 abort();
5180 }
5181 }
5182 NEON_SET_REG(T0, rd, pass);
5183 }
5184 break;
5185 case 2: /* VMLAL sclar */
5186 case 3: /* VQDMLAL scalar */
5187 case 6: /* VMLSL scalar */
5188 case 7: /* VQDMLSL scalar */
5189 case 10: /* VMULL scalar */
5190 case 11: /* VQDMULL scalar */
5191 if (size == 0 && (op == 3 || op == 7 || op == 11))
5192 return 1;
5193
5194 gen_neon_get_scalar(size, rm);
5195 NEON_GET_REG(T1, rn, 1);
5196
5197 for (pass = 0; pass < 2; pass++) {
5198 if (pass == 0) {
5199 tmp = neon_load_reg(rn, 0);
5200 } else {
5201 tmp = new_tmp();
5202 tcg_gen_mov_i32(tmp, cpu_T[1]);
5203 }
5204 tmp2 = new_tmp();
5205 tcg_gen_mov_i32(tmp2, cpu_T[0]);
5206 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5207 if (op == 6 || op == 7) {
5208 gen_neon_negl(cpu_V0, size);
5209 }
5210 if (op != 11) {
5211 neon_load_reg64(cpu_V1, rd + pass);
5212 }
5213 switch (op) {
5214 case 2: case 6:
5215 gen_neon_addl(size);
5216 break;
5217 case 3: case 7:
5218 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5219 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5220 break;
5221 case 10:
5222 /* no-op */
5223 break;
5224 case 11:
5225 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5226 break;
5227 default:
5228 abort();
5229 }
5230 neon_store_reg64(cpu_V0, rd + pass);
5231 }
5232 break;
5233 default: /* 14 and 15 are RESERVED */
5234 return 1;
5235 }
5236 }
5237 } else { /* size == 3 */
5238 if (!u) {
5239 /* Extract. */
5240 imm = (insn >> 8) & 0xf;
5241 count = q + 1;
5242
5243 if (imm > 7 && !q)
5244 return 1;
5245
5246 if (imm == 0) {
5247 neon_load_reg64(cpu_V0, rn);
5248 if (q) {
5249 neon_load_reg64(cpu_V1, rn + 1);
5250 }
5251 } else if (imm == 8) {
5252 neon_load_reg64(cpu_V0, rn + 1);
5253 if (q) {
5254 neon_load_reg64(cpu_V1, rm);
5255 }
5256 } else if (q) {
5257 tmp64 = tcg_temp_new_i64();
5258 if (imm < 8) {
5259 neon_load_reg64(cpu_V0, rn);
5260 neon_load_reg64(tmp64, rn + 1);
5261 } else {
5262 neon_load_reg64(cpu_V0, rn + 1);
5263 neon_load_reg64(tmp64, rm);
5264 }
5265 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5266 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5267 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5268 if (imm < 8) {
5269 neon_load_reg64(cpu_V1, rm);
5270 } else {
5271 neon_load_reg64(cpu_V1, rm + 1);
5272 imm -= 8;
5273 }
5274 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5275 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5276 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5277 } else {
5278 /* BUGFIX */
5279 neon_load_reg64(cpu_V0, rn);
5280 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5281 neon_load_reg64(cpu_V1, rm);
5282 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5283 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5284 }
5285 neon_store_reg64(cpu_V0, rd);
5286 if (q) {
5287 neon_store_reg64(cpu_V1, rd + 1);
5288 }
5289 } else if ((insn & (1 << 11)) == 0) {
5290 /* Two register misc. */
5291 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5292 size = (insn >> 18) & 3;
5293 switch (op) {
5294 case 0: /* VREV64 */
5295 if (size == 3)
5296 return 1;
5297 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5298 NEON_GET_REG(T0, rm, pass * 2);
5299 NEON_GET_REG(T1, rm, pass * 2 + 1);
5300 switch (size) {
5301 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5302 case 1: gen_swap_half(cpu_T[0]); break;
5303 case 2: /* no-op */ break;
5304 default: abort();
5305 }
5306 NEON_SET_REG(T0, rd, pass * 2 + 1);
5307 if (size == 2) {
5308 NEON_SET_REG(T1, rd, pass * 2);
5309 } else {
5310 gen_op_movl_T0_T1();
5311 switch (size) {
5312 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5313 case 1: gen_swap_half(cpu_T[0]); break;
5314 default: abort();
5315 }
5316 NEON_SET_REG(T0, rd, pass * 2);
5317 }
5318 }
5319 break;
5320 case 4: case 5: /* VPADDL */
5321 case 12: case 13: /* VPADAL */
5322 if (size == 3)
5323 return 1;
5324 for (pass = 0; pass < q + 1; pass++) {
5325 tmp = neon_load_reg(rm, pass * 2);
5326 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5327 tmp = neon_load_reg(rm, pass * 2 + 1);
5328 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5329 switch (size) {
5330 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5331 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5332 case 2: tcg_gen_add_i64(CPU_V001); break;
5333 default: abort();
5334 }
5335 if (op >= 12) {
5336 /* Accumulate. */
5337 neon_load_reg64(cpu_V1, rd + pass);
5338 gen_neon_addl(size);
5339 }
5340 neon_store_reg64(cpu_V0, rd + pass);
5341 }
5342 break;
5343 case 33: /* VTRN */
5344 if (size == 2) {
5345 for (n = 0; n < (q ? 4 : 2); n += 2) {
5346 NEON_GET_REG(T0, rm, n);
5347 NEON_GET_REG(T1, rd, n + 1);
5348 NEON_SET_REG(T1, rm, n);
5349 NEON_SET_REG(T0, rd, n + 1);
5350 }
5351 } else {
5352 goto elementwise;
5353 }
5354 break;
5355 case 34: /* VUZP */
5356 /* Reg Before After
5357 Rd A3 A2 A1 A0 B2 B0 A2 A0
5358 Rm B3 B2 B1 B0 B3 B1 A3 A1
5359 */
5360 if (size == 3)
5361 return 1;
5362 gen_neon_unzip(rd, q, 0, size);
5363 gen_neon_unzip(rm, q, 4, size);
5364 if (q) {
5365 static int unzip_order_q[8] =
5366 {0, 2, 4, 6, 1, 3, 5, 7};
5367 for (n = 0; n < 8; n++) {
5368 int reg = (n < 4) ? rd : rm;
5369 gen_neon_movl_T0_scratch(unzip_order_q[n]);
5370 NEON_SET_REG(T0, reg, n % 4);
5371 }
5372 } else {
5373 static int unzip_order[4] =
5374 {0, 4, 1, 5};
5375 for (n = 0; n < 4; n++) {
5376 int reg = (n < 2) ? rd : rm;
5377 gen_neon_movl_T0_scratch(unzip_order[n]);
5378 NEON_SET_REG(T0, reg, n % 2);
5379 }
5380 }
5381 break;
5382 case 35: /* VZIP */
5383 /* Reg Before After
5384 Rd A3 A2 A1 A0 B1 A1 B0 A0
5385 Rm B3 B2 B1 B0 B3 A3 B2 A2
5386 */
5387 if (size == 3)
5388 return 1;
5389 count = (q ? 4 : 2);
5390 for (n = 0; n < count; n++) {
5391 NEON_GET_REG(T0, rd, n);
5392 NEON_GET_REG(T1, rd, n);
5393 switch (size) {
5394 case 0: gen_neon_zip_u8(cpu_T[0], cpu_T[1]); break;
5395 case 1: gen_neon_zip_u16(cpu_T[0], cpu_T[1]); break;
5396 case 2: /* no-op */; break;
5397 default: abort();
5398 }
5399 gen_neon_movl_scratch_T0(n * 2);
5400 gen_neon_movl_scratch_T1(n * 2 + 1);
5401 }
5402 for (n = 0; n < count * 2; n++) {
5403 int reg = (n < count) ? rd : rm;
5404 gen_neon_movl_T0_scratch(n);
5405 NEON_SET_REG(T0, reg, n % count);
5406 }
5407 break;
5408 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5409 if (size == 3)
5410 return 1;
5411 TCGV_UNUSED(tmp2);
5412 for (pass = 0; pass < 2; pass++) {
5413 neon_load_reg64(cpu_V0, rm + pass);
5414 tmp = new_tmp();
5415 if (op == 36 && q == 0) {
5416 gen_neon_narrow(size, tmp, cpu_V0);
5417 } else if (q) {
5418 gen_neon_narrow_satu(size, tmp, cpu_V0);
5419 } else {
5420 gen_neon_narrow_sats(size, tmp, cpu_V0);
5421 }
5422 if (pass == 0) {
5423 tmp2 = tmp;
5424 } else {
5425 neon_store_reg(rd, 0, tmp2);
5426 neon_store_reg(rd, 1, tmp);
5427 }
5428 }
5429 break;
5430 case 38: /* VSHLL */
5431 if (q || size == 3)
5432 return 1;
5433 tmp = neon_load_reg(rm, 0);
5434 tmp2 = neon_load_reg(rm, 1);
5435 for (pass = 0; pass < 2; pass++) {
5436 if (pass == 1)
5437 tmp = tmp2;
5438 gen_neon_widen(cpu_V0, tmp, size, 1);
5439 neon_store_reg64(cpu_V0, rd + pass);
5440 }
5441 break;
5442 default:
5443 elementwise:
5444 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5445 if (op == 30 || op == 31 || op >= 58) {
5446 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5447 neon_reg_offset(rm, pass));
5448 } else {
5449 NEON_GET_REG(T0, rm, pass);
5450 }
5451 switch (op) {
5452 case 1: /* VREV32 */
5453 switch (size) {
5454 case 0: tcg_gen_bswap32_i32(cpu_T[0], cpu_T[0]); break;
5455 case 1: gen_swap_half(cpu_T[0]); break;
5456 default: return 1;
5457 }
5458 break;
5459 case 2: /* VREV16 */
5460 if (size != 0)
5461 return 1;
5462 gen_rev16(cpu_T[0]);
5463 break;
5464 case 8: /* CLS */
5465 switch (size) {
5466 case 0: gen_helper_neon_cls_s8(cpu_T[0], cpu_T[0]); break;
5467 case 1: gen_helper_neon_cls_s16(cpu_T[0], cpu_T[0]); break;
5468 case 2: gen_helper_neon_cls_s32(cpu_T[0], cpu_T[0]); break;
5469 default: return 1;
5470 }
5471 break;
5472 case 9: /* CLZ */
5473 switch (size) {
5474 case 0: gen_helper_neon_clz_u8(cpu_T[0], cpu_T[0]); break;
5475 case 1: gen_helper_neon_clz_u16(cpu_T[0], cpu_T[0]); break;
5476 case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
5477 default: return 1;
5478 }
5479 break;
5480 case 10: /* CNT */
5481 if (size != 0)
5482 return 1;
5483 gen_helper_neon_cnt_u8(cpu_T[0], cpu_T[0]);
5484 break;
5485 case 11: /* VNOT */
5486 if (size != 0)
5487 return 1;
5488 gen_op_notl_T0();
5489 break;
5490 case 14: /* VQABS */
5491 switch (size) {
5492 case 0: gen_helper_neon_qabs_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5493 case 1: gen_helper_neon_qabs_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5494 case 2: gen_helper_neon_qabs_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5495 default: return 1;
5496 }
5497 break;
5498 case 15: /* VQNEG */
5499 switch (size) {
5500 case 0: gen_helper_neon_qneg_s8(cpu_T[0], cpu_env, cpu_T[0]); break;
5501 case 1: gen_helper_neon_qneg_s16(cpu_T[0], cpu_env, cpu_T[0]); break;
5502 case 2: gen_helper_neon_qneg_s32(cpu_T[0], cpu_env, cpu_T[0]); break;
5503 default: return 1;
5504 }
5505 break;
5506 case 16: case 19: /* VCGT #0, VCLE #0 */
5507 gen_op_movl_T1_im(0);
5508 switch(size) {
5509 case 0: gen_helper_neon_cgt_s8(CPU_T001); break;
5510 case 1: gen_helper_neon_cgt_s16(CPU_T001); break;
5511 case 2: gen_helper_neon_cgt_s32(CPU_T001); break;
5512 default: return 1;
5513 }
5514 if (op == 19)
5515 gen_op_notl_T0();
5516 break;
5517 case 17: case 20: /* VCGE #0, VCLT #0 */
5518 gen_op_movl_T1_im(0);
5519 switch(size) {
5520 case 0: gen_helper_neon_cge_s8(CPU_T001); break;
5521 case 1: gen_helper_neon_cge_s16(CPU_T001); break;
5522 case 2: gen_helper_neon_cge_s32(CPU_T001); break;
5523 default: return 1;
5524 }
5525 if (op == 20)
5526 gen_op_notl_T0();
5527 break;
5528 case 18: /* VCEQ #0 */
5529 gen_op_movl_T1_im(0);
5530 switch(size) {
5531 case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
5532 case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
5533 case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
5534 default: return 1;
5535 }
5536 break;
5537 case 22: /* VABS */
5538 switch(size) {
5539 case 0: gen_helper_neon_abs_s8(cpu_T[0], cpu_T[0]); break;
5540 case 1: gen_helper_neon_abs_s16(cpu_T[0], cpu_T[0]); break;
5541 case 2: tcg_gen_abs_i32(cpu_T[0], cpu_T[0]); break;
5542 default: return 1;
5543 }
5544 break;
5545 case 23: /* VNEG */
5546 gen_op_movl_T1_im(0);
5547 if (size == 3)
5548 return 1;
5549 gen_neon_rsb(size);
5550 break;
5551 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5552 gen_op_movl_T1_im(0);
5553 gen_helper_neon_cgt_f32(CPU_T001);
5554 if (op == 27)
5555 gen_op_notl_T0();
5556 break;
5557 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5558 gen_op_movl_T1_im(0);
5559 gen_helper_neon_cge_f32(CPU_T001);
5560 if (op == 28)
5561 gen_op_notl_T0();
5562 break;
5563 case 26: /* Float VCEQ #0 */
5564 gen_op_movl_T1_im(0);
5565 gen_helper_neon_ceq_f32(CPU_T001);
5566 break;
5567 case 30: /* Float VABS */
5568 gen_vfp_abs(0);
5569 break;
5570 case 31: /* Float VNEG */
5571 gen_vfp_neg(0);
5572 break;
5573 case 32: /* VSWP */
5574 NEON_GET_REG(T1, rd, pass);
5575 NEON_SET_REG(T1, rm, pass);
5576 break;
5577 case 33: /* VTRN */
5578 NEON_GET_REG(T1, rd, pass);
5579 switch (size) {
5580 case 0: gen_neon_trn_u8(cpu_T[0], cpu_T[1]); break;
5581 case 1: gen_neon_trn_u16(cpu_T[0], cpu_T[1]); break;
5582 case 2: abort();
5583 default: return 1;
5584 }
5585 NEON_SET_REG(T1, rm, pass);
5586 break;
5587 case 56: /* Integer VRECPE */
5588 gen_helper_recpe_u32(cpu_T[0], cpu_T[0], cpu_env);
5589 break;
5590 case 57: /* Integer VRSQRTE */
5591 gen_helper_rsqrte_u32(cpu_T[0], cpu_T[0], cpu_env);
5592 break;
5593 case 58: /* Float VRECPE */
5594 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5595 break;
5596 case 59: /* Float VRSQRTE */
5597 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5598 break;
5599 case 60: /* VCVT.F32.S32 */
5600 gen_vfp_tosiz(0);
5601 break;
5602 case 61: /* VCVT.F32.U32 */
5603 gen_vfp_touiz(0);
5604 break;
5605 case 62: /* VCVT.S32.F32 */
5606 gen_vfp_sito(0);
5607 break;
5608 case 63: /* VCVT.U32.F32 */
5609 gen_vfp_uito(0);
5610 break;
5611 default:
5612 /* Reserved: 21, 29, 39-56 */
5613 return 1;
5614 }
5615 if (op == 30 || op == 31 || op >= 58) {
5616 tcg_gen_st_f32(cpu_F0s, cpu_env,
5617 neon_reg_offset(rd, pass));
5618 } else {
5619 NEON_SET_REG(T0, rd, pass);
5620 }
5621 }
5622 break;
5623 }
5624 } else if ((insn & (1 << 10)) == 0) {
5625 /* VTBL, VTBX. */
5626 n = ((insn >> 5) & 0x18) + 8;
5627 if (insn & (1 << 6)) {
5628 tmp = neon_load_reg(rd, 0);
5629 } else {
5630 tmp = new_tmp();
5631 tcg_gen_movi_i32(tmp, 0);
5632 }
5633 tmp2 = neon_load_reg(rm, 0);
5634 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5635 tcg_const_i32(n));
5636 dead_tmp(tmp);
5637 if (insn & (1 << 6)) {
5638 tmp = neon_load_reg(rd, 1);
5639 } else {
5640 tmp = new_tmp();
5641 tcg_gen_movi_i32(tmp, 0);
5642 }
5643 tmp3 = neon_load_reg(rm, 1);
5644 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5645 tcg_const_i32(n));
5646 neon_store_reg(rd, 0, tmp2);
5647 neon_store_reg(rd, 1, tmp3);
5648 dead_tmp(tmp);
5649 } else if ((insn & 0x380) == 0) {
5650 /* VDUP */
5651 if (insn & (1 << 19)) {
5652 NEON_SET_REG(T0, rm, 1);
5653 } else {
5654 NEON_SET_REG(T0, rm, 0);
5655 }
5656 if (insn & (1 << 16)) {
5657 gen_neon_dup_u8(cpu_T[0], ((insn >> 17) & 3) * 8);
5658 } else if (insn & (1 << 17)) {
5659 if ((insn >> 18) & 1)
5660 gen_neon_dup_high16(cpu_T[0]);
5661 else
5662 gen_neon_dup_low16(cpu_T[0]);
5663 }
5664 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5665 NEON_SET_REG(T0, rd, pass);
5666 }
5667 } else {
5668 return 1;
5669 }
5670 }
5671 }
5672 return 0;
5673 }
5674
5675 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5676 {
5677 int crn = (insn >> 16) & 0xf;
5678 int crm = insn & 0xf;
5679 int op1 = (insn >> 21) & 7;
5680 int op2 = (insn >> 5) & 7;
5681 int rt = (insn >> 12) & 0xf;
5682 TCGv tmp;
5683
5684 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5685 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5686 /* TEECR */
5687 if (IS_USER(s))
5688 return 1;
5689 tmp = load_cpu_field(teecr);
5690 store_reg(s, rt, tmp);
5691 return 0;
5692 }
5693 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5694 /* TEEHBR */
5695 if (IS_USER(s) && (env->teecr & 1))
5696 return 1;
5697 tmp = load_cpu_field(teehbr);
5698 store_reg(s, rt, tmp);
5699 return 0;
5700 }
5701 }
5702 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5703 op1, crn, crm, op2);
5704 return 1;
5705 }
5706
5707 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5708 {
5709 int crn = (insn >> 16) & 0xf;
5710 int crm = insn & 0xf;
5711 int op1 = (insn >> 21) & 7;
5712 int op2 = (insn >> 5) & 7;
5713 int rt = (insn >> 12) & 0xf;
5714 TCGv tmp;
5715
5716 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5717 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5718 /* TEECR */
5719 if (IS_USER(s))
5720 return 1;
5721 tmp = load_reg(s, rt);
5722 gen_helper_set_teecr(cpu_env, tmp);
5723 dead_tmp(tmp);
5724 return 0;
5725 }
5726 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5727 /* TEEHBR */
5728 if (IS_USER(s) && (env->teecr & 1))
5729 return 1;
5730 tmp = load_reg(s, rt);
5731 store_cpu_field(tmp, teehbr);
5732 return 0;
5733 }
5734 }
5735 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5736 op1, crn, crm, op2);
5737 return 1;
5738 }
5739
5740 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5741 {
5742 int cpnum;
5743
5744 cpnum = (insn >> 8) & 0xf;
5745 if (arm_feature(env, ARM_FEATURE_XSCALE)
5746 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5747 return 1;
5748
5749 switch (cpnum) {
5750 case 0:
5751 case 1:
5752 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5753 return disas_iwmmxt_insn(env, s, insn);
5754 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5755 return disas_dsp_insn(env, s, insn);
5756 }
5757 return 1;
5758 case 10:
5759 case 11:
5760 return disas_vfp_insn (env, s, insn);
5761 case 14:
5762 /* Coprocessors 7-15 are architecturally reserved by ARM.
5763 Unfortunately Intel decided to ignore this. */
5764 if (arm_feature(env, ARM_FEATURE_XSCALE))
5765 goto board;
5766 if (insn & (1 << 20))
5767 return disas_cp14_read(env, s, insn);
5768 else
5769 return disas_cp14_write(env, s, insn);
5770 case 15:
5771 return disas_cp15_insn (env, s, insn);
5772 default:
5773 board:
5774 /* Unknown coprocessor. See if the board has hooked it. */
5775 return disas_cp_insn (env, s, insn);
5776 }
5777 }
5778
5779
5780 /* Store a 64-bit value to a register pair. Clobbers val. */
5781 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5782 {
5783 TCGv tmp;
5784 tmp = new_tmp();
5785 tcg_gen_trunc_i64_i32(tmp, val);
5786 store_reg(s, rlow, tmp);
5787 tmp = new_tmp();
5788 tcg_gen_shri_i64(val, val, 32);
5789 tcg_gen_trunc_i64_i32(tmp, val);
5790 store_reg(s, rhigh, tmp);
5791 }
5792
5793 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5794 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5795 {
5796 TCGv_i64 tmp;
5797 TCGv tmp2;
5798
5799 /* Load value and extend to 64 bits. */
5800 tmp = tcg_temp_new_i64();
5801 tmp2 = load_reg(s, rlow);
5802 tcg_gen_extu_i32_i64(tmp, tmp2);
5803 dead_tmp(tmp2);
5804 tcg_gen_add_i64(val, val, tmp);
5805 }
5806
5807 /* load and add a 64-bit value from a register pair. */
5808 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5809 {
5810 TCGv_i64 tmp;
5811 TCGv tmpl;
5812 TCGv tmph;
5813
5814 /* Load 64-bit value rd:rn. */
5815 tmpl = load_reg(s, rlow);
5816 tmph = load_reg(s, rhigh);
5817 tmp = tcg_temp_new_i64();
5818 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5819 dead_tmp(tmpl);
5820 dead_tmp(tmph);
5821 tcg_gen_add_i64(val, val, tmp);
5822 }
5823
5824 /* Set N and Z flags from a 64-bit value. */
5825 static void gen_logicq_cc(TCGv_i64 val)
5826 {
5827 TCGv tmp = new_tmp();
5828 gen_helper_logicq_cc(tmp, val);
5829 gen_logic_CC(tmp);
5830 dead_tmp(tmp);
5831 }
5832
5833 static void disas_arm_insn(CPUState * env, DisasContext *s)
5834 {
5835 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5836 TCGv tmp;
5837 TCGv tmp2;
5838 TCGv tmp3;
5839 TCGv addr;
5840 TCGv_i64 tmp64;
5841
5842 insn = ldl_code(s->pc);
5843 s->pc += 4;
5844
5845 /* M variants do not implement ARM mode. */
5846 if (IS_M(env))
5847 goto illegal_op;
5848 cond = insn >> 28;
5849 if (cond == 0xf){
5850 /* Unconditional instructions. */
5851 if (((insn >> 25) & 7) == 1) {
5852 /* NEON Data processing. */
5853 if (!arm_feature(env, ARM_FEATURE_NEON))
5854 goto illegal_op;
5855
5856 if (disas_neon_data_insn(env, s, insn))
5857 goto illegal_op;
5858 return;
5859 }
5860 if ((insn & 0x0f100000) == 0x04000000) {
5861 /* NEON load/store. */
5862 if (!arm_feature(env, ARM_FEATURE_NEON))
5863 goto illegal_op;
5864
5865 if (disas_neon_ls_insn(env, s, insn))
5866 goto illegal_op;
5867 return;
5868 }
5869 if ((insn & 0x0d70f000) == 0x0550f000)
5870 return; /* PLD */
5871 else if ((insn & 0x0ffffdff) == 0x01010000) {
5872 ARCH(6);
5873 /* setend */
5874 if (insn & (1 << 9)) {
5875 /* BE8 mode not implemented. */
5876 goto illegal_op;
5877 }
5878 return;
5879 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5880 switch ((insn >> 4) & 0xf) {
5881 case 1: /* clrex */
5882 ARCH(6K);
5883 gen_helper_clrex(cpu_env);
5884 return;
5885 case 4: /* dsb */
5886 case 5: /* dmb */
5887 case 6: /* isb */
5888 ARCH(7);
5889 /* We don't emulate caches so these are a no-op. */
5890 return;
5891 default:
5892 goto illegal_op;
5893 }
5894 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5895 /* srs */
5896 int32_t offset;
5897 if (IS_USER(s))
5898 goto illegal_op;
5899 ARCH(6);
5900 op1 = (insn & 0x1f);
5901 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5902 addr = load_reg(s, 13);
5903 } else {
5904 addr = new_tmp();
5905 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5906 }
5907 i = (insn >> 23) & 3;
5908 switch (i) {
5909 case 0: offset = -4; break; /* DA */
5910 case 1: offset = 0; break; /* IA */
5911 case 2: offset = -8; break; /* DB */
5912 case 3: offset = 4; break; /* IB */
5913 default: abort();
5914 }
5915 if (offset)
5916 tcg_gen_addi_i32(addr, addr, offset);
5917 tmp = load_reg(s, 14);
5918 gen_st32(tmp, addr, 0);
5919 tmp = load_cpu_field(spsr);
5920 tcg_gen_addi_i32(addr, addr, 4);
5921 gen_st32(tmp, addr, 0);
5922 if (insn & (1 << 21)) {
5923 /* Base writeback. */
5924 switch (i) {
5925 case 0: offset = -8; break;
5926 case 1: offset = 4; break;
5927 case 2: offset = -4; break;
5928 case 3: offset = 0; break;
5929 default: abort();
5930 }
5931 if (offset)
5932 tcg_gen_addi_i32(addr, addr, offset);
5933 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5934 store_reg(s, 13, addr);
5935 } else {
5936 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5937 dead_tmp(addr);
5938 }
5939 } else {
5940 dead_tmp(addr);
5941 }
5942 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5943 /* rfe */
5944 int32_t offset;
5945 if (IS_USER(s))
5946 goto illegal_op;
5947 ARCH(6);
5948 rn = (insn >> 16) & 0xf;
5949 addr = load_reg(s, rn);
5950 i = (insn >> 23) & 3;
5951 switch (i) {
5952 case 0: offset = -4; break; /* DA */
5953 case 1: offset = 0; break; /* IA */
5954 case 2: offset = -8; break; /* DB */
5955 case 3: offset = 4; break; /* IB */
5956 default: abort();
5957 }
5958 if (offset)
5959 tcg_gen_addi_i32(addr, addr, offset);
5960 /* Load PC into tmp and CPSR into tmp2. */
5961 tmp = gen_ld32(addr, 0);
5962 tcg_gen_addi_i32(addr, addr, 4);
5963 tmp2 = gen_ld32(addr, 0);
5964 if (insn & (1 << 21)) {
5965 /* Base writeback. */
5966 switch (i) {
5967 case 0: offset = -8; break;
5968 case 1: offset = 4; break;
5969 case 2: offset = -4; break;
5970 case 3: offset = 0; break;
5971 default: abort();
5972 }
5973 if (offset)
5974 tcg_gen_addi_i32(addr, addr, offset);
5975 store_reg(s, rn, addr);
5976 } else {
5977 dead_tmp(addr);
5978 }
5979 gen_rfe(s, tmp, tmp2);
5980 return;
5981 } else if ((insn & 0x0e000000) == 0x0a000000) {
5982 /* branch link and change to thumb (blx <offset>) */
5983 int32_t offset;
5984
5985 val = (uint32_t)s->pc;
5986 tmp = new_tmp();
5987 tcg_gen_movi_i32(tmp, val);
5988 store_reg(s, 14, tmp);
5989 /* Sign-extend the 24-bit offset */
5990 offset = (((int32_t)insn) << 8) >> 8;
5991 /* offset * 4 + bit24 * 2 + (thumb bit) */
5992 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5993 /* pipeline offset */
5994 val += 4;
5995 gen_bx_im(s, val);
5996 return;
5997 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5998 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5999 /* iWMMXt register transfer. */
6000 if (env->cp15.c15_cpar & (1 << 1))
6001 if (!disas_iwmmxt_insn(env, s, insn))
6002 return;
6003 }
6004 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6005 /* Coprocessor double register transfer. */
6006 } else if ((insn & 0x0f000010) == 0x0e000010) {
6007 /* Additional coprocessor register transfer. */
6008 } else if ((insn & 0x0ff10020) == 0x01000000) {
6009 uint32_t mask;
6010 uint32_t val;
6011 /* cps (privileged) */
6012 if (IS_USER(s))
6013 return;
6014 mask = val = 0;
6015 if (insn & (1 << 19)) {
6016 if (insn & (1 << 8))
6017 mask |= CPSR_A;
6018 if (insn & (1 << 7))
6019 mask |= CPSR_I;
6020 if (insn & (1 << 6))
6021 mask |= CPSR_F;
6022 if (insn & (1 << 18))
6023 val |= mask;
6024 }
6025 if (insn & (1 << 17)) {
6026 mask |= CPSR_M;
6027 val |= (insn & 0x1f);
6028 }
6029 if (mask) {
6030 gen_set_psr_im(s, mask, 0, val);
6031 }
6032 return;
6033 }
6034 goto illegal_op;
6035 }
6036 if (cond != 0xe) {
6037 /* if not always execute, we generate a conditional jump to
6038 next instruction */
6039 s->condlabel = gen_new_label();
6040 gen_test_cc(cond ^ 1, s->condlabel);
6041 s->condjmp = 1;
6042 }
6043 if ((insn & 0x0f900000) == 0x03000000) {
6044 if ((insn & (1 << 21)) == 0) {
6045 ARCH(6T2);
6046 rd = (insn >> 12) & 0xf;
6047 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6048 if ((insn & (1 << 22)) == 0) {
6049 /* MOVW */
6050 tmp = new_tmp();
6051 tcg_gen_movi_i32(tmp, val);
6052 } else {
6053 /* MOVT */
6054 tmp = load_reg(s, rd);
6055 tcg_gen_ext16u_i32(tmp, tmp);
6056 tcg_gen_ori_i32(tmp, tmp, val << 16);
6057 }
6058 store_reg(s, rd, tmp);
6059 } else {
6060 if (((insn >> 12) & 0xf) != 0xf)
6061 goto illegal_op;
6062 if (((insn >> 16) & 0xf) == 0) {
6063 gen_nop_hint(s, insn & 0xff);
6064 } else {
6065 /* CPSR = immediate */
6066 val = insn & 0xff;
6067 shift = ((insn >> 8) & 0xf) * 2;
6068 if (shift)
6069 val = (val >> shift) | (val << (32 - shift));
6070 i = ((insn & (1 << 22)) != 0);
6071 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6072 goto illegal_op;
6073 }
6074 }
6075 } else if ((insn & 0x0f900000) == 0x01000000
6076 && (insn & 0x00000090) != 0x00000090) {
6077 /* miscellaneous instructions */
6078 op1 = (insn >> 21) & 3;
6079 sh = (insn >> 4) & 0xf;
6080 rm = insn & 0xf;
6081 switch (sh) {
6082 case 0x0: /* move program status register */
6083 if (op1 & 1) {
6084 /* PSR = reg */
6085 tmp = load_reg(s, rm);
6086 i = ((op1 & 2) != 0);
6087 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6088 goto illegal_op;
6089 } else {
6090 /* reg = PSR */
6091 rd = (insn >> 12) & 0xf;
6092 if (op1 & 2) {
6093 if (IS_USER(s))
6094 goto illegal_op;
6095 tmp = load_cpu_field(spsr);
6096 } else {
6097 tmp = new_tmp();
6098 gen_helper_cpsr_read(tmp);
6099 }
6100 store_reg(s, rd, tmp);
6101 }
6102 break;
6103 case 0x1:
6104 if (op1 == 1) {
6105 /* branch/exchange thumb (bx). */
6106 tmp = load_reg(s, rm);
6107 gen_bx(s, tmp);
6108 } else if (op1 == 3) {
6109 /* clz */
6110 rd = (insn >> 12) & 0xf;
6111 tmp = load_reg(s, rm);
6112 gen_helper_clz(tmp, tmp);
6113 store_reg(s, rd, tmp);
6114 } else {
6115 goto illegal_op;
6116 }
6117 break;
6118 case 0x2:
6119 if (op1 == 1) {
6120 ARCH(5J); /* bxj */
6121 /* Trivial implementation equivalent to bx. */
6122 tmp = load_reg(s, rm);
6123 gen_bx(s, tmp);
6124 } else {
6125 goto illegal_op;
6126 }
6127 break;
6128 case 0x3:
6129 if (op1 != 1)
6130 goto illegal_op;
6131
6132 /* branch link/exchange thumb (blx) */
6133 tmp = load_reg(s, rm);
6134 tmp2 = new_tmp();
6135 tcg_gen_movi_i32(tmp2, s->pc);
6136 store_reg(s, 14, tmp2);
6137 gen_bx(s, tmp);
6138 break;
6139 case 0x5: /* saturating add/subtract */
6140 rd = (insn >> 12) & 0xf;
6141 rn = (insn >> 16) & 0xf;
6142 tmp = load_reg(s, rm);
6143 tmp2 = load_reg(s, rn);
6144 if (op1 & 2)
6145 gen_helper_double_saturate(tmp2, tmp2);
6146 if (op1 & 1)
6147 gen_helper_sub_saturate(tmp, tmp, tmp2);
6148 else
6149 gen_helper_add_saturate(tmp, tmp, tmp2);
6150 dead_tmp(tmp2);
6151 store_reg(s, rd, tmp);
6152 break;
6153 case 7: /* bkpt */
6154 gen_set_condexec(s);
6155 gen_set_pc_im(s->pc - 4);
6156 gen_exception(EXCP_BKPT);
6157 s->is_jmp = DISAS_JUMP;
6158 break;
6159 case 0x8: /* signed multiply */
6160 case 0xa:
6161 case 0xc:
6162 case 0xe:
6163 rs = (insn >> 8) & 0xf;
6164 rn = (insn >> 12) & 0xf;
6165 rd = (insn >> 16) & 0xf;
6166 if (op1 == 1) {
6167 /* (32 * 16) >> 16 */
6168 tmp = load_reg(s, rm);
6169 tmp2 = load_reg(s, rs);
6170 if (sh & 4)
6171 tcg_gen_sari_i32(tmp2, tmp2, 16);
6172 else
6173 gen_sxth(tmp2);
6174 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6175 tcg_gen_shri_i64(tmp64, tmp64, 16);
6176 tmp = new_tmp();
6177 tcg_gen_trunc_i64_i32(tmp, tmp64);
6178 if ((sh & 2) == 0) {
6179 tmp2 = load_reg(s, rn);
6180 gen_helper_add_setq(tmp, tmp, tmp2);
6181 dead_tmp(tmp2);
6182 }
6183 store_reg(s, rd, tmp);
6184 } else {
6185 /* 16 * 16 */
6186 tmp = load_reg(s, rm);
6187 tmp2 = load_reg(s, rs);
6188 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6189 dead_tmp(tmp2);
6190 if (op1 == 2) {
6191 tmp64 = tcg_temp_new_i64();
6192 tcg_gen_ext_i32_i64(tmp64, tmp);
6193 dead_tmp(tmp);
6194 gen_addq(s, tmp64, rn, rd);
6195 gen_storeq_reg(s, rn, rd, tmp64);
6196 } else {
6197 if (op1 == 0) {
6198 tmp2 = load_reg(s, rn);
6199 gen_helper_add_setq(tmp, tmp, tmp2);
6200 dead_tmp(tmp2);
6201 }
6202 store_reg(s, rd, tmp);
6203 }
6204 }
6205 break;
6206 default:
6207 goto illegal_op;
6208 }
6209 } else if (((insn & 0x0e000000) == 0 &&
6210 (insn & 0x00000090) != 0x90) ||
6211 ((insn & 0x0e000000) == (1 << 25))) {
6212 int set_cc, logic_cc, shiftop;
6213
6214 op1 = (insn >> 21) & 0xf;
6215 set_cc = (insn >> 20) & 1;
6216 logic_cc = table_logic_cc[op1] & set_cc;
6217
6218 /* data processing instruction */
6219 if (insn & (1 << 25)) {
6220 /* immediate operand */
6221 val = insn & 0xff;
6222 shift = ((insn >> 8) & 0xf) * 2;
6223 if (shift) {
6224 val = (val >> shift) | (val << (32 - shift));
6225 }
6226 tmp2 = new_tmp();
6227 tcg_gen_movi_i32(tmp2, val);
6228 if (logic_cc && shift) {
6229 gen_set_CF_bit31(tmp2);
6230 }
6231 } else {
6232 /* register */
6233 rm = (insn) & 0xf;
6234 tmp2 = load_reg(s, rm);
6235 shiftop = (insn >> 5) & 3;
6236 if (!(insn & (1 << 4))) {
6237 shift = (insn >> 7) & 0x1f;
6238 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6239 } else {
6240 rs = (insn >> 8) & 0xf;
6241 tmp = load_reg(s, rs);
6242 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6243 }
6244 }
6245 if (op1 != 0x0f && op1 != 0x0d) {
6246 rn = (insn >> 16) & 0xf;
6247 tmp = load_reg(s, rn);
6248 } else {
6249 TCGV_UNUSED(tmp);
6250 }
6251 rd = (insn >> 12) & 0xf;
6252 switch(op1) {
6253 case 0x00:
6254 tcg_gen_and_i32(tmp, tmp, tmp2);
6255 if (logic_cc) {
6256 gen_logic_CC(tmp);
6257 }
6258 store_reg_bx(env, s, rd, tmp);
6259 break;
6260 case 0x01:
6261 tcg_gen_xor_i32(tmp, tmp, tmp2);
6262 if (logic_cc) {
6263 gen_logic_CC(tmp);
6264 }
6265 store_reg_bx(env, s, rd, tmp);
6266 break;
6267 case 0x02:
6268 if (set_cc && rd == 15) {
6269 /* SUBS r15, ... is used for exception return. */
6270 if (IS_USER(s)) {
6271 goto illegal_op;
6272 }
6273 gen_helper_sub_cc(tmp, tmp, tmp2);
6274 gen_exception_return(s, tmp);
6275 } else {
6276 if (set_cc) {
6277 gen_helper_sub_cc(tmp, tmp, tmp2);
6278 } else {
6279 tcg_gen_sub_i32(tmp, tmp, tmp2);
6280 }
6281 store_reg_bx(env, s, rd, tmp);
6282 }
6283 break;
6284 case 0x03:
6285 if (set_cc) {
6286 gen_helper_sub_cc(tmp, tmp2, tmp);
6287 } else {
6288 tcg_gen_sub_i32(tmp, tmp2, tmp);
6289 }
6290 store_reg_bx(env, s, rd, tmp);
6291 break;
6292 case 0x04:
6293 if (set_cc) {
6294 gen_helper_add_cc(tmp, tmp, tmp2);
6295 } else {
6296 tcg_gen_add_i32(tmp, tmp, tmp2);
6297 }
6298 store_reg_bx(env, s, rd, tmp);
6299 break;
6300 case 0x05:
6301 if (set_cc) {
6302 gen_helper_adc_cc(tmp, tmp, tmp2);
6303 } else {
6304 gen_add_carry(tmp, tmp, tmp2);
6305 }
6306 store_reg_bx(env, s, rd, tmp);
6307 break;
6308 case 0x06:
6309 if (set_cc) {
6310 gen_helper_sbc_cc(tmp, tmp, tmp2);
6311 } else {
6312 gen_sub_carry(tmp, tmp, tmp2);
6313 }
6314 store_reg_bx(env, s, rd, tmp);
6315 break;
6316 case 0x07:
6317 if (set_cc) {
6318 gen_helper_sbc_cc(tmp, tmp2, tmp);
6319 } else {
6320 gen_sub_carry(tmp, tmp2, tmp);
6321 }
6322 store_reg_bx(env, s, rd, tmp);
6323 break;
6324 case 0x08:
6325 if (set_cc) {
6326 tcg_gen_and_i32(tmp, tmp, tmp2);
6327 gen_logic_CC(tmp);
6328 }
6329 dead_tmp(tmp);
6330 break;
6331 case 0x09:
6332 if (set_cc) {
6333 tcg_gen_xor_i32(tmp, tmp, tmp2);
6334 gen_logic_CC(tmp);
6335 }
6336 dead_tmp(tmp);
6337 break;
6338 case 0x0a:
6339 if (set_cc) {
6340 gen_helper_sub_cc(tmp, tmp, tmp2);
6341 }
6342 dead_tmp(tmp);
6343 break;
6344 case 0x0b:
6345 if (set_cc) {
6346 gen_helper_add_cc(tmp, tmp, tmp2);
6347 }
6348 dead_tmp(tmp);
6349 break;
6350 case 0x0c:
6351 tcg_gen_or_i32(tmp, tmp, tmp2);
6352 if (logic_cc) {
6353 gen_logic_CC(tmp);
6354 }
6355 store_reg_bx(env, s, rd, tmp);
6356 break;
6357 case 0x0d:
6358 if (logic_cc && rd == 15) {
6359 /* MOVS r15, ... is used for exception return. */
6360 if (IS_USER(s)) {
6361 goto illegal_op;
6362 }
6363 gen_exception_return(s, tmp2);
6364 } else {
6365 if (logic_cc) {
6366 gen_logic_CC(tmp2);
6367 }
6368 store_reg_bx(env, s, rd, tmp2);
6369 }
6370 break;
6371 case 0x0e:
6372 tcg_gen_bic_i32(tmp, tmp, tmp2);
6373 if (logic_cc) {
6374 gen_logic_CC(tmp);
6375 }
6376 store_reg_bx(env, s, rd, tmp);
6377 break;
6378 default:
6379 case 0x0f:
6380 tcg_gen_not_i32(tmp2, tmp2);
6381 if (logic_cc) {
6382 gen_logic_CC(tmp2);
6383 }
6384 store_reg_bx(env, s, rd, tmp2);
6385 break;
6386 }
6387 if (op1 != 0x0f && op1 != 0x0d) {
6388 dead_tmp(tmp2);
6389 }
6390 } else {
6391 /* other instructions */
6392 op1 = (insn >> 24) & 0xf;
6393 switch(op1) {
6394 case 0x0:
6395 case 0x1:
6396 /* multiplies, extra load/stores */
6397 sh = (insn >> 5) & 3;
6398 if (sh == 0) {
6399 if (op1 == 0x0) {
6400 rd = (insn >> 16) & 0xf;
6401 rn = (insn >> 12) & 0xf;
6402 rs = (insn >> 8) & 0xf;
6403 rm = (insn) & 0xf;
6404 op1 = (insn >> 20) & 0xf;
6405 switch (op1) {
6406 case 0: case 1: case 2: case 3: case 6:
6407 /* 32 bit mul */
6408 tmp = load_reg(s, rs);
6409 tmp2 = load_reg(s, rm);
6410 tcg_gen_mul_i32(tmp, tmp, tmp2);
6411 dead_tmp(tmp2);
6412 if (insn & (1 << 22)) {
6413 /* Subtract (mls) */
6414 ARCH(6T2);
6415 tmp2 = load_reg(s, rn);
6416 tcg_gen_sub_i32(tmp, tmp2, tmp);
6417 dead_tmp(tmp2);
6418 } else if (insn & (1 << 21)) {
6419 /* Add */
6420 tmp2 = load_reg(s, rn);
6421 tcg_gen_add_i32(tmp, tmp, tmp2);
6422 dead_tmp(tmp2);
6423 }
6424 if (insn & (1 << 20))
6425 gen_logic_CC(tmp);
6426 store_reg(s, rd, tmp);
6427 break;
6428 default:
6429 /* 64 bit mul */
6430 tmp = load_reg(s, rs);
6431 tmp2 = load_reg(s, rm);
6432 if (insn & (1 << 22))
6433 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6434 else
6435 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6436 if (insn & (1 << 21)) /* mult accumulate */
6437 gen_addq(s, tmp64, rn, rd);
6438 if (!(insn & (1 << 23))) { /* double accumulate */
6439 ARCH(6);
6440 gen_addq_lo(s, tmp64, rn);
6441 gen_addq_lo(s, tmp64, rd);
6442 }
6443 if (insn & (1 << 20))
6444 gen_logicq_cc(tmp64);
6445 gen_storeq_reg(s, rn, rd, tmp64);
6446 break;
6447 }
6448 } else {
6449 rn = (insn >> 16) & 0xf;
6450 rd = (insn >> 12) & 0xf;
6451 if (insn & (1 << 23)) {
6452 /* load/store exclusive */
6453 op1 = (insn >> 21) & 0x3;
6454 if (op1)
6455 ARCH(6K);
6456 else
6457 ARCH(6);
6458 gen_movl_T1_reg(s, rn);
6459 addr = cpu_T[1];
6460 if (insn & (1 << 20)) {
6461 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
6462 switch (op1) {
6463 case 0: /* ldrex */
6464 tmp = gen_ld32(addr, IS_USER(s));
6465 break;
6466 case 1: /* ldrexd */
6467 tmp = gen_ld32(addr, IS_USER(s));
6468 store_reg(s, rd, tmp);
6469 tcg_gen_addi_i32(addr, addr, 4);
6470 tmp = gen_ld32(addr, IS_USER(s));
6471 rd++;
6472 break;
6473 case 2: /* ldrexb */
6474 tmp = gen_ld8u(addr, IS_USER(s));
6475 break;
6476 case 3: /* ldrexh */
6477 tmp = gen_ld16u(addr, IS_USER(s));
6478 break;
6479 default:
6480 abort();
6481 }
6482 store_reg(s, rd, tmp);
6483 } else {
6484 int label = gen_new_label();
6485 rm = insn & 0xf;
6486 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
6487 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
6488 0, label);
6489 tmp = load_reg(s,rm);
6490 switch (op1) {
6491 case 0: /* strex */
6492 gen_st32(tmp, addr, IS_USER(s));
6493 break;
6494 case 1: /* strexd */
6495 gen_st32(tmp, addr, IS_USER(s));
6496 tcg_gen_addi_i32(addr, addr, 4);
6497 tmp = load_reg(s, rm + 1);
6498 gen_st32(tmp, addr, IS_USER(s));
6499 break;
6500 case 2: /* strexb */
6501 gen_st8(tmp, addr, IS_USER(s));
6502 break;
6503 case 3: /* strexh */
6504 gen_st16(tmp, addr, IS_USER(s));
6505 break;
6506 default:
6507 abort();
6508 }
6509 gen_set_label(label);
6510 gen_movl_reg_T0(s, rd);
6511 }
6512 } else {
6513 /* SWP instruction */
6514 rm = (insn) & 0xf;
6515
6516 /* ??? This is not really atomic. However we know
6517 we never have multiple CPUs running in parallel,
6518 so it is good enough. */
6519 addr = load_reg(s, rn);
6520 tmp = load_reg(s, rm);
6521 if (insn & (1 << 22)) {
6522 tmp2 = gen_ld8u(addr, IS_USER(s));
6523 gen_st8(tmp, addr, IS_USER(s));
6524 } else {
6525 tmp2 = gen_ld32(addr, IS_USER(s));
6526 gen_st32(tmp, addr, IS_USER(s));
6527 }
6528 dead_tmp(addr);
6529 store_reg(s, rd, tmp2);
6530 }
6531 }
6532 } else {
6533 int address_offset;
6534 int load;
6535 /* Misc load/store */
6536 rn = (insn >> 16) & 0xf;
6537 rd = (insn >> 12) & 0xf;
6538 addr = load_reg(s, rn);
6539 if (insn & (1 << 24))
6540 gen_add_datah_offset(s, insn, 0, addr);
6541 address_offset = 0;
6542 if (insn & (1 << 20)) {
6543 /* load */
6544 switch(sh) {
6545 case 1:
6546 tmp = gen_ld16u(addr, IS_USER(s));
6547 break;
6548 case 2:
6549 tmp = gen_ld8s(addr, IS_USER(s));
6550 break;
6551 default:
6552 case 3:
6553 tmp = gen_ld16s(addr, IS_USER(s));
6554 break;
6555 }
6556 load = 1;
6557 } else if (sh & 2) {
6558 /* doubleword */
6559 if (sh & 1) {
6560 /* store */
6561 tmp = load_reg(s, rd);
6562 gen_st32(tmp, addr, IS_USER(s));
6563 tcg_gen_addi_i32(addr, addr, 4);
6564 tmp = load_reg(s, rd + 1);
6565 gen_st32(tmp, addr, IS_USER(s));
6566 load = 0;
6567 } else {
6568 /* load */
6569 tmp = gen_ld32(addr, IS_USER(s));
6570 store_reg(s, rd, tmp);
6571 tcg_gen_addi_i32(addr, addr, 4);
6572 tmp = gen_ld32(addr, IS_USER(s));
6573 rd++;
6574 load = 1;
6575 }
6576 address_offset = -4;
6577 } else {
6578 /* store */
6579 tmp = load_reg(s, rd);
6580 gen_st16(tmp, addr, IS_USER(s));
6581 load = 0;
6582 }
6583 /* Perform base writeback before the loaded value to
6584 ensure correct behavior with overlapping index registers.
6585 ldrd with base writeback is is undefined if the
6586 destination and index registers overlap. */
6587 if (!(insn & (1 << 24))) {
6588 gen_add_datah_offset(s, insn, address_offset, addr);
6589 store_reg(s, rn, addr);
6590 } else if (insn & (1 << 21)) {
6591 if (address_offset)
6592 tcg_gen_addi_i32(addr, addr, address_offset);
6593 store_reg(s, rn, addr);
6594 } else {
6595 dead_tmp(addr);
6596 }
6597 if (load) {
6598 /* Complete the load. */
6599 store_reg(s, rd, tmp);
6600 }
6601 }
6602 break;
6603 case 0x4:
6604 case 0x5:
6605 goto do_ldst;
6606 case 0x6:
6607 case 0x7:
6608 if (insn & (1 << 4)) {
6609 ARCH(6);
6610 /* Armv6 Media instructions. */
6611 rm = insn & 0xf;
6612 rn = (insn >> 16) & 0xf;
6613 rd = (insn >> 12) & 0xf;
6614 rs = (insn >> 8) & 0xf;
6615 switch ((insn >> 23) & 3) {
6616 case 0: /* Parallel add/subtract. */
6617 op1 = (insn >> 20) & 7;
6618 tmp = load_reg(s, rn);
6619 tmp2 = load_reg(s, rm);
6620 sh = (insn >> 5) & 7;
6621 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6622 goto illegal_op;
6623 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6624 dead_tmp(tmp2);
6625 store_reg(s, rd, tmp);
6626 break;
6627 case 1:
6628 if ((insn & 0x00700020) == 0) {
6629 /* Halfword pack. */
6630 tmp = load_reg(s, rn);
6631 tmp2 = load_reg(s, rm);
6632 shift = (insn >> 7) & 0x1f;
6633 if (insn & (1 << 6)) {
6634 /* pkhtb */
6635 if (shift == 0)
6636 shift = 31;
6637 tcg_gen_sari_i32(tmp2, tmp2, shift);
6638 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6639 tcg_gen_ext16u_i32(tmp2, tmp2);
6640 } else {
6641 /* pkhbt */
6642 if (shift)
6643 tcg_gen_shli_i32(tmp2, tmp2, shift);
6644 tcg_gen_ext16u_i32(tmp, tmp);
6645 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6646 }
6647 tcg_gen_or_i32(tmp, tmp, tmp2);
6648 dead_tmp(tmp2);
6649 store_reg(s, rd, tmp);
6650 } else if ((insn & 0x00200020) == 0x00200000) {
6651 /* [us]sat */
6652 tmp = load_reg(s, rm);
6653 shift = (insn >> 7) & 0x1f;
6654 if (insn & (1 << 6)) {
6655 if (shift == 0)
6656 shift = 31;
6657 tcg_gen_sari_i32(tmp, tmp, shift);
6658 } else {
6659 tcg_gen_shli_i32(tmp, tmp, shift);
6660 }
6661 sh = (insn >> 16) & 0x1f;
6662 if (sh != 0) {
6663 if (insn & (1 << 22))
6664 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6665 else
6666 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6667 }
6668 store_reg(s, rd, tmp);
6669 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6670 /* [us]sat16 */
6671 tmp = load_reg(s, rm);
6672 sh = (insn >> 16) & 0x1f;
6673 if (sh != 0) {
6674 if (insn & (1 << 22))
6675 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6676 else
6677 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6678 }
6679 store_reg(s, rd, tmp);
6680 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6681 /* Select bytes. */
6682 tmp = load_reg(s, rn);
6683 tmp2 = load_reg(s, rm);
6684 tmp3 = new_tmp();
6685 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6686 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6687 dead_tmp(tmp3);
6688 dead_tmp(tmp2);
6689 store_reg(s, rd, tmp);
6690 } else if ((insn & 0x000003e0) == 0x00000060) {
6691 tmp = load_reg(s, rm);
6692 shift = (insn >> 10) & 3;
6693 /* ??? In many cases it's not neccessary to do a
6694 rotate, a shift is sufficient. */
6695 if (shift != 0)
6696 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6697 op1 = (insn >> 20) & 7;
6698 switch (op1) {
6699 case 0: gen_sxtb16(tmp); break;
6700 case 2: gen_sxtb(tmp); break;
6701 case 3: gen_sxth(tmp); break;
6702 case 4: gen_uxtb16(tmp); break;
6703 case 6: gen_uxtb(tmp); break;
6704 case 7: gen_uxth(tmp); break;
6705 default: goto illegal_op;
6706 }
6707 if (rn != 15) {
6708 tmp2 = load_reg(s, rn);
6709 if ((op1 & 3) == 0) {
6710 gen_add16(tmp, tmp2);
6711 } else {
6712 tcg_gen_add_i32(tmp, tmp, tmp2);
6713 dead_tmp(tmp2);
6714 }
6715 }
6716 store_reg(s, rd, tmp);
6717 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6718 /* rev */
6719 tmp = load_reg(s, rm);
6720 if (insn & (1 << 22)) {
6721 if (insn & (1 << 7)) {
6722 gen_revsh(tmp);
6723 } else {
6724 ARCH(6T2);
6725 gen_helper_rbit(tmp, tmp);
6726 }
6727 } else {
6728 if (insn & (1 << 7))
6729 gen_rev16(tmp);
6730 else
6731 tcg_gen_bswap32_i32(tmp, tmp);
6732 }
6733 store_reg(s, rd, tmp);
6734 } else {
6735 goto illegal_op;
6736 }
6737 break;
6738 case 2: /* Multiplies (Type 3). */
6739 tmp = load_reg(s, rm);
6740 tmp2 = load_reg(s, rs);
6741 if (insn & (1 << 20)) {
6742 /* Signed multiply most significant [accumulate]. */
6743 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6744 if (insn & (1 << 5))
6745 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6746 tcg_gen_shri_i64(tmp64, tmp64, 32);
6747 tmp = new_tmp();
6748 tcg_gen_trunc_i64_i32(tmp, tmp64);
6749 if (rd != 15) {
6750 tmp2 = load_reg(s, rd);
6751 if (insn & (1 << 6)) {
6752 tcg_gen_sub_i32(tmp, tmp, tmp2);
6753 } else {
6754 tcg_gen_add_i32(tmp, tmp, tmp2);
6755 }
6756 dead_tmp(tmp2);
6757 }
6758 store_reg(s, rn, tmp);
6759 } else {
6760 if (insn & (1 << 5))
6761 gen_swap_half(tmp2);
6762 gen_smul_dual(tmp, tmp2);
6763 /* This addition cannot overflow. */
6764 if (insn & (1 << 6)) {
6765 tcg_gen_sub_i32(tmp, tmp, tmp2);
6766 } else {
6767 tcg_gen_add_i32(tmp, tmp, tmp2);
6768 }
6769 dead_tmp(tmp2);
6770 if (insn & (1 << 22)) {
6771 /* smlald, smlsld */
6772 tmp64 = tcg_temp_new_i64();
6773 tcg_gen_ext_i32_i64(tmp64, tmp);
6774 dead_tmp(tmp);
6775 gen_addq(s, tmp64, rd, rn);
6776 gen_storeq_reg(s, rd, rn, tmp64);
6777 } else {
6778 /* smuad, smusd, smlad, smlsd */
6779 if (rd != 15)
6780 {
6781 tmp2 = load_reg(s, rd);
6782 gen_helper_add_setq(tmp, tmp, tmp2);
6783 dead_tmp(tmp2);
6784 }
6785 store_reg(s, rn, tmp);
6786 }
6787 }
6788 break;
6789 case 3:
6790 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6791 switch (op1) {
6792 case 0: /* Unsigned sum of absolute differences. */
6793 ARCH(6);
6794 tmp = load_reg(s, rm);
6795 tmp2 = load_reg(s, rs);
6796 gen_helper_usad8(tmp, tmp, tmp2);
6797 dead_tmp(tmp2);
6798 if (rd != 15) {
6799 tmp2 = load_reg(s, rd);
6800 tcg_gen_add_i32(tmp, tmp, tmp2);
6801 dead_tmp(tmp2);
6802 }
6803 store_reg(s, rn, tmp);
6804 break;
6805 case 0x20: case 0x24: case 0x28: case 0x2c:
6806 /* Bitfield insert/clear. */
6807 ARCH(6T2);
6808 shift = (insn >> 7) & 0x1f;
6809 i = (insn >> 16) & 0x1f;
6810 i = i + 1 - shift;
6811 if (rm == 15) {
6812 tmp = new_tmp();
6813 tcg_gen_movi_i32(tmp, 0);
6814 } else {
6815 tmp = load_reg(s, rm);
6816 }
6817 if (i != 32) {
6818 tmp2 = load_reg(s, rd);
6819 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6820 dead_tmp(tmp2);
6821 }
6822 store_reg(s, rd, tmp);
6823 break;
6824 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6825 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6826 ARCH(6T2);
6827 tmp = load_reg(s, rm);
6828 shift = (insn >> 7) & 0x1f;
6829 i = ((insn >> 16) & 0x1f) + 1;
6830 if (shift + i > 32)
6831 goto illegal_op;
6832 if (i < 32) {
6833 if (op1 & 0x20) {
6834 gen_ubfx(tmp, shift, (1u << i) - 1);
6835 } else {
6836 gen_sbfx(tmp, shift, i);
6837 }
6838 }
6839 store_reg(s, rd, tmp);
6840 break;
6841 default:
6842 goto illegal_op;
6843 }
6844 break;
6845 }
6846 break;
6847 }
6848 do_ldst:
6849 /* Check for undefined extension instructions
6850 * per the ARM Bible IE:
6851 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6852 */
6853 sh = (0xf << 20) | (0xf << 4);
6854 if (op1 == 0x7 && ((insn & sh) == sh))
6855 {
6856 goto illegal_op;
6857 }
6858 /* load/store byte/word */
6859 rn = (insn >> 16) & 0xf;
6860 rd = (insn >> 12) & 0xf;
6861 tmp2 = load_reg(s, rn);
6862 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6863 if (insn & (1 << 24))
6864 gen_add_data_offset(s, insn, tmp2);
6865 if (insn & (1 << 20)) {
6866 /* load */
6867 if (insn & (1 << 22)) {
6868 tmp = gen_ld8u(tmp2, i);
6869 } else {
6870 tmp = gen_ld32(tmp2, i);
6871 }
6872 } else {
6873 /* store */
6874 tmp = load_reg(s, rd);
6875 if (insn & (1 << 22))
6876 gen_st8(tmp, tmp2, i);
6877 else
6878 gen_st32(tmp, tmp2, i);
6879 }
6880 if (!(insn & (1 << 24))) {
6881 gen_add_data_offset(s, insn, tmp2);
6882 store_reg(s, rn, tmp2);
6883 } else if (insn & (1 << 21)) {
6884 store_reg(s, rn, tmp2);
6885 } else {
6886 dead_tmp(tmp2);
6887 }
6888 if (insn & (1 << 20)) {
6889 /* Complete the load. */
6890 if (rd == 15)
6891 gen_bx(s, tmp);
6892 else
6893 store_reg(s, rd, tmp);
6894 }
6895 break;
6896 case 0x08:
6897 case 0x09:
6898 {
6899 int j, n, user, loaded_base;
6900 TCGv loaded_var;
6901 /* load/store multiple words */
6902 /* XXX: store correct base if write back */
6903 user = 0;
6904 if (insn & (1 << 22)) {
6905 if (IS_USER(s))
6906 goto illegal_op; /* only usable in supervisor mode */
6907
6908 if ((insn & (1 << 15)) == 0)
6909 user = 1;
6910 }
6911 rn = (insn >> 16) & 0xf;
6912 addr = load_reg(s, rn);
6913
6914 /* compute total size */
6915 loaded_base = 0;
6916 TCGV_UNUSED(loaded_var);
6917 n = 0;
6918 for(i=0;i<16;i++) {
6919 if (insn & (1 << i))
6920 n++;
6921 }
6922 /* XXX: test invalid n == 0 case ? */
6923 if (insn & (1 << 23)) {
6924 if (insn & (1 << 24)) {
6925 /* pre increment */
6926 tcg_gen_addi_i32(addr, addr, 4);
6927 } else {
6928 /* post increment */
6929 }
6930 } else {
6931 if (insn & (1 << 24)) {
6932 /* pre decrement */
6933 tcg_gen_addi_i32(addr, addr, -(n * 4));
6934 } else {
6935 /* post decrement */
6936 if (n != 1)
6937 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6938 }
6939 }
6940 j = 0;
6941 for(i=0;i<16;i++) {
6942 if (insn & (1 << i)) {
6943 if (insn & (1 << 20)) {
6944 /* load */
6945 tmp = gen_ld32(addr, IS_USER(s));
6946 if (i == 15) {
6947 gen_bx(s, tmp);
6948 } else if (user) {
6949 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6950 dead_tmp(tmp);
6951 } else if (i == rn) {
6952 loaded_var = tmp;
6953 loaded_base = 1;
6954 } else {
6955 store_reg(s, i, tmp);
6956 }
6957 } else {
6958 /* store */
6959 if (i == 15) {
6960 /* special case: r15 = PC + 8 */
6961 val = (long)s->pc + 4;
6962 tmp = new_tmp();
6963 tcg_gen_movi_i32(tmp, val);
6964 } else if (user) {
6965 tmp = new_tmp();
6966 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6967 } else {
6968 tmp = load_reg(s, i);
6969 }
6970 gen_st32(tmp, addr, IS_USER(s));
6971 }
6972 j++;
6973 /* no need to add after the last transfer */
6974 if (j != n)
6975 tcg_gen_addi_i32(addr, addr, 4);
6976 }
6977 }
6978 if (insn & (1 << 21)) {
6979 /* write back */
6980 if (insn & (1 << 23)) {
6981 if (insn & (1 << 24)) {
6982 /* pre increment */
6983 } else {
6984 /* post increment */
6985 tcg_gen_addi_i32(addr, addr, 4);
6986 }
6987 } else {
6988 if (insn & (1 << 24)) {
6989 /* pre decrement */
6990 if (n != 1)
6991 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6992 } else {
6993 /* post decrement */
6994 tcg_gen_addi_i32(addr, addr, -(n * 4));
6995 }
6996 }
6997 store_reg(s, rn, addr);
6998 } else {
6999 dead_tmp(addr);
7000 }
7001 if (loaded_base) {
7002 store_reg(s, rn, loaded_var);
7003 }
7004 if ((insn & (1 << 22)) && !user) {
7005 /* Restore CPSR from SPSR. */
7006 tmp = load_cpu_field(spsr);
7007 gen_set_cpsr(tmp, 0xffffffff);
7008 dead_tmp(tmp);
7009 s->is_jmp = DISAS_UPDATE;
7010 }
7011 }
7012 break;
7013 case 0xa:
7014 case 0xb:
7015 {
7016 int32_t offset;
7017
7018 /* branch (and link) */
7019 val = (int32_t)s->pc;
7020 if (insn & (1 << 24)) {
7021 tmp = new_tmp();
7022 tcg_gen_movi_i32(tmp, val);
7023 store_reg(s, 14, tmp);
7024 }
7025 offset = (((int32_t)insn << 8) >> 8);
7026 val += (offset << 2) + 4;
7027 gen_jmp(s, val);
7028 }
7029 break;
7030 case 0xc:
7031 case 0xd:
7032 case 0xe:
7033 /* Coprocessor. */
7034 if (disas_coproc_insn(env, s, insn))
7035 goto illegal_op;
7036 break;
7037 case 0xf:
7038 /* swi */
7039 gen_set_pc_im(s->pc);
7040 s->is_jmp = DISAS_SWI;
7041 break;
7042 default:
7043 illegal_op:
7044 gen_set_condexec(s);
7045 gen_set_pc_im(s->pc - 4);
7046 gen_exception(EXCP_UDEF);
7047 s->is_jmp = DISAS_JUMP;
7048 break;
7049 }
7050 }
7051 }
7052
7053 /* Return true if this is a Thumb-2 logical op. */
7054 static int
7055 thumb2_logic_op(int op)
7056 {
7057 return (op < 8);
7058 }
7059
7060 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7061 then set condition code flags based on the result of the operation.
7062 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7063 to the high bit of T1.
7064 Returns zero if the opcode is valid. */
7065
7066 static int
7067 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
7068 {
7069 int logic_cc;
7070
7071 logic_cc = 0;
7072 switch (op) {
7073 case 0: /* and */
7074 gen_op_andl_T0_T1();
7075 logic_cc = conds;
7076 break;
7077 case 1: /* bic */
7078 gen_op_bicl_T0_T1();
7079 logic_cc = conds;
7080 break;
7081 case 2: /* orr */
7082 gen_op_orl_T0_T1();
7083 logic_cc = conds;
7084 break;
7085 case 3: /* orn */
7086 gen_op_notl_T1();
7087 gen_op_orl_T0_T1();
7088 logic_cc = conds;
7089 break;
7090 case 4: /* eor */
7091 gen_op_xorl_T0_T1();
7092 logic_cc = conds;
7093 break;
7094 case 8: /* add */
7095 if (conds)
7096 gen_op_addl_T0_T1_cc();
7097 else
7098 gen_op_addl_T0_T1();
7099 break;
7100 case 10: /* adc */
7101 if (conds)
7102 gen_op_adcl_T0_T1_cc();
7103 else
7104 gen_adc_T0_T1();
7105 break;
7106 case 11: /* sbc */
7107 if (conds)
7108 gen_op_sbcl_T0_T1_cc();
7109 else
7110 gen_sbc_T0_T1();
7111 break;
7112 case 13: /* sub */
7113 if (conds)
7114 gen_op_subl_T0_T1_cc();
7115 else
7116 gen_op_subl_T0_T1();
7117 break;
7118 case 14: /* rsb */
7119 if (conds)
7120 gen_op_rsbl_T0_T1_cc();
7121 else
7122 gen_op_rsbl_T0_T1();
7123 break;
7124 default: /* 5, 6, 7, 9, 12, 15. */
7125 return 1;
7126 }
7127 if (logic_cc) {
7128 gen_op_logic_T0_cc();
7129 if (shifter_out)
7130 gen_set_CF_bit31(cpu_T[1]);
7131 }
7132 return 0;
7133 }
7134
7135 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7136 is not legal. */
7137 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7138 {
7139 uint32_t insn, imm, shift, offset;
7140 uint32_t rd, rn, rm, rs;
7141 TCGv tmp;
7142 TCGv tmp2;
7143 TCGv tmp3;
7144 TCGv addr;
7145 TCGv_i64 tmp64;
7146 int op;
7147 int shiftop;
7148 int conds;
7149 int logic_cc;
7150
7151 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7152 || arm_feature (env, ARM_FEATURE_M))) {
7153 /* Thumb-1 cores may need to treat bl and blx as a pair of
7154 16-bit instructions to get correct prefetch abort behavior. */
7155 insn = insn_hw1;
7156 if ((insn & (1 << 12)) == 0) {
7157 /* Second half of blx. */
7158 offset = ((insn & 0x7ff) << 1);
7159 tmp = load_reg(s, 14);
7160 tcg_gen_addi_i32(tmp, tmp, offset);
7161 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7162
7163 tmp2 = new_tmp();
7164 tcg_gen_movi_i32(tmp2, s->pc | 1);
7165 store_reg(s, 14, tmp2);
7166 gen_bx(s, tmp);
7167 return 0;
7168 }
7169 if (insn & (1 << 11)) {
7170 /* Second half of bl. */
7171 offset = ((insn & 0x7ff) << 1) | 1;
7172 tmp = load_reg(s, 14);
7173 tcg_gen_addi_i32(tmp, tmp, offset);
7174
7175 tmp2 = new_tmp();
7176 tcg_gen_movi_i32(tmp2, s->pc | 1);
7177 store_reg(s, 14, tmp2);
7178 gen_bx(s, tmp);
7179 return 0;
7180 }
7181 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7182 /* Instruction spans a page boundary. Implement it as two
7183 16-bit instructions in case the second half causes an
7184 prefetch abort. */
7185 offset = ((int32_t)insn << 21) >> 9;
7186 gen_op_movl_T0_im(s->pc + 2 + offset);
7187 gen_movl_reg_T0(s, 14);
7188 return 0;
7189 }
7190 /* Fall through to 32-bit decode. */
7191 }
7192
7193 insn = lduw_code(s->pc);
7194 s->pc += 2;
7195 insn |= (uint32_t)insn_hw1 << 16;
7196
7197 if ((insn & 0xf800e800) != 0xf000e800) {
7198 ARCH(6T2);
7199 }
7200
7201 rn = (insn >> 16) & 0xf;
7202 rs = (insn >> 12) & 0xf;
7203 rd = (insn >> 8) & 0xf;
7204 rm = insn & 0xf;
7205 switch ((insn >> 25) & 0xf) {
7206 case 0: case 1: case 2: case 3:
7207 /* 16-bit instructions. Should never happen. */
7208 abort();
7209 case 4:
7210 if (insn & (1 << 22)) {
7211 /* Other load/store, table branch. */
7212 if (insn & 0x01200000) {
7213 /* Load/store doubleword. */
7214 if (rn == 15) {
7215 addr = new_tmp();
7216 tcg_gen_movi_i32(addr, s->pc & ~3);
7217 } else {
7218 addr = load_reg(s, rn);
7219 }
7220 offset = (insn & 0xff) * 4;
7221 if ((insn & (1 << 23)) == 0)
7222 offset = -offset;
7223 if (insn & (1 << 24)) {
7224 tcg_gen_addi_i32(addr, addr, offset);
7225 offset = 0;
7226 }
7227 if (insn & (1 << 20)) {
7228 /* ldrd */
7229 tmp = gen_ld32(addr, IS_USER(s));
7230 store_reg(s, rs, tmp);
7231 tcg_gen_addi_i32(addr, addr, 4);
7232 tmp = gen_ld32(addr, IS_USER(s));
7233 store_reg(s, rd, tmp);
7234 } else {
7235 /* strd */
7236 tmp = load_reg(s, rs);
7237 gen_st32(tmp, addr, IS_USER(s));
7238 tcg_gen_addi_i32(addr, addr, 4);
7239 tmp = load_reg(s, rd);
7240 gen_st32(tmp, addr, IS_USER(s));
7241 }
7242 if (insn & (1 << 21)) {
7243 /* Base writeback. */
7244 if (rn == 15)
7245 goto illegal_op;
7246 tcg_gen_addi_i32(addr, addr, offset - 4);
7247 store_reg(s, rn, addr);
7248 } else {
7249 dead_tmp(addr);
7250 }
7251 } else if ((insn & (1 << 23)) == 0) {
7252 /* Load/store exclusive word. */
7253 gen_movl_T1_reg(s, rn);
7254 addr = cpu_T[1];
7255 if (insn & (1 << 20)) {
7256 gen_helper_mark_exclusive(cpu_env, cpu_T[1]);
7257 tmp = gen_ld32(addr, IS_USER(s));
7258 store_reg(s, rd, tmp);
7259 } else {
7260 int label = gen_new_label();
7261 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7262 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0],
7263 0, label);
7264 tmp = load_reg(s, rs);
7265 gen_st32(tmp, cpu_T[1], IS_USER(s));
7266 gen_set_label(label);
7267 gen_movl_reg_T0(s, rd);
7268 }
7269 } else if ((insn & (1 << 6)) == 0) {
7270 /* Table Branch. */
7271 if (rn == 15) {
7272 addr = new_tmp();
7273 tcg_gen_movi_i32(addr, s->pc);
7274 } else {
7275 addr = load_reg(s, rn);
7276 }
7277 tmp = load_reg(s, rm);
7278 tcg_gen_add_i32(addr, addr, tmp);
7279 if (insn & (1 << 4)) {
7280 /* tbh */
7281 tcg_gen_add_i32(addr, addr, tmp);
7282 dead_tmp(tmp);
7283 tmp = gen_ld16u(addr, IS_USER(s));
7284 } else { /* tbb */
7285 dead_tmp(tmp);
7286 tmp = gen_ld8u(addr, IS_USER(s));
7287 }
7288 dead_tmp(addr);
7289 tcg_gen_shli_i32(tmp, tmp, 1);
7290 tcg_gen_addi_i32(tmp, tmp, s->pc);
7291 store_reg(s, 15, tmp);
7292 } else {
7293 /* Load/store exclusive byte/halfword/doubleword. */
7294 /* ??? These are not really atomic. However we know
7295 we never have multiple CPUs running in parallel,
7296 so it is good enough. */
7297 op = (insn >> 4) & 0x3;
7298 /* Must use a global reg for the address because we have
7299 a conditional branch in the store instruction. */
7300 gen_movl_T1_reg(s, rn);
7301 addr = cpu_T[1];
7302 if (insn & (1 << 20)) {
7303 gen_helper_mark_exclusive(cpu_env, addr);
7304 switch (op) {
7305 case 0:
7306 tmp = gen_ld8u(addr, IS_USER(s));
7307 break;
7308 case 1:
7309 tmp = gen_ld16u(addr, IS_USER(s));
7310 break;
7311 case 3:
7312 tmp = gen_ld32(addr, IS_USER(s));
7313 tcg_gen_addi_i32(addr, addr, 4);
7314 tmp2 = gen_ld32(addr, IS_USER(s));
7315 store_reg(s, rd, tmp2);
7316 break;
7317 default:
7318 goto illegal_op;
7319 }
7320 store_reg(s, rs, tmp);
7321 } else {
7322 int label = gen_new_label();
7323 /* Must use a global that is not killed by the branch. */
7324 gen_helper_test_exclusive(cpu_T[0], cpu_env, addr);
7325 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], 0, label);
7326 tmp = load_reg(s, rs);
7327 switch (op) {
7328 case 0:
7329 gen_st8(tmp, addr, IS_USER(s));
7330 break;
7331 case 1:
7332 gen_st16(tmp, addr, IS_USER(s));
7333 break;
7334 case 3:
7335 gen_st32(tmp, addr, IS_USER(s));
7336 tcg_gen_addi_i32(addr, addr, 4);
7337 tmp = load_reg(s, rd);
7338 gen_st32(tmp, addr, IS_USER(s));
7339 break;
7340 default:
7341 goto illegal_op;
7342 }
7343 gen_set_label(label);
7344 gen_movl_reg_T0(s, rm);
7345 }
7346 }
7347 } else {
7348 /* Load/store multiple, RFE, SRS. */
7349 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7350 /* Not available in user mode. */
7351 if (IS_USER(s))
7352 goto illegal_op;
7353 if (insn & (1 << 20)) {
7354 /* rfe */
7355 addr = load_reg(s, rn);
7356 if ((insn & (1 << 24)) == 0)
7357 tcg_gen_addi_i32(addr, addr, -8);
7358 /* Load PC into tmp and CPSR into tmp2. */
7359 tmp = gen_ld32(addr, 0);
7360 tcg_gen_addi_i32(addr, addr, 4);
7361 tmp2 = gen_ld32(addr, 0);
7362 if (insn & (1 << 21)) {
7363 /* Base writeback. */
7364 if (insn & (1 << 24)) {
7365 tcg_gen_addi_i32(addr, addr, 4);
7366 } else {
7367 tcg_gen_addi_i32(addr, addr, -4);
7368 }
7369 store_reg(s, rn, addr);
7370 } else {
7371 dead_tmp(addr);
7372 }
7373 gen_rfe(s, tmp, tmp2);
7374 } else {
7375 /* srs */
7376 op = (insn & 0x1f);
7377 if (op == (env->uncached_cpsr & CPSR_M)) {
7378 addr = load_reg(s, 13);
7379 } else {
7380 addr = new_tmp();
7381 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7382 }
7383 if ((insn & (1 << 24)) == 0) {
7384 tcg_gen_addi_i32(addr, addr, -8);
7385 }
7386 tmp = load_reg(s, 14);
7387 gen_st32(tmp, addr, 0);
7388 tcg_gen_addi_i32(addr, addr, 4);
7389 tmp = new_tmp();
7390 gen_helper_cpsr_read(tmp);
7391 gen_st32(tmp, addr, 0);
7392 if (insn & (1 << 21)) {
7393 if ((insn & (1 << 24)) == 0) {
7394 tcg_gen_addi_i32(addr, addr, -4);
7395 } else {
7396 tcg_gen_addi_i32(addr, addr, 4);
7397 }
7398 if (op == (env->uncached_cpsr & CPSR_M)) {
7399 store_reg(s, 13, addr);
7400 } else {
7401 gen_helper_set_r13_banked(cpu_env,
7402 tcg_const_i32(op), addr);
7403 }
7404 } else {
7405 dead_tmp(addr);
7406 }
7407 }
7408 } else {
7409 int i;
7410 /* Load/store multiple. */
7411 addr = load_reg(s, rn);
7412 offset = 0;
7413 for (i = 0; i < 16; i++) {
7414 if (insn & (1 << i))
7415 offset += 4;
7416 }
7417 if (insn & (1 << 24)) {
7418 tcg_gen_addi_i32(addr, addr, -offset);
7419 }
7420
7421 for (i = 0; i < 16; i++) {
7422 if ((insn & (1 << i)) == 0)
7423 continue;
7424 if (insn & (1 << 20)) {
7425 /* Load. */
7426 tmp = gen_ld32(addr, IS_USER(s));
7427 if (i == 15) {
7428 gen_bx(s, tmp);
7429 } else {
7430 store_reg(s, i, tmp);
7431 }
7432 } else {
7433 /* Store. */
7434 tmp = load_reg(s, i);
7435 gen_st32(tmp, addr, IS_USER(s));
7436 }
7437 tcg_gen_addi_i32(addr, addr, 4);
7438 }
7439 if (insn & (1 << 21)) {
7440 /* Base register writeback. */
7441 if (insn & (1 << 24)) {
7442 tcg_gen_addi_i32(addr, addr, -offset);
7443 }
7444 /* Fault if writeback register is in register list. */
7445 if (insn & (1 << rn))
7446 goto illegal_op;
7447 store_reg(s, rn, addr);
7448 } else {
7449 dead_tmp(addr);
7450 }
7451 }
7452 }
7453 break;
7454 case 5: /* Data processing register constant shift. */
7455 if (rn == 15)
7456 gen_op_movl_T0_im(0);
7457 else
7458 gen_movl_T0_reg(s, rn);
7459 gen_movl_T1_reg(s, rm);
7460 op = (insn >> 21) & 0xf;
7461 shiftop = (insn >> 4) & 3;
7462 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7463 conds = (insn & (1 << 20)) != 0;
7464 logic_cc = (conds && thumb2_logic_op(op));
7465 gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
7466 if (gen_thumb2_data_op(s, op, conds, 0))
7467 goto illegal_op;
7468 if (rd != 15)
7469 gen_movl_reg_T0(s, rd);
7470 break;
7471 case 13: /* Misc data processing. */
7472 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7473 if (op < 4 && (insn & 0xf000) != 0xf000)
7474 goto illegal_op;
7475 switch (op) {
7476 case 0: /* Register controlled shift. */
7477 tmp = load_reg(s, rn);
7478 tmp2 = load_reg(s, rm);
7479 if ((insn & 0x70) != 0)
7480 goto illegal_op;
7481 op = (insn >> 21) & 3;
7482 logic_cc = (insn & (1 << 20)) != 0;
7483 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7484 if (logic_cc)
7485 gen_logic_CC(tmp);
7486 store_reg_bx(env, s, rd, tmp);
7487 break;
7488 case 1: /* Sign/zero extend. */
7489 tmp = load_reg(s, rm);
7490 shift = (insn >> 4) & 3;
7491 /* ??? In many cases it's not neccessary to do a
7492 rotate, a shift is sufficient. */
7493 if (shift != 0)
7494 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7495 op = (insn >> 20) & 7;
7496 switch (op) {
7497 case 0: gen_sxth(tmp); break;
7498 case 1: gen_uxth(tmp); break;
7499 case 2: gen_sxtb16(tmp); break;
7500 case 3: gen_uxtb16(tmp); break;
7501 case 4: gen_sxtb(tmp); break;
7502 case 5: gen_uxtb(tmp); break;
7503 default: goto illegal_op;
7504 }
7505 if (rn != 15) {
7506 tmp2 = load_reg(s, rn);
7507 if ((op >> 1) == 1) {
7508 gen_add16(tmp, tmp2);
7509 } else {
7510 tcg_gen_add_i32(tmp, tmp, tmp2);
7511 dead_tmp(tmp2);
7512 }
7513 }
7514 store_reg(s, rd, tmp);
7515 break;
7516 case 2: /* SIMD add/subtract. */
7517 op = (insn >> 20) & 7;
7518 shift = (insn >> 4) & 7;
7519 if ((op & 3) == 3 || (shift & 3) == 3)
7520 goto illegal_op;
7521 tmp = load_reg(s, rn);
7522 tmp2 = load_reg(s, rm);
7523 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7524 dead_tmp(tmp2);
7525 store_reg(s, rd, tmp);
7526 break;
7527 case 3: /* Other data processing. */
7528 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7529 if (op < 4) {
7530 /* Saturating add/subtract. */
7531 tmp = load_reg(s, rn);
7532 tmp2 = load_reg(s, rm);
7533 if (op & 2)
7534 gen_helper_double_saturate(tmp, tmp);
7535 if (op & 1)
7536 gen_helper_sub_saturate(tmp, tmp2, tmp);
7537 else
7538 gen_helper_add_saturate(tmp, tmp, tmp2);
7539 dead_tmp(tmp2);
7540 } else {
7541 tmp = load_reg(s, rn);
7542 switch (op) {
7543 case 0x0a: /* rbit */
7544 gen_helper_rbit(tmp, tmp);
7545 break;
7546 case 0x08: /* rev */
7547 tcg_gen_bswap32_i32(tmp, tmp);
7548 break;
7549 case 0x09: /* rev16 */
7550 gen_rev16(tmp);
7551 break;
7552 case 0x0b: /* revsh */
7553 gen_revsh(tmp);
7554 break;
7555 case 0x10: /* sel */
7556 tmp2 = load_reg(s, rm);
7557 tmp3 = new_tmp();
7558 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7559 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7560 dead_tmp(tmp3);
7561 dead_tmp(tmp2);
7562 break;
7563 case 0x18: /* clz */
7564 gen_helper_clz(tmp, tmp);
7565 break;
7566 default:
7567 goto illegal_op;
7568 }
7569 }
7570 store_reg(s, rd, tmp);
7571 break;
7572 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7573 op = (insn >> 4) & 0xf;
7574 tmp = load_reg(s, rn);
7575 tmp2 = load_reg(s, rm);
7576 switch ((insn >> 20) & 7) {
7577 case 0: /* 32 x 32 -> 32 */
7578 tcg_gen_mul_i32(tmp, tmp, tmp2);
7579 dead_tmp(tmp2);
7580 if (rs != 15) {
7581 tmp2 = load_reg(s, rs);
7582 if (op)
7583 tcg_gen_sub_i32(tmp, tmp2, tmp);
7584 else
7585 tcg_gen_add_i32(tmp, tmp, tmp2);
7586 dead_tmp(tmp2);
7587 }
7588 break;
7589 case 1: /* 16 x 16 -> 32 */
7590 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7591 dead_tmp(tmp2);
7592 if (rs != 15) {
7593 tmp2 = load_reg(s, rs);
7594 gen_helper_add_setq(tmp, tmp, tmp2);
7595 dead_tmp(tmp2);
7596 }
7597 break;
7598 case 2: /* Dual multiply add. */
7599 case 4: /* Dual multiply subtract. */
7600 if (op)
7601 gen_swap_half(tmp2);
7602 gen_smul_dual(tmp, tmp2);
7603 /* This addition cannot overflow. */
7604 if (insn & (1 << 22)) {
7605 tcg_gen_sub_i32(tmp, tmp, tmp2);
7606 } else {
7607 tcg_gen_add_i32(tmp, tmp, tmp2);
7608 }
7609 dead_tmp(tmp2);
7610 if (rs != 15)
7611 {
7612 tmp2 = load_reg(s, rs);
7613 gen_helper_add_setq(tmp, tmp, tmp2);
7614 dead_tmp(tmp2);
7615 }
7616 break;
7617 case 3: /* 32 * 16 -> 32msb */
7618 if (op)
7619 tcg_gen_sari_i32(tmp2, tmp2, 16);
7620 else
7621 gen_sxth(tmp2);
7622 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7623 tcg_gen_shri_i64(tmp64, tmp64, 16);
7624 tmp = new_tmp();
7625 tcg_gen_trunc_i64_i32(tmp, tmp64);
7626 if (rs != 15)
7627 {
7628 tmp2 = load_reg(s, rs);
7629 gen_helper_add_setq(tmp, tmp, tmp2);
7630 dead_tmp(tmp2);
7631 }
7632 break;
7633 case 5: case 6: /* 32 * 32 -> 32msb */
7634 gen_imull(tmp, tmp2);
7635 if (insn & (1 << 5)) {
7636 gen_roundqd(tmp, tmp2);
7637 dead_tmp(tmp2);
7638 } else {
7639 dead_tmp(tmp);
7640 tmp = tmp2;
7641 }
7642 if (rs != 15) {
7643 tmp2 = load_reg(s, rs);
7644 if (insn & (1 << 21)) {
7645 tcg_gen_add_i32(tmp, tmp, tmp2);
7646 } else {
7647 tcg_gen_sub_i32(tmp, tmp2, tmp);
7648 }
7649 dead_tmp(tmp2);
7650 }
7651 break;
7652 case 7: /* Unsigned sum of absolute differences. */
7653 gen_helper_usad8(tmp, tmp, tmp2);
7654 dead_tmp(tmp2);
7655 if (rs != 15) {
7656 tmp2 = load_reg(s, rs);
7657 tcg_gen_add_i32(tmp, tmp, tmp2);
7658 dead_tmp(tmp2);
7659 }
7660 break;
7661 }
7662 store_reg(s, rd, tmp);
7663 break;
7664 case 6: case 7: /* 64-bit multiply, Divide. */
7665 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7666 tmp = load_reg(s, rn);
7667 tmp2 = load_reg(s, rm);
7668 if ((op & 0x50) == 0x10) {
7669 /* sdiv, udiv */
7670 if (!arm_feature(env, ARM_FEATURE_DIV))
7671 goto illegal_op;
7672 if (op & 0x20)
7673 gen_helper_udiv(tmp, tmp, tmp2);
7674 else
7675 gen_helper_sdiv(tmp, tmp, tmp2);
7676 dead_tmp(tmp2);
7677 store_reg(s, rd, tmp);
7678 } else if ((op & 0xe) == 0xc) {
7679 /* Dual multiply accumulate long. */
7680 if (op & 1)
7681 gen_swap_half(tmp2);
7682 gen_smul_dual(tmp, tmp2);
7683 if (op & 0x10) {
7684 tcg_gen_sub_i32(tmp, tmp, tmp2);
7685 } else {
7686 tcg_gen_add_i32(tmp, tmp, tmp2);
7687 }
7688 dead_tmp(tmp2);
7689 /* BUGFIX */
7690 tmp64 = tcg_temp_new_i64();
7691 tcg_gen_ext_i32_i64(tmp64, tmp);
7692 dead_tmp(tmp);
7693 gen_addq(s, tmp64, rs, rd);
7694 gen_storeq_reg(s, rs, rd, tmp64);
7695 } else {
7696 if (op & 0x20) {
7697 /* Unsigned 64-bit multiply */
7698 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7699 } else {
7700 if (op & 8) {
7701 /* smlalxy */
7702 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7703 dead_tmp(tmp2);
7704 tmp64 = tcg_temp_new_i64();
7705 tcg_gen_ext_i32_i64(tmp64, tmp);
7706 dead_tmp(tmp);
7707 } else {
7708 /* Signed 64-bit multiply */
7709 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7710 }
7711 }
7712 if (op & 4) {
7713 /* umaal */
7714 gen_addq_lo(s, tmp64, rs);
7715 gen_addq_lo(s, tmp64, rd);
7716 } else if (op & 0x40) {
7717 /* 64-bit accumulate. */
7718 gen_addq(s, tmp64, rs, rd);
7719 }
7720 gen_storeq_reg(s, rs, rd, tmp64);
7721 }
7722 break;
7723 }
7724 break;
7725 case 6: case 7: case 14: case 15:
7726 /* Coprocessor. */
7727 if (((insn >> 24) & 3) == 3) {
7728 /* Translate into the equivalent ARM encoding. */
7729 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7730 if (disas_neon_data_insn(env, s, insn))
7731 goto illegal_op;
7732 } else {
7733 if (insn & (1 << 28))
7734 goto illegal_op;
7735 if (disas_coproc_insn (env, s, insn))
7736 goto illegal_op;
7737 }
7738 break;
7739 case 8: case 9: case 10: case 11:
7740 if (insn & (1 << 15)) {
7741 /* Branches, misc control. */
7742 if (insn & 0x5000) {
7743 /* Unconditional branch. */
7744 /* signextend(hw1[10:0]) -> offset[:12]. */
7745 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7746 /* hw1[10:0] -> offset[11:1]. */
7747 offset |= (insn & 0x7ff) << 1;
7748 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7749 offset[24:22] already have the same value because of the
7750 sign extension above. */
7751 offset ^= ((~insn) & (1 << 13)) << 10;
7752 offset ^= ((~insn) & (1 << 11)) << 11;
7753
7754 if (insn & (1 << 14)) {
7755 /* Branch and link. */
7756 gen_op_movl_T1_im(s->pc | 1);
7757 gen_movl_reg_T1(s, 14);
7758 }
7759
7760 offset += s->pc;
7761 if (insn & (1 << 12)) {
7762 /* b/bl */
7763 gen_jmp(s, offset);
7764 } else {
7765 /* blx */
7766 offset &= ~(uint32_t)2;
7767 gen_bx_im(s, offset);
7768 }
7769 } else if (((insn >> 23) & 7) == 7) {
7770 /* Misc control */
7771 if (insn & (1 << 13))
7772 goto illegal_op;
7773
7774 if (insn & (1 << 26)) {
7775 /* Secure monitor call (v6Z) */
7776 goto illegal_op; /* not implemented. */
7777 } else {
7778 op = (insn >> 20) & 7;
7779 switch (op) {
7780 case 0: /* msr cpsr. */
7781 if (IS_M(env)) {
7782 tmp = load_reg(s, rn);
7783 addr = tcg_const_i32(insn & 0xff);
7784 gen_helper_v7m_msr(cpu_env, addr, tmp);
7785 gen_lookup_tb(s);
7786 break;
7787 }
7788 /* fall through */
7789 case 1: /* msr spsr. */
7790 if (IS_M(env))
7791 goto illegal_op;
7792 tmp = load_reg(s, rn);
7793 if (gen_set_psr(s,
7794 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7795 op == 1, tmp))
7796 goto illegal_op;
7797 break;
7798 case 2: /* cps, nop-hint. */
7799 if (((insn >> 8) & 7) == 0) {
7800 gen_nop_hint(s, insn & 0xff);
7801 }
7802 /* Implemented as NOP in user mode. */
7803 if (IS_USER(s))
7804 break;
7805 offset = 0;
7806 imm = 0;
7807 if (insn & (1 << 10)) {
7808 if (insn & (1 << 7))
7809 offset |= CPSR_A;
7810 if (insn & (1 << 6))
7811 offset |= CPSR_I;
7812 if (insn & (1 << 5))
7813 offset |= CPSR_F;
7814 if (insn & (1 << 9))
7815 imm = CPSR_A | CPSR_I | CPSR_F;
7816 }
7817 if (insn & (1 << 8)) {
7818 offset |= 0x1f;
7819 imm |= (insn & 0x1f);
7820 }
7821 if (offset) {
7822 gen_set_psr_im(s, offset, 0, imm);
7823 }
7824 break;
7825 case 3: /* Special control operations. */
7826 op = (insn >> 4) & 0xf;
7827 switch (op) {
7828 case 2: /* clrex */
7829 gen_helper_clrex(cpu_env);
7830 break;
7831 case 4: /* dsb */
7832 case 5: /* dmb */
7833 case 6: /* isb */
7834 /* These execute as NOPs. */
7835 ARCH(7);
7836 break;
7837 default:
7838 goto illegal_op;
7839 }
7840 break;
7841 case 4: /* bxj */
7842 /* Trivial implementation equivalent to bx. */
7843 tmp = load_reg(s, rn);
7844 gen_bx(s, tmp);
7845 break;
7846 case 5: /* Exception return. */
7847 /* Unpredictable in user mode. */
7848 goto illegal_op;
7849 case 6: /* mrs cpsr. */
7850 tmp = new_tmp();
7851 if (IS_M(env)) {
7852 addr = tcg_const_i32(insn & 0xff);
7853 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7854 } else {
7855 gen_helper_cpsr_read(tmp);
7856 }
7857 store_reg(s, rd, tmp);
7858 break;
7859 case 7: /* mrs spsr. */
7860 /* Not accessible in user mode. */
7861 if (IS_USER(s) || IS_M(env))
7862 goto illegal_op;
7863 tmp = load_cpu_field(spsr);
7864 store_reg(s, rd, tmp);
7865 break;
7866 }
7867 }
7868 } else {
7869 /* Conditional branch. */
7870 op = (insn >> 22) & 0xf;
7871 /* Generate a conditional jump to next instruction. */
7872 s->condlabel = gen_new_label();
7873 gen_test_cc(op ^ 1, s->condlabel);
7874 s->condjmp = 1;
7875
7876 /* offset[11:1] = insn[10:0] */
7877 offset = (insn & 0x7ff) << 1;
7878 /* offset[17:12] = insn[21:16]. */
7879 offset |= (insn & 0x003f0000) >> 4;
7880 /* offset[31:20] = insn[26]. */
7881 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7882 /* offset[18] = insn[13]. */
7883 offset |= (insn & (1 << 13)) << 5;
7884 /* offset[19] = insn[11]. */
7885 offset |= (insn & (1 << 11)) << 8;
7886
7887 /* jump to the offset */
7888 gen_jmp(s, s->pc + offset);
7889 }
7890 } else {
7891 /* Data processing immediate. */
7892 if (insn & (1 << 25)) {
7893 if (insn & (1 << 24)) {
7894 if (insn & (1 << 20))
7895 goto illegal_op;
7896 /* Bitfield/Saturate. */
7897 op = (insn >> 21) & 7;
7898 imm = insn & 0x1f;
7899 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7900 if (rn == 15) {
7901 tmp = new_tmp();
7902 tcg_gen_movi_i32(tmp, 0);
7903 } else {
7904 tmp = load_reg(s, rn);
7905 }
7906 switch (op) {
7907 case 2: /* Signed bitfield extract. */
7908 imm++;
7909 if (shift + imm > 32)
7910 goto illegal_op;
7911 if (imm < 32)
7912 gen_sbfx(tmp, shift, imm);
7913 break;
7914 case 6: /* Unsigned bitfield extract. */
7915 imm++;
7916 if (shift + imm > 32)
7917 goto illegal_op;
7918 if (imm < 32)
7919 gen_ubfx(tmp, shift, (1u << imm) - 1);
7920 break;
7921 case 3: /* Bitfield insert/clear. */
7922 if (imm < shift)
7923 goto illegal_op;
7924 imm = imm + 1 - shift;
7925 if (imm != 32) {
7926 tmp2 = load_reg(s, rd);
7927 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7928 dead_tmp(tmp2);
7929 }
7930 break;
7931 case 7:
7932 goto illegal_op;
7933 default: /* Saturate. */
7934 if (shift) {
7935 if (op & 1)
7936 tcg_gen_sari_i32(tmp, tmp, shift);
7937 else
7938 tcg_gen_shli_i32(tmp, tmp, shift);
7939 }
7940 tmp2 = tcg_const_i32(imm);
7941 if (op & 4) {
7942 /* Unsigned. */
7943 if ((op & 1) && shift == 0)
7944 gen_helper_usat16(tmp, tmp, tmp2);
7945 else
7946 gen_helper_usat(tmp, tmp, tmp2);
7947 } else {
7948 /* Signed. */
7949 if ((op & 1) && shift == 0)
7950 gen_helper_ssat16(tmp, tmp, tmp2);
7951 else
7952 gen_helper_ssat(tmp, tmp, tmp2);
7953 }
7954 break;
7955 }
7956 store_reg(s, rd, tmp);
7957 } else {
7958 imm = ((insn & 0x04000000) >> 15)
7959 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7960 if (insn & (1 << 22)) {
7961 /* 16-bit immediate. */
7962 imm |= (insn >> 4) & 0xf000;
7963 if (insn & (1 << 23)) {
7964 /* movt */
7965 tmp = load_reg(s, rd);
7966 tcg_gen_ext16u_i32(tmp, tmp);
7967 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7968 } else {
7969 /* movw */
7970 tmp = new_tmp();
7971 tcg_gen_movi_i32(tmp, imm);
7972 }
7973 } else {
7974 /* Add/sub 12-bit immediate. */
7975 if (rn == 15) {
7976 offset = s->pc & ~(uint32_t)3;
7977 if (insn & (1 << 23))
7978 offset -= imm;
7979 else
7980 offset += imm;
7981 tmp = new_tmp();
7982 tcg_gen_movi_i32(tmp, offset);
7983 } else {
7984 tmp = load_reg(s, rn);
7985 if (insn & (1 << 23))
7986 tcg_gen_subi_i32(tmp, tmp, imm);
7987 else
7988 tcg_gen_addi_i32(tmp, tmp, imm);
7989 }
7990 }
7991 store_reg(s, rd, tmp);
7992 }
7993 } else {
7994 int shifter_out = 0;
7995 /* modified 12-bit immediate. */
7996 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7997 imm = (insn & 0xff);
7998 switch (shift) {
7999 case 0: /* XY */
8000 /* Nothing to do. */
8001 break;
8002 case 1: /* 00XY00XY */
8003 imm |= imm << 16;
8004 break;
8005 case 2: /* XY00XY00 */
8006 imm |= imm << 16;
8007 imm <<= 8;
8008 break;
8009 case 3: /* XYXYXYXY */
8010 imm |= imm << 16;
8011 imm |= imm << 8;
8012 break;
8013 default: /* Rotated constant. */
8014 shift = (shift << 1) | (imm >> 7);
8015 imm |= 0x80;
8016 imm = imm << (32 - shift);
8017 shifter_out = 1;
8018 break;
8019 }
8020 gen_op_movl_T1_im(imm);
8021 rn = (insn >> 16) & 0xf;
8022 if (rn == 15)
8023 gen_op_movl_T0_im(0);
8024 else
8025 gen_movl_T0_reg(s, rn);
8026 op = (insn >> 21) & 0xf;
8027 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8028 shifter_out))
8029 goto illegal_op;
8030 rd = (insn >> 8) & 0xf;
8031 if (rd != 15) {
8032 gen_movl_reg_T0(s, rd);
8033 }
8034 }
8035 }
8036 break;
8037 case 12: /* Load/store single data item. */
8038 {
8039 int postinc = 0;
8040 int writeback = 0;
8041 int user;
8042 if ((insn & 0x01100000) == 0x01000000) {
8043 if (disas_neon_ls_insn(env, s, insn))
8044 goto illegal_op;
8045 break;
8046 }
8047 user = IS_USER(s);
8048 if (rn == 15) {
8049 addr = new_tmp();
8050 /* PC relative. */
8051 /* s->pc has already been incremented by 4. */
8052 imm = s->pc & 0xfffffffc;
8053 if (insn & (1 << 23))
8054 imm += insn & 0xfff;
8055 else
8056 imm -= insn & 0xfff;
8057 tcg_gen_movi_i32(addr, imm);
8058 } else {
8059 addr = load_reg(s, rn);
8060 if (insn & (1 << 23)) {
8061 /* Positive offset. */
8062 imm = insn & 0xfff;
8063 tcg_gen_addi_i32(addr, addr, imm);
8064 } else {
8065 op = (insn >> 8) & 7;
8066 imm = insn & 0xff;
8067 switch (op) {
8068 case 0: case 8: /* Shifted Register. */
8069 shift = (insn >> 4) & 0xf;
8070 if (shift > 3)
8071 goto illegal_op;
8072 tmp = load_reg(s, rm);
8073 if (shift)
8074 tcg_gen_shli_i32(tmp, tmp, shift);
8075 tcg_gen_add_i32(addr, addr, tmp);
8076 dead_tmp(tmp);
8077 break;
8078 case 4: /* Negative offset. */
8079 tcg_gen_addi_i32(addr, addr, -imm);
8080 break;
8081 case 6: /* User privilege. */
8082 tcg_gen_addi_i32(addr, addr, imm);
8083 user = 1;
8084 break;
8085 case 1: /* Post-decrement. */
8086 imm = -imm;
8087 /* Fall through. */
8088 case 3: /* Post-increment. */
8089 postinc = 1;
8090 writeback = 1;
8091 break;
8092 case 5: /* Pre-decrement. */
8093 imm = -imm;
8094 /* Fall through. */
8095 case 7: /* Pre-increment. */
8096 tcg_gen_addi_i32(addr, addr, imm);
8097 writeback = 1;
8098 break;
8099 default:
8100 goto illegal_op;
8101 }
8102 }
8103 }
8104 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8105 if (insn & (1 << 20)) {
8106 /* Load. */
8107 if (rs == 15 && op != 2) {
8108 if (op & 2)
8109 goto illegal_op;
8110 /* Memory hint. Implemented as NOP. */
8111 } else {
8112 switch (op) {
8113 case 0: tmp = gen_ld8u(addr, user); break;
8114 case 4: tmp = gen_ld8s(addr, user); break;
8115 case 1: tmp = gen_ld16u(addr, user); break;
8116 case 5: tmp = gen_ld16s(addr, user); break;
8117 case 2: tmp = gen_ld32(addr, user); break;
8118 default: goto illegal_op;
8119 }
8120 if (rs == 15) {
8121 gen_bx(s, tmp);
8122 } else {
8123 store_reg(s, rs, tmp);
8124 }
8125 }
8126 } else {
8127 /* Store. */
8128 if (rs == 15)
8129 goto illegal_op;
8130 tmp = load_reg(s, rs);
8131 switch (op) {
8132 case 0: gen_st8(tmp, addr, user); break;
8133 case 1: gen_st16(tmp, addr, user); break;
8134 case 2: gen_st32(tmp, addr, user); break;
8135 default: goto illegal_op;
8136 }
8137 }
8138 if (postinc)
8139 tcg_gen_addi_i32(addr, addr, imm);
8140 if (writeback) {
8141 store_reg(s, rn, addr);
8142 } else {
8143 dead_tmp(addr);
8144 }
8145 }
8146 break;
8147 default:
8148 goto illegal_op;
8149 }
8150 return 0;
8151 illegal_op:
8152 return 1;
8153 }
8154
8155 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8156 {
8157 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8158 int32_t offset;
8159 int i;
8160 TCGv tmp;
8161 TCGv tmp2;
8162 TCGv addr;
8163
8164 if (s->condexec_mask) {
8165 cond = s->condexec_cond;
8166 s->condlabel = gen_new_label();
8167 gen_test_cc(cond ^ 1, s->condlabel);
8168 s->condjmp = 1;
8169 }
8170
8171 insn = lduw_code(s->pc);
8172 s->pc += 2;
8173
8174 switch (insn >> 12) {
8175 case 0: case 1:
8176 rd = insn & 7;
8177 op = (insn >> 11) & 3;
8178 if (op == 3) {
8179 /* add/subtract */
8180 rn = (insn >> 3) & 7;
8181 gen_movl_T0_reg(s, rn);
8182 if (insn & (1 << 10)) {
8183 /* immediate */
8184 gen_op_movl_T1_im((insn >> 6) & 7);
8185 } else {
8186 /* reg */
8187 rm = (insn >> 6) & 7;
8188 gen_movl_T1_reg(s, rm);
8189 }
8190 if (insn & (1 << 9)) {
8191 if (s->condexec_mask)
8192 gen_op_subl_T0_T1();
8193 else
8194 gen_op_subl_T0_T1_cc();
8195 } else {
8196 if (s->condexec_mask)
8197 gen_op_addl_T0_T1();
8198 else
8199 gen_op_addl_T0_T1_cc();
8200 }
8201 gen_movl_reg_T0(s, rd);
8202 } else {
8203 /* shift immediate */
8204 rm = (insn >> 3) & 7;
8205 shift = (insn >> 6) & 0x1f;
8206 tmp = load_reg(s, rm);
8207 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8208 if (!s->condexec_mask)
8209 gen_logic_CC(tmp);
8210 store_reg(s, rd, tmp);
8211 }
8212 break;
8213 case 2: case 3:
8214 /* arithmetic large immediate */
8215 op = (insn >> 11) & 3;
8216 rd = (insn >> 8) & 0x7;
8217 if (op == 0) {
8218 gen_op_movl_T0_im(insn & 0xff);
8219 } else {
8220 gen_movl_T0_reg(s, rd);
8221 gen_op_movl_T1_im(insn & 0xff);
8222 }
8223 switch (op) {
8224 case 0: /* mov */
8225 if (!s->condexec_mask)
8226 gen_op_logic_T0_cc();
8227 break;
8228 case 1: /* cmp */
8229 gen_op_subl_T0_T1_cc();
8230 break;
8231 case 2: /* add */
8232 if (s->condexec_mask)
8233 gen_op_addl_T0_T1();
8234 else
8235 gen_op_addl_T0_T1_cc();
8236 break;
8237 case 3: /* sub */
8238 if (s->condexec_mask)
8239 gen_op_subl_T0_T1();
8240 else
8241 gen_op_subl_T0_T1_cc();
8242 break;
8243 }
8244 if (op != 1)
8245 gen_movl_reg_T0(s, rd);
8246 break;
8247 case 4:
8248 if (insn & (1 << 11)) {
8249 rd = (insn >> 8) & 7;
8250 /* load pc-relative. Bit 1 of PC is ignored. */
8251 val = s->pc + 2 + ((insn & 0xff) * 4);
8252 val &= ~(uint32_t)2;
8253 addr = new_tmp();
8254 tcg_gen_movi_i32(addr, val);
8255 tmp = gen_ld32(addr, IS_USER(s));
8256 dead_tmp(addr);
8257 store_reg(s, rd, tmp);
8258 break;
8259 }
8260 if (insn & (1 << 10)) {
8261 /* data processing extended or blx */
8262 rd = (insn & 7) | ((insn >> 4) & 8);
8263 rm = (insn >> 3) & 0xf;
8264 op = (insn >> 8) & 3;
8265 switch (op) {
8266 case 0: /* add */
8267 gen_movl_T0_reg(s, rd);
8268 gen_movl_T1_reg(s, rm);
8269 gen_op_addl_T0_T1();
8270 gen_movl_reg_T0(s, rd);
8271 break;
8272 case 1: /* cmp */
8273 gen_movl_T0_reg(s, rd);
8274 gen_movl_T1_reg(s, rm);
8275 gen_op_subl_T0_T1_cc();
8276 break;
8277 case 2: /* mov/cpy */
8278 gen_movl_T0_reg(s, rm);
8279 gen_movl_reg_T0(s, rd);
8280 break;
8281 case 3:/* branch [and link] exchange thumb register */
8282 tmp = load_reg(s, rm);
8283 if (insn & (1 << 7)) {
8284 val = (uint32_t)s->pc | 1;
8285 tmp2 = new_tmp();
8286 tcg_gen_movi_i32(tmp2, val);
8287 store_reg(s, 14, tmp2);
8288 }
8289 gen_bx(s, tmp);
8290 break;
8291 }
8292 break;
8293 }
8294
8295 /* data processing register */
8296 rd = insn & 7;
8297 rm = (insn >> 3) & 7;
8298 op = (insn >> 6) & 0xf;
8299 if (op == 2 || op == 3 || op == 4 || op == 7) {
8300 /* the shift/rotate ops want the operands backwards */
8301 val = rm;
8302 rm = rd;
8303 rd = val;
8304 val = 1;
8305 } else {
8306 val = 0;
8307 }
8308
8309 if (op == 9) /* neg */
8310 gen_op_movl_T0_im(0);
8311 else if (op != 0xf) /* mvn doesn't read its first operand */
8312 gen_movl_T0_reg(s, rd);
8313
8314 gen_movl_T1_reg(s, rm);
8315 switch (op) {
8316 case 0x0: /* and */
8317 gen_op_andl_T0_T1();
8318 if (!s->condexec_mask)
8319 gen_op_logic_T0_cc();
8320 break;
8321 case 0x1: /* eor */
8322 gen_op_xorl_T0_T1();
8323 if (!s->condexec_mask)
8324 gen_op_logic_T0_cc();
8325 break;
8326 case 0x2: /* lsl */
8327 if (s->condexec_mask) {
8328 gen_helper_shl(cpu_T[1], cpu_T[1], cpu_T[0]);
8329 } else {
8330 gen_helper_shl_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8331 gen_op_logic_T1_cc();
8332 }
8333 break;
8334 case 0x3: /* lsr */
8335 if (s->condexec_mask) {
8336 gen_helper_shr(cpu_T[1], cpu_T[1], cpu_T[0]);
8337 } else {
8338 gen_helper_shr_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8339 gen_op_logic_T1_cc();
8340 }
8341 break;
8342 case 0x4: /* asr */
8343 if (s->condexec_mask) {
8344 gen_helper_sar(cpu_T[1], cpu_T[1], cpu_T[0]);
8345 } else {
8346 gen_helper_sar_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8347 gen_op_logic_T1_cc();
8348 }
8349 break;
8350 case 0x5: /* adc */
8351 if (s->condexec_mask)
8352 gen_adc_T0_T1();
8353 else
8354 gen_op_adcl_T0_T1_cc();
8355 break;
8356 case 0x6: /* sbc */
8357 if (s->condexec_mask)
8358 gen_sbc_T0_T1();
8359 else
8360 gen_op_sbcl_T0_T1_cc();
8361 break;
8362 case 0x7: /* ror */
8363 if (s->condexec_mask) {
8364 gen_helper_ror(cpu_T[1], cpu_T[1], cpu_T[0]);
8365 } else {
8366 gen_helper_ror_cc(cpu_T[1], cpu_T[1], cpu_T[0]);
8367 gen_op_logic_T1_cc();
8368 }
8369 break;
8370 case 0x8: /* tst */
8371 gen_op_andl_T0_T1();
8372 gen_op_logic_T0_cc();
8373 rd = 16;
8374 break;
8375 case 0x9: /* neg */
8376 if (s->condexec_mask)
8377 tcg_gen_neg_i32(cpu_T[0], cpu_T[1]);
8378 else
8379 gen_op_subl_T0_T1_cc();
8380 break;
8381 case 0xa: /* cmp */
8382 gen_op_subl_T0_T1_cc();
8383 rd = 16;
8384 break;
8385 case 0xb: /* cmn */
8386 gen_op_addl_T0_T1_cc();
8387 rd = 16;
8388 break;
8389 case 0xc: /* orr */
8390 gen_op_orl_T0_T1();
8391 if (!s->condexec_mask)
8392 gen_op_logic_T0_cc();
8393 break;
8394 case 0xd: /* mul */
8395 gen_op_mull_T0_T1();
8396 if (!s->condexec_mask)
8397 gen_op_logic_T0_cc();
8398 break;
8399 case 0xe: /* bic */
8400 gen_op_bicl_T0_T1();
8401 if (!s->condexec_mask)
8402 gen_op_logic_T0_cc();
8403 break;
8404 case 0xf: /* mvn */
8405 gen_op_notl_T1();
8406 if (!s->condexec_mask)
8407 gen_op_logic_T1_cc();
8408 val = 1;
8409 rm = rd;
8410 break;
8411 }
8412 if (rd != 16) {
8413 if (val)
8414 gen_movl_reg_T1(s, rm);
8415 else
8416 gen_movl_reg_T0(s, rd);
8417 }
8418 break;
8419
8420 case 5:
8421 /* load/store register offset. */
8422 rd = insn & 7;
8423 rn = (insn >> 3) & 7;
8424 rm = (insn >> 6) & 7;
8425 op = (insn >> 9) & 7;
8426 addr = load_reg(s, rn);
8427 tmp = load_reg(s, rm);
8428 tcg_gen_add_i32(addr, addr, tmp);
8429 dead_tmp(tmp);
8430
8431 if (op < 3) /* store */
8432 tmp = load_reg(s, rd);
8433
8434 switch (op) {
8435 case 0: /* str */
8436 gen_st32(tmp, addr, IS_USER(s));
8437 break;
8438 case 1: /* strh */
8439 gen_st16(tmp, addr, IS_USER(s));
8440 break;
8441 case 2: /* strb */
8442 gen_st8(tmp, addr, IS_USER(s));
8443 break;
8444 case 3: /* ldrsb */
8445 tmp = gen_ld8s(addr, IS_USER(s));
8446 break;
8447 case 4: /* ldr */
8448 tmp = gen_ld32(addr, IS_USER(s));
8449 break;
8450 case 5: /* ldrh */
8451 tmp = gen_ld16u(addr, IS_USER(s));
8452 break;
8453 case 6: /* ldrb */
8454 tmp = gen_ld8u(addr, IS_USER(s));
8455 break;
8456 case 7: /* ldrsh */
8457 tmp = gen_ld16s(addr, IS_USER(s));
8458 break;
8459 }
8460 if (op >= 3) /* load */
8461 store_reg(s, rd, tmp);
8462 dead_tmp(addr);
8463 break;
8464
8465 case 6:
8466 /* load/store word immediate offset */
8467 rd = insn & 7;
8468 rn = (insn >> 3) & 7;
8469 addr = load_reg(s, rn);
8470 val = (insn >> 4) & 0x7c;
8471 tcg_gen_addi_i32(addr, addr, val);
8472
8473 if (insn & (1 << 11)) {
8474 /* load */
8475 tmp = gen_ld32(addr, IS_USER(s));
8476 store_reg(s, rd, tmp);
8477 } else {
8478 /* store */
8479 tmp = load_reg(s, rd);
8480 gen_st32(tmp, addr, IS_USER(s));
8481 }
8482 dead_tmp(addr);
8483 break;
8484
8485 case 7:
8486 /* load/store byte immediate offset */
8487 rd = insn & 7;
8488 rn = (insn >> 3) & 7;
8489 addr = load_reg(s, rn);
8490 val = (insn >> 6) & 0x1f;
8491 tcg_gen_addi_i32(addr, addr, val);
8492
8493 if (insn & (1 << 11)) {
8494 /* load */
8495 tmp = gen_ld8u(addr, IS_USER(s));
8496 store_reg(s, rd, tmp);
8497 } else {
8498 /* store */
8499 tmp = load_reg(s, rd);
8500 gen_st8(tmp, addr, IS_USER(s));
8501 }
8502 dead_tmp(addr);
8503 break;
8504
8505 case 8:
8506 /* load/store halfword immediate offset */
8507 rd = insn & 7;
8508 rn = (insn >> 3) & 7;
8509 addr = load_reg(s, rn);
8510 val = (insn >> 5) & 0x3e;
8511 tcg_gen_addi_i32(addr, addr, val);
8512
8513 if (insn & (1 << 11)) {
8514 /* load */
8515 tmp = gen_ld16u(addr, IS_USER(s));
8516 store_reg(s, rd, tmp);
8517 } else {
8518 /* store */
8519 tmp = load_reg(s, rd);
8520 gen_st16(tmp, addr, IS_USER(s));
8521 }
8522 dead_tmp(addr);
8523 break;
8524
8525 case 9:
8526 /* load/store from stack */
8527 rd = (insn >> 8) & 7;
8528 addr = load_reg(s, 13);
8529 val = (insn & 0xff) * 4;
8530 tcg_gen_addi_i32(addr, addr, val);
8531
8532 if (insn & (1 << 11)) {
8533 /* load */
8534 tmp = gen_ld32(addr, IS_USER(s));
8535 store_reg(s, rd, tmp);
8536 } else {
8537 /* store */
8538 tmp = load_reg(s, rd);
8539 gen_st32(tmp, addr, IS_USER(s));
8540 }
8541 dead_tmp(addr);
8542 break;
8543
8544 case 10:
8545 /* add to high reg */
8546 rd = (insn >> 8) & 7;
8547 if (insn & (1 << 11)) {
8548 /* SP */
8549 tmp = load_reg(s, 13);
8550 } else {
8551 /* PC. bit 1 is ignored. */
8552 tmp = new_tmp();
8553 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8554 }
8555 val = (insn & 0xff) * 4;
8556 tcg_gen_addi_i32(tmp, tmp, val);
8557 store_reg(s, rd, tmp);
8558 break;
8559
8560 case 11:
8561 /* misc */
8562 op = (insn >> 8) & 0xf;
8563 switch (op) {
8564 case 0:
8565 /* adjust stack pointer */
8566 tmp = load_reg(s, 13);
8567 val = (insn & 0x7f) * 4;
8568 if (insn & (1 << 7))
8569 val = -(int32_t)val;
8570 tcg_gen_addi_i32(tmp, tmp, val);
8571 store_reg(s, 13, tmp);
8572 break;
8573
8574 case 2: /* sign/zero extend. */
8575 ARCH(6);
8576 rd = insn & 7;
8577 rm = (insn >> 3) & 7;
8578 tmp = load_reg(s, rm);
8579 switch ((insn >> 6) & 3) {
8580 case 0: gen_sxth(tmp); break;
8581 case 1: gen_sxtb(tmp); break;
8582 case 2: gen_uxth(tmp); break;
8583 case 3: gen_uxtb(tmp); break;
8584 }
8585 store_reg(s, rd, tmp);
8586 break;
8587 case 4: case 5: case 0xc: case 0xd:
8588 /* push/pop */
8589 addr = load_reg(s, 13);
8590 if (insn & (1 << 8))
8591 offset = 4;
8592 else
8593 offset = 0;
8594 for (i = 0; i < 8; i++) {
8595 if (insn & (1 << i))
8596 offset += 4;
8597 }
8598 if ((insn & (1 << 11)) == 0) {
8599 tcg_gen_addi_i32(addr, addr, -offset);
8600 }
8601 for (i = 0; i < 8; i++) {
8602 if (insn & (1 << i)) {
8603 if (insn & (1 << 11)) {
8604 /* pop */
8605 tmp = gen_ld32(addr, IS_USER(s));
8606 store_reg(s, i, tmp);
8607 } else {
8608 /* push */
8609 tmp = load_reg(s, i);
8610 gen_st32(tmp, addr, IS_USER(s));
8611 }
8612 /* advance to the next address. */
8613 tcg_gen_addi_i32(addr, addr, 4);
8614 }
8615 }
8616 TCGV_UNUSED(tmp);
8617 if (insn & (1 << 8)) {
8618 if (insn & (1 << 11)) {
8619 /* pop pc */
8620 tmp = gen_ld32(addr, IS_USER(s));
8621 /* don't set the pc until the rest of the instruction
8622 has completed */
8623 } else {
8624 /* push lr */
8625 tmp = load_reg(s, 14);
8626 gen_st32(tmp, addr, IS_USER(s));
8627 }
8628 tcg_gen_addi_i32(addr, addr, 4);
8629 }
8630 if ((insn & (1 << 11)) == 0) {
8631 tcg_gen_addi_i32(addr, addr, -offset);
8632 }
8633 /* write back the new stack pointer */
8634 store_reg(s, 13, addr);
8635 /* set the new PC value */
8636 if ((insn & 0x0900) == 0x0900)
8637 gen_bx(s, tmp);
8638 break;
8639
8640 case 1: case 3: case 9: case 11: /* czb */
8641 rm = insn & 7;
8642 tmp = load_reg(s, rm);
8643 s->condlabel = gen_new_label();
8644 s->condjmp = 1;
8645 if (insn & (1 << 11))
8646 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8647 else
8648 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8649 dead_tmp(tmp);
8650 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8651 val = (uint32_t)s->pc + 2;
8652 val += offset;
8653 gen_jmp(s, val);
8654 break;
8655
8656 case 15: /* IT, nop-hint. */
8657 if ((insn & 0xf) == 0) {
8658 gen_nop_hint(s, (insn >> 4) & 0xf);
8659 break;
8660 }
8661 /* If Then. */
8662 s->condexec_cond = (insn >> 4) & 0xe;
8663 s->condexec_mask = insn & 0x1f;
8664 /* No actual code generated for this insn, just setup state. */
8665 break;
8666
8667 case 0xe: /* bkpt */
8668 gen_set_condexec(s);
8669 gen_set_pc_im(s->pc - 2);
8670 gen_exception(EXCP_BKPT);
8671 s->is_jmp = DISAS_JUMP;
8672 break;
8673
8674 case 0xa: /* rev */
8675 ARCH(6);
8676 rn = (insn >> 3) & 0x7;
8677 rd = insn & 0x7;
8678 tmp = load_reg(s, rn);
8679 switch ((insn >> 6) & 3) {
8680 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8681 case 1: gen_rev16(tmp); break;
8682 case 3: gen_revsh(tmp); break;
8683 default: goto illegal_op;
8684 }
8685 store_reg(s, rd, tmp);
8686 break;
8687
8688 case 6: /* cps */
8689 ARCH(6);
8690 if (IS_USER(s))
8691 break;
8692 if (IS_M(env)) {
8693 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8694 /* PRIMASK */
8695 if (insn & 1) {
8696 addr = tcg_const_i32(16);
8697 gen_helper_v7m_msr(cpu_env, addr, tmp);
8698 }
8699 /* FAULTMASK */
8700 if (insn & 2) {
8701 addr = tcg_const_i32(17);
8702 gen_helper_v7m_msr(cpu_env, addr, tmp);
8703 }
8704 gen_lookup_tb(s);
8705 } else {
8706 if (insn & (1 << 4))
8707 shift = CPSR_A | CPSR_I | CPSR_F;
8708 else
8709 shift = 0;
8710 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8711 }
8712 break;
8713
8714 default:
8715 goto undef;
8716 }
8717 break;
8718
8719 case 12:
8720 /* load/store multiple */
8721 rn = (insn >> 8) & 0x7;
8722 addr = load_reg(s, rn);
8723 for (i = 0; i < 8; i++) {
8724 if (insn & (1 << i)) {
8725 if (insn & (1 << 11)) {
8726 /* load */
8727 tmp = gen_ld32(addr, IS_USER(s));
8728 store_reg(s, i, tmp);
8729 } else {
8730 /* store */
8731 tmp = load_reg(s, i);
8732 gen_st32(tmp, addr, IS_USER(s));
8733 }
8734 /* advance to the next address */
8735 tcg_gen_addi_i32(addr, addr, 4);
8736 }
8737 }
8738 /* Base register writeback. */
8739 if ((insn & (1 << rn)) == 0) {
8740 store_reg(s, rn, addr);
8741 } else {
8742 dead_tmp(addr);
8743 }
8744 break;
8745
8746 case 13:
8747 /* conditional branch or swi */
8748 cond = (insn >> 8) & 0xf;
8749 if (cond == 0xe)
8750 goto undef;
8751
8752 if (cond == 0xf) {
8753 /* swi */
8754 gen_set_condexec(s);
8755 gen_set_pc_im(s->pc);
8756 s->is_jmp = DISAS_SWI;
8757 break;
8758 }
8759 /* generate a conditional jump to next instruction */
8760 s->condlabel = gen_new_label();
8761 gen_test_cc(cond ^ 1, s->condlabel);
8762 s->condjmp = 1;
8763
8764 /* jump to the offset */
8765 val = (uint32_t)s->pc + 2;
8766 offset = ((int32_t)insn << 24) >> 24;
8767 val += offset << 1;
8768 gen_jmp(s, val);
8769 break;
8770
8771 case 14:
8772 if (insn & (1 << 11)) {
8773 if (disas_thumb2_insn(env, s, insn))
8774 goto undef32;
8775 break;
8776 }
8777 /* unconditional branch */
8778 val = (uint32_t)s->pc;
8779 offset = ((int32_t)insn << 21) >> 21;
8780 val += (offset << 1) + 2;
8781 gen_jmp(s, val);
8782 break;
8783
8784 case 15:
8785 if (disas_thumb2_insn(env, s, insn))
8786 goto undef32;
8787 break;
8788 }
8789 return;
8790 undef32:
8791 gen_set_condexec(s);
8792 gen_set_pc_im(s->pc - 4);
8793 gen_exception(EXCP_UDEF);
8794 s->is_jmp = DISAS_JUMP;
8795 return;
8796 illegal_op:
8797 undef:
8798 gen_set_condexec(s);
8799 gen_set_pc_im(s->pc - 2);
8800 gen_exception(EXCP_UDEF);
8801 s->is_jmp = DISAS_JUMP;
8802 }
8803
8804 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8805 basic block 'tb'. If search_pc is TRUE, also generate PC
8806 information for each intermediate instruction. */
8807 static inline void gen_intermediate_code_internal(CPUState *env,
8808 TranslationBlock *tb,
8809 int search_pc)
8810 {
8811 DisasContext dc1, *dc = &dc1;
8812 CPUBreakpoint *bp;
8813 uint16_t *gen_opc_end;
8814 int j, lj;
8815 target_ulong pc_start;
8816 uint32_t next_page_start;
8817 int num_insns;
8818 int max_insns;
8819
8820 /* generate intermediate code */
8821 num_temps = 0;
8822
8823 pc_start = tb->pc;
8824
8825 dc->tb = tb;
8826
8827 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8828
8829 dc->is_jmp = DISAS_NEXT;
8830 dc->pc = pc_start;
8831 dc->singlestep_enabled = env->singlestep_enabled;
8832 dc->condjmp = 0;
8833 dc->thumb = env->thumb;
8834 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8835 dc->condexec_cond = env->condexec_bits >> 4;
8836 #if !defined(CONFIG_USER_ONLY)
8837 if (IS_M(env)) {
8838 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8839 } else {
8840 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8841 }
8842 #endif
8843 cpu_F0s = tcg_temp_new_i32();
8844 cpu_F1s = tcg_temp_new_i32();
8845 cpu_F0d = tcg_temp_new_i64();
8846 cpu_F1d = tcg_temp_new_i64();
8847 cpu_V0 = cpu_F0d;
8848 cpu_V1 = cpu_F1d;
8849 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8850 cpu_M0 = tcg_temp_new_i64();
8851 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8852 lj = -1;
8853 num_insns = 0;
8854 max_insns = tb->cflags & CF_COUNT_MASK;
8855 if (max_insns == 0)
8856 max_insns = CF_COUNT_MASK;
8857
8858 gen_icount_start();
8859 /* Reset the conditional execution bits immediately. This avoids
8860 complications trying to do it at the end of the block. */
8861 if (env->condexec_bits)
8862 {
8863 TCGv tmp = new_tmp();
8864 tcg_gen_movi_i32(tmp, 0);
8865 store_cpu_field(tmp, condexec_bits);
8866 }
8867 do {
8868 #ifdef CONFIG_USER_ONLY
8869 /* Intercept jump to the magic kernel page. */
8870 if (dc->pc >= 0xffff0000) {
8871 /* We always get here via a jump, so know we are not in a
8872 conditional execution block. */
8873 gen_exception(EXCP_KERNEL_TRAP);
8874 dc->is_jmp = DISAS_UPDATE;
8875 break;
8876 }
8877 #else
8878 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8879 /* We always get here via a jump, so know we are not in a
8880 conditional execution block. */
8881 gen_exception(EXCP_EXCEPTION_EXIT);
8882 dc->is_jmp = DISAS_UPDATE;
8883 break;
8884 }
8885 #endif
8886
8887 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8888 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8889 if (bp->pc == dc->pc) {
8890 gen_set_condexec(dc);
8891 gen_set_pc_im(dc->pc);
8892 gen_exception(EXCP_DEBUG);
8893 dc->is_jmp = DISAS_JUMP;
8894 /* Advance PC so that clearing the breakpoint will
8895 invalidate this TB. */
8896 dc->pc += 2;
8897 goto done_generating;
8898 break;
8899 }
8900 }
8901 }
8902 if (search_pc) {
8903 j = gen_opc_ptr - gen_opc_buf;
8904 if (lj < j) {
8905 lj++;
8906 while (lj < j)
8907 gen_opc_instr_start[lj++] = 0;
8908 }
8909 gen_opc_pc[lj] = dc->pc;
8910 gen_opc_instr_start[lj] = 1;
8911 gen_opc_icount[lj] = num_insns;
8912 }
8913
8914 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8915 gen_io_start();
8916
8917 if (env->thumb) {
8918 disas_thumb_insn(env, dc);
8919 if (dc->condexec_mask) {
8920 dc->condexec_cond = (dc->condexec_cond & 0xe)
8921 | ((dc->condexec_mask >> 4) & 1);
8922 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8923 if (dc->condexec_mask == 0) {
8924 dc->condexec_cond = 0;
8925 }
8926 }
8927 } else {
8928 disas_arm_insn(env, dc);
8929 }
8930 if (num_temps) {
8931 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8932 num_temps = 0;
8933 }
8934
8935 if (dc->condjmp && !dc->is_jmp) {
8936 gen_set_label(dc->condlabel);
8937 dc->condjmp = 0;
8938 }
8939 /* Translation stops when a conditional branch is encountered.
8940 * Otherwise the subsequent code could get translated several times.
8941 * Also stop translation when a page boundary is reached. This
8942 * ensures prefetch aborts occur at the right place. */
8943 num_insns ++;
8944 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8945 !env->singlestep_enabled &&
8946 !singlestep &&
8947 dc->pc < next_page_start &&
8948 num_insns < max_insns);
8949
8950 if (tb->cflags & CF_LAST_IO) {
8951 if (dc->condjmp) {
8952 /* FIXME: This can theoretically happen with self-modifying
8953 code. */
8954 cpu_abort(env, "IO on conditional branch instruction");
8955 }
8956 gen_io_end();
8957 }
8958
8959 /* At this stage dc->condjmp will only be set when the skipped
8960 instruction was a conditional branch or trap, and the PC has
8961 already been written. */
8962 if (unlikely(env->singlestep_enabled)) {
8963 /* Make sure the pc is updated, and raise a debug exception. */
8964 if (dc->condjmp) {
8965 gen_set_condexec(dc);
8966 if (dc->is_jmp == DISAS_SWI) {
8967 gen_exception(EXCP_SWI);
8968 } else {
8969 gen_exception(EXCP_DEBUG);
8970 }
8971 gen_set_label(dc->condlabel);
8972 }
8973 if (dc->condjmp || !dc->is_jmp) {
8974 gen_set_pc_im(dc->pc);
8975 dc->condjmp = 0;
8976 }
8977 gen_set_condexec(dc);
8978 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8979 gen_exception(EXCP_SWI);
8980 } else {
8981 /* FIXME: Single stepping a WFI insn will not halt
8982 the CPU. */
8983 gen_exception(EXCP_DEBUG);
8984 }
8985 } else {
8986 /* While branches must always occur at the end of an IT block,
8987 there are a few other things that can cause us to terminate
8988 the TB in the middel of an IT block:
8989 - Exception generating instructions (bkpt, swi, undefined).
8990 - Page boundaries.
8991 - Hardware watchpoints.
8992 Hardware breakpoints have already been handled and skip this code.
8993 */
8994 gen_set_condexec(dc);
8995 switch(dc->is_jmp) {
8996 case DISAS_NEXT:
8997 gen_goto_tb(dc, 1, dc->pc);
8998 break;
8999 default:
9000 case DISAS_JUMP:
9001 case DISAS_UPDATE:
9002 /* indicate that the hash table must be used to find the next TB */
9003 tcg_gen_exit_tb(0);
9004 break;
9005 case DISAS_TB_JUMP:
9006 /* nothing more to generate */
9007 break;
9008 case DISAS_WFI:
9009 gen_helper_wfi();
9010 break;
9011 case DISAS_SWI:
9012 gen_exception(EXCP_SWI);
9013 break;
9014 }
9015 if (dc->condjmp) {
9016 gen_set_label(dc->condlabel);
9017 gen_set_condexec(dc);
9018 gen_goto_tb(dc, 1, dc->pc);
9019 dc->condjmp = 0;
9020 }
9021 }
9022
9023 done_generating:
9024 gen_icount_end(tb, num_insns);
9025 *gen_opc_ptr = INDEX_op_end;
9026
9027 #ifdef DEBUG_DISAS
9028 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9029 qemu_log("----------------\n");
9030 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9031 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9032 qemu_log("\n");
9033 }
9034 #endif
9035 if (search_pc) {
9036 j = gen_opc_ptr - gen_opc_buf;
9037 lj++;
9038 while (lj <= j)
9039 gen_opc_instr_start[lj++] = 0;
9040 } else {
9041 tb->size = dc->pc - pc_start;
9042 tb->icount = num_insns;
9043 }
9044 }
9045
9046 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9047 {
9048 gen_intermediate_code_internal(env, tb, 0);
9049 }
9050
9051 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9052 {
9053 gen_intermediate_code_internal(env, tb, 1);
9054 }
9055
9056 static const char *cpu_mode_names[16] = {
9057 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9058 "???", "???", "???", "und", "???", "???", "???", "sys"
9059 };
9060
9061 void cpu_dump_state(CPUState *env, FILE *f,
9062 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9063 int flags)
9064 {
9065 int i;
9066 #if 0
9067 union {
9068 uint32_t i;
9069 float s;
9070 } s0, s1;
9071 CPU_DoubleU d;
9072 /* ??? This assumes float64 and double have the same layout.
9073 Oh well, it's only debug dumps. */
9074 union {
9075 float64 f64;
9076 double d;
9077 } d0;
9078 #endif
9079 uint32_t psr;
9080
9081 for(i=0;i<16;i++) {
9082 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9083 if ((i % 4) == 3)
9084 cpu_fprintf(f, "\n");
9085 else
9086 cpu_fprintf(f, " ");
9087 }
9088 psr = cpsr_read(env);
9089 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9090 psr,
9091 psr & (1 << 31) ? 'N' : '-',
9092 psr & (1 << 30) ? 'Z' : '-',
9093 psr & (1 << 29) ? 'C' : '-',
9094 psr & (1 << 28) ? 'V' : '-',
9095 psr & CPSR_T ? 'T' : 'A',
9096 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9097
9098 #if 0
9099 for (i = 0; i < 16; i++) {
9100 d.d = env->vfp.regs[i];
9101 s0.i = d.l.lower;
9102 s1.i = d.l.upper;
9103 d0.f64 = d.d;
9104 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9105 i * 2, (int)s0.i, s0.s,
9106 i * 2 + 1, (int)s1.i, s1.s,
9107 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9108 d0.d);
9109 }
9110 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9111 #endif
9112 }
9113
9114 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9115 unsigned long searched_pc, int pc_pos, void *puc)
9116 {
9117 env->regs[15] = gen_opc_pc[pc_pos];
9118 }