Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 92cdfaeb

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

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