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