Statistics
| Branch: | Revision:

root / target-arm / translate.c @ e00c1e71

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