Statistics
| Branch: | Revision:

root / target-arm / translate.c @ db8d9902

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