Statistics
| Branch: | Revision:

root / target-arm / translate.c @ e318a60b

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

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