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