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