Statistics
| Branch: | Revision:

root / target-arm / translate.c @ bf20dc07

History | View | Annotate | Download (295.9 kB)

1
/*
2
 *  ARM translation
3
 *
4
 *  Copyright (c) 2003 Fabrice Bellard
5
 *  Copyright (c) 2005-2007 CodeSourcery
6
 *  Copyright (c) 2007 OpenedHand, Ltd.
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21
 */
22
#include <stdarg.h>
23
#include <stdlib.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include <inttypes.h>
27

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31
#include "tcg-op.h"
32

    
33
#define GEN_HELPER 1
34
#include "helpers.h"
35

    
36
#define ENABLE_ARCH_5J    0
37
#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
38
#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
39
#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
40
#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
41

    
42
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
43

    
44
/* internal defines */
45
typedef struct DisasContext {
46
    target_ulong pc;
47
    int is_jmp;
48
    /* Nonzero if this instruction has been conditionally skipped.  */
49
    int condjmp;
50
    /* The label that will be jumped to when the instruction is skipped.  */
51
    int condlabel;
52
    /* Thumb-2 condtional execution bits.  */
53
    int condexec_mask;
54
    int condexec_cond;
55
    struct TranslationBlock *tb;
56
    int singlestep_enabled;
57
    int thumb;
58
    int is_mem;
59
#if !defined(CONFIG_USER_ONLY)
60
    int user;
61
#endif
62
} DisasContext;
63

    
64
#if defined(CONFIG_USER_ONLY)
65
#define IS_USER(s) 1
66
#else
67
#define IS_USER(s) (s->user)
68
#endif
69

    
70
/* These instructions trap after executing, so defer them until after the
71
   conditional executions state has been updated.  */
72
#define DISAS_WFI 4
73
#define DISAS_SWI 5
74

    
75
/* XXX: move that elsewhere */
76
extern FILE *logfile;
77
extern int loglevel;
78

    
79
static TCGv cpu_env;
80
/* We reuse the same 64-bit temporaries for efficiency.  */
81
static TCGv cpu_V0, cpu_V1, cpu_M0;
82

    
83
/* FIXME:  These should be removed.  */
84
static TCGv cpu_T[2];
85
static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d;
86

    
87
#define ICOUNT_TEMP cpu_T[0]
88
#include "gen-icount.h"
89

    
90
/* initialize TCG globals.  */
91
void arm_translate_init(void)
92
{
93
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
94

    
95
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
96
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
97
}
98

    
99
/* The code generator doesn't like lots of temporaries, so maintain our own
100
   cache for reuse within a function.  */
101
#define MAX_TEMPS 8
102
static int num_temps;
103
static TCGv temps[MAX_TEMPS];
104

    
105
/* Allocate a temporary variable.  */
106
static TCGv new_tmp(void)
107
{
108
    TCGv tmp;
109
    if (num_temps == MAX_TEMPS)
110
        abort();
111

    
112
    if (GET_TCGV(temps[num_temps]))
113
      return temps[num_temps++];
114

    
115
    tmp = tcg_temp_new(TCG_TYPE_I32);
116
    temps[num_temps++] = tmp;
117
    return tmp;
118
}
119

    
120
/* Release a temporary variable.  */
121
static void dead_tmp(TCGv tmp)
122
{
123
    int i;
124
    num_temps--;
125
    i = num_temps;
126
    if (GET_TCGV(temps[i]) == GET_TCGV(tmp))
127
        return;
128

    
129
    /* Shuffle this temp to the last slot.  */
130
    while (GET_TCGV(temps[i]) != GET_TCGV(tmp))
131
        i--;
132
    while (i < num_temps) {
133
        temps[i] = temps[i + 1];
134
        i++;
135
    }
136
    temps[i] = tmp;
137
}
138

    
139
static inline TCGv load_cpu_offset(int offset)
140
{
141
    TCGv tmp = new_tmp();
142
    tcg_gen_ld_i32(tmp, cpu_env, offset);
143
    return tmp;
144
}
145

    
146
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
147

    
148
static inline void store_cpu_offset(TCGv var, int offset)
149
{
150
    tcg_gen_st_i32(var, cpu_env, offset);
151
    dead_tmp(var);
152
}
153

    
154
#define store_cpu_field(var, name) \
155
    store_cpu_offset(var, offsetof(CPUState, name))
156

    
157
/* Set a variable to the value of a CPU register.  */
158
static void load_reg_var(DisasContext *s, TCGv var, int reg)
159
{
160
    if (reg == 15) {
161
        uint32_t addr;
162
        /* normaly, since we updated PC, we need only to add one insn */
163
        if (s->thumb)
164
            addr = (long)s->pc + 2;
165
        else
166
            addr = (long)s->pc + 4;
167
        tcg_gen_movi_i32(var, addr);
168
    } else {
169
        tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
170
    }
171
}
172

    
173
/* Create a new temporary and set it to the value of a CPU register.  */
174
static inline TCGv load_reg(DisasContext *s, int reg)
175
{
176
    TCGv tmp = new_tmp();
177
    load_reg_var(s, tmp, reg);
178
    return tmp;
179
}
180

    
181
/* Set a CPU register.  The source must be a temporary and will be
182
   marked as dead.  */
183
static void store_reg(DisasContext *s, int reg, TCGv var)
184
{
185
    if (reg == 15) {
186
        tcg_gen_andi_i32(var, var, ~1);
187
        s->is_jmp = DISAS_JUMP;
188
    }
189
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
190
    dead_tmp(var);
191
}
192

    
193

    
194
/* Basic operations.  */
195
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
196
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
197
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
198
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
199

    
200
#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
201
#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202
#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
203
#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
204

    
205
#define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206
#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
207
#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208
#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
209
#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
210
#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
211

    
212
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
214
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
215
#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
216
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
217
#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
218
#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
219

    
220
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
221
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
222
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
223
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
224
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
225

    
226
/* Value extensions.  */
227
#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
228
#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
229
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
230
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
231

    
232
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
233
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
234

    
235
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
236

    
237
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
238
/* Set NZCV flags from the high 4 bits of var.  */
239
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
240

    
241
static void gen_exception(int excp)
242
{
243
    TCGv tmp = new_tmp();
244
    tcg_gen_movi_i32(tmp, excp);
245
    gen_helper_exception(tmp);
246
    dead_tmp(tmp);
247
}
248

    
249
static void gen_smul_dual(TCGv a, TCGv b)
250
{
251
    TCGv tmp1 = new_tmp();
252
    TCGv tmp2 = new_tmp();
253
    tcg_gen_ext8s_i32(tmp1, a);
254
    tcg_gen_ext8s_i32(tmp2, b);
255
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
256
    dead_tmp(tmp2);
257
    tcg_gen_sari_i32(a, a, 16);
258
    tcg_gen_sari_i32(b, b, 16);
259
    tcg_gen_mul_i32(b, b, a);
260
    tcg_gen_mov_i32(a, tmp1);
261
    dead_tmp(tmp1);
262
}
263

    
264
/* Byteswap each halfword.  */
265
static void gen_rev16(TCGv var)
266
{
267
    TCGv tmp = new_tmp();
268
    tcg_gen_shri_i32(tmp, var, 8);
269
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
270
    tcg_gen_shli_i32(var, var, 8);
271
    tcg_gen_andi_i32(var, var, 0xff00ff00);
272
    tcg_gen_or_i32(var, var, tmp);
273
    dead_tmp(tmp);
274
}
275

    
276
/* Byteswap low halfword and sign extend.  */
277
static void gen_revsh(TCGv var)
278
{
279
    TCGv tmp = new_tmp();
280
    tcg_gen_shri_i32(tmp, var, 8);
281
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
282
    tcg_gen_shli_i32(var, var, 8);
283
    tcg_gen_ext8s_i32(var, var);
284
    tcg_gen_or_i32(var, var, tmp);
285
    dead_tmp(tmp);
286
}
287

    
288
/* Unsigned bitfield extract.  */
289
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
290
{
291
    if (shift)
292
        tcg_gen_shri_i32(var, var, shift);
293
    tcg_gen_andi_i32(var, var, mask);
294
}
295

    
296
/* Signed bitfield extract.  */
297
static void gen_sbfx(TCGv var, int shift, int width)
298
{
299
    uint32_t signbit;
300

    
301
    if (shift)
302
        tcg_gen_sari_i32(var, var, shift);
303
    if (shift + width < 32) {
304
        signbit = 1u << (width - 1);
305
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
306
        tcg_gen_xori_i32(var, var, signbit);
307
        tcg_gen_subi_i32(var, var, signbit);
308
    }
309
}
310

    
311
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
312
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
313
{
314
    tcg_gen_andi_i32(val, val, mask);
315
    tcg_gen_shli_i32(val, val, shift);
316
    tcg_gen_andi_i32(base, base, ~(mask << shift));
317
    tcg_gen_or_i32(dest, base, val);
318
}
319

    
320
/* Round the top 32 bits of a 64-bit value.  */
321
static void gen_roundqd(TCGv a, TCGv b)
322
{
323
    tcg_gen_shri_i32(a, a, 31);
324
    tcg_gen_add_i32(a, a, b);
325
}
326

    
327
/* FIXME: Most targets have native widening multiplication.
328
   It would be good to use that instead of a full wide multiply.  */
329
/* 32x32->64 multiply.  Marks inputs as dead.  */
330
static TCGv gen_mulu_i64_i32(TCGv a, TCGv b)
331
{
332
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
333
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
334

    
335
    tcg_gen_extu_i32_i64(tmp1, a);
336
    dead_tmp(a);
337
    tcg_gen_extu_i32_i64(tmp2, b);
338
    dead_tmp(b);
339
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
340
    return tmp1;
341
}
342

    
343
static TCGv gen_muls_i64_i32(TCGv a, TCGv b)
344
{
345
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
346
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
347

    
348
    tcg_gen_ext_i32_i64(tmp1, a);
349
    dead_tmp(a);
350
    tcg_gen_ext_i32_i64(tmp2, b);
351
    dead_tmp(b);
352
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
353
    return tmp1;
354
}
355

    
356
/* Unsigned 32x32->64 multiply.  */
357
static void gen_op_mull_T0_T1(void)
358
{
359
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
360
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
361

    
362
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
363
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
364
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
365
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
366
    tcg_gen_shri_i64(tmp1, tmp1, 32);
367
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
368
}
369

    
370
/* Signed 32x32->64 multiply.  */
371
static void gen_imull(TCGv a, TCGv b)
372
{
373
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
374
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
375

    
376
    tcg_gen_ext_i32_i64(tmp1, a);
377
    tcg_gen_ext_i32_i64(tmp2, b);
378
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
379
    tcg_gen_trunc_i64_i32(a, tmp1);
380
    tcg_gen_shri_i64(tmp1, tmp1, 32);
381
    tcg_gen_trunc_i64_i32(b, tmp1);
382
}
383
#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
384

    
385
/* Swap low and high halfwords.  */
386
static void gen_swap_half(TCGv var)
387
{
388
    TCGv tmp = new_tmp();
389
    tcg_gen_shri_i32(tmp, var, 16);
390
    tcg_gen_shli_i32(var, var, 16);
391
    tcg_gen_or_i32(var, var, tmp);
392
    dead_tmp(tmp);
393
}
394

    
395
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
396
    tmp = (t0 ^ t1) & 0x8000;
397
    t0 &= ~0x8000;
398
    t1 &= ~0x8000;
399
    t0 = (t0 + t1) ^ tmp;
400
 */
401

    
402
static void gen_add16(TCGv t0, TCGv t1)
403
{
404
    TCGv tmp = new_tmp();
405
    tcg_gen_xor_i32(tmp, t0, t1);
406
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
407
    tcg_gen_andi_i32(t0, t0, ~0x8000);
408
    tcg_gen_andi_i32(t1, t1, ~0x8000);
409
    tcg_gen_add_i32(t0, t0, t1);
410
    tcg_gen_xor_i32(t0, t0, tmp);
411
    dead_tmp(tmp);
412
    dead_tmp(t1);
413
}
414

    
415
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
416

    
417
/* Set CF to the top bit of var.  */
418
static void gen_set_CF_bit31(TCGv var)
419
{
420
    TCGv tmp = new_tmp();
421
    tcg_gen_shri_i32(tmp, var, 31);
422
    gen_set_CF(var);
423
    dead_tmp(tmp);
424
}
425

    
426
/* Set N and Z flags from var.  */
427
static inline void gen_logic_CC(TCGv var)
428
{
429
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
430
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
431
}
432

    
433
/* T0 += T1 + CF.  */
434
static void gen_adc_T0_T1(void)
435
{
436
    TCGv tmp;
437
    gen_op_addl_T0_T1();
438
    tmp = load_cpu_field(CF);
439
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
440
    dead_tmp(tmp);
441
}
442

    
443
/* dest = T0 - T1 + CF - 1.  */
444
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
445
{
446
    TCGv tmp;
447
    tcg_gen_sub_i32(dest, t0, t1);
448
    tmp = load_cpu_field(CF);
449
    tcg_gen_add_i32(dest, dest, tmp);
450
    tcg_gen_subi_i32(dest, dest, 1);
451
    dead_tmp(tmp);
452
}
453

    
454
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
455
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
456

    
457
/* T0 &= ~T1.  Clobbers T1.  */
458
/* FIXME: Implement bic natively.  */
459
static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
460
{
461
    TCGv tmp = new_tmp();
462
    tcg_gen_not_i32(tmp, t1);
463
    tcg_gen_and_i32(dest, t0, tmp);
464
    dead_tmp(tmp);
465
}
466
static inline void gen_op_bicl_T0_T1(void)
467
{
468
    gen_op_notl_T1();
469
    gen_op_andl_T0_T1();
470
}
471

    
472
/* FIXME:  Implement this natively.  */
473
#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
474

    
475
/* FIXME:  Implement this natively.  */
476
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
477
{
478
    TCGv tmp;
479

    
480
    if (i == 0)
481
        return;
482

    
483
    tmp = new_tmp();
484
    tcg_gen_shri_i32(tmp, t1, i);
485
    tcg_gen_shli_i32(t1, t1, 32 - i);
486
    tcg_gen_or_i32(t0, t1, tmp);
487
    dead_tmp(tmp);
488
}
489

    
490
static void shifter_out_im(TCGv var, int shift)
491
{
492
    TCGv tmp = new_tmp();
493
    if (shift == 0) {
494
        tcg_gen_andi_i32(tmp, var, 1);
495
    } else {
496
        tcg_gen_shri_i32(tmp, var, shift);
497
        if (shift != 31);
498
            tcg_gen_andi_i32(tmp, tmp, 1);
499
    }
500
    gen_set_CF(tmp);
501
    dead_tmp(tmp);
502
}
503

    
504
/* Shift by immediate.  Includes special handling for shift == 0.  */
505
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
506
{
507
    switch (shiftop) {
508
    case 0: /* LSL */
509
        if (shift != 0) {
510
            if (flags)
511
                shifter_out_im(var, 32 - shift);
512
            tcg_gen_shli_i32(var, var, shift);
513
        }
514
        break;
515
    case 1: /* LSR */
516
        if (shift == 0) {
517
            if (flags) {
518
                tcg_gen_shri_i32(var, var, 31);
519
                gen_set_CF(var);
520
            }
521
            tcg_gen_movi_i32(var, 0);
522
        } else {
523
            if (flags)
524
                shifter_out_im(var, shift - 1);
525
            tcg_gen_shri_i32(var, var, shift);
526
        }
527
        break;
528
    case 2: /* ASR */
529
        if (shift == 0)
530
            shift = 32;
531
        if (flags)
532
            shifter_out_im(var, shift - 1);
533
        if (shift == 32)
534
          shift = 31;
535
        tcg_gen_sari_i32(var, var, shift);
536
        break;
537
    case 3: /* ROR/RRX */
538
        if (shift != 0) {
539
            if (flags)
540
                shifter_out_im(var, shift - 1);
541
            tcg_gen_rori_i32(var, var, shift); break;
542
        } else {
543
            TCGv tmp = load_cpu_field(CF);
544
            if (flags)
545
                shifter_out_im(var, 0);
546
            tcg_gen_shri_i32(var, var, 1);
547
            tcg_gen_shli_i32(tmp, tmp, 31);
548
            tcg_gen_or_i32(var, var, tmp);
549
            dead_tmp(tmp);
550
        }
551
    }
552
};
553

    
554
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
555
                                     TCGv shift, int flags)
556
{
557
    if (flags) {
558
        switch (shiftop) {
559
        case 0: gen_helper_shl_cc(var, var, shift); break;
560
        case 1: gen_helper_shr_cc(var, var, shift); break;
561
        case 2: gen_helper_sar_cc(var, var, shift); break;
562
        case 3: gen_helper_ror_cc(var, var, shift); break;
563
        }
564
    } else {
565
        switch (shiftop) {
566
        case 0: gen_helper_shl(var, var, shift); break;
567
        case 1: gen_helper_shr(var, var, shift); break;
568
        case 2: gen_helper_sar(var, var, shift); break;
569
        case 3: gen_helper_ror(var, var, shift); break;
570
        }
571
    }
572
    dead_tmp(shift);
573
}
574

    
575
#define PAS_OP(pfx) \
576
    switch (op2) {  \
577
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
578
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
579
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
580
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
581
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
582
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
583
    }
584
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
585
{
586
    TCGv tmp;
587

    
588
    switch (op1) {
589
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
590
    case 1:
591
        tmp = tcg_temp_new(TCG_TYPE_PTR);
592
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
593
        PAS_OP(s)
594
        break;
595
    case 5:
596
        tmp = tcg_temp_new(TCG_TYPE_PTR);
597
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
598
        PAS_OP(u)
599
        break;
600
#undef gen_pas_helper
601
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
602
    case 2:
603
        PAS_OP(q);
604
        break;
605
    case 3:
606
        PAS_OP(sh);
607
        break;
608
    case 6:
609
        PAS_OP(uq);
610
        break;
611
    case 7:
612
        PAS_OP(uh);
613
        break;
614
#undef gen_pas_helper
615
    }
616
}
617
#undef PAS_OP
618

    
619
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
620
#define PAS_OP(pfx) \
621
    switch (op2) {  \
622
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
623
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
624
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
625
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
626
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
627
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
628
    }
629
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
630
{
631
    TCGv tmp;
632

    
633
    switch (op1) {
634
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
635
    case 0:
636
        tmp = tcg_temp_new(TCG_TYPE_PTR);
637
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
638
        PAS_OP(s)
639
        break;
640
    case 4:
641
        tmp = tcg_temp_new(TCG_TYPE_PTR);
642
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
643
        PAS_OP(u)
644
        break;
645
#undef gen_pas_helper
646
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
647
    case 1:
648
        PAS_OP(q);
649
        break;
650
    case 2:
651
        PAS_OP(sh);
652
        break;
653
    case 5:
654
        PAS_OP(uq);
655
        break;
656
    case 6:
657
        PAS_OP(uh);
658
        break;
659
#undef gen_pas_helper
660
    }
661
}
662
#undef PAS_OP
663

    
664
static void gen_test_cc(int cc, int label)
665
{
666
    TCGv tmp;
667
    TCGv tmp2;
668
    int inv;
669

    
670
    switch (cc) {
671
    case 0: /* eq: Z */
672
        tmp = load_cpu_field(ZF);
673
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
674
        break;
675
    case 1: /* ne: !Z */
676
        tmp = load_cpu_field(ZF);
677
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
678
        break;
679
    case 2: /* cs: C */
680
        tmp = load_cpu_field(CF);
681
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
682
        break;
683
    case 3: /* cc: !C */
684
        tmp = load_cpu_field(CF);
685
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
686
        break;
687
    case 4: /* mi: N */
688
        tmp = load_cpu_field(NF);
689
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
690
        break;
691
    case 5: /* pl: !N */
692
        tmp = load_cpu_field(NF);
693
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
694
        break;
695
    case 6: /* vs: V */
696
        tmp = load_cpu_field(VF);
697
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
698
        break;
699
    case 7: /* vc: !V */
700
        tmp = load_cpu_field(VF);
701
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
702
        break;
703
    case 8: /* hi: C && !Z */
704
        inv = gen_new_label();
705
        tmp = load_cpu_field(CF);
706
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
707
        dead_tmp(tmp);
708
        tmp = load_cpu_field(ZF);
709
        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
710
        gen_set_label(inv);
711
        break;
712
    case 9: /* ls: !C || Z */
713
        tmp = load_cpu_field(CF);
714
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
715
        dead_tmp(tmp);
716
        tmp = load_cpu_field(ZF);
717
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
718
        break;
719
    case 10: /* ge: N == V -> N ^ V == 0 */
720
        tmp = load_cpu_field(VF);
721
        tmp2 = load_cpu_field(NF);
722
        tcg_gen_xor_i32(tmp, tmp, tmp2);
723
        dead_tmp(tmp2);
724
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
725
        break;
726
    case 11: /* lt: N != V -> N ^ V != 0 */
727
        tmp = load_cpu_field(VF);
728
        tmp2 = load_cpu_field(NF);
729
        tcg_gen_xor_i32(tmp, tmp, tmp2);
730
        dead_tmp(tmp2);
731
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
732
        break;
733
    case 12: /* gt: !Z && N == V */
734
        inv = gen_new_label();
735
        tmp = load_cpu_field(ZF);
736
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
737
        dead_tmp(tmp);
738
        tmp = load_cpu_field(VF);
739
        tmp2 = load_cpu_field(NF);
740
        tcg_gen_xor_i32(tmp, tmp, tmp2);
741
        dead_tmp(tmp2);
742
        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
743
        gen_set_label(inv);
744
        break;
745
    case 13: /* le: Z || N != V */
746
        tmp = load_cpu_field(ZF);
747
        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
748
        dead_tmp(tmp);
749
        tmp = load_cpu_field(VF);
750
        tmp2 = load_cpu_field(NF);
751
        tcg_gen_xor_i32(tmp, tmp, tmp2);
752
        dead_tmp(tmp2);
753
        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
754
        break;
755
    default:
756
        fprintf(stderr, "Bad condition code 0x%x\n", cc);
757
        abort();
758
    }
759
    dead_tmp(tmp);
760
}
761

    
762
const uint8_t table_logic_cc[16] = {
763
    1, /* and */
764
    1, /* xor */
765
    0, /* sub */
766
    0, /* rsb */
767
    0, /* add */
768
    0, /* adc */
769
    0, /* sbc */
770
    0, /* rsc */
771
    1, /* andl */
772
    1, /* xorl */
773
    0, /* cmp */
774
    0, /* cmn */
775
    1, /* orr */
776
    1, /* mov */
777
    1, /* bic */
778
    1, /* mvn */
779
};
780

    
781
/* Set PC and Thumb state from an immediate address.  */
782
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
783
{
784
    TCGv tmp;
785

    
786
    s->is_jmp = DISAS_UPDATE;
787
    tmp = new_tmp();
788
    if (s->thumb != (addr & 1)) {
789
        tcg_gen_movi_i32(tmp, addr & 1);
790
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
791
    }
792
    tcg_gen_movi_i32(tmp, addr & ~1);
793
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
794
    dead_tmp(tmp);
795
}
796

    
797
/* Set PC and Thumb state from var.  var is marked as dead.  */
798
static inline void gen_bx(DisasContext *s, TCGv var)
799
{
800
    TCGv tmp;
801

    
802
    s->is_jmp = DISAS_UPDATE;
803
    tmp = new_tmp();
804
    tcg_gen_andi_i32(tmp, var, 1);
805
    store_cpu_field(tmp, thumb);
806
    tcg_gen_andi_i32(var, var, ~1);
807
    store_cpu_field(var, regs[15]);
808
}
809

    
810
/* TODO: This should be removed.  Use gen_bx instead.  */
811
static inline void gen_bx_T0(DisasContext *s)
812
{
813
    TCGv tmp = new_tmp();
814
    tcg_gen_mov_i32(tmp, cpu_T[0]);
815
    gen_bx(s, tmp);
816
}
817

    
818
#if defined(CONFIG_USER_ONLY)
819
#define gen_ldst(name, s) gen_op_##name##_raw()
820
#else
821
#define gen_ldst(name, s) do { \
822
    s->is_mem = 1; \
823
    if (IS_USER(s)) \
824
        gen_op_##name##_user(); \
825
    else \
826
        gen_op_##name##_kernel(); \
827
    } while (0)
828
#endif
829
static inline TCGv gen_ld8s(TCGv addr, int index)
830
{
831
    TCGv tmp = new_tmp();
832
    tcg_gen_qemu_ld8s(tmp, addr, index);
833
    return tmp;
834
}
835
static inline TCGv gen_ld8u(TCGv addr, int index)
836
{
837
    TCGv tmp = new_tmp();
838
    tcg_gen_qemu_ld8u(tmp, addr, index);
839
    return tmp;
840
}
841
static inline TCGv gen_ld16s(TCGv addr, int index)
842
{
843
    TCGv tmp = new_tmp();
844
    tcg_gen_qemu_ld16s(tmp, addr, index);
845
    return tmp;
846
}
847
static inline TCGv gen_ld16u(TCGv addr, int index)
848
{
849
    TCGv tmp = new_tmp();
850
    tcg_gen_qemu_ld16u(tmp, addr, index);
851
    return tmp;
852
}
853
static inline TCGv gen_ld32(TCGv addr, int index)
854
{
855
    TCGv tmp = new_tmp();
856
    tcg_gen_qemu_ld32u(tmp, addr, index);
857
    return tmp;
858
}
859
static inline void gen_st8(TCGv val, TCGv addr, int index)
860
{
861
    tcg_gen_qemu_st8(val, addr, index);
862
    dead_tmp(val);
863
}
864
static inline void gen_st16(TCGv val, TCGv addr, int index)
865
{
866
    tcg_gen_qemu_st16(val, addr, index);
867
    dead_tmp(val);
868
}
869
static inline void gen_st32(TCGv val, TCGv addr, int index)
870
{
871
    tcg_gen_qemu_st32(val, addr, index);
872
    dead_tmp(val);
873
}
874

    
875
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
876
{
877
    load_reg_var(s, cpu_T[0], reg);
878
}
879

    
880
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
881
{
882
    load_reg_var(s, cpu_T[1], reg);
883
}
884

    
885
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
886
{
887
    load_reg_var(s, cpu_T[2], reg);
888
}
889

    
890
static inline void gen_set_pc_im(uint32_t val)
891
{
892
    TCGv tmp = new_tmp();
893
    tcg_gen_movi_i32(tmp, val);
894
    store_cpu_field(tmp, regs[15]);
895
}
896

    
897
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
898
{
899
    TCGv tmp;
900
    if (reg == 15) {
901
        tmp = new_tmp();
902
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
903
    } else {
904
        tmp = cpu_T[t];
905
    }
906
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
907
    if (reg == 15) {
908
        dead_tmp(tmp);
909
        s->is_jmp = DISAS_JUMP;
910
    }
911
}
912

    
913
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
914
{
915
    gen_movl_reg_TN(s, reg, 0);
916
}
917

    
918
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
919
{
920
    gen_movl_reg_TN(s, reg, 1);
921
}
922

    
923
/* Force a TB lookup after an instruction that changes the CPU state.  */
924
static inline void gen_lookup_tb(DisasContext *s)
925
{
926
    gen_op_movl_T0_im(s->pc);
927
    gen_movl_reg_T0(s, 15);
928
    s->is_jmp = DISAS_UPDATE;
929
}
930

    
931
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
932
                                       TCGv var)
933
{
934
    int val, rm, shift, shiftop;
935
    TCGv offset;
936

    
937
    if (!(insn & (1 << 25))) {
938
        /* immediate */
939
        val = insn & 0xfff;
940
        if (!(insn & (1 << 23)))
941
            val = -val;
942
        if (val != 0)
943
            tcg_gen_addi_i32(var, var, val);
944
    } else {
945
        /* shift/register */
946
        rm = (insn) & 0xf;
947
        shift = (insn >> 7) & 0x1f;
948
        shiftop = (insn >> 5) & 3;
949
        offset = load_reg(s, rm);
950
        gen_arm_shift_im(offset, shiftop, shift, 0);
951
        if (!(insn & (1 << 23)))
952
            tcg_gen_sub_i32(var, var, offset);
953
        else
954
            tcg_gen_add_i32(var, var, offset);
955
        dead_tmp(offset);
956
    }
957
}
958

    
959
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
960
                                        int extra, TCGv var)
961
{
962
    int val, rm;
963
    TCGv offset;
964

    
965
    if (insn & (1 << 22)) {
966
        /* immediate */
967
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
968
        if (!(insn & (1 << 23)))
969
            val = -val;
970
        val += extra;
971
        if (val != 0)
972
            tcg_gen_addi_i32(var, var, val);
973
    } else {
974
        /* register */
975
        if (extra)
976
            tcg_gen_addi_i32(var, var, extra);
977
        rm = (insn) & 0xf;
978
        offset = load_reg(s, rm);
979
        if (!(insn & (1 << 23)))
980
            tcg_gen_sub_i32(var, var, offset);
981
        else
982
            tcg_gen_add_i32(var, var, offset);
983
        dead_tmp(offset);
984
    }
985
}
986

    
987
#define VFP_OP2(name)                                                 \
988
static inline void gen_vfp_##name(int dp)                             \
989
{                                                                     \
990
    if (dp)                                                           \
991
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
992
    else                                                              \
993
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
994
}
995

    
996
#define VFP_OP1(name)                               \
997
static inline void gen_vfp_##name(int dp, int arg)  \
998
{                                                   \
999
    if (dp)                                         \
1000
        gen_op_vfp_##name##d(arg);                  \
1001
    else                                            \
1002
        gen_op_vfp_##name##s(arg);                  \
1003
}
1004

    
1005
VFP_OP2(add)
1006
VFP_OP2(sub)
1007
VFP_OP2(mul)
1008
VFP_OP2(div)
1009

    
1010
#undef VFP_OP2
1011

    
1012
static inline void gen_vfp_abs(int dp)
1013
{
1014
    if (dp)
1015
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1016
    else
1017
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1018
}
1019

    
1020
static inline void gen_vfp_neg(int dp)
1021
{
1022
    if (dp)
1023
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1024
    else
1025
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1026
}
1027

    
1028
static inline void gen_vfp_sqrt(int dp)
1029
{
1030
    if (dp)
1031
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1032
    else
1033
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1034
}
1035

    
1036
static inline void gen_vfp_cmp(int dp)
1037
{
1038
    if (dp)
1039
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1040
    else
1041
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1042
}
1043

    
1044
static inline void gen_vfp_cmpe(int dp)
1045
{
1046
    if (dp)
1047
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1048
    else
1049
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1050
}
1051

    
1052
static inline void gen_vfp_F1_ld0(int dp)
1053
{
1054
    if (dp)
1055
        tcg_gen_movi_i64(cpu_F1d, 0);
1056
    else
1057
        tcg_gen_movi_i32(cpu_F1s, 0);
1058
}
1059

    
1060
static inline void gen_vfp_uito(int dp)
1061
{
1062
    if (dp)
1063
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1064
    else
1065
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1066
}
1067

    
1068
static inline void gen_vfp_sito(int dp)
1069
{
1070
    if (dp)
1071
        gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1072
    else
1073
        gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1074
}
1075

    
1076
static inline void gen_vfp_toui(int dp)
1077
{
1078
    if (dp)
1079
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1080
    else
1081
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1082
}
1083

    
1084
static inline void gen_vfp_touiz(int dp)
1085
{
1086
    if (dp)
1087
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1088
    else
1089
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1090
}
1091

    
1092
static inline void gen_vfp_tosi(int dp)
1093
{
1094
    if (dp)
1095
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1096
    else
1097
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1098
}
1099

    
1100
static inline void gen_vfp_tosiz(int dp)
1101
{
1102
    if (dp)
1103
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1104
    else
1105
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1106
}
1107

    
1108
#define VFP_GEN_FIX(name) \
1109
static inline void gen_vfp_##name(int dp, int shift) \
1110
{ \
1111
    if (dp) \
1112
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1113
    else \
1114
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1115
}
1116
VFP_GEN_FIX(tosh)
1117
VFP_GEN_FIX(tosl)
1118
VFP_GEN_FIX(touh)
1119
VFP_GEN_FIX(toul)
1120
VFP_GEN_FIX(shto)
1121
VFP_GEN_FIX(slto)
1122
VFP_GEN_FIX(uhto)
1123
VFP_GEN_FIX(ulto)
1124
#undef VFP_GEN_FIX
1125

    
1126
static inline void gen_vfp_ld(DisasContext *s, int dp)
1127
{
1128
    if (dp)
1129
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1130
    else
1131
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1132
}
1133

    
1134
static inline void gen_vfp_st(DisasContext *s, int dp)
1135
{
1136
    if (dp)
1137
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1138
    else
1139
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1140
}
1141

    
1142
static inline long
1143
vfp_reg_offset (int dp, int reg)
1144
{
1145
    if (dp)
1146
        return offsetof(CPUARMState, vfp.regs[reg]);
1147
    else if (reg & 1) {
1148
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1149
          + offsetof(CPU_DoubleU, l.upper);
1150
    } else {
1151
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1152
          + offsetof(CPU_DoubleU, l.lower);
1153
    }
1154
}
1155

    
1156
/* Return the offset of a 32-bit piece of a NEON register.
1157
   zero is the least significant end of the register.  */
1158
static inline long
1159
neon_reg_offset (int reg, int n)
1160
{
1161
    int sreg;
1162
    sreg = reg * 2 + n;
1163
    return vfp_reg_offset(0, sreg);
1164
}
1165

    
1166
/* FIXME: Remove these.  */
1167
#define neon_T0 cpu_T[0]
1168
#define neon_T1 cpu_T[1]
1169
#define NEON_GET_REG(T, reg, n) \
1170
  tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1171
#define NEON_SET_REG(T, reg, n) \
1172
  tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1173

    
1174
static TCGv neon_load_reg(int reg, int pass)
1175
{
1176
    TCGv tmp = new_tmp();
1177
    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1178
    return tmp;
1179
}
1180

    
1181
static void neon_store_reg(int reg, int pass, TCGv var)
1182
{
1183
    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1184
    dead_tmp(var);
1185
}
1186

    
1187
static inline void neon_load_reg64(TCGv var, int reg)
1188
{
1189
    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1190
}
1191

    
1192
static inline void neon_store_reg64(TCGv var, int reg)
1193
{
1194
    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1195
}
1196

    
1197
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1198
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1199
#define tcg_gen_st_f32 tcg_gen_st_i32
1200
#define tcg_gen_st_f64 tcg_gen_st_i64
1201

    
1202
static inline void gen_mov_F0_vreg(int dp, int reg)
1203
{
1204
    if (dp)
1205
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1206
    else
1207
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1208
}
1209

    
1210
static inline void gen_mov_F1_vreg(int dp, int reg)
1211
{
1212
    if (dp)
1213
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1214
    else
1215
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1216
}
1217

    
1218
static inline void gen_mov_vreg_F0(int dp, int reg)
1219
{
1220
    if (dp)
1221
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1222
    else
1223
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1224
}
1225

    
1226
#define ARM_CP_RW_BIT        (1 << 20)
1227

    
1228
static inline void iwmmxt_load_reg(TCGv var, int reg)
1229
{
1230
    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1231
}
1232

    
1233
static inline void iwmmxt_store_reg(TCGv var, int reg)
1234
{
1235
    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1236
}
1237

    
1238
static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1239
{
1240
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1241
}
1242

    
1243
static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1244
{
1245
    tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1246
}
1247

    
1248
static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1249
{
1250
    tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1251
}
1252

    
1253
static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1254
{
1255
    iwmmxt_store_reg(cpu_M0, rn);
1256
}
1257

    
1258
static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1259
{
1260
    iwmmxt_load_reg(cpu_M0, rn);
1261
}
1262

    
1263
static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1264
{
1265
    iwmmxt_load_reg(cpu_V1, rn);
1266
    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1267
}
1268

    
1269
static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1270
{
1271
    iwmmxt_load_reg(cpu_V1, rn);
1272
    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1273
}
1274

    
1275
static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1276
{
1277
    iwmmxt_load_reg(cpu_V1, rn);
1278
    tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1279
}
1280

    
1281
#define IWMMXT_OP(name) \
1282
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1283
{ \
1284
    iwmmxt_load_reg(cpu_V1, rn); \
1285
    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1286
}
1287

    
1288
#define IWMMXT_OP_ENV(name) \
1289
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1290
{ \
1291
    iwmmxt_load_reg(cpu_V1, rn); \
1292
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1293
}
1294

    
1295
#define IWMMXT_OP_ENV_SIZE(name) \
1296
IWMMXT_OP_ENV(name##b) \
1297
IWMMXT_OP_ENV(name##w) \
1298
IWMMXT_OP_ENV(name##l)
1299

    
1300
#define IWMMXT_OP_ENV1(name) \
1301
static inline void gen_op_iwmmxt_##name##_M0(void) \
1302
{ \
1303
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1304
}
1305

    
1306
IWMMXT_OP(maddsq)
1307
IWMMXT_OP(madduq)
1308
IWMMXT_OP(sadb)
1309
IWMMXT_OP(sadw)
1310
IWMMXT_OP(mulslw)
1311
IWMMXT_OP(mulshw)
1312
IWMMXT_OP(mululw)
1313
IWMMXT_OP(muluhw)
1314
IWMMXT_OP(macsw)
1315
IWMMXT_OP(macuw)
1316

    
1317
IWMMXT_OP_ENV_SIZE(unpackl)
1318
IWMMXT_OP_ENV_SIZE(unpackh)
1319

    
1320
IWMMXT_OP_ENV1(unpacklub)
1321
IWMMXT_OP_ENV1(unpackluw)
1322
IWMMXT_OP_ENV1(unpacklul)
1323
IWMMXT_OP_ENV1(unpackhub)
1324
IWMMXT_OP_ENV1(unpackhuw)
1325
IWMMXT_OP_ENV1(unpackhul)
1326
IWMMXT_OP_ENV1(unpacklsb)
1327
IWMMXT_OP_ENV1(unpacklsw)
1328
IWMMXT_OP_ENV1(unpacklsl)
1329
IWMMXT_OP_ENV1(unpackhsb)
1330
IWMMXT_OP_ENV1(unpackhsw)
1331
IWMMXT_OP_ENV1(unpackhsl)
1332

    
1333
IWMMXT_OP_ENV_SIZE(cmpeq)
1334
IWMMXT_OP_ENV_SIZE(cmpgtu)
1335
IWMMXT_OP_ENV_SIZE(cmpgts)
1336

    
1337
IWMMXT_OP_ENV_SIZE(mins)
1338
IWMMXT_OP_ENV_SIZE(minu)
1339
IWMMXT_OP_ENV_SIZE(maxs)
1340
IWMMXT_OP_ENV_SIZE(maxu)
1341

    
1342
IWMMXT_OP_ENV_SIZE(subn)
1343
IWMMXT_OP_ENV_SIZE(addn)
1344
IWMMXT_OP_ENV_SIZE(subu)
1345
IWMMXT_OP_ENV_SIZE(addu)
1346
IWMMXT_OP_ENV_SIZE(subs)
1347
IWMMXT_OP_ENV_SIZE(adds)
1348

    
1349
IWMMXT_OP_ENV(avgb0)
1350
IWMMXT_OP_ENV(avgb1)
1351
IWMMXT_OP_ENV(avgw0)
1352
IWMMXT_OP_ENV(avgw1)
1353

    
1354
IWMMXT_OP(msadb)
1355

    
1356
IWMMXT_OP_ENV(packuw)
1357
IWMMXT_OP_ENV(packul)
1358
IWMMXT_OP_ENV(packuq)
1359
IWMMXT_OP_ENV(packsw)
1360
IWMMXT_OP_ENV(packsl)
1361
IWMMXT_OP_ENV(packsq)
1362

    
1363
static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1364
{
1365
    gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1366
}
1367

    
1368
static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1369
{
1370
    gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1371
}
1372

    
1373
static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1374
{
1375
    gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1376
}
1377

    
1378
static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1379
{
1380
    iwmmxt_load_reg(cpu_V1, rn);
1381
    gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1382
}
1383

    
1384
static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1385
{
1386
    TCGv tmp = tcg_const_i32(shift);
1387
    gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1388
}
1389

    
1390
static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1391
{
1392
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1393
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1394
    tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1395
}
1396

    
1397
static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1398
{
1399
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1400
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1401
    tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1402
}
1403

    
1404
static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1405
{
1406
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1407
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1408
    if (mask != ~0u)
1409
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1410
}
1411

    
1412
static void gen_op_iwmmxt_set_mup(void)
1413
{
1414
    TCGv tmp;
1415
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1416
    tcg_gen_ori_i32(tmp, tmp, 2);
1417
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1418
}
1419

    
1420
static void gen_op_iwmmxt_set_cup(void)
1421
{
1422
    TCGv tmp;
1423
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1424
    tcg_gen_ori_i32(tmp, tmp, 1);
1425
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1426
}
1427

    
1428
static void gen_op_iwmmxt_setpsr_nz(void)
1429
{
1430
    TCGv tmp = new_tmp();
1431
    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1432
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1433
}
1434

    
1435
static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1436
{
1437
    iwmmxt_load_reg(cpu_V1, rn);
1438
    tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1439
    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1440
}
1441

    
1442

    
1443
static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1444
{
1445
    iwmmxt_load_reg(cpu_V0, rn);
1446
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1447
    tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1448
    tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1449
}
1450

    
1451
static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1452
{
1453
    tcg_gen_extu_i32_i64(cpu_V0, cpu_T[0]);
1454
    tcg_gen_extu_i32_i64(cpu_V1, cpu_T[0]);
1455
    tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
1456
    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
1457
    iwmmxt_store_reg(cpu_V0, rn);
1458
}
1459

    
1460
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1461
{
1462
    int rd;
1463
    uint32_t offset;
1464

    
1465
    rd = (insn >> 16) & 0xf;
1466
    gen_movl_T1_reg(s, rd);
1467

    
1468
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1469
    if (insn & (1 << 24)) {
1470
        /* Pre indexed */
1471
        if (insn & (1 << 23))
1472
            gen_op_addl_T1_im(offset);
1473
        else
1474
            gen_op_addl_T1_im(-offset);
1475

    
1476
        if (insn & (1 << 21))
1477
            gen_movl_reg_T1(s, rd);
1478
    } else if (insn & (1 << 21)) {
1479
        /* Post indexed */
1480
        if (insn & (1 << 23))
1481
            gen_op_movl_T0_im(offset);
1482
        else
1483
            gen_op_movl_T0_im(- offset);
1484
        gen_op_addl_T0_T1();
1485
        gen_movl_reg_T0(s, rd);
1486
    } else if (!(insn & (1 << 23)))
1487
        return 1;
1488
    return 0;
1489
}
1490

    
1491
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1492
{
1493
    int rd = (insn >> 0) & 0xf;
1494

    
1495
    if (insn & (1 << 8))
1496
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1497
            return 1;
1498
        else
1499
            gen_op_iwmmxt_movl_T0_wCx(rd);
1500
    else
1501
        gen_iwmmxt_movl_T0_T1_wRn(rd);
1502

    
1503
    gen_op_movl_T1_im(mask);
1504
    gen_op_andl_T0_T1();
1505
    return 0;
1506
}
1507

    
1508
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1509
   (ie. an undefined instruction).  */
1510
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1511
{
1512
    int rd, wrd;
1513
    int rdhi, rdlo, rd0, rd1, i;
1514
    TCGv tmp;
1515

    
1516
    if ((insn & 0x0e000e00) == 0x0c000000) {
1517
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1518
            wrd = insn & 0xf;
1519
            rdlo = (insn >> 12) & 0xf;
1520
            rdhi = (insn >> 16) & 0xf;
1521
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1522
                gen_iwmmxt_movl_T0_T1_wRn(wrd);
1523
                gen_movl_reg_T0(s, rdlo);
1524
                gen_movl_reg_T1(s, rdhi);
1525
            } else {                                        /* TMCRR */
1526
                gen_movl_T0_reg(s, rdlo);
1527
                gen_movl_T1_reg(s, rdhi);
1528
                gen_iwmmxt_movl_wRn_T0_T1(wrd);
1529
                gen_op_iwmmxt_set_mup();
1530
            }
1531
            return 0;
1532
        }
1533

    
1534
        wrd = (insn >> 12) & 0xf;
1535
        if (gen_iwmmxt_address(s, insn))
1536
            return 1;
1537
        if (insn & ARM_CP_RW_BIT) {
1538
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1539
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1540
                tcg_gen_mov_i32(cpu_T[0], tmp);
1541
                dead_tmp(tmp);
1542
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1543
            } else {
1544
                i = 1;
1545
                if (insn & (1 << 8)) {
1546
                    if (insn & (1 << 22)) {                /* WLDRD */
1547
                        tcg_gen_qemu_ld64(cpu_M0, cpu_T[1], IS_USER(s));
1548
                        i = 0;
1549
                    } else {                                /* WLDRW wRd */
1550
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
1551
                    }
1552
                } else {
1553
                    if (insn & (1 << 22)) {                /* WLDRH */
1554
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
1555
                    } else {                                /* WLDRB */
1556
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
1557
                    }
1558
                }
1559
                if (i) {
1560
                    tcg_gen_extu_i32_i64(cpu_M0, tmp);
1561
                    dead_tmp(tmp);
1562
                }
1563
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1564
            }
1565
        } else {
1566
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1567
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1568
                tmp = new_tmp();
1569
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1570
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1571
            } else {
1572
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1573
                tmp = new_tmp();
1574
                if (insn & (1 << 8)) {
1575
                    if (insn & (1 << 22)) {                /* WSTRD */
1576
                        dead_tmp(tmp);
1577
                        tcg_gen_qemu_st64(cpu_M0, cpu_T[1], IS_USER(s));
1578
                    } else {                                /* WSTRW wRd */
1579
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1580
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
1581
                    }
1582
                } else {
1583
                    if (insn & (1 << 22)) {                /* WSTRH */
1584
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1585
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
1586
                    } else {                                /* WSTRB */
1587
                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1588
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
1589
                    }
1590
                }
1591
            }
1592
        }
1593
        return 0;
1594
    }
1595

    
1596
    if ((insn & 0x0f000000) != 0x0e000000)
1597
        return 1;
1598

    
1599
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1600
    case 0x000:                                                /* WOR */
1601
        wrd = (insn >> 12) & 0xf;
1602
        rd0 = (insn >> 0) & 0xf;
1603
        rd1 = (insn >> 16) & 0xf;
1604
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1605
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1606
        gen_op_iwmmxt_setpsr_nz();
1607
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1608
        gen_op_iwmmxt_set_mup();
1609
        gen_op_iwmmxt_set_cup();
1610
        break;
1611
    case 0x011:                                                /* TMCR */
1612
        if (insn & 0xf)
1613
            return 1;
1614
        rd = (insn >> 12) & 0xf;
1615
        wrd = (insn >> 16) & 0xf;
1616
        switch (wrd) {
1617
        case ARM_IWMMXT_wCID:
1618
        case ARM_IWMMXT_wCASF:
1619
            break;
1620
        case ARM_IWMMXT_wCon:
1621
            gen_op_iwmmxt_set_cup();
1622
            /* Fall through.  */
1623
        case ARM_IWMMXT_wCSSF:
1624
            gen_op_iwmmxt_movl_T0_wCx(wrd);
1625
            gen_movl_T1_reg(s, rd);
1626
            gen_op_bicl_T0_T1();
1627
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1628
            break;
1629
        case ARM_IWMMXT_wCGR0:
1630
        case ARM_IWMMXT_wCGR1:
1631
        case ARM_IWMMXT_wCGR2:
1632
        case ARM_IWMMXT_wCGR3:
1633
            gen_op_iwmmxt_set_cup();
1634
            gen_movl_reg_T0(s, rd);
1635
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1636
            break;
1637
        default:
1638
            return 1;
1639
        }
1640
        break;
1641
    case 0x100:                                                /* WXOR */
1642
        wrd = (insn >> 12) & 0xf;
1643
        rd0 = (insn >> 0) & 0xf;
1644
        rd1 = (insn >> 16) & 0xf;
1645
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1646
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1647
        gen_op_iwmmxt_setpsr_nz();
1648
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1649
        gen_op_iwmmxt_set_mup();
1650
        gen_op_iwmmxt_set_cup();
1651
        break;
1652
    case 0x111:                                                /* TMRC */
1653
        if (insn & 0xf)
1654
            return 1;
1655
        rd = (insn >> 12) & 0xf;
1656
        wrd = (insn >> 16) & 0xf;
1657
        gen_op_iwmmxt_movl_T0_wCx(wrd);
1658
        gen_movl_reg_T0(s, rd);
1659
        break;
1660
    case 0x300:                                                /* WANDN */
1661
        wrd = (insn >> 12) & 0xf;
1662
        rd0 = (insn >> 0) & 0xf;
1663
        rd1 = (insn >> 16) & 0xf;
1664
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1665
        tcg_gen_neg_i64(cpu_M0, cpu_M0);
1666
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1667
        gen_op_iwmmxt_setpsr_nz();
1668
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1669
        gen_op_iwmmxt_set_mup();
1670
        gen_op_iwmmxt_set_cup();
1671
        break;
1672
    case 0x200:                                                /* WAND */
1673
        wrd = (insn >> 12) & 0xf;
1674
        rd0 = (insn >> 0) & 0xf;
1675
        rd1 = (insn >> 16) & 0xf;
1676
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1677
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1678
        gen_op_iwmmxt_setpsr_nz();
1679
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1680
        gen_op_iwmmxt_set_mup();
1681
        gen_op_iwmmxt_set_cup();
1682
        break;
1683
    case 0x810: case 0xa10:                                /* WMADD */
1684
        wrd = (insn >> 12) & 0xf;
1685
        rd0 = (insn >> 0) & 0xf;
1686
        rd1 = (insn >> 16) & 0xf;
1687
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1688
        if (insn & (1 << 21))
1689
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1690
        else
1691
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1692
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1693
        gen_op_iwmmxt_set_mup();
1694
        break;
1695
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1696
        wrd = (insn >> 12) & 0xf;
1697
        rd0 = (insn >> 16) & 0xf;
1698
        rd1 = (insn >> 0) & 0xf;
1699
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1700
        switch ((insn >> 22) & 3) {
1701
        case 0:
1702
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1703
            break;
1704
        case 1:
1705
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1706
            break;
1707
        case 2:
1708
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1709
            break;
1710
        case 3:
1711
            return 1;
1712
        }
1713
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1714
        gen_op_iwmmxt_set_mup();
1715
        gen_op_iwmmxt_set_cup();
1716
        break;
1717
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1718
        wrd = (insn >> 12) & 0xf;
1719
        rd0 = (insn >> 16) & 0xf;
1720
        rd1 = (insn >> 0) & 0xf;
1721
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1722
        switch ((insn >> 22) & 3) {
1723
        case 0:
1724
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1725
            break;
1726
        case 1:
1727
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1728
            break;
1729
        case 2:
1730
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1731
            break;
1732
        case 3:
1733
            return 1;
1734
        }
1735
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1736
        gen_op_iwmmxt_set_mup();
1737
        gen_op_iwmmxt_set_cup();
1738
        break;
1739
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1740
        wrd = (insn >> 12) & 0xf;
1741
        rd0 = (insn >> 16) & 0xf;
1742
        rd1 = (insn >> 0) & 0xf;
1743
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1744
        if (insn & (1 << 22))
1745
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1746
        else
1747
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1748
        if (!(insn & (1 << 20)))
1749
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1750
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1751
        gen_op_iwmmxt_set_mup();
1752
        break;
1753
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1754
        wrd = (insn >> 12) & 0xf;
1755
        rd0 = (insn >> 16) & 0xf;
1756
        rd1 = (insn >> 0) & 0xf;
1757
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1758
        if (insn & (1 << 21)) {
1759
            if (insn & (1 << 20))
1760
                gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1761
            else
1762
                gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1763
        } else {
1764
            if (insn & (1 << 20))
1765
                gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1766
            else
1767
                gen_op_iwmmxt_mululw_M0_wRn(rd1);
1768
        }
1769
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1770
        gen_op_iwmmxt_set_mup();
1771
        break;
1772
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1773
        wrd = (insn >> 12) & 0xf;
1774
        rd0 = (insn >> 16) & 0xf;
1775
        rd1 = (insn >> 0) & 0xf;
1776
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1777
        if (insn & (1 << 21))
1778
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1779
        else
1780
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1781
        if (!(insn & (1 << 20))) {
1782
            iwmmxt_load_reg(cpu_V1, wrd);
1783
            tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1784
        }
1785
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1786
        gen_op_iwmmxt_set_mup();
1787
        break;
1788
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1789
        wrd = (insn >> 12) & 0xf;
1790
        rd0 = (insn >> 16) & 0xf;
1791
        rd1 = (insn >> 0) & 0xf;
1792
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1793
        switch ((insn >> 22) & 3) {
1794
        case 0:
1795
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1796
            break;
1797
        case 1:
1798
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1799
            break;
1800
        case 2:
1801
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1802
            break;
1803
        case 3:
1804
            return 1;
1805
        }
1806
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1807
        gen_op_iwmmxt_set_mup();
1808
        gen_op_iwmmxt_set_cup();
1809
        break;
1810
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1811
        wrd = (insn >> 12) & 0xf;
1812
        rd0 = (insn >> 16) & 0xf;
1813
        rd1 = (insn >> 0) & 0xf;
1814
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1815
        if (insn & (1 << 22)) {
1816
            if (insn & (1 << 20))
1817
                gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1818
            else
1819
                gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1820
        } else {
1821
            if (insn & (1 << 20))
1822
                gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1823
            else
1824
                gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1825
        }
1826
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1827
        gen_op_iwmmxt_set_mup();
1828
        gen_op_iwmmxt_set_cup();
1829
        break;
1830
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1831
        wrd = (insn >> 12) & 0xf;
1832
        rd0 = (insn >> 16) & 0xf;
1833
        rd1 = (insn >> 0) & 0xf;
1834
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1835
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1836
        gen_op_movl_T1_im(7);
1837
        gen_op_andl_T0_T1();
1838
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1839
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1840
        gen_op_iwmmxt_set_mup();
1841
        break;
1842
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1843
        rd = (insn >> 12) & 0xf;
1844
        wrd = (insn >> 16) & 0xf;
1845
        gen_movl_T0_reg(s, rd);
1846
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1847
        switch ((insn >> 6) & 3) {
1848
        case 0:
1849
            gen_op_movl_T1_im(0xff);
1850
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1851
            break;
1852
        case 1:
1853
            gen_op_movl_T1_im(0xffff);
1854
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1855
            break;
1856
        case 2:
1857
            gen_op_movl_T1_im(0xffffffff);
1858
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1859
            break;
1860
        case 3:
1861
            return 1;
1862
        }
1863
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1864
        gen_op_iwmmxt_set_mup();
1865
        break;
1866
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1867
        rd = (insn >> 12) & 0xf;
1868
        wrd = (insn >> 16) & 0xf;
1869
        if (rd == 15)
1870
            return 1;
1871
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1872
        switch ((insn >> 22) & 3) {
1873
        case 0:
1874
            if (insn & 8)
1875
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1876
            else {
1877
                gen_op_iwmmxt_extru_T0_M0((insn & 7) << 3, 0xff);
1878
            }
1879
            break;
1880
        case 1:
1881
            if (insn & 8)
1882
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1883
            else {
1884
                gen_op_iwmmxt_extru_T0_M0((insn & 3) << 4, 0xffff);
1885
            }
1886
            break;
1887
        case 2:
1888
            gen_op_iwmmxt_extru_T0_M0((insn & 1) << 5, ~0u);
1889
            break;
1890
        case 3:
1891
            return 1;
1892
        }
1893
        gen_movl_reg_T0(s, rd);
1894
        break;
1895
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1896
        if ((insn & 0x000ff008) != 0x0003f000)
1897
            return 1;
1898
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1899
        switch ((insn >> 22) & 3) {
1900
        case 0:
1901
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1902
            break;
1903
        case 1:
1904
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1905
            break;
1906
        case 2:
1907
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1908
            break;
1909
        case 3:
1910
            return 1;
1911
        }
1912
        gen_op_shll_T1_im(28);
1913
        gen_set_nzcv(cpu_T[1]);
1914
        break;
1915
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1916
        rd = (insn >> 12) & 0xf;
1917
        wrd = (insn >> 16) & 0xf;
1918
        gen_movl_T0_reg(s, rd);
1919
        switch ((insn >> 6) & 3) {
1920
        case 0:
1921
            gen_helper_iwmmxt_bcstb(cpu_M0, cpu_T[0]);
1922
            break;
1923
        case 1:
1924
            gen_helper_iwmmxt_bcstw(cpu_M0, cpu_T[0]);
1925
            break;
1926
        case 2:
1927
            gen_helper_iwmmxt_bcstl(cpu_M0, cpu_T[0]);
1928
            break;
1929
        case 3:
1930
            return 1;
1931
        }
1932
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1933
        gen_op_iwmmxt_set_mup();
1934
        break;
1935
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1936
        if ((insn & 0x000ff00f) != 0x0003f000)
1937
            return 1;
1938
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1939
        switch ((insn >> 22) & 3) {
1940
        case 0:
1941
            for (i = 0; i < 7; i ++) {
1942
                gen_op_shll_T1_im(4);
1943
                gen_op_andl_T0_T1();
1944
            }
1945
            break;
1946
        case 1:
1947
            for (i = 0; i < 3; i ++) {
1948
                gen_op_shll_T1_im(8);
1949
                gen_op_andl_T0_T1();
1950
            }
1951
            break;
1952
        case 2:
1953
            gen_op_shll_T1_im(16);
1954
            gen_op_andl_T0_T1();
1955
            break;
1956
        case 3:
1957
            return 1;
1958
        }
1959
        gen_set_nzcv(cpu_T[0]);
1960
        break;
1961
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1962
        wrd = (insn >> 12) & 0xf;
1963
        rd0 = (insn >> 16) & 0xf;
1964
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1965
        switch ((insn >> 22) & 3) {
1966
        case 0:
1967
            gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1968
            break;
1969
        case 1:
1970
            gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1971
            break;
1972
        case 2:
1973
            gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1974
            break;
1975
        case 3:
1976
            return 1;
1977
        }
1978
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1979
        gen_op_iwmmxt_set_mup();
1980
        break;
1981
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1982
        if ((insn & 0x000ff00f) != 0x0003f000)
1983
            return 1;
1984
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1985
        switch ((insn >> 22) & 3) {
1986
        case 0:
1987
            for (i = 0; i < 7; i ++) {
1988
                gen_op_shll_T1_im(4);
1989
                gen_op_orl_T0_T1();
1990
            }
1991
            break;
1992
        case 1:
1993
            for (i = 0; i < 3; i ++) {
1994
                gen_op_shll_T1_im(8);
1995
                gen_op_orl_T0_T1();
1996
            }
1997
            break;
1998
        case 2:
1999
            gen_op_shll_T1_im(16);
2000
            gen_op_orl_T0_T1();
2001
            break;
2002
        case 3:
2003
            return 1;
2004
        }
2005
        gen_set_nzcv(cpu_T[0]);
2006
        break;
2007
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
2008
        rd = (insn >> 12) & 0xf;
2009
        rd0 = (insn >> 16) & 0xf;
2010
        if ((insn & 0xf) != 0)
2011
            return 1;
2012
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2013
        switch ((insn >> 22) & 3) {
2014
        case 0:
2015
            gen_helper_iwmmxt_msbb(cpu_T[0], cpu_M0);
2016
            break;
2017
        case 1:
2018
            gen_helper_iwmmxt_msbw(cpu_T[0], cpu_M0);
2019
            break;
2020
        case 2:
2021
            gen_helper_iwmmxt_msbl(cpu_T[0], cpu_M0);
2022
            break;
2023
        case 3:
2024
            return 1;
2025
        }
2026
        gen_movl_reg_T0(s, rd);
2027
        break;
2028
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
2029
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
2030
        wrd = (insn >> 12) & 0xf;
2031
        rd0 = (insn >> 16) & 0xf;
2032
        rd1 = (insn >> 0) & 0xf;
2033
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2034
        switch ((insn >> 22) & 3) {
2035
        case 0:
2036
            if (insn & (1 << 21))
2037
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2038
            else
2039
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2040
            break;
2041
        case 1:
2042
            if (insn & (1 << 21))
2043
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2044
            else
2045
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2046
            break;
2047
        case 2:
2048
            if (insn & (1 << 21))
2049
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2050
            else
2051
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2052
            break;
2053
        case 3:
2054
            return 1;
2055
        }
2056
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2057
        gen_op_iwmmxt_set_mup();
2058
        gen_op_iwmmxt_set_cup();
2059
        break;
2060
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
2061
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2062
        wrd = (insn >> 12) & 0xf;
2063
        rd0 = (insn >> 16) & 0xf;
2064
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2065
        switch ((insn >> 22) & 3) {
2066
        case 0:
2067
            if (insn & (1 << 21))
2068
                gen_op_iwmmxt_unpacklsb_M0();
2069
            else
2070
                gen_op_iwmmxt_unpacklub_M0();
2071
            break;
2072
        case 1:
2073
            if (insn & (1 << 21))
2074
                gen_op_iwmmxt_unpacklsw_M0();
2075
            else
2076
                gen_op_iwmmxt_unpackluw_M0();
2077
            break;
2078
        case 2:
2079
            if (insn & (1 << 21))
2080
                gen_op_iwmmxt_unpacklsl_M0();
2081
            else
2082
                gen_op_iwmmxt_unpacklul_M0();
2083
            break;
2084
        case 3:
2085
            return 1;
2086
        }
2087
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2088
        gen_op_iwmmxt_set_mup();
2089
        gen_op_iwmmxt_set_cup();
2090
        break;
2091
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
2092
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2093
        wrd = (insn >> 12) & 0xf;
2094
        rd0 = (insn >> 16) & 0xf;
2095
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2096
        switch ((insn >> 22) & 3) {
2097
        case 0:
2098
            if (insn & (1 << 21))
2099
                gen_op_iwmmxt_unpackhsb_M0();
2100
            else
2101
                gen_op_iwmmxt_unpackhub_M0();
2102
            break;
2103
        case 1:
2104
            if (insn & (1 << 21))
2105
                gen_op_iwmmxt_unpackhsw_M0();
2106
            else
2107
                gen_op_iwmmxt_unpackhuw_M0();
2108
            break;
2109
        case 2:
2110
            if (insn & (1 << 21))
2111
                gen_op_iwmmxt_unpackhsl_M0();
2112
            else
2113
                gen_op_iwmmxt_unpackhul_M0();
2114
            break;
2115
        case 3:
2116
            return 1;
2117
        }
2118
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2119
        gen_op_iwmmxt_set_mup();
2120
        gen_op_iwmmxt_set_cup();
2121
        break;
2122
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
2123
    case 0x214: case 0x614: case 0xa14: case 0xe14:
2124
        wrd = (insn >> 12) & 0xf;
2125
        rd0 = (insn >> 16) & 0xf;
2126
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2127
        if (gen_iwmmxt_shift(insn, 0xff))
2128
            return 1;
2129
        switch ((insn >> 22) & 3) {
2130
        case 0:
2131
            return 1;
2132
        case 1:
2133
            gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2134
            break;
2135
        case 2:
2136
            gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2137
            break;
2138
        case 3:
2139
            gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2140
            break;
2141
        }
2142
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2143
        gen_op_iwmmxt_set_mup();
2144
        gen_op_iwmmxt_set_cup();
2145
        break;
2146
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
2147
    case 0x014: case 0x414: case 0x814: case 0xc14:
2148
        wrd = (insn >> 12) & 0xf;
2149
        rd0 = (insn >> 16) & 0xf;
2150
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2151
        if (gen_iwmmxt_shift(insn, 0xff))
2152
            return 1;
2153
        switch ((insn >> 22) & 3) {
2154
        case 0:
2155
            return 1;
2156
        case 1:
2157
            gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2158
            break;
2159
        case 2:
2160
            gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2161
            break;
2162
        case 3:
2163
            gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2164
            break;
2165
        }
2166
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2167
        gen_op_iwmmxt_set_mup();
2168
        gen_op_iwmmxt_set_cup();
2169
        break;
2170
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
2171
    case 0x114: case 0x514: case 0x914: case 0xd14:
2172
        wrd = (insn >> 12) & 0xf;
2173
        rd0 = (insn >> 16) & 0xf;
2174
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2175
        if (gen_iwmmxt_shift(insn, 0xff))
2176
            return 1;
2177
        switch ((insn >> 22) & 3) {
2178
        case 0:
2179
            return 1;
2180
        case 1:
2181
            gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2182
            break;
2183
        case 2:
2184
            gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2185
            break;
2186
        case 3:
2187
            gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2188
            break;
2189
        }
2190
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2191
        gen_op_iwmmxt_set_mup();
2192
        gen_op_iwmmxt_set_cup();
2193
        break;
2194
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
2195
    case 0x314: case 0x714: case 0xb14: case 0xf14:
2196
        wrd = (insn >> 12) & 0xf;
2197
        rd0 = (insn >> 16) & 0xf;
2198
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2199
        switch ((insn >> 22) & 3) {
2200
        case 0:
2201
            return 1;
2202
        case 1:
2203
            if (gen_iwmmxt_shift(insn, 0xf))
2204
                return 1;
2205
            gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2206
            break;
2207
        case 2:
2208
            if (gen_iwmmxt_shift(insn, 0x1f))
2209
                return 1;
2210
            gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2211
            break;
2212
        case 3:
2213
            if (gen_iwmmxt_shift(insn, 0x3f))
2214
                return 1;
2215
            gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2216
            break;
2217
        }
2218
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2219
        gen_op_iwmmxt_set_mup();
2220
        gen_op_iwmmxt_set_cup();
2221
        break;
2222
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
2223
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
2224
        wrd = (insn >> 12) & 0xf;
2225
        rd0 = (insn >> 16) & 0xf;
2226
        rd1 = (insn >> 0) & 0xf;
2227
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2228
        switch ((insn >> 22) & 3) {
2229
        case 0:
2230
            if (insn & (1 << 21))
2231
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
2232
            else
2233
                gen_op_iwmmxt_minub_M0_wRn(rd1);
2234
            break;
2235
        case 1:
2236
            if (insn & (1 << 21))
2237
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
2238
            else
2239
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
2240
            break;
2241
        case 2:
2242
            if (insn & (1 << 21))
2243
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
2244
            else
2245
                gen_op_iwmmxt_minul_M0_wRn(rd1);
2246
            break;
2247
        case 3:
2248
            return 1;
2249
        }
2250
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2251
        gen_op_iwmmxt_set_mup();
2252
        break;
2253
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
2254
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
2255
        wrd = (insn >> 12) & 0xf;
2256
        rd0 = (insn >> 16) & 0xf;
2257
        rd1 = (insn >> 0) & 0xf;
2258
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2259
        switch ((insn >> 22) & 3) {
2260
        case 0:
2261
            if (insn & (1 << 21))
2262
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2263
            else
2264
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
2265
            break;
2266
        case 1:
2267
            if (insn & (1 << 21))
2268
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2269
            else
2270
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2271
            break;
2272
        case 2:
2273
            if (insn & (1 << 21))
2274
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2275
            else
2276
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
2277
            break;
2278
        case 3:
2279
            return 1;
2280
        }
2281
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2282
        gen_op_iwmmxt_set_mup();
2283
        break;
2284
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
2285
    case 0x402: case 0x502: case 0x602: case 0x702:
2286
        wrd = (insn >> 12) & 0xf;
2287
        rd0 = (insn >> 16) & 0xf;
2288
        rd1 = (insn >> 0) & 0xf;
2289
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2290
        gen_op_movl_T0_im((insn >> 20) & 3);
2291
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
2292
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2293
        gen_op_iwmmxt_set_mup();
2294
        break;
2295
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
2296
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2297
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2298
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2299
        wrd = (insn >> 12) & 0xf;
2300
        rd0 = (insn >> 16) & 0xf;
2301
        rd1 = (insn >> 0) & 0xf;
2302
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2303
        switch ((insn >> 20) & 0xf) {
2304
        case 0x0:
2305
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
2306
            break;
2307
        case 0x1:
2308
            gen_op_iwmmxt_subub_M0_wRn(rd1);
2309
            break;
2310
        case 0x3:
2311
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
2312
            break;
2313
        case 0x4:
2314
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
2315
            break;
2316
        case 0x5:
2317
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
2318
            break;
2319
        case 0x7:
2320
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
2321
            break;
2322
        case 0x8:
2323
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
2324
            break;
2325
        case 0x9:
2326
            gen_op_iwmmxt_subul_M0_wRn(rd1);
2327
            break;
2328
        case 0xb:
2329
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
2330
            break;
2331
        default:
2332
            return 1;
2333
        }
2334
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2335
        gen_op_iwmmxt_set_mup();
2336
        gen_op_iwmmxt_set_cup();
2337
        break;
2338
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
2339
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2340
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2341
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2342
        wrd = (insn >> 12) & 0xf;
2343
        rd0 = (insn >> 16) & 0xf;
2344
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2345
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2346
        gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, cpu_T[0]);
2347
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2348
        gen_op_iwmmxt_set_mup();
2349
        gen_op_iwmmxt_set_cup();
2350
        break;
2351
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
2352
    case 0x418: case 0x518: case 0x618: case 0x718:
2353
    case 0x818: case 0x918: case 0xa18: case 0xb18:
2354
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2355
        wrd = (insn >> 12) & 0xf;
2356
        rd0 = (insn >> 16) & 0xf;
2357
        rd1 = (insn >> 0) & 0xf;
2358
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2359
        switch ((insn >> 20) & 0xf) {
2360
        case 0x0:
2361
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
2362
            break;
2363
        case 0x1:
2364
            gen_op_iwmmxt_addub_M0_wRn(rd1);
2365
            break;
2366
        case 0x3:
2367
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
2368
            break;
2369
        case 0x4:
2370
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
2371
            break;
2372
        case 0x5:
2373
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
2374
            break;
2375
        case 0x7:
2376
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
2377
            break;
2378
        case 0x8:
2379
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
2380
            break;
2381
        case 0x9:
2382
            gen_op_iwmmxt_addul_M0_wRn(rd1);
2383
            break;
2384
        case 0xb:
2385
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
2386
            break;
2387
        default:
2388
            return 1;
2389
        }
2390
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2391
        gen_op_iwmmxt_set_mup();
2392
        gen_op_iwmmxt_set_cup();
2393
        break;
2394
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
2395
    case 0x408: case 0x508: case 0x608: case 0x708:
2396
    case 0x808: case 0x908: case 0xa08: case 0xb08:
2397
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2398
        wrd = (insn >> 12) & 0xf;
2399
        rd0 = (insn >> 16) & 0xf;
2400
        rd1 = (insn >> 0) & 0xf;
2401
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2402
        if (!(insn & (1 << 20)))
2403
            return 1;
2404
        switch ((insn >> 22) & 3) {
2405
        case 0:
2406
            return 1;
2407
        case 1:
2408
            if (insn & (1 << 21))
2409
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
2410
            else
2411
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
2412
            break;
2413
        case 2:
2414
            if (insn & (1 << 21))
2415
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
2416
            else
2417
                gen_op_iwmmxt_packul_M0_wRn(rd1);
2418
            break;
2419
        case 3:
2420
            if (insn & (1 << 21))
2421
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
2422
            else
2423
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
2424
            break;
2425
        }
2426
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2427
        gen_op_iwmmxt_set_mup();
2428
        gen_op_iwmmxt_set_cup();
2429
        break;
2430
    case 0x201: case 0x203: case 0x205: case 0x207:
2431
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
2432
    case 0x211: case 0x213: case 0x215: case 0x217:
2433
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
2434
        wrd = (insn >> 5) & 0xf;
2435
        rd0 = (insn >> 12) & 0xf;
2436
        rd1 = (insn >> 0) & 0xf;
2437
        if (rd0 == 0xf || rd1 == 0xf)
2438
            return 1;
2439
        gen_op_iwmmxt_movq_M0_wRn(wrd);
2440
        switch ((insn >> 16) & 0xf) {
2441
        case 0x0:                                        /* TMIA */
2442
            gen_movl_T0_reg(s, rd0);
2443
            gen_movl_T1_reg(s, rd1);
2444
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2445
            break;
2446
        case 0x8:                                        /* TMIAPH */
2447
            gen_movl_T0_reg(s, rd0);
2448
            gen_movl_T1_reg(s, rd1);
2449
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2450
            break;
2451
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2452
            gen_movl_T1_reg(s, rd0);
2453
            if (insn & (1 << 16))
2454
                gen_op_shrl_T1_im(16);
2455
            gen_op_movl_T0_T1();
2456
            gen_movl_T1_reg(s, rd1);
2457
            if (insn & (1 << 17))
2458
                gen_op_shrl_T1_im(16);
2459
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2460
            break;
2461
        default:
2462
            return 1;
2463
        }
2464
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2465
        gen_op_iwmmxt_set_mup();
2466
        break;
2467
    default:
2468
        return 1;
2469
    }
2470

    
2471
    return 0;
2472
}
2473

    
2474
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2475
   (ie. an undefined instruction).  */
2476
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2477
{
2478
    int acc, rd0, rd1, rdhi, rdlo;
2479

    
2480
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2481
        /* Multiply with Internal Accumulate Format */
2482
        rd0 = (insn >> 12) & 0xf;
2483
        rd1 = insn & 0xf;
2484
        acc = (insn >> 5) & 7;
2485

    
2486
        if (acc != 0)
2487
            return 1;
2488

    
2489
        switch ((insn >> 16) & 0xf) {
2490
        case 0x0:                                        /* MIA */
2491
            gen_movl_T0_reg(s, rd0);
2492
            gen_movl_T1_reg(s, rd1);
2493
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2494
            break;
2495
        case 0x8:                                        /* MIAPH */
2496
            gen_movl_T0_reg(s, rd0);
2497
            gen_movl_T1_reg(s, rd1);
2498
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2499
            break;
2500
        case 0xc:                                        /* MIABB */
2501
        case 0xd:                                        /* MIABT */
2502
        case 0xe:                                        /* MIATB */
2503
        case 0xf:                                        /* MIATT */
2504
            gen_movl_T1_reg(s, rd0);
2505
            if (insn & (1 << 16))
2506
                gen_op_shrl_T1_im(16);
2507
            gen_op_movl_T0_T1();
2508
            gen_movl_T1_reg(s, rd1);
2509
            if (insn & (1 << 17))
2510
                gen_op_shrl_T1_im(16);
2511
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2512
            break;
2513
        default:
2514
            return 1;
2515
        }
2516

    
2517
        gen_op_iwmmxt_movq_wRn_M0(acc);
2518
        return 0;
2519
    }
2520

    
2521
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2522
        /* Internal Accumulator Access Format */
2523
        rdhi = (insn >> 16) & 0xf;
2524
        rdlo = (insn >> 12) & 0xf;
2525
        acc = insn & 7;
2526

    
2527
        if (acc != 0)
2528
            return 1;
2529

    
2530
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2531
            gen_iwmmxt_movl_T0_T1_wRn(acc);
2532
            gen_movl_reg_T0(s, rdlo);
2533
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2534
            gen_op_andl_T0_T1();
2535
            gen_movl_reg_T0(s, rdhi);
2536
        } else {                                        /* MAR */
2537
            gen_movl_T0_reg(s, rdlo);
2538
            gen_movl_T1_reg(s, rdhi);
2539
            gen_iwmmxt_movl_wRn_T0_T1(acc);
2540
        }
2541
        return 0;
2542
    }
2543

    
2544
    return 1;
2545
}
2546

    
2547
/* Disassemble system coprocessor instruction.  Return nonzero if
2548
   instruction is not defined.  */
2549
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2550
{
2551
    TCGv tmp;
2552
    uint32_t rd = (insn >> 12) & 0xf;
2553
    uint32_t cp = (insn >> 8) & 0xf;
2554
    if (IS_USER(s)) {
2555
        return 1;
2556
    }
2557

    
2558
    if (insn & ARM_CP_RW_BIT) {
2559
        if (!env->cp[cp].cp_read)
2560
            return 1;
2561
        gen_set_pc_im(s->pc);
2562
        tmp = new_tmp();
2563
        gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2564
        store_reg(s, rd, tmp);
2565
    } else {
2566
        if (!env->cp[cp].cp_write)
2567
            return 1;
2568
        gen_set_pc_im(s->pc);
2569
        tmp = load_reg(s, rd);
2570
        gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2571
        dead_tmp(tmp);
2572
    }
2573
    return 0;
2574
}
2575

    
2576
static int cp15_user_ok(uint32_t insn)
2577
{
2578
    int cpn = (insn >> 16) & 0xf;
2579
    int cpm = insn & 0xf;
2580
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2581

    
2582
    if (cpn == 13 && cpm == 0) {
2583
        /* TLS register.  */
2584
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2585
            return 1;
2586
    }
2587
    if (cpn == 7) {
2588
        /* ISB, DSB, DMB.  */
2589
        if ((cpm == 5 && op == 4)
2590
                || (cpm == 10 && (op == 4 || op == 5)))
2591
            return 1;
2592
    }
2593
    return 0;
2594
}
2595

    
2596
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2597
   instruction is not defined.  */
2598
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2599
{
2600
    uint32_t rd;
2601
    TCGv tmp;
2602

    
2603
    /* M profile cores use memory mapped registers instead of cp15.  */
2604
    if (arm_feature(env, ARM_FEATURE_M))
2605
        return 1;
2606

    
2607
    if ((insn & (1 << 25)) == 0) {
2608
        if (insn & (1 << 20)) {
2609
            /* mrrc */
2610
            return 1;
2611
        }
2612
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2613
        return 0;
2614
    }
2615
    if ((insn & (1 << 4)) == 0) {
2616
        /* cdp */
2617
        return 1;
2618
    }
2619
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2620
        return 1;
2621
    }
2622
    if ((insn & 0x0fff0fff) == 0x0e070f90
2623
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2624
        /* Wait for interrupt.  */
2625
        gen_set_pc_im(s->pc);
2626
        s->is_jmp = DISAS_WFI;
2627
        return 0;
2628
    }
2629
    rd = (insn >> 12) & 0xf;
2630
    if (insn & ARM_CP_RW_BIT) {
2631
        tmp = new_tmp();
2632
        gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2633
        /* If the destination register is r15 then sets condition codes.  */
2634
        if (rd != 15)
2635
            store_reg(s, rd, tmp);
2636
        else
2637
            dead_tmp(tmp);
2638
    } else {
2639
        tmp = load_reg(s, rd);
2640
        gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2641
        dead_tmp(tmp);
2642
        /* Normally we would always end the TB here, but Linux
2643
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2644
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2645
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2646
                (insn & 0x0fff0fff) != 0x0e010f10)
2647
            gen_lookup_tb(s);
2648
    }
2649
    return 0;
2650
}
2651

    
2652
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2653
#define VFP_SREG(insn, bigbit, smallbit) \
2654
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2655
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2656
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2657
        reg = (((insn) >> (bigbit)) & 0x0f) \
2658
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2659
    } else { \
2660
        if (insn & (1 << (smallbit))) \
2661
            return 1; \
2662
        reg = ((insn) >> (bigbit)) & 0x0f; \
2663
    }} while (0)
2664

    
2665
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2666
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2667
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2668
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2669
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2670
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2671

    
2672
/* Move between integer and VFP cores.  */
2673
static TCGv gen_vfp_mrs(void)
2674
{
2675
    TCGv tmp = new_tmp();
2676
    tcg_gen_mov_i32(tmp, cpu_F0s);
2677
    return tmp;
2678
}
2679

    
2680
static void gen_vfp_msr(TCGv tmp)
2681
{
2682
    tcg_gen_mov_i32(cpu_F0s, tmp);
2683
    dead_tmp(tmp);
2684
}
2685

    
2686
static inline int
2687
vfp_enabled(CPUState * env)
2688
{
2689
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2690
}
2691

    
2692
static void gen_neon_dup_u8(TCGv var, int shift)
2693
{
2694
    TCGv tmp = new_tmp();
2695
    if (shift)
2696
        tcg_gen_shri_i32(var, var, shift);
2697
    tcg_gen_ext8u_i32(var, var);
2698
    tcg_gen_shli_i32(tmp, var, 8);
2699
    tcg_gen_or_i32(var, var, tmp);
2700
    tcg_gen_shli_i32(tmp, var, 16);
2701
    tcg_gen_or_i32(var, var, tmp);
2702
    dead_tmp(tmp);
2703
}
2704

    
2705
static void gen_neon_dup_low16(TCGv var)
2706
{
2707
    TCGv tmp = new_tmp();
2708
    tcg_gen_ext16u_i32(var, var);
2709
    tcg_gen_shli_i32(tmp, var, 16);
2710
    tcg_gen_or_i32(var, var, tmp);
2711
    dead_tmp(tmp);
2712
}
2713

    
2714
static void gen_neon_dup_high16(TCGv var)
2715
{
2716
    TCGv tmp = new_tmp();
2717
    tcg_gen_andi_i32(var, var, 0xffff0000);
2718
    tcg_gen_shri_i32(tmp, var, 16);
2719
    tcg_gen_or_i32(var, var, tmp);
2720
    dead_tmp(tmp);
2721
}
2722

    
2723
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2724
   (ie. an undefined instruction).  */
2725
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2726
{
2727
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2728
    int dp, veclen;
2729
    TCGv tmp;
2730
    TCGv tmp2;
2731

    
2732
    if (!arm_feature(env, ARM_FEATURE_VFP))
2733
        return 1;
2734

    
2735
    if (!vfp_enabled(env)) {
2736
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2737
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2738
            return 1;
2739
        rn = (insn >> 16) & 0xf;
2740
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2741
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2742
            return 1;
2743
    }
2744
    dp = ((insn & 0xf00) == 0xb00);
2745
    switch ((insn >> 24) & 0xf) {
2746
    case 0xe:
2747
        if (insn & (1 << 4)) {
2748
            /* single register transfer */
2749
            rd = (insn >> 12) & 0xf;
2750
            if (dp) {
2751
                int size;
2752
                int pass;
2753

    
2754
                VFP_DREG_N(rn, insn);
2755
                if (insn & 0xf)
2756
                    return 1;
2757
                if (insn & 0x00c00060
2758
                    && !arm_feature(env, ARM_FEATURE_NEON))
2759
                    return 1;
2760

    
2761
                pass = (insn >> 21) & 1;
2762
                if (insn & (1 << 22)) {
2763
                    size = 0;
2764
                    offset = ((insn >> 5) & 3) * 8;
2765
                } else if (insn & (1 << 5)) {
2766
                    size = 1;
2767
                    offset = (insn & (1 << 6)) ? 16 : 0;
2768
                } else {
2769
                    size = 2;
2770
                    offset = 0;
2771
                }
2772
                if (insn & ARM_CP_RW_BIT) {
2773
                    /* vfp->arm */
2774
                    tmp = neon_load_reg(rn, pass);
2775
                    switch (size) {
2776
                    case 0:
2777
                        if (offset)
2778
                            tcg_gen_shri_i32(tmp, tmp, offset);
2779
                        if (insn & (1 << 23))
2780
                            gen_uxtb(tmp);
2781
                        else
2782
                            gen_sxtb(tmp);
2783
                        break;
2784
                    case 1:
2785
                        if (insn & (1 << 23)) {
2786
                            if (offset) {
2787
                                tcg_gen_shri_i32(tmp, tmp, 16);
2788
                            } else {
2789
                                gen_uxth(tmp);
2790
                            }
2791
                        } else {
2792
                            if (offset) {
2793
                                tcg_gen_sari_i32(tmp, tmp, 16);
2794
                            } else {
2795
                                gen_sxth(tmp);
2796
                            }
2797
                        }
2798
                        break;
2799
                    case 2:
2800
                        break;
2801
                    }
2802
                    store_reg(s, rd, tmp);
2803
                } else {
2804
                    /* arm->vfp */
2805
                    tmp = load_reg(s, rd);
2806
                    if (insn & (1 << 23)) {
2807
                        /* VDUP */
2808
                        if (size == 0) {
2809
                            gen_neon_dup_u8(tmp, 0);
2810
                        } else if (size == 1) {
2811
                            gen_neon_dup_low16(tmp);
2812
                        }
2813
                        tmp2 = new_tmp();
2814
                        tcg_gen_mov_i32(tmp2, tmp);
2815
                        neon_store_reg(rn, 0, tmp2);
2816
                        neon_store_reg(rn, 0, tmp);
2817
                    } else {
2818
                        /* VMOV */
2819
                        switch (size) {
2820
                        case 0:
2821
                            tmp2 = neon_load_reg(rn, pass);
2822
                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2823
                            dead_tmp(tmp2);
2824
                            break;
2825
                        case 1:
2826
                            tmp2 = neon_load_reg(rn, pass);
2827
                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2828
                            dead_tmp(tmp2);
2829
                            break;
2830
                        case 2:
2831
                            break;
2832
                        }
2833
                        neon_store_reg(rn, pass, tmp);
2834
                    }
2835
                }
2836
            } else { /* !dp */
2837
                if ((insn & 0x6f) != 0x00)
2838
                    return 1;
2839
                rn = VFP_SREG_N(insn);
2840
                if (insn & ARM_CP_RW_BIT) {
2841
                    /* vfp->arm */
2842
                    if (insn & (1 << 21)) {
2843
                        /* system register */
2844
                        rn >>= 1;
2845

    
2846
                        switch (rn) {
2847
                        case ARM_VFP_FPSID:
2848
                            /* VFP2 allows access to FSID from userspace.
2849
                               VFP3 restricts all id registers to privileged
2850
                               accesses.  */
2851
                            if (IS_USER(s)
2852
                                && arm_feature(env, ARM_FEATURE_VFP3))
2853
                                return 1;
2854
                            tmp = load_cpu_field(vfp.xregs[rn]);
2855
                            break;
2856
                        case ARM_VFP_FPEXC:
2857
                            if (IS_USER(s))
2858
                                return 1;
2859
                            tmp = load_cpu_field(vfp.xregs[rn]);
2860
                            break;
2861
                        case ARM_VFP_FPINST:
2862
                        case ARM_VFP_FPINST2:
2863
                            /* Not present in VFP3.  */
2864
                            if (IS_USER(s)
2865
                                || arm_feature(env, ARM_FEATURE_VFP3))
2866
                                return 1;
2867
                            tmp = load_cpu_field(vfp.xregs[rn]);
2868
                            break;
2869
                        case ARM_VFP_FPSCR:
2870
                            if (rd == 15) {
2871
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2872
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2873
                            } else {
2874
                                tmp = new_tmp();
2875
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2876
                            }
2877
                            break;
2878
                        case ARM_VFP_MVFR0:
2879
                        case ARM_VFP_MVFR1:
2880
                            if (IS_USER(s)
2881
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2882
                                return 1;
2883
                            tmp = load_cpu_field(vfp.xregs[rn]);
2884
                            break;
2885
                        default:
2886
                            return 1;
2887
                        }
2888
                    } else {
2889
                        gen_mov_F0_vreg(0, rn);
2890
                        tmp = gen_vfp_mrs();
2891
                    }
2892
                    if (rd == 15) {
2893
                        /* Set the 4 flag bits in the CPSR.  */
2894
                        gen_set_nzcv(tmp);
2895
                        dead_tmp(tmp);
2896
                    } else {
2897
                        store_reg(s, rd, tmp);
2898
                    }
2899
                } else {
2900
                    /* arm->vfp */
2901
                    tmp = load_reg(s, rd);
2902
                    if (insn & (1 << 21)) {
2903
                        rn >>= 1;
2904
                        /* system register */
2905
                        switch (rn) {
2906
                        case ARM_VFP_FPSID:
2907
                        case ARM_VFP_MVFR0:
2908
                        case ARM_VFP_MVFR1:
2909
                            /* Writes are ignored.  */
2910
                            break;
2911
                        case ARM_VFP_FPSCR:
2912
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2913
                            dead_tmp(tmp);
2914
                            gen_lookup_tb(s);
2915
                            break;
2916
                        case ARM_VFP_FPEXC:
2917
                            if (IS_USER(s))
2918
                                return 1;
2919
                            store_cpu_field(tmp, vfp.xregs[rn]);
2920
                            gen_lookup_tb(s);
2921
                            break;
2922
                        case ARM_VFP_FPINST:
2923
                        case ARM_VFP_FPINST2:
2924
                            store_cpu_field(tmp, vfp.xregs[rn]);
2925
                            break;
2926
                        default:
2927
                            return 1;
2928
                        }
2929
                    } else {
2930
                        gen_vfp_msr(tmp);
2931
                        gen_mov_vreg_F0(0, rn);
2932
                    }
2933
                }
2934
            }
2935
        } else {
2936
            /* data processing */
2937
            /* The opcode is in bits 23, 21, 20 and 6.  */
2938
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2939
            if (dp) {
2940
                if (op == 15) {
2941
                    /* rn is opcode */
2942
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2943
                } else {
2944
                    /* rn is register number */
2945
                    VFP_DREG_N(rn, insn);
2946
                }
2947

    
2948
                if (op == 15 && (rn == 15 || rn > 17)) {
2949
                    /* Integer or single precision destination.  */
2950
                    rd = VFP_SREG_D(insn);
2951
                } else {
2952
                    VFP_DREG_D(rd, insn);
2953
                }
2954

    
2955
                if (op == 15 && (rn == 16 || rn == 17)) {
2956
                    /* Integer source.  */
2957
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2958
                } else {
2959
                    VFP_DREG_M(rm, insn);
2960
                }
2961
            } else {
2962
                rn = VFP_SREG_N(insn);
2963
                if (op == 15 && rn == 15) {
2964
                    /* Double precision destination.  */
2965
                    VFP_DREG_D(rd, insn);
2966
                } else {
2967
                    rd = VFP_SREG_D(insn);
2968
                }
2969
                rm = VFP_SREG_M(insn);
2970
            }
2971

    
2972
            veclen = env->vfp.vec_len;
2973
            if (op == 15 && rn > 3)
2974
                veclen = 0;
2975

    
2976
            /* Shut up compiler warnings.  */
2977
            delta_m = 0;
2978
            delta_d = 0;
2979
            bank_mask = 0;
2980

    
2981
            if (veclen > 0) {
2982
                if (dp)
2983
                    bank_mask = 0xc;
2984
                else
2985
                    bank_mask = 0x18;
2986

    
2987
                /* Figure out what type of vector operation this is.  */
2988
                if ((rd & bank_mask) == 0) {
2989
                    /* scalar */
2990
                    veclen = 0;
2991
                } else {
2992
                    if (dp)
2993
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2994
                    else
2995
                        delta_d = env->vfp.vec_stride + 1;
2996

    
2997
                    if ((rm & bank_mask) == 0) {
2998
                        /* mixed scalar/vector */
2999
                        delta_m = 0;
3000
                    } else {
3001
                        /* vector */
3002
                        delta_m = delta_d;
3003
                    }
3004
                }
3005
            }
3006

    
3007
            /* Load the initial operands.  */
3008
            if (op == 15) {
3009
                switch (rn) {
3010
                case 16:
3011
                case 17:
3012
                    /* Integer source */
3013
                    gen_mov_F0_vreg(0, rm);
3014
                    break;
3015
                case 8:
3016
                case 9:
3017
                    /* Compare */
3018
                    gen_mov_F0_vreg(dp, rd);
3019
                    gen_mov_F1_vreg(dp, rm);
3020
                    break;
3021
                case 10:
3022
                case 11:
3023
                    /* Compare with zero */
3024
                    gen_mov_F0_vreg(dp, rd);
3025
                    gen_vfp_F1_ld0(dp);
3026
                    break;
3027
                case 20:
3028
                case 21:
3029
                case 22:
3030
                case 23:
3031
                    /* Source and destination the same.  */
3032
                    gen_mov_F0_vreg(dp, rd);
3033
                    break;
3034
                default:
3035
                    /* One source operand.  */
3036
                    gen_mov_F0_vreg(dp, rm);
3037
                    break;
3038
                }
3039
            } else {
3040
                /* Two source operands.  */
3041
                gen_mov_F0_vreg(dp, rn);
3042
                gen_mov_F1_vreg(dp, rm);
3043
            }
3044

    
3045
            for (;;) {
3046
                /* Perform the calculation.  */
3047
                switch (op) {
3048
                case 0: /* mac: fd + (fn * fm) */
3049
                    gen_vfp_mul(dp);
3050
                    gen_mov_F1_vreg(dp, rd);
3051
                    gen_vfp_add(dp);
3052
                    break;
3053
                case 1: /* nmac: fd - (fn * fm) */
3054
                    gen_vfp_mul(dp);
3055
                    gen_vfp_neg(dp);
3056
                    gen_mov_F1_vreg(dp, rd);
3057
                    gen_vfp_add(dp);
3058
                    break;
3059
                case 2: /* msc: -fd + (fn * fm) */
3060
                    gen_vfp_mul(dp);
3061
                    gen_mov_F1_vreg(dp, rd);
3062
                    gen_vfp_sub(dp);
3063
                    break;
3064
                case 3: /* nmsc: -fd - (fn * fm)  */
3065
                    gen_vfp_mul(dp);
3066
                    gen_mov_F1_vreg(dp, rd);
3067
                    gen_vfp_add(dp);
3068
                    gen_vfp_neg(dp);
3069
                    break;
3070
                case 4: /* mul: fn * fm */
3071
                    gen_vfp_mul(dp);
3072
                    break;
3073
                case 5: /* nmul: -(fn * fm) */
3074
                    gen_vfp_mul(dp);
3075
                    gen_vfp_neg(dp);
3076
                    break;
3077
                case 6: /* add: fn + fm */
3078
                    gen_vfp_add(dp);
3079
                    break;
3080
                case 7: /* sub: fn - fm */
3081
                    gen_vfp_sub(dp);
3082
                    break;
3083
                case 8: /* div: fn / fm */
3084
                    gen_vfp_div(dp);
3085
                    break;
3086
                case 14: /* fconst */
3087
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
3088
                      return 1;
3089

    
3090
                    n = (insn << 12) & 0x80000000;
3091
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
3092
                    if (dp) {
3093
                        if (i & 0x40)
3094
                            i |= 0x3f80;
3095
                        else
3096
                            i |= 0x4000;
3097
                        n |= i << 16;
3098
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3099
                    } else {
3100
                        if (i & 0x40)
3101
                            i |= 0x780;
3102
                        else
3103
                            i |= 0x800;
3104
                        n |= i << 19;
3105
                        tcg_gen_movi_i32(cpu_F0s, n);
3106
                    }
3107
                    break;
3108
                case 15: /* extension space */
3109
                    switch (rn) {
3110
                    case 0: /* cpy */
3111
                        /* no-op */
3112
                        break;
3113
                    case 1: /* abs */
3114
                        gen_vfp_abs(dp);
3115
                        break;
3116
                    case 2: /* neg */
3117
                        gen_vfp_neg(dp);
3118
                        break;
3119
                    case 3: /* sqrt */
3120
                        gen_vfp_sqrt(dp);
3121
                        break;
3122
                    case 8: /* cmp */
3123
                        gen_vfp_cmp(dp);
3124
                        break;
3125
                    case 9: /* cmpe */
3126
                        gen_vfp_cmpe(dp);
3127
                        break;
3128
                    case 10: /* cmpz */
3129
                        gen_vfp_cmp(dp);
3130
                        break;
3131
                    case 11: /* cmpez */
3132
                        gen_vfp_F1_ld0(dp);
3133
                        gen_vfp_cmpe(dp);
3134
                        break;
3135
                    case 15: /* single<->double conversion */
3136
                        if (dp)
3137
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3138
                        else
3139
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3140
                        break;
3141
                    case 16: /* fuito */
3142
                        gen_vfp_uito(dp);
3143
                        break;
3144
                    case 17: /* fsito */
3145
                        gen_vfp_sito(dp);
3146
                        break;
3147
                    case 20: /* fshto */
3148
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3149
                          return 1;
3150
                        gen_vfp_shto(dp, rm);
3151
                        break;
3152
                    case 21: /* fslto */
3153
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3154
                          return 1;
3155
                        gen_vfp_slto(dp, rm);
3156
                        break;
3157
                    case 22: /* fuhto */
3158
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3159
                          return 1;
3160
                        gen_vfp_uhto(dp, rm);
3161
                        break;
3162
                    case 23: /* fulto */
3163
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3164
                          return 1;
3165
                        gen_vfp_ulto(dp, rm);
3166
                        break;
3167
                    case 24: /* ftoui */
3168
                        gen_vfp_toui(dp);
3169
                        break;
3170
                    case 25: /* ftouiz */
3171
                        gen_vfp_touiz(dp);
3172
                        break;
3173
                    case 26: /* ftosi */
3174
                        gen_vfp_tosi(dp);
3175
                        break;
3176
                    case 27: /* ftosiz */
3177
                        gen_vfp_tosiz(dp);
3178
                        break;
3179
                    case 28: /* ftosh */
3180
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3181
                          return 1;
3182
                        gen_vfp_tosh(dp, rm);
3183
                        break;
3184
                    case 29: /* ftosl */
3185
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3186
                          return 1;
3187
                        gen_vfp_tosl(dp, rm);
3188
                        break;
3189
                    case 30: /* ftouh */
3190
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3191
                          return 1;
3192
                        gen_vfp_touh(dp, rm);
3193
                        break;
3194
                    case 31: /* ftoul */
3195
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
3196
                          return 1;
3197
                        gen_vfp_toul(dp, rm);
3198
                        break;
3199
                    default: /* undefined */
3200
                        printf ("rn:%d\n", rn);
3201
                        return 1;
3202
                    }
3203
                    break;
3204
                default: /* undefined */
3205
                    printf ("op:%d\n", op);
3206
                    return 1;
3207
                }
3208

    
3209
                /* Write back the result.  */
3210
                if (op == 15 && (rn >= 8 && rn <= 11))
3211
                    ; /* Comparison, do nothing.  */
3212
                else if (op == 15 && rn > 17)
3213
                    /* Integer result.  */
3214
                    gen_mov_vreg_F0(0, rd);
3215
                else if (op == 15 && rn == 15)
3216
                    /* conversion */
3217
                    gen_mov_vreg_F0(!dp, rd);
3218
                else
3219
                    gen_mov_vreg_F0(dp, rd);
3220

    
3221
                /* break out of the loop if we have finished  */
3222
                if (veclen == 0)
3223
                    break;
3224

    
3225
                if (op == 15 && delta_m == 0) {
3226
                    /* single source one-many */
3227
                    while (veclen--) {
3228
                        rd = ((rd + delta_d) & (bank_mask - 1))
3229
                             | (rd & bank_mask);
3230
                        gen_mov_vreg_F0(dp, rd);
3231
                    }
3232
                    break;
3233
                }
3234
                /* Setup the next operands.  */
3235
                veclen--;
3236
                rd = ((rd + delta_d) & (bank_mask - 1))
3237
                     | (rd & bank_mask);
3238

    
3239
                if (op == 15) {
3240
                    /* One source operand.  */
3241
                    rm = ((rm + delta_m) & (bank_mask - 1))
3242
                         | (rm & bank_mask);
3243
                    gen_mov_F0_vreg(dp, rm);
3244
                } else {
3245
                    /* Two source operands.  */
3246
                    rn = ((rn + delta_d) & (bank_mask - 1))
3247
                         | (rn & bank_mask);
3248
                    gen_mov_F0_vreg(dp, rn);
3249
                    if (delta_m) {
3250
                        rm = ((rm + delta_m) & (bank_mask - 1))
3251
                             | (rm & bank_mask);
3252
                        gen_mov_F1_vreg(dp, rm);
3253
                    }
3254
                }
3255
            }
3256
        }
3257
        break;
3258
    case 0xc:
3259
    case 0xd:
3260
        if (dp && (insn & 0x03e00000) == 0x00400000) {
3261
            /* two-register transfer */
3262
            rn = (insn >> 16) & 0xf;
3263
            rd = (insn >> 12) & 0xf;
3264
            if (dp) {
3265
                VFP_DREG_M(rm, insn);
3266
            } else {
3267
                rm = VFP_SREG_M(insn);
3268
            }
3269

    
3270
            if (insn & ARM_CP_RW_BIT) {
3271
                /* vfp->arm */
3272
                if (dp) {
3273
                    gen_mov_F0_vreg(0, rm * 2);
3274
                    tmp = gen_vfp_mrs();
3275
                    store_reg(s, rd, tmp);
3276
                    gen_mov_F0_vreg(0, rm * 2 + 1);
3277
                    tmp = gen_vfp_mrs();
3278
                    store_reg(s, rn, tmp);
3279
                } else {
3280
                    gen_mov_F0_vreg(0, rm);
3281
                    tmp = gen_vfp_mrs();
3282
                    store_reg(s, rn, tmp);
3283
                    gen_mov_F0_vreg(0, rm + 1);
3284
                    tmp = gen_vfp_mrs();
3285
                    store_reg(s, rd, tmp);
3286
                }
3287
            } else {
3288
                /* arm->vfp */
3289
                if (dp) {
3290
                    tmp = load_reg(s, rd);
3291
                    gen_vfp_msr(tmp);
3292
                    gen_mov_vreg_F0(0, rm * 2);
3293
                    tmp = load_reg(s, rn);
3294
                    gen_vfp_msr(tmp);
3295
                    gen_mov_vreg_F0(0, rm * 2 + 1);
3296
                } else {
3297
                    tmp = load_reg(s, rn);
3298
                    gen_vfp_msr(tmp);
3299
                    gen_mov_vreg_F0(0, rm);
3300
                    tmp = load_reg(s, rd);
3301
                    gen_vfp_msr(tmp);
3302
                    gen_mov_vreg_F0(0, rm + 1);
3303
                }
3304
            }
3305
        } else {
3306
            /* Load/store */
3307
            rn = (insn >> 16) & 0xf;
3308
            if (dp)
3309
                VFP_DREG_D(rd, insn);
3310
            else
3311
                rd = VFP_SREG_D(insn);
3312
            if (s->thumb && rn == 15) {
3313
                gen_op_movl_T1_im(s->pc & ~2);
3314
            } else {
3315
                gen_movl_T1_reg(s, rn);
3316
            }
3317
            if ((insn & 0x01200000) == 0x01000000) {
3318
                /* Single load/store */
3319
                offset = (insn & 0xff) << 2;
3320
                if ((insn & (1 << 23)) == 0)
3321
                    offset = -offset;
3322
                gen_op_addl_T1_im(offset);
3323
                if (insn & (1 << 20)) {
3324
                    gen_vfp_ld(s, dp);
3325
                    gen_mov_vreg_F0(dp, rd);
3326
                } else {
3327
                    gen_mov_F0_vreg(dp, rd);
3328
                    gen_vfp_st(s, dp);
3329
                }
3330
            } else {
3331
                /* load/store multiple */
3332
                if (dp)
3333
                    n = (insn >> 1) & 0x7f;
3334
                else
3335
                    n = insn & 0xff;
3336

    
3337
                if (insn & (1 << 24)) /* pre-decrement */
3338
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3339

    
3340
                if (dp)
3341
                    offset = 8;
3342
                else
3343
                    offset = 4;
3344
                for (i = 0; i < n; i++) {
3345
                    if (insn & ARM_CP_RW_BIT) {
3346
                        /* load */
3347
                        gen_vfp_ld(s, dp);
3348
                        gen_mov_vreg_F0(dp, rd + i);
3349
                    } else {
3350
                        /* store */
3351
                        gen_mov_F0_vreg(dp, rd + i);
3352
                        gen_vfp_st(s, dp);
3353
                    }
3354
                    gen_op_addl_T1_im(offset);
3355
                }
3356
                if (insn & (1 << 21)) {
3357
                    /* writeback */
3358
                    if (insn & (1 << 24))
3359
                        offset = -offset * n;
3360
                    else if (dp && (insn & 1))
3361
                        offset = 4;
3362
                    else
3363
                        offset = 0;
3364

    
3365
                    if (offset != 0)
3366
                        gen_op_addl_T1_im(offset);
3367
                    gen_movl_reg_T1(s, rn);
3368
                }
3369
            }
3370
        }
3371
        break;
3372
    default:
3373
        /* Should never happen.  */
3374
        return 1;
3375
    }
3376
    return 0;
3377
}
3378

    
3379
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3380
{
3381
    TranslationBlock *tb;
3382

    
3383
    tb = s->tb;
3384
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3385
        tcg_gen_goto_tb(n);
3386
        gen_set_pc_im(dest);
3387
        tcg_gen_exit_tb((long)tb + n);
3388
    } else {
3389
        gen_set_pc_im(dest);
3390
        tcg_gen_exit_tb(0);
3391
    }
3392
}
3393

    
3394
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3395
{
3396
    if (__builtin_expect(s->singlestep_enabled, 0)) {
3397
        /* An indirect jump so that we still trigger the debug exception.  */
3398
        if (s->thumb)
3399
            dest |= 1;
3400
        gen_bx_im(s, dest);
3401
    } else {
3402
        gen_goto_tb(s, 0, dest);
3403
        s->is_jmp = DISAS_TB_JUMP;
3404
    }
3405
}
3406

    
3407
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3408
{
3409
    if (x)
3410
        tcg_gen_sari_i32(t0, t0, 16);
3411
    else
3412
        gen_sxth(t0);
3413
    if (y)
3414
        tcg_gen_sari_i32(t1, t1, 16);
3415
    else
3416
        gen_sxth(t1);
3417
    tcg_gen_mul_i32(t0, t0, t1);
3418
}
3419

    
3420
/* Return the mask of PSR bits set by a MSR instruction.  */
3421
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3422
    uint32_t mask;
3423

    
3424
    mask = 0;
3425
    if (flags & (1 << 0))
3426
        mask |= 0xff;
3427
    if (flags & (1 << 1))
3428
        mask |= 0xff00;
3429
    if (flags & (1 << 2))
3430
        mask |= 0xff0000;
3431
    if (flags & (1 << 3))
3432
        mask |= 0xff000000;
3433

    
3434
    /* Mask out undefined bits.  */
3435
    mask &= ~CPSR_RESERVED;
3436
    if (!arm_feature(env, ARM_FEATURE_V6))
3437
        mask &= ~(CPSR_E | CPSR_GE);
3438
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3439
        mask &= ~CPSR_IT;
3440
    /* Mask out execution state bits.  */
3441
    if (!spsr)
3442
        mask &= ~CPSR_EXEC;
3443
    /* Mask out privileged bits.  */
3444
    if (IS_USER(s))
3445
        mask &= CPSR_USER;
3446
    return mask;
3447
}
3448

    
3449
/* Returns nonzero if access to the PSR is not permitted.  */
3450
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3451
{
3452
    TCGv tmp;
3453
    if (spsr) {
3454
        /* ??? This is also undefined in system mode.  */
3455
        if (IS_USER(s))
3456
            return 1;
3457

    
3458
        tmp = load_cpu_field(spsr);
3459
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3460
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3461
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3462
        store_cpu_field(tmp, spsr);
3463
    } else {
3464
        gen_set_cpsr(cpu_T[0], mask);
3465
    }
3466
    gen_lookup_tb(s);
3467
    return 0;
3468
}
3469

    
3470
/* Generate an old-style exception return.  */
3471
static void gen_exception_return(DisasContext *s)
3472
{
3473
    TCGv tmp;
3474
    gen_movl_reg_T0(s, 15);
3475
    tmp = load_cpu_field(spsr);
3476
    gen_set_cpsr(tmp, 0xffffffff);
3477
    dead_tmp(tmp);
3478
    s->is_jmp = DISAS_UPDATE;
3479
}
3480

    
3481
/* Generate a v6 exception return.  Marks both values as dead.  */
3482
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3483
{
3484
    gen_set_cpsr(cpsr, 0xffffffff);
3485
    dead_tmp(cpsr);
3486
    store_reg(s, 15, pc);
3487
    s->is_jmp = DISAS_UPDATE;
3488
}
3489

    
3490
static inline void
3491
gen_set_condexec (DisasContext *s)
3492
{
3493
    if (s->condexec_mask) {
3494
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3495
        TCGv tmp = new_tmp();
3496
        tcg_gen_movi_i32(tmp, val);
3497
        store_cpu_field(tmp, condexec_bits);
3498
    }
3499
}
3500

    
3501
static void gen_nop_hint(DisasContext *s, int val)
3502
{
3503
    switch (val) {
3504
    case 3: /* wfi */
3505
        gen_set_pc_im(s->pc);
3506
        s->is_jmp = DISAS_WFI;
3507
        break;
3508
    case 2: /* wfe */
3509
    case 4: /* sev */
3510
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3511
    default: /* nop */
3512
        break;
3513
    }
3514
}
3515

    
3516
/* These macros help make the code more readable when migrating from the
3517
   old dyngen helpers.  They should probably be removed when
3518
   T0/T1 are removed.  */
3519
#define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3520
#define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3521

    
3522
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3523

    
3524
static inline int gen_neon_add(int size)
3525
{
3526
    switch (size) {
3527
    case 0: gen_helper_neon_add_u8(CPU_T001); break;
3528
    case 1: gen_helper_neon_add_u16(CPU_T001); break;
3529
    case 2: gen_op_addl_T0_T1(); break;
3530
    default: return 1;
3531
    }
3532
    return 0;
3533
}
3534

    
3535
static inline void gen_neon_rsb(int size)
3536
{
3537
    switch (size) {
3538
    case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3539
    case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3540
    case 2: gen_op_rsbl_T0_T1(); break;
3541
    default: return;
3542
    }
3543
}
3544

    
3545
/* 32-bit pairwise ops end up the same as the elementwise versions.  */
3546
#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
3547
#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
3548
#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
3549
#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
3550

    
3551
/* FIXME: This is wrong.  They set the wrong overflow bit.  */
3552
#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3553
#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3554
#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3555
#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3556

    
3557
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3558
    switch ((size << 1) | u) { \
3559
    case 0: \
3560
        gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3561
        break; \
3562
    case 1: \
3563
        gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3564
        break; \
3565
    case 2: \
3566
        gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3567
        break; \
3568
    case 3: \
3569
        gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3570
        break; \
3571
    case 4: \
3572
        gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3573
        break; \
3574
    case 5: \
3575
        gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3576
        break; \
3577
    default: return 1; \
3578
    }} while (0)
3579

    
3580
#define GEN_NEON_INTEGER_OP(name) do { \
3581
    switch ((size << 1) | u) { \
3582
    case 0: \
3583
        gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3584
        break; \
3585
    case 1: \
3586
        gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3587
        break; \
3588
    case 2: \
3589
        gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3590
        break; \
3591
    case 3: \
3592
        gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3593
        break; \
3594
    case 4: \
3595
        gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3596
        break; \
3597
    case 5: \
3598
        gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3599
        break; \
3600
    default: return 1; \
3601
    }} while (0)
3602

    
3603
static inline void
3604
gen_neon_movl_scratch_T0(int scratch)
3605
{
3606
  uint32_t offset;
3607

    
3608
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3609
  tcg_gen_st_i32(cpu_T[0], cpu_env, offset);
3610
}
3611

    
3612
static inline void
3613
gen_neon_movl_scratch_T1(int scratch)
3614
{
3615
  uint32_t offset;
3616

    
3617
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3618
  tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3619
}
3620

    
3621
static inline void
3622
gen_neon_movl_T0_scratch(int scratch)
3623
{
3624
  uint32_t offset;
3625

    
3626
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3627
  tcg_gen_ld_i32(cpu_T[0], cpu_env, offset);
3628
}
3629

    
3630
static inline void
3631
gen_neon_movl_T1_scratch(int scratch)
3632
{
3633
  uint32_t offset;
3634

    
3635
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3636
  tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3637
}
3638

    
3639
static inline void gen_neon_get_scalar(int size, int reg)
3640
{
3641
    if (size == 1) {
3642
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3643
    } else {
3644
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3645
        if (reg & 1)
3646
            gen_neon_dup_low16(cpu_T[0]);
3647
        else
3648
            gen_neon_dup_high16(cpu_T[0]);
3649
    }
3650
}
3651

    
3652
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3653
{
3654
    int n;
3655

    
3656
    for (n = 0; n < q + 1; n += 2) {
3657
        NEON_GET_REG(T0, reg, n);
3658
        NEON_GET_REG(T0, reg, n + n);
3659
        switch (size) {
3660
        case 0: gen_helper_neon_unzip_u8(); break;
3661
        case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same.  */
3662
        case 2: /* no-op */; break;
3663
        default: abort();
3664
        }
3665
        gen_neon_movl_scratch_T0(tmp + n);
3666
        gen_neon_movl_scratch_T1(tmp + n + 1);
3667
    }
3668
}
3669

    
3670
static struct {
3671
    int nregs;
3672
    int interleave;
3673
    int spacing;
3674
} neon_ls_element_type[11] = {
3675
    {4, 4, 1},
3676
    {4, 4, 2},
3677
    {4, 1, 1},
3678
    {4, 2, 1},
3679
    {3, 3, 1},
3680
    {3, 3, 2},
3681
    {3, 1, 1},
3682
    {1, 1, 1},
3683
    {2, 2, 1},
3684
    {2, 2, 2},
3685
    {2, 1, 1}
3686
};
3687

    
3688
/* Translate a NEON load/store element instruction.  Return nonzero if the
3689
   instruction is invalid.  */
3690
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3691
{
3692
    int rd, rn, rm;
3693
    int op;
3694
    int nregs;
3695
    int interleave;
3696
    int stride;
3697
    int size;
3698
    int reg;
3699
    int pass;
3700
    int load;
3701
    int shift;
3702
    int n;
3703
    TCGv tmp;
3704
    TCGv tmp2;
3705

    
3706
    if (!vfp_enabled(env))
3707
      return 1;
3708
    VFP_DREG_D(rd, insn);
3709
    rn = (insn >> 16) & 0xf;
3710
    rm = insn & 0xf;
3711
    load = (insn & (1 << 21)) != 0;
3712
    if ((insn & (1 << 23)) == 0) {
3713
        /* Load store all elements.  */
3714
        op = (insn >> 8) & 0xf;
3715
        size = (insn >> 6) & 3;
3716
        if (op > 10 || size == 3)
3717
            return 1;
3718
        nregs = neon_ls_element_type[op].nregs;
3719
        interleave = neon_ls_element_type[op].interleave;
3720
        gen_movl_T1_reg(s, rn);
3721
        stride = (1 << size) * interleave;
3722
        for (reg = 0; reg < nregs; reg++) {
3723
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3724
                gen_movl_T1_reg(s, rn);
3725
                gen_op_addl_T1_im((1 << size) * reg);
3726
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3727
                gen_movl_T1_reg(s, rn);
3728
                gen_op_addl_T1_im(1 << size);
3729
            }
3730
            for (pass = 0; pass < 2; pass++) {
3731
                if (size == 2) {
3732
                    if (load) {
3733
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3734
                        neon_store_reg(rd, pass, tmp);
3735
                    } else {
3736
                        tmp = neon_load_reg(rd, pass);
3737
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3738
                    }
3739
                    gen_op_addl_T1_im(stride);
3740
                } else if (size == 1) {
3741
                    if (load) {
3742
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3743
                        gen_op_addl_T1_im(stride);
3744
                        tmp2 = gen_ld16u(cpu_T[1], IS_USER(s));
3745
                        gen_op_addl_T1_im(stride);
3746
                        gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3747
                        dead_tmp(tmp2);
3748
                        neon_store_reg(rd, pass, tmp);
3749
                    } else {
3750
                        tmp = neon_load_reg(rd, pass);
3751
                        tmp2 = new_tmp();
3752
                        tcg_gen_shri_i32(tmp2, tmp, 16);
3753
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3754
                        gen_op_addl_T1_im(stride);
3755
                        gen_st16(tmp2, cpu_T[1], IS_USER(s));
3756
                        gen_op_addl_T1_im(stride);
3757
                    }
3758
                } else /* size == 0 */ {
3759
                    if (load) {
3760
                        TCGV_UNUSED(tmp2);
3761
                        for (n = 0; n < 4; n++) {
3762
                            tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3763
                            gen_op_addl_T1_im(stride);
3764
                            if (n == 0) {
3765
                                tmp2 = tmp;
3766
                            } else {
3767
                                gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3768
                                dead_tmp(tmp);
3769
                            }
3770
                        }
3771
                        neon_store_reg(rd, pass, tmp2);
3772
                    } else {
3773
                        tmp2 = neon_load_reg(rd, pass);
3774
                        for (n = 0; n < 4; n++) {
3775
                            tmp = new_tmp();
3776
                            if (n == 0) {
3777
                                tcg_gen_mov_i32(tmp, tmp2);
3778
                            } else {
3779
                                tcg_gen_shri_i32(tmp, tmp2, n * 8);
3780
                            }
3781
                            gen_st8(tmp, cpu_T[1], IS_USER(s));
3782
                            gen_op_addl_T1_im(stride);
3783
                        }
3784
                        dead_tmp(tmp2);
3785
                    }
3786
                }
3787
            }
3788
            rd += neon_ls_element_type[op].spacing;
3789
        }
3790
        stride = nregs * 8;
3791
    } else {
3792
        size = (insn >> 10) & 3;
3793
        if (size == 3) {
3794
            /* Load single element to all lanes.  */
3795
            if (!load)
3796
                return 1;
3797
            size = (insn >> 6) & 3;
3798
            nregs = ((insn >> 8) & 3) + 1;
3799
            stride = (insn & (1 << 5)) ? 2 : 1;
3800
            gen_movl_T1_reg(s, rn);
3801
            for (reg = 0; reg < nregs; reg++) {
3802
                switch (size) {
3803
                case 0:
3804
                    tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3805
                    gen_neon_dup_u8(tmp, 0);
3806
                    break;
3807
                case 1:
3808
                    tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3809
                    gen_neon_dup_low16(tmp);
3810
                    break;
3811
                case 2:
3812
                    tmp = gen_ld32(cpu_T[0], IS_USER(s));
3813
                    break;
3814
                case 3:
3815
                    return 1;
3816
                default: /* Avoid compiler warnings.  */
3817
                    abort();
3818
                }
3819
                gen_op_addl_T1_im(1 << size);
3820
                tmp2 = new_tmp();
3821
                tcg_gen_mov_i32(tmp2, tmp);
3822
                neon_store_reg(rd, 0, tmp2);
3823
                neon_store_reg(rd, 0, tmp);
3824
                rd += stride;
3825
            }
3826
            stride = (1 << size) * nregs;
3827
        } else {
3828
            /* Single element.  */
3829
            pass = (insn >> 7) & 1;
3830
            switch (size) {
3831
            case 0:
3832
                shift = ((insn >> 5) & 3) * 8;
3833
                stride = 1;
3834
                break;
3835
            case 1:
3836
                shift = ((insn >> 6) & 1) * 16;
3837
                stride = (insn & (1 << 5)) ? 2 : 1;
3838
                break;
3839
            case 2:
3840
                shift = 0;
3841
                stride = (insn & (1 << 6)) ? 2 : 1;
3842
                break;
3843
            default:
3844
                abort();
3845
            }
3846
            nregs = ((insn >> 8) & 3) + 1;
3847
            gen_movl_T1_reg(s, rn);
3848
            for (reg = 0; reg < nregs; reg++) {
3849
                if (load) {
3850
                    switch (size) {
3851
                    case 0:
3852
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3853
                        break;
3854
                    case 1:
3855
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3856
                        break;
3857
                    case 2:
3858
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3859
                        break;
3860
                    default: /* Avoid compiler warnings.  */
3861
                        abort();
3862
                    }
3863
                    if (size != 2) {
3864
                        tmp2 = neon_load_reg(rd, pass);
3865
                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3866
                        dead_tmp(tmp2);
3867
                    }
3868
                    neon_store_reg(rd, pass, tmp);
3869
                } else { /* Store */
3870
                    tmp = neon_load_reg(rd, pass);
3871
                    if (shift)
3872
                        tcg_gen_shri_i32(tmp, tmp, shift);
3873
                    switch (size) {
3874
                    case 0:
3875
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
3876
                        break;
3877
                    case 1:
3878
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3879
                        break;
3880
                    case 2:
3881
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3882
                        break;
3883
                    }
3884
                }
3885
                rd += stride;
3886
                gen_op_addl_T1_im(1 << size);
3887
            }
3888
            stride = nregs * (1 << size);
3889
        }
3890
    }
3891
    if (rm != 15) {
3892
        TCGv base;
3893

    
3894
        base = load_reg(s, rn);
3895
        if (rm == 13) {
3896
            tcg_gen_addi_i32(base, base, stride);
3897
        } else {
3898
            TCGv index;
3899
            index = load_reg(s, rm);
3900
            tcg_gen_add_i32(base, base, index);
3901
            dead_tmp(index);
3902
        }
3903
        store_reg(s, rn, base);
3904
    }
3905
    return 0;
3906
}
3907

    
3908
/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
3909
static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3910
{
3911
    tcg_gen_and_i32(t, t, c);
3912
    tcg_gen_bic_i32(f, f, c);
3913
    tcg_gen_or_i32(dest, t, f);
3914
}
3915

    
3916
static inline void gen_neon_narrow(int size, TCGv dest, TCGv src)
3917
{
3918
    switch (size) {
3919
    case 0: gen_helper_neon_narrow_u8(dest, src); break;
3920
    case 1: gen_helper_neon_narrow_u16(dest, src); break;
3921
    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3922
    default: abort();
3923
    }
3924
}
3925

    
3926
static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv src)
3927
{
3928
    switch (size) {
3929
    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3930
    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3931
    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3932
    default: abort();
3933
    }
3934
}
3935

    
3936
static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv src)
3937
{
3938
    switch (size) {
3939
    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3940
    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3941
    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3942
    default: abort();
3943
    }
3944
}
3945

    
3946
static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3947
                                         int q, int u)
3948
{
3949
    if (q) {
3950
        if (u) {
3951
            switch (size) {
3952
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3953
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3954
            default: abort();
3955
            }
3956
        } else {
3957
            switch (size) {
3958
            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3959
            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3960
            default: abort();
3961
            }
3962
        }
3963
    } else {
3964
        if (u) {
3965
            switch (size) {
3966
            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3967
            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3968
            default: abort();
3969
            }
3970
        } else {
3971
            switch (size) {
3972
            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3973
            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3974
            default: abort();
3975
            }
3976
        }
3977
    }
3978
}
3979

    
3980
static inline void gen_neon_widen(TCGv dest, TCGv src, int size, int u)
3981
{
3982
    if (u) {
3983
        switch (size) {
3984
        case 0: gen_helper_neon_widen_u8(dest, src); break;
3985
        case 1: gen_helper_neon_widen_u16(dest, src); break;
3986
        case 2: tcg_gen_extu_i32_i64(dest, src); break;
3987
        default: abort();
3988
        }
3989
    } else {
3990
        switch (size) {
3991
        case 0: gen_helper_neon_widen_s8(dest, src); break;
3992
        case 1: gen_helper_neon_widen_s16(dest, src); break;
3993
        case 2: tcg_gen_ext_i32_i64(dest, src); break;
3994
        default: abort();
3995
        }
3996
    }
3997
    dead_tmp(src);
3998
}
3999

    
4000
static inline void gen_neon_addl(int size)
4001
{
4002
    switch (size) {
4003
    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4004
    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4005
    case 2: tcg_gen_add_i64(CPU_V001); break;
4006
    default: abort();
4007
    }
4008
}
4009

    
4010
static inline void gen_neon_subl(int size)
4011
{
4012
    switch (size) {
4013
    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4014
    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4015
    case 2: tcg_gen_sub_i64(CPU_V001); break;
4016
    default: abort();
4017
    }
4018
}
4019

    
4020
static inline void gen_neon_negl(TCGv var, int size)
4021
{
4022
    switch (size) {
4023
    case 0: gen_helper_neon_negl_u16(var, var); break;
4024
    case 1: gen_helper_neon_negl_u32(var, var); break;
4025
    case 2: gen_helper_neon_negl_u64(var, var); break;
4026
    default: abort();
4027
    }
4028
}
4029

    
4030
static inline void gen_neon_addl_saturate(TCGv op0, TCGv op1, int size)
4031
{
4032
    switch (size) {
4033
    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4034
    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4035
    default: abort();
4036
    }
4037
}
4038

    
4039
static inline void gen_neon_mull(TCGv dest, TCGv a, TCGv b, int size, int u)
4040
{
4041
    TCGv tmp;
4042

    
4043
    switch ((size << 1) | u) {
4044
    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4045
    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4046
    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4047
    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4048
    case 4:
4049
        tmp = gen_muls_i64_i32(a, b);
4050
        tcg_gen_mov_i64(dest, tmp);
4051
        break;
4052
    case 5:
4053
        tmp = gen_mulu_i64_i32(a, b);
4054
        tcg_gen_mov_i64(dest, tmp);
4055
        break;
4056
    default: abort();
4057
    }
4058
    if (size < 2) {
4059
        dead_tmp(b);
4060
        dead_tmp(a);
4061
    }
4062
}
4063

    
4064
/* Translate a NEON data processing instruction.  Return nonzero if the
4065
   instruction is invalid.
4066
   We process data in a mixture of 32-bit and 64-bit chunks.
4067
   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
4068

    
4069
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4070
{
4071
    int op;
4072
    int q;
4073
    int rd, rn, rm;
4074
    int size;
4075
    int shift;
4076
    int pass;
4077
    int count;
4078
    int pairwise;
4079
    int u;
4080
    int n;
4081
    uint32_t imm;
4082
    TCGv tmp;
4083
    TCGv tmp2;
4084
    TCGv tmp3;
4085

    
4086
    if (!vfp_enabled(env))
4087
      return 1;
4088
    q = (insn & (1 << 6)) != 0;
4089
    u = (insn >> 24) & 1;
4090
    VFP_DREG_D(rd, insn);
4091
    VFP_DREG_N(rn, insn);
4092
    VFP_DREG_M(rm, insn);
4093
    size = (insn >> 20) & 3;
4094
    if ((insn & (1 << 23)) == 0) {
4095
        /* Three register same length.  */
4096
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4097
        if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4098
                          || op == 10 || op  == 11 || op == 16)) {
4099
            /* 64-bit element instructions.  */
4100
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
4101
                neon_load_reg64(cpu_V0, rn + pass);
4102
                neon_load_reg64(cpu_V1, rm + pass);
4103
                switch (op) {
4104
                case 1: /* VQADD */
4105
                    if (u) {
4106
                        gen_helper_neon_add_saturate_u64(CPU_V001);
4107
                    } else {
4108
                        gen_helper_neon_add_saturate_s64(CPU_V001);
4109
                    }
4110
                    break;
4111
                case 5: /* VQSUB */
4112
                    if (u) {
4113
                        gen_helper_neon_sub_saturate_u64(CPU_V001);
4114
                    } else {
4115
                        gen_helper_neon_sub_saturate_s64(CPU_V001);
4116
                    }
4117
                    break;
4118
                case 8: /* VSHL */
4119
                    if (u) {
4120
                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4121
                    } else {
4122
                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4123
                    }
4124
                    break;
4125
                case 9: /* VQSHL */
4126
                    if (u) {
4127
                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4128
                                                 cpu_V0, cpu_V0);
4129
                    } else {
4130
                        gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4131
                                                 cpu_V1, cpu_V0);
4132
                    }
4133
                    break;
4134
                case 10: /* VRSHL */
4135
                    if (u) {
4136
                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4137
                    } else {
4138
                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4139
                    }
4140
                    break;
4141
                case 11: /* VQRSHL */
4142
                    if (u) {
4143
                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4144
                                                  cpu_V1, cpu_V0);
4145
                    } else {
4146
                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4147
                                                  cpu_V1, cpu_V0);
4148
                    }
4149
                    break;
4150
                case 16:
4151
                    if (u) {
4152
                        tcg_gen_sub_i64(CPU_V001);
4153
                    } else {
4154
                        tcg_gen_add_i64(CPU_V001);
4155
                    }
4156
                    break;
4157
                default:
4158
                    abort();
4159
                }
4160
                neon_store_reg64(cpu_V0, rd + pass);
4161
            }
4162
            return 0;
4163
        }
4164
        switch (op) {
4165
        case 8: /* VSHL */
4166
        case 9: /* VQSHL */
4167
        case 10: /* VRSHL */
4168
        case 11: /* VQRSHL */
4169
            {
4170
                int rtmp;
4171
                /* Shift instruction operands are reversed.  */
4172
                rtmp = rn;
4173
                rn = rm;
4174
                rm = rtmp;
4175
                pairwise = 0;
4176
            }
4177
            break;
4178
        case 20: /* VPMAX */
4179
        case 21: /* VPMIN */
4180
        case 23: /* VPADD */
4181
            pairwise = 1;
4182
            break;
4183
        case 26: /* VPADD (float) */
4184
            pairwise = (u && size < 2);
4185
            break;
4186
        case 30: /* VPMIN/VPMAX (float) */
4187
            pairwise = u;
4188
            break;
4189
        default:
4190
            pairwise = 0;
4191
            break;
4192
        }
4193
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
4194

    
4195
        if (pairwise) {
4196
            /* Pairwise.  */
4197
            if (q)
4198
                n = (pass & 1) * 2;
4199
            else
4200
                n = 0;
4201
            if (pass < q + 1) {
4202
                NEON_GET_REG(T0, rn, n);
4203
                NEON_GET_REG(T1, rn, n + 1);
4204
            } else {
4205
                NEON_GET_REG(T0, rm, n);
4206
                NEON_GET_REG(T1, rm, n + 1);
4207
            }
4208
        } else {
4209
            /* Elementwise.  */
4210
            NEON_GET_REG(T0, rn, pass);
4211
            NEON_GET_REG(T1, rm, pass);
4212
        }
4213
        switch (op) {
4214
        case 0: /* VHADD */
4215
            GEN_NEON_INTEGER_OP(hadd);
4216
            break;
4217
        case 1: /* VQADD */
4218
            GEN_NEON_INTEGER_OP_ENV(qadd);
4219
            break;
4220
        case 2: /* VRHADD */
4221
            GEN_NEON_INTEGER_OP(rhadd);
4222
            break;
4223
        case 3: /* Logic ops.  */
4224
            switch ((u << 2) | size) {
4225
            case 0: /* VAND */
4226
                gen_op_andl_T0_T1();
4227
                break;
4228
            case 1: /* BIC */
4229
                gen_op_bicl_T0_T1();
4230
                break;
4231
            case 2: /* VORR */
4232
                gen_op_orl_T0_T1();
4233
                break;
4234
            case 3: /* VORN */
4235
                gen_op_notl_T1();
4236
                gen_op_orl_T0_T1();
4237
                break;
4238
            case 4: /* VEOR */
4239
                gen_op_xorl_T0_T1();
4240
                break;
4241
            case 5: /* VBSL */
4242
                tmp = neon_load_reg(rd, pass);
4243
                gen_neon_bsl(cpu_T[0], cpu_T[0], cpu_T[1], tmp);
4244
                dead_tmp(tmp);
4245
                break;
4246
            case 6: /* VBIT */
4247
                tmp = neon_load_reg(rd, pass);
4248
                gen_neon_bsl(cpu_T[0], cpu_T[0], tmp, cpu_T[1]);
4249
                dead_tmp(tmp);
4250
                break;
4251
            case 7: /* VBIF */
4252
                tmp = neon_load_reg(rd, pass);
4253
                gen_neon_bsl(cpu_T[0], tmp, cpu_T[0], cpu_T[1]);
4254
                dead_tmp(tmp);
4255
                break;
4256
            }
4257
            break;
4258
        case 4: /* VHSUB */
4259
            GEN_NEON_INTEGER_OP(hsub);
4260
            break;
4261
        case 5: /* VQSUB */
4262
            GEN_NEON_INTEGER_OP_ENV(qsub);
4263
            break;
4264
        case 6: /* VCGT */
4265
            GEN_NEON_INTEGER_OP(cgt);
4266
            break;
4267
        case 7: /* VCGE */
4268
            GEN_NEON_INTEGER_OP(cge);
4269
            break;
4270
        case 8: /* VSHL */
4271
            GEN_NEON_INTEGER_OP(shl);
4272
            break;
4273
        case 9: /* VQSHL */
4274
            GEN_NEON_INTEGER_OP_ENV(qshl);
4275
            break;
4276
        case 10: /* VRSHL */
4277
            GEN_NEON_INTEGER_OP(rshl);
4278
            break;
4279
        case 11: /* VQRSHL */
4280
            GEN_NEON_INTEGER_OP_ENV(qrshl);
4281
            break;
4282
        case 12: /* VMAX */
4283
            GEN_NEON_INTEGER_OP(max);
4284
            break;
4285
        case 13: /* VMIN */
4286
            GEN_NEON_INTEGER_OP(min);
4287
            break;
4288
        case 14: /* VABD */
4289
            GEN_NEON_INTEGER_OP(abd);
4290
            break;
4291
        case 15: /* VABA */
4292
            GEN_NEON_INTEGER_OP(abd);
4293
            NEON_GET_REG(T1, rd, pass);
4294
            gen_neon_add(size);
4295
            break;
4296
        case 16:
4297
            if (!u) { /* VADD */
4298
                if (gen_neon_add(size))
4299
                    return 1;
4300
            } else { /* VSUB */
4301
                switch (size) {
4302
                case 0: gen_helper_neon_sub_u8(CPU_T001); break;
4303
                case 1: gen_helper_neon_sub_u16(CPU_T001); break;
4304
                case 2: gen_op_subl_T0_T1(); break;
4305
                default: return 1;
4306
                }
4307
            }
4308
            break;
4309
        case 17:
4310
            if (!u) { /* VTST */
4311
                switch (size) {
4312
                case 0: gen_helper_neon_tst_u8(CPU_T001); break;
4313
                case 1: gen_helper_neon_tst_u16(CPU_T001); break;
4314
                case 2: gen_helper_neon_tst_u32(CPU_T001); break;
4315
                default: return 1;
4316
                }
4317
            } else { /* VCEQ */
4318
                switch (size) {
4319
                case 0: gen_helper_neon_ceq_u8(CPU_T001); break;
4320
                case 1: gen_helper_neon_ceq_u16(CPU_T001); break;
4321
                case 2: gen_helper_neon_ceq_u32(CPU_T001); break;
4322
                default: return 1;
4323
                }
4324
            }
4325
            break;
4326
        case 18: /* Multiply.  */
4327
            switch (size) {
4328
            case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4329
            case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4330
            case 2: gen_op_mul_T0_T1(); break;
4331
            default: return 1;
4332
            }
4333
            NEON_GET_REG(T1, rd, pass);
4334
            if (u) { /* VMLS */
4335
                gen_neon_rsb(size);
4336
            } else { /* VMLA */
4337
                gen_neon_add(size);
4338
            }
4339
            break;
4340
        case 19: /* VMUL */
4341
            if (u) { /* polynomial */
4342
                gen_helper_neon_mul_p8(CPU_T001);
4343
            } else { /* Integer */
4344
                switch (size) {
4345
                case 0: gen_helper_neon_mul_u8(CPU_T001); break;
4346
                case 1: gen_helper_neon_mul_u16(CPU_T001); break;
4347
                case 2: gen_op_mul_T0_T1(); break;
4348
                default: return 1;
4349
                }
4350
            }
4351
            break;
4352
        case 20: /* VPMAX */
4353
            GEN_NEON_INTEGER_OP(pmax);
4354
            break;
4355
        case 21: /* VPMIN */
4356
            GEN_NEON_INTEGER_OP(pmin);
4357
            break;
4358
        case 22: /* Hultiply high.  */
4359
            if (!u) { /* VQDMULH */
4360
                switch (size) {
4361
                case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01); break;
4362
                case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01); break;
4363
                default: return 1;
4364
                }
4365
            } else { /* VQRDHMUL */
4366
                switch (size) {
4367
                case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01); break;
4368
                case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01); break;
4369
                default: return 1;
4370
                }
4371
            }
4372
            break;
4373
        case 23: /* VPADD */
4374
            if (u)
4375
                return 1;
4376
            switch (size) {
4377
            case 0: gen_helper_neon_padd_u8(CPU_T001); break;
4378
            case 1: gen_helper_neon_padd_u16(CPU_T001); break;
4379
            case 2: gen_op_addl_T0_T1(); break;
4380
            default: return 1;
4381
            }
4382
            break;
4383
        case 26: /* Floating point arithnetic.  */
4384
            switch ((u << 2) | size) {
4385
            case 0: /* VADD */
4386
                gen_helper_neon_add_f32(CPU_T001);
4387
                break;
4388
            case 2: /* VSUB */
4389
                gen_helper_neon_sub_f32(CPU_T001);
4390
                break;
4391
            case 4: /* VPADD */
4392
                gen_helper_neon_add_f32(CPU_T001);
4393
                break;
4394
            case 6: /* VABD */
4395
                gen_helper_neon_abd_f32(CPU_T001);
4396
                break;
4397
            default:
4398
                return 1;
4399
            }
4400
            break;
4401
        case 27: /* Float multiply.  */
4402
            gen_helper_neon_mul_f32(CPU_T001);
4403
            if (!u) {
4404
                NEON_GET_REG(T1, rd, pass);
4405
                if (size == 0) {
4406
                    gen_helper_neon_add_f32(CPU_T001);
4407
                } else {
4408
                    gen_helper_neon_sub_f32(cpu_T[0], cpu_T[1], cpu_T[0]);
4409
                }
4410
            }
4411
            break;
4412
        case 28: /* Float compare.  */
4413
            if (!u) {
4414
                gen_helper_neon_ceq_f32(CPU_T001);
4415
            } else {
4416
                if (size == 0)
4417
                    gen_helper_neon_cge_f32(CPU_T001);
4418
                else
4419
                    gen_helper_neon_cgt_f32(CPU_T001);
4420
            }
4421
            break;
4422
        case 29: /* Float compare absolute.  */
4423
            if (!u)
4424
                return 1;
4425
            if (size == 0)
4426
                gen_helper_neon_acge_f32(CPU_T001);
4427
            else
4428
                gen_helper_neon_acgt_f32(CPU_T001);
4429
            break;
4430
        case 30: /* Float min/max.  */
4431
            if (size == 0)
4432
                gen_helper_neon_max_f32(CPU_T001);
4433
            else
4434
                gen_helper_neon_min_f32(CPU_T001);
4435
            break;
4436
        case 31:
4437
            if (size == 0)
4438
                gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4439
            else
4440
                gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4441
            break;
4442
        default:
4443
            abort();
4444
        }
4445
        /* Save the result.  For elementwise operations we can put it
4446
           straight into the destination register.  For pairwise operations
4447
           we have to be careful to avoid clobbering the source operands.  */
4448
        if (pairwise && rd == rm) {
4449
            gen_neon_movl_scratch_T0(pass);
4450
        } else {
4451
            NEON_SET_REG(T0, rd, pass);
4452
        }
4453

    
4454
        } /* for pass */
4455
        if (pairwise && rd == rm) {
4456
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4457
                gen_neon_movl_T0_scratch(pass);
4458
                NEON_SET_REG(T0, rd, pass);
4459
            }
4460
        }
4461
        /* End of 3 register same size operations.  */
4462
    } else if (insn & (1 << 4)) {
4463
        if ((insn & 0x00380080) != 0) {
4464
            /* Two registers and shift.  */
4465
            op = (insn >> 8) & 0xf;
4466
            if (insn & (1 << 7)) {
4467
                /* 64-bit shift.   */
4468
                size = 3;
4469
            } else {
4470
                size = 2;
4471
                while ((insn & (1 << (size + 19))) == 0)
4472
                    size--;
4473
            }
4474
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4475
            /* To avoid excessive dumplication of ops we implement shift
4476
               by immediate using the variable shift operations.  */
4477
            if (op < 8) {
4478
                /* Shift by immediate:
4479
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4480
                /* Right shifts are encoded as N - shift, where N is the
4481
                   element size in bits.  */
4482
                if (op <= 4)
4483
                    shift = shift - (1 << (size + 3));
4484
                if (size == 3) {
4485
                    count = q + 1;
4486
                } else {
4487
                    count = q ? 4: 2;
4488
                }
4489
                switch (size) {
4490
                case 0:
4491
                    imm = (uint8_t) shift;
4492
                    imm |= imm << 8;
4493
                    imm |= imm << 16;
4494
                    break;
4495
                case 1:
4496
                    imm = (uint16_t) shift;
4497
                    imm |= imm << 16;
4498
                    break;
4499
                case 2:
4500
                case 3:
4501
                    imm = shift;
4502
                    break;
4503
                default:
4504
                    abort();
4505
                }
4506

    
4507
                for (pass = 0; pass < count; pass++) {
4508
                    if (size == 3) {
4509
                        neon_load_reg64(cpu_V0, rm + pass);
4510
                        tcg_gen_movi_i64(cpu_V1, imm);
4511
                        switch (op) {
4512
                        case 0:  /* VSHR */
4513
                        case 1:  /* VSRA */
4514
                            if (u)
4515
                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4516
                            else
4517
                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4518
                            break;
4519
                        case 2: /* VRSHR */
4520
                        case 3: /* VRSRA */
4521
                            if (u)
4522
                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4523
                            else
4524
                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4525
                            break;
4526
                        case 4: /* VSRI */
4527
                            if (!u)
4528
                                return 1;
4529
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4530
                            break;
4531
                        case 5: /* VSHL, VSLI */
4532
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4533
                            break;
4534
                        case 6: /* VQSHL */
4535
                            if (u)
4536
                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4537
                            else
4538
                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4539
                            break;
4540
                        case 7: /* VQSHLU */
4541
                            gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4542
                            break;
4543
                        }
4544
                        if (op == 1 || op == 3) {
4545
                            /* Accumulate.  */
4546
                            neon_load_reg64(cpu_V0, rd + pass);
4547
                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4548
                        } else if (op == 4 || (op == 5 && u)) {
4549
                            /* Insert */
4550
                            cpu_abort(env, "VS[LR]I.64 not implemented");
4551
                        }
4552
                        neon_store_reg64(cpu_V0, rd + pass);
4553
                    } else { /* size < 3 */
4554
                        /* Operands in T0 and T1.  */
4555
                        gen_op_movl_T1_im(imm);
4556
                        NEON_GET_REG(T0, rm, pass);
4557
                        switch (op) {
4558
                        case 0:  /* VSHR */
4559
                        case 1:  /* VSRA */
4560
                            GEN_NEON_INTEGER_OP(shl);
4561
                            break;
4562
                        case 2: /* VRSHR */
4563
                        case 3: /* VRSRA */
4564
                            GEN_NEON_INTEGER_OP(rshl);
4565
                            break;
4566
                        case 4: /* VSRI */
4567
                            if (!u)
4568
                                return 1;
4569
                            GEN_NEON_INTEGER_OP(shl);
4570
                            break;
4571
                        case 5: /* VSHL, VSLI */
4572
                            switch (size) {
4573
                            case 0: gen_helper_neon_shl_u8(CPU_T001); break;
4574
                            case 1: gen_helper_neon_shl_u16(CPU_T001); break;
4575
                            case 2: gen_helper_neon_shl_u32(CPU_T001); break;
4576
                            default: return 1;
4577
                            }
4578
                            break;
4579
                        case 6: /* VQSHL */
4580
                            GEN_NEON_INTEGER_OP_ENV(qshl);
4581
                            break;
4582
                        case 7: /* VQSHLU */
4583
                            switch (size) {
4584
                            case 0: gen_helper_neon_qshl_u8(CPU_T0E01); break;
4585
                            case 1: gen_helper_neon_qshl_u16(CPU_T0E01); break;
4586
                            case 2: gen_helper_neon_qshl_u32(CPU_T0E01); break;
4587
                            default: return 1;
4588
                            }
4589
                            break;
4590
                        }
4591

    
4592
                        if (op == 1 || op == 3) {
4593
                            /* Accumulate.  */
4594
                            NEON_GET_REG(T1, rd, pass);
4595
                            gen_neon_add(size);
4596
                        } else if (op == 4 || (op == 5 && u)) {
4597
                            /* Insert */
4598
                            switch (size) {
4599
                            case 0:
4600
                                if (op == 4)
4601
                                    imm = 0xff >> -shift;
4602
                                else
4603
                                    imm = (uint8_t)(0xff << shift);
4604
                                imm |= imm << 8;
4605
                                imm |= imm << 16;
4606
                                break;
4607
                            case 1:
4608
                                if (op == 4)
4609
                                    imm = 0xffff >> -shift;
4610
                                else
4611
                                    imm = (uint16_t)(0xffff << shift);
4612
                                imm |= imm << 16;
4613
                                break;
4614
                            case 2:
4615
                                if (op == 4)
4616
                                    imm = 0xffffffffu >> -shift;
4617
                                else
4618
                                    imm = 0xffffffffu << shift;
4619
                                break;
4620
                            default:
4621
                                abort();
4622
                            }
4623
                            tmp = neon_load_reg(rd, pass);
4624
                            tcg_gen_andi_i32(cpu_T[0], cpu_T[0], imm);
4625
                            tcg_gen_andi_i32(tmp, tmp, ~imm);
4626
                            tcg_gen_or_i32(cpu_T[0], cpu_T[0], tmp);
4627
                        }
4628
                        NEON_SET_REG(T0, rd, pass);
4629
                    }
4630
                } /* for pass */
4631
            } else if (op < 10) {
4632
                /* Shift by immediate and narrow:
4633
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4634
                shift = shift - (1 << (size + 3));
4635
                size++;
4636
                switch (size) {
4637
                case 1:
4638
                    imm = (uint16_t)shift;
4639
                    imm |= imm << 16;
4640
                    tmp2 = tcg_const_i32(imm);
4641
                    break;
4642
                case 2:
4643
                    imm = (uint32_t)shift;
4644
                    tmp2 = tcg_const_i32(imm);
4645
                case 3:
4646
                    tmp2 = tcg_const_i64(shift);
4647
                    break;
4648
                default:
4649
                    abort();
4650
                }
4651

    
4652
                for (pass = 0; pass < 2; pass++) {
4653
                    if (size == 3) {
4654
                        neon_load_reg64(cpu_V0, rm + pass);
4655
                        if (q) {
4656
                          if (u)
4657
                            gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp2);
4658
                          else
4659
                            gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp2);
4660
                        } else {
4661
                          if (u)
4662
                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp2);
4663
                          else
4664
                            gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp2);
4665
                        }
4666
                    } else {
4667
                        tmp = neon_load_reg(rm + pass, 0);
4668
                        gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4669
                        tcg_gen_extu_i32_i64(cpu_V0, tmp);
4670
                        dead_tmp(tmp);
4671
                        tmp = neon_load_reg(rm + pass, 1);
4672
                        gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4673
                        tcg_gen_extu_i32_i64(cpu_V1, tmp);
4674
                        dead_tmp(tmp);
4675
                        tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
4676
                        tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4677
                    }
4678
                    tmp = new_tmp();
4679
                    if (op == 8 && !u) {
4680
                        gen_neon_narrow(size - 1, tmp, cpu_V0);
4681
                    } else {
4682
                        if (op == 8)
4683
                            gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4684
                        else
4685
                            gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4686
                    }
4687
                    if (pass == 0) {
4688
                        tmp2 = tmp;
4689
                    } else {
4690
                        neon_store_reg(rd, 0, tmp2);
4691
                        neon_store_reg(rd, 1, tmp);
4692
                    }
4693
                } /* for pass */
4694
            } else if (op == 10) {
4695
                /* VSHLL */
4696
                if (q || size == 3)
4697
                    return 1;
4698
                tmp = neon_load_reg(rm, 0);
4699
                tmp2 = neon_load_reg(rm, 1);
4700
                for (pass = 0; pass < 2; pass++) {
4701
                    if (pass == 1)
4702
                        tmp = tmp2;
4703

    
4704
                    gen_neon_widen(cpu_V0, tmp, size, u);
4705

    
4706
                    if (shift != 0) {
4707
                        /* The shift is less than the width of the source
4708
                           type, so we can just shift the whole register.  */
4709
                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4710
                        if (size < 2 || !u) {
4711
                            uint64_t imm64;
4712
                            if (size == 0) {
4713
                                imm = (0xffu >> (8 - shift));
4714
                                imm |= imm << 16;
4715
                            } else {
4716
                                imm = 0xffff >> (16 - shift);
4717
                            }
4718
                            imm64 = imm | (((uint64_t)imm) << 32);
4719
                            tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4720
                        }
4721
                    }
4722
                    neon_store_reg64(cpu_V0, rd + pass);
4723
                }
4724
            } else if (op == 15 || op == 16) {
4725
                /* VCVT fixed-point.  */
4726
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4727
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4728
                    if (op & 1) {
4729
                        if (u)
4730
                            gen_vfp_ulto(0, shift);
4731
                        else
4732
                            gen_vfp_slto(0, shift);
4733
                    } else {
4734
                        if (u)
4735
                            gen_vfp_toul(0, shift);
4736
                        else
4737
                            gen_vfp_tosl(0, shift);
4738
                    }
4739
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4740
                }
4741
            } else {
4742
                return 1;
4743
            }
4744
        } else { /* (insn & 0x00380080) == 0 */
4745
            int invert;
4746

    
4747
            op = (insn >> 8) & 0xf;
4748
            /* One register and immediate.  */
4749
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4750
            invert = (insn & (1 << 5)) != 0;
4751
            switch (op) {
4752
            case 0: case 1:
4753
                /* no-op */
4754
                break;
4755
            case 2: case 3:
4756
                imm <<= 8;
4757
                break;
4758
            case 4: case 5:
4759
                imm <<= 16;
4760
                break;
4761
            case 6: case 7:
4762
                imm <<= 24;
4763
                break;
4764
            case 8: case 9:
4765
                imm |= imm << 16;
4766
                break;