]> git.proxmox.com Git - mirror_qemu.git/blame - target/arm/translate.c
target/arm: Introduce ARM_FEATURE_M_MAIN
[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"
63c91552 26#include "exec/exec-all.h"
57fec1fe 27#include "tcg-op.h"
36a71934 28#include "tcg-op-gvec.h"
1de7afc9 29#include "qemu/log.h"
534df156 30#include "qemu/bitops.h"
1d854765 31#include "arm_ldst.h"
19a6e31c 32#include "exec/semihost.h"
1497c961 33
2ef6175a
RH
34#include "exec/helper-proto.h"
35#include "exec/helper-gen.h"
2c0262af 36
a7e30d84 37#include "trace-tcg.h"
508127e2 38#include "exec/log.h"
a7e30d84
LV
39
40
2b51668f
PM
41#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
be5e7a76 43/* currently all emulated v5 cores are also v5TE, so don't bother */
2b51668f 44#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
c99a55d3 45#define ENABLE_ARCH_5J arm_dc_feature(s, ARM_FEATURE_JAZELLE)
2b51668f
PM
46#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
47#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
48#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
49#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
50#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
b5ff1b31 51
86753403 52#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 53
f570c61e 54#include "translate.h"
e12ce78d 55
b5ff1b31
FB
56#if defined(CONFIG_USER_ONLY)
57#define IS_USER(s) 1
58#else
59#define IS_USER(s) (s->user)
60#endif
61
ad69471c 62/* We reuse the same 64-bit temporaries for efficiency. */
a7812ae4 63static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
155c3eac 64static TCGv_i32 cpu_R[16];
78bcaa3e
RH
65TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66TCGv_i64 cpu_exclusive_addr;
67TCGv_i64 cpu_exclusive_val;
ad69471c 68
b26eefb6 69/* FIXME: These should be removed. */
39d5492a 70static TCGv_i32 cpu_F0s, cpu_F1s;
a7812ae4 71static TCGv_i64 cpu_F0d, cpu_F1d;
b26eefb6 72
022c62cb 73#include "exec/gen-icount.h"
2e70f6ef 74
155c3eac
FN
75static const char *regnames[] =
76 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
78
61adacc8
RH
79/* Function prototypes for gen_ functions calling Neon helpers. */
80typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
81 TCGv_i32, TCGv_i32);
82
b26eefb6
PB
83/* initialize TCG globals. */
84void arm_translate_init(void)
85{
155c3eac
FN
86 int i;
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");
155c3eac 102
14ade10f 103 a64_translate_init();
b26eefb6
PB
104}
105
9bb6558a
PM
106/* Flags for the disas_set_da_iss info argument:
107 * lower bits hold the Rt register number, higher bits are flags.
108 */
109typedef enum ISSInfo {
110 ISSNone = 0,
111 ISSRegMask = 0x1f,
112 ISSInvalid = (1 << 5),
113 ISSIsAcqRel = (1 << 6),
114 ISSIsWrite = (1 << 7),
115 ISSIs16Bit = (1 << 8),
116} ISSInfo;
117
118/* Save the syndrome information for a Data Abort */
119static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
120{
121 uint32_t syn;
122 int sas = memop & MO_SIZE;
123 bool sse = memop & MO_SIGN;
124 bool is_acqrel = issinfo & ISSIsAcqRel;
125 bool is_write = issinfo & ISSIsWrite;
126 bool is_16bit = issinfo & ISSIs16Bit;
127 int srt = issinfo & ISSRegMask;
128
129 if (issinfo & ISSInvalid) {
130 /* Some callsites want to conditionally provide ISS info,
131 * eg "only if this was not a writeback"
132 */
133 return;
134 }
135
136 if (srt == 15) {
137 /* For AArch32, insns where the src/dest is R15 never generate
138 * ISS information. Catching that here saves checking at all
139 * the call sites.
140 */
141 return;
142 }
143
144 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
145 0, 0, 0, is_write, 0, is_16bit);
146 disas_set_insn_syndrome(s, syn);
147}
148
8bd5c820 149static inline int get_a32_user_mem_index(DisasContext *s)
579d21cc 150{
8bd5c820 151 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
579d21cc
PM
152 * insns:
153 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
154 * otherwise, access as if at PL0.
155 */
156 switch (s->mmu_idx) {
157 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
158 case ARMMMUIdx_S12NSE0:
159 case ARMMMUIdx_S12NSE1:
8bd5c820 160 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
579d21cc
PM
161 case ARMMMUIdx_S1E3:
162 case ARMMMUIdx_S1SE0:
163 case ARMMMUIdx_S1SE1:
8bd5c820 164 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
e7b921c2
PM
165 case ARMMMUIdx_MUser:
166 case ARMMMUIdx_MPriv:
167 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
62593718
PM
168 case ARMMMUIdx_MUserNegPri:
169 case ARMMMUIdx_MPrivNegPri:
170 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
b9f587d6
PM
171 case ARMMMUIdx_MSUser:
172 case ARMMMUIdx_MSPriv:
b9f587d6 173 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
62593718
PM
174 case ARMMMUIdx_MSUserNegPri:
175 case ARMMMUIdx_MSPrivNegPri:
176 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
579d21cc
PM
177 case ARMMMUIdx_S2NS:
178 default:
179 g_assert_not_reached();
180 }
181}
182
39d5492a 183static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 184{
39d5492a 185 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
186 tcg_gen_ld_i32(tmp, cpu_env, offset);
187 return tmp;
188}
189
0ecb72a5 190#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 191
39d5492a 192static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
193{
194 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 195 tcg_temp_free_i32(var);
d9ba4830
PB
196}
197
198#define store_cpu_field(var, name) \
0ecb72a5 199 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 200
b26eefb6 201/* Set a variable to the value of a CPU register. */
39d5492a 202static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
203{
204 if (reg == 15) {
205 uint32_t addr;
b90372ad 206 /* normally, since we updated PC, we need only to add one insn */
b26eefb6
PB
207 if (s->thumb)
208 addr = (long)s->pc + 2;
209 else
210 addr = (long)s->pc + 4;
211 tcg_gen_movi_i32(var, addr);
212 } else {
155c3eac 213 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
214 }
215}
216
217/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 218static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 219{
39d5492a 220 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
221 load_reg_var(s, tmp, reg);
222 return tmp;
223}
224
225/* Set a CPU register. The source must be a temporary and will be
226 marked as dead. */
39d5492a 227static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
228{
229 if (reg == 15) {
9b6a3ea7
PM
230 /* In Thumb mode, we must ignore bit 0.
231 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
232 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
233 * We choose to ignore [1:0] in ARM mode for all architecture versions.
234 */
235 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
dcba3a8d 236 s->base.is_jmp = DISAS_JUMP;
b26eefb6 237 }
155c3eac 238 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 239 tcg_temp_free_i32(var);
b26eefb6
PB
240}
241
b26eefb6 242/* Value extensions. */
86831435
PB
243#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
244#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
245#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
246#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
247
1497c961
PB
248#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
249#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 250
b26eefb6 251
39d5492a 252static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 253{
39d5492a 254 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 255 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
256 tcg_temp_free_i32(tmp_mask);
257}
d9ba4830
PB
258/* Set NZCV flags from the high 4 bits of var. */
259#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
260
d4a2dc67 261static void gen_exception_internal(int excp)
d9ba4830 262{
d4a2dc67
PM
263 TCGv_i32 tcg_excp = tcg_const_i32(excp);
264
265 assert(excp_is_internal(excp));
266 gen_helper_exception_internal(cpu_env, tcg_excp);
267 tcg_temp_free_i32(tcg_excp);
268}
269
73710361 270static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
d4a2dc67
PM
271{
272 TCGv_i32 tcg_excp = tcg_const_i32(excp);
273 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
73710361 274 TCGv_i32 tcg_el = tcg_const_i32(target_el);
d4a2dc67 275
73710361
GB
276 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
277 tcg_syn, tcg_el);
278
279 tcg_temp_free_i32(tcg_el);
d4a2dc67
PM
280 tcg_temp_free_i32(tcg_syn);
281 tcg_temp_free_i32(tcg_excp);
d9ba4830
PB
282}
283
50225ad0
PM
284static void gen_ss_advance(DisasContext *s)
285{
286 /* If the singlestep state is Active-not-pending, advance to
287 * Active-pending.
288 */
289 if (s->ss_active) {
290 s->pstate_ss = 0;
291 gen_helper_clear_pstate_ss(cpu_env);
292 }
293}
294
295static void gen_step_complete_exception(DisasContext *s)
296{
297 /* We just completed step of an insn. Move from Active-not-pending
298 * to Active-pending, and then also take the swstep exception.
299 * This corresponds to making the (IMPDEF) choice to prioritize
300 * swstep exceptions over asynchronous exceptions taken to an exception
301 * level where debug is disabled. This choice has the advantage that
302 * we do not need to maintain internal state corresponding to the
303 * ISV/EX syndrome bits between completion of the step and generation
304 * of the exception, and our syndrome information is always correct.
305 */
306 gen_ss_advance(s);
73710361
GB
307 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
308 default_exception_el(s));
dcba3a8d 309 s->base.is_jmp = DISAS_NORETURN;
50225ad0
PM
310}
311
5425415e
PM
312static void gen_singlestep_exception(DisasContext *s)
313{
314 /* Generate the right kind of exception for singlestep, which is
315 * either the architectural singlestep or EXCP_DEBUG for QEMU's
316 * gdb singlestepping.
317 */
318 if (s->ss_active) {
319 gen_step_complete_exception(s);
320 } else {
321 gen_exception_internal(EXCP_DEBUG);
322 }
323}
324
b636649f
PM
325static inline bool is_singlestepping(DisasContext *s)
326{
327 /* Return true if we are singlestepping either because of
328 * architectural singlestep or QEMU gdbstub singlestep. This does
329 * not include the command line '-singlestep' mode which is rather
330 * misnamed as it only means "one instruction per TB" and doesn't
331 * affect the code we generate.
332 */
dcba3a8d 333 return s->base.singlestep_enabled || s->ss_active;
b636649f
PM
334}
335
39d5492a 336static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 337{
39d5492a
PM
338 TCGv_i32 tmp1 = tcg_temp_new_i32();
339 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
340 tcg_gen_ext16s_i32(tmp1, a);
341 tcg_gen_ext16s_i32(tmp2, b);
3670669c 342 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 343 tcg_temp_free_i32(tmp2);
3670669c
PB
344 tcg_gen_sari_i32(a, a, 16);
345 tcg_gen_sari_i32(b, b, 16);
346 tcg_gen_mul_i32(b, b, a);
347 tcg_gen_mov_i32(a, tmp1);
7d1b0095 348 tcg_temp_free_i32(tmp1);
3670669c
PB
349}
350
351/* Byteswap each halfword. */
39d5492a 352static void gen_rev16(TCGv_i32 var)
3670669c 353{
39d5492a 354 TCGv_i32 tmp = tcg_temp_new_i32();
68cedf73 355 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
3670669c 356 tcg_gen_shri_i32(tmp, var, 8);
68cedf73
AJ
357 tcg_gen_and_i32(tmp, tmp, mask);
358 tcg_gen_and_i32(var, var, mask);
3670669c 359 tcg_gen_shli_i32(var, var, 8);
3670669c 360 tcg_gen_or_i32(var, var, tmp);
68cedf73 361 tcg_temp_free_i32(mask);
7d1b0095 362 tcg_temp_free_i32(tmp);
3670669c
PB
363}
364
365/* Byteswap low halfword and sign extend. */
39d5492a 366static void gen_revsh(TCGv_i32 var)
3670669c 367{
1a855029
AJ
368 tcg_gen_ext16u_i32(var, var);
369 tcg_gen_bswap16_i32(var, var);
370 tcg_gen_ext16s_i32(var, var);
3670669c
PB
371}
372
838fa72d 373/* Return (b << 32) + a. Mark inputs as dead */
39d5492a 374static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
3670669c 375{
838fa72d
AJ
376 TCGv_i64 tmp64 = tcg_temp_new_i64();
377
378 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 379 tcg_temp_free_i32(b);
838fa72d
AJ
380 tcg_gen_shli_i64(tmp64, tmp64, 32);
381 tcg_gen_add_i64(a, tmp64, a);
382
383 tcg_temp_free_i64(tmp64);
384 return a;
385}
386
387/* Return (b << 32) - a. Mark inputs as dead. */
39d5492a 388static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
838fa72d
AJ
389{
390 TCGv_i64 tmp64 = tcg_temp_new_i64();
391
392 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 393 tcg_temp_free_i32(b);
838fa72d
AJ
394 tcg_gen_shli_i64(tmp64, tmp64, 32);
395 tcg_gen_sub_i64(a, tmp64, a);
396
397 tcg_temp_free_i64(tmp64);
398 return a;
3670669c
PB
399}
400
5e3f878a 401/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 402static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 403{
39d5492a
PM
404 TCGv_i32 lo = tcg_temp_new_i32();
405 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 406 TCGv_i64 ret;
5e3f878a 407
831d7fe8 408 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 409 tcg_temp_free_i32(a);
7d1b0095 410 tcg_temp_free_i32(b);
831d7fe8
RH
411
412 ret = tcg_temp_new_i64();
413 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
414 tcg_temp_free_i32(lo);
415 tcg_temp_free_i32(hi);
831d7fe8
RH
416
417 return ret;
5e3f878a
PB
418}
419
39d5492a 420static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 421{
39d5492a
PM
422 TCGv_i32 lo = tcg_temp_new_i32();
423 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 424 TCGv_i64 ret;
5e3f878a 425
831d7fe8 426 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 427 tcg_temp_free_i32(a);
7d1b0095 428 tcg_temp_free_i32(b);
831d7fe8
RH
429
430 ret = tcg_temp_new_i64();
431 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
432 tcg_temp_free_i32(lo);
433 tcg_temp_free_i32(hi);
831d7fe8
RH
434
435 return ret;
5e3f878a
PB
436}
437
8f01245e 438/* Swap low and high halfwords. */
39d5492a 439static void gen_swap_half(TCGv_i32 var)
8f01245e 440{
39d5492a 441 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e
PB
442 tcg_gen_shri_i32(tmp, var, 16);
443 tcg_gen_shli_i32(var, var, 16);
444 tcg_gen_or_i32(var, var, tmp);
7d1b0095 445 tcg_temp_free_i32(tmp);
8f01245e
PB
446}
447
b26eefb6
PB
448/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
449 tmp = (t0 ^ t1) & 0x8000;
450 t0 &= ~0x8000;
451 t1 &= ~0x8000;
452 t0 = (t0 + t1) ^ tmp;
453 */
454
39d5492a 455static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 456{
39d5492a 457 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
458 tcg_gen_xor_i32(tmp, t0, t1);
459 tcg_gen_andi_i32(tmp, tmp, 0x8000);
460 tcg_gen_andi_i32(t0, t0, ~0x8000);
461 tcg_gen_andi_i32(t1, t1, ~0x8000);
462 tcg_gen_add_i32(t0, t0, t1);
463 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
464 tcg_temp_free_i32(tmp);
465 tcg_temp_free_i32(t1);
b26eefb6
PB
466}
467
468/* Set CF to the top bit of var. */
39d5492a 469static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 470{
66c374de 471 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
472}
473
474/* Set N and Z flags from var. */
39d5492a 475static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 476{
66c374de
AJ
477 tcg_gen_mov_i32(cpu_NF, var);
478 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
479}
480
481/* T0 += T1 + CF. */
39d5492a 482static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 483{
396e467c 484 tcg_gen_add_i32(t0, t0, t1);
66c374de 485 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
486}
487
e9bb4aa9 488/* dest = T0 + T1 + CF. */
39d5492a 489static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 490{
e9bb4aa9 491 tcg_gen_add_i32(dest, t0, t1);
66c374de 492 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
493}
494
3670669c 495/* dest = T0 - T1 + CF - 1. */
39d5492a 496static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 497{
3670669c 498 tcg_gen_sub_i32(dest, t0, t1);
66c374de 499 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 500 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
501}
502
72485ec4 503/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 504static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 505{
39d5492a 506 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
507 tcg_gen_movi_i32(tmp, 0);
508 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 509 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 510 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
511 tcg_gen_xor_i32(tmp, t0, t1);
512 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
513 tcg_temp_free_i32(tmp);
514 tcg_gen_mov_i32(dest, cpu_NF);
515}
516
49b4c31e 517/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 518static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 519{
39d5492a 520 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
521 if (TCG_TARGET_HAS_add2_i32) {
522 tcg_gen_movi_i32(tmp, 0);
523 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 524 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
525 } else {
526 TCGv_i64 q0 = tcg_temp_new_i64();
527 TCGv_i64 q1 = tcg_temp_new_i64();
528 tcg_gen_extu_i32_i64(q0, t0);
529 tcg_gen_extu_i32_i64(q1, t1);
530 tcg_gen_add_i64(q0, q0, q1);
531 tcg_gen_extu_i32_i64(q1, cpu_CF);
532 tcg_gen_add_i64(q0, q0, q1);
533 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
534 tcg_temp_free_i64(q0);
535 tcg_temp_free_i64(q1);
536 }
537 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
538 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
539 tcg_gen_xor_i32(tmp, t0, t1);
540 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
541 tcg_temp_free_i32(tmp);
542 tcg_gen_mov_i32(dest, cpu_NF);
543}
544
72485ec4 545/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 546static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 547{
39d5492a 548 TCGv_i32 tmp;
72485ec4
AJ
549 tcg_gen_sub_i32(cpu_NF, t0, t1);
550 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
551 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
552 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
553 tmp = tcg_temp_new_i32();
554 tcg_gen_xor_i32(tmp, t0, t1);
555 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
556 tcg_temp_free_i32(tmp);
557 tcg_gen_mov_i32(dest, cpu_NF);
558}
559
e77f0832 560/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 561static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 562{
39d5492a 563 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
564 tcg_gen_not_i32(tmp, t1);
565 gen_adc_CC(dest, t0, tmp);
39d5492a 566 tcg_temp_free_i32(tmp);
2de68a49
RH
567}
568
365af80e 569#define GEN_SHIFT(name) \
39d5492a 570static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 571{ \
39d5492a 572 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
573 tmp1 = tcg_temp_new_i32(); \
574 tcg_gen_andi_i32(tmp1, t1, 0xff); \
575 tmp2 = tcg_const_i32(0); \
576 tmp3 = tcg_const_i32(0x1f); \
577 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
578 tcg_temp_free_i32(tmp3); \
579 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
580 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
581 tcg_temp_free_i32(tmp2); \
582 tcg_temp_free_i32(tmp1); \
583}
584GEN_SHIFT(shl)
585GEN_SHIFT(shr)
586#undef GEN_SHIFT
587
39d5492a 588static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 589{
39d5492a 590 TCGv_i32 tmp1, tmp2;
365af80e
AJ
591 tmp1 = tcg_temp_new_i32();
592 tcg_gen_andi_i32(tmp1, t1, 0xff);
593 tmp2 = tcg_const_i32(0x1f);
594 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
595 tcg_temp_free_i32(tmp2);
596 tcg_gen_sar_i32(dest, t0, tmp1);
597 tcg_temp_free_i32(tmp1);
598}
599
39d5492a 600static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
36c91fd1 601{
39d5492a
PM
602 TCGv_i32 c0 = tcg_const_i32(0);
603 TCGv_i32 tmp = tcg_temp_new_i32();
36c91fd1
PM
604 tcg_gen_neg_i32(tmp, src);
605 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
606 tcg_temp_free_i32(c0);
607 tcg_temp_free_i32(tmp);
608}
ad69471c 609
39d5492a 610static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 611{
9a119ff6 612 if (shift == 0) {
66c374de 613 tcg_gen_andi_i32(cpu_CF, var, 1);
b26eefb6 614 } else {
66c374de
AJ
615 tcg_gen_shri_i32(cpu_CF, var, shift);
616 if (shift != 31) {
617 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
618 }
9a119ff6 619 }
9a119ff6 620}
b26eefb6 621
9a119ff6 622/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
623static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
624 int shift, int flags)
9a119ff6
PB
625{
626 switch (shiftop) {
627 case 0: /* LSL */
628 if (shift != 0) {
629 if (flags)
630 shifter_out_im(var, 32 - shift);
631 tcg_gen_shli_i32(var, var, shift);
632 }
633 break;
634 case 1: /* LSR */
635 if (shift == 0) {
636 if (flags) {
66c374de 637 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
638 }
639 tcg_gen_movi_i32(var, 0);
640 } else {
641 if (flags)
642 shifter_out_im(var, shift - 1);
643 tcg_gen_shri_i32(var, var, shift);
644 }
645 break;
646 case 2: /* ASR */
647 if (shift == 0)
648 shift = 32;
649 if (flags)
650 shifter_out_im(var, shift - 1);
651 if (shift == 32)
652 shift = 31;
653 tcg_gen_sari_i32(var, var, shift);
654 break;
655 case 3: /* ROR/RRX */
656 if (shift != 0) {
657 if (flags)
658 shifter_out_im(var, shift - 1);
f669df27 659 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 660 } else {
39d5492a 661 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 662 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
663 if (flags)
664 shifter_out_im(var, 0);
665 tcg_gen_shri_i32(var, var, 1);
b26eefb6 666 tcg_gen_or_i32(var, var, tmp);
7d1b0095 667 tcg_temp_free_i32(tmp);
b26eefb6
PB
668 }
669 }
670};
671
39d5492a
PM
672static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
673 TCGv_i32 shift, int flags)
8984bd2e
PB
674{
675 if (flags) {
676 switch (shiftop) {
9ef39277
BS
677 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
678 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
679 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
680 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
681 }
682 } else {
683 switch (shiftop) {
365af80e
AJ
684 case 0:
685 gen_shl(var, var, shift);
686 break;
687 case 1:
688 gen_shr(var, var, shift);
689 break;
690 case 2:
691 gen_sar(var, var, shift);
692 break;
f669df27
AJ
693 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
694 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
695 }
696 }
7d1b0095 697 tcg_temp_free_i32(shift);
8984bd2e
PB
698}
699
6ddbc6e4
PB
700#define PAS_OP(pfx) \
701 switch (op2) { \
702 case 0: gen_pas_helper(glue(pfx,add16)); break; \
703 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
704 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
705 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
706 case 4: gen_pas_helper(glue(pfx,add8)); break; \
707 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
708 }
39d5492a 709static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 710{
a7812ae4 711 TCGv_ptr tmp;
6ddbc6e4
PB
712
713 switch (op1) {
714#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
715 case 1:
a7812ae4 716 tmp = tcg_temp_new_ptr();
0ecb72a5 717 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 718 PAS_OP(s)
b75263d6 719 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
720 break;
721 case 5:
a7812ae4 722 tmp = tcg_temp_new_ptr();
0ecb72a5 723 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 724 PAS_OP(u)
b75263d6 725 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
726 break;
727#undef gen_pas_helper
728#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
729 case 2:
730 PAS_OP(q);
731 break;
732 case 3:
733 PAS_OP(sh);
734 break;
735 case 6:
736 PAS_OP(uq);
737 break;
738 case 7:
739 PAS_OP(uh);
740 break;
741#undef gen_pas_helper
742 }
743}
9ee6e8bb
PB
744#undef PAS_OP
745
6ddbc6e4
PB
746/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
747#define PAS_OP(pfx) \
ed89a2f1 748 switch (op1) { \
6ddbc6e4
PB
749 case 0: gen_pas_helper(glue(pfx,add8)); break; \
750 case 1: gen_pas_helper(glue(pfx,add16)); break; \
751 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
752 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
753 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
754 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
755 }
39d5492a 756static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 757{
a7812ae4 758 TCGv_ptr tmp;
6ddbc6e4 759
ed89a2f1 760 switch (op2) {
6ddbc6e4
PB
761#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
762 case 0:
a7812ae4 763 tmp = tcg_temp_new_ptr();
0ecb72a5 764 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 765 PAS_OP(s)
b75263d6 766 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
767 break;
768 case 4:
a7812ae4 769 tmp = tcg_temp_new_ptr();
0ecb72a5 770 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 771 PAS_OP(u)
b75263d6 772 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
773 break;
774#undef gen_pas_helper
775#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
776 case 1:
777 PAS_OP(q);
778 break;
779 case 2:
780 PAS_OP(sh);
781 break;
782 case 5:
783 PAS_OP(uq);
784 break;
785 case 6:
786 PAS_OP(uh);
787 break;
788#undef gen_pas_helper
789 }
790}
9ee6e8bb
PB
791#undef PAS_OP
792
39fb730a 793/*
6c2c63d3 794 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
795 * This is common between ARM and Aarch64 targets.
796 */
6c2c63d3 797void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 798{
6c2c63d3
RH
799 TCGv_i32 value;
800 TCGCond cond;
801 bool global = true;
d9ba4830 802
d9ba4830
PB
803 switch (cc) {
804 case 0: /* eq: Z */
d9ba4830 805 case 1: /* ne: !Z */
6c2c63d3
RH
806 cond = TCG_COND_EQ;
807 value = cpu_ZF;
d9ba4830 808 break;
6c2c63d3 809
d9ba4830 810 case 2: /* cs: C */
d9ba4830 811 case 3: /* cc: !C */
6c2c63d3
RH
812 cond = TCG_COND_NE;
813 value = cpu_CF;
d9ba4830 814 break;
6c2c63d3 815
d9ba4830 816 case 4: /* mi: N */
d9ba4830 817 case 5: /* pl: !N */
6c2c63d3
RH
818 cond = TCG_COND_LT;
819 value = cpu_NF;
d9ba4830 820 break;
6c2c63d3 821
d9ba4830 822 case 6: /* vs: V */
d9ba4830 823 case 7: /* vc: !V */
6c2c63d3
RH
824 cond = TCG_COND_LT;
825 value = cpu_VF;
d9ba4830 826 break;
6c2c63d3 827
d9ba4830 828 case 8: /* hi: C && !Z */
6c2c63d3
RH
829 case 9: /* ls: !C || Z -> !(C && !Z) */
830 cond = TCG_COND_NE;
831 value = tcg_temp_new_i32();
832 global = false;
833 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
834 ZF is non-zero for !Z; so AND the two subexpressions. */
835 tcg_gen_neg_i32(value, cpu_CF);
836 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 837 break;
6c2c63d3 838
d9ba4830 839 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 840 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
841 /* Since we're only interested in the sign bit, == 0 is >= 0. */
842 cond = TCG_COND_GE;
843 value = tcg_temp_new_i32();
844 global = false;
845 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 846 break;
6c2c63d3 847
d9ba4830 848 case 12: /* gt: !Z && N == V */
d9ba4830 849 case 13: /* le: Z || N != V */
6c2c63d3
RH
850 cond = TCG_COND_NE;
851 value = tcg_temp_new_i32();
852 global = false;
853 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
854 * the sign bit then AND with ZF to yield the result. */
855 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
856 tcg_gen_sari_i32(value, value, 31);
857 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 858 break;
6c2c63d3 859
9305eac0
RH
860 case 14: /* always */
861 case 15: /* always */
862 /* Use the ALWAYS condition, which will fold early.
863 * It doesn't matter what we use for the value. */
864 cond = TCG_COND_ALWAYS;
865 value = cpu_ZF;
866 goto no_invert;
867
d9ba4830
PB
868 default:
869 fprintf(stderr, "Bad condition code 0x%x\n", cc);
870 abort();
871 }
6c2c63d3
RH
872
873 if (cc & 1) {
874 cond = tcg_invert_cond(cond);
875 }
876
9305eac0 877 no_invert:
6c2c63d3
RH
878 cmp->cond = cond;
879 cmp->value = value;
880 cmp->value_global = global;
881}
882
883void arm_free_cc(DisasCompare *cmp)
884{
885 if (!cmp->value_global) {
886 tcg_temp_free_i32(cmp->value);
887 }
888}
889
890void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
891{
892 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
893}
894
895void arm_gen_test_cc(int cc, TCGLabel *label)
896{
897 DisasCompare cmp;
898 arm_test_cc(&cmp, cc);
899 arm_jump_cc(&cmp, label);
900 arm_free_cc(&cmp);
d9ba4830 901}
2c0262af 902
b1d8e52e 903static const uint8_t table_logic_cc[16] = {
2c0262af
FB
904 1, /* and */
905 1, /* xor */
906 0, /* sub */
907 0, /* rsb */
908 0, /* add */
909 0, /* adc */
910 0, /* sbc */
911 0, /* rsc */
912 1, /* andl */
913 1, /* xorl */
914 0, /* cmp */
915 0, /* cmn */
916 1, /* orr */
917 1, /* mov */
918 1, /* bic */
919 1, /* mvn */
920};
3b46e624 921
4d5e8c96
PM
922static inline void gen_set_condexec(DisasContext *s)
923{
924 if (s->condexec_mask) {
925 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
926 TCGv_i32 tmp = tcg_temp_new_i32();
927 tcg_gen_movi_i32(tmp, val);
928 store_cpu_field(tmp, condexec_bits);
929 }
930}
931
932static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
933{
934 tcg_gen_movi_i32(cpu_R[15], val);
935}
936
d9ba4830
PB
937/* Set PC and Thumb state from an immediate address. */
938static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 939{
39d5492a 940 TCGv_i32 tmp;
99c475ab 941
dcba3a8d 942 s->base.is_jmp = DISAS_JUMP;
d9ba4830 943 if (s->thumb != (addr & 1)) {
7d1b0095 944 tmp = tcg_temp_new_i32();
d9ba4830 945 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 946 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 947 tcg_temp_free_i32(tmp);
d9ba4830 948 }
155c3eac 949 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
950}
951
952/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 953static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 954{
dcba3a8d 955 s->base.is_jmp = DISAS_JUMP;
155c3eac
FN
956 tcg_gen_andi_i32(cpu_R[15], var, ~1);
957 tcg_gen_andi_i32(var, var, 1);
958 store_cpu_field(var, thumb);
d9ba4830
PB
959}
960
3bb8a96f
PM
961/* Set PC and Thumb state from var. var is marked as dead.
962 * For M-profile CPUs, include logic to detect exception-return
963 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
964 * and BX reg, and no others, and happens only for code in Handler mode.
965 */
966static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
967{
968 /* Generate the same code here as for a simple bx, but flag via
dcba3a8d 969 * s->base.is_jmp that we need to do the rest of the work later.
3bb8a96f
PM
970 */
971 gen_bx(s, var);
d02a8698
PM
972 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
973 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
dcba3a8d 974 s->base.is_jmp = DISAS_BX_EXCRET;
3bb8a96f
PM
975 }
976}
977
978static inline void gen_bx_excret_final_code(DisasContext *s)
979{
980 /* Generate the code to finish possible exception return and end the TB */
981 TCGLabel *excret_label = gen_new_label();
d02a8698
PM
982 uint32_t min_magic;
983
984 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
985 /* Covers FNC_RETURN and EXC_RETURN magic */
986 min_magic = FNC_RETURN_MIN_MAGIC;
987 } else {
988 /* EXC_RETURN magic only */
989 min_magic = EXC_RETURN_MIN_MAGIC;
990 }
3bb8a96f
PM
991
992 /* Is the new PC value in the magic range indicating exception return? */
d02a8698 993 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
3bb8a96f
PM
994 /* No: end the TB as we would for a DISAS_JMP */
995 if (is_singlestepping(s)) {
996 gen_singlestep_exception(s);
997 } else {
07ea28b4 998 tcg_gen_exit_tb(NULL, 0);
3bb8a96f
PM
999 }
1000 gen_set_label(excret_label);
1001 /* Yes: this is an exception return.
1002 * At this point in runtime env->regs[15] and env->thumb will hold
1003 * the exception-return magic number, which do_v7m_exception_exit()
1004 * will read. Nothing else will be able to see those values because
1005 * the cpu-exec main loop guarantees that we will always go straight
1006 * from raising the exception to the exception-handling code.
1007 *
1008 * gen_ss_advance(s) does nothing on M profile currently but
1009 * calling it is conceptually the right thing as we have executed
1010 * this instruction (compare SWI, HVC, SMC handling).
1011 */
1012 gen_ss_advance(s);
1013 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1014}
1015
fb602cb7
PM
1016static inline void gen_bxns(DisasContext *s, int rm)
1017{
1018 TCGv_i32 var = load_reg(s, rm);
1019
1020 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1021 * we need to sync state before calling it, but:
1022 * - we don't need to do gen_set_pc_im() because the bxns helper will
1023 * always set the PC itself
1024 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1025 * unless it's outside an IT block or the last insn in an IT block,
1026 * so we know that condexec == 0 (already set at the top of the TB)
1027 * is correct in the non-UNPREDICTABLE cases, and we can choose
1028 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1029 */
1030 gen_helper_v7m_bxns(cpu_env, var);
1031 tcg_temp_free_i32(var);
ef475b5d 1032 s->base.is_jmp = DISAS_EXIT;
fb602cb7
PM
1033}
1034
3e3fa230
PM
1035static inline void gen_blxns(DisasContext *s, int rm)
1036{
1037 TCGv_i32 var = load_reg(s, rm);
1038
1039 /* We don't need to sync condexec state, for the same reason as bxns.
1040 * We do however need to set the PC, because the blxns helper reads it.
1041 * The blxns helper may throw an exception.
1042 */
1043 gen_set_pc_im(s, s->pc);
1044 gen_helper_v7m_blxns(cpu_env, var);
1045 tcg_temp_free_i32(var);
1046 s->base.is_jmp = DISAS_EXIT;
1047}
1048
21aeb343
JR
1049/* Variant of store_reg which uses branch&exchange logic when storing
1050 to r15 in ARM architecture v7 and above. The source must be a temporary
1051 and will be marked as dead. */
7dcc1f89 1052static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
1053{
1054 if (reg == 15 && ENABLE_ARCH_7) {
1055 gen_bx(s, var);
1056 } else {
1057 store_reg(s, reg, var);
1058 }
1059}
1060
be5e7a76
DES
1061/* Variant of store_reg which uses branch&exchange logic when storing
1062 * to r15 in ARM architecture v5T and above. This is used for storing
1063 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1064 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 1065static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
1066{
1067 if (reg == 15 && ENABLE_ARCH_5) {
3bb8a96f 1068 gen_bx_excret(s, var);
be5e7a76
DES
1069 } else {
1070 store_reg(s, reg, var);
1071 }
1072}
1073
e334bd31
PB
1074#ifdef CONFIG_USER_ONLY
1075#define IS_USER_ONLY 1
1076#else
1077#define IS_USER_ONLY 0
1078#endif
1079
08307563
PM
1080/* Abstractions of "generate code to do a guest load/store for
1081 * AArch32", where a vaddr is always 32 bits (and is zero
1082 * extended if we're a 64 bit core) and data is also
1083 * 32 bits unless specifically doing a 64 bit access.
1084 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 1085 * that the address argument is TCGv_i32 rather than TCGv.
08307563 1086 */
08307563 1087
7f5616f5 1088static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
08307563 1089{
7f5616f5
RH
1090 TCGv addr = tcg_temp_new();
1091 tcg_gen_extu_i32_tl(addr, a32);
1092
e334bd31 1093 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
1094 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1095 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 1096 }
7f5616f5 1097 return addr;
08307563
PM
1098}
1099
7f5616f5
RH
1100static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1101 int index, TCGMemOp opc)
08307563 1102{
7f5616f5
RH
1103 TCGv addr = gen_aa32_addr(s, a32, opc);
1104 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1105 tcg_temp_free(addr);
08307563
PM
1106}
1107
7f5616f5
RH
1108static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1109 int index, TCGMemOp opc)
1110{
1111 TCGv addr = gen_aa32_addr(s, a32, opc);
1112 tcg_gen_qemu_st_i32(val, addr, index, opc);
1113 tcg_temp_free(addr);
1114}
08307563 1115
7f5616f5 1116#define DO_GEN_LD(SUFF, OPC) \
12dcc321 1117static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1118 TCGv_i32 a32, int index) \
08307563 1119{ \
7f5616f5 1120 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1121} \
1122static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1123 TCGv_i32 val, \
1124 TCGv_i32 a32, int index, \
1125 ISSInfo issinfo) \
1126{ \
1127 gen_aa32_ld##SUFF(s, val, a32, index); \
1128 disas_set_da_iss(s, OPC, issinfo); \
08307563
PM
1129}
1130
7f5616f5 1131#define DO_GEN_ST(SUFF, OPC) \
12dcc321 1132static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1133 TCGv_i32 a32, int index) \
08307563 1134{ \
7f5616f5 1135 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1136} \
1137static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1138 TCGv_i32 val, \
1139 TCGv_i32 a32, int index, \
1140 ISSInfo issinfo) \
1141{ \
1142 gen_aa32_st##SUFF(s, val, a32, index); \
1143 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
08307563
PM
1144}
1145
7f5616f5 1146static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 1147{
e334bd31
PB
1148 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1149 if (!IS_USER_ONLY && s->sctlr_b) {
1150 tcg_gen_rotri_i64(val, val, 32);
1151 }
08307563
PM
1152}
1153
7f5616f5
RH
1154static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1155 int index, TCGMemOp opc)
08307563 1156{
7f5616f5
RH
1157 TCGv addr = gen_aa32_addr(s, a32, opc);
1158 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1159 gen_aa32_frob64(s, val);
1160 tcg_temp_free(addr);
1161}
1162
1163static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1164 TCGv_i32 a32, int index)
1165{
1166 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1167}
1168
1169static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1170 int index, TCGMemOp opc)
1171{
1172 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
1173
1174 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1175 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 1176 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 1177 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1178 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1179 tcg_temp_free_i64(tmp);
e334bd31 1180 } else {
7f5616f5 1181 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1182 }
7f5616f5 1183 tcg_temp_free(addr);
08307563
PM
1184}
1185
7f5616f5
RH
1186static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1187 TCGv_i32 a32, int index)
1188{
1189 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1190}
08307563 1191
7f5616f5
RH
1192DO_GEN_LD(8s, MO_SB)
1193DO_GEN_LD(8u, MO_UB)
1194DO_GEN_LD(16s, MO_SW)
1195DO_GEN_LD(16u, MO_UW)
1196DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1197DO_GEN_ST(8, MO_UB)
1198DO_GEN_ST(16, MO_UW)
1199DO_GEN_ST(32, MO_UL)
08307563 1200
37e6456e
PM
1201static inline void gen_hvc(DisasContext *s, int imm16)
1202{
1203 /* The pre HVC helper handles cases when HVC gets trapped
1204 * as an undefined insn by runtime configuration (ie before
1205 * the insn really executes).
1206 */
1207 gen_set_pc_im(s, s->pc - 4);
1208 gen_helper_pre_hvc(cpu_env);
1209 /* Otherwise we will treat this as a real exception which
1210 * happens after execution of the insn. (The distinction matters
1211 * for the PC value reported to the exception handler and also
1212 * for single stepping.)
1213 */
1214 s->svc_imm = imm16;
1215 gen_set_pc_im(s, s->pc);
dcba3a8d 1216 s->base.is_jmp = DISAS_HVC;
37e6456e
PM
1217}
1218
1219static inline void gen_smc(DisasContext *s)
1220{
1221 /* As with HVC, we may take an exception either before or after
1222 * the insn executes.
1223 */
1224 TCGv_i32 tmp;
1225
1226 gen_set_pc_im(s, s->pc - 4);
1227 tmp = tcg_const_i32(syn_aa32_smc());
1228 gen_helper_pre_smc(cpu_env, tmp);
1229 tcg_temp_free_i32(tmp);
1230 gen_set_pc_im(s, s->pc);
dcba3a8d 1231 s->base.is_jmp = DISAS_SMC;
37e6456e
PM
1232}
1233
d4a2dc67
PM
1234static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1235{
1236 gen_set_condexec(s);
1237 gen_set_pc_im(s, s->pc - offset);
1238 gen_exception_internal(excp);
dcba3a8d 1239 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1240}
1241
73710361
GB
1242static void gen_exception_insn(DisasContext *s, int offset, int excp,
1243 int syn, uint32_t target_el)
d4a2dc67
PM
1244{
1245 gen_set_condexec(s);
1246 gen_set_pc_im(s, s->pc - offset);
73710361 1247 gen_exception(excp, syn, target_el);
dcba3a8d 1248 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1249}
1250
c900a2e6
PM
1251static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1252{
1253 TCGv_i32 tcg_syn;
1254
1255 gen_set_condexec(s);
1256 gen_set_pc_im(s, s->pc - offset);
1257 tcg_syn = tcg_const_i32(syn);
1258 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1259 tcg_temp_free_i32(tcg_syn);
1260 s->base.is_jmp = DISAS_NORETURN;
1261}
1262
b5ff1b31
FB
1263/* Force a TB lookup after an instruction that changes the CPU state. */
1264static inline void gen_lookup_tb(DisasContext *s)
1265{
a6445c52 1266 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
dcba3a8d 1267 s->base.is_jmp = DISAS_EXIT;
b5ff1b31
FB
1268}
1269
19a6e31c
PM
1270static inline void gen_hlt(DisasContext *s, int imm)
1271{
1272 /* HLT. This has two purposes.
1273 * Architecturally, it is an external halting debug instruction.
1274 * Since QEMU doesn't implement external debug, we treat this as
1275 * it is required for halting debug disabled: it will UNDEF.
1276 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1277 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1278 * must trigger semihosting even for ARMv7 and earlier, where
1279 * HLT was an undefined encoding.
1280 * In system mode, we don't allow userspace access to
1281 * semihosting, to provide some semblance of security
1282 * (and for consistency with our 32-bit semihosting).
1283 */
1284 if (semihosting_enabled() &&
1285#ifndef CONFIG_USER_ONLY
1286 s->current_el != 0 &&
1287#endif
1288 (imm == (s->thumb ? 0x3c : 0xf000))) {
1289 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1290 return;
1291 }
1292
1293 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1294 default_exception_el(s));
1295}
1296
b0109805 1297static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1298 TCGv_i32 var)
2c0262af 1299{
1e8d4eec 1300 int val, rm, shift, shiftop;
39d5492a 1301 TCGv_i32 offset;
2c0262af
FB
1302
1303 if (!(insn & (1 << 25))) {
1304 /* immediate */
1305 val = insn & 0xfff;
1306 if (!(insn & (1 << 23)))
1307 val = -val;
537730b9 1308 if (val != 0)
b0109805 1309 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1310 } else {
1311 /* shift/register */
1312 rm = (insn) & 0xf;
1313 shift = (insn >> 7) & 0x1f;
1e8d4eec 1314 shiftop = (insn >> 5) & 3;
b26eefb6 1315 offset = load_reg(s, rm);
9a119ff6 1316 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1317 if (!(insn & (1 << 23)))
b0109805 1318 tcg_gen_sub_i32(var, var, offset);
2c0262af 1319 else
b0109805 1320 tcg_gen_add_i32(var, var, offset);
7d1b0095 1321 tcg_temp_free_i32(offset);
2c0262af
FB
1322 }
1323}
1324
191f9a93 1325static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1326 int extra, TCGv_i32 var)
2c0262af
FB
1327{
1328 int val, rm;
39d5492a 1329 TCGv_i32 offset;
3b46e624 1330
2c0262af
FB
1331 if (insn & (1 << 22)) {
1332 /* immediate */
1333 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1334 if (!(insn & (1 << 23)))
1335 val = -val;
18acad92 1336 val += extra;
537730b9 1337 if (val != 0)
b0109805 1338 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1339 } else {
1340 /* register */
191f9a93 1341 if (extra)
b0109805 1342 tcg_gen_addi_i32(var, var, extra);
2c0262af 1343 rm = (insn) & 0xf;
b26eefb6 1344 offset = load_reg(s, rm);
2c0262af 1345 if (!(insn & (1 << 23)))
b0109805 1346 tcg_gen_sub_i32(var, var, offset);
2c0262af 1347 else
b0109805 1348 tcg_gen_add_i32(var, var, offset);
7d1b0095 1349 tcg_temp_free_i32(offset);
2c0262af
FB
1350 }
1351}
1352
5aaebd13
PM
1353static TCGv_ptr get_fpstatus_ptr(int neon)
1354{
1355 TCGv_ptr statusptr = tcg_temp_new_ptr();
1356 int offset;
1357 if (neon) {
0ecb72a5 1358 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1359 } else {
0ecb72a5 1360 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1361 }
1362 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1363 return statusptr;
1364}
1365
4373f3ce
PB
1366#define VFP_OP2(name) \
1367static inline void gen_vfp_##name(int dp) \
1368{ \
ae1857ec
PM
1369 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1370 if (dp) { \
1371 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1372 } else { \
1373 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1374 } \
1375 tcg_temp_free_ptr(fpst); \
b7bcbe95
FB
1376}
1377
4373f3ce
PB
1378VFP_OP2(add)
1379VFP_OP2(sub)
1380VFP_OP2(mul)
1381VFP_OP2(div)
1382
1383#undef VFP_OP2
1384
605a6aed
PM
1385static inline void gen_vfp_F1_mul(int dp)
1386{
1387 /* Like gen_vfp_mul() but put result in F1 */
ae1857ec 1388 TCGv_ptr fpst = get_fpstatus_ptr(0);
605a6aed 1389 if (dp) {
ae1857ec 1390 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
605a6aed 1391 } else {
ae1857ec 1392 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
605a6aed 1393 }
ae1857ec 1394 tcg_temp_free_ptr(fpst);
605a6aed
PM
1395}
1396
1397static inline void gen_vfp_F1_neg(int dp)
1398{
1399 /* Like gen_vfp_neg() but put result in F1 */
1400 if (dp) {
1401 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1402 } else {
1403 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1404 }
1405}
1406
4373f3ce
PB
1407static inline void gen_vfp_abs(int dp)
1408{
1409 if (dp)
1410 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1411 else
1412 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1413}
1414
1415static inline void gen_vfp_neg(int dp)
1416{
1417 if (dp)
1418 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1419 else
1420 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1421}
1422
1423static inline void gen_vfp_sqrt(int dp)
1424{
1425 if (dp)
1426 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1427 else
1428 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1429}
1430
1431static inline void gen_vfp_cmp(int dp)
1432{
1433 if (dp)
1434 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1435 else
1436 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1437}
1438
1439static inline void gen_vfp_cmpe(int dp)
1440{
1441 if (dp)
1442 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1443 else
1444 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1445}
1446
1447static inline void gen_vfp_F1_ld0(int dp)
1448{
1449 if (dp)
5b340b51 1450 tcg_gen_movi_i64(cpu_F1d, 0);
4373f3ce 1451 else
5b340b51 1452 tcg_gen_movi_i32(cpu_F1s, 0);
4373f3ce
PB
1453}
1454
5500b06c
PM
1455#define VFP_GEN_ITOF(name) \
1456static inline void gen_vfp_##name(int dp, int neon) \
1457{ \
5aaebd13 1458 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1459 if (dp) { \
1460 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1461 } else { \
1462 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1463 } \
b7fa9214 1464 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1465}
1466
5500b06c
PM
1467VFP_GEN_ITOF(uito)
1468VFP_GEN_ITOF(sito)
1469#undef VFP_GEN_ITOF
4373f3ce 1470
5500b06c
PM
1471#define VFP_GEN_FTOI(name) \
1472static inline void gen_vfp_##name(int dp, int neon) \
1473{ \
5aaebd13 1474 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1475 if (dp) { \
1476 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1477 } else { \
1478 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1479 } \
b7fa9214 1480 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1481}
1482
5500b06c
PM
1483VFP_GEN_FTOI(toui)
1484VFP_GEN_FTOI(touiz)
1485VFP_GEN_FTOI(tosi)
1486VFP_GEN_FTOI(tosiz)
1487#undef VFP_GEN_FTOI
4373f3ce 1488
16d5b3ca 1489#define VFP_GEN_FIX(name, round) \
5500b06c 1490static inline void gen_vfp_##name(int dp, int shift, int neon) \
4373f3ce 1491{ \
39d5492a 1492 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
5aaebd13 1493 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c 1494 if (dp) { \
16d5b3ca
WN
1495 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1496 statusptr); \
5500b06c 1497 } else { \
16d5b3ca
WN
1498 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1499 statusptr); \
5500b06c 1500 } \
b75263d6 1501 tcg_temp_free_i32(tmp_shift); \
b7fa9214 1502 tcg_temp_free_ptr(statusptr); \
9ee6e8bb 1503}
16d5b3ca
WN
1504VFP_GEN_FIX(tosh, _round_to_zero)
1505VFP_GEN_FIX(tosl, _round_to_zero)
1506VFP_GEN_FIX(touh, _round_to_zero)
1507VFP_GEN_FIX(toul, _round_to_zero)
1508VFP_GEN_FIX(shto, )
1509VFP_GEN_FIX(slto, )
1510VFP_GEN_FIX(uhto, )
1511VFP_GEN_FIX(ulto, )
4373f3ce 1512#undef VFP_GEN_FIX
9ee6e8bb 1513
39d5492a 1514static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1515{
08307563 1516 if (dp) {
12dcc321 1517 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1518 } else {
12dcc321 1519 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
08307563 1520 }
b5ff1b31
FB
1521}
1522
39d5492a 1523static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1524{
08307563 1525 if (dp) {
12dcc321 1526 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1527 } else {
12dcc321 1528 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
08307563 1529 }
b5ff1b31
FB
1530}
1531
c39c2b90 1532static inline long vfp_reg_offset(bool dp, unsigned reg)
8e96005d 1533{
9a2b5256 1534 if (dp) {
c39c2b90 1535 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
8e96005d 1536 } else {
c39c2b90 1537 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
9a2b5256
RH
1538 if (reg & 1) {
1539 ofs += offsetof(CPU_DoubleU, l.upper);
1540 } else {
1541 ofs += offsetof(CPU_DoubleU, l.lower);
1542 }
1543 return ofs;
8e96005d
FB
1544 }
1545}
9ee6e8bb
PB
1546
1547/* Return the offset of a 32-bit piece of a NEON register.
1548 zero is the least significant end of the register. */
1549static inline long
1550neon_reg_offset (int reg, int n)
1551{
1552 int sreg;
1553 sreg = reg * 2 + n;
1554 return vfp_reg_offset(0, sreg);
1555}
1556
39d5492a 1557static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1558{
39d5492a 1559 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1560 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1561 return tmp;
1562}
1563
39d5492a 1564static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1565{
1566 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1567 tcg_temp_free_i32(var);
8f8e3aa4
PB
1568}
1569
a7812ae4 1570static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1571{
1572 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1573}
1574
a7812ae4 1575static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1576{
1577 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1578}
1579
1a66ac61
RH
1580static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1581{
1582 TCGv_ptr ret = tcg_temp_new_ptr();
1583 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1584 return ret;
1585}
1586
4373f3ce
PB
1587#define tcg_gen_ld_f32 tcg_gen_ld_i32
1588#define tcg_gen_ld_f64 tcg_gen_ld_i64
1589#define tcg_gen_st_f32 tcg_gen_st_i32
1590#define tcg_gen_st_f64 tcg_gen_st_i64
1591
b7bcbe95
FB
1592static inline void gen_mov_F0_vreg(int dp, int reg)
1593{
1594 if (dp)
4373f3ce 1595 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1596 else
4373f3ce 1597 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1598}
1599
1600static inline void gen_mov_F1_vreg(int dp, int reg)
1601{
1602 if (dp)
4373f3ce 1603 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1604 else
4373f3ce 1605 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1606}
1607
1608static inline void gen_mov_vreg_F0(int dp, int reg)
1609{
1610 if (dp)
4373f3ce 1611 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1612 else
4373f3ce 1613 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1614}
1615
18c9b560
AZ
1616#define ARM_CP_RW_BIT (1 << 20)
1617
a7812ae4 1618static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1619{
0ecb72a5 1620 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1621}
1622
a7812ae4 1623static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1624{
0ecb72a5 1625 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1626}
1627
39d5492a 1628static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1629{
39d5492a 1630 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1631 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1632 return var;
e677137d
PB
1633}
1634
39d5492a 1635static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1636{
0ecb72a5 1637 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1638 tcg_temp_free_i32(var);
e677137d
PB
1639}
1640
1641static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1642{
1643 iwmmxt_store_reg(cpu_M0, rn);
1644}
1645
1646static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1647{
1648 iwmmxt_load_reg(cpu_M0, rn);
1649}
1650
1651static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1652{
1653 iwmmxt_load_reg(cpu_V1, rn);
1654 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1655}
1656
1657static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1658{
1659 iwmmxt_load_reg(cpu_V1, rn);
1660 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1661}
1662
1663static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1664{
1665 iwmmxt_load_reg(cpu_V1, rn);
1666 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1667}
1668
1669#define IWMMXT_OP(name) \
1670static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1671{ \
1672 iwmmxt_load_reg(cpu_V1, rn); \
1673 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1674}
1675
477955bd
PM
1676#define IWMMXT_OP_ENV(name) \
1677static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1678{ \
1679 iwmmxt_load_reg(cpu_V1, rn); \
1680 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1681}
1682
1683#define IWMMXT_OP_ENV_SIZE(name) \
1684IWMMXT_OP_ENV(name##b) \
1685IWMMXT_OP_ENV(name##w) \
1686IWMMXT_OP_ENV(name##l)
e677137d 1687
477955bd 1688#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1689static inline void gen_op_iwmmxt_##name##_M0(void) \
1690{ \
477955bd 1691 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1692}
1693
1694IWMMXT_OP(maddsq)
1695IWMMXT_OP(madduq)
1696IWMMXT_OP(sadb)
1697IWMMXT_OP(sadw)
1698IWMMXT_OP(mulslw)
1699IWMMXT_OP(mulshw)
1700IWMMXT_OP(mululw)
1701IWMMXT_OP(muluhw)
1702IWMMXT_OP(macsw)
1703IWMMXT_OP(macuw)
1704
477955bd
PM
1705IWMMXT_OP_ENV_SIZE(unpackl)
1706IWMMXT_OP_ENV_SIZE(unpackh)
1707
1708IWMMXT_OP_ENV1(unpacklub)
1709IWMMXT_OP_ENV1(unpackluw)
1710IWMMXT_OP_ENV1(unpacklul)
1711IWMMXT_OP_ENV1(unpackhub)
1712IWMMXT_OP_ENV1(unpackhuw)
1713IWMMXT_OP_ENV1(unpackhul)
1714IWMMXT_OP_ENV1(unpacklsb)
1715IWMMXT_OP_ENV1(unpacklsw)
1716IWMMXT_OP_ENV1(unpacklsl)
1717IWMMXT_OP_ENV1(unpackhsb)
1718IWMMXT_OP_ENV1(unpackhsw)
1719IWMMXT_OP_ENV1(unpackhsl)
1720
1721IWMMXT_OP_ENV_SIZE(cmpeq)
1722IWMMXT_OP_ENV_SIZE(cmpgtu)
1723IWMMXT_OP_ENV_SIZE(cmpgts)
1724
1725IWMMXT_OP_ENV_SIZE(mins)
1726IWMMXT_OP_ENV_SIZE(minu)
1727IWMMXT_OP_ENV_SIZE(maxs)
1728IWMMXT_OP_ENV_SIZE(maxu)
1729
1730IWMMXT_OP_ENV_SIZE(subn)
1731IWMMXT_OP_ENV_SIZE(addn)
1732IWMMXT_OP_ENV_SIZE(subu)
1733IWMMXT_OP_ENV_SIZE(addu)
1734IWMMXT_OP_ENV_SIZE(subs)
1735IWMMXT_OP_ENV_SIZE(adds)
1736
1737IWMMXT_OP_ENV(avgb0)
1738IWMMXT_OP_ENV(avgb1)
1739IWMMXT_OP_ENV(avgw0)
1740IWMMXT_OP_ENV(avgw1)
e677137d 1741
477955bd
PM
1742IWMMXT_OP_ENV(packuw)
1743IWMMXT_OP_ENV(packul)
1744IWMMXT_OP_ENV(packuq)
1745IWMMXT_OP_ENV(packsw)
1746IWMMXT_OP_ENV(packsl)
1747IWMMXT_OP_ENV(packsq)
e677137d 1748
e677137d
PB
1749static void gen_op_iwmmxt_set_mup(void)
1750{
39d5492a 1751 TCGv_i32 tmp;
e677137d
PB
1752 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1753 tcg_gen_ori_i32(tmp, tmp, 2);
1754 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1755}
1756
1757static void gen_op_iwmmxt_set_cup(void)
1758{
39d5492a 1759 TCGv_i32 tmp;
e677137d
PB
1760 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1761 tcg_gen_ori_i32(tmp, tmp, 1);
1762 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1763}
1764
1765static void gen_op_iwmmxt_setpsr_nz(void)
1766{
39d5492a 1767 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1768 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1769 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1770}
1771
1772static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1773{
1774 iwmmxt_load_reg(cpu_V1, rn);
86831435 1775 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1776 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1777}
1778
39d5492a
PM
1779static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1780 TCGv_i32 dest)
18c9b560
AZ
1781{
1782 int rd;
1783 uint32_t offset;
39d5492a 1784 TCGv_i32 tmp;
18c9b560
AZ
1785
1786 rd = (insn >> 16) & 0xf;
da6b5335 1787 tmp = load_reg(s, rd);
18c9b560
AZ
1788
1789 offset = (insn & 0xff) << ((insn >> 7) & 2);
1790 if (insn & (1 << 24)) {
1791 /* Pre indexed */
1792 if (insn & (1 << 23))
da6b5335 1793 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1794 else
da6b5335
FN
1795 tcg_gen_addi_i32(tmp, tmp, -offset);
1796 tcg_gen_mov_i32(dest, tmp);
18c9b560 1797 if (insn & (1 << 21))
da6b5335
FN
1798 store_reg(s, rd, tmp);
1799 else
7d1b0095 1800 tcg_temp_free_i32(tmp);
18c9b560
AZ
1801 } else if (insn & (1 << 21)) {
1802 /* Post indexed */
da6b5335 1803 tcg_gen_mov_i32(dest, tmp);
18c9b560 1804 if (insn & (1 << 23))
da6b5335 1805 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1806 else
da6b5335
FN
1807 tcg_gen_addi_i32(tmp, tmp, -offset);
1808 store_reg(s, rd, tmp);
18c9b560
AZ
1809 } else if (!(insn & (1 << 23)))
1810 return 1;
1811 return 0;
1812}
1813
39d5492a 1814static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1815{
1816 int rd = (insn >> 0) & 0xf;
39d5492a 1817 TCGv_i32 tmp;
18c9b560 1818
da6b5335
FN
1819 if (insn & (1 << 8)) {
1820 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1821 return 1;
da6b5335
FN
1822 } else {
1823 tmp = iwmmxt_load_creg(rd);
1824 }
1825 } else {
7d1b0095 1826 tmp = tcg_temp_new_i32();
da6b5335 1827 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1828 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1829 }
1830 tcg_gen_andi_i32(tmp, tmp, mask);
1831 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1832 tcg_temp_free_i32(tmp);
18c9b560
AZ
1833 return 0;
1834}
1835
a1c7273b 1836/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1837 (ie. an undefined instruction). */
7dcc1f89 1838static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1839{
1840 int rd, wrd;
1841 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1842 TCGv_i32 addr;
1843 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1844
1845 if ((insn & 0x0e000e00) == 0x0c000000) {
1846 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1847 wrd = insn & 0xf;
1848 rdlo = (insn >> 12) & 0xf;
1849 rdhi = (insn >> 16) & 0xf;
1850 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1851 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1852 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
da6b5335 1853 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 1854 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
18c9b560 1855 } else { /* TMCRR */
da6b5335
FN
1856 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1857 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1858 gen_op_iwmmxt_set_mup();
1859 }
1860 return 0;
1861 }
1862
1863 wrd = (insn >> 12) & 0xf;
7d1b0095 1864 addr = tcg_temp_new_i32();
da6b5335 1865 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1866 tcg_temp_free_i32(addr);
18c9b560 1867 return 1;
da6b5335 1868 }
18c9b560
AZ
1869 if (insn & ARM_CP_RW_BIT) {
1870 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1871 tmp = tcg_temp_new_i32();
12dcc321 1872 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1873 iwmmxt_store_creg(wrd, tmp);
18c9b560 1874 } else {
e677137d
PB
1875 i = 1;
1876 if (insn & (1 << 8)) {
1877 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1878 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d
PB
1879 i = 0;
1880 } else { /* WLDRW wRd */
29531141 1881 tmp = tcg_temp_new_i32();
12dcc321 1882 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1883 }
1884 } else {
29531141 1885 tmp = tcg_temp_new_i32();
e677137d 1886 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1887 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
e677137d 1888 } else { /* WLDRB */
12dcc321 1889 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1890 }
1891 }
1892 if (i) {
1893 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1894 tcg_temp_free_i32(tmp);
e677137d 1895 }
18c9b560
AZ
1896 gen_op_iwmmxt_movq_wRn_M0(wrd);
1897 }
1898 } else {
1899 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1900 tmp = iwmmxt_load_creg(wrd);
12dcc321 1901 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1902 } else {
1903 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1904 tmp = tcg_temp_new_i32();
e677137d
PB
1905 if (insn & (1 << 8)) {
1906 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 1907 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1908 } else { /* WSTRW wRd */
ecc7b3aa 1909 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1910 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
1911 }
1912 } else {
1913 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1914 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1915 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
e677137d 1916 } else { /* WSTRB */
ecc7b3aa 1917 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1918 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
1919 }
1920 }
18c9b560 1921 }
29531141 1922 tcg_temp_free_i32(tmp);
18c9b560 1923 }
7d1b0095 1924 tcg_temp_free_i32(addr);
18c9b560
AZ
1925 return 0;
1926 }
1927
1928 if ((insn & 0x0f000000) != 0x0e000000)
1929 return 1;
1930
1931 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1932 case 0x000: /* WOR */
1933 wrd = (insn >> 12) & 0xf;
1934 rd0 = (insn >> 0) & 0xf;
1935 rd1 = (insn >> 16) & 0xf;
1936 gen_op_iwmmxt_movq_M0_wRn(rd0);
1937 gen_op_iwmmxt_orq_M0_wRn(rd1);
1938 gen_op_iwmmxt_setpsr_nz();
1939 gen_op_iwmmxt_movq_wRn_M0(wrd);
1940 gen_op_iwmmxt_set_mup();
1941 gen_op_iwmmxt_set_cup();
1942 break;
1943 case 0x011: /* TMCR */
1944 if (insn & 0xf)
1945 return 1;
1946 rd = (insn >> 12) & 0xf;
1947 wrd = (insn >> 16) & 0xf;
1948 switch (wrd) {
1949 case ARM_IWMMXT_wCID:
1950 case ARM_IWMMXT_wCASF:
1951 break;
1952 case ARM_IWMMXT_wCon:
1953 gen_op_iwmmxt_set_cup();
1954 /* Fall through. */
1955 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1956 tmp = iwmmxt_load_creg(wrd);
1957 tmp2 = load_reg(s, rd);
f669df27 1958 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1959 tcg_temp_free_i32(tmp2);
da6b5335 1960 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1961 break;
1962 case ARM_IWMMXT_wCGR0:
1963 case ARM_IWMMXT_wCGR1:
1964 case ARM_IWMMXT_wCGR2:
1965 case ARM_IWMMXT_wCGR3:
1966 gen_op_iwmmxt_set_cup();
da6b5335
FN
1967 tmp = load_reg(s, rd);
1968 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1969 break;
1970 default:
1971 return 1;
1972 }
1973 break;
1974 case 0x100: /* WXOR */
1975 wrd = (insn >> 12) & 0xf;
1976 rd0 = (insn >> 0) & 0xf;
1977 rd1 = (insn >> 16) & 0xf;
1978 gen_op_iwmmxt_movq_M0_wRn(rd0);
1979 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1980 gen_op_iwmmxt_setpsr_nz();
1981 gen_op_iwmmxt_movq_wRn_M0(wrd);
1982 gen_op_iwmmxt_set_mup();
1983 gen_op_iwmmxt_set_cup();
1984 break;
1985 case 0x111: /* TMRC */
1986 if (insn & 0xf)
1987 return 1;
1988 rd = (insn >> 12) & 0xf;
1989 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1990 tmp = iwmmxt_load_creg(wrd);
1991 store_reg(s, rd, tmp);
18c9b560
AZ
1992 break;
1993 case 0x300: /* WANDN */
1994 wrd = (insn >> 12) & 0xf;
1995 rd0 = (insn >> 0) & 0xf;
1996 rd1 = (insn >> 16) & 0xf;
1997 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1998 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1999 gen_op_iwmmxt_andq_M0_wRn(rd1);
2000 gen_op_iwmmxt_setpsr_nz();
2001 gen_op_iwmmxt_movq_wRn_M0(wrd);
2002 gen_op_iwmmxt_set_mup();
2003 gen_op_iwmmxt_set_cup();
2004 break;
2005 case 0x200: /* WAND */
2006 wrd = (insn >> 12) & 0xf;
2007 rd0 = (insn >> 0) & 0xf;
2008 rd1 = (insn >> 16) & 0xf;
2009 gen_op_iwmmxt_movq_M0_wRn(rd0);
2010 gen_op_iwmmxt_andq_M0_wRn(rd1);
2011 gen_op_iwmmxt_setpsr_nz();
2012 gen_op_iwmmxt_movq_wRn_M0(wrd);
2013 gen_op_iwmmxt_set_mup();
2014 gen_op_iwmmxt_set_cup();
2015 break;
2016 case 0x810: case 0xa10: /* WMADD */
2017 wrd = (insn >> 12) & 0xf;
2018 rd0 = (insn >> 0) & 0xf;
2019 rd1 = (insn >> 16) & 0xf;
2020 gen_op_iwmmxt_movq_M0_wRn(rd0);
2021 if (insn & (1 << 21))
2022 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2023 else
2024 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2025 gen_op_iwmmxt_movq_wRn_M0(wrd);
2026 gen_op_iwmmxt_set_mup();
2027 break;
2028 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2029 wrd = (insn >> 12) & 0xf;
2030 rd0 = (insn >> 16) & 0xf;
2031 rd1 = (insn >> 0) & 0xf;
2032 gen_op_iwmmxt_movq_M0_wRn(rd0);
2033 switch ((insn >> 22) & 3) {
2034 case 0:
2035 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2036 break;
2037 case 1:
2038 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2039 break;
2040 case 2:
2041 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2042 break;
2043 case 3:
2044 return 1;
2045 }
2046 gen_op_iwmmxt_movq_wRn_M0(wrd);
2047 gen_op_iwmmxt_set_mup();
2048 gen_op_iwmmxt_set_cup();
2049 break;
2050 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2051 wrd = (insn >> 12) & 0xf;
2052 rd0 = (insn >> 16) & 0xf;
2053 rd1 = (insn >> 0) & 0xf;
2054 gen_op_iwmmxt_movq_M0_wRn(rd0);
2055 switch ((insn >> 22) & 3) {
2056 case 0:
2057 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2058 break;
2059 case 1:
2060 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2061 break;
2062 case 2:
2063 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2064 break;
2065 case 3:
2066 return 1;
2067 }
2068 gen_op_iwmmxt_movq_wRn_M0(wrd);
2069 gen_op_iwmmxt_set_mup();
2070 gen_op_iwmmxt_set_cup();
2071 break;
2072 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2073 wrd = (insn >> 12) & 0xf;
2074 rd0 = (insn >> 16) & 0xf;
2075 rd1 = (insn >> 0) & 0xf;
2076 gen_op_iwmmxt_movq_M0_wRn(rd0);
2077 if (insn & (1 << 22))
2078 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2079 else
2080 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2081 if (!(insn & (1 << 20)))
2082 gen_op_iwmmxt_addl_M0_wRn(wrd);
2083 gen_op_iwmmxt_movq_wRn_M0(wrd);
2084 gen_op_iwmmxt_set_mup();
2085 break;
2086 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 16) & 0xf;
2089 rd1 = (insn >> 0) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2091 if (insn & (1 << 21)) {
2092 if (insn & (1 << 20))
2093 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2094 else
2095 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2096 } else {
2097 if (insn & (1 << 20))
2098 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2099 else
2100 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2101 }
18c9b560
AZ
2102 gen_op_iwmmxt_movq_wRn_M0(wrd);
2103 gen_op_iwmmxt_set_mup();
2104 break;
2105 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2106 wrd = (insn >> 12) & 0xf;
2107 rd0 = (insn >> 16) & 0xf;
2108 rd1 = (insn >> 0) & 0xf;
2109 gen_op_iwmmxt_movq_M0_wRn(rd0);
2110 if (insn & (1 << 21))
2111 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2112 else
2113 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2114 if (!(insn & (1 << 20))) {
e677137d
PB
2115 iwmmxt_load_reg(cpu_V1, wrd);
2116 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
2117 }
2118 gen_op_iwmmxt_movq_wRn_M0(wrd);
2119 gen_op_iwmmxt_set_mup();
2120 break;
2121 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2122 wrd = (insn >> 12) & 0xf;
2123 rd0 = (insn >> 16) & 0xf;
2124 rd1 = (insn >> 0) & 0xf;
2125 gen_op_iwmmxt_movq_M0_wRn(rd0);
2126 switch ((insn >> 22) & 3) {
2127 case 0:
2128 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2129 break;
2130 case 1:
2131 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2132 break;
2133 case 2:
2134 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2135 break;
2136 case 3:
2137 return 1;
2138 }
2139 gen_op_iwmmxt_movq_wRn_M0(wrd);
2140 gen_op_iwmmxt_set_mup();
2141 gen_op_iwmmxt_set_cup();
2142 break;
2143 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2144 wrd = (insn >> 12) & 0xf;
2145 rd0 = (insn >> 16) & 0xf;
2146 rd1 = (insn >> 0) & 0xf;
2147 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2148 if (insn & (1 << 22)) {
2149 if (insn & (1 << 20))
2150 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2151 else
2152 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2153 } else {
2154 if (insn & (1 << 20))
2155 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2156 else
2157 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2158 }
18c9b560
AZ
2159 gen_op_iwmmxt_movq_wRn_M0(wrd);
2160 gen_op_iwmmxt_set_mup();
2161 gen_op_iwmmxt_set_cup();
2162 break;
2163 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2164 wrd = (insn >> 12) & 0xf;
2165 rd0 = (insn >> 16) & 0xf;
2166 rd1 = (insn >> 0) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2168 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2169 tcg_gen_andi_i32(tmp, tmp, 7);
2170 iwmmxt_load_reg(cpu_V1, rd1);
2171 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 2172 tcg_temp_free_i32(tmp);
18c9b560
AZ
2173 gen_op_iwmmxt_movq_wRn_M0(wrd);
2174 gen_op_iwmmxt_set_mup();
2175 break;
2176 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
2177 if (((insn >> 6) & 3) == 3)
2178 return 1;
18c9b560
AZ
2179 rd = (insn >> 12) & 0xf;
2180 wrd = (insn >> 16) & 0xf;
da6b5335 2181 tmp = load_reg(s, rd);
18c9b560
AZ
2182 gen_op_iwmmxt_movq_M0_wRn(wrd);
2183 switch ((insn >> 6) & 3) {
2184 case 0:
da6b5335
FN
2185 tmp2 = tcg_const_i32(0xff);
2186 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
2187 break;
2188 case 1:
da6b5335
FN
2189 tmp2 = tcg_const_i32(0xffff);
2190 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
2191 break;
2192 case 2:
da6b5335
FN
2193 tmp2 = tcg_const_i32(0xffffffff);
2194 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 2195 break;
da6b5335 2196 default:
f764718d
RH
2197 tmp2 = NULL;
2198 tmp3 = NULL;
18c9b560 2199 }
da6b5335 2200 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
2201 tcg_temp_free_i32(tmp3);
2202 tcg_temp_free_i32(tmp2);
7d1b0095 2203 tcg_temp_free_i32(tmp);
18c9b560
AZ
2204 gen_op_iwmmxt_movq_wRn_M0(wrd);
2205 gen_op_iwmmxt_set_mup();
2206 break;
2207 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2208 rd = (insn >> 12) & 0xf;
2209 wrd = (insn >> 16) & 0xf;
da6b5335 2210 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2211 return 1;
2212 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 2213 tmp = tcg_temp_new_i32();
18c9b560
AZ
2214 switch ((insn >> 22) & 3) {
2215 case 0:
da6b5335 2216 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 2217 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2218 if (insn & 8) {
2219 tcg_gen_ext8s_i32(tmp, tmp);
2220 } else {
2221 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
2222 }
2223 break;
2224 case 1:
da6b5335 2225 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 2226 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2227 if (insn & 8) {
2228 tcg_gen_ext16s_i32(tmp, tmp);
2229 } else {
2230 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
2231 }
2232 break;
2233 case 2:
da6b5335 2234 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 2235 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 2236 break;
18c9b560 2237 }
da6b5335 2238 store_reg(s, rd, tmp);
18c9b560
AZ
2239 break;
2240 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2241 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2242 return 1;
da6b5335 2243 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2244 switch ((insn >> 22) & 3) {
2245 case 0:
da6b5335 2246 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2247 break;
2248 case 1:
da6b5335 2249 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2250 break;
2251 case 2:
da6b5335 2252 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2253 break;
18c9b560 2254 }
da6b5335
FN
2255 tcg_gen_shli_i32(tmp, tmp, 28);
2256 gen_set_nzcv(tmp);
7d1b0095 2257 tcg_temp_free_i32(tmp);
18c9b560
AZ
2258 break;
2259 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2260 if (((insn >> 6) & 3) == 3)
2261 return 1;
18c9b560
AZ
2262 rd = (insn >> 12) & 0xf;
2263 wrd = (insn >> 16) & 0xf;
da6b5335 2264 tmp = load_reg(s, rd);
18c9b560
AZ
2265 switch ((insn >> 6) & 3) {
2266 case 0:
da6b5335 2267 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2268 break;
2269 case 1:
da6b5335 2270 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2271 break;
2272 case 2:
da6b5335 2273 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2274 break;
18c9b560 2275 }
7d1b0095 2276 tcg_temp_free_i32(tmp);
18c9b560
AZ
2277 gen_op_iwmmxt_movq_wRn_M0(wrd);
2278 gen_op_iwmmxt_set_mup();
2279 break;
2280 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2281 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2282 return 1;
da6b5335 2283 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2284 tmp2 = tcg_temp_new_i32();
da6b5335 2285 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2286 switch ((insn >> 22) & 3) {
2287 case 0:
2288 for (i = 0; i < 7; i ++) {
da6b5335
FN
2289 tcg_gen_shli_i32(tmp2, tmp2, 4);
2290 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2291 }
2292 break;
2293 case 1:
2294 for (i = 0; i < 3; i ++) {
da6b5335
FN
2295 tcg_gen_shli_i32(tmp2, tmp2, 8);
2296 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2297 }
2298 break;
2299 case 2:
da6b5335
FN
2300 tcg_gen_shli_i32(tmp2, tmp2, 16);
2301 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2302 break;
18c9b560 2303 }
da6b5335 2304 gen_set_nzcv(tmp);
7d1b0095
PM
2305 tcg_temp_free_i32(tmp2);
2306 tcg_temp_free_i32(tmp);
18c9b560
AZ
2307 break;
2308 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2309 wrd = (insn >> 12) & 0xf;
2310 rd0 = (insn >> 16) & 0xf;
2311 gen_op_iwmmxt_movq_M0_wRn(rd0);
2312 switch ((insn >> 22) & 3) {
2313 case 0:
e677137d 2314 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2315 break;
2316 case 1:
e677137d 2317 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2318 break;
2319 case 2:
e677137d 2320 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2321 break;
2322 case 3:
2323 return 1;
2324 }
2325 gen_op_iwmmxt_movq_wRn_M0(wrd);
2326 gen_op_iwmmxt_set_mup();
2327 break;
2328 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2329 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2330 return 1;
da6b5335 2331 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2332 tmp2 = tcg_temp_new_i32();
da6b5335 2333 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2334 switch ((insn >> 22) & 3) {
2335 case 0:
2336 for (i = 0; i < 7; i ++) {
da6b5335
FN
2337 tcg_gen_shli_i32(tmp2, tmp2, 4);
2338 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2339 }
2340 break;
2341 case 1:
2342 for (i = 0; i < 3; i ++) {
da6b5335
FN
2343 tcg_gen_shli_i32(tmp2, tmp2, 8);
2344 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2345 }
2346 break;
2347 case 2:
da6b5335
FN
2348 tcg_gen_shli_i32(tmp2, tmp2, 16);
2349 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2350 break;
18c9b560 2351 }
da6b5335 2352 gen_set_nzcv(tmp);
7d1b0095
PM
2353 tcg_temp_free_i32(tmp2);
2354 tcg_temp_free_i32(tmp);
18c9b560
AZ
2355 break;
2356 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2357 rd = (insn >> 12) & 0xf;
2358 rd0 = (insn >> 16) & 0xf;
da6b5335 2359 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2360 return 1;
2361 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2362 tmp = tcg_temp_new_i32();
18c9b560
AZ
2363 switch ((insn >> 22) & 3) {
2364 case 0:
da6b5335 2365 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2366 break;
2367 case 1:
da6b5335 2368 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2369 break;
2370 case 2:
da6b5335 2371 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2372 break;
18c9b560 2373 }
da6b5335 2374 store_reg(s, rd, tmp);
18c9b560
AZ
2375 break;
2376 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2377 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2378 wrd = (insn >> 12) & 0xf;
2379 rd0 = (insn >> 16) & 0xf;
2380 rd1 = (insn >> 0) & 0xf;
2381 gen_op_iwmmxt_movq_M0_wRn(rd0);
2382 switch ((insn >> 22) & 3) {
2383 case 0:
2384 if (insn & (1 << 21))
2385 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2386 else
2387 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2388 break;
2389 case 1:
2390 if (insn & (1 << 21))
2391 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2392 else
2393 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2394 break;
2395 case 2:
2396 if (insn & (1 << 21))
2397 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2398 else
2399 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2400 break;
2401 case 3:
2402 return 1;
2403 }
2404 gen_op_iwmmxt_movq_wRn_M0(wrd);
2405 gen_op_iwmmxt_set_mup();
2406 gen_op_iwmmxt_set_cup();
2407 break;
2408 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2409 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2410 wrd = (insn >> 12) & 0xf;
2411 rd0 = (insn >> 16) & 0xf;
2412 gen_op_iwmmxt_movq_M0_wRn(rd0);
2413 switch ((insn >> 22) & 3) {
2414 case 0:
2415 if (insn & (1 << 21))
2416 gen_op_iwmmxt_unpacklsb_M0();
2417 else
2418 gen_op_iwmmxt_unpacklub_M0();
2419 break;
2420 case 1:
2421 if (insn & (1 << 21))
2422 gen_op_iwmmxt_unpacklsw_M0();
2423 else
2424 gen_op_iwmmxt_unpackluw_M0();
2425 break;
2426 case 2:
2427 if (insn & (1 << 21))
2428 gen_op_iwmmxt_unpacklsl_M0();
2429 else
2430 gen_op_iwmmxt_unpacklul_M0();
2431 break;
2432 case 3:
2433 return 1;
2434 }
2435 gen_op_iwmmxt_movq_wRn_M0(wrd);
2436 gen_op_iwmmxt_set_mup();
2437 gen_op_iwmmxt_set_cup();
2438 break;
2439 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2440 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2441 wrd = (insn >> 12) & 0xf;
2442 rd0 = (insn >> 16) & 0xf;
2443 gen_op_iwmmxt_movq_M0_wRn(rd0);
2444 switch ((insn >> 22) & 3) {
2445 case 0:
2446 if (insn & (1 << 21))
2447 gen_op_iwmmxt_unpackhsb_M0();
2448 else
2449 gen_op_iwmmxt_unpackhub_M0();
2450 break;
2451 case 1:
2452 if (insn & (1 << 21))
2453 gen_op_iwmmxt_unpackhsw_M0();
2454 else
2455 gen_op_iwmmxt_unpackhuw_M0();
2456 break;
2457 case 2:
2458 if (insn & (1 << 21))
2459 gen_op_iwmmxt_unpackhsl_M0();
2460 else
2461 gen_op_iwmmxt_unpackhul_M0();
2462 break;
2463 case 3:
2464 return 1;
2465 }
2466 gen_op_iwmmxt_movq_wRn_M0(wrd);
2467 gen_op_iwmmxt_set_mup();
2468 gen_op_iwmmxt_set_cup();
2469 break;
2470 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2471 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2472 if (((insn >> 22) & 3) == 0)
2473 return 1;
18c9b560
AZ
2474 wrd = (insn >> 12) & 0xf;
2475 rd0 = (insn >> 16) & 0xf;
2476 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2477 tmp = tcg_temp_new_i32();
da6b5335 2478 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2479 tcg_temp_free_i32(tmp);
18c9b560 2480 return 1;
da6b5335 2481 }
18c9b560 2482 switch ((insn >> 22) & 3) {
18c9b560 2483 case 1:
477955bd 2484 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2485 break;
2486 case 2:
477955bd 2487 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2488 break;
2489 case 3:
477955bd 2490 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2491 break;
2492 }
7d1b0095 2493 tcg_temp_free_i32(tmp);
18c9b560
AZ
2494 gen_op_iwmmxt_movq_wRn_M0(wrd);
2495 gen_op_iwmmxt_set_mup();
2496 gen_op_iwmmxt_set_cup();
2497 break;
2498 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2499 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2500 if (((insn >> 22) & 3) == 0)
2501 return 1;
18c9b560
AZ
2502 wrd = (insn >> 12) & 0xf;
2503 rd0 = (insn >> 16) & 0xf;
2504 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2505 tmp = tcg_temp_new_i32();
da6b5335 2506 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2507 tcg_temp_free_i32(tmp);
18c9b560 2508 return 1;
da6b5335 2509 }
18c9b560 2510 switch ((insn >> 22) & 3) {
18c9b560 2511 case 1:
477955bd 2512 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2513 break;
2514 case 2:
477955bd 2515 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2516 break;
2517 case 3:
477955bd 2518 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2519 break;
2520 }
7d1b0095 2521 tcg_temp_free_i32(tmp);
18c9b560
AZ
2522 gen_op_iwmmxt_movq_wRn_M0(wrd);
2523 gen_op_iwmmxt_set_mup();
2524 gen_op_iwmmxt_set_cup();
2525 break;
2526 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2527 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2528 if (((insn >> 22) & 3) == 0)
2529 return 1;
18c9b560
AZ
2530 wrd = (insn >> 12) & 0xf;
2531 rd0 = (insn >> 16) & 0xf;
2532 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2533 tmp = tcg_temp_new_i32();
da6b5335 2534 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2535 tcg_temp_free_i32(tmp);
18c9b560 2536 return 1;
da6b5335 2537 }
18c9b560 2538 switch ((insn >> 22) & 3) {
18c9b560 2539 case 1:
477955bd 2540 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2541 break;
2542 case 2:
477955bd 2543 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2544 break;
2545 case 3:
477955bd 2546 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2547 break;
2548 }
7d1b0095 2549 tcg_temp_free_i32(tmp);
18c9b560
AZ
2550 gen_op_iwmmxt_movq_wRn_M0(wrd);
2551 gen_op_iwmmxt_set_mup();
2552 gen_op_iwmmxt_set_cup();
2553 break;
2554 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2555 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2556 if (((insn >> 22) & 3) == 0)
2557 return 1;
18c9b560
AZ
2558 wrd = (insn >> 12) & 0xf;
2559 rd0 = (insn >> 16) & 0xf;
2560 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2561 tmp = tcg_temp_new_i32();
18c9b560 2562 switch ((insn >> 22) & 3) {
18c9b560 2563 case 1:
da6b5335 2564 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2565 tcg_temp_free_i32(tmp);
18c9b560 2566 return 1;
da6b5335 2567 }
477955bd 2568 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2569 break;
2570 case 2:
da6b5335 2571 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2572 tcg_temp_free_i32(tmp);
18c9b560 2573 return 1;
da6b5335 2574 }
477955bd 2575 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2576 break;
2577 case 3:
da6b5335 2578 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2579 tcg_temp_free_i32(tmp);
18c9b560 2580 return 1;
da6b5335 2581 }
477955bd 2582 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2583 break;
2584 }
7d1b0095 2585 tcg_temp_free_i32(tmp);
18c9b560
AZ
2586 gen_op_iwmmxt_movq_wRn_M0(wrd);
2587 gen_op_iwmmxt_set_mup();
2588 gen_op_iwmmxt_set_cup();
2589 break;
2590 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2591 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2592 wrd = (insn >> 12) & 0xf;
2593 rd0 = (insn >> 16) & 0xf;
2594 rd1 = (insn >> 0) & 0xf;
2595 gen_op_iwmmxt_movq_M0_wRn(rd0);
2596 switch ((insn >> 22) & 3) {
2597 case 0:
2598 if (insn & (1 << 21))
2599 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2600 else
2601 gen_op_iwmmxt_minub_M0_wRn(rd1);
2602 break;
2603 case 1:
2604 if (insn & (1 << 21))
2605 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2606 else
2607 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2608 break;
2609 case 2:
2610 if (insn & (1 << 21))
2611 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2612 else
2613 gen_op_iwmmxt_minul_M0_wRn(rd1);
2614 break;
2615 case 3:
2616 return 1;
2617 }
2618 gen_op_iwmmxt_movq_wRn_M0(wrd);
2619 gen_op_iwmmxt_set_mup();
2620 break;
2621 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2622 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2623 wrd = (insn >> 12) & 0xf;
2624 rd0 = (insn >> 16) & 0xf;
2625 rd1 = (insn >> 0) & 0xf;
2626 gen_op_iwmmxt_movq_M0_wRn(rd0);
2627 switch ((insn >> 22) & 3) {
2628 case 0:
2629 if (insn & (1 << 21))
2630 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2631 else
2632 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2633 break;
2634 case 1:
2635 if (insn & (1 << 21))
2636 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2637 else
2638 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2639 break;
2640 case 2:
2641 if (insn & (1 << 21))
2642 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2643 else
2644 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2645 break;
2646 case 3:
2647 return 1;
2648 }
2649 gen_op_iwmmxt_movq_wRn_M0(wrd);
2650 gen_op_iwmmxt_set_mup();
2651 break;
2652 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2653 case 0x402: case 0x502: case 0x602: case 0x702:
2654 wrd = (insn >> 12) & 0xf;
2655 rd0 = (insn >> 16) & 0xf;
2656 rd1 = (insn >> 0) & 0xf;
2657 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2658 tmp = tcg_const_i32((insn >> 20) & 3);
2659 iwmmxt_load_reg(cpu_V1, rd1);
2660 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2661 tcg_temp_free_i32(tmp);
18c9b560
AZ
2662 gen_op_iwmmxt_movq_wRn_M0(wrd);
2663 gen_op_iwmmxt_set_mup();
2664 break;
2665 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2666 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2667 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2668 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2669 wrd = (insn >> 12) & 0xf;
2670 rd0 = (insn >> 16) & 0xf;
2671 rd1 = (insn >> 0) & 0xf;
2672 gen_op_iwmmxt_movq_M0_wRn(rd0);
2673 switch ((insn >> 20) & 0xf) {
2674 case 0x0:
2675 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2676 break;
2677 case 0x1:
2678 gen_op_iwmmxt_subub_M0_wRn(rd1);
2679 break;
2680 case 0x3:
2681 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2682 break;
2683 case 0x4:
2684 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2685 break;
2686 case 0x5:
2687 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2688 break;
2689 case 0x7:
2690 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2691 break;
2692 case 0x8:
2693 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2694 break;
2695 case 0x9:
2696 gen_op_iwmmxt_subul_M0_wRn(rd1);
2697 break;
2698 case 0xb:
2699 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2700 break;
2701 default:
2702 return 1;
2703 }
2704 gen_op_iwmmxt_movq_wRn_M0(wrd);
2705 gen_op_iwmmxt_set_mup();
2706 gen_op_iwmmxt_set_cup();
2707 break;
2708 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2709 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2710 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2711 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2712 wrd = (insn >> 12) & 0xf;
2713 rd0 = (insn >> 16) & 0xf;
2714 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2715 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2716 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2717 tcg_temp_free_i32(tmp);
18c9b560
AZ
2718 gen_op_iwmmxt_movq_wRn_M0(wrd);
2719 gen_op_iwmmxt_set_mup();
2720 gen_op_iwmmxt_set_cup();
2721 break;
2722 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2723 case 0x418: case 0x518: case 0x618: case 0x718:
2724 case 0x818: case 0x918: case 0xa18: case 0xb18:
2725 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2726 wrd = (insn >> 12) & 0xf;
2727 rd0 = (insn >> 16) & 0xf;
2728 rd1 = (insn >> 0) & 0xf;
2729 gen_op_iwmmxt_movq_M0_wRn(rd0);
2730 switch ((insn >> 20) & 0xf) {
2731 case 0x0:
2732 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2733 break;
2734 case 0x1:
2735 gen_op_iwmmxt_addub_M0_wRn(rd1);
2736 break;
2737 case 0x3:
2738 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2739 break;
2740 case 0x4:
2741 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2742 break;
2743 case 0x5:
2744 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2745 break;
2746 case 0x7:
2747 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2748 break;
2749 case 0x8:
2750 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2751 break;
2752 case 0x9:
2753 gen_op_iwmmxt_addul_M0_wRn(rd1);
2754 break;
2755 case 0xb:
2756 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2757 break;
2758 default:
2759 return 1;
2760 }
2761 gen_op_iwmmxt_movq_wRn_M0(wrd);
2762 gen_op_iwmmxt_set_mup();
2763 gen_op_iwmmxt_set_cup();
2764 break;
2765 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2766 case 0x408: case 0x508: case 0x608: case 0x708:
2767 case 0x808: case 0x908: case 0xa08: case 0xb08:
2768 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2769 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2770 return 1;
18c9b560
AZ
2771 wrd = (insn >> 12) & 0xf;
2772 rd0 = (insn >> 16) & 0xf;
2773 rd1 = (insn >> 0) & 0xf;
2774 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2775 switch ((insn >> 22) & 3) {
18c9b560
AZ
2776 case 1:
2777 if (insn & (1 << 21))
2778 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2779 else
2780 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2781 break;
2782 case 2:
2783 if (insn & (1 << 21))
2784 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2785 else
2786 gen_op_iwmmxt_packul_M0_wRn(rd1);
2787 break;
2788 case 3:
2789 if (insn & (1 << 21))
2790 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2791 else
2792 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2793 break;
2794 }
2795 gen_op_iwmmxt_movq_wRn_M0(wrd);
2796 gen_op_iwmmxt_set_mup();
2797 gen_op_iwmmxt_set_cup();
2798 break;
2799 case 0x201: case 0x203: case 0x205: case 0x207:
2800 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2801 case 0x211: case 0x213: case 0x215: case 0x217:
2802 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2803 wrd = (insn >> 5) & 0xf;
2804 rd0 = (insn >> 12) & 0xf;
2805 rd1 = (insn >> 0) & 0xf;
2806 if (rd0 == 0xf || rd1 == 0xf)
2807 return 1;
2808 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2809 tmp = load_reg(s, rd0);
2810 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2811 switch ((insn >> 16) & 0xf) {
2812 case 0x0: /* TMIA */
da6b5335 2813 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2814 break;
2815 case 0x8: /* TMIAPH */
da6b5335 2816 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2817 break;
2818 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2819 if (insn & (1 << 16))
da6b5335 2820 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2821 if (insn & (1 << 17))
da6b5335
FN
2822 tcg_gen_shri_i32(tmp2, tmp2, 16);
2823 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2824 break;
2825 default:
7d1b0095
PM
2826 tcg_temp_free_i32(tmp2);
2827 tcg_temp_free_i32(tmp);
18c9b560
AZ
2828 return 1;
2829 }
7d1b0095
PM
2830 tcg_temp_free_i32(tmp2);
2831 tcg_temp_free_i32(tmp);
18c9b560
AZ
2832 gen_op_iwmmxt_movq_wRn_M0(wrd);
2833 gen_op_iwmmxt_set_mup();
2834 break;
2835 default:
2836 return 1;
2837 }
2838
2839 return 0;
2840}
2841
a1c7273b 2842/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2843 (ie. an undefined instruction). */
7dcc1f89 2844static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2845{
2846 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2847 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2848
2849 if ((insn & 0x0ff00f10) == 0x0e200010) {
2850 /* Multiply with Internal Accumulate Format */
2851 rd0 = (insn >> 12) & 0xf;
2852 rd1 = insn & 0xf;
2853 acc = (insn >> 5) & 7;
2854
2855 if (acc != 0)
2856 return 1;
2857
3a554c0f
FN
2858 tmp = load_reg(s, rd0);
2859 tmp2 = load_reg(s, rd1);
18c9b560
AZ
2860 switch ((insn >> 16) & 0xf) {
2861 case 0x0: /* MIA */
3a554c0f 2862 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2863 break;
2864 case 0x8: /* MIAPH */
3a554c0f 2865 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2866 break;
2867 case 0xc: /* MIABB */
2868 case 0xd: /* MIABT */
2869 case 0xe: /* MIATB */
2870 case 0xf: /* MIATT */
18c9b560 2871 if (insn & (1 << 16))
3a554c0f 2872 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2873 if (insn & (1 << 17))
3a554c0f
FN
2874 tcg_gen_shri_i32(tmp2, tmp2, 16);
2875 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2876 break;
2877 default:
2878 return 1;
2879 }
7d1b0095
PM
2880 tcg_temp_free_i32(tmp2);
2881 tcg_temp_free_i32(tmp);
18c9b560
AZ
2882
2883 gen_op_iwmmxt_movq_wRn_M0(acc);
2884 return 0;
2885 }
2886
2887 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2888 /* Internal Accumulator Access Format */
2889 rdhi = (insn >> 16) & 0xf;
2890 rdlo = (insn >> 12) & 0xf;
2891 acc = insn & 7;
2892
2893 if (acc != 0)
2894 return 1;
2895
2896 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2897 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2898 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3a554c0f 2899 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 2900 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2901 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
18c9b560 2902 } else { /* MAR */
3a554c0f
FN
2903 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2904 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2905 }
2906 return 0;
2907 }
2908
2909 return 1;
2910}
2911
9ee6e8bb
PB
2912#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2913#define VFP_SREG(insn, bigbit, smallbit) \
2914 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2915#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2916 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2917 reg = (((insn) >> (bigbit)) & 0x0f) \
2918 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2919 } else { \
2920 if (insn & (1 << (smallbit))) \
2921 return 1; \
2922 reg = ((insn) >> (bigbit)) & 0x0f; \
2923 }} while (0)
2924
2925#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2926#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2927#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2928#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2929#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2930#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2931
4373f3ce 2932/* Move between integer and VFP cores. */
39d5492a 2933static TCGv_i32 gen_vfp_mrs(void)
4373f3ce 2934{
39d5492a 2935 TCGv_i32 tmp = tcg_temp_new_i32();
4373f3ce
PB
2936 tcg_gen_mov_i32(tmp, cpu_F0s);
2937 return tmp;
2938}
2939
39d5492a 2940static void gen_vfp_msr(TCGv_i32 tmp)
4373f3ce
PB
2941{
2942 tcg_gen_mov_i32(cpu_F0s, tmp);
7d1b0095 2943 tcg_temp_free_i32(tmp);
4373f3ce
PB
2944}
2945
39d5492a 2946static void gen_neon_dup_u8(TCGv_i32 var, int shift)
ad69471c 2947{
39d5492a 2948 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2949 if (shift)
2950 tcg_gen_shri_i32(var, var, shift);
86831435 2951 tcg_gen_ext8u_i32(var, var);
ad69471c
PB
2952 tcg_gen_shli_i32(tmp, var, 8);
2953 tcg_gen_or_i32(var, var, tmp);
2954 tcg_gen_shli_i32(tmp, var, 16);
2955 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2956 tcg_temp_free_i32(tmp);
ad69471c
PB
2957}
2958
39d5492a 2959static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2960{
39d5492a 2961 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2962 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2963 tcg_gen_shli_i32(tmp, var, 16);
2964 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2965 tcg_temp_free_i32(tmp);
ad69471c
PB
2966}
2967
39d5492a 2968static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2969{
39d5492a 2970 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2971 tcg_gen_andi_i32(var, var, 0xffff0000);
2972 tcg_gen_shri_i32(tmp, var, 16);
2973 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2974 tcg_temp_free_i32(tmp);
ad69471c
PB
2975}
2976
39d5492a 2977static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
8e18cde3
PM
2978{
2979 /* Load a single Neon element and replicate into a 32 bit TCG reg */
58ab8e96 2980 TCGv_i32 tmp = tcg_temp_new_i32();
8e18cde3
PM
2981 switch (size) {
2982 case 0:
12dcc321 2983 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2984 gen_neon_dup_u8(tmp, 0);
2985 break;
2986 case 1:
12dcc321 2987 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2988 gen_neon_dup_low16(tmp);
2989 break;
2990 case 2:
12dcc321 2991 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8e18cde3
PM
2992 break;
2993 default: /* Avoid compiler warnings. */
2994 abort();
2995 }
2996 return tmp;
2997}
2998
04731fb5
WN
2999static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
3000 uint32_t dp)
3001{
3002 uint32_t cc = extract32(insn, 20, 2);
3003
3004 if (dp) {
3005 TCGv_i64 frn, frm, dest;
3006 TCGv_i64 tmp, zero, zf, nf, vf;
3007
3008 zero = tcg_const_i64(0);
3009
3010 frn = tcg_temp_new_i64();
3011 frm = tcg_temp_new_i64();
3012 dest = tcg_temp_new_i64();
3013
3014 zf = tcg_temp_new_i64();
3015 nf = tcg_temp_new_i64();
3016 vf = tcg_temp_new_i64();
3017
3018 tcg_gen_extu_i32_i64(zf, cpu_ZF);
3019 tcg_gen_ext_i32_i64(nf, cpu_NF);
3020 tcg_gen_ext_i32_i64(vf, cpu_VF);
3021
3022 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3023 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3024 switch (cc) {
3025 case 0: /* eq: Z */
3026 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
3027 frn, frm);
3028 break;
3029 case 1: /* vs: V */
3030 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
3031 frn, frm);
3032 break;
3033 case 2: /* ge: N == V -> N ^ V == 0 */
3034 tmp = tcg_temp_new_i64();
3035 tcg_gen_xor_i64(tmp, vf, nf);
3036 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3037 frn, frm);
3038 tcg_temp_free_i64(tmp);
3039 break;
3040 case 3: /* gt: !Z && N == V */
3041 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
3042 frn, frm);
3043 tmp = tcg_temp_new_i64();
3044 tcg_gen_xor_i64(tmp, vf, nf);
3045 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3046 dest, frm);
3047 tcg_temp_free_i64(tmp);
3048 break;
3049 }
3050 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3051 tcg_temp_free_i64(frn);
3052 tcg_temp_free_i64(frm);
3053 tcg_temp_free_i64(dest);
3054
3055 tcg_temp_free_i64(zf);
3056 tcg_temp_free_i64(nf);
3057 tcg_temp_free_i64(vf);
3058
3059 tcg_temp_free_i64(zero);
3060 } else {
3061 TCGv_i32 frn, frm, dest;
3062 TCGv_i32 tmp, zero;
3063
3064 zero = tcg_const_i32(0);
3065
3066 frn = tcg_temp_new_i32();
3067 frm = tcg_temp_new_i32();
3068 dest = tcg_temp_new_i32();
3069 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3070 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3071 switch (cc) {
3072 case 0: /* eq: Z */
3073 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
3074 frn, frm);
3075 break;
3076 case 1: /* vs: V */
3077 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
3078 frn, frm);
3079 break;
3080 case 2: /* ge: N == V -> N ^ V == 0 */
3081 tmp = tcg_temp_new_i32();
3082 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3083 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3084 frn, frm);
3085 tcg_temp_free_i32(tmp);
3086 break;
3087 case 3: /* gt: !Z && N == V */
3088 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
3089 frn, frm);
3090 tmp = tcg_temp_new_i32();
3091 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3092 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3093 dest, frm);
3094 tcg_temp_free_i32(tmp);
3095 break;
3096 }
3097 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3098 tcg_temp_free_i32(frn);
3099 tcg_temp_free_i32(frm);
3100 tcg_temp_free_i32(dest);
3101
3102 tcg_temp_free_i32(zero);
3103 }
3104
3105 return 0;
3106}
3107
40cfacdd
WN
3108static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
3109 uint32_t rm, uint32_t dp)
3110{
3111 uint32_t vmin = extract32(insn, 6, 1);
3112 TCGv_ptr fpst = get_fpstatus_ptr(0);
3113
3114 if (dp) {
3115 TCGv_i64 frn, frm, dest;
3116
3117 frn = tcg_temp_new_i64();
3118 frm = tcg_temp_new_i64();
3119 dest = tcg_temp_new_i64();
3120
3121 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3122 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3123 if (vmin) {
f71a2ae5 3124 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
40cfacdd 3125 } else {
f71a2ae5 3126 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
40cfacdd
WN
3127 }
3128 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3129 tcg_temp_free_i64(frn);
3130 tcg_temp_free_i64(frm);
3131 tcg_temp_free_i64(dest);
3132 } else {
3133 TCGv_i32 frn, frm, dest;
3134
3135 frn = tcg_temp_new_i32();
3136 frm = tcg_temp_new_i32();
3137 dest = tcg_temp_new_i32();
3138
3139 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3140 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3141 if (vmin) {
f71a2ae5 3142 gen_helper_vfp_minnums(dest, frn, frm, fpst);
40cfacdd 3143 } else {
f71a2ae5 3144 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
40cfacdd
WN
3145 }
3146 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3147 tcg_temp_free_i32(frn);
3148 tcg_temp_free_i32(frm);
3149 tcg_temp_free_i32(dest);
3150 }
3151
3152 tcg_temp_free_ptr(fpst);
3153 return 0;
3154}
3155
7655f39b
WN
3156static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3157 int rounding)
3158{
3159 TCGv_ptr fpst = get_fpstatus_ptr(0);
3160 TCGv_i32 tcg_rmode;
3161
3162 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
9b049916 3163 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
7655f39b
WN
3164
3165 if (dp) {
3166 TCGv_i64 tcg_op;
3167 TCGv_i64 tcg_res;
3168 tcg_op = tcg_temp_new_i64();
3169 tcg_res = tcg_temp_new_i64();
3170 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3171 gen_helper_rintd(tcg_res, tcg_op, fpst);
3172 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3173 tcg_temp_free_i64(tcg_op);
3174 tcg_temp_free_i64(tcg_res);
3175 } else {
3176 TCGv_i32 tcg_op;
3177 TCGv_i32 tcg_res;
3178 tcg_op = tcg_temp_new_i32();
3179 tcg_res = tcg_temp_new_i32();
3180 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3181 gen_helper_rints(tcg_res, tcg_op, fpst);
3182 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3183 tcg_temp_free_i32(tcg_op);
3184 tcg_temp_free_i32(tcg_res);
3185 }
3186
9b049916 3187 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
7655f39b
WN
3188 tcg_temp_free_i32(tcg_rmode);
3189
3190 tcg_temp_free_ptr(fpst);
3191 return 0;
3192}
3193
c9975a83
WN
3194static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3195 int rounding)
3196{
3197 bool is_signed = extract32(insn, 7, 1);
3198 TCGv_ptr fpst = get_fpstatus_ptr(0);
3199 TCGv_i32 tcg_rmode, tcg_shift;
3200
3201 tcg_shift = tcg_const_i32(0);
3202
3203 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
9b049916 3204 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
c9975a83
WN
3205
3206 if (dp) {
3207 TCGv_i64 tcg_double, tcg_res;
3208 TCGv_i32 tcg_tmp;
3209 /* Rd is encoded as a single precision register even when the source
3210 * is double precision.
3211 */
3212 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3213 tcg_double = tcg_temp_new_i64();
3214 tcg_res = tcg_temp_new_i64();
3215 tcg_tmp = tcg_temp_new_i32();
3216 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3217 if (is_signed) {
3218 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3219 } else {
3220 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3221 }
ecc7b3aa 3222 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
c9975a83
WN
3223 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3224 tcg_temp_free_i32(tcg_tmp);
3225 tcg_temp_free_i64(tcg_res);
3226 tcg_temp_free_i64(tcg_double);
3227 } else {
3228 TCGv_i32 tcg_single, tcg_res;
3229 tcg_single = tcg_temp_new_i32();
3230 tcg_res = tcg_temp_new_i32();
3231 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3232 if (is_signed) {
3233 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3234 } else {
3235 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3236 }
3237 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3238 tcg_temp_free_i32(tcg_res);
3239 tcg_temp_free_i32(tcg_single);
3240 }
3241
9b049916 3242 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
c9975a83
WN
3243 tcg_temp_free_i32(tcg_rmode);
3244
3245 tcg_temp_free_i32(tcg_shift);
3246
3247 tcg_temp_free_ptr(fpst);
3248
3249 return 0;
3250}
7655f39b
WN
3251
3252/* Table for converting the most common AArch32 encoding of
3253 * rounding mode to arm_fprounding order (which matches the
3254 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3255 */
3256static const uint8_t fp_decode_rm[] = {
3257 FPROUNDING_TIEAWAY,
3258 FPROUNDING_TIEEVEN,
3259 FPROUNDING_POSINF,
3260 FPROUNDING_NEGINF,
3261};
3262
7dcc1f89 3263static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
04731fb5
WN
3264{
3265 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3266
d614a513 3267 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
04731fb5
WN
3268 return 1;
3269 }
3270
3271 if (dp) {
3272 VFP_DREG_D(rd, insn);
3273 VFP_DREG_N(rn, insn);
3274 VFP_DREG_M(rm, insn);
3275 } else {
3276 rd = VFP_SREG_D(insn);
3277 rn = VFP_SREG_N(insn);
3278 rm = VFP_SREG_M(insn);
3279 }
3280
3281 if ((insn & 0x0f800e50) == 0x0e000a00) {
3282 return handle_vsel(insn, rd, rn, rm, dp);
40cfacdd
WN
3283 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
3284 return handle_vminmaxnm(insn, rd, rn, rm, dp);
7655f39b
WN
3285 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
3286 /* VRINTA, VRINTN, VRINTP, VRINTM */
3287 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3288 return handle_vrint(insn, rd, rm, dp, rounding);
c9975a83
WN
3289 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
3290 /* VCVTA, VCVTN, VCVTP, VCVTM */
3291 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3292 return handle_vcvt(insn, rd, rm, dp, rounding);
04731fb5
WN
3293 }
3294 return 1;
3295}
3296
a1c7273b 3297/* Disassemble a VFP instruction. Returns nonzero if an error occurred
b7bcbe95 3298 (ie. an undefined instruction). */
7dcc1f89 3299static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95
FB
3300{
3301 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3302 int dp, veclen;
39d5492a
PM
3303 TCGv_i32 addr;
3304 TCGv_i32 tmp;
3305 TCGv_i32 tmp2;
b7bcbe95 3306
d614a513 3307 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 3308 return 1;
d614a513 3309 }
40f137e1 3310
2c7ffc41
PM
3311 /* FIXME: this access check should not take precedence over UNDEF
3312 * for invalid encodings; we will generate incorrect syndrome information
3313 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3314 */
9dbbc748 3315 if (s->fp_excp_el) {
2c7ffc41 3316 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 3317 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3318 return 0;
3319 }
3320
5df8bac1 3321 if (!s->vfp_enabled) {
9ee6e8bb 3322 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
3323 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3324 return 1;
3325 rn = (insn >> 16) & 0xf;
a50c0f51
PM
3326 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3327 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
40f137e1 3328 return 1;
a50c0f51 3329 }
40f137e1 3330 }
6a57f3eb
WN
3331
3332 if (extract32(insn, 28, 4) == 0xf) {
3333 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3334 * only used in v8 and above.
3335 */
7dcc1f89 3336 return disas_vfp_v8_insn(s, insn);
6a57f3eb
WN
3337 }
3338
b7bcbe95
FB
3339 dp = ((insn & 0xf00) == 0xb00);
3340 switch ((insn >> 24) & 0xf) {
3341 case 0xe:
3342 if (insn & (1 << 4)) {
3343 /* single register transfer */
b7bcbe95
FB
3344 rd = (insn >> 12) & 0xf;
3345 if (dp) {
9ee6e8bb
PB
3346 int size;
3347 int pass;
3348
3349 VFP_DREG_N(rn, insn);
3350 if (insn & 0xf)
b7bcbe95 3351 return 1;
9ee6e8bb 3352 if (insn & 0x00c00060
d614a513 3353 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 3354 return 1;
d614a513 3355 }
9ee6e8bb
PB
3356
3357 pass = (insn >> 21) & 1;
3358 if (insn & (1 << 22)) {
3359 size = 0;
3360 offset = ((insn >> 5) & 3) * 8;
3361 } else if (insn & (1 << 5)) {
3362 size = 1;
3363 offset = (insn & (1 << 6)) ? 16 : 0;
3364 } else {
3365 size = 2;
3366 offset = 0;
3367 }
18c9b560 3368 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3369 /* vfp->arm */
ad69471c 3370 tmp = neon_load_reg(rn, pass);
9ee6e8bb
PB
3371 switch (size) {
3372 case 0:
9ee6e8bb 3373 if (offset)
ad69471c 3374 tcg_gen_shri_i32(tmp, tmp, offset);
9ee6e8bb 3375 if (insn & (1 << 23))
ad69471c 3376 gen_uxtb(tmp);
9ee6e8bb 3377 else
ad69471c 3378 gen_sxtb(tmp);
9ee6e8bb
PB
3379 break;
3380 case 1:
9ee6e8bb
PB
3381 if (insn & (1 << 23)) {
3382 if (offset) {
ad69471c 3383 tcg_gen_shri_i32(tmp, tmp, 16);
9ee6e8bb 3384 } else {
ad69471c 3385 gen_uxth(tmp);
9ee6e8bb
PB
3386 }
3387 } else {
3388 if (offset) {
ad69471c 3389 tcg_gen_sari_i32(tmp, tmp, 16);
9ee6e8bb 3390 } else {
ad69471c 3391 gen_sxth(tmp);
9ee6e8bb
PB
3392 }
3393 }
3394 break;
3395 case 2:
9ee6e8bb
PB
3396 break;
3397 }
ad69471c 3398 store_reg(s, rd, tmp);
b7bcbe95
FB
3399 } else {
3400 /* arm->vfp */
ad69471c 3401 tmp = load_reg(s, rd);
9ee6e8bb
PB
3402 if (insn & (1 << 23)) {
3403 /* VDUP */
3404 if (size == 0) {
ad69471c 3405 gen_neon_dup_u8(tmp, 0);
9ee6e8bb 3406 } else if (size == 1) {
ad69471c 3407 gen_neon_dup_low16(tmp);
9ee6e8bb 3408 }
cbbccffc 3409 for (n = 0; n <= pass * 2; n++) {
7d1b0095 3410 tmp2 = tcg_temp_new_i32();
cbbccffc
PB
3411 tcg_gen_mov_i32(tmp2, tmp);
3412 neon_store_reg(rn, n, tmp2);
3413 }
3414 neon_store_reg(rn, n, tmp);
9ee6e8bb
PB
3415 } else {
3416 /* VMOV */
3417 switch (size) {
3418 case 0:
ad69471c 3419 tmp2 = neon_load_reg(rn, pass);
d593c48e 3420 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
7d1b0095 3421 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3422 break;
3423 case 1:
ad69471c 3424 tmp2 = neon_load_reg(rn, pass);
d593c48e 3425 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
7d1b0095 3426 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3427 break;
3428 case 2:
9ee6e8bb
PB
3429 break;
3430 }
ad69471c 3431 neon_store_reg(rn, pass, tmp);
9ee6e8bb 3432 }
b7bcbe95 3433 }
9ee6e8bb
PB
3434 } else { /* !dp */
3435 if ((insn & 0x6f) != 0x00)
3436 return 1;
3437 rn = VFP_SREG_N(insn);
18c9b560 3438 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3439 /* vfp->arm */
3440 if (insn & (1 << 21)) {
3441 /* system register */
40f137e1 3442 rn >>= 1;
9ee6e8bb 3443
b7bcbe95 3444 switch (rn) {
40f137e1 3445 case ARM_VFP_FPSID:
4373f3ce 3446 /* VFP2 allows access to FSID from userspace.
9ee6e8bb
PB
3447 VFP3 restricts all id registers to privileged
3448 accesses. */
3449 if (IS_USER(s)
d614a513 3450 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3451 return 1;
d614a513 3452 }
4373f3ce 3453 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3454 break;
40f137e1 3455 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3456 if (IS_USER(s))
3457 return 1;
4373f3ce 3458 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3459 break;
40f137e1
PB
3460 case ARM_VFP_FPINST:
3461 case ARM_VFP_FPINST2:
9ee6e8bb
PB
3462 /* Not present in VFP3. */
3463 if (IS_USER(s)
d614a513 3464 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3465 return 1;
d614a513 3466 }
4373f3ce 3467 tmp = load_cpu_field(vfp.xregs[rn]);
b7bcbe95 3468 break;
40f137e1 3469 case ARM_VFP_FPSCR:
601d70b9 3470 if (rd == 15) {
4373f3ce
PB
3471 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3472 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3473 } else {
7d1b0095 3474 tmp = tcg_temp_new_i32();
4373f3ce
PB
3475 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3476 }
b7bcbe95 3477 break;
a50c0f51 3478 case ARM_VFP_MVFR2:
d614a513 3479 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
a50c0f51
PM
3480 return 1;
3481 }
3482 /* fall through */
9ee6e8bb
PB
3483 case ARM_VFP_MVFR0:
3484 case ARM_VFP_MVFR1:
3485 if (IS_USER(s)
d614a513 3486 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
9ee6e8bb 3487 return 1;
d614a513 3488 }
4373f3ce 3489 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3490 break;
b7bcbe95
FB
3491 default:
3492 return 1;
3493 }
3494 } else {
3495 gen_mov_F0_vreg(0, rn);
4373f3ce 3496 tmp = gen_vfp_mrs();
b7bcbe95
FB
3497 }
3498 if (rd == 15) {
b5ff1b31 3499 /* Set the 4 flag bits in the CPSR. */
4373f3ce 3500 gen_set_nzcv(tmp);
7d1b0095 3501 tcg_temp_free_i32(tmp);
4373f3ce
PB
3502 } else {
3503 store_reg(s, rd, tmp);
3504 }
b7bcbe95
FB
3505 } else {
3506 /* arm->vfp */
b7bcbe95 3507 if (insn & (1 << 21)) {
40f137e1 3508 rn >>= 1;
b7bcbe95
FB
3509 /* system register */
3510 switch (rn) {
40f137e1 3511 case ARM_VFP_FPSID:
9ee6e8bb
PB
3512 case ARM_VFP_MVFR0:
3513 case ARM_VFP_MVFR1:
b7bcbe95
FB
3514 /* Writes are ignored. */
3515 break;
40f137e1 3516 case ARM_VFP_FPSCR:
e4c1cfa5 3517 tmp = load_reg(s, rd);
4373f3ce 3518 gen_helper_vfp_set_fpscr(cpu_env, tmp);
7d1b0095 3519 tcg_temp_free_i32(tmp);
b5ff1b31 3520 gen_lookup_tb(s);
b7bcbe95 3521 break;
40f137e1 3522 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3523 if (IS_USER(s))
3524 return 1;
71b3c3de
JR
3525 /* TODO: VFP subarchitecture support.
3526 * For now, keep the EN bit only */
e4c1cfa5 3527 tmp = load_reg(s, rd);
71b3c3de 3528 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
4373f3ce 3529 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1
PB
3530 gen_lookup_tb(s);
3531 break;
3532 case ARM_VFP_FPINST:
3533 case ARM_VFP_FPINST2:
23adb861
PM
3534 if (IS_USER(s)) {
3535 return 1;
3536 }
e4c1cfa5 3537 tmp = load_reg(s, rd);
4373f3ce 3538 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1 3539 break;
b7bcbe95
FB
3540 default:
3541 return 1;
3542 }
3543 } else {
e4c1cfa5 3544 tmp = load_reg(s, rd);
4373f3ce 3545 gen_vfp_msr(tmp);
b7bcbe95
FB
3546 gen_mov_vreg_F0(0, rn);
3547 }
3548 }
3549 }
3550 } else {
3551 /* data processing */
3552 /* The opcode is in bits 23, 21, 20 and 6. */
3553 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3554 if (dp) {
3555 if (op == 15) {
3556 /* rn is opcode */
3557 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3558 } else {
3559 /* rn is register number */
9ee6e8bb 3560 VFP_DREG_N(rn, insn);
b7bcbe95
FB
3561 }
3562
239c20c7
WN
3563 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3564 ((rn & 0x1e) == 0x6))) {
3565 /* Integer or single/half precision destination. */
9ee6e8bb 3566 rd = VFP_SREG_D(insn);
b7bcbe95 3567 } else {
9ee6e8bb 3568 VFP_DREG_D(rd, insn);
b7bcbe95 3569 }
04595bf6 3570 if (op == 15 &&
239c20c7
WN
3571 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3572 ((rn & 0x1e) == 0x4))) {
3573 /* VCVT from int or half precision is always from S reg
3574 * regardless of dp bit. VCVT with immediate frac_bits
3575 * has same format as SREG_M.
04595bf6
PM
3576 */
3577 rm = VFP_SREG_M(insn);
b7bcbe95 3578 } else {
9ee6e8bb 3579 VFP_DREG_M(rm, insn);
b7bcbe95
FB
3580 }
3581 } else {
9ee6e8bb 3582 rn = VFP_SREG_N(insn);
b7bcbe95
FB
3583 if (op == 15 && rn == 15) {
3584 /* Double precision destination. */
9ee6e8bb
PB
3585 VFP_DREG_D(rd, insn);
3586 } else {
3587 rd = VFP_SREG_D(insn);
3588 }
04595bf6
PM
3589 /* NB that we implicitly rely on the encoding for the frac_bits
3590 * in VCVT of fixed to float being the same as that of an SREG_M
3591 */
9ee6e8bb 3592 rm = VFP_SREG_M(insn);
b7bcbe95
FB
3593 }
3594
69d1fc22 3595 veclen = s->vec_len;
b7bcbe95
FB
3596 if (op == 15 && rn > 3)
3597 veclen = 0;
3598
3599 /* Shut up compiler warnings. */
3600 delta_m = 0;
3601 delta_d = 0;
3602 bank_mask = 0;
3b46e624 3603
b7bcbe95
FB
3604 if (veclen > 0) {
3605 if (dp)
3606 bank_mask = 0xc;
3607 else
3608 bank_mask = 0x18;
3609
3610 /* Figure out what type of vector operation this is. */
3611 if ((rd & bank_mask) == 0) {
3612 /* scalar */
3613 veclen = 0;
3614 } else {
3615 if (dp)
69d1fc22 3616 delta_d = (s->vec_stride >> 1) + 1;
b7bcbe95 3617 else
69d1fc22 3618 delta_d = s->vec_stride + 1;
b7bcbe95
FB
3619
3620 if ((rm & bank_mask) == 0) {
3621 /* mixed scalar/vector */
3622 delta_m = 0;
3623 } else {
3624 /* vector */
3625 delta_m = delta_d;
3626 }
3627 }
3628 }
3629
3630 /* Load the initial operands. */
3631 if (op == 15) {
3632 switch (rn) {
3633 case 16:
3634 case 17:
3635 /* Integer source */
3636 gen_mov_F0_vreg(0, rm);
3637 break;
3638 case 8:
3639 case 9:
3640 /* Compare */
3641 gen_mov_F0_vreg(dp, rd);
3642 gen_mov_F1_vreg(dp, rm);
3643 break;
3644 case 10:
3645 case 11:
3646 /* Compare with zero */
3647 gen_mov_F0_vreg(dp, rd);
3648 gen_vfp_F1_ld0(dp);
3649 break;
9ee6e8bb
PB
3650 case 20:
3651 case 21:
3652 case 22:
3653 case 23:
644ad806
PB
3654 case 28:
3655 case 29:
3656 case 30:
3657 case 31:
9ee6e8bb
PB
3658 /* Source and destination the same. */
3659 gen_mov_F0_vreg(dp, rd);
3660 break;
6e0c0ed1
PM
3661 case 4:
3662 case 5:
3663 case 6:
3664 case 7:
239c20c7
WN
3665 /* VCVTB, VCVTT: only present with the halfprec extension
3666 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3667 * (we choose to UNDEF)
6e0c0ed1 3668 */
d614a513
PM
3669 if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
3670 !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
6e0c0ed1
PM
3671 return 1;
3672 }
239c20c7
WN
3673 if (!extract32(rn, 1, 1)) {
3674 /* Half precision source. */
3675 gen_mov_F0_vreg(0, rm);
3676 break;
3677 }
6e0c0ed1 3678 /* Otherwise fall through */
b7bcbe95
FB
3679 default:
3680 /* One source operand. */
3681 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 3682 break;
b7bcbe95
FB
3683 }
3684 } else {
3685 /* Two source operands. */
3686 gen_mov_F0_vreg(dp, rn);
3687 gen_mov_F1_vreg(dp, rm);
3688 }
3689
3690 for (;;) {
3691 /* Perform the calculation. */
3692 switch (op) {
605a6aed
PM
3693 case 0: /* VMLA: fd + (fn * fm) */
3694 /* Note that order of inputs to the add matters for NaNs */
3695 gen_vfp_F1_mul(dp);
3696 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3697 gen_vfp_add(dp);
3698 break;
605a6aed 3699 case 1: /* VMLS: fd + -(fn * fm) */
b7bcbe95 3700 gen_vfp_mul(dp);
605a6aed
PM
3701 gen_vfp_F1_neg(dp);
3702 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3703 gen_vfp_add(dp);
3704 break;
605a6aed
PM
3705 case 2: /* VNMLS: -fd + (fn * fm) */
3706 /* Note that it isn't valid to replace (-A + B) with (B - A)
3707 * or similar plausible looking simplifications
3708 * because this will give wrong results for NaNs.
3709 */
3710 gen_vfp_F1_mul(dp);
3711 gen_mov_F0_vreg(dp, rd);
3712 gen_vfp_neg(dp);
3713 gen_vfp_add(dp);
b7bcbe95 3714 break;
605a6aed 3715 case 3: /* VNMLA: -fd + -(fn * fm) */
b7bcbe95 3716 gen_vfp_mul(dp);
605a6aed
PM
3717 gen_vfp_F1_neg(dp);
3718 gen_mov_F0_vreg(dp, rd);
b7bcbe95 3719 gen_vfp_neg(dp);
605a6aed 3720 gen_vfp_add(dp);
b7bcbe95
FB
3721 break;
3722 case 4: /* mul: fn * fm */
3723 gen_vfp_mul(dp);
3724 break;
3725 case 5: /* nmul: -(fn * fm) */
3726 gen_vfp_mul(dp);
3727 gen_vfp_neg(dp);
3728 break;
3729 case 6: /* add: fn + fm */
3730 gen_vfp_add(dp);
3731 break;
3732 case 7: /* sub: fn - fm */
3733 gen_vfp_sub(dp);
3734 break;
3735 case 8: /* div: fn / fm */
3736 gen_vfp_div(dp);
3737 break;
da97f52c
PM
3738 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3739 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3740 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3741 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3742 /* These are fused multiply-add, and must be done as one
3743 * floating point operation with no rounding between the
3744 * multiplication and addition steps.
3745 * NB that doing the negations here as separate steps is
3746 * correct : an input NaN should come out with its sign bit
3747 * flipped if it is a negated-input.
3748 */
d614a513 3749 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
3750 return 1;
3751 }
3752 if (dp) {
3753 TCGv_ptr fpst;
3754 TCGv_i64 frd;
3755 if (op & 1) {
3756 /* VFNMS, VFMS */
3757 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3758 }
3759 frd = tcg_temp_new_i64();
3760 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3761 if (op & 2) {
3762 /* VFNMA, VFNMS */
3763 gen_helper_vfp_negd(frd, frd);
3764 }
3765 fpst = get_fpstatus_ptr(0);
3766 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3767 cpu_F1d, frd, fpst);
3768 tcg_temp_free_ptr(fpst);
3769 tcg_temp_free_i64(frd);
3770 } else {
3771 TCGv_ptr fpst;
3772 TCGv_i32 frd;
3773 if (op & 1) {
3774 /* VFNMS, VFMS */
3775 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3776 }
3777 frd = tcg_temp_new_i32();
3778 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3779 if (op & 2) {
3780 gen_helper_vfp_negs(frd, frd);
3781 }
3782 fpst = get_fpstatus_ptr(0);
3783 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3784 cpu_F1s, frd, fpst);
3785 tcg_temp_free_ptr(fpst);
3786 tcg_temp_free_i32(frd);
3787 }
3788 break;
9ee6e8bb 3789 case 14: /* fconst */
d614a513
PM
3790 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3791 return 1;
3792 }
9ee6e8bb
PB
3793
3794 n = (insn << 12) & 0x80000000;
3795 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3796 if (dp) {
3797 if (i & 0x40)
3798 i |= 0x3f80;
3799 else
3800 i |= 0x4000;
3801 n |= i << 16;
4373f3ce 3802 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
9ee6e8bb
PB
3803 } else {
3804 if (i & 0x40)
3805 i |= 0x780;
3806 else
3807 i |= 0x800;
3808 n |= i << 19;
5b340b51 3809 tcg_gen_movi_i32(cpu_F0s, n);
9ee6e8bb 3810 }
9ee6e8bb 3811 break;
b7bcbe95
FB
3812 case 15: /* extension space */
3813 switch (rn) {
3814 case 0: /* cpy */
3815 /* no-op */
3816 break;
3817 case 1: /* abs */
3818 gen_vfp_abs(dp);
3819 break;
3820 case 2: /* neg */
3821 gen_vfp_neg(dp);
3822 break;
3823 case 3: /* sqrt */
3824 gen_vfp_sqrt(dp);
3825 break;
239c20c7 3826 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
486624fc
AB
3827 {
3828 TCGv_ptr fpst = get_fpstatus_ptr(false);
3829 TCGv_i32 ahp_mode = get_ahp_flag();
60011498
PB
3830 tmp = gen_vfp_mrs();
3831 tcg_gen_ext16u_i32(tmp, tmp);
239c20c7
WN
3832 if (dp) {
3833 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
486624fc 3834 fpst, ahp_mode);
239c20c7
WN
3835 } else {
3836 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
486624fc 3837 fpst, ahp_mode);
239c20c7 3838 }
486624fc
AB
3839 tcg_temp_free_i32(ahp_mode);
3840 tcg_temp_free_ptr(fpst);
7d1b0095 3841 tcg_temp_free_i32(tmp);
60011498 3842 break;
486624fc 3843 }
239c20c7 3844 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
486624fc
AB
3845 {
3846 TCGv_ptr fpst = get_fpstatus_ptr(false);
3847 TCGv_i32 ahp = get_ahp_flag();
60011498
PB
3848 tmp = gen_vfp_mrs();
3849 tcg_gen_shri_i32(tmp, tmp, 16);
239c20c7
WN
3850 if (dp) {
3851 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
486624fc 3852 fpst, ahp);
239c20c7
WN
3853 } else {
3854 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
486624fc 3855 fpst, ahp);
239c20c7 3856 }
7d1b0095 3857 tcg_temp_free_i32(tmp);
486624fc
AB
3858 tcg_temp_free_i32(ahp);
3859 tcg_temp_free_ptr(fpst);
60011498 3860 break;
486624fc 3861 }
239c20c7 3862 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
486624fc
AB
3863 {
3864 TCGv_ptr fpst = get_fpstatus_ptr(false);
3865 TCGv_i32 ahp = get_ahp_flag();
7d1b0095 3866 tmp = tcg_temp_new_i32();
486624fc 3867
239c20c7
WN
3868 if (dp) {
3869 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
486624fc 3870 fpst, ahp);
239c20c7
WN
3871 } else {
3872 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
486624fc 3873 fpst, ahp);
239c20c7 3874 }
486624fc
AB
3875 tcg_temp_free_i32(ahp);
3876 tcg_temp_free_ptr(fpst);
60011498
PB
3877 gen_mov_F0_vreg(0, rd);
3878 tmp2 = gen_vfp_mrs();
3879 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3880 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3881 tcg_temp_free_i32(tmp2);
60011498
PB
3882 gen_vfp_msr(tmp);
3883 break;
486624fc 3884 }
239c20c7 3885 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
486624fc
AB
3886 {
3887 TCGv_ptr fpst = get_fpstatus_ptr(false);
3888 TCGv_i32 ahp = get_ahp_flag();
7d1b0095 3889 tmp = tcg_temp_new_i32();
239c20c7
WN
3890 if (dp) {
3891 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
486624fc 3892 fpst, ahp);
239c20c7
WN
3893 } else {
3894 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
486624fc 3895 fpst, ahp);
239c20c7 3896 }
486624fc
AB
3897 tcg_temp_free_i32(ahp);
3898 tcg_temp_free_ptr(fpst);
60011498
PB
3899 tcg_gen_shli_i32(tmp, tmp, 16);
3900 gen_mov_F0_vreg(0, rd);
3901 tmp2 = gen_vfp_mrs();
3902 tcg_gen_ext16u_i32(tmp2, tmp2);
3903 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3904 tcg_temp_free_i32(tmp2);
60011498
PB
3905 gen_vfp_msr(tmp);
3906 break;
486624fc 3907 }
b7bcbe95
FB
3908 case 8: /* cmp */
3909 gen_vfp_cmp(dp);
3910 break;
3911 case 9: /* cmpe */
3912 gen_vfp_cmpe(dp);
3913 break;
3914 case 10: /* cmpz */
3915 gen_vfp_cmp(dp);
3916 break;
3917 case 11: /* cmpez */
3918 gen_vfp_F1_ld0(dp);
3919 gen_vfp_cmpe(dp);
3920 break;
664c6733
WN
3921 case 12: /* vrintr */
3922 {
3923 TCGv_ptr fpst = get_fpstatus_ptr(0);
3924 if (dp) {
3925 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3926 } else {
3927 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3928 }
3929 tcg_temp_free_ptr(fpst);
3930 break;
3931 }
a290c62a
WN
3932 case 13: /* vrintz */
3933 {
3934 TCGv_ptr fpst = get_fpstatus_ptr(0);
3935 TCGv_i32 tcg_rmode;
3936 tcg_rmode = tcg_const_i32(float_round_to_zero);
9b049916 3937 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
a290c62a
WN
3938 if (dp) {
3939 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3940 } else {
3941 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3942 }
9b049916 3943 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
a290c62a
WN
3944 tcg_temp_free_i32(tcg_rmode);
3945 tcg_temp_free_ptr(fpst);
3946 break;
3947 }
4e82bc01
WN
3948 case 14: /* vrintx */
3949 {
3950 TCGv_ptr fpst = get_fpstatus_ptr(0);
3951 if (dp) {
3952 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3953 } else {
3954 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3955 }
3956 tcg_temp_free_ptr(fpst);
3957 break;
3958 }
b7bcbe95
FB
3959 case 15: /* single<->double conversion */
3960 if (dp)
4373f3ce 3961 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
b7bcbe95 3962 else
4373f3ce 3963 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
b7bcbe95
FB
3964 break;
3965 case 16: /* fuito */
5500b06c 3966 gen_vfp_uito(dp, 0);
b7bcbe95
FB
3967 break;
3968 case 17: /* fsito */
5500b06c 3969 gen_vfp_sito(dp, 0);
b7bcbe95 3970 break;
9ee6e8bb 3971 case 20: /* fshto */
d614a513
PM
3972 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3973 return 1;
3974 }
5500b06c 3975 gen_vfp_shto(dp, 16 - rm, 0);
9ee6e8bb
PB
3976 break;
3977 case 21: /* fslto */
d614a513
PM
3978 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3979 return 1;
3980 }
5500b06c 3981 gen_vfp_slto(dp, 32 - rm, 0);
9ee6e8bb
PB
3982 break;
3983 case 22: /* fuhto */
d614a513
PM
3984 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3985 return 1;
3986 }
5500b06c 3987 gen_vfp_uhto(dp, 16 - rm, 0);
9ee6e8bb
PB
3988 break;
3989 case 23: /* fulto */
d614a513
PM
3990 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3991 return 1;
3992 }
5500b06c 3993 gen_vfp_ulto(dp, 32 - rm, 0);
9ee6e8bb 3994 break;
b7bcbe95 3995 case 24: /* ftoui */
5500b06c 3996 gen_vfp_toui(dp, 0);
b7bcbe95
FB
3997 break;
3998 case 25: /* ftouiz */
5500b06c 3999 gen_vfp_touiz(dp, 0);
b7bcbe95
FB
4000 break;
4001 case 26: /* ftosi */
5500b06c 4002 gen_vfp_tosi(dp, 0);
b7bcbe95
FB
4003 break;
4004 case 27: /* ftosiz */
5500b06c 4005 gen_vfp_tosiz(dp, 0);
b7bcbe95 4006 break;
9ee6e8bb 4007 case 28: /* ftosh */
d614a513
PM
4008 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4009 return 1;
4010 }
5500b06c 4011 gen_vfp_tosh(dp, 16 - rm, 0);
9ee6e8bb
PB
4012 break;
4013 case 29: /* ftosl */
d614a513
PM
4014 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4015 return 1;
4016 }
5500b06c 4017 gen_vfp_tosl(dp, 32 - rm, 0);
9ee6e8bb
PB
4018 break;
4019 case 30: /* ftouh */
d614a513
PM
4020 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4021 return 1;
4022 }
5500b06c 4023 gen_vfp_touh(dp, 16 - rm, 0);
9ee6e8bb
PB
4024 break;
4025 case 31: /* ftoul */
d614a513
PM
4026 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4027 return 1;
4028 }
5500b06c 4029 gen_vfp_toul(dp, 32 - rm, 0);
9ee6e8bb 4030 break;
b7bcbe95 4031 default: /* undefined */
b7bcbe95
FB
4032 return 1;
4033 }
4034 break;
4035 default: /* undefined */
b7bcbe95
FB
4036 return 1;
4037 }
4038
4039 /* Write back the result. */
239c20c7
WN
4040 if (op == 15 && (rn >= 8 && rn <= 11)) {
4041 /* Comparison, do nothing. */
4042 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
4043 (rn & 0x1e) == 0x6)) {
4044 /* VCVT double to int: always integer result.
4045 * VCVT double to half precision is always a single
4046 * precision result.
4047 */
b7bcbe95 4048 gen_mov_vreg_F0(0, rd);
239c20c7 4049 } else if (op == 15 && rn == 15) {
b7bcbe95
FB
4050 /* conversion */
4051 gen_mov_vreg_F0(!dp, rd);
239c20c7 4052 } else {
b7bcbe95 4053 gen_mov_vreg_F0(dp, rd);
239c20c7 4054 }
b7bcbe95
FB
4055
4056 /* break out of the loop if we have finished */
4057 if (veclen == 0)
4058 break;
4059
4060 if (op == 15 && delta_m == 0) {
4061 /* single source one-many */
4062 while (veclen--) {
4063 rd = ((rd + delta_d) & (bank_mask - 1))
4064 | (rd & bank_mask);
4065 gen_mov_vreg_F0(dp, rd);
4066 }
4067 break;
4068 }
4069 /* Setup the next operands. */
4070 veclen--;
4071 rd = ((rd + delta_d) & (bank_mask - 1))
4072 | (rd & bank_mask);
4073
4074 if (op == 15) {
4075 /* One source operand. */
4076 rm = ((rm + delta_m) & (bank_mask - 1))
4077 | (rm & bank_mask);
4078 gen_mov_F0_vreg(dp, rm);
4079 } else {
4080 /* Two source operands. */
4081 rn = ((rn + delta_d) & (bank_mask - 1))
4082 | (rn & bank_mask);
4083 gen_mov_F0_vreg(dp, rn);
4084 if (delta_m) {
4085 rm = ((rm + delta_m) & (bank_mask - 1))
4086 | (rm & bank_mask);
4087 gen_mov_F1_vreg(dp, rm);
4088 }
4089 }
4090 }
4091 }
4092 break;
4093 case 0xc:
4094 case 0xd:
8387da81 4095 if ((insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
4096 /* two-register transfer */
4097 rn = (insn >> 16) & 0xf;
4098 rd = (insn >> 12) & 0xf;
4099 if (dp) {
9ee6e8bb
PB
4100 VFP_DREG_M(rm, insn);
4101 } else {
4102 rm = VFP_SREG_M(insn);
4103 }
b7bcbe95 4104
18c9b560 4105 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
4106 /* vfp->arm */
4107 if (dp) {
4373f3ce
PB
4108 gen_mov_F0_vreg(0, rm * 2);
4109 tmp = gen_vfp_mrs();
4110 store_reg(s, rd, tmp);
4111 gen_mov_F0_vreg(0, rm * 2 + 1);
4112 tmp = gen_vfp_mrs();
4113 store_reg(s, rn, tmp);
b7bcbe95
FB
4114 } else {
4115 gen_mov_F0_vreg(0, rm);
4373f3ce 4116 tmp = gen_vfp_mrs();
8387da81 4117 store_reg(s, rd, tmp);
b7bcbe95 4118 gen_mov_F0_vreg(0, rm + 1);
4373f3ce 4119 tmp = gen_vfp_mrs();
8387da81 4120 store_reg(s, rn, tmp);
b7bcbe95
FB
4121 }
4122 } else {
4123 /* arm->vfp */
4124 if (dp) {
4373f3ce
PB
4125 tmp = load_reg(s, rd);
4126 gen_vfp_msr(tmp);
4127 gen_mov_vreg_F0(0, rm * 2);
4128 tmp = load_reg(s, rn);
4129 gen_vfp_msr(tmp);
4130 gen_mov_vreg_F0(0, rm * 2 + 1);
b7bcbe95 4131 } else {
8387da81 4132 tmp = load_reg(s, rd);
4373f3ce 4133 gen_vfp_msr(tmp);
b7bcbe95 4134 gen_mov_vreg_F0(0, rm);
8387da81 4135 tmp = load_reg(s, rn);
4373f3ce 4136 gen_vfp_msr(tmp);
b7bcbe95
FB
4137 gen_mov_vreg_F0(0, rm + 1);
4138 }
4139 }
4140 } else {
4141 /* Load/store */
4142 rn = (insn >> 16) & 0xf;
4143 if (dp)
9ee6e8bb 4144 VFP_DREG_D(rd, insn);
b7bcbe95 4145 else
9ee6e8bb 4146 rd = VFP_SREG_D(insn);
b7bcbe95
FB
4147 if ((insn & 0x01200000) == 0x01000000) {
4148 /* Single load/store */
4149 offset = (insn & 0xff) << 2;
4150 if ((insn & (1 << 23)) == 0)
4151 offset = -offset;
934814f1
PM
4152 if (s->thumb && rn == 15) {
4153 /* This is actually UNPREDICTABLE */
4154 addr = tcg_temp_new_i32();
4155 tcg_gen_movi_i32(addr, s->pc & ~2);
4156 } else {
4157 addr = load_reg(s, rn);
4158 }
312eea9f 4159 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 4160 if (insn & (1 << 20)) {
312eea9f 4161 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
4162 gen_mov_vreg_F0(dp, rd);
4163 } else {
4164 gen_mov_F0_vreg(dp, rd);
312eea9f 4165 gen_vfp_st(s, dp, addr);
b7bcbe95 4166 }
7d1b0095 4167 tcg_temp_free_i32(addr);
b7bcbe95
FB
4168 } else {
4169 /* load/store multiple */
934814f1 4170 int w = insn & (1 << 21);
b7bcbe95
FB
4171 if (dp)
4172 n = (insn >> 1) & 0x7f;
4173 else
4174 n = insn & 0xff;
4175
934814f1
PM
4176 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
4177 /* P == U , W == 1 => UNDEF */
4178 return 1;
4179 }
4180 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
4181 /* UNPREDICTABLE cases for bad immediates: we choose to
4182 * UNDEF to avoid generating huge numbers of TCG ops
4183 */
4184 return 1;
4185 }
4186 if (rn == 15 && w) {
4187 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
4188 return 1;
4189 }
4190
4191 if (s->thumb && rn == 15) {
4192 /* This is actually UNPREDICTABLE */
4193 addr = tcg_temp_new_i32();
4194 tcg_gen_movi_i32(addr, s->pc & ~2);
4195 } else {
4196 addr = load_reg(s, rn);
4197 }
b7bcbe95 4198 if (insn & (1 << 24)) /* pre-decrement */
312eea9f 4199 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
b7bcbe95
FB
4200
4201 if (dp)
4202 offset = 8;
4203 else
4204 offset = 4;
4205 for (i = 0; i < n; i++) {
18c9b560 4206 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 4207 /* load */
312eea9f 4208 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
4209 gen_mov_vreg_F0(dp, rd + i);
4210 } else {
4211 /* store */
4212 gen_mov_F0_vreg(dp, rd + i);
312eea9f 4213 gen_vfp_st(s, dp, addr);
b7bcbe95 4214 }
312eea9f 4215 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 4216 }
934814f1 4217 if (w) {
b7bcbe95
FB
4218 /* writeback */
4219 if (insn & (1 << 24))
4220 offset = -offset * n;
4221 else if (dp && (insn & 1))
4222 offset = 4;
4223 else
4224 offset = 0;
4225
4226 if (offset != 0)
312eea9f
FN
4227 tcg_gen_addi_i32(addr, addr, offset);
4228 store_reg(s, rn, addr);
4229 } else {
7d1b0095 4230 tcg_temp_free_i32(addr);
b7bcbe95
FB
4231 }
4232 }
4233 }
4234 break;
4235 default:
4236 /* Should never happen. */
4237 return 1;
4238 }
4239 return 0;
4240}
4241
90aa39a1 4242static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 4243{
90aa39a1 4244#ifndef CONFIG_USER_ONLY
dcba3a8d 4245 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
90aa39a1
SF
4246 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4247#else
4248 return true;
4249#endif
4250}
6e256c93 4251
8a6b28c7
EC
4252static void gen_goto_ptr(void)
4253{
7f11636d 4254 tcg_gen_lookup_and_goto_ptr();
8a6b28c7
EC
4255}
4256
4cae8f56
AB
4257/* This will end the TB but doesn't guarantee we'll return to
4258 * cpu_loop_exec. Any live exit_requests will be processed as we
4259 * enter the next TB.
4260 */
8a6b28c7 4261static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
90aa39a1
SF
4262{
4263 if (use_goto_tb(s, dest)) {
57fec1fe 4264 tcg_gen_goto_tb(n);
eaed129d 4265 gen_set_pc_im(s, dest);
07ea28b4 4266 tcg_gen_exit_tb(s->base.tb, n);
6e256c93 4267 } else {
eaed129d 4268 gen_set_pc_im(s, dest);
8a6b28c7 4269 gen_goto_ptr();
6e256c93 4270 }
dcba3a8d 4271 s->base.is_jmp = DISAS_NORETURN;
c53be334
FB
4272}
4273
8aaca4c0
FB
4274static inline void gen_jmp (DisasContext *s, uint32_t dest)
4275{
b636649f 4276 if (unlikely(is_singlestepping(s))) {
8aaca4c0 4277 /* An indirect jump so that we still trigger the debug exception. */
5899f386 4278 if (s->thumb)
d9ba4830
PB
4279 dest |= 1;
4280 gen_bx_im(s, dest);
8aaca4c0 4281 } else {
6e256c93 4282 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
4283 }
4284}
4285
39d5492a 4286static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 4287{
ee097184 4288 if (x)
d9ba4830 4289 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 4290 else
d9ba4830 4291 gen_sxth(t0);
ee097184 4292 if (y)
d9ba4830 4293 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 4294 else
d9ba4830
PB
4295 gen_sxth(t1);
4296 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
4297}
4298
4299/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
4300static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4301{
b5ff1b31
FB
4302 uint32_t mask;
4303
4304 mask = 0;
4305 if (flags & (1 << 0))
4306 mask |= 0xff;
4307 if (flags & (1 << 1))
4308 mask |= 0xff00;
4309 if (flags & (1 << 2))
4310 mask |= 0xff0000;
4311 if (flags & (1 << 3))
4312 mask |= 0xff000000;
9ee6e8bb 4313
2ae23e75 4314 /* Mask out undefined bits. */
9ee6e8bb 4315 mask &= ~CPSR_RESERVED;
d614a513 4316 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 4317 mask &= ~CPSR_T;
d614a513
PM
4318 }
4319 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 4320 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
4321 }
4322 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 4323 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
4324 }
4325 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 4326 mask &= ~CPSR_IT;
d614a513 4327 }
4051e12c
PM
4328 /* Mask out execution state and reserved bits. */
4329 if (!spsr) {
4330 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4331 }
b5ff1b31
FB
4332 /* Mask out privileged bits. */
4333 if (IS_USER(s))
9ee6e8bb 4334 mask &= CPSR_USER;
b5ff1b31
FB
4335 return mask;
4336}
4337
2fbac54b 4338/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 4339static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 4340{
39d5492a 4341 TCGv_i32 tmp;
b5ff1b31
FB
4342 if (spsr) {
4343 /* ??? This is also undefined in system mode. */
4344 if (IS_USER(s))
4345 return 1;
d9ba4830
PB
4346
4347 tmp = load_cpu_field(spsr);
4348 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
4349 tcg_gen_andi_i32(t0, t0, mask);
4350 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 4351 store_cpu_field(tmp, spsr);
b5ff1b31 4352 } else {
2fbac54b 4353 gen_set_cpsr(t0, mask);
b5ff1b31 4354 }
7d1b0095 4355 tcg_temp_free_i32(t0);
b5ff1b31
FB
4356 gen_lookup_tb(s);
4357 return 0;
4358}
4359
2fbac54b
FN
4360/* Returns nonzero if access to the PSR is not permitted. */
4361static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4362{
39d5492a 4363 TCGv_i32 tmp;
7d1b0095 4364 tmp = tcg_temp_new_i32();
2fbac54b
FN
4365 tcg_gen_movi_i32(tmp, val);
4366 return gen_set_psr(s, mask, spsr, tmp);
4367}
4368
8bfd0550
PM
4369static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4370 int *tgtmode, int *regno)
4371{
4372 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4373 * the target mode and register number, and identify the various
4374 * unpredictable cases.
4375 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4376 * + executed in user mode
4377 * + using R15 as the src/dest register
4378 * + accessing an unimplemented register
4379 * + accessing a register that's inaccessible at current PL/security state*
4380 * + accessing a register that you could access with a different insn
4381 * We choose to UNDEF in all these cases.
4382 * Since we don't know which of the various AArch32 modes we are in
4383 * we have to defer some checks to runtime.
4384 * Accesses to Monitor mode registers from Secure EL1 (which implies
4385 * that EL3 is AArch64) must trap to EL3.
4386 *
4387 * If the access checks fail this function will emit code to take
4388 * an exception and return false. Otherwise it will return true,
4389 * and set *tgtmode and *regno appropriately.
4390 */
4391 int exc_target = default_exception_el(s);
4392
4393 /* These instructions are present only in ARMv8, or in ARMv7 with the
4394 * Virtualization Extensions.
4395 */
4396 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4397 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4398 goto undef;
4399 }
4400
4401 if (IS_USER(s) || rn == 15) {
4402 goto undef;
4403 }
4404
4405 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4406 * of registers into (r, sysm).
4407 */
4408 if (r) {
4409 /* SPSRs for other modes */
4410 switch (sysm) {
4411 case 0xe: /* SPSR_fiq */
4412 *tgtmode = ARM_CPU_MODE_FIQ;
4413 break;
4414 case 0x10: /* SPSR_irq */
4415 *tgtmode = ARM_CPU_MODE_IRQ;
4416 break;
4417 case 0x12: /* SPSR_svc */
4418 *tgtmode = ARM_CPU_MODE_SVC;
4419 break;
4420 case 0x14: /* SPSR_abt */
4421 *tgtmode = ARM_CPU_MODE_ABT;
4422 break;
4423 case 0x16: /* SPSR_und */
4424 *tgtmode = ARM_CPU_MODE_UND;
4425 break;
4426 case 0x1c: /* SPSR_mon */
4427 *tgtmode = ARM_CPU_MODE_MON;
4428 break;
4429 case 0x1e: /* SPSR_hyp */
4430 *tgtmode = ARM_CPU_MODE_HYP;
4431 break;
4432 default: /* unallocated */
4433 goto undef;
4434 }
4435 /* We arbitrarily assign SPSR a register number of 16. */
4436 *regno = 16;
4437 } else {
4438 /* general purpose registers for other modes */
4439 switch (sysm) {
4440 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4441 *tgtmode = ARM_CPU_MODE_USR;
4442 *regno = sysm + 8;
4443 break;
4444 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4445 *tgtmode = ARM_CPU_MODE_FIQ;
4446 *regno = sysm;
4447 break;
4448 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4449 *tgtmode = ARM_CPU_MODE_IRQ;
4450 *regno = sysm & 1 ? 13 : 14;
4451 break;
4452 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4453 *tgtmode = ARM_CPU_MODE_SVC;
4454 *regno = sysm & 1 ? 13 : 14;
4455 break;
4456 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4457 *tgtmode = ARM_CPU_MODE_ABT;
4458 *regno = sysm & 1 ? 13 : 14;
4459 break;
4460 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4461 *tgtmode = ARM_CPU_MODE_UND;
4462 *regno = sysm & 1 ? 13 : 14;
4463 break;
4464 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4465 *tgtmode = ARM_CPU_MODE_MON;
4466 *regno = sysm & 1 ? 13 : 14;
4467 break;
4468 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4469 *tgtmode = ARM_CPU_MODE_HYP;
4470 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4471 *regno = sysm & 1 ? 13 : 17;
4472 break;
4473 default: /* unallocated */
4474 goto undef;
4475 }
4476 }
4477
4478 /* Catch the 'accessing inaccessible register' cases we can detect
4479 * at translate time.
4480 */
4481 switch (*tgtmode) {
4482 case ARM_CPU_MODE_MON:
4483 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4484 goto undef;
4485 }
4486 if (s->current_el == 1) {
4487 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4488 * then accesses to Mon registers trap to EL3
4489 */
4490 exc_target = 3;
4491 goto undef;
4492 }
4493 break;
4494 case ARM_CPU_MODE_HYP:
4495 /* Note that we can forbid accesses from EL2 here because they
4496 * must be from Hyp mode itself
4497 */
4498 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 3) {
4499 goto undef;
4500 }
4501 break;
4502 default:
4503 break;
4504 }
4505
4506 return true;
4507
4508undef:
4509 /* If we get here then some access check did not pass */
4510 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4511 return false;
4512}
4513
4514static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4515{
4516 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4517 int tgtmode = 0, regno = 0;
4518
4519 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4520 return;
4521 }
4522
4523 /* Sync state because msr_banked() can raise exceptions */
4524 gen_set_condexec(s);
4525 gen_set_pc_im(s, s->pc - 4);
4526 tcg_reg = load_reg(s, rn);
4527 tcg_tgtmode = tcg_const_i32(tgtmode);
4528 tcg_regno = tcg_const_i32(regno);
4529 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4530 tcg_temp_free_i32(tcg_tgtmode);
4531 tcg_temp_free_i32(tcg_regno);
4532 tcg_temp_free_i32(tcg_reg);
dcba3a8d 4533 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
4534}
4535
4536static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4537{
4538 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4539 int tgtmode = 0, regno = 0;
4540
4541 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4542 return;
4543 }
4544
4545 /* Sync state because mrs_banked() can raise exceptions */
4546 gen_set_condexec(s);
4547 gen_set_pc_im(s, s->pc - 4);
4548 tcg_reg = tcg_temp_new_i32();
4549 tcg_tgtmode = tcg_const_i32(tgtmode);
4550 tcg_regno = tcg_const_i32(regno);
4551 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4552 tcg_temp_free_i32(tcg_tgtmode);
4553 tcg_temp_free_i32(tcg_regno);
4554 store_reg(s, rn, tcg_reg);
dcba3a8d 4555 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
4556}
4557
fb0e8e79
PM
4558/* Store value to PC as for an exception return (ie don't
4559 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4560 * will do the masking based on the new value of the Thumb bit.
4561 */
4562static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 4563{
fb0e8e79
PM
4564 tcg_gen_mov_i32(cpu_R[15], pc);
4565 tcg_temp_free_i32(pc);
b5ff1b31
FB
4566}
4567
b0109805 4568/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 4569static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 4570{
fb0e8e79
PM
4571 store_pc_exc_ret(s, pc);
4572 /* The cpsr_write_eret helper will mask the low bits of PC
4573 * appropriately depending on the new Thumb bit, so it must
4574 * be called after storing the new PC.
4575 */
e69ad9df
AL
4576 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4577 gen_io_start();
4578 }
235ea1f5 4579 gen_helper_cpsr_write_eret(cpu_env, cpsr);
e69ad9df
AL
4580 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4581 gen_io_end();
4582 }
7d1b0095 4583 tcg_temp_free_i32(cpsr);
b29fd33d 4584 /* Must exit loop to check un-masked IRQs */
dcba3a8d 4585 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb 4586}
3b46e624 4587
fb0e8e79
PM
4588/* Generate an old-style exception return. Marks pc as dead. */
4589static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4590{
4591 gen_rfe(s, pc, load_cpu_field(spsr));
4592}
4593
c22edfeb
AB
4594/*
4595 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4596 * only call the helper when running single threaded TCG code to ensure
4597 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4598 * just skip this instruction. Currently the SEV/SEVL instructions
4599 * which are *one* of many ways to wake the CPU from WFE are not
4600 * implemented so we can't sleep like WFI does.
4601 */
9ee6e8bb
PB
4602static void gen_nop_hint(DisasContext *s, int val)
4603{
4604 switch (val) {
2399d4e7
EC
4605 /* When running in MTTCG we don't generate jumps to the yield and
4606 * WFE helpers as it won't affect the scheduling of other vCPUs.
4607 * If we wanted to more completely model WFE/SEV so we don't busy
4608 * spin unnecessarily we would need to do something more involved.
4609 */
c87e5a61 4610 case 1: /* yield */
2399d4e7 4611 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 4612 gen_set_pc_im(s, s->pc);
dcba3a8d 4613 s->base.is_jmp = DISAS_YIELD;
c22edfeb 4614 }
c87e5a61 4615 break;
9ee6e8bb 4616 case 3: /* wfi */
eaed129d 4617 gen_set_pc_im(s, s->pc);
dcba3a8d 4618 s->base.is_jmp = DISAS_WFI;
9ee6e8bb
PB
4619 break;
4620 case 2: /* wfe */
2399d4e7 4621 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 4622 gen_set_pc_im(s, s->pc);
dcba3a8d 4623 s->base.is_jmp = DISAS_WFE;
c22edfeb 4624 }
72c1d3af 4625 break;
9ee6e8bb 4626 case 4: /* sev */
12b10571
MR
4627 case 5: /* sevl */
4628 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
4629 default: /* nop */
4630 break;
4631 }
4632}
99c475ab 4633
ad69471c 4634#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 4635
39d5492a 4636static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
4637{
4638 switch (size) {
dd8fbd78
FN
4639 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4640 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4641 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 4642 default: abort();
9ee6e8bb 4643 }
9ee6e8bb
PB
4644}
4645
39d5492a 4646static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
4647{
4648 switch (size) {
dd8fbd78
FN
4649 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4650 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4651 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
4652 default: return;
4653 }
4654}
4655
4656/* 32-bit pairwise ops end up the same as the elementwise versions. */
4657#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4658#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4659#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4660#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4661
ad69471c
PB
4662#define GEN_NEON_INTEGER_OP_ENV(name) do { \
4663 switch ((size << 1) | u) { \
4664 case 0: \
dd8fbd78 4665 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4666 break; \
4667 case 1: \
dd8fbd78 4668 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4669 break; \
4670 case 2: \
dd8fbd78 4671 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4672 break; \
4673 case 3: \
dd8fbd78 4674 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4675 break; \
4676 case 4: \
dd8fbd78 4677 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4678 break; \
4679 case 5: \
dd8fbd78 4680 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4681 break; \
4682 default: return 1; \
4683 }} while (0)
9ee6e8bb
PB
4684
4685#define GEN_NEON_INTEGER_OP(name) do { \
4686 switch ((size << 1) | u) { \
ad69471c 4687 case 0: \
dd8fbd78 4688 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
4689 break; \
4690 case 1: \
dd8fbd78 4691 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
4692 break; \
4693 case 2: \
dd8fbd78 4694 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
4695 break; \
4696 case 3: \
dd8fbd78 4697 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
4698 break; \
4699 case 4: \
dd8fbd78 4700 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
4701 break; \
4702 case 5: \
dd8fbd78 4703 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 4704 break; \
9ee6e8bb
PB
4705 default: return 1; \
4706 }} while (0)
4707
39d5492a 4708static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 4709{
39d5492a 4710 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
4711 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4712 return tmp;
9ee6e8bb
PB
4713}
4714
39d5492a 4715static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 4716{
dd8fbd78 4717 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 4718 tcg_temp_free_i32(var);
9ee6e8bb
PB
4719}
4720
39d5492a 4721static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 4722{
39d5492a 4723 TCGv_i32 tmp;
9ee6e8bb 4724 if (size == 1) {
0fad6efc
PM
4725 tmp = neon_load_reg(reg & 7, reg >> 4);
4726 if (reg & 8) {
dd8fbd78 4727 gen_neon_dup_high16(tmp);
0fad6efc
PM
4728 } else {
4729 gen_neon_dup_low16(tmp);
dd8fbd78 4730 }
0fad6efc
PM
4731 } else {
4732 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 4733 }
dd8fbd78 4734 return tmp;
9ee6e8bb
PB
4735}
4736
02acedf9 4737static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 4738{
b13708bb
RH
4739 TCGv_ptr pd, pm;
4740
600b828c 4741 if (!q && size == 2) {
02acedf9
PM
4742 return 1;
4743 }
b13708bb
RH
4744 pd = vfp_reg_ptr(true, rd);
4745 pm = vfp_reg_ptr(true, rm);
02acedf9
PM
4746 if (q) {
4747 switch (size) {
4748 case 0:
b13708bb 4749 gen_helper_neon_qunzip8(pd, pm);
02acedf9
PM
4750 break;
4751 case 1:
b13708bb 4752 gen_helper_neon_qunzip16(pd, pm);
02acedf9
PM
4753 break;
4754 case 2:
b13708bb 4755 gen_helper_neon_qunzip32(pd, pm);
02acedf9
PM
4756 break;
4757 default:
4758 abort();
4759 }
4760 } else {
4761 switch (size) {
4762 case 0:
b13708bb 4763 gen_helper_neon_unzip8(pd, pm);
02acedf9
PM
4764 break;
4765 case 1:
b13708bb 4766 gen_helper_neon_unzip16(pd, pm);
02acedf9
PM
4767 break;
4768 default:
4769 abort();
4770 }
4771 }
b13708bb
RH
4772 tcg_temp_free_ptr(pd);
4773 tcg_temp_free_ptr(pm);
02acedf9 4774 return 0;
19457615
FN
4775}
4776
d68a6f3a 4777static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 4778{
b13708bb
RH
4779 TCGv_ptr pd, pm;
4780
600b828c 4781 if (!q && size == 2) {
d68a6f3a
PM
4782 return 1;
4783 }
b13708bb
RH
4784 pd = vfp_reg_ptr(true, rd);
4785 pm = vfp_reg_ptr(true, rm);
d68a6f3a
PM
4786 if (q) {
4787 switch (size) {
4788 case 0:
b13708bb 4789 gen_helper_neon_qzip8(pd, pm);
d68a6f3a
PM
4790 break;
4791 case 1:
b13708bb 4792 gen_helper_neon_qzip16(pd, pm);
d68a6f3a
PM
4793 break;
4794 case 2:
b13708bb 4795 gen_helper_neon_qzip32(pd, pm);
d68a6f3a
PM
4796 break;
4797 default:
4798 abort();
4799 }
4800 } else {
4801 switch (size) {
4802 case 0:
b13708bb 4803 gen_helper_neon_zip8(pd, pm);
d68a6f3a
PM
4804 break;
4805 case 1:
b13708bb 4806 gen_helper_neon_zip16(pd, pm);
d68a6f3a
PM
4807 break;
4808 default:
4809 abort();
4810 }
4811 }
b13708bb
RH
4812 tcg_temp_free_ptr(pd);
4813 tcg_temp_free_ptr(pm);
d68a6f3a 4814 return 0;
19457615
FN
4815}
4816
39d5492a 4817static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 4818{
39d5492a 4819 TCGv_i32 rd, tmp;
19457615 4820
7d1b0095
PM
4821 rd = tcg_temp_new_i32();
4822 tmp = tcg_temp_new_i32();
19457615
FN
4823
4824 tcg_gen_shli_i32(rd, t0, 8);
4825 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4826 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4827 tcg_gen_or_i32(rd, rd, tmp);
4828
4829 tcg_gen_shri_i32(t1, t1, 8);
4830 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4831 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4832 tcg_gen_or_i32(t1, t1, tmp);
4833 tcg_gen_mov_i32(t0, rd);
4834
7d1b0095
PM
4835 tcg_temp_free_i32(tmp);
4836 tcg_temp_free_i32(rd);
19457615
FN
4837}
4838
39d5492a 4839static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 4840{
39d5492a 4841 TCGv_i32 rd, tmp;
19457615 4842
7d1b0095
PM
4843 rd = tcg_temp_new_i32();
4844 tmp = tcg_temp_new_i32();
19457615
FN
4845
4846 tcg_gen_shli_i32(rd, t0, 16);
4847 tcg_gen_andi_i32(tmp, t1, 0xffff);
4848 tcg_gen_or_i32(rd, rd, tmp);
4849 tcg_gen_shri_i32(t1, t1, 16);
4850 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4851 tcg_gen_or_i32(t1, t1, tmp);
4852 tcg_gen_mov_i32(t0, rd);
4853
7d1b0095
PM
4854 tcg_temp_free_i32(tmp);
4855 tcg_temp_free_i32(rd);
19457615
FN
4856}
4857
4858
9ee6e8bb
PB
4859static struct {
4860 int nregs;
4861 int interleave;
4862 int spacing;
4863} neon_ls_element_type[11] = {
4864 {4, 4, 1},
4865 {4, 4, 2},
4866 {4, 1, 1},
4867 {4, 2, 1},
4868 {3, 3, 1},
4869 {3, 3, 2},
4870 {3, 1, 1},
4871 {1, 1, 1},
4872 {2, 2, 1},
4873 {2, 2, 2},
4874 {2, 1, 1}
4875};
4876
4877/* Translate a NEON load/store element instruction. Return nonzero if the
4878 instruction is invalid. */
7dcc1f89 4879static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4880{
4881 int rd, rn, rm;
4882 int op;
4883 int nregs;
4884 int interleave;
84496233 4885 int spacing;
9ee6e8bb
PB
4886 int stride;
4887 int size;
4888 int reg;
4889 int pass;
4890 int load;
4891 int shift;
9ee6e8bb 4892 int n;
39d5492a
PM
4893 TCGv_i32 addr;
4894 TCGv_i32 tmp;
4895 TCGv_i32 tmp2;
84496233 4896 TCGv_i64 tmp64;
9ee6e8bb 4897
2c7ffc41
PM
4898 /* FIXME: this access check should not take precedence over UNDEF
4899 * for invalid encodings; we will generate incorrect syndrome information
4900 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4901 */
9dbbc748 4902 if (s->fp_excp_el) {
2c7ffc41 4903 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 4904 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4905 return 0;
4906 }
4907
5df8bac1 4908 if (!s->vfp_enabled)
9ee6e8bb
PB
4909 return 1;
4910 VFP_DREG_D(rd, insn);
4911 rn = (insn >> 16) & 0xf;
4912 rm = insn & 0xf;
4913 load = (insn & (1 << 21)) != 0;
4914 if ((insn & (1 << 23)) == 0) {
4915 /* Load store all elements. */
4916 op = (insn >> 8) & 0xf;
4917 size = (insn >> 6) & 3;
84496233 4918 if (op > 10)
9ee6e8bb 4919 return 1;
f2dd89d0
PM
4920 /* Catch UNDEF cases for bad values of align field */
4921 switch (op & 0xc) {
4922 case 4:
4923 if (((insn >> 5) & 1) == 1) {
4924 return 1;
4925 }
4926 break;
4927 case 8:
4928 if (((insn >> 4) & 3) == 3) {
4929 return 1;
4930 }
4931 break;
4932 default:
4933 break;
4934 }
9ee6e8bb
PB
4935 nregs = neon_ls_element_type[op].nregs;
4936 interleave = neon_ls_element_type[op].interleave;
84496233
JR
4937 spacing = neon_ls_element_type[op].spacing;
4938 if (size == 3 && (interleave | spacing) != 1)
4939 return 1;
e318a60b 4940 addr = tcg_temp_new_i32();
dcc65026 4941 load_reg_var(s, addr, rn);
9ee6e8bb
PB
4942 stride = (1 << size) * interleave;
4943 for (reg = 0; reg < nregs; reg++) {
4944 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
dcc65026
AJ
4945 load_reg_var(s, addr, rn);
4946 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
9ee6e8bb 4947 } else if (interleave == 2 && nregs == 4 && reg == 2) {
dcc65026
AJ
4948 load_reg_var(s, addr, rn);
4949 tcg_gen_addi_i32(addr, addr, 1 << size);
9ee6e8bb 4950 }
84496233 4951 if (size == 3) {
8ed1237d 4952 tmp64 = tcg_temp_new_i64();
84496233 4953 if (load) {
12dcc321 4954 gen_aa32_ld64(s, tmp64, addr, get_mem_index(s));
84496233 4955 neon_store_reg64(tmp64, rd);
84496233 4956 } else {
84496233 4957 neon_load_reg64(tmp64, rd);
12dcc321 4958 gen_aa32_st64(s, tmp64, addr, get_mem_index(s));
84496233 4959 }
8ed1237d 4960 tcg_temp_free_i64(tmp64);
84496233
JR
4961 tcg_gen_addi_i32(addr, addr, stride);
4962 } else {
4963 for (pass = 0; pass < 2; pass++) {
4964 if (size == 2) {
4965 if (load) {
58ab8e96 4966 tmp = tcg_temp_new_i32();
12dcc321 4967 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
84496233
JR
4968 neon_store_reg(rd, pass, tmp);
4969 } else {
4970 tmp = neon_load_reg(rd, pass);
12dcc321 4971 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
58ab8e96 4972 tcg_temp_free_i32(tmp);
84496233 4973 }
1b2b1e54 4974 tcg_gen_addi_i32(addr, addr, stride);
84496233
JR
4975 } else if (size == 1) {
4976 if (load) {
58ab8e96 4977 tmp = tcg_temp_new_i32();
12dcc321 4978 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
84496233 4979 tcg_gen_addi_i32(addr, addr, stride);
58ab8e96 4980 tmp2 = tcg_temp_new_i32();
12dcc321 4981 gen_aa32_ld16u(s, tmp2, addr, get_mem_index(s));
84496233 4982 tcg_gen_addi_i32(addr, addr, stride);
41ba8341
PB
4983 tcg_gen_shli_i32(tmp2, tmp2, 16);
4984 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 4985 tcg_temp_free_i32(tmp2);
84496233
JR
4986 neon_store_reg(rd, pass, tmp);
4987 } else {
4988 tmp = neon_load_reg(rd, pass);
7d1b0095 4989 tmp2 = tcg_temp_new_i32();
84496233 4990 tcg_gen_shri_i32(tmp2, tmp, 16);
12dcc321 4991 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
58ab8e96 4992 tcg_temp_free_i32(tmp);
84496233 4993 tcg_gen_addi_i32(addr, addr, stride);
12dcc321 4994 gen_aa32_st16(s, tmp2, addr, get_mem_index(s));
58ab8e96 4995 tcg_temp_free_i32(tmp2);
1b2b1e54 4996 tcg_gen_addi_i32(addr, addr, stride);
9ee6e8bb 4997 }
84496233
JR
4998 } else /* size == 0 */ {
4999 if (load) {
f764718d 5000 tmp2 = NULL;
84496233 5001 for (n = 0; n < 4; n++) {
58ab8e96 5002 tmp = tcg_temp_new_i32();
12dcc321 5003 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
84496233
JR
5004 tcg_gen_addi_i32(addr, addr, stride);
5005 if (n == 0) {
5006 tmp2 = tmp;
5007 } else {
41ba8341
PB
5008 tcg_gen_shli_i32(tmp, tmp, n * 8);
5009 tcg_gen_or_i32(tmp2, tmp2, tmp);
7d1b0095 5010 tcg_temp_free_i32(tmp);
84496233 5011 }
9ee6e8bb 5012 }
84496233
JR
5013 neon_store_reg(rd, pass, tmp2);
5014 } else {
5015 tmp2 = neon_load_reg(rd, pass);
5016 for (n = 0; n < 4; n++) {
7d1b0095 5017 tmp = tcg_temp_new_i32();
84496233
JR
5018 if (n == 0) {
5019 tcg_gen_mov_i32(tmp, tmp2);
5020 } else {
5021 tcg_gen_shri_i32(tmp, tmp2, n * 8);
5022 }
12dcc321 5023 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
58ab8e96 5024 tcg_temp_free_i32(tmp);
84496233
JR
5025 tcg_gen_addi_i32(addr, addr, stride);
5026 }
7d1b0095 5027 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
5028 }
5029 }
5030 }
5031 }
84496233 5032 rd += spacing;
9ee6e8bb 5033 }
e318a60b 5034 tcg_temp_free_i32(addr);
9ee6e8bb
PB
5035 stride = nregs * 8;
5036 } else {
5037 size = (insn >> 10) & 3;
5038 if (size == 3) {
5039 /* Load single element to all lanes. */
8e18cde3
PM
5040 int a = (insn >> 4) & 1;
5041 if (!load) {
9ee6e8bb 5042 return 1;
8e18cde3 5043 }
9ee6e8bb
PB
5044 size = (insn >> 6) & 3;
5045 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
5046
5047 if (size == 3) {
5048 if (nregs != 4 || a == 0) {
9ee6e8bb 5049 return 1;
99c475ab 5050 }
8e18cde3
PM
5051 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
5052 size = 2;
5053 }
5054 if (nregs == 1 && a == 1 && size == 0) {
5055 return 1;
5056 }
5057 if (nregs == 3 && a == 1) {
5058 return 1;
5059 }
e318a60b 5060 addr = tcg_temp_new_i32();
8e18cde3
PM
5061 load_reg_var(s, addr, rn);
5062 if (nregs == 1) {
5063 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
5064 tmp = gen_load_and_replicate(s, addr, size);
5065 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
5066 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
5067 if (insn & (1 << 5)) {
5068 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
5069 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
5070 }
5071 tcg_temp_free_i32(tmp);
5072 } else {
5073 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
5074 stride = (insn & (1 << 5)) ? 2 : 1;
5075 for (reg = 0; reg < nregs; reg++) {
5076 tmp = gen_load_and_replicate(s, addr, size);
5077 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
5078 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
5079 tcg_temp_free_i32(tmp);
5080 tcg_gen_addi_i32(addr, addr, 1 << size);
5081 rd += stride;
5082 }
9ee6e8bb 5083 }
e318a60b 5084 tcg_temp_free_i32(addr);
9ee6e8bb
PB
5085 stride = (1 << size) * nregs;
5086 } else {
5087 /* Single element. */
93262b16 5088 int idx = (insn >> 4) & 0xf;
9ee6e8bb
PB
5089 pass = (insn >> 7) & 1;
5090 switch (size) {
5091 case 0:
5092 shift = ((insn >> 5) & 3) * 8;
9ee6e8bb
PB
5093 stride = 1;
5094 break;
5095 case 1:
5096 shift = ((insn >> 6) & 1) * 16;
9ee6e8bb
PB
5097 stride = (insn & (1 << 5)) ? 2 : 1;
5098 break;
5099 case 2:
5100 shift = 0;
9ee6e8bb
PB
5101 stride = (insn & (1 << 6)) ? 2 : 1;
5102 break;
5103 default:
5104 abort();
5105 }
5106 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
5107 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
5108 switch (nregs) {
5109 case 1:
5110 if (((idx & (1 << size)) != 0) ||
5111 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
5112 return 1;
5113 }
5114 break;
5115 case 3:
5116 if ((idx & 1) != 0) {
5117 return 1;
5118 }
5119 /* fall through */
5120 case 2:
5121 if (size == 2 && (idx & 2) != 0) {
5122 return 1;
5123 }
5124 break;
5125 case 4:
5126 if ((size == 2) && ((idx & 3) == 3)) {
5127 return 1;
5128 }
5129 break;
5130 default:
5131 abort();
5132 }
5133 if ((rd + stride * (nregs - 1)) > 31) {
5134 /* Attempts to write off the end of the register file
5135 * are UNPREDICTABLE; we choose to UNDEF because otherwise
5136 * the neon_load_reg() would write off the end of the array.
5137 */
5138 return 1;
5139 }
e318a60b 5140 addr = tcg_temp_new_i32();
dcc65026 5141 load_reg_var(s, addr, rn);
9ee6e8bb
PB
5142 for (reg = 0; reg < nregs; reg++) {
5143 if (load) {
58ab8e96 5144 tmp = tcg_temp_new_i32();
9ee6e8bb
PB
5145 switch (size) {
5146 case 0:
12dcc321 5147 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5148 break;
5149 case 1:
12dcc321 5150 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5151 break;
5152 case 2:
12dcc321 5153 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 5154 break;
a50f5b91
PB
5155 default: /* Avoid compiler warnings. */
5156 abort();
9ee6e8bb
PB
5157 }
5158 if (size != 2) {
8f8e3aa4 5159 tmp2 = neon_load_reg(rd, pass);
d593c48e
AJ
5160 tcg_gen_deposit_i32(tmp, tmp2, tmp,
5161 shift, size ? 16 : 8);
7d1b0095 5162 tcg_temp_free_i32(tmp2);
9ee6e8bb 5163 }
8f8e3aa4 5164 neon_store_reg(rd, pass, tmp);
9ee6e8bb 5165 } else { /* Store */
8f8e3aa4
PB
5166 tmp = neon_load_reg(rd, pass);
5167 if (shift)
5168 tcg_gen_shri_i32(tmp, tmp, shift);
9ee6e8bb
PB
5169 switch (size) {
5170 case 0:
12dcc321 5171 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5172 break;
5173 case 1:
12dcc321 5174 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5175 break;
5176 case 2:
12dcc321 5177 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9ee6e8bb 5178 break;
99c475ab 5179 }
58ab8e96 5180 tcg_temp_free_i32(tmp);
99c475ab 5181 }
9ee6e8bb 5182 rd += stride;
1b2b1e54 5183 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 5184 }
e318a60b 5185 tcg_temp_free_i32(addr);
9ee6e8bb 5186 stride = nregs * (1 << size);
99c475ab 5187 }
9ee6e8bb
PB
5188 }
5189 if (rm != 15) {
39d5492a 5190 TCGv_i32 base;
b26eefb6
PB
5191
5192 base = load_reg(s, rn);
9ee6e8bb 5193 if (rm == 13) {
b26eefb6 5194 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 5195 } else {
39d5492a 5196 TCGv_i32 index;
b26eefb6
PB
5197 index = load_reg(s, rm);
5198 tcg_gen_add_i32(base, base, index);
7d1b0095 5199 tcg_temp_free_i32(index);
9ee6e8bb 5200 }
b26eefb6 5201 store_reg(s, rn, base);
9ee6e8bb
PB
5202 }
5203 return 0;
5204}
3b46e624 5205
8f8e3aa4 5206/* Bitwise select. dest = c ? t : f. Clobbers T and F. */
39d5492a 5207static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
8f8e3aa4
PB
5208{
5209 tcg_gen_and_i32(t, t, c);
f669df27 5210 tcg_gen_andc_i32(f, f, c);
8f8e3aa4
PB
5211 tcg_gen_or_i32(dest, t, f);
5212}
5213
39d5492a 5214static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5215{
5216 switch (size) {
5217 case 0: gen_helper_neon_narrow_u8(dest, src); break;
5218 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 5219 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
5220 default: abort();
5221 }
5222}
5223
39d5492a 5224static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5225{
5226 switch (size) {
02da0b2d
PM
5227 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
5228 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
5229 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
5230 default: abort();
5231 }
5232}
5233
39d5492a 5234static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5235{
5236 switch (size) {
02da0b2d
PM
5237 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5238 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5239 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
5240 default: abort();
5241 }
5242}
5243
39d5492a 5244static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
5245{
5246 switch (size) {
02da0b2d
PM
5247 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5248 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5249 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
5250 default: abort();
5251 }
5252}
5253
39d5492a 5254static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
5255 int q, int u)
5256{
5257 if (q) {
5258 if (u) {
5259 switch (size) {
5260 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5261 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5262 default: abort();
5263 }
5264 } else {
5265 switch (size) {
5266 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5267 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5268 default: abort();
5269 }
5270 }
5271 } else {
5272 if (u) {
5273 switch (size) {
b408a9b0
CL
5274 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5275 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
5276 default: abort();
5277 }
5278 } else {
5279 switch (size) {
5280 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5281 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5282 default: abort();
5283 }
5284 }
5285 }
5286}
5287
39d5492a 5288static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
5289{
5290 if (u) {
5291 switch (size) {
5292 case 0: gen_helper_neon_widen_u8(dest, src); break;
5293 case 1: gen_helper_neon_widen_u16(dest, src); break;
5294 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5295 default: abort();
5296 }
5297 } else {
5298 switch (size) {
5299 case 0: gen_helper_neon_widen_s8(dest, src); break;
5300 case 1: gen_helper_neon_widen_s16(dest, src); break;
5301 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5302 default: abort();
5303 }
5304 }
7d1b0095 5305 tcg_temp_free_i32(src);
ad69471c
PB
5306}
5307
5308static inline void gen_neon_addl(int size)
5309{
5310 switch (size) {
5311 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5312 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5313 case 2: tcg_gen_add_i64(CPU_V001); break;
5314 default: abort();
5315 }
5316}
5317
5318static inline void gen_neon_subl(int size)
5319{
5320 switch (size) {
5321 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5322 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5323 case 2: tcg_gen_sub_i64(CPU_V001); break;
5324 default: abort();
5325 }
5326}
5327
a7812ae4 5328static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
5329{
5330 switch (size) {
5331 case 0: gen_helper_neon_negl_u16(var, var); break;
5332 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
5333 case 2:
5334 tcg_gen_neg_i64(var, var);
5335 break;
ad69471c
PB
5336 default: abort();
5337 }
5338}
5339
a7812ae4 5340static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
5341{
5342 switch (size) {
02da0b2d
PM
5343 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5344 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
5345 default: abort();
5346 }
5347}
5348
39d5492a
PM
5349static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5350 int size, int u)
ad69471c 5351{
a7812ae4 5352 TCGv_i64 tmp;
ad69471c
PB
5353
5354 switch ((size << 1) | u) {
5355 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5356 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5357 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5358 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5359 case 4:
5360 tmp = gen_muls_i64_i32(a, b);
5361 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5362 tcg_temp_free_i64(tmp);
ad69471c
PB
5363 break;
5364 case 5:
5365 tmp = gen_mulu_i64_i32(a, b);
5366 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5367 tcg_temp_free_i64(tmp);
ad69471c
PB
5368 break;
5369 default: abort();
5370 }
c6067f04
CL
5371
5372 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5373 Don't forget to clean them now. */
5374 if (size < 2) {
7d1b0095
PM
5375 tcg_temp_free_i32(a);
5376 tcg_temp_free_i32(b);
c6067f04 5377 }
ad69471c
PB
5378}
5379
39d5492a
PM
5380static void gen_neon_narrow_op(int op, int u, int size,
5381 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
5382{
5383 if (op) {
5384 if (u) {
5385 gen_neon_unarrow_sats(size, dest, src);
5386 } else {
5387 gen_neon_narrow(size, dest, src);
5388 }
5389 } else {
5390 if (u) {
5391 gen_neon_narrow_satu(size, dest, src);
5392 } else {
5393 gen_neon_narrow_sats(size, dest, src);
5394 }
5395 }
5396}
5397
62698be3
PM
5398/* Symbolic constants for op fields for Neon 3-register same-length.
5399 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5400 * table A7-9.
5401 */
5402#define NEON_3R_VHADD 0
5403#define NEON_3R_VQADD 1
5404#define NEON_3R_VRHADD 2
5405#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5406#define NEON_3R_VHSUB 4
5407#define NEON_3R_VQSUB 5
5408#define NEON_3R_VCGT 6
5409#define NEON_3R_VCGE 7
5410#define NEON_3R_VSHL 8
5411#define NEON_3R_VQSHL 9
5412#define NEON_3R_VRSHL 10
5413#define NEON_3R_VQRSHL 11
5414#define NEON_3R_VMAX 12
5415#define NEON_3R_VMIN 13
5416#define NEON_3R_VABD 14
5417#define NEON_3R_VABA 15
5418#define NEON_3R_VADD_VSUB 16
5419#define NEON_3R_VTST_VCEQ 17
5420#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
5421#define NEON_3R_VMUL 19
5422#define NEON_3R_VPMAX 20
5423#define NEON_3R_VPMIN 21
5424#define NEON_3R_VQDMULH_VQRDMULH 22
36a71934 5425#define NEON_3R_VPADD_VQRDMLAH 23
f1ecb913 5426#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
36a71934 5427#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
62698be3
PM
5428#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5429#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5430#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5431#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5432#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 5433#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
5434
5435static const uint8_t neon_3r_sizes[] = {
5436 [NEON_3R_VHADD] = 0x7,
5437 [NEON_3R_VQADD] = 0xf,
5438 [NEON_3R_VRHADD] = 0x7,
5439 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5440 [NEON_3R_VHSUB] = 0x7,
5441 [NEON_3R_VQSUB] = 0xf,
5442 [NEON_3R_VCGT] = 0x7,
5443 [NEON_3R_VCGE] = 0x7,
5444 [NEON_3R_VSHL] = 0xf,
5445 [NEON_3R_VQSHL] = 0xf,
5446 [NEON_3R_VRSHL] = 0xf,
5447 [NEON_3R_VQRSHL] = 0xf,
5448 [NEON_3R_VMAX] = 0x7,
5449 [NEON_3R_VMIN] = 0x7,
5450 [NEON_3R_VABD] = 0x7,
5451 [NEON_3R_VABA] = 0x7,
5452 [NEON_3R_VADD_VSUB] = 0xf,
5453 [NEON_3R_VTST_VCEQ] = 0x7,
5454 [NEON_3R_VML] = 0x7,
5455 [NEON_3R_VMUL] = 0x7,
5456 [NEON_3R_VPMAX] = 0x7,
5457 [NEON_3R_VPMIN] = 0x7,
5458 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
36a71934 5459 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
f1ecb913 5460 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
36a71934 5461 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
62698be3
PM
5462 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5463 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5464 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5465 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5466 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 5467 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
5468};
5469
600b828c
PM
5470/* Symbolic constants for op fields for Neon 2-register miscellaneous.
5471 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5472 * table A7-13.
5473 */
5474#define NEON_2RM_VREV64 0
5475#define NEON_2RM_VREV32 1
5476#define NEON_2RM_VREV16 2
5477#define NEON_2RM_VPADDL 4
5478#define NEON_2RM_VPADDL_U 5
9d935509
AB
5479#define NEON_2RM_AESE 6 /* Includes AESD */
5480#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
5481#define NEON_2RM_VCLS 8
5482#define NEON_2RM_VCLZ 9
5483#define NEON_2RM_VCNT 10
5484#define NEON_2RM_VMVN 11
5485#define NEON_2RM_VPADAL 12
5486#define NEON_2RM_VPADAL_U 13
5487#define NEON_2RM_VQABS 14
5488#define NEON_2RM_VQNEG 15
5489#define NEON_2RM_VCGT0 16
5490#define NEON_2RM_VCGE0 17
5491#define NEON_2RM_VCEQ0 18
5492#define NEON_2RM_VCLE0 19
5493#define NEON_2RM_VCLT0 20
f1ecb913 5494#define NEON_2RM_SHA1H 21
600b828c
PM
5495#define NEON_2RM_VABS 22
5496#define NEON_2RM_VNEG 23
5497#define NEON_2RM_VCGT0_F 24
5498#define NEON_2RM_VCGE0_F 25
5499#define NEON_2RM_VCEQ0_F 26
5500#define NEON_2RM_VCLE0_F 27
5501#define NEON_2RM_VCLT0_F 28
5502#define NEON_2RM_VABS_F 30
5503#define NEON_2RM_VNEG_F 31
5504#define NEON_2RM_VSWP 32
5505#define NEON_2RM_VTRN 33
5506#define NEON_2RM_VUZP 34
5507#define NEON_2RM_VZIP 35
5508#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5509#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5510#define NEON_2RM_VSHLL 38
f1ecb913 5511#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 5512#define NEON_2RM_VRINTN 40
2ce70625 5513#define NEON_2RM_VRINTX 41
34f7b0a2
WN
5514#define NEON_2RM_VRINTA 42
5515#define NEON_2RM_VRINTZ 43
600b828c 5516#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 5517#define NEON_2RM_VRINTM 45
600b828c 5518#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 5519#define NEON_2RM_VRINTP 47
901ad525
WN
5520#define NEON_2RM_VCVTAU 48
5521#define NEON_2RM_VCVTAS 49
5522#define NEON_2RM_VCVTNU 50
5523#define NEON_2RM_VCVTNS 51
5524#define NEON_2RM_VCVTPU 52
5525#define NEON_2RM_VCVTPS 53
5526#define NEON_2RM_VCVTMU 54
5527#define NEON_2RM_VCVTMS 55
600b828c
PM
5528#define NEON_2RM_VRECPE 56
5529#define NEON_2RM_VRSQRTE 57
5530#define NEON_2RM_VRECPE_F 58
5531#define NEON_2RM_VRSQRTE_F 59
5532#define NEON_2RM_VCVT_FS 60
5533#define NEON_2RM_VCVT_FU 61
5534#define NEON_2RM_VCVT_SF 62
5535#define NEON_2RM_VCVT_UF 63
5536
5537static int neon_2rm_is_float_op(int op)
5538{
5539 /* Return true if this neon 2reg-misc op is float-to-float */
5540 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
34f7b0a2 5541 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
901ad525
WN
5542 op == NEON_2RM_VRINTM ||
5543 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
34f7b0a2 5544 op >= NEON_2RM_VRECPE_F);
600b828c
PM
5545}
5546
fe8fcf3d
PM
5547static bool neon_2rm_is_v8_op(int op)
5548{
5549 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5550 switch (op) {
5551 case NEON_2RM_VRINTN:
5552 case NEON_2RM_VRINTA:
5553 case NEON_2RM_VRINTM:
5554 case NEON_2RM_VRINTP:
5555 case NEON_2RM_VRINTZ:
5556 case NEON_2RM_VRINTX:
5557 case NEON_2RM_VCVTAU:
5558 case NEON_2RM_VCVTAS:
5559 case NEON_2RM_VCVTNU:
5560 case NEON_2RM_VCVTNS:
5561 case NEON_2RM_VCVTPU:
5562 case NEON_2RM_VCVTPS:
5563 case NEON_2RM_VCVTMU:
5564 case NEON_2RM_VCVTMS:
5565 return true;
5566 default:
5567 return false;
5568 }
5569}
5570
600b828c
PM
5571/* Each entry in this array has bit n set if the insn allows
5572 * size value n (otherwise it will UNDEF). Since unallocated
5573 * op values will have no bits set they always UNDEF.
5574 */
5575static const uint8_t neon_2rm_sizes[] = {
5576 [NEON_2RM_VREV64] = 0x7,
5577 [NEON_2RM_VREV32] = 0x3,
5578 [NEON_2RM_VREV16] = 0x1,
5579 [NEON_2RM_VPADDL] = 0x7,
5580 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
5581 [NEON_2RM_AESE] = 0x1,
5582 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
5583 [NEON_2RM_VCLS] = 0x7,
5584 [NEON_2RM_VCLZ] = 0x7,
5585 [NEON_2RM_VCNT] = 0x1,
5586 [NEON_2RM_VMVN] = 0x1,
5587 [NEON_2RM_VPADAL] = 0x7,
5588 [NEON_2RM_VPADAL_U] = 0x7,
5589 [NEON_2RM_VQABS] = 0x7,
5590 [NEON_2RM_VQNEG] = 0x7,
5591 [NEON_2RM_VCGT0] = 0x7,
5592 [NEON_2RM_VCGE0] = 0x7,
5593 [NEON_2RM_VCEQ0] = 0x7,
5594 [NEON_2RM_VCLE0] = 0x7,
5595 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 5596 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
5597 [NEON_2RM_VABS] = 0x7,
5598 [NEON_2RM_VNEG] = 0x7,
5599 [NEON_2RM_VCGT0_F] = 0x4,
5600 [NEON_2RM_VCGE0_F] = 0x4,
5601 [NEON_2RM_VCEQ0_F] = 0x4,
5602 [NEON_2RM_VCLE0_F] = 0x4,
5603 [NEON_2RM_VCLT0_F] = 0x4,
5604 [NEON_2RM_VABS_F] = 0x4,
5605 [NEON_2RM_VNEG_F] = 0x4,
5606 [NEON_2RM_VSWP] = 0x1,
5607 [NEON_2RM_VTRN] = 0x7,
5608 [NEON_2RM_VUZP] = 0x7,
5609 [NEON_2RM_VZIP] = 0x7,
5610 [NEON_2RM_VMOVN] = 0x7,
5611 [NEON_2RM_VQMOVN] = 0x7,
5612 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 5613 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 5614 [NEON_2RM_VRINTN] = 0x4,
2ce70625 5615 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
5616 [NEON_2RM_VRINTA] = 0x4,
5617 [NEON_2RM_VRINTZ] = 0x4,
600b828c 5618 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 5619 [NEON_2RM_VRINTM] = 0x4,
600b828c 5620 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 5621 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
5622 [NEON_2RM_VCVTAU] = 0x4,
5623 [NEON_2RM_VCVTAS] = 0x4,
5624 [NEON_2RM_VCVTNU] = 0x4,
5625 [NEON_2RM_VCVTNS] = 0x4,
5626 [NEON_2RM_VCVTPU] = 0x4,
5627 [NEON_2RM_VCVTPS] = 0x4,
5628 [NEON_2RM_VCVTMU] = 0x4,
5629 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
5630 [NEON_2RM_VRECPE] = 0x4,
5631 [NEON_2RM_VRSQRTE] = 0x4,
5632 [NEON_2RM_VRECPE_F] = 0x4,
5633 [NEON_2RM_VRSQRTE_F] = 0x4,
5634 [NEON_2RM_VCVT_FS] = 0x4,
5635 [NEON_2RM_VCVT_FU] = 0x4,
5636 [NEON_2RM_VCVT_SF] = 0x4,
5637 [NEON_2RM_VCVT_UF] = 0x4,
5638};
5639
36a71934
RH
5640
5641/* Expand v8.1 simd helper. */
5642static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5643 int q, int rd, int rn, int rm)
5644{
5645 if (arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
5646 int opr_sz = (1 + q) * 8;
5647 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5648 vfp_reg_offset(1, rn),
5649 vfp_reg_offset(1, rm), cpu_env,
5650 opr_sz, opr_sz, 0, fn);
5651 return 0;
5652 }
5653 return 1;
5654}
5655
9ee6e8bb
PB
5656/* Translate a NEON data processing instruction. Return nonzero if the
5657 instruction is invalid.
ad69471c
PB
5658 We process data in a mixture of 32-bit and 64-bit chunks.
5659 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 5660
7dcc1f89 5661static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
5662{
5663 int op;
5664 int q;
5665 int rd, rn, rm;
5666 int size;
5667 int shift;
5668 int pass;
5669 int count;
5670 int pairwise;
5671 int u;
ca9a32e4 5672 uint32_t imm, mask;
39d5492a 5673 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
1a66ac61 5674 TCGv_ptr ptr1, ptr2, ptr3;
a7812ae4 5675 TCGv_i64 tmp64;
9ee6e8bb 5676
2c7ffc41
PM
5677 /* FIXME: this access check should not take precedence over UNDEF
5678 * for invalid encodings; we will generate incorrect syndrome information
5679 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5680 */
9dbbc748 5681 if (s->fp_excp_el) {
2c7ffc41 5682 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 5683 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
5684 return 0;
5685 }
5686
5df8bac1 5687 if (!s->vfp_enabled)
9ee6e8bb
PB
5688 return 1;
5689 q = (insn & (1 << 6)) != 0;
5690 u = (insn >> 24) & 1;
5691 VFP_DREG_D(rd, insn);
5692 VFP_DREG_N(rn, insn);
5693 VFP_DREG_M(rm, insn);
5694 size = (insn >> 20) & 3;
5695 if ((insn & (1 << 23)) == 0) {
5696 /* Three register same length. */
5697 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
5698 /* Catch invalid op and bad size combinations: UNDEF */
5699 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5700 return 1;
5701 }
25f84f79
PM
5702 /* All insns of this form UNDEF for either this condition or the
5703 * superset of cases "Q==1"; we catch the latter later.
5704 */
5705 if (q && ((rd | rn | rm) & 1)) {
5706 return 1;
5707 }
36a71934
RH
5708 switch (op) {
5709 case NEON_3R_SHA:
5710 /* The SHA-1/SHA-256 3-register instructions require special
5711 * treatment here, as their size field is overloaded as an
5712 * op type selector, and they all consume their input in a
5713 * single pass.
5714 */
f1ecb913
AB
5715 if (!q) {
5716 return 1;
5717 }
5718 if (!u) { /* SHA-1 */
d614a513 5719 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
5720 return 1;
5721 }
1a66ac61
RH
5722 ptr1 = vfp_reg_ptr(true, rd);
5723 ptr2 = vfp_reg_ptr(true, rn);
5724 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913 5725 tmp4 = tcg_const_i32(size);
1a66ac61 5726 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
f1ecb913
AB
5727 tcg_temp_free_i32(tmp4);
5728 } else { /* SHA-256 */
d614a513 5729 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
f1ecb913
AB
5730 return 1;
5731 }
1a66ac61
RH
5732 ptr1 = vfp_reg_ptr(true, rd);
5733 ptr2 = vfp_reg_ptr(true, rn);
5734 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913
AB
5735 switch (size) {
5736 case 0:
1a66ac61 5737 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
f1ecb913
AB
5738 break;
5739 case 1:
1a66ac61 5740 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
f1ecb913
AB
5741 break;
5742 case 2:
1a66ac61 5743 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
f1ecb913
AB
5744 break;
5745 }
5746 }
1a66ac61
RH
5747 tcg_temp_free_ptr(ptr1);
5748 tcg_temp_free_ptr(ptr2);
5749 tcg_temp_free_ptr(ptr3);
f1ecb913 5750 return 0;
36a71934
RH
5751
5752 case NEON_3R_VPADD_VQRDMLAH:
5753 if (!u) {
5754 break; /* VPADD */
5755 }
5756 /* VQRDMLAH */
5757 switch (size) {
5758 case 1:
5759 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
5760 q, rd, rn, rm);
5761 case 2:
5762 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
5763 q, rd, rn, rm);
5764 }
5765 return 1;
5766
5767 case NEON_3R_VFM_VQRDMLSH:
5768 if (!u) {
5769 /* VFM, VFMS */
5770 if (size == 1) {
5771 return 1;
5772 }
5773 break;
5774 }
5775 /* VQRDMLSH */
5776 switch (size) {
5777 case 1:
5778 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
5779 q, rd, rn, rm);
5780 case 2:
5781 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
5782 q, rd, rn, rm);
5783 }
5784 return 1;
f1ecb913 5785 }
62698be3
PM
5786 if (size == 3 && op != NEON_3R_LOGIC) {
5787 /* 64-bit element instructions. */
9ee6e8bb 5788 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
5789 neon_load_reg64(cpu_V0, rn + pass);
5790 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 5791 switch (op) {
62698be3 5792 case NEON_3R_VQADD:
9ee6e8bb 5793 if (u) {
02da0b2d
PM
5794 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5795 cpu_V0, cpu_V1);
2c0262af 5796 } else {
02da0b2d
PM
5797 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5798 cpu_V0, cpu_V1);
2c0262af 5799 }
9ee6e8bb 5800 break;
62698be3 5801 case NEON_3R_VQSUB:
9ee6e8bb 5802 if (u) {
02da0b2d
PM
5803 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5804 cpu_V0, cpu_V1);
ad69471c 5805 } else {
02da0b2d
PM
5806 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5807 cpu_V0, cpu_V1);
ad69471c
PB
5808 }
5809 break;
62698be3 5810 case NEON_3R_VSHL:
ad69471c
PB
5811 if (u) {
5812 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5813 } else {
5814 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5815 }
5816 break;
62698be3 5817 case NEON_3R_VQSHL:
ad69471c 5818 if (u) {
02da0b2d
PM
5819 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5820 cpu_V1, cpu_V0);
ad69471c 5821 } else {
02da0b2d
PM
5822 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5823 cpu_V1, cpu_V0);
ad69471c
PB
5824 }
5825 break;
62698be3 5826 case NEON_3R_VRSHL:
ad69471c
PB
5827 if (u) {
5828 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 5829 } else {
ad69471c
PB
5830 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5831 }
5832 break;
62698be3 5833 case NEON_3R_VQRSHL:
ad69471c 5834 if (u) {
02da0b2d
PM
5835 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5836 cpu_V1, cpu_V0);
ad69471c 5837 } else {
02da0b2d
PM
5838 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5839 cpu_V1, cpu_V0);
1e8d4eec 5840 }
9ee6e8bb 5841 break;
62698be3 5842 case NEON_3R_VADD_VSUB:
9ee6e8bb 5843 if (u) {
ad69471c 5844 tcg_gen_sub_i64(CPU_V001);
9ee6e8bb 5845 } else {
ad69471c 5846 tcg_gen_add_i64(CPU_V001);
9ee6e8bb
PB
5847 }
5848 break;
5849 default:
5850 abort();
2c0262af 5851 }
ad69471c 5852 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 5853 }
9ee6e8bb 5854 return 0;
2c0262af 5855 }
25f84f79 5856 pairwise = 0;
9ee6e8bb 5857 switch (op) {
62698be3
PM
5858 case NEON_3R_VSHL:
5859 case NEON_3R_VQSHL:
5860 case NEON_3R_VRSHL:
5861 case NEON_3R_VQRSHL:
9ee6e8bb 5862 {
ad69471c
PB
5863 int rtmp;
5864 /* Shift instruction operands are reversed. */
5865 rtmp = rn;
9ee6e8bb 5866 rn = rm;
ad69471c 5867 rm = rtmp;
9ee6e8bb 5868 }
2c0262af 5869 break;
36a71934 5870 case NEON_3R_VPADD_VQRDMLAH:
62698be3
PM
5871 case NEON_3R_VPMAX:
5872 case NEON_3R_VPMIN:
9ee6e8bb 5873 pairwise = 1;
2c0262af 5874 break;
25f84f79
PM
5875 case NEON_3R_FLOAT_ARITH:
5876 pairwise = (u && size < 2); /* if VPADD (float) */
5877 break;
5878 case NEON_3R_FLOAT_MINMAX:
5879 pairwise = u; /* if VPMIN/VPMAX (float) */
5880 break;
5881 case NEON_3R_FLOAT_CMP:
5882 if (!u && size) {
5883 /* no encoding for U=0 C=1x */
5884 return 1;
5885 }
5886 break;
5887 case NEON_3R_FLOAT_ACMP:
5888 if (!u) {
5889 return 1;
5890 }
5891 break;
505935fc
WN
5892 case NEON_3R_FLOAT_MISC:
5893 /* VMAXNM/VMINNM in ARMv8 */
d614a513 5894 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
5895 return 1;
5896 }
2c0262af 5897 break;
25f84f79
PM
5898 case NEON_3R_VMUL:
5899 if (u && (size != 0)) {
5900 /* UNDEF on invalid size for polynomial subcase */
5901 return 1;
5902 }
2c0262af 5903 break;
36a71934
RH
5904 case NEON_3R_VFM_VQRDMLSH:
5905 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
5906 return 1;
5907 }
5908 break;
9ee6e8bb 5909 default:
2c0262af 5910 break;
9ee6e8bb 5911 }
dd8fbd78 5912
25f84f79
PM
5913 if (pairwise && q) {
5914 /* All the pairwise insns UNDEF if Q is set */
5915 return 1;
5916 }
5917
9ee6e8bb
PB
5918 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5919
5920 if (pairwise) {
5921 /* Pairwise. */
a5a14945
JR
5922 if (pass < 1) {
5923 tmp = neon_load_reg(rn, 0);
5924 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 5925 } else {
a5a14945
JR
5926 tmp = neon_load_reg(rm, 0);
5927 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
5928 }
5929 } else {
5930 /* Elementwise. */
dd8fbd78
FN
5931 tmp = neon_load_reg(rn, pass);
5932 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
5933 }
5934 switch (op) {
62698be3 5935 case NEON_3R_VHADD:
9ee6e8bb
PB
5936 GEN_NEON_INTEGER_OP(hadd);
5937 break;
62698be3 5938 case NEON_3R_VQADD:
02da0b2d 5939 GEN_NEON_INTEGER_OP_ENV(qadd);
2c0262af 5940 break;
62698be3 5941 case NEON_3R_VRHADD:
9ee6e8bb 5942 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 5943 break;
62698be3 5944 case NEON_3R_LOGIC: /* Logic ops. */
9ee6e8bb
PB
5945 switch ((u << 2) | size) {
5946 case 0: /* VAND */
dd8fbd78 5947 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5948 break;
5949 case 1: /* BIC */
f669df27 5950 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5951 break;
5952 case 2: /* VORR */
dd8fbd78 5953 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5954 break;
5955 case 3: /* VORN */
f669df27 5956 tcg_gen_orc_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5957 break;
5958 case 4: /* VEOR */
dd8fbd78 5959 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb
PB
5960 break;
5961 case 5: /* VBSL */
dd8fbd78
FN
5962 tmp3 = neon_load_reg(rd, pass);
5963 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
7d1b0095 5964 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5965 break;
5966 case 6: /* VBIT */
dd8fbd78
FN
5967 tmp3 = neon_load_reg(rd, pass);
5968 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
7d1b0095 5969 tcg_temp_free_i32(tmp3);
9ee6e8bb
PB
5970 break;
5971 case 7: /* VBIF */
dd8fbd78
FN
5972 tmp3 = neon_load_reg(rd, pass);
5973 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
7d1b0095 5974 tcg_temp_free_i32(tmp3);
9ee6e8bb 5975 break;
2c0262af
FB
5976 }
5977 break;
62698be3 5978 case NEON_3R_VHSUB:
9ee6e8bb
PB
5979 GEN_NEON_INTEGER_OP(hsub);
5980 break;
62698be3 5981 case NEON_3R_VQSUB:
02da0b2d 5982 GEN_NEON_INTEGER_OP_ENV(qsub);
2c0262af 5983 break;
62698be3 5984 case NEON_3R_VCGT:
9ee6e8bb
PB
5985 GEN_NEON_INTEGER_OP(cgt);
5986 break;
62698be3 5987 case NEON_3R_VCGE:
9ee6e8bb
PB
5988 GEN_NEON_INTEGER_OP(cge);
5989 break;
62698be3 5990 case NEON_3R_VSHL:
ad69471c 5991 GEN_NEON_INTEGER_OP(shl);
2c0262af 5992 break;
62698be3 5993 case NEON_3R_VQSHL:
02da0b2d 5994 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5995 break;
62698be3 5996 case NEON_3R_VRSHL:
ad69471c 5997 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5998 break;
62698be3 5999 case NEON_3R_VQRSHL:
02da0b2d 6000 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 6001 break;
62698be3 6002 case NEON_3R_VMAX:
9ee6e8bb
PB
6003 GEN_NEON_INTEGER_OP(max);
6004 break;
62698be3 6005 case NEON_3R_VMIN:
9ee6e8bb
PB
6006 GEN_NEON_INTEGER_OP(min);
6007 break;
62698be3 6008 case NEON_3R_VABD:
9ee6e8bb
PB
6009 GEN_NEON_INTEGER_OP(abd);
6010 break;
62698be3 6011 case NEON_3R_VABA:
9ee6e8bb 6012 GEN_NEON_INTEGER_OP(abd);
7d1b0095 6013 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
6014 tmp2 = neon_load_reg(rd, pass);
6015 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 6016 break;
62698be3 6017 case NEON_3R_VADD_VSUB:
9ee6e8bb 6018 if (!u) { /* VADD */
62698be3 6019 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6020 } else { /* VSUB */
6021 switch (size) {
dd8fbd78
FN
6022 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
6023 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
6024 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
62698be3 6025 default: abort();
9ee6e8bb
PB
6026 }
6027 }
6028 break;
62698be3 6029 case NEON_3R_VTST_VCEQ:
9ee6e8bb
PB
6030 if (!u) { /* VTST */
6031 switch (size) {
dd8fbd78
FN
6032 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
6033 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
6034 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
62698be3 6035 default: abort();
9ee6e8bb
PB
6036 }
6037 } else { /* VCEQ */
6038 switch (size) {
dd8fbd78
FN
6039 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6040 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6041 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
62698be3 6042 default: abort();
9ee6e8bb
PB
6043 }
6044 }
6045 break;
62698be3 6046 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
9ee6e8bb 6047 switch (size) {
dd8fbd78
FN
6048 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6049 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6050 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 6051 default: abort();
9ee6e8bb 6052 }
7d1b0095 6053 tcg_temp_free_i32(tmp2);
dd8fbd78 6054 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6055 if (u) { /* VMLS */
dd8fbd78 6056 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb 6057 } else { /* VMLA */
dd8fbd78 6058 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6059 }
6060 break;
62698be3 6061 case NEON_3R_VMUL:
9ee6e8bb 6062 if (u) { /* polynomial */
dd8fbd78 6063 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb
PB
6064 } else { /* Integer */
6065 switch (size) {
dd8fbd78
FN
6066 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6067 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6068 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
62698be3 6069 default: abort();
9ee6e8bb
PB
6070 }
6071 }
6072 break;
62698be3 6073 case NEON_3R_VPMAX:
9ee6e8bb
PB
6074 GEN_NEON_INTEGER_OP(pmax);
6075 break;
62698be3 6076 case NEON_3R_VPMIN:
9ee6e8bb
PB
6077 GEN_NEON_INTEGER_OP(pmin);
6078 break;
62698be3 6079 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
6080 if (!u) { /* VQDMULH */
6081 switch (size) {
02da0b2d
PM
6082 case 1:
6083 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6084 break;
6085 case 2:
6086 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6087 break;
62698be3 6088 default: abort();
9ee6e8bb 6089 }
62698be3 6090 } else { /* VQRDMULH */
9ee6e8bb 6091 switch (size) {
02da0b2d
PM
6092 case 1:
6093 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6094 break;
6095 case 2:
6096 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6097 break;
62698be3 6098 default: abort();
9ee6e8bb
PB
6099 }
6100 }
6101 break;
36a71934 6102 case NEON_3R_VPADD_VQRDMLAH:
9ee6e8bb 6103 switch (size) {
dd8fbd78
FN
6104 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6105 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6106 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 6107 default: abort();
9ee6e8bb
PB
6108 }
6109 break;
62698be3 6110 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
6111 {
6112 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
6113 switch ((u << 2) | size) {
6114 case 0: /* VADD */
aa47cfdd
PM
6115 case 4: /* VPADD */
6116 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6117 break;
6118 case 2: /* VSUB */
aa47cfdd 6119 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6120 break;
6121 case 6: /* VABD */
aa47cfdd 6122 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6123 break;
6124 default:
62698be3 6125 abort();
9ee6e8bb 6126 }
aa47cfdd 6127 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6128 break;
aa47cfdd 6129 }
62698be3 6130 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
6131 {
6132 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6133 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 6134 if (!u) {
7d1b0095 6135 tcg_temp_free_i32(tmp2);
dd8fbd78 6136 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6137 if (size == 0) {
aa47cfdd 6138 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 6139 } else {
aa47cfdd 6140 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
6141 }
6142 }
aa47cfdd 6143 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6144 break;
aa47cfdd 6145 }
62698be3 6146 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
6147 {
6148 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 6149 if (!u) {
aa47cfdd 6150 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 6151 } else {
aa47cfdd
PM
6152 if (size == 0) {
6153 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6154 } else {
6155 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6156 }
b5ff1b31 6157 }
aa47cfdd 6158 tcg_temp_free_ptr(fpstatus);
2c0262af 6159 break;
aa47cfdd 6160 }
62698be3 6161 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
6162 {
6163 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6164 if (size == 0) {
6165 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6166 } else {
6167 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6168 }
6169 tcg_temp_free_ptr(fpstatus);
2c0262af 6170 break;
aa47cfdd 6171 }
62698be3 6172 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
6173 {
6174 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6175 if (size == 0) {
f71a2ae5 6176 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 6177 } else {
f71a2ae5 6178 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
6179 }
6180 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6181 break;
aa47cfdd 6182 }
505935fc
WN
6183 case NEON_3R_FLOAT_MISC:
6184 if (u) {
6185 /* VMAXNM/VMINNM */
6186 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6187 if (size == 0) {
f71a2ae5 6188 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 6189 } else {
f71a2ae5 6190 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
6191 }
6192 tcg_temp_free_ptr(fpstatus);
6193 } else {
6194 if (size == 0) {
6195 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6196 } else {
6197 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6198 }
6199 }
2c0262af 6200 break;
36a71934 6201 case NEON_3R_VFM_VQRDMLSH:
da97f52c
PM
6202 {
6203 /* VFMA, VFMS: fused multiply-add */
6204 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6205 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6206 if (size) {
6207 /* VFMS */
6208 gen_helper_vfp_negs(tmp, tmp);
6209 }
6210 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6211 tcg_temp_free_i32(tmp3);
6212 tcg_temp_free_ptr(fpstatus);
6213 break;
6214 }
9ee6e8bb
PB
6215 default:
6216 abort();
2c0262af 6217 }
7d1b0095 6218 tcg_temp_free_i32(tmp2);
dd8fbd78 6219
9ee6e8bb
PB
6220 /* Save the result. For elementwise operations we can put it
6221 straight into the destination register. For pairwise operations
6222 we have to be careful to avoid clobbering the source operands. */
6223 if (pairwise && rd == rm) {
dd8fbd78 6224 neon_store_scratch(pass, tmp);
9ee6e8bb 6225 } else {
dd8fbd78 6226 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6227 }
6228
6229 } /* for pass */
6230 if (pairwise && rd == rm) {
6231 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
6232 tmp = neon_load_scratch(pass);
6233 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6234 }
6235 }
ad69471c 6236 /* End of 3 register same size operations. */
9ee6e8bb
PB
6237 } else if (insn & (1 << 4)) {
6238 if ((insn & 0x00380080) != 0) {
6239 /* Two registers and shift. */
6240 op = (insn >> 8) & 0xf;
6241 if (insn & (1 << 7)) {
cc13115b
PM
6242 /* 64-bit shift. */
6243 if (op > 7) {
6244 return 1;
6245 }
9ee6e8bb
PB
6246 size = 3;
6247 } else {
6248 size = 2;
6249 while ((insn & (1 << (size + 19))) == 0)
6250 size--;
6251 }
6252 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
b90372ad 6253 /* To avoid excessive duplication of ops we implement shift
9ee6e8bb
PB
6254 by immediate using the variable shift operations. */
6255 if (op < 8) {
6256 /* Shift by immediate:
6257 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
6258 if (q && ((rd | rm) & 1)) {
6259 return 1;
6260 }
6261 if (!u && (op == 4 || op == 6)) {
6262 return 1;
6263 }
9ee6e8bb
PB
6264 /* Right shifts are encoded as N - shift, where N is the
6265 element size in bits. */
6266 if (op <= 4)
6267 shift = shift - (1 << (size + 3));
9ee6e8bb
PB
6268 if (size == 3) {
6269 count = q + 1;
6270 } else {
6271 count = q ? 4: 2;
6272 }
6273 switch (size) {
6274 case 0:
6275 imm = (uint8_t) shift;
6276 imm |= imm << 8;
6277 imm |= imm << 16;
6278 break;
6279 case 1:
6280 imm = (uint16_t) shift;
6281 imm |= imm << 16;
6282 break;
6283 case 2:
6284 case 3:
6285 imm = shift;
6286 break;
6287 default:
6288 abort();
6289 }
6290
6291 for (pass = 0; pass < count; pass++) {
ad69471c
PB
6292 if (size == 3) {
6293 neon_load_reg64(cpu_V0, rm + pass);
6294 tcg_gen_movi_i64(cpu_V1, imm);
6295 switch (op) {
6296 case 0: /* VSHR */
6297 case 1: /* VSRA */
6298 if (u)
6299 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6300 else
ad69471c 6301 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6302 break;
ad69471c
PB
6303 case 2: /* VRSHR */
6304 case 3: /* VRSRA */
6305 if (u)
6306 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6307 else
ad69471c 6308 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6309 break;
ad69471c 6310 case 4: /* VSRI */
ad69471c
PB
6311 case 5: /* VSHL, VSLI */
6312 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
6313 break;
0322b26e 6314 case 6: /* VQSHLU */
02da0b2d
PM
6315 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6316 cpu_V0, cpu_V1);
ad69471c 6317 break;
0322b26e
PM
6318 case 7: /* VQSHL */
6319 if (u) {
02da0b2d 6320 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
6321 cpu_V0, cpu_V1);
6322 } else {
02da0b2d 6323 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
6324 cpu_V0, cpu_V1);
6325 }
9ee6e8bb 6326 break;
9ee6e8bb 6327 }
ad69471c
PB
6328 if (op == 1 || op == 3) {
6329 /* Accumulate. */
5371cb81 6330 neon_load_reg64(cpu_V1, rd + pass);
ad69471c
PB
6331 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
6332 } else if (op == 4 || (op == 5 && u)) {
6333 /* Insert */
923e6509
CL
6334 neon_load_reg64(cpu_V1, rd + pass);
6335 uint64_t mask;
6336 if (shift < -63 || shift > 63) {
6337 mask = 0;
6338 } else {
6339 if (op == 4) {
6340 mask = 0xffffffffffffffffull >> -shift;
6341 } else {
6342 mask = 0xffffffffffffffffull << shift;
6343 }
6344 }
6345 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
6346 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
6347 }
6348 neon_store_reg64(cpu_V0, rd + pass);
6349 } else { /* size < 3 */
6350 /* Operands in T0 and T1. */
dd8fbd78 6351 tmp = neon_load_reg(rm, pass);
7d1b0095 6352 tmp2 = tcg_temp_new_i32();
dd8fbd78 6353 tcg_gen_movi_i32(tmp2, imm);
ad69471c
PB
6354 switch (op) {
6355 case 0: /* VSHR */
6356 case 1: /* VSRA */
6357 GEN_NEON_INTEGER_OP(shl);
6358 break;
6359 case 2: /* VRSHR */
6360 case 3: /* VRSRA */
6361 GEN_NEON_INTEGER_OP(rshl);
6362 break;
6363 case 4: /* VSRI */
ad69471c
PB
6364 case 5: /* VSHL, VSLI */
6365 switch (size) {
dd8fbd78
FN
6366 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
6367 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
6368 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
cc13115b 6369 default: abort();
ad69471c
PB
6370 }
6371 break;
0322b26e 6372 case 6: /* VQSHLU */
ad69471c 6373 switch (size) {
0322b26e 6374 case 0:
02da0b2d
PM
6375 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6376 tmp, tmp2);
0322b26e
PM
6377 break;
6378 case 1:
02da0b2d
PM
6379 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6380 tmp, tmp2);
0322b26e
PM
6381 break;
6382 case 2:
02da0b2d
PM
6383 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6384 tmp, tmp2);
0322b26e
PM
6385 break;
6386 default:
cc13115b 6387 abort();
ad69471c
PB
6388 }
6389 break;
0322b26e 6390 case 7: /* VQSHL */
02da0b2d 6391 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 6392 break;
ad69471c 6393 }
7d1b0095 6394 tcg_temp_free_i32(tmp2);
ad69471c
PB
6395
6396 if (op == 1 || op == 3) {
6397 /* Accumulate. */
dd8fbd78 6398 tmp2 = neon_load_reg(rd, pass);
5371cb81 6399 gen_neon_add(size, tmp, tmp2);
7d1b0095 6400 tcg_temp_free_i32(tmp2);
ad69471c
PB
6401 } else if (op == 4 || (op == 5 && u)) {
6402 /* Insert */
6403 switch (size) {
6404 case 0:
6405 if (op == 4)
ca9a32e4 6406 mask = 0xff >> -shift;
ad69471c 6407 else
ca9a32e4
JR
6408 mask = (uint8_t)(0xff << shift);
6409 mask |= mask << 8;
6410 mask |= mask << 16;
ad69471c
PB
6411 break;
6412 case 1:
6413 if (op == 4)
ca9a32e4 6414 mask = 0xffff >> -shift;
ad69471c 6415 else
ca9a32e4
JR
6416 mask = (uint16_t)(0xffff << shift);
6417 mask |= mask << 16;
ad69471c
PB
6418 break;
6419 case 2:
ca9a32e4
JR
6420 if (shift < -31 || shift > 31) {
6421 mask = 0;
6422 } else {
6423 if (op == 4)
6424 mask = 0xffffffffu >> -shift;
6425 else
6426 mask = 0xffffffffu << shift;
6427 }
ad69471c
PB
6428 break;
6429 default:
6430 abort();
6431 }
dd8fbd78 6432 tmp2 = neon_load_reg(rd, pass);
ca9a32e4
JR
6433 tcg_gen_andi_i32(tmp, tmp, mask);
6434 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
dd8fbd78 6435 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 6436 tcg_temp_free_i32(tmp2);
ad69471c 6437 }
dd8fbd78 6438 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6439 }
6440 } /* for pass */
6441 } else if (op < 10) {
ad69471c 6442 /* Shift by immediate and narrow:
9ee6e8bb 6443 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 6444 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
6445 if (rm & 1) {
6446 return 1;
6447 }
9ee6e8bb
PB
6448 shift = shift - (1 << (size + 3));
6449 size++;
92cdfaeb 6450 if (size == 3) {
a7812ae4 6451 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
6452 neon_load_reg64(cpu_V0, rm);
6453 neon_load_reg64(cpu_V1, rm + 1);
6454 for (pass = 0; pass < 2; pass++) {
6455 TCGv_i64 in;
6456 if (pass == 0) {
6457 in = cpu_V0;
6458 } else {
6459 in = cpu_V1;
6460 }
ad69471c 6461 if (q) {
0b36f4cd 6462 if (input_unsigned) {
92cdfaeb 6463 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 6464 } else {
92cdfaeb 6465 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 6466 }
ad69471c 6467 } else {
0b36f4cd 6468 if (input_unsigned) {
92cdfaeb 6469 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 6470 } else {
92cdfaeb 6471 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 6472 }
ad69471c 6473 }
7d1b0095 6474 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6475 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6476 neon_store_reg(rd, pass, tmp);
6477 } /* for pass */
6478 tcg_temp_free_i64(tmp64);
6479 } else {
6480 if (size == 1) {
6481 imm = (uint16_t)shift;
6482 imm |= imm << 16;
2c0262af 6483 } else {
92cdfaeb
PM
6484 /* size == 2 */
6485 imm = (uint32_t)shift;
6486 }
6487 tmp2 = tcg_const_i32(imm);
6488 tmp4 = neon_load_reg(rm + 1, 0);
6489 tmp5 = neon_load_reg(rm + 1, 1);
6490 for (pass = 0; pass < 2; pass++) {
6491 if (pass == 0) {
6492 tmp = neon_load_reg(rm, 0);
6493 } else {
6494 tmp = tmp4;
6495 }
0b36f4cd
CL
6496 gen_neon_shift_narrow(size, tmp, tmp2, q,
6497 input_unsigned);
92cdfaeb
PM
6498 if (pass == 0) {
6499 tmp3 = neon_load_reg(rm, 1);
6500 } else {
6501 tmp3 = tmp5;
6502 }
0b36f4cd
CL
6503 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6504 input_unsigned);
36aa55dc 6505 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
6506 tcg_temp_free_i32(tmp);
6507 tcg_temp_free_i32(tmp3);
6508 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6509 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6510 neon_store_reg(rd, pass, tmp);
6511 } /* for pass */
c6067f04 6512 tcg_temp_free_i32(tmp2);
b75263d6 6513 }
9ee6e8bb 6514 } else if (op == 10) {
cc13115b
PM
6515 /* VSHLL, VMOVL */
6516 if (q || (rd & 1)) {
9ee6e8bb 6517 return 1;
cc13115b 6518 }
ad69471c
PB
6519 tmp = neon_load_reg(rm, 0);
6520 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6521 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6522 if (pass == 1)
6523 tmp = tmp2;
6524
6525 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 6526
9ee6e8bb
PB
6527 if (shift != 0) {
6528 /* The shift is less than the width of the source
ad69471c
PB
6529 type, so we can just shift the whole register. */
6530 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
6531 /* Widen the result of shift: we need to clear
6532 * the potential overflow bits resulting from
6533 * left bits of the narrow input appearing as
6534 * right bits of left the neighbour narrow
6535 * input. */
ad69471c
PB
6536 if (size < 2 || !u) {
6537 uint64_t imm64;
6538 if (size == 0) {
6539 imm = (0xffu >> (8 - shift));
6540 imm |= imm << 16;
acdf01ef 6541 } else if (size == 1) {
ad69471c 6542 imm = 0xffff >> (16 - shift);
acdf01ef
CL
6543 } else {
6544 /* size == 2 */
6545 imm = 0xffffffff >> (32 - shift);
6546 }
6547 if (size < 2) {
6548 imm64 = imm | (((uint64_t)imm) << 32);
6549 } else {
6550 imm64 = imm;
9ee6e8bb 6551 }
acdf01ef 6552 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
6553 }
6554 }
ad69471c 6555 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6556 }
f73534a5 6557 } else if (op >= 14) {
9ee6e8bb 6558 /* VCVT fixed-point. */
cc13115b
PM
6559 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
6560 return 1;
6561 }
f73534a5
PM
6562 /* We have already masked out the must-be-1 top bit of imm6,
6563 * hence this 32-shift where the ARM ARM has 64-imm6.
6564 */
6565 shift = 32 - shift;
9ee6e8bb 6566 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373f3ce 6567 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
f73534a5 6568 if (!(op & 1)) {
9ee6e8bb 6569 if (u)
5500b06c 6570 gen_vfp_ulto(0, shift, 1);
9ee6e8bb 6571 else
5500b06c 6572 gen_vfp_slto(0, shift, 1);
9ee6e8bb
PB
6573 } else {
6574 if (u)
5500b06c 6575 gen_vfp_toul(0, shift, 1);
9ee6e8bb 6576 else
5500b06c 6577 gen_vfp_tosl(0, shift, 1);
2c0262af 6578 }
4373f3ce 6579 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
2c0262af
FB
6580 }
6581 } else {
9ee6e8bb
PB
6582 return 1;
6583 }
6584 } else { /* (insn & 0x00380080) == 0 */
6585 int invert;
7d80fee5
PM
6586 if (q && (rd & 1)) {
6587 return 1;
6588 }
9ee6e8bb
PB
6589
6590 op = (insn >> 8) & 0xf;
6591 /* One register and immediate. */
6592 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6593 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
6594 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
6595 * We choose to not special-case this and will behave as if a
6596 * valid constant encoding of 0 had been given.
6597 */
9ee6e8bb
PB
6598 switch (op) {
6599 case 0: case 1:
6600 /* no-op */
6601 break;
6602 case 2: case 3:
6603 imm <<= 8;
6604 break;
6605 case 4: case 5:
6606 imm <<= 16;
6607 break;
6608 case 6: case 7:
6609 imm <<= 24;
6610 break;
6611 case 8: case 9:
6612 imm |= imm << 16;
6613 break;
6614 case 10: case 11:
6615 imm = (imm << 8) | (imm << 24);
6616 break;
6617 case 12:
8e31209e 6618 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
6619 break;
6620 case 13:
6621 imm = (imm << 16) | 0xffff;
6622 break;
6623 case 14:
6624 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6625 if (invert)
6626 imm = ~imm;
6627 break;
6628 case 15:
7d80fee5
PM
6629 if (invert) {
6630 return 1;
6631 }
9ee6e8bb
PB
6632 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6633 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6634 break;
6635 }
6636 if (invert)
6637 imm = ~imm;
6638
9ee6e8bb
PB
6639 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6640 if (op & 1 && op < 12) {
ad69471c 6641 tmp = neon_load_reg(rd, pass);
9ee6e8bb
PB
6642 if (invert) {
6643 /* The immediate value has already been inverted, so
6644 BIC becomes AND. */
ad69471c 6645 tcg_gen_andi_i32(tmp, tmp, imm);
9ee6e8bb 6646 } else {
ad69471c 6647 tcg_gen_ori_i32(tmp, tmp, imm);
9ee6e8bb 6648 }
9ee6e8bb 6649 } else {
ad69471c 6650 /* VMOV, VMVN. */
7d1b0095 6651 tmp = tcg_temp_new_i32();
9ee6e8bb 6652 if (op == 14 && invert) {
a5a14945 6653 int n;
ad69471c
PB
6654 uint32_t val;
6655 val = 0;
9ee6e8bb
PB
6656 for (n = 0; n < 4; n++) {
6657 if (imm & (1 << (n + (pass & 1) * 4)))
ad69471c 6658 val |= 0xff << (n * 8);
9ee6e8bb 6659 }
ad69471c
PB
6660 tcg_gen_movi_i32(tmp, val);
6661 } else {
6662 tcg_gen_movi_i32(tmp, imm);
9ee6e8bb 6663 }
9ee6e8bb 6664 }
ad69471c 6665 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6666 }
6667 }
e4b3861d 6668 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
6669 if (size != 3) {
6670 op = (insn >> 8) & 0xf;
6671 if ((insn & (1 << 6)) == 0) {
6672 /* Three registers of different lengths. */
6673 int src1_wide;
6674 int src2_wide;
6675 int prewiden;
526d0096
PM
6676 /* undefreq: bit 0 : UNDEF if size == 0
6677 * bit 1 : UNDEF if size == 1
6678 * bit 2 : UNDEF if size == 2
6679 * bit 3 : UNDEF if U == 1
6680 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
6681 */
6682 int undefreq;
6683 /* prewiden, src1_wide, src2_wide, undefreq */
6684 static const int neon_3reg_wide[16][4] = {
6685 {1, 0, 0, 0}, /* VADDL */
6686 {1, 1, 0, 0}, /* VADDW */
6687 {1, 0, 0, 0}, /* VSUBL */
6688 {1, 1, 0, 0}, /* VSUBW */
6689 {0, 1, 1, 0}, /* VADDHN */
6690 {0, 0, 0, 0}, /* VABAL */
6691 {0, 1, 1, 0}, /* VSUBHN */
6692 {0, 0, 0, 0}, /* VABDL */
6693 {0, 0, 0, 0}, /* VMLAL */
526d0096 6694 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 6695 {0, 0, 0, 0}, /* VMLSL */
526d0096 6696 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 6697 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 6698 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 6699 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 6700 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
6701 };
6702
6703 prewiden = neon_3reg_wide[op][0];
6704 src1_wide = neon_3reg_wide[op][1];
6705 src2_wide = neon_3reg_wide[op][2];
695272dc 6706 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 6707
526d0096
PM
6708 if ((undefreq & (1 << size)) ||
6709 ((undefreq & 8) && u)) {
695272dc
PM
6710 return 1;
6711 }
6712 if ((src1_wide && (rn & 1)) ||
6713 (src2_wide && (rm & 1)) ||
6714 (!src2_wide && (rd & 1))) {
ad69471c 6715 return 1;
695272dc 6716 }
ad69471c 6717
4e624eda
PM
6718 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6719 * outside the loop below as it only performs a single pass.
6720 */
6721 if (op == 14 && size == 2) {
6722 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6723
d614a513 6724 if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
4e624eda
PM
6725 return 1;
6726 }
6727 tcg_rn = tcg_temp_new_i64();
6728 tcg_rm = tcg_temp_new_i64();
6729 tcg_rd = tcg_temp_new_i64();
6730 neon_load_reg64(tcg_rn, rn);
6731 neon_load_reg64(tcg_rm, rm);
6732 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6733 neon_store_reg64(tcg_rd, rd);
6734 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6735 neon_store_reg64(tcg_rd, rd + 1);
6736 tcg_temp_free_i64(tcg_rn);
6737 tcg_temp_free_i64(tcg_rm);
6738 tcg_temp_free_i64(tcg_rd);
6739 return 0;
6740 }
6741
9ee6e8bb
PB
6742 /* Avoid overlapping operands. Wide source operands are
6743 always aligned so will never overlap with wide
6744 destinations in problematic ways. */
8f8e3aa4 6745 if (rd == rm && !src2_wide) {
dd8fbd78
FN
6746 tmp = neon_load_reg(rm, 1);
6747 neon_store_scratch(2, tmp);
8f8e3aa4 6748 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
6749 tmp = neon_load_reg(rn, 1);
6750 neon_store_scratch(2, tmp);
9ee6e8bb 6751 }
f764718d 6752 tmp3 = NULL;
9ee6e8bb 6753 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6754 if (src1_wide) {
6755 neon_load_reg64(cpu_V0, rn + pass);
f764718d 6756 tmp = NULL;
9ee6e8bb 6757 } else {
ad69471c 6758 if (pass == 1 && rd == rn) {
dd8fbd78 6759 tmp = neon_load_scratch(2);
9ee6e8bb 6760 } else {
ad69471c
PB
6761 tmp = neon_load_reg(rn, pass);
6762 }
6763 if (prewiden) {
6764 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
6765 }
6766 }
ad69471c
PB
6767 if (src2_wide) {
6768 neon_load_reg64(cpu_V1, rm + pass);
f764718d 6769 tmp2 = NULL;
9ee6e8bb 6770 } else {
ad69471c 6771 if (pass == 1 && rd == rm) {
dd8fbd78 6772 tmp2 = neon_load_scratch(2);
9ee6e8bb 6773 } else {
ad69471c
PB
6774 tmp2 = neon_load_reg(rm, pass);
6775 }
6776 if (prewiden) {
6777 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 6778 }
9ee6e8bb
PB
6779 }
6780 switch (op) {
6781 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 6782 gen_neon_addl(size);
9ee6e8bb 6783 break;
79b0e534 6784 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 6785 gen_neon_subl(size);
9ee6e8bb
PB
6786 break;
6787 case 5: case 7: /* VABAL, VABDL */
6788 switch ((size << 1) | u) {
ad69471c
PB
6789 case 0:
6790 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6791 break;
6792 case 1:
6793 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6794 break;
6795 case 2:
6796 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6797 break;
6798 case 3:
6799 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6800 break;
6801 case 4:
6802 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6803 break;
6804 case 5:
6805 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6806 break;
9ee6e8bb
PB
6807 default: abort();
6808 }
7d1b0095
PM
6809 tcg_temp_free_i32(tmp2);
6810 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6811 break;
6812 case 8: case 9: case 10: case 11: case 12: case 13:
6813 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 6814 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
6815 break;
6816 case 14: /* Polynomial VMULL */
e5ca24cb 6817 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
6818 tcg_temp_free_i32(tmp2);
6819 tcg_temp_free_i32(tmp);
e5ca24cb 6820 break;
695272dc
PM
6821 default: /* 15 is RESERVED: caught earlier */
6822 abort();
9ee6e8bb 6823 }
ebcd88ce
PM
6824 if (op == 13) {
6825 /* VQDMULL */
6826 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6827 neon_store_reg64(cpu_V0, rd + pass);
6828 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 6829 /* Accumulate. */
ebcd88ce 6830 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6831 switch (op) {
4dc064e6
PM
6832 case 10: /* VMLSL */
6833 gen_neon_negl(cpu_V0, size);
6834 /* Fall through */
6835 case 5: case 8: /* VABAL, VMLAL */
ad69471c 6836 gen_neon_addl(size);
9ee6e8bb
PB
6837 break;
6838 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 6839 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6840 if (op == 11) {
6841 gen_neon_negl(cpu_V0, size);
6842 }
ad69471c
PB
6843 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6844 break;
9ee6e8bb
PB
6845 default:
6846 abort();
6847 }
ad69471c 6848 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6849 } else if (op == 4 || op == 6) {
6850 /* Narrowing operation. */
7d1b0095 6851 tmp = tcg_temp_new_i32();
79b0e534 6852 if (!u) {
9ee6e8bb 6853 switch (size) {
ad69471c
PB
6854 case 0:
6855 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6856 break;
6857 case 1:
6858 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6859 break;
6860 case 2:
6861 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6862 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6863 break;
9ee6e8bb
PB
6864 default: abort();
6865 }
6866 } else {
6867 switch (size) {
ad69471c
PB
6868 case 0:
6869 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6870 break;
6871 case 1:
6872 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6873 break;
6874 case 2:
6875 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6876 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6877 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6878 break;
9ee6e8bb
PB
6879 default: abort();
6880 }
6881 }
ad69471c
PB
6882 if (pass == 0) {
6883 tmp3 = tmp;
6884 } else {
6885 neon_store_reg(rd, 0, tmp3);
6886 neon_store_reg(rd, 1, tmp);
6887 }
9ee6e8bb
PB
6888 } else {
6889 /* Write back the result. */
ad69471c 6890 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6891 }
6892 }
6893 } else {
3e3326df
PM
6894 /* Two registers and a scalar. NB that for ops of this form
6895 * the ARM ARM labels bit 24 as Q, but it is in our variable
6896 * 'u', not 'q'.
6897 */
6898 if (size == 0) {
6899 return 1;
6900 }
9ee6e8bb 6901 switch (op) {
9ee6e8bb 6902 case 1: /* Float VMLA scalar */
9ee6e8bb 6903 case 5: /* Floating point VMLS scalar */
9ee6e8bb 6904 case 9: /* Floating point VMUL scalar */
3e3326df
PM
6905 if (size == 1) {
6906 return 1;
6907 }
6908 /* fall through */
6909 case 0: /* Integer VMLA scalar */
6910 case 4: /* Integer VMLS scalar */
6911 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
6912 case 12: /* VQDMULH scalar */
6913 case 13: /* VQRDMULH scalar */
3e3326df
PM
6914 if (u && ((rd | rn) & 1)) {
6915 return 1;
6916 }
dd8fbd78
FN
6917 tmp = neon_get_scalar(size, rm);
6918 neon_store_scratch(0, tmp);
9ee6e8bb 6919 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
6920 tmp = neon_load_scratch(0);
6921 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
6922 if (op == 12) {
6923 if (size == 1) {
02da0b2d 6924 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6925 } else {
02da0b2d 6926 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6927 }
6928 } else if (op == 13) {
6929 if (size == 1) {
02da0b2d 6930 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6931 } else {
02da0b2d 6932 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6933 }
6934 } else if (op & 1) {
aa47cfdd
PM
6935 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6936 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6937 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
6938 } else {
6939 switch (size) {
dd8fbd78
FN
6940 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6941 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6942 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 6943 default: abort();
9ee6e8bb
PB
6944 }
6945 }
7d1b0095 6946 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
6947 if (op < 8) {
6948 /* Accumulate. */
dd8fbd78 6949 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
6950 switch (op) {
6951 case 0:
dd8fbd78 6952 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6953 break;
6954 case 1:
aa47cfdd
PM
6955 {
6956 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6957 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6958 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6959 break;
aa47cfdd 6960 }
9ee6e8bb 6961 case 4:
dd8fbd78 6962 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
6963 break;
6964 case 5:
aa47cfdd
PM
6965 {
6966 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6967 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6968 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6969 break;
aa47cfdd 6970 }
9ee6e8bb
PB
6971 default:
6972 abort();
6973 }
7d1b0095 6974 tcg_temp_free_i32(tmp2);
9ee6e8bb 6975 }
dd8fbd78 6976 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6977 }
6978 break;
9ee6e8bb 6979 case 3: /* VQDMLAL scalar */
9ee6e8bb 6980 case 7: /* VQDMLSL scalar */
9ee6e8bb 6981 case 11: /* VQDMULL scalar */
3e3326df 6982 if (u == 1) {
ad69471c 6983 return 1;
3e3326df
PM
6984 }
6985 /* fall through */
6986 case 2: /* VMLAL sclar */
6987 case 6: /* VMLSL scalar */
6988 case 10: /* VMULL scalar */
6989 if (rd & 1) {
6990 return 1;
6991 }
dd8fbd78 6992 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
6993 /* We need a copy of tmp2 because gen_neon_mull
6994 * deletes it during pass 0. */
7d1b0095 6995 tmp4 = tcg_temp_new_i32();
c6067f04 6996 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 6997 tmp3 = neon_load_reg(rn, 1);
ad69471c 6998
9ee6e8bb 6999 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
7000 if (pass == 0) {
7001 tmp = neon_load_reg(rn, 0);
9ee6e8bb 7002 } else {
dd8fbd78 7003 tmp = tmp3;
c6067f04 7004 tmp2 = tmp4;
9ee6e8bb 7005 }
ad69471c 7006 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
7007 if (op != 11) {
7008 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 7009 }
9ee6e8bb 7010 switch (op) {
4dc064e6
PM
7011 case 6:
7012 gen_neon_negl(cpu_V0, size);
7013 /* Fall through */
7014 case 2:
ad69471c 7015 gen_neon_addl(size);
9ee6e8bb
PB
7016 break;
7017 case 3: case 7:
ad69471c 7018 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
7019 if (op == 7) {
7020 gen_neon_negl(cpu_V0, size);
7021 }
ad69471c 7022 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
7023 break;
7024 case 10:
7025 /* no-op */
7026 break;
7027 case 11:
ad69471c 7028 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
7029 break;
7030 default:
7031 abort();
7032 }
ad69471c 7033 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 7034 }
61adacc8
RH
7035 break;
7036 case 14: /* VQRDMLAH scalar */
7037 case 15: /* VQRDMLSH scalar */
7038 {
7039 NeonGenThreeOpEnvFn *fn;
dd8fbd78 7040
61adacc8
RH
7041 if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
7042 return 1;
7043 }
7044 if (u && ((rd | rn) & 1)) {
7045 return 1;
7046 }
7047 if (op == 14) {
7048 if (size == 1) {
7049 fn = gen_helper_neon_qrdmlah_s16;
7050 } else {
7051 fn = gen_helper_neon_qrdmlah_s32;
7052 }
7053 } else {
7054 if (size == 1) {
7055 fn = gen_helper_neon_qrdmlsh_s16;
7056 } else {
7057 fn = gen_helper_neon_qrdmlsh_s32;
7058 }
7059 }
dd8fbd78 7060
61adacc8
RH
7061 tmp2 = neon_get_scalar(size, rm);
7062 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7063 tmp = neon_load_reg(rn, pass);
7064 tmp3 = neon_load_reg(rd, pass);
7065 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7066 tcg_temp_free_i32(tmp3);
7067 neon_store_reg(rd, pass, tmp);
7068 }
7069 tcg_temp_free_i32(tmp2);
7070 }
9ee6e8bb 7071 break;
61adacc8
RH
7072 default:
7073 g_assert_not_reached();
9ee6e8bb
PB
7074 }
7075 }
7076 } else { /* size == 3 */
7077 if (!u) {
7078 /* Extract. */
9ee6e8bb 7079 imm = (insn >> 8) & 0xf;
ad69471c
PB
7080
7081 if (imm > 7 && !q)
7082 return 1;
7083
52579ea1
PM
7084 if (q && ((rd | rn | rm) & 1)) {
7085 return 1;
7086 }
7087
ad69471c
PB
7088 if (imm == 0) {
7089 neon_load_reg64(cpu_V0, rn);
7090 if (q) {
7091 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 7092 }
ad69471c
PB
7093 } else if (imm == 8) {
7094 neon_load_reg64(cpu_V0, rn + 1);
7095 if (q) {
7096 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 7097 }
ad69471c 7098 } else if (q) {
a7812ae4 7099 tmp64 = tcg_temp_new_i64();
ad69471c
PB
7100 if (imm < 8) {
7101 neon_load_reg64(cpu_V0, rn);
a7812ae4 7102 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
7103 } else {
7104 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 7105 neon_load_reg64(tmp64, rm);
ad69471c
PB
7106 }
7107 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 7108 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
7109 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7110 if (imm < 8) {
7111 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 7112 } else {
ad69471c
PB
7113 neon_load_reg64(cpu_V1, rm + 1);
7114 imm -= 8;
9ee6e8bb 7115 }
ad69471c 7116 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
7117 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7118 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 7119 tcg_temp_free_i64(tmp64);
ad69471c 7120 } else {
a7812ae4 7121 /* BUGFIX */
ad69471c 7122 neon_load_reg64(cpu_V0, rn);
a7812ae4 7123 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 7124 neon_load_reg64(cpu_V1, rm);
a7812ae4 7125 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
7126 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7127 }
7128 neon_store_reg64(cpu_V0, rd);
7129 if (q) {
7130 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
7131 }
7132 } else if ((insn & (1 << 11)) == 0) {
7133 /* Two register misc. */
7134 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7135 size = (insn >> 18) & 3;
600b828c
PM
7136 /* UNDEF for unknown op values and bad op-size combinations */
7137 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7138 return 1;
7139 }
fe8fcf3d
PM
7140 if (neon_2rm_is_v8_op(op) &&
7141 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7142 return 1;
7143 }
fc2a9b37
PM
7144 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7145 q && ((rm | rd) & 1)) {
7146 return 1;
7147 }
9ee6e8bb 7148 switch (op) {
600b828c 7149 case NEON_2RM_VREV64:
9ee6e8bb 7150 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
7151 tmp = neon_load_reg(rm, pass * 2);
7152 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 7153 switch (size) {
dd8fbd78
FN
7154 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7155 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
7156 case 2: /* no-op */ break;
7157 default: abort();
7158 }
dd8fbd78 7159 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 7160 if (size == 2) {
dd8fbd78 7161 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 7162 } else {
9ee6e8bb 7163 switch (size) {
dd8fbd78
FN
7164 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7165 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
7166 default: abort();
7167 }
dd8fbd78 7168 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
7169 }
7170 }
7171 break;
600b828c
PM
7172 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7173 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
7174 for (pass = 0; pass < q + 1; pass++) {
7175 tmp = neon_load_reg(rm, pass * 2);
7176 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7177 tmp = neon_load_reg(rm, pass * 2 + 1);
7178 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7179 switch (size) {
7180 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7181 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7182 case 2: tcg_gen_add_i64(CPU_V001); break;
7183 default: abort();
7184 }
600b828c 7185 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 7186 /* Accumulate. */
ad69471c
PB
7187 neon_load_reg64(cpu_V1, rd + pass);
7188 gen_neon_addl(size);
9ee6e8bb 7189 }
ad69471c 7190 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7191 }
7192 break;
600b828c 7193 case NEON_2RM_VTRN:
9ee6e8bb 7194 if (size == 2) {
a5a14945 7195 int n;
9ee6e8bb 7196 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
7197 tmp = neon_load_reg(rm, n);
7198 tmp2 = neon_load_reg(rd, n + 1);
7199 neon_store_reg(rm, n, tmp2);
7200 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
7201 }
7202 } else {
7203 goto elementwise;
7204 }
7205 break;
600b828c 7206 case NEON_2RM_VUZP:
02acedf9 7207 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 7208 return 1;
9ee6e8bb
PB
7209 }
7210 break;
600b828c 7211 case NEON_2RM_VZIP:
d68a6f3a 7212 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 7213 return 1;
9ee6e8bb
PB
7214 }
7215 break;
600b828c
PM
7216 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7217 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
7218 if (rm & 1) {
7219 return 1;
7220 }
f764718d 7221 tmp2 = NULL;
9ee6e8bb 7222 for (pass = 0; pass < 2; pass++) {
ad69471c 7223 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 7224 tmp = tcg_temp_new_i32();
600b828c
PM
7225 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7226 tmp, cpu_V0);
ad69471c
PB
7227 if (pass == 0) {
7228 tmp2 = tmp;
7229 } else {
7230 neon_store_reg(rd, 0, tmp2);
7231 neon_store_reg(rd, 1, tmp);
9ee6e8bb 7232 }
9ee6e8bb
PB
7233 }
7234 break;
600b828c 7235 case NEON_2RM_VSHLL:
fc2a9b37 7236 if (q || (rd & 1)) {
9ee6e8bb 7237 return 1;
600b828c 7238 }
ad69471c
PB
7239 tmp = neon_load_reg(rm, 0);
7240 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 7241 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
7242 if (pass == 1)
7243 tmp = tmp2;
7244 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 7245 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 7246 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7247 }
7248 break;
600b828c 7249 case NEON_2RM_VCVT_F16_F32:
486624fc
AB
7250 {
7251 TCGv_ptr fpst;
7252 TCGv_i32 ahp;
7253
d614a513 7254 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
7255 q || (rm & 1)) {
7256 return 1;
7257 }
7d1b0095
PM
7258 tmp = tcg_temp_new_i32();
7259 tmp2 = tcg_temp_new_i32();
486624fc
AB
7260 fpst = get_fpstatus_ptr(true);
7261 ahp = get_ahp_flag();
60011498 7262 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
486624fc 7263 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
60011498 7264 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
486624fc 7265 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
60011498
PB
7266 tcg_gen_shli_i32(tmp2, tmp2, 16);
7267 tcg_gen_or_i32(tmp2, tmp2, tmp);
7268 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
486624fc 7269 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
60011498
PB
7270 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7271 neon_store_reg(rd, 0, tmp2);
7d1b0095 7272 tmp2 = tcg_temp_new_i32();
486624fc 7273 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
60011498
PB
7274 tcg_gen_shli_i32(tmp2, tmp2, 16);
7275 tcg_gen_or_i32(tmp2, tmp2, tmp);
7276 neon_store_reg(rd, 1, tmp2);
7d1b0095 7277 tcg_temp_free_i32(tmp);
486624fc
AB
7278 tcg_temp_free_i32(ahp);
7279 tcg_temp_free_ptr(fpst);
60011498 7280 break;
486624fc 7281 }
600b828c 7282 case NEON_2RM_VCVT_F32_F16:
486624fc
AB
7283 {
7284 TCGv_ptr fpst;
7285 TCGv_i32 ahp;
d614a513 7286 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
7287 q || (rd & 1)) {
7288 return 1;
7289 }
486624fc
AB
7290 fpst = get_fpstatus_ptr(true);
7291 ahp = get_ahp_flag();
7d1b0095 7292 tmp3 = tcg_temp_new_i32();
60011498
PB
7293 tmp = neon_load_reg(rm, 0);
7294 tmp2 = neon_load_reg(rm, 1);
7295 tcg_gen_ext16u_i32(tmp3, tmp);
486624fc 7296 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498
PB
7297 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7298 tcg_gen_shri_i32(tmp3, tmp, 16);
486624fc 7299 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498 7300 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7d1b0095 7301 tcg_temp_free_i32(tmp);
60011498 7302 tcg_gen_ext16u_i32(tmp3, tmp2);
486624fc 7303 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498
PB
7304 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7305 tcg_gen_shri_i32(tmp3, tmp2, 16);
486624fc 7306 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498 7307 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7d1b0095
PM
7308 tcg_temp_free_i32(tmp2);
7309 tcg_temp_free_i32(tmp3);
486624fc
AB
7310 tcg_temp_free_i32(ahp);
7311 tcg_temp_free_ptr(fpst);
60011498 7312 break;
486624fc 7313 }
9d935509 7314 case NEON_2RM_AESE: case NEON_2RM_AESMC:
d614a513 7315 if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
9d935509
AB
7316 || ((rm | rd) & 1)) {
7317 return 1;
7318 }
1a66ac61
RH
7319 ptr1 = vfp_reg_ptr(true, rd);
7320 ptr2 = vfp_reg_ptr(true, rm);
9d935509
AB
7321
7322 /* Bit 6 is the lowest opcode bit; it distinguishes between
7323 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7324 */
7325 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7326
7327 if (op == NEON_2RM_AESE) {
1a66ac61 7328 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
9d935509 7329 } else {
1a66ac61 7330 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
9d935509 7331 }
1a66ac61
RH
7332 tcg_temp_free_ptr(ptr1);
7333 tcg_temp_free_ptr(ptr2);
9d935509
AB
7334 tcg_temp_free_i32(tmp3);
7335 break;
f1ecb913 7336 case NEON_2RM_SHA1H:
d614a513 7337 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)
f1ecb913
AB
7338 || ((rm | rd) & 1)) {
7339 return 1;
7340 }
1a66ac61
RH
7341 ptr1 = vfp_reg_ptr(true, rd);
7342 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 7343
1a66ac61 7344 gen_helper_crypto_sha1h(ptr1, ptr2);
f1ecb913 7345
1a66ac61
RH
7346 tcg_temp_free_ptr(ptr1);
7347 tcg_temp_free_ptr(ptr2);
f1ecb913
AB
7348 break;
7349 case NEON_2RM_SHA1SU1:
7350 if ((rm | rd) & 1) {
7351 return 1;
7352 }
7353 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7354 if (q) {
d614a513 7355 if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256)) {
f1ecb913
AB
7356 return 1;
7357 }
d614a513 7358 } else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
f1ecb913
AB
7359 return 1;
7360 }
1a66ac61
RH
7361 ptr1 = vfp_reg_ptr(true, rd);
7362 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 7363 if (q) {
1a66ac61 7364 gen_helper_crypto_sha256su0(ptr1, ptr2);
f1ecb913 7365 } else {
1a66ac61 7366 gen_helper_crypto_sha1su1(ptr1, ptr2);
f1ecb913 7367 }
1a66ac61
RH
7368 tcg_temp_free_ptr(ptr1);
7369 tcg_temp_free_ptr(ptr2);
f1ecb913 7370 break;
9ee6e8bb
PB
7371 default:
7372 elementwise:
7373 for (pass = 0; pass < (q ? 4 : 2); pass++) {
600b828c 7374 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7375 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7376 neon_reg_offset(rm, pass));
f764718d 7377 tmp = NULL;
9ee6e8bb 7378 } else {
dd8fbd78 7379 tmp = neon_load_reg(rm, pass);
9ee6e8bb
PB
7380 }
7381 switch (op) {
600b828c 7382 case NEON_2RM_VREV32:
9ee6e8bb 7383 switch (size) {
dd8fbd78
FN
7384 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7385 case 1: gen_swap_half(tmp); break;
600b828c 7386 default: abort();
9ee6e8bb
PB
7387 }
7388 break;
600b828c 7389 case NEON_2RM_VREV16:
dd8fbd78 7390 gen_rev16(tmp);
9ee6e8bb 7391 break;
600b828c 7392 case NEON_2RM_VCLS:
9ee6e8bb 7393 switch (size) {
dd8fbd78
FN
7394 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7395 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7396 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 7397 default: abort();
9ee6e8bb
PB
7398 }
7399 break;
600b828c 7400 case NEON_2RM_VCLZ:
9ee6e8bb 7401 switch (size) {
dd8fbd78
FN
7402 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7403 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7539a012 7404 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
600b828c 7405 default: abort();
9ee6e8bb
PB
7406 }
7407 break;
600b828c 7408 case NEON_2RM_VCNT:
dd8fbd78 7409 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 7410 break;
600b828c 7411 case NEON_2RM_VMVN:
dd8fbd78 7412 tcg_gen_not_i32(tmp, tmp);
9ee6e8bb 7413 break;
600b828c 7414 case NEON_2RM_VQABS:
9ee6e8bb 7415 switch (size) {
02da0b2d
PM
7416 case 0:
7417 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7418 break;
7419 case 1:
7420 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7421 break;
7422 case 2:
7423 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7424 break;
600b828c 7425 default: abort();
9ee6e8bb
PB
7426 }
7427 break;
600b828c 7428 case NEON_2RM_VQNEG:
9ee6e8bb 7429 switch (size) {
02da0b2d
PM
7430 case 0:
7431 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7432 break;
7433 case 1:
7434 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7435 break;
7436 case 2:
7437 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7438 break;
600b828c 7439 default: abort();
9ee6e8bb
PB
7440 }
7441 break;
600b828c 7442 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 7443 tmp2 = tcg_const_i32(0);
9ee6e8bb 7444 switch(size) {
dd8fbd78
FN
7445 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7446 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7447 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 7448 default: abort();
9ee6e8bb 7449 }
39d5492a 7450 tcg_temp_free_i32(tmp2);
600b828c 7451 if (op == NEON_2RM_VCLE0) {
dd8fbd78 7452 tcg_gen_not_i32(tmp, tmp);
600b828c 7453 }
9ee6e8bb 7454 break;
600b828c 7455 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 7456 tmp2 = tcg_const_i32(0);
9ee6e8bb 7457 switch(size) {
dd8fbd78
FN
7458 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7459 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7460 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 7461 default: abort();
9ee6e8bb 7462 }
39d5492a 7463 tcg_temp_free_i32(tmp2);
600b828c 7464 if (op == NEON_2RM_VCLT0) {
dd8fbd78 7465 tcg_gen_not_i32(tmp, tmp);
600b828c 7466 }
9ee6e8bb 7467 break;
600b828c 7468 case NEON_2RM_VCEQ0:
dd8fbd78 7469 tmp2 = tcg_const_i32(0);
9ee6e8bb 7470 switch(size) {
dd8fbd78
FN
7471 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7472 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7473 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 7474 default: abort();
9ee6e8bb 7475 }
39d5492a 7476 tcg_temp_free_i32(tmp2);
9ee6e8bb 7477 break;
600b828c 7478 case NEON_2RM_VABS:
9ee6e8bb 7479 switch(size) {
dd8fbd78
FN
7480 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
7481 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
7482 case 2: tcg_gen_abs_i32(tmp, tmp); break;
600b828c 7483 default: abort();
9ee6e8bb
PB
7484 }
7485 break;
600b828c 7486 case NEON_2RM_VNEG:
dd8fbd78
FN
7487 tmp2 = tcg_const_i32(0);
7488 gen_neon_rsb(size, tmp, tmp2);
39d5492a 7489 tcg_temp_free_i32(tmp2);
9ee6e8bb 7490 break;
600b828c 7491 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
7492 {
7493 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7494 tmp2 = tcg_const_i32(0);
aa47cfdd 7495 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7496 tcg_temp_free_i32(tmp2);
aa47cfdd 7497 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7498 break;
aa47cfdd 7499 }
600b828c 7500 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
7501 {
7502 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7503 tmp2 = tcg_const_i32(0);
aa47cfdd 7504 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7505 tcg_temp_free_i32(tmp2);
aa47cfdd 7506 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7507 break;
aa47cfdd 7508 }
600b828c 7509 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
7510 {
7511 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7512 tmp2 = tcg_const_i32(0);
aa47cfdd 7513 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7514 tcg_temp_free_i32(tmp2);
aa47cfdd 7515 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7516 break;
aa47cfdd 7517 }
600b828c 7518 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
7519 {
7520 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7521 tmp2 = tcg_const_i32(0);
aa47cfdd 7522 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 7523 tcg_temp_free_i32(tmp2);
aa47cfdd 7524 tcg_temp_free_ptr(fpstatus);
0e326109 7525 break;
aa47cfdd 7526 }
600b828c 7527 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
7528 {
7529 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7530 tmp2 = tcg_const_i32(0);
aa47cfdd 7531 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 7532 tcg_temp_free_i32(tmp2);
aa47cfdd 7533 tcg_temp_free_ptr(fpstatus);
0e326109 7534 break;
aa47cfdd 7535 }
600b828c 7536 case NEON_2RM_VABS_F:
4373f3ce 7537 gen_vfp_abs(0);
9ee6e8bb 7538 break;
600b828c 7539 case NEON_2RM_VNEG_F:
4373f3ce 7540 gen_vfp_neg(0);
9ee6e8bb 7541 break;
600b828c 7542 case NEON_2RM_VSWP:
dd8fbd78
FN
7543 tmp2 = neon_load_reg(rd, pass);
7544 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 7545 break;
600b828c 7546 case NEON_2RM_VTRN:
dd8fbd78 7547 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 7548 switch (size) {
dd8fbd78
FN
7549 case 0: gen_neon_trn_u8(tmp, tmp2); break;
7550 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 7551 default: abort();
9ee6e8bb 7552 }
dd8fbd78 7553 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 7554 break;
34f7b0a2
WN
7555 case NEON_2RM_VRINTN:
7556 case NEON_2RM_VRINTA:
7557 case NEON_2RM_VRINTM:
7558 case NEON_2RM_VRINTP:
7559 case NEON_2RM_VRINTZ:
7560 {
7561 TCGv_i32 tcg_rmode;
7562 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7563 int rmode;
7564
7565 if (op == NEON_2RM_VRINTZ) {
7566 rmode = FPROUNDING_ZERO;
7567 } else {
7568 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
7569 }
7570
7571 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7572 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7573 cpu_env);
7574 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
7575 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7576 cpu_env);
7577 tcg_temp_free_ptr(fpstatus);
7578 tcg_temp_free_i32(tcg_rmode);
7579 break;
7580 }
2ce70625
WN
7581 case NEON_2RM_VRINTX:
7582 {
7583 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7584 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
7585 tcg_temp_free_ptr(fpstatus);
7586 break;
7587 }
901ad525
WN
7588 case NEON_2RM_VCVTAU:
7589 case NEON_2RM_VCVTAS:
7590 case NEON_2RM_VCVTNU:
7591 case NEON_2RM_VCVTNS:
7592 case NEON_2RM_VCVTPU:
7593 case NEON_2RM_VCVTPS:
7594 case NEON_2RM_VCVTMU:
7595 case NEON_2RM_VCVTMS:
7596 {
7597 bool is_signed = !extract32(insn, 7, 1);
7598 TCGv_ptr fpst = get_fpstatus_ptr(1);
7599 TCGv_i32 tcg_rmode, tcg_shift;
7600 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
7601
7602 tcg_shift = tcg_const_i32(0);
7603 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7604 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7605 cpu_env);
7606
7607 if (is_signed) {
7608 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
7609 tcg_shift, fpst);
7610 } else {
7611 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
7612 tcg_shift, fpst);
7613 }
7614
7615 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7616 cpu_env);
7617 tcg_temp_free_i32(tcg_rmode);
7618 tcg_temp_free_i32(tcg_shift);
7619 tcg_temp_free_ptr(fpst);
7620 break;
7621 }
600b828c 7622 case NEON_2RM_VRECPE:
b6d4443a
AB
7623 {
7624 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7625 gen_helper_recpe_u32(tmp, tmp, fpstatus);
7626 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7627 break;
b6d4443a 7628 }
600b828c 7629 case NEON_2RM_VRSQRTE:
c2fb418e
AB
7630 {
7631 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7632 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7633 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7634 break;
c2fb418e 7635 }
600b828c 7636 case NEON_2RM_VRECPE_F:
b6d4443a
AB
7637 {
7638 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7639 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7640 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7641 break;
b6d4443a 7642 }
600b828c 7643 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
7644 {
7645 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7646 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7647 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7648 break;
c2fb418e 7649 }
600b828c 7650 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
5500b06c 7651 gen_vfp_sito(0, 1);
9ee6e8bb 7652 break;
600b828c 7653 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
5500b06c 7654 gen_vfp_uito(0, 1);
9ee6e8bb 7655 break;
600b828c 7656 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
5500b06c 7657 gen_vfp_tosiz(0, 1);
9ee6e8bb 7658 break;
600b828c 7659 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
5500b06c 7660 gen_vfp_touiz(0, 1);
9ee6e8bb
PB
7661 break;
7662 default:
600b828c
PM
7663 /* Reserved op values were caught by the
7664 * neon_2rm_sizes[] check earlier.
7665 */
7666 abort();
9ee6e8bb 7667 }
600b828c 7668 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7669 tcg_gen_st_f32(cpu_F0s, cpu_env,
7670 neon_reg_offset(rd, pass));
9ee6e8bb 7671 } else {
dd8fbd78 7672 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
7673 }
7674 }
7675 break;
7676 }
7677 } else if ((insn & (1 << 10)) == 0) {
7678 /* VTBL, VTBX. */
56907d77
PM
7679 int n = ((insn >> 8) & 3) + 1;
7680 if ((rn + n) > 32) {
7681 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
7682 * helper function running off the end of the register file.
7683 */
7684 return 1;
7685 }
7686 n <<= 3;
9ee6e8bb 7687 if (insn & (1 << 6)) {
8f8e3aa4 7688 tmp = neon_load_reg(rd, 0);
9ee6e8bb 7689 } else {
7d1b0095 7690 tmp = tcg_temp_new_i32();
8f8e3aa4 7691 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7692 }
8f8e3aa4 7693 tmp2 = neon_load_reg(rm, 0);
e7c06c4e 7694 ptr1 = vfp_reg_ptr(true, rn);
b75263d6 7695 tmp5 = tcg_const_i32(n);
e7c06c4e 7696 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7d1b0095 7697 tcg_temp_free_i32(tmp);
9ee6e8bb 7698 if (insn & (1 << 6)) {
8f8e3aa4 7699 tmp = neon_load_reg(rd, 1);
9ee6e8bb 7700 } else {
7d1b0095 7701 tmp = tcg_temp_new_i32();
8f8e3aa4 7702 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 7703 }
8f8e3aa4 7704 tmp3 = neon_load_reg(rm, 1);
e7c06c4e 7705 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
25aeb69b 7706 tcg_temp_free_i32(tmp5);
e7c06c4e 7707 tcg_temp_free_ptr(ptr1);
8f8e3aa4 7708 neon_store_reg(rd, 0, tmp2);
3018f259 7709 neon_store_reg(rd, 1, tmp3);
7d1b0095 7710 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7711 } else if ((insn & 0x380) == 0) {
7712 /* VDUP */
133da6aa
JR
7713 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7714 return 1;
7715 }
9ee6e8bb 7716 if (insn & (1 << 19)) {
dd8fbd78 7717 tmp = neon_load_reg(rm, 1);
9ee6e8bb 7718 } else {
dd8fbd78 7719 tmp = neon_load_reg(rm, 0);
9ee6e8bb
PB
7720 }
7721 if (insn & (1 << 16)) {
dd8fbd78 7722 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
9ee6e8bb
PB
7723 } else if (insn & (1 << 17)) {
7724 if ((insn >> 18) & 1)
dd8fbd78 7725 gen_neon_dup_high16(tmp);
9ee6e8bb 7726 else
dd8fbd78 7727 gen_neon_dup_low16(tmp);
9ee6e8bb
PB
7728 }
7729 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7d1b0095 7730 tmp2 = tcg_temp_new_i32();
dd8fbd78
FN
7731 tcg_gen_mov_i32(tmp2, tmp);
7732 neon_store_reg(rd, pass, tmp2);
9ee6e8bb 7733 }
7d1b0095 7734 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7735 } else {
7736 return 1;
7737 }
7738 }
7739 }
7740 return 0;
7741}
7742
8b7209fa
RH
7743/* Advanced SIMD three registers of the same length extension.
7744 * 31 25 23 22 20 16 12 11 10 9 8 3 0
7745 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7746 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7747 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7748 */
7749static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
7750{
7751 gen_helper_gvec_3_ptr *fn_gvec_ptr;
7752 int rd, rn, rm, rot, size, opr_sz;
7753 TCGv_ptr fpst;
7754 bool q;
7755
7756 q = extract32(insn, 6, 1);
7757 VFP_DREG_D(rd, insn);
7758 VFP_DREG_N(rn, insn);
7759 VFP_DREG_M(rm, insn);
7760 if ((rd | rn | rm) & q) {
7761 return 1;
7762 }
7763
7764 if ((insn & 0xfe200f10) == 0xfc200800) {
7765 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
7766 size = extract32(insn, 20, 1);
7767 rot = extract32(insn, 23, 2);
7768 if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
7769 || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
7770 return 1;
7771 }
7772 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
7773 } else if ((insn & 0xfea00f10) == 0xfc800800) {
7774 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
7775 size = extract32(insn, 20, 1);
7776 rot = extract32(insn, 24, 1);
7777 if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
7778 || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
7779 return 1;
7780 }
7781 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
7782 } else {
7783 return 1;
7784 }
7785
7786 if (s->fp_excp_el) {
7787 gen_exception_insn(s, 4, EXCP_UDEF,
7788 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
7789 return 0;
7790 }
7791 if (!s->vfp_enabled) {
7792 return 1;
7793 }
7794
7795 opr_sz = (1 + q) * 8;
7796 fpst = get_fpstatus_ptr(1);
7797 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
7798 vfp_reg_offset(1, rn),
7799 vfp_reg_offset(1, rm), fpst,
7800 opr_sz, opr_sz, rot, fn_gvec_ptr);
7801 tcg_temp_free_ptr(fpst);
7802 return 0;
7803}
7804
638808ff
RH
7805/* Advanced SIMD two registers and a scalar extension.
7806 * 31 24 23 22 20 16 12 11 10 9 8 3 0
7807 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7808 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7809 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7810 *
7811 */
7812
7813static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
7814{
7815 int rd, rn, rm, rot, size, opr_sz;
7816 TCGv_ptr fpst;
7817 bool q;
7818
7819 q = extract32(insn, 6, 1);
7820 VFP_DREG_D(rd, insn);
7821 VFP_DREG_N(rn, insn);
7822 VFP_DREG_M(rm, insn);
7823 if ((rd | rn) & q) {
7824 return 1;
7825 }
7826
7827 if ((insn & 0xff000f10) == 0xfe000800) {
7828 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
7829 rot = extract32(insn, 20, 2);
7830 size = extract32(insn, 23, 1);
7831 if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)
7832 || (!size && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))) {
7833 return 1;
7834 }
7835 } else {
7836 return 1;
7837 }
7838
7839 if (s->fp_excp_el) {
7840 gen_exception_insn(s, 4, EXCP_UDEF,
7841 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
7842 return 0;
7843 }
7844 if (!s->vfp_enabled) {
7845 return 1;
7846 }
7847
7848 opr_sz = (1 + q) * 8;
7849 fpst = get_fpstatus_ptr(1);
7850 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
7851 vfp_reg_offset(1, rn),
7852 vfp_reg_offset(1, rm), fpst,
7853 opr_sz, opr_sz, rot,
7854 size ? gen_helper_gvec_fcmlas_idx
7855 : gen_helper_gvec_fcmlah_idx);
7856 tcg_temp_free_ptr(fpst);
7857 return 0;
7858}
7859
7dcc1f89 7860static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 7861{
4b6a83fb
PM
7862 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7863 const ARMCPRegInfo *ri;
9ee6e8bb
PB
7864
7865 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
7866
7867 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 7868 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
7869 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7870 return 1;
7871 }
d614a513 7872 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 7873 return disas_iwmmxt_insn(s, insn);
d614a513 7874 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 7875 return disas_dsp_insn(s, insn);
c0f4af17
PM
7876 }
7877 return 1;
4b6a83fb
PM
7878 }
7879
7880 /* Otherwise treat as a generic register access */
7881 is64 = (insn & (1 << 25)) == 0;
7882 if (!is64 && ((insn & (1 << 4)) == 0)) {
7883 /* cdp */
7884 return 1;
7885 }
7886
7887 crm = insn & 0xf;
7888 if (is64) {
7889 crn = 0;
7890 opc1 = (insn >> 4) & 0xf;
7891 opc2 = 0;
7892 rt2 = (insn >> 16) & 0xf;
7893 } else {
7894 crn = (insn >> 16) & 0xf;
7895 opc1 = (insn >> 21) & 7;
7896 opc2 = (insn >> 5) & 7;
7897 rt2 = 0;
7898 }
7899 isread = (insn >> 20) & 1;
7900 rt = (insn >> 12) & 0xf;
7901
60322b39 7902 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 7903 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
7904 if (ri) {
7905 /* Check access permissions */
dcbff19b 7906 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
7907 return 1;
7908 }
7909
c0f4af17 7910 if (ri->accessfn ||
d614a513 7911 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
7912 /* Emit code to perform further access permissions checks at
7913 * runtime; this may result in an exception.
c0f4af17
PM
7914 * Note that on XScale all cp0..c13 registers do an access check
7915 * call in order to handle c15_cpar.
f59df3f2
PM
7916 */
7917 TCGv_ptr tmpptr;
3f208fd7 7918 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
7919 uint32_t syndrome;
7920
7921 /* Note that since we are an implementation which takes an
7922 * exception on a trapped conditional instruction only if the
7923 * instruction passes its condition code check, we can take
7924 * advantage of the clause in the ARM ARM that allows us to set
7925 * the COND field in the instruction to 0xE in all cases.
7926 * We could fish the actual condition out of the insn (ARM)
7927 * or the condexec bits (Thumb) but it isn't necessary.
7928 */
7929 switch (cpnum) {
7930 case 14:
7931 if (is64) {
7932 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7933 isread, false);
8bcbf37c
PM
7934 } else {
7935 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7936 rt, isread, false);
8bcbf37c
PM
7937 }
7938 break;
7939 case 15:
7940 if (is64) {
7941 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7942 isread, false);
8bcbf37c
PM
7943 } else {
7944 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7945 rt, isread, false);
8bcbf37c
PM
7946 }
7947 break;
7948 default:
7949 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7950 * so this can only happen if this is an ARMv7 or earlier CPU,
7951 * in which case the syndrome information won't actually be
7952 * guest visible.
7953 */
d614a513 7954 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7955 syndrome = syn_uncategorized();
7956 break;
7957 }
7958
43bfa4a1 7959 gen_set_condexec(s);
3977ee5d 7960 gen_set_pc_im(s, s->pc - 4);
f59df3f2 7961 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7962 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7963 tcg_isread = tcg_const_i32(isread);
7964 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7965 tcg_isread);
f59df3f2 7966 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7967 tcg_temp_free_i32(tcg_syn);
3f208fd7 7968 tcg_temp_free_i32(tcg_isread);
f59df3f2
PM
7969 }
7970
4b6a83fb
PM
7971 /* Handle special cases first */
7972 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7973 case ARM_CP_NOP:
7974 return 0;
7975 case ARM_CP_WFI:
7976 if (isread) {
7977 return 1;
7978 }
eaed129d 7979 gen_set_pc_im(s, s->pc);
dcba3a8d 7980 s->base.is_jmp = DISAS_WFI;
2bee5105 7981 return 0;
4b6a83fb
PM
7982 default:
7983 break;
7984 }
7985
c5a49c63 7986 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7987 gen_io_start();
7988 }
7989
4b6a83fb
PM
7990 if (isread) {
7991 /* Read */
7992 if (is64) {
7993 TCGv_i64 tmp64;
7994 TCGv_i32 tmp;
7995 if (ri->type & ARM_CP_CONST) {
7996 tmp64 = tcg_const_i64(ri->resetvalue);
7997 } else if (ri->readfn) {
7998 TCGv_ptr tmpptr;
4b6a83fb
PM
7999 tmp64 = tcg_temp_new_i64();
8000 tmpptr = tcg_const_ptr(ri);
8001 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8002 tcg_temp_free_ptr(tmpptr);
8003 } else {
8004 tmp64 = tcg_temp_new_i64();
8005 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8006 }
8007 tmp = tcg_temp_new_i32();
ecc7b3aa 8008 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb
PM
8009 store_reg(s, rt, tmp);
8010 tcg_gen_shri_i64(tmp64, tmp64, 32);
ed336850 8011 tmp = tcg_temp_new_i32();
ecc7b3aa 8012 tcg_gen_extrl_i64_i32(tmp, tmp64);
ed336850 8013 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
8014 store_reg(s, rt2, tmp);
8015 } else {
39d5492a 8016 TCGv_i32 tmp;
4b6a83fb
PM
8017 if (ri->type & ARM_CP_CONST) {
8018 tmp = tcg_const_i32(ri->resetvalue);
8019 } else if (ri->readfn) {
8020 TCGv_ptr tmpptr;
4b6a83fb
PM
8021 tmp = tcg_temp_new_i32();
8022 tmpptr = tcg_const_ptr(ri);
8023 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8024 tcg_temp_free_ptr(tmpptr);
8025 } else {
8026 tmp = load_cpu_offset(ri->fieldoffset);
8027 }
8028 if (rt == 15) {
8029 /* Destination register of r15 for 32 bit loads sets
8030 * the condition codes from the high 4 bits of the value
8031 */
8032 gen_set_nzcv(tmp);
8033 tcg_temp_free_i32(tmp);
8034 } else {
8035 store_reg(s, rt, tmp);
8036 }
8037 }
8038 } else {
8039 /* Write */
8040 if (ri->type & ARM_CP_CONST) {
8041 /* If not forbidden by access permissions, treat as WI */
8042 return 0;
8043 }
8044
8045 if (is64) {
39d5492a 8046 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
8047 TCGv_i64 tmp64 = tcg_temp_new_i64();
8048 tmplo = load_reg(s, rt);
8049 tmphi = load_reg(s, rt2);
8050 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8051 tcg_temp_free_i32(tmplo);
8052 tcg_temp_free_i32(tmphi);
8053 if (ri->writefn) {
8054 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
8055 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8056 tcg_temp_free_ptr(tmpptr);
8057 } else {
8058 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8059 }
8060 tcg_temp_free_i64(tmp64);
8061 } else {
8062 if (ri->writefn) {
39d5492a 8063 TCGv_i32 tmp;
4b6a83fb 8064 TCGv_ptr tmpptr;
4b6a83fb
PM
8065 tmp = load_reg(s, rt);
8066 tmpptr = tcg_const_ptr(ri);
8067 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8068 tcg_temp_free_ptr(tmpptr);
8069 tcg_temp_free_i32(tmp);
8070 } else {
39d5492a 8071 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
8072 store_cpu_offset(tmp, ri->fieldoffset);
8073 }
8074 }
2452731c
PM
8075 }
8076
c5a49c63 8077 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
8078 /* I/O operations must end the TB here (whether read or write) */
8079 gen_io_end();
8080 gen_lookup_tb(s);
8081 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
8082 /* We default to ending the TB on a coprocessor register write,
8083 * but allow this to be suppressed by the register definition
8084 * (usually only necessary to work around guest bugs).
8085 */
2452731c 8086 gen_lookup_tb(s);
4b6a83fb 8087 }
2452731c 8088
4b6a83fb
PM
8089 return 0;
8090 }
8091
626187d8
PM
8092 /* Unknown register; this might be a guest error or a QEMU
8093 * unimplemented feature.
8094 */
8095 if (is64) {
8096 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
8097 "64 bit system register cp:%d opc1: %d crm:%d "
8098 "(%s)\n",
8099 isread ? "read" : "write", cpnum, opc1, crm,
8100 s->ns ? "non-secure" : "secure");
626187d8
PM
8101 } else {
8102 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
8103 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8104 "(%s)\n",
8105 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8106 s->ns ? "non-secure" : "secure");
626187d8
PM
8107 }
8108
4a9a539f 8109 return 1;
9ee6e8bb
PB
8110}
8111
5e3f878a
PB
8112
8113/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 8114static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 8115{
39d5492a 8116 TCGv_i32 tmp;
7d1b0095 8117 tmp = tcg_temp_new_i32();
ecc7b3aa 8118 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 8119 store_reg(s, rlow, tmp);
7d1b0095 8120 tmp = tcg_temp_new_i32();
5e3f878a 8121 tcg_gen_shri_i64(val, val, 32);
ecc7b3aa 8122 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a
PB
8123 store_reg(s, rhigh, tmp);
8124}
8125
8126/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 8127static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 8128{
a7812ae4 8129 TCGv_i64 tmp;
39d5492a 8130 TCGv_i32 tmp2;
5e3f878a 8131
36aa55dc 8132 /* Load value and extend to 64 bits. */
a7812ae4 8133 tmp = tcg_temp_new_i64();
5e3f878a
PB
8134 tmp2 = load_reg(s, rlow);
8135 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 8136 tcg_temp_free_i32(tmp2);
5e3f878a 8137 tcg_gen_add_i64(val, val, tmp);
b75263d6 8138 tcg_temp_free_i64(tmp);
5e3f878a
PB
8139}
8140
8141/* load and add a 64-bit value from a register pair. */
a7812ae4 8142static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 8143{
a7812ae4 8144 TCGv_i64 tmp;
39d5492a
PM
8145 TCGv_i32 tmpl;
8146 TCGv_i32 tmph;
5e3f878a
PB
8147
8148 /* Load 64-bit value rd:rn. */
36aa55dc
PB
8149 tmpl = load_reg(s, rlow);
8150 tmph = load_reg(s, rhigh);
a7812ae4 8151 tmp = tcg_temp_new_i64();
36aa55dc 8152 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
8153 tcg_temp_free_i32(tmpl);
8154 tcg_temp_free_i32(tmph);
5e3f878a 8155 tcg_gen_add_i64(val, val, tmp);
b75263d6 8156 tcg_temp_free_i64(tmp);
5e3f878a
PB
8157}
8158
c9f10124 8159/* Set N and Z flags from hi|lo. */
39d5492a 8160static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 8161{
c9f10124
RH
8162 tcg_gen_mov_i32(cpu_NF, hi);
8163 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
8164}
8165
426f5abc
PB
8166/* Load/Store exclusive instructions are implemented by remembering
8167 the value/address loaded, and seeing if these are the same
354161b3 8168 when the store is performed. This should be sufficient to implement
426f5abc 8169 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
8170 regular stores. The compare vs the remembered value is done during
8171 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 8172static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 8173 TCGv_i32 addr, int size)
426f5abc 8174{
94ee24e7 8175 TCGv_i32 tmp = tcg_temp_new_i32();
354161b3 8176 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 8177
50225ad0
PM
8178 s->is_ldex = true;
8179
426f5abc 8180 if (size == 3) {
39d5492a 8181 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 8182 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 8183
3448d47b
PM
8184 /* For AArch32, architecturally the 32-bit word at the lowest
8185 * address is always Rt and the one at addr+4 is Rt2, even if
8186 * the CPU is big-endian. That means we don't want to do a
8187 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8188 * for an architecturally 64-bit access, but instead do a
8189 * 64-bit access using MO_BE if appropriate and then split
8190 * the two halves.
8191 * This only makes a difference for BE32 user-mode, where
8192 * frob64() must not flip the two halves of the 64-bit data
8193 * but this code must treat BE32 user-mode like BE32 system.
8194 */
8195 TCGv taddr = gen_aa32_addr(s, addr, opc);
8196
8197 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8198 tcg_temp_free(taddr);
354161b3 8199 tcg_gen_mov_i64(cpu_exclusive_val, t64);
3448d47b
PM
8200 if (s->be_data == MO_BE) {
8201 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8202 } else {
8203 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8204 }
354161b3
EC
8205 tcg_temp_free_i64(t64);
8206
8207 store_reg(s, rt2, tmp2);
03d05e2d 8208 } else {
354161b3 8209 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 8210 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 8211 }
03d05e2d
PM
8212
8213 store_reg(s, rt, tmp);
8214 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
8215}
8216
8217static void gen_clrex(DisasContext *s)
8218{
03d05e2d 8219 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
8220}
8221
426f5abc 8222static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 8223 TCGv_i32 addr, int size)
426f5abc 8224{
354161b3
EC
8225 TCGv_i32 t0, t1, t2;
8226 TCGv_i64 extaddr;
8227 TCGv taddr;
42a268c2
RH
8228 TCGLabel *done_label;
8229 TCGLabel *fail_label;
354161b3 8230 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
8231
8232 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8233 [addr] = {Rt};
8234 {Rd} = 0;
8235 } else {
8236 {Rd} = 1;
8237 } */
8238 fail_label = gen_new_label();
8239 done_label = gen_new_label();
03d05e2d
PM
8240 extaddr = tcg_temp_new_i64();
8241 tcg_gen_extu_i32_i64(extaddr, addr);
8242 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8243 tcg_temp_free_i64(extaddr);
8244
354161b3
EC
8245 taddr = gen_aa32_addr(s, addr, opc);
8246 t0 = tcg_temp_new_i32();
8247 t1 = load_reg(s, rt);
426f5abc 8248 if (size == 3) {
354161b3
EC
8249 TCGv_i64 o64 = tcg_temp_new_i64();
8250 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 8251
354161b3 8252 t2 = load_reg(s, rt2);
3448d47b
PM
8253 /* For AArch32, architecturally the 32-bit word at the lowest
8254 * address is always Rt and the one at addr+4 is Rt2, even if
8255 * the CPU is big-endian. Since we're going to treat this as a
8256 * single 64-bit BE store, we need to put the two halves in the
8257 * opposite order for BE to LE, so that they end up in the right
8258 * places.
8259 * We don't want gen_aa32_frob64() because that does the wrong
8260 * thing for BE32 usermode.
8261 */
8262 if (s->be_data == MO_BE) {
8263 tcg_gen_concat_i32_i64(n64, t2, t1);
8264 } else {
8265 tcg_gen_concat_i32_i64(n64, t1, t2);
8266 }
354161b3 8267 tcg_temp_free_i32(t2);
03d05e2d 8268
354161b3
EC
8269 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
8270 get_mem_index(s), opc);
8271 tcg_temp_free_i64(n64);
8272
354161b3
EC
8273 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
8274 tcg_gen_extrl_i64_i32(t0, o64);
8275
8276 tcg_temp_free_i64(o64);
8277 } else {
8278 t2 = tcg_temp_new_i32();
8279 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
8280 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
8281 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
8282 tcg_temp_free_i32(t2);
426f5abc 8283 }
354161b3
EC
8284 tcg_temp_free_i32(t1);
8285 tcg_temp_free(taddr);
8286 tcg_gen_mov_i32(cpu_R[rd], t0);
8287 tcg_temp_free_i32(t0);
426f5abc 8288 tcg_gen_br(done_label);
354161b3 8289
426f5abc
PB
8290 gen_set_label(fail_label);
8291 tcg_gen_movi_i32(cpu_R[rd], 1);
8292 gen_set_label(done_label);
03d05e2d 8293 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 8294}
426f5abc 8295
81465888
PM
8296/* gen_srs:
8297 * @env: CPUARMState
8298 * @s: DisasContext
8299 * @mode: mode field from insn (which stack to store to)
8300 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
8301 * @writeback: true if writeback bit set
8302 *
8303 * Generate code for the SRS (Store Return State) insn.
8304 */
8305static void gen_srs(DisasContext *s,
8306 uint32_t mode, uint32_t amode, bool writeback)
8307{
8308 int32_t offset;
cbc0326b
PM
8309 TCGv_i32 addr, tmp;
8310 bool undef = false;
8311
8312 /* SRS is:
8313 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 8314 * and specified mode is monitor mode
cbc0326b
PM
8315 * - UNDEFINED in Hyp mode
8316 * - UNPREDICTABLE in User or System mode
8317 * - UNPREDICTABLE if the specified mode is:
8318 * -- not implemented
8319 * -- not a valid mode number
8320 * -- a mode that's at a higher exception level
8321 * -- Monitor, if we are Non-secure
f01377f5 8322 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 8323 */
ba63cf47 8324 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
cbc0326b
PM
8325 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
8326 return;
8327 }
8328
8329 if (s->current_el == 0 || s->current_el == 2) {
8330 undef = true;
8331 }
8332
8333 switch (mode) {
8334 case ARM_CPU_MODE_USR:
8335 case ARM_CPU_MODE_FIQ:
8336 case ARM_CPU_MODE_IRQ:
8337 case ARM_CPU_MODE_SVC:
8338 case ARM_CPU_MODE_ABT:
8339 case ARM_CPU_MODE_UND:
8340 case ARM_CPU_MODE_SYS:
8341 break;
8342 case ARM_CPU_MODE_HYP:
8343 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
8344 undef = true;
8345 }
8346 break;
8347 case ARM_CPU_MODE_MON:
8348 /* No need to check specifically for "are we non-secure" because
8349 * we've already made EL0 UNDEF and handled the trap for S-EL1;
8350 * so if this isn't EL3 then we must be non-secure.
8351 */
8352 if (s->current_el != 3) {
8353 undef = true;
8354 }
8355 break;
8356 default:
8357 undef = true;
8358 }
8359
8360 if (undef) {
8361 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
8362 default_exception_el(s));
8363 return;
8364 }
8365
8366 addr = tcg_temp_new_i32();
8367 tmp = tcg_const_i32(mode);
f01377f5
PM
8368 /* get_r13_banked() will raise an exception if called from System mode */
8369 gen_set_condexec(s);
8370 gen_set_pc_im(s, s->pc - 4);
81465888
PM
8371 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8372 tcg_temp_free_i32(tmp);
8373 switch (amode) {
8374 case 0: /* DA */
8375 offset = -4;
8376 break;
8377 case 1: /* IA */
8378 offset = 0;
8379 break;
8380 case 2: /* DB */
8381 offset = -8;
8382 break;
8383 case 3: /* IB */
8384 offset = 4;
8385 break;
8386 default:
8387 abort();
8388 }
8389 tcg_gen_addi_i32(addr, addr, offset);
8390 tmp = load_reg(s, 14);
12dcc321 8391 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8392 tcg_temp_free_i32(tmp);
81465888
PM
8393 tmp = load_cpu_field(spsr);
8394 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 8395 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8396 tcg_temp_free_i32(tmp);
81465888
PM
8397 if (writeback) {
8398 switch (amode) {
8399 case 0:
8400 offset = -8;
8401 break;
8402 case 1:
8403 offset = 4;
8404 break;
8405 case 2:
8406 offset = -4;
8407 break;
8408 case 3:
8409 offset = 0;
8410 break;
8411 default:
8412 abort();
8413 }
8414 tcg_gen_addi_i32(addr, addr, offset);
8415 tmp = tcg_const_i32(mode);
8416 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8417 tcg_temp_free_i32(tmp);
8418 }
8419 tcg_temp_free_i32(addr);
dcba3a8d 8420 s->base.is_jmp = DISAS_UPDATE;
81465888
PM
8421}
8422
f4df2210 8423static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 8424{
f4df2210 8425 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
8426 TCGv_i32 tmp;
8427 TCGv_i32 tmp2;
8428 TCGv_i32 tmp3;
8429 TCGv_i32 addr;
a7812ae4 8430 TCGv_i64 tmp64;
9ee6e8bb 8431
e13886e3
PM
8432 /* M variants do not implement ARM mode; this must raise the INVSTATE
8433 * UsageFault exception.
8434 */
b53d8923 8435 if (arm_dc_feature(s, ARM_FEATURE_M)) {
e13886e3
PM
8436 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
8437 default_exception_el(s));
8438 return;
b53d8923 8439 }
9ee6e8bb
PB
8440 cond = insn >> 28;
8441 if (cond == 0xf){
be5e7a76
DES
8442 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8443 * choose to UNDEF. In ARMv5 and above the space is used
8444 * for miscellaneous unconditional instructions.
8445 */
8446 ARCH(5);
8447
9ee6e8bb
PB
8448 /* Unconditional instructions. */
8449 if (((insn >> 25) & 7) == 1) {
8450 /* NEON Data processing. */
d614a513 8451 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 8452 goto illegal_op;
d614a513 8453 }
9ee6e8bb 8454
7dcc1f89 8455 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 8456 goto illegal_op;
7dcc1f89 8457 }
9ee6e8bb
PB
8458 return;
8459 }
8460 if ((insn & 0x0f100000) == 0x04000000) {
8461 /* NEON load/store. */
d614a513 8462 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 8463 goto illegal_op;
d614a513 8464 }
9ee6e8bb 8465
7dcc1f89 8466 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 8467 goto illegal_op;
7dcc1f89 8468 }
9ee6e8bb
PB
8469 return;
8470 }
6a57f3eb
WN
8471 if ((insn & 0x0f000e10) == 0x0e000a00) {
8472 /* VFP. */
7dcc1f89 8473 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
8474 goto illegal_op;
8475 }
8476 return;
8477 }
3d185e5d
PM
8478 if (((insn & 0x0f30f000) == 0x0510f000) ||
8479 ((insn & 0x0f30f010) == 0x0710f000)) {
8480 if ((insn & (1 << 22)) == 0) {
8481 /* PLDW; v7MP */
d614a513 8482 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
8483 goto illegal_op;
8484 }
8485 }
8486 /* Otherwise PLD; v5TE+ */
be5e7a76 8487 ARCH(5TE);
3d185e5d
PM
8488 return;
8489 }
8490 if (((insn & 0x0f70f000) == 0x0450f000) ||
8491 ((insn & 0x0f70f010) == 0x0650f000)) {
8492 ARCH(7);
8493 return; /* PLI; V7 */
8494 }
8495 if (((insn & 0x0f700000) == 0x04100000) ||
8496 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 8497 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
8498 goto illegal_op;
8499 }
8500 return; /* v7MP: Unallocated memory hint: must NOP */
8501 }
8502
8503 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
8504 ARCH(6);
8505 /* setend */
9886ecdf
PB
8506 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
8507 gen_helper_setend(cpu_env);
dcba3a8d 8508 s->base.is_jmp = DISAS_UPDATE;
9ee6e8bb
PB
8509 }
8510 return;
8511 } else if ((insn & 0x0fffff00) == 0x057ff000) {
8512 switch ((insn >> 4) & 0xf) {
8513 case 1: /* clrex */
8514 ARCH(6K);
426f5abc 8515 gen_clrex(s);
9ee6e8bb
PB
8516 return;
8517 case 4: /* dsb */
8518 case 5: /* dmb */
9ee6e8bb 8519 ARCH(7);
61e4c432 8520 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 8521 return;
6df99dec
SS
8522 case 6: /* isb */
8523 /* We need to break the TB after this insn to execute
8524 * self-modifying code correctly and also to take
8525 * any pending interrupts immediately.
8526 */
0b609cc1 8527 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 8528 return;
9ee6e8bb
PB
8529 default:
8530 goto illegal_op;
8531 }
8532 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
8533 /* srs */
81465888
PM
8534 ARCH(6);
8535 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 8536 return;
ea825eee 8537 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 8538 /* rfe */
c67b6b71 8539 int32_t offset;
9ee6e8bb
PB
8540 if (IS_USER(s))
8541 goto illegal_op;
8542 ARCH(6);
8543 rn = (insn >> 16) & 0xf;
b0109805 8544 addr = load_reg(s, rn);
9ee6e8bb
PB
8545 i = (insn >> 23) & 3;
8546 switch (i) {
b0109805 8547 case 0: offset = -4; break; /* DA */
c67b6b71
FN
8548 case 1: offset = 0; break; /* IA */
8549 case 2: offset = -8; break; /* DB */
b0109805 8550 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
8551 default: abort();
8552 }
8553 if (offset)
b0109805
PB
8554 tcg_gen_addi_i32(addr, addr, offset);
8555 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 8556 tmp = tcg_temp_new_i32();
12dcc321 8557 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 8558 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8559 tmp2 = tcg_temp_new_i32();
12dcc321 8560 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
8561 if (insn & (1 << 21)) {
8562 /* Base writeback. */
8563 switch (i) {
b0109805 8564 case 0: offset = -8; break;
c67b6b71
FN
8565 case 1: offset = 4; break;
8566 case 2: offset = -4; break;
b0109805 8567 case 3: offset = 0; break;
9ee6e8bb
PB
8568 default: abort();
8569 }
8570 if (offset)
b0109805
PB
8571 tcg_gen_addi_i32(addr, addr, offset);
8572 store_reg(s, rn, addr);
8573 } else {
7d1b0095 8574 tcg_temp_free_i32(addr);
9ee6e8bb 8575 }
b0109805 8576 gen_rfe(s, tmp, tmp2);
c67b6b71 8577 return;
9ee6e8bb
PB
8578 } else if ((insn & 0x0e000000) == 0x0a000000) {
8579 /* branch link and change to thumb (blx <offset>) */
8580 int32_t offset;
8581
8582 val = (uint32_t)s->pc;
7d1b0095 8583 tmp = tcg_temp_new_i32();
d9ba4830
PB
8584 tcg_gen_movi_i32(tmp, val);
8585 store_reg(s, 14, tmp);
9ee6e8bb
PB
8586 /* Sign-extend the 24-bit offset */
8587 offset = (((int32_t)insn) << 8) >> 8;
8588 /* offset * 4 + bit24 * 2 + (thumb bit) */
8589 val += (offset << 2) | ((insn >> 23) & 2) | 1;
8590 /* pipeline offset */
8591 val += 4;
be5e7a76 8592 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 8593 gen_bx_im(s, val);
9ee6e8bb
PB
8594 return;
8595 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 8596 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 8597 /* iWMMXt register transfer. */
c0f4af17 8598 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 8599 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 8600 return;
c0f4af17
PM
8601 }
8602 }
9ee6e8bb 8603 }
8b7209fa
RH
8604 } else if ((insn & 0x0e000a00) == 0x0c000800
8605 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8606 if (disas_neon_insn_3same_ext(s, insn)) {
8607 goto illegal_op;
8608 }
8609 return;
638808ff
RH
8610 } else if ((insn & 0x0f000a00) == 0x0e000800
8611 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8612 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
8613 goto illegal_op;
8614 }
8615 return;
9ee6e8bb
PB
8616 } else if ((insn & 0x0fe00000) == 0x0c400000) {
8617 /* Coprocessor double register transfer. */
be5e7a76 8618 ARCH(5TE);
9ee6e8bb
PB
8619 } else if ((insn & 0x0f000010) == 0x0e000010) {
8620 /* Additional coprocessor register transfer. */
7997d92f 8621 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
8622 uint32_t mask;
8623 uint32_t val;
8624 /* cps (privileged) */
8625 if (IS_USER(s))
8626 return;
8627 mask = val = 0;
8628 if (insn & (1 << 19)) {
8629 if (insn & (1 << 8))
8630 mask |= CPSR_A;
8631 if (insn & (1 << 7))
8632 mask |= CPSR_I;
8633 if (insn & (1 << 6))
8634 mask |= CPSR_F;
8635 if (insn & (1 << 18))
8636 val |= mask;
8637 }
7997d92f 8638 if (insn & (1 << 17)) {
9ee6e8bb
PB
8639 mask |= CPSR_M;
8640 val |= (insn & 0x1f);
8641 }
8642 if (mask) {
2fbac54b 8643 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
8644 }
8645 return;
8646 }
8647 goto illegal_op;
8648 }
8649 if (cond != 0xe) {
8650 /* if not always execute, we generate a conditional jump to
8651 next instruction */
8652 s->condlabel = gen_new_label();
39fb730a 8653 arm_gen_test_cc(cond ^ 1, s->condlabel);
9ee6e8bb
PB
8654 s->condjmp = 1;
8655 }
8656 if ((insn & 0x0f900000) == 0x03000000) {
8657 if ((insn & (1 << 21)) == 0) {
8658 ARCH(6T2);
8659 rd = (insn >> 12) & 0xf;
8660 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
8661 if ((insn & (1 << 22)) == 0) {
8662 /* MOVW */
7d1b0095 8663 tmp = tcg_temp_new_i32();
5e3f878a 8664 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
8665 } else {
8666 /* MOVT */
5e3f878a 8667 tmp = load_reg(s, rd);
86831435 8668 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 8669 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 8670 }
5e3f878a 8671 store_reg(s, rd, tmp);
9ee6e8bb
PB
8672 } else {
8673 if (((insn >> 12) & 0xf) != 0xf)
8674 goto illegal_op;
8675 if (((insn >> 16) & 0xf) == 0) {
8676 gen_nop_hint(s, insn & 0xff);
8677 } else {
8678 /* CPSR = immediate */
8679 val = insn & 0xff;
8680 shift = ((insn >> 8) & 0xf) * 2;
8681 if (shift)
8682 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 8683 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
8684 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
8685 i, val)) {
9ee6e8bb 8686 goto illegal_op;
7dcc1f89 8687 }
9ee6e8bb
PB
8688 }
8689 }
8690 } else if ((insn & 0x0f900000) == 0x01000000
8691 && (insn & 0x00000090) != 0x00000090) {
8692 /* miscellaneous instructions */
8693 op1 = (insn >> 21) & 3;
8694 sh = (insn >> 4) & 0xf;
8695 rm = insn & 0xf;
8696 switch (sh) {
8bfd0550
PM
8697 case 0x0: /* MSR, MRS */
8698 if (insn & (1 << 9)) {
8699 /* MSR (banked) and MRS (banked) */
8700 int sysm = extract32(insn, 16, 4) |
8701 (extract32(insn, 8, 1) << 4);
8702 int r = extract32(insn, 22, 1);
8703
8704 if (op1 & 1) {
8705 /* MSR (banked) */
8706 gen_msr_banked(s, r, sysm, rm);
8707 } else {
8708 /* MRS (banked) */
8709 int rd = extract32(insn, 12, 4);
8710
8711 gen_mrs_banked(s, r, sysm, rd);
8712 }
8713 break;
8714 }
8715
8716 /* MSR, MRS (for PSRs) */
9ee6e8bb
PB
8717 if (op1 & 1) {
8718 /* PSR = reg */
2fbac54b 8719 tmp = load_reg(s, rm);
9ee6e8bb 8720 i = ((op1 & 2) != 0);
7dcc1f89 8721 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
8722 goto illegal_op;
8723 } else {
8724 /* reg = PSR */
8725 rd = (insn >> 12) & 0xf;
8726 if (op1 & 2) {
8727 if (IS_USER(s))
8728 goto illegal_op;
d9ba4830 8729 tmp = load_cpu_field(spsr);
9ee6e8bb 8730 } else {
7d1b0095 8731 tmp = tcg_temp_new_i32();
9ef39277 8732 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 8733 }
d9ba4830 8734 store_reg(s, rd, tmp);
9ee6e8bb
PB
8735 }
8736 break;
8737 case 0x1:
8738 if (op1 == 1) {
8739 /* branch/exchange thumb (bx). */
be5e7a76 8740 ARCH(4T);
d9ba4830
PB
8741 tmp = load_reg(s, rm);
8742 gen_bx(s, tmp);
9ee6e8bb
PB
8743 } else if (op1 == 3) {
8744 /* clz */
be5e7a76 8745 ARCH(5);
9ee6e8bb 8746 rd = (insn >> 12) & 0xf;
1497c961 8747 tmp = load_reg(s, rm);
7539a012 8748 tcg_gen_clzi_i32(tmp, tmp, 32);
1497c961 8749 store_reg(s, rd, tmp);
9ee6e8bb
PB
8750 } else {
8751 goto illegal_op;
8752 }
8753 break;
8754 case 0x2:
8755 if (op1 == 1) {
8756 ARCH(5J); /* bxj */
8757 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
8758 tmp = load_reg(s, rm);
8759 gen_bx(s, tmp);
9ee6e8bb
PB
8760 } else {
8761 goto illegal_op;
8762 }
8763 break;
8764 case 0x3:
8765 if (op1 != 1)
8766 goto illegal_op;
8767
be5e7a76 8768 ARCH(5);
9ee6e8bb 8769 /* branch link/exchange thumb (blx) */
d9ba4830 8770 tmp = load_reg(s, rm);
7d1b0095 8771 tmp2 = tcg_temp_new_i32();
d9ba4830
PB
8772 tcg_gen_movi_i32(tmp2, s->pc);
8773 store_reg(s, 14, tmp2);
8774 gen_bx(s, tmp);
9ee6e8bb 8775 break;
eb0ecd5a
WN
8776 case 0x4:
8777 {
8778 /* crc32/crc32c */
8779 uint32_t c = extract32(insn, 8, 4);
8780
8781 /* Check this CPU supports ARMv8 CRC instructions.
8782 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8783 * Bits 8, 10 and 11 should be zero.
8784 */
d614a513 8785 if (!arm_dc_feature(s, ARM_FEATURE_CRC) || op1 == 0x3 ||
eb0ecd5a
WN
8786 (c & 0xd) != 0) {
8787 goto illegal_op;
8788 }
8789
8790 rn = extract32(insn, 16, 4);
8791 rd = extract32(insn, 12, 4);
8792
8793 tmp = load_reg(s, rn);
8794 tmp2 = load_reg(s, rm);
aa633469
PM
8795 if (op1 == 0) {
8796 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8797 } else if (op1 == 1) {
8798 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8799 }
eb0ecd5a
WN
8800 tmp3 = tcg_const_i32(1 << op1);
8801 if (c & 0x2) {
8802 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8803 } else {
8804 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8805 }
8806 tcg_temp_free_i32(tmp2);
8807 tcg_temp_free_i32(tmp3);
8808 store_reg(s, rd, tmp);
8809 break;
8810 }
9ee6e8bb 8811 case 0x5: /* saturating add/subtract */
be5e7a76 8812 ARCH(5TE);
9ee6e8bb
PB
8813 rd = (insn >> 12) & 0xf;
8814 rn = (insn >> 16) & 0xf;
b40d0353 8815 tmp = load_reg(s, rm);
5e3f878a 8816 tmp2 = load_reg(s, rn);
9ee6e8bb 8817 if (op1 & 2)
9ef39277 8818 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9ee6e8bb 8819 if (op1 & 1)
9ef39277 8820 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 8821 else
9ef39277 8822 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 8823 tcg_temp_free_i32(tmp2);
5e3f878a 8824 store_reg(s, rd, tmp);
9ee6e8bb 8825 break;
49e14940 8826 case 7:
d4a2dc67
PM
8827 {
8828 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e 8829 switch (op1) {
19a6e31c
PM
8830 case 0:
8831 /* HLT */
8832 gen_hlt(s, imm16);
8833 break;
37e6456e
PM
8834 case 1:
8835 /* bkpt */
8836 ARCH(5);
c900a2e6 8837 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
37e6456e
PM
8838 break;
8839 case 2:
8840 /* Hypervisor call (v7) */
8841 ARCH(7);
8842 if (IS_USER(s)) {
8843 goto illegal_op;
8844 }
8845 gen_hvc(s, imm16);
8846 break;
8847 case 3:
8848 /* Secure monitor call (v6+) */
8849 ARCH(6K);
8850 if (IS_USER(s)) {
8851 goto illegal_op;
8852 }
8853 gen_smc(s);
8854 break;
8855 default:
19a6e31c 8856 g_assert_not_reached();
49e14940 8857 }
9ee6e8bb 8858 break;
d4a2dc67 8859 }
9ee6e8bb
PB
8860 case 0x8: /* signed multiply */
8861 case 0xa:
8862 case 0xc:
8863 case 0xe:
be5e7a76 8864 ARCH(5TE);
9ee6e8bb
PB
8865 rs = (insn >> 8) & 0xf;
8866 rn = (insn >> 12) & 0xf;
8867 rd = (insn >> 16) & 0xf;
8868 if (op1 == 1) {
8869 /* (32 * 16) >> 16 */
5e3f878a
PB
8870 tmp = load_reg(s, rm);
8871 tmp2 = load_reg(s, rs);
9ee6e8bb 8872 if (sh & 4)
5e3f878a 8873 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 8874 else
5e3f878a 8875 gen_sxth(tmp2);
a7812ae4
PB
8876 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8877 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 8878 tmp = tcg_temp_new_i32();
ecc7b3aa 8879 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 8880 tcg_temp_free_i64(tmp64);
9ee6e8bb 8881 if ((sh & 2) == 0) {
5e3f878a 8882 tmp2 = load_reg(s, rn);
9ef39277 8883 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8884 tcg_temp_free_i32(tmp2);
9ee6e8bb 8885 }
5e3f878a 8886 store_reg(s, rd, tmp);
9ee6e8bb
PB
8887 } else {
8888 /* 16 * 16 */
5e3f878a
PB
8889 tmp = load_reg(s, rm);
8890 tmp2 = load_reg(s, rs);
8891 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 8892 tcg_temp_free_i32(tmp2);
9ee6e8bb 8893 if (op1 == 2) {
a7812ae4
PB
8894 tmp64 = tcg_temp_new_i64();
8895 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 8896 tcg_temp_free_i32(tmp);
a7812ae4
PB
8897 gen_addq(s, tmp64, rn, rd);
8898 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 8899 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
8900 } else {
8901 if (op1 == 0) {
5e3f878a 8902 tmp2 = load_reg(s, rn);
9ef39277 8903 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8904 tcg_temp_free_i32(tmp2);
9ee6e8bb 8905 }
5e3f878a 8906 store_reg(s, rd, tmp);
9ee6e8bb
PB
8907 }
8908 }
8909 break;
8910 default:
8911 goto illegal_op;
8912 }
8913 } else if (((insn & 0x0e000000) == 0 &&
8914 (insn & 0x00000090) != 0x90) ||
8915 ((insn & 0x0e000000) == (1 << 25))) {
8916 int set_cc, logic_cc, shiftop;
8917
8918 op1 = (insn >> 21) & 0xf;
8919 set_cc = (insn >> 20) & 1;
8920 logic_cc = table_logic_cc[op1] & set_cc;
8921
8922 /* data processing instruction */
8923 if (insn & (1 << 25)) {
8924 /* immediate operand */
8925 val = insn & 0xff;
8926 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 8927 if (shift) {
9ee6e8bb 8928 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9 8929 }
7d1b0095 8930 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
8931 tcg_gen_movi_i32(tmp2, val);
8932 if (logic_cc && shift) {
8933 gen_set_CF_bit31(tmp2);
8934 }
9ee6e8bb
PB
8935 } else {
8936 /* register */
8937 rm = (insn) & 0xf;
e9bb4aa9 8938 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8939 shiftop = (insn >> 5) & 3;
8940 if (!(insn & (1 << 4))) {
8941 shift = (insn >> 7) & 0x1f;
e9bb4aa9 8942 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
8943 } else {
8944 rs = (insn >> 8) & 0xf;
8984bd2e 8945 tmp = load_reg(s, rs);
e9bb4aa9 8946 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
8947 }
8948 }
8949 if (op1 != 0x0f && op1 != 0x0d) {
8950 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
8951 tmp = load_reg(s, rn);
8952 } else {
f764718d 8953 tmp = NULL;
9ee6e8bb
PB
8954 }
8955 rd = (insn >> 12) & 0xf;
8956 switch(op1) {
8957 case 0x00:
e9bb4aa9
JR
8958 tcg_gen_and_i32(tmp, tmp, tmp2);
8959 if (logic_cc) {
8960 gen_logic_CC(tmp);
8961 }
7dcc1f89 8962 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8963 break;
8964 case 0x01:
e9bb4aa9
JR
8965 tcg_gen_xor_i32(tmp, tmp, tmp2);
8966 if (logic_cc) {
8967 gen_logic_CC(tmp);
8968 }
7dcc1f89 8969 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8970 break;
8971 case 0x02:
8972 if (set_cc && rd == 15) {
8973 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 8974 if (IS_USER(s)) {
9ee6e8bb 8975 goto illegal_op;
e9bb4aa9 8976 }
72485ec4 8977 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 8978 gen_exception_return(s, tmp);
9ee6e8bb 8979 } else {
e9bb4aa9 8980 if (set_cc) {
72485ec4 8981 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8982 } else {
8983 tcg_gen_sub_i32(tmp, tmp, tmp2);
8984 }
7dcc1f89 8985 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8986 }
8987 break;
8988 case 0x03:
e9bb4aa9 8989 if (set_cc) {
72485ec4 8990 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8991 } else {
8992 tcg_gen_sub_i32(tmp, tmp2, tmp);
8993 }
7dcc1f89 8994 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8995 break;
8996 case 0x04:
e9bb4aa9 8997 if (set_cc) {
72485ec4 8998 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8999 } else {
9000 tcg_gen_add_i32(tmp, tmp, tmp2);
9001 }
7dcc1f89 9002 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9003 break;
9004 case 0x05:
e9bb4aa9 9005 if (set_cc) {
49b4c31e 9006 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9007 } else {
9008 gen_add_carry(tmp, tmp, tmp2);
9009 }
7dcc1f89 9010 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9011 break;
9012 case 0x06:
e9bb4aa9 9013 if (set_cc) {
2de68a49 9014 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9015 } else {
9016 gen_sub_carry(tmp, tmp, tmp2);
9017 }
7dcc1f89 9018 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9019 break;
9020 case 0x07:
e9bb4aa9 9021 if (set_cc) {
2de68a49 9022 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
9023 } else {
9024 gen_sub_carry(tmp, tmp2, tmp);
9025 }
7dcc1f89 9026 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9027 break;
9028 case 0x08:
9029 if (set_cc) {
e9bb4aa9
JR
9030 tcg_gen_and_i32(tmp, tmp, tmp2);
9031 gen_logic_CC(tmp);
9ee6e8bb 9032 }
7d1b0095 9033 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9034 break;
9035 case 0x09:
9036 if (set_cc) {
e9bb4aa9
JR
9037 tcg_gen_xor_i32(tmp, tmp, tmp2);
9038 gen_logic_CC(tmp);
9ee6e8bb 9039 }
7d1b0095 9040 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9041 break;
9042 case 0x0a:
9043 if (set_cc) {
72485ec4 9044 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 9045 }
7d1b0095 9046 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9047 break;
9048 case 0x0b:
9049 if (set_cc) {
72485ec4 9050 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 9051 }
7d1b0095 9052 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9053 break;
9054 case 0x0c:
e9bb4aa9
JR
9055 tcg_gen_or_i32(tmp, tmp, tmp2);
9056 if (logic_cc) {
9057 gen_logic_CC(tmp);
9058 }
7dcc1f89 9059 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9060 break;
9061 case 0x0d:
9062 if (logic_cc && rd == 15) {
9063 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 9064 if (IS_USER(s)) {
9ee6e8bb 9065 goto illegal_op;
e9bb4aa9
JR
9066 }
9067 gen_exception_return(s, tmp2);
9ee6e8bb 9068 } else {
e9bb4aa9
JR
9069 if (logic_cc) {
9070 gen_logic_CC(tmp2);
9071 }
7dcc1f89 9072 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
9073 }
9074 break;
9075 case 0x0e:
f669df27 9076 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
9077 if (logic_cc) {
9078 gen_logic_CC(tmp);
9079 }
7dcc1f89 9080 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9081 break;
9082 default:
9083 case 0x0f:
e9bb4aa9
JR
9084 tcg_gen_not_i32(tmp2, tmp2);
9085 if (logic_cc) {
9086 gen_logic_CC(tmp2);
9087 }
7dcc1f89 9088 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
9089 break;
9090 }
e9bb4aa9 9091 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 9092 tcg_temp_free_i32(tmp2);
e9bb4aa9 9093 }
9ee6e8bb
PB
9094 } else {
9095 /* other instructions */
9096 op1 = (insn >> 24) & 0xf;
9097 switch(op1) {
9098 case 0x0:
9099 case 0x1:
9100 /* multiplies, extra load/stores */
9101 sh = (insn >> 5) & 3;
9102 if (sh == 0) {
9103 if (op1 == 0x0) {
9104 rd = (insn >> 16) & 0xf;
9105 rn = (insn >> 12) & 0xf;
9106 rs = (insn >> 8) & 0xf;
9107 rm = (insn) & 0xf;
9108 op1 = (insn >> 20) & 0xf;
9109 switch (op1) {
9110 case 0: case 1: case 2: case 3: case 6:
9111 /* 32 bit mul */
5e3f878a
PB
9112 tmp = load_reg(s, rs);
9113 tmp2 = load_reg(s, rm);
9114 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 9115 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9116 if (insn & (1 << 22)) {
9117 /* Subtract (mls) */
9118 ARCH(6T2);
5e3f878a
PB
9119 tmp2 = load_reg(s, rn);
9120 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 9121 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9122 } else if (insn & (1 << 21)) {
9123 /* Add */
5e3f878a
PB
9124 tmp2 = load_reg(s, rn);
9125 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9126 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9127 }
9128 if (insn & (1 << 20))
5e3f878a
PB
9129 gen_logic_CC(tmp);
9130 store_reg(s, rd, tmp);
9ee6e8bb 9131 break;
8aac08b1
AJ
9132 case 4:
9133 /* 64 bit mul double accumulate (UMAAL) */
9134 ARCH(6);
9135 tmp = load_reg(s, rs);
9136 tmp2 = load_reg(s, rm);
9137 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9138 gen_addq_lo(s, tmp64, rn);
9139 gen_addq_lo(s, tmp64, rd);
9140 gen_storeq_reg(s, rn, rd, tmp64);
9141 tcg_temp_free_i64(tmp64);
9142 break;
9143 case 8: case 9: case 10: case 11:
9144 case 12: case 13: case 14: case 15:
9145 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
9146 tmp = load_reg(s, rs);
9147 tmp2 = load_reg(s, rm);
8aac08b1 9148 if (insn & (1 << 22)) {
c9f10124 9149 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 9150 } else {
c9f10124 9151 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
9152 }
9153 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
9154 TCGv_i32 al = load_reg(s, rn);
9155 TCGv_i32 ah = load_reg(s, rd);
c9f10124 9156 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
9157 tcg_temp_free_i32(al);
9158 tcg_temp_free_i32(ah);
9ee6e8bb 9159 }
8aac08b1 9160 if (insn & (1 << 20)) {
c9f10124 9161 gen_logicq_cc(tmp, tmp2);
8aac08b1 9162 }
c9f10124
RH
9163 store_reg(s, rn, tmp);
9164 store_reg(s, rd, tmp2);
9ee6e8bb 9165 break;
8aac08b1
AJ
9166 default:
9167 goto illegal_op;
9ee6e8bb
PB
9168 }
9169 } else {
9170 rn = (insn >> 16) & 0xf;
9171 rd = (insn >> 12) & 0xf;
9172 if (insn & (1 << 23)) {
9173 /* load/store exclusive */
2359bf80 9174 int op2 = (insn >> 8) & 3;
86753403 9175 op1 = (insn >> 21) & 0x3;
2359bf80
MR
9176
9177 switch (op2) {
9178 case 0: /* lda/stl */
9179 if (op1 == 1) {
9180 goto illegal_op;
9181 }
9182 ARCH(8);
9183 break;
9184 case 1: /* reserved */
9185 goto illegal_op;
9186 case 2: /* ldaex/stlex */
9187 ARCH(8);
9188 break;
9189 case 3: /* ldrex/strex */
9190 if (op1) {
9191 ARCH(6K);
9192 } else {
9193 ARCH(6);
9194 }
9195 break;
9196 }
9197
3174f8e9 9198 addr = tcg_temp_local_new_i32();
98a46317 9199 load_reg_var(s, addr, rn);
2359bf80
MR
9200
9201 /* Since the emulation does not have barriers,
9202 the acquire/release semantics need no special
9203 handling */
9204 if (op2 == 0) {
9205 if (insn & (1 << 20)) {
9206 tmp = tcg_temp_new_i32();
9207 switch (op1) {
9208 case 0: /* lda */
9bb6558a
PM
9209 gen_aa32_ld32u_iss(s, tmp, addr,
9210 get_mem_index(s),
9211 rd | ISSIsAcqRel);
2359bf80
MR
9212 break;
9213 case 2: /* ldab */
9bb6558a
PM
9214 gen_aa32_ld8u_iss(s, tmp, addr,
9215 get_mem_index(s),
9216 rd | ISSIsAcqRel);
2359bf80
MR
9217 break;
9218 case 3: /* ldah */
9bb6558a
PM
9219 gen_aa32_ld16u_iss(s, tmp, addr,
9220 get_mem_index(s),
9221 rd | ISSIsAcqRel);
2359bf80
MR
9222 break;
9223 default:
9224 abort();
9225 }
9226 store_reg(s, rd, tmp);
9227 } else {
9228 rm = insn & 0xf;
9229 tmp = load_reg(s, rm);
9230 switch (op1) {
9231 case 0: /* stl */
9bb6558a
PM
9232 gen_aa32_st32_iss(s, tmp, addr,
9233 get_mem_index(s),
9234 rm | ISSIsAcqRel);
2359bf80
MR
9235 break;
9236 case 2: /* stlb */
9bb6558a
PM
9237 gen_aa32_st8_iss(s, tmp, addr,
9238 get_mem_index(s),
9239 rm | ISSIsAcqRel);
2359bf80
MR
9240 break;
9241 case 3: /* stlh */
9bb6558a
PM
9242 gen_aa32_st16_iss(s, tmp, addr,
9243 get_mem_index(s),
9244 rm | ISSIsAcqRel);
2359bf80
MR
9245 break;
9246 default:
9247 abort();
9248 }
9249 tcg_temp_free_i32(tmp);
9250 }
9251 } else if (insn & (1 << 20)) {
86753403
PB
9252 switch (op1) {
9253 case 0: /* ldrex */
426f5abc 9254 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
9255 break;
9256 case 1: /* ldrexd */
426f5abc 9257 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
9258 break;
9259 case 2: /* ldrexb */
426f5abc 9260 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
9261 break;
9262 case 3: /* ldrexh */
426f5abc 9263 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
9264 break;
9265 default:
9266 abort();
9267 }
9ee6e8bb
PB
9268 } else {
9269 rm = insn & 0xf;
86753403
PB
9270 switch (op1) {
9271 case 0: /* strex */
426f5abc 9272 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
9273 break;
9274 case 1: /* strexd */
502e64fe 9275 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
9276 break;
9277 case 2: /* strexb */
426f5abc 9278 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
9279 break;
9280 case 3: /* strexh */
426f5abc 9281 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
9282 break;
9283 default:
9284 abort();
9285 }
9ee6e8bb 9286 }
39d5492a 9287 tcg_temp_free_i32(addr);
c4869ca6
OS
9288 } else if ((insn & 0x00300f00) == 0) {
9289 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
9290 * - SWP, SWPB
9291 */
9292
cf12bce0
EC
9293 TCGv taddr;
9294 TCGMemOp opc = s->be_data;
9295
9ee6e8bb
PB
9296 rm = (insn) & 0xf;
9297
9ee6e8bb 9298 if (insn & (1 << 22)) {
cf12bce0 9299 opc |= MO_UB;
9ee6e8bb 9300 } else {
cf12bce0 9301 opc |= MO_UL | MO_ALIGN;
9ee6e8bb 9302 }
cf12bce0
EC
9303
9304 addr = load_reg(s, rn);
9305 taddr = gen_aa32_addr(s, addr, opc);
7d1b0095 9306 tcg_temp_free_i32(addr);
cf12bce0
EC
9307
9308 tmp = load_reg(s, rm);
9309 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
9310 get_mem_index(s), opc);
9311 tcg_temp_free(taddr);
9312 store_reg(s, rd, tmp);
c4869ca6
OS
9313 } else {
9314 goto illegal_op;
9ee6e8bb
PB
9315 }
9316 }
9317 } else {
9318 int address_offset;
3960c336 9319 bool load = insn & (1 << 20);
63f26fcf
PM
9320 bool wbit = insn & (1 << 21);
9321 bool pbit = insn & (1 << 24);
3960c336 9322 bool doubleword = false;
9bb6558a
PM
9323 ISSInfo issinfo;
9324
9ee6e8bb
PB
9325 /* Misc load/store */
9326 rn = (insn >> 16) & 0xf;
9327 rd = (insn >> 12) & 0xf;
3960c336 9328
9bb6558a
PM
9329 /* ISS not valid if writeback */
9330 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
9331
3960c336
PM
9332 if (!load && (sh & 2)) {
9333 /* doubleword */
9334 ARCH(5TE);
9335 if (rd & 1) {
9336 /* UNPREDICTABLE; we choose to UNDEF */
9337 goto illegal_op;
9338 }
9339 load = (sh & 1) == 0;
9340 doubleword = true;
9341 }
9342
b0109805 9343 addr = load_reg(s, rn);
63f26fcf 9344 if (pbit) {
b0109805 9345 gen_add_datah_offset(s, insn, 0, addr);
63f26fcf 9346 }
9ee6e8bb 9347 address_offset = 0;
3960c336
PM
9348
9349 if (doubleword) {
9350 if (!load) {
9ee6e8bb 9351 /* store */
b0109805 9352 tmp = load_reg(s, rd);
12dcc321 9353 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9354 tcg_temp_free_i32(tmp);
b0109805
PB
9355 tcg_gen_addi_i32(addr, addr, 4);
9356 tmp = load_reg(s, rd + 1);
12dcc321 9357 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9358 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9359 } else {
9360 /* load */
5a839c0d 9361 tmp = tcg_temp_new_i32();
12dcc321 9362 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
9363 store_reg(s, rd, tmp);
9364 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 9365 tmp = tcg_temp_new_i32();
12dcc321 9366 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9367 rd++;
9ee6e8bb
PB
9368 }
9369 address_offset = -4;
3960c336
PM
9370 } else if (load) {
9371 /* load */
9372 tmp = tcg_temp_new_i32();
9373 switch (sh) {
9374 case 1:
9bb6558a
PM
9375 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9376 issinfo);
3960c336
PM
9377 break;
9378 case 2:
9bb6558a
PM
9379 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
9380 issinfo);
3960c336
PM
9381 break;
9382 default:
9383 case 3:
9bb6558a
PM
9384 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
9385 issinfo);
3960c336
PM
9386 break;
9387 }
9ee6e8bb
PB
9388 } else {
9389 /* store */
b0109805 9390 tmp = load_reg(s, rd);
9bb6558a 9391 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
5a839c0d 9392 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9393 }
9394 /* Perform base writeback before the loaded value to
9395 ensure correct behavior with overlapping index registers.
b6af0975 9396 ldrd with base writeback is undefined if the
9ee6e8bb 9397 destination and index registers overlap. */
63f26fcf 9398 if (!pbit) {
b0109805
PB
9399 gen_add_datah_offset(s, insn, address_offset, addr);
9400 store_reg(s, rn, addr);
63f26fcf 9401 } else if (wbit) {
9ee6e8bb 9402 if (address_offset)
b0109805
PB
9403 tcg_gen_addi_i32(addr, addr, address_offset);
9404 store_reg(s, rn, addr);
9405 } else {
7d1b0095 9406 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9407 }
9408 if (load) {
9409 /* Complete the load. */
b0109805 9410 store_reg(s, rd, tmp);
9ee6e8bb
PB
9411 }
9412 }
9413 break;
9414 case 0x4:
9415 case 0x5:
9416 goto do_ldst;
9417 case 0x6:
9418 case 0x7:
9419 if (insn & (1 << 4)) {
9420 ARCH(6);
9421 /* Armv6 Media instructions. */
9422 rm = insn & 0xf;
9423 rn = (insn >> 16) & 0xf;
2c0262af 9424 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
9425 rs = (insn >> 8) & 0xf;
9426 switch ((insn >> 23) & 3) {
9427 case 0: /* Parallel add/subtract. */
9428 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
9429 tmp = load_reg(s, rn);
9430 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9431 sh = (insn >> 5) & 7;
9432 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
9433 goto illegal_op;
6ddbc6e4 9434 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 9435 tcg_temp_free_i32(tmp2);
6ddbc6e4 9436 store_reg(s, rd, tmp);
9ee6e8bb
PB
9437 break;
9438 case 1:
9439 if ((insn & 0x00700020) == 0) {
6c95676b 9440 /* Halfword pack. */
3670669c
PB
9441 tmp = load_reg(s, rn);
9442 tmp2 = load_reg(s, rm);
9ee6e8bb 9443 shift = (insn >> 7) & 0x1f;
3670669c
PB
9444 if (insn & (1 << 6)) {
9445 /* pkhtb */
22478e79
AZ
9446 if (shift == 0)
9447 shift = 31;
9448 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 9449 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 9450 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
9451 } else {
9452 /* pkhbt */
22478e79
AZ
9453 if (shift)
9454 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 9455 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
9456 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9457 }
9458 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 9459 tcg_temp_free_i32(tmp2);
3670669c 9460 store_reg(s, rd, tmp);
9ee6e8bb
PB
9461 } else if ((insn & 0x00200020) == 0x00200000) {
9462 /* [us]sat */
6ddbc6e4 9463 tmp = load_reg(s, rm);
9ee6e8bb
PB
9464 shift = (insn >> 7) & 0x1f;
9465 if (insn & (1 << 6)) {
9466 if (shift == 0)
9467 shift = 31;
6ddbc6e4 9468 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 9469 } else {
6ddbc6e4 9470 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
9471 }
9472 sh = (insn >> 16) & 0x1f;
40d3c433
CL
9473 tmp2 = tcg_const_i32(sh);
9474 if (insn & (1 << 22))
9ef39277 9475 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 9476 else
9ef39277 9477 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 9478 tcg_temp_free_i32(tmp2);
6ddbc6e4 9479 store_reg(s, rd, tmp);
9ee6e8bb
PB
9480 } else if ((insn & 0x00300fe0) == 0x00200f20) {
9481 /* [us]sat16 */
6ddbc6e4 9482 tmp = load_reg(s, rm);
9ee6e8bb 9483 sh = (insn >> 16) & 0x1f;
40d3c433
CL
9484 tmp2 = tcg_const_i32(sh);
9485 if (insn & (1 << 22))
9ef39277 9486 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 9487 else
9ef39277 9488 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 9489 tcg_temp_free_i32(tmp2);
6ddbc6e4 9490 store_reg(s, rd, tmp);
9ee6e8bb
PB
9491 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
9492 /* Select bytes. */
6ddbc6e4
PB
9493 tmp = load_reg(s, rn);
9494 tmp2 = load_reg(s, rm);
7d1b0095 9495 tmp3 = tcg_temp_new_i32();
0ecb72a5 9496 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 9497 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
9498 tcg_temp_free_i32(tmp3);
9499 tcg_temp_free_i32(tmp2);
6ddbc6e4 9500 store_reg(s, rd, tmp);
9ee6e8bb 9501 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 9502 tmp = load_reg(s, rm);
9ee6e8bb 9503 shift = (insn >> 10) & 3;
1301f322 9504 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
9505 rotate, a shift is sufficient. */
9506 if (shift != 0)
f669df27 9507 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
9508 op1 = (insn >> 20) & 7;
9509 switch (op1) {
5e3f878a
PB
9510 case 0: gen_sxtb16(tmp); break;
9511 case 2: gen_sxtb(tmp); break;
9512 case 3: gen_sxth(tmp); break;
9513 case 4: gen_uxtb16(tmp); break;
9514 case 6: gen_uxtb(tmp); break;
9515 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
9516 default: goto illegal_op;
9517 }
9518 if (rn != 15) {
5e3f878a 9519 tmp2 = load_reg(s, rn);
9ee6e8bb 9520 if ((op1 & 3) == 0) {
5e3f878a 9521 gen_add16(tmp, tmp2);
9ee6e8bb 9522 } else {
5e3f878a 9523 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9524 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9525 }
9526 }
6c95676b 9527 store_reg(s, rd, tmp);
9ee6e8bb
PB
9528 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
9529 /* rev */
b0109805 9530 tmp = load_reg(s, rm);
9ee6e8bb
PB
9531 if (insn & (1 << 22)) {
9532 if (insn & (1 << 7)) {
b0109805 9533 gen_revsh(tmp);
9ee6e8bb
PB
9534 } else {
9535 ARCH(6T2);
b0109805 9536 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9537 }
9538 } else {
9539 if (insn & (1 << 7))
b0109805 9540 gen_rev16(tmp);
9ee6e8bb 9541 else
66896cb8 9542 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 9543 }
b0109805 9544 store_reg(s, rd, tmp);
9ee6e8bb
PB
9545 } else {
9546 goto illegal_op;
9547 }
9548 break;
9549 case 2: /* Multiplies (Type 3). */
41e9564d
PM
9550 switch ((insn >> 20) & 0x7) {
9551 case 5:
9552 if (((insn >> 6) ^ (insn >> 7)) & 1) {
9553 /* op2 not 00x or 11x : UNDEF */
9554 goto illegal_op;
9555 }
838fa72d
AJ
9556 /* Signed multiply most significant [accumulate].
9557 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
9558 tmp = load_reg(s, rm);
9559 tmp2 = load_reg(s, rs);
a7812ae4 9560 tmp64 = gen_muls_i64_i32(tmp, tmp2);
838fa72d 9561
955a7dd5 9562 if (rd != 15) {
838fa72d 9563 tmp = load_reg(s, rd);
9ee6e8bb 9564 if (insn & (1 << 6)) {
838fa72d 9565 tmp64 = gen_subq_msw(tmp64, tmp);
9ee6e8bb 9566 } else {
838fa72d 9567 tmp64 = gen_addq_msw(tmp64, tmp);
9ee6e8bb
PB
9568 }
9569 }
838fa72d
AJ
9570 if (insn & (1 << 5)) {
9571 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9572 }
9573 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 9574 tmp = tcg_temp_new_i32();
ecc7b3aa 9575 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 9576 tcg_temp_free_i64(tmp64);
955a7dd5 9577 store_reg(s, rn, tmp);
41e9564d
PM
9578 break;
9579 case 0:
9580 case 4:
9581 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
9582 if (insn & (1 << 7)) {
9583 goto illegal_op;
9584 }
9585 tmp = load_reg(s, rm);
9586 tmp2 = load_reg(s, rs);
9ee6e8bb 9587 if (insn & (1 << 5))
5e3f878a
PB
9588 gen_swap_half(tmp2);
9589 gen_smul_dual(tmp, tmp2);
9ee6e8bb 9590 if (insn & (1 << 22)) {
5e3f878a 9591 /* smlald, smlsld */
33bbd75a
PC
9592 TCGv_i64 tmp64_2;
9593
a7812ae4 9594 tmp64 = tcg_temp_new_i64();
33bbd75a 9595 tmp64_2 = tcg_temp_new_i64();
a7812ae4 9596 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 9597 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 9598 tcg_temp_free_i32(tmp);
33bbd75a
PC
9599 tcg_temp_free_i32(tmp2);
9600 if (insn & (1 << 6)) {
9601 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
9602 } else {
9603 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
9604 }
9605 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
9606 gen_addq(s, tmp64, rd, rn);
9607 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 9608 tcg_temp_free_i64(tmp64);
9ee6e8bb 9609 } else {
5e3f878a 9610 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
9611 if (insn & (1 << 6)) {
9612 /* This subtraction cannot overflow. */
9613 tcg_gen_sub_i32(tmp, tmp, tmp2);
9614 } else {
9615 /* This addition cannot overflow 32 bits;
9616 * however it may overflow considered as a
9617 * signed operation, in which case we must set
9618 * the Q flag.
9619 */
9620 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9621 }
9622 tcg_temp_free_i32(tmp2);
22478e79 9623 if (rd != 15)
9ee6e8bb 9624 {
22478e79 9625 tmp2 = load_reg(s, rd);
9ef39277 9626 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9627 tcg_temp_free_i32(tmp2);
9ee6e8bb 9628 }
22478e79 9629 store_reg(s, rn, tmp);
9ee6e8bb 9630 }
41e9564d 9631 break;
b8b8ea05
PM
9632 case 1:
9633 case 3:
9634 /* SDIV, UDIV */
d614a513 9635 if (!arm_dc_feature(s, ARM_FEATURE_ARM_DIV)) {
b8b8ea05
PM
9636 goto illegal_op;
9637 }
9638 if (((insn >> 5) & 7) || (rd != 15)) {
9639 goto illegal_op;
9640 }
9641 tmp = load_reg(s, rm);
9642 tmp2 = load_reg(s, rs);
9643 if (insn & (1 << 21)) {
9644 gen_helper_udiv(tmp, tmp, tmp2);
9645 } else {
9646 gen_helper_sdiv(tmp, tmp, tmp2);
9647 }
9648 tcg_temp_free_i32(tmp2);
9649 store_reg(s, rn, tmp);
9650 break;
41e9564d
PM
9651 default:
9652 goto illegal_op;
9ee6e8bb
PB
9653 }
9654 break;
9655 case 3:
9656 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
9657 switch (op1) {
9658 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
9659 ARCH(6);
9660 tmp = load_reg(s, rm);
9661 tmp2 = load_reg(s, rs);
9662 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 9663 tcg_temp_free_i32(tmp2);
ded9d295
AZ
9664 if (rd != 15) {
9665 tmp2 = load_reg(s, rd);
6ddbc6e4 9666 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9667 tcg_temp_free_i32(tmp2);
9ee6e8bb 9668 }
ded9d295 9669 store_reg(s, rn, tmp);
9ee6e8bb
PB
9670 break;
9671 case 0x20: case 0x24: case 0x28: case 0x2c:
9672 /* Bitfield insert/clear. */
9673 ARCH(6T2);
9674 shift = (insn >> 7) & 0x1f;
9675 i = (insn >> 16) & 0x1f;
45140a57
KB
9676 if (i < shift) {
9677 /* UNPREDICTABLE; we choose to UNDEF */
9678 goto illegal_op;
9679 }
9ee6e8bb
PB
9680 i = i + 1 - shift;
9681 if (rm == 15) {
7d1b0095 9682 tmp = tcg_temp_new_i32();
5e3f878a 9683 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 9684 } else {
5e3f878a 9685 tmp = load_reg(s, rm);
9ee6e8bb
PB
9686 }
9687 if (i != 32) {
5e3f878a 9688 tmp2 = load_reg(s, rd);
d593c48e 9689 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 9690 tcg_temp_free_i32(tmp2);
9ee6e8bb 9691 }
5e3f878a 9692 store_reg(s, rd, tmp);
9ee6e8bb
PB
9693 break;
9694 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
9695 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 9696 ARCH(6T2);
5e3f878a 9697 tmp = load_reg(s, rm);
9ee6e8bb
PB
9698 shift = (insn >> 7) & 0x1f;
9699 i = ((insn >> 16) & 0x1f) + 1;
9700 if (shift + i > 32)
9701 goto illegal_op;
9702 if (i < 32) {
9703 if (op1 & 0x20) {
59a71b4c 9704 tcg_gen_extract_i32(tmp, tmp, shift, i);
9ee6e8bb 9705 } else {
59a71b4c 9706 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9ee6e8bb
PB
9707 }
9708 }
5e3f878a 9709 store_reg(s, rd, tmp);
9ee6e8bb
PB
9710 break;
9711 default:
9712 goto illegal_op;
9713 }
9714 break;
9715 }
9716 break;
9717 }
9718 do_ldst:
9719 /* Check for undefined extension instructions
9720 * per the ARM Bible IE:
9721 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9722 */
9723 sh = (0xf << 20) | (0xf << 4);
9724 if (op1 == 0x7 && ((insn & sh) == sh))
9725 {
9726 goto illegal_op;
9727 }
9728 /* load/store byte/word */
9729 rn = (insn >> 16) & 0xf;
9730 rd = (insn >> 12) & 0xf;
b0109805 9731 tmp2 = load_reg(s, rn);
a99caa48
PM
9732 if ((insn & 0x01200000) == 0x00200000) {
9733 /* ldrt/strt */
579d21cc 9734 i = get_a32_user_mem_index(s);
a99caa48
PM
9735 } else {
9736 i = get_mem_index(s);
9737 }
9ee6e8bb 9738 if (insn & (1 << 24))
b0109805 9739 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
9740 if (insn & (1 << 20)) {
9741 /* load */
5a839c0d 9742 tmp = tcg_temp_new_i32();
9ee6e8bb 9743 if (insn & (1 << 22)) {
9bb6558a 9744 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9745 } else {
9bb6558a 9746 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9747 }
9ee6e8bb
PB
9748 } else {
9749 /* store */
b0109805 9750 tmp = load_reg(s, rd);
5a839c0d 9751 if (insn & (1 << 22)) {
9bb6558a 9752 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
5a839c0d 9753 } else {
9bb6558a 9754 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
5a839c0d
PM
9755 }
9756 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9757 }
9758 if (!(insn & (1 << 24))) {
b0109805
PB
9759 gen_add_data_offset(s, insn, tmp2);
9760 store_reg(s, rn, tmp2);
9761 } else if (insn & (1 << 21)) {
9762 store_reg(s, rn, tmp2);
9763 } else {
7d1b0095 9764 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9765 }
9766 if (insn & (1 << 20)) {
9767 /* Complete the load. */
7dcc1f89 9768 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
9769 }
9770 break;
9771 case 0x08:
9772 case 0x09:
9773 {
da3e53dd
PM
9774 int j, n, loaded_base;
9775 bool exc_return = false;
9776 bool is_load = extract32(insn, 20, 1);
9777 bool user = false;
39d5492a 9778 TCGv_i32 loaded_var;
9ee6e8bb
PB
9779 /* load/store multiple words */
9780 /* XXX: store correct base if write back */
9ee6e8bb 9781 if (insn & (1 << 22)) {
da3e53dd 9782 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
9783 if (IS_USER(s))
9784 goto illegal_op; /* only usable in supervisor mode */
9785
da3e53dd
PM
9786 if (is_load && extract32(insn, 15, 1)) {
9787 exc_return = true;
9788 } else {
9789 user = true;
9790 }
9ee6e8bb
PB
9791 }
9792 rn = (insn >> 16) & 0xf;
b0109805 9793 addr = load_reg(s, rn);
9ee6e8bb
PB
9794
9795 /* compute total size */
9796 loaded_base = 0;
f764718d 9797 loaded_var = NULL;
9ee6e8bb
PB
9798 n = 0;
9799 for(i=0;i<16;i++) {
9800 if (insn & (1 << i))
9801 n++;
9802 }
9803 /* XXX: test invalid n == 0 case ? */
9804 if (insn & (1 << 23)) {
9805 if (insn & (1 << 24)) {
9806 /* pre increment */
b0109805 9807 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9808 } else {
9809 /* post increment */
9810 }
9811 } else {
9812 if (insn & (1 << 24)) {
9813 /* pre decrement */
b0109805 9814 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9815 } else {
9816 /* post decrement */
9817 if (n != 1)
b0109805 9818 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9819 }
9820 }
9821 j = 0;
9822 for(i=0;i<16;i++) {
9823 if (insn & (1 << i)) {
da3e53dd 9824 if (is_load) {
9ee6e8bb 9825 /* load */
5a839c0d 9826 tmp = tcg_temp_new_i32();
12dcc321 9827 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
be5e7a76 9828 if (user) {
b75263d6 9829 tmp2 = tcg_const_i32(i);
1ce94f81 9830 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 9831 tcg_temp_free_i32(tmp2);
7d1b0095 9832 tcg_temp_free_i32(tmp);
9ee6e8bb 9833 } else if (i == rn) {
b0109805 9834 loaded_var = tmp;
9ee6e8bb 9835 loaded_base = 1;
fb0e8e79
PM
9836 } else if (rn == 15 && exc_return) {
9837 store_pc_exc_ret(s, tmp);
9ee6e8bb 9838 } else {
7dcc1f89 9839 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
9840 }
9841 } else {
9842 /* store */
9843 if (i == 15) {
9844 /* special case: r15 = PC + 8 */
9845 val = (long)s->pc + 4;
7d1b0095 9846 tmp = tcg_temp_new_i32();
b0109805 9847 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 9848 } else if (user) {
7d1b0095 9849 tmp = tcg_temp_new_i32();
b75263d6 9850 tmp2 = tcg_const_i32(i);
9ef39277 9851 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 9852 tcg_temp_free_i32(tmp2);
9ee6e8bb 9853 } else {
b0109805 9854 tmp = load_reg(s, i);
9ee6e8bb 9855 }
12dcc321 9856 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9857 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9858 }
9859 j++;
9860 /* no need to add after the last transfer */
9861 if (j != n)
b0109805 9862 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9863 }
9864 }
9865 if (insn & (1 << 21)) {
9866 /* write back */
9867 if (insn & (1 << 23)) {
9868 if (insn & (1 << 24)) {
9869 /* pre increment */
9870 } else {
9871 /* post increment */
b0109805 9872 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9873 }
9874 } else {
9875 if (insn & (1 << 24)) {
9876 /* pre decrement */
9877 if (n != 1)
b0109805 9878 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9879 } else {
9880 /* post decrement */
b0109805 9881 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9882 }
9883 }
b0109805
PB
9884 store_reg(s, rn, addr);
9885 } else {
7d1b0095 9886 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9887 }
9888 if (loaded_base) {
b0109805 9889 store_reg(s, rn, loaded_var);
9ee6e8bb 9890 }
da3e53dd 9891 if (exc_return) {
9ee6e8bb 9892 /* Restore CPSR from SPSR. */
d9ba4830 9893 tmp = load_cpu_field(spsr);
e69ad9df
AL
9894 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9895 gen_io_start();
9896 }
235ea1f5 9897 gen_helper_cpsr_write_eret(cpu_env, tmp);
e69ad9df
AL
9898 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9899 gen_io_end();
9900 }
7d1b0095 9901 tcg_temp_free_i32(tmp);
b29fd33d 9902 /* Must exit loop to check un-masked IRQs */
dcba3a8d 9903 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb
PB
9904 }
9905 }
9906 break;
9907 case 0xa:
9908 case 0xb:
9909 {
9910 int32_t offset;
9911
9912 /* branch (and link) */
9913 val = (int32_t)s->pc;
9914 if (insn & (1 << 24)) {
7d1b0095 9915 tmp = tcg_temp_new_i32();
5e3f878a
PB
9916 tcg_gen_movi_i32(tmp, val);
9917 store_reg(s, 14, tmp);
9ee6e8bb 9918 }
534df156
PM
9919 offset = sextract32(insn << 2, 0, 26);
9920 val += offset + 4;
9ee6e8bb
PB
9921 gen_jmp(s, val);
9922 }
9923 break;
9924 case 0xc:
9925 case 0xd:
9926 case 0xe:
6a57f3eb
WN
9927 if (((insn >> 8) & 0xe) == 10) {
9928 /* VFP. */
7dcc1f89 9929 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9930 goto illegal_op;
9931 }
7dcc1f89 9932 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 9933 /* Coprocessor. */
9ee6e8bb 9934 goto illegal_op;
6a57f3eb 9935 }
9ee6e8bb
PB
9936 break;
9937 case 0xf:
9938 /* swi */
eaed129d 9939 gen_set_pc_im(s, s->pc);
d4a2dc67 9940 s->svc_imm = extract32(insn, 0, 24);
dcba3a8d 9941 s->base.is_jmp = DISAS_SWI;
9ee6e8bb
PB
9942 break;
9943 default:
9944 illegal_op:
73710361
GB
9945 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9946 default_exception_el(s));
9ee6e8bb
PB
9947 break;
9948 }
9949 }
9950}
9951
296e5a0a
PM
9952static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
9953{
9954 /* Return true if this is a 16 bit instruction. We must be precise
9955 * about this (matching the decode). We assume that s->pc still
9956 * points to the first 16 bits of the insn.
9957 */
9958 if ((insn >> 11) < 0x1d) {
9959 /* Definitely a 16-bit instruction */
9960 return true;
9961 }
9962
9963 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
9964 * first half of a 32-bit Thumb insn. Thumb-1 cores might
9965 * end up actually treating this as two 16-bit insns, though,
9966 * if it's half of a bl/blx pair that might span a page boundary.
9967 */
14120108
JS
9968 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9969 arm_dc_feature(s, ARM_FEATURE_M)) {
296e5a0a
PM
9970 /* Thumb2 cores (including all M profile ones) always treat
9971 * 32-bit insns as 32-bit.
9972 */
9973 return false;
9974 }
9975
bfe7ad5b 9976 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
296e5a0a
PM
9977 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
9978 * is not on the next page; we merge this into a 32-bit
9979 * insn.
9980 */
9981 return false;
9982 }
9983 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
9984 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
9985 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
9986 * -- handle as single 16 bit insn
9987 */
9988 return true;
9989}
9990
9ee6e8bb
PB
9991/* Return true if this is a Thumb-2 logical op. */
9992static int
9993thumb2_logic_op(int op)
9994{
9995 return (op < 8);
9996}
9997
9998/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
9999 then set condition code flags based on the result of the operation.
10000 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10001 to the high bit of T1.
10002 Returns zero if the opcode is valid. */
10003
10004static int
39d5492a
PM
10005gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10006 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
10007{
10008 int logic_cc;
10009
10010 logic_cc = 0;
10011 switch (op) {
10012 case 0: /* and */
396e467c 10013 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
10014 logic_cc = conds;
10015 break;
10016 case 1: /* bic */
f669df27 10017 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
10018 logic_cc = conds;
10019 break;
10020 case 2: /* orr */
396e467c 10021 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
10022 logic_cc = conds;
10023 break;
10024 case 3: /* orn */
29501f1b 10025 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
10026 logic_cc = conds;
10027 break;
10028 case 4: /* eor */
396e467c 10029 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
10030 logic_cc = conds;
10031 break;
10032 case 8: /* add */
10033 if (conds)
72485ec4 10034 gen_add_CC(t0, t0, t1);
9ee6e8bb 10035 else
396e467c 10036 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
10037 break;
10038 case 10: /* adc */
10039 if (conds)
49b4c31e 10040 gen_adc_CC(t0, t0, t1);
9ee6e8bb 10041 else
396e467c 10042 gen_adc(t0, t1);
9ee6e8bb
PB
10043 break;
10044 case 11: /* sbc */
2de68a49
RH
10045 if (conds) {
10046 gen_sbc_CC(t0, t0, t1);
10047 } else {
396e467c 10048 gen_sub_carry(t0, t0, t1);
2de68a49 10049 }
9ee6e8bb
PB
10050 break;
10051 case 13: /* sub */
10052 if (conds)
72485ec4 10053 gen_sub_CC(t0, t0, t1);
9ee6e8bb 10054 else
396e467c 10055 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
10056 break;
10057 case 14: /* rsb */
10058 if (conds)
72485ec4 10059 gen_sub_CC(t0, t1, t0);
9ee6e8bb 10060 else
396e467c 10061 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
10062 break;
10063 default: /* 5, 6, 7, 9, 12, 15. */
10064 return 1;
10065 }
10066 if (logic_cc) {
396e467c 10067 gen_logic_CC(t0);
9ee6e8bb 10068 if (shifter_out)
396e467c 10069 gen_set_CF_bit31(t1);
9ee6e8bb
PB
10070 }
10071 return 0;
10072}
10073
2eea841c
PM
10074/* Translate a 32-bit thumb instruction. */
10075static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 10076{
296e5a0a 10077 uint32_t imm, shift, offset;
9ee6e8bb 10078 uint32_t rd, rn, rm, rs;
39d5492a
PM
10079 TCGv_i32 tmp;
10080 TCGv_i32 tmp2;
10081 TCGv_i32 tmp3;
10082 TCGv_i32 addr;
a7812ae4 10083 TCGv_i64 tmp64;
9ee6e8bb
PB
10084 int op;
10085 int shiftop;
10086 int conds;
10087 int logic_cc;
10088
14120108
JS
10089 /*
10090 * ARMv6-M supports a limited subset of Thumb2 instructions.
10091 * Other Thumb1 architectures allow only 32-bit
10092 * combined BL/BLX prefix and suffix.
296e5a0a 10093 */
14120108
JS
10094 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10095 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10096 int i;
10097 bool found = false;
8297cb13
JS
10098 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10099 0xf3b08040 /* dsb */,
10100 0xf3b08050 /* dmb */,
10101 0xf3b08060 /* isb */,
10102 0xf3e08000 /* mrs */,
10103 0xf000d000 /* bl */};
10104 static const uint32_t armv6m_mask[] = {0xffe0d000,
10105 0xfff0d0f0,
10106 0xfff0d0f0,
10107 0xfff0d0f0,
10108 0xffe0d000,
10109 0xf800d000};
14120108
JS
10110
10111 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10112 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10113 found = true;
10114 break;
10115 }
10116 }
10117 if (!found) {
10118 goto illegal_op;
10119 }
10120 } else if ((insn & 0xf800e800) != 0xf000e800) {
9ee6e8bb
PB
10121 ARCH(6T2);
10122 }
10123
10124 rn = (insn >> 16) & 0xf;
10125 rs = (insn >> 12) & 0xf;
10126 rd = (insn >> 8) & 0xf;
10127 rm = insn & 0xf;
10128 switch ((insn >> 25) & 0xf) {
10129 case 0: case 1: case 2: case 3:
10130 /* 16-bit instructions. Should never happen. */
10131 abort();
10132 case 4:
10133 if (insn & (1 << 22)) {
ebfe27c5
PM
10134 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10135 * - load/store doubleword, load/store exclusive, ldacq/strel,
5158de24 10136 * table branch, TT.
ebfe27c5 10137 */
76eff04d
PM
10138 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10139 arm_dc_feature(s, ARM_FEATURE_V8)) {
10140 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10141 * - SG (v8M only)
10142 * The bulk of the behaviour for this instruction is implemented
10143 * in v7m_handle_execute_nsc(), which deals with the insn when
10144 * it is executed by a CPU in non-secure state from memory
10145 * which is Secure & NonSecure-Callable.
10146 * Here we only need to handle the remaining cases:
10147 * * in NS memory (including the "security extension not
10148 * implemented" case) : NOP
10149 * * in S memory but CPU already secure (clear IT bits)
10150 * We know that the attribute for the memory this insn is
10151 * in must match the current CPU state, because otherwise
10152 * get_phys_addr_pmsav8 would have generated an exception.
10153 */
10154 if (s->v8m_secure) {
10155 /* Like the IT insn, we don't need to generate any code */
10156 s->condexec_cond = 0;
10157 s->condexec_mask = 0;
10158 }
10159 } else if (insn & 0x01200000) {
ebfe27c5
PM
10160 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10161 * - load/store dual (post-indexed)
10162 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10163 * - load/store dual (literal and immediate)
10164 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10165 * - load/store dual (pre-indexed)
10166 */
9ee6e8bb 10167 if (rn == 15) {
ebfe27c5
PM
10168 if (insn & (1 << 21)) {
10169 /* UNPREDICTABLE */
10170 goto illegal_op;
10171 }
7d1b0095 10172 addr = tcg_temp_new_i32();
b0109805 10173 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 10174 } else {
b0109805 10175 addr = load_reg(s, rn);
9ee6e8bb
PB
10176 }
10177 offset = (insn & 0xff) * 4;
10178 if ((insn & (1 << 23)) == 0)
10179 offset = -offset;
10180 if (insn & (1 << 24)) {
b0109805 10181 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
10182 offset = 0;
10183 }
10184 if (insn & (1 << 20)) {
10185 /* ldrd */
e2592fad 10186 tmp = tcg_temp_new_i32();
12dcc321 10187 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
10188 store_reg(s, rs, tmp);
10189 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 10190 tmp = tcg_temp_new_i32();
12dcc321 10191 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 10192 store_reg(s, rd, tmp);
9ee6e8bb
PB
10193 } else {
10194 /* strd */
b0109805 10195 tmp = load_reg(s, rs);
12dcc321 10196 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 10197 tcg_temp_free_i32(tmp);
b0109805
PB
10198 tcg_gen_addi_i32(addr, addr, 4);
10199 tmp = load_reg(s, rd);
12dcc321 10200 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 10201 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10202 }
10203 if (insn & (1 << 21)) {
10204 /* Base writeback. */
b0109805
PB
10205 tcg_gen_addi_i32(addr, addr, offset - 4);
10206 store_reg(s, rn, addr);
10207 } else {
7d1b0095 10208 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10209 }
10210 } else if ((insn & (1 << 23)) == 0) {
ebfe27c5
PM
10211 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
10212 * - load/store exclusive word
5158de24 10213 * - TT (v8M only)
ebfe27c5
PM
10214 */
10215 if (rs == 15) {
5158de24
PM
10216 if (!(insn & (1 << 20)) &&
10217 arm_dc_feature(s, ARM_FEATURE_M) &&
10218 arm_dc_feature(s, ARM_FEATURE_V8)) {
10219 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
10220 * - TT (v8M only)
10221 */
10222 bool alt = insn & (1 << 7);
10223 TCGv_i32 addr, op, ttresp;
10224
10225 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
10226 /* we UNDEF for these UNPREDICTABLE cases */
10227 goto illegal_op;
10228 }
10229
10230 if (alt && !s->v8m_secure) {
10231 goto illegal_op;
10232 }
10233
10234 addr = load_reg(s, rn);
10235 op = tcg_const_i32(extract32(insn, 6, 2));
10236 ttresp = tcg_temp_new_i32();
10237 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
10238 tcg_temp_free_i32(addr);
10239 tcg_temp_free_i32(op);
10240 store_reg(s, rd, ttresp);
384c6c03 10241 break;
5158de24 10242 }
ebfe27c5
PM
10243 goto illegal_op;
10244 }
39d5492a 10245 addr = tcg_temp_local_new_i32();
98a46317 10246 load_reg_var(s, addr, rn);
426f5abc 10247 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 10248 if (insn & (1 << 20)) {
426f5abc 10249 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 10250 } else {
426f5abc 10251 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 10252 }
39d5492a 10253 tcg_temp_free_i32(addr);
2359bf80 10254 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb
PB
10255 /* Table Branch. */
10256 if (rn == 15) {
7d1b0095 10257 addr = tcg_temp_new_i32();
b0109805 10258 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 10259 } else {
b0109805 10260 addr = load_reg(s, rn);
9ee6e8bb 10261 }
b26eefb6 10262 tmp = load_reg(s, rm);
b0109805 10263 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
10264 if (insn & (1 << 4)) {
10265 /* tbh */
b0109805 10266 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10267 tcg_temp_free_i32(tmp);
e2592fad 10268 tmp = tcg_temp_new_i32();
12dcc321 10269 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10270 } else { /* tbb */
7d1b0095 10271 tcg_temp_free_i32(tmp);
e2592fad 10272 tmp = tcg_temp_new_i32();
12dcc321 10273 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10274 }
7d1b0095 10275 tcg_temp_free_i32(addr);
b0109805
PB
10276 tcg_gen_shli_i32(tmp, tmp, 1);
10277 tcg_gen_addi_i32(tmp, tmp, s->pc);
10278 store_reg(s, 15, tmp);
9ee6e8bb 10279 } else {
2359bf80 10280 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 10281 op = (insn >> 4) & 0x3;
2359bf80
MR
10282 switch (op2) {
10283 case 0:
426f5abc 10284 goto illegal_op;
2359bf80
MR
10285 case 1:
10286 /* Load/store exclusive byte/halfword/doubleword */
10287 if (op == 2) {
10288 goto illegal_op;
10289 }
10290 ARCH(7);
10291 break;
10292 case 2:
10293 /* Load-acquire/store-release */
10294 if (op == 3) {
10295 goto illegal_op;
10296 }
10297 /* Fall through */
10298 case 3:
10299 /* Load-acquire/store-release exclusive */
10300 ARCH(8);
10301 break;
426f5abc 10302 }
39d5492a 10303 addr = tcg_temp_local_new_i32();
98a46317 10304 load_reg_var(s, addr, rn);
2359bf80
MR
10305 if (!(op2 & 1)) {
10306 if (insn & (1 << 20)) {
10307 tmp = tcg_temp_new_i32();
10308 switch (op) {
10309 case 0: /* ldab */
9bb6558a
PM
10310 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
10311 rs | ISSIsAcqRel);
2359bf80
MR
10312 break;
10313 case 1: /* ldah */
9bb6558a
PM
10314 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10315 rs | ISSIsAcqRel);
2359bf80
MR
10316 break;
10317 case 2: /* lda */
9bb6558a
PM
10318 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
10319 rs | ISSIsAcqRel);
2359bf80
MR
10320 break;
10321 default:
10322 abort();
10323 }
10324 store_reg(s, rs, tmp);
10325 } else {
10326 tmp = load_reg(s, rs);
10327 switch (op) {
10328 case 0: /* stlb */
9bb6558a
PM
10329 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
10330 rs | ISSIsAcqRel);
2359bf80
MR
10331 break;
10332 case 1: /* stlh */
9bb6558a
PM
10333 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
10334 rs | ISSIsAcqRel);
2359bf80
MR
10335 break;
10336 case 2: /* stl */
9bb6558a
PM
10337 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
10338 rs | ISSIsAcqRel);
2359bf80
MR
10339 break;
10340 default:
10341 abort();
10342 }
10343 tcg_temp_free_i32(tmp);
10344 }
10345 } else if (insn & (1 << 20)) {
426f5abc 10346 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 10347 } else {
426f5abc 10348 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 10349 }
39d5492a 10350 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10351 }
10352 } else {
10353 /* Load/store multiple, RFE, SRS. */
10354 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 10355 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 10356 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10357 goto illegal_op;
00115976 10358 }
9ee6e8bb
PB
10359 if (insn & (1 << 20)) {
10360 /* rfe */
b0109805
PB
10361 addr = load_reg(s, rn);
10362 if ((insn & (1 << 24)) == 0)
10363 tcg_gen_addi_i32(addr, addr, -8);
10364 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 10365 tmp = tcg_temp_new_i32();
12dcc321 10366 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 10367 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 10368 tmp2 = tcg_temp_new_i32();
12dcc321 10369 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
10370 if (insn & (1 << 21)) {
10371 /* Base writeback. */
b0109805
PB
10372 if (insn & (1 << 24)) {
10373 tcg_gen_addi_i32(addr, addr, 4);
10374 } else {
10375 tcg_gen_addi_i32(addr, addr, -4);
10376 }
10377 store_reg(s, rn, addr);
10378 } else {
7d1b0095 10379 tcg_temp_free_i32(addr);
9ee6e8bb 10380 }
b0109805 10381 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
10382 } else {
10383 /* srs */
81465888
PM
10384 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
10385 insn & (1 << 21));
9ee6e8bb
PB
10386 }
10387 } else {
5856d44e 10388 int i, loaded_base = 0;
39d5492a 10389 TCGv_i32 loaded_var;
9ee6e8bb 10390 /* Load/store multiple. */
b0109805 10391 addr = load_reg(s, rn);
9ee6e8bb
PB
10392 offset = 0;
10393 for (i = 0; i < 16; i++) {
10394 if (insn & (1 << i))
10395 offset += 4;
10396 }
10397 if (insn & (1 << 24)) {
b0109805 10398 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
10399 }
10400
f764718d 10401 loaded_var = NULL;
9ee6e8bb
PB
10402 for (i = 0; i < 16; i++) {
10403 if ((insn & (1 << i)) == 0)
10404 continue;
10405 if (insn & (1 << 20)) {
10406 /* Load. */
e2592fad 10407 tmp = tcg_temp_new_i32();
12dcc321 10408 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10409 if (i == 15) {
3bb8a96f 10410 gen_bx_excret(s, tmp);
5856d44e
YO
10411 } else if (i == rn) {
10412 loaded_var = tmp;
10413 loaded_base = 1;
9ee6e8bb 10414 } else {
b0109805 10415 store_reg(s, i, tmp);
9ee6e8bb
PB
10416 }
10417 } else {
10418 /* Store. */
b0109805 10419 tmp = load_reg(s, i);
12dcc321 10420 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 10421 tcg_temp_free_i32(tmp);
9ee6e8bb 10422 }
b0109805 10423 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 10424 }
5856d44e
YO
10425 if (loaded_base) {
10426 store_reg(s, rn, loaded_var);
10427 }
9ee6e8bb
PB
10428 if (insn & (1 << 21)) {
10429 /* Base register writeback. */
10430 if (insn & (1 << 24)) {
b0109805 10431 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
10432 }
10433 /* Fault if writeback register is in register list. */
10434 if (insn & (1 << rn))
10435 goto illegal_op;
b0109805
PB
10436 store_reg(s, rn, addr);
10437 } else {
7d1b0095 10438 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10439 }
10440 }
10441 }
10442 break;
2af9ab77
JB
10443 case 5:
10444
9ee6e8bb 10445 op = (insn >> 21) & 0xf;
2af9ab77 10446 if (op == 6) {
62b44f05
AR
10447 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10448 goto illegal_op;
10449 }
2af9ab77
JB
10450 /* Halfword pack. */
10451 tmp = load_reg(s, rn);
10452 tmp2 = load_reg(s, rm);
10453 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
10454 if (insn & (1 << 5)) {
10455 /* pkhtb */
10456 if (shift == 0)
10457 shift = 31;
10458 tcg_gen_sari_i32(tmp2, tmp2, shift);
10459 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10460 tcg_gen_ext16u_i32(tmp2, tmp2);
10461 } else {
10462 /* pkhbt */
10463 if (shift)
10464 tcg_gen_shli_i32(tmp2, tmp2, shift);
10465 tcg_gen_ext16u_i32(tmp, tmp);
10466 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10467 }
10468 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 10469 tcg_temp_free_i32(tmp2);
3174f8e9
FN
10470 store_reg(s, rd, tmp);
10471 } else {
2af9ab77
JB
10472 /* Data processing register constant shift. */
10473 if (rn == 15) {
7d1b0095 10474 tmp = tcg_temp_new_i32();
2af9ab77
JB
10475 tcg_gen_movi_i32(tmp, 0);
10476 } else {
10477 tmp = load_reg(s, rn);
10478 }
10479 tmp2 = load_reg(s, rm);
10480
10481 shiftop = (insn >> 4) & 3;
10482 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
10483 conds = (insn & (1 << 20)) != 0;
10484 logic_cc = (conds && thumb2_logic_op(op));
10485 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
10486 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
10487 goto illegal_op;
7d1b0095 10488 tcg_temp_free_i32(tmp2);
2af9ab77
JB
10489 if (rd != 15) {
10490 store_reg(s, rd, tmp);
10491 } else {
7d1b0095 10492 tcg_temp_free_i32(tmp);
2af9ab77 10493 }
3174f8e9 10494 }
9ee6e8bb
PB
10495 break;
10496 case 13: /* Misc data processing. */
10497 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
10498 if (op < 4 && (insn & 0xf000) != 0xf000)
10499 goto illegal_op;
10500 switch (op) {
10501 case 0: /* Register controlled shift. */
8984bd2e
PB
10502 tmp = load_reg(s, rn);
10503 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10504 if ((insn & 0x70) != 0)
10505 goto illegal_op;
10506 op = (insn >> 21) & 3;
8984bd2e
PB
10507 logic_cc = (insn & (1 << 20)) != 0;
10508 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
10509 if (logic_cc)
10510 gen_logic_CC(tmp);
bedb8a6b 10511 store_reg(s, rd, tmp);
9ee6e8bb
PB
10512 break;
10513 case 1: /* Sign/zero extend. */
62b44f05
AR
10514 op = (insn >> 20) & 7;
10515 switch (op) {
10516 case 0: /* SXTAH, SXTH */
10517 case 1: /* UXTAH, UXTH */
10518 case 4: /* SXTAB, SXTB */
10519 case 5: /* UXTAB, UXTB */
10520 break;
10521 case 2: /* SXTAB16, SXTB16 */
10522 case 3: /* UXTAB16, UXTB16 */
10523 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10524 goto illegal_op;
10525 }
10526 break;
10527 default:
10528 goto illegal_op;
10529 }
10530 if (rn != 15) {
10531 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10532 goto illegal_op;
10533 }
10534 }
5e3f878a 10535 tmp = load_reg(s, rm);
9ee6e8bb 10536 shift = (insn >> 4) & 3;
1301f322 10537 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
10538 rotate, a shift is sufficient. */
10539 if (shift != 0)
f669df27 10540 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
10541 op = (insn >> 20) & 7;
10542 switch (op) {
5e3f878a
PB
10543 case 0: gen_sxth(tmp); break;
10544 case 1: gen_uxth(tmp); break;
10545 case 2: gen_sxtb16(tmp); break;
10546 case 3: gen_uxtb16(tmp); break;
10547 case 4: gen_sxtb(tmp); break;
10548 case 5: gen_uxtb(tmp); break;
62b44f05
AR
10549 default:
10550 g_assert_not_reached();
9ee6e8bb
PB
10551 }
10552 if (rn != 15) {
5e3f878a 10553 tmp2 = load_reg(s, rn);
9ee6e8bb 10554 if ((op >> 1) == 1) {
5e3f878a 10555 gen_add16(tmp, tmp2);
9ee6e8bb 10556 } else {
5e3f878a 10557 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10558 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10559 }
10560 }
5e3f878a 10561 store_reg(s, rd, tmp);
9ee6e8bb
PB
10562 break;
10563 case 2: /* SIMD add/subtract. */
62b44f05
AR
10564 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10565 goto illegal_op;
10566 }
9ee6e8bb
PB
10567 op = (insn >> 20) & 7;
10568 shift = (insn >> 4) & 7;
10569 if ((op & 3) == 3 || (shift & 3) == 3)
10570 goto illegal_op;
6ddbc6e4
PB
10571 tmp = load_reg(s, rn);
10572 tmp2 = load_reg(s, rm);
10573 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 10574 tcg_temp_free_i32(tmp2);
6ddbc6e4 10575 store_reg(s, rd, tmp);
9ee6e8bb
PB
10576 break;
10577 case 3: /* Other data processing. */
10578 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
10579 if (op < 4) {
10580 /* Saturating add/subtract. */
62b44f05
AR
10581 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10582 goto illegal_op;
10583 }
d9ba4830
PB
10584 tmp = load_reg(s, rn);
10585 tmp2 = load_reg(s, rm);
9ee6e8bb 10586 if (op & 1)
9ef39277 10587 gen_helper_double_saturate(tmp, cpu_env, tmp);
4809c612 10588 if (op & 2)
9ef39277 10589 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 10590 else
9ef39277 10591 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 10592 tcg_temp_free_i32(tmp2);
9ee6e8bb 10593 } else {
62b44f05
AR
10594 switch (op) {
10595 case 0x0a: /* rbit */
10596 case 0x08: /* rev */
10597 case 0x09: /* rev16 */
10598 case 0x0b: /* revsh */
10599 case 0x18: /* clz */
10600 break;
10601 case 0x10: /* sel */
10602 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10603 goto illegal_op;
10604 }
10605 break;
10606 case 0x20: /* crc32/crc32c */
10607 case 0x21:
10608 case 0x22:
10609 case 0x28:
10610 case 0x29:
10611 case 0x2a:
10612 if (!arm_dc_feature(s, ARM_FEATURE_CRC)) {
10613 goto illegal_op;
10614 }
10615 break;
10616 default:
10617 goto illegal_op;
10618 }
d9ba4830 10619 tmp = load_reg(s, rn);
9ee6e8bb
PB
10620 switch (op) {
10621 case 0x0a: /* rbit */
d9ba4830 10622 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
10623 break;
10624 case 0x08: /* rev */
66896cb8 10625 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
10626 break;
10627 case 0x09: /* rev16 */
d9ba4830 10628 gen_rev16(tmp);
9ee6e8bb
PB
10629 break;
10630 case 0x0b: /* revsh */
d9ba4830 10631 gen_revsh(tmp);
9ee6e8bb
PB
10632 break;
10633 case 0x10: /* sel */
d9ba4830 10634 tmp2 = load_reg(s, rm);
7d1b0095 10635 tmp3 = tcg_temp_new_i32();
0ecb72a5 10636 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 10637 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
10638 tcg_temp_free_i32(tmp3);
10639 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10640 break;
10641 case 0x18: /* clz */
7539a012 10642 tcg_gen_clzi_i32(tmp, tmp, 32);
9ee6e8bb 10643 break;
eb0ecd5a
WN
10644 case 0x20:
10645 case 0x21:
10646 case 0x22:
10647 case 0x28:
10648 case 0x29:
10649 case 0x2a:
10650 {
10651 /* crc32/crc32c */
10652 uint32_t sz = op & 0x3;
10653 uint32_t c = op & 0x8;
10654
eb0ecd5a 10655 tmp2 = load_reg(s, rm);
aa633469
PM
10656 if (sz == 0) {
10657 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10658 } else if (sz == 1) {
10659 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10660 }
eb0ecd5a
WN
10661 tmp3 = tcg_const_i32(1 << sz);
10662 if (c) {
10663 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10664 } else {
10665 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10666 }
10667 tcg_temp_free_i32(tmp2);
10668 tcg_temp_free_i32(tmp3);
10669 break;
10670 }
9ee6e8bb 10671 default:
62b44f05 10672 g_assert_not_reached();
9ee6e8bb
PB
10673 }
10674 }
d9ba4830 10675 store_reg(s, rd, tmp);
9ee6e8bb
PB
10676 break;
10677 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
10678 switch ((insn >> 20) & 7) {
10679 case 0: /* 32 x 32 -> 32 */
10680 case 7: /* Unsigned sum of absolute differences. */
10681 break;
10682 case 1: /* 16 x 16 -> 32 */
10683 case 2: /* Dual multiply add. */
10684 case 3: /* 32 * 16 -> 32msb */
10685 case 4: /* Dual multiply subtract. */
10686 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10687 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10688 goto illegal_op;
10689 }
10690 break;
10691 }
9ee6e8bb 10692 op = (insn >> 4) & 0xf;
d9ba4830
PB
10693 tmp = load_reg(s, rn);
10694 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10695 switch ((insn >> 20) & 7) {
10696 case 0: /* 32 x 32 -> 32 */
d9ba4830 10697 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 10698 tcg_temp_free_i32(tmp2);
9ee6e8bb 10699 if (rs != 15) {
d9ba4830 10700 tmp2 = load_reg(s, rs);
9ee6e8bb 10701 if (op)
d9ba4830 10702 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 10703 else
d9ba4830 10704 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10705 tcg_temp_free_i32(tmp2);
9ee6e8bb 10706 }
9ee6e8bb
PB
10707 break;
10708 case 1: /* 16 x 16 -> 32 */
d9ba4830 10709 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10710 tcg_temp_free_i32(tmp2);
9ee6e8bb 10711 if (rs != 15) {
d9ba4830 10712 tmp2 = load_reg(s, rs);
9ef39277 10713 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10714 tcg_temp_free_i32(tmp2);
9ee6e8bb 10715 }
9ee6e8bb
PB
10716 break;
10717 case 2: /* Dual multiply add. */
10718 case 4: /* Dual multiply subtract. */
10719 if (op)
d9ba4830
PB
10720 gen_swap_half(tmp2);
10721 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10722 if (insn & (1 << 22)) {
e1d177b9 10723 /* This subtraction cannot overflow. */
d9ba4830 10724 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10725 } else {
e1d177b9
PM
10726 /* This addition cannot overflow 32 bits;
10727 * however it may overflow considered as a signed
10728 * operation, in which case we must set the Q flag.
10729 */
9ef39277 10730 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 10731 }
7d1b0095 10732 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10733 if (rs != 15)
10734 {
d9ba4830 10735 tmp2 = load_reg(s, rs);
9ef39277 10736 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10737 tcg_temp_free_i32(tmp2);
9ee6e8bb 10738 }
9ee6e8bb
PB
10739 break;
10740 case 3: /* 32 * 16 -> 32msb */
10741 if (op)
d9ba4830 10742 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 10743 else
d9ba4830 10744 gen_sxth(tmp2);
a7812ae4
PB
10745 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10746 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 10747 tmp = tcg_temp_new_i32();
ecc7b3aa 10748 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 10749 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10750 if (rs != 15)
10751 {
d9ba4830 10752 tmp2 = load_reg(s, rs);
9ef39277 10753 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10754 tcg_temp_free_i32(tmp2);
9ee6e8bb 10755 }
9ee6e8bb 10756 break;
838fa72d
AJ
10757 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10758 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10759 if (rs != 15) {
838fa72d
AJ
10760 tmp = load_reg(s, rs);
10761 if (insn & (1 << 20)) {
10762 tmp64 = gen_addq_msw(tmp64, tmp);
99c475ab 10763 } else {
838fa72d 10764 tmp64 = gen_subq_msw(tmp64, tmp);
99c475ab 10765 }
2c0262af 10766 }
838fa72d
AJ
10767 if (insn & (1 << 4)) {
10768 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10769 }
10770 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 10771 tmp = tcg_temp_new_i32();
ecc7b3aa 10772 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 10773 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10774 break;
10775 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 10776 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 10777 tcg_temp_free_i32(tmp2);
9ee6e8bb 10778 if (rs != 15) {
d9ba4830
PB
10779 tmp2 = load_reg(s, rs);
10780 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10781 tcg_temp_free_i32(tmp2);
5fd46862 10782 }
9ee6e8bb 10783 break;
2c0262af 10784 }
d9ba4830 10785 store_reg(s, rd, tmp);
2c0262af 10786 break;
9ee6e8bb
PB
10787 case 6: case 7: /* 64-bit multiply, Divide. */
10788 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
10789 tmp = load_reg(s, rn);
10790 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10791 if ((op & 0x50) == 0x10) {
10792 /* sdiv, udiv */
d614a513 10793 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DIV)) {
9ee6e8bb 10794 goto illegal_op;
47789990 10795 }
9ee6e8bb 10796 if (op & 0x20)
5e3f878a 10797 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 10798 else
5e3f878a 10799 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 10800 tcg_temp_free_i32(tmp2);
5e3f878a 10801 store_reg(s, rd, tmp);
9ee6e8bb
PB
10802 } else if ((op & 0xe) == 0xc) {
10803 /* Dual multiply accumulate long. */
62b44f05
AR
10804 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10805 tcg_temp_free_i32(tmp);
10806 tcg_temp_free_i32(tmp2);
10807 goto illegal_op;
10808 }
9ee6e8bb 10809 if (op & 1)
5e3f878a
PB
10810 gen_swap_half(tmp2);
10811 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10812 if (op & 0x10) {
5e3f878a 10813 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 10814 } else {
5e3f878a 10815 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 10816 }
7d1b0095 10817 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10818 /* BUGFIX */
10819 tmp64 = tcg_temp_new_i64();
10820 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10821 tcg_temp_free_i32(tmp);
a7812ae4
PB
10822 gen_addq(s, tmp64, rs, rd);
10823 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10824 tcg_temp_free_i64(tmp64);
2c0262af 10825 } else {
9ee6e8bb
PB
10826 if (op & 0x20) {
10827 /* Unsigned 64-bit multiply */
a7812ae4 10828 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 10829 } else {
9ee6e8bb
PB
10830 if (op & 8) {
10831 /* smlalxy */
62b44f05
AR
10832 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10833 tcg_temp_free_i32(tmp2);
10834 tcg_temp_free_i32(tmp);
10835 goto illegal_op;
10836 }
5e3f878a 10837 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10838 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10839 tmp64 = tcg_temp_new_i64();
10840 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10841 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10842 } else {
10843 /* Signed 64-bit multiply */
a7812ae4 10844 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10845 }
b5ff1b31 10846 }
9ee6e8bb
PB
10847 if (op & 4) {
10848 /* umaal */
62b44f05
AR
10849 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10850 tcg_temp_free_i64(tmp64);
10851 goto illegal_op;
10852 }
a7812ae4
PB
10853 gen_addq_lo(s, tmp64, rs);
10854 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
10855 } else if (op & 0x40) {
10856 /* 64-bit accumulate. */
a7812ae4 10857 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 10858 }
a7812ae4 10859 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10860 tcg_temp_free_i64(tmp64);
5fd46862 10861 }
2c0262af 10862 break;
9ee6e8bb
PB
10863 }
10864 break;
10865 case 6: case 7: case 14: case 15:
10866 /* Coprocessor. */
7517748e
PM
10867 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10868 /* We don't currently implement M profile FP support,
b1e5336a
PM
10869 * so this entire space should give a NOCP fault, with
10870 * the exception of the v8M VLLDM and VLSTM insns, which
10871 * must be NOPs in Secure state and UNDEF in Nonsecure state.
7517748e 10872 */
b1e5336a
PM
10873 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
10874 (insn & 0xffa00f00) == 0xec200a00) {
10875 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
10876 * - VLLDM, VLSTM
10877 * We choose to UNDEF if the RAZ bits are non-zero.
10878 */
10879 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
10880 goto illegal_op;
10881 }
10882 /* Just NOP since FP support is not implemented */
10883 break;
10884 }
10885 /* All other insns: NOCP */
7517748e
PM
10886 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
10887 default_exception_el(s));
10888 break;
10889 }
0052087e
RH
10890 if ((insn & 0xfe000a00) == 0xfc000800
10891 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10892 /* The Thumb2 and ARM encodings are identical. */
10893 if (disas_neon_insn_3same_ext(s, insn)) {
10894 goto illegal_op;
10895 }
10896 } else if ((insn & 0xff000a00) == 0xfe000800
10897 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10898 /* The Thumb2 and ARM encodings are identical. */
10899 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
10900 goto illegal_op;
10901 }
10902 } else if (((insn >> 24) & 3) == 3) {
9ee6e8bb 10903 /* Translate into the equivalent ARM encoding. */
f06053e3 10904 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 10905 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10906 goto illegal_op;
7dcc1f89 10907 }
6a57f3eb 10908 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 10909 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10910 goto illegal_op;
10911 }
9ee6e8bb
PB
10912 } else {
10913 if (insn & (1 << 28))
10914 goto illegal_op;
7dcc1f89 10915 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 10916 goto illegal_op;
7dcc1f89 10917 }
9ee6e8bb
PB
10918 }
10919 break;
10920 case 8: case 9: case 10: case 11:
10921 if (insn & (1 << 15)) {
10922 /* Branches, misc control. */
10923 if (insn & 0x5000) {
10924 /* Unconditional branch. */
10925 /* signextend(hw1[10:0]) -> offset[:12]. */
10926 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
10927 /* hw1[10:0] -> offset[11:1]. */
10928 offset |= (insn & 0x7ff) << 1;
10929 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
10930 offset[24:22] already have the same value because of the
10931 sign extension above. */
10932 offset ^= ((~insn) & (1 << 13)) << 10;
10933 offset ^= ((~insn) & (1 << 11)) << 11;
10934
9ee6e8bb
PB
10935 if (insn & (1 << 14)) {
10936 /* Branch and link. */
3174f8e9 10937 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
b5ff1b31 10938 }
3b46e624 10939
b0109805 10940 offset += s->pc;
9ee6e8bb
PB
10941 if (insn & (1 << 12)) {
10942 /* b/bl */
b0109805 10943 gen_jmp(s, offset);
9ee6e8bb
PB
10944 } else {
10945 /* blx */
b0109805 10946 offset &= ~(uint32_t)2;
be5e7a76 10947 /* thumb2 bx, no need to check */
b0109805 10948 gen_bx_im(s, offset);
2c0262af 10949 }
9ee6e8bb
PB
10950 } else if (((insn >> 23) & 7) == 7) {
10951 /* Misc control */
10952 if (insn & (1 << 13))
10953 goto illegal_op;
10954
10955 if (insn & (1 << 26)) {
001b3cab
PM
10956 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10957 goto illegal_op;
10958 }
37e6456e
PM
10959 if (!(insn & (1 << 20))) {
10960 /* Hypervisor call (v7) */
10961 int imm16 = extract32(insn, 16, 4) << 12
10962 | extract32(insn, 0, 12);
10963 ARCH(7);
10964 if (IS_USER(s)) {
10965 goto illegal_op;
10966 }
10967 gen_hvc(s, imm16);
10968 } else {
10969 /* Secure monitor call (v6+) */
10970 ARCH(6K);
10971 if (IS_USER(s)) {
10972 goto illegal_op;
10973 }
10974 gen_smc(s);
10975 }
2c0262af 10976 } else {
9ee6e8bb
PB
10977 op = (insn >> 20) & 7;
10978 switch (op) {
10979 case 0: /* msr cpsr. */
b53d8923 10980 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e 10981 tmp = load_reg(s, rn);
b28b3377
PM
10982 /* the constant is the mask and SYSm fields */
10983 addr = tcg_const_i32(insn & 0xfff);
8984bd2e 10984 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 10985 tcg_temp_free_i32(addr);
7d1b0095 10986 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10987 gen_lookup_tb(s);
10988 break;
10989 }
10990 /* fall through */
10991 case 1: /* msr spsr. */
b53d8923 10992 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10993 goto illegal_op;
b53d8923 10994 }
8bfd0550
PM
10995
10996 if (extract32(insn, 5, 1)) {
10997 /* MSR (banked) */
10998 int sysm = extract32(insn, 8, 4) |
10999 (extract32(insn, 4, 1) << 4);
11000 int r = op & 1;
11001
11002 gen_msr_banked(s, r, sysm, rm);
11003 break;
11004 }
11005
11006 /* MSR (for PSRs) */
2fbac54b
FN
11007 tmp = load_reg(s, rn);
11008 if (gen_set_psr(s,
7dcc1f89 11009 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 11010 op == 1, tmp))
9ee6e8bb
PB
11011 goto illegal_op;
11012 break;
11013 case 2: /* cps, nop-hint. */
11014 if (((insn >> 8) & 7) == 0) {
11015 gen_nop_hint(s, insn & 0xff);
11016 }
11017 /* Implemented as NOP in user mode. */
11018 if (IS_USER(s))
11019 break;
11020 offset = 0;
11021 imm = 0;
11022 if (insn & (1 << 10)) {
11023 if (insn & (1 << 7))
11024 offset |= CPSR_A;
11025 if (insn & (1 << 6))
11026 offset |= CPSR_I;
11027 if (insn & (1 << 5))
11028 offset |= CPSR_F;
11029 if (insn & (1 << 9))
11030 imm = CPSR_A | CPSR_I | CPSR_F;
11031 }
11032 if (insn & (1 << 8)) {
11033 offset |= 0x1f;
11034 imm |= (insn & 0x1f);
11035 }
11036 if (offset) {
2fbac54b 11037 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
11038 }
11039 break;
11040 case 3: /* Special control operations. */
14120108 11041 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
8297cb13 11042 !arm_dc_feature(s, ARM_FEATURE_M)) {
14120108
JS
11043 goto illegal_op;
11044 }
9ee6e8bb
PB
11045 op = (insn >> 4) & 0xf;
11046 switch (op) {
11047 case 2: /* clrex */
426f5abc 11048 gen_clrex(s);
9ee6e8bb
PB
11049 break;
11050 case 4: /* dsb */
11051 case 5: /* dmb */
61e4c432 11052 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 11053 break;
6df99dec
SS
11054 case 6: /* isb */
11055 /* We need to break the TB after this insn
11056 * to execute self-modifying code correctly
11057 * and also to take any pending interrupts
11058 * immediately.
11059 */
0b609cc1 11060 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 11061 break;
9ee6e8bb
PB
11062 default:
11063 goto illegal_op;
11064 }
11065 break;
11066 case 4: /* bxj */
9d7c59c8
PM
11067 /* Trivial implementation equivalent to bx.
11068 * This instruction doesn't exist at all for M-profile.
11069 */
11070 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11071 goto illegal_op;
11072 }
d9ba4830
PB
11073 tmp = load_reg(s, rn);
11074 gen_bx(s, tmp);
9ee6e8bb
PB
11075 break;
11076 case 5: /* Exception return. */
b8b45b68
RV
11077 if (IS_USER(s)) {
11078 goto illegal_op;
11079 }
11080 if (rn != 14 || rd != 15) {
11081 goto illegal_op;
11082 }
11083 tmp = load_reg(s, rn);
11084 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11085 gen_exception_return(s, tmp);
11086 break;
8bfd0550 11087 case 6: /* MRS */
43ac6574
PM
11088 if (extract32(insn, 5, 1) &&
11089 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
11090 /* MRS (banked) */
11091 int sysm = extract32(insn, 16, 4) |
11092 (extract32(insn, 4, 1) << 4);
11093
11094 gen_mrs_banked(s, 0, sysm, rd);
11095 break;
11096 }
11097
3d54026f
PM
11098 if (extract32(insn, 16, 4) != 0xf) {
11099 goto illegal_op;
11100 }
11101 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
11102 extract32(insn, 0, 8) != 0) {
11103 goto illegal_op;
11104 }
11105
8bfd0550 11106 /* mrs cpsr */
7d1b0095 11107 tmp = tcg_temp_new_i32();
b53d8923 11108 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
11109 addr = tcg_const_i32(insn & 0xff);
11110 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 11111 tcg_temp_free_i32(addr);
9ee6e8bb 11112 } else {
9ef39277 11113 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 11114 }
8984bd2e 11115 store_reg(s, rd, tmp);
9ee6e8bb 11116 break;
8bfd0550 11117 case 7: /* MRS */
43ac6574
PM
11118 if (extract32(insn, 5, 1) &&
11119 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
11120 /* MRS (banked) */
11121 int sysm = extract32(insn, 16, 4) |
11122 (extract32(insn, 4, 1) << 4);
11123
11124 gen_mrs_banked(s, 1, sysm, rd);
11125 break;
11126 }
11127
11128 /* mrs spsr. */
9ee6e8bb 11129 /* Not accessible in user mode. */
b53d8923 11130 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 11131 goto illegal_op;
b53d8923 11132 }
3d54026f
PM
11133
11134 if (extract32(insn, 16, 4) != 0xf ||
11135 extract32(insn, 0, 8) != 0) {
11136 goto illegal_op;
11137 }
11138
d9ba4830
PB
11139 tmp = load_cpu_field(spsr);
11140 store_reg(s, rd, tmp);
9ee6e8bb 11141 break;
2c0262af
FB
11142 }
11143 }
9ee6e8bb
PB
11144 } else {
11145 /* Conditional branch. */
11146 op = (insn >> 22) & 0xf;
11147 /* Generate a conditional jump to next instruction. */
11148 s->condlabel = gen_new_label();
39fb730a 11149 arm_gen_test_cc(op ^ 1, s->condlabel);
9ee6e8bb
PB
11150 s->condjmp = 1;
11151
11152 /* offset[11:1] = insn[10:0] */
11153 offset = (insn & 0x7ff) << 1;
11154 /* offset[17:12] = insn[21:16]. */
11155 offset |= (insn & 0x003f0000) >> 4;
11156 /* offset[31:20] = insn[26]. */
11157 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
11158 /* offset[18] = insn[13]. */
11159 offset |= (insn & (1 << 13)) << 5;
11160 /* offset[19] = insn[11]. */
11161 offset |= (insn & (1 << 11)) << 8;
11162
11163 /* jump to the offset */
b0109805 11164 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
11165 }
11166 } else {
11167 /* Data processing immediate. */
11168 if (insn & (1 << 25)) {
11169 if (insn & (1 << 24)) {
11170 if (insn & (1 << 20))
11171 goto illegal_op;
11172 /* Bitfield/Saturate. */
11173 op = (insn >> 21) & 7;
11174 imm = insn & 0x1f;
11175 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 11176 if (rn == 15) {
7d1b0095 11177 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
11178 tcg_gen_movi_i32(tmp, 0);
11179 } else {
11180 tmp = load_reg(s, rn);
11181 }
9ee6e8bb
PB
11182 switch (op) {
11183 case 2: /* Signed bitfield extract. */
11184 imm++;
11185 if (shift + imm > 32)
11186 goto illegal_op;
59a71b4c
RH
11187 if (imm < 32) {
11188 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
11189 }
9ee6e8bb
PB
11190 break;
11191 case 6: /* Unsigned bitfield extract. */
11192 imm++;
11193 if (shift + imm > 32)
11194 goto illegal_op;
59a71b4c
RH
11195 if (imm < 32) {
11196 tcg_gen_extract_i32(tmp, tmp, shift, imm);
11197 }
9ee6e8bb
PB
11198 break;
11199 case 3: /* Bitfield insert/clear. */
11200 if (imm < shift)
11201 goto illegal_op;
11202 imm = imm + 1 - shift;
11203 if (imm != 32) {
6ddbc6e4 11204 tmp2 = load_reg(s, rd);
d593c48e 11205 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 11206 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11207 }
11208 break;
11209 case 7:
11210 goto illegal_op;
11211 default: /* Saturate. */
9ee6e8bb
PB
11212 if (shift) {
11213 if (op & 1)
6ddbc6e4 11214 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 11215 else
6ddbc6e4 11216 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 11217 }
6ddbc6e4 11218 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
11219 if (op & 4) {
11220 /* Unsigned. */
62b44f05
AR
11221 if ((op & 1) && shift == 0) {
11222 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11223 tcg_temp_free_i32(tmp);
11224 tcg_temp_free_i32(tmp2);
11225 goto illegal_op;
11226 }
9ef39277 11227 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 11228 } else {
9ef39277 11229 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 11230 }
2c0262af 11231 } else {
9ee6e8bb 11232 /* Signed. */
62b44f05
AR
11233 if ((op & 1) && shift == 0) {
11234 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11235 tcg_temp_free_i32(tmp);
11236 tcg_temp_free_i32(tmp2);
11237 goto illegal_op;
11238 }
9ef39277 11239 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 11240 } else {
9ef39277 11241 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 11242 }
2c0262af 11243 }
b75263d6 11244 tcg_temp_free_i32(tmp2);
9ee6e8bb 11245 break;
2c0262af 11246 }
6ddbc6e4 11247 store_reg(s, rd, tmp);
9ee6e8bb
PB
11248 } else {
11249 imm = ((insn & 0x04000000) >> 15)
11250 | ((insn & 0x7000) >> 4) | (insn & 0xff);
11251 if (insn & (1 << 22)) {
11252 /* 16-bit immediate. */
11253 imm |= (insn >> 4) & 0xf000;
11254 if (insn & (1 << 23)) {
11255 /* movt */
5e3f878a 11256 tmp = load_reg(s, rd);
86831435 11257 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 11258 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 11259 } else {
9ee6e8bb 11260 /* movw */
7d1b0095 11261 tmp = tcg_temp_new_i32();
5e3f878a 11262 tcg_gen_movi_i32(tmp, imm);
2c0262af
FB
11263 }
11264 } else {
9ee6e8bb
PB
11265 /* Add/sub 12-bit immediate. */
11266 if (rn == 15) {
b0109805 11267 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 11268 if (insn & (1 << 23))
b0109805 11269 offset -= imm;
9ee6e8bb 11270 else
b0109805 11271 offset += imm;
7d1b0095 11272 tmp = tcg_temp_new_i32();
5e3f878a 11273 tcg_gen_movi_i32(tmp, offset);
2c0262af 11274 } else {
5e3f878a 11275 tmp = load_reg(s, rn);
9ee6e8bb 11276 if (insn & (1 << 23))
5e3f878a 11277 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 11278 else
5e3f878a 11279 tcg_gen_addi_i32(tmp, tmp, imm);
2c0262af 11280 }
9ee6e8bb 11281 }
5e3f878a 11282 store_reg(s, rd, tmp);
191abaa2 11283 }
9ee6e8bb
PB
11284 } else {
11285 int shifter_out = 0;
11286 /* modified 12-bit immediate. */
11287 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
11288 imm = (insn & 0xff);
11289 switch (shift) {
11290 case 0: /* XY */
11291 /* Nothing to do. */
11292 break;
11293 case 1: /* 00XY00XY */
11294 imm |= imm << 16;
11295 break;
11296 case 2: /* XY00XY00 */
11297 imm |= imm << 16;
11298 imm <<= 8;
11299 break;
11300 case 3: /* XYXYXYXY */
11301 imm |= imm << 16;
11302 imm |= imm << 8;
11303 break;
11304 default: /* Rotated constant. */
11305 shift = (shift << 1) | (imm >> 7);
11306 imm |= 0x80;
11307 imm = imm << (32 - shift);
11308 shifter_out = 1;
11309 break;
b5ff1b31 11310 }
7d1b0095 11311 tmp2 = tcg_temp_new_i32();
3174f8e9 11312 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 11313 rn = (insn >> 16) & 0xf;
3174f8e9 11314 if (rn == 15) {
7d1b0095 11315 tmp = tcg_temp_new_i32();
3174f8e9
FN
11316 tcg_gen_movi_i32(tmp, 0);
11317 } else {
11318 tmp = load_reg(s, rn);
11319 }
9ee6e8bb
PB
11320 op = (insn >> 21) & 0xf;
11321 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 11322 shifter_out, tmp, tmp2))
9ee6e8bb 11323 goto illegal_op;
7d1b0095 11324 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11325 rd = (insn >> 8) & 0xf;
11326 if (rd != 15) {
3174f8e9
FN
11327 store_reg(s, rd, tmp);
11328 } else {
7d1b0095 11329 tcg_temp_free_i32(tmp);
2c0262af 11330 }
2c0262af 11331 }
9ee6e8bb
PB
11332 }
11333 break;
11334 case 12: /* Load/store single data item. */
11335 {
11336 int postinc = 0;
11337 int writeback = 0;
a99caa48 11338 int memidx;
9bb6558a
PM
11339 ISSInfo issinfo;
11340
9ee6e8bb 11341 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 11342 if (disas_neon_ls_insn(s, insn)) {
c1713132 11343 goto illegal_op;
7dcc1f89 11344 }
9ee6e8bb
PB
11345 break;
11346 }
a2fdc890
PM
11347 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
11348 if (rs == 15) {
11349 if (!(insn & (1 << 20))) {
11350 goto illegal_op;
11351 }
11352 if (op != 2) {
11353 /* Byte or halfword load space with dest == r15 : memory hints.
11354 * Catch them early so we don't emit pointless addressing code.
11355 * This space is a mix of:
11356 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
11357 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
11358 * cores)
11359 * unallocated hints, which must be treated as NOPs
11360 * UNPREDICTABLE space, which we NOP or UNDEF depending on
11361 * which is easiest for the decoding logic
11362 * Some space which must UNDEF
11363 */
11364 int op1 = (insn >> 23) & 3;
11365 int op2 = (insn >> 6) & 0x3f;
11366 if (op & 2) {
11367 goto illegal_op;
11368 }
11369 if (rn == 15) {
02afbf64
PM
11370 /* UNPREDICTABLE, unallocated hint or
11371 * PLD/PLDW/PLI (literal)
11372 */
2eea841c 11373 return;
a2fdc890
PM
11374 }
11375 if (op1 & 1) {
2eea841c 11376 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
11377 }
11378 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
2eea841c 11379 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
11380 }
11381 /* UNDEF space, or an UNPREDICTABLE */
2eea841c 11382 goto illegal_op;
a2fdc890
PM
11383 }
11384 }
a99caa48 11385 memidx = get_mem_index(s);
9ee6e8bb 11386 if (rn == 15) {
7d1b0095 11387 addr = tcg_temp_new_i32();
9ee6e8bb
PB
11388 /* PC relative. */
11389 /* s->pc has already been incremented by 4. */
11390 imm = s->pc & 0xfffffffc;
11391 if (insn & (1 << 23))
11392 imm += insn & 0xfff;
11393 else
11394 imm -= insn & 0xfff;
b0109805 11395 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 11396 } else {
b0109805 11397 addr = load_reg(s, rn);
9ee6e8bb
PB
11398 if (insn & (1 << 23)) {
11399 /* Positive offset. */
11400 imm = insn & 0xfff;
b0109805 11401 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb 11402 } else {
9ee6e8bb 11403 imm = insn & 0xff;
2a0308c5
PM
11404 switch ((insn >> 8) & 0xf) {
11405 case 0x0: /* Shifted Register. */
9ee6e8bb 11406 shift = (insn >> 4) & 0xf;
2a0308c5
PM
11407 if (shift > 3) {
11408 tcg_temp_free_i32(addr);
18c9b560 11409 goto illegal_op;
2a0308c5 11410 }
b26eefb6 11411 tmp = load_reg(s, rm);
9ee6e8bb 11412 if (shift)
b26eefb6 11413 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 11414 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 11415 tcg_temp_free_i32(tmp);
9ee6e8bb 11416 break;
2a0308c5 11417 case 0xc: /* Negative offset. */
b0109805 11418 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb 11419 break;
2a0308c5 11420 case 0xe: /* User privilege. */
b0109805 11421 tcg_gen_addi_i32(addr, addr, imm);
579d21cc 11422 memidx = get_a32_user_mem_index(s);
9ee6e8bb 11423 break;
2a0308c5 11424 case 0x9: /* Post-decrement. */
9ee6e8bb
PB
11425 imm = -imm;
11426 /* Fall through. */
2a0308c5 11427 case 0xb: /* Post-increment. */
9ee6e8bb
PB
11428 postinc = 1;
11429 writeback = 1;
11430 break;
2a0308c5 11431 case 0xd: /* Pre-decrement. */
9ee6e8bb
PB
11432 imm = -imm;
11433 /* Fall through. */
2a0308c5 11434 case 0xf: /* Pre-increment. */
b0109805 11435 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb
PB
11436 writeback = 1;
11437 break;
11438 default:
2a0308c5 11439 tcg_temp_free_i32(addr);
b7bcbe95 11440 goto illegal_op;
9ee6e8bb
PB
11441 }
11442 }
11443 }
9bb6558a
PM
11444
11445 issinfo = writeback ? ISSInvalid : rs;
11446
9ee6e8bb
PB
11447 if (insn & (1 << 20)) {
11448 /* Load. */
5a839c0d 11449 tmp = tcg_temp_new_i32();
a2fdc890 11450 switch (op) {
5a839c0d 11451 case 0:
9bb6558a 11452 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11453 break;
11454 case 4:
9bb6558a 11455 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11456 break;
11457 case 1:
9bb6558a 11458 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11459 break;
11460 case 5:
9bb6558a 11461 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11462 break;
11463 case 2:
9bb6558a 11464 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 11465 break;
2a0308c5 11466 default:
5a839c0d 11467 tcg_temp_free_i32(tmp);
2a0308c5
PM
11468 tcg_temp_free_i32(addr);
11469 goto illegal_op;
a2fdc890
PM
11470 }
11471 if (rs == 15) {
3bb8a96f 11472 gen_bx_excret(s, tmp);
9ee6e8bb 11473 } else {
a2fdc890 11474 store_reg(s, rs, tmp);
9ee6e8bb
PB
11475 }
11476 } else {
11477 /* Store. */
b0109805 11478 tmp = load_reg(s, rs);
9ee6e8bb 11479 switch (op) {
5a839c0d 11480 case 0:
9bb6558a 11481 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11482 break;
11483 case 1:
9bb6558a 11484 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
11485 break;
11486 case 2:
9bb6558a 11487 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 11488 break;
2a0308c5 11489 default:
5a839c0d 11490 tcg_temp_free_i32(tmp);
2a0308c5
PM
11491 tcg_temp_free_i32(addr);
11492 goto illegal_op;
b7bcbe95 11493 }
5a839c0d 11494 tcg_temp_free_i32(tmp);
2c0262af 11495 }
9ee6e8bb 11496 if (postinc)
b0109805
PB
11497 tcg_gen_addi_i32(addr, addr, imm);
11498 if (writeback) {
11499 store_reg(s, rn, addr);
11500 } else {
7d1b0095 11501 tcg_temp_free_i32(addr);
b0109805 11502 }
9ee6e8bb
PB
11503 }
11504 break;
11505 default:
11506 goto illegal_op;
2c0262af 11507 }
2eea841c 11508 return;
9ee6e8bb 11509illegal_op:
2eea841c
PM
11510 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11511 default_exception_el(s));
2c0262af
FB
11512}
11513
296e5a0a 11514static void disas_thumb_insn(DisasContext *s, uint32_t insn)
99c475ab 11515{
296e5a0a 11516 uint32_t val, op, rm, rn, rd, shift, cond;
99c475ab
FB
11517 int32_t offset;
11518 int i;
39d5492a
PM
11519 TCGv_i32 tmp;
11520 TCGv_i32 tmp2;
11521 TCGv_i32 addr;
99c475ab 11522
99c475ab
FB
11523 switch (insn >> 12) {
11524 case 0: case 1:
396e467c 11525
99c475ab
FB
11526 rd = insn & 7;
11527 op = (insn >> 11) & 3;
11528 if (op == 3) {
11529 /* add/subtract */
11530 rn = (insn >> 3) & 7;
396e467c 11531 tmp = load_reg(s, rn);
99c475ab
FB
11532 if (insn & (1 << 10)) {
11533 /* immediate */
7d1b0095 11534 tmp2 = tcg_temp_new_i32();
396e467c 11535 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
11536 } else {
11537 /* reg */
11538 rm = (insn >> 6) & 7;
396e467c 11539 tmp2 = load_reg(s, rm);
99c475ab 11540 }
9ee6e8bb
PB
11541 if (insn & (1 << 9)) {
11542 if (s->condexec_mask)
396e467c 11543 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 11544 else
72485ec4 11545 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
11546 } else {
11547 if (s->condexec_mask)
396e467c 11548 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 11549 else
72485ec4 11550 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 11551 }
7d1b0095 11552 tcg_temp_free_i32(tmp2);
396e467c 11553 store_reg(s, rd, tmp);
99c475ab
FB
11554 } else {
11555 /* shift immediate */
11556 rm = (insn >> 3) & 7;
11557 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
11558 tmp = load_reg(s, rm);
11559 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
11560 if (!s->condexec_mask)
11561 gen_logic_CC(tmp);
11562 store_reg(s, rd, tmp);
99c475ab
FB
11563 }
11564 break;
11565 case 2: case 3:
11566 /* arithmetic large immediate */
11567 op = (insn >> 11) & 3;
11568 rd = (insn >> 8) & 0x7;
396e467c 11569 if (op == 0) { /* mov */
7d1b0095 11570 tmp = tcg_temp_new_i32();
396e467c 11571 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 11572 if (!s->condexec_mask)
396e467c
FN
11573 gen_logic_CC(tmp);
11574 store_reg(s, rd, tmp);
11575 } else {
11576 tmp = load_reg(s, rd);
7d1b0095 11577 tmp2 = tcg_temp_new_i32();
396e467c
FN
11578 tcg_gen_movi_i32(tmp2, insn & 0xff);
11579 switch (op) {
11580 case 1: /* cmp */
72485ec4 11581 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11582 tcg_temp_free_i32(tmp);
11583 tcg_temp_free_i32(tmp2);
396e467c
FN
11584 break;
11585 case 2: /* add */
11586 if (s->condexec_mask)
11587 tcg_gen_add_i32(tmp, tmp, tmp2);
11588 else
72485ec4 11589 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 11590 tcg_temp_free_i32(tmp2);
396e467c
FN
11591 store_reg(s, rd, tmp);
11592 break;
11593 case 3: /* sub */
11594 if (s->condexec_mask)
11595 tcg_gen_sub_i32(tmp, tmp, tmp2);
11596 else
72485ec4 11597 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 11598 tcg_temp_free_i32(tmp2);
396e467c
FN
11599 store_reg(s, rd, tmp);
11600 break;
11601 }
99c475ab 11602 }
99c475ab
FB
11603 break;
11604 case 4:
11605 if (insn & (1 << 11)) {
11606 rd = (insn >> 8) & 7;
5899f386
FB
11607 /* load pc-relative. Bit 1 of PC is ignored. */
11608 val = s->pc + 2 + ((insn & 0xff) * 4);
11609 val &= ~(uint32_t)2;
7d1b0095 11610 addr = tcg_temp_new_i32();
b0109805 11611 tcg_gen_movi_i32(addr, val);
c40c8556 11612 tmp = tcg_temp_new_i32();
9bb6558a
PM
11613 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11614 rd | ISSIs16Bit);
7d1b0095 11615 tcg_temp_free_i32(addr);
b0109805 11616 store_reg(s, rd, tmp);
99c475ab
FB
11617 break;
11618 }
11619 if (insn & (1 << 10)) {
ebfe27c5
PM
11620 /* 0b0100_01xx_xxxx_xxxx
11621 * - data processing extended, branch and exchange
11622 */
99c475ab
FB
11623 rd = (insn & 7) | ((insn >> 4) & 8);
11624 rm = (insn >> 3) & 0xf;
11625 op = (insn >> 8) & 3;
11626 switch (op) {
11627 case 0: /* add */
396e467c
FN
11628 tmp = load_reg(s, rd);
11629 tmp2 = load_reg(s, rm);
11630 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11631 tcg_temp_free_i32(tmp2);
396e467c 11632 store_reg(s, rd, tmp);
99c475ab
FB
11633 break;
11634 case 1: /* cmp */
396e467c
FN
11635 tmp = load_reg(s, rd);
11636 tmp2 = load_reg(s, rm);
72485ec4 11637 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11638 tcg_temp_free_i32(tmp2);
11639 tcg_temp_free_i32(tmp);
99c475ab
FB
11640 break;
11641 case 2: /* mov/cpy */
396e467c
FN
11642 tmp = load_reg(s, rm);
11643 store_reg(s, rd, tmp);
99c475ab 11644 break;
ebfe27c5
PM
11645 case 3:
11646 {
11647 /* 0b0100_0111_xxxx_xxxx
11648 * - branch [and link] exchange thumb register
11649 */
11650 bool link = insn & (1 << 7);
11651
fb602cb7 11652 if (insn & 3) {
ebfe27c5
PM
11653 goto undef;
11654 }
11655 if (link) {
be5e7a76 11656 ARCH(5);
ebfe27c5 11657 }
fb602cb7
PM
11658 if ((insn & 4)) {
11659 /* BXNS/BLXNS: only exists for v8M with the
11660 * security extensions, and always UNDEF if NonSecure.
11661 * We don't implement these in the user-only mode
11662 * either (in theory you can use them from Secure User
11663 * mode but they are too tied in to system emulation.)
11664 */
11665 if (!s->v8m_secure || IS_USER_ONLY) {
11666 goto undef;
11667 }
11668 if (link) {
3e3fa230 11669 gen_blxns(s, rm);
fb602cb7
PM
11670 } else {
11671 gen_bxns(s, rm);
11672 }
11673 break;
11674 }
11675 /* BLX/BX */
ebfe27c5
PM
11676 tmp = load_reg(s, rm);
11677 if (link) {
99c475ab 11678 val = (uint32_t)s->pc | 1;
7d1b0095 11679 tmp2 = tcg_temp_new_i32();
b0109805
PB
11680 tcg_gen_movi_i32(tmp2, val);
11681 store_reg(s, 14, tmp2);
3bb8a96f
PM
11682 gen_bx(s, tmp);
11683 } else {
11684 /* Only BX works as exception-return, not BLX */
11685 gen_bx_excret(s, tmp);
99c475ab 11686 }
99c475ab
FB
11687 break;
11688 }
ebfe27c5 11689 }
99c475ab
FB
11690 break;
11691 }
11692
11693 /* data processing register */
11694 rd = insn & 7;
11695 rm = (insn >> 3) & 7;
11696 op = (insn >> 6) & 0xf;
11697 if (op == 2 || op == 3 || op == 4 || op == 7) {
11698 /* the shift/rotate ops want the operands backwards */
11699 val = rm;
11700 rm = rd;
11701 rd = val;
11702 val = 1;
11703 } else {
11704 val = 0;
11705 }
11706
396e467c 11707 if (op == 9) { /* neg */
7d1b0095 11708 tmp = tcg_temp_new_i32();
396e467c
FN
11709 tcg_gen_movi_i32(tmp, 0);
11710 } else if (op != 0xf) { /* mvn doesn't read its first operand */
11711 tmp = load_reg(s, rd);
11712 } else {
f764718d 11713 tmp = NULL;
396e467c 11714 }
99c475ab 11715
396e467c 11716 tmp2 = load_reg(s, rm);
5899f386 11717 switch (op) {
99c475ab 11718 case 0x0: /* and */
396e467c 11719 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 11720 if (!s->condexec_mask)
396e467c 11721 gen_logic_CC(tmp);
99c475ab
FB
11722 break;
11723 case 0x1: /* eor */
396e467c 11724 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 11725 if (!s->condexec_mask)
396e467c 11726 gen_logic_CC(tmp);
99c475ab
FB
11727 break;
11728 case 0x2: /* lsl */
9ee6e8bb 11729 if (s->condexec_mask) {
365af80e 11730 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 11731 } else {
9ef39277 11732 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11733 gen_logic_CC(tmp2);
9ee6e8bb 11734 }
99c475ab
FB
11735 break;
11736 case 0x3: /* lsr */
9ee6e8bb 11737 if (s->condexec_mask) {
365af80e 11738 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 11739 } else {
9ef39277 11740 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11741 gen_logic_CC(tmp2);
9ee6e8bb 11742 }
99c475ab
FB
11743 break;
11744 case 0x4: /* asr */
9ee6e8bb 11745 if (s->condexec_mask) {
365af80e 11746 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 11747 } else {
9ef39277 11748 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11749 gen_logic_CC(tmp2);
9ee6e8bb 11750 }
99c475ab
FB
11751 break;
11752 case 0x5: /* adc */
49b4c31e 11753 if (s->condexec_mask) {
396e467c 11754 gen_adc(tmp, tmp2);
49b4c31e
RH
11755 } else {
11756 gen_adc_CC(tmp, tmp, tmp2);
11757 }
99c475ab
FB
11758 break;
11759 case 0x6: /* sbc */
2de68a49 11760 if (s->condexec_mask) {
396e467c 11761 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
11762 } else {
11763 gen_sbc_CC(tmp, tmp, tmp2);
11764 }
99c475ab
FB
11765 break;
11766 case 0x7: /* ror */
9ee6e8bb 11767 if (s->condexec_mask) {
f669df27
AJ
11768 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11769 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 11770 } else {
9ef39277 11771 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11772 gen_logic_CC(tmp2);
9ee6e8bb 11773 }
99c475ab
FB
11774 break;
11775 case 0x8: /* tst */
396e467c
FN
11776 tcg_gen_and_i32(tmp, tmp, tmp2);
11777 gen_logic_CC(tmp);
99c475ab 11778 rd = 16;
5899f386 11779 break;
99c475ab 11780 case 0x9: /* neg */
9ee6e8bb 11781 if (s->condexec_mask)
396e467c 11782 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 11783 else
72485ec4 11784 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11785 break;
11786 case 0xa: /* cmp */
72485ec4 11787 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11788 rd = 16;
11789 break;
11790 case 0xb: /* cmn */
72485ec4 11791 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
11792 rd = 16;
11793 break;
11794 case 0xc: /* orr */
396e467c 11795 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 11796 if (!s->condexec_mask)
396e467c 11797 gen_logic_CC(tmp);
99c475ab
FB
11798 break;
11799 case 0xd: /* mul */
7b2919a0 11800 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 11801 if (!s->condexec_mask)
396e467c 11802 gen_logic_CC(tmp);
99c475ab
FB
11803 break;
11804 case 0xe: /* bic */
f669df27 11805 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 11806 if (!s->condexec_mask)
396e467c 11807 gen_logic_CC(tmp);
99c475ab
FB
11808 break;
11809 case 0xf: /* mvn */
396e467c 11810 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 11811 if (!s->condexec_mask)
396e467c 11812 gen_logic_CC(tmp2);
99c475ab 11813 val = 1;
5899f386 11814 rm = rd;
99c475ab
FB
11815 break;
11816 }
11817 if (rd != 16) {
396e467c
FN
11818 if (val) {
11819 store_reg(s, rm, tmp2);
11820 if (op != 0xf)
7d1b0095 11821 tcg_temp_free_i32(tmp);
396e467c
FN
11822 } else {
11823 store_reg(s, rd, tmp);
7d1b0095 11824 tcg_temp_free_i32(tmp2);
396e467c
FN
11825 }
11826 } else {
7d1b0095
PM
11827 tcg_temp_free_i32(tmp);
11828 tcg_temp_free_i32(tmp2);
99c475ab
FB
11829 }
11830 break;
11831
11832 case 5:
11833 /* load/store register offset. */
11834 rd = insn & 7;
11835 rn = (insn >> 3) & 7;
11836 rm = (insn >> 6) & 7;
11837 op = (insn >> 9) & 7;
b0109805 11838 addr = load_reg(s, rn);
b26eefb6 11839 tmp = load_reg(s, rm);
b0109805 11840 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 11841 tcg_temp_free_i32(tmp);
99c475ab 11842
c40c8556 11843 if (op < 3) { /* store */
b0109805 11844 tmp = load_reg(s, rd);
c40c8556
PM
11845 } else {
11846 tmp = tcg_temp_new_i32();
11847 }
99c475ab
FB
11848
11849 switch (op) {
11850 case 0: /* str */
9bb6558a 11851 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11852 break;
11853 case 1: /* strh */
9bb6558a 11854 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11855 break;
11856 case 2: /* strb */
9bb6558a 11857 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11858 break;
11859 case 3: /* ldrsb */
9bb6558a 11860 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11861 break;
11862 case 4: /* ldr */
9bb6558a 11863 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11864 break;
11865 case 5: /* ldrh */
9bb6558a 11866 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11867 break;
11868 case 6: /* ldrb */
9bb6558a 11869 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11870 break;
11871 case 7: /* ldrsh */
9bb6558a 11872 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11873 break;
11874 }
c40c8556 11875 if (op >= 3) { /* load */
b0109805 11876 store_reg(s, rd, tmp);
c40c8556
PM
11877 } else {
11878 tcg_temp_free_i32(tmp);
11879 }
7d1b0095 11880 tcg_temp_free_i32(addr);
99c475ab
FB
11881 break;
11882
11883 case 6:
11884 /* load/store word immediate offset */
11885 rd = insn & 7;
11886 rn = (insn >> 3) & 7;
b0109805 11887 addr = load_reg(s, rn);
99c475ab 11888 val = (insn >> 4) & 0x7c;
b0109805 11889 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11890
11891 if (insn & (1 << 11)) {
11892 /* load */
c40c8556 11893 tmp = tcg_temp_new_i32();
12dcc321 11894 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11895 store_reg(s, rd, tmp);
99c475ab
FB
11896 } else {
11897 /* store */
b0109805 11898 tmp = load_reg(s, rd);
12dcc321 11899 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11900 tcg_temp_free_i32(tmp);
99c475ab 11901 }
7d1b0095 11902 tcg_temp_free_i32(addr);
99c475ab
FB
11903 break;
11904
11905 case 7:
11906 /* load/store byte immediate offset */
11907 rd = insn & 7;
11908 rn = (insn >> 3) & 7;
b0109805 11909 addr = load_reg(s, rn);
99c475ab 11910 val = (insn >> 6) & 0x1f;
b0109805 11911 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11912
11913 if (insn & (1 << 11)) {
11914 /* load */
c40c8556 11915 tmp = tcg_temp_new_i32();
9bb6558a 11916 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11917 store_reg(s, rd, tmp);
99c475ab
FB
11918 } else {
11919 /* store */
b0109805 11920 tmp = load_reg(s, rd);
9bb6558a 11921 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11922 tcg_temp_free_i32(tmp);
99c475ab 11923 }
7d1b0095 11924 tcg_temp_free_i32(addr);
99c475ab
FB
11925 break;
11926
11927 case 8:
11928 /* load/store halfword immediate offset */
11929 rd = insn & 7;
11930 rn = (insn >> 3) & 7;
b0109805 11931 addr = load_reg(s, rn);
99c475ab 11932 val = (insn >> 5) & 0x3e;
b0109805 11933 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11934
11935 if (insn & (1 << 11)) {
11936 /* load */
c40c8556 11937 tmp = tcg_temp_new_i32();
9bb6558a 11938 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11939 store_reg(s, rd, tmp);
99c475ab
FB
11940 } else {
11941 /* store */
b0109805 11942 tmp = load_reg(s, rd);
9bb6558a 11943 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11944 tcg_temp_free_i32(tmp);
99c475ab 11945 }
7d1b0095 11946 tcg_temp_free_i32(addr);
99c475ab
FB
11947 break;
11948
11949 case 9:
11950 /* load/store from stack */
11951 rd = (insn >> 8) & 7;
b0109805 11952 addr = load_reg(s, 13);
99c475ab 11953 val = (insn & 0xff) * 4;
b0109805 11954 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11955
11956 if (insn & (1 << 11)) {
11957 /* load */
c40c8556 11958 tmp = tcg_temp_new_i32();
9bb6558a 11959 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11960 store_reg(s, rd, tmp);
99c475ab
FB
11961 } else {
11962 /* store */
b0109805 11963 tmp = load_reg(s, rd);
9bb6558a 11964 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11965 tcg_temp_free_i32(tmp);
99c475ab 11966 }
7d1b0095 11967 tcg_temp_free_i32(addr);
99c475ab
FB
11968 break;
11969
11970 case 10:
11971 /* add to high reg */
11972 rd = (insn >> 8) & 7;
5899f386
FB
11973 if (insn & (1 << 11)) {
11974 /* SP */
5e3f878a 11975 tmp = load_reg(s, 13);
5899f386
FB
11976 } else {
11977 /* PC. bit 1 is ignored. */
7d1b0095 11978 tmp = tcg_temp_new_i32();
5e3f878a 11979 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 11980 }
99c475ab 11981 val = (insn & 0xff) * 4;
5e3f878a
PB
11982 tcg_gen_addi_i32(tmp, tmp, val);
11983 store_reg(s, rd, tmp);
99c475ab
FB
11984 break;
11985
11986 case 11:
11987 /* misc */
11988 op = (insn >> 8) & 0xf;
11989 switch (op) {
11990 case 0:
11991 /* adjust stack pointer */
b26eefb6 11992 tmp = load_reg(s, 13);
99c475ab
FB
11993 val = (insn & 0x7f) * 4;
11994 if (insn & (1 << 7))
6a0d8a1d 11995 val = -(int32_t)val;
b26eefb6
PB
11996 tcg_gen_addi_i32(tmp, tmp, val);
11997 store_reg(s, 13, tmp);
99c475ab
FB
11998 break;
11999
9ee6e8bb
PB
12000 case 2: /* sign/zero extend. */
12001 ARCH(6);
12002 rd = insn & 7;
12003 rm = (insn >> 3) & 7;
b0109805 12004 tmp = load_reg(s, rm);
9ee6e8bb 12005 switch ((insn >> 6) & 3) {
b0109805
PB
12006 case 0: gen_sxth(tmp); break;
12007 case 1: gen_sxtb(tmp); break;
12008 case 2: gen_uxth(tmp); break;
12009 case 3: gen_uxtb(tmp); break;
9ee6e8bb 12010 }
b0109805 12011 store_reg(s, rd, tmp);
9ee6e8bb 12012 break;
99c475ab
FB
12013 case 4: case 5: case 0xc: case 0xd:
12014 /* push/pop */
b0109805 12015 addr = load_reg(s, 13);
5899f386
FB
12016 if (insn & (1 << 8))
12017 offset = 4;
99c475ab 12018 else
5899f386
FB
12019 offset = 0;
12020 for (i = 0; i < 8; i++) {
12021 if (insn & (1 << i))
12022 offset += 4;
12023 }
12024 if ((insn & (1 << 11)) == 0) {
b0109805 12025 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 12026 }
99c475ab
FB
12027 for (i = 0; i < 8; i++) {
12028 if (insn & (1 << i)) {
12029 if (insn & (1 << 11)) {
12030 /* pop */
c40c8556 12031 tmp = tcg_temp_new_i32();
12dcc321 12032 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 12033 store_reg(s, i, tmp);
99c475ab
FB
12034 } else {
12035 /* push */
b0109805 12036 tmp = load_reg(s, i);
12dcc321 12037 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12038 tcg_temp_free_i32(tmp);
99c475ab 12039 }
5899f386 12040 /* advance to the next address. */
b0109805 12041 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
12042 }
12043 }
f764718d 12044 tmp = NULL;
99c475ab
FB
12045 if (insn & (1 << 8)) {
12046 if (insn & (1 << 11)) {
12047 /* pop pc */
c40c8556 12048 tmp = tcg_temp_new_i32();
12dcc321 12049 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
12050 /* don't set the pc until the rest of the instruction
12051 has completed */
12052 } else {
12053 /* push lr */
b0109805 12054 tmp = load_reg(s, 14);
12dcc321 12055 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12056 tcg_temp_free_i32(tmp);
99c475ab 12057 }
b0109805 12058 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 12059 }
5899f386 12060 if ((insn & (1 << 11)) == 0) {
b0109805 12061 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 12062 }
99c475ab 12063 /* write back the new stack pointer */
b0109805 12064 store_reg(s, 13, addr);
99c475ab 12065 /* set the new PC value */
be5e7a76 12066 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 12067 store_reg_from_load(s, 15, tmp);
be5e7a76 12068 }
99c475ab
FB
12069 break;
12070
9ee6e8bb
PB
12071 case 1: case 3: case 9: case 11: /* czb */
12072 rm = insn & 7;
d9ba4830 12073 tmp = load_reg(s, rm);
9ee6e8bb
PB
12074 s->condlabel = gen_new_label();
12075 s->condjmp = 1;
12076 if (insn & (1 << 11))
cb63669a 12077 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 12078 else
cb63669a 12079 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 12080 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
12081 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
12082 val = (uint32_t)s->pc + 2;
12083 val += offset;
12084 gen_jmp(s, val);
12085 break;
12086
12087 case 15: /* IT, nop-hint. */
12088 if ((insn & 0xf) == 0) {
12089 gen_nop_hint(s, (insn >> 4) & 0xf);
12090 break;
12091 }
12092 /* If Then. */
12093 s->condexec_cond = (insn >> 4) & 0xe;
12094 s->condexec_mask = insn & 0x1f;
12095 /* No actual code generated for this insn, just setup state. */
12096 break;
12097
06c949e6 12098 case 0xe: /* bkpt */
d4a2dc67
PM
12099 {
12100 int imm8 = extract32(insn, 0, 8);
be5e7a76 12101 ARCH(5);
c900a2e6 12102 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
06c949e6 12103 break;
d4a2dc67 12104 }
06c949e6 12105
19a6e31c
PM
12106 case 0xa: /* rev, and hlt */
12107 {
12108 int op1 = extract32(insn, 6, 2);
12109
12110 if (op1 == 2) {
12111 /* HLT */
12112 int imm6 = extract32(insn, 0, 6);
12113
12114 gen_hlt(s, imm6);
12115 break;
12116 }
12117
12118 /* Otherwise this is rev */
9ee6e8bb
PB
12119 ARCH(6);
12120 rn = (insn >> 3) & 0x7;
12121 rd = insn & 0x7;
b0109805 12122 tmp = load_reg(s, rn);
19a6e31c 12123 switch (op1) {
66896cb8 12124 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
12125 case 1: gen_rev16(tmp); break;
12126 case 3: gen_revsh(tmp); break;
19a6e31c
PM
12127 default:
12128 g_assert_not_reached();
9ee6e8bb 12129 }
b0109805 12130 store_reg(s, rd, tmp);
9ee6e8bb 12131 break;
19a6e31c 12132 }
9ee6e8bb 12133
d9e028c1
PM
12134 case 6:
12135 switch ((insn >> 5) & 7) {
12136 case 2:
12137 /* setend */
12138 ARCH(6);
9886ecdf
PB
12139 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
12140 gen_helper_setend(cpu_env);
dcba3a8d 12141 s->base.is_jmp = DISAS_UPDATE;
d9e028c1 12142 }
9ee6e8bb 12143 break;
d9e028c1
PM
12144 case 3:
12145 /* cps */
12146 ARCH(6);
12147 if (IS_USER(s)) {
12148 break;
8984bd2e 12149 }
b53d8923 12150 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
12151 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
12152 /* FAULTMASK */
12153 if (insn & 1) {
12154 addr = tcg_const_i32(19);
12155 gen_helper_v7m_msr(cpu_env, addr, tmp);
12156 tcg_temp_free_i32(addr);
12157 }
12158 /* PRIMASK */
12159 if (insn & 2) {
12160 addr = tcg_const_i32(16);
12161 gen_helper_v7m_msr(cpu_env, addr, tmp);
12162 tcg_temp_free_i32(addr);
12163 }
12164 tcg_temp_free_i32(tmp);
12165 gen_lookup_tb(s);
12166 } else {
12167 if (insn & (1 << 4)) {
12168 shift = CPSR_A | CPSR_I | CPSR_F;
12169 } else {
12170 shift = 0;
12171 }
12172 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 12173 }
d9e028c1
PM
12174 break;
12175 default:
12176 goto undef;
9ee6e8bb
PB
12177 }
12178 break;
12179
99c475ab
FB
12180 default:
12181 goto undef;
12182 }
12183 break;
12184
12185 case 12:
a7d3970d 12186 {
99c475ab 12187 /* load/store multiple */
f764718d 12188 TCGv_i32 loaded_var = NULL;
99c475ab 12189 rn = (insn >> 8) & 0x7;
b0109805 12190 addr = load_reg(s, rn);
99c475ab
FB
12191 for (i = 0; i < 8; i++) {
12192 if (insn & (1 << i)) {
99c475ab
FB
12193 if (insn & (1 << 11)) {
12194 /* load */
c40c8556 12195 tmp = tcg_temp_new_i32();
12dcc321 12196 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
a7d3970d
PM
12197 if (i == rn) {
12198 loaded_var = tmp;
12199 } else {
12200 store_reg(s, i, tmp);
12201 }
99c475ab
FB
12202 } else {
12203 /* store */
b0109805 12204 tmp = load_reg(s, i);
12dcc321 12205 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12206 tcg_temp_free_i32(tmp);
99c475ab 12207 }
5899f386 12208 /* advance to the next address */
b0109805 12209 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
12210 }
12211 }
b0109805 12212 if ((insn & (1 << rn)) == 0) {
a7d3970d 12213 /* base reg not in list: base register writeback */
b0109805
PB
12214 store_reg(s, rn, addr);
12215 } else {
a7d3970d
PM
12216 /* base reg in list: if load, complete it now */
12217 if (insn & (1 << 11)) {
12218 store_reg(s, rn, loaded_var);
12219 }
7d1b0095 12220 tcg_temp_free_i32(addr);
b0109805 12221 }
99c475ab 12222 break;
a7d3970d 12223 }
99c475ab
FB
12224 case 13:
12225 /* conditional branch or swi */
12226 cond = (insn >> 8) & 0xf;
12227 if (cond == 0xe)
12228 goto undef;
12229
12230 if (cond == 0xf) {
12231 /* swi */
eaed129d 12232 gen_set_pc_im(s, s->pc);
d4a2dc67 12233 s->svc_imm = extract32(insn, 0, 8);
dcba3a8d 12234 s->base.is_jmp = DISAS_SWI;
99c475ab
FB
12235 break;
12236 }
12237 /* generate a conditional jump to next instruction */
e50e6a20 12238 s->condlabel = gen_new_label();
39fb730a 12239 arm_gen_test_cc(cond ^ 1, s->condlabel);
e50e6a20 12240 s->condjmp = 1;
99c475ab
FB
12241
12242 /* jump to the offset */
5899f386 12243 val = (uint32_t)s->pc + 2;
99c475ab 12244 offset = ((int32_t)insn << 24) >> 24;
5899f386 12245 val += offset << 1;
8aaca4c0 12246 gen_jmp(s, val);
99c475ab
FB
12247 break;
12248
12249 case 14:
358bf29e 12250 if (insn & (1 << 11)) {
296e5a0a
PM
12251 /* thumb_insn_is_16bit() ensures we can't get here for
12252 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
12253 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
12254 */
12255 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12256 ARCH(5);
12257 offset = ((insn & 0x7ff) << 1);
12258 tmp = load_reg(s, 14);
12259 tcg_gen_addi_i32(tmp, tmp, offset);
12260 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
12261
12262 tmp2 = tcg_temp_new_i32();
12263 tcg_gen_movi_i32(tmp2, s->pc | 1);
12264 store_reg(s, 14, tmp2);
12265 gen_bx(s, tmp);
358bf29e
PB
12266 break;
12267 }
9ee6e8bb 12268 /* unconditional branch */
99c475ab
FB
12269 val = (uint32_t)s->pc;
12270 offset = ((int32_t)insn << 21) >> 21;
12271 val += (offset << 1) + 2;
8aaca4c0 12272 gen_jmp(s, val);
99c475ab
FB
12273 break;
12274
12275 case 15:
296e5a0a
PM
12276 /* thumb_insn_is_16bit() ensures we can't get here for
12277 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
12278 */
12279 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12280
12281 if (insn & (1 << 11)) {
12282 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
12283 offset = ((insn & 0x7ff) << 1) | 1;
12284 tmp = load_reg(s, 14);
12285 tcg_gen_addi_i32(tmp, tmp, offset);
12286
12287 tmp2 = tcg_temp_new_i32();
12288 tcg_gen_movi_i32(tmp2, s->pc | 1);
12289 store_reg(s, 14, tmp2);
12290 gen_bx(s, tmp);
12291 } else {
12292 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
12293 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
12294
12295 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
12296 }
9ee6e8bb 12297 break;
99c475ab
FB
12298 }
12299 return;
9ee6e8bb 12300illegal_op:
99c475ab 12301undef:
73710361
GB
12302 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
12303 default_exception_el(s));
99c475ab
FB
12304}
12305
541ebcd4
PM
12306static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
12307{
12308 /* Return true if the insn at dc->pc might cross a page boundary.
12309 * (False positives are OK, false negatives are not.)
5b8d7289
PM
12310 * We know this is a Thumb insn, and our caller ensures we are
12311 * only called if dc->pc is less than 4 bytes from the page
12312 * boundary, so we cross the page if the first 16 bits indicate
12313 * that this is a 32 bit insn.
541ebcd4 12314 */
5b8d7289 12315 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
541ebcd4 12316
5b8d7289 12317 return !thumb_insn_is_16bit(s, insn);
541ebcd4
PM
12318}
12319
b542683d 12320static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2c0262af 12321{
1d8a5535 12322 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 12323 CPUARMState *env = cs->env_ptr;
4e5e1215 12324 ARMCPU *cpu = arm_env_get_cpu(env);
3b46e624 12325
dcba3a8d 12326 dc->pc = dc->base.pc_first;
e50e6a20 12327 dc->condjmp = 0;
3926cc84 12328
40f860cd 12329 dc->aarch64 = 0;
cef9ee70
SS
12330 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
12331 * there is no secure EL1, so we route exceptions to EL3.
12332 */
12333 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
12334 !arm_el_is_aa64(env, 3);
1d8a5535
LV
12335 dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags);
12336 dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags);
12337 dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
12338 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1;
12339 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4;
12340 dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
c1e37810 12341 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 12342#if !defined(CONFIG_USER_ONLY)
c1e37810 12343 dc->user = (dc->current_el == 0);
3926cc84 12344#endif
1d8a5535
LV
12345 dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
12346 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
12347 dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
12348 dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
12349 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
12350 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
12351 dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
fb602cb7
PM
12352 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
12353 regime_is_secure(env, dc->mmu_idx);
60322b39 12354 dc->cp_regs = cpu->cp_regs;
a984e42c 12355 dc->features = env->features;
40f860cd 12356
50225ad0
PM
12357 /* Single step state. The code-generation logic here is:
12358 * SS_ACTIVE == 0:
12359 * generate code with no special handling for single-stepping (except
12360 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
12361 * this happens anyway because those changes are all system register or
12362 * PSTATE writes).
12363 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
12364 * emit code for one insn
12365 * emit code to clear PSTATE.SS
12366 * emit code to generate software step exception for completed step
12367 * end TB (as usual for having generated an exception)
12368 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
12369 * emit code to generate a software step exception
12370 * end the TB
12371 */
1d8a5535
LV
12372 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
12373 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
50225ad0
PM
12374 dc->is_ldex = false;
12375 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
12376
bfe7ad5b 12377 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
1d8a5535 12378
f7708456
RH
12379 /* If architectural single step active, limit to 1. */
12380 if (is_singlestepping(dc)) {
b542683d 12381 dc->base.max_insns = 1;
f7708456
RH
12382 }
12383
d0264d86
RH
12384 /* ARM is a fixed-length ISA. Bound the number of insns to execute
12385 to those left on the page. */
12386 if (!dc->thumb) {
bfe7ad5b 12387 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 12388 dc->base.max_insns = MIN(dc->base.max_insns, bound);
d0264d86
RH
12389 }
12390
a7812ae4
PB
12391 cpu_F0s = tcg_temp_new_i32();
12392 cpu_F1s = tcg_temp_new_i32();
12393 cpu_F0d = tcg_temp_new_i64();
12394 cpu_F1d = tcg_temp_new_i64();
ad69471c
PB
12395 cpu_V0 = cpu_F0d;
12396 cpu_V1 = cpu_F1d;
e677137d 12397 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 12398 cpu_M0 = tcg_temp_new_i64();
1d8a5535
LV
12399}
12400
b1476854
LV
12401static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
12402{
12403 DisasContext *dc = container_of(dcbase, DisasContext, base);
12404
12405 /* A note on handling of the condexec (IT) bits:
12406 *
12407 * We want to avoid the overhead of having to write the updated condexec
12408 * bits back to the CPUARMState for every instruction in an IT block. So:
12409 * (1) if the condexec bits are not already zero then we write
12410 * zero back into the CPUARMState now. This avoids complications trying
12411 * to do it at the end of the block. (For example if we don't do this
12412 * it's hard to identify whether we can safely skip writing condexec
12413 * at the end of the TB, which we definitely want to do for the case
12414 * where a TB doesn't do anything with the IT state at all.)
12415 * (2) if we are going to leave the TB then we call gen_set_condexec()
12416 * which will write the correct value into CPUARMState if zero is wrong.
12417 * This is done both for leaving the TB at the end, and for leaving
12418 * it because of an exception we know will happen, which is done in
12419 * gen_exception_insn(). The latter is necessary because we need to
12420 * leave the TB with the PC/IT state just prior to execution of the
12421 * instruction which caused the exception.
12422 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
12423 * then the CPUARMState will be wrong and we need to reset it.
12424 * This is handled in the same way as restoration of the
12425 * PC in these situations; we save the value of the condexec bits
12426 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
12427 * then uses this to restore them after an exception.
12428 *
12429 * Note that there are no instructions which can read the condexec
12430 * bits, and none which can write non-static values to them, so
12431 * we don't need to care about whether CPUARMState is correct in the
12432 * middle of a TB.
12433 */
12434
12435 /* Reset the conditional execution bits immediately. This avoids
12436 complications trying to do it at the end of the block. */
12437 if (dc->condexec_mask || dc->condexec_cond) {
12438 TCGv_i32 tmp = tcg_temp_new_i32();
12439 tcg_gen_movi_i32(tmp, 0);
12440 store_cpu_field(tmp, condexec_bits);
12441 }
23169224 12442 tcg_clear_temp_count();
b1476854
LV
12443}
12444
f62bd897
LV
12445static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
12446{
12447 DisasContext *dc = container_of(dcbase, DisasContext, base);
12448
f62bd897
LV
12449 tcg_gen_insn_start(dc->pc,
12450 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
12451 0);
15fa08f8 12452 dc->insn_start = tcg_last_op();
f62bd897
LV
12453}
12454
a68956ad
LV
12455static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
12456 const CPUBreakpoint *bp)
12457{
12458 DisasContext *dc = container_of(dcbase, DisasContext, base);
12459
12460 if (bp->flags & BP_CPU) {
12461 gen_set_condexec(dc);
12462 gen_set_pc_im(dc, dc->pc);
12463 gen_helper_check_breakpoints(cpu_env);
12464 /* End the TB early; it's likely not going to be executed */
12465 dc->base.is_jmp = DISAS_TOO_MANY;
12466 } else {
12467 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
12468 /* The address covered by the breakpoint must be
12469 included in [tb->pc, tb->pc + tb->size) in order
12470 to for it to be properly cleared -- thus we
12471 increment the PC here so that the logic setting
12472 tb->size below does the right thing. */
12473 /* TODO: Advance PC by correct instruction length to
12474 * avoid disassembler error messages */
12475 dc->pc += 2;
12476 dc->base.is_jmp = DISAS_NORETURN;
12477 }
12478
12479 return true;
12480}
12481
722ef0a5 12482static bool arm_pre_translate_insn(DisasContext *dc)
13189a90 12483{
13189a90
LV
12484#ifdef CONFIG_USER_ONLY
12485 /* Intercept jump to the magic kernel page. */
12486 if (dc->pc >= 0xffff0000) {
12487 /* We always get here via a jump, so know we are not in a
12488 conditional execution block. */
12489 gen_exception_internal(EXCP_KERNEL_TRAP);
12490 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 12491 return true;
13189a90
LV
12492 }
12493#endif
12494
12495 if (dc->ss_active && !dc->pstate_ss) {
12496 /* Singlestep state is Active-pending.
12497 * If we're in this state at the start of a TB then either
12498 * a) we just took an exception to an EL which is being debugged
12499 * and this is the first insn in the exception handler
12500 * b) debug exceptions were masked and we just unmasked them
12501 * without changing EL (eg by clearing PSTATE.D)
12502 * In either case we're going to take a swstep exception in the
12503 * "did not step an insn" case, and so the syndrome ISV and EX
12504 * bits should be zero.
12505 */
12506 assert(dc->base.num_insns == 1);
12507 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
12508 default_exception_el(dc));
12509 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 12510 return true;
13189a90
LV
12511 }
12512
722ef0a5
RH
12513 return false;
12514}
13189a90 12515
d0264d86 12516static void arm_post_translate_insn(DisasContext *dc)
722ef0a5 12517{
13189a90
LV
12518 if (dc->condjmp && !dc->base.is_jmp) {
12519 gen_set_label(dc->condlabel);
12520 dc->condjmp = 0;
12521 }
13189a90 12522 dc->base.pc_next = dc->pc;
23169224 12523 translator_loop_temp_check(&dc->base);
13189a90
LV
12524}
12525
722ef0a5
RH
12526static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12527{
12528 DisasContext *dc = container_of(dcbase, DisasContext, base);
12529 CPUARMState *env = cpu->env_ptr;
12530 unsigned int insn;
12531
12532 if (arm_pre_translate_insn(dc)) {
12533 return;
12534 }
12535
12536 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
58803318 12537 dc->insn = insn;
722ef0a5
RH
12538 dc->pc += 4;
12539 disas_arm_insn(dc, insn);
12540
d0264d86
RH
12541 arm_post_translate_insn(dc);
12542
12543 /* ARM is a fixed-length ISA. We performed the cross-page check
12544 in init_disas_context by adjusting max_insns. */
722ef0a5
RH
12545}
12546
dcf14dfb
PM
12547static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
12548{
12549 /* Return true if this Thumb insn is always unconditional,
12550 * even inside an IT block. This is true of only a very few
12551 * instructions: BKPT, HLT, and SG.
12552 *
12553 * A larger class of instructions are UNPREDICTABLE if used
12554 * inside an IT block; we do not need to detect those here, because
12555 * what we do by default (perform the cc check and update the IT
12556 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
12557 * choice for those situations.
12558 *
12559 * insn is either a 16-bit or a 32-bit instruction; the two are
12560 * distinguishable because for the 16-bit case the top 16 bits
12561 * are zeroes, and that isn't a valid 32-bit encoding.
12562 */
12563 if ((insn & 0xffffff00) == 0xbe00) {
12564 /* BKPT */
12565 return true;
12566 }
12567
12568 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
12569 !arm_dc_feature(s, ARM_FEATURE_M)) {
12570 /* HLT: v8A only. This is unconditional even when it is going to
12571 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
12572 * For v7 cores this was a plain old undefined encoding and so
12573 * honours its cc check. (We might be using the encoding as
12574 * a semihosting trap, but we don't change the cc check behaviour
12575 * on that account, because a debugger connected to a real v7A
12576 * core and emulating semihosting traps by catching the UNDEF
12577 * exception would also only see cases where the cc check passed.
12578 * No guest code should be trying to do a HLT semihosting trap
12579 * in an IT block anyway.
12580 */
12581 return true;
12582 }
12583
12584 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
12585 arm_dc_feature(s, ARM_FEATURE_M)) {
12586 /* SG: v8M only */
12587 return true;
12588 }
12589
12590 return false;
12591}
12592
722ef0a5
RH
12593static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12594{
12595 DisasContext *dc = container_of(dcbase, DisasContext, base);
12596 CPUARMState *env = cpu->env_ptr;
296e5a0a
PM
12597 uint32_t insn;
12598 bool is_16bit;
722ef0a5
RH
12599
12600 if (arm_pre_translate_insn(dc)) {
12601 return;
12602 }
12603
296e5a0a
PM
12604 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12605 is_16bit = thumb_insn_is_16bit(dc, insn);
12606 dc->pc += 2;
12607 if (!is_16bit) {
12608 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12609
12610 insn = insn << 16 | insn2;
12611 dc->pc += 2;
12612 }
58803318 12613 dc->insn = insn;
296e5a0a 12614
dcf14dfb 12615 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
296e5a0a
PM
12616 uint32_t cond = dc->condexec_cond;
12617
12618 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
12619 dc->condlabel = gen_new_label();
12620 arm_gen_test_cc(cond ^ 1, dc->condlabel);
12621 dc->condjmp = 1;
12622 }
12623 }
12624
12625 if (is_16bit) {
12626 disas_thumb_insn(dc, insn);
12627 } else {
2eea841c 12628 disas_thumb2_insn(dc, insn);
296e5a0a 12629 }
722ef0a5
RH
12630
12631 /* Advance the Thumb condexec condition. */
12632 if (dc->condexec_mask) {
12633 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
12634 ((dc->condexec_mask >> 4) & 1));
12635 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
12636 if (dc->condexec_mask == 0) {
12637 dc->condexec_cond = 0;
12638 }
12639 }
12640
d0264d86
RH
12641 arm_post_translate_insn(dc);
12642
12643 /* Thumb is a variable-length ISA. Stop translation when the next insn
12644 * will touch a new page. This ensures that prefetch aborts occur at
12645 * the right place.
12646 *
12647 * We want to stop the TB if the next insn starts in a new page,
12648 * or if it spans between this page and the next. This means that
12649 * if we're looking at the last halfword in the page we need to
12650 * see if it's a 16-bit Thumb insn (which will fit in this TB)
12651 * or a 32-bit Thumb insn (which won't).
12652 * This is to avoid generating a silly TB with a single 16-bit insn
12653 * in it at the end of this page (which would execute correctly
12654 * but isn't very efficient).
12655 */
12656 if (dc->base.is_jmp == DISAS_NEXT
bfe7ad5b
EC
12657 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
12658 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
d0264d86
RH
12659 && insn_crosses_page(env, dc)))) {
12660 dc->base.is_jmp = DISAS_TOO_MANY;
12661 }
722ef0a5
RH
12662}
12663
70d3c035 12664static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1d8a5535 12665{
70d3c035 12666 DisasContext *dc = container_of(dcbase, DisasContext, base);
2e70f6ef 12667
c5a49c63 12668 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
70d3c035
LV
12669 /* FIXME: This can theoretically happen with self-modifying code. */
12670 cpu_abort(cpu, "IO on conditional branch instruction");
2e70f6ef 12671 }
9ee6e8bb 12672
b5ff1b31 12673 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
12674 instruction was a conditional branch or trap, and the PC has
12675 already been written. */
f021b2c4 12676 gen_set_condexec(dc);
dcba3a8d 12677 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
3bb8a96f
PM
12678 /* Exception return branches need some special case code at the
12679 * end of the TB, which is complex enough that it has to
12680 * handle the single-step vs not and the condition-failed
12681 * insn codepath itself.
12682 */
12683 gen_bx_excret_final_code(dc);
12684 } else if (unlikely(is_singlestepping(dc))) {
7999a5c8 12685 /* Unconditional and "condition passed" instruction codepath. */
dcba3a8d 12686 switch (dc->base.is_jmp) {
7999a5c8 12687 case DISAS_SWI:
50225ad0 12688 gen_ss_advance(dc);
73710361
GB
12689 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12690 default_exception_el(dc));
7999a5c8
SF
12691 break;
12692 case DISAS_HVC:
37e6456e 12693 gen_ss_advance(dc);
73710361 12694 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
12695 break;
12696 case DISAS_SMC:
37e6456e 12697 gen_ss_advance(dc);
73710361 12698 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
12699 break;
12700 case DISAS_NEXT:
a68956ad 12701 case DISAS_TOO_MANY:
7999a5c8
SF
12702 case DISAS_UPDATE:
12703 gen_set_pc_im(dc, dc->pc);
12704 /* fall through */
12705 default:
5425415e
PM
12706 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
12707 gen_singlestep_exception(dc);
a0c231e6
RH
12708 break;
12709 case DISAS_NORETURN:
12710 break;
7999a5c8 12711 }
8aaca4c0 12712 } else {
9ee6e8bb
PB
12713 /* While branches must always occur at the end of an IT block,
12714 there are a few other things that can cause us to terminate
65626741 12715 the TB in the middle of an IT block:
9ee6e8bb
PB
12716 - Exception generating instructions (bkpt, swi, undefined).
12717 - Page boundaries.
12718 - Hardware watchpoints.
12719 Hardware breakpoints have already been handled and skip this code.
12720 */
dcba3a8d 12721 switch(dc->base.is_jmp) {
8aaca4c0 12722 case DISAS_NEXT:
a68956ad 12723 case DISAS_TOO_MANY:
6e256c93 12724 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0 12725 break;
577bf808 12726 case DISAS_JUMP:
8a6b28c7
EC
12727 gen_goto_ptr();
12728 break;
e8d52302
AB
12729 case DISAS_UPDATE:
12730 gen_set_pc_im(dc, dc->pc);
12731 /* fall through */
577bf808 12732 default:
8aaca4c0 12733 /* indicate that the hash table must be used to find the next TB */
07ea28b4 12734 tcg_gen_exit_tb(NULL, 0);
8aaca4c0 12735 break;
a0c231e6 12736 case DISAS_NORETURN:
8aaca4c0
FB
12737 /* nothing more to generate */
12738 break;
9ee6e8bb 12739 case DISAS_WFI:
58803318
SS
12740 {
12741 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
12742 !(dc->insn & (1U << 31))) ? 2 : 4);
12743
12744 gen_helper_wfi(cpu_env, tmp);
12745 tcg_temp_free_i32(tmp);
84549b6d
PM
12746 /* The helper doesn't necessarily throw an exception, but we
12747 * must go back to the main loop to check for interrupts anyway.
12748 */
07ea28b4 12749 tcg_gen_exit_tb(NULL, 0);
9ee6e8bb 12750 break;
58803318 12751 }
72c1d3af
PM
12752 case DISAS_WFE:
12753 gen_helper_wfe(cpu_env);
12754 break;
c87e5a61
PM
12755 case DISAS_YIELD:
12756 gen_helper_yield(cpu_env);
12757 break;
9ee6e8bb 12758 case DISAS_SWI:
73710361
GB
12759 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12760 default_exception_el(dc));
9ee6e8bb 12761 break;
37e6456e 12762 case DISAS_HVC:
73710361 12763 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
12764 break;
12765 case DISAS_SMC:
73710361 12766 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 12767 break;
8aaca4c0 12768 }
f021b2c4
PM
12769 }
12770
12771 if (dc->condjmp) {
12772 /* "Condition failed" instruction codepath for the branch/trap insn */
12773 gen_set_label(dc->condlabel);
12774 gen_set_condexec(dc);
b636649f 12775 if (unlikely(is_singlestepping(dc))) {
f021b2c4
PM
12776 gen_set_pc_im(dc, dc->pc);
12777 gen_singlestep_exception(dc);
12778 } else {
6e256c93 12779 gen_goto_tb(dc, 1, dc->pc);
e50e6a20 12780 }
2c0262af 12781 }
23169224
LV
12782
12783 /* Functions above can change dc->pc, so re-align db->pc_next */
12784 dc->base.pc_next = dc->pc;
70d3c035
LV
12785}
12786
4013f7fc
LV
12787static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
12788{
12789 DisasContext *dc = container_of(dcbase, DisasContext, base);
12790
12791 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 12792 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
4013f7fc
LV
12793}
12794
23169224
LV
12795static const TranslatorOps arm_translator_ops = {
12796 .init_disas_context = arm_tr_init_disas_context,
12797 .tb_start = arm_tr_tb_start,
12798 .insn_start = arm_tr_insn_start,
12799 .breakpoint_check = arm_tr_breakpoint_check,
12800 .translate_insn = arm_tr_translate_insn,
12801 .tb_stop = arm_tr_tb_stop,
12802 .disas_log = arm_tr_disas_log,
12803};
12804
722ef0a5
RH
12805static const TranslatorOps thumb_translator_ops = {
12806 .init_disas_context = arm_tr_init_disas_context,
12807 .tb_start = arm_tr_tb_start,
12808 .insn_start = arm_tr_insn_start,
12809 .breakpoint_check = arm_tr_breakpoint_check,
12810 .translate_insn = thumb_tr_translate_insn,
12811 .tb_stop = arm_tr_tb_stop,
12812 .disas_log = arm_tr_disas_log,
12813};
12814
70d3c035 12815/* generate intermediate code for basic block 'tb'. */
23169224 12816void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
70d3c035 12817{
23169224
LV
12818 DisasContext dc;
12819 const TranslatorOps *ops = &arm_translator_ops;
70d3c035 12820
722ef0a5
RH
12821 if (ARM_TBFLAG_THUMB(tb->flags)) {
12822 ops = &thumb_translator_ops;
12823 }
23169224 12824#ifdef TARGET_AARCH64
70d3c035 12825 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
23169224 12826 ops = &aarch64_translator_ops;
2c0262af
FB
12827 }
12828#endif
23169224
LV
12829
12830 translator_loop(ops, &dc.base, cpu, tb);
2c0262af
FB
12831}
12832
b5ff1b31 12833static const char *cpu_mode_names[16] = {
28c9457d
EI
12834 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
12835 "???", "???", "hyp", "und", "???", "???", "???", "sys"
b5ff1b31 12836};
9ee6e8bb 12837
878096ee
AF
12838void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
12839 int flags)
2c0262af 12840{
878096ee
AF
12841 ARMCPU *cpu = ARM_CPU(cs);
12842 CPUARMState *env = &cpu->env;
2c0262af
FB
12843 int i;
12844
17731115
PM
12845 if (is_a64(env)) {
12846 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
12847 return;
12848 }
12849
2c0262af 12850 for(i=0;i<16;i++) {
7fe48483 12851 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 12852 if ((i % 4) == 3)
7fe48483 12853 cpu_fprintf(f, "\n");
2c0262af 12854 else
7fe48483 12855 cpu_fprintf(f, " ");
2c0262af 12856 }
06e5cf7a 12857
5b906f35
PM
12858 if (arm_feature(env, ARM_FEATURE_M)) {
12859 uint32_t xpsr = xpsr_read(env);
12860 const char *mode;
1e577cc7
PM
12861 const char *ns_status = "";
12862
12863 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
12864 ns_status = env->v7m.secure ? "S " : "NS ";
12865 }
5b906f35
PM
12866
12867 if (xpsr & XPSR_EXCP) {
12868 mode = "handler";
12869 } else {
8bfc26ea 12870 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
5b906f35
PM
12871 mode = "unpriv-thread";
12872 } else {
12873 mode = "priv-thread";
12874 }
12875 }
12876
1e577cc7 12877 cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
5b906f35
PM
12878 xpsr,
12879 xpsr & XPSR_N ? 'N' : '-',
12880 xpsr & XPSR_Z ? 'Z' : '-',
12881 xpsr & XPSR_C ? 'C' : '-',
12882 xpsr & XPSR_V ? 'V' : '-',
12883 xpsr & XPSR_T ? 'T' : 'A',
1e577cc7 12884 ns_status,
5b906f35 12885 mode);
06e5cf7a 12886 } else {
5b906f35
PM
12887 uint32_t psr = cpsr_read(env);
12888 const char *ns_status = "";
12889
12890 if (arm_feature(env, ARM_FEATURE_EL3) &&
12891 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
12892 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
12893 }
12894
12895 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
12896 psr,
12897 psr & CPSR_N ? 'N' : '-',
12898 psr & CPSR_Z ? 'Z' : '-',
12899 psr & CPSR_C ? 'C' : '-',
12900 psr & CPSR_V ? 'V' : '-',
12901 psr & CPSR_T ? 'T' : 'A',
12902 ns_status,
12903 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
12904 }
b7bcbe95 12905
f2617cfc
PM
12906 if (flags & CPU_DUMP_FPU) {
12907 int numvfpregs = 0;
12908 if (arm_feature(env, ARM_FEATURE_VFP)) {
12909 numvfpregs += 16;
12910 }
12911 if (arm_feature(env, ARM_FEATURE_VFP3)) {
12912 numvfpregs += 16;
12913 }
12914 for (i = 0; i < numvfpregs; i++) {
9a2b5256 12915 uint64_t v = *aa32_vfp_dreg(env, i);
f2617cfc
PM
12916 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
12917 i * 2, (uint32_t)v,
12918 i * 2 + 1, (uint32_t)(v >> 32),
12919 i, v);
12920 }
12921 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
b7bcbe95 12922 }
2c0262af 12923}
a6b025d3 12924
bad729e2
RH
12925void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
12926 target_ulong *data)
d2856f1a 12927{
3926cc84 12928 if (is_a64(env)) {
bad729e2 12929 env->pc = data[0];
40f860cd 12930 env->condexec_bits = 0;
aaa1f954 12931 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12932 } else {
bad729e2
RH
12933 env->regs[15] = data[0];
12934 env->condexec_bits = data[1];
aaa1f954 12935 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12936 }
d2856f1a 12937}