Statistics
| Branch: | Revision:

root / target-arm / translate.c @ b7fa9214

History | View | Annotate | Download (336.7 kB)

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

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