Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 64e58fe5

History | View | Annotate | Download (304.9 kB)

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