Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 2bee5105

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

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