Statistics
| Branch: | Revision:

root / target-arm / translate.c @ bf20dc07

History | View | Annotate | Download (295.9 kB)

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