Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 6ddbc6e4

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