Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 9a78eead

History | View | Annotate | Download (312.3 kB)

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

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