Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 66230e0d

History | View | Annotate | Download (294.7 kB)

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