Statistics
| Branch: | Revision:

root / target-arm / translate.c @ f4918804

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

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