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