Statistics
| Branch: | Revision:

root / target-arm / translate.c @ a60de947

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