Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 5e3f878a

History | View | Annotate | Download (283.3 kB)

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