Statistics
| Branch: | Revision:

root / target-arm / translate.c @ d9ba4830

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