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