Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 30d11a2a

History | View | Annotate | Download (312.1 kB)

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

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