Statistics
| Branch: | Revision:

root / target-arm / translate.c @ f97572e5

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