]> git.proxmox.com Git - mirror_qemu.git/blame - target-arm/translate.c
linux-user: arm: pass env to get_user_code_*
[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
8167ee88 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 20 */
74c21bd0 21#include "qemu/osdep.h"
2c0262af
FB
22
23#include "cpu.h"
ccd38087 24#include "internals.h"
76cad711 25#include "disas/disas.h"
57fec1fe 26#include "tcg-op.h"
1de7afc9 27#include "qemu/log.h"
534df156 28#include "qemu/bitops.h"
1d854765 29#include "arm_ldst.h"
1497c961 30
2ef6175a
RH
31#include "exec/helper-proto.h"
32#include "exec/helper-gen.h"
2c0262af 33
a7e30d84 34#include "trace-tcg.h"
508127e2 35#include "exec/log.h"
a7e30d84
LV
36
37
2b51668f
PM
38#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
39#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
be5e7a76 40/* currently all emulated v5 cores are also v5TE, so don't bother */
2b51668f 41#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
9ee6e8bb 42#define ENABLE_ARCH_5J 0
2b51668f
PM
43#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
44#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
45#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
46#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
47#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
b5ff1b31 48
86753403 49#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 50
f570c61e 51#include "translate.h"
e12ce78d 52
b5ff1b31
FB
53#if defined(CONFIG_USER_ONLY)
54#define IS_USER(s) 1
55#else
56#define IS_USER(s) (s->user)
57#endif
58
1bcea73e 59TCGv_env cpu_env;
ad69471c 60/* We reuse the same 64-bit temporaries for efficiency. */
a7812ae4 61static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
155c3eac 62static TCGv_i32 cpu_R[16];
78bcaa3e
RH
63TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
64TCGv_i64 cpu_exclusive_addr;
65TCGv_i64 cpu_exclusive_val;
426f5abc 66#ifdef CONFIG_USER_ONLY
78bcaa3e
RH
67TCGv_i64 cpu_exclusive_test;
68TCGv_i32 cpu_exclusive_info;
426f5abc 69#endif
ad69471c 70
b26eefb6 71/* FIXME: These should be removed. */
39d5492a 72static TCGv_i32 cpu_F0s, cpu_F1s;
a7812ae4 73static TCGv_i64 cpu_F0d, cpu_F1d;
b26eefb6 74
022c62cb 75#include "exec/gen-icount.h"
2e70f6ef 76
155c3eac
FN
77static const char *regnames[] =
78 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
79 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
80
b26eefb6
PB
81/* initialize TCG globals. */
82void arm_translate_init(void)
83{
155c3eac
FN
84 int i;
85
a7812ae4
PB
86 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
87
155c3eac 88 for (i = 0; i < 16; i++) {
e1ccc054 89 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 90 offsetof(CPUARMState, regs[i]),
155c3eac
FN
91 regnames[i]);
92 }
e1ccc054
RH
93 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
94 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
95 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
96 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
66c374de 97
e1ccc054 98 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 99 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
e1ccc054 100 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 101 offsetof(CPUARMState, exclusive_val), "exclusive_val");
426f5abc 102#ifdef CONFIG_USER_ONLY
e1ccc054 103 cpu_exclusive_test = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 104 offsetof(CPUARMState, exclusive_test), "exclusive_test");
e1ccc054 105 cpu_exclusive_info = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 106 offsetof(CPUARMState, exclusive_info), "exclusive_info");
426f5abc 107#endif
155c3eac 108
14ade10f 109 a64_translate_init();
b26eefb6
PB
110}
111
579d21cc
PM
112static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s)
113{
114 /* Return the mmu_idx to use for A32/T32 "unprivileged load/store"
115 * insns:
116 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
117 * otherwise, access as if at PL0.
118 */
119 switch (s->mmu_idx) {
120 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
121 case ARMMMUIdx_S12NSE0:
122 case ARMMMUIdx_S12NSE1:
123 return ARMMMUIdx_S12NSE0;
124 case ARMMMUIdx_S1E3:
125 case ARMMMUIdx_S1SE0:
126 case ARMMMUIdx_S1SE1:
127 return ARMMMUIdx_S1SE0;
128 case ARMMMUIdx_S2NS:
129 default:
130 g_assert_not_reached();
131 }
132}
133
39d5492a 134static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 135{
39d5492a 136 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
137 tcg_gen_ld_i32(tmp, cpu_env, offset);
138 return tmp;
139}
140
0ecb72a5 141#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 142
39d5492a 143static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
144{
145 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 146 tcg_temp_free_i32(var);
d9ba4830
PB
147}
148
149#define store_cpu_field(var, name) \
0ecb72a5 150 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 151
b26eefb6 152/* Set a variable to the value of a CPU register. */
39d5492a 153static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
154{
155 if (reg == 15) {
156 uint32_t addr;
b90372ad 157 /* normally, since we updated PC, we need only to add one insn */
b26eefb6
PB
158 if (s->thumb)
159 addr = (long)s->pc + 2;
160 else
161 addr = (long)s->pc + 4;
162 tcg_gen_movi_i32(var, addr);
163 } else {
155c3eac 164 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
165 }
166}
167
168/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 169static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 170{
39d5492a 171 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
172 load_reg_var(s, tmp, reg);
173 return tmp;
174}
175
176/* Set a CPU register. The source must be a temporary and will be
177 marked as dead. */
39d5492a 178static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
179{
180 if (reg == 15) {
181 tcg_gen_andi_i32(var, var, ~1);
182 s->is_jmp = DISAS_JUMP;
183 }
155c3eac 184 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 185 tcg_temp_free_i32(var);
b26eefb6
PB
186}
187
b26eefb6 188/* Value extensions. */
86831435
PB
189#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
190#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
191#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
192#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
193
1497c961
PB
194#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
195#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 196
b26eefb6 197
39d5492a 198static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 199{
39d5492a 200 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 201 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
202 tcg_temp_free_i32(tmp_mask);
203}
d9ba4830
PB
204/* Set NZCV flags from the high 4 bits of var. */
205#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
206
d4a2dc67 207static void gen_exception_internal(int excp)
d9ba4830 208{
d4a2dc67
PM
209 TCGv_i32 tcg_excp = tcg_const_i32(excp);
210
211 assert(excp_is_internal(excp));
212 gen_helper_exception_internal(cpu_env, tcg_excp);
213 tcg_temp_free_i32(tcg_excp);
214}
215
73710361 216static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
d4a2dc67
PM
217{
218 TCGv_i32 tcg_excp = tcg_const_i32(excp);
219 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
73710361 220 TCGv_i32 tcg_el = tcg_const_i32(target_el);
d4a2dc67 221
73710361
GB
222 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
223 tcg_syn, tcg_el);
224
225 tcg_temp_free_i32(tcg_el);
d4a2dc67
PM
226 tcg_temp_free_i32(tcg_syn);
227 tcg_temp_free_i32(tcg_excp);
d9ba4830
PB
228}
229
50225ad0
PM
230static void gen_ss_advance(DisasContext *s)
231{
232 /* If the singlestep state is Active-not-pending, advance to
233 * Active-pending.
234 */
235 if (s->ss_active) {
236 s->pstate_ss = 0;
237 gen_helper_clear_pstate_ss(cpu_env);
238 }
239}
240
241static void gen_step_complete_exception(DisasContext *s)
242{
243 /* We just completed step of an insn. Move from Active-not-pending
244 * to Active-pending, and then also take the swstep exception.
245 * This corresponds to making the (IMPDEF) choice to prioritize
246 * swstep exceptions over asynchronous exceptions taken to an exception
247 * level where debug is disabled. This choice has the advantage that
248 * we do not need to maintain internal state corresponding to the
249 * ISV/EX syndrome bits between completion of the step and generation
250 * of the exception, and our syndrome information is always correct.
251 */
252 gen_ss_advance(s);
73710361
GB
253 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
254 default_exception_el(s));
50225ad0
PM
255 s->is_jmp = DISAS_EXC;
256}
257
39d5492a 258static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 259{
39d5492a
PM
260 TCGv_i32 tmp1 = tcg_temp_new_i32();
261 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
262 tcg_gen_ext16s_i32(tmp1, a);
263 tcg_gen_ext16s_i32(tmp2, b);
3670669c 264 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 265 tcg_temp_free_i32(tmp2);
3670669c
PB
266 tcg_gen_sari_i32(a, a, 16);
267 tcg_gen_sari_i32(b, b, 16);
268 tcg_gen_mul_i32(b, b, a);
269 tcg_gen_mov_i32(a, tmp1);
7d1b0095 270 tcg_temp_free_i32(tmp1);
3670669c
PB
271}
272
273/* Byteswap each halfword. */
39d5492a 274static void gen_rev16(TCGv_i32 var)
3670669c 275{
39d5492a 276 TCGv_i32 tmp = tcg_temp_new_i32();
3670669c
PB
277 tcg_gen_shri_i32(tmp, var, 8);
278 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
279 tcg_gen_shli_i32(var, var, 8);
280 tcg_gen_andi_i32(var, var, 0xff00ff00);
281 tcg_gen_or_i32(var, var, tmp);
7d1b0095 282 tcg_temp_free_i32(tmp);
3670669c
PB
283}
284
285/* Byteswap low halfword and sign extend. */
39d5492a 286static void gen_revsh(TCGv_i32 var)
3670669c 287{
1a855029
AJ
288 tcg_gen_ext16u_i32(var, var);
289 tcg_gen_bswap16_i32(var, var);
290 tcg_gen_ext16s_i32(var, var);
3670669c
PB
291}
292
293/* Unsigned bitfield extract. */
39d5492a 294static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
3670669c
PB
295{
296 if (shift)
297 tcg_gen_shri_i32(var, var, shift);
298 tcg_gen_andi_i32(var, var, mask);
299}
300
301/* Signed bitfield extract. */
39d5492a 302static void gen_sbfx(TCGv_i32 var, int shift, int width)
3670669c
PB
303{
304 uint32_t signbit;
305
306 if (shift)
307 tcg_gen_sari_i32(var, var, shift);
308 if (shift + width < 32) {
309 signbit = 1u << (width - 1);
310 tcg_gen_andi_i32(var, var, (1u << width) - 1);
311 tcg_gen_xori_i32(var, var, signbit);
312 tcg_gen_subi_i32(var, var, signbit);
313 }
314}
315
838fa72d 316/* Return (b << 32) + a. Mark inputs as dead */
39d5492a 317static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
3670669c 318{
838fa72d
AJ
319 TCGv_i64 tmp64 = tcg_temp_new_i64();
320
321 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 322 tcg_temp_free_i32(b);
838fa72d
AJ
323 tcg_gen_shli_i64(tmp64, tmp64, 32);
324 tcg_gen_add_i64(a, tmp64, a);
325
326 tcg_temp_free_i64(tmp64);
327 return a;
328}
329
330/* Return (b << 32) - a. Mark inputs as dead. */
39d5492a 331static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
838fa72d
AJ
332{
333 TCGv_i64 tmp64 = tcg_temp_new_i64();
334
335 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 336 tcg_temp_free_i32(b);
838fa72d
AJ
337 tcg_gen_shli_i64(tmp64, tmp64, 32);
338 tcg_gen_sub_i64(a, tmp64, a);
339
340 tcg_temp_free_i64(tmp64);
341 return a;
3670669c
PB
342}
343
5e3f878a 344/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 345static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 346{
39d5492a
PM
347 TCGv_i32 lo = tcg_temp_new_i32();
348 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 349 TCGv_i64 ret;
5e3f878a 350
831d7fe8 351 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 352 tcg_temp_free_i32(a);
7d1b0095 353 tcg_temp_free_i32(b);
831d7fe8
RH
354
355 ret = tcg_temp_new_i64();
356 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
357 tcg_temp_free_i32(lo);
358 tcg_temp_free_i32(hi);
831d7fe8
RH
359
360 return ret;
5e3f878a
PB
361}
362
39d5492a 363static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 364{
39d5492a
PM
365 TCGv_i32 lo = tcg_temp_new_i32();
366 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 367 TCGv_i64 ret;
5e3f878a 368
831d7fe8 369 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 370 tcg_temp_free_i32(a);
7d1b0095 371 tcg_temp_free_i32(b);
831d7fe8
RH
372
373 ret = tcg_temp_new_i64();
374 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
375 tcg_temp_free_i32(lo);
376 tcg_temp_free_i32(hi);
831d7fe8
RH
377
378 return ret;
5e3f878a
PB
379}
380
8f01245e 381/* Swap low and high halfwords. */
39d5492a 382static void gen_swap_half(TCGv_i32 var)
8f01245e 383{
39d5492a 384 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e
PB
385 tcg_gen_shri_i32(tmp, var, 16);
386 tcg_gen_shli_i32(var, var, 16);
387 tcg_gen_or_i32(var, var, tmp);
7d1b0095 388 tcg_temp_free_i32(tmp);
8f01245e
PB
389}
390
b26eefb6
PB
391/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
392 tmp = (t0 ^ t1) & 0x8000;
393 t0 &= ~0x8000;
394 t1 &= ~0x8000;
395 t0 = (t0 + t1) ^ tmp;
396 */
397
39d5492a 398static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 399{
39d5492a 400 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
401 tcg_gen_xor_i32(tmp, t0, t1);
402 tcg_gen_andi_i32(tmp, tmp, 0x8000);
403 tcg_gen_andi_i32(t0, t0, ~0x8000);
404 tcg_gen_andi_i32(t1, t1, ~0x8000);
405 tcg_gen_add_i32(t0, t0, t1);
406 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
407 tcg_temp_free_i32(tmp);
408 tcg_temp_free_i32(t1);
b26eefb6
PB
409}
410
411/* Set CF to the top bit of var. */
39d5492a 412static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 413{
66c374de 414 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
415}
416
417/* Set N and Z flags from var. */
39d5492a 418static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 419{
66c374de
AJ
420 tcg_gen_mov_i32(cpu_NF, var);
421 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
422}
423
424/* T0 += T1 + CF. */
39d5492a 425static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 426{
396e467c 427 tcg_gen_add_i32(t0, t0, t1);
66c374de 428 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
429}
430
e9bb4aa9 431/* dest = T0 + T1 + CF. */
39d5492a 432static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 433{
e9bb4aa9 434 tcg_gen_add_i32(dest, t0, t1);
66c374de 435 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
436}
437
3670669c 438/* dest = T0 - T1 + CF - 1. */
39d5492a 439static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 440{
3670669c 441 tcg_gen_sub_i32(dest, t0, t1);
66c374de 442 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 443 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
444}
445
72485ec4 446/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 447static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 448{
39d5492a 449 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
450 tcg_gen_movi_i32(tmp, 0);
451 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 452 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 453 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
454 tcg_gen_xor_i32(tmp, t0, t1);
455 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
456 tcg_temp_free_i32(tmp);
457 tcg_gen_mov_i32(dest, cpu_NF);
458}
459
49b4c31e 460/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 461static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 462{
39d5492a 463 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
464 if (TCG_TARGET_HAS_add2_i32) {
465 tcg_gen_movi_i32(tmp, 0);
466 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 467 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
468 } else {
469 TCGv_i64 q0 = tcg_temp_new_i64();
470 TCGv_i64 q1 = tcg_temp_new_i64();
471 tcg_gen_extu_i32_i64(q0, t0);
472 tcg_gen_extu_i32_i64(q1, t1);
473 tcg_gen_add_i64(q0, q0, q1);
474 tcg_gen_extu_i32_i64(q1, cpu_CF);
475 tcg_gen_add_i64(q0, q0, q1);
476 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
477 tcg_temp_free_i64(q0);
478 tcg_temp_free_i64(q1);
479 }
480 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
481 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
482 tcg_gen_xor_i32(tmp, t0, t1);
483 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
484 tcg_temp_free_i32(tmp);
485 tcg_gen_mov_i32(dest, cpu_NF);
486}
487
72485ec4 488/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 489static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 490{
39d5492a 491 TCGv_i32 tmp;
72485ec4
AJ
492 tcg_gen_sub_i32(cpu_NF, t0, t1);
493 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
494 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
495 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
496 tmp = tcg_temp_new_i32();
497 tcg_gen_xor_i32(tmp, t0, t1);
498 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
499 tcg_temp_free_i32(tmp);
500 tcg_gen_mov_i32(dest, cpu_NF);
501}
502
e77f0832 503/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 504static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 505{
39d5492a 506 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
507 tcg_gen_not_i32(tmp, t1);
508 gen_adc_CC(dest, t0, tmp);
39d5492a 509 tcg_temp_free_i32(tmp);
2de68a49
RH
510}
511
365af80e 512#define GEN_SHIFT(name) \
39d5492a 513static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 514{ \
39d5492a 515 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
516 tmp1 = tcg_temp_new_i32(); \
517 tcg_gen_andi_i32(tmp1, t1, 0xff); \
518 tmp2 = tcg_const_i32(0); \
519 tmp3 = tcg_const_i32(0x1f); \
520 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
521 tcg_temp_free_i32(tmp3); \
522 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
523 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
524 tcg_temp_free_i32(tmp2); \
525 tcg_temp_free_i32(tmp1); \
526}
527GEN_SHIFT(shl)
528GEN_SHIFT(shr)
529#undef GEN_SHIFT
530
39d5492a 531static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 532{
39d5492a 533 TCGv_i32 tmp1, tmp2;
365af80e
AJ
534 tmp1 = tcg_temp_new_i32();
535 tcg_gen_andi_i32(tmp1, t1, 0xff);
536 tmp2 = tcg_const_i32(0x1f);
537 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
538 tcg_temp_free_i32(tmp2);
539 tcg_gen_sar_i32(dest, t0, tmp1);
540 tcg_temp_free_i32(tmp1);
541}
542
39d5492a 543static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
36c91fd1 544{
39d5492a
PM
545 TCGv_i32 c0 = tcg_const_i32(0);
546 TCGv_i32 tmp = tcg_temp_new_i32();
36c91fd1
PM
547 tcg_gen_neg_i32(tmp, src);
548 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
549 tcg_temp_free_i32(c0);
550 tcg_temp_free_i32(tmp);
551}
ad69471c 552
39d5492a 553static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 554{
9a119ff6 555 if (shift == 0) {
66c374de 556 tcg_gen_andi_i32(cpu_CF, var, 1);
b26eefb6 557 } else {
66c374de
AJ
558 tcg_gen_shri_i32(cpu_CF, var, shift);
559 if (shift != 31) {
560 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
561 }
9a119ff6 562 }
9a119ff6 563}
b26eefb6 564
9a119ff6 565/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
566static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
567 int shift, int flags)
9a119ff6
PB
568{
569 switch (shiftop) {
570 case 0: /* LSL */
571 if (shift != 0) {
572 if (flags)
573 shifter_out_im(var, 32 - shift);
574 tcg_gen_shli_i32(var, var, shift);
575 }
576 break;
577 case 1: /* LSR */
578 if (shift == 0) {
579 if (flags) {
66c374de 580 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
581 }
582 tcg_gen_movi_i32(var, 0);
583 } else {
584 if (flags)
585 shifter_out_im(var, shift - 1);
586 tcg_gen_shri_i32(var, var, shift);
587 }
588 break;
589 case 2: /* ASR */
590 if (shift == 0)
591 shift = 32;
592 if (flags)
593 shifter_out_im(var, shift - 1);
594 if (shift == 32)
595 shift = 31;
596 tcg_gen_sari_i32(var, var, shift);
597 break;
598 case 3: /* ROR/RRX */
599 if (shift != 0) {
600 if (flags)
601 shifter_out_im(var, shift - 1);
f669df27 602 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 603 } else {
39d5492a 604 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 605 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
606 if (flags)
607 shifter_out_im(var, 0);
608 tcg_gen_shri_i32(var, var, 1);
b26eefb6 609 tcg_gen_or_i32(var, var, tmp);
7d1b0095 610 tcg_temp_free_i32(tmp);
b26eefb6
PB
611 }
612 }
613};
614
39d5492a
PM
615static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
616 TCGv_i32 shift, int flags)
8984bd2e
PB
617{
618 if (flags) {
619 switch (shiftop) {
9ef39277
BS
620 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
621 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
622 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
623 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
624 }
625 } else {
626 switch (shiftop) {
365af80e
AJ
627 case 0:
628 gen_shl(var, var, shift);
629 break;
630 case 1:
631 gen_shr(var, var, shift);
632 break;
633 case 2:
634 gen_sar(var, var, shift);
635 break;
f669df27
AJ
636 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
637 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
638 }
639 }
7d1b0095 640 tcg_temp_free_i32(shift);
8984bd2e
PB
641}
642
6ddbc6e4
PB
643#define PAS_OP(pfx) \
644 switch (op2) { \
645 case 0: gen_pas_helper(glue(pfx,add16)); break; \
646 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
647 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
648 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
649 case 4: gen_pas_helper(glue(pfx,add8)); break; \
650 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
651 }
39d5492a 652static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 653{
a7812ae4 654 TCGv_ptr tmp;
6ddbc6e4
PB
655
656 switch (op1) {
657#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
658 case 1:
a7812ae4 659 tmp = tcg_temp_new_ptr();
0ecb72a5 660 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 661 PAS_OP(s)
b75263d6 662 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
663 break;
664 case 5:
a7812ae4 665 tmp = tcg_temp_new_ptr();
0ecb72a5 666 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 667 PAS_OP(u)
b75263d6 668 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
669 break;
670#undef gen_pas_helper
671#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
672 case 2:
673 PAS_OP(q);
674 break;
675 case 3:
676 PAS_OP(sh);
677 break;
678 case 6:
679 PAS_OP(uq);
680 break;
681 case 7:
682 PAS_OP(uh);
683 break;
684#undef gen_pas_helper
685 }
686}
9ee6e8bb
PB
687#undef PAS_OP
688
6ddbc6e4
PB
689/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
690#define PAS_OP(pfx) \
ed89a2f1 691 switch (op1) { \
6ddbc6e4
PB
692 case 0: gen_pas_helper(glue(pfx,add8)); break; \
693 case 1: gen_pas_helper(glue(pfx,add16)); break; \
694 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
695 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
696 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
697 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
698 }
39d5492a 699static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 700{
a7812ae4 701 TCGv_ptr tmp;
6ddbc6e4 702
ed89a2f1 703 switch (op2) {
6ddbc6e4
PB
704#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
705 case 0:
a7812ae4 706 tmp = tcg_temp_new_ptr();
0ecb72a5 707 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 708 PAS_OP(s)
b75263d6 709 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
710 break;
711 case 4:
a7812ae4 712 tmp = tcg_temp_new_ptr();
0ecb72a5 713 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 714 PAS_OP(u)
b75263d6 715 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
716 break;
717#undef gen_pas_helper
718#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
719 case 1:
720 PAS_OP(q);
721 break;
722 case 2:
723 PAS_OP(sh);
724 break;
725 case 5:
726 PAS_OP(uq);
727 break;
728 case 6:
729 PAS_OP(uh);
730 break;
731#undef gen_pas_helper
732 }
733}
9ee6e8bb
PB
734#undef PAS_OP
735
39fb730a 736/*
6c2c63d3 737 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
738 * This is common between ARM and Aarch64 targets.
739 */
6c2c63d3 740void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 741{
6c2c63d3
RH
742 TCGv_i32 value;
743 TCGCond cond;
744 bool global = true;
d9ba4830 745
d9ba4830
PB
746 switch (cc) {
747 case 0: /* eq: Z */
d9ba4830 748 case 1: /* ne: !Z */
6c2c63d3
RH
749 cond = TCG_COND_EQ;
750 value = cpu_ZF;
d9ba4830 751 break;
6c2c63d3 752
d9ba4830 753 case 2: /* cs: C */
d9ba4830 754 case 3: /* cc: !C */
6c2c63d3
RH
755 cond = TCG_COND_NE;
756 value = cpu_CF;
d9ba4830 757 break;
6c2c63d3 758
d9ba4830 759 case 4: /* mi: N */
d9ba4830 760 case 5: /* pl: !N */
6c2c63d3
RH
761 cond = TCG_COND_LT;
762 value = cpu_NF;
d9ba4830 763 break;
6c2c63d3 764
d9ba4830 765 case 6: /* vs: V */
d9ba4830 766 case 7: /* vc: !V */
6c2c63d3
RH
767 cond = TCG_COND_LT;
768 value = cpu_VF;
d9ba4830 769 break;
6c2c63d3 770
d9ba4830 771 case 8: /* hi: C && !Z */
6c2c63d3
RH
772 case 9: /* ls: !C || Z -> !(C && !Z) */
773 cond = TCG_COND_NE;
774 value = tcg_temp_new_i32();
775 global = false;
776 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
777 ZF is non-zero for !Z; so AND the two subexpressions. */
778 tcg_gen_neg_i32(value, cpu_CF);
779 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 780 break;
6c2c63d3 781
d9ba4830 782 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 783 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
784 /* Since we're only interested in the sign bit, == 0 is >= 0. */
785 cond = TCG_COND_GE;
786 value = tcg_temp_new_i32();
787 global = false;
788 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 789 break;
6c2c63d3 790
d9ba4830 791 case 12: /* gt: !Z && N == V */
d9ba4830 792 case 13: /* le: Z || N != V */
6c2c63d3
RH
793 cond = TCG_COND_NE;
794 value = tcg_temp_new_i32();
795 global = false;
796 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
797 * the sign bit then AND with ZF to yield the result. */
798 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
799 tcg_gen_sari_i32(value, value, 31);
800 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 801 break;
6c2c63d3 802
9305eac0
RH
803 case 14: /* always */
804 case 15: /* always */
805 /* Use the ALWAYS condition, which will fold early.
806 * It doesn't matter what we use for the value. */
807 cond = TCG_COND_ALWAYS;
808 value = cpu_ZF;
809 goto no_invert;
810
d9ba4830
PB
811 default:
812 fprintf(stderr, "Bad condition code 0x%x\n", cc);
813 abort();
814 }
6c2c63d3
RH
815
816 if (cc & 1) {
817 cond = tcg_invert_cond(cond);
818 }
819
9305eac0 820 no_invert:
6c2c63d3
RH
821 cmp->cond = cond;
822 cmp->value = value;
823 cmp->value_global = global;
824}
825
826void arm_free_cc(DisasCompare *cmp)
827{
828 if (!cmp->value_global) {
829 tcg_temp_free_i32(cmp->value);
830 }
831}
832
833void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
834{
835 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
836}
837
838void arm_gen_test_cc(int cc, TCGLabel *label)
839{
840 DisasCompare cmp;
841 arm_test_cc(&cmp, cc);
842 arm_jump_cc(&cmp, label);
843 arm_free_cc(&cmp);
d9ba4830 844}
2c0262af 845
b1d8e52e 846static const uint8_t table_logic_cc[16] = {
2c0262af
FB
847 1, /* and */
848 1, /* xor */
849 0, /* sub */
850 0, /* rsb */
851 0, /* add */
852 0, /* adc */
853 0, /* sbc */
854 0, /* rsc */
855 1, /* andl */
856 1, /* xorl */
857 0, /* cmp */
858 0, /* cmn */
859 1, /* orr */
860 1, /* mov */
861 1, /* bic */
862 1, /* mvn */
863};
3b46e624 864
d9ba4830
PB
865/* Set PC and Thumb state from an immediate address. */
866static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 867{
39d5492a 868 TCGv_i32 tmp;
99c475ab 869
577bf808 870 s->is_jmp = DISAS_JUMP;
d9ba4830 871 if (s->thumb != (addr & 1)) {
7d1b0095 872 tmp = tcg_temp_new_i32();
d9ba4830 873 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 874 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 875 tcg_temp_free_i32(tmp);
d9ba4830 876 }
155c3eac 877 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
878}
879
880/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 881static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 882{
577bf808 883 s->is_jmp = DISAS_JUMP;
155c3eac
FN
884 tcg_gen_andi_i32(cpu_R[15], var, ~1);
885 tcg_gen_andi_i32(var, var, 1);
886 store_cpu_field(var, thumb);
d9ba4830
PB
887}
888
21aeb343
JR
889/* Variant of store_reg which uses branch&exchange logic when storing
890 to r15 in ARM architecture v7 and above. The source must be a temporary
891 and will be marked as dead. */
7dcc1f89 892static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
893{
894 if (reg == 15 && ENABLE_ARCH_7) {
895 gen_bx(s, var);
896 } else {
897 store_reg(s, reg, var);
898 }
899}
900
be5e7a76
DES
901/* Variant of store_reg which uses branch&exchange logic when storing
902 * to r15 in ARM architecture v5T and above. This is used for storing
903 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
904 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 905static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
906{
907 if (reg == 15 && ENABLE_ARCH_5) {
908 gen_bx(s, var);
909 } else {
910 store_reg(s, reg, var);
911 }
912}
913
08307563
PM
914/* Abstractions of "generate code to do a guest load/store for
915 * AArch32", where a vaddr is always 32 bits (and is zero
916 * extended if we're a 64 bit core) and data is also
917 * 32 bits unless specifically doing a 64 bit access.
918 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 919 * that the address argument is TCGv_i32 rather than TCGv.
08307563
PM
920 */
921#if TARGET_LONG_BITS == 32
922
09f78135
RH
923#define DO_GEN_LD(SUFF, OPC) \
924static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
08307563 925{ \
30901475 926 tcg_gen_qemu_ld_i32(val, addr, index, (OPC)); \
08307563
PM
927}
928
09f78135
RH
929#define DO_GEN_ST(SUFF, OPC) \
930static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
08307563 931{ \
30901475 932 tcg_gen_qemu_st_i32(val, addr, index, (OPC)); \
08307563
PM
933}
934
935static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
936{
09f78135 937 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
08307563
PM
938}
939
940static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
941{
09f78135 942 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
08307563
PM
943}
944
945#else
946
09f78135
RH
947#define DO_GEN_LD(SUFF, OPC) \
948static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
08307563
PM
949{ \
950 TCGv addr64 = tcg_temp_new(); \
08307563 951 tcg_gen_extu_i32_i64(addr64, addr); \
09f78135 952 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
08307563 953 tcg_temp_free(addr64); \
08307563
PM
954}
955
09f78135
RH
956#define DO_GEN_ST(SUFF, OPC) \
957static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
08307563
PM
958{ \
959 TCGv addr64 = tcg_temp_new(); \
08307563 960 tcg_gen_extu_i32_i64(addr64, addr); \
09f78135 961 tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
08307563 962 tcg_temp_free(addr64); \
08307563
PM
963}
964
965static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
966{
967 TCGv addr64 = tcg_temp_new();
968 tcg_gen_extu_i32_i64(addr64, addr);
09f78135 969 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
08307563
PM
970 tcg_temp_free(addr64);
971}
972
973static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
974{
975 TCGv addr64 = tcg_temp_new();
976 tcg_gen_extu_i32_i64(addr64, addr);
09f78135 977 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
08307563
PM
978 tcg_temp_free(addr64);
979}
980
981#endif
982
09f78135
RH
983DO_GEN_LD(8s, MO_SB)
984DO_GEN_LD(8u, MO_UB)
985DO_GEN_LD(16s, MO_TESW)
986DO_GEN_LD(16u, MO_TEUW)
987DO_GEN_LD(32u, MO_TEUL)
30901475
AB
988/* 'a' variants include an alignment check */
989DO_GEN_LD(16ua, MO_TEUW | MO_ALIGN)
990DO_GEN_LD(32ua, MO_TEUL | MO_ALIGN)
09f78135
RH
991DO_GEN_ST(8, MO_UB)
992DO_GEN_ST(16, MO_TEUW)
993DO_GEN_ST(32, MO_TEUL)
08307563 994
eaed129d 995static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
5e3f878a 996{
40f860cd 997 tcg_gen_movi_i32(cpu_R[15], val);
5e3f878a
PB
998}
999
37e6456e
PM
1000static inline void gen_hvc(DisasContext *s, int imm16)
1001{
1002 /* The pre HVC helper handles cases when HVC gets trapped
1003 * as an undefined insn by runtime configuration (ie before
1004 * the insn really executes).
1005 */
1006 gen_set_pc_im(s, s->pc - 4);
1007 gen_helper_pre_hvc(cpu_env);
1008 /* Otherwise we will treat this as a real exception which
1009 * happens after execution of the insn. (The distinction matters
1010 * for the PC value reported to the exception handler and also
1011 * for single stepping.)
1012 */
1013 s->svc_imm = imm16;
1014 gen_set_pc_im(s, s->pc);
1015 s->is_jmp = DISAS_HVC;
1016}
1017
1018static inline void gen_smc(DisasContext *s)
1019{
1020 /* As with HVC, we may take an exception either before or after
1021 * the insn executes.
1022 */
1023 TCGv_i32 tmp;
1024
1025 gen_set_pc_im(s, s->pc - 4);
1026 tmp = tcg_const_i32(syn_aa32_smc());
1027 gen_helper_pre_smc(cpu_env, tmp);
1028 tcg_temp_free_i32(tmp);
1029 gen_set_pc_im(s, s->pc);
1030 s->is_jmp = DISAS_SMC;
1031}
1032
d4a2dc67
PM
1033static inline void
1034gen_set_condexec (DisasContext *s)
1035{
1036 if (s->condexec_mask) {
1037 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
1038 TCGv_i32 tmp = tcg_temp_new_i32();
1039 tcg_gen_movi_i32(tmp, val);
1040 store_cpu_field(tmp, condexec_bits);
1041 }
1042}
1043
1044static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1045{
1046 gen_set_condexec(s);
1047 gen_set_pc_im(s, s->pc - offset);
1048 gen_exception_internal(excp);
1049 s->is_jmp = DISAS_JUMP;
1050}
1051
73710361
GB
1052static void gen_exception_insn(DisasContext *s, int offset, int excp,
1053 int syn, uint32_t target_el)
d4a2dc67
PM
1054{
1055 gen_set_condexec(s);
1056 gen_set_pc_im(s, s->pc - offset);
73710361 1057 gen_exception(excp, syn, target_el);
d4a2dc67
PM
1058 s->is_jmp = DISAS_JUMP;
1059}
1060
b5ff1b31
FB
1061/* Force a TB lookup after an instruction that changes the CPU state. */
1062static inline void gen_lookup_tb(DisasContext *s)
1063{
a6445c52 1064 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
577bf808 1065 s->is_jmp = DISAS_JUMP;
b5ff1b31
FB
1066}
1067
b0109805 1068static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1069 TCGv_i32 var)
2c0262af 1070{
1e8d4eec 1071 int val, rm, shift, shiftop;
39d5492a 1072 TCGv_i32 offset;
2c0262af
FB
1073
1074 if (!(insn & (1 << 25))) {
1075 /* immediate */
1076 val = insn & 0xfff;
1077 if (!(insn & (1 << 23)))
1078 val = -val;
537730b9 1079 if (val != 0)
b0109805 1080 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1081 } else {
1082 /* shift/register */
1083 rm = (insn) & 0xf;
1084 shift = (insn >> 7) & 0x1f;
1e8d4eec 1085 shiftop = (insn >> 5) & 3;
b26eefb6 1086 offset = load_reg(s, rm);
9a119ff6 1087 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1088 if (!(insn & (1 << 23)))
b0109805 1089 tcg_gen_sub_i32(var, var, offset);
2c0262af 1090 else
b0109805 1091 tcg_gen_add_i32(var, var, offset);
7d1b0095 1092 tcg_temp_free_i32(offset);
2c0262af
FB
1093 }
1094}
1095
191f9a93 1096static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1097 int extra, TCGv_i32 var)
2c0262af
FB
1098{
1099 int val, rm;
39d5492a 1100 TCGv_i32 offset;
3b46e624 1101
2c0262af
FB
1102 if (insn & (1 << 22)) {
1103 /* immediate */
1104 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1105 if (!(insn & (1 << 23)))
1106 val = -val;
18acad92 1107 val += extra;
537730b9 1108 if (val != 0)
b0109805 1109 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1110 } else {
1111 /* register */
191f9a93 1112 if (extra)
b0109805 1113 tcg_gen_addi_i32(var, var, extra);
2c0262af 1114 rm = (insn) & 0xf;
b26eefb6 1115 offset = load_reg(s, rm);
2c0262af 1116 if (!(insn & (1 << 23)))
b0109805 1117 tcg_gen_sub_i32(var, var, offset);
2c0262af 1118 else
b0109805 1119 tcg_gen_add_i32(var, var, offset);
7d1b0095 1120 tcg_temp_free_i32(offset);
2c0262af
FB
1121 }
1122}
1123
5aaebd13
PM
1124static TCGv_ptr get_fpstatus_ptr(int neon)
1125{
1126 TCGv_ptr statusptr = tcg_temp_new_ptr();
1127 int offset;
1128 if (neon) {
0ecb72a5 1129 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1130 } else {
0ecb72a5 1131 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1132 }
1133 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1134 return statusptr;
1135}
1136
4373f3ce
PB
1137#define VFP_OP2(name) \
1138static inline void gen_vfp_##name(int dp) \
1139{ \
ae1857ec
PM
1140 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1141 if (dp) { \
1142 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1143 } else { \
1144 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1145 } \
1146 tcg_temp_free_ptr(fpst); \
b7bcbe95
FB
1147}
1148
4373f3ce
PB
1149VFP_OP2(add)
1150VFP_OP2(sub)
1151VFP_OP2(mul)
1152VFP_OP2(div)
1153
1154#undef VFP_OP2
1155
605a6aed
PM
1156static inline void gen_vfp_F1_mul(int dp)
1157{
1158 /* Like gen_vfp_mul() but put result in F1 */
ae1857ec 1159 TCGv_ptr fpst = get_fpstatus_ptr(0);
605a6aed 1160 if (dp) {
ae1857ec 1161 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
605a6aed 1162 } else {
ae1857ec 1163 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
605a6aed 1164 }
ae1857ec 1165 tcg_temp_free_ptr(fpst);
605a6aed
PM
1166}
1167
1168static inline void gen_vfp_F1_neg(int dp)
1169{
1170 /* Like gen_vfp_neg() but put result in F1 */
1171 if (dp) {
1172 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1173 } else {
1174 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1175 }
1176}
1177
4373f3ce
PB
1178static inline void gen_vfp_abs(int dp)
1179{
1180 if (dp)
1181 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1182 else
1183 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1184}
1185
1186static inline void gen_vfp_neg(int dp)
1187{
1188 if (dp)
1189 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1190 else
1191 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1192}
1193
1194static inline void gen_vfp_sqrt(int dp)
1195{
1196 if (dp)
1197 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1198 else
1199 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1200}
1201
1202static inline void gen_vfp_cmp(int dp)
1203{
1204 if (dp)
1205 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1206 else
1207 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1208}
1209
1210static inline void gen_vfp_cmpe(int dp)
1211{
1212 if (dp)
1213 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1214 else
1215 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1216}
1217
1218static inline void gen_vfp_F1_ld0(int dp)
1219{
1220 if (dp)
5b340b51 1221 tcg_gen_movi_i64(cpu_F1d, 0);
4373f3ce 1222 else
5b340b51 1223 tcg_gen_movi_i32(cpu_F1s, 0);
4373f3ce
PB
1224}
1225
5500b06c
PM
1226#define VFP_GEN_ITOF(name) \
1227static inline void gen_vfp_##name(int dp, int neon) \
1228{ \
5aaebd13 1229 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1230 if (dp) { \
1231 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1232 } else { \
1233 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1234 } \
b7fa9214 1235 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1236}
1237
5500b06c
PM
1238VFP_GEN_ITOF(uito)
1239VFP_GEN_ITOF(sito)
1240#undef VFP_GEN_ITOF
4373f3ce 1241
5500b06c
PM
1242#define VFP_GEN_FTOI(name) \
1243static inline void gen_vfp_##name(int dp, int neon) \
1244{ \
5aaebd13 1245 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1246 if (dp) { \
1247 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1248 } else { \
1249 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1250 } \
b7fa9214 1251 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1252}
1253
5500b06c
PM
1254VFP_GEN_FTOI(toui)
1255VFP_GEN_FTOI(touiz)
1256VFP_GEN_FTOI(tosi)
1257VFP_GEN_FTOI(tosiz)
1258#undef VFP_GEN_FTOI
4373f3ce 1259
16d5b3ca 1260#define VFP_GEN_FIX(name, round) \
5500b06c 1261static inline void gen_vfp_##name(int dp, int shift, int neon) \
4373f3ce 1262{ \
39d5492a 1263 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
5aaebd13 1264 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c 1265 if (dp) { \
16d5b3ca
WN
1266 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1267 statusptr); \
5500b06c 1268 } else { \
16d5b3ca
WN
1269 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1270 statusptr); \
5500b06c 1271 } \
b75263d6 1272 tcg_temp_free_i32(tmp_shift); \
b7fa9214 1273 tcg_temp_free_ptr(statusptr); \
9ee6e8bb 1274}
16d5b3ca
WN
1275VFP_GEN_FIX(tosh, _round_to_zero)
1276VFP_GEN_FIX(tosl, _round_to_zero)
1277VFP_GEN_FIX(touh, _round_to_zero)
1278VFP_GEN_FIX(toul, _round_to_zero)
1279VFP_GEN_FIX(shto, )
1280VFP_GEN_FIX(slto, )
1281VFP_GEN_FIX(uhto, )
1282VFP_GEN_FIX(ulto, )
4373f3ce 1283#undef VFP_GEN_FIX
9ee6e8bb 1284
39d5492a 1285static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1286{
08307563 1287 if (dp) {
6ce2faf4 1288 gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
08307563 1289 } else {
6ce2faf4 1290 gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
08307563 1291 }
b5ff1b31
FB
1292}
1293
39d5492a 1294static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1295{
08307563 1296 if (dp) {
6ce2faf4 1297 gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
08307563 1298 } else {
6ce2faf4 1299 gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
08307563 1300 }
b5ff1b31
FB
1301}
1302
8e96005d
FB
1303static inline long
1304vfp_reg_offset (int dp, int reg)
1305{
1306 if (dp)
1307 return offsetof(CPUARMState, vfp.regs[reg]);
1308 else if (reg & 1) {
1309 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1310 + offsetof(CPU_DoubleU, l.upper);
1311 } else {
1312 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1313 + offsetof(CPU_DoubleU, l.lower);
1314 }
1315}
9ee6e8bb
PB
1316
1317/* Return the offset of a 32-bit piece of a NEON register.
1318 zero is the least significant end of the register. */
1319static inline long
1320neon_reg_offset (int reg, int n)
1321{
1322 int sreg;
1323 sreg = reg * 2 + n;
1324 return vfp_reg_offset(0, sreg);
1325}
1326
39d5492a 1327static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1328{
39d5492a 1329 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1330 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1331 return tmp;
1332}
1333
39d5492a 1334static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1335{
1336 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1337 tcg_temp_free_i32(var);
8f8e3aa4
PB
1338}
1339
a7812ae4 1340static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1341{
1342 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1343}
1344
a7812ae4 1345static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1346{
1347 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1348}
1349
4373f3ce
PB
1350#define tcg_gen_ld_f32 tcg_gen_ld_i32
1351#define tcg_gen_ld_f64 tcg_gen_ld_i64
1352#define tcg_gen_st_f32 tcg_gen_st_i32
1353#define tcg_gen_st_f64 tcg_gen_st_i64
1354
b7bcbe95
FB
1355static inline void gen_mov_F0_vreg(int dp, int reg)
1356{
1357 if (dp)
4373f3ce 1358 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1359 else
4373f3ce 1360 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1361}
1362
1363static inline void gen_mov_F1_vreg(int dp, int reg)
1364{
1365 if (dp)
4373f3ce 1366 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1367 else
4373f3ce 1368 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1369}
1370
1371static inline void gen_mov_vreg_F0(int dp, int reg)
1372{
1373 if (dp)
4373f3ce 1374 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1375 else
4373f3ce 1376 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1377}
1378
18c9b560
AZ
1379#define ARM_CP_RW_BIT (1 << 20)
1380
a7812ae4 1381static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1382{
0ecb72a5 1383 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1384}
1385
a7812ae4 1386static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1387{
0ecb72a5 1388 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1389}
1390
39d5492a 1391static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1392{
39d5492a 1393 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1394 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1395 return var;
e677137d
PB
1396}
1397
39d5492a 1398static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1399{
0ecb72a5 1400 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1401 tcg_temp_free_i32(var);
e677137d
PB
1402}
1403
1404static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1405{
1406 iwmmxt_store_reg(cpu_M0, rn);
1407}
1408
1409static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1410{
1411 iwmmxt_load_reg(cpu_M0, rn);
1412}
1413
1414static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1415{
1416 iwmmxt_load_reg(cpu_V1, rn);
1417 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1418}
1419
1420static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1421{
1422 iwmmxt_load_reg(cpu_V1, rn);
1423 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1424}
1425
1426static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1427{
1428 iwmmxt_load_reg(cpu_V1, rn);
1429 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1430}
1431
1432#define IWMMXT_OP(name) \
1433static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1434{ \
1435 iwmmxt_load_reg(cpu_V1, rn); \
1436 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1437}
1438
477955bd
PM
1439#define IWMMXT_OP_ENV(name) \
1440static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1441{ \
1442 iwmmxt_load_reg(cpu_V1, rn); \
1443 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1444}
1445
1446#define IWMMXT_OP_ENV_SIZE(name) \
1447IWMMXT_OP_ENV(name##b) \
1448IWMMXT_OP_ENV(name##w) \
1449IWMMXT_OP_ENV(name##l)
e677137d 1450
477955bd 1451#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1452static inline void gen_op_iwmmxt_##name##_M0(void) \
1453{ \
477955bd 1454 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1455}
1456
1457IWMMXT_OP(maddsq)
1458IWMMXT_OP(madduq)
1459IWMMXT_OP(sadb)
1460IWMMXT_OP(sadw)
1461IWMMXT_OP(mulslw)
1462IWMMXT_OP(mulshw)
1463IWMMXT_OP(mululw)
1464IWMMXT_OP(muluhw)
1465IWMMXT_OP(macsw)
1466IWMMXT_OP(macuw)
1467
477955bd
PM
1468IWMMXT_OP_ENV_SIZE(unpackl)
1469IWMMXT_OP_ENV_SIZE(unpackh)
1470
1471IWMMXT_OP_ENV1(unpacklub)
1472IWMMXT_OP_ENV1(unpackluw)
1473IWMMXT_OP_ENV1(unpacklul)
1474IWMMXT_OP_ENV1(unpackhub)
1475IWMMXT_OP_ENV1(unpackhuw)
1476IWMMXT_OP_ENV1(unpackhul)
1477IWMMXT_OP_ENV1(unpacklsb)
1478IWMMXT_OP_ENV1(unpacklsw)
1479IWMMXT_OP_ENV1(unpacklsl)
1480IWMMXT_OP_ENV1(unpackhsb)
1481IWMMXT_OP_ENV1(unpackhsw)
1482IWMMXT_OP_ENV1(unpackhsl)
1483
1484IWMMXT_OP_ENV_SIZE(cmpeq)
1485IWMMXT_OP_ENV_SIZE(cmpgtu)
1486IWMMXT_OP_ENV_SIZE(cmpgts)
1487
1488IWMMXT_OP_ENV_SIZE(mins)
1489IWMMXT_OP_ENV_SIZE(minu)
1490IWMMXT_OP_ENV_SIZE(maxs)
1491IWMMXT_OP_ENV_SIZE(maxu)
1492
1493IWMMXT_OP_ENV_SIZE(subn)
1494IWMMXT_OP_ENV_SIZE(addn)
1495IWMMXT_OP_ENV_SIZE(subu)
1496IWMMXT_OP_ENV_SIZE(addu)
1497IWMMXT_OP_ENV_SIZE(subs)
1498IWMMXT_OP_ENV_SIZE(adds)
1499
1500IWMMXT_OP_ENV(avgb0)
1501IWMMXT_OP_ENV(avgb1)
1502IWMMXT_OP_ENV(avgw0)
1503IWMMXT_OP_ENV(avgw1)
e677137d 1504
477955bd
PM
1505IWMMXT_OP_ENV(packuw)
1506IWMMXT_OP_ENV(packul)
1507IWMMXT_OP_ENV(packuq)
1508IWMMXT_OP_ENV(packsw)
1509IWMMXT_OP_ENV(packsl)
1510IWMMXT_OP_ENV(packsq)
e677137d 1511
e677137d
PB
1512static void gen_op_iwmmxt_set_mup(void)
1513{
39d5492a 1514 TCGv_i32 tmp;
e677137d
PB
1515 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1516 tcg_gen_ori_i32(tmp, tmp, 2);
1517 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1518}
1519
1520static void gen_op_iwmmxt_set_cup(void)
1521{
39d5492a 1522 TCGv_i32 tmp;
e677137d
PB
1523 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1524 tcg_gen_ori_i32(tmp, tmp, 1);
1525 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1526}
1527
1528static void gen_op_iwmmxt_setpsr_nz(void)
1529{
39d5492a 1530 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1531 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1532 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1533}
1534
1535static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1536{
1537 iwmmxt_load_reg(cpu_V1, rn);
86831435 1538 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1539 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1540}
1541
39d5492a
PM
1542static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1543 TCGv_i32 dest)
18c9b560
AZ
1544{
1545 int rd;
1546 uint32_t offset;
39d5492a 1547 TCGv_i32 tmp;
18c9b560
AZ
1548
1549 rd = (insn >> 16) & 0xf;
da6b5335 1550 tmp = load_reg(s, rd);
18c9b560
AZ
1551
1552 offset = (insn & 0xff) << ((insn >> 7) & 2);
1553 if (insn & (1 << 24)) {
1554 /* Pre indexed */
1555 if (insn & (1 << 23))
da6b5335 1556 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1557 else
da6b5335
FN
1558 tcg_gen_addi_i32(tmp, tmp, -offset);
1559 tcg_gen_mov_i32(dest, tmp);
18c9b560 1560 if (insn & (1 << 21))
da6b5335
FN
1561 store_reg(s, rd, tmp);
1562 else
7d1b0095 1563 tcg_temp_free_i32(tmp);
18c9b560
AZ
1564 } else if (insn & (1 << 21)) {
1565 /* Post indexed */
da6b5335 1566 tcg_gen_mov_i32(dest, tmp);
18c9b560 1567 if (insn & (1 << 23))
da6b5335 1568 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1569 else
da6b5335
FN
1570 tcg_gen_addi_i32(tmp, tmp, -offset);
1571 store_reg(s, rd, tmp);
18c9b560
AZ
1572 } else if (!(insn & (1 << 23)))
1573 return 1;
1574 return 0;
1575}
1576
39d5492a 1577static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1578{
1579 int rd = (insn >> 0) & 0xf;
39d5492a 1580 TCGv_i32 tmp;
18c9b560 1581
da6b5335
FN
1582 if (insn & (1 << 8)) {
1583 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1584 return 1;
da6b5335
FN
1585 } else {
1586 tmp = iwmmxt_load_creg(rd);
1587 }
1588 } else {
7d1b0095 1589 tmp = tcg_temp_new_i32();
da6b5335 1590 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1591 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1592 }
1593 tcg_gen_andi_i32(tmp, tmp, mask);
1594 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1595 tcg_temp_free_i32(tmp);
18c9b560
AZ
1596 return 0;
1597}
1598
a1c7273b 1599/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1600 (ie. an undefined instruction). */
7dcc1f89 1601static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1602{
1603 int rd, wrd;
1604 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1605 TCGv_i32 addr;
1606 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1607
1608 if ((insn & 0x0e000e00) == 0x0c000000) {
1609 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1610 wrd = insn & 0xf;
1611 rdlo = (insn >> 12) & 0xf;
1612 rdhi = (insn >> 16) & 0xf;
1613 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1614 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1615 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
da6b5335 1616 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 1617 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
18c9b560 1618 } else { /* TMCRR */
da6b5335
FN
1619 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1620 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1621 gen_op_iwmmxt_set_mup();
1622 }
1623 return 0;
1624 }
1625
1626 wrd = (insn >> 12) & 0xf;
7d1b0095 1627 addr = tcg_temp_new_i32();
da6b5335 1628 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1629 tcg_temp_free_i32(addr);
18c9b560 1630 return 1;
da6b5335 1631 }
18c9b560
AZ
1632 if (insn & ARM_CP_RW_BIT) {
1633 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1634 tmp = tcg_temp_new_i32();
6ce2faf4 1635 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
da6b5335 1636 iwmmxt_store_creg(wrd, tmp);
18c9b560 1637 } else {
e677137d
PB
1638 i = 1;
1639 if (insn & (1 << 8)) {
1640 if (insn & (1 << 22)) { /* WLDRD */
6ce2faf4 1641 gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
e677137d
PB
1642 i = 0;
1643 } else { /* WLDRW wRd */
29531141 1644 tmp = tcg_temp_new_i32();
6ce2faf4 1645 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
e677137d
PB
1646 }
1647 } else {
29531141 1648 tmp = tcg_temp_new_i32();
e677137d 1649 if (insn & (1 << 22)) { /* WLDRH */
6ce2faf4 1650 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
e677137d 1651 } else { /* WLDRB */
6ce2faf4 1652 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
e677137d
PB
1653 }
1654 }
1655 if (i) {
1656 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1657 tcg_temp_free_i32(tmp);
e677137d 1658 }
18c9b560
AZ
1659 gen_op_iwmmxt_movq_wRn_M0(wrd);
1660 }
1661 } else {
1662 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1663 tmp = iwmmxt_load_creg(wrd);
6ce2faf4 1664 gen_aa32_st32(tmp, addr, get_mem_index(s));
18c9b560
AZ
1665 } else {
1666 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1667 tmp = tcg_temp_new_i32();
e677137d
PB
1668 if (insn & (1 << 8)) {
1669 if (insn & (1 << 22)) { /* WSTRD */
6ce2faf4 1670 gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
e677137d 1671 } else { /* WSTRW wRd */
ecc7b3aa 1672 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
6ce2faf4 1673 gen_aa32_st32(tmp, addr, get_mem_index(s));
e677137d
PB
1674 }
1675 } else {
1676 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1677 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
6ce2faf4 1678 gen_aa32_st16(tmp, addr, get_mem_index(s));
e677137d 1679 } else { /* WSTRB */
ecc7b3aa 1680 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
6ce2faf4 1681 gen_aa32_st8(tmp, addr, get_mem_index(s));
e677137d
PB
1682 }
1683 }
18c9b560 1684 }
29531141 1685 tcg_temp_free_i32(tmp);
18c9b560 1686 }
7d1b0095 1687 tcg_temp_free_i32(addr);
18c9b560
AZ
1688 return 0;
1689 }
1690
1691 if ((insn & 0x0f000000) != 0x0e000000)
1692 return 1;
1693
1694 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1695 case 0x000: /* WOR */
1696 wrd = (insn >> 12) & 0xf;
1697 rd0 = (insn >> 0) & 0xf;
1698 rd1 = (insn >> 16) & 0xf;
1699 gen_op_iwmmxt_movq_M0_wRn(rd0);
1700 gen_op_iwmmxt_orq_M0_wRn(rd1);
1701 gen_op_iwmmxt_setpsr_nz();
1702 gen_op_iwmmxt_movq_wRn_M0(wrd);
1703 gen_op_iwmmxt_set_mup();
1704 gen_op_iwmmxt_set_cup();
1705 break;
1706 case 0x011: /* TMCR */
1707 if (insn & 0xf)
1708 return 1;
1709 rd = (insn >> 12) & 0xf;
1710 wrd = (insn >> 16) & 0xf;
1711 switch (wrd) {
1712 case ARM_IWMMXT_wCID:
1713 case ARM_IWMMXT_wCASF:
1714 break;
1715 case ARM_IWMMXT_wCon:
1716 gen_op_iwmmxt_set_cup();
1717 /* Fall through. */
1718 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1719 tmp = iwmmxt_load_creg(wrd);
1720 tmp2 = load_reg(s, rd);
f669df27 1721 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1722 tcg_temp_free_i32(tmp2);
da6b5335 1723 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1724 break;
1725 case ARM_IWMMXT_wCGR0:
1726 case ARM_IWMMXT_wCGR1:
1727 case ARM_IWMMXT_wCGR2:
1728 case ARM_IWMMXT_wCGR3:
1729 gen_op_iwmmxt_set_cup();
da6b5335
FN
1730 tmp = load_reg(s, rd);
1731 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1732 break;
1733 default:
1734 return 1;
1735 }
1736 break;
1737 case 0x100: /* WXOR */
1738 wrd = (insn >> 12) & 0xf;
1739 rd0 = (insn >> 0) & 0xf;
1740 rd1 = (insn >> 16) & 0xf;
1741 gen_op_iwmmxt_movq_M0_wRn(rd0);
1742 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1743 gen_op_iwmmxt_setpsr_nz();
1744 gen_op_iwmmxt_movq_wRn_M0(wrd);
1745 gen_op_iwmmxt_set_mup();
1746 gen_op_iwmmxt_set_cup();
1747 break;
1748 case 0x111: /* TMRC */
1749 if (insn & 0xf)
1750 return 1;
1751 rd = (insn >> 12) & 0xf;
1752 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1753 tmp = iwmmxt_load_creg(wrd);
1754 store_reg(s, rd, tmp);
18c9b560
AZ
1755 break;
1756 case 0x300: /* WANDN */
1757 wrd = (insn >> 12) & 0xf;
1758 rd0 = (insn >> 0) & 0xf;
1759 rd1 = (insn >> 16) & 0xf;
1760 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1761 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1762 gen_op_iwmmxt_andq_M0_wRn(rd1);
1763 gen_op_iwmmxt_setpsr_nz();
1764 gen_op_iwmmxt_movq_wRn_M0(wrd);
1765 gen_op_iwmmxt_set_mup();
1766 gen_op_iwmmxt_set_cup();
1767 break;
1768 case 0x200: /* WAND */
1769 wrd = (insn >> 12) & 0xf;
1770 rd0 = (insn >> 0) & 0xf;
1771 rd1 = (insn >> 16) & 0xf;
1772 gen_op_iwmmxt_movq_M0_wRn(rd0);
1773 gen_op_iwmmxt_andq_M0_wRn(rd1);
1774 gen_op_iwmmxt_setpsr_nz();
1775 gen_op_iwmmxt_movq_wRn_M0(wrd);
1776 gen_op_iwmmxt_set_mup();
1777 gen_op_iwmmxt_set_cup();
1778 break;
1779 case 0x810: case 0xa10: /* WMADD */
1780 wrd = (insn >> 12) & 0xf;
1781 rd0 = (insn >> 0) & 0xf;
1782 rd1 = (insn >> 16) & 0xf;
1783 gen_op_iwmmxt_movq_M0_wRn(rd0);
1784 if (insn & (1 << 21))
1785 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1786 else
1787 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1788 gen_op_iwmmxt_movq_wRn_M0(wrd);
1789 gen_op_iwmmxt_set_mup();
1790 break;
1791 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1792 wrd = (insn >> 12) & 0xf;
1793 rd0 = (insn >> 16) & 0xf;
1794 rd1 = (insn >> 0) & 0xf;
1795 gen_op_iwmmxt_movq_M0_wRn(rd0);
1796 switch ((insn >> 22) & 3) {
1797 case 0:
1798 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1799 break;
1800 case 1:
1801 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1802 break;
1803 case 2:
1804 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1805 break;
1806 case 3:
1807 return 1;
1808 }
1809 gen_op_iwmmxt_movq_wRn_M0(wrd);
1810 gen_op_iwmmxt_set_mup();
1811 gen_op_iwmmxt_set_cup();
1812 break;
1813 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1814 wrd = (insn >> 12) & 0xf;
1815 rd0 = (insn >> 16) & 0xf;
1816 rd1 = (insn >> 0) & 0xf;
1817 gen_op_iwmmxt_movq_M0_wRn(rd0);
1818 switch ((insn >> 22) & 3) {
1819 case 0:
1820 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1821 break;
1822 case 1:
1823 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1824 break;
1825 case 2:
1826 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1827 break;
1828 case 3:
1829 return 1;
1830 }
1831 gen_op_iwmmxt_movq_wRn_M0(wrd);
1832 gen_op_iwmmxt_set_mup();
1833 gen_op_iwmmxt_set_cup();
1834 break;
1835 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1836 wrd = (insn >> 12) & 0xf;
1837 rd0 = (insn >> 16) & 0xf;
1838 rd1 = (insn >> 0) & 0xf;
1839 gen_op_iwmmxt_movq_M0_wRn(rd0);
1840 if (insn & (1 << 22))
1841 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1842 else
1843 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1844 if (!(insn & (1 << 20)))
1845 gen_op_iwmmxt_addl_M0_wRn(wrd);
1846 gen_op_iwmmxt_movq_wRn_M0(wrd);
1847 gen_op_iwmmxt_set_mup();
1848 break;
1849 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1850 wrd = (insn >> 12) & 0xf;
1851 rd0 = (insn >> 16) & 0xf;
1852 rd1 = (insn >> 0) & 0xf;
1853 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1854 if (insn & (1 << 21)) {
1855 if (insn & (1 << 20))
1856 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1857 else
1858 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1859 } else {
1860 if (insn & (1 << 20))
1861 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1862 else
1863 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1864 }
18c9b560
AZ
1865 gen_op_iwmmxt_movq_wRn_M0(wrd);
1866 gen_op_iwmmxt_set_mup();
1867 break;
1868 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1869 wrd = (insn >> 12) & 0xf;
1870 rd0 = (insn >> 16) & 0xf;
1871 rd1 = (insn >> 0) & 0xf;
1872 gen_op_iwmmxt_movq_M0_wRn(rd0);
1873 if (insn & (1 << 21))
1874 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1875 else
1876 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1877 if (!(insn & (1 << 20))) {
e677137d
PB
1878 iwmmxt_load_reg(cpu_V1, wrd);
1879 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
1880 }
1881 gen_op_iwmmxt_movq_wRn_M0(wrd);
1882 gen_op_iwmmxt_set_mup();
1883 break;
1884 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1885 wrd = (insn >> 12) & 0xf;
1886 rd0 = (insn >> 16) & 0xf;
1887 rd1 = (insn >> 0) & 0xf;
1888 gen_op_iwmmxt_movq_M0_wRn(rd0);
1889 switch ((insn >> 22) & 3) {
1890 case 0:
1891 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1892 break;
1893 case 1:
1894 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1895 break;
1896 case 2:
1897 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1898 break;
1899 case 3:
1900 return 1;
1901 }
1902 gen_op_iwmmxt_movq_wRn_M0(wrd);
1903 gen_op_iwmmxt_set_mup();
1904 gen_op_iwmmxt_set_cup();
1905 break;
1906 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1907 wrd = (insn >> 12) & 0xf;
1908 rd0 = (insn >> 16) & 0xf;
1909 rd1 = (insn >> 0) & 0xf;
1910 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1911 if (insn & (1 << 22)) {
1912 if (insn & (1 << 20))
1913 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1914 else
1915 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1916 } else {
1917 if (insn & (1 << 20))
1918 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1919 else
1920 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1921 }
18c9b560
AZ
1922 gen_op_iwmmxt_movq_wRn_M0(wrd);
1923 gen_op_iwmmxt_set_mup();
1924 gen_op_iwmmxt_set_cup();
1925 break;
1926 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1927 wrd = (insn >> 12) & 0xf;
1928 rd0 = (insn >> 16) & 0xf;
1929 rd1 = (insn >> 0) & 0xf;
1930 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
1931 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1932 tcg_gen_andi_i32(tmp, tmp, 7);
1933 iwmmxt_load_reg(cpu_V1, rd1);
1934 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 1935 tcg_temp_free_i32(tmp);
18c9b560
AZ
1936 gen_op_iwmmxt_movq_wRn_M0(wrd);
1937 gen_op_iwmmxt_set_mup();
1938 break;
1939 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
1940 if (((insn >> 6) & 3) == 3)
1941 return 1;
18c9b560
AZ
1942 rd = (insn >> 12) & 0xf;
1943 wrd = (insn >> 16) & 0xf;
da6b5335 1944 tmp = load_reg(s, rd);
18c9b560
AZ
1945 gen_op_iwmmxt_movq_M0_wRn(wrd);
1946 switch ((insn >> 6) & 3) {
1947 case 0:
da6b5335
FN
1948 tmp2 = tcg_const_i32(0xff);
1949 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
1950 break;
1951 case 1:
da6b5335
FN
1952 tmp2 = tcg_const_i32(0xffff);
1953 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
1954 break;
1955 case 2:
da6b5335
FN
1956 tmp2 = tcg_const_i32(0xffffffff);
1957 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 1958 break;
da6b5335 1959 default:
39d5492a
PM
1960 TCGV_UNUSED_I32(tmp2);
1961 TCGV_UNUSED_I32(tmp3);
18c9b560 1962 }
da6b5335 1963 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
1964 tcg_temp_free_i32(tmp3);
1965 tcg_temp_free_i32(tmp2);
7d1b0095 1966 tcg_temp_free_i32(tmp);
18c9b560
AZ
1967 gen_op_iwmmxt_movq_wRn_M0(wrd);
1968 gen_op_iwmmxt_set_mup();
1969 break;
1970 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1971 rd = (insn >> 12) & 0xf;
1972 wrd = (insn >> 16) & 0xf;
da6b5335 1973 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
1974 return 1;
1975 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1976 tmp = tcg_temp_new_i32();
18c9b560
AZ
1977 switch ((insn >> 22) & 3) {
1978 case 0:
da6b5335 1979 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 1980 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
1981 if (insn & 8) {
1982 tcg_gen_ext8s_i32(tmp, tmp);
1983 } else {
1984 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
1985 }
1986 break;
1987 case 1:
da6b5335 1988 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 1989 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
1990 if (insn & 8) {
1991 tcg_gen_ext16s_i32(tmp, tmp);
1992 } else {
1993 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
1994 }
1995 break;
1996 case 2:
da6b5335 1997 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 1998 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 1999 break;
18c9b560 2000 }
da6b5335 2001 store_reg(s, rd, tmp);
18c9b560
AZ
2002 break;
2003 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2004 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2005 return 1;
da6b5335 2006 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2007 switch ((insn >> 22) & 3) {
2008 case 0:
da6b5335 2009 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2010 break;
2011 case 1:
da6b5335 2012 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2013 break;
2014 case 2:
da6b5335 2015 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2016 break;
18c9b560 2017 }
da6b5335
FN
2018 tcg_gen_shli_i32(tmp, tmp, 28);
2019 gen_set_nzcv(tmp);
7d1b0095 2020 tcg_temp_free_i32(tmp);
18c9b560
AZ
2021 break;
2022 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2023 if (((insn >> 6) & 3) == 3)
2024 return 1;
18c9b560
AZ
2025 rd = (insn >> 12) & 0xf;
2026 wrd = (insn >> 16) & 0xf;
da6b5335 2027 tmp = load_reg(s, rd);
18c9b560
AZ
2028 switch ((insn >> 6) & 3) {
2029 case 0:
da6b5335 2030 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2031 break;
2032 case 1:
da6b5335 2033 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2034 break;
2035 case 2:
da6b5335 2036 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2037 break;
18c9b560 2038 }
7d1b0095 2039 tcg_temp_free_i32(tmp);
18c9b560
AZ
2040 gen_op_iwmmxt_movq_wRn_M0(wrd);
2041 gen_op_iwmmxt_set_mup();
2042 break;
2043 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2044 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2045 return 1;
da6b5335 2046 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2047 tmp2 = tcg_temp_new_i32();
da6b5335 2048 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2049 switch ((insn >> 22) & 3) {
2050 case 0:
2051 for (i = 0; i < 7; i ++) {
da6b5335
FN
2052 tcg_gen_shli_i32(tmp2, tmp2, 4);
2053 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2054 }
2055 break;
2056 case 1:
2057 for (i = 0; i < 3; i ++) {
da6b5335
FN
2058 tcg_gen_shli_i32(tmp2, tmp2, 8);
2059 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2060 }
2061 break;
2062 case 2:
da6b5335
FN
2063 tcg_gen_shli_i32(tmp2, tmp2, 16);
2064 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2065 break;
18c9b560 2066 }
da6b5335 2067 gen_set_nzcv(tmp);
7d1b0095
PM
2068 tcg_temp_free_i32(tmp2);
2069 tcg_temp_free_i32(tmp);
18c9b560
AZ
2070 break;
2071 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2072 wrd = (insn >> 12) & 0xf;
2073 rd0 = (insn >> 16) & 0xf;
2074 gen_op_iwmmxt_movq_M0_wRn(rd0);
2075 switch ((insn >> 22) & 3) {
2076 case 0:
e677137d 2077 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2078 break;
2079 case 1:
e677137d 2080 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2081 break;
2082 case 2:
e677137d 2083 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2084 break;
2085 case 3:
2086 return 1;
2087 }
2088 gen_op_iwmmxt_movq_wRn_M0(wrd);
2089 gen_op_iwmmxt_set_mup();
2090 break;
2091 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2092 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2093 return 1;
da6b5335 2094 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2095 tmp2 = tcg_temp_new_i32();
da6b5335 2096 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2097 switch ((insn >> 22) & 3) {
2098 case 0:
2099 for (i = 0; i < 7; i ++) {
da6b5335
FN
2100 tcg_gen_shli_i32(tmp2, tmp2, 4);
2101 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2102 }
2103 break;
2104 case 1:
2105 for (i = 0; i < 3; i ++) {
da6b5335
FN
2106 tcg_gen_shli_i32(tmp2, tmp2, 8);
2107 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2108 }
2109 break;
2110 case 2:
da6b5335
FN
2111 tcg_gen_shli_i32(tmp2, tmp2, 16);
2112 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2113 break;
18c9b560 2114 }
da6b5335 2115 gen_set_nzcv(tmp);
7d1b0095
PM
2116 tcg_temp_free_i32(tmp2);
2117 tcg_temp_free_i32(tmp);
18c9b560
AZ
2118 break;
2119 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2120 rd = (insn >> 12) & 0xf;
2121 rd0 = (insn >> 16) & 0xf;
da6b5335 2122 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2123 return 1;
2124 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2125 tmp = tcg_temp_new_i32();
18c9b560
AZ
2126 switch ((insn >> 22) & 3) {
2127 case 0:
da6b5335 2128 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2129 break;
2130 case 1:
da6b5335 2131 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2132 break;
2133 case 2:
da6b5335 2134 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2135 break;
18c9b560 2136 }
da6b5335 2137 store_reg(s, rd, tmp);
18c9b560
AZ
2138 break;
2139 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2140 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2141 wrd = (insn >> 12) & 0xf;
2142 rd0 = (insn >> 16) & 0xf;
2143 rd1 = (insn >> 0) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0);
2145 switch ((insn >> 22) & 3) {
2146 case 0:
2147 if (insn & (1 << 21))
2148 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2149 else
2150 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2151 break;
2152 case 1:
2153 if (insn & (1 << 21))
2154 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2155 else
2156 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2157 break;
2158 case 2:
2159 if (insn & (1 << 21))
2160 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2161 else
2162 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2163 break;
2164 case 3:
2165 return 1;
2166 }
2167 gen_op_iwmmxt_movq_wRn_M0(wrd);
2168 gen_op_iwmmxt_set_mup();
2169 gen_op_iwmmxt_set_cup();
2170 break;
2171 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2172 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2173 wrd = (insn >> 12) & 0xf;
2174 rd0 = (insn >> 16) & 0xf;
2175 gen_op_iwmmxt_movq_M0_wRn(rd0);
2176 switch ((insn >> 22) & 3) {
2177 case 0:
2178 if (insn & (1 << 21))
2179 gen_op_iwmmxt_unpacklsb_M0();
2180 else
2181 gen_op_iwmmxt_unpacklub_M0();
2182 break;
2183 case 1:
2184 if (insn & (1 << 21))
2185 gen_op_iwmmxt_unpacklsw_M0();
2186 else
2187 gen_op_iwmmxt_unpackluw_M0();
2188 break;
2189 case 2:
2190 if (insn & (1 << 21))
2191 gen_op_iwmmxt_unpacklsl_M0();
2192 else
2193 gen_op_iwmmxt_unpacklul_M0();
2194 break;
2195 case 3:
2196 return 1;
2197 }
2198 gen_op_iwmmxt_movq_wRn_M0(wrd);
2199 gen_op_iwmmxt_set_mup();
2200 gen_op_iwmmxt_set_cup();
2201 break;
2202 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2203 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2204 wrd = (insn >> 12) & 0xf;
2205 rd0 = (insn >> 16) & 0xf;
2206 gen_op_iwmmxt_movq_M0_wRn(rd0);
2207 switch ((insn >> 22) & 3) {
2208 case 0:
2209 if (insn & (1 << 21))
2210 gen_op_iwmmxt_unpackhsb_M0();
2211 else
2212 gen_op_iwmmxt_unpackhub_M0();
2213 break;
2214 case 1:
2215 if (insn & (1 << 21))
2216 gen_op_iwmmxt_unpackhsw_M0();
2217 else
2218 gen_op_iwmmxt_unpackhuw_M0();
2219 break;
2220 case 2:
2221 if (insn & (1 << 21))
2222 gen_op_iwmmxt_unpackhsl_M0();
2223 else
2224 gen_op_iwmmxt_unpackhul_M0();
2225 break;
2226 case 3:
2227 return 1;
2228 }
2229 gen_op_iwmmxt_movq_wRn_M0(wrd);
2230 gen_op_iwmmxt_set_mup();
2231 gen_op_iwmmxt_set_cup();
2232 break;
2233 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2234 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2235 if (((insn >> 22) & 3) == 0)
2236 return 1;
18c9b560
AZ
2237 wrd = (insn >> 12) & 0xf;
2238 rd0 = (insn >> 16) & 0xf;
2239 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2240 tmp = tcg_temp_new_i32();
da6b5335 2241 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2242 tcg_temp_free_i32(tmp);
18c9b560 2243 return 1;
da6b5335 2244 }
18c9b560 2245 switch ((insn >> 22) & 3) {
18c9b560 2246 case 1:
477955bd 2247 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2248 break;
2249 case 2:
477955bd 2250 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2251 break;
2252 case 3:
477955bd 2253 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2254 break;
2255 }
7d1b0095 2256 tcg_temp_free_i32(tmp);
18c9b560
AZ
2257 gen_op_iwmmxt_movq_wRn_M0(wrd);
2258 gen_op_iwmmxt_set_mup();
2259 gen_op_iwmmxt_set_cup();
2260 break;
2261 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2262 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2263 if (((insn >> 22) & 3) == 0)
2264 return 1;
18c9b560
AZ
2265 wrd = (insn >> 12) & 0xf;
2266 rd0 = (insn >> 16) & 0xf;
2267 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2268 tmp = tcg_temp_new_i32();
da6b5335 2269 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2270 tcg_temp_free_i32(tmp);
18c9b560 2271 return 1;
da6b5335 2272 }
18c9b560 2273 switch ((insn >> 22) & 3) {
18c9b560 2274 case 1:
477955bd 2275 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2276 break;
2277 case 2:
477955bd 2278 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2279 break;
2280 case 3:
477955bd 2281 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2282 break;
2283 }
7d1b0095 2284 tcg_temp_free_i32(tmp);
18c9b560
AZ
2285 gen_op_iwmmxt_movq_wRn_M0(wrd);
2286 gen_op_iwmmxt_set_mup();
2287 gen_op_iwmmxt_set_cup();
2288 break;
2289 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2290 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2291 if (((insn >> 22) & 3) == 0)
2292 return 1;
18c9b560
AZ
2293 wrd = (insn >> 12) & 0xf;
2294 rd0 = (insn >> 16) & 0xf;
2295 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2296 tmp = tcg_temp_new_i32();
da6b5335 2297 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2298 tcg_temp_free_i32(tmp);
18c9b560 2299 return 1;
da6b5335 2300 }
18c9b560 2301 switch ((insn >> 22) & 3) {
18c9b560 2302 case 1:
477955bd 2303 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2304 break;
2305 case 2:
477955bd 2306 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2307 break;
2308 case 3:
477955bd 2309 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2310 break;
2311 }
7d1b0095 2312 tcg_temp_free_i32(tmp);
18c9b560
AZ
2313 gen_op_iwmmxt_movq_wRn_M0(wrd);
2314 gen_op_iwmmxt_set_mup();
2315 gen_op_iwmmxt_set_cup();
2316 break;
2317 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2318 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2319 if (((insn >> 22) & 3) == 0)
2320 return 1;
18c9b560
AZ
2321 wrd = (insn >> 12) & 0xf;
2322 rd0 = (insn >> 16) & 0xf;
2323 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2324 tmp = tcg_temp_new_i32();
18c9b560 2325 switch ((insn >> 22) & 3) {
18c9b560 2326 case 1:
da6b5335 2327 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2328 tcg_temp_free_i32(tmp);
18c9b560 2329 return 1;
da6b5335 2330 }
477955bd 2331 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2332 break;
2333 case 2:
da6b5335 2334 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2335 tcg_temp_free_i32(tmp);
18c9b560 2336 return 1;
da6b5335 2337 }
477955bd 2338 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2339 break;
2340 case 3:
da6b5335 2341 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2342 tcg_temp_free_i32(tmp);
18c9b560 2343 return 1;
da6b5335 2344 }
477955bd 2345 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2346 break;
2347 }
7d1b0095 2348 tcg_temp_free_i32(tmp);
18c9b560
AZ
2349 gen_op_iwmmxt_movq_wRn_M0(wrd);
2350 gen_op_iwmmxt_set_mup();
2351 gen_op_iwmmxt_set_cup();
2352 break;
2353 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2354 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2355 wrd = (insn >> 12) & 0xf;
2356 rd0 = (insn >> 16) & 0xf;
2357 rd1 = (insn >> 0) & 0xf;
2358 gen_op_iwmmxt_movq_M0_wRn(rd0);
2359 switch ((insn >> 22) & 3) {
2360 case 0:
2361 if (insn & (1 << 21))
2362 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2363 else
2364 gen_op_iwmmxt_minub_M0_wRn(rd1);
2365 break;
2366 case 1:
2367 if (insn & (1 << 21))
2368 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2369 else
2370 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2371 break;
2372 case 2:
2373 if (insn & (1 << 21))
2374 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2375 else
2376 gen_op_iwmmxt_minul_M0_wRn(rd1);
2377 break;
2378 case 3:
2379 return 1;
2380 }
2381 gen_op_iwmmxt_movq_wRn_M0(wrd);
2382 gen_op_iwmmxt_set_mup();
2383 break;
2384 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2385 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2386 wrd = (insn >> 12) & 0xf;
2387 rd0 = (insn >> 16) & 0xf;
2388 rd1 = (insn >> 0) & 0xf;
2389 gen_op_iwmmxt_movq_M0_wRn(rd0);
2390 switch ((insn >> 22) & 3) {
2391 case 0:
2392 if (insn & (1 << 21))
2393 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2394 else
2395 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2396 break;
2397 case 1:
2398 if (insn & (1 << 21))
2399 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2400 else
2401 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2402 break;
2403 case 2:
2404 if (insn & (1 << 21))
2405 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2406 else
2407 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2408 break;
2409 case 3:
2410 return 1;
2411 }
2412 gen_op_iwmmxt_movq_wRn_M0(wrd);
2413 gen_op_iwmmxt_set_mup();
2414 break;
2415 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2416 case 0x402: case 0x502: case 0x602: case 0x702:
2417 wrd = (insn >> 12) & 0xf;
2418 rd0 = (insn >> 16) & 0xf;
2419 rd1 = (insn >> 0) & 0xf;
2420 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2421 tmp = tcg_const_i32((insn >> 20) & 3);
2422 iwmmxt_load_reg(cpu_V1, rd1);
2423 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2424 tcg_temp_free_i32(tmp);
18c9b560
AZ
2425 gen_op_iwmmxt_movq_wRn_M0(wrd);
2426 gen_op_iwmmxt_set_mup();
2427 break;
2428 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2429 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2430 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2431 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2432 wrd = (insn >> 12) & 0xf;
2433 rd0 = (insn >> 16) & 0xf;
2434 rd1 = (insn >> 0) & 0xf;
2435 gen_op_iwmmxt_movq_M0_wRn(rd0);
2436 switch ((insn >> 20) & 0xf) {
2437 case 0x0:
2438 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2439 break;
2440 case 0x1:
2441 gen_op_iwmmxt_subub_M0_wRn(rd1);
2442 break;
2443 case 0x3:
2444 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2445 break;
2446 case 0x4:
2447 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2448 break;
2449 case 0x5:
2450 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2451 break;
2452 case 0x7:
2453 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2454 break;
2455 case 0x8:
2456 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2457 break;
2458 case 0x9:
2459 gen_op_iwmmxt_subul_M0_wRn(rd1);
2460 break;
2461 case 0xb:
2462 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2463 break;
2464 default:
2465 return 1;
2466 }
2467 gen_op_iwmmxt_movq_wRn_M0(wrd);
2468 gen_op_iwmmxt_set_mup();
2469 gen_op_iwmmxt_set_cup();
2470 break;
2471 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2472 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2473 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2474 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2475 wrd = (insn >> 12) & 0xf;
2476 rd0 = (insn >> 16) & 0xf;
2477 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2478 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2479 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2480 tcg_temp_free_i32(tmp);
18c9b560
AZ
2481 gen_op_iwmmxt_movq_wRn_M0(wrd);
2482 gen_op_iwmmxt_set_mup();
2483 gen_op_iwmmxt_set_cup();
2484 break;
2485 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2486 case 0x418: case 0x518: case 0x618: case 0x718:
2487 case 0x818: case 0x918: case 0xa18: case 0xb18:
2488 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2489 wrd = (insn >> 12) & 0xf;
2490 rd0 = (insn >> 16) & 0xf;
2491 rd1 = (insn >> 0) & 0xf;
2492 gen_op_iwmmxt_movq_M0_wRn(rd0);
2493 switch ((insn >> 20) & 0xf) {
2494 case 0x0:
2495 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2496 break;
2497 case 0x1:
2498 gen_op_iwmmxt_addub_M0_wRn(rd1);
2499 break;
2500 case 0x3:
2501 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2502 break;
2503 case 0x4:
2504 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2505 break;
2506 case 0x5:
2507 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2508 break;
2509 case 0x7:
2510 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2511 break;
2512 case 0x8:
2513 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2514 break;
2515 case 0x9:
2516 gen_op_iwmmxt_addul_M0_wRn(rd1);
2517 break;
2518 case 0xb:
2519 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2520 break;
2521 default:
2522 return 1;
2523 }
2524 gen_op_iwmmxt_movq_wRn_M0(wrd);
2525 gen_op_iwmmxt_set_mup();
2526 gen_op_iwmmxt_set_cup();
2527 break;
2528 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2529 case 0x408: case 0x508: case 0x608: case 0x708:
2530 case 0x808: case 0x908: case 0xa08: case 0xb08:
2531 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2532 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2533 return 1;
18c9b560
AZ
2534 wrd = (insn >> 12) & 0xf;
2535 rd0 = (insn >> 16) & 0xf;
2536 rd1 = (insn >> 0) & 0xf;
2537 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2538 switch ((insn >> 22) & 3) {
18c9b560
AZ
2539 case 1:
2540 if (insn & (1 << 21))
2541 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2542 else
2543 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2544 break;
2545 case 2:
2546 if (insn & (1 << 21))
2547 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2548 else
2549 gen_op_iwmmxt_packul_M0_wRn(rd1);
2550 break;
2551 case 3:
2552 if (insn & (1 << 21))
2553 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2554 else
2555 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2556 break;
2557 }
2558 gen_op_iwmmxt_movq_wRn_M0(wrd);
2559 gen_op_iwmmxt_set_mup();
2560 gen_op_iwmmxt_set_cup();
2561 break;
2562 case 0x201: case 0x203: case 0x205: case 0x207:
2563 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2564 case 0x211: case 0x213: case 0x215: case 0x217:
2565 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2566 wrd = (insn >> 5) & 0xf;
2567 rd0 = (insn >> 12) & 0xf;
2568 rd1 = (insn >> 0) & 0xf;
2569 if (rd0 == 0xf || rd1 == 0xf)
2570 return 1;
2571 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2572 tmp = load_reg(s, rd0);
2573 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2574 switch ((insn >> 16) & 0xf) {
2575 case 0x0: /* TMIA */
da6b5335 2576 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2577 break;
2578 case 0x8: /* TMIAPH */
da6b5335 2579 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2580 break;
2581 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2582 if (insn & (1 << 16))
da6b5335 2583 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2584 if (insn & (1 << 17))
da6b5335
FN
2585 tcg_gen_shri_i32(tmp2, tmp2, 16);
2586 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2587 break;
2588 default:
7d1b0095
PM
2589 tcg_temp_free_i32(tmp2);
2590 tcg_temp_free_i32(tmp);
18c9b560
AZ
2591 return 1;
2592 }
7d1b0095
PM
2593 tcg_temp_free_i32(tmp2);
2594 tcg_temp_free_i32(tmp);
18c9b560
AZ
2595 gen_op_iwmmxt_movq_wRn_M0(wrd);
2596 gen_op_iwmmxt_set_mup();
2597 break;
2598 default:
2599 return 1;
2600 }
2601
2602 return 0;
2603}
2604
a1c7273b 2605/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2606 (ie. an undefined instruction). */
7dcc1f89 2607static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2608{
2609 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2610 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2611
2612 if ((insn & 0x0ff00f10) == 0x0e200010) {
2613 /* Multiply with Internal Accumulate Format */
2614 rd0 = (insn >> 12) & 0xf;
2615 rd1 = insn & 0xf;
2616 acc = (insn >> 5) & 7;
2617
2618 if (acc != 0)
2619 return 1;
2620
3a554c0f
FN
2621 tmp = load_reg(s, rd0);
2622 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2623 switch ((insn >> 16) & 0xf) {
2624 case 0x0: /* MIA */
3a554c0f 2625 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2626 break;
2627 case 0x8: /* MIAPH */
3a554c0f 2628 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2629 break;
2630 case 0xc: /* MIABB */
2631 case 0xd: /* MIABT */
2632 case 0xe: /* MIATB */
2633 case 0xf: /* MIATT */
18c9b560 2634 if (insn & (1 << 16))
3a554c0f 2635 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2636 if (insn & (1 << 17))
3a554c0f
FN
2637 tcg_gen_shri_i32(tmp2, tmp2, 16);
2638 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2639 break;
2640 default:
2641 return 1;
2642 }
7d1b0095
PM
2643 tcg_temp_free_i32(tmp2);
2644 tcg_temp_free_i32(tmp);
18c9b560
AZ
2645
2646 gen_op_iwmmxt_movq_wRn_M0(acc);
2647 return 0;
2648 }
2649
2650 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2651 /* Internal Accumulator Access Format */
2652 rdhi = (insn >> 16) & 0xf;
2653 rdlo = (insn >> 12) & 0xf;
2654 acc = insn & 7;
2655
2656 if (acc != 0)
2657 return 1;
2658
2659 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2660 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2661 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3a554c0f 2662 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 2663 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2664 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
18c9b560 2665 } else { /* MAR */
3a554c0f
FN
2666 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2667 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2668 }
2669 return 0;
2670 }
2671
2672 return 1;
2673}
2674
9ee6e8bb
PB
2675#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2676#define VFP_SREG(insn, bigbit, smallbit) \
2677 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2678#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2679 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2680 reg = (((insn) >> (bigbit)) & 0x0f) \
2681 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2682 } else { \
2683 if (insn & (1 << (smallbit))) \
2684 return 1; \
2685 reg = ((insn) >> (bigbit)) & 0x0f; \
2686 }} while (0)
2687
2688#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2689#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2690#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2691#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2692#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2693#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2694
4373f3ce 2695/* Move between integer and VFP cores. */
39d5492a 2696static TCGv_i32 gen_vfp_mrs(void)
4373f3ce 2697{
39d5492a 2698 TCGv_i32 tmp = tcg_temp_new_i32();
4373f3ce
PB
2699 tcg_gen_mov_i32(tmp, cpu_F0s);
2700 return tmp;
2701}
2702
39d5492a 2703static void gen_vfp_msr(TCGv_i32 tmp)
4373f3ce
PB
2704{
2705 tcg_gen_mov_i32(cpu_F0s, tmp);
7d1b0095 2706 tcg_temp_free_i32(tmp);
4373f3ce
PB
2707}
2708
39d5492a 2709static void gen_neon_dup_u8(TCGv_i32 var, int shift)
ad69471c 2710{
39d5492a 2711 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2712 if (shift)
2713 tcg_gen_shri_i32(var, var, shift);
86831435 2714 tcg_gen_ext8u_i32(var, var);
ad69471c
PB
2715 tcg_gen_shli_i32(tmp, var, 8);
2716 tcg_gen_or_i32(var, var, tmp);
2717 tcg_gen_shli_i32(tmp, var, 16);
2718 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2719 tcg_temp_free_i32(tmp);
ad69471c
PB
2720}
2721
39d5492a 2722static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2723{
39d5492a 2724 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2725 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2726 tcg_gen_shli_i32(tmp, var, 16);
2727 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2728 tcg_temp_free_i32(tmp);
ad69471c
PB
2729}
2730
39d5492a 2731static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2732{
39d5492a 2733 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2734 tcg_gen_andi_i32(var, var, 0xffff0000);
2735 tcg_gen_shri_i32(tmp, var, 16);
2736 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2737 tcg_temp_free_i32(tmp);
ad69471c
PB
2738}
2739
39d5492a 2740static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
8e18cde3
PM
2741{
2742 /* Load a single Neon element and replicate into a 32 bit TCG reg */
58ab8e96 2743 TCGv_i32 tmp = tcg_temp_new_i32();
8e18cde3
PM
2744 switch (size) {
2745 case 0:
6ce2faf4 2746 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
8e18cde3
PM
2747 gen_neon_dup_u8(tmp, 0);
2748 break;
2749 case 1:
6ce2faf4 2750 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8e18cde3
PM
2751 gen_neon_dup_low16(tmp);
2752 break;
2753 case 2:
6ce2faf4 2754 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8e18cde3
PM
2755 break;
2756 default: /* Avoid compiler warnings. */
2757 abort();
2758 }
2759 return tmp;
2760}
2761
04731fb5
WN
2762static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2763 uint32_t dp)
2764{
2765 uint32_t cc = extract32(insn, 20, 2);
2766
2767 if (dp) {
2768 TCGv_i64 frn, frm, dest;
2769 TCGv_i64 tmp, zero, zf, nf, vf;
2770
2771 zero = tcg_const_i64(0);
2772
2773 frn = tcg_temp_new_i64();
2774 frm = tcg_temp_new_i64();
2775 dest = tcg_temp_new_i64();
2776
2777 zf = tcg_temp_new_i64();
2778 nf = tcg_temp_new_i64();
2779 vf = tcg_temp_new_i64();
2780
2781 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2782 tcg_gen_ext_i32_i64(nf, cpu_NF);
2783 tcg_gen_ext_i32_i64(vf, cpu_VF);
2784
2785 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2786 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2787 switch (cc) {
2788 case 0: /* eq: Z */
2789 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2790 frn, frm);
2791 break;
2792 case 1: /* vs: V */
2793 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2794 frn, frm);
2795 break;
2796 case 2: /* ge: N == V -> N ^ V == 0 */
2797 tmp = tcg_temp_new_i64();
2798 tcg_gen_xor_i64(tmp, vf, nf);
2799 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2800 frn, frm);
2801 tcg_temp_free_i64(tmp);
2802 break;
2803 case 3: /* gt: !Z && N == V */
2804 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2805 frn, frm);
2806 tmp = tcg_temp_new_i64();
2807 tcg_gen_xor_i64(tmp, vf, nf);
2808 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2809 dest, frm);
2810 tcg_temp_free_i64(tmp);
2811 break;
2812 }
2813 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2814 tcg_temp_free_i64(frn);
2815 tcg_temp_free_i64(frm);
2816 tcg_temp_free_i64(dest);
2817
2818 tcg_temp_free_i64(zf);
2819 tcg_temp_free_i64(nf);
2820 tcg_temp_free_i64(vf);
2821
2822 tcg_temp_free_i64(zero);
2823 } else {
2824 TCGv_i32 frn, frm, dest;
2825 TCGv_i32 tmp, zero;
2826
2827 zero = tcg_const_i32(0);
2828
2829 frn = tcg_temp_new_i32();
2830 frm = tcg_temp_new_i32();
2831 dest = tcg_temp_new_i32();
2832 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2833 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2834 switch (cc) {
2835 case 0: /* eq: Z */
2836 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2837 frn, frm);
2838 break;
2839 case 1: /* vs: V */
2840 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2841 frn, frm);
2842 break;
2843 case 2: /* ge: N == V -> N ^ V == 0 */
2844 tmp = tcg_temp_new_i32();
2845 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2846 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2847 frn, frm);
2848 tcg_temp_free_i32(tmp);
2849 break;
2850 case 3: /* gt: !Z && N == V */
2851 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2852 frn, frm);
2853 tmp = tcg_temp_new_i32();
2854 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2855 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2856 dest, frm);
2857 tcg_temp_free_i32(tmp);
2858 break;
2859 }
2860 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2861 tcg_temp_free_i32(frn);
2862 tcg_temp_free_i32(frm);
2863 tcg_temp_free_i32(dest);
2864
2865 tcg_temp_free_i32(zero);
2866 }
2867
2868 return 0;
2869}
2870
40cfacdd
WN
2871static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2872 uint32_t rm, uint32_t dp)
2873{
2874 uint32_t vmin = extract32(insn, 6, 1);
2875 TCGv_ptr fpst = get_fpstatus_ptr(0);
2876
2877 if (dp) {
2878 TCGv_i64 frn, frm, dest;
2879
2880 frn = tcg_temp_new_i64();
2881 frm = tcg_temp_new_i64();
2882 dest = tcg_temp_new_i64();
2883
2884 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2885 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2886 if (vmin) {
f71a2ae5 2887 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
40cfacdd 2888 } else {
f71a2ae5 2889 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
40cfacdd
WN
2890 }
2891 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2892 tcg_temp_free_i64(frn);
2893 tcg_temp_free_i64(frm);
2894 tcg_temp_free_i64(dest);
2895 } else {
2896 TCGv_i32 frn, frm, dest;
2897
2898 frn = tcg_temp_new_i32();
2899 frm = tcg_temp_new_i32();
2900 dest = tcg_temp_new_i32();
2901
2902 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2903 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2904 if (vmin) {
f71a2ae5 2905 gen_helper_vfp_minnums(dest, frn, frm, fpst);
40cfacdd 2906 } else {
f71a2ae5 2907 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
40cfacdd
WN
2908 }
2909 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2910 tcg_temp_free_i32(frn);
2911 tcg_temp_free_i32(frm);
2912 tcg_temp_free_i32(dest);
2913 }
2914
2915 tcg_temp_free_ptr(fpst);
2916 return 0;
2917}
2918
7655f39b
WN
2919static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2920 int rounding)
2921{
2922 TCGv_ptr fpst = get_fpstatus_ptr(0);
2923 TCGv_i32 tcg_rmode;
2924
2925 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2926 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2927
2928 if (dp) {
2929 TCGv_i64 tcg_op;
2930 TCGv_i64 tcg_res;
2931 tcg_op = tcg_temp_new_i64();
2932 tcg_res = tcg_temp_new_i64();
2933 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2934 gen_helper_rintd(tcg_res, tcg_op, fpst);
2935 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2936 tcg_temp_free_i64(tcg_op);
2937 tcg_temp_free_i64(tcg_res);
2938 } else {
2939 TCGv_i32 tcg_op;
2940 TCGv_i32 tcg_res;
2941 tcg_op = tcg_temp_new_i32();
2942 tcg_res = tcg_temp_new_i32();
2943 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2944 gen_helper_rints(tcg_res, tcg_op, fpst);
2945 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2946 tcg_temp_free_i32(tcg_op);
2947 tcg_temp_free_i32(tcg_res);
2948 }
2949
2950 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2951 tcg_temp_free_i32(tcg_rmode);
2952
2953 tcg_temp_free_ptr(fpst);
2954 return 0;
2955}
2956
c9975a83
WN
2957static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2958 int rounding)
2959{
2960 bool is_signed = extract32(insn, 7, 1);
2961 TCGv_ptr fpst = get_fpstatus_ptr(0);
2962 TCGv_i32 tcg_rmode, tcg_shift;
2963
2964 tcg_shift = tcg_const_i32(0);
2965
2966 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2967 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2968
2969 if (dp) {
2970 TCGv_i64 tcg_double, tcg_res;
2971 TCGv_i32 tcg_tmp;
2972 /* Rd is encoded as a single precision register even when the source
2973 * is double precision.
2974 */
2975 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2976 tcg_double = tcg_temp_new_i64();
2977 tcg_res = tcg_temp_new_i64();
2978 tcg_tmp = tcg_temp_new_i32();
2979 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2980 if (is_signed) {
2981 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2982 } else {
2983 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2984 }
ecc7b3aa 2985 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
c9975a83
WN
2986 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2987 tcg_temp_free_i32(tcg_tmp);
2988 tcg_temp_free_i64(tcg_res);
2989 tcg_temp_free_i64(tcg_double);
2990 } else {
2991 TCGv_i32 tcg_single, tcg_res;
2992 tcg_single = tcg_temp_new_i32();
2993 tcg_res = tcg_temp_new_i32();
2994 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2995 if (is_signed) {
2996 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2997 } else {
2998 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2999 }
3000 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3001 tcg_temp_free_i32(tcg_res);
3002 tcg_temp_free_i32(tcg_single);
3003 }
3004
3005 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3006 tcg_temp_free_i32(tcg_rmode);
3007
3008 tcg_temp_free_i32(tcg_shift);
3009
3010 tcg_temp_free_ptr(fpst);
3011
3012 return 0;
3013}
7655f39b
WN
3014
3015/* Table for converting the most common AArch32 encoding of
3016 * rounding mode to arm_fprounding order (which matches the
3017 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3018 */
3019static const uint8_t fp_decode_rm[] = {
3020 FPROUNDING_TIEAWAY,
3021 FPROUNDING_TIEEVEN,
3022 FPROUNDING_POSINF,
3023 FPROUNDING_NEGINF,
3024};
3025
7dcc1f89 3026static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
04731fb5
WN
3027{
3028 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3029
d614a513 3030 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
04731fb5
WN
3031 return 1;
3032 }
3033
3034 if (dp) {
3035 VFP_DREG_D(rd, insn);
3036 VFP_DREG_N(rn, insn);
3037 VFP_DREG_M(rm, insn);
3038 } else {
3039 rd = VFP_SREG_D(insn);
3040 rn = VFP_SREG_N(insn);
3041 rm = VFP_SREG_M(insn);
3042 }
3043
3044 if ((insn & 0x0f800e50) == 0x0e000a00) {
3045 return handle_vsel(insn, rd, rn, rm, dp);
40cfacdd
WN
3046 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
3047 return handle_vminmaxnm(insn, rd, rn, rm, dp);
7655f39b
WN
3048 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
3049 /* VRINTA, VRINTN, VRINTP, VRINTM */
3050 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3051 return handle_vrint(insn, rd, rm, dp, rounding);
c9975a83
WN
3052 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
3053 /* VCVTA, VCVTN, VCVTP, VCVTM */
3054 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3055 return handle_vcvt(insn, rd, rm, dp, rounding);
04731fb5
WN
3056 }
3057 return 1;
3058}
3059
a1c7273b 3060/* Disassemble a VFP instruction. Returns nonzero if an error occurred
b7bcbe95 3061 (ie. an undefined instruction). */
7dcc1f89 3062static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95
FB
3063{
3064 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3065 int dp, veclen;
39d5492a
PM
3066 TCGv_i32 addr;
3067 TCGv_i32 tmp;
3068 TCGv_i32 tmp2;
b7bcbe95 3069
d614a513 3070 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 3071 return 1;
d614a513 3072 }
40f137e1 3073
2c7ffc41
PM
3074 /* FIXME: this access check should not take precedence over UNDEF
3075 * for invalid encodings; we will generate incorrect syndrome information
3076 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3077 */
9dbbc748 3078 if (s->fp_excp_el) {
2c7ffc41 3079 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 3080 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3081 return 0;
3082 }
3083
5df8bac1 3084 if (!s->vfp_enabled) {
9ee6e8bb 3085 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
3086 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3087 return 1;
3088 rn = (insn >> 16) & 0xf;
a50c0f51
PM
3089 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3090 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
40f137e1 3091 return 1;
a50c0f51 3092 }
40f137e1 3093 }
6a57f3eb
WN
3094
3095 if (extract32(insn, 28, 4) == 0xf) {
3096 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3097 * only used in v8 and above.
3098 */
7dcc1f89 3099 return disas_vfp_v8_insn(s, insn);
6a57f3eb
WN
3100 }
3101
b7bcbe95
FB
3102 dp = ((insn & 0xf00) == 0xb00);
3103 switch ((insn >> 24) & 0xf) {
3104 case 0xe:
3105 if (insn & (1 << 4)) {
3106 /* single register transfer */
b7bcbe95
FB
3107 rd = (insn >> 12) & 0xf;
3108 if (dp) {
9ee6e8bb
PB
3109 int size;
3110 int pass;
3111
3112 VFP_DREG_N(rn, insn);
3113 if (insn & 0xf)
b7bcbe95 3114 return 1;
9ee6e8bb 3115 if (insn & 0x00c00060
d614a513 3116 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 3117 return 1;
d614a513 3118 }
9ee6e8bb
PB
3119
3120 pass = (insn >> 21) & 1;
3121 if (insn & (1 << 22)) {
3122 size = 0;
3123 offset = ((insn >> 5) & 3) * 8;
3124 } else if (insn & (1 << 5)) {
3125 size = 1;
3126 offset = (insn & (1 << 6)) ? 16 : 0;
3127 } else {
3128 size = 2;
3129 offset = 0;
3130 }
18c9b560 3131 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3132 /* vfp->arm */
ad69471c 3133 tmp = neon_load_reg(rn, pass);
9ee6e8bb
PB
3134 switch (size) {
3135 case 0:
9ee6e8bb 3136 if (offset)
ad69471c 3137 tcg_gen_shri_i32(tmp, tmp, offset);
9ee6e8bb 3138 if (insn & (1 << 23))
ad69471c 3139 gen_uxtb(tmp);
9ee6e8bb 3140 else
ad69471c 3141 gen_sxtb(tmp);
9ee6e8bb
PB
3142 break;
3143 case 1:
9ee6e8bb
PB
3144 if (insn & (1 << 23)) {
3145 if (offset) {
ad69471c 3146 tcg_gen_shri_i32(tmp, tmp, 16);
9ee6e8bb 3147 } else {
ad69471c 3148 gen_uxth(tmp);
9ee6e8bb
PB
3149 }
3150 } else {
3151 if (offset) {
ad69471c 3152 tcg_gen_sari_i32(tmp, tmp, 16);
9ee6e8bb 3153 } else {
ad69471c 3154 gen_sxth(tmp);
9ee6e8bb
PB
3155 }
3156 }
3157 break;
3158 case 2:
9ee6e8bb
PB
3159 break;
3160 }
ad69471c 3161 store_reg(s, rd, tmp);
b7bcbe95
FB
3162 } else {
3163 /* arm->vfp */
ad69471c 3164 tmp = load_reg(s, rd);
9ee6e8bb
PB
3165 if (insn & (1 << 23)) {
3166 /* VDUP */
3167 if (size == 0) {
ad69471c 3168 gen_neon_dup_u8(tmp, 0);
9ee6e8bb 3169 } else if (size == 1) {
ad69471c 3170 gen_neon_dup_low16(tmp);
9ee6e8bb 3171 }
cbbccffc 3172 for (n = 0; n <= pass * 2; n++) {
7d1b0095 3173 tmp2 = tcg_temp_new_i32();
cbbccffc
PB
3174 tcg_gen_mov_i32(tmp2, tmp);
3175 neon_store_reg(rn, n, tmp2);
3176 }
3177 neon_store_reg(rn, n, tmp);
9ee6e8bb
PB
3178 } else {
3179 /* VMOV */
3180 switch (size) {
3181 case 0:
ad69471c 3182 tmp2 = neon_load_reg(rn, pass);
d593c48e 3183 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
7d1b0095 3184 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3185 break;
3186 case 1:
ad69471c 3187 tmp2 = neon_load_reg(rn, pass);
d593c48e 3188 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
7d1b0095 3189 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3190 break;
3191 case 2:
9ee6e8bb
PB
3192 break;
3193 }
ad69471c 3194 neon_store_reg(rn, pass, tmp);
9ee6e8bb 3195 }
b7bcbe95 3196 }
9ee6e8bb
PB
3197 } else { /* !dp */
3198 if ((insn & 0x6f) != 0x00)
3199 return 1;
3200 rn = VFP_SREG_N(insn);
18c9b560 3201 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3202 /* vfp->arm */
3203 if (insn & (1 << 21)) {
3204 /* system register */
40f137e1 3205 rn >>= 1;
9ee6e8bb 3206
b7bcbe95 3207 switch (rn) {
40f137e1 3208 case ARM_VFP_FPSID:
4373f3ce 3209 /* VFP2 allows access to FSID from userspace.
9ee6e8bb
PB
3210 VFP3 restricts all id registers to privileged
3211 accesses. */
3212 if (IS_USER(s)
d614a513 3213 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3214 return 1;
d614a513 3215 }
4373f3ce 3216 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3217 break;
40f137e1 3218 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3219 if (IS_USER(s))
3220 return 1;
4373f3ce 3221 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3222 break;
40f137e1
PB
3223 case ARM_VFP_FPINST:
3224 case ARM_VFP_FPINST2:
9ee6e8bb
PB
3225 /* Not present in VFP3. */
3226 if (IS_USER(s)
d614a513 3227 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3228 return 1;
d614a513 3229 }
4373f3ce 3230 tmp = load_cpu_field(vfp.xregs[rn]);
b7bcbe95 3231 break;
40f137e1 3232 case ARM_VFP_FPSCR:
601d70b9 3233 if (rd == 15) {
4373f3ce
PB
3234 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3235 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3236 } else {
7d1b0095 3237 tmp = tcg_temp_new_i32();
4373f3ce
PB
3238 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3239 }
b7bcbe95 3240 break;
a50c0f51 3241 case ARM_VFP_MVFR2:
d614a513 3242 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
a50c0f51
PM
3243 return 1;
3244 }
3245 /* fall through */
9ee6e8bb
PB
3246 case ARM_VFP_MVFR0:
3247 case ARM_VFP_MVFR1:
3248 if (IS_USER(s)
d614a513 3249 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
9ee6e8bb 3250 return 1;
d614a513 3251 }
4373f3ce 3252 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3253 break;
b7bcbe95
FB
3254 default:
3255 return 1;
3256 }
3257 } else {
3258 gen_mov_F0_vreg(0, rn);
4373f3ce 3259 tmp = gen_vfp_mrs();
b7bcbe95
FB
3260 }
3261 if (rd == 15) {
b5ff1b31 3262 /* Set the 4 flag bits in the CPSR. */
4373f3ce 3263 gen_set_nzcv(tmp);
7d1b0095 3264 tcg_temp_free_i32(tmp);
4373f3ce
PB
3265 } else {
3266 store_reg(s, rd, tmp);
3267 }
b7bcbe95
FB
3268 } else {
3269 /* arm->vfp */
b7bcbe95 3270 if (insn & (1 << 21)) {
40f137e1 3271 rn >>= 1;
b7bcbe95
FB
3272 /* system register */
3273 switch (rn) {
40f137e1 3274 case ARM_VFP_FPSID:
9ee6e8bb
PB
3275 case ARM_VFP_MVFR0:
3276 case ARM_VFP_MVFR1:
b7bcbe95
FB
3277 /* Writes are ignored. */
3278 break;
40f137e1 3279 case ARM_VFP_FPSCR:
e4c1cfa5 3280 tmp = load_reg(s, rd);
4373f3ce 3281 gen_helper_vfp_set_fpscr(cpu_env, tmp);
7d1b0095 3282 tcg_temp_free_i32(tmp);
b5ff1b31 3283 gen_lookup_tb(s);
b7bcbe95 3284 break;
40f137e1 3285 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3286 if (IS_USER(s))
3287 return 1;
71b3c3de
JR
3288 /* TODO: VFP subarchitecture support.
3289 * For now, keep the EN bit only */
e4c1cfa5 3290 tmp = load_reg(s, rd);
71b3c3de 3291 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
4373f3ce 3292 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1
PB
3293 gen_lookup_tb(s);
3294 break;
3295 case ARM_VFP_FPINST:
3296 case ARM_VFP_FPINST2:
23adb861
PM
3297 if (IS_USER(s)) {
3298 return 1;
3299 }
e4c1cfa5 3300 tmp = load_reg(s, rd);
4373f3ce 3301 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1 3302 break;
b7bcbe95
FB
3303 default:
3304 return 1;
3305 }
3306 } else {
e4c1cfa5 3307 tmp = load_reg(s, rd);
4373f3ce 3308 gen_vfp_msr(tmp);
b7bcbe95
FB
3309 gen_mov_vreg_F0(0, rn);
3310 }
3311 }
3312 }
3313 } else {
3314 /* data processing */
3315 /* The opcode is in bits 23, 21, 20 and 6. */
3316 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3317 if (dp) {
3318 if (op == 15) {
3319 /* rn is opcode */
3320 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3321 } else {
3322 /* rn is register number */
9ee6e8bb 3323 VFP_DREG_N(rn, insn);
b7bcbe95
FB
3324 }
3325
239c20c7
WN
3326 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3327 ((rn & 0x1e) == 0x6))) {
3328 /* Integer or single/half precision destination. */
9ee6e8bb 3329 rd = VFP_SREG_D(insn);
b7bcbe95 3330 } else {
9ee6e8bb 3331 VFP_DREG_D(rd, insn);
b7bcbe95 3332 }
04595bf6 3333 if (op == 15 &&
239c20c7
WN
3334 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3335 ((rn & 0x1e) == 0x4))) {
3336 /* VCVT from int or half precision is always from S reg
3337 * regardless of dp bit. VCVT with immediate frac_bits
3338 * has same format as SREG_M.
04595bf6
PM
3339 */
3340 rm = VFP_SREG_M(insn);
b7bcbe95 3341 } else {
9ee6e8bb 3342 VFP_DREG_M(rm, insn);
b7bcbe95
FB
3343 }
3344 } else {
9ee6e8bb 3345 rn = VFP_SREG_N(insn);
b7bcbe95
FB
3346 if (op == 15 && rn == 15) {
3347 /* Double precision destination. */
9ee6e8bb
PB
3348 VFP_DREG_D(rd, insn);
3349 } else {
3350 rd = VFP_SREG_D(insn);
3351 }
04595bf6
PM
3352 /* NB that we implicitly rely on the encoding for the frac_bits
3353 * in VCVT of fixed to float being the same as that of an SREG_M
3354 */
9ee6e8bb 3355 rm = VFP_SREG_M(insn);
b7bcbe95
FB
3356 }
3357
69d1fc22 3358 veclen = s->vec_len;
b7bcbe95
FB
3359 if (op == 15 && rn > 3)
3360 veclen = 0;
3361
3362 /* Shut up compiler warnings. */
3363 delta_m = 0;
3364 delta_d = 0;
3365 bank_mask = 0;
3b46e624 3366
b7bcbe95
FB
3367 if (veclen > 0) {
3368 if (dp)
3369 bank_mask = 0xc;
3370 else
3371 bank_mask = 0x18;
3372
3373 /* Figure out what type of vector operation this is. */
3374 if ((rd & bank_mask) == 0) {
3375 /* scalar */
3376 veclen = 0;
3377 } else {
3378 if (dp)
69d1fc22 3379 delta_d = (s->vec_stride >> 1) + 1;
b7bcbe95 3380 else
69d1fc22 3381 delta_d = s->vec_stride + 1;
b7bcbe95
FB
3382
3383 if ((rm & bank_mask) == 0) {
3384 /* mixed scalar/vector */
3385 delta_m = 0;
3386 } else {
3387 /* vector */
3388 delta_m = delta_d;
3389 }
3390 }
3391 }
3392
3393 /* Load the initial operands. */
3394 if (op == 15) {
3395 switch (rn) {
3396 case 16:
3397 case 17:
3398 /* Integer source */
3399 gen_mov_F0_vreg(0, rm);
3400 break;
3401 case 8:
3402 case 9:
3403 /* Compare */
3404 gen_mov_F0_vreg(dp, rd);
3405 gen_mov_F1_vreg(dp, rm);
3406 break;
3407 case 10:
3408 case 11:
3409 /* Compare with zero */
3410 gen_mov_F0_vreg(dp, rd);
3411 gen_vfp_F1_ld0(dp);
3412 break;
9ee6e8bb
PB
3413 case 20:
3414 case 21:
3415 case 22:
3416 case 23:
644ad806
PB
3417 case 28:
3418 case 29:
3419 case 30:
3420 case 31:
9ee6e8bb
PB
3421 /* Source and destination the same. */
3422 gen_mov_F0_vreg(dp, rd);
3423 break;
6e0c0ed1
PM
3424 case 4:
3425 case 5:
3426 case 6:
3427 case 7:
239c20c7
WN
3428 /* VCVTB, VCVTT: only present with the halfprec extension
3429 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3430 * (we choose to UNDEF)
6e0c0ed1 3431 */
d614a513
PM
3432 if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
3433 !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
6e0c0ed1
PM
3434 return 1;
3435 }
239c20c7
WN
3436 if (!extract32(rn, 1, 1)) {
3437 /* Half precision source. */
3438 gen_mov_F0_vreg(0, rm);
3439 break;
3440 }
6e0c0ed1 3441 /* Otherwise fall through */
b7bcbe95
FB
3442 default:
3443 /* One source operand. */
3444 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 3445 break;
b7bcbe95
FB
3446 }
3447 } else {
3448 /* Two source operands. */
3449 gen_mov_F0_vreg(dp, rn);
3450 gen_mov_F1_vreg(dp, rm);
3451 }
3452
3453 for (;;) {
3454 /* Perform the calculation. */
3455 switch (op) {
605a6aed
PM
3456 case 0: /* VMLA: fd + (fn * fm) */
3457 /* Note that order of inputs to the add matters for NaNs */
3458 gen_vfp_F1_mul(dp);
3459 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3460 gen_vfp_add(dp);
3461 break;
605a6aed 3462 case 1: /* VMLS: fd + -(fn * fm) */
b7bcbe95 3463 gen_vfp_mul(dp);
605a6aed
PM
3464 gen_vfp_F1_neg(dp);
3465 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3466 gen_vfp_add(dp);
3467 break;
605a6aed
PM
3468 case 2: /* VNMLS: -fd + (fn * fm) */
3469 /* Note that it isn't valid to replace (-A + B) with (B - A)
3470 * or similar plausible looking simplifications
3471 * because this will give wrong results for NaNs.
3472 */
3473 gen_vfp_F1_mul(dp);
3474 gen_mov_F0_vreg(dp, rd);
3475 gen_vfp_neg(dp);
3476 gen_vfp_add(dp);
b7bcbe95 3477 break;
605a6aed 3478 case 3: /* VNMLA: -fd + -(fn * fm) */
b7bcbe95 3479 gen_vfp_mul(dp);
605a6aed
PM
3480 gen_vfp_F1_neg(dp);
3481 gen_mov_F0_vreg(dp, rd);
b7bcbe95 3482 gen_vfp_neg(dp);
605a6aed 3483 gen_vfp_add(dp);
b7bcbe95
FB
3484 break;
3485 case 4: /* mul: fn * fm */
3486 gen_vfp_mul(dp);
3487 break;
3488 case 5: /* nmul: -(fn * fm) */
3489 gen_vfp_mul(dp);
3490 gen_vfp_neg(dp);
3491 break;
3492 case 6: /* add: fn + fm */
3493 gen_vfp_add(dp);
3494 break;
3495 case 7: /* sub: fn - fm */
3496 gen_vfp_sub(dp);
3497 break;
3498 case 8: /* div: fn / fm */
3499 gen_vfp_div(dp);
3500 break;
da97f52c
PM
3501 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3502 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3503 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3504 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3505 /* These are fused multiply-add, and must be done as one
3506 * floating point operation with no rounding between the
3507 * multiplication and addition steps.
3508 * NB that doing the negations here as separate steps is
3509 * correct : an input NaN should come out with its sign bit
3510 * flipped if it is a negated-input.
3511 */
d614a513 3512 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
3513 return 1;
3514 }
3515 if (dp) {
3516 TCGv_ptr fpst;
3517 TCGv_i64 frd;
3518 if (op & 1) {
3519 /* VFNMS, VFMS */
3520 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3521 }
3522 frd = tcg_temp_new_i64();
3523 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3524 if (op & 2) {
3525 /* VFNMA, VFNMS */
3526 gen_helper_vfp_negd(frd, frd);
3527 }
3528 fpst = get_fpstatus_ptr(0);
3529 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3530 cpu_F1d, frd, fpst);
3531 tcg_temp_free_ptr(fpst);
3532 tcg_temp_free_i64(frd);
3533 } else {
3534 TCGv_ptr fpst;
3535 TCGv_i32 frd;
3536 if (op & 1) {
3537 /* VFNMS, VFMS */
3538 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3539 }
3540 frd = tcg_temp_new_i32();
3541 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3542 if (op & 2) {
3543 gen_helper_vfp_negs(frd, frd);
3544 }
3545 fpst = get_fpstatus_ptr(0);
3546 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3547 cpu_F1s, frd, fpst);
3548 tcg_temp_free_ptr(fpst);
3549 tcg_temp_free_i32(frd);
3550 }
3551 break;
9ee6e8bb 3552 case 14: /* fconst */
d614a513
PM
3553 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3554 return 1;
3555 }
9ee6e8bb
PB
3556
3557 n = (insn << 12) & 0x80000000;
3558 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3559 if (dp) {
3560 if (i & 0x40)
3561 i |= 0x3f80;
3562 else
3563 i |= 0x4000;
3564 n |= i << 16;
4373f3ce 3565 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
9ee6e8bb
PB
3566 } else {
3567 if (i & 0x40)
3568 i |= 0x780;
3569 else
3570 i |= 0x800;
3571 n |= i << 19;
5b340b51 3572 tcg_gen_movi_i32(cpu_F0s, n);
9ee6e8bb 3573 }
9ee6e8bb 3574 break;
b7bcbe95
FB
3575 case 15: /* extension space */
3576 switch (rn) {
3577 case 0: /* cpy */
3578 /* no-op */
3579 break;
3580 case 1: /* abs */
3581 gen_vfp_abs(dp);
3582 break;
3583 case 2: /* neg */
3584 gen_vfp_neg(dp);
3585 break;
3586 case 3: /* sqrt */
3587 gen_vfp_sqrt(dp);
3588 break;
239c20c7 3589 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
60011498
PB
3590 tmp = gen_vfp_mrs();
3591 tcg_gen_ext16u_i32(tmp, tmp);
239c20c7
WN
3592 if (dp) {
3593 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3594 cpu_env);
3595 } else {
3596 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3597 cpu_env);
3598 }
7d1b0095 3599 tcg_temp_free_i32(tmp);
60011498 3600 break;
239c20c7 3601 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
60011498
PB
3602 tmp = gen_vfp_mrs();
3603 tcg_gen_shri_i32(tmp, tmp, 16);
239c20c7
WN
3604 if (dp) {
3605 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3606 cpu_env);
3607 } else {
3608 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3609 cpu_env);
3610 }
7d1b0095 3611 tcg_temp_free_i32(tmp);
60011498 3612 break;
239c20c7 3613 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
7d1b0095 3614 tmp = tcg_temp_new_i32();
239c20c7
WN
3615 if (dp) {
3616 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3617 cpu_env);
3618 } else {
3619 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3620 cpu_env);
3621 }
60011498
PB
3622 gen_mov_F0_vreg(0, rd);
3623 tmp2 = gen_vfp_mrs();
3624 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3625 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3626 tcg_temp_free_i32(tmp2);
60011498
PB
3627 gen_vfp_msr(tmp);
3628 break;
239c20c7 3629 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
7d1b0095 3630 tmp = tcg_temp_new_i32();
239c20c7
WN
3631 if (dp) {
3632 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3633 cpu_env);
3634 } else {
3635 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3636 cpu_env);
3637 }
60011498
PB
3638 tcg_gen_shli_i32(tmp, tmp, 16);
3639 gen_mov_F0_vreg(0, rd);
3640 tmp2 = gen_vfp_mrs();
3641 tcg_gen_ext16u_i32(tmp2, tmp2);
3642 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3643 tcg_temp_free_i32(tmp2);
60011498
PB
3644 gen_vfp_msr(tmp);
3645 break;
b7bcbe95
FB
3646 case 8: /* cmp */
3647 gen_vfp_cmp(dp);
3648 break;
3649 case 9: /* cmpe */
3650 gen_vfp_cmpe(dp);
3651 break;
3652 case 10: /* cmpz */
3653 gen_vfp_cmp(dp);
3654 break;
3655 case 11: /* cmpez */
3656 gen_vfp_F1_ld0(dp);
3657 gen_vfp_cmpe(dp);
3658 break;
664c6733
WN
3659 case 12: /* vrintr */
3660 {
3661 TCGv_ptr fpst = get_fpstatus_ptr(0);
3662 if (dp) {
3663 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3664 } else {
3665 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3666 }
3667 tcg_temp_free_ptr(fpst);
3668 break;
3669 }
a290c62a
WN
3670 case 13: /* vrintz */
3671 {
3672 TCGv_ptr fpst = get_fpstatus_ptr(0);
3673 TCGv_i32 tcg_rmode;
3674 tcg_rmode = tcg_const_i32(float_round_to_zero);
3675 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3676 if (dp) {
3677 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3678 } else {
3679 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3680 }
3681 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3682 tcg_temp_free_i32(tcg_rmode);
3683 tcg_temp_free_ptr(fpst);
3684 break;
3685 }
4e82bc01
WN
3686 case 14: /* vrintx */
3687 {
3688 TCGv_ptr fpst = get_fpstatus_ptr(0);
3689 if (dp) {
3690 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3691 } else {
3692 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3693 }
3694 tcg_temp_free_ptr(fpst);
3695 break;
3696 }
b7bcbe95
FB
3697 case 15: /* single<->double conversion */
3698 if (dp)
4373f3ce 3699 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
b7bcbe95 3700 else
4373f3ce 3701 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
b7bcbe95
FB
3702 break;
3703 case 16: /* fuito */
5500b06c 3704 gen_vfp_uito(dp, 0);
b7bcbe95
FB
3705 break;
3706 case 17: /* fsito */
5500b06c 3707 gen_vfp_sito(dp, 0);
b7bcbe95 3708 break;
9ee6e8bb 3709 case 20: /* fshto */
d614a513
PM
3710 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3711 return 1;
3712 }
5500b06c 3713 gen_vfp_shto(dp, 16 - rm, 0);
9ee6e8bb
PB
3714 break;
3715 case 21: /* fslto */
d614a513
PM
3716 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3717 return 1;
3718 }
5500b06c 3719 gen_vfp_slto(dp, 32 - rm, 0);
9ee6e8bb
PB
3720 break;
3721 case 22: /* fuhto */
d614a513
PM
3722 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3723 return 1;
3724 }
5500b06c 3725 gen_vfp_uhto(dp, 16 - rm, 0);
9ee6e8bb
PB
3726 break;
3727 case 23: /* fulto */
d614a513
PM
3728 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3729 return 1;
3730 }
5500b06c 3731 gen_vfp_ulto(dp, 32 - rm, 0);
9ee6e8bb 3732 break;
b7bcbe95 3733 case 24: /* ftoui */
5500b06c 3734 gen_vfp_toui(dp, 0);
b7bcbe95
FB
3735 break;
3736 case 25: /* ftouiz */
5500b06c 3737 gen_vfp_touiz(dp, 0);
b7bcbe95
FB
3738 break;
3739 case 26: /* ftosi */
5500b06c 3740 gen_vfp_tosi(dp, 0);
b7bcbe95
FB
3741 break;
3742 case 27: /* ftosiz */
5500b06c 3743 gen_vfp_tosiz(dp, 0);
b7bcbe95 3744 break;
9ee6e8bb 3745 case 28: /* ftosh */
d614a513
PM
3746 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3747 return 1;
3748 }
5500b06c 3749 gen_vfp_tosh(dp, 16 - rm, 0);
9ee6e8bb
PB
3750 break;
3751 case 29: /* ftosl */
d614a513
PM
3752 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3753 return 1;
3754 }
5500b06c 3755 gen_vfp_tosl(dp, 32 - rm, 0);
9ee6e8bb
PB
3756 break;
3757 case 30: /* ftouh */
d614a513
PM
3758 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3759 return 1;
3760 }
5500b06c 3761 gen_vfp_touh(dp, 16 - rm, 0);
9ee6e8bb
PB
3762 break;
3763 case 31: /* ftoul */
d614a513
PM
3764 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3765 return 1;
3766 }
5500b06c 3767 gen_vfp_toul(dp, 32 - rm, 0);
9ee6e8bb 3768 break;
b7bcbe95 3769 default: /* undefined */
b7bcbe95
FB
3770 return 1;
3771 }
3772 break;
3773 default: /* undefined */
b7bcbe95
FB
3774 return 1;
3775 }
3776
3777 /* Write back the result. */
239c20c7
WN
3778 if (op == 15 && (rn >= 8 && rn <= 11)) {
3779 /* Comparison, do nothing. */
3780 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3781 (rn & 0x1e) == 0x6)) {
3782 /* VCVT double to int: always integer result.
3783 * VCVT double to half precision is always a single
3784 * precision result.
3785 */
b7bcbe95 3786 gen_mov_vreg_F0(0, rd);
239c20c7 3787 } else if (op == 15 && rn == 15) {
b7bcbe95
FB
3788 /* conversion */
3789 gen_mov_vreg_F0(!dp, rd);
239c20c7 3790 } else {
b7bcbe95 3791 gen_mov_vreg_F0(dp, rd);
239c20c7 3792 }
b7bcbe95
FB
3793
3794 /* break out of the loop if we have finished */
3795 if (veclen == 0)
3796 break;
3797
3798 if (op == 15 && delta_m == 0) {
3799 /* single source one-many */
3800 while (veclen--) {
3801 rd = ((rd + delta_d) & (bank_mask - 1))
3802 | (rd & bank_mask);
3803 gen_mov_vreg_F0(dp, rd);
3804 }
3805 break;
3806 }
3807 /* Setup the next operands. */
3808 veclen--;
3809 rd = ((rd + delta_d) & (bank_mask - 1))
3810 | (rd & bank_mask);
3811
3812 if (op == 15) {
3813 /* One source operand. */
3814 rm = ((rm + delta_m) & (bank_mask - 1))
3815 | (rm & bank_mask);
3816 gen_mov_F0_vreg(dp, rm);
3817 } else {
3818 /* Two source operands. */
3819 rn = ((rn + delta_d) & (bank_mask - 1))
3820 | (rn & bank_mask);
3821 gen_mov_F0_vreg(dp, rn);
3822 if (delta_m) {
3823 rm = ((rm + delta_m) & (bank_mask - 1))
3824 | (rm & bank_mask);
3825 gen_mov_F1_vreg(dp, rm);
3826 }
3827 }
3828 }
3829 }
3830 break;
3831 case 0xc:
3832 case 0xd:
8387da81 3833 if ((insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
3834 /* two-register transfer */
3835 rn = (insn >> 16) & 0xf;
3836 rd = (insn >> 12) & 0xf;
3837 if (dp) {
9ee6e8bb
PB
3838 VFP_DREG_M(rm, insn);
3839 } else {
3840 rm = VFP_SREG_M(insn);
3841 }
b7bcbe95 3842
18c9b560 3843 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3844 /* vfp->arm */
3845 if (dp) {
4373f3ce
PB
3846 gen_mov_F0_vreg(0, rm * 2);
3847 tmp = gen_vfp_mrs();
3848 store_reg(s, rd, tmp);
3849 gen_mov_F0_vreg(0, rm * 2 + 1);
3850 tmp = gen_vfp_mrs();
3851 store_reg(s, rn, tmp);
b7bcbe95
FB
3852 } else {
3853 gen_mov_F0_vreg(0, rm);
4373f3ce 3854 tmp = gen_vfp_mrs();
8387da81 3855 store_reg(s, rd, tmp);
b7bcbe95 3856 gen_mov_F0_vreg(0, rm + 1);
4373f3ce 3857 tmp = gen_vfp_mrs();
8387da81 3858 store_reg(s, rn, tmp);
b7bcbe95
FB
3859 }
3860 } else {
3861 /* arm->vfp */
3862 if (dp) {
4373f3ce
PB
3863 tmp = load_reg(s, rd);
3864 gen_vfp_msr(tmp);
3865 gen_mov_vreg_F0(0, rm * 2);
3866 tmp = load_reg(s, rn);
3867 gen_vfp_msr(tmp);
3868 gen_mov_vreg_F0(0, rm * 2 + 1);
b7bcbe95 3869 } else {
8387da81 3870 tmp = load_reg(s, rd);
4373f3ce 3871 gen_vfp_msr(tmp);
b7bcbe95 3872 gen_mov_vreg_F0(0, rm);
8387da81 3873 tmp = load_reg(s, rn);
4373f3ce 3874 gen_vfp_msr(tmp);
b7bcbe95
FB
3875 gen_mov_vreg_F0(0, rm + 1);
3876 }
3877 }
3878 } else {
3879 /* Load/store */
3880 rn = (insn >> 16) & 0xf;
3881 if (dp)
9ee6e8bb 3882 VFP_DREG_D(rd, insn);
b7bcbe95 3883 else
9ee6e8bb 3884 rd = VFP_SREG_D(insn);
b7bcbe95
FB
3885 if ((insn & 0x01200000) == 0x01000000) {
3886 /* Single load/store */
3887 offset = (insn & 0xff) << 2;
3888 if ((insn & (1 << 23)) == 0)
3889 offset = -offset;
934814f1
PM
3890 if (s->thumb && rn == 15) {
3891 /* This is actually UNPREDICTABLE */
3892 addr = tcg_temp_new_i32();
3893 tcg_gen_movi_i32(addr, s->pc & ~2);
3894 } else {
3895 addr = load_reg(s, rn);
3896 }
312eea9f 3897 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 3898 if (insn & (1 << 20)) {
312eea9f 3899 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
3900 gen_mov_vreg_F0(dp, rd);
3901 } else {
3902 gen_mov_F0_vreg(dp, rd);
312eea9f 3903 gen_vfp_st(s, dp, addr);
b7bcbe95 3904 }
7d1b0095 3905 tcg_temp_free_i32(addr);
b7bcbe95
FB
3906 } else {
3907 /* load/store multiple */
934814f1 3908 int w = insn & (1 << 21);
b7bcbe95
FB
3909 if (dp)
3910 n = (insn >> 1) & 0x7f;
3911 else
3912 n = insn & 0xff;
3913
934814f1
PM
3914 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3915 /* P == U , W == 1 => UNDEF */
3916 return 1;
3917 }
3918 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3919 /* UNPREDICTABLE cases for bad immediates: we choose to
3920 * UNDEF to avoid generating huge numbers of TCG ops
3921 */
3922 return 1;
3923 }
3924 if (rn == 15 && w) {
3925 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3926 return 1;
3927 }
3928
3929 if (s->thumb && rn == 15) {
3930 /* This is actually UNPREDICTABLE */
3931 addr = tcg_temp_new_i32();
3932 tcg_gen_movi_i32(addr, s->pc & ~2);
3933 } else {
3934 addr = load_reg(s, rn);
3935 }
b7bcbe95 3936 if (insn & (1 << 24)) /* pre-decrement */
312eea9f 3937 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
b7bcbe95
FB
3938
3939 if (dp)
3940 offset = 8;
3941 else
3942 offset = 4;
3943 for (i = 0; i < n; i++) {
18c9b560 3944 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3945 /* load */
312eea9f 3946 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
3947 gen_mov_vreg_F0(dp, rd + i);
3948 } else {
3949 /* store */
3950 gen_mov_F0_vreg(dp, rd + i);
312eea9f 3951 gen_vfp_st(s, dp, addr);
b7bcbe95 3952 }
312eea9f 3953 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 3954 }
934814f1 3955 if (w) {
b7bcbe95
FB
3956 /* writeback */
3957 if (insn & (1 << 24))
3958 offset = -offset * n;
3959 else if (dp && (insn & 1))
3960 offset = 4;
3961 else
3962 offset = 0;
3963
3964 if (offset != 0)
312eea9f
FN
3965 tcg_gen_addi_i32(addr, addr, offset);
3966 store_reg(s, rn, addr);
3967 } else {
7d1b0095 3968 tcg_temp_free_i32(addr);
b7bcbe95
FB
3969 }
3970 }
3971 }
3972 break;
3973 default:
3974 /* Should never happen. */
3975 return 1;
3976 }
3977 return 0;
3978}
3979
0a2461fa 3980static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
c53be334 3981{
6e256c93
FB
3982 TranslationBlock *tb;
3983
3984 tb = s->tb;
3985 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
57fec1fe 3986 tcg_gen_goto_tb(n);
eaed129d 3987 gen_set_pc_im(s, dest);
8cfd0495 3988 tcg_gen_exit_tb((uintptr_t)tb + n);
6e256c93 3989 } else {
eaed129d 3990 gen_set_pc_im(s, dest);
57fec1fe 3991 tcg_gen_exit_tb(0);
6e256c93 3992 }
c53be334
FB
3993}
3994
8aaca4c0
FB
3995static inline void gen_jmp (DisasContext *s, uint32_t dest)
3996{
50225ad0 3997 if (unlikely(s->singlestep_enabled || s->ss_active)) {
8aaca4c0 3998 /* An indirect jump so that we still trigger the debug exception. */
5899f386 3999 if (s->thumb)
d9ba4830
PB
4000 dest |= 1;
4001 gen_bx_im(s, dest);
8aaca4c0 4002 } else {
6e256c93 4003 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
4004 s->is_jmp = DISAS_TB_JUMP;
4005 }
4006}
4007
39d5492a 4008static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 4009{
ee097184 4010 if (x)
d9ba4830 4011 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 4012 else
d9ba4830 4013 gen_sxth(t0);
ee097184 4014 if (y)
d9ba4830 4015 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 4016 else
d9ba4830
PB
4017 gen_sxth(t1);
4018 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
4019}
4020
4021/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
4022static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4023{
b5ff1b31
FB
4024 uint32_t mask;
4025
4026 mask = 0;
4027 if (flags & (1 << 0))
4028 mask |= 0xff;
4029 if (flags & (1 << 1))
4030 mask |= 0xff00;
4031 if (flags & (1 << 2))
4032 mask |= 0xff0000;
4033 if (flags & (1 << 3))
4034 mask |= 0xff000000;
9ee6e8bb 4035
2ae23e75 4036 /* Mask out undefined bits. */
9ee6e8bb 4037 mask &= ~CPSR_RESERVED;
d614a513 4038 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 4039 mask &= ~CPSR_T;
d614a513
PM
4040 }
4041 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 4042 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
4043 }
4044 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 4045 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
4046 }
4047 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 4048 mask &= ~CPSR_IT;
d614a513 4049 }
4051e12c
PM
4050 /* Mask out execution state and reserved bits. */
4051 if (!spsr) {
4052 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4053 }
b5ff1b31
FB
4054 /* Mask out privileged bits. */
4055 if (IS_USER(s))
9ee6e8bb 4056 mask &= CPSR_USER;
b5ff1b31
FB
4057 return mask;
4058}
4059
2fbac54b 4060/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 4061static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 4062{
39d5492a 4063 TCGv_i32 tmp;
b5ff1b31
FB
4064 if (spsr) {
4065 /* ??? This is also undefined in system mode. */
4066 if (IS_USER(s))
4067 return 1;
d9ba4830
PB
4068
4069 tmp = load_cpu_field(spsr);
4070 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
4071 tcg_gen_andi_i32(t0, t0, mask);
4072 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 4073 store_cpu_field(tmp, spsr);
b5ff1b31 4074 } else {
2fbac54b 4075 gen_set_cpsr(t0, mask);
b5ff1b31 4076 }
7d1b0095 4077 tcg_temp_free_i32(t0);
b5ff1b31
FB
4078 gen_lookup_tb(s);
4079 return 0;
4080}
4081
2fbac54b
FN
4082/* Returns nonzero if access to the PSR is not permitted. */
4083static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4084{
39d5492a 4085 TCGv_i32 tmp;
7d1b0095 4086 tmp = tcg_temp_new_i32();
2fbac54b
FN
4087 tcg_gen_movi_i32(tmp, val);
4088 return gen_set_psr(s, mask, spsr, tmp);
4089}
4090
e9bb4aa9 4091/* Generate an old-style exception return. Marks pc as dead. */
39d5492a 4092static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
b5ff1b31 4093{
39d5492a 4094 TCGv_i32 tmp;
e9bb4aa9 4095 store_reg(s, 15, pc);
d9ba4830 4096 tmp = load_cpu_field(spsr);
235ea1f5 4097 gen_helper_cpsr_write_eret(cpu_env, tmp);
7d1b0095 4098 tcg_temp_free_i32(tmp);
577bf808 4099 s->is_jmp = DISAS_JUMP;
b5ff1b31
FB
4100}
4101
b0109805 4102/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 4103static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 4104{
235ea1f5 4105 gen_helper_cpsr_write_eret(cpu_env, cpsr);
7d1b0095 4106 tcg_temp_free_i32(cpsr);
b0109805 4107 store_reg(s, 15, pc);
577bf808 4108 s->is_jmp = DISAS_JUMP;
9ee6e8bb 4109}
3b46e624 4110
9ee6e8bb
PB
4111static void gen_nop_hint(DisasContext *s, int val)
4112{
4113 switch (val) {
c87e5a61
PM
4114 case 1: /* yield */
4115 gen_set_pc_im(s, s->pc);
4116 s->is_jmp = DISAS_YIELD;
4117 break;
9ee6e8bb 4118 case 3: /* wfi */
eaed129d 4119 gen_set_pc_im(s, s->pc);
9ee6e8bb
PB
4120 s->is_jmp = DISAS_WFI;
4121 break;
4122 case 2: /* wfe */
72c1d3af
PM
4123 gen_set_pc_im(s, s->pc);
4124 s->is_jmp = DISAS_WFE;
4125 break;
9ee6e8bb 4126 case 4: /* sev */
12b10571
MR
4127 case 5: /* sevl */
4128 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
4129 default: /* nop */
4130 break;
4131 }
4132}
99c475ab 4133
ad69471c 4134#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 4135
39d5492a 4136static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
4137{
4138 switch (size) {
dd8fbd78
FN
4139 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4140 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4141 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 4142 default: abort();
9ee6e8bb 4143 }
9ee6e8bb
PB
4144}
4145
39d5492a 4146static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
4147{
4148 switch (size) {
dd8fbd78
FN
4149 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4150 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4151 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
4152 default: return;
4153 }
4154}
4155
4156/* 32-bit pairwise ops end up the same as the elementwise versions. */
4157#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4158#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4159#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4160#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4161
ad69471c
PB
4162#define GEN_NEON_INTEGER_OP_ENV(name) do { \
4163 switch ((size << 1) | u) { \
4164 case 0: \
dd8fbd78 4165 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4166 break; \
4167 case 1: \
dd8fbd78 4168 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4169 break; \
4170 case 2: \
dd8fbd78 4171 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4172 break; \
4173 case 3: \
dd8fbd78 4174 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4175 break; \
4176 case 4: \
dd8fbd78 4177 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4178 break; \
4179 case 5: \
dd8fbd78 4180 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4181 break; \
4182 default: return 1; \
4183 }} while (0)
9ee6e8bb
PB
4184
4185#define GEN_NEON_INTEGER_OP(name) do { \
4186 switch ((size << 1) | u) { \
ad69471c 4187 case 0: \
dd8fbd78 4188 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
4189 break; \
4190 case 1: \
dd8fbd78 4191 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
4192 break; \
4193 case 2: \
dd8fbd78 4194 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
4195 break; \
4196 case 3: \
dd8fbd78 4197 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
4198 break; \
4199 case 4: \
dd8fbd78 4200 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
4201 break; \
4202 case 5: \
dd8fbd78 4203 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 4204 break; \
9ee6e8bb
PB
4205 default: return 1; \
4206 }} while (0)
4207
39d5492a 4208static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 4209{
39d5492a 4210 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
4211 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4212 return tmp;
9ee6e8bb
PB
4213}
4214
39d5492a 4215static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 4216{
dd8fbd78 4217 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 4218 tcg_temp_free_i32(var);
9ee6e8bb
PB
4219}
4220
39d5492a 4221static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 4222{
39d5492a 4223 TCGv_i32 tmp;
9ee6e8bb 4224 if (size == 1) {
0fad6efc
PM
4225 tmp = neon_load_reg(reg & 7, reg >> 4);
4226 if (reg & 8) {
dd8fbd78 4227 gen_neon_dup_high16(tmp);
0fad6efc
PM
4228 } else {
4229 gen_neon_dup_low16(tmp);
dd8fbd78 4230 }
0fad6efc
PM
4231 } else {
4232 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 4233 }
dd8fbd78 4234 return tmp;
9ee6e8bb
PB
4235}
4236
02acedf9 4237static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 4238{
39d5492a 4239 TCGv_i32 tmp, tmp2;
600b828c 4240 if (!q && size == 2) {
02acedf9
PM
4241 return 1;
4242 }
4243 tmp = tcg_const_i32(rd);
4244 tmp2 = tcg_const_i32(rm);
4245 if (q) {
4246 switch (size) {
4247 case 0:
02da0b2d 4248 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
02acedf9
PM
4249 break;
4250 case 1:
02da0b2d 4251 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
02acedf9
PM
4252 break;
4253 case 2:
02da0b2d 4254 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
02acedf9
PM
4255 break;
4256 default:
4257 abort();
4258 }
4259 } else {
4260 switch (size) {
4261 case 0:
02da0b2d 4262 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
02acedf9
PM
4263 break;
4264 case 1:
02da0b2d 4265 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
02acedf9
PM
4266 break;
4267 default:
4268 abort();
4269 }
4270 }
4271 tcg_temp_free_i32(tmp);
4272 tcg_temp_free_i32(tmp2);
4273 return 0;
19457615
FN
4274}
4275
d68a6f3a 4276static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 4277{
39d5492a 4278 TCGv_i32 tmp, tmp2;
600b828c 4279 if (!q && size == 2) {
d68a6f3a
PM
4280 return 1;
4281 }
4282 tmp = tcg_const_i32(rd);
4283 tmp2 = tcg_const_i32(rm);
4284 if (q) {
4285 switch (size) {
4286 case 0:
02da0b2d 4287 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
d68a6f3a
PM
4288 break;
4289 case 1:
02da0b2d 4290 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
d68a6f3a
PM
4291 break;
4292 case 2:
02da0b2d 4293 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
d68a6f3a
PM
4294 break;
4295 default:
4296 abort();
4297 }
4298 } else {
4299 switch (size) {
4300 case 0:
02da0b2d 4301 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
d68a6f3a
PM
4302 break;
4303 case 1:
02da0b2d 4304 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
d68a6f3a
PM
4305 break;
4306 default:
4307 abort();
4308 }
4309 }
4310 tcg_temp_free_i32(tmp);
4311 tcg_temp_free_i32(tmp2);
4312 return 0;
19457615
FN
4313}
4314
39d5492a 4315static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 4316{
39d5492a 4317 TCGv_i32 rd, tmp;
19457615 4318
7d1b0095
PM
4319 rd = tcg_temp_new_i32();
4320 tmp = tcg_temp_new_i32();
19457615
FN
4321
4322 tcg_gen_shli_i32(rd, t0, 8);
4323 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4324 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4325 tcg_gen_or_i32(rd, rd, tmp);
4326
4327 tcg_gen_shri_i32(t1, t1, 8);
4328 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4329 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4330 tcg_gen_or_i32(t1, t1, tmp);
4331 tcg_gen_mov_i32(t0, rd);
4332
7d1b0095
PM
4333 tcg_temp_free_i32(tmp);
4334 tcg_temp_free_i32(rd);
19457615
FN
4335}
4336
39d5492a 4337static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 4338{
39d5492a 4339 TCGv_i32 rd, tmp;
19457615 4340
7d1b0095
PM
4341 rd = tcg_temp_new_i32();
4342 tmp = tcg_temp_new_i32();
19457615
FN
4343
4344 tcg_gen_shli_i32(rd, t0, 16);
4345 tcg_gen_andi_i32(tmp, t1, 0xffff);
4346 tcg_gen_or_i32(rd, rd, tmp);
4347 tcg_gen_shri_i32(t1, t1, 16);
4348 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4349 tcg_gen_or_i32(t1, t1, tmp);
4350 tcg_gen_mov_i32(t0, rd);
4351
7d1b0095
PM
4352 tcg_temp_free_i32(tmp);
4353 tcg_temp_free_i32(rd);
19457615
FN
4354}
4355
4356
9ee6e8bb
PB
4357static struct {
4358 int nregs;
4359 int interleave;
4360 int spacing;
4361} neon_ls_element_type[11] = {
4362 {4, 4, 1},
4363 {4, 4, 2},
4364 {4, 1, 1},
4365 {4, 2, 1},
4366 {3, 3, 1},
4367 {3, 3, 2},
4368 {3, 1, 1},
4369 {1, 1, 1},
4370 {2, 2, 1},
4371 {2, 2, 2},
4372 {2, 1, 1}
4373};
4374
4375/* Translate a NEON load/store element instruction. Return nonzero if the
4376 instruction is invalid. */
7dcc1f89 4377static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4378{
4379 int rd, rn, rm;
4380 int op;
4381 int nregs;
4382 int interleave;
84496233 4383 int spacing;
9ee6e8bb
PB
4384 int stride;
4385 int size;
4386 int reg;
4387 int pass;
4388 int load;
4389 int shift;
9ee6e8bb 4390 int n;
39d5492a
PM
4391 TCGv_i32 addr;
4392 TCGv_i32 tmp;
4393 TCGv_i32 tmp2;
84496233 4394 TCGv_i64 tmp64;
9ee6e8bb 4395
2c7ffc41
PM
4396 /* FIXME: this access check should not take precedence over UNDEF
4397 * for invalid encodings; we will generate incorrect syndrome information
4398 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4399 */
9dbbc748 4400 if (s->fp_excp_el) {
2c7ffc41 4401 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 4402 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4403 return 0;
4404 }
4405
5df8bac1 4406 if (!s->vfp_enabled)
9ee6e8bb
PB
4407 return 1;
4408 VFP_DREG_D(rd, insn);
4409 rn = (insn >> 16) & 0xf;
4410 rm = insn & 0xf;
4411 load = (insn & (1 << 21)) != 0;
4412 if ((insn & (1 << 23)) == 0) {
4413 /* Load store all elements. */
4414 op = (insn >> 8) & 0xf;
4415 size = (insn >> 6) & 3;
84496233 4416 if (op > 10)
9ee6e8bb 4417 return 1;
f2dd89d0
PM
4418 /* Catch UNDEF cases for bad values of align field */
4419 switch (op & 0xc) {
4420 case 4:
4421 if (((insn >> 5) & 1) == 1) {
4422 return 1;
4423 }
4424 break;
4425 case 8:
4426 if (((insn >> 4) & 3) == 3) {
4427 return 1;
4428 }
4429 break;
4430 default:
4431 break;
4432 }
9ee6e8bb
PB
4433 nregs = neon_ls_element_type[op].nregs;
4434 interleave = neon_ls_element_type[op].interleave;
84496233
JR
4435 spacing = neon_ls_element_type[op].spacing;
4436 if (size == 3 && (interleave | spacing) != 1)
4437 return 1;
e318a60b 4438 addr = tcg_temp_new_i32();
dcc65026 4439 load_reg_var(s, addr, rn);
9ee6e8bb
PB
4440 stride = (1 << size) * interleave;
4441 for (reg = 0; reg < nregs; reg++) {
4442 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
dcc65026
AJ
4443 load_reg_var(s, addr, rn);
4444 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
9ee6e8bb 4445 } else if (interleave == 2 && nregs == 4 && reg == 2) {
dcc65026
AJ
4446 load_reg_var(s, addr, rn);
4447 tcg_gen_addi_i32(addr, addr, 1 << size);
9ee6e8bb 4448 }
84496233 4449 if (size == 3) {
8ed1237d 4450 tmp64 = tcg_temp_new_i64();
84496233 4451 if (load) {
6ce2faf4 4452 gen_aa32_ld64(tmp64, addr, get_mem_index(s));
84496233 4453 neon_store_reg64(tmp64, rd);
84496233 4454 } else {
84496233 4455 neon_load_reg64(tmp64, rd);
6ce2faf4 4456 gen_aa32_st64(tmp64, addr, get_mem_index(s));
84496233 4457 }
8ed1237d 4458 tcg_temp_free_i64(tmp64);
84496233
JR
4459 tcg_gen_addi_i32(addr, addr, stride);
4460 } else {
4461 for (pass = 0; pass < 2; pass++) {
4462 if (size == 2) {
4463 if (load) {
58ab8e96 4464 tmp = tcg_temp_new_i32();
6ce2faf4 4465 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
84496233
JR
4466 neon_store_reg(rd, pass, tmp);
4467 } else {
4468 tmp = neon_load_reg(rd, pass);
6ce2faf4 4469 gen_aa32_st32(tmp, addr, get_mem_index(s));
58ab8e96 4470 tcg_temp_free_i32(tmp);
84496233 4471 }
1b2b1e54 4472 tcg_gen_addi_i32(addr, addr, stride);
84496233
JR
4473 } else if (size == 1) {
4474 if (load) {
58ab8e96 4475 tmp = tcg_temp_new_i32();
6ce2faf4 4476 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
84496233 4477 tcg_gen_addi_i32(addr, addr, stride);
58ab8e96 4478 tmp2 = tcg_temp_new_i32();
6ce2faf4 4479 gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
84496233 4480 tcg_gen_addi_i32(addr, addr, stride);
41ba8341
PB
4481 tcg_gen_shli_i32(tmp2, tmp2, 16);
4482 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 4483 tcg_temp_free_i32(tmp2);
84496233
JR
4484 neon_store_reg(rd, pass, tmp);
4485 } else {
4486 tmp = neon_load_reg(rd, pass);
7d1b0095 4487 tmp2 = tcg_temp_new_i32();
84496233 4488 tcg_gen_shri_i32(tmp2, tmp, 16);
6ce2faf4 4489 gen_aa32_st16(tmp, addr, get_mem_index(s));
58ab8e96 4490 tcg_temp_free_i32(tmp);
84496233 4491 tcg_gen_addi_i32(addr, addr, stride);
6ce2faf4 4492 gen_aa32_st16(tmp2, addr, get_mem_index(s));
58ab8e96 4493 tcg_temp_free_i32(tmp2);
1b2b1e54 4494 tcg_gen_addi_i32(addr, addr, stride);
9ee6e8bb 4495 }
84496233
JR
4496 } else /* size == 0 */ {
4497 if (load) {
39d5492a 4498 TCGV_UNUSED_I32(tmp2);
84496233 4499 for (n = 0; n < 4; n++) {
58ab8e96 4500 tmp = tcg_temp_new_i32();
6ce2faf4 4501 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
84496233
JR
4502 tcg_gen_addi_i32(addr, addr, stride);
4503 if (n == 0) {
4504 tmp2 = tmp;
4505 } else {
41ba8341
PB
4506 tcg_gen_shli_i32(tmp, tmp, n * 8);
4507 tcg_gen_or_i32(tmp2, tmp2, tmp);
7d1b0095 4508 tcg_temp_free_i32(tmp);
84496233 4509 }
9ee6e8bb 4510 }
84496233
JR
4511 neon_store_reg(rd, pass, tmp2);
4512 } else {
4513 tmp2 = neon_load_reg(rd, pass);
4514 for (n = 0; n < 4; n++) {
7d1b0095 4515 tmp = tcg_temp_new_i32();
84496233
JR
4516 if (n == 0) {
4517 tcg_gen_mov_i32(tmp, tmp2);
4518 } else {
4519 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4520 }
6ce2faf4 4521 gen_aa32_st8(tmp, addr, get_mem_index(s));
58ab8e96 4522 tcg_temp_free_i32(tmp);
84496233
JR
4523 tcg_gen_addi_i32(addr, addr, stride);
4524 }
7d1b0095 4525 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
4526 }
4527 }
4528 }
4529 }
84496233 4530 rd += spacing;
9ee6e8bb 4531 }
e318a60b 4532 tcg_temp_free_i32(addr);
9ee6e8bb
PB
4533 stride = nregs * 8;
4534 } else {
4535 size = (insn >> 10) & 3;
4536 if (size == 3) {
4537 /* Load single element to all lanes. */
8e18cde3
PM
4538 int a = (insn >> 4) & 1;
4539 if (!load) {
9ee6e8bb 4540 return 1;
8e18cde3 4541 }
9ee6e8bb
PB
4542 size = (insn >> 6) & 3;
4543 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
4544
4545 if (size == 3) {
4546 if (nregs != 4 || a == 0) {
9ee6e8bb 4547 return 1;
99c475ab 4548 }
8e18cde3
PM
4549 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4550 size = 2;
4551 }
4552 if (nregs == 1 && a == 1 && size == 0) {
4553 return 1;
4554 }
4555 if (nregs == 3 && a == 1) {
4556 return 1;
4557 }
e318a60b 4558 addr = tcg_temp_new_i32();
8e18cde3
PM
4559 load_reg_var(s, addr, rn);
4560 if (nregs == 1) {
4561 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4562 tmp = gen_load_and_replicate(s, addr, size);
4563 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4564 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4565 if (insn & (1 << 5)) {
4566 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4567 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4568 }
4569 tcg_temp_free_i32(tmp);
4570 } else {
4571 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4572 stride = (insn & (1 << 5)) ? 2 : 1;
4573 for (reg = 0; reg < nregs; reg++) {
4574 tmp = gen_load_and_replicate(s, addr, size);
4575 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4576 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4577 tcg_temp_free_i32(tmp);
4578 tcg_gen_addi_i32(addr, addr, 1 << size);
4579 rd += stride;
4580 }
9ee6e8bb 4581 }
e318a60b 4582 tcg_temp_free_i32(addr);
9ee6e8bb
PB
4583 stride = (1 << size) * nregs;
4584 } else {
4585 /* Single element. */
93262b16 4586 int idx = (insn >> 4) & 0xf;
9ee6e8bb
PB
4587 pass = (insn >> 7) & 1;
4588 switch (size) {
4589 case 0:
4590 shift = ((insn >> 5) & 3) * 8;
9ee6e8bb
PB
4591 stride = 1;
4592 break;
4593 case 1:
4594 shift = ((insn >> 6) & 1) * 16;
9ee6e8bb
PB
4595 stride = (insn & (1 << 5)) ? 2 : 1;
4596 break;
4597 case 2:
4598 shift = 0;
9ee6e8bb
PB
4599 stride = (insn & (1 << 6)) ? 2 : 1;
4600 break;
4601 default:
4602 abort();
4603 }
4604 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
4605 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4606 switch (nregs) {
4607 case 1:
4608 if (((idx & (1 << size)) != 0) ||
4609 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4610 return 1;
4611 }
4612 break;
4613 case 3:
4614 if ((idx & 1) != 0) {
4615 return 1;
4616 }
4617 /* fall through */
4618 case 2:
4619 if (size == 2 && (idx & 2) != 0) {
4620 return 1;
4621 }
4622 break;
4623 case 4:
4624 if ((size == 2) && ((idx & 3) == 3)) {
4625 return 1;
4626 }
4627 break;
4628 default:
4629 abort();
4630 }
4631 if ((rd + stride * (nregs - 1)) > 31) {
4632 /* Attempts to write off the end of the register file
4633 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4634 * the neon_load_reg() would write off the end of the array.
4635 */
4636 return 1;
4637 }
e318a60b 4638 addr = tcg_temp_new_i32();
dcc65026 4639 load_reg_var(s, addr, rn);
9ee6e8bb
PB
4640 for (reg = 0; reg < nregs; reg++) {
4641 if (load) {
58ab8e96 4642 tmp = tcg_temp_new_i32();
9ee6e8bb
PB
4643 switch (size) {
4644 case 0:
6ce2faf4 4645 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4646 break;
4647 case 1:
6ce2faf4 4648 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4649 break;
4650 case 2:
6ce2faf4 4651 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9ee6e8bb 4652 break;
a50f5b91
PB
4653 default: /* Avoid compiler warnings. */
4654 abort();
9ee6e8bb
PB
4655 }
4656 if (size != 2) {
8f8e3aa4 4657 tmp2 = neon_load_reg(rd, pass);
d593c48e
AJ
4658 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4659 shift, size ? 16 : 8);
7d1b0095 4660 tcg_temp_free_i32(tmp2);
9ee6e8bb 4661 }
8f8e3aa4 4662 neon_store_reg(rd, pass, tmp);
9ee6e8bb 4663 } else { /* Store */
8f8e3aa4
PB
4664 tmp = neon_load_reg(rd, pass);
4665 if (shift)
4666 tcg_gen_shri_i32(tmp, tmp, shift);
9ee6e8bb
PB
4667 switch (size) {
4668 case 0:
6ce2faf4 4669 gen_aa32_st8(tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4670 break;
4671 case 1:
6ce2faf4 4672 gen_aa32_st16(tmp, addr, get_mem_index(s));
9ee6e8bb
PB
4673 break;
4674 case 2:
6ce2faf4 4675 gen_aa32_st32(tmp, addr, get_mem_index(s));
9ee6e8bb 4676 break;
99c475ab 4677 }
58ab8e96 4678 tcg_temp_free_i32(tmp);
99c475ab 4679 }
9ee6e8bb 4680 rd += stride;
1b2b1e54 4681 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 4682 }
e318a60b 4683 tcg_temp_free_i32(addr);
9ee6e8bb 4684 stride = nregs * (1 << size);
99c475ab 4685 }
9ee6e8bb
PB
4686 }
4687 if (rm != 15) {
39d5492a 4688 TCGv_i32 base;
b26eefb6
PB
4689
4690 base = load_reg(s, rn);
9ee6e8bb 4691 if (rm == 13) {
b26eefb6 4692 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 4693 } else {
39d5492a 4694 TCGv_i32 index;
b26eefb6
PB
4695 index = load_reg(s, rm);
4696 tcg_gen_add_i32(base, base, index);
7d1b0095 4697 tcg_temp_free_i32(index);
9ee6e8bb 4698 }
b26eefb6 4699 store_reg(s, rn, base);
9ee6e8bb
PB
4700 }
4701 return 0;
4702}
3b46e624 4703
8f8e3aa4 4704/* Bitwise select. dest = c ? t : f. Clobbers T and F. */
39d5492a 4705static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
8f8e3aa4
PB
4706{
4707 tcg_gen_and_i32(t, t, c);
f669df27 4708 tcg_gen_andc_i32(f, f, c);
8f8e3aa4
PB
4709 tcg_gen_or_i32(dest, t, f);
4710}
4711
39d5492a 4712static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4713{
4714 switch (size) {
4715 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4716 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 4717 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
4718 default: abort();
4719 }
4720}
4721
39d5492a 4722static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4723{
4724 switch (size) {
02da0b2d
PM
4725 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4726 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4727 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
4728 default: abort();
4729 }
4730}
4731
39d5492a 4732static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
4733{
4734 switch (size) {
02da0b2d
PM
4735 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4736 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4737 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
4738 default: abort();
4739 }
4740}
4741
39d5492a 4742static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
4743{
4744 switch (size) {
02da0b2d
PM
4745 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4746 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4747 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
4748 default: abort();
4749 }
4750}
4751
39d5492a 4752static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
4753 int q, int u)
4754{
4755 if (q) {
4756 if (u) {
4757 switch (size) {
4758 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4759 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4760 default: abort();
4761 }
4762 } else {
4763 switch (size) {
4764 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4765 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4766 default: abort();
4767 }
4768 }
4769 } else {
4770 if (u) {
4771 switch (size) {
b408a9b0
CL
4772 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4773 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
4774 default: abort();
4775 }
4776 } else {
4777 switch (size) {
4778 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4779 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4780 default: abort();
4781 }
4782 }
4783 }
4784}
4785
39d5492a 4786static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
4787{
4788 if (u) {
4789 switch (size) {
4790 case 0: gen_helper_neon_widen_u8(dest, src); break;
4791 case 1: gen_helper_neon_widen_u16(dest, src); break;
4792 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4793 default: abort();
4794 }
4795 } else {
4796 switch (size) {
4797 case 0: gen_helper_neon_widen_s8(dest, src); break;
4798 case 1: gen_helper_neon_widen_s16(dest, src); break;
4799 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4800 default: abort();
4801 }
4802 }
7d1b0095 4803 tcg_temp_free_i32(src);
ad69471c
PB
4804}
4805
4806static inline void gen_neon_addl(int size)
4807{
4808 switch (size) {
4809 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4810 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4811 case 2: tcg_gen_add_i64(CPU_V001); break;
4812 default: abort();
4813 }
4814}
4815
4816static inline void gen_neon_subl(int size)
4817{
4818 switch (size) {
4819 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4820 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4821 case 2: tcg_gen_sub_i64(CPU_V001); break;
4822 default: abort();
4823 }
4824}
4825
a7812ae4 4826static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
4827{
4828 switch (size) {
4829 case 0: gen_helper_neon_negl_u16(var, var); break;
4830 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
4831 case 2:
4832 tcg_gen_neg_i64(var, var);
4833 break;
ad69471c
PB
4834 default: abort();
4835 }
4836}
4837
a7812ae4 4838static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
4839{
4840 switch (size) {
02da0b2d
PM
4841 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4842 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
4843 default: abort();
4844 }
4845}
4846
39d5492a
PM
4847static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4848 int size, int u)
ad69471c 4849{
a7812ae4 4850 TCGv_i64 tmp;
ad69471c
PB
4851
4852 switch ((size << 1) | u) {
4853 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4854 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4855 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4856 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4857 case 4:
4858 tmp = gen_muls_i64_i32(a, b);
4859 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 4860 tcg_temp_free_i64(tmp);
ad69471c
PB
4861 break;
4862 case 5:
4863 tmp = gen_mulu_i64_i32(a, b);
4864 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 4865 tcg_temp_free_i64(tmp);
ad69471c
PB
4866 break;
4867 default: abort();
4868 }
c6067f04
CL
4869
4870 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4871 Don't forget to clean them now. */
4872 if (size < 2) {
7d1b0095
PM
4873 tcg_temp_free_i32(a);
4874 tcg_temp_free_i32(b);
c6067f04 4875 }
ad69471c
PB
4876}
4877
39d5492a
PM
4878static void gen_neon_narrow_op(int op, int u, int size,
4879 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
4880{
4881 if (op) {
4882 if (u) {
4883 gen_neon_unarrow_sats(size, dest, src);
4884 } else {
4885 gen_neon_narrow(size, dest, src);
4886 }
4887 } else {
4888 if (u) {
4889 gen_neon_narrow_satu(size, dest, src);
4890 } else {
4891 gen_neon_narrow_sats(size, dest, src);
4892 }
4893 }
4894}
4895
62698be3
PM
4896/* Symbolic constants for op fields for Neon 3-register same-length.
4897 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4898 * table A7-9.
4899 */
4900#define NEON_3R_VHADD 0
4901#define NEON_3R_VQADD 1
4902#define NEON_3R_VRHADD 2
4903#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4904#define NEON_3R_VHSUB 4
4905#define NEON_3R_VQSUB 5
4906#define NEON_3R_VCGT 6
4907#define NEON_3R_VCGE 7
4908#define NEON_3R_VSHL 8
4909#define NEON_3R_VQSHL 9
4910#define NEON_3R_VRSHL 10
4911#define NEON_3R_VQRSHL 11
4912#define NEON_3R_VMAX 12
4913#define NEON_3R_VMIN 13
4914#define NEON_3R_VABD 14
4915#define NEON_3R_VABA 15
4916#define NEON_3R_VADD_VSUB 16
4917#define NEON_3R_VTST_VCEQ 17
4918#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4919#define NEON_3R_VMUL 19
4920#define NEON_3R_VPMAX 20
4921#define NEON_3R_VPMIN 21
4922#define NEON_3R_VQDMULH_VQRDMULH 22
4923#define NEON_3R_VPADD 23
f1ecb913 4924#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
da97f52c 4925#define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
62698be3
PM
4926#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4927#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4928#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4929#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4930#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 4931#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
4932
4933static const uint8_t neon_3r_sizes[] = {
4934 [NEON_3R_VHADD] = 0x7,
4935 [NEON_3R_VQADD] = 0xf,
4936 [NEON_3R_VRHADD] = 0x7,
4937 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4938 [NEON_3R_VHSUB] = 0x7,
4939 [NEON_3R_VQSUB] = 0xf,
4940 [NEON_3R_VCGT] = 0x7,
4941 [NEON_3R_VCGE] = 0x7,
4942 [NEON_3R_VSHL] = 0xf,
4943 [NEON_3R_VQSHL] = 0xf,
4944 [NEON_3R_VRSHL] = 0xf,
4945 [NEON_3R_VQRSHL] = 0xf,
4946 [NEON_3R_VMAX] = 0x7,
4947 [NEON_3R_VMIN] = 0x7,
4948 [NEON_3R_VABD] = 0x7,
4949 [NEON_3R_VABA] = 0x7,
4950 [NEON_3R_VADD_VSUB] = 0xf,
4951 [NEON_3R_VTST_VCEQ] = 0x7,
4952 [NEON_3R_VML] = 0x7,
4953 [NEON_3R_VMUL] = 0x7,
4954 [NEON_3R_VPMAX] = 0x7,
4955 [NEON_3R_VPMIN] = 0x7,
4956 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4957 [NEON_3R_VPADD] = 0x7,
f1ecb913 4958 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
da97f52c 4959 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
62698be3
PM
4960 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4961 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4962 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4963 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4964 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 4965 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
4966};
4967
600b828c
PM
4968/* Symbolic constants for op fields for Neon 2-register miscellaneous.
4969 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4970 * table A7-13.
4971 */
4972#define NEON_2RM_VREV64 0
4973#define NEON_2RM_VREV32 1
4974#define NEON_2RM_VREV16 2
4975#define NEON_2RM_VPADDL 4
4976#define NEON_2RM_VPADDL_U 5
9d935509
AB
4977#define NEON_2RM_AESE 6 /* Includes AESD */
4978#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
4979#define NEON_2RM_VCLS 8
4980#define NEON_2RM_VCLZ 9
4981#define NEON_2RM_VCNT 10
4982#define NEON_2RM_VMVN 11
4983#define NEON_2RM_VPADAL 12
4984#define NEON_2RM_VPADAL_U 13
4985#define NEON_2RM_VQABS 14
4986#define NEON_2RM_VQNEG 15
4987#define NEON_2RM_VCGT0 16
4988#define NEON_2RM_VCGE0 17
4989#define NEON_2RM_VCEQ0 18
4990#define NEON_2RM_VCLE0 19
4991#define NEON_2RM_VCLT0 20
f1ecb913 4992#define NEON_2RM_SHA1H 21
600b828c
PM
4993#define NEON_2RM_VABS 22
4994#define NEON_2RM_VNEG 23
4995#define NEON_2RM_VCGT0_F 24
4996#define NEON_2RM_VCGE0_F 25
4997#define NEON_2RM_VCEQ0_F 26
4998#define NEON_2RM_VCLE0_F 27
4999#define NEON_2RM_VCLT0_F 28
5000#define NEON_2RM_VABS_F 30
5001#define NEON_2RM_VNEG_F 31
5002#define NEON_2RM_VSWP 32
5003#define NEON_2RM_VTRN 33
5004#define NEON_2RM_VUZP 34
5005#define NEON_2RM_VZIP 35
5006#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5007#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5008#define NEON_2RM_VSHLL 38
f1ecb913 5009#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 5010#define NEON_2RM_VRINTN 40
2ce70625 5011#define NEON_2RM_VRINTX 41
34f7b0a2
WN
5012#define NEON_2RM_VRINTA 42
5013#define NEON_2RM_VRINTZ 43
600b828c 5014#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 5015#define NEON_2RM_VRINTM 45
600b828c 5016#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 5017#define NEON_2RM_VRINTP 47
901ad525
WN
5018#define NEON_2RM_VCVTAU 48
5019#define NEON_2RM_VCVTAS 49
5020#define NEON_2RM_VCVTNU 50
5021#define NEON_2RM_VCVTNS 51
5022#define NEON_2RM_VCVTPU 52
5023#define NEON_2RM_VCVTPS 53
5024#define NEON_2RM_VCVTMU 54
5025#define NEON_2RM_VCVTMS 55
600b828c
PM
5026#define NEON_2RM_VRECPE 56
5027#define NEON_2RM_VRSQRTE 57
5028#define NEON_2RM_VRECPE_F 58
5029#define NEON_2RM_VRSQRTE_F 59
5030#define NEON_2RM_VCVT_FS 60
5031#define NEON_2RM_VCVT_FU 61
5032#define NEON_2RM_VCVT_SF 62
5033#define NEON_2RM_VCVT_UF 63
5034
5035static int neon_2rm_is_float_op(int op)
5036{
5037 /* Return true if this neon 2reg-misc op is float-to-float */
5038 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
34f7b0a2 5039 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
901ad525
WN
5040 op == NEON_2RM_VRINTM ||
5041 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
34f7b0a2 5042 op >= NEON_2RM_VRECPE_F);
600b828c
PM
5043}
5044
5045/* Each entry in this array has bit n set if the insn allows
5046 * size value n (otherwise it will UNDEF). Since unallocated
5047 * op values will have no bits set they always UNDEF.
5048 */
5049static const uint8_t neon_2rm_sizes[] = {
5050 [NEON_2RM_VREV64] = 0x7,
5051 [NEON_2RM_VREV32] = 0x3,
5052 [NEON_2RM_VREV16] = 0x1,
5053 [NEON_2RM_VPADDL] = 0x7,
5054 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
5055 [NEON_2RM_AESE] = 0x1,
5056 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
5057 [NEON_2RM_VCLS] = 0x7,
5058 [NEON_2RM_VCLZ] = 0x7,
5059 [NEON_2RM_VCNT] = 0x1,
5060 [NEON_2RM_VMVN] = 0x1,
5061 [NEON_2RM_VPADAL] = 0x7,
5062 [NEON_2RM_VPADAL_U] = 0x7,
5063 [NEON_2RM_VQABS] = 0x7,
5064 [NEON_2RM_VQNEG] = 0x7,
5065 [NEON_2RM_VCGT0] = 0x7,
5066 [NEON_2RM_VCGE0] = 0x7,
5067 [NEON_2RM_VCEQ0] = 0x7,
5068 [NEON_2RM_VCLE0] = 0x7,
5069 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 5070 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
5071 [NEON_2RM_VABS] = 0x7,
5072 [NEON_2RM_VNEG] = 0x7,
5073 [NEON_2RM_VCGT0_F] = 0x4,
5074 [NEON_2RM_VCGE0_F] = 0x4,
5075 [NEON_2RM_VCEQ0_F] = 0x4,
5076 [NEON_2RM_VCLE0_F] = 0x4,
5077 [NEON_2RM_VCLT0_F] = 0x4,
5078 [NEON_2RM_VABS_F] = 0x4,
5079 [NEON_2RM_VNEG_F] = 0x4,
5080 [NEON_2RM_VSWP] = 0x1,
5081 [NEON_2RM_VTRN] = 0x7,
5082 [NEON_2RM_VUZP] = 0x7,
5083 [NEON_2RM_VZIP] = 0x7,
5084 [NEON_2RM_VMOVN] = 0x7,
5085 [NEON_2RM_VQMOVN] = 0x7,
5086 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 5087 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 5088 [NEON_2RM_VRINTN] = 0x4,
2ce70625 5089 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
5090 [NEON_2RM_VRINTA] = 0x4,
5091 [NEON_2RM_VRINTZ] = 0x4,
600b828c 5092 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 5093 [NEON_2RM_VRINTM] = 0x4,
600b828c 5094 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 5095 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
5096 [NEON_2RM_VCVTAU] = 0x4,
5097 [NEON_2RM_VCVTAS] = 0x4,
5098 [NEON_2RM_VCVTNU] = 0x4,
5099 [NEON_2RM_VCVTNS] = 0x4,
5100 [NEON_2RM_VCVTPU] = 0x4,
5101 [NEON_2RM_VCVTPS] = 0x4,
5102 [NEON_2RM_VCVTMU] = 0x4,
5103 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
5104 [NEON_2RM_VRECPE] = 0x4,
5105 [NEON_2RM_VRSQRTE] = 0x4,
5106 [NEON_2RM_VRECPE_F] = 0x4,
5107 [NEON_2RM_VRSQRTE_F] = 0x4,
5108 [NEON_2RM_VCVT_FS] = 0x4,
5109 [NEON_2RM_VCVT_FU] = 0x4,
5110 [NEON_2RM_VCVT_SF] = 0x4,
5111 [NEON_2RM_VCVT_UF] = 0x4,
5112};
5113
9ee6e8bb
PB
5114/* Translate a NEON data processing instruction. Return nonzero if the
5115 instruction is invalid.
ad69471c
PB
5116 We process data in a mixture of 32-bit and 64-bit chunks.
5117 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 5118
7dcc1f89 5119static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
5120{
5121 int op;
5122 int q;
5123 int rd, rn, rm;
5124 int size;
5125 int shift;
5126 int pass;
5127 int count;
5128 int pairwise;
5129 int u;
ca9a32e4 5130 uint32_t imm, mask;
39d5492a 5131 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
a7812ae4 5132 TCGv_i64 tmp64;
9ee6e8bb 5133
2c7ffc41
PM
5134 /* FIXME: this access check should not take precedence over UNDEF
5135 * for invalid encodings; we will generate incorrect syndrome information
5136 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5137 */
9dbbc748 5138 if (s->fp_excp_el) {
2c7ffc41 5139 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 5140 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
5141 return 0;
5142 }
5143
5df8bac1 5144 if (!s->vfp_enabled)
9ee6e8bb
PB
5145 return 1;
5146 q = (insn & (1 << 6)) != 0;
5147 u = (insn >> 24) & 1;
5148 VFP_DREG_D(rd, insn);
5149 VFP_DREG_N(rn, insn);
5150 VFP_DREG_M(rm, insn);
5151 size = (insn >> 20) & 3;
5152 if ((insn & (1 << 23)) == 0) {
5153 /* Three register same length. */
5154 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
5155 /* Catch invalid op and bad size combinations: UNDEF */
5156 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5157 return 1;
5158 }
25f84f79
PM
5159 /* All insns of this form UNDEF for either this condition or the
5160 * superset of cases "Q==1"; we catch the latter later.
5161 */
5162 if (q && ((rd | rn | rm) & 1)) {
5163 return 1;
5164 }
f1ecb913
AB
5165 /*
5166 * The SHA-1/SHA-256 3-register instructions require special treatment
5167 * here, as their size field is overloaded as an op type selector, and
5168 * they all consume their input in a single pass.
5169 */
5170 if (op == NEON_3R_SHA) {
5171 if (!q) {
5172 return 1;
5173 }
5174 if (!u) { /* SHA-1 */
d614a513 5175 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
5176 return 1;
5177 }
5178 tmp = tcg_const_i32(rd);
5179 tmp2 = tcg_const_i32(rn);
5180 tmp3 = tcg_const_i32(rm);
5181 tmp4 = tcg_const_i32(size);
5182 gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
5183 tcg_temp_free_i32(tmp4);
5184 } else { /* SHA-256 */
d614a513 5185 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
f1ecb913
AB
5186 return 1;
5187 }
5188 tmp = tcg_const_i32(rd);
5189 tmp2 = tcg_const_i32(rn);
5190 tmp3 = tcg_const_i32(rm);
5191 switch (size) {
5192 case 0:
5193 gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
5194 break;
5195 case 1:
5196 gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
5197 break;
5198 case 2:
5199 gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
5200 break;
5201 }
5202 }
5203 tcg_temp_free_i32(tmp);
5204 tcg_temp_free_i32(tmp2);
5205 tcg_temp_free_i32(tmp3);
5206 return 0;
5207 }
62698be3
PM
5208 if (size == 3 && op != NEON_3R_LOGIC) {
5209 /* 64-bit element instructions. */
9ee6e8bb 5210 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
5211 neon_load_reg64(cpu_V0, rn + pass);
5212 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 5213 switch (op) {
62698be3 5214 case NEON_3R_VQADD:
9ee6e8bb 5215 if (u) {
02da0b2d
PM
5216 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5217 cpu_V0, cpu_V1);
2c0262af 5218 } else {
02da0b2d
PM
5219 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5220 cpu_V0, cpu_V1);
2c0262af 5221 }
9ee6e8bb 5222 break;
62698be3 5223 case NEON_3R_VQSUB:
9ee6e8bb 5224 if (u) {
02da0b2d
PM
5225 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5226 cpu_V0, cpu_V1);
ad69471c 5227 } else {
02da0b2d
PM
5228 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5229 cpu_V0, cpu_V1);
ad69471c
PB
5230 }
5231 break;
62698be3 5232 case NEON_3R_VSHL:
ad69471c
PB
5233 if (u) {
5234 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5235 } else {
5236 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5237 }
5238 break;
62698be3 5239 case NEON_3R_VQSHL:
ad69471c 5240 if (u) {
02da0b2d
PM
5241 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5242 cpu_V1, cpu_V0);
ad69471c 5243 } else {
02da0b2d
PM
5244 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5245 cpu_V1, cpu_V0);
ad69471c
PB
5246 }
5247 break;
62698be3 5248 case NEON_3R_VRSHL:
ad69471c
PB
5249 if (u) {
5250 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 5251 } else {
ad69471c
PB
5252 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5253 }
5254 break;
62698be3 5255 case NEON_3R_VQRSHL:
ad69471c 5256 if (u) {
02da0b2d
PM
5257 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5258 cpu_V1, cpu_V0);
ad69471c 5259 } else {
02da0b2d
PM
5260 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5261 cpu_V1, cpu_V0);
1e8d4eec 5262 }
9ee6e8bb 5263 break;
62698be3 5264 case NEON_3R_VADD_VSUB:
9ee6e8bb 5265 if (u) {
ad69471c 5266 tcg_gen_sub_i64(CPU_V001);
9ee6e8bb 5267 } else {
ad69471c 5268 tcg_gen_add_i64(CPU_V001);
9ee6e8bb
PB
5269 }
5270 break;
5271 default:
5272 abort();
2c0262af 5273 }
ad69471c 5274 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 5275 }
9ee6e8bb 5276 return 0;
2c0262af 5277 }
25f84f79 5278 pairwise = 0;
9ee6e8bb 5279 switch (op) {
62698be3
PM
5280 case NEON_3R_VSHL:
5281 case NEON_3R_VQSHL:
5282 case NEON_3R_VRSHL:
5283 case NEON_3R_VQRSHL:
9ee6e8bb 5284 {
ad69471c
PB
5285 int rtmp;
5286 /* Shift instruction operands are reversed. */
5287 rtmp = rn;
9ee6e8bb 5288 rn = rm;
ad69471c 5289 rm = rtmp;
9ee6e8bb 5290 }
2c0262af 5291 break;
25f84f79
PM
5292 case NEON_3R_VPADD:
5293 if (u) {
5294 return 1;
5295 }
5296 /* Fall through */
62698be3
PM
5297 case NEON_3R_VPMAX:
5298 case NEON_3R_VPMIN:
9ee6e8bb 5299 pairwise = 1;
2c0262af 5300 break;
25f84f79
PM
5301 case NEON_3R_FLOAT_ARITH:
5302 pairwise = (u && size < 2); /* if VPADD (float) */
5303 break;
5304 case NEON_3R_FLOAT_MINMAX:
5305 pairwise = u; /* if VPMIN/VPMAX (float) */
5306 break;
5307 case NEON_3R_FLOAT_CMP:
5308 if (!u && size) {
5309 /* no encoding for U=0 C=1x */
5310 return 1;
5311 }
5312 break;
5313 case NEON_3R_FLOAT_ACMP:
5314 if (!u) {
5315 return 1;
5316 }
5317 break;
505935fc
WN
5318 case NEON_3R_FLOAT_MISC:
5319 /* VMAXNM/VMINNM in ARMv8 */
d614a513 5320 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
5321 return 1;
5322 }
2c0262af 5323 break;
25f84f79
PM
5324 case NEON_3R_VMUL:
5325 if (u && (size != 0)) {
5326 /* UNDEF on invalid size for polynomial subcase */
5327 return 1;
5328 }
2c0262af 5329 break;
da97f52c 5330 case NEON_3R_VFM:
d614a513 5331 if (!arm_dc_feature(s, ARM_FEATURE_VFP4) || u) {
da97f52c
PM
5332 return 1;
5333 }
5334 break;
9ee6e8bb 5335 default:
2c0262af 5336 break;
9ee6e8bb 5337 }
dd8fbd78 5338
25f84f79
PM
5339 if (pairwise && q) {
5340 /* All the pairwise insns UNDEF if Q is set */
5341 return 1;
5342 }
5343
9ee6e8bb
PB
5344 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5345
5346 if (pairwise) {
5347 /* Pairwise. */
a5a14945
JR
5348 if (pass < 1) {
5349 tmp = neon_load_reg(rn, 0);
5350 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 5351 } else {
a5a14945
JR
5352 tmp = neon_load_reg(rm, 0);
5353 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
5354 }
5355 } else {
5356 /* Elementwise. */
dd8fbd78
FN
5357 tmp = neon_load_reg(rn, pass);
5358 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
5359 }
5360 switch (op) {
62698be3 5361 case NEON_3R_VHADD:
9ee6e8bb
PB
5362 GEN_NEON_INTEGER_OP(hadd);
5363 break;
62698be3 5364 case NEON_3R_VQADD:
02da0b2d 5365 GEN_NEON_INTEGER_OP_ENV(qadd);
2c0262af 5366 break;
62698be3 5367 case NEON_3R_VRHADD:
9ee6e8bb 5368 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 5369 break;
62698be3 5370 case NEON_3R_LOGIC: /* Logic ops. */
9ee6e8bb
PB
5371 switch ((u << 2) | size) {
5372 case 0: /* VAND */
dd8fbd78 5373 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5374 break;
5375 case 1: /* BIC */
f669df27 5376 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5377 break;
5378 case 2: /* VORR */
dd8fbd78 5379 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5380 break;
5381 case 3: /* VORN */
f669df27 5382 tcg_gen_orc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5383 break;
5384 case 4: /* VEOR */
dd8fbd78 5385 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5386 break;
5387 case 5: /* VBSL */
dd8fbd78
FN
5388 tmp3 = neon_load_reg(rd, pass);
5389 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
7d1b0095 5390 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5391 break;
5392 case 6: /* VBIT */
dd8fbd78
FN
5393 tmp3 = neon_load_reg(rd, pass);
5394 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
7d1b0095 5395 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5396 break;
5397 case 7: /* VBIF */
dd8fbd78
FN
5398 tmp3 = neon_load_reg(rd, pass);
5399 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
7d1b0095 5400 tcg_temp_free_i32(tmp3);
9ee6e8bb 5401 break;
2c0262af
FB
5402 }
5403 break;
62698be3 5404 case NEON_3R_VHSUB:
9ee6e8bb
PB
5405 GEN_NEON_INTEGER_OP(hsub);
5406 break;
62698be3 5407 case NEON_3R_VQSUB:
02da0b2d 5408 GEN_NEON_INTEGER_OP_ENV(qsub);
2c0262af 5409 break;
62698be3 5410 case NEON_3R_VCGT:
9ee6e8bb
PB
5411 GEN_NEON_INTEGER_OP(cgt);
5412 break;
62698be3 5413 case NEON_3R_VCGE:
9ee6e8bb
PB
5414 GEN_NEON_INTEGER_OP(cge);
5415 break;
62698be3 5416 case NEON_3R_VSHL:
ad69471c 5417 GEN_NEON_INTEGER_OP(shl);
2c0262af 5418 break;
62698be3 5419 case NEON_3R_VQSHL:
02da0b2d 5420 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5421 break;
62698be3 5422 case NEON_3R_VRSHL:
ad69471c 5423 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5424 break;
62698be3 5425 case NEON_3R_VQRSHL:
02da0b2d 5426 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 5427 break;
62698be3 5428 case NEON_3R_VMAX:
9ee6e8bb
PB
5429 GEN_NEON_INTEGER_OP(max);
5430 break;
62698be3 5431 case NEON_3R_VMIN:
9ee6e8bb
PB
5432 GEN_NEON_INTEGER_OP(min);
5433 break;
62698be3 5434 case NEON_3R_VABD:
9ee6e8bb
PB
5435 GEN_NEON_INTEGER_OP(abd);
5436 break;
62698be3 5437 case NEON_3R_VABA:
9ee6e8bb 5438 GEN_NEON_INTEGER_OP(abd);
7d1b0095 5439 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
5440 tmp2 = neon_load_reg(rd, pass);
5441 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 5442 break;
62698be3 5443 case NEON_3R_VADD_VSUB:
9ee6e8bb 5444 if (!u) { /* VADD */
62698be3 5445 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
5446 } else { /* VSUB */
5447 switch (size) {
dd8fbd78
FN
5448 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5449 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5450 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
62698be3 5451 default: abort();
9ee6e8bb
PB
5452 }
5453 }
5454 break;
62698be3 5455 case NEON_3R_VTST_VCEQ:
9ee6e8bb
PB
5456 if (!u) { /* VTST */
5457 switch (size) {
dd8fbd78
FN
5458 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5459 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5460 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
62698be3 5461 default: abort();
9ee6e8bb
PB
5462 }
5463 } else { /* VCEQ */
5464 switch (size) {
dd8fbd78
FN
5465 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5466 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5467 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
62698be3 5468 default: abort();
9ee6e8bb
PB
5469 }
5470 }
5471 break;
62698be3 5472 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
9ee6e8bb 5473 switch (size) {
dd8fbd78
FN
5474 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5475 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5476 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 5477 default: abort();
9ee6e8bb 5478 }
7d1b0095 5479 tcg_temp_free_i32(tmp2);
dd8fbd78 5480 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5481 if (u) { /* VMLS */
dd8fbd78 5482 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb 5483 } else { /* VMLA */
dd8fbd78 5484 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
5485 }
5486 break;
62698be3 5487 case NEON_3R_VMUL:
9ee6e8bb 5488 if (u) { /* polynomial */
dd8fbd78 5489 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb
PB
5490 } else { /* Integer */
5491 switch (size) {
dd8fbd78
FN
5492 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5493 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5494 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 5495 default: abort();
9ee6e8bb
PB
5496 }
5497 }
5498 break;
62698be3 5499 case NEON_3R_VPMAX:
9ee6e8bb
PB
5500 GEN_NEON_INTEGER_OP(pmax);
5501 break;
62698be3 5502 case NEON_3R_VPMIN:
9ee6e8bb
PB
5503 GEN_NEON_INTEGER_OP(pmin);
5504 break;
62698be3 5505 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
5506 if (!u) { /* VQDMULH */
5507 switch (size) {
02da0b2d
PM
5508 case 1:
5509 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5510 break;
5511 case 2:
5512 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5513 break;
62698be3 5514 default: abort();
9ee6e8bb 5515 }
62698be3 5516 } else { /* VQRDMULH */
9ee6e8bb 5517 switch (size) {
02da0b2d
PM
5518 case 1:
5519 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5520 break;
5521 case 2:
5522 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5523 break;
62698be3 5524 default: abort();
9ee6e8bb
PB
5525 }
5526 }
5527 break;
62698be3 5528 case NEON_3R_VPADD:
9ee6e8bb 5529 switch (size) {
dd8fbd78
FN
5530 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5531 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5532 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 5533 default: abort();
9ee6e8bb
PB
5534 }
5535 break;
62698be3 5536 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
5537 {
5538 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
5539 switch ((u << 2) | size) {
5540 case 0: /* VADD */
aa47cfdd
PM
5541 case 4: /* VPADD */
5542 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5543 break;
5544 case 2: /* VSUB */
aa47cfdd 5545 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5546 break;
5547 case 6: /* VABD */
aa47cfdd 5548 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5549 break;
5550 default:
62698be3 5551 abort();
9ee6e8bb 5552 }
aa47cfdd 5553 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5554 break;
aa47cfdd 5555 }
62698be3 5556 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
5557 {
5558 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5559 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5560 if (!u) {
7d1b0095 5561 tcg_temp_free_i32(tmp2);
dd8fbd78 5562 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5563 if (size == 0) {
aa47cfdd 5564 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5565 } else {
aa47cfdd 5566 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
5567 }
5568 }
aa47cfdd 5569 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5570 break;
aa47cfdd 5571 }
62698be3 5572 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
5573 {
5574 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 5575 if (!u) {
aa47cfdd 5576 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 5577 } else {
aa47cfdd
PM
5578 if (size == 0) {
5579 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5580 } else {
5581 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5582 }
b5ff1b31 5583 }
aa47cfdd 5584 tcg_temp_free_ptr(fpstatus);
2c0262af 5585 break;
aa47cfdd 5586 }
62698be3 5587 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
5588 {
5589 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5590 if (size == 0) {
5591 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5592 } else {
5593 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5594 }
5595 tcg_temp_free_ptr(fpstatus);
2c0262af 5596 break;
aa47cfdd 5597 }
62698be3 5598 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
5599 {
5600 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5601 if (size == 0) {
f71a2ae5 5602 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 5603 } else {
f71a2ae5 5604 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
5605 }
5606 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5607 break;
aa47cfdd 5608 }
505935fc
WN
5609 case NEON_3R_FLOAT_MISC:
5610 if (u) {
5611 /* VMAXNM/VMINNM */
5612 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5613 if (size == 0) {
f71a2ae5 5614 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 5615 } else {
f71a2ae5 5616 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
5617 }
5618 tcg_temp_free_ptr(fpstatus);
5619 } else {
5620 if (size == 0) {
5621 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5622 } else {
5623 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5624 }
5625 }
2c0262af 5626 break;
da97f52c
PM
5627 case NEON_3R_VFM:
5628 {
5629 /* VFMA, VFMS: fused multiply-add */
5630 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5631 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5632 if (size) {
5633 /* VFMS */
5634 gen_helper_vfp_negs(tmp, tmp);
5635 }
5636 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5637 tcg_temp_free_i32(tmp3);
5638 tcg_temp_free_ptr(fpstatus);
5639 break;
5640 }
9ee6e8bb
PB
5641 default:
5642 abort();
2c0262af 5643 }
7d1b0095 5644 tcg_temp_free_i32(tmp2);
dd8fbd78 5645
9ee6e8bb
PB
5646 /* Save the result. For elementwise operations we can put it
5647 straight into the destination register. For pairwise operations
5648 we have to be careful to avoid clobbering the source operands. */
5649 if (pairwise && rd == rm) {
dd8fbd78 5650 neon_store_scratch(pass, tmp);
9ee6e8bb 5651 } else {
dd8fbd78 5652 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5653 }
5654
5655 } /* for pass */
5656 if (pairwise && rd == rm) {
5657 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
5658 tmp = neon_load_scratch(pass);
5659 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5660 }
5661 }
ad69471c 5662 /* End of 3 register same size operations. */
9ee6e8bb
PB
5663 } else if (insn & (1 << 4)) {
5664 if ((insn & 0x00380080) != 0) {
5665 /* Two registers and shift. */
5666 op = (insn >> 8) & 0xf;
5667 if (insn & (1 << 7)) {
cc13115b
PM
5668 /* 64-bit shift. */
5669 if (op > 7) {
5670 return 1;
5671 }
9ee6e8bb
PB
5672 size = 3;
5673 } else {
5674 size = 2;
5675 while ((insn & (1 << (size + 19))) == 0)
5676 size--;
5677 }
5678 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
b90372ad 5679 /* To avoid excessive duplication of ops we implement shift
9ee6e8bb
PB
5680 by immediate using the variable shift operations. */
5681 if (op < 8) {
5682 /* Shift by immediate:
5683 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
5684 if (q && ((rd | rm) & 1)) {
5685 return 1;
5686 }
5687 if (!u && (op == 4 || op == 6)) {
5688 return 1;
5689 }
9ee6e8bb
PB
5690 /* Right shifts are encoded as N - shift, where N is the
5691 element size in bits. */
5692 if (op <= 4)
5693 shift = shift - (1 << (size + 3));
9ee6e8bb
PB
5694 if (size == 3) {
5695 count = q + 1;
5696 } else {
5697 count = q ? 4: 2;
5698 }
5699 switch (size) {
5700 case 0:
5701 imm = (uint8_t) shift;
5702 imm |= imm << 8;
5703 imm |= imm << 16;
5704 break;
5705 case 1:
5706 imm = (uint16_t) shift;
5707 imm |= imm << 16;
5708 break;
5709 case 2:
5710 case 3:
5711 imm = shift;
5712 break;
5713 default:
5714 abort();
5715 }
5716
5717 for (pass = 0; pass < count; pass++) {
ad69471c
PB
5718 if (size == 3) {
5719 neon_load_reg64(cpu_V0, rm + pass);
5720 tcg_gen_movi_i64(cpu_V1, imm);
5721 switch (op) {
5722 case 0: /* VSHR */
5723 case 1: /* VSRA */
5724 if (u)
5725 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5726 else
ad69471c 5727 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5728 break;
ad69471c
PB
5729 case 2: /* VRSHR */
5730 case 3: /* VRSRA */
5731 if (u)
5732 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5733 else
ad69471c 5734 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5735 break;
ad69471c 5736 case 4: /* VSRI */
ad69471c
PB
5737 case 5: /* VSHL, VSLI */
5738 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5739 break;
0322b26e 5740 case 6: /* VQSHLU */
02da0b2d
PM
5741 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5742 cpu_V0, cpu_V1);
ad69471c 5743 break;
0322b26e
PM
5744 case 7: /* VQSHL */
5745 if (u) {
02da0b2d 5746 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
5747 cpu_V0, cpu_V1);
5748 } else {
02da0b2d 5749 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
5750 cpu_V0, cpu_V1);
5751 }
9ee6e8bb 5752 break;
9ee6e8bb 5753 }
ad69471c
PB
5754 if (op == 1 || op == 3) {
5755 /* Accumulate. */
5371cb81 5756 neon_load_reg64(cpu_V1, rd + pass);
ad69471c
PB
5757 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5758 } else if (op == 4 || (op == 5 && u)) {
5759 /* Insert */
923e6509
CL
5760 neon_load_reg64(cpu_V1, rd + pass);
5761 uint64_t mask;
5762 if (shift < -63 || shift > 63) {
5763 mask = 0;
5764 } else {
5765 if (op == 4) {
5766 mask = 0xffffffffffffffffull >> -shift;
5767 } else {
5768 mask = 0xffffffffffffffffull << shift;
5769 }
5770 }
5771 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5772 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
5773 }
5774 neon_store_reg64(cpu_V0, rd + pass);
5775 } else { /* size < 3 */
5776 /* Operands in T0 and T1. */
dd8fbd78 5777 tmp = neon_load_reg(rm, pass);
7d1b0095 5778 tmp2 = tcg_temp_new_i32();
dd8fbd78 5779 tcg_gen_movi_i32(tmp2, imm);
ad69471c
PB
5780 switch (op) {
5781 case 0: /* VSHR */
5782 case 1: /* VSRA */
5783 GEN_NEON_INTEGER_OP(shl);
5784 break;
5785 case 2: /* VRSHR */
5786 case 3: /* VRSRA */
5787 GEN_NEON_INTEGER_OP(rshl);
5788 break;
5789 case 4: /* VSRI */
ad69471c
PB
5790 case 5: /* VSHL, VSLI */
5791 switch (size) {
dd8fbd78
FN
5792 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5793 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5794 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
cc13115b 5795 default: abort();
ad69471c
PB
5796 }
5797 break;
0322b26e 5798 case 6: /* VQSHLU */
ad69471c 5799 switch (size) {
0322b26e 5800 case 0:
02da0b2d
PM
5801 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5802 tmp, tmp2);
0322b26e
PM
5803 break;
5804 case 1:
02da0b2d
PM
5805 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5806 tmp, tmp2);
0322b26e
PM
5807 break;
5808 case 2:
02da0b2d
PM
5809 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5810 tmp, tmp2);
0322b26e
PM
5811 break;
5812 default:
cc13115b 5813 abort();
ad69471c
PB
5814 }
5815 break;
0322b26e 5816 case 7: /* VQSHL */
02da0b2d 5817 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 5818 break;
ad69471c 5819 }
7d1b0095 5820 tcg_temp_free_i32(tmp2);
ad69471c
PB
5821
5822 if (op == 1 || op == 3) {
5823 /* Accumulate. */
dd8fbd78 5824 tmp2 = neon_load_reg(rd, pass);
5371cb81 5825 gen_neon_add(size, tmp, tmp2);
7d1b0095 5826 tcg_temp_free_i32(tmp2);
ad69471c
PB
5827 } else if (op == 4 || (op == 5 && u)) {
5828 /* Insert */
5829 switch (size) {
5830 case 0:
5831 if (op == 4)
ca9a32e4 5832 mask = 0xff >> -shift;
ad69471c 5833 else
ca9a32e4
JR
5834 mask = (uint8_t)(0xff << shift);
5835 mask |= mask << 8;
5836 mask |= mask << 16;
ad69471c
PB
5837 break;
5838 case 1:
5839 if (op == 4)
ca9a32e4 5840 mask = 0xffff >> -shift;
ad69471c 5841 else
ca9a32e4
JR
5842 mask = (uint16_t)(0xffff << shift);
5843 mask |= mask << 16;
ad69471c
PB
5844 break;
5845 case 2:
ca9a32e4
JR
5846 if (shift < -31 || shift > 31) {
5847 mask = 0;
5848 } else {
5849 if (op == 4)
5850 mask = 0xffffffffu >> -shift;
5851 else
5852 mask = 0xffffffffu << shift;
5853 }
ad69471c
PB
5854 break;
5855 default:
5856 abort();
5857 }
dd8fbd78 5858 tmp2 = neon_load_reg(rd, pass);
ca9a32e4
JR
5859 tcg_gen_andi_i32(tmp, tmp, mask);
5860 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
dd8fbd78 5861 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 5862 tcg_temp_free_i32(tmp2);
ad69471c 5863 }
dd8fbd78 5864 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5865 }
5866 } /* for pass */
5867 } else if (op < 10) {
ad69471c 5868 /* Shift by immediate and narrow:
9ee6e8bb 5869 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 5870 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
5871 if (rm & 1) {
5872 return 1;
5873 }
9ee6e8bb
PB
5874 shift = shift - (1 << (size + 3));
5875 size++;
92cdfaeb 5876 if (size == 3) {
a7812ae4 5877 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
5878 neon_load_reg64(cpu_V0, rm);
5879 neon_load_reg64(cpu_V1, rm + 1);
5880 for (pass = 0; pass < 2; pass++) {
5881 TCGv_i64 in;
5882 if (pass == 0) {
5883 in = cpu_V0;
5884 } else {
5885 in = cpu_V1;
5886 }
ad69471c 5887 if (q) {
0b36f4cd 5888 if (input_unsigned) {
92cdfaeb 5889 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 5890 } else {
92cdfaeb 5891 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 5892 }
ad69471c 5893 } else {
0b36f4cd 5894 if (input_unsigned) {
92cdfaeb 5895 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 5896 } else {
92cdfaeb 5897 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 5898 }
ad69471c 5899 }
7d1b0095 5900 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5901 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5902 neon_store_reg(rd, pass, tmp);
5903 } /* for pass */
5904 tcg_temp_free_i64(tmp64);
5905 } else {
5906 if (size == 1) {
5907 imm = (uint16_t)shift;
5908 imm |= imm << 16;
2c0262af 5909 } else {
92cdfaeb
PM
5910 /* size == 2 */
5911 imm = (uint32_t)shift;
5912 }
5913 tmp2 = tcg_const_i32(imm);
5914 tmp4 = neon_load_reg(rm + 1, 0);
5915 tmp5 = neon_load_reg(rm + 1, 1);
5916 for (pass = 0; pass < 2; pass++) {
5917 if (pass == 0) {
5918 tmp = neon_load_reg(rm, 0);
5919 } else {
5920 tmp = tmp4;
5921 }
0b36f4cd
CL
5922 gen_neon_shift_narrow(size, tmp, tmp2, q,
5923 input_unsigned);
92cdfaeb
PM
5924 if (pass == 0) {
5925 tmp3 = neon_load_reg(rm, 1);
5926 } else {
5927 tmp3 = tmp5;
5928 }
0b36f4cd
CL
5929 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5930 input_unsigned);
36aa55dc 5931 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
5932 tcg_temp_free_i32(tmp);
5933 tcg_temp_free_i32(tmp3);
5934 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5935 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5936 neon_store_reg(rd, pass, tmp);
5937 } /* for pass */
c6067f04 5938 tcg_temp_free_i32(tmp2);
b75263d6 5939 }
9ee6e8bb 5940 } else if (op == 10) {
cc13115b
PM
5941 /* VSHLL, VMOVL */
5942 if (q || (rd & 1)) {
9ee6e8bb 5943 return 1;
cc13115b 5944 }
ad69471c
PB
5945 tmp = neon_load_reg(rm, 0);
5946 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 5947 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5948 if (pass == 1)
5949 tmp = tmp2;
5950
5951 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 5952
9ee6e8bb
PB
5953 if (shift != 0) {
5954 /* The shift is less than the width of the source
ad69471c
PB
5955 type, so we can just shift the whole register. */
5956 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
5957 /* Widen the result of shift: we need to clear
5958 * the potential overflow bits resulting from
5959 * left bits of the narrow input appearing as
5960 * right bits of left the neighbour narrow
5961 * input. */
ad69471c
PB
5962 if (size < 2 || !u) {
5963 uint64_t imm64;
5964 if (size == 0) {
5965 imm = (0xffu >> (8 - shift));
5966 imm |= imm << 16;
acdf01ef 5967 } else if (size == 1) {
ad69471c 5968 imm = 0xffff >> (16 - shift);
acdf01ef
CL
5969 } else {
5970 /* size == 2 */
5971 imm = 0xffffffff >> (32 - shift);
5972 }
5973 if (size < 2) {
5974 imm64 = imm | (((uint64_t)imm) << 32);
5975 } else {
5976 imm64 = imm;
9ee6e8bb 5977 }
acdf01ef 5978 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
5979 }
5980 }
ad69471c 5981 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 5982 }
f73534a5 5983 } else if (op >= 14) {
9ee6e8bb 5984 /* VCVT fixed-point. */
cc13115b
PM
5985 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5986 return 1;
5987 }
f73534a5
PM
5988 /* We have already masked out the must-be-1 top bit of imm6,
5989 * hence this 32-shift where the ARM ARM has 64-imm6.
5990 */
5991 shift = 32 - shift;
9ee6e8bb 5992 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373f3ce 5993 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
f73534a5 5994 if (!(op & 1)) {
9ee6e8bb 5995 if (u)
5500b06c 5996 gen_vfp_ulto(0, shift, 1);
9ee6e8bb 5997 else
5500b06c 5998 gen_vfp_slto(0, shift, 1);
9ee6e8bb
PB
5999 } else {
6000 if (u)
5500b06c 6001 gen_vfp_toul(0, shift, 1);
9ee6e8bb 6002 else
5500b06c 6003 gen_vfp_tosl(0, shift, 1);
2c0262af 6004 }
4373f3ce 6005 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
2c0262af
FB
6006 }
6007 } else {
9ee6e8bb
PB
6008 return 1;
6009 }
6010 } else { /* (insn & 0x00380080) == 0 */
6011 int invert;
7d80fee5
PM
6012 if (q && (rd & 1)) {
6013 return 1;
6014 }
9ee6e8bb
PB
6015
6016 op = (insn >> 8) & 0xf;
6017 /* One register and immediate. */
6018 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6019 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
6020 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
6021 * We choose to not special-case this and will behave as if a
6022 * valid constant encoding of 0 had been given.
6023 */
9ee6e8bb
PB
6024 switch (op) {
6025 case 0: case 1:
6026 /* no-op */
6027 break;
6028 case 2: case 3:
6029 imm <<= 8;
6030 break;
6031 case 4: case 5:
6032 imm <<= 16;
6033 break;
6034 case 6: case 7:
6035 imm <<= 24;
6036 break;
6037 case 8: case 9:
6038 imm |= imm << 16;
6039 break;
6040 case 10: case 11:
6041 imm = (imm << 8) | (imm << 24);
6042 break;
6043 case 12:
8e31209e 6044 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
6045 break;
6046 case 13:
6047 imm = (imm << 16) | 0xffff;
6048 break;
6049 case 14:
6050 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6051 if (invert)
6052 imm = ~imm;
6053 break;
6054 case 15:
7d80fee5
PM
6055 if (invert) {
6056 return 1;
6057 }
9ee6e8bb
PB
6058 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6059 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6060 break;
6061 }
6062 if (invert)
6063 imm = ~imm;
6064
9ee6e8bb
PB
6065 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6066 if (op & 1 && op < 12) {
ad69471c 6067 tmp = neon_load_reg(rd, pass);
9ee6e8bb
PB
6068 if (invert) {
6069 /* The immediate value has already been inverted, so
6070 BIC becomes AND. */
ad69471c 6071 tcg_gen_andi_i32(tmp, tmp, imm);
9ee6e8bb 6072 } else {
ad69471c 6073 tcg_gen_ori_i32(tmp, tmp, imm);
9ee6e8bb 6074 }
9ee6e8bb 6075 } else {
ad69471c 6076 /* VMOV, VMVN. */
7d1b0095 6077 tmp = tcg_temp_new_i32();
9ee6e8bb 6078 if (op == 14 && invert) {
a5a14945 6079 int n;
ad69471c
PB
6080 uint32_t val;
6081 val = 0;
9ee6e8bb
PB
6082 for (n = 0; n < 4; n++) {
6083 if (imm & (1 << (n + (pass & 1) * 4)))
ad69471c 6084 val |= 0xff << (n * 8);
9ee6e8bb 6085 }
ad69471c
PB
6086 tcg_gen_movi_i32(tmp, val);
6087 } else {
6088 tcg_gen_movi_i32(tmp, imm);
9ee6e8bb 6089 }
9ee6e8bb 6090 }
ad69471c 6091 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6092 }
6093 }
e4b3861d 6094 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
6095 if (size != 3) {
6096 op = (insn >> 8) & 0xf;
6097 if ((insn & (1 << 6)) == 0) {
6098 /* Three registers of different lengths. */
6099 int src1_wide;
6100 int src2_wide;
6101 int prewiden;
526d0096
PM
6102 /* undefreq: bit 0 : UNDEF if size == 0
6103 * bit 1 : UNDEF if size == 1
6104 * bit 2 : UNDEF if size == 2
6105 * bit 3 : UNDEF if U == 1
6106 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
6107 */
6108 int undefreq;
6109 /* prewiden, src1_wide, src2_wide, undefreq */
6110 static const int neon_3reg_wide[16][4] = {
6111 {1, 0, 0, 0}, /* VADDL */
6112 {1, 1, 0, 0}, /* VADDW */
6113 {1, 0, 0, 0}, /* VSUBL */
6114 {1, 1, 0, 0}, /* VSUBW */
6115 {0, 1, 1, 0}, /* VADDHN */
6116 {0, 0, 0, 0}, /* VABAL */
6117 {0, 1, 1, 0}, /* VSUBHN */
6118 {0, 0, 0, 0}, /* VABDL */
6119 {0, 0, 0, 0}, /* VMLAL */
526d0096 6120 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 6121 {0, 0, 0, 0}, /* VMLSL */
526d0096 6122 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 6123 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 6124 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 6125 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 6126 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
6127 };
6128
6129 prewiden = neon_3reg_wide[op][0];
6130 src1_wide = neon_3reg_wide[op][1];
6131 src2_wide = neon_3reg_wide[op][2];
695272dc 6132 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 6133
526d0096
PM
6134 if ((undefreq & (1 << size)) ||
6135 ((undefreq & 8) && u)) {
695272dc
PM
6136 return 1;
6137 }
6138 if ((src1_wide && (rn & 1)) ||
6139 (src2_wide && (rm & 1)) ||
6140 (!src2_wide && (rd & 1))) {
ad69471c 6141 return 1;
695272dc 6142 }
ad69471c 6143
4e624eda
PM
6144 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6145 * outside the loop below as it only performs a single pass.
6146 */
6147 if (op == 14 && size == 2) {
6148 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6149
d614a513 6150 if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
4e624eda
PM
6151 return 1;
6152 }
6153 tcg_rn = tcg_temp_new_i64();
6154 tcg_rm = tcg_temp_new_i64();
6155 tcg_rd = tcg_temp_new_i64();
6156 neon_load_reg64(tcg_rn, rn);
6157 neon_load_reg64(tcg_rm, rm);
6158 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6159 neon_store_reg64(tcg_rd, rd);
6160 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6161 neon_store_reg64(tcg_rd, rd + 1);
6162 tcg_temp_free_i64(tcg_rn);
6163 tcg_temp_free_i64(tcg_rm);
6164 tcg_temp_free_i64(tcg_rd);
6165 return 0;
6166 }
6167
9ee6e8bb
PB
6168 /* Avoid overlapping operands. Wide source operands are
6169 always aligned so will never overlap with wide
6170 destinations in problematic ways. */
8f8e3aa4 6171 if (rd == rm && !src2_wide) {
dd8fbd78
FN
6172 tmp = neon_load_reg(rm, 1);
6173 neon_store_scratch(2, tmp);
8f8e3aa4 6174 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
6175 tmp = neon_load_reg(rn, 1);
6176 neon_store_scratch(2, tmp);
9ee6e8bb 6177 }
39d5492a 6178 TCGV_UNUSED_I32(tmp3);
9ee6e8bb 6179 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6180 if (src1_wide) {
6181 neon_load_reg64(cpu_V0, rn + pass);
39d5492a 6182 TCGV_UNUSED_I32(tmp);
9ee6e8bb 6183 } else {
ad69471c 6184 if (pass == 1 && rd == rn) {
dd8fbd78 6185 tmp = neon_load_scratch(2);
9ee6e8bb 6186 } else {
ad69471c
PB
6187 tmp = neon_load_reg(rn, pass);
6188 }
6189 if (prewiden) {
6190 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
6191 }
6192 }
ad69471c
PB
6193 if (src2_wide) {
6194 neon_load_reg64(cpu_V1, rm + pass);
39d5492a 6195 TCGV_UNUSED_I32(tmp2);
9ee6e8bb 6196 } else {
ad69471c 6197 if (pass == 1 && rd == rm) {
dd8fbd78 6198 tmp2 = neon_load_scratch(2);
9ee6e8bb 6199 } else {
ad69471c
PB
6200 tmp2 = neon_load_reg(rm, pass);
6201 }
6202 if (prewiden) {
6203 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 6204 }
9ee6e8bb
PB
6205 }
6206 switch (op) {
6207 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 6208 gen_neon_addl(size);
9ee6e8bb 6209 break;
79b0e534 6210 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 6211 gen_neon_subl(size);
9ee6e8bb
PB
6212 break;
6213 case 5: case 7: /* VABAL, VABDL */
6214 switch ((size << 1) | u) {
ad69471c
PB
6215 case 0:
6216 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6217 break;
6218 case 1:
6219 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6220 break;
6221 case 2:
6222 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6223 break;
6224 case 3:
6225 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6226 break;
6227 case 4:
6228 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6229 break;
6230 case 5:
6231 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6232 break;
9ee6e8bb
PB
6233 default: abort();
6234 }
7d1b0095
PM
6235 tcg_temp_free_i32(tmp2);
6236 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6237 break;
6238 case 8: case 9: case 10: case 11: case 12: case 13:
6239 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 6240 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
6241 break;
6242 case 14: /* Polynomial VMULL */
e5ca24cb 6243 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
6244 tcg_temp_free_i32(tmp2);
6245 tcg_temp_free_i32(tmp);
e5ca24cb 6246 break;
695272dc
PM
6247 default: /* 15 is RESERVED: caught earlier */
6248 abort();
9ee6e8bb 6249 }
ebcd88ce
PM
6250 if (op == 13) {
6251 /* VQDMULL */
6252 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6253 neon_store_reg64(cpu_V0, rd + pass);
6254 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 6255 /* Accumulate. */
ebcd88ce 6256 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6257 switch (op) {
4dc064e6
PM
6258 case 10: /* VMLSL */
6259 gen_neon_negl(cpu_V0, size);
6260 /* Fall through */
6261 case 5: case 8: /* VABAL, VMLAL */
ad69471c 6262 gen_neon_addl(size);
9ee6e8bb
PB
6263 break;
6264 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 6265 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6266 if (op == 11) {
6267 gen_neon_negl(cpu_V0, size);
6268 }
ad69471c
PB
6269 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6270 break;
9ee6e8bb
PB
6271 default:
6272 abort();
6273 }
ad69471c 6274 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6275 } else if (op == 4 || op == 6) {
6276 /* Narrowing operation. */
7d1b0095 6277 tmp = tcg_temp_new_i32();
79b0e534 6278 if (!u) {
9ee6e8bb 6279 switch (size) {
ad69471c
PB
6280 case 0:
6281 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6282 break;
6283 case 1:
6284 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6285 break;
6286 case 2:
6287 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6288 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6289 break;
9ee6e8bb
PB
6290 default: abort();
6291 }
6292 } else {
6293 switch (size) {
ad69471c
PB
6294 case 0:
6295 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6296 break;
6297 case 1:
6298 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6299 break;
6300 case 2:
6301 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6302 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6303 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6304 break;
9ee6e8bb
PB
6305 default: abort();
6306 }
6307 }
ad69471c
PB
6308 if (pass == 0) {
6309 tmp3 = tmp;
6310 } else {
6311 neon_store_reg(rd, 0, tmp3);
6312 neon_store_reg(rd, 1, tmp);
6313 }
9ee6e8bb
PB
6314 } else {
6315 /* Write back the result. */
ad69471c 6316 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6317 }
6318 }
6319 } else {
3e3326df
PM
6320 /* Two registers and a scalar. NB that for ops of this form
6321 * the ARM ARM labels bit 24 as Q, but it is in our variable
6322 * 'u', not 'q'.
6323 */
6324 if (size == 0) {
6325 return 1;
6326 }
9ee6e8bb 6327 switch (op) {
9ee6e8bb 6328 case 1: /* Float VMLA scalar */
9ee6e8bb 6329 case 5: /* Floating point VMLS scalar */
9ee6e8bb 6330 case 9: /* Floating point VMUL scalar */
3e3326df
PM
6331 if (size == 1) {
6332 return 1;
6333 }
6334 /* fall through */
6335 case 0: /* Integer VMLA scalar */
6336 case 4: /* Integer VMLS scalar */
6337 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
6338 case 12: /* VQDMULH scalar */
6339 case 13: /* VQRDMULH scalar */
3e3326df
PM
6340 if (u && ((rd | rn) & 1)) {
6341 return 1;
6342 }
dd8fbd78
FN
6343 tmp = neon_get_scalar(size, rm);
6344 neon_store_scratch(0, tmp);
9ee6e8bb 6345 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
6346 tmp = neon_load_scratch(0);
6347 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
6348 if (op == 12) {
6349 if (size == 1) {
02da0b2d 6350 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6351 } else {
02da0b2d 6352 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6353 }
6354 } else if (op == 13) {
6355 if (size == 1) {
02da0b2d 6356 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6357 } else {
02da0b2d 6358 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6359 }
6360 } else if (op & 1) {
aa47cfdd
PM
6361 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6362 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6363 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
6364 } else {
6365 switch (size) {
dd8fbd78
FN
6366 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6367 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6368 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 6369 default: abort();
9ee6e8bb
PB
6370 }
6371 }
7d1b0095 6372 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
6373 if (op < 8) {
6374 /* Accumulate. */
dd8fbd78 6375 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
6376 switch (op) {
6377 case 0:
dd8fbd78 6378 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6379 break;
6380 case 1:
aa47cfdd
PM
6381 {
6382 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6383 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6384 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6385 break;
aa47cfdd 6386 }
9ee6e8bb 6387 case 4:
dd8fbd78 6388 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
6389 break;
6390 case 5:
aa47cfdd
PM
6391 {
6392 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6393 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6394 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6395 break;
aa47cfdd 6396 }
9ee6e8bb
PB
6397 default:
6398 abort();
6399 }
7d1b0095 6400 tcg_temp_free_i32(tmp2);
9ee6e8bb 6401 }
dd8fbd78 6402 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6403 }
6404 break;
9ee6e8bb 6405 case 3: /* VQDMLAL scalar */
9ee6e8bb 6406 case 7: /* VQDMLSL scalar */
9ee6e8bb 6407 case 11: /* VQDMULL scalar */
3e3326df 6408 if (u == 1) {
ad69471c 6409 return 1;
3e3326df
PM
6410 }
6411 /* fall through */
6412 case 2: /* VMLAL sclar */
6413 case 6: /* VMLSL scalar */
6414 case 10: /* VMULL scalar */
6415 if (rd & 1) {
6416 return 1;
6417 }
dd8fbd78 6418 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
6419 /* We need a copy of tmp2 because gen_neon_mull
6420 * deletes it during pass 0. */
7d1b0095 6421 tmp4 = tcg_temp_new_i32();
c6067f04 6422 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 6423 tmp3 = neon_load_reg(rn, 1);
ad69471c 6424
9ee6e8bb 6425 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6426 if (pass == 0) {
6427 tmp = neon_load_reg(rn, 0);
9ee6e8bb 6428 } else {
dd8fbd78 6429 tmp = tmp3;
c6067f04 6430 tmp2 = tmp4;
9ee6e8bb 6431 }
ad69471c 6432 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
6433 if (op != 11) {
6434 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6435 }
9ee6e8bb 6436 switch (op) {
4dc064e6
PM
6437 case 6:
6438 gen_neon_negl(cpu_V0, size);
6439 /* Fall through */
6440 case 2:
ad69471c 6441 gen_neon_addl(size);
9ee6e8bb
PB
6442 break;
6443 case 3: case 7:
ad69471c 6444 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6445 if (op == 7) {
6446 gen_neon_negl(cpu_V0, size);
6447 }
ad69471c 6448 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
6449 break;
6450 case 10:
6451 /* no-op */
6452 break;
6453 case 11:
ad69471c 6454 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
6455 break;
6456 default:
6457 abort();
6458 }
ad69471c 6459 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6460 }
dd8fbd78 6461
dd8fbd78 6462
9ee6e8bb
PB
6463 break;
6464 default: /* 14 and 15 are RESERVED */
6465 return 1;
6466 }
6467 }
6468 } else { /* size == 3 */
6469 if (!u) {
6470 /* Extract. */
9ee6e8bb 6471 imm = (insn >> 8) & 0xf;
ad69471c
PB
6472
6473 if (imm > 7 && !q)
6474 return 1;
6475
52579ea1
PM
6476 if (q && ((rd | rn | rm) & 1)) {
6477 return 1;
6478 }
6479
ad69471c
PB
6480 if (imm == 0) {
6481 neon_load_reg64(cpu_V0, rn);
6482 if (q) {
6483 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 6484 }
ad69471c
PB
6485 } else if (imm == 8) {
6486 neon_load_reg64(cpu_V0, rn + 1);
6487 if (q) {
6488 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6489 }
ad69471c 6490 } else if (q) {
a7812ae4 6491 tmp64 = tcg_temp_new_i64();
ad69471c
PB
6492 if (imm < 8) {
6493 neon_load_reg64(cpu_V0, rn);
a7812ae4 6494 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
6495 } else {
6496 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 6497 neon_load_reg64(tmp64, rm);
ad69471c
PB
6498 }
6499 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 6500 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
6501 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6502 if (imm < 8) {
6503 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6504 } else {
ad69471c
PB
6505 neon_load_reg64(cpu_V1, rm + 1);
6506 imm -= 8;
9ee6e8bb 6507 }
ad69471c 6508 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
6509 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6510 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 6511 tcg_temp_free_i64(tmp64);
ad69471c 6512 } else {
a7812ae4 6513 /* BUGFIX */
ad69471c 6514 neon_load_reg64(cpu_V0, rn);
a7812ae4 6515 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 6516 neon_load_reg64(cpu_V1, rm);
a7812ae4 6517 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
6518 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6519 }
6520 neon_store_reg64(cpu_V0, rd);
6521 if (q) {
6522 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
6523 }
6524 } else if ((insn & (1 << 11)) == 0) {
6525 /* Two register misc. */
6526 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6527 size = (insn >> 18) & 3;
600b828c
PM
6528 /* UNDEF for unknown op values and bad op-size combinations */
6529 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6530 return 1;
6531 }
fc2a9b37
PM
6532 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6533 q && ((rm | rd) & 1)) {
6534 return 1;
6535 }
9ee6e8bb 6536 switch (op) {
600b828c 6537 case NEON_2RM_VREV64:
9ee6e8bb 6538 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
6539 tmp = neon_load_reg(rm, pass * 2);
6540 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 6541 switch (size) {
dd8fbd78
FN
6542 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6543 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
6544 case 2: /* no-op */ break;
6545 default: abort();
6546 }
dd8fbd78 6547 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 6548 if (size == 2) {
dd8fbd78 6549 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 6550 } else {
9ee6e8bb 6551 switch (size) {
dd8fbd78
FN
6552 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6553 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
6554 default: abort();
6555 }
dd8fbd78 6556 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
6557 }
6558 }
6559 break;
600b828c
PM
6560 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6561 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
6562 for (pass = 0; pass < q + 1; pass++) {
6563 tmp = neon_load_reg(rm, pass * 2);
6564 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6565 tmp = neon_load_reg(rm, pass * 2 + 1);
6566 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6567 switch (size) {
6568 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6569 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6570 case 2: tcg_gen_add_i64(CPU_V001); break;
6571 default: abort();
6572 }
600b828c 6573 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 6574 /* Accumulate. */
ad69471c
PB
6575 neon_load_reg64(cpu_V1, rd + pass);
6576 gen_neon_addl(size);
9ee6e8bb 6577 }
ad69471c 6578 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6579 }
6580 break;
600b828c 6581 case NEON_2RM_VTRN:
9ee6e8bb 6582 if (size == 2) {
a5a14945 6583 int n;
9ee6e8bb 6584 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
6585 tmp = neon_load_reg(rm, n);
6586 tmp2 = neon_load_reg(rd, n + 1);
6587 neon_store_reg(rm, n, tmp2);
6588 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
6589 }
6590 } else {
6591 goto elementwise;
6592 }
6593 break;
600b828c 6594 case NEON_2RM_VUZP:
02acedf9 6595 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 6596 return 1;
9ee6e8bb
PB
6597 }
6598 break;
600b828c 6599 case NEON_2RM_VZIP:
d68a6f3a 6600 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 6601 return 1;
9ee6e8bb
PB
6602 }
6603 break;
600b828c
PM
6604 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6605 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
6606 if (rm & 1) {
6607 return 1;
6608 }
39d5492a 6609 TCGV_UNUSED_I32(tmp2);
9ee6e8bb 6610 for (pass = 0; pass < 2; pass++) {
ad69471c 6611 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 6612 tmp = tcg_temp_new_i32();
600b828c
PM
6613 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6614 tmp, cpu_V0);
ad69471c
PB
6615 if (pass == 0) {
6616 tmp2 = tmp;
6617 } else {
6618 neon_store_reg(rd, 0, tmp2);
6619 neon_store_reg(rd, 1, tmp);
9ee6e8bb 6620 }
9ee6e8bb
PB
6621 }
6622 break;
600b828c 6623 case NEON_2RM_VSHLL:
fc2a9b37 6624 if (q || (rd & 1)) {
9ee6e8bb 6625 return 1;
600b828c 6626 }
ad69471c
PB
6627 tmp = neon_load_reg(rm, 0);
6628 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6629 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6630 if (pass == 1)
6631 tmp = tmp2;
6632 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 6633 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 6634 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6635 }
6636 break;
600b828c 6637 case NEON_2RM_VCVT_F16_F32:
d614a513 6638 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
6639 q || (rm & 1)) {
6640 return 1;
6641 }
7d1b0095
PM
6642 tmp = tcg_temp_new_i32();
6643 tmp2 = tcg_temp_new_i32();
60011498 6644 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
2d981da7 6645 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
60011498 6646 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
2d981da7 6647 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
60011498
PB
6648 tcg_gen_shli_i32(tmp2, tmp2, 16);
6649 tcg_gen_or_i32(tmp2, tmp2, tmp);
6650 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
2d981da7 6651 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
60011498
PB
6652 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6653 neon_store_reg(rd, 0, tmp2);
7d1b0095 6654 tmp2 = tcg_temp_new_i32();
2d981da7 6655 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
60011498
PB
6656 tcg_gen_shli_i32(tmp2, tmp2, 16);
6657 tcg_gen_or_i32(tmp2, tmp2, tmp);
6658 neon_store_reg(rd, 1, tmp2);
7d1b0095 6659 tcg_temp_free_i32(tmp);
60011498 6660 break;
600b828c 6661 case NEON_2RM_VCVT_F32_F16:
d614a513 6662 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
6663 q || (rd & 1)) {
6664 return 1;
6665 }
7d1b0095 6666 tmp3 = tcg_temp_new_i32();
60011498
PB
6667 tmp = neon_load_reg(rm, 0);
6668 tmp2 = neon_load_reg(rm, 1);
6669 tcg_gen_ext16u_i32(tmp3, tmp);
2d981da7 6670 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498
PB
6671 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6672 tcg_gen_shri_i32(tmp3, tmp, 16);
2d981da7 6673 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498 6674 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7d1b0095 6675 tcg_temp_free_i32(tmp);
60011498 6676 tcg_gen_ext16u_i32(tmp3, tmp2);
2d981da7 6677 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498
PB
6678 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6679 tcg_gen_shri_i32(tmp3, tmp2, 16);
2d981da7 6680 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
60011498 6681 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7d1b0095
PM
6682 tcg_temp_free_i32(tmp2);
6683 tcg_temp_free_i32(tmp3);
60011498 6684 break;
9d935509 6685 case NEON_2RM_AESE: case NEON_2RM_AESMC:
d614a513 6686 if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
9d935509
AB
6687 || ((rm | rd) & 1)) {
6688 return 1;
6689 }
6690 tmp = tcg_const_i32(rd);
6691 tmp2 = tcg_const_i32(rm);
6692
6693 /* Bit 6 is the lowest opcode bit; it distinguishes between
6694 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6695 */
6696 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6697
6698 if (op == NEON_2RM_AESE) {
6699 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6700 } else {
6701 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6702 }
6703 tcg_temp_free_i32(tmp);
6704 tcg_temp_free_i32(tmp2);
6705 tcg_temp_free_i32(tmp3);
6706 break;
f1ecb913 6707 case NEON_2RM_SHA1H:
d614a513 6708 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)
f1ecb913
AB
6709 || ((rm | rd) & 1)) {
6710 return 1;
6711 }
6712 tmp = tcg_const_i32(rd);
6713 tmp2 = tcg_const_i32(rm);
6714
6715 gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
6716
6717 tcg_temp_free_i32(tmp);
6718 tcg_temp_free_i32(tmp2);
6719 break;
6720 case NEON_2RM_SHA1SU1:
6721 if ((rm | rd) & 1) {
6722 return 1;
6723 }
6724 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6725 if (q) {
d614a513 6726 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) {
f1ecb913
AB
6727 return 1;
6728 }
d614a513 6729 } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
6730 return 1;
6731 }
6732 tmp = tcg_const_i32(rd);
6733 tmp2 = tcg_const_i32(rm);
6734 if (q) {
6735 gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
6736 } else {
6737 gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
6738 }
6739 tcg_temp_free_i32(tmp);
6740 tcg_temp_free_i32(tmp2);
6741 break;
9ee6e8bb
PB
6742 default:
6743 elementwise:
6744 for (pass = 0; pass < (q ? 4 : 2); pass++) {
600b828c 6745 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
6746 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6747 neon_reg_offset(rm, pass));
39d5492a 6748 TCGV_UNUSED_I32(tmp);
9ee6e8bb 6749 } else {
dd8fbd78 6750 tmp = neon_load_reg(rm, pass);
9ee6e8bb
PB
6751 }
6752 switch (op) {
600b828c 6753 case NEON_2RM_VREV32:
9ee6e8bb 6754 switch (size) {
dd8fbd78
FN
6755 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6756 case 1: gen_swap_half(tmp); break;
600b828c 6757 default: abort();
9ee6e8bb
PB
6758 }
6759 break;
600b828c 6760 case NEON_2RM_VREV16:
dd8fbd78 6761 gen_rev16(tmp);
9ee6e8bb 6762 break;
600b828c 6763 case NEON_2RM_VCLS:
9ee6e8bb 6764 switch (size) {
dd8fbd78
FN
6765 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6766 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6767 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 6768 default: abort();
9ee6e8bb
PB
6769 }
6770 break;
600b828c 6771 case NEON_2RM_VCLZ:
9ee6e8bb 6772 switch (size) {
dd8fbd78
FN
6773 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6774 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6775 case 2: gen_helper_clz(tmp, tmp); break;
600b828c 6776 default: abort();
9ee6e8bb
PB
6777 }
6778 break;
600b828c 6779 case NEON_2RM_VCNT:
dd8fbd78 6780 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 6781 break;
600b828c 6782 case NEON_2RM_VMVN:
dd8fbd78 6783 tcg_gen_not_i32(tmp, tmp);
9ee6e8bb 6784 break;
600b828c 6785 case NEON_2RM_VQABS:
9ee6e8bb 6786 switch (size) {
02da0b2d
PM
6787 case 0:
6788 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6789 break;
6790 case 1:
6791 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6792 break;
6793 case 2:
6794 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6795 break;
600b828c 6796 default: abort();
9ee6e8bb
PB
6797 }
6798 break;
600b828c 6799 case NEON_2RM_VQNEG:
9ee6e8bb 6800 switch (size) {
02da0b2d
PM
6801 case 0:
6802 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6803 break;
6804 case 1:
6805 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6806 break;
6807 case 2:
6808 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6809 break;
600b828c 6810 default: abort();
9ee6e8bb
PB
6811 }
6812 break;
600b828c 6813 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 6814 tmp2 = tcg_const_i32(0);
9ee6e8bb 6815 switch(size) {
dd8fbd78
FN
6816 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6817 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6818 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 6819 default: abort();
9ee6e8bb 6820 }
39d5492a 6821 tcg_temp_free_i32(tmp2);
600b828c 6822 if (op == NEON_2RM_VCLE0) {
dd8fbd78 6823 tcg_gen_not_i32(tmp, tmp);
600b828c 6824 }
9ee6e8bb 6825 break;
600b828c 6826 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 6827 tmp2 = tcg_const_i32(0);
9ee6e8bb 6828 switch(size) {
dd8fbd78
FN
6829 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6830 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6831 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 6832 default: abort();
9ee6e8bb 6833 }
39d5492a 6834 tcg_temp_free_i32(tmp2);
600b828c 6835 if (op == NEON_2RM_VCLT0) {
dd8fbd78 6836 tcg_gen_not_i32(tmp, tmp);
600b828c 6837 }
9ee6e8bb 6838 break;
600b828c 6839 case NEON_2RM_VCEQ0:
dd8fbd78 6840 tmp2 = tcg_const_i32(0);
9ee6e8bb 6841 switch(size) {
dd8fbd78
FN
6842 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6843 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6844 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 6845 default: abort();
9ee6e8bb 6846 }
39d5492a 6847 tcg_temp_free_i32(tmp2);
9ee6e8bb 6848 break;
600b828c 6849 case NEON_2RM_VABS:
9ee6e8bb 6850 switch(size) {
dd8fbd78
FN
6851 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6852 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6853 case 2: tcg_gen_abs_i32(tmp, tmp); break;
600b828c 6854 default: abort();
9ee6e8bb
PB
6855 }
6856 break;
600b828c 6857 case NEON_2RM_VNEG:
dd8fbd78
FN
6858 tmp2 = tcg_const_i32(0);
6859 gen_neon_rsb(size, tmp, tmp2);
39d5492a 6860 tcg_temp_free_i32(tmp2);
9ee6e8bb 6861 break;
600b828c 6862 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
6863 {
6864 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6865 tmp2 = tcg_const_i32(0);
aa47cfdd 6866 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6867 tcg_temp_free_i32(tmp2);
aa47cfdd 6868 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6869 break;
aa47cfdd 6870 }
600b828c 6871 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
6872 {
6873 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6874 tmp2 = tcg_const_i32(0);
aa47cfdd 6875 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6876 tcg_temp_free_i32(tmp2);
aa47cfdd 6877 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6878 break;
aa47cfdd 6879 }
600b828c 6880 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
6881 {
6882 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6883 tmp2 = tcg_const_i32(0);
aa47cfdd 6884 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6885 tcg_temp_free_i32(tmp2);
aa47cfdd 6886 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6887 break;
aa47cfdd 6888 }
600b828c 6889 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
6890 {
6891 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6892 tmp2 = tcg_const_i32(0);
aa47cfdd 6893 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6894 tcg_temp_free_i32(tmp2);
aa47cfdd 6895 tcg_temp_free_ptr(fpstatus);
0e326109 6896 break;
aa47cfdd 6897 }
600b828c 6898 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
6899 {
6900 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6901 tmp2 = tcg_const_i32(0);
aa47cfdd 6902 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6903 tcg_temp_free_i32(tmp2);
aa47cfdd 6904 tcg_temp_free_ptr(fpstatus);
0e326109 6905 break;
aa47cfdd 6906 }
600b828c 6907 case NEON_2RM_VABS_F:
4373f3ce 6908 gen_vfp_abs(0);
9ee6e8bb 6909 break;
600b828c 6910 case NEON_2RM_VNEG_F:
4373f3ce 6911 gen_vfp_neg(0);
9ee6e8bb 6912 break;
600b828c 6913 case NEON_2RM_VSWP:
dd8fbd78
FN
6914 tmp2 = neon_load_reg(rd, pass);
6915 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6916 break;
600b828c 6917 case NEON_2RM_VTRN:
dd8fbd78 6918 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6919 switch (size) {
dd8fbd78
FN
6920 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6921 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 6922 default: abort();
9ee6e8bb 6923 }
dd8fbd78 6924 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6925 break;
34f7b0a2
WN
6926 case NEON_2RM_VRINTN:
6927 case NEON_2RM_VRINTA:
6928 case NEON_2RM_VRINTM:
6929 case NEON_2RM_VRINTP:
6930 case NEON_2RM_VRINTZ:
6931 {
6932 TCGv_i32 tcg_rmode;
6933 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6934 int rmode;
6935
6936 if (op == NEON_2RM_VRINTZ) {
6937 rmode = FPROUNDING_ZERO;
6938 } else {
6939 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6940 }
6941
6942 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6943 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6944 cpu_env);
6945 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6946 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6947 cpu_env);
6948 tcg_temp_free_ptr(fpstatus);
6949 tcg_temp_free_i32(tcg_rmode);
6950 break;
6951 }
2ce70625
WN
6952 case NEON_2RM_VRINTX:
6953 {
6954 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6955 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6956 tcg_temp_free_ptr(fpstatus);
6957 break;
6958 }
901ad525
WN
6959 case NEON_2RM_VCVTAU:
6960 case NEON_2RM_VCVTAS:
6961 case NEON_2RM_VCVTNU:
6962 case NEON_2RM_VCVTNS:
6963 case NEON_2RM_VCVTPU:
6964 case NEON_2RM_VCVTPS:
6965 case NEON_2RM_VCVTMU:
6966 case NEON_2RM_VCVTMS:
6967 {
6968 bool is_signed = !extract32(insn, 7, 1);
6969 TCGv_ptr fpst = get_fpstatus_ptr(1);
6970 TCGv_i32 tcg_rmode, tcg_shift;
6971 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6972
6973 tcg_shift = tcg_const_i32(0);
6974 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6975 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6976 cpu_env);
6977
6978 if (is_signed) {
6979 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6980 tcg_shift, fpst);
6981 } else {
6982 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6983 tcg_shift, fpst);
6984 }
6985
6986 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6987 cpu_env);
6988 tcg_temp_free_i32(tcg_rmode);
6989 tcg_temp_free_i32(tcg_shift);
6990 tcg_temp_free_ptr(fpst);
6991 break;
6992 }
600b828c 6993 case NEON_2RM_VRECPE:
b6d4443a
AB
6994 {
6995 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6996 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6997 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6998 break;
b6d4443a 6999 }
600b828c 7000 case NEON_2RM_VRSQRTE:
c2fb418e
AB
7001 {
7002 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7003 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7004 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7005 break;
c2fb418e 7006 }
600b828c 7007 case NEON_2RM_VRECPE_F:
b6d4443a
AB
7008 {
7009 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7010 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7011 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7012 break;
b6d4443a 7013 }
600b828c 7014 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
7015 {
7016 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7017 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7018 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7019 break;
c2fb418e 7020 }
600b828c 7021 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
5500b06c 7022 gen_vfp_sito(0, 1);
9ee6e8bb 7023 break;
600b828c 7024 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
5500b06c 7025 gen_vfp_uito(0, 1);
9ee6e8bb 7026 break;
600b828c 7027 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
5500b06c 7028 gen_vfp_tosiz(0, 1);
9ee6e8bb 7029 break;
600b828c 7030 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
5500b06c 7031 gen_vfp_touiz(0, 1);
9ee6e8bb
PB
7032 break;
7033 default:
600b828c
PM
7034 /* Reserved op values were caught by the
7035 * neon_2rm_sizes[] check earlier.
7036 */
7037 abort();
9ee6e8bb 7038 }
600b828c 7039 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7040 tcg_gen_st_f32(cpu_F0s, cpu_env,
7041 neon_reg_offset(rd, pass));
9ee6e8bb 7042 } else {
dd8fbd78 7043 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
7044 }
7045 }
7046 break;
7047 }
7048 } else if ((insn & (1 << 10)) == 0) {
7049 /* VTBL, VTBX. */
56907d77
PM
7050 int n = ((insn >> 8) & 3) + 1;
7051 if ((rn + n) > 32) {
7052 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
7053 * helper function running off the end of the register file.
7054 */
7055 return 1;
7056 }
7057 n <<= 3;
9ee6e8bb 7058 if (insn & (1 << 6)) {
8f8e3aa4 7059 tmp = neon_load_reg(rd, 0);
9ee6e8bb 7060 } else {
7d1b0095 7061 tmp = tcg_temp_new_i32();
8f8e3aa4 7062 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7063 }
8f8e3aa4 7064 tmp2 = neon_load_reg(rm, 0);
b75263d6
JR
7065 tmp4 = tcg_const_i32(rn);
7066 tmp5 = tcg_const_i32(n);
9ef39277 7067 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
7d1b0095 7068 tcg_temp_free_i32(tmp);
9ee6e8bb 7069 if (insn & (1 << 6)) {
8f8e3aa4 7070 tmp = neon_load_reg(rd, 1);
9ee6e8bb 7071 } else {
7d1b0095 7072 tmp = tcg_temp_new_i32();
8f8e3aa4 7073 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7074 }
8f8e3aa4 7075 tmp3 = neon_load_reg(rm, 1);
9ef39277 7076 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
25aeb69b
JR
7077 tcg_temp_free_i32(tmp5);
7078 tcg_temp_free_i32(tmp4);
8f8e3aa4 7079 neon_store_reg(rd, 0, tmp2);
3018f259 7080 neon_store_reg(rd, 1, tmp3);
7d1b0095 7081 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7082 } else if ((insn & 0x380) == 0) {
7083 /* VDUP */
133da6aa
JR
7084 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7085 return 1;
7086 }
9ee6e8bb 7087 if (insn & (1 << 19)) {
dd8fbd78 7088 tmp = neon_load_reg(rm, 1);
9ee6e8bb 7089 } else {
dd8fbd78 7090 tmp = neon_load_reg(rm, 0);
9ee6e8bb
PB
7091 }
7092 if (insn & (1 << 16)) {
dd8fbd78 7093 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
9ee6e8bb
PB
7094 } else if (insn & (1 << 17)) {
7095 if ((insn >> 18) & 1)
dd8fbd78 7096 gen_neon_dup_high16(tmp);
9ee6e8bb 7097 else
dd8fbd78 7098 gen_neon_dup_low16(tmp);
9ee6e8bb
PB
7099 }
7100 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7d1b0095 7101 tmp2 = tcg_temp_new_i32();
dd8fbd78
FN
7102 tcg_gen_mov_i32(tmp2, tmp);
7103 neon_store_reg(rd, pass, tmp2);
9ee6e8bb 7104 }
7d1b0095 7105 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7106 } else {
7107 return 1;
7108 }
7109 }
7110 }
7111 return 0;
7112}
7113
7dcc1f89 7114static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 7115{
4b6a83fb
PM
7116 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7117 const ARMCPRegInfo *ri;
9ee6e8bb
PB
7118
7119 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
7120
7121 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 7122 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
7123 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7124 return 1;
7125 }
d614a513 7126 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 7127 return disas_iwmmxt_insn(s, insn);
d614a513 7128 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 7129 return disas_dsp_insn(s, insn);
c0f4af17
PM
7130 }
7131 return 1;
4b6a83fb
PM
7132 }
7133
7134 /* Otherwise treat as a generic register access */
7135 is64 = (insn & (1 << 25)) == 0;
7136 if (!is64 && ((insn & (1 << 4)) == 0)) {
7137 /* cdp */
7138 return 1;
7139 }
7140
7141 crm = insn & 0xf;
7142 if (is64) {
7143 crn = 0;
7144 opc1 = (insn >> 4) & 0xf;
7145 opc2 = 0;
7146 rt2 = (insn >> 16) & 0xf;
7147 } else {
7148 crn = (insn >> 16) & 0xf;
7149 opc1 = (insn >> 21) & 7;
7150 opc2 = (insn >> 5) & 7;
7151 rt2 = 0;
7152 }
7153 isread = (insn >> 20) & 1;
7154 rt = (insn >> 12) & 0xf;
7155
60322b39 7156 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 7157 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
7158 if (ri) {
7159 /* Check access permissions */
dcbff19b 7160 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
7161 return 1;
7162 }
7163
c0f4af17 7164 if (ri->accessfn ||
d614a513 7165 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
7166 /* Emit code to perform further access permissions checks at
7167 * runtime; this may result in an exception.
c0f4af17
PM
7168 * Note that on XScale all cp0..c13 registers do an access check
7169 * call in order to handle c15_cpar.
f59df3f2
PM
7170 */
7171 TCGv_ptr tmpptr;
3f208fd7 7172 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
7173 uint32_t syndrome;
7174
7175 /* Note that since we are an implementation which takes an
7176 * exception on a trapped conditional instruction only if the
7177 * instruction passes its condition code check, we can take
7178 * advantage of the clause in the ARM ARM that allows us to set
7179 * the COND field in the instruction to 0xE in all cases.
7180 * We could fish the actual condition out of the insn (ARM)
7181 * or the condexec bits (Thumb) but it isn't necessary.
7182 */
7183 switch (cpnum) {
7184 case 14:
7185 if (is64) {
7186 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7187 isread, false);
8bcbf37c
PM
7188 } else {
7189 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7190 rt, isread, false);
8bcbf37c
PM
7191 }
7192 break;
7193 case 15:
7194 if (is64) {
7195 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7196 isread, false);
8bcbf37c
PM
7197 } else {
7198 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7199 rt, isread, false);
8bcbf37c
PM
7200 }
7201 break;
7202 default:
7203 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7204 * so this can only happen if this is an ARMv7 or earlier CPU,
7205 * in which case the syndrome information won't actually be
7206 * guest visible.
7207 */
d614a513 7208 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7209 syndrome = syn_uncategorized();
7210 break;
7211 }
7212
43bfa4a1 7213 gen_set_condexec(s);
3977ee5d 7214 gen_set_pc_im(s, s->pc - 4);
f59df3f2 7215 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7216 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7217 tcg_isread = tcg_const_i32(isread);
7218 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7219 tcg_isread);
f59df3f2 7220 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7221 tcg_temp_free_i32(tcg_syn);
3f208fd7 7222 tcg_temp_free_i32(tcg_isread);
f59df3f2
PM
7223 }
7224
4b6a83fb
PM
7225 /* Handle special cases first */
7226 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7227 case ARM_CP_NOP:
7228 return 0;
7229 case ARM_CP_WFI:
7230 if (isread) {
7231 return 1;
7232 }
eaed129d 7233 gen_set_pc_im(s, s->pc);
4b6a83fb 7234 s->is_jmp = DISAS_WFI;
2bee5105 7235 return 0;
4b6a83fb
PM
7236 default:
7237 break;
7238 }
7239
bd79255d 7240 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7241 gen_io_start();
7242 }
7243
4b6a83fb
PM
7244 if (isread) {
7245 /* Read */
7246 if (is64) {
7247 TCGv_i64 tmp64;
7248 TCGv_i32 tmp;
7249 if (ri->type & ARM_CP_CONST) {
7250 tmp64 = tcg_const_i64(ri->resetvalue);
7251 } else if (ri->readfn) {
7252 TCGv_ptr tmpptr;
4b6a83fb
PM
7253 tmp64 = tcg_temp_new_i64();
7254 tmpptr = tcg_const_ptr(ri);
7255 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7256 tcg_temp_free_ptr(tmpptr);
7257 } else {
7258 tmp64 = tcg_temp_new_i64();
7259 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7260 }
7261 tmp = tcg_temp_new_i32();
ecc7b3aa 7262 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb
PM
7263 store_reg(s, rt, tmp);
7264 tcg_gen_shri_i64(tmp64, tmp64, 32);
ed336850 7265 tmp = tcg_temp_new_i32();
ecc7b3aa 7266 tcg_gen_extrl_i64_i32(tmp, tmp64);
ed336850 7267 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
7268 store_reg(s, rt2, tmp);
7269 } else {
39d5492a 7270 TCGv_i32 tmp;
4b6a83fb
PM
7271 if (ri->type & ARM_CP_CONST) {
7272 tmp = tcg_const_i32(ri->resetvalue);
7273 } else if (ri->readfn) {
7274 TCGv_ptr tmpptr;
4b6a83fb
PM
7275 tmp = tcg_temp_new_i32();
7276 tmpptr = tcg_const_ptr(ri);
7277 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7278 tcg_temp_free_ptr(tmpptr);
7279 } else {
7280 tmp = load_cpu_offset(ri->fieldoffset);
7281 }
7282 if (rt == 15) {
7283 /* Destination register of r15 for 32 bit loads sets
7284 * the condition codes from the high 4 bits of the value
7285 */
7286 gen_set_nzcv(tmp);
7287 tcg_temp_free_i32(tmp);
7288 } else {
7289 store_reg(s, rt, tmp);
7290 }
7291 }
7292 } else {
7293 /* Write */
7294 if (ri->type & ARM_CP_CONST) {
7295 /* If not forbidden by access permissions, treat as WI */
7296 return 0;
7297 }
7298
7299 if (is64) {
39d5492a 7300 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
7301 TCGv_i64 tmp64 = tcg_temp_new_i64();
7302 tmplo = load_reg(s, rt);
7303 tmphi = load_reg(s, rt2);
7304 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7305 tcg_temp_free_i32(tmplo);
7306 tcg_temp_free_i32(tmphi);
7307 if (ri->writefn) {
7308 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
7309 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7310 tcg_temp_free_ptr(tmpptr);
7311 } else {
7312 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7313 }
7314 tcg_temp_free_i64(tmp64);
7315 } else {
7316 if (ri->writefn) {
39d5492a 7317 TCGv_i32 tmp;
4b6a83fb 7318 TCGv_ptr tmpptr;
4b6a83fb
PM
7319 tmp = load_reg(s, rt);
7320 tmpptr = tcg_const_ptr(ri);
7321 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7322 tcg_temp_free_ptr(tmpptr);
7323 tcg_temp_free_i32(tmp);
7324 } else {
39d5492a 7325 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
7326 store_cpu_offset(tmp, ri->fieldoffset);
7327 }
7328 }
2452731c
PM
7329 }
7330
bd79255d 7331 if ((s->tb->cflags & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7332 /* I/O operations must end the TB here (whether read or write) */
7333 gen_io_end();
7334 gen_lookup_tb(s);
7335 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
7336 /* We default to ending the TB on a coprocessor register write,
7337 * but allow this to be suppressed by the register definition
7338 * (usually only necessary to work around guest bugs).
7339 */
2452731c 7340 gen_lookup_tb(s);
4b6a83fb 7341 }
2452731c 7342
4b6a83fb
PM
7343 return 0;
7344 }
7345
626187d8
PM
7346 /* Unknown register; this might be a guest error or a QEMU
7347 * unimplemented feature.
7348 */
7349 if (is64) {
7350 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7351 "64 bit system register cp:%d opc1: %d crm:%d "
7352 "(%s)\n",
7353 isread ? "read" : "write", cpnum, opc1, crm,
7354 s->ns ? "non-secure" : "secure");
626187d8
PM
7355 } else {
7356 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7357 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7358 "(%s)\n",
7359 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7360 s->ns ? "non-secure" : "secure");
626187d8
PM
7361 }
7362
4a9a539f 7363 return 1;
9ee6e8bb
PB
7364}
7365
5e3f878a
PB
7366
7367/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 7368static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 7369{
39d5492a 7370 TCGv_i32 tmp;
7d1b0095 7371 tmp = tcg_temp_new_i32();
ecc7b3aa 7372 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 7373 store_reg(s, rlow, tmp);
7d1b0095 7374 tmp = tcg_temp_new_i32();
5e3f878a 7375 tcg_gen_shri_i64(val, val, 32);
ecc7b3aa 7376 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a
PB
7377 store_reg(s, rhigh, tmp);
7378}
7379
7380/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 7381static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 7382{
a7812ae4 7383 TCGv_i64 tmp;
39d5492a 7384 TCGv_i32 tmp2;
5e3f878a 7385
36aa55dc 7386 /* Load value and extend to 64 bits. */
a7812ae4 7387 tmp = tcg_temp_new_i64();
5e3f878a
PB
7388 tmp2 = load_reg(s, rlow);
7389 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 7390 tcg_temp_free_i32(tmp2);
5e3f878a 7391 tcg_gen_add_i64(val, val, tmp);
b75263d6 7392 tcg_temp_free_i64(tmp);
5e3f878a
PB
7393}
7394
7395/* load and add a 64-bit value from a register pair. */
a7812ae4 7396static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 7397{
a7812ae4 7398 TCGv_i64 tmp;
39d5492a
PM
7399 TCGv_i32 tmpl;
7400 TCGv_i32 tmph;
5e3f878a
PB
7401
7402 /* Load 64-bit value rd:rn. */
36aa55dc
PB
7403 tmpl = load_reg(s, rlow);
7404 tmph = load_reg(s, rhigh);
a7812ae4 7405 tmp = tcg_temp_new_i64();
36aa55dc 7406 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
7407 tcg_temp_free_i32(tmpl);
7408 tcg_temp_free_i32(tmph);
5e3f878a 7409 tcg_gen_add_i64(val, val, tmp);
b75263d6 7410 tcg_temp_free_i64(tmp);
5e3f878a
PB
7411}
7412
c9f10124 7413/* Set N and Z flags from hi|lo. */
39d5492a 7414static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 7415{
c9f10124
RH
7416 tcg_gen_mov_i32(cpu_NF, hi);
7417 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
7418}
7419
426f5abc
PB
7420/* Load/Store exclusive instructions are implemented by remembering
7421 the value/address loaded, and seeing if these are the same
b90372ad 7422 when the store is performed. This should be sufficient to implement
426f5abc
PB
7423 the architecturally mandated semantics, and avoids having to monitor
7424 regular stores.
7425
7426 In system emulation mode only one CPU will be running at once, so
7427 this sequence is effectively atomic. In user emulation mode we
7428 throw an exception and handle the atomic operation elsewhere. */
7429static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 7430 TCGv_i32 addr, int size)
426f5abc 7431{
94ee24e7 7432 TCGv_i32 tmp = tcg_temp_new_i32();
426f5abc 7433
50225ad0
PM
7434 s->is_ldex = true;
7435
426f5abc
PB
7436 switch (size) {
7437 case 0:
6ce2faf4 7438 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
426f5abc
PB
7439 break;
7440 case 1:
30901475 7441 gen_aa32_ld16ua(tmp, addr, get_mem_index(s));
426f5abc
PB
7442 break;
7443 case 2:
7444 case 3:
30901475 7445 gen_aa32_ld32ua(tmp, addr, get_mem_index(s));
426f5abc
PB
7446 break;
7447 default:
7448 abort();
7449 }
03d05e2d 7450
426f5abc 7451 if (size == 3) {
39d5492a 7452 TCGv_i32 tmp2 = tcg_temp_new_i32();
03d05e2d
PM
7453 TCGv_i32 tmp3 = tcg_temp_new_i32();
7454
2c9adbda 7455 tcg_gen_addi_i32(tmp2, addr, 4);
6ce2faf4 7456 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7d1b0095 7457 tcg_temp_free_i32(tmp2);
03d05e2d
PM
7458 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7459 store_reg(s, rt2, tmp3);
7460 } else {
7461 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 7462 }
03d05e2d
PM
7463
7464 store_reg(s, rt, tmp);
7465 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
7466}
7467
7468static void gen_clrex(DisasContext *s)
7469{
03d05e2d 7470 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7471}
7472
7473#ifdef CONFIG_USER_ONLY
7474static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7475 TCGv_i32 addr, int size)
426f5abc 7476{
03d05e2d 7477 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
426f5abc
PB
7478 tcg_gen_movi_i32(cpu_exclusive_info,
7479 size | (rd << 4) | (rt << 8) | (rt2 << 12));
d4a2dc67 7480 gen_exception_internal_insn(s, 4, EXCP_STREX);
426f5abc
PB
7481}
7482#else
7483static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7484 TCGv_i32 addr, int size)
426f5abc 7485{
39d5492a 7486 TCGv_i32 tmp;
03d05e2d 7487 TCGv_i64 val64, extaddr;
42a268c2
RH
7488 TCGLabel *done_label;
7489 TCGLabel *fail_label;
426f5abc
PB
7490
7491 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7492 [addr] = {Rt};
7493 {Rd} = 0;
7494 } else {
7495 {Rd} = 1;
7496 } */
7497 fail_label = gen_new_label();
7498 done_label = gen_new_label();
03d05e2d
PM
7499 extaddr = tcg_temp_new_i64();
7500 tcg_gen_extu_i32_i64(extaddr, addr);
7501 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7502 tcg_temp_free_i64(extaddr);
7503
94ee24e7 7504 tmp = tcg_temp_new_i32();
426f5abc
PB
7505 switch (size) {
7506 case 0:
6ce2faf4 7507 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
426f5abc
PB
7508 break;
7509 case 1:
6ce2faf4 7510 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
426f5abc
PB
7511 break;
7512 case 2:
7513 case 3:
6ce2faf4 7514 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
426f5abc
PB
7515 break;
7516 default:
7517 abort();
7518 }
03d05e2d
PM
7519
7520 val64 = tcg_temp_new_i64();
426f5abc 7521 if (size == 3) {
39d5492a 7522 TCGv_i32 tmp2 = tcg_temp_new_i32();
03d05e2d 7523 TCGv_i32 tmp3 = tcg_temp_new_i32();
426f5abc 7524 tcg_gen_addi_i32(tmp2, addr, 4);
6ce2faf4 7525 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7d1b0095 7526 tcg_temp_free_i32(tmp2);
03d05e2d
PM
7527 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7528 tcg_temp_free_i32(tmp3);
7529 } else {
7530 tcg_gen_extu_i32_i64(val64, tmp);
426f5abc 7531 }
03d05e2d
PM
7532 tcg_temp_free_i32(tmp);
7533
7534 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7535 tcg_temp_free_i64(val64);
7536
426f5abc
PB
7537 tmp = load_reg(s, rt);
7538 switch (size) {
7539 case 0:
6ce2faf4 7540 gen_aa32_st8(tmp, addr, get_mem_index(s));
426f5abc
PB
7541 break;
7542 case 1:
6ce2faf4 7543 gen_aa32_st16(tmp, addr, get_mem_index(s));
426f5abc
PB
7544 break;
7545 case 2:
7546 case 3:
6ce2faf4 7547 gen_aa32_st32(tmp, addr, get_mem_index(s));
426f5abc
PB
7548 break;
7549 default:
7550 abort();
7551 }
94ee24e7 7552 tcg_temp_free_i32(tmp);
426f5abc
PB
7553 if (size == 3) {
7554 tcg_gen_addi_i32(addr, addr, 4);
7555 tmp = load_reg(s, rt2);
6ce2faf4 7556 gen_aa32_st32(tmp, addr, get_mem_index(s));
94ee24e7 7557 tcg_temp_free_i32(tmp);
426f5abc
PB
7558 }
7559 tcg_gen_movi_i32(cpu_R[rd], 0);
7560 tcg_gen_br(done_label);
7561 gen_set_label(fail_label);
7562 tcg_gen_movi_i32(cpu_R[rd], 1);
7563 gen_set_label(done_label);
03d05e2d 7564 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7565}
7566#endif
7567
81465888
PM
7568/* gen_srs:
7569 * @env: CPUARMState
7570 * @s: DisasContext
7571 * @mode: mode field from insn (which stack to store to)
7572 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7573 * @writeback: true if writeback bit set
7574 *
7575 * Generate code for the SRS (Store Return State) insn.
7576 */
7577static void gen_srs(DisasContext *s,
7578 uint32_t mode, uint32_t amode, bool writeback)
7579{
7580 int32_t offset;
cbc0326b
PM
7581 TCGv_i32 addr, tmp;
7582 bool undef = false;
7583
7584 /* SRS is:
7585 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
7586 * - UNDEFINED in Hyp mode
7587 * - UNPREDICTABLE in User or System mode
7588 * - UNPREDICTABLE if the specified mode is:
7589 * -- not implemented
7590 * -- not a valid mode number
7591 * -- a mode that's at a higher exception level
7592 * -- Monitor, if we are Non-secure
f01377f5 7593 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b
PM
7594 */
7595 if (s->current_el == 1 && !s->ns) {
7596 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
7597 return;
7598 }
7599
7600 if (s->current_el == 0 || s->current_el == 2) {
7601 undef = true;
7602 }
7603
7604 switch (mode) {
7605 case ARM_CPU_MODE_USR:
7606 case ARM_CPU_MODE_FIQ:
7607 case ARM_CPU_MODE_IRQ:
7608 case ARM_CPU_MODE_SVC:
7609 case ARM_CPU_MODE_ABT:
7610 case ARM_CPU_MODE_UND:
7611 case ARM_CPU_MODE_SYS:
7612 break;
7613 case ARM_CPU_MODE_HYP:
7614 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7615 undef = true;
7616 }
7617 break;
7618 case ARM_CPU_MODE_MON:
7619 /* No need to check specifically for "are we non-secure" because
7620 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7621 * so if this isn't EL3 then we must be non-secure.
7622 */
7623 if (s->current_el != 3) {
7624 undef = true;
7625 }
7626 break;
7627 default:
7628 undef = true;
7629 }
7630
7631 if (undef) {
7632 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
7633 default_exception_el(s));
7634 return;
7635 }
7636
7637 addr = tcg_temp_new_i32();
7638 tmp = tcg_const_i32(mode);
f01377f5
PM
7639 /* get_r13_banked() will raise an exception if called from System mode */
7640 gen_set_condexec(s);
7641 gen_set_pc_im(s, s->pc - 4);
81465888
PM
7642 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7643 tcg_temp_free_i32(tmp);
7644 switch (amode) {
7645 case 0: /* DA */
7646 offset = -4;
7647 break;
7648 case 1: /* IA */
7649 offset = 0;
7650 break;
7651 case 2: /* DB */
7652 offset = -8;
7653 break;
7654 case 3: /* IB */
7655 offset = 4;
7656 break;
7657 default:
7658 abort();
7659 }
7660 tcg_gen_addi_i32(addr, addr, offset);
7661 tmp = load_reg(s, 14);
c1197795 7662 gen_aa32_st32(tmp, addr, get_mem_index(s));
5a839c0d 7663 tcg_temp_free_i32(tmp);
81465888
PM
7664 tmp = load_cpu_field(spsr);
7665 tcg_gen_addi_i32(addr, addr, 4);
c1197795 7666 gen_aa32_st32(tmp, addr, get_mem_index(s));
5a839c0d 7667 tcg_temp_free_i32(tmp);
81465888
PM
7668 if (writeback) {
7669 switch (amode) {
7670 case 0:
7671 offset = -8;
7672 break;
7673 case 1:
7674 offset = 4;
7675 break;
7676 case 2:
7677 offset = -4;
7678 break;
7679 case 3:
7680 offset = 0;
7681 break;
7682 default:
7683 abort();
7684 }
7685 tcg_gen_addi_i32(addr, addr, offset);
7686 tmp = tcg_const_i32(mode);
7687 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7688 tcg_temp_free_i32(tmp);
7689 }
7690 tcg_temp_free_i32(addr);
f01377f5 7691 s->is_jmp = DISAS_UPDATE;
81465888
PM
7692}
7693
f4df2210 7694static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 7695{
f4df2210 7696 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
7697 TCGv_i32 tmp;
7698 TCGv_i32 tmp2;
7699 TCGv_i32 tmp3;
7700 TCGv_i32 addr;
a7812ae4 7701 TCGv_i64 tmp64;
9ee6e8bb 7702
9ee6e8bb 7703 /* M variants do not implement ARM mode. */
b53d8923 7704 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 7705 goto illegal_op;
b53d8923 7706 }
9ee6e8bb
PB
7707 cond = insn >> 28;
7708 if (cond == 0xf){
be5e7a76
DES
7709 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7710 * choose to UNDEF. In ARMv5 and above the space is used
7711 * for miscellaneous unconditional instructions.
7712 */
7713 ARCH(5);
7714
9ee6e8bb
PB
7715 /* Unconditional instructions. */
7716 if (((insn >> 25) & 7) == 1) {
7717 /* NEON Data processing. */
d614a513 7718 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7719 goto illegal_op;
d614a513 7720 }
9ee6e8bb 7721
7dcc1f89 7722 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 7723 goto illegal_op;
7dcc1f89 7724 }
9ee6e8bb
PB
7725 return;
7726 }
7727 if ((insn & 0x0f100000) == 0x04000000) {
7728 /* NEON load/store. */
d614a513 7729 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7730 goto illegal_op;
d614a513 7731 }
9ee6e8bb 7732
7dcc1f89 7733 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 7734 goto illegal_op;
7dcc1f89 7735 }
9ee6e8bb
PB
7736 return;
7737 }
6a57f3eb
WN
7738 if ((insn & 0x0f000e10) == 0x0e000a00) {
7739 /* VFP. */
7dcc1f89 7740 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
7741 goto illegal_op;
7742 }
7743 return;
7744 }
3d185e5d
PM
7745 if (((insn & 0x0f30f000) == 0x0510f000) ||
7746 ((insn & 0x0f30f010) == 0x0710f000)) {
7747 if ((insn & (1 << 22)) == 0) {
7748 /* PLDW; v7MP */
d614a513 7749 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7750 goto illegal_op;
7751 }
7752 }
7753 /* Otherwise PLD; v5TE+ */
be5e7a76 7754 ARCH(5TE);
3d185e5d
PM
7755 return;
7756 }
7757 if (((insn & 0x0f70f000) == 0x0450f000) ||
7758 ((insn & 0x0f70f010) == 0x0650f000)) {
7759 ARCH(7);
7760 return; /* PLI; V7 */
7761 }
7762 if (((insn & 0x0f700000) == 0x04100000) ||
7763 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 7764 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7765 goto illegal_op;
7766 }
7767 return; /* v7MP: Unallocated memory hint: must NOP */
7768 }
7769
7770 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
7771 ARCH(6);
7772 /* setend */
10962fd5
PM
7773 if (((insn >> 9) & 1) != s->bswap_code) {
7774 /* Dynamic endianness switching not implemented. */
e0c270d9 7775 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
9ee6e8bb
PB
7776 goto illegal_op;
7777 }
7778 return;
7779 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7780 switch ((insn >> 4) & 0xf) {
7781 case 1: /* clrex */
7782 ARCH(6K);
426f5abc 7783 gen_clrex(s);
9ee6e8bb
PB
7784 return;
7785 case 4: /* dsb */
7786 case 5: /* dmb */
9ee6e8bb
PB
7787 ARCH(7);
7788 /* We don't emulate caches so these are a no-op. */
7789 return;
6df99dec
SS
7790 case 6: /* isb */
7791 /* We need to break the TB after this insn to execute
7792 * self-modifying code correctly and also to take
7793 * any pending interrupts immediately.
7794 */
7795 gen_lookup_tb(s);
7796 return;
9ee6e8bb
PB
7797 default:
7798 goto illegal_op;
7799 }
7800 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7801 /* srs */
81465888
PM
7802 ARCH(6);
7803 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 7804 return;
ea825eee 7805 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 7806 /* rfe */
c67b6b71 7807 int32_t offset;
9ee6e8bb
PB
7808 if (IS_USER(s))
7809 goto illegal_op;
7810 ARCH(6);
7811 rn = (insn >> 16) & 0xf;
b0109805 7812 addr = load_reg(s, rn);
9ee6e8bb
PB
7813 i = (insn >> 23) & 3;
7814 switch (i) {
b0109805 7815 case 0: offset = -4; break; /* DA */
c67b6b71
FN
7816 case 1: offset = 0; break; /* IA */
7817 case 2: offset = -8; break; /* DB */
b0109805 7818 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
7819 default: abort();
7820 }
7821 if (offset)
b0109805
PB
7822 tcg_gen_addi_i32(addr, addr, offset);
7823 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 7824 tmp = tcg_temp_new_i32();
6ce2faf4 7825 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 7826 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 7827 tmp2 = tcg_temp_new_i32();
6ce2faf4 7828 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
7829 if (insn & (1 << 21)) {
7830 /* Base writeback. */
7831 switch (i) {
b0109805 7832 case 0: offset = -8; break;
c67b6b71
FN
7833 case 1: offset = 4; break;
7834 case 2: offset = -4; break;
b0109805 7835 case 3: offset = 0; break;
9ee6e8bb
PB
7836 default: abort();
7837 }
7838 if (offset)
b0109805
PB
7839 tcg_gen_addi_i32(addr, addr, offset);
7840 store_reg(s, rn, addr);
7841 } else {
7d1b0095 7842 tcg_temp_free_i32(addr);
9ee6e8bb 7843 }
b0109805 7844 gen_rfe(s, tmp, tmp2);
c67b6b71 7845 return;
9ee6e8bb
PB
7846 } else if ((insn & 0x0e000000) == 0x0a000000) {
7847 /* branch link and change to thumb (blx <offset>) */
7848 int32_t offset;
7849
7850 val = (uint32_t)s->pc;
7d1b0095 7851 tmp = tcg_temp_new_i32();
d9ba4830
PB
7852 tcg_gen_movi_i32(tmp, val);
7853 store_reg(s, 14, tmp);
9ee6e8bb
PB
7854 /* Sign-extend the 24-bit offset */
7855 offset = (((int32_t)insn) << 8) >> 8;
7856 /* offset * 4 + bit24 * 2 + (thumb bit) */
7857 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7858 /* pipeline offset */
7859 val += 4;
be5e7a76 7860 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 7861 gen_bx_im(s, val);
9ee6e8bb
PB
7862 return;
7863 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 7864 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 7865 /* iWMMXt register transfer. */
c0f4af17 7866 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 7867 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 7868 return;
c0f4af17
PM
7869 }
7870 }
9ee6e8bb
PB
7871 }
7872 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7873 /* Coprocessor double register transfer. */
be5e7a76 7874 ARCH(5TE);
9ee6e8bb
PB
7875 } else if ((insn & 0x0f000010) == 0x0e000010) {
7876 /* Additional coprocessor register transfer. */
7997d92f 7877 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
7878 uint32_t mask;
7879 uint32_t val;
7880 /* cps (privileged) */
7881 if (IS_USER(s))
7882 return;
7883 mask = val = 0;
7884 if (insn & (1 << 19)) {
7885 if (insn & (1 << 8))
7886 mask |= CPSR_A;
7887 if (insn & (1 << 7))
7888 mask |= CPSR_I;
7889 if (insn & (1 << 6))
7890 mask |= CPSR_F;
7891 if (insn & (1 << 18))
7892 val |= mask;
7893 }
7997d92f 7894 if (insn & (1 << 17)) {
9ee6e8bb
PB
7895 mask |= CPSR_M;
7896 val |= (insn & 0x1f);
7897 }
7898 if (mask) {
2fbac54b 7899 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
7900 }
7901 return;
7902 }
7903 goto illegal_op;
7904 }
7905 if (cond != 0xe) {
7906 /* if not always execute, we generate a conditional jump to
7907 next instruction */
7908 s->condlabel = gen_new_label();
39fb730a 7909 arm_gen_test_cc(cond ^ 1, s->condlabel);
9ee6e8bb
PB
7910 s->condjmp = 1;
7911 }
7912 if ((insn & 0x0f900000) == 0x03000000) {
7913 if ((insn & (1 << 21)) == 0) {
7914 ARCH(6T2);
7915 rd = (insn >> 12) & 0xf;
7916 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7917 if ((insn & (1 << 22)) == 0) {
7918 /* MOVW */
7d1b0095 7919 tmp = tcg_temp_new_i32();
5e3f878a 7920 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
7921 } else {
7922 /* MOVT */
5e3f878a 7923 tmp = load_reg(s, rd);
86831435 7924 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 7925 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 7926 }
5e3f878a 7927 store_reg(s, rd, tmp);
9ee6e8bb
PB
7928 } else {
7929 if (((insn >> 12) & 0xf) != 0xf)
7930 goto illegal_op;
7931 if (((insn >> 16) & 0xf) == 0) {
7932 gen_nop_hint(s, insn & 0xff);
7933 } else {
7934 /* CPSR = immediate */
7935 val = insn & 0xff;
7936 shift = ((insn >> 8) & 0xf) * 2;
7937 if (shift)
7938 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 7939 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
7940 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
7941 i, val)) {
9ee6e8bb 7942 goto illegal_op;
7dcc1f89 7943 }
9ee6e8bb
PB
7944 }
7945 }
7946 } else if ((insn & 0x0f900000) == 0x01000000
7947 && (insn & 0x00000090) != 0x00000090) {
7948 /* miscellaneous instructions */
7949 op1 = (insn >> 21) & 3;
7950 sh = (insn >> 4) & 0xf;
7951 rm = insn & 0xf;
7952 switch (sh) {
7953 case 0x0: /* move program status register */
7954 if (op1 & 1) {
7955 /* PSR = reg */
2fbac54b 7956 tmp = load_reg(s, rm);
9ee6e8bb 7957 i = ((op1 & 2) != 0);
7dcc1f89 7958 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
7959 goto illegal_op;
7960 } else {
7961 /* reg = PSR */
7962 rd = (insn >> 12) & 0xf;
7963 if (op1 & 2) {
7964 if (IS_USER(s))
7965 goto illegal_op;
d9ba4830 7966 tmp = load_cpu_field(spsr);
9ee6e8bb 7967 } else {
7d1b0095 7968 tmp = tcg_temp_new_i32();
9ef39277 7969 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 7970 }
d9ba4830 7971 store_reg(s, rd, tmp);
9ee6e8bb
PB
7972 }
7973 break;
7974 case 0x1:
7975 if (op1 == 1) {
7976 /* branch/exchange thumb (bx). */
be5e7a76 7977 ARCH(4T);
d9ba4830
PB
7978 tmp = load_reg(s, rm);
7979 gen_bx(s, tmp);
9ee6e8bb
PB
7980 } else if (op1 == 3) {
7981 /* clz */
be5e7a76 7982 ARCH(5);
9ee6e8bb 7983 rd = (insn >> 12) & 0xf;
1497c961
PB
7984 tmp = load_reg(s, rm);
7985 gen_helper_clz(tmp, tmp);
7986 store_reg(s, rd, tmp);
9ee6e8bb
PB
7987 } else {
7988 goto illegal_op;
7989 }
7990 break;
7991 case 0x2:
7992 if (op1 == 1) {
7993 ARCH(5J); /* bxj */
7994 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
7995 tmp = load_reg(s, rm);
7996 gen_bx(s, tmp);
9ee6e8bb
PB
7997 } else {
7998 goto illegal_op;
7999 }
8000 break;
8001 case 0x3:
8002 if (op1 != 1)
8003 goto illegal_op;
8004
be5e7a76 8005 ARCH(5);
9ee6e8bb 8006 /* branch link/exchange thumb (blx) */
d9ba4830 8007 tmp = load_reg(s, rm);
7d1b0095 8008 tmp2 = tcg_temp_new_i32();
d9ba4830
PB
8009 tcg_gen_movi_i32(tmp2, s->pc);
8010 store_reg(s, 14, tmp2);
8011 gen_bx(s, tmp);
9ee6e8bb 8012 break;
eb0ecd5a
WN
8013 case 0x4:
8014 {
8015 /* crc32/crc32c */
8016 uint32_t c = extract32(insn, 8, 4);
8017
8018 /* Check this CPU supports ARMv8 CRC instructions.
8019 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8020 * Bits 8, 10 and 11 should be zero.
8021 */
d614a513 8022 if (!arm_dc_feature(s, ARM_FEATURE_CRC) || op1 == 0x3 ||
eb0ecd5a
WN
8023 (c & 0xd) != 0) {
8024 goto illegal_op;
8025 }
8026
8027 rn = extract32(insn, 16, 4);
8028 rd = extract32(insn, 12, 4);
8029
8030 tmp = load_reg(s, rn);
8031 tmp2 = load_reg(s, rm);
aa633469
PM
8032 if (op1 == 0) {
8033 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8034 } else if (op1 == 1) {
8035 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8036 }
eb0ecd5a
WN
8037 tmp3 = tcg_const_i32(1 << op1);
8038 if (c & 0x2) {
8039 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8040 } else {
8041 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8042 }
8043 tcg_temp_free_i32(tmp2);
8044 tcg_temp_free_i32(tmp3);
8045 store_reg(s, rd, tmp);
8046 break;
8047 }
9ee6e8bb 8048 case 0x5: /* saturating add/subtract */
be5e7a76 8049 ARCH(5TE);
9ee6e8bb
PB
8050 rd = (insn >> 12) & 0xf;
8051 rn = (insn >> 16) & 0xf;
b40d0353 8052 tmp = load_reg(s, rm);
5e3f878a 8053 tmp2 = load_reg(s, rn);
9ee6e8bb 8054 if (op1 & 2)
9ef39277 8055 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9ee6e8bb 8056 if (op1 & 1)
9ef39277 8057 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 8058 else
9ef39277 8059 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 8060 tcg_temp_free_i32(tmp2);
5e3f878a 8061 store_reg(s, rd, tmp);
9ee6e8bb 8062 break;
49e14940 8063 case 7:
d4a2dc67
PM
8064 {
8065 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e
PM
8066 switch (op1) {
8067 case 1:
8068 /* bkpt */
8069 ARCH(5);
8070 gen_exception_insn(s, 4, EXCP_BKPT,
73710361
GB
8071 syn_aa32_bkpt(imm16, false),
8072 default_exception_el(s));
37e6456e
PM
8073 break;
8074 case 2:
8075 /* Hypervisor call (v7) */
8076 ARCH(7);
8077 if (IS_USER(s)) {
8078 goto illegal_op;
8079 }
8080 gen_hvc(s, imm16);
8081 break;
8082 case 3:
8083 /* Secure monitor call (v6+) */
8084 ARCH(6K);
8085 if (IS_USER(s)) {
8086 goto illegal_op;
8087 }
8088 gen_smc(s);
8089 break;
8090 default:
49e14940
AL
8091 goto illegal_op;
8092 }
9ee6e8bb 8093 break;
d4a2dc67 8094 }
9ee6e8bb
PB
8095 case 0x8: /* signed multiply */
8096 case 0xa:
8097 case 0xc:
8098 case 0xe:
be5e7a76 8099 ARCH(5TE);
9ee6e8bb
PB
8100 rs = (insn >> 8) & 0xf;
8101 rn = (insn >> 12) & 0xf;
8102 rd = (insn >> 16) & 0xf;
8103 if (op1 == 1) {
8104 /* (32 * 16) >> 16 */
5e3f878a
PB
8105 tmp = load_reg(s, rm);
8106 tmp2 = load_reg(s, rs);
9ee6e8bb 8107 if (sh & 4)
5e3f878a 8108 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 8109 else
5e3f878a 8110 gen_sxth(tmp2);
a7812ae4
PB
8111 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8112 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 8113 tmp = tcg_temp_new_i32();
ecc7b3aa 8114 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 8115 tcg_temp_free_i64(tmp64);
9ee6e8bb 8116 if ((sh & 2) == 0) {
5e3f878a 8117 tmp2 = load_reg(s, rn);
9ef39277 8118 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8119 tcg_temp_free_i32(tmp2);
9ee6e8bb 8120 }
5e3f878a 8121 store_reg(s, rd, tmp);
9ee6e8bb
PB
8122 } else {
8123 /* 16 * 16 */
5e3f878a
PB
8124 tmp = load_reg(s, rm);
8125 tmp2 = load_reg(s, rs);
8126 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 8127 tcg_temp_free_i32(tmp2);
9ee6e8bb 8128 if (op1 == 2) {
a7812ae4
PB
8129 tmp64 = tcg_temp_new_i64();
8130 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 8131 tcg_temp_free_i32(tmp);
a7812ae4
PB
8132 gen_addq(s, tmp64, rn, rd);
8133 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 8134 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
8135 } else {
8136 if (op1 == 0) {
5e3f878a 8137 tmp2 = load_reg(s, rn);
9ef39277 8138 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8139 tcg_temp_free_i32(tmp2);
9ee6e8bb 8140 }
5e3f878a 8141 store_reg(s, rd, tmp);
9ee6e8bb
PB
8142 }
8143 }
8144 break;
8145 default:
8146 goto illegal_op;
8147 }
8148 } else if (((insn & 0x0e000000) == 0 &&
8149 (insn & 0x00000090) != 0x90) ||
8150 ((insn & 0x0e000000) == (1 << 25))) {
8151 int set_cc, logic_cc, shiftop;
8152
8153 op1 = (insn >> 21) & 0xf;
8154 set_cc = (insn >> 20) & 1;
8155 logic_cc = table_logic_cc[op1] & set_cc;
8156
8157 /* data processing instruction */
8158 if (insn & (1 << 25)) {
8159 /* immediate operand */
8160 val = insn & 0xff;
8161 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 8162 if (shift) {
9ee6e8bb 8163 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9 8164 }
7d1b0095 8165 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
8166 tcg_gen_movi_i32(tmp2, val);
8167 if (logic_cc && shift) {
8168 gen_set_CF_bit31(tmp2);
8169 }
9ee6e8bb
PB
8170 } else {
8171 /* register */
8172 rm = (insn) & 0xf;
e9bb4aa9 8173 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8174 shiftop = (insn >> 5) & 3;
8175 if (!(insn & (1 << 4))) {
8176 shift = (insn >> 7) & 0x1f;
e9bb4aa9 8177 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
8178 } else {
8179 rs = (insn >> 8) & 0xf;
8984bd2e 8180 tmp = load_reg(s, rs);
e9bb4aa9 8181 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
8182 }
8183 }
8184 if (op1 != 0x0f && op1 != 0x0d) {
8185 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
8186 tmp = load_reg(s, rn);
8187 } else {
39d5492a 8188 TCGV_UNUSED_I32(tmp);
9ee6e8bb
PB
8189 }
8190 rd = (insn >> 12) & 0xf;
8191 switch(op1) {
8192 case 0x00:
e9bb4aa9
JR
8193 tcg_gen_and_i32(tmp, tmp, tmp2);
8194 if (logic_cc) {
8195 gen_logic_CC(tmp);
8196 }
7dcc1f89 8197 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8198 break;
8199 case 0x01:
e9bb4aa9
JR
8200 tcg_gen_xor_i32(tmp, tmp, tmp2);
8201 if (logic_cc) {
8202 gen_logic_CC(tmp);
8203 }
7dcc1f89 8204 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8205 break;
8206 case 0x02:
8207 if (set_cc && rd == 15) {
8208 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 8209 if (IS_USER(s)) {
9ee6e8bb 8210 goto illegal_op;
e9bb4aa9 8211 }
72485ec4 8212 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 8213 gen_exception_return(s, tmp);
9ee6e8bb 8214 } else {
e9bb4aa9 8215 if (set_cc) {
72485ec4 8216 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8217 } else {
8218 tcg_gen_sub_i32(tmp, tmp, tmp2);
8219 }
7dcc1f89 8220 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8221 }
8222 break;
8223 case 0x03:
e9bb4aa9 8224 if (set_cc) {
72485ec4 8225 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8226 } else {
8227 tcg_gen_sub_i32(tmp, tmp2, tmp);
8228 }
7dcc1f89 8229 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8230 break;
8231 case 0x04:
e9bb4aa9 8232 if (set_cc) {
72485ec4 8233 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8234 } else {
8235 tcg_gen_add_i32(tmp, tmp, tmp2);
8236 }
7dcc1f89 8237 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8238 break;
8239 case 0x05:
e9bb4aa9 8240 if (set_cc) {
49b4c31e 8241 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8242 } else {
8243 gen_add_carry(tmp, tmp, tmp2);
8244 }
7dcc1f89 8245 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8246 break;
8247 case 0x06:
e9bb4aa9 8248 if (set_cc) {
2de68a49 8249 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8250 } else {
8251 gen_sub_carry(tmp, tmp, tmp2);
8252 }
7dcc1f89 8253 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8254 break;
8255 case 0x07:
e9bb4aa9 8256 if (set_cc) {
2de68a49 8257 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8258 } else {
8259 gen_sub_carry(tmp, tmp2, tmp);
8260 }
7dcc1f89 8261 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8262 break;
8263 case 0x08:
8264 if (set_cc) {
e9bb4aa9
JR
8265 tcg_gen_and_i32(tmp, tmp, tmp2);
8266 gen_logic_CC(tmp);
9ee6e8bb 8267 }
7d1b0095 8268 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8269 break;
8270 case 0x09:
8271 if (set_cc) {
e9bb4aa9
JR
8272 tcg_gen_xor_i32(tmp, tmp, tmp2);
8273 gen_logic_CC(tmp);
9ee6e8bb 8274 }
7d1b0095 8275 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8276 break;
8277 case 0x0a:
8278 if (set_cc) {
72485ec4 8279 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 8280 }
7d1b0095 8281 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8282 break;
8283 case 0x0b:
8284 if (set_cc) {
72485ec4 8285 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 8286 }
7d1b0095 8287 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8288 break;
8289 case 0x0c:
e9bb4aa9
JR
8290 tcg_gen_or_i32(tmp, tmp, tmp2);
8291 if (logic_cc) {
8292 gen_logic_CC(tmp);
8293 }
7dcc1f89 8294 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8295 break;
8296 case 0x0d:
8297 if (logic_cc && rd == 15) {
8298 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 8299 if (IS_USER(s)) {
9ee6e8bb 8300 goto illegal_op;
e9bb4aa9
JR
8301 }
8302 gen_exception_return(s, tmp2);
9ee6e8bb 8303 } else {
e9bb4aa9
JR
8304 if (logic_cc) {
8305 gen_logic_CC(tmp2);
8306 }
7dcc1f89 8307 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8308 }
8309 break;
8310 case 0x0e:
f669df27 8311 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
8312 if (logic_cc) {
8313 gen_logic_CC(tmp);
8314 }
7dcc1f89 8315 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8316 break;
8317 default:
8318 case 0x0f:
e9bb4aa9
JR
8319 tcg_gen_not_i32(tmp2, tmp2);
8320 if (logic_cc) {
8321 gen_logic_CC(tmp2);
8322 }
7dcc1f89 8323 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8324 break;
8325 }
e9bb4aa9 8326 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 8327 tcg_temp_free_i32(tmp2);
e9bb4aa9 8328 }
9ee6e8bb
PB
8329 } else {
8330 /* other instructions */
8331 op1 = (insn >> 24) & 0xf;
8332 switch(op1) {
8333 case 0x0:
8334 case 0x1:
8335 /* multiplies, extra load/stores */
8336 sh = (insn >> 5) & 3;
8337 if (sh == 0) {
8338 if (op1 == 0x0) {
8339 rd = (insn >> 16) & 0xf;
8340 rn = (insn >> 12) & 0xf;
8341 rs = (insn >> 8) & 0xf;
8342 rm = (insn) & 0xf;
8343 op1 = (insn >> 20) & 0xf;
8344 switch (op1) {
8345 case 0: case 1: case 2: case 3: case 6:
8346 /* 32 bit mul */
5e3f878a
PB
8347 tmp = load_reg(s, rs);
8348 tmp2 = load_reg(s, rm);
8349 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 8350 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8351 if (insn & (1 << 22)) {
8352 /* Subtract (mls) */
8353 ARCH(6T2);
5e3f878a
PB
8354 tmp2 = load_reg(s, rn);
8355 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 8356 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8357 } else if (insn & (1 << 21)) {
8358 /* Add */
5e3f878a
PB
8359 tmp2 = load_reg(s, rn);
8360 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8361 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8362 }
8363 if (insn & (1 << 20))
5e3f878a
PB
8364 gen_logic_CC(tmp);
8365 store_reg(s, rd, tmp);
9ee6e8bb 8366 break;
8aac08b1
AJ
8367 case 4:
8368 /* 64 bit mul double accumulate (UMAAL) */
8369 ARCH(6);
8370 tmp = load_reg(s, rs);
8371 tmp2 = load_reg(s, rm);
8372 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8373 gen_addq_lo(s, tmp64, rn);
8374 gen_addq_lo(s, tmp64, rd);
8375 gen_storeq_reg(s, rn, rd, tmp64);
8376 tcg_temp_free_i64(tmp64);
8377 break;
8378 case 8: case 9: case 10: case 11:
8379 case 12: case 13: case 14: case 15:
8380 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
8381 tmp = load_reg(s, rs);
8382 tmp2 = load_reg(s, rm);
8aac08b1 8383 if (insn & (1 << 22)) {
c9f10124 8384 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 8385 } else {
c9f10124 8386 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
8387 }
8388 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
8389 TCGv_i32 al = load_reg(s, rn);
8390 TCGv_i32 ah = load_reg(s, rd);
c9f10124 8391 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
8392 tcg_temp_free_i32(al);
8393 tcg_temp_free_i32(ah);
9ee6e8bb 8394 }
8aac08b1 8395 if (insn & (1 << 20)) {
c9f10124 8396 gen_logicq_cc(tmp, tmp2);
8aac08b1 8397 }
c9f10124
RH
8398 store_reg(s, rn, tmp);
8399 store_reg(s, rd, tmp2);
9ee6e8bb 8400 break;
8aac08b1
AJ
8401 default:
8402 goto illegal_op;
9ee6e8bb
PB
8403 }
8404 } else {
8405 rn = (insn >> 16) & 0xf;
8406 rd = (insn >> 12) & 0xf;
8407 if (insn & (1 << 23)) {
8408 /* load/store exclusive */
2359bf80 8409 int op2 = (insn >> 8) & 3;
86753403 8410 op1 = (insn >> 21) & 0x3;
2359bf80
MR
8411
8412 switch (op2) {
8413 case 0: /* lda/stl */
8414 if (op1 == 1) {
8415 goto illegal_op;
8416 }
8417 ARCH(8);
8418 break;
8419 case 1: /* reserved */
8420 goto illegal_op;
8421 case 2: /* ldaex/stlex */
8422 ARCH(8);
8423 break;
8424 case 3: /* ldrex/strex */
8425 if (op1) {
8426 ARCH(6K);
8427 } else {
8428 ARCH(6);
8429 }
8430 break;
8431 }
8432
3174f8e9 8433 addr = tcg_temp_local_new_i32();
98a46317 8434 load_reg_var(s, addr, rn);
2359bf80
MR
8435
8436 /* Since the emulation does not have barriers,
8437 the acquire/release semantics need no special
8438 handling */
8439 if (op2 == 0) {
8440 if (insn & (1 << 20)) {
8441 tmp = tcg_temp_new_i32();
8442 switch (op1) {
8443 case 0: /* lda */
6ce2faf4 8444 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
2359bf80
MR
8445 break;
8446 case 2: /* ldab */
6ce2faf4 8447 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
2359bf80
MR
8448 break;
8449 case 3: /* ldah */
6ce2faf4 8450 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
2359bf80
MR
8451 break;
8452 default:
8453 abort();
8454 }
8455 store_reg(s, rd, tmp);
8456 } else {
8457 rm = insn & 0xf;
8458 tmp = load_reg(s, rm);
8459 switch (op1) {
8460 case 0: /* stl */
6ce2faf4 8461 gen_aa32_st32(tmp, addr, get_mem_index(s));
2359bf80
MR
8462 break;
8463 case 2: /* stlb */
6ce2faf4 8464 gen_aa32_st8(tmp, addr, get_mem_index(s));
2359bf80
MR
8465 break;
8466 case 3: /* stlh */
6ce2faf4 8467 gen_aa32_st16(tmp, addr, get_mem_index(s));
2359bf80
MR
8468 break;
8469 default:
8470 abort();
8471 }
8472 tcg_temp_free_i32(tmp);
8473 }
8474 } else if (insn & (1 << 20)) {
86753403
PB
8475 switch (op1) {
8476 case 0: /* ldrex */
426f5abc 8477 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
8478 break;
8479 case 1: /* ldrexd */
426f5abc 8480 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
8481 break;
8482 case 2: /* ldrexb */
426f5abc 8483 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
8484 break;
8485 case 3: /* ldrexh */
426f5abc 8486 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
8487 break;
8488 default:
8489 abort();
8490 }
9ee6e8bb
PB
8491 } else {
8492 rm = insn & 0xf;
86753403
PB
8493 switch (op1) {
8494 case 0: /* strex */
426f5abc 8495 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
8496 break;
8497 case 1: /* strexd */
502e64fe 8498 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
8499 break;
8500 case 2: /* strexb */
426f5abc 8501 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
8502 break;
8503 case 3: /* strexh */
426f5abc 8504 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
8505 break;
8506 default:
8507 abort();
8508 }
9ee6e8bb 8509 }
39d5492a 8510 tcg_temp_free_i32(addr);
9ee6e8bb
PB
8511 } else {
8512 /* SWP instruction */
8513 rm = (insn) & 0xf;
8514
8984bd2e
PB
8515 /* ??? This is not really atomic. However we know
8516 we never have multiple CPUs running in parallel,
8517 so it is good enough. */
8518 addr = load_reg(s, rn);
8519 tmp = load_reg(s, rm);
5a839c0d 8520 tmp2 = tcg_temp_new_i32();
9ee6e8bb 8521 if (insn & (1 << 22)) {
6ce2faf4
EI
8522 gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
8523 gen_aa32_st8(tmp, addr, get_mem_index(s));
9ee6e8bb 8524 } else {
6ce2faf4
EI
8525 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
8526 gen_aa32_st32(tmp, addr, get_mem_index(s));
9ee6e8bb 8527 }
5a839c0d 8528 tcg_temp_free_i32(tmp);
7d1b0095 8529 tcg_temp_free_i32(addr);
8984bd2e 8530 store_reg(s, rd, tmp2);
9ee6e8bb
PB
8531 }
8532 }
8533 } else {
8534 int address_offset;
3960c336
PM
8535 bool load = insn & (1 << 20);
8536 bool doubleword = false;
9ee6e8bb
PB
8537 /* Misc load/store */
8538 rn = (insn >> 16) & 0xf;
8539 rd = (insn >> 12) & 0xf;
3960c336
PM
8540
8541 if (!load && (sh & 2)) {
8542 /* doubleword */
8543 ARCH(5TE);
8544 if (rd & 1) {
8545 /* UNPREDICTABLE; we choose to UNDEF */
8546 goto illegal_op;
8547 }
8548 load = (sh & 1) == 0;
8549 doubleword = true;
8550 }
8551
b0109805 8552 addr = load_reg(s, rn);
9ee6e8bb 8553 if (insn & (1 << 24))
b0109805 8554 gen_add_datah_offset(s, insn, 0, addr);
9ee6e8bb 8555 address_offset = 0;
3960c336
PM
8556
8557 if (doubleword) {
8558 if (!load) {
9ee6e8bb 8559 /* store */
b0109805 8560 tmp = load_reg(s, rd);
6ce2faf4 8561 gen_aa32_st32(tmp, addr, get_mem_index(s));
5a839c0d 8562 tcg_temp_free_i32(tmp);
b0109805
PB
8563 tcg_gen_addi_i32(addr, addr, 4);
8564 tmp = load_reg(s, rd + 1);
6ce2faf4 8565 gen_aa32_st32(tmp, addr, get_mem_index(s));
5a839c0d 8566 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8567 } else {
8568 /* load */
5a839c0d 8569 tmp = tcg_temp_new_i32();
6ce2faf4 8570 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805
PB
8571 store_reg(s, rd, tmp);
8572 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8573 tmp = tcg_temp_new_i32();
6ce2faf4 8574 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9ee6e8bb 8575 rd++;
9ee6e8bb
PB
8576 }
8577 address_offset = -4;
3960c336
PM
8578 } else if (load) {
8579 /* load */
8580 tmp = tcg_temp_new_i32();
8581 switch (sh) {
8582 case 1:
8583 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8584 break;
8585 case 2:
8586 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
8587 break;
8588 default:
8589 case 3:
8590 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
8591 break;
8592 }
9ee6e8bb
PB
8593 } else {
8594 /* store */
b0109805 8595 tmp = load_reg(s, rd);
6ce2faf4 8596 gen_aa32_st16(tmp, addr, get_mem_index(s));
5a839c0d 8597 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8598 }
8599 /* Perform base writeback before the loaded value to
8600 ensure correct behavior with overlapping index registers.
b6af0975 8601 ldrd with base writeback is undefined if the
9ee6e8bb
PB
8602 destination and index registers overlap. */
8603 if (!(insn & (1 << 24))) {
b0109805
PB
8604 gen_add_datah_offset(s, insn, address_offset, addr);
8605 store_reg(s, rn, addr);
9ee6e8bb
PB
8606 } else if (insn & (1 << 21)) {
8607 if (address_offset)
b0109805
PB
8608 tcg_gen_addi_i32(addr, addr, address_offset);
8609 store_reg(s, rn, addr);
8610 } else {
7d1b0095 8611 tcg_temp_free_i32(addr);
9ee6e8bb
PB
8612 }
8613 if (load) {
8614 /* Complete the load. */
b0109805 8615 store_reg(s, rd, tmp);
9ee6e8bb
PB
8616 }
8617 }
8618 break;
8619 case 0x4:
8620 case 0x5:
8621 goto do_ldst;
8622 case 0x6:
8623 case 0x7:
8624 if (insn & (1 << 4)) {
8625 ARCH(6);
8626 /* Armv6 Media instructions. */
8627 rm = insn & 0xf;
8628 rn = (insn >> 16) & 0xf;
2c0262af 8629 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
8630 rs = (insn >> 8) & 0xf;
8631 switch ((insn >> 23) & 3) {
8632 case 0: /* Parallel add/subtract. */
8633 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
8634 tmp = load_reg(s, rn);
8635 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8636 sh = (insn >> 5) & 7;
8637 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8638 goto illegal_op;
6ddbc6e4 8639 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 8640 tcg_temp_free_i32(tmp2);
6ddbc6e4 8641 store_reg(s, rd, tmp);
9ee6e8bb
PB
8642 break;
8643 case 1:
8644 if ((insn & 0x00700020) == 0) {
6c95676b 8645 /* Halfword pack. */
3670669c
PB
8646 tmp = load_reg(s, rn);
8647 tmp2 = load_reg(s, rm);
9ee6e8bb 8648 shift = (insn >> 7) & 0x1f;
3670669c
PB
8649 if (insn & (1 << 6)) {
8650 /* pkhtb */
22478e79
AZ
8651 if (shift == 0)
8652 shift = 31;
8653 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 8654 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 8655 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
8656 } else {
8657 /* pkhbt */
22478e79
AZ
8658 if (shift)
8659 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 8660 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
8661 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8662 }
8663 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 8664 tcg_temp_free_i32(tmp2);
3670669c 8665 store_reg(s, rd, tmp);
9ee6e8bb
PB
8666 } else if ((insn & 0x00200020) == 0x00200000) {
8667 /* [us]sat */
6ddbc6e4 8668 tmp = load_reg(s, rm);
9ee6e8bb
PB
8669 shift = (insn >> 7) & 0x1f;
8670 if (insn & (1 << 6)) {
8671 if (shift == 0)
8672 shift = 31;
6ddbc6e4 8673 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 8674 } else {
6ddbc6e4 8675 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
8676 }
8677 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8678 tmp2 = tcg_const_i32(sh);
8679 if (insn & (1 << 22))
9ef39277 8680 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 8681 else
9ef39277 8682 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 8683 tcg_temp_free_i32(tmp2);
6ddbc6e4 8684 store_reg(s, rd, tmp);
9ee6e8bb
PB
8685 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8686 /* [us]sat16 */
6ddbc6e4 8687 tmp = load_reg(s, rm);
9ee6e8bb 8688 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8689 tmp2 = tcg_const_i32(sh);
8690 if (insn & (1 << 22))
9ef39277 8691 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8692 else
9ef39277 8693 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8694 tcg_temp_free_i32(tmp2);
6ddbc6e4 8695 store_reg(s, rd, tmp);
9ee6e8bb
PB
8696 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8697 /* Select bytes. */
6ddbc6e4
PB
8698 tmp = load_reg(s, rn);
8699 tmp2 = load_reg(s, rm);
7d1b0095 8700 tmp3 = tcg_temp_new_i32();
0ecb72a5 8701 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 8702 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
8703 tcg_temp_free_i32(tmp3);
8704 tcg_temp_free_i32(tmp2);
6ddbc6e4 8705 store_reg(s, rd, tmp);
9ee6e8bb 8706 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 8707 tmp = load_reg(s, rm);
9ee6e8bb 8708 shift = (insn >> 10) & 3;
1301f322 8709 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
8710 rotate, a shift is sufficient. */
8711 if (shift != 0)
f669df27 8712 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
8713 op1 = (insn >> 20) & 7;
8714 switch (op1) {
5e3f878a
PB
8715 case 0: gen_sxtb16(tmp); break;
8716 case 2: gen_sxtb(tmp); break;
8717 case 3: gen_sxth(tmp); break;
8718 case 4: gen_uxtb16(tmp); break;
8719 case 6: gen_uxtb(tmp); break;
8720 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
8721 default: goto illegal_op;
8722 }
8723 if (rn != 15) {
5e3f878a 8724 tmp2 = load_reg(s, rn);
9ee6e8bb 8725 if ((op1 & 3) == 0) {
5e3f878a 8726 gen_add16(tmp, tmp2);
9ee6e8bb 8727 } else {
5e3f878a 8728 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8729 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8730 }
8731 }
6c95676b 8732 store_reg(s, rd, tmp);
9ee6e8bb
PB
8733 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8734 /* rev */
b0109805 8735 tmp = load_reg(s, rm);
9ee6e8bb
PB
8736 if (insn & (1 << 22)) {
8737 if (insn & (1 << 7)) {
b0109805 8738 gen_revsh(tmp);
9ee6e8bb
PB
8739 } else {
8740 ARCH(6T2);
b0109805 8741 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
8742 }
8743 } else {
8744 if (insn & (1 << 7))
b0109805 8745 gen_rev16(tmp);
9ee6e8bb 8746 else
66896cb8 8747 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 8748 }
b0109805 8749 store_reg(s, rd, tmp);
9ee6e8bb
PB
8750 } else {
8751 goto illegal_op;
8752 }
8753 break;
8754 case 2: /* Multiplies (Type 3). */
41e9564d
PM
8755 switch ((insn >> 20) & 0x7) {
8756 case 5:
8757 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8758 /* op2 not 00x or 11x : UNDEF */
8759 goto illegal_op;
8760 }
838fa72d
AJ
8761 /* Signed multiply most significant [accumulate].
8762 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
8763 tmp = load_reg(s, rm);
8764 tmp2 = load_reg(s, rs);
a7812ae4 8765 tmp64 = gen_muls_i64_i32(tmp, tmp2);
838fa72d 8766
955a7dd5 8767 if (rd != 15) {
838fa72d 8768 tmp = load_reg(s, rd);
9ee6e8bb 8769 if (insn & (1 << 6)) {
838fa72d 8770 tmp64 = gen_subq_msw(tmp64, tmp);
9ee6e8bb 8771 } else {
838fa72d 8772 tmp64 = gen_addq_msw(tmp64, tmp);
9ee6e8bb
PB
8773 }
8774 }
838fa72d
AJ
8775 if (insn & (1 << 5)) {
8776 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8777 }
8778 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 8779 tmp = tcg_temp_new_i32();
ecc7b3aa 8780 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 8781 tcg_temp_free_i64(tmp64);
955a7dd5 8782 store_reg(s, rn, tmp);
41e9564d
PM
8783 break;
8784 case 0:
8785 case 4:
8786 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8787 if (insn & (1 << 7)) {
8788 goto illegal_op;
8789 }
8790 tmp = load_reg(s, rm);
8791 tmp2 = load_reg(s, rs);
9ee6e8bb 8792 if (insn & (1 << 5))
5e3f878a
PB
8793 gen_swap_half(tmp2);
8794 gen_smul_dual(tmp, tmp2);
9ee6e8bb 8795 if (insn & (1 << 22)) {
5e3f878a 8796 /* smlald, smlsld */
33bbd75a
PC
8797 TCGv_i64 tmp64_2;
8798
a7812ae4 8799 tmp64 = tcg_temp_new_i64();
33bbd75a 8800 tmp64_2 = tcg_temp_new_i64();
a7812ae4 8801 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 8802 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 8803 tcg_temp_free_i32(tmp);
33bbd75a
PC
8804 tcg_temp_free_i32(tmp2);
8805 if (insn & (1 << 6)) {
8806 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8807 } else {
8808 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8809 }
8810 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
8811 gen_addq(s, tmp64, rd, rn);
8812 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 8813 tcg_temp_free_i64(tmp64);
9ee6e8bb 8814 } else {
5e3f878a 8815 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
8816 if (insn & (1 << 6)) {
8817 /* This subtraction cannot overflow. */
8818 tcg_gen_sub_i32(tmp, tmp, tmp2);
8819 } else {
8820 /* This addition cannot overflow 32 bits;
8821 * however it may overflow considered as a
8822 * signed operation, in which case we must set
8823 * the Q flag.
8824 */
8825 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8826 }
8827 tcg_temp_free_i32(tmp2);
22478e79 8828 if (rd != 15)
9ee6e8bb 8829 {
22478e79 8830 tmp2 = load_reg(s, rd);
9ef39277 8831 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8832 tcg_temp_free_i32(tmp2);
9ee6e8bb 8833 }
22478e79 8834 store_reg(s, rn, tmp);
9ee6e8bb 8835 }
41e9564d 8836 break;
b8b8ea05
PM
8837 case 1:
8838 case 3:
8839 /* SDIV, UDIV */
d614a513 8840 if (!arm_dc_feature(s, ARM_FEATURE_ARM_DIV)) {
b8b8ea05
PM
8841 goto illegal_op;
8842 }
8843 if (((insn >> 5) & 7) || (rd != 15)) {
8844 goto illegal_op;
8845 }
8846 tmp = load_reg(s, rm);
8847 tmp2 = load_reg(s, rs);
8848 if (insn & (1 << 21)) {
8849 gen_helper_udiv(tmp, tmp, tmp2);
8850 } else {
8851 gen_helper_sdiv(tmp, tmp, tmp2);
8852 }
8853 tcg_temp_free_i32(tmp2);
8854 store_reg(s, rn, tmp);
8855 break;
41e9564d
PM
8856 default:
8857 goto illegal_op;
9ee6e8bb
PB
8858 }
8859 break;
8860 case 3:
8861 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8862 switch (op1) {
8863 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
8864 ARCH(6);
8865 tmp = load_reg(s, rm);
8866 tmp2 = load_reg(s, rs);
8867 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 8868 tcg_temp_free_i32(tmp2);
ded9d295
AZ
8869 if (rd != 15) {
8870 tmp2 = load_reg(s, rd);
6ddbc6e4 8871 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8872 tcg_temp_free_i32(tmp2);
9ee6e8bb 8873 }
ded9d295 8874 store_reg(s, rn, tmp);
9ee6e8bb
PB
8875 break;
8876 case 0x20: case 0x24: case 0x28: case 0x2c:
8877 /* Bitfield insert/clear. */
8878 ARCH(6T2);
8879 shift = (insn >> 7) & 0x1f;
8880 i = (insn >> 16) & 0x1f;
45140a57
KB
8881 if (i < shift) {
8882 /* UNPREDICTABLE; we choose to UNDEF */
8883 goto illegal_op;
8884 }
9ee6e8bb
PB
8885 i = i + 1 - shift;
8886 if (rm == 15) {
7d1b0095 8887 tmp = tcg_temp_new_i32();
5e3f878a 8888 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 8889 } else {
5e3f878a 8890 tmp = load_reg(s, rm);
9ee6e8bb
PB
8891 }
8892 if (i != 32) {
5e3f878a 8893 tmp2 = load_reg(s, rd);
d593c48e 8894 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 8895 tcg_temp_free_i32(tmp2);
9ee6e8bb 8896 }
5e3f878a 8897 store_reg(s, rd, tmp);
9ee6e8bb
PB
8898 break;
8899 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8900 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 8901 ARCH(6T2);
5e3f878a 8902 tmp = load_reg(s, rm);
9ee6e8bb
PB
8903 shift = (insn >> 7) & 0x1f;
8904 i = ((insn >> 16) & 0x1f) + 1;
8905 if (shift + i > 32)
8906 goto illegal_op;
8907 if (i < 32) {
8908 if (op1 & 0x20) {
5e3f878a 8909 gen_ubfx(tmp, shift, (1u << i) - 1);
9ee6e8bb 8910 } else {
5e3f878a 8911 gen_sbfx(tmp, shift, i);
9ee6e8bb
PB
8912 }
8913 }
5e3f878a 8914 store_reg(s, rd, tmp);
9ee6e8bb
PB
8915 break;
8916 default:
8917 goto illegal_op;
8918 }
8919 break;
8920 }
8921 break;
8922 }
8923 do_ldst:
8924 /* Check for undefined extension instructions
8925 * per the ARM Bible IE:
8926 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8927 */
8928 sh = (0xf << 20) | (0xf << 4);
8929 if (op1 == 0x7 && ((insn & sh) == sh))
8930 {
8931 goto illegal_op;
8932 }
8933 /* load/store byte/word */
8934 rn = (insn >> 16) & 0xf;
8935 rd = (insn >> 12) & 0xf;
b0109805 8936 tmp2 = load_reg(s, rn);
a99caa48
PM
8937 if ((insn & 0x01200000) == 0x00200000) {
8938 /* ldrt/strt */
579d21cc 8939 i = get_a32_user_mem_index(s);
a99caa48
PM
8940 } else {
8941 i = get_mem_index(s);
8942 }
9ee6e8bb 8943 if (insn & (1 << 24))
b0109805 8944 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
8945 if (insn & (1 << 20)) {
8946 /* load */
5a839c0d 8947 tmp = tcg_temp_new_i32();
9ee6e8bb 8948 if (insn & (1 << 22)) {
08307563 8949 gen_aa32_ld8u(tmp, tmp2, i);
9ee6e8bb 8950 } else {
08307563 8951 gen_aa32_ld32u(tmp, tmp2, i);
9ee6e8bb 8952 }
9ee6e8bb
PB
8953 } else {
8954 /* store */
b0109805 8955 tmp = load_reg(s, rd);
5a839c0d 8956 if (insn & (1 << 22)) {
08307563 8957 gen_aa32_st8(tmp, tmp2, i);
5a839c0d 8958 } else {
08307563 8959 gen_aa32_st32(tmp, tmp2, i);
5a839c0d
PM
8960 }
8961 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8962 }
8963 if (!(insn & (1 << 24))) {
b0109805
PB
8964 gen_add_data_offset(s, insn, tmp2);
8965 store_reg(s, rn, tmp2);
8966 } else if (insn & (1 << 21)) {
8967 store_reg(s, rn, tmp2);
8968 } else {
7d1b0095 8969 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8970 }
8971 if (insn & (1 << 20)) {
8972 /* Complete the load. */
7dcc1f89 8973 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
8974 }
8975 break;
8976 case 0x08:
8977 case 0x09:
8978 {
da3e53dd
PM
8979 int j, n, loaded_base;
8980 bool exc_return = false;
8981 bool is_load = extract32(insn, 20, 1);
8982 bool user = false;
39d5492a 8983 TCGv_i32 loaded_var;
9ee6e8bb
PB
8984 /* load/store multiple words */
8985 /* XXX: store correct base if write back */
9ee6e8bb 8986 if (insn & (1 << 22)) {
da3e53dd 8987 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
8988 if (IS_USER(s))
8989 goto illegal_op; /* only usable in supervisor mode */
8990
da3e53dd
PM
8991 if (is_load && extract32(insn, 15, 1)) {
8992 exc_return = true;
8993 } else {
8994 user = true;
8995 }
9ee6e8bb
PB
8996 }
8997 rn = (insn >> 16) & 0xf;
b0109805 8998 addr = load_reg(s, rn);
9ee6e8bb
PB
8999
9000 /* compute total size */
9001 loaded_base = 0;
39d5492a 9002 TCGV_UNUSED_I32(loaded_var);
9ee6e8bb
PB
9003 n = 0;
9004 for(i=0;i<16;i++) {
9005 if (insn & (1 << i))
9006 n++;
9007 }
9008 /* XXX: test invalid n == 0 case ? */
9009 if (insn & (1 << 23)) {
9010 if (insn & (1 << 24)) {
9011 /* pre increment */
b0109805 9012 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9013 } else {
9014 /* post increment */
9015 }
9016 } else {
9017 if (insn & (1 << 24)) {
9018 /* pre decrement */
b0109805 9019 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9020 } else {
9021 /* post decrement */
9022 if (n != 1)
b0109805 9023 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9024 }
9025 }
9026 j = 0;
9027 for(i=0;i<16;i++) {
9028 if (insn & (1 << i)) {
da3e53dd 9029 if (is_load) {
9ee6e8bb 9030 /* load */
5a839c0d 9031 tmp = tcg_temp_new_i32();
6ce2faf4 9032 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
be5e7a76 9033 if (user) {
b75263d6 9034 tmp2 = tcg_const_i32(i);
1ce94f81 9035 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 9036 tcg_temp_free_i32(tmp2);
7d1b0095 9037 tcg_temp_free_i32(tmp);
9ee6e8bb 9038 } else if (i == rn) {
b0109805 9039 loaded_var = tmp;
9ee6e8bb
PB
9040 loaded_base = 1;
9041 } else {
7dcc1f89 9042 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
9043 }
9044 } else {
9045 /* store */
9046 if (i == 15) {
9047 /* special case: r15 = PC + 8 */
9048 val = (long)s->pc + 4;
7d1b0095 9049 tmp = tcg_temp_new_i32();
b0109805 9050 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 9051 } else if (user) {
7d1b0095 9052 tmp = tcg_temp_new_i32();
b75263d6 9053 tmp2 = tcg_const_i32(i);
9ef39277 9054 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 9055 tcg_temp_free_i32(tmp2);
9ee6e8bb 9056 } else {
b0109805 9057 tmp = load_reg(s, i);
9ee6e8bb 9058 }
6ce2faf4 9059 gen_aa32_st32(tmp, addr, get_mem_index(s));
5a839c0d 9060 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9061 }
9062 j++;
9063 /* no need to add after the last transfer */
9064 if (j != n)
b0109805 9065 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9066 }
9067 }
9068 if (insn & (1 << 21)) {
9069 /* write back */
9070 if (insn & (1 << 23)) {
9071 if (insn & (1 << 24)) {
9072 /* pre increment */
9073 } else {
9074 /* post increment */
b0109805 9075 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9076 }
9077 } else {
9078 if (insn & (1 << 24)) {
9079 /* pre decrement */
9080 if (n != 1)
b0109805 9081 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9082 } else {
9083 /* post decrement */
b0109805 9084 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9085 }
9086 }
b0109805
PB
9087 store_reg(s, rn, addr);
9088 } else {
7d1b0095 9089 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9090 }
9091 if (loaded_base) {
b0109805 9092 store_reg(s, rn, loaded_var);
9ee6e8bb 9093 }
da3e53dd 9094 if (exc_return) {
9ee6e8bb 9095 /* Restore CPSR from SPSR. */
d9ba4830 9096 tmp = load_cpu_field(spsr);
235ea1f5 9097 gen_helper_cpsr_write_eret(cpu_env, tmp);
7d1b0095 9098 tcg_temp_free_i32(tmp);
577bf808 9099 s->is_jmp = DISAS_JUMP;
9ee6e8bb
PB
9100 }
9101 }
9102 break;
9103 case 0xa:
9104 case 0xb:
9105 {
9106 int32_t offset;
9107
9108 /* branch (and link) */
9109 val = (int32_t)s->pc;
9110 if (insn & (1 << 24)) {
7d1b0095 9111 tmp = tcg_temp_new_i32();
5e3f878a
PB
9112 tcg_gen_movi_i32(tmp, val);
9113 store_reg(s, 14, tmp);
9ee6e8bb 9114 }
534df156
PM
9115 offset = sextract32(insn << 2, 0, 26);
9116 val += offset + 4;
9ee6e8bb
PB
9117 gen_jmp(s, val);
9118 }
9119 break;
9120 case 0xc:
9121 case 0xd:
9122 case 0xe:
6a57f3eb
WN
9123 if (((insn >> 8) & 0xe) == 10) {
9124 /* VFP. */
7dcc1f89 9125 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9126 goto illegal_op;
9127 }
7dcc1f89 9128 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 9129 /* Coprocessor. */
9ee6e8bb 9130 goto illegal_op;
6a57f3eb 9131 }
9ee6e8bb
PB
9132 break;
9133 case 0xf:
9134 /* swi */
eaed129d 9135 gen_set_pc_im(s, s->pc);
d4a2dc67 9136 s->svc_imm = extract32(insn, 0, 24);
9ee6e8bb
PB
9137 s->is_jmp = DISAS_SWI;
9138 break;
9139 default:
9140 illegal_op:
73710361
GB
9141 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9142 default_exception_el(s));
9ee6e8bb
PB
9143 break;
9144 }
9145 }
9146}
9147
9148/* Return true if this is a Thumb-2 logical op. */
9149static int
9150thumb2_logic_op(int op)
9151{
9152 return (op < 8);
9153}
9154
9155/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
9156 then set condition code flags based on the result of the operation.
9157 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
9158 to the high bit of T1.
9159 Returns zero if the opcode is valid. */
9160
9161static int
39d5492a
PM
9162gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
9163 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
9164{
9165 int logic_cc;
9166
9167 logic_cc = 0;
9168 switch (op) {
9169 case 0: /* and */
396e467c 9170 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
9171 logic_cc = conds;
9172 break;
9173 case 1: /* bic */
f669df27 9174 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
9175 logic_cc = conds;
9176 break;
9177 case 2: /* orr */
396e467c 9178 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
9179 logic_cc = conds;
9180 break;
9181 case 3: /* orn */
29501f1b 9182 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
9183 logic_cc = conds;
9184 break;
9185 case 4: /* eor */
396e467c 9186 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
9187 logic_cc = conds;
9188 break;
9189 case 8: /* add */
9190 if (conds)
72485ec4 9191 gen_add_CC(t0, t0, t1);
9ee6e8bb 9192 else
396e467c 9193 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
9194 break;
9195 case 10: /* adc */
9196 if (conds)
49b4c31e 9197 gen_adc_CC(t0, t0, t1);
9ee6e8bb 9198 else
396e467c 9199 gen_adc(t0, t1);
9ee6e8bb
PB
9200 break;
9201 case 11: /* sbc */
2de68a49
RH
9202 if (conds) {
9203 gen_sbc_CC(t0, t0, t1);
9204 } else {
396e467c 9205 gen_sub_carry(t0, t0, t1);
2de68a49 9206 }
9ee6e8bb
PB
9207 break;
9208 case 13: /* sub */
9209 if (conds)
72485ec4 9210 gen_sub_CC(t0, t0, t1);
9ee6e8bb 9211 else
396e467c 9212 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
9213 break;
9214 case 14: /* rsb */
9215 if (conds)
72485ec4 9216 gen_sub_CC(t0, t1, t0);
9ee6e8bb 9217 else
396e467c 9218 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
9219 break;
9220 default: /* 5, 6, 7, 9, 12, 15. */
9221 return 1;
9222 }
9223 if (logic_cc) {
396e467c 9224 gen_logic_CC(t0);
9ee6e8bb 9225 if (shifter_out)
396e467c 9226 gen_set_CF_bit31(t1);
9ee6e8bb
PB
9227 }
9228 return 0;
9229}
9230
9231/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
9232 is not legal. */
0ecb72a5 9233static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9ee6e8bb 9234{
b0109805 9235 uint32_t insn, imm, shift, offset;
9ee6e8bb 9236 uint32_t rd, rn, rm, rs;
39d5492a
PM
9237 TCGv_i32 tmp;
9238 TCGv_i32 tmp2;
9239 TCGv_i32 tmp3;
9240 TCGv_i32 addr;
a7812ae4 9241 TCGv_i64 tmp64;
9ee6e8bb
PB
9242 int op;
9243 int shiftop;
9244 int conds;
9245 int logic_cc;
9246
d614a513
PM
9247 if (!(arm_dc_feature(s, ARM_FEATURE_THUMB2)
9248 || arm_dc_feature(s, ARM_FEATURE_M))) {
601d70b9 9249 /* Thumb-1 cores may need to treat bl and blx as a pair of
9ee6e8bb
PB
9250 16-bit instructions to get correct prefetch abort behavior. */
9251 insn = insn_hw1;
9252 if ((insn & (1 << 12)) == 0) {
be5e7a76 9253 ARCH(5);
9ee6e8bb
PB
9254 /* Second half of blx. */
9255 offset = ((insn & 0x7ff) << 1);
d9ba4830
PB
9256 tmp = load_reg(s, 14);
9257 tcg_gen_addi_i32(tmp, tmp, offset);
9258 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9ee6e8bb 9259
7d1b0095 9260 tmp2 = tcg_temp_new_i32();
b0109805 9261 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
9262 store_reg(s, 14, tmp2);
9263 gen_bx(s, tmp);
9ee6e8bb
PB
9264 return 0;
9265 }
9266 if (insn & (1 << 11)) {
9267 /* Second half of bl. */
9268 offset = ((insn & 0x7ff) << 1) | 1;
d9ba4830 9269 tmp = load_reg(s, 14);
6a0d8a1d 9270 tcg_gen_addi_i32(tmp, tmp, offset);
9ee6e8bb 9271
7d1b0095 9272 tmp2 = tcg_temp_new_i32();
b0109805 9273 tcg_gen_movi_i32(tmp2, s->pc | 1);
d9ba4830
PB
9274 store_reg(s, 14, tmp2);
9275 gen_bx(s, tmp);
9ee6e8bb
PB
9276 return 0;
9277 }
9278 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9279 /* Instruction spans a page boundary. Implement it as two
9280 16-bit instructions in case the second half causes an
9281 prefetch abort. */
9282 offset = ((int32_t)insn << 21) >> 9;
396e467c 9283 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9ee6e8bb
PB
9284 return 0;
9285 }
9286 /* Fall through to 32-bit decode. */
9287 }
9288
d31dd73e 9289 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9ee6e8bb
PB
9290 s->pc += 2;
9291 insn |= (uint32_t)insn_hw1 << 16;
9292
9293 if ((insn & 0xf800e800) != 0xf000e800) {
9294 ARCH(6T2);
9295 }
9296
9297 rn = (insn >> 16) & 0xf;
9298 rs = (insn >> 12) & 0xf;
9299 rd = (insn >> 8) & 0xf;
9300 rm = insn & 0xf;
9301 switch ((insn >> 25) & 0xf) {
9302 case 0: case 1: case 2: case 3:
9303 /* 16-bit instructions. Should never happen. */
9304 abort();
9305 case 4:
9306 if (insn & (1 << 22)) {
9307 /* Other load/store, table branch. */
9308 if (insn & 0x01200000) {
9309 /* Load/store doubleword. */
9310 if (rn == 15) {
7d1b0095 9311 addr = tcg_temp_new_i32();
b0109805 9312 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 9313 } else {
b0109805 9314 addr = load_reg(s, rn);
9ee6e8bb
PB
9315 }
9316 offset = (insn & 0xff) * 4;
9317 if ((insn & (1 << 23)) == 0)
9318 offset = -offset;
9319 if (insn & (1 << 24)) {
b0109805 9320 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
9321 offset = 0;
9322 }
9323 if (insn & (1 << 20)) {
9324 /* ldrd */
e2592fad 9325 tmp = tcg_temp_new_i32();
6ce2faf4 9326 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805
PB
9327 store_reg(s, rs, tmp);
9328 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9329 tmp = tcg_temp_new_i32();
6ce2faf4 9330 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 9331 store_reg(s, rd, tmp);
9ee6e8bb
PB
9332 } else {
9333 /* strd */
b0109805 9334 tmp = load_reg(s, rs);
6ce2faf4 9335 gen_aa32_st32(tmp, addr, get_mem_index(s));
e2592fad 9336 tcg_temp_free_i32(tmp);
b0109805
PB
9337 tcg_gen_addi_i32(addr, addr, 4);
9338 tmp = load_reg(s, rd);
6ce2faf4 9339 gen_aa32_st32(tmp, addr, get_mem_index(s));
e2592fad 9340 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9341 }
9342 if (insn & (1 << 21)) {
9343 /* Base writeback. */
9344 if (rn == 15)
9345 goto illegal_op;
b0109805
PB
9346 tcg_gen_addi_i32(addr, addr, offset - 4);
9347 store_reg(s, rn, addr);
9348 } else {
7d1b0095 9349 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9350 }
9351 } else if ((insn & (1 << 23)) == 0) {
9352 /* Load/store exclusive word. */
39d5492a 9353 addr = tcg_temp_local_new_i32();
98a46317 9354 load_reg_var(s, addr, rn);
426f5abc 9355 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 9356 if (insn & (1 << 20)) {
426f5abc 9357 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 9358 } else {
426f5abc 9359 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 9360 }
39d5492a 9361 tcg_temp_free_i32(addr);
2359bf80 9362 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb
PB
9363 /* Table Branch. */
9364 if (rn == 15) {
7d1b0095 9365 addr = tcg_temp_new_i32();
b0109805 9366 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 9367 } else {
b0109805 9368 addr = load_reg(s, rn);
9ee6e8bb 9369 }
b26eefb6 9370 tmp = load_reg(s, rm);
b0109805 9371 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
9372 if (insn & (1 << 4)) {
9373 /* tbh */
b0109805 9374 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 9375 tcg_temp_free_i32(tmp);
e2592fad 9376 tmp = tcg_temp_new_i32();
6ce2faf4 9377 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9ee6e8bb 9378 } else { /* tbb */
7d1b0095 9379 tcg_temp_free_i32(tmp);
e2592fad 9380 tmp = tcg_temp_new_i32();
6ce2faf4 9381 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9ee6e8bb 9382 }
7d1b0095 9383 tcg_temp_free_i32(addr);
b0109805
PB
9384 tcg_gen_shli_i32(tmp, tmp, 1);
9385 tcg_gen_addi_i32(tmp, tmp, s->pc);
9386 store_reg(s, 15, tmp);
9ee6e8bb 9387 } else {
2359bf80 9388 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 9389 op = (insn >> 4) & 0x3;
2359bf80
MR
9390 switch (op2) {
9391 case 0:
426f5abc 9392 goto illegal_op;
2359bf80
MR
9393 case 1:
9394 /* Load/store exclusive byte/halfword/doubleword */
9395 if (op == 2) {
9396 goto illegal_op;
9397 }
9398 ARCH(7);
9399 break;
9400 case 2:
9401 /* Load-acquire/store-release */
9402 if (op == 3) {
9403 goto illegal_op;
9404 }
9405 /* Fall through */
9406 case 3:
9407 /* Load-acquire/store-release exclusive */
9408 ARCH(8);
9409 break;
426f5abc 9410 }
39d5492a 9411 addr = tcg_temp_local_new_i32();
98a46317 9412 load_reg_var(s, addr, rn);
2359bf80
MR
9413 if (!(op2 & 1)) {
9414 if (insn & (1 << 20)) {
9415 tmp = tcg_temp_new_i32();
9416 switch (op) {
9417 case 0: /* ldab */
6ce2faf4 9418 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
2359bf80
MR
9419 break;
9420 case 1: /* ldah */
6ce2faf4 9421 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
2359bf80
MR
9422 break;
9423 case 2: /* lda */
6ce2faf4 9424 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
2359bf80
MR
9425 break;
9426 default:
9427 abort();
9428 }
9429 store_reg(s, rs, tmp);
9430 } else {
9431 tmp = load_reg(s, rs);
9432 switch (op) {
9433 case 0: /* stlb */
6ce2faf4 9434 gen_aa32_st8(tmp, addr, get_mem_index(s));
2359bf80
MR
9435 break;
9436 case 1: /* stlh */
6ce2faf4 9437 gen_aa32_st16(tmp, addr, get_mem_index(s));
2359bf80
MR
9438 break;
9439 case 2: /* stl */
6ce2faf4 9440 gen_aa32_st32(tmp, addr, get_mem_index(s));
2359bf80
MR
9441 break;
9442 default:
9443 abort();
9444 }
9445 tcg_temp_free_i32(tmp);
9446 }
9447 } else if (insn & (1 << 20)) {
426f5abc 9448 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 9449 } else {
426f5abc 9450 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 9451 }
39d5492a 9452 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9453 }
9454 } else {
9455 /* Load/store multiple, RFE, SRS. */
9456 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 9457 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 9458 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 9459 goto illegal_op;
00115976 9460 }
9ee6e8bb
PB
9461 if (insn & (1 << 20)) {
9462 /* rfe */
b0109805
PB
9463 addr = load_reg(s, rn);
9464 if ((insn & (1 << 24)) == 0)
9465 tcg_gen_addi_i32(addr, addr, -8);
9466 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 9467 tmp = tcg_temp_new_i32();
6ce2faf4 9468 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 9469 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9470 tmp2 = tcg_temp_new_i32();
6ce2faf4 9471 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
9472 if (insn & (1 << 21)) {
9473 /* Base writeback. */
b0109805
PB
9474 if (insn & (1 << 24)) {
9475 tcg_gen_addi_i32(addr, addr, 4);
9476 } else {
9477 tcg_gen_addi_i32(addr, addr, -4);
9478 }
9479 store_reg(s, rn, addr);
9480 } else {
7d1b0095 9481 tcg_temp_free_i32(addr);
9ee6e8bb 9482 }
b0109805 9483 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
9484 } else {
9485 /* srs */
81465888
PM
9486 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9487 insn & (1 << 21));
9ee6e8bb
PB
9488 }
9489 } else {
5856d44e 9490 int i, loaded_base = 0;
39d5492a 9491 TCGv_i32 loaded_var;
9ee6e8bb 9492 /* Load/store multiple. */
b0109805 9493 addr = load_reg(s, rn);
9ee6e8bb
PB
9494 offset = 0;
9495 for (i = 0; i < 16; i++) {
9496 if (insn & (1 << i))
9497 offset += 4;
9498 }
9499 if (insn & (1 << 24)) {
b0109805 9500 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9501 }
9502
39d5492a 9503 TCGV_UNUSED_I32(loaded_var);
9ee6e8bb
PB
9504 for (i = 0; i < 16; i++) {
9505 if ((insn & (1 << i)) == 0)
9506 continue;
9507 if (insn & (1 << 20)) {
9508 /* Load. */
e2592fad 9509 tmp = tcg_temp_new_i32();
6ce2faf4 9510 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9ee6e8bb 9511 if (i == 15) {
b0109805 9512 gen_bx(s, tmp);
5856d44e
YO
9513 } else if (i == rn) {
9514 loaded_var = tmp;
9515 loaded_base = 1;
9ee6e8bb 9516 } else {
b0109805 9517 store_reg(s, i, tmp);
9ee6e8bb
PB
9518 }
9519 } else {
9520 /* Store. */
b0109805 9521 tmp = load_reg(s, i);
6ce2faf4 9522 gen_aa32_st32(tmp, addr, get_mem_index(s));
e2592fad 9523 tcg_temp_free_i32(tmp);
9ee6e8bb 9524 }
b0109805 9525 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 9526 }
5856d44e
YO
9527 if (loaded_base) {
9528 store_reg(s, rn, loaded_var);
9529 }
9ee6e8bb
PB
9530 if (insn & (1 << 21)) {
9531 /* Base register writeback. */
9532 if (insn & (1 << 24)) {
b0109805 9533 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9534 }
9535 /* Fault if writeback register is in register list. */
9536 if (insn & (1 << rn))
9537 goto illegal_op;
b0109805
PB
9538 store_reg(s, rn, addr);
9539 } else {
7d1b0095 9540 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9541 }
9542 }
9543 }
9544 break;
2af9ab77
JB
9545 case 5:
9546
9ee6e8bb 9547 op = (insn >> 21) & 0xf;
2af9ab77 9548 if (op == 6) {
62b44f05
AR
9549 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9550 goto illegal_op;
9551 }
2af9ab77
JB
9552 /* Halfword pack. */
9553 tmp = load_reg(s, rn);
9554 tmp2 = load_reg(s, rm);
9555 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9556 if (insn & (1 << 5)) {
9557 /* pkhtb */
9558 if (shift == 0)
9559 shift = 31;
9560 tcg_gen_sari_i32(tmp2, tmp2, shift);
9561 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9562 tcg_gen_ext16u_i32(tmp2, tmp2);
9563 } else {
9564 /* pkhbt */
9565 if (shift)
9566 tcg_gen_shli_i32(tmp2, tmp2, shift);
9567 tcg_gen_ext16u_i32(tmp, tmp);
9568 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9569 }
9570 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 9571 tcg_temp_free_i32(tmp2);
3174f8e9
FN
9572 store_reg(s, rd, tmp);
9573 } else {
2af9ab77
JB
9574 /* Data processing register constant shift. */
9575 if (rn == 15) {
7d1b0095 9576 tmp = tcg_temp_new_i32();
2af9ab77
JB
9577 tcg_gen_movi_i32(tmp, 0);
9578 } else {
9579 tmp = load_reg(s, rn);
9580 }
9581 tmp2 = load_reg(s, rm);
9582
9583 shiftop = (insn >> 4) & 3;
9584 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9585 conds = (insn & (1 << 20)) != 0;
9586 logic_cc = (conds && thumb2_logic_op(op));
9587 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9588 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9589 goto illegal_op;
7d1b0095 9590 tcg_temp_free_i32(tmp2);
2af9ab77
JB
9591 if (rd != 15) {
9592 store_reg(s, rd, tmp);
9593 } else {
7d1b0095 9594 tcg_temp_free_i32(tmp);
2af9ab77 9595 }
3174f8e9 9596 }
9ee6e8bb
PB
9597 break;
9598 case 13: /* Misc data processing. */
9599 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9600 if (op < 4 && (insn & 0xf000) != 0xf000)
9601 goto illegal_op;
9602 switch (op) {
9603 case 0: /* Register controlled shift. */
8984bd2e
PB
9604 tmp = load_reg(s, rn);
9605 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9606 if ((insn & 0x70) != 0)
9607 goto illegal_op;
9608 op = (insn >> 21) & 3;
8984bd2e
PB
9609 logic_cc = (insn & (1 << 20)) != 0;
9610 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9611 if (logic_cc)
9612 gen_logic_CC(tmp);
7dcc1f89 9613 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9614 break;
9615 case 1: /* Sign/zero extend. */
62b44f05
AR
9616 op = (insn >> 20) & 7;
9617 switch (op) {
9618 case 0: /* SXTAH, SXTH */
9619 case 1: /* UXTAH, UXTH */
9620 case 4: /* SXTAB, SXTB */
9621 case 5: /* UXTAB, UXTB */
9622 break;
9623 case 2: /* SXTAB16, SXTB16 */
9624 case 3: /* UXTAB16, UXTB16 */
9625 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9626 goto illegal_op;
9627 }
9628 break;
9629 default:
9630 goto illegal_op;
9631 }
9632 if (rn != 15) {
9633 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9634 goto illegal_op;
9635 }
9636 }
5e3f878a 9637 tmp = load_reg(s, rm);
9ee6e8bb 9638 shift = (insn >> 4) & 3;
1301f322 9639 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
9640 rotate, a shift is sufficient. */
9641 if (shift != 0)
f669df27 9642 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
9643 op = (insn >> 20) & 7;
9644 switch (op) {
5e3f878a
PB
9645 case 0: gen_sxth(tmp); break;
9646 case 1: gen_uxth(tmp); break;
9647 case 2: gen_sxtb16(tmp); break;
9648 case 3: gen_uxtb16(tmp); break;
9649 case 4: gen_sxtb(tmp); break;
9650 case 5: gen_uxtb(tmp); break;
62b44f05
AR
9651 default:
9652 g_assert_not_reached();
9ee6e8bb
PB
9653 }
9654 if (rn != 15) {
5e3f878a 9655 tmp2 = load_reg(s, rn);
9ee6e8bb 9656 if ((op >> 1) == 1) {
5e3f878a 9657 gen_add16(tmp, tmp2);
9ee6e8bb 9658 } else {
5e3f878a 9659 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9660 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9661 }
9662 }
5e3f878a 9663 store_reg(s, rd, tmp);
9ee6e8bb
PB
9664 break;
9665 case 2: /* SIMD add/subtract. */
62b44f05
AR
9666 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9667 goto illegal_op;
9668 }
9ee6e8bb
PB
9669 op = (insn >> 20) & 7;
9670 shift = (insn >> 4) & 7;
9671 if ((op & 3) == 3 || (shift & 3) == 3)
9672 goto illegal_op;
6ddbc6e4
PB
9673 tmp = load_reg(s, rn);
9674 tmp2 = load_reg(s, rm);
9675 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 9676 tcg_temp_free_i32(tmp2);
6ddbc6e4 9677 store_reg(s, rd, tmp);
9ee6e8bb
PB
9678 break;
9679 case 3: /* Other data processing. */
9680 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9681 if (op < 4) {
9682 /* Saturating add/subtract. */
62b44f05
AR
9683 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9684 goto illegal_op;
9685 }
d9ba4830
PB
9686 tmp = load_reg(s, rn);
9687 tmp2 = load_reg(s, rm);
9ee6e8bb 9688 if (op & 1)
9ef39277 9689 gen_helper_double_saturate(tmp, cpu_env, tmp);
4809c612 9690 if (op & 2)
9ef39277 9691 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 9692 else
9ef39277 9693 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 9694 tcg_temp_free_i32(tmp2);
9ee6e8bb 9695 } else {
62b44f05
AR
9696 switch (op) {
9697 case 0x0a: /* rbit */
9698 case 0x08: /* rev */
9699 case 0x09: /* rev16 */
9700 case 0x0b: /* revsh */
9701 case 0x18: /* clz */
9702 break;
9703 case 0x10: /* sel */
9704 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9705 goto illegal_op;
9706 }
9707 break;
9708 case 0x20: /* crc32/crc32c */
9709 case 0x21:
9710 case 0x22:
9711 case 0x28:
9712 case 0x29:
9713 case 0x2a:
9714 if (!arm_dc_feature(s, ARM_FEATURE_CRC)) {
9715 goto illegal_op;
9716 }
9717 break;
9718 default:
9719 goto illegal_op;
9720 }
d9ba4830 9721 tmp = load_reg(s, rn);
9ee6e8bb
PB
9722 switch (op) {
9723 case 0x0a: /* rbit */
d9ba4830 9724 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9725 break;
9726 case 0x08: /* rev */
66896cb8 9727 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
9728 break;
9729 case 0x09: /* rev16 */
d9ba4830 9730 gen_rev16(tmp);
9ee6e8bb
PB
9731 break;
9732 case 0x0b: /* revsh */
d9ba4830 9733 gen_revsh(tmp);
9ee6e8bb
PB
9734 break;
9735 case 0x10: /* sel */
d9ba4830 9736 tmp2 = load_reg(s, rm);
7d1b0095 9737 tmp3 = tcg_temp_new_i32();
0ecb72a5 9738 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 9739 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
9740 tcg_temp_free_i32(tmp3);
9741 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9742 break;
9743 case 0x18: /* clz */
d9ba4830 9744 gen_helper_clz(tmp, tmp);
9ee6e8bb 9745 break;
eb0ecd5a
WN
9746 case 0x20:
9747 case 0x21:
9748 case 0x22:
9749 case 0x28:
9750 case 0x29:
9751 case 0x2a:
9752 {
9753 /* crc32/crc32c */
9754 uint32_t sz = op & 0x3;
9755 uint32_t c = op & 0x8;
9756
eb0ecd5a 9757 tmp2 = load_reg(s, rm);
aa633469
PM
9758 if (sz == 0) {
9759 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9760 } else if (sz == 1) {
9761 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9762 }
eb0ecd5a
WN
9763 tmp3 = tcg_const_i32(1 << sz);
9764 if (c) {
9765 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9766 } else {
9767 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9768 }
9769 tcg_temp_free_i32(tmp2);
9770 tcg_temp_free_i32(tmp3);
9771 break;
9772 }
9ee6e8bb 9773 default:
62b44f05 9774 g_assert_not_reached();
9ee6e8bb
PB
9775 }
9776 }
d9ba4830 9777 store_reg(s, rd, tmp);
9ee6e8bb
PB
9778 break;
9779 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
9780 switch ((insn >> 20) & 7) {
9781 case 0: /* 32 x 32 -> 32 */
9782 case 7: /* Unsigned sum of absolute differences. */
9783 break;
9784 case 1: /* 16 x 16 -> 32 */
9785 case 2: /* Dual multiply add. */
9786 case 3: /* 32 * 16 -> 32msb */
9787 case 4: /* Dual multiply subtract. */
9788 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9789 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9790 goto illegal_op;
9791 }
9792 break;
9793 }
9ee6e8bb 9794 op = (insn >> 4) & 0xf;
d9ba4830
PB
9795 tmp = load_reg(s, rn);
9796 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9797 switch ((insn >> 20) & 7) {
9798 case 0: /* 32 x 32 -> 32 */
d9ba4830 9799 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 9800 tcg_temp_free_i32(tmp2);
9ee6e8bb 9801 if (rs != 15) {
d9ba4830 9802 tmp2 = load_reg(s, rs);
9ee6e8bb 9803 if (op)
d9ba4830 9804 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 9805 else
d9ba4830 9806 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9807 tcg_temp_free_i32(tmp2);
9ee6e8bb 9808 }
9ee6e8bb
PB
9809 break;
9810 case 1: /* 16 x 16 -> 32 */
d9ba4830 9811 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 9812 tcg_temp_free_i32(tmp2);
9ee6e8bb 9813 if (rs != 15) {
d9ba4830 9814 tmp2 = load_reg(s, rs);
9ef39277 9815 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9816 tcg_temp_free_i32(tmp2);
9ee6e8bb 9817 }
9ee6e8bb
PB
9818 break;
9819 case 2: /* Dual multiply add. */
9820 case 4: /* Dual multiply subtract. */
9821 if (op)
d9ba4830
PB
9822 gen_swap_half(tmp2);
9823 gen_smul_dual(tmp, tmp2);
9ee6e8bb 9824 if (insn & (1 << 22)) {
e1d177b9 9825 /* This subtraction cannot overflow. */
d9ba4830 9826 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 9827 } else {
e1d177b9
PM
9828 /* This addition cannot overflow 32 bits;
9829 * however it may overflow considered as a signed
9830 * operation, in which case we must set the Q flag.
9831 */
9ef39277 9832 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 9833 }
7d1b0095 9834 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9835 if (rs != 15)
9836 {
d9ba4830 9837 tmp2 = load_reg(s, rs);
9ef39277 9838 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9839 tcg_temp_free_i32(tmp2);
9ee6e8bb 9840 }
9ee6e8bb
PB
9841 break;
9842 case 3: /* 32 * 16 -> 32msb */
9843 if (op)
d9ba4830 9844 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 9845 else
d9ba4830 9846 gen_sxth(tmp2);
a7812ae4
PB
9847 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9848 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 9849 tmp = tcg_temp_new_i32();
ecc7b3aa 9850 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 9851 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
9852 if (rs != 15)
9853 {
d9ba4830 9854 tmp2 = load_reg(s, rs);
9ef39277 9855 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9856 tcg_temp_free_i32(tmp2);
9ee6e8bb 9857 }
9ee6e8bb 9858 break;
838fa72d
AJ
9859 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9860 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 9861 if (rs != 15) {
838fa72d
AJ
9862 tmp = load_reg(s, rs);
9863 if (insn & (1 << 20)) {
9864 tmp64 = gen_addq_msw(tmp64, tmp);
99c475ab 9865 } else {
838fa72d 9866 tmp64 = gen_subq_msw(tmp64, tmp);
99c475ab 9867 }
2c0262af 9868 }
838fa72d
AJ
9869 if (insn & (1 << 4)) {
9870 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9871 }
9872 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 9873 tmp = tcg_temp_new_i32();
ecc7b3aa 9874 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 9875 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
9876 break;
9877 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 9878 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 9879 tcg_temp_free_i32(tmp2);
9ee6e8bb 9880 if (rs != 15) {
d9ba4830
PB
9881 tmp2 = load_reg(s, rs);
9882 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9883 tcg_temp_free_i32(tmp2);
5fd46862 9884 }
9ee6e8bb 9885 break;
2c0262af 9886 }
d9ba4830 9887 store_reg(s, rd, tmp);
2c0262af 9888 break;
9ee6e8bb
PB
9889 case 6: case 7: /* 64-bit multiply, Divide. */
9890 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
9891 tmp = load_reg(s, rn);
9892 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9893 if ((op & 0x50) == 0x10) {
9894 /* sdiv, udiv */
d614a513 9895 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DIV)) {
9ee6e8bb 9896 goto illegal_op;
47789990 9897 }
9ee6e8bb 9898 if (op & 0x20)
5e3f878a 9899 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 9900 else
5e3f878a 9901 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 9902 tcg_temp_free_i32(tmp2);
5e3f878a 9903 store_reg(s, rd, tmp);
9ee6e8bb
PB
9904 } else if ((op & 0xe) == 0xc) {
9905 /* Dual multiply accumulate long. */
62b44f05
AR
9906 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9907 tcg_temp_free_i32(tmp);
9908 tcg_temp_free_i32(tmp2);
9909 goto illegal_op;
9910 }
9ee6e8bb 9911 if (op & 1)
5e3f878a
PB
9912 gen_swap_half(tmp2);
9913 gen_smul_dual(tmp, tmp2);
9ee6e8bb 9914 if (op & 0x10) {
5e3f878a 9915 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 9916 } else {
5e3f878a 9917 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 9918 }
7d1b0095 9919 tcg_temp_free_i32(tmp2);
a7812ae4
PB
9920 /* BUGFIX */
9921 tmp64 = tcg_temp_new_i64();
9922 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 9923 tcg_temp_free_i32(tmp);
a7812ae4
PB
9924 gen_addq(s, tmp64, rs, rd);
9925 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 9926 tcg_temp_free_i64(tmp64);
2c0262af 9927 } else {
9ee6e8bb
PB
9928 if (op & 0x20) {
9929 /* Unsigned 64-bit multiply */
a7812ae4 9930 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 9931 } else {
9ee6e8bb
PB
9932 if (op & 8) {
9933 /* smlalxy */
62b44f05
AR
9934 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9935 tcg_temp_free_i32(tmp2);
9936 tcg_temp_free_i32(tmp);
9937 goto illegal_op;
9938 }
5e3f878a 9939 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 9940 tcg_temp_free_i32(tmp2);
a7812ae4
PB
9941 tmp64 = tcg_temp_new_i64();
9942 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 9943 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9944 } else {
9945 /* Signed 64-bit multiply */
a7812ae4 9946 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 9947 }
b5ff1b31 9948 }
9ee6e8bb
PB
9949 if (op & 4) {
9950 /* umaal */
62b44f05
AR
9951 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9952 tcg_temp_free_i64(tmp64);
9953 goto illegal_op;
9954 }
a7812ae4
PB
9955 gen_addq_lo(s, tmp64, rs);
9956 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
9957 } else if (op & 0x40) {
9958 /* 64-bit accumulate. */
a7812ae4 9959 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 9960 }
a7812ae4 9961 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 9962 tcg_temp_free_i64(tmp64);
5fd46862 9963 }
2c0262af 9964 break;
9ee6e8bb
PB
9965 }
9966 break;
9967 case 6: case 7: case 14: case 15:
9968 /* Coprocessor. */
9969 if (((insn >> 24) & 3) == 3) {
9970 /* Translate into the equivalent ARM encoding. */
f06053e3 9971 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 9972 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 9973 goto illegal_op;
7dcc1f89 9974 }
6a57f3eb 9975 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 9976 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9977 goto illegal_op;
9978 }
9ee6e8bb
PB
9979 } else {
9980 if (insn & (1 << 28))
9981 goto illegal_op;
7dcc1f89 9982 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 9983 goto illegal_op;
7dcc1f89 9984 }
9ee6e8bb
PB
9985 }
9986 break;
9987 case 8: case 9: case 10: case 11:
9988 if (insn & (1 << 15)) {
9989 /* Branches, misc control. */
9990 if (insn & 0x5000) {
9991 /* Unconditional branch. */
9992 /* signextend(hw1[10:0]) -> offset[:12]. */
9993 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9994 /* hw1[10:0] -> offset[11:1]. */
9995 offset |= (insn & 0x7ff) << 1;
9996 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9997 offset[24:22] already have the same value because of the
9998 sign extension above. */
9999 offset ^= ((~insn) & (1 << 13)) << 10;
10000 offset ^= ((~insn) & (1 << 11)) << 11;
10001
9ee6e8bb
PB
10002 if (insn & (1 << 14)) {
10003 /* Branch and link. */
3174f8e9 10004 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
b5ff1b31 10005 }
3b46e624 10006
b0109805 10007 offset += s->pc;
9ee6e8bb
PB
10008 if (insn & (1 << 12)) {
10009 /* b/bl */
b0109805 10010 gen_jmp(s, offset);
9ee6e8bb
PB
10011 } else {
10012 /* blx */
b0109805 10013 offset &= ~(uint32_t)2;
be5e7a76 10014 /* thumb2 bx, no need to check */
b0109805 10015 gen_bx_im(s, offset);
2c0262af 10016 }
9ee6e8bb
PB
10017 } else if (((insn >> 23) & 7) == 7) {
10018 /* Misc control */
10019 if (insn & (1 << 13))
10020 goto illegal_op;
10021
10022 if (insn & (1 << 26)) {
37e6456e
PM
10023 if (!(insn & (1 << 20))) {
10024 /* Hypervisor call (v7) */
10025 int imm16 = extract32(insn, 16, 4) << 12
10026 | extract32(insn, 0, 12);
10027 ARCH(7);
10028 if (IS_USER(s)) {
10029 goto illegal_op;
10030 }
10031 gen_hvc(s, imm16);
10032 } else {
10033 /* Secure monitor call (v6+) */
10034 ARCH(6K);
10035 if (IS_USER(s)) {
10036 goto illegal_op;
10037 }
10038 gen_smc(s);
10039 }
2c0262af 10040 } else {
9ee6e8bb
PB
10041 op = (insn >> 20) & 7;
10042 switch (op) {
10043 case 0: /* msr cpsr. */
b53d8923 10044 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10045 tmp = load_reg(s, rn);
10046 addr = tcg_const_i32(insn & 0xff);
10047 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 10048 tcg_temp_free_i32(addr);
7d1b0095 10049 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10050 gen_lookup_tb(s);
10051 break;
10052 }
10053 /* fall through */
10054 case 1: /* msr spsr. */
b53d8923 10055 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10056 goto illegal_op;
b53d8923 10057 }
2fbac54b
FN
10058 tmp = load_reg(s, rn);
10059 if (gen_set_psr(s,
7dcc1f89 10060 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 10061 op == 1, tmp))
9ee6e8bb
PB
10062 goto illegal_op;
10063 break;
10064 case 2: /* cps, nop-hint. */
10065 if (((insn >> 8) & 7) == 0) {
10066 gen_nop_hint(s, insn & 0xff);
10067 }
10068 /* Implemented as NOP in user mode. */
10069 if (IS_USER(s))
10070 break;
10071 offset = 0;
10072 imm = 0;
10073 if (insn & (1 << 10)) {
10074 if (insn & (1 << 7))
10075 offset |= CPSR_A;
10076 if (insn & (1 << 6))
10077 offset |= CPSR_I;
10078 if (insn & (1 << 5))
10079 offset |= CPSR_F;
10080 if (insn & (1 << 9))
10081 imm = CPSR_A | CPSR_I | CPSR_F;
10082 }
10083 if (insn & (1 << 8)) {
10084 offset |= 0x1f;
10085 imm |= (insn & 0x1f);
10086 }
10087 if (offset) {
2fbac54b 10088 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
10089 }
10090 break;
10091 case 3: /* Special control operations. */
426f5abc 10092 ARCH(7);
9ee6e8bb
PB
10093 op = (insn >> 4) & 0xf;
10094 switch (op) {
10095 case 2: /* clrex */
426f5abc 10096 gen_clrex(s);
9ee6e8bb
PB
10097 break;
10098 case 4: /* dsb */
10099 case 5: /* dmb */
9ee6e8bb 10100 /* These execute as NOPs. */
9ee6e8bb 10101 break;
6df99dec
SS
10102 case 6: /* isb */
10103 /* We need to break the TB after this insn
10104 * to execute self-modifying code correctly
10105 * and also to take any pending interrupts
10106 * immediately.
10107 */
10108 gen_lookup_tb(s);
10109 break;
9ee6e8bb
PB
10110 default:
10111 goto illegal_op;
10112 }
10113 break;
10114 case 4: /* bxj */
10115 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
10116 tmp = load_reg(s, rn);
10117 gen_bx(s, tmp);
9ee6e8bb
PB
10118 break;
10119 case 5: /* Exception return. */
b8b45b68
RV
10120 if (IS_USER(s)) {
10121 goto illegal_op;
10122 }
10123 if (rn != 14 || rd != 15) {
10124 goto illegal_op;
10125 }
10126 tmp = load_reg(s, rn);
10127 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
10128 gen_exception_return(s, tmp);
10129 break;
9ee6e8bb 10130 case 6: /* mrs cpsr. */
7d1b0095 10131 tmp = tcg_temp_new_i32();
b53d8923 10132 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10133 addr = tcg_const_i32(insn & 0xff);
10134 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 10135 tcg_temp_free_i32(addr);
9ee6e8bb 10136 } else {
9ef39277 10137 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 10138 }
8984bd2e 10139 store_reg(s, rd, tmp);
9ee6e8bb
PB
10140 break;
10141 case 7: /* mrs spsr. */
10142 /* Not accessible in user mode. */
b53d8923 10143 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10144 goto illegal_op;
b53d8923 10145 }
d9ba4830
PB
10146 tmp = load_cpu_field(spsr);
10147 store_reg(s, rd, tmp);
9ee6e8bb 10148 break;
2c0262af
FB
10149 }
10150 }
9ee6e8bb
PB
10151 } else {
10152 /* Conditional branch. */
10153 op = (insn >> 22) & 0xf;
10154 /* Generate a conditional jump to next instruction. */
10155 s->condlabel = gen_new_label();
39fb730a 10156 arm_gen_test_cc(op ^ 1, s->condlabel);
9ee6e8bb
PB
10157 s->condjmp = 1;
10158
10159 /* offset[11:1] = insn[10:0] */
10160 offset = (insn & 0x7ff) << 1;
10161 /* offset[17:12] = insn[21:16]. */
10162 offset |= (insn & 0x003f0000) >> 4;
10163 /* offset[31:20] = insn[26]. */
10164 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
10165 /* offset[18] = insn[13]. */
10166 offset |= (insn & (1 << 13)) << 5;
10167 /* offset[19] = insn[11]. */
10168 offset |= (insn & (1 << 11)) << 8;
10169
10170 /* jump to the offset */
b0109805 10171 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
10172 }
10173 } else {
10174 /* Data processing immediate. */
10175 if (insn & (1 << 25)) {
10176 if (insn & (1 << 24)) {
10177 if (insn & (1 << 20))
10178 goto illegal_op;
10179 /* Bitfield/Saturate. */
10180 op = (insn >> 21) & 7;
10181 imm = insn & 0x1f;
10182 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 10183 if (rn == 15) {
7d1b0095 10184 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
10185 tcg_gen_movi_i32(tmp, 0);
10186 } else {
10187 tmp = load_reg(s, rn);
10188 }
9ee6e8bb
PB
10189 switch (op) {
10190 case 2: /* Signed bitfield extract. */
10191 imm++;
10192 if (shift + imm > 32)
10193 goto illegal_op;
10194 if (imm < 32)
6ddbc6e4 10195 gen_sbfx(tmp, shift, imm);
9ee6e8bb
PB
10196 break;
10197 case 6: /* Unsigned bitfield extract. */
10198 imm++;
10199 if (shift + imm > 32)
10200 goto illegal_op;
10201 if (imm < 32)
6ddbc6e4 10202 gen_ubfx(tmp, shift, (1u << imm) - 1);
9ee6e8bb
PB
10203 break;
10204 case 3: /* Bitfield insert/clear. */
10205 if (imm < shift)
10206 goto illegal_op;
10207 imm = imm + 1 - shift;
10208 if (imm != 32) {
6ddbc6e4 10209 tmp2 = load_reg(s, rd);
d593c48e 10210 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 10211 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10212 }
10213 break;
10214 case 7:
10215 goto illegal_op;
10216 default: /* Saturate. */
9ee6e8bb
PB
10217 if (shift) {
10218 if (op & 1)
6ddbc6e4 10219 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 10220 else
6ddbc6e4 10221 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 10222 }
6ddbc6e4 10223 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
10224 if (op & 4) {
10225 /* Unsigned. */
62b44f05
AR
10226 if ((op & 1) && shift == 0) {
10227 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10228 tcg_temp_free_i32(tmp);
10229 tcg_temp_free_i32(tmp2);
10230 goto illegal_op;
10231 }
9ef39277 10232 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10233 } else {
9ef39277 10234 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 10235 }
2c0262af 10236 } else {
9ee6e8bb 10237 /* Signed. */
62b44f05
AR
10238 if ((op & 1) && shift == 0) {
10239 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10240 tcg_temp_free_i32(tmp);
10241 tcg_temp_free_i32(tmp2);
10242 goto illegal_op;
10243 }
9ef39277 10244 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10245 } else {
9ef39277 10246 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 10247 }
2c0262af 10248 }
b75263d6 10249 tcg_temp_free_i32(tmp2);
9ee6e8bb 10250 break;
2c0262af 10251 }
6ddbc6e4 10252 store_reg(s, rd, tmp);
9ee6e8bb
PB
10253 } else {
10254 imm = ((insn & 0x04000000) >> 15)
10255 | ((insn & 0x7000) >> 4) | (insn & 0xff);
10256 if (insn & (1 << 22)) {
10257 /* 16-bit immediate. */
10258 imm |= (insn >> 4) & 0xf000;
10259 if (insn & (1 << 23)) {
10260 /* movt */
5e3f878a 10261 tmp = load_reg(s, rd);
86831435 10262 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 10263 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 10264 } else {
9ee6e8bb 10265 /* movw */
7d1b0095 10266 tmp = tcg_temp_new_i32();
5e3f878a 10267 tcg_gen_movi_i32(tmp, imm);
2c0262af
FB
10268 }
10269 } else {
9ee6e8bb
PB
10270 /* Add/sub 12-bit immediate. */
10271 if (rn == 15) {
b0109805 10272 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 10273 if (insn & (1 << 23))
b0109805 10274 offset -= imm;
9ee6e8bb 10275 else
b0109805 10276 offset += imm;
7d1b0095 10277 tmp = tcg_temp_new_i32();
5e3f878a 10278 tcg_gen_movi_i32(tmp, offset);
2c0262af 10279 } else {
5e3f878a 10280 tmp = load_reg(s, rn);
9ee6e8bb 10281 if (insn & (1 << 23))
5e3f878a 10282 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 10283 else
5e3f878a 10284 tcg_gen_addi_i32(tmp, tmp, imm);
2c0262af 10285 }
9ee6e8bb 10286 }
5e3f878a 10287 store_reg(s, rd, tmp);
191abaa2 10288 }
9ee6e8bb
PB
10289 } else {
10290 int shifter_out = 0;
10291 /* modified 12-bit immediate. */
10292 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10293 imm = (insn & 0xff);
10294 switch (shift) {
10295 case 0: /* XY */
10296 /* Nothing to do. */
10297 break;
10298 case 1: /* 00XY00XY */
10299 imm |= imm << 16;
10300 break;
10301 case 2: /* XY00XY00 */
10302 imm |= imm << 16;
10303 imm <<= 8;
10304 break;
10305 case 3: /* XYXYXYXY */
10306 imm |= imm << 16;
10307 imm |= imm << 8;
10308 break;
10309 default: /* Rotated constant. */
10310 shift = (shift << 1) | (imm >> 7);
10311 imm |= 0x80;
10312 imm = imm << (32 - shift);
10313 shifter_out = 1;
10314 break;
b5ff1b31 10315 }
7d1b0095 10316 tmp2 = tcg_temp_new_i32();
3174f8e9 10317 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 10318 rn = (insn >> 16) & 0xf;
3174f8e9 10319 if (rn == 15) {
7d1b0095 10320 tmp = tcg_temp_new_i32();
3174f8e9
FN
10321 tcg_gen_movi_i32(tmp, 0);
10322 } else {
10323 tmp = load_reg(s, rn);
10324 }
9ee6e8bb
PB
10325 op = (insn >> 21) & 0xf;
10326 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 10327 shifter_out, tmp, tmp2))
9ee6e8bb 10328 goto illegal_op;
7d1b0095 10329 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10330 rd = (insn >> 8) & 0xf;
10331 if (rd != 15) {
3174f8e9
FN
10332 store_reg(s, rd, tmp);
10333 } else {
7d1b0095 10334 tcg_temp_free_i32(tmp);
2c0262af 10335 }
2c0262af 10336 }
9ee6e8bb
PB
10337 }
10338 break;
10339 case 12: /* Load/store single data item. */
10340 {
10341 int postinc = 0;
10342 int writeback = 0;
a99caa48 10343 int memidx;
9ee6e8bb 10344 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 10345 if (disas_neon_ls_insn(s, insn)) {
c1713132 10346 goto illegal_op;
7dcc1f89 10347 }
9ee6e8bb
PB
10348 break;
10349 }
a2fdc890
PM
10350 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10351 if (rs == 15) {
10352 if (!(insn & (1 << 20))) {
10353 goto illegal_op;
10354 }
10355 if (op != 2) {
10356 /* Byte or halfword load space with dest == r15 : memory hints.
10357 * Catch them early so we don't emit pointless addressing code.
10358 * This space is a mix of:
10359 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10360 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10361 * cores)
10362 * unallocated hints, which must be treated as NOPs
10363 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10364 * which is easiest for the decoding logic
10365 * Some space which must UNDEF
10366 */
10367 int op1 = (insn >> 23) & 3;
10368 int op2 = (insn >> 6) & 0x3f;
10369 if (op & 2) {
10370 goto illegal_op;
10371 }
10372 if (rn == 15) {
02afbf64
PM
10373 /* UNPREDICTABLE, unallocated hint or
10374 * PLD/PLDW/PLI (literal)
10375 */
a2fdc890
PM
10376 return 0;
10377 }
10378 if (op1 & 1) {
02afbf64 10379 return 0; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10380 }
10381 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
02afbf64 10382 return 0; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10383 }
10384 /* UNDEF space, or an UNPREDICTABLE */
10385 return 1;
10386 }
10387 }
a99caa48 10388 memidx = get_mem_index(s);
9ee6e8bb 10389 if (rn == 15) {
7d1b0095 10390 addr = tcg_temp_new_i32();
9ee6e8bb
PB
10391 /* PC relative. */
10392 /* s->pc has already been incremented by 4. */
10393 imm = s->pc & 0xfffffffc;
10394 if (insn & (1 << 23))
10395 imm += insn & 0xfff;
10396 else
10397 imm -= insn & 0xfff;
b0109805 10398 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 10399 } else {
b0109805 10400 addr = load_reg(s, rn);
9ee6e8bb
PB
10401 if (insn & (1 << 23)) {
10402 /* Positive offset. */
10403 imm = insn & 0xfff;
b0109805 10404 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb 10405 } else {
9ee6e8bb 10406 imm = insn & 0xff;
2a0308c5
PM
10407 switch ((insn >> 8) & 0xf) {
10408 case 0x0: /* Shifted Register. */
9ee6e8bb 10409 shift = (insn >> 4) & 0xf;
2a0308c5
PM
10410 if (shift > 3) {
10411 tcg_temp_free_i32(addr);
18c9b560 10412 goto illegal_op;
2a0308c5 10413 }
b26eefb6 10414 tmp = load_reg(s, rm);
9ee6e8bb 10415 if (shift)
b26eefb6 10416 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 10417 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10418 tcg_temp_free_i32(tmp);
9ee6e8bb 10419 break;
2a0308c5 10420 case 0xc: /* Negative offset. */
b0109805 10421 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb 10422 break;
2a0308c5 10423 case 0xe: /* User privilege. */
b0109805 10424 tcg_gen_addi_i32(addr, addr, imm);
579d21cc 10425 memidx = get_a32_user_mem_index(s);
9ee6e8bb 10426 break;
2a0308c5 10427 case 0x9: /* Post-decrement. */
9ee6e8bb
PB
10428 imm = -imm;
10429 /* Fall through. */
2a0308c5 10430 case 0xb: /* Post-increment. */
9ee6e8bb
PB
10431 postinc = 1;
10432 writeback = 1;
10433 break;
2a0308c5 10434 case 0xd: /* Pre-decrement. */
9ee6e8bb
PB
10435 imm = -imm;
10436 /* Fall through. */
2a0308c5 10437 case 0xf: /* Pre-increment. */
b0109805 10438 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb
PB
10439 writeback = 1;
10440 break;
10441 default:
2a0308c5 10442 tcg_temp_free_i32(addr);
b7bcbe95 10443 goto illegal_op;
9ee6e8bb
PB
10444 }
10445 }
10446 }
9ee6e8bb
PB
10447 if (insn & (1 << 20)) {
10448 /* Load. */
5a839c0d 10449 tmp = tcg_temp_new_i32();
a2fdc890 10450 switch (op) {
5a839c0d 10451 case 0:
a99caa48 10452 gen_aa32_ld8u(tmp, addr, memidx);
5a839c0d
PM
10453 break;
10454 case 4:
a99caa48 10455 gen_aa32_ld8s(tmp, addr, memidx);
5a839c0d
PM
10456 break;
10457 case 1:
a99caa48 10458 gen_aa32_ld16u(tmp, addr, memidx);
5a839c0d
PM
10459 break;
10460 case 5:
a99caa48 10461 gen_aa32_ld16s(tmp, addr, memidx);
5a839c0d
PM
10462 break;
10463 case 2:
a99caa48 10464 gen_aa32_ld32u(tmp, addr, memidx);
5a839c0d 10465 break;
2a0308c5 10466 default:
5a839c0d 10467 tcg_temp_free_i32(tmp);
2a0308c5
PM
10468 tcg_temp_free_i32(addr);
10469 goto illegal_op;
a2fdc890
PM
10470 }
10471 if (rs == 15) {
10472 gen_bx(s, tmp);
9ee6e8bb 10473 } else {
a2fdc890 10474 store_reg(s, rs, tmp);
9ee6e8bb
PB
10475 }
10476 } else {
10477 /* Store. */
b0109805 10478 tmp = load_reg(s, rs);
9ee6e8bb 10479 switch (op) {
5a839c0d 10480 case 0:
a99caa48 10481 gen_aa32_st8(tmp, addr, memidx);
5a839c0d
PM
10482 break;
10483 case 1:
a99caa48 10484 gen_aa32_st16(tmp, addr, memidx);
5a839c0d
PM
10485 break;
10486 case 2:
a99caa48 10487 gen_aa32_st32(tmp, addr, memidx);
5a839c0d 10488 break;
2a0308c5 10489 default:
5a839c0d 10490 tcg_temp_free_i32(tmp);
2a0308c5
PM
10491 tcg_temp_free_i32(addr);
10492 goto illegal_op;
b7bcbe95 10493 }
5a839c0d 10494 tcg_temp_free_i32(tmp);
2c0262af 10495 }
9ee6e8bb 10496 if (postinc)
b0109805
PB
10497 tcg_gen_addi_i32(addr, addr, imm);
10498 if (writeback) {
10499 store_reg(s, rn, addr);
10500 } else {
7d1b0095 10501 tcg_temp_free_i32(addr);
b0109805 10502 }
9ee6e8bb
PB
10503 }
10504 break;
10505 default:
10506 goto illegal_op;
2c0262af 10507 }
9ee6e8bb
PB
10508 return 0;
10509illegal_op:
10510 return 1;
2c0262af
FB
10511}
10512
0ecb72a5 10513static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
99c475ab
FB
10514{
10515 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10516 int32_t offset;
10517 int i;
39d5492a
PM
10518 TCGv_i32 tmp;
10519 TCGv_i32 tmp2;
10520 TCGv_i32 addr;
99c475ab 10521
9ee6e8bb
PB
10522 if (s->condexec_mask) {
10523 cond = s->condexec_cond;
bedd2912
JB
10524 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10525 s->condlabel = gen_new_label();
39fb730a 10526 arm_gen_test_cc(cond ^ 1, s->condlabel);
bedd2912
JB
10527 s->condjmp = 1;
10528 }
9ee6e8bb
PB
10529 }
10530
d31dd73e 10531 insn = arm_lduw_code(env, s->pc, s->bswap_code);
99c475ab 10532 s->pc += 2;
b5ff1b31 10533
99c475ab
FB
10534 switch (insn >> 12) {
10535 case 0: case 1:
396e467c 10536
99c475ab
FB
10537 rd = insn & 7;
10538 op = (insn >> 11) & 3;
10539 if (op == 3) {
10540 /* add/subtract */
10541 rn = (insn >> 3) & 7;
396e467c 10542 tmp = load_reg(s, rn);
99c475ab
FB
10543 if (insn & (1 << 10)) {
10544 /* immediate */
7d1b0095 10545 tmp2 = tcg_temp_new_i32();
396e467c 10546 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
10547 } else {
10548 /* reg */
10549 rm = (insn >> 6) & 7;
396e467c 10550 tmp2 = load_reg(s, rm);
99c475ab 10551 }
9ee6e8bb
PB
10552 if (insn & (1 << 9)) {
10553 if (s->condexec_mask)
396e467c 10554 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10555 else
72485ec4 10556 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
10557 } else {
10558 if (s->condexec_mask)
396e467c 10559 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 10560 else
72485ec4 10561 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 10562 }
7d1b0095 10563 tcg_temp_free_i32(tmp2);
396e467c 10564 store_reg(s, rd, tmp);
99c475ab
FB
10565 } else {
10566 /* shift immediate */
10567 rm = (insn >> 3) & 7;
10568 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
10569 tmp = load_reg(s, rm);
10570 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10571 if (!s->condexec_mask)
10572 gen_logic_CC(tmp);
10573 store_reg(s, rd, tmp);
99c475ab
FB
10574 }
10575 break;
10576 case 2: case 3:
10577 /* arithmetic large immediate */
10578 op = (insn >> 11) & 3;
10579 rd = (insn >> 8) & 0x7;
396e467c 10580 if (op == 0) { /* mov */
7d1b0095 10581 tmp = tcg_temp_new_i32();
396e467c 10582 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 10583 if (!s->condexec_mask)
396e467c
FN
10584 gen_logic_CC(tmp);
10585 store_reg(s, rd, tmp);
10586 } else {
10587 tmp = load_reg(s, rd);
7d1b0095 10588 tmp2 = tcg_temp_new_i32();
396e467c
FN
10589 tcg_gen_movi_i32(tmp2, insn & 0xff);
10590 switch (op) {
10591 case 1: /* cmp */
72485ec4 10592 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
10593 tcg_temp_free_i32(tmp);
10594 tcg_temp_free_i32(tmp2);
396e467c
FN
10595 break;
10596 case 2: /* add */
10597 if (s->condexec_mask)
10598 tcg_gen_add_i32(tmp, tmp, tmp2);
10599 else
72485ec4 10600 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 10601 tcg_temp_free_i32(tmp2);
396e467c
FN
10602 store_reg(s, rd, tmp);
10603 break;
10604 case 3: /* sub */
10605 if (s->condexec_mask)
10606 tcg_gen_sub_i32(tmp, tmp, tmp2);
10607 else
72485ec4 10608 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 10609 tcg_temp_free_i32(tmp2);
396e467c
FN
10610 store_reg(s, rd, tmp);
10611 break;
10612 }
99c475ab 10613 }
99c475ab
FB
10614 break;
10615 case 4:
10616 if (insn & (1 << 11)) {
10617 rd = (insn >> 8) & 7;
5899f386
FB
10618 /* load pc-relative. Bit 1 of PC is ignored. */
10619 val = s->pc + 2 + ((insn & 0xff) * 4);
10620 val &= ~(uint32_t)2;
7d1b0095 10621 addr = tcg_temp_new_i32();
b0109805 10622 tcg_gen_movi_i32(addr, val);
c40c8556 10623 tmp = tcg_temp_new_i32();
6ce2faf4 10624 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7d1b0095 10625 tcg_temp_free_i32(addr);
b0109805 10626 store_reg(s, rd, tmp);
99c475ab
FB
10627 break;
10628 }
10629 if (insn & (1 << 10)) {
10630 /* data processing extended or blx */
10631 rd = (insn & 7) | ((insn >> 4) & 8);
10632 rm = (insn >> 3) & 0xf;
10633 op = (insn >> 8) & 3;
10634 switch (op) {
10635 case 0: /* add */
396e467c
FN
10636 tmp = load_reg(s, rd);
10637 tmp2 = load_reg(s, rm);
10638 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10639 tcg_temp_free_i32(tmp2);
396e467c 10640 store_reg(s, rd, tmp);
99c475ab
FB
10641 break;
10642 case 1: /* cmp */
396e467c
FN
10643 tmp = load_reg(s, rd);
10644 tmp2 = load_reg(s, rm);
72485ec4 10645 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
10646 tcg_temp_free_i32(tmp2);
10647 tcg_temp_free_i32(tmp);
99c475ab
FB
10648 break;
10649 case 2: /* mov/cpy */
396e467c
FN
10650 tmp = load_reg(s, rm);
10651 store_reg(s, rd, tmp);
99c475ab
FB
10652 break;
10653 case 3:/* branch [and link] exchange thumb register */
b0109805 10654 tmp = load_reg(s, rm);
99c475ab 10655 if (insn & (1 << 7)) {
be5e7a76 10656 ARCH(5);
99c475ab 10657 val = (uint32_t)s->pc | 1;
7d1b0095 10658 tmp2 = tcg_temp_new_i32();
b0109805
PB
10659 tcg_gen_movi_i32(tmp2, val);
10660 store_reg(s, 14, tmp2);
99c475ab 10661 }
be5e7a76 10662 /* already thumb, no need to check */
d9ba4830 10663 gen_bx(s, tmp);
99c475ab
FB
10664 break;
10665 }
10666 break;
10667 }
10668
10669 /* data processing register */
10670 rd = insn & 7;
10671 rm = (insn >> 3) & 7;
10672 op = (insn >> 6) & 0xf;
10673 if (op == 2 || op == 3 || op == 4 || op == 7) {
10674 /* the shift/rotate ops want the operands backwards */
10675 val = rm;
10676 rm = rd;
10677 rd = val;
10678 val = 1;
10679 } else {
10680 val = 0;
10681 }
10682
396e467c 10683 if (op == 9) { /* neg */
7d1b0095 10684 tmp = tcg_temp_new_i32();
396e467c
FN
10685 tcg_gen_movi_i32(tmp, 0);
10686 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10687 tmp = load_reg(s, rd);
10688 } else {
39d5492a 10689 TCGV_UNUSED_I32(tmp);
396e467c 10690 }
99c475ab 10691
396e467c 10692 tmp2 = load_reg(s, rm);
5899f386 10693 switch (op) {
99c475ab 10694 case 0x0: /* and */
396e467c 10695 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 10696 if (!s->condexec_mask)
396e467c 10697 gen_logic_CC(tmp);
99c475ab
FB
10698 break;
10699 case 0x1: /* eor */
396e467c 10700 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 10701 if (!s->condexec_mask)
396e467c 10702 gen_logic_CC(tmp);
99c475ab
FB
10703 break;
10704 case 0x2: /* lsl */
9ee6e8bb 10705 if (s->condexec_mask) {
365af80e 10706 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 10707 } else {
9ef39277 10708 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 10709 gen_logic_CC(tmp2);
9ee6e8bb 10710 }
99c475ab
FB
10711 break;
10712 case 0x3: /* lsr */
9ee6e8bb 10713 if (s->condexec_mask) {
365af80e 10714 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 10715 } else {
9ef39277 10716 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 10717 gen_logic_CC(tmp2);
9ee6e8bb 10718 }
99c475ab
FB
10719 break;
10720 case 0x4: /* asr */
9ee6e8bb 10721 if (s->condexec_mask) {
365af80e 10722 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 10723 } else {
9ef39277 10724 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 10725 gen_logic_CC(tmp2);
9ee6e8bb 10726 }
99c475ab
FB
10727 break;
10728 case 0x5: /* adc */
49b4c31e 10729 if (s->condexec_mask) {
396e467c 10730 gen_adc(tmp, tmp2);
49b4c31e
RH
10731 } else {
10732 gen_adc_CC(tmp, tmp, tmp2);
10733 }
99c475ab
FB
10734 break;
10735 case 0x6: /* sbc */
2de68a49 10736 if (s->condexec_mask) {
396e467c 10737 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
10738 } else {
10739 gen_sbc_CC(tmp, tmp, tmp2);
10740 }
99c475ab
FB
10741 break;
10742 case 0x7: /* ror */
9ee6e8bb 10743 if (s->condexec_mask) {
f669df27
AJ
10744 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10745 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 10746 } else {
9ef39277 10747 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 10748 gen_logic_CC(tmp2);
9ee6e8bb 10749 }
99c475ab
FB
10750 break;
10751 case 0x8: /* tst */
396e467c
FN
10752 tcg_gen_and_i32(tmp, tmp, tmp2);
10753 gen_logic_CC(tmp);
99c475ab 10754 rd = 16;
5899f386 10755 break;
99c475ab 10756 case 0x9: /* neg */
9ee6e8bb 10757 if (s->condexec_mask)
396e467c 10758 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 10759 else
72485ec4 10760 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
10761 break;
10762 case 0xa: /* cmp */
72485ec4 10763 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
10764 rd = 16;
10765 break;
10766 case 0xb: /* cmn */
72485ec4 10767 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
10768 rd = 16;
10769 break;
10770 case 0xc: /* orr */
396e467c 10771 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 10772 if (!s->condexec_mask)
396e467c 10773 gen_logic_CC(tmp);
99c475ab
FB
10774 break;
10775 case 0xd: /* mul */
7b2919a0 10776 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 10777 if (!s->condexec_mask)
396e467c 10778 gen_logic_CC(tmp);
99c475ab
FB
10779 break;
10780 case 0xe: /* bic */
f669df27 10781 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 10782 if (!s->condexec_mask)
396e467c 10783 gen_logic_CC(tmp);
99c475ab
FB
10784 break;
10785 case 0xf: /* mvn */
396e467c 10786 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 10787 if (!s->condexec_mask)
396e467c 10788 gen_logic_CC(tmp2);
99c475ab 10789 val = 1;
5899f386 10790 rm = rd;
99c475ab
FB
10791 break;
10792 }
10793 if (rd != 16) {
396e467c
FN
10794 if (val) {
10795 store_reg(s, rm, tmp2);
10796 if (op != 0xf)
7d1b0095 10797 tcg_temp_free_i32(tmp);
396e467c
FN
10798 } else {
10799 store_reg(s, rd, tmp);
7d1b0095 10800 tcg_temp_free_i32(tmp2);
396e467c
FN
10801 }
10802 } else {
7d1b0095
PM
10803 tcg_temp_free_i32(tmp);
10804 tcg_temp_free_i32(tmp2);
99c475ab
FB
10805 }
10806 break;
10807
10808 case 5:
10809 /* load/store register offset. */
10810 rd = insn & 7;
10811 rn = (insn >> 3) & 7;
10812 rm = (insn >> 6) & 7;
10813 op = (insn >> 9) & 7;
b0109805 10814 addr = load_reg(s, rn);
b26eefb6 10815 tmp = load_reg(s, rm);
b0109805 10816 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10817 tcg_temp_free_i32(tmp);
99c475ab 10818
c40c8556 10819 if (op < 3) { /* store */
b0109805 10820 tmp = load_reg(s, rd);
c40c8556
PM
10821 } else {
10822 tmp = tcg_temp_new_i32();
10823 }
99c475ab
FB
10824
10825 switch (op) {
10826 case 0: /* str */
6ce2faf4 10827 gen_aa32_st32(tmp, addr, get_mem_index(s));
99c475ab
FB
10828 break;
10829 case 1: /* strh */
6ce2faf4 10830 gen_aa32_st16(tmp, addr, get_mem_index(s));
99c475ab
FB
10831 break;
10832 case 2: /* strb */
6ce2faf4 10833 gen_aa32_st8(tmp, addr, get_mem_index(s));
99c475ab
FB
10834 break;
10835 case 3: /* ldrsb */
6ce2faf4 10836 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
99c475ab
FB
10837 break;
10838 case 4: /* ldr */
6ce2faf4 10839 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
99c475ab
FB
10840 break;
10841 case 5: /* ldrh */
6ce2faf4 10842 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
99c475ab
FB
10843 break;
10844 case 6: /* ldrb */
6ce2faf4 10845 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
99c475ab
FB
10846 break;
10847 case 7: /* ldrsh */
6ce2faf4 10848 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
99c475ab
FB
10849 break;
10850 }
c40c8556 10851 if (op >= 3) { /* load */
b0109805 10852 store_reg(s, rd, tmp);
c40c8556
PM
10853 } else {
10854 tcg_temp_free_i32(tmp);
10855 }
7d1b0095 10856 tcg_temp_free_i32(addr);
99c475ab
FB
10857 break;
10858
10859 case 6:
10860 /* load/store word immediate offset */
10861 rd = insn & 7;
10862 rn = (insn >> 3) & 7;
b0109805 10863 addr = load_reg(s, rn);
99c475ab 10864 val = (insn >> 4) & 0x7c;
b0109805 10865 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
10866
10867 if (insn & (1 << 11)) {
10868 /* load */
c40c8556 10869 tmp = tcg_temp_new_i32();
6ce2faf4 10870 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 10871 store_reg(s, rd, tmp);
99c475ab
FB
10872 } else {
10873 /* store */
b0109805 10874 tmp = load_reg(s, rd);
6ce2faf4 10875 gen_aa32_st32(tmp, addr, get_mem_index(s));
c40c8556 10876 tcg_temp_free_i32(tmp);
99c475ab 10877 }
7d1b0095 10878 tcg_temp_free_i32(addr);
99c475ab
FB
10879 break;
10880
10881 case 7:
10882 /* load/store byte immediate offset */
10883 rd = insn & 7;
10884 rn = (insn >> 3) & 7;
b0109805 10885 addr = load_reg(s, rn);
99c475ab 10886 val = (insn >> 6) & 0x1f;
b0109805 10887 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
10888
10889 if (insn & (1 << 11)) {
10890 /* load */
c40c8556 10891 tmp = tcg_temp_new_i32();
6ce2faf4 10892 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
b0109805 10893 store_reg(s, rd, tmp);
99c475ab
FB
10894 } else {
10895 /* store */
b0109805 10896 tmp = load_reg(s, rd);
6ce2faf4 10897 gen_aa32_st8(tmp, addr, get_mem_index(s));
c40c8556 10898 tcg_temp_free_i32(tmp);
99c475ab 10899 }
7d1b0095 10900 tcg_temp_free_i32(addr);
99c475ab
FB
10901 break;
10902
10903 case 8:
10904 /* load/store halfword immediate offset */
10905 rd = insn & 7;
10906 rn = (insn >> 3) & 7;
b0109805 10907 addr = load_reg(s, rn);
99c475ab 10908 val = (insn >> 5) & 0x3e;
b0109805 10909 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
10910
10911 if (insn & (1 << 11)) {
10912 /* load */
c40c8556 10913 tmp = tcg_temp_new_i32();
6ce2faf4 10914 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
b0109805 10915 store_reg(s, rd, tmp);
99c475ab
FB
10916 } else {
10917 /* store */
b0109805 10918 tmp = load_reg(s, rd);
6ce2faf4 10919 gen_aa32_st16(tmp, addr, get_mem_index(s));
c40c8556 10920 tcg_temp_free_i32(tmp);
99c475ab 10921 }
7d1b0095 10922 tcg_temp_free_i32(addr);
99c475ab
FB
10923 break;
10924
10925 case 9:
10926 /* load/store from stack */
10927 rd = (insn >> 8) & 7;
b0109805 10928 addr = load_reg(s, 13);
99c475ab 10929 val = (insn & 0xff) * 4;
b0109805 10930 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
10931
10932 if (insn & (1 << 11)) {
10933 /* load */
c40c8556 10934 tmp = tcg_temp_new_i32();
6ce2faf4 10935 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 10936 store_reg(s, rd, tmp);
99c475ab
FB
10937 } else {
10938 /* store */
b0109805 10939 tmp = load_reg(s, rd);
6ce2faf4 10940 gen_aa32_st32(tmp, addr, get_mem_index(s));
c40c8556 10941 tcg_temp_free_i32(tmp);
99c475ab 10942 }
7d1b0095 10943 tcg_temp_free_i32(addr);
99c475ab
FB
10944 break;
10945
10946 case 10:
10947 /* add to high reg */
10948 rd = (insn >> 8) & 7;
5899f386
FB
10949 if (insn & (1 << 11)) {
10950 /* SP */
5e3f878a 10951 tmp = load_reg(s, 13);
5899f386
FB
10952 } else {
10953 /* PC. bit 1 is ignored. */
7d1b0095 10954 tmp = tcg_temp_new_i32();
5e3f878a 10955 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 10956 }
99c475ab 10957 val = (insn & 0xff) * 4;
5e3f878a
PB
10958 tcg_gen_addi_i32(tmp, tmp, val);
10959 store_reg(s, rd, tmp);
99c475ab
FB
10960 break;
10961
10962 case 11:
10963 /* misc */
10964 op = (insn >> 8) & 0xf;
10965 switch (op) {
10966 case 0:
10967 /* adjust stack pointer */
b26eefb6 10968 tmp = load_reg(s, 13);
99c475ab
FB
10969 val = (insn & 0x7f) * 4;
10970 if (insn & (1 << 7))
6a0d8a1d 10971 val = -(int32_t)val;
b26eefb6
PB
10972 tcg_gen_addi_i32(tmp, tmp, val);
10973 store_reg(s, 13, tmp);
99c475ab
FB
10974 break;
10975
9ee6e8bb
PB
10976 case 2: /* sign/zero extend. */
10977 ARCH(6);
10978 rd = insn & 7;
10979 rm = (insn >> 3) & 7;
b0109805 10980 tmp = load_reg(s, rm);
9ee6e8bb 10981 switch ((insn >> 6) & 3) {
b0109805
PB
10982 case 0: gen_sxth(tmp); break;
10983 case 1: gen_sxtb(tmp); break;
10984 case 2: gen_uxth(tmp); break;
10985 case 3: gen_uxtb(tmp); break;
9ee6e8bb 10986 }
b0109805 10987 store_reg(s, rd, tmp);
9ee6e8bb 10988 break;
99c475ab
FB
10989 case 4: case 5: case 0xc: case 0xd:
10990 /* push/pop */
b0109805 10991 addr = load_reg(s, 13);
5899f386
FB
10992 if (insn & (1 << 8))
10993 offset = 4;
99c475ab 10994 else
5899f386
FB
10995 offset = 0;
10996 for (i = 0; i < 8; i++) {
10997 if (insn & (1 << i))
10998 offset += 4;
10999 }
11000 if ((insn & (1 << 11)) == 0) {
b0109805 11001 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11002 }
99c475ab
FB
11003 for (i = 0; i < 8; i++) {
11004 if (insn & (1 << i)) {
11005 if (insn & (1 << 11)) {
11006 /* pop */
c40c8556 11007 tmp = tcg_temp_new_i32();
6ce2faf4 11008 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
b0109805 11009 store_reg(s, i, tmp);
99c475ab
FB
11010 } else {
11011 /* push */
b0109805 11012 tmp = load_reg(s, i);
6ce2faf4 11013 gen_aa32_st32(tmp, addr, get_mem_index(s));
c40c8556 11014 tcg_temp_free_i32(tmp);
99c475ab 11015 }
5899f386 11016 /* advance to the next address. */
b0109805 11017 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11018 }
11019 }
39d5492a 11020 TCGV_UNUSED_I32(tmp);
99c475ab
FB
11021 if (insn & (1 << 8)) {
11022 if (insn & (1 << 11)) {
11023 /* pop pc */
c40c8556 11024 tmp = tcg_temp_new_i32();
6ce2faf4 11025 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
99c475ab
FB
11026 /* don't set the pc until the rest of the instruction
11027 has completed */
11028 } else {
11029 /* push lr */
b0109805 11030 tmp = load_reg(s, 14);
6ce2faf4 11031 gen_aa32_st32(tmp, addr, get_mem_index(s));
c40c8556 11032 tcg_temp_free_i32(tmp);
99c475ab 11033 }
b0109805 11034 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 11035 }
5899f386 11036 if ((insn & (1 << 11)) == 0) {
b0109805 11037 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11038 }
99c475ab 11039 /* write back the new stack pointer */
b0109805 11040 store_reg(s, 13, addr);
99c475ab 11041 /* set the new PC value */
be5e7a76 11042 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 11043 store_reg_from_load(s, 15, tmp);
be5e7a76 11044 }
99c475ab
FB
11045 break;
11046
9ee6e8bb
PB
11047 case 1: case 3: case 9: case 11: /* czb */
11048 rm = insn & 7;
d9ba4830 11049 tmp = load_reg(s, rm);
9ee6e8bb
PB
11050 s->condlabel = gen_new_label();
11051 s->condjmp = 1;
11052 if (insn & (1 << 11))
cb63669a 11053 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 11054 else
cb63669a 11055 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 11056 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
11057 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
11058 val = (uint32_t)s->pc + 2;
11059 val += offset;
11060 gen_jmp(s, val);
11061 break;
11062
11063 case 15: /* IT, nop-hint. */
11064 if ((insn & 0xf) == 0) {
11065 gen_nop_hint(s, (insn >> 4) & 0xf);
11066 break;
11067 }
11068 /* If Then. */
11069 s->condexec_cond = (insn >> 4) & 0xe;
11070 s->condexec_mask = insn & 0x1f;
11071 /* No actual code generated for this insn, just setup state. */
11072 break;
11073
06c949e6 11074 case 0xe: /* bkpt */
d4a2dc67
PM
11075 {
11076 int imm8 = extract32(insn, 0, 8);
be5e7a76 11077 ARCH(5);
73710361
GB
11078 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true),
11079 default_exception_el(s));
06c949e6 11080 break;
d4a2dc67 11081 }
06c949e6 11082
9ee6e8bb
PB
11083 case 0xa: /* rev */
11084 ARCH(6);
11085 rn = (insn >> 3) & 0x7;
11086 rd = insn & 0x7;
b0109805 11087 tmp = load_reg(s, rn);
9ee6e8bb 11088 switch ((insn >> 6) & 3) {
66896cb8 11089 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
11090 case 1: gen_rev16(tmp); break;
11091 case 3: gen_revsh(tmp); break;
9ee6e8bb
PB
11092 default: goto illegal_op;
11093 }
b0109805 11094 store_reg(s, rd, tmp);
9ee6e8bb
PB
11095 break;
11096
d9e028c1
PM
11097 case 6:
11098 switch ((insn >> 5) & 7) {
11099 case 2:
11100 /* setend */
11101 ARCH(6);
10962fd5
PM
11102 if (((insn >> 3) & 1) != s->bswap_code) {
11103 /* Dynamic endianness switching not implemented. */
e0c270d9 11104 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
d9e028c1
PM
11105 goto illegal_op;
11106 }
9ee6e8bb 11107 break;
d9e028c1
PM
11108 case 3:
11109 /* cps */
11110 ARCH(6);
11111 if (IS_USER(s)) {
11112 break;
8984bd2e 11113 }
b53d8923 11114 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
11115 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
11116 /* FAULTMASK */
11117 if (insn & 1) {
11118 addr = tcg_const_i32(19);
11119 gen_helper_v7m_msr(cpu_env, addr, tmp);
11120 tcg_temp_free_i32(addr);
11121 }
11122 /* PRIMASK */
11123 if (insn & 2) {
11124 addr = tcg_const_i32(16);
11125 gen_helper_v7m_msr(cpu_env, addr, tmp);
11126 tcg_temp_free_i32(addr);
11127 }
11128 tcg_temp_free_i32(tmp);
11129 gen_lookup_tb(s);
11130 } else {
11131 if (insn & (1 << 4)) {
11132 shift = CPSR_A | CPSR_I | CPSR_F;
11133 } else {
11134 shift = 0;
11135 }
11136 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 11137 }
d9e028c1
PM
11138 break;
11139 default:
11140 goto undef;
9ee6e8bb
PB
11141 }
11142 break;
11143
99c475ab
FB
11144 default:
11145 goto undef;
11146 }
11147 break;
11148
11149 case 12:
a7d3970d 11150 {
99c475ab 11151 /* load/store multiple */
39d5492a
PM
11152 TCGv_i32 loaded_var;
11153 TCGV_UNUSED_I32(loaded_var);
99c475ab 11154 rn = (insn >> 8) & 0x7;
b0109805 11155 addr = load_reg(s, rn);
99c475ab
FB
11156 for (i = 0; i < 8; i++) {
11157 if (insn & (1 << i)) {
99c475ab
FB
11158 if (insn & (1 << 11)) {
11159 /* load */
c40c8556 11160 tmp = tcg_temp_new_i32();
6ce2faf4 11161 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
a7d3970d
PM
11162 if (i == rn) {
11163 loaded_var = tmp;
11164 } else {
11165 store_reg(s, i, tmp);
11166 }
99c475ab
FB
11167 } else {
11168 /* store */
b0109805 11169 tmp = load_reg(s, i);
6ce2faf4 11170 gen_aa32_st32(tmp, addr, get_mem_index(s));
c40c8556 11171 tcg_temp_free_i32(tmp);
99c475ab 11172 }
5899f386 11173 /* advance to the next address */
b0109805 11174 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11175 }
11176 }
b0109805 11177 if ((insn & (1 << rn)) == 0) {
a7d3970d 11178 /* base reg not in list: base register writeback */
b0109805
PB
11179 store_reg(s, rn, addr);
11180 } else {
a7d3970d
PM
11181 /* base reg in list: if load, complete it now */
11182 if (insn & (1 << 11)) {
11183 store_reg(s, rn, loaded_var);
11184 }
7d1b0095 11185 tcg_temp_free_i32(addr);
b0109805 11186 }
99c475ab 11187 break;
a7d3970d 11188 }
99c475ab
FB
11189 case 13:
11190 /* conditional branch or swi */
11191 cond = (insn >> 8) & 0xf;
11192 if (cond == 0xe)
11193 goto undef;
11194
11195 if (cond == 0xf) {
11196 /* swi */
eaed129d 11197 gen_set_pc_im(s, s->pc);
d4a2dc67 11198 s->svc_imm = extract32(insn, 0, 8);
9ee6e8bb 11199 s->is_jmp = DISAS_SWI;
99c475ab
FB
11200 break;
11201 }
11202 /* generate a conditional jump to next instruction */
e50e6a20 11203 s->condlabel = gen_new_label();
39fb730a 11204 arm_gen_test_cc(cond ^ 1, s->condlabel);
e50e6a20 11205 s->condjmp = 1;
99c475ab
FB
11206
11207 /* jump to the offset */
5899f386 11208 val = (uint32_t)s->pc + 2;
99c475ab 11209 offset = ((int32_t)insn << 24) >> 24;
5899f386 11210 val += offset << 1;
8aaca4c0 11211 gen_jmp(s, val);
99c475ab
FB
11212 break;
11213
11214 case 14:
358bf29e 11215 if (insn & (1 << 11)) {
9ee6e8bb
PB
11216 if (disas_thumb2_insn(env, s, insn))
11217 goto undef32;
358bf29e
PB
11218 break;
11219 }
9ee6e8bb 11220 /* unconditional branch */
99c475ab
FB
11221 val = (uint32_t)s->pc;
11222 offset = ((int32_t)insn << 21) >> 21;
11223 val += (offset << 1) + 2;
8aaca4c0 11224 gen_jmp(s, val);
99c475ab
FB
11225 break;
11226
11227 case 15:
9ee6e8bb 11228 if (disas_thumb2_insn(env, s, insn))
6a0d8a1d 11229 goto undef32;
9ee6e8bb 11230 break;
99c475ab
FB
11231 }
11232 return;
9ee6e8bb 11233undef32:
73710361
GB
11234 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11235 default_exception_el(s));
9ee6e8bb
PB
11236 return;
11237illegal_op:
99c475ab 11238undef:
73710361
GB
11239 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
11240 default_exception_el(s));
99c475ab
FB
11241}
11242
541ebcd4
PM
11243static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11244{
11245 /* Return true if the insn at dc->pc might cross a page boundary.
11246 * (False positives are OK, false negatives are not.)
11247 */
11248 uint16_t insn;
11249
11250 if ((s->pc & 3) == 0) {
11251 /* At a 4-aligned address we can't be crossing a page */
11252 return false;
11253 }
11254
11255 /* This must be a Thumb insn */
11256 insn = arm_lduw_code(env, s->pc, s->bswap_code);
11257
11258 if ((insn >> 11) >= 0x1d) {
11259 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
11260 * First half of a 32-bit Thumb insn. Thumb-1 cores might
11261 * end up actually treating this as two 16-bit insns (see the
11262 * code at the start of disas_thumb2_insn()) but we don't bother
11263 * to check for that as it is unlikely, and false positives here
11264 * are harmless.
11265 */
11266 return true;
11267 }
11268 /* Definitely a 16-bit insn, can't be crossing a page. */
11269 return false;
11270}
11271
20157705 11272/* generate intermediate code for basic block 'tb'. */
4e5e1215 11273void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
2c0262af 11274{
4e5e1215 11275 ARMCPU *cpu = arm_env_get_cpu(env);
ed2803da 11276 CPUState *cs = CPU(cpu);
2c0262af 11277 DisasContext dc1, *dc = &dc1;
0fa85d43 11278 target_ulong pc_start;
0a2461fa 11279 target_ulong next_page_start;
2e70f6ef
PB
11280 int num_insns;
11281 int max_insns;
541ebcd4 11282 bool end_of_page;
3b46e624 11283
2c0262af 11284 /* generate intermediate code */
40f860cd
PM
11285
11286 /* The A64 decoder has its own top level loop, because it doesn't need
11287 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
11288 */
11289 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
4e5e1215 11290 gen_intermediate_code_a64(cpu, tb);
40f860cd
PM
11291 return;
11292 }
11293
0fa85d43 11294 pc_start = tb->pc;
3b46e624 11295
2c0262af
FB
11296 dc->tb = tb;
11297
2c0262af
FB
11298 dc->is_jmp = DISAS_NEXT;
11299 dc->pc = pc_start;
ed2803da 11300 dc->singlestep_enabled = cs->singlestep_enabled;
e50e6a20 11301 dc->condjmp = 0;
3926cc84 11302
40f860cd 11303 dc->aarch64 = 0;
cef9ee70
SS
11304 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
11305 * there is no secure EL1, so we route exceptions to EL3.
11306 */
11307 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11308 !arm_el_is_aa64(env, 3);
40f860cd
PM
11309 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
11310 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
11311 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
11312 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
c1e37810
PM
11313 dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
11314 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 11315#if !defined(CONFIG_USER_ONLY)
c1e37810 11316 dc->user = (dc->current_el == 0);
3926cc84 11317#endif
3f342b9e 11318 dc->ns = ARM_TBFLAG_NS(tb->flags);
9dbbc748 11319 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(tb->flags);
40f860cd
PM
11320 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
11321 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
11322 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
c0f4af17 11323 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
60322b39 11324 dc->cp_regs = cpu->cp_regs;
a984e42c 11325 dc->features = env->features;
40f860cd 11326
50225ad0
PM
11327 /* Single step state. The code-generation logic here is:
11328 * SS_ACTIVE == 0:
11329 * generate code with no special handling for single-stepping (except
11330 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11331 * this happens anyway because those changes are all system register or
11332 * PSTATE writes).
11333 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11334 * emit code for one insn
11335 * emit code to clear PSTATE.SS
11336 * emit code to generate software step exception for completed step
11337 * end TB (as usual for having generated an exception)
11338 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11339 * emit code to generate a software step exception
11340 * end the TB
11341 */
11342 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
11343 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
11344 dc->is_ldex = false;
11345 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
11346
a7812ae4
PB
11347 cpu_F0s = tcg_temp_new_i32();
11348 cpu_F1s = tcg_temp_new_i32();
11349 cpu_F0d = tcg_temp_new_i64();
11350 cpu_F1d = tcg_temp_new_i64();
ad69471c
PB
11351 cpu_V0 = cpu_F0d;
11352 cpu_V1 = cpu_F1d;
e677137d 11353 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 11354 cpu_M0 = tcg_temp_new_i64();
b5ff1b31 11355 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2e70f6ef
PB
11356 num_insns = 0;
11357 max_insns = tb->cflags & CF_COUNT_MASK;
190ce7fb 11358 if (max_insns == 0) {
2e70f6ef 11359 max_insns = CF_COUNT_MASK;
190ce7fb
RH
11360 }
11361 if (max_insns > TCG_MAX_INSNS) {
11362 max_insns = TCG_MAX_INSNS;
11363 }
2e70f6ef 11364
cd42d5b2 11365 gen_tb_start(tb);
e12ce78d 11366
3849902c
PM
11367 tcg_clear_temp_count();
11368
e12ce78d
PM
11369 /* A note on handling of the condexec (IT) bits:
11370 *
11371 * We want to avoid the overhead of having to write the updated condexec
0ecb72a5 11372 * bits back to the CPUARMState for every instruction in an IT block. So:
e12ce78d 11373 * (1) if the condexec bits are not already zero then we write
0ecb72a5 11374 * zero back into the CPUARMState now. This avoids complications trying
e12ce78d
PM
11375 * to do it at the end of the block. (For example if we don't do this
11376 * it's hard to identify whether we can safely skip writing condexec
11377 * at the end of the TB, which we definitely want to do for the case
11378 * where a TB doesn't do anything with the IT state at all.)
11379 * (2) if we are going to leave the TB then we call gen_set_condexec()
0ecb72a5 11380 * which will write the correct value into CPUARMState if zero is wrong.
e12ce78d
PM
11381 * This is done both for leaving the TB at the end, and for leaving
11382 * it because of an exception we know will happen, which is done in
11383 * gen_exception_insn(). The latter is necessary because we need to
11384 * leave the TB with the PC/IT state just prior to execution of the
11385 * instruction which caused the exception.
11386 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
0ecb72a5 11387 * then the CPUARMState will be wrong and we need to reset it.
e12ce78d 11388 * This is handled in the same way as restoration of the
4e5e1215
RH
11389 * PC in these situations; we save the value of the condexec bits
11390 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
11391 * then uses this to restore them after an exception.
e12ce78d
PM
11392 *
11393 * Note that there are no instructions which can read the condexec
11394 * bits, and none which can write non-static values to them, so
0ecb72a5 11395 * we don't need to care about whether CPUARMState is correct in the
e12ce78d
PM
11396 * middle of a TB.
11397 */
11398
9ee6e8bb
PB
11399 /* Reset the conditional execution bits immediately. This avoids
11400 complications trying to do it at the end of the block. */
98eac7ca 11401 if (dc->condexec_mask || dc->condexec_cond)
8f01245e 11402 {
39d5492a 11403 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e 11404 tcg_gen_movi_i32(tmp, 0);
d9ba4830 11405 store_cpu_field(tmp, condexec_bits);
8f01245e 11406 }
2c0262af 11407 do {
52e971d9
RH
11408 tcg_gen_insn_start(dc->pc,
11409 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1));
b933066a
RH
11410 num_insns++;
11411
fbb4a2e3
PB
11412#ifdef CONFIG_USER_ONLY
11413 /* Intercept jump to the magic kernel page. */
40f860cd 11414 if (dc->pc >= 0xffff0000) {
fbb4a2e3
PB
11415 /* We always get here via a jump, so know we are not in a
11416 conditional execution block. */
d4a2dc67 11417 gen_exception_internal(EXCP_KERNEL_TRAP);
577bf808 11418 dc->is_jmp = DISAS_EXC;
fbb4a2e3
PB
11419 break;
11420 }
11421#else
b53d8923 11422 if (dc->pc >= 0xfffffff0 && arm_dc_feature(dc, ARM_FEATURE_M)) {
9ee6e8bb
PB
11423 /* We always get here via a jump, so know we are not in a
11424 conditional execution block. */
d4a2dc67 11425 gen_exception_internal(EXCP_EXCEPTION_EXIT);
577bf808 11426 dc->is_jmp = DISAS_EXC;
d60bb01c 11427 break;
9ee6e8bb
PB
11428 }
11429#endif
11430
f0c3c505 11431 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
b933066a 11432 CPUBreakpoint *bp;
f0c3c505 11433 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
a1d1bb31 11434 if (bp->pc == dc->pc) {
5d98bf8f 11435 if (bp->flags & BP_CPU) {
ce8a1b54 11436 gen_set_condexec(dc);
ed6c6448 11437 gen_set_pc_im(dc, dc->pc);
5d98bf8f
SF
11438 gen_helper_check_breakpoints(cpu_env);
11439 /* End the TB early; it's likely not going to be executed */
11440 dc->is_jmp = DISAS_UPDATE;
11441 } else {
11442 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
522a0d4e
RH
11443 /* The address covered by the breakpoint must be
11444 included in [tb->pc, tb->pc + tb->size) in order
11445 to for it to be properly cleared -- thus we
11446 increment the PC here so that the logic setting
11447 tb->size below does the right thing. */
5d98bf8f
SF
11448 /* TODO: Advance PC by correct instruction length to
11449 * avoid disassembler error messages */
11450 dc->pc += 2;
11451 goto done_generating;
11452 }
11453 break;
1fddef4b
FB
11454 }
11455 }
11456 }
e50e6a20 11457
959082fc 11458 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
2e70f6ef 11459 gen_io_start();
959082fc 11460 }
2e70f6ef 11461
50225ad0
PM
11462 if (dc->ss_active && !dc->pstate_ss) {
11463 /* Singlestep state is Active-pending.
11464 * If we're in this state at the start of a TB then either
11465 * a) we just took an exception to an EL which is being debugged
11466 * and this is the first insn in the exception handler
11467 * b) debug exceptions were masked and we just unmasked them
11468 * without changing EL (eg by clearing PSTATE.D)
11469 * In either case we're going to take a swstep exception in the
11470 * "did not step an insn" case, and so the syndrome ISV and EX
11471 * bits should be zero.
11472 */
959082fc 11473 assert(num_insns == 1);
73710361
GB
11474 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
11475 default_exception_el(dc));
50225ad0
PM
11476 goto done_generating;
11477 }
11478
40f860cd 11479 if (dc->thumb) {
9ee6e8bb
PB
11480 disas_thumb_insn(env, dc);
11481 if (dc->condexec_mask) {
11482 dc->condexec_cond = (dc->condexec_cond & 0xe)
11483 | ((dc->condexec_mask >> 4) & 1);
11484 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11485 if (dc->condexec_mask == 0) {
11486 dc->condexec_cond = 0;
11487 }
11488 }
11489 } else {
f4df2210
PM
11490 unsigned int insn = arm_ldl_code(env, dc->pc, dc->bswap_code);
11491 dc->pc += 4;
11492 disas_arm_insn(dc, insn);
9ee6e8bb 11493 }
e50e6a20
FB
11494
11495 if (dc->condjmp && !dc->is_jmp) {
11496 gen_set_label(dc->condlabel);
11497 dc->condjmp = 0;
11498 }
3849902c
PM
11499
11500 if (tcg_check_temp_count()) {
0a2461fa
AG
11501 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11502 dc->pc);
3849902c
PM
11503 }
11504
aaf2d97d 11505 /* Translation stops when a conditional branch is encountered.
e50e6a20 11506 * Otherwise the subsequent code could get translated several times.
b5ff1b31 11507 * Also stop translation when a page boundary is reached. This
bf20dc07 11508 * ensures prefetch aborts occur at the right place. */
541ebcd4
PM
11509
11510 /* We want to stop the TB if the next insn starts in a new page,
11511 * or if it spans between this page and the next. This means that
11512 * if we're looking at the last halfword in the page we need to
11513 * see if it's a 16-bit Thumb insn (which will fit in this TB)
11514 * or a 32-bit Thumb insn (which won't).
11515 * This is to avoid generating a silly TB with a single 16-bit insn
11516 * in it at the end of this page (which would execute correctly
11517 * but isn't very efficient).
11518 */
11519 end_of_page = (dc->pc >= next_page_start) ||
11520 ((dc->pc >= next_page_start - 3) && insn_crosses_page(env, dc));
11521
fe700adb 11522 } while (!dc->is_jmp && !tcg_op_buf_full() &&
ed2803da 11523 !cs->singlestep_enabled &&
1b530a6d 11524 !singlestep &&
50225ad0 11525 !dc->ss_active &&
541ebcd4 11526 !end_of_page &&
2e70f6ef
PB
11527 num_insns < max_insns);
11528
11529 if (tb->cflags & CF_LAST_IO) {
11530 if (dc->condjmp) {
11531 /* FIXME: This can theoretically happen with self-modifying
11532 code. */
a47dddd7 11533 cpu_abort(cs, "IO on conditional branch instruction");
2e70f6ef
PB
11534 }
11535 gen_io_end();
11536 }
9ee6e8bb 11537
b5ff1b31 11538 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
11539 instruction was a conditional branch or trap, and the PC has
11540 already been written. */
50225ad0 11541 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
7999a5c8 11542 /* Unconditional and "condition passed" instruction codepath. */
9ee6e8bb 11543 gen_set_condexec(dc);
7999a5c8
SF
11544 switch (dc->is_jmp) {
11545 case DISAS_SWI:
50225ad0 11546 gen_ss_advance(dc);
73710361
GB
11547 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11548 default_exception_el(dc));
7999a5c8
SF
11549 break;
11550 case DISAS_HVC:
37e6456e 11551 gen_ss_advance(dc);
73710361 11552 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
11553 break;
11554 case DISAS_SMC:
37e6456e 11555 gen_ss_advance(dc);
73710361 11556 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
11557 break;
11558 case DISAS_NEXT:
11559 case DISAS_UPDATE:
11560 gen_set_pc_im(dc, dc->pc);
11561 /* fall through */
11562 default:
11563 if (dc->ss_active) {
11564 gen_step_complete_exception(dc);
11565 } else {
11566 /* FIXME: Single stepping a WFI insn will not halt
11567 the CPU. */
11568 gen_exception_internal(EXCP_DEBUG);
11569 }
11570 }
11571 if (dc->condjmp) {
11572 /* "Condition failed" instruction codepath. */
11573 gen_set_label(dc->condlabel);
11574 gen_set_condexec(dc);
11575 gen_set_pc_im(dc, dc->pc);
11576 if (dc->ss_active) {
11577 gen_step_complete_exception(dc);
11578 } else {
11579 gen_exception_internal(EXCP_DEBUG);
11580 }
9ee6e8bb 11581 }
8aaca4c0 11582 } else {
9ee6e8bb
PB
11583 /* While branches must always occur at the end of an IT block,
11584 there are a few other things that can cause us to terminate
65626741 11585 the TB in the middle of an IT block:
9ee6e8bb
PB
11586 - Exception generating instructions (bkpt, swi, undefined).
11587 - Page boundaries.
11588 - Hardware watchpoints.
11589 Hardware breakpoints have already been handled and skip this code.
11590 */
11591 gen_set_condexec(dc);
8aaca4c0 11592 switch(dc->is_jmp) {
8aaca4c0 11593 case DISAS_NEXT:
6e256c93 11594 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0 11595 break;
8aaca4c0 11596 case DISAS_UPDATE:
577bf808
SF
11597 gen_set_pc_im(dc, dc->pc);
11598 /* fall through */
11599 case DISAS_JUMP:
11600 default:
8aaca4c0 11601 /* indicate that the hash table must be used to find the next TB */
57fec1fe 11602 tcg_gen_exit_tb(0);
8aaca4c0
FB
11603 break;
11604 case DISAS_TB_JUMP:
11605 /* nothing more to generate */
11606 break;
9ee6e8bb 11607 case DISAS_WFI:
1ce94f81 11608 gen_helper_wfi(cpu_env);
84549b6d
PM
11609 /* The helper doesn't necessarily throw an exception, but we
11610 * must go back to the main loop to check for interrupts anyway.
11611 */
11612 tcg_gen_exit_tb(0);
9ee6e8bb 11613 break;
72c1d3af
PM
11614 case DISAS_WFE:
11615 gen_helper_wfe(cpu_env);
11616 break;
c87e5a61
PM
11617 case DISAS_YIELD:
11618 gen_helper_yield(cpu_env);
11619 break;
9ee6e8bb 11620 case DISAS_SWI:
73710361
GB
11621 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11622 default_exception_el(dc));
9ee6e8bb 11623 break;
37e6456e 11624 case DISAS_HVC:
73710361 11625 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
11626 break;
11627 case DISAS_SMC:
73710361 11628 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 11629 break;
8aaca4c0 11630 }
e50e6a20
FB
11631 if (dc->condjmp) {
11632 gen_set_label(dc->condlabel);
9ee6e8bb 11633 gen_set_condexec(dc);
6e256c93 11634 gen_goto_tb(dc, 1, dc->pc);
e50e6a20
FB
11635 dc->condjmp = 0;
11636 }
2c0262af 11637 }
2e70f6ef 11638
9ee6e8bb 11639done_generating:
806f352d 11640 gen_tb_end(tb, num_insns);
2c0262af
FB
11641
11642#ifdef DEBUG_DISAS
8fec2b8c 11643 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
11644 qemu_log("----------------\n");
11645 qemu_log("IN: %s\n", lookup_symbol(pc_start));
d49190c4 11646 log_target_disas(cs, pc_start, dc->pc - pc_start,
d8fd2954 11647 dc->thumb | (dc->bswap_code << 1));
93fcfe39 11648 qemu_log("\n");
2c0262af
FB
11649 }
11650#endif
4e5e1215
RH
11651 tb->size = dc->pc - pc_start;
11652 tb->icount = num_insns;
2c0262af
FB
11653}
11654
b5ff1b31 11655static const char *cpu_mode_names[16] = {
28c9457d
EI
11656 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11657 "???", "???", "hyp", "und", "???", "???", "???", "sys"
b5ff1b31 11658};
9ee6e8bb 11659
878096ee
AF
11660void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11661 int flags)
2c0262af 11662{
878096ee
AF
11663 ARMCPU *cpu = ARM_CPU(cs);
11664 CPUARMState *env = &cpu->env;
2c0262af 11665 int i;
b5ff1b31 11666 uint32_t psr;
06e5cf7a 11667 const char *ns_status;
2c0262af 11668
17731115
PM
11669 if (is_a64(env)) {
11670 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11671 return;
11672 }
11673
2c0262af 11674 for(i=0;i<16;i++) {
7fe48483 11675 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 11676 if ((i % 4) == 3)
7fe48483 11677 cpu_fprintf(f, "\n");
2c0262af 11678 else
7fe48483 11679 cpu_fprintf(f, " ");
2c0262af 11680 }
b5ff1b31 11681 psr = cpsr_read(env);
06e5cf7a
PM
11682
11683 if (arm_feature(env, ARM_FEATURE_EL3) &&
11684 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
11685 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
11686 } else {
11687 ns_status = "";
11688 }
11689
11690 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
687fa640 11691 psr,
b5ff1b31
FB
11692 psr & (1 << 31) ? 'N' : '-',
11693 psr & (1 << 30) ? 'Z' : '-',
11694 psr & (1 << 29) ? 'C' : '-',
11695 psr & (1 << 28) ? 'V' : '-',
5fafdf24 11696 psr & CPSR_T ? 'T' : 'A',
06e5cf7a 11697 ns_status,
b5ff1b31 11698 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
b7bcbe95 11699
f2617cfc
PM
11700 if (flags & CPU_DUMP_FPU) {
11701 int numvfpregs = 0;
11702 if (arm_feature(env, ARM_FEATURE_VFP)) {
11703 numvfpregs += 16;
11704 }
11705 if (arm_feature(env, ARM_FEATURE_VFP3)) {
11706 numvfpregs += 16;
11707 }
11708 for (i = 0; i < numvfpregs; i++) {
11709 uint64_t v = float64_val(env->vfp.regs[i]);
11710 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
11711 i * 2, (uint32_t)v,
11712 i * 2 + 1, (uint32_t)(v >> 32),
11713 i, v);
11714 }
11715 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
b7bcbe95 11716 }
2c0262af 11717}
a6b025d3 11718
bad729e2
RH
11719void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
11720 target_ulong *data)
d2856f1a 11721{
3926cc84 11722 if (is_a64(env)) {
bad729e2 11723 env->pc = data[0];
40f860cd 11724 env->condexec_bits = 0;
3926cc84 11725 } else {
bad729e2
RH
11726 env->regs[15] = data[0];
11727 env->condexec_bits = data[1];
3926cc84 11728 }
d2856f1a 11729}