Statistics
| Branch: | Revision:

root / target-arm / translate.c @ d9e028c1

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

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