Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 72cf2d4f

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