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