Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 1472a95b

History | View | Annotate | Download (322.9 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 b7bcbe95 bellard
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2652 b7bcbe95 bellard
   (ie. an undefined instruction).  */
2653 b7bcbe95 bellard
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2654 b7bcbe95 bellard
{
2655 b7bcbe95 bellard
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2656 b7bcbe95 bellard
    int dp, veclen;
2657 312eea9f Filip Navara
    TCGv addr;
2658 4373f3ce pbrook
    TCGv tmp;
2659 ad69471c pbrook
    TCGv tmp2;
2660 b7bcbe95 bellard
2661 40f137e1 pbrook
    if (!arm_feature(env, ARM_FEATURE_VFP))
2662 40f137e1 pbrook
        return 1;
2663 40f137e1 pbrook
2664 5df8bac1 Peter Maydell
    if (!s->vfp_enabled) {
2665 9ee6e8bb pbrook
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2666 40f137e1 pbrook
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2667 40f137e1 pbrook
            return 1;
2668 40f137e1 pbrook
        rn = (insn >> 16) & 0xf;
2669 9ee6e8bb pbrook
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2670 9ee6e8bb pbrook
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2671 40f137e1 pbrook
            return 1;
2672 40f137e1 pbrook
    }
2673 b7bcbe95 bellard
    dp = ((insn & 0xf00) == 0xb00);
2674 b7bcbe95 bellard
    switch ((insn >> 24) & 0xf) {
2675 b7bcbe95 bellard
    case 0xe:
2676 b7bcbe95 bellard
        if (insn & (1 << 4)) {
2677 b7bcbe95 bellard
            /* single register transfer */
2678 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
2679 b7bcbe95 bellard
            if (dp) {
2680 9ee6e8bb pbrook
                int size;
2681 9ee6e8bb pbrook
                int pass;
2682 9ee6e8bb pbrook
2683 9ee6e8bb pbrook
                VFP_DREG_N(rn, insn);
2684 9ee6e8bb pbrook
                if (insn & 0xf)
2685 b7bcbe95 bellard
                    return 1;
2686 9ee6e8bb pbrook
                if (insn & 0x00c00060
2687 9ee6e8bb pbrook
                    && !arm_feature(env, ARM_FEATURE_NEON))
2688 9ee6e8bb pbrook
                    return 1;
2689 9ee6e8bb pbrook
2690 9ee6e8bb pbrook
                pass = (insn >> 21) & 1;
2691 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
2692 9ee6e8bb pbrook
                    size = 0;
2693 9ee6e8bb pbrook
                    offset = ((insn >> 5) & 3) * 8;
2694 9ee6e8bb pbrook
                } else if (insn & (1 << 5)) {
2695 9ee6e8bb pbrook
                    size = 1;
2696 9ee6e8bb pbrook
                    offset = (insn & (1 << 6)) ? 16 : 0;
2697 9ee6e8bb pbrook
                } else {
2698 9ee6e8bb pbrook
                    size = 2;
2699 9ee6e8bb pbrook
                    offset = 0;
2700 9ee6e8bb pbrook
                }
2701 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2702 b7bcbe95 bellard
                    /* vfp->arm */
2703 ad69471c pbrook
                    tmp = neon_load_reg(rn, pass);
2704 9ee6e8bb pbrook
                    switch (size) {
2705 9ee6e8bb pbrook
                    case 0:
2706 9ee6e8bb pbrook
                        if (offset)
2707 ad69471c pbrook
                            tcg_gen_shri_i32(tmp, tmp, offset);
2708 9ee6e8bb pbrook
                        if (insn & (1 << 23))
2709 ad69471c pbrook
                            gen_uxtb(tmp);
2710 9ee6e8bb pbrook
                        else
2711 ad69471c pbrook
                            gen_sxtb(tmp);
2712 9ee6e8bb pbrook
                        break;
2713 9ee6e8bb pbrook
                    case 1:
2714 9ee6e8bb pbrook
                        if (insn & (1 << 23)) {
2715 9ee6e8bb pbrook
                            if (offset) {
2716 ad69471c pbrook
                                tcg_gen_shri_i32(tmp, tmp, 16);
2717 9ee6e8bb pbrook
                            } else {
2718 ad69471c pbrook
                                gen_uxth(tmp);
2719 9ee6e8bb pbrook
                            }
2720 9ee6e8bb pbrook
                        } else {
2721 9ee6e8bb pbrook
                            if (offset) {
2722 ad69471c pbrook
                                tcg_gen_sari_i32(tmp, tmp, 16);
2723 9ee6e8bb pbrook
                            } else {
2724 ad69471c pbrook
                                gen_sxth(tmp);
2725 9ee6e8bb pbrook
                            }
2726 9ee6e8bb pbrook
                        }
2727 9ee6e8bb pbrook
                        break;
2728 9ee6e8bb pbrook
                    case 2:
2729 9ee6e8bb pbrook
                        break;
2730 9ee6e8bb pbrook
                    }
2731 ad69471c pbrook
                    store_reg(s, rd, tmp);
2732 b7bcbe95 bellard
                } else {
2733 b7bcbe95 bellard
                    /* arm->vfp */
2734 ad69471c pbrook
                    tmp = load_reg(s, rd);
2735 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
2736 9ee6e8bb pbrook
                        /* VDUP */
2737 9ee6e8bb pbrook
                        if (size == 0) {
2738 ad69471c pbrook
                            gen_neon_dup_u8(tmp, 0);
2739 9ee6e8bb pbrook
                        } else if (size == 1) {
2740 ad69471c pbrook
                            gen_neon_dup_low16(tmp);
2741 9ee6e8bb pbrook
                        }
2742 cbbccffc pbrook
                        for (n = 0; n <= pass * 2; n++) {
2743 7d1b0095 Peter Maydell
                            tmp2 = tcg_temp_new_i32();
2744 cbbccffc pbrook
                            tcg_gen_mov_i32(tmp2, tmp);
2745 cbbccffc pbrook
                            neon_store_reg(rn, n, tmp2);
2746 cbbccffc pbrook
                        }
2747 cbbccffc pbrook
                        neon_store_reg(rn, n, tmp);
2748 9ee6e8bb pbrook
                    } else {
2749 9ee6e8bb pbrook
                        /* VMOV */
2750 9ee6e8bb pbrook
                        switch (size) {
2751 9ee6e8bb pbrook
                        case 0:
2752 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2753 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2754 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
2755 9ee6e8bb pbrook
                            break;
2756 9ee6e8bb pbrook
                        case 1:
2757 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2758 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2759 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
2760 9ee6e8bb pbrook
                            break;
2761 9ee6e8bb pbrook
                        case 2:
2762 9ee6e8bb pbrook
                            break;
2763 9ee6e8bb pbrook
                        }
2764 ad69471c pbrook
                        neon_store_reg(rn, pass, tmp);
2765 9ee6e8bb pbrook
                    }
2766 b7bcbe95 bellard
                }
2767 9ee6e8bb pbrook
            } else { /* !dp */
2768 9ee6e8bb pbrook
                if ((insn & 0x6f) != 0x00)
2769 9ee6e8bb pbrook
                    return 1;
2770 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2771 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2772 b7bcbe95 bellard
                    /* vfp->arm */
2773 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2774 b7bcbe95 bellard
                        /* system register */
2775 40f137e1 pbrook
                        rn >>= 1;
2776 9ee6e8bb pbrook
2777 b7bcbe95 bellard
                        switch (rn) {
2778 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2779 4373f3ce pbrook
                            /* VFP2 allows access to FSID from userspace.
2780 9ee6e8bb pbrook
                               VFP3 restricts all id registers to privileged
2781 9ee6e8bb pbrook
                               accesses.  */
2782 9ee6e8bb pbrook
                            if (IS_USER(s)
2783 9ee6e8bb pbrook
                                && arm_feature(env, ARM_FEATURE_VFP3))
2784 9ee6e8bb pbrook
                                return 1;
2785 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2786 9ee6e8bb pbrook
                            break;
2787 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2788 9ee6e8bb pbrook
                            if (IS_USER(s))
2789 9ee6e8bb pbrook
                                return 1;
2790 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2791 9ee6e8bb pbrook
                            break;
2792 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2793 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2794 9ee6e8bb pbrook
                            /* Not present in VFP3.  */
2795 9ee6e8bb pbrook
                            if (IS_USER(s)
2796 9ee6e8bb pbrook
                                || arm_feature(env, ARM_FEATURE_VFP3))
2797 9ee6e8bb pbrook
                                return 1;
2798 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2799 b7bcbe95 bellard
                            break;
2800 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2801 601d70b9 balrog
                            if (rd == 15) {
2802 4373f3ce pbrook
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2803 4373f3ce pbrook
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2804 4373f3ce pbrook
                            } else {
2805 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
2806 4373f3ce pbrook
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2807 4373f3ce pbrook
                            }
2808 b7bcbe95 bellard
                            break;
2809 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2810 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2811 9ee6e8bb pbrook
                            if (IS_USER(s)
2812 9ee6e8bb pbrook
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2813 9ee6e8bb pbrook
                                return 1;
2814 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2815 9ee6e8bb pbrook
                            break;
2816 b7bcbe95 bellard
                        default:
2817 b7bcbe95 bellard
                            return 1;
2818 b7bcbe95 bellard
                        }
2819 b7bcbe95 bellard
                    } else {
2820 b7bcbe95 bellard
                        gen_mov_F0_vreg(0, rn);
2821 4373f3ce pbrook
                        tmp = gen_vfp_mrs();
2822 b7bcbe95 bellard
                    }
2823 b7bcbe95 bellard
                    if (rd == 15) {
2824 b5ff1b31 bellard
                        /* Set the 4 flag bits in the CPSR.  */
2825 4373f3ce pbrook
                        gen_set_nzcv(tmp);
2826 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
2827 4373f3ce pbrook
                    } else {
2828 4373f3ce pbrook
                        store_reg(s, rd, tmp);
2829 4373f3ce pbrook
                    }
2830 b7bcbe95 bellard
                } else {
2831 b7bcbe95 bellard
                    /* arm->vfp */
2832 4373f3ce pbrook
                    tmp = load_reg(s, rd);
2833 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2834 40f137e1 pbrook
                        rn >>= 1;
2835 b7bcbe95 bellard
                        /* system register */
2836 b7bcbe95 bellard
                        switch (rn) {
2837 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2838 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2839 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2840 b7bcbe95 bellard
                            /* Writes are ignored.  */
2841 b7bcbe95 bellard
                            break;
2842 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2843 4373f3ce pbrook
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2844 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp);
2845 b5ff1b31 bellard
                            gen_lookup_tb(s);
2846 b7bcbe95 bellard
                            break;
2847 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2848 9ee6e8bb pbrook
                            if (IS_USER(s))
2849 9ee6e8bb pbrook
                                return 1;
2850 71b3c3de Juha Riihimรคki
                            /* TODO: VFP subarchitecture support.
2851 71b3c3de Juha Riihimรคki
                             * For now, keep the EN bit only */
2852 71b3c3de Juha Riihimรคki
                            tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2853 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2854 40f137e1 pbrook
                            gen_lookup_tb(s);
2855 40f137e1 pbrook
                            break;
2856 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2857 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2858 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2859 40f137e1 pbrook
                            break;
2860 b7bcbe95 bellard
                        default:
2861 b7bcbe95 bellard
                            return 1;
2862 b7bcbe95 bellard
                        }
2863 b7bcbe95 bellard
                    } else {
2864 4373f3ce pbrook
                        gen_vfp_msr(tmp);
2865 b7bcbe95 bellard
                        gen_mov_vreg_F0(0, rn);
2866 b7bcbe95 bellard
                    }
2867 b7bcbe95 bellard
                }
2868 b7bcbe95 bellard
            }
2869 b7bcbe95 bellard
        } else {
2870 b7bcbe95 bellard
            /* data processing */
2871 b7bcbe95 bellard
            /* The opcode is in bits 23, 21, 20 and 6.  */
2872 b7bcbe95 bellard
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2873 b7bcbe95 bellard
            if (dp) {
2874 b7bcbe95 bellard
                if (op == 15) {
2875 b7bcbe95 bellard
                    /* rn is opcode */
2876 b7bcbe95 bellard
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2877 b7bcbe95 bellard
                } else {
2878 b7bcbe95 bellard
                    /* rn is register number */
2879 9ee6e8bb pbrook
                    VFP_DREG_N(rn, insn);
2880 b7bcbe95 bellard
                }
2881 b7bcbe95 bellard
2882 04595bf6 Peter Maydell
                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2883 b7bcbe95 bellard
                    /* Integer or single precision destination.  */
2884 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2885 b7bcbe95 bellard
                } else {
2886 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2887 b7bcbe95 bellard
                }
2888 04595bf6 Peter Maydell
                if (op == 15 &&
2889 04595bf6 Peter Maydell
                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2890 04595bf6 Peter Maydell
                    /* VCVT from int is always from S reg regardless of dp bit.
2891 04595bf6 Peter Maydell
                     * VCVT with immediate frac_bits has same format as SREG_M
2892 04595bf6 Peter Maydell
                     */
2893 04595bf6 Peter Maydell
                    rm = VFP_SREG_M(insn);
2894 b7bcbe95 bellard
                } else {
2895 9ee6e8bb pbrook
                    VFP_DREG_M(rm, insn);
2896 b7bcbe95 bellard
                }
2897 b7bcbe95 bellard
            } else {
2898 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2899 b7bcbe95 bellard
                if (op == 15 && rn == 15) {
2900 b7bcbe95 bellard
                    /* Double precision destination.  */
2901 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2902 9ee6e8bb pbrook
                } else {
2903 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2904 9ee6e8bb pbrook
                }
2905 04595bf6 Peter Maydell
                /* NB that we implicitly rely on the encoding for the frac_bits
2906 04595bf6 Peter Maydell
                 * in VCVT of fixed to float being the same as that of an SREG_M
2907 04595bf6 Peter Maydell
                 */
2908 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
2909 b7bcbe95 bellard
            }
2910 b7bcbe95 bellard
2911 69d1fc22 Peter Maydell
            veclen = s->vec_len;
2912 b7bcbe95 bellard
            if (op == 15 && rn > 3)
2913 b7bcbe95 bellard
                veclen = 0;
2914 b7bcbe95 bellard
2915 b7bcbe95 bellard
            /* Shut up compiler warnings.  */
2916 b7bcbe95 bellard
            delta_m = 0;
2917 b7bcbe95 bellard
            delta_d = 0;
2918 b7bcbe95 bellard
            bank_mask = 0;
2919 3b46e624 ths
2920 b7bcbe95 bellard
            if (veclen > 0) {
2921 b7bcbe95 bellard
                if (dp)
2922 b7bcbe95 bellard
                    bank_mask = 0xc;
2923 b7bcbe95 bellard
                else
2924 b7bcbe95 bellard
                    bank_mask = 0x18;
2925 b7bcbe95 bellard
2926 b7bcbe95 bellard
                /* Figure out what type of vector operation this is.  */
2927 b7bcbe95 bellard
                if ((rd & bank_mask) == 0) {
2928 b7bcbe95 bellard
                    /* scalar */
2929 b7bcbe95 bellard
                    veclen = 0;
2930 b7bcbe95 bellard
                } else {
2931 b7bcbe95 bellard
                    if (dp)
2932 69d1fc22 Peter Maydell
                        delta_d = (s->vec_stride >> 1) + 1;
2933 b7bcbe95 bellard
                    else
2934 69d1fc22 Peter Maydell
                        delta_d = s->vec_stride + 1;
2935 b7bcbe95 bellard
2936 b7bcbe95 bellard
                    if ((rm & bank_mask) == 0) {
2937 b7bcbe95 bellard
                        /* mixed scalar/vector */
2938 b7bcbe95 bellard
                        delta_m = 0;
2939 b7bcbe95 bellard
                    } else {
2940 b7bcbe95 bellard
                        /* vector */
2941 b7bcbe95 bellard
                        delta_m = delta_d;
2942 b7bcbe95 bellard
                    }
2943 b7bcbe95 bellard
                }
2944 b7bcbe95 bellard
            }
2945 b7bcbe95 bellard
2946 b7bcbe95 bellard
            /* Load the initial operands.  */
2947 b7bcbe95 bellard
            if (op == 15) {
2948 b7bcbe95 bellard
                switch (rn) {
2949 b7bcbe95 bellard
                case 16:
2950 b7bcbe95 bellard
                case 17:
2951 b7bcbe95 bellard
                    /* Integer source */
2952 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
2953 b7bcbe95 bellard
                    break;
2954 b7bcbe95 bellard
                case 8:
2955 b7bcbe95 bellard
                case 9:
2956 b7bcbe95 bellard
                    /* Compare */
2957 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
2958 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rm);
2959 b7bcbe95 bellard
                    break;
2960 b7bcbe95 bellard
                case 10:
2961 b7bcbe95 bellard
                case 11:
2962 b7bcbe95 bellard
                    /* Compare with zero */
2963 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
2964 b7bcbe95 bellard
                    gen_vfp_F1_ld0(dp);
2965 b7bcbe95 bellard
                    break;
2966 9ee6e8bb pbrook
                case 20:
2967 9ee6e8bb pbrook
                case 21:
2968 9ee6e8bb pbrook
                case 22:
2969 9ee6e8bb pbrook
                case 23:
2970 644ad806 pbrook
                case 28:
2971 644ad806 pbrook
                case 29:
2972 644ad806 pbrook
                case 30:
2973 644ad806 pbrook
                case 31:
2974 9ee6e8bb pbrook
                    /* Source and destination the same.  */
2975 9ee6e8bb pbrook
                    gen_mov_F0_vreg(dp, rd);
2976 9ee6e8bb pbrook
                    break;
2977 b7bcbe95 bellard
                default:
2978 b7bcbe95 bellard
                    /* One source operand.  */
2979 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
2980 9ee6e8bb pbrook
                    break;
2981 b7bcbe95 bellard
                }
2982 b7bcbe95 bellard
            } else {
2983 b7bcbe95 bellard
                /* Two source operands.  */
2984 b7bcbe95 bellard
                gen_mov_F0_vreg(dp, rn);
2985 b7bcbe95 bellard
                gen_mov_F1_vreg(dp, rm);
2986 b7bcbe95 bellard
            }
2987 b7bcbe95 bellard
2988 b7bcbe95 bellard
            for (;;) {
2989 b7bcbe95 bellard
                /* Perform the calculation.  */
2990 b7bcbe95 bellard
                switch (op) {
2991 b7bcbe95 bellard
                case 0: /* mac: fd + (fn * fm) */
2992 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2993 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
2994 b7bcbe95 bellard
                    gen_vfp_add(dp);
2995 b7bcbe95 bellard
                    break;
2996 b7bcbe95 bellard
                case 1: /* nmac: fd - (fn * fm) */
2997 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2998 b7bcbe95 bellard
                    gen_vfp_neg(dp);
2999 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
3000 b7bcbe95 bellard
                    gen_vfp_add(dp);
3001 b7bcbe95 bellard
                    break;
3002 b7bcbe95 bellard
                case 2: /* msc: -fd + (fn * fm) */
3003 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3004 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
3005 b7bcbe95 bellard
                    gen_vfp_sub(dp);
3006 b7bcbe95 bellard
                    break;
3007 b7bcbe95 bellard
                case 3: /* nmsc: -fd - (fn * fm)  */
3008 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3009 b7bcbe95 bellard
                    gen_vfp_neg(dp);
3010 c9fb531a pbrook
                    gen_mov_F1_vreg(dp, rd);
3011 c9fb531a pbrook
                    gen_vfp_sub(dp);
3012 b7bcbe95 bellard
                    break;
3013 b7bcbe95 bellard
                case 4: /* mul: fn * fm */
3014 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3015 b7bcbe95 bellard
                    break;
3016 b7bcbe95 bellard
                case 5: /* nmul: -(fn * fm) */
3017 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3018 b7bcbe95 bellard
                    gen_vfp_neg(dp);
3019 b7bcbe95 bellard
                    break;
3020 b7bcbe95 bellard
                case 6: /* add: fn + fm */
3021 b7bcbe95 bellard
                    gen_vfp_add(dp);
3022 b7bcbe95 bellard
                    break;
3023 b7bcbe95 bellard
                case 7: /* sub: fn - fm */
3024 b7bcbe95 bellard
                    gen_vfp_sub(dp);
3025 b7bcbe95 bellard
                    break;
3026 b7bcbe95 bellard
                case 8: /* div: fn / fm */
3027 b7bcbe95 bellard
                    gen_vfp_div(dp);
3028 b7bcbe95 bellard
                    break;
3029 9ee6e8bb pbrook
                case 14: /* fconst */
3030 9ee6e8bb pbrook
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
3031 9ee6e8bb pbrook
                      return 1;
3032 9ee6e8bb pbrook
3033 9ee6e8bb pbrook
                    n = (insn << 12) & 0x80000000;
3034 9ee6e8bb pbrook
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
3035 9ee6e8bb pbrook
                    if (dp) {
3036 9ee6e8bb pbrook
                        if (i & 0x40)
3037 9ee6e8bb pbrook
                            i |= 0x3f80;
3038 9ee6e8bb pbrook
                        else
3039 9ee6e8bb pbrook
                            i |= 0x4000;
3040 9ee6e8bb pbrook
                        n |= i << 16;
3041 4373f3ce pbrook
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3042 9ee6e8bb pbrook
                    } else {
3043 9ee6e8bb pbrook
                        if (i & 0x40)
3044 9ee6e8bb pbrook
                            i |= 0x780;
3045 9ee6e8bb pbrook
                        else
3046 9ee6e8bb pbrook
                            i |= 0x800;
3047 9ee6e8bb pbrook
                        n |= i << 19;
3048 5b340b51 balrog
                        tcg_gen_movi_i32(cpu_F0s, n);
3049 9ee6e8bb pbrook
                    }
3050 9ee6e8bb pbrook
                    break;
3051 b7bcbe95 bellard
                case 15: /* extension space */
3052 b7bcbe95 bellard
                    switch (rn) {
3053 b7bcbe95 bellard
                    case 0: /* cpy */
3054 b7bcbe95 bellard
                        /* no-op */
3055 b7bcbe95 bellard
                        break;
3056 b7bcbe95 bellard
                    case 1: /* abs */
3057 b7bcbe95 bellard
                        gen_vfp_abs(dp);
3058 b7bcbe95 bellard
                        break;
3059 b7bcbe95 bellard
                    case 2: /* neg */
3060 b7bcbe95 bellard
                        gen_vfp_neg(dp);
3061 b7bcbe95 bellard
                        break;
3062 b7bcbe95 bellard
                    case 3: /* sqrt */
3063 b7bcbe95 bellard
                        gen_vfp_sqrt(dp);
3064 b7bcbe95 bellard
                        break;
3065 60011498 Paul Brook
                    case 4: /* vcvtb.f32.f16 */
3066 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3067 60011498 Paul Brook
                          return 1;
3068 60011498 Paul Brook
                        tmp = gen_vfp_mrs();
3069 60011498 Paul Brook
                        tcg_gen_ext16u_i32(tmp, tmp);
3070 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3071 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
3072 60011498 Paul Brook
                        break;
3073 60011498 Paul Brook
                    case 5: /* vcvtt.f32.f16 */
3074 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3075 60011498 Paul Brook
                          return 1;
3076 60011498 Paul Brook
                        tmp = gen_vfp_mrs();
3077 60011498 Paul Brook
                        tcg_gen_shri_i32(tmp, tmp, 16);
3078 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3079 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
3080 60011498 Paul Brook
                        break;
3081 60011498 Paul Brook
                    case 6: /* vcvtb.f16.f32 */
3082 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3083 60011498 Paul Brook
                          return 1;
3084 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
3085 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3086 60011498 Paul Brook
                        gen_mov_F0_vreg(0, rd);
3087 60011498 Paul Brook
                        tmp2 = gen_vfp_mrs();
3088 60011498 Paul Brook
                        tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3089 60011498 Paul Brook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
3090 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
3091 60011498 Paul Brook
                        gen_vfp_msr(tmp);
3092 60011498 Paul Brook
                        break;
3093 60011498 Paul Brook
                    case 7: /* vcvtt.f16.f32 */
3094 60011498 Paul Brook
                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3095 60011498 Paul Brook
                          return 1;
3096 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
3097 60011498 Paul Brook
                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3098 60011498 Paul Brook
                        tcg_gen_shli_i32(tmp, tmp, 16);
3099 60011498 Paul Brook
                        gen_mov_F0_vreg(0, rd);
3100 60011498 Paul Brook
                        tmp2 = gen_vfp_mrs();
3101 60011498 Paul Brook
                        tcg_gen_ext16u_i32(tmp2, tmp2);
3102 60011498 Paul Brook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
3103 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
3104 60011498 Paul Brook
                        gen_vfp_msr(tmp);
3105 60011498 Paul Brook
                        break;
3106 b7bcbe95 bellard
                    case 8: /* cmp */
3107 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3108 b7bcbe95 bellard
                        break;
3109 b7bcbe95 bellard
                    case 9: /* cmpe */
3110 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3111 b7bcbe95 bellard
                        break;
3112 b7bcbe95 bellard
                    case 10: /* cmpz */
3113 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3114 b7bcbe95 bellard
                        break;
3115 b7bcbe95 bellard
                    case 11: /* cmpez */
3116 b7bcbe95 bellard
                        gen_vfp_F1_ld0(dp);
3117 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3118 b7bcbe95 bellard
                        break;
3119 b7bcbe95 bellard
                    case 15: /* single<->double conversion */
3120 b7bcbe95 bellard
                        if (dp)
3121 4373f3ce pbrook
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3122 b7bcbe95 bellard
                        else
3123 4373f3ce pbrook
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3124 b7bcbe95 bellard
                        break;
3125 b7bcbe95 bellard
                    case 16: /* fuito */
3126 b7bcbe95 bellard
                        gen_vfp_uito(dp);
3127 b7bcbe95 bellard
                        break;
3128 b7bcbe95 bellard
                    case 17: /* fsito */
3129 b7bcbe95 bellard
                        gen_vfp_sito(dp);
3130 b7bcbe95 bellard
                        break;
3131 9ee6e8bb pbrook
                    case 20: /* fshto */
3132 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3133 9ee6e8bb pbrook
                          return 1;
3134 644ad806 pbrook
                        gen_vfp_shto(dp, 16 - rm);
3135 9ee6e8bb pbrook
                        break;
3136 9ee6e8bb pbrook
                    case 21: /* fslto */
3137 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3138 9ee6e8bb pbrook
                          return 1;
3139 644ad806 pbrook
                        gen_vfp_slto(dp, 32 - rm);
3140 9ee6e8bb pbrook
                        break;
3141 9ee6e8bb pbrook
                    case 22: /* fuhto */
3142 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3143 9ee6e8bb pbrook
                          return 1;
3144 644ad806 pbrook
                        gen_vfp_uhto(dp, 16 - rm);
3145 9ee6e8bb pbrook
                        break;
3146 9ee6e8bb pbrook
                    case 23: /* fulto */
3147 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3148 9ee6e8bb pbrook
                          return 1;
3149 644ad806 pbrook
                        gen_vfp_ulto(dp, 32 - rm);
3150 9ee6e8bb pbrook
                        break;
3151 b7bcbe95 bellard
                    case 24: /* ftoui */
3152 b7bcbe95 bellard
                        gen_vfp_toui(dp);
3153 b7bcbe95 bellard
                        break;
3154 b7bcbe95 bellard
                    case 25: /* ftouiz */
3155 b7bcbe95 bellard
                        gen_vfp_touiz(dp);
3156 b7bcbe95 bellard
                        break;
3157 b7bcbe95 bellard
                    case 26: /* ftosi */
3158 b7bcbe95 bellard
                        gen_vfp_tosi(dp);
3159 b7bcbe95 bellard
                        break;
3160 b7bcbe95 bellard
                    case 27: /* ftosiz */
3161 b7bcbe95 bellard
                        gen_vfp_tosiz(dp);
3162 b7bcbe95 bellard
                        break;
3163 9ee6e8bb pbrook
                    case 28: /* ftosh */
3164 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 9ee6e8bb pbrook
                          return 1;
3166 644ad806 pbrook
                        gen_vfp_tosh(dp, 16 - rm);
3167 9ee6e8bb pbrook
                        break;
3168 9ee6e8bb pbrook
                    case 29: /* ftosl */
3169 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3170 9ee6e8bb pbrook
                          return 1;
3171 644ad806 pbrook
                        gen_vfp_tosl(dp, 32 - rm);
3172 9ee6e8bb pbrook
                        break;
3173 9ee6e8bb pbrook
                    case 30: /* ftouh */
3174 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3175 9ee6e8bb pbrook
                          return 1;
3176 644ad806 pbrook
                        gen_vfp_touh(dp, 16 - rm);
3177 9ee6e8bb pbrook
                        break;
3178 9ee6e8bb pbrook
                    case 31: /* ftoul */
3179 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3180 9ee6e8bb pbrook
                          return 1;
3181 644ad806 pbrook
                        gen_vfp_toul(dp, 32 - rm);
3182 9ee6e8bb pbrook
                        break;
3183 b7bcbe95 bellard
                    default: /* undefined */
3184 b7bcbe95 bellard
                        printf ("rn:%d\n", rn);
3185 b7bcbe95 bellard
                        return 1;
3186 b7bcbe95 bellard
                    }
3187 b7bcbe95 bellard
                    break;
3188 b7bcbe95 bellard
                default: /* undefined */
3189 b7bcbe95 bellard
                    printf ("op:%d\n", op);
3190 b7bcbe95 bellard
                    return 1;
3191 b7bcbe95 bellard
                }
3192 b7bcbe95 bellard
3193 b7bcbe95 bellard
                /* Write back the result.  */
3194 b7bcbe95 bellard
                if (op == 15 && (rn >= 8 && rn <= 11))
3195 b7bcbe95 bellard
                    ; /* Comparison, do nothing.  */
3196 04595bf6 Peter Maydell
                else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3197 04595bf6 Peter Maydell
                    /* VCVT double to int: always integer result. */
3198 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rd);
3199 b7bcbe95 bellard
                else if (op == 15 && rn == 15)
3200 b7bcbe95 bellard
                    /* conversion */
3201 b7bcbe95 bellard
                    gen_mov_vreg_F0(!dp, rd);
3202 b7bcbe95 bellard
                else
3203 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3204 b7bcbe95 bellard
3205 b7bcbe95 bellard
                /* break out of the loop if we have finished  */
3206 b7bcbe95 bellard
                if (veclen == 0)
3207 b7bcbe95 bellard
                    break;
3208 b7bcbe95 bellard
3209 b7bcbe95 bellard
                if (op == 15 && delta_m == 0) {
3210 b7bcbe95 bellard
                    /* single source one-many */
3211 b7bcbe95 bellard
                    while (veclen--) {
3212 b7bcbe95 bellard
                        rd = ((rd + delta_d) & (bank_mask - 1))
3213 b7bcbe95 bellard
                             | (rd & bank_mask);
3214 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd);
3215 b7bcbe95 bellard
                    }
3216 b7bcbe95 bellard
                    break;
3217 b7bcbe95 bellard
                }
3218 b7bcbe95 bellard
                /* Setup the next operands.  */
3219 b7bcbe95 bellard
                veclen--;
3220 b7bcbe95 bellard
                rd = ((rd + delta_d) & (bank_mask - 1))
3221 b7bcbe95 bellard
                     | (rd & bank_mask);
3222 b7bcbe95 bellard
3223 b7bcbe95 bellard
                if (op == 15) {
3224 b7bcbe95 bellard
                    /* One source operand.  */
3225 b7bcbe95 bellard
                    rm = ((rm + delta_m) & (bank_mask - 1))
3226 b7bcbe95 bellard
                         | (rm & bank_mask);
3227 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
3228 b7bcbe95 bellard
                } else {
3229 b7bcbe95 bellard
                    /* Two source operands.  */
3230 b7bcbe95 bellard
                    rn = ((rn + delta_d) & (bank_mask - 1))
3231 b7bcbe95 bellard
                         | (rn & bank_mask);
3232 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rn);
3233 b7bcbe95 bellard
                    if (delta_m) {
3234 b7bcbe95 bellard
                        rm = ((rm + delta_m) & (bank_mask - 1))
3235 b7bcbe95 bellard
                             | (rm & bank_mask);
3236 b7bcbe95 bellard
                        gen_mov_F1_vreg(dp, rm);
3237 b7bcbe95 bellard
                    }
3238 b7bcbe95 bellard
                }
3239 b7bcbe95 bellard
            }
3240 b7bcbe95 bellard
        }
3241 b7bcbe95 bellard
        break;
3242 b7bcbe95 bellard
    case 0xc:
3243 b7bcbe95 bellard
    case 0xd:
3244 8387da81 Peter Maydell
        if ((insn & 0x03e00000) == 0x00400000) {
3245 b7bcbe95 bellard
            /* two-register transfer */
3246 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3247 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
3248 b7bcbe95 bellard
            if (dp) {
3249 9ee6e8bb pbrook
                VFP_DREG_M(rm, insn);
3250 9ee6e8bb pbrook
            } else {
3251 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
3252 9ee6e8bb pbrook
            }
3253 b7bcbe95 bellard
3254 18c9b560 balrog
            if (insn & ARM_CP_RW_BIT) {
3255 b7bcbe95 bellard
                /* vfp->arm */
3256 b7bcbe95 bellard
                if (dp) {
3257 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2);
3258 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3259 4373f3ce pbrook
                    store_reg(s, rd, tmp);
3260 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2 + 1);
3261 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3262 4373f3ce pbrook
                    store_reg(s, rn, tmp);
3263 b7bcbe95 bellard
                } else {
3264 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
3265 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3266 8387da81 Peter Maydell
                    store_reg(s, rd, tmp);
3267 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm + 1);
3268 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3269 8387da81 Peter Maydell
                    store_reg(s, rn, tmp);
3270 b7bcbe95 bellard
                }
3271 b7bcbe95 bellard
            } else {
3272 b7bcbe95 bellard
                /* arm->vfp */
3273 b7bcbe95 bellard
                if (dp) {
3274 4373f3ce pbrook
                    tmp = load_reg(s, rd);
3275 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3276 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2);
3277 4373f3ce pbrook
                    tmp = load_reg(s, rn);
3278 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3279 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2 + 1);
3280 b7bcbe95 bellard
                } else {
3281 8387da81 Peter Maydell
                    tmp = load_reg(s, rd);
3282 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3283 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm);
3284 8387da81 Peter Maydell
                    tmp = load_reg(s, rn);
3285 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3286 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm + 1);
3287 b7bcbe95 bellard
                }
3288 b7bcbe95 bellard
            }
3289 b7bcbe95 bellard
        } else {
3290 b7bcbe95 bellard
            /* Load/store */
3291 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3292 b7bcbe95 bellard
            if (dp)
3293 9ee6e8bb pbrook
                VFP_DREG_D(rd, insn);
3294 b7bcbe95 bellard
            else
3295 9ee6e8bb pbrook
                rd = VFP_SREG_D(insn);
3296 9ee6e8bb pbrook
            if (s->thumb && rn == 15) {
3297 7d1b0095 Peter Maydell
                addr = tcg_temp_new_i32();
3298 312eea9f Filip Navara
                tcg_gen_movi_i32(addr, s->pc & ~2);
3299 9ee6e8bb pbrook
            } else {
3300 312eea9f Filip Navara
                addr = load_reg(s, rn);
3301 9ee6e8bb pbrook
            }
3302 b7bcbe95 bellard
            if ((insn & 0x01200000) == 0x01000000) {
3303 b7bcbe95 bellard
                /* Single load/store */
3304 b7bcbe95 bellard
                offset = (insn & 0xff) << 2;
3305 b7bcbe95 bellard
                if ((insn & (1 << 23)) == 0)
3306 b7bcbe95 bellard
                    offset = -offset;
3307 312eea9f Filip Navara
                tcg_gen_addi_i32(addr, addr, offset);
3308 b7bcbe95 bellard
                if (insn & (1 << 20)) {
3309 312eea9f Filip Navara
                    gen_vfp_ld(s, dp, addr);
3310 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3311 b7bcbe95 bellard
                } else {
3312 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
3313 312eea9f Filip Navara
                    gen_vfp_st(s, dp, addr);
3314 b7bcbe95 bellard
                }
3315 7d1b0095 Peter Maydell
                tcg_temp_free_i32(addr);
3316 b7bcbe95 bellard
            } else {
3317 b7bcbe95 bellard
                /* load/store multiple */
3318 b7bcbe95 bellard
                if (dp)
3319 b7bcbe95 bellard
                    n = (insn >> 1) & 0x7f;
3320 b7bcbe95 bellard
                else
3321 b7bcbe95 bellard
                    n = insn & 0xff;
3322 b7bcbe95 bellard
3323 b7bcbe95 bellard
                if (insn & (1 << 24)) /* pre-decrement */
3324 312eea9f Filip Navara
                    tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3325 b7bcbe95 bellard
3326 b7bcbe95 bellard
                if (dp)
3327 b7bcbe95 bellard
                    offset = 8;
3328 b7bcbe95 bellard
                else
3329 b7bcbe95 bellard
                    offset = 4;
3330 b7bcbe95 bellard
                for (i = 0; i < n; i++) {
3331 18c9b560 balrog
                    if (insn & ARM_CP_RW_BIT) {
3332 b7bcbe95 bellard
                        /* load */
3333 312eea9f Filip Navara
                        gen_vfp_ld(s, dp, addr);
3334 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd + i);
3335 b7bcbe95 bellard
                    } else {
3336 b7bcbe95 bellard
                        /* store */
3337 b7bcbe95 bellard
                        gen_mov_F0_vreg(dp, rd + i);
3338 312eea9f Filip Navara
                        gen_vfp_st(s, dp, addr);
3339 b7bcbe95 bellard
                    }
3340 312eea9f Filip Navara
                    tcg_gen_addi_i32(addr, addr, offset);
3341 b7bcbe95 bellard
                }
3342 b7bcbe95 bellard
                if (insn & (1 << 21)) {
3343 b7bcbe95 bellard
                    /* writeback */
3344 b7bcbe95 bellard
                    if (insn & (1 << 24))
3345 b7bcbe95 bellard
                        offset = -offset * n;
3346 b7bcbe95 bellard
                    else if (dp && (insn & 1))
3347 b7bcbe95 bellard
                        offset = 4;
3348 b7bcbe95 bellard
                    else
3349 b7bcbe95 bellard
                        offset = 0;
3350 b7bcbe95 bellard
3351 b7bcbe95 bellard
                    if (offset != 0)
3352 312eea9f Filip Navara
                        tcg_gen_addi_i32(addr, addr, offset);
3353 312eea9f Filip Navara
                    store_reg(s, rn, addr);
3354 312eea9f Filip Navara
                } else {
3355 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(addr);
3356 b7bcbe95 bellard
                }
3357 b7bcbe95 bellard
            }
3358 b7bcbe95 bellard
        }
3359 b7bcbe95 bellard
        break;
3360 b7bcbe95 bellard
    default:
3361 b7bcbe95 bellard
        /* Should never happen.  */
3362 b7bcbe95 bellard
        return 1;
3363 b7bcbe95 bellard
    }
3364 b7bcbe95 bellard
    return 0;
3365 b7bcbe95 bellard
}
3366 b7bcbe95 bellard
3367 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3368 c53be334 bellard
{
3369 6e256c93 bellard
    TranslationBlock *tb;
3370 6e256c93 bellard
3371 6e256c93 bellard
    tb = s->tb;
3372 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3373 57fec1fe bellard
        tcg_gen_goto_tb(n);
3374 8984bd2e pbrook
        gen_set_pc_im(dest);
3375 57fec1fe bellard
        tcg_gen_exit_tb((long)tb + n);
3376 6e256c93 bellard
    } else {
3377 8984bd2e pbrook
        gen_set_pc_im(dest);
3378 57fec1fe bellard
        tcg_gen_exit_tb(0);
3379 6e256c93 bellard
    }
3380 c53be334 bellard
}
3381 c53be334 bellard
3382 8aaca4c0 bellard
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3383 8aaca4c0 bellard
{
3384 551bd27f ths
    if (unlikely(s->singlestep_enabled)) {
3385 8aaca4c0 bellard
        /* An indirect jump so that we still trigger the debug exception.  */
3386 5899f386 bellard
        if (s->thumb)
3387 d9ba4830 pbrook
            dest |= 1;
3388 d9ba4830 pbrook
        gen_bx_im(s, dest);
3389 8aaca4c0 bellard
    } else {
3390 6e256c93 bellard
        gen_goto_tb(s, 0, dest);
3391 8aaca4c0 bellard
        s->is_jmp = DISAS_TB_JUMP;
3392 8aaca4c0 bellard
    }
3393 8aaca4c0 bellard
}
3394 8aaca4c0 bellard
3395 d9ba4830 pbrook
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3396 b5ff1b31 bellard
{
3397 ee097184 bellard
    if (x)
3398 d9ba4830 pbrook
        tcg_gen_sari_i32(t0, t0, 16);
3399 b5ff1b31 bellard
    else
3400 d9ba4830 pbrook
        gen_sxth(t0);
3401 ee097184 bellard
    if (y)
3402 d9ba4830 pbrook
        tcg_gen_sari_i32(t1, t1, 16);
3403 b5ff1b31 bellard
    else
3404 d9ba4830 pbrook
        gen_sxth(t1);
3405 d9ba4830 pbrook
    tcg_gen_mul_i32(t0, t0, t1);
3406 b5ff1b31 bellard
}
3407 b5ff1b31 bellard
3408 b5ff1b31 bellard
/* Return the mask of PSR bits set by a MSR instruction.  */
3409 9ee6e8bb pbrook
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3410 b5ff1b31 bellard
    uint32_t mask;
3411 b5ff1b31 bellard
3412 b5ff1b31 bellard
    mask = 0;
3413 b5ff1b31 bellard
    if (flags & (1 << 0))
3414 b5ff1b31 bellard
        mask |= 0xff;
3415 b5ff1b31 bellard
    if (flags & (1 << 1))
3416 b5ff1b31 bellard
        mask |= 0xff00;
3417 b5ff1b31 bellard
    if (flags & (1 << 2))
3418 b5ff1b31 bellard
        mask |= 0xff0000;
3419 b5ff1b31 bellard
    if (flags & (1 << 3))
3420 b5ff1b31 bellard
        mask |= 0xff000000;
3421 9ee6e8bb pbrook
3422 2ae23e75 pbrook
    /* Mask out undefined bits.  */
3423 9ee6e8bb pbrook
    mask &= ~CPSR_RESERVED;
3424 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_V6))
3425 e160c51c pbrook
        mask &= ~(CPSR_E | CPSR_GE);
3426 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3427 e160c51c pbrook
        mask &= ~CPSR_IT;
3428 9ee6e8bb pbrook
    /* Mask out execution state bits.  */
3429 2ae23e75 pbrook
    if (!spsr)
3430 e160c51c pbrook
        mask &= ~CPSR_EXEC;
3431 b5ff1b31 bellard
    /* Mask out privileged bits.  */
3432 b5ff1b31 bellard
    if (IS_USER(s))
3433 9ee6e8bb pbrook
        mask &= CPSR_USER;
3434 b5ff1b31 bellard
    return mask;
3435 b5ff1b31 bellard
}
3436 b5ff1b31 bellard
3437 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3438 2fbac54b Filip Navara
static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3439 b5ff1b31 bellard
{
3440 d9ba4830 pbrook
    TCGv tmp;
3441 b5ff1b31 bellard
    if (spsr) {
3442 b5ff1b31 bellard
        /* ??? This is also undefined in system mode.  */
3443 b5ff1b31 bellard
        if (IS_USER(s))
3444 b5ff1b31 bellard
            return 1;
3445 d9ba4830 pbrook
3446 d9ba4830 pbrook
        tmp = load_cpu_field(spsr);
3447 d9ba4830 pbrook
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3448 2fbac54b Filip Navara
        tcg_gen_andi_i32(t0, t0, mask);
3449 2fbac54b Filip Navara
        tcg_gen_or_i32(tmp, tmp, t0);
3450 d9ba4830 pbrook
        store_cpu_field(tmp, spsr);
3451 b5ff1b31 bellard
    } else {
3452 2fbac54b Filip Navara
        gen_set_cpsr(t0, mask);
3453 b5ff1b31 bellard
    }
3454 7d1b0095 Peter Maydell
    tcg_temp_free_i32(t0);
3455 b5ff1b31 bellard
    gen_lookup_tb(s);
3456 b5ff1b31 bellard
    return 0;
3457 b5ff1b31 bellard
}
3458 b5ff1b31 bellard
3459 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted.  */
3460 2fbac54b Filip Navara
static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3461 2fbac54b Filip Navara
{
3462 2fbac54b Filip Navara
    TCGv tmp;
3463 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
3464 2fbac54b Filip Navara
    tcg_gen_movi_i32(tmp, val);
3465 2fbac54b Filip Navara
    return gen_set_psr(s, mask, spsr, tmp);
3466 2fbac54b Filip Navara
}
3467 2fbac54b Filip Navara
3468 e9bb4aa9 Juha Riihimรคki
/* Generate an old-style exception return. Marks pc as dead. */
3469 e9bb4aa9 Juha Riihimรคki
static void gen_exception_return(DisasContext *s, TCGv pc)
3470 b5ff1b31 bellard
{
3471 d9ba4830 pbrook
    TCGv tmp;
3472 e9bb4aa9 Juha Riihimรคki
    store_reg(s, 15, pc);
3473 d9ba4830 pbrook
    tmp = load_cpu_field(spsr);
3474 d9ba4830 pbrook
    gen_set_cpsr(tmp, 0xffffffff);
3475 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3476 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
3477 b5ff1b31 bellard
}
3478 b5ff1b31 bellard
3479 b0109805 pbrook
/* Generate a v6 exception return.  Marks both values as dead.  */
3480 b0109805 pbrook
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3481 2c0262af bellard
{
3482 b0109805 pbrook
    gen_set_cpsr(cpsr, 0xffffffff);
3483 7d1b0095 Peter Maydell
    tcg_temp_free_i32(cpsr);
3484 b0109805 pbrook
    store_reg(s, 15, pc);
3485 9ee6e8bb pbrook
    s->is_jmp = DISAS_UPDATE;
3486 9ee6e8bb pbrook
}
3487 3b46e624 ths
3488 9ee6e8bb pbrook
static inline void
3489 9ee6e8bb pbrook
gen_set_condexec (DisasContext *s)
3490 9ee6e8bb pbrook
{
3491 9ee6e8bb pbrook
    if (s->condexec_mask) {
3492 8f01245e pbrook
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3493 7d1b0095 Peter Maydell
        TCGv tmp = tcg_temp_new_i32();
3494 8f01245e pbrook
        tcg_gen_movi_i32(tmp, val);
3495 d9ba4830 pbrook
        store_cpu_field(tmp, condexec_bits);
3496 9ee6e8bb pbrook
    }
3497 9ee6e8bb pbrook
}
3498 3b46e624 ths
3499 bc4a0de0 Peter Maydell
static void gen_exception_insn(DisasContext *s, int offset, int excp)
3500 bc4a0de0 Peter Maydell
{
3501 bc4a0de0 Peter Maydell
    gen_set_condexec(s);
3502 bc4a0de0 Peter Maydell
    gen_set_pc_im(s->pc - offset);
3503 bc4a0de0 Peter Maydell
    gen_exception(excp);
3504 bc4a0de0 Peter Maydell
    s->is_jmp = DISAS_JUMP;
3505 bc4a0de0 Peter Maydell
}
3506 bc4a0de0 Peter Maydell
3507 9ee6e8bb pbrook
static void gen_nop_hint(DisasContext *s, int val)
3508 9ee6e8bb pbrook
{
3509 9ee6e8bb pbrook
    switch (val) {
3510 9ee6e8bb pbrook
    case 3: /* wfi */
3511 8984bd2e pbrook
        gen_set_pc_im(s->pc);
3512 9ee6e8bb pbrook
        s->is_jmp = DISAS_WFI;
3513 9ee6e8bb pbrook
        break;
3514 9ee6e8bb pbrook
    case 2: /* wfe */
3515 9ee6e8bb pbrook
    case 4: /* sev */
3516 9ee6e8bb pbrook
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3517 9ee6e8bb pbrook
    default: /* nop */
3518 9ee6e8bb pbrook
        break;
3519 9ee6e8bb pbrook
    }
3520 9ee6e8bb pbrook
}
3521 99c475ab bellard
3522 ad69471c pbrook
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3523 9ee6e8bb pbrook
3524 dd8fbd78 Filip Navara
static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3525 9ee6e8bb pbrook
{
3526 9ee6e8bb pbrook
    switch (size) {
3527 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3528 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3529 dd8fbd78 Filip Navara
    case 2: tcg_gen_add_i32(t0, t0, t1); break;
3530 9ee6e8bb pbrook
    default: return 1;
3531 9ee6e8bb pbrook
    }
3532 9ee6e8bb pbrook
    return 0;
3533 9ee6e8bb pbrook
}
3534 9ee6e8bb pbrook
3535 dd8fbd78 Filip Navara
static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3536 ad69471c pbrook
{
3537 ad69471c pbrook
    switch (size) {
3538 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3539 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3540 dd8fbd78 Filip Navara
    case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3541 ad69471c pbrook
    default: return;
3542 ad69471c pbrook
    }
3543 ad69471c pbrook
}
3544 ad69471c pbrook
3545 ad69471c pbrook
/* 32-bit pairwise ops end up the same as the elementwise versions.  */
3546 ad69471c pbrook
#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
3547 ad69471c pbrook
#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
3548 ad69471c pbrook
#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
3549 ad69471c pbrook
#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
3550 ad69471c pbrook
3551 ad69471c pbrook
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3552 ad69471c pbrook
    switch ((size << 1) | u) { \
3553 ad69471c pbrook
    case 0: \
3554 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3555 ad69471c pbrook
        break; \
3556 ad69471c pbrook
    case 1: \
3557 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3558 ad69471c pbrook
        break; \
3559 ad69471c pbrook
    case 2: \
3560 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3561 ad69471c pbrook
        break; \
3562 ad69471c pbrook
    case 3: \
3563 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3564 ad69471c pbrook
        break; \
3565 ad69471c pbrook
    case 4: \
3566 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3567 ad69471c pbrook
        break; \
3568 ad69471c pbrook
    case 5: \
3569 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3570 ad69471c pbrook
        break; \
3571 ad69471c pbrook
    default: return 1; \
3572 ad69471c pbrook
    }} while (0)
3573 9ee6e8bb pbrook
3574 9ee6e8bb pbrook
#define GEN_NEON_INTEGER_OP(name) do { \
3575 9ee6e8bb pbrook
    switch ((size << 1) | u) { \
3576 ad69471c pbrook
    case 0: \
3577 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3578 ad69471c pbrook
        break; \
3579 ad69471c pbrook
    case 1: \
3580 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3581 ad69471c pbrook
        break; \
3582 ad69471c pbrook
    case 2: \
3583 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3584 ad69471c pbrook
        break; \
3585 ad69471c pbrook
    case 3: \
3586 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3587 ad69471c pbrook
        break; \
3588 ad69471c pbrook
    case 4: \
3589 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3590 ad69471c pbrook
        break; \
3591 ad69471c pbrook
    case 5: \
3592 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3593 ad69471c pbrook
        break; \
3594 9ee6e8bb pbrook
    default: return 1; \
3595 9ee6e8bb pbrook
    }} while (0)
3596 9ee6e8bb pbrook
3597 dd8fbd78 Filip Navara
static TCGv neon_load_scratch(int scratch)
3598 9ee6e8bb pbrook
{
3599 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
3600 dd8fbd78 Filip Navara
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3601 dd8fbd78 Filip Navara
    return tmp;
3602 9ee6e8bb pbrook
}
3603 9ee6e8bb pbrook
3604 dd8fbd78 Filip Navara
static void neon_store_scratch(int scratch, TCGv var)
3605 9ee6e8bb pbrook
{
3606 dd8fbd78 Filip Navara
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3607 7d1b0095 Peter Maydell
    tcg_temp_free_i32(var);
3608 9ee6e8bb pbrook
}
3609 9ee6e8bb pbrook
3610 dd8fbd78 Filip Navara
static inline TCGv neon_get_scalar(int size, int reg)
3611 9ee6e8bb pbrook
{
3612 dd8fbd78 Filip Navara
    TCGv tmp;
3613 9ee6e8bb pbrook
    if (size == 1) {
3614 0fad6efc Peter Maydell
        tmp = neon_load_reg(reg & 7, reg >> 4);
3615 0fad6efc Peter Maydell
        if (reg & 8) {
3616 dd8fbd78 Filip Navara
            gen_neon_dup_high16(tmp);
3617 0fad6efc Peter Maydell
        } else {
3618 0fad6efc Peter Maydell
            gen_neon_dup_low16(tmp);
3619 dd8fbd78 Filip Navara
        }
3620 0fad6efc Peter Maydell
    } else {
3621 0fad6efc Peter Maydell
        tmp = neon_load_reg(reg & 15, reg >> 4);
3622 9ee6e8bb pbrook
    }
3623 dd8fbd78 Filip Navara
    return tmp;
3624 9ee6e8bb pbrook
}
3625 9ee6e8bb pbrook
3626 02acedf9 Peter Maydell
static int gen_neon_unzip(int rd, int rm, int size, int q)
3627 19457615 Filip Navara
{
3628 02acedf9 Peter Maydell
    TCGv tmp, tmp2;
3629 02acedf9 Peter Maydell
    if (size == 3 || (!q && size == 2)) {
3630 02acedf9 Peter Maydell
        return 1;
3631 02acedf9 Peter Maydell
    }
3632 02acedf9 Peter Maydell
    tmp = tcg_const_i32(rd);
3633 02acedf9 Peter Maydell
    tmp2 = tcg_const_i32(rm);
3634 02acedf9 Peter Maydell
    if (q) {
3635 02acedf9 Peter Maydell
        switch (size) {
3636 02acedf9 Peter Maydell
        case 0:
3637 02acedf9 Peter Maydell
            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3638 02acedf9 Peter Maydell
            break;
3639 02acedf9 Peter Maydell
        case 1:
3640 02acedf9 Peter Maydell
            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3641 02acedf9 Peter Maydell
            break;
3642 02acedf9 Peter Maydell
        case 2:
3643 02acedf9 Peter Maydell
            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3644 02acedf9 Peter Maydell
            break;
3645 02acedf9 Peter Maydell
        default:
3646 02acedf9 Peter Maydell
            abort();
3647 02acedf9 Peter Maydell
        }
3648 02acedf9 Peter Maydell
    } else {
3649 02acedf9 Peter Maydell
        switch (size) {
3650 02acedf9 Peter Maydell
        case 0:
3651 02acedf9 Peter Maydell
            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3652 02acedf9 Peter Maydell
            break;
3653 02acedf9 Peter Maydell
        case 1:
3654 02acedf9 Peter Maydell
            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3655 02acedf9 Peter Maydell
            break;
3656 02acedf9 Peter Maydell
        default:
3657 02acedf9 Peter Maydell
            abort();
3658 02acedf9 Peter Maydell
        }
3659 02acedf9 Peter Maydell
    }
3660 02acedf9 Peter Maydell
    tcg_temp_free_i32(tmp);
3661 02acedf9 Peter Maydell
    tcg_temp_free_i32(tmp2);
3662 02acedf9 Peter Maydell
    return 0;
3663 19457615 Filip Navara
}
3664 19457615 Filip Navara
3665 d68a6f3a Peter Maydell
static int gen_neon_zip(int rd, int rm, int size, int q)
3666 19457615 Filip Navara
{
3667 19457615 Filip Navara
    TCGv tmp, tmp2;
3668 d68a6f3a Peter Maydell
    if (size == 3 || (!q && size == 2)) {
3669 d68a6f3a Peter Maydell
        return 1;
3670 d68a6f3a Peter Maydell
    }
3671 d68a6f3a Peter Maydell
    tmp = tcg_const_i32(rd);
3672 d68a6f3a Peter Maydell
    tmp2 = tcg_const_i32(rm);
3673 d68a6f3a Peter Maydell
    if (q) {
3674 d68a6f3a Peter Maydell
        switch (size) {
3675 d68a6f3a Peter Maydell
        case 0:
3676 d68a6f3a Peter Maydell
            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3677 d68a6f3a Peter Maydell
            break;
3678 d68a6f3a Peter Maydell
        case 1:
3679 d68a6f3a Peter Maydell
            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3680 d68a6f3a Peter Maydell
            break;
3681 d68a6f3a Peter Maydell
        case 2:
3682 d68a6f3a Peter Maydell
            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3683 d68a6f3a Peter Maydell
            break;
3684 d68a6f3a Peter Maydell
        default:
3685 d68a6f3a Peter Maydell
            abort();
3686 d68a6f3a Peter Maydell
        }
3687 d68a6f3a Peter Maydell
    } else {
3688 d68a6f3a Peter Maydell
        switch (size) {
3689 d68a6f3a Peter Maydell
        case 0:
3690 d68a6f3a Peter Maydell
            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3691 d68a6f3a Peter Maydell
            break;
3692 d68a6f3a Peter Maydell
        case 1:
3693 d68a6f3a Peter Maydell
            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3694 d68a6f3a Peter Maydell
            break;
3695 d68a6f3a Peter Maydell
        default:
3696 d68a6f3a Peter Maydell
            abort();
3697 d68a6f3a Peter Maydell
        }
3698 d68a6f3a Peter Maydell
    }
3699 d68a6f3a Peter Maydell
    tcg_temp_free_i32(tmp);
3700 d68a6f3a Peter Maydell
    tcg_temp_free_i32(tmp2);
3701 d68a6f3a Peter Maydell
    return 0;
3702 19457615 Filip Navara
}
3703 19457615 Filip Navara
3704 19457615 Filip Navara
static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3705 19457615 Filip Navara
{
3706 19457615 Filip Navara
    TCGv rd, tmp;
3707 19457615 Filip Navara
3708 7d1b0095 Peter Maydell
    rd = tcg_temp_new_i32();
3709 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
3710 19457615 Filip Navara
3711 19457615 Filip Navara
    tcg_gen_shli_i32(rd, t0, 8);
3712 19457615 Filip Navara
    tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3713 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3714 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3715 19457615 Filip Navara
3716 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 8);
3717 19457615 Filip Navara
    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3718 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3719 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3720 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3721 19457615 Filip Navara
3722 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3723 7d1b0095 Peter Maydell
    tcg_temp_free_i32(rd);
3724 19457615 Filip Navara
}
3725 19457615 Filip Navara
3726 19457615 Filip Navara
static void gen_neon_trn_u16(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, 16);
3734 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0xffff);
3735 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3736 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 16);
3737 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3738 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3739 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3740 19457615 Filip Navara
3741 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
3742 7d1b0095 Peter Maydell
    tcg_temp_free_i32(rd);
3743 19457615 Filip Navara
}
3744 19457615 Filip Navara
3745 19457615 Filip Navara
3746 9ee6e8bb pbrook
static struct {
3747 9ee6e8bb pbrook
    int nregs;
3748 9ee6e8bb pbrook
    int interleave;
3749 9ee6e8bb pbrook
    int spacing;
3750 9ee6e8bb pbrook
} neon_ls_element_type[11] = {
3751 9ee6e8bb pbrook
    {4, 4, 1},
3752 9ee6e8bb pbrook
    {4, 4, 2},
3753 9ee6e8bb pbrook
    {4, 1, 1},
3754 9ee6e8bb pbrook
    {4, 2, 1},
3755 9ee6e8bb pbrook
    {3, 3, 1},
3756 9ee6e8bb pbrook
    {3, 3, 2},
3757 9ee6e8bb pbrook
    {3, 1, 1},
3758 9ee6e8bb pbrook
    {1, 1, 1},
3759 9ee6e8bb pbrook
    {2, 2, 1},
3760 9ee6e8bb pbrook
    {2, 2, 2},
3761 9ee6e8bb pbrook
    {2, 1, 1}
3762 9ee6e8bb pbrook
};
3763 9ee6e8bb pbrook
3764 9ee6e8bb pbrook
/* Translate a NEON load/store element instruction.  Return nonzero if the
3765 9ee6e8bb pbrook
   instruction is invalid.  */
3766 9ee6e8bb pbrook
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3767 9ee6e8bb pbrook
{
3768 9ee6e8bb pbrook
    int rd, rn, rm;
3769 9ee6e8bb pbrook
    int op;
3770 9ee6e8bb pbrook
    int nregs;
3771 9ee6e8bb pbrook
    int interleave;
3772 84496233 Juha Riihimรคki
    int spacing;
3773 9ee6e8bb pbrook
    int stride;
3774 9ee6e8bb pbrook
    int size;
3775 9ee6e8bb pbrook
    int reg;
3776 9ee6e8bb pbrook
    int pass;
3777 9ee6e8bb pbrook
    int load;
3778 9ee6e8bb pbrook
    int shift;
3779 9ee6e8bb pbrook
    int n;
3780 1b2b1e54 Filip Navara
    TCGv addr;
3781 b0109805 pbrook
    TCGv tmp;
3782 8f8e3aa4 pbrook
    TCGv tmp2;
3783 84496233 Juha Riihimรคki
    TCGv_i64 tmp64;
3784 9ee6e8bb pbrook
3785 5df8bac1 Peter Maydell
    if (!s->vfp_enabled)
3786 9ee6e8bb pbrook
      return 1;
3787 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
3788 9ee6e8bb pbrook
    rn = (insn >> 16) & 0xf;
3789 9ee6e8bb pbrook
    rm = insn & 0xf;
3790 9ee6e8bb pbrook
    load = (insn & (1 << 21)) != 0;
3791 7d1b0095 Peter Maydell
    addr = tcg_temp_new_i32();
3792 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
3793 9ee6e8bb pbrook
        /* Load store all elements.  */
3794 9ee6e8bb pbrook
        op = (insn >> 8) & 0xf;
3795 9ee6e8bb pbrook
        size = (insn >> 6) & 3;
3796 84496233 Juha Riihimรคki
        if (op > 10)
3797 9ee6e8bb pbrook
            return 1;
3798 9ee6e8bb pbrook
        nregs = neon_ls_element_type[op].nregs;
3799 9ee6e8bb pbrook
        interleave = neon_ls_element_type[op].interleave;
3800 84496233 Juha Riihimรคki
        spacing = neon_ls_element_type[op].spacing;
3801 84496233 Juha Riihimรคki
        if (size == 3 && (interleave | spacing) != 1)
3802 84496233 Juha Riihimรคki
            return 1;
3803 dcc65026 Aurelien Jarno
        load_reg_var(s, addr, rn);
3804 9ee6e8bb pbrook
        stride = (1 << size) * interleave;
3805 9ee6e8bb pbrook
        for (reg = 0; reg < nregs; reg++) {
3806 9ee6e8bb pbrook
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3807 dcc65026 Aurelien Jarno
                load_reg_var(s, addr, rn);
3808 dcc65026 Aurelien Jarno
                tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3809 9ee6e8bb pbrook
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3810 dcc65026 Aurelien Jarno
                load_reg_var(s, addr, rn);
3811 dcc65026 Aurelien Jarno
                tcg_gen_addi_i32(addr, addr, 1 << size);
3812 9ee6e8bb pbrook
            }
3813 84496233 Juha Riihimรคki
            if (size == 3) {
3814 84496233 Juha Riihimรคki
                if (load) {
3815 84496233 Juha Riihimรคki
                    tmp64 = gen_ld64(addr, IS_USER(s));
3816 84496233 Juha Riihimรคki
                    neon_store_reg64(tmp64, rd);
3817 84496233 Juha Riihimรคki
                    tcg_temp_free_i64(tmp64);
3818 84496233 Juha Riihimรคki
                } else {
3819 84496233 Juha Riihimรคki
                    tmp64 = tcg_temp_new_i64();
3820 84496233 Juha Riihimรคki
                    neon_load_reg64(tmp64, rd);
3821 84496233 Juha Riihimรคki
                    gen_st64(tmp64, addr, IS_USER(s));
3822 84496233 Juha Riihimรคki
                }
3823 84496233 Juha Riihimรคki
                tcg_gen_addi_i32(addr, addr, stride);
3824 84496233 Juha Riihimรคki
            } else {
3825 84496233 Juha Riihimรคki
                for (pass = 0; pass < 2; pass++) {
3826 84496233 Juha Riihimรคki
                    if (size == 2) {
3827 84496233 Juha Riihimรคki
                        if (load) {
3828 84496233 Juha Riihimรคki
                            tmp = gen_ld32(addr, IS_USER(s));
3829 84496233 Juha Riihimรคki
                            neon_store_reg(rd, pass, tmp);
3830 84496233 Juha Riihimรคki
                        } else {
3831 84496233 Juha Riihimรคki
                            tmp = neon_load_reg(rd, pass);
3832 84496233 Juha Riihimรคki
                            gen_st32(tmp, addr, IS_USER(s));
3833 84496233 Juha Riihimรคki
                        }
3834 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3835 84496233 Juha Riihimรคki
                    } else if (size == 1) {
3836 84496233 Juha Riihimรคki
                        if (load) {
3837 84496233 Juha Riihimรคki
                            tmp = gen_ld16u(addr, IS_USER(s));
3838 84496233 Juha Riihimรคki
                            tcg_gen_addi_i32(addr, addr, stride);
3839 84496233 Juha Riihimรคki
                            tmp2 = gen_ld16u(addr, IS_USER(s));
3840 84496233 Juha Riihimรคki
                            tcg_gen_addi_i32(addr, addr, stride);
3841 41ba8341 Paul Brook
                            tcg_gen_shli_i32(tmp2, tmp2, 16);
3842 41ba8341 Paul Brook
                            tcg_gen_or_i32(tmp, tmp, tmp2);
3843 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
3844 84496233 Juha Riihimรคki
                            neon_store_reg(rd, pass, tmp);
3845 84496233 Juha Riihimรคki
                        } else {
3846 84496233 Juha Riihimรคki
                            tmp = neon_load_reg(rd, pass);
3847 7d1b0095 Peter Maydell
                            tmp2 = tcg_temp_new_i32();
3848 84496233 Juha Riihimรคki
                            tcg_gen_shri_i32(tmp2, tmp, 16);
3849 84496233 Juha Riihimรคki
                            gen_st16(tmp, addr, IS_USER(s));
3850 84496233 Juha Riihimรคki
                            tcg_gen_addi_i32(addr, addr, stride);
3851 84496233 Juha Riihimรคki
                            gen_st16(tmp2, addr, IS_USER(s));
3852 1b2b1e54 Filip Navara
                            tcg_gen_addi_i32(addr, addr, stride);
3853 9ee6e8bb pbrook
                        }
3854 84496233 Juha Riihimรคki
                    } else /* size == 0 */ {
3855 84496233 Juha Riihimรคki
                        if (load) {
3856 84496233 Juha Riihimรคki
                            TCGV_UNUSED(tmp2);
3857 84496233 Juha Riihimรคki
                            for (n = 0; n < 4; n++) {
3858 84496233 Juha Riihimรคki
                                tmp = gen_ld8u(addr, IS_USER(s));
3859 84496233 Juha Riihimรคki
                                tcg_gen_addi_i32(addr, addr, stride);
3860 84496233 Juha Riihimรคki
                                if (n == 0) {
3861 84496233 Juha Riihimรคki
                                    tmp2 = tmp;
3862 84496233 Juha Riihimรคki
                                } else {
3863 41ba8341 Paul Brook
                                    tcg_gen_shli_i32(tmp, tmp, n * 8);
3864 41ba8341 Paul Brook
                                    tcg_gen_or_i32(tmp2, tmp2, tmp);
3865 7d1b0095 Peter Maydell
                                    tcg_temp_free_i32(tmp);
3866 84496233 Juha Riihimรคki
                                }
3867 9ee6e8bb pbrook
                            }
3868 84496233 Juha Riihimรคki
                            neon_store_reg(rd, pass, tmp2);
3869 84496233 Juha Riihimรคki
                        } else {
3870 84496233 Juha Riihimรคki
                            tmp2 = neon_load_reg(rd, pass);
3871 84496233 Juha Riihimรคki
                            for (n = 0; n < 4; n++) {
3872 7d1b0095 Peter Maydell
                                tmp = tcg_temp_new_i32();
3873 84496233 Juha Riihimรคki
                                if (n == 0) {
3874 84496233 Juha Riihimรคki
                                    tcg_gen_mov_i32(tmp, tmp2);
3875 84496233 Juha Riihimรคki
                                } else {
3876 84496233 Juha Riihimรคki
                                    tcg_gen_shri_i32(tmp, tmp2, n * 8);
3877 84496233 Juha Riihimรคki
                                }
3878 84496233 Juha Riihimรคki
                                gen_st8(tmp, addr, IS_USER(s));
3879 84496233 Juha Riihimรคki
                                tcg_gen_addi_i32(addr, addr, stride);
3880 84496233 Juha Riihimรคki
                            }
3881 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
3882 9ee6e8bb pbrook
                        }
3883 9ee6e8bb pbrook
                    }
3884 9ee6e8bb pbrook
                }
3885 9ee6e8bb pbrook
            }
3886 84496233 Juha Riihimรคki
            rd += spacing;
3887 9ee6e8bb pbrook
        }
3888 9ee6e8bb pbrook
        stride = nregs * 8;
3889 9ee6e8bb pbrook
    } else {
3890 9ee6e8bb pbrook
        size = (insn >> 10) & 3;
3891 9ee6e8bb pbrook
        if (size == 3) {
3892 9ee6e8bb pbrook
            /* Load single element to all lanes.  */
3893 9ee6e8bb pbrook
            if (!load)
3894 9ee6e8bb pbrook
                return 1;
3895 9ee6e8bb pbrook
            size = (insn >> 6) & 3;
3896 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
3897 9ee6e8bb pbrook
            stride = (insn & (1 << 5)) ? 2 : 1;
3898 dcc65026 Aurelien Jarno
            load_reg_var(s, addr, rn);
3899 9ee6e8bb pbrook
            for (reg = 0; reg < nregs; reg++) {
3900 9ee6e8bb pbrook
                switch (size) {
3901 9ee6e8bb pbrook
                case 0:
3902 1b2b1e54 Filip Navara
                    tmp = gen_ld8u(addr, IS_USER(s));
3903 ad69471c pbrook
                    gen_neon_dup_u8(tmp, 0);
3904 9ee6e8bb pbrook
                    break;
3905 9ee6e8bb pbrook
                case 1:
3906 1b2b1e54 Filip Navara
                    tmp = gen_ld16u(addr, IS_USER(s));
3907 ad69471c pbrook
                    gen_neon_dup_low16(tmp);
3908 9ee6e8bb pbrook
                    break;
3909 9ee6e8bb pbrook
                case 2:
3910 1b2b1e54 Filip Navara
                    tmp = gen_ld32(addr, IS_USER(s));
3911 9ee6e8bb pbrook
                    break;
3912 9ee6e8bb pbrook
                case 3:
3913 9ee6e8bb pbrook
                    return 1;
3914 a50f5b91 pbrook
                default: /* Avoid compiler warnings.  */
3915 a50f5b91 pbrook
                    abort();
3916 99c475ab bellard
                }
3917 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, addr, 1 << size);
3918 7d1b0095 Peter Maydell
                tmp2 = tcg_temp_new_i32();
3919 ad69471c pbrook
                tcg_gen_mov_i32(tmp2, tmp);
3920 ad69471c pbrook
                neon_store_reg(rd, 0, tmp2);
3921 3018f259 pbrook
                neon_store_reg(rd, 1, tmp);
3922 9ee6e8bb pbrook
                rd += stride;
3923 9ee6e8bb pbrook
            }
3924 9ee6e8bb pbrook
            stride = (1 << size) * nregs;
3925 9ee6e8bb pbrook
        } else {
3926 9ee6e8bb pbrook
            /* Single element.  */
3927 9ee6e8bb pbrook
            pass = (insn >> 7) & 1;
3928 9ee6e8bb pbrook
            switch (size) {
3929 9ee6e8bb pbrook
            case 0:
3930 9ee6e8bb pbrook
                shift = ((insn >> 5) & 3) * 8;
3931 9ee6e8bb pbrook
                stride = 1;
3932 9ee6e8bb pbrook
                break;
3933 9ee6e8bb pbrook
            case 1:
3934 9ee6e8bb pbrook
                shift = ((insn >> 6) & 1) * 16;
3935 9ee6e8bb pbrook
                stride = (insn & (1 << 5)) ? 2 : 1;
3936 9ee6e8bb pbrook
                break;
3937 9ee6e8bb pbrook
            case 2:
3938 9ee6e8bb pbrook
                shift = 0;
3939 9ee6e8bb pbrook
                stride = (insn & (1 << 6)) ? 2 : 1;
3940 9ee6e8bb pbrook
                break;
3941 9ee6e8bb pbrook
            default:
3942 9ee6e8bb pbrook
                abort();
3943 9ee6e8bb pbrook
            }
3944 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
3945 dcc65026 Aurelien Jarno
            load_reg_var(s, addr, rn);
3946 9ee6e8bb pbrook
            for (reg = 0; reg < nregs; reg++) {
3947 9ee6e8bb pbrook
                if (load) {
3948 9ee6e8bb pbrook
                    switch (size) {
3949 9ee6e8bb pbrook
                    case 0:
3950 1b2b1e54 Filip Navara
                        tmp = gen_ld8u(addr, IS_USER(s));
3951 9ee6e8bb pbrook
                        break;
3952 9ee6e8bb pbrook
                    case 1:
3953 1b2b1e54 Filip Navara
                        tmp = gen_ld16u(addr, IS_USER(s));
3954 9ee6e8bb pbrook
                        break;
3955 9ee6e8bb pbrook
                    case 2:
3956 1b2b1e54 Filip Navara
                        tmp = gen_ld32(addr, IS_USER(s));
3957 9ee6e8bb pbrook
                        break;
3958 a50f5b91 pbrook
                    default: /* Avoid compiler warnings.  */
3959 a50f5b91 pbrook
                        abort();
3960 9ee6e8bb pbrook
                    }
3961 9ee6e8bb pbrook
                    if (size != 2) {
3962 8f8e3aa4 pbrook
                        tmp2 = neon_load_reg(rd, pass);
3963 8f8e3aa4 pbrook
                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3964 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
3965 9ee6e8bb pbrook
                    }
3966 8f8e3aa4 pbrook
                    neon_store_reg(rd, pass, tmp);
3967 9ee6e8bb pbrook
                } else { /* Store */
3968 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, pass);
3969 8f8e3aa4 pbrook
                    if (shift)
3970 8f8e3aa4 pbrook
                        tcg_gen_shri_i32(tmp, tmp, shift);
3971 9ee6e8bb pbrook
                    switch (size) {
3972 9ee6e8bb pbrook
                    case 0:
3973 1b2b1e54 Filip Navara
                        gen_st8(tmp, addr, IS_USER(s));
3974 9ee6e8bb pbrook
                        break;
3975 9ee6e8bb pbrook
                    case 1:
3976 1b2b1e54 Filip Navara
                        gen_st16(tmp, addr, IS_USER(s));
3977 9ee6e8bb pbrook
                        break;
3978 9ee6e8bb pbrook
                    case 2:
3979 1b2b1e54 Filip Navara
                        gen_st32(tmp, addr, IS_USER(s));
3980 9ee6e8bb pbrook
                        break;
3981 99c475ab bellard
                    }
3982 99c475ab bellard
                }
3983 9ee6e8bb pbrook
                rd += stride;
3984 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, addr, 1 << size);
3985 99c475ab bellard
            }
3986 9ee6e8bb pbrook
            stride = nregs * (1 << size);
3987 99c475ab bellard
        }
3988 9ee6e8bb pbrook
    }
3989 7d1b0095 Peter Maydell
    tcg_temp_free_i32(addr);
3990 9ee6e8bb pbrook
    if (rm != 15) {
3991 b26eefb6 pbrook
        TCGv base;
3992 b26eefb6 pbrook
3993 b26eefb6 pbrook
        base = load_reg(s, rn);
3994 9ee6e8bb pbrook
        if (rm == 13) {
3995 b26eefb6 pbrook
            tcg_gen_addi_i32(base, base, stride);
3996 9ee6e8bb pbrook
        } else {
3997 b26eefb6 pbrook
            TCGv index;
3998 b26eefb6 pbrook
            index = load_reg(s, rm);
3999 b26eefb6 pbrook
            tcg_gen_add_i32(base, base, index);
4000 7d1b0095 Peter Maydell
            tcg_temp_free_i32(index);
4001 9ee6e8bb pbrook
        }
4002 b26eefb6 pbrook
        store_reg(s, rn, base);
4003 9ee6e8bb pbrook
    }
4004 9ee6e8bb pbrook
    return 0;
4005 9ee6e8bb pbrook
}
4006 3b46e624 ths
4007 8f8e3aa4 pbrook
/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
4008 8f8e3aa4 pbrook
static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4009 8f8e3aa4 pbrook
{
4010 8f8e3aa4 pbrook
    tcg_gen_and_i32(t, t, c);
4011 f669df27 Aurelien Jarno
    tcg_gen_andc_i32(f, f, c);
4012 8f8e3aa4 pbrook
    tcg_gen_or_i32(dest, t, f);
4013 8f8e3aa4 pbrook
}
4014 8f8e3aa4 pbrook
4015 a7812ae4 pbrook
static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4016 ad69471c pbrook
{
4017 ad69471c pbrook
    switch (size) {
4018 ad69471c pbrook
    case 0: gen_helper_neon_narrow_u8(dest, src); break;
4019 ad69471c pbrook
    case 1: gen_helper_neon_narrow_u16(dest, src); break;
4020 ad69471c pbrook
    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4021 ad69471c pbrook
    default: abort();
4022 ad69471c pbrook
    }
4023 ad69471c pbrook
}
4024 ad69471c pbrook
4025 a7812ae4 pbrook
static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4026 ad69471c pbrook
{
4027 ad69471c pbrook
    switch (size) {
4028 ad69471c pbrook
    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4029 ad69471c pbrook
    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4030 ad69471c pbrook
    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4031 ad69471c pbrook
    default: abort();
4032 ad69471c pbrook
    }
4033 ad69471c pbrook
}
4034 ad69471c pbrook
4035 a7812ae4 pbrook
static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4036 ad69471c pbrook
{
4037 ad69471c pbrook
    switch (size) {
4038 ad69471c pbrook
    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4039 ad69471c pbrook
    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4040 ad69471c pbrook
    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4041 ad69471c pbrook
    default: abort();
4042 ad69471c pbrook
    }
4043 ad69471c pbrook
}
4044 ad69471c pbrook
4045 af1bbf30 Juha Riihimรคki
static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4046 af1bbf30 Juha Riihimรคki
{
4047 af1bbf30 Juha Riihimรคki
    switch (size) {
4048 af1bbf30 Juha Riihimรคki
    case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4049 af1bbf30 Juha Riihimรคki
    case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4050 af1bbf30 Juha Riihimรคki
    case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4051 af1bbf30 Juha Riihimรคki
    default: abort();
4052 af1bbf30 Juha Riihimรคki
    }
4053 af1bbf30 Juha Riihimรคki
}
4054 af1bbf30 Juha Riihimรคki
4055 ad69471c pbrook
static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4056 ad69471c pbrook
                                         int q, int u)
4057 ad69471c pbrook
{
4058 ad69471c pbrook
    if (q) {
4059 ad69471c pbrook
        if (u) {
4060 ad69471c pbrook
            switch (size) {
4061 ad69471c pbrook
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4062 ad69471c pbrook
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4063 ad69471c pbrook
            default: abort();
4064 ad69471c pbrook
            }
4065 ad69471c pbrook
        } else {
4066 ad69471c pbrook
            switch (size) {
4067 ad69471c pbrook
            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4068 ad69471c pbrook
            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4069 ad69471c pbrook
            default: abort();
4070 ad69471c pbrook
            }
4071 ad69471c pbrook
        }
4072 ad69471c pbrook
    } else {
4073 ad69471c pbrook
        if (u) {
4074 ad69471c pbrook
            switch (size) {
4075 b408a9b0 Christophe Lyon
            case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4076 b408a9b0 Christophe Lyon
            case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4077 ad69471c pbrook
            default: abort();
4078 ad69471c pbrook
            }
4079 ad69471c pbrook
        } else {
4080 ad69471c pbrook
            switch (size) {
4081 ad69471c pbrook
            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4082 ad69471c pbrook
            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4083 ad69471c pbrook
            default: abort();
4084 ad69471c pbrook
            }
4085 ad69471c pbrook
        }
4086 ad69471c pbrook
    }
4087 ad69471c pbrook
}
4088 ad69471c pbrook
4089 a7812ae4 pbrook
static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4090 ad69471c pbrook
{
4091 ad69471c pbrook
    if (u) {
4092 ad69471c pbrook
        switch (size) {
4093 ad69471c pbrook
        case 0: gen_helper_neon_widen_u8(dest, src); break;
4094 ad69471c pbrook
        case 1: gen_helper_neon_widen_u16(dest, src); break;
4095 ad69471c pbrook
        case 2: tcg_gen_extu_i32_i64(dest, src); break;
4096 ad69471c pbrook
        default: abort();
4097 ad69471c pbrook
        }
4098 ad69471c pbrook
    } else {
4099 ad69471c pbrook
        switch (size) {
4100 ad69471c pbrook
        case 0: gen_helper_neon_widen_s8(dest, src); break;
4101 ad69471c pbrook
        case 1: gen_helper_neon_widen_s16(dest, src); break;
4102 ad69471c pbrook
        case 2: tcg_gen_ext_i32_i64(dest, src); break;
4103 ad69471c pbrook
        default: abort();
4104 ad69471c pbrook
        }
4105 ad69471c pbrook
    }
4106 7d1b0095 Peter Maydell
    tcg_temp_free_i32(src);
4107 ad69471c pbrook
}
4108 ad69471c pbrook
4109 ad69471c pbrook
static inline void gen_neon_addl(int size)
4110 ad69471c pbrook
{
4111 ad69471c pbrook
    switch (size) {
4112 ad69471c pbrook
    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4113 ad69471c pbrook
    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4114 ad69471c pbrook
    case 2: tcg_gen_add_i64(CPU_V001); break;
4115 ad69471c pbrook
    default: abort();
4116 ad69471c pbrook
    }
4117 ad69471c pbrook
}
4118 ad69471c pbrook
4119 ad69471c pbrook
static inline void gen_neon_subl(int size)
4120 ad69471c pbrook
{
4121 ad69471c pbrook
    switch (size) {
4122 ad69471c pbrook
    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4123 ad69471c pbrook
    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4124 ad69471c pbrook
    case 2: tcg_gen_sub_i64(CPU_V001); break;
4125 ad69471c pbrook
    default: abort();
4126 ad69471c pbrook
    }
4127 ad69471c pbrook
}
4128 ad69471c pbrook
4129 a7812ae4 pbrook
static inline void gen_neon_negl(TCGv_i64 var, int size)
4130 ad69471c pbrook
{
4131 ad69471c pbrook
    switch (size) {
4132 ad69471c pbrook
    case 0: gen_helper_neon_negl_u16(var, var); break;
4133 ad69471c pbrook
    case 1: gen_helper_neon_negl_u32(var, var); break;
4134 ad69471c pbrook
    case 2: gen_helper_neon_negl_u64(var, var); break;
4135 ad69471c pbrook
    default: abort();
4136 ad69471c pbrook
    }
4137 ad69471c pbrook
}
4138 ad69471c pbrook
4139 a7812ae4 pbrook
static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4140 ad69471c pbrook
{
4141 ad69471c pbrook
    switch (size) {
4142 ad69471c pbrook
    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4143 ad69471c pbrook
    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4144 ad69471c pbrook
    default: abort();
4145 ad69471c pbrook
    }
4146 ad69471c pbrook
}
4147 ad69471c pbrook
4148 a7812ae4 pbrook
static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4149 ad69471c pbrook
{
4150 a7812ae4 pbrook
    TCGv_i64 tmp;
4151 ad69471c pbrook
4152 ad69471c pbrook
    switch ((size << 1) | u) {
4153 ad69471c pbrook
    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4154 ad69471c pbrook
    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4155 ad69471c pbrook
    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4156 ad69471c pbrook
    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4157 ad69471c pbrook
    case 4:
4158 ad69471c pbrook
        tmp = gen_muls_i64_i32(a, b);
4159 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4160 7d2aabe2 Peter Maydell
        tcg_temp_free_i64(tmp);
4161 ad69471c pbrook
        break;
4162 ad69471c pbrook
    case 5:
4163 ad69471c pbrook
        tmp = gen_mulu_i64_i32(a, b);
4164 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4165 7d2aabe2 Peter Maydell
        tcg_temp_free_i64(tmp);
4166 ad69471c pbrook
        break;
4167 ad69471c pbrook
    default: abort();
4168 ad69471c pbrook
    }
4169 c6067f04 Christophe Lyon
4170 c6067f04 Christophe Lyon
    /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4171 c6067f04 Christophe Lyon
       Don't forget to clean them now.  */
4172 c6067f04 Christophe Lyon
    if (size < 2) {
4173 7d1b0095 Peter Maydell
        tcg_temp_free_i32(a);
4174 7d1b0095 Peter Maydell
        tcg_temp_free_i32(b);
4175 c6067f04 Christophe Lyon
    }
4176 ad69471c pbrook
}
4177 ad69471c pbrook
4178 c33171c7 Peter Maydell
static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4179 c33171c7 Peter Maydell
{
4180 c33171c7 Peter Maydell
    if (op) {
4181 c33171c7 Peter Maydell
        if (u) {
4182 c33171c7 Peter Maydell
            gen_neon_unarrow_sats(size, dest, src);
4183 c33171c7 Peter Maydell
        } else {
4184 c33171c7 Peter Maydell
            gen_neon_narrow(size, dest, src);
4185 c33171c7 Peter Maydell
        }
4186 c33171c7 Peter Maydell
    } else {
4187 c33171c7 Peter Maydell
        if (u) {
4188 c33171c7 Peter Maydell
            gen_neon_narrow_satu(size, dest, src);
4189 c33171c7 Peter Maydell
        } else {
4190 c33171c7 Peter Maydell
            gen_neon_narrow_sats(size, dest, src);
4191 c33171c7 Peter Maydell
        }
4192 c33171c7 Peter Maydell
    }
4193 c33171c7 Peter Maydell
}
4194 c33171c7 Peter Maydell
4195 9ee6e8bb pbrook
/* Translate a NEON data processing instruction.  Return nonzero if the
4196 9ee6e8bb pbrook
   instruction is invalid.
4197 ad69471c pbrook
   We process data in a mixture of 32-bit and 64-bit chunks.
4198 ad69471c pbrook
   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
4199 2c0262af bellard
4200 9ee6e8bb pbrook
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4201 9ee6e8bb pbrook
{
4202 9ee6e8bb pbrook
    int op;
4203 9ee6e8bb pbrook
    int q;
4204 9ee6e8bb pbrook
    int rd, rn, rm;
4205 9ee6e8bb pbrook
    int size;
4206 9ee6e8bb pbrook
    int shift;
4207 9ee6e8bb pbrook
    int pass;
4208 9ee6e8bb pbrook
    int count;
4209 9ee6e8bb pbrook
    int pairwise;
4210 9ee6e8bb pbrook
    int u;
4211 9ee6e8bb pbrook
    int n;
4212 ca9a32e4 Juha Riihimรคki
    uint32_t imm, mask;
4213 b75263d6 Juha Riihimรคki
    TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4214 a7812ae4 pbrook
    TCGv_i64 tmp64;
4215 9ee6e8bb pbrook
4216 5df8bac1 Peter Maydell
    if (!s->vfp_enabled)
4217 9ee6e8bb pbrook
      return 1;
4218 9ee6e8bb pbrook
    q = (insn & (1 << 6)) != 0;
4219 9ee6e8bb pbrook
    u = (insn >> 24) & 1;
4220 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
4221 9ee6e8bb pbrook
    VFP_DREG_N(rn, insn);
4222 9ee6e8bb pbrook
    VFP_DREG_M(rm, insn);
4223 9ee6e8bb pbrook
    size = (insn >> 20) & 3;
4224 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
4225 9ee6e8bb pbrook
        /* Three register same length.  */
4226 9ee6e8bb pbrook
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4227 ad69471c pbrook
        if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4228 ad69471c pbrook
                          || op == 10 || op  == 11 || op == 16)) {
4229 ad69471c pbrook
            /* 64-bit element instructions.  */
4230 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
4231 ad69471c pbrook
                neon_load_reg64(cpu_V0, rn + pass);
4232 ad69471c pbrook
                neon_load_reg64(cpu_V1, rm + pass);
4233 9ee6e8bb pbrook
                switch (op) {
4234 9ee6e8bb pbrook
                case 1: /* VQADD */
4235 9ee6e8bb pbrook
                    if (u) {
4236 72902672 Christophe Lyon
                        gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4237 72902672 Christophe Lyon
                                                 cpu_V0, cpu_V1);
4238 2c0262af bellard
                    } else {
4239 72902672 Christophe Lyon
                        gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4240 72902672 Christophe Lyon
                                                 cpu_V0, cpu_V1);
4241 2c0262af bellard
                    }
4242 9ee6e8bb pbrook
                    break;
4243 9ee6e8bb pbrook
                case 5: /* VQSUB */
4244 9ee6e8bb pbrook
                    if (u) {
4245 72902672 Christophe Lyon
                        gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4246 72902672 Christophe Lyon
                                                 cpu_V0, cpu_V1);
4247 ad69471c pbrook
                    } else {
4248 72902672 Christophe Lyon
                        gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4249 72902672 Christophe Lyon
                                                 cpu_V0, cpu_V1);
4250 ad69471c pbrook
                    }
4251 ad69471c pbrook
                    break;
4252 ad69471c pbrook
                case 8: /* VSHL */
4253 ad69471c pbrook
                    if (u) {
4254 ad69471c pbrook
                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4255 ad69471c pbrook
                    } else {
4256 ad69471c pbrook
                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4257 ad69471c pbrook
                    }
4258 ad69471c pbrook
                    break;
4259 ad69471c pbrook
                case 9: /* VQSHL */
4260 ad69471c pbrook
                    if (u) {
4261 ad69471c pbrook
                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4262 def126ce Juha Riihimรคki
                                                 cpu_V1, cpu_V0);
4263 ad69471c pbrook
                    } else {
4264 def126ce Juha Riihimรคki
                        gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4265 ad69471c pbrook
                                                 cpu_V1, cpu_V0);
4266 ad69471c pbrook
                    }
4267 ad69471c pbrook
                    break;
4268 ad69471c pbrook
                case 10: /* VRSHL */
4269 ad69471c pbrook
                    if (u) {
4270 ad69471c pbrook
                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4271 1e8d4eec bellard
                    } else {
4272 ad69471c pbrook
                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4273 ad69471c pbrook
                    }
4274 ad69471c pbrook
                    break;
4275 ad69471c pbrook
                case 11: /* VQRSHL */
4276 ad69471c pbrook
                    if (u) {
4277 ad69471c pbrook
                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4278 ad69471c pbrook
                                                  cpu_V1, cpu_V0);
4279 ad69471c pbrook
                    } else {
4280 ad69471c pbrook
                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4281 ad69471c pbrook
                                                  cpu_V1, cpu_V0);
4282 1e8d4eec bellard
                    }
4283 9ee6e8bb pbrook
                    break;
4284 9ee6e8bb pbrook
                case 16:
4285 9ee6e8bb pbrook
                    if (u) {
4286 ad69471c pbrook
                        tcg_gen_sub_i64(CPU_V001);
4287 9ee6e8bb pbrook
                    } else {
4288 ad69471c pbrook
                        tcg_gen_add_i64(CPU_V001);
4289 9ee6e8bb pbrook
                    }
4290 9ee6e8bb pbrook
                    break;
4291 9ee6e8bb pbrook
                default:
4292 9ee6e8bb pbrook
                    abort();
4293 2c0262af bellard
                }
4294 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd + pass);
4295 2c0262af bellard
            }
4296 9ee6e8bb pbrook
            return 0;
4297 2c0262af bellard
        }
4298 9ee6e8bb pbrook
        switch (op) {
4299 9ee6e8bb pbrook
        case 8: /* VSHL */
4300 9ee6e8bb pbrook
        case 9: /* VQSHL */
4301 9ee6e8bb pbrook
        case 10: /* VRSHL */
4302 ad69471c pbrook
        case 11: /* VQRSHL */
4303 9ee6e8bb pbrook
            {
4304 ad69471c pbrook
                int rtmp;
4305 ad69471c pbrook
                /* Shift instruction operands are reversed.  */
4306 ad69471c pbrook
                rtmp = rn;
4307 9ee6e8bb pbrook
                rn = rm;
4308 ad69471c pbrook
                rm = rtmp;
4309 9ee6e8bb pbrook
                pairwise = 0;
4310 9ee6e8bb pbrook
            }
4311 2c0262af bellard
            break;
4312 9ee6e8bb pbrook
        case 20: /* VPMAX */
4313 9ee6e8bb pbrook
        case 21: /* VPMIN */
4314 9ee6e8bb pbrook
        case 23: /* VPADD */
4315 9ee6e8bb pbrook
            pairwise = 1;
4316 2c0262af bellard
            break;
4317 9ee6e8bb pbrook
        case 26: /* VPADD (float) */
4318 9ee6e8bb pbrook
            pairwise = (u && size < 2);
4319 2c0262af bellard
            break;
4320 9ee6e8bb pbrook
        case 30: /* VPMIN/VPMAX (float) */
4321 9ee6e8bb pbrook
            pairwise = u;
4322 2c0262af bellard
            break;
4323 9ee6e8bb pbrook
        default:
4324 9ee6e8bb pbrook
            pairwise = 0;
4325 2c0262af bellard
            break;
4326 9ee6e8bb pbrook
        }
4327 dd8fbd78 Filip Navara
4328 9ee6e8bb pbrook
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
4329 9ee6e8bb pbrook
4330 9ee6e8bb pbrook
        if (pairwise) {
4331 9ee6e8bb pbrook
            /* Pairwise.  */
4332 9ee6e8bb pbrook
            if (q)
4333 9ee6e8bb pbrook
                n = (pass & 1) * 2;
4334 2c0262af bellard
            else
4335 9ee6e8bb pbrook
                n = 0;
4336 9ee6e8bb pbrook
            if (pass < q + 1) {
4337 dd8fbd78 Filip Navara
                tmp = neon_load_reg(rn, n);
4338 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rn, n + 1);
4339 9ee6e8bb pbrook
            } else {
4340 dd8fbd78 Filip Navara
                tmp = neon_load_reg(rm, n);
4341 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rm, n + 1);
4342 9ee6e8bb pbrook
            }
4343 9ee6e8bb pbrook
        } else {
4344 9ee6e8bb pbrook
            /* Elementwise.  */
4345 dd8fbd78 Filip Navara
            tmp = neon_load_reg(rn, pass);
4346 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rm, pass);
4347 9ee6e8bb pbrook
        }
4348 9ee6e8bb pbrook
        switch (op) {
4349 9ee6e8bb pbrook
        case 0: /* VHADD */
4350 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hadd);
4351 9ee6e8bb pbrook
            break;
4352 9ee6e8bb pbrook
        case 1: /* VQADD */
4353 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qadd);
4354 2c0262af bellard
            break;
4355 9ee6e8bb pbrook
        case 2: /* VRHADD */
4356 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(rhadd);
4357 2c0262af bellard
            break;
4358 9ee6e8bb pbrook
        case 3: /* Logic ops.  */
4359 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4360 9ee6e8bb pbrook
            case 0: /* VAND */
4361 dd8fbd78 Filip Navara
                tcg_gen_and_i32(tmp, tmp, tmp2);
4362 9ee6e8bb pbrook
                break;
4363 9ee6e8bb pbrook
            case 1: /* BIC */
4364 f669df27 Aurelien Jarno
                tcg_gen_andc_i32(tmp, tmp, tmp2);
4365 9ee6e8bb pbrook
                break;
4366 9ee6e8bb pbrook
            case 2: /* VORR */
4367 dd8fbd78 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
4368 9ee6e8bb pbrook
                break;
4369 9ee6e8bb pbrook
            case 3: /* VORN */
4370 f669df27 Aurelien Jarno
                tcg_gen_orc_i32(tmp, tmp, tmp2);
4371 9ee6e8bb pbrook
                break;
4372 9ee6e8bb pbrook
            case 4: /* VEOR */
4373 dd8fbd78 Filip Navara
                tcg_gen_xor_i32(tmp, tmp, tmp2);
4374 9ee6e8bb pbrook
                break;
4375 9ee6e8bb pbrook
            case 5: /* VBSL */
4376 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4377 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4378 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4379 9ee6e8bb pbrook
                break;
4380 9ee6e8bb pbrook
            case 6: /* VBIT */
4381 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4382 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4383 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4384 9ee6e8bb pbrook
                break;
4385 9ee6e8bb pbrook
            case 7: /* VBIF */
4386 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4387 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4388 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp3);
4389 9ee6e8bb pbrook
                break;
4390 2c0262af bellard
            }
4391 2c0262af bellard
            break;
4392 9ee6e8bb pbrook
        case 4: /* VHSUB */
4393 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hsub);
4394 9ee6e8bb pbrook
            break;
4395 9ee6e8bb pbrook
        case 5: /* VQSUB */
4396 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qsub);
4397 2c0262af bellard
            break;
4398 9ee6e8bb pbrook
        case 6: /* VCGT */
4399 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cgt);
4400 9ee6e8bb pbrook
            break;
4401 9ee6e8bb pbrook
        case 7: /* VCGE */
4402 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cge);
4403 9ee6e8bb pbrook
            break;
4404 9ee6e8bb pbrook
        case 8: /* VSHL */
4405 ad69471c pbrook
            GEN_NEON_INTEGER_OP(shl);
4406 2c0262af bellard
            break;
4407 9ee6e8bb pbrook
        case 9: /* VQSHL */
4408 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qshl);
4409 2c0262af bellard
            break;
4410 9ee6e8bb pbrook
        case 10: /* VRSHL */
4411 ad69471c pbrook
            GEN_NEON_INTEGER_OP(rshl);
4412 2c0262af bellard
            break;
4413 9ee6e8bb pbrook
        case 11: /* VQRSHL */
4414 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qrshl);
4415 9ee6e8bb pbrook
            break;
4416 9ee6e8bb pbrook
        case 12: /* VMAX */
4417 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(max);
4418 9ee6e8bb pbrook
            break;
4419 9ee6e8bb pbrook
        case 13: /* VMIN */
4420 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(min);
4421 9ee6e8bb pbrook
            break;
4422 9ee6e8bb pbrook
        case 14: /* VABD */
4423 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4424 9ee6e8bb pbrook
            break;
4425 9ee6e8bb pbrook
        case 15: /* VABA */
4426 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4427 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
4428 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4429 dd8fbd78 Filip Navara
            gen_neon_add(size, tmp, tmp2);
4430 9ee6e8bb pbrook
            break;
4431 9ee6e8bb pbrook
        case 16:
4432 9ee6e8bb pbrook
            if (!u) { /* VADD */
4433 dd8fbd78 Filip Navara
                if (gen_neon_add(size, tmp, tmp2))
4434 9ee6e8bb pbrook
                    return 1;
4435 9ee6e8bb pbrook
            } else { /* VSUB */
4436 9ee6e8bb pbrook
                switch (size) {
4437 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4438 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4439 dd8fbd78 Filip Navara
                case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4440 9ee6e8bb pbrook
                default: return 1;
4441 9ee6e8bb pbrook
                }
4442 9ee6e8bb pbrook
            }
4443 9ee6e8bb pbrook
            break;
4444 9ee6e8bb pbrook
        case 17:
4445 9ee6e8bb pbrook
            if (!u) { /* VTST */
4446 9ee6e8bb pbrook
                switch (size) {
4447 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4448 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4449 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4450 9ee6e8bb pbrook
                default: return 1;
4451 9ee6e8bb pbrook
                }
4452 9ee6e8bb pbrook
            } else { /* VCEQ */
4453 9ee6e8bb pbrook
                switch (size) {
4454 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4455 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4456 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4457 9ee6e8bb pbrook
                default: return 1;
4458 9ee6e8bb pbrook
                }
4459 9ee6e8bb pbrook
            }
4460 9ee6e8bb pbrook
            break;
4461 9ee6e8bb pbrook
        case 18: /* Multiply.  */
4462 9ee6e8bb pbrook
            switch (size) {
4463 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4464 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4465 dd8fbd78 Filip Navara
            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4466 9ee6e8bb pbrook
            default: return 1;
4467 9ee6e8bb pbrook
            }
4468 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp2);
4469 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4470 9ee6e8bb pbrook
            if (u) { /* VMLS */
4471 dd8fbd78 Filip Navara
                gen_neon_rsb(size, tmp, tmp2);
4472 9ee6e8bb pbrook
            } else { /* VMLA */
4473 dd8fbd78 Filip Navara
                gen_neon_add(size, tmp, tmp2);
4474 9ee6e8bb pbrook
            }
4475 9ee6e8bb pbrook
            break;
4476 9ee6e8bb pbrook
        case 19: /* VMUL */
4477 9ee6e8bb pbrook
            if (u) { /* polynomial */
4478 dd8fbd78 Filip Navara
                gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4479 9ee6e8bb pbrook
            } else { /* Integer */
4480 9ee6e8bb pbrook
                switch (size) {
4481 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4482 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4483 dd8fbd78 Filip Navara
                case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4484 9ee6e8bb pbrook
                default: return 1;
4485 9ee6e8bb pbrook
                }
4486 9ee6e8bb pbrook
            }
4487 9ee6e8bb pbrook
            break;
4488 9ee6e8bb pbrook
        case 20: /* VPMAX */
4489 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmax);
4490 9ee6e8bb pbrook
            break;
4491 9ee6e8bb pbrook
        case 21: /* VPMIN */
4492 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmin);
4493 9ee6e8bb pbrook
            break;
4494 9ee6e8bb pbrook
        case 22: /* Hultiply high.  */
4495 9ee6e8bb pbrook
            if (!u) { /* VQDMULH */
4496 9ee6e8bb pbrook
                switch (size) {
4497 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4498 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4499 9ee6e8bb pbrook
                default: return 1;
4500 9ee6e8bb pbrook
                }
4501 9ee6e8bb pbrook
            } else { /* VQRDHMUL */
4502 9ee6e8bb pbrook
                switch (size) {
4503 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4504 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4505 9ee6e8bb pbrook
                default: return 1;
4506 9ee6e8bb pbrook
                }
4507 9ee6e8bb pbrook
            }
4508 9ee6e8bb pbrook
            break;
4509 9ee6e8bb pbrook
        case 23: /* VPADD */
4510 9ee6e8bb pbrook
            if (u)
4511 9ee6e8bb pbrook
                return 1;
4512 9ee6e8bb pbrook
            switch (size) {
4513 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4514 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4515 dd8fbd78 Filip Navara
            case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4516 9ee6e8bb pbrook
            default: return 1;
4517 9ee6e8bb pbrook
            }
4518 9ee6e8bb pbrook
            break;
4519 9ee6e8bb pbrook
        case 26: /* Floating point arithnetic.  */
4520 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4521 9ee6e8bb pbrook
            case 0: /* VADD */
4522 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4523 9ee6e8bb pbrook
                break;
4524 9ee6e8bb pbrook
            case 2: /* VSUB */
4525 dd8fbd78 Filip Navara
                gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4526 9ee6e8bb pbrook
                break;
4527 9ee6e8bb pbrook
            case 4: /* VPADD */
4528 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4529 9ee6e8bb pbrook
                break;
4530 9ee6e8bb pbrook
            case 6: /* VABD */
4531 dd8fbd78 Filip Navara
                gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4532 9ee6e8bb pbrook
                break;
4533 9ee6e8bb pbrook
            default:
4534 9ee6e8bb pbrook
                return 1;
4535 9ee6e8bb pbrook
            }
4536 9ee6e8bb pbrook
            break;
4537 9ee6e8bb pbrook
        case 27: /* Float multiply.  */
4538 dd8fbd78 Filip Navara
            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4539 9ee6e8bb pbrook
            if (!u) {
4540 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp2);
4541 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rd, pass);
4542 9ee6e8bb pbrook
                if (size == 0) {
4543 dd8fbd78 Filip Navara
                    gen_helper_neon_add_f32(tmp, tmp, tmp2);
4544 9ee6e8bb pbrook
                } else {
4545 dd8fbd78 Filip Navara
                    gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4546 9ee6e8bb pbrook
                }
4547 9ee6e8bb pbrook
            }
4548 9ee6e8bb pbrook
            break;
4549 9ee6e8bb pbrook
        case 28: /* Float compare.  */
4550 9ee6e8bb pbrook
            if (!u) {
4551 dd8fbd78 Filip Navara
                gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4552 b5ff1b31 bellard
            } else {
4553 9ee6e8bb pbrook
                if (size == 0)
4554 dd8fbd78 Filip Navara
                    gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4555 9ee6e8bb pbrook
                else
4556 dd8fbd78 Filip Navara
                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4557 b5ff1b31 bellard
            }
4558 2c0262af bellard
            break;
4559 9ee6e8bb pbrook
        case 29: /* Float compare absolute.  */
4560 9ee6e8bb pbrook
            if (!u)
4561 9ee6e8bb pbrook
                return 1;
4562 9ee6e8bb pbrook
            if (size == 0)
4563 dd8fbd78 Filip Navara
                gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4564 9ee6e8bb pbrook
            else
4565 dd8fbd78 Filip Navara
                gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4566 2c0262af bellard
            break;
4567 9ee6e8bb pbrook
        case 30: /* Float min/max.  */
4568 9ee6e8bb pbrook
            if (size == 0)
4569 dd8fbd78 Filip Navara
                gen_helper_neon_max_f32(tmp, tmp, tmp2);
4570 9ee6e8bb pbrook
            else
4571 dd8fbd78 Filip Navara
                gen_helper_neon_min_f32(tmp, tmp, tmp2);
4572 9ee6e8bb pbrook
            break;
4573 9ee6e8bb pbrook
        case 31:
4574 9ee6e8bb pbrook
            if (size == 0)
4575 dd8fbd78 Filip Navara
                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4576 9ee6e8bb pbrook
            else
4577 dd8fbd78 Filip Navara
                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4578 2c0262af bellard
            break;
4579 9ee6e8bb pbrook
        default:
4580 9ee6e8bb pbrook
            abort();
4581 2c0262af bellard
        }
4582 7d1b0095 Peter Maydell
        tcg_temp_free_i32(tmp2);
4583 dd8fbd78 Filip Navara
4584 9ee6e8bb pbrook
        /* Save the result.  For elementwise operations we can put it
4585 9ee6e8bb pbrook
           straight into the destination register.  For pairwise operations
4586 9ee6e8bb pbrook
           we have to be careful to avoid clobbering the source operands.  */
4587 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4588 dd8fbd78 Filip Navara
            neon_store_scratch(pass, tmp);
4589 9ee6e8bb pbrook
        } else {
4590 dd8fbd78 Filip Navara
            neon_store_reg(rd, pass, tmp);
4591 9ee6e8bb pbrook
        }
4592 9ee6e8bb pbrook
4593 9ee6e8bb pbrook
        } /* for pass */
4594 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4595 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4596 dd8fbd78 Filip Navara
                tmp = neon_load_scratch(pass);
4597 dd8fbd78 Filip Navara
                neon_store_reg(rd, pass, tmp);
4598 9ee6e8bb pbrook
            }
4599 9ee6e8bb pbrook
        }
4600 ad69471c pbrook
        /* End of 3 register same size operations.  */
4601 9ee6e8bb pbrook
    } else if (insn & (1 << 4)) {
4602 9ee6e8bb pbrook
        if ((insn & 0x00380080) != 0) {
4603 9ee6e8bb pbrook
            /* Two registers and shift.  */
4604 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4605 9ee6e8bb pbrook
            if (insn & (1 << 7)) {
4606 9ee6e8bb pbrook
                /* 64-bit shift.   */
4607 9ee6e8bb pbrook
                size = 3;
4608 9ee6e8bb pbrook
            } else {
4609 9ee6e8bb pbrook
                size = 2;
4610 9ee6e8bb pbrook
                while ((insn & (1 << (size + 19))) == 0)
4611 9ee6e8bb pbrook
                    size--;
4612 9ee6e8bb pbrook
            }
4613 9ee6e8bb pbrook
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4614 9ee6e8bb pbrook
            /* To avoid excessive dumplication of ops we implement shift
4615 9ee6e8bb pbrook
               by immediate using the variable shift operations.  */
4616 9ee6e8bb pbrook
            if (op < 8) {
4617 9ee6e8bb pbrook
                /* Shift by immediate:
4618 9ee6e8bb pbrook
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4619 9ee6e8bb pbrook
                /* Right shifts are encoded as N - shift, where N is the
4620 9ee6e8bb pbrook
                   element size in bits.  */
4621 9ee6e8bb pbrook
                if (op <= 4)
4622 9ee6e8bb pbrook
                    shift = shift - (1 << (size + 3));
4623 9ee6e8bb pbrook
                if (size == 3) {
4624 9ee6e8bb pbrook
                    count = q + 1;
4625 9ee6e8bb pbrook
                } else {
4626 9ee6e8bb pbrook
                    count = q ? 4: 2;
4627 9ee6e8bb pbrook
                }
4628 9ee6e8bb pbrook
                switch (size) {
4629 9ee6e8bb pbrook
                case 0:
4630 9ee6e8bb pbrook
                    imm = (uint8_t) shift;
4631 9ee6e8bb pbrook
                    imm |= imm << 8;
4632 9ee6e8bb pbrook
                    imm |= imm << 16;
4633 9ee6e8bb pbrook
                    break;
4634 9ee6e8bb pbrook
                case 1:
4635 9ee6e8bb pbrook
                    imm = (uint16_t) shift;
4636 9ee6e8bb pbrook
                    imm |= imm << 16;
4637 9ee6e8bb pbrook
                    break;
4638 9ee6e8bb pbrook
                case 2:
4639 9ee6e8bb pbrook
                case 3:
4640 9ee6e8bb pbrook
                    imm = shift;
4641 9ee6e8bb pbrook
                    break;
4642 9ee6e8bb pbrook
                default:
4643 9ee6e8bb pbrook
                    abort();
4644 9ee6e8bb pbrook
                }
4645 9ee6e8bb pbrook
4646 9ee6e8bb pbrook
                for (pass = 0; pass < count; pass++) {
4647 ad69471c pbrook
                    if (size == 3) {
4648 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
4649 ad69471c pbrook
                        tcg_gen_movi_i64(cpu_V1, imm);
4650 ad69471c pbrook
                        switch (op) {
4651 ad69471c pbrook
                        case 0:  /* VSHR */
4652 ad69471c pbrook
                        case 1:  /* VSRA */
4653 ad69471c pbrook
                            if (u)
4654 ad69471c pbrook
                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4655 9ee6e8bb pbrook
                            else
4656 ad69471c pbrook
                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4657 9ee6e8bb pbrook
                            break;
4658 ad69471c pbrook
                        case 2: /* VRSHR */
4659 ad69471c pbrook
                        case 3: /* VRSRA */
4660 ad69471c pbrook
                            if (u)
4661 ad69471c pbrook
                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4662 9ee6e8bb pbrook
                            else
4663 ad69471c pbrook
                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4664 9ee6e8bb pbrook
                            break;
4665 ad69471c pbrook
                        case 4: /* VSRI */
4666 ad69471c pbrook
                            if (!u)
4667 ad69471c pbrook
                                return 1;
4668 ad69471c pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4669 ad69471c pbrook
                            break;
4670 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
4671 ad69471c pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4672 ad69471c pbrook
                            break;
4673 0322b26e Peter Maydell
                        case 6: /* VQSHLU */
4674 0322b26e Peter Maydell
                            if (u) {
4675 0322b26e Peter Maydell
                                gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
4676 0322b26e Peter Maydell
                                                          cpu_V0, cpu_V1);
4677 0322b26e Peter Maydell
                            } else {
4678 0322b26e Peter Maydell
                                return 1;
4679 0322b26e Peter Maydell
                            }
4680 ad69471c pbrook
                            break;
4681 0322b26e Peter Maydell
                        case 7: /* VQSHL */
4682 0322b26e Peter Maydell
                            if (u) {
4683 0322b26e Peter Maydell
                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4684 0322b26e Peter Maydell
                                                         cpu_V0, cpu_V1);
4685 0322b26e Peter Maydell
                            } else {
4686 0322b26e Peter Maydell
                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4687 0322b26e Peter Maydell
                                                         cpu_V0, cpu_V1);
4688 0322b26e Peter Maydell
                            }
4689 9ee6e8bb pbrook
                            break;
4690 9ee6e8bb pbrook
                        }
4691 ad69471c pbrook
                        if (op == 1 || op == 3) {
4692 ad69471c pbrook
                            /* Accumulate.  */
4693 5371cb81 Christophe Lyon
                            neon_load_reg64(cpu_V1, rd + pass);
4694 ad69471c pbrook
                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4695 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
4696 ad69471c pbrook
                            /* Insert */
4697 923e6509 Christophe Lyon
                            neon_load_reg64(cpu_V1, rd + pass);
4698 923e6509 Christophe Lyon
                            uint64_t mask;
4699 923e6509 Christophe Lyon
                            if (shift < -63 || shift > 63) {
4700 923e6509 Christophe Lyon
                                mask = 0;
4701 923e6509 Christophe Lyon
                            } else {
4702 923e6509 Christophe Lyon
                                if (op == 4) {
4703 923e6509 Christophe Lyon
                                    mask = 0xffffffffffffffffull >> -shift;
4704 923e6509 Christophe Lyon
                                } else {
4705 923e6509 Christophe Lyon
                                    mask = 0xffffffffffffffffull << shift;
4706 923e6509 Christophe Lyon
                                }
4707 923e6509 Christophe Lyon
                            }
4708 923e6509 Christophe Lyon
                            tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
4709 923e6509 Christophe Lyon
                            tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4710 ad69471c pbrook
                        }
4711 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
4712 ad69471c pbrook
                    } else { /* size < 3 */
4713 ad69471c pbrook
                        /* Operands in T0 and T1.  */
4714 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass);
4715 7d1b0095 Peter Maydell
                        tmp2 = tcg_temp_new_i32();
4716 dd8fbd78 Filip Navara
                        tcg_gen_movi_i32(tmp2, imm);
4717 ad69471c pbrook
                        switch (op) {
4718 ad69471c pbrook
                        case 0:  /* VSHR */
4719 ad69471c pbrook
                        case 1:  /* VSRA */
4720 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(shl);
4721 ad69471c pbrook
                            break;
4722 ad69471c pbrook
                        case 2: /* VRSHR */
4723 ad69471c pbrook
                        case 3: /* VRSRA */
4724 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(rshl);
4725 ad69471c pbrook
                            break;
4726 ad69471c pbrook
                        case 4: /* VSRI */
4727 ad69471c pbrook
                            if (!u)
4728 ad69471c pbrook
                                return 1;
4729 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(shl);
4730 ad69471c pbrook
                            break;
4731 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
4732 ad69471c pbrook
                            switch (size) {
4733 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4734 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4735 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4736 ad69471c pbrook
                            default: return 1;
4737 ad69471c pbrook
                            }
4738 ad69471c pbrook
                            break;
4739 0322b26e Peter Maydell
                        case 6: /* VQSHLU */
4740 0322b26e Peter Maydell
                            if (!u) {
4741 0322b26e Peter Maydell
                                return 1;
4742 0322b26e Peter Maydell
                            }
4743 ad69471c pbrook
                            switch (size) {
4744 0322b26e Peter Maydell
                            case 0:
4745 0322b26e Peter Maydell
                                gen_helper_neon_qshlu_s8(tmp, cpu_env,
4746 0322b26e Peter Maydell
                                                         tmp, tmp2);
4747 0322b26e Peter Maydell
                                break;
4748 0322b26e Peter Maydell
                            case 1:
4749 0322b26e Peter Maydell
                                gen_helper_neon_qshlu_s16(tmp, cpu_env,
4750 0322b26e Peter Maydell
                                                          tmp, tmp2);
4751 0322b26e Peter Maydell
                                break;
4752 0322b26e Peter Maydell
                            case 2:
4753 0322b26e Peter Maydell
                                gen_helper_neon_qshlu_s32(tmp, cpu_env,
4754 0322b26e Peter Maydell
                                                          tmp, tmp2);
4755 0322b26e Peter Maydell
                                break;
4756 0322b26e Peter Maydell
                            default:
4757 0322b26e Peter Maydell
                                return 1;
4758 ad69471c pbrook
                            }
4759 ad69471c pbrook
                            break;
4760 0322b26e Peter Maydell
                        case 7: /* VQSHL */
4761 0322b26e Peter Maydell
                            GEN_NEON_INTEGER_OP_ENV(qshl);
4762 0322b26e Peter Maydell
                            break;
4763 ad69471c pbrook
                        }
4764 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
4765 ad69471c pbrook
4766 ad69471c pbrook
                        if (op == 1 || op == 3) {
4767 ad69471c pbrook
                            /* Accumulate.  */
4768 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
4769 5371cb81 Christophe Lyon
                            gen_neon_add(size, tmp, tmp2);
4770 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
4771 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
4772 ad69471c pbrook
                            /* Insert */
4773 ad69471c pbrook
                            switch (size) {
4774 ad69471c pbrook
                            case 0:
4775 ad69471c pbrook
                                if (op == 4)
4776 ca9a32e4 Juha Riihimรคki
                                    mask = 0xff >> -shift;
4777 ad69471c pbrook
                                else
4778 ca9a32e4 Juha Riihimรคki
                                    mask = (uint8_t)(0xff << shift);
4779 ca9a32e4 Juha Riihimรคki
                                mask |= mask << 8;
4780 ca9a32e4 Juha Riihimรคki
                                mask |= mask << 16;
4781 ad69471c pbrook
                                break;
4782 ad69471c pbrook
                            case 1:
4783 ad69471c pbrook
                                if (op == 4)
4784 ca9a32e4 Juha Riihimรคki
                                    mask = 0xffff >> -shift;
4785 ad69471c pbrook
                                else
4786 ca9a32e4 Juha Riihimรคki
                                    mask = (uint16_t)(0xffff << shift);
4787 ca9a32e4 Juha Riihimรคki
                                mask |= mask << 16;
4788 ad69471c pbrook
                                break;
4789 ad69471c pbrook
                            case 2:
4790 ca9a32e4 Juha Riihimรคki
                                if (shift < -31 || shift > 31) {
4791 ca9a32e4 Juha Riihimรคki
                                    mask = 0;
4792 ca9a32e4 Juha Riihimรคki
                                } else {
4793 ca9a32e4 Juha Riihimรคki
                                    if (op == 4)
4794 ca9a32e4 Juha Riihimรคki
                                        mask = 0xffffffffu >> -shift;
4795 ca9a32e4 Juha Riihimรคki
                                    else
4796 ca9a32e4 Juha Riihimรคki
                                        mask = 0xffffffffu << shift;
4797 ca9a32e4 Juha Riihimรคki
                                }
4798 ad69471c pbrook
                                break;
4799 ad69471c pbrook
                            default:
4800 ad69471c pbrook
                                abort();
4801 ad69471c pbrook
                            }
4802 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
4803 ca9a32e4 Juha Riihimรคki
                            tcg_gen_andi_i32(tmp, tmp, mask);
4804 ca9a32e4 Juha Riihimรคki
                            tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4805 dd8fbd78 Filip Navara
                            tcg_gen_or_i32(tmp, tmp, tmp2);
4806 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
4807 ad69471c pbrook
                        }
4808 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
4809 9ee6e8bb pbrook
                    }
4810 9ee6e8bb pbrook
                } /* for pass */
4811 9ee6e8bb pbrook
            } else if (op < 10) {
4812 ad69471c pbrook
                /* Shift by immediate and narrow:
4813 9ee6e8bb pbrook
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4814 0b36f4cd Christophe Lyon
                int input_unsigned = (op == 8) ? !u : u;
4815 0b36f4cd Christophe Lyon
4816 9ee6e8bb pbrook
                shift = shift - (1 << (size + 3));
4817 9ee6e8bb pbrook
                size++;
4818 92cdfaeb Peter Maydell
                if (size == 3) {
4819 a7812ae4 pbrook
                    tmp64 = tcg_const_i64(shift);
4820 92cdfaeb Peter Maydell
                    neon_load_reg64(cpu_V0, rm);
4821 92cdfaeb Peter Maydell
                    neon_load_reg64(cpu_V1, rm + 1);
4822 92cdfaeb Peter Maydell
                    for (pass = 0; pass < 2; pass++) {
4823 92cdfaeb Peter Maydell
                        TCGv_i64 in;
4824 92cdfaeb Peter Maydell
                        if (pass == 0) {
4825 92cdfaeb Peter Maydell
                            in = cpu_V0;
4826 92cdfaeb Peter Maydell
                        } else {
4827 92cdfaeb Peter Maydell
                            in = cpu_V1;
4828 92cdfaeb Peter Maydell
                        }
4829 ad69471c pbrook
                        if (q) {
4830 0b36f4cd Christophe Lyon
                            if (input_unsigned) {
4831 92cdfaeb Peter Maydell
                                gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
4832 0b36f4cd Christophe Lyon
                            } else {
4833 92cdfaeb Peter Maydell
                                gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
4834 0b36f4cd Christophe Lyon
                            }
4835 ad69471c pbrook
                        } else {
4836 0b36f4cd Christophe Lyon
                            if (input_unsigned) {
4837 92cdfaeb Peter Maydell
                                gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
4838 0b36f4cd Christophe Lyon
                            } else {
4839 92cdfaeb Peter Maydell
                                gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
4840 0b36f4cd Christophe Lyon
                            }
4841 ad69471c pbrook
                        }
4842 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
4843 92cdfaeb Peter Maydell
                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4844 92cdfaeb Peter Maydell
                        neon_store_reg(rd, pass, tmp);
4845 92cdfaeb Peter Maydell
                    } /* for pass */
4846 92cdfaeb Peter Maydell
                    tcg_temp_free_i64(tmp64);
4847 92cdfaeb Peter Maydell
                } else {
4848 92cdfaeb Peter Maydell
                    if (size == 1) {
4849 92cdfaeb Peter Maydell
                        imm = (uint16_t)shift;
4850 92cdfaeb Peter Maydell
                        imm |= imm << 16;
4851 2c0262af bellard
                    } else {
4852 92cdfaeb Peter Maydell
                        /* size == 2 */
4853 92cdfaeb Peter Maydell
                        imm = (uint32_t)shift;
4854 92cdfaeb Peter Maydell
                    }
4855 92cdfaeb Peter Maydell
                    tmp2 = tcg_const_i32(imm);
4856 92cdfaeb Peter Maydell
                    tmp4 = neon_load_reg(rm + 1, 0);
4857 92cdfaeb Peter Maydell
                    tmp5 = neon_load_reg(rm + 1, 1);
4858 92cdfaeb Peter Maydell
                    for (pass = 0; pass < 2; pass++) {
4859 92cdfaeb Peter Maydell
                        if (pass == 0) {
4860 92cdfaeb Peter Maydell
                            tmp = neon_load_reg(rm, 0);
4861 92cdfaeb Peter Maydell
                        } else {
4862 92cdfaeb Peter Maydell
                            tmp = tmp4;
4863 92cdfaeb Peter Maydell
                        }
4864 0b36f4cd Christophe Lyon
                        gen_neon_shift_narrow(size, tmp, tmp2, q,
4865 0b36f4cd Christophe Lyon
                                              input_unsigned);
4866 92cdfaeb Peter Maydell
                        if (pass == 0) {
4867 92cdfaeb Peter Maydell
                            tmp3 = neon_load_reg(rm, 1);
4868 92cdfaeb Peter Maydell
                        } else {
4869 92cdfaeb Peter Maydell
                            tmp3 = tmp5;
4870 92cdfaeb Peter Maydell
                        }
4871 0b36f4cd Christophe Lyon
                        gen_neon_shift_narrow(size, tmp3, tmp2, q,
4872 0b36f4cd Christophe Lyon
                                              input_unsigned);
4873 36aa55dc pbrook
                        tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4874 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
4875 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp3);
4876 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
4877 92cdfaeb Peter Maydell
                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4878 92cdfaeb Peter Maydell
                        neon_store_reg(rd, pass, tmp);
4879 92cdfaeb Peter Maydell
                    } /* for pass */
4880 c6067f04 Christophe Lyon
                    tcg_temp_free_i32(tmp2);
4881 b75263d6 Juha Riihimรคki
                }
4882 9ee6e8bb pbrook
            } else if (op == 10) {
4883 9ee6e8bb pbrook
                /* VSHLL */
4884 ad69471c pbrook
                if (q || size == 3)
4885 9ee6e8bb pbrook
                    return 1;
4886 ad69471c pbrook
                tmp = neon_load_reg(rm, 0);
4887 ad69471c pbrook
                tmp2 = neon_load_reg(rm, 1);
4888 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
4889 ad69471c pbrook
                    if (pass == 1)
4890 ad69471c pbrook
                        tmp = tmp2;
4891 ad69471c pbrook
4892 ad69471c pbrook
                    gen_neon_widen(cpu_V0, tmp, size, u);
4893 9ee6e8bb pbrook
4894 9ee6e8bb pbrook
                    if (shift != 0) {
4895 9ee6e8bb pbrook
                        /* The shift is less than the width of the source
4896 ad69471c pbrook
                           type, so we can just shift the whole register.  */
4897 ad69471c pbrook
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4898 acdf01ef Christophe Lyon
                        /* Widen the result of shift: we need to clear
4899 acdf01ef Christophe Lyon
                         * the potential overflow bits resulting from
4900 acdf01ef Christophe Lyon
                         * left bits of the narrow input appearing as
4901 acdf01ef Christophe Lyon
                         * right bits of left the neighbour narrow
4902 acdf01ef Christophe Lyon
                         * input.  */
4903 ad69471c pbrook
                        if (size < 2 || !u) {
4904 ad69471c pbrook
                            uint64_t imm64;
4905 ad69471c pbrook
                            if (size == 0) {
4906 ad69471c pbrook
                                imm = (0xffu >> (8 - shift));
4907 ad69471c pbrook
                                imm |= imm << 16;
4908 acdf01ef Christophe Lyon
                            } else if (size == 1) {
4909 ad69471c pbrook
                                imm = 0xffff >> (16 - shift);
4910 acdf01ef Christophe Lyon
                            } else {
4911 acdf01ef Christophe Lyon
                                /* size == 2 */
4912 acdf01ef Christophe Lyon
                                imm = 0xffffffff >> (32 - shift);
4913 acdf01ef Christophe Lyon
                            }
4914 acdf01ef Christophe Lyon
                            if (size < 2) {
4915 acdf01ef Christophe Lyon
                                imm64 = imm | (((uint64_t)imm) << 32);
4916 acdf01ef Christophe Lyon
                            } else {
4917 acdf01ef Christophe Lyon
                                imm64 = imm;
4918 9ee6e8bb pbrook
                            }
4919 acdf01ef Christophe Lyon
                            tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
4920 9ee6e8bb pbrook
                        }
4921 9ee6e8bb pbrook
                    }
4922 ad69471c pbrook
                    neon_store_reg64(cpu_V0, rd + pass);
4923 9ee6e8bb pbrook
                }
4924 f73534a5 Peter Maydell
            } else if (op >= 14) {
4925 9ee6e8bb pbrook
                /* VCVT fixed-point.  */
4926 f73534a5 Peter Maydell
                /* We have already masked out the must-be-1 top bit of imm6,
4927 f73534a5 Peter Maydell
                 * hence this 32-shift where the ARM ARM has 64-imm6.
4928 f73534a5 Peter Maydell
                 */
4929 f73534a5 Peter Maydell
                shift = 32 - shift;
4930 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4931 4373f3ce pbrook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4932 f73534a5 Peter Maydell
                    if (!(op & 1)) {
4933 9ee6e8bb pbrook
                        if (u)
4934 4373f3ce pbrook
                            gen_vfp_ulto(0, shift);
4935 9ee6e8bb pbrook
                        else
4936 4373f3ce pbrook
                            gen_vfp_slto(0, shift);
4937 9ee6e8bb pbrook
                    } else {
4938 9ee6e8bb pbrook
                        if (u)
4939 4373f3ce pbrook
                            gen_vfp_toul(0, shift);
4940 9ee6e8bb pbrook
                        else
4941 4373f3ce pbrook
                            gen_vfp_tosl(0, shift);
4942 2c0262af bellard
                    }
4943 4373f3ce pbrook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4944 2c0262af bellard
                }
4945 2c0262af bellard
            } else {
4946 9ee6e8bb pbrook
                return 1;
4947 9ee6e8bb pbrook
            }
4948 9ee6e8bb pbrook
        } else { /* (insn & 0x00380080) == 0 */
4949 9ee6e8bb pbrook
            int invert;
4950 9ee6e8bb pbrook
4951 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4952 9ee6e8bb pbrook
            /* One register and immediate.  */
4953 9ee6e8bb pbrook
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4954 9ee6e8bb pbrook
            invert = (insn & (1 << 5)) != 0;
4955 9ee6e8bb pbrook
            switch (op) {
4956 9ee6e8bb pbrook
            case 0: case 1:
4957 9ee6e8bb pbrook
                /* no-op */
4958 9ee6e8bb pbrook
                break;
4959 9ee6e8bb pbrook
            case 2: case 3:
4960 9ee6e8bb pbrook
                imm <<= 8;
4961 9ee6e8bb pbrook
                break;
4962 9ee6e8bb pbrook
            case 4: case 5:
4963 9ee6e8bb pbrook
                imm <<= 16;
4964 9ee6e8bb pbrook
                break;
4965 9ee6e8bb pbrook
            case 6: case 7:
4966 9ee6e8bb pbrook
                imm <<= 24;
4967 9ee6e8bb pbrook
                break;
4968 9ee6e8bb pbrook
            case 8: case 9:
4969 9ee6e8bb pbrook
                imm |= imm << 16;
4970 9ee6e8bb pbrook
                break;
4971 9ee6e8bb pbrook
            case 10: case 11:
4972 9ee6e8bb pbrook
                imm = (imm << 8) | (imm << 24);
4973 9ee6e8bb pbrook
                break;
4974 9ee6e8bb pbrook
            case 12:
4975 8e31209e Juha Riihimรคki
                imm = (imm << 8) | 0xff;
4976 9ee6e8bb pbrook
                break;
4977 9ee6e8bb pbrook
            case 13:
4978 9ee6e8bb pbrook
                imm = (imm << 16) | 0xffff;
4979 9ee6e8bb pbrook
                break;
4980 9ee6e8bb pbrook
            case 14:
4981 9ee6e8bb pbrook
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4982 9ee6e8bb pbrook
                if (invert)
4983 9ee6e8bb pbrook
                    imm = ~imm;
4984 9ee6e8bb pbrook
                break;
4985 9ee6e8bb pbrook
            case 15:
4986 9ee6e8bb pbrook
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4987 9ee6e8bb pbrook
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4988 9ee6e8bb pbrook
                break;
4989 9ee6e8bb pbrook
            }
4990 9ee6e8bb pbrook
            if (invert)
4991 9ee6e8bb pbrook
                imm = ~imm;
4992 9ee6e8bb pbrook
4993 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4994 9ee6e8bb pbrook
                if (op & 1 && op < 12) {
4995 ad69471c pbrook
                    tmp = neon_load_reg(rd, pass);
4996 9ee6e8bb pbrook
                    if (invert) {
4997 9ee6e8bb pbrook
                        /* The immediate value has already been inverted, so
4998 9ee6e8bb pbrook
                           BIC becomes AND.  */
4999 ad69471c pbrook
                        tcg_gen_andi_i32(tmp, tmp, imm);
5000 9ee6e8bb pbrook
                    } else {
5001 ad69471c pbrook
                        tcg_gen_ori_i32(tmp, tmp, imm);
5002 9ee6e8bb pbrook
                    }
5003 9ee6e8bb pbrook
                } else {
5004 ad69471c pbrook
                    /* VMOV, VMVN.  */
5005 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5006 9ee6e8bb pbrook
                    if (op == 14 && invert) {
5007 ad69471c pbrook
                        uint32_t val;
5008 ad69471c pbrook
                        val = 0;
5009 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
5010 9ee6e8bb pbrook
                            if (imm & (1 << (n + (pass & 1) * 4)))
5011 ad69471c pbrook
                                val |= 0xff << (n * 8);
5012 9ee6e8bb pbrook
                        }
5013 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, val);
5014 ad69471c pbrook
                    } else {
5015 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, imm);
5016 9ee6e8bb pbrook
                    }
5017 9ee6e8bb pbrook
                }
5018 ad69471c pbrook
                neon_store_reg(rd, pass, tmp);
5019 9ee6e8bb pbrook
            }
5020 9ee6e8bb pbrook
        }
5021 e4b3861d pbrook
    } else { /* (insn & 0x00800010 == 0x00800000) */
5022 9ee6e8bb pbrook
        if (size != 3) {
5023 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
5024 9ee6e8bb pbrook
            if ((insn & (1 << 6)) == 0) {
5025 9ee6e8bb pbrook
                /* Three registers of different lengths.  */
5026 9ee6e8bb pbrook
                int src1_wide;
5027 9ee6e8bb pbrook
                int src2_wide;
5028 9ee6e8bb pbrook
                int prewiden;
5029 9ee6e8bb pbrook
                /* prewiden, src1_wide, src2_wide */
5030 9ee6e8bb pbrook
                static const int neon_3reg_wide[16][3] = {
5031 9ee6e8bb pbrook
                    {1, 0, 0}, /* VADDL */
5032 9ee6e8bb pbrook
                    {1, 1, 0}, /* VADDW */
5033 9ee6e8bb pbrook
                    {1, 0, 0}, /* VSUBL */
5034 9ee6e8bb pbrook
                    {1, 1, 0}, /* VSUBW */
5035 9ee6e8bb pbrook
                    {0, 1, 1}, /* VADDHN */
5036 9ee6e8bb pbrook
                    {0, 0, 0}, /* VABAL */
5037 9ee6e8bb pbrook
                    {0, 1, 1}, /* VSUBHN */
5038 9ee6e8bb pbrook
                    {0, 0, 0}, /* VABDL */
5039 9ee6e8bb pbrook
                    {0, 0, 0}, /* VMLAL */
5040 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMLAL */
5041 9ee6e8bb pbrook
                    {0, 0, 0}, /* VMLSL */
5042 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMLSL */
5043 9ee6e8bb pbrook
                    {0, 0, 0}, /* Integer VMULL */
5044 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMULL */
5045 9ee6e8bb pbrook
                    {0, 0, 0}  /* Polynomial VMULL */
5046 9ee6e8bb pbrook
                };
5047 9ee6e8bb pbrook
5048 9ee6e8bb pbrook
                prewiden = neon_3reg_wide[op][0];
5049 9ee6e8bb pbrook
                src1_wide = neon_3reg_wide[op][1];
5050 9ee6e8bb pbrook
                src2_wide = neon_3reg_wide[op][2];
5051 9ee6e8bb pbrook
5052 ad69471c pbrook
                if (size == 0 && (op == 9 || op == 11 || op == 13))
5053 ad69471c pbrook
                    return 1;
5054 ad69471c pbrook
5055 9ee6e8bb pbrook
                /* Avoid overlapping operands.  Wide source operands are
5056 9ee6e8bb pbrook
                   always aligned so will never overlap with wide
5057 9ee6e8bb pbrook
                   destinations in problematic ways.  */
5058 8f8e3aa4 pbrook
                if (rd == rm && !src2_wide) {
5059 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
5060 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
5061 8f8e3aa4 pbrook
                } else if (rd == rn && !src1_wide) {
5062 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rn, 1);
5063 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
5064 9ee6e8bb pbrook
                }
5065 a50f5b91 pbrook
                TCGV_UNUSED(tmp3);
5066 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
5067 ad69471c pbrook
                    if (src1_wide) {
5068 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + pass);
5069 a50f5b91 pbrook
                        TCGV_UNUSED(tmp);
5070 9ee6e8bb pbrook
                    } else {
5071 ad69471c pbrook
                        if (pass == 1 && rd == rn) {
5072 dd8fbd78 Filip Navara
                            tmp = neon_load_scratch(2);
5073 9ee6e8bb pbrook
                        } else {
5074 ad69471c pbrook
                            tmp = neon_load_reg(rn, pass);
5075 ad69471c pbrook
                        }
5076 ad69471c pbrook
                        if (prewiden) {
5077 ad69471c pbrook
                            gen_neon_widen(cpu_V0, tmp, size, u);
5078 9ee6e8bb pbrook
                        }
5079 9ee6e8bb pbrook
                    }
5080 ad69471c pbrook
                    if (src2_wide) {
5081 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + pass);
5082 a50f5b91 pbrook
                        TCGV_UNUSED(tmp2);
5083 9ee6e8bb pbrook
                    } else {
5084 ad69471c pbrook
                        if (pass == 1 && rd == rm) {
5085 dd8fbd78 Filip Navara
                            tmp2 = neon_load_scratch(2);
5086 9ee6e8bb pbrook
                        } else {
5087 ad69471c pbrook
                            tmp2 = neon_load_reg(rm, pass);
5088 ad69471c pbrook
                        }
5089 ad69471c pbrook
                        if (prewiden) {
5090 ad69471c pbrook
                            gen_neon_widen(cpu_V1, tmp2, size, u);
5091 9ee6e8bb pbrook
                        }
5092 9ee6e8bb pbrook
                    }
5093 9ee6e8bb pbrook
                    switch (op) {
5094 9ee6e8bb pbrook
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5095 ad69471c pbrook
                        gen_neon_addl(size);
5096 9ee6e8bb pbrook
                        break;
5097 79b0e534 Riku Voipio
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5098 ad69471c pbrook
                        gen_neon_subl(size);
5099 9ee6e8bb pbrook
                        break;
5100 9ee6e8bb pbrook
                    case 5: case 7: /* VABAL, VABDL */
5101 9ee6e8bb pbrook
                        switch ((size << 1) | u) {
5102 ad69471c pbrook
                        case 0:
5103 ad69471c pbrook
                            gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5104 ad69471c pbrook
                            break;
5105 ad69471c pbrook
                        case 1:
5106 ad69471c pbrook
                            gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5107 ad69471c pbrook
                            break;
5108 ad69471c pbrook
                        case 2:
5109 ad69471c pbrook
                            gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5110 ad69471c pbrook
                            break;
5111 ad69471c pbrook
                        case 3:
5112 ad69471c pbrook
                            gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5113 ad69471c pbrook
                            break;
5114 ad69471c pbrook
                        case 4:
5115 ad69471c pbrook
                            gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5116 ad69471c pbrook
                            break;
5117 ad69471c pbrook
                        case 5:
5118 ad69471c pbrook
                            gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5119 ad69471c pbrook
                            break;
5120 9ee6e8bb pbrook
                        default: abort();
5121 9ee6e8bb pbrook
                        }
5122 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5123 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
5124 9ee6e8bb pbrook
                        break;
5125 9ee6e8bb pbrook
                    case 8: case 9: case 10: case 11: case 12: case 13:
5126 9ee6e8bb pbrook
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5127 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5128 9ee6e8bb pbrook
                        break;
5129 9ee6e8bb pbrook
                    case 14: /* Polynomial VMULL */
5130 e5ca24cb Peter Maydell
                        gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5131 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5132 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp);
5133 e5ca24cb Peter Maydell
                        break;
5134 9ee6e8bb pbrook
                    default: /* 15 is RESERVED.  */
5135 9ee6e8bb pbrook
                        return 1;
5136 9ee6e8bb pbrook
                    }
5137 ebcd88ce Peter Maydell
                    if (op == 13) {
5138 ebcd88ce Peter Maydell
                        /* VQDMULL */
5139 ebcd88ce Peter Maydell
                        gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5140 ebcd88ce Peter Maydell
                        neon_store_reg64(cpu_V0, rd + pass);
5141 ebcd88ce Peter Maydell
                    } else if (op == 5 || (op >= 8 && op <= 11)) {
5142 9ee6e8bb pbrook
                        /* Accumulate.  */
5143 ebcd88ce Peter Maydell
                        neon_load_reg64(cpu_V1, rd + pass);
5144 9ee6e8bb pbrook
                        switch (op) {
5145 4dc064e6 Peter Maydell
                        case 10: /* VMLSL */
5146 4dc064e6 Peter Maydell
                            gen_neon_negl(cpu_V0, size);
5147 4dc064e6 Peter Maydell
                            /* Fall through */
5148 4dc064e6 Peter Maydell
                        case 5: case 8: /* VABAL, VMLAL */
5149 ad69471c pbrook
                            gen_neon_addl(size);
5150 9ee6e8bb pbrook
                            break;
5151 9ee6e8bb pbrook
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
5152 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5153 4dc064e6 Peter Maydell
                            if (op == 11) {
5154 4dc064e6 Peter Maydell
                                gen_neon_negl(cpu_V0, size);
5155 4dc064e6 Peter Maydell
                            }
5156 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5157 ad69471c pbrook
                            break;
5158 9ee6e8bb pbrook
                        default:
5159 9ee6e8bb pbrook
                            abort();
5160 9ee6e8bb pbrook
                        }
5161 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5162 9ee6e8bb pbrook
                    } else if (op == 4 || op == 6) {
5163 9ee6e8bb pbrook
                        /* Narrowing operation.  */
5164 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5165 79b0e534 Riku Voipio
                        if (!u) {
5166 9ee6e8bb pbrook
                            switch (size) {
5167 ad69471c pbrook
                            case 0:
5168 ad69471c pbrook
                                gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5169 ad69471c pbrook
                                break;
5170 ad69471c pbrook
                            case 1:
5171 ad69471c pbrook
                                gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5172 ad69471c pbrook
                                break;
5173 ad69471c pbrook
                            case 2:
5174 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5175 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5176 ad69471c pbrook
                                break;
5177 9ee6e8bb pbrook
                            default: abort();
5178 9ee6e8bb pbrook
                            }
5179 9ee6e8bb pbrook
                        } else {
5180 9ee6e8bb pbrook
                            switch (size) {
5181 ad69471c pbrook
                            case 0:
5182 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5183 ad69471c pbrook
                                break;
5184 ad69471c pbrook
                            case 1:
5185 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5186 ad69471c pbrook
                                break;
5187 ad69471c pbrook
                            case 2:
5188 ad69471c pbrook
                                tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5189 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5190 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5191 ad69471c pbrook
                                break;
5192 9ee6e8bb pbrook
                            default: abort();
5193 9ee6e8bb pbrook
                            }
5194 9ee6e8bb pbrook
                        }
5195 ad69471c pbrook
                        if (pass == 0) {
5196 ad69471c pbrook
                            tmp3 = tmp;
5197 ad69471c pbrook
                        } else {
5198 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp3);
5199 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5200 ad69471c pbrook
                        }
5201 9ee6e8bb pbrook
                    } else {
5202 9ee6e8bb pbrook
                        /* Write back the result.  */
5203 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5204 9ee6e8bb pbrook
                    }
5205 9ee6e8bb pbrook
                }
5206 9ee6e8bb pbrook
            } else {
5207 9ee6e8bb pbrook
                /* Two registers and a scalar.  */
5208 9ee6e8bb pbrook
                switch (op) {
5209 9ee6e8bb pbrook
                case 0: /* Integer VMLA scalar */
5210 9ee6e8bb pbrook
                case 1: /* Float VMLA scalar */
5211 9ee6e8bb pbrook
                case 4: /* Integer VMLS scalar */
5212 9ee6e8bb pbrook
                case 5: /* Floating point VMLS scalar */
5213 9ee6e8bb pbrook
                case 8: /* Integer VMUL scalar */
5214 9ee6e8bb pbrook
                case 9: /* Floating point VMUL scalar */
5215 9ee6e8bb pbrook
                case 12: /* VQDMULH scalar */
5216 9ee6e8bb pbrook
                case 13: /* VQRDMULH scalar */
5217 dd8fbd78 Filip Navara
                    tmp = neon_get_scalar(size, rm);
5218 dd8fbd78 Filip Navara
                    neon_store_scratch(0, tmp);
5219 9ee6e8bb pbrook
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
5220 dd8fbd78 Filip Navara
                        tmp = neon_load_scratch(0);
5221 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rn, pass);
5222 9ee6e8bb pbrook
                        if (op == 12) {
5223 9ee6e8bb pbrook
                            if (size == 1) {
5224 dd8fbd78 Filip Navara
                                gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5225 9ee6e8bb pbrook
                            } else {
5226 dd8fbd78 Filip Navara
                                gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5227 9ee6e8bb pbrook
                            }
5228 9ee6e8bb pbrook
                        } else if (op == 13) {
5229 9ee6e8bb pbrook
                            if (size == 1) {
5230 dd8fbd78 Filip Navara
                                gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5231 9ee6e8bb pbrook
                            } else {
5232 dd8fbd78 Filip Navara
                                gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5233 9ee6e8bb pbrook
                            }
5234 9ee6e8bb pbrook
                        } else if (op & 1) {
5235 dd8fbd78 Filip Navara
                            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5236 9ee6e8bb pbrook
                        } else {
5237 9ee6e8bb pbrook
                            switch (size) {
5238 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5239 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5240 dd8fbd78 Filip Navara
                            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5241 9ee6e8bb pbrook
                            default: return 1;
5242 9ee6e8bb pbrook
                            }
5243 9ee6e8bb pbrook
                        }
5244 7d1b0095 Peter Maydell
                        tcg_temp_free_i32(tmp2);
5245 9ee6e8bb pbrook
                        if (op < 8) {
5246 9ee6e8bb pbrook
                            /* Accumulate.  */
5247 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5248 9ee6e8bb pbrook
                            switch (op) {
5249 9ee6e8bb pbrook
                            case 0:
5250 dd8fbd78 Filip Navara
                                gen_neon_add(size, tmp, tmp2);
5251 9ee6e8bb pbrook
                                break;
5252 9ee6e8bb pbrook
                            case 1:
5253 dd8fbd78 Filip Navara
                                gen_helper_neon_add_f32(tmp, tmp, tmp2);
5254 9ee6e8bb pbrook
                                break;
5255 9ee6e8bb pbrook
                            case 4:
5256 dd8fbd78 Filip Navara
                                gen_neon_rsb(size, tmp, tmp2);
5257 9ee6e8bb pbrook
                                break;
5258 9ee6e8bb pbrook
                            case 5:
5259 dd8fbd78 Filip Navara
                                gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5260 9ee6e8bb pbrook
                                break;
5261 9ee6e8bb pbrook
                            default:
5262 9ee6e8bb pbrook
                                abort();
5263 9ee6e8bb pbrook
                            }
5264 7d1b0095 Peter Maydell
                            tcg_temp_free_i32(tmp2);
5265 9ee6e8bb pbrook
                        }
5266 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
5267 9ee6e8bb pbrook
                    }
5268 9ee6e8bb pbrook
                    break;
5269 9ee6e8bb pbrook
                case 2: /* VMLAL sclar */
5270 9ee6e8bb pbrook
                case 3: /* VQDMLAL scalar */
5271 9ee6e8bb pbrook
                case 6: /* VMLSL scalar */
5272 9ee6e8bb pbrook
                case 7: /* VQDMLSL scalar */
5273 9ee6e8bb pbrook
                case 10: /* VMULL scalar */
5274 9ee6e8bb pbrook
                case 11: /* VQDMULL scalar */
5275 ad69471c pbrook
                    if (size == 0 && (op == 3 || op == 7 || op == 11))
5276 ad69471c pbrook
                        return 1;
5277 ad69471c pbrook
5278 dd8fbd78 Filip Navara
                    tmp2 = neon_get_scalar(size, rm);
5279 c6067f04 Christophe Lyon
                    /* We need a copy of tmp2 because gen_neon_mull
5280 c6067f04 Christophe Lyon
                     * deletes it during pass 0.  */
5281 7d1b0095 Peter Maydell
                    tmp4 = tcg_temp_new_i32();
5282 c6067f04 Christophe Lyon
                    tcg_gen_mov_i32(tmp4, tmp2);
5283 dd8fbd78 Filip Navara
                    tmp3 = neon_load_reg(rn, 1);
5284 ad69471c pbrook
5285 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5286 ad69471c pbrook
                        if (pass == 0) {
5287 ad69471c pbrook
                            tmp = neon_load_reg(rn, 0);
5288 9ee6e8bb pbrook
                        } else {
5289 dd8fbd78 Filip Navara
                            tmp = tmp3;
5290 c6067f04 Christophe Lyon
                            tmp2 = tmp4;
5291 9ee6e8bb pbrook
                        }
5292 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5293 ad69471c pbrook
                        if (op != 11) {
5294 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5295 9ee6e8bb pbrook
                        }
5296 9ee6e8bb pbrook
                        switch (op) {
5297 4dc064e6 Peter Maydell
                        case 6:
5298 4dc064e6 Peter Maydell
                            gen_neon_negl(cpu_V0, size);
5299 4dc064e6 Peter Maydell
                            /* Fall through */
5300 4dc064e6 Peter Maydell
                        case 2:
5301 ad69471c pbrook
                            gen_neon_addl(size);
5302 9ee6e8bb pbrook
                            break;
5303 9ee6e8bb pbrook
                        case 3: case 7:
5304 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5305 4dc064e6 Peter Maydell
                            if (op == 7) {
5306 4dc064e6 Peter Maydell
                                gen_neon_negl(cpu_V0, size);
5307 4dc064e6 Peter Maydell
                            }
5308 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5309 9ee6e8bb pbrook
                            break;
5310 9ee6e8bb pbrook
                        case 10:
5311 9ee6e8bb pbrook
                            /* no-op */
5312 9ee6e8bb pbrook
                            break;
5313 9ee6e8bb pbrook
                        case 11:
5314 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5315 9ee6e8bb pbrook
                            break;
5316 9ee6e8bb pbrook
                        default:
5317 9ee6e8bb pbrook
                            abort();
5318 9ee6e8bb pbrook
                        }
5319 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5320 9ee6e8bb pbrook
                    }
5321 dd8fbd78 Filip Navara
5322 dd8fbd78 Filip Navara
5323 9ee6e8bb pbrook
                    break;
5324 9ee6e8bb pbrook
                default: /* 14 and 15 are RESERVED */
5325 9ee6e8bb pbrook
                    return 1;
5326 9ee6e8bb pbrook
                }
5327 9ee6e8bb pbrook
            }
5328 9ee6e8bb pbrook
        } else { /* size == 3 */
5329 9ee6e8bb pbrook
            if (!u) {
5330 9ee6e8bb pbrook
                /* Extract.  */
5331 9ee6e8bb pbrook
                imm = (insn >> 8) & 0xf;
5332 ad69471c pbrook
5333 ad69471c pbrook
                if (imm > 7 && !q)
5334 ad69471c pbrook
                    return 1;
5335 ad69471c pbrook
5336 ad69471c pbrook
                if (imm == 0) {
5337 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5338 ad69471c pbrook
                    if (q) {
5339 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rn + 1);
5340 9ee6e8bb pbrook
                    }
5341 ad69471c pbrook
                } else if (imm == 8) {
5342 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn + 1);
5343 ad69471c pbrook
                    if (q) {
5344 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5345 9ee6e8bb pbrook
                    }
5346 ad69471c pbrook
                } else if (q) {
5347 a7812ae4 pbrook
                    tmp64 = tcg_temp_new_i64();
5348 ad69471c pbrook
                    if (imm < 8) {
5349 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn);
5350 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rn + 1);
5351 ad69471c pbrook
                    } else {
5352 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + 1);
5353 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rm);
5354 ad69471c pbrook
                    }
5355 ad69471c pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5356 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5357 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5358 ad69471c pbrook
                    if (imm < 8) {
5359 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5360 9ee6e8bb pbrook
                    } else {
5361 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + 1);
5362 ad69471c pbrook
                        imm -= 8;
5363 9ee6e8bb pbrook
                    }
5364 ad69471c pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5365 a7812ae4 pbrook
                    tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5366 a7812ae4 pbrook
                    tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5367 b75263d6 Juha Riihimรคki
                    tcg_temp_free_i64(tmp64);
5368 ad69471c pbrook
                } else {
5369 a7812ae4 pbrook
                    /* BUGFIX */
5370 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5371 a7812ae4 pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5372 ad69471c pbrook
                    neon_load_reg64(cpu_V1, rm);
5373 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5374 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5375 ad69471c pbrook
                }
5376 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd);
5377 ad69471c pbrook
                if (q) {
5378 ad69471c pbrook
                    neon_store_reg64(cpu_V1, rd + 1);
5379 9ee6e8bb pbrook
                }
5380 9ee6e8bb pbrook
            } else if ((insn & (1 << 11)) == 0) {
5381 9ee6e8bb pbrook
                /* Two register misc.  */
5382 9ee6e8bb pbrook
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5383 9ee6e8bb pbrook
                size = (insn >> 18) & 3;
5384 9ee6e8bb pbrook
                switch (op) {
5385 9ee6e8bb pbrook
                case 0: /* VREV64 */
5386 9ee6e8bb pbrook
                    if (size == 3)
5387 9ee6e8bb pbrook
                        return 1;
5388 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
5389 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass * 2);
5390 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rm, pass * 2 + 1);
5391 9ee6e8bb pbrook
                        switch (size) {
5392 dd8fbd78 Filip Navara
                        case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5393 dd8fbd78 Filip Navara
                        case 1: gen_swap_half(tmp); break;
5394 9ee6e8bb pbrook
                        case 2: /* no-op */ break;
5395 9ee6e8bb pbrook
                        default: abort();
5396 9ee6e8bb pbrook
                        }
5397 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass * 2 + 1, tmp);
5398 9ee6e8bb pbrook
                        if (size == 2) {
5399 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5400 9ee6e8bb pbrook
                        } else {
5401 9ee6e8bb pbrook
                            switch (size) {
5402 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5403 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp2); break;
5404 9ee6e8bb pbrook
                            default: abort();
5405 9ee6e8bb pbrook
                            }
5406 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5407 9ee6e8bb pbrook
                        }
5408 9ee6e8bb pbrook
                    }
5409 9ee6e8bb pbrook
                    break;
5410 9ee6e8bb pbrook
                case 4: case 5: /* VPADDL */
5411 9ee6e8bb pbrook
                case 12: case 13: /* VPADAL */
5412 9ee6e8bb pbrook
                    if (size == 3)
5413 9ee6e8bb pbrook
                        return 1;
5414 ad69471c pbrook
                    for (pass = 0; pass < q + 1; pass++) {
5415 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2);
5416 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, op & 1);
5417 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2 + 1);
5418 ad69471c pbrook
                        gen_neon_widen(cpu_V1, tmp, size, op & 1);
5419 ad69471c pbrook
                        switch (size) {
5420 ad69471c pbrook
                        case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5421 ad69471c pbrook
                        case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5422 ad69471c pbrook
                        case 2: tcg_gen_add_i64(CPU_V001); break;
5423 ad69471c pbrook
                        default: abort();
5424 ad69471c pbrook
                        }
5425 9ee6e8bb pbrook
                        if (op >= 12) {
5426 9ee6e8bb pbrook
                            /* Accumulate.  */
5427 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5428 ad69471c pbrook
                            gen_neon_addl(size);
5429 9ee6e8bb pbrook
                        }
5430 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5431 9ee6e8bb pbrook
                    }
5432 9ee6e8bb pbrook
                    break;
5433 9ee6e8bb pbrook
                case 33: /* VTRN */
5434 9ee6e8bb pbrook
                    if (size == 2) {
5435 9ee6e8bb pbrook
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
5436 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, n);
5437 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, n + 1);
5438 dd8fbd78 Filip Navara
                            neon_store_reg(rm, n, tmp2);
5439 dd8fbd78 Filip Navara
                            neon_store_reg(rd, n + 1, tmp);
5440 9ee6e8bb pbrook
                        }
5441 9ee6e8bb pbrook
                    } else {
5442 9ee6e8bb pbrook
                        goto elementwise;
5443 9ee6e8bb pbrook
                    }
5444 9ee6e8bb pbrook
                    break;
5445 9ee6e8bb pbrook
                case 34: /* VUZP */
5446 02acedf9 Peter Maydell
                    if (gen_neon_unzip(rd, rm, size, q)) {
5447 9ee6e8bb pbrook
                        return 1;
5448 9ee6e8bb pbrook
                    }
5449 9ee6e8bb pbrook
                    break;
5450 9ee6e8bb pbrook
                case 35: /* VZIP */
5451 d68a6f3a Peter Maydell
                    if (gen_neon_zip(rd, rm, size, q)) {
5452 9ee6e8bb pbrook
                        return 1;
5453 9ee6e8bb pbrook
                    }
5454 9ee6e8bb pbrook
                    break;
5455 9ee6e8bb pbrook
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5456 ad69471c pbrook
                    if (size == 3)
5457 ad69471c pbrook
                        return 1;
5458 a50f5b91 pbrook
                    TCGV_UNUSED(tmp2);
5459 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5460 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
5461 7d1b0095 Peter Maydell
                        tmp = tcg_temp_new_i32();
5462 c33171c7 Peter Maydell
                        gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
5463 ad69471c pbrook
                        if (pass == 0) {
5464 ad69471c pbrook
                            tmp2 = tmp;
5465 ad69471c pbrook
                        } else {
5466 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp2);
5467 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5468 9ee6e8bb pbrook
                        }
5469 9ee6e8bb pbrook
                    }
5470 9ee6e8bb pbrook
                    break;
5471 9ee6e8bb pbrook
                case 38: /* VSHLL */
5472 ad69471c pbrook
                    if (q || size == 3)
5473 9ee6e8bb pbrook
                        return 1;
5474 ad69471c pbrook
                    tmp = neon_load_reg(rm, 0);
5475 ad69471c pbrook
                    tmp2 = neon_load_reg(rm, 1);
5476 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5477 ad69471c pbrook
                        if (pass == 1)
5478 ad69471c pbrook
                            tmp = tmp2;
5479 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, 1);
5480 30d11a2a Juha Riihimรคki
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5481 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5482 9ee6e8bb pbrook
                    }
5483 9ee6e8bb pbrook
                    break;
5484 60011498 Paul Brook
                case 44: /* VCVT.F16.F32 */
5485 60011498 Paul Brook
                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5486 60011498 Paul Brook
                      return 1;
5487 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5488 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
5489 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5490 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5491 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5492 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5493 60011498 Paul Brook
                    tcg_gen_shli_i32(tmp2, tmp2, 16);
5494 60011498 Paul Brook
                    tcg_gen_or_i32(tmp2, tmp2, tmp);
5495 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5496 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5497 60011498 Paul Brook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5498 60011498 Paul Brook
                    neon_store_reg(rd, 0, tmp2);
5499 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
5500 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5501 60011498 Paul Brook
                    tcg_gen_shli_i32(tmp2, tmp2, 16);
5502 60011498 Paul Brook
                    tcg_gen_or_i32(tmp2, tmp2, tmp);
5503 60011498 Paul Brook
                    neon_store_reg(rd, 1, tmp2);
5504 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
5505 60011498 Paul Brook
                    break;
5506 60011498 Paul Brook
                case 46: /* VCVT.F32.F16 */
5507 60011498 Paul Brook
                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5508 60011498 Paul Brook
                      return 1;
5509 7d1b0095 Peter Maydell
                    tmp3 = tcg_temp_new_i32();
5510 60011498 Paul Brook
                    tmp = neon_load_reg(rm, 0);
5511 60011498 Paul Brook
                    tmp2 = neon_load_reg(rm, 1);
5512 60011498 Paul Brook
                    tcg_gen_ext16u_i32(tmp3, tmp);
5513 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5514 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5515 60011498 Paul Brook
                    tcg_gen_shri_i32(tmp3, tmp, 16);
5516 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5517 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5518 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp);
5519 60011498 Paul Brook
                    tcg_gen_ext16u_i32(tmp3, tmp2);
5520 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5521 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5522 60011498 Paul Brook
                    tcg_gen_shri_i32(tmp3, tmp2, 16);
5523 2d981da7 Peter Maydell
                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5524 60011498 Paul Brook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5525 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp2);
5526 7d1b0095 Peter Maydell
                    tcg_temp_free_i32(tmp3);
5527 60011498 Paul Brook
                    break;
5528 9ee6e8bb pbrook
                default:
5529 9ee6e8bb pbrook
                elementwise:
5530 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
5531 9ee6e8bb pbrook
                        if (op == 30 || op == 31 || op >= 58) {
5532 4373f3ce pbrook
                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
5533 4373f3ce pbrook
                                           neon_reg_offset(rm, pass));
5534 dd8fbd78 Filip Navara
                            TCGV_UNUSED(tmp);
5535 9ee6e8bb pbrook
                        } else {
5536 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, pass);
5537 9ee6e8bb pbrook
                        }
5538 9ee6e8bb pbrook
                        switch (op) {
5539 9ee6e8bb pbrook
                        case 1: /* VREV32 */
5540 9ee6e8bb pbrook
                            switch (size) {
5541 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5542 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp); break;
5543 9ee6e8bb pbrook
                            default: return 1;
5544 9ee6e8bb pbrook
                            }
5545 9ee6e8bb pbrook
                            break;
5546 9ee6e8bb pbrook
                        case 2: /* VREV16 */
5547 9ee6e8bb pbrook
                            if (size != 0)
5548 9ee6e8bb pbrook
                                return 1;
5549 dd8fbd78 Filip Navara
                            gen_rev16(tmp);
5550 9ee6e8bb pbrook
                            break;
5551 9ee6e8bb pbrook
                        case 8: /* CLS */
5552 9ee6e8bb pbrook
                            switch (size) {
5553 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5554 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5555 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5556 9ee6e8bb pbrook
                            default: return 1;
5557 9ee6e8bb pbrook
                            }
5558 9ee6e8bb pbrook
                            break;
5559 9ee6e8bb pbrook
                        case 9: /* CLZ */
5560 9ee6e8bb pbrook
                            switch (size) {
5561 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5562 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5563 dd8fbd78 Filip Navara
                            case 2: gen_helper_clz(tmp, tmp); break;
5564 9ee6e8bb pbrook
                            default: return 1;
5565 9ee6e8bb pbrook
                            }
5566 9ee6e8bb pbrook
                            break;
5567 9ee6e8bb pbrook
                        case 10: /* CNT */
5568 9ee6e8bb pbrook
                            if (size != 0)
5569 9ee6e8bb pbrook
                                return 1;
5570 dd8fbd78 Filip Navara
                            gen_helper_neon_cnt_u8(tmp, tmp);
5571 9ee6e8bb pbrook
                            break;
5572 9ee6e8bb pbrook
                        case 11: /* VNOT */
5573 9ee6e8bb pbrook
                            if (size != 0)
5574 9ee6e8bb pbrook
                                return 1;
5575 dd8fbd78 Filip Navara
                            tcg_gen_not_i32(tmp, tmp);
5576 9ee6e8bb pbrook
                            break;
5577 9ee6e8bb pbrook
                        case 14: /* VQABS */
5578 9ee6e8bb pbrook
                            switch (size) {
5579 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5580 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5581 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5582 9ee6e8bb pbrook
                            default: return 1;
5583 9ee6e8bb pbrook
                            }
5584 9ee6e8bb pbrook
                            break;
5585 9ee6e8bb pbrook
                        case 15: /* VQNEG */
5586 9ee6e8bb pbrook
                            switch (size) {
5587 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5588 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5589 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5590 9ee6e8bb pbrook
                            default: return 1;
5591 9ee6e8bb pbrook
                            }
5592 9ee6e8bb pbrook
                            break;
5593 9ee6e8bb pbrook
                        case 16: case 19: /* VCGT #0, VCLE #0 */
5594 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5595 9ee6e8bb pbrook
                            switch(size) {
5596 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5597 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5598 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5599 9ee6e8bb pbrook
                            default: return 1;
5600 9ee6e8bb pbrook
                            }
5601 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5602 9ee6e8bb pbrook
                            if (op == 19)
5603 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5604 9ee6e8bb pbrook
                            break;
5605 9ee6e8bb pbrook
                        case 17: case 20: /* VCGE #0, VCLT #0 */
5606 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5607 9ee6e8bb pbrook
                            switch(size) {
5608 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5609 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5610 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5611 9ee6e8bb pbrook
                            default: return 1;
5612 9ee6e8bb pbrook
                            }
5613 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5614 9ee6e8bb pbrook
                            if (op == 20)
5615 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5616 9ee6e8bb pbrook
                            break;
5617 9ee6e8bb pbrook
                        case 18: /* VCEQ #0 */
5618 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5619 9ee6e8bb pbrook
                            switch(size) {
5620 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5621 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5622 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5623 9ee6e8bb pbrook
                            default: return 1;
5624 9ee6e8bb pbrook
                            }
5625 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5626 9ee6e8bb pbrook
                            break;
5627 9ee6e8bb pbrook
                        case 22: /* VABS */
5628 9ee6e8bb pbrook
                            switch(size) {
5629 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5630 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5631 dd8fbd78 Filip Navara
                            case 2: tcg_gen_abs_i32(tmp, tmp); break;
5632 9ee6e8bb pbrook
                            default: return 1;
5633 9ee6e8bb pbrook
                            }
5634 9ee6e8bb pbrook
                            break;
5635 9ee6e8bb pbrook
                        case 23: /* VNEG */
5636 ad69471c pbrook
                            if (size == 3)
5637 ad69471c pbrook
                                return 1;
5638 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5639 dd8fbd78 Filip Navara
                            gen_neon_rsb(size, tmp, tmp2);
5640 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5641 9ee6e8bb pbrook
                            break;
5642 9ee6e8bb pbrook
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5643 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5644 dd8fbd78 Filip Navara
                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5645 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5646 9ee6e8bb pbrook
                            if (op == 27)
5647 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5648 9ee6e8bb pbrook
                            break;
5649 9ee6e8bb pbrook
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5650 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5651 dd8fbd78 Filip Navara
                            gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5652 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5653 9ee6e8bb pbrook
                            if (op == 28)
5654 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5655 9ee6e8bb pbrook
                            break;
5656 9ee6e8bb pbrook
                        case 26: /* Float VCEQ #0 */
5657 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5658 dd8fbd78 Filip Navara
                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5659 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5660 9ee6e8bb pbrook
                            break;
5661 9ee6e8bb pbrook
                        case 30: /* Float VABS */
5662 4373f3ce pbrook
                            gen_vfp_abs(0);
5663 9ee6e8bb pbrook
                            break;
5664 9ee6e8bb pbrook
                        case 31: /* Float VNEG */
5665 4373f3ce pbrook
                            gen_vfp_neg(0);
5666 9ee6e8bb pbrook
                            break;
5667 9ee6e8bb pbrook
                        case 32: /* VSWP */
5668 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5669 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
5670 9ee6e8bb pbrook
                            break;
5671 9ee6e8bb pbrook
                        case 33: /* VTRN */
5672 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5673 9ee6e8bb pbrook
                            switch (size) {
5674 dd8fbd78 Filip Navara
                            case 0: gen_neon_trn_u8(tmp, tmp2); break;
5675 dd8fbd78 Filip Navara
                            case 1: gen_neon_trn_u16(tmp, tmp2); break;
5676 9ee6e8bb pbrook
                            case 2: abort();
5677 9ee6e8bb pbrook
                            default: return 1;
5678 9ee6e8bb pbrook
                            }
5679 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
5680 9ee6e8bb pbrook
                            break;
5681 9ee6e8bb pbrook
                        case 56: /* Integer VRECPE */
5682 dd8fbd78 Filip Navara
                            gen_helper_recpe_u32(tmp, tmp, cpu_env);
5683 9ee6e8bb pbrook
                            break;
5684 9ee6e8bb pbrook
                        case 57: /* Integer VRSQRTE */
5685 dd8fbd78 Filip Navara
                            gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5686 9ee6e8bb pbrook
                            break;
5687 9ee6e8bb pbrook
                        case 58: /* Float VRECPE */
5688 4373f3ce pbrook
                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5689 9ee6e8bb pbrook
                            break;
5690 9ee6e8bb pbrook
                        case 59: /* Float VRSQRTE */
5691 4373f3ce pbrook
                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5692 9ee6e8bb pbrook
                            break;
5693 9ee6e8bb pbrook
                        case 60: /* VCVT.F32.S32 */
5694 d3587ef8 Peter Maydell
                            gen_vfp_sito(0);
5695 9ee6e8bb pbrook
                            break;
5696 9ee6e8bb pbrook
                        case 61: /* VCVT.F32.U32 */
5697 d3587ef8 Peter Maydell
                            gen_vfp_uito(0);
5698 9ee6e8bb pbrook
                            break;
5699 9ee6e8bb pbrook
                        case 62: /* VCVT.S32.F32 */
5700 d3587ef8 Peter Maydell
                            gen_vfp_tosiz(0);
5701 9ee6e8bb pbrook
                            break;
5702 9ee6e8bb pbrook
                        case 63: /* VCVT.U32.F32 */
5703 d3587ef8 Peter Maydell
                            gen_vfp_touiz(0);
5704 9ee6e8bb pbrook
                            break;
5705 9ee6e8bb pbrook
                        default:
5706 9ee6e8bb pbrook
                            /* Reserved: 21, 29, 39-56 */
5707 9ee6e8bb pbrook
                            return 1;
5708 9ee6e8bb pbrook
                        }
5709 9ee6e8bb pbrook
                        if (op == 30 || op == 31 || op >= 58) {
5710 4373f3ce pbrook
                            tcg_gen_st_f32(cpu_F0s, cpu_env,
5711 4373f3ce pbrook
                                           neon_reg_offset(rd, pass));
5712 9ee6e8bb pbrook
                        } else {
5713 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass, tmp);
5714 9ee6e8bb pbrook
                        }
5715 9ee6e8bb pbrook
                    }
5716 9ee6e8bb pbrook
                    break;
5717 9ee6e8bb pbrook
                }
5718 9ee6e8bb pbrook
            } else if ((insn & (1 << 10)) == 0) {
5719 9ee6e8bb pbrook
                /* VTBL, VTBX.  */
5720 3018f259 pbrook
                n = ((insn >> 5) & 0x18) + 8;
5721 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
5722 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 0);
5723 9ee6e8bb pbrook
                } else {
5724 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5725 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
5726 9ee6e8bb pbrook
                }
5727 8f8e3aa4 pbrook
                tmp2 = neon_load_reg(rm, 0);
5728 b75263d6 Juha Riihimรคki
                tmp4 = tcg_const_i32(rn);
5729 b75263d6 Juha Riihimรคki
                tmp5 = tcg_const_i32(n);
5730 b75263d6 Juha Riihimรคki
                gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5731 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
5732 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
5733 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 1);
5734 9ee6e8bb pbrook
                } else {
5735 7d1b0095 Peter Maydell
                    tmp = tcg_temp_new_i32();
5736 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
5737 9ee6e8bb pbrook
                }
5738 8f8e3aa4 pbrook
                tmp3 = neon_load_reg(rm, 1);
5739 b75263d6 Juha Riihimรคki
                gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5740 25aeb69b Juha Riihimรคki
                tcg_temp_free_i32(tmp5);
5741 25aeb69b Juha Riihimรคki
                tcg_temp_free_i32(tmp4);
5742 8f8e3aa4 pbrook
                neon_store_reg(rd, 0, tmp2);
5743 3018f259 pbrook
                neon_store_reg(rd, 1, tmp3);
5744 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
5745 9ee6e8bb pbrook
            } else if ((insn & 0x380) == 0) {
5746 9ee6e8bb pbrook
                /* VDUP */
5747 9ee6e8bb pbrook
                if (insn & (1 << 19)) {
5748 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
5749 9ee6e8bb pbrook
                } else {
5750 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 0);
5751 9ee6e8bb pbrook
                }
5752 9ee6e8bb pbrook
                if (insn & (1 << 16)) {
5753 dd8fbd78 Filip Navara
                    gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5754 9ee6e8bb pbrook
                } else if (insn & (1 << 17)) {
5755 9ee6e8bb pbrook
                    if ((insn >> 18) & 1)
5756 dd8fbd78 Filip Navara
                        gen_neon_dup_high16(tmp);
5757 9ee6e8bb pbrook
                    else
5758 dd8fbd78 Filip Navara
                        gen_neon_dup_low16(tmp);
5759 9ee6e8bb pbrook
                }
5760 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
5761 7d1b0095 Peter Maydell
                    tmp2 = tcg_temp_new_i32();
5762 dd8fbd78 Filip Navara
                    tcg_gen_mov_i32(tmp2, tmp);
5763 dd8fbd78 Filip Navara
                    neon_store_reg(rd, pass, tmp2);
5764 9ee6e8bb pbrook
                }
5765 7d1b0095 Peter Maydell
                tcg_temp_free_i32(tmp);
5766 9ee6e8bb pbrook
            } else {
5767 9ee6e8bb pbrook
                return 1;
5768 9ee6e8bb pbrook
            }
5769 9ee6e8bb pbrook
        }
5770 9ee6e8bb pbrook
    }
5771 9ee6e8bb pbrook
    return 0;
5772 9ee6e8bb pbrook
}
5773 9ee6e8bb pbrook
5774 fe1479c3 pbrook
static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5775 fe1479c3 pbrook
{
5776 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
5777 fe1479c3 pbrook
    int crm = insn & 0xf;
5778 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
5779 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
5780 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
5781 fe1479c3 pbrook
    TCGv tmp;
5782 fe1479c3 pbrook
5783 ca27c052 Peter Maydell
    /* Minimal set of debug registers, since we don't support debug */
5784 ca27c052 Peter Maydell
    if (op1 == 0 && crn == 0 && op2 == 0) {
5785 ca27c052 Peter Maydell
        switch (crm) {
5786 ca27c052 Peter Maydell
        case 0:
5787 ca27c052 Peter Maydell
            /* DBGDIDR: just RAZ. In particular this means the
5788 ca27c052 Peter Maydell
             * "debug architecture version" bits will read as
5789 ca27c052 Peter Maydell
             * a reserved value, which should cause Linux to
5790 ca27c052 Peter Maydell
             * not try to use the debug hardware.
5791 ca27c052 Peter Maydell
             */
5792 ca27c052 Peter Maydell
            tmp = tcg_const_i32(0);
5793 ca27c052 Peter Maydell
            store_reg(s, rt, tmp);
5794 ca27c052 Peter Maydell
            return 0;
5795 ca27c052 Peter Maydell
        case 1:
5796 ca27c052 Peter Maydell
        case 2:
5797 ca27c052 Peter Maydell
            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
5798 ca27c052 Peter Maydell
             * don't implement memory mapped debug components
5799 ca27c052 Peter Maydell
             */
5800 ca27c052 Peter Maydell
            if (ENABLE_ARCH_7) {
5801 ca27c052 Peter Maydell
                tmp = tcg_const_i32(0);
5802 ca27c052 Peter Maydell
                store_reg(s, rt, tmp);
5803 ca27c052 Peter Maydell
                return 0;
5804 ca27c052 Peter Maydell
            }
5805 ca27c052 Peter Maydell
            break;
5806 ca27c052 Peter Maydell
        default:
5807 ca27c052 Peter Maydell
            break;
5808 ca27c052 Peter Maydell
        }
5809 ca27c052 Peter Maydell
    }
5810 ca27c052 Peter Maydell
5811 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5812 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5813 fe1479c3 pbrook
            /* TEECR */
5814 fe1479c3 pbrook
            if (IS_USER(s))
5815 fe1479c3 pbrook
                return 1;
5816 fe1479c3 pbrook
            tmp = load_cpu_field(teecr);
5817 fe1479c3 pbrook
            store_reg(s, rt, tmp);
5818 fe1479c3 pbrook
            return 0;
5819 fe1479c3 pbrook
        }
5820 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5821 fe1479c3 pbrook
            /* TEEHBR */
5822 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
5823 fe1479c3 pbrook
                return 1;
5824 fe1479c3 pbrook
            tmp = load_cpu_field(teehbr);
5825 fe1479c3 pbrook
            store_reg(s, rt, tmp);
5826 fe1479c3 pbrook
            return 0;
5827 fe1479c3 pbrook
        }
5828 fe1479c3 pbrook
    }
5829 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5830 fe1479c3 pbrook
            op1, crn, crm, op2);
5831 fe1479c3 pbrook
    return 1;
5832 fe1479c3 pbrook
}
5833 fe1479c3 pbrook
5834 fe1479c3 pbrook
static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5835 fe1479c3 pbrook
{
5836 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
5837 fe1479c3 pbrook
    int crm = insn & 0xf;
5838 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
5839 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
5840 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
5841 fe1479c3 pbrook
    TCGv tmp;
5842 fe1479c3 pbrook
5843 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5844 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5845 fe1479c3 pbrook
            /* TEECR */
5846 fe1479c3 pbrook
            if (IS_USER(s))
5847 fe1479c3 pbrook
                return 1;
5848 fe1479c3 pbrook
            tmp = load_reg(s, rt);
5849 fe1479c3 pbrook
            gen_helper_set_teecr(cpu_env, tmp);
5850 7d1b0095 Peter Maydell
            tcg_temp_free_i32(tmp);
5851 fe1479c3 pbrook
            return 0;
5852 fe1479c3 pbrook
        }
5853 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5854 fe1479c3 pbrook
            /* TEEHBR */
5855 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
5856 fe1479c3 pbrook
                return 1;
5857 fe1479c3 pbrook
            tmp = load_reg(s, rt);
5858 fe1479c3 pbrook
            store_cpu_field(tmp, teehbr);
5859 fe1479c3 pbrook
            return 0;
5860 fe1479c3 pbrook
        }
5861 fe1479c3 pbrook
    }
5862 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5863 fe1479c3 pbrook
            op1, crn, crm, op2);
5864 fe1479c3 pbrook
    return 1;
5865 fe1479c3 pbrook
}
5866 fe1479c3 pbrook
5867 9ee6e8bb pbrook
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5868 9ee6e8bb pbrook
{
5869 9ee6e8bb pbrook
    int cpnum;
5870 9ee6e8bb pbrook
5871 9ee6e8bb pbrook
    cpnum = (insn >> 8) & 0xf;
5872 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_XSCALE)
5873 9ee6e8bb pbrook
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5874 9ee6e8bb pbrook
        return 1;
5875 9ee6e8bb pbrook
5876 9ee6e8bb pbrook
    switch (cpnum) {
5877 9ee6e8bb pbrook
      case 0:
5878 9ee6e8bb pbrook
      case 1:
5879 9ee6e8bb pbrook
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5880 9ee6e8bb pbrook
            return disas_iwmmxt_insn(env, s, insn);
5881 9ee6e8bb pbrook
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5882 9ee6e8bb pbrook
            return disas_dsp_insn(env, s, insn);
5883 9ee6e8bb pbrook
        }
5884 9ee6e8bb pbrook
        return 1;
5885 9ee6e8bb pbrook
    case 10:
5886 9ee6e8bb pbrook
    case 11:
5887 9ee6e8bb pbrook
        return disas_vfp_insn (env, s, insn);
5888 fe1479c3 pbrook
    case 14:
5889 fe1479c3 pbrook
        /* Coprocessors 7-15 are architecturally reserved by ARM.
5890 fe1479c3 pbrook
           Unfortunately Intel decided to ignore this.  */
5891 fe1479c3 pbrook
        if (arm_feature(env, ARM_FEATURE_XSCALE))
5892 fe1479c3 pbrook
            goto board;
5893 fe1479c3 pbrook
        if (insn & (1 << 20))
5894 fe1479c3 pbrook
            return disas_cp14_read(env, s, insn);
5895 fe1479c3 pbrook
        else
5896 fe1479c3 pbrook
            return disas_cp14_write(env, s, insn);
5897 9ee6e8bb pbrook
    case 15:
5898 9ee6e8bb pbrook
        return disas_cp15_insn (env, s, insn);
5899 9ee6e8bb pbrook
    default:
5900 fe1479c3 pbrook
    board:
5901 9ee6e8bb pbrook
        /* Unknown coprocessor.  See if the board has hooked it.  */
5902 9ee6e8bb pbrook
        return disas_cp_insn (env, s, insn);
5903 9ee6e8bb pbrook
    }
5904 9ee6e8bb pbrook
}
5905 9ee6e8bb pbrook
5906 5e3f878a pbrook
5907 5e3f878a pbrook
/* Store a 64-bit value to a register pair.  Clobbers val.  */
5908 a7812ae4 pbrook
static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5909 5e3f878a pbrook
{
5910 5e3f878a pbrook
    TCGv tmp;
5911 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
5912 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
5913 5e3f878a pbrook
    store_reg(s, rlow, tmp);
5914 7d1b0095 Peter Maydell
    tmp = tcg_temp_new_i32();
5915 5e3f878a pbrook
    tcg_gen_shri_i64(val, val, 32);
5916 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
5917 5e3f878a pbrook
    store_reg(s, rhigh, tmp);
5918 5e3f878a pbrook
}
5919 5e3f878a pbrook
5920 5e3f878a pbrook
/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
5921 a7812ae4 pbrook
static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5922 5e3f878a pbrook
{
5923 a7812ae4 pbrook
    TCGv_i64 tmp;
5924 5e3f878a pbrook
    TCGv tmp2;
5925 5e3f878a pbrook
5926 36aa55dc pbrook
    /* Load value and extend to 64 bits.  */
5927 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
5928 5e3f878a pbrook
    tmp2 = load_reg(s, rlow);
5929 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp, tmp2);
5930 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp2);
5931 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
5932 b75263d6 Juha Riihimรคki
    tcg_temp_free_i64(tmp);
5933 5e3f878a pbrook
}
5934 5e3f878a pbrook
5935 5e3f878a pbrook
/* load and add a 64-bit value from a register pair.  */
5936 a7812ae4 pbrook
static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5937 5e3f878a pbrook
{
5938 a7812ae4 pbrook
    TCGv_i64 tmp;
5939 36aa55dc pbrook
    TCGv tmpl;
5940 36aa55dc pbrook
    TCGv tmph;
5941 5e3f878a pbrook
5942 5e3f878a pbrook
    /* Load 64-bit value rd:rn.  */
5943 36aa55dc pbrook
    tmpl = load_reg(s, rlow);
5944 36aa55dc pbrook
    tmph = load_reg(s, rhigh);
5945 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
5946 36aa55dc pbrook
    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5947 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmpl);
5948 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmph);
5949 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
5950 b75263d6 Juha Riihimรคki
    tcg_temp_free_i64(tmp);
5951 5e3f878a pbrook
}
5952 5e3f878a pbrook
5953 5e3f878a pbrook
/* Set N and Z flags from a 64-bit value.  */
5954 a7812ae4 pbrook
static void gen_logicq_cc(TCGv_i64 val)
5955 5e3f878a pbrook
{
5956 7d1b0095 Peter Maydell
    TCGv tmp = tcg_temp_new_i32();
5957 5e3f878a pbrook
    gen_helper_logicq_cc(tmp, val);
5958 6fbe23d5 pbrook
    gen_logic_CC(tmp);
5959 7d1b0095 Peter Maydell
    tcg_temp_free_i32(tmp);
5960 5e3f878a pbrook
}
5961 5e3f878a pbrook
5962 426f5abc Paul Brook
/* Load/Store exclusive instructions are implemented by remembering
5963 426f5abc Paul Brook
   the value/address loaded, and seeing if these are the same
5964 426f5abc Paul Brook
   when the store is performed. This should be is sufficient to implement
5965 426f5abc Paul Brook
   the architecturally mandated semantics, and avoids having to monitor
5966 426f5abc Paul Brook
   regular stores.
5967 426f5abc Paul Brook

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