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