Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 3a554c0f

History | View | Annotate | Download (303.4 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 ad69471c pbrook
80 b26eefb6 pbrook
/* FIXME:  These should be removed.  */
81 8f8e3aa4 pbrook
static TCGv cpu_T[2];
82 a7812ae4 pbrook
static TCGv cpu_F0s, cpu_F1s;
83 a7812ae4 pbrook
static TCGv_i64 cpu_F0d, cpu_F1d;
84 b26eefb6 pbrook
85 2e70f6ef pbrook
#define ICOUNT_TEMP cpu_T[0]
86 2e70f6ef pbrook
#include "gen-icount.h"
87 2e70f6ef pbrook
88 155c3eac Filip Navara
static const char *regnames[] =
89 155c3eac Filip Navara
    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
90 155c3eac Filip Navara
      "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
91 155c3eac Filip Navara
92 b26eefb6 pbrook
/* initialize TCG globals.  */
93 b26eefb6 pbrook
void arm_translate_init(void)
94 b26eefb6 pbrook
{
95 155c3eac Filip Navara
    int i;
96 155c3eac Filip Navara
97 a7812ae4 pbrook
    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
98 a7812ae4 pbrook
99 a7812ae4 pbrook
    cpu_T[0] = tcg_global_reg_new_i32(TCG_AREG1, "T0");
100 a7812ae4 pbrook
    cpu_T[1] = tcg_global_reg_new_i32(TCG_AREG2, "T1");
101 b26eefb6 pbrook
102 155c3eac Filip Navara
    for (i = 0; i < 16; i++) {
103 155c3eac Filip Navara
        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
104 155c3eac Filip Navara
                                          offsetof(CPUState, regs[i]),
105 155c3eac Filip Navara
                                          regnames[i]);
106 155c3eac Filip Navara
    }
107 155c3eac Filip Navara
108 a7812ae4 pbrook
#define GEN_HELPER 2
109 a7812ae4 pbrook
#include "helpers.h"
110 b26eefb6 pbrook
}
111 b26eefb6 pbrook
112 b26eefb6 pbrook
static int num_temps;
113 b26eefb6 pbrook
114 b26eefb6 pbrook
/* Allocate a temporary variable.  */
115 a7812ae4 pbrook
static TCGv_i32 new_tmp(void)
116 b26eefb6 pbrook
{
117 12edd4f2 Filip Navara
    num_temps++;
118 12edd4f2 Filip Navara
    return tcg_temp_new_i32();
119 b26eefb6 pbrook
}
120 b26eefb6 pbrook
121 b26eefb6 pbrook
/* Release a temporary variable.  */
122 b26eefb6 pbrook
static void dead_tmp(TCGv tmp)
123 b26eefb6 pbrook
{
124 12edd4f2 Filip Navara
    tcg_temp_free(tmp);
125 b26eefb6 pbrook
    num_temps--;
126 b26eefb6 pbrook
}
127 b26eefb6 pbrook
128 d9ba4830 pbrook
static inline TCGv load_cpu_offset(int offset)
129 d9ba4830 pbrook
{
130 d9ba4830 pbrook
    TCGv tmp = new_tmp();
131 d9ba4830 pbrook
    tcg_gen_ld_i32(tmp, cpu_env, offset);
132 d9ba4830 pbrook
    return tmp;
133 d9ba4830 pbrook
}
134 d9ba4830 pbrook
135 d9ba4830 pbrook
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
136 d9ba4830 pbrook
137 d9ba4830 pbrook
static inline void store_cpu_offset(TCGv var, int offset)
138 d9ba4830 pbrook
{
139 d9ba4830 pbrook
    tcg_gen_st_i32(var, cpu_env, offset);
140 d9ba4830 pbrook
    dead_tmp(var);
141 d9ba4830 pbrook
}
142 d9ba4830 pbrook
143 d9ba4830 pbrook
#define store_cpu_field(var, name) \
144 d9ba4830 pbrook
    store_cpu_offset(var, offsetof(CPUState, name))
145 d9ba4830 pbrook
146 b26eefb6 pbrook
/* Set a variable to the value of a CPU register.  */
147 b26eefb6 pbrook
static void load_reg_var(DisasContext *s, TCGv var, int reg)
148 b26eefb6 pbrook
{
149 b26eefb6 pbrook
    if (reg == 15) {
150 b26eefb6 pbrook
        uint32_t addr;
151 b26eefb6 pbrook
        /* normaly, since we updated PC, we need only to add one insn */
152 b26eefb6 pbrook
        if (s->thumb)
153 b26eefb6 pbrook
            addr = (long)s->pc + 2;
154 b26eefb6 pbrook
        else
155 b26eefb6 pbrook
            addr = (long)s->pc + 4;
156 b26eefb6 pbrook
        tcg_gen_movi_i32(var, addr);
157 b26eefb6 pbrook
    } else {
158 155c3eac Filip Navara
        tcg_gen_mov_i32(var, cpu_R[reg]);
159 b26eefb6 pbrook
    }
160 b26eefb6 pbrook
}
161 b26eefb6 pbrook
162 b26eefb6 pbrook
/* Create a new temporary and set it to the value of a CPU register.  */
163 b26eefb6 pbrook
static inline TCGv load_reg(DisasContext *s, int reg)
164 b26eefb6 pbrook
{
165 b26eefb6 pbrook
    TCGv tmp = new_tmp();
166 b26eefb6 pbrook
    load_reg_var(s, tmp, reg);
167 b26eefb6 pbrook
    return tmp;
168 b26eefb6 pbrook
}
169 b26eefb6 pbrook
170 b26eefb6 pbrook
/* Set a CPU register.  The source must be a temporary and will be
171 b26eefb6 pbrook
   marked as dead.  */
172 b26eefb6 pbrook
static void store_reg(DisasContext *s, int reg, TCGv var)
173 b26eefb6 pbrook
{
174 b26eefb6 pbrook
    if (reg == 15) {
175 b26eefb6 pbrook
        tcg_gen_andi_i32(var, var, ~1);
176 b26eefb6 pbrook
        s->is_jmp = DISAS_JUMP;
177 b26eefb6 pbrook
    }
178 155c3eac Filip Navara
    tcg_gen_mov_i32(cpu_R[reg], var);
179 b26eefb6 pbrook
    dead_tmp(var);
180 b26eefb6 pbrook
}
181 b26eefb6 pbrook
182 b26eefb6 pbrook
183 b26eefb6 pbrook
/* Basic operations.  */
184 b26eefb6 pbrook
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
185 b26eefb6 pbrook
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
186 b26eefb6 pbrook
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
187 b26eefb6 pbrook
188 b26eefb6 pbrook
#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
189 b26eefb6 pbrook
#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
190 b26eefb6 pbrook
191 b26eefb6 pbrook
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
192 b26eefb6 pbrook
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
193 b26eefb6 pbrook
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
194 b26eefb6 pbrook
195 b26eefb6 pbrook
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
196 b26eefb6 pbrook
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
197 b26eefb6 pbrook
198 b26eefb6 pbrook
/* Value extensions.  */
199 86831435 pbrook
#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
200 86831435 pbrook
#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
201 b26eefb6 pbrook
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
202 b26eefb6 pbrook
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
203 b26eefb6 pbrook
204 1497c961 pbrook
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
205 1497c961 pbrook
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
206 8f01245e pbrook
207 b26eefb6 pbrook
208 d9ba4830 pbrook
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
209 d9ba4830 pbrook
/* Set NZCV flags from the high 4 bits of var.  */
210 d9ba4830 pbrook
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
211 d9ba4830 pbrook
212 d9ba4830 pbrook
static void gen_exception(int excp)
213 d9ba4830 pbrook
{
214 d9ba4830 pbrook
    TCGv tmp = new_tmp();
215 d9ba4830 pbrook
    tcg_gen_movi_i32(tmp, excp);
216 d9ba4830 pbrook
    gen_helper_exception(tmp);
217 d9ba4830 pbrook
    dead_tmp(tmp);
218 d9ba4830 pbrook
}
219 d9ba4830 pbrook
220 3670669c pbrook
static void gen_smul_dual(TCGv a, TCGv b)
221 3670669c pbrook
{
222 3670669c pbrook
    TCGv tmp1 = new_tmp();
223 3670669c pbrook
    TCGv tmp2 = new_tmp();
224 22478e79 balrog
    tcg_gen_ext16s_i32(tmp1, a);
225 22478e79 balrog
    tcg_gen_ext16s_i32(tmp2, b);
226 3670669c pbrook
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
227 3670669c pbrook
    dead_tmp(tmp2);
228 3670669c pbrook
    tcg_gen_sari_i32(a, a, 16);
229 3670669c pbrook
    tcg_gen_sari_i32(b, b, 16);
230 3670669c pbrook
    tcg_gen_mul_i32(b, b, a);
231 3670669c pbrook
    tcg_gen_mov_i32(a, tmp1);
232 3670669c pbrook
    dead_tmp(tmp1);
233 3670669c pbrook
}
234 3670669c pbrook
235 3670669c pbrook
/* Byteswap each halfword.  */
236 3670669c pbrook
static void gen_rev16(TCGv var)
237 3670669c pbrook
{
238 3670669c pbrook
    TCGv tmp = new_tmp();
239 3670669c pbrook
    tcg_gen_shri_i32(tmp, var, 8);
240 3670669c pbrook
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
241 3670669c pbrook
    tcg_gen_shli_i32(var, var, 8);
242 3670669c pbrook
    tcg_gen_andi_i32(var, var, 0xff00ff00);
243 3670669c pbrook
    tcg_gen_or_i32(var, var, tmp);
244 3670669c pbrook
    dead_tmp(tmp);
245 3670669c pbrook
}
246 3670669c pbrook
247 3670669c pbrook
/* Byteswap low halfword and sign extend.  */
248 3670669c pbrook
static void gen_revsh(TCGv var)
249 3670669c pbrook
{
250 3670669c pbrook
    TCGv tmp = new_tmp();
251 3670669c pbrook
    tcg_gen_shri_i32(tmp, var, 8);
252 3670669c pbrook
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
253 3670669c pbrook
    tcg_gen_shli_i32(var, var, 8);
254 3670669c pbrook
    tcg_gen_ext8s_i32(var, var);
255 3670669c pbrook
    tcg_gen_or_i32(var, var, tmp);
256 3670669c pbrook
    dead_tmp(tmp);
257 3670669c pbrook
}
258 3670669c pbrook
259 3670669c pbrook
/* Unsigned bitfield extract.  */
260 3670669c pbrook
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
261 3670669c pbrook
{
262 3670669c pbrook
    if (shift)
263 3670669c pbrook
        tcg_gen_shri_i32(var, var, shift);
264 3670669c pbrook
    tcg_gen_andi_i32(var, var, mask);
265 3670669c pbrook
}
266 3670669c pbrook
267 3670669c pbrook
/* Signed bitfield extract.  */
268 3670669c pbrook
static void gen_sbfx(TCGv var, int shift, int width)
269 3670669c pbrook
{
270 3670669c pbrook
    uint32_t signbit;
271 3670669c pbrook
272 3670669c pbrook
    if (shift)
273 3670669c pbrook
        tcg_gen_sari_i32(var, var, shift);
274 3670669c pbrook
    if (shift + width < 32) {
275 3670669c pbrook
        signbit = 1u << (width - 1);
276 3670669c pbrook
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
277 3670669c pbrook
        tcg_gen_xori_i32(var, var, signbit);
278 3670669c pbrook
        tcg_gen_subi_i32(var, var, signbit);
279 3670669c pbrook
    }
280 3670669c pbrook
}
281 3670669c pbrook
282 3670669c pbrook
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
283 3670669c pbrook
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
284 3670669c pbrook
{
285 3670669c pbrook
    tcg_gen_andi_i32(val, val, mask);
286 8f8e3aa4 pbrook
    tcg_gen_shli_i32(val, val, shift);
287 8f8e3aa4 pbrook
    tcg_gen_andi_i32(base, base, ~(mask << shift));
288 3670669c pbrook
    tcg_gen_or_i32(dest, base, val);
289 3670669c pbrook
}
290 3670669c pbrook
291 d9ba4830 pbrook
/* Round the top 32 bits of a 64-bit value.  */
292 d9ba4830 pbrook
static void gen_roundqd(TCGv a, TCGv b)
293 3670669c pbrook
{
294 d9ba4830 pbrook
    tcg_gen_shri_i32(a, a, 31);
295 d9ba4830 pbrook
    tcg_gen_add_i32(a, a, b);
296 3670669c pbrook
}
297 3670669c pbrook
298 8f01245e pbrook
/* FIXME: Most targets have native widening multiplication.
299 8f01245e pbrook
   It would be good to use that instead of a full wide multiply.  */
300 5e3f878a pbrook
/* 32x32->64 multiply.  Marks inputs as dead.  */
301 a7812ae4 pbrook
static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
302 5e3f878a pbrook
{
303 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
304 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
305 5e3f878a pbrook
306 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp1, a);
307 5e3f878a pbrook
    dead_tmp(a);
308 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp2, b);
309 5e3f878a pbrook
    dead_tmp(b);
310 5e3f878a pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
311 5e3f878a pbrook
    return tmp1;
312 5e3f878a pbrook
}
313 5e3f878a pbrook
314 a7812ae4 pbrook
static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
315 5e3f878a pbrook
{
316 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
317 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
318 5e3f878a pbrook
319 5e3f878a pbrook
    tcg_gen_ext_i32_i64(tmp1, a);
320 5e3f878a pbrook
    dead_tmp(a);
321 5e3f878a pbrook
    tcg_gen_ext_i32_i64(tmp2, b);
322 5e3f878a pbrook
    dead_tmp(b);
323 5e3f878a pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
324 5e3f878a pbrook
    return tmp1;
325 5e3f878a pbrook
}
326 5e3f878a pbrook
327 8f01245e pbrook
/* Unsigned 32x32->64 multiply.  */
328 396e467c Filip Navara
static void gen_mull(TCGv a, TCGv b)
329 8f01245e pbrook
{
330 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
331 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
332 8f01245e pbrook
333 396e467c Filip Navara
    tcg_gen_extu_i32_i64(tmp1, a);
334 396e467c Filip Navara
    tcg_gen_extu_i32_i64(tmp2, b);
335 8f01245e pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
336 396e467c Filip Navara
    tcg_gen_trunc_i64_i32(a, tmp1);
337 8f01245e pbrook
    tcg_gen_shri_i64(tmp1, tmp1, 32);
338 396e467c Filip Navara
    tcg_gen_trunc_i64_i32(b, tmp1);
339 8f01245e pbrook
}
340 8f01245e pbrook
341 8f01245e pbrook
/* Signed 32x32->64 multiply.  */
342 d9ba4830 pbrook
static void gen_imull(TCGv a, TCGv b)
343 8f01245e pbrook
{
344 a7812ae4 pbrook
    TCGv_i64 tmp1 = tcg_temp_new_i64();
345 a7812ae4 pbrook
    TCGv_i64 tmp2 = tcg_temp_new_i64();
346 8f01245e pbrook
347 d9ba4830 pbrook
    tcg_gen_ext_i32_i64(tmp1, a);
348 d9ba4830 pbrook
    tcg_gen_ext_i32_i64(tmp2, b);
349 8f01245e pbrook
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
350 d9ba4830 pbrook
    tcg_gen_trunc_i64_i32(a, tmp1);
351 8f01245e pbrook
    tcg_gen_shri_i64(tmp1, tmp1, 32);
352 d9ba4830 pbrook
    tcg_gen_trunc_i64_i32(b, tmp1);
353 d9ba4830 pbrook
}
354 d9ba4830 pbrook
355 8f01245e pbrook
/* Swap low and high halfwords.  */
356 8f01245e pbrook
static void gen_swap_half(TCGv var)
357 8f01245e pbrook
{
358 8f01245e pbrook
    TCGv tmp = new_tmp();
359 8f01245e pbrook
    tcg_gen_shri_i32(tmp, var, 16);
360 8f01245e pbrook
    tcg_gen_shli_i32(var, var, 16);
361 8f01245e pbrook
    tcg_gen_or_i32(var, var, tmp);
362 3670669c pbrook
    dead_tmp(tmp);
363 8f01245e pbrook
}
364 8f01245e pbrook
365 b26eefb6 pbrook
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
366 b26eefb6 pbrook
    tmp = (t0 ^ t1) & 0x8000;
367 b26eefb6 pbrook
    t0 &= ~0x8000;
368 b26eefb6 pbrook
    t1 &= ~0x8000;
369 b26eefb6 pbrook
    t0 = (t0 + t1) ^ tmp;
370 b26eefb6 pbrook
 */
371 b26eefb6 pbrook
372 b26eefb6 pbrook
static void gen_add16(TCGv t0, TCGv t1)
373 b26eefb6 pbrook
{
374 b26eefb6 pbrook
    TCGv tmp = new_tmp();
375 b26eefb6 pbrook
    tcg_gen_xor_i32(tmp, t0, t1);
376 b26eefb6 pbrook
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
377 b26eefb6 pbrook
    tcg_gen_andi_i32(t0, t0, ~0x8000);
378 b26eefb6 pbrook
    tcg_gen_andi_i32(t1, t1, ~0x8000);
379 b26eefb6 pbrook
    tcg_gen_add_i32(t0, t0, t1);
380 b26eefb6 pbrook
    tcg_gen_xor_i32(t0, t0, tmp);
381 b26eefb6 pbrook
    dead_tmp(tmp);
382 b26eefb6 pbrook
    dead_tmp(t1);
383 b26eefb6 pbrook
}
384 b26eefb6 pbrook
385 9a119ff6 pbrook
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
386 9a119ff6 pbrook
387 b26eefb6 pbrook
/* Set CF to the top bit of var.  */
388 b26eefb6 pbrook
static void gen_set_CF_bit31(TCGv var)
389 b26eefb6 pbrook
{
390 b26eefb6 pbrook
    TCGv tmp = new_tmp();
391 b26eefb6 pbrook
    tcg_gen_shri_i32(tmp, var, 31);
392 4cc633c3 balrog
    gen_set_CF(tmp);
393 b26eefb6 pbrook
    dead_tmp(tmp);
394 b26eefb6 pbrook
}
395 b26eefb6 pbrook
396 b26eefb6 pbrook
/* Set N and Z flags from var.  */
397 b26eefb6 pbrook
static inline void gen_logic_CC(TCGv var)
398 b26eefb6 pbrook
{
399 6fbe23d5 pbrook
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
400 6fbe23d5 pbrook
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
401 b26eefb6 pbrook
}
402 b26eefb6 pbrook
403 b26eefb6 pbrook
/* T0 += T1 + CF.  */
404 396e467c Filip Navara
static void gen_adc(TCGv t0, TCGv t1)
405 b26eefb6 pbrook
{
406 d9ba4830 pbrook
    TCGv tmp;
407 396e467c Filip Navara
    tcg_gen_add_i32(t0, t0, t1);
408 d9ba4830 pbrook
    tmp = load_cpu_field(CF);
409 396e467c Filip Navara
    tcg_gen_add_i32(t0, t0, tmp);
410 b26eefb6 pbrook
    dead_tmp(tmp);
411 b26eefb6 pbrook
}
412 b26eefb6 pbrook
413 e9bb4aa9 Juha Riihimรคki
/* dest = T0 + T1 + CF. */
414 e9bb4aa9 Juha Riihimรคki
static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
415 e9bb4aa9 Juha Riihimรคki
{
416 e9bb4aa9 Juha Riihimรคki
    TCGv tmp;
417 e9bb4aa9 Juha Riihimรคki
    tcg_gen_add_i32(dest, t0, t1);
418 e9bb4aa9 Juha Riihimรคki
    tmp = load_cpu_field(CF);
419 e9bb4aa9 Juha Riihimรคki
    tcg_gen_add_i32(dest, dest, tmp);
420 e9bb4aa9 Juha Riihimรคki
    dead_tmp(tmp);
421 e9bb4aa9 Juha Riihimรคki
}
422 e9bb4aa9 Juha Riihimรคki
423 3670669c pbrook
/* dest = T0 - T1 + CF - 1.  */
424 3670669c pbrook
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
425 3670669c pbrook
{
426 d9ba4830 pbrook
    TCGv tmp;
427 3670669c pbrook
    tcg_gen_sub_i32(dest, t0, t1);
428 d9ba4830 pbrook
    tmp = load_cpu_field(CF);
429 3670669c pbrook
    tcg_gen_add_i32(dest, dest, tmp);
430 3670669c pbrook
    tcg_gen_subi_i32(dest, dest, 1);
431 3670669c pbrook
    dead_tmp(tmp);
432 3670669c pbrook
}
433 3670669c pbrook
434 b26eefb6 pbrook
/* T0 &= ~T1.  Clobbers T1.  */
435 b26eefb6 pbrook
/* FIXME: Implement bic natively.  */
436 8f8e3aa4 pbrook
static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
437 8f8e3aa4 pbrook
{
438 8f8e3aa4 pbrook
    TCGv tmp = new_tmp();
439 8f8e3aa4 pbrook
    tcg_gen_not_i32(tmp, t1);
440 8f8e3aa4 pbrook
    tcg_gen_and_i32(dest, t0, tmp);
441 8f8e3aa4 pbrook
    dead_tmp(tmp);
442 8f8e3aa4 pbrook
}
443 b26eefb6 pbrook
static inline void gen_op_bicl_T0_T1(void)
444 b26eefb6 pbrook
{
445 b26eefb6 pbrook
    gen_op_notl_T1();
446 b26eefb6 pbrook
    gen_op_andl_T0_T1();
447 b26eefb6 pbrook
}
448 b26eefb6 pbrook
449 b26eefb6 pbrook
/* FIXME:  Implement this natively.  */
450 ad69471c pbrook
#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
451 ad69471c pbrook
452 ad69471c pbrook
/* FIXME:  Implement this natively.  */
453 b26eefb6 pbrook
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
454 b26eefb6 pbrook
{
455 b26eefb6 pbrook
    TCGv tmp;
456 b26eefb6 pbrook
457 b26eefb6 pbrook
    if (i == 0)
458 b26eefb6 pbrook
        return;
459 b26eefb6 pbrook
460 b26eefb6 pbrook
    tmp = new_tmp();
461 b26eefb6 pbrook
    tcg_gen_shri_i32(tmp, t1, i);
462 b26eefb6 pbrook
    tcg_gen_shli_i32(t1, t1, 32 - i);
463 b26eefb6 pbrook
    tcg_gen_or_i32(t0, t1, tmp);
464 b26eefb6 pbrook
    dead_tmp(tmp);
465 b26eefb6 pbrook
}
466 b26eefb6 pbrook
467 9a119ff6 pbrook
static void shifter_out_im(TCGv var, int shift)
468 b26eefb6 pbrook
{
469 9a119ff6 pbrook
    TCGv tmp = new_tmp();
470 9a119ff6 pbrook
    if (shift == 0) {
471 9a119ff6 pbrook
        tcg_gen_andi_i32(tmp, var, 1);
472 b26eefb6 pbrook
    } else {
473 9a119ff6 pbrook
        tcg_gen_shri_i32(tmp, var, shift);
474 4cc633c3 balrog
        if (shift != 31)
475 9a119ff6 pbrook
            tcg_gen_andi_i32(tmp, tmp, 1);
476 9a119ff6 pbrook
    }
477 9a119ff6 pbrook
    gen_set_CF(tmp);
478 9a119ff6 pbrook
    dead_tmp(tmp);
479 9a119ff6 pbrook
}
480 b26eefb6 pbrook
481 9a119ff6 pbrook
/* Shift by immediate.  Includes special handling for shift == 0.  */
482 9a119ff6 pbrook
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
483 9a119ff6 pbrook
{
484 9a119ff6 pbrook
    switch (shiftop) {
485 9a119ff6 pbrook
    case 0: /* LSL */
486 9a119ff6 pbrook
        if (shift != 0) {
487 9a119ff6 pbrook
            if (flags)
488 9a119ff6 pbrook
                shifter_out_im(var, 32 - shift);
489 9a119ff6 pbrook
            tcg_gen_shli_i32(var, var, shift);
490 9a119ff6 pbrook
        }
491 9a119ff6 pbrook
        break;
492 9a119ff6 pbrook
    case 1: /* LSR */
493 9a119ff6 pbrook
        if (shift == 0) {
494 9a119ff6 pbrook
            if (flags) {
495 9a119ff6 pbrook
                tcg_gen_shri_i32(var, var, 31);
496 9a119ff6 pbrook
                gen_set_CF(var);
497 9a119ff6 pbrook
            }
498 9a119ff6 pbrook
            tcg_gen_movi_i32(var, 0);
499 9a119ff6 pbrook
        } else {
500 9a119ff6 pbrook
            if (flags)
501 9a119ff6 pbrook
                shifter_out_im(var, shift - 1);
502 9a119ff6 pbrook
            tcg_gen_shri_i32(var, var, shift);
503 9a119ff6 pbrook
        }
504 9a119ff6 pbrook
        break;
505 9a119ff6 pbrook
    case 2: /* ASR */
506 9a119ff6 pbrook
        if (shift == 0)
507 9a119ff6 pbrook
            shift = 32;
508 9a119ff6 pbrook
        if (flags)
509 9a119ff6 pbrook
            shifter_out_im(var, shift - 1);
510 9a119ff6 pbrook
        if (shift == 32)
511 9a119ff6 pbrook
          shift = 31;
512 9a119ff6 pbrook
        tcg_gen_sari_i32(var, var, shift);
513 9a119ff6 pbrook
        break;
514 9a119ff6 pbrook
    case 3: /* ROR/RRX */
515 9a119ff6 pbrook
        if (shift != 0) {
516 9a119ff6 pbrook
            if (flags)
517 9a119ff6 pbrook
                shifter_out_im(var, shift - 1);
518 9a119ff6 pbrook
            tcg_gen_rori_i32(var, var, shift); break;
519 9a119ff6 pbrook
        } else {
520 d9ba4830 pbrook
            TCGv tmp = load_cpu_field(CF);
521 9a119ff6 pbrook
            if (flags)
522 9a119ff6 pbrook
                shifter_out_im(var, 0);
523 9a119ff6 pbrook
            tcg_gen_shri_i32(var, var, 1);
524 b26eefb6 pbrook
            tcg_gen_shli_i32(tmp, tmp, 31);
525 b26eefb6 pbrook
            tcg_gen_or_i32(var, var, tmp);
526 b26eefb6 pbrook
            dead_tmp(tmp);
527 b26eefb6 pbrook
        }
528 b26eefb6 pbrook
    }
529 b26eefb6 pbrook
};
530 b26eefb6 pbrook
531 8984bd2e pbrook
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
532 8984bd2e pbrook
                                     TCGv shift, int flags)
533 8984bd2e pbrook
{
534 8984bd2e pbrook
    if (flags) {
535 8984bd2e pbrook
        switch (shiftop) {
536 8984bd2e pbrook
        case 0: gen_helper_shl_cc(var, var, shift); break;
537 8984bd2e pbrook
        case 1: gen_helper_shr_cc(var, var, shift); break;
538 8984bd2e pbrook
        case 2: gen_helper_sar_cc(var, var, shift); break;
539 8984bd2e pbrook
        case 3: gen_helper_ror_cc(var, var, shift); break;
540 8984bd2e pbrook
        }
541 8984bd2e pbrook
    } else {
542 8984bd2e pbrook
        switch (shiftop) {
543 8984bd2e pbrook
        case 0: gen_helper_shl(var, var, shift); break;
544 8984bd2e pbrook
        case 1: gen_helper_shr(var, var, shift); break;
545 8984bd2e pbrook
        case 2: gen_helper_sar(var, var, shift); break;
546 8984bd2e pbrook
        case 3: gen_helper_ror(var, var, shift); break;
547 8984bd2e pbrook
        }
548 8984bd2e pbrook
    }
549 8984bd2e pbrook
    dead_tmp(shift);
550 8984bd2e pbrook
}
551 8984bd2e pbrook
552 6ddbc6e4 pbrook
#define PAS_OP(pfx) \
553 6ddbc6e4 pbrook
    switch (op2) {  \
554 6ddbc6e4 pbrook
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
555 6ddbc6e4 pbrook
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
556 6ddbc6e4 pbrook
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
557 6ddbc6e4 pbrook
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
558 6ddbc6e4 pbrook
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
559 6ddbc6e4 pbrook
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
560 6ddbc6e4 pbrook
    }
561 d9ba4830 pbrook
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
562 6ddbc6e4 pbrook
{
563 a7812ae4 pbrook
    TCGv_ptr tmp;
564 6ddbc6e4 pbrook
565 6ddbc6e4 pbrook
    switch (op1) {
566 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
567 6ddbc6e4 pbrook
    case 1:
568 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
569 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
570 6ddbc6e4 pbrook
        PAS_OP(s)
571 6ddbc6e4 pbrook
        break;
572 6ddbc6e4 pbrook
    case 5:
573 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
574 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
575 6ddbc6e4 pbrook
        PAS_OP(u)
576 6ddbc6e4 pbrook
        break;
577 6ddbc6e4 pbrook
#undef gen_pas_helper
578 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
579 6ddbc6e4 pbrook
    case 2:
580 6ddbc6e4 pbrook
        PAS_OP(q);
581 6ddbc6e4 pbrook
        break;
582 6ddbc6e4 pbrook
    case 3:
583 6ddbc6e4 pbrook
        PAS_OP(sh);
584 6ddbc6e4 pbrook
        break;
585 6ddbc6e4 pbrook
    case 6:
586 6ddbc6e4 pbrook
        PAS_OP(uq);
587 6ddbc6e4 pbrook
        break;
588 6ddbc6e4 pbrook
    case 7:
589 6ddbc6e4 pbrook
        PAS_OP(uh);
590 6ddbc6e4 pbrook
        break;
591 6ddbc6e4 pbrook
#undef gen_pas_helper
592 6ddbc6e4 pbrook
    }
593 6ddbc6e4 pbrook
}
594 9ee6e8bb pbrook
#undef PAS_OP
595 9ee6e8bb pbrook
596 6ddbc6e4 pbrook
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
597 6ddbc6e4 pbrook
#define PAS_OP(pfx) \
598 6ddbc6e4 pbrook
    switch (op2) {  \
599 6ddbc6e4 pbrook
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
600 6ddbc6e4 pbrook
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
601 6ddbc6e4 pbrook
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
602 6ddbc6e4 pbrook
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
603 6ddbc6e4 pbrook
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
604 6ddbc6e4 pbrook
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
605 6ddbc6e4 pbrook
    }
606 d9ba4830 pbrook
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
607 6ddbc6e4 pbrook
{
608 a7812ae4 pbrook
    TCGv_ptr tmp;
609 6ddbc6e4 pbrook
610 6ddbc6e4 pbrook
    switch (op1) {
611 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
612 6ddbc6e4 pbrook
    case 0:
613 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
614 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
615 6ddbc6e4 pbrook
        PAS_OP(s)
616 6ddbc6e4 pbrook
        break;
617 6ddbc6e4 pbrook
    case 4:
618 a7812ae4 pbrook
        tmp = tcg_temp_new_ptr();
619 6ddbc6e4 pbrook
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
620 6ddbc6e4 pbrook
        PAS_OP(u)
621 6ddbc6e4 pbrook
        break;
622 6ddbc6e4 pbrook
#undef gen_pas_helper
623 6ddbc6e4 pbrook
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
624 6ddbc6e4 pbrook
    case 1:
625 6ddbc6e4 pbrook
        PAS_OP(q);
626 6ddbc6e4 pbrook
        break;
627 6ddbc6e4 pbrook
    case 2:
628 6ddbc6e4 pbrook
        PAS_OP(sh);
629 6ddbc6e4 pbrook
        break;
630 6ddbc6e4 pbrook
    case 5:
631 6ddbc6e4 pbrook
        PAS_OP(uq);
632 6ddbc6e4 pbrook
        break;
633 6ddbc6e4 pbrook
    case 6:
634 6ddbc6e4 pbrook
        PAS_OP(uh);
635 6ddbc6e4 pbrook
        break;
636 6ddbc6e4 pbrook
#undef gen_pas_helper
637 6ddbc6e4 pbrook
    }
638 6ddbc6e4 pbrook
}
639 9ee6e8bb pbrook
#undef PAS_OP
640 9ee6e8bb pbrook
641 d9ba4830 pbrook
static void gen_test_cc(int cc, int label)
642 d9ba4830 pbrook
{
643 d9ba4830 pbrook
    TCGv tmp;
644 d9ba4830 pbrook
    TCGv tmp2;
645 d9ba4830 pbrook
    int inv;
646 d9ba4830 pbrook
647 d9ba4830 pbrook
    switch (cc) {
648 d9ba4830 pbrook
    case 0: /* eq: Z */
649 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
650 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
651 d9ba4830 pbrook
        break;
652 d9ba4830 pbrook
    case 1: /* ne: !Z */
653 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
654 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
655 d9ba4830 pbrook
        break;
656 d9ba4830 pbrook
    case 2: /* cs: C */
657 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
658 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
659 d9ba4830 pbrook
        break;
660 d9ba4830 pbrook
    case 3: /* cc: !C */
661 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
662 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
663 d9ba4830 pbrook
        break;
664 d9ba4830 pbrook
    case 4: /* mi: N */
665 6fbe23d5 pbrook
        tmp = load_cpu_field(NF);
666 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
667 d9ba4830 pbrook
        break;
668 d9ba4830 pbrook
    case 5: /* pl: !N */
669 6fbe23d5 pbrook
        tmp = load_cpu_field(NF);
670 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
671 d9ba4830 pbrook
        break;
672 d9ba4830 pbrook
    case 6: /* vs: V */
673 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
674 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
675 d9ba4830 pbrook
        break;
676 d9ba4830 pbrook
    case 7: /* vc: !V */
677 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
678 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
679 d9ba4830 pbrook
        break;
680 d9ba4830 pbrook
    case 8: /* hi: C && !Z */
681 d9ba4830 pbrook
        inv = gen_new_label();
682 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
683 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
684 d9ba4830 pbrook
        dead_tmp(tmp);
685 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
686 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
687 d9ba4830 pbrook
        gen_set_label(inv);
688 d9ba4830 pbrook
        break;
689 d9ba4830 pbrook
    case 9: /* ls: !C || Z */
690 d9ba4830 pbrook
        tmp = load_cpu_field(CF);
691 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
692 d9ba4830 pbrook
        dead_tmp(tmp);
693 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
694 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
695 d9ba4830 pbrook
        break;
696 d9ba4830 pbrook
    case 10: /* ge: N == V -> N ^ V == 0 */
697 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
698 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
699 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
700 d9ba4830 pbrook
        dead_tmp(tmp2);
701 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
702 d9ba4830 pbrook
        break;
703 d9ba4830 pbrook
    case 11: /* lt: N != V -> N ^ V != 0 */
704 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
705 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
706 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
707 d9ba4830 pbrook
        dead_tmp(tmp2);
708 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
709 d9ba4830 pbrook
        break;
710 d9ba4830 pbrook
    case 12: /* gt: !Z && N == V */
711 d9ba4830 pbrook
        inv = gen_new_label();
712 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
713 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
714 d9ba4830 pbrook
        dead_tmp(tmp);
715 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
716 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
717 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
718 d9ba4830 pbrook
        dead_tmp(tmp2);
719 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
720 d9ba4830 pbrook
        gen_set_label(inv);
721 d9ba4830 pbrook
        break;
722 d9ba4830 pbrook
    case 13: /* le: Z || N != V */
723 6fbe23d5 pbrook
        tmp = load_cpu_field(ZF);
724 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
725 d9ba4830 pbrook
        dead_tmp(tmp);
726 d9ba4830 pbrook
        tmp = load_cpu_field(VF);
727 6fbe23d5 pbrook
        tmp2 = load_cpu_field(NF);
728 d9ba4830 pbrook
        tcg_gen_xor_i32(tmp, tmp, tmp2);
729 d9ba4830 pbrook
        dead_tmp(tmp2);
730 cb63669a pbrook
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
731 d9ba4830 pbrook
        break;
732 d9ba4830 pbrook
    default:
733 d9ba4830 pbrook
        fprintf(stderr, "Bad condition code 0x%x\n", cc);
734 d9ba4830 pbrook
        abort();
735 d9ba4830 pbrook
    }
736 d9ba4830 pbrook
    dead_tmp(tmp);
737 d9ba4830 pbrook
}
738 2c0262af bellard
739 b1d8e52e blueswir1
static const uint8_t table_logic_cc[16] = {
740 2c0262af bellard
    1, /* and */
741 2c0262af bellard
    1, /* xor */
742 2c0262af bellard
    0, /* sub */
743 2c0262af bellard
    0, /* rsb */
744 2c0262af bellard
    0, /* add */
745 2c0262af bellard
    0, /* adc */
746 2c0262af bellard
    0, /* sbc */
747 2c0262af bellard
    0, /* rsc */
748 2c0262af bellard
    1, /* andl */
749 2c0262af bellard
    1, /* xorl */
750 2c0262af bellard
    0, /* cmp */
751 2c0262af bellard
    0, /* cmn */
752 2c0262af bellard
    1, /* orr */
753 2c0262af bellard
    1, /* mov */
754 2c0262af bellard
    1, /* bic */
755 2c0262af bellard
    1, /* mvn */
756 2c0262af bellard
};
757 3b46e624 ths
758 d9ba4830 pbrook
/* Set PC and Thumb state from an immediate address.  */
759 d9ba4830 pbrook
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
760 99c475ab bellard
{
761 b26eefb6 pbrook
    TCGv tmp;
762 99c475ab bellard
763 b26eefb6 pbrook
    s->is_jmp = DISAS_UPDATE;
764 d9ba4830 pbrook
    if (s->thumb != (addr & 1)) {
765 155c3eac Filip Navara
        tmp = new_tmp();
766 d9ba4830 pbrook
        tcg_gen_movi_i32(tmp, addr & 1);
767 d9ba4830 pbrook
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
768 155c3eac Filip Navara
        dead_tmp(tmp);
769 d9ba4830 pbrook
    }
770 155c3eac Filip Navara
    tcg_gen_movi_i32(cpu_R[15], addr & ~1);
771 d9ba4830 pbrook
}
772 d9ba4830 pbrook
773 d9ba4830 pbrook
/* Set PC and Thumb state from var.  var is marked as dead.  */
774 d9ba4830 pbrook
static inline void gen_bx(DisasContext *s, TCGv var)
775 d9ba4830 pbrook
{
776 d9ba4830 pbrook
    s->is_jmp = DISAS_UPDATE;
777 155c3eac Filip Navara
    tcg_gen_andi_i32(cpu_R[15], var, ~1);
778 155c3eac Filip Navara
    tcg_gen_andi_i32(var, var, 1);
779 155c3eac Filip Navara
    store_cpu_field(var, thumb);
780 d9ba4830 pbrook
}
781 d9ba4830 pbrook
782 21aeb343 Juha Riihimรคki
/* Variant of store_reg which uses branch&exchange logic when storing
783 21aeb343 Juha Riihimรคki
   to r15 in ARM architecture v7 and above. The source must be a temporary
784 21aeb343 Juha Riihimรคki
   and will be marked as dead. */
785 21aeb343 Juha Riihimรคki
static inline void store_reg_bx(CPUState *env, DisasContext *s,
786 21aeb343 Juha Riihimรคki
                                int reg, TCGv var)
787 21aeb343 Juha Riihimรคki
{
788 21aeb343 Juha Riihimรคki
    if (reg == 15 && ENABLE_ARCH_7) {
789 21aeb343 Juha Riihimรคki
        gen_bx(s, var);
790 21aeb343 Juha Riihimรคki
    } else {
791 21aeb343 Juha Riihimรคki
        store_reg(s, reg, var);
792 21aeb343 Juha Riihimรคki
    }
793 21aeb343 Juha Riihimรคki
}
794 21aeb343 Juha Riihimรคki
795 b0109805 pbrook
static inline TCGv gen_ld8s(TCGv addr, int index)
796 b0109805 pbrook
{
797 b0109805 pbrook
    TCGv tmp = new_tmp();
798 b0109805 pbrook
    tcg_gen_qemu_ld8s(tmp, addr, index);
799 b0109805 pbrook
    return tmp;
800 b0109805 pbrook
}
801 b0109805 pbrook
static inline TCGv gen_ld8u(TCGv addr, int index)
802 b0109805 pbrook
{
803 b0109805 pbrook
    TCGv tmp = new_tmp();
804 b0109805 pbrook
    tcg_gen_qemu_ld8u(tmp, addr, index);
805 b0109805 pbrook
    return tmp;
806 b0109805 pbrook
}
807 b0109805 pbrook
static inline TCGv gen_ld16s(TCGv addr, int index)
808 b0109805 pbrook
{
809 b0109805 pbrook
    TCGv tmp = new_tmp();
810 b0109805 pbrook
    tcg_gen_qemu_ld16s(tmp, addr, index);
811 b0109805 pbrook
    return tmp;
812 b0109805 pbrook
}
813 b0109805 pbrook
static inline TCGv gen_ld16u(TCGv addr, int index)
814 b0109805 pbrook
{
815 b0109805 pbrook
    TCGv tmp = new_tmp();
816 b0109805 pbrook
    tcg_gen_qemu_ld16u(tmp, addr, index);
817 b0109805 pbrook
    return tmp;
818 b0109805 pbrook
}
819 b0109805 pbrook
static inline TCGv gen_ld32(TCGv addr, int index)
820 b0109805 pbrook
{
821 b0109805 pbrook
    TCGv tmp = new_tmp();
822 b0109805 pbrook
    tcg_gen_qemu_ld32u(tmp, addr, index);
823 b0109805 pbrook
    return tmp;
824 b0109805 pbrook
}
825 b0109805 pbrook
static inline void gen_st8(TCGv val, TCGv addr, int index)
826 b0109805 pbrook
{
827 b0109805 pbrook
    tcg_gen_qemu_st8(val, addr, index);
828 b0109805 pbrook
    dead_tmp(val);
829 b0109805 pbrook
}
830 b0109805 pbrook
static inline void gen_st16(TCGv val, TCGv addr, int index)
831 b0109805 pbrook
{
832 b0109805 pbrook
    tcg_gen_qemu_st16(val, addr, index);
833 b0109805 pbrook
    dead_tmp(val);
834 b0109805 pbrook
}
835 b0109805 pbrook
static inline void gen_st32(TCGv val, TCGv addr, int index)
836 b0109805 pbrook
{
837 b0109805 pbrook
    tcg_gen_qemu_st32(val, addr, index);
838 b0109805 pbrook
    dead_tmp(val);
839 b0109805 pbrook
}
840 b5ff1b31 bellard
841 2c0262af bellard
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
842 2c0262af bellard
{
843 b26eefb6 pbrook
    load_reg_var(s, cpu_T[0], reg);
844 2c0262af bellard
}
845 2c0262af bellard
846 2c0262af bellard
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
847 2c0262af bellard
{
848 b26eefb6 pbrook
    load_reg_var(s, cpu_T[1], reg);
849 2c0262af bellard
}
850 2c0262af bellard
851 5e3f878a pbrook
static inline void gen_set_pc_im(uint32_t val)
852 5e3f878a pbrook
{
853 155c3eac Filip Navara
    tcg_gen_movi_i32(cpu_R[15], val);
854 5e3f878a pbrook
}
855 5e3f878a pbrook
856 2c0262af bellard
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
857 2c0262af bellard
{
858 b26eefb6 pbrook
    TCGv tmp;
859 b26eefb6 pbrook
    if (reg == 15) {
860 b26eefb6 pbrook
        tmp = new_tmp();
861 b26eefb6 pbrook
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
862 b26eefb6 pbrook
    } else {
863 b26eefb6 pbrook
        tmp = cpu_T[t];
864 b26eefb6 pbrook
    }
865 155c3eac Filip Navara
    tcg_gen_mov_i32(cpu_R[reg], tmp);
866 2c0262af bellard
    if (reg == 15) {
867 b26eefb6 pbrook
        dead_tmp(tmp);
868 2c0262af bellard
        s->is_jmp = DISAS_JUMP;
869 2c0262af bellard
    }
870 2c0262af bellard
}
871 2c0262af bellard
872 2c0262af bellard
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
873 2c0262af bellard
{
874 2c0262af bellard
    gen_movl_reg_TN(s, reg, 0);
875 2c0262af bellard
}
876 2c0262af bellard
877 2c0262af bellard
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
878 2c0262af bellard
{
879 2c0262af bellard
    gen_movl_reg_TN(s, reg, 1);
880 2c0262af bellard
}
881 2c0262af bellard
882 b5ff1b31 bellard
/* Force a TB lookup after an instruction that changes the CPU state.  */
883 b5ff1b31 bellard
static inline void gen_lookup_tb(DisasContext *s)
884 b5ff1b31 bellard
{
885 a6445c52 Filip Navara
    tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
886 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
887 b5ff1b31 bellard
}
888 b5ff1b31 bellard
889 b0109805 pbrook
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
890 b0109805 pbrook
                                       TCGv var)
891 2c0262af bellard
{
892 1e8d4eec bellard
    int val, rm, shift, shiftop;
893 b26eefb6 pbrook
    TCGv offset;
894 2c0262af bellard
895 2c0262af bellard
    if (!(insn & (1 << 25))) {
896 2c0262af bellard
        /* immediate */
897 2c0262af bellard
        val = insn & 0xfff;
898 2c0262af bellard
        if (!(insn & (1 << 23)))
899 2c0262af bellard
            val = -val;
900 537730b9 bellard
        if (val != 0)
901 b0109805 pbrook
            tcg_gen_addi_i32(var, var, val);
902 2c0262af bellard
    } else {
903 2c0262af bellard
        /* shift/register */
904 2c0262af bellard
        rm = (insn) & 0xf;
905 2c0262af bellard
        shift = (insn >> 7) & 0x1f;
906 1e8d4eec bellard
        shiftop = (insn >> 5) & 3;
907 b26eefb6 pbrook
        offset = load_reg(s, rm);
908 9a119ff6 pbrook
        gen_arm_shift_im(offset, shiftop, shift, 0);
909 2c0262af bellard
        if (!(insn & (1 << 23)))
910 b0109805 pbrook
            tcg_gen_sub_i32(var, var, offset);
911 2c0262af bellard
        else
912 b0109805 pbrook
            tcg_gen_add_i32(var, var, offset);
913 b26eefb6 pbrook
        dead_tmp(offset);
914 2c0262af bellard
    }
915 2c0262af bellard
}
916 2c0262af bellard
917 191f9a93 pbrook
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
918 b0109805 pbrook
                                        int extra, TCGv var)
919 2c0262af bellard
{
920 2c0262af bellard
    int val, rm;
921 b26eefb6 pbrook
    TCGv offset;
922 3b46e624 ths
923 2c0262af bellard
    if (insn & (1 << 22)) {
924 2c0262af bellard
        /* immediate */
925 2c0262af bellard
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
926 2c0262af bellard
        if (!(insn & (1 << 23)))
927 2c0262af bellard
            val = -val;
928 18acad92 pbrook
        val += extra;
929 537730b9 bellard
        if (val != 0)
930 b0109805 pbrook
            tcg_gen_addi_i32(var, var, val);
931 2c0262af bellard
    } else {
932 2c0262af bellard
        /* register */
933 191f9a93 pbrook
        if (extra)
934 b0109805 pbrook
            tcg_gen_addi_i32(var, var, extra);
935 2c0262af bellard
        rm = (insn) & 0xf;
936 b26eefb6 pbrook
        offset = load_reg(s, rm);
937 2c0262af bellard
        if (!(insn & (1 << 23)))
938 b0109805 pbrook
            tcg_gen_sub_i32(var, var, offset);
939 2c0262af bellard
        else
940 b0109805 pbrook
            tcg_gen_add_i32(var, var, offset);
941 b26eefb6 pbrook
        dead_tmp(offset);
942 2c0262af bellard
    }
943 2c0262af bellard
}
944 2c0262af bellard
945 4373f3ce pbrook
#define VFP_OP2(name)                                                 \
946 4373f3ce pbrook
static inline void gen_vfp_##name(int dp)                             \
947 4373f3ce pbrook
{                                                                     \
948 4373f3ce pbrook
    if (dp)                                                           \
949 4373f3ce pbrook
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
950 4373f3ce pbrook
    else                                                              \
951 4373f3ce pbrook
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
952 b7bcbe95 bellard
}
953 b7bcbe95 bellard
954 4373f3ce pbrook
VFP_OP2(add)
955 4373f3ce pbrook
VFP_OP2(sub)
956 4373f3ce pbrook
VFP_OP2(mul)
957 4373f3ce pbrook
VFP_OP2(div)
958 4373f3ce pbrook
959 4373f3ce pbrook
#undef VFP_OP2
960 4373f3ce pbrook
961 4373f3ce pbrook
static inline void gen_vfp_abs(int dp)
962 4373f3ce pbrook
{
963 4373f3ce pbrook
    if (dp)
964 4373f3ce pbrook
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
965 4373f3ce pbrook
    else
966 4373f3ce pbrook
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
967 4373f3ce pbrook
}
968 4373f3ce pbrook
969 4373f3ce pbrook
static inline void gen_vfp_neg(int dp)
970 4373f3ce pbrook
{
971 4373f3ce pbrook
    if (dp)
972 4373f3ce pbrook
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
973 4373f3ce pbrook
    else
974 4373f3ce pbrook
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
975 4373f3ce pbrook
}
976 4373f3ce pbrook
977 4373f3ce pbrook
static inline void gen_vfp_sqrt(int dp)
978 4373f3ce pbrook
{
979 4373f3ce pbrook
    if (dp)
980 4373f3ce pbrook
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
981 4373f3ce pbrook
    else
982 4373f3ce pbrook
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
983 4373f3ce pbrook
}
984 4373f3ce pbrook
985 4373f3ce pbrook
static inline void gen_vfp_cmp(int dp)
986 4373f3ce pbrook
{
987 4373f3ce pbrook
    if (dp)
988 4373f3ce pbrook
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
989 4373f3ce pbrook
    else
990 4373f3ce pbrook
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
991 4373f3ce pbrook
}
992 4373f3ce pbrook
993 4373f3ce pbrook
static inline void gen_vfp_cmpe(int dp)
994 4373f3ce pbrook
{
995 4373f3ce pbrook
    if (dp)
996 4373f3ce pbrook
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
997 4373f3ce pbrook
    else
998 4373f3ce pbrook
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
999 4373f3ce pbrook
}
1000 4373f3ce pbrook
1001 4373f3ce pbrook
static inline void gen_vfp_F1_ld0(int dp)
1002 4373f3ce pbrook
{
1003 4373f3ce pbrook
    if (dp)
1004 5b340b51 balrog
        tcg_gen_movi_i64(cpu_F1d, 0);
1005 4373f3ce pbrook
    else
1006 5b340b51 balrog
        tcg_gen_movi_i32(cpu_F1s, 0);
1007 4373f3ce pbrook
}
1008 4373f3ce pbrook
1009 4373f3ce pbrook
static inline void gen_vfp_uito(int dp)
1010 4373f3ce pbrook
{
1011 4373f3ce pbrook
    if (dp)
1012 4373f3ce pbrook
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1013 4373f3ce pbrook
    else
1014 4373f3ce pbrook
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1015 4373f3ce pbrook
}
1016 4373f3ce pbrook
1017 4373f3ce pbrook
static inline void gen_vfp_sito(int dp)
1018 4373f3ce pbrook
{
1019 4373f3ce pbrook
    if (dp)
1020 66230e0d balrog
        gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1021 4373f3ce pbrook
    else
1022 66230e0d balrog
        gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1023 4373f3ce pbrook
}
1024 4373f3ce pbrook
1025 4373f3ce pbrook
static inline void gen_vfp_toui(int dp)
1026 4373f3ce pbrook
{
1027 4373f3ce pbrook
    if (dp)
1028 4373f3ce pbrook
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1029 4373f3ce pbrook
    else
1030 4373f3ce pbrook
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1031 4373f3ce pbrook
}
1032 4373f3ce pbrook
1033 4373f3ce pbrook
static inline void gen_vfp_touiz(int dp)
1034 4373f3ce pbrook
{
1035 4373f3ce pbrook
    if (dp)
1036 4373f3ce pbrook
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1037 4373f3ce pbrook
    else
1038 4373f3ce pbrook
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1039 4373f3ce pbrook
}
1040 4373f3ce pbrook
1041 4373f3ce pbrook
static inline void gen_vfp_tosi(int dp)
1042 4373f3ce pbrook
{
1043 4373f3ce pbrook
    if (dp)
1044 4373f3ce pbrook
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1045 4373f3ce pbrook
    else
1046 4373f3ce pbrook
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1047 4373f3ce pbrook
}
1048 4373f3ce pbrook
1049 4373f3ce pbrook
static inline void gen_vfp_tosiz(int dp)
1050 9ee6e8bb pbrook
{
1051 9ee6e8bb pbrook
    if (dp)
1052 4373f3ce pbrook
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1053 9ee6e8bb pbrook
    else
1054 4373f3ce pbrook
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1055 4373f3ce pbrook
}
1056 4373f3ce pbrook
1057 4373f3ce pbrook
#define VFP_GEN_FIX(name) \
1058 4373f3ce pbrook
static inline void gen_vfp_##name(int dp, int shift) \
1059 4373f3ce pbrook
{ \
1060 4373f3ce pbrook
    if (dp) \
1061 4373f3ce pbrook
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1062 4373f3ce pbrook
    else \
1063 4373f3ce pbrook
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1064 9ee6e8bb pbrook
}
1065 4373f3ce pbrook
VFP_GEN_FIX(tosh)
1066 4373f3ce pbrook
VFP_GEN_FIX(tosl)
1067 4373f3ce pbrook
VFP_GEN_FIX(touh)
1068 4373f3ce pbrook
VFP_GEN_FIX(toul)
1069 4373f3ce pbrook
VFP_GEN_FIX(shto)
1070 4373f3ce pbrook
VFP_GEN_FIX(slto)
1071 4373f3ce pbrook
VFP_GEN_FIX(uhto)
1072 4373f3ce pbrook
VFP_GEN_FIX(ulto)
1073 4373f3ce pbrook
#undef VFP_GEN_FIX
1074 9ee6e8bb pbrook
1075 b5ff1b31 bellard
static inline void gen_vfp_ld(DisasContext *s, int dp)
1076 b5ff1b31 bellard
{
1077 b5ff1b31 bellard
    if (dp)
1078 4373f3ce pbrook
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1079 b5ff1b31 bellard
    else
1080 4373f3ce pbrook
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1081 b5ff1b31 bellard
}
1082 b5ff1b31 bellard
1083 b5ff1b31 bellard
static inline void gen_vfp_st(DisasContext *s, int dp)
1084 b5ff1b31 bellard
{
1085 b5ff1b31 bellard
    if (dp)
1086 4373f3ce pbrook
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1087 b5ff1b31 bellard
    else
1088 4373f3ce pbrook
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1089 b5ff1b31 bellard
}
1090 b5ff1b31 bellard
1091 8e96005d bellard
static inline long
1092 8e96005d bellard
vfp_reg_offset (int dp, int reg)
1093 8e96005d bellard
{
1094 8e96005d bellard
    if (dp)
1095 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg]);
1096 8e96005d bellard
    else if (reg & 1) {
1097 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1098 8e96005d bellard
          + offsetof(CPU_DoubleU, l.upper);
1099 8e96005d bellard
    } else {
1100 8e96005d bellard
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1101 8e96005d bellard
          + offsetof(CPU_DoubleU, l.lower);
1102 8e96005d bellard
    }
1103 8e96005d bellard
}
1104 9ee6e8bb pbrook
1105 9ee6e8bb pbrook
/* Return the offset of a 32-bit piece of a NEON register.
1106 9ee6e8bb pbrook
   zero is the least significant end of the register.  */
1107 9ee6e8bb pbrook
static inline long
1108 9ee6e8bb pbrook
neon_reg_offset (int reg, int n)
1109 9ee6e8bb pbrook
{
1110 9ee6e8bb pbrook
    int sreg;
1111 9ee6e8bb pbrook
    sreg = reg * 2 + n;
1112 9ee6e8bb pbrook
    return vfp_reg_offset(0, sreg);
1113 9ee6e8bb pbrook
}
1114 9ee6e8bb pbrook
1115 8f8e3aa4 pbrook
static TCGv neon_load_reg(int reg, int pass)
1116 8f8e3aa4 pbrook
{
1117 8f8e3aa4 pbrook
    TCGv tmp = new_tmp();
1118 8f8e3aa4 pbrook
    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1119 8f8e3aa4 pbrook
    return tmp;
1120 8f8e3aa4 pbrook
}
1121 8f8e3aa4 pbrook
1122 8f8e3aa4 pbrook
static void neon_store_reg(int reg, int pass, TCGv var)
1123 8f8e3aa4 pbrook
{
1124 8f8e3aa4 pbrook
    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1125 8f8e3aa4 pbrook
    dead_tmp(var);
1126 8f8e3aa4 pbrook
}
1127 8f8e3aa4 pbrook
1128 a7812ae4 pbrook
static inline void neon_load_reg64(TCGv_i64 var, int reg)
1129 ad69471c pbrook
{
1130 ad69471c pbrook
    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1131 ad69471c pbrook
}
1132 ad69471c pbrook
1133 a7812ae4 pbrook
static inline void neon_store_reg64(TCGv_i64 var, int reg)
1134 ad69471c pbrook
{
1135 ad69471c pbrook
    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1136 ad69471c pbrook
}
1137 ad69471c pbrook
1138 4373f3ce pbrook
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1139 4373f3ce pbrook
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1140 4373f3ce pbrook
#define tcg_gen_st_f32 tcg_gen_st_i32
1141 4373f3ce pbrook
#define tcg_gen_st_f64 tcg_gen_st_i64
1142 4373f3ce pbrook
1143 b7bcbe95 bellard
static inline void gen_mov_F0_vreg(int dp, int reg)
1144 b7bcbe95 bellard
{
1145 b7bcbe95 bellard
    if (dp)
1146 4373f3ce pbrook
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1147 b7bcbe95 bellard
    else
1148 4373f3ce pbrook
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1149 b7bcbe95 bellard
}
1150 b7bcbe95 bellard
1151 b7bcbe95 bellard
static inline void gen_mov_F1_vreg(int dp, int reg)
1152 b7bcbe95 bellard
{
1153 b7bcbe95 bellard
    if (dp)
1154 4373f3ce pbrook
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1155 b7bcbe95 bellard
    else
1156 4373f3ce pbrook
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1157 b7bcbe95 bellard
}
1158 b7bcbe95 bellard
1159 b7bcbe95 bellard
static inline void gen_mov_vreg_F0(int dp, int reg)
1160 b7bcbe95 bellard
{
1161 b7bcbe95 bellard
    if (dp)
1162 4373f3ce pbrook
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1163 b7bcbe95 bellard
    else
1164 4373f3ce pbrook
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1165 b7bcbe95 bellard
}
1166 b7bcbe95 bellard
1167 18c9b560 balrog
#define ARM_CP_RW_BIT        (1 << 20)
1168 18c9b560 balrog
1169 a7812ae4 pbrook
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1170 e677137d pbrook
{
1171 e677137d pbrook
    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1172 e677137d pbrook
}
1173 e677137d pbrook
1174 a7812ae4 pbrook
static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1175 e677137d pbrook
{
1176 e677137d pbrook
    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1177 e677137d pbrook
}
1178 e677137d pbrook
1179 e677137d pbrook
static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1180 e677137d pbrook
{
1181 e677137d pbrook
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1182 e677137d pbrook
}
1183 e677137d pbrook
1184 e677137d pbrook
static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1185 e677137d pbrook
{
1186 e677137d pbrook
    tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1187 e677137d pbrook
}
1188 e677137d pbrook
1189 e677137d pbrook
static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1190 e677137d pbrook
{
1191 e677137d pbrook
    tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1192 e677137d pbrook
}
1193 e677137d pbrook
1194 e677137d pbrook
static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1195 e677137d pbrook
{
1196 e677137d pbrook
    iwmmxt_store_reg(cpu_M0, rn);
1197 e677137d pbrook
}
1198 e677137d pbrook
1199 e677137d pbrook
static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1200 e677137d pbrook
{
1201 e677137d pbrook
    iwmmxt_load_reg(cpu_M0, rn);
1202 e677137d pbrook
}
1203 e677137d pbrook
1204 e677137d pbrook
static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1205 e677137d pbrook
{
1206 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1207 e677137d pbrook
    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1208 e677137d pbrook
}
1209 e677137d pbrook
1210 e677137d pbrook
static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1211 e677137d pbrook
{
1212 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1213 e677137d pbrook
    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1214 e677137d pbrook
}
1215 e677137d pbrook
1216 e677137d pbrook
static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1217 e677137d pbrook
{
1218 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1219 e677137d pbrook
    tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1220 e677137d pbrook
}
1221 e677137d pbrook
1222 e677137d pbrook
#define IWMMXT_OP(name) \
1223 e677137d pbrook
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1224 e677137d pbrook
{ \
1225 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn); \
1226 e677137d pbrook
    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1227 e677137d pbrook
}
1228 e677137d pbrook
1229 e677137d pbrook
#define IWMMXT_OP_ENV(name) \
1230 e677137d pbrook
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1231 e677137d pbrook
{ \
1232 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn); \
1233 e677137d pbrook
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1234 e677137d pbrook
}
1235 e677137d pbrook
1236 e677137d pbrook
#define IWMMXT_OP_ENV_SIZE(name) \
1237 e677137d pbrook
IWMMXT_OP_ENV(name##b) \
1238 e677137d pbrook
IWMMXT_OP_ENV(name##w) \
1239 e677137d pbrook
IWMMXT_OP_ENV(name##l)
1240 e677137d pbrook
1241 e677137d pbrook
#define IWMMXT_OP_ENV1(name) \
1242 e677137d pbrook
static inline void gen_op_iwmmxt_##name##_M0(void) \
1243 e677137d pbrook
{ \
1244 e677137d pbrook
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1245 e677137d pbrook
}
1246 e677137d pbrook
1247 e677137d pbrook
IWMMXT_OP(maddsq)
1248 e677137d pbrook
IWMMXT_OP(madduq)
1249 e677137d pbrook
IWMMXT_OP(sadb)
1250 e677137d pbrook
IWMMXT_OP(sadw)
1251 e677137d pbrook
IWMMXT_OP(mulslw)
1252 e677137d pbrook
IWMMXT_OP(mulshw)
1253 e677137d pbrook
IWMMXT_OP(mululw)
1254 e677137d pbrook
IWMMXT_OP(muluhw)
1255 e677137d pbrook
IWMMXT_OP(macsw)
1256 e677137d pbrook
IWMMXT_OP(macuw)
1257 e677137d pbrook
1258 e677137d pbrook
IWMMXT_OP_ENV_SIZE(unpackl)
1259 e677137d pbrook
IWMMXT_OP_ENV_SIZE(unpackh)
1260 e677137d pbrook
1261 e677137d pbrook
IWMMXT_OP_ENV1(unpacklub)
1262 e677137d pbrook
IWMMXT_OP_ENV1(unpackluw)
1263 e677137d pbrook
IWMMXT_OP_ENV1(unpacklul)
1264 e677137d pbrook
IWMMXT_OP_ENV1(unpackhub)
1265 e677137d pbrook
IWMMXT_OP_ENV1(unpackhuw)
1266 e677137d pbrook
IWMMXT_OP_ENV1(unpackhul)
1267 e677137d pbrook
IWMMXT_OP_ENV1(unpacklsb)
1268 e677137d pbrook
IWMMXT_OP_ENV1(unpacklsw)
1269 e677137d pbrook
IWMMXT_OP_ENV1(unpacklsl)
1270 e677137d pbrook
IWMMXT_OP_ENV1(unpackhsb)
1271 e677137d pbrook
IWMMXT_OP_ENV1(unpackhsw)
1272 e677137d pbrook
IWMMXT_OP_ENV1(unpackhsl)
1273 e677137d pbrook
1274 e677137d pbrook
IWMMXT_OP_ENV_SIZE(cmpeq)
1275 e677137d pbrook
IWMMXT_OP_ENV_SIZE(cmpgtu)
1276 e677137d pbrook
IWMMXT_OP_ENV_SIZE(cmpgts)
1277 e677137d pbrook
1278 e677137d pbrook
IWMMXT_OP_ENV_SIZE(mins)
1279 e677137d pbrook
IWMMXT_OP_ENV_SIZE(minu)
1280 e677137d pbrook
IWMMXT_OP_ENV_SIZE(maxs)
1281 e677137d pbrook
IWMMXT_OP_ENV_SIZE(maxu)
1282 e677137d pbrook
1283 e677137d pbrook
IWMMXT_OP_ENV_SIZE(subn)
1284 e677137d pbrook
IWMMXT_OP_ENV_SIZE(addn)
1285 e677137d pbrook
IWMMXT_OP_ENV_SIZE(subu)
1286 e677137d pbrook
IWMMXT_OP_ENV_SIZE(addu)
1287 e677137d pbrook
IWMMXT_OP_ENV_SIZE(subs)
1288 e677137d pbrook
IWMMXT_OP_ENV_SIZE(adds)
1289 e677137d pbrook
1290 e677137d pbrook
IWMMXT_OP_ENV(avgb0)
1291 e677137d pbrook
IWMMXT_OP_ENV(avgb1)
1292 e677137d pbrook
IWMMXT_OP_ENV(avgw0)
1293 e677137d pbrook
IWMMXT_OP_ENV(avgw1)
1294 e677137d pbrook
1295 e677137d pbrook
IWMMXT_OP(msadb)
1296 e677137d pbrook
1297 e677137d pbrook
IWMMXT_OP_ENV(packuw)
1298 e677137d pbrook
IWMMXT_OP_ENV(packul)
1299 e677137d pbrook
IWMMXT_OP_ENV(packuq)
1300 e677137d pbrook
IWMMXT_OP_ENV(packsw)
1301 e677137d pbrook
IWMMXT_OP_ENV(packsl)
1302 e677137d pbrook
IWMMXT_OP_ENV(packsq)
1303 e677137d pbrook
1304 e677137d pbrook
static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1305 e677137d pbrook
{
1306 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1307 e677137d pbrook
    gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1308 e677137d pbrook
}
1309 e677137d pbrook
1310 e677137d pbrook
static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1311 e677137d pbrook
{
1312 e677137d pbrook
    TCGv tmp = tcg_const_i32(shift);
1313 e677137d pbrook
    gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1314 e677137d pbrook
}
1315 e677137d pbrook
1316 e677137d pbrook
static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1317 e677137d pbrook
{
1318 e677137d pbrook
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1319 e677137d pbrook
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1320 e677137d pbrook
    tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1321 e677137d pbrook
}
1322 e677137d pbrook
1323 e677137d pbrook
static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1324 e677137d pbrook
{
1325 e677137d pbrook
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1326 e677137d pbrook
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1327 e677137d pbrook
    tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1328 e677137d pbrook
}
1329 e677137d pbrook
1330 e677137d pbrook
static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1331 e677137d pbrook
{
1332 e677137d pbrook
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1333 e677137d pbrook
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1334 e677137d pbrook
    if (mask != ~0u)
1335 e677137d pbrook
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1336 e677137d pbrook
}
1337 e677137d pbrook
1338 e677137d pbrook
static void gen_op_iwmmxt_set_mup(void)
1339 e677137d pbrook
{
1340 e677137d pbrook
    TCGv tmp;
1341 e677137d pbrook
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1342 e677137d pbrook
    tcg_gen_ori_i32(tmp, tmp, 2);
1343 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1344 e677137d pbrook
}
1345 e677137d pbrook
1346 e677137d pbrook
static void gen_op_iwmmxt_set_cup(void)
1347 e677137d pbrook
{
1348 e677137d pbrook
    TCGv tmp;
1349 e677137d pbrook
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1350 e677137d pbrook
    tcg_gen_ori_i32(tmp, tmp, 1);
1351 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1352 e677137d pbrook
}
1353 e677137d pbrook
1354 e677137d pbrook
static void gen_op_iwmmxt_setpsr_nz(void)
1355 e677137d pbrook
{
1356 e677137d pbrook
    TCGv tmp = new_tmp();
1357 e677137d pbrook
    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1358 e677137d pbrook
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1359 e677137d pbrook
}
1360 e677137d pbrook
1361 e677137d pbrook
static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1362 e677137d pbrook
{
1363 e677137d pbrook
    iwmmxt_load_reg(cpu_V1, rn);
1364 86831435 pbrook
    tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1365 e677137d pbrook
    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1366 e677137d pbrook
}
1367 e677137d pbrook
1368 e677137d pbrook
static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1369 e677137d pbrook
{
1370 e677137d pbrook
    iwmmxt_load_reg(cpu_V0, rn);
1371 e677137d pbrook
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1372 e677137d pbrook
    tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1373 e677137d pbrook
    tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1374 e677137d pbrook
}
1375 e677137d pbrook
1376 e677137d pbrook
static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1377 e677137d pbrook
{
1378 36aa55dc pbrook
    tcg_gen_concat_i32_i64(cpu_V0, cpu_T[0], cpu_T[1]);
1379 e677137d pbrook
    iwmmxt_store_reg(cpu_V0, rn);
1380 e677137d pbrook
}
1381 e677137d pbrook
1382 18c9b560 balrog
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1383 18c9b560 balrog
{
1384 18c9b560 balrog
    int rd;
1385 18c9b560 balrog
    uint32_t offset;
1386 18c9b560 balrog
1387 18c9b560 balrog
    rd = (insn >> 16) & 0xf;
1388 18c9b560 balrog
    gen_movl_T1_reg(s, rd);
1389 18c9b560 balrog
1390 18c9b560 balrog
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1391 18c9b560 balrog
    if (insn & (1 << 24)) {
1392 18c9b560 balrog
        /* Pre indexed */
1393 18c9b560 balrog
        if (insn & (1 << 23))
1394 18c9b560 balrog
            gen_op_addl_T1_im(offset);
1395 18c9b560 balrog
        else
1396 18c9b560 balrog
            gen_op_addl_T1_im(-offset);
1397 18c9b560 balrog
1398 18c9b560 balrog
        if (insn & (1 << 21))
1399 18c9b560 balrog
            gen_movl_reg_T1(s, rd);
1400 18c9b560 balrog
    } else if (insn & (1 << 21)) {
1401 18c9b560 balrog
        /* Post indexed */
1402 18c9b560 balrog
        if (insn & (1 << 23))
1403 18c9b560 balrog
            gen_op_movl_T0_im(offset);
1404 18c9b560 balrog
        else
1405 18c9b560 balrog
            gen_op_movl_T0_im(- offset);
1406 18c9b560 balrog
        gen_op_addl_T0_T1();
1407 18c9b560 balrog
        gen_movl_reg_T0(s, rd);
1408 18c9b560 balrog
    } else if (!(insn & (1 << 23)))
1409 18c9b560 balrog
        return 1;
1410 18c9b560 balrog
    return 0;
1411 18c9b560 balrog
}
1412 18c9b560 balrog
1413 18c9b560 balrog
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1414 18c9b560 balrog
{
1415 18c9b560 balrog
    int rd = (insn >> 0) & 0xf;
1416 18c9b560 balrog
1417 18c9b560 balrog
    if (insn & (1 << 8))
1418 18c9b560 balrog
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1419 18c9b560 balrog
            return 1;
1420 18c9b560 balrog
        else
1421 18c9b560 balrog
            gen_op_iwmmxt_movl_T0_wCx(rd);
1422 18c9b560 balrog
    else
1423 e677137d pbrook
        gen_iwmmxt_movl_T0_T1_wRn(rd);
1424 18c9b560 balrog
1425 18c9b560 balrog
    gen_op_movl_T1_im(mask);
1426 18c9b560 balrog
    gen_op_andl_T0_T1();
1427 18c9b560 balrog
    return 0;
1428 18c9b560 balrog
}
1429 18c9b560 balrog
1430 18c9b560 balrog
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1431 18c9b560 balrog
   (ie. an undefined instruction).  */
1432 18c9b560 balrog
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1433 18c9b560 balrog
{
1434 18c9b560 balrog
    int rd, wrd;
1435 18c9b560 balrog
    int rdhi, rdlo, rd0, rd1, i;
1436 b0109805 pbrook
    TCGv tmp;
1437 18c9b560 balrog
1438 18c9b560 balrog
    if ((insn & 0x0e000e00) == 0x0c000000) {
1439 18c9b560 balrog
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1440 18c9b560 balrog
            wrd = insn & 0xf;
1441 18c9b560 balrog
            rdlo = (insn >> 12) & 0xf;
1442 18c9b560 balrog
            rdhi = (insn >> 16) & 0xf;
1443 18c9b560 balrog
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1444 e677137d pbrook
                gen_iwmmxt_movl_T0_T1_wRn(wrd);
1445 18c9b560 balrog
                gen_movl_reg_T0(s, rdlo);
1446 18c9b560 balrog
                gen_movl_reg_T1(s, rdhi);
1447 18c9b560 balrog
            } else {                                        /* TMCRR */
1448 18c9b560 balrog
                gen_movl_T0_reg(s, rdlo);
1449 18c9b560 balrog
                gen_movl_T1_reg(s, rdhi);
1450 e677137d pbrook
                gen_iwmmxt_movl_wRn_T0_T1(wrd);
1451 18c9b560 balrog
                gen_op_iwmmxt_set_mup();
1452 18c9b560 balrog
            }
1453 18c9b560 balrog
            return 0;
1454 18c9b560 balrog
        }
1455 18c9b560 balrog
1456 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1457 18c9b560 balrog
        if (gen_iwmmxt_address(s, insn))
1458 18c9b560 balrog
            return 1;
1459 18c9b560 balrog
        if (insn & ARM_CP_RW_BIT) {
1460 18c9b560 balrog
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1461 b0109805 pbrook
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1462 b0109805 pbrook
                tcg_gen_mov_i32(cpu_T[0], tmp);
1463 b0109805 pbrook
                dead_tmp(tmp);
1464 18c9b560 balrog
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1465 18c9b560 balrog
            } else {
1466 e677137d pbrook
                i = 1;
1467 e677137d pbrook
                if (insn & (1 << 8)) {
1468 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WLDRD */
1469 e677137d pbrook
                        tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1470 e677137d pbrook
                        i = 0;
1471 e677137d pbrook
                    } else {                                /* WLDRW wRd */
1472 e677137d pbrook
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
1473 e677137d pbrook
                    }
1474 e677137d pbrook
                } else {
1475 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WLDRH */
1476 e677137d pbrook
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1477 e677137d pbrook
                    } else {                                /* WLDRB */
1478 e677137d pbrook
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1479 e677137d pbrook
                    }
1480 e677137d pbrook
                }
1481 e677137d pbrook
                if (i) {
1482 e677137d pbrook
                    tcg_gen_extu_i32_i64(cpu_M0, tmp);
1483 e677137d pbrook
                    dead_tmp(tmp);
1484 e677137d pbrook
                }
1485 18c9b560 balrog
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1486 18c9b560 balrog
            }
1487 18c9b560 balrog
        } else {
1488 18c9b560 balrog
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1489 18c9b560 balrog
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1490 b0109805 pbrook
                tmp = new_tmp();
1491 b0109805 pbrook
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1492 b0109805 pbrook
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1493 18c9b560 balrog
            } else {
1494 18c9b560 balrog
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1495 e677137d pbrook
                tmp = new_tmp();
1496 e677137d pbrook
                if (insn & (1 << 8)) {
1497 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WSTRD */
1498 e677137d pbrook
                        dead_tmp(tmp);
1499 e677137d pbrook
                        tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1500 e677137d pbrook
                    } else {                                /* WSTRW wRd */
1501 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1502 e677137d pbrook
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
1503 e677137d pbrook
                    }
1504 e677137d pbrook
                } else {
1505 e677137d pbrook
                    if (insn & (1 << 22)) {                /* WSTRH */
1506 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1507 e677137d pbrook
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
1508 e677137d pbrook
                    } else {                                /* WSTRB */
1509 e677137d pbrook
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1510 e677137d pbrook
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
1511 e677137d pbrook
                    }
1512 e677137d pbrook
                }
1513 18c9b560 balrog
            }
1514 18c9b560 balrog
        }
1515 18c9b560 balrog
        return 0;
1516 18c9b560 balrog
    }
1517 18c9b560 balrog
1518 18c9b560 balrog
    if ((insn & 0x0f000000) != 0x0e000000)
1519 18c9b560 balrog
        return 1;
1520 18c9b560 balrog
1521 18c9b560 balrog
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1522 18c9b560 balrog
    case 0x000:                                                /* WOR */
1523 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1524 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1525 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1526 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1527 18c9b560 balrog
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1528 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1529 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1530 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1531 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1532 18c9b560 balrog
        break;
1533 18c9b560 balrog
    case 0x011:                                                /* TMCR */
1534 18c9b560 balrog
        if (insn & 0xf)
1535 18c9b560 balrog
            return 1;
1536 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1537 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1538 18c9b560 balrog
        switch (wrd) {
1539 18c9b560 balrog
        case ARM_IWMMXT_wCID:
1540 18c9b560 balrog
        case ARM_IWMMXT_wCASF:
1541 18c9b560 balrog
            break;
1542 18c9b560 balrog
        case ARM_IWMMXT_wCon:
1543 18c9b560 balrog
            gen_op_iwmmxt_set_cup();
1544 18c9b560 balrog
            /* Fall through.  */
1545 18c9b560 balrog
        case ARM_IWMMXT_wCSSF:
1546 18c9b560 balrog
            gen_op_iwmmxt_movl_T0_wCx(wrd);
1547 18c9b560 balrog
            gen_movl_T1_reg(s, rd);
1548 18c9b560 balrog
            gen_op_bicl_T0_T1();
1549 18c9b560 balrog
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1550 18c9b560 balrog
            break;
1551 18c9b560 balrog
        case ARM_IWMMXT_wCGR0:
1552 18c9b560 balrog
        case ARM_IWMMXT_wCGR1:
1553 18c9b560 balrog
        case ARM_IWMMXT_wCGR2:
1554 18c9b560 balrog
        case ARM_IWMMXT_wCGR3:
1555 18c9b560 balrog
            gen_op_iwmmxt_set_cup();
1556 18c9b560 balrog
            gen_movl_reg_T0(s, rd);
1557 18c9b560 balrog
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1558 18c9b560 balrog
            break;
1559 18c9b560 balrog
        default:
1560 18c9b560 balrog
            return 1;
1561 18c9b560 balrog
        }
1562 18c9b560 balrog
        break;
1563 18c9b560 balrog
    case 0x100:                                                /* WXOR */
1564 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1565 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1566 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1567 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1568 18c9b560 balrog
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1569 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1570 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1571 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1572 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1573 18c9b560 balrog
        break;
1574 18c9b560 balrog
    case 0x111:                                                /* TMRC */
1575 18c9b560 balrog
        if (insn & 0xf)
1576 18c9b560 balrog
            return 1;
1577 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1578 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1579 18c9b560 balrog
        gen_op_iwmmxt_movl_T0_wCx(wrd);
1580 18c9b560 balrog
        gen_movl_reg_T0(s, rd);
1581 18c9b560 balrog
        break;
1582 18c9b560 balrog
    case 0x300:                                                /* WANDN */
1583 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1584 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1585 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1586 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1587 e677137d pbrook
        tcg_gen_neg_i64(cpu_M0, cpu_M0);
1588 18c9b560 balrog
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1589 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1590 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1591 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1592 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1593 18c9b560 balrog
        break;
1594 18c9b560 balrog
    case 0x200:                                                /* WAND */
1595 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1596 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1597 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1598 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1599 18c9b560 balrog
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1600 18c9b560 balrog
        gen_op_iwmmxt_setpsr_nz();
1601 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1602 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1603 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1604 18c9b560 balrog
        break;
1605 18c9b560 balrog
    case 0x810: case 0xa10:                                /* WMADD */
1606 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1607 18c9b560 balrog
        rd0 = (insn >> 0) & 0xf;
1608 18c9b560 balrog
        rd1 = (insn >> 16) & 0xf;
1609 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1610 18c9b560 balrog
        if (insn & (1 << 21))
1611 18c9b560 balrog
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1612 18c9b560 balrog
        else
1613 18c9b560 balrog
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1614 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1615 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1616 18c9b560 balrog
        break;
1617 18c9b560 balrog
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1618 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1619 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1620 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1621 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1622 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1623 18c9b560 balrog
        case 0:
1624 18c9b560 balrog
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1625 18c9b560 balrog
            break;
1626 18c9b560 balrog
        case 1:
1627 18c9b560 balrog
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1628 18c9b560 balrog
            break;
1629 18c9b560 balrog
        case 2:
1630 18c9b560 balrog
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1631 18c9b560 balrog
            break;
1632 18c9b560 balrog
        case 3:
1633 18c9b560 balrog
            return 1;
1634 18c9b560 balrog
        }
1635 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1636 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1637 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1638 18c9b560 balrog
        break;
1639 18c9b560 balrog
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1640 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1641 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1642 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1643 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1644 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1645 18c9b560 balrog
        case 0:
1646 18c9b560 balrog
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1647 18c9b560 balrog
            break;
1648 18c9b560 balrog
        case 1:
1649 18c9b560 balrog
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1650 18c9b560 balrog
            break;
1651 18c9b560 balrog
        case 2:
1652 18c9b560 balrog
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1653 18c9b560 balrog
            break;
1654 18c9b560 balrog
        case 3:
1655 18c9b560 balrog
            return 1;
1656 18c9b560 balrog
        }
1657 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1658 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1659 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1660 18c9b560 balrog
        break;
1661 18c9b560 balrog
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1662 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1663 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1664 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1665 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1666 18c9b560 balrog
        if (insn & (1 << 22))
1667 18c9b560 balrog
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1668 18c9b560 balrog
        else
1669 18c9b560 balrog
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1670 18c9b560 balrog
        if (!(insn & (1 << 20)))
1671 18c9b560 balrog
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1672 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1673 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1674 18c9b560 balrog
        break;
1675 18c9b560 balrog
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1676 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1677 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1678 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1679 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1680 e677137d pbrook
        if (insn & (1 << 21)) {
1681 e677137d pbrook
            if (insn & (1 << 20))
1682 e677137d pbrook
                gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1683 e677137d pbrook
            else
1684 e677137d pbrook
                gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1685 e677137d pbrook
        } else {
1686 e677137d pbrook
            if (insn & (1 << 20))
1687 e677137d pbrook
                gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1688 e677137d pbrook
            else
1689 e677137d pbrook
                gen_op_iwmmxt_mululw_M0_wRn(rd1);
1690 e677137d pbrook
        }
1691 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1692 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1693 18c9b560 balrog
        break;
1694 18c9b560 balrog
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1695 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1696 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1697 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1698 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1699 18c9b560 balrog
        if (insn & (1 << 21))
1700 18c9b560 balrog
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1701 18c9b560 balrog
        else
1702 18c9b560 balrog
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1703 18c9b560 balrog
        if (!(insn & (1 << 20))) {
1704 e677137d pbrook
            iwmmxt_load_reg(cpu_V1, wrd);
1705 e677137d pbrook
            tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1706 18c9b560 balrog
        }
1707 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1708 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1709 18c9b560 balrog
        break;
1710 18c9b560 balrog
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1711 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1712 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1713 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1714 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1715 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1716 18c9b560 balrog
        case 0:
1717 18c9b560 balrog
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1718 18c9b560 balrog
            break;
1719 18c9b560 balrog
        case 1:
1720 18c9b560 balrog
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1721 18c9b560 balrog
            break;
1722 18c9b560 balrog
        case 2:
1723 18c9b560 balrog
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1724 18c9b560 balrog
            break;
1725 18c9b560 balrog
        case 3:
1726 18c9b560 balrog
            return 1;
1727 18c9b560 balrog
        }
1728 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1729 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1730 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1731 18c9b560 balrog
        break;
1732 18c9b560 balrog
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1733 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1734 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1735 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1736 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1737 e677137d pbrook
        if (insn & (1 << 22)) {
1738 e677137d pbrook
            if (insn & (1 << 20))
1739 e677137d pbrook
                gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1740 e677137d pbrook
            else
1741 e677137d pbrook
                gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1742 e677137d pbrook
        } else {
1743 e677137d pbrook
            if (insn & (1 << 20))
1744 e677137d pbrook
                gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1745 e677137d pbrook
            else
1746 e677137d pbrook
                gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1747 e677137d pbrook
        }
1748 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1749 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1750 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1751 18c9b560 balrog
        break;
1752 18c9b560 balrog
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1753 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1754 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1755 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1756 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1757 18c9b560 balrog
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1758 18c9b560 balrog
        gen_op_movl_T1_im(7);
1759 18c9b560 balrog
        gen_op_andl_T0_T1();
1760 18c9b560 balrog
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1761 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1762 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1763 18c9b560 balrog
        break;
1764 18c9b560 balrog
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1765 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1766 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1767 18c9b560 balrog
        gen_movl_T0_reg(s, rd);
1768 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1769 18c9b560 balrog
        switch ((insn >> 6) & 3) {
1770 18c9b560 balrog
        case 0:
1771 18c9b560 balrog
            gen_op_movl_T1_im(0xff);
1772 18c9b560 balrog
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1773 18c9b560 balrog
            break;
1774 18c9b560 balrog
        case 1:
1775 18c9b560 balrog
            gen_op_movl_T1_im(0xffff);
1776 18c9b560 balrog
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1777 18c9b560 balrog
            break;
1778 18c9b560 balrog
        case 2:
1779 18c9b560 balrog
            gen_op_movl_T1_im(0xffffffff);
1780 18c9b560 balrog
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1781 18c9b560 balrog
            break;
1782 18c9b560 balrog
        case 3:
1783 18c9b560 balrog
            return 1;
1784 18c9b560 balrog
        }
1785 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1786 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1787 18c9b560 balrog
        break;
1788 18c9b560 balrog
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1789 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1790 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1791 18c9b560 balrog
        if (rd == 15)
1792 18c9b560 balrog
            return 1;
1793 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1794 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1795 18c9b560 balrog
        case 0:
1796 18c9b560 balrog
            if (insn & 8)
1797 18c9b560 balrog
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1798 18c9b560 balrog
            else {
1799 e677137d pbrook
                gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1800 18c9b560 balrog
            }
1801 18c9b560 balrog
            break;
1802 18c9b560 balrog
        case 1:
1803 18c9b560 balrog
            if (insn & 8)
1804 18c9b560 balrog
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1805 18c9b560 balrog
            else {
1806 e677137d pbrook
                gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1807 18c9b560 balrog
            }
1808 18c9b560 balrog
            break;
1809 18c9b560 balrog
        case 2:
1810 e677137d pbrook
            gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1811 18c9b560 balrog
            break;
1812 18c9b560 balrog
        case 3:
1813 18c9b560 balrog
            return 1;
1814 18c9b560 balrog
        }
1815 b26eefb6 pbrook
        gen_movl_reg_T0(s, rd);
1816 18c9b560 balrog
        break;
1817 18c9b560 balrog
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1818 18c9b560 balrog
        if ((insn & 0x000ff008) != 0x0003f000)
1819 18c9b560 balrog
            return 1;
1820 18c9b560 balrog
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1821 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1822 18c9b560 balrog
        case 0:
1823 18c9b560 balrog
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1824 18c9b560 balrog
            break;
1825 18c9b560 balrog
        case 1:
1826 18c9b560 balrog
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1827 18c9b560 balrog
            break;
1828 18c9b560 balrog
        case 2:
1829 18c9b560 balrog
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1830 18c9b560 balrog
            break;
1831 18c9b560 balrog
        case 3:
1832 18c9b560 balrog
            return 1;
1833 18c9b560 balrog
        }
1834 18c9b560 balrog
        gen_op_shll_T1_im(28);
1835 d9ba4830 pbrook
        gen_set_nzcv(cpu_T[1]);
1836 18c9b560 balrog
        break;
1837 18c9b560 balrog
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1838 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1839 18c9b560 balrog
        wrd = (insn >> 16) & 0xf;
1840 18c9b560 balrog
        gen_movl_T0_reg(s, rd);
1841 18c9b560 balrog
        switch ((insn >> 6) & 3) {
1842 18c9b560 balrog
        case 0:
1843 e677137d pbrook
            gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1844 18c9b560 balrog
            break;
1845 18c9b560 balrog
        case 1:
1846 e677137d pbrook
            gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1847 18c9b560 balrog
            break;
1848 18c9b560 balrog
        case 2:
1849 e677137d pbrook
            gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1850 18c9b560 balrog
            break;
1851 18c9b560 balrog
        case 3:
1852 18c9b560 balrog
            return 1;
1853 18c9b560 balrog
        }
1854 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1855 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1856 18c9b560 balrog
        break;
1857 18c9b560 balrog
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1858 18c9b560 balrog
        if ((insn & 0x000ff00f) != 0x0003f000)
1859 18c9b560 balrog
            return 1;
1860 18c9b560 balrog
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1861 15bb4eac Filip Navara
        gen_op_movl_T0_T1();
1862 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1863 18c9b560 balrog
        case 0:
1864 18c9b560 balrog
            for (i = 0; i < 7; i ++) {
1865 18c9b560 balrog
                gen_op_shll_T1_im(4);
1866 18c9b560 balrog
                gen_op_andl_T0_T1();
1867 18c9b560 balrog
            }
1868 18c9b560 balrog
            break;
1869 18c9b560 balrog
        case 1:
1870 18c9b560 balrog
            for (i = 0; i < 3; i ++) {
1871 18c9b560 balrog
                gen_op_shll_T1_im(8);
1872 18c9b560 balrog
                gen_op_andl_T0_T1();
1873 18c9b560 balrog
            }
1874 18c9b560 balrog
            break;
1875 18c9b560 balrog
        case 2:
1876 18c9b560 balrog
            gen_op_shll_T1_im(16);
1877 18c9b560 balrog
            gen_op_andl_T0_T1();
1878 18c9b560 balrog
            break;
1879 18c9b560 balrog
        case 3:
1880 18c9b560 balrog
            return 1;
1881 18c9b560 balrog
        }
1882 d9ba4830 pbrook
        gen_set_nzcv(cpu_T[0]);
1883 18c9b560 balrog
        break;
1884 18c9b560 balrog
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1885 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1886 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1887 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1888 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1889 18c9b560 balrog
        case 0:
1890 e677137d pbrook
            gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1891 18c9b560 balrog
            break;
1892 18c9b560 balrog
        case 1:
1893 e677137d pbrook
            gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1894 18c9b560 balrog
            break;
1895 18c9b560 balrog
        case 2:
1896 e677137d pbrook
            gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1897 18c9b560 balrog
            break;
1898 18c9b560 balrog
        case 3:
1899 18c9b560 balrog
            return 1;
1900 18c9b560 balrog
        }
1901 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1902 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1903 18c9b560 balrog
        break;
1904 18c9b560 balrog
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1905 18c9b560 balrog
        if ((insn & 0x000ff00f) != 0x0003f000)
1906 18c9b560 balrog
            return 1;
1907 18c9b560 balrog
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1908 15bb4eac Filip Navara
        gen_op_movl_T0_T1();
1909 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1910 18c9b560 balrog
        case 0:
1911 18c9b560 balrog
            for (i = 0; i < 7; i ++) {
1912 18c9b560 balrog
                gen_op_shll_T1_im(4);
1913 18c9b560 balrog
                gen_op_orl_T0_T1();
1914 18c9b560 balrog
            }
1915 18c9b560 balrog
            break;
1916 18c9b560 balrog
        case 1:
1917 18c9b560 balrog
            for (i = 0; i < 3; i ++) {
1918 18c9b560 balrog
                gen_op_shll_T1_im(8);
1919 18c9b560 balrog
                gen_op_orl_T0_T1();
1920 18c9b560 balrog
            }
1921 18c9b560 balrog
            break;
1922 18c9b560 balrog
        case 2:
1923 18c9b560 balrog
            gen_op_shll_T1_im(16);
1924 18c9b560 balrog
            gen_op_orl_T0_T1();
1925 18c9b560 balrog
            break;
1926 18c9b560 balrog
        case 3:
1927 18c9b560 balrog
            return 1;
1928 18c9b560 balrog
        }
1929 d9ba4830 pbrook
        gen_set_nzcv(cpu_T[0]);
1930 18c9b560 balrog
        break;
1931 18c9b560 balrog
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1932 18c9b560 balrog
        rd = (insn >> 12) & 0xf;
1933 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1934 18c9b560 balrog
        if ((insn & 0xf) != 0)
1935 18c9b560 balrog
            return 1;
1936 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1937 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1938 18c9b560 balrog
        case 0:
1939 e677137d pbrook
            gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
1940 18c9b560 balrog
            break;
1941 18c9b560 balrog
        case 1:
1942 e677137d pbrook
            gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
1943 18c9b560 balrog
            break;
1944 18c9b560 balrog
        case 2:
1945 e677137d pbrook
            gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
1946 18c9b560 balrog
            break;
1947 18c9b560 balrog
        case 3:
1948 18c9b560 balrog
            return 1;
1949 18c9b560 balrog
        }
1950 18c9b560 balrog
        gen_movl_reg_T0(s, rd);
1951 18c9b560 balrog
        break;
1952 18c9b560 balrog
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1953 18c9b560 balrog
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1954 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1955 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1956 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
1957 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1958 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1959 18c9b560 balrog
        case 0:
1960 18c9b560 balrog
            if (insn & (1 << 21))
1961 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1962 18c9b560 balrog
            else
1963 18c9b560 balrog
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1964 18c9b560 balrog
            break;
1965 18c9b560 balrog
        case 1:
1966 18c9b560 balrog
            if (insn & (1 << 21))
1967 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1968 18c9b560 balrog
            else
1969 18c9b560 balrog
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1970 18c9b560 balrog
            break;
1971 18c9b560 balrog
        case 2:
1972 18c9b560 balrog
            if (insn & (1 << 21))
1973 18c9b560 balrog
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1974 18c9b560 balrog
            else
1975 18c9b560 balrog
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1976 18c9b560 balrog
            break;
1977 18c9b560 balrog
        case 3:
1978 18c9b560 balrog
            return 1;
1979 18c9b560 balrog
        }
1980 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1981 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
1982 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
1983 18c9b560 balrog
        break;
1984 18c9b560 balrog
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1985 18c9b560 balrog
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1986 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
1987 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
1988 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1989 18c9b560 balrog
        switch ((insn >> 22) & 3) {
1990 18c9b560 balrog
        case 0:
1991 18c9b560 balrog
            if (insn & (1 << 21))
1992 18c9b560 balrog
                gen_op_iwmmxt_unpacklsb_M0();
1993 18c9b560 balrog
            else
1994 18c9b560 balrog
                gen_op_iwmmxt_unpacklub_M0();
1995 18c9b560 balrog
            break;
1996 18c9b560 balrog
        case 1:
1997 18c9b560 balrog
            if (insn & (1 << 21))
1998 18c9b560 balrog
                gen_op_iwmmxt_unpacklsw_M0();
1999 18c9b560 balrog
            else
2000 18c9b560 balrog
                gen_op_iwmmxt_unpackluw_M0();
2001 18c9b560 balrog
            break;
2002 18c9b560 balrog
        case 2:
2003 18c9b560 balrog
            if (insn & (1 << 21))
2004 18c9b560 balrog
                gen_op_iwmmxt_unpacklsl_M0();
2005 18c9b560 balrog
            else
2006 18c9b560 balrog
                gen_op_iwmmxt_unpacklul_M0();
2007 18c9b560 balrog
            break;
2008 18c9b560 balrog
        case 3:
2009 18c9b560 balrog
            return 1;
2010 18c9b560 balrog
        }
2011 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2012 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2013 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2014 18c9b560 balrog
        break;
2015 18c9b560 balrog
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
2016 18c9b560 balrog
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2017 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2018 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2019 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2020 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2021 18c9b560 balrog
        case 0:
2022 18c9b560 balrog
            if (insn & (1 << 21))
2023 18c9b560 balrog
                gen_op_iwmmxt_unpackhsb_M0();
2024 18c9b560 balrog
            else
2025 18c9b560 balrog
                gen_op_iwmmxt_unpackhub_M0();
2026 18c9b560 balrog
            break;
2027 18c9b560 balrog
        case 1:
2028 18c9b560 balrog
            if (insn & (1 << 21))
2029 18c9b560 balrog
                gen_op_iwmmxt_unpackhsw_M0();
2030 18c9b560 balrog
            else
2031 18c9b560 balrog
                gen_op_iwmmxt_unpackhuw_M0();
2032 18c9b560 balrog
            break;
2033 18c9b560 balrog
        case 2:
2034 18c9b560 balrog
            if (insn & (1 << 21))
2035 18c9b560 balrog
                gen_op_iwmmxt_unpackhsl_M0();
2036 18c9b560 balrog
            else
2037 18c9b560 balrog
                gen_op_iwmmxt_unpackhul_M0();
2038 18c9b560 balrog
            break;
2039 18c9b560 balrog
        case 3:
2040 18c9b560 balrog
            return 1;
2041 18c9b560 balrog
        }
2042 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2043 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2044 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2045 18c9b560 balrog
        break;
2046 18c9b560 balrog
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
2047 18c9b560 balrog
    case 0x214: case 0x614: case 0xa14: case 0xe14:
2048 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2049 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2050 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2051 18c9b560 balrog
        if (gen_iwmmxt_shift(insn, 0xff))
2052 18c9b560 balrog
            return 1;
2053 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2054 18c9b560 balrog
        case 0:
2055 18c9b560 balrog
            return 1;
2056 18c9b560 balrog
        case 1:
2057 e677137d pbrook
            gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2058 18c9b560 balrog
            break;
2059 18c9b560 balrog
        case 2:
2060 e677137d pbrook
            gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2061 18c9b560 balrog
            break;
2062 18c9b560 balrog
        case 3:
2063 e677137d pbrook
            gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2064 18c9b560 balrog
            break;
2065 18c9b560 balrog
        }
2066 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2067 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2068 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2069 18c9b560 balrog
        break;
2070 18c9b560 balrog
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
2071 18c9b560 balrog
    case 0x014: case 0x414: case 0x814: case 0xc14:
2072 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2073 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2074 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2075 18c9b560 balrog
        if (gen_iwmmxt_shift(insn, 0xff))
2076 18c9b560 balrog
            return 1;
2077 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2078 18c9b560 balrog
        case 0:
2079 18c9b560 balrog
            return 1;
2080 18c9b560 balrog
        case 1:
2081 e677137d pbrook
            gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2082 18c9b560 balrog
            break;
2083 18c9b560 balrog
        case 2:
2084 e677137d pbrook
            gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2085 18c9b560 balrog
            break;
2086 18c9b560 balrog
        case 3:
2087 e677137d pbrook
            gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2088 18c9b560 balrog
            break;
2089 18c9b560 balrog
        }
2090 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2091 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2092 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2093 18c9b560 balrog
        break;
2094 18c9b560 balrog
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
2095 18c9b560 balrog
    case 0x114: case 0x514: case 0x914: case 0xd14:
2096 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2097 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2098 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2099 18c9b560 balrog
        if (gen_iwmmxt_shift(insn, 0xff))
2100 18c9b560 balrog
            return 1;
2101 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2102 18c9b560 balrog
        case 0:
2103 18c9b560 balrog
            return 1;
2104 18c9b560 balrog
        case 1:
2105 e677137d pbrook
            gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2106 18c9b560 balrog
            break;
2107 18c9b560 balrog
        case 2:
2108 e677137d pbrook
            gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2109 18c9b560 balrog
            break;
2110 18c9b560 balrog
        case 3:
2111 e677137d pbrook
            gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2112 18c9b560 balrog
            break;
2113 18c9b560 balrog
        }
2114 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2115 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2116 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2117 18c9b560 balrog
        break;
2118 18c9b560 balrog
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
2119 18c9b560 balrog
    case 0x314: case 0x714: case 0xb14: case 0xf14:
2120 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2121 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2122 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2123 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2124 18c9b560 balrog
        case 0:
2125 18c9b560 balrog
            return 1;
2126 18c9b560 balrog
        case 1:
2127 18c9b560 balrog
            if (gen_iwmmxt_shift(insn, 0xf))
2128 18c9b560 balrog
                return 1;
2129 e677137d pbrook
            gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2130 18c9b560 balrog
            break;
2131 18c9b560 balrog
        case 2:
2132 18c9b560 balrog
            if (gen_iwmmxt_shift(insn, 0x1f))
2133 18c9b560 balrog
                return 1;
2134 e677137d pbrook
            gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2135 18c9b560 balrog
            break;
2136 18c9b560 balrog
        case 3:
2137 18c9b560 balrog
            if (gen_iwmmxt_shift(insn, 0x3f))
2138 18c9b560 balrog
                return 1;
2139 e677137d pbrook
            gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2140 18c9b560 balrog
            break;
2141 18c9b560 balrog
        }
2142 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2143 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2144 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2145 18c9b560 balrog
        break;
2146 18c9b560 balrog
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
2147 18c9b560 balrog
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
2148 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2149 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2150 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2151 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2152 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2153 18c9b560 balrog
        case 0:
2154 18c9b560 balrog
            if (insn & (1 << 21))
2155 18c9b560 balrog
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
2156 18c9b560 balrog
            else
2157 18c9b560 balrog
                gen_op_iwmmxt_minub_M0_wRn(rd1);
2158 18c9b560 balrog
            break;
2159 18c9b560 balrog
        case 1:
2160 18c9b560 balrog
            if (insn & (1 << 21))
2161 18c9b560 balrog
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
2162 18c9b560 balrog
            else
2163 18c9b560 balrog
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
2164 18c9b560 balrog
            break;
2165 18c9b560 balrog
        case 2:
2166 18c9b560 balrog
            if (insn & (1 << 21))
2167 18c9b560 balrog
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
2168 18c9b560 balrog
            else
2169 18c9b560 balrog
                gen_op_iwmmxt_minul_M0_wRn(rd1);
2170 18c9b560 balrog
            break;
2171 18c9b560 balrog
        case 3:
2172 18c9b560 balrog
            return 1;
2173 18c9b560 balrog
        }
2174 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2175 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2176 18c9b560 balrog
        break;
2177 18c9b560 balrog
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
2178 18c9b560 balrog
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
2179 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2180 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2181 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2182 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2183 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2184 18c9b560 balrog
        case 0:
2185 18c9b560 balrog
            if (insn & (1 << 21))
2186 18c9b560 balrog
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2187 18c9b560 balrog
            else
2188 18c9b560 balrog
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
2189 18c9b560 balrog
            break;
2190 18c9b560 balrog
        case 1:
2191 18c9b560 balrog
            if (insn & (1 << 21))
2192 18c9b560 balrog
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2193 18c9b560 balrog
            else
2194 18c9b560 balrog
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2195 18c9b560 balrog
            break;
2196 18c9b560 balrog
        case 2:
2197 18c9b560 balrog
            if (insn & (1 << 21))
2198 18c9b560 balrog
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2199 18c9b560 balrog
            else
2200 18c9b560 balrog
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
2201 18c9b560 balrog
            break;
2202 18c9b560 balrog
        case 3:
2203 18c9b560 balrog
            return 1;
2204 18c9b560 balrog
        }
2205 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2206 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2207 18c9b560 balrog
        break;
2208 18c9b560 balrog
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
2209 18c9b560 balrog
    case 0x402: case 0x502: case 0x602: case 0x702:
2210 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2211 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2212 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2213 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2214 18c9b560 balrog
        gen_op_movl_T0_im((insn >> 20) & 3);
2215 18c9b560 balrog
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2216 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2217 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2218 18c9b560 balrog
        break;
2219 18c9b560 balrog
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
2220 18c9b560 balrog
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2221 18c9b560 balrog
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2222 18c9b560 balrog
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2223 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2224 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2225 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2226 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2227 18c9b560 balrog
        switch ((insn >> 20) & 0xf) {
2228 18c9b560 balrog
        case 0x0:
2229 18c9b560 balrog
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
2230 18c9b560 balrog
            break;
2231 18c9b560 balrog
        case 0x1:
2232 18c9b560 balrog
            gen_op_iwmmxt_subub_M0_wRn(rd1);
2233 18c9b560 balrog
            break;
2234 18c9b560 balrog
        case 0x3:
2235 18c9b560 balrog
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
2236 18c9b560 balrog
            break;
2237 18c9b560 balrog
        case 0x4:
2238 18c9b560 balrog
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
2239 18c9b560 balrog
            break;
2240 18c9b560 balrog
        case 0x5:
2241 18c9b560 balrog
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
2242 18c9b560 balrog
            break;
2243 18c9b560 balrog
        case 0x7:
2244 18c9b560 balrog
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
2245 18c9b560 balrog
            break;
2246 18c9b560 balrog
        case 0x8:
2247 18c9b560 balrog
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
2248 18c9b560 balrog
            break;
2249 18c9b560 balrog
        case 0x9:
2250 18c9b560 balrog
            gen_op_iwmmxt_subul_M0_wRn(rd1);
2251 18c9b560 balrog
            break;
2252 18c9b560 balrog
        case 0xb:
2253 18c9b560 balrog
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
2254 18c9b560 balrog
            break;
2255 18c9b560 balrog
        default:
2256 18c9b560 balrog
            return 1;
2257 18c9b560 balrog
        }
2258 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2259 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2260 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2261 18c9b560 balrog
        break;
2262 18c9b560 balrog
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
2263 18c9b560 balrog
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2264 18c9b560 balrog
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2265 18c9b560 balrog
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2266 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2267 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2268 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2269 18c9b560 balrog
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2270 e677137d pbrook
        gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2271 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2272 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2273 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2274 18c9b560 balrog
        break;
2275 18c9b560 balrog
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
2276 18c9b560 balrog
    case 0x418: case 0x518: case 0x618: case 0x718:
2277 18c9b560 balrog
    case 0x818: case 0x918: case 0xa18: case 0xb18:
2278 18c9b560 balrog
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2279 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2280 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2281 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2282 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2283 18c9b560 balrog
        switch ((insn >> 20) & 0xf) {
2284 18c9b560 balrog
        case 0x0:
2285 18c9b560 balrog
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
2286 18c9b560 balrog
            break;
2287 18c9b560 balrog
        case 0x1:
2288 18c9b560 balrog
            gen_op_iwmmxt_addub_M0_wRn(rd1);
2289 18c9b560 balrog
            break;
2290 18c9b560 balrog
        case 0x3:
2291 18c9b560 balrog
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
2292 18c9b560 balrog
            break;
2293 18c9b560 balrog
        case 0x4:
2294 18c9b560 balrog
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
2295 18c9b560 balrog
            break;
2296 18c9b560 balrog
        case 0x5:
2297 18c9b560 balrog
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
2298 18c9b560 balrog
            break;
2299 18c9b560 balrog
        case 0x7:
2300 18c9b560 balrog
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
2301 18c9b560 balrog
            break;
2302 18c9b560 balrog
        case 0x8:
2303 18c9b560 balrog
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
2304 18c9b560 balrog
            break;
2305 18c9b560 balrog
        case 0x9:
2306 18c9b560 balrog
            gen_op_iwmmxt_addul_M0_wRn(rd1);
2307 18c9b560 balrog
            break;
2308 18c9b560 balrog
        case 0xb:
2309 18c9b560 balrog
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
2310 18c9b560 balrog
            break;
2311 18c9b560 balrog
        default:
2312 18c9b560 balrog
            return 1;
2313 18c9b560 balrog
        }
2314 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2315 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2316 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2317 18c9b560 balrog
        break;
2318 18c9b560 balrog
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
2319 18c9b560 balrog
    case 0x408: case 0x508: case 0x608: case 0x708:
2320 18c9b560 balrog
    case 0x808: case 0x908: case 0xa08: case 0xb08:
2321 18c9b560 balrog
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2322 18c9b560 balrog
        wrd = (insn >> 12) & 0xf;
2323 18c9b560 balrog
        rd0 = (insn >> 16) & 0xf;
2324 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2325 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2326 18c9b560 balrog
        if (!(insn & (1 << 20)))
2327 18c9b560 balrog
            return 1;
2328 18c9b560 balrog
        switch ((insn >> 22) & 3) {
2329 18c9b560 balrog
        case 0:
2330 18c9b560 balrog
            return 1;
2331 18c9b560 balrog
        case 1:
2332 18c9b560 balrog
            if (insn & (1 << 21))
2333 18c9b560 balrog
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
2334 18c9b560 balrog
            else
2335 18c9b560 balrog
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
2336 18c9b560 balrog
            break;
2337 18c9b560 balrog
        case 2:
2338 18c9b560 balrog
            if (insn & (1 << 21))
2339 18c9b560 balrog
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
2340 18c9b560 balrog
            else
2341 18c9b560 balrog
                gen_op_iwmmxt_packul_M0_wRn(rd1);
2342 18c9b560 balrog
            break;
2343 18c9b560 balrog
        case 3:
2344 18c9b560 balrog
            if (insn & (1 << 21))
2345 18c9b560 balrog
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
2346 18c9b560 balrog
            else
2347 18c9b560 balrog
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
2348 18c9b560 balrog
            break;
2349 18c9b560 balrog
        }
2350 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2351 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2352 18c9b560 balrog
        gen_op_iwmmxt_set_cup();
2353 18c9b560 balrog
        break;
2354 18c9b560 balrog
    case 0x201: case 0x203: case 0x205: case 0x207:
2355 18c9b560 balrog
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
2356 18c9b560 balrog
    case 0x211: case 0x213: case 0x215: case 0x217:
2357 18c9b560 balrog
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
2358 18c9b560 balrog
        wrd = (insn >> 5) & 0xf;
2359 18c9b560 balrog
        rd0 = (insn >> 12) & 0xf;
2360 18c9b560 balrog
        rd1 = (insn >> 0) & 0xf;
2361 18c9b560 balrog
        if (rd0 == 0xf || rd1 == 0xf)
2362 18c9b560 balrog
            return 1;
2363 18c9b560 balrog
        gen_op_iwmmxt_movq_M0_wRn(wrd);
2364 18c9b560 balrog
        switch ((insn >> 16) & 0xf) {
2365 18c9b560 balrog
        case 0x0:                                        /* TMIA */
2366 b26eefb6 pbrook
            gen_movl_T0_reg(s, rd0);
2367 b26eefb6 pbrook
            gen_movl_T1_reg(s, rd1);
2368 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
2369 18c9b560 balrog
            break;
2370 18c9b560 balrog
        case 0x8:                                        /* TMIAPH */
2371 b26eefb6 pbrook
            gen_movl_T0_reg(s, rd0);
2372 b26eefb6 pbrook
            gen_movl_T1_reg(s, rd1);
2373 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
2374 18c9b560 balrog
            break;
2375 18c9b560 balrog
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2376 b26eefb6 pbrook
            gen_movl_T1_reg(s, rd0);
2377 18c9b560 balrog
            if (insn & (1 << 16))
2378 18c9b560 balrog
                gen_op_shrl_T1_im(16);
2379 18c9b560 balrog
            gen_op_movl_T0_T1();
2380 b26eefb6 pbrook
            gen_movl_T1_reg(s, rd1);
2381 18c9b560 balrog
            if (insn & (1 << 17))
2382 18c9b560 balrog
                gen_op_shrl_T1_im(16);
2383 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
2384 18c9b560 balrog
            break;
2385 18c9b560 balrog
        default:
2386 18c9b560 balrog
            return 1;
2387 18c9b560 balrog
        }
2388 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2389 18c9b560 balrog
        gen_op_iwmmxt_set_mup();
2390 18c9b560 balrog
        break;
2391 18c9b560 balrog
    default:
2392 18c9b560 balrog
        return 1;
2393 18c9b560 balrog
    }
2394 18c9b560 balrog
2395 18c9b560 balrog
    return 0;
2396 18c9b560 balrog
}
2397 18c9b560 balrog
2398 18c9b560 balrog
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2399 18c9b560 balrog
   (ie. an undefined instruction).  */
2400 18c9b560 balrog
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2401 18c9b560 balrog
{
2402 18c9b560 balrog
    int acc, rd0, rd1, rdhi, rdlo;
2403 3a554c0f Filip Navara
    TCGv tmp, tmp2;
2404 18c9b560 balrog
2405 18c9b560 balrog
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2406 18c9b560 balrog
        /* Multiply with Internal Accumulate Format */
2407 18c9b560 balrog
        rd0 = (insn >> 12) & 0xf;
2408 18c9b560 balrog
        rd1 = insn & 0xf;
2409 18c9b560 balrog
        acc = (insn >> 5) & 7;
2410 18c9b560 balrog
2411 18c9b560 balrog
        if (acc != 0)
2412 18c9b560 balrog
            return 1;
2413 18c9b560 balrog
2414 3a554c0f Filip Navara
        tmp = load_reg(s, rd0);
2415 3a554c0f Filip Navara
        tmp2 = load_reg(s, rd1);
2416 18c9b560 balrog
        switch ((insn >> 16) & 0xf) {
2417 18c9b560 balrog
        case 0x0:                                        /* MIA */
2418 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2419 18c9b560 balrog
            break;
2420 18c9b560 balrog
        case 0x8:                                        /* MIAPH */
2421 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2422 18c9b560 balrog
            break;
2423 18c9b560 balrog
        case 0xc:                                        /* MIABB */
2424 18c9b560 balrog
        case 0xd:                                        /* MIABT */
2425 18c9b560 balrog
        case 0xe:                                        /* MIATB */
2426 18c9b560 balrog
        case 0xf:                                        /* MIATT */
2427 18c9b560 balrog
            if (insn & (1 << 16))
2428 3a554c0f Filip Navara
                tcg_gen_shri_i32(tmp, tmp, 16);
2429 18c9b560 balrog
            if (insn & (1 << 17))
2430 3a554c0f Filip Navara
                tcg_gen_shri_i32(tmp2, tmp2, 16);
2431 3a554c0f Filip Navara
            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2432 18c9b560 balrog
            break;
2433 18c9b560 balrog
        default:
2434 18c9b560 balrog
            return 1;
2435 18c9b560 balrog
        }
2436 3a554c0f Filip Navara
        dead_tmp(tmp2);
2437 3a554c0f Filip Navara
        dead_tmp(tmp);
2438 18c9b560 balrog
2439 18c9b560 balrog
        gen_op_iwmmxt_movq_wRn_M0(acc);
2440 18c9b560 balrog
        return 0;
2441 18c9b560 balrog
    }
2442 18c9b560 balrog
2443 18c9b560 balrog
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2444 18c9b560 balrog
        /* Internal Accumulator Access Format */
2445 18c9b560 balrog
        rdhi = (insn >> 16) & 0xf;
2446 18c9b560 balrog
        rdlo = (insn >> 12) & 0xf;
2447 18c9b560 balrog
        acc = insn & 7;
2448 18c9b560 balrog
2449 18c9b560 balrog
        if (acc != 0)
2450 18c9b560 balrog
            return 1;
2451 18c9b560 balrog
2452 18c9b560 balrog
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2453 3a554c0f Filip Navara
            iwmmxt_load_reg(cpu_V0, acc);
2454 3a554c0f Filip Navara
            tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2455 3a554c0f Filip Navara
            tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2456 3a554c0f Filip Navara
            tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2457 3a554c0f Filip Navara
            tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2458 18c9b560 balrog
        } else {                                        /* MAR */
2459 3a554c0f Filip Navara
            tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2460 3a554c0f Filip Navara
            iwmmxt_store_reg(cpu_V0, acc);
2461 18c9b560 balrog
        }
2462 18c9b560 balrog
        return 0;
2463 18c9b560 balrog
    }
2464 18c9b560 balrog
2465 18c9b560 balrog
    return 1;
2466 18c9b560 balrog
}
2467 18c9b560 balrog
2468 c1713132 balrog
/* Disassemble system coprocessor instruction.  Return nonzero if
2469 c1713132 balrog
   instruction is not defined.  */
2470 c1713132 balrog
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2471 c1713132 balrog
{
2472 8984bd2e pbrook
    TCGv tmp;
2473 c1713132 balrog
    uint32_t rd = (insn >> 12) & 0xf;
2474 c1713132 balrog
    uint32_t cp = (insn >> 8) & 0xf;
2475 c1713132 balrog
    if (IS_USER(s)) {
2476 c1713132 balrog
        return 1;
2477 c1713132 balrog
    }
2478 c1713132 balrog
2479 18c9b560 balrog
    if (insn & ARM_CP_RW_BIT) {
2480 c1713132 balrog
        if (!env->cp[cp].cp_read)
2481 c1713132 balrog
            return 1;
2482 8984bd2e pbrook
        gen_set_pc_im(s->pc);
2483 8984bd2e pbrook
        tmp = new_tmp();
2484 8984bd2e pbrook
        gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2485 8984bd2e pbrook
        store_reg(s, rd, tmp);
2486 c1713132 balrog
    } else {
2487 c1713132 balrog
        if (!env->cp[cp].cp_write)
2488 c1713132 balrog
            return 1;
2489 8984bd2e pbrook
        gen_set_pc_im(s->pc);
2490 8984bd2e pbrook
        tmp = load_reg(s, rd);
2491 8984bd2e pbrook
        gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2492 a60de947 balrog
        dead_tmp(tmp);
2493 c1713132 balrog
    }
2494 c1713132 balrog
    return 0;
2495 c1713132 balrog
}
2496 c1713132 balrog
2497 9ee6e8bb pbrook
static int cp15_user_ok(uint32_t insn)
2498 9ee6e8bb pbrook
{
2499 9ee6e8bb pbrook
    int cpn = (insn >> 16) & 0xf;
2500 9ee6e8bb pbrook
    int cpm = insn & 0xf;
2501 9ee6e8bb pbrook
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2502 9ee6e8bb pbrook
2503 9ee6e8bb pbrook
    if (cpn == 13 && cpm == 0) {
2504 9ee6e8bb pbrook
        /* TLS register.  */
2505 9ee6e8bb pbrook
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2506 9ee6e8bb pbrook
            return 1;
2507 9ee6e8bb pbrook
    }
2508 9ee6e8bb pbrook
    if (cpn == 7) {
2509 9ee6e8bb pbrook
        /* ISB, DSB, DMB.  */
2510 9ee6e8bb pbrook
        if ((cpm == 5 && op == 4)
2511 9ee6e8bb pbrook
                || (cpm == 10 && (op == 4 || op == 5)))
2512 9ee6e8bb pbrook
            return 1;
2513 9ee6e8bb pbrook
    }
2514 9ee6e8bb pbrook
    return 0;
2515 9ee6e8bb pbrook
}
2516 9ee6e8bb pbrook
2517 b5ff1b31 bellard
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2518 b5ff1b31 bellard
   instruction is not defined.  */
2519 a90b7318 balrog
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2520 b5ff1b31 bellard
{
2521 b5ff1b31 bellard
    uint32_t rd;
2522 8984bd2e pbrook
    TCGv tmp;
2523 b5ff1b31 bellard
2524 9ee6e8bb pbrook
    /* M profile cores use memory mapped registers instead of cp15.  */
2525 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_M))
2526 9ee6e8bb pbrook
        return 1;
2527 9ee6e8bb pbrook
2528 9ee6e8bb pbrook
    if ((insn & (1 << 25)) == 0) {
2529 9ee6e8bb pbrook
        if (insn & (1 << 20)) {
2530 9ee6e8bb pbrook
            /* mrrc */
2531 9ee6e8bb pbrook
            return 1;
2532 9ee6e8bb pbrook
        }
2533 9ee6e8bb pbrook
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2534 9ee6e8bb pbrook
        return 0;
2535 9ee6e8bb pbrook
    }
2536 9ee6e8bb pbrook
    if ((insn & (1 << 4)) == 0) {
2537 9ee6e8bb pbrook
        /* cdp */
2538 9ee6e8bb pbrook
        return 1;
2539 9ee6e8bb pbrook
    }
2540 9ee6e8bb pbrook
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2541 b5ff1b31 bellard
        return 1;
2542 b5ff1b31 bellard
    }
2543 9332f9da bellard
    if ((insn & 0x0fff0fff) == 0x0e070f90
2544 9332f9da bellard
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2545 9332f9da bellard
        /* Wait for interrupt.  */
2546 8984bd2e pbrook
        gen_set_pc_im(s->pc);
2547 9ee6e8bb pbrook
        s->is_jmp = DISAS_WFI;
2548 9332f9da bellard
        return 0;
2549 9332f9da bellard
    }
2550 b5ff1b31 bellard
    rd = (insn >> 12) & 0xf;
2551 18c9b560 balrog
    if (insn & ARM_CP_RW_BIT) {
2552 8984bd2e pbrook
        tmp = new_tmp();
2553 8984bd2e pbrook
        gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2554 b5ff1b31 bellard
        /* If the destination register is r15 then sets condition codes.  */
2555 b5ff1b31 bellard
        if (rd != 15)
2556 8984bd2e pbrook
            store_reg(s, rd, tmp);
2557 8984bd2e pbrook
        else
2558 8984bd2e pbrook
            dead_tmp(tmp);
2559 b5ff1b31 bellard
    } else {
2560 8984bd2e pbrook
        tmp = load_reg(s, rd);
2561 8984bd2e pbrook
        gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2562 8984bd2e pbrook
        dead_tmp(tmp);
2563 a90b7318 balrog
        /* Normally we would always end the TB here, but Linux
2564 a90b7318 balrog
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2565 a90b7318 balrog
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2566 a90b7318 balrog
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2567 a90b7318 balrog
                (insn & 0x0fff0fff) != 0x0e010f10)
2568 a90b7318 balrog
            gen_lookup_tb(s);
2569 b5ff1b31 bellard
    }
2570 b5ff1b31 bellard
    return 0;
2571 b5ff1b31 bellard
}
2572 b5ff1b31 bellard
2573 9ee6e8bb pbrook
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2574 9ee6e8bb pbrook
#define VFP_SREG(insn, bigbit, smallbit) \
2575 9ee6e8bb pbrook
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2576 9ee6e8bb pbrook
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2577 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2578 9ee6e8bb pbrook
        reg = (((insn) >> (bigbit)) & 0x0f) \
2579 9ee6e8bb pbrook
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2580 9ee6e8bb pbrook
    } else { \
2581 9ee6e8bb pbrook
        if (insn & (1 << (smallbit))) \
2582 9ee6e8bb pbrook
            return 1; \
2583 9ee6e8bb pbrook
        reg = ((insn) >> (bigbit)) & 0x0f; \
2584 9ee6e8bb pbrook
    }} while (0)
2585 9ee6e8bb pbrook
2586 9ee6e8bb pbrook
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2587 9ee6e8bb pbrook
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2588 9ee6e8bb pbrook
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2589 9ee6e8bb pbrook
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2590 9ee6e8bb pbrook
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2591 9ee6e8bb pbrook
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2592 9ee6e8bb pbrook
2593 4373f3ce pbrook
/* Move between integer and VFP cores.  */
2594 4373f3ce pbrook
static TCGv gen_vfp_mrs(void)
2595 4373f3ce pbrook
{
2596 4373f3ce pbrook
    TCGv tmp = new_tmp();
2597 4373f3ce pbrook
    tcg_gen_mov_i32(tmp, cpu_F0s);
2598 4373f3ce pbrook
    return tmp;
2599 4373f3ce pbrook
}
2600 4373f3ce pbrook
2601 4373f3ce pbrook
static void gen_vfp_msr(TCGv tmp)
2602 4373f3ce pbrook
{
2603 4373f3ce pbrook
    tcg_gen_mov_i32(cpu_F0s, tmp);
2604 4373f3ce pbrook
    dead_tmp(tmp);
2605 4373f3ce pbrook
}
2606 4373f3ce pbrook
2607 9ee6e8bb pbrook
static inline int
2608 9ee6e8bb pbrook
vfp_enabled(CPUState * env)
2609 9ee6e8bb pbrook
{
2610 9ee6e8bb pbrook
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2611 9ee6e8bb pbrook
}
2612 9ee6e8bb pbrook
2613 ad69471c pbrook
static void gen_neon_dup_u8(TCGv var, int shift)
2614 ad69471c pbrook
{
2615 ad69471c pbrook
    TCGv tmp = new_tmp();
2616 ad69471c pbrook
    if (shift)
2617 ad69471c pbrook
        tcg_gen_shri_i32(var, var, shift);
2618 86831435 pbrook
    tcg_gen_ext8u_i32(var, var);
2619 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 8);
2620 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2621 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 16);
2622 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2623 ad69471c pbrook
    dead_tmp(tmp);
2624 ad69471c pbrook
}
2625 ad69471c pbrook
2626 ad69471c pbrook
static void gen_neon_dup_low16(TCGv var)
2627 ad69471c pbrook
{
2628 ad69471c pbrook
    TCGv tmp = new_tmp();
2629 86831435 pbrook
    tcg_gen_ext16u_i32(var, var);
2630 ad69471c pbrook
    tcg_gen_shli_i32(tmp, var, 16);
2631 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2632 ad69471c pbrook
    dead_tmp(tmp);
2633 ad69471c pbrook
}
2634 ad69471c pbrook
2635 ad69471c pbrook
static void gen_neon_dup_high16(TCGv var)
2636 ad69471c pbrook
{
2637 ad69471c pbrook
    TCGv tmp = new_tmp();
2638 ad69471c pbrook
    tcg_gen_andi_i32(var, var, 0xffff0000);
2639 ad69471c pbrook
    tcg_gen_shri_i32(tmp, var, 16);
2640 ad69471c pbrook
    tcg_gen_or_i32(var, var, tmp);
2641 ad69471c pbrook
    dead_tmp(tmp);
2642 ad69471c pbrook
}
2643 ad69471c pbrook
2644 b7bcbe95 bellard
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2645 b7bcbe95 bellard
   (ie. an undefined instruction).  */
2646 b7bcbe95 bellard
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2647 b7bcbe95 bellard
{
2648 b7bcbe95 bellard
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2649 b7bcbe95 bellard
    int dp, veclen;
2650 4373f3ce pbrook
    TCGv tmp;
2651 ad69471c pbrook
    TCGv tmp2;
2652 b7bcbe95 bellard
2653 40f137e1 pbrook
    if (!arm_feature(env, ARM_FEATURE_VFP))
2654 40f137e1 pbrook
        return 1;
2655 40f137e1 pbrook
2656 9ee6e8bb pbrook
    if (!vfp_enabled(env)) {
2657 9ee6e8bb pbrook
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2658 40f137e1 pbrook
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2659 40f137e1 pbrook
            return 1;
2660 40f137e1 pbrook
        rn = (insn >> 16) & 0xf;
2661 9ee6e8bb pbrook
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2662 9ee6e8bb pbrook
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2663 40f137e1 pbrook
            return 1;
2664 40f137e1 pbrook
    }
2665 b7bcbe95 bellard
    dp = ((insn & 0xf00) == 0xb00);
2666 b7bcbe95 bellard
    switch ((insn >> 24) & 0xf) {
2667 b7bcbe95 bellard
    case 0xe:
2668 b7bcbe95 bellard
        if (insn & (1 << 4)) {
2669 b7bcbe95 bellard
            /* single register transfer */
2670 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
2671 b7bcbe95 bellard
            if (dp) {
2672 9ee6e8bb pbrook
                int size;
2673 9ee6e8bb pbrook
                int pass;
2674 9ee6e8bb pbrook
2675 9ee6e8bb pbrook
                VFP_DREG_N(rn, insn);
2676 9ee6e8bb pbrook
                if (insn & 0xf)
2677 b7bcbe95 bellard
                    return 1;
2678 9ee6e8bb pbrook
                if (insn & 0x00c00060
2679 9ee6e8bb pbrook
                    && !arm_feature(env, ARM_FEATURE_NEON))
2680 9ee6e8bb pbrook
                    return 1;
2681 9ee6e8bb pbrook
2682 9ee6e8bb pbrook
                pass = (insn >> 21) & 1;
2683 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
2684 9ee6e8bb pbrook
                    size = 0;
2685 9ee6e8bb pbrook
                    offset = ((insn >> 5) & 3) * 8;
2686 9ee6e8bb pbrook
                } else if (insn & (1 << 5)) {
2687 9ee6e8bb pbrook
                    size = 1;
2688 9ee6e8bb pbrook
                    offset = (insn & (1 << 6)) ? 16 : 0;
2689 9ee6e8bb pbrook
                } else {
2690 9ee6e8bb pbrook
                    size = 2;
2691 9ee6e8bb pbrook
                    offset = 0;
2692 9ee6e8bb pbrook
                }
2693 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2694 b7bcbe95 bellard
                    /* vfp->arm */
2695 ad69471c pbrook
                    tmp = neon_load_reg(rn, pass);
2696 9ee6e8bb pbrook
                    switch (size) {
2697 9ee6e8bb pbrook
                    case 0:
2698 9ee6e8bb pbrook
                        if (offset)
2699 ad69471c pbrook
                            tcg_gen_shri_i32(tmp, tmp, offset);
2700 9ee6e8bb pbrook
                        if (insn & (1 << 23))
2701 ad69471c pbrook
                            gen_uxtb(tmp);
2702 9ee6e8bb pbrook
                        else
2703 ad69471c pbrook
                            gen_sxtb(tmp);
2704 9ee6e8bb pbrook
                        break;
2705 9ee6e8bb pbrook
                    case 1:
2706 9ee6e8bb pbrook
                        if (insn & (1 << 23)) {
2707 9ee6e8bb pbrook
                            if (offset) {
2708 ad69471c pbrook
                                tcg_gen_shri_i32(tmp, tmp, 16);
2709 9ee6e8bb pbrook
                            } else {
2710 ad69471c pbrook
                                gen_uxth(tmp);
2711 9ee6e8bb pbrook
                            }
2712 9ee6e8bb pbrook
                        } else {
2713 9ee6e8bb pbrook
                            if (offset) {
2714 ad69471c pbrook
                                tcg_gen_sari_i32(tmp, tmp, 16);
2715 9ee6e8bb pbrook
                            } else {
2716 ad69471c pbrook
                                gen_sxth(tmp);
2717 9ee6e8bb pbrook
                            }
2718 9ee6e8bb pbrook
                        }
2719 9ee6e8bb pbrook
                        break;
2720 9ee6e8bb pbrook
                    case 2:
2721 9ee6e8bb pbrook
                        break;
2722 9ee6e8bb pbrook
                    }
2723 ad69471c pbrook
                    store_reg(s, rd, tmp);
2724 b7bcbe95 bellard
                } else {
2725 b7bcbe95 bellard
                    /* arm->vfp */
2726 ad69471c pbrook
                    tmp = load_reg(s, rd);
2727 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
2728 9ee6e8bb pbrook
                        /* VDUP */
2729 9ee6e8bb pbrook
                        if (size == 0) {
2730 ad69471c pbrook
                            gen_neon_dup_u8(tmp, 0);
2731 9ee6e8bb pbrook
                        } else if (size == 1) {
2732 ad69471c pbrook
                            gen_neon_dup_low16(tmp);
2733 9ee6e8bb pbrook
                        }
2734 cbbccffc pbrook
                        for (n = 0; n <= pass * 2; n++) {
2735 cbbccffc pbrook
                            tmp2 = new_tmp();
2736 cbbccffc pbrook
                            tcg_gen_mov_i32(tmp2, tmp);
2737 cbbccffc pbrook
                            neon_store_reg(rn, n, tmp2);
2738 cbbccffc pbrook
                        }
2739 cbbccffc pbrook
                        neon_store_reg(rn, n, tmp);
2740 9ee6e8bb pbrook
                    } else {
2741 9ee6e8bb pbrook
                        /* VMOV */
2742 9ee6e8bb pbrook
                        switch (size) {
2743 9ee6e8bb pbrook
                        case 0:
2744 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2745 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2746 ad69471c pbrook
                            dead_tmp(tmp2);
2747 9ee6e8bb pbrook
                            break;
2748 9ee6e8bb pbrook
                        case 1:
2749 ad69471c pbrook
                            tmp2 = neon_load_reg(rn, pass);
2750 ad69471c pbrook
                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2751 ad69471c pbrook
                            dead_tmp(tmp2);
2752 9ee6e8bb pbrook
                            break;
2753 9ee6e8bb pbrook
                        case 2:
2754 9ee6e8bb pbrook
                            break;
2755 9ee6e8bb pbrook
                        }
2756 ad69471c pbrook
                        neon_store_reg(rn, pass, tmp);
2757 9ee6e8bb pbrook
                    }
2758 b7bcbe95 bellard
                }
2759 9ee6e8bb pbrook
            } else { /* !dp */
2760 9ee6e8bb pbrook
                if ((insn & 0x6f) != 0x00)
2761 9ee6e8bb pbrook
                    return 1;
2762 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2763 18c9b560 balrog
                if (insn & ARM_CP_RW_BIT) {
2764 b7bcbe95 bellard
                    /* vfp->arm */
2765 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2766 b7bcbe95 bellard
                        /* system register */
2767 40f137e1 pbrook
                        rn >>= 1;
2768 9ee6e8bb pbrook
2769 b7bcbe95 bellard
                        switch (rn) {
2770 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2771 4373f3ce pbrook
                            /* VFP2 allows access to FSID from userspace.
2772 9ee6e8bb pbrook
                               VFP3 restricts all id registers to privileged
2773 9ee6e8bb pbrook
                               accesses.  */
2774 9ee6e8bb pbrook
                            if (IS_USER(s)
2775 9ee6e8bb pbrook
                                && arm_feature(env, ARM_FEATURE_VFP3))
2776 9ee6e8bb pbrook
                                return 1;
2777 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2778 9ee6e8bb pbrook
                            break;
2779 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2780 9ee6e8bb pbrook
                            if (IS_USER(s))
2781 9ee6e8bb pbrook
                                return 1;
2782 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2783 9ee6e8bb pbrook
                            break;
2784 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2785 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2786 9ee6e8bb pbrook
                            /* Not present in VFP3.  */
2787 9ee6e8bb pbrook
                            if (IS_USER(s)
2788 9ee6e8bb pbrook
                                || arm_feature(env, ARM_FEATURE_VFP3))
2789 9ee6e8bb pbrook
                                return 1;
2790 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2791 b7bcbe95 bellard
                            break;
2792 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2793 601d70b9 balrog
                            if (rd == 15) {
2794 4373f3ce pbrook
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2795 4373f3ce pbrook
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2796 4373f3ce pbrook
                            } else {
2797 4373f3ce pbrook
                                tmp = new_tmp();
2798 4373f3ce pbrook
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2799 4373f3ce pbrook
                            }
2800 b7bcbe95 bellard
                            break;
2801 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2802 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2803 9ee6e8bb pbrook
                            if (IS_USER(s)
2804 9ee6e8bb pbrook
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2805 9ee6e8bb pbrook
                                return 1;
2806 4373f3ce pbrook
                            tmp = load_cpu_field(vfp.xregs[rn]);
2807 9ee6e8bb pbrook
                            break;
2808 b7bcbe95 bellard
                        default:
2809 b7bcbe95 bellard
                            return 1;
2810 b7bcbe95 bellard
                        }
2811 b7bcbe95 bellard
                    } else {
2812 b7bcbe95 bellard
                        gen_mov_F0_vreg(0, rn);
2813 4373f3ce pbrook
                        tmp = gen_vfp_mrs();
2814 b7bcbe95 bellard
                    }
2815 b7bcbe95 bellard
                    if (rd == 15) {
2816 b5ff1b31 bellard
                        /* Set the 4 flag bits in the CPSR.  */
2817 4373f3ce pbrook
                        gen_set_nzcv(tmp);
2818 4373f3ce pbrook
                        dead_tmp(tmp);
2819 4373f3ce pbrook
                    } else {
2820 4373f3ce pbrook
                        store_reg(s, rd, tmp);
2821 4373f3ce pbrook
                    }
2822 b7bcbe95 bellard
                } else {
2823 b7bcbe95 bellard
                    /* arm->vfp */
2824 4373f3ce pbrook
                    tmp = load_reg(s, rd);
2825 b7bcbe95 bellard
                    if (insn & (1 << 21)) {
2826 40f137e1 pbrook
                        rn >>= 1;
2827 b7bcbe95 bellard
                        /* system register */
2828 b7bcbe95 bellard
                        switch (rn) {
2829 40f137e1 pbrook
                        case ARM_VFP_FPSID:
2830 9ee6e8bb pbrook
                        case ARM_VFP_MVFR0:
2831 9ee6e8bb pbrook
                        case ARM_VFP_MVFR1:
2832 b7bcbe95 bellard
                            /* Writes are ignored.  */
2833 b7bcbe95 bellard
                            break;
2834 40f137e1 pbrook
                        case ARM_VFP_FPSCR:
2835 4373f3ce pbrook
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2836 4373f3ce pbrook
                            dead_tmp(tmp);
2837 b5ff1b31 bellard
                            gen_lookup_tb(s);
2838 b7bcbe95 bellard
                            break;
2839 40f137e1 pbrook
                        case ARM_VFP_FPEXC:
2840 9ee6e8bb pbrook
                            if (IS_USER(s))
2841 9ee6e8bb pbrook
                                return 1;
2842 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2843 40f137e1 pbrook
                            gen_lookup_tb(s);
2844 40f137e1 pbrook
                            break;
2845 40f137e1 pbrook
                        case ARM_VFP_FPINST:
2846 40f137e1 pbrook
                        case ARM_VFP_FPINST2:
2847 4373f3ce pbrook
                            store_cpu_field(tmp, vfp.xregs[rn]);
2848 40f137e1 pbrook
                            break;
2849 b7bcbe95 bellard
                        default:
2850 b7bcbe95 bellard
                            return 1;
2851 b7bcbe95 bellard
                        }
2852 b7bcbe95 bellard
                    } else {
2853 4373f3ce pbrook
                        gen_vfp_msr(tmp);
2854 b7bcbe95 bellard
                        gen_mov_vreg_F0(0, rn);
2855 b7bcbe95 bellard
                    }
2856 b7bcbe95 bellard
                }
2857 b7bcbe95 bellard
            }
2858 b7bcbe95 bellard
        } else {
2859 b7bcbe95 bellard
            /* data processing */
2860 b7bcbe95 bellard
            /* The opcode is in bits 23, 21, 20 and 6.  */
2861 b7bcbe95 bellard
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2862 b7bcbe95 bellard
            if (dp) {
2863 b7bcbe95 bellard
                if (op == 15) {
2864 b7bcbe95 bellard
                    /* rn is opcode */
2865 b7bcbe95 bellard
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2866 b7bcbe95 bellard
                } else {
2867 b7bcbe95 bellard
                    /* rn is register number */
2868 9ee6e8bb pbrook
                    VFP_DREG_N(rn, insn);
2869 b7bcbe95 bellard
                }
2870 b7bcbe95 bellard
2871 b7bcbe95 bellard
                if (op == 15 && (rn == 15 || rn > 17)) {
2872 b7bcbe95 bellard
                    /* Integer or single precision destination.  */
2873 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2874 b7bcbe95 bellard
                } else {
2875 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2876 b7bcbe95 bellard
                }
2877 b7bcbe95 bellard
2878 b7bcbe95 bellard
                if (op == 15 && (rn == 16 || rn == 17)) {
2879 b7bcbe95 bellard
                    /* Integer source.  */
2880 b7bcbe95 bellard
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2881 b7bcbe95 bellard
                } else {
2882 9ee6e8bb pbrook
                    VFP_DREG_M(rm, insn);
2883 b7bcbe95 bellard
                }
2884 b7bcbe95 bellard
            } else {
2885 9ee6e8bb pbrook
                rn = VFP_SREG_N(insn);
2886 b7bcbe95 bellard
                if (op == 15 && rn == 15) {
2887 b7bcbe95 bellard
                    /* Double precision destination.  */
2888 9ee6e8bb pbrook
                    VFP_DREG_D(rd, insn);
2889 9ee6e8bb pbrook
                } else {
2890 9ee6e8bb pbrook
                    rd = VFP_SREG_D(insn);
2891 9ee6e8bb pbrook
                }
2892 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
2893 b7bcbe95 bellard
            }
2894 b7bcbe95 bellard
2895 b7bcbe95 bellard
            veclen = env->vfp.vec_len;
2896 b7bcbe95 bellard
            if (op == 15 && rn > 3)
2897 b7bcbe95 bellard
                veclen = 0;
2898 b7bcbe95 bellard
2899 b7bcbe95 bellard
            /* Shut up compiler warnings.  */
2900 b7bcbe95 bellard
            delta_m = 0;
2901 b7bcbe95 bellard
            delta_d = 0;
2902 b7bcbe95 bellard
            bank_mask = 0;
2903 3b46e624 ths
2904 b7bcbe95 bellard
            if (veclen > 0) {
2905 b7bcbe95 bellard
                if (dp)
2906 b7bcbe95 bellard
                    bank_mask = 0xc;
2907 b7bcbe95 bellard
                else
2908 b7bcbe95 bellard
                    bank_mask = 0x18;
2909 b7bcbe95 bellard
2910 b7bcbe95 bellard
                /* Figure out what type of vector operation this is.  */
2911 b7bcbe95 bellard
                if ((rd & bank_mask) == 0) {
2912 b7bcbe95 bellard
                    /* scalar */
2913 b7bcbe95 bellard
                    veclen = 0;
2914 b7bcbe95 bellard
                } else {
2915 b7bcbe95 bellard
                    if (dp)
2916 b7bcbe95 bellard
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2917 b7bcbe95 bellard
                    else
2918 b7bcbe95 bellard
                        delta_d = env->vfp.vec_stride + 1;
2919 b7bcbe95 bellard
2920 b7bcbe95 bellard
                    if ((rm & bank_mask) == 0) {
2921 b7bcbe95 bellard
                        /* mixed scalar/vector */
2922 b7bcbe95 bellard
                        delta_m = 0;
2923 b7bcbe95 bellard
                    } else {
2924 b7bcbe95 bellard
                        /* vector */
2925 b7bcbe95 bellard
                        delta_m = delta_d;
2926 b7bcbe95 bellard
                    }
2927 b7bcbe95 bellard
                }
2928 b7bcbe95 bellard
            }
2929 b7bcbe95 bellard
2930 b7bcbe95 bellard
            /* Load the initial operands.  */
2931 b7bcbe95 bellard
            if (op == 15) {
2932 b7bcbe95 bellard
                switch (rn) {
2933 b7bcbe95 bellard
                case 16:
2934 b7bcbe95 bellard
                case 17:
2935 b7bcbe95 bellard
                    /* Integer source */
2936 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
2937 b7bcbe95 bellard
                    break;
2938 b7bcbe95 bellard
                case 8:
2939 b7bcbe95 bellard
                case 9:
2940 b7bcbe95 bellard
                    /* Compare */
2941 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
2942 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rm);
2943 b7bcbe95 bellard
                    break;
2944 b7bcbe95 bellard
                case 10:
2945 b7bcbe95 bellard
                case 11:
2946 b7bcbe95 bellard
                    /* Compare with zero */
2947 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
2948 b7bcbe95 bellard
                    gen_vfp_F1_ld0(dp);
2949 b7bcbe95 bellard
                    break;
2950 9ee6e8bb pbrook
                case 20:
2951 9ee6e8bb pbrook
                case 21:
2952 9ee6e8bb pbrook
                case 22:
2953 9ee6e8bb pbrook
                case 23:
2954 644ad806 pbrook
                case 28:
2955 644ad806 pbrook
                case 29:
2956 644ad806 pbrook
                case 30:
2957 644ad806 pbrook
                case 31:
2958 9ee6e8bb pbrook
                    /* Source and destination the same.  */
2959 9ee6e8bb pbrook
                    gen_mov_F0_vreg(dp, rd);
2960 9ee6e8bb pbrook
                    break;
2961 b7bcbe95 bellard
                default:
2962 b7bcbe95 bellard
                    /* One source operand.  */
2963 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
2964 9ee6e8bb pbrook
                    break;
2965 b7bcbe95 bellard
                }
2966 b7bcbe95 bellard
            } else {
2967 b7bcbe95 bellard
                /* Two source operands.  */
2968 b7bcbe95 bellard
                gen_mov_F0_vreg(dp, rn);
2969 b7bcbe95 bellard
                gen_mov_F1_vreg(dp, rm);
2970 b7bcbe95 bellard
            }
2971 b7bcbe95 bellard
2972 b7bcbe95 bellard
            for (;;) {
2973 b7bcbe95 bellard
                /* Perform the calculation.  */
2974 b7bcbe95 bellard
                switch (op) {
2975 b7bcbe95 bellard
                case 0: /* mac: fd + (fn * fm) */
2976 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2977 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
2978 b7bcbe95 bellard
                    gen_vfp_add(dp);
2979 b7bcbe95 bellard
                    break;
2980 b7bcbe95 bellard
                case 1: /* nmac: fd - (fn * fm) */
2981 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2982 b7bcbe95 bellard
                    gen_vfp_neg(dp);
2983 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
2984 b7bcbe95 bellard
                    gen_vfp_add(dp);
2985 b7bcbe95 bellard
                    break;
2986 b7bcbe95 bellard
                case 2: /* msc: -fd + (fn * fm) */
2987 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2988 b7bcbe95 bellard
                    gen_mov_F1_vreg(dp, rd);
2989 b7bcbe95 bellard
                    gen_vfp_sub(dp);
2990 b7bcbe95 bellard
                    break;
2991 b7bcbe95 bellard
                case 3: /* nmsc: -fd - (fn * fm)  */
2992 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2993 b7bcbe95 bellard
                    gen_vfp_neg(dp);
2994 c9fb531a pbrook
                    gen_mov_F1_vreg(dp, rd);
2995 c9fb531a pbrook
                    gen_vfp_sub(dp);
2996 b7bcbe95 bellard
                    break;
2997 b7bcbe95 bellard
                case 4: /* mul: fn * fm */
2998 b7bcbe95 bellard
                    gen_vfp_mul(dp);
2999 b7bcbe95 bellard
                    break;
3000 b7bcbe95 bellard
                case 5: /* nmul: -(fn * fm) */
3001 b7bcbe95 bellard
                    gen_vfp_mul(dp);
3002 b7bcbe95 bellard
                    gen_vfp_neg(dp);
3003 b7bcbe95 bellard
                    break;
3004 b7bcbe95 bellard
                case 6: /* add: fn + fm */
3005 b7bcbe95 bellard
                    gen_vfp_add(dp);
3006 b7bcbe95 bellard
                    break;
3007 b7bcbe95 bellard
                case 7: /* sub: fn - fm */
3008 b7bcbe95 bellard
                    gen_vfp_sub(dp);
3009 b7bcbe95 bellard
                    break;
3010 b7bcbe95 bellard
                case 8: /* div: fn / fm */
3011 b7bcbe95 bellard
                    gen_vfp_div(dp);
3012 b7bcbe95 bellard
                    break;
3013 9ee6e8bb pbrook
                case 14: /* fconst */
3014 9ee6e8bb pbrook
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
3015 9ee6e8bb pbrook
                      return 1;
3016 9ee6e8bb pbrook
3017 9ee6e8bb pbrook
                    n = (insn << 12) & 0x80000000;
3018 9ee6e8bb pbrook
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
3019 9ee6e8bb pbrook
                    if (dp) {
3020 9ee6e8bb pbrook
                        if (i & 0x40)
3021 9ee6e8bb pbrook
                            i |= 0x3f80;
3022 9ee6e8bb pbrook
                        else
3023 9ee6e8bb pbrook
                            i |= 0x4000;
3024 9ee6e8bb pbrook
                        n |= i << 16;
3025 4373f3ce pbrook
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3026 9ee6e8bb pbrook
                    } else {
3027 9ee6e8bb pbrook
                        if (i & 0x40)
3028 9ee6e8bb pbrook
                            i |= 0x780;
3029 9ee6e8bb pbrook
                        else
3030 9ee6e8bb pbrook
                            i |= 0x800;
3031 9ee6e8bb pbrook
                        n |= i << 19;
3032 5b340b51 balrog
                        tcg_gen_movi_i32(cpu_F0s, n);
3033 9ee6e8bb pbrook
                    }
3034 9ee6e8bb pbrook
                    break;
3035 b7bcbe95 bellard
                case 15: /* extension space */
3036 b7bcbe95 bellard
                    switch (rn) {
3037 b7bcbe95 bellard
                    case 0: /* cpy */
3038 b7bcbe95 bellard
                        /* no-op */
3039 b7bcbe95 bellard
                        break;
3040 b7bcbe95 bellard
                    case 1: /* abs */
3041 b7bcbe95 bellard
                        gen_vfp_abs(dp);
3042 b7bcbe95 bellard
                        break;
3043 b7bcbe95 bellard
                    case 2: /* neg */
3044 b7bcbe95 bellard
                        gen_vfp_neg(dp);
3045 b7bcbe95 bellard
                        break;
3046 b7bcbe95 bellard
                    case 3: /* sqrt */
3047 b7bcbe95 bellard
                        gen_vfp_sqrt(dp);
3048 b7bcbe95 bellard
                        break;
3049 b7bcbe95 bellard
                    case 8: /* cmp */
3050 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3051 b7bcbe95 bellard
                        break;
3052 b7bcbe95 bellard
                    case 9: /* cmpe */
3053 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3054 b7bcbe95 bellard
                        break;
3055 b7bcbe95 bellard
                    case 10: /* cmpz */
3056 b7bcbe95 bellard
                        gen_vfp_cmp(dp);
3057 b7bcbe95 bellard
                        break;
3058 b7bcbe95 bellard
                    case 11: /* cmpez */
3059 b7bcbe95 bellard
                        gen_vfp_F1_ld0(dp);
3060 b7bcbe95 bellard
                        gen_vfp_cmpe(dp);
3061 b7bcbe95 bellard
                        break;
3062 b7bcbe95 bellard
                    case 15: /* single<->double conversion */
3063 b7bcbe95 bellard
                        if (dp)
3064 4373f3ce pbrook
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3065 b7bcbe95 bellard
                        else
3066 4373f3ce pbrook
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3067 b7bcbe95 bellard
                        break;
3068 b7bcbe95 bellard
                    case 16: /* fuito */
3069 b7bcbe95 bellard
                        gen_vfp_uito(dp);
3070 b7bcbe95 bellard
                        break;
3071 b7bcbe95 bellard
                    case 17: /* fsito */
3072 b7bcbe95 bellard
                        gen_vfp_sito(dp);
3073 b7bcbe95 bellard
                        break;
3074 9ee6e8bb pbrook
                    case 20: /* fshto */
3075 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3076 9ee6e8bb pbrook
                          return 1;
3077 644ad806 pbrook
                        gen_vfp_shto(dp, 16 - rm);
3078 9ee6e8bb pbrook
                        break;
3079 9ee6e8bb pbrook
                    case 21: /* fslto */
3080 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3081 9ee6e8bb pbrook
                          return 1;
3082 644ad806 pbrook
                        gen_vfp_slto(dp, 32 - rm);
3083 9ee6e8bb pbrook
                        break;
3084 9ee6e8bb pbrook
                    case 22: /* fuhto */
3085 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3086 9ee6e8bb pbrook
                          return 1;
3087 644ad806 pbrook
                        gen_vfp_uhto(dp, 16 - rm);
3088 9ee6e8bb pbrook
                        break;
3089 9ee6e8bb pbrook
                    case 23: /* fulto */
3090 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3091 9ee6e8bb pbrook
                          return 1;
3092 644ad806 pbrook
                        gen_vfp_ulto(dp, 32 - rm);
3093 9ee6e8bb pbrook
                        break;
3094 b7bcbe95 bellard
                    case 24: /* ftoui */
3095 b7bcbe95 bellard
                        gen_vfp_toui(dp);
3096 b7bcbe95 bellard
                        break;
3097 b7bcbe95 bellard
                    case 25: /* ftouiz */
3098 b7bcbe95 bellard
                        gen_vfp_touiz(dp);
3099 b7bcbe95 bellard
                        break;
3100 b7bcbe95 bellard
                    case 26: /* ftosi */
3101 b7bcbe95 bellard
                        gen_vfp_tosi(dp);
3102 b7bcbe95 bellard
                        break;
3103 b7bcbe95 bellard
                    case 27: /* ftosiz */
3104 b7bcbe95 bellard
                        gen_vfp_tosiz(dp);
3105 b7bcbe95 bellard
                        break;
3106 9ee6e8bb pbrook
                    case 28: /* ftosh */
3107 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3108 9ee6e8bb pbrook
                          return 1;
3109 644ad806 pbrook
                        gen_vfp_tosh(dp, 16 - rm);
3110 9ee6e8bb pbrook
                        break;
3111 9ee6e8bb pbrook
                    case 29: /* ftosl */
3112 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3113 9ee6e8bb pbrook
                          return 1;
3114 644ad806 pbrook
                        gen_vfp_tosl(dp, 32 - rm);
3115 9ee6e8bb pbrook
                        break;
3116 9ee6e8bb pbrook
                    case 30: /* ftouh */
3117 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3118 9ee6e8bb pbrook
                          return 1;
3119 644ad806 pbrook
                        gen_vfp_touh(dp, 16 - rm);
3120 9ee6e8bb pbrook
                        break;
3121 9ee6e8bb pbrook
                    case 31: /* ftoul */
3122 9ee6e8bb pbrook
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3123 9ee6e8bb pbrook
                          return 1;
3124 644ad806 pbrook
                        gen_vfp_toul(dp, 32 - rm);
3125 9ee6e8bb pbrook
                        break;
3126 b7bcbe95 bellard
                    default: /* undefined */
3127 b7bcbe95 bellard
                        printf ("rn:%d\n", rn);
3128 b7bcbe95 bellard
                        return 1;
3129 b7bcbe95 bellard
                    }
3130 b7bcbe95 bellard
                    break;
3131 b7bcbe95 bellard
                default: /* undefined */
3132 b7bcbe95 bellard
                    printf ("op:%d\n", op);
3133 b7bcbe95 bellard
                    return 1;
3134 b7bcbe95 bellard
                }
3135 b7bcbe95 bellard
3136 b7bcbe95 bellard
                /* Write back the result.  */
3137 b7bcbe95 bellard
                if (op == 15 && (rn >= 8 && rn <= 11))
3138 b7bcbe95 bellard
                    ; /* Comparison, do nothing.  */
3139 b7bcbe95 bellard
                else if (op == 15 && rn > 17)
3140 b7bcbe95 bellard
                    /* Integer result.  */
3141 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rd);
3142 b7bcbe95 bellard
                else if (op == 15 && rn == 15)
3143 b7bcbe95 bellard
                    /* conversion */
3144 b7bcbe95 bellard
                    gen_mov_vreg_F0(!dp, rd);
3145 b7bcbe95 bellard
                else
3146 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3147 b7bcbe95 bellard
3148 b7bcbe95 bellard
                /* break out of the loop if we have finished  */
3149 b7bcbe95 bellard
                if (veclen == 0)
3150 b7bcbe95 bellard
                    break;
3151 b7bcbe95 bellard
3152 b7bcbe95 bellard
                if (op == 15 && delta_m == 0) {
3153 b7bcbe95 bellard
                    /* single source one-many */
3154 b7bcbe95 bellard
                    while (veclen--) {
3155 b7bcbe95 bellard
                        rd = ((rd + delta_d) & (bank_mask - 1))
3156 b7bcbe95 bellard
                             | (rd & bank_mask);
3157 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd);
3158 b7bcbe95 bellard
                    }
3159 b7bcbe95 bellard
                    break;
3160 b7bcbe95 bellard
                }
3161 b7bcbe95 bellard
                /* Setup the next operands.  */
3162 b7bcbe95 bellard
                veclen--;
3163 b7bcbe95 bellard
                rd = ((rd + delta_d) & (bank_mask - 1))
3164 b7bcbe95 bellard
                     | (rd & bank_mask);
3165 b7bcbe95 bellard
3166 b7bcbe95 bellard
                if (op == 15) {
3167 b7bcbe95 bellard
                    /* One source operand.  */
3168 b7bcbe95 bellard
                    rm = ((rm + delta_m) & (bank_mask - 1))
3169 b7bcbe95 bellard
                         | (rm & bank_mask);
3170 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rm);
3171 b7bcbe95 bellard
                } else {
3172 b7bcbe95 bellard
                    /* Two source operands.  */
3173 b7bcbe95 bellard
                    rn = ((rn + delta_d) & (bank_mask - 1))
3174 b7bcbe95 bellard
                         | (rn & bank_mask);
3175 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rn);
3176 b7bcbe95 bellard
                    if (delta_m) {
3177 b7bcbe95 bellard
                        rm = ((rm + delta_m) & (bank_mask - 1))
3178 b7bcbe95 bellard
                             | (rm & bank_mask);
3179 b7bcbe95 bellard
                        gen_mov_F1_vreg(dp, rm);
3180 b7bcbe95 bellard
                    }
3181 b7bcbe95 bellard
                }
3182 b7bcbe95 bellard
            }
3183 b7bcbe95 bellard
        }
3184 b7bcbe95 bellard
        break;
3185 b7bcbe95 bellard
    case 0xc:
3186 b7bcbe95 bellard
    case 0xd:
3187 9ee6e8bb pbrook
        if (dp && (insn & 0x03e00000) == 0x00400000) {
3188 b7bcbe95 bellard
            /* two-register transfer */
3189 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3190 b7bcbe95 bellard
            rd = (insn >> 12) & 0xf;
3191 b7bcbe95 bellard
            if (dp) {
3192 9ee6e8bb pbrook
                VFP_DREG_M(rm, insn);
3193 9ee6e8bb pbrook
            } else {
3194 9ee6e8bb pbrook
                rm = VFP_SREG_M(insn);
3195 9ee6e8bb pbrook
            }
3196 b7bcbe95 bellard
3197 18c9b560 balrog
            if (insn & ARM_CP_RW_BIT) {
3198 b7bcbe95 bellard
                /* vfp->arm */
3199 b7bcbe95 bellard
                if (dp) {
3200 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2);
3201 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3202 4373f3ce pbrook
                    store_reg(s, rd, tmp);
3203 4373f3ce pbrook
                    gen_mov_F0_vreg(0, rm * 2 + 1);
3204 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3205 4373f3ce pbrook
                    store_reg(s, rn, tmp);
3206 b7bcbe95 bellard
                } else {
3207 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm);
3208 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3209 4373f3ce pbrook
                    store_reg(s, rn, tmp);
3210 b7bcbe95 bellard
                    gen_mov_F0_vreg(0, rm + 1);
3211 4373f3ce pbrook
                    tmp = gen_vfp_mrs();
3212 4373f3ce pbrook
                    store_reg(s, rd, tmp);
3213 b7bcbe95 bellard
                }
3214 b7bcbe95 bellard
            } else {
3215 b7bcbe95 bellard
                /* arm->vfp */
3216 b7bcbe95 bellard
                if (dp) {
3217 4373f3ce pbrook
                    tmp = load_reg(s, rd);
3218 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3219 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2);
3220 4373f3ce pbrook
                    tmp = load_reg(s, rn);
3221 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3222 4373f3ce pbrook
                    gen_mov_vreg_F0(0, rm * 2 + 1);
3223 b7bcbe95 bellard
                } else {
3224 4373f3ce pbrook
                    tmp = load_reg(s, rn);
3225 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3226 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm);
3227 4373f3ce pbrook
                    tmp = load_reg(s, rd);
3228 4373f3ce pbrook
                    gen_vfp_msr(tmp);
3229 b7bcbe95 bellard
                    gen_mov_vreg_F0(0, rm + 1);
3230 b7bcbe95 bellard
                }
3231 b7bcbe95 bellard
            }
3232 b7bcbe95 bellard
        } else {
3233 b7bcbe95 bellard
            /* Load/store */
3234 b7bcbe95 bellard
            rn = (insn >> 16) & 0xf;
3235 b7bcbe95 bellard
            if (dp)
3236 9ee6e8bb pbrook
                VFP_DREG_D(rd, insn);
3237 b7bcbe95 bellard
            else
3238 9ee6e8bb pbrook
                rd = VFP_SREG_D(insn);
3239 9ee6e8bb pbrook
            if (s->thumb && rn == 15) {
3240 9ee6e8bb pbrook
                gen_op_movl_T1_im(s->pc & ~2);
3241 9ee6e8bb pbrook
            } else {
3242 9ee6e8bb pbrook
                gen_movl_T1_reg(s, rn);
3243 9ee6e8bb pbrook
            }
3244 b7bcbe95 bellard
            if ((insn & 0x01200000) == 0x01000000) {
3245 b7bcbe95 bellard
                /* Single load/store */
3246 b7bcbe95 bellard
                offset = (insn & 0xff) << 2;
3247 b7bcbe95 bellard
                if ((insn & (1 << 23)) == 0)
3248 b7bcbe95 bellard
                    offset = -offset;
3249 b7bcbe95 bellard
                gen_op_addl_T1_im(offset);
3250 b7bcbe95 bellard
                if (insn & (1 << 20)) {
3251 b5ff1b31 bellard
                    gen_vfp_ld(s, dp);
3252 b7bcbe95 bellard
                    gen_mov_vreg_F0(dp, rd);
3253 b7bcbe95 bellard
                } else {
3254 b7bcbe95 bellard
                    gen_mov_F0_vreg(dp, rd);
3255 b5ff1b31 bellard
                    gen_vfp_st(s, dp);
3256 b7bcbe95 bellard
                }
3257 b7bcbe95 bellard
            } else {
3258 b7bcbe95 bellard
                /* load/store multiple */
3259 b7bcbe95 bellard
                if (dp)
3260 b7bcbe95 bellard
                    n = (insn >> 1) & 0x7f;
3261 b7bcbe95 bellard
                else
3262 b7bcbe95 bellard
                    n = insn & 0xff;
3263 b7bcbe95 bellard
3264 b7bcbe95 bellard
                if (insn & (1 << 24)) /* pre-decrement */
3265 b7bcbe95 bellard
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3266 b7bcbe95 bellard
3267 b7bcbe95 bellard
                if (dp)
3268 b7bcbe95 bellard
                    offset = 8;
3269 b7bcbe95 bellard
                else
3270 b7bcbe95 bellard
                    offset = 4;
3271 b7bcbe95 bellard
                for (i = 0; i < n; i++) {
3272 18c9b560 balrog
                    if (insn & ARM_CP_RW_BIT) {
3273 b7bcbe95 bellard
                        /* load */
3274 b5ff1b31 bellard
                        gen_vfp_ld(s, dp);
3275 b7bcbe95 bellard
                        gen_mov_vreg_F0(dp, rd + i);
3276 b7bcbe95 bellard
                    } else {
3277 b7bcbe95 bellard
                        /* store */
3278 b7bcbe95 bellard
                        gen_mov_F0_vreg(dp, rd + i);
3279 b5ff1b31 bellard
                        gen_vfp_st(s, dp);
3280 b7bcbe95 bellard
                    }
3281 b7bcbe95 bellard
                    gen_op_addl_T1_im(offset);
3282 b7bcbe95 bellard
                }
3283 b7bcbe95 bellard
                if (insn & (1 << 21)) {
3284 b7bcbe95 bellard
                    /* writeback */
3285 b7bcbe95 bellard
                    if (insn & (1 << 24))
3286 b7bcbe95 bellard
                        offset = -offset * n;
3287 b7bcbe95 bellard
                    else if (dp && (insn & 1))
3288 b7bcbe95 bellard
                        offset = 4;
3289 b7bcbe95 bellard
                    else
3290 b7bcbe95 bellard
                        offset = 0;
3291 b7bcbe95 bellard
3292 b7bcbe95 bellard
                    if (offset != 0)
3293 b7bcbe95 bellard
                        gen_op_addl_T1_im(offset);
3294 b7bcbe95 bellard
                    gen_movl_reg_T1(s, rn);
3295 b7bcbe95 bellard
                }
3296 b7bcbe95 bellard
            }
3297 b7bcbe95 bellard
        }
3298 b7bcbe95 bellard
        break;
3299 b7bcbe95 bellard
    default:
3300 b7bcbe95 bellard
        /* Should never happen.  */
3301 b7bcbe95 bellard
        return 1;
3302 b7bcbe95 bellard
    }
3303 b7bcbe95 bellard
    return 0;
3304 b7bcbe95 bellard
}
3305 b7bcbe95 bellard
3306 6e256c93 bellard
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3307 c53be334 bellard
{
3308 6e256c93 bellard
    TranslationBlock *tb;
3309 6e256c93 bellard
3310 6e256c93 bellard
    tb = s->tb;
3311 6e256c93 bellard
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3312 57fec1fe bellard
        tcg_gen_goto_tb(n);
3313 8984bd2e pbrook
        gen_set_pc_im(dest);
3314 57fec1fe bellard
        tcg_gen_exit_tb((long)tb + n);
3315 6e256c93 bellard
    } else {
3316 8984bd2e pbrook
        gen_set_pc_im(dest);
3317 57fec1fe bellard
        tcg_gen_exit_tb(0);
3318 6e256c93 bellard
    }
3319 c53be334 bellard
}
3320 c53be334 bellard
3321 8aaca4c0 bellard
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3322 8aaca4c0 bellard
{
3323 551bd27f ths
    if (unlikely(s->singlestep_enabled)) {
3324 8aaca4c0 bellard
        /* An indirect jump so that we still trigger the debug exception.  */
3325 5899f386 bellard
        if (s->thumb)
3326 d9ba4830 pbrook
            dest |= 1;
3327 d9ba4830 pbrook
        gen_bx_im(s, dest);
3328 8aaca4c0 bellard
    } else {
3329 6e256c93 bellard
        gen_goto_tb(s, 0, dest);
3330 8aaca4c0 bellard
        s->is_jmp = DISAS_TB_JUMP;
3331 8aaca4c0 bellard
    }
3332 8aaca4c0 bellard
}
3333 8aaca4c0 bellard
3334 d9ba4830 pbrook
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3335 b5ff1b31 bellard
{
3336 ee097184 bellard
    if (x)
3337 d9ba4830 pbrook
        tcg_gen_sari_i32(t0, t0, 16);
3338 b5ff1b31 bellard
    else
3339 d9ba4830 pbrook
        gen_sxth(t0);
3340 ee097184 bellard
    if (y)
3341 d9ba4830 pbrook
        tcg_gen_sari_i32(t1, t1, 16);
3342 b5ff1b31 bellard
    else
3343 d9ba4830 pbrook
        gen_sxth(t1);
3344 d9ba4830 pbrook
    tcg_gen_mul_i32(t0, t0, t1);
3345 b5ff1b31 bellard
}
3346 b5ff1b31 bellard
3347 b5ff1b31 bellard
/* Return the mask of PSR bits set by a MSR instruction.  */
3348 9ee6e8bb pbrook
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3349 b5ff1b31 bellard
    uint32_t mask;
3350 b5ff1b31 bellard
3351 b5ff1b31 bellard
    mask = 0;
3352 b5ff1b31 bellard
    if (flags & (1 << 0))
3353 b5ff1b31 bellard
        mask |= 0xff;
3354 b5ff1b31 bellard
    if (flags & (1 << 1))
3355 b5ff1b31 bellard
        mask |= 0xff00;
3356 b5ff1b31 bellard
    if (flags & (1 << 2))
3357 b5ff1b31 bellard
        mask |= 0xff0000;
3358 b5ff1b31 bellard
    if (flags & (1 << 3))
3359 b5ff1b31 bellard
        mask |= 0xff000000;
3360 9ee6e8bb pbrook
3361 2ae23e75 pbrook
    /* Mask out undefined bits.  */
3362 9ee6e8bb pbrook
    mask &= ~CPSR_RESERVED;
3363 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_V6))
3364 e160c51c pbrook
        mask &= ~(CPSR_E | CPSR_GE);
3365 9ee6e8bb pbrook
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3366 e160c51c pbrook
        mask &= ~CPSR_IT;
3367 9ee6e8bb pbrook
    /* Mask out execution state bits.  */
3368 2ae23e75 pbrook
    if (!spsr)
3369 e160c51c pbrook
        mask &= ~CPSR_EXEC;
3370 b5ff1b31 bellard
    /* Mask out privileged bits.  */
3371 b5ff1b31 bellard
    if (IS_USER(s))
3372 9ee6e8bb pbrook
        mask &= CPSR_USER;
3373 b5ff1b31 bellard
    return mask;
3374 b5ff1b31 bellard
}
3375 b5ff1b31 bellard
3376 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3377 2fbac54b Filip Navara
static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3378 b5ff1b31 bellard
{
3379 d9ba4830 pbrook
    TCGv tmp;
3380 b5ff1b31 bellard
    if (spsr) {
3381 b5ff1b31 bellard
        /* ??? This is also undefined in system mode.  */
3382 b5ff1b31 bellard
        if (IS_USER(s))
3383 b5ff1b31 bellard
            return 1;
3384 d9ba4830 pbrook
3385 d9ba4830 pbrook
        tmp = load_cpu_field(spsr);
3386 d9ba4830 pbrook
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3387 2fbac54b Filip Navara
        tcg_gen_andi_i32(t0, t0, mask);
3388 2fbac54b Filip Navara
        tcg_gen_or_i32(tmp, tmp, t0);
3389 d9ba4830 pbrook
        store_cpu_field(tmp, spsr);
3390 b5ff1b31 bellard
    } else {
3391 2fbac54b Filip Navara
        gen_set_cpsr(t0, mask);
3392 b5ff1b31 bellard
    }
3393 2fbac54b Filip Navara
    dead_tmp(t0);
3394 b5ff1b31 bellard
    gen_lookup_tb(s);
3395 b5ff1b31 bellard
    return 0;
3396 b5ff1b31 bellard
}
3397 b5ff1b31 bellard
3398 2fbac54b Filip Navara
/* Returns nonzero if access to the PSR is not permitted.  */
3399 2fbac54b Filip Navara
static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3400 2fbac54b Filip Navara
{
3401 2fbac54b Filip Navara
    TCGv tmp;
3402 2fbac54b Filip Navara
    tmp = new_tmp();
3403 2fbac54b Filip Navara
    tcg_gen_movi_i32(tmp, val);
3404 2fbac54b Filip Navara
    return gen_set_psr(s, mask, spsr, tmp);
3405 2fbac54b Filip Navara
}
3406 2fbac54b Filip Navara
3407 e9bb4aa9 Juha Riihimรคki
/* Generate an old-style exception return. Marks pc as dead. */
3408 e9bb4aa9 Juha Riihimรคki
static void gen_exception_return(DisasContext *s, TCGv pc)
3409 b5ff1b31 bellard
{
3410 d9ba4830 pbrook
    TCGv tmp;
3411 e9bb4aa9 Juha Riihimรคki
    store_reg(s, 15, pc);
3412 d9ba4830 pbrook
    tmp = load_cpu_field(spsr);
3413 d9ba4830 pbrook
    gen_set_cpsr(tmp, 0xffffffff);
3414 d9ba4830 pbrook
    dead_tmp(tmp);
3415 b5ff1b31 bellard
    s->is_jmp = DISAS_UPDATE;
3416 b5ff1b31 bellard
}
3417 b5ff1b31 bellard
3418 b0109805 pbrook
/* Generate a v6 exception return.  Marks both values as dead.  */
3419 b0109805 pbrook
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3420 2c0262af bellard
{
3421 b0109805 pbrook
    gen_set_cpsr(cpsr, 0xffffffff);
3422 b0109805 pbrook
    dead_tmp(cpsr);
3423 b0109805 pbrook
    store_reg(s, 15, pc);
3424 9ee6e8bb pbrook
    s->is_jmp = DISAS_UPDATE;
3425 9ee6e8bb pbrook
}
3426 3b46e624 ths
3427 9ee6e8bb pbrook
static inline void
3428 9ee6e8bb pbrook
gen_set_condexec (DisasContext *s)
3429 9ee6e8bb pbrook
{
3430 9ee6e8bb pbrook
    if (s->condexec_mask) {
3431 8f01245e pbrook
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3432 8f01245e pbrook
        TCGv tmp = new_tmp();
3433 8f01245e pbrook
        tcg_gen_movi_i32(tmp, val);
3434 d9ba4830 pbrook
        store_cpu_field(tmp, condexec_bits);
3435 9ee6e8bb pbrook
    }
3436 9ee6e8bb pbrook
}
3437 3b46e624 ths
3438 9ee6e8bb pbrook
static void gen_nop_hint(DisasContext *s, int val)
3439 9ee6e8bb pbrook
{
3440 9ee6e8bb pbrook
    switch (val) {
3441 9ee6e8bb pbrook
    case 3: /* wfi */
3442 8984bd2e pbrook
        gen_set_pc_im(s->pc);
3443 9ee6e8bb pbrook
        s->is_jmp = DISAS_WFI;
3444 9ee6e8bb pbrook
        break;
3445 9ee6e8bb pbrook
    case 2: /* wfe */
3446 9ee6e8bb pbrook
    case 4: /* sev */
3447 9ee6e8bb pbrook
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3448 9ee6e8bb pbrook
    default: /* nop */
3449 9ee6e8bb pbrook
        break;
3450 9ee6e8bb pbrook
    }
3451 9ee6e8bb pbrook
}
3452 99c475ab bellard
3453 ad69471c pbrook
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3454 9ee6e8bb pbrook
3455 dd8fbd78 Filip Navara
static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3456 9ee6e8bb pbrook
{
3457 9ee6e8bb pbrook
    switch (size) {
3458 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3459 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3460 dd8fbd78 Filip Navara
    case 2: tcg_gen_add_i32(t0, t0, t1); break;
3461 9ee6e8bb pbrook
    default: return 1;
3462 9ee6e8bb pbrook
    }
3463 9ee6e8bb pbrook
    return 0;
3464 9ee6e8bb pbrook
}
3465 9ee6e8bb pbrook
3466 dd8fbd78 Filip Navara
static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3467 ad69471c pbrook
{
3468 ad69471c pbrook
    switch (size) {
3469 dd8fbd78 Filip Navara
    case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3470 dd8fbd78 Filip Navara
    case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3471 dd8fbd78 Filip Navara
    case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3472 ad69471c pbrook
    default: return;
3473 ad69471c pbrook
    }
3474 ad69471c pbrook
}
3475 ad69471c pbrook
3476 ad69471c pbrook
/* 32-bit pairwise ops end up the same as the elementwise versions.  */
3477 ad69471c pbrook
#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
3478 ad69471c pbrook
#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
3479 ad69471c pbrook
#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
3480 ad69471c pbrook
#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
3481 ad69471c pbrook
3482 ad69471c pbrook
/* FIXME: This is wrong.  They set the wrong overflow bit.  */
3483 ad69471c pbrook
#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3484 ad69471c pbrook
#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3485 ad69471c pbrook
#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3486 ad69471c pbrook
#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3487 ad69471c pbrook
3488 ad69471c pbrook
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3489 ad69471c pbrook
    switch ((size << 1) | u) { \
3490 ad69471c pbrook
    case 0: \
3491 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3492 ad69471c pbrook
        break; \
3493 ad69471c pbrook
    case 1: \
3494 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3495 ad69471c pbrook
        break; \
3496 ad69471c pbrook
    case 2: \
3497 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3498 ad69471c pbrook
        break; \
3499 ad69471c pbrook
    case 3: \
3500 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3501 ad69471c pbrook
        break; \
3502 ad69471c pbrook
    case 4: \
3503 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3504 ad69471c pbrook
        break; \
3505 ad69471c pbrook
    case 5: \
3506 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3507 ad69471c pbrook
        break; \
3508 ad69471c pbrook
    default: return 1; \
3509 ad69471c pbrook
    }} while (0)
3510 9ee6e8bb pbrook
3511 9ee6e8bb pbrook
#define GEN_NEON_INTEGER_OP(name) do { \
3512 9ee6e8bb pbrook
    switch ((size << 1) | u) { \
3513 ad69471c pbrook
    case 0: \
3514 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3515 ad69471c pbrook
        break; \
3516 ad69471c pbrook
    case 1: \
3517 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3518 ad69471c pbrook
        break; \
3519 ad69471c pbrook
    case 2: \
3520 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3521 ad69471c pbrook
        break; \
3522 ad69471c pbrook
    case 3: \
3523 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3524 ad69471c pbrook
        break; \
3525 ad69471c pbrook
    case 4: \
3526 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3527 ad69471c pbrook
        break; \
3528 ad69471c pbrook
    case 5: \
3529 dd8fbd78 Filip Navara
        gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3530 ad69471c pbrook
        break; \
3531 9ee6e8bb pbrook
    default: return 1; \
3532 9ee6e8bb pbrook
    }} while (0)
3533 9ee6e8bb pbrook
3534 dd8fbd78 Filip Navara
static TCGv neon_load_scratch(int scratch)
3535 9ee6e8bb pbrook
{
3536 dd8fbd78 Filip Navara
    TCGv tmp = new_tmp();
3537 dd8fbd78 Filip Navara
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3538 dd8fbd78 Filip Navara
    return tmp;
3539 9ee6e8bb pbrook
}
3540 9ee6e8bb pbrook
3541 dd8fbd78 Filip Navara
static void neon_store_scratch(int scratch, TCGv var)
3542 9ee6e8bb pbrook
{
3543 dd8fbd78 Filip Navara
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3544 dd8fbd78 Filip Navara
    dead_tmp(var);
3545 9ee6e8bb pbrook
}
3546 9ee6e8bb pbrook
3547 dd8fbd78 Filip Navara
static inline TCGv neon_get_scalar(int size, int reg)
3548 9ee6e8bb pbrook
{
3549 dd8fbd78 Filip Navara
    TCGv tmp;
3550 9ee6e8bb pbrook
    if (size == 1) {
3551 dd8fbd78 Filip Navara
        tmp = neon_load_reg(reg >> 1, reg & 1);
3552 9ee6e8bb pbrook
    } else {
3553 dd8fbd78 Filip Navara
        tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3554 dd8fbd78 Filip Navara
        if (reg & 1) {
3555 dd8fbd78 Filip Navara
            gen_neon_dup_low16(tmp);
3556 dd8fbd78 Filip Navara
        } else {
3557 dd8fbd78 Filip Navara
            gen_neon_dup_high16(tmp);
3558 dd8fbd78 Filip Navara
        }
3559 9ee6e8bb pbrook
    }
3560 dd8fbd78 Filip Navara
    return tmp;
3561 9ee6e8bb pbrook
}
3562 9ee6e8bb pbrook
3563 19457615 Filip Navara
static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3564 19457615 Filip Navara
{
3565 19457615 Filip Navara
    TCGv rd, rm, tmp;
3566 19457615 Filip Navara
3567 19457615 Filip Navara
    rd = new_tmp();
3568 19457615 Filip Navara
    rm = new_tmp();
3569 19457615 Filip Navara
    tmp = new_tmp();
3570 19457615 Filip Navara
3571 19457615 Filip Navara
    tcg_gen_andi_i32(rd, t0, 0xff);
3572 19457615 Filip Navara
    tcg_gen_shri_i32(tmp, t0, 8);
3573 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff00);
3574 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3575 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t1, 16);
3576 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3577 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3578 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t1, 8);
3579 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3580 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3581 19457615 Filip Navara
3582 19457615 Filip Navara
    tcg_gen_shri_i32(rm, t0, 8);
3583 19457615 Filip Navara
    tcg_gen_andi_i32(rm, rm, 0xff);
3584 19457615 Filip Navara
    tcg_gen_shri_i32(tmp, t0, 16);
3585 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff00);
3586 19457615 Filip Navara
    tcg_gen_or_i32(rm, rm, tmp);
3587 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t1, 8);
3588 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3589 19457615 Filip Navara
    tcg_gen_or_i32(rm, rm, tmp);
3590 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0xff000000);
3591 19457615 Filip Navara
    tcg_gen_or_i32(t1, rm, tmp);
3592 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3593 19457615 Filip Navara
3594 19457615 Filip Navara
    dead_tmp(tmp);
3595 19457615 Filip Navara
    dead_tmp(rm);
3596 19457615 Filip Navara
    dead_tmp(rd);
3597 19457615 Filip Navara
}
3598 19457615 Filip Navara
3599 19457615 Filip Navara
static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3600 19457615 Filip Navara
{
3601 19457615 Filip Navara
    TCGv rd, rm, tmp;
3602 19457615 Filip Navara
3603 19457615 Filip Navara
    rd = new_tmp();
3604 19457615 Filip Navara
    rm = new_tmp();
3605 19457615 Filip Navara
    tmp = new_tmp();
3606 19457615 Filip Navara
3607 19457615 Filip Navara
    tcg_gen_andi_i32(rd, t0, 0xff);
3608 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t1, 8);
3609 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff00);
3610 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3611 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t0, 16);
3612 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3613 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3614 19457615 Filip Navara
    tcg_gen_shli_i32(tmp, t1, 24);
3615 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3616 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3617 19457615 Filip Navara
3618 19457615 Filip Navara
    tcg_gen_andi_i32(rm, t1, 0xff000000);
3619 19457615 Filip Navara
    tcg_gen_shri_i32(tmp, t0, 8);
3620 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3621 19457615 Filip Navara
    tcg_gen_or_i32(rm, rm, tmp);
3622 19457615 Filip Navara
    tcg_gen_shri_i32(tmp, t1, 8);
3623 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff00);
3624 19457615 Filip Navara
    tcg_gen_or_i32(rm, rm, tmp);
3625 19457615 Filip Navara
    tcg_gen_shri_i32(tmp, t0, 16);
3626 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, tmp, 0xff);
3627 19457615 Filip Navara
    tcg_gen_or_i32(t1, rm, tmp);
3628 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3629 19457615 Filip Navara
3630 19457615 Filip Navara
    dead_tmp(tmp);
3631 19457615 Filip Navara
    dead_tmp(rm);
3632 19457615 Filip Navara
    dead_tmp(rd);
3633 19457615 Filip Navara
}
3634 19457615 Filip Navara
3635 19457615 Filip Navara
static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3636 19457615 Filip Navara
{
3637 19457615 Filip Navara
    TCGv tmp, tmp2;
3638 19457615 Filip Navara
3639 19457615 Filip Navara
    tmp = new_tmp();
3640 19457615 Filip Navara
    tmp2 = new_tmp();
3641 19457615 Filip Navara
3642 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xffff);
3643 19457615 Filip Navara
    tcg_gen_shli_i32(tmp2, t1, 16);
3644 19457615 Filip Navara
    tcg_gen_or_i32(tmp, tmp, tmp2);
3645 19457615 Filip Navara
    tcg_gen_andi_i32(t1, t1, 0xffff0000);
3646 19457615 Filip Navara
    tcg_gen_shri_i32(tmp2, t0, 16);
3647 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp2);
3648 19457615 Filip Navara
    tcg_gen_mov_i32(t0, tmp);
3649 19457615 Filip Navara
3650 19457615 Filip Navara
    dead_tmp(tmp2);
3651 19457615 Filip Navara
    dead_tmp(tmp);
3652 19457615 Filip Navara
}
3653 19457615 Filip Navara
3654 9ee6e8bb pbrook
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3655 9ee6e8bb pbrook
{
3656 9ee6e8bb pbrook
    int n;
3657 dd8fbd78 Filip Navara
    TCGv t0, t1;
3658 9ee6e8bb pbrook
3659 9ee6e8bb pbrook
    for (n = 0; n < q + 1; n += 2) {
3660 dd8fbd78 Filip Navara
        t0 = neon_load_reg(reg, n);
3661 dd8fbd78 Filip Navara
        t1 = neon_load_reg(reg, n + 1);
3662 9ee6e8bb pbrook
        switch (size) {
3663 dd8fbd78 Filip Navara
        case 0: gen_neon_unzip_u8(t0, t1); break;
3664 dd8fbd78 Filip Navara
        case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same.  */
3665 9ee6e8bb pbrook
        case 2: /* no-op */; break;
3666 9ee6e8bb pbrook
        default: abort();
3667 9ee6e8bb pbrook
        }
3668 dd8fbd78 Filip Navara
        neon_store_scratch(tmp + n, t0);
3669 dd8fbd78 Filip Navara
        neon_store_scratch(tmp + n + 1, t1);
3670 9ee6e8bb pbrook
    }
3671 9ee6e8bb pbrook
}
3672 9ee6e8bb pbrook
3673 19457615 Filip Navara
static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3674 19457615 Filip Navara
{
3675 19457615 Filip Navara
    TCGv rd, tmp;
3676 19457615 Filip Navara
3677 19457615 Filip Navara
    rd = new_tmp();
3678 19457615 Filip Navara
    tmp = new_tmp();
3679 19457615 Filip Navara
3680 19457615 Filip Navara
    tcg_gen_shli_i32(rd, t0, 8);
3681 19457615 Filip Navara
    tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3682 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3683 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3684 19457615 Filip Navara
3685 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 8);
3686 19457615 Filip Navara
    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3687 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3688 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3689 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3690 19457615 Filip Navara
3691 19457615 Filip Navara
    dead_tmp(tmp);
3692 19457615 Filip Navara
    dead_tmp(rd);
3693 19457615 Filip Navara
}
3694 19457615 Filip Navara
3695 19457615 Filip Navara
static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3696 19457615 Filip Navara
{
3697 19457615 Filip Navara
    TCGv rd, tmp;
3698 19457615 Filip Navara
3699 19457615 Filip Navara
    rd = new_tmp();
3700 19457615 Filip Navara
    tmp = new_tmp();
3701 19457615 Filip Navara
3702 19457615 Filip Navara
    tcg_gen_shli_i32(rd, t0, 16);
3703 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t1, 0xffff);
3704 19457615 Filip Navara
    tcg_gen_or_i32(rd, rd, tmp);
3705 19457615 Filip Navara
    tcg_gen_shri_i32(t1, t1, 16);
3706 19457615 Filip Navara
    tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3707 19457615 Filip Navara
    tcg_gen_or_i32(t1, t1, tmp);
3708 19457615 Filip Navara
    tcg_gen_mov_i32(t0, rd);
3709 19457615 Filip Navara
3710 19457615 Filip Navara
    dead_tmp(tmp);
3711 19457615 Filip Navara
    dead_tmp(rd);
3712 19457615 Filip Navara
}
3713 19457615 Filip Navara
3714 19457615 Filip Navara
3715 9ee6e8bb pbrook
static struct {
3716 9ee6e8bb pbrook
    int nregs;
3717 9ee6e8bb pbrook
    int interleave;
3718 9ee6e8bb pbrook
    int spacing;
3719 9ee6e8bb pbrook
} neon_ls_element_type[11] = {
3720 9ee6e8bb pbrook
    {4, 4, 1},
3721 9ee6e8bb pbrook
    {4, 4, 2},
3722 9ee6e8bb pbrook
    {4, 1, 1},
3723 9ee6e8bb pbrook
    {4, 2, 1},
3724 9ee6e8bb pbrook
    {3, 3, 1},
3725 9ee6e8bb pbrook
    {3, 3, 2},
3726 9ee6e8bb pbrook
    {3, 1, 1},
3727 9ee6e8bb pbrook
    {1, 1, 1},
3728 9ee6e8bb pbrook
    {2, 2, 1},
3729 9ee6e8bb pbrook
    {2, 2, 2},
3730 9ee6e8bb pbrook
    {2, 1, 1}
3731 9ee6e8bb pbrook
};
3732 9ee6e8bb pbrook
3733 9ee6e8bb pbrook
/* Translate a NEON load/store element instruction.  Return nonzero if the
3734 9ee6e8bb pbrook
   instruction is invalid.  */
3735 9ee6e8bb pbrook
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3736 9ee6e8bb pbrook
{
3737 9ee6e8bb pbrook
    int rd, rn, rm;
3738 9ee6e8bb pbrook
    int op;
3739 9ee6e8bb pbrook
    int nregs;
3740 9ee6e8bb pbrook
    int interleave;
3741 9ee6e8bb pbrook
    int stride;
3742 9ee6e8bb pbrook
    int size;
3743 9ee6e8bb pbrook
    int reg;
3744 9ee6e8bb pbrook
    int pass;
3745 9ee6e8bb pbrook
    int load;
3746 9ee6e8bb pbrook
    int shift;
3747 9ee6e8bb pbrook
    int n;
3748 1b2b1e54 Filip Navara
    TCGv addr;
3749 b0109805 pbrook
    TCGv tmp;
3750 8f8e3aa4 pbrook
    TCGv tmp2;
3751 9ee6e8bb pbrook
3752 9ee6e8bb pbrook
    if (!vfp_enabled(env))
3753 9ee6e8bb pbrook
      return 1;
3754 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
3755 9ee6e8bb pbrook
    rn = (insn >> 16) & 0xf;
3756 9ee6e8bb pbrook
    rm = insn & 0xf;
3757 9ee6e8bb pbrook
    load = (insn & (1 << 21)) != 0;
3758 1b2b1e54 Filip Navara
    addr = new_tmp();
3759 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
3760 9ee6e8bb pbrook
        /* Load store all elements.  */
3761 9ee6e8bb pbrook
        op = (insn >> 8) & 0xf;
3762 9ee6e8bb pbrook
        size = (insn >> 6) & 3;
3763 9ee6e8bb pbrook
        if (op > 10 || size == 3)
3764 9ee6e8bb pbrook
            return 1;
3765 9ee6e8bb pbrook
        nregs = neon_ls_element_type[op].nregs;
3766 9ee6e8bb pbrook
        interleave = neon_ls_element_type[op].interleave;
3767 1b2b1e54 Filip Navara
        tcg_gen_mov_i32(addr, cpu_R[rn]);
3768 9ee6e8bb pbrook
        stride = (1 << size) * interleave;
3769 9ee6e8bb pbrook
        for (reg = 0; reg < nregs; reg++) {
3770 9ee6e8bb pbrook
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3771 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, cpu_R[rn], (1 << size) * reg);
3772 9ee6e8bb pbrook
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3773 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, cpu_R[rn], 1 << size);
3774 9ee6e8bb pbrook
            }
3775 9ee6e8bb pbrook
            for (pass = 0; pass < 2; pass++) {
3776 9ee6e8bb pbrook
                if (size == 2) {
3777 9ee6e8bb pbrook
                    if (load) {
3778 1b2b1e54 Filip Navara
                        tmp = gen_ld32(addr, IS_USER(s));
3779 ad69471c pbrook
                        neon_store_reg(rd, pass, tmp);
3780 9ee6e8bb pbrook
                    } else {
3781 ad69471c pbrook
                        tmp = neon_load_reg(rd, pass);
3782 1b2b1e54 Filip Navara
                        gen_st32(tmp, addr, IS_USER(s));
3783 9ee6e8bb pbrook
                    }
3784 1b2b1e54 Filip Navara
                    tcg_gen_addi_i32(addr, addr, stride);
3785 9ee6e8bb pbrook
                } else if (size == 1) {
3786 9ee6e8bb pbrook
                    if (load) {
3787 1b2b1e54 Filip Navara
                        tmp = gen_ld16u(addr, IS_USER(s));
3788 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3789 1b2b1e54 Filip Navara
                        tmp2 = gen_ld16u(addr, IS_USER(s));
3790 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3791 8f8e3aa4 pbrook
                        gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3792 8f8e3aa4 pbrook
                        dead_tmp(tmp2);
3793 8f8e3aa4 pbrook
                        neon_store_reg(rd, pass, tmp);
3794 9ee6e8bb pbrook
                    } else {
3795 8f8e3aa4 pbrook
                        tmp = neon_load_reg(rd, pass);
3796 8f8e3aa4 pbrook
                        tmp2 = new_tmp();
3797 8f8e3aa4 pbrook
                        tcg_gen_shri_i32(tmp2, tmp, 16);
3798 1b2b1e54 Filip Navara
                        gen_st16(tmp, addr, IS_USER(s));
3799 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3800 1b2b1e54 Filip Navara
                        gen_st16(tmp2, addr, IS_USER(s));
3801 1b2b1e54 Filip Navara
                        tcg_gen_addi_i32(addr, addr, stride);
3802 9ee6e8bb pbrook
                    }
3803 9ee6e8bb pbrook
                } else /* size == 0 */ {
3804 9ee6e8bb pbrook
                    if (load) {
3805 a50f5b91 pbrook
                        TCGV_UNUSED(tmp2);
3806 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
3807 1b2b1e54 Filip Navara
                            tmp = gen_ld8u(addr, IS_USER(s));
3808 1b2b1e54 Filip Navara
                            tcg_gen_addi_i32(addr, addr, stride);
3809 9ee6e8bb pbrook
                            if (n == 0) {
3810 8f8e3aa4 pbrook
                                tmp2 = tmp;
3811 9ee6e8bb pbrook
                            } else {
3812 8f8e3aa4 pbrook
                                gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3813 8f8e3aa4 pbrook
                                dead_tmp(tmp);
3814 9ee6e8bb pbrook
                            }
3815 9ee6e8bb pbrook
                        }
3816 8f8e3aa4 pbrook
                        neon_store_reg(rd, pass, tmp2);
3817 9ee6e8bb pbrook
                    } else {
3818 8f8e3aa4 pbrook
                        tmp2 = neon_load_reg(rd, pass);
3819 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
3820 8f8e3aa4 pbrook
                            tmp = new_tmp();
3821 9ee6e8bb pbrook
                            if (n == 0) {
3822 8f8e3aa4 pbrook
                                tcg_gen_mov_i32(tmp, tmp2);
3823 9ee6e8bb pbrook
                            } else {
3824 8f8e3aa4 pbrook
                                tcg_gen_shri_i32(tmp, tmp2, n * 8);
3825 9ee6e8bb pbrook
                            }
3826 1b2b1e54 Filip Navara
                            gen_st8(tmp, addr, IS_USER(s));
3827 1b2b1e54 Filip Navara
                            tcg_gen_addi_i32(addr, addr, stride);
3828 9ee6e8bb pbrook
                        }
3829 8f8e3aa4 pbrook
                        dead_tmp(tmp2);
3830 9ee6e8bb pbrook
                    }
3831 9ee6e8bb pbrook
                }
3832 9ee6e8bb pbrook
            }
3833 9ee6e8bb pbrook
            rd += neon_ls_element_type[op].spacing;
3834 9ee6e8bb pbrook
        }
3835 9ee6e8bb pbrook
        stride = nregs * 8;
3836 9ee6e8bb pbrook
    } else {
3837 9ee6e8bb pbrook
        size = (insn >> 10) & 3;
3838 9ee6e8bb pbrook
        if (size == 3) {
3839 9ee6e8bb pbrook
            /* Load single element to all lanes.  */
3840 9ee6e8bb pbrook
            if (!load)
3841 9ee6e8bb pbrook
                return 1;
3842 9ee6e8bb pbrook
            size = (insn >> 6) & 3;
3843 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
3844 9ee6e8bb pbrook
            stride = (insn & (1 << 5)) ? 2 : 1;
3845 1b2b1e54 Filip Navara
            tcg_gen_mov_i32(addr, cpu_R[rn]);
3846 9ee6e8bb pbrook
            for (reg = 0; reg < nregs; reg++) {
3847 9ee6e8bb pbrook
                switch (size) {
3848 9ee6e8bb pbrook
                case 0:
3849 1b2b1e54 Filip Navara
                    tmp = gen_ld8u(addr, IS_USER(s));
3850 ad69471c pbrook
                    gen_neon_dup_u8(tmp, 0);
3851 9ee6e8bb pbrook
                    break;
3852 9ee6e8bb pbrook
                case 1:
3853 1b2b1e54 Filip Navara
                    tmp = gen_ld16u(addr, IS_USER(s));
3854 ad69471c pbrook
                    gen_neon_dup_low16(tmp);
3855 9ee6e8bb pbrook
                    break;
3856 9ee6e8bb pbrook
                case 2:
3857 1b2b1e54 Filip Navara
                    tmp = gen_ld32(addr, IS_USER(s));
3858 9ee6e8bb pbrook
                    break;
3859 9ee6e8bb pbrook
                case 3:
3860 9ee6e8bb pbrook
                    return 1;
3861 a50f5b91 pbrook
                default: /* Avoid compiler warnings.  */
3862 a50f5b91 pbrook
                    abort();
3863 99c475ab bellard
                }
3864 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, addr, 1 << size);
3865 ad69471c pbrook
                tmp2 = new_tmp();
3866 ad69471c pbrook
                tcg_gen_mov_i32(tmp2, tmp);
3867 ad69471c pbrook
                neon_store_reg(rd, 0, tmp2);
3868 3018f259 pbrook
                neon_store_reg(rd, 1, tmp);
3869 9ee6e8bb pbrook
                rd += stride;
3870 9ee6e8bb pbrook
            }
3871 9ee6e8bb pbrook
            stride = (1 << size) * nregs;
3872 9ee6e8bb pbrook
        } else {
3873 9ee6e8bb pbrook
            /* Single element.  */
3874 9ee6e8bb pbrook
            pass = (insn >> 7) & 1;
3875 9ee6e8bb pbrook
            switch (size) {
3876 9ee6e8bb pbrook
            case 0:
3877 9ee6e8bb pbrook
                shift = ((insn >> 5) & 3) * 8;
3878 9ee6e8bb pbrook
                stride = 1;
3879 9ee6e8bb pbrook
                break;
3880 9ee6e8bb pbrook
            case 1:
3881 9ee6e8bb pbrook
                shift = ((insn >> 6) & 1) * 16;
3882 9ee6e8bb pbrook
                stride = (insn & (1 << 5)) ? 2 : 1;
3883 9ee6e8bb pbrook
                break;
3884 9ee6e8bb pbrook
            case 2:
3885 9ee6e8bb pbrook
                shift = 0;
3886 9ee6e8bb pbrook
                stride = (insn & (1 << 6)) ? 2 : 1;
3887 9ee6e8bb pbrook
                break;
3888 9ee6e8bb pbrook
            default:
3889 9ee6e8bb pbrook
                abort();
3890 9ee6e8bb pbrook
            }
3891 9ee6e8bb pbrook
            nregs = ((insn >> 8) & 3) + 1;
3892 1b2b1e54 Filip Navara
            tcg_gen_mov_i32(addr, cpu_R[rn]);
3893 9ee6e8bb pbrook
            for (reg = 0; reg < nregs; reg++) {
3894 9ee6e8bb pbrook
                if (load) {
3895 9ee6e8bb pbrook
                    switch (size) {
3896 9ee6e8bb pbrook
                    case 0:
3897 1b2b1e54 Filip Navara
                        tmp = gen_ld8u(addr, IS_USER(s));
3898 9ee6e8bb pbrook
                        break;
3899 9ee6e8bb pbrook
                    case 1:
3900 1b2b1e54 Filip Navara
                        tmp = gen_ld16u(addr, IS_USER(s));
3901 9ee6e8bb pbrook
                        break;
3902 9ee6e8bb pbrook
                    case 2:
3903 1b2b1e54 Filip Navara
                        tmp = gen_ld32(addr, IS_USER(s));
3904 9ee6e8bb pbrook
                        break;
3905 a50f5b91 pbrook
                    default: /* Avoid compiler warnings.  */
3906 a50f5b91 pbrook
                        abort();
3907 9ee6e8bb pbrook
                    }
3908 9ee6e8bb pbrook
                    if (size != 2) {
3909 8f8e3aa4 pbrook
                        tmp2 = neon_load_reg(rd, pass);
3910 8f8e3aa4 pbrook
                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3911 8f8e3aa4 pbrook
                        dead_tmp(tmp2);
3912 9ee6e8bb pbrook
                    }
3913 8f8e3aa4 pbrook
                    neon_store_reg(rd, pass, tmp);
3914 9ee6e8bb pbrook
                } else { /* Store */
3915 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, pass);
3916 8f8e3aa4 pbrook
                    if (shift)
3917 8f8e3aa4 pbrook
                        tcg_gen_shri_i32(tmp, tmp, shift);
3918 9ee6e8bb pbrook
                    switch (size) {
3919 9ee6e8bb pbrook
                    case 0:
3920 1b2b1e54 Filip Navara
                        gen_st8(tmp, addr, IS_USER(s));
3921 9ee6e8bb pbrook
                        break;
3922 9ee6e8bb pbrook
                    case 1:
3923 1b2b1e54 Filip Navara
                        gen_st16(tmp, addr, IS_USER(s));
3924 9ee6e8bb pbrook
                        break;
3925 9ee6e8bb pbrook
                    case 2:
3926 1b2b1e54 Filip Navara
                        gen_st32(tmp, addr, IS_USER(s));
3927 9ee6e8bb pbrook
                        break;
3928 99c475ab bellard
                    }
3929 99c475ab bellard
                }
3930 9ee6e8bb pbrook
                rd += stride;
3931 1b2b1e54 Filip Navara
                tcg_gen_addi_i32(addr, addr, 1 << size);
3932 99c475ab bellard
            }
3933 9ee6e8bb pbrook
            stride = nregs * (1 << size);
3934 99c475ab bellard
        }
3935 9ee6e8bb pbrook
    }
3936 1b2b1e54 Filip Navara
    dead_tmp(addr);
3937 9ee6e8bb pbrook
    if (rm != 15) {
3938 b26eefb6 pbrook
        TCGv base;
3939 b26eefb6 pbrook
3940 b26eefb6 pbrook
        base = load_reg(s, rn);
3941 9ee6e8bb pbrook
        if (rm == 13) {
3942 b26eefb6 pbrook
            tcg_gen_addi_i32(base, base, stride);
3943 9ee6e8bb pbrook
        } else {
3944 b26eefb6 pbrook
            TCGv index;
3945 b26eefb6 pbrook
            index = load_reg(s, rm);
3946 b26eefb6 pbrook
            tcg_gen_add_i32(base, base, index);
3947 b26eefb6 pbrook
            dead_tmp(index);
3948 9ee6e8bb pbrook
        }
3949 b26eefb6 pbrook
        store_reg(s, rn, base);
3950 9ee6e8bb pbrook
    }
3951 9ee6e8bb pbrook
    return 0;
3952 9ee6e8bb pbrook
}
3953 3b46e624 ths
3954 8f8e3aa4 pbrook
/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
3955 8f8e3aa4 pbrook
static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3956 8f8e3aa4 pbrook
{
3957 8f8e3aa4 pbrook
    tcg_gen_and_i32(t, t, c);
3958 8f8e3aa4 pbrook
    tcg_gen_bic_i32(f, f, c);
3959 8f8e3aa4 pbrook
    tcg_gen_or_i32(dest, t, f);
3960 8f8e3aa4 pbrook
}
3961 8f8e3aa4 pbrook
3962 a7812ae4 pbrook
static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3963 ad69471c pbrook
{
3964 ad69471c pbrook
    switch (size) {
3965 ad69471c pbrook
    case 0: gen_helper_neon_narrow_u8(dest, src); break;
3966 ad69471c pbrook
    case 1: gen_helper_neon_narrow_u16(dest, src); break;
3967 ad69471c pbrook
    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3968 ad69471c pbrook
    default: abort();
3969 ad69471c pbrook
    }
3970 ad69471c pbrook
}
3971 ad69471c pbrook
3972 a7812ae4 pbrook
static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3973 ad69471c pbrook
{
3974 ad69471c pbrook
    switch (size) {
3975 ad69471c pbrook
    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3976 ad69471c pbrook
    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3977 ad69471c pbrook
    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3978 ad69471c pbrook
    default: abort();
3979 ad69471c pbrook
    }
3980 ad69471c pbrook
}
3981 ad69471c pbrook
3982 a7812ae4 pbrook
static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3983 ad69471c pbrook
{
3984 ad69471c pbrook
    switch (size) {
3985 ad69471c pbrook
    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3986 ad69471c pbrook
    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3987 ad69471c pbrook
    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3988 ad69471c pbrook
    default: abort();
3989 ad69471c pbrook
    }
3990 ad69471c pbrook
}
3991 ad69471c pbrook
3992 ad69471c pbrook
static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3993 ad69471c pbrook
                                         int q, int u)
3994 ad69471c pbrook
{
3995 ad69471c pbrook
    if (q) {
3996 ad69471c pbrook
        if (u) {
3997 ad69471c pbrook
            switch (size) {
3998 ad69471c pbrook
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3999 ad69471c pbrook
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4000 ad69471c pbrook
            default: abort();
4001 ad69471c pbrook
            }
4002 ad69471c pbrook
        } else {
4003 ad69471c pbrook
            switch (size) {
4004 ad69471c pbrook
            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4005 ad69471c pbrook
            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4006 ad69471c pbrook
            default: abort();
4007 ad69471c pbrook
            }
4008 ad69471c pbrook
        }
4009 ad69471c pbrook
    } else {
4010 ad69471c pbrook
        if (u) {
4011 ad69471c pbrook
            switch (size) {
4012 ad69471c pbrook
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4013 ad69471c pbrook
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4014 ad69471c pbrook
            default: abort();
4015 ad69471c pbrook
            }
4016 ad69471c pbrook
        } else {
4017 ad69471c pbrook
            switch (size) {
4018 ad69471c pbrook
            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4019 ad69471c pbrook
            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4020 ad69471c pbrook
            default: abort();
4021 ad69471c pbrook
            }
4022 ad69471c pbrook
        }
4023 ad69471c pbrook
    }
4024 ad69471c pbrook
}
4025 ad69471c pbrook
4026 a7812ae4 pbrook
static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4027 ad69471c pbrook
{
4028 ad69471c pbrook
    if (u) {
4029 ad69471c pbrook
        switch (size) {
4030 ad69471c pbrook
        case 0: gen_helper_neon_widen_u8(dest, src); break;
4031 ad69471c pbrook
        case 1: gen_helper_neon_widen_u16(dest, src); break;
4032 ad69471c pbrook
        case 2: tcg_gen_extu_i32_i64(dest, src); break;
4033 ad69471c pbrook
        default: abort();
4034 ad69471c pbrook
        }
4035 ad69471c pbrook
    } else {
4036 ad69471c pbrook
        switch (size) {
4037 ad69471c pbrook
        case 0: gen_helper_neon_widen_s8(dest, src); break;
4038 ad69471c pbrook
        case 1: gen_helper_neon_widen_s16(dest, src); break;
4039 ad69471c pbrook
        case 2: tcg_gen_ext_i32_i64(dest, src); break;
4040 ad69471c pbrook
        default: abort();
4041 ad69471c pbrook
        }
4042 ad69471c pbrook
    }
4043 ad69471c pbrook
    dead_tmp(src);
4044 ad69471c pbrook
}
4045 ad69471c pbrook
4046 ad69471c pbrook
static inline void gen_neon_addl(int size)
4047 ad69471c pbrook
{
4048 ad69471c pbrook
    switch (size) {
4049 ad69471c pbrook
    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4050 ad69471c pbrook
    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4051 ad69471c pbrook
    case 2: tcg_gen_add_i64(CPU_V001); break;
4052 ad69471c pbrook
    default: abort();
4053 ad69471c pbrook
    }
4054 ad69471c pbrook
}
4055 ad69471c pbrook
4056 ad69471c pbrook
static inline void gen_neon_subl(int size)
4057 ad69471c pbrook
{
4058 ad69471c pbrook
    switch (size) {
4059 ad69471c pbrook
    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4060 ad69471c pbrook
    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4061 ad69471c pbrook
    case 2: tcg_gen_sub_i64(CPU_V001); break;
4062 ad69471c pbrook
    default: abort();
4063 ad69471c pbrook
    }
4064 ad69471c pbrook
}
4065 ad69471c pbrook
4066 a7812ae4 pbrook
static inline void gen_neon_negl(TCGv_i64 var, int size)
4067 ad69471c pbrook
{
4068 ad69471c pbrook
    switch (size) {
4069 ad69471c pbrook
    case 0: gen_helper_neon_negl_u16(var, var); break;
4070 ad69471c pbrook
    case 1: gen_helper_neon_negl_u32(var, var); break;
4071 ad69471c pbrook
    case 2: gen_helper_neon_negl_u64(var, var); break;
4072 ad69471c pbrook
    default: abort();
4073 ad69471c pbrook
    }
4074 ad69471c pbrook
}
4075 ad69471c pbrook
4076 a7812ae4 pbrook
static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4077 ad69471c pbrook
{
4078 ad69471c pbrook
    switch (size) {
4079 ad69471c pbrook
    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4080 ad69471c pbrook
    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4081 ad69471c pbrook
    default: abort();
4082 ad69471c pbrook
    }
4083 ad69471c pbrook
}
4084 ad69471c pbrook
4085 a7812ae4 pbrook
static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4086 ad69471c pbrook
{
4087 a7812ae4 pbrook
    TCGv_i64 tmp;
4088 ad69471c pbrook
4089 ad69471c pbrook
    switch ((size << 1) | u) {
4090 ad69471c pbrook
    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4091 ad69471c pbrook
    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4092 ad69471c pbrook
    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4093 ad69471c pbrook
    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4094 ad69471c pbrook
    case 4:
4095 ad69471c pbrook
        tmp = gen_muls_i64_i32(a, b);
4096 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4097 ad69471c pbrook
        break;
4098 ad69471c pbrook
    case 5:
4099 ad69471c pbrook
        tmp = gen_mulu_i64_i32(a, b);
4100 ad69471c pbrook
        tcg_gen_mov_i64(dest, tmp);
4101 ad69471c pbrook
        break;
4102 ad69471c pbrook
    default: abort();
4103 ad69471c pbrook
    }
4104 ad69471c pbrook
}
4105 ad69471c pbrook
4106 9ee6e8bb pbrook
/* Translate a NEON data processing instruction.  Return nonzero if the
4107 9ee6e8bb pbrook
   instruction is invalid.
4108 ad69471c pbrook
   We process data in a mixture of 32-bit and 64-bit chunks.
4109 ad69471c pbrook
   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
4110 2c0262af bellard
4111 9ee6e8bb pbrook
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4112 9ee6e8bb pbrook
{
4113 9ee6e8bb pbrook
    int op;
4114 9ee6e8bb pbrook
    int q;
4115 9ee6e8bb pbrook
    int rd, rn, rm;
4116 9ee6e8bb pbrook
    int size;
4117 9ee6e8bb pbrook
    int shift;
4118 9ee6e8bb pbrook
    int pass;
4119 9ee6e8bb pbrook
    int count;
4120 9ee6e8bb pbrook
    int pairwise;
4121 9ee6e8bb pbrook
    int u;
4122 9ee6e8bb pbrook
    int n;
4123 9ee6e8bb pbrook
    uint32_t imm;
4124 8f8e3aa4 pbrook
    TCGv tmp;
4125 8f8e3aa4 pbrook
    TCGv tmp2;
4126 8f8e3aa4 pbrook
    TCGv tmp3;
4127 a7812ae4 pbrook
    TCGv_i64 tmp64;
4128 9ee6e8bb pbrook
4129 9ee6e8bb pbrook
    if (!vfp_enabled(env))
4130 9ee6e8bb pbrook
      return 1;
4131 9ee6e8bb pbrook
    q = (insn & (1 << 6)) != 0;
4132 9ee6e8bb pbrook
    u = (insn >> 24) & 1;
4133 9ee6e8bb pbrook
    VFP_DREG_D(rd, insn);
4134 9ee6e8bb pbrook
    VFP_DREG_N(rn, insn);
4135 9ee6e8bb pbrook
    VFP_DREG_M(rm, insn);
4136 9ee6e8bb pbrook
    size = (insn >> 20) & 3;
4137 9ee6e8bb pbrook
    if ((insn & (1 << 23)) == 0) {
4138 9ee6e8bb pbrook
        /* Three register same length.  */
4139 9ee6e8bb pbrook
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4140 ad69471c pbrook
        if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4141 ad69471c pbrook
                          || op == 10 || op  == 11 || op == 16)) {
4142 ad69471c pbrook
            /* 64-bit element instructions.  */
4143 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
4144 ad69471c pbrook
                neon_load_reg64(cpu_V0, rn + pass);
4145 ad69471c pbrook
                neon_load_reg64(cpu_V1, rm + pass);
4146 9ee6e8bb pbrook
                switch (op) {
4147 9ee6e8bb pbrook
                case 1: /* VQADD */
4148 9ee6e8bb pbrook
                    if (u) {
4149 ad69471c pbrook
                        gen_helper_neon_add_saturate_u64(CPU_V001);
4150 2c0262af bellard
                    } else {
4151 ad69471c pbrook
                        gen_helper_neon_add_saturate_s64(CPU_V001);
4152 2c0262af bellard
                    }
4153 9ee6e8bb pbrook
                    break;
4154 9ee6e8bb pbrook
                case 5: /* VQSUB */
4155 9ee6e8bb pbrook
                    if (u) {
4156 ad69471c pbrook
                        gen_helper_neon_sub_saturate_u64(CPU_V001);
4157 ad69471c pbrook
                    } else {
4158 ad69471c pbrook
                        gen_helper_neon_sub_saturate_s64(CPU_V001);
4159 ad69471c pbrook
                    }
4160 ad69471c pbrook
                    break;
4161 ad69471c pbrook
                case 8: /* VSHL */
4162 ad69471c pbrook
                    if (u) {
4163 ad69471c pbrook
                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4164 ad69471c pbrook
                    } else {
4165 ad69471c pbrook
                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4166 ad69471c pbrook
                    }
4167 ad69471c pbrook
                    break;
4168 ad69471c pbrook
                case 9: /* VQSHL */
4169 ad69471c pbrook
                    if (u) {
4170 ad69471c pbrook
                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4171 ad69471c pbrook
                                                 cpu_V0, cpu_V0);
4172 ad69471c pbrook
                    } else {
4173 ad69471c pbrook
                        gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4174 ad69471c pbrook
                                                 cpu_V1, cpu_V0);
4175 ad69471c pbrook
                    }
4176 ad69471c pbrook
                    break;
4177 ad69471c pbrook
                case 10: /* VRSHL */
4178 ad69471c pbrook
                    if (u) {
4179 ad69471c pbrook
                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4180 1e8d4eec bellard
                    } else {
4181 ad69471c pbrook
                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4182 ad69471c pbrook
                    }
4183 ad69471c pbrook
                    break;
4184 ad69471c pbrook
                case 11: /* VQRSHL */
4185 ad69471c pbrook
                    if (u) {
4186 ad69471c pbrook
                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4187 ad69471c pbrook
                                                  cpu_V1, cpu_V0);
4188 ad69471c pbrook
                    } else {
4189 ad69471c pbrook
                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4190 ad69471c pbrook
                                                  cpu_V1, cpu_V0);
4191 1e8d4eec bellard
                    }
4192 9ee6e8bb pbrook
                    break;
4193 9ee6e8bb pbrook
                case 16:
4194 9ee6e8bb pbrook
                    if (u) {
4195 ad69471c pbrook
                        tcg_gen_sub_i64(CPU_V001);
4196 9ee6e8bb pbrook
                    } else {
4197 ad69471c pbrook
                        tcg_gen_add_i64(CPU_V001);
4198 9ee6e8bb pbrook
                    }
4199 9ee6e8bb pbrook
                    break;
4200 9ee6e8bb pbrook
                default:
4201 9ee6e8bb pbrook
                    abort();
4202 2c0262af bellard
                }
4203 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd + pass);
4204 2c0262af bellard
            }
4205 9ee6e8bb pbrook
            return 0;
4206 2c0262af bellard
        }
4207 9ee6e8bb pbrook
        switch (op) {
4208 9ee6e8bb pbrook
        case 8: /* VSHL */
4209 9ee6e8bb pbrook
        case 9: /* VQSHL */
4210 9ee6e8bb pbrook
        case 10: /* VRSHL */
4211 ad69471c pbrook
        case 11: /* VQRSHL */
4212 9ee6e8bb pbrook
            {
4213 ad69471c pbrook
                int rtmp;
4214 ad69471c pbrook
                /* Shift instruction operands are reversed.  */
4215 ad69471c pbrook
                rtmp = rn;
4216 9ee6e8bb pbrook
                rn = rm;
4217 ad69471c pbrook
                rm = rtmp;
4218 9ee6e8bb pbrook
                pairwise = 0;
4219 9ee6e8bb pbrook
            }
4220 2c0262af bellard
            break;
4221 9ee6e8bb pbrook
        case 20: /* VPMAX */
4222 9ee6e8bb pbrook
        case 21: /* VPMIN */
4223 9ee6e8bb pbrook
        case 23: /* VPADD */
4224 9ee6e8bb pbrook
            pairwise = 1;
4225 2c0262af bellard
            break;
4226 9ee6e8bb pbrook
        case 26: /* VPADD (float) */
4227 9ee6e8bb pbrook
            pairwise = (u && size < 2);
4228 2c0262af bellard
            break;
4229 9ee6e8bb pbrook
        case 30: /* VPMIN/VPMAX (float) */
4230 9ee6e8bb pbrook
            pairwise = u;
4231 2c0262af bellard
            break;
4232 9ee6e8bb pbrook
        default:
4233 9ee6e8bb pbrook
            pairwise = 0;
4234 2c0262af bellard
            break;
4235 9ee6e8bb pbrook
        }
4236 dd8fbd78 Filip Navara
4237 9ee6e8bb pbrook
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
4238 9ee6e8bb pbrook
4239 9ee6e8bb pbrook
        if (pairwise) {
4240 9ee6e8bb pbrook
            /* Pairwise.  */
4241 9ee6e8bb pbrook
            if (q)
4242 9ee6e8bb pbrook
                n = (pass & 1) * 2;
4243 2c0262af bellard
            else
4244 9ee6e8bb pbrook
                n = 0;
4245 9ee6e8bb pbrook
            if (pass < q + 1) {
4246 dd8fbd78 Filip Navara
                tmp = neon_load_reg(rn, n);
4247 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rn, n + 1);
4248 9ee6e8bb pbrook
            } else {
4249 dd8fbd78 Filip Navara
                tmp = neon_load_reg(rm, n);
4250 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rm, n + 1);
4251 9ee6e8bb pbrook
            }
4252 9ee6e8bb pbrook
        } else {
4253 9ee6e8bb pbrook
            /* Elementwise.  */
4254 dd8fbd78 Filip Navara
            tmp = neon_load_reg(rn, pass);
4255 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rm, pass);
4256 9ee6e8bb pbrook
        }
4257 9ee6e8bb pbrook
        switch (op) {
4258 9ee6e8bb pbrook
        case 0: /* VHADD */
4259 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hadd);
4260 9ee6e8bb pbrook
            break;
4261 9ee6e8bb pbrook
        case 1: /* VQADD */
4262 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qadd);
4263 2c0262af bellard
            break;
4264 9ee6e8bb pbrook
        case 2: /* VRHADD */
4265 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(rhadd);
4266 2c0262af bellard
            break;
4267 9ee6e8bb pbrook
        case 3: /* Logic ops.  */
4268 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4269 9ee6e8bb pbrook
            case 0: /* VAND */
4270 dd8fbd78 Filip Navara
                tcg_gen_and_i32(tmp, tmp, tmp2);
4271 9ee6e8bb pbrook
                break;
4272 9ee6e8bb pbrook
            case 1: /* BIC */
4273 dd8fbd78 Filip Navara
                tcg_gen_bic_i32(tmp, tmp, tmp2);
4274 9ee6e8bb pbrook
                break;
4275 9ee6e8bb pbrook
            case 2: /* VORR */
4276 dd8fbd78 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
4277 9ee6e8bb pbrook
                break;
4278 9ee6e8bb pbrook
            case 3: /* VORN */
4279 dd8fbd78 Filip Navara
                tcg_gen_not_i32(tmp2, tmp2);
4280 dd8fbd78 Filip Navara
                tcg_gen_or_i32(tmp, tmp, tmp2);
4281 9ee6e8bb pbrook
                break;
4282 9ee6e8bb pbrook
            case 4: /* VEOR */
4283 dd8fbd78 Filip Navara
                tcg_gen_xor_i32(tmp, tmp, tmp2);
4284 9ee6e8bb pbrook
                break;
4285 9ee6e8bb pbrook
            case 5: /* VBSL */
4286 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4287 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4288 dd8fbd78 Filip Navara
                dead_tmp(tmp3);
4289 9ee6e8bb pbrook
                break;
4290 9ee6e8bb pbrook
            case 6: /* VBIT */
4291 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4292 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4293 dd8fbd78 Filip Navara
                dead_tmp(tmp3);
4294 9ee6e8bb pbrook
                break;
4295 9ee6e8bb pbrook
            case 7: /* VBIF */
4296 dd8fbd78 Filip Navara
                tmp3 = neon_load_reg(rd, pass);
4297 dd8fbd78 Filip Navara
                gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4298 dd8fbd78 Filip Navara
                dead_tmp(tmp3);
4299 9ee6e8bb pbrook
                break;
4300 2c0262af bellard
            }
4301 2c0262af bellard
            break;
4302 9ee6e8bb pbrook
        case 4: /* VHSUB */
4303 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(hsub);
4304 9ee6e8bb pbrook
            break;
4305 9ee6e8bb pbrook
        case 5: /* VQSUB */
4306 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qsub);
4307 2c0262af bellard
            break;
4308 9ee6e8bb pbrook
        case 6: /* VCGT */
4309 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cgt);
4310 9ee6e8bb pbrook
            break;
4311 9ee6e8bb pbrook
        case 7: /* VCGE */
4312 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(cge);
4313 9ee6e8bb pbrook
            break;
4314 9ee6e8bb pbrook
        case 8: /* VSHL */
4315 ad69471c pbrook
            GEN_NEON_INTEGER_OP(shl);
4316 2c0262af bellard
            break;
4317 9ee6e8bb pbrook
        case 9: /* VQSHL */
4318 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qshl);
4319 2c0262af bellard
            break;
4320 9ee6e8bb pbrook
        case 10: /* VRSHL */
4321 ad69471c pbrook
            GEN_NEON_INTEGER_OP(rshl);
4322 2c0262af bellard
            break;
4323 9ee6e8bb pbrook
        case 11: /* VQRSHL */
4324 ad69471c pbrook
            GEN_NEON_INTEGER_OP_ENV(qrshl);
4325 9ee6e8bb pbrook
            break;
4326 9ee6e8bb pbrook
        case 12: /* VMAX */
4327 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(max);
4328 9ee6e8bb pbrook
            break;
4329 9ee6e8bb pbrook
        case 13: /* VMIN */
4330 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(min);
4331 9ee6e8bb pbrook
            break;
4332 9ee6e8bb pbrook
        case 14: /* VABD */
4333 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4334 9ee6e8bb pbrook
            break;
4335 9ee6e8bb pbrook
        case 15: /* VABA */
4336 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(abd);
4337 dd8fbd78 Filip Navara
            dead_tmp(tmp2);
4338 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4339 dd8fbd78 Filip Navara
            gen_neon_add(size, tmp, tmp2);
4340 9ee6e8bb pbrook
            break;
4341 9ee6e8bb pbrook
        case 16:
4342 9ee6e8bb pbrook
            if (!u) { /* VADD */
4343 dd8fbd78 Filip Navara
                if (gen_neon_add(size, tmp, tmp2))
4344 9ee6e8bb pbrook
                    return 1;
4345 9ee6e8bb pbrook
            } else { /* VSUB */
4346 9ee6e8bb pbrook
                switch (size) {
4347 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4348 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4349 dd8fbd78 Filip Navara
                case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4350 9ee6e8bb pbrook
                default: return 1;
4351 9ee6e8bb pbrook
                }
4352 9ee6e8bb pbrook
            }
4353 9ee6e8bb pbrook
            break;
4354 9ee6e8bb pbrook
        case 17:
4355 9ee6e8bb pbrook
            if (!u) { /* VTST */
4356 9ee6e8bb pbrook
                switch (size) {
4357 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4358 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4359 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4360 9ee6e8bb pbrook
                default: return 1;
4361 9ee6e8bb pbrook
                }
4362 9ee6e8bb pbrook
            } else { /* VCEQ */
4363 9ee6e8bb pbrook
                switch (size) {
4364 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4365 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4366 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4367 9ee6e8bb pbrook
                default: return 1;
4368 9ee6e8bb pbrook
                }
4369 9ee6e8bb pbrook
            }
4370 9ee6e8bb pbrook
            break;
4371 9ee6e8bb pbrook
        case 18: /* Multiply.  */
4372 9ee6e8bb pbrook
            switch (size) {
4373 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4374 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4375 dd8fbd78 Filip Navara
            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4376 9ee6e8bb pbrook
            default: return 1;
4377 9ee6e8bb pbrook
            }
4378 dd8fbd78 Filip Navara
            dead_tmp(tmp2);
4379 dd8fbd78 Filip Navara
            tmp2 = neon_load_reg(rd, pass);
4380 9ee6e8bb pbrook
            if (u) { /* VMLS */
4381 dd8fbd78 Filip Navara
                gen_neon_rsb(size, tmp, tmp2);
4382 9ee6e8bb pbrook
            } else { /* VMLA */
4383 dd8fbd78 Filip Navara
                gen_neon_add(size, tmp, tmp2);
4384 9ee6e8bb pbrook
            }
4385 9ee6e8bb pbrook
            break;
4386 9ee6e8bb pbrook
        case 19: /* VMUL */
4387 9ee6e8bb pbrook
            if (u) { /* polynomial */
4388 dd8fbd78 Filip Navara
                gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4389 9ee6e8bb pbrook
            } else { /* Integer */
4390 9ee6e8bb pbrook
                switch (size) {
4391 dd8fbd78 Filip Navara
                case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4392 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4393 dd8fbd78 Filip Navara
                case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4394 9ee6e8bb pbrook
                default: return 1;
4395 9ee6e8bb pbrook
                }
4396 9ee6e8bb pbrook
            }
4397 9ee6e8bb pbrook
            break;
4398 9ee6e8bb pbrook
        case 20: /* VPMAX */
4399 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmax);
4400 9ee6e8bb pbrook
            break;
4401 9ee6e8bb pbrook
        case 21: /* VPMIN */
4402 9ee6e8bb pbrook
            GEN_NEON_INTEGER_OP(pmin);
4403 9ee6e8bb pbrook
            break;
4404 9ee6e8bb pbrook
        case 22: /* Hultiply high.  */
4405 9ee6e8bb pbrook
            if (!u) { /* VQDMULH */
4406 9ee6e8bb pbrook
                switch (size) {
4407 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4408 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4409 9ee6e8bb pbrook
                default: return 1;
4410 9ee6e8bb pbrook
                }
4411 9ee6e8bb pbrook
            } else { /* VQRDHMUL */
4412 9ee6e8bb pbrook
                switch (size) {
4413 dd8fbd78 Filip Navara
                case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4414 dd8fbd78 Filip Navara
                case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4415 9ee6e8bb pbrook
                default: return 1;
4416 9ee6e8bb pbrook
                }
4417 9ee6e8bb pbrook
            }
4418 9ee6e8bb pbrook
            break;
4419 9ee6e8bb pbrook
        case 23: /* VPADD */
4420 9ee6e8bb pbrook
            if (u)
4421 9ee6e8bb pbrook
                return 1;
4422 9ee6e8bb pbrook
            switch (size) {
4423 dd8fbd78 Filip Navara
            case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4424 dd8fbd78 Filip Navara
            case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4425 dd8fbd78 Filip Navara
            case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4426 9ee6e8bb pbrook
            default: return 1;
4427 9ee6e8bb pbrook
            }
4428 9ee6e8bb pbrook
            break;
4429 9ee6e8bb pbrook
        case 26: /* Floating point arithnetic.  */
4430 9ee6e8bb pbrook
            switch ((u << 2) | size) {
4431 9ee6e8bb pbrook
            case 0: /* VADD */
4432 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4433 9ee6e8bb pbrook
                break;
4434 9ee6e8bb pbrook
            case 2: /* VSUB */
4435 dd8fbd78 Filip Navara
                gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4436 9ee6e8bb pbrook
                break;
4437 9ee6e8bb pbrook
            case 4: /* VPADD */
4438 dd8fbd78 Filip Navara
                gen_helper_neon_add_f32(tmp, tmp, tmp2);
4439 9ee6e8bb pbrook
                break;
4440 9ee6e8bb pbrook
            case 6: /* VABD */
4441 dd8fbd78 Filip Navara
                gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4442 9ee6e8bb pbrook
                break;
4443 9ee6e8bb pbrook
            default:
4444 9ee6e8bb pbrook
                return 1;
4445 9ee6e8bb pbrook
            }
4446 9ee6e8bb pbrook
            break;
4447 9ee6e8bb pbrook
        case 27: /* Float multiply.  */
4448 dd8fbd78 Filip Navara
            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4449 9ee6e8bb pbrook
            if (!u) {
4450 dd8fbd78 Filip Navara
                dead_tmp(tmp2);
4451 dd8fbd78 Filip Navara
                tmp2 = neon_load_reg(rd, pass);
4452 9ee6e8bb pbrook
                if (size == 0) {
4453 dd8fbd78 Filip Navara
                    gen_helper_neon_add_f32(tmp, tmp, tmp2);
4454 9ee6e8bb pbrook
                } else {
4455 dd8fbd78 Filip Navara
                    gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4456 9ee6e8bb pbrook
                }
4457 9ee6e8bb pbrook
            }
4458 9ee6e8bb pbrook
            break;
4459 9ee6e8bb pbrook
        case 28: /* Float compare.  */
4460 9ee6e8bb pbrook
            if (!u) {
4461 dd8fbd78 Filip Navara
                gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4462 b5ff1b31 bellard
            } else {
4463 9ee6e8bb pbrook
                if (size == 0)
4464 dd8fbd78 Filip Navara
                    gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4465 9ee6e8bb pbrook
                else
4466 dd8fbd78 Filip Navara
                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4467 b5ff1b31 bellard
            }
4468 2c0262af bellard
            break;
4469 9ee6e8bb pbrook
        case 29: /* Float compare absolute.  */
4470 9ee6e8bb pbrook
            if (!u)
4471 9ee6e8bb pbrook
                return 1;
4472 9ee6e8bb pbrook
            if (size == 0)
4473 dd8fbd78 Filip Navara
                gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4474 9ee6e8bb pbrook
            else
4475 dd8fbd78 Filip Navara
                gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4476 2c0262af bellard
            break;
4477 9ee6e8bb pbrook
        case 30: /* Float min/max.  */
4478 9ee6e8bb pbrook
            if (size == 0)
4479 dd8fbd78 Filip Navara
                gen_helper_neon_max_f32(tmp, tmp, tmp2);
4480 9ee6e8bb pbrook
            else
4481 dd8fbd78 Filip Navara
                gen_helper_neon_min_f32(tmp, tmp, tmp2);
4482 9ee6e8bb pbrook
            break;
4483 9ee6e8bb pbrook
        case 31:
4484 9ee6e8bb pbrook
            if (size == 0)
4485 dd8fbd78 Filip Navara
                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4486 9ee6e8bb pbrook
            else
4487 dd8fbd78 Filip Navara
                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4488 2c0262af bellard
            break;
4489 9ee6e8bb pbrook
        default:
4490 9ee6e8bb pbrook
            abort();
4491 2c0262af bellard
        }
4492 dd8fbd78 Filip Navara
        dead_tmp(tmp2);
4493 dd8fbd78 Filip Navara
4494 9ee6e8bb pbrook
        /* Save the result.  For elementwise operations we can put it
4495 9ee6e8bb pbrook
           straight into the destination register.  For pairwise operations
4496 9ee6e8bb pbrook
           we have to be careful to avoid clobbering the source operands.  */
4497 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4498 dd8fbd78 Filip Navara
            neon_store_scratch(pass, tmp);
4499 9ee6e8bb pbrook
        } else {
4500 dd8fbd78 Filip Navara
            neon_store_reg(rd, pass, tmp);
4501 9ee6e8bb pbrook
        }
4502 9ee6e8bb pbrook
4503 9ee6e8bb pbrook
        } /* for pass */
4504 9ee6e8bb pbrook
        if (pairwise && rd == rm) {
4505 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4506 dd8fbd78 Filip Navara
                tmp = neon_load_scratch(pass);
4507 dd8fbd78 Filip Navara
                neon_store_reg(rd, pass, tmp);
4508 9ee6e8bb pbrook
            }
4509 9ee6e8bb pbrook
        }
4510 ad69471c pbrook
        /* End of 3 register same size operations.  */
4511 9ee6e8bb pbrook
    } else if (insn & (1 << 4)) {
4512 9ee6e8bb pbrook
        if ((insn & 0x00380080) != 0) {
4513 9ee6e8bb pbrook
            /* Two registers and shift.  */
4514 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4515 9ee6e8bb pbrook
            if (insn & (1 << 7)) {
4516 9ee6e8bb pbrook
                /* 64-bit shift.   */
4517 9ee6e8bb pbrook
                size = 3;
4518 9ee6e8bb pbrook
            } else {
4519 9ee6e8bb pbrook
                size = 2;
4520 9ee6e8bb pbrook
                while ((insn & (1 << (size + 19))) == 0)
4521 9ee6e8bb pbrook
                    size--;
4522 9ee6e8bb pbrook
            }
4523 9ee6e8bb pbrook
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4524 9ee6e8bb pbrook
            /* To avoid excessive dumplication of ops we implement shift
4525 9ee6e8bb pbrook
               by immediate using the variable shift operations.  */
4526 9ee6e8bb pbrook
            if (op < 8) {
4527 9ee6e8bb pbrook
                /* Shift by immediate:
4528 9ee6e8bb pbrook
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4529 9ee6e8bb pbrook
                /* Right shifts are encoded as N - shift, where N is the
4530 9ee6e8bb pbrook
                   element size in bits.  */
4531 9ee6e8bb pbrook
                if (op <= 4)
4532 9ee6e8bb pbrook
                    shift = shift - (1 << (size + 3));
4533 9ee6e8bb pbrook
                if (size == 3) {
4534 9ee6e8bb pbrook
                    count = q + 1;
4535 9ee6e8bb pbrook
                } else {
4536 9ee6e8bb pbrook
                    count = q ? 4: 2;
4537 9ee6e8bb pbrook
                }
4538 9ee6e8bb pbrook
                switch (size) {
4539 9ee6e8bb pbrook
                case 0:
4540 9ee6e8bb pbrook
                    imm = (uint8_t) shift;
4541 9ee6e8bb pbrook
                    imm |= imm << 8;
4542 9ee6e8bb pbrook
                    imm |= imm << 16;
4543 9ee6e8bb pbrook
                    break;
4544 9ee6e8bb pbrook
                case 1:
4545 9ee6e8bb pbrook
                    imm = (uint16_t) shift;
4546 9ee6e8bb pbrook
                    imm |= imm << 16;
4547 9ee6e8bb pbrook
                    break;
4548 9ee6e8bb pbrook
                case 2:
4549 9ee6e8bb pbrook
                case 3:
4550 9ee6e8bb pbrook
                    imm = shift;
4551 9ee6e8bb pbrook
                    break;
4552 9ee6e8bb pbrook
                default:
4553 9ee6e8bb pbrook
                    abort();
4554 9ee6e8bb pbrook
                }
4555 9ee6e8bb pbrook
4556 9ee6e8bb pbrook
                for (pass = 0; pass < count; pass++) {
4557 ad69471c pbrook
                    if (size == 3) {
4558 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
4559 ad69471c pbrook
                        tcg_gen_movi_i64(cpu_V1, imm);
4560 ad69471c pbrook
                        switch (op) {
4561 ad69471c pbrook
                        case 0:  /* VSHR */
4562 ad69471c pbrook
                        case 1:  /* VSRA */
4563 ad69471c pbrook
                            if (u)
4564 ad69471c pbrook
                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4565 9ee6e8bb pbrook
                            else
4566 ad69471c pbrook
                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4567 9ee6e8bb pbrook
                            break;
4568 ad69471c pbrook
                        case 2: /* VRSHR */
4569 ad69471c pbrook
                        case 3: /* VRSRA */
4570 ad69471c pbrook
                            if (u)
4571 ad69471c pbrook
                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4572 9ee6e8bb pbrook
                            else
4573 ad69471c pbrook
                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4574 9ee6e8bb pbrook
                            break;
4575 ad69471c pbrook
                        case 4: /* VSRI */
4576 ad69471c pbrook
                            if (!u)
4577 ad69471c pbrook
                                return 1;
4578 ad69471c pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4579 ad69471c pbrook
                            break;
4580 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
4581 ad69471c pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4582 ad69471c pbrook
                            break;
4583 ad69471c pbrook
                        case 6: /* VQSHL */
4584 ad69471c pbrook
                            if (u)
4585 ad69471c pbrook
                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4586 9ee6e8bb pbrook
                            else
4587 ad69471c pbrook
                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4588 ad69471c pbrook
                            break;
4589 ad69471c pbrook
                        case 7: /* VQSHLU */
4590 ad69471c pbrook
                            gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4591 9ee6e8bb pbrook
                            break;
4592 9ee6e8bb pbrook
                        }
4593 ad69471c pbrook
                        if (op == 1 || op == 3) {
4594 ad69471c pbrook
                            /* Accumulate.  */
4595 ad69471c pbrook
                            neon_load_reg64(cpu_V0, rd + pass);
4596 ad69471c pbrook
                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4597 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
4598 ad69471c pbrook
                            /* Insert */
4599 ad69471c pbrook
                            cpu_abort(env, "VS[LR]I.64 not implemented");
4600 ad69471c pbrook
                        }
4601 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
4602 ad69471c pbrook
                    } else { /* size < 3 */
4603 ad69471c pbrook
                        /* Operands in T0 and T1.  */
4604 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass);
4605 dd8fbd78 Filip Navara
                        tmp2 = new_tmp();
4606 dd8fbd78 Filip Navara
                        tcg_gen_movi_i32(tmp2, imm);
4607 ad69471c pbrook
                        switch (op) {
4608 ad69471c pbrook
                        case 0:  /* VSHR */
4609 ad69471c pbrook
                        case 1:  /* VSRA */
4610 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(shl);
4611 ad69471c pbrook
                            break;
4612 ad69471c pbrook
                        case 2: /* VRSHR */
4613 ad69471c pbrook
                        case 3: /* VRSRA */
4614 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(rshl);
4615 ad69471c pbrook
                            break;
4616 ad69471c pbrook
                        case 4: /* VSRI */
4617 ad69471c pbrook
                            if (!u)
4618 ad69471c pbrook
                                return 1;
4619 ad69471c pbrook
                            GEN_NEON_INTEGER_OP(shl);
4620 ad69471c pbrook
                            break;
4621 ad69471c pbrook
                        case 5: /* VSHL, VSLI */
4622 ad69471c pbrook
                            switch (size) {
4623 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4624 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4625 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4626 ad69471c pbrook
                            default: return 1;
4627 ad69471c pbrook
                            }
4628 ad69471c pbrook
                            break;
4629 ad69471c pbrook
                        case 6: /* VQSHL */
4630 ad69471c pbrook
                            GEN_NEON_INTEGER_OP_ENV(qshl);
4631 ad69471c pbrook
                            break;
4632 ad69471c pbrook
                        case 7: /* VQSHLU */
4633 ad69471c pbrook
                            switch (size) {
4634 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4635 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4636 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4637 ad69471c pbrook
                            default: return 1;
4638 ad69471c pbrook
                            }
4639 ad69471c pbrook
                            break;
4640 ad69471c pbrook
                        }
4641 dd8fbd78 Filip Navara
                        dead_tmp(tmp2);
4642 ad69471c pbrook
4643 ad69471c pbrook
                        if (op == 1 || op == 3) {
4644 ad69471c pbrook
                            /* Accumulate.  */
4645 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
4646 dd8fbd78 Filip Navara
                            gen_neon_add(size, tmp2, tmp);
4647 dd8fbd78 Filip Navara
                            dead_tmp(tmp2);
4648 ad69471c pbrook
                        } else if (op == 4 || (op == 5 && u)) {
4649 ad69471c pbrook
                            /* Insert */
4650 ad69471c pbrook
                            switch (size) {
4651 ad69471c pbrook
                            case 0:
4652 ad69471c pbrook
                                if (op == 4)
4653 ad69471c pbrook
                                    imm = 0xff >> -shift;
4654 ad69471c pbrook
                                else
4655 ad69471c pbrook
                                    imm = (uint8_t)(0xff << shift);
4656 ad69471c pbrook
                                imm |= imm << 8;
4657 ad69471c pbrook
                                imm |= imm << 16;
4658 ad69471c pbrook
                                break;
4659 ad69471c pbrook
                            case 1:
4660 ad69471c pbrook
                                if (op == 4)
4661 ad69471c pbrook
                                    imm = 0xffff >> -shift;
4662 ad69471c pbrook
                                else
4663 ad69471c pbrook
                                    imm = (uint16_t)(0xffff << shift);
4664 ad69471c pbrook
                                imm |= imm << 16;
4665 ad69471c pbrook
                                break;
4666 ad69471c pbrook
                            case 2:
4667 ad69471c pbrook
                                if (op == 4)
4668 ad69471c pbrook
                                    imm = 0xffffffffu >> -shift;
4669 ad69471c pbrook
                                else
4670 ad69471c pbrook
                                    imm = 0xffffffffu << shift;
4671 ad69471c pbrook
                                break;
4672 ad69471c pbrook
                            default:
4673 ad69471c pbrook
                                abort();
4674 ad69471c pbrook
                            }
4675 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
4676 dd8fbd78 Filip Navara
                            tcg_gen_andi_i32(tmp, tmp, imm);
4677 dd8fbd78 Filip Navara
                            tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4678 dd8fbd78 Filip Navara
                            tcg_gen_or_i32(tmp, tmp, tmp2);
4679 dd8fbd78 Filip Navara
                            dead_tmp(tmp2);
4680 ad69471c pbrook
                        }
4681 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
4682 9ee6e8bb pbrook
                    }
4683 9ee6e8bb pbrook
                } /* for pass */
4684 9ee6e8bb pbrook
            } else if (op < 10) {
4685 ad69471c pbrook
                /* Shift by immediate and narrow:
4686 9ee6e8bb pbrook
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4687 9ee6e8bb pbrook
                shift = shift - (1 << (size + 3));
4688 9ee6e8bb pbrook
                size++;
4689 9ee6e8bb pbrook
                switch (size) {
4690 9ee6e8bb pbrook
                case 1:
4691 ad69471c pbrook
                    imm = (uint16_t)shift;
4692 9ee6e8bb pbrook
                    imm |= imm << 16;
4693 ad69471c pbrook
                    tmp2 = tcg_const_i32(imm);
4694 a7812ae4 pbrook
                    TCGV_UNUSED_I64(tmp64);
4695 9ee6e8bb pbrook
                    break;
4696 9ee6e8bb pbrook
                case 2:
4697 ad69471c pbrook
                    imm = (uint32_t)shift;
4698 ad69471c pbrook
                    tmp2 = tcg_const_i32(imm);
4699 a7812ae4 pbrook
                    TCGV_UNUSED_I64(tmp64);
4700 4cc633c3 balrog
                    break;
4701 9ee6e8bb pbrook
                case 3:
4702 a7812ae4 pbrook
                    tmp64 = tcg_const_i64(shift);
4703 a7812ae4 pbrook
                    TCGV_UNUSED(tmp2);
4704 9ee6e8bb pbrook
                    break;
4705 9ee6e8bb pbrook
                default:
4706 9ee6e8bb pbrook
                    abort();
4707 9ee6e8bb pbrook
                }
4708 9ee6e8bb pbrook
4709 ad69471c pbrook
                for (pass = 0; pass < 2; pass++) {
4710 ad69471c pbrook
                    if (size == 3) {
4711 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
4712 ad69471c pbrook
                        if (q) {
4713 ad69471c pbrook
                          if (u)
4714 a7812ae4 pbrook
                            gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4715 ad69471c pbrook
                          else
4716 a7812ae4 pbrook
                            gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4717 ad69471c pbrook
                        } else {
4718 ad69471c pbrook
                          if (u)
4719 a7812ae4 pbrook
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4720 ad69471c pbrook
                          else
4721 a7812ae4 pbrook
                            gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4722 ad69471c pbrook
                        }
4723 2c0262af bellard
                    } else {
4724 ad69471c pbrook
                        tmp = neon_load_reg(rm + pass, 0);
4725 ad69471c pbrook
                        gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4726 36aa55dc pbrook
                        tmp3 = neon_load_reg(rm + pass, 1);
4727 36aa55dc pbrook
                        gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4728 36aa55dc pbrook
                        tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4729 ad69471c pbrook
                        dead_tmp(tmp);
4730 36aa55dc pbrook
                        dead_tmp(tmp3);
4731 9ee6e8bb pbrook
                    }
4732 ad69471c pbrook
                    tmp = new_tmp();
4733 ad69471c pbrook
                    if (op == 8 && !u) {
4734 ad69471c pbrook
                        gen_neon_narrow(size - 1, tmp, cpu_V0);
4735 9ee6e8bb pbrook
                    } else {
4736 ad69471c pbrook
                        if (op == 8)
4737 ad69471c pbrook
                            gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4738 9ee6e8bb pbrook
                        else
4739 ad69471c pbrook
                            gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4740 ad69471c pbrook
                    }
4741 ad69471c pbrook
                    if (pass == 0) {
4742 ad69471c pbrook
                        tmp2 = tmp;
4743 ad69471c pbrook
                    } else {
4744 ad69471c pbrook
                        neon_store_reg(rd, 0, tmp2);
4745 ad69471c pbrook
                        neon_store_reg(rd, 1, tmp);
4746 9ee6e8bb pbrook
                    }
4747 9ee6e8bb pbrook
                } /* for pass */
4748 9ee6e8bb pbrook
            } else if (op == 10) {
4749 9ee6e8bb pbrook
                /* VSHLL */
4750 ad69471c pbrook
                if (q || size == 3)
4751 9ee6e8bb pbrook
                    return 1;
4752 ad69471c pbrook
                tmp = neon_load_reg(rm, 0);
4753 ad69471c pbrook
                tmp2 = neon_load_reg(rm, 1);
4754 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
4755 ad69471c pbrook
                    if (pass == 1)
4756 ad69471c pbrook
                        tmp = tmp2;
4757 ad69471c pbrook
4758 ad69471c pbrook
                    gen_neon_widen(cpu_V0, tmp, size, u);
4759 9ee6e8bb pbrook
4760 9ee6e8bb pbrook
                    if (shift != 0) {
4761 9ee6e8bb pbrook
                        /* The shift is less than the width of the source
4762 ad69471c pbrook
                           type, so we can just shift the whole register.  */
4763 ad69471c pbrook
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4764 ad69471c pbrook
                        if (size < 2 || !u) {
4765 ad69471c pbrook
                            uint64_t imm64;
4766 ad69471c pbrook
                            if (size == 0) {
4767 ad69471c pbrook
                                imm = (0xffu >> (8 - shift));
4768 ad69471c pbrook
                                imm |= imm << 16;
4769 ad69471c pbrook
                            } else {
4770 ad69471c pbrook
                                imm = 0xffff >> (16 - shift);
4771 9ee6e8bb pbrook
                            }
4772 ad69471c pbrook
                            imm64 = imm | (((uint64_t)imm) << 32);
4773 ad69471c pbrook
                            tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4774 9ee6e8bb pbrook
                        }
4775 9ee6e8bb pbrook
                    }
4776 ad69471c pbrook
                    neon_store_reg64(cpu_V0, rd + pass);
4777 9ee6e8bb pbrook
                }
4778 9ee6e8bb pbrook
            } else if (op == 15 || op == 16) {
4779 9ee6e8bb pbrook
                /* VCVT fixed-point.  */
4780 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4781 4373f3ce pbrook
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4782 9ee6e8bb pbrook
                    if (op & 1) {
4783 9ee6e8bb pbrook
                        if (u)
4784 4373f3ce pbrook
                            gen_vfp_ulto(0, shift);
4785 9ee6e8bb pbrook
                        else
4786 4373f3ce pbrook
                            gen_vfp_slto(0, shift);
4787 9ee6e8bb pbrook
                    } else {
4788 9ee6e8bb pbrook
                        if (u)
4789 4373f3ce pbrook
                            gen_vfp_toul(0, shift);
4790 9ee6e8bb pbrook
                        else
4791 4373f3ce pbrook
                            gen_vfp_tosl(0, shift);
4792 2c0262af bellard
                    }
4793 4373f3ce pbrook
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4794 2c0262af bellard
                }
4795 2c0262af bellard
            } else {
4796 9ee6e8bb pbrook
                return 1;
4797 9ee6e8bb pbrook
            }
4798 9ee6e8bb pbrook
        } else { /* (insn & 0x00380080) == 0 */
4799 9ee6e8bb pbrook
            int invert;
4800 9ee6e8bb pbrook
4801 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4802 9ee6e8bb pbrook
            /* One register and immediate.  */
4803 9ee6e8bb pbrook
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4804 9ee6e8bb pbrook
            invert = (insn & (1 << 5)) != 0;
4805 9ee6e8bb pbrook
            switch (op) {
4806 9ee6e8bb pbrook
            case 0: case 1:
4807 9ee6e8bb pbrook
                /* no-op */
4808 9ee6e8bb pbrook
                break;
4809 9ee6e8bb pbrook
            case 2: case 3:
4810 9ee6e8bb pbrook
                imm <<= 8;
4811 9ee6e8bb pbrook
                break;
4812 9ee6e8bb pbrook
            case 4: case 5:
4813 9ee6e8bb pbrook
                imm <<= 16;
4814 9ee6e8bb pbrook
                break;
4815 9ee6e8bb pbrook
            case 6: case 7:
4816 9ee6e8bb pbrook
                imm <<= 24;
4817 9ee6e8bb pbrook
                break;
4818 9ee6e8bb pbrook
            case 8: case 9:
4819 9ee6e8bb pbrook
                imm |= imm << 16;
4820 9ee6e8bb pbrook
                break;
4821 9ee6e8bb pbrook
            case 10: case 11:
4822 9ee6e8bb pbrook
                imm = (imm << 8) | (imm << 24);
4823 9ee6e8bb pbrook
                break;
4824 9ee6e8bb pbrook
            case 12:
4825 9ee6e8bb pbrook
                imm = (imm < 8) | 0xff;
4826 9ee6e8bb pbrook
                break;
4827 9ee6e8bb pbrook
            case 13:
4828 9ee6e8bb pbrook
                imm = (imm << 16) | 0xffff;
4829 9ee6e8bb pbrook
                break;
4830 9ee6e8bb pbrook
            case 14:
4831 9ee6e8bb pbrook
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4832 9ee6e8bb pbrook
                if (invert)
4833 9ee6e8bb pbrook
                    imm = ~imm;
4834 9ee6e8bb pbrook
                break;
4835 9ee6e8bb pbrook
            case 15:
4836 9ee6e8bb pbrook
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4837 9ee6e8bb pbrook
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4838 9ee6e8bb pbrook
                break;
4839 9ee6e8bb pbrook
            }
4840 9ee6e8bb pbrook
            if (invert)
4841 9ee6e8bb pbrook
                imm = ~imm;
4842 9ee6e8bb pbrook
4843 9ee6e8bb pbrook
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4844 9ee6e8bb pbrook
                if (op & 1 && op < 12) {
4845 ad69471c pbrook
                    tmp = neon_load_reg(rd, pass);
4846 9ee6e8bb pbrook
                    if (invert) {
4847 9ee6e8bb pbrook
                        /* The immediate value has already been inverted, so
4848 9ee6e8bb pbrook
                           BIC becomes AND.  */
4849 ad69471c pbrook
                        tcg_gen_andi_i32(tmp, tmp, imm);
4850 9ee6e8bb pbrook
                    } else {
4851 ad69471c pbrook
                        tcg_gen_ori_i32(tmp, tmp, imm);
4852 9ee6e8bb pbrook
                    }
4853 9ee6e8bb pbrook
                } else {
4854 ad69471c pbrook
                    /* VMOV, VMVN.  */
4855 ad69471c pbrook
                    tmp = new_tmp();
4856 9ee6e8bb pbrook
                    if (op == 14 && invert) {
4857 ad69471c pbrook
                        uint32_t val;
4858 ad69471c pbrook
                        val = 0;
4859 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
4860 9ee6e8bb pbrook
                            if (imm & (1 << (n + (pass & 1) * 4)))
4861 ad69471c pbrook
                                val |= 0xff << (n * 8);
4862 9ee6e8bb pbrook
                        }
4863 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, val);
4864 ad69471c pbrook
                    } else {
4865 ad69471c pbrook
                        tcg_gen_movi_i32(tmp, imm);
4866 9ee6e8bb pbrook
                    }
4867 9ee6e8bb pbrook
                }
4868 ad69471c pbrook
                neon_store_reg(rd, pass, tmp);
4869 9ee6e8bb pbrook
            }
4870 9ee6e8bb pbrook
        }
4871 e4b3861d pbrook
    } else { /* (insn & 0x00800010 == 0x00800000) */
4872 9ee6e8bb pbrook
        if (size != 3) {
4873 9ee6e8bb pbrook
            op = (insn >> 8) & 0xf;
4874 9ee6e8bb pbrook
            if ((insn & (1 << 6)) == 0) {
4875 9ee6e8bb pbrook
                /* Three registers of different lengths.  */
4876 9ee6e8bb pbrook
                int src1_wide;
4877 9ee6e8bb pbrook
                int src2_wide;
4878 9ee6e8bb pbrook
                int prewiden;
4879 9ee6e8bb pbrook
                /* prewiden, src1_wide, src2_wide */
4880 9ee6e8bb pbrook
                static const int neon_3reg_wide[16][3] = {
4881 9ee6e8bb pbrook
                    {1, 0, 0}, /* VADDL */
4882 9ee6e8bb pbrook
                    {1, 1, 0}, /* VADDW */
4883 9ee6e8bb pbrook
                    {1, 0, 0}, /* VSUBL */
4884 9ee6e8bb pbrook
                    {1, 1, 0}, /* VSUBW */
4885 9ee6e8bb pbrook
                    {0, 1, 1}, /* VADDHN */
4886 9ee6e8bb pbrook
                    {0, 0, 0}, /* VABAL */
4887 9ee6e8bb pbrook
                    {0, 1, 1}, /* VSUBHN */
4888 9ee6e8bb pbrook
                    {0, 0, 0}, /* VABDL */
4889 9ee6e8bb pbrook
                    {0, 0, 0}, /* VMLAL */
4890 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMLAL */
4891 9ee6e8bb pbrook
                    {0, 0, 0}, /* VMLSL */
4892 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMLSL */
4893 9ee6e8bb pbrook
                    {0, 0, 0}, /* Integer VMULL */
4894 9ee6e8bb pbrook
                    {0, 0, 0}, /* VQDMULL */
4895 9ee6e8bb pbrook
                    {0, 0, 0}  /* Polynomial VMULL */
4896 9ee6e8bb pbrook
                };
4897 9ee6e8bb pbrook
4898 9ee6e8bb pbrook
                prewiden = neon_3reg_wide[op][0];
4899 9ee6e8bb pbrook
                src1_wide = neon_3reg_wide[op][1];
4900 9ee6e8bb pbrook
                src2_wide = neon_3reg_wide[op][2];
4901 9ee6e8bb pbrook
4902 ad69471c pbrook
                if (size == 0 && (op == 9 || op == 11 || op == 13))
4903 ad69471c pbrook
                    return 1;
4904 ad69471c pbrook
4905 9ee6e8bb pbrook
                /* Avoid overlapping operands.  Wide source operands are
4906 9ee6e8bb pbrook
                   always aligned so will never overlap with wide
4907 9ee6e8bb pbrook
                   destinations in problematic ways.  */
4908 8f8e3aa4 pbrook
                if (rd == rm && !src2_wide) {
4909 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
4910 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
4911 8f8e3aa4 pbrook
                } else if (rd == rn && !src1_wide) {
4912 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rn, 1);
4913 dd8fbd78 Filip Navara
                    neon_store_scratch(2, tmp);
4914 9ee6e8bb pbrook
                }
4915 a50f5b91 pbrook
                TCGV_UNUSED(tmp3);
4916 9ee6e8bb pbrook
                for (pass = 0; pass < 2; pass++) {
4917 ad69471c pbrook
                    if (src1_wide) {
4918 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + pass);
4919 a50f5b91 pbrook
                        TCGV_UNUSED(tmp);
4920 9ee6e8bb pbrook
                    } else {
4921 ad69471c pbrook
                        if (pass == 1 && rd == rn) {
4922 dd8fbd78 Filip Navara
                            tmp = neon_load_scratch(2);
4923 9ee6e8bb pbrook
                        } else {
4924 ad69471c pbrook
                            tmp = neon_load_reg(rn, pass);
4925 ad69471c pbrook
                        }
4926 ad69471c pbrook
                        if (prewiden) {
4927 ad69471c pbrook
                            gen_neon_widen(cpu_V0, tmp, size, u);
4928 9ee6e8bb pbrook
                        }
4929 9ee6e8bb pbrook
                    }
4930 ad69471c pbrook
                    if (src2_wide) {
4931 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + pass);
4932 a50f5b91 pbrook
                        TCGV_UNUSED(tmp2);
4933 9ee6e8bb pbrook
                    } else {
4934 ad69471c pbrook
                        if (pass == 1 && rd == rm) {
4935 dd8fbd78 Filip Navara
                            tmp2 = neon_load_scratch(2);
4936 9ee6e8bb pbrook
                        } else {
4937 ad69471c pbrook
                            tmp2 = neon_load_reg(rm, pass);
4938 ad69471c pbrook
                        }
4939 ad69471c pbrook
                        if (prewiden) {
4940 ad69471c pbrook
                            gen_neon_widen(cpu_V1, tmp2, size, u);
4941 9ee6e8bb pbrook
                        }
4942 9ee6e8bb pbrook
                    }
4943 9ee6e8bb pbrook
                    switch (op) {
4944 9ee6e8bb pbrook
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4945 ad69471c pbrook
                        gen_neon_addl(size);
4946 9ee6e8bb pbrook
                        break;
4947 9ee6e8bb pbrook
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4948 ad69471c pbrook
                        gen_neon_subl(size);
4949 9ee6e8bb pbrook
                        break;
4950 9ee6e8bb pbrook
                    case 5: case 7: /* VABAL, VABDL */
4951 9ee6e8bb pbrook
                        switch ((size << 1) | u) {
4952 ad69471c pbrook
                        case 0:
4953 ad69471c pbrook
                            gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4954 ad69471c pbrook
                            break;
4955 ad69471c pbrook
                        case 1:
4956 ad69471c pbrook
                            gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4957 ad69471c pbrook
                            break;
4958 ad69471c pbrook
                        case 2:
4959 ad69471c pbrook
                            gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4960 ad69471c pbrook
                            break;
4961 ad69471c pbrook
                        case 3:
4962 ad69471c pbrook
                            gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4963 ad69471c pbrook
                            break;
4964 ad69471c pbrook
                        case 4:
4965 ad69471c pbrook
                            gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4966 ad69471c pbrook
                            break;
4967 ad69471c pbrook
                        case 5:
4968 ad69471c pbrook
                            gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4969 ad69471c pbrook
                            break;
4970 9ee6e8bb pbrook
                        default: abort();
4971 9ee6e8bb pbrook
                        }
4972 ad69471c pbrook
                        dead_tmp(tmp2);
4973 ad69471c pbrook
                        dead_tmp(tmp);
4974 9ee6e8bb pbrook
                        break;
4975 9ee6e8bb pbrook
                    case 8: case 9: case 10: case 11: case 12: case 13:
4976 9ee6e8bb pbrook
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4977 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4978 dd8fbd78 Filip Navara
                        dead_tmp(tmp2);
4979 dd8fbd78 Filip Navara
                        dead_tmp(tmp);
4980 9ee6e8bb pbrook
                        break;
4981 9ee6e8bb pbrook
                    case 14: /* Polynomial VMULL */
4982 9ee6e8bb pbrook
                        cpu_abort(env, "Polynomial VMULL not implemented");
4983 9ee6e8bb pbrook
4984 9ee6e8bb pbrook
                    default: /* 15 is RESERVED.  */
4985 9ee6e8bb pbrook
                        return 1;
4986 9ee6e8bb pbrook
                    }
4987 9ee6e8bb pbrook
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4988 9ee6e8bb pbrook
                        /* Accumulate.  */
4989 9ee6e8bb pbrook
                        if (op == 10 || op == 11) {
4990 ad69471c pbrook
                            gen_neon_negl(cpu_V0, size);
4991 9ee6e8bb pbrook
                        }
4992 9ee6e8bb pbrook
4993 9ee6e8bb pbrook
                        if (op != 13) {
4994 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
4995 9ee6e8bb pbrook
                        }
4996 9ee6e8bb pbrook
4997 9ee6e8bb pbrook
                        switch (op) {
4998 9ee6e8bb pbrook
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4999 ad69471c pbrook
                            gen_neon_addl(size);
5000 9ee6e8bb pbrook
                            break;
5001 9ee6e8bb pbrook
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
5002 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5003 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5004 ad69471c pbrook
                            break;
5005 9ee6e8bb pbrook
                            /* Fall through.  */
5006 9ee6e8bb pbrook
                        case 13: /* VQDMULL */
5007 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5008 9ee6e8bb pbrook
                            break;
5009 9ee6e8bb pbrook
                        default:
5010 9ee6e8bb pbrook
                            abort();
5011 9ee6e8bb pbrook
                        }
5012 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5013 9ee6e8bb pbrook
                    } else if (op == 4 || op == 6) {
5014 9ee6e8bb pbrook
                        /* Narrowing operation.  */
5015 ad69471c pbrook
                        tmp = new_tmp();
5016 9ee6e8bb pbrook
                        if (u) {
5017 9ee6e8bb pbrook
                            switch (size) {
5018 ad69471c pbrook
                            case 0:
5019 ad69471c pbrook
                                gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5020 ad69471c pbrook
                                break;
5021 ad69471c pbrook
                            case 1:
5022 ad69471c pbrook
                                gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5023 ad69471c pbrook
                                break;
5024 ad69471c pbrook
                            case 2:
5025 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5026 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5027 ad69471c pbrook
                                break;
5028 9ee6e8bb pbrook
                            default: abort();
5029 9ee6e8bb pbrook
                            }
5030 9ee6e8bb pbrook
                        } else {
5031 9ee6e8bb pbrook
                            switch (size) {
5032 ad69471c pbrook
                            case 0:
5033 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5034 ad69471c pbrook
                                break;
5035 ad69471c pbrook
                            case 1:
5036 ad69471c pbrook
                                gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5037 ad69471c pbrook
                                break;
5038 ad69471c pbrook
                            case 2:
5039 ad69471c pbrook
                                tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5040 ad69471c pbrook
                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5041 ad69471c pbrook
                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5042 ad69471c pbrook
                                break;
5043 9ee6e8bb pbrook
                            default: abort();
5044 9ee6e8bb pbrook
                            }
5045 9ee6e8bb pbrook
                        }
5046 ad69471c pbrook
                        if (pass == 0) {
5047 ad69471c pbrook
                            tmp3 = tmp;
5048 ad69471c pbrook
                        } else {
5049 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp3);
5050 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5051 ad69471c pbrook
                        }
5052 9ee6e8bb pbrook
                    } else {
5053 9ee6e8bb pbrook
                        /* Write back the result.  */
5054 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5055 9ee6e8bb pbrook
                    }
5056 9ee6e8bb pbrook
                }
5057 9ee6e8bb pbrook
            } else {
5058 9ee6e8bb pbrook
                /* Two registers and a scalar.  */
5059 9ee6e8bb pbrook
                switch (op) {
5060 9ee6e8bb pbrook
                case 0: /* Integer VMLA scalar */
5061 9ee6e8bb pbrook
                case 1: /* Float VMLA scalar */
5062 9ee6e8bb pbrook
                case 4: /* Integer VMLS scalar */
5063 9ee6e8bb pbrook
                case 5: /* Floating point VMLS scalar */
5064 9ee6e8bb pbrook
                case 8: /* Integer VMUL scalar */
5065 9ee6e8bb pbrook
                case 9: /* Floating point VMUL scalar */
5066 9ee6e8bb pbrook
                case 12: /* VQDMULH scalar */
5067 9ee6e8bb pbrook
                case 13: /* VQRDMULH scalar */
5068 dd8fbd78 Filip Navara
                    tmp = neon_get_scalar(size, rm);
5069 dd8fbd78 Filip Navara
                    neon_store_scratch(0, tmp);
5070 9ee6e8bb pbrook
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
5071 dd8fbd78 Filip Navara
                        tmp = neon_load_scratch(0);
5072 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rn, pass);
5073 9ee6e8bb pbrook
                        if (op == 12) {
5074 9ee6e8bb pbrook
                            if (size == 1) {
5075 dd8fbd78 Filip Navara
                                gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5076 9ee6e8bb pbrook
                            } else {
5077 dd8fbd78 Filip Navara
                                gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5078 9ee6e8bb pbrook
                            }
5079 9ee6e8bb pbrook
                        } else if (op == 13) {
5080 9ee6e8bb pbrook
                            if (size == 1) {
5081 dd8fbd78 Filip Navara
                                gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5082 9ee6e8bb pbrook
                            } else {
5083 dd8fbd78 Filip Navara
                                gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5084 9ee6e8bb pbrook
                            }
5085 9ee6e8bb pbrook
                        } else if (op & 1) {
5086 dd8fbd78 Filip Navara
                            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5087 9ee6e8bb pbrook
                        } else {
5088 9ee6e8bb pbrook
                            switch (size) {
5089 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5090 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5091 dd8fbd78 Filip Navara
                            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5092 9ee6e8bb pbrook
                            default: return 1;
5093 9ee6e8bb pbrook
                            }
5094 9ee6e8bb pbrook
                        }
5095 dd8fbd78 Filip Navara
                        dead_tmp(tmp2);
5096 9ee6e8bb pbrook
                        if (op < 8) {
5097 9ee6e8bb pbrook
                            /* Accumulate.  */
5098 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5099 9ee6e8bb pbrook
                            switch (op) {
5100 9ee6e8bb pbrook
                            case 0:
5101 dd8fbd78 Filip Navara
                                gen_neon_add(size, tmp, tmp2);
5102 9ee6e8bb pbrook
                                break;
5103 9ee6e8bb pbrook
                            case 1:
5104 dd8fbd78 Filip Navara
                                gen_helper_neon_add_f32(tmp, tmp, tmp2);
5105 9ee6e8bb pbrook
                                break;
5106 9ee6e8bb pbrook
                            case 4:
5107 dd8fbd78 Filip Navara
                                gen_neon_rsb(size, tmp, tmp2);
5108 9ee6e8bb pbrook
                                break;
5109 9ee6e8bb pbrook
                            case 5:
5110 dd8fbd78 Filip Navara
                                gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5111 9ee6e8bb pbrook
                                break;
5112 9ee6e8bb pbrook
                            default:
5113 9ee6e8bb pbrook
                                abort();
5114 9ee6e8bb pbrook
                            }
5115 dd8fbd78 Filip Navara
                            dead_tmp(tmp2);
5116 9ee6e8bb pbrook
                        }
5117 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass, tmp);
5118 9ee6e8bb pbrook
                    }
5119 9ee6e8bb pbrook
                    break;
5120 9ee6e8bb pbrook
                case 2: /* VMLAL sclar */
5121 9ee6e8bb pbrook
                case 3: /* VQDMLAL scalar */
5122 9ee6e8bb pbrook
                case 6: /* VMLSL scalar */
5123 9ee6e8bb pbrook
                case 7: /* VQDMLSL scalar */
5124 9ee6e8bb pbrook
                case 10: /* VMULL scalar */
5125 9ee6e8bb pbrook
                case 11: /* VQDMULL scalar */
5126 ad69471c pbrook
                    if (size == 0 && (op == 3 || op == 7 || op == 11))
5127 ad69471c pbrook
                        return 1;
5128 ad69471c pbrook
5129 dd8fbd78 Filip Navara
                    tmp2 = neon_get_scalar(size, rm);
5130 dd8fbd78 Filip Navara
                    tmp3 = neon_load_reg(rn, 1);
5131 ad69471c pbrook
5132 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5133 ad69471c pbrook
                        if (pass == 0) {
5134 ad69471c pbrook
                            tmp = neon_load_reg(rn, 0);
5135 9ee6e8bb pbrook
                        } else {
5136 dd8fbd78 Filip Navara
                            tmp = tmp3;
5137 9ee6e8bb pbrook
                        }
5138 ad69471c pbrook
                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5139 dd8fbd78 Filip Navara
                        dead_tmp(tmp);
5140 9ee6e8bb pbrook
                        if (op == 6 || op == 7) {
5141 ad69471c pbrook
                            gen_neon_negl(cpu_V0, size);
5142 ad69471c pbrook
                        }
5143 ad69471c pbrook
                        if (op != 11) {
5144 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5145 9ee6e8bb pbrook
                        }
5146 9ee6e8bb pbrook
                        switch (op) {
5147 9ee6e8bb pbrook
                        case 2: case 6:
5148 ad69471c pbrook
                            gen_neon_addl(size);
5149 9ee6e8bb pbrook
                            break;
5150 9ee6e8bb pbrook
                        case 3: case 7:
5151 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5152 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5153 9ee6e8bb pbrook
                            break;
5154 9ee6e8bb pbrook
                        case 10:
5155 9ee6e8bb pbrook
                            /* no-op */
5156 9ee6e8bb pbrook
                            break;
5157 9ee6e8bb pbrook
                        case 11:
5158 ad69471c pbrook
                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5159 9ee6e8bb pbrook
                            break;
5160 9ee6e8bb pbrook
                        default:
5161 9ee6e8bb pbrook
                            abort();
5162 9ee6e8bb pbrook
                        }
5163 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5164 9ee6e8bb pbrook
                    }
5165 dd8fbd78 Filip Navara
5166 dd8fbd78 Filip Navara
                    dead_tmp(tmp2);
5167 dd8fbd78 Filip Navara
5168 9ee6e8bb pbrook
                    break;
5169 9ee6e8bb pbrook
                default: /* 14 and 15 are RESERVED */
5170 9ee6e8bb pbrook
                    return 1;
5171 9ee6e8bb pbrook
                }
5172 9ee6e8bb pbrook
            }
5173 9ee6e8bb pbrook
        } else { /* size == 3 */
5174 9ee6e8bb pbrook
            if (!u) {
5175 9ee6e8bb pbrook
                /* Extract.  */
5176 9ee6e8bb pbrook
                imm = (insn >> 8) & 0xf;
5177 ad69471c pbrook
                count = q + 1;
5178 ad69471c pbrook
5179 ad69471c pbrook
                if (imm > 7 && !q)
5180 ad69471c pbrook
                    return 1;
5181 ad69471c pbrook
5182 ad69471c pbrook
                if (imm == 0) {
5183 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5184 ad69471c pbrook
                    if (q) {
5185 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rn + 1);
5186 9ee6e8bb pbrook
                    }
5187 ad69471c pbrook
                } else if (imm == 8) {
5188 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn + 1);
5189 ad69471c pbrook
                    if (q) {
5190 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5191 9ee6e8bb pbrook
                    }
5192 ad69471c pbrook
                } else if (q) {
5193 a7812ae4 pbrook
                    tmp64 = tcg_temp_new_i64();
5194 ad69471c pbrook
                    if (imm < 8) {
5195 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn);
5196 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rn + 1);
5197 ad69471c pbrook
                    } else {
5198 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rn + 1);
5199 a7812ae4 pbrook
                        neon_load_reg64(tmp64, rm);
5200 ad69471c pbrook
                    }
5201 ad69471c pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5202 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5203 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5204 ad69471c pbrook
                    if (imm < 8) {
5205 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm);
5206 9ee6e8bb pbrook
                    } else {
5207 ad69471c pbrook
                        neon_load_reg64(cpu_V1, rm + 1);
5208 ad69471c pbrook
                        imm -= 8;
5209 9ee6e8bb pbrook
                    }
5210 ad69471c pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5211 a7812ae4 pbrook
                    tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5212 a7812ae4 pbrook
                    tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5213 ad69471c pbrook
                } else {
5214 a7812ae4 pbrook
                    /* BUGFIX */
5215 ad69471c pbrook
                    neon_load_reg64(cpu_V0, rn);
5216 a7812ae4 pbrook
                    tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5217 ad69471c pbrook
                    neon_load_reg64(cpu_V1, rm);
5218 a7812ae4 pbrook
                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5219 ad69471c pbrook
                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5220 ad69471c pbrook
                }
5221 ad69471c pbrook
                neon_store_reg64(cpu_V0, rd);
5222 ad69471c pbrook
                if (q) {
5223 ad69471c pbrook
                    neon_store_reg64(cpu_V1, rd + 1);
5224 9ee6e8bb pbrook
                }
5225 9ee6e8bb pbrook
            } else if ((insn & (1 << 11)) == 0) {
5226 9ee6e8bb pbrook
                /* Two register misc.  */
5227 9ee6e8bb pbrook
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5228 9ee6e8bb pbrook
                size = (insn >> 18) & 3;
5229 9ee6e8bb pbrook
                switch (op) {
5230 9ee6e8bb pbrook
                case 0: /* VREV64 */
5231 9ee6e8bb pbrook
                    if (size == 3)
5232 9ee6e8bb pbrook
                        return 1;
5233 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
5234 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rm, pass * 2);
5235 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rm, pass * 2 + 1);
5236 9ee6e8bb pbrook
                        switch (size) {
5237 dd8fbd78 Filip Navara
                        case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5238 dd8fbd78 Filip Navara
                        case 1: gen_swap_half(tmp); break;
5239 9ee6e8bb pbrook
                        case 2: /* no-op */ break;
5240 9ee6e8bb pbrook
                        default: abort();
5241 9ee6e8bb pbrook
                        }
5242 dd8fbd78 Filip Navara
                        neon_store_reg(rd, pass * 2 + 1, tmp);
5243 9ee6e8bb pbrook
                        if (size == 2) {
5244 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5245 9ee6e8bb pbrook
                        } else {
5246 9ee6e8bb pbrook
                            switch (size) {
5247 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5248 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp2); break;
5249 9ee6e8bb pbrook
                            default: abort();
5250 9ee6e8bb pbrook
                            }
5251 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass * 2, tmp2);
5252 9ee6e8bb pbrook
                        }
5253 9ee6e8bb pbrook
                    }
5254 9ee6e8bb pbrook
                    break;
5255 9ee6e8bb pbrook
                case 4: case 5: /* VPADDL */
5256 9ee6e8bb pbrook
                case 12: case 13: /* VPADAL */
5257 9ee6e8bb pbrook
                    if (size == 3)
5258 9ee6e8bb pbrook
                        return 1;
5259 ad69471c pbrook
                    for (pass = 0; pass < q + 1; pass++) {
5260 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2);
5261 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, op & 1);
5262 ad69471c pbrook
                        tmp = neon_load_reg(rm, pass * 2 + 1);
5263 ad69471c pbrook
                        gen_neon_widen(cpu_V1, tmp, size, op & 1);
5264 ad69471c pbrook
                        switch (size) {
5265 ad69471c pbrook
                        case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5266 ad69471c pbrook
                        case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5267 ad69471c pbrook
                        case 2: tcg_gen_add_i64(CPU_V001); break;
5268 ad69471c pbrook
                        default: abort();
5269 ad69471c pbrook
                        }
5270 9ee6e8bb pbrook
                        if (op >= 12) {
5271 9ee6e8bb pbrook
                            /* Accumulate.  */
5272 ad69471c pbrook
                            neon_load_reg64(cpu_V1, rd + pass);
5273 ad69471c pbrook
                            gen_neon_addl(size);
5274 9ee6e8bb pbrook
                        }
5275 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5276 9ee6e8bb pbrook
                    }
5277 9ee6e8bb pbrook
                    break;
5278 9ee6e8bb pbrook
                case 33: /* VTRN */
5279 9ee6e8bb pbrook
                    if (size == 2) {
5280 9ee6e8bb pbrook
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
5281 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, n);
5282 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, n + 1);
5283 dd8fbd78 Filip Navara
                            neon_store_reg(rm, n, tmp2);
5284 dd8fbd78 Filip Navara
                            neon_store_reg(rd, n + 1, tmp);
5285 9ee6e8bb pbrook
                        }
5286 9ee6e8bb pbrook
                    } else {
5287 9ee6e8bb pbrook
                        goto elementwise;
5288 9ee6e8bb pbrook
                    }
5289 9ee6e8bb pbrook
                    break;
5290 9ee6e8bb pbrook
                case 34: /* VUZP */
5291 9ee6e8bb pbrook
                    /* Reg  Before       After
5292 9ee6e8bb pbrook
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
5293 9ee6e8bb pbrook
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
5294 9ee6e8bb pbrook
                     */
5295 9ee6e8bb pbrook
                    if (size == 3)
5296 9ee6e8bb pbrook
                        return 1;
5297 9ee6e8bb pbrook
                    gen_neon_unzip(rd, q, 0, size);
5298 9ee6e8bb pbrook
                    gen_neon_unzip(rm, q, 4, size);
5299 9ee6e8bb pbrook
                    if (q) {
5300 9ee6e8bb pbrook
                        static int unzip_order_q[8] =
5301 9ee6e8bb pbrook
                            {0, 2, 4, 6, 1, 3, 5, 7};
5302 9ee6e8bb pbrook
                        for (n = 0; n < 8; n++) {
5303 9ee6e8bb pbrook
                            int reg = (n < 4) ? rd : rm;
5304 dd8fbd78 Filip Navara
                            tmp = neon_load_scratch(unzip_order_q[n]);
5305 dd8fbd78 Filip Navara
                            neon_store_reg(reg, n % 4, tmp);
5306 9ee6e8bb pbrook
                        }
5307 9ee6e8bb pbrook
                    } else {
5308 9ee6e8bb pbrook
                        static int unzip_order[4] =
5309 9ee6e8bb pbrook
                            {0, 4, 1, 5};
5310 9ee6e8bb pbrook
                        for (n = 0; n < 4; n++) {
5311 9ee6e8bb pbrook
                            int reg = (n < 2) ? rd : rm;
5312 dd8fbd78 Filip Navara
                            tmp = neon_load_scratch(unzip_order[n]);
5313 dd8fbd78 Filip Navara
                            neon_store_reg(reg, n % 2, tmp);
5314 9ee6e8bb pbrook
                        }
5315 9ee6e8bb pbrook
                    }
5316 9ee6e8bb pbrook
                    break;
5317 9ee6e8bb pbrook
                case 35: /* VZIP */
5318 9ee6e8bb pbrook
                    /* Reg  Before       After
5319 9ee6e8bb pbrook
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
5320 9ee6e8bb pbrook
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
5321 9ee6e8bb pbrook
                     */
5322 9ee6e8bb pbrook
                    if (size == 3)
5323 9ee6e8bb pbrook
                        return 1;
5324 9ee6e8bb pbrook
                    count = (q ? 4 : 2);
5325 9ee6e8bb pbrook
                    for (n = 0; n < count; n++) {
5326 dd8fbd78 Filip Navara
                        tmp = neon_load_reg(rd, n);
5327 dd8fbd78 Filip Navara
                        tmp2 = neon_load_reg(rd, n);
5328 9ee6e8bb pbrook
                        switch (size) {
5329 dd8fbd78 Filip Navara
                        case 0: gen_neon_zip_u8(tmp, tmp2); break;
5330 dd8fbd78 Filip Navara
                        case 1: gen_neon_zip_u16(tmp, tmp2); break;
5331 9ee6e8bb pbrook
                        case 2: /* no-op */; break;
5332 9ee6e8bb pbrook
                        default: abort();
5333 9ee6e8bb pbrook
                        }
5334 dd8fbd78 Filip Navara
                        neon_store_scratch(n * 2, tmp);
5335 dd8fbd78 Filip Navara
                        neon_store_scratch(n * 2 + 1, tmp2);
5336 9ee6e8bb pbrook
                    }
5337 9ee6e8bb pbrook
                    for (n = 0; n < count * 2; n++) {
5338 9ee6e8bb pbrook
                        int reg = (n < count) ? rd : rm;
5339 dd8fbd78 Filip Navara
                        tmp = neon_load_scratch(n);
5340 dd8fbd78 Filip Navara
                        neon_store_reg(reg, n % count, tmp);
5341 9ee6e8bb pbrook
                    }
5342 9ee6e8bb pbrook
                    break;
5343 9ee6e8bb pbrook
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5344 ad69471c pbrook
                    if (size == 3)
5345 ad69471c pbrook
                        return 1;
5346 a50f5b91 pbrook
                    TCGV_UNUSED(tmp2);
5347 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5348 ad69471c pbrook
                        neon_load_reg64(cpu_V0, rm + pass);
5349 ad69471c pbrook
                        tmp = new_tmp();
5350 9ee6e8bb pbrook
                        if (op == 36 && q == 0) {
5351 ad69471c pbrook
                            gen_neon_narrow(size, tmp, cpu_V0);
5352 9ee6e8bb pbrook
                        } else if (q) {
5353 ad69471c pbrook
                            gen_neon_narrow_satu(size, tmp, cpu_V0);
5354 9ee6e8bb pbrook
                        } else {
5355 ad69471c pbrook
                            gen_neon_narrow_sats(size, tmp, cpu_V0);
5356 ad69471c pbrook
                        }
5357 ad69471c pbrook
                        if (pass == 0) {
5358 ad69471c pbrook
                            tmp2 = tmp;
5359 ad69471c pbrook
                        } else {
5360 ad69471c pbrook
                            neon_store_reg(rd, 0, tmp2);
5361 ad69471c pbrook
                            neon_store_reg(rd, 1, tmp);
5362 9ee6e8bb pbrook
                        }
5363 9ee6e8bb pbrook
                    }
5364 9ee6e8bb pbrook
                    break;
5365 9ee6e8bb pbrook
                case 38: /* VSHLL */
5366 ad69471c pbrook
                    if (q || size == 3)
5367 9ee6e8bb pbrook
                        return 1;
5368 ad69471c pbrook
                    tmp = neon_load_reg(rm, 0);
5369 ad69471c pbrook
                    tmp2 = neon_load_reg(rm, 1);
5370 9ee6e8bb pbrook
                    for (pass = 0; pass < 2; pass++) {
5371 ad69471c pbrook
                        if (pass == 1)
5372 ad69471c pbrook
                            tmp = tmp2;
5373 ad69471c pbrook
                        gen_neon_widen(cpu_V0, tmp, size, 1);
5374 ad69471c pbrook
                        neon_store_reg64(cpu_V0, rd + pass);
5375 9ee6e8bb pbrook
                    }
5376 9ee6e8bb pbrook
                    break;
5377 9ee6e8bb pbrook
                default:
5378 9ee6e8bb pbrook
                elementwise:
5379 9ee6e8bb pbrook
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
5380 9ee6e8bb pbrook
                        if (op == 30 || op == 31 || op >= 58) {
5381 4373f3ce pbrook
                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
5382 4373f3ce pbrook
                                           neon_reg_offset(rm, pass));
5383 dd8fbd78 Filip Navara
                            TCGV_UNUSED(tmp);
5384 9ee6e8bb pbrook
                        } else {
5385 dd8fbd78 Filip Navara
                            tmp = neon_load_reg(rm, pass);
5386 9ee6e8bb pbrook
                        }
5387 9ee6e8bb pbrook
                        switch (op) {
5388 9ee6e8bb pbrook
                        case 1: /* VREV32 */
5389 9ee6e8bb pbrook
                            switch (size) {
5390 dd8fbd78 Filip Navara
                            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5391 dd8fbd78 Filip Navara
                            case 1: gen_swap_half(tmp); break;
5392 9ee6e8bb pbrook
                            default: return 1;
5393 9ee6e8bb pbrook
                            }
5394 9ee6e8bb pbrook
                            break;
5395 9ee6e8bb pbrook
                        case 2: /* VREV16 */
5396 9ee6e8bb pbrook
                            if (size != 0)
5397 9ee6e8bb pbrook
                                return 1;
5398 dd8fbd78 Filip Navara
                            gen_rev16(tmp);
5399 9ee6e8bb pbrook
                            break;
5400 9ee6e8bb pbrook
                        case 8: /* CLS */
5401 9ee6e8bb pbrook
                            switch (size) {
5402 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5403 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5404 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5405 9ee6e8bb pbrook
                            default: return 1;
5406 9ee6e8bb pbrook
                            }
5407 9ee6e8bb pbrook
                            break;
5408 9ee6e8bb pbrook
                        case 9: /* CLZ */
5409 9ee6e8bb pbrook
                            switch (size) {
5410 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5411 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5412 dd8fbd78 Filip Navara
                            case 2: gen_helper_clz(tmp, tmp); break;
5413 9ee6e8bb pbrook
                            default: return 1;
5414 9ee6e8bb pbrook
                            }
5415 9ee6e8bb pbrook
                            break;
5416 9ee6e8bb pbrook
                        case 10: /* CNT */
5417 9ee6e8bb pbrook
                            if (size != 0)
5418 9ee6e8bb pbrook
                                return 1;
5419 dd8fbd78 Filip Navara
                            gen_helper_neon_cnt_u8(tmp, tmp);
5420 9ee6e8bb pbrook
                            break;
5421 9ee6e8bb pbrook
                        case 11: /* VNOT */
5422 9ee6e8bb pbrook
                            if (size != 0)
5423 9ee6e8bb pbrook
                                return 1;
5424 dd8fbd78 Filip Navara
                            tcg_gen_not_i32(tmp, tmp);
5425 9ee6e8bb pbrook
                            break;
5426 9ee6e8bb pbrook
                        case 14: /* VQABS */
5427 9ee6e8bb pbrook
                            switch (size) {
5428 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5429 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5430 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5431 9ee6e8bb pbrook
                            default: return 1;
5432 9ee6e8bb pbrook
                            }
5433 9ee6e8bb pbrook
                            break;
5434 9ee6e8bb pbrook
                        case 15: /* VQNEG */
5435 9ee6e8bb pbrook
                            switch (size) {
5436 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5437 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5438 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5439 9ee6e8bb pbrook
                            default: return 1;
5440 9ee6e8bb pbrook
                            }
5441 9ee6e8bb pbrook
                            break;
5442 9ee6e8bb pbrook
                        case 16: case 19: /* VCGT #0, VCLE #0 */
5443 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5444 9ee6e8bb pbrook
                            switch(size) {
5445 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5446 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5447 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5448 9ee6e8bb pbrook
                            default: return 1;
5449 9ee6e8bb pbrook
                            }
5450 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5451 9ee6e8bb pbrook
                            if (op == 19)
5452 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5453 9ee6e8bb pbrook
                            break;
5454 9ee6e8bb pbrook
                        case 17: case 20: /* VCGE #0, VCLT #0 */
5455 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5456 9ee6e8bb pbrook
                            switch(size) {
5457 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5458 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5459 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5460 9ee6e8bb pbrook
                            default: return 1;
5461 9ee6e8bb pbrook
                            }
5462 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5463 9ee6e8bb pbrook
                            if (op == 20)
5464 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5465 9ee6e8bb pbrook
                            break;
5466 9ee6e8bb pbrook
                        case 18: /* VCEQ #0 */
5467 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5468 9ee6e8bb pbrook
                            switch(size) {
5469 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5470 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5471 dd8fbd78 Filip Navara
                            case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5472 9ee6e8bb pbrook
                            default: return 1;
5473 9ee6e8bb pbrook
                            }
5474 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5475 9ee6e8bb pbrook
                            break;
5476 9ee6e8bb pbrook
                        case 22: /* VABS */
5477 9ee6e8bb pbrook
                            switch(size) {
5478 dd8fbd78 Filip Navara
                            case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5479 dd8fbd78 Filip Navara
                            case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5480 dd8fbd78 Filip Navara
                            case 2: tcg_gen_abs_i32(tmp, tmp); break;
5481 9ee6e8bb pbrook
                            default: return 1;
5482 9ee6e8bb pbrook
                            }
5483 9ee6e8bb pbrook
                            break;
5484 9ee6e8bb pbrook
                        case 23: /* VNEG */
5485 ad69471c pbrook
                            if (size == 3)
5486 ad69471c pbrook
                                return 1;
5487 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5488 dd8fbd78 Filip Navara
                            gen_neon_rsb(size, tmp, tmp2);
5489 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5490 9ee6e8bb pbrook
                            break;
5491 9ee6e8bb pbrook
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5492 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5493 dd8fbd78 Filip Navara
                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5494 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5495 9ee6e8bb pbrook
                            if (op == 27)
5496 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5497 9ee6e8bb pbrook
                            break;
5498 9ee6e8bb pbrook
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5499 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5500 dd8fbd78 Filip Navara
                            gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5501 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5502 9ee6e8bb pbrook
                            if (op == 28)
5503 dd8fbd78 Filip Navara
                                tcg_gen_not_i32(tmp, tmp);
5504 9ee6e8bb pbrook
                            break;
5505 9ee6e8bb pbrook
                        case 26: /* Float VCEQ #0 */
5506 dd8fbd78 Filip Navara
                            tmp2 = tcg_const_i32(0);
5507 dd8fbd78 Filip Navara
                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5508 dd8fbd78 Filip Navara
                            tcg_temp_free(tmp2);
5509 9ee6e8bb pbrook
                            break;
5510 9ee6e8bb pbrook
                        case 30: /* Float VABS */
5511 4373f3ce pbrook
                            gen_vfp_abs(0);
5512 9ee6e8bb pbrook
                            break;
5513 9ee6e8bb pbrook
                        case 31: /* Float VNEG */
5514 4373f3ce pbrook
                            gen_vfp_neg(0);
5515 9ee6e8bb pbrook
                            break;
5516 9ee6e8bb pbrook
                        case 32: /* VSWP */
5517 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5518 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
5519 9ee6e8bb pbrook
                            break;
5520 9ee6e8bb pbrook
                        case 33: /* VTRN */
5521 dd8fbd78 Filip Navara
                            tmp2 = neon_load_reg(rd, pass);
5522 9ee6e8bb pbrook
                            switch (size) {
5523 dd8fbd78 Filip Navara
                            case 0: gen_neon_trn_u8(tmp, tmp2); break;
5524 dd8fbd78 Filip Navara
                            case 1: gen_neon_trn_u16(tmp, tmp2); break;
5525 9ee6e8bb pbrook
                            case 2: abort();
5526 9ee6e8bb pbrook
                            default: return 1;
5527 9ee6e8bb pbrook
                            }
5528 dd8fbd78 Filip Navara
                            neon_store_reg(rm, pass, tmp2);
5529 9ee6e8bb pbrook
                            break;
5530 9ee6e8bb pbrook
                        case 56: /* Integer VRECPE */
5531 dd8fbd78 Filip Navara
                            gen_helper_recpe_u32(tmp, tmp, cpu_env);
5532 9ee6e8bb pbrook
                            break;
5533 9ee6e8bb pbrook
                        case 57: /* Integer VRSQRTE */
5534 dd8fbd78 Filip Navara
                            gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5535 9ee6e8bb pbrook
                            break;
5536 9ee6e8bb pbrook
                        case 58: /* Float VRECPE */
5537 4373f3ce pbrook
                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5538 9ee6e8bb pbrook
                            break;
5539 9ee6e8bb pbrook
                        case 59: /* Float VRSQRTE */
5540 4373f3ce pbrook
                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5541 9ee6e8bb pbrook
                            break;
5542 9ee6e8bb pbrook
                        case 60: /* VCVT.F32.S32 */
5543 4373f3ce pbrook
                            gen_vfp_tosiz(0);
5544 9ee6e8bb pbrook
                            break;
5545 9ee6e8bb pbrook
                        case 61: /* VCVT.F32.U32 */
5546 4373f3ce pbrook
                            gen_vfp_touiz(0);
5547 9ee6e8bb pbrook
                            break;
5548 9ee6e8bb pbrook
                        case 62: /* VCVT.S32.F32 */
5549 4373f3ce pbrook
                            gen_vfp_sito(0);
5550 9ee6e8bb pbrook
                            break;
5551 9ee6e8bb pbrook
                        case 63: /* VCVT.U32.F32 */
5552 4373f3ce pbrook
                            gen_vfp_uito(0);
5553 9ee6e8bb pbrook
                            break;
5554 9ee6e8bb pbrook
                        default:
5555 9ee6e8bb pbrook
                            /* Reserved: 21, 29, 39-56 */
5556 9ee6e8bb pbrook
                            return 1;
5557 9ee6e8bb pbrook
                        }
5558 9ee6e8bb pbrook
                        if (op == 30 || op == 31 || op >= 58) {
5559 4373f3ce pbrook
                            tcg_gen_st_f32(cpu_F0s, cpu_env,
5560 4373f3ce pbrook
                                           neon_reg_offset(rd, pass));
5561 9ee6e8bb pbrook
                        } else {
5562 dd8fbd78 Filip Navara
                            neon_store_reg(rd, pass, tmp);
5563 9ee6e8bb pbrook
                        }
5564 9ee6e8bb pbrook
                    }
5565 9ee6e8bb pbrook
                    break;
5566 9ee6e8bb pbrook
                }
5567 9ee6e8bb pbrook
            } else if ((insn & (1 << 10)) == 0) {
5568 9ee6e8bb pbrook
                /* VTBL, VTBX.  */
5569 3018f259 pbrook
                n = ((insn >> 5) & 0x18) + 8;
5570 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
5571 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 0);
5572 9ee6e8bb pbrook
                } else {
5573 8f8e3aa4 pbrook
                    tmp = new_tmp();
5574 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
5575 9ee6e8bb pbrook
                }
5576 8f8e3aa4 pbrook
                tmp2 = neon_load_reg(rm, 0);
5577 8f8e3aa4 pbrook
                gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5578 8f8e3aa4 pbrook
                                    tcg_const_i32(n));
5579 3018f259 pbrook
                dead_tmp(tmp);
5580 9ee6e8bb pbrook
                if (insn & (1 << 6)) {
5581 8f8e3aa4 pbrook
                    tmp = neon_load_reg(rd, 1);
5582 9ee6e8bb pbrook
                } else {
5583 8f8e3aa4 pbrook
                    tmp = new_tmp();
5584 8f8e3aa4 pbrook
                    tcg_gen_movi_i32(tmp, 0);
5585 9ee6e8bb pbrook
                }
5586 8f8e3aa4 pbrook
                tmp3 = neon_load_reg(rm, 1);
5587 8f8e3aa4 pbrook
                gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5588 8f8e3aa4 pbrook
                                    tcg_const_i32(n));
5589 8f8e3aa4 pbrook
                neon_store_reg(rd, 0, tmp2);
5590 3018f259 pbrook
                neon_store_reg(rd, 1, tmp3);
5591 3018f259 pbrook
                dead_tmp(tmp);
5592 9ee6e8bb pbrook
            } else if ((insn & 0x380) == 0) {
5593 9ee6e8bb pbrook
                /* VDUP */
5594 9ee6e8bb pbrook
                if (insn & (1 << 19)) {
5595 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 1);
5596 9ee6e8bb pbrook
                } else {
5597 dd8fbd78 Filip Navara
                    tmp = neon_load_reg(rm, 0);
5598 9ee6e8bb pbrook
                }
5599 9ee6e8bb pbrook
                if (insn & (1 << 16)) {
5600 dd8fbd78 Filip Navara
                    gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5601 9ee6e8bb pbrook
                } else if (insn & (1 << 17)) {
5602 9ee6e8bb pbrook
                    if ((insn >> 18) & 1)
5603 dd8fbd78 Filip Navara
                        gen_neon_dup_high16(tmp);
5604 9ee6e8bb pbrook
                    else
5605 dd8fbd78 Filip Navara
                        gen_neon_dup_low16(tmp);
5606 9ee6e8bb pbrook
                }
5607 9ee6e8bb pbrook
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
5608 dd8fbd78 Filip Navara
                    tmp2 = new_tmp();
5609 dd8fbd78 Filip Navara
                    tcg_gen_mov_i32(tmp2, tmp);
5610 dd8fbd78 Filip Navara
                    neon_store_reg(rd, pass, tmp2);
5611 9ee6e8bb pbrook
                }
5612 dd8fbd78 Filip Navara
                dead_tmp(tmp);
5613 9ee6e8bb pbrook
            } else {
5614 9ee6e8bb pbrook
                return 1;
5615 9ee6e8bb pbrook
            }
5616 9ee6e8bb pbrook
        }
5617 9ee6e8bb pbrook
    }
5618 9ee6e8bb pbrook
    return 0;
5619 9ee6e8bb pbrook
}
5620 9ee6e8bb pbrook
5621 fe1479c3 pbrook
static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5622 fe1479c3 pbrook
{
5623 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
5624 fe1479c3 pbrook
    int crm = insn & 0xf;
5625 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
5626 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
5627 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
5628 fe1479c3 pbrook
    TCGv tmp;
5629 fe1479c3 pbrook
5630 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5631 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5632 fe1479c3 pbrook
            /* TEECR */
5633 fe1479c3 pbrook
            if (IS_USER(s))
5634 fe1479c3 pbrook
                return 1;
5635 fe1479c3 pbrook
            tmp = load_cpu_field(teecr);
5636 fe1479c3 pbrook
            store_reg(s, rt, tmp);
5637 fe1479c3 pbrook
            return 0;
5638 fe1479c3 pbrook
        }
5639 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5640 fe1479c3 pbrook
            /* TEEHBR */
5641 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
5642 fe1479c3 pbrook
                return 1;
5643 fe1479c3 pbrook
            tmp = load_cpu_field(teehbr);
5644 fe1479c3 pbrook
            store_reg(s, rt, tmp);
5645 fe1479c3 pbrook
            return 0;
5646 fe1479c3 pbrook
        }
5647 fe1479c3 pbrook
    }
5648 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5649 fe1479c3 pbrook
            op1, crn, crm, op2);
5650 fe1479c3 pbrook
    return 1;
5651 fe1479c3 pbrook
}
5652 fe1479c3 pbrook
5653 fe1479c3 pbrook
static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5654 fe1479c3 pbrook
{
5655 fe1479c3 pbrook
    int crn = (insn >> 16) & 0xf;
5656 fe1479c3 pbrook
    int crm = insn & 0xf;
5657 fe1479c3 pbrook
    int op1 = (insn >> 21) & 7;
5658 fe1479c3 pbrook
    int op2 = (insn >> 5) & 7;
5659 fe1479c3 pbrook
    int rt = (insn >> 12) & 0xf;
5660 fe1479c3 pbrook
    TCGv tmp;
5661 fe1479c3 pbrook
5662 fe1479c3 pbrook
    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5663 fe1479c3 pbrook
        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5664 fe1479c3 pbrook
            /* TEECR */
5665 fe1479c3 pbrook
            if (IS_USER(s))
5666 fe1479c3 pbrook
                return 1;
5667 fe1479c3 pbrook
            tmp = load_reg(s, rt);
5668 fe1479c3 pbrook
            gen_helper_set_teecr(cpu_env, tmp);
5669 fe1479c3 pbrook
            dead_tmp(tmp);
5670 fe1479c3 pbrook
            return 0;
5671 fe1479c3 pbrook
        }
5672 fe1479c3 pbrook
        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5673 fe1479c3 pbrook
            /* TEEHBR */
5674 fe1479c3 pbrook
            if (IS_USER(s) && (env->teecr & 1))
5675 fe1479c3 pbrook
                return 1;
5676 fe1479c3 pbrook
            tmp = load_reg(s, rt);
5677 fe1479c3 pbrook
            store_cpu_field(tmp, teehbr);
5678 fe1479c3 pbrook
            return 0;
5679 fe1479c3 pbrook
        }
5680 fe1479c3 pbrook
    }
5681 fe1479c3 pbrook
    fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5682 fe1479c3 pbrook
            op1, crn, crm, op2);
5683 fe1479c3 pbrook
    return 1;
5684 fe1479c3 pbrook
}
5685 fe1479c3 pbrook
5686 9ee6e8bb pbrook
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5687 9ee6e8bb pbrook
{
5688 9ee6e8bb pbrook
    int cpnum;
5689 9ee6e8bb pbrook
5690 9ee6e8bb pbrook
    cpnum = (insn >> 8) & 0xf;
5691 9ee6e8bb pbrook
    if (arm_feature(env, ARM_FEATURE_XSCALE)
5692 9ee6e8bb pbrook
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5693 9ee6e8bb pbrook
        return 1;
5694 9ee6e8bb pbrook
5695 9ee6e8bb pbrook
    switch (cpnum) {
5696 9ee6e8bb pbrook
      case 0:
5697 9ee6e8bb pbrook
      case 1:
5698 9ee6e8bb pbrook
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5699 9ee6e8bb pbrook
            return disas_iwmmxt_insn(env, s, insn);
5700 9ee6e8bb pbrook
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5701 9ee6e8bb pbrook
            return disas_dsp_insn(env, s, insn);
5702 9ee6e8bb pbrook
        }
5703 9ee6e8bb pbrook
        return 1;
5704 9ee6e8bb pbrook
    case 10:
5705 9ee6e8bb pbrook
    case 11:
5706 9ee6e8bb pbrook
        return disas_vfp_insn (env, s, insn);
5707 fe1479c3 pbrook
    case 14:
5708 fe1479c3 pbrook
        /* Coprocessors 7-15 are architecturally reserved by ARM.
5709 fe1479c3 pbrook
           Unfortunately Intel decided to ignore this.  */
5710 fe1479c3 pbrook
        if (arm_feature(env, ARM_FEATURE_XSCALE))
5711 fe1479c3 pbrook
            goto board;
5712 fe1479c3 pbrook
        if (insn & (1 << 20))
5713 fe1479c3 pbrook
            return disas_cp14_read(env, s, insn);
5714 fe1479c3 pbrook
        else
5715 fe1479c3 pbrook
            return disas_cp14_write(env, s, insn);
5716 9ee6e8bb pbrook
    case 15:
5717 9ee6e8bb pbrook
        return disas_cp15_insn (env, s, insn);
5718 9ee6e8bb pbrook
    default:
5719 fe1479c3 pbrook
    board:
5720 9ee6e8bb pbrook
        /* Unknown coprocessor.  See if the board has hooked it.  */
5721 9ee6e8bb pbrook
        return disas_cp_insn (env, s, insn);
5722 9ee6e8bb pbrook
    }
5723 9ee6e8bb pbrook
}
5724 9ee6e8bb pbrook
5725 5e3f878a pbrook
5726 5e3f878a pbrook
/* Store a 64-bit value to a register pair.  Clobbers val.  */
5727 a7812ae4 pbrook
static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5728 5e3f878a pbrook
{
5729 5e3f878a pbrook
    TCGv tmp;
5730 5e3f878a pbrook
    tmp = new_tmp();
5731 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
5732 5e3f878a pbrook
    store_reg(s, rlow, tmp);
5733 5e3f878a pbrook
    tmp = new_tmp();
5734 5e3f878a pbrook
    tcg_gen_shri_i64(val, val, 32);
5735 5e3f878a pbrook
    tcg_gen_trunc_i64_i32(tmp, val);
5736 5e3f878a pbrook
    store_reg(s, rhigh, tmp);
5737 5e3f878a pbrook
}
5738 5e3f878a pbrook
5739 5e3f878a pbrook
/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
5740 a7812ae4 pbrook
static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5741 5e3f878a pbrook
{
5742 a7812ae4 pbrook
    TCGv_i64 tmp;
5743 5e3f878a pbrook
    TCGv tmp2;
5744 5e3f878a pbrook
5745 36aa55dc pbrook
    /* Load value and extend to 64 bits.  */
5746 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
5747 5e3f878a pbrook
    tmp2 = load_reg(s, rlow);
5748 5e3f878a pbrook
    tcg_gen_extu_i32_i64(tmp, tmp2);
5749 5e3f878a pbrook
    dead_tmp(tmp2);
5750 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
5751 5e3f878a pbrook
}
5752 5e3f878a pbrook
5753 5e3f878a pbrook
/* load and add a 64-bit value from a register pair.  */
5754 a7812ae4 pbrook
static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5755 5e3f878a pbrook
{
5756 a7812ae4 pbrook
    TCGv_i64 tmp;
5757 36aa55dc pbrook
    TCGv tmpl;
5758 36aa55dc pbrook
    TCGv tmph;
5759 5e3f878a pbrook
5760 5e3f878a pbrook
    /* Load 64-bit value rd:rn.  */
5761 36aa55dc pbrook
    tmpl = load_reg(s, rlow);
5762 36aa55dc pbrook
    tmph = load_reg(s, rhigh);
5763 a7812ae4 pbrook
    tmp = tcg_temp_new_i64();
5764 36aa55dc pbrook
    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5765 36aa55dc pbrook
    dead_tmp(tmpl);
5766 36aa55dc pbrook
    dead_tmp(tmph);
5767 5e3f878a pbrook
    tcg_gen_add_i64(val, val, tmp);
5768 5e3f878a pbrook
}
5769 5e3f878a pbrook
5770 5e3f878a pbrook
/* Set N and Z flags from a 64-bit value.  */
5771 a7812ae4 pbrook
static void gen_logicq_cc(TCGv_i64 val)
5772 5e3f878a pbrook
{
5773 5e3f878a pbrook
    TCGv tmp = new_tmp();
5774 5e3f878a pbrook
    gen_helper_logicq_cc(tmp, val);
5775 6fbe23d5 pbrook
    gen_logic_CC(tmp);
5776 6fbe23d5 pbrook
    dead_tmp(tmp);
5777 5e3f878a pbrook
}
5778 5e3f878a pbrook
5779 9ee6e8bb pbrook
static void disas_arm_insn(CPUState * env, DisasContext *s)
5780 9ee6e8bb pbrook
{
5781 9ee6e8bb pbrook
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5782 b26eefb6 pbrook
    TCGv tmp;
5783 3670669c pbrook
    TCGv tmp2;
5784 6ddbc6e4 pbrook
    TCGv tmp3;
5785 b0109805 pbrook
    TCGv addr;
5786 a7812ae4 pbrook
    TCGv_i64 tmp64;
5787 9ee6e8bb pbrook
5788 9ee6e8bb pbrook
    insn = ldl_code(s->pc);
5789 9ee6e8bb pbrook
    s->pc += 4;
5790 9ee6e8bb pbrook
5791 9ee6e8bb pbrook
    /* M variants do not implement ARM mode.  */
5792 9ee6e8bb pbrook
    if (IS_M(env))
5793 9ee6e8bb pbrook
        goto illegal_op;
5794 9ee6e8bb pbrook
    cond = insn >> 28;
5795 9ee6e8bb pbrook
    if (cond == 0xf){
5796 9ee6e8bb pbrook
        /* Unconditional instructions.  */
5797 9ee6e8bb pbrook
        if (((insn >> 25) & 7) == 1) {
5798 9ee6e8bb pbrook
            /* NEON Data processing.  */
5799 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_NEON))
5800 9ee6e8bb pbrook
                goto illegal_op;
5801 9ee6e8bb pbrook
5802 9ee6e8bb pbrook
            if (disas_neon_data_insn(env, s, insn))
5803 9ee6e8bb pbrook
                goto illegal_op;
5804 9ee6e8bb pbrook
            return;
5805 9ee6e8bb pbrook
        }
5806 9ee6e8bb pbrook
        if ((insn & 0x0f100000) == 0x04000000) {
5807 9ee6e8bb pbrook
            /* NEON load/store.  */
5808 9ee6e8bb pbrook
            if (!arm_feature(env, ARM_FEATURE_NEON))
5809 9ee6e8bb pbrook
                goto illegal_op;
5810 9ee6e8bb pbrook
5811 9ee6e8bb pbrook
            if (disas_neon_ls_insn(env, s, insn))
5812 9ee6e8bb pbrook
                goto illegal_op;
5813 9ee6e8bb pbrook
            return;
5814 9ee6e8bb pbrook
        }
5815 9ee6e8bb pbrook
        if ((insn & 0x0d70f000) == 0x0550f000)
5816 9ee6e8bb pbrook
            return; /* PLD */
5817 9ee6e8bb pbrook
        else if ((insn & 0x0ffffdff) == 0x01010000) {
5818 9ee6e8bb pbrook
            ARCH(6);
5819 9ee6e8bb pbrook
            /* setend */
5820 9ee6e8bb pbrook
            if (insn & (1 << 9)) {
5821 9ee6e8bb pbrook
                /* BE8 mode not implemented.  */
5822 9ee6e8bb pbrook
                goto illegal_op;
5823 9ee6e8bb pbrook
            }
5824 9ee6e8bb pbrook
            return;
5825 9ee6e8bb pbrook
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
5826 9ee6e8bb pbrook
            switch ((insn >> 4) & 0xf) {
5827 9ee6e8bb pbrook
            case 1: /* clrex */
5828 9ee6e8bb pbrook
                ARCH(6K);
5829 8f8e3aa4 pbrook
                gen_helper_clrex(cpu_env);
5830 9ee6e8bb pbrook
                return;
5831 9ee6e8bb pbrook
            case 4: /* dsb */
5832 9ee6e8bb pbrook
            case 5: /* dmb */
5833 9ee6e8bb pbrook
            case 6: /* isb */
5834 9ee6e8bb pbrook
                ARCH(7);
5835 9ee6e8bb pbrook
                /* We don't emulate caches so these are a no-op.  */
5836 9ee6e8bb pbrook
                return;
5837 9ee6e8bb pbrook
            default:
5838 9ee6e8bb pbrook
                goto illegal_op;
5839 9ee6e8bb pbrook
            }
5840 9ee6e8bb pbrook
        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5841 9ee6e8bb pbrook
            /* srs */
5842 c67b6b71 Filip Navara
            int32_t offset;
5843 9ee6e8bb pbrook
            if (IS_USER(s))
5844 9ee6e8bb pbrook
                goto illegal_op;
5845 9ee6e8bb pbrook
            ARCH(6);
5846 9ee6e8bb pbrook
            op1 = (insn & 0x1f);
5847 9ee6e8bb pbrook
            if (op1 == (env->uncached_cpsr & CPSR_M)) {
5848 b0109805 pbrook
                addr = load_reg(s, 13);
5849 9ee6e8bb pbrook
            } else {
5850 b0109805 pbrook
                addr = new_tmp();
5851 b0109805 pbrook
                gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5852 9ee6e8bb pbrook
            }
5853 9ee6e8bb pbrook
            i = (insn >> 23) & 3;
5854 9ee6e8bb pbrook
            switch (i) {
5855 9ee6e8bb pbrook
            case 0: offset = -4; break; /* DA */
5856 c67b6b71 Filip Navara
            case 1: offset = 0; break; /* IA */
5857 c67b6b71 Filip Navara
            case 2: offset = -8; break; /* DB */
5858 9ee6e8bb pbrook
            case 3: offset = 4; break; /* IB */
5859 9ee6e8bb pbrook
            default: abort();
5860 9ee6e8bb pbrook
            }
5861 9ee6e8bb pbrook
            if (offset)
5862 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, offset);
5863 b0109805 pbrook
            tmp = load_reg(s, 14);
5864 b0109805 pbrook
            gen_st32(tmp, addr, 0);
5865 c67b6b71 Filip Navara
            tmp = load_cpu_field(spsr);
5866 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, 4);
5867 b0109805 pbrook
            gen_st32(tmp, addr, 0);
5868 9ee6e8bb pbrook
            if (insn & (1 << 21)) {
5869 9ee6e8bb pbrook
                /* Base writeback.  */
5870 9ee6e8bb pbrook
                switch (i) {
5871 9ee6e8bb pbrook
                case 0: offset = -8; break;
5872 c67b6b71 Filip Navara
                case 1: offset = 4; break;
5873 c67b6b71 Filip Navara
                case 2: offset = -4; break;
5874 9ee6e8bb pbrook
                case 3: offset = 0; break;
5875 9ee6e8bb pbrook
                default: abort();
5876 9ee6e8bb pbrook
                }
5877 9ee6e8bb pbrook
                if (offset)
5878 c67b6b71 Filip Navara
                    tcg_gen_addi_i32(addr, addr, offset);
5879 9ee6e8bb pbrook
                if (op1 == (env->uncached_cpsr & CPSR_M)) {
5880 c67b6b71 Filip Navara
                    store_reg(s, 13, addr);
5881 9ee6e8bb pbrook
                } else {
5882 c67b6b71 Filip Navara
                    gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5883 c67b6b71 Filip Navara
                    dead_tmp(addr);
5884 9ee6e8bb pbrook
                }
5885 b0109805 pbrook
            } else {
5886 b0109805 pbrook
                dead_tmp(addr);
5887 9ee6e8bb pbrook
            }
5888 9ee6e8bb pbrook
        } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5889 9ee6e8bb pbrook
            /* rfe */
5890 c67b6b71 Filip Navara
            int32_t offset;
5891 9ee6e8bb pbrook
            if (IS_USER(s))
5892 9ee6e8bb pbrook
                goto illegal_op;
5893 9ee6e8bb pbrook
            ARCH(6);
5894 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
5895 b0109805 pbrook
            addr = load_reg(s, rn);
5896 9ee6e8bb pbrook
            i = (insn >> 23) & 3;
5897 9ee6e8bb pbrook
            switch (i) {
5898 b0109805 pbrook
            case 0: offset = -4; break; /* DA */
5899 c67b6b71 Filip Navara
            case 1: offset = 0; break; /* IA */
5900 c67b6b71 Filip Navara
            case 2: offset = -8; break; /* DB */
5901 b0109805 pbrook
            case 3: offset = 4; break; /* IB */
5902 9ee6e8bb pbrook
            default: abort();
5903 9ee6e8bb pbrook
            }
5904 9ee6e8bb pbrook
            if (offset)
5905 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, offset);
5906 b0109805 pbrook
            /* Load PC into tmp and CPSR into tmp2.  */
5907 b0109805 pbrook
            tmp = gen_ld32(addr, 0);
5908 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, 4);
5909 b0109805 pbrook
            tmp2 = gen_ld32(addr, 0);
5910 9ee6e8bb pbrook
            if (insn & (1 << 21)) {
5911 9ee6e8bb pbrook
                /* Base writeback.  */
5912 9ee6e8bb pbrook
                switch (i) {
5913 b0109805 pbrook
                case 0: offset = -8; break;
5914 c67b6b71 Filip Navara
                case 1: offset = 4; break;
5915 c67b6b71 Filip Navara
                case 2: offset = -4; break;
5916 b0109805 pbrook
                case 3: offset = 0; break;
5917 9ee6e8bb pbrook
                default: abort();
5918 9ee6e8bb pbrook
                }
5919 9ee6e8bb pbrook
                if (offset)
5920 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset);
5921 b0109805 pbrook
                store_reg(s, rn, addr);
5922 b0109805 pbrook
            } else {
5923 b0109805 pbrook
                dead_tmp(addr);
5924 9ee6e8bb pbrook
            }
5925 b0109805 pbrook
            gen_rfe(s, tmp, tmp2);
5926 c67b6b71 Filip Navara
            return;
5927 9ee6e8bb pbrook
        } else if ((insn & 0x0e000000) == 0x0a000000) {
5928 9ee6e8bb pbrook
            /* branch link and change to thumb (blx <offset>) */
5929 9ee6e8bb pbrook
            int32_t offset;
5930 9ee6e8bb pbrook
5931 9ee6e8bb pbrook
            val = (uint32_t)s->pc;
5932 d9ba4830 pbrook
            tmp = new_tmp();
5933 d9ba4830 pbrook
            tcg_gen_movi_i32(tmp, val);
5934 d9ba4830 pbrook
            store_reg(s, 14, tmp);
5935 9ee6e8bb pbrook
            /* Sign-extend the 24-bit offset */
5936 9ee6e8bb pbrook
            offset = (((int32_t)insn) << 8) >> 8;
5937 9ee6e8bb pbrook
            /* offset * 4 + bit24 * 2 + (thumb bit) */
5938 9ee6e8bb pbrook
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
5939 9ee6e8bb pbrook
            /* pipeline offset */
5940 9ee6e8bb pbrook
            val += 4;
5941 d9ba4830 pbrook
            gen_bx_im(s, val);
5942 9ee6e8bb pbrook
            return;
5943 9ee6e8bb pbrook
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
5944 9ee6e8bb pbrook
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5945 9ee6e8bb pbrook
                /* iWMMXt register transfer.  */
5946 9ee6e8bb pbrook
                if (env->cp15.c15_cpar & (1 << 1))
5947 9ee6e8bb pbrook
                    if (!disas_iwmmxt_insn(env, s, insn))
5948 9ee6e8bb pbrook
                        return;
5949 9ee6e8bb pbrook
            }
5950 9ee6e8bb pbrook
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
5951 9ee6e8bb pbrook
            /* Coprocessor double register transfer.  */
5952 9ee6e8bb pbrook
        } else if ((insn & 0x0f000010) == 0x0e000010) {
5953 9ee6e8bb pbrook
            /* Additional coprocessor register transfer.  */
5954 7997d92f balrog
        } else if ((insn & 0x0ff10020) == 0x01000000) {
5955 9ee6e8bb pbrook
            uint32_t mask;
5956 9ee6e8bb pbrook
            uint32_t val;
5957 9ee6e8bb pbrook
            /* cps (privileged) */
5958 9ee6e8bb pbrook
            if (IS_USER(s))
5959 9ee6e8bb pbrook
                return;
5960 9ee6e8bb pbrook
            mask = val = 0;
5961 9ee6e8bb pbrook
            if (insn & (1 << 19)) {
5962 9ee6e8bb pbrook
                if (insn & (1 << 8))
5963 9ee6e8bb pbrook
                    mask |= CPSR_A;
5964 9ee6e8bb pbrook
                if (insn & (1 << 7))
5965 9ee6e8bb pbrook
                    mask |= CPSR_I;
5966 9ee6e8bb pbrook
                if (insn & (1 << 6))
5967 9ee6e8bb pbrook
                    mask |= CPSR_F;
5968 9ee6e8bb pbrook
                if (insn & (1 << 18))
5969 9ee6e8bb pbrook
                    val |= mask;
5970 9ee6e8bb pbrook
            }
5971 7997d92f balrog
            if (insn & (1 << 17)) {
5972 9ee6e8bb pbrook
                mask |= CPSR_M;
5973 9ee6e8bb pbrook
                val |= (insn & 0x1f);
5974 9ee6e8bb pbrook
            }
5975 9ee6e8bb pbrook
            if (mask) {
5976 2fbac54b Filip Navara
                gen_set_psr_im(s, mask, 0, val);
5977 9ee6e8bb pbrook
            }
5978 9ee6e8bb pbrook
            return;
5979 9ee6e8bb pbrook
        }
5980 9ee6e8bb pbrook
        goto illegal_op;
5981 9ee6e8bb pbrook
    }
5982 9ee6e8bb pbrook
    if (cond != 0xe) {
5983 9ee6e8bb pbrook
        /* if not always execute, we generate a conditional jump to
5984 9ee6e8bb pbrook
           next instruction */
5985 9ee6e8bb pbrook
        s->condlabel = gen_new_label();
5986 d9ba4830 pbrook
        gen_test_cc(cond ^ 1, s->condlabel);
5987 9ee6e8bb pbrook
        s->condjmp = 1;
5988 9ee6e8bb pbrook
    }
5989 9ee6e8bb pbrook
    if ((insn & 0x0f900000) == 0x03000000) {
5990 9ee6e8bb pbrook
        if ((insn & (1 << 21)) == 0) {
5991 9ee6e8bb pbrook
            ARCH(6T2);
5992 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
5993 9ee6e8bb pbrook
            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5994 9ee6e8bb pbrook
            if ((insn & (1 << 22)) == 0) {
5995 9ee6e8bb pbrook
                /* MOVW */
5996 5e3f878a pbrook
                tmp = new_tmp();
5997 5e3f878a pbrook
                tcg_gen_movi_i32(tmp, val);
5998 9ee6e8bb pbrook
            } else {
5999 9ee6e8bb pbrook
                /* MOVT */
6000 5e3f878a pbrook
                tmp = load_reg(s, rd);
6001 86831435 pbrook
                tcg_gen_ext16u_i32(tmp, tmp);
6002 5e3f878a pbrook
                tcg_gen_ori_i32(tmp, tmp, val << 16);
6003 9ee6e8bb pbrook
            }
6004 5e3f878a pbrook
            store_reg(s, rd, tmp);
6005 9ee6e8bb pbrook
        } else {
6006 9ee6e8bb pbrook
            if (((insn >> 12) & 0xf) != 0xf)
6007 9ee6e8bb pbrook
                goto illegal_op;
6008 9ee6e8bb pbrook
            if (((insn >> 16) & 0xf) == 0) {
6009 9ee6e8bb pbrook
                gen_nop_hint(s, insn & 0xff);
6010 9ee6e8bb pbrook
            } else {
6011 9ee6e8bb pbrook
                /* CPSR = immediate */
6012 9ee6e8bb pbrook
                val = insn & 0xff;
6013 9ee6e8bb pbrook
                shift = ((insn >> 8) & 0xf) * 2;
6014 9ee6e8bb pbrook
                if (shift)
6015 9ee6e8bb pbrook
                    val = (val >> shift) | (val << (32 - shift));
6016 9ee6e8bb pbrook
                i = ((insn & (1 << 22)) != 0);
6017 2fbac54b Filip Navara
                if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6018 9ee6e8bb pbrook
                    goto illegal_op;
6019 9ee6e8bb pbrook
            }
6020 9ee6e8bb pbrook
        }
6021 9ee6e8bb pbrook
    } else if ((insn & 0x0f900000) == 0x01000000
6022 9ee6e8bb pbrook
               && (insn & 0x00000090) != 0x00000090) {
6023 9ee6e8bb pbrook
        /* miscellaneous instructions */
6024 9ee6e8bb pbrook
        op1 = (insn >> 21) & 3;
6025 9ee6e8bb pbrook
        sh = (insn >> 4) & 0xf;
6026 9ee6e8bb pbrook
        rm = insn & 0xf;
6027 9ee6e8bb pbrook
        switch (sh) {
6028 9ee6e8bb pbrook
        case 0x0: /* move program status register */
6029 9ee6e8bb pbrook
            if (op1 & 1) {
6030 9ee6e8bb pbrook
                /* PSR = reg */
6031 2fbac54b Filip Navara
                tmp = load_reg(s, rm);
6032 9ee6e8bb pbrook
                i = ((op1 & 2) != 0);
6033 2fbac54b Filip Navara
                if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6034 9ee6e8bb pbrook
                    goto illegal_op;
6035 9ee6e8bb pbrook
            } else {
6036 9ee6e8bb pbrook
                /* reg = PSR */
6037 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
6038 9ee6e8bb pbrook
                if (op1 & 2) {
6039 9ee6e8bb pbrook
                    if (IS_USER(s))
6040 9ee6e8bb pbrook
                        goto illegal_op;
6041 d9ba4830 pbrook
                    tmp = load_cpu_field(spsr);
6042 9ee6e8bb pbrook
                } else {
6043 d9ba4830 pbrook
                    tmp = new_tmp();
6044 d9ba4830 pbrook
                    gen_helper_cpsr_read(tmp);
6045 9ee6e8bb pbrook
                }
6046 d9ba4830 pbrook
                store_reg(s, rd, tmp);
6047 9ee6e8bb pbrook
            }
6048 9ee6e8bb pbrook
            break;
6049 9ee6e8bb pbrook
        case 0x1:
6050 9ee6e8bb pbrook
            if (op1 == 1) {
6051 9ee6e8bb pbrook
                /* branch/exchange thumb (bx).  */
6052 d9ba4830 pbrook
                tmp = load_reg(s, rm);
6053 d9ba4830 pbrook
                gen_bx(s, tmp);
6054 9ee6e8bb pbrook
            } else if (op1 == 3) {
6055 9ee6e8bb pbrook
                /* clz */
6056 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
6057 1497c961 pbrook
                tmp = load_reg(s, rm);
6058 1497c961 pbrook
                gen_helper_clz(tmp, tmp);
6059 1497c961 pbrook
                store_reg(s, rd, tmp);
6060 9ee6e8bb pbrook
            } else {
6061 9ee6e8bb pbrook
                goto illegal_op;
6062 9ee6e8bb pbrook
            }
6063 9ee6e8bb pbrook
            break;
6064 9ee6e8bb pbrook
        case 0x2:
6065 9ee6e8bb pbrook
            if (op1 == 1) {
6066 9ee6e8bb pbrook
                ARCH(5J); /* bxj */
6067 9ee6e8bb pbrook
                /* Trivial implementation equivalent to bx.  */
6068 d9ba4830 pbrook
                tmp = load_reg(s, rm);
6069 d9ba4830 pbrook
                gen_bx(s, tmp);
6070 9ee6e8bb pbrook
            } else {
6071 9ee6e8bb pbrook
                goto illegal_op;
6072 9ee6e8bb pbrook
            }
6073 9ee6e8bb pbrook
            break;
6074 9ee6e8bb pbrook
        case 0x3:
6075 9ee6e8bb pbrook
            if (op1 != 1)
6076 9ee6e8bb pbrook
              goto illegal_op;
6077 9ee6e8bb pbrook
6078 9ee6e8bb pbrook
            /* branch link/exchange thumb (blx) */
6079 d9ba4830 pbrook
            tmp = load_reg(s, rm);
6080 d9ba4830 pbrook
            tmp2 = new_tmp();
6081 d9ba4830 pbrook
            tcg_gen_movi_i32(tmp2, s->pc);
6082 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
6083 d9ba4830 pbrook
            gen_bx(s, tmp);
6084 9ee6e8bb pbrook
            break;
6085 9ee6e8bb pbrook
        case 0x5: /* saturating add/subtract */
6086 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
6087 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6088 b40d0353 balrog
            tmp = load_reg(s, rm);
6089 5e3f878a pbrook
            tmp2 = load_reg(s, rn);
6090 9ee6e8bb pbrook
            if (op1 & 2)
6091 5e3f878a pbrook
                gen_helper_double_saturate(tmp2, tmp2);
6092 9ee6e8bb pbrook
            if (op1 & 1)
6093 5e3f878a pbrook
                gen_helper_sub_saturate(tmp, tmp, tmp2);
6094 9ee6e8bb pbrook
            else
6095 5e3f878a pbrook
                gen_helper_add_saturate(tmp, tmp, tmp2);
6096 5e3f878a pbrook
            dead_tmp(tmp2);
6097 5e3f878a pbrook
            store_reg(s, rd, tmp);
6098 9ee6e8bb pbrook
            break;
6099 9ee6e8bb pbrook
        case 7: /* bkpt */
6100 9ee6e8bb pbrook
            gen_set_condexec(s);
6101 5e3f878a pbrook
            gen_set_pc_im(s->pc - 4);
6102 d9ba4830 pbrook
            gen_exception(EXCP_BKPT);
6103 9ee6e8bb pbrook
            s->is_jmp = DISAS_JUMP;
6104 9ee6e8bb pbrook
            break;
6105 9ee6e8bb pbrook
        case 0x8: /* signed multiply */
6106 9ee6e8bb pbrook
        case 0xa:
6107 9ee6e8bb pbrook
        case 0xc:
6108 9ee6e8bb pbrook
        case 0xe:
6109 9ee6e8bb pbrook
            rs = (insn >> 8) & 0xf;
6110 9ee6e8bb pbrook
            rn = (insn >> 12) & 0xf;
6111 9ee6e8bb pbrook
            rd = (insn >> 16) & 0xf;
6112 9ee6e8bb pbrook
            if (op1 == 1) {
6113 9ee6e8bb pbrook
                /* (32 * 16) >> 16 */
6114 5e3f878a pbrook
                tmp = load_reg(s, rm);
6115 5e3f878a pbrook
                tmp2 = load_reg(s, rs);
6116 9ee6e8bb pbrook
                if (sh & 4)
6117 5e3f878a pbrook
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
6118 9ee6e8bb pbrook
                else
6119 5e3f878a pbrook
                    gen_sxth(tmp2);
6120 a7812ae4 pbrook
                tmp64 = gen_muls_i64_i32(tmp, tmp2);
6121 a7812ae4 pbrook
                tcg_gen_shri_i64(tmp64, tmp64, 16);
6122 5e3f878a pbrook
                tmp = new_tmp();
6123 a7812ae4 pbrook
                tcg_gen_trunc_i64_i32(tmp, tmp64);
6124 9ee6e8bb pbrook
                if ((sh & 2) == 0) {
6125 5e3f878a pbrook
                    tmp2 = load_reg(s, rn);
6126 5e3f878a pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
6127 5e3f878a pbrook
                    dead_tmp(tmp2);
6128 9ee6e8bb pbrook
                }
6129 5e3f878a pbrook
                store_reg(s, rd, tmp);
6130 9ee6e8bb pbrook
            } else {
6131 9ee6e8bb pbrook
                /* 16 * 16 */
6132 5e3f878a pbrook
                tmp = load_reg(s, rm);
6133 5e3f878a pbrook
                tmp2 = load_reg(s, rs);
6134 5e3f878a pbrook
                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6135 5e3f878a pbrook
                dead_tmp(tmp2);
6136 9ee6e8bb pbrook
                if (op1 == 2) {
6137 a7812ae4 pbrook
                    tmp64 = tcg_temp_new_i64();
6138 a7812ae4 pbrook
                    tcg_gen_ext_i32_i64(tmp64, tmp);
6139 22478e79 balrog
                    dead_tmp(tmp);
6140 a7812ae4 pbrook
                    gen_addq(s, tmp64, rn, rd);
6141 a7812ae4 pbrook
                    gen_storeq_reg(s, rn, rd, tmp64);
6142 9ee6e8bb pbrook
                } else {
6143 9ee6e8bb pbrook
                    if (op1 == 0) {
6144 5e3f878a pbrook
                        tmp2 = load_reg(s, rn);
6145 5e3f878a pbrook
                        gen_helper_add_setq(tmp, tmp, tmp2);
6146 5e3f878a pbrook
                        dead_tmp(tmp2);
6147 9ee6e8bb pbrook
                    }
6148 5e3f878a pbrook
                    store_reg(s, rd, tmp);
6149 9ee6e8bb pbrook
                }
6150 9ee6e8bb pbrook
            }
6151 9ee6e8bb pbrook
            break;
6152 9ee6e8bb pbrook
        default:
6153 9ee6e8bb pbrook
            goto illegal_op;
6154 9ee6e8bb pbrook
        }
6155 9ee6e8bb pbrook
    } else if (((insn & 0x0e000000) == 0 &&
6156 9ee6e8bb pbrook
                (insn & 0x00000090) != 0x90) ||
6157 9ee6e8bb pbrook
               ((insn & 0x0e000000) == (1 << 25))) {
6158 9ee6e8bb pbrook
        int set_cc, logic_cc, shiftop;
6159 9ee6e8bb pbrook
6160 9ee6e8bb pbrook
        op1 = (insn >> 21) & 0xf;
6161 9ee6e8bb pbrook
        set_cc = (insn >> 20) & 1;
6162 9ee6e8bb pbrook
        logic_cc = table_logic_cc[op1] & set_cc;
6163 9ee6e8bb pbrook
6164 9ee6e8bb pbrook
        /* data processing instruction */
6165 9ee6e8bb pbrook
        if (insn & (1 << 25)) {
6166 9ee6e8bb pbrook
            /* immediate operand */
6167 9ee6e8bb pbrook
            val = insn & 0xff;
6168 9ee6e8bb pbrook
            shift = ((insn >> 8) & 0xf) * 2;
6169 e9bb4aa9 Juha Riihimรคki
            if (shift) {
6170 9ee6e8bb pbrook
                val = (val >> shift) | (val << (32 - shift));
6171 e9bb4aa9 Juha Riihimรคki
            }
6172 e9bb4aa9 Juha Riihimรคki
            tmp2 = new_tmp();
6173 e9bb4aa9 Juha Riihimรคki
            tcg_gen_movi_i32(tmp2, val);
6174 e9bb4aa9 Juha Riihimรคki
            if (logic_cc && shift) {
6175 e9bb4aa9 Juha Riihimรคki
                gen_set_CF_bit31(tmp2);
6176 e9bb4aa9 Juha Riihimรคki
            }
6177 9ee6e8bb pbrook
        } else {
6178 9ee6e8bb pbrook
            /* register */
6179 9ee6e8bb pbrook
            rm = (insn) & 0xf;
6180 e9bb4aa9 Juha Riihimรคki
            tmp2 = load_reg(s, rm);
6181 9ee6e8bb pbrook
            shiftop = (insn >> 5) & 3;
6182 9ee6e8bb pbrook
            if (!(insn & (1 << 4))) {
6183 9ee6e8bb pbrook
                shift = (insn >> 7) & 0x1f;
6184 e9bb4aa9 Juha Riihimรคki
                gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6185 9ee6e8bb pbrook
            } else {
6186 9ee6e8bb pbrook
                rs = (insn >> 8) & 0xf;
6187 8984bd2e pbrook
                tmp = load_reg(s, rs);
6188 e9bb4aa9 Juha Riihimรคki
                gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6189 9ee6e8bb pbrook
            }
6190 9ee6e8bb pbrook
        }
6191 9ee6e8bb pbrook
        if (op1 != 0x0f && op1 != 0x0d) {
6192 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6193 e9bb4aa9 Juha Riihimรคki
            tmp = load_reg(s, rn);
6194 e9bb4aa9 Juha Riihimรคki
        } else {
6195 e9bb4aa9 Juha Riihimรคki
            TCGV_UNUSED(tmp);
6196 9ee6e8bb pbrook
        }
6197 9ee6e8bb pbrook
        rd = (insn >> 12) & 0xf;
6198 9ee6e8bb pbrook
        switch(op1) {
6199 9ee6e8bb pbrook
        case 0x00:
6200 e9bb4aa9 Juha Riihimรคki
            tcg_gen_and_i32(tmp, tmp, tmp2);
6201 e9bb4aa9 Juha Riihimรคki
            if (logic_cc) {
6202 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6203 e9bb4aa9 Juha Riihimรคki
            }
6204 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6205 9ee6e8bb pbrook
            break;
6206 9ee6e8bb pbrook
        case 0x01:
6207 e9bb4aa9 Juha Riihimรคki
            tcg_gen_xor_i32(tmp, tmp, tmp2);
6208 e9bb4aa9 Juha Riihimรคki
            if (logic_cc) {
6209 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6210 e9bb4aa9 Juha Riihimรคki
            }
6211 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6212 9ee6e8bb pbrook
            break;
6213 9ee6e8bb pbrook
        case 0x02:
6214 9ee6e8bb pbrook
            if (set_cc && rd == 15) {
6215 9ee6e8bb pbrook
                /* SUBS r15, ... is used for exception return.  */
6216 e9bb4aa9 Juha Riihimรคki
                if (IS_USER(s)) {
6217 9ee6e8bb pbrook
                    goto illegal_op;
6218 e9bb4aa9 Juha Riihimรคki
                }
6219 e9bb4aa9 Juha Riihimรคki
                gen_helper_sub_cc(tmp, tmp, tmp2);
6220 e9bb4aa9 Juha Riihimรคki
                gen_exception_return(s, tmp);
6221 9ee6e8bb pbrook
            } else {
6222 e9bb4aa9 Juha Riihimรคki
                if (set_cc) {
6223 e9bb4aa9 Juha Riihimรคki
                    gen_helper_sub_cc(tmp, tmp, tmp2);
6224 e9bb4aa9 Juha Riihimรคki
                } else {
6225 e9bb4aa9 Juha Riihimรคki
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
6226 e9bb4aa9 Juha Riihimรคki
                }
6227 21aeb343 Juha Riihimรคki
                store_reg_bx(env, s, rd, tmp);
6228 9ee6e8bb pbrook
            }
6229 9ee6e8bb pbrook
            break;
6230 9ee6e8bb pbrook
        case 0x03:
6231 e9bb4aa9 Juha Riihimรคki
            if (set_cc) {
6232 e9bb4aa9 Juha Riihimรคki
                gen_helper_sub_cc(tmp, tmp2, tmp);
6233 e9bb4aa9 Juha Riihimรคki
            } else {
6234 e9bb4aa9 Juha Riihimรคki
                tcg_gen_sub_i32(tmp, tmp2, tmp);
6235 e9bb4aa9 Juha Riihimรคki
            }
6236 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6237 9ee6e8bb pbrook
            break;
6238 9ee6e8bb pbrook
        case 0x04:
6239 e9bb4aa9 Juha Riihimรคki
            if (set_cc) {
6240 e9bb4aa9 Juha Riihimรคki
                gen_helper_add_cc(tmp, tmp, tmp2);
6241 e9bb4aa9 Juha Riihimรคki
            } else {
6242 e9bb4aa9 Juha Riihimรคki
                tcg_gen_add_i32(tmp, tmp, tmp2);
6243 e9bb4aa9 Juha Riihimรคki
            }
6244 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6245 9ee6e8bb pbrook
            break;
6246 9ee6e8bb pbrook
        case 0x05:
6247 e9bb4aa9 Juha Riihimรคki
            if (set_cc) {
6248 e9bb4aa9 Juha Riihimรคki
                gen_helper_adc_cc(tmp, tmp, tmp2);
6249 e9bb4aa9 Juha Riihimรคki
            } else {
6250 e9bb4aa9 Juha Riihimรคki
                gen_add_carry(tmp, tmp, tmp2);
6251 e9bb4aa9 Juha Riihimรคki
            }
6252 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6253 9ee6e8bb pbrook
            break;
6254 9ee6e8bb pbrook
        case 0x06:
6255 e9bb4aa9 Juha Riihimรคki
            if (set_cc) {
6256 e9bb4aa9 Juha Riihimรคki
                gen_helper_sbc_cc(tmp, tmp, tmp2);
6257 e9bb4aa9 Juha Riihimรคki
            } else {
6258 e9bb4aa9 Juha Riihimรคki
                gen_sub_carry(tmp, tmp, tmp2);
6259 e9bb4aa9 Juha Riihimรคki
            }
6260 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6261 9ee6e8bb pbrook
            break;
6262 9ee6e8bb pbrook
        case 0x07:
6263 e9bb4aa9 Juha Riihimรคki
            if (set_cc) {
6264 e9bb4aa9 Juha Riihimรคki
                gen_helper_sbc_cc(tmp, tmp2, tmp);
6265 e9bb4aa9 Juha Riihimรคki
            } else {
6266 e9bb4aa9 Juha Riihimรคki
                gen_sub_carry(tmp, tmp2, tmp);
6267 e9bb4aa9 Juha Riihimรคki
            }
6268 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6269 9ee6e8bb pbrook
            break;
6270 9ee6e8bb pbrook
        case 0x08:
6271 9ee6e8bb pbrook
            if (set_cc) {
6272 e9bb4aa9 Juha Riihimรคki
                tcg_gen_and_i32(tmp, tmp, tmp2);
6273 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6274 9ee6e8bb pbrook
            }
6275 e9bb4aa9 Juha Riihimรคki
            dead_tmp(tmp);
6276 9ee6e8bb pbrook
            break;
6277 9ee6e8bb pbrook
        case 0x09:
6278 9ee6e8bb pbrook
            if (set_cc) {
6279 e9bb4aa9 Juha Riihimรคki
                tcg_gen_xor_i32(tmp, tmp, tmp2);
6280 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6281 9ee6e8bb pbrook
            }
6282 e9bb4aa9 Juha Riihimรคki
            dead_tmp(tmp);
6283 9ee6e8bb pbrook
            break;
6284 9ee6e8bb pbrook
        case 0x0a:
6285 9ee6e8bb pbrook
            if (set_cc) {
6286 e9bb4aa9 Juha Riihimรคki
                gen_helper_sub_cc(tmp, tmp, tmp2);
6287 9ee6e8bb pbrook
            }
6288 e9bb4aa9 Juha Riihimรคki
            dead_tmp(tmp);
6289 9ee6e8bb pbrook
            break;
6290 9ee6e8bb pbrook
        case 0x0b:
6291 9ee6e8bb pbrook
            if (set_cc) {
6292 e9bb4aa9 Juha Riihimรคki
                gen_helper_add_cc(tmp, tmp, tmp2);
6293 9ee6e8bb pbrook
            }
6294 e9bb4aa9 Juha Riihimรคki
            dead_tmp(tmp);
6295 9ee6e8bb pbrook
            break;
6296 9ee6e8bb pbrook
        case 0x0c:
6297 e9bb4aa9 Juha Riihimรคki
            tcg_gen_or_i32(tmp, tmp, tmp2);
6298 e9bb4aa9 Juha Riihimรคki
            if (logic_cc) {
6299 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6300 e9bb4aa9 Juha Riihimรคki
            }
6301 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6302 9ee6e8bb pbrook
            break;
6303 9ee6e8bb pbrook
        case 0x0d:
6304 9ee6e8bb pbrook
            if (logic_cc && rd == 15) {
6305 9ee6e8bb pbrook
                /* MOVS r15, ... is used for exception return.  */
6306 e9bb4aa9 Juha Riihimรคki
                if (IS_USER(s)) {
6307 9ee6e8bb pbrook
                    goto illegal_op;
6308 e9bb4aa9 Juha Riihimรคki
                }
6309 e9bb4aa9 Juha Riihimรคki
                gen_exception_return(s, tmp2);
6310 9ee6e8bb pbrook
            } else {
6311 e9bb4aa9 Juha Riihimรคki
                if (logic_cc) {
6312 e9bb4aa9 Juha Riihimรคki
                    gen_logic_CC(tmp2);
6313 e9bb4aa9 Juha Riihimรคki
                }
6314 21aeb343 Juha Riihimรคki
                store_reg_bx(env, s, rd, tmp2);
6315 9ee6e8bb pbrook
            }
6316 9ee6e8bb pbrook
            break;
6317 9ee6e8bb pbrook
        case 0x0e:
6318 e9bb4aa9 Juha Riihimรคki
            tcg_gen_bic_i32(tmp, tmp, tmp2);
6319 e9bb4aa9 Juha Riihimรคki
            if (logic_cc) {
6320 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp);
6321 e9bb4aa9 Juha Riihimรคki
            }
6322 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
6323 9ee6e8bb pbrook
            break;
6324 9ee6e8bb pbrook
        default:
6325 9ee6e8bb pbrook
        case 0x0f:
6326 e9bb4aa9 Juha Riihimรคki
            tcg_gen_not_i32(tmp2, tmp2);
6327 e9bb4aa9 Juha Riihimรคki
            if (logic_cc) {
6328 e9bb4aa9 Juha Riihimรคki
                gen_logic_CC(tmp2);
6329 e9bb4aa9 Juha Riihimรคki
            }
6330 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp2);
6331 9ee6e8bb pbrook
            break;
6332 9ee6e8bb pbrook
        }
6333 e9bb4aa9 Juha Riihimรคki
        if (op1 != 0x0f && op1 != 0x0d) {
6334 e9bb4aa9 Juha Riihimรคki
            dead_tmp(tmp2);
6335 e9bb4aa9 Juha Riihimรคki
        }
6336 9ee6e8bb pbrook
    } else {
6337 9ee6e8bb pbrook
        /* other instructions */
6338 9ee6e8bb pbrook
        op1 = (insn >> 24) & 0xf;
6339 9ee6e8bb pbrook
        switch(op1) {
6340 9ee6e8bb pbrook
        case 0x0:
6341 9ee6e8bb pbrook
        case 0x1:
6342 9ee6e8bb pbrook
            /* multiplies, extra load/stores */
6343 9ee6e8bb pbrook
            sh = (insn >> 5) & 3;
6344 9ee6e8bb pbrook
            if (sh == 0) {
6345 9ee6e8bb pbrook
                if (op1 == 0x0) {
6346 9ee6e8bb pbrook
                    rd = (insn >> 16) & 0xf;
6347 9ee6e8bb pbrook
                    rn = (insn >> 12) & 0xf;
6348 9ee6e8bb pbrook
                    rs = (insn >> 8) & 0xf;
6349 9ee6e8bb pbrook
                    rm = (insn) & 0xf;
6350 9ee6e8bb pbrook
                    op1 = (insn >> 20) & 0xf;
6351 9ee6e8bb pbrook
                    switch (op1) {
6352 9ee6e8bb pbrook
                    case 0: case 1: case 2: case 3: case 6:
6353 9ee6e8bb pbrook
                        /* 32 bit mul */
6354 5e3f878a pbrook
                        tmp = load_reg(s, rs);
6355 5e3f878a pbrook
                        tmp2 = load_reg(s, rm);
6356 5e3f878a pbrook
                        tcg_gen_mul_i32(tmp, tmp, tmp2);
6357 5e3f878a pbrook
                        dead_tmp(tmp2);
6358 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
6359 9ee6e8bb pbrook
                            /* Subtract (mls) */
6360 9ee6e8bb pbrook
                            ARCH(6T2);
6361 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
6362 5e3f878a pbrook
                            tcg_gen_sub_i32(tmp, tmp2, tmp);
6363 5e3f878a pbrook
                            dead_tmp(tmp2);
6364 9ee6e8bb pbrook
                        } else if (insn & (1 << 21)) {
6365 9ee6e8bb pbrook
                            /* Add */
6366 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
6367 5e3f878a pbrook
                            tcg_gen_add_i32(tmp, tmp, tmp2);
6368 5e3f878a pbrook
                            dead_tmp(tmp2);
6369 9ee6e8bb pbrook
                        }
6370 9ee6e8bb pbrook
                        if (insn & (1 << 20))
6371 5e3f878a pbrook
                            gen_logic_CC(tmp);
6372 5e3f878a pbrook
                        store_reg(s, rd, tmp);
6373 9ee6e8bb pbrook
                        break;
6374 9ee6e8bb pbrook
                    default:
6375 9ee6e8bb pbrook
                        /* 64 bit mul */
6376 5e3f878a pbrook
                        tmp = load_reg(s, rs);
6377 5e3f878a pbrook
                        tmp2 = load_reg(s, rm);
6378 9ee6e8bb pbrook
                        if (insn & (1 << 22))
6379 a7812ae4 pbrook
                            tmp64 = gen_muls_i64_i32(tmp, tmp2);
6380 9ee6e8bb pbrook
                        else
6381 a7812ae4 pbrook
                            tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6382 9ee6e8bb pbrook
                        if (insn & (1 << 21)) /* mult accumulate */
6383 a7812ae4 pbrook
                            gen_addq(s, tmp64, rn, rd);
6384 9ee6e8bb pbrook
                        if (!(insn & (1 << 23))) { /* double accumulate */
6385 9ee6e8bb pbrook
                            ARCH(6);
6386 a7812ae4 pbrook
                            gen_addq_lo(s, tmp64, rn);
6387 a7812ae4 pbrook
                            gen_addq_lo(s, tmp64, rd);
6388 9ee6e8bb pbrook
                        }
6389 9ee6e8bb pbrook
                        if (insn & (1 << 20))
6390 a7812ae4 pbrook
                            gen_logicq_cc(tmp64);
6391 a7812ae4 pbrook
                        gen_storeq_reg(s, rn, rd, tmp64);
6392 9ee6e8bb pbrook
                        break;
6393 9ee6e8bb pbrook
                    }
6394 9ee6e8bb pbrook
                } else {
6395 9ee6e8bb pbrook
                    rn = (insn >> 16) & 0xf;
6396 9ee6e8bb pbrook
                    rd = (insn >> 12) & 0xf;
6397 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
6398 9ee6e8bb pbrook
                        /* load/store exclusive */
6399 86753403 pbrook
                        op1 = (insn >> 21) & 0x3;
6400 86753403 pbrook
                        if (op1)
6401 a47f43d2 pbrook
                            ARCH(6K);
6402 86753403 pbrook
                        else
6403 86753403 pbrook
                            ARCH(6);
6404 3174f8e9 Filip Navara
                        addr = tcg_temp_local_new_i32();
6405 3174f8e9 Filip Navara
                        tcg_gen_mov_i32(addr, cpu_R[rn]);
6406 9ee6e8bb pbrook
                        if (insn & (1 << 20)) {
6407 3174f8e9 Filip Navara
                            gen_helper_mark_exclusive(cpu_env, addr);
6408 86753403 pbrook
                            switch (op1) {
6409 86753403 pbrook
                            case 0: /* ldrex */
6410 86753403 pbrook
                                tmp = gen_ld32(addr, IS_USER(s));
6411 86753403 pbrook
                                break;
6412 86753403 pbrook
                            case 1: /* ldrexd */
6413 86753403 pbrook
                                tmp = gen_ld32(addr, IS_USER(s));
6414 86753403 pbrook
                                store_reg(s, rd, tmp);
6415 86753403 pbrook
                                tcg_gen_addi_i32(addr, addr, 4);
6416 86753403 pbrook
                                tmp = gen_ld32(addr, IS_USER(s));
6417 86753403 pbrook
                                rd++;
6418 86753403 pbrook
                                break;
6419 86753403 pbrook
                            case 2: /* ldrexb */
6420 86753403 pbrook
                                tmp = gen_ld8u(addr, IS_USER(s));
6421 86753403 pbrook
                                break;
6422 86753403 pbrook
                            case 3: /* ldrexh */
6423 86753403 pbrook
                                tmp = gen_ld16u(addr, IS_USER(s));
6424 86753403 pbrook
                                break;
6425 86753403 pbrook
                            default:
6426 86753403 pbrook
                                abort();
6427 86753403 pbrook
                            }
6428 8f8e3aa4 pbrook
                            store_reg(s, rd, tmp);
6429 9ee6e8bb pbrook
                        } else {
6430 8f8e3aa4 pbrook
                            int label = gen_new_label();
6431 9ee6e8bb pbrook
                            rm = insn & 0xf;
6432 3174f8e9 Filip Navara
                            tmp2 = tcg_temp_local_new_i32();
6433 3174f8e9 Filip Navara
                            gen_helper_test_exclusive(tmp2, cpu_env, addr);
6434 3174f8e9 Filip Navara
                            tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6435 8f8e3aa4 pbrook
                            tmp = load_reg(s,rm);
6436 86753403 pbrook
                            switch (op1) {
6437 86753403 pbrook
                            case 0:  /*  strex */
6438 86753403 pbrook
                                gen_st32(tmp, addr, IS_USER(s));
6439 86753403 pbrook
                                break;
6440 86753403 pbrook
                            case 1: /*  strexd */
6441 86753403 pbrook
                                gen_st32(tmp, addr, IS_USER(s));
6442 86753403 pbrook
                                tcg_gen_addi_i32(addr, addr, 4);
6443 86753403 pbrook
                                tmp = load_reg(s, rm + 1);
6444 86753403 pbrook
                                gen_st32(tmp, addr, IS_USER(s));
6445 86753403 pbrook
                                break;
6446 86753403 pbrook
                            case 2: /*  strexb */
6447 86753403 pbrook
                                gen_st8(tmp, addr, IS_USER(s));
6448 86753403 pbrook
                                break;
6449 86753403 pbrook
                            case 3: /* strexh */
6450 86753403 pbrook
                                gen_st16(tmp, addr, IS_USER(s));
6451 86753403 pbrook
                                break;
6452 86753403 pbrook
                            default:
6453 86753403 pbrook
                                abort();
6454 86753403 pbrook
                            }
6455 2637a3be balrog
                            gen_set_label(label);
6456 3174f8e9 Filip Navara
                            tcg_gen_mov_i32(cpu_R[rd], tmp2);
6457 3174f8e9 Filip Navara
                            tcg_temp_free(tmp2);
6458 9ee6e8bb pbrook
                        }
6459 3174f8e9 Filip Navara
                        tcg_temp_free(addr);
6460 9ee6e8bb pbrook
                    } else {
6461 9ee6e8bb pbrook
                        /* SWP instruction */
6462 9ee6e8bb pbrook
                        rm = (insn) & 0xf;
6463 9ee6e8bb pbrook
6464 8984bd2e pbrook
                        /* ??? This is not really atomic.  However we know
6465 8984bd2e pbrook
                           we never have multiple CPUs running in parallel,
6466 8984bd2e pbrook
                           so it is good enough.  */
6467 8984bd2e pbrook
                        addr = load_reg(s, rn);
6468 8984bd2e pbrook
                        tmp = load_reg(s, rm);
6469 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
6470 8984bd2e pbrook
                            tmp2 = gen_ld8u(addr, IS_USER(s));
6471 8984bd2e pbrook
                            gen_st8(tmp, addr, IS_USER(s));
6472 9ee6e8bb pbrook
                        } else {
6473 8984bd2e pbrook
                            tmp2 = gen_ld32(addr, IS_USER(s));
6474 8984bd2e pbrook
                            gen_st32(tmp, addr, IS_USER(s));
6475 9ee6e8bb pbrook
                        }
6476 8984bd2e pbrook
                        dead_tmp(addr);
6477 8984bd2e pbrook
                        store_reg(s, rd, tmp2);
6478 9ee6e8bb pbrook
                    }
6479 9ee6e8bb pbrook
                }
6480 9ee6e8bb pbrook
            } else {
6481 9ee6e8bb pbrook
                int address_offset;
6482 9ee6e8bb pbrook
                int load;
6483 9ee6e8bb pbrook
                /* Misc load/store */
6484 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
6485 9ee6e8bb pbrook
                rd = (insn >> 12) & 0xf;
6486 b0109805 pbrook
                addr = load_reg(s, rn);
6487 9ee6e8bb pbrook
                if (insn & (1 << 24))
6488 b0109805 pbrook
                    gen_add_datah_offset(s, insn, 0, addr);
6489 9ee6e8bb pbrook
                address_offset = 0;
6490 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
6491 9ee6e8bb pbrook
                    /* load */
6492 9ee6e8bb pbrook
                    switch(sh) {
6493 9ee6e8bb pbrook
                    case 1:
6494 b0109805 pbrook
                        tmp = gen_ld16u(addr, IS_USER(s));
6495 9ee6e8bb pbrook
                        break;
6496 9ee6e8bb pbrook
                    case 2:
6497 b0109805 pbrook
                        tmp = gen_ld8s(addr, IS_USER(s));
6498 9ee6e8bb pbrook
                        break;
6499 9ee6e8bb pbrook
                    default:
6500 9ee6e8bb pbrook
                    case 3:
6501 b0109805 pbrook
                        tmp = gen_ld16s(addr, IS_USER(s));
6502 9ee6e8bb pbrook
                        break;
6503 9ee6e8bb pbrook
                    }
6504 9ee6e8bb pbrook
                    load = 1;
6505 9ee6e8bb pbrook
                } else if (sh & 2) {
6506 9ee6e8bb pbrook
                    /* doubleword */
6507 9ee6e8bb pbrook
                    if (sh & 1) {
6508 9ee6e8bb pbrook
                        /* store */
6509 b0109805 pbrook
                        tmp = load_reg(s, rd);
6510 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
6511 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
6512 b0109805 pbrook
                        tmp = load_reg(s, rd + 1);
6513 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
6514 9ee6e8bb pbrook
                        load = 0;
6515 9ee6e8bb pbrook
                    } else {
6516 9ee6e8bb pbrook
                        /* load */
6517 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
6518 b0109805 pbrook
                        store_reg(s, rd, tmp);
6519 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
6520 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
6521 9ee6e8bb pbrook
                        rd++;
6522 9ee6e8bb pbrook
                        load = 1;
6523 9ee6e8bb pbrook
                    }
6524 9ee6e8bb pbrook
                    address_offset = -4;
6525 9ee6e8bb pbrook
                } else {
6526 9ee6e8bb pbrook
                    /* store */
6527 b0109805 pbrook
                    tmp = load_reg(s, rd);
6528 b0109805 pbrook
                    gen_st16(tmp, addr, IS_USER(s));
6529 9ee6e8bb pbrook
                    load = 0;
6530 9ee6e8bb pbrook
                }
6531 9ee6e8bb pbrook
                /* Perform base writeback before the loaded value to
6532 9ee6e8bb pbrook
                   ensure correct behavior with overlapping index registers.
6533 9ee6e8bb pbrook
                   ldrd with base writeback is is undefined if the
6534 9ee6e8bb pbrook
                   destination and index registers overlap.  */
6535 9ee6e8bb pbrook
                if (!(insn & (1 << 24))) {
6536 b0109805 pbrook
                    gen_add_datah_offset(s, insn, address_offset, addr);
6537 b0109805 pbrook
                    store_reg(s, rn, addr);
6538 9ee6e8bb pbrook
                } else if (insn & (1 << 21)) {
6539 9ee6e8bb pbrook
                    if (address_offset)
6540 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, address_offset);
6541 b0109805 pbrook
                    store_reg(s, rn, addr);
6542 b0109805 pbrook
                } else {
6543 b0109805 pbrook
                    dead_tmp(addr);
6544 9ee6e8bb pbrook
                }
6545 9ee6e8bb pbrook
                if (load) {
6546 9ee6e8bb pbrook
                    /* Complete the load.  */
6547 b0109805 pbrook
                    store_reg(s, rd, tmp);
6548 9ee6e8bb pbrook
                }
6549 9ee6e8bb pbrook
            }
6550 9ee6e8bb pbrook
            break;
6551 9ee6e8bb pbrook
        case 0x4:
6552 9ee6e8bb pbrook
        case 0x5:
6553 9ee6e8bb pbrook
            goto do_ldst;
6554 9ee6e8bb pbrook
        case 0x6:
6555 9ee6e8bb pbrook
        case 0x7:
6556 9ee6e8bb pbrook
            if (insn & (1 << 4)) {
6557 9ee6e8bb pbrook
                ARCH(6);
6558 9ee6e8bb pbrook
                /* Armv6 Media instructions.  */
6559 9ee6e8bb pbrook
                rm = insn & 0xf;
6560 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
6561 2c0262af bellard
                rd = (insn >> 12) & 0xf;
6562 9ee6e8bb pbrook
                rs = (insn >> 8) & 0xf;
6563 9ee6e8bb pbrook
                switch ((insn >> 23) & 3) {
6564 9ee6e8bb pbrook
                case 0: /* Parallel add/subtract.  */
6565 9ee6e8bb pbrook
                    op1 = (insn >> 20) & 7;
6566 6ddbc6e4 pbrook
                    tmp = load_reg(s, rn);
6567 6ddbc6e4 pbrook
                    tmp2 = load_reg(s, rm);
6568 9ee6e8bb pbrook
                    sh = (insn >> 5) & 7;
6569 9ee6e8bb pbrook
                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6570 9ee6e8bb pbrook
                        goto illegal_op;
6571 6ddbc6e4 pbrook
                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6572 6ddbc6e4 pbrook
                    dead_tmp(tmp2);
6573 6ddbc6e4 pbrook
                    store_reg(s, rd, tmp);
6574 9ee6e8bb pbrook
                    break;
6575 9ee6e8bb pbrook
                case 1:
6576 9ee6e8bb pbrook
                    if ((insn & 0x00700020) == 0) {
6577 6c95676b balrog
                        /* Halfword pack.  */
6578 3670669c pbrook
                        tmp = load_reg(s, rn);
6579 3670669c pbrook
                        tmp2 = load_reg(s, rm);
6580 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
6581 3670669c pbrook
                        if (insn & (1 << 6)) {
6582 3670669c pbrook
                            /* pkhtb */
6583 22478e79 balrog
                            if (shift == 0)
6584 22478e79 balrog
                                shift = 31;
6585 22478e79 balrog
                            tcg_gen_sari_i32(tmp2, tmp2, shift);
6586 3670669c pbrook
                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6587 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp2, tmp2);
6588 3670669c pbrook
                        } else {
6589 3670669c pbrook
                            /* pkhbt */
6590 22478e79 balrog
                            if (shift)
6591 22478e79 balrog
                                tcg_gen_shli_i32(tmp2, tmp2, shift);
6592 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp, tmp);
6593 3670669c pbrook
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6594 3670669c pbrook
                        }
6595 3670669c pbrook
                        tcg_gen_or_i32(tmp, tmp, tmp2);
6596 22478e79 balrog
                        dead_tmp(tmp2);
6597 3670669c pbrook
                        store_reg(s, rd, tmp);
6598 9ee6e8bb pbrook
                    } else if ((insn & 0x00200020) == 0x00200000) {
6599 9ee6e8bb pbrook
                        /* [us]sat */
6600 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
6601 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
6602 9ee6e8bb pbrook
                        if (insn & (1 << 6)) {
6603 9ee6e8bb pbrook
                            if (shift == 0)
6604 9ee6e8bb pbrook
                                shift = 31;
6605 6ddbc6e4 pbrook
                            tcg_gen_sari_i32(tmp, tmp, shift);
6606 9ee6e8bb pbrook
                        } else {
6607 6ddbc6e4 pbrook
                            tcg_gen_shli_i32(tmp, tmp, shift);
6608 9ee6e8bb pbrook
                        }
6609 9ee6e8bb pbrook
                        sh = (insn >> 16) & 0x1f;
6610 9ee6e8bb pbrook
                        if (sh != 0) {
6611 9ee6e8bb pbrook
                            if (insn & (1 << 22))
6612 6ddbc6e4 pbrook
                                gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6613 9ee6e8bb pbrook
                            else
6614 6ddbc6e4 pbrook
                                gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6615 9ee6e8bb pbrook
                        }
6616 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
6617 9ee6e8bb pbrook
                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
6618 9ee6e8bb pbrook
                        /* [us]sat16 */
6619 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
6620 9ee6e8bb pbrook
                        sh = (insn >> 16) & 0x1f;
6621 9ee6e8bb pbrook
                        if (sh != 0) {
6622 9ee6e8bb pbrook
                            if (insn & (1 << 22))
6623 6ddbc6e4 pbrook
                                gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6624 9ee6e8bb pbrook
                            else
6625 6ddbc6e4 pbrook
                                gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6626 9ee6e8bb pbrook
                        }
6627 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
6628 9ee6e8bb pbrook
                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6629 9ee6e8bb pbrook
                        /* Select bytes.  */
6630 6ddbc6e4 pbrook
                        tmp = load_reg(s, rn);
6631 6ddbc6e4 pbrook
                        tmp2 = load_reg(s, rm);
6632 6ddbc6e4 pbrook
                        tmp3 = new_tmp();
6633 6ddbc6e4 pbrook
                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6634 6ddbc6e4 pbrook
                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6635 6ddbc6e4 pbrook
                        dead_tmp(tmp3);
6636 6ddbc6e4 pbrook
                        dead_tmp(tmp2);
6637 6ddbc6e4 pbrook
                        store_reg(s, rd, tmp);
6638 9ee6e8bb pbrook
                    } else if ((insn & 0x000003e0) == 0x00000060) {
6639 5e3f878a pbrook
                        tmp = load_reg(s, rm);
6640 9ee6e8bb pbrook
                        shift = (insn >> 10) & 3;
6641 9ee6e8bb pbrook
                        /* ??? In many cases it's not neccessary to do a
6642 9ee6e8bb pbrook
                           rotate, a shift is sufficient.  */
6643 9ee6e8bb pbrook
                        if (shift != 0)
6644 5e3f878a pbrook
                            tcg_gen_rori_i32(tmp, tmp, shift * 8);
6645 9ee6e8bb pbrook
                        op1 = (insn >> 20) & 7;
6646 9ee6e8bb pbrook
                        switch (op1) {
6647 5e3f878a pbrook
                        case 0: gen_sxtb16(tmp);  break;
6648 5e3f878a pbrook
                        case 2: gen_sxtb(tmp);    break;
6649 5e3f878a pbrook
                        case 3: gen_sxth(tmp);    break;
6650 5e3f878a pbrook
                        case 4: gen_uxtb16(tmp);  break;
6651 5e3f878a pbrook
                        case 6: gen_uxtb(tmp);    break;
6652 5e3f878a pbrook
                        case 7: gen_uxth(tmp);    break;
6653 9ee6e8bb pbrook
                        default: goto illegal_op;
6654 9ee6e8bb pbrook
                        }
6655 9ee6e8bb pbrook
                        if (rn != 15) {
6656 5e3f878a pbrook
                            tmp2 = load_reg(s, rn);
6657 9ee6e8bb pbrook
                            if ((op1 & 3) == 0) {
6658 5e3f878a pbrook
                                gen_add16(tmp, tmp2);
6659 9ee6e8bb pbrook
                            } else {
6660 5e3f878a pbrook
                                tcg_gen_add_i32(tmp, tmp, tmp2);
6661 5e3f878a pbrook
                                dead_tmp(tmp2);
6662 9ee6e8bb pbrook
                            }
6663 9ee6e8bb pbrook
                        }
6664 6c95676b balrog
                        store_reg(s, rd, tmp);
6665 9ee6e8bb pbrook
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6666 9ee6e8bb pbrook
                        /* rev */
6667 b0109805 pbrook
                        tmp = load_reg(s, rm);
6668 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
6669 9ee6e8bb pbrook
                            if (insn & (1 << 7)) {
6670 b0109805 pbrook
                                gen_revsh(tmp);
6671 9ee6e8bb pbrook
                            } else {
6672 9ee6e8bb pbrook
                                ARCH(6T2);
6673 b0109805 pbrook
                                gen_helper_rbit(tmp, tmp);
6674 9ee6e8bb pbrook
                            }
6675 9ee6e8bb pbrook
                        } else {
6676 9ee6e8bb pbrook
                            if (insn & (1 << 7))
6677 b0109805 pbrook
                                gen_rev16(tmp);
6678 9ee6e8bb pbrook
                            else
6679 66896cb8 aurel32
                                tcg_gen_bswap32_i32(tmp, tmp);
6680 9ee6e8bb pbrook
                        }
6681 b0109805 pbrook
                        store_reg(s, rd, tmp);
6682 9ee6e8bb pbrook
                    } else {
6683 9ee6e8bb pbrook
                        goto illegal_op;
6684 9ee6e8bb pbrook
                    }
6685 9ee6e8bb pbrook
                    break;
6686 9ee6e8bb pbrook
                case 2: /* Multiplies (Type 3).  */
6687 5e3f878a pbrook
                    tmp = load_reg(s, rm);
6688 5e3f878a pbrook
                    tmp2 = load_reg(s, rs);
6689 9ee6e8bb pbrook
                    if (insn & (1 << 20)) {
6690 9ee6e8bb pbrook
                        /* Signed multiply most significant [accumulate].  */
6691 a7812ae4 pbrook
                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
6692 9ee6e8bb pbrook
                        if (insn & (1 << 5))
6693 a7812ae4 pbrook
                            tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6694 a7812ae4 pbrook
                        tcg_gen_shri_i64(tmp64, tmp64, 32);
6695 5e3f878a pbrook
                        tmp = new_tmp();
6696 a7812ae4 pbrook
                        tcg_gen_trunc_i64_i32(tmp, tmp64);
6697 955a7dd5 balrog
                        if (rd != 15) {
6698 955a7dd5 balrog
                            tmp2 = load_reg(s, rd);
6699 9ee6e8bb pbrook
                            if (insn & (1 << 6)) {
6700 5e3f878a pbrook
                                tcg_gen_sub_i32(tmp, tmp, tmp2);
6701 9ee6e8bb pbrook
                            } else {
6702 5e3f878a pbrook
                                tcg_gen_add_i32(tmp, tmp, tmp2);
6703 9ee6e8bb pbrook
                            }
6704 5e3f878a pbrook
                            dead_tmp(tmp2);
6705 9ee6e8bb pbrook
                        }
6706 955a7dd5 balrog
                        store_reg(s, rn, tmp);
6707 9ee6e8bb pbrook
                    } else {
6708 9ee6e8bb pbrook
                        if (insn & (1 << 5))
6709 5e3f878a pbrook
                            gen_swap_half(tmp2);
6710 5e3f878a pbrook
                        gen_smul_dual(tmp, tmp2);
6711 5e3f878a pbrook
                        /* This addition cannot overflow.  */
6712 5e3f878a pbrook
                        if (insn & (1 << 6)) {
6713 5e3f878a pbrook
                            tcg_gen_sub_i32(tmp, tmp, tmp2);
6714 5e3f878a pbrook
                        } else {
6715 5e3f878a pbrook
                            tcg_gen_add_i32(tmp, tmp, tmp2);
6716 5e3f878a pbrook
                        }
6717 5e3f878a pbrook
                        dead_tmp(tmp2);
6718 9ee6e8bb pbrook
                        if (insn & (1 << 22)) {
6719 5e3f878a pbrook
                            /* smlald, smlsld */
6720 a7812ae4 pbrook
                            tmp64 = tcg_temp_new_i64();
6721 a7812ae4 pbrook
                            tcg_gen_ext_i32_i64(tmp64, tmp);
6722 5e3f878a pbrook
                            dead_tmp(tmp);
6723 a7812ae4 pbrook
                            gen_addq(s, tmp64, rd, rn);
6724 a7812ae4 pbrook
                            gen_storeq_reg(s, rd, rn, tmp64);
6725 9ee6e8bb pbrook
                        } else {
6726 5e3f878a pbrook
                            /* smuad, smusd, smlad, smlsd */
6727 22478e79 balrog
                            if (rd != 15)
6728 9ee6e8bb pbrook
                              {
6729 22478e79 balrog
                                tmp2 = load_reg(s, rd);
6730 5e3f878a pbrook
                                gen_helper_add_setq(tmp, tmp, tmp2);
6731 5e3f878a pbrook
                                dead_tmp(tmp2);
6732 9ee6e8bb pbrook
                              }
6733 22478e79 balrog
                            store_reg(s, rn, tmp);
6734 9ee6e8bb pbrook
                        }
6735 9ee6e8bb pbrook
                    }
6736 9ee6e8bb pbrook
                    break;
6737 9ee6e8bb pbrook
                case 3:
6738 9ee6e8bb pbrook
                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6739 9ee6e8bb pbrook
                    switch (op1) {
6740 9ee6e8bb pbrook
                    case 0: /* Unsigned sum of absolute differences.  */
6741 6ddbc6e4 pbrook
                        ARCH(6);
6742 6ddbc6e4 pbrook
                        tmp = load_reg(s, rm);
6743 6ddbc6e4 pbrook
                        tmp2 = load_reg(s, rs);
6744 6ddbc6e4 pbrook
                        gen_helper_usad8(tmp, tmp, tmp2);
6745 6ddbc6e4 pbrook
                        dead_tmp(tmp2);
6746 ded9d295 balrog
                        if (rd != 15) {
6747 ded9d295 balrog
                            tmp2 = load_reg(s, rd);
6748 6ddbc6e4 pbrook
                            tcg_gen_add_i32(tmp, tmp, tmp2);
6749 6ddbc6e4 pbrook
                            dead_tmp(tmp2);
6750 9ee6e8bb pbrook
                        }
6751 ded9d295 balrog
                        store_reg(s, rn, tmp);
6752 9ee6e8bb pbrook
                        break;
6753 9ee6e8bb pbrook
                    case 0x20: case 0x24: case 0x28: case 0x2c:
6754 9ee6e8bb pbrook
                        /* Bitfield insert/clear.  */
6755 9ee6e8bb pbrook
                        ARCH(6T2);
6756 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
6757 9ee6e8bb pbrook
                        i = (insn >> 16) & 0x1f;
6758 9ee6e8bb pbrook
                        i = i + 1 - shift;
6759 9ee6e8bb pbrook
                        if (rm == 15) {
6760 5e3f878a pbrook
                            tmp = new_tmp();
6761 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, 0);
6762 9ee6e8bb pbrook
                        } else {
6763 5e3f878a pbrook
                            tmp = load_reg(s, rm);
6764 9ee6e8bb pbrook
                        }
6765 9ee6e8bb pbrook
                        if (i != 32) {
6766 5e3f878a pbrook
                            tmp2 = load_reg(s, rd);
6767 8f8e3aa4 pbrook
                            gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6768 5e3f878a pbrook
                            dead_tmp(tmp2);
6769 9ee6e8bb pbrook
                        }
6770 5e3f878a pbrook
                        store_reg(s, rd, tmp);
6771 9ee6e8bb pbrook
                        break;
6772 9ee6e8bb pbrook
                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6773 9ee6e8bb pbrook
                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6774 4cc633c3 balrog
                        ARCH(6T2);
6775 5e3f878a pbrook
                        tmp = load_reg(s, rm);
6776 9ee6e8bb pbrook
                        shift = (insn >> 7) & 0x1f;
6777 9ee6e8bb pbrook
                        i = ((insn >> 16) & 0x1f) + 1;
6778 9ee6e8bb pbrook
                        if (shift + i > 32)
6779 9ee6e8bb pbrook
                            goto illegal_op;
6780 9ee6e8bb pbrook
                        if (i < 32) {
6781 9ee6e8bb pbrook
                            if (op1 & 0x20) {
6782 5e3f878a pbrook
                                gen_ubfx(tmp, shift, (1u << i) - 1);
6783 9ee6e8bb pbrook
                            } else {
6784 5e3f878a pbrook
                                gen_sbfx(tmp, shift, i);
6785 9ee6e8bb pbrook
                            }
6786 9ee6e8bb pbrook
                        }
6787 5e3f878a pbrook
                        store_reg(s, rd, tmp);
6788 9ee6e8bb pbrook
                        break;
6789 9ee6e8bb pbrook
                    default:
6790 9ee6e8bb pbrook
                        goto illegal_op;
6791 9ee6e8bb pbrook
                    }
6792 9ee6e8bb pbrook
                    break;
6793 9ee6e8bb pbrook
                }
6794 9ee6e8bb pbrook
                break;
6795 9ee6e8bb pbrook
            }
6796 9ee6e8bb pbrook
        do_ldst:
6797 9ee6e8bb pbrook
            /* Check for undefined extension instructions
6798 9ee6e8bb pbrook
             * per the ARM Bible IE:
6799 9ee6e8bb pbrook
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
6800 9ee6e8bb pbrook
             */
6801 9ee6e8bb pbrook
            sh = (0xf << 20) | (0xf << 4);
6802 9ee6e8bb pbrook
            if (op1 == 0x7 && ((insn & sh) == sh))
6803 9ee6e8bb pbrook
            {
6804 9ee6e8bb pbrook
                goto illegal_op;
6805 9ee6e8bb pbrook
            }
6806 9ee6e8bb pbrook
            /* load/store byte/word */
6807 9ee6e8bb pbrook
            rn = (insn >> 16) & 0xf;
6808 9ee6e8bb pbrook
            rd = (insn >> 12) & 0xf;
6809 b0109805 pbrook
            tmp2 = load_reg(s, rn);
6810 9ee6e8bb pbrook
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6811 9ee6e8bb pbrook
            if (insn & (1 << 24))
6812 b0109805 pbrook
                gen_add_data_offset(s, insn, tmp2);
6813 9ee6e8bb pbrook
            if (insn & (1 << 20)) {
6814 9ee6e8bb pbrook
                /* load */
6815 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
6816 b0109805 pbrook
                    tmp = gen_ld8u(tmp2, i);
6817 9ee6e8bb pbrook
                } else {
6818 b0109805 pbrook
                    tmp = gen_ld32(tmp2, i);
6819 9ee6e8bb pbrook
                }
6820 9ee6e8bb pbrook
            } else {
6821 9ee6e8bb pbrook
                /* store */
6822 b0109805 pbrook
                tmp = load_reg(s, rd);
6823 9ee6e8bb pbrook
                if (insn & (1 << 22))
6824 b0109805 pbrook
                    gen_st8(tmp, tmp2, i);
6825 9ee6e8bb pbrook
                else
6826 b0109805 pbrook
                    gen_st32(tmp, tmp2, i);
6827 9ee6e8bb pbrook
            }
6828 9ee6e8bb pbrook
            if (!(insn & (1 << 24))) {
6829 b0109805 pbrook
                gen_add_data_offset(s, insn, tmp2);
6830 b0109805 pbrook
                store_reg(s, rn, tmp2);
6831 b0109805 pbrook
            } else if (insn & (1 << 21)) {
6832 b0109805 pbrook
                store_reg(s, rn, tmp2);
6833 b0109805 pbrook
            } else {
6834 b0109805 pbrook
                dead_tmp(tmp2);
6835 9ee6e8bb pbrook
            }
6836 9ee6e8bb pbrook
            if (insn & (1 << 20)) {
6837 9ee6e8bb pbrook
                /* Complete the load.  */
6838 9ee6e8bb pbrook
                if (rd == 15)
6839 b0109805 pbrook
                    gen_bx(s, tmp);
6840 9ee6e8bb pbrook
                else
6841 b0109805 pbrook
                    store_reg(s, rd, tmp);
6842 9ee6e8bb pbrook
            }
6843 9ee6e8bb pbrook
            break;
6844 9ee6e8bb pbrook
        case 0x08:
6845 9ee6e8bb pbrook
        case 0x09:
6846 9ee6e8bb pbrook
            {
6847 9ee6e8bb pbrook
                int j, n, user, loaded_base;
6848 b0109805 pbrook
                TCGv loaded_var;
6849 9ee6e8bb pbrook
                /* load/store multiple words */
6850 9ee6e8bb pbrook
                /* XXX: store correct base if write back */
6851 9ee6e8bb pbrook
                user = 0;
6852 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
6853 9ee6e8bb pbrook
                    if (IS_USER(s))
6854 9ee6e8bb pbrook
                        goto illegal_op; /* only usable in supervisor mode */
6855 9ee6e8bb pbrook
6856 9ee6e8bb pbrook
                    if ((insn & (1 << 15)) == 0)
6857 9ee6e8bb pbrook
                        user = 1;
6858 9ee6e8bb pbrook
                }
6859 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
6860 b0109805 pbrook
                addr = load_reg(s, rn);
6861 9ee6e8bb pbrook
6862 9ee6e8bb pbrook
                /* compute total size */
6863 9ee6e8bb pbrook
                loaded_base = 0;
6864 a50f5b91 pbrook
                TCGV_UNUSED(loaded_var);
6865 9ee6e8bb pbrook
                n = 0;
6866 9ee6e8bb pbrook
                for(i=0;i<16;i++) {
6867 9ee6e8bb pbrook
                    if (insn & (1 << i))
6868 9ee6e8bb pbrook
                        n++;
6869 9ee6e8bb pbrook
                }
6870 9ee6e8bb pbrook
                /* XXX: test invalid n == 0 case ? */
6871 9ee6e8bb pbrook
                if (insn & (1 << 23)) {
6872 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
6873 9ee6e8bb pbrook
                        /* pre increment */
6874 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
6875 9ee6e8bb pbrook
                    } else {
6876 9ee6e8bb pbrook
                        /* post increment */
6877 9ee6e8bb pbrook
                    }
6878 9ee6e8bb pbrook
                } else {
6879 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
6880 9ee6e8bb pbrook
                        /* pre decrement */
6881 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -(n * 4));
6882 9ee6e8bb pbrook
                    } else {
6883 9ee6e8bb pbrook
                        /* post decrement */
6884 9ee6e8bb pbrook
                        if (n != 1)
6885 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6886 9ee6e8bb pbrook
                    }
6887 9ee6e8bb pbrook
                }
6888 9ee6e8bb pbrook
                j = 0;
6889 9ee6e8bb pbrook
                for(i=0;i<16;i++) {
6890 9ee6e8bb pbrook
                    if (insn & (1 << i)) {
6891 9ee6e8bb pbrook
                        if (insn & (1 << 20)) {
6892 9ee6e8bb pbrook
                            /* load */
6893 b0109805 pbrook
                            tmp = gen_ld32(addr, IS_USER(s));
6894 9ee6e8bb pbrook
                            if (i == 15) {
6895 b0109805 pbrook
                                gen_bx(s, tmp);
6896 9ee6e8bb pbrook
                            } else if (user) {
6897 b0109805 pbrook
                                gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6898 b0109805 pbrook
                                dead_tmp(tmp);
6899 9ee6e8bb pbrook
                            } else if (i == rn) {
6900 b0109805 pbrook
                                loaded_var = tmp;
6901 9ee6e8bb pbrook
                                loaded_base = 1;
6902 9ee6e8bb pbrook
                            } else {
6903 b0109805 pbrook
                                store_reg(s, i, tmp);
6904 9ee6e8bb pbrook
                            }
6905 9ee6e8bb pbrook
                        } else {
6906 9ee6e8bb pbrook
                            /* store */
6907 9ee6e8bb pbrook
                            if (i == 15) {
6908 9ee6e8bb pbrook
                                /* special case: r15 = PC + 8 */
6909 9ee6e8bb pbrook
                                val = (long)s->pc + 4;
6910 b0109805 pbrook
                                tmp = new_tmp();
6911 b0109805 pbrook
                                tcg_gen_movi_i32(tmp, val);
6912 9ee6e8bb pbrook
                            } else if (user) {
6913 b0109805 pbrook
                                tmp = new_tmp();
6914 b0109805 pbrook
                                gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6915 9ee6e8bb pbrook
                            } else {
6916 b0109805 pbrook
                                tmp = load_reg(s, i);
6917 9ee6e8bb pbrook
                            }
6918 b0109805 pbrook
                            gen_st32(tmp, addr, IS_USER(s));
6919 9ee6e8bb pbrook
                        }
6920 9ee6e8bb pbrook
                        j++;
6921 9ee6e8bb pbrook
                        /* no need to add after the last transfer */
6922 9ee6e8bb pbrook
                        if (j != n)
6923 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
6924 9ee6e8bb pbrook
                    }
6925 9ee6e8bb pbrook
                }
6926 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
6927 9ee6e8bb pbrook
                    /* write back */
6928 9ee6e8bb pbrook
                    if (insn & (1 << 23)) {
6929 9ee6e8bb pbrook
                        if (insn & (1 << 24)) {
6930 9ee6e8bb pbrook
                            /* pre increment */
6931 9ee6e8bb pbrook
                        } else {
6932 9ee6e8bb pbrook
                            /* post increment */
6933 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
6934 9ee6e8bb pbrook
                        }
6935 9ee6e8bb pbrook
                    } else {
6936 9ee6e8bb pbrook
                        if (insn & (1 << 24)) {
6937 9ee6e8bb pbrook
                            /* pre decrement */
6938 9ee6e8bb pbrook
                            if (n != 1)
6939 b0109805 pbrook
                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6940 9ee6e8bb pbrook
                        } else {
6941 9ee6e8bb pbrook
                            /* post decrement */
6942 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -(n * 4));
6943 9ee6e8bb pbrook
                        }
6944 9ee6e8bb pbrook
                    }
6945 b0109805 pbrook
                    store_reg(s, rn, addr);
6946 b0109805 pbrook
                } else {
6947 b0109805 pbrook
                    dead_tmp(addr);
6948 9ee6e8bb pbrook
                }
6949 9ee6e8bb pbrook
                if (loaded_base) {
6950 b0109805 pbrook
                    store_reg(s, rn, loaded_var);
6951 9ee6e8bb pbrook
                }
6952 9ee6e8bb pbrook
                if ((insn & (1 << 22)) && !user) {
6953 9ee6e8bb pbrook
                    /* Restore CPSR from SPSR.  */
6954 d9ba4830 pbrook
                    tmp = load_cpu_field(spsr);
6955 d9ba4830 pbrook
                    gen_set_cpsr(tmp, 0xffffffff);
6956 d9ba4830 pbrook
                    dead_tmp(tmp);
6957 9ee6e8bb pbrook
                    s->is_jmp = DISAS_UPDATE;
6958 9ee6e8bb pbrook
                }
6959 9ee6e8bb pbrook
            }
6960 9ee6e8bb pbrook
            break;
6961 9ee6e8bb pbrook
        case 0xa:
6962 9ee6e8bb pbrook
        case 0xb:
6963 9ee6e8bb pbrook
            {
6964 9ee6e8bb pbrook
                int32_t offset;
6965 9ee6e8bb pbrook
6966 9ee6e8bb pbrook
                /* branch (and link) */
6967 9ee6e8bb pbrook
                val = (int32_t)s->pc;
6968 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
6969 5e3f878a pbrook
                    tmp = new_tmp();
6970 5e3f878a pbrook
                    tcg_gen_movi_i32(tmp, val);
6971 5e3f878a pbrook
                    store_reg(s, 14, tmp);
6972 9ee6e8bb pbrook
                }
6973 9ee6e8bb pbrook
                offset = (((int32_t)insn << 8) >> 8);
6974 9ee6e8bb pbrook
                val += (offset << 2) + 4;
6975 9ee6e8bb pbrook
                gen_jmp(s, val);
6976 9ee6e8bb pbrook
            }
6977 9ee6e8bb pbrook
            break;
6978 9ee6e8bb pbrook
        case 0xc:
6979 9ee6e8bb pbrook
        case 0xd:
6980 9ee6e8bb pbrook
        case 0xe:
6981 9ee6e8bb pbrook
            /* Coprocessor.  */
6982 9ee6e8bb pbrook
            if (disas_coproc_insn(env, s, insn))
6983 9ee6e8bb pbrook
                goto illegal_op;
6984 9ee6e8bb pbrook
            break;
6985 9ee6e8bb pbrook
        case 0xf:
6986 9ee6e8bb pbrook
            /* swi */
6987 5e3f878a pbrook
            gen_set_pc_im(s->pc);
6988 9ee6e8bb pbrook
            s->is_jmp = DISAS_SWI;
6989 9ee6e8bb pbrook
            break;
6990 9ee6e8bb pbrook
        default:
6991 9ee6e8bb pbrook
        illegal_op:
6992 9ee6e8bb pbrook
            gen_set_condexec(s);
6993 5e3f878a pbrook
            gen_set_pc_im(s->pc - 4);
6994 d9ba4830 pbrook
            gen_exception(EXCP_UDEF);
6995 9ee6e8bb pbrook
            s->is_jmp = DISAS_JUMP;
6996 9ee6e8bb pbrook
            break;
6997 9ee6e8bb pbrook
        }
6998 9ee6e8bb pbrook
    }
6999 9ee6e8bb pbrook
}
7000 9ee6e8bb pbrook
7001 9ee6e8bb pbrook
/* Return true if this is a Thumb-2 logical op.  */
7002 9ee6e8bb pbrook
static int
7003 9ee6e8bb pbrook
thumb2_logic_op(int op)
7004 9ee6e8bb pbrook
{
7005 9ee6e8bb pbrook
    return (op < 8);
7006 9ee6e8bb pbrook
}
7007 9ee6e8bb pbrook
7008 9ee6e8bb pbrook
/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
7009 9ee6e8bb pbrook
   then set condition code flags based on the result of the operation.
7010 9ee6e8bb pbrook
   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7011 9ee6e8bb pbrook
   to the high bit of T1.
7012 9ee6e8bb pbrook
   Returns zero if the opcode is valid.  */
7013 9ee6e8bb pbrook
7014 9ee6e8bb pbrook
static int
7015 396e467c Filip Navara
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7016 9ee6e8bb pbrook
{
7017 9ee6e8bb pbrook
    int logic_cc;
7018 9ee6e8bb pbrook
7019 9ee6e8bb pbrook
    logic_cc = 0;
7020 9ee6e8bb pbrook
    switch (op) {
7021 9ee6e8bb pbrook
    case 0: /* and */
7022 396e467c Filip Navara
        tcg_gen_and_i32(t0, t0, t1);
7023 9ee6e8bb pbrook
        logic_cc = conds;
7024 9ee6e8bb pbrook
        break;
7025 9ee6e8bb pbrook
    case 1: /* bic */
7026 396e467c Filip Navara
        tcg_gen_bic_i32(t0, t0, t1);
7027 9ee6e8bb pbrook
        logic_cc = conds;
7028 9ee6e8bb pbrook
        break;
7029 9ee6e8bb pbrook
    case 2: /* orr */
7030 396e467c Filip Navara
        tcg_gen_or_i32(t0, t0, t1);
7031 9ee6e8bb pbrook
        logic_cc = conds;
7032 9ee6e8bb pbrook
        break;
7033 9ee6e8bb pbrook
    case 3: /* orn */
7034 396e467c Filip Navara
        tcg_gen_not_i32(t1, t1);
7035 396e467c Filip Navara
        tcg_gen_or_i32(t0, t0, t1);
7036 9ee6e8bb pbrook
        logic_cc = conds;
7037 9ee6e8bb pbrook
        break;
7038 9ee6e8bb pbrook
    case 4: /* eor */
7039 396e467c Filip Navara
        tcg_gen_xor_i32(t0, t0, t1);
7040 9ee6e8bb pbrook
        logic_cc = conds;
7041 9ee6e8bb pbrook
        break;
7042 9ee6e8bb pbrook
    case 8: /* add */
7043 9ee6e8bb pbrook
        if (conds)
7044 396e467c Filip Navara
            gen_helper_add_cc(t0, t0, t1);
7045 9ee6e8bb pbrook
        else
7046 396e467c Filip Navara
            tcg_gen_add_i32(t0, t0, t1);
7047 9ee6e8bb pbrook
        break;
7048 9ee6e8bb pbrook
    case 10: /* adc */
7049 9ee6e8bb pbrook
        if (conds)
7050 396e467c Filip Navara
            gen_helper_adc_cc(t0, t0, t1);
7051 9ee6e8bb pbrook
        else
7052 396e467c Filip Navara
            gen_adc(t0, t1);
7053 9ee6e8bb pbrook
        break;
7054 9ee6e8bb pbrook
    case 11: /* sbc */
7055 9ee6e8bb pbrook
        if (conds)
7056 396e467c Filip Navara
            gen_helper_sbc_cc(t0, t0, t1);
7057 9ee6e8bb pbrook
        else
7058 396e467c Filip Navara
            gen_sub_carry(t0, t0, t1);
7059 9ee6e8bb pbrook
        break;
7060 9ee6e8bb pbrook
    case 13: /* sub */
7061 9ee6e8bb pbrook
        if (conds)
7062 396e467c Filip Navara
            gen_helper_sub_cc(t0, t0, t1);
7063 9ee6e8bb pbrook
        else
7064 396e467c Filip Navara
            tcg_gen_sub_i32(t0, t0, t1);
7065 9ee6e8bb pbrook
        break;
7066 9ee6e8bb pbrook
    case 14: /* rsb */
7067 9ee6e8bb pbrook
        if (conds)
7068 396e467c Filip Navara
            gen_helper_sub_cc(t0, t1, t0);
7069 9ee6e8bb pbrook
        else
7070 396e467c Filip Navara
            tcg_gen_sub_i32(t0, t1, t0);
7071 9ee6e8bb pbrook
        break;
7072 9ee6e8bb pbrook
    default: /* 5, 6, 7, 9, 12, 15. */
7073 9ee6e8bb pbrook
        return 1;
7074 9ee6e8bb pbrook
    }
7075 9ee6e8bb pbrook
    if (logic_cc) {
7076 396e467c Filip Navara
        gen_logic_CC(t0);
7077 9ee6e8bb pbrook
        if (shifter_out)
7078 396e467c Filip Navara
            gen_set_CF_bit31(t1);
7079 9ee6e8bb pbrook
    }
7080 9ee6e8bb pbrook
    return 0;
7081 9ee6e8bb pbrook
}
7082 9ee6e8bb pbrook
7083 9ee6e8bb pbrook
/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
7084 9ee6e8bb pbrook
   is not legal.  */
7085 9ee6e8bb pbrook
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7086 9ee6e8bb pbrook
{
7087 b0109805 pbrook
    uint32_t insn, imm, shift, offset;
7088 9ee6e8bb pbrook
    uint32_t rd, rn, rm, rs;
7089 b26eefb6 pbrook
    TCGv tmp;
7090 6ddbc6e4 pbrook
    TCGv tmp2;
7091 6ddbc6e4 pbrook
    TCGv tmp3;
7092 b0109805 pbrook
    TCGv addr;
7093 a7812ae4 pbrook
    TCGv_i64 tmp64;
7094 9ee6e8bb pbrook
    int op;
7095 9ee6e8bb pbrook
    int shiftop;
7096 9ee6e8bb pbrook
    int conds;
7097 9ee6e8bb pbrook
    int logic_cc;
7098 9ee6e8bb pbrook
7099 9ee6e8bb pbrook
    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7100 9ee6e8bb pbrook
          || arm_feature (env, ARM_FEATURE_M))) {
7101 601d70b9 balrog
        /* Thumb-1 cores may need to treat bl and blx as a pair of
7102 9ee6e8bb pbrook
           16-bit instructions to get correct prefetch abort behavior.  */
7103 9ee6e8bb pbrook
        insn = insn_hw1;
7104 9ee6e8bb pbrook
        if ((insn & (1 << 12)) == 0) {
7105 9ee6e8bb pbrook
            /* Second half of blx.  */
7106 9ee6e8bb pbrook
            offset = ((insn & 0x7ff) << 1);
7107 d9ba4830 pbrook
            tmp = load_reg(s, 14);
7108 d9ba4830 pbrook
            tcg_gen_addi_i32(tmp, tmp, offset);
7109 d9ba4830 pbrook
            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7110 9ee6e8bb pbrook
7111 d9ba4830 pbrook
            tmp2 = new_tmp();
7112 b0109805 pbrook
            tcg_gen_movi_i32(tmp2, s->pc | 1);
7113 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
7114 d9ba4830 pbrook
            gen_bx(s, tmp);
7115 9ee6e8bb pbrook
            return 0;
7116 9ee6e8bb pbrook
        }
7117 9ee6e8bb pbrook
        if (insn & (1 << 11)) {
7118 9ee6e8bb pbrook
            /* Second half of bl.  */
7119 9ee6e8bb pbrook
            offset = ((insn & 0x7ff) << 1) | 1;
7120 d9ba4830 pbrook
            tmp = load_reg(s, 14);
7121 6a0d8a1d balrog
            tcg_gen_addi_i32(tmp, tmp, offset);
7122 9ee6e8bb pbrook
7123 d9ba4830 pbrook
            tmp2 = new_tmp();
7124 b0109805 pbrook
            tcg_gen_movi_i32(tmp2, s->pc | 1);
7125 d9ba4830 pbrook
            store_reg(s, 14, tmp2);
7126 d9ba4830 pbrook
            gen_bx(s, tmp);
7127 9ee6e8bb pbrook
            return 0;
7128 9ee6e8bb pbrook
        }
7129 9ee6e8bb pbrook
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7130 9ee6e8bb pbrook
            /* Instruction spans a page boundary.  Implement it as two
7131 9ee6e8bb pbrook
               16-bit instructions in case the second half causes an
7132 9ee6e8bb pbrook
               prefetch abort.  */
7133 9ee6e8bb pbrook
            offset = ((int32_t)insn << 21) >> 9;
7134 396e467c Filip Navara
            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7135 9ee6e8bb pbrook
            return 0;
7136 9ee6e8bb pbrook
        }
7137 9ee6e8bb pbrook
        /* Fall through to 32-bit decode.  */
7138 9ee6e8bb pbrook
    }
7139 9ee6e8bb pbrook
7140 9ee6e8bb pbrook
    insn = lduw_code(s->pc);
7141 9ee6e8bb pbrook
    s->pc += 2;
7142 9ee6e8bb pbrook
    insn |= (uint32_t)insn_hw1 << 16;
7143 9ee6e8bb pbrook
7144 9ee6e8bb pbrook
    if ((insn & 0xf800e800) != 0xf000e800) {
7145 9ee6e8bb pbrook
        ARCH(6T2);
7146 9ee6e8bb pbrook
    }
7147 9ee6e8bb pbrook
7148 9ee6e8bb pbrook
    rn = (insn >> 16) & 0xf;
7149 9ee6e8bb pbrook
    rs = (insn >> 12) & 0xf;
7150 9ee6e8bb pbrook
    rd = (insn >> 8) & 0xf;
7151 9ee6e8bb pbrook
    rm = insn & 0xf;
7152 9ee6e8bb pbrook
    switch ((insn >> 25) & 0xf) {
7153 9ee6e8bb pbrook
    case 0: case 1: case 2: case 3:
7154 9ee6e8bb pbrook
        /* 16-bit instructions.  Should never happen.  */
7155 9ee6e8bb pbrook
        abort();
7156 9ee6e8bb pbrook
    case 4:
7157 9ee6e8bb pbrook
        if (insn & (1 << 22)) {
7158 9ee6e8bb pbrook
            /* Other load/store, table branch.  */
7159 9ee6e8bb pbrook
            if (insn & 0x01200000) {
7160 9ee6e8bb pbrook
                /* Load/store doubleword.  */
7161 9ee6e8bb pbrook
                if (rn == 15) {
7162 b0109805 pbrook
                    addr = new_tmp();
7163 b0109805 pbrook
                    tcg_gen_movi_i32(addr, s->pc & ~3);
7164 9ee6e8bb pbrook
                } else {
7165 b0109805 pbrook
                    addr = load_reg(s, rn);
7166 9ee6e8bb pbrook
                }
7167 9ee6e8bb pbrook
                offset = (insn & 0xff) * 4;
7168 9ee6e8bb pbrook
                if ((insn & (1 << 23)) == 0)
7169 9ee6e8bb pbrook
                    offset = -offset;
7170 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
7171 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset);
7172 9ee6e8bb pbrook
                    offset = 0;
7173 9ee6e8bb pbrook
                }
7174 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7175 9ee6e8bb pbrook
                    /* ldrd */
7176 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
7177 b0109805 pbrook
                    store_reg(s, rs, tmp);
7178 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7179 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
7180 b0109805 pbrook
                    store_reg(s, rd, tmp);
7181 9ee6e8bb pbrook
                } else {
7182 9ee6e8bb pbrook
                    /* strd */
7183 b0109805 pbrook
                    tmp = load_reg(s, rs);
7184 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
7185 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7186 b0109805 pbrook
                    tmp = load_reg(s, rd);
7187 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
7188 9ee6e8bb pbrook
                }
7189 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
7190 9ee6e8bb pbrook
                    /* Base writeback.  */
7191 9ee6e8bb pbrook
                    if (rn == 15)
7192 9ee6e8bb pbrook
                        goto illegal_op;
7193 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, offset - 4);
7194 b0109805 pbrook
                    store_reg(s, rn, addr);
7195 b0109805 pbrook
                } else {
7196 b0109805 pbrook
                    dead_tmp(addr);
7197 9ee6e8bb pbrook
                }
7198 9ee6e8bb pbrook
            } else if ((insn & (1 << 23)) == 0) {
7199 9ee6e8bb pbrook
                /* Load/store exclusive word.  */
7200 3174f8e9 Filip Navara
                addr = tcg_temp_local_new();
7201 3174f8e9 Filip Navara
                tcg_gen_mov_i32(addr, cpu_R[rn]);
7202 2c0262af bellard
                if (insn & (1 << 20)) {
7203 3174f8e9 Filip Navara
                    gen_helper_mark_exclusive(cpu_env, addr);
7204 8f8e3aa4 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
7205 8f8e3aa4 pbrook
                    store_reg(s, rd, tmp);
7206 9ee6e8bb pbrook
                } else {
7207 8f8e3aa4 pbrook
                    int label = gen_new_label();
7208 3174f8e9 Filip Navara
                    tmp2 = tcg_temp_local_new();
7209 3174f8e9 Filip Navara
                    gen_helper_test_exclusive(tmp2, cpu_env, addr);
7210 3174f8e9 Filip Navara
                    tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7211 8f8e3aa4 pbrook
                    tmp = load_reg(s, rs);
7212 3174f8e9 Filip Navara
                    gen_st32(tmp, addr, IS_USER(s));
7213 8f8e3aa4 pbrook
                    gen_set_label(label);
7214 3174f8e9 Filip Navara
                    tcg_gen_mov_i32(cpu_R[rd], tmp2);
7215 3174f8e9 Filip Navara
                    tcg_temp_free(tmp2);
7216 9ee6e8bb pbrook
                }
7217 3174f8e9 Filip Navara
                tcg_temp_free(addr);
7218 9ee6e8bb pbrook
            } else if ((insn & (1 << 6)) == 0) {
7219 9ee6e8bb pbrook
                /* Table Branch.  */
7220 9ee6e8bb pbrook
                if (rn == 15) {
7221 b0109805 pbrook
                    addr = new_tmp();
7222 b0109805 pbrook
                    tcg_gen_movi_i32(addr, s->pc);
7223 9ee6e8bb pbrook
                } else {
7224 b0109805 pbrook
                    addr = load_reg(s, rn);
7225 9ee6e8bb pbrook
                }
7226 b26eefb6 pbrook
                tmp = load_reg(s, rm);
7227 b0109805 pbrook
                tcg_gen_add_i32(addr, addr, tmp);
7228 9ee6e8bb pbrook
                if (insn & (1 << 4)) {
7229 9ee6e8bb pbrook
                    /* tbh */
7230 b0109805 pbrook
                    tcg_gen_add_i32(addr, addr, tmp);
7231 b26eefb6 pbrook
                    dead_tmp(tmp);
7232 b0109805 pbrook
                    tmp = gen_ld16u(addr, IS_USER(s));
7233 9ee6e8bb pbrook
                } else { /* tbb */
7234 b26eefb6 pbrook
                    dead_tmp(tmp);
7235 b0109805 pbrook
                    tmp = gen_ld8u(addr, IS_USER(s));
7236 9ee6e8bb pbrook
                }
7237 b0109805 pbrook
                dead_tmp(addr);
7238 b0109805 pbrook
                tcg_gen_shli_i32(tmp, tmp, 1);
7239 b0109805 pbrook
                tcg_gen_addi_i32(tmp, tmp, s->pc);
7240 b0109805 pbrook
                store_reg(s, 15, tmp);
7241 9ee6e8bb pbrook
            } else {
7242 9ee6e8bb pbrook
                /* Load/store exclusive byte/halfword/doubleword.  */
7243 8f8e3aa4 pbrook
                /* ??? These are not really atomic.  However we know
7244 8f8e3aa4 pbrook
                   we never have multiple CPUs running in parallel,
7245 8f8e3aa4 pbrook
                   so it is good enough.  */
7246 9ee6e8bb pbrook
                op = (insn >> 4) & 0x3;
7247 3174f8e9 Filip Navara
                addr = tcg_temp_local_new();
7248 3174f8e9 Filip Navara
                tcg_gen_mov_i32(addr, cpu_R[rn]);
7249 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7250 8f8e3aa4 pbrook
                    gen_helper_mark_exclusive(cpu_env, addr);
7251 9ee6e8bb pbrook
                    switch (op) {
7252 9ee6e8bb pbrook
                    case 0:
7253 8f8e3aa4 pbrook
                        tmp = gen_ld8u(addr, IS_USER(s));
7254 9ee6e8bb pbrook
                        break;
7255 2c0262af bellard
                    case 1:
7256 8f8e3aa4 pbrook
                        tmp = gen_ld16u(addr, IS_USER(s));
7257 2c0262af bellard
                        break;
7258 9ee6e8bb pbrook
                    case 3:
7259 8f8e3aa4 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
7260 8f8e3aa4 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
7261 8f8e3aa4 pbrook
                        tmp2 = gen_ld32(addr, IS_USER(s));
7262 8f8e3aa4 pbrook
                        store_reg(s, rd, tmp2);
7263 2c0262af bellard
                        break;
7264 2c0262af bellard
                    default:
7265 9ee6e8bb pbrook
                        goto illegal_op;
7266 9ee6e8bb pbrook
                    }
7267 8f8e3aa4 pbrook
                    store_reg(s, rs, tmp);
7268 9ee6e8bb pbrook
                } else {
7269 8f8e3aa4 pbrook
                    int label = gen_new_label();
7270 3174f8e9 Filip Navara
                    tmp2 = tcg_temp_local_new();
7271 3174f8e9 Filip Navara
                    gen_helper_test_exclusive(tmp2, cpu_env, addr);
7272 3174f8e9 Filip Navara
                    tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7273 8f8e3aa4 pbrook
                    tmp = load_reg(s, rs);
7274 9ee6e8bb pbrook
                    switch (op) {
7275 9ee6e8bb pbrook
                    case 0:
7276 8f8e3aa4 pbrook
                        gen_st8(tmp, addr, IS_USER(s));
7277 9ee6e8bb pbrook
                        break;
7278 9ee6e8bb pbrook
                    case 1:
7279 8f8e3aa4 pbrook
                        gen_st16(tmp, addr, IS_USER(s));
7280 9ee6e8bb pbrook
                        break;
7281 2c0262af bellard
                    case 3:
7282 8f8e3aa4 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
7283 8f8e3aa4 pbrook
                        tcg_gen_addi_i32(addr, addr, 4);
7284 8f8e3aa4 pbrook
                        tmp = load_reg(s, rd);
7285 8f8e3aa4 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
7286 2c0262af bellard
                        break;
7287 9ee6e8bb pbrook
                    default:
7288 9ee6e8bb pbrook
                        goto illegal_op;
7289 2c0262af bellard
                    }
7290 8f8e3aa4 pbrook
                    gen_set_label(label);
7291 3174f8e9 Filip Navara
                    tcg_gen_mov_i32(cpu_R[rm], tmp2);
7292 3174f8e9 Filip Navara
                    tcg_temp_free(tmp2);
7293 9ee6e8bb pbrook
                }
7294 3174f8e9 Filip Navara
                tcg_temp_free(addr);
7295 9ee6e8bb pbrook
            }
7296 9ee6e8bb pbrook
        } else {
7297 9ee6e8bb pbrook
            /* Load/store multiple, RFE, SRS.  */
7298 9ee6e8bb pbrook
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7299 9ee6e8bb pbrook
                /* Not available in user mode.  */
7300 b0109805 pbrook
                if (IS_USER(s))
7301 9ee6e8bb pbrook
                    goto illegal_op;
7302 9ee6e8bb pbrook
                if (insn & (1 << 20)) {
7303 9ee6e8bb pbrook
                    /* rfe */
7304 b0109805 pbrook
                    addr = load_reg(s, rn);
7305 b0109805 pbrook
                    if ((insn & (1 << 24)) == 0)
7306 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -8);
7307 b0109805 pbrook
                    /* Load PC into tmp and CPSR into tmp2.  */
7308 b0109805 pbrook
                    tmp = gen_ld32(addr, 0);
7309 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7310 b0109805 pbrook
                    tmp2 = gen_ld32(addr, 0);
7311 9ee6e8bb pbrook
                    if (insn & (1 << 21)) {
7312 9ee6e8bb pbrook
                        /* Base writeback.  */
7313 b0109805 pbrook
                        if (insn & (1 << 24)) {
7314 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
7315 b0109805 pbrook
                        } else {
7316 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -4);
7317 b0109805 pbrook
                        }
7318 b0109805 pbrook
                        store_reg(s, rn, addr);
7319 b0109805 pbrook
                    } else {
7320 b0109805 pbrook
                        dead_tmp(addr);
7321 9ee6e8bb pbrook
                    }
7322 b0109805 pbrook
                    gen_rfe(s, tmp, tmp2);
7323 9ee6e8bb pbrook
                } else {
7324 9ee6e8bb pbrook
                    /* srs */
7325 9ee6e8bb pbrook
                    op = (insn & 0x1f);
7326 9ee6e8bb pbrook
                    if (op == (env->uncached_cpsr & CPSR_M)) {
7327 b0109805 pbrook
                        addr = load_reg(s, 13);
7328 9ee6e8bb pbrook
                    } else {
7329 b0109805 pbrook
                        addr = new_tmp();
7330 b0109805 pbrook
                        gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7331 9ee6e8bb pbrook
                    }
7332 9ee6e8bb pbrook
                    if ((insn & (1 << 24)) == 0) {
7333 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -8);
7334 9ee6e8bb pbrook
                    }
7335 b0109805 pbrook
                    tmp = load_reg(s, 14);
7336 b0109805 pbrook
                    gen_st32(tmp, addr, 0);
7337 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7338 b0109805 pbrook
                    tmp = new_tmp();
7339 b0109805 pbrook
                    gen_helper_cpsr_read(tmp);
7340 b0109805 pbrook
                    gen_st32(tmp, addr, 0);
7341 9ee6e8bb pbrook
                    if (insn & (1 << 21)) {
7342 9ee6e8bb pbrook
                        if ((insn & (1 << 24)) == 0) {
7343 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, -4);
7344 9ee6e8bb pbrook
                        } else {
7345 b0109805 pbrook
                            tcg_gen_addi_i32(addr, addr, 4);
7346 9ee6e8bb pbrook
                        }
7347 9ee6e8bb pbrook
                        if (op == (env->uncached_cpsr & CPSR_M)) {
7348 b0109805 pbrook
                            store_reg(s, 13, addr);
7349 9ee6e8bb pbrook
                        } else {
7350 b0109805 pbrook
                            gen_helper_set_r13_banked(cpu_env,
7351 b0109805 pbrook
                                tcg_const_i32(op), addr);
7352 9ee6e8bb pbrook
                        }
7353 b0109805 pbrook
                    } else {
7354 b0109805 pbrook
                        dead_tmp(addr);
7355 9ee6e8bb pbrook
                    }
7356 9ee6e8bb pbrook
                }
7357 9ee6e8bb pbrook
            } else {
7358 9ee6e8bb pbrook
                int i;
7359 9ee6e8bb pbrook
                /* Load/store multiple.  */
7360 b0109805 pbrook
                addr = load_reg(s, rn);
7361 9ee6e8bb pbrook
                offset = 0;
7362 9ee6e8bb pbrook
                for (i = 0; i < 16; i++) {
7363 9ee6e8bb pbrook
                    if (insn & (1 << i))
7364 9ee6e8bb pbrook
                        offset += 4;
7365 9ee6e8bb pbrook
                }
7366 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
7367 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, -offset);
7368 9ee6e8bb pbrook
                }
7369 9ee6e8bb pbrook
7370 9ee6e8bb pbrook
                for (i = 0; i < 16; i++) {
7371 9ee6e8bb pbrook
                    if ((insn & (1 << i)) == 0)
7372 9ee6e8bb pbrook
                        continue;
7373 9ee6e8bb pbrook
                    if (insn & (1 << 20)) {
7374 9ee6e8bb pbrook
                        /* Load.  */
7375 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
7376 9ee6e8bb pbrook
                        if (i == 15) {
7377 b0109805 pbrook
                            gen_bx(s, tmp);
7378 9ee6e8bb pbrook
                        } else {
7379 b0109805 pbrook
                            store_reg(s, i, tmp);
7380 9ee6e8bb pbrook
                        }
7381 9ee6e8bb pbrook
                    } else {
7382 9ee6e8bb pbrook
                        /* Store.  */
7383 b0109805 pbrook
                        tmp = load_reg(s, i);
7384 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
7385 9ee6e8bb pbrook
                    }
7386 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
7387 9ee6e8bb pbrook
                }
7388 9ee6e8bb pbrook
                if (insn & (1 << 21)) {
7389 9ee6e8bb pbrook
                    /* Base register writeback.  */
7390 9ee6e8bb pbrook
                    if (insn & (1 << 24)) {
7391 b0109805 pbrook
                        tcg_gen_addi_i32(addr, addr, -offset);
7392 9ee6e8bb pbrook
                    }
7393 9ee6e8bb pbrook
                    /* Fault if writeback register is in register list.  */
7394 9ee6e8bb pbrook
                    if (insn & (1 << rn))
7395 9ee6e8bb pbrook
                        goto illegal_op;
7396 b0109805 pbrook
                    store_reg(s, rn, addr);
7397 b0109805 pbrook
                } else {
7398 b0109805 pbrook
                    dead_tmp(addr);
7399 9ee6e8bb pbrook
                }
7400 9ee6e8bb pbrook
            }
7401 9ee6e8bb pbrook
        }
7402 9ee6e8bb pbrook
        break;
7403 9ee6e8bb pbrook
    case 5: /* Data processing register constant shift.  */
7404 3174f8e9 Filip Navara
        if (rn == 15) {
7405 3174f8e9 Filip Navara
            tmp = new_tmp();
7406 3174f8e9 Filip Navara
            tcg_gen_movi_i32(tmp, 0);
7407 3174f8e9 Filip Navara
        } else {
7408 3174f8e9 Filip Navara
            tmp = load_reg(s, rn);
7409 3174f8e9 Filip Navara
        }
7410 3174f8e9 Filip Navara
        tmp2 = load_reg(s, rm);
7411 9ee6e8bb pbrook
        op = (insn >> 21) & 0xf;
7412 9ee6e8bb pbrook
        shiftop = (insn >> 4) & 3;
7413 9ee6e8bb pbrook
        shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7414 9ee6e8bb pbrook
        conds = (insn & (1 << 20)) != 0;
7415 9ee6e8bb pbrook
        logic_cc = (conds && thumb2_logic_op(op));
7416 3174f8e9 Filip Navara
        gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7417 3174f8e9 Filip Navara
        if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7418 9ee6e8bb pbrook
            goto illegal_op;
7419 3174f8e9 Filip Navara
        dead_tmp(tmp2);
7420 3174f8e9 Filip Navara
        if (rd != 15) {
7421 3174f8e9 Filip Navara
            store_reg(s, rd, tmp);
7422 3174f8e9 Filip Navara
        } else {
7423 3174f8e9 Filip Navara
            dead_tmp(tmp);
7424 3174f8e9 Filip Navara
        }
7425 9ee6e8bb pbrook
        break;
7426 9ee6e8bb pbrook
    case 13: /* Misc data processing.  */
7427 9ee6e8bb pbrook
        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7428 9ee6e8bb pbrook
        if (op < 4 && (insn & 0xf000) != 0xf000)
7429 9ee6e8bb pbrook
            goto illegal_op;
7430 9ee6e8bb pbrook
        switch (op) {
7431 9ee6e8bb pbrook
        case 0: /* Register controlled shift.  */
7432 8984bd2e pbrook
            tmp = load_reg(s, rn);
7433 8984bd2e pbrook
            tmp2 = load_reg(s, rm);
7434 9ee6e8bb pbrook
            if ((insn & 0x70) != 0)
7435 9ee6e8bb pbrook
                goto illegal_op;
7436 9ee6e8bb pbrook
            op = (insn >> 21) & 3;
7437 8984bd2e pbrook
            logic_cc = (insn & (1 << 20)) != 0;
7438 8984bd2e pbrook
            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7439 8984bd2e pbrook
            if (logic_cc)
7440 8984bd2e pbrook
                gen_logic_CC(tmp);
7441 21aeb343 Juha Riihimรคki
            store_reg_bx(env, s, rd, tmp);
7442 9ee6e8bb pbrook
            break;
7443 9ee6e8bb pbrook
        case 1: /* Sign/zero extend.  */
7444 5e3f878a pbrook
            tmp = load_reg(s, rm);
7445 9ee6e8bb pbrook
            shift = (insn >> 4) & 3;
7446 9ee6e8bb pbrook
            /* ??? In many cases it's not neccessary to do a
7447 9ee6e8bb pbrook
               rotate, a shift is sufficient.  */
7448 9ee6e8bb pbrook
            if (shift != 0)
7449 5e3f878a pbrook
                tcg_gen_rori_i32(tmp, tmp, shift * 8);
7450 9ee6e8bb pbrook
            op = (insn >> 20) & 7;
7451 9ee6e8bb pbrook
            switch (op) {
7452 5e3f878a pbrook
            case 0: gen_sxth(tmp);   break;
7453 5e3f878a pbrook
            case 1: gen_uxth(tmp);   break;
7454 5e3f878a pbrook
            case 2: gen_sxtb16(tmp); break;
7455 5e3f878a pbrook
            case 3: gen_uxtb16(tmp); break;
7456 5e3f878a pbrook
            case 4: gen_sxtb(tmp);   break;
7457 5e3f878a pbrook
            case 5: gen_uxtb(tmp);   break;
7458 9ee6e8bb pbrook
            default: goto illegal_op;
7459 9ee6e8bb pbrook
            }
7460 9ee6e8bb pbrook
            if (rn != 15) {
7461 5e3f878a pbrook
                tmp2 = load_reg(s, rn);
7462 9ee6e8bb pbrook
                if ((op >> 1) == 1) {
7463 5e3f878a pbrook
                    gen_add16(tmp, tmp2);
7464 9ee6e8bb pbrook
                } else {
7465 5e3f878a pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7466 5e3f878a pbrook
                    dead_tmp(tmp2);
7467 9ee6e8bb pbrook
                }
7468 9ee6e8bb pbrook
            }
7469 5e3f878a pbrook
            store_reg(s, rd, tmp);
7470 9ee6e8bb pbrook
            break;
7471 9ee6e8bb pbrook
        case 2: /* SIMD add/subtract.  */
7472 9ee6e8bb pbrook
            op = (insn >> 20) & 7;
7473 9ee6e8bb pbrook
            shift = (insn >> 4) & 7;
7474 9ee6e8bb pbrook
            if ((op & 3) == 3 || (shift & 3) == 3)
7475 9ee6e8bb pbrook
                goto illegal_op;
7476 6ddbc6e4 pbrook
            tmp = load_reg(s, rn);
7477 6ddbc6e4 pbrook
            tmp2 = load_reg(s, rm);
7478 6ddbc6e4 pbrook
            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7479 6ddbc6e4 pbrook
            dead_tmp(tmp2);
7480 6ddbc6e4 pbrook
            store_reg(s, rd, tmp);
7481 9ee6e8bb pbrook
            break;
7482 9ee6e8bb pbrook
        case 3: /* Other data processing.  */
7483 9ee6e8bb pbrook
            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7484 9ee6e8bb pbrook
            if (op < 4) {
7485 9ee6e8bb pbrook
                /* Saturating add/subtract.  */
7486 d9ba4830 pbrook
                tmp = load_reg(s, rn);
7487 d9ba4830 pbrook
                tmp2 = load_reg(s, rm);
7488 9ee6e8bb pbrook
                if (op & 2)
7489 d9ba4830 pbrook
                    gen_helper_double_saturate(tmp, tmp);
7490 9ee6e8bb pbrook
                if (op & 1)
7491 d9ba4830 pbrook
                    gen_helper_sub_saturate(tmp, tmp2, tmp);
7492 9ee6e8bb pbrook
                else
7493 d9ba4830 pbrook
                    gen_helper_add_saturate(tmp, tmp, tmp2);
7494 d9ba4830 pbrook
                dead_tmp(tmp2);
7495 9ee6e8bb pbrook
            } else {
7496 d9ba4830 pbrook
                tmp = load_reg(s, rn);
7497 9ee6e8bb pbrook
                switch (op) {
7498 9ee6e8bb pbrook
                case 0x0a: /* rbit */
7499 d9ba4830 pbrook
                    gen_helper_rbit(tmp, tmp);
7500 9ee6e8bb pbrook
                    break;
7501 9ee6e8bb pbrook
                case 0x08: /* rev */
7502 66896cb8 aurel32
                    tcg_gen_bswap32_i32(tmp, tmp);
7503 9ee6e8bb pbrook
                    break;
7504 9ee6e8bb pbrook
                case 0x09: /* rev16 */
7505 d9ba4830 pbrook
                    gen_rev16(tmp);
7506 9ee6e8bb pbrook
                    break;
7507 9ee6e8bb pbrook
                case 0x0b: /* revsh */
7508 d9ba4830 pbrook
                    gen_revsh(tmp);
7509 9ee6e8bb pbrook
                    break;
7510 9ee6e8bb pbrook
                case 0x10: /* sel */
7511 d9ba4830 pbrook
                    tmp2 = load_reg(s, rm);
7512 6ddbc6e4 pbrook
                    tmp3 = new_tmp();
7513 6ddbc6e4 pbrook
                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7514 d9ba4830 pbrook
                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7515 6ddbc6e4 pbrook
                    dead_tmp(tmp3);
7516 d9ba4830 pbrook
                    dead_tmp(tmp2);
7517 9ee6e8bb pbrook
                    break;
7518 9ee6e8bb pbrook
                case 0x18: /* clz */
7519 d9ba4830 pbrook
                    gen_helper_clz(tmp, tmp);
7520 9ee6e8bb pbrook
                    break;
7521 9ee6e8bb pbrook
                default:
7522 9ee6e8bb pbrook
                    goto illegal_op;
7523 9ee6e8bb pbrook
                }
7524 9ee6e8bb pbrook
            }
7525 d9ba4830 pbrook
            store_reg(s, rd, tmp);
7526 9ee6e8bb pbrook
            break;
7527 9ee6e8bb pbrook
        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
7528 9ee6e8bb pbrook
            op = (insn >> 4) & 0xf;
7529 d9ba4830 pbrook
            tmp = load_reg(s, rn);
7530 d9ba4830 pbrook
            tmp2 = load_reg(s, rm);
7531 9ee6e8bb pbrook
            switch ((insn >> 20) & 7) {
7532 9ee6e8bb pbrook
            case 0: /* 32 x 32 -> 32 */
7533 d9ba4830 pbrook
                tcg_gen_mul_i32(tmp, tmp, tmp2);
7534 d9ba4830 pbrook
                dead_tmp(tmp2);
7535 9ee6e8bb pbrook
                if (rs != 15) {
7536 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7537 9ee6e8bb pbrook
                    if (op)
7538 d9ba4830 pbrook
                        tcg_gen_sub_i32(tmp, tmp2, tmp);
7539 9ee6e8bb pbrook
                    else
7540 d9ba4830 pbrook
                        tcg_gen_add_i32(tmp, tmp, tmp2);
7541 d9ba4830 pbrook
                    dead_tmp(tmp2);
7542 9ee6e8bb pbrook
                }
7543 9ee6e8bb pbrook
                break;
7544 9ee6e8bb pbrook
            case 1: /* 16 x 16 -> 32 */
7545 d9ba4830 pbrook
                gen_mulxy(tmp, tmp2, op & 2, op & 1);
7546 d9ba4830 pbrook
                dead_tmp(tmp2);
7547 9ee6e8bb pbrook
                if (rs != 15) {
7548 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7549 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
7550 d9ba4830 pbrook
                    dead_tmp(tmp2);
7551 9ee6e8bb pbrook
                }
7552 9ee6e8bb pbrook
                break;
7553 9ee6e8bb pbrook
            case 2: /* Dual multiply add.  */
7554 9ee6e8bb pbrook
            case 4: /* Dual multiply subtract.  */
7555 9ee6e8bb pbrook
                if (op)
7556 d9ba4830 pbrook
                    gen_swap_half(tmp2);
7557 d9ba4830 pbrook
                gen_smul_dual(tmp, tmp2);
7558 9ee6e8bb pbrook
                /* This addition cannot overflow.  */
7559 9ee6e8bb pbrook
                if (insn & (1 << 22)) {
7560 d9ba4830 pbrook
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
7561 9ee6e8bb pbrook
                } else {
7562 d9ba4830 pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7563 9ee6e8bb pbrook
                }
7564 d9ba4830 pbrook
                dead_tmp(tmp2);
7565 9ee6e8bb pbrook
                if (rs != 15)
7566 9ee6e8bb pbrook
                  {
7567 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7568 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
7569 d9ba4830 pbrook
                    dead_tmp(tmp2);
7570 9ee6e8bb pbrook
                  }
7571 9ee6e8bb pbrook
                break;
7572 9ee6e8bb pbrook
            case 3: /* 32 * 16 -> 32msb */
7573 9ee6e8bb pbrook
                if (op)
7574 d9ba4830 pbrook
                    tcg_gen_sari_i32(tmp2, tmp2, 16);
7575 9ee6e8bb pbrook
                else
7576 d9ba4830 pbrook
                    gen_sxth(tmp2);
7577 a7812ae4 pbrook
                tmp64 = gen_muls_i64_i32(tmp, tmp2);
7578 a7812ae4 pbrook
                tcg_gen_shri_i64(tmp64, tmp64, 16);
7579 5e3f878a pbrook
                tmp = new_tmp();
7580 a7812ae4 pbrook
                tcg_gen_trunc_i64_i32(tmp, tmp64);
7581 9ee6e8bb pbrook
                if (rs != 15)
7582 9ee6e8bb pbrook
                  {
7583 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7584 d9ba4830 pbrook
                    gen_helper_add_setq(tmp, tmp, tmp2);
7585 d9ba4830 pbrook
                    dead_tmp(tmp2);
7586 9ee6e8bb pbrook
                  }
7587 9ee6e8bb pbrook
                break;
7588 9ee6e8bb pbrook
            case 5: case 6: /* 32 * 32 -> 32msb */
7589 d9ba4830 pbrook
                gen_imull(tmp, tmp2);
7590 d9ba4830 pbrook
                if (insn & (1 << 5)) {
7591 d9ba4830 pbrook
                    gen_roundqd(tmp, tmp2);
7592 d9ba4830 pbrook
                    dead_tmp(tmp2);
7593 d9ba4830 pbrook
                } else {
7594 d9ba4830 pbrook
                    dead_tmp(tmp);
7595 d9ba4830 pbrook
                    tmp = tmp2;
7596 d9ba4830 pbrook
                }
7597 9ee6e8bb pbrook
                if (rs != 15) {
7598 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7599 9ee6e8bb pbrook
                    if (insn & (1 << 21)) {
7600 d9ba4830 pbrook
                        tcg_gen_add_i32(tmp, tmp, tmp2);
7601 99c475ab bellard
                    } else {
7602 d9ba4830 pbrook
                        tcg_gen_sub_i32(tmp, tmp2, tmp);
7603 99c475ab bellard
                    }
7604 d9ba4830 pbrook
                    dead_tmp(tmp2);
7605 2c0262af bellard
                }
7606 9ee6e8bb pbrook
                break;
7607 9ee6e8bb pbrook
            case 7: /* Unsigned sum of absolute differences.  */
7608 d9ba4830 pbrook
                gen_helper_usad8(tmp, tmp, tmp2);
7609 d9ba4830 pbrook
                dead_tmp(tmp2);
7610 9ee6e8bb pbrook
                if (rs != 15) {
7611 d9ba4830 pbrook
                    tmp2 = load_reg(s, rs);
7612 d9ba4830 pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7613 d9ba4830 pbrook
                    dead_tmp(tmp2);
7614 5fd46862 pbrook
                }
7615 9ee6e8bb pbrook
                break;
7616 2c0262af bellard
            }
7617 d9ba4830 pbrook
            store_reg(s, rd, tmp);
7618 2c0262af bellard
            break;
7619 9ee6e8bb pbrook
        case 6: case 7: /* 64-bit multiply, Divide.  */
7620 9ee6e8bb pbrook
            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7621 5e3f878a pbrook
            tmp = load_reg(s, rn);
7622 5e3f878a pbrook
            tmp2 = load_reg(s, rm);
7623 9ee6e8bb pbrook
            if ((op & 0x50) == 0x10) {
7624 9ee6e8bb pbrook
                /* sdiv, udiv */
7625 9ee6e8bb pbrook
                if (!arm_feature(env, ARM_FEATURE_DIV))
7626 9ee6e8bb pbrook
                    goto illegal_op;
7627 9ee6e8bb pbrook
                if (op & 0x20)
7628 5e3f878a pbrook
                    gen_helper_udiv(tmp, tmp, tmp2);
7629 2c0262af bellard
                else
7630 5e3f878a pbrook
                    gen_helper_sdiv(tmp, tmp, tmp2);
7631 5e3f878a pbrook
                dead_tmp(tmp2);
7632 5e3f878a pbrook
                store_reg(s, rd, tmp);
7633 9ee6e8bb pbrook
            } else if ((op & 0xe) == 0xc) {
7634 9ee6e8bb pbrook
                /* Dual multiply accumulate long.  */
7635 9ee6e8bb pbrook
                if (op & 1)
7636 5e3f878a pbrook
                    gen_swap_half(tmp2);
7637 5e3f878a pbrook
                gen_smul_dual(tmp, tmp2);
7638 9ee6e8bb pbrook
                if (op & 0x10) {
7639 5e3f878a pbrook
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
7640 b5ff1b31 bellard
                } else {
7641 5e3f878a pbrook
                    tcg_gen_add_i32(tmp, tmp, tmp2);
7642 b5ff1b31 bellard
                }
7643 5e3f878a pbrook
                dead_tmp(tmp2);
7644 a7812ae4 pbrook
                /* BUGFIX */
7645 a7812ae4 pbrook
                tmp64 = tcg_temp_new_i64();
7646 a7812ae4 pbrook
                tcg_gen_ext_i32_i64(tmp64, tmp);
7647 a7812ae4 pbrook
                dead_tmp(tmp);
7648 a7812ae4 pbrook
                gen_addq(s, tmp64, rs, rd);
7649 a7812ae4 pbrook
                gen_storeq_reg(s, rs, rd, tmp64);
7650 2c0262af bellard
            } else {
7651 9ee6e8bb pbrook
                if (op & 0x20) {
7652 9ee6e8bb pbrook
                    /* Unsigned 64-bit multiply  */
7653 a7812ae4 pbrook
                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7654 b5ff1b31 bellard
                } else {
7655 9ee6e8bb pbrook
                    if (op & 8) {
7656 9ee6e8bb pbrook
                        /* smlalxy */
7657 5e3f878a pbrook
                        gen_mulxy(tmp, tmp2, op & 2, op & 1);
7658 5e3f878a pbrook
                        dead_tmp(tmp2);
7659 a7812ae4 pbrook
                        tmp64 = tcg_temp_new_i64();
7660 a7812ae4 pbrook
                        tcg_gen_ext_i32_i64(tmp64, tmp);
7661 5e3f878a pbrook
                        dead_tmp(tmp);
7662 9ee6e8bb pbrook
                    } else {
7663 9ee6e8bb pbrook
                        /* Signed 64-bit multiply  */
7664 a7812ae4 pbrook
                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
7665 9ee6e8bb pbrook
                    }
7666 b5ff1b31 bellard
                }
7667 9ee6e8bb pbrook
                if (op & 4) {
7668 9ee6e8bb pbrook
                    /* umaal */
7669 a7812ae4 pbrook
                    gen_addq_lo(s, tmp64, rs);
7670 a7812ae4 pbrook
                    gen_addq_lo(s, tmp64, rd);
7671 9ee6e8bb pbrook
                } else if (op & 0x40) {
7672 9ee6e8bb pbrook
                    /* 64-bit accumulate.  */
7673 a7812ae4 pbrook
                    gen_addq(s, tmp64, rs, rd);
7674 9ee6e8bb pbrook
                }
7675 a7812ae4 pbrook
                gen_storeq_reg(s, rs, rd, tmp64);
7676 5fd46862 pbrook
            }
7677 2c0262af bellard
            break;
7678 9ee6e8bb pbrook
        }
7679 9ee6e8bb pbrook
        break;
7680 9ee6e8bb pbrook
    case 6: case 7: case 14: case 15:
7681 9ee6e8bb pbrook
        /* Coprocessor.  */
7682 9ee6e8bb pbrook
        if (((insn >> 24) & 3) == 3) {
7683 9ee6e8bb pbrook
            /* Translate into the equivalent ARM encoding.  */
7684 9ee6e8bb pbrook
            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7685 9ee6e8bb pbrook
            if (disas_neon_data_insn(env, s, insn))
7686 9ee6e8bb pbrook
                goto illegal_op;
7687 9ee6e8bb pbrook
        } else {
7688 9ee6e8bb pbrook
            if (insn & (1 << 28))
7689 9ee6e8bb pbrook
                goto illegal_op;
7690 9ee6e8bb pbrook
            if (disas_coproc_insn (env, s, insn))
7691 9ee6e8bb pbrook
                goto illegal_op;
7692 9ee6e8bb pbrook
        }
7693 9ee6e8bb pbrook
        break;
7694 9ee6e8bb pbrook
    case 8: case 9: case 10: case 11:
7695 9ee6e8bb pbrook
        if (insn & (1 << 15)) {
7696 9ee6e8bb pbrook
            /* Branches, misc control.  */
7697 9ee6e8bb pbrook
            if (insn & 0x5000) {
7698 9ee6e8bb pbrook
                /* Unconditional branch.  */
7699 9ee6e8bb pbrook
                /* signextend(hw1[10:0]) -> offset[:12].  */
7700 9ee6e8bb pbrook
                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7701 9ee6e8bb pbrook
                /* hw1[10:0] -> offset[11:1].  */
7702 9ee6e8bb pbrook
                offset |= (insn & 0x7ff) << 1;
7703 9ee6e8bb pbrook
                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7704 9ee6e8bb pbrook
                   offset[24:22] already have the same value because of the
7705 9ee6e8bb pbrook
                   sign extension above.  */
7706 9ee6e8bb pbrook
                offset ^= ((~insn) & (1 << 13)) << 10;
7707 9ee6e8bb pbrook
                offset ^= ((~insn) & (1 << 11)) << 11;
7708 9ee6e8bb pbrook
7709 9ee6e8bb pbrook
                if (insn & (1 << 14)) {
7710 9ee6e8bb pbrook
                    /* Branch and link.  */
7711 3174f8e9 Filip Navara
                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7712 b5ff1b31 bellard
                }
7713 3b46e624 ths
7714 b0109805 pbrook
                offset += s->pc;
7715 9ee6e8bb pbrook
                if (insn & (1 << 12)) {
7716 9ee6e8bb pbrook
                    /* b/bl */
7717 b0109805 pbrook
                    gen_jmp(s, offset);
7718 9ee6e8bb pbrook
                } else {
7719 9ee6e8bb pbrook
                    /* blx */
7720 b0109805 pbrook
                    offset &= ~(uint32_t)2;
7721 b0109805 pbrook
                    gen_bx_im(s, offset);
7722 2c0262af bellard
                }
7723 9ee6e8bb pbrook
            } else if (((insn >> 23) & 7) == 7) {
7724 9ee6e8bb pbrook
                /* Misc control */
7725 9ee6e8bb pbrook
                if (insn & (1 << 13))
7726 9ee6e8bb pbrook
                    goto illegal_op;
7727 9ee6e8bb pbrook
7728 9ee6e8bb pbrook
                if (insn & (1 << 26)) {
7729 9ee6e8bb pbrook
                    /* Secure monitor call (v6Z) */
7730 9ee6e8bb pbrook
                    goto illegal_op; /* not implemented.  */
7731 2c0262af bellard
                } else {
7732 9ee6e8bb pbrook
                    op = (insn >> 20) & 7;
7733 9ee6e8bb pbrook
                    switch (op) {
7734 9ee6e8bb pbrook
                    case 0: /* msr cpsr.  */
7735 9ee6e8bb pbrook
                        if (IS_M(env)) {
7736 8984bd2e pbrook
                            tmp = load_reg(s, rn);
7737 8984bd2e pbrook
                            addr = tcg_const_i32(insn & 0xff);
7738 8984bd2e pbrook
                            gen_helper_v7m_msr(cpu_env, addr, tmp);
7739 9ee6e8bb pbrook
                            gen_lookup_tb(s);
7740 9ee6e8bb pbrook
                            break;
7741 9ee6e8bb pbrook
                        }
7742 9ee6e8bb pbrook
                        /* fall through */
7743 9ee6e8bb pbrook
                    case 1: /* msr spsr.  */
7744 9ee6e8bb pbrook
                        if (IS_M(env))
7745 9ee6e8bb pbrook
                            goto illegal_op;
7746 2fbac54b Filip Navara
                        tmp = load_reg(s, rn);
7747 2fbac54b Filip Navara
                        if (gen_set_psr(s,
7748 9ee6e8bb pbrook
                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7749 2fbac54b Filip Navara
                              op == 1, tmp))
7750 9ee6e8bb pbrook
                            goto illegal_op;
7751 9ee6e8bb pbrook
                        break;
7752 9ee6e8bb pbrook
                    case 2: /* cps, nop-hint.  */
7753 9ee6e8bb pbrook
                        if (((insn >> 8) & 7) == 0) {
7754 9ee6e8bb pbrook
                            gen_nop_hint(s, insn & 0xff);
7755 9ee6e8bb pbrook
                        }
7756 9ee6e8bb pbrook
                        /* Implemented as NOP in user mode.  */
7757 9ee6e8bb pbrook
                        if (IS_USER(s))
7758 9ee6e8bb pbrook
                            break;
7759 9ee6e8bb pbrook
                        offset = 0;
7760 9ee6e8bb pbrook
                        imm = 0;
7761 9ee6e8bb pbrook
                        if (insn & (1 << 10)) {
7762 9ee6e8bb pbrook
                            if (insn & (1 << 7))
7763 9ee6e8bb pbrook
                                offset |= CPSR_A;
7764 9ee6e8bb pbrook
                            if (insn & (1 << 6))
7765 9ee6e8bb pbrook
                                offset |= CPSR_I;
7766 9ee6e8bb pbrook
                            if (insn & (1 << 5))
7767 9ee6e8bb pbrook
                                offset |= CPSR_F;
7768 9ee6e8bb pbrook
                            if (insn & (1 << 9))
7769 9ee6e8bb pbrook
                                imm = CPSR_A | CPSR_I | CPSR_F;
7770 9ee6e8bb pbrook
                        }
7771 9ee6e8bb pbrook
                        if (insn & (1 << 8)) {
7772 9ee6e8bb pbrook
                            offset |= 0x1f;
7773 9ee6e8bb pbrook
                            imm |= (insn & 0x1f);
7774 9ee6e8bb pbrook
                        }
7775 9ee6e8bb pbrook
                        if (offset) {
7776 2fbac54b Filip Navara
                            gen_set_psr_im(s, offset, 0, imm);
7777 9ee6e8bb pbrook
                        }
7778 9ee6e8bb pbrook
                        break;
7779 9ee6e8bb pbrook
                    case 3: /* Special control operations.  */
7780 9ee6e8bb pbrook
                        op = (insn >> 4) & 0xf;
7781 9ee6e8bb pbrook
                        switch (op) {
7782 9ee6e8bb pbrook
                        case 2: /* clrex */
7783 8f8e3aa4 pbrook
                            gen_helper_clrex(cpu_env);
7784 9ee6e8bb pbrook
                            break;
7785 9ee6e8bb pbrook
                        case 4: /* dsb */
7786 9ee6e8bb pbrook
                        case 5: /* dmb */
7787 9ee6e8bb pbrook
                        case 6: /* isb */
7788 9ee6e8bb pbrook
                            /* These execute as NOPs.  */
7789 9ee6e8bb pbrook
                            ARCH(7);
7790 9ee6e8bb pbrook
                            break;
7791 9ee6e8bb pbrook
                        default:
7792 9ee6e8bb pbrook
                            goto illegal_op;
7793 9ee6e8bb pbrook
                        }
7794 9ee6e8bb pbrook
                        break;
7795 9ee6e8bb pbrook
                    case 4: /* bxj */
7796 9ee6e8bb pbrook
                        /* Trivial implementation equivalent to bx.  */
7797 d9ba4830 pbrook
                        tmp = load_reg(s, rn);
7798 d9ba4830 pbrook
                        gen_bx(s, tmp);
7799 9ee6e8bb pbrook
                        break;
7800 9ee6e8bb pbrook
                    case 5: /* Exception return.  */
7801 9ee6e8bb pbrook
                        /* Unpredictable in user mode.  */
7802 9ee6e8bb pbrook
                        goto illegal_op;
7803 9ee6e8bb pbrook
                    case 6: /* mrs cpsr.  */
7804 8984bd2e pbrook
                        tmp = new_tmp();
7805 9ee6e8bb pbrook
                        if (IS_M(env)) {
7806 8984bd2e pbrook
                            addr = tcg_const_i32(insn & 0xff);
7807 8984bd2e pbrook
                            gen_helper_v7m_mrs(tmp, cpu_env, addr);
7808 9ee6e8bb pbrook
                        } else {
7809 8984bd2e pbrook
                            gen_helper_cpsr_read(tmp);
7810 9ee6e8bb pbrook
                        }
7811 8984bd2e pbrook
                        store_reg(s, rd, tmp);
7812 9ee6e8bb pbrook
                        break;
7813 9ee6e8bb pbrook
                    case 7: /* mrs spsr.  */
7814 9ee6e8bb pbrook
                        /* Not accessible in user mode.  */
7815 9ee6e8bb pbrook
                        if (IS_USER(s) || IS_M(env))
7816 9ee6e8bb pbrook
                            goto illegal_op;
7817 d9ba4830 pbrook
                        tmp = load_cpu_field(spsr);
7818 d9ba4830 pbrook
                        store_reg(s, rd, tmp);
7819 9ee6e8bb pbrook
                        break;
7820 2c0262af bellard
                    }
7821 2c0262af bellard
                }
7822 9ee6e8bb pbrook
            } else {
7823 9ee6e8bb pbrook
                /* Conditional branch.  */
7824 9ee6e8bb pbrook
                op = (insn >> 22) & 0xf;
7825 9ee6e8bb pbrook
                /* Generate a conditional jump to next instruction.  */
7826 9ee6e8bb pbrook
                s->condlabel = gen_new_label();
7827 d9ba4830 pbrook
                gen_test_cc(op ^ 1, s->condlabel);
7828 9ee6e8bb pbrook
                s->condjmp = 1;
7829 9ee6e8bb pbrook
7830 9ee6e8bb pbrook
                /* offset[11:1] = insn[10:0] */
7831 9ee6e8bb pbrook
                offset = (insn & 0x7ff) << 1;
7832 9ee6e8bb pbrook
                /* offset[17:12] = insn[21:16].  */
7833 9ee6e8bb pbrook
                offset |= (insn & 0x003f0000) >> 4;
7834 9ee6e8bb pbrook
                /* offset[31:20] = insn[26].  */
7835 9ee6e8bb pbrook
                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7836 9ee6e8bb pbrook
                /* offset[18] = insn[13].  */
7837 9ee6e8bb pbrook
                offset |= (insn & (1 << 13)) << 5;
7838 9ee6e8bb pbrook
                /* offset[19] = insn[11].  */
7839 9ee6e8bb pbrook
                offset |= (insn & (1 << 11)) << 8;
7840 9ee6e8bb pbrook
7841 9ee6e8bb pbrook
                /* jump to the offset */
7842 b0109805 pbrook
                gen_jmp(s, s->pc + offset);
7843 9ee6e8bb pbrook
            }
7844 9ee6e8bb pbrook
        } else {
7845 9ee6e8bb pbrook
            /* Data processing immediate.  */
7846 9ee6e8bb pbrook
            if (insn & (1 << 25)) {
7847 9ee6e8bb pbrook
                if (insn & (1 << 24)) {
7848 9ee6e8bb pbrook
                    if (insn & (1 << 20))
7849 9ee6e8bb pbrook
                        goto illegal_op;
7850 9ee6e8bb pbrook
                    /* Bitfield/Saturate.  */
7851 9ee6e8bb pbrook
                    op = (insn >> 21) & 7;
7852 9ee6e8bb pbrook
                    imm = insn & 0x1f;
7853 9ee6e8bb pbrook
                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7854 6ddbc6e4 pbrook
                    if (rn == 15) {
7855 6ddbc6e4 pbrook
                        tmp = new_tmp();
7856 6ddbc6e4 pbrook
                        tcg_gen_movi_i32(tmp, 0);
7857 6ddbc6e4 pbrook
                    } else {
7858 6ddbc6e4 pbrook
                        tmp = load_reg(s, rn);
7859 6ddbc6e4 pbrook
                    }
7860 9ee6e8bb pbrook
                    switch (op) {
7861 9ee6e8bb pbrook
                    case 2: /* Signed bitfield extract.  */
7862 9ee6e8bb pbrook
                        imm++;
7863 9ee6e8bb pbrook
                        if (shift + imm > 32)
7864 9ee6e8bb pbrook
                            goto illegal_op;
7865 9ee6e8bb pbrook
                        if (imm < 32)
7866 6ddbc6e4 pbrook
                            gen_sbfx(tmp, shift, imm);
7867 9ee6e8bb pbrook
                        break;
7868 9ee6e8bb pbrook
                    case 6: /* Unsigned bitfield extract.  */
7869 9ee6e8bb pbrook
                        imm++;
7870 9ee6e8bb pbrook
                        if (shift + imm > 32)
7871 9ee6e8bb pbrook
                            goto illegal_op;
7872 9ee6e8bb pbrook
                        if (imm < 32)
7873 6ddbc6e4 pbrook
                            gen_ubfx(tmp, shift, (1u << imm) - 1);
7874 9ee6e8bb pbrook
                        break;
7875 9ee6e8bb pbrook
                    case 3: /* Bitfield insert/clear.  */
7876 9ee6e8bb pbrook
                        if (imm < shift)
7877 9ee6e8bb pbrook
                            goto illegal_op;
7878 9ee6e8bb pbrook
                        imm = imm + 1 - shift;
7879 9ee6e8bb pbrook
                        if (imm != 32) {
7880 6ddbc6e4 pbrook
                            tmp2 = load_reg(s, rd);
7881 8f8e3aa4 pbrook
                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7882 6ddbc6e4 pbrook
                            dead_tmp(tmp2);
7883 9ee6e8bb pbrook
                        }
7884 9ee6e8bb pbrook
                        break;
7885 9ee6e8bb pbrook
                    case 7:
7886 9ee6e8bb pbrook
                        goto illegal_op;
7887 9ee6e8bb pbrook
                    default: /* Saturate.  */
7888 9ee6e8bb pbrook
                        if (shift) {
7889 9ee6e8bb pbrook
                            if (op & 1)
7890 6ddbc6e4 pbrook
                                tcg_gen_sari_i32(tmp, tmp, shift);
7891 9ee6e8bb pbrook
                            else
7892 6ddbc6e4 pbrook
                                tcg_gen_shli_i32(tmp, tmp, shift);
7893 9ee6e8bb pbrook
                        }
7894 6ddbc6e4 pbrook
                        tmp2 = tcg_const_i32(imm);
7895 9ee6e8bb pbrook
                        if (op & 4) {
7896 9ee6e8bb pbrook
                            /* Unsigned.  */
7897 9ee6e8bb pbrook
                            if ((op & 1) && shift == 0)
7898 6ddbc6e4 pbrook
                                gen_helper_usat16(tmp, tmp, tmp2);
7899 9ee6e8bb pbrook
                            else
7900 6ddbc6e4 pbrook
                                gen_helper_usat(tmp, tmp, tmp2);
7901 2c0262af bellard
                        } else {
7902 9ee6e8bb pbrook
                            /* Signed.  */
7903 9ee6e8bb pbrook
                            if ((op & 1) && shift == 0)
7904 6ddbc6e4 pbrook
                                gen_helper_ssat16(tmp, tmp, tmp2);
7905 9ee6e8bb pbrook
                            else
7906 6ddbc6e4 pbrook
                                gen_helper_ssat(tmp, tmp, tmp2);
7907 2c0262af bellard
                        }
7908 9ee6e8bb pbrook
                        break;
7909 2c0262af bellard
                    }
7910 6ddbc6e4 pbrook
                    store_reg(s, rd, tmp);
7911 9ee6e8bb pbrook
                } else {
7912 9ee6e8bb pbrook
                    imm = ((insn & 0x04000000) >> 15)
7913 9ee6e8bb pbrook
                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
7914 9ee6e8bb pbrook
                    if (insn & (1 << 22)) {
7915 9ee6e8bb pbrook
                        /* 16-bit immediate.  */
7916 9ee6e8bb pbrook
                        imm |= (insn >> 4) & 0xf000;
7917 9ee6e8bb pbrook
                        if (insn & (1 << 23)) {
7918 9ee6e8bb pbrook
                            /* movt */
7919 5e3f878a pbrook
                            tmp = load_reg(s, rd);
7920 86831435 pbrook
                            tcg_gen_ext16u_i32(tmp, tmp);
7921 5e3f878a pbrook
                            tcg_gen_ori_i32(tmp, tmp, imm << 16);
7922 2c0262af bellard
                        } else {
7923 9ee6e8bb pbrook
                            /* movw */
7924 5e3f878a pbrook
                            tmp = new_tmp();
7925 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, imm);
7926 2c0262af bellard
                        }
7927 2c0262af bellard
                    } else {
7928 9ee6e8bb pbrook
                        /* Add/sub 12-bit immediate.  */
7929 9ee6e8bb pbrook
                        if (rn == 15) {
7930 b0109805 pbrook
                            offset = s->pc & ~(uint32_t)3;
7931 9ee6e8bb pbrook
                            if (insn & (1 << 23))
7932 b0109805 pbrook
                                offset -= imm;
7933 9ee6e8bb pbrook
                            else
7934 b0109805 pbrook
                                offset += imm;
7935 5e3f878a pbrook
                            tmp = new_tmp();
7936 5e3f878a pbrook
                            tcg_gen_movi_i32(tmp, offset);
7937 2c0262af bellard
                        } else {
7938 5e3f878a pbrook
                            tmp = load_reg(s, rn);
7939 9ee6e8bb pbrook
                            if (insn & (1 << 23))
7940 5e3f878a pbrook
                                tcg_gen_subi_i32(tmp, tmp, imm);
7941 9ee6e8bb pbrook
                            else
7942 5e3f878a pbrook
                                tcg_gen_addi_i32(tmp, tmp, imm);
7943 2c0262af bellard
                        }
7944 9ee6e8bb pbrook
                    }
7945 5e3f878a pbrook
                    store_reg(s, rd, tmp);
7946 191abaa2 pbrook
                }
7947 9ee6e8bb pbrook
            } else {
7948 9ee6e8bb pbrook
                int shifter_out = 0;
7949 9ee6e8bb pbrook
                /* modified 12-bit immediate.  */
7950 9ee6e8bb pbrook
                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7951 9ee6e8bb pbrook
                imm = (insn & 0xff);
7952 9ee6e8bb pbrook
                switch (shift) {
7953 9ee6e8bb pbrook
                case 0: /* XY */
7954 9ee6e8bb pbrook
                    /* Nothing to do.  */
7955 9ee6e8bb pbrook
                    break;
7956 9ee6e8bb pbrook
                case 1: /* 00XY00XY */
7957 9ee6e8bb pbrook
                    imm |= imm << 16;
7958 9ee6e8bb pbrook
                    break;
7959 9ee6e8bb pbrook
                case 2: /* XY00XY00 */
7960 9ee6e8bb pbrook
                    imm |= imm << 16;
7961 9ee6e8bb pbrook
                    imm <<= 8;
7962 9ee6e8bb pbrook
                    break;
7963 9ee6e8bb pbrook
                case 3: /* XYXYXYXY */
7964 9ee6e8bb pbrook
                    imm |= imm << 16;
7965 9ee6e8bb pbrook
                    imm |= imm << 8;
7966 9ee6e8bb pbrook
                    break;
7967 9ee6e8bb pbrook
                default: /* Rotated constant.  */
7968 9ee6e8bb pbrook
                    shift = (shift << 1) | (imm >> 7);
7969 9ee6e8bb pbrook
                    imm |= 0x80;
7970 9ee6e8bb pbrook
                    imm = imm << (32 - shift);
7971 9ee6e8bb pbrook
                    shifter_out = 1;
7972 9ee6e8bb pbrook
                    break;
7973 b5ff1b31 bellard
                }
7974 3174f8e9 Filip Navara
                tmp2 = new_tmp();
7975 3174f8e9 Filip Navara
                tcg_gen_movi_i32(tmp2, imm);
7976 9ee6e8bb pbrook
                rn = (insn >> 16) & 0xf;
7977 3174f8e9 Filip Navara
                if (rn == 15) {
7978 3174f8e9 Filip Navara
                    tmp = new_tmp();
7979 3174f8e9 Filip Navara
                    tcg_gen_movi_i32(tmp, 0);
7980 3174f8e9 Filip Navara
                } else {
7981 3174f8e9 Filip Navara
                    tmp = load_reg(s, rn);
7982 3174f8e9 Filip Navara
                }
7983 9ee6e8bb pbrook
                op = (insn >> 21) & 0xf;
7984 9ee6e8bb pbrook
                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7985 3174f8e9 Filip Navara
                                       shifter_out, tmp, tmp2))
7986 9ee6e8bb pbrook
                    goto illegal_op;
7987 3174f8e9 Filip Navara
                dead_tmp(tmp2);
7988 9ee6e8bb pbrook
                rd = (insn >> 8) & 0xf;
7989 9ee6e8bb pbrook
                if (rd != 15) {
7990 3174f8e9 Filip Navara
                    store_reg(s, rd, tmp);
7991 3174f8e9 Filip Navara
                } else {
7992 3174f8e9 Filip Navara
                    dead_tmp(tmp);
7993 2c0262af bellard
                }
7994 2c0262af bellard
            }
7995 9ee6e8bb pbrook
        }
7996 9ee6e8bb pbrook
        break;
7997 9ee6e8bb pbrook
    case 12: /* Load/store single data item.  */
7998 9ee6e8bb pbrook
        {
7999 9ee6e8bb pbrook
        int postinc = 0;
8000 9ee6e8bb pbrook
        int writeback = 0;
8001 b0109805 pbrook
        int user;
8002 9ee6e8bb pbrook
        if ((insn & 0x01100000) == 0x01000000) {
8003 9ee6e8bb pbrook
            if (disas_neon_ls_insn(env, s, insn))
8004 c1713132 balrog
                goto illegal_op;
8005 9ee6e8bb pbrook
            break;
8006 9ee6e8bb pbrook
        }
8007 b0109805 pbrook
        user = IS_USER(s);
8008 9ee6e8bb pbrook
        if (rn == 15) {
8009 b0109805 pbrook
            addr = new_tmp();
8010 9ee6e8bb pbrook
            /* PC relative.  */
8011 9ee6e8bb pbrook
            /* s->pc has already been incremented by 4.  */
8012 9ee6e8bb pbrook
            imm = s->pc & 0xfffffffc;
8013 9ee6e8bb pbrook
            if (insn & (1 << 23))
8014 9ee6e8bb pbrook
                imm += insn & 0xfff;
8015 9ee6e8bb pbrook
            else
8016 9ee6e8bb pbrook
                imm -= insn & 0xfff;
8017 b0109805 pbrook
            tcg_gen_movi_i32(addr, imm);
8018 9ee6e8bb pbrook
        } else {
8019 b0109805 pbrook
            addr = load_reg(s, rn);
8020 9ee6e8bb pbrook
            if (insn & (1 << 23)) {
8021 9ee6e8bb pbrook
                /* Positive offset.  */
8022 9ee6e8bb pbrook
                imm = insn & 0xfff;
8023 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, imm);
8024 9ee6e8bb pbrook
            } else {
8025 9ee6e8bb pbrook
                op = (insn >> 8) & 7;
8026 9ee6e8bb pbrook
                imm = insn & 0xff;
8027 9ee6e8bb pbrook
                switch (op) {
8028 9ee6e8bb pbrook
                case 0: case 8: /* Shifted Register.  */
8029 9ee6e8bb pbrook
                    shift = (insn >> 4) & 0xf;
8030 9ee6e8bb pbrook
                    if (shift > 3)
8031 18c9b560 balrog
                        goto illegal_op;
8032 b26eefb6 pbrook
                    tmp = load_reg(s, rm);
8033 9ee6e8bb pbrook
                    if (shift)
8034 b26eefb6 pbrook
                        tcg_gen_shli_i32(tmp, tmp, shift);
8035 b0109805 pbrook
                    tcg_gen_add_i32(addr, addr, tmp);
8036 b26eefb6 pbrook
                    dead_tmp(tmp);
8037 9ee6e8bb pbrook
                    break;
8038 9ee6e8bb pbrook
                case 4: /* Negative offset.  */
8039 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, -imm);
8040 9ee6e8bb pbrook
                    break;
8041 9ee6e8bb pbrook
                case 6: /* User privilege.  */
8042 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, imm);
8043 b0109805 pbrook
                    user = 1;
8044 9ee6e8bb pbrook
                    break;
8045 9ee6e8bb pbrook
                case 1: /* Post-decrement.  */
8046 9ee6e8bb pbrook
                    imm = -imm;
8047 9ee6e8bb pbrook
                    /* Fall through.  */
8048 9ee6e8bb pbrook
                case 3: /* Post-increment.  */
8049 9ee6e8bb pbrook
                    postinc = 1;
8050 9ee6e8bb pbrook
                    writeback = 1;
8051 9ee6e8bb pbrook
                    break;
8052 9ee6e8bb pbrook
                case 5: /* Pre-decrement.  */
8053 9ee6e8bb pbrook
                    imm = -imm;
8054 9ee6e8bb pbrook
                    /* Fall through.  */
8055 9ee6e8bb pbrook
                case 7: /* Pre-increment.  */
8056 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, imm);
8057 9ee6e8bb pbrook
                    writeback = 1;
8058 9ee6e8bb pbrook
                    break;
8059 9ee6e8bb pbrook
                default:
8060 b7bcbe95 bellard
                    goto illegal_op;
8061 9ee6e8bb pbrook
                }
8062 9ee6e8bb pbrook
            }
8063 9ee6e8bb pbrook
        }
8064 9ee6e8bb pbrook
        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8065 9ee6e8bb pbrook
        if (insn & (1 << 20)) {
8066 9ee6e8bb pbrook
            /* Load.  */
8067 9ee6e8bb pbrook
            if (rs == 15 && op != 2) {
8068 9ee6e8bb pbrook
                if (op & 2)
8069 b5ff1b31 bellard
                    goto illegal_op;
8070 9ee6e8bb pbrook
                /* Memory hint.  Implemented as NOP.  */
8071 9ee6e8bb pbrook
            } else {
8072 9ee6e8bb pbrook
                switch (op) {
8073 b0109805 pbrook
                case 0: tmp = gen_ld8u(addr, user); break;
8074 b0109805 pbrook
                case 4: tmp = gen_ld8s(addr, user); break;
8075 b0109805 pbrook
                case 1: tmp = gen_ld16u(addr, user); break;
8076 b0109805 pbrook
                case 5: tmp = gen_ld16s(addr, user); break;
8077 b0109805 pbrook
                case 2: tmp = gen_ld32(addr, user); break;
8078 9ee6e8bb pbrook
                default: goto illegal_op;
8079 9ee6e8bb pbrook
                }
8080 9ee6e8bb pbrook
                if (rs == 15) {
8081 b0109805 pbrook
                    gen_bx(s, tmp);
8082 9ee6e8bb pbrook
                } else {
8083 b0109805 pbrook
                    store_reg(s, rs, tmp);
8084 9ee6e8bb pbrook
                }
8085 9ee6e8bb pbrook
            }
8086 9ee6e8bb pbrook
        } else {
8087 9ee6e8bb pbrook
            /* Store.  */
8088 9ee6e8bb pbrook
            if (rs == 15)
8089 b7bcbe95 bellard
                goto illegal_op;
8090 b0109805 pbrook
            tmp = load_reg(s, rs);
8091 9ee6e8bb pbrook
            switch (op) {
8092 b0109805 pbrook
            case 0: gen_st8(tmp, addr, user); break;
8093 b0109805 pbrook
            case 1: gen_st16(tmp, addr, user); break;
8094 b0109805 pbrook
            case 2: gen_st32(tmp, addr, user); break;
8095 9ee6e8bb pbrook
            default: goto illegal_op;
8096 b7bcbe95 bellard
            }
8097 2c0262af bellard
        }
8098 9ee6e8bb pbrook
        if (postinc)
8099 b0109805 pbrook
            tcg_gen_addi_i32(addr, addr, imm);
8100 b0109805 pbrook
        if (writeback) {
8101 b0109805 pbrook
            store_reg(s, rn, addr);
8102 b0109805 pbrook
        } else {
8103 b0109805 pbrook
            dead_tmp(addr);
8104 b0109805 pbrook
        }
8105 9ee6e8bb pbrook
        }
8106 9ee6e8bb pbrook
        break;
8107 9ee6e8bb pbrook
    default:
8108 9ee6e8bb pbrook
        goto illegal_op;
8109 2c0262af bellard
    }
8110 9ee6e8bb pbrook
    return 0;
8111 9ee6e8bb pbrook
illegal_op:
8112 9ee6e8bb pbrook
    return 1;
8113 2c0262af bellard
}
8114 2c0262af bellard
8115 9ee6e8bb pbrook
static void disas_thumb_insn(CPUState *env, DisasContext *s)
8116 99c475ab bellard
{
8117 99c475ab bellard
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
8118 99c475ab bellard
    int32_t offset;
8119 99c475ab bellard
    int i;
8120 b26eefb6 pbrook
    TCGv tmp;
8121 d9ba4830 pbrook
    TCGv tmp2;
8122 b0109805 pbrook
    TCGv addr;
8123 99c475ab bellard
8124 9ee6e8bb pbrook
    if (s->condexec_mask) {
8125 9ee6e8bb pbrook
        cond = s->condexec_cond;
8126 9ee6e8bb pbrook
        s->condlabel = gen_new_label();
8127 d9ba4830 pbrook
        gen_test_cc(cond ^ 1, s->condlabel);
8128 9ee6e8bb pbrook
        s->condjmp = 1;
8129 9ee6e8bb pbrook
    }
8130 9ee6e8bb pbrook
8131 b5ff1b31 bellard
    insn = lduw_code(s->pc);
8132 99c475ab bellard
    s->pc += 2;
8133 b5ff1b31 bellard
8134 99c475ab bellard
    switch (insn >> 12) {
8135 99c475ab bellard
    case 0: case 1:
8136 396e467c Filip Navara
8137 99c475ab bellard
        rd = insn & 7;
8138 99c475ab bellard
        op = (insn >> 11) & 3;
8139 99c475ab bellard
        if (op == 3) {
8140 99c475ab bellard
            /* add/subtract */
8141 99c475ab bellard
            rn = (insn >> 3) & 7;
8142 396e467c Filip Navara
            tmp = load_reg(s, rn);
8143 99c475ab bellard
            if (insn & (1 << 10)) {
8144 99c475ab bellard
                /* immediate */
8145 396e467c Filip Navara
                tmp2 = new_tmp();
8146 396e467c Filip Navara
                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8147 99c475ab bellard
            } else {
8148 99c475ab bellard
                /* reg */
8149 99c475ab bellard
                rm = (insn >> 6) & 7;
8150 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
8151 99c475ab bellard
            }
8152 9ee6e8bb pbrook
            if (insn & (1 << 9)) {
8153 9ee6e8bb pbrook
                if (s->condexec_mask)
8154 396e467c Filip Navara
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8155 9ee6e8bb pbrook
                else
8156 396e467c Filip Navara
                    gen_helper_sub_cc(tmp, tmp, tmp2);
8157 9ee6e8bb pbrook
            } else {
8158 9ee6e8bb pbrook
                if (s->condexec_mask)
8159 396e467c Filip Navara
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8160 9ee6e8bb pbrook
                else
8161 396e467c Filip Navara
                    gen_helper_add_cc(tmp, tmp, tmp2);
8162 9ee6e8bb pbrook
            }
8163 396e467c Filip Navara
            dead_tmp(tmp2);
8164 396e467c Filip Navara
            store_reg(s, rd, tmp);
8165 99c475ab bellard
        } else {
8166 99c475ab bellard
            /* shift immediate */
8167 99c475ab bellard
            rm = (insn >> 3) & 7;
8168 99c475ab bellard
            shift = (insn >> 6) & 0x1f;
8169 9a119ff6 pbrook
            tmp = load_reg(s, rm);
8170 9a119ff6 pbrook
            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8171 9a119ff6 pbrook
            if (!s->condexec_mask)
8172 9a119ff6 pbrook
                gen_logic_CC(tmp);
8173 9a119ff6 pbrook
            store_reg(s, rd, tmp);
8174 99c475ab bellard
        }
8175 99c475ab bellard
        break;
8176 99c475ab bellard
    case 2: case 3:
8177 99c475ab bellard
        /* arithmetic large immediate */
8178 99c475ab bellard
        op = (insn >> 11) & 3;
8179 99c475ab bellard
        rd = (insn >> 8) & 0x7;
8180 396e467c Filip Navara
        if (op == 0) { /* mov */
8181 396e467c Filip Navara
            tmp = new_tmp();
8182 396e467c Filip Navara
            tcg_gen_movi_i32(tmp, insn & 0xff);
8183 9ee6e8bb pbrook
            if (!s->condexec_mask)
8184 396e467c Filip Navara
                gen_logic_CC(tmp);
8185 396e467c Filip Navara
            store_reg(s, rd, tmp);
8186 396e467c Filip Navara
        } else {
8187 396e467c Filip Navara
            tmp = load_reg(s, rd);
8188 396e467c Filip Navara
            tmp2 = new_tmp();
8189 396e467c Filip Navara
            tcg_gen_movi_i32(tmp2, insn & 0xff);
8190 396e467c Filip Navara
            switch (op) {
8191 396e467c Filip Navara
            case 1: /* cmp */
8192 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
8193 396e467c Filip Navara
                dead_tmp(tmp);
8194 396e467c Filip Navara
                dead_tmp(tmp2);
8195 396e467c Filip Navara
                break;
8196 396e467c Filip Navara
            case 2: /* add */
8197 396e467c Filip Navara
                if (s->condexec_mask)
8198 396e467c Filip Navara
                    tcg_gen_add_i32(tmp, tmp, tmp2);
8199 396e467c Filip Navara
                else
8200 396e467c Filip Navara
                    gen_helper_add_cc(tmp, tmp, tmp2);
8201 396e467c Filip Navara
                dead_tmp(tmp2);
8202 396e467c Filip Navara
                store_reg(s, rd, tmp);
8203 396e467c Filip Navara
                break;
8204 396e467c Filip Navara
            case 3: /* sub */
8205 396e467c Filip Navara
                if (s->condexec_mask)
8206 396e467c Filip Navara
                    tcg_gen_sub_i32(tmp, tmp, tmp2);
8207 396e467c Filip Navara
                else
8208 396e467c Filip Navara
                    gen_helper_sub_cc(tmp, tmp, tmp2);
8209 396e467c Filip Navara
                dead_tmp(tmp2);
8210 396e467c Filip Navara
                store_reg(s, rd, tmp);
8211 396e467c Filip Navara
                break;
8212 396e467c Filip Navara
            }
8213 99c475ab bellard
        }
8214 99c475ab bellard
        break;
8215 99c475ab bellard
    case 4:
8216 99c475ab bellard
        if (insn & (1 << 11)) {
8217 99c475ab bellard
            rd = (insn >> 8) & 7;
8218 5899f386 bellard
            /* load pc-relative.  Bit 1 of PC is ignored.  */
8219 5899f386 bellard
            val = s->pc + 2 + ((insn & 0xff) * 4);
8220 5899f386 bellard
            val &= ~(uint32_t)2;
8221 b0109805 pbrook
            addr = new_tmp();
8222 b0109805 pbrook
            tcg_gen_movi_i32(addr, val);
8223 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
8224 b0109805 pbrook
            dead_tmp(addr);
8225 b0109805 pbrook
            store_reg(s, rd, tmp);
8226 99c475ab bellard
            break;
8227 99c475ab bellard
        }
8228 99c475ab bellard
        if (insn & (1 << 10)) {
8229 99c475ab bellard
            /* data processing extended or blx */
8230 99c475ab bellard
            rd = (insn & 7) | ((insn >> 4) & 8);
8231 99c475ab bellard
            rm = (insn >> 3) & 0xf;
8232 99c475ab bellard
            op = (insn >> 8) & 3;
8233 99c475ab bellard
            switch (op) {
8234 99c475ab bellard
            case 0: /* add */
8235 396e467c Filip Navara
                tmp = load_reg(s, rd);
8236 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
8237 396e467c Filip Navara
                tcg_gen_add_i32(tmp, tmp, tmp2);
8238 396e467c Filip Navara
                dead_tmp(tmp2);
8239 396e467c Filip Navara
                store_reg(s, rd, tmp);
8240 99c475ab bellard
                break;
8241 99c475ab bellard
            case 1: /* cmp */
8242 396e467c Filip Navara
                tmp = load_reg(s, rd);
8243 396e467c Filip Navara
                tmp2 = load_reg(s, rm);
8244 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
8245 396e467c Filip Navara
                dead_tmp(tmp2);
8246 396e467c Filip Navara
                dead_tmp(tmp);
8247 99c475ab bellard
                break;
8248 99c475ab bellard
            case 2: /* mov/cpy */
8249 396e467c Filip Navara
                tmp = load_reg(s, rm);
8250 396e467c Filip Navara
                store_reg(s, rd, tmp);
8251 99c475ab bellard
                break;
8252 99c475ab bellard
            case 3:/* branch [and link] exchange thumb register */
8253 b0109805 pbrook
                tmp = load_reg(s, rm);
8254 99c475ab bellard
                if (insn & (1 << 7)) {
8255 99c475ab bellard
                    val = (uint32_t)s->pc | 1;
8256 b0109805 pbrook
                    tmp2 = new_tmp();
8257 b0109805 pbrook
                    tcg_gen_movi_i32(tmp2, val);
8258 b0109805 pbrook
                    store_reg(s, 14, tmp2);
8259 99c475ab bellard
                }
8260 d9ba4830 pbrook
                gen_bx(s, tmp);
8261 99c475ab bellard
                break;
8262 99c475ab bellard
            }
8263 99c475ab bellard
            break;
8264 99c475ab bellard
        }
8265 99c475ab bellard
8266 99c475ab bellard
        /* data processing register */
8267 99c475ab bellard
        rd = insn & 7;
8268 99c475ab bellard
        rm = (insn >> 3) & 7;
8269 99c475ab bellard
        op = (insn >> 6) & 0xf;
8270 99c475ab bellard
        if (op == 2 || op == 3 || op == 4 || op == 7) {
8271 99c475ab bellard
            /* the shift/rotate ops want the operands backwards */
8272 99c475ab bellard
            val = rm;
8273 99c475ab bellard
            rm = rd;
8274 99c475ab bellard
            rd = val;
8275 99c475ab bellard
            val = 1;
8276 99c475ab bellard
        } else {
8277 99c475ab bellard
            val = 0;
8278 99c475ab bellard
        }
8279 99c475ab bellard
8280 396e467c Filip Navara
        if (op == 9) { /* neg */
8281 396e467c Filip Navara
            tmp = new_tmp();
8282 396e467c Filip Navara
            tcg_gen_movi_i32(tmp, 0);
8283 396e467c Filip Navara
        } else if (op != 0xf) { /* mvn doesn't read its first operand */
8284 396e467c Filip Navara
            tmp = load_reg(s, rd);
8285 396e467c Filip Navara
        } else {
8286 396e467c Filip Navara
            TCGV_UNUSED(tmp);
8287 396e467c Filip Navara
        }
8288 99c475ab bellard
8289 396e467c Filip Navara
        tmp2 = load_reg(s, rm);
8290 5899f386 bellard
        switch (op) {
8291 99c475ab bellard
        case 0x0: /* and */
8292 396e467c Filip Navara
            tcg_gen_and_i32(tmp, tmp, tmp2);
8293 9ee6e8bb pbrook
            if (!s->condexec_mask)
8294 396e467c Filip Navara
                gen_logic_CC(tmp);
8295 99c475ab bellard
            break;
8296 99c475ab bellard
        case 0x1: /* eor */
8297 396e467c Filip Navara
            tcg_gen_xor_i32(tmp, tmp, tmp2);
8298 9ee6e8bb pbrook
            if (!s->condexec_mask)
8299 396e467c Filip Navara
                gen_logic_CC(tmp);
8300 99c475ab bellard
            break;
8301 99c475ab bellard
        case 0x2: /* lsl */
8302 9ee6e8bb pbrook
            if (s->condexec_mask) {
8303 396e467c Filip Navara
                gen_helper_shl(tmp2, tmp2, tmp);
8304 9ee6e8bb pbrook
            } else {
8305 396e467c Filip Navara
                gen_helper_shl_cc(tmp2, tmp2, tmp);
8306 396e467c Filip Navara
                gen_logic_CC(tmp2);
8307 9ee6e8bb pbrook
            }
8308 99c475ab bellard
            break;
8309 99c475ab bellard
        case 0x3: /* lsr */
8310 9ee6e8bb pbrook
            if (s->condexec_mask) {
8311 396e467c Filip Navara
                gen_helper_shr(tmp2, tmp2, tmp);
8312 9ee6e8bb pbrook
            } else {
8313 396e467c Filip Navara
                gen_helper_shr_cc(tmp2, tmp2, tmp);
8314 396e467c Filip Navara
                gen_logic_CC(tmp2);
8315 9ee6e8bb pbrook
            }
8316 99c475ab bellard
            break;
8317 99c475ab bellard
        case 0x4: /* asr */
8318 9ee6e8bb pbrook
            if (s->condexec_mask) {
8319 396e467c Filip Navara
                gen_helper_sar(tmp2, tmp2, tmp);
8320 9ee6e8bb pbrook
            } else {
8321 396e467c Filip Navara
                gen_helper_sar_cc(tmp2, tmp2, tmp);
8322 396e467c Filip Navara
                gen_logic_CC(tmp2);
8323 9ee6e8bb pbrook
            }
8324 99c475ab bellard
            break;
8325 99c475ab bellard
        case 0x5: /* adc */
8326 9ee6e8bb pbrook
            if (s->condexec_mask)
8327 396e467c Filip Navara
                gen_adc(tmp, tmp2);
8328 9ee6e8bb pbrook
            else
8329 396e467c Filip Navara
                gen_helper_adc_cc(tmp, tmp, tmp2);
8330 99c475ab bellard
            break;
8331 99c475ab bellard
        case 0x6: /* sbc */
8332 9ee6e8bb pbrook
            if (s->condexec_mask)
8333 396e467c Filip Navara
                gen_sub_carry(tmp, tmp, tmp2);
8334 9ee6e8bb pbrook
            else
8335 396e467c Filip Navara
                gen_helper_sbc_cc(tmp, tmp, tmp2);
8336 99c475ab bellard
            break;
8337 99c475ab bellard
        case 0x7: /* ror */
8338 9ee6e8bb pbrook
            if (s->condexec_mask) {
8339 396e467c Filip Navara
                gen_helper_ror(tmp2, tmp2, tmp);
8340 9ee6e8bb pbrook
            } else {
8341 396e467c Filip Navara
                gen_helper_ror_cc(tmp2, tmp2, tmp);
8342 396e467c Filip Navara
                gen_logic_CC(tmp2);
8343 9ee6e8bb pbrook
            }
8344 99c475ab bellard
            break;
8345 99c475ab bellard
        case 0x8: /* tst */
8346 396e467c Filip Navara
            tcg_gen_and_i32(tmp, tmp, tmp2);
8347 396e467c Filip Navara
            gen_logic_CC(tmp);
8348 99c475ab bellard
            rd = 16;
8349 5899f386 bellard
            break;
8350 99c475ab bellard
        case 0x9: /* neg */
8351 9ee6e8bb pbrook
            if (s->condexec_mask)
8352 396e467c Filip Navara
                tcg_gen_neg_i32(tmp, tmp2);
8353 9ee6e8bb pbrook
            else
8354 396e467c Filip Navara
                gen_helper_sub_cc(tmp, tmp, tmp2);
8355 99c475ab bellard
            break;
8356 99c475ab bellard
        case 0xa: /* cmp */
8357 396e467c Filip Navara
            gen_helper_sub_cc(tmp, tmp, tmp2);
8358 99c475ab bellard
            rd = 16;
8359 99c475ab bellard
            break;
8360 99c475ab bellard
        case 0xb: /* cmn */
8361 396e467c Filip Navara
            gen_helper_add_cc(tmp, tmp, tmp2);
8362 99c475ab bellard
            rd = 16;
8363 99c475ab bellard
            break;
8364 99c475ab bellard
        case 0xc: /* orr */
8365 396e467c Filip Navara
            tcg_gen_or_i32(tmp, tmp, tmp2);
8366 9ee6e8bb pbrook
            if (!s->condexec_mask)
8367 396e467c Filip Navara
                gen_logic_CC(tmp);
8368 99c475ab bellard
            break;
8369 99c475ab bellard
        case 0xd: /* mul */
8370 396e467c Filip Navara
            gen_mull(tmp, tmp2);
8371 9ee6e8bb pbrook
            if (!s->condexec_mask)
8372 396e467c Filip Navara
                gen_logic_CC(tmp);
8373 99c475ab bellard
            break;
8374 99c475ab bellard
        case 0xe: /* bic */
8375 396e467c Filip Navara
            tcg_gen_bic_i32(tmp, tmp, tmp2);
8376 9ee6e8bb pbrook
            if (!s->condexec_mask)
8377 396e467c Filip Navara
                gen_logic_CC(tmp);
8378 99c475ab bellard
            break;
8379 99c475ab bellard
        case 0xf: /* mvn */
8380 396e467c Filip Navara
            tcg_gen_not_i32(tmp2, tmp2);
8381 9ee6e8bb pbrook
            if (!s->condexec_mask)
8382 396e467c Filip Navara
                gen_logic_CC(tmp2);
8383 99c475ab bellard
            val = 1;
8384 5899f386 bellard
            rm = rd;
8385 99c475ab bellard
            break;
8386 99c475ab bellard
        }
8387 99c475ab bellard
        if (rd != 16) {
8388 396e467c Filip Navara
            if (val) {
8389 396e467c Filip Navara
                store_reg(s, rm, tmp2);
8390 396e467c Filip Navara
                if (op != 0xf)
8391 396e467c Filip Navara
                    dead_tmp(tmp);
8392 396e467c Filip Navara
            } else {
8393 396e467c Filip Navara
                store_reg(s, rd, tmp);
8394 396e467c Filip Navara
                dead_tmp(tmp2);
8395 396e467c Filip Navara
            }
8396 396e467c Filip Navara
        } else {
8397 396e467c Filip Navara
            dead_tmp(tmp);
8398 396e467c Filip Navara
            dead_tmp(tmp2);
8399 99c475ab bellard
        }
8400 99c475ab bellard
        break;
8401 99c475ab bellard
8402 99c475ab bellard
    case 5:
8403 99c475ab bellard
        /* load/store register offset.  */
8404 99c475ab bellard
        rd = insn & 7;
8405 99c475ab bellard
        rn = (insn >> 3) & 7;
8406 99c475ab bellard
        rm = (insn >> 6) & 7;
8407 99c475ab bellard
        op = (insn >> 9) & 7;
8408 b0109805 pbrook
        addr = load_reg(s, rn);
8409 b26eefb6 pbrook
        tmp = load_reg(s, rm);
8410 b0109805 pbrook
        tcg_gen_add_i32(addr, addr, tmp);
8411 b26eefb6 pbrook
        dead_tmp(tmp);
8412 99c475ab bellard
8413 99c475ab bellard
        if (op < 3) /* store */
8414 b0109805 pbrook
            tmp = load_reg(s, rd);
8415 99c475ab bellard
8416 99c475ab bellard
        switch (op) {
8417 99c475ab bellard
        case 0: /* str */
8418 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
8419 99c475ab bellard
            break;
8420 99c475ab bellard
        case 1: /* strh */
8421 b0109805 pbrook
            gen_st16(tmp, addr, IS_USER(s));
8422 99c475ab bellard
            break;
8423 99c475ab bellard
        case 2: /* strb */
8424 b0109805 pbrook
            gen_st8(tmp, addr, IS_USER(s));
8425 99c475ab bellard
            break;
8426 99c475ab bellard
        case 3: /* ldrsb */
8427 b0109805 pbrook
            tmp = gen_ld8s(addr, IS_USER(s));
8428 99c475ab bellard
            break;
8429 99c475ab bellard
        case 4: /* ldr */
8430 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
8431 99c475ab bellard
            break;
8432 99c475ab bellard
        case 5: /* ldrh */
8433 b0109805 pbrook
            tmp = gen_ld16u(addr, IS_USER(s));
8434 99c475ab bellard
            break;
8435 99c475ab bellard
        case 6: /* ldrb */
8436 b0109805 pbrook
            tmp = gen_ld8u(addr, IS_USER(s));
8437 99c475ab bellard
            break;
8438 99c475ab bellard
        case 7: /* ldrsh */
8439 b0109805 pbrook
            tmp = gen_ld16s(addr, IS_USER(s));
8440 99c475ab bellard
            break;
8441 99c475ab bellard
        }
8442 99c475ab bellard
        if (op >= 3) /* load */
8443 b0109805 pbrook
            store_reg(s, rd, tmp);
8444 b0109805 pbrook
        dead_tmp(addr);
8445 99c475ab bellard
        break;
8446 99c475ab bellard
8447 99c475ab bellard
    case 6:
8448 99c475ab bellard
        /* load/store word immediate offset */
8449 99c475ab bellard
        rd = insn & 7;
8450 99c475ab bellard
        rn = (insn >> 3) & 7;
8451 b0109805 pbrook
        addr = load_reg(s, rn);
8452 99c475ab bellard
        val = (insn >> 4) & 0x7c;
8453 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
8454 99c475ab bellard
8455 99c475ab bellard
        if (insn & (1 << 11)) {
8456 99c475ab bellard
            /* load */
8457 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
8458 b0109805 pbrook
            store_reg(s, rd, tmp);
8459 99c475ab bellard
        } else {
8460 99c475ab bellard
            /* store */
8461 b0109805 pbrook
            tmp = load_reg(s, rd);
8462 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
8463 99c475ab bellard
        }
8464 b0109805 pbrook
        dead_tmp(addr);
8465 99c475ab bellard
        break;
8466 99c475ab bellard
8467 99c475ab bellard
    case 7:
8468 99c475ab bellard
        /* load/store byte immediate offset */
8469 99c475ab bellard
        rd = insn & 7;
8470 99c475ab bellard
        rn = (insn >> 3) & 7;
8471 b0109805 pbrook
        addr = load_reg(s, rn);
8472 99c475ab bellard
        val = (insn >> 6) & 0x1f;
8473 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
8474 99c475ab bellard
8475 99c475ab bellard
        if (insn & (1 << 11)) {
8476 99c475ab bellard
            /* load */
8477 b0109805 pbrook
            tmp = gen_ld8u(addr, IS_USER(s));
8478 b0109805 pbrook
            store_reg(s, rd, tmp);
8479 99c475ab bellard
        } else {
8480 99c475ab bellard
            /* store */
8481 b0109805 pbrook
            tmp = load_reg(s, rd);
8482 b0109805 pbrook
            gen_st8(tmp, addr, IS_USER(s));
8483 99c475ab bellard
        }
8484 b0109805 pbrook
        dead_tmp(addr);
8485 99c475ab bellard
        break;
8486 99c475ab bellard
8487 99c475ab bellard
    case 8:
8488 99c475ab bellard
        /* load/store halfword immediate offset */
8489 99c475ab bellard
        rd = insn & 7;
8490 99c475ab bellard
        rn = (insn >> 3) & 7;
8491 b0109805 pbrook
        addr = load_reg(s, rn);
8492 99c475ab bellard
        val = (insn >> 5) & 0x3e;
8493 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
8494 99c475ab bellard
8495 99c475ab bellard
        if (insn & (1 << 11)) {
8496 99c475ab bellard
            /* load */
8497 b0109805 pbrook
            tmp = gen_ld16u(addr, IS_USER(s));
8498 b0109805 pbrook
            store_reg(s, rd, tmp);
8499 99c475ab bellard
        } else {
8500 99c475ab bellard
            /* store */
8501 b0109805 pbrook
            tmp = load_reg(s, rd);
8502 b0109805 pbrook
            gen_st16(tmp, addr, IS_USER(s));
8503 99c475ab bellard
        }
8504 b0109805 pbrook
        dead_tmp(addr);
8505 99c475ab bellard
        break;
8506 99c475ab bellard
8507 99c475ab bellard
    case 9:
8508 99c475ab bellard
        /* load/store from stack */
8509 99c475ab bellard
        rd = (insn >> 8) & 7;
8510 b0109805 pbrook
        addr = load_reg(s, 13);
8511 99c475ab bellard
        val = (insn & 0xff) * 4;
8512 b0109805 pbrook
        tcg_gen_addi_i32(addr, addr, val);
8513 99c475ab bellard
8514 99c475ab bellard
        if (insn & (1 << 11)) {
8515 99c475ab bellard
            /* load */
8516 b0109805 pbrook
            tmp = gen_ld32(addr, IS_USER(s));
8517 b0109805 pbrook
            store_reg(s, rd, tmp);
8518 99c475ab bellard
        } else {
8519 99c475ab bellard
            /* store */
8520 b0109805 pbrook
            tmp = load_reg(s, rd);
8521 b0109805 pbrook
            gen_st32(tmp, addr, IS_USER(s));
8522 99c475ab bellard
        }
8523 b0109805 pbrook
        dead_tmp(addr);
8524 99c475ab bellard
        break;
8525 99c475ab bellard
8526 99c475ab bellard
    case 10:
8527 99c475ab bellard
        /* add to high reg */
8528 99c475ab bellard
        rd = (insn >> 8) & 7;
8529 5899f386 bellard
        if (insn & (1 << 11)) {
8530 5899f386 bellard
            /* SP */
8531 5e3f878a pbrook
            tmp = load_reg(s, 13);
8532 5899f386 bellard
        } else {
8533 5899f386 bellard
            /* PC. bit 1 is ignored.  */
8534 5e3f878a pbrook
            tmp = new_tmp();
8535 5e3f878a pbrook
            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8536 5899f386 bellard
        }
8537 99c475ab bellard
        val = (insn & 0xff) * 4;
8538 5e3f878a pbrook
        tcg_gen_addi_i32(tmp, tmp, val);
8539 5e3f878a pbrook
        store_reg(s, rd, tmp);
8540 99c475ab bellard
        break;
8541 99c475ab bellard
8542 99c475ab bellard
    case 11:
8543 99c475ab bellard
        /* misc */
8544 99c475ab bellard
        op = (insn >> 8) & 0xf;
8545 99c475ab bellard
        switch (op) {
8546 99c475ab bellard
        case 0:
8547 99c475ab bellard
            /* adjust stack pointer */
8548 b26eefb6 pbrook
            tmp = load_reg(s, 13);
8549 99c475ab bellard
            val = (insn & 0x7f) * 4;
8550 99c475ab bellard
            if (insn & (1 << 7))
8551 6a0d8a1d balrog
                val = -(int32_t)val;
8552 b26eefb6 pbrook
            tcg_gen_addi_i32(tmp, tmp, val);
8553 b26eefb6 pbrook
            store_reg(s, 13, tmp);
8554 99c475ab bellard
            break;
8555 99c475ab bellard
8556 9ee6e8bb pbrook
        case 2: /* sign/zero extend.  */
8557 9ee6e8bb pbrook
            ARCH(6);
8558 9ee6e8bb pbrook
            rd = insn & 7;
8559 9ee6e8bb pbrook
            rm = (insn >> 3) & 7;
8560 b0109805 pbrook
            tmp = load_reg(s, rm);
8561 9ee6e8bb pbrook
            switch ((insn >> 6) & 3) {
8562 b0109805 pbrook
            case 0: gen_sxth(tmp); break;
8563 b0109805 pbrook
            case 1: gen_sxtb(tmp); break;
8564 b0109805 pbrook
            case 2: gen_uxth(tmp); break;
8565 b0109805 pbrook
            case 3: gen_uxtb(tmp); break;
8566 9ee6e8bb pbrook
            }
8567 b0109805 pbrook
            store_reg(s, rd, tmp);
8568 9ee6e8bb pbrook
            break;
8569 99c475ab bellard
        case 4: case 5: case 0xc: case 0xd:
8570 99c475ab bellard
            /* push/pop */
8571 b0109805 pbrook
            addr = load_reg(s, 13);
8572 5899f386 bellard
            if (insn & (1 << 8))
8573 5899f386 bellard
                offset = 4;
8574 99c475ab bellard
            else
8575 5899f386 bellard
                offset = 0;
8576 5899f386 bellard
            for (i = 0; i < 8; i++) {
8577 5899f386 bellard
                if (insn & (1 << i))
8578 5899f386 bellard
                    offset += 4;
8579 5899f386 bellard
            }
8580 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
8581 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, -offset);
8582 5899f386 bellard
            }
8583 99c475ab bellard
            for (i = 0; i < 8; i++) {
8584 99c475ab bellard
                if (insn & (1 << i)) {
8585 99c475ab bellard
                    if (insn & (1 << 11)) {
8586 99c475ab bellard
                        /* pop */
8587 b0109805 pbrook
                        tmp = gen_ld32(addr, IS_USER(s));
8588 b0109805 pbrook
                        store_reg(s, i, tmp);
8589 99c475ab bellard
                    } else {
8590 99c475ab bellard
                        /* push */
8591 b0109805 pbrook
                        tmp = load_reg(s, i);
8592 b0109805 pbrook
                        gen_st32(tmp, addr, IS_USER(s));
8593 99c475ab bellard
                    }
8594 5899f386 bellard
                    /* advance to the next address.  */
8595 b0109805 pbrook
                    tcg_gen_addi_i32(addr, addr, 4);
8596 99c475ab bellard
                }
8597 99c475ab bellard
            }
8598 a50f5b91 pbrook
            TCGV_UNUSED(tmp);
8599 99c475ab bellard
            if (insn & (1 << 8)) {
8600 99c475ab bellard
                if (insn & (1 << 11)) {
8601 99c475ab bellard
                    /* pop pc */
8602 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
8603 99c475ab bellard
                    /* don't set the pc until the rest of the instruction
8604 99c475ab bellard
                       has completed */
8605 99c475ab bellard
                } else {
8606 99c475ab bellard
                    /* push lr */
8607 b0109805 pbrook
                    tmp = load_reg(s, 14);
8608 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
8609 99c475ab bellard
                }
8610 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, 4);
8611 99c475ab bellard
            }
8612 5899f386 bellard
            if ((insn & (1 << 11)) == 0) {
8613 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, -offset);
8614 5899f386 bellard
            }
8615 99c475ab bellard
            /* write back the new stack pointer */
8616 b0109805 pbrook
            store_reg(s, 13, addr);
8617 99c475ab bellard
            /* set the new PC value */
8618 99c475ab bellard
            if ((insn & 0x0900) == 0x0900)
8619 b0109805 pbrook
                gen_bx(s, tmp);
8620 99c475ab bellard
            break;
8621 99c475ab bellard
8622 9ee6e8bb pbrook
        case 1: case 3: case 9: case 11: /* czb */
8623 9ee6e8bb pbrook
            rm = insn & 7;
8624 d9ba4830 pbrook
            tmp = load_reg(s, rm);
8625 9ee6e8bb pbrook
            s->condlabel = gen_new_label();
8626 9ee6e8bb pbrook
            s->condjmp = 1;
8627 9ee6e8bb pbrook
            if (insn & (1 << 11))
8628 cb63669a pbrook
                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8629 9ee6e8bb pbrook
            else
8630 cb63669a pbrook
                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8631 d9ba4830 pbrook
            dead_tmp(tmp);
8632 9ee6e8bb pbrook
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8633 9ee6e8bb pbrook
            val = (uint32_t)s->pc + 2;
8634 9ee6e8bb pbrook
            val += offset;
8635 9ee6e8bb pbrook
            gen_jmp(s, val);
8636 9ee6e8bb pbrook
            break;
8637 9ee6e8bb pbrook
8638 9ee6e8bb pbrook
        case 15: /* IT, nop-hint.  */
8639 9ee6e8bb pbrook
            if ((insn & 0xf) == 0) {
8640 9ee6e8bb pbrook
                gen_nop_hint(s, (insn >> 4) & 0xf);
8641 9ee6e8bb pbrook
                break;
8642 9ee6e8bb pbrook
            }
8643 9ee6e8bb pbrook
            /* If Then.  */
8644 9ee6e8bb pbrook
            s->condexec_cond = (insn >> 4) & 0xe;
8645 9ee6e8bb pbrook
            s->condexec_mask = insn & 0x1f;
8646 9ee6e8bb pbrook
            /* No actual code generated for this insn, just setup state.  */
8647 9ee6e8bb pbrook
            break;
8648 9ee6e8bb pbrook
8649 06c949e6 pbrook
        case 0xe: /* bkpt */
8650 9ee6e8bb pbrook
            gen_set_condexec(s);
8651 5e3f878a pbrook
            gen_set_pc_im(s->pc - 2);
8652 d9ba4830 pbrook
            gen_exception(EXCP_BKPT);
8653 06c949e6 pbrook
            s->is_jmp = DISAS_JUMP;
8654 06c949e6 pbrook
            break;
8655 06c949e6 pbrook
8656 9ee6e8bb pbrook
        case 0xa: /* rev */
8657 9ee6e8bb pbrook
            ARCH(6);
8658 9ee6e8bb pbrook
            rn = (insn >> 3) & 0x7;
8659 9ee6e8bb pbrook
            rd = insn & 0x7;
8660 b0109805 pbrook
            tmp = load_reg(s, rn);
8661 9ee6e8bb pbrook
            switch ((insn >> 6) & 3) {
8662 66896cb8 aurel32
            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8663 b0109805 pbrook
            case 1: gen_rev16(tmp); break;
8664 b0109805 pbrook
            case 3: gen_revsh(tmp); break;
8665 9ee6e8bb pbrook
            default: goto illegal_op;
8666 9ee6e8bb pbrook
            }
8667 b0109805 pbrook
            store_reg(s, rd, tmp);
8668 9ee6e8bb pbrook
            break;
8669 9ee6e8bb pbrook
8670 9ee6e8bb pbrook
        case 6: /* cps */
8671 9ee6e8bb pbrook
            ARCH(6);
8672 9ee6e8bb pbrook
            if (IS_USER(s))
8673 9ee6e8bb pbrook
                break;
8674 9ee6e8bb pbrook
            if (IS_M(env)) {
8675 8984bd2e pbrook
                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8676 9ee6e8bb pbrook
                /* PRIMASK */
8677 8984bd2e pbrook
                if (insn & 1) {
8678 8984bd2e pbrook
                    addr = tcg_const_i32(16);
8679 8984bd2e pbrook
                    gen_helper_v7m_msr(cpu_env, addr, tmp);
8680 8984bd2e pbrook
                }
8681 9ee6e8bb pbrook
                /* FAULTMASK */
8682 8984bd2e pbrook
                if (insn & 2) {
8683 8984bd2e pbrook
                    addr = tcg_const_i32(17);
8684 8984bd2e pbrook
                    gen_helper_v7m_msr(cpu_env, addr, tmp);
8685 8984bd2e pbrook
                }
8686 9ee6e8bb pbrook
                gen_lookup_tb(s);
8687 9ee6e8bb pbrook
            } else {
8688 9ee6e8bb pbrook
                if (insn & (1 << 4))
8689 9ee6e8bb pbrook
                    shift = CPSR_A | CPSR_I | CPSR_F;
8690 9ee6e8bb pbrook
                else
8691 9ee6e8bb pbrook
                    shift = 0;
8692 2fbac54b Filip Navara
                gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8693 9ee6e8bb pbrook
            }
8694 9ee6e8bb pbrook
            break;
8695 9ee6e8bb pbrook
8696 99c475ab bellard
        default:
8697 99c475ab bellard
            goto undef;
8698 99c475ab bellard
        }
8699 99c475ab bellard
        break;
8700 99c475ab bellard
8701 99c475ab bellard
    case 12:
8702 99c475ab bellard
        /* load/store multiple */
8703 99c475ab bellard
        rn = (insn >> 8) & 0x7;
8704 b0109805 pbrook
        addr = load_reg(s, rn);
8705 99c475ab bellard
        for (i = 0; i < 8; i++) {
8706 99c475ab bellard
            if (insn & (1 << i)) {
8707 99c475ab bellard
                if (insn & (1 << 11)) {
8708 99c475ab bellard
                    /* load */
8709 b0109805 pbrook
                    tmp = gen_ld32(addr, IS_USER(s));
8710 b0109805 pbrook
                    store_reg(s, i, tmp);
8711 99c475ab bellard
                } else {
8712 99c475ab bellard
                    /* store */
8713 b0109805 pbrook
                    tmp = load_reg(s, i);
8714 b0109805 pbrook
                    gen_st32(tmp, addr, IS_USER(s));
8715 99c475ab bellard
                }
8716 5899f386 bellard
                /* advance to the next address */
8717 b0109805 pbrook
                tcg_gen_addi_i32(addr, addr, 4);
8718 99c475ab bellard
            }
8719 99c475ab bellard
        }
8720 5899f386 bellard
        /* Base register writeback.  */
8721 b0109805 pbrook
        if ((insn & (1 << rn)) == 0) {
8722 b0109805 pbrook
            store_reg(s, rn, addr);
8723 b0109805 pbrook
        } else {
8724 b0109805 pbrook
            dead_tmp(addr);
8725 b0109805 pbrook
        }
8726 99c475ab bellard
        break;
8727 99c475ab bellard
8728 99c475ab bellard
    case 13:
8729 99c475ab bellard
        /* conditional branch or swi */
8730 99c475ab bellard
        cond = (insn >> 8) & 0xf;
8731 99c475ab bellard
        if (cond == 0xe)
8732 99c475ab bellard
            goto undef;
8733 99c475ab bellard
8734 99c475ab bellard
        if (cond == 0xf) {
8735 99c475ab bellard
            /* swi */
8736 9ee6e8bb pbrook
            gen_set_condexec(s);
8737 422ebf69 balrog
            gen_set_pc_im(s->pc);
8738 9ee6e8bb pbrook
            s->is_jmp = DISAS_SWI;
8739 99c475ab bellard
            break;
8740 99c475ab bellard
        }
8741 99c475ab bellard
        /* generate a conditional jump to next instruction */
8742 e50e6a20 bellard
        s->condlabel = gen_new_label();
8743 d9ba4830 pbrook
        gen_test_cc(cond ^ 1, s->condlabel);
8744 e50e6a20 bellard
        s->condjmp = 1;
8745 99c475ab bellard
8746 99c475ab bellard
        /* jump to the offset */
8747 5899f386 bellard
        val = (uint32_t)s->pc + 2;
8748 99c475ab bellard
        offset = ((int32_t)insn << 24) >> 24;
8749 5899f386 bellard
        val += offset << 1;
8750 8aaca4c0 bellard
        gen_jmp(s, val);
8751 99c475ab bellard
        break;
8752 99c475ab bellard
8753 99c475ab bellard
    case 14:
8754 358bf29e pbrook
        if (insn & (1 << 11)) {
8755 9ee6e8bb pbrook
            if (disas_thumb2_insn(env, s, insn))
8756 9ee6e8bb pbrook
              goto undef32;
8757 358bf29e pbrook
            break;
8758 358bf29e pbrook
        }
8759 9ee6e8bb pbrook
        /* unconditional branch */
8760 99c475ab bellard
        val = (uint32_t)s->pc;
8761 99c475ab bellard
        offset = ((int32_t)insn << 21) >> 21;
8762 99c475ab bellard
        val += (offset << 1) + 2;
8763 8aaca4c0 bellard
        gen_jmp(s, val);
8764 99c475ab bellard
        break;
8765 99c475ab bellard
8766 99c475ab bellard
    case 15:
8767 9ee6e8bb pbrook
        if (disas_thumb2_insn(env, s, insn))
8768 6a0d8a1d balrog
            goto undef32;
8769 9ee6e8bb pbrook
        break;
8770 99c475ab bellard
    }
8771 99c475ab bellard
    return;
8772 9ee6e8bb pbrook
undef32:
8773 9ee6e8bb pbrook
    gen_set_condexec(s);
8774 5e3f878a pbrook
    gen_set_pc_im(s->pc - 4);
8775 d9ba4830 pbrook
    gen_exception(EXCP_UDEF);
8776 9ee6e8bb pbrook
    s->is_jmp = DISAS_JUMP;
8777 9ee6e8bb pbrook
    return;
8778 9ee6e8bb pbrook
illegal_op:
8779 99c475ab bellard
undef:
8780 9ee6e8bb pbrook
    gen_set_condexec(s);
8781 5e3f878a pbrook
    gen_set_pc_im(s->pc - 2);
8782 d9ba4830 pbrook
    gen_exception(EXCP_UDEF);
8783 99c475ab bellard
    s->is_jmp = DISAS_JUMP;
8784 99c475ab bellard
}
8785 99c475ab bellard
8786 2c0262af bellard
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8787 2c0262af bellard
   basic block 'tb'. If search_pc is TRUE, also generate PC
8788 2c0262af bellard
   information for each intermediate instruction. */
8789 2cfc5f17 ths
static inline void gen_intermediate_code_internal(CPUState *env,
8790 2cfc5f17 ths
                                                  TranslationBlock *tb,
8791 2cfc5f17 ths
                                                  int search_pc)
8792 2c0262af bellard
{
8793 2c0262af bellard
    DisasContext dc1, *dc = &dc1;
8794 a1d1bb31 aliguori
    CPUBreakpoint *bp;
8795 2c0262af bellard
    uint16_t *gen_opc_end;
8796 2c0262af bellard
    int j, lj;
8797 0fa85d43 bellard
    target_ulong pc_start;
8798 b5ff1b31 bellard
    uint32_t next_page_start;
8799 2e70f6ef pbrook
    int num_insns;
8800 2e70f6ef pbrook
    int max_insns;
8801 3b46e624 ths
8802 2c0262af bellard
    /* generate intermediate code */
8803 b26eefb6 pbrook
    num_temps = 0;
8804 b26eefb6 pbrook
8805 0fa85d43 bellard
    pc_start = tb->pc;
8806 3b46e624 ths
8807 2c0262af bellard
    dc->tb = tb;
8808 2c0262af bellard
8809 2c0262af bellard
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8810 2c0262af bellard
8811 2c0262af bellard
    dc->is_jmp = DISAS_NEXT;
8812 2c0262af bellard
    dc->pc = pc_start;
8813 8aaca4c0 bellard
    dc->singlestep_enabled = env->singlestep_enabled;
8814 e50e6a20 bellard
    dc->condjmp = 0;
8815 5899f386 bellard
    dc->thumb = env->thumb;
8816 9ee6e8bb pbrook
    dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8817 9ee6e8bb pbrook
    dc->condexec_cond = env->condexec_bits >> 4;
8818 b5ff1b31 bellard
#if !defined(CONFIG_USER_ONLY)
8819 9ee6e8bb pbrook
    if (IS_M(env)) {
8820 9ee6e8bb pbrook
        dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8821 9ee6e8bb pbrook
    } else {
8822 9ee6e8bb pbrook
        dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8823 9ee6e8bb pbrook
    }
8824 b5ff1b31 bellard
#endif
8825 a7812ae4 pbrook
    cpu_F0s = tcg_temp_new_i32();
8826 a7812ae4 pbrook
    cpu_F1s = tcg_temp_new_i32();
8827 a7812ae4 pbrook
    cpu_F0d = tcg_temp_new_i64();
8828 a7812ae4 pbrook
    cpu_F1d = tcg_temp_new_i64();
8829 ad69471c pbrook
    cpu_V0 = cpu_F0d;
8830 ad69471c pbrook
    cpu_V1 = cpu_F1d;
8831 e677137d pbrook
    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
8832 a7812ae4 pbrook
    cpu_M0 = tcg_temp_new_i64();
8833 b5ff1b31 bellard
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8834 2c0262af bellard
    lj = -1;
8835 2e70f6ef pbrook
    num_insns = 0;
8836 2e70f6ef pbrook
    max_insns = tb->cflags & CF_COUNT_MASK;
8837 2e70f6ef pbrook
    if (max_insns == 0)
8838 2e70f6ef pbrook
        max_insns = CF_COUNT_MASK;
8839 2e70f6ef pbrook
8840 2e70f6ef pbrook
    gen_icount_start();
8841 9ee6e8bb pbrook
    /* Reset the conditional execution bits immediately. This avoids
8842 9ee6e8bb pbrook
       complications trying to do it at the end of the block.  */
8843 9ee6e8bb pbrook
    if (env->condexec_bits)
8844 8f01245e pbrook
      {
8845 8f01245e pbrook
        TCGv tmp = new_tmp();
8846 8f01245e pbrook
        tcg_gen_movi_i32(tmp, 0);
8847 d9ba4830 pbrook
        store_cpu_field(tmp, condexec_bits);
8848 8f01245e pbrook
      }
8849 2c0262af bellard
    do {
8850 fbb4a2e3 pbrook
#ifdef CONFIG_USER_ONLY
8851 fbb4a2e3 pbrook
        /* Intercept jump to the magic kernel page.  */
8852 fbb4a2e3 pbrook
        if (dc->pc >= 0xffff0000) {
8853 fbb4a2e3 pbrook
            /* We always get here via a jump, so know we are not in a
8854 fbb4a2e3 pbrook
               conditional execution block.  */
8855 fbb4a2e3 pbrook
            gen_exception(EXCP_KERNEL_TRAP);
8856 fbb4a2e3 pbrook
            dc->is_jmp = DISAS_UPDATE;
8857 fbb4a2e3 pbrook
            break;
8858 fbb4a2e3 pbrook
        }
8859 fbb4a2e3 pbrook
#else
8860 9ee6e8bb pbrook
        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8861 9ee6e8bb pbrook
            /* We always get here via a jump, so know we are not in a
8862 9ee6e8bb pbrook
               conditional execution block.  */
8863 d9ba4830 pbrook
            gen_exception(EXCP_EXCEPTION_EXIT);
8864 d60bb01c pbrook
            dc->is_jmp = DISAS_UPDATE;
8865 d60bb01c pbrook
            break;
8866 9ee6e8bb pbrook
        }
8867 9ee6e8bb pbrook
#endif
8868 9ee6e8bb pbrook
8869 72cf2d4f Blue Swirl
        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8870 72cf2d4f Blue Swirl
            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8871 a1d1bb31 aliguori
                if (bp->pc == dc->pc) {
8872 9ee6e8bb pbrook
                    gen_set_condexec(dc);
8873 5e3f878a pbrook
                    gen_set_pc_im(dc->pc);
8874 d9ba4830 pbrook
                    gen_exception(EXCP_DEBUG);
8875 1fddef4b bellard
                    dc->is_jmp = DISAS_JUMP;
8876 9ee6e8bb pbrook
                    /* Advance PC so that clearing the breakpoint will
8877 9ee6e8bb pbrook
                       invalidate this TB.  */
8878 9ee6e8bb pbrook
                    dc->pc += 2;
8879 9ee6e8bb pbrook
                    goto done_generating;
8880 1fddef4b bellard
                    break;
8881 1fddef4b bellard
                }
8882 1fddef4b bellard
            }
8883 1fddef4b bellard
        }
8884 2c0262af bellard
        if (search_pc) {
8885 2c0262af bellard
            j = gen_opc_ptr - gen_opc_buf;
8886 2c0262af bellard
            if (lj < j) {
8887 2c0262af bellard
                lj++;
8888 2c0262af bellard
                while (lj < j)
8889 2c0262af bellard
                    gen_opc_instr_start[lj++] = 0;
8890 2c0262af bellard
            }
8891 0fa85d43 bellard
            gen_opc_pc[lj] = dc->pc;
8892 2c0262af bellard
            gen_opc_instr_start[lj] = 1;
8893 2e70f6ef pbrook
            gen_opc_icount[lj] = num_insns;
8894 2c0262af bellard
        }
8895 e50e6a20 bellard
8896 2e70f6ef pbrook
        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8897 2e70f6ef pbrook
            gen_io_start();
8898 2e70f6ef pbrook
8899 9ee6e8bb pbrook
        if (env->thumb) {
8900 9ee6e8bb pbrook
            disas_thumb_insn(env, dc);
8901 9ee6e8bb pbrook
            if (dc->condexec_mask) {
8902 9ee6e8bb pbrook
                dc->condexec_cond = (dc->condexec_cond & 0xe)
8903 9ee6e8bb pbrook
                                   | ((dc->condexec_mask >> 4) & 1);
8904 9ee6e8bb pbrook
                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8905 9ee6e8bb pbrook
                if (dc->condexec_mask == 0) {
8906 9ee6e8bb pbrook
                    dc->condexec_cond = 0;
8907 9ee6e8bb pbrook
                }
8908 9ee6e8bb pbrook
            }
8909 9ee6e8bb pbrook
        } else {
8910 9ee6e8bb pbrook
            disas_arm_insn(env, dc);
8911 9ee6e8bb pbrook
        }
8912 b26eefb6 pbrook
        if (num_temps) {
8913 b26eefb6 pbrook
            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8914 b26eefb6 pbrook
            num_temps = 0;
8915 b26eefb6 pbrook
        }
8916 e50e6a20 bellard
8917 e50e6a20 bellard
        if (dc->condjmp && !dc->is_jmp) {
8918 e50e6a20 bellard
            gen_set_label(dc->condlabel);
8919 e50e6a20 bellard
            dc->condjmp = 0;
8920 e50e6a20 bellard
        }
8921 aaf2d97d balrog
        /* Translation stops when a conditional branch is encountered.
8922 e50e6a20 bellard
         * Otherwise the subsequent code could get translated several times.
8923 b5ff1b31 bellard
         * Also stop translation when a page boundary is reached.  This
8924 bf20dc07 ths
         * ensures prefetch aborts occur at the right place.  */
8925 2e70f6ef pbrook
        num_insns ++;
8926 1fddef4b bellard
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8927 1fddef4b bellard
             !env->singlestep_enabled &&
8928 1b530a6d aurel32
             !singlestep &&
8929 2e70f6ef pbrook
             dc->pc < next_page_start &&
8930 2e70f6ef pbrook
             num_insns < max_insns);
8931 2e70f6ef pbrook
8932 2e70f6ef pbrook
    if (tb->cflags & CF_LAST_IO) {
8933 2e70f6ef pbrook
        if (dc->condjmp) {
8934 2e70f6ef pbrook
            /* FIXME:  This can theoretically happen with self-modifying
8935 2e70f6ef pbrook
               code.  */
8936 2e70f6ef pbrook
            cpu_abort(env, "IO on conditional branch instruction");
8937 2e70f6ef pbrook
        }
8938 2e70f6ef pbrook
        gen_io_end();
8939 2e70f6ef pbrook
    }
8940 9ee6e8bb pbrook
8941 b5ff1b31 bellard
    /* At this stage dc->condjmp will only be set when the skipped
8942 9ee6e8bb pbrook
       instruction was a conditional branch or trap, and the PC has
8943 9ee6e8bb pbrook
       already been written.  */
8944 551bd27f ths
    if (unlikely(env->singlestep_enabled)) {
8945 8aaca4c0 bellard
        /* Make sure the pc is updated, and raise a debug exception.  */
8946 e50e6a20 bellard
        if (dc->condjmp) {
8947 9ee6e8bb pbrook
            gen_set_condexec(dc);
8948 9ee6e8bb pbrook
            if (dc->is_jmp == DISAS_SWI) {
8949 d9ba4830 pbrook
                gen_exception(EXCP_SWI);
8950 9ee6e8bb pbrook
            } else {
8951 d9ba4830 pbrook
                gen_exception(EXCP_DEBUG);
8952 9ee6e8bb pbrook
            }
8953 e50e6a20 bellard
            gen_set_label(dc->condlabel);
8954 e50e6a20 bellard
        }
8955 e50e6a20 bellard
        if (dc->condjmp || !dc->is_jmp) {
8956 5e3f878a pbrook
            gen_set_pc_im(dc->pc);
8957 e50e6a20 bellard
            dc->condjmp = 0;
8958 8aaca4c0 bellard
        }
8959 9ee6e8bb pbrook
        gen_set_condexec(dc);
8960 9ee6e8bb pbrook
        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8961 d9ba4830 pbrook
            gen_exception(EXCP_SWI);
8962 9ee6e8bb pbrook
        } else {
8963 9ee6e8bb pbrook
            /* FIXME: Single stepping a WFI insn will not halt
8964 9ee6e8bb pbrook
               the CPU.  */
8965 d9ba4830 pbrook
            gen_exception(EXCP_DEBUG);
8966 9ee6e8bb pbrook
        }
8967 8aaca4c0 bellard
    } else {
8968 9ee6e8bb pbrook
        /* While branches must always occur at the end of an IT block,
8969 9ee6e8bb pbrook
           there are a few other things that can cause us to terminate
8970 9ee6e8bb pbrook
           the TB in the middel of an IT block:
8971 9ee6e8bb pbrook
            - Exception generating instructions (bkpt, swi, undefined).
8972 9ee6e8bb pbrook
            - Page boundaries.
8973 9ee6e8bb pbrook
            - Hardware watchpoints.
8974 9ee6e8bb pbrook
           Hardware breakpoints have already been handled and skip this code.
8975 9ee6e8bb pbrook
         */
8976 9ee6e8bb pbrook
        gen_set_condexec(dc);
8977 8aaca4c0 bellard
        switch(dc->is_jmp) {
8978 8aaca4c0 bellard
        case DISAS_NEXT:
8979 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
8980 8aaca4c0 bellard
            break;
8981 8aaca4c0 bellard
        default:
8982 8aaca4c0 bellard
        case DISAS_JUMP:
8983 8aaca4c0 bellard
        case DISAS_UPDATE:
8984 8aaca4c0 bellard
            /* indicate that the hash table must be used to find the next TB */
8985 57fec1fe bellard
            tcg_gen_exit_tb(0);
8986 8aaca4c0 bellard
            break;
8987 8aaca4c0 bellard
        case DISAS_TB_JUMP:
8988 8aaca4c0 bellard
            /* nothing more to generate */
8989 8aaca4c0 bellard
            break;
8990 9ee6e8bb pbrook
        case DISAS_WFI:
8991 d9ba4830 pbrook
            gen_helper_wfi();
8992 9ee6e8bb pbrook
            break;
8993 9ee6e8bb pbrook
        case DISAS_SWI:
8994 d9ba4830 pbrook
            gen_exception(EXCP_SWI);
8995 9ee6e8bb pbrook
            break;
8996 8aaca4c0 bellard
        }
8997 e50e6a20 bellard
        if (dc->condjmp) {
8998 e50e6a20 bellard
            gen_set_label(dc->condlabel);
8999 9ee6e8bb pbrook
            gen_set_condexec(dc);
9000 6e256c93 bellard
            gen_goto_tb(dc, 1, dc->pc);
9001 e50e6a20 bellard
            dc->condjmp = 0;
9002 e50e6a20 bellard
        }
9003 2c0262af bellard
    }
9004 2e70f6ef pbrook
9005 9ee6e8bb pbrook
done_generating:
9006 2e70f6ef pbrook
    gen_icount_end(tb, num_insns);
9007 2c0262af bellard
    *gen_opc_ptr = INDEX_op_end;
9008 2c0262af bellard
9009 2c0262af bellard
#ifdef DEBUG_DISAS
9010 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9011 93fcfe39 aliguori
        qemu_log("----------------\n");
9012 93fcfe39 aliguori
        qemu_log("IN: %s\n", lookup_symbol(pc_start));
9013 93fcfe39 aliguori
        log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9014 93fcfe39 aliguori
        qemu_log("\n");
9015 2c0262af bellard
    }
9016 2c0262af bellard
#endif
9017 b5ff1b31 bellard
    if (search_pc) {
9018 b5ff1b31 bellard
        j = gen_opc_ptr - gen_opc_buf;
9019 b5ff1b31 bellard
        lj++;
9020 b5ff1b31 bellard
        while (lj <= j)
9021 b5ff1b31 bellard
            gen_opc_instr_start[lj++] = 0;
9022 b5ff1b31 bellard
    } else {
9023 2c0262af bellard
        tb->size = dc->pc - pc_start;
9024 2e70f6ef pbrook
        tb->icount = num_insns;
9025 b5ff1b31 bellard
    }
9026 2c0262af bellard
}
9027 2c0262af bellard
9028 2cfc5f17 ths
void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9029 2c0262af bellard
{
9030 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 0);
9031 2c0262af bellard
}
9032 2c0262af bellard
9033 2cfc5f17 ths
void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9034 2c0262af bellard
{
9035 2cfc5f17 ths
    gen_intermediate_code_internal(env, tb, 1);
9036 2c0262af bellard
}
9037 2c0262af bellard
9038 b5ff1b31 bellard
static const char *cpu_mode_names[16] = {
9039 b5ff1b31 bellard
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9040 b5ff1b31 bellard
  "???", "???", "???", "und", "???", "???", "???", "sys"
9041 b5ff1b31 bellard
};
9042 9ee6e8bb pbrook
9043 5fafdf24 ths
void cpu_dump_state(CPUState *env, FILE *f,
9044 7fe48483 bellard
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9045 7fe48483 bellard
                    int flags)
9046 2c0262af bellard
{
9047 2c0262af bellard
    int i;
9048 06e80fc9 ths
#if 0
9049 bc380d17 bellard
    union {
9050 b7bcbe95 bellard
        uint32_t i;
9051 b7bcbe95 bellard
        float s;
9052 b7bcbe95 bellard
    } s0, s1;
9053 b7bcbe95 bellard
    CPU_DoubleU d;
9054 a94a6abf pbrook
    /* ??? This assumes float64 and double have the same layout.
9055 a94a6abf pbrook
       Oh well, it's only debug dumps.  */
9056 a94a6abf pbrook
    union {
9057 a94a6abf pbrook
        float64 f64;
9058 a94a6abf pbrook
        double d;
9059 a94a6abf pbrook
    } d0;
9060 06e80fc9 ths
#endif
9061 b5ff1b31 bellard
    uint32_t psr;
9062 2c0262af bellard
9063 2c0262af bellard
    for(i=0;i<16;i++) {
9064 7fe48483 bellard
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9065 2c0262af bellard
        if ((i % 4) == 3)
9066 7fe48483 bellard
            cpu_fprintf(f, "\n");
9067 2c0262af bellard
        else
9068 7fe48483 bellard
            cpu_fprintf(f, " ");
9069 2c0262af bellard
    }
9070 b5ff1b31 bellard
    psr = cpsr_read(env);
9071 687fa640 ths
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9072 687fa640 ths
                psr,
9073 b5ff1b31 bellard
                psr & (1 << 31) ? 'N' : '-',
9074 b5ff1b31 bellard
                psr & (1 << 30) ? 'Z' : '-',
9075 b5ff1b31 bellard
                psr & (1 << 29) ? 'C' : '-',
9076 b5ff1b31 bellard
                psr & (1 << 28) ? 'V' : '-',
9077 5fafdf24 ths
                psr & CPSR_T ? 'T' : 'A',
9078 b5ff1b31 bellard
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9079 b7bcbe95 bellard
9080 5e3f878a pbrook
#if 0
9081 b7bcbe95 bellard
    for (i = 0; i < 16; i++) {
9082 8e96005d bellard
        d.d = env->vfp.regs[i];
9083 8e96005d bellard
        s0.i = d.l.lower;
9084 8e96005d bellard
        s1.i = d.l.upper;
9085 a94a6abf pbrook
        d0.f64 = d.d;
9086 a94a6abf pbrook
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9087 b7bcbe95 bellard
                    i * 2, (int)s0.i, s0.s,
9088 a94a6abf pbrook
                    i * 2 + 1, (int)s1.i, s1.s,
9089 b7bcbe95 bellard
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9090 a94a6abf pbrook
                    d0.d);
9091 b7bcbe95 bellard
    }
9092 40f137e1 pbrook
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9093 5e3f878a pbrook
#endif
9094 2c0262af bellard
}
9095 a6b025d3 bellard
9096 d2856f1a aurel32
void gen_pc_load(CPUState *env, TranslationBlock *tb,
9097 d2856f1a aurel32
                unsigned long searched_pc, int pc_pos, void *puc)
9098 d2856f1a aurel32
{
9099 d2856f1a aurel32
    env->regs[15] = gen_opc_pc[pc_pos];
9100 d2856f1a aurel32
}