Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 44f8625d

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