Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 8387da81

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

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