Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 36802b6b

History | View | Annotate | Download (336.1 kB)

1 2c0262af bellard
/*
2 2c0262af bellard
 *  ARM translation
3 5fafdf24 ths
 *
4 2c0262af bellard
 *  Copyright (c) 2003 Fabrice Bellard
5 9ee6e8bb pbrook
 *  Copyright (c) 2005-2007 CodeSourcery
6 18c9b560 balrog
 *  Copyright (c) 2007 OpenedHand, Ltd.
7 2c0262af bellard
 *
8 2c0262af bellard
 * This library is free software; you can redistribute it and/or
9 2c0262af bellard
 * modify it under the terms of the GNU Lesser General Public
10 2c0262af bellard
 * License as published by the Free Software Foundation; either
11 2c0262af bellard
 * version 2 of the License, or (at your option) any later version.
12 2c0262af bellard
 *
13 2c0262af bellard
 * This library is distributed in the hope that it will be useful,
14 2c0262af bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 2c0262af bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 2c0262af bellard
 * Lesser General Public License for more details.
17 2c0262af bellard
 *
18 2c0262af bellard
 * You should have received a copy of the GNU Lesser General Public
19 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 2c0262af bellard
 */
21 2c0262af bellard
#include <stdarg.h>
22 2c0262af bellard
#include <stdlib.h>
23 2c0262af bellard
#include <stdio.h>
24 2c0262af bellard
#include <string.h>
25 2c0262af bellard
#include <inttypes.h>
26 2c0262af bellard
27 2c0262af bellard
#include "cpu.h"
28 2c0262af bellard
#include "exec-all.h"
29 2c0262af bellard
#include "disas.h"
30 57fec1fe bellard
#include "tcg-op.h"
31 79383c9c blueswir1
#include "qemu-log.h"
32 1497c961 pbrook
33 7b59220e Lluís
#include "helper.h"
34 1497c961 pbrook
#define GEN_HELPER 1
35 7b59220e Lluís
#include "helper.h"
36 2c0262af bellard
37 be5e7a76 Dmitry Eremin-Solenikov
#define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
38 be5e7a76 Dmitry Eremin-Solenikov
#define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
39 be5e7a76 Dmitry Eremin-Solenikov
/* currently all emulated v5 cores are also v5TE, so don't bother */
40 be5e7a76 Dmitry Eremin-Solenikov
#define ENABLE_ARCH_5TE   arm_feature(env, ARM_FEATURE_V5)
41 9ee6e8bb pbrook
#define ENABLE_ARCH_5J    0
42 9ee6e8bb pbrook
#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
43 9ee6e8bb pbrook
#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
44 9ee6e8bb pbrook
#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
45 9ee6e8bb pbrook
#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
46 b5ff1b31 bellard
47 86753403 pbrook
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
48 b5ff1b31 bellard
49 2c0262af bellard
/* internal defines */
50 2c0262af bellard
typedef struct DisasContext {
51 0fa85d43 bellard
    target_ulong pc;
52 2c0262af bellard
    int is_jmp;
53 e50e6a20 bellard
    /* Nonzero if this instruction has been conditionally skipped.  */
54 e50e6a20 bellard
    int condjmp;
55 e50e6a20 bellard
    /* The label that will be jumped to when the instruction is skipped.  */
56 e50e6a20 bellard
    int condlabel;
57 9ee6e8bb pbrook
    /* Thumb-2 condtional execution bits.  */
58 9ee6e8bb pbrook
    int condexec_mask;
59 9ee6e8bb pbrook
    int condexec_cond;
60 2c0262af bellard
    struct TranslationBlock *tb;
61 8aaca4c0 bellard
    int singlestep_enabled;
62 5899f386 bellard
    int thumb;
63 b5ff1b31 bellard
#if !defined(CONFIG_USER_ONLY)
64 b5ff1b31 bellard
    int user;
65 b5ff1b31 bellard
#endif
66 5df8bac1 Peter Maydell
    int vfp_enabled;
67 69d1fc22 Peter Maydell
    int vec_len;
68 69d1fc22 Peter Maydell
    int vec_stride;
69 2c0262af bellard
} DisasContext;
70 2c0262af bellard
71 e12ce78d Peter Maydell
static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
72 e12ce78d Peter Maydell
73 b5ff1b31 bellard
#if defined(CONFIG_USER_ONLY)
74 b5ff1b31 bellard
#define IS_USER(s) 1
75 b5ff1b31 bellard
#else
76 b5ff1b31 bellard
#define IS_USER(s) (s->user)
77 b5ff1b31 bellard
#endif
78 b5ff1b31 bellard
79 9ee6e8bb pbrook
/* These instructions trap after executing, so defer them until after the
80 9ee6e8bb pbrook
   conditional executions state has been updated.  */
81 9ee6e8bb pbrook
#define DISAS_WFI 4
82 9ee6e8bb pbrook
#define DISAS_SWI 5
83 2c0262af bellard
84 a7812ae4 pbrook
static TCGv_ptr cpu_env;
85 ad69471c pbrook
/* We reuse the same 64-bit temporaries for efficiency.  */
86 a7812ae4 pbrook
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
87 155c3eac Filip Navara
static TCGv_i32 cpu_R[16];
88 426f5abc Paul Brook
static TCGv_i32 cpu_exclusive_addr;
89 426f5abc Paul Brook
static TCGv_i32 cpu_exclusive_val;
90 426f5abc Paul Brook
static TCGv_i32 cpu_exclusive_high;
91 426f5abc Paul Brook
#ifdef CONFIG_USER_ONLY
92 426f5abc Paul Brook
static TCGv_i32 cpu_exclusive_test;
93 426f5abc Paul Brook
static TCGv_i32 cpu_exclusive_info;
94 426f5abc Paul Brook
#endif
95 ad69471c pbrook
96 b26eefb6 pbrook
/* FIXME:  These should be removed.  */
97 a7812ae4 pbrook
static TCGv cpu_F0s, cpu_F1s;
98 a7812ae4 pbrook
static TCGv_i64 cpu_F0d, cpu_F1d;
99 b26eefb6 pbrook
100 2e70f6ef pbrook
#include "gen-icount.h"
101 2e70f6ef pbrook
102 155c3eac Filip Navara
static const char *regnames[] =
103 155c3eac Filip Navara
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
104 155c3eac Filip Navara
      "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
105 155c3eac Filip Navara
106 b26eefb6 pbrook
/* initialize TCG globals.  */
107 b26eefb6 pbrook
void arm_translate_init(void)
108 b26eefb6 pbrook
{
109 155c3eac Filip Navara
    int i;
110 155c3eac Filip Navara
111 a7812ae4 pbrook
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
112 a7812ae4 pbrook
113 155c3eac Filip Navara
    for (i = 0; i < 16; i++) {
114 155c3eac Filip Navara
        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
115 155c3eac Filip Navara
                                          offsetof(CPUState, regs[i]),
116 155c3eac Filip Navara
                                          regnames[i]);
117 155c3eac Filip Navara
    }
118 426f5abc Paul Brook
    cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
119 426f5abc Paul Brook
        offsetof(CPUState, exclusive_addr), "exclusive_addr");
120 426f5abc Paul Brook
    cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
121 426f5abc Paul Brook
        offsetof(CPUState, exclusive_val), "exclusive_val");
122 426f5abc Paul Brook
    cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
123 426f5abc Paul Brook
        offsetof(CPUState, exclusive_high), "exclusive_high");
124 426f5abc Paul Brook
#ifdef CONFIG_USER_ONLY
125 426f5abc Paul Brook
    cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
126 426f5abc Paul Brook
        offsetof(CPUState, exclusive_test), "exclusive_test");
127 426f5abc Paul Brook
    cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
128 426f5abc Paul Brook
        offsetof(CPUState, exclusive_info), "exclusive_info");
129 426f5abc Paul Brook
#endif
130 155c3eac Filip Navara
131 a7812ae4 pbrook
#define GEN_HELPER 2
132 7b59220e Lluís
#include "helper.h"
133 b26eefb6 pbrook
}
134 b26eefb6 pbrook
135 d9ba4830 pbrook
static inline TCGv load_cpu_offset(int offset)
136 d9ba4830 pbrook
{
137 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
138 d9ba4830 pbrook
    tcg_gen_ld_i32(tmp, cpu_env, offset);
139 d9ba4830 pbrook
    return tmp;
140 d9ba4830 pbrook
}
141 d9ba4830 pbrook
142 d9ba4830 pbrook
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
143 d9ba4830 pbrook
144 d9ba4830 pbrook
static inline void store_cpu_offset(TCGv var, int offset)
145 d9ba4830 pbrook
{
146 d9ba4830 pbrook
    tcg_gen_st_i32(var, cpu_env, offset);
147 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
148 d9ba4830 pbrook
}
149 d9ba4830 pbrook
150 d9ba4830 pbrook
#define store_cpu_field(var, name) \
151 d9ba4830 pbrook
    store_cpu_offset(var, offsetof(CPUState, name))
152 d9ba4830 pbrook
153 b26eefb6 pbrook
/* Set a variable to the value of a CPU register.  */
154 b26eefb6 pbrook
static void load_reg_var(DisasContext *s, TCGv var, int reg)
155 b26eefb6 pbrook
{
156 b26eefb6 pbrook
    if (reg == 15) {
157 b26eefb6 pbrook
        uint32_t addr;
158 b26eefb6 pbrook
        /* normaly, since we updated PC, we need only to add one insn */
159 b26eefb6 pbrook
        if (s->thumb)
160 b26eefb6 pbrook
            addr = (long)s->pc + 2;
161 b26eefb6 pbrook
        else
162 b26eefb6 pbrook
            addr = (long)s->pc + 4;
163 b26eefb6 pbrook
        tcg_gen_movi_i32(var, addr);
164 b26eefb6 pbrook
    } else {
165 155c3eac Filip Navara
        tcg_gen_mov_i32(var, cpu_R[reg]);
166 b26eefb6 pbrook
    }
167 b26eefb6 pbrook
}
168 b26eefb6 pbrook
169 b26eefb6 pbrook
/* Create a new temporary and set it to the value of a CPU register.  */
170 b26eefb6 pbrook
static inline TCGv load_reg(DisasContext *s, int reg)
171 b26eefb6 pbrook
{
172 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
173 b26eefb6 pbrook
    load_reg_var(s, tmp, reg);
174 b26eefb6 pbrook
    return tmp;
175 b26eefb6 pbrook
}
176 b26eefb6 pbrook
177 b26eefb6 pbrook
/* Set a CPU register.  The source must be a temporary and will be
178 b26eefb6 pbrook
   marked as dead.  */
179 b26eefb6 pbrook
static void store_reg(DisasContext *s, int reg, TCGv var)
180 b26eefb6 pbrook
{
181 b26eefb6 pbrook
    if (reg == 15) {
182 b26eefb6 pbrook
        tcg_gen_andi_i32(var, var, ~1);
183 b26eefb6 pbrook
        s->is_jmp = DISAS_JUMP;
184 b26eefb6 pbrook
    }
185 155c3eac Filip Navara
    tcg_gen_mov_i32(cpu_R[reg], var);
186 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
187 b26eefb6 pbrook
}
188 b26eefb6 pbrook
189 b26eefb6 pbrook
/* Value extensions.  */
190 86831435 pbrook
#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
191 86831435 pbrook
#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
192 b26eefb6 pbrook
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
193 b26eefb6 pbrook
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
194 b26eefb6 pbrook
195 1497c961 pbrook
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
196 1497c961 pbrook
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
197 8f01245e pbrook
198 b26eefb6 pbrook
199 b75263d6 Juha Riihimäki
static inline void gen_set_cpsr(TCGv var, uint32_t mask)
200 b75263d6 Juha Riihimäki
{
201 b75263d6 Juha Riihimäki
    TCGv tmp_mask = tcg_const_i32(mask);
202 b75263d6 Juha Riihimäki
    gen_helper_cpsr_write(var, tmp_mask);
203 b75263d6 Juha Riihimäki
    tcg_temp_free_i32(tmp_mask);
204 b75263d6 Juha Riihimäki
}
205 d9ba4830 pbrook
/* Set NZCV flags from the high 4 bits of var.  */
206 d9ba4830 pbrook
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
207 d9ba4830 pbrook
208 d9ba4830 pbrook
static void gen_exception(int excp)
209 d9ba4830 pbrook
{
210 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
211 d9ba4830 pbrook
    tcg_gen_movi_i32(tmp, excp);
212 d9ba4830 pbrook
    gen_helper_exception(tmp);
213 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
214 d9ba4830 pbrook
}
215 d9ba4830 pbrook
216 3670669c pbrook
static void gen_smul_dual(TCGv a, TCGv b)
217 3670669c pbrook
{
218 7d1b0095 Peter Maydell
    TCGv tmp1 = tcg_temp_new_i32();
219 7d1b0095 Peter Maydell
    TCGv tmp2 = tcg_temp_new_i32();
220 22478e79 balrog
    tcg_gen_ext16s_i32(tmp1, a);
221 22478e79 balrog
    tcg_gen_ext16s_i32(tmp2, b);
222 3670669c pbrook
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
223 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp2);
224 3670669c pbrook
    tcg_gen_sari_i32(a, a, 16);
225 3670669c pbrook
    tcg_gen_sari_i32(b, b, 16);
226 3670669c pbrook
    tcg_gen_mul_i32(b, b, a);
227 3670669c pbrook
    tcg_gen_mov_i32(a, tmp1);
228 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp1);
229 3670669c pbrook
}
230 3670669c pbrook
231 3670669c pbrook
/* Byteswap each halfword.  */
232 3670669c pbrook
static void gen_rev16(TCGv var)
233 3670669c pbrook
{
234 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
235 3670669c pbrook
    tcg_gen_shri_i32(tmp, var, 8);
236 3670669c pbrook
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
237 3670669c pbrook
    tcg_gen_shli_i32(var, var, 8);
238 3670669c pbrook
    tcg_gen_andi_i32(var, var, 0xff00ff00);
239 3670669c pbrook
    tcg_gen_or_i32(var, var, tmp);
240 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
241 3670669c pbrook
}
242 3670669c pbrook
243 3670669c pbrook
/* Byteswap low halfword and sign extend.  */
244 3670669c pbrook
static void gen_revsh(TCGv var)
245 3670669c pbrook
{
246 1a855029 Aurelien Jarno
    tcg_gen_ext16u_i32(var, var);
247 1a855029 Aurelien Jarno
    tcg_gen_bswap16_i32(var, var);
248 1a855029 Aurelien Jarno
    tcg_gen_ext16s_i32(var, var);
249 3670669c pbrook
}
250 3670669c pbrook
251 3670669c pbrook
/* Unsigned bitfield extract.  */
252 3670669c pbrook
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
253 3670669c pbrook
{
254 3670669c pbrook
    if (shift)
255 3670669c pbrook
        tcg_gen_shri_i32(var, var, shift);
256 3670669c pbrook
    tcg_gen_andi_i32(var, var, mask);
257 3670669c pbrook
}
258 3670669c pbrook
259 3670669c pbrook
/* Signed bitfield extract.  */
260 3670669c pbrook
static void gen_sbfx(TCGv var, int shift, int width)
261 3670669c pbrook
{
262 3670669c pbrook
    uint32_t signbit;
263 3670669c pbrook
264 3670669c pbrook
    if (shift)
265 3670669c pbrook
        tcg_gen_sari_i32(var, var, shift);
266 3670669c pbrook
    if (shift + width < 32) {
267 3670669c pbrook
        signbit = 1u << (width - 1);
268 3670669c pbrook
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
269 3670669c pbrook
        tcg_gen_xori_i32(var, var, signbit);
270 3670669c pbrook
        tcg_gen_subi_i32(var, var, signbit);
271 3670669c pbrook
    }
272 3670669c pbrook
}
273 3670669c pbrook
274 3670669c pbrook
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
275 3670669c pbrook
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
276 3670669c pbrook
{
277 3670669c pbrook
    tcg_gen_andi_i32(val, val, mask);
278 8f8e3aa4 pbrook
    tcg_gen_shli_i32(val, val, shift);
279 8f8e3aa4 pbrook
    tcg_gen_andi_i32(base, base, ~(mask << shift));
280 3670669c pbrook
    tcg_gen_or_i32(dest, base, val);
281 3670669c pbrook
}
282 3670669c pbrook
283 838fa72d Aurelien Jarno
/* Return (b << 32) + a. Mark inputs as dead */
284 838fa72d Aurelien Jarno
static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
285 3670669c pbrook
{
286 838fa72d Aurelien Jarno
    TCGv_i64 tmp64 = tcg_temp_new_i64();
287 838fa72d Aurelien Jarno
288 838fa72d Aurelien Jarno
    tcg_gen_extu_i32_i64(tmp64, b);
289 7d1b0095 Peter Maydell
    tcg_temp_free_i32(b);
290 838fa72d Aurelien Jarno
    tcg_gen_shli_i64(tmp64, tmp64, 32);
291 838fa72d Aurelien Jarno
    tcg_gen_add_i64(a, tmp64, a);
292 838fa72d Aurelien Jarno
293 838fa72d Aurelien Jarno
    tcg_temp_free_i64(tmp64);
294 838fa72d Aurelien Jarno
    return a;
295 838fa72d Aurelien Jarno
}
296 838fa72d Aurelien Jarno
297 838fa72d Aurelien Jarno
/* Return (b << 32) - a. Mark inputs as dead. */
298 838fa72d Aurelien Jarno
static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
299 838fa72d Aurelien Jarno
{
300 838fa72d Aurelien Jarno
    TCGv_i64 tmp64 = tcg_temp_new_i64();
301 838fa72d Aurelien Jarno
302 838fa72d Aurelien Jarno
    tcg_gen_extu_i32_i64(tmp64, b);
303 7d1b0095 Peter Maydell
    tcg_temp_free_i32(b);
304 838fa72d Aurelien Jarno
    tcg_gen_shli_i64(tmp64, tmp64, 32);
305 838fa72d Aurelien Jarno
    tcg_gen_sub_i64(a, tmp64, a);
306 838fa72d Aurelien Jarno
307 838fa72d Aurelien Jarno
    tcg_temp_free_i64(tmp64);
308 838fa72d Aurelien Jarno
    return a;
309 3670669c pbrook
}
310 3670669c pbrook
311 8f01245e pbrook
/* FIXME: Most targets have native widening multiplication.
312 8f01245e pbrook
   It would be good to use that instead of a full wide multiply.  */
313 5e3f878a pbrook
/* 32x32->64 multiply.  Marks inputs as dead.  */
314 a7812ae4 pbrook
static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
315 5e3f878a pbrook
{
316 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
317 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
318 5e3f878a pbrook
319 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp1, a);
320 7d1b0095 Peter Maydell
    tcg_temp_free_i32(a);
321 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp2, b);
322 7d1b0095 Peter Maydell
    tcg_temp_free_i32(b);
323 5e3f878a pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
324 b75263d6 Juha Riihimäki
    tcg_temp_free_i64(tmp2);
325 5e3f878a pbrook
    return tmp1;
326 5e3f878a pbrook
}
327 5e3f878a pbrook
328 a7812ae4 pbrook
static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
329 5e3f878a pbrook
{
330 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
331 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
332 5e3f878a pbrook
333 5e3f878a pbrook
    tcg_gen_ext_i32_i64(tmp1, a);
334 7d1b0095 Peter Maydell
    tcg_temp_free_i32(a);
335 5e3f878a pbrook
    tcg_gen_ext_i32_i64(tmp2, b);
336 7d1b0095 Peter Maydell
    tcg_temp_free_i32(b);
337 5e3f878a pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
338 b75263d6 Juha Riihimäki
    tcg_temp_free_i64(tmp2);
339 5e3f878a pbrook
    return tmp1;
340 5e3f878a pbrook
}
341 5e3f878a pbrook
342 8f01245e pbrook
/* Swap low and high halfwords.  */
343 8f01245e pbrook
static void gen_swap_half(TCGv var)
344 8f01245e pbrook
{
345 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
346 8f01245e pbrook
    tcg_gen_shri_i32(tmp, var, 16);
347 8f01245e pbrook
    tcg_gen_shli_i32(var, var, 16);
348 8f01245e pbrook
    tcg_gen_or_i32(var, var, tmp);
349 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
350 8f01245e pbrook
}
351 8f01245e pbrook
352 b26eefb6 pbrook
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
353 b26eefb6 pbrook
    tmp = (t0 ^ t1) & 0x8000;
354 b26eefb6 pbrook
    t0 &= ~0x8000;
355 b26eefb6 pbrook
    t1 &= ~0x8000;
356 b26eefb6 pbrook
    t0 = (t0 + t1) ^ tmp;
357 b26eefb6 pbrook
 */
358 b26eefb6 pbrook
359 b26eefb6 pbrook
static void gen_add16(TCGv t0, TCGv t1)
360 b26eefb6 pbrook
{
361 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
362 b26eefb6 pbrook
    tcg_gen_xor_i32(tmp, t0, t1);
363 b26eefb6 pbrook
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
364 b26eefb6 pbrook
    tcg_gen_andi_i32(t0, t0, ~0x8000);
365 b26eefb6 pbrook
    tcg_gen_andi_i32(t1, t1, ~0x8000);
366 b26eefb6 pbrook
    tcg_gen_add_i32(t0, t0, t1);
367 b26eefb6 pbrook
    tcg_gen_xor_i32(t0, t0, tmp);
368 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
369 7d1b0095 Peter Maydell
    tcg_temp_free_i32(t1);
370 b26eefb6 pbrook
}
371 b26eefb6 pbrook
372 9a119ff6 pbrook
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
373 9a119ff6 pbrook
374 b26eefb6 pbrook
/* Set CF to the top bit of var.  */
375 b26eefb6 pbrook
static void gen_set_CF_bit31(TCGv var)
376 b26eefb6 pbrook
{
377 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
378 b26eefb6 pbrook
    tcg_gen_shri_i32(tmp, var, 31);
379 4cc633c3 balrog
    gen_set_CF(tmp);
380 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
381 b26eefb6 pbrook
}
382 b26eefb6 pbrook
383 b26eefb6 pbrook
/* Set N and Z flags from var.  */
384 b26eefb6 pbrook
static inline void gen_logic_CC(TCGv var)
385 b26eefb6 pbrook
{
386 6fbe23d5 pbrook
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
387 6fbe23d5 pbrook
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
388 b26eefb6 pbrook
}
389 b26eefb6 pbrook
390 b26eefb6 pbrook
/* T0 += T1 + CF.  */
391 396e467c Filip Navara
static void gen_adc(TCGv t0, TCGv t1)
392 b26eefb6 pbrook
{
393 d9ba4830 pbrook
    TCGv tmp;
394 396e467c Filip Navara
    tcg_gen_add_i32(t0, t0, t1);
395 d9ba4830 pbrook
    tmp = load_cpu_field(CF);
396 396e467c Filip Navara
    tcg_gen_add_i32(t0, t0, tmp);
397 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
398 b26eefb6 pbrook
}
399 b26eefb6 pbrook
400 e9bb4aa9 Juha Riihimäki
/* dest = T0 + T1 + CF. */
401 e9bb4aa9 Juha Riihimäki
static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
402 e9bb4aa9 Juha Riihimäki
{
403 e9bb4aa9 Juha Riihimäki
    TCGv tmp;
404 e9bb4aa9 Juha Riihimäki
    tcg_gen_add_i32(dest, t0, t1);
405 e9bb4aa9 Juha Riihimäki
    tmp = load_cpu_field(CF);
406 e9bb4aa9 Juha Riihimäki
    tcg_gen_add_i32(dest, dest, tmp);
407 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
408 e9bb4aa9 Juha Riihimäki
}
409 e9bb4aa9 Juha Riihimäki
410 3670669c pbrook
/* dest = T0 - T1 + CF - 1.  */
411 3670669c pbrook
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
412 3670669c pbrook
{
413 d9ba4830 pbrook
    TCGv tmp;
414 3670669c pbrook
    tcg_gen_sub_i32(dest, t0, t1);
415 d9ba4830 pbrook
    tmp = load_cpu_field(CF);
416 3670669c pbrook
    tcg_gen_add_i32(dest, dest, tmp);
417 3670669c pbrook
    tcg_gen_subi_i32(dest, dest, 1);
418 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
419 3670669c pbrook
}
420 3670669c pbrook
421 b26eefb6 pbrook
/* FIXME:  Implement this natively.  */
422 ad69471c pbrook
#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
423 ad69471c pbrook
424 9a119ff6 pbrook
static void shifter_out_im(TCGv var, int shift)
425 b26eefb6 pbrook
{
426 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
427 9a119ff6 pbrook
    if (shift == 0) {
428 9a119ff6 pbrook
        tcg_gen_andi_i32(tmp, var, 1);
429 b26eefb6 pbrook
    } else {
430 9a119ff6 pbrook
        tcg_gen_shri_i32(tmp, var, shift);
431 4cc633c3 balrog
        if (shift != 31)
432 9a119ff6 pbrook
            tcg_gen_andi_i32(tmp, tmp, 1);
433 9a119ff6 pbrook
    }
434 9a119ff6 pbrook
    gen_set_CF(tmp);
435 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
436 9a119ff6 pbrook
}
437 b26eefb6 pbrook
438 9a119ff6 pbrook
/* Shift by immediate.  Includes special handling for shift == 0.  */
439 9a119ff6 pbrook
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
440 9a119ff6 pbrook
{
441 9a119ff6 pbrook
    switch (shiftop) {
442 9a119ff6 pbrook
    case 0: /* LSL */
443 9a119ff6 pbrook
        if (shift != 0) {
444 9a119ff6 pbrook
            if (flags)
445 9a119ff6 pbrook
                shifter_out_im(var, 32 - shift);
446 9a119ff6 pbrook
            tcg_gen_shli_i32(var, var, shift);
447 9a119ff6 pbrook
        }
448 9a119ff6 pbrook
        break;
449 9a119ff6 pbrook
    case 1: /* LSR */
450 9a119ff6 pbrook
        if (shift == 0) {
451 9a119ff6 pbrook
            if (flags) {
452 9a119ff6 pbrook
                tcg_gen_shri_i32(var, var, 31);
453 9a119ff6 pbrook
                gen_set_CF(var);
454 9a119ff6 pbrook
            }
455 9a119ff6 pbrook
            tcg_gen_movi_i32(var, 0);
456 9a119ff6 pbrook
        } else {
457 9a119ff6 pbrook
            if (flags)
458 9a119ff6 pbrook
                shifter_out_im(var, shift - 1);
459 9a119ff6 pbrook
            tcg_gen_shri_i32(var, var, shift);
460 9a119ff6 pbrook
        }
461 9a119ff6 pbrook
        break;
462 9a119ff6 pbrook
    case 2: /* ASR */
463 9a119ff6 pbrook
        if (shift == 0)
464 9a119ff6 pbrook
            shift = 32;
465 9a119ff6 pbrook
        if (flags)
466 9a119ff6 pbrook
            shifter_out_im(var, shift - 1);
467 9a119ff6 pbrook
        if (shift == 32)
468 9a119ff6 pbrook
          shift = 31;
469 9a119ff6 pbrook
        tcg_gen_sari_i32(var, var, shift);
470 9a119ff6 pbrook
        break;
471 9a119ff6 pbrook
    case 3: /* ROR/RRX */
472 9a119ff6 pbrook
        if (shift != 0) {
473 9a119ff6 pbrook
            if (flags)
474 9a119ff6 pbrook
                shifter_out_im(var, shift - 1);
475 f669df27 Aurelien Jarno
            tcg_gen_rotri_i32(var, var, shift); break;
476 9a119ff6 pbrook
        } else {
477 d9ba4830 pbrook
            TCGv tmp = load_cpu_field(CF);
478 9a119ff6 pbrook
            if (flags)
479 9a119ff6 pbrook
                shifter_out_im(var, 0);
480 9a119ff6 pbrook
            tcg_gen_shri_i32(var, var, 1);
481 b26eefb6 pbrook
            tcg_gen_shli_i32(tmp, tmp, 31);
482 b26eefb6 pbrook
            tcg_gen_or_i32(var, var, tmp);
483 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
484 b26eefb6 pbrook
        }
485 b26eefb6 pbrook
    }
486 b26eefb6 pbrook
};
487 b26eefb6 pbrook
488 8984bd2e pbrook
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
489 8984bd2e pbrook
                                     TCGv shift, int flags)
490 8984bd2e pbrook
{
491 8984bd2e pbrook
    if (flags) {
492 8984bd2e pbrook
        switch (shiftop) {
493 8984bd2e pbrook
        case 0: gen_helper_shl_cc(var, var, shift); break;
494 8984bd2e pbrook
        case 1: gen_helper_shr_cc(var, var, shift); break;
495 8984bd2e pbrook
        case 2: gen_helper_sar_cc(var, var, shift); break;
496 8984bd2e pbrook
        case 3: gen_helper_ror_cc(var, var, shift); break;
497 8984bd2e pbrook
        }
498 8984bd2e pbrook
    } else {
499 8984bd2e pbrook
        switch (shiftop) {
500 8984bd2e pbrook
        case 0: gen_helper_shl(var, var, shift); break;
501 8984bd2e pbrook
        case 1: gen_helper_shr(var, var, shift); break;
502 8984bd2e pbrook
        case 2: gen_helper_sar(var, var, shift); break;
503 f669df27 Aurelien Jarno
        case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
504 f669df27 Aurelien Jarno
                tcg_gen_rotr_i32(var, var, shift); break;
505 8984bd2e pbrook
        }
506 8984bd2e pbrook
    }
507 7d1b0095 Peter Maydell
    tcg_temp_free_i32(shift);
508 8984bd2e pbrook
}
509 8984bd2e pbrook
510 6ddbc6e4 pbrook
#define PAS_OP(pfx) \
511 6ddbc6e4 pbrook
    switch (op2) {  \
512 6ddbc6e4 pbrook
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
513 6ddbc6e4 pbrook
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
514 6ddbc6e4 pbrook
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
515 6ddbc6e4 pbrook
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
516 6ddbc6e4 pbrook
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
517 6ddbc6e4 pbrook
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
518 6ddbc6e4 pbrook
    }
519 d9ba4830 pbrook
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
520 6ddbc6e4 pbrook
{
521 a7812ae4 pbrook
    TCGv_ptr tmp;
522 6ddbc6e4 pbrook
523 6ddbc6e4 pbrook
    switch (op1) {
524 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
525 6ddbc6e4 pbrook
    case 1:
526 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
527 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
528 6ddbc6e4 pbrook
        PAS_OP(s)
529 b75263d6 Juha Riihimäki
        tcg_temp_free_ptr(tmp);
530 6ddbc6e4 pbrook
        break;
531 6ddbc6e4 pbrook
    case 5:
532 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
533 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
534 6ddbc6e4 pbrook
        PAS_OP(u)
535 b75263d6 Juha Riihimäki
        tcg_temp_free_ptr(tmp);
536 6ddbc6e4 pbrook
        break;
537 6ddbc6e4 pbrook
#undef gen_pas_helper
538 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
539 6ddbc6e4 pbrook
    case 2:
540 6ddbc6e4 pbrook
        PAS_OP(q);
541 6ddbc6e4 pbrook
        break;
542 6ddbc6e4 pbrook
    case 3:
543 6ddbc6e4 pbrook
        PAS_OP(sh);
544 6ddbc6e4 pbrook
        break;
545 6ddbc6e4 pbrook
    case 6:
546 6ddbc6e4 pbrook
        PAS_OP(uq);
547 6ddbc6e4 pbrook
        break;
548 6ddbc6e4 pbrook
    case 7:
549 6ddbc6e4 pbrook
        PAS_OP(uh);
550 6ddbc6e4 pbrook
        break;
551 6ddbc6e4 pbrook
#undef gen_pas_helper
552 6ddbc6e4 pbrook
    }
553 6ddbc6e4 pbrook
}
554 9ee6e8bb pbrook
#undef PAS_OP
555 9ee6e8bb pbrook
556 6ddbc6e4 pbrook
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
557 6ddbc6e4 pbrook
#define PAS_OP(pfx) \
558 ed89a2f1 Chih-Min Chao
    switch (op1) {  \
559 6ddbc6e4 pbrook
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
560 6ddbc6e4 pbrook
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
561 6ddbc6e4 pbrook
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
562 6ddbc6e4 pbrook
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
563 6ddbc6e4 pbrook
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
564 6ddbc6e4 pbrook
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
565 6ddbc6e4 pbrook
    }
566 d9ba4830 pbrook
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
567 6ddbc6e4 pbrook
{
568 a7812ae4 pbrook
    TCGv_ptr tmp;
569 6ddbc6e4 pbrook
570 ed89a2f1 Chih-Min Chao
    switch (op2) {
571 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
572 6ddbc6e4 pbrook
    case 0:
573 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
574 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
575 6ddbc6e4 pbrook
        PAS_OP(s)
576 b75263d6 Juha Riihimäki
        tcg_temp_free_ptr(tmp);
577 6ddbc6e4 pbrook
        break;
578 6ddbc6e4 pbrook
    case 4:
579 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
580 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
581 6ddbc6e4 pbrook
        PAS_OP(u)
582 b75263d6 Juha Riihimäki
        tcg_temp_free_ptr(tmp);
583 6ddbc6e4 pbrook
        break;
584 6ddbc6e4 pbrook
#undef gen_pas_helper
585 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
586 6ddbc6e4 pbrook
    case 1:
587 6ddbc6e4 pbrook
        PAS_OP(q);
588 6ddbc6e4 pbrook
        break;
589 6ddbc6e4 pbrook
    case 2:
590 6ddbc6e4 pbrook
        PAS_OP(sh);
591 6ddbc6e4 pbrook
        break;
592 6ddbc6e4 pbrook
    case 5:
593 6ddbc6e4 pbrook
        PAS_OP(uq);
594 6ddbc6e4 pbrook
        break;
595 6ddbc6e4 pbrook
    case 6:
596 6ddbc6e4 pbrook
        PAS_OP(uh);
597 6ddbc6e4 pbrook
        break;
598 6ddbc6e4 pbrook
#undef gen_pas_helper
599 6ddbc6e4 pbrook
    }
600 6ddbc6e4 pbrook
}
601 9ee6e8bb pbrook
#undef PAS_OP
602 9ee6e8bb pbrook
603 d9ba4830 pbrook
static void gen_test_cc(int cc, int label)
604 d9ba4830 pbrook
{
605 d9ba4830 pbrook
    TCGv tmp;
606 d9ba4830 pbrook
    TCGv tmp2;
607 d9ba4830 pbrook
    int inv;
608 d9ba4830 pbrook
609 d9ba4830 pbrook
    switch (cc) {
610 d9ba4830 pbrook
    case 0: /* eq: Z */
611 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
612 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
613 d9ba4830 pbrook
        break;
614 d9ba4830 pbrook
    case 1: /* ne: !Z */
615 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
616 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
617 d9ba4830 pbrook
        break;
618 d9ba4830 pbrook
    case 2: /* cs: C */
619 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
620 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
621 d9ba4830 pbrook
        break;
622 d9ba4830 pbrook
    case 3: /* cc: !C */
623 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
624 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
625 d9ba4830 pbrook
        break;
626 d9ba4830 pbrook
    case 4: /* mi: N */
627 6fbe23d5 pbrook
        tmp = load_cpu_field(NF);
628 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
629 d9ba4830 pbrook
        break;
630 d9ba4830 pbrook
    case 5: /* pl: !N */
631 6fbe23d5 pbrook
        tmp = load_cpu_field(NF);
632 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
633 d9ba4830 pbrook
        break;
634 d9ba4830 pbrook
    case 6: /* vs: V */
635 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
636 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
637 d9ba4830 pbrook
        break;
638 d9ba4830 pbrook
    case 7: /* vc: !V */
639 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
640 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
641 d9ba4830 pbrook
        break;
642 d9ba4830 pbrook
    case 8: /* hi: C && !Z */
643 d9ba4830 pbrook
        inv = gen_new_label();
644 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
645 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
646 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
647 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
648 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
649 d9ba4830 pbrook
        gen_set_label(inv);
650 d9ba4830 pbrook
        break;
651 d9ba4830 pbrook
    case 9: /* ls: !C || Z */
652 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
653 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
654 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
655 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
656 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
657 d9ba4830 pbrook
        break;
658 d9ba4830 pbrook
    case 10: /* ge: N == V -> N ^ V == 0 */
659 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
660 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
661 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
662 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
663 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
664 d9ba4830 pbrook
        break;
665 d9ba4830 pbrook
    case 11: /* lt: N != V -> N ^ V != 0 */
666 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
667 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
668 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
669 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
670 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
671 d9ba4830 pbrook
        break;
672 d9ba4830 pbrook
    case 12: /* gt: !Z && N == V */
673 d9ba4830 pbrook
        inv = gen_new_label();
674 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
675 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
676 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
677 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
678 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
679 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
680 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
681 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
682 d9ba4830 pbrook
        gen_set_label(inv);
683 d9ba4830 pbrook
        break;
684 d9ba4830 pbrook
    case 13: /* le: Z || N != V */
685 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
686 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
687 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
688 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
689 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
690 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
691 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
692 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
693 d9ba4830 pbrook
        break;
694 d9ba4830 pbrook
    default:
695 d9ba4830 pbrook
        fprintf(stderr, "Bad condition code 0x%x\n", cc);
696 d9ba4830 pbrook
        abort();
697 d9ba4830 pbrook
    }
698 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
699 d9ba4830 pbrook
}
700 2c0262af bellard
701 b1d8e52e blueswir1
static const uint8_t table_logic_cc[16] = {
702 2c0262af bellard
    1, /* and */
703 2c0262af bellard
    1, /* xor */
704 2c0262af bellard
    0, /* sub */
705 2c0262af bellard
    0, /* rsb */
706 2c0262af bellard
    0, /* add */
707 2c0262af bellard
    0, /* adc */
708 2c0262af bellard
    0, /* sbc */
709 2c0262af bellard
    0, /* rsc */
710 2c0262af bellard
    1, /* andl */
711 2c0262af bellard
    1, /* xorl */
712 2c0262af bellard
    0, /* cmp */
713 2c0262af bellard
    0, /* cmn */
714 2c0262af bellard
    1, /* orr */
715 2c0262af bellard
    1, /* mov */
716 2c0262af bellard
    1, /* bic */
717 2c0262af bellard
    1, /* mvn */
718 2c0262af bellard
};
719 3b46e624 ths
720 d9ba4830 pbrook
/* Set PC and Thumb state from an immediate address.  */
721 d9ba4830 pbrook
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
722 99c475ab bellard
{
723 b26eefb6 pbrook
    TCGv tmp;
724 99c475ab bellard
725 b26eefb6 pbrook
    s->is_jmp = DISAS_UPDATE;
726 d9ba4830 pbrook
    if (s->thumb != (addr & 1)) {
727 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
728 d9ba4830 pbrook
        tcg_gen_movi_i32(tmp, addr & 1);
729 d9ba4830 pbrook
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
730 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
731 d9ba4830 pbrook
    }
732 155c3eac Filip Navara
    tcg_gen_movi_i32(cpu_R[15], addr & ~1);
733 d9ba4830 pbrook
}
734 d9ba4830 pbrook
735 d9ba4830 pbrook
/* Set PC and Thumb state from var.  var is marked as dead.  */
736 d9ba4830 pbrook
static inline void gen_bx(DisasContext *s, TCGv var)
737 d9ba4830 pbrook
{
738 d9ba4830 pbrook
    s->is_jmp = DISAS_UPDATE;
739 155c3eac Filip Navara
    tcg_gen_andi_i32(cpu_R[15], var, ~1);
740 155c3eac Filip Navara
    tcg_gen_andi_i32(var, var, 1);
741 155c3eac Filip Navara
    store_cpu_field(var, thumb);
742 d9ba4830 pbrook
}
743 d9ba4830 pbrook
744 21aeb343 Juha Riihimäki
/* Variant of store_reg which uses branch&exchange logic when storing
745 21aeb343 Juha Riihimäki
   to r15 in ARM architecture v7 and above. The source must be a temporary
746 21aeb343 Juha Riihimäki
   and will be marked as dead. */
747 21aeb343 Juha Riihimäki
static inline void store_reg_bx(CPUState *env, DisasContext *s,
748 21aeb343 Juha Riihimäki
                                int reg, TCGv var)
749 21aeb343 Juha Riihimäki
{
750 21aeb343 Juha Riihimäki
    if (reg == 15 && ENABLE_ARCH_7) {
751 21aeb343 Juha Riihimäki
        gen_bx(s, var);
752 21aeb343 Juha Riihimäki
    } else {
753 21aeb343 Juha Riihimäki
        store_reg(s, reg, var);
754 21aeb343 Juha Riihimäki
    }
755 21aeb343 Juha Riihimäki
}
756 21aeb343 Juha Riihimäki
757 be5e7a76 Dmitry Eremin-Solenikov
/* Variant of store_reg which uses branch&exchange logic when storing
758 be5e7a76 Dmitry Eremin-Solenikov
 * to r15 in ARM architecture v5T and above. This is used for storing
759 be5e7a76 Dmitry Eremin-Solenikov
 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
760 be5e7a76 Dmitry Eremin-Solenikov
 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
761 be5e7a76 Dmitry Eremin-Solenikov
static inline void store_reg_from_load(CPUState *env, DisasContext *s,
762 be5e7a76 Dmitry Eremin-Solenikov
                                int reg, TCGv var)
763 be5e7a76 Dmitry Eremin-Solenikov
{
764 be5e7a76 Dmitry Eremin-Solenikov
    if (reg == 15 && ENABLE_ARCH_5) {
765 be5e7a76 Dmitry Eremin-Solenikov
        gen_bx(s, var);
766 be5e7a76 Dmitry Eremin-Solenikov
    } else {
767 be5e7a76 Dmitry Eremin-Solenikov
        store_reg(s, reg, var);
768 be5e7a76 Dmitry Eremin-Solenikov
    }
769 be5e7a76 Dmitry Eremin-Solenikov
}
770 be5e7a76 Dmitry Eremin-Solenikov
771 b0109805 pbrook
static inline TCGv gen_ld8s(TCGv addr, int index)
772 b0109805 pbrook
{
773 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
774 b0109805 pbrook
    tcg_gen_qemu_ld8s(tmp, addr, index);
775 b0109805 pbrook
    return tmp;
776 b0109805 pbrook
}
777 b0109805 pbrook
static inline TCGv gen_ld8u(TCGv addr, int index)
778 b0109805 pbrook
{
779 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
780 b0109805 pbrook
    tcg_gen_qemu_ld8u(tmp, addr, index);
781 b0109805 pbrook
    return tmp;
782 b0109805 pbrook
}
783 b0109805 pbrook
static inline TCGv gen_ld16s(TCGv addr, int index)
784 b0109805 pbrook
{
785 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
786 b0109805 pbrook
    tcg_gen_qemu_ld16s(tmp, addr, index);
787 b0109805 pbrook
    return tmp;
788 b0109805 pbrook
}
789 b0109805 pbrook
static inline TCGv gen_ld16u(TCGv addr, int index)
790 b0109805 pbrook
{
791 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
792 b0109805 pbrook
    tcg_gen_qemu_ld16u(tmp, addr, index);
793 b0109805 pbrook
    return tmp;
794 b0109805 pbrook
}
795 b0109805 pbrook
static inline TCGv gen_ld32(TCGv addr, int index)
796 b0109805 pbrook
{
797 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
798 b0109805 pbrook
    tcg_gen_qemu_ld32u(tmp, addr, index);
799 b0109805 pbrook
    return tmp;
800 b0109805 pbrook
}
801 84496233 Juha Riihimäki
static inline TCGv_i64 gen_ld64(TCGv addr, int index)
802 84496233 Juha Riihimäki
{
803 84496233 Juha Riihimäki
    TCGv_i64 tmp = tcg_temp_new_i64();
804 84496233 Juha Riihimäki
    tcg_gen_qemu_ld64(tmp, addr, index);
805 84496233 Juha Riihimäki
    return tmp;
806 84496233 Juha Riihimäki
}
807 b0109805 pbrook
static inline void gen_st8(TCGv val, TCGv addr, int index)
808 b0109805 pbrook
{
809 b0109805 pbrook
    tcg_gen_qemu_st8(val, addr, index);
810 7d1b0095 Peter Maydell
    tcg_temp_free_i32(val);
811 b0109805 pbrook
}
812 b0109805 pbrook
static inline void gen_st16(TCGv val, TCGv addr, int index)
813 b0109805 pbrook
{
814 b0109805 pbrook
    tcg_gen_qemu_st16(val, addr, index);
815 7d1b0095 Peter Maydell
    tcg_temp_free_i32(val);
816 b0109805 pbrook
}
817 b0109805 pbrook
static inline void gen_st32(TCGv val, TCGv addr, int index)
818 b0109805 pbrook
{
819 b0109805 pbrook
    tcg_gen_qemu_st32(val, addr, index);
820 7d1b0095 Peter Maydell
    tcg_temp_free_i32(val);
821 b0109805 pbrook
}
822 84496233 Juha Riihimäki
static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
823 84496233 Juha Riihimäki
{
824 84496233 Juha Riihimäki
    tcg_gen_qemu_st64(val, addr, index);
825 84496233 Juha Riihimäki
    tcg_temp_free_i64(val);
826 84496233 Juha Riihimäki
}
827 b5ff1b31 bellard
828 5e3f878a pbrook
static inline void gen_set_pc_im(uint32_t val)
829 5e3f878a pbrook
{
830 155c3eac Filip Navara
    tcg_gen_movi_i32(cpu_R[15], val);
831 5e3f878a pbrook
}
832 5e3f878a pbrook
833 b5ff1b31 bellard
/* Force a TB lookup after an instruction that changes the CPU state.  */
834 b5ff1b31 bellard
static inline void gen_lookup_tb(DisasContext *s)
835 b5ff1b31 bellard
{
836 a6445c52 Filip Navara
    tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
837 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
838 b5ff1b31 bellard
}
839 b5ff1b31 bellard
840 b0109805 pbrook
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
841 b0109805 pbrook
                                       TCGv var)
842 2c0262af bellard
{
843 1e8d4eec bellard
    int val, rm, shift, shiftop;
844 b26eefb6 pbrook
    TCGv offset;
845 2c0262af bellard
846 2c0262af bellard
    if (!(insn & (1 << 25))) {
847 2c0262af bellard
        /* immediate */
848 2c0262af bellard
        val = insn & 0xfff;
849 2c0262af bellard
        if (!(insn & (1 << 23)))
850 2c0262af bellard
            val = -val;
851 537730b9 bellard
        if (val != 0)
852 b0109805 pbrook
            tcg_gen_addi_i32(var, var, val);
853 2c0262af bellard
    } else {
854 2c0262af bellard
        /* shift/register */
855 2c0262af bellard
        rm = (insn) & 0xf;
856 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
857 1e8d4eec bellard
        shiftop = (insn >> 5) & 3;
858 b26eefb6 pbrook
        offset = load_reg(s, rm);
859 9a119ff6 pbrook
        gen_arm_shift_im(offset, shiftop, shift, 0);
860 2c0262af bellard
        if (!(insn & (1 << 23)))
861 b0109805 pbrook
            tcg_gen_sub_i32(var, var, offset);
862 2c0262af bellard
        else
863 b0109805 pbrook
            tcg_gen_add_i32(var, var, offset);
864 7d1b0095 Peter Maydell
        tcg_temp_free_i32(offset);
865 2c0262af bellard
    }
866 2c0262af bellard
}
867 2c0262af bellard
868 191f9a93 pbrook
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
869 b0109805 pbrook
                                        int extra, TCGv var)
870 2c0262af bellard
{
871 2c0262af bellard
    int val, rm;
872 b26eefb6 pbrook
    TCGv offset;
873 3b46e624 ths
874 2c0262af bellard
    if (insn & (1 << 22)) {
875 2c0262af bellard
        /* immediate */
876 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
877 2c0262af bellard
        if (!(insn & (1 << 23)))
878 2c0262af bellard
            val = -val;
879 18acad92 pbrook
        val += extra;
880 537730b9 bellard
        if (val != 0)
881 b0109805 pbrook
            tcg_gen_addi_i32(var, var, val);
882 2c0262af bellard
    } else {
883 2c0262af bellard
        /* register */
884 191f9a93 pbrook
        if (extra)
885 b0109805 pbrook
            tcg_gen_addi_i32(var, var, extra);
886 2c0262af bellard
        rm = (insn) & 0xf;
887 b26eefb6 pbrook
        offset = load_reg(s, rm);
888 2c0262af bellard
        if (!(insn & (1 << 23)))
889 b0109805 pbrook
            tcg_gen_sub_i32(var, var, offset);
890 2c0262af bellard
        else
891 b0109805 pbrook
            tcg_gen_add_i32(var, var, offset);
892 7d1b0095 Peter Maydell
        tcg_temp_free_i32(offset);
893 2c0262af bellard
    }
894 2c0262af bellard
}
895 2c0262af bellard
896 4373f3ce pbrook
#define VFP_OP2(name)                                                 \
897 4373f3ce pbrook
static inline void gen_vfp_##name(int dp)                             \
898 4373f3ce pbrook
{                                                                     \
899 4373f3ce pbrook
    if (dp)                                                           \
900 4373f3ce pbrook
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
901 4373f3ce pbrook
    else                                                              \
902 4373f3ce pbrook
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
903 b7bcbe95 bellard
}
904 b7bcbe95 bellard
905 4373f3ce pbrook
VFP_OP2(add)
906 4373f3ce pbrook
VFP_OP2(sub)
907 4373f3ce pbrook
VFP_OP2(mul)
908 4373f3ce pbrook
VFP_OP2(div)
909 4373f3ce pbrook
910 4373f3ce pbrook
#undef VFP_OP2
911 4373f3ce pbrook
912 605a6aed Peter Maydell
static inline void gen_vfp_F1_mul(int dp)
913 605a6aed Peter Maydell
{
914 605a6aed Peter Maydell
    /* Like gen_vfp_mul() but put result in F1 */
915 605a6aed Peter Maydell
    if (dp) {
916 605a6aed Peter Maydell
        gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env);
917 605a6aed Peter Maydell
    } else {
918 605a6aed Peter Maydell
        gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env);
919 605a6aed Peter Maydell
    }
920 605a6aed Peter Maydell
}
921 605a6aed Peter Maydell
922 605a6aed Peter Maydell
static inline void gen_vfp_F1_neg(int dp)
923 605a6aed Peter Maydell
{
924 605a6aed Peter Maydell
    /* Like gen_vfp_neg() but put result in F1 */
925 605a6aed Peter Maydell
    if (dp) {
926 605a6aed Peter Maydell
        gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
927 605a6aed Peter Maydell
    } else {
928 605a6aed Peter Maydell
        gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
929 605a6aed Peter Maydell
    }
930 605a6aed Peter Maydell
}
931 605a6aed Peter Maydell
932 4373f3ce pbrook
static inline void gen_vfp_abs(int dp)
933 4373f3ce pbrook
{
934 4373f3ce pbrook
    if (dp)
935 4373f3ce pbrook
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
936 4373f3ce pbrook
    else
937 4373f3ce pbrook
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
938 4373f3ce pbrook
}
939 4373f3ce pbrook
940 4373f3ce pbrook
static inline void gen_vfp_neg(int dp)
941 4373f3ce pbrook
{
942 4373f3ce pbrook
    if (dp)
943 4373f3ce pbrook
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
944 4373f3ce pbrook
    else
945 4373f3ce pbrook
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
946 4373f3ce pbrook
}
947 4373f3ce pbrook
948 4373f3ce pbrook
static inline void gen_vfp_sqrt(int dp)
949 4373f3ce pbrook
{
950 4373f3ce pbrook
    if (dp)
951 4373f3ce pbrook
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
952 4373f3ce pbrook
    else
953 4373f3ce pbrook
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
954 4373f3ce pbrook
}
955 4373f3ce pbrook
956 4373f3ce pbrook
static inline void gen_vfp_cmp(int dp)
957 4373f3ce pbrook
{
958 4373f3ce pbrook
    if (dp)
959 4373f3ce pbrook
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
960 4373f3ce pbrook
    else
961 4373f3ce pbrook
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
962 4373f3ce pbrook
}
963 4373f3ce pbrook
964 4373f3ce pbrook
static inline void gen_vfp_cmpe(int dp)
965 4373f3ce pbrook
{
966 4373f3ce pbrook
    if (dp)
967 4373f3ce pbrook
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
968 4373f3ce pbrook
    else
969 4373f3ce pbrook
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
970 4373f3ce pbrook
}
971 4373f3ce pbrook
972 4373f3ce pbrook
static inline void gen_vfp_F1_ld0(int dp)
973 4373f3ce pbrook
{
974 4373f3ce pbrook
    if (dp)
975 5b340b51 balrog
        tcg_gen_movi_i64(cpu_F1d, 0);
976 4373f3ce pbrook
    else
977 5b340b51 balrog
        tcg_gen_movi_i32(cpu_F1s, 0);
978 4373f3ce pbrook
}
979 4373f3ce pbrook
980 4373f3ce pbrook
static inline void gen_vfp_uito(int dp)
981 4373f3ce pbrook
{
982 4373f3ce pbrook
    if (dp)
983 4373f3ce pbrook
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
984 4373f3ce pbrook
    else
985 4373f3ce pbrook
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
986 4373f3ce pbrook
}
987 4373f3ce pbrook
988 4373f3ce pbrook
static inline void gen_vfp_sito(int dp)
989 4373f3ce pbrook
{
990 4373f3ce pbrook
    if (dp)
991 66230e0d balrog
        gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
992 4373f3ce pbrook
    else
993 66230e0d balrog
        gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
994 4373f3ce pbrook
}
995 4373f3ce pbrook
996 4373f3ce pbrook
static inline void gen_vfp_toui(int dp)
997 4373f3ce pbrook
{
998 4373f3ce pbrook
    if (dp)
999 4373f3ce pbrook
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1000 4373f3ce pbrook
    else
1001 4373f3ce pbrook
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1002 4373f3ce pbrook
}
1003 4373f3ce pbrook
1004 4373f3ce pbrook
static inline void gen_vfp_touiz(int dp)
1005 4373f3ce pbrook
{
1006 4373f3ce pbrook
    if (dp)
1007 4373f3ce pbrook
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1008 4373f3ce pbrook
    else
1009 4373f3ce pbrook
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1010 4373f3ce pbrook
}
1011 4373f3ce pbrook
1012 4373f3ce pbrook
static inline void gen_vfp_tosi(int dp)
1013 4373f3ce pbrook
{
1014 4373f3ce pbrook
    if (dp)
1015 4373f3ce pbrook
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1016 4373f3ce pbrook
    else
1017 4373f3ce pbrook
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1018 4373f3ce pbrook
}
1019 4373f3ce pbrook
1020 4373f3ce pbrook
static inline void gen_vfp_tosiz(int dp)
1021 9ee6e8bb pbrook
{
1022 9ee6e8bb pbrook
    if (dp)
1023 4373f3ce pbrook
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1024 9ee6e8bb pbrook
    else
1025 4373f3ce pbrook
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1026 4373f3ce pbrook
}
1027 4373f3ce pbrook
1028 4373f3ce pbrook
#define VFP_GEN_FIX(name) \
1029 4373f3ce pbrook
static inline void gen_vfp_##name(int dp, int shift) \
1030 4373f3ce pbrook
{ \
1031 b75263d6 Juha Riihimäki
    TCGv tmp_shift = tcg_const_i32(shift); \
1032 4373f3ce pbrook
    if (dp) \
1033 b75263d6 Juha Riihimäki
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1034 4373f3ce pbrook
    else \
1035 b75263d6 Juha Riihimäki
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1036 b75263d6 Juha Riihimäki
    tcg_temp_free_i32(tmp_shift); \
1037 9ee6e8bb pbrook
}
1038 4373f3ce pbrook
VFP_GEN_FIX(tosh)
1039 4373f3ce pbrook
VFP_GEN_FIX(tosl)
1040 4373f3ce pbrook
VFP_GEN_FIX(touh)
1041 4373f3ce pbrook
VFP_GEN_FIX(toul)
1042 4373f3ce pbrook
VFP_GEN_FIX(shto)
1043 4373f3ce pbrook
VFP_GEN_FIX(slto)
1044 4373f3ce pbrook
VFP_GEN_FIX(uhto)
1045 4373f3ce pbrook
VFP_GEN_FIX(ulto)
1046 4373f3ce pbrook
#undef VFP_GEN_FIX
1047 9ee6e8bb pbrook
1048 312eea9f Filip Navara
static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1049 b5ff1b31 bellard
{
1050 b5ff1b31 bellard
    if (dp)
1051 312eea9f Filip Navara
        tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1052 b5ff1b31 bellard
    else
1053 312eea9f Filip Navara
        tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1054 b5ff1b31 bellard
}
1055 b5ff1b31 bellard
1056 312eea9f Filip Navara
static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1057 b5ff1b31 bellard
{
1058 b5ff1b31 bellard
    if (dp)
1059 312eea9f Filip Navara
        tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1060 b5ff1b31 bellard
    else
1061 312eea9f Filip Navara
        tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1062 b5ff1b31 bellard
}
1063 b5ff1b31 bellard
1064 8e96005d bellard
static inline long
1065 8e96005d bellard
vfp_reg_offset (int dp, int reg)
1066 8e96005d bellard
{
1067 8e96005d bellard
    if (dp)
1068 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg]);
1069 8e96005d bellard
    else if (reg & 1) {
1070 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1071 8e96005d bellard
          + offsetof(CPU_DoubleU, l.upper);
1072 8e96005d bellard
    } else {
1073 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1074 8e96005d bellard
          + offsetof(CPU_DoubleU, l.lower);
1075 8e96005d bellard
    }
1076 8e96005d bellard
}
1077 9ee6e8bb pbrook
1078 9ee6e8bb pbrook
/* Return the offset of a 32-bit piece of a NEON register.
1079 9ee6e8bb pbrook
   zero is the least significant end of the register.  */
1080 9ee6e8bb pbrook
static inline long
1081 9ee6e8bb pbrook
neon_reg_offset (int reg, int n)
1082 9ee6e8bb pbrook
{
1083 9ee6e8bb pbrook
    int sreg;
1084 9ee6e8bb pbrook
    sreg = reg * 2 + n;
1085 9ee6e8bb pbrook
    return vfp_reg_offset(0, sreg);
1086 9ee6e8bb pbrook
}
1087 9ee6e8bb pbrook
1088 8f8e3aa4 pbrook
static TCGv neon_load_reg(int reg, int pass)
1089 8f8e3aa4 pbrook
{
1090 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
1091 8f8e3aa4 pbrook
    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1092 8f8e3aa4 pbrook
    return tmp;
1093 8f8e3aa4 pbrook
}
1094 8f8e3aa4 pbrook
1095 8f8e3aa4 pbrook
static void neon_store_reg(int reg, int pass, TCGv var)
1096 8f8e3aa4 pbrook
{
1097 8f8e3aa4 pbrook
    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1098 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
1099 8f8e3aa4 pbrook
}
1100 8f8e3aa4 pbrook
1101 a7812ae4 pbrook
static inline void neon_load_reg64(TCGv_i64 var, int reg)
1102 ad69471c pbrook
{
1103 ad69471c pbrook
    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1104 ad69471c pbrook
}
1105 ad69471c pbrook
1106 a7812ae4 pbrook
static inline void neon_store_reg64(TCGv_i64 var, int reg)
1107 ad69471c pbrook
{
1108 ad69471c pbrook
    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1109 ad69471c pbrook
}
1110 ad69471c pbrook
1111 4373f3ce pbrook
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1112 4373f3ce pbrook
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1113 4373f3ce pbrook
#define tcg_gen_st_f32 tcg_gen_st_i32
1114 4373f3ce pbrook
#define tcg_gen_st_f64 tcg_gen_st_i64
1115 4373f3ce pbrook
1116 b7bcbe95 bellard
static inline void gen_mov_F0_vreg(int dp, int reg)
1117 b7bcbe95 bellard
{
1118 b7bcbe95 bellard
    if (dp)
1119 4373f3ce pbrook
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1120 b7bcbe95 bellard
    else
1121 4373f3ce pbrook
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1122 b7bcbe95 bellard
}
1123 b7bcbe95 bellard
1124 b7bcbe95 bellard
static inline void gen_mov_F1_vreg(int dp, int reg)
1125 b7bcbe95 bellard
{
1126 b7bcbe95 bellard
    if (dp)
1127 4373f3ce pbrook
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1128 b7bcbe95 bellard
    else
1129 4373f3ce pbrook
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1130 b7bcbe95 bellard
}
1131 b7bcbe95 bellard
1132 b7bcbe95 bellard
static inline void gen_mov_vreg_F0(int dp, int reg)
1133 b7bcbe95 bellard
{
1134 b7bcbe95 bellard
    if (dp)
1135 4373f3ce pbrook
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1136 b7bcbe95 bellard
    else
1137 4373f3ce pbrook
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1138 b7bcbe95 bellard
}
1139 b7bcbe95 bellard
1140 18c9b560 balrog
#define ARM_CP_RW_BIT        (1 << 20)
1141 18c9b560 balrog
1142 a7812ae4 pbrook
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1143 e677137d pbrook
{
1144 e677137d pbrook
    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1145 e677137d pbrook
}
1146 e677137d pbrook
1147 a7812ae4 pbrook
static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1148 e677137d pbrook
{
1149 e677137d pbrook
    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1150 e677137d pbrook
}
1151 e677137d pbrook
1152 da6b5335 Filip Navara
static inline TCGv iwmmxt_load_creg(int reg)
1153 e677137d pbrook
{
1154 7d1b0095 Peter Maydell
    TCGv var = tcg_temp_new_i32();
1155 da6b5335 Filip Navara
    tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1156 da6b5335 Filip Navara
    return var;
1157 e677137d pbrook
}
1158 e677137d pbrook
1159 da6b5335 Filip Navara
static inline void iwmmxt_store_creg(int reg, TCGv var)
1160 e677137d pbrook
{
1161 da6b5335 Filip Navara
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1162 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
1163 e677137d pbrook
}
1164 e677137d pbrook
1165 e677137d pbrook
static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1166 e677137d pbrook
{
1167 e677137d pbrook
    iwmmxt_store_reg(cpu_M0, rn);
1168 e677137d pbrook
}
1169 e677137d pbrook
1170 e677137d pbrook
static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1171 e677137d pbrook
{
1172 e677137d pbrook
    iwmmxt_load_reg(cpu_M0, rn);
1173 e677137d pbrook
}
1174 e677137d pbrook
1175 e677137d pbrook
static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1176 e677137d pbrook
{
1177 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1178 e677137d pbrook
    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1179 e677137d pbrook
}
1180 e677137d pbrook
1181 e677137d pbrook
static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1182 e677137d pbrook
{
1183 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1184 e677137d pbrook
    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1185 e677137d pbrook
}
1186 e677137d pbrook
1187 e677137d pbrook
static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1188 e677137d pbrook
{
1189 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1190 e677137d pbrook
    tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1191 e677137d pbrook
}
1192 e677137d pbrook
1193 e677137d pbrook
#define IWMMXT_OP(name) \
1194 e677137d pbrook
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1195 e677137d pbrook
{ \
1196 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn); \
1197 e677137d pbrook
    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1198 e677137d pbrook
}
1199 e677137d pbrook
1200 947a2fa2 Peter Maydell
#define IWMMXT_OP_SIZE(name) \
1201 947a2fa2 Peter Maydell
IWMMXT_OP(name##b) \
1202 947a2fa2 Peter Maydell
IWMMXT_OP(name##w) \
1203 947a2fa2 Peter Maydell
IWMMXT_OP(name##l)
1204 e677137d pbrook
1205 947a2fa2 Peter Maydell
#define IWMMXT_OP_1(name) \
1206 e677137d pbrook
static inline void gen_op_iwmmxt_##name##_M0(void) \
1207 e677137d pbrook
{ \
1208 947a2fa2 Peter Maydell
    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \
1209 e677137d pbrook
}
1210 e677137d pbrook
1211 e677137d pbrook
IWMMXT_OP(maddsq)
1212 e677137d pbrook
IWMMXT_OP(madduq)
1213 e677137d pbrook
IWMMXT_OP(sadb)
1214 e677137d pbrook
IWMMXT_OP(sadw)
1215 e677137d pbrook
IWMMXT_OP(mulslw)
1216 e677137d pbrook
IWMMXT_OP(mulshw)
1217 e677137d pbrook
IWMMXT_OP(mululw)
1218 e677137d pbrook
IWMMXT_OP(muluhw)
1219 e677137d pbrook
IWMMXT_OP(macsw)
1220 e677137d pbrook
IWMMXT_OP(macuw)
1221 e677137d pbrook
1222 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(unpackl)
1223 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(unpackh)
1224 947a2fa2 Peter Maydell
1225 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpacklub)
1226 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackluw)
1227 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpacklul)
1228 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhub)
1229 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhuw)
1230 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhul)
1231 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpacklsb)
1232 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpacklsw)
1233 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpacklsl)
1234 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhsb)
1235 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhsw)
1236 947a2fa2 Peter Maydell
IWMMXT_OP_1(unpackhsl)
1237 947a2fa2 Peter Maydell
1238 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(cmpeq)
1239 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(cmpgtu)
1240 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(cmpgts)
1241 947a2fa2 Peter Maydell
1242 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(mins)
1243 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(minu)
1244 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(maxs)
1245 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(maxu)
1246 947a2fa2 Peter Maydell
1247 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(subn)
1248 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(addn)
1249 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(subu)
1250 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(addu)
1251 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(subs)
1252 947a2fa2 Peter Maydell
IWMMXT_OP_SIZE(adds)
1253 947a2fa2 Peter Maydell
1254 947a2fa2 Peter Maydell
IWMMXT_OP(avgb0)
1255 947a2fa2 Peter Maydell
IWMMXT_OP(avgb1)
1256 947a2fa2 Peter Maydell
IWMMXT_OP(avgw0)
1257 947a2fa2 Peter Maydell
IWMMXT_OP(avgw1)
1258 e677137d pbrook
1259 e677137d pbrook
IWMMXT_OP(msadb)
1260 e677137d pbrook
1261 947a2fa2 Peter Maydell
IWMMXT_OP(packuw)
1262 947a2fa2 Peter Maydell
IWMMXT_OP(packul)
1263 947a2fa2 Peter Maydell
IWMMXT_OP(packuq)
1264 947a2fa2 Peter Maydell
IWMMXT_OP(packsw)
1265 947a2fa2 Peter Maydell
IWMMXT_OP(packsl)
1266 947a2fa2 Peter Maydell
IWMMXT_OP(packsq)
1267 e677137d pbrook
1268 e677137d pbrook
static void gen_op_iwmmxt_set_mup(void)
1269 e677137d pbrook
{
1270 e677137d pbrook
    TCGv tmp;
1271 e677137d pbrook
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1272 e677137d pbrook
    tcg_gen_ori_i32(tmp, tmp, 2);
1273 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1274 e677137d pbrook
}
1275 e677137d pbrook
1276 e677137d pbrook
static void gen_op_iwmmxt_set_cup(void)
1277 e677137d pbrook
{
1278 e677137d pbrook
    TCGv tmp;
1279 e677137d pbrook
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1280 e677137d pbrook
    tcg_gen_ori_i32(tmp, tmp, 1);
1281 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1282 e677137d pbrook
}
1283 e677137d pbrook
1284 e677137d pbrook
static void gen_op_iwmmxt_setpsr_nz(void)
1285 e677137d pbrook
{
1286 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
1287 e677137d pbrook
    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1288 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1289 e677137d pbrook
}
1290 e677137d pbrook
1291 e677137d pbrook
static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1292 e677137d pbrook
{
1293 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1294 86831435 pbrook
    tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1295 e677137d pbrook
    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1296 e677137d pbrook
}
1297 e677137d pbrook
1298 da6b5335 Filip Navara
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1299 18c9b560 balrog
{
1300 18c9b560 balrog
    int rd;
1301 18c9b560 balrog
    uint32_t offset;
1302 da6b5335 Filip Navara
    TCGv tmp;
1303 18c9b560 balrog
1304 18c9b560 balrog
    rd = (insn >> 16) & 0xf;
1305 da6b5335 Filip Navara
    tmp = load_reg(s, rd);
1306 18c9b560 balrog
1307 18c9b560 balrog
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1308 18c9b560 balrog
    if (insn & (1 << 24)) {
1309 18c9b560 balrog
        /* Pre indexed */
1310 18c9b560 balrog
        if (insn & (1 << 23))
1311 da6b5335 Filip Navara
            tcg_gen_addi_i32(tmp, tmp, offset);
1312 18c9b560 balrog
        else
1313 da6b5335 Filip Navara
            tcg_gen_addi_i32(tmp, tmp, -offset);
1314 da6b5335 Filip Navara
        tcg_gen_mov_i32(dest, tmp);
1315 18c9b560 balrog
        if (insn & (1 << 21))
1316 da6b5335 Filip Navara
            store_reg(s, rd, tmp);
1317 da6b5335 Filip Navara
        else
1318 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
1319 18c9b560 balrog
    } else if (insn & (1 << 21)) {
1320 18c9b560 balrog
        /* Post indexed */
1321 da6b5335 Filip Navara
        tcg_gen_mov_i32(dest, tmp);
1322 18c9b560 balrog
        if (insn & (1 << 23))
1323 da6b5335 Filip Navara
            tcg_gen_addi_i32(tmp, tmp, offset);
1324 18c9b560 balrog
        else
1325 da6b5335 Filip Navara
            tcg_gen_addi_i32(tmp, tmp, -offset);
1326 da6b5335 Filip Navara
        store_reg(s, rd, tmp);
1327 18c9b560 balrog
    } else if (!(insn & (1 << 23)))
1328 18c9b560 balrog
        return 1;
1329 18c9b560 balrog
    return 0;
1330 18c9b560 balrog
}
1331 18c9b560 balrog
1332 da6b5335 Filip Navara
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1333 18c9b560 balrog
{
1334 18c9b560 balrog
    int rd = (insn >> 0) & 0xf;
1335 da6b5335 Filip Navara
    TCGv tmp;
1336 18c9b560 balrog
1337 da6b5335 Filip Navara
    if (insn & (1 << 8)) {
1338 da6b5335 Filip Navara
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1339 18c9b560 balrog
            return 1;
1340 da6b5335 Filip Navara
        } else {
1341 da6b5335 Filip Navara
            tmp = iwmmxt_load_creg(rd);
1342 da6b5335 Filip Navara
        }
1343 da6b5335 Filip Navara
    } else {
1344 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
1345 da6b5335 Filip Navara
        iwmmxt_load_reg(cpu_V0, rd);
1346 da6b5335 Filip Navara
        tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1347 da6b5335 Filip Navara
    }
1348 da6b5335 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, mask);
1349 da6b5335 Filip Navara
    tcg_gen_mov_i32(dest, tmp);
1350 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
1351 18c9b560 balrog
    return 0;
1352 18c9b560 balrog
}
1353 18c9b560 balrog
1354 a1c7273b Stefan Weil
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occurred
1355 18c9b560 balrog
   (ie. an undefined instruction).  */
1356 18c9b560 balrog
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1357 18c9b560 balrog
{
1358 18c9b560 balrog
    int rd, wrd;
1359 18c9b560 balrog
    int rdhi, rdlo, rd0, rd1, i;
1360 da6b5335 Filip Navara
    TCGv addr;
1361 da6b5335 Filip Navara
    TCGv tmp, tmp2, tmp3;
1362 18c9b560 balrog
1363 18c9b560 balrog
    if ((insn & 0x0e000e00) == 0x0c000000) {
1364 18c9b560 balrog
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1365 18c9b560 balrog
            wrd = insn & 0xf;
1366 18c9b560 balrog
            rdlo = (insn >> 12) & 0xf;
1367 18c9b560 balrog
            rdhi = (insn >> 16) & 0xf;
1368 18c9b560 balrog
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1369 da6b5335 Filip Navara
                iwmmxt_load_reg(cpu_V0, wrd);
1370 da6b5335 Filip Navara
                tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1371 da6b5335 Filip Navara
                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1372 da6b5335 Filip Navara
                tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1373 18c9b560 balrog
            } else {                                        /* TMCRR */
1374 da6b5335 Filip Navara
                tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1375 da6b5335 Filip Navara
                iwmmxt_store_reg(cpu_V0, wrd);
1376 18c9b560 balrog
                gen_op_iwmmxt_set_mup();
1377 18c9b560 balrog
            }
1378 18c9b560 balrog
            return 0;
1379 18c9b560 balrog
        }
1380 18c9b560 balrog
1381 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1382 7d1b0095 Peter Maydell
        addr = tcg_temp_new_i32();
1383 da6b5335 Filip Navara
        if (gen_iwmmxt_address(s, insn, addr)) {
1384 7d1b0095 Peter Maydell
            tcg_temp_free_i32(addr);
1385 18c9b560 balrog
            return 1;
1386 da6b5335 Filip Navara
        }
1387 18c9b560 balrog
        if (insn & ARM_CP_RW_BIT) {
1388 18c9b560 balrog
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1389 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
1390 da6b5335 Filip Navara
                tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1391 da6b5335 Filip Navara
                iwmmxt_store_creg(wrd, tmp);
1392 18c9b560 balrog
            } else {
1393 e677137d pbrook
                i = 1;
1394 e677137d pbrook
                if (insn & (1 << 8)) {
1395 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WLDRD */
1396 da6b5335 Filip Navara
                        tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1397 e677137d pbrook
                        i = 0;
1398 e677137d pbrook
                    } else {                                /* WLDRW wRd */
1399 da6b5335 Filip Navara
                        tmp = gen_ld32(addr, IS_USER(s));
1400 e677137d pbrook
                    }
1401 e677137d pbrook
                } else {
1402 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WLDRH */
1403 da6b5335 Filip Navara
                        tmp = gen_ld16u(addr, IS_USER(s));
1404 e677137d pbrook
                    } else {                                /* WLDRB */
1405 da6b5335 Filip Navara
                        tmp = gen_ld8u(addr, IS_USER(s));
1406 e677137d pbrook
                    }
1407 e677137d pbrook
                }
1408 e677137d pbrook
                if (i) {
1409 e677137d pbrook
                    tcg_gen_extu_i32_i64(cpu_M0, tmp);
1410 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
1411 e677137d pbrook
                }
1412 18c9b560 balrog
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1413 18c9b560 balrog
            }
1414 18c9b560 balrog
        } else {
1415 18c9b560 balrog
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1416 da6b5335 Filip Navara
                tmp = iwmmxt_load_creg(wrd);
1417 da6b5335 Filip Navara
                gen_st32(tmp, addr, IS_USER(s));
1418 18c9b560 balrog
            } else {
1419 18c9b560 balrog
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1420 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
1421 e677137d pbrook
                if (insn & (1 << 8)) {
1422 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WSTRD */
1423 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
1424 da6b5335 Filip Navara
                        tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1425 e677137d pbrook
                    } else {                                /* WSTRW wRd */
1426 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1427 da6b5335 Filip Navara
                        gen_st32(tmp, addr, IS_USER(s));
1428 e677137d pbrook
                    }
1429 e677137d pbrook
                } else {
1430 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WSTRH */
1431 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1432 da6b5335 Filip Navara
                        gen_st16(tmp, addr, IS_USER(s));
1433 e677137d pbrook
                    } else {                                /* WSTRB */
1434 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1435 da6b5335 Filip Navara
                        gen_st8(tmp, addr, IS_USER(s));
1436 e677137d pbrook
                    }
1437 e677137d pbrook
                }
1438 18c9b560 balrog
            }
1439 18c9b560 balrog
        }
1440 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
1441 18c9b560 balrog
        return 0;
1442 18c9b560 balrog
    }
1443 18c9b560 balrog
1444 18c9b560 balrog
    if ((insn & 0x0f000000) != 0x0e000000)
1445 18c9b560 balrog
        return 1;
1446 18c9b560 balrog
1447 18c9b560 balrog
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1448 18c9b560 balrog
    case 0x000:                                                /* WOR */
1449 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1450 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1451 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1452 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1453 18c9b560 balrog
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1454 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1455 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1456 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1457 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1458 18c9b560 balrog
        break;
1459 18c9b560 balrog
    case 0x011:                                                /* TMCR */
1460 18c9b560 balrog
        if (insn & 0xf)
1461 18c9b560 balrog
            return 1;
1462 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1463 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1464 18c9b560 balrog
        switch (wrd) {
1465 18c9b560 balrog
        case ARM_IWMMXT_wCID:
1466 18c9b560 balrog
        case ARM_IWMMXT_wCASF:
1467 18c9b560 balrog
            break;
1468 18c9b560 balrog
        case ARM_IWMMXT_wCon:
1469 18c9b560 balrog
            gen_op_iwmmxt_set_cup();
1470 18c9b560 balrog
            /* Fall through.  */
1471 18c9b560 balrog
        case ARM_IWMMXT_wCSSF:
1472 da6b5335 Filip Navara
            tmp = iwmmxt_load_creg(wrd);
1473 da6b5335 Filip Navara
            tmp2 = load_reg(s, rd);
1474 f669df27 Aurelien Jarno
            tcg_gen_andc_i32(tmp, tmp, tmp2);
1475 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
1476 da6b5335 Filip Navara
            iwmmxt_store_creg(wrd, tmp);
1477 18c9b560 balrog
            break;
1478 18c9b560 balrog
        case ARM_IWMMXT_wCGR0:
1479 18c9b560 balrog
        case ARM_IWMMXT_wCGR1:
1480 18c9b560 balrog
        case ARM_IWMMXT_wCGR2:
1481 18c9b560 balrog
        case ARM_IWMMXT_wCGR3:
1482 18c9b560 balrog
            gen_op_iwmmxt_set_cup();
1483 da6b5335 Filip Navara
            tmp = load_reg(s, rd);
1484 da6b5335 Filip Navara
            iwmmxt_store_creg(wrd, tmp);
1485 18c9b560 balrog
            break;
1486 18c9b560 balrog
        default:
1487 18c9b560 balrog
            return 1;
1488 18c9b560 balrog
        }
1489 18c9b560 balrog
        break;
1490 18c9b560 balrog
    case 0x100:                                                /* WXOR */
1491 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1492 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1493 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1494 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1495 18c9b560 balrog
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1496 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1497 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1498 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1499 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1500 18c9b560 balrog
        break;
1501 18c9b560 balrog
    case 0x111:                                                /* TMRC */
1502 18c9b560 balrog
        if (insn & 0xf)
1503 18c9b560 balrog
            return 1;
1504 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1505 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1506 da6b5335 Filip Navara
        tmp = iwmmxt_load_creg(wrd);
1507 da6b5335 Filip Navara
        store_reg(s, rd, tmp);
1508 18c9b560 balrog
        break;
1509 18c9b560 balrog
    case 0x300:                                                /* WANDN */
1510 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1511 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1512 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1513 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1514 e677137d pbrook
        tcg_gen_neg_i64(cpu_M0, cpu_M0);
1515 18c9b560 balrog
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1516 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1517 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1518 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1519 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1520 18c9b560 balrog
        break;
1521 18c9b560 balrog
    case 0x200:                                                /* WAND */
1522 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1523 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1524 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1525 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1526 18c9b560 balrog
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1527 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1528 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1529 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1530 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1531 18c9b560 balrog
        break;
1532 18c9b560 balrog
    case 0x810: case 0xa10:                                /* WMADD */
1533 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1534 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1535 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1536 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1537 18c9b560 balrog
        if (insn & (1 << 21))
1538 18c9b560 balrog
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1539 18c9b560 balrog
        else
1540 18c9b560 balrog
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1541 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1542 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1543 18c9b560 balrog
        break;
1544 18c9b560 balrog
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1545 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1546 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1547 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1548 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1549 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1550 18c9b560 balrog
        case 0:
1551 18c9b560 balrog
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1552 18c9b560 balrog
            break;
1553 18c9b560 balrog
        case 1:
1554 18c9b560 balrog
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1555 18c9b560 balrog
            break;
1556 18c9b560 balrog
        case 2:
1557 18c9b560 balrog
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1558 18c9b560 balrog
            break;
1559 18c9b560 balrog
        case 3:
1560 18c9b560 balrog
            return 1;
1561 18c9b560 balrog
        }
1562 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1563 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1564 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1565 18c9b560 balrog
        break;
1566 18c9b560 balrog
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1567 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1568 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1569 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1570 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1571 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1572 18c9b560 balrog
        case 0:
1573 18c9b560 balrog
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1574 18c9b560 balrog
            break;
1575 18c9b560 balrog
        case 1:
1576 18c9b560 balrog
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1577 18c9b560 balrog
            break;
1578 18c9b560 balrog
        case 2:
1579 18c9b560 balrog
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1580 18c9b560 balrog
            break;
1581 18c9b560 balrog
        case 3:
1582 18c9b560 balrog
            return 1;
1583 18c9b560 balrog
        }
1584 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1585 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1586 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1587 18c9b560 balrog
        break;
1588 18c9b560 balrog
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1589 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1590 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1591 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1592 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1593 18c9b560 balrog
        if (insn & (1 << 22))
1594 18c9b560 balrog
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1595 18c9b560 balrog
        else
1596 18c9b560 balrog
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1597 18c9b560 balrog
        if (!(insn & (1 << 20)))
1598 18c9b560 balrog
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1599 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1600 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1601 18c9b560 balrog
        break;
1602 18c9b560 balrog
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1603 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1604 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1605 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1606 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1607 e677137d pbrook
        if (insn & (1 << 21)) {
1608 e677137d pbrook
            if (insn & (1 << 20))
1609 e677137d pbrook
                gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1610 e677137d pbrook
            else
1611 e677137d pbrook
                gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1612 e677137d pbrook
        } else {
1613 e677137d pbrook
            if (insn & (1 << 20))
1614 e677137d pbrook
                gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1615 e677137d pbrook
            else
1616 e677137d pbrook
                gen_op_iwmmxt_mululw_M0_wRn(rd1);
1617 e677137d pbrook
        }
1618 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1619 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1620 18c9b560 balrog
        break;
1621 18c9b560 balrog
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1622 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1623 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1624 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1625 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1626 18c9b560 balrog
        if (insn & (1 << 21))
1627 18c9b560 balrog
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1628 18c9b560 balrog
        else
1629 18c9b560 balrog
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1630 18c9b560 balrog
        if (!(insn & (1 << 20))) {
1631 e677137d pbrook
            iwmmxt_load_reg(cpu_V1, wrd);
1632 e677137d pbrook
            tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1633 18c9b560 balrog
        }
1634 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1635 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1636 18c9b560 balrog
        break;
1637 18c9b560 balrog
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1638 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1639 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1640 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1641 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1642 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1643 18c9b560 balrog
        case 0:
1644 18c9b560 balrog
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1645 18c9b560 balrog
            break;
1646 18c9b560 balrog
        case 1:
1647 18c9b560 balrog
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1648 18c9b560 balrog
            break;
1649 18c9b560 balrog
        case 2:
1650 18c9b560 balrog
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1651 18c9b560 balrog
            break;
1652 18c9b560 balrog
        case 3:
1653 18c9b560 balrog
            return 1;
1654 18c9b560 balrog
        }
1655 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1656 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1657 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1658 18c9b560 balrog
        break;
1659 18c9b560 balrog
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1660 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1661 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1662 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1663 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1664 e677137d pbrook
        if (insn & (1 << 22)) {
1665 e677137d pbrook
            if (insn & (1 << 20))
1666 e677137d pbrook
                gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1667 e677137d pbrook
            else
1668 e677137d pbrook
                gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1669 e677137d pbrook
        } else {
1670 e677137d pbrook
            if (insn & (1 << 20))
1671 e677137d pbrook
                gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1672 e677137d pbrook
            else
1673 e677137d pbrook
                gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1674 e677137d pbrook
        }
1675 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1676 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1677 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1678 18c9b560 balrog
        break;
1679 18c9b560 balrog
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1680 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1681 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1682 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1683 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1684 da6b5335 Filip Navara
        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1685 da6b5335 Filip Navara
        tcg_gen_andi_i32(tmp, tmp, 7);
1686 da6b5335 Filip Navara
        iwmmxt_load_reg(cpu_V1, rd1);
1687 da6b5335 Filip Navara
        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1688 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1689 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1690 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1691 18c9b560 balrog
        break;
1692 18c9b560 balrog
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1693 da6b5335 Filip Navara
        if (((insn >> 6) & 3) == 3)
1694 da6b5335 Filip Navara
            return 1;
1695 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1696 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1697 da6b5335 Filip Navara
        tmp = load_reg(s, rd);
1698 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1699 18c9b560 balrog
        switch ((insn >> 6) & 3) {
1700 18c9b560 balrog
        case 0:
1701 da6b5335 Filip Navara
            tmp2 = tcg_const_i32(0xff);
1702 da6b5335 Filip Navara
            tmp3 = tcg_const_i32((insn & 7) << 3);
1703 18c9b560 balrog
            break;
1704 18c9b560 balrog
        case 1:
1705 da6b5335 Filip Navara
            tmp2 = tcg_const_i32(0xffff);
1706 da6b5335 Filip Navara
            tmp3 = tcg_const_i32((insn & 3) << 4);
1707 18c9b560 balrog
            break;
1708 18c9b560 balrog
        case 2:
1709 da6b5335 Filip Navara
            tmp2 = tcg_const_i32(0xffffffff);
1710 da6b5335 Filip Navara
            tmp3 = tcg_const_i32((insn & 1) << 5);
1711 18c9b560 balrog
            break;
1712 da6b5335 Filip Navara
        default:
1713 da6b5335 Filip Navara
            TCGV_UNUSED(tmp2);
1714 da6b5335 Filip Navara
            TCGV_UNUSED(tmp3);
1715 18c9b560 balrog
        }
1716 da6b5335 Filip Navara
        gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1717 da6b5335 Filip Navara
        tcg_temp_free(tmp3);
1718 da6b5335 Filip Navara
        tcg_temp_free(tmp2);
1719 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1720 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1721 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1722 18c9b560 balrog
        break;
1723 18c9b560 balrog
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1724 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1725 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1726 da6b5335 Filip Navara
        if (rd == 15 || ((insn >> 22) & 3) == 3)
1727 18c9b560 balrog
            return 1;
1728 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1729 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
1730 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1731 18c9b560 balrog
        case 0:
1732 da6b5335 Filip Navara
            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1733 da6b5335 Filip Navara
            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1734 da6b5335 Filip Navara
            if (insn & 8) {
1735 da6b5335 Filip Navara
                tcg_gen_ext8s_i32(tmp, tmp);
1736 da6b5335 Filip Navara
            } else {
1737 da6b5335 Filip Navara
                tcg_gen_andi_i32(tmp, tmp, 0xff);
1738 18c9b560 balrog
            }
1739 18c9b560 balrog
            break;
1740 18c9b560 balrog
        case 1:
1741 da6b5335 Filip Navara
            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1742 da6b5335 Filip Navara
            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1743 da6b5335 Filip Navara
            if (insn & 8) {
1744 da6b5335 Filip Navara
                tcg_gen_ext16s_i32(tmp, tmp);
1745 da6b5335 Filip Navara
            } else {
1746 da6b5335 Filip Navara
                tcg_gen_andi_i32(tmp, tmp, 0xffff);
1747 18c9b560 balrog
            }
1748 18c9b560 balrog
            break;
1749 18c9b560 balrog
        case 2:
1750 da6b5335 Filip Navara
            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1751 da6b5335 Filip Navara
            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1752 18c9b560 balrog
            break;
1753 18c9b560 balrog
        }
1754 da6b5335 Filip Navara
        store_reg(s, rd, tmp);
1755 18c9b560 balrog
        break;
1756 18c9b560 balrog
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1757 da6b5335 Filip Navara
        if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1758 18c9b560 balrog
            return 1;
1759 da6b5335 Filip Navara
        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1760 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1761 18c9b560 balrog
        case 0:
1762 da6b5335 Filip Navara
            tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1763 18c9b560 balrog
            break;
1764 18c9b560 balrog
        case 1:
1765 da6b5335 Filip Navara
            tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1766 18c9b560 balrog
            break;
1767 18c9b560 balrog
        case 2:
1768 da6b5335 Filip Navara
            tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1769 18c9b560 balrog
            break;
1770 18c9b560 balrog
        }
1771 da6b5335 Filip Navara
        tcg_gen_shli_i32(tmp, tmp, 28);
1772 da6b5335 Filip Navara
        gen_set_nzcv(tmp);
1773 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1774 18c9b560 balrog
        break;
1775 18c9b560 balrog
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1776 da6b5335 Filip Navara
        if (((insn >> 6) & 3) == 3)
1777 da6b5335 Filip Navara
            return 1;
1778 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1779 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1780 da6b5335 Filip Navara
        tmp = load_reg(s, rd);
1781 18c9b560 balrog
        switch ((insn >> 6) & 3) {
1782 18c9b560 balrog
        case 0:
1783 da6b5335 Filip Navara
            gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1784 18c9b560 balrog
            break;
1785 18c9b560 balrog
        case 1:
1786 da6b5335 Filip Navara
            gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1787 18c9b560 balrog
            break;
1788 18c9b560 balrog
        case 2:
1789 da6b5335 Filip Navara
            gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1790 18c9b560 balrog
            break;
1791 18c9b560 balrog
        }
1792 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1793 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1794 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1795 18c9b560 balrog
        break;
1796 18c9b560 balrog
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1797 da6b5335 Filip Navara
        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1798 18c9b560 balrog
            return 1;
1799 da6b5335 Filip Navara
        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1800 7d1b0095 Peter Maydell
        tmp2 = tcg_temp_new_i32();
1801 da6b5335 Filip Navara
        tcg_gen_mov_i32(tmp2, tmp);
1802 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1803 18c9b560 balrog
        case 0:
1804 18c9b560 balrog
            for (i = 0; i < 7; i ++) {
1805 da6b5335 Filip Navara
                tcg_gen_shli_i32(tmp2, tmp2, 4);
1806 da6b5335 Filip Navara
                tcg_gen_and_i32(tmp, tmp, tmp2);
1807 18c9b560 balrog
            }
1808 18c9b560 balrog
            break;
1809 18c9b560 balrog
        case 1:
1810 18c9b560 balrog
            for (i = 0; i < 3; i ++) {
1811 da6b5335 Filip Navara
                tcg_gen_shli_i32(tmp2, tmp2, 8);
1812 da6b5335 Filip Navara
                tcg_gen_and_i32(tmp, tmp, tmp2);
1813 18c9b560 balrog
            }
1814 18c9b560 balrog
            break;
1815 18c9b560 balrog
        case 2:
1816 da6b5335 Filip Navara
            tcg_gen_shli_i32(tmp2, tmp2, 16);
1817 da6b5335 Filip Navara
            tcg_gen_and_i32(tmp, tmp, tmp2);
1818 18c9b560 balrog
            break;
1819 18c9b560 balrog
        }
1820 da6b5335 Filip Navara
        gen_set_nzcv(tmp);
1821 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
1822 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1823 18c9b560 balrog
        break;
1824 18c9b560 balrog
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1825 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1826 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1827 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1828 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1829 18c9b560 balrog
        case 0:
1830 e677137d pbrook
            gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1831 18c9b560 balrog
            break;
1832 18c9b560 balrog
        case 1:
1833 e677137d pbrook
            gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1834 18c9b560 balrog
            break;
1835 18c9b560 balrog
        case 2:
1836 e677137d pbrook
            gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1837 18c9b560 balrog
            break;
1838 18c9b560 balrog
        case 3:
1839 18c9b560 balrog
            return 1;
1840 18c9b560 balrog
        }
1841 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1842 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1843 18c9b560 balrog
        break;
1844 18c9b560 balrog
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1845 da6b5335 Filip Navara
        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1846 18c9b560 balrog
            return 1;
1847 da6b5335 Filip Navara
        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1848 7d1b0095 Peter Maydell
        tmp2 = tcg_temp_new_i32();
1849 da6b5335 Filip Navara
        tcg_gen_mov_i32(tmp2, tmp);
1850 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1851 18c9b560 balrog
        case 0:
1852 18c9b560 balrog
            for (i = 0; i < 7; i ++) {
1853 da6b5335 Filip Navara
                tcg_gen_shli_i32(tmp2, tmp2, 4);
1854 da6b5335 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
1855 18c9b560 balrog
            }
1856 18c9b560 balrog
            break;
1857 18c9b560 balrog
        case 1:
1858 18c9b560 balrog
            for (i = 0; i < 3; i ++) {
1859 da6b5335 Filip Navara
                tcg_gen_shli_i32(tmp2, tmp2, 8);
1860 da6b5335 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
1861 18c9b560 balrog
            }
1862 18c9b560 balrog
            break;
1863 18c9b560 balrog
        case 2:
1864 da6b5335 Filip Navara
            tcg_gen_shli_i32(tmp2, tmp2, 16);
1865 da6b5335 Filip Navara
            tcg_gen_or_i32(tmp, tmp, tmp2);
1866 18c9b560 balrog
            break;
1867 18c9b560 balrog
        }
1868 da6b5335 Filip Navara
        gen_set_nzcv(tmp);
1869 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
1870 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
1871 18c9b560 balrog
        break;
1872 18c9b560 balrog
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1873 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1874 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1875 da6b5335 Filip Navara
        if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1876 18c9b560 balrog
            return 1;
1877 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1878 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
1879 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1880 18c9b560 balrog
        case 0:
1881 da6b5335 Filip Navara
            gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1882 18c9b560 balrog
            break;
1883 18c9b560 balrog
        case 1:
1884 da6b5335 Filip Navara
            gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1885 18c9b560 balrog
            break;
1886 18c9b560 balrog
        case 2:
1887 da6b5335 Filip Navara
            gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1888 18c9b560 balrog
            break;
1889 18c9b560 balrog
        }
1890 da6b5335 Filip Navara
        store_reg(s, rd, tmp);
1891 18c9b560 balrog
        break;
1892 18c9b560 balrog
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1893 18c9b560 balrog
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1894 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1895 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1896 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1897 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1898 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1899 18c9b560 balrog
        case 0:
1900 18c9b560 balrog
            if (insn & (1 << 21))
1901 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1902 18c9b560 balrog
            else
1903 18c9b560 balrog
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1904 18c9b560 balrog
            break;
1905 18c9b560 balrog
        case 1:
1906 18c9b560 balrog
            if (insn & (1 << 21))
1907 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1908 18c9b560 balrog
            else
1909 18c9b560 balrog
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1910 18c9b560 balrog
            break;
1911 18c9b560 balrog
        case 2:
1912 18c9b560 balrog
            if (insn & (1 << 21))
1913 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1914 18c9b560 balrog
            else
1915 18c9b560 balrog
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1916 18c9b560 balrog
            break;
1917 18c9b560 balrog
        case 3:
1918 18c9b560 balrog
            return 1;
1919 18c9b560 balrog
        }
1920 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1921 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1922 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1923 18c9b560 balrog
        break;
1924 18c9b560 balrog
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1925 18c9b560 balrog
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1926 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1927 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1928 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1929 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1930 18c9b560 balrog
        case 0:
1931 18c9b560 balrog
            if (insn & (1 << 21))
1932 18c9b560 balrog
                gen_op_iwmmxt_unpacklsb_M0();
1933 18c9b560 balrog
            else
1934 18c9b560 balrog
                gen_op_iwmmxt_unpacklub_M0();
1935 18c9b560 balrog
            break;
1936 18c9b560 balrog
        case 1:
1937 18c9b560 balrog
            if (insn & (1 << 21))
1938 18c9b560 balrog
                gen_op_iwmmxt_unpacklsw_M0();
1939 18c9b560 balrog
            else
1940 18c9b560 balrog
                gen_op_iwmmxt_unpackluw_M0();
1941 18c9b560 balrog
            break;
1942 18c9b560 balrog
        case 2:
1943 18c9b560 balrog
            if (insn & (1 << 21))
1944 18c9b560 balrog
                gen_op_iwmmxt_unpacklsl_M0();
1945 18c9b560 balrog
            else
1946 18c9b560 balrog
                gen_op_iwmmxt_unpacklul_M0();
1947 18c9b560 balrog
            break;
1948 18c9b560 balrog
        case 3:
1949 18c9b560 balrog
            return 1;
1950 18c9b560 balrog
        }
1951 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1952 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1953 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1954 18c9b560 balrog
        break;
1955 18c9b560 balrog
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1956 18c9b560 balrog
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1957 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1958 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1959 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1960 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1961 18c9b560 balrog
        case 0:
1962 18c9b560 balrog
            if (insn & (1 << 21))
1963 18c9b560 balrog
                gen_op_iwmmxt_unpackhsb_M0();
1964 18c9b560 balrog
            else
1965 18c9b560 balrog
                gen_op_iwmmxt_unpackhub_M0();
1966 18c9b560 balrog
            break;
1967 18c9b560 balrog
        case 1:
1968 18c9b560 balrog
            if (insn & (1 << 21))
1969 18c9b560 balrog
                gen_op_iwmmxt_unpackhsw_M0();
1970 18c9b560 balrog
            else
1971 18c9b560 balrog
                gen_op_iwmmxt_unpackhuw_M0();
1972 18c9b560 balrog
            break;
1973 18c9b560 balrog
        case 2:
1974 18c9b560 balrog
            if (insn & (1 << 21))
1975 18c9b560 balrog
                gen_op_iwmmxt_unpackhsl_M0();
1976 18c9b560 balrog
            else
1977 18c9b560 balrog
                gen_op_iwmmxt_unpackhul_M0();
1978 18c9b560 balrog
            break;
1979 18c9b560 balrog
        case 3:
1980 18c9b560 balrog
            return 1;
1981 18c9b560 balrog
        }
1982 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1983 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1984 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1985 18c9b560 balrog
        break;
1986 18c9b560 balrog
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1987 18c9b560 balrog
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1988 da6b5335 Filip Navara
        if (((insn >> 22) & 3) == 0)
1989 da6b5335 Filip Navara
            return 1;
1990 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1991 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1992 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1993 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
1994 da6b5335 Filip Navara
        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1995 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
1996 18c9b560 balrog
            return 1;
1997 da6b5335 Filip Navara
        }
1998 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1999 18c9b560 balrog
        case 1:
2000 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp);
2001 18c9b560 balrog
            break;
2002 18c9b560 balrog
        case 2:
2003 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp);
2004 18c9b560 balrog
            break;
2005 18c9b560 balrog
        case 3:
2006 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp);
2007 18c9b560 balrog
            break;
2008 18c9b560 balrog
        }
2009 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2010 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2011 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2012 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2013 18c9b560 balrog
        break;
2014 18c9b560 balrog
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
2015 18c9b560 balrog
    case 0x014: case 0x414: case 0x814: case 0xc14:
2016 da6b5335 Filip Navara
        if (((insn >> 22) & 3) == 0)
2017 da6b5335 Filip Navara
            return 1;
2018 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2019 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2020 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2021 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
2022 da6b5335 Filip Navara
        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2023 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
2024 18c9b560 balrog
            return 1;
2025 da6b5335 Filip Navara
        }
2026 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2027 18c9b560 balrog
        case 1:
2028 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp);
2029 18c9b560 balrog
            break;
2030 18c9b560 balrog
        case 2:
2031 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp);
2032 18c9b560 balrog
            break;
2033 18c9b560 balrog
        case 3:
2034 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp);
2035 18c9b560 balrog
            break;
2036 18c9b560 balrog
        }
2037 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2038 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2039 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2040 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2041 18c9b560 balrog
        break;
2042 18c9b560 balrog
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
2043 18c9b560 balrog
    case 0x114: case 0x514: case 0x914: case 0xd14:
2044 da6b5335 Filip Navara
        if (((insn >> 22) & 3) == 0)
2045 da6b5335 Filip Navara
            return 1;
2046 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2047 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2048 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2049 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
2050 da6b5335 Filip Navara
        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2051 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
2052 18c9b560 balrog
            return 1;
2053 da6b5335 Filip Navara
        }
2054 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2055 18c9b560 balrog
        case 1:
2056 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp);
2057 18c9b560 balrog
            break;
2058 18c9b560 balrog
        case 2:
2059 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp);
2060 18c9b560 balrog
            break;
2061 18c9b560 balrog
        case 3:
2062 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp);
2063 18c9b560 balrog
            break;
2064 18c9b560 balrog
        }
2065 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2066 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2067 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2068 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2069 18c9b560 balrog
        break;
2070 18c9b560 balrog
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
2071 18c9b560 balrog
    case 0x314: case 0x714: case 0xb14: case 0xf14:
2072 da6b5335 Filip Navara
        if (((insn >> 22) & 3) == 0)
2073 da6b5335 Filip Navara
            return 1;
2074 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2075 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2076 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2077 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
2078 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2079 18c9b560 balrog
        case 1:
2080 da6b5335 Filip Navara
            if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2081 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
2082 18c9b560 balrog
                return 1;
2083 da6b5335 Filip Navara
            }
2084 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp);
2085 18c9b560 balrog
            break;
2086 18c9b560 balrog
        case 2:
2087 da6b5335 Filip Navara
            if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2088 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
2089 18c9b560 balrog
                return 1;
2090 da6b5335 Filip Navara
            }
2091 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp);
2092 18c9b560 balrog
            break;
2093 18c9b560 balrog
        case 3:
2094 da6b5335 Filip Navara
            if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2095 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
2096 18c9b560 balrog
                return 1;
2097 da6b5335 Filip Navara
            }
2098 947a2fa2 Peter Maydell
            gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp);
2099 18c9b560 balrog
            break;
2100 18c9b560 balrog
        }
2101 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2102 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2103 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2104 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2105 18c9b560 balrog
        break;
2106 18c9b560 balrog
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
2107 18c9b560 balrog
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
2108 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2109 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2110 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2111 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2112 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2113 18c9b560 balrog
        case 0:
2114 18c9b560 balrog
            if (insn & (1 << 21))
2115 18c9b560 balrog
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
2116 18c9b560 balrog
            else
2117 18c9b560 balrog
                gen_op_iwmmxt_minub_M0_wRn(rd1);
2118 18c9b560 balrog
            break;
2119 18c9b560 balrog
        case 1:
2120 18c9b560 balrog
            if (insn & (1 << 21))
2121 18c9b560 balrog
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
2122 18c9b560 balrog
            else
2123 18c9b560 balrog
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
2124 18c9b560 balrog
            break;
2125 18c9b560 balrog
        case 2:
2126 18c9b560 balrog
            if (insn & (1 << 21))
2127 18c9b560 balrog
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
2128 18c9b560 balrog
            else
2129 18c9b560 balrog
                gen_op_iwmmxt_minul_M0_wRn(rd1);
2130 18c9b560 balrog
            break;
2131 18c9b560 balrog
        case 3:
2132 18c9b560 balrog
            return 1;
2133 18c9b560 balrog
        }
2134 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2135 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2136 18c9b560 balrog
        break;
2137 18c9b560 balrog
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
2138 18c9b560 balrog
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
2139 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2140 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2141 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2142 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2143 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2144 18c9b560 balrog
        case 0:
2145 18c9b560 balrog
            if (insn & (1 << 21))
2146 18c9b560 balrog
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2147 18c9b560 balrog
            else
2148 18c9b560 balrog
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
2149 18c9b560 balrog
            break;
2150 18c9b560 balrog
        case 1:
2151 18c9b560 balrog
            if (insn & (1 << 21))
2152 18c9b560 balrog
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2153 18c9b560 balrog
            else
2154 18c9b560 balrog
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2155 18c9b560 balrog
            break;
2156 18c9b560 balrog
        case 2:
2157 18c9b560 balrog
            if (insn & (1 << 21))
2158 18c9b560 balrog
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2159 18c9b560 balrog
            else
2160 18c9b560 balrog
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
2161 18c9b560 balrog
            break;
2162 18c9b560 balrog
        case 3:
2163 18c9b560 balrog
            return 1;
2164 18c9b560 balrog
        }
2165 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2166 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2167 18c9b560 balrog
        break;
2168 18c9b560 balrog
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
2169 18c9b560 balrog
    case 0x402: case 0x502: case 0x602: case 0x702:
2170 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2171 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2172 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2173 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2174 da6b5335 Filip Navara
        tmp = tcg_const_i32((insn >> 20) & 3);
2175 da6b5335 Filip Navara
        iwmmxt_load_reg(cpu_V1, rd1);
2176 da6b5335 Filip Navara
        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2177 da6b5335 Filip Navara
        tcg_temp_free(tmp);
2178 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2179 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2180 18c9b560 balrog
        break;
2181 18c9b560 balrog
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
2182 18c9b560 balrog
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2183 18c9b560 balrog
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2184 18c9b560 balrog
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2185 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2186 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2187 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2188 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2189 18c9b560 balrog
        switch ((insn >> 20) & 0xf) {
2190 18c9b560 balrog
        case 0x0:
2191 18c9b560 balrog
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
2192 18c9b560 balrog
            break;
2193 18c9b560 balrog
        case 0x1:
2194 18c9b560 balrog
            gen_op_iwmmxt_subub_M0_wRn(rd1);
2195 18c9b560 balrog
            break;
2196 18c9b560 balrog
        case 0x3:
2197 18c9b560 balrog
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
2198 18c9b560 balrog
            break;
2199 18c9b560 balrog
        case 0x4:
2200 18c9b560 balrog
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
2201 18c9b560 balrog
            break;
2202 18c9b560 balrog
        case 0x5:
2203 18c9b560 balrog
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
2204 18c9b560 balrog
            break;
2205 18c9b560 balrog
        case 0x7:
2206 18c9b560 balrog
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
2207 18c9b560 balrog
            break;
2208 18c9b560 balrog
        case 0x8:
2209 18c9b560 balrog
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
2210 18c9b560 balrog
            break;
2211 18c9b560 balrog
        case 0x9:
2212 18c9b560 balrog
            gen_op_iwmmxt_subul_M0_wRn(rd1);
2213 18c9b560 balrog
            break;
2214 18c9b560 balrog
        case 0xb:
2215 18c9b560 balrog
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
2216 18c9b560 balrog
            break;
2217 18c9b560 balrog
        default:
2218 18c9b560 balrog
            return 1;
2219 18c9b560 balrog
        }
2220 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2221 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2222 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2223 18c9b560 balrog
        break;
2224 18c9b560 balrog
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
2225 18c9b560 balrog
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2226 18c9b560 balrog
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2227 18c9b560 balrog
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2228 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2229 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2230 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2231 da6b5335 Filip Navara
        tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2232 947a2fa2 Peter Maydell
        gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp);
2233 da6b5335 Filip Navara
        tcg_temp_free(tmp);
2234 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2235 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2236 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2237 18c9b560 balrog
        break;
2238 18c9b560 balrog
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
2239 18c9b560 balrog
    case 0x418: case 0x518: case 0x618: case 0x718:
2240 18c9b560 balrog
    case 0x818: case 0x918: case 0xa18: case 0xb18:
2241 18c9b560 balrog
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2242 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2243 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2244 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2245 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2246 18c9b560 balrog
        switch ((insn >> 20) & 0xf) {
2247 18c9b560 balrog
        case 0x0:
2248 18c9b560 balrog
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
2249 18c9b560 balrog
            break;
2250 18c9b560 balrog
        case 0x1:
2251 18c9b560 balrog
            gen_op_iwmmxt_addub_M0_wRn(rd1);
2252 18c9b560 balrog
            break;
2253 18c9b560 balrog
        case 0x3:
2254 18c9b560 balrog
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
2255 18c9b560 balrog
            break;
2256 18c9b560 balrog
        case 0x4:
2257 18c9b560 balrog
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
2258 18c9b560 balrog
            break;
2259 18c9b560 balrog
        case 0x5:
2260 18c9b560 balrog
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
2261 18c9b560 balrog
            break;
2262 18c9b560 balrog
        case 0x7:
2263 18c9b560 balrog
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
2264 18c9b560 balrog
            break;
2265 18c9b560 balrog
        case 0x8:
2266 18c9b560 balrog
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
2267 18c9b560 balrog
            break;
2268 18c9b560 balrog
        case 0x9:
2269 18c9b560 balrog
            gen_op_iwmmxt_addul_M0_wRn(rd1);
2270 18c9b560 balrog
            break;
2271 18c9b560 balrog
        case 0xb:
2272 18c9b560 balrog
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
2273 18c9b560 balrog
            break;
2274 18c9b560 balrog
        default:
2275 18c9b560 balrog
            return 1;
2276 18c9b560 balrog
        }
2277 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2278 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2279 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2280 18c9b560 balrog
        break;
2281 18c9b560 balrog
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
2282 18c9b560 balrog
    case 0x408: case 0x508: case 0x608: case 0x708:
2283 18c9b560 balrog
    case 0x808: case 0x908: case 0xa08: case 0xb08:
2284 18c9b560 balrog
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2285 da6b5335 Filip Navara
        if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2286 da6b5335 Filip Navara
            return 1;
2287 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2288 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2289 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2290 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2291 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2292 18c9b560 balrog
        case 1:
2293 18c9b560 balrog
            if (insn & (1 << 21))
2294 18c9b560 balrog
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
2295 18c9b560 balrog
            else
2296 18c9b560 balrog
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
2297 18c9b560 balrog
            break;
2298 18c9b560 balrog
        case 2:
2299 18c9b560 balrog
            if (insn & (1 << 21))
2300 18c9b560 balrog
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
2301 18c9b560 balrog
            else
2302 18c9b560 balrog
                gen_op_iwmmxt_packul_M0_wRn(rd1);
2303 18c9b560 balrog
            break;
2304 18c9b560 balrog
        case 3:
2305 18c9b560 balrog
            if (insn & (1 << 21))
2306 18c9b560 balrog
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
2307 18c9b560 balrog
            else
2308 18c9b560 balrog
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
2309 18c9b560 balrog
            break;
2310 18c9b560 balrog
        }
2311 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2312 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2313 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2314 18c9b560 balrog
        break;
2315 18c9b560 balrog
    case 0x201: case 0x203: case 0x205: case 0x207:
2316 18c9b560 balrog
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
2317 18c9b560 balrog
    case 0x211: case 0x213: case 0x215: case 0x217:
2318 18c9b560 balrog
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
2319 18c9b560 balrog
        wrd = (insn >> 5) & 0xf;
2320 18c9b560 balrog
        rd0 = (insn >> 12) & 0xf;
2321 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2322 18c9b560 balrog
        if (rd0 == 0xf || rd1 == 0xf)
2323 18c9b560 balrog
            return 1;
2324 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
2325 da6b5335 Filip Navara
        tmp = load_reg(s, rd0);
2326 da6b5335 Filip Navara
        tmp2 = load_reg(s, rd1);
2327 18c9b560 balrog
        switch ((insn >> 16) & 0xf) {
2328 18c9b560 balrog
        case 0x0:                                        /* TMIA */
2329 da6b5335 Filip Navara
            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2330 18c9b560 balrog
            break;
2331 18c9b560 balrog
        case 0x8:                                        /* TMIAPH */
2332 da6b5335 Filip Navara
            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2333 18c9b560 balrog
            break;
2334 18c9b560 balrog
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2335 18c9b560 balrog
            if (insn & (1 << 16))
2336 da6b5335 Filip Navara
                tcg_gen_shri_i32(tmp, tmp, 16);
2337 18c9b560 balrog
            if (insn & (1 << 17))
2338 da6b5335 Filip Navara
                tcg_gen_shri_i32(tmp2, tmp2, 16);
2339 da6b5335 Filip Navara
            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2340 18c9b560 balrog
            break;
2341 18c9b560 balrog
        default:
2342 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
2343 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
2344 18c9b560 balrog
            return 1;
2345 18c9b560 balrog
        }
2346 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
2347 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2348 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2349 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2350 18c9b560 balrog
        break;
2351 18c9b560 balrog
    default:
2352 18c9b560 balrog
        return 1;
2353 18c9b560 balrog
    }
2354 18c9b560 balrog
2355 18c9b560 balrog
    return 0;
2356 18c9b560 balrog
}
2357 18c9b560 balrog
2358 a1c7273b Stefan Weil
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occurred
2359 18c9b560 balrog
   (ie. an undefined instruction).  */
2360 18c9b560 balrog
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2361 18c9b560 balrog
{
2362 18c9b560 balrog
    int acc, rd0, rd1, rdhi, rdlo;
2363 3a554c0f Filip Navara
    TCGv tmp, tmp2;
2364 18c9b560 balrog
2365 18c9b560 balrog
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2366 18c9b560 balrog
        /* Multiply with Internal Accumulate Format */
2367 18c9b560 balrog
        rd0 = (insn >> 12) & 0xf;
2368 18c9b560 balrog
        rd1 = insn & 0xf;
2369 18c9b560 balrog
        acc = (insn >> 5) & 7;
2370 18c9b560 balrog
2371 18c9b560 balrog
        if (acc != 0)
2372 18c9b560 balrog
            return 1;
2373 18c9b560 balrog
2374 3a554c0f Filip Navara
        tmp = load_reg(s, rd0);
2375 3a554c0f Filip Navara
        tmp2 = load_reg(s, rd1);
2376 18c9b560 balrog
        switch ((insn >> 16) & 0xf) {
2377 18c9b560 balrog
        case 0x0:                                        /* MIA */
2378 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2379 18c9b560 balrog
            break;
2380 18c9b560 balrog
        case 0x8:                                        /* MIAPH */
2381 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2382 18c9b560 balrog
            break;
2383 18c9b560 balrog
        case 0xc:                                        /* MIABB */
2384 18c9b560 balrog
        case 0xd:                                        /* MIABT */
2385 18c9b560 balrog
        case 0xe:                                        /* MIATB */
2386 18c9b560 balrog
        case 0xf:                                        /* MIATT */
2387 18c9b560 balrog
            if (insn & (1 << 16))
2388 3a554c0f Filip Navara
                tcg_gen_shri_i32(tmp, tmp, 16);
2389 18c9b560 balrog
            if (insn & (1 << 17))
2390 3a554c0f Filip Navara
                tcg_gen_shri_i32(tmp2, tmp2, 16);
2391 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2392 18c9b560 balrog
            break;
2393 18c9b560 balrog
        default:
2394 18c9b560 balrog
            return 1;
2395 18c9b560 balrog
        }
2396 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
2397 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2398 18c9b560 balrog
2399 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(acc);
2400 18c9b560 balrog
        return 0;
2401 18c9b560 balrog
    }
2402 18c9b560 balrog
2403 18c9b560 balrog
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2404 18c9b560 balrog
        /* Internal Accumulator Access Format */
2405 18c9b560 balrog
        rdhi = (insn >> 16) & 0xf;
2406 18c9b560 balrog
        rdlo = (insn >> 12) & 0xf;
2407 18c9b560 balrog
        acc = insn & 7;
2408 18c9b560 balrog
2409 18c9b560 balrog
        if (acc != 0)
2410 18c9b560 balrog
            return 1;
2411 18c9b560 balrog
2412 18c9b560 balrog
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2413 3a554c0f Filip Navara
            iwmmxt_load_reg(cpu_V0, acc);
2414 3a554c0f Filip Navara
            tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2415 3a554c0f Filip Navara
            tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2416 3a554c0f Filip Navara
            tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2417 3a554c0f Filip Navara
            tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2418 18c9b560 balrog
        } else {                                        /* MAR */
2419 3a554c0f Filip Navara
            tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2420 3a554c0f Filip Navara
            iwmmxt_store_reg(cpu_V0, acc);
2421 18c9b560 balrog
        }
2422 18c9b560 balrog
        return 0;
2423 18c9b560 balrog
    }
2424 18c9b560 balrog
2425 18c9b560 balrog
    return 1;
2426 18c9b560 balrog
}
2427 18c9b560 balrog
2428 c1713132 balrog
/* Disassemble system coprocessor instruction.  Return nonzero if
2429 c1713132 balrog
   instruction is not defined.  */
2430 c1713132 balrog
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2431 c1713132 balrog
{
2432 b75263d6 Juha Riihimäki
    TCGv tmp, tmp2;
2433 c1713132 balrog
    uint32_t rd = (insn >> 12) & 0xf;
2434 c1713132 balrog
    uint32_t cp = (insn >> 8) & 0xf;
2435 c1713132 balrog
    if (IS_USER(s)) {
2436 c1713132 balrog
        return 1;
2437 c1713132 balrog
    }
2438 c1713132 balrog
2439 18c9b560 balrog
    if (insn & ARM_CP_RW_BIT) {
2440 c1713132 balrog
        if (!env->cp[cp].cp_read)
2441 c1713132 balrog
            return 1;
2442 8984bd2e pbrook
        gen_set_pc_im(s->pc);
2443 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
2444 b75263d6 Juha Riihimäki
        tmp2 = tcg_const_i32(insn);
2445 b75263d6 Juha Riihimäki
        gen_helper_get_cp(tmp, cpu_env, tmp2);
2446 b75263d6 Juha Riihimäki
        tcg_temp_free(tmp2);
2447 8984bd2e pbrook
        store_reg(s, rd, tmp);
2448 c1713132 balrog
    } else {
2449 c1713132 balrog
        if (!env->cp[cp].cp_write)
2450 c1713132 balrog
            return 1;
2451 8984bd2e pbrook
        gen_set_pc_im(s->pc);
2452 8984bd2e pbrook
        tmp = load_reg(s, rd);
2453 b75263d6 Juha Riihimäki
        tmp2 = tcg_const_i32(insn);
2454 b75263d6 Juha Riihimäki
        gen_helper_set_cp(cpu_env, tmp2, tmp);
2455 b75263d6 Juha Riihimäki
        tcg_temp_free(tmp2);
2456 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2457 c1713132 balrog
    }
2458 c1713132 balrog
    return 0;
2459 c1713132 balrog
}
2460 c1713132 balrog
2461 9ee6e8bb pbrook
static int cp15_user_ok(uint32_t insn)
2462 9ee6e8bb pbrook
{
2463 9ee6e8bb pbrook
    int cpn = (insn >> 16) & 0xf;
2464 9ee6e8bb pbrook
    int cpm = insn & 0xf;
2465 9ee6e8bb pbrook
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2466 9ee6e8bb pbrook
2467 9ee6e8bb pbrook
    if (cpn == 13 && cpm == 0) {
2468 9ee6e8bb pbrook
        /* TLS register.  */
2469 9ee6e8bb pbrook
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2470 9ee6e8bb pbrook
            return 1;
2471 9ee6e8bb pbrook
    }
2472 9ee6e8bb pbrook
    if (cpn == 7) {
2473 9ee6e8bb pbrook
        /* ISB, DSB, DMB.  */
2474 9ee6e8bb pbrook
        if ((cpm == 5 && op == 4)
2475 9ee6e8bb pbrook
                || (cpm == 10 && (op == 4 || op == 5)))
2476 9ee6e8bb pbrook
            return 1;
2477 9ee6e8bb pbrook
    }
2478 9ee6e8bb pbrook
    return 0;
2479 9ee6e8bb pbrook
}
2480 9ee6e8bb pbrook
2481 3f26c122 Riku Voipio
static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2482 3f26c122 Riku Voipio
{
2483 3f26c122 Riku Voipio
    TCGv tmp;
2484 3f26c122 Riku Voipio
    int cpn = (insn >> 16) & 0xf;
2485 3f26c122 Riku Voipio
    int cpm = insn & 0xf;
2486 3f26c122 Riku Voipio
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2487 3f26c122 Riku Voipio
2488 3f26c122 Riku Voipio
    if (!arm_feature(env, ARM_FEATURE_V6K))
2489 3f26c122 Riku Voipio
        return 0;
2490 3f26c122 Riku Voipio
2491 3f26c122 Riku Voipio
    if (!(cpn == 13 && cpm == 0))
2492 3f26c122 Riku Voipio
        return 0;
2493 3f26c122 Riku Voipio
2494 3f26c122 Riku Voipio
    if (insn & ARM_CP_RW_BIT) {
2495 3f26c122 Riku Voipio
        switch (op) {
2496 3f26c122 Riku Voipio
        case 2:
2497 c5883be2 Paul Brook
            tmp = load_cpu_field(cp15.c13_tls1);
2498 3f26c122 Riku Voipio
            break;
2499 3f26c122 Riku Voipio
        case 3:
2500 c5883be2 Paul Brook
            tmp = load_cpu_field(cp15.c13_tls2);
2501 3f26c122 Riku Voipio
            break;
2502 3f26c122 Riku Voipio
        case 4:
2503 c5883be2 Paul Brook
            tmp = load_cpu_field(cp15.c13_tls3);
2504 3f26c122 Riku Voipio
            break;
2505 3f26c122 Riku Voipio
        default:
2506 3f26c122 Riku Voipio
            return 0;
2507 3f26c122 Riku Voipio
        }
2508 3f26c122 Riku Voipio
        store_reg(s, rd, tmp);
2509 3f26c122 Riku Voipio
2510 3f26c122 Riku Voipio
    } else {
2511 3f26c122 Riku Voipio
        tmp = load_reg(s, rd);
2512 3f26c122 Riku Voipio
        switch (op) {
2513 3f26c122 Riku Voipio
        case 2:
2514 c5883be2 Paul Brook
            store_cpu_field(tmp, cp15.c13_tls1);
2515 3f26c122 Riku Voipio
            break;
2516 3f26c122 Riku Voipio
        case 3:
2517 c5883be2 Paul Brook
            store_cpu_field(tmp, cp15.c13_tls2);
2518 3f26c122 Riku Voipio
            break;
2519 3f26c122 Riku Voipio
        case 4:
2520 c5883be2 Paul Brook
            store_cpu_field(tmp, cp15.c13_tls3);
2521 3f26c122 Riku Voipio
            break;
2522 3f26c122 Riku Voipio
        default:
2523 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
2524 3f26c122 Riku Voipio
            return 0;
2525 3f26c122 Riku Voipio
        }
2526 3f26c122 Riku Voipio
    }
2527 3f26c122 Riku Voipio
    return 1;
2528 3f26c122 Riku Voipio
}
2529 3f26c122 Riku Voipio
2530 b5ff1b31 bellard
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2531 b5ff1b31 bellard
   instruction is not defined.  */
2532 a90b7318 balrog
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2533 b5ff1b31 bellard
{
2534 b5ff1b31 bellard
    uint32_t rd;
2535 b75263d6 Juha Riihimäki
    TCGv tmp, tmp2;
2536 b5ff1b31 bellard
2537 9ee6e8bb pbrook
    /* M profile cores use memory mapped registers instead of cp15.  */
2538 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_M))
2539 9ee6e8bb pbrook
        return 1;
2540 9ee6e8bb pbrook
2541 9ee6e8bb pbrook
    if ((insn & (1 << 25)) == 0) {
2542 9ee6e8bb pbrook
        if (insn & (1 << 20)) {
2543 9ee6e8bb pbrook
            /* mrrc */
2544 9ee6e8bb pbrook
            return 1;
2545 9ee6e8bb pbrook
        }
2546 9ee6e8bb pbrook
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2547 9ee6e8bb pbrook
        return 0;
2548 9ee6e8bb pbrook
    }
2549 9ee6e8bb pbrook
    if ((insn & (1 << 4)) == 0) {
2550 9ee6e8bb pbrook
        /* cdp */
2551 9ee6e8bb pbrook
        return 1;
2552 9ee6e8bb pbrook
    }
2553 9ee6e8bb pbrook
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2554 b5ff1b31 bellard
        return 1;
2555 b5ff1b31 bellard
    }
2556 cc688901 Peter Maydell
2557 cc688901 Peter Maydell
    /* Pre-v7 versions of the architecture implemented WFI via coprocessor
2558 cc688901 Peter Maydell
     * instructions rather than a separate instruction.
2559 cc688901 Peter Maydell
     */
2560 cc688901 Peter Maydell
    if ((insn & 0x0fff0fff) == 0x0e070f90) {
2561 cc688901 Peter Maydell
        /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
2562 cc688901 Peter Maydell
         * In v7, this must NOP.
2563 cc688901 Peter Maydell
         */
2564 cc688901 Peter Maydell
        if (!arm_feature(env, ARM_FEATURE_V7)) {
2565 cc688901 Peter Maydell
            /* Wait for interrupt.  */
2566 cc688901 Peter Maydell
            gen_set_pc_im(s->pc);
2567 cc688901 Peter Maydell
            s->is_jmp = DISAS_WFI;
2568 cc688901 Peter Maydell
        }
2569 9332f9da bellard
        return 0;
2570 9332f9da bellard
    }
2571 cc688901 Peter Maydell
2572 cc688901 Peter Maydell
    if ((insn & 0x0fff0fff) == 0x0e070f58) {
2573 cc688901 Peter Maydell
        /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
2574 cc688901 Peter Maydell
         * so this is slightly over-broad.
2575 cc688901 Peter Maydell
         */
2576 cc688901 Peter Maydell
        if (!arm_feature(env, ARM_FEATURE_V6)) {
2577 cc688901 Peter Maydell
            /* Wait for interrupt.  */
2578 cc688901 Peter Maydell
            gen_set_pc_im(s->pc);
2579 cc688901 Peter Maydell
            s->is_jmp = DISAS_WFI;
2580 cc688901 Peter Maydell
            return 0;
2581 cc688901 Peter Maydell
        }
2582 cc688901 Peter Maydell
        /* Otherwise fall through to handle via helper function.
2583 cc688901 Peter Maydell
         * In particular, on v7 and some v6 cores this is one of
2584 cc688901 Peter Maydell
         * the VA-PA registers.
2585 cc688901 Peter Maydell
         */
2586 cc688901 Peter Maydell
    }
2587 cc688901 Peter Maydell
2588 b5ff1b31 bellard
    rd = (insn >> 12) & 0xf;
2589 3f26c122 Riku Voipio
2590 3f26c122 Riku Voipio
    if (cp15_tls_load_store(env, s, insn, rd))
2591 3f26c122 Riku Voipio
        return 0;
2592 3f26c122 Riku Voipio
2593 b75263d6 Juha Riihimäki
    tmp2 = tcg_const_i32(insn);
2594 18c9b560 balrog
    if (insn & ARM_CP_RW_BIT) {
2595 7d1b0095 Peter Maydell
        tmp = tcg_temp_new_i32();
2596 b75263d6 Juha Riihimäki
        gen_helper_get_cp15(tmp, cpu_env, tmp2);
2597 b5ff1b31 bellard
        /* If the destination register is r15 then sets condition codes.  */
2598 b5ff1b31 bellard
        if (rd != 15)
2599 8984bd2e pbrook
            store_reg(s, rd, tmp);
2600 8984bd2e pbrook
        else
2601 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
2602 b5ff1b31 bellard
    } else {
2603 8984bd2e pbrook
        tmp = load_reg(s, rd);
2604 b75263d6 Juha Riihimäki
        gen_helper_set_cp15(cpu_env, tmp2, tmp);
2605 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
2606 a90b7318 balrog
        /* Normally we would always end the TB here, but Linux
2607 a90b7318 balrog
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2608 a90b7318 balrog
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2609 a90b7318 balrog
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2610 a90b7318 balrog
                (insn & 0x0fff0fff) != 0x0e010f10)
2611 a90b7318 balrog
            gen_lookup_tb(s);
2612 b5ff1b31 bellard
    }
2613 b75263d6 Juha Riihimäki
    tcg_temp_free_i32(tmp2);
2614 b5ff1b31 bellard
    return 0;
2615 b5ff1b31 bellard
}
2616 b5ff1b31 bellard
2617 9ee6e8bb pbrook
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2618 9ee6e8bb pbrook
#define VFP_SREG(insn, bigbit, smallbit) \
2619 9ee6e8bb pbrook
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2620 9ee6e8bb pbrook
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2621 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2622 9ee6e8bb pbrook
        reg = (((insn) >> (bigbit)) & 0x0f) \
2623 9ee6e8bb pbrook
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2624 9ee6e8bb pbrook
    } else { \
2625 9ee6e8bb pbrook
        if (insn & (1 << (smallbit))) \
2626 9ee6e8bb pbrook
            return 1; \
2627 9ee6e8bb pbrook
        reg = ((insn) >> (bigbit)) & 0x0f; \
2628 9ee6e8bb pbrook
    }} while (0)
2629 9ee6e8bb pbrook
2630 9ee6e8bb pbrook
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2631 9ee6e8bb pbrook
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2632 9ee6e8bb pbrook
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2633 9ee6e8bb pbrook
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2634 9ee6e8bb pbrook
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2635 9ee6e8bb pbrook
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2636 9ee6e8bb pbrook
2637 4373f3ce pbrook
/* Move between integer and VFP cores.  */
2638 4373f3ce pbrook
static TCGv gen_vfp_mrs(void)
2639 4373f3ce pbrook
{
2640 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
2641 4373f3ce pbrook
    tcg_gen_mov_i32(tmp, cpu_F0s);
2642 4373f3ce pbrook
    return tmp;
2643 4373f3ce pbrook
}
2644 4373f3ce pbrook
2645 4373f3ce pbrook
static void gen_vfp_msr(TCGv tmp)
2646 4373f3ce pbrook
{
2647 4373f3ce pbrook
    tcg_gen_mov_i32(cpu_F0s, tmp);
2648 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
2649 4373f3ce pbrook
}
2650 4373f3ce pbrook
2651 ad69471c pbrook
static void gen_neon_dup_u8(TCGv var, int shift)
2652 ad69471c pbrook
{
2653 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
2654 ad69471c pbrook
    if (shift)
2655 ad69471c pbrook
        tcg_gen_shri_i32(var, var, shift);
2656 86831435 pbrook
    tcg_gen_ext8u_i32(var, var);
2657 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 8);
2658 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2659 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 16);
2660 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2661 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
2662 ad69471c pbrook
}
2663 ad69471c pbrook
2664 ad69471c pbrook
static void gen_neon_dup_low16(TCGv var)
2665 ad69471c pbrook
{
2666 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
2667 86831435 pbrook
    tcg_gen_ext16u_i32(var, var);
2668 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 16);
2669 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2670 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
2671 ad69471c pbrook
}
2672 ad69471c pbrook
2673 ad69471c pbrook
static void gen_neon_dup_high16(TCGv var)
2674 ad69471c pbrook
{
2675 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
2676 ad69471c pbrook
    tcg_gen_andi_i32(var, var, 0xffff0000);
2677 ad69471c pbrook
    tcg_gen_shri_i32(tmp, var, 16);
2678 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2679 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
2680 ad69471c pbrook
}
2681 ad69471c pbrook
2682 8e18cde3 Peter Maydell
static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2683 8e18cde3 Peter Maydell
{
2684 8e18cde3 Peter Maydell
    /* Load a single Neon element and replicate into a 32 bit TCG reg */
2685 8e18cde3 Peter Maydell
    TCGv tmp;
2686 8e18cde3 Peter Maydell
    switch (size) {
2687 8e18cde3 Peter Maydell
    case 0:
2688 8e18cde3 Peter Maydell
        tmp = gen_ld8u(addr, IS_USER(s));
2689 8e18cde3 Peter Maydell
        gen_neon_dup_u8(tmp, 0);
2690 8e18cde3 Peter Maydell
        break;
2691 8e18cde3 Peter Maydell
    case 1:
2692 8e18cde3 Peter Maydell
        tmp = gen_ld16u(addr, IS_USER(s));
2693 8e18cde3 Peter Maydell
        gen_neon_dup_low16(tmp);
2694 8e18cde3 Peter Maydell
        break;
2695 8e18cde3 Peter Maydell
    case 2:
2696 8e18cde3 Peter Maydell
        tmp = gen_ld32(addr, IS_USER(s));
2697 8e18cde3 Peter Maydell
        break;
2698 8e18cde3 Peter Maydell
    default: /* Avoid compiler warnings.  */
2699 8e18cde3 Peter Maydell
        abort();
2700 8e18cde3 Peter Maydell
    }
2701 8e18cde3 Peter Maydell
    return tmp;
2702 8e18cde3 Peter Maydell
}
2703 8e18cde3 Peter Maydell
2704 a1c7273b Stefan Weil
/* Disassemble a VFP instruction.  Returns nonzero if an error occurred
2705 b7bcbe95 bellard
   (ie. an undefined instruction).  */
2706 b7bcbe95 bellard
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2707 b7bcbe95 bellard
{
2708 b7bcbe95 bellard
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2709 b7bcbe95 bellard
    int dp, veclen;
2710 312eea9f Filip Navara
    TCGv addr;
2711 4373f3ce pbrook
    TCGv tmp;
2712 ad69471c pbrook
    TCGv tmp2;
2713 b7bcbe95 bellard
2714 40f137e1 pbrook
    if (!arm_feature(env, ARM_FEATURE_VFP))
2715 40f137e1 pbrook
        return 1;
2716 40f137e1 pbrook
2717 5df8bac1 Peter Maydell
    if (!s->vfp_enabled) {
2718 9ee6e8bb pbrook
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2719 40f137e1 pbrook
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2720 40f137e1 pbrook
            return 1;
2721 40f137e1 pbrook
        rn = (insn >> 16) & 0xf;
2722 9ee6e8bb pbrook
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2723 9ee6e8bb pbrook
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2724 40f137e1 pbrook
            return 1;
2725 40f137e1 pbrook
    }
2726 b7bcbe95 bellard
    dp = ((insn & 0xf00) == 0xb00);
2727 b7bcbe95 bellard
    switch ((insn >> 24) & 0xf) {
2728 b7bcbe95 bellard
    case 0xe:
2729 b7bcbe95 bellard
        if (insn & (1 << 4)) {
2730 b7bcbe95 bellard
            /* single register transfer */
2731 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
2732 b7bcbe95 bellard
            if (dp) {
2733 9ee6e8bb pbrook
                int size;
2734 9ee6e8bb pbrook
                int pass;
2735 9ee6e8bb pbrook
2736 9ee6e8bb pbrook
                VFP_DREG_N(rn, insn);
2737 9ee6e8bb pbrook
                if (insn & 0xf)
2738 b7bcbe95 bellard
                    return 1;
2739 9ee6e8bb pbrook
                if (insn & 0x00c00060
2740 9ee6e8bb pbrook
                    && !arm_feature(env, ARM_FEATURE_NEON))
2741 9ee6e8bb pbrook
                    return 1;
2742 9ee6e8bb pbrook
2743 9ee6e8bb pbrook
                pass = (insn >> 21) & 1;
2744 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
2745 9ee6e8bb pbrook
                    size = 0;
2746 9ee6e8bb pbrook
                    offset = ((insn >> 5) & 3) * 8;
2747 9ee6e8bb pbrook
                } else if (insn & (1 << 5)) {
2748 9ee6e8bb pbrook
                    size = 1;
2749 9ee6e8bb pbrook
                    offset = (insn & (1 << 6)) ? 16 : 0;
2750 9ee6e8bb pbrook
                } else {
2751 9ee6e8bb pbrook
                    size = 2;
2752 9ee6e8bb pbrook
                    offset = 0;
2753 9ee6e8bb pbrook
                }
2754 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2755 b7bcbe95 bellard
                    /* vfp->arm */
2756 ad69471c pbrook
                    tmp = neon_load_reg(rn, pass);
2757 9ee6e8bb pbrook
                    switch (size) {
2758 9ee6e8bb pbrook
                    case 0:
2759 9ee6e8bb pbrook
                        if (offset)
2760 ad69471c pbrook
                            tcg_gen_shri_i32(tmp, tmp, offset);
2761 9ee6e8bb pbrook
                        if (insn & (1 << 23))
2762 ad69471c pbrook
                            gen_uxtb(tmp);
2763 9ee6e8bb pbrook
                        else
2764 ad69471c pbrook
                            gen_sxtb(tmp);
2765 9ee6e8bb pbrook
                        break;
2766 9ee6e8bb pbrook
                    case 1:
2767 9ee6e8bb pbrook
                        if (insn & (1 << 23)) {
2768 9ee6e8bb pbrook
                            if (offset) {
2769 ad69471c pbrook
                                tcg_gen_shri_i32(tmp, tmp, 16);
2770 9ee6e8bb pbrook
                            } else {
2771 ad69471c pbrook
                                gen_uxth(tmp);
2772 9ee6e8bb pbrook
                            }
2773 9ee6e8bb pbrook
                        } else {
2774 9ee6e8bb pbrook
                            if (offset) {
2775 ad69471c pbrook
                                tcg_gen_sari_i32(tmp, tmp, 16);
2776 9ee6e8bb pbrook
                            } else {
2777 ad69471c pbrook
                                gen_sxth(tmp);
2778 9ee6e8bb pbrook
                            }
2779 9ee6e8bb pbrook
                        }
2780 9ee6e8bb pbrook
                        break;
2781 9ee6e8bb pbrook
                    case 2:
2782 9ee6e8bb pbrook
                        break;
2783 9ee6e8bb pbrook
                    }
2784 ad69471c pbrook
                    store_reg(s, rd, tmp);
2785 b7bcbe95 bellard
                } else {
2786 b7bcbe95 bellard
                    /* arm->vfp */
2787 ad69471c pbrook
                    tmp = load_reg(s, rd);
2788 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
2789 9ee6e8bb pbrook
                        /* VDUP */
2790 9ee6e8bb pbrook
                        if (size == 0) {
2791 ad69471c pbrook
                            gen_neon_dup_u8(tmp, 0);
2792 9ee6e8bb pbrook
                        } else if (size == 1) {
2793 ad69471c pbrook
                            gen_neon_dup_low16(tmp);
2794 9ee6e8bb pbrook
                        }
2795 cbbccffc pbrook
                        for (n = 0; n <= pass * 2; n++) {
2796 7d1b0095 Peter Maydell
                            tmp2 = tcg_temp_new_i32();
2797 cbbccffc pbrook
                            tcg_gen_mov_i32(tmp2, tmp);
2798 cbbccffc pbrook
                            neon_store_reg(rn, n, tmp2);
2799 cbbccffc pbrook
                        }
2800 cbbccffc pbrook
                        neon_store_reg(rn, n, tmp);
2801 9ee6e8bb pbrook
                    } else {
2802 9ee6e8bb pbrook
                        /* VMOV */
2803 9ee6e8bb pbrook
                        switch (size) {
2804 9ee6e8bb pbrook
                        case 0:
2805 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2806 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2807 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
2808 9ee6e8bb pbrook
                            break;
2809 9ee6e8bb pbrook
                        case 1:
2810 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2811 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2812 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
2813 9ee6e8bb pbrook
                            break;
2814 9ee6e8bb pbrook
                        case 2:
2815 9ee6e8bb pbrook
                            break;
2816 9ee6e8bb pbrook
                        }
2817 ad69471c pbrook
                        neon_store_reg(rn, pass, tmp);
2818 9ee6e8bb pbrook
                    }
2819 b7bcbe95 bellard
                }
2820 9ee6e8bb pbrook
            } else { /* !dp */
2821 9ee6e8bb pbrook
                if ((insn & 0x6f) != 0x00)
2822 9ee6e8bb pbrook
                    return 1;
2823 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2824 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2825 b7bcbe95 bellard
                    /* vfp->arm */
2826 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2827 b7bcbe95 bellard
                        /* system register */
2828 40f137e1 pbrook
                        rn >>= 1;
2829 9ee6e8bb pbrook
2830 b7bcbe95 bellard
                        switch (rn) {
2831 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2832 4373f3ce pbrook
                            /* VFP2 allows access to FSID from userspace.
2833 9ee6e8bb pbrook
                               VFP3 restricts all id registers to privileged
2834 9ee6e8bb pbrook
                               accesses.  */
2835 9ee6e8bb pbrook
                            if (IS_USER(s)
2836 9ee6e8bb pbrook
                                && arm_feature(env, ARM_FEATURE_VFP3))
2837 9ee6e8bb pbrook
                                return 1;
2838 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2839 9ee6e8bb pbrook
                            break;
2840 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2841 9ee6e8bb pbrook
                            if (IS_USER(s))
2842 9ee6e8bb pbrook
                                return 1;
2843 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2844 9ee6e8bb pbrook
                            break;
2845 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2846 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2847 9ee6e8bb pbrook
                            /* Not present in VFP3.  */
2848 9ee6e8bb pbrook
                            if (IS_USER(s)
2849 9ee6e8bb pbrook
                                || arm_feature(env, ARM_FEATURE_VFP3))
2850 9ee6e8bb pbrook
                                return 1;
2851 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2852 b7bcbe95 bellard
                            break;
2853 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2854 601d70b9 balrog
                            if (rd == 15) {
2855 4373f3ce pbrook
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2856 4373f3ce pbrook
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2857 4373f3ce pbrook
                            } else {
2858 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
2859 4373f3ce pbrook
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2860 4373f3ce pbrook
                            }
2861 b7bcbe95 bellard
                            break;
2862 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2863 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2864 9ee6e8bb pbrook
                            if (IS_USER(s)
2865 9ee6e8bb pbrook
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2866 9ee6e8bb pbrook
                                return 1;
2867 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2868 9ee6e8bb pbrook
                            break;
2869 b7bcbe95 bellard
                        default:
2870 b7bcbe95 bellard
                            return 1;
2871 b7bcbe95 bellard
                        }
2872 b7bcbe95 bellard
                    } else {
2873 b7bcbe95 bellard
                        gen_mov_F0_vreg(0, rn);
2874 4373f3ce pbrook
                        tmp = gen_vfp_mrs();
2875 b7bcbe95 bellard
                    }
2876 b7bcbe95 bellard
                    if (rd == 15) {
2877 b5ff1b31 bellard
                        /* Set the 4 flag bits in the CPSR.  */
2878 4373f3ce pbrook
                        gen_set_nzcv(tmp);
2879 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
2880 4373f3ce pbrook
                    } else {
2881 4373f3ce pbrook
                        store_reg(s, rd, tmp);
2882 4373f3ce pbrook
                    }
2883 b7bcbe95 bellard
                } else {
2884 b7bcbe95 bellard
                    /* arm->vfp */
2885 4373f3ce pbrook
                    tmp = load_reg(s, rd);
2886 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2887 40f137e1 pbrook
                        rn >>= 1;
2888 b7bcbe95 bellard
                        /* system register */
2889 b7bcbe95 bellard
                        switch (rn) {
2890 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2891 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2892 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2893 b7bcbe95 bellard
                            /* Writes are ignored.  */
2894 b7bcbe95 bellard
                            break;
2895 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2896 4373f3ce pbrook
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2897 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp);
2898 b5ff1b31 bellard
                            gen_lookup_tb(s);
2899 b7bcbe95 bellard
                            break;
2900 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2901 9ee6e8bb pbrook
                            if (IS_USER(s))
2902 9ee6e8bb pbrook
                                return 1;
2903 71b3c3de Juha Riihimäki
                            /* TODO: VFP subarchitecture support.
2904 71b3c3de Juha Riihimäki
                             * For now, keep the EN bit only */
2905 71b3c3de Juha Riihimäki
                            tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2906 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2907 40f137e1 pbrook
                            gen_lookup_tb(s);
2908 40f137e1 pbrook
                            break;
2909 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2910 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2911 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2912 40f137e1 pbrook
                            break;
2913 b7bcbe95 bellard
                        default:
2914 b7bcbe95 bellard
                            return 1;
2915 b7bcbe95 bellard
                        }
2916 b7bcbe95 bellard
                    } else {
2917 4373f3ce pbrook
                        gen_vfp_msr(tmp);
2918 b7bcbe95 bellard
                        gen_mov_vreg_F0(0, rn);
2919 b7bcbe95 bellard
                    }
2920 b7bcbe95 bellard
                }
2921 b7bcbe95 bellard
            }
2922 b7bcbe95 bellard
        } else {
2923 b7bcbe95 bellard
            /* data processing */
2924 b7bcbe95 bellard
            /* The opcode is in bits 23, 21, 20 and 6.  */
2925 b7bcbe95 bellard
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2926 b7bcbe95 bellard
            if (dp) {
2927 b7bcbe95 bellard
                if (op == 15) {
2928 b7bcbe95 bellard
                    /* rn is opcode */
2929 b7bcbe95 bellard
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2930 b7bcbe95 bellard
                } else {
2931 b7bcbe95 bellard
                    /* rn is register number */
2932 9ee6e8bb pbrook
                    VFP_DREG_N(rn, insn);
2933 b7bcbe95 bellard
                }
2934 b7bcbe95 bellard
2935 04595bf6 Peter Maydell
                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2936 b7bcbe95 bellard
                    /* Integer or single precision destination.  */
2937 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2938 b7bcbe95 bellard
                } else {
2939 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2940 b7bcbe95 bellard
                }
2941 04595bf6 Peter Maydell
                if (op == 15 &&
2942 04595bf6 Peter Maydell
                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2943 04595bf6 Peter Maydell
                    /* VCVT from int is always from S reg regardless of dp bit.
2944 04595bf6 Peter Maydell
                     * VCVT with immediate frac_bits has same format as SREG_M
2945 04595bf6 Peter Maydell
                     */
2946 04595bf6 Peter Maydell
                    rm = VFP_SREG_M(insn);
2947 b7bcbe95 bellard
                } else {
2948 9ee6e8bb pbrook
                    VFP_DREG_M(rm, insn);
2949 b7bcbe95 bellard
                }
2950 b7bcbe95 bellard
            } else {
2951 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2952 b7bcbe95 bellard
                if (op == 15 && rn == 15) {
2953 b7bcbe95 bellard
                    /* Double precision destination.  */
2954 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2955 9ee6e8bb pbrook
                } else {
2956 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2957 9ee6e8bb pbrook
                }
2958 04595bf6 Peter Maydell
                /* NB that we implicitly rely on the encoding for the frac_bits
2959 04595bf6 Peter Maydell
                 * in VCVT of fixed to float being the same as that of an SREG_M
2960 04595bf6 Peter Maydell
                 */
2961 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
2962 b7bcbe95 bellard
            }
2963 b7bcbe95 bellard
2964 69d1fc22 Peter Maydell
            veclen = s->vec_len;
2965 b7bcbe95 bellard
            if (op == 15 && rn > 3)
2966 b7bcbe95 bellard
                veclen = 0;
2967 b7bcbe95 bellard
2968 b7bcbe95 bellard
            /* Shut up compiler warnings.  */
2969 b7bcbe95 bellard
            delta_m = 0;
2970 b7bcbe95 bellard
            delta_d = 0;
2971 b7bcbe95 bellard
            bank_mask = 0;
2972 3b46e624 ths
2973 b7bcbe95 bellard
            if (veclen > 0) {
2974 b7bcbe95 bellard
                if (dp)
2975 b7bcbe95 bellard
                    bank_mask = 0xc;
2976 b7bcbe95 bellard
                else
2977 b7bcbe95 bellard
                    bank_mask = 0x18;
2978 b7bcbe95 bellard
2979 b7bcbe95 bellard
                /* Figure out what type of vector operation this is.  */
2980 b7bcbe95 bellard
                if ((rd & bank_mask) == 0) {
2981 b7bcbe95 bellard
                    /* scalar */
2982 b7bcbe95 bellard
                    veclen = 0;
2983 b7bcbe95 bellard
                } else {
2984 b7bcbe95 bellard
                    if (dp)
2985 69d1fc22 Peter Maydell
                        delta_d = (s->vec_stride >> 1) + 1;
2986 b7bcbe95 bellard
                    else
2987 69d1fc22 Peter Maydell
                        delta_d = s->vec_stride + 1;
2988 b7bcbe95 bellard
2989 b7bcbe95 bellard
                    if ((rm & bank_mask) == 0) {
2990 b7bcbe95 bellard
                        /* mixed scalar/vector */
2991 b7bcbe95 bellard
                        delta_m = 0;
2992 b7bcbe95 bellard
                    } else {
2993 b7bcbe95 bellard
                        /* vector */
2994 b7bcbe95 bellard
                        delta_m = delta_d;
2995 b7bcbe95 bellard
                    }
2996 b7bcbe95 bellard
                }
2997 b7bcbe95 bellard
            }
2998 b7bcbe95 bellard
2999 b7bcbe95 bellard
            /* Load the initial operands.  */
3000 b7bcbe95 bellard
            if (op == 15) {
3001 b7bcbe95 bellard
                switch (rn) {
3002 b7bcbe95 bellard
                case 16:
3003 b7bcbe95 bellard
                case 17:
3004 b7bcbe95 bellard
                    /* Integer source */
3005 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
3006 b7bcbe95 bellard
                    break;
3007 b7bcbe95 bellard
                case 8:
3008 b7bcbe95 bellard
                case 9:
3009 b7bcbe95 bellard
                    /* Compare */
3010 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
3011 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rm);
3012 b7bcbe95 bellard
                    break;
3013 b7bcbe95 bellard
                case 10:
3014 b7bcbe95 bellard
                case 11:
3015 b7bcbe95 bellard
                    /* Compare with zero */
3016 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
3017 b7bcbe95 bellard
                    gen_vfp_F1_ld0(dp);
3018 b7bcbe95 bellard
                    break;
3019 9ee6e8bb pbrook
                case 20:
3020 9ee6e8bb pbrook
                case 21:
3021 9ee6e8bb pbrook
                case 22:
3022 9ee6e8bb pbrook
                case 23:
3023 644ad806 pbrook
                case 28:
3024 644ad806 pbrook
                case 29:
3025 644ad806 pbrook
                case 30:
3026 644ad806 pbrook
                case 31:
3027 9ee6e8bb pbrook
                    /* Source and destination the same.  */
3028 9ee6e8bb pbrook
                    gen_mov_F0_vreg(dp, rd);
3029 9ee6e8bb pbrook
                    break;
3030 b7bcbe95 bellard
                default:
3031 b7bcbe95 bellard
                    /* One source operand.  */
3032 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
3033 9ee6e8bb pbrook
                    break;
3034 b7bcbe95 bellard
                }
3035 b7bcbe95 bellard
            } else {
3036 b7bcbe95 bellard
                /* Two source operands.  */
3037 b7bcbe95 bellard
                gen_mov_F0_vreg(dp, rn);
3038 b7bcbe95 bellard
                gen_mov_F1_vreg(dp, rm);
3039 b7bcbe95 bellard
            }
3040 b7bcbe95 bellard
3041 b7bcbe95 bellard
            for (;;) {
3042 b7bcbe95 bellard
                /* Perform the calculation.  */
3043 b7bcbe95 bellard
                switch (op) {
3044 605a6aed Peter Maydell
                case 0: /* VMLA: fd + (fn * fm) */
3045 605a6aed Peter Maydell
                    /* Note that order of inputs to the add matters for NaNs */
3046 605a6aed Peter Maydell
                    gen_vfp_F1_mul(dp);
3047 605a6aed Peter Maydell
                    gen_mov_F0_vreg(dp, rd);
3048 b7bcbe95 bellard
                    gen_vfp_add(dp);
3049 b7bcbe95 bellard
                    break;
3050 605a6aed Peter Maydell
                case 1: /* VMLS: fd + -(fn * fm) */
3051 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3052 605a6aed Peter Maydell
                    gen_vfp_F1_neg(dp);
3053 605a6aed Peter Maydell
                    gen_mov_F0_vreg(dp, rd);
3054 b7bcbe95 bellard
                    gen_vfp_add(dp);
3055 b7bcbe95 bellard
                    break;
3056 605a6aed Peter Maydell
                case 2: /* VNMLS: -fd + (fn * fm) */
3057 605a6aed Peter Maydell
                    /* Note that it isn't valid to replace (-A + B) with (B - A)
3058 605a6aed Peter Maydell
                     * or similar plausible looking simplifications
3059 605a6aed Peter Maydell
                     * because this will give wrong results for NaNs.
3060 605a6aed Peter Maydell
                     */
3061 605a6aed Peter Maydell
                    gen_vfp_F1_mul(dp);
3062 605a6aed Peter Maydell
                    gen_mov_F0_vreg(dp, rd);
3063 605a6aed Peter Maydell
                    gen_vfp_neg(dp);
3064 605a6aed Peter Maydell
                    gen_vfp_add(dp);
3065 b7bcbe95 bellard
                    break;
3066 605a6aed Peter Maydell
                case 3: /* VNMLA: -fd + -(fn * fm) */
3067 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3068 605a6aed Peter Maydell
                    gen_vfp_F1_neg(dp);
3069 605a6aed Peter Maydell
                    gen_mov_F0_vreg(dp, rd);
3070 b7bcbe95 bellard
                    gen_vfp_neg(dp);
3071 605a6aed Peter Maydell
                    gen_vfp_add(dp);
3072 b7bcbe95 bellard
                    break;
3073 b7bcbe95 bellard
                case 4: /* mul: fn * fm */
3074 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3075 b7bcbe95 bellard
                    break;
3076 b7bcbe95 bellard
                case 5: /* nmul: -(fn * fm) */
3077 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3078 b7bcbe95 bellard
                    gen_vfp_neg(dp);
3079 b7bcbe95 bellard
                    break;
3080 b7bcbe95 bellard
                case 6: /* add: fn + fm */
3081 b7bcbe95 bellard
                    gen_vfp_add(dp);
3082 b7bcbe95 bellard
                    break;
3083 b7bcbe95 bellard
                case 7: /* sub: fn - fm */
3084 b7bcbe95 bellard
                    gen_vfp_sub(dp);
3085 b7bcbe95 bellard
                    break;
3086 b7bcbe95 bellard
                case 8: /* div: fn / fm */
3087 b7bcbe95 bellard
                    gen_vfp_div(dp);
3088 b7bcbe95 bellard
                    break;
3089 9ee6e8bb pbrook
                case 14: /* fconst */
3090 9ee6e8bb pbrook
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
3091 9ee6e8bb pbrook
                      return 1;
3092 9ee6e8bb pbrook
3093 9ee6e8bb pbrook
                    n = (insn << 12) & 0x80000000;
3094 9ee6e8bb pbrook
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
3095 9ee6e8bb pbrook
                    if (dp) {
3096 9ee6e8bb pbrook
                        if (i & 0x40)
3097 9ee6e8bb pbrook
                            i |= 0x3f80;
3098 9ee6e8bb pbrook
                        else
3099 9ee6e8bb pbrook
                            i |= 0x4000;
3100 9ee6e8bb pbrook
                        n |= i << 16;
3101 4373f3ce pbrook
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3102 9ee6e8bb pbrook
                    } else {
3103 9ee6e8bb pbrook
                        if (i & 0x40)
3104 9ee6e8bb pbrook
                            i |= 0x780;
3105 9ee6e8bb pbrook
                        else
3106 9ee6e8bb pbrook
                            i |= 0x800;
3107 9ee6e8bb pbrook
                        n |= i << 19;
3108 5b340b51 balrog
                        tcg_gen_movi_i32(cpu_F0s, n);
3109 9ee6e8bb pbrook
                    }
3110 9ee6e8bb pbrook
                    break;
3111 b7bcbe95 bellard
                case 15: /* extension space */
3112 b7bcbe95 bellard
                    switch (rn) {
3113 b7bcbe95 bellard
                    case 0: /* cpy */
3114 b7bcbe95 bellard
                        /* no-op */
3115 b7bcbe95 bellard
                        break;
3116 b7bcbe95 bellard
                    case 1: /* abs */
3117 b7bcbe95 bellard
                        gen_vfp_abs(dp);
3118 b7bcbe95 bellard
                        break;
3119 b7bcbe95 bellard
                    case 2: /* neg */
3120 b7bcbe95 bellard
                        gen_vfp_neg(dp);
3121 b7bcbe95 bellard
                        break;
3122 b7bcbe95 bellard
                    case 3: /* sqrt */
3123 b7bcbe95 bellard
                        gen_vfp_sqrt(dp);
3124 b7bcbe95 bellard
                        break;
3125 60011498 Paul Brook
                    case 4: /* vcvtb.f32.f16 */
3126 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3127 60011498 Paul Brook
                          return 1;
3128 60011498 Paul Brook
                        tmp = gen_vfp_mrs();
3129 60011498 Paul Brook
                        tcg_gen_ext16u_i32(tmp, tmp);
3130 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3131 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
3132 60011498 Paul Brook
                        break;
3133 60011498 Paul Brook
                    case 5: /* vcvtt.f32.f16 */
3134 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3135 60011498 Paul Brook
                          return 1;
3136 60011498 Paul Brook
                        tmp = gen_vfp_mrs();
3137 60011498 Paul Brook
                        tcg_gen_shri_i32(tmp, tmp, 16);
3138 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3139 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
3140 60011498 Paul Brook
                        break;
3141 60011498 Paul Brook
                    case 6: /* vcvtb.f16.f32 */
3142 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3143 60011498 Paul Brook
                          return 1;
3144 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
3145 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3146 60011498 Paul Brook
                        gen_mov_F0_vreg(0, rd);
3147 60011498 Paul Brook
                        tmp2 = gen_vfp_mrs();
3148 60011498 Paul Brook
                        tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3149 60011498 Paul Brook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
3150 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
3151 60011498 Paul Brook
                        gen_vfp_msr(tmp);
3152 60011498 Paul Brook
                        break;
3153 60011498 Paul Brook
                    case 7: /* vcvtt.f16.f32 */
3154 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3155 60011498 Paul Brook
                          return 1;
3156 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
3157 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3158 60011498 Paul Brook
                        tcg_gen_shli_i32(tmp, tmp, 16);
3159 60011498 Paul Brook
                        gen_mov_F0_vreg(0, rd);
3160 60011498 Paul Brook
                        tmp2 = gen_vfp_mrs();
3161 60011498 Paul Brook
                        tcg_gen_ext16u_i32(tmp2, tmp2);
3162 60011498 Paul Brook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
3163 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
3164 60011498 Paul Brook
                        gen_vfp_msr(tmp);
3165 60011498 Paul Brook
                        break;
3166 b7bcbe95 bellard
                    case 8: /* cmp */
3167 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3168 b7bcbe95 bellard
                        break;
3169 b7bcbe95 bellard
                    case 9: /* cmpe */
3170 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3171 b7bcbe95 bellard
                        break;
3172 b7bcbe95 bellard
                    case 10: /* cmpz */
3173 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3174 b7bcbe95 bellard
                        break;
3175 b7bcbe95 bellard
                    case 11: /* cmpez */
3176 b7bcbe95 bellard
                        gen_vfp_F1_ld0(dp);
3177 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3178 b7bcbe95 bellard
                        break;
3179 b7bcbe95 bellard
                    case 15: /* single<->double conversion */
3180 b7bcbe95 bellard
                        if (dp)
3181 4373f3ce pbrook
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3182 b7bcbe95 bellard
                        else
3183 4373f3ce pbrook
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3184 b7bcbe95 bellard
                        break;
3185 b7bcbe95 bellard
                    case 16: /* fuito */
3186 b7bcbe95 bellard
                        gen_vfp_uito(dp);
3187 b7bcbe95 bellard
                        break;
3188 b7bcbe95 bellard
                    case 17: /* fsito */
3189 b7bcbe95 bellard
                        gen_vfp_sito(dp);
3190 b7bcbe95 bellard
                        break;
3191 9ee6e8bb pbrook
                    case 20: /* fshto */
3192 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3193 9ee6e8bb pbrook
                          return 1;
3194 644ad806 pbrook
                        gen_vfp_shto(dp, 16 - rm);
3195 9ee6e8bb pbrook
                        break;
3196 9ee6e8bb pbrook
                    case 21: /* fslto */
3197 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3198 9ee6e8bb pbrook
                          return 1;
3199 644ad806 pbrook
                        gen_vfp_slto(dp, 32 - rm);
3200 9ee6e8bb pbrook
                        break;
3201 9ee6e8bb pbrook
                    case 22: /* fuhto */
3202 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3203 9ee6e8bb pbrook
                          return 1;
3204 644ad806 pbrook
                        gen_vfp_uhto(dp, 16 - rm);
3205 9ee6e8bb pbrook
                        break;
3206 9ee6e8bb pbrook
                    case 23: /* fulto */
3207 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3208 9ee6e8bb pbrook
                          return 1;
3209 644ad806 pbrook
                        gen_vfp_ulto(dp, 32 - rm);
3210 9ee6e8bb pbrook
                        break;
3211 b7bcbe95 bellard
                    case 24: /* ftoui */
3212 b7bcbe95 bellard
                        gen_vfp_toui(dp);
3213 b7bcbe95 bellard
                        break;
3214 b7bcbe95 bellard
                    case 25: /* ftouiz */
3215 b7bcbe95 bellard
                        gen_vfp_touiz(dp);
3216 b7bcbe95 bellard
                        break;
3217 b7bcbe95 bellard
                    case 26: /* ftosi */
3218 b7bcbe95 bellard
                        gen_vfp_tosi(dp);
3219 b7bcbe95 bellard
                        break;
3220 b7bcbe95 bellard
                    case 27: /* ftosiz */
3221 b7bcbe95 bellard
                        gen_vfp_tosiz(dp);
3222 b7bcbe95 bellard
                        break;
3223 9ee6e8bb pbrook
                    case 28: /* ftosh */
3224 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3225 9ee6e8bb pbrook
                          return 1;
3226 644ad806 pbrook
                        gen_vfp_tosh(dp, 16 - rm);
3227 9ee6e8bb pbrook
                        break;
3228 9ee6e8bb pbrook
                    case 29: /* ftosl */
3229 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3230 9ee6e8bb pbrook
                          return 1;
3231 644ad806 pbrook
                        gen_vfp_tosl(dp, 32 - rm);
3232 9ee6e8bb pbrook
                        break;
3233 9ee6e8bb pbrook
                    case 30: /* ftouh */
3234 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3235 9ee6e8bb pbrook
                          return 1;
3236 644ad806 pbrook
                        gen_vfp_touh(dp, 16 - rm);
3237 9ee6e8bb pbrook
                        break;
3238 9ee6e8bb pbrook
                    case 31: /* ftoul */
3239 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3240 9ee6e8bb pbrook
                          return 1;
3241 644ad806 pbrook
                        gen_vfp_toul(dp, 32 - rm);
3242 9ee6e8bb pbrook
                        break;
3243 b7bcbe95 bellard
                    default: /* undefined */
3244 b7bcbe95 bellard
                        printf ("rn:%d\n", rn);
3245 b7bcbe95 bellard
                        return 1;
3246 b7bcbe95 bellard
                    }
3247 b7bcbe95 bellard
                    break;
3248 b7bcbe95 bellard
                default: /* undefined */
3249 b7bcbe95 bellard
                    printf ("op:%d\n", op);
3250 b7bcbe95 bellard
                    return 1;
3251 b7bcbe95 bellard
                }
3252 b7bcbe95 bellard
3253 b7bcbe95 bellard
                /* Write back the result.  */
3254 b7bcbe95 bellard
                if (op == 15 && (rn >= 8 && rn <= 11))
3255 b7bcbe95 bellard
                    ; /* Comparison, do nothing.  */
3256 04595bf6 Peter Maydell
                else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3257 04595bf6 Peter Maydell
                    /* VCVT double to int: always integer result. */
3258 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rd);
3259 b7bcbe95 bellard
                else if (op == 15 && rn == 15)
3260 b7bcbe95 bellard
                    /* conversion */
3261 b7bcbe95 bellard
                    gen_mov_vreg_F0(!dp, rd);
3262 b7bcbe95 bellard
                else
3263 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3264 b7bcbe95 bellard
3265 b7bcbe95 bellard
                /* break out of the loop if we have finished  */
3266 b7bcbe95 bellard
                if (veclen == 0)
3267 b7bcbe95 bellard
                    break;
3268 b7bcbe95 bellard
3269 b7bcbe95 bellard
                if (op == 15 && delta_m == 0) {
3270 b7bcbe95 bellard
                    /* single source one-many */
3271 b7bcbe95 bellard
                    while (veclen--) {
3272 b7bcbe95 bellard
                        rd = ((rd + delta_d) & (bank_mask - 1))
3273 b7bcbe95 bellard
                             | (rd & bank_mask);
3274 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd);
3275 b7bcbe95 bellard
                    }
3276 b7bcbe95 bellard
                    break;
3277 b7bcbe95 bellard
                }
3278 b7bcbe95 bellard
                /* Setup the next operands.  */
3279 b7bcbe95 bellard
                veclen--;
3280 b7bcbe95 bellard
                rd = ((rd + delta_d) & (bank_mask - 1))
3281 b7bcbe95 bellard
                     | (rd & bank_mask);
3282 b7bcbe95 bellard
3283 b7bcbe95 bellard
                if (op == 15) {
3284 b7bcbe95 bellard
                    /* One source operand.  */
3285 b7bcbe95 bellard
                    rm = ((rm + delta_m) & (bank_mask - 1))
3286 b7bcbe95 bellard
                         | (rm & bank_mask);
3287 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
3288 b7bcbe95 bellard
                } else {
3289 b7bcbe95 bellard
                    /* Two source operands.  */
3290 b7bcbe95 bellard
                    rn = ((rn + delta_d) & (bank_mask - 1))
3291 b7bcbe95 bellard
                         | (rn & bank_mask);
3292 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rn);
3293 b7bcbe95 bellard
                    if (delta_m) {
3294 b7bcbe95 bellard
                        rm = ((rm + delta_m) & (bank_mask - 1))
3295 b7bcbe95 bellard
                             | (rm & bank_mask);
3296 b7bcbe95 bellard
                        gen_mov_F1_vreg(dp, rm);
3297 b7bcbe95 bellard
                    }
3298 b7bcbe95 bellard
                }
3299 b7bcbe95 bellard
            }
3300 b7bcbe95 bellard
        }
3301 b7bcbe95 bellard
        break;
3302 b7bcbe95 bellard
    case 0xc:
3303 b7bcbe95 bellard
    case 0xd:
3304 8387da81 Peter Maydell
        if ((insn & 0x03e00000) == 0x00400000) {
3305 b7bcbe95 bellard
            /* two-register transfer */
3306 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3307 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
3308 b7bcbe95 bellard
            if (dp) {
3309 9ee6e8bb pbrook
                VFP_DREG_M(rm, insn);
3310 9ee6e8bb pbrook
            } else {
3311 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
3312 9ee6e8bb pbrook
            }
3313 b7bcbe95 bellard
3314 18c9b560 balrog
            if (insn & ARM_CP_RW_BIT) {
3315 b7bcbe95 bellard
                /* vfp->arm */
3316 b7bcbe95 bellard
                if (dp) {
3317 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2);
3318 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3319 4373f3ce pbrook
                    store_reg(s, rd, tmp);
3320 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2 + 1);
3321 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3322 4373f3ce pbrook
                    store_reg(s, rn, tmp);
3323 b7bcbe95 bellard
                } else {
3324 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
3325 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3326 8387da81 Peter Maydell
                    store_reg(s, rd, tmp);
3327 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm + 1);
3328 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3329 8387da81 Peter Maydell
                    store_reg(s, rn, tmp);
3330 b7bcbe95 bellard
                }
3331 b7bcbe95 bellard
            } else {
3332 b7bcbe95 bellard
                /* arm->vfp */
3333 b7bcbe95 bellard
                if (dp) {
3334 4373f3ce pbrook
                    tmp = load_reg(s, rd);
3335 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3336 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2);
3337 4373f3ce pbrook
                    tmp = load_reg(s, rn);
3338 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3339 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2 + 1);
3340 b7bcbe95 bellard
                } else {
3341 8387da81 Peter Maydell
                    tmp = load_reg(s, rd);
3342 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3343 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm);
3344 8387da81 Peter Maydell
                    tmp = load_reg(s, rn);
3345 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3346 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm + 1);
3347 b7bcbe95 bellard
                }
3348 b7bcbe95 bellard
            }
3349 b7bcbe95 bellard
        } else {
3350 b7bcbe95 bellard
            /* Load/store */
3351 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3352 b7bcbe95 bellard
            if (dp)
3353 9ee6e8bb pbrook
                VFP_DREG_D(rd, insn);
3354 b7bcbe95 bellard
            else
3355 9ee6e8bb pbrook
                rd = VFP_SREG_D(insn);
3356 9ee6e8bb pbrook
            if (s->thumb && rn == 15) {
3357 7d1b0095 Peter Maydell
                addr = tcg_temp_new_i32();
3358 312eea9f Filip Navara
                tcg_gen_movi_i32(addr, s->pc & ~2);
3359 9ee6e8bb pbrook
            } else {
3360 312eea9f Filip Navara
                addr = load_reg(s, rn);
3361 9ee6e8bb pbrook
            }
3362 b7bcbe95 bellard
            if ((insn & 0x01200000) == 0x01000000) {
3363 b7bcbe95 bellard
                /* Single load/store */
3364 b7bcbe95 bellard
                offset = (insn & 0xff) << 2;
3365 b7bcbe95 bellard
                if ((insn & (1 << 23)) == 0)
3366 b7bcbe95 bellard
                    offset = -offset;
3367 312eea9f Filip Navara
                tcg_gen_addi_i32(addr, addr, offset);
3368 b7bcbe95 bellard
                if (insn & (1 << 20)) {
3369 312eea9f Filip Navara
                    gen_vfp_ld(s, dp, addr);
3370 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3371 b7bcbe95 bellard
                } else {
3372 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
3373 312eea9f Filip Navara
                    gen_vfp_st(s, dp, addr);
3374 b7bcbe95 bellard
                }
3375 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
3376 b7bcbe95 bellard
            } else {
3377 b7bcbe95 bellard
                /* load/store multiple */
3378 b7bcbe95 bellard
                if (dp)
3379 b7bcbe95 bellard
                    n = (insn >> 1) & 0x7f;
3380 b7bcbe95 bellard
                else
3381 b7bcbe95 bellard
                    n = insn & 0xff;
3382 b7bcbe95 bellard
3383 b7bcbe95 bellard
                if (insn & (1 << 24)) /* pre-decrement */
3384 312eea9f Filip Navara
                    tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3385 b7bcbe95 bellard
3386 b7bcbe95 bellard
                if (dp)
3387 b7bcbe95 bellard
                    offset = 8;
3388 b7bcbe95 bellard
                else
3389 b7bcbe95 bellard
                    offset = 4;
3390 b7bcbe95 bellard
                for (i = 0; i < n; i++) {
3391 18c9b560 balrog
                    if (insn & ARM_CP_RW_BIT) {
3392 b7bcbe95 bellard
                        /* load */
3393 312eea9f Filip Navara
                        gen_vfp_ld(s, dp, addr);
3394 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd + i);
3395 b7bcbe95 bellard
                    } else {
3396 b7bcbe95 bellard
                        /* store */
3397 b7bcbe95 bellard
                        gen_mov_F0_vreg(dp, rd + i);
3398 312eea9f Filip Navara
                        gen_vfp_st(s, dp, addr);
3399 b7bcbe95 bellard
                    }
3400 312eea9f Filip Navara
                    tcg_gen_addi_i32(addr, addr, offset);
3401 b7bcbe95 bellard
                }
3402 b7bcbe95 bellard
                if (insn & (1 << 21)) {
3403 b7bcbe95 bellard
                    /* writeback */
3404 b7bcbe95 bellard
                    if (insn & (1 << 24))
3405 b7bcbe95 bellard
                        offset = -offset * n;
3406 b7bcbe95 bellard
                    else if (dp && (insn & 1))
3407 b7bcbe95 bellard
                        offset = 4;
3408 b7bcbe95 bellard
                    else
3409 b7bcbe95 bellard
                        offset = 0;
3410 b7bcbe95 bellard
3411 b7bcbe95 bellard
                    if (offset != 0)
3412 312eea9f Filip Navara
                        tcg_gen_addi_i32(addr, addr, offset);
3413 312eea9f Filip Navara
                    store_reg(s, rn, addr);
3414 312eea9f Filip Navara
                } else {
3415 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
3416 b7bcbe95 bellard
                }
3417 b7bcbe95 bellard
            }
3418 b7bcbe95 bellard
        }
3419 b7bcbe95 bellard
        break;
3420 b7bcbe95 bellard
    default:
3421 b7bcbe95 bellard
        /* Should never happen.  */
3422 b7bcbe95 bellard
        return 1;
3423 b7bcbe95 bellard
    }
3424 b7bcbe95 bellard
    return 0;
3425 b7bcbe95 bellard
}
3426 b7bcbe95 bellard
3427 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3428 c53be334 bellard
{
3429 6e256c93 bellard
    TranslationBlock *tb;
3430 6e256c93 bellard
3431 6e256c93 bellard
    tb = s->tb;
3432 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3433 57fec1fe bellard
        tcg_gen_goto_tb(n);
3434 8984bd2e pbrook
        gen_set_pc_im(dest);
3435 4b4a72e5 Stefan Weil
        tcg_gen_exit_tb((tcg_target_long)tb + n);
3436 6e256c93 bellard
    } else {
3437 8984bd2e pbrook
        gen_set_pc_im(dest);
3438 57fec1fe bellard
        tcg_gen_exit_tb(0);
3439 6e256c93 bellard
    }
3440 c53be334 bellard
}
3441 c53be334 bellard
3442 8aaca4c0 bellard
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3443 8aaca4c0 bellard
{
3444 551bd27f ths
    if (unlikely(s->singlestep_enabled)) {
3445 8aaca4c0 bellard
        /* An indirect jump so that we still trigger the debug exception.  */
3446 5899f386 bellard
        if (s->thumb)
3447 d9ba4830 pbrook
            dest |= 1;
3448 d9ba4830 pbrook
        gen_bx_im(s, dest);
3449 8aaca4c0 bellard
    } else {
3450 6e256c93 bellard
        gen_goto_tb(s, 0, dest);
3451 8aaca4c0 bellard
        s->is_jmp = DISAS_TB_JUMP;
3452 8aaca4c0 bellard
    }
3453 8aaca4c0 bellard
}
3454 8aaca4c0 bellard
3455 d9ba4830 pbrook
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3456 b5ff1b31 bellard
{
3457 ee097184 bellard
    if (x)
3458 d9ba4830 pbrook
        tcg_gen_sari_i32(t0, t0, 16);
3459 b5ff1b31 bellard
    else
3460 d9ba4830 pbrook
        gen_sxth(t0);
3461 ee097184 bellard
    if (y)
3462 d9ba4830 pbrook
        tcg_gen_sari_i32(t1, t1, 16);
3463 b5ff1b31 bellard
    else
3464 d9ba4830 pbrook
        gen_sxth(t1);
3465 d9ba4830 pbrook
    tcg_gen_mul_i32(t0, t0, t1);
3466 b5ff1b31 bellard
}
3467 b5ff1b31 bellard
3468 b5ff1b31 bellard
/* Return the mask of PSR bits set by a MSR instruction.  */
3469 9ee6e8bb pbrook
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3470 b5ff1b31 bellard
    uint32_t mask;
3471 b5ff1b31 bellard
3472 b5ff1b31 bellard
    mask = 0;
3473 b5ff1b31 bellard
    if (flags & (1 << 0))
3474 b5ff1b31 bellard
        mask |= 0xff;
3475 b5ff1b31 bellard
    if (flags & (1 << 1))
3476 b5ff1b31 bellard
        mask |= 0xff00;
3477 b5ff1b31 bellard
    if (flags & (1 << 2))
3478 b5ff1b31 bellard
        mask |= 0xff0000;
3479 b5ff1b31 bellard
    if (flags & (1 << 3))
3480 b5ff1b31 bellard
        mask |= 0xff000000;
3481 9ee6e8bb pbrook
3482 2ae23e75 pbrook
    /* Mask out undefined bits.  */
3483 9ee6e8bb pbrook
    mask &= ~CPSR_RESERVED;
3484 be5e7a76 Dmitry Eremin-Solenikov
    if (!arm_feature(env, ARM_FEATURE_V4T))
3485 be5e7a76 Dmitry Eremin-Solenikov
        mask &= ~CPSR_T;
3486 be5e7a76 Dmitry Eremin-Solenikov
    if (!arm_feature(env, ARM_FEATURE_V5))
3487 be5e7a76 Dmitry Eremin-Solenikov
        mask &= ~CPSR_Q; /* V5TE in reality*/
3488 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_V6))
3489 e160c51c pbrook
        mask &= ~(CPSR_E | CPSR_GE);
3490 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3491 e160c51c pbrook
        mask &= ~CPSR_IT;
3492 9ee6e8bb pbrook
    /* Mask out execution state bits.  */
3493 2ae23e75 pbrook
    if (!spsr)
3494 e160c51c pbrook
        mask &= ~CPSR_EXEC;
3495 b5ff1b31 bellard
    /* Mask out privileged bits.  */
3496 b5ff1b31 bellard
    if (IS_USER(s))
3497 9ee6e8bb pbrook
        mask &= CPSR_USER;
3498 b5ff1b31 bellard
    return mask;
3499 b5ff1b31 bellard
}
3500 b5ff1b31 bellard
3501 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3502 2fbac54b Filip Navara
static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3503 b5ff1b31 bellard
{
3504 d9ba4830 pbrook
    TCGv tmp;
3505 b5ff1b31 bellard
    if (spsr) {
3506 b5ff1b31 bellard
        /* ??? This is also undefined in system mode.  */
3507 b5ff1b31 bellard
        if (IS_USER(s))
3508 b5ff1b31 bellard
            return 1;
3509 d9ba4830 pbrook
3510 d9ba4830 pbrook
        tmp = load_cpu_field(spsr);
3511 d9ba4830 pbrook
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3512 2fbac54b Filip Navara
        tcg_gen_andi_i32(t0, t0, mask);
3513 2fbac54b Filip Navara
        tcg_gen_or_i32(tmp, tmp, t0);
3514 d9ba4830 pbrook
        store_cpu_field(tmp, spsr);
3515 b5ff1b31 bellard
    } else {
3516 2fbac54b Filip Navara
        gen_set_cpsr(t0, mask);
3517 b5ff1b31 bellard
    }
3518 7d1b0095 Peter Maydell
    tcg_temp_free_i32(t0);
3519 b5ff1b31 bellard
    gen_lookup_tb(s);
3520 b5ff1b31 bellard
    return 0;
3521 b5ff1b31 bellard
}
3522 b5ff1b31 bellard
3523 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted.  */
3524 2fbac54b Filip Navara
static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3525 2fbac54b Filip Navara
{
3526 2fbac54b Filip Navara
    TCGv tmp;
3527 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
3528 2fbac54b Filip Navara
    tcg_gen_movi_i32(tmp, val);
3529 2fbac54b Filip Navara
    return gen_set_psr(s, mask, spsr, tmp);
3530 2fbac54b Filip Navara
}
3531 2fbac54b Filip Navara
3532 e9bb4aa9 Juha Riihimäki
/* Generate an old-style exception return. Marks pc as dead. */
3533 e9bb4aa9 Juha Riihimäki
static void gen_exception_return(DisasContext *s, TCGv pc)
3534 b5ff1b31 bellard
{
3535 d9ba4830 pbrook
    TCGv tmp;
3536 e9bb4aa9 Juha Riihimäki
    store_reg(s, 15, pc);
3537 d9ba4830 pbrook
    tmp = load_cpu_field(spsr);
3538 d9ba4830 pbrook
    gen_set_cpsr(tmp, 0xffffffff);
3539 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3540 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
3541 b5ff1b31 bellard
}
3542 b5ff1b31 bellard
3543 b0109805 pbrook
/* Generate a v6 exception return.  Marks both values as dead.  */
3544 b0109805 pbrook
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3545 2c0262af bellard
{
3546 b0109805 pbrook
    gen_set_cpsr(cpsr, 0xffffffff);
3547 7d1b0095 Peter Maydell
    tcg_temp_free_i32(cpsr);
3548 b0109805 pbrook
    store_reg(s, 15, pc);
3549 9ee6e8bb pbrook
    s->is_jmp = DISAS_UPDATE;
3550 9ee6e8bb pbrook
}
3551 3b46e624 ths
3552 9ee6e8bb pbrook
static inline void
3553 9ee6e8bb pbrook
gen_set_condexec (DisasContext *s)
3554 9ee6e8bb pbrook
{
3555 9ee6e8bb pbrook
    if (s->condexec_mask) {
3556 8f01245e pbrook
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3557 7d1b0095 Peter Maydell
        TCGv tmp = tcg_temp_new_i32();
3558 8f01245e pbrook
        tcg_gen_movi_i32(tmp, val);
3559 d9ba4830 pbrook
        store_cpu_field(tmp, condexec_bits);
3560 9ee6e8bb pbrook
    }
3561 9ee6e8bb pbrook
}
3562 3b46e624 ths
3563 bc4a0de0 Peter Maydell
static void gen_exception_insn(DisasContext *s, int offset, int excp)
3564 bc4a0de0 Peter Maydell
{
3565 bc4a0de0 Peter Maydell
    gen_set_condexec(s);
3566 bc4a0de0 Peter Maydell
    gen_set_pc_im(s->pc - offset);
3567 bc4a0de0 Peter Maydell
    gen_exception(excp);
3568 bc4a0de0 Peter Maydell
    s->is_jmp = DISAS_JUMP;
3569 bc4a0de0 Peter Maydell
}
3570 bc4a0de0 Peter Maydell
3571 9ee6e8bb pbrook
static void gen_nop_hint(DisasContext *s, int val)
3572 9ee6e8bb pbrook
{
3573 9ee6e8bb pbrook
    switch (val) {
3574 9ee6e8bb pbrook
    case 3: /* wfi */
3575 8984bd2e pbrook
        gen_set_pc_im(s->pc);
3576 9ee6e8bb pbrook
        s->is_jmp = DISAS_WFI;
3577 9ee6e8bb pbrook
        break;
3578 9ee6e8bb pbrook
    case 2: /* wfe */
3579 9ee6e8bb pbrook
    case 4: /* sev */
3580 9ee6e8bb pbrook
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3581 9ee6e8bb pbrook
    default: /* nop */
3582 9ee6e8bb pbrook
        break;
3583 9ee6e8bb pbrook
    }
3584 9ee6e8bb pbrook
}
3585 99c475ab bellard
3586 ad69471c pbrook
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3587 9ee6e8bb pbrook
3588 62698be3 Peter Maydell
static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
3589 9ee6e8bb pbrook
{
3590 9ee6e8bb pbrook
    switch (size) {
3591 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3592 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3593 dd8fbd78 Filip Navara
    case 2: tcg_gen_add_i32(t0, t0, t1); break;
3594 62698be3 Peter Maydell
    default: abort();
3595 9ee6e8bb pbrook
    }
3596 9ee6e8bb pbrook
}
3597 9ee6e8bb pbrook
3598 dd8fbd78 Filip Navara
static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3599 ad69471c pbrook
{
3600 ad69471c pbrook
    switch (size) {
3601 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3602 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3603 dd8fbd78 Filip Navara
    case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3604 ad69471c pbrook
    default: return;
3605 ad69471c pbrook
    }
3606 ad69471c pbrook
}
3607 ad69471c pbrook
3608 ad69471c pbrook
/* 32-bit pairwise ops end up the same as the elementwise versions.  */
3609 ad69471c pbrook
#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
3610 ad69471c pbrook
#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
3611 ad69471c pbrook
#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
3612 ad69471c pbrook
#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
3613 ad69471c pbrook
3614 ad69471c pbrook
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3615 ad69471c pbrook
    switch ((size << 1) | u) { \
3616 ad69471c pbrook
    case 0: \
3617 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3618 ad69471c pbrook
        break; \
3619 ad69471c pbrook
    case 1: \
3620 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3621 ad69471c pbrook
        break; \
3622 ad69471c pbrook
    case 2: \
3623 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3624 ad69471c pbrook
        break; \
3625 ad69471c pbrook
    case 3: \
3626 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3627 ad69471c pbrook
        break; \
3628 ad69471c pbrook
    case 4: \
3629 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3630 ad69471c pbrook
        break; \
3631 ad69471c pbrook
    case 5: \
3632 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3633 ad69471c pbrook
        break; \
3634 ad69471c pbrook
    default: return 1; \
3635 ad69471c pbrook
    }} while (0)
3636 9ee6e8bb pbrook
3637 9ee6e8bb pbrook
#define GEN_NEON_INTEGER_OP(name) do { \
3638 9ee6e8bb pbrook
    switch ((size << 1) | u) { \
3639 ad69471c pbrook
    case 0: \
3640 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3641 ad69471c pbrook
        break; \
3642 ad69471c pbrook
    case 1: \
3643 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3644 ad69471c pbrook
        break; \
3645 ad69471c pbrook
    case 2: \
3646 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3647 ad69471c pbrook
        break; \
3648 ad69471c pbrook
    case 3: \
3649 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3650 ad69471c pbrook
        break; \
3651 ad69471c pbrook
    case 4: \
3652 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3653 ad69471c pbrook
        break; \
3654 ad69471c pbrook
    case 5: \
3655 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3656 ad69471c pbrook
        break; \
3657 9ee6e8bb pbrook
    default: return 1; \
3658 9ee6e8bb pbrook
    }} while (0)
3659 9ee6e8bb pbrook
3660 dd8fbd78 Filip Navara
static TCGv neon_load_scratch(int scratch)
3661 9ee6e8bb pbrook
{
3662 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
3663 dd8fbd78 Filip Navara
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3664 dd8fbd78 Filip Navara
    return tmp;
3665 9ee6e8bb pbrook
}
3666 9ee6e8bb pbrook
3667 dd8fbd78 Filip Navara
static void neon_store_scratch(int scratch, TCGv var)
3668 9ee6e8bb pbrook
{
3669 dd8fbd78 Filip Navara
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3670 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
3671 9ee6e8bb pbrook
}
3672 9ee6e8bb pbrook
3673 dd8fbd78 Filip Navara
static inline TCGv neon_get_scalar(int size, int reg)
3674 9ee6e8bb pbrook
{
3675 dd8fbd78 Filip Navara
    TCGv tmp;
3676 9ee6e8bb pbrook
    if (size == 1) {
3677 0fad6efc Peter Maydell
        tmp = neon_load_reg(reg & 7, reg >> 4);
3678 0fad6efc Peter Maydell
        if (reg & 8) {
3679 dd8fbd78 Filip Navara
            gen_neon_dup_high16(tmp);
3680 0fad6efc Peter Maydell
        } else {
3681 0fad6efc Peter Maydell
            gen_neon_dup_low16(tmp);
3682 dd8fbd78 Filip Navara
        }
3683 0fad6efc Peter Maydell
    } else {
3684 0fad6efc Peter Maydell
        tmp = neon_load_reg(reg & 15, reg >> 4);
3685 9ee6e8bb pbrook
    }
3686 dd8fbd78 Filip Navara
    return tmp;
3687 9ee6e8bb pbrook
}
3688 9ee6e8bb pbrook
3689 02acedf9 Peter Maydell
static int gen_neon_unzip(int rd, int rm, int size, int q)
3690 19457615 Filip Navara
{
3691 02acedf9 Peter Maydell
    TCGv tmp, tmp2;
3692 600b828c Peter Maydell
    if (!q && size == 2) {
3693 02acedf9 Peter Maydell
        return 1;
3694 02acedf9 Peter Maydell
    }
3695 02acedf9 Peter Maydell
    tmp = tcg_const_i32(rd);
3696 02acedf9 Peter Maydell
    tmp2 = tcg_const_i32(rm);
3697 02acedf9 Peter Maydell
    if (q) {
3698 02acedf9 Peter Maydell
        switch (size) {
3699 02acedf9 Peter Maydell
        case 0:
3700 2a3f75b4 Peter Maydell
            gen_helper_neon_qunzip8(tmp, tmp2);
3701 02acedf9 Peter Maydell
            break;
3702 02acedf9 Peter Maydell
        case 1:
3703 2a3f75b4 Peter Maydell
            gen_helper_neon_qunzip16(tmp, tmp2);
3704 02acedf9 Peter Maydell
            break;
3705 02acedf9 Peter Maydell
        case 2:
3706 2a3f75b4 Peter Maydell
            gen_helper_neon_qunzip32(tmp, tmp2);
3707 02acedf9 Peter Maydell
            break;
3708 02acedf9 Peter Maydell
        default:
3709 02acedf9 Peter Maydell
            abort();
3710 02acedf9 Peter Maydell
        }
3711 02acedf9 Peter Maydell
    } else {
3712 02acedf9 Peter Maydell
        switch (size) {
3713 02acedf9 Peter Maydell
        case 0:
3714 2a3f75b4 Peter Maydell
            gen_helper_neon_unzip8(tmp, tmp2);
3715 02acedf9 Peter Maydell
            break;
3716 02acedf9 Peter Maydell
        case 1:
3717 2a3f75b4 Peter Maydell
            gen_helper_neon_unzip16(tmp, tmp2);
3718 02acedf9 Peter Maydell
            break;
3719 02acedf9 Peter Maydell
        default:
3720 02acedf9 Peter Maydell
            abort();
3721 02acedf9 Peter Maydell
        }
3722 02acedf9 Peter Maydell
    }
3723 02acedf9 Peter Maydell
    tcg_temp_free_i32(tmp);
3724 02acedf9 Peter Maydell
    tcg_temp_free_i32(tmp2);
3725 02acedf9 Peter Maydell
    return 0;
3726 19457615 Filip Navara
}
3727 19457615 Filip Navara
3728 d68a6f3a Peter Maydell
static int gen_neon_zip(int rd, int rm, int size, int q)
3729 19457615 Filip Navara
{
3730 19457615 Filip Navara
    TCGv tmp, tmp2;
3731 600b828c Peter Maydell
    if (!q && size == 2) {
3732 d68a6f3a Peter Maydell
        return 1;
3733 d68a6f3a Peter Maydell
    }
3734 d68a6f3a Peter Maydell
    tmp = tcg_const_i32(rd);
3735 d68a6f3a Peter Maydell
    tmp2 = tcg_const_i32(rm);
3736 d68a6f3a Peter Maydell
    if (q) {
3737 d68a6f3a Peter Maydell
        switch (size) {
3738 d68a6f3a Peter Maydell
        case 0:
3739 2a3f75b4 Peter Maydell
            gen_helper_neon_qzip8(tmp, tmp2);
3740 d68a6f3a Peter Maydell
            break;
3741 d68a6f3a Peter Maydell
        case 1:
3742 2a3f75b4 Peter Maydell
            gen_helper_neon_qzip16(tmp, tmp2);
3743 d68a6f3a Peter Maydell
            break;
3744 d68a6f3a Peter Maydell
        case 2:
3745 2a3f75b4 Peter Maydell
            gen_helper_neon_qzip32(tmp, tmp2);
3746 d68a6f3a Peter Maydell
            break;
3747 d68a6f3a Peter Maydell
        default:
3748 d68a6f3a Peter Maydell
            abort();
3749 d68a6f3a Peter Maydell
        }
3750 d68a6f3a Peter Maydell
    } else {
3751 d68a6f3a Peter Maydell
        switch (size) {
3752 d68a6f3a Peter Maydell
        case 0:
3753 2a3f75b4 Peter Maydell
            gen_helper_neon_zip8(tmp, tmp2);
3754 d68a6f3a Peter Maydell
            break;
3755 d68a6f3a Peter Maydell
        case 1:
3756 2a3f75b4 Peter Maydell
            gen_helper_neon_zip16(tmp, tmp2);
3757 d68a6f3a Peter Maydell
            break;
3758 d68a6f3a Peter Maydell
        default:
3759 d68a6f3a Peter Maydell
            abort();
3760 d68a6f3a Peter Maydell
        }
3761 d68a6f3a Peter Maydell
    }
3762 d68a6f3a Peter Maydell
    tcg_temp_free_i32(tmp);
3763 d68a6f3a Peter Maydell
    tcg_temp_free_i32(tmp2);
3764 d68a6f3a Peter Maydell
    return 0;
3765 19457615 Filip Navara
}
3766 19457615 Filip Navara
3767 19457615 Filip Navara
static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3768 19457615 Filip Navara
{
3769 19457615 Filip Navara
    TCGv rd, tmp;
3770 19457615 Filip Navara
3771 7d1b0095 Peter Maydell
    rd = tcg_temp_new_i32();
3772 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
3773 19457615 Filip Navara
3774 19457615 Filip Navara
    tcg_gen_shli_i32(rd, t0, 8);
3775 19457615 Filip Navara
    tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3776 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3777 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3778 19457615 Filip Navara
3779 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 8);
3780 19457615 Filip Navara
    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3781 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3782 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3783 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3784 19457615 Filip Navara
3785 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3786 7d1b0095 Peter Maydell
    tcg_temp_free_i32(rd);
3787 19457615 Filip Navara
}
3788 19457615 Filip Navara
3789 19457615 Filip Navara
static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3790 19457615 Filip Navara
{
3791 19457615 Filip Navara
    TCGv rd, tmp;
3792 19457615 Filip Navara
3793 7d1b0095 Peter Maydell
    rd = tcg_temp_new_i32();
3794 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
3795 19457615 Filip Navara
3796 19457615 Filip Navara
    tcg_gen_shli_i32(rd, t0, 16);
3797 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0xffff);
3798 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3799 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 16);
3800 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3801 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3802 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3803 19457615 Filip Navara
3804 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3805 7d1b0095 Peter Maydell
    tcg_temp_free_i32(rd);
3806 19457615 Filip Navara
}
3807 19457615 Filip Navara
3808 19457615 Filip Navara
3809 9ee6e8bb pbrook
static struct {
3810 9ee6e8bb pbrook
    int nregs;
3811 9ee6e8bb pbrook
    int interleave;
3812 9ee6e8bb pbrook
    int spacing;
3813 9ee6e8bb pbrook
} neon_ls_element_type[11] = {
3814 9ee6e8bb pbrook
    {4, 4, 1},
3815 9ee6e8bb pbrook
    {4, 4, 2},
3816 9ee6e8bb pbrook
    {4, 1, 1},
3817 9ee6e8bb pbrook
    {4, 2, 1},
3818 9ee6e8bb pbrook
    {3, 3, 1},
3819 9ee6e8bb pbrook
    {3, 3, 2},
3820 9ee6e8bb pbrook
    {3, 1, 1},
3821 9ee6e8bb pbrook
    {1, 1, 1},
3822 9ee6e8bb pbrook
    {2, 2, 1},
3823 9ee6e8bb pbrook
    {2, 2, 2},
3824 9ee6e8bb pbrook
    {2, 1, 1}
3825 9ee6e8bb pbrook
};
3826 9ee6e8bb pbrook
3827 9ee6e8bb pbrook
/* Translate a NEON load/store element instruction.  Return nonzero if the
3828 9ee6e8bb pbrook
   instruction is invalid.  */
3829 9ee6e8bb pbrook
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3830 9ee6e8bb pbrook
{
3831 9ee6e8bb pbrook
    int rd, rn, rm;
3832 9ee6e8bb pbrook
    int op;
3833 9ee6e8bb pbrook
    int nregs;
3834 9ee6e8bb pbrook
    int interleave;
3835 84496233 Juha Riihimäki
    int spacing;
3836 9ee6e8bb pbrook
    int stride;
3837 9ee6e8bb pbrook
    int size;
3838 9ee6e8bb pbrook
    int reg;
3839 9ee6e8bb pbrook
    int pass;
3840 9ee6e8bb pbrook
    int load;
3841 9ee6e8bb pbrook
    int shift;
3842 9ee6e8bb pbrook
    int n;
3843 1b2b1e54 Filip Navara
    TCGv addr;
3844 b0109805 pbrook
    TCGv tmp;
3845 8f8e3aa4 pbrook
    TCGv tmp2;
3846 84496233 Juha Riihimäki
    TCGv_i64 tmp64;
3847 9ee6e8bb pbrook
3848 5df8bac1 Peter Maydell
    if (!s->vfp_enabled)
3849 9ee6e8bb pbrook
      return 1;
3850 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
3851 9ee6e8bb pbrook
    rn = (insn >> 16) & 0xf;
3852 9ee6e8bb pbrook
    rm = insn & 0xf;
3853 9ee6e8bb pbrook
    load = (insn & (1 << 21)) != 0;
3854 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
3855 9ee6e8bb pbrook
        /* Load store all elements.  */
3856 9ee6e8bb pbrook
        op = (insn >> 8) & 0xf;
3857 9ee6e8bb pbrook
        size = (insn >> 6) & 3;
3858 84496233 Juha Riihimäki
        if (op > 10)
3859 9ee6e8bb pbrook
            return 1;
3860 f2dd89d0 Peter Maydell
        /* Catch UNDEF cases for bad values of align field */
3861 f2dd89d0 Peter Maydell
        switch (op & 0xc) {
3862 f2dd89d0 Peter Maydell
        case 4:
3863 f2dd89d0 Peter Maydell
            if (((insn >> 5) & 1) == 1) {
3864 f2dd89d0 Peter Maydell
                return 1;
3865 f2dd89d0 Peter Maydell
            }
3866 f2dd89d0 Peter Maydell
            break;
3867 f2dd89d0 Peter Maydell
        case 8:
3868 f2dd89d0 Peter Maydell
            if (((insn >> 4) & 3) == 3) {
3869 f2dd89d0 Peter Maydell
                return 1;
3870 f2dd89d0 Peter Maydell
            }
3871 f2dd89d0 Peter Maydell
            break;
3872 f2dd89d0 Peter Maydell
        default:
3873 f2dd89d0 Peter Maydell
            break;
3874 f2dd89d0 Peter Maydell
        }
3875 9ee6e8bb pbrook
        nregs = neon_ls_element_type[op].nregs;
3876 9ee6e8bb pbrook
        interleave = neon_ls_element_type[op].interleave;
3877 84496233 Juha Riihimäki
        spacing = neon_ls_element_type[op].spacing;
3878 84496233 Juha Riihimäki
        if (size == 3 && (interleave | spacing) != 1)
3879 84496233 Juha Riihimäki
            return 1;
3880 e318a60b Peter Maydell
        addr = tcg_temp_new_i32();
3881 dcc65026 Aurelien Jarno
        load_reg_var(s, addr, rn);
3882 9ee6e8bb pbrook
        stride = (1 << size) * interleave;
3883 9ee6e8bb pbrook
        for (reg = 0; reg < nregs; reg++) {
3884 9ee6e8bb pbrook
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3885 dcc65026 Aurelien Jarno
                load_reg_var(s, addr, rn);
3886 dcc65026 Aurelien Jarno
                tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3887 9ee6e8bb pbrook
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3888 dcc65026 Aurelien Jarno
                load_reg_var(s, addr, rn);
3889 dcc65026 Aurelien Jarno
                tcg_gen_addi_i32(addr, addr, 1 << size);
3890 9ee6e8bb pbrook
            }
3891 84496233 Juha Riihimäki
            if (size == 3) {
3892 84496233 Juha Riihimäki
                if (load) {
3893 84496233 Juha Riihimäki
                    tmp64 = gen_ld64(addr, IS_USER(s));
3894 84496233 Juha Riihimäki
                    neon_store_reg64(tmp64, rd);
3895 84496233 Juha Riihimäki
                    tcg_temp_free_i64(tmp64);
3896 84496233 Juha Riihimäki
                } else {
3897 84496233 Juha Riihimäki
                    tmp64 = tcg_temp_new_i64();
3898 84496233 Juha Riihimäki
                    neon_load_reg64(tmp64, rd);
3899 84496233 Juha Riihimäki
                    gen_st64(tmp64, addr, IS_USER(s));
3900 84496233 Juha Riihimäki
                }
3901 84496233 Juha Riihimäki
                tcg_gen_addi_i32(addr, addr, stride);
3902 84496233 Juha Riihimäki
            } else {
3903 84496233 Juha Riihimäki
                for (pass = 0; pass < 2; pass++) {
3904 84496233 Juha Riihimäki
                    if (size == 2) {
3905 84496233 Juha Riihimäki
                        if (load) {
3906 84496233 Juha Riihimäki
                            tmp = gen_ld32(addr, IS_USER(s));
3907 84496233 Juha Riihimäki
                            neon_store_reg(rd, pass, tmp);
3908 84496233 Juha Riihimäki
                        } else {
3909 84496233 Juha Riihimäki
                            tmp = neon_load_reg(rd, pass);
3910 84496233 Juha Riihimäki
                            gen_st32(tmp, addr, IS_USER(s));
3911 84496233 Juha Riihimäki
                        }
3912 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3913 84496233 Juha Riihimäki
                    } else if (size == 1) {
3914 84496233 Juha Riihimäki
                        if (load) {
3915 84496233 Juha Riihimäki
                            tmp = gen_ld16u(addr, IS_USER(s));
3916 84496233 Juha Riihimäki
                            tcg_gen_addi_i32(addr, addr, stride);
3917 84496233 Juha Riihimäki
                            tmp2 = gen_ld16u(addr, IS_USER(s));
3918 84496233 Juha Riihimäki
                            tcg_gen_addi_i32(addr, addr, stride);
3919 41ba8341 Paul Brook
                            tcg_gen_shli_i32(tmp2, tmp2, 16);
3920 41ba8341 Paul Brook
                            tcg_gen_or_i32(tmp, tmp, tmp2);
3921 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
3922 84496233 Juha Riihimäki
                            neon_store_reg(rd, pass, tmp);
3923 84496233 Juha Riihimäki
                        } else {
3924 84496233 Juha Riihimäki
                            tmp = neon_load_reg(rd, pass);
3925 7d1b0095 Peter Maydell
                            tmp2 = tcg_temp_new_i32();
3926 84496233 Juha Riihimäki
                            tcg_gen_shri_i32(tmp2, tmp, 16);
3927 84496233 Juha Riihimäki
                            gen_st16(tmp, addr, IS_USER(s));
3928 84496233 Juha Riihimäki
                            tcg_gen_addi_i32(addr, addr, stride);
3929 84496233 Juha Riihimäki
                            gen_st16(tmp2, addr, IS_USER(s));
3930 1b2b1e54 Filip Navara
                            tcg_gen_addi_i32(addr, addr, stride);
3931 9ee6e8bb pbrook
                        }
3932 84496233 Juha Riihimäki
                    } else /* size == 0 */ {
3933 84496233 Juha Riihimäki
                        if (load) {
3934 84496233 Juha Riihimäki
                            TCGV_UNUSED(tmp2);
3935 84496233 Juha Riihimäki
                            for (n = 0; n < 4; n++) {
3936 84496233 Juha Riihimäki
                                tmp = gen_ld8u(addr, IS_USER(s));
3937 84496233 Juha Riihimäki
                                tcg_gen_addi_i32(addr, addr, stride);
3938 84496233 Juha Riihimäki
                                if (n == 0) {
3939 84496233 Juha Riihimäki
                                    tmp2 = tmp;
3940 84496233 Juha Riihimäki
                                } else {
3941 41ba8341 Paul Brook
                                    tcg_gen_shli_i32(tmp, tmp, n * 8);
3942 41ba8341 Paul Brook
                                    tcg_gen_or_i32(tmp2, tmp2, tmp);
3943 7d1b0095 Peter Maydell
                                    tcg_temp_free_i32(tmp);
3944 84496233 Juha Riihimäki
                                }
3945 9ee6e8bb pbrook
                            }
3946 84496233 Juha Riihimäki
                            neon_store_reg(rd, pass, tmp2);
3947 84496233 Juha Riihimäki
                        } else {
3948 84496233 Juha Riihimäki
                            tmp2 = neon_load_reg(rd, pass);
3949 84496233 Juha Riihimäki
                            for (n = 0; n < 4; n++) {
3950 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
3951 84496233 Juha Riihimäki
                                if (n == 0) {
3952 84496233 Juha Riihimäki
                                    tcg_gen_mov_i32(tmp, tmp2);
3953 84496233 Juha Riihimäki
                                } else {
3954 84496233 Juha Riihimäki
                                    tcg_gen_shri_i32(tmp, tmp2, n * 8);
3955 84496233 Juha Riihimäki
                                }
3956 84496233 Juha Riihimäki
                                gen_st8(tmp, addr, IS_USER(s));
3957 84496233 Juha Riihimäki
                                tcg_gen_addi_i32(addr, addr, stride);
3958 84496233 Juha Riihimäki
                            }
3959 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
3960 9ee6e8bb pbrook
                        }
3961 9ee6e8bb pbrook
                    }
3962 9ee6e8bb pbrook
                }
3963 9ee6e8bb pbrook
            }
3964 84496233 Juha Riihimäki
            rd += spacing;
3965 9ee6e8bb pbrook
        }
3966 e318a60b Peter Maydell
        tcg_temp_free_i32(addr);
3967 9ee6e8bb pbrook
        stride = nregs * 8;
3968 9ee6e8bb pbrook
    } else {
3969 9ee6e8bb pbrook
        size = (insn >> 10) & 3;
3970 9ee6e8bb pbrook
        if (size == 3) {
3971 9ee6e8bb pbrook
            /* Load single element to all lanes.  */
3972 8e18cde3 Peter Maydell
            int a = (insn >> 4) & 1;
3973 8e18cde3 Peter Maydell
            if (!load) {
3974 9ee6e8bb pbrook
                return 1;
3975 8e18cde3 Peter Maydell
            }
3976 9ee6e8bb pbrook
            size = (insn >> 6) & 3;
3977 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
3978 8e18cde3 Peter Maydell
3979 8e18cde3 Peter Maydell
            if (size == 3) {
3980 8e18cde3 Peter Maydell
                if (nregs != 4 || a == 0) {
3981 9ee6e8bb pbrook
                    return 1;
3982 99c475ab bellard
                }
3983 8e18cde3 Peter Maydell
                /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3984 8e18cde3 Peter Maydell
                size = 2;
3985 8e18cde3 Peter Maydell
            }
3986 8e18cde3 Peter Maydell
            if (nregs == 1 && a == 1 && size == 0) {
3987 8e18cde3 Peter Maydell
                return 1;
3988 8e18cde3 Peter Maydell
            }
3989 8e18cde3 Peter Maydell
            if (nregs == 3 && a == 1) {
3990 8e18cde3 Peter Maydell
                return 1;
3991 8e18cde3 Peter Maydell
            }
3992 e318a60b Peter Maydell
            addr = tcg_temp_new_i32();
3993 8e18cde3 Peter Maydell
            load_reg_var(s, addr, rn);
3994 8e18cde3 Peter Maydell
            if (nregs == 1) {
3995 8e18cde3 Peter Maydell
                /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3996 8e18cde3 Peter Maydell
                tmp = gen_load_and_replicate(s, addr, size);
3997 8e18cde3 Peter Maydell
                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3998 8e18cde3 Peter Maydell
                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3999 8e18cde3 Peter Maydell
                if (insn & (1 << 5)) {
4000 8e18cde3 Peter Maydell
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4001 8e18cde3 Peter Maydell
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4002 8e18cde3 Peter Maydell
                }
4003 8e18cde3 Peter Maydell
                tcg_temp_free_i32(tmp);
4004 8e18cde3 Peter Maydell
            } else {
4005 8e18cde3 Peter Maydell
                /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4006 8e18cde3 Peter Maydell
                stride = (insn & (1 << 5)) ? 2 : 1;
4007 8e18cde3 Peter Maydell
                for (reg = 0; reg < nregs; reg++) {
4008 8e18cde3 Peter Maydell
                    tmp = gen_load_and_replicate(s, addr, size);
4009 8e18cde3 Peter Maydell
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4010 8e18cde3 Peter Maydell
                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4011 8e18cde3 Peter Maydell
                    tcg_temp_free_i32(tmp);
4012 8e18cde3 Peter Maydell
                    tcg_gen_addi_i32(addr, addr, 1 << size);
4013 8e18cde3 Peter Maydell
                    rd += stride;
4014 8e18cde3 Peter Maydell
                }
4015 9ee6e8bb pbrook
            }
4016 e318a60b Peter Maydell
            tcg_temp_free_i32(addr);
4017 9ee6e8bb pbrook
            stride = (1 << size) * nregs;
4018 9ee6e8bb pbrook
        } else {
4019 9ee6e8bb pbrook
            /* Single element.  */
4020 93262b16 Peter Maydell
            int idx = (insn >> 4) & 0xf;
4021 9ee6e8bb pbrook
            pass = (insn >> 7) & 1;
4022 9ee6e8bb pbrook
            switch (size) {
4023 9ee6e8bb pbrook
            case 0:
4024 9ee6e8bb pbrook
                shift = ((insn >> 5) & 3) * 8;
4025 9ee6e8bb pbrook
                stride = 1;
4026 9ee6e8bb pbrook
                break;
4027 9ee6e8bb pbrook
            case 1:
4028 9ee6e8bb pbrook
                shift = ((insn >> 6) & 1) * 16;
4029 9ee6e8bb pbrook
                stride = (insn & (1 << 5)) ? 2 : 1;
4030 9ee6e8bb pbrook
                break;
4031 9ee6e8bb pbrook
            case 2:
4032 9ee6e8bb pbrook
                shift = 0;
4033 9ee6e8bb pbrook
                stride = (insn & (1 << 6)) ? 2 : 1;
4034 9ee6e8bb pbrook
                break;
4035 9ee6e8bb pbrook
            default:
4036 9ee6e8bb pbrook
                abort();
4037 9ee6e8bb pbrook
            }
4038 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
4039 93262b16 Peter Maydell
            /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4040 93262b16 Peter Maydell
            switch (nregs) {
4041 93262b16 Peter Maydell
            case 1:
4042 93262b16 Peter Maydell
                if (((idx & (1 << size)) != 0) ||
4043 93262b16 Peter Maydell
                    (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4044 93262b16 Peter Maydell
                    return 1;
4045 93262b16 Peter Maydell
                }
4046 93262b16 Peter Maydell
                break;
4047 93262b16 Peter Maydell
            case 3:
4048 93262b16 Peter Maydell
                if ((idx & 1) != 0) {
4049 93262b16 Peter Maydell
                    return 1;
4050 93262b16 Peter Maydell
                }
4051 93262b16 Peter Maydell
                /* fall through */
4052 93262b16 Peter Maydell
            case 2:
4053 93262b16 Peter Maydell
                if (size == 2 && (idx & 2) != 0) {
4054 93262b16 Peter Maydell
                    return 1;
4055 93262b16 Peter Maydell
                }
4056 93262b16 Peter Maydell
                break;
4057 93262b16 Peter Maydell
            case 4:
4058 93262b16 Peter Maydell
                if ((size == 2) && ((idx & 3) == 3)) {
4059 93262b16 Peter Maydell
                    return 1;
4060 93262b16 Peter Maydell
                }
4061 93262b16 Peter Maydell
                break;
4062 93262b16 Peter Maydell
            default:
4063 93262b16 Peter Maydell
                abort();
4064 93262b16 Peter Maydell
            }
4065 93262b16 Peter Maydell
            if ((rd + stride * (nregs - 1)) > 31) {
4066 93262b16 Peter Maydell
                /* Attempts to write off the end of the register file
4067 93262b16 Peter Maydell
                 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4068 93262b16 Peter Maydell
                 * the neon_load_reg() would write off the end of the array.
4069 93262b16 Peter Maydell
                 */
4070 93262b16 Peter Maydell
                return 1;
4071 93262b16 Peter Maydell
            }
4072 e318a60b Peter Maydell
            addr = tcg_temp_new_i32();
4073 dcc65026 Aurelien Jarno
            load_reg_var(s, addr, rn);
4074 9ee6e8bb pbrook
            for (reg = 0; reg < nregs; reg++) {
4075 9ee6e8bb pbrook
                if (load) {
4076 9ee6e8bb pbrook
                    switch (size) {
4077 9ee6e8bb pbrook
                    case 0:
4078 1b2b1e54 Filip Navara
                        tmp = gen_ld8u(addr, IS_USER(s));
4079 9ee6e8bb pbrook
                        break;
4080 9ee6e8bb pbrook
                    case 1:
4081 1b2b1e54 Filip Navara
                        tmp = gen_ld16u(addr, IS_USER(s));
4082 9ee6e8bb pbrook
                        break;
4083 9ee6e8bb pbrook
                    case 2:
4084 1b2b1e54 Filip Navara
                        tmp = gen_ld32(addr, IS_USER(s));
4085 9ee6e8bb pbrook
                        break;
4086 a50f5b91 pbrook
                    default: /* Avoid compiler warnings.  */
4087 a50f5b91 pbrook
                        abort();
4088 9ee6e8bb pbrook
                    }
4089 9ee6e8bb pbrook
                    if (size != 2) {
4090 8f8e3aa4 pbrook
                        tmp2 = neon_load_reg(rd, pass);
4091 8f8e3aa4 pbrook
                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
4092 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
4093 9ee6e8bb pbrook
                    }
4094 8f8e3aa4 pbrook
                    neon_store_reg(rd, pass, tmp);
4095 9ee6e8bb pbrook
                } else { /* Store */
4096 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, pass);
4097 8f8e3aa4 pbrook
                    if (shift)
4098 8f8e3aa4 pbrook
                        tcg_gen_shri_i32(tmp, tmp, shift);
4099 9ee6e8bb pbrook
                    switch (size) {
4100 9ee6e8bb pbrook
                    case 0:
4101 1b2b1e54 Filip Navara
                        gen_st8(tmp, addr, IS_USER(s));
4102 9ee6e8bb pbrook
                        break;
4103 9ee6e8bb pbrook
                    case 1:
4104 1b2b1e54 Filip Navara
                        gen_st16(tmp, addr, IS_USER(s));
4105 9ee6e8bb pbrook
                        break;
4106 9ee6e8bb pbrook
                    case 2:
4107 1b2b1e54 Filip Navara
                        gen_st32(tmp, addr, IS_USER(s));
4108 9ee6e8bb pbrook
                        break;
4109 99c475ab bellard
                    }
4110 99c475ab bellard
                }
4111 9ee6e8bb pbrook
                rd += stride;
4112 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, addr, 1 << size);
4113 99c475ab bellard
            }
4114 e318a60b Peter Maydell
            tcg_temp_free_i32(addr);
4115 9ee6e8bb pbrook
            stride = nregs * (1 << size);
4116 99c475ab bellard
        }
4117 9ee6e8bb pbrook
    }
4118 9ee6e8bb pbrook
    if (rm != 15) {
4119 b26eefb6 pbrook
        TCGv base;
4120 b26eefb6 pbrook
4121 b26eefb6 pbrook
        base = load_reg(s, rn);
4122 9ee6e8bb pbrook
        if (rm == 13) {
4123 b26eefb6 pbrook
            tcg_gen_addi_i32(base, base, stride);
4124 9ee6e8bb pbrook
        } else {
4125 b26eefb6 pbrook
            TCGv index;
4126 b26eefb6 pbrook
            index = load_reg(s, rm);
4127 b26eefb6 pbrook
            tcg_gen_add_i32(base, base, index);
4128 7d1b0095 Peter Maydell
            tcg_temp_free_i32(index);
4129 9ee6e8bb pbrook
        }
4130 b26eefb6 pbrook
        store_reg(s, rn, base);
4131 9ee6e8bb pbrook
    }
4132 9ee6e8bb pbrook
    return 0;
4133 9ee6e8bb pbrook
}
4134 3b46e624 ths
4135 8f8e3aa4 pbrook
/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
4136 8f8e3aa4 pbrook
static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4137 8f8e3aa4 pbrook
{
4138 8f8e3aa4 pbrook
    tcg_gen_and_i32(t, t, c);
4139 f669df27 Aurelien Jarno
    tcg_gen_andc_i32(f, f, c);
4140 8f8e3aa4 pbrook
    tcg_gen_or_i32(dest, t, f);
4141 8f8e3aa4 pbrook
}
4142 8f8e3aa4 pbrook
4143 a7812ae4 pbrook
static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4144 ad69471c pbrook
{
4145 ad69471c pbrook
    switch (size) {
4146 ad69471c pbrook
    case 0: gen_helper_neon_narrow_u8(dest, src); break;
4147 ad69471c pbrook
    case 1: gen_helper_neon_narrow_u16(dest, src); break;
4148 ad69471c pbrook
    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4149 ad69471c pbrook
    default: abort();
4150 ad69471c pbrook
    }
4151 ad69471c pbrook
}
4152 ad69471c pbrook
4153 a7812ae4 pbrook
static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4154 ad69471c pbrook
{
4155 ad69471c pbrook
    switch (size) {
4156 2a3f75b4 Peter Maydell
    case 0: gen_helper_neon_narrow_sat_s8(dest, src); break;
4157 2a3f75b4 Peter Maydell
    case 1: gen_helper_neon_narrow_sat_s16(dest, src); break;
4158 2a3f75b4 Peter Maydell
    case 2: gen_helper_neon_narrow_sat_s32(dest, src); break;
4159 ad69471c pbrook
    default: abort();
4160 ad69471c pbrook
    }
4161 ad69471c pbrook
}
4162 ad69471c pbrook
4163 a7812ae4 pbrook
static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4164 ad69471c pbrook
{
4165 ad69471c pbrook
    switch (size) {
4166 2a3f75b4 Peter Maydell
    case 0: gen_helper_neon_narrow_sat_u8(dest, src); break;
4167 2a3f75b4 Peter Maydell
    case 1: gen_helper_neon_narrow_sat_u16(dest, src); break;
4168 2a3f75b4 Peter Maydell
    case 2: gen_helper_neon_narrow_sat_u32(dest, src); break;
4169 ad69471c pbrook
    default: abort();
4170 ad69471c pbrook
    }
4171 ad69471c pbrook
}
4172 ad69471c pbrook
4173 af1bbf30 Juha Riihimäki
static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4174 af1bbf30 Juha Riihimäki
{
4175 af1bbf30 Juha Riihimäki
    switch (size) {
4176 2a3f75b4 Peter Maydell
    case 0: gen_helper_neon_unarrow_sat8(dest, src); break;
4177 2a3f75b4 Peter Maydell
    case 1: gen_helper_neon_unarrow_sat16(dest, src); break;
4178 2a3f75b4 Peter Maydell
    case 2: gen_helper_neon_unarrow_sat32(dest, src); break;
4179 af1bbf30 Juha Riihimäki
    default: abort();
4180 af1bbf30 Juha Riihimäki
    }
4181 af1bbf30 Juha Riihimäki
}
4182 af1bbf30 Juha Riihimäki
4183 ad69471c pbrook
static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4184 ad69471c pbrook
                                         int q, int u)
4185 ad69471c pbrook
{
4186 ad69471c pbrook
    if (q) {
4187 ad69471c pbrook
        if (u) {
4188 ad69471c pbrook
            switch (size) {
4189 ad69471c pbrook
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4190 ad69471c pbrook
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4191 ad69471c pbrook
            default: abort();
4192 ad69471c pbrook
            }
4193 ad69471c pbrook
        } else {
4194 ad69471c pbrook
            switch (size) {
4195 ad69471c pbrook
            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4196 ad69471c pbrook
            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4197 ad69471c pbrook
            default: abort();
4198 ad69471c pbrook
            }
4199 ad69471c pbrook
        }
4200 ad69471c pbrook
    } else {
4201 ad69471c pbrook
        if (u) {
4202 ad69471c pbrook
            switch (size) {
4203 b408a9b0 Christophe Lyon
            case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4204 b408a9b0 Christophe Lyon
            case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4205 ad69471c pbrook
            default: abort();
4206 ad69471c pbrook
            }
4207 ad69471c pbrook
        } else {
4208 ad69471c pbrook
            switch (size) {
4209 ad69471c pbrook
            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4210 ad69471c pbrook
            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4211 ad69471c pbrook
            default: abort();
4212 ad69471c pbrook
            }
4213 ad69471c pbrook
        }
4214 ad69471c pbrook
    }
4215 ad69471c pbrook
}
4216 ad69471c pbrook
4217 a7812ae4 pbrook
static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4218 ad69471c pbrook
{
4219 ad69471c pbrook
    if (u) {
4220 ad69471c pbrook
        switch (size) {
4221 ad69471c pbrook
        case 0: gen_helper_neon_widen_u8(dest, src); break;
4222 ad69471c pbrook
        case 1: gen_helper_neon_widen_u16(dest, src); break;
4223 ad69471c pbrook
        case 2: tcg_gen_extu_i32_i64(dest, src); break;
4224 ad69471c pbrook
        default: abort();
4225 ad69471c pbrook
        }
4226 ad69471c pbrook
    } else {
4227 ad69471c pbrook
        switch (size) {
4228 ad69471c pbrook
        case 0: gen_helper_neon_widen_s8(dest, src); break;
4229 ad69471c pbrook
        case 1: gen_helper_neon_widen_s16(dest, src); break;
4230 ad69471c pbrook
        case 2: tcg_gen_ext_i32_i64(dest, src); break;
4231 ad69471c pbrook
        default: abort();
4232 ad69471c pbrook
        }
4233 ad69471c pbrook
    }
4234 7d1b0095 Peter Maydell
    tcg_temp_free_i32(src);
4235 ad69471c pbrook
}
4236 ad69471c pbrook
4237 ad69471c pbrook
static inline void gen_neon_addl(int size)
4238 ad69471c pbrook
{
4239 ad69471c pbrook
    switch (size) {
4240 ad69471c pbrook
    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4241 ad69471c pbrook
    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4242 ad69471c pbrook
    case 2: tcg_gen_add_i64(CPU_V001); break;
4243 ad69471c pbrook
    default: abort();
4244 ad69471c pbrook
    }
4245 ad69471c pbrook
}
4246 ad69471c pbrook
4247 ad69471c pbrook
static inline void gen_neon_subl(int size)
4248 ad69471c pbrook
{
4249 ad69471c pbrook
    switch (size) {
4250 ad69471c pbrook
    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4251 ad69471c pbrook
    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4252 ad69471c pbrook
    case 2: tcg_gen_sub_i64(CPU_V001); break;
4253 ad69471c pbrook
    default: abort();
4254 ad69471c pbrook
    }
4255 ad69471c pbrook
}
4256 ad69471c pbrook
4257 a7812ae4 pbrook
static inline void gen_neon_negl(TCGv_i64 var, int size)
4258 ad69471c pbrook
{
4259 ad69471c pbrook
    switch (size) {
4260 ad69471c pbrook
    case 0: gen_helper_neon_negl_u16(var, var); break;
4261 ad69471c pbrook
    case 1: gen_helper_neon_negl_u32(var, var); break;
4262 ad69471c pbrook
    case 2: gen_helper_neon_negl_u64(var, var); break;
4263 ad69471c pbrook
    default: abort();
4264 ad69471c pbrook
    }
4265 ad69471c pbrook
}
4266 ad69471c pbrook
4267 a7812ae4 pbrook
static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4268 ad69471c pbrook
{
4269 ad69471c pbrook
    switch (size) {
4270 2a3f75b4 Peter Maydell
    case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break;
4271 2a3f75b4 Peter Maydell
    case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break;
4272 ad69471c pbrook
    default: abort();
4273 ad69471c pbrook
    }
4274 ad69471c pbrook
}
4275 ad69471c pbrook
4276 a7812ae4 pbrook
static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4277 ad69471c pbrook
{
4278 a7812ae4 pbrook
    TCGv_i64 tmp;
4279 ad69471c pbrook
4280 ad69471c pbrook
    switch ((size << 1) | u) {
4281 ad69471c pbrook
    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4282 ad69471c pbrook
    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4283 ad69471c pbrook
    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4284 ad69471c pbrook
    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4285 ad69471c pbrook
    case 4:
4286 ad69471c pbrook
        tmp = gen_muls_i64_i32(a, b);
4287 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4288 7d2aabe2 Peter Maydell
        tcg_temp_free_i64(tmp);
4289 ad69471c pbrook
        break;
4290 ad69471c pbrook
    case 5:
4291 ad69471c pbrook
        tmp = gen_mulu_i64_i32(a, b);
4292 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4293 7d2aabe2 Peter Maydell
        tcg_temp_free_i64(tmp);
4294 ad69471c pbrook
        break;
4295 ad69471c pbrook
    default: abort();
4296 ad69471c pbrook
    }
4297 c6067f04 Christophe Lyon
4298 c6067f04 Christophe Lyon
    /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4299 c6067f04 Christophe Lyon
       Don't forget to clean them now.  */
4300 c6067f04 Christophe Lyon
    if (size < 2) {
4301 7d1b0095 Peter Maydell
        tcg_temp_free_i32(a);
4302 7d1b0095 Peter Maydell
        tcg_temp_free_i32(b);
4303 c6067f04 Christophe Lyon
    }
4304 ad69471c pbrook
}
4305 ad69471c pbrook
4306 c33171c7 Peter Maydell
static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4307 c33171c7 Peter Maydell
{
4308 c33171c7 Peter Maydell
    if (op) {
4309 c33171c7 Peter Maydell
        if (u) {
4310 c33171c7 Peter Maydell
            gen_neon_unarrow_sats(size, dest, src);
4311 c33171c7 Peter Maydell
        } else {
4312 c33171c7 Peter Maydell
            gen_neon_narrow(size, dest, src);
4313 c33171c7 Peter Maydell
        }
4314 c33171c7 Peter Maydell
    } else {
4315 c33171c7 Peter Maydell
        if (u) {
4316 c33171c7 Peter Maydell
            gen_neon_narrow_satu(size, dest, src);
4317 c33171c7 Peter Maydell
        } else {
4318 c33171c7 Peter Maydell
            gen_neon_narrow_sats(size, dest, src);
4319 c33171c7 Peter Maydell
        }
4320 c33171c7 Peter Maydell
    }
4321 c33171c7 Peter Maydell
}
4322 c33171c7 Peter Maydell
4323 62698be3 Peter Maydell
/* Symbolic constants for op fields for Neon 3-register same-length.
4324 62698be3 Peter Maydell
 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4325 62698be3 Peter Maydell
 * table A7-9.
4326 62698be3 Peter Maydell
 */
4327 62698be3 Peter Maydell
#define NEON_3R_VHADD 0
4328 62698be3 Peter Maydell
#define NEON_3R_VQADD 1
4329 62698be3 Peter Maydell
#define NEON_3R_VRHADD 2
4330 62698be3 Peter Maydell
#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4331 62698be3 Peter Maydell
#define NEON_3R_VHSUB 4
4332 62698be3 Peter Maydell
#define NEON_3R_VQSUB 5
4333 62698be3 Peter Maydell
#define NEON_3R_VCGT 6
4334 62698be3 Peter Maydell
#define NEON_3R_VCGE 7
4335 62698be3 Peter Maydell
#define NEON_3R_VSHL 8
4336 62698be3 Peter Maydell
#define NEON_3R_VQSHL 9
4337 62698be3 Peter Maydell
#define NEON_3R_VRSHL 10
4338 62698be3 Peter Maydell
#define NEON_3R_VQRSHL 11
4339 62698be3 Peter Maydell
#define NEON_3R_VMAX 12
4340 62698be3 Peter Maydell
#define NEON_3R_VMIN 13
4341 62698be3 Peter Maydell
#define NEON_3R_VABD 14
4342 62698be3 Peter Maydell
#define NEON_3R_VABA 15
4343 62698be3 Peter Maydell
#define NEON_3R_VADD_VSUB 16
4344 62698be3 Peter Maydell
#define NEON_3R_VTST_VCEQ 17
4345 62698be3 Peter Maydell
#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4346 62698be3 Peter Maydell
#define NEON_3R_VMUL 19
4347 62698be3 Peter Maydell
#define NEON_3R_VPMAX 20
4348 62698be3 Peter Maydell
#define NEON_3R_VPMIN 21
4349 62698be3 Peter Maydell
#define NEON_3R_VQDMULH_VQRDMULH 22
4350 62698be3 Peter Maydell
#define NEON_3R_VPADD 23
4351 62698be3 Peter Maydell
#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4352 62698be3 Peter Maydell
#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4353 62698be3 Peter Maydell
#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4354 62698be3 Peter Maydell
#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4355 62698be3 Peter Maydell
#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4356 62698be3 Peter Maydell
#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4357 62698be3 Peter Maydell
4358 62698be3 Peter Maydell
static const uint8_t neon_3r_sizes[] = {
4359 62698be3 Peter Maydell
    [NEON_3R_VHADD] = 0x7,
4360 62698be3 Peter Maydell
    [NEON_3R_VQADD] = 0xf,
4361 62698be3 Peter Maydell
    [NEON_3R_VRHADD] = 0x7,
4362 62698be3 Peter Maydell
    [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4363 62698be3 Peter Maydell
    [NEON_3R_VHSUB] = 0x7,
4364 62698be3 Peter Maydell
    [NEON_3R_VQSUB] = 0xf,
4365 62698be3 Peter Maydell
    [NEON_3R_VCGT] = 0x7,
4366 62698be3 Peter Maydell
    [NEON_3R_VCGE] = 0x7,
4367 62698be3 Peter Maydell
    [NEON_3R_VSHL] = 0xf,
4368 62698be3 Peter Maydell
    [NEON_3R_VQSHL] = 0xf,
4369 62698be3 Peter Maydell
    [NEON_3R_VRSHL] = 0xf,
4370 62698be3 Peter Maydell
    [NEON_3R_VQRSHL] = 0xf,
4371 62698be3 Peter Maydell
    [NEON_3R_VMAX] = 0x7,
4372 62698be3 Peter Maydell
    [NEON_3R_VMIN] = 0x7,
4373 62698be3 Peter Maydell
    [NEON_3R_VABD] = 0x7,
4374 62698be3 Peter Maydell
    [NEON_3R_VABA] = 0x7,
4375 62698be3 Peter Maydell
    [NEON_3R_VADD_VSUB] = 0xf,
4376 62698be3 Peter Maydell
    [NEON_3R_VTST_VCEQ] = 0x7,
4377 62698be3 Peter Maydell
    [NEON_3R_VML] = 0x7,
4378 62698be3 Peter Maydell
    [NEON_3R_VMUL] = 0x7,
4379 62698be3 Peter Maydell
    [NEON_3R_VPMAX] = 0x7,
4380 62698be3 Peter Maydell
    [NEON_3R_VPMIN] = 0x7,
4381 62698be3 Peter Maydell
    [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4382 62698be3 Peter Maydell
    [NEON_3R_VPADD] = 0x7,
4383 62698be3 Peter Maydell
    [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4384 62698be3 Peter Maydell
    [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4385 62698be3 Peter Maydell
    [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4386 62698be3 Peter Maydell
    [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4387 62698be3 Peter Maydell
    [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4388 62698be3 Peter Maydell
    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
4389 62698be3 Peter Maydell
};
4390 62698be3 Peter Maydell
4391 600b828c Peter Maydell
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
4392 600b828c Peter Maydell
 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4393 600b828c Peter Maydell
 * table A7-13.
4394 600b828c Peter Maydell
 */
4395 600b828c Peter Maydell
#define NEON_2RM_VREV64 0
4396 600b828c Peter Maydell
#define NEON_2RM_VREV32 1
4397 600b828c Peter Maydell
#define NEON_2RM_VREV16 2
4398 600b828c Peter Maydell
#define NEON_2RM_VPADDL 4
4399 600b828c Peter Maydell
#define NEON_2RM_VPADDL_U 5
4400 600b828c Peter Maydell
#define NEON_2RM_VCLS 8
4401 600b828c Peter Maydell
#define NEON_2RM_VCLZ 9
4402 600b828c Peter Maydell
#define NEON_2RM_VCNT 10
4403 600b828c Peter Maydell
#define NEON_2RM_VMVN 11
4404 600b828c Peter Maydell
#define NEON_2RM_VPADAL 12
4405 600b828c Peter Maydell
#define NEON_2RM_VPADAL_U 13
4406 600b828c Peter Maydell
#define NEON_2RM_VQABS 14
4407 600b828c Peter Maydell
#define NEON_2RM_VQNEG 15
4408 600b828c Peter Maydell
#define NEON_2RM_VCGT0 16
4409 600b828c Peter Maydell
#define NEON_2RM_VCGE0 17
4410 600b828c Peter Maydell
#define NEON_2RM_VCEQ0 18
4411 600b828c Peter Maydell
#define NEON_2RM_VCLE0 19
4412 600b828c Peter Maydell
#define NEON_2RM_VCLT0 20
4413 600b828c Peter Maydell
#define NEON_2RM_VABS 22
4414 600b828c Peter Maydell
#define NEON_2RM_VNEG 23
4415 600b828c Peter Maydell
#define NEON_2RM_VCGT0_F 24
4416 600b828c Peter Maydell
#define NEON_2RM_VCGE0_F 25
4417 600b828c Peter Maydell
#define NEON_2RM_VCEQ0_F 26
4418 600b828c Peter Maydell
#define NEON_2RM_VCLE0_F 27
4419 600b828c Peter Maydell
#define NEON_2RM_VCLT0_F 28
4420 600b828c Peter Maydell
#define NEON_2RM_VABS_F 30
4421 600b828c Peter Maydell
#define NEON_2RM_VNEG_F 31
4422 600b828c Peter Maydell
#define NEON_2RM_VSWP 32
4423 600b828c Peter Maydell
#define NEON_2RM_VTRN 33
4424 600b828c Peter Maydell
#define NEON_2RM_VUZP 34
4425 600b828c Peter Maydell
#define NEON_2RM_VZIP 35
4426 600b828c Peter Maydell
#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4427 600b828c Peter Maydell
#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4428 600b828c Peter Maydell
#define NEON_2RM_VSHLL 38
4429 600b828c Peter Maydell
#define NEON_2RM_VCVT_F16_F32 44
4430 600b828c Peter Maydell
#define NEON_2RM_VCVT_F32_F16 46
4431 600b828c Peter Maydell
#define NEON_2RM_VRECPE 56
4432 600b828c Peter Maydell
#define NEON_2RM_VRSQRTE 57
4433 600b828c Peter Maydell
#define NEON_2RM_VRECPE_F 58
4434 600b828c Peter Maydell
#define NEON_2RM_VRSQRTE_F 59
4435 600b828c Peter Maydell
#define NEON_2RM_VCVT_FS 60
4436 600b828c Peter Maydell
#define NEON_2RM_VCVT_FU 61
4437 600b828c Peter Maydell
#define NEON_2RM_VCVT_SF 62
4438 600b828c Peter Maydell
#define NEON_2RM_VCVT_UF 63
4439 600b828c Peter Maydell
4440 600b828c Peter Maydell
static int neon_2rm_is_float_op(int op)
4441 600b828c Peter Maydell
{
4442 600b828c Peter Maydell
    /* Return true if this neon 2reg-misc op is float-to-float */
4443 600b828c Peter Maydell
    return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4444 600b828c Peter Maydell
            op >= NEON_2RM_VRECPE_F);
4445 600b828c Peter Maydell
}
4446 600b828c Peter Maydell
4447 600b828c Peter Maydell
/* Each entry in this array has bit n set if the insn allows
4448 600b828c Peter Maydell
 * size value n (otherwise it will UNDEF). Since unallocated
4449 600b828c Peter Maydell
 * op values will have no bits set they always UNDEF.
4450 600b828c Peter Maydell
 */
4451 600b828c Peter Maydell
static const uint8_t neon_2rm_sizes[] = {
4452 600b828c Peter Maydell
    [NEON_2RM_VREV64] = 0x7,
4453 600b828c Peter Maydell
    [NEON_2RM_VREV32] = 0x3,
4454 600b828c Peter Maydell
    [NEON_2RM_VREV16] = 0x1,
4455 600b828c Peter Maydell
    [NEON_2RM_VPADDL] = 0x7,
4456 600b828c Peter Maydell
    [NEON_2RM_VPADDL_U] = 0x7,
4457 600b828c Peter Maydell
    [NEON_2RM_VCLS] = 0x7,
4458 600b828c Peter Maydell
    [NEON_2RM_VCLZ] = 0x7,
4459 600b828c Peter Maydell
    [NEON_2RM_VCNT] = 0x1,
4460 600b828c Peter Maydell
    [NEON_2RM_VMVN] = 0x1,
4461 600b828c Peter Maydell
    [NEON_2RM_VPADAL] = 0x7,
4462 600b828c Peter Maydell
    [NEON_2RM_VPADAL_U] = 0x7,
4463 600b828c Peter Maydell
    [NEON_2RM_VQABS] = 0x7,
4464 600b828c Peter Maydell
    [NEON_2RM_VQNEG] = 0x7,
4465 600b828c Peter Maydell
    [NEON_2RM_VCGT0] = 0x7,
4466 600b828c Peter Maydell
    [NEON_2RM_VCGE0] = 0x7,
4467 600b828c Peter Maydell
    [NEON_2RM_VCEQ0] = 0x7,
4468 600b828c Peter Maydell
    [NEON_2RM_VCLE0] = 0x7,
4469 600b828c Peter Maydell
    [NEON_2RM_VCLT0] = 0x7,
4470 600b828c Peter Maydell
    [NEON_2RM_VABS] = 0x7,
4471 600b828c Peter Maydell
    [NEON_2RM_VNEG] = 0x7,
4472 600b828c Peter Maydell
    [NEON_2RM_VCGT0_F] = 0x4,
4473 600b828c Peter Maydell
    [NEON_2RM_VCGE0_F] = 0x4,
4474 600b828c Peter Maydell
    [NEON_2RM_VCEQ0_F] = 0x4,
4475 600b828c Peter Maydell
    [NEON_2RM_VCLE0_F] = 0x4,
4476 600b828c Peter Maydell
    [NEON_2RM_VCLT0_F] = 0x4,
4477 600b828c Peter Maydell
    [NEON_2RM_VABS_F] = 0x4,
4478 600b828c Peter Maydell
    [NEON_2RM_VNEG_F] = 0x4,
4479 600b828c Peter Maydell
    [NEON_2RM_VSWP] = 0x1,
4480 600b828c Peter Maydell
    [NEON_2RM_VTRN] = 0x7,
4481 600b828c Peter Maydell
    [NEON_2RM_VUZP] = 0x7,
4482 600b828c Peter Maydell
    [NEON_2RM_VZIP] = 0x7,
4483 600b828c Peter Maydell
    [NEON_2RM_VMOVN] = 0x7,
4484 600b828c Peter Maydell
    [NEON_2RM_VQMOVN] = 0x7,
4485 600b828c Peter Maydell
    [NEON_2RM_VSHLL] = 0x7,
4486 600b828c Peter Maydell
    [NEON_2RM_VCVT_F16_F32] = 0x2,
4487 600b828c Peter Maydell
    [NEON_2RM_VCVT_F32_F16] = 0x2,
4488 600b828c Peter Maydell
    [NEON_2RM_VRECPE] = 0x4,
4489 600b828c Peter Maydell
    [NEON_2RM_VRSQRTE] = 0x4,
4490 600b828c Peter Maydell
    [NEON_2RM_VRECPE_F] = 0x4,
4491 600b828c Peter Maydell
    [NEON_2RM_VRSQRTE_F] = 0x4,
4492 600b828c Peter Maydell
    [NEON_2RM_VCVT_FS] = 0x4,
4493 600b828c Peter Maydell
    [NEON_2RM_VCVT_FU] = 0x4,
4494 600b828c Peter Maydell
    [NEON_2RM_VCVT_SF] = 0x4,
4495 600b828c Peter Maydell
    [NEON_2RM_VCVT_UF] = 0x4,
4496 600b828c Peter Maydell
};
4497 600b828c Peter Maydell
4498 9ee6e8bb pbrook
/* Translate a NEON data processing instruction.  Return nonzero if the
4499 9ee6e8bb pbrook
   instruction is invalid.
4500 ad69471c pbrook
   We process data in a mixture of 32-bit and 64-bit chunks.
4501 ad69471c pbrook
   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
4502 2c0262af bellard
4503 9ee6e8bb pbrook
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4504 9ee6e8bb pbrook
{
4505 9ee6e8bb pbrook
    int op;
4506 9ee6e8bb pbrook
    int q;
4507 9ee6e8bb pbrook
    int rd, rn, rm;
4508 9ee6e8bb pbrook
    int size;
4509 9ee6e8bb pbrook
    int shift;
4510 9ee6e8bb pbrook
    int pass;
4511 9ee6e8bb pbrook
    int count;
4512 9ee6e8bb pbrook
    int pairwise;
4513 9ee6e8bb pbrook
    int u;
4514 ca9a32e4 Juha Riihimäki
    uint32_t imm, mask;
4515 b75263d6 Juha Riihimäki
    TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4516 a7812ae4 pbrook
    TCGv_i64 tmp64;
4517 9ee6e8bb pbrook
4518 5df8bac1 Peter Maydell
    if (!s->vfp_enabled)
4519 9ee6e8bb pbrook
      return 1;
4520 9ee6e8bb pbrook
    q = (insn & (1 << 6)) != 0;
4521 9ee6e8bb pbrook
    u = (insn >> 24) & 1;
4522 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
4523 9ee6e8bb pbrook
    VFP_DREG_N(rn, insn);
4524 9ee6e8bb pbrook
    VFP_DREG_M(rm, insn);
4525 9ee6e8bb pbrook
    size = (insn >> 20) & 3;
4526 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
4527 9ee6e8bb pbrook
        /* Three register same length.  */
4528 9ee6e8bb pbrook
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4529 62698be3 Peter Maydell
        /* Catch invalid op and bad size combinations: UNDEF */
4530 62698be3 Peter Maydell
        if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4531 62698be3 Peter Maydell
            return 1;
4532 62698be3 Peter Maydell
        }
4533 25f84f79 Peter Maydell
        /* All insns of this form UNDEF for either this condition or the
4534 25f84f79 Peter Maydell
         * superset of cases "Q==1"; we catch the latter later.
4535 25f84f79 Peter Maydell
         */
4536 25f84f79 Peter Maydell
        if (q && ((rd | rn | rm) & 1)) {
4537 25f84f79 Peter Maydell
            return 1;
4538 25f84f79 Peter Maydell
        }
4539 62698be3 Peter Maydell
        if (size == 3 && op != NEON_3R_LOGIC) {
4540 62698be3 Peter Maydell
            /* 64-bit element instructions. */
4541 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
4542 ad69471c pbrook
                neon_load_reg64(cpu_V0, rn + pass);
4543 ad69471c pbrook
                neon_load_reg64(cpu_V1, rm + pass);
4544 9ee6e8bb pbrook
                switch (op) {
4545 62698be3 Peter Maydell
                case NEON_3R_VQADD:
4546 9ee6e8bb pbrook
                    if (u) {
4547 2a3f75b4 Peter Maydell
                        gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
4548 2c0262af bellard
                    } else {
4549 2a3f75b4 Peter Maydell
                        gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
4550 2c0262af bellard
                    }
4551 9ee6e8bb pbrook
                    break;
4552 62698be3 Peter Maydell
                case NEON_3R_VQSUB:
4553 9ee6e8bb pbrook
                    if (u) {
4554 2a3f75b4 Peter Maydell
                        gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
4555 ad69471c pbrook
                    } else {
4556 2a3f75b4 Peter Maydell
                        gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
4557 ad69471c pbrook
                    }
4558 ad69471c pbrook
                    break;
4559 62698be3 Peter Maydell
                case NEON_3R_VSHL:
4560 ad69471c pbrook
                    if (u) {
4561 ad69471c pbrook
                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4562 ad69471c pbrook
                    } else {
4563 ad69471c pbrook
                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4564 ad69471c pbrook
                    }
4565 ad69471c pbrook
                    break;
4566 62698be3 Peter Maydell
                case NEON_3R_VQSHL:
4567 ad69471c pbrook
                    if (u) {
4568 2a3f75b4 Peter Maydell
                        gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
4569 ad69471c pbrook
                    } else {
4570 2a3f75b4 Peter Maydell
                        gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
4571 ad69471c pbrook
                    }
4572 ad69471c pbrook
                    break;
4573 62698be3 Peter Maydell
                case NEON_3R_VRSHL:
4574 ad69471c pbrook
                    if (u) {
4575 ad69471c pbrook
                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4576 1e8d4eec bellard
                    } else {
4577 ad69471c pbrook
                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4578 ad69471c pbrook
                    }
4579 ad69471c pbrook
                    break;
4580 62698be3 Peter Maydell
                case NEON_3R_VQRSHL:
4581 ad69471c pbrook
                    if (u) {
4582 2a3f75b4 Peter Maydell
                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
4583 ad69471c pbrook
                    } else {
4584 2a3f75b4 Peter Maydell
                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
4585 1e8d4eec bellard
                    }
4586 9ee6e8bb pbrook
                    break;
4587 62698be3 Peter Maydell
                case NEON_3R_VADD_VSUB:
4588 9ee6e8bb pbrook
                    if (u) {
4589 ad69471c pbrook
                        tcg_gen_sub_i64(CPU_V001);
4590 9ee6e8bb pbrook
                    } else {
4591 ad69471c pbrook
                        tcg_gen_add_i64(CPU_V001);
4592 9ee6e8bb pbrook
                    }
4593 9ee6e8bb pbrook
                    break;
4594 9ee6e8bb pbrook
                default:
4595 9ee6e8bb pbrook
                    abort();
4596 2c0262af bellard
                }
4597 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd + pass);
4598 2c0262af bellard
            }
4599 9ee6e8bb pbrook
            return 0;
4600 2c0262af bellard
        }
4601 25f84f79 Peter Maydell
        pairwise = 0;
4602 9ee6e8bb pbrook
        switch (op) {
4603 62698be3 Peter Maydell
        case NEON_3R_VSHL:
4604 62698be3 Peter Maydell
        case NEON_3R_VQSHL:
4605 62698be3 Peter Maydell
        case NEON_3R_VRSHL:
4606 62698be3 Peter Maydell
        case NEON_3R_VQRSHL:
4607 9ee6e8bb pbrook
            {
4608 ad69471c pbrook
                int rtmp;
4609 ad69471c pbrook
                /* Shift instruction operands are reversed.  */
4610 ad69471c pbrook
                rtmp = rn;
4611 9ee6e8bb pbrook
                rn = rm;
4612 ad69471c pbrook
                rm = rtmp;
4613 9ee6e8bb pbrook
            }
4614 2c0262af bellard
            break;
4615 25f84f79 Peter Maydell
        case NEON_3R_VPADD:
4616 25f84f79 Peter Maydell
            if (u) {
4617 25f84f79 Peter Maydell
                return 1;
4618 25f84f79 Peter Maydell
            }
4619 25f84f79 Peter Maydell
            /* Fall through */
4620 62698be3 Peter Maydell
        case NEON_3R_VPMAX:
4621 62698be3 Peter Maydell
        case NEON_3R_VPMIN:
4622 9ee6e8bb pbrook
            pairwise = 1;
4623 2c0262af bellard
            break;
4624 25f84f79 Peter Maydell
        case NEON_3R_FLOAT_ARITH:
4625 25f84f79 Peter Maydell
            pairwise = (u && size < 2); /* if VPADD (float) */
4626 25f84f79 Peter Maydell
            break;
4627 25f84f79 Peter Maydell
        case NEON_3R_FLOAT_MINMAX:
4628 25f84f79 Peter Maydell
            pairwise = u; /* if VPMIN/VPMAX (float) */
4629 25f84f79 Peter Maydell
            break;
4630 25f84f79 Peter Maydell
        case NEON_3R_FLOAT_CMP:
4631 25f84f79 Peter Maydell
            if (!u && size) {
4632 25f84f79 Peter Maydell
                /* no encoding for U=0 C=1x */
4633 25f84f79 Peter Maydell
                return 1;
4634 25f84f79 Peter Maydell
            }
4635 25f84f79 Peter Maydell
            break;
4636 25f84f79 Peter Maydell
        case NEON_3R_FLOAT_ACMP:
4637 25f84f79 Peter Maydell
            if (!u) {
4638 25f84f79 Peter Maydell
                return 1;
4639 25f84f79 Peter Maydell
            }
4640 25f84f79 Peter Maydell
            break;
4641 25f84f79 Peter Maydell
        case NEON_3R_VRECPS_VRSQRTS:
4642 25f84f79 Peter Maydell
            if (u) {
4643 25f84f79 Peter Maydell
                return 1;
4644 25f84f79 Peter Maydell
            }
4645 2c0262af bellard
            break;
4646 25f84f79 Peter Maydell
        case NEON_3R_VMUL:
4647 25f84f79 Peter Maydell
            if (u && (size != 0)) {
4648 25f84f79 Peter Maydell
                /* UNDEF on invalid size for polynomial subcase */
4649 25f84f79 Peter Maydell
                return 1;
4650 25f84f79 Peter Maydell
            }
4651 2c0262af bellard
            break;
4652 9ee6e8bb pbrook
        default:
4653 2c0262af bellard
            break;
4654 9ee6e8bb pbrook
        }
4655 dd8fbd78 Filip Navara
4656 25f84f79 Peter Maydell
        if (pairwise && q) {
4657 25f84f79 Peter Maydell
            /* All the pairwise insns UNDEF if Q is set */
4658 25f84f79 Peter Maydell
            return 1;
4659 25f84f79 Peter Maydell
        }
4660 25f84f79 Peter Maydell
4661 9ee6e8bb pbrook
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
4662 9ee6e8bb pbrook
4663 9ee6e8bb pbrook
        if (pairwise) {
4664 9ee6e8bb pbrook
            /* Pairwise.  */
4665 a5a14945 Juha Riihimäki
            if (pass < 1) {
4666 a5a14945 Juha Riihimäki
                tmp = neon_load_reg(rn, 0);
4667 a5a14945 Juha Riihimäki
                tmp2 = neon_load_reg(rn, 1);
4668 9ee6e8bb pbrook
            } else {
4669 a5a14945 Juha Riihimäki
                tmp = neon_load_reg(rm, 0);
4670 a5a14945 Juha Riihimäki
                tmp2 = neon_load_reg(rm, 1);
4671 9ee6e8bb pbrook
            }
4672 9ee6e8bb pbrook
        } else {
4673 9ee6e8bb pbrook
            /* Elementwise.  */
4674 dd8fbd78 Filip Navara
            tmp = neon_load_reg(rn, pass);
4675 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rm, pass);
4676 9ee6e8bb pbrook
        }
4677 9ee6e8bb pbrook
        switch (op) {
4678 62698be3 Peter Maydell
        case NEON_3R_VHADD:
4679 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hadd);
4680 9ee6e8bb pbrook
            break;
4681 62698be3 Peter Maydell
        case NEON_3R_VQADD:
4682 2a3f75b4 Peter Maydell
            GEN_NEON_INTEGER_OP(qadd);
4683 2c0262af bellard
            break;
4684 62698be3 Peter Maydell
        case NEON_3R_VRHADD:
4685 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(rhadd);
4686 2c0262af bellard
            break;
4687 62698be3 Peter Maydell
        case NEON_3R_LOGIC: /* Logic ops.  */
4688 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4689 9ee6e8bb pbrook
            case 0: /* VAND */
4690 dd8fbd78 Filip Navara
                tcg_gen_and_i32(tmp, tmp, tmp2);
4691 9ee6e8bb pbrook
                break;
4692 9ee6e8bb pbrook
            case 1: /* BIC */
4693 f669df27 Aurelien Jarno
                tcg_gen_andc_i32(tmp, tmp, tmp2);
4694 9ee6e8bb pbrook
                break;
4695 9ee6e8bb pbrook
            case 2: /* VORR */
4696 dd8fbd78 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
4697 9ee6e8bb pbrook
                break;
4698 9ee6e8bb pbrook
            case 3: /* VORN */
4699 f669df27 Aurelien Jarno
                tcg_gen_orc_i32(tmp, tmp, tmp2);
4700 9ee6e8bb pbrook
                break;
4701 9ee6e8bb pbrook
            case 4: /* VEOR */
4702 dd8fbd78 Filip Navara
                tcg_gen_xor_i32(tmp, tmp, tmp2);
4703 9ee6e8bb pbrook
                break;
4704 9ee6e8bb pbrook
            case 5: /* VBSL */
4705 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4706 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4707 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4708 9ee6e8bb pbrook
                break;
4709 9ee6e8bb pbrook
            case 6: /* VBIT */
4710 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4711 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4712 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4713 9ee6e8bb pbrook
                break;
4714 9ee6e8bb pbrook
            case 7: /* VBIF */
4715 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4716 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4717 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4718 9ee6e8bb pbrook
                break;
4719 2c0262af bellard
            }
4720 2c0262af bellard
            break;
4721 62698be3 Peter Maydell
        case NEON_3R_VHSUB:
4722 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hsub);
4723 9ee6e8bb pbrook
            break;
4724 62698be3 Peter Maydell
        case NEON_3R_VQSUB:
4725 2a3f75b4 Peter Maydell
            GEN_NEON_INTEGER_OP(qsub);
4726 2c0262af bellard
            break;
4727 62698be3 Peter Maydell
        case NEON_3R_VCGT:
4728 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cgt);
4729 9ee6e8bb pbrook
            break;
4730 62698be3 Peter Maydell
        case NEON_3R_VCGE:
4731 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cge);
4732 9ee6e8bb pbrook
            break;
4733 62698be3 Peter Maydell
        case NEON_3R_VSHL:
4734 ad69471c pbrook
            GEN_NEON_INTEGER_OP(shl);
4735 2c0262af bellard
            break;
4736 62698be3 Peter Maydell
        case NEON_3R_VQSHL:
4737 2a3f75b4 Peter Maydell
            GEN_NEON_INTEGER_OP(qshl);
4738 2c0262af bellard
            break;
4739 62698be3 Peter Maydell
        case NEON_3R_VRSHL:
4740 ad69471c pbrook
            GEN_NEON_INTEGER_OP(rshl);
4741 2c0262af bellard
            break;
4742 62698be3 Peter Maydell
        case NEON_3R_VQRSHL:
4743 2a3f75b4 Peter Maydell
            GEN_NEON_INTEGER_OP(qrshl);
4744 9ee6e8bb pbrook
            break;
4745 62698be3 Peter Maydell
        case NEON_3R_VMAX:
4746 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(max);
4747 9ee6e8bb pbrook
            break;
4748 62698be3 Peter Maydell
        case NEON_3R_VMIN:
4749 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(min);
4750 9ee6e8bb pbrook
            break;
4751 62698be3 Peter Maydell
        case NEON_3R_VABD:
4752 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4753 9ee6e8bb pbrook
            break;
4754 62698be3 Peter Maydell
        case NEON_3R_VABA:
4755 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4756 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
4757 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4758 dd8fbd78 Filip Navara
            gen_neon_add(size, tmp, tmp2);
4759 9ee6e8bb pbrook
            break;
4760 62698be3 Peter Maydell
        case NEON_3R_VADD_VSUB:
4761 9ee6e8bb pbrook
            if (!u) { /* VADD */
4762 62698be3 Peter Maydell
                gen_neon_add(size, tmp, tmp2);
4763 9ee6e8bb pbrook
            } else { /* VSUB */
4764 9ee6e8bb pbrook
                switch (size) {
4765 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4766 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4767 dd8fbd78 Filip Navara
                case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4768 62698be3 Peter Maydell
                default: abort();
4769 9ee6e8bb pbrook
                }
4770 9ee6e8bb pbrook
            }
4771 9ee6e8bb pbrook
            break;
4772 62698be3 Peter Maydell
        case NEON_3R_VTST_VCEQ:
4773 9ee6e8bb pbrook
            if (!u) { /* VTST */
4774 9ee6e8bb pbrook
                switch (size) {
4775 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4776 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4777 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4778 62698be3 Peter Maydell
                default: abort();
4779 9ee6e8bb pbrook
                }
4780 9ee6e8bb pbrook
            } else { /* VCEQ */
4781 9ee6e8bb pbrook
                switch (size) {
4782 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4783 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4784 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4785 62698be3 Peter Maydell
                default: abort();
4786 9ee6e8bb pbrook
                }
4787 9ee6e8bb pbrook
            }
4788 9ee6e8bb pbrook
            break;
4789 62698be3 Peter Maydell
        case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4790 9ee6e8bb pbrook
            switch (size) {
4791 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4792 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4793 dd8fbd78 Filip Navara
            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4794 62698be3 Peter Maydell
            default: abort();
4795 9ee6e8bb pbrook
            }
4796 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
4797 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4798 9ee6e8bb pbrook
            if (u) { /* VMLS */
4799 dd8fbd78 Filip Navara
                gen_neon_rsb(size, tmp, tmp2);
4800 9ee6e8bb pbrook
            } else { /* VMLA */
4801 dd8fbd78 Filip Navara
                gen_neon_add(size, tmp, tmp2);
4802 9ee6e8bb pbrook
            }
4803 9ee6e8bb pbrook
            break;
4804 62698be3 Peter Maydell
        case NEON_3R_VMUL:
4805 9ee6e8bb pbrook
            if (u) { /* polynomial */
4806 dd8fbd78 Filip Navara
                gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4807 9ee6e8bb pbrook
            } else { /* Integer */
4808 9ee6e8bb pbrook
                switch (size) {
4809 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4810 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4811 dd8fbd78 Filip Navara
                case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4812 62698be3 Peter Maydell
                default: abort();
4813 9ee6e8bb pbrook
                }
4814 9ee6e8bb pbrook
            }
4815 9ee6e8bb pbrook
            break;
4816 62698be3 Peter Maydell
        case NEON_3R_VPMAX:
4817 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmax);
4818 9ee6e8bb pbrook
            break;
4819 62698be3 Peter Maydell
        case NEON_3R_VPMIN:
4820 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmin);
4821 9ee6e8bb pbrook
            break;
4822 62698be3 Peter Maydell
        case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
4823 9ee6e8bb pbrook
            if (!u) { /* VQDMULH */
4824 9ee6e8bb pbrook
                switch (size) {
4825 2a3f75b4 Peter Maydell
                case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
4826 2a3f75b4 Peter Maydell
                case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
4827 62698be3 Peter Maydell
                default: abort();
4828 9ee6e8bb pbrook
                }
4829 62698be3 Peter Maydell
            } else { /* VQRDMULH */
4830 9ee6e8bb pbrook
                switch (size) {
4831 2a3f75b4 Peter Maydell
                case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
4832 2a3f75b4 Peter Maydell
                case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
4833 62698be3 Peter Maydell
                default: abort();
4834 9ee6e8bb pbrook
                }
4835 9ee6e8bb pbrook
            }
4836 9ee6e8bb pbrook
            break;
4837 62698be3 Peter Maydell
        case NEON_3R_VPADD:
4838 9ee6e8bb pbrook
            switch (size) {
4839 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4840 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4841 dd8fbd78 Filip Navara
            case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4842 62698be3 Peter Maydell
            default: abort();
4843 9ee6e8bb pbrook
            }
4844 9ee6e8bb pbrook
            break;
4845 62698be3 Peter Maydell
        case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
4846 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4847 9ee6e8bb pbrook
            case 0: /* VADD */
4848 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4849 9ee6e8bb pbrook
                break;
4850 9ee6e8bb pbrook
            case 2: /* VSUB */
4851 dd8fbd78 Filip Navara
                gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4852 9ee6e8bb pbrook
                break;
4853 9ee6e8bb pbrook
            case 4: /* VPADD */
4854 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4855 9ee6e8bb pbrook
                break;
4856 9ee6e8bb pbrook
            case 6: /* VABD */
4857 dd8fbd78 Filip Navara
                gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4858 9ee6e8bb pbrook
                break;
4859 9ee6e8bb pbrook
            default:
4860 62698be3 Peter Maydell
                abort();
4861 9ee6e8bb pbrook
            }
4862 9ee6e8bb pbrook
            break;
4863 62698be3 Peter Maydell
        case NEON_3R_FLOAT_MULTIPLY:
4864 dd8fbd78 Filip Navara
            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4865 9ee6e8bb pbrook
            if (!u) {
4866 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
4867 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rd, pass);
4868 9ee6e8bb pbrook
                if (size == 0) {
4869 dd8fbd78 Filip Navara
                    gen_helper_neon_add_f32(tmp, tmp, tmp2);
4870 9ee6e8bb pbrook
                } else {
4871 dd8fbd78 Filip Navara
                    gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4872 9ee6e8bb pbrook
                }
4873 9ee6e8bb pbrook
            }
4874 9ee6e8bb pbrook
            break;
4875 62698be3 Peter Maydell
        case NEON_3R_FLOAT_CMP:
4876 9ee6e8bb pbrook
            if (!u) {
4877 dd8fbd78 Filip Navara
                gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4878 b5ff1b31 bellard
            } else {
4879 9ee6e8bb pbrook
                if (size == 0)
4880 dd8fbd78 Filip Navara
                    gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4881 9ee6e8bb pbrook
                else
4882 dd8fbd78 Filip Navara
                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4883 b5ff1b31 bellard
            }
4884 2c0262af bellard
            break;
4885 62698be3 Peter Maydell
        case NEON_3R_FLOAT_ACMP:
4886 9ee6e8bb pbrook
            if (size == 0)
4887 dd8fbd78 Filip Navara
                gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4888 9ee6e8bb pbrook
            else
4889 dd8fbd78 Filip Navara
                gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4890 2c0262af bellard
            break;
4891 62698be3 Peter Maydell
        case NEON_3R_FLOAT_MINMAX:
4892 9ee6e8bb pbrook
            if (size == 0)
4893 dd8fbd78 Filip Navara
                gen_helper_neon_max_f32(tmp, tmp, tmp2);
4894 9ee6e8bb pbrook
            else
4895 dd8fbd78 Filip Navara
                gen_helper_neon_min_f32(tmp, tmp, tmp2);
4896 9ee6e8bb pbrook
            break;
4897 62698be3 Peter Maydell
        case NEON_3R_VRECPS_VRSQRTS:
4898 9ee6e8bb pbrook
            if (size == 0)
4899 dd8fbd78 Filip Navara
                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4900 9ee6e8bb pbrook
            else
4901 dd8fbd78 Filip Navara
                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4902 2c0262af bellard
            break;
4903 9ee6e8bb pbrook
        default:
4904 9ee6e8bb pbrook
            abort();
4905 2c0262af bellard
        }
4906 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
4907 dd8fbd78 Filip Navara
4908 9ee6e8bb pbrook
        /* Save the result.  For elementwise operations we can put it
4909 9ee6e8bb pbrook
           straight into the destination register.  For pairwise operations
4910 9ee6e8bb pbrook
           we have to be careful to avoid clobbering the source operands.  */
4911 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4912 dd8fbd78 Filip Navara
            neon_store_scratch(pass, tmp);
4913 9ee6e8bb pbrook
        } else {
4914 dd8fbd78 Filip Navara
            neon_store_reg(rd, pass, tmp);
4915 9ee6e8bb pbrook
        }
4916 9ee6e8bb pbrook
4917 9ee6e8bb pbrook
        } /* for pass */
4918 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4919 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4920 dd8fbd78 Filip Navara
                tmp = neon_load_scratch(pass);
4921 dd8fbd78 Filip Navara
                neon_store_reg(rd, pass, tmp);
4922 9ee6e8bb pbrook
            }
4923 9ee6e8bb pbrook
        }
4924 ad69471c pbrook
        /* End of 3 register same size operations.  */
4925 9ee6e8bb pbrook
    } else if (insn & (1 << 4)) {
4926 9ee6e8bb pbrook
        if ((insn & 0x00380080) != 0) {
4927 9ee6e8bb pbrook
            /* Two registers and shift.  */
4928 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4929 9ee6e8bb pbrook
            if (insn & (1 << 7)) {
4930 cc13115b Peter Maydell
                /* 64-bit shift. */
4931 cc13115b Peter Maydell
                if (op > 7) {
4932 cc13115b Peter Maydell
                    return 1;
4933 cc13115b Peter Maydell
                }
4934 9ee6e8bb pbrook
                size = 3;
4935 9ee6e8bb pbrook
            } else {
4936 9ee6e8bb pbrook
                size = 2;
4937 9ee6e8bb pbrook
                while ((insn & (1 << (size + 19))) == 0)
4938 9ee6e8bb pbrook
                    size--;
4939 9ee6e8bb pbrook
            }
4940 9ee6e8bb pbrook
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4941 9ee6e8bb pbrook
            /* To avoid excessive dumplication of ops we implement shift
4942 9ee6e8bb pbrook
               by immediate using the variable shift operations.  */
4943 9ee6e8bb pbrook
            if (op < 8) {
4944 9ee6e8bb pbrook
                /* Shift by immediate:
4945 9ee6e8bb pbrook
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4946 cc13115b Peter Maydell
                if (q && ((rd | rm) & 1)) {
4947 cc13115b Peter Maydell
                    return 1;
4948 cc13115b Peter Maydell
                }
4949 cc13115b Peter Maydell
                if (!u && (op == 4 || op == 6)) {
4950 cc13115b Peter Maydell
                    return 1;
4951 cc13115b Peter Maydell
                }
4952 9ee6e8bb pbrook
                /* Right shifts are encoded as N - shift, where N is the
4953 9ee6e8bb pbrook
                   element size in bits.  */
4954 9ee6e8bb pbrook
                if (op <= 4)
4955 9ee6e8bb pbrook
                    shift = shift - (1 << (size + 3));
4956 9ee6e8bb pbrook
                if (size == 3) {
4957 9ee6e8bb pbrook
                    count = q + 1;
4958 9ee6e8bb pbrook
                } else {
4959 9ee6e8bb pbrook
                    count = q ? 4: 2;
4960 9ee6e8bb pbrook
                }
4961 9ee6e8bb pbrook
                switch (size) {
4962 9ee6e8bb pbrook
                case 0:
4963 9ee6e8bb pbrook
                    imm = (uint8_t) shift;
4964 9ee6e8bb pbrook
                    imm |= imm << 8;
4965 9ee6e8bb pbrook
                    imm |= imm << 16;
4966 9ee6e8bb pbrook
                    break;
4967 9ee6e8bb pbrook
                case 1:
4968 9ee6e8bb pbrook
                    imm = (uint16_t) shift;
4969 9ee6e8bb pbrook
                    imm |= imm << 16;
4970 9ee6e8bb pbrook
                    break;
4971 9ee6e8bb pbrook
                case 2:
4972 9ee6e8bb pbrook
                case 3:
4973 9ee6e8bb pbrook
                    imm = shift;
4974 9ee6e8bb pbrook
                    break;
4975 9ee6e8bb pbrook
                default:
4976 9ee6e8bb pbrook
                    abort();
4977 9ee6e8bb pbrook
                }
4978 9ee6e8bb pbrook
4979 9ee6e8bb pbrook
                for (pass = 0; pass < count; pass++) {
4980 ad69471c pbrook
                    if (size == 3) {
4981 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
4982 ad69471c pbrook
                        tcg_gen_movi_i64(cpu_V1, imm);
4983 ad69471c pbrook
                        switch (op) {
4984 ad69471c pbrook
                        case 0:  /* VSHR */
4985 ad69471c pbrook
                        case 1:  /* VSRA */
4986 ad69471c pbrook
                            if (u)
4987 ad69471c pbrook
                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4988 9ee6e8bb pbrook
                            else
4989 ad69471c pbrook
                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4990 9ee6e8bb pbrook
                            break;
4991 ad69471c pbrook
                        case 2: /* VRSHR */
4992 ad69471c pbrook
                        case 3: /* VRSRA */
4993 ad69471c pbrook
                            if (u)
4994 ad69471c pbrook
                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4995 9ee6e8bb pbrook
                            else
4996 ad69471c pbrook
                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4997 9ee6e8bb pbrook
                            break;
4998 ad69471c pbrook
                        case 4: /* VSRI */
4999 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
5000 ad69471c pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5001 ad69471c pbrook
                            break;
5002 0322b26e Peter Maydell
                        case 6: /* VQSHLU */
5003 cc13115b Peter Maydell
                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
5004 ad69471c pbrook
                            break;
5005 0322b26e Peter Maydell
                        case 7: /* VQSHL */
5006 0322b26e Peter Maydell
                            if (u) {
5007 2a3f75b4 Peter Maydell
                                gen_helper_neon_qshl_u64(cpu_V0,
5008 0322b26e Peter Maydell
                                                         cpu_V0, cpu_V1);
5009 0322b26e Peter Maydell
                            } else {
5010 2a3f75b4 Peter Maydell
                                gen_helper_neon_qshl_s64(cpu_V0,
5011 0322b26e Peter Maydell
                                                         cpu_V0, cpu_V1);
5012 0322b26e Peter Maydell
                            }
5013 9ee6e8bb pbrook
                            break;
5014 9ee6e8bb pbrook
                        }
5015 ad69471c pbrook
                        if (op == 1 || op == 3) {
5016 ad69471c pbrook
                            /* Accumulate.  */
5017 5371cb81 Christophe Lyon
                            neon_load_reg64(cpu_V1, rd + pass);
5018 ad69471c pbrook
                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5019 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
5020 ad69471c pbrook
                            /* Insert */
5021 923e6509 Christophe Lyon
                            neon_load_reg64(cpu_V1, rd + pass);
5022 923e6509 Christophe Lyon
                            uint64_t mask;
5023 923e6509 Christophe Lyon
                            if (shift < -63 || shift > 63) {
5024 923e6509 Christophe Lyon
                                mask = 0;
5025 923e6509 Christophe Lyon
                            } else {
5026 923e6509 Christophe Lyon
                                if (op == 4) {
5027 923e6509 Christophe Lyon
                                    mask = 0xffffffffffffffffull >> -shift;
5028 923e6509 Christophe Lyon
                                } else {
5029 923e6509 Christophe Lyon
                                    mask = 0xffffffffffffffffull << shift;
5030 923e6509 Christophe Lyon
                                }
5031 923e6509 Christophe Lyon
                            }
5032 923e6509 Christophe Lyon
                            tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5033 923e6509 Christophe Lyon
                            tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5034 ad69471c pbrook
                        }
5035 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5036 ad69471c pbrook
                    } else { /* size < 3 */
5037 ad69471c pbrook
                        /* Operands in T0 and T1.  */
5038 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass);
5039 7d1b0095 Peter Maydell
                        tmp2 = tcg_temp_new_i32();
5040 dd8fbd78 Filip Navara
                        tcg_gen_movi_i32(tmp2, imm);
5041 ad69471c pbrook
                        switch (op) {
5042 ad69471c pbrook
                        case 0:  /* VSHR */
5043 ad69471c pbrook
                        case 1:  /* VSRA */
5044 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(shl);
5045 ad69471c pbrook
                            break;
5046 ad69471c pbrook
                        case 2: /* VRSHR */
5047 ad69471c pbrook
                        case 3: /* VRSRA */
5048 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(rshl);
5049 ad69471c pbrook
                            break;
5050 ad69471c pbrook
                        case 4: /* VSRI */
5051 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
5052 ad69471c pbrook
                            switch (size) {
5053 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5054 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5055 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5056 cc13115b Peter Maydell
                            default: abort();
5057 ad69471c pbrook
                            }
5058 ad69471c pbrook
                            break;
5059 0322b26e Peter Maydell
                        case 6: /* VQSHLU */
5060 ad69471c pbrook
                            switch (size) {
5061 0322b26e Peter Maydell
                            case 0:
5062 2a3f75b4 Peter Maydell
                                gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
5063 0322b26e Peter Maydell
                                break;
5064 0322b26e Peter Maydell
                            case 1:
5065 2a3f75b4 Peter Maydell
                                gen_helper_neon_qshlu_s16(tmp, tmp, tmp2);
5066 0322b26e Peter Maydell
                                break;
5067 0322b26e Peter Maydell
                            case 2:
5068 2a3f75b4 Peter Maydell
                                gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
5069 0322b26e Peter Maydell
                                break;
5070 0322b26e Peter Maydell
                            default:
5071 cc13115b Peter Maydell
                                abort();
5072 ad69471c pbrook
                            }
5073 ad69471c pbrook
                            break;
5074 0322b26e Peter Maydell
                        case 7: /* VQSHL */
5075 2a3f75b4 Peter Maydell
                            GEN_NEON_INTEGER_OP(qshl);
5076 0322b26e Peter Maydell
                            break;
5077 ad69471c pbrook
                        }
5078 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5079 ad69471c pbrook
5080 ad69471c pbrook
                        if (op == 1 || op == 3) {
5081 ad69471c pbrook
                            /* Accumulate.  */
5082 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5083 5371cb81 Christophe Lyon
                            gen_neon_add(size, tmp, tmp2);
5084 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
5085 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
5086 ad69471c pbrook
                            /* Insert */
5087 ad69471c pbrook
                            switch (size) {
5088 ad69471c pbrook
                            case 0:
5089 ad69471c pbrook
                                if (op == 4)
5090 ca9a32e4 Juha Riihimäki
                                    mask = 0xff >> -shift;
5091 ad69471c pbrook
                                else
5092 ca9a32e4 Juha Riihimäki
                                    mask = (uint8_t)(0xff << shift);
5093 ca9a32e4 Juha Riihimäki
                                mask |= mask << 8;
5094 ca9a32e4 Juha Riihimäki
                                mask |= mask << 16;
5095 ad69471c pbrook
                                break;
5096 ad69471c pbrook
                            case 1:
5097 ad69471c pbrook
                                if (op == 4)
5098 ca9a32e4 Juha Riihimäki
                                    mask = 0xffff >> -shift;
5099 ad69471c pbrook
                                else
5100 ca9a32e4 Juha Riihimäki
                                    mask = (uint16_t)(0xffff << shift);
5101 ca9a32e4 Juha Riihimäki
                                mask |= mask << 16;
5102 ad69471c pbrook
                                break;
5103 ad69471c pbrook
                            case 2:
5104 ca9a32e4 Juha Riihimäki
                                if (shift < -31 || shift > 31) {
5105 ca9a32e4 Juha Riihimäki
                                    mask = 0;
5106 ca9a32e4 Juha Riihimäki
                                } else {
5107 ca9a32e4 Juha Riihimäki
                                    if (op == 4)
5108 ca9a32e4 Juha Riihimäki
                                        mask = 0xffffffffu >> -shift;
5109 ca9a32e4 Juha Riihimäki
                                    else
5110 ca9a32e4 Juha Riihimäki
                                        mask = 0xffffffffu << shift;
5111 ca9a32e4 Juha Riihimäki
                                }
5112 ad69471c pbrook
                                break;
5113 ad69471c pbrook
                            default:
5114 ad69471c pbrook
                                abort();
5115 ad69471c pbrook
                            }
5116 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5117 ca9a32e4 Juha Riihimäki
                            tcg_gen_andi_i32(tmp, tmp, mask);
5118 ca9a32e4 Juha Riihimäki
                            tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5119 dd8fbd78 Filip Navara
                            tcg_gen_or_i32(tmp, tmp, tmp2);
5120 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
5121 ad69471c pbrook
                        }
5122 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
5123 9ee6e8bb pbrook
                    }
5124 9ee6e8bb pbrook
                } /* for pass */
5125 9ee6e8bb pbrook
            } else if (op < 10) {
5126 ad69471c pbrook
                /* Shift by immediate and narrow:
5127 9ee6e8bb pbrook
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
5128 0b36f4cd Christophe Lyon
                int input_unsigned = (op == 8) ? !u : u;
5129 cc13115b Peter Maydell
                if (rm & 1) {
5130 cc13115b Peter Maydell
                    return 1;
5131 cc13115b Peter Maydell
                }
5132 9ee6e8bb pbrook
                shift = shift - (1 << (size + 3));
5133 9ee6e8bb pbrook
                size++;
5134 92cdfaeb Peter Maydell
                if (size == 3) {
5135 a7812ae4 pbrook
                    tmp64 = tcg_const_i64(shift);
5136 92cdfaeb Peter Maydell
                    neon_load_reg64(cpu_V0, rm);
5137 92cdfaeb Peter Maydell
                    neon_load_reg64(cpu_V1, rm + 1);
5138 92cdfaeb Peter Maydell
                    for (pass = 0; pass < 2; pass++) {
5139 92cdfaeb Peter Maydell
                        TCGv_i64 in;
5140 92cdfaeb Peter Maydell
                        if (pass == 0) {
5141 92cdfaeb Peter Maydell
                            in = cpu_V0;
5142 92cdfaeb Peter Maydell
                        } else {
5143 92cdfaeb Peter Maydell
                            in = cpu_V1;
5144 92cdfaeb Peter Maydell
                        }
5145 ad69471c pbrook
                        if (q) {
5146 0b36f4cd Christophe Lyon
                            if (input_unsigned) {
5147 92cdfaeb Peter Maydell
                                gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5148 0b36f4cd Christophe Lyon
                            } else {
5149 92cdfaeb Peter Maydell
                                gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5150 0b36f4cd Christophe Lyon
                            }
5151 ad69471c pbrook
                        } else {
5152 0b36f4cd Christophe Lyon
                            if (input_unsigned) {
5153 92cdfaeb Peter Maydell
                                gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5154 0b36f4cd Christophe Lyon
                            } else {
5155 92cdfaeb Peter Maydell
                                gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5156 0b36f4cd Christophe Lyon
                            }
5157 ad69471c pbrook
                        }
5158 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5159 92cdfaeb Peter Maydell
                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5160 92cdfaeb Peter Maydell
                        neon_store_reg(rd, pass, tmp);
5161 92cdfaeb Peter Maydell
                    } /* for pass */
5162 92cdfaeb Peter Maydell
                    tcg_temp_free_i64(tmp64);
5163 92cdfaeb Peter Maydell
                } else {
5164 92cdfaeb Peter Maydell
                    if (size == 1) {
5165 92cdfaeb Peter Maydell
                        imm = (uint16_t)shift;
5166 92cdfaeb Peter Maydell
                        imm |= imm << 16;
5167 2c0262af bellard
                    } else {
5168 92cdfaeb Peter Maydell
                        /* size == 2 */
5169 92cdfaeb Peter Maydell
                        imm = (uint32_t)shift;
5170 92cdfaeb Peter Maydell
                    }
5171 92cdfaeb Peter Maydell
                    tmp2 = tcg_const_i32(imm);
5172 92cdfaeb Peter Maydell
                    tmp4 = neon_load_reg(rm + 1, 0);
5173 92cdfaeb Peter Maydell
                    tmp5 = neon_load_reg(rm + 1, 1);
5174 92cdfaeb Peter Maydell
                    for (pass = 0; pass < 2; pass++) {
5175 92cdfaeb Peter Maydell
                        if (pass == 0) {
5176 92cdfaeb Peter Maydell
                            tmp = neon_load_reg(rm, 0);
5177 92cdfaeb Peter Maydell
                        } else {
5178 92cdfaeb Peter Maydell
                            tmp = tmp4;
5179 92cdfaeb Peter Maydell
                        }
5180 0b36f4cd Christophe Lyon
                        gen_neon_shift_narrow(size, tmp, tmp2, q,
5181 0b36f4cd Christophe Lyon
                                              input_unsigned);
5182 92cdfaeb Peter Maydell
                        if (pass == 0) {
5183 92cdfaeb Peter Maydell
                            tmp3 = neon_load_reg(rm, 1);
5184 92cdfaeb Peter Maydell
                        } else {
5185 92cdfaeb Peter Maydell
                            tmp3 = tmp5;
5186 92cdfaeb Peter Maydell
                        }
5187 0b36f4cd Christophe Lyon
                        gen_neon_shift_narrow(size, tmp3, tmp2, q,
5188 0b36f4cd Christophe Lyon
                                              input_unsigned);
5189 36aa55dc pbrook
                        tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5190 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
5191 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp3);
5192 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5193 92cdfaeb Peter Maydell
                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5194 92cdfaeb Peter Maydell
                        neon_store_reg(rd, pass, tmp);
5195 92cdfaeb Peter Maydell
                    } /* for pass */
5196 c6067f04 Christophe Lyon
                    tcg_temp_free_i32(tmp2);
5197 b75263d6 Juha Riihimäki
                }
5198 9ee6e8bb pbrook
            } else if (op == 10) {
5199 cc13115b Peter Maydell
                /* VSHLL, VMOVL */
5200 cc13115b Peter Maydell
                if (q || (rd & 1)) {
5201 9ee6e8bb pbrook
                    return 1;
5202 cc13115b Peter Maydell
                }
5203 ad69471c pbrook
                tmp = neon_load_reg(rm, 0);
5204 ad69471c pbrook
                tmp2 = neon_load_reg(rm, 1);
5205 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
5206 ad69471c pbrook
                    if (pass == 1)
5207 ad69471c pbrook
                        tmp = tmp2;
5208 ad69471c pbrook
5209 ad69471c pbrook
                    gen_neon_widen(cpu_V0, tmp, size, u);
5210 9ee6e8bb pbrook
5211 9ee6e8bb pbrook
                    if (shift != 0) {
5212 9ee6e8bb pbrook
                        /* The shift is less than the width of the source
5213 ad69471c pbrook
                           type, so we can just shift the whole register.  */
5214 ad69471c pbrook
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5215 acdf01ef Christophe Lyon
                        /* Widen the result of shift: we need to clear
5216 acdf01ef Christophe Lyon
                         * the potential overflow bits resulting from
5217 acdf01ef Christophe Lyon
                         * left bits of the narrow input appearing as
5218 acdf01ef Christophe Lyon
                         * right bits of left the neighbour narrow
5219 acdf01ef Christophe Lyon
                         * input.  */
5220 ad69471c pbrook
                        if (size < 2 || !u) {
5221 ad69471c pbrook
                            uint64_t imm64;
5222 ad69471c pbrook
                            if (size == 0) {
5223 ad69471c pbrook
                                imm = (0xffu >> (8 - shift));
5224 ad69471c pbrook
                                imm |= imm << 16;
5225 acdf01ef Christophe Lyon
                            } else if (size == 1) {
5226 ad69471c pbrook
                                imm = 0xffff >> (16 - shift);
5227 acdf01ef Christophe Lyon
                            } else {
5228 acdf01ef Christophe Lyon
                                /* size == 2 */
5229 acdf01ef Christophe Lyon
                                imm = 0xffffffff >> (32 - shift);
5230 acdf01ef Christophe Lyon
                            }
5231 acdf01ef Christophe Lyon
                            if (size < 2) {
5232 acdf01ef Christophe Lyon
                                imm64 = imm | (((uint64_t)imm) << 32);
5233 acdf01ef Christophe Lyon
                            } else {
5234 acdf01ef Christophe Lyon
                                imm64 = imm;
5235 9ee6e8bb pbrook
                            }
5236 acdf01ef Christophe Lyon
                            tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5237 9ee6e8bb pbrook
                        }
5238 9ee6e8bb pbrook
                    }
5239 ad69471c pbrook
                    neon_store_reg64(cpu_V0, rd + pass);
5240 9ee6e8bb pbrook
                }
5241 f73534a5 Peter Maydell
            } else if (op >= 14) {
5242 9ee6e8bb pbrook
                /* VCVT fixed-point.  */
5243 cc13115b Peter Maydell
                if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5244 cc13115b Peter Maydell
                    return 1;
5245 cc13115b Peter Maydell
                }
5246 f73534a5 Peter Maydell
                /* We have already masked out the must-be-1 top bit of imm6,
5247 f73534a5 Peter Maydell
                 * hence this 32-shift where the ARM ARM has 64-imm6.
5248 f73534a5 Peter Maydell
                 */
5249 f73534a5 Peter Maydell
                shift = 32 - shift;
5250 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
5251 4373f3ce pbrook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5252 f73534a5 Peter Maydell
                    if (!(op & 1)) {
5253 9ee6e8bb pbrook
                        if (u)
5254 4373f3ce pbrook
                            gen_vfp_ulto(0, shift);
5255 9ee6e8bb pbrook
                        else
5256 4373f3ce pbrook
                            gen_vfp_slto(0, shift);
5257 9ee6e8bb pbrook
                    } else {
5258 9ee6e8bb pbrook
                        if (u)
5259 4373f3ce pbrook
                            gen_vfp_toul(0, shift);
5260 9ee6e8bb pbrook
                        else
5261 4373f3ce pbrook
                            gen_vfp_tosl(0, shift);
5262 2c0262af bellard
                    }
5263 4373f3ce pbrook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5264 2c0262af bellard
                }
5265 2c0262af bellard
            } else {
5266 9ee6e8bb pbrook
                return 1;
5267 9ee6e8bb pbrook
            }
5268 9ee6e8bb pbrook
        } else { /* (insn & 0x00380080) == 0 */
5269 9ee6e8bb pbrook
            int invert;
5270 7d80fee5 Peter Maydell
            if (q && (rd & 1)) {
5271 7d80fee5 Peter Maydell
                return 1;
5272 7d80fee5 Peter Maydell
            }
5273 9ee6e8bb pbrook
5274 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
5275 9ee6e8bb pbrook
            /* One register and immediate.  */
5276 9ee6e8bb pbrook
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5277 9ee6e8bb pbrook
            invert = (insn & (1 << 5)) != 0;
5278 7d80fee5 Peter Maydell
            /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5279 7d80fee5 Peter Maydell
             * We choose to not special-case this and will behave as if a
5280 7d80fee5 Peter Maydell
             * valid constant encoding of 0 had been given.
5281 7d80fee5 Peter Maydell
             */
5282 9ee6e8bb pbrook
            switch (op) {
5283 9ee6e8bb pbrook
            case 0: case 1:
5284 9ee6e8bb pbrook
                /* no-op */
5285 9ee6e8bb pbrook
                break;
5286 9ee6e8bb pbrook
            case 2: case 3:
5287 9ee6e8bb pbrook
                imm <<= 8;
5288 9ee6e8bb pbrook
                break;
5289 9ee6e8bb pbrook
            case 4: case 5:
5290 9ee6e8bb pbrook
                imm <<= 16;
5291 9ee6e8bb pbrook
                break;
5292 9ee6e8bb pbrook
            case 6: case 7:
5293 9ee6e8bb pbrook
                imm <<= 24;
5294 9ee6e8bb pbrook
                break;
5295 9ee6e8bb pbrook
            case 8: case 9:
5296 9ee6e8bb pbrook
                imm |= imm << 16;
5297 9ee6e8bb pbrook
                break;
5298 9ee6e8bb pbrook
            case 10: case 11:
5299 9ee6e8bb pbrook
                imm = (imm << 8) | (imm << 24);
5300 9ee6e8bb pbrook
                break;
5301 9ee6e8bb pbrook
            case 12:
5302 8e31209e Juha Riihimäki
                imm = (imm << 8) | 0xff;
5303 9ee6e8bb pbrook
                break;
5304 9ee6e8bb pbrook
            case 13:
5305 9ee6e8bb pbrook
                imm = (imm << 16) | 0xffff;
5306 9ee6e8bb pbrook
                break;
5307 9ee6e8bb pbrook
            case 14:
5308 9ee6e8bb pbrook
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
5309 9ee6e8bb pbrook
                if (invert)
5310 9ee6e8bb pbrook
                    imm = ~imm;
5311 9ee6e8bb pbrook
                break;
5312 9ee6e8bb pbrook
            case 15:
5313 7d80fee5 Peter Maydell
                if (invert) {
5314 7d80fee5 Peter Maydell
                    return 1;
5315 7d80fee5 Peter Maydell
                }
5316 9ee6e8bb pbrook
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5317 9ee6e8bb pbrook
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5318 9ee6e8bb pbrook
                break;
5319 9ee6e8bb pbrook
            }
5320 9ee6e8bb pbrook
            if (invert)
5321 9ee6e8bb pbrook
                imm = ~imm;
5322 9ee6e8bb pbrook
5323 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
5324 9ee6e8bb pbrook
                if (op & 1 && op < 12) {
5325 ad69471c pbrook
                    tmp = neon_load_reg(rd, pass);
5326 9ee6e8bb pbrook
                    if (invert) {
5327 9ee6e8bb pbrook
                        /* The immediate value has already been inverted, so
5328 9ee6e8bb pbrook
                           BIC becomes AND.  */
5329 ad69471c pbrook
                        tcg_gen_andi_i32(tmp, tmp, imm);
5330 9ee6e8bb pbrook
                    } else {
5331 ad69471c pbrook
                        tcg_gen_ori_i32(tmp, tmp, imm);
5332 9ee6e8bb pbrook
                    }
5333 9ee6e8bb pbrook
                } else {
5334 ad69471c pbrook
                    /* VMOV, VMVN.  */
5335 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5336 9ee6e8bb pbrook
                    if (op == 14 && invert) {
5337 a5a14945 Juha Riihimäki
                        int n;
5338 ad69471c pbrook
                        uint32_t val;
5339 ad69471c pbrook
                        val = 0;
5340 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
5341 9ee6e8bb pbrook
                            if (imm & (1 << (n + (pass & 1) * 4)))
5342 ad69471c pbrook
                                val |= 0xff << (n * 8);
5343 9ee6e8bb pbrook
                        }
5344 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, val);
5345 ad69471c pbrook
                    } else {
5346 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, imm);
5347 9ee6e8bb pbrook
                    }
5348 9ee6e8bb pbrook
                }
5349 ad69471c pbrook
                neon_store_reg(rd, pass, tmp);
5350 9ee6e8bb pbrook
            }
5351 9ee6e8bb pbrook
        }
5352 e4b3861d pbrook
    } else { /* (insn & 0x00800010 == 0x00800000) */
5353 9ee6e8bb pbrook
        if (size != 3) {
5354 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
5355 9ee6e8bb pbrook
            if ((insn & (1 << 6)) == 0) {
5356 9ee6e8bb pbrook
                /* Three registers of different lengths.  */
5357 9ee6e8bb pbrook
                int src1_wide;
5358 9ee6e8bb pbrook
                int src2_wide;
5359 9ee6e8bb pbrook
                int prewiden;
5360 695272dc Peter Maydell
                /* undefreq: bit 0 : UNDEF if size != 0
5361 695272dc Peter Maydell
                 *           bit 1 : UNDEF if size == 0
5362 695272dc Peter Maydell
                 *           bit 2 : UNDEF if U == 1
5363 695272dc Peter Maydell
                 * Note that [1:0] set implies 'always UNDEF'
5364 695272dc Peter Maydell
                 */
5365 695272dc Peter Maydell
                int undefreq;
5366 695272dc Peter Maydell
                /* prewiden, src1_wide, src2_wide, undefreq */
5367 695272dc Peter Maydell
                static const int neon_3reg_wide[16][4] = {
5368 695272dc Peter Maydell
                    {1, 0, 0, 0}, /* VADDL */
5369 695272dc Peter Maydell
                    {1, 1, 0, 0}, /* VADDW */
5370 695272dc Peter Maydell
                    {1, 0, 0, 0}, /* VSUBL */
5371 695272dc Peter Maydell
                    {1, 1, 0, 0}, /* VSUBW */
5372 695272dc Peter Maydell
                    {0, 1, 1, 0}, /* VADDHN */
5373 695272dc Peter Maydell
                    {0, 0, 0, 0}, /* VABAL */
5374 695272dc Peter Maydell
                    {0, 1, 1, 0}, /* VSUBHN */
5375 695272dc Peter Maydell
                    {0, 0, 0, 0}, /* VABDL */
5376 695272dc Peter Maydell
                    {0, 0, 0, 0}, /* VMLAL */
5377 695272dc Peter Maydell
                    {0, 0, 0, 6}, /* VQDMLAL */
5378 695272dc Peter Maydell
                    {0, 0, 0, 0}, /* VMLSL */
5379 695272dc Peter Maydell
                    {0, 0, 0, 6}, /* VQDMLSL */
5380 695272dc Peter Maydell
                    {0, 0, 0, 0}, /* Integer VMULL */
5381 695272dc Peter Maydell
                    {0, 0, 0, 2}, /* VQDMULL */
5382 695272dc Peter Maydell
                    {0, 0, 0, 5}, /* Polynomial VMULL */
5383 695272dc Peter Maydell
                    {0, 0, 0, 3}, /* Reserved: always UNDEF */
5384 9ee6e8bb pbrook
                };
5385 9ee6e8bb pbrook
5386 9ee6e8bb pbrook
                prewiden = neon_3reg_wide[op][0];
5387 9ee6e8bb pbrook
                src1_wide = neon_3reg_wide[op][1];
5388 9ee6e8bb pbrook
                src2_wide = neon_3reg_wide[op][2];
5389 695272dc Peter Maydell
                undefreq = neon_3reg_wide[op][3];
5390 9ee6e8bb pbrook
5391 695272dc Peter Maydell
                if (((undefreq & 1) && (size != 0)) ||
5392 695272dc Peter Maydell
                    ((undefreq & 2) && (size == 0)) ||
5393 695272dc Peter Maydell
                    ((undefreq & 4) && u)) {
5394 695272dc Peter Maydell
                    return 1;
5395 695272dc Peter Maydell
                }
5396 695272dc Peter Maydell
                if ((src1_wide && (rn & 1)) ||
5397 695272dc Peter Maydell
                    (src2_wide && (rm & 1)) ||
5398 695272dc Peter Maydell
                    (!src2_wide && (rd & 1))) {
5399 ad69471c pbrook
                    return 1;
5400 695272dc Peter Maydell
                }
5401 ad69471c pbrook
5402 9ee6e8bb pbrook
                /* Avoid overlapping operands.  Wide source operands are
5403 9ee6e8bb pbrook
                   always aligned so will never overlap with wide
5404 9ee6e8bb pbrook
                   destinations in problematic ways.  */
5405 8f8e3aa4 pbrook
                if (rd == rm && !src2_wide) {
5406 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
5407 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
5408 8f8e3aa4 pbrook
                } else if (rd == rn && !src1_wide) {
5409 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rn, 1);
5410 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
5411 9ee6e8bb pbrook
                }
5412 a50f5b91 pbrook
                TCGV_UNUSED(tmp3);
5413 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
5414 ad69471c pbrook
                    if (src1_wide) {
5415 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + pass);
5416 a50f5b91 pbrook
                        TCGV_UNUSED(tmp);
5417 9ee6e8bb pbrook
                    } else {
5418 ad69471c pbrook
                        if (pass == 1 && rd == rn) {
5419 dd8fbd78 Filip Navara
                            tmp = neon_load_scratch(2);
5420 9ee6e8bb pbrook
                        } else {
5421 ad69471c pbrook
                            tmp = neon_load_reg(rn, pass);
5422 ad69471c pbrook
                        }
5423 ad69471c pbrook
                        if (prewiden) {
5424 ad69471c pbrook
                            gen_neon_widen(cpu_V0, tmp, size, u);
5425 9ee6e8bb pbrook
                        }
5426 9ee6e8bb pbrook
                    }
5427 ad69471c pbrook
                    if (src2_wide) {
5428 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + pass);
5429 a50f5b91 pbrook
                        TCGV_UNUSED(tmp2);
5430 9ee6e8bb pbrook
                    } else {
5431 ad69471c pbrook
                        if (pass == 1 && rd == rm) {
5432 dd8fbd78 Filip Navara
                            tmp2 = neon_load_scratch(2);
5433 9ee6e8bb pbrook
                        } else {
5434 ad69471c pbrook
                            tmp2 = neon_load_reg(rm, pass);
5435 ad69471c pbrook
                        }
5436 ad69471c pbrook
                        if (prewiden) {
5437 ad69471c pbrook
                            gen_neon_widen(cpu_V1, tmp2, size, u);
5438 9ee6e8bb pbrook
                        }
5439 9ee6e8bb pbrook
                    }
5440 9ee6e8bb pbrook
                    switch (op) {
5441 9ee6e8bb pbrook
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5442 ad69471c pbrook
                        gen_neon_addl(size);
5443 9ee6e8bb pbrook
                        break;
5444 79b0e534 Riku Voipio
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5445 ad69471c pbrook
                        gen_neon_subl(size);
5446 9ee6e8bb pbrook
                        break;
5447 9ee6e8bb pbrook
                    case 5: case 7: /* VABAL, VABDL */
5448 9ee6e8bb pbrook
                        switch ((size << 1) | u) {
5449 ad69471c pbrook
                        case 0:
5450 ad69471c pbrook
                            gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5451 ad69471c pbrook
                            break;
5452 ad69471c pbrook
                        case 1:
5453 ad69471c pbrook
                            gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5454 ad69471c pbrook
                            break;
5455 ad69471c pbrook
                        case 2:
5456 ad69471c pbrook
                            gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5457 ad69471c pbrook
                            break;
5458 ad69471c pbrook
                        case 3:
5459 ad69471c pbrook
                            gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5460 ad69471c pbrook
                            break;
5461 ad69471c pbrook
                        case 4:
5462 ad69471c pbrook
                            gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5463 ad69471c pbrook
                            break;
5464 ad69471c pbrook
                        case 5:
5465 ad69471c pbrook
                            gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5466 ad69471c pbrook
                            break;
5467 9ee6e8bb pbrook
                        default: abort();
5468 9ee6e8bb pbrook
                        }
5469 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5470 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
5471 9ee6e8bb pbrook
                        break;
5472 9ee6e8bb pbrook
                    case 8: case 9: case 10: case 11: case 12: case 13:
5473 9ee6e8bb pbrook
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5474 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5475 9ee6e8bb pbrook
                        break;
5476 9ee6e8bb pbrook
                    case 14: /* Polynomial VMULL */
5477 e5ca24cb Peter Maydell
                        gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5478 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5479 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
5480 e5ca24cb Peter Maydell
                        break;
5481 695272dc Peter Maydell
                    default: /* 15 is RESERVED: caught earlier  */
5482 695272dc Peter Maydell
                        abort();
5483 9ee6e8bb pbrook
                    }
5484 ebcd88ce Peter Maydell
                    if (op == 13) {
5485 ebcd88ce Peter Maydell
                        /* VQDMULL */
5486 ebcd88ce Peter Maydell
                        gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5487 ebcd88ce Peter Maydell
                        neon_store_reg64(cpu_V0, rd + pass);
5488 ebcd88ce Peter Maydell
                    } else if (op == 5 || (op >= 8 && op <= 11)) {
5489 9ee6e8bb pbrook
                        /* Accumulate.  */
5490 ebcd88ce Peter Maydell
                        neon_load_reg64(cpu_V1, rd + pass);
5491 9ee6e8bb pbrook
                        switch (op) {
5492 4dc064e6 Peter Maydell
                        case 10: /* VMLSL */
5493 4dc064e6 Peter Maydell
                            gen_neon_negl(cpu_V0, size);
5494 4dc064e6 Peter Maydell
                            /* Fall through */
5495 4dc064e6 Peter Maydell
                        case 5: case 8: /* VABAL, VMLAL */
5496 ad69471c pbrook
                            gen_neon_addl(size);
5497 9ee6e8bb pbrook
                            break;
5498 9ee6e8bb pbrook
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
5499 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5500 4dc064e6 Peter Maydell
                            if (op == 11) {
5501 4dc064e6 Peter Maydell
                                gen_neon_negl(cpu_V0, size);
5502 4dc064e6 Peter Maydell
                            }
5503 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5504 ad69471c pbrook
                            break;
5505 9ee6e8bb pbrook
                        default:
5506 9ee6e8bb pbrook
                            abort();
5507 9ee6e8bb pbrook
                        }
5508 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5509 9ee6e8bb pbrook
                    } else if (op == 4 || op == 6) {
5510 9ee6e8bb pbrook
                        /* Narrowing operation.  */
5511 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5512 79b0e534 Riku Voipio
                        if (!u) {
5513 9ee6e8bb pbrook
                            switch (size) {
5514 ad69471c pbrook
                            case 0:
5515 ad69471c pbrook
                                gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5516 ad69471c pbrook
                                break;
5517 ad69471c pbrook
                            case 1:
5518 ad69471c pbrook
                                gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5519 ad69471c pbrook
                                break;
5520 ad69471c pbrook
                            case 2:
5521 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5522 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5523 ad69471c pbrook
                                break;
5524 9ee6e8bb pbrook
                            default: abort();
5525 9ee6e8bb pbrook
                            }
5526 9ee6e8bb pbrook
                        } else {
5527 9ee6e8bb pbrook
                            switch (size) {
5528 ad69471c pbrook
                            case 0:
5529 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5530 ad69471c pbrook
                                break;
5531 ad69471c pbrook
                            case 1:
5532 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5533 ad69471c pbrook
                                break;
5534 ad69471c pbrook
                            case 2:
5535 ad69471c pbrook
                                tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5536 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5537 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5538 ad69471c pbrook
                                break;
5539 9ee6e8bb pbrook
                            default: abort();
5540 9ee6e8bb pbrook
                            }
5541 9ee6e8bb pbrook
                        }
5542 ad69471c pbrook
                        if (pass == 0) {
5543 ad69471c pbrook
                            tmp3 = tmp;
5544 ad69471c pbrook
                        } else {
5545 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp3);
5546 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5547 ad69471c pbrook
                        }
5548 9ee6e8bb pbrook
                    } else {
5549 9ee6e8bb pbrook
                        /* Write back the result.  */
5550 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5551 9ee6e8bb pbrook
                    }
5552 9ee6e8bb pbrook
                }
5553 9ee6e8bb pbrook
            } else {
5554 3e3326df Peter Maydell
                /* Two registers and a scalar. NB that for ops of this form
5555 3e3326df Peter Maydell
                 * the ARM ARM labels bit 24 as Q, but it is in our variable
5556 3e3326df Peter Maydell
                 * 'u', not 'q'.
5557 3e3326df Peter Maydell
                 */
5558 3e3326df Peter Maydell
                if (size == 0) {
5559 3e3326df Peter Maydell
                    return 1;
5560 3e3326df Peter Maydell
                }
5561 9ee6e8bb pbrook
                switch (op) {
5562 9ee6e8bb pbrook
                case 1: /* Float VMLA scalar */
5563 9ee6e8bb pbrook
                case 5: /* Floating point VMLS scalar */
5564 9ee6e8bb pbrook
                case 9: /* Floating point VMUL scalar */
5565 3e3326df Peter Maydell
                    if (size == 1) {
5566 3e3326df Peter Maydell
                        return 1;
5567 3e3326df Peter Maydell
                    }
5568 3e3326df Peter Maydell
                    /* fall through */
5569 3e3326df Peter Maydell
                case 0: /* Integer VMLA scalar */
5570 3e3326df Peter Maydell
                case 4: /* Integer VMLS scalar */
5571 3e3326df Peter Maydell
                case 8: /* Integer VMUL scalar */
5572 9ee6e8bb pbrook
                case 12: /* VQDMULH scalar */
5573 9ee6e8bb pbrook
                case 13: /* VQRDMULH scalar */
5574 3e3326df Peter Maydell
                    if (u && ((rd | rn) & 1)) {
5575 3e3326df Peter Maydell
                        return 1;
5576 3e3326df Peter Maydell
                    }
5577 dd8fbd78 Filip Navara
                    tmp = neon_get_scalar(size, rm);
5578 dd8fbd78 Filip Navara
                    neon_store_scratch(0, tmp);
5579 9ee6e8bb pbrook
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
5580 dd8fbd78 Filip Navara
                        tmp = neon_load_scratch(0);
5581 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rn, pass);
5582 9ee6e8bb pbrook
                        if (op == 12) {
5583 9ee6e8bb pbrook
                            if (size == 1) {
5584 2a3f75b4 Peter Maydell
                                gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2);
5585 9ee6e8bb pbrook
                            } else {
5586 2a3f75b4 Peter Maydell
                                gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2);
5587 9ee6e8bb pbrook
                            }
5588 9ee6e8bb pbrook
                        } else if (op == 13) {
5589 9ee6e8bb pbrook
                            if (size == 1) {
5590 2a3f75b4 Peter Maydell
                                gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2);
5591 9ee6e8bb pbrook
                            } else {
5592 2a3f75b4 Peter Maydell
                                gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
5593 9ee6e8bb pbrook
                            }
5594 9ee6e8bb pbrook
                        } else if (op & 1) {
5595 dd8fbd78 Filip Navara
                            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5596 9ee6e8bb pbrook
                        } else {
5597 9ee6e8bb pbrook
                            switch (size) {
5598 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5599 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5600 dd8fbd78 Filip Navara
                            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5601 3e3326df Peter Maydell
                            default: abort();
5602 9ee6e8bb pbrook
                            }
5603 9ee6e8bb pbrook
                        }
5604 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5605 9ee6e8bb pbrook
                        if (op < 8) {
5606 9ee6e8bb pbrook
                            /* Accumulate.  */
5607 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5608 9ee6e8bb pbrook
                            switch (op) {
5609 9ee6e8bb pbrook
                            case 0:
5610 dd8fbd78 Filip Navara
                                gen_neon_add(size, tmp, tmp2);
5611 9ee6e8bb pbrook
                                break;
5612 9ee6e8bb pbrook
                            case 1:
5613 dd8fbd78 Filip Navara
                                gen_helper_neon_add_f32(tmp, tmp, tmp2);
5614 9ee6e8bb pbrook
                                break;
5615 9ee6e8bb pbrook
                            case 4:
5616 dd8fbd78 Filip Navara
                                gen_neon_rsb(size, tmp, tmp2);
5617 9ee6e8bb pbrook
                                break;
5618 9ee6e8bb pbrook
                            case 5:
5619 dd8fbd78 Filip Navara
                                gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5620 9ee6e8bb pbrook
                                break;
5621 9ee6e8bb pbrook
                            default:
5622 9ee6e8bb pbrook
                                abort();
5623 9ee6e8bb pbrook
                            }
5624 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
5625 9ee6e8bb pbrook
                        }
5626 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
5627 9ee6e8bb pbrook
                    }
5628 9ee6e8bb pbrook
                    break;
5629 9ee6e8bb pbrook
                case 3: /* VQDMLAL scalar */
5630 9ee6e8bb pbrook
                case 7: /* VQDMLSL scalar */
5631 9ee6e8bb pbrook
                case 11: /* VQDMULL scalar */
5632 3e3326df Peter Maydell
                    if (u == 1) {
5633 ad69471c pbrook
                        return 1;
5634 3e3326df Peter Maydell
                    }
5635 3e3326df Peter Maydell
                    /* fall through */
5636 3e3326df Peter Maydell
                case 2: /* VMLAL sclar */
5637 3e3326df Peter Maydell
                case 6: /* VMLSL scalar */
5638 3e3326df Peter Maydell
                case 10: /* VMULL scalar */
5639 3e3326df Peter Maydell
                    if (rd & 1) {
5640 3e3326df Peter Maydell
                        return 1;
5641 3e3326df Peter Maydell
                    }
5642 dd8fbd78 Filip Navara
                    tmp2 = neon_get_scalar(size, rm);
5643 c6067f04 Christophe Lyon
                    /* We need a copy of tmp2 because gen_neon_mull
5644 c6067f04 Christophe Lyon
                     * deletes it during pass 0.  */
5645 7d1b0095 Peter Maydell
                    tmp4 = tcg_temp_new_i32();
5646 c6067f04 Christophe Lyon
                    tcg_gen_mov_i32(tmp4, tmp2);
5647 dd8fbd78 Filip Navara
                    tmp3 = neon_load_reg(rn, 1);
5648 ad69471c pbrook
5649 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5650 ad69471c pbrook
                        if (pass == 0) {
5651 ad69471c pbrook
                            tmp = neon_load_reg(rn, 0);
5652 9ee6e8bb pbrook
                        } else {
5653 dd8fbd78 Filip Navara
                            tmp = tmp3;
5654 c6067f04 Christophe Lyon
                            tmp2 = tmp4;
5655 9ee6e8bb pbrook
                        }
5656 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5657 ad69471c pbrook
                        if (op != 11) {
5658 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5659 9ee6e8bb pbrook
                        }
5660 9ee6e8bb pbrook
                        switch (op) {
5661 4dc064e6 Peter Maydell
                        case 6:
5662 4dc064e6 Peter Maydell
                            gen_neon_negl(cpu_V0, size);
5663 4dc064e6 Peter Maydell
                            /* Fall through */
5664 4dc064e6 Peter Maydell
                        case 2:
5665 ad69471c pbrook
                            gen_neon_addl(size);
5666 9ee6e8bb pbrook
                            break;
5667 9ee6e8bb pbrook
                        case 3: case 7:
5668 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5669 4dc064e6 Peter Maydell
                            if (op == 7) {
5670 4dc064e6 Peter Maydell
                                gen_neon_negl(cpu_V0, size);
5671 4dc064e6 Peter Maydell
                            }
5672 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5673 9ee6e8bb pbrook
                            break;
5674 9ee6e8bb pbrook
                        case 10:
5675 9ee6e8bb pbrook
                            /* no-op */
5676 9ee6e8bb pbrook
                            break;
5677 9ee6e8bb pbrook
                        case 11:
5678 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5679 9ee6e8bb pbrook
                            break;
5680 9ee6e8bb pbrook
                        default:
5681 9ee6e8bb pbrook
                            abort();
5682 9ee6e8bb pbrook
                        }
5683 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5684 9ee6e8bb pbrook
                    }
5685 dd8fbd78 Filip Navara
5686 dd8fbd78 Filip Navara
5687 9ee6e8bb pbrook
                    break;
5688 9ee6e8bb pbrook
                default: /* 14 and 15 are RESERVED */
5689 9ee6e8bb pbrook
                    return 1;
5690 9ee6e8bb pbrook
                }
5691 9ee6e8bb pbrook
            }
5692 9ee6e8bb pbrook
        } else { /* size == 3 */
5693 9ee6e8bb pbrook
            if (!u) {
5694 9ee6e8bb pbrook
                /* Extract.  */
5695 9ee6e8bb pbrook
                imm = (insn >> 8) & 0xf;
5696 ad69471c pbrook
5697 ad69471c pbrook
                if (imm > 7 && !q)
5698 ad69471c pbrook
                    return 1;
5699 ad69471c pbrook
5700 52579ea1 Peter Maydell
                if (q && ((rd | rn | rm) & 1)) {
5701 52579ea1 Peter Maydell
                    return 1;
5702 52579ea1 Peter Maydell
                }
5703 52579ea1 Peter Maydell
5704 ad69471c pbrook
                if (imm == 0) {
5705 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5706 ad69471c pbrook
                    if (q) {
5707 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rn + 1);
5708 9ee6e8bb pbrook
                    }
5709 ad69471c pbrook
                } else if (imm == 8) {
5710 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn + 1);
5711 ad69471c pbrook
                    if (q) {
5712 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5713 9ee6e8bb pbrook
                    }
5714 ad69471c pbrook
                } else if (q) {
5715 a7812ae4 pbrook
                    tmp64 = tcg_temp_new_i64();
5716 ad69471c pbrook
                    if (imm < 8) {
5717 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn);
5718 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rn + 1);
5719 ad69471c pbrook
                    } else {
5720 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + 1);
5721 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rm);
5722 ad69471c pbrook
                    }
5723 ad69471c pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5724 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5725 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5726 ad69471c pbrook
                    if (imm < 8) {
5727 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5728 9ee6e8bb pbrook
                    } else {
5729 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + 1);
5730 ad69471c pbrook
                        imm -= 8;
5731 9ee6e8bb pbrook
                    }
5732 ad69471c pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5733 a7812ae4 pbrook
                    tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5734 a7812ae4 pbrook
                    tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5735 b75263d6 Juha Riihimäki
                    tcg_temp_free_i64(tmp64);
5736 ad69471c pbrook
                } else {
5737 a7812ae4 pbrook
                    /* BUGFIX */
5738 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5739 a7812ae4 pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5740 ad69471c pbrook
                    neon_load_reg64(cpu_V1, rm);
5741 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5742 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5743 ad69471c pbrook
                }
5744 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd);
5745 ad69471c pbrook
                if (q) {
5746 ad69471c pbrook
                    neon_store_reg64(cpu_V1, rd + 1);
5747 9ee6e8bb pbrook
                }
5748 9ee6e8bb pbrook
            } else if ((insn & (1 << 11)) == 0) {
5749 9ee6e8bb pbrook
                /* Two register misc.  */
5750 9ee6e8bb pbrook
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5751 9ee6e8bb pbrook
                size = (insn >> 18) & 3;
5752 600b828c Peter Maydell
                /* UNDEF for unknown op values and bad op-size combinations */
5753 600b828c Peter Maydell
                if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5754 600b828c Peter Maydell
                    return 1;
5755 600b828c Peter Maydell
                }
5756 fc2a9b37 Peter Maydell
                if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5757 fc2a9b37 Peter Maydell
                    q && ((rm | rd) & 1)) {
5758 fc2a9b37 Peter Maydell
                    return 1;
5759 fc2a9b37 Peter Maydell
                }
5760 9ee6e8bb pbrook
                switch (op) {
5761 600b828c Peter Maydell
                case NEON_2RM_VREV64:
5762 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
5763 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass * 2);
5764 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rm, pass * 2 + 1);
5765 9ee6e8bb pbrook
                        switch (size) {
5766 dd8fbd78 Filip Navara
                        case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5767 dd8fbd78 Filip Navara
                        case 1: gen_swap_half(tmp); break;
5768 9ee6e8bb pbrook
                        case 2: /* no-op */ break;
5769 9ee6e8bb pbrook
                        default: abort();
5770 9ee6e8bb pbrook
                        }
5771 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass * 2 + 1, tmp);
5772 9ee6e8bb pbrook
                        if (size == 2) {
5773 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5774 9ee6e8bb pbrook
                        } else {
5775 9ee6e8bb pbrook
                            switch (size) {
5776 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5777 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp2); break;
5778 9ee6e8bb pbrook
                            default: abort();
5779 9ee6e8bb pbrook
                            }
5780 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5781 9ee6e8bb pbrook
                        }
5782 9ee6e8bb pbrook
                    }
5783 9ee6e8bb pbrook
                    break;
5784 600b828c Peter Maydell
                case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5785 600b828c Peter Maydell
                case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5786 ad69471c pbrook
                    for (pass = 0; pass < q + 1; pass++) {
5787 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2);
5788 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, op & 1);
5789 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2 + 1);
5790 ad69471c pbrook
                        gen_neon_widen(cpu_V1, tmp, size, op & 1);
5791 ad69471c pbrook
                        switch (size) {
5792 ad69471c pbrook
                        case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5793 ad69471c pbrook
                        case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5794 ad69471c pbrook
                        case 2: tcg_gen_add_i64(CPU_V001); break;
5795 ad69471c pbrook
                        default: abort();
5796 ad69471c pbrook
                        }
5797 600b828c Peter Maydell
                        if (op >= NEON_2RM_VPADAL) {
5798 9ee6e8bb pbrook
                            /* Accumulate.  */
5799 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5800 ad69471c pbrook
                            gen_neon_addl(size);
5801 9ee6e8bb pbrook
                        }
5802 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5803 9ee6e8bb pbrook
                    }
5804 9ee6e8bb pbrook
                    break;
5805 600b828c Peter Maydell
                case NEON_2RM_VTRN:
5806 9ee6e8bb pbrook
                    if (size == 2) {
5807 a5a14945 Juha Riihimäki
                        int n;
5808 9ee6e8bb pbrook
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
5809 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, n);
5810 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, n + 1);
5811 dd8fbd78 Filip Navara
                            neon_store_reg(rm, n, tmp2);
5812 dd8fbd78 Filip Navara
                            neon_store_reg(rd, n + 1, tmp);
5813 9ee6e8bb pbrook
                        }
5814 9ee6e8bb pbrook
                    } else {
5815 9ee6e8bb pbrook
                        goto elementwise;
5816 9ee6e8bb pbrook
                    }
5817 9ee6e8bb pbrook
                    break;
5818 600b828c Peter Maydell
                case NEON_2RM_VUZP:
5819 02acedf9 Peter Maydell
                    if (gen_neon_unzip(rd, rm, size, q)) {
5820 9ee6e8bb pbrook
                        return 1;
5821 9ee6e8bb pbrook
                    }
5822 9ee6e8bb pbrook
                    break;
5823 600b828c Peter Maydell
                case NEON_2RM_VZIP:
5824 d68a6f3a Peter Maydell
                    if (gen_neon_zip(rd, rm, size, q)) {
5825 9ee6e8bb pbrook
                        return 1;
5826 9ee6e8bb pbrook
                    }
5827 9ee6e8bb pbrook
                    break;
5828 600b828c Peter Maydell
                case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5829 600b828c Peter Maydell
                    /* also VQMOVUN; op field and mnemonics don't line up */
5830 fc2a9b37 Peter Maydell
                    if (rm & 1) {
5831 fc2a9b37 Peter Maydell
                        return 1;
5832 fc2a9b37 Peter Maydell
                    }
5833 a50f5b91 pbrook
                    TCGV_UNUSED(tmp2);
5834 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5835 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
5836 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5837 600b828c Peter Maydell
                        gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5838 600b828c Peter Maydell
                                           tmp, cpu_V0);
5839 ad69471c pbrook
                        if (pass == 0) {
5840 ad69471c pbrook
                            tmp2 = tmp;
5841 ad69471c pbrook
                        } else {
5842 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp2);
5843 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5844 9ee6e8bb pbrook
                        }
5845 9ee6e8bb pbrook
                    }
5846 9ee6e8bb pbrook
                    break;
5847 600b828c Peter Maydell
                case NEON_2RM_VSHLL:
5848 fc2a9b37 Peter Maydell
                    if (q || (rd & 1)) {
5849 9ee6e8bb pbrook
                        return 1;
5850 600b828c Peter Maydell
                    }
5851 ad69471c pbrook
                    tmp = neon_load_reg(rm, 0);
5852 ad69471c pbrook
                    tmp2 = neon_load_reg(rm, 1);
5853 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5854 ad69471c pbrook
                        if (pass == 1)
5855 ad69471c pbrook
                            tmp = tmp2;
5856 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, 1);
5857 30d11a2a Juha Riihimäki
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5858 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5859 9ee6e8bb pbrook
                    }
5860 9ee6e8bb pbrook
                    break;
5861 600b828c Peter Maydell
                case NEON_2RM_VCVT_F16_F32:
5862 fc2a9b37 Peter Maydell
                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5863 fc2a9b37 Peter Maydell
                        q || (rm & 1)) {
5864 fc2a9b37 Peter Maydell
                        return 1;
5865 fc2a9b37 Peter Maydell
                    }
5866 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5867 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
5868 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5869 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5870 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5871 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5872 60011498 Paul Brook
                    tcg_gen_shli_i32(tmp2, tmp2, 16);
5873 60011498 Paul Brook
                    tcg_gen_or_i32(tmp2, tmp2, tmp);
5874 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5875 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5876 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5877 60011498 Paul Brook
                    neon_store_reg(rd, 0, tmp2);
5878 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
5879 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5880 60011498 Paul Brook
                    tcg_gen_shli_i32(tmp2, tmp2, 16);
5881 60011498 Paul Brook
                    tcg_gen_or_i32(tmp2, tmp2, tmp);
5882 60011498 Paul Brook
                    neon_store_reg(rd, 1, tmp2);
5883 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
5884 60011498 Paul Brook
                    break;
5885 600b828c Peter Maydell
                case NEON_2RM_VCVT_F32_F16:
5886 fc2a9b37 Peter Maydell
                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5887 fc2a9b37 Peter Maydell
                        q || (rd & 1)) {
5888 fc2a9b37 Peter Maydell
                        return 1;
5889 fc2a9b37 Peter Maydell
                    }
5890 7d1b0095 Peter Maydell
                    tmp3 = tcg_temp_new_i32();
5891 60011498 Paul Brook
                    tmp = neon_load_reg(rm, 0);
5892 60011498 Paul Brook
                    tmp2 = neon_load_reg(rm, 1);
5893 60011498 Paul Brook
                    tcg_gen_ext16u_i32(tmp3, tmp);
5894 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5895 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5896 60011498 Paul Brook
                    tcg_gen_shri_i32(tmp3, tmp, 16);
5897 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5898 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5899 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
5900 60011498 Paul Brook
                    tcg_gen_ext16u_i32(tmp3, tmp2);
5901 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5902 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5903 60011498 Paul Brook
                    tcg_gen_shri_i32(tmp3, tmp2, 16);
5904 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5905 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5906 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
5907 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp3);
5908 60011498 Paul Brook
                    break;
5909 9ee6e8bb pbrook
                default:
5910 9ee6e8bb pbrook
                elementwise:
5911 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
5912 600b828c Peter Maydell
                        if (neon_2rm_is_float_op(op)) {
5913 4373f3ce pbrook
                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
5914 4373f3ce pbrook
                                           neon_reg_offset(rm, pass));
5915 dd8fbd78 Filip Navara
                            TCGV_UNUSED(tmp);
5916 9ee6e8bb pbrook
                        } else {
5917 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, pass);
5918 9ee6e8bb pbrook
                        }
5919 9ee6e8bb pbrook
                        switch (op) {
5920 600b828c Peter Maydell
                        case NEON_2RM_VREV32:
5921 9ee6e8bb pbrook
                            switch (size) {
5922 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5923 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp); break;
5924 600b828c Peter Maydell
                            default: abort();
5925 9ee6e8bb pbrook
                            }
5926 9ee6e8bb pbrook
                            break;
5927 600b828c Peter Maydell
                        case NEON_2RM_VREV16:
5928 dd8fbd78 Filip Navara
                            gen_rev16(tmp);
5929 9ee6e8bb pbrook
                            break;
5930 600b828c Peter Maydell
                        case NEON_2RM_VCLS:
5931 9ee6e8bb pbrook
                            switch (size) {
5932 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5933 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5934 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5935 600b828c Peter Maydell
                            default: abort();
5936 9ee6e8bb pbrook
                            }
5937 9ee6e8bb pbrook
                            break;
5938 600b828c Peter Maydell
                        case NEON_2RM_VCLZ:
5939 9ee6e8bb pbrook
                            switch (size) {
5940 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5941 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5942 dd8fbd78 Filip Navara
                            case 2: gen_helper_clz(tmp, tmp); break;
5943 600b828c Peter Maydell
                            default: abort();
5944 9ee6e8bb pbrook
                            }
5945 9ee6e8bb pbrook
                            break;
5946 600b828c Peter Maydell
                        case NEON_2RM_VCNT:
5947 dd8fbd78 Filip Navara
                            gen_helper_neon_cnt_u8(tmp, tmp);
5948 9ee6e8bb pbrook
                            break;
5949 600b828c Peter Maydell
                        case NEON_2RM_VMVN:
5950 dd8fbd78 Filip Navara
                            tcg_gen_not_i32(tmp, tmp);
5951 9ee6e8bb pbrook
                            break;
5952 600b828c Peter Maydell
                        case NEON_2RM_VQABS:
5953 9ee6e8bb pbrook
                            switch (size) {
5954 2a3f75b4 Peter Maydell
                            case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
5955 2a3f75b4 Peter Maydell
                            case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
5956 2a3f75b4 Peter Maydell
                            case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
5957 600b828c Peter Maydell
                            default: abort();
5958 9ee6e8bb pbrook
                            }
5959 9ee6e8bb pbrook
                            break;
5960 600b828c Peter Maydell
                        case NEON_2RM_VQNEG:
5961 9ee6e8bb pbrook
                            switch (size) {
5962 2a3f75b4 Peter Maydell
                            case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
5963 2a3f75b4 Peter Maydell
                            case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
5964 2a3f75b4 Peter Maydell
                            case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
5965 600b828c Peter Maydell
                            default: abort();
5966 9ee6e8bb pbrook
                            }
5967 9ee6e8bb pbrook
                            break;
5968 600b828c Peter Maydell
                        case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
5969 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5970 9ee6e8bb pbrook
                            switch(size) {
5971 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5972 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5973 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5974 600b828c Peter Maydell
                            default: abort();
5975 9ee6e8bb pbrook
                            }
5976 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5977 600b828c Peter Maydell
                            if (op == NEON_2RM_VCLE0) {
5978 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5979 600b828c Peter Maydell
                            }
5980 9ee6e8bb pbrook
                            break;
5981 600b828c Peter Maydell
                        case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
5982 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5983 9ee6e8bb pbrook
                            switch(size) {
5984 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5985 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5986 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5987 600b828c Peter Maydell
                            default: abort();
5988 9ee6e8bb pbrook
                            }
5989 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5990 600b828c Peter Maydell
                            if (op == NEON_2RM_VCLT0) {
5991 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5992 600b828c Peter Maydell
                            }
5993 9ee6e8bb pbrook
                            break;
5994 600b828c Peter Maydell
                        case NEON_2RM_VCEQ0:
5995 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5996 9ee6e8bb pbrook
                            switch(size) {
5997 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5998 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5999 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6000 600b828c Peter Maydell
                            default: abort();
6001 9ee6e8bb pbrook
                            }
6002 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
6003 9ee6e8bb pbrook
                            break;
6004 600b828c Peter Maydell
                        case NEON_2RM_VABS:
6005 9ee6e8bb pbrook
                            switch(size) {
6006 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6007 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6008 dd8fbd78 Filip Navara
                            case 2: tcg_gen_abs_i32(tmp, tmp); break;
6009 600b828c Peter Maydell
                            default: abort();
6010 9ee6e8bb pbrook
                            }
6011 9ee6e8bb pbrook
                            break;
6012 600b828c Peter Maydell
                        case NEON_2RM_VNEG:
6013 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
6014 dd8fbd78 Filip Navara
                            gen_neon_rsb(size, tmp, tmp2);
6015 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
6016 9ee6e8bb pbrook
                            break;
6017 600b828c Peter Maydell
                        case NEON_2RM_VCGT0_F:
6018 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
6019 dd8fbd78 Filip Navara
                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
6020 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
6021 9ee6e8bb pbrook
                            break;
6022 600b828c Peter Maydell
                        case NEON_2RM_VCGE0_F:
6023 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
6024 dd8fbd78 Filip Navara
                            gen_helper_neon_cge_f32(tmp, tmp, tmp2);
6025 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
6026 9ee6e8bb pbrook
                            break;
6027 600b828c Peter Maydell
                        case NEON_2RM_VCEQ0_F:
6028 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
6029 dd8fbd78 Filip Navara
                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
6030 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
6031 9ee6e8bb pbrook
                            break;
6032 600b828c Peter Maydell
                        case NEON_2RM_VCLE0_F:
6033 0e326109 Peter Maydell
                            tmp2 = tcg_const_i32(0);
6034 0e326109 Peter Maydell
                            gen_helper_neon_cge_f32(tmp, tmp2, tmp);
6035 0e326109 Peter Maydell
                            tcg_temp_free(tmp2);
6036 0e326109 Peter Maydell
                            break;
6037 600b828c Peter Maydell
                        case NEON_2RM_VCLT0_F:
6038 0e326109 Peter Maydell
                            tmp2 = tcg_const_i32(0);
6039 0e326109 Peter Maydell
                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
6040 0e326109 Peter Maydell
                            tcg_temp_free(tmp2);
6041 0e326109 Peter Maydell
                            break;
6042 600b828c Peter Maydell
                        case NEON_2RM_VABS_F:
6043 4373f3ce pbrook
                            gen_vfp_abs(0);
6044 9ee6e8bb pbrook
                            break;
6045 600b828c Peter Maydell
                        case NEON_2RM_VNEG_F:
6046 4373f3ce pbrook
                            gen_vfp_neg(0);
6047 9ee6e8bb pbrook
                            break;
6048 600b828c Peter Maydell
                        case NEON_2RM_VSWP:
6049 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
6050 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
6051 9ee6e8bb pbrook
                            break;
6052 600b828c Peter Maydell
                        case NEON_2RM_VTRN:
6053 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
6054 9ee6e8bb pbrook
                            switch (size) {
6055 dd8fbd78 Filip Navara
                            case 0: gen_neon_trn_u8(tmp, tmp2); break;
6056 dd8fbd78 Filip Navara
                            case 1: gen_neon_trn_u16(tmp, tmp2); break;
6057 600b828c Peter Maydell
                            default: abort();
6058 9ee6e8bb pbrook
                            }
6059 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
6060 9ee6e8bb pbrook
                            break;
6061 600b828c Peter Maydell
                        case NEON_2RM_VRECPE:
6062 dd8fbd78 Filip Navara
                            gen_helper_recpe_u32(tmp, tmp, cpu_env);
6063 9ee6e8bb pbrook
                            break;
6064 600b828c Peter Maydell
                        case NEON_2RM_VRSQRTE:
6065 dd8fbd78 Filip Navara
                            gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6066 9ee6e8bb pbrook
                            break;
6067 600b828c Peter Maydell
                        case NEON_2RM_VRECPE_F:
6068 4373f3ce pbrook
                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6069 9ee6e8bb pbrook
                            break;
6070 600b828c Peter Maydell
                        case NEON_2RM_VRSQRTE_F:
6071 4373f3ce pbrook
                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6072 9ee6e8bb pbrook
                            break;
6073 600b828c Peter Maydell
                        case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6074 d3587ef8 Peter Maydell
                            gen_vfp_sito(0);
6075 9ee6e8bb pbrook
                            break;
6076 600b828c Peter Maydell
                        case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6077 d3587ef8 Peter Maydell
                            gen_vfp_uito(0);
6078 9ee6e8bb pbrook
                            break;
6079 600b828c Peter Maydell
                        case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6080 d3587ef8 Peter Maydell
                            gen_vfp_tosiz(0);
6081 9ee6e8bb pbrook
                            break;
6082 600b828c Peter Maydell
                        case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6083 d3587ef8 Peter Maydell
                            gen_vfp_touiz(0);
6084 9ee6e8bb pbrook
                            break;
6085 9ee6e8bb pbrook
                        default:
6086 600b828c Peter Maydell
                            /* Reserved op values were caught by the
6087 600b828c Peter Maydell
                             * neon_2rm_sizes[] check earlier.
6088 600b828c Peter Maydell
                             */
6089 600b828c Peter Maydell
                            abort();
6090 9ee6e8bb pbrook
                        }
6091 600b828c Peter Maydell
                        if (neon_2rm_is_float_op(op)) {
6092 4373f3ce pbrook
                            tcg_gen_st_f32(cpu_F0s, cpu_env,
6093 4373f3ce pbrook
                                           neon_reg_offset(rd, pass));
6094 9ee6e8bb pbrook
                        } else {
6095 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass, tmp);
6096 9ee6e8bb pbrook
                        }
6097 9ee6e8bb pbrook
                    }
6098 9ee6e8bb pbrook
                    break;
6099 9ee6e8bb pbrook
                }
6100 9ee6e8bb pbrook
            } else if ((insn & (1 << 10)) == 0) {
6101 9ee6e8bb pbrook
                /* VTBL, VTBX.  */
6102 56907d77 Peter Maydell
                int n = ((insn >> 8) & 3) + 1;
6103 56907d77 Peter Maydell
                if ((rn + n) > 32) {
6104 56907d77 Peter Maydell
                    /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6105 56907d77 Peter Maydell
                     * helper function running off the end of the register file.
6106 56907d77 Peter Maydell
                     */
6107 56907d77 Peter Maydell
                    return 1;
6108 56907d77 Peter Maydell
                }
6109 56907d77 Peter Maydell
                n <<= 3;
6110 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
6111 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 0);
6112 9ee6e8bb pbrook
                } else {
6113 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
6114 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
6115 9ee6e8bb pbrook
                }
6116 8f8e3aa4 pbrook
                tmp2 = neon_load_reg(rm, 0);
6117 b75263d6 Juha Riihimäki
                tmp4 = tcg_const_i32(rn);
6118 b75263d6 Juha Riihimäki
                tmp5 = tcg_const_i32(n);
6119 b75263d6 Juha Riihimäki
                gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
6120 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
6121 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
6122 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 1);
6123 9ee6e8bb pbrook
                } else {
6124 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
6125 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
6126 9ee6e8bb pbrook
                }
6127 8f8e3aa4 pbrook
                tmp3 = neon_load_reg(rm, 1);
6128 b75263d6 Juha Riihimäki
                gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
6129 25aeb69b Juha Riihimäki
                tcg_temp_free_i32(tmp5);
6130 25aeb69b Juha Riihimäki
                tcg_temp_free_i32(tmp4);
6131 8f8e3aa4 pbrook
                neon_store_reg(rd, 0, tmp2);
6132 3018f259 pbrook
                neon_store_reg(rd, 1, tmp3);
6133 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
6134 9ee6e8bb pbrook
            } else if ((insn & 0x380) == 0) {
6135 9ee6e8bb pbrook
                /* VDUP */
6136 133da6aa Juha Riihimäki
                if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6137 133da6aa Juha Riihimäki
                    return 1;
6138 133da6aa Juha Riihimäki
                }
6139 9ee6e8bb pbrook
                if (insn & (1 << 19)) {
6140 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
6141 9ee6e8bb pbrook
                } else {
6142 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 0);
6143 9ee6e8bb pbrook
                }
6144 9ee6e8bb pbrook
                if (insn & (1 << 16)) {
6145 dd8fbd78 Filip Navara
                    gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6146 9ee6e8bb pbrook
                } else if (insn & (1 << 17)) {
6147 9ee6e8bb pbrook
                    if ((insn >> 18) & 1)
6148 dd8fbd78 Filip Navara
                        gen_neon_dup_high16(tmp);
6149 9ee6e8bb pbrook
                    else
6150 dd8fbd78 Filip Navara
                        gen_neon_dup_low16(tmp);
6151 9ee6e8bb pbrook
                }
6152 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
6153 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
6154 dd8fbd78 Filip Navara
                    tcg_gen_mov_i32(tmp2, tmp);
6155 dd8fbd78 Filip Navara
                    neon_store_reg(rd, pass, tmp2);
6156 9ee6e8bb pbrook
                }
6157 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
6158 9ee6e8bb pbrook
            } else {
6159 9ee6e8bb pbrook
                return 1;
6160 9ee6e8bb pbrook
            }
6161 9ee6e8bb pbrook
        }
6162 9ee6e8bb pbrook
    }
6163 9ee6e8bb pbrook
    return 0;
6164 9ee6e8bb pbrook
}
6165 9ee6e8bb pbrook
6166 fe1479c3 pbrook
static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
6167 fe1479c3 pbrook
{
6168 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
6169 fe1479c3 pbrook
    int crm = insn & 0xf;
6170 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
6171 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
6172 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
6173 fe1479c3 pbrook
    TCGv tmp;
6174 fe1479c3 pbrook
6175 ca27c052 Peter Maydell
    /* Minimal set of debug registers, since we don't support debug */
6176 ca27c052 Peter Maydell
    if (op1 == 0 && crn == 0 && op2 == 0) {
6177 ca27c052 Peter Maydell
        switch (crm) {
6178 ca27c052 Peter Maydell
        case 0:
6179 ca27c052 Peter Maydell
            /* DBGDIDR: just RAZ. In particular this means the
6180 ca27c052 Peter Maydell
             * "debug architecture version" bits will read as
6181 ca27c052 Peter Maydell
             * a reserved value, which should cause Linux to
6182 ca27c052 Peter Maydell
             * not try to use the debug hardware.
6183 ca27c052 Peter Maydell
             */
6184 ca27c052 Peter Maydell
            tmp = tcg_const_i32(0);
6185 ca27c052 Peter Maydell
            store_reg(s, rt, tmp);
6186 ca27c052 Peter Maydell
            return 0;
6187 ca27c052 Peter Maydell
        case 1:
6188 ca27c052 Peter Maydell
        case 2:
6189 ca27c052 Peter Maydell
            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
6190 ca27c052 Peter Maydell
             * don't implement memory mapped debug components
6191 ca27c052 Peter Maydell
             */
6192 ca27c052 Peter Maydell
            if (ENABLE_ARCH_7) {
6193 ca27c052 Peter Maydell
                tmp = tcg_const_i32(0);
6194 ca27c052 Peter Maydell
                store_reg(s, rt, tmp);
6195 ca27c052 Peter Maydell
                return 0;
6196 ca27c052 Peter Maydell
            }
6197 ca27c052 Peter Maydell
            break;
6198 ca27c052 Peter Maydell
        default:
6199 ca27c052 Peter Maydell
            break;
6200 ca27c052 Peter Maydell
        }
6201 ca27c052 Peter Maydell
    }
6202 ca27c052 Peter Maydell
6203 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6204 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6205 fe1479c3 pbrook
            /* TEECR */
6206 fe1479c3 pbrook
            if (IS_USER(s))
6207 fe1479c3 pbrook
                return 1;
6208 fe1479c3 pbrook
            tmp = load_cpu_field(teecr);
6209 fe1479c3 pbrook
            store_reg(s, rt, tmp);
6210 fe1479c3 pbrook
            return 0;
6211 fe1479c3 pbrook
        }
6212 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6213 fe1479c3 pbrook
            /* TEEHBR */
6214 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
6215 fe1479c3 pbrook
                return 1;
6216 fe1479c3 pbrook
            tmp = load_cpu_field(teehbr);
6217 fe1479c3 pbrook
            store_reg(s, rt, tmp);
6218 fe1479c3 pbrook
            return 0;
6219 fe1479c3 pbrook
        }
6220 fe1479c3 pbrook
    }
6221 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
6222 fe1479c3 pbrook
            op1, crn, crm, op2);
6223 fe1479c3 pbrook
    return 1;
6224 fe1479c3 pbrook
}
6225 fe1479c3 pbrook
6226 fe1479c3 pbrook
static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
6227 fe1479c3 pbrook
{
6228 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
6229 fe1479c3 pbrook
    int crm = insn & 0xf;
6230 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
6231 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
6232 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
6233 fe1479c3 pbrook
    TCGv tmp;
6234 fe1479c3 pbrook
6235 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6236 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6237 fe1479c3 pbrook
            /* TEECR */
6238 fe1479c3 pbrook
            if (IS_USER(s))
6239 fe1479c3 pbrook
                return 1;
6240 fe1479c3 pbrook
            tmp = load_reg(s, rt);
6241 fe1479c3 pbrook
            gen_helper_set_teecr(cpu_env, tmp);
6242 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
6243 fe1479c3 pbrook
            return 0;
6244 fe1479c3 pbrook
        }
6245 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6246 fe1479c3 pbrook
            /* TEEHBR */
6247 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
6248 fe1479c3 pbrook
                return 1;
6249 fe1479c3 pbrook
            tmp = load_reg(s, rt);
6250 fe1479c3 pbrook
            store_cpu_field(tmp, teehbr);
6251 fe1479c3 pbrook
            return 0;
6252 fe1479c3 pbrook
        }
6253 fe1479c3 pbrook
    }
6254 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
6255 fe1479c3 pbrook
            op1, crn, crm, op2);
6256 fe1479c3 pbrook
    return 1;
6257 fe1479c3 pbrook
}
6258 fe1479c3 pbrook
6259 9ee6e8bb pbrook
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
6260 9ee6e8bb pbrook
{
6261 9ee6e8bb pbrook
    int cpnum;
6262 9ee6e8bb pbrook
6263 9ee6e8bb pbrook
    cpnum = (insn >> 8) & 0xf;
6264 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_XSCALE)
6265 9ee6e8bb pbrook
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6266 9ee6e8bb pbrook
        return 1;
6267 9ee6e8bb pbrook
6268 9ee6e8bb pbrook
    switch (cpnum) {
6269 9ee6e8bb pbrook
      case 0:
6270 9ee6e8bb pbrook
      case 1:
6271 9ee6e8bb pbrook
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6272 9ee6e8bb pbrook
            return disas_iwmmxt_insn(env, s, insn);
6273 9ee6e8bb pbrook
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6274 9ee6e8bb pbrook
            return disas_dsp_insn(env, s, insn);
6275 9ee6e8bb pbrook
        }
6276 9ee6e8bb pbrook
        return 1;
6277 9ee6e8bb pbrook
    case 10:
6278 9ee6e8bb pbrook
    case 11:
6279 9ee6e8bb pbrook
        return disas_vfp_insn (env, s, insn);
6280 fe1479c3 pbrook
    case 14:
6281 fe1479c3 pbrook
        /* Coprocessors 7-15 are architecturally reserved by ARM.
6282 fe1479c3 pbrook
           Unfortunately Intel decided to ignore this.  */
6283 fe1479c3 pbrook
        if (arm_feature(env, ARM_FEATURE_XSCALE))
6284 fe1479c3 pbrook
            goto board;
6285 fe1479c3 pbrook
        if (insn & (1 << 20))
6286 fe1479c3 pbrook
            return disas_cp14_read(env, s, insn);
6287 fe1479c3 pbrook
        else
6288 fe1479c3 pbrook
            return disas_cp14_write(env, s, insn);
6289 9ee6e8bb pbrook
    case 15:
6290 9ee6e8bb pbrook
        return disas_cp15_insn (env, s, insn);
6291 9ee6e8bb pbrook
    default:
6292 fe1479c3 pbrook
    board:
6293 9ee6e8bb pbrook
        /* Unknown coprocessor.  See if the board has hooked it.  */
6294 9ee6e8bb pbrook
        return disas_cp_insn (env, s, insn);
6295 9ee6e8bb pbrook
    }
6296 9ee6e8bb pbrook
}
6297 9ee6e8bb pbrook
6298 5e3f878a pbrook
6299 5e3f878a pbrook
/* Store a 64-bit value to a register pair.  Clobbers val.  */
6300 a7812ae4 pbrook
static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6301 5e3f878a pbrook
{
6302 5e3f878a pbrook
    TCGv tmp;
6303 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
6304 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
6305 5e3f878a pbrook
    store_reg(s, rlow, tmp);
6306 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
6307 5e3f878a pbrook
    tcg_gen_shri_i64(val, val, 32);
6308 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
6309 5e3f878a pbrook
    store_reg(s, rhigh, tmp);
6310 5e3f878a pbrook
}
6311 5e3f878a pbrook
6312 5e3f878a pbrook
/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
6313 a7812ae4 pbrook
static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6314 5e3f878a pbrook
{
6315 a7812ae4 pbrook
    TCGv_i64 tmp;
6316 5e3f878a pbrook
    TCGv tmp2;
6317 5e3f878a pbrook
6318 36aa55dc pbrook
    /* Load value and extend to 64 bits.  */
6319 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
6320 5e3f878a pbrook
    tmp2 = load_reg(s, rlow);
6321 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp, tmp2);
6322 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp2);
6323 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
6324 b75263d6 Juha Riihimäki
    tcg_temp_free_i64(tmp);
6325 5e3f878a pbrook
}
6326 5e3f878a pbrook
6327 5e3f878a pbrook
/* load and add a 64-bit value from a register pair.  */
6328 a7812ae4 pbrook
static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6329 5e3f878a pbrook
{
6330 a7812ae4 pbrook
    TCGv_i64 tmp;
6331 36aa55dc pbrook
    TCGv tmpl;
6332 36aa55dc pbrook
    TCGv tmph;
6333 5e3f878a pbrook
6334 5e3f878a pbrook
    /* Load 64-bit value rd:rn.  */
6335 36aa55dc pbrook
    tmpl = load_reg(s, rlow);
6336 36aa55dc pbrook
    tmph = load_reg(s, rhigh);
6337 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
6338 36aa55dc pbrook
    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6339 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmpl);
6340 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmph);
6341 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
6342 b75263d6 Juha Riihimäki
    tcg_temp_free_i64(tmp);
6343 5e3f878a pbrook
}
6344 5e3f878a pbrook
6345 5e3f878a pbrook
/* Set N and Z flags from a 64-bit value.  */
6346 a7812ae4 pbrook
static void gen_logicq_cc(TCGv_i64 val)
6347 5e3f878a pbrook
{
6348 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
6349 5e3f878a pbrook
    gen_helper_logicq_cc(tmp, val);
6350 6fbe23d5 pbrook
    gen_logic_CC(tmp);
6351 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
6352 5e3f878a pbrook
}
6353 5e3f878a pbrook
6354 426f5abc Paul Brook
/* Load/Store exclusive instructions are implemented by remembering
6355 426f5abc Paul Brook
   the value/address loaded, and seeing if these are the same
6356 426f5abc Paul Brook
   when the store is performed. This should be is sufficient to implement
6357 426f5abc Paul Brook
   the architecturally mandated semantics, and avoids having to monitor
6358 426f5abc Paul Brook
   regular stores.
6359 426f5abc Paul Brook

6360 426f5abc Paul Brook
   In system emulation mode only one CPU will be running at once, so
6361 426f5abc Paul Brook
   this sequence is effectively atomic.  In user emulation mode we
6362 426f5abc Paul Brook
   throw an exception and handle the atomic operation elsewhere.  */
6363 426f5abc Paul Brook
static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6364 426f5abc Paul Brook
                               TCGv addr, int size)
6365 426f5abc Paul Brook
{
6366 426f5abc Paul Brook
    TCGv tmp;
6367 426f5abc Paul Brook
6368 426f5abc Paul Brook
    switch (size) {
6369 426f5abc Paul Brook
    case 0:
6370 426f5abc Paul Brook
        tmp = gen_ld8u(addr, IS_USER(s));
6371 426f5abc Paul Brook
        break;
6372 426f5abc Paul Brook
    case 1:
6373 426f5abc Paul Brook
        tmp = gen_ld16u(addr, IS_USER(s));
6374 426f5abc Paul Brook
        break;
6375 426f5abc Paul Brook
    case 2:
6376 426f5abc Paul Brook
    case 3:
6377 426f5abc Paul Brook
        tmp = gen_ld32(addr, IS_USER(s));
6378 426f5abc Paul Brook
        break;
6379 426f5abc Paul Brook
    default:
6380 426f5abc Paul Brook
        abort();
6381 426f5abc Paul Brook
    }
6382 426f5abc Paul Brook
    tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6383 426f5abc Paul Brook
    store_reg(s, rt, tmp);
6384 426f5abc Paul Brook
    if (size == 3) {
6385 7d1b0095 Peter Maydell
        TCGv tmp2 = tcg_temp_new_i32();
6386 2c9adbda Peter Maydell
        tcg_gen_addi_i32(tmp2, addr, 4);
6387 2c9adbda Peter Maydell
        tmp = gen_ld32(tmp2, IS_USER(s));
6388 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
6389 426f5abc Paul Brook
        tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6390 426f5abc Paul Brook
        store_reg(s, rt2, tmp);
6391 426f5abc Paul Brook
    }
6392 426f5abc Paul Brook
    tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6393 426f5abc Paul Brook
}
6394 426f5abc Paul Brook
6395 426f5abc Paul Brook
static void gen_clrex(DisasContext *s)
6396 426f5abc Paul Brook
{
6397 426f5abc Paul Brook
    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6398 426f5abc Paul Brook
}
6399 426f5abc Paul Brook
6400 426f5abc Paul Brook
#ifdef CONFIG_USER_ONLY
6401 426f5abc Paul Brook
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6402 426f5abc Paul Brook
                                TCGv addr, int size)
6403 426f5abc Paul Brook
{
6404 426f5abc Paul Brook
    tcg_gen_mov_i32(cpu_exclusive_test, addr);
6405 426f5abc Paul Brook
    tcg_gen_movi_i32(cpu_exclusive_info,
6406 426f5abc Paul Brook
                     size | (rd << 4) | (rt << 8) | (rt2 << 12));
6407 bc4a0de0 Peter Maydell
    gen_exception_insn(s, 4, EXCP_STREX);
6408 426f5abc Paul Brook
}
6409 426f5abc Paul Brook
#else
6410 426f5abc Paul Brook
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6411 426f5abc Paul Brook
                                TCGv addr, int size)
6412 426f5abc Paul Brook
{
6413 426f5abc Paul Brook
    TCGv tmp;
6414 426f5abc Paul Brook
    int done_label;
6415 426f5abc Paul Brook
    int fail_label;
6416 426f5abc Paul Brook
6417 426f5abc Paul Brook
    /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6418 426f5abc Paul Brook
         [addr] = {Rt};
6419 426f5abc Paul Brook
         {Rd} = 0;
6420 426f5abc Paul Brook
       } else {
6421 426f5abc Paul Brook
         {Rd} = 1;
6422 426f5abc Paul Brook
       } */
6423 426f5abc Paul Brook
    fail_label = gen_new_label();
6424 426f5abc Paul Brook
    done_label = gen_new_label();
6425 426f5abc Paul Brook
    tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6426 426f5abc Paul Brook
    switch (size) {
6427 426f5abc Paul Brook
    case 0:
6428 426f5abc Paul Brook
        tmp = gen_ld8u(addr, IS_USER(s));
6429 426f5abc Paul Brook
        break;
6430 426f5abc Paul Brook
    case 1:
6431 426f5abc Paul Brook
        tmp = gen_ld16u(addr, IS_USER(s));
6432 426f5abc Paul Brook
        break;
6433 426f5abc Paul Brook
    case 2:
6434 426f5abc Paul Brook
    case 3:
6435 426f5abc Paul Brook
        tmp = gen_ld32(addr, IS_USER(s));
6436 426f5abc Paul Brook
        break;
6437 426f5abc Paul Brook
    default:
6438 426f5abc Paul Brook
        abort();
6439 426f5abc Paul Brook
    }
6440 426f5abc Paul Brook
    tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6441 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
6442 426f5abc Paul Brook
    if (size == 3) {
6443 7d1b0095 Peter Maydell
        TCGv tmp2 = tcg_temp_new_i32();
6444 426f5abc Paul Brook
        tcg_gen_addi_i32(tmp2, addr, 4);
6445 2c9adbda Peter Maydell
        tmp = gen_ld32(tmp2, IS_USER(s));
6446 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
6447 426f5abc Paul Brook
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6448 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
6449 426f5abc Paul Brook
    }
6450 426f5abc Paul Brook
    tmp = load_reg(s, rt);
6451 426f5abc Paul Brook
    switch (size) {
6452 426f5abc Paul Brook
    case 0:
6453 426f5abc Paul Brook
        gen_st8(tmp, addr, IS_USER(s));
6454 426f5abc Paul Brook
        break;
6455 426f5abc Paul Brook
    case 1:
6456 426f5abc Paul Brook
        gen_st16(tmp, addr, IS_USER(s));
6457 426f5abc Paul Brook
        break;
6458 426f5abc Paul Brook
    case 2:
6459 426f5abc Paul Brook
    case 3:
6460 426f5abc Paul Brook
        gen_st32(tmp, addr, IS_USER(s));
6461 426f5abc Paul Brook
        break;
6462 426f5abc Paul Brook
    default:
6463 426f5abc Paul Brook
        abort();
6464 426f5abc Paul Brook
    }
6465 426f5abc Paul Brook
    if (size == 3) {
6466 426f5abc Paul Brook
        tcg_gen_addi_i32(addr, addr, 4);
6467 426f5abc Paul Brook
        tmp = load_reg(s, rt2);
6468 426f5abc Paul Brook
        gen_st32(tmp, addr, IS_USER(s));
6469 426f5abc Paul Brook
    }
6470 426f5abc Paul Brook
    tcg_gen_movi_i32(cpu_R[rd], 0);
6471 426f5abc Paul Brook
    tcg_gen_br(done_label);
6472 426f5abc Paul Brook
    gen_set_label(fail_label);
6473 426f5abc Paul Brook
    tcg_gen_movi_i32(cpu_R[rd], 1);
6474 426f5abc Paul Brook
    gen_set_label(done_label);
6475 426f5abc Paul Brook
    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6476 426f5abc Paul Brook
}
6477 426f5abc Paul Brook
#endif
6478 426f5abc Paul Brook
6479 9ee6e8bb pbrook
static void disas_arm_insn(CPUState * env, DisasContext *s)
6480 9ee6e8bb pbrook
{
6481 9ee6e8bb pbrook
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6482 b26eefb6 pbrook
    TCGv tmp;
6483 3670669c pbrook
    TCGv tmp2;
6484 6ddbc6e4 pbrook
    TCGv tmp3;
6485 b0109805 pbrook
    TCGv addr;
6486 a7812ae4 pbrook
    TCGv_i64 tmp64;
6487 9ee6e8bb pbrook
6488 9ee6e8bb pbrook
    insn = ldl_code(s->pc);
6489 9ee6e8bb pbrook
    s->pc += 4;
6490 9ee6e8bb pbrook
6491 9ee6e8bb pbrook
    /* M variants do not implement ARM mode.  */
6492 9ee6e8bb pbrook
    if (IS_M(env))
6493 9ee6e8bb pbrook
        goto illegal_op;
6494 9ee6e8bb pbrook
    cond = insn >> 28;
6495 9ee6e8bb pbrook
    if (cond == 0xf){
6496 be5e7a76 Dmitry Eremin-Solenikov
        /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6497 be5e7a76 Dmitry Eremin-Solenikov
         * choose to UNDEF. In ARMv5 and above the space is used
6498 be5e7a76 Dmitry Eremin-Solenikov
         * for miscellaneous unconditional instructions.
6499 be5e7a76 Dmitry Eremin-Solenikov
         */
6500 be5e7a76 Dmitry Eremin-Solenikov
        ARCH(5);
6501 be5e7a76 Dmitry Eremin-Solenikov
6502 9ee6e8bb pbrook
        /* Unconditional instructions.  */
6503 9ee6e8bb pbrook
        if (((insn >> 25) & 7) == 1) {
6504 9ee6e8bb pbrook
            /* NEON Data processing.  */
6505 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_NEON))
6506 9ee6e8bb pbrook
                goto illegal_op;
6507 9ee6e8bb pbrook
6508 9ee6e8bb pbrook
            if (disas_neon_data_insn(env, s, insn))
6509 9ee6e8bb pbrook
                goto illegal_op;
6510 9ee6e8bb pbrook
            return;
6511 9ee6e8bb pbrook
        }
6512 9ee6e8bb pbrook
        if ((insn & 0x0f100000) == 0x04000000) {
6513 9ee6e8bb pbrook
            /* NEON load/store.  */
6514 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_NEON))
6515 9ee6e8bb pbrook
                goto illegal_op;
6516 9ee6e8bb pbrook
6517 9ee6e8bb pbrook
            if (disas_neon_ls_insn(env, s, insn))
6518 9ee6e8bb pbrook
                goto illegal_op;
6519 9ee6e8bb pbrook
            return;
6520 9ee6e8bb pbrook
        }
6521 3d185e5d Peter Maydell
        if (((insn & 0x0f30f000) == 0x0510f000) ||
6522 3d185e5d Peter Maydell
            ((insn & 0x0f30f010) == 0x0710f000)) {
6523 3d185e5d Peter Maydell
            if ((insn & (1 << 22)) == 0) {
6524 3d185e5d Peter Maydell
                /* PLDW; v7MP */
6525 3d185e5d Peter Maydell
                if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6526 3d185e5d Peter Maydell
                    goto illegal_op;
6527 3d185e5d Peter Maydell
                }
6528 3d185e5d Peter Maydell
            }
6529 3d185e5d Peter Maydell
            /* Otherwise PLD; v5TE+ */
6530 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5TE);
6531 3d185e5d Peter Maydell
            return;
6532 3d185e5d Peter Maydell
        }
6533 3d185e5d Peter Maydell
        if (((insn & 0x0f70f000) == 0x0450f000) ||
6534 3d185e5d Peter Maydell
            ((insn & 0x0f70f010) == 0x0650f000)) {
6535 3d185e5d Peter Maydell
            ARCH(7);
6536 3d185e5d Peter Maydell
            return; /* PLI; V7 */
6537 3d185e5d Peter Maydell
        }
6538 3d185e5d Peter Maydell
        if (((insn & 0x0f700000) == 0x04100000) ||
6539 3d185e5d Peter Maydell
            ((insn & 0x0f700010) == 0x06100000)) {
6540 3d185e5d Peter Maydell
            if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6541 3d185e5d Peter Maydell
                goto illegal_op;
6542 3d185e5d Peter Maydell
            }
6543 3d185e5d Peter Maydell
            return; /* v7MP: Unallocated memory hint: must NOP */
6544 3d185e5d Peter Maydell
        }
6545 3d185e5d Peter Maydell
6546 3d185e5d Peter Maydell
        if ((insn & 0x0ffffdff) == 0x01010000) {
6547 9ee6e8bb pbrook
            ARCH(6);
6548 9ee6e8bb pbrook
            /* setend */
6549 9ee6e8bb pbrook
            if (insn & (1 << 9)) {
6550 9ee6e8bb pbrook
                /* BE8 mode not implemented.  */
6551 9ee6e8bb pbrook
                goto illegal_op;
6552 9ee6e8bb pbrook
            }
6553 9ee6e8bb pbrook
            return;
6554 9ee6e8bb pbrook
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
6555 9ee6e8bb pbrook
            switch ((insn >> 4) & 0xf) {
6556 9ee6e8bb pbrook
            case 1: /* clrex */
6557 9ee6e8bb pbrook
                ARCH(6K);
6558 426f5abc Paul Brook
                gen_clrex(s);
6559 9ee6e8bb pbrook
                return;
6560 9ee6e8bb pbrook
            case 4: /* dsb */
6561 9ee6e8bb pbrook
            case 5: /* dmb */
6562 9ee6e8bb pbrook
            case 6: /* isb */
6563 9ee6e8bb pbrook
                ARCH(7);
6564 9ee6e8bb pbrook
                /* We don't emulate caches so these are a no-op.  */
6565 9ee6e8bb pbrook
                return;
6566 9ee6e8bb pbrook
            default:
6567 9ee6e8bb pbrook
                goto illegal_op;
6568 9ee6e8bb pbrook
            }
6569 9ee6e8bb pbrook
        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6570 9ee6e8bb pbrook
            /* srs */
6571 c67b6b71 Filip Navara
            int32_t offset;
6572 9ee6e8bb pbrook
            if (IS_USER(s))
6573 9ee6e8bb pbrook
                goto illegal_op;
6574 9ee6e8bb pbrook
            ARCH(6);
6575 9ee6e8bb pbrook
            op1 = (insn & 0x1f);
6576 7d1b0095 Peter Maydell
            addr = tcg_temp_new_i32();
6577 39ea3d4e Peter Maydell
            tmp = tcg_const_i32(op1);
6578 39ea3d4e Peter Maydell
            gen_helper_get_r13_banked(addr, cpu_env, tmp);
6579 39ea3d4e Peter Maydell
            tcg_temp_free_i32(tmp);
6580 9ee6e8bb pbrook
            i = (insn >> 23) & 3;
6581 9ee6e8bb pbrook
            switch (i) {
6582 9ee6e8bb pbrook
            case 0: offset = -4; break; /* DA */
6583 c67b6b71 Filip Navara
            case 1: offset = 0; break; /* IA */
6584 c67b6b71 Filip Navara
            case 2: offset = -8; break; /* DB */
6585 9ee6e8bb pbrook
            case 3: offset = 4; break; /* IB */
6586 9ee6e8bb pbrook
            default: abort();
6587 9ee6e8bb pbrook
            }
6588 9ee6e8bb pbrook
            if (offset)
6589 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, offset);
6590 b0109805 pbrook
            tmp = load_reg(s, 14);
6591 b0109805 pbrook
            gen_st32(tmp, addr, 0);
6592 c67b6b71 Filip Navara
            tmp = load_cpu_field(spsr);
6593 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, 4);
6594 b0109805 pbrook
            gen_st32(tmp, addr, 0);
6595 9ee6e8bb pbrook
            if (insn & (1 << 21)) {
6596 9ee6e8bb pbrook
                /* Base writeback.  */
6597 9ee6e8bb pbrook
                switch (i) {
6598 9ee6e8bb pbrook
                case 0: offset = -8; break;
6599 c67b6b71 Filip Navara
                case 1: offset = 4; break;
6600 c67b6b71 Filip Navara
                case 2: offset = -4; break;
6601 9ee6e8bb pbrook
                case 3: offset = 0; break;
6602 9ee6e8bb pbrook
                default: abort();
6603 9ee6e8bb pbrook
                }
6604 9ee6e8bb pbrook
                if (offset)
6605 c67b6b71 Filip Navara
                    tcg_gen_addi_i32(addr, addr, offset);
6606 39ea3d4e Peter Maydell
                tmp = tcg_const_i32(op1);
6607 39ea3d4e Peter Maydell
                gen_helper_set_r13_banked(cpu_env, tmp, addr);
6608 39ea3d4e Peter Maydell
                tcg_temp_free_i32(tmp);
6609 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
6610 b0109805 pbrook
            } else {
6611 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
6612 9ee6e8bb pbrook
            }
6613 a990f58f Adam Lackorzynski
            return;
6614 ea825eee Adam Lackorzynski
        } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6615 9ee6e8bb pbrook
            /* rfe */
6616 c67b6b71 Filip Navara
            int32_t offset;
6617 9ee6e8bb pbrook
            if (IS_USER(s))
6618 9ee6e8bb pbrook
                goto illegal_op;
6619 9ee6e8bb pbrook
            ARCH(6);
6620 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6621 b0109805 pbrook
            addr = load_reg(s, rn);
6622 9ee6e8bb pbrook
            i = (insn >> 23) & 3;
6623 9ee6e8bb pbrook
            switch (i) {
6624 b0109805 pbrook
            case 0: offset = -4; break; /* DA */
6625 c67b6b71 Filip Navara
            case 1: offset = 0; break; /* IA */
6626 c67b6b71 Filip Navara
            case 2: offset = -8; break; /* DB */
6627 b0109805 pbrook
            case 3: offset = 4; break; /* IB */
6628 9ee6e8bb pbrook
            default: abort();
6629 9ee6e8bb pbrook
            }
6630 9ee6e8bb pbrook
            if (offset)
6631 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, offset);
6632 b0109805 pbrook
            /* Load PC into tmp and CPSR into tmp2.  */
6633 b0109805 pbrook
            tmp = gen_ld32(addr, 0);
6634 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, 4);
6635 b0109805 pbrook
            tmp2 = gen_ld32(addr, 0);
6636 9ee6e8bb pbrook
            if (insn & (1 << 21)) {
6637 9ee6e8bb pbrook
                /* Base writeback.  */
6638 9ee6e8bb pbrook
                switch (i) {
6639 b0109805 pbrook
                case 0: offset = -8; break;
6640 c67b6b71 Filip Navara
                case 1: offset = 4; break;
6641 c67b6b71 Filip Navara
                case 2: offset = -4; break;
6642 b0109805 pbrook
                case 3: offset = 0; break;
6643 9ee6e8bb pbrook
                default: abort();
6644 9ee6e8bb pbrook
                }
6645 9ee6e8bb pbrook
                if (offset)
6646 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset);
6647 b0109805 pbrook
                store_reg(s, rn, addr);
6648 b0109805 pbrook
            } else {
6649 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
6650 9ee6e8bb pbrook
            }
6651 b0109805 pbrook
            gen_rfe(s, tmp, tmp2);
6652 c67b6b71 Filip Navara
            return;
6653 9ee6e8bb pbrook
        } else if ((insn & 0x0e000000) == 0x0a000000) {
6654 9ee6e8bb pbrook
            /* branch link and change to thumb (blx <offset>) */
6655 9ee6e8bb pbrook
            int32_t offset;
6656 9ee6e8bb pbrook
6657 9ee6e8bb pbrook
            val = (uint32_t)s->pc;
6658 7d1b0095 Peter Maydell
            tmp = tcg_temp_new_i32();
6659 d9ba4830 pbrook
            tcg_gen_movi_i32(tmp, val);
6660 d9ba4830 pbrook
            store_reg(s, 14, tmp);
6661 9ee6e8bb pbrook
            /* Sign-extend the 24-bit offset */
6662 9ee6e8bb pbrook
            offset = (((int32_t)insn) << 8) >> 8;
6663 9ee6e8bb pbrook
            /* offset * 4 + bit24 * 2 + (thumb bit) */
6664 9ee6e8bb pbrook
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
6665 9ee6e8bb pbrook
            /* pipeline offset */
6666 9ee6e8bb pbrook
            val += 4;
6667 be5e7a76 Dmitry Eremin-Solenikov
            /* protected by ARCH(5); above, near the start of uncond block */
6668 d9ba4830 pbrook
            gen_bx_im(s, val);
6669 9ee6e8bb pbrook
            return;
6670 9ee6e8bb pbrook
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
6671 9ee6e8bb pbrook
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6672 9ee6e8bb pbrook
                /* iWMMXt register transfer.  */
6673 9ee6e8bb pbrook
                if (env->cp15.c15_cpar & (1 << 1))
6674 9ee6e8bb pbrook
                    if (!disas_iwmmxt_insn(env, s, insn))
6675 9ee6e8bb pbrook
                        return;
6676 9ee6e8bb pbrook
            }
6677 9ee6e8bb pbrook
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
6678 9ee6e8bb pbrook
            /* Coprocessor double register transfer.  */
6679 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5TE);
6680 9ee6e8bb pbrook
        } else if ((insn & 0x0f000010) == 0x0e000010) {
6681 9ee6e8bb pbrook
            /* Additional coprocessor register transfer.  */
6682 7997d92f balrog
        } else if ((insn & 0x0ff10020) == 0x01000000) {
6683 9ee6e8bb pbrook
            uint32_t mask;
6684 9ee6e8bb pbrook
            uint32_t val;
6685 9ee6e8bb pbrook
            /* cps (privileged) */
6686 9ee6e8bb pbrook
            if (IS_USER(s))
6687 9ee6e8bb pbrook
                return;
6688 9ee6e8bb pbrook
            mask = val = 0;
6689 9ee6e8bb pbrook
            if (insn & (1 << 19)) {
6690 9ee6e8bb pbrook
                if (insn & (1 << 8))
6691 9ee6e8bb pbrook
                    mask |= CPSR_A;
6692 9ee6e8bb pbrook
                if (insn & (1 << 7))
6693 9ee6e8bb pbrook
                    mask |= CPSR_I;
6694 9ee6e8bb pbrook
                if (insn & (1 << 6))
6695 9ee6e8bb pbrook
                    mask |= CPSR_F;
6696 9ee6e8bb pbrook
                if (insn & (1 << 18))
6697 9ee6e8bb pbrook
                    val |= mask;
6698 9ee6e8bb pbrook
            }
6699 7997d92f balrog
            if (insn & (1 << 17)) {
6700 9ee6e8bb pbrook
                mask |= CPSR_M;
6701 9ee6e8bb pbrook
                val |= (insn & 0x1f);
6702 9ee6e8bb pbrook
            }
6703 9ee6e8bb pbrook
            if (mask) {
6704 2fbac54b Filip Navara
                gen_set_psr_im(s, mask, 0, val);
6705 9ee6e8bb pbrook
            }
6706 9ee6e8bb pbrook
            return;
6707 9ee6e8bb pbrook
        }
6708 9ee6e8bb pbrook
        goto illegal_op;
6709 9ee6e8bb pbrook
    }
6710 9ee6e8bb pbrook
    if (cond != 0xe) {
6711 9ee6e8bb pbrook
        /* if not always execute, we generate a conditional jump to
6712 9ee6e8bb pbrook
           next instruction */
6713 9ee6e8bb pbrook
        s->condlabel = gen_new_label();
6714 d9ba4830 pbrook
        gen_test_cc(cond ^ 1, s->condlabel);
6715 9ee6e8bb pbrook
        s->condjmp = 1;
6716 9ee6e8bb pbrook
    }
6717 9ee6e8bb pbrook
    if ((insn & 0x0f900000) == 0x03000000) {
6718 9ee6e8bb pbrook
        if ((insn & (1 << 21)) == 0) {
6719 9ee6e8bb pbrook
            ARCH(6T2);
6720 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
6721 9ee6e8bb pbrook
            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6722 9ee6e8bb pbrook
            if ((insn & (1 << 22)) == 0) {
6723 9ee6e8bb pbrook
                /* MOVW */
6724 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
6725 5e3f878a pbrook
                tcg_gen_movi_i32(tmp, val);
6726 9ee6e8bb pbrook
            } else {
6727 9ee6e8bb pbrook
                /* MOVT */
6728 5e3f878a pbrook
                tmp = load_reg(s, rd);
6729 86831435 pbrook
                tcg_gen_ext16u_i32(tmp, tmp);
6730 5e3f878a pbrook
                tcg_gen_ori_i32(tmp, tmp, val << 16);
6731 9ee6e8bb pbrook
            }
6732 5e3f878a pbrook
            store_reg(s, rd, tmp);
6733 9ee6e8bb pbrook
        } else {
6734 9ee6e8bb pbrook
            if (((insn >> 12) & 0xf) != 0xf)
6735 9ee6e8bb pbrook
                goto illegal_op;
6736 9ee6e8bb pbrook
            if (((insn >> 16) & 0xf) == 0) {
6737 9ee6e8bb pbrook
                gen_nop_hint(s, insn & 0xff);
6738 9ee6e8bb pbrook
            } else {
6739 9ee6e8bb pbrook
                /* CPSR = immediate */
6740 9ee6e8bb pbrook
                val = insn & 0xff;
6741 9ee6e8bb pbrook
                shift = ((insn >> 8) & 0xf) * 2;
6742 9ee6e8bb pbrook
                if (shift)
6743 9ee6e8bb pbrook
                    val = (val >> shift) | (val << (32 - shift));
6744 9ee6e8bb pbrook
                i = ((insn & (1 << 22)) != 0);
6745 2fbac54b Filip Navara
                if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6746 9ee6e8bb pbrook
                    goto illegal_op;
6747 9ee6e8bb pbrook
            }
6748 9ee6e8bb pbrook
        }
6749 9ee6e8bb pbrook
    } else if ((insn & 0x0f900000) == 0x01000000
6750 9ee6e8bb pbrook
               && (insn & 0x00000090) != 0x00000090) {
6751 9ee6e8bb pbrook
        /* miscellaneous instructions */
6752 9ee6e8bb pbrook
        op1 = (insn >> 21) & 3;
6753 9ee6e8bb pbrook
        sh = (insn >> 4) & 0xf;
6754 9ee6e8bb pbrook
        rm = insn & 0xf;
6755 9ee6e8bb pbrook
        switch (sh) {
6756 9ee6e8bb pbrook
        case 0x0: /* move program status register */
6757 9ee6e8bb pbrook
            if (op1 & 1) {
6758 9ee6e8bb pbrook
                /* PSR = reg */
6759 2fbac54b Filip Navara
                tmp = load_reg(s, rm);
6760 9ee6e8bb pbrook
                i = ((op1 & 2) != 0);
6761 2fbac54b Filip Navara
                if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6762 9ee6e8bb pbrook
                    goto illegal_op;
6763 9ee6e8bb pbrook
            } else {
6764 9ee6e8bb pbrook
                /* reg = PSR */
6765 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
6766 9ee6e8bb pbrook
                if (op1 & 2) {
6767 9ee6e8bb pbrook
                    if (IS_USER(s))
6768 9ee6e8bb pbrook
                        goto illegal_op;
6769 d9ba4830 pbrook
                    tmp = load_cpu_field(spsr);
6770 9ee6e8bb pbrook
                } else {
6771 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
6772 d9ba4830 pbrook
                    gen_helper_cpsr_read(tmp);
6773 9ee6e8bb pbrook
                }
6774 d9ba4830 pbrook
                store_reg(s, rd, tmp);
6775 9ee6e8bb pbrook
            }
6776 9ee6e8bb pbrook
            break;
6777 9ee6e8bb pbrook
        case 0x1:
6778 9ee6e8bb pbrook
            if (op1 == 1) {
6779 9ee6e8bb pbrook
                /* branch/exchange thumb (bx).  */
6780 be5e7a76 Dmitry Eremin-Solenikov
                ARCH(4T);
6781 d9ba4830 pbrook
                tmp = load_reg(s, rm);
6782 d9ba4830 pbrook
                gen_bx(s, tmp);
6783 9ee6e8bb pbrook
            } else if (op1 == 3) {
6784 9ee6e8bb pbrook
                /* clz */
6785 be5e7a76 Dmitry Eremin-Solenikov
                ARCH(5);
6786 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
6787 1497c961 pbrook
                tmp = load_reg(s, rm);
6788 1497c961 pbrook
                gen_helper_clz(tmp, tmp);
6789 1497c961 pbrook
                store_reg(s, rd, tmp);
6790 9ee6e8bb pbrook
            } else {
6791 9ee6e8bb pbrook
                goto illegal_op;
6792 9ee6e8bb pbrook
            }
6793 9ee6e8bb pbrook
            break;
6794 9ee6e8bb pbrook
        case 0x2:
6795 9ee6e8bb pbrook
            if (op1 == 1) {
6796 9ee6e8bb pbrook
                ARCH(5J); /* bxj */
6797 9ee6e8bb pbrook
                /* Trivial implementation equivalent to bx.  */
6798 d9ba4830 pbrook
                tmp = load_reg(s, rm);
6799 d9ba4830 pbrook
                gen_bx(s, tmp);
6800 9ee6e8bb pbrook
            } else {
6801 9ee6e8bb pbrook
                goto illegal_op;
6802 9ee6e8bb pbrook
            }
6803 9ee6e8bb pbrook
            break;
6804 9ee6e8bb pbrook
        case 0x3:
6805 9ee6e8bb pbrook
            if (op1 != 1)
6806 9ee6e8bb pbrook
              goto illegal_op;
6807 9ee6e8bb pbrook
6808 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5);
6809 9ee6e8bb pbrook
            /* branch link/exchange thumb (blx) */
6810 d9ba4830 pbrook
            tmp = load_reg(s, rm);
6811 7d1b0095 Peter Maydell
            tmp2 = tcg_temp_new_i32();
6812 d9ba4830 pbrook
            tcg_gen_movi_i32(tmp2, s->pc);
6813 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
6814 d9ba4830 pbrook
            gen_bx(s, tmp);
6815 9ee6e8bb pbrook
            break;
6816 9ee6e8bb pbrook
        case 0x5: /* saturating add/subtract */
6817 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5TE);
6818 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
6819 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6820 b40d0353 balrog
            tmp = load_reg(s, rm);
6821 5e3f878a pbrook
            tmp2 = load_reg(s, rn);
6822 9ee6e8bb pbrook
            if (op1 & 2)
6823 5e3f878a pbrook
                gen_helper_double_saturate(tmp2, tmp2);
6824 9ee6e8bb pbrook
            if (op1 & 1)
6825 5e3f878a pbrook
                gen_helper_sub_saturate(tmp, tmp, tmp2);
6826 9ee6e8bb pbrook
            else
6827 5e3f878a pbrook
                gen_helper_add_saturate(tmp, tmp, tmp2);
6828 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
6829 5e3f878a pbrook
            store_reg(s, rd, tmp);
6830 9ee6e8bb pbrook
            break;
6831 49e14940 Adam Lackorzynski
        case 7:
6832 49e14940 Adam Lackorzynski
            /* SMC instruction (op1 == 3)
6833 49e14940 Adam Lackorzynski
               and undefined instructions (op1 == 0 || op1 == 2)
6834 49e14940 Adam Lackorzynski
               will trap */
6835 49e14940 Adam Lackorzynski
            if (op1 != 1) {
6836 49e14940 Adam Lackorzynski
                goto illegal_op;
6837 49e14940 Adam Lackorzynski
            }
6838 49e14940 Adam Lackorzynski
            /* bkpt */
6839 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5);
6840 bc4a0de0 Peter Maydell
            gen_exception_insn(s, 4, EXCP_BKPT);
6841 9ee6e8bb pbrook
            break;
6842 9ee6e8bb pbrook
        case 0x8: /* signed multiply */
6843 9ee6e8bb pbrook
        case 0xa:
6844 9ee6e8bb pbrook
        case 0xc:
6845 9ee6e8bb pbrook
        case 0xe:
6846 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5TE);
6847 9ee6e8bb pbrook
            rs = (insn >> 8) & 0xf;
6848 9ee6e8bb pbrook
            rn = (insn >> 12) & 0xf;
6849 9ee6e8bb pbrook
            rd = (insn >> 16) & 0xf;
6850 9ee6e8bb pbrook
            if (op1 == 1) {
6851 9ee6e8bb pbrook
                /* (32 * 16) >> 16 */
6852 5e3f878a pbrook
                tmp = load_reg(s, rm);
6853 5e3f878a pbrook
                tmp2 = load_reg(s, rs);
6854 9ee6e8bb pbrook
                if (sh & 4)
6855 5e3f878a pbrook
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
6856 9ee6e8bb pbrook
                else
6857 5e3f878a pbrook
                    gen_sxth(tmp2);
6858 a7812ae4 pbrook
                tmp64 = gen_muls_i64_i32(tmp, tmp2);
6859 a7812ae4 pbrook
                tcg_gen_shri_i64(tmp64, tmp64, 16);
6860 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
6861 a7812ae4 pbrook
                tcg_gen_trunc_i64_i32(tmp, tmp64);
6862 b75263d6 Juha Riihimäki
                tcg_temp_free_i64(tmp64);
6863 9ee6e8bb pbrook
                if ((sh & 2) == 0) {
6864 5e3f878a pbrook
                    tmp2 = load_reg(s, rn);
6865 5e3f878a pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
6866 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
6867 9ee6e8bb pbrook
                }
6868 5e3f878a pbrook
                store_reg(s, rd, tmp);
6869 9ee6e8bb pbrook
            } else {
6870 9ee6e8bb pbrook
                /* 16 * 16 */
6871 5e3f878a pbrook
                tmp = load_reg(s, rm);
6872 5e3f878a pbrook
                tmp2 = load_reg(s, rs);
6873 5e3f878a pbrook
                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6874 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
6875 9ee6e8bb pbrook
                if (op1 == 2) {
6876 a7812ae4 pbrook
                    tmp64 = tcg_temp_new_i64();
6877 a7812ae4 pbrook
                    tcg_gen_ext_i32_i64(tmp64, tmp);
6878 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
6879 a7812ae4 pbrook
                    gen_addq(s, tmp64, rn, rd);
6880 a7812ae4 pbrook
                    gen_storeq_reg(s, rn, rd, tmp64);
6881 b75263d6 Juha Riihimäki
                    tcg_temp_free_i64(tmp64);
6882 9ee6e8bb pbrook
                } else {
6883 9ee6e8bb pbrook
                    if (op1 == 0) {
6884 5e3f878a pbrook
                        tmp2 = load_reg(s, rn);
6885 5e3f878a pbrook
                        gen_helper_add_setq(tmp, tmp, tmp2);
6886 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
6887 9ee6e8bb pbrook
                    }
6888 5e3f878a pbrook
                    store_reg(s, rd, tmp);
6889 9ee6e8bb pbrook
                }
6890 9ee6e8bb pbrook
            }
6891 9ee6e8bb pbrook
            break;
6892 9ee6e8bb pbrook
        default:
6893 9ee6e8bb pbrook
            goto illegal_op;
6894 9ee6e8bb pbrook
        }
6895 9ee6e8bb pbrook
    } else if (((insn & 0x0e000000) == 0 &&
6896 9ee6e8bb pbrook
                (insn & 0x00000090) != 0x90) ||
6897 9ee6e8bb pbrook
               ((insn & 0x0e000000) == (1 << 25))) {
6898 9ee6e8bb pbrook
        int set_cc, logic_cc, shiftop;
6899 9ee6e8bb pbrook
6900 9ee6e8bb pbrook
        op1 = (insn >> 21) & 0xf;
6901 9ee6e8bb pbrook
        set_cc = (insn >> 20) & 1;
6902 9ee6e8bb pbrook
        logic_cc = table_logic_cc[op1] & set_cc;
6903 9ee6e8bb pbrook
6904 9ee6e8bb pbrook
        /* data processing instruction */
6905 9ee6e8bb pbrook
        if (insn & (1 << 25)) {
6906 9ee6e8bb pbrook
            /* immediate operand */
6907 9ee6e8bb pbrook
            val = insn & 0xff;
6908 9ee6e8bb pbrook
            shift = ((insn >> 8) & 0xf) * 2;
6909 e9bb4aa9 Juha Riihimäki
            if (shift) {
6910 9ee6e8bb pbrook
                val = (val >> shift) | (val << (32 - shift));
6911 e9bb4aa9 Juha Riihimäki
            }
6912 7d1b0095 Peter Maydell
            tmp2 = tcg_temp_new_i32();
6913 e9bb4aa9 Juha Riihimäki
            tcg_gen_movi_i32(tmp2, val);
6914 e9bb4aa9 Juha Riihimäki
            if (logic_cc && shift) {
6915 e9bb4aa9 Juha Riihimäki
                gen_set_CF_bit31(tmp2);
6916 e9bb4aa9 Juha Riihimäki
            }
6917 9ee6e8bb pbrook
        } else {
6918 9ee6e8bb pbrook
            /* register */
6919 9ee6e8bb pbrook
            rm = (insn) & 0xf;
6920 e9bb4aa9 Juha Riihimäki
            tmp2 = load_reg(s, rm);
6921 9ee6e8bb pbrook
            shiftop = (insn >> 5) & 3;
6922 9ee6e8bb pbrook
            if (!(insn & (1 << 4))) {
6923 9ee6e8bb pbrook
                shift = (insn >> 7) & 0x1f;
6924 e9bb4aa9 Juha Riihimäki
                gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6925 9ee6e8bb pbrook
            } else {
6926 9ee6e8bb pbrook
                rs = (insn >> 8) & 0xf;
6927 8984bd2e pbrook
                tmp = load_reg(s, rs);
6928 e9bb4aa9 Juha Riihimäki
                gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6929 9ee6e8bb pbrook
            }
6930 9ee6e8bb pbrook
        }
6931 9ee6e8bb pbrook
        if (op1 != 0x0f && op1 != 0x0d) {
6932 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6933 e9bb4aa9 Juha Riihimäki
            tmp = load_reg(s, rn);
6934 e9bb4aa9 Juha Riihimäki
        } else {
6935 e9bb4aa9 Juha Riihimäki
            TCGV_UNUSED(tmp);
6936 9ee6e8bb pbrook
        }
6937 9ee6e8bb pbrook
        rd = (insn >> 12) & 0xf;
6938 9ee6e8bb pbrook
        switch(op1) {
6939 9ee6e8bb pbrook
        case 0x00:
6940 e9bb4aa9 Juha Riihimäki
            tcg_gen_and_i32(tmp, tmp, tmp2);
6941 e9bb4aa9 Juha Riihimäki
            if (logic_cc) {
6942 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
6943 e9bb4aa9 Juha Riihimäki
            }
6944 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
6945 9ee6e8bb pbrook
            break;
6946 9ee6e8bb pbrook
        case 0x01:
6947 e9bb4aa9 Juha Riihimäki
            tcg_gen_xor_i32(tmp, tmp, tmp2);
6948 e9bb4aa9 Juha Riihimäki
            if (logic_cc) {
6949 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
6950 e9bb4aa9 Juha Riihimäki
            }
6951 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
6952 9ee6e8bb pbrook
            break;
6953 9ee6e8bb pbrook
        case 0x02:
6954 9ee6e8bb pbrook
            if (set_cc && rd == 15) {
6955 9ee6e8bb pbrook
                /* SUBS r15, ... is used for exception return.  */
6956 e9bb4aa9 Juha Riihimäki
                if (IS_USER(s)) {
6957 9ee6e8bb pbrook
                    goto illegal_op;
6958 e9bb4aa9 Juha Riihimäki
                }
6959 e9bb4aa9 Juha Riihimäki
                gen_helper_sub_cc(tmp, tmp, tmp2);
6960 e9bb4aa9 Juha Riihimäki
                gen_exception_return(s, tmp);
6961 9ee6e8bb pbrook
            } else {
6962 e9bb4aa9 Juha Riihimäki
                if (set_cc) {
6963 e9bb4aa9 Juha Riihimäki
                    gen_helper_sub_cc(tmp, tmp, tmp2);
6964 e9bb4aa9 Juha Riihimäki
                } else {
6965 e9bb4aa9 Juha Riihimäki
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
6966 e9bb4aa9 Juha Riihimäki
                }
6967 21aeb343 Juha Riihimäki
                store_reg_bx(env, s, rd, tmp);
6968 9ee6e8bb pbrook
            }
6969 9ee6e8bb pbrook
            break;
6970 9ee6e8bb pbrook
        case 0x03:
6971 e9bb4aa9 Juha Riihimäki
            if (set_cc) {
6972 e9bb4aa9 Juha Riihimäki
                gen_helper_sub_cc(tmp, tmp2, tmp);
6973 e9bb4aa9 Juha Riihimäki
            } else {
6974 e9bb4aa9 Juha Riihimäki
                tcg_gen_sub_i32(tmp, tmp2, tmp);
6975 e9bb4aa9 Juha Riihimäki
            }
6976 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
6977 9ee6e8bb pbrook
            break;
6978 9ee6e8bb pbrook
        case 0x04:
6979 e9bb4aa9 Juha Riihimäki
            if (set_cc) {
6980 e9bb4aa9 Juha Riihimäki
                gen_helper_add_cc(tmp, tmp, tmp2);
6981 e9bb4aa9 Juha Riihimäki
            } else {
6982 e9bb4aa9 Juha Riihimäki
                tcg_gen_add_i32(tmp, tmp, tmp2);
6983 e9bb4aa9 Juha Riihimäki
            }
6984 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
6985 9ee6e8bb pbrook
            break;
6986 9ee6e8bb pbrook
        case 0x05:
6987 e9bb4aa9 Juha Riihimäki
            if (set_cc) {
6988 e9bb4aa9 Juha Riihimäki
                gen_helper_adc_cc(tmp, tmp, tmp2);
6989 e9bb4aa9 Juha Riihimäki
            } else {
6990 e9bb4aa9 Juha Riihimäki
                gen_add_carry(tmp, tmp, tmp2);
6991 e9bb4aa9 Juha Riihimäki
            }
6992 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
6993 9ee6e8bb pbrook
            break;
6994 9ee6e8bb pbrook
        case 0x06:
6995 e9bb4aa9 Juha Riihimäki
            if (set_cc) {
6996 e9bb4aa9 Juha Riihimäki
                gen_helper_sbc_cc(tmp, tmp, tmp2);
6997 e9bb4aa9 Juha Riihimäki
            } else {
6998 e9bb4aa9 Juha Riihimäki
                gen_sub_carry(tmp, tmp, tmp2);
6999 e9bb4aa9 Juha Riihimäki
            }
7000 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
7001 9ee6e8bb pbrook
            break;
7002 9ee6e8bb pbrook
        case 0x07:
7003 e9bb4aa9 Juha Riihimäki
            if (set_cc) {
7004 e9bb4aa9 Juha Riihimäki
                gen_helper_sbc_cc(tmp, tmp2, tmp);
7005 e9bb4aa9 Juha Riihimäki
            } else {
7006 e9bb4aa9 Juha Riihimäki
                gen_sub_carry(tmp, tmp2, tmp);
7007 e9bb4aa9 Juha Riihimäki
            }
7008 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
7009 9ee6e8bb pbrook
            break;
7010 9ee6e8bb pbrook
        case 0x08:
7011 9ee6e8bb pbrook
            if (set_cc) {
7012 e9bb4aa9 Juha Riihimäki
                tcg_gen_and_i32(tmp, tmp, tmp2);
7013 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
7014 9ee6e8bb pbrook
            }
7015 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
7016 9ee6e8bb pbrook
            break;
7017 9ee6e8bb pbrook
        case 0x09:
7018 9ee6e8bb pbrook
            if (set_cc) {
7019 e9bb4aa9 Juha Riihimäki
                tcg_gen_xor_i32(tmp, tmp, tmp2);
7020 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
7021 9ee6e8bb pbrook
            }
7022 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
7023 9ee6e8bb pbrook
            break;
7024 9ee6e8bb pbrook
        case 0x0a:
7025 9ee6e8bb pbrook
            if (set_cc) {
7026 e9bb4aa9 Juha Riihimäki
                gen_helper_sub_cc(tmp, tmp, tmp2);
7027 9ee6e8bb pbrook
            }
7028 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
7029 9ee6e8bb pbrook
            break;
7030 9ee6e8bb pbrook
        case 0x0b:
7031 9ee6e8bb pbrook
            if (set_cc) {
7032 e9bb4aa9 Juha Riihimäki
                gen_helper_add_cc(tmp, tmp, tmp2);
7033 9ee6e8bb pbrook
            }
7034 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
7035 9ee6e8bb pbrook
            break;
7036 9ee6e8bb pbrook
        case 0x0c:
7037 e9bb4aa9 Juha Riihimäki
            tcg_gen_or_i32(tmp, tmp, tmp2);
7038 e9bb4aa9 Juha Riihimäki
            if (logic_cc) {
7039 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
7040 e9bb4aa9 Juha Riihimäki
            }
7041 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
7042 9ee6e8bb pbrook
            break;
7043 9ee6e8bb pbrook
        case 0x0d:
7044 9ee6e8bb pbrook
            if (logic_cc && rd == 15) {
7045 9ee6e8bb pbrook
                /* MOVS r15, ... is used for exception return.  */
7046 e9bb4aa9 Juha Riihimäki
                if (IS_USER(s)) {
7047 9ee6e8bb pbrook
                    goto illegal_op;
7048 e9bb4aa9 Juha Riihimäki
                }
7049 e9bb4aa9 Juha Riihimäki
                gen_exception_return(s, tmp2);
7050 9ee6e8bb pbrook
            } else {
7051 e9bb4aa9 Juha Riihimäki
                if (logic_cc) {
7052 e9bb4aa9 Juha Riihimäki
                    gen_logic_CC(tmp2);
7053 e9bb4aa9 Juha Riihimäki
                }
7054 21aeb343 Juha Riihimäki
                store_reg_bx(env, s, rd, tmp2);
7055 9ee6e8bb pbrook
            }
7056 9ee6e8bb pbrook
            break;
7057 9ee6e8bb pbrook
        case 0x0e:
7058 f669df27 Aurelien Jarno
            tcg_gen_andc_i32(tmp, tmp, tmp2);
7059 e9bb4aa9 Juha Riihimäki
            if (logic_cc) {
7060 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp);
7061 e9bb4aa9 Juha Riihimäki
            }
7062 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
7063 9ee6e8bb pbrook
            break;
7064 9ee6e8bb pbrook
        default:
7065 9ee6e8bb pbrook
        case 0x0f:
7066 e9bb4aa9 Juha Riihimäki
            tcg_gen_not_i32(tmp2, tmp2);
7067 e9bb4aa9 Juha Riihimäki
            if (logic_cc) {
7068 e9bb4aa9 Juha Riihimäki
                gen_logic_CC(tmp2);
7069 e9bb4aa9 Juha Riihimäki
            }
7070 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp2);
7071 9ee6e8bb pbrook
            break;
7072 9ee6e8bb pbrook
        }
7073 e9bb4aa9 Juha Riihimäki
        if (op1 != 0x0f && op1 != 0x0d) {
7074 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
7075 e9bb4aa9 Juha Riihimäki
        }
7076 9ee6e8bb pbrook
    } else {
7077 9ee6e8bb pbrook
        /* other instructions */
7078 9ee6e8bb pbrook
        op1 = (insn >> 24) & 0xf;
7079 9ee6e8bb pbrook
        switch(op1) {
7080 9ee6e8bb pbrook
        case 0x0:
7081 9ee6e8bb pbrook
        case 0x1:
7082 9ee6e8bb pbrook
            /* multiplies, extra load/stores */
7083 9ee6e8bb pbrook
            sh = (insn >> 5) & 3;
7084 9ee6e8bb pbrook
            if (sh == 0) {
7085 9ee6e8bb pbrook
                if (op1 == 0x0) {
7086 9ee6e8bb pbrook
                    rd = (insn >> 16) & 0xf;
7087 9ee6e8bb pbrook
                    rn = (insn >> 12) & 0xf;
7088 9ee6e8bb pbrook
                    rs = (insn >> 8) & 0xf;
7089 9ee6e8bb pbrook
                    rm = (insn) & 0xf;
7090 9ee6e8bb pbrook
                    op1 = (insn >> 20) & 0xf;
7091 9ee6e8bb pbrook
                    switch (op1) {
7092 9ee6e8bb pbrook
                    case 0: case 1: case 2: case 3: case 6:
7093 9ee6e8bb pbrook
                        /* 32 bit mul */
7094 5e3f878a pbrook
                        tmp = load_reg(s, rs);
7095 5e3f878a pbrook
                        tmp2 = load_reg(s, rm);
7096 5e3f878a pbrook
                        tcg_gen_mul_i32(tmp, tmp, tmp2);
7097 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
7098 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
7099 9ee6e8bb pbrook
                            /* Subtract (mls) */
7100 9ee6e8bb pbrook
                            ARCH(6T2);
7101 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
7102 5e3f878a pbrook
                            tcg_gen_sub_i32(tmp, tmp2, tmp);
7103 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
7104 9ee6e8bb pbrook
                        } else if (insn & (1 << 21)) {
7105 9ee6e8bb pbrook
                            /* Add */
7106 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
7107 5e3f878a pbrook
                            tcg_gen_add_i32(tmp, tmp, tmp2);
7108 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
7109 9ee6e8bb pbrook
                        }
7110 9ee6e8bb pbrook
                        if (insn & (1 << 20))
7111 5e3f878a pbrook
                            gen_logic_CC(tmp);
7112 5e3f878a pbrook
                        store_reg(s, rd, tmp);
7113 9ee6e8bb pbrook
                        break;
7114 8aac08b1 Aurelien Jarno
                    case 4:
7115 8aac08b1 Aurelien Jarno
                        /* 64 bit mul double accumulate (UMAAL) */
7116 8aac08b1 Aurelien Jarno
                        ARCH(6);
7117 8aac08b1 Aurelien Jarno
                        tmp = load_reg(s, rs);
7118 8aac08b1 Aurelien Jarno
                        tmp2 = load_reg(s, rm);
7119 8aac08b1 Aurelien Jarno
                        tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7120 8aac08b1 Aurelien Jarno
                        gen_addq_lo(s, tmp64, rn);
7121 8aac08b1 Aurelien Jarno
                        gen_addq_lo(s, tmp64, rd);
7122 8aac08b1 Aurelien Jarno
                        gen_storeq_reg(s, rn, rd, tmp64);
7123 8aac08b1 Aurelien Jarno
                        tcg_temp_free_i64(tmp64);
7124 8aac08b1 Aurelien Jarno
                        break;
7125 8aac08b1 Aurelien Jarno
                    case 8: case 9: case 10: case 11:
7126 8aac08b1 Aurelien Jarno
                    case 12: case 13: case 14: case 15:
7127 8aac08b1 Aurelien Jarno
                        /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7128 5e3f878a pbrook
                        tmp = load_reg(s, rs);
7129 5e3f878a pbrook
                        tmp2 = load_reg(s, rm);
7130 8aac08b1 Aurelien Jarno
                        if (insn & (1 << 22)) {
7131 a7812ae4 pbrook
                            tmp64 = gen_muls_i64_i32(tmp, tmp2);
7132 8aac08b1 Aurelien Jarno
                        } else {
7133 a7812ae4 pbrook
                            tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7134 8aac08b1 Aurelien Jarno
                        }
7135 8aac08b1 Aurelien Jarno
                        if (insn & (1 << 21)) { /* mult accumulate */
7136 a7812ae4 pbrook
                            gen_addq(s, tmp64, rn, rd);
7137 9ee6e8bb pbrook
                        }
7138 8aac08b1 Aurelien Jarno
                        if (insn & (1 << 20)) {
7139 a7812ae4 pbrook
                            gen_logicq_cc(tmp64);
7140 8aac08b1 Aurelien Jarno
                        }
7141 a7812ae4 pbrook
                        gen_storeq_reg(s, rn, rd, tmp64);
7142 b75263d6 Juha Riihimäki
                        tcg_temp_free_i64(tmp64);
7143 9ee6e8bb pbrook
                        break;
7144 8aac08b1 Aurelien Jarno
                    default:
7145 8aac08b1 Aurelien Jarno
                        goto illegal_op;
7146 9ee6e8bb pbrook
                    }
7147 9ee6e8bb pbrook
                } else {
7148 9ee6e8bb pbrook
                    rn = (insn >> 16) & 0xf;
7149 9ee6e8bb pbrook
                    rd = (insn >> 12) & 0xf;
7150 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
7151 9ee6e8bb pbrook
                        /* load/store exclusive */
7152 86753403 pbrook
                        op1 = (insn >> 21) & 0x3;
7153 86753403 pbrook
                        if (op1)
7154 a47f43d2 pbrook
                            ARCH(6K);
7155 86753403 pbrook
                        else
7156 86753403 pbrook
                            ARCH(6);
7157 3174f8e9 Filip Navara
                        addr = tcg_temp_local_new_i32();
7158 98a46317 Aurelien Jarno
                        load_reg_var(s, addr, rn);
7159 9ee6e8bb pbrook
                        if (insn & (1 << 20)) {
7160 86753403 pbrook
                            switch (op1) {
7161 86753403 pbrook
                            case 0: /* ldrex */
7162 426f5abc Paul Brook
                                gen_load_exclusive(s, rd, 15, addr, 2);
7163 86753403 pbrook
                                break;
7164 86753403 pbrook
                            case 1: /* ldrexd */
7165 426f5abc Paul Brook
                                gen_load_exclusive(s, rd, rd + 1, addr, 3);
7166 86753403 pbrook
                                break;
7167 86753403 pbrook
                            case 2: /* ldrexb */
7168 426f5abc Paul Brook
                                gen_load_exclusive(s, rd, 15, addr, 0);
7169 86753403 pbrook
                                break;
7170 86753403 pbrook
                            case 3: /* ldrexh */
7171 426f5abc Paul Brook
                                gen_load_exclusive(s, rd, 15, addr, 1);
7172 86753403 pbrook
                                break;
7173 86753403 pbrook
                            default:
7174 86753403 pbrook
                                abort();
7175 86753403 pbrook
                            }
7176 9ee6e8bb pbrook
                        } else {
7177 9ee6e8bb pbrook
                            rm = insn & 0xf;
7178 86753403 pbrook
                            switch (op1) {
7179 86753403 pbrook
                            case 0:  /*  strex */
7180 426f5abc Paul Brook
                                gen_store_exclusive(s, rd, rm, 15, addr, 2);
7181 86753403 pbrook
                                break;
7182 86753403 pbrook
                            case 1: /*  strexd */
7183 502e64fe Aurelien Jarno
                                gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7184 86753403 pbrook
                                break;
7185 86753403 pbrook
                            case 2: /*  strexb */
7186 426f5abc Paul Brook
                                gen_store_exclusive(s, rd, rm, 15, addr, 0);
7187 86753403 pbrook
                                break;
7188 86753403 pbrook
                            case 3: /* strexh */
7189 426f5abc Paul Brook
                                gen_store_exclusive(s, rd, rm, 15, addr, 1);
7190 86753403 pbrook
                                break;
7191 86753403 pbrook
                            default:
7192 86753403 pbrook
                                abort();
7193 86753403 pbrook
                            }
7194 9ee6e8bb pbrook
                        }
7195 3174f8e9 Filip Navara
                        tcg_temp_free(addr);
7196 9ee6e8bb pbrook
                    } else {
7197 9ee6e8bb pbrook
                        /* SWP instruction */
7198 9ee6e8bb pbrook
                        rm = (insn) & 0xf;
7199 9ee6e8bb pbrook
7200 8984bd2e pbrook
                        /* ??? This is not really atomic.  However we know
7201 8984bd2e pbrook
                           we never have multiple CPUs running in parallel,
7202 8984bd2e pbrook
                           so it is good enough.  */
7203 8984bd2e pbrook
                        addr = load_reg(s, rn);
7204 8984bd2e pbrook
                        tmp = load_reg(s, rm);
7205 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
7206 8984bd2e pbrook
                            tmp2 = gen_ld8u(addr, IS_USER(s));
7207 8984bd2e pbrook
                            gen_st8(tmp, addr, IS_USER(s));
7208 9ee6e8bb pbrook
                        } else {
7209 8984bd2e pbrook
                            tmp2 = gen_ld32(addr, IS_USER(s));
7210 8984bd2e pbrook
                            gen_st32(tmp, addr, IS_USER(s));
7211 9ee6e8bb pbrook
                        }
7212 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(addr);
7213 8984bd2e pbrook
                        store_reg(s, rd, tmp2);
7214 9ee6e8bb pbrook
                    }
7215 9ee6e8bb pbrook
                }
7216 9ee6e8bb pbrook
            } else {
7217 9ee6e8bb pbrook
                int address_offset;
7218 9ee6e8bb pbrook
                int load;
7219 9ee6e8bb pbrook
                /* Misc load/store */
7220 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
7221 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
7222 b0109805 pbrook
                addr = load_reg(s, rn);
7223 9ee6e8bb pbrook
                if (insn & (1 << 24))
7224 b0109805 pbrook
                    gen_add_datah_offset(s, insn, 0, addr);
7225 9ee6e8bb pbrook
                address_offset = 0;
7226 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7227 9ee6e8bb pbrook
                    /* load */
7228 9ee6e8bb pbrook
                    switch(sh) {
7229 9ee6e8bb pbrook
                    case 1:
7230 b0109805 pbrook
                        tmp = gen_ld16u(addr, IS_USER(s));
7231 9ee6e8bb pbrook
                        break;
7232 9ee6e8bb pbrook
                    case 2:
7233 b0109805 pbrook
                        tmp = gen_ld8s(addr, IS_USER(s));
7234 9ee6e8bb pbrook
                        break;
7235 9ee6e8bb pbrook
                    default:
7236 9ee6e8bb pbrook
                    case 3:
7237 b0109805 pbrook
                        tmp = gen_ld16s(addr, IS_USER(s));
7238 9ee6e8bb pbrook
                        break;
7239 9ee6e8bb pbrook
                    }
7240 9ee6e8bb pbrook
                    load = 1;
7241 9ee6e8bb pbrook
                } else if (sh & 2) {
7242 be5e7a76 Dmitry Eremin-Solenikov
                    ARCH(5TE);
7243 9ee6e8bb pbrook
                    /* doubleword */
7244 9ee6e8bb pbrook
                    if (sh & 1) {
7245 9ee6e8bb pbrook
                        /* store */
7246 b0109805 pbrook
                        tmp = load_reg(s, rd);
7247 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
7248 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
7249 b0109805 pbrook
                        tmp = load_reg(s, rd + 1);
7250 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
7251 9ee6e8bb pbrook
                        load = 0;
7252 9ee6e8bb pbrook
                    } else {
7253 9ee6e8bb pbrook
                        /* load */
7254 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
7255 b0109805 pbrook
                        store_reg(s, rd, tmp);
7256 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
7257 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
7258 9ee6e8bb pbrook
                        rd++;
7259 9ee6e8bb pbrook
                        load = 1;
7260 9ee6e8bb pbrook
                    }
7261 9ee6e8bb pbrook
                    address_offset = -4;
7262 9ee6e8bb pbrook
                } else {
7263 9ee6e8bb pbrook
                    /* store */
7264 b0109805 pbrook
                    tmp = load_reg(s, rd);
7265 b0109805 pbrook
                    gen_st16(tmp, addr, IS_USER(s));
7266 9ee6e8bb pbrook
                    load = 0;
7267 9ee6e8bb pbrook
                }
7268 9ee6e8bb pbrook
                /* Perform base writeback before the loaded value to
7269 9ee6e8bb pbrook
                   ensure correct behavior with overlapping index registers.
7270 9ee6e8bb pbrook
                   ldrd with base writeback is is undefined if the
7271 9ee6e8bb pbrook
                   destination and index registers overlap.  */
7272 9ee6e8bb pbrook
                if (!(insn & (1 << 24))) {
7273 b0109805 pbrook
                    gen_add_datah_offset(s, insn, address_offset, addr);
7274 b0109805 pbrook
                    store_reg(s, rn, addr);
7275 9ee6e8bb pbrook
                } else if (insn & (1 << 21)) {
7276 9ee6e8bb pbrook
                    if (address_offset)
7277 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, address_offset);
7278 b0109805 pbrook
                    store_reg(s, rn, addr);
7279 b0109805 pbrook
                } else {
7280 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
7281 9ee6e8bb pbrook
                }
7282 9ee6e8bb pbrook
                if (load) {
7283 9ee6e8bb pbrook
                    /* Complete the load.  */
7284 b0109805 pbrook
                    store_reg(s, rd, tmp);
7285 9ee6e8bb pbrook
                }
7286 9ee6e8bb pbrook
            }
7287 9ee6e8bb pbrook
            break;
7288 9ee6e8bb pbrook
        case 0x4:
7289 9ee6e8bb pbrook
        case 0x5:
7290 9ee6e8bb pbrook
            goto do_ldst;
7291 9ee6e8bb pbrook
        case 0x6:
7292 9ee6e8bb pbrook
        case 0x7:
7293 9ee6e8bb pbrook
            if (insn & (1 << 4)) {
7294 9ee6e8bb pbrook
                ARCH(6);
7295 9ee6e8bb pbrook
                /* Armv6 Media instructions.  */
7296 9ee6e8bb pbrook
                rm = insn & 0xf;
7297 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
7298 2c0262af bellard
                rd = (insn >> 12) & 0xf;
7299 9ee6e8bb pbrook
                rs = (insn >> 8) & 0xf;
7300 9ee6e8bb pbrook
                switch ((insn >> 23) & 3) {
7301 9ee6e8bb pbrook
                case 0: /* Parallel add/subtract.  */
7302 9ee6e8bb pbrook
                    op1 = (insn >> 20) & 7;
7303 6ddbc6e4 pbrook
                    tmp = load_reg(s, rn);
7304 6ddbc6e4 pbrook
                    tmp2 = load_reg(s, rm);
7305 9ee6e8bb pbrook
                    sh = (insn >> 5) & 7;
7306 9ee6e8bb pbrook
                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7307 9ee6e8bb pbrook
                        goto illegal_op;
7308 6ddbc6e4 pbrook
                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7309 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
7310 6ddbc6e4 pbrook
                    store_reg(s, rd, tmp);
7311 9ee6e8bb pbrook
                    break;
7312 9ee6e8bb pbrook
                case 1:
7313 9ee6e8bb pbrook
                    if ((insn & 0x00700020) == 0) {
7314 6c95676b balrog
                        /* Halfword pack.  */
7315 3670669c pbrook
                        tmp = load_reg(s, rn);
7316 3670669c pbrook
                        tmp2 = load_reg(s, rm);
7317 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
7318 3670669c pbrook
                        if (insn & (1 << 6)) {
7319 3670669c pbrook
                            /* pkhtb */
7320 22478e79 balrog
                            if (shift == 0)
7321 22478e79 balrog
                                shift = 31;
7322 22478e79 balrog
                            tcg_gen_sari_i32(tmp2, tmp2, shift);
7323 3670669c pbrook
                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7324 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp2, tmp2);
7325 3670669c pbrook
                        } else {
7326 3670669c pbrook
                            /* pkhbt */
7327 22478e79 balrog
                            if (shift)
7328 22478e79 balrog
                                tcg_gen_shli_i32(tmp2, tmp2, shift);
7329 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp, tmp);
7330 3670669c pbrook
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7331 3670669c pbrook
                        }
7332 3670669c pbrook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
7333 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
7334 3670669c pbrook
                        store_reg(s, rd, tmp);
7335 9ee6e8bb pbrook
                    } else if ((insn & 0x00200020) == 0x00200000) {
7336 9ee6e8bb pbrook
                        /* [us]sat */
7337 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
7338 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
7339 9ee6e8bb pbrook
                        if (insn & (1 << 6)) {
7340 9ee6e8bb pbrook
                            if (shift == 0)
7341 9ee6e8bb pbrook
                                shift = 31;
7342 6ddbc6e4 pbrook
                            tcg_gen_sari_i32(tmp, tmp, shift);
7343 9ee6e8bb pbrook
                        } else {
7344 6ddbc6e4 pbrook
                            tcg_gen_shli_i32(tmp, tmp, shift);
7345 9ee6e8bb pbrook
                        }
7346 9ee6e8bb pbrook
                        sh = (insn >> 16) & 0x1f;
7347 40d3c433 Christophe Lyon
                        tmp2 = tcg_const_i32(sh);
7348 40d3c433 Christophe Lyon
                        if (insn & (1 << 22))
7349 40d3c433 Christophe Lyon
                          gen_helper_usat(tmp, tmp, tmp2);
7350 40d3c433 Christophe Lyon
                        else
7351 40d3c433 Christophe Lyon
                          gen_helper_ssat(tmp, tmp, tmp2);
7352 40d3c433 Christophe Lyon
                        tcg_temp_free_i32(tmp2);
7353 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
7354 9ee6e8bb pbrook
                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
7355 9ee6e8bb pbrook
                        /* [us]sat16 */
7356 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
7357 9ee6e8bb pbrook
                        sh = (insn >> 16) & 0x1f;
7358 40d3c433 Christophe Lyon
                        tmp2 = tcg_const_i32(sh);
7359 40d3c433 Christophe Lyon
                        if (insn & (1 << 22))
7360 40d3c433 Christophe Lyon
                          gen_helper_usat16(tmp, tmp, tmp2);
7361 40d3c433 Christophe Lyon
                        else
7362 40d3c433 Christophe Lyon
                          gen_helper_ssat16(tmp, tmp, tmp2);
7363 40d3c433 Christophe Lyon
                        tcg_temp_free_i32(tmp2);
7364 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
7365 9ee6e8bb pbrook
                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7366 9ee6e8bb pbrook
                        /* Select bytes.  */
7367 6ddbc6e4 pbrook
                        tmp = load_reg(s, rn);
7368 6ddbc6e4 pbrook
                        tmp2 = load_reg(s, rm);
7369 7d1b0095 Peter Maydell
                        tmp3 = tcg_temp_new_i32();
7370 6ddbc6e4 pbrook
                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7371 6ddbc6e4 pbrook
                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7372 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp3);
7373 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
7374 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
7375 9ee6e8bb pbrook
                    } else if ((insn & 0x000003e0) == 0x00000060) {
7376 5e3f878a pbrook
                        tmp = load_reg(s, rm);
7377 9ee6e8bb pbrook
                        shift = (insn >> 10) & 3;
7378 1301f322 Stefan Weil
                        /* ??? In many cases it's not necessary to do a
7379 9ee6e8bb pbrook
                           rotate, a shift is sufficient.  */
7380 9ee6e8bb pbrook
                        if (shift != 0)
7381 f669df27 Aurelien Jarno
                            tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7382 9ee6e8bb pbrook
                        op1 = (insn >> 20) & 7;
7383 9ee6e8bb pbrook
                        switch (op1) {
7384 5e3f878a pbrook
                        case 0: gen_sxtb16(tmp);  break;
7385 5e3f878a pbrook
                        case 2: gen_sxtb(tmp);    break;
7386 5e3f878a pbrook
                        case 3: gen_sxth(tmp);    break;
7387 5e3f878a pbrook
                        case 4: gen_uxtb16(tmp);  break;
7388 5e3f878a pbrook
                        case 6: gen_uxtb(tmp);    break;
7389 5e3f878a pbrook
                        case 7: gen_uxth(tmp);    break;
7390 9ee6e8bb pbrook
                        default: goto illegal_op;
7391 9ee6e8bb pbrook
                        }
7392 9ee6e8bb pbrook
                        if (rn != 15) {
7393 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
7394 9ee6e8bb pbrook
                            if ((op1 & 3) == 0) {
7395 5e3f878a pbrook
                                gen_add16(tmp, tmp2);
7396 9ee6e8bb pbrook
                            } else {
7397 5e3f878a pbrook
                                tcg_gen_add_i32(tmp, tmp, tmp2);
7398 7d1b0095 Peter Maydell
                                tcg_temp_free_i32(tmp2);
7399 9ee6e8bb pbrook
                            }
7400 9ee6e8bb pbrook
                        }
7401 6c95676b balrog
                        store_reg(s, rd, tmp);
7402 9ee6e8bb pbrook
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7403 9ee6e8bb pbrook
                        /* rev */
7404 b0109805 pbrook
                        tmp = load_reg(s, rm);
7405 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
7406 9ee6e8bb pbrook
                            if (insn & (1 << 7)) {
7407 b0109805 pbrook
                                gen_revsh(tmp);
7408 9ee6e8bb pbrook
                            } else {
7409 9ee6e8bb pbrook
                                ARCH(6T2);
7410 b0109805 pbrook
                                gen_helper_rbit(tmp, tmp);
7411 9ee6e8bb pbrook
                            }
7412 9ee6e8bb pbrook
                        } else {
7413 9ee6e8bb pbrook
                            if (insn & (1 << 7))
7414 b0109805 pbrook
                                gen_rev16(tmp);
7415 9ee6e8bb pbrook
                            else
7416 66896cb8 aurel32
                                tcg_gen_bswap32_i32(tmp, tmp);
7417 9ee6e8bb pbrook
                        }
7418 b0109805 pbrook
                        store_reg(s, rd, tmp);
7419 9ee6e8bb pbrook
                    } else {
7420 9ee6e8bb pbrook
                        goto illegal_op;
7421 9ee6e8bb pbrook
                    }
7422 9ee6e8bb pbrook
                    break;
7423 9ee6e8bb pbrook
                case 2: /* Multiplies (Type 3).  */
7424 5e3f878a pbrook
                    tmp = load_reg(s, rm);
7425 5e3f878a pbrook
                    tmp2 = load_reg(s, rs);
7426 9ee6e8bb pbrook
                    if (insn & (1 << 20)) {
7427 838fa72d Aurelien Jarno
                        /* Signed multiply most significant [accumulate].
7428 838fa72d Aurelien Jarno
                           (SMMUL, SMMLA, SMMLS) */
7429 a7812ae4 pbrook
                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
7430 838fa72d Aurelien Jarno
7431 955a7dd5 balrog
                        if (rd != 15) {
7432 838fa72d Aurelien Jarno
                            tmp = load_reg(s, rd);
7433 9ee6e8bb pbrook
                            if (insn & (1 << 6)) {
7434 838fa72d Aurelien Jarno
                                tmp64 = gen_subq_msw(tmp64, tmp);
7435 9ee6e8bb pbrook
                            } else {
7436 838fa72d Aurelien Jarno
                                tmp64 = gen_addq_msw(tmp64, tmp);
7437 9ee6e8bb pbrook
                            }
7438 9ee6e8bb pbrook
                        }
7439 838fa72d Aurelien Jarno
                        if (insn & (1 << 5)) {
7440 838fa72d Aurelien Jarno
                            tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7441 838fa72d Aurelien Jarno
                        }
7442 838fa72d Aurelien Jarno
                        tcg_gen_shri_i64(tmp64, tmp64, 32);
7443 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
7444 838fa72d Aurelien Jarno
                        tcg_gen_trunc_i64_i32(tmp, tmp64);
7445 838fa72d Aurelien Jarno
                        tcg_temp_free_i64(tmp64);
7446 955a7dd5 balrog
                        store_reg(s, rn, tmp);
7447 9ee6e8bb pbrook
                    } else {
7448 9ee6e8bb pbrook
                        if (insn & (1 << 5))
7449 5e3f878a pbrook
                            gen_swap_half(tmp2);
7450 5e3f878a pbrook
                        gen_smul_dual(tmp, tmp2);
7451 5e3f878a pbrook
                        if (insn & (1 << 6)) {
7452 e1d177b9 Peter Maydell
                            /* This subtraction cannot overflow. */
7453 5e3f878a pbrook
                            tcg_gen_sub_i32(tmp, tmp, tmp2);
7454 5e3f878a pbrook
                        } else {
7455 e1d177b9 Peter Maydell
                            /* This addition cannot overflow 32 bits;
7456 e1d177b9 Peter Maydell
                             * however it may overflow considered as a signed
7457 e1d177b9 Peter Maydell
                             * operation, in which case we must set the Q flag.
7458 e1d177b9 Peter Maydell
                             */
7459 e1d177b9 Peter Maydell
                            gen_helper_add_setq(tmp, tmp, tmp2);
7460 5e3f878a pbrook
                        }
7461 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
7462 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
7463 5e3f878a pbrook
                            /* smlald, smlsld */
7464 a7812ae4 pbrook
                            tmp64 = tcg_temp_new_i64();
7465 a7812ae4 pbrook
                            tcg_gen_ext_i32_i64(tmp64, tmp);
7466 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp);
7467 a7812ae4 pbrook
                            gen_addq(s, tmp64, rd, rn);
7468 a7812ae4 pbrook
                            gen_storeq_reg(s, rd, rn, tmp64);
7469 b75263d6 Juha Riihimäki
                            tcg_temp_free_i64(tmp64);
7470 9ee6e8bb pbrook
                        } else {
7471 5e3f878a pbrook
                            /* smuad, smusd, smlad, smlsd */
7472 22478e79 balrog
                            if (rd != 15)
7473 9ee6e8bb pbrook
                              {
7474 22478e79 balrog
                                tmp2 = load_reg(s, rd);
7475 5e3f878a pbrook
                                gen_helper_add_setq(tmp, tmp, tmp2);
7476 7d1b0095 Peter Maydell
                                tcg_temp_free_i32(tmp2);
7477 9ee6e8bb pbrook
                              }
7478 22478e79 balrog
                            store_reg(s, rn, tmp);
7479 9ee6e8bb pbrook
                        }
7480 9ee6e8bb pbrook
                    }
7481 9ee6e8bb pbrook
                    break;
7482 9ee6e8bb pbrook
                case 3:
7483 9ee6e8bb pbrook
                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7484 9ee6e8bb pbrook
                    switch (op1) {
7485 9ee6e8bb pbrook
                    case 0: /* Unsigned sum of absolute differences.  */
7486 6ddbc6e4 pbrook
                        ARCH(6);
7487 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
7488 6ddbc6e4 pbrook
                        tmp2 = load_reg(s, rs);
7489 6ddbc6e4 pbrook
                        gen_helper_usad8(tmp, tmp, tmp2);
7490 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
7491 ded9d295 balrog
                        if (rd != 15) {
7492 ded9d295 balrog
                            tmp2 = load_reg(s, rd);
7493 6ddbc6e4 pbrook
                            tcg_gen_add_i32(tmp, tmp, tmp2);
7494 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
7495 9ee6e8bb pbrook
                        }
7496 ded9d295 balrog
                        store_reg(s, rn, tmp);
7497 9ee6e8bb pbrook
                        break;
7498 9ee6e8bb pbrook
                    case 0x20: case 0x24: case 0x28: case 0x2c:
7499 9ee6e8bb pbrook
                        /* Bitfield insert/clear.  */
7500 9ee6e8bb pbrook
                        ARCH(6T2);
7501 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
7502 9ee6e8bb pbrook
                        i = (insn >> 16) & 0x1f;
7503 9ee6e8bb pbrook
                        i = i + 1 - shift;
7504 9ee6e8bb pbrook
                        if (rm == 15) {
7505 7d1b0095 Peter Maydell
                            tmp = tcg_temp_new_i32();
7506 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, 0);
7507 9ee6e8bb pbrook
                        } else {
7508 5e3f878a pbrook
                            tmp = load_reg(s, rm);
7509 9ee6e8bb pbrook
                        }
7510 9ee6e8bb pbrook
                        if (i != 32) {
7511 5e3f878a pbrook
                            tmp2 = load_reg(s, rd);
7512 8f8e3aa4 pbrook
                            gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7513 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
7514 9ee6e8bb pbrook
                        }
7515 5e3f878a pbrook
                        store_reg(s, rd, tmp);
7516 9ee6e8bb pbrook
                        break;
7517 9ee6e8bb pbrook
                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7518 9ee6e8bb pbrook
                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7519 4cc633c3 balrog
                        ARCH(6T2);
7520 5e3f878a pbrook
                        tmp = load_reg(s, rm);
7521 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
7522 9ee6e8bb pbrook
                        i = ((insn >> 16) & 0x1f) + 1;
7523 9ee6e8bb pbrook
                        if (shift + i > 32)
7524 9ee6e8bb pbrook
                            goto illegal_op;
7525 9ee6e8bb pbrook
                        if (i < 32) {
7526 9ee6e8bb pbrook
                            if (op1 & 0x20) {
7527 5e3f878a pbrook
                                gen_ubfx(tmp, shift, (1u << i) - 1);
7528 9ee6e8bb pbrook
                            } else {
7529 5e3f878a pbrook
                                gen_sbfx(tmp, shift, i);
7530 9ee6e8bb pbrook
                            }
7531 9ee6e8bb pbrook
                        }
7532 5e3f878a pbrook
                        store_reg(s, rd, tmp);
7533 9ee6e8bb pbrook
                        break;
7534 9ee6e8bb pbrook
                    default:
7535 9ee6e8bb pbrook
                        goto illegal_op;
7536 9ee6e8bb pbrook
                    }
7537 9ee6e8bb pbrook
                    break;
7538 9ee6e8bb pbrook
                }
7539 9ee6e8bb pbrook
                break;
7540 9ee6e8bb pbrook
            }
7541 9ee6e8bb pbrook
        do_ldst:
7542 9ee6e8bb pbrook
            /* Check for undefined extension instructions
7543 9ee6e8bb pbrook
             * per the ARM Bible IE:
7544 9ee6e8bb pbrook
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
7545 9ee6e8bb pbrook
             */
7546 9ee6e8bb pbrook
            sh = (0xf << 20) | (0xf << 4);
7547 9ee6e8bb pbrook
            if (op1 == 0x7 && ((insn & sh) == sh))
7548 9ee6e8bb pbrook
            {
7549 9ee6e8bb pbrook
                goto illegal_op;
7550 9ee6e8bb pbrook
            }
7551 9ee6e8bb pbrook
            /* load/store byte/word */
7552 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
7553 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
7554 b0109805 pbrook
            tmp2 = load_reg(s, rn);
7555 9ee6e8bb pbrook
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7556 9ee6e8bb pbrook
            if (insn & (1 << 24))
7557 b0109805 pbrook
                gen_add_data_offset(s, insn, tmp2);
7558 9ee6e8bb pbrook
            if (insn & (1 << 20)) {
7559 9ee6e8bb pbrook
                /* load */
7560 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
7561 b0109805 pbrook
                    tmp = gen_ld8u(tmp2, i);
7562 9ee6e8bb pbrook
                } else {
7563 b0109805 pbrook
                    tmp = gen_ld32(tmp2, i);
7564 9ee6e8bb pbrook
                }
7565 9ee6e8bb pbrook
            } else {
7566 9ee6e8bb pbrook
                /* store */
7567 b0109805 pbrook
                tmp = load_reg(s, rd);
7568 9ee6e8bb pbrook
                if (insn & (1 << 22))
7569 b0109805 pbrook
                    gen_st8(tmp, tmp2, i);
7570 9ee6e8bb pbrook
                else
7571 b0109805 pbrook
                    gen_st32(tmp, tmp2, i);
7572 9ee6e8bb pbrook
            }
7573 9ee6e8bb pbrook
            if (!(insn & (1 << 24))) {
7574 b0109805 pbrook
                gen_add_data_offset(s, insn, tmp2);
7575 b0109805 pbrook
                store_reg(s, rn, tmp2);
7576 b0109805 pbrook
            } else if (insn & (1 << 21)) {
7577 b0109805 pbrook
                store_reg(s, rn, tmp2);
7578 b0109805 pbrook
            } else {
7579 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
7580 9ee6e8bb pbrook
            }
7581 9ee6e8bb pbrook
            if (insn & (1 << 20)) {
7582 9ee6e8bb pbrook
                /* Complete the load.  */
7583 be5e7a76 Dmitry Eremin-Solenikov
                store_reg_from_load(env, s, rd, tmp);
7584 9ee6e8bb pbrook
            }
7585 9ee6e8bb pbrook
            break;
7586 9ee6e8bb pbrook
        case 0x08:
7587 9ee6e8bb pbrook
        case 0x09:
7588 9ee6e8bb pbrook
            {
7589 9ee6e8bb pbrook
                int j, n, user, loaded_base;
7590 b0109805 pbrook
                TCGv loaded_var;
7591 9ee6e8bb pbrook
                /* load/store multiple words */
7592 9ee6e8bb pbrook
                /* XXX: store correct base if write back */
7593 9ee6e8bb pbrook
                user = 0;
7594 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
7595 9ee6e8bb pbrook
                    if (IS_USER(s))
7596 9ee6e8bb pbrook
                        goto illegal_op; /* only usable in supervisor mode */
7597 9ee6e8bb pbrook
7598 9ee6e8bb pbrook
                    if ((insn & (1 << 15)) == 0)
7599 9ee6e8bb pbrook
                        user = 1;
7600 9ee6e8bb pbrook
                }
7601 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
7602 b0109805 pbrook
                addr = load_reg(s, rn);
7603 9ee6e8bb pbrook
7604 9ee6e8bb pbrook
                /* compute total size */
7605 9ee6e8bb pbrook
                loaded_base = 0;
7606 a50f5b91 pbrook
                TCGV_UNUSED(loaded_var);
7607 9ee6e8bb pbrook
                n = 0;
7608 9ee6e8bb pbrook
                for(i=0;i<16;i++) {
7609 9ee6e8bb pbrook
                    if (insn & (1 << i))
7610 9ee6e8bb pbrook
                        n++;
7611 9ee6e8bb pbrook
                }
7612 9ee6e8bb pbrook
                /* XXX: test invalid n == 0 case ? */
7613 9ee6e8bb pbrook
                if (insn & (1 << 23)) {
7614 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
7615 9ee6e8bb pbrook
                        /* pre increment */
7616 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
7617 9ee6e8bb pbrook
                    } else {
7618 9ee6e8bb pbrook
                        /* post increment */
7619 9ee6e8bb pbrook
                    }
7620 9ee6e8bb pbrook
                } else {
7621 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
7622 9ee6e8bb pbrook
                        /* pre decrement */
7623 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -(n * 4));
7624 9ee6e8bb pbrook
                    } else {
7625 9ee6e8bb pbrook
                        /* post decrement */
7626 9ee6e8bb pbrook
                        if (n != 1)
7627 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7628 9ee6e8bb pbrook
                    }
7629 9ee6e8bb pbrook
                }
7630 9ee6e8bb pbrook
                j = 0;
7631 9ee6e8bb pbrook
                for(i=0;i<16;i++) {
7632 9ee6e8bb pbrook
                    if (insn & (1 << i)) {
7633 9ee6e8bb pbrook
                        if (insn & (1 << 20)) {
7634 9ee6e8bb pbrook
                            /* load */
7635 b0109805 pbrook
                            tmp = gen_ld32(addr, IS_USER(s));
7636 be5e7a76 Dmitry Eremin-Solenikov
                            if (user) {
7637 b75263d6 Juha Riihimäki
                                tmp2 = tcg_const_i32(i);
7638 b75263d6 Juha Riihimäki
                                gen_helper_set_user_reg(tmp2, tmp);
7639 b75263d6 Juha Riihimäki
                                tcg_temp_free_i32(tmp2);
7640 7d1b0095 Peter Maydell
                                tcg_temp_free_i32(tmp);
7641 9ee6e8bb pbrook
                            } else if (i == rn) {
7642 b0109805 pbrook
                                loaded_var = tmp;
7643 9ee6e8bb pbrook
                                loaded_base = 1;
7644 9ee6e8bb pbrook
                            } else {
7645 be5e7a76 Dmitry Eremin-Solenikov
                                store_reg_from_load(env, s, i, tmp);
7646 9ee6e8bb pbrook
                            }
7647 9ee6e8bb pbrook
                        } else {
7648 9ee6e8bb pbrook
                            /* store */
7649 9ee6e8bb pbrook
                            if (i == 15) {
7650 9ee6e8bb pbrook
                                /* special case: r15 = PC + 8 */
7651 9ee6e8bb pbrook
                                val = (long)s->pc + 4;
7652 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
7653 b0109805 pbrook
                                tcg_gen_movi_i32(tmp, val);
7654 9ee6e8bb pbrook
                            } else if (user) {
7655 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
7656 b75263d6 Juha Riihimäki
                                tmp2 = tcg_const_i32(i);
7657 b75263d6 Juha Riihimäki
                                gen_helper_get_user_reg(tmp, tmp2);
7658 b75263d6 Juha Riihimäki
                                tcg_temp_free_i32(tmp2);
7659 9ee6e8bb pbrook
                            } else {
7660 b0109805 pbrook
                                tmp = load_reg(s, i);
7661 9ee6e8bb pbrook
                            }
7662 b0109805 pbrook
                            gen_st32(tmp, addr, IS_USER(s));
7663 9ee6e8bb pbrook
                        }
7664 9ee6e8bb pbrook
                        j++;
7665 9ee6e8bb pbrook
                        /* no need to add after the last transfer */
7666 9ee6e8bb pbrook
                        if (j != n)
7667 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
7668 9ee6e8bb pbrook
                    }
7669 9ee6e8bb pbrook
                }
7670 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
7671 9ee6e8bb pbrook
                    /* write back */
7672 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
7673 9ee6e8bb pbrook
                        if (insn & (1 << 24)) {
7674 9ee6e8bb pbrook
                            /* pre increment */
7675 9ee6e8bb pbrook
                        } else {
7676 9ee6e8bb pbrook
                            /* post increment */
7677 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
7678 9ee6e8bb pbrook
                        }
7679 9ee6e8bb pbrook
                    } else {
7680 9ee6e8bb pbrook
                        if (insn & (1 << 24)) {
7681 9ee6e8bb pbrook
                            /* pre decrement */
7682 9ee6e8bb pbrook
                            if (n != 1)
7683 b0109805 pbrook
                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7684 9ee6e8bb pbrook
                        } else {
7685 9ee6e8bb pbrook
                            /* post decrement */
7686 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -(n * 4));
7687 9ee6e8bb pbrook
                        }
7688 9ee6e8bb pbrook
                    }
7689 b0109805 pbrook
                    store_reg(s, rn, addr);
7690 b0109805 pbrook
                } else {
7691 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
7692 9ee6e8bb pbrook
                }
7693 9ee6e8bb pbrook
                if (loaded_base) {
7694 b0109805 pbrook
                    store_reg(s, rn, loaded_var);
7695 9ee6e8bb pbrook
                }
7696 9ee6e8bb pbrook
                if ((insn & (1 << 22)) && !user) {
7697 9ee6e8bb pbrook
                    /* Restore CPSR from SPSR.  */
7698 d9ba4830 pbrook
                    tmp = load_cpu_field(spsr);
7699 d9ba4830 pbrook
                    gen_set_cpsr(tmp, 0xffffffff);
7700 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
7701 9ee6e8bb pbrook
                    s->is_jmp = DISAS_UPDATE;
7702 9ee6e8bb pbrook
                }
7703 9ee6e8bb pbrook
            }
7704 9ee6e8bb pbrook
            break;
7705 9ee6e8bb pbrook
        case 0xa:
7706 9ee6e8bb pbrook
        case 0xb:
7707 9ee6e8bb pbrook
            {
7708 9ee6e8bb pbrook
                int32_t offset;
7709 9ee6e8bb pbrook
7710 9ee6e8bb pbrook
                /* branch (and link) */
7711 9ee6e8bb pbrook
                val = (int32_t)s->pc;
7712 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
7713 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
7714 5e3f878a pbrook
                    tcg_gen_movi_i32(tmp, val);
7715 5e3f878a pbrook
                    store_reg(s, 14, tmp);
7716 9ee6e8bb pbrook
                }
7717 9ee6e8bb pbrook
                offset = (((int32_t)insn << 8) >> 8);
7718 9ee6e8bb pbrook
                val += (offset << 2) + 4;
7719 9ee6e8bb pbrook
                gen_jmp(s, val);
7720 9ee6e8bb pbrook
            }
7721 9ee6e8bb pbrook
            break;
7722 9ee6e8bb pbrook
        case 0xc:
7723 9ee6e8bb pbrook
        case 0xd:
7724 9ee6e8bb pbrook
        case 0xe:
7725 9ee6e8bb pbrook
            /* Coprocessor.  */
7726 9ee6e8bb pbrook
            if (disas_coproc_insn(env, s, insn))
7727 9ee6e8bb pbrook
                goto illegal_op;
7728 9ee6e8bb pbrook
            break;
7729 9ee6e8bb pbrook
        case 0xf:
7730 9ee6e8bb pbrook
            /* swi */
7731 5e3f878a pbrook
            gen_set_pc_im(s->pc);
7732 9ee6e8bb pbrook
            s->is_jmp = DISAS_SWI;
7733 9ee6e8bb pbrook
            break;
7734 9ee6e8bb pbrook
        default:
7735 9ee6e8bb pbrook
        illegal_op:
7736 bc4a0de0 Peter Maydell
            gen_exception_insn(s, 4, EXCP_UDEF);
7737 9ee6e8bb pbrook
            break;
7738 9ee6e8bb pbrook
        }
7739 9ee6e8bb pbrook
    }
7740 9ee6e8bb pbrook
}
7741 9ee6e8bb pbrook
7742 9ee6e8bb pbrook
/* Return true if this is a Thumb-2 logical op.  */
7743 9ee6e8bb pbrook
static int
7744 9ee6e8bb pbrook
thumb2_logic_op(int op)
7745 9ee6e8bb pbrook
{
7746 9ee6e8bb pbrook
    return (op < 8);
7747 9ee6e8bb pbrook
}
7748 9ee6e8bb pbrook
7749 9ee6e8bb pbrook
/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
7750 9ee6e8bb pbrook
   then set condition code flags based on the result of the operation.
7751 9ee6e8bb pbrook
   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7752 9ee6e8bb pbrook
   to the high bit of T1.
7753 9ee6e8bb pbrook
   Returns zero if the opcode is valid.  */
7754 9ee6e8bb pbrook
7755 9ee6e8bb pbrook
static int
7756 396e467c Filip Navara
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7757 9ee6e8bb pbrook
{
7758 9ee6e8bb pbrook
    int logic_cc;
7759 9ee6e8bb pbrook
7760 9ee6e8bb pbrook
    logic_cc = 0;
7761 9ee6e8bb pbrook
    switch (op) {
7762 9ee6e8bb pbrook
    case 0: /* and */
7763 396e467c Filip Navara
        tcg_gen_and_i32(t0, t0, t1);
7764 9ee6e8bb pbrook
        logic_cc = conds;
7765 9ee6e8bb pbrook
        break;
7766 9ee6e8bb pbrook
    case 1: /* bic */
7767 f669df27 Aurelien Jarno
        tcg_gen_andc_i32(t0, t0, t1);
7768 9ee6e8bb pbrook
        logic_cc = conds;
7769 9ee6e8bb pbrook
        break;
7770 9ee6e8bb pbrook
    case 2: /* orr */
7771 396e467c Filip Navara
        tcg_gen_or_i32(t0, t0, t1);
7772 9ee6e8bb pbrook
        logic_cc = conds;
7773 9ee6e8bb pbrook
        break;
7774 9ee6e8bb pbrook
    case 3: /* orn */
7775 29501f1b Peter Maydell
        tcg_gen_orc_i32(t0, t0, t1);
7776 9ee6e8bb pbrook
        logic_cc = conds;
7777 9ee6e8bb pbrook
        break;
7778 9ee6e8bb pbrook
    case 4: /* eor */
7779 396e467c Filip Navara
        tcg_gen_xor_i32(t0, t0, t1);
7780 9ee6e8bb pbrook
        logic_cc = conds;
7781 9ee6e8bb pbrook
        break;
7782 9ee6e8bb pbrook
    case 8: /* add */
7783 9ee6e8bb pbrook
        if (conds)
7784 396e467c Filip Navara
            gen_helper_add_cc(t0, t0, t1);
7785 9ee6e8bb pbrook
        else
7786 396e467c Filip Navara
            tcg_gen_add_i32(t0, t0, t1);
7787 9ee6e8bb pbrook
        break;
7788 9ee6e8bb pbrook
    case 10: /* adc */
7789 9ee6e8bb pbrook
        if (conds)
7790 396e467c Filip Navara
            gen_helper_adc_cc(t0, t0, t1);
7791 9ee6e8bb pbrook
        else
7792 396e467c Filip Navara
            gen_adc(t0, t1);
7793 9ee6e8bb pbrook
        break;
7794 9ee6e8bb pbrook
    case 11: /* sbc */
7795 9ee6e8bb pbrook
        if (conds)
7796 396e467c Filip Navara
            gen_helper_sbc_cc(t0, t0, t1);
7797 9ee6e8bb pbrook
        else
7798 396e467c Filip Navara
            gen_sub_carry(t0, t0, t1);
7799 9ee6e8bb pbrook
        break;
7800 9ee6e8bb pbrook
    case 13: /* sub */
7801 9ee6e8bb pbrook
        if (conds)
7802 396e467c Filip Navara
            gen_helper_sub_cc(t0, t0, t1);
7803 9ee6e8bb pbrook
        else
7804 396e467c Filip Navara
            tcg_gen_sub_i32(t0, t0, t1);
7805 9ee6e8bb pbrook
        break;
7806 9ee6e8bb pbrook
    case 14: /* rsb */
7807 9ee6e8bb pbrook
        if (conds)
7808 396e467c Filip Navara
            gen_helper_sub_cc(t0, t1, t0);
7809 9ee6e8bb pbrook
        else
7810 396e467c Filip Navara
            tcg_gen_sub_i32(t0, t1, t0);
7811 9ee6e8bb pbrook
        break;
7812 9ee6e8bb pbrook
    default: /* 5, 6, 7, 9, 12, 15. */
7813 9ee6e8bb pbrook
        return 1;
7814 9ee6e8bb pbrook
    }
7815 9ee6e8bb pbrook
    if (logic_cc) {
7816 396e467c Filip Navara
        gen_logic_CC(t0);
7817 9ee6e8bb pbrook
        if (shifter_out)
7818 396e467c Filip Navara
            gen_set_CF_bit31(t1);
7819 9ee6e8bb pbrook
    }
7820 9ee6e8bb pbrook
    return 0;
7821 9ee6e8bb pbrook
}
7822 9ee6e8bb pbrook
7823 9ee6e8bb pbrook
/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
7824 9ee6e8bb pbrook
   is not legal.  */
7825 9ee6e8bb pbrook
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7826 9ee6e8bb pbrook
{
7827 b0109805 pbrook
    uint32_t insn, imm, shift, offset;
7828 9ee6e8bb pbrook
    uint32_t rd, rn, rm, rs;
7829 b26eefb6 pbrook
    TCGv tmp;
7830 6ddbc6e4 pbrook
    TCGv tmp2;
7831 6ddbc6e4 pbrook
    TCGv tmp3;
7832 b0109805 pbrook
    TCGv addr;
7833 a7812ae4 pbrook
    TCGv_i64 tmp64;
7834 9ee6e8bb pbrook
    int op;
7835 9ee6e8bb pbrook
    int shiftop;
7836 9ee6e8bb pbrook
    int conds;
7837 9ee6e8bb pbrook
    int logic_cc;
7838 9ee6e8bb pbrook
7839 9ee6e8bb pbrook
    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7840 9ee6e8bb pbrook
          || arm_feature (env, ARM_FEATURE_M))) {
7841 601d70b9 balrog
        /* Thumb-1 cores may need to treat bl and blx as a pair of
7842 9ee6e8bb pbrook
           16-bit instructions to get correct prefetch abort behavior.  */
7843 9ee6e8bb pbrook
        insn = insn_hw1;
7844 9ee6e8bb pbrook
        if ((insn & (1 << 12)) == 0) {
7845 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5);
7846 9ee6e8bb pbrook
            /* Second half of blx.  */
7847 9ee6e8bb pbrook
            offset = ((insn & 0x7ff) << 1);
7848 d9ba4830 pbrook
            tmp = load_reg(s, 14);
7849 d9ba4830 pbrook
            tcg_gen_addi_i32(tmp, tmp, offset);
7850 d9ba4830 pbrook
            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7851 9ee6e8bb pbrook
7852 7d1b0095 Peter Maydell
            tmp2 = tcg_temp_new_i32();
7853 b0109805 pbrook
            tcg_gen_movi_i32(tmp2, s->pc | 1);
7854 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
7855 d9ba4830 pbrook
            gen_bx(s, tmp);
7856 9ee6e8bb pbrook
            return 0;
7857 9ee6e8bb pbrook
        }
7858 9ee6e8bb pbrook
        if (insn & (1 << 11)) {
7859 9ee6e8bb pbrook
            /* Second half of bl.  */
7860 9ee6e8bb pbrook
            offset = ((insn & 0x7ff) << 1) | 1;
7861 d9ba4830 pbrook
            tmp = load_reg(s, 14);
7862 6a0d8a1d balrog
            tcg_gen_addi_i32(tmp, tmp, offset);
7863 9ee6e8bb pbrook
7864 7d1b0095 Peter Maydell
            tmp2 = tcg_temp_new_i32();
7865 b0109805 pbrook
            tcg_gen_movi_i32(tmp2, s->pc | 1);
7866 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
7867 d9ba4830 pbrook
            gen_bx(s, tmp);
7868 9ee6e8bb pbrook
            return 0;
7869 9ee6e8bb pbrook
        }
7870 9ee6e8bb pbrook
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7871 9ee6e8bb pbrook
            /* Instruction spans a page boundary.  Implement it as two
7872 9ee6e8bb pbrook
               16-bit instructions in case the second half causes an
7873 9ee6e8bb pbrook
               prefetch abort.  */
7874 9ee6e8bb pbrook
            offset = ((int32_t)insn << 21) >> 9;
7875 396e467c Filip Navara
            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7876 9ee6e8bb pbrook
            return 0;
7877 9ee6e8bb pbrook
        }
7878 9ee6e8bb pbrook
        /* Fall through to 32-bit decode.  */
7879 9ee6e8bb pbrook
    }
7880 9ee6e8bb pbrook
7881 9ee6e8bb pbrook
    insn = lduw_code(s->pc);
7882 9ee6e8bb pbrook
    s->pc += 2;
7883 9ee6e8bb pbrook
    insn |= (uint32_t)insn_hw1 << 16;
7884 9ee6e8bb pbrook
7885 9ee6e8bb pbrook
    if ((insn & 0xf800e800) != 0xf000e800) {
7886 9ee6e8bb pbrook
        ARCH(6T2);
7887 9ee6e8bb pbrook
    }
7888 9ee6e8bb pbrook
7889 9ee6e8bb pbrook
    rn = (insn >> 16) & 0xf;
7890 9ee6e8bb pbrook
    rs = (insn >> 12) & 0xf;
7891 9ee6e8bb pbrook
    rd = (insn >> 8) & 0xf;
7892 9ee6e8bb pbrook
    rm = insn & 0xf;
7893 9ee6e8bb pbrook
    switch ((insn >> 25) & 0xf) {
7894 9ee6e8bb pbrook
    case 0: case 1: case 2: case 3:
7895 9ee6e8bb pbrook
        /* 16-bit instructions.  Should never happen.  */
7896 9ee6e8bb pbrook
        abort();
7897 9ee6e8bb pbrook
    case 4:
7898 9ee6e8bb pbrook
        if (insn & (1 << 22)) {
7899 9ee6e8bb pbrook
            /* Other load/store, table branch.  */
7900 9ee6e8bb pbrook
            if (insn & 0x01200000) {
7901 9ee6e8bb pbrook
                /* Load/store doubleword.  */
7902 9ee6e8bb pbrook
                if (rn == 15) {
7903 7d1b0095 Peter Maydell
                    addr = tcg_temp_new_i32();
7904 b0109805 pbrook
                    tcg_gen_movi_i32(addr, s->pc & ~3);
7905 9ee6e8bb pbrook
                } else {
7906 b0109805 pbrook
                    addr = load_reg(s, rn);
7907 9ee6e8bb pbrook
                }
7908 9ee6e8bb pbrook
                offset = (insn & 0xff) * 4;
7909 9ee6e8bb pbrook
                if ((insn & (1 << 23)) == 0)
7910 9ee6e8bb pbrook
                    offset = -offset;
7911 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
7912 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset);
7913 9ee6e8bb pbrook
                    offset = 0;
7914 9ee6e8bb pbrook
                }
7915 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7916 9ee6e8bb pbrook
                    /* ldrd */
7917 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
7918 b0109805 pbrook
                    store_reg(s, rs, tmp);
7919 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7920 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
7921 b0109805 pbrook
                    store_reg(s, rd, tmp);
7922 9ee6e8bb pbrook
                } else {
7923 9ee6e8bb pbrook
                    /* strd */
7924 b0109805 pbrook
                    tmp = load_reg(s, rs);
7925 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
7926 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7927 b0109805 pbrook
                    tmp = load_reg(s, rd);
7928 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
7929 9ee6e8bb pbrook
                }
7930 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
7931 9ee6e8bb pbrook
                    /* Base writeback.  */
7932 9ee6e8bb pbrook
                    if (rn == 15)
7933 9ee6e8bb pbrook
                        goto illegal_op;
7934 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset - 4);
7935 b0109805 pbrook
                    store_reg(s, rn, addr);
7936 b0109805 pbrook
                } else {
7937 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
7938 9ee6e8bb pbrook
                }
7939 9ee6e8bb pbrook
            } else if ((insn & (1 << 23)) == 0) {
7940 9ee6e8bb pbrook
                /* Load/store exclusive word.  */
7941 3174f8e9 Filip Navara
                addr = tcg_temp_local_new();
7942 98a46317 Aurelien Jarno
                load_reg_var(s, addr, rn);
7943 426f5abc Paul Brook
                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7944 2c0262af bellard
                if (insn & (1 << 20)) {
7945 426f5abc Paul Brook
                    gen_load_exclusive(s, rs, 15, addr, 2);
7946 9ee6e8bb pbrook
                } else {
7947 426f5abc Paul Brook
                    gen_store_exclusive(s, rd, rs, 15, addr, 2);
7948 9ee6e8bb pbrook
                }
7949 3174f8e9 Filip Navara
                tcg_temp_free(addr);
7950 9ee6e8bb pbrook
            } else if ((insn & (1 << 6)) == 0) {
7951 9ee6e8bb pbrook
                /* Table Branch.  */
7952 9ee6e8bb pbrook
                if (rn == 15) {
7953 7d1b0095 Peter Maydell
                    addr = tcg_temp_new_i32();
7954 b0109805 pbrook
                    tcg_gen_movi_i32(addr, s->pc);
7955 9ee6e8bb pbrook
                } else {
7956 b0109805 pbrook
                    addr = load_reg(s, rn);
7957 9ee6e8bb pbrook
                }
7958 b26eefb6 pbrook
                tmp = load_reg(s, rm);
7959 b0109805 pbrook
                tcg_gen_add_i32(addr, addr, tmp);
7960 9ee6e8bb pbrook
                if (insn & (1 << 4)) {
7961 9ee6e8bb pbrook
                    /* tbh */
7962 b0109805 pbrook
                    tcg_gen_add_i32(addr, addr, tmp);
7963 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
7964 b0109805 pbrook
                    tmp = gen_ld16u(addr, IS_USER(s));
7965 9ee6e8bb pbrook
                } else { /* tbb */
7966 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
7967 b0109805 pbrook
                    tmp = gen_ld8u(addr, IS_USER(s));
7968 9ee6e8bb pbrook
                }
7969 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
7970 b0109805 pbrook
                tcg_gen_shli_i32(tmp, tmp, 1);
7971 b0109805 pbrook
                tcg_gen_addi_i32(tmp, tmp, s->pc);
7972 b0109805 pbrook
                store_reg(s, 15, tmp);
7973 9ee6e8bb pbrook
            } else {
7974 9ee6e8bb pbrook
                /* Load/store exclusive byte/halfword/doubleword.  */
7975 426f5abc Paul Brook
                ARCH(7);
7976 9ee6e8bb pbrook
                op = (insn >> 4) & 0x3;
7977 426f5abc Paul Brook
                if (op == 2) {
7978 426f5abc Paul Brook
                    goto illegal_op;
7979 426f5abc Paul Brook
                }
7980 3174f8e9 Filip Navara
                addr = tcg_temp_local_new();
7981 98a46317 Aurelien Jarno
                load_reg_var(s, addr, rn);
7982 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7983 426f5abc Paul Brook
                    gen_load_exclusive(s, rs, rd, addr, op);
7984 9ee6e8bb pbrook
                } else {
7985 426f5abc Paul Brook
                    gen_store_exclusive(s, rm, rs, rd, addr, op);
7986 9ee6e8bb pbrook
                }
7987 3174f8e9 Filip Navara
                tcg_temp_free(addr);
7988 9ee6e8bb pbrook
            }
7989 9ee6e8bb pbrook
        } else {
7990 9ee6e8bb pbrook
            /* Load/store multiple, RFE, SRS.  */
7991 9ee6e8bb pbrook
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7992 9ee6e8bb pbrook
                /* Not available in user mode.  */
7993 b0109805 pbrook
                if (IS_USER(s))
7994 9ee6e8bb pbrook
                    goto illegal_op;
7995 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7996 9ee6e8bb pbrook
                    /* rfe */
7997 b0109805 pbrook
                    addr = load_reg(s, rn);
7998 b0109805 pbrook
                    if ((insn & (1 << 24)) == 0)
7999 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -8);
8000 b0109805 pbrook
                    /* Load PC into tmp and CPSR into tmp2.  */
8001 b0109805 pbrook
                    tmp = gen_ld32(addr, 0);
8002 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
8003 b0109805 pbrook
                    tmp2 = gen_ld32(addr, 0);
8004 9ee6e8bb pbrook
                    if (insn & (1 << 21)) {
8005 9ee6e8bb pbrook
                        /* Base writeback.  */
8006 b0109805 pbrook
                        if (insn & (1 << 24)) {
8007 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
8008 b0109805 pbrook
                        } else {
8009 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -4);
8010 b0109805 pbrook
                        }
8011 b0109805 pbrook
                        store_reg(s, rn, addr);
8012 b0109805 pbrook
                    } else {
8013 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(addr);
8014 9ee6e8bb pbrook
                    }
8015 b0109805 pbrook
                    gen_rfe(s, tmp, tmp2);
8016 9ee6e8bb pbrook
                } else {
8017 9ee6e8bb pbrook
                    /* srs */
8018 9ee6e8bb pbrook
                    op = (insn & 0x1f);
8019 7d1b0095 Peter Maydell
                    addr = tcg_temp_new_i32();
8020 39ea3d4e Peter Maydell
                    tmp = tcg_const_i32(op);
8021 39ea3d4e Peter Maydell
                    gen_helper_get_r13_banked(addr, cpu_env, tmp);
8022 39ea3d4e Peter Maydell
                    tcg_temp_free_i32(tmp);
8023 9ee6e8bb pbrook
                    if ((insn & (1 << 24)) == 0) {
8024 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -8);
8025 9ee6e8bb pbrook
                    }
8026 b0109805 pbrook
                    tmp = load_reg(s, 14);
8027 b0109805 pbrook
                    gen_st32(tmp, addr, 0);
8028 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
8029 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
8030 b0109805 pbrook
                    gen_helper_cpsr_read(tmp);
8031 b0109805 pbrook
                    gen_st32(tmp, addr, 0);
8032 9ee6e8bb pbrook
                    if (insn & (1 << 21)) {
8033 9ee6e8bb pbrook
                        if ((insn & (1 << 24)) == 0) {
8034 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -4);
8035 9ee6e8bb pbrook
                        } else {
8036 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
8037 9ee6e8bb pbrook
                        }
8038 39ea3d4e Peter Maydell
                        tmp = tcg_const_i32(op);
8039 39ea3d4e Peter Maydell
                        gen_helper_set_r13_banked(cpu_env, tmp, addr);
8040 39ea3d4e Peter Maydell
                        tcg_temp_free_i32(tmp);
8041 b0109805 pbrook
                    } else {
8042 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(addr);
8043 9ee6e8bb pbrook
                    }
8044 9ee6e8bb pbrook
                }
8045 9ee6e8bb pbrook
            } else {
8046 5856d44e YuYeon Oh
                int i, loaded_base = 0;
8047 5856d44e YuYeon Oh
                TCGv loaded_var;
8048 9ee6e8bb pbrook
                /* Load/store multiple.  */
8049 b0109805 pbrook
                addr = load_reg(s, rn);
8050 9ee6e8bb pbrook
                offset = 0;
8051 9ee6e8bb pbrook
                for (i = 0; i < 16; i++) {
8052 9ee6e8bb pbrook
                    if (insn & (1 << i))
8053 9ee6e8bb pbrook
                        offset += 4;
8054 9ee6e8bb pbrook
                }
8055 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
8056 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, -offset);
8057 9ee6e8bb pbrook
                }
8058 9ee6e8bb pbrook
8059 5856d44e YuYeon Oh
                TCGV_UNUSED(loaded_var);
8060 9ee6e8bb pbrook
                for (i = 0; i < 16; i++) {
8061 9ee6e8bb pbrook
                    if ((insn & (1 << i)) == 0)
8062 9ee6e8bb pbrook
                        continue;
8063 9ee6e8bb pbrook
                    if (insn & (1 << 20)) {
8064 9ee6e8bb pbrook
                        /* Load.  */
8065 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
8066 9ee6e8bb pbrook
                        if (i == 15) {
8067 b0109805 pbrook
                            gen_bx(s, tmp);
8068 5856d44e YuYeon Oh
                        } else if (i == rn) {
8069 5856d44e YuYeon Oh
                            loaded_var = tmp;
8070 5856d44e YuYeon Oh
                            loaded_base = 1;
8071 9ee6e8bb pbrook
                        } else {
8072 b0109805 pbrook
                            store_reg(s, i, tmp);
8073 9ee6e8bb pbrook
                        }
8074 9ee6e8bb pbrook
                    } else {
8075 9ee6e8bb pbrook
                        /* Store.  */
8076 b0109805 pbrook
                        tmp = load_reg(s, i);
8077 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
8078 9ee6e8bb pbrook
                    }
8079 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
8080 9ee6e8bb pbrook
                }
8081 5856d44e YuYeon Oh
                if (loaded_base) {
8082 5856d44e YuYeon Oh
                    store_reg(s, rn, loaded_var);
8083 5856d44e YuYeon Oh
                }
8084 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
8085 9ee6e8bb pbrook
                    /* Base register writeback.  */
8086 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
8087 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -offset);
8088 9ee6e8bb pbrook
                    }
8089 9ee6e8bb pbrook
                    /* Fault if writeback register is in register list.  */
8090 9ee6e8bb pbrook
                    if (insn & (1 << rn))
8091 9ee6e8bb pbrook
                        goto illegal_op;
8092 b0109805 pbrook
                    store_reg(s, rn, addr);
8093 b0109805 pbrook
                } else {
8094 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
8095 9ee6e8bb pbrook
                }
8096 9ee6e8bb pbrook
            }
8097 9ee6e8bb pbrook
        }
8098 9ee6e8bb pbrook
        break;
8099 2af9ab77 Johan Bengtsson
    case 5:
8100 2af9ab77 Johan Bengtsson
8101 9ee6e8bb pbrook
        op = (insn >> 21) & 0xf;
8102 2af9ab77 Johan Bengtsson
        if (op == 6) {
8103 2af9ab77 Johan Bengtsson
            /* Halfword pack.  */
8104 2af9ab77 Johan Bengtsson
            tmp = load_reg(s, rn);
8105 2af9ab77 Johan Bengtsson
            tmp2 = load_reg(s, rm);
8106 2af9ab77 Johan Bengtsson
            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8107 2af9ab77 Johan Bengtsson
            if (insn & (1 << 5)) {
8108 2af9ab77 Johan Bengtsson
                /* pkhtb */
8109 2af9ab77 Johan Bengtsson
                if (shift == 0)
8110 2af9ab77 Johan Bengtsson
                    shift = 31;
8111 2af9ab77 Johan Bengtsson
                tcg_gen_sari_i32(tmp2, tmp2, shift);
8112 2af9ab77 Johan Bengtsson
                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8113 2af9ab77 Johan Bengtsson
                tcg_gen_ext16u_i32(tmp2, tmp2);
8114 2af9ab77 Johan Bengtsson
            } else {
8115 2af9ab77 Johan Bengtsson
                /* pkhbt */
8116 2af9ab77 Johan Bengtsson
                if (shift)
8117 2af9ab77 Johan Bengtsson
                    tcg_gen_shli_i32(tmp2, tmp2, shift);
8118 2af9ab77 Johan Bengtsson
                tcg_gen_ext16u_i32(tmp, tmp);
8119 2af9ab77 Johan Bengtsson
                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8120 2af9ab77 Johan Bengtsson
            }
8121 2af9ab77 Johan Bengtsson
            tcg_gen_or_i32(tmp, tmp, tmp2);
8122 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
8123 3174f8e9 Filip Navara
            store_reg(s, rd, tmp);
8124 3174f8e9 Filip Navara
        } else {
8125 2af9ab77 Johan Bengtsson
            /* Data processing register constant shift.  */
8126 2af9ab77 Johan Bengtsson
            if (rn == 15) {
8127 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
8128 2af9ab77 Johan Bengtsson
                tcg_gen_movi_i32(tmp, 0);
8129 2af9ab77 Johan Bengtsson
            } else {
8130 2af9ab77 Johan Bengtsson
                tmp = load_reg(s, rn);
8131 2af9ab77 Johan Bengtsson
            }
8132 2af9ab77 Johan Bengtsson
            tmp2 = load_reg(s, rm);
8133 2af9ab77 Johan Bengtsson
8134 2af9ab77 Johan Bengtsson
            shiftop = (insn >> 4) & 3;
8135 2af9ab77 Johan Bengtsson
            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8136 2af9ab77 Johan Bengtsson
            conds = (insn & (1 << 20)) != 0;
8137 2af9ab77 Johan Bengtsson
            logic_cc = (conds && thumb2_logic_op(op));
8138 2af9ab77 Johan Bengtsson
            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8139 2af9ab77 Johan Bengtsson
            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8140 2af9ab77 Johan Bengtsson
                goto illegal_op;
8141 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
8142 2af9ab77 Johan Bengtsson
            if (rd != 15) {
8143 2af9ab77 Johan Bengtsson
                store_reg(s, rd, tmp);
8144 2af9ab77 Johan Bengtsson
            } else {
8145 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
8146 2af9ab77 Johan Bengtsson
            }
8147 3174f8e9 Filip Navara
        }
8148 9ee6e8bb pbrook
        break;
8149 9ee6e8bb pbrook
    case 13: /* Misc data processing.  */
8150 9ee6e8bb pbrook
        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8151 9ee6e8bb pbrook
        if (op < 4 && (insn & 0xf000) != 0xf000)
8152 9ee6e8bb pbrook
            goto illegal_op;
8153 9ee6e8bb pbrook
        switch (op) {
8154 9ee6e8bb pbrook
        case 0: /* Register controlled shift.  */
8155 8984bd2e pbrook
            tmp = load_reg(s, rn);
8156 8984bd2e pbrook
            tmp2 = load_reg(s, rm);
8157 9ee6e8bb pbrook
            if ((insn & 0x70) != 0)
8158 9ee6e8bb pbrook
                goto illegal_op;
8159 9ee6e8bb pbrook
            op = (insn >> 21) & 3;
8160 8984bd2e pbrook
            logic_cc = (insn & (1 << 20)) != 0;
8161 8984bd2e pbrook
            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8162 8984bd2e pbrook
            if (logic_cc)
8163 8984bd2e pbrook
                gen_logic_CC(tmp);
8164 21aeb343 Juha Riihimäki
            store_reg_bx(env, s, rd, tmp);
8165 9ee6e8bb pbrook
            break;
8166 9ee6e8bb pbrook
        case 1: /* Sign/zero extend.  */
8167 5e3f878a pbrook
            tmp = load_reg(s, rm);
8168 9ee6e8bb pbrook
            shift = (insn >> 4) & 3;
8169 1301f322 Stefan Weil
            /* ??? In many cases it's not necessary to do a
8170 9ee6e8bb pbrook
               rotate, a shift is sufficient.  */
8171 9ee6e8bb pbrook
            if (shift != 0)
8172 f669df27 Aurelien Jarno
                tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8173 9ee6e8bb pbrook
            op = (insn >> 20) & 7;
8174 9ee6e8bb pbrook
            switch (op) {
8175 5e3f878a pbrook
            case 0: gen_sxth(tmp);   break;
8176 5e3f878a pbrook
            case 1: gen_uxth(tmp);   break;
8177 5e3f878a pbrook
            case 2: gen_sxtb16(tmp); break;
8178 5e3f878a pbrook
            case 3: gen_uxtb16(tmp); break;
8179 5e3f878a pbrook
            case 4: gen_sxtb(tmp);   break;
8180 5e3f878a pbrook
            case 5: gen_uxtb(tmp);   break;
8181 9ee6e8bb pbrook
            default: goto illegal_op;
8182 9ee6e8bb pbrook
            }
8183 9ee6e8bb pbrook
            if (rn != 15) {
8184 5e3f878a pbrook
                tmp2 = load_reg(s, rn);
8185 9ee6e8bb pbrook
                if ((op >> 1) == 1) {
8186 5e3f878a pbrook
                    gen_add16(tmp, tmp2);
8187 9ee6e8bb pbrook
                } else {
8188 5e3f878a pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8189 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8190 9ee6e8bb pbrook
                }
8191 9ee6e8bb pbrook
            }
8192 5e3f878a pbrook
            store_reg(s, rd, tmp);
8193 9ee6e8bb pbrook
            break;
8194 9ee6e8bb pbrook
        case 2: /* SIMD add/subtract.  */
8195 9ee6e8bb pbrook
            op = (insn >> 20) & 7;
8196 9ee6e8bb pbrook
            shift = (insn >> 4) & 7;
8197 9ee6e8bb pbrook
            if ((op & 3) == 3 || (shift & 3) == 3)
8198 9ee6e8bb pbrook
                goto illegal_op;
8199 6ddbc6e4 pbrook
            tmp = load_reg(s, rn);
8200 6ddbc6e4 pbrook
            tmp2 = load_reg(s, rm);
8201 6ddbc6e4 pbrook
            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8202 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
8203 6ddbc6e4 pbrook
            store_reg(s, rd, tmp);
8204 9ee6e8bb pbrook
            break;
8205 9ee6e8bb pbrook
        case 3: /* Other data processing.  */
8206 9ee6e8bb pbrook
            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8207 9ee6e8bb pbrook
            if (op < 4) {
8208 9ee6e8bb pbrook
                /* Saturating add/subtract.  */
8209 d9ba4830 pbrook
                tmp = load_reg(s, rn);
8210 d9ba4830 pbrook
                tmp2 = load_reg(s, rm);
8211 9ee6e8bb pbrook
                if (op & 1)
8212 4809c612 Johan Bengtsson
                    gen_helper_double_saturate(tmp, tmp);
8213 4809c612 Johan Bengtsson
                if (op & 2)
8214 d9ba4830 pbrook
                    gen_helper_sub_saturate(tmp, tmp2, tmp);
8215 9ee6e8bb pbrook
                else
8216 d9ba4830 pbrook
                    gen_helper_add_saturate(tmp, tmp, tmp2);
8217 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8218 9ee6e8bb pbrook
            } else {
8219 d9ba4830 pbrook
                tmp = load_reg(s, rn);
8220 9ee6e8bb pbrook
                switch (op) {
8221 9ee6e8bb pbrook
                case 0x0a: /* rbit */
8222 d9ba4830 pbrook
                    gen_helper_rbit(tmp, tmp);
8223 9ee6e8bb pbrook
                    break;
8224 9ee6e8bb pbrook
                case 0x08: /* rev */
8225 66896cb8 aurel32
                    tcg_gen_bswap32_i32(tmp, tmp);
8226 9ee6e8bb pbrook
                    break;
8227 9ee6e8bb pbrook
                case 0x09: /* rev16 */
8228 d9ba4830 pbrook
                    gen_rev16(tmp);
8229 9ee6e8bb pbrook
                    break;
8230 9ee6e8bb pbrook
                case 0x0b: /* revsh */
8231 d9ba4830 pbrook
                    gen_revsh(tmp);
8232 9ee6e8bb pbrook
                    break;
8233 9ee6e8bb pbrook
                case 0x10: /* sel */
8234 d9ba4830 pbrook
                    tmp2 = load_reg(s, rm);
8235 7d1b0095 Peter Maydell
                    tmp3 = tcg_temp_new_i32();
8236 6ddbc6e4 pbrook
                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
8237 d9ba4830 pbrook
                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8238 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp3);
8239 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8240 9ee6e8bb pbrook
                    break;
8241 9ee6e8bb pbrook
                case 0x18: /* clz */
8242 d9ba4830 pbrook
                    gen_helper_clz(tmp, tmp);
8243 9ee6e8bb pbrook
                    break;
8244 9ee6e8bb pbrook
                default:
8245 9ee6e8bb pbrook
                    goto illegal_op;
8246 9ee6e8bb pbrook
                }
8247 9ee6e8bb pbrook
            }
8248 d9ba4830 pbrook
            store_reg(s, rd, tmp);
8249 9ee6e8bb pbrook
            break;
8250 9ee6e8bb pbrook
        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
8251 9ee6e8bb pbrook
            op = (insn >> 4) & 0xf;
8252 d9ba4830 pbrook
            tmp = load_reg(s, rn);
8253 d9ba4830 pbrook
            tmp2 = load_reg(s, rm);
8254 9ee6e8bb pbrook
            switch ((insn >> 20) & 7) {
8255 9ee6e8bb pbrook
            case 0: /* 32 x 32 -> 32 */
8256 d9ba4830 pbrook
                tcg_gen_mul_i32(tmp, tmp, tmp2);
8257 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8258 9ee6e8bb pbrook
                if (rs != 15) {
8259 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
8260 9ee6e8bb pbrook
                    if (op)
8261 d9ba4830 pbrook
                        tcg_gen_sub_i32(tmp, tmp2, tmp);
8262 9ee6e8bb pbrook
                    else
8263 d9ba4830 pbrook
                        tcg_gen_add_i32(tmp, tmp, tmp2);
8264 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8265 9ee6e8bb pbrook
                }
8266 9ee6e8bb pbrook
                break;
8267 9ee6e8bb pbrook
            case 1: /* 16 x 16 -> 32 */
8268 d9ba4830 pbrook
                gen_mulxy(tmp, tmp2, op & 2, op & 1);
8269 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8270 9ee6e8bb pbrook
                if (rs != 15) {
8271 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
8272 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
8273 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8274 9ee6e8bb pbrook
                }
8275 9ee6e8bb pbrook
                break;
8276 9ee6e8bb pbrook
            case 2: /* Dual multiply add.  */
8277 9ee6e8bb pbrook
            case 4: /* Dual multiply subtract.  */
8278 9ee6e8bb pbrook
                if (op)
8279 d9ba4830 pbrook
                    gen_swap_half(tmp2);
8280 d9ba4830 pbrook
                gen_smul_dual(tmp, tmp2);
8281 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
8282 e1d177b9 Peter Maydell
                    /* This subtraction cannot overflow. */
8283 d9ba4830 pbrook
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8284 9ee6e8bb pbrook
                } else {
8285 e1d177b9 Peter Maydell
                    /* This addition cannot overflow 32 bits;
8286 e1d177b9 Peter Maydell
                     * however it may overflow considered as a signed
8287 e1d177b9 Peter Maydell
                     * operation, in which case we must set the Q flag.
8288 e1d177b9 Peter Maydell
                     */
8289 e1d177b9 Peter Maydell
                    gen_helper_add_setq(tmp, tmp, tmp2);
8290 9ee6e8bb pbrook
                }
8291 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8292 9ee6e8bb pbrook
                if (rs != 15)
8293 9ee6e8bb pbrook
                  {
8294 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
8295 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
8296 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8297 9ee6e8bb pbrook
                  }
8298 9ee6e8bb pbrook
                break;
8299 9ee6e8bb pbrook
            case 3: /* 32 * 16 -> 32msb */
8300 9ee6e8bb pbrook
                if (op)
8301 d9ba4830 pbrook
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
8302 9ee6e8bb pbrook
                else
8303 d9ba4830 pbrook
                    gen_sxth(tmp2);
8304 a7812ae4 pbrook
                tmp64 = gen_muls_i64_i32(tmp, tmp2);
8305 a7812ae4 pbrook
                tcg_gen_shri_i64(tmp64, tmp64, 16);
8306 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
8307 a7812ae4 pbrook
                tcg_gen_trunc_i64_i32(tmp, tmp64);
8308 b75263d6 Juha Riihimäki
                tcg_temp_free_i64(tmp64);
8309 9ee6e8bb pbrook
                if (rs != 15)
8310 9ee6e8bb pbrook
                  {
8311 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
8312 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
8313 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8314 9ee6e8bb pbrook
                  }
8315 9ee6e8bb pbrook
                break;
8316 838fa72d Aurelien Jarno
            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8317 838fa72d Aurelien Jarno
                tmp64 = gen_muls_i64_i32(tmp, tmp2);
8318 9ee6e8bb pbrook
                if (rs != 15) {
8319 838fa72d Aurelien Jarno
                    tmp = load_reg(s, rs);
8320 838fa72d Aurelien Jarno
                    if (insn & (1 << 20)) {
8321 838fa72d Aurelien Jarno
                        tmp64 = gen_addq_msw(tmp64, tmp);
8322 99c475ab bellard
                    } else {
8323 838fa72d Aurelien Jarno
                        tmp64 = gen_subq_msw(tmp64, tmp);
8324 99c475ab bellard
                    }
8325 2c0262af bellard
                }
8326 838fa72d Aurelien Jarno
                if (insn & (1 << 4)) {
8327 838fa72d Aurelien Jarno
                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8328 838fa72d Aurelien Jarno
                }
8329 838fa72d Aurelien Jarno
                tcg_gen_shri_i64(tmp64, tmp64, 32);
8330 7d1b0095 Peter Maydell
                tmp = tcg_temp_new_i32();
8331 838fa72d Aurelien Jarno
                tcg_gen_trunc_i64_i32(tmp, tmp64);
8332 838fa72d Aurelien Jarno
                tcg_temp_free_i64(tmp64);
8333 9ee6e8bb pbrook
                break;
8334 9ee6e8bb pbrook
            case 7: /* Unsigned sum of absolute differences.  */
8335 d9ba4830 pbrook
                gen_helper_usad8(tmp, tmp, tmp2);
8336 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8337 9ee6e8bb pbrook
                if (rs != 15) {
8338 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
8339 d9ba4830 pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8340 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
8341 5fd46862 pbrook
                }
8342 9ee6e8bb pbrook
                break;
8343 2c0262af bellard
            }
8344 d9ba4830 pbrook
            store_reg(s, rd, tmp);
8345 2c0262af bellard
            break;
8346 9ee6e8bb pbrook
        case 6: case 7: /* 64-bit multiply, Divide.  */
8347 9ee6e8bb pbrook
            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8348 5e3f878a pbrook
            tmp = load_reg(s, rn);
8349 5e3f878a pbrook
            tmp2 = load_reg(s, rm);
8350 9ee6e8bb pbrook
            if ((op & 0x50) == 0x10) {
8351 9ee6e8bb pbrook
                /* sdiv, udiv */
8352 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_DIV))
8353 9ee6e8bb pbrook
                    goto illegal_op;
8354 9ee6e8bb pbrook
                if (op & 0x20)
8355 5e3f878a pbrook
                    gen_helper_udiv(tmp, tmp, tmp2);
8356 2c0262af bellard
                else
8357 5e3f878a pbrook
                    gen_helper_sdiv(tmp, tmp, tmp2);
8358 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8359 5e3f878a pbrook
                store_reg(s, rd, tmp);
8360 9ee6e8bb pbrook
            } else if ((op & 0xe) == 0xc) {
8361 9ee6e8bb pbrook
                /* Dual multiply accumulate long.  */
8362 9ee6e8bb pbrook
                if (op & 1)
8363 5e3f878a pbrook
                    gen_swap_half(tmp2);
8364 5e3f878a pbrook
                gen_smul_dual(tmp, tmp2);
8365 9ee6e8bb pbrook
                if (op & 0x10) {
8366 5e3f878a pbrook
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8367 b5ff1b31 bellard
                } else {
8368 5e3f878a pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8369 b5ff1b31 bellard
                }
8370 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8371 a7812ae4 pbrook
                /* BUGFIX */
8372 a7812ae4 pbrook
                tmp64 = tcg_temp_new_i64();
8373 a7812ae4 pbrook
                tcg_gen_ext_i32_i64(tmp64, tmp);
8374 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
8375 a7812ae4 pbrook
                gen_addq(s, tmp64, rs, rd);
8376 a7812ae4 pbrook
                gen_storeq_reg(s, rs, rd, tmp64);
8377 b75263d6 Juha Riihimäki
                tcg_temp_free_i64(tmp64);
8378 2c0262af bellard
            } else {
8379 9ee6e8bb pbrook
                if (op & 0x20) {
8380 9ee6e8bb pbrook
                    /* Unsigned 64-bit multiply  */
8381 a7812ae4 pbrook
                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8382 b5ff1b31 bellard
                } else {
8383 9ee6e8bb pbrook
                    if (op & 8) {
8384 9ee6e8bb pbrook
                        /* smlalxy */
8385 5e3f878a pbrook
                        gen_mulxy(tmp, tmp2, op & 2, op & 1);
8386 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
8387 a7812ae4 pbrook
                        tmp64 = tcg_temp_new_i64();
8388 a7812ae4 pbrook
                        tcg_gen_ext_i32_i64(tmp64, tmp);
8389 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
8390 9ee6e8bb pbrook
                    } else {
8391 9ee6e8bb pbrook
                        /* Signed 64-bit multiply  */
8392 a7812ae4 pbrook
                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
8393 9ee6e8bb pbrook
                    }
8394 b5ff1b31 bellard
                }
8395 9ee6e8bb pbrook
                if (op & 4) {
8396 9ee6e8bb pbrook
                    /* umaal */
8397 a7812ae4 pbrook
                    gen_addq_lo(s, tmp64, rs);
8398 a7812ae4 pbrook
                    gen_addq_lo(s, tmp64, rd);
8399 9ee6e8bb pbrook
                } else if (op & 0x40) {
8400 9ee6e8bb pbrook
                    /* 64-bit accumulate.  */
8401 a7812ae4 pbrook
                    gen_addq(s, tmp64, rs, rd);
8402 9ee6e8bb pbrook
                }
8403 a7812ae4 pbrook
                gen_storeq_reg(s, rs, rd, tmp64);
8404 b75263d6 Juha Riihimäki
                tcg_temp_free_i64(tmp64);
8405 5fd46862 pbrook
            }
8406 2c0262af bellard
            break;
8407 9ee6e8bb pbrook
        }
8408 9ee6e8bb pbrook
        break;
8409 9ee6e8bb pbrook
    case 6: case 7: case 14: case 15:
8410 9ee6e8bb pbrook
        /* Coprocessor.  */
8411 9ee6e8bb pbrook
        if (((insn >> 24) & 3) == 3) {
8412 9ee6e8bb pbrook
            /* Translate into the equivalent ARM encoding.  */
8413 f06053e3 Juha Riihimäki
            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8414 9ee6e8bb pbrook
            if (disas_neon_data_insn(env, s, insn))
8415 9ee6e8bb pbrook
                goto illegal_op;
8416 9ee6e8bb pbrook
        } else {
8417 9ee6e8bb pbrook
            if (insn & (1 << 28))
8418 9ee6e8bb pbrook
                goto illegal_op;
8419 9ee6e8bb pbrook
            if (disas_coproc_insn (env, s, insn))
8420 9ee6e8bb pbrook
                goto illegal_op;
8421 9ee6e8bb pbrook
        }
8422 9ee6e8bb pbrook
        break;
8423 9ee6e8bb pbrook
    case 8: case 9: case 10: case 11:
8424 9ee6e8bb pbrook
        if (insn & (1 << 15)) {
8425 9ee6e8bb pbrook
            /* Branches, misc control.  */
8426 9ee6e8bb pbrook
            if (insn & 0x5000) {
8427 9ee6e8bb pbrook
                /* Unconditional branch.  */
8428 9ee6e8bb pbrook
                /* signextend(hw1[10:0]) -> offset[:12].  */
8429 9ee6e8bb pbrook
                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8430 9ee6e8bb pbrook
                /* hw1[10:0] -> offset[11:1].  */
8431 9ee6e8bb pbrook
                offset |= (insn & 0x7ff) << 1;
8432 9ee6e8bb pbrook
                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8433 9ee6e8bb pbrook
                   offset[24:22] already have the same value because of the
8434 9ee6e8bb pbrook
                   sign extension above.  */
8435 9ee6e8bb pbrook
                offset ^= ((~insn) & (1 << 13)) << 10;
8436 9ee6e8bb pbrook
                offset ^= ((~insn) & (1 << 11)) << 11;
8437 9ee6e8bb pbrook
8438 9ee6e8bb pbrook
                if (insn & (1 << 14)) {
8439 9ee6e8bb pbrook
                    /* Branch and link.  */
8440 3174f8e9 Filip Navara
                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8441 b5ff1b31 bellard
                }
8442 3b46e624 ths
8443 b0109805 pbrook
                offset += s->pc;
8444 9ee6e8bb pbrook
                if (insn & (1 << 12)) {
8445 9ee6e8bb pbrook
                    /* b/bl */
8446 b0109805 pbrook
                    gen_jmp(s, offset);
8447 9ee6e8bb pbrook
                } else {
8448 9ee6e8bb pbrook
                    /* blx */
8449 b0109805 pbrook
                    offset &= ~(uint32_t)2;
8450 be5e7a76 Dmitry Eremin-Solenikov
                    /* thumb2 bx, no need to check */
8451 b0109805 pbrook
                    gen_bx_im(s, offset);
8452 2c0262af bellard
                }
8453 9ee6e8bb pbrook
            } else if (((insn >> 23) & 7) == 7) {
8454 9ee6e8bb pbrook
                /* Misc control */
8455 9ee6e8bb pbrook
                if (insn & (1 << 13))
8456 9ee6e8bb pbrook
                    goto illegal_op;
8457 9ee6e8bb pbrook
8458 9ee6e8bb pbrook
                if (insn & (1 << 26)) {
8459 9ee6e8bb pbrook
                    /* Secure monitor call (v6Z) */
8460 9ee6e8bb pbrook
                    goto illegal_op; /* not implemented.  */
8461 2c0262af bellard
                } else {
8462 9ee6e8bb pbrook
                    op = (insn >> 20) & 7;
8463 9ee6e8bb pbrook
                    switch (op) {
8464 9ee6e8bb pbrook
                    case 0: /* msr cpsr.  */
8465 9ee6e8bb pbrook
                        if (IS_M(env)) {
8466 8984bd2e pbrook
                            tmp = load_reg(s, rn);
8467 8984bd2e pbrook
                            addr = tcg_const_i32(insn & 0xff);
8468 8984bd2e pbrook
                            gen_helper_v7m_msr(cpu_env, addr, tmp);
8469 b75263d6 Juha Riihimäki
                            tcg_temp_free_i32(addr);
8470 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp);
8471 9ee6e8bb pbrook
                            gen_lookup_tb(s);
8472 9ee6e8bb pbrook
                            break;
8473 9ee6e8bb pbrook
                        }
8474 9ee6e8bb pbrook
                        /* fall through */
8475 9ee6e8bb pbrook
                    case 1: /* msr spsr.  */
8476 9ee6e8bb pbrook
                        if (IS_M(env))
8477 9ee6e8bb pbrook
                            goto illegal_op;
8478 2fbac54b Filip Navara
                        tmp = load_reg(s, rn);
8479 2fbac54b Filip Navara
                        if (gen_set_psr(s,
8480 9ee6e8bb pbrook
                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8481 2fbac54b Filip Navara
                              op == 1, tmp))
8482 9ee6e8bb pbrook
                            goto illegal_op;
8483 9ee6e8bb pbrook
                        break;
8484 9ee6e8bb pbrook
                    case 2: /* cps, nop-hint.  */
8485 9ee6e8bb pbrook
                        if (((insn >> 8) & 7) == 0) {
8486 9ee6e8bb pbrook
                            gen_nop_hint(s, insn & 0xff);
8487 9ee6e8bb pbrook
                        }
8488 9ee6e8bb pbrook
                        /* Implemented as NOP in user mode.  */
8489 9ee6e8bb pbrook
                        if (IS_USER(s))
8490 9ee6e8bb pbrook
                            break;
8491 9ee6e8bb pbrook
                        offset = 0;
8492 9ee6e8bb pbrook
                        imm = 0;
8493 9ee6e8bb pbrook
                        if (insn & (1 << 10)) {
8494 9ee6e8bb pbrook
                            if (insn & (1 << 7))
8495 9ee6e8bb pbrook
                                offset |= CPSR_A;
8496 9ee6e8bb pbrook
                            if (insn & (1 << 6))
8497 9ee6e8bb pbrook
                                offset |= CPSR_I;
8498 9ee6e8bb pbrook
                            if (insn & (1 << 5))
8499 9ee6e8bb pbrook
                                offset |= CPSR_F;
8500 9ee6e8bb pbrook
                            if (insn & (1 << 9))
8501 9ee6e8bb pbrook
                                imm = CPSR_A | CPSR_I | CPSR_F;
8502 9ee6e8bb pbrook
                        }
8503 9ee6e8bb pbrook
                        if (insn & (1 << 8)) {
8504 9ee6e8bb pbrook
                            offset |= 0x1f;
8505 9ee6e8bb pbrook
                            imm |= (insn & 0x1f);
8506 9ee6e8bb pbrook
                        }
8507 9ee6e8bb pbrook
                        if (offset) {
8508 2fbac54b Filip Navara
                            gen_set_psr_im(s, offset, 0, imm);
8509 9ee6e8bb pbrook
                        }
8510 9ee6e8bb pbrook
                        break;
8511 9ee6e8bb pbrook
                    case 3: /* Special control operations.  */
8512 426f5abc Paul Brook
                        ARCH(7);
8513 9ee6e8bb pbrook
                        op = (insn >> 4) & 0xf;
8514 9ee6e8bb pbrook
                        switch (op) {
8515 9ee6e8bb pbrook
                        case 2: /* clrex */
8516 426f5abc Paul Brook
                            gen_clrex(s);
8517 9ee6e8bb pbrook
                            break;
8518 9ee6e8bb pbrook
                        case 4: /* dsb */
8519 9ee6e8bb pbrook
                        case 5: /* dmb */
8520 9ee6e8bb pbrook
                        case 6: /* isb */
8521 9ee6e8bb pbrook
                            /* These execute as NOPs.  */
8522 9ee6e8bb pbrook
                            break;
8523 9ee6e8bb pbrook
                        default:
8524 9ee6e8bb pbrook
                            goto illegal_op;
8525 9ee6e8bb pbrook
                        }
8526 9ee6e8bb pbrook
                        break;
8527 9ee6e8bb pbrook
                    case 4: /* bxj */
8528 9ee6e8bb pbrook
                        /* Trivial implementation equivalent to bx.  */
8529 d9ba4830 pbrook
                        tmp = load_reg(s, rn);
8530 d9ba4830 pbrook
                        gen_bx(s, tmp);
8531 9ee6e8bb pbrook
                        break;
8532 9ee6e8bb pbrook
                    case 5: /* Exception return.  */
8533 b8b45b68 Rabin Vincent
                        if (IS_USER(s)) {
8534 b8b45b68 Rabin Vincent
                            goto illegal_op;
8535 b8b45b68 Rabin Vincent
                        }
8536 b8b45b68 Rabin Vincent
                        if (rn != 14 || rd != 15) {
8537 b8b45b68 Rabin Vincent
                            goto illegal_op;
8538 b8b45b68 Rabin Vincent
                        }
8539 b8b45b68 Rabin Vincent
                        tmp = load_reg(s, rn);
8540 b8b45b68 Rabin Vincent
                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8541 b8b45b68 Rabin Vincent
                        gen_exception_return(s, tmp);
8542 b8b45b68 Rabin Vincent
                        break;
8543 9ee6e8bb pbrook
                    case 6: /* mrs cpsr.  */
8544 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
8545 9ee6e8bb pbrook
                        if (IS_M(env)) {
8546 8984bd2e pbrook
                            addr = tcg_const_i32(insn & 0xff);
8547 8984bd2e pbrook
                            gen_helper_v7m_mrs(tmp, cpu_env, addr);
8548 b75263d6 Juha Riihimäki
                            tcg_temp_free_i32(addr);
8549 9ee6e8bb pbrook
                        } else {
8550 8984bd2e pbrook
                            gen_helper_cpsr_read(tmp);
8551 9ee6e8bb pbrook
                        }
8552 8984bd2e pbrook
                        store_reg(s, rd, tmp);
8553 9ee6e8bb pbrook
                        break;
8554 9ee6e8bb pbrook
                    case 7: /* mrs spsr.  */
8555 9ee6e8bb pbrook
                        /* Not accessible in user mode.  */
8556 9ee6e8bb pbrook
                        if (IS_USER(s) || IS_M(env))
8557 9ee6e8bb pbrook
                            goto illegal_op;
8558 d9ba4830 pbrook
                        tmp = load_cpu_field(spsr);
8559 d9ba4830 pbrook
                        store_reg(s, rd, tmp);
8560 9ee6e8bb pbrook
                        break;
8561 2c0262af bellard
                    }
8562 2c0262af bellard
                }
8563 9ee6e8bb pbrook
            } else {
8564 9ee6e8bb pbrook
                /* Conditional branch.  */
8565 9ee6e8bb pbrook
                op = (insn >> 22) & 0xf;
8566 9ee6e8bb pbrook
                /* Generate a conditional jump to next instruction.  */
8567 9ee6e8bb pbrook
                s->condlabel = gen_new_label();
8568 d9ba4830 pbrook
                gen_test_cc(op ^ 1, s->condlabel);
8569 9ee6e8bb pbrook
                s->condjmp = 1;
8570 9ee6e8bb pbrook
8571 9ee6e8bb pbrook
                /* offset[11:1] = insn[10:0] */
8572 9ee6e8bb pbrook
                offset = (insn & 0x7ff) << 1;
8573 9ee6e8bb pbrook
                /* offset[17:12] = insn[21:16].  */
8574 9ee6e8bb pbrook
                offset |= (insn & 0x003f0000) >> 4;
8575 9ee6e8bb pbrook
                /* offset[31:20] = insn[26].  */
8576 9ee6e8bb pbrook
                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8577 9ee6e8bb pbrook
                /* offset[18] = insn[13].  */
8578 9ee6e8bb pbrook
                offset |= (insn & (1 << 13)) << 5;
8579 9ee6e8bb pbrook
                /* offset[19] = insn[11].  */
8580 9ee6e8bb pbrook
                offset |= (insn & (1 << 11)) << 8;
8581 9ee6e8bb pbrook
8582 9ee6e8bb pbrook
                /* jump to the offset */
8583 b0109805 pbrook
                gen_jmp(s, s->pc + offset);
8584 9ee6e8bb pbrook
            }
8585 9ee6e8bb pbrook
        } else {
8586 9ee6e8bb pbrook
            /* Data processing immediate.  */
8587 9ee6e8bb pbrook
            if (insn & (1 << 25)) {
8588 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
8589 9ee6e8bb pbrook
                    if (insn & (1 << 20))
8590 9ee6e8bb pbrook
                        goto illegal_op;
8591 9ee6e8bb pbrook
                    /* Bitfield/Saturate.  */
8592 9ee6e8bb pbrook
                    op = (insn >> 21) & 7;
8593 9ee6e8bb pbrook
                    imm = insn & 0x1f;
8594 9ee6e8bb pbrook
                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8595 6ddbc6e4 pbrook
                    if (rn == 15) {
8596 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
8597 6ddbc6e4 pbrook
                        tcg_gen_movi_i32(tmp, 0);
8598 6ddbc6e4 pbrook
                    } else {
8599 6ddbc6e4 pbrook
                        tmp = load_reg(s, rn);
8600 6ddbc6e4 pbrook
                    }
8601 9ee6e8bb pbrook
                    switch (op) {
8602 9ee6e8bb pbrook
                    case 2: /* Signed bitfield extract.  */
8603 9ee6e8bb pbrook
                        imm++;
8604 9ee6e8bb pbrook
                        if (shift + imm > 32)
8605 9ee6e8bb pbrook
                            goto illegal_op;
8606 9ee6e8bb pbrook
                        if (imm < 32)
8607 6ddbc6e4 pbrook
                            gen_sbfx(tmp, shift, imm);
8608 9ee6e8bb pbrook
                        break;
8609 9ee6e8bb pbrook
                    case 6: /* Unsigned bitfield extract.  */
8610 9ee6e8bb pbrook
                        imm++;
8611 9ee6e8bb pbrook
                        if (shift + imm > 32)
8612 9ee6e8bb pbrook
                            goto illegal_op;
8613 9ee6e8bb pbrook
                        if (imm < 32)
8614 6ddbc6e4 pbrook
                            gen_ubfx(tmp, shift, (1u << imm) - 1);
8615 9ee6e8bb pbrook
                        break;
8616 9ee6e8bb pbrook
                    case 3: /* Bitfield insert/clear.  */
8617 9ee6e8bb pbrook
                        if (imm < shift)
8618 9ee6e8bb pbrook
                            goto illegal_op;
8619 9ee6e8bb pbrook
                        imm = imm + 1 - shift;
8620 9ee6e8bb pbrook
                        if (imm != 32) {
8621 6ddbc6e4 pbrook
                            tmp2 = load_reg(s, rd);
8622 8f8e3aa4 pbrook
                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8623 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
8624 9ee6e8bb pbrook
                        }
8625 9ee6e8bb pbrook
                        break;
8626 9ee6e8bb pbrook
                    case 7:
8627 9ee6e8bb pbrook
                        goto illegal_op;
8628 9ee6e8bb pbrook
                    default: /* Saturate.  */
8629 9ee6e8bb pbrook
                        if (shift) {
8630 9ee6e8bb pbrook
                            if (op & 1)
8631 6ddbc6e4 pbrook
                                tcg_gen_sari_i32(tmp, tmp, shift);
8632 9ee6e8bb pbrook
                            else
8633 6ddbc6e4 pbrook
                                tcg_gen_shli_i32(tmp, tmp, shift);
8634 9ee6e8bb pbrook
                        }
8635 6ddbc6e4 pbrook
                        tmp2 = tcg_const_i32(imm);
8636 9ee6e8bb pbrook
                        if (op & 4) {
8637 9ee6e8bb pbrook
                            /* Unsigned.  */
8638 9ee6e8bb pbrook
                            if ((op & 1) && shift == 0)
8639 6ddbc6e4 pbrook
                                gen_helper_usat16(tmp, tmp, tmp2);
8640 9ee6e8bb pbrook
                            else
8641 6ddbc6e4 pbrook
                                gen_helper_usat(tmp, tmp, tmp2);
8642 2c0262af bellard
                        } else {
8643 9ee6e8bb pbrook
                            /* Signed.  */
8644 9ee6e8bb pbrook
                            if ((op & 1) && shift == 0)
8645 6ddbc6e4 pbrook
                                gen_helper_ssat16(tmp, tmp, tmp2);
8646 9ee6e8bb pbrook
                            else
8647 6ddbc6e4 pbrook
                                gen_helper_ssat(tmp, tmp, tmp2);
8648 2c0262af bellard
                        }
8649 b75263d6 Juha Riihimäki
                        tcg_temp_free_i32(tmp2);
8650 9ee6e8bb pbrook
                        break;
8651 2c0262af bellard
                    }
8652 6ddbc6e4 pbrook
                    store_reg(s, rd, tmp);
8653 9ee6e8bb pbrook
                } else {
8654 9ee6e8bb pbrook
                    imm = ((insn & 0x04000000) >> 15)
8655 9ee6e8bb pbrook
                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
8656 9ee6e8bb pbrook
                    if (insn & (1 << 22)) {
8657 9ee6e8bb pbrook
                        /* 16-bit immediate.  */
8658 9ee6e8bb pbrook
                        imm |= (insn >> 4) & 0xf000;
8659 9ee6e8bb pbrook
                        if (insn & (1 << 23)) {
8660 9ee6e8bb pbrook
                            /* movt */
8661 5e3f878a pbrook
                            tmp = load_reg(s, rd);
8662 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp, tmp);
8663 5e3f878a pbrook
                            tcg_gen_ori_i32(tmp, tmp, imm << 16);
8664 2c0262af bellard
                        } else {
8665 9ee6e8bb pbrook
                            /* movw */
8666 7d1b0095 Peter Maydell
                            tmp = tcg_temp_new_i32();
8667 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, imm);
8668 2c0262af bellard
                        }
8669 2c0262af bellard
                    } else {
8670 9ee6e8bb pbrook
                        /* Add/sub 12-bit immediate.  */
8671 9ee6e8bb pbrook
                        if (rn == 15) {
8672 b0109805 pbrook
                            offset = s->pc & ~(uint32_t)3;
8673 9ee6e8bb pbrook
                            if (insn & (1 << 23))
8674 b0109805 pbrook
                                offset -= imm;
8675 9ee6e8bb pbrook
                            else
8676 b0109805 pbrook
                                offset += imm;
8677 7d1b0095 Peter Maydell
                            tmp = tcg_temp_new_i32();
8678 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, offset);
8679 2c0262af bellard
                        } else {
8680 5e3f878a pbrook
                            tmp = load_reg(s, rn);
8681 9ee6e8bb pbrook
                            if (insn & (1 << 23))
8682 5e3f878a pbrook
                                tcg_gen_subi_i32(tmp, tmp, imm);
8683 9ee6e8bb pbrook
                            else
8684 5e3f878a pbrook
                                tcg_gen_addi_i32(tmp, tmp, imm);
8685 2c0262af bellard
                        }
8686 9ee6e8bb pbrook
                    }
8687 5e3f878a pbrook
                    store_reg(s, rd, tmp);
8688 191abaa2 pbrook
                }
8689 9ee6e8bb pbrook
            } else {
8690 9ee6e8bb pbrook
                int shifter_out = 0;
8691 9ee6e8bb pbrook
                /* modified 12-bit immediate.  */
8692 9ee6e8bb pbrook
                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8693 9ee6e8bb pbrook
                imm = (insn & 0xff);
8694 9ee6e8bb pbrook
                switch (shift) {
8695 9ee6e8bb pbrook
                case 0: /* XY */
8696 9ee6e8bb pbrook
                    /* Nothing to do.  */
8697 9ee6e8bb pbrook
                    break;
8698 9ee6e8bb pbrook
                case 1: /* 00XY00XY */
8699 9ee6e8bb pbrook
                    imm |= imm << 16;
8700 9ee6e8bb pbrook
                    break;
8701 9ee6e8bb pbrook
                case 2: /* XY00XY00 */
8702 9ee6e8bb pbrook
                    imm |= imm << 16;
8703 9ee6e8bb pbrook
                    imm <<= 8;
8704 9ee6e8bb pbrook
                    break;
8705 9ee6e8bb pbrook
                case 3: /* XYXYXYXY */
8706 9ee6e8bb pbrook
                    imm |= imm << 16;
8707 9ee6e8bb pbrook
                    imm |= imm << 8;
8708 9ee6e8bb pbrook
                    break;
8709 9ee6e8bb pbrook
                default: /* Rotated constant.  */
8710 9ee6e8bb pbrook
                    shift = (shift << 1) | (imm >> 7);
8711 9ee6e8bb pbrook
                    imm |= 0x80;
8712 9ee6e8bb pbrook
                    imm = imm << (32 - shift);
8713 9ee6e8bb pbrook
                    shifter_out = 1;
8714 9ee6e8bb pbrook
                    break;
8715 b5ff1b31 bellard
                }
8716 7d1b0095 Peter Maydell
                tmp2 = tcg_temp_new_i32();
8717 3174f8e9 Filip Navara
                tcg_gen_movi_i32(tmp2, imm);
8718 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
8719 3174f8e9 Filip Navara
                if (rn == 15) {
8720 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
8721 3174f8e9 Filip Navara
                    tcg_gen_movi_i32(tmp, 0);
8722 3174f8e9 Filip Navara
                } else {
8723 3174f8e9 Filip Navara
                    tmp = load_reg(s, rn);
8724 3174f8e9 Filip Navara
                }
8725 9ee6e8bb pbrook
                op = (insn >> 21) & 0xf;
8726 9ee6e8bb pbrook
                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8727 3174f8e9 Filip Navara
                                       shifter_out, tmp, tmp2))
8728 9ee6e8bb pbrook
                    goto illegal_op;
8729 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8730 9ee6e8bb pbrook
                rd = (insn >> 8) & 0xf;
8731 9ee6e8bb pbrook
                if (rd != 15) {
8732 3174f8e9 Filip Navara
                    store_reg(s, rd, tmp);
8733 3174f8e9 Filip Navara
                } else {
8734 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
8735 2c0262af bellard
                }
8736 2c0262af bellard
            }
8737 9ee6e8bb pbrook
        }
8738 9ee6e8bb pbrook
        break;
8739 9ee6e8bb pbrook
    case 12: /* Load/store single data item.  */
8740 9ee6e8bb pbrook
        {
8741 9ee6e8bb pbrook
        int postinc = 0;
8742 9ee6e8bb pbrook
        int writeback = 0;
8743 b0109805 pbrook
        int user;
8744 9ee6e8bb pbrook
        if ((insn & 0x01100000) == 0x01000000) {
8745 9ee6e8bb pbrook
            if (disas_neon_ls_insn(env, s, insn))
8746 c1713132 balrog
                goto illegal_op;
8747 9ee6e8bb pbrook
            break;
8748 9ee6e8bb pbrook
        }
8749 a2fdc890 Peter Maydell
        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8750 a2fdc890 Peter Maydell
        if (rs == 15) {
8751 a2fdc890 Peter Maydell
            if (!(insn & (1 << 20))) {
8752 a2fdc890 Peter Maydell
                goto illegal_op;
8753 a2fdc890 Peter Maydell
            }
8754 a2fdc890 Peter Maydell
            if (op != 2) {
8755 a2fdc890 Peter Maydell
                /* Byte or halfword load space with dest == r15 : memory hints.
8756 a2fdc890 Peter Maydell
                 * Catch them early so we don't emit pointless addressing code.
8757 a2fdc890 Peter Maydell
                 * This space is a mix of:
8758 a2fdc890 Peter Maydell
                 *  PLD/PLDW/PLI,  which we implement as NOPs (note that unlike
8759 a2fdc890 Peter Maydell
                 *     the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8760 a2fdc890 Peter Maydell
                 *     cores)
8761 a2fdc890 Peter Maydell
                 *  unallocated hints, which must be treated as NOPs
8762 a2fdc890 Peter Maydell
                 *  UNPREDICTABLE space, which we NOP or UNDEF depending on
8763 a2fdc890 Peter Maydell
                 *     which is easiest for the decoding logic
8764 a2fdc890 Peter Maydell
                 *  Some space which must UNDEF
8765 a2fdc890 Peter Maydell
                 */
8766 a2fdc890 Peter Maydell
                int op1 = (insn >> 23) & 3;
8767 a2fdc890 Peter Maydell
                int op2 = (insn >> 6) & 0x3f;
8768 a2fdc890 Peter Maydell
                if (op & 2) {
8769 a2fdc890 Peter Maydell
                    goto illegal_op;
8770 a2fdc890 Peter Maydell
                }
8771 a2fdc890 Peter Maydell
                if (rn == 15) {
8772 a2fdc890 Peter Maydell
                    /* UNPREDICTABLE or unallocated hint */
8773 a2fdc890 Peter Maydell
                    return 0;
8774 a2fdc890 Peter Maydell
                }
8775 a2fdc890 Peter Maydell
                if (op1 & 1) {
8776 a2fdc890 Peter Maydell
                    return 0; /* PLD* or unallocated hint */
8777 a2fdc890 Peter Maydell
                }
8778 a2fdc890 Peter Maydell
                if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8779 a2fdc890 Peter Maydell
                    return 0; /* PLD* or unallocated hint */
8780 a2fdc890 Peter Maydell
                }
8781 a2fdc890 Peter Maydell
                /* UNDEF space, or an UNPREDICTABLE */
8782 a2fdc890 Peter Maydell
                return 1;
8783 a2fdc890 Peter Maydell
            }
8784 a2fdc890 Peter Maydell
        }
8785 b0109805 pbrook
        user = IS_USER(s);
8786 9ee6e8bb pbrook
        if (rn == 15) {
8787 7d1b0095 Peter Maydell
            addr = tcg_temp_new_i32();
8788 9ee6e8bb pbrook
            /* PC relative.  */
8789 9ee6e8bb pbrook
            /* s->pc has already been incremented by 4.  */
8790 9ee6e8bb pbrook
            imm = s->pc & 0xfffffffc;
8791 9ee6e8bb pbrook
            if (insn & (1 << 23))
8792 9ee6e8bb pbrook
                imm += insn & 0xfff;
8793 9ee6e8bb pbrook
            else
8794 9ee6e8bb pbrook
                imm -= insn & 0xfff;
8795 b0109805 pbrook
            tcg_gen_movi_i32(addr, imm);
8796 9ee6e8bb pbrook
        } else {
8797 b0109805 pbrook
            addr = load_reg(s, rn);
8798 9ee6e8bb pbrook
            if (insn & (1 << 23)) {
8799 9ee6e8bb pbrook
                /* Positive offset.  */
8800 9ee6e8bb pbrook
                imm = insn & 0xfff;
8801 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, imm);
8802 9ee6e8bb pbrook
            } else {
8803 9ee6e8bb pbrook
                imm = insn & 0xff;
8804 2a0308c5 Peter Maydell
                switch ((insn >> 8) & 0xf) {
8805 2a0308c5 Peter Maydell
                case 0x0: /* Shifted Register.  */
8806 9ee6e8bb pbrook
                    shift = (insn >> 4) & 0xf;
8807 2a0308c5 Peter Maydell
                    if (shift > 3) {
8808 2a0308c5 Peter Maydell
                        tcg_temp_free_i32(addr);
8809 18c9b560 balrog
                        goto illegal_op;
8810 2a0308c5 Peter Maydell
                    }
8811 b26eefb6 pbrook
                    tmp = load_reg(s, rm);
8812 9ee6e8bb pbrook
                    if (shift)
8813 b26eefb6 pbrook
                        tcg_gen_shli_i32(tmp, tmp, shift);
8814 b0109805 pbrook
                    tcg_gen_add_i32(addr, addr, tmp);
8815 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
8816 9ee6e8bb pbrook
                    break;
8817 2a0308c5 Peter Maydell
                case 0xc: /* Negative offset.  */
8818 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, -imm);
8819 9ee6e8bb pbrook
                    break;
8820 2a0308c5 Peter Maydell
                case 0xe: /* User privilege.  */
8821 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, imm);
8822 b0109805 pbrook
                    user = 1;
8823 9ee6e8bb pbrook
                    break;
8824 2a0308c5 Peter Maydell
                case 0x9: /* Post-decrement.  */
8825 9ee6e8bb pbrook
                    imm = -imm;
8826 9ee6e8bb pbrook
                    /* Fall through.  */
8827 2a0308c5 Peter Maydell
                case 0xb: /* Post-increment.  */
8828 9ee6e8bb pbrook
                    postinc = 1;
8829 9ee6e8bb pbrook
                    writeback = 1;
8830 9ee6e8bb pbrook
                    break;
8831 2a0308c5 Peter Maydell
                case 0xd: /* Pre-decrement.  */
8832 9ee6e8bb pbrook
                    imm = -imm;
8833 9ee6e8bb pbrook
                    /* Fall through.  */
8834 2a0308c5 Peter Maydell
                case 0xf: /* Pre-increment.  */
8835 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, imm);
8836 9ee6e8bb pbrook
                    writeback = 1;
8837 9ee6e8bb pbrook
                    break;
8838 9ee6e8bb pbrook
                default:
8839 2a0308c5 Peter Maydell
                    tcg_temp_free_i32(addr);
8840 b7bcbe95 bellard
                    goto illegal_op;
8841 9ee6e8bb pbrook
                }
8842 9ee6e8bb pbrook
            }
8843 9ee6e8bb pbrook
        }
8844 9ee6e8bb pbrook
        if (insn & (1 << 20)) {
8845 9ee6e8bb pbrook
            /* Load.  */
8846 a2fdc890 Peter Maydell
            switch (op) {
8847 a2fdc890 Peter Maydell
            case 0: tmp = gen_ld8u(addr, user); break;
8848 a2fdc890 Peter Maydell
            case 4: tmp = gen_ld8s(addr, user); break;
8849 a2fdc890 Peter Maydell
            case 1: tmp = gen_ld16u(addr, user); break;
8850 a2fdc890 Peter Maydell
            case 5: tmp = gen_ld16s(addr, user); break;
8851 a2fdc890 Peter Maydell
            case 2: tmp = gen_ld32(addr, user); break;
8852 2a0308c5 Peter Maydell
            default:
8853 2a0308c5 Peter Maydell
                tcg_temp_free_i32(addr);
8854 2a0308c5 Peter Maydell
                goto illegal_op;
8855 a2fdc890 Peter Maydell
            }
8856 a2fdc890 Peter Maydell
            if (rs == 15) {
8857 a2fdc890 Peter Maydell
                gen_bx(s, tmp);
8858 9ee6e8bb pbrook
            } else {
8859 a2fdc890 Peter Maydell
                store_reg(s, rs, tmp);
8860 9ee6e8bb pbrook
            }
8861 9ee6e8bb pbrook
        } else {
8862 9ee6e8bb pbrook
            /* Store.  */
8863 b0109805 pbrook
            tmp = load_reg(s, rs);
8864 9ee6e8bb pbrook
            switch (op) {
8865 b0109805 pbrook
            case 0: gen_st8(tmp, addr, user); break;
8866 b0109805 pbrook
            case 1: gen_st16(tmp, addr, user); break;
8867 b0109805 pbrook
            case 2: gen_st32(tmp, addr, user); break;
8868 2a0308c5 Peter Maydell
            default:
8869 2a0308c5 Peter Maydell
                tcg_temp_free_i32(addr);
8870 2a0308c5 Peter Maydell
                goto illegal_op;
8871 b7bcbe95 bellard
            }
8872 2c0262af bellard
        }
8873 9ee6e8bb pbrook
        if (postinc)
8874 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, imm);
8875 b0109805 pbrook
        if (writeback) {
8876 b0109805 pbrook
            store_reg(s, rn, addr);
8877 b0109805 pbrook
        } else {
8878 7d1b0095 Peter Maydell
            tcg_temp_free_i32(addr);
8879 b0109805 pbrook
        }
8880 9ee6e8bb pbrook
        }
8881 9ee6e8bb pbrook
        break;
8882 9ee6e8bb pbrook
    default:
8883 9ee6e8bb pbrook
        goto illegal_op;
8884 2c0262af bellard
    }
8885 9ee6e8bb pbrook
    return 0;
8886 9ee6e8bb pbrook
illegal_op:
8887 9ee6e8bb pbrook
    return 1;
8888 2c0262af bellard
}
8889 2c0262af bellard
8890 9ee6e8bb pbrook
static void disas_thumb_insn(CPUState *env, DisasContext *s)
8891 99c475ab bellard
{
8892 99c475ab bellard
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
8893 99c475ab bellard
    int32_t offset;
8894 99c475ab bellard
    int i;
8895 b26eefb6 pbrook
    TCGv tmp;
8896 d9ba4830 pbrook
    TCGv tmp2;
8897 b0109805 pbrook
    TCGv addr;
8898 99c475ab bellard
8899 9ee6e8bb pbrook
    if (s->condexec_mask) {
8900 9ee6e8bb pbrook
        cond = s->condexec_cond;
8901 bedd2912 Johan Bengtsson
        if (cond != 0x0e) {     /* Skip conditional when condition is AL. */
8902 bedd2912 Johan Bengtsson
          s->condlabel = gen_new_label();
8903 bedd2912 Johan Bengtsson
          gen_test_cc(cond ^ 1, s->condlabel);
8904 bedd2912 Johan Bengtsson
          s->condjmp = 1;
8905 bedd2912 Johan Bengtsson
        }
8906 9ee6e8bb pbrook
    }
8907 9ee6e8bb pbrook
8908 b5ff1b31 bellard
    insn = lduw_code(s->pc);
8909 99c475ab bellard
    s->pc += 2;
8910 b5ff1b31 bellard
8911 99c475ab bellard
    switch (insn >> 12) {
8912 99c475ab bellard
    case 0: case 1:
8913 396e467c Filip Navara
8914 99c475ab bellard
        rd = insn & 7;
8915 99c475ab bellard
        op = (insn >> 11) & 3;
8916 99c475ab bellard
        if (op == 3) {
8917 99c475ab bellard
            /* add/subtract */
8918 99c475ab bellard
            rn = (insn >> 3) & 7;
8919 396e467c Filip Navara
            tmp = load_reg(s, rn);
8920 99c475ab bellard
            if (insn & (1 << 10)) {
8921 99c475ab bellard
                /* immediate */
8922 7d1b0095 Peter Maydell
                tmp2 = tcg_temp_new_i32();
8923 396e467c Filip Navara
                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8924 99c475ab bellard
            } else {
8925 99c475ab bellard
                /* reg */
8926 99c475ab bellard
                rm = (insn >> 6) & 7;
8927 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
8928 99c475ab bellard
            }
8929 9ee6e8bb pbrook
            if (insn & (1 << 9)) {
8930 9ee6e8bb pbrook
                if (s->condexec_mask)
8931 396e467c Filip Navara
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8932 9ee6e8bb pbrook
                else
8933 396e467c Filip Navara
                    gen_helper_sub_cc(tmp, tmp, tmp2);
8934 9ee6e8bb pbrook
            } else {
8935 9ee6e8bb pbrook
                if (s->condexec_mask)
8936 396e467c Filip Navara
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8937 9ee6e8bb pbrook
                else
8938 396e467c Filip Navara
                    gen_helper_add_cc(tmp, tmp, tmp2);
8939 9ee6e8bb pbrook
            }
8940 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
8941 396e467c Filip Navara
            store_reg(s, rd, tmp);
8942 99c475ab bellard
        } else {
8943 99c475ab bellard
            /* shift immediate */
8944 99c475ab bellard
            rm = (insn >> 3) & 7;
8945 99c475ab bellard
            shift = (insn >> 6) & 0x1f;
8946 9a119ff6 pbrook
            tmp = load_reg(s, rm);
8947 9a119ff6 pbrook
            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8948 9a119ff6 pbrook
            if (!s->condexec_mask)
8949 9a119ff6 pbrook
                gen_logic_CC(tmp);
8950 9a119ff6 pbrook
            store_reg(s, rd, tmp);
8951 99c475ab bellard
        }
8952 99c475ab bellard
        break;
8953 99c475ab bellard
    case 2: case 3:
8954 99c475ab bellard
        /* arithmetic large immediate */
8955 99c475ab bellard
        op = (insn >> 11) & 3;
8956 99c475ab bellard
        rd = (insn >> 8) & 0x7;
8957 396e467c Filip Navara
        if (op == 0) { /* mov */
8958 7d1b0095 Peter Maydell
            tmp = tcg_temp_new_i32();
8959 396e467c Filip Navara
            tcg_gen_movi_i32(tmp, insn & 0xff);
8960 9ee6e8bb pbrook
            if (!s->condexec_mask)
8961 396e467c Filip Navara
                gen_logic_CC(tmp);
8962 396e467c Filip Navara
            store_reg(s, rd, tmp);
8963 396e467c Filip Navara
        } else {
8964 396e467c Filip Navara
            tmp = load_reg(s, rd);
8965 7d1b0095 Peter Maydell
            tmp2 = tcg_temp_new_i32();
8966 396e467c Filip Navara
            tcg_gen_movi_i32(tmp2, insn & 0xff);
8967 396e467c Filip Navara
            switch (op) {
8968 396e467c Filip Navara
            case 1: /* cmp */
8969 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
8970 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
8971 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8972 396e467c Filip Navara
                break;
8973 396e467c Filip Navara
            case 2: /* add */
8974 396e467c Filip Navara
                if (s->condexec_mask)
8975 396e467c Filip Navara
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8976 396e467c Filip Navara
                else
8977 396e467c Filip Navara
                    gen_helper_add_cc(tmp, tmp, tmp2);
8978 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8979 396e467c Filip Navara
                store_reg(s, rd, tmp);
8980 396e467c Filip Navara
                break;
8981 396e467c Filip Navara
            case 3: /* sub */
8982 396e467c Filip Navara
                if (s->condexec_mask)
8983 396e467c Filip Navara
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8984 396e467c Filip Navara
                else
8985 396e467c Filip Navara
                    gen_helper_sub_cc(tmp, tmp, tmp2);
8986 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
8987 396e467c Filip Navara
                store_reg(s, rd, tmp);
8988 396e467c Filip Navara
                break;
8989 396e467c Filip Navara
            }
8990 99c475ab bellard
        }
8991 99c475ab bellard
        break;
8992 99c475ab bellard
    case 4:
8993 99c475ab bellard
        if (insn & (1 << 11)) {
8994 99c475ab bellard
            rd = (insn >> 8) & 7;
8995 5899f386 bellard
            /* load pc-relative.  Bit 1 of PC is ignored.  */
8996 5899f386 bellard
            val = s->pc + 2 + ((insn & 0xff) * 4);
8997 5899f386 bellard
            val &= ~(uint32_t)2;
8998 7d1b0095 Peter Maydell
            addr = tcg_temp_new_i32();
8999 b0109805 pbrook
            tcg_gen_movi_i32(addr, val);
9000 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
9001 7d1b0095 Peter Maydell
            tcg_temp_free_i32(addr);
9002 b0109805 pbrook
            store_reg(s, rd, tmp);
9003 99c475ab bellard
            break;
9004 99c475ab bellard
        }
9005 99c475ab bellard
        if (insn & (1 << 10)) {
9006 99c475ab bellard
            /* data processing extended or blx */
9007 99c475ab bellard
            rd = (insn & 7) | ((insn >> 4) & 8);
9008 99c475ab bellard
            rm = (insn >> 3) & 0xf;
9009 99c475ab bellard
            op = (insn >> 8) & 3;
9010 99c475ab bellard
            switch (op) {
9011 99c475ab bellard
            case 0: /* add */
9012 396e467c Filip Navara
                tmp = load_reg(s, rd);
9013 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
9014 396e467c Filip Navara
                tcg_gen_add_i32(tmp, tmp, tmp2);
9015 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
9016 396e467c Filip Navara
                store_reg(s, rd, tmp);
9017 99c475ab bellard
                break;
9018 99c475ab bellard
            case 1: /* cmp */
9019 396e467c Filip Navara
                tmp = load_reg(s, rd);
9020 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
9021 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
9022 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
9023 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
9024 99c475ab bellard
                break;
9025 99c475ab bellard
            case 2: /* mov/cpy */
9026 396e467c Filip Navara
                tmp = load_reg(s, rm);
9027 396e467c Filip Navara
                store_reg(s, rd, tmp);
9028 99c475ab bellard
                break;
9029 99c475ab bellard
            case 3:/* branch [and link] exchange thumb register */
9030 b0109805 pbrook
                tmp = load_reg(s, rm);
9031 99c475ab bellard
                if (insn & (1 << 7)) {
9032 be5e7a76 Dmitry Eremin-Solenikov
                    ARCH(5);
9033 99c475ab bellard
                    val = (uint32_t)s->pc | 1;
9034 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
9035 b0109805 pbrook
                    tcg_gen_movi_i32(tmp2, val);
9036 b0109805 pbrook
                    store_reg(s, 14, tmp2);
9037 99c475ab bellard
                }
9038 be5e7a76 Dmitry Eremin-Solenikov
                /* already thumb, no need to check */
9039 d9ba4830 pbrook
                gen_bx(s, tmp);
9040 99c475ab bellard
                break;
9041 99c475ab bellard
            }
9042 99c475ab bellard
            break;
9043 99c475ab bellard
        }
9044 99c475ab bellard
9045 99c475ab bellard
        /* data processing register */
9046 99c475ab bellard
        rd = insn & 7;
9047 99c475ab bellard
        rm = (insn >> 3) & 7;
9048 99c475ab bellard
        op = (insn >> 6) & 0xf;
9049 99c475ab bellard
        if (op == 2 || op == 3 || op == 4 || op == 7) {
9050 99c475ab bellard
            /* the shift/rotate ops want the operands backwards */
9051 99c475ab bellard
            val = rm;
9052 99c475ab bellard
            rm = rd;
9053 99c475ab bellard
            rd = val;
9054 99c475ab bellard
            val = 1;
9055 99c475ab bellard
        } else {
9056 99c475ab bellard
            val = 0;
9057 99c475ab bellard
        }
9058 99c475ab bellard
9059 396e467c Filip Navara
        if (op == 9) { /* neg */
9060 7d1b0095 Peter Maydell
            tmp = tcg_temp_new_i32();
9061 396e467c Filip Navara
            tcg_gen_movi_i32(tmp, 0);
9062 396e467c Filip Navara
        } else if (op != 0xf) { /* mvn doesn't read its first operand */
9063 396e467c Filip Navara
            tmp = load_reg(s, rd);
9064 396e467c Filip Navara
        } else {
9065 396e467c Filip Navara
            TCGV_UNUSED(tmp);
9066 396e467c Filip Navara
        }
9067 99c475ab bellard
9068 396e467c Filip Navara
        tmp2 = load_reg(s, rm);
9069 5899f386 bellard
        switch (op) {
9070 99c475ab bellard
        case 0x0: /* and */
9071 396e467c Filip Navara
            tcg_gen_and_i32(tmp, tmp, tmp2);
9072 9ee6e8bb pbrook
            if (!s->condexec_mask)
9073 396e467c Filip Navara
                gen_logic_CC(tmp);
9074 99c475ab bellard
            break;
9075 99c475ab bellard
        case 0x1: /* eor */
9076 396e467c Filip Navara
            tcg_gen_xor_i32(tmp, tmp, tmp2);
9077 9ee6e8bb pbrook
            if (!s->condexec_mask)
9078 396e467c Filip Navara
                gen_logic_CC(tmp);
9079 99c475ab bellard
            break;
9080 99c475ab bellard
        case 0x2: /* lsl */
9081 9ee6e8bb pbrook
            if (s->condexec_mask) {
9082 396e467c Filip Navara
                gen_helper_shl(tmp2, tmp2, tmp);
9083 9ee6e8bb pbrook
            } else {
9084 396e467c Filip Navara
                gen_helper_shl_cc(tmp2, tmp2, tmp);
9085 396e467c Filip Navara
                gen_logic_CC(tmp2);
9086 9ee6e8bb pbrook
            }
9087 99c475ab bellard
            break;
9088 99c475ab bellard
        case 0x3: /* lsr */
9089 9ee6e8bb pbrook
            if (s->condexec_mask) {
9090 396e467c Filip Navara
                gen_helper_shr(tmp2, tmp2, tmp);
9091 9ee6e8bb pbrook
            } else {
9092 396e467c Filip Navara
                gen_helper_shr_cc(tmp2, tmp2, tmp);
9093 396e467c Filip Navara
                gen_logic_CC(tmp2);
9094 9ee6e8bb pbrook
            }
9095 99c475ab bellard
            break;
9096 99c475ab bellard
        case 0x4: /* asr */
9097 9ee6e8bb pbrook
            if (s->condexec_mask) {
9098 396e467c Filip Navara
                gen_helper_sar(tmp2, tmp2, tmp);
9099 9ee6e8bb pbrook
            } else {
9100 396e467c Filip Navara
                gen_helper_sar_cc(tmp2, tmp2, tmp);
9101 396e467c Filip Navara
                gen_logic_CC(tmp2);
9102 9ee6e8bb pbrook
            }
9103 99c475ab bellard
            break;
9104 99c475ab bellard
        case 0x5: /* adc */
9105 9ee6e8bb pbrook
            if (s->condexec_mask)
9106 396e467c Filip Navara
                gen_adc(tmp, tmp2);
9107 9ee6e8bb pbrook
            else
9108 396e467c Filip Navara
                gen_helper_adc_cc(tmp, tmp, tmp2);
9109 99c475ab bellard
            break;
9110 99c475ab bellard
        case 0x6: /* sbc */
9111 9ee6e8bb pbrook
            if (s->condexec_mask)
9112 396e467c Filip Navara
                gen_sub_carry(tmp, tmp, tmp2);
9113 9ee6e8bb pbrook
            else
9114 396e467c Filip Navara
                gen_helper_sbc_cc(tmp, tmp, tmp2);
9115 99c475ab bellard
            break;
9116 99c475ab bellard
        case 0x7: /* ror */
9117 9ee6e8bb pbrook
            if (s->condexec_mask) {
9118 f669df27 Aurelien Jarno
                tcg_gen_andi_i32(tmp, tmp, 0x1f);
9119 f669df27 Aurelien Jarno
                tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9120 9ee6e8bb pbrook
            } else {
9121 396e467c Filip Navara
                gen_helper_ror_cc(tmp2, tmp2, tmp);
9122 396e467c Filip Navara
                gen_logic_CC(tmp2);
9123 9ee6e8bb pbrook
            }
9124 99c475ab bellard
            break;
9125 99c475ab bellard
        case 0x8: /* tst */
9126 396e467c Filip Navara
            tcg_gen_and_i32(tmp, tmp, tmp2);
9127 396e467c Filip Navara
            gen_logic_CC(tmp);
9128 99c475ab bellard
            rd = 16;
9129 5899f386 bellard
            break;
9130 99c475ab bellard
        case 0x9: /* neg */
9131 9ee6e8bb pbrook
            if (s->condexec_mask)
9132 396e467c Filip Navara
                tcg_gen_neg_i32(tmp, tmp2);
9133 9ee6e8bb pbrook
            else
9134 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
9135 99c475ab bellard
            break;
9136 99c475ab bellard
        case 0xa: /* cmp */
9137 396e467c Filip Navara
            gen_helper_sub_cc(tmp, tmp, tmp2);
9138 99c475ab bellard
            rd = 16;
9139 99c475ab bellard
            break;
9140 99c475ab bellard
        case 0xb: /* cmn */
9141 396e467c Filip Navara
            gen_helper_add_cc(tmp, tmp, tmp2);
9142 99c475ab bellard
            rd = 16;
9143 99c475ab bellard
            break;
9144 99c475ab bellard
        case 0xc: /* orr */
9145 396e467c Filip Navara
            tcg_gen_or_i32(tmp, tmp, tmp2);
9146 9ee6e8bb pbrook
            if (!s->condexec_mask)
9147 396e467c Filip Navara
                gen_logic_CC(tmp);
9148 99c475ab bellard
            break;
9149 99c475ab bellard
        case 0xd: /* mul */
9150 7b2919a0 Juha.Riihimaki@nokia.com
            tcg_gen_mul_i32(tmp, tmp, tmp2);
9151 9ee6e8bb pbrook
            if (!s->condexec_mask)
9152 396e467c Filip Navara
                gen_logic_CC(tmp);
9153 99c475ab bellard
            break;
9154 99c475ab bellard
        case 0xe: /* bic */
9155 f669df27 Aurelien Jarno
            tcg_gen_andc_i32(tmp, tmp, tmp2);
9156 9ee6e8bb pbrook
            if (!s->condexec_mask)
9157 396e467c Filip Navara
                gen_logic_CC(tmp);
9158 99c475ab bellard
            break;
9159 99c475ab bellard
        case 0xf: /* mvn */
9160 396e467c Filip Navara
            tcg_gen_not_i32(tmp2, tmp2);
9161 9ee6e8bb pbrook
            if (!s->condexec_mask)
9162 396e467c Filip Navara
                gen_logic_CC(tmp2);
9163 99c475ab bellard
            val = 1;
9164 5899f386 bellard
            rm = rd;
9165 99c475ab bellard
            break;
9166 99c475ab bellard
        }
9167 99c475ab bellard
        if (rd != 16) {
9168 396e467c Filip Navara
            if (val) {
9169 396e467c Filip Navara
                store_reg(s, rm, tmp2);
9170 396e467c Filip Navara
                if (op != 0xf)
9171 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
9172 396e467c Filip Navara
            } else {
9173 396e467c Filip Navara
                store_reg(s, rd, tmp);
9174 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
9175 396e467c Filip Navara
            }
9176 396e467c Filip Navara
        } else {
9177 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
9178 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
9179 99c475ab bellard
        }
9180 99c475ab bellard
        break;
9181 99c475ab bellard
9182 99c475ab bellard
    case 5:
9183 99c475ab bellard
        /* load/store register offset.  */
9184 99c475ab bellard
        rd = insn & 7;
9185 99c475ab bellard
        rn = (insn >> 3) & 7;
9186 99c475ab bellard
        rm = (insn >> 6) & 7;
9187 99c475ab bellard
        op = (insn >> 9) & 7;
9188 b0109805 pbrook
        addr = load_reg(s, rn);
9189 b26eefb6 pbrook
        tmp = load_reg(s, rm);
9190 b0109805 pbrook
        tcg_gen_add_i32(addr, addr, tmp);
9191 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp);
9192 99c475ab bellard
9193 99c475ab bellard
        if (op < 3) /* store */
9194 b0109805 pbrook
            tmp = load_reg(s, rd);
9195 99c475ab bellard
9196 99c475ab bellard
        switch (op) {
9197 99c475ab bellard
        case 0: /* str */
9198 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
9199 99c475ab bellard
            break;
9200 99c475ab bellard
        case 1: /* strh */
9201 b0109805 pbrook
            gen_st16(tmp, addr, IS_USER(s));
9202 99c475ab bellard
            break;
9203 99c475ab bellard
        case 2: /* strb */
9204 b0109805 pbrook
            gen_st8(tmp, addr, IS_USER(s));
9205 99c475ab bellard
            break;
9206 99c475ab bellard
        case 3: /* ldrsb */
9207 b0109805 pbrook
            tmp = gen_ld8s(addr, IS_USER(s));
9208 99c475ab bellard
            break;
9209 99c475ab bellard
        case 4: /* ldr */
9210 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
9211 99c475ab bellard
            break;
9212 99c475ab bellard
        case 5: /* ldrh */
9213 b0109805 pbrook
            tmp = gen_ld16u(addr, IS_USER(s));
9214 99c475ab bellard
            break;
9215 99c475ab bellard
        case 6: /* ldrb */
9216 b0109805 pbrook
            tmp = gen_ld8u(addr, IS_USER(s));
9217 99c475ab bellard
            break;
9218 99c475ab bellard
        case 7: /* ldrsh */
9219 b0109805 pbrook
            tmp = gen_ld16s(addr, IS_USER(s));
9220 99c475ab bellard
            break;
9221 99c475ab bellard
        }
9222 99c475ab bellard
        if (op >= 3) /* load */
9223 b0109805 pbrook
            store_reg(s, rd, tmp);
9224 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
9225 99c475ab bellard
        break;
9226 99c475ab bellard
9227 99c475ab bellard
    case 6:
9228 99c475ab bellard
        /* load/store word immediate offset */
9229 99c475ab bellard
        rd = insn & 7;
9230 99c475ab bellard
        rn = (insn >> 3) & 7;
9231 b0109805 pbrook
        addr = load_reg(s, rn);
9232 99c475ab bellard
        val = (insn >> 4) & 0x7c;
9233 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
9234 99c475ab bellard
9235 99c475ab bellard
        if (insn & (1 << 11)) {
9236 99c475ab bellard
            /* load */
9237 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
9238 b0109805 pbrook
            store_reg(s, rd, tmp);
9239 99c475ab bellard
        } else {
9240 99c475ab bellard
            /* store */
9241 b0109805 pbrook
            tmp = load_reg(s, rd);
9242 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
9243 99c475ab bellard
        }
9244 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
9245 99c475ab bellard
        break;
9246 99c475ab bellard
9247 99c475ab bellard
    case 7:
9248 99c475ab bellard
        /* load/store byte immediate offset */
9249 99c475ab bellard
        rd = insn & 7;
9250 99c475ab bellard
        rn = (insn >> 3) & 7;
9251 b0109805 pbrook
        addr = load_reg(s, rn);
9252 99c475ab bellard
        val = (insn >> 6) & 0x1f;
9253 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
9254 99c475ab bellard
9255 99c475ab bellard
        if (insn & (1 << 11)) {
9256 99c475ab bellard
            /* load */
9257 b0109805 pbrook
            tmp = gen_ld8u(addr, IS_USER(s));
9258 b0109805 pbrook
            store_reg(s, rd, tmp);
9259 99c475ab bellard
        } else {
9260 99c475ab bellard
            /* store */
9261 b0109805 pbrook
            tmp = load_reg(s, rd);
9262 b0109805 pbrook
            gen_st8(tmp, addr, IS_USER(s));
9263 99c475ab bellard
        }
9264 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
9265 99c475ab bellard
        break;
9266 99c475ab bellard
9267 99c475ab bellard
    case 8:
9268 99c475ab bellard
        /* load/store halfword immediate offset */
9269 99c475ab bellard
        rd = insn & 7;
9270 99c475ab bellard
        rn = (insn >> 3) & 7;
9271 b0109805 pbrook
        addr = load_reg(s, rn);
9272 99c475ab bellard
        val = (insn >> 5) & 0x3e;
9273 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
9274 99c475ab bellard
9275 99c475ab bellard
        if (insn & (1 << 11)) {
9276 99c475ab bellard
            /* load */
9277 b0109805 pbrook
            tmp = gen_ld16u(addr, IS_USER(s));
9278 b0109805 pbrook
            store_reg(s, rd, tmp);
9279 99c475ab bellard
        } else {
9280 99c475ab bellard
            /* store */
9281 b0109805 pbrook
            tmp = load_reg(s, rd);
9282 b0109805 pbrook
            gen_st16(tmp, addr, IS_USER(s));
9283 99c475ab bellard
        }
9284 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
9285 99c475ab bellard
        break;
9286 99c475ab bellard
9287 99c475ab bellard
    case 9:
9288 99c475ab bellard
        /* load/store from stack */
9289 99c475ab bellard
        rd = (insn >> 8) & 7;
9290 b0109805 pbrook
        addr = load_reg(s, 13);
9291 99c475ab bellard
        val = (insn & 0xff) * 4;
9292 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
9293 99c475ab bellard
9294 99c475ab bellard
        if (insn & (1 << 11)) {
9295 99c475ab bellard
            /* load */
9296 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
9297 b0109805 pbrook
            store_reg(s, rd, tmp);
9298 99c475ab bellard
        } else {
9299 99c475ab bellard
            /* store */
9300 b0109805 pbrook
            tmp = load_reg(s, rd);
9301 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
9302 99c475ab bellard
        }
9303 7d1b0095 Peter Maydell
        tcg_temp_free_i32(addr);
9304 99c475ab bellard
        break;
9305 99c475ab bellard
9306 99c475ab bellard
    case 10:
9307 99c475ab bellard
        /* add to high reg */
9308 99c475ab bellard
        rd = (insn >> 8) & 7;
9309 5899f386 bellard
        if (insn & (1 << 11)) {
9310 5899f386 bellard
            /* SP */
9311 5e3f878a pbrook
            tmp = load_reg(s, 13);
9312 5899f386 bellard
        } else {
9313 5899f386 bellard
            /* PC. bit 1 is ignored.  */
9314 7d1b0095 Peter Maydell
            tmp = tcg_temp_new_i32();
9315 5e3f878a pbrook
            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9316 5899f386 bellard
        }
9317 99c475ab bellard
        val = (insn & 0xff) * 4;
9318 5e3f878a pbrook
        tcg_gen_addi_i32(tmp, tmp, val);
9319 5e3f878a pbrook
        store_reg(s, rd, tmp);
9320 99c475ab bellard
        break;
9321 99c475ab bellard
9322 99c475ab bellard
    case 11:
9323 99c475ab bellard
        /* misc */
9324 99c475ab bellard
        op = (insn >> 8) & 0xf;
9325 99c475ab bellard
        switch (op) {
9326 99c475ab bellard
        case 0:
9327 99c475ab bellard
            /* adjust stack pointer */
9328 b26eefb6 pbrook
            tmp = load_reg(s, 13);
9329 99c475ab bellard
            val = (insn & 0x7f) * 4;
9330 99c475ab bellard
            if (insn & (1 << 7))
9331 6a0d8a1d balrog
                val = -(int32_t)val;
9332 b26eefb6 pbrook
            tcg_gen_addi_i32(tmp, tmp, val);
9333 b26eefb6 pbrook
            store_reg(s, 13, tmp);
9334 99c475ab bellard
            break;
9335 99c475ab bellard
9336 9ee6e8bb pbrook
        case 2: /* sign/zero extend.  */
9337 9ee6e8bb pbrook
            ARCH(6);
9338 9ee6e8bb pbrook
            rd = insn & 7;
9339 9ee6e8bb pbrook
            rm = (insn >> 3) & 7;
9340 b0109805 pbrook
            tmp = load_reg(s, rm);
9341 9ee6e8bb pbrook
            switch ((insn >> 6) & 3) {
9342 b0109805 pbrook
            case 0: gen_sxth(tmp); break;
9343 b0109805 pbrook
            case 1: gen_sxtb(tmp); break;
9344 b0109805 pbrook
            case 2: gen_uxth(tmp); break;
9345 b0109805 pbrook
            case 3: gen_uxtb(tmp); break;
9346 9ee6e8bb pbrook
            }
9347 b0109805 pbrook
            store_reg(s, rd, tmp);
9348 9ee6e8bb pbrook
            break;
9349 99c475ab bellard
        case 4: case 5: case 0xc: case 0xd:
9350 99c475ab bellard
            /* push/pop */
9351 b0109805 pbrook
            addr = load_reg(s, 13);
9352 5899f386 bellard
            if (insn & (1 << 8))
9353 5899f386 bellard
                offset = 4;
9354 99c475ab bellard
            else
9355 5899f386 bellard
                offset = 0;
9356 5899f386 bellard
            for (i = 0; i < 8; i++) {
9357 5899f386 bellard
                if (insn & (1 << i))
9358 5899f386 bellard
                    offset += 4;
9359 5899f386 bellard
            }
9360 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
9361 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, -offset);
9362 5899f386 bellard
            }
9363 99c475ab bellard
            for (i = 0; i < 8; i++) {
9364 99c475ab bellard
                if (insn & (1 << i)) {
9365 99c475ab bellard
                    if (insn & (1 << 11)) {
9366 99c475ab bellard
                        /* pop */
9367 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
9368 b0109805 pbrook
                        store_reg(s, i, tmp);
9369 99c475ab bellard
                    } else {
9370 99c475ab bellard
                        /* push */
9371 b0109805 pbrook
                        tmp = load_reg(s, i);
9372 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
9373 99c475ab bellard
                    }
9374 5899f386 bellard
                    /* advance to the next address.  */
9375 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
9376 99c475ab bellard
                }
9377 99c475ab bellard
            }
9378 a50f5b91 pbrook
            TCGV_UNUSED(tmp);
9379 99c475ab bellard
            if (insn & (1 << 8)) {
9380 99c475ab bellard
                if (insn & (1 << 11)) {
9381 99c475ab bellard
                    /* pop pc */
9382 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
9383 99c475ab bellard
                    /* don't set the pc until the rest of the instruction
9384 99c475ab bellard
                       has completed */
9385 99c475ab bellard
                } else {
9386 99c475ab bellard
                    /* push lr */
9387 b0109805 pbrook
                    tmp = load_reg(s, 14);
9388 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
9389 99c475ab bellard
                }
9390 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, 4);
9391 99c475ab bellard
            }
9392 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
9393 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, -offset);
9394 5899f386 bellard
            }
9395 99c475ab bellard
            /* write back the new stack pointer */
9396 b0109805 pbrook
            store_reg(s, 13, addr);
9397 99c475ab bellard
            /* set the new PC value */
9398 be5e7a76 Dmitry Eremin-Solenikov
            if ((insn & 0x0900) == 0x0900) {
9399 be5e7a76 Dmitry Eremin-Solenikov
                store_reg_from_load(env, s, 15, tmp);
9400 be5e7a76 Dmitry Eremin-Solenikov
            }
9401 99c475ab bellard
            break;
9402 99c475ab bellard
9403 9ee6e8bb pbrook
        case 1: case 3: case 9: case 11: /* czb */
9404 9ee6e8bb pbrook
            rm = insn & 7;
9405 d9ba4830 pbrook
            tmp = load_reg(s, rm);
9406 9ee6e8bb pbrook
            s->condlabel = gen_new_label();
9407 9ee6e8bb pbrook
            s->condjmp = 1;
9408 9ee6e8bb pbrook
            if (insn & (1 << 11))
9409 cb63669a pbrook
                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9410 9ee6e8bb pbrook
            else
9411 cb63669a pbrook
                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9412 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
9413 9ee6e8bb pbrook
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9414 9ee6e8bb pbrook
            val = (uint32_t)s->pc + 2;
9415 9ee6e8bb pbrook
            val += offset;
9416 9ee6e8bb pbrook
            gen_jmp(s, val);
9417 9ee6e8bb pbrook
            break;
9418 9ee6e8bb pbrook
9419 9ee6e8bb pbrook
        case 15: /* IT, nop-hint.  */
9420 9ee6e8bb pbrook
            if ((insn & 0xf) == 0) {
9421 9ee6e8bb pbrook
                gen_nop_hint(s, (insn >> 4) & 0xf);
9422 9ee6e8bb pbrook
                break;
9423 9ee6e8bb pbrook
            }
9424 9ee6e8bb pbrook
            /* If Then.  */
9425 9ee6e8bb pbrook
            s->condexec_cond = (insn >> 4) & 0xe;
9426 9ee6e8bb pbrook
            s->condexec_mask = insn & 0x1f;
9427 9ee6e8bb pbrook
            /* No actual code generated for this insn, just setup state.  */
9428 9ee6e8bb pbrook
            break;
9429 9ee6e8bb pbrook
9430 06c949e6 pbrook
        case 0xe: /* bkpt */
9431 be5e7a76 Dmitry Eremin-Solenikov
            ARCH(5);
9432 bc4a0de0 Peter Maydell
            gen_exception_insn(s, 2, EXCP_BKPT);
9433 06c949e6 pbrook
            break;
9434 06c949e6 pbrook
9435 9ee6e8bb pbrook
        case 0xa: /* rev */
9436 9ee6e8bb pbrook
            ARCH(6);
9437 9ee6e8bb pbrook
            rn = (insn >> 3) & 0x7;
9438 9ee6e8bb pbrook
            rd = insn & 0x7;
9439 b0109805 pbrook
            tmp = load_reg(s, rn);
9440 9ee6e8bb pbrook
            switch ((insn >> 6) & 3) {
9441 66896cb8 aurel32
            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9442 b0109805 pbrook
            case 1: gen_rev16(tmp); break;
9443 b0109805 pbrook
            case 3: gen_revsh(tmp); break;
9444 9ee6e8bb pbrook
            default: goto illegal_op;
9445 9ee6e8bb pbrook
            }
9446 b0109805 pbrook
            store_reg(s, rd, tmp);
9447 9ee6e8bb pbrook
            break;
9448 9ee6e8bb pbrook
9449 9ee6e8bb pbrook
        case 6: /* cps */
9450 9ee6e8bb pbrook
            ARCH(6);
9451 9ee6e8bb pbrook
            if (IS_USER(s))
9452 9ee6e8bb pbrook
                break;
9453 9ee6e8bb pbrook
            if (IS_M(env)) {
9454 8984bd2e pbrook
                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9455 9ee6e8bb pbrook
                /* PRIMASK */
9456 8984bd2e pbrook
                if (insn & 1) {
9457 8984bd2e pbrook
                    addr = tcg_const_i32(16);
9458 8984bd2e pbrook
                    gen_helper_v7m_msr(cpu_env, addr, tmp);
9459 b75263d6 Juha Riihimäki
                    tcg_temp_free_i32(addr);
9460 8984bd2e pbrook
                }
9461 9ee6e8bb pbrook
                /* FAULTMASK */
9462 8984bd2e pbrook
                if (insn & 2) {
9463 8984bd2e pbrook
                    addr = tcg_const_i32(17);
9464 8984bd2e pbrook
                    gen_helper_v7m_msr(cpu_env, addr, tmp);
9465 b75263d6 Juha Riihimäki
                    tcg_temp_free_i32(addr);
9466 8984bd2e pbrook
                }
9467 b75263d6 Juha Riihimäki
                tcg_temp_free_i32(tmp);
9468 9ee6e8bb pbrook
                gen_lookup_tb(s);
9469 9ee6e8bb pbrook
            } else {
9470 9ee6e8bb pbrook
                if (insn & (1 << 4))
9471 9ee6e8bb pbrook
                    shift = CPSR_A | CPSR_I | CPSR_F;
9472 9ee6e8bb pbrook
                else
9473 9ee6e8bb pbrook
                    shift = 0;
9474 fa26df03 Rabin Vincent
                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9475 9ee6e8bb pbrook
            }
9476 9ee6e8bb pbrook
            break;
9477 9ee6e8bb pbrook
9478 99c475ab bellard
        default:
9479 99c475ab bellard
            goto undef;
9480 99c475ab bellard
        }
9481 99c475ab bellard
        break;
9482 99c475ab bellard
9483 99c475ab bellard
    case 12:
9484 a7d3970d Peter Maydell
    {
9485 99c475ab bellard
        /* load/store multiple */
9486 a7d3970d Peter Maydell
        TCGv loaded_var;
9487 a7d3970d Peter Maydell
        TCGV_UNUSED(loaded_var);
9488 99c475ab bellard
        rn = (insn >> 8) & 0x7;
9489 b0109805 pbrook
        addr = load_reg(s, rn);
9490 99c475ab bellard
        for (i = 0; i < 8; i++) {
9491 99c475ab bellard
            if (insn & (1 << i)) {
9492 99c475ab bellard
                if (insn & (1 << 11)) {
9493 99c475ab bellard
                    /* load */
9494 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
9495 a7d3970d Peter Maydell
                    if (i == rn) {
9496 a7d3970d Peter Maydell
                        loaded_var = tmp;
9497 a7d3970d Peter Maydell
                    } else {
9498 a7d3970d Peter Maydell
                        store_reg(s, i, tmp);
9499 a7d3970d Peter Maydell
                    }
9500 99c475ab bellard
                } else {
9501 99c475ab bellard
                    /* store */
9502 b0109805 pbrook
                    tmp = load_reg(s, i);
9503 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
9504 99c475ab bellard
                }
9505 5899f386 bellard
                /* advance to the next address */
9506 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, 4);
9507 99c475ab bellard
            }
9508 99c475ab bellard
        }
9509 b0109805 pbrook
        if ((insn & (1 << rn)) == 0) {
9510 a7d3970d Peter Maydell
            /* base reg not in list: base register writeback */
9511 b0109805 pbrook
            store_reg(s, rn, addr);
9512 b0109805 pbrook
        } else {
9513 a7d3970d Peter Maydell
            /* base reg in list: if load, complete it now */
9514 a7d3970d Peter Maydell
            if (insn & (1 << 11)) {
9515 a7d3970d Peter Maydell
                store_reg(s, rn, loaded_var);
9516 a7d3970d Peter Maydell
            }
9517 7d1b0095 Peter Maydell
            tcg_temp_free_i32(addr);
9518 b0109805 pbrook
        }
9519 99c475ab bellard
        break;
9520 a7d3970d Peter Maydell
    }
9521 99c475ab bellard
    case 13:
9522 99c475ab bellard
        /* conditional branch or swi */
9523 99c475ab bellard
        cond = (insn >> 8) & 0xf;
9524 99c475ab bellard
        if (cond == 0xe)
9525 99c475ab bellard
            goto undef;
9526 99c475ab bellard
9527 99c475ab bellard
        if (cond == 0xf) {
9528 99c475ab bellard
            /* swi */
9529 422ebf69 balrog
            gen_set_pc_im(s->pc);
9530 9ee6e8bb pbrook
            s->is_jmp = DISAS_SWI;
9531 99c475ab bellard
            break;
9532 99c475ab bellard
        }
9533 99c475ab bellard
        /* generate a conditional jump to next instruction */
9534 e50e6a20 bellard
        s->condlabel = gen_new_label();
9535 d9ba4830 pbrook
        gen_test_cc(cond ^ 1, s->condlabel);
9536 e50e6a20 bellard
        s->condjmp = 1;
9537 99c475ab bellard
9538 99c475ab bellard
        /* jump to the offset */
9539 5899f386 bellard
        val = (uint32_t)s->pc + 2;
9540 99c475ab bellard
        offset = ((int32_t)insn << 24) >> 24;
9541 5899f386 bellard
        val += offset << 1;
9542 8aaca4c0 bellard
        gen_jmp(s, val);
9543 99c475ab bellard
        break;
9544 99c475ab bellard
9545 99c475ab bellard
    case 14:
9546 358bf29e pbrook
        if (insn & (1 << 11)) {
9547 9ee6e8bb pbrook
            if (disas_thumb2_insn(env, s, insn))
9548 9ee6e8bb pbrook
              goto undef32;
9549 358bf29e pbrook
            break;
9550 358bf29e pbrook
        }
9551 9ee6e8bb pbrook
        /* unconditional branch */
9552 99c475ab bellard
        val = (uint32_t)s->pc;
9553 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 21;
9554 99c475ab bellard
        val += (offset << 1) + 2;
9555 8aaca4c0 bellard
        gen_jmp(s, val);
9556 99c475ab bellard
        break;
9557 99c475ab bellard
9558 99c475ab bellard
    case 15:
9559 9ee6e8bb pbrook
        if (disas_thumb2_insn(env, s, insn))
9560 6a0d8a1d balrog
            goto undef32;
9561 9ee6e8bb pbrook
        break;
9562 99c475ab bellard
    }
9563 99c475ab bellard
    return;
9564 9ee6e8bb pbrook
undef32:
9565 bc4a0de0 Peter Maydell
    gen_exception_insn(s, 4, EXCP_UDEF);
9566 9ee6e8bb pbrook
    return;
9567 9ee6e8bb pbrook
illegal_op:
9568 99c475ab bellard
undef:
9569 bc4a0de0 Peter Maydell
    gen_exception_insn(s, 2, EXCP_UDEF);
9570 99c475ab bellard
}
9571 99c475ab bellard
9572 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9573 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
9574 2c0262af bellard
   information for each intermediate instruction. */
9575 2cfc5f17 ths
static inline void gen_intermediate_code_internal(CPUState *env,
9576 2cfc5f17 ths
                                                  TranslationBlock *tb,
9577 2cfc5f17 ths
                                                  int search_pc)
9578 2c0262af bellard
{
9579 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
9580 a1d1bb31 aliguori
    CPUBreakpoint *bp;
9581 2c0262af bellard
    uint16_t *gen_opc_end;
9582 2c0262af bellard
    int j, lj;
9583 0fa85d43 bellard
    target_ulong pc_start;
9584 b5ff1b31 bellard
    uint32_t next_page_start;
9585 2e70f6ef pbrook
    int num_insns;
9586 2e70f6ef pbrook
    int max_insns;
9587 3b46e624 ths
9588 2c0262af bellard
    /* generate intermediate code */
9589 0fa85d43 bellard
    pc_start = tb->pc;
9590 3b46e624 ths
9591 2c0262af bellard
    dc->tb = tb;
9592 2c0262af bellard
9593 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9594 2c0262af bellard
9595 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
9596 2c0262af bellard
    dc->pc = pc_start;
9597 8aaca4c0 bellard
    dc->singlestep_enabled = env->singlestep_enabled;
9598 e50e6a20 bellard
    dc->condjmp = 0;
9599 7204ab88 Peter Maydell
    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9600 98eac7ca Peter Maydell
    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9601 98eac7ca Peter Maydell
    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9602 b5ff1b31 bellard
#if !defined(CONFIG_USER_ONLY)
9603 61f74d6a Peter Maydell
    dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9604 b5ff1b31 bellard
#endif
9605 5df8bac1 Peter Maydell
    dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9606 69d1fc22 Peter Maydell
    dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9607 69d1fc22 Peter Maydell
    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9608 a7812ae4 pbrook
    cpu_F0s = tcg_temp_new_i32();
9609 a7812ae4 pbrook
    cpu_F1s = tcg_temp_new_i32();
9610 a7812ae4 pbrook
    cpu_F0d = tcg_temp_new_i64();
9611 a7812ae4 pbrook
    cpu_F1d = tcg_temp_new_i64();
9612 ad69471c pbrook
    cpu_V0 = cpu_F0d;
9613 ad69471c pbrook
    cpu_V1 = cpu_F1d;
9614 e677137d pbrook
    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
9615 a7812ae4 pbrook
    cpu_M0 = tcg_temp_new_i64();
9616 b5ff1b31 bellard
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9617 2c0262af bellard
    lj = -1;
9618 2e70f6ef pbrook
    num_insns = 0;
9619 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
9620 2e70f6ef pbrook
    if (max_insns == 0)
9621 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
9622 2e70f6ef pbrook
9623 2e70f6ef pbrook
    gen_icount_start();
9624 e12ce78d Peter Maydell
9625 3849902c Peter Maydell
    tcg_clear_temp_count();
9626 3849902c Peter Maydell
9627 e12ce78d Peter Maydell
    /* A note on handling of the condexec (IT) bits:
9628 e12ce78d Peter Maydell
     *
9629 e12ce78d Peter Maydell
     * We want to avoid the overhead of having to write the updated condexec
9630 e12ce78d Peter Maydell
     * bits back to the CPUState for every instruction in an IT block. So:
9631 e12ce78d Peter Maydell
     * (1) if the condexec bits are not already zero then we write
9632 e12ce78d Peter Maydell
     * zero back into the CPUState now. This avoids complications trying
9633 e12ce78d Peter Maydell
     * to do it at the end of the block. (For example if we don't do this
9634 e12ce78d Peter Maydell
     * it's hard to identify whether we can safely skip writing condexec
9635 e12ce78d Peter Maydell
     * at the end of the TB, which we definitely want to do for the case
9636 e12ce78d Peter Maydell
     * where a TB doesn't do anything with the IT state at all.)
9637 e12ce78d Peter Maydell
     * (2) if we are going to leave the TB then we call gen_set_condexec()
9638 e12ce78d Peter Maydell
     * which will write the correct value into CPUState if zero is wrong.
9639 e12ce78d Peter Maydell
     * This is done both for leaving the TB at the end, and for leaving
9640 e12ce78d Peter Maydell
     * it because of an exception we know will happen, which is done in
9641 e12ce78d Peter Maydell
     * gen_exception_insn(). The latter is necessary because we need to
9642 e12ce78d Peter Maydell
     * leave the TB with the PC/IT state just prior to execution of the
9643 e12ce78d Peter Maydell
     * instruction which caused the exception.
9644 e12ce78d Peter Maydell
     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9645 e12ce78d Peter Maydell
     * then the CPUState will be wrong and we need to reset it.
9646 e12ce78d Peter Maydell
     * This is handled in the same way as restoration of the
9647 e12ce78d Peter Maydell
     * PC in these situations: we will be called again with search_pc=1
9648 e12ce78d Peter Maydell
     * and generate a mapping of the condexec bits for each PC in
9649 e87b7cb0 Stefan Weil
     * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9650 e87b7cb0 Stefan Weil
     * this to restore the condexec bits.
9651 e12ce78d Peter Maydell
     *
9652 e12ce78d Peter Maydell
     * Note that there are no instructions which can read the condexec
9653 e12ce78d Peter Maydell
     * bits, and none which can write non-static values to them, so
9654 e12ce78d Peter Maydell
     * we don't need to care about whether CPUState is correct in the
9655 e12ce78d Peter Maydell
     * middle of a TB.
9656 e12ce78d Peter Maydell
     */
9657 e12ce78d Peter Maydell
9658 9ee6e8bb pbrook
    /* Reset the conditional execution bits immediately. This avoids
9659 9ee6e8bb pbrook
       complications trying to do it at the end of the block.  */
9660 98eac7ca Peter Maydell
    if (dc->condexec_mask || dc->condexec_cond)
9661 8f01245e pbrook
      {
9662 7d1b0095 Peter Maydell
        TCGv tmp = tcg_temp_new_i32();
9663 8f01245e pbrook
        tcg_gen_movi_i32(tmp, 0);
9664 d9ba4830 pbrook
        store_cpu_field(tmp, condexec_bits);
9665 8f01245e pbrook
      }
9666 2c0262af bellard
    do {
9667 fbb4a2e3 pbrook
#ifdef CONFIG_USER_ONLY
9668 fbb4a2e3 pbrook
        /* Intercept jump to the magic kernel page.  */
9669 fbb4a2e3 pbrook
        if (dc->pc >= 0xffff0000) {
9670 fbb4a2e3 pbrook
            /* We always get here via a jump, so know we are not in a
9671 fbb4a2e3 pbrook
               conditional execution block.  */
9672 fbb4a2e3 pbrook
            gen_exception(EXCP_KERNEL_TRAP);
9673 fbb4a2e3 pbrook
            dc->is_jmp = DISAS_UPDATE;
9674 fbb4a2e3 pbrook
            break;
9675 fbb4a2e3 pbrook
        }
9676 fbb4a2e3 pbrook
#else
9677 9ee6e8bb pbrook
        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9678 9ee6e8bb pbrook
            /* We always get here via a jump, so know we are not in a
9679 9ee6e8bb pbrook
               conditional execution block.  */
9680 d9ba4830 pbrook
            gen_exception(EXCP_EXCEPTION_EXIT);
9681 d60bb01c pbrook
            dc->is_jmp = DISAS_UPDATE;
9682 d60bb01c pbrook
            break;
9683 9ee6e8bb pbrook
        }
9684 9ee6e8bb pbrook
#endif
9685 9ee6e8bb pbrook
9686 72cf2d4f Blue Swirl
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9687 72cf2d4f Blue Swirl
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9688 a1d1bb31 aliguori
                if (bp->pc == dc->pc) {
9689 bc4a0de0 Peter Maydell
                    gen_exception_insn(dc, 0, EXCP_DEBUG);
9690 9ee6e8bb pbrook
                    /* Advance PC so that clearing the breakpoint will
9691 9ee6e8bb pbrook
                       invalidate this TB.  */
9692 9ee6e8bb pbrook
                    dc->pc += 2;
9693 9ee6e8bb pbrook
                    goto done_generating;
9694 1fddef4b bellard
                    break;
9695 1fddef4b bellard
                }
9696 1fddef4b bellard
            }
9697 1fddef4b bellard
        }
9698 2c0262af bellard
        if (search_pc) {
9699 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
9700 2c0262af bellard
            if (lj < j) {
9701 2c0262af bellard
                lj++;
9702 2c0262af bellard
                while (lj < j)
9703 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
9704 2c0262af bellard
            }
9705 0fa85d43 bellard
            gen_opc_pc[lj] = dc->pc;
9706 e12ce78d Peter Maydell
            gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9707 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
9708 2e70f6ef pbrook
            gen_opc_icount[lj] = num_insns;
9709 2c0262af bellard
        }
9710 e50e6a20 bellard
9711 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9712 2e70f6ef pbrook
            gen_io_start();
9713 2e70f6ef pbrook
9714 5642463a Peter Maydell
        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9715 5642463a Peter Maydell
            tcg_gen_debug_insn_start(dc->pc);
9716 5642463a Peter Maydell
        }
9717 5642463a Peter Maydell
9718 7204ab88 Peter Maydell
        if (dc->thumb) {
9719 9ee6e8bb pbrook
            disas_thumb_insn(env, dc);
9720 9ee6e8bb pbrook
            if (dc->condexec_mask) {
9721 9ee6e8bb pbrook
                dc->condexec_cond = (dc->condexec_cond & 0xe)
9722 9ee6e8bb pbrook
                                   | ((dc->condexec_mask >> 4) & 1);
9723 9ee6e8bb pbrook
                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9724 9ee6e8bb pbrook
                if (dc->condexec_mask == 0) {
9725 9ee6e8bb pbrook
                    dc->condexec_cond = 0;
9726 9ee6e8bb pbrook
                }
9727 9ee6e8bb pbrook
            }
9728 9ee6e8bb pbrook
        } else {
9729 9ee6e8bb pbrook
            disas_arm_insn(env, dc);
9730 9ee6e8bb pbrook
        }
9731 e50e6a20 bellard
9732 e50e6a20 bellard
        if (dc->condjmp && !dc->is_jmp) {
9733 e50e6a20 bellard
            gen_set_label(dc->condlabel);
9734 e50e6a20 bellard
            dc->condjmp = 0;
9735 e50e6a20 bellard
        }
9736 3849902c Peter Maydell
9737 3849902c Peter Maydell
        if (tcg_check_temp_count()) {
9738 3849902c Peter Maydell
            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9739 3849902c Peter Maydell
        }
9740 3849902c Peter Maydell
9741 aaf2d97d balrog
        /* Translation stops when a conditional branch is encountered.
9742 e50e6a20 bellard
         * Otherwise the subsequent code could get translated several times.
9743 b5ff1b31 bellard
         * Also stop translation when a page boundary is reached.  This
9744 bf20dc07 ths
         * ensures prefetch aborts occur at the right place.  */
9745 2e70f6ef pbrook
        num_insns ++;
9746 1fddef4b bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9747 1fddef4b bellard
             !env->singlestep_enabled &&
9748 1b530a6d aurel32
             !singlestep &&
9749 2e70f6ef pbrook
             dc->pc < next_page_start &&
9750 2e70f6ef pbrook
             num_insns < max_insns);
9751 2e70f6ef pbrook
9752 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO) {
9753 2e70f6ef pbrook
        if (dc->condjmp) {
9754 2e70f6ef pbrook
            /* FIXME:  This can theoretically happen with self-modifying
9755 2e70f6ef pbrook
               code.  */
9756 2e70f6ef pbrook
            cpu_abort(env, "IO on conditional branch instruction");
9757 2e70f6ef pbrook
        }
9758 2e70f6ef pbrook
        gen_io_end();
9759 2e70f6ef pbrook
    }
9760 9ee6e8bb pbrook
9761 b5ff1b31 bellard
    /* At this stage dc->condjmp will only be set when the skipped
9762 9ee6e8bb pbrook
       instruction was a conditional branch or trap, and the PC has
9763 9ee6e8bb pbrook
       already been written.  */
9764 551bd27f ths
    if (unlikely(env->singlestep_enabled)) {
9765 8aaca4c0 bellard
        /* Make sure the pc is updated, and raise a debug exception.  */
9766 e50e6a20 bellard
        if (dc->condjmp) {
9767 9ee6e8bb pbrook
            gen_set_condexec(dc);
9768 9ee6e8bb pbrook
            if (dc->is_jmp == DISAS_SWI) {
9769 d9ba4830 pbrook
                gen_exception(EXCP_SWI);
9770 9ee6e8bb pbrook
            } else {
9771 d9ba4830 pbrook
                gen_exception(EXCP_DEBUG);
9772 9ee6e8bb pbrook
            }
9773 e50e6a20 bellard
            gen_set_label(dc->condlabel);
9774 e50e6a20 bellard
        }
9775 e50e6a20 bellard
        if (dc->condjmp || !dc->is_jmp) {
9776 5e3f878a pbrook
            gen_set_pc_im(dc->pc);
9777 e50e6a20 bellard
            dc->condjmp = 0;
9778 8aaca4c0 bellard
        }
9779 9ee6e8bb pbrook
        gen_set_condexec(dc);
9780 9ee6e8bb pbrook
        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9781 d9ba4830 pbrook
            gen_exception(EXCP_SWI);
9782 9ee6e8bb pbrook
        } else {
9783 9ee6e8bb pbrook
            /* FIXME: Single stepping a WFI insn will not halt
9784 9ee6e8bb pbrook
               the CPU.  */
9785 d9ba4830 pbrook
            gen_exception(EXCP_DEBUG);
9786 9ee6e8bb pbrook
        }
9787 8aaca4c0 bellard
    } else {
9788 9ee6e8bb pbrook
        /* While branches must always occur at the end of an IT block,
9789 9ee6e8bb pbrook
           there are a few other things that can cause us to terminate
9790 9ee6e8bb pbrook
           the TB in the middel of an IT block:
9791 9ee6e8bb pbrook
            - Exception generating instructions (bkpt, swi, undefined).
9792 9ee6e8bb pbrook
            - Page boundaries.
9793 9ee6e8bb pbrook
            - Hardware watchpoints.
9794 9ee6e8bb pbrook
           Hardware breakpoints have already been handled and skip this code.
9795 9ee6e8bb pbrook
         */
9796 9ee6e8bb pbrook
        gen_set_condexec(dc);
9797 8aaca4c0 bellard
        switch(dc->is_jmp) {
9798 8aaca4c0 bellard
        case DISAS_NEXT:
9799 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
9800 8aaca4c0 bellard
            break;
9801 8aaca4c0 bellard
        default:
9802 8aaca4c0 bellard
        case DISAS_JUMP:
9803 8aaca4c0 bellard
        case DISAS_UPDATE:
9804 8aaca4c0 bellard
            /* indicate that the hash table must be used to find the next TB */
9805 57fec1fe bellard
            tcg_gen_exit_tb(0);
9806 8aaca4c0 bellard
            break;
9807 8aaca4c0 bellard
        case DISAS_TB_JUMP:
9808 8aaca4c0 bellard
            /* nothing more to generate */
9809 8aaca4c0 bellard
            break;
9810 9ee6e8bb pbrook
        case DISAS_WFI:
9811 d9ba4830 pbrook
            gen_helper_wfi();
9812 9ee6e8bb pbrook
            break;
9813 9ee6e8bb pbrook
        case DISAS_SWI:
9814 d9ba4830 pbrook
            gen_exception(EXCP_SWI);
9815 9ee6e8bb pbrook
            break;
9816 8aaca4c0 bellard
        }
9817 e50e6a20 bellard
        if (dc->condjmp) {
9818 e50e6a20 bellard
            gen_set_label(dc->condlabel);
9819 9ee6e8bb pbrook
            gen_set_condexec(dc);
9820 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
9821 e50e6a20 bellard
            dc->condjmp = 0;
9822 e50e6a20 bellard
        }
9823 2c0262af bellard
    }
9824 2e70f6ef pbrook
9825 9ee6e8bb pbrook
done_generating:
9826 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
9827 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
9828 2c0262af bellard
9829 2c0262af bellard
#ifdef DEBUG_DISAS
9830 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9831 93fcfe39 aliguori
        qemu_log("----------------\n");
9832 93fcfe39 aliguori
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
9833 7204ab88 Peter Maydell
        log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9834 93fcfe39 aliguori
        qemu_log("\n");
9835 2c0262af bellard
    }
9836 2c0262af bellard
#endif
9837 b5ff1b31 bellard
    if (search_pc) {
9838 b5ff1b31 bellard
        j = gen_opc_ptr - gen_opc_buf;
9839 b5ff1b31 bellard
        lj++;
9840 b5ff1b31 bellard
        while (lj <= j)
9841 b5ff1b31 bellard
            gen_opc_instr_start[lj++] = 0;
9842 b5ff1b31 bellard
    } else {
9843 2c0262af bellard
        tb->size = dc->pc - pc_start;
9844 2e70f6ef pbrook
        tb->icount = num_insns;
9845 b5ff1b31 bellard
    }
9846 2c0262af bellard
}
9847 2c0262af bellard
9848 2cfc5f17 ths
void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9849 2c0262af bellard
{
9850 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
9851 2c0262af bellard
}
9852 2c0262af bellard
9853 2cfc5f17 ths
void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9854 2c0262af bellard
{
9855 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
9856 2c0262af bellard
}
9857 2c0262af bellard
9858 b5ff1b31 bellard
static const char *cpu_mode_names[16] = {
9859 b5ff1b31 bellard
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9860 b5ff1b31 bellard
  "???", "???", "???", "und", "???", "???", "???", "sys"
9861 b5ff1b31 bellard
};
9862 9ee6e8bb pbrook
9863 9a78eead Stefan Weil
void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9864 7fe48483 bellard
                    int flags)
9865 2c0262af bellard
{
9866 2c0262af bellard
    int i;
9867 06e80fc9 ths
#if 0
9868 bc380d17 bellard
    union {
9869 b7bcbe95 bellard
        uint32_t i;
9870 b7bcbe95 bellard
        float s;
9871 b7bcbe95 bellard
    } s0, s1;
9872 b7bcbe95 bellard
    CPU_DoubleU d;
9873 a94a6abf pbrook
    /* ??? This assumes float64 and double have the same layout.
9874 a94a6abf pbrook
       Oh well, it's only debug dumps.  */
9875 a94a6abf pbrook
    union {
9876 a94a6abf pbrook
        float64 f64;
9877 a94a6abf pbrook
        double d;
9878 a94a6abf pbrook
    } d0;
9879 06e80fc9 ths
#endif
9880 b5ff1b31 bellard
    uint32_t psr;
9881 2c0262af bellard
9882 2c0262af bellard
    for(i=0;i<16;i++) {
9883 7fe48483 bellard
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9884 2c0262af bellard
        if ((i % 4) == 3)
9885 7fe48483 bellard
            cpu_fprintf(f, "\n");
9886 2c0262af bellard
        else
9887 7fe48483 bellard
            cpu_fprintf(f, " ");
9888 2c0262af bellard
    }
9889 b5ff1b31 bellard
    psr = cpsr_read(env);
9890 687fa640 ths
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9891 687fa640 ths
                psr,
9892 b5ff1b31 bellard
                psr & (1 << 31) ? 'N' : '-',
9893 b5ff1b31 bellard
                psr & (1 << 30) ? 'Z' : '-',
9894 b5ff1b31 bellard
                psr & (1 << 29) ? 'C' : '-',
9895 b5ff1b31 bellard
                psr & (1 << 28) ? 'V' : '-',
9896 5fafdf24 ths
                psr & CPSR_T ? 'T' : 'A',
9897 b5ff1b31 bellard
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9898 b7bcbe95 bellard
9899 5e3f878a pbrook
#if 0
9900 b7bcbe95 bellard
    for (i = 0; i < 16; i++) {
9901 8e96005d bellard
        d.d = env->vfp.regs[i];
9902 8e96005d bellard
        s0.i = d.l.lower;
9903 8e96005d bellard
        s1.i = d.l.upper;
9904 a94a6abf pbrook
        d0.f64 = d.d;
9905 a94a6abf pbrook
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9906 b7bcbe95 bellard
                    i * 2, (int)s0.i, s0.s,
9907 a94a6abf pbrook
                    i * 2 + 1, (int)s1.i, s1.s,
9908 b7bcbe95 bellard
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9909 a94a6abf pbrook
                    d0.d);
9910 b7bcbe95 bellard
    }
9911 40f137e1 pbrook
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9912 5e3f878a pbrook
#endif
9913 2c0262af bellard
}
9914 a6b025d3 bellard
9915 e87b7cb0 Stefan Weil
void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
9916 d2856f1a aurel32
{
9917 d2856f1a aurel32
    env->regs[15] = gen_opc_pc[pc_pos];
9918 e12ce78d Peter Maydell
    env->condexec_bits = gen_opc_condexec_bits[pc_pos];
9919 d2856f1a aurel32
}