Statistics
| Branch: | Revision:

root / target-arm / translate.c @ e160c51c

History | View | Annotate | Download (256.3 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

    
32
#define ENABLE_ARCH_5J    0
33
#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
34
#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
35
#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
36
#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
37

    
38
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
39

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

    
60
#if defined(CONFIG_USER_ONLY)
61
#define IS_USER(s) 1
62
#else
63
#define IS_USER(s) (s->user)
64
#endif
65

    
66
/* These instructions trap after executing, so defer them until after the
67
   conditional executions state has been updated.  */
68
#define DISAS_WFI 4
69
#define DISAS_SWI 5
70

    
71
#ifdef USE_DIRECT_JUMP
72
#define TBPARAM(x)
73
#else
74
#define TBPARAM(x) (long)(x)
75
#endif
76

    
77
/* XXX: move that elsewhere */
78
static uint16_t *gen_opc_ptr;
79
static uint32_t *gen_opparam_ptr;
80
extern FILE *logfile;
81
extern int loglevel;
82

    
83
enum {
84
#define DEF(s, n, copy_size) INDEX_op_ ## s,
85
#include "opc.h"
86
#undef DEF
87
    NB_OPS,
88
};
89

    
90
#include "gen-op.h"
91

    
92
#define PAS_OP(pfx) {  \
93
    gen_op_ ## pfx ## add16_T0_T1, \
94
    gen_op_ ## pfx ## addsubx_T0_T1, \
95
    gen_op_ ## pfx ## subaddx_T0_T1, \
96
    gen_op_ ## pfx ## sub16_T0_T1, \
97
    gen_op_ ## pfx ## add8_T0_T1, \
98
    NULL, \
99
    NULL, \
100
    gen_op_ ## pfx ## sub8_T0_T1 }
101

    
102
static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
103
    {},
104
    PAS_OP(s),
105
    PAS_OP(q),
106
    PAS_OP(sh),
107
    {},
108
    PAS_OP(u),
109
    PAS_OP(uq),
110
    PAS_OP(uh),
111
};
112
#undef PAS_OP
113

    
114
/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings.  */
115
#define PAS_OP(pfx) {  \
116
    gen_op_ ## pfx ## add8_T0_T1, \
117
    gen_op_ ## pfx ## add16_T0_T1, \
118
    gen_op_ ## pfx ## addsubx_T0_T1, \
119
    NULL, \
120
    gen_op_ ## pfx ## sub8_T0_T1, \
121
    gen_op_ ## pfx ## sub16_T0_T1, \
122
    gen_op_ ## pfx ## subaddx_T0_T1, \
123
    NULL }
124

    
125
static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
126
    PAS_OP(s),
127
    PAS_OP(q),
128
    PAS_OP(sh),
129
    {},
130
    PAS_OP(u),
131
    PAS_OP(uq),
132
    PAS_OP(uh),
133
    {}
134
};
135
#undef PAS_OP
136

    
137
static GenOpFunc1 *gen_test_cc[14] = {
138
    gen_op_test_eq,
139
    gen_op_test_ne,
140
    gen_op_test_cs,
141
    gen_op_test_cc,
142
    gen_op_test_mi,
143
    gen_op_test_pl,
144
    gen_op_test_vs,
145
    gen_op_test_vc,
146
    gen_op_test_hi,
147
    gen_op_test_ls,
148
    gen_op_test_ge,
149
    gen_op_test_lt,
150
    gen_op_test_gt,
151
    gen_op_test_le,
152
};
153

    
154
const uint8_t table_logic_cc[16] = {
155
    1, /* and */
156
    1, /* xor */
157
    0, /* sub */
158
    0, /* rsb */
159
    0, /* add */
160
    0, /* adc */
161
    0, /* sbc */
162
    0, /* rsc */
163
    1, /* andl */
164
    1, /* xorl */
165
    0, /* cmp */
166
    0, /* cmn */
167
    1, /* orr */
168
    1, /* mov */
169
    1, /* bic */
170
    1, /* mvn */
171
};
172

    
173
static GenOpFunc1 *gen_shift_T1_im[4] = {
174
    gen_op_shll_T1_im,
175
    gen_op_shrl_T1_im,
176
    gen_op_sarl_T1_im,
177
    gen_op_rorl_T1_im,
178
};
179

    
180
static GenOpFunc *gen_shift_T1_0[4] = {
181
    NULL,
182
    gen_op_shrl_T1_0,
183
    gen_op_sarl_T1_0,
184
    gen_op_rrxl_T1,
185
};
186

    
187
static GenOpFunc1 *gen_shift_T2_im[4] = {
188
    gen_op_shll_T2_im,
189
    gen_op_shrl_T2_im,
190
    gen_op_sarl_T2_im,
191
    gen_op_rorl_T2_im,
192
};
193

    
194
static GenOpFunc *gen_shift_T2_0[4] = {
195
    NULL,
196
    gen_op_shrl_T2_0,
197
    gen_op_sarl_T2_0,
198
    gen_op_rrxl_T2,
199
};
200

    
201
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
202
    gen_op_shll_T1_im_cc,
203
    gen_op_shrl_T1_im_cc,
204
    gen_op_sarl_T1_im_cc,
205
    gen_op_rorl_T1_im_cc,
206
};
207

    
208
static GenOpFunc *gen_shift_T1_0_cc[4] = {
209
    NULL,
210
    gen_op_shrl_T1_0_cc,
211
    gen_op_sarl_T1_0_cc,
212
    gen_op_rrxl_T1_cc,
213
};
214

    
215
static GenOpFunc *gen_shift_T1_T0[4] = {
216
    gen_op_shll_T1_T0,
217
    gen_op_shrl_T1_T0,
218
    gen_op_sarl_T1_T0,
219
    gen_op_rorl_T1_T0,
220
};
221

    
222
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
223
    gen_op_shll_T1_T0_cc,
224
    gen_op_shrl_T1_T0_cc,
225
    gen_op_sarl_T1_T0_cc,
226
    gen_op_rorl_T1_T0_cc,
227
};
228

    
229
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
230
    {
231
        gen_op_movl_T0_r0,
232
        gen_op_movl_T0_r1,
233
        gen_op_movl_T0_r2,
234
        gen_op_movl_T0_r3,
235
        gen_op_movl_T0_r4,
236
        gen_op_movl_T0_r5,
237
        gen_op_movl_T0_r6,
238
        gen_op_movl_T0_r7,
239
        gen_op_movl_T0_r8,
240
        gen_op_movl_T0_r9,
241
        gen_op_movl_T0_r10,
242
        gen_op_movl_T0_r11,
243
        gen_op_movl_T0_r12,
244
        gen_op_movl_T0_r13,
245
        gen_op_movl_T0_r14,
246
        gen_op_movl_T0_r15,
247
    },
248
    {
249
        gen_op_movl_T1_r0,
250
        gen_op_movl_T1_r1,
251
        gen_op_movl_T1_r2,
252
        gen_op_movl_T1_r3,
253
        gen_op_movl_T1_r4,
254
        gen_op_movl_T1_r5,
255
        gen_op_movl_T1_r6,
256
        gen_op_movl_T1_r7,
257
        gen_op_movl_T1_r8,
258
        gen_op_movl_T1_r9,
259
        gen_op_movl_T1_r10,
260
        gen_op_movl_T1_r11,
261
        gen_op_movl_T1_r12,
262
        gen_op_movl_T1_r13,
263
        gen_op_movl_T1_r14,
264
        gen_op_movl_T1_r15,
265
    },
266
    {
267
        gen_op_movl_T2_r0,
268
        gen_op_movl_T2_r1,
269
        gen_op_movl_T2_r2,
270
        gen_op_movl_T2_r3,
271
        gen_op_movl_T2_r4,
272
        gen_op_movl_T2_r5,
273
        gen_op_movl_T2_r6,
274
        gen_op_movl_T2_r7,
275
        gen_op_movl_T2_r8,
276
        gen_op_movl_T2_r9,
277
        gen_op_movl_T2_r10,
278
        gen_op_movl_T2_r11,
279
        gen_op_movl_T2_r12,
280
        gen_op_movl_T2_r13,
281
        gen_op_movl_T2_r14,
282
        gen_op_movl_T2_r15,
283
    },
284
};
285

    
286
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
287
    {
288
        gen_op_movl_r0_T0,
289
        gen_op_movl_r1_T0,
290
        gen_op_movl_r2_T0,
291
        gen_op_movl_r3_T0,
292
        gen_op_movl_r4_T0,
293
        gen_op_movl_r5_T0,
294
        gen_op_movl_r6_T0,
295
        gen_op_movl_r7_T0,
296
        gen_op_movl_r8_T0,
297
        gen_op_movl_r9_T0,
298
        gen_op_movl_r10_T0,
299
        gen_op_movl_r11_T0,
300
        gen_op_movl_r12_T0,
301
        gen_op_movl_r13_T0,
302
        gen_op_movl_r14_T0,
303
        gen_op_movl_r15_T0,
304
    },
305
    {
306
        gen_op_movl_r0_T1,
307
        gen_op_movl_r1_T1,
308
        gen_op_movl_r2_T1,
309
        gen_op_movl_r3_T1,
310
        gen_op_movl_r4_T1,
311
        gen_op_movl_r5_T1,
312
        gen_op_movl_r6_T1,
313
        gen_op_movl_r7_T1,
314
        gen_op_movl_r8_T1,
315
        gen_op_movl_r9_T1,
316
        gen_op_movl_r10_T1,
317
        gen_op_movl_r11_T1,
318
        gen_op_movl_r12_T1,
319
        gen_op_movl_r13_T1,
320
        gen_op_movl_r14_T1,
321
        gen_op_movl_r15_T1,
322
    },
323
};
324

    
325
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
326
    gen_op_movl_T0_im,
327
    gen_op_movl_T1_im,
328
    gen_op_movl_T2_im,
329
};
330

    
331
static GenOpFunc1 *gen_shift_T0_im_thumb_cc[3] = {
332
    gen_op_shll_T0_im_thumb_cc,
333
    gen_op_shrl_T0_im_thumb_cc,
334
    gen_op_sarl_T0_im_thumb_cc,
335
};
336

    
337
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
338
    gen_op_shll_T0_im_thumb,
339
    gen_op_shrl_T0_im_thumb,
340
    gen_op_sarl_T0_im_thumb,
341
};
342

    
343
static inline void gen_bx(DisasContext *s)
344
{
345
  s->is_jmp = DISAS_UPDATE;
346
  gen_op_bx_T0();
347
}
348

    
349

    
350
#if defined(CONFIG_USER_ONLY)
351
#define gen_ldst(name, s) gen_op_##name##_raw()
352
#else
353
#define gen_ldst(name, s) do { \
354
    s->is_mem = 1; \
355
    if (IS_USER(s)) \
356
        gen_op_##name##_user(); \
357
    else \
358
        gen_op_##name##_kernel(); \
359
    } while (0)
360
#endif
361

    
362
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
363
{
364
    int val;
365

    
366
    if (reg == 15) {
367
        /* normaly, since we updated PC, we need only to add one insn */
368
        if (s->thumb)
369
            val = (long)s->pc + 2;
370
        else
371
            val = (long)s->pc + 4;
372
        gen_op_movl_TN_im[t](val);
373
    } else {
374
        gen_op_movl_TN_reg[t][reg]();
375
    }
376
}
377

    
378
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
379
{
380
    gen_movl_TN_reg(s, reg, 0);
381
}
382

    
383
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
384
{
385
    gen_movl_TN_reg(s, reg, 1);
386
}
387

    
388
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
389
{
390
    gen_movl_TN_reg(s, reg, 2);
391
}
392

    
393
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
394
{
395
    gen_op_movl_reg_TN[t][reg]();
396
    if (reg == 15) {
397
        s->is_jmp = DISAS_JUMP;
398
    }
399
}
400

    
401
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
402
{
403
    gen_movl_reg_TN(s, reg, 0);
404
}
405

    
406
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
407
{
408
    gen_movl_reg_TN(s, reg, 1);
409
}
410

    
411
/* Force a TB lookup after an instruction that changes the CPU state.  */
412
static inline void gen_lookup_tb(DisasContext *s)
413
{
414
    gen_op_movl_T0_im(s->pc);
415
    gen_movl_reg_T0(s, 15);
416
    s->is_jmp = DISAS_UPDATE;
417
}
418

    
419
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
420
{
421
    int val, rm, shift, shiftop;
422

    
423
    if (!(insn & (1 << 25))) {
424
        /* immediate */
425
        val = insn & 0xfff;
426
        if (!(insn & (1 << 23)))
427
            val = -val;
428
        if (val != 0)
429
            gen_op_addl_T1_im(val);
430
    } else {
431
        /* shift/register */
432
        rm = (insn) & 0xf;
433
        shift = (insn >> 7) & 0x1f;
434
        gen_movl_T2_reg(s, rm);
435
        shiftop = (insn >> 5) & 3;
436
        if (shift != 0) {
437
            gen_shift_T2_im[shiftop](shift);
438
        } else if (shiftop != 0) {
439
            gen_shift_T2_0[shiftop]();
440
        }
441
        if (!(insn & (1 << 23)))
442
            gen_op_subl_T1_T2();
443
        else
444
            gen_op_addl_T1_T2();
445
    }
446
}
447

    
448
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
449
                                        int extra)
450
{
451
    int val, rm;
452

    
453
    if (insn & (1 << 22)) {
454
        /* immediate */
455
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
456
        if (!(insn & (1 << 23)))
457
            val = -val;
458
        val += extra;
459
        if (val != 0)
460
            gen_op_addl_T1_im(val);
461
    } else {
462
        /* register */
463
        if (extra)
464
            gen_op_addl_T1_im(extra);
465
        rm = (insn) & 0xf;
466
        gen_movl_T2_reg(s, rm);
467
        if (!(insn & (1 << 23)))
468
            gen_op_subl_T1_T2();
469
        else
470
            gen_op_addl_T1_T2();
471
    }
472
}
473

    
474
#define VFP_OP(name)                      \
475
static inline void gen_vfp_##name(int dp) \
476
{                                         \
477
    if (dp)                               \
478
        gen_op_vfp_##name##d();           \
479
    else                                  \
480
        gen_op_vfp_##name##s();           \
481
}
482

    
483
#define VFP_OP1(name)                               \
484
static inline void gen_vfp_##name(int dp, int arg)  \
485
{                                                   \
486
    if (dp)                                         \
487
        gen_op_vfp_##name##d(arg);                  \
488
    else                                            \
489
        gen_op_vfp_##name##s(arg);                  \
490
}
491

    
492
VFP_OP(add)
493
VFP_OP(sub)
494
VFP_OP(mul)
495
VFP_OP(div)
496
VFP_OP(neg)
497
VFP_OP(abs)
498
VFP_OP(sqrt)
499
VFP_OP(cmp)
500
VFP_OP(cmpe)
501
VFP_OP(F1_ld0)
502
VFP_OP(uito)
503
VFP_OP(sito)
504
VFP_OP(toui)
505
VFP_OP(touiz)
506
VFP_OP(tosi)
507
VFP_OP(tosiz)
508
VFP_OP1(tosh)
509
VFP_OP1(tosl)
510
VFP_OP1(touh)
511
VFP_OP1(toul)
512
VFP_OP1(shto)
513
VFP_OP1(slto)
514
VFP_OP1(uhto)
515
VFP_OP1(ulto)
516

    
517
#undef VFP_OP
518

    
519
static inline void gen_vfp_fconst(int dp, uint32_t val)
520
{
521
    if (dp)
522
        gen_op_vfp_fconstd(val);
523
    else
524
        gen_op_vfp_fconsts(val);
525
}
526

    
527
static inline void gen_vfp_ld(DisasContext *s, int dp)
528
{
529
    if (dp)
530
        gen_ldst(vfp_ldd, s);
531
    else
532
        gen_ldst(vfp_lds, s);
533
}
534

    
535
static inline void gen_vfp_st(DisasContext *s, int dp)
536
{
537
    if (dp)
538
        gen_ldst(vfp_std, s);
539
    else
540
        gen_ldst(vfp_sts, s);
541
}
542

    
543
static inline long
544
vfp_reg_offset (int dp, int reg)
545
{
546
    if (dp)
547
        return offsetof(CPUARMState, vfp.regs[reg]);
548
    else if (reg & 1) {
549
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
550
          + offsetof(CPU_DoubleU, l.upper);
551
    } else {
552
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
553
          + offsetof(CPU_DoubleU, l.lower);
554
    }
555
}
556

    
557
/* Return the offset of a 32-bit piece of a NEON register.
558
   zero is the least significant end of the register.  */
559
static inline long
560
neon_reg_offset (int reg, int n)
561
{
562
    int sreg;
563
    sreg = reg * 2 + n;
564
    return vfp_reg_offset(0, sreg);
565
}
566

    
567
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
568
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
569

    
570
static inline void gen_mov_F0_vreg(int dp, int reg)
571
{
572
    if (dp)
573
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
574
    else
575
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
576
}
577

    
578
static inline void gen_mov_F1_vreg(int dp, int reg)
579
{
580
    if (dp)
581
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
582
    else
583
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
584
}
585

    
586
static inline void gen_mov_vreg_F0(int dp, int reg)
587
{
588
    if (dp)
589
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
590
    else
591
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
592
}
593

    
594
#define ARM_CP_RW_BIT        (1 << 20)
595

    
596
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
597
{
598
    int rd;
599
    uint32_t offset;
600

    
601
    rd = (insn >> 16) & 0xf;
602
    gen_movl_T1_reg(s, rd);
603

    
604
    offset = (insn & 0xff) << ((insn >> 7) & 2);
605
    if (insn & (1 << 24)) {
606
        /* Pre indexed */
607
        if (insn & (1 << 23))
608
            gen_op_addl_T1_im(offset);
609
        else
610
            gen_op_addl_T1_im(-offset);
611

    
612
        if (insn & (1 << 21))
613
            gen_movl_reg_T1(s, rd);
614
    } else if (insn & (1 << 21)) {
615
        /* Post indexed */
616
        if (insn & (1 << 23))
617
            gen_op_movl_T0_im(offset);
618
        else
619
            gen_op_movl_T0_im(- offset);
620
        gen_op_addl_T0_T1();
621
        gen_movl_reg_T0(s, rd);
622
    } else if (!(insn & (1 << 23)))
623
        return 1;
624
    return 0;
625
}
626

    
627
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
628
{
629
    int rd = (insn >> 0) & 0xf;
630

    
631
    if (insn & (1 << 8))
632
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
633
            return 1;
634
        else
635
            gen_op_iwmmxt_movl_T0_wCx(rd);
636
    else
637
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
638

    
639
    gen_op_movl_T1_im(mask);
640
    gen_op_andl_T0_T1();
641
    return 0;
642
}
643

    
644
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
645
   (ie. an undefined instruction).  */
646
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
647
{
648
    int rd, wrd;
649
    int rdhi, rdlo, rd0, rd1, i;
650

    
651
    if ((insn & 0x0e000e00) == 0x0c000000) {
652
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
653
            wrd = insn & 0xf;
654
            rdlo = (insn >> 12) & 0xf;
655
            rdhi = (insn >> 16) & 0xf;
656
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
657
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
658
                gen_movl_reg_T0(s, rdlo);
659
                gen_movl_reg_T1(s, rdhi);
660
            } else {                                        /* TMCRR */
661
                gen_movl_T0_reg(s, rdlo);
662
                gen_movl_T1_reg(s, rdhi);
663
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
664
                gen_op_iwmmxt_set_mup();
665
            }
666
            return 0;
667
        }
668

    
669
        wrd = (insn >> 12) & 0xf;
670
        if (gen_iwmmxt_address(s, insn))
671
            return 1;
672
        if (insn & ARM_CP_RW_BIT) {
673
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
674
                gen_ldst(ldl, s);
675
                gen_op_iwmmxt_movl_wCx_T0(wrd);
676
            } else {
677
                if (insn & (1 << 8))
678
                    if (insn & (1 << 22))                /* WLDRD */
679
                        gen_ldst(iwmmxt_ldq, s);
680
                    else                                /* WLDRW wRd */
681
                        gen_ldst(iwmmxt_ldl, s);
682
                else
683
                    if (insn & (1 << 22))                /* WLDRH */
684
                        gen_ldst(iwmmxt_ldw, s);
685
                    else                                /* WLDRB */
686
                        gen_ldst(iwmmxt_ldb, s);
687
                gen_op_iwmmxt_movq_wRn_M0(wrd);
688
            }
689
        } else {
690
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
691
                gen_op_iwmmxt_movl_T0_wCx(wrd);
692
                gen_ldst(stl, s);
693
            } else {
694
                gen_op_iwmmxt_movq_M0_wRn(wrd);
695
                if (insn & (1 << 8))
696
                    if (insn & (1 << 22))                /* WSTRD */
697
                        gen_ldst(iwmmxt_stq, s);
698
                    else                                /* WSTRW wRd */
699
                        gen_ldst(iwmmxt_stl, s);
700
                else
701
                    if (insn & (1 << 22))                /* WSTRH */
702
                        gen_ldst(iwmmxt_ldw, s);
703
                    else                                /* WSTRB */
704
                        gen_ldst(iwmmxt_stb, s);
705
            }
706
        }
707
        return 0;
708
    }
709

    
710
    if ((insn & 0x0f000000) != 0x0e000000)
711
        return 1;
712

    
713
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
714
    case 0x000:                                                /* WOR */
715
        wrd = (insn >> 12) & 0xf;
716
        rd0 = (insn >> 0) & 0xf;
717
        rd1 = (insn >> 16) & 0xf;
718
        gen_op_iwmmxt_movq_M0_wRn(rd0);
719
        gen_op_iwmmxt_orq_M0_wRn(rd1);
720
        gen_op_iwmmxt_setpsr_nz();
721
        gen_op_iwmmxt_movq_wRn_M0(wrd);
722
        gen_op_iwmmxt_set_mup();
723
        gen_op_iwmmxt_set_cup();
724
        break;
725
    case 0x011:                                                /* TMCR */
726
        if (insn & 0xf)
727
            return 1;
728
        rd = (insn >> 12) & 0xf;
729
        wrd = (insn >> 16) & 0xf;
730
        switch (wrd) {
731
        case ARM_IWMMXT_wCID:
732
        case ARM_IWMMXT_wCASF:
733
            break;
734
        case ARM_IWMMXT_wCon:
735
            gen_op_iwmmxt_set_cup();
736
            /* Fall through.  */
737
        case ARM_IWMMXT_wCSSF:
738
            gen_op_iwmmxt_movl_T0_wCx(wrd);
739
            gen_movl_T1_reg(s, rd);
740
            gen_op_bicl_T0_T1();
741
            gen_op_iwmmxt_movl_wCx_T0(wrd);
742
            break;
743
        case ARM_IWMMXT_wCGR0:
744
        case ARM_IWMMXT_wCGR1:
745
        case ARM_IWMMXT_wCGR2:
746
        case ARM_IWMMXT_wCGR3:
747
            gen_op_iwmmxt_set_cup();
748
            gen_movl_reg_T0(s, rd);
749
            gen_op_iwmmxt_movl_wCx_T0(wrd);
750
            break;
751
        default:
752
            return 1;
753
        }
754
        break;
755
    case 0x100:                                                /* WXOR */
756
        wrd = (insn >> 12) & 0xf;
757
        rd0 = (insn >> 0) & 0xf;
758
        rd1 = (insn >> 16) & 0xf;
759
        gen_op_iwmmxt_movq_M0_wRn(rd0);
760
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
761
        gen_op_iwmmxt_setpsr_nz();
762
        gen_op_iwmmxt_movq_wRn_M0(wrd);
763
        gen_op_iwmmxt_set_mup();
764
        gen_op_iwmmxt_set_cup();
765
        break;
766
    case 0x111:                                                /* TMRC */
767
        if (insn & 0xf)
768
            return 1;
769
        rd = (insn >> 12) & 0xf;
770
        wrd = (insn >> 16) & 0xf;
771
        gen_op_iwmmxt_movl_T0_wCx(wrd);
772
        gen_movl_reg_T0(s, rd);
773
        break;
774
    case 0x300:                                                /* WANDN */
775
        wrd = (insn >> 12) & 0xf;
776
        rd0 = (insn >> 0) & 0xf;
777
        rd1 = (insn >> 16) & 0xf;
778
        gen_op_iwmmxt_movq_M0_wRn(rd0);
779
        gen_op_iwmmxt_negq_M0();
780
        gen_op_iwmmxt_andq_M0_wRn(rd1);
781
        gen_op_iwmmxt_setpsr_nz();
782
        gen_op_iwmmxt_movq_wRn_M0(wrd);
783
        gen_op_iwmmxt_set_mup();
784
        gen_op_iwmmxt_set_cup();
785
        break;
786
    case 0x200:                                                /* WAND */
787
        wrd = (insn >> 12) & 0xf;
788
        rd0 = (insn >> 0) & 0xf;
789
        rd1 = (insn >> 16) & 0xf;
790
        gen_op_iwmmxt_movq_M0_wRn(rd0);
791
        gen_op_iwmmxt_andq_M0_wRn(rd1);
792
        gen_op_iwmmxt_setpsr_nz();
793
        gen_op_iwmmxt_movq_wRn_M0(wrd);
794
        gen_op_iwmmxt_set_mup();
795
        gen_op_iwmmxt_set_cup();
796
        break;
797
    case 0x810: case 0xa10:                                /* WMADD */
798
        wrd = (insn >> 12) & 0xf;
799
        rd0 = (insn >> 0) & 0xf;
800
        rd1 = (insn >> 16) & 0xf;
801
        gen_op_iwmmxt_movq_M0_wRn(rd0);
802
        if (insn & (1 << 21))
803
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
804
        else
805
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
806
        gen_op_iwmmxt_movq_wRn_M0(wrd);
807
        gen_op_iwmmxt_set_mup();
808
        break;
809
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
810
        wrd = (insn >> 12) & 0xf;
811
        rd0 = (insn >> 16) & 0xf;
812
        rd1 = (insn >> 0) & 0xf;
813
        gen_op_iwmmxt_movq_M0_wRn(rd0);
814
        switch ((insn >> 22) & 3) {
815
        case 0:
816
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
817
            break;
818
        case 1:
819
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
820
            break;
821
        case 2:
822
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
823
            break;
824
        case 3:
825
            return 1;
826
        }
827
        gen_op_iwmmxt_movq_wRn_M0(wrd);
828
        gen_op_iwmmxt_set_mup();
829
        gen_op_iwmmxt_set_cup();
830
        break;
831
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
832
        wrd = (insn >> 12) & 0xf;
833
        rd0 = (insn >> 16) & 0xf;
834
        rd1 = (insn >> 0) & 0xf;
835
        gen_op_iwmmxt_movq_M0_wRn(rd0);
836
        switch ((insn >> 22) & 3) {
837
        case 0:
838
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
839
            break;
840
        case 1:
841
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
842
            break;
843
        case 2:
844
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
845
            break;
846
        case 3:
847
            return 1;
848
        }
849
        gen_op_iwmmxt_movq_wRn_M0(wrd);
850
        gen_op_iwmmxt_set_mup();
851
        gen_op_iwmmxt_set_cup();
852
        break;
853
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
854
        wrd = (insn >> 12) & 0xf;
855
        rd0 = (insn >> 16) & 0xf;
856
        rd1 = (insn >> 0) & 0xf;
857
        gen_op_iwmmxt_movq_M0_wRn(rd0);
858
        if (insn & (1 << 22))
859
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
860
        else
861
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
862
        if (!(insn & (1 << 20)))
863
            gen_op_iwmmxt_addl_M0_wRn(wrd);
864
        gen_op_iwmmxt_movq_wRn_M0(wrd);
865
        gen_op_iwmmxt_set_mup();
866
        break;
867
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
868
        wrd = (insn >> 12) & 0xf;
869
        rd0 = (insn >> 16) & 0xf;
870
        rd1 = (insn >> 0) & 0xf;
871
        gen_op_iwmmxt_movq_M0_wRn(rd0);
872
        if (insn & (1 << 21))
873
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
874
        else
875
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
876
        gen_op_iwmmxt_movq_wRn_M0(wrd);
877
        gen_op_iwmmxt_set_mup();
878
        break;
879
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
880
        wrd = (insn >> 12) & 0xf;
881
        rd0 = (insn >> 16) & 0xf;
882
        rd1 = (insn >> 0) & 0xf;
883
        gen_op_iwmmxt_movq_M0_wRn(rd0);
884
        if (insn & (1 << 21))
885
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
886
        else
887
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
888
        if (!(insn & (1 << 20))) {
889
            if (insn & (1 << 21))
890
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
891
            else
892
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
893
        }
894
        gen_op_iwmmxt_movq_wRn_M0(wrd);
895
        gen_op_iwmmxt_set_mup();
896
        break;
897
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
898
        wrd = (insn >> 12) & 0xf;
899
        rd0 = (insn >> 16) & 0xf;
900
        rd1 = (insn >> 0) & 0xf;
901
        gen_op_iwmmxt_movq_M0_wRn(rd0);
902
        switch ((insn >> 22) & 3) {
903
        case 0:
904
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
905
            break;
906
        case 1:
907
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
908
            break;
909
        case 2:
910
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
911
            break;
912
        case 3:
913
            return 1;
914
        }
915
        gen_op_iwmmxt_movq_wRn_M0(wrd);
916
        gen_op_iwmmxt_set_mup();
917
        gen_op_iwmmxt_set_cup();
918
        break;
919
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
920
        wrd = (insn >> 12) & 0xf;
921
        rd0 = (insn >> 16) & 0xf;
922
        rd1 = (insn >> 0) & 0xf;
923
        gen_op_iwmmxt_movq_M0_wRn(rd0);
924
        if (insn & (1 << 22))
925
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
926
        else
927
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
928
        gen_op_iwmmxt_movq_wRn_M0(wrd);
929
        gen_op_iwmmxt_set_mup();
930
        gen_op_iwmmxt_set_cup();
931
        break;
932
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
933
        wrd = (insn >> 12) & 0xf;
934
        rd0 = (insn >> 16) & 0xf;
935
        rd1 = (insn >> 0) & 0xf;
936
        gen_op_iwmmxt_movq_M0_wRn(rd0);
937
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
938
        gen_op_movl_T1_im(7);
939
        gen_op_andl_T0_T1();
940
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
941
        gen_op_iwmmxt_movq_wRn_M0(wrd);
942
        gen_op_iwmmxt_set_mup();
943
        break;
944
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
945
        rd = (insn >> 12) & 0xf;
946
        wrd = (insn >> 16) & 0xf;
947
        gen_movl_T0_reg(s, rd);
948
        gen_op_iwmmxt_movq_M0_wRn(wrd);
949
        switch ((insn >> 6) & 3) {
950
        case 0:
951
            gen_op_movl_T1_im(0xff);
952
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
953
            break;
954
        case 1:
955
            gen_op_movl_T1_im(0xffff);
956
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
957
            break;
958
        case 2:
959
            gen_op_movl_T1_im(0xffffffff);
960
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
961
            break;
962
        case 3:
963
            return 1;
964
        }
965
        gen_op_iwmmxt_movq_wRn_M0(wrd);
966
        gen_op_iwmmxt_set_mup();
967
        break;
968
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
969
        rd = (insn >> 12) & 0xf;
970
        wrd = (insn >> 16) & 0xf;
971
        if (rd == 15)
972
            return 1;
973
        gen_op_iwmmxt_movq_M0_wRn(wrd);
974
        switch ((insn >> 22) & 3) {
975
        case 0:
976
            if (insn & 8)
977
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
978
            else {
979
                gen_op_movl_T1_im(0xff);
980
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
981
            }
982
            break;
983
        case 1:
984
            if (insn & 8)
985
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
986
            else {
987
                gen_op_movl_T1_im(0xffff);
988
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
989
            }
990
            break;
991
        case 2:
992
            gen_op_movl_T1_im(0xffffffff);
993
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
994
            break;
995
        case 3:
996
            return 1;
997
        }
998
        gen_op_movl_reg_TN[0][rd]();
999
        break;
1000
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1001
        if ((insn & 0x000ff008) != 0x0003f000)
1002
            return 1;
1003
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1004
        switch ((insn >> 22) & 3) {
1005
        case 0:
1006
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1007
            break;
1008
        case 1:
1009
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1010
            break;
1011
        case 2:
1012
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1013
            break;
1014
        case 3:
1015
            return 1;
1016
        }
1017
        gen_op_shll_T1_im(28);
1018
        gen_op_movl_T0_T1();
1019
        gen_op_movl_cpsr_T0(0xf0000000);
1020
        break;
1021
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1022
        rd = (insn >> 12) & 0xf;
1023
        wrd = (insn >> 16) & 0xf;
1024
        gen_movl_T0_reg(s, rd);
1025
        switch ((insn >> 6) & 3) {
1026
        case 0:
1027
            gen_op_iwmmxt_bcstb_M0_T0();
1028
            break;
1029
        case 1:
1030
            gen_op_iwmmxt_bcstw_M0_T0();
1031
            break;
1032
        case 2:
1033
            gen_op_iwmmxt_bcstl_M0_T0();
1034
            break;
1035
        case 3:
1036
            return 1;
1037
        }
1038
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1039
        gen_op_iwmmxt_set_mup();
1040
        break;
1041
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1042
        if ((insn & 0x000ff00f) != 0x0003f000)
1043
            return 1;
1044
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1045
        switch ((insn >> 22) & 3) {
1046
        case 0:
1047
            for (i = 0; i < 7; i ++) {
1048
                gen_op_shll_T1_im(4);
1049
                gen_op_andl_T0_T1();
1050
            }
1051
            break;
1052
        case 1:
1053
            for (i = 0; i < 3; i ++) {
1054
                gen_op_shll_T1_im(8);
1055
                gen_op_andl_T0_T1();
1056
            }
1057
            break;
1058
        case 2:
1059
            gen_op_shll_T1_im(16);
1060
            gen_op_andl_T0_T1();
1061
            break;
1062
        case 3:
1063
            return 1;
1064
        }
1065
        gen_op_movl_cpsr_T0(0xf0000000);
1066
        break;
1067
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1068
        wrd = (insn >> 12) & 0xf;
1069
        rd0 = (insn >> 16) & 0xf;
1070
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1071
        switch ((insn >> 22) & 3) {
1072
        case 0:
1073
            gen_op_iwmmxt_addcb_M0();
1074
            break;
1075
        case 1:
1076
            gen_op_iwmmxt_addcw_M0();
1077
            break;
1078
        case 2:
1079
            gen_op_iwmmxt_addcl_M0();
1080
            break;
1081
        case 3:
1082
            return 1;
1083
        }
1084
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1085
        gen_op_iwmmxt_set_mup();
1086
        break;
1087
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1088
        if ((insn & 0x000ff00f) != 0x0003f000)
1089
            return 1;
1090
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1091
        switch ((insn >> 22) & 3) {
1092
        case 0:
1093
            for (i = 0; i < 7; i ++) {
1094
                gen_op_shll_T1_im(4);
1095
                gen_op_orl_T0_T1();
1096
            }
1097
            break;
1098
        case 1:
1099
            for (i = 0; i < 3; i ++) {
1100
                gen_op_shll_T1_im(8);
1101
                gen_op_orl_T0_T1();
1102
            }
1103
            break;
1104
        case 2:
1105
            gen_op_shll_T1_im(16);
1106
            gen_op_orl_T0_T1();
1107
            break;
1108
        case 3:
1109
            return 1;
1110
        }
1111
        gen_op_movl_T1_im(0xf0000000);
1112
        gen_op_andl_T0_T1();
1113
        gen_op_movl_cpsr_T0(0xf0000000);
1114
        break;
1115
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1116
        rd = (insn >> 12) & 0xf;
1117
        rd0 = (insn >> 16) & 0xf;
1118
        if ((insn & 0xf) != 0)
1119
            return 1;
1120
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1121
        switch ((insn >> 22) & 3) {
1122
        case 0:
1123
            gen_op_iwmmxt_msbb_T0_M0();
1124
            break;
1125
        case 1:
1126
            gen_op_iwmmxt_msbw_T0_M0();
1127
            break;
1128
        case 2:
1129
            gen_op_iwmmxt_msbl_T0_M0();
1130
            break;
1131
        case 3:
1132
            return 1;
1133
        }
1134
        gen_movl_reg_T0(s, rd);
1135
        break;
1136
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1137
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1138
        wrd = (insn >> 12) & 0xf;
1139
        rd0 = (insn >> 16) & 0xf;
1140
        rd1 = (insn >> 0) & 0xf;
1141
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1142
        switch ((insn >> 22) & 3) {
1143
        case 0:
1144
            if (insn & (1 << 21))
1145
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1146
            else
1147
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1148
            break;
1149
        case 1:
1150
            if (insn & (1 << 21))
1151
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1152
            else
1153
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1154
            break;
1155
        case 2:
1156
            if (insn & (1 << 21))
1157
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1158
            else
1159
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1160
            break;
1161
        case 3:
1162
            return 1;
1163
        }
1164
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1165
        gen_op_iwmmxt_set_mup();
1166
        gen_op_iwmmxt_set_cup();
1167
        break;
1168
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1169
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1170
        wrd = (insn >> 12) & 0xf;
1171
        rd0 = (insn >> 16) & 0xf;
1172
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1173
        switch ((insn >> 22) & 3) {
1174
        case 0:
1175
            if (insn & (1 << 21))
1176
                gen_op_iwmmxt_unpacklsb_M0();
1177
            else
1178
                gen_op_iwmmxt_unpacklub_M0();
1179
            break;
1180
        case 1:
1181
            if (insn & (1 << 21))
1182
                gen_op_iwmmxt_unpacklsw_M0();
1183
            else
1184
                gen_op_iwmmxt_unpackluw_M0();
1185
            break;
1186
        case 2:
1187
            if (insn & (1 << 21))
1188
                gen_op_iwmmxt_unpacklsl_M0();
1189
            else
1190
                gen_op_iwmmxt_unpacklul_M0();
1191
            break;
1192
        case 3:
1193
            return 1;
1194
        }
1195
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1196
        gen_op_iwmmxt_set_mup();
1197
        gen_op_iwmmxt_set_cup();
1198
        break;
1199
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1200
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1201
        wrd = (insn >> 12) & 0xf;
1202
        rd0 = (insn >> 16) & 0xf;
1203
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1204
        switch ((insn >> 22) & 3) {
1205
        case 0:
1206
            if (insn & (1 << 21))
1207
                gen_op_iwmmxt_unpackhsb_M0();
1208
            else
1209
                gen_op_iwmmxt_unpackhub_M0();
1210
            break;
1211
        case 1:
1212
            if (insn & (1 << 21))
1213
                gen_op_iwmmxt_unpackhsw_M0();
1214
            else
1215
                gen_op_iwmmxt_unpackhuw_M0();
1216
            break;
1217
        case 2:
1218
            if (insn & (1 << 21))
1219
                gen_op_iwmmxt_unpackhsl_M0();
1220
            else
1221
                gen_op_iwmmxt_unpackhul_M0();
1222
            break;
1223
        case 3:
1224
            return 1;
1225
        }
1226
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1227
        gen_op_iwmmxt_set_mup();
1228
        gen_op_iwmmxt_set_cup();
1229
        break;
1230
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1231
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1232
        wrd = (insn >> 12) & 0xf;
1233
        rd0 = (insn >> 16) & 0xf;
1234
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1235
        if (gen_iwmmxt_shift(insn, 0xff))
1236
            return 1;
1237
        switch ((insn >> 22) & 3) {
1238
        case 0:
1239
            return 1;
1240
        case 1:
1241
            gen_op_iwmmxt_srlw_M0_T0();
1242
            break;
1243
        case 2:
1244
            gen_op_iwmmxt_srll_M0_T0();
1245
            break;
1246
        case 3:
1247
            gen_op_iwmmxt_srlq_M0_T0();
1248
            break;
1249
        }
1250
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1251
        gen_op_iwmmxt_set_mup();
1252
        gen_op_iwmmxt_set_cup();
1253
        break;
1254
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1255
    case 0x014: case 0x414: case 0x814: case 0xc14:
1256
        wrd = (insn >> 12) & 0xf;
1257
        rd0 = (insn >> 16) & 0xf;
1258
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1259
        if (gen_iwmmxt_shift(insn, 0xff))
1260
            return 1;
1261
        switch ((insn >> 22) & 3) {
1262
        case 0:
1263
            return 1;
1264
        case 1:
1265
            gen_op_iwmmxt_sraw_M0_T0();
1266
            break;
1267
        case 2:
1268
            gen_op_iwmmxt_sral_M0_T0();
1269
            break;
1270
        case 3:
1271
            gen_op_iwmmxt_sraq_M0_T0();
1272
            break;
1273
        }
1274
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1275
        gen_op_iwmmxt_set_mup();
1276
        gen_op_iwmmxt_set_cup();
1277
        break;
1278
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1279
    case 0x114: case 0x514: case 0x914: case 0xd14:
1280
        wrd = (insn >> 12) & 0xf;
1281
        rd0 = (insn >> 16) & 0xf;
1282
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1283
        if (gen_iwmmxt_shift(insn, 0xff))
1284
            return 1;
1285
        switch ((insn >> 22) & 3) {
1286
        case 0:
1287
            return 1;
1288
        case 1:
1289
            gen_op_iwmmxt_sllw_M0_T0();
1290
            break;
1291
        case 2:
1292
            gen_op_iwmmxt_slll_M0_T0();
1293
            break;
1294
        case 3:
1295
            gen_op_iwmmxt_sllq_M0_T0();
1296
            break;
1297
        }
1298
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1299
        gen_op_iwmmxt_set_mup();
1300
        gen_op_iwmmxt_set_cup();
1301
        break;
1302
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1303
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1304
        wrd = (insn >> 12) & 0xf;
1305
        rd0 = (insn >> 16) & 0xf;
1306
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1307
        switch ((insn >> 22) & 3) {
1308
        case 0:
1309
            return 1;
1310
        case 1:
1311
            if (gen_iwmmxt_shift(insn, 0xf))
1312
                return 1;
1313
            gen_op_iwmmxt_rorw_M0_T0();
1314
            break;
1315
        case 2:
1316
            if (gen_iwmmxt_shift(insn, 0x1f))
1317
                return 1;
1318
            gen_op_iwmmxt_rorl_M0_T0();
1319
            break;
1320
        case 3:
1321
            if (gen_iwmmxt_shift(insn, 0x3f))
1322
                return 1;
1323
            gen_op_iwmmxt_rorq_M0_T0();
1324
            break;
1325
        }
1326
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1327
        gen_op_iwmmxt_set_mup();
1328
        gen_op_iwmmxt_set_cup();
1329
        break;
1330
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1331
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1332
        wrd = (insn >> 12) & 0xf;
1333
        rd0 = (insn >> 16) & 0xf;
1334
        rd1 = (insn >> 0) & 0xf;
1335
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1336
        switch ((insn >> 22) & 3) {
1337
        case 0:
1338
            if (insn & (1 << 21))
1339
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1340
            else
1341
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1342
            break;
1343
        case 1:
1344
            if (insn & (1 << 21))
1345
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1346
            else
1347
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1348
            break;
1349
        case 2:
1350
            if (insn & (1 << 21))
1351
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1352
            else
1353
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1354
            break;
1355
        case 3:
1356
            return 1;
1357
        }
1358
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1359
        gen_op_iwmmxt_set_mup();
1360
        break;
1361
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1362
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1363
        wrd = (insn >> 12) & 0xf;
1364
        rd0 = (insn >> 16) & 0xf;
1365
        rd1 = (insn >> 0) & 0xf;
1366
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1367
        switch ((insn >> 22) & 3) {
1368
        case 0:
1369
            if (insn & (1 << 21))
1370
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1371
            else
1372
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1373
            break;
1374
        case 1:
1375
            if (insn & (1 << 21))
1376
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1377
            else
1378
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1379
            break;
1380
        case 2:
1381
            if (insn & (1 << 21))
1382
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1383
            else
1384
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1385
            break;
1386
        case 3:
1387
            return 1;
1388
        }
1389
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1390
        gen_op_iwmmxt_set_mup();
1391
        break;
1392
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1393
    case 0x402: case 0x502: case 0x602: case 0x702:
1394
        wrd = (insn >> 12) & 0xf;
1395
        rd0 = (insn >> 16) & 0xf;
1396
        rd1 = (insn >> 0) & 0xf;
1397
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1398
        gen_op_movl_T0_im((insn >> 20) & 3);
1399
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1400
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1401
        gen_op_iwmmxt_set_mup();
1402
        break;
1403
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1404
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1405
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1406
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1407
        wrd = (insn >> 12) & 0xf;
1408
        rd0 = (insn >> 16) & 0xf;
1409
        rd1 = (insn >> 0) & 0xf;
1410
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1411
        switch ((insn >> 20) & 0xf) {
1412
        case 0x0:
1413
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
1414
            break;
1415
        case 0x1:
1416
            gen_op_iwmmxt_subub_M0_wRn(rd1);
1417
            break;
1418
        case 0x3:
1419
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
1420
            break;
1421
        case 0x4:
1422
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
1423
            break;
1424
        case 0x5:
1425
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
1426
            break;
1427
        case 0x7:
1428
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
1429
            break;
1430
        case 0x8:
1431
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
1432
            break;
1433
        case 0x9:
1434
            gen_op_iwmmxt_subul_M0_wRn(rd1);
1435
            break;
1436
        case 0xb:
1437
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
1438
            break;
1439
        default:
1440
            return 1;
1441
        }
1442
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1443
        gen_op_iwmmxt_set_mup();
1444
        gen_op_iwmmxt_set_cup();
1445
        break;
1446
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
1447
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1448
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1449
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1450
        wrd = (insn >> 12) & 0xf;
1451
        rd0 = (insn >> 16) & 0xf;
1452
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1453
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
1454
        gen_op_iwmmxt_shufh_M0_T0();
1455
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1456
        gen_op_iwmmxt_set_mup();
1457
        gen_op_iwmmxt_set_cup();
1458
        break;
1459
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
1460
    case 0x418: case 0x518: case 0x618: case 0x718:
1461
    case 0x818: case 0x918: case 0xa18: case 0xb18:
1462
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1463
        wrd = (insn >> 12) & 0xf;
1464
        rd0 = (insn >> 16) & 0xf;
1465
        rd1 = (insn >> 0) & 0xf;
1466
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1467
        switch ((insn >> 20) & 0xf) {
1468
        case 0x0:
1469
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
1470
            break;
1471
        case 0x1:
1472
            gen_op_iwmmxt_addub_M0_wRn(rd1);
1473
            break;
1474
        case 0x3:
1475
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
1476
            break;
1477
        case 0x4:
1478
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
1479
            break;
1480
        case 0x5:
1481
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
1482
            break;
1483
        case 0x7:
1484
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
1485
            break;
1486
        case 0x8:
1487
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
1488
            break;
1489
        case 0x9:
1490
            gen_op_iwmmxt_addul_M0_wRn(rd1);
1491
            break;
1492
        case 0xb:
1493
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
1494
            break;
1495
        default:
1496
            return 1;
1497
        }
1498
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1499
        gen_op_iwmmxt_set_mup();
1500
        gen_op_iwmmxt_set_cup();
1501
        break;
1502
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
1503
    case 0x408: case 0x508: case 0x608: case 0x708:
1504
    case 0x808: case 0x908: case 0xa08: case 0xb08:
1505
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1506
        wrd = (insn >> 12) & 0xf;
1507
        rd0 = (insn >> 16) & 0xf;
1508
        rd1 = (insn >> 0) & 0xf;
1509
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1510
        if (!(insn & (1 << 20)))
1511
            return 1;
1512
        switch ((insn >> 22) & 3) {
1513
        case 0:
1514
            return 1;
1515
        case 1:
1516
            if (insn & (1 << 21))
1517
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
1518
            else
1519
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
1520
            break;
1521
        case 2:
1522
            if (insn & (1 << 21))
1523
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
1524
            else
1525
                gen_op_iwmmxt_packul_M0_wRn(rd1);
1526
            break;
1527
        case 3:
1528
            if (insn & (1 << 21))
1529
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
1530
            else
1531
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
1532
            break;
1533
        }
1534
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1535
        gen_op_iwmmxt_set_mup();
1536
        gen_op_iwmmxt_set_cup();
1537
        break;
1538
    case 0x201: case 0x203: case 0x205: case 0x207:
1539
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
1540
    case 0x211: case 0x213: case 0x215: case 0x217:
1541
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
1542
        wrd = (insn >> 5) & 0xf;
1543
        rd0 = (insn >> 12) & 0xf;
1544
        rd1 = (insn >> 0) & 0xf;
1545
        if (rd0 == 0xf || rd1 == 0xf)
1546
            return 1;
1547
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1548
        switch ((insn >> 16) & 0xf) {
1549
        case 0x0:                                        /* TMIA */
1550
            gen_op_movl_TN_reg[0][rd0]();
1551
            gen_op_movl_TN_reg[1][rd1]();
1552
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1553
            break;
1554
        case 0x8:                                        /* TMIAPH */
1555
            gen_op_movl_TN_reg[0][rd0]();
1556
            gen_op_movl_TN_reg[1][rd1]();
1557
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1558
            break;
1559
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
1560
            gen_op_movl_TN_reg[1][rd0]();
1561
            if (insn & (1 << 16))
1562
                gen_op_shrl_T1_im(16);
1563
            gen_op_movl_T0_T1();
1564
            gen_op_movl_TN_reg[1][rd1]();
1565
            if (insn & (1 << 17))
1566
                gen_op_shrl_T1_im(16);
1567
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1568
            break;
1569
        default:
1570
            return 1;
1571
        }
1572
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1573
        gen_op_iwmmxt_set_mup();
1574
        break;
1575
    default:
1576
        return 1;
1577
    }
1578

    
1579
    return 0;
1580
}
1581

    
1582
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
1583
   (ie. an undefined instruction).  */
1584
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1585
{
1586
    int acc, rd0, rd1, rdhi, rdlo;
1587

    
1588
    if ((insn & 0x0ff00f10) == 0x0e200010) {
1589
        /* Multiply with Internal Accumulate Format */
1590
        rd0 = (insn >> 12) & 0xf;
1591
        rd1 = insn & 0xf;
1592
        acc = (insn >> 5) & 7;
1593

    
1594
        if (acc != 0)
1595
            return 1;
1596

    
1597
        switch ((insn >> 16) & 0xf) {
1598
        case 0x0:                                        /* MIA */
1599
            gen_op_movl_TN_reg[0][rd0]();
1600
            gen_op_movl_TN_reg[1][rd1]();
1601
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1602
            break;
1603
        case 0x8:                                        /* MIAPH */
1604
            gen_op_movl_TN_reg[0][rd0]();
1605
            gen_op_movl_TN_reg[1][rd1]();
1606
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1607
            break;
1608
        case 0xc:                                        /* MIABB */
1609
        case 0xd:                                        /* MIABT */
1610
        case 0xe:                                        /* MIATB */
1611
        case 0xf:                                        /* MIATT */
1612
            gen_op_movl_TN_reg[1][rd0]();
1613
            if (insn & (1 << 16))
1614
                gen_op_shrl_T1_im(16);
1615
            gen_op_movl_T0_T1();
1616
            gen_op_movl_TN_reg[1][rd1]();
1617
            if (insn & (1 << 17))
1618
                gen_op_shrl_T1_im(16);
1619
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1620
            break;
1621
        default:
1622
            return 1;
1623
        }
1624

    
1625
        gen_op_iwmmxt_movq_wRn_M0(acc);
1626
        return 0;
1627
    }
1628

    
1629
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
1630
        /* Internal Accumulator Access Format */
1631
        rdhi = (insn >> 16) & 0xf;
1632
        rdlo = (insn >> 12) & 0xf;
1633
        acc = insn & 7;
1634

    
1635
        if (acc != 0)
1636
            return 1;
1637

    
1638
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
1639
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
1640
            gen_op_movl_reg_TN[0][rdlo]();
1641
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1642
            gen_op_andl_T0_T1();
1643
            gen_op_movl_reg_TN[0][rdhi]();
1644
        } else {                                        /* MAR */
1645
            gen_op_movl_TN_reg[0][rdlo]();
1646
            gen_op_movl_TN_reg[1][rdhi]();
1647
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1648
        }
1649
        return 0;
1650
    }
1651

    
1652
    return 1;
1653
}
1654

    
1655
/* Disassemble system coprocessor instruction.  Return nonzero if
1656
   instruction is not defined.  */
1657
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1658
{
1659
    uint32_t rd = (insn >> 12) & 0xf;
1660
    uint32_t cp = (insn >> 8) & 0xf;
1661
    if (IS_USER(s)) {
1662
        return 1;
1663
    }
1664

    
1665
    if (insn & ARM_CP_RW_BIT) {
1666
        if (!env->cp[cp].cp_read)
1667
            return 1;
1668
        gen_op_movl_T0_im((uint32_t) s->pc);
1669
        gen_op_movl_reg_TN[0][15]();
1670
        gen_op_movl_T0_cp(insn);
1671
        gen_movl_reg_T0(s, rd);
1672
    } else {
1673
        if (!env->cp[cp].cp_write)
1674
            return 1;
1675
        gen_op_movl_T0_im((uint32_t) s->pc);
1676
        gen_op_movl_reg_TN[0][15]();
1677
        gen_movl_T0_reg(s, rd);
1678
        gen_op_movl_cp_T0(insn);
1679
    }
1680
    return 0;
1681
}
1682

    
1683
static int cp15_user_ok(uint32_t insn)
1684
{
1685
    int cpn = (insn >> 16) & 0xf;
1686
    int cpm = insn & 0xf;
1687
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1688

    
1689
    if (cpn == 13 && cpm == 0) {
1690
        /* TLS register.  */
1691
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1692
            return 1;
1693
    }
1694
    if (cpn == 7) {
1695
        /* ISB, DSB, DMB.  */
1696
        if ((cpm == 5 && op == 4)
1697
                || (cpm == 10 && (op == 4 || op == 5)))
1698
            return 1;
1699
    }
1700
    return 0;
1701
}
1702

    
1703
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
1704
   instruction is not defined.  */
1705
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1706
{
1707
    uint32_t rd;
1708

    
1709
    /* M profile cores use memory mapped registers instead of cp15.  */
1710
    if (arm_feature(env, ARM_FEATURE_M))
1711
        return 1;
1712

    
1713
    if ((insn & (1 << 25)) == 0) {
1714
        if (insn & (1 << 20)) {
1715
            /* mrrc */
1716
            return 1;
1717
        }
1718
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
1719
        return 0;
1720
    }
1721
    if ((insn & (1 << 4)) == 0) {
1722
        /* cdp */
1723
        return 1;
1724
    }
1725
    if (IS_USER(s) && !cp15_user_ok(insn)) {
1726
        return 1;
1727
    }
1728
    if ((insn & 0x0fff0fff) == 0x0e070f90
1729
        || (insn & 0x0fff0fff) == 0x0e070f58) {
1730
        /* Wait for interrupt.  */
1731
        gen_op_movl_T0_im((long)s->pc);
1732
        gen_op_movl_reg_TN[0][15]();
1733
        s->is_jmp = DISAS_WFI;
1734
        return 0;
1735
    }
1736
    rd = (insn >> 12) & 0xf;
1737
    if (insn & ARM_CP_RW_BIT) {
1738
        gen_op_movl_T0_cp15(insn);
1739
        /* If the destination register is r15 then sets condition codes.  */
1740
        if (rd != 15)
1741
            gen_movl_reg_T0(s, rd);
1742
    } else {
1743
        gen_movl_T0_reg(s, rd);
1744
        gen_op_movl_cp15_T0(insn);
1745
        /* Normally we would always end the TB here, but Linux
1746
         * arch/arm/mach-pxa/sleep.S expects two instructions following
1747
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
1748
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
1749
                (insn & 0x0fff0fff) != 0x0e010f10)
1750
            gen_lookup_tb(s);
1751
    }
1752
    return 0;
1753
}
1754

    
1755
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
1756
#define VFP_SREG(insn, bigbit, smallbit) \
1757
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
1758
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
1759
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
1760
        reg = (((insn) >> (bigbit)) & 0x0f) \
1761
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
1762
    } else { \
1763
        if (insn & (1 << (smallbit))) \
1764
            return 1; \
1765
        reg = ((insn) >> (bigbit)) & 0x0f; \
1766
    }} while (0)
1767

    
1768
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
1769
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
1770
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
1771
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
1772
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
1773
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
1774

    
1775
static inline int
1776
vfp_enabled(CPUState * env)
1777
{
1778
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
1779
}
1780

    
1781
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
1782
   (ie. an undefined instruction).  */
1783
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
1784
{
1785
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
1786
    int dp, veclen;
1787

    
1788
    if (!arm_feature(env, ARM_FEATURE_VFP))
1789
        return 1;
1790

    
1791
    if (!vfp_enabled(env)) {
1792
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
1793
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
1794
            return 1;
1795
        rn = (insn >> 16) & 0xf;
1796
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
1797
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
1798
            return 1;
1799
    }
1800
    dp = ((insn & 0xf00) == 0xb00);
1801
    switch ((insn >> 24) & 0xf) {
1802
    case 0xe:
1803
        if (insn & (1 << 4)) {
1804
            /* single register transfer */
1805
            rd = (insn >> 12) & 0xf;
1806
            if (dp) {
1807
                int size;
1808
                int pass;
1809

    
1810
                VFP_DREG_N(rn, insn);
1811
                if (insn & 0xf)
1812
                    return 1;
1813
                if (insn & 0x00c00060
1814
                    && !arm_feature(env, ARM_FEATURE_NEON))
1815
                    return 1;
1816

    
1817
                pass = (insn >> 21) & 1;
1818
                if (insn & (1 << 22)) {
1819
                    size = 0;
1820
                    offset = ((insn >> 5) & 3) * 8;
1821
                } else if (insn & (1 << 5)) {
1822
                    size = 1;
1823
                    offset = (insn & (1 << 6)) ? 16 : 0;
1824
                } else {
1825
                    size = 2;
1826
                    offset = 0;
1827
                }
1828
                if (insn & ARM_CP_RW_BIT) {
1829
                    /* vfp->arm */
1830
                    switch (size) {
1831
                    case 0:
1832
                        NEON_GET_REG(T1, rn, pass);
1833
                        if (offset)
1834
                            gen_op_shrl_T1_im(offset);
1835
                        if (insn & (1 << 23))
1836
                            gen_op_uxtb_T1();
1837
                        else
1838
                            gen_op_sxtb_T1();
1839
                        break;
1840
                    case 1:
1841
                        NEON_GET_REG(T1, rn, pass);
1842
                        if (insn & (1 << 23)) {
1843
                            if (offset) {
1844
                                gen_op_shrl_T1_im(16);
1845
                            } else {
1846
                                gen_op_uxth_T1();
1847
                            }
1848
                        } else {
1849
                            if (offset) {
1850
                                gen_op_sarl_T1_im(16);
1851
                            } else {
1852
                                gen_op_sxth_T1();
1853
                            }
1854
                        }
1855
                        break;
1856
                    case 2:
1857
                        NEON_GET_REG(T1, rn, pass);
1858
                        break;
1859
                    }
1860
                    gen_movl_reg_T1(s, rd);
1861
                } else {
1862
                    /* arm->vfp */
1863
                    gen_movl_T0_reg(s, rd);
1864
                    if (insn & (1 << 23)) {
1865
                        /* VDUP */
1866
                        if (size == 0) {
1867
                            gen_op_neon_dup_u8(0);
1868
                        } else if (size == 1) {
1869
                            gen_op_neon_dup_low16();
1870
                        }
1871
                        NEON_SET_REG(T0, rn, 0);
1872
                        NEON_SET_REG(T0, rn, 1);
1873
                    } else {
1874
                        /* VMOV */
1875
                        switch (size) {
1876
                        case 0:
1877
                            NEON_GET_REG(T2, rn, pass);
1878
                            gen_op_movl_T1_im(0xff);
1879
                            gen_op_andl_T0_T1();
1880
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
1881
                            NEON_SET_REG(T2, rn, pass);
1882
                            break;
1883
                        case 1:
1884
                            NEON_GET_REG(T2, rn, pass);
1885
                            gen_op_movl_T1_im(0xffff);
1886
                            gen_op_andl_T0_T1();
1887
                            bank_mask = offset ? 0xffff : 0xffff0000;
1888
                            gen_op_neon_insert_elt(offset, bank_mask);
1889
                            NEON_SET_REG(T2, rn, pass);
1890
                            break;
1891
                        case 2:
1892
                            NEON_SET_REG(T0, rn, pass);
1893
                            break;
1894
                        }
1895
                    }
1896
                }
1897
            } else { /* !dp */
1898
                if ((insn & 0x6f) != 0x00)
1899
                    return 1;
1900
                rn = VFP_SREG_N(insn);
1901
                if (insn & ARM_CP_RW_BIT) {
1902
                    /* vfp->arm */
1903
                    if (insn & (1 << 21)) {
1904
                        /* system register */
1905
                        rn >>= 1;
1906

    
1907
                        switch (rn) {
1908
                        case ARM_VFP_FPSID:
1909
                            /* VFP2 allows access for FSID from userspace.
1910
                               VFP3 restricts all id registers to privileged
1911
                               accesses.  */
1912
                            if (IS_USER(s)
1913
                                && arm_feature(env, ARM_FEATURE_VFP3))
1914
                                return 1;
1915
                            gen_op_vfp_movl_T0_xreg(rn);
1916
                            break;
1917
                        case ARM_VFP_FPEXC:
1918
                            if (IS_USER(s))
1919
                                return 1;
1920
                            gen_op_vfp_movl_T0_xreg(rn);
1921
                            break;
1922
                        case ARM_VFP_FPINST:
1923
                        case ARM_VFP_FPINST2:
1924
                            /* Not present in VFP3.  */
1925
                            if (IS_USER(s)
1926
                                || arm_feature(env, ARM_FEATURE_VFP3))
1927
                                return 1;
1928
                            gen_op_vfp_movl_T0_xreg(rn);
1929
                            break;
1930
                        case ARM_VFP_FPSCR:
1931
                            if (rd == 15)
1932
                                gen_op_vfp_movl_T0_fpscr_flags();
1933
                            else
1934
                                gen_op_vfp_movl_T0_fpscr();
1935
                            break;
1936
                        case ARM_VFP_MVFR0:
1937
                        case ARM_VFP_MVFR1:
1938
                            if (IS_USER(s)
1939
                                || !arm_feature(env, ARM_FEATURE_VFP3))
1940
                                return 1;
1941
                            gen_op_vfp_movl_T0_xreg(rn);
1942
                            break;
1943
                        default:
1944
                            return 1;
1945
                        }
1946
                    } else {
1947
                        gen_mov_F0_vreg(0, rn);
1948
                        gen_op_vfp_mrs();
1949
                    }
1950
                    if (rd == 15) {
1951
                        /* Set the 4 flag bits in the CPSR.  */
1952
                        gen_op_movl_cpsr_T0(0xf0000000);
1953
                    } else
1954
                        gen_movl_reg_T0(s, rd);
1955
                } else {
1956
                    /* arm->vfp */
1957
                    gen_movl_T0_reg(s, rd);
1958
                    if (insn & (1 << 21)) {
1959
                        rn >>= 1;
1960
                        /* system register */
1961
                        switch (rn) {
1962
                        case ARM_VFP_FPSID:
1963
                        case ARM_VFP_MVFR0:
1964
                        case ARM_VFP_MVFR1:
1965
                            /* Writes are ignored.  */
1966
                            break;
1967
                        case ARM_VFP_FPSCR:
1968
                            gen_op_vfp_movl_fpscr_T0();
1969
                            gen_lookup_tb(s);
1970
                            break;
1971
                        case ARM_VFP_FPEXC:
1972
                            if (IS_USER(s))
1973
                                return 1;
1974
                            gen_op_vfp_movl_xreg_T0(rn);
1975
                            gen_lookup_tb(s);
1976
                            break;
1977
                        case ARM_VFP_FPINST:
1978
                        case ARM_VFP_FPINST2:
1979
                            gen_op_vfp_movl_xreg_T0(rn);
1980
                            break;
1981
                        default:
1982
                            return 1;
1983
                        }
1984
                    } else {
1985
                        gen_op_vfp_msr();
1986
                        gen_mov_vreg_F0(0, rn);
1987
                    }
1988
                }
1989
            }
1990
        } else {
1991
            /* data processing */
1992
            /* The opcode is in bits 23, 21, 20 and 6.  */
1993
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
1994
            if (dp) {
1995
                if (op == 15) {
1996
                    /* rn is opcode */
1997
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
1998
                } else {
1999
                    /* rn is register number */
2000
                    VFP_DREG_N(rn, insn);
2001
                }
2002

    
2003
                if (op == 15 && (rn == 15 || rn > 17)) {
2004
                    /* Integer or single precision destination.  */
2005
                    rd = VFP_SREG_D(insn);
2006
                } else {
2007
                    VFP_DREG_D(rd, insn);
2008
                }
2009

    
2010
                if (op == 15 && (rn == 16 || rn == 17)) {
2011
                    /* Integer source.  */
2012
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2013
                } else {
2014
                    VFP_DREG_M(rm, insn);
2015
                }
2016
            } else {
2017
                rn = VFP_SREG_N(insn);
2018
                if (op == 15 && rn == 15) {
2019
                    /* Double precision destination.  */
2020
                    VFP_DREG_D(rd, insn);
2021
                } else {
2022
                    rd = VFP_SREG_D(insn);
2023
                }
2024
                rm = VFP_SREG_M(insn);
2025
            }
2026

    
2027
            veclen = env->vfp.vec_len;
2028
            if (op == 15 && rn > 3)
2029
                veclen = 0;
2030

    
2031
            /* Shut up compiler warnings.  */
2032
            delta_m = 0;
2033
            delta_d = 0;
2034
            bank_mask = 0;
2035

    
2036
            if (veclen > 0) {
2037
                if (dp)
2038
                    bank_mask = 0xc;
2039
                else
2040
                    bank_mask = 0x18;
2041

    
2042
                /* Figure out what type of vector operation this is.  */
2043
                if ((rd & bank_mask) == 0) {
2044
                    /* scalar */
2045
                    veclen = 0;
2046
                } else {
2047
                    if (dp)
2048
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2049
                    else
2050
                        delta_d = env->vfp.vec_stride + 1;
2051

    
2052
                    if ((rm & bank_mask) == 0) {
2053
                        /* mixed scalar/vector */
2054
                        delta_m = 0;
2055
                    } else {
2056
                        /* vector */
2057
                        delta_m = delta_d;
2058
                    }
2059
                }
2060
            }
2061

    
2062
            /* Load the initial operands.  */
2063
            if (op == 15) {
2064
                switch (rn) {
2065
                case 16:
2066
                case 17:
2067
                    /* Integer source */
2068
                    gen_mov_F0_vreg(0, rm);
2069
                    break;
2070
                case 8:
2071
                case 9:
2072
                    /* Compare */
2073
                    gen_mov_F0_vreg(dp, rd);
2074
                    gen_mov_F1_vreg(dp, rm);
2075
                    break;
2076
                case 10:
2077
                case 11:
2078
                    /* Compare with zero */
2079
                    gen_mov_F0_vreg(dp, rd);
2080
                    gen_vfp_F1_ld0(dp);
2081
                    break;
2082
                case 20:
2083
                case 21:
2084
                case 22:
2085
                case 23:
2086
                    /* Source and destination the same.  */
2087
                    gen_mov_F0_vreg(dp, rd);
2088
                    break;
2089
                default:
2090
                    /* One source operand.  */
2091
                    gen_mov_F0_vreg(dp, rm);
2092
                    break;
2093
                }
2094
            } else {
2095
                /* Two source operands.  */
2096
                gen_mov_F0_vreg(dp, rn);
2097
                gen_mov_F1_vreg(dp, rm);
2098
            }
2099

    
2100
            for (;;) {
2101
                /* Perform the calculation.  */
2102
                switch (op) {
2103
                case 0: /* mac: fd + (fn * fm) */
2104
                    gen_vfp_mul(dp);
2105
                    gen_mov_F1_vreg(dp, rd);
2106
                    gen_vfp_add(dp);
2107
                    break;
2108
                case 1: /* nmac: fd - (fn * fm) */
2109
                    gen_vfp_mul(dp);
2110
                    gen_vfp_neg(dp);
2111
                    gen_mov_F1_vreg(dp, rd);
2112
                    gen_vfp_add(dp);
2113
                    break;
2114
                case 2: /* msc: -fd + (fn * fm) */
2115
                    gen_vfp_mul(dp);
2116
                    gen_mov_F1_vreg(dp, rd);
2117
                    gen_vfp_sub(dp);
2118
                    break;
2119
                case 3: /* nmsc: -fd - (fn * fm)  */
2120
                    gen_vfp_mul(dp);
2121
                    gen_mov_F1_vreg(dp, rd);
2122
                    gen_vfp_add(dp);
2123
                    gen_vfp_neg(dp);
2124
                    break;
2125
                case 4: /* mul: fn * fm */
2126
                    gen_vfp_mul(dp);
2127
                    break;
2128
                case 5: /* nmul: -(fn * fm) */
2129
                    gen_vfp_mul(dp);
2130
                    gen_vfp_neg(dp);
2131
                    break;
2132
                case 6: /* add: fn + fm */
2133
                    gen_vfp_add(dp);
2134
                    break;
2135
                case 7: /* sub: fn - fm */
2136
                    gen_vfp_sub(dp);
2137
                    break;
2138
                case 8: /* div: fn / fm */
2139
                    gen_vfp_div(dp);
2140
                    break;
2141
                case 14: /* fconst */
2142
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2143
                      return 1;
2144

    
2145
                    n = (insn << 12) & 0x80000000;
2146
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2147
                    if (dp) {
2148
                        if (i & 0x40)
2149
                            i |= 0x3f80;
2150
                        else
2151
                            i |= 0x4000;
2152
                        n |= i << 16;
2153
                    } else {
2154
                        if (i & 0x40)
2155
                            i |= 0x780;
2156
                        else
2157
                            i |= 0x800;
2158
                        n |= i << 19;
2159
                    }
2160
                    gen_vfp_fconst(dp, n);
2161
                    break;
2162
                case 15: /* extension space */
2163
                    switch (rn) {
2164
                    case 0: /* cpy */
2165
                        /* no-op */
2166
                        break;
2167
                    case 1: /* abs */
2168
                        gen_vfp_abs(dp);
2169
                        break;
2170
                    case 2: /* neg */
2171
                        gen_vfp_neg(dp);
2172
                        break;
2173
                    case 3: /* sqrt */
2174
                        gen_vfp_sqrt(dp);
2175
                        break;
2176
                    case 8: /* cmp */
2177
                        gen_vfp_cmp(dp);
2178
                        break;
2179
                    case 9: /* cmpe */
2180
                        gen_vfp_cmpe(dp);
2181
                        break;
2182
                    case 10: /* cmpz */
2183
                        gen_vfp_cmp(dp);
2184
                        break;
2185
                    case 11: /* cmpez */
2186
                        gen_vfp_F1_ld0(dp);
2187
                        gen_vfp_cmpe(dp);
2188
                        break;
2189
                    case 15: /* single<->double conversion */
2190
                        if (dp)
2191
                            gen_op_vfp_fcvtsd();
2192
                        else
2193
                            gen_op_vfp_fcvtds();
2194
                        break;
2195
                    case 16: /* fuito */
2196
                        gen_vfp_uito(dp);
2197
                        break;
2198
                    case 17: /* fsito */
2199
                        gen_vfp_sito(dp);
2200
                        break;
2201
                    case 20: /* fshto */
2202
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2203
                          return 1;
2204
                        gen_vfp_shto(dp, rm);
2205
                        break;
2206
                    case 21: /* fslto */
2207
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2208
                          return 1;
2209
                        gen_vfp_slto(dp, rm);
2210
                        break;
2211
                    case 22: /* fuhto */
2212
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2213
                          return 1;
2214
                        gen_vfp_uhto(dp, rm);
2215
                        break;
2216
                    case 23: /* fulto */
2217
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2218
                          return 1;
2219
                        gen_vfp_ulto(dp, rm);
2220
                        break;
2221
                    case 24: /* ftoui */
2222
                        gen_vfp_toui(dp);
2223
                        break;
2224
                    case 25: /* ftouiz */
2225
                        gen_vfp_touiz(dp);
2226
                        break;
2227
                    case 26: /* ftosi */
2228
                        gen_vfp_tosi(dp);
2229
                        break;
2230
                    case 27: /* ftosiz */
2231
                        gen_vfp_tosiz(dp);
2232
                        break;
2233
                    case 28: /* ftosh */
2234
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2235
                          return 1;
2236
                        gen_vfp_tosh(dp, rm);
2237
                        break;
2238
                    case 29: /* ftosl */
2239
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2240
                          return 1;
2241
                        gen_vfp_tosl(dp, rm);
2242
                        break;
2243
                    case 30: /* ftouh */
2244
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2245
                          return 1;
2246
                        gen_vfp_touh(dp, rm);
2247
                        break;
2248
                    case 31: /* ftoul */
2249
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2250
                          return 1;
2251
                        gen_vfp_toul(dp, rm);
2252
                        break;
2253
                    default: /* undefined */
2254
                        printf ("rn:%d\n", rn);
2255
                        return 1;
2256
                    }
2257
                    break;
2258
                default: /* undefined */
2259
                    printf ("op:%d\n", op);
2260
                    return 1;
2261
                }
2262

    
2263
                /* Write back the result.  */
2264
                if (op == 15 && (rn >= 8 && rn <= 11))
2265
                    ; /* Comparison, do nothing.  */
2266
                else if (op == 15 && rn > 17)
2267
                    /* Integer result.  */
2268
                    gen_mov_vreg_F0(0, rd);
2269
                else if (op == 15 && rn == 15)
2270
                    /* conversion */
2271
                    gen_mov_vreg_F0(!dp, rd);
2272
                else
2273
                    gen_mov_vreg_F0(dp, rd);
2274

    
2275
                /* break out of the loop if we have finished  */
2276
                if (veclen == 0)
2277
                    break;
2278

    
2279
                if (op == 15 && delta_m == 0) {
2280
                    /* single source one-many */
2281
                    while (veclen--) {
2282
                        rd = ((rd + delta_d) & (bank_mask - 1))
2283
                             | (rd & bank_mask);
2284
                        gen_mov_vreg_F0(dp, rd);
2285
                    }
2286
                    break;
2287
                }
2288
                /* Setup the next operands.  */
2289
                veclen--;
2290
                rd = ((rd + delta_d) & (bank_mask - 1))
2291
                     | (rd & bank_mask);
2292

    
2293
                if (op == 15) {
2294
                    /* One source operand.  */
2295
                    rm = ((rm + delta_m) & (bank_mask - 1))
2296
                         | (rm & bank_mask);
2297
                    gen_mov_F0_vreg(dp, rm);
2298
                } else {
2299
                    /* Two source operands.  */
2300
                    rn = ((rn + delta_d) & (bank_mask - 1))
2301
                         | (rn & bank_mask);
2302
                    gen_mov_F0_vreg(dp, rn);
2303
                    if (delta_m) {
2304
                        rm = ((rm + delta_m) & (bank_mask - 1))
2305
                             | (rm & bank_mask);
2306
                        gen_mov_F1_vreg(dp, rm);
2307
                    }
2308
                }
2309
            }
2310
        }
2311
        break;
2312
    case 0xc:
2313
    case 0xd:
2314
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2315
            /* two-register transfer */
2316
            rn = (insn >> 16) & 0xf;
2317
            rd = (insn >> 12) & 0xf;
2318
            if (dp) {
2319
                VFP_DREG_M(rm, insn);
2320
            } else {
2321
                rm = VFP_SREG_M(insn);
2322
            }
2323

    
2324
            if (insn & ARM_CP_RW_BIT) {
2325
                /* vfp->arm */
2326
                if (dp) {
2327
                    gen_mov_F0_vreg(1, rm);
2328
                    gen_op_vfp_mrrd();
2329
                    gen_movl_reg_T0(s, rd);
2330
                    gen_movl_reg_T1(s, rn);
2331
                } else {
2332
                    gen_mov_F0_vreg(0, rm);
2333
                    gen_op_vfp_mrs();
2334
                    gen_movl_reg_T0(s, rn);
2335
                    gen_mov_F0_vreg(0, rm + 1);
2336
                    gen_op_vfp_mrs();
2337
                    gen_movl_reg_T0(s, rd);
2338
                }
2339
            } else {
2340
                /* arm->vfp */
2341
                if (dp) {
2342
                    gen_movl_T0_reg(s, rd);
2343
                    gen_movl_T1_reg(s, rn);
2344
                    gen_op_vfp_mdrr();
2345
                    gen_mov_vreg_F0(1, rm);
2346
                } else {
2347
                    gen_movl_T0_reg(s, rn);
2348
                    gen_op_vfp_msr();
2349
                    gen_mov_vreg_F0(0, rm);
2350
                    gen_movl_T0_reg(s, rd);
2351
                    gen_op_vfp_msr();
2352
                    gen_mov_vreg_F0(0, rm + 1);
2353
                }
2354
            }
2355
        } else {
2356
            /* Load/store */
2357
            rn = (insn >> 16) & 0xf;
2358
            if (dp)
2359
                VFP_DREG_D(rd, insn);
2360
            else
2361
                rd = VFP_SREG_D(insn);
2362
            if (s->thumb && rn == 15) {
2363
                gen_op_movl_T1_im(s->pc & ~2);
2364
            } else {
2365
                gen_movl_T1_reg(s, rn);
2366
            }
2367
            if ((insn & 0x01200000) == 0x01000000) {
2368
                /* Single load/store */
2369
                offset = (insn & 0xff) << 2;
2370
                if ((insn & (1 << 23)) == 0)
2371
                    offset = -offset;
2372
                gen_op_addl_T1_im(offset);
2373
                if (insn & (1 << 20)) {
2374
                    gen_vfp_ld(s, dp);
2375
                    gen_mov_vreg_F0(dp, rd);
2376
                } else {
2377
                    gen_mov_F0_vreg(dp, rd);
2378
                    gen_vfp_st(s, dp);
2379
                }
2380
            } else {
2381
                /* load/store multiple */
2382
                if (dp)
2383
                    n = (insn >> 1) & 0x7f;
2384
                else
2385
                    n = insn & 0xff;
2386

    
2387
                if (insn & (1 << 24)) /* pre-decrement */
2388
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2389

    
2390
                if (dp)
2391
                    offset = 8;
2392
                else
2393
                    offset = 4;
2394
                for (i = 0; i < n; i++) {
2395
                    if (insn & ARM_CP_RW_BIT) {
2396
                        /* load */
2397
                        gen_vfp_ld(s, dp);
2398
                        gen_mov_vreg_F0(dp, rd + i);
2399
                    } else {
2400
                        /* store */
2401
                        gen_mov_F0_vreg(dp, rd + i);
2402
                        gen_vfp_st(s, dp);
2403
                    }
2404
                    gen_op_addl_T1_im(offset);
2405
                }
2406
                if (insn & (1 << 21)) {
2407
                    /* writeback */
2408
                    if (insn & (1 << 24))
2409
                        offset = -offset * n;
2410
                    else if (dp && (insn & 1))
2411
                        offset = 4;
2412
                    else
2413
                        offset = 0;
2414

    
2415
                    if (offset != 0)
2416
                        gen_op_addl_T1_im(offset);
2417
                    gen_movl_reg_T1(s, rn);
2418
                }
2419
            }
2420
        }
2421
        break;
2422
    default:
2423
        /* Should never happen.  */
2424
        return 1;
2425
    }
2426
    return 0;
2427
}
2428

    
2429
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2430
{
2431
    TranslationBlock *tb;
2432

    
2433
    tb = s->tb;
2434
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2435
        if (n == 0)
2436
            gen_op_goto_tb0(TBPARAM(tb));
2437
        else
2438
            gen_op_goto_tb1(TBPARAM(tb));
2439
        gen_op_movl_T0_im(dest);
2440
        gen_op_movl_r15_T0();
2441
        gen_op_movl_T0_im((long)tb + n);
2442
        gen_op_exit_tb();
2443
    } else {
2444
        gen_op_movl_T0_im(dest);
2445
        gen_op_movl_r15_T0();
2446
        gen_op_movl_T0_0();
2447
        gen_op_exit_tb();
2448
    }
2449
}
2450

    
2451
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2452
{
2453
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2454
        /* An indirect jump so that we still trigger the debug exception.  */
2455
        if (s->thumb)
2456
          dest |= 1;
2457
        gen_op_movl_T0_im(dest);
2458
        gen_bx(s);
2459
    } else {
2460
        gen_goto_tb(s, 0, dest);
2461
        s->is_jmp = DISAS_TB_JUMP;
2462
    }
2463
}
2464

    
2465
static inline void gen_mulxy(int x, int y)
2466
{
2467
    if (x)
2468
        gen_op_sarl_T0_im(16);
2469
    else
2470
        gen_op_sxth_T0();
2471
    if (y)
2472
        gen_op_sarl_T1_im(16);
2473
    else
2474
        gen_op_sxth_T1();
2475
    gen_op_mul_T0_T1();
2476
}
2477

    
2478
/* Return the mask of PSR bits set by a MSR instruction.  */
2479
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2480
    uint32_t mask;
2481

    
2482
    mask = 0;
2483
    if (flags & (1 << 0))
2484
        mask |= 0xff;
2485
    if (flags & (1 << 1))
2486
        mask |= 0xff00;
2487
    if (flags & (1 << 2))
2488
        mask |= 0xff0000;
2489
    if (flags & (1 << 3))
2490
        mask |= 0xff000000;
2491

    
2492
    /* Mask out undefined bits.  */
2493
    mask &= ~CPSR_RESERVED;
2494
    if (!arm_feature(env, ARM_FEATURE_V6))
2495
        mask &= ~(CPSR_E | CPSR_GE);
2496
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2497
        mask &= ~CPSR_IT;
2498
    /* Mask out execution state bits.  */
2499
    if (!spsr)
2500
        mask &= ~CPSR_EXEC;
2501
    /* Mask out privileged bits.  */
2502
    if (IS_USER(s))
2503
        mask &= CPSR_USER;
2504
    return mask;
2505
}
2506

    
2507
/* Returns nonzero if access to the PSR is not permitted.  */
2508
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2509
{
2510
    if (spsr) {
2511
        /* ??? This is also undefined in system mode.  */
2512
        if (IS_USER(s))
2513
            return 1;
2514
        gen_op_movl_spsr_T0(mask);
2515
    } else {
2516
        gen_op_movl_cpsr_T0(mask);
2517
    }
2518
    gen_lookup_tb(s);
2519
    return 0;
2520
}
2521

    
2522
/* Generate an old-style exception return.  */
2523
static void gen_exception_return(DisasContext *s)
2524
{
2525
    gen_op_movl_reg_TN[0][15]();
2526
    gen_op_movl_T0_spsr();
2527
    gen_op_movl_cpsr_T0(0xffffffff);
2528
    s->is_jmp = DISAS_UPDATE;
2529
}
2530

    
2531
/* Generate a v6 exception return.  */
2532
static void gen_rfe(DisasContext *s)
2533
{
2534
    gen_op_movl_cpsr_T0(0xffffffff);
2535
    gen_op_movl_T0_T2();
2536
    gen_op_movl_reg_TN[0][15]();
2537
    s->is_jmp = DISAS_UPDATE;
2538
}
2539

    
2540
static inline void
2541
gen_set_condexec (DisasContext *s)
2542
{
2543
    if (s->condexec_mask) {
2544
        gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1));
2545
    }
2546
}
2547

    
2548
static void gen_nop_hint(DisasContext *s, int val)
2549
{
2550
    switch (val) {
2551
    case 3: /* wfi */
2552
        gen_op_movl_T0_im((long)s->pc);
2553
        gen_op_movl_reg_TN[0][15]();
2554
        s->is_jmp = DISAS_WFI;
2555
        break;
2556
    case 2: /* wfe */
2557
    case 4: /* sev */
2558
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
2559
    default: /* nop */
2560
        break;
2561
    }
2562
}
2563

    
2564
/* Neon shift by constant.  The actual ops are the same as used for variable
2565
   shifts.  [OP][U][SIZE]  */
2566
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2567
    { /* 0 */ /* VSHR */
2568
      {
2569
        gen_op_neon_shl_u8,
2570
        gen_op_neon_shl_u16,
2571
        gen_op_neon_shl_u32,
2572
        gen_op_neon_shl_u64
2573
      }, {
2574
        gen_op_neon_shl_s8,
2575
        gen_op_neon_shl_s16,
2576
        gen_op_neon_shl_s32,
2577
        gen_op_neon_shl_s64
2578
      }
2579
    }, { /* 1 */ /* VSRA */
2580
      {
2581
        gen_op_neon_shl_u8,
2582
        gen_op_neon_shl_u16,
2583
        gen_op_neon_shl_u32,
2584
        gen_op_neon_shl_u64
2585
      }, {
2586
        gen_op_neon_shl_s8,
2587
        gen_op_neon_shl_s16,
2588
        gen_op_neon_shl_s32,
2589
        gen_op_neon_shl_s64
2590
      }
2591
    }, { /* 2 */ /* VRSHR */
2592
      {
2593
        gen_op_neon_rshl_u8,
2594
        gen_op_neon_rshl_u16,
2595
        gen_op_neon_rshl_u32,
2596
        gen_op_neon_rshl_u64
2597
      }, {
2598
        gen_op_neon_rshl_s8,
2599
        gen_op_neon_rshl_s16,
2600
        gen_op_neon_rshl_s32,
2601
        gen_op_neon_rshl_s64
2602
      }
2603
    }, { /* 3 */ /* VRSRA */
2604
      {
2605
        gen_op_neon_rshl_u8,
2606
        gen_op_neon_rshl_u16,
2607
        gen_op_neon_rshl_u32,
2608
        gen_op_neon_rshl_u64
2609
      }, {
2610
        gen_op_neon_rshl_s8,
2611
        gen_op_neon_rshl_s16,
2612
        gen_op_neon_rshl_s32,
2613
        gen_op_neon_rshl_s64
2614
      }
2615
    }, { /* 4 */
2616
      {
2617
        NULL, NULL, NULL, NULL
2618
      }, { /* VSRI */
2619
        gen_op_neon_shl_u8,
2620
        gen_op_neon_shl_u16,
2621
        gen_op_neon_shl_u32,
2622
        gen_op_neon_shl_u64,
2623
      }
2624
    }, { /* 5 */
2625
      { /* VSHL */
2626
        gen_op_neon_shl_u8,
2627
        gen_op_neon_shl_u16,
2628
        gen_op_neon_shl_u32,
2629
        gen_op_neon_shl_u64,
2630
      }, { /* VSLI */
2631
        gen_op_neon_shl_u8,
2632
        gen_op_neon_shl_u16,
2633
        gen_op_neon_shl_u32,
2634
        gen_op_neon_shl_u64,
2635
      }
2636
    }, { /* 6 */ /* VQSHL */
2637
      {
2638
        gen_op_neon_qshl_u8,
2639
        gen_op_neon_qshl_u16,
2640
        gen_op_neon_qshl_u32,
2641
        gen_op_neon_qshl_u64
2642
      }, {
2643
        gen_op_neon_qshl_s8,
2644
        gen_op_neon_qshl_s16,
2645
        gen_op_neon_qshl_s32,
2646
        gen_op_neon_qshl_s64
2647
      }
2648
    }, { /* 7 */ /* VQSHLU */
2649
      {
2650
        gen_op_neon_qshl_u8,
2651
        gen_op_neon_qshl_u16,
2652
        gen_op_neon_qshl_u32,
2653
        gen_op_neon_qshl_u64
2654
      }, {
2655
        gen_op_neon_qshl_u8,
2656
        gen_op_neon_qshl_u16,
2657
        gen_op_neon_qshl_u32,
2658
        gen_op_neon_qshl_u64
2659
      }
2660
    }
2661
};
2662

    
2663
/* [R][U][size - 1] */
2664
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2665
    {
2666
      {
2667
        gen_op_neon_shl_u16,
2668
        gen_op_neon_shl_u32,
2669
        gen_op_neon_shl_u64
2670
      }, {
2671
        gen_op_neon_shl_s16,
2672
        gen_op_neon_shl_s32,
2673
        gen_op_neon_shl_s64
2674
      }
2675
    }, {
2676
      {
2677
        gen_op_neon_rshl_u16,
2678
        gen_op_neon_rshl_u32,
2679
        gen_op_neon_rshl_u64
2680
      }, {
2681
        gen_op_neon_rshl_s16,
2682
        gen_op_neon_rshl_s32,
2683
        gen_op_neon_rshl_s64
2684
      }
2685
    }
2686
};
2687

    
2688
static inline void
2689
gen_op_neon_narrow_u32 ()
2690
{
2691
    /* No-op.  */
2692
}
2693

    
2694
static GenOpFunc *gen_neon_narrow[3] = {
2695
    gen_op_neon_narrow_u8,
2696
    gen_op_neon_narrow_u16,
2697
    gen_op_neon_narrow_u32
2698
};
2699

    
2700
static GenOpFunc *gen_neon_narrow_satu[3] = {
2701
    gen_op_neon_narrow_sat_u8,
2702
    gen_op_neon_narrow_sat_u16,
2703
    gen_op_neon_narrow_sat_u32
2704
};
2705

    
2706
static GenOpFunc *gen_neon_narrow_sats[3] = {
2707
    gen_op_neon_narrow_sat_s8,
2708
    gen_op_neon_narrow_sat_s16,
2709
    gen_op_neon_narrow_sat_s32
2710
};
2711

    
2712
static inline int gen_neon_add(int size)
2713
{
2714
    switch (size) {
2715
    case 0: gen_op_neon_add_u8(); break;
2716
    case 1: gen_op_neon_add_u16(); break;
2717
    case 2: gen_op_addl_T0_T1(); break;
2718
    default: return 1;
2719
    }
2720
    return 0;
2721
}
2722

    
2723
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
2724
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
2725
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
2726
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
2727
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
2728

    
2729
#define GEN_NEON_INTEGER_OP(name) do { \
2730
    switch ((size << 1) | u) { \
2731
    case 0: gen_op_neon_##name##_s8(); break; \
2732
    case 1: gen_op_neon_##name##_u8(); break; \
2733
    case 2: gen_op_neon_##name##_s16(); break; \
2734
    case 3: gen_op_neon_##name##_u16(); break; \
2735
    case 4: gen_op_neon_##name##_s32(); break; \
2736
    case 5: gen_op_neon_##name##_u32(); break; \
2737
    default: return 1; \
2738
    }} while (0)
2739

    
2740
static inline void
2741
gen_neon_movl_scratch_T0(int scratch)
2742
{
2743
  uint32_t offset;
2744

    
2745
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2746
  gen_op_neon_setreg_T0(offset);
2747
}
2748

    
2749
static inline void
2750
gen_neon_movl_scratch_T1(int scratch)
2751
{
2752
  uint32_t offset;
2753

    
2754
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2755
  gen_op_neon_setreg_T1(offset);
2756
}
2757

    
2758
static inline void
2759
gen_neon_movl_T0_scratch(int scratch)
2760
{
2761
  uint32_t offset;
2762

    
2763
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2764
  gen_op_neon_getreg_T0(offset);
2765
}
2766

    
2767
static inline void
2768
gen_neon_movl_T1_scratch(int scratch)
2769
{
2770
  uint32_t offset;
2771

    
2772
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2773
  gen_op_neon_getreg_T1(offset);
2774
}
2775

    
2776
static inline void gen_op_neon_widen_u32(void)
2777
{
2778
    gen_op_movl_T1_im(0);
2779
}
2780

    
2781
static inline void gen_neon_get_scalar(int size, int reg)
2782
{
2783
    if (size == 1) {
2784
        NEON_GET_REG(T0, reg >> 1, reg & 1);
2785
    } else {
2786
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
2787
        if (reg & 1)
2788
            gen_op_neon_dup_low16();
2789
        else
2790
            gen_op_neon_dup_high16();
2791
    }
2792
}
2793

    
2794
static void gen_neon_unzip(int reg, int q, int tmp, int size)
2795
{
2796
    int n;
2797

    
2798
    for (n = 0; n < q + 1; n += 2) {
2799
        NEON_GET_REG(T0, reg, n);
2800
        NEON_GET_REG(T0, reg, n + n);
2801
        switch (size) {
2802
        case 0: gen_op_neon_unzip_u8(); break;
2803
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
2804
        case 2: /* no-op */; break;
2805
        default: abort();
2806
        }
2807
        gen_neon_movl_scratch_T0(tmp + n);
2808
        gen_neon_movl_scratch_T1(tmp + n + 1);
2809
    }
2810
}
2811

    
2812
static struct {
2813
    int nregs;
2814
    int interleave;
2815
    int spacing;
2816
} neon_ls_element_type[11] = {
2817
    {4, 4, 1},
2818
    {4, 4, 2},
2819
    {4, 1, 1},
2820
    {4, 2, 1},
2821
    {3, 3, 1},
2822
    {3, 3, 2},
2823
    {3, 1, 1},
2824
    {1, 1, 1},
2825
    {2, 2, 1},
2826
    {2, 2, 2},
2827
    {2, 1, 1}
2828
};
2829

    
2830
/* Translate a NEON load/store element instruction.  Return nonzero if the
2831
   instruction is invalid.  */
2832
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
2833
{
2834
    int rd, rn, rm;
2835
    int op;
2836
    int nregs;
2837
    int interleave;
2838
    int stride;
2839
    int size;
2840
    int reg;
2841
    int pass;
2842
    int load;
2843
    int shift;
2844
    uint32_t mask;
2845
    int n;
2846

    
2847
    if (!vfp_enabled(env))
2848
      return 1;
2849
    VFP_DREG_D(rd, insn);
2850
    rn = (insn >> 16) & 0xf;
2851
    rm = insn & 0xf;
2852
    load = (insn & (1 << 21)) != 0;
2853
    if ((insn & (1 << 23)) == 0) {
2854
        /* Load store all elements.  */
2855
        op = (insn >> 8) & 0xf;
2856
        size = (insn >> 6) & 3;
2857
        if (op > 10 || size == 3)
2858
            return 1;
2859
        nregs = neon_ls_element_type[op].nregs;
2860
        interleave = neon_ls_element_type[op].interleave;
2861
        gen_movl_T1_reg(s, rn);
2862
        stride = (1 << size) * interleave;
2863
        for (reg = 0; reg < nregs; reg++) {
2864
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
2865
                gen_movl_T1_reg(s, rn);
2866
                gen_op_addl_T1_im((1 << size) * reg);
2867
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
2868
                gen_movl_T1_reg(s, rn);
2869
                gen_op_addl_T1_im(1 << size);
2870
            }
2871
            for (pass = 0; pass < 2; pass++) {
2872
                if (size == 2) {
2873
                    if (load) {
2874
                        gen_ldst(ldl, s);
2875
                        NEON_SET_REG(T0, rd, pass);
2876
                    } else {
2877
                        NEON_GET_REG(T0, rd, pass);
2878
                        gen_ldst(stl, s);
2879
                    }
2880
                    gen_op_addl_T1_im(stride);
2881
                } else if (size == 1) {
2882
                    if (load) {
2883
                        gen_ldst(lduw, s);
2884
                        gen_op_addl_T1_im(stride);
2885
                        gen_op_movl_T2_T0();
2886
                        gen_ldst(lduw, s);
2887
                        gen_op_addl_T1_im(stride);
2888
                        gen_op_neon_insert_elt(16, 0xffff);
2889
                        NEON_SET_REG(T2, rd, pass);
2890
                    } else {
2891
                        NEON_GET_REG(T2, rd, pass);
2892
                        gen_op_movl_T0_T2();
2893
                        gen_ldst(stw, s);
2894
                        gen_op_addl_T1_im(stride);
2895
                        gen_op_neon_extract_elt(16, 0xffff0000);
2896
                        gen_ldst(stw, s);
2897
                        gen_op_addl_T1_im(stride);
2898
                    }
2899
                } else /* size == 0 */ {
2900
                    if (load) {
2901
                        mask = 0xff;
2902
                        for (n = 0; n < 4; n++) {
2903
                            gen_ldst(ldub, s);
2904
                            gen_op_addl_T1_im(stride);
2905
                            if (n == 0) {
2906
                                gen_op_movl_T2_T0();
2907
                            } else {
2908
                                gen_op_neon_insert_elt(n * 8, ~mask);
2909
                            }
2910
                            mask <<= 8;
2911
                        }
2912
                        NEON_SET_REG(T2, rd, pass);
2913
                    } else {
2914
                        NEON_GET_REG(T2, rd, pass);
2915
                        mask = 0xff;
2916
                        for (n = 0; n < 4; n++) {
2917
                            if (n == 0) {
2918
                                gen_op_movl_T0_T2();
2919
                            } else {
2920
                                gen_op_neon_extract_elt(n * 8, mask);
2921
                            }
2922
                            gen_ldst(stb, s);
2923
                            gen_op_addl_T1_im(stride);
2924
                            mask <<= 8;
2925
                        }
2926
                    }
2927
                }
2928
            }
2929
            rd += neon_ls_element_type[op].spacing;
2930
        }
2931
        stride = nregs * 8;
2932
    } else {
2933
        size = (insn >> 10) & 3;
2934
        if (size == 3) {
2935
            /* Load single element to all lanes.  */
2936
            if (!load)
2937
                return 1;
2938
            size = (insn >> 6) & 3;
2939
            nregs = ((insn >> 8) & 3) + 1;
2940
            stride = (insn & (1 << 5)) ? 2 : 1;
2941
            gen_movl_T1_reg(s, rn);
2942
            for (reg = 0; reg < nregs; reg++) {
2943
                switch (size) {
2944
                case 0:
2945
                    gen_ldst(ldub, s);
2946
                    gen_op_neon_dup_u8(0);
2947
                    break;
2948
                case 1:
2949
                    gen_ldst(lduw, s);
2950
                    gen_op_neon_dup_low16();
2951
                    break;
2952
                case 2:
2953
                    gen_ldst(ldl, s);
2954
                    break;
2955
                case 3:
2956
                    return 1;
2957
                }
2958
                gen_op_addl_T1_im(1 << size);
2959
                NEON_SET_REG(T0, rd, 0);
2960
                NEON_SET_REG(T0, rd, 1);
2961
                rd += stride;
2962
            }
2963
            stride = (1 << size) * nregs;
2964
        } else {
2965
            /* Single element.  */
2966
            pass = (insn >> 7) & 1;
2967
            switch (size) {
2968
            case 0:
2969
                shift = ((insn >> 5) & 3) * 8;
2970
                mask = 0xff << shift;
2971
                stride = 1;
2972
                break;
2973
            case 1:
2974
                shift = ((insn >> 6) & 1) * 16;
2975
                mask = shift ? 0xffff0000 : 0xffff;
2976
                stride = (insn & (1 << 5)) ? 2 : 1;
2977
                break;
2978
            case 2:
2979
                shift = 0;
2980
                mask = 0xffffffff;
2981
                stride = (insn & (1 << 6)) ? 2 : 1;
2982
                break;
2983
            default:
2984
                abort();
2985
            }
2986
            nregs = ((insn >> 8) & 3) + 1;
2987
            gen_movl_T1_reg(s, rn);
2988
            for (reg = 0; reg < nregs; reg++) {
2989
                if (load) {
2990
                    if (size != 2) {
2991
                        NEON_GET_REG(T2, rd, pass);
2992
                    }
2993
                    switch (size) {
2994
                    case 0:
2995
                        gen_ldst(ldub, s);
2996
                        break;
2997
                    case 1:
2998
                        gen_ldst(lduw, s);
2999
                        break;
3000
                    case 2:
3001
                        gen_ldst(ldl, s);
3002
                        NEON_SET_REG(T0, rd, pass);
3003
                        break;
3004
                    }
3005
                    if (size != 2) {
3006
                        gen_op_neon_insert_elt(shift, ~mask);
3007
                        NEON_SET_REG(T0, rd, pass);
3008
                    }
3009
                } else { /* Store */
3010
                    if (size == 2) {
3011
                        NEON_GET_REG(T0, rd, pass);
3012
                    } else {
3013
                        NEON_GET_REG(T2, rd, pass);
3014
                        gen_op_neon_extract_elt(shift, mask);
3015
                    }
3016
                    switch (size) {
3017
                    case 0:
3018
                        gen_ldst(stb, s);
3019
                        break;
3020
                    case 1:
3021
                        gen_ldst(stw, s);
3022
                        break;
3023
                    case 2:
3024
                        gen_ldst(stl, s);
3025
                        break;
3026
                    }
3027
                }
3028
                rd += stride;
3029
                gen_op_addl_T1_im(1 << size);
3030
            }
3031
            stride = nregs * (1 << size);
3032
        }
3033
    }
3034
    if (rm != 15) {
3035
        gen_movl_T1_reg(s, rn);
3036
        if (rm == 13) {
3037
            gen_op_addl_T1_im(stride);
3038
        } else {
3039
            gen_movl_T2_reg(s, rm);
3040
            gen_op_addl_T1_T2();
3041
        }
3042
        gen_movl_reg_T1(s, rn);
3043
    }
3044
    return 0;
3045
}
3046

    
3047
/* Translate a NEON data processing instruction.  Return nonzero if the
3048
   instruction is invalid.
3049
   In general we process vectors in 32-bit chunks.  This means we can reuse
3050
   some of the scalar ops, and hopefully the code generated for 32-bit
3051
   hosts won't be too awful.  The downside is that the few 64-bit operations
3052
   (mainly shifts) get complicated.  */
3053

    
3054
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3055
{
3056
    int op;
3057
    int q;
3058
    int rd, rn, rm;
3059
    int size;
3060
    int shift;
3061
    int pass;
3062
    int count;
3063
    int pairwise;
3064
    int u;
3065
    int n;
3066
    uint32_t imm;
3067

    
3068
    if (!vfp_enabled(env))
3069
      return 1;
3070
    q = (insn & (1 << 6)) != 0;
3071
    u = (insn >> 24) & 1;
3072
    VFP_DREG_D(rd, insn);
3073
    VFP_DREG_N(rn, insn);
3074
    VFP_DREG_M(rm, insn);
3075
    size = (insn >> 20) & 3;
3076
    if ((insn & (1 << 23)) == 0) {
3077
        /* Three register same length.  */
3078
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3079
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3080
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3081
                NEON_GET_REG(T0, rm, pass * 2);
3082
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3083
                gen_neon_movl_scratch_T0(0);
3084
                gen_neon_movl_scratch_T1(1);
3085
                NEON_GET_REG(T0, rn, pass * 2);
3086
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3087
                switch (op) {
3088
                case 1: /* VQADD */
3089
                    if (u) {
3090
                        gen_op_neon_addl_saturate_u64();
3091
                    } else {
3092
                        gen_op_neon_addl_saturate_s64();
3093
                    }
3094
                    break;
3095
                case 5: /* VQSUB */
3096
                    if (u) {
3097
                        gen_op_neon_subl_saturate_u64();
3098
                    } else {
3099
                        gen_op_neon_subl_saturate_s64();
3100
                    }
3101
                    break;
3102
                case 16:
3103
                    if (u) {
3104
                        gen_op_neon_subl_u64();
3105
                    } else {
3106
                        gen_op_neon_addl_u64();
3107
                    }
3108
                    break;
3109
                default:
3110
                    abort();
3111
                }
3112
                NEON_SET_REG(T0, rd, pass * 2);
3113
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3114
            }
3115
            return 0;
3116
        }
3117
        switch (op) {
3118
        case 8: /* VSHL */
3119
        case 9: /* VQSHL */
3120
        case 10: /* VRSHL */
3121
        case 11: /* VQSHL */
3122
            /* Shift operations have Rn and Rm reversed.  */
3123
            {
3124
                int tmp;
3125
                tmp = rn;
3126
                rn = rm;
3127
                rm = tmp;
3128
                pairwise = 0;
3129
            }
3130
            break;
3131
        case 20: /* VPMAX */
3132
        case 21: /* VPMIN */
3133
        case 23: /* VPADD */
3134
            pairwise = 1;
3135
            break;
3136
        case 26: /* VPADD (float) */
3137
            pairwise = (u && size < 2);
3138
            break;
3139
        case 30: /* VPMIN/VPMAX (float) */
3140
            pairwise = u;
3141
            break;
3142
        default:
3143
            pairwise = 0;
3144
            break;
3145
        }
3146
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3147

    
3148
        if (pairwise) {
3149
            /* Pairwise.  */
3150
            if (q)
3151
                n = (pass & 1) * 2;
3152
            else
3153
                n = 0;
3154
            if (pass < q + 1) {
3155
                NEON_GET_REG(T0, rn, n);
3156
                NEON_GET_REG(T1, rn, n + 1);
3157
            } else {
3158
                NEON_GET_REG(T0, rm, n);
3159
                NEON_GET_REG(T1, rm, n + 1);
3160
            }
3161
        } else {
3162
            /* Elementwise.  */
3163
            NEON_GET_REG(T0, rn, pass);
3164
            NEON_GET_REG(T1, rm, pass);
3165
        }
3166
        switch (op) {
3167
        case 0: /* VHADD */
3168
            GEN_NEON_INTEGER_OP(hadd);
3169
            break;
3170
        case 1: /* VQADD */
3171
            switch (size << 1| u) {
3172
            case 0: gen_op_neon_qadd_s8(); break;
3173
            case 1: gen_op_neon_qadd_u8(); break;
3174
            case 2: gen_op_neon_qadd_s16(); break;
3175
            case 3: gen_op_neon_qadd_u16(); break;
3176
            case 4: gen_op_addl_T0_T1_saturate(); break;
3177
            case 5: gen_op_addl_T0_T1_usaturate(); break;
3178
            default: abort();
3179
            }
3180
            break;
3181
        case 2: /* VRHADD */
3182
            GEN_NEON_INTEGER_OP(rhadd);
3183
            break;
3184
        case 3: /* Logic ops.  */
3185
            switch ((u << 2) | size) {
3186
            case 0: /* VAND */
3187
                gen_op_andl_T0_T1();
3188
                break;
3189
            case 1: /* BIC */
3190
                gen_op_bicl_T0_T1();
3191
                break;
3192
            case 2: /* VORR */
3193
                gen_op_orl_T0_T1();
3194
                break;
3195
            case 3: /* VORN */
3196
                gen_op_notl_T1();
3197
                gen_op_orl_T0_T1();
3198
                break;
3199
            case 4: /* VEOR */
3200
                gen_op_xorl_T0_T1();
3201
                break;
3202
            case 5: /* VBSL */
3203
                NEON_GET_REG(T2, rd, pass);
3204
                gen_op_neon_bsl();
3205
                break;
3206
            case 6: /* VBIT */
3207
                NEON_GET_REG(T2, rd, pass);
3208
                gen_op_neon_bit();
3209
                break;
3210
            case 7: /* VBIF */
3211
                NEON_GET_REG(T2, rd, pass);
3212
                gen_op_neon_bif();
3213
                break;
3214
            }
3215
            break;
3216
        case 4: /* VHSUB */
3217
            GEN_NEON_INTEGER_OP(hsub);
3218
            break;
3219
        case 5: /* VQSUB */
3220
            switch ((size << 1) | u) {
3221
            case 0: gen_op_neon_qsub_s8(); break;
3222
            case 1: gen_op_neon_qsub_u8(); break;
3223
            case 2: gen_op_neon_qsub_s16(); break;
3224
            case 3: gen_op_neon_qsub_u16(); break;
3225
            case 4: gen_op_subl_T0_T1_saturate(); break;
3226
            case 5: gen_op_subl_T0_T1_usaturate(); break;
3227
            default: abort();
3228
            }
3229
            break;
3230
        case 6: /* VCGT */
3231
            GEN_NEON_INTEGER_OP(cgt);
3232
            break;
3233
        case 7: /* VCGE */
3234
            GEN_NEON_INTEGER_OP(cge);
3235
            break;
3236
        case 8: /* VSHL */
3237
            switch ((size << 1) | u) {
3238
            case 0: gen_op_neon_shl_s8(); break;
3239
            case 1: gen_op_neon_shl_u8(); break;
3240
            case 2: gen_op_neon_shl_s16(); break;
3241
            case 3: gen_op_neon_shl_u16(); break;
3242
            case 4: gen_op_neon_shl_s32(); break;
3243
            case 5: gen_op_neon_shl_u32(); break;
3244
#if 0
3245
            /* ??? Implementing these is tricky because the vector ops work
3246
               on 32-bit pieces.  */
3247
            case 6: gen_op_neon_shl_s64(); break;
3248
            case 7: gen_op_neon_shl_u64(); break;
3249
#else
3250
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3251
#endif
3252
            }
3253
            break;
3254
        case 9: /* VQSHL */
3255
            switch ((size << 1) | u) {
3256
            case 0: gen_op_neon_qshl_s8(); break;
3257
            case 1: gen_op_neon_qshl_u8(); break;
3258
            case 2: gen_op_neon_qshl_s16(); break;
3259
            case 3: gen_op_neon_qshl_u16(); break;
3260
            case 4: gen_op_neon_qshl_s32(); break;
3261
            case 5: gen_op_neon_qshl_u32(); break;
3262
#if 0
3263
            /* ??? Implementing these is tricky because the vector ops work
3264
               on 32-bit pieces.  */
3265
            case 6: gen_op_neon_qshl_s64(); break;
3266
            case 7: gen_op_neon_qshl_u64(); break;
3267
#else
3268
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3269
#endif
3270
            }
3271
            break;
3272
        case 10: /* VRSHL */
3273
            switch ((size << 1) | u) {
3274
            case 0: gen_op_neon_rshl_s8(); break;
3275
            case 1: gen_op_neon_rshl_u8(); break;
3276
            case 2: gen_op_neon_rshl_s16(); break;
3277
            case 3: gen_op_neon_rshl_u16(); break;
3278
            case 4: gen_op_neon_rshl_s32(); break;
3279
            case 5: gen_op_neon_rshl_u32(); break;
3280
#if 0
3281
            /* ??? Implementing these is tricky because the vector ops work
3282
               on 32-bit pieces.  */
3283
            case 6: gen_op_neon_rshl_s64(); break;
3284
            case 7: gen_op_neon_rshl_u64(); break;
3285
#else
3286
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3287
#endif
3288
            }
3289
            break;
3290
        case 11: /* VQRSHL */
3291
            switch ((size << 1) | u) {
3292
            case 0: gen_op_neon_qrshl_s8(); break;
3293
            case 1: gen_op_neon_qrshl_u8(); break;
3294
            case 2: gen_op_neon_qrshl_s16(); break;
3295
            case 3: gen_op_neon_qrshl_u16(); break;
3296
            case 4: gen_op_neon_qrshl_s32(); break;
3297
            case 5: gen_op_neon_qrshl_u32(); break;
3298
#if 0
3299
            /* ??? Implementing these is tricky because the vector ops work
3300
               on 32-bit pieces.  */
3301
            case 6: gen_op_neon_qrshl_s64(); break;
3302
            case 7: gen_op_neon_qrshl_u64(); break;
3303
#else
3304
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3305
#endif
3306
            }
3307
            break;
3308
        case 12: /* VMAX */
3309
            GEN_NEON_INTEGER_OP(max);
3310
            break;
3311
        case 13: /* VMIN */
3312
            GEN_NEON_INTEGER_OP(min);
3313
            break;
3314
        case 14: /* VABD */
3315
            GEN_NEON_INTEGER_OP(abd);
3316
            break;
3317
        case 15: /* VABA */
3318
            GEN_NEON_INTEGER_OP(abd);
3319
            NEON_GET_REG(T1, rd, pass);
3320
            gen_neon_add(size);
3321
            break;
3322
        case 16:
3323
            if (!u) { /* VADD */
3324
                if (gen_neon_add(size))
3325
                    return 1;
3326
            } else { /* VSUB */
3327
                switch (size) {
3328
                case 0: gen_op_neon_sub_u8(); break;
3329
                case 1: gen_op_neon_sub_u16(); break;
3330
                case 2: gen_op_subl_T0_T1(); break;
3331
                default: return 1;
3332
                }
3333
            }
3334
            break;
3335
        case 17:
3336
            if (!u) { /* VTST */
3337
                switch (size) {
3338
                case 0: gen_op_neon_tst_u8(); break;
3339
                case 1: gen_op_neon_tst_u16(); break;
3340
                case 2: gen_op_neon_tst_u32(); break;
3341
                default: return 1;
3342
                }
3343
            } else { /* VCEQ */
3344
                switch (size) {
3345
                case 0: gen_op_neon_ceq_u8(); break;
3346
                case 1: gen_op_neon_ceq_u16(); break;
3347
                case 2: gen_op_neon_ceq_u32(); break;
3348
                default: return 1;
3349
                }
3350
            }
3351
            break;
3352
        case 18: /* Multiply.  */
3353
            switch (size) {
3354
            case 0: gen_op_neon_mul_u8(); break;
3355
            case 1: gen_op_neon_mul_u16(); break;
3356
            case 2: gen_op_mul_T0_T1(); break;
3357
            default: return 1;
3358
            }
3359
            NEON_GET_REG(T1, rd, pass);
3360
            if (u) { /* VMLS */
3361
                switch (size) {
3362
                case 0: gen_op_neon_rsb_u8(); break;
3363
                case 1: gen_op_neon_rsb_u16(); break;
3364
                case 2: gen_op_rsbl_T0_T1(); break;
3365
                default: return 1;
3366
                }
3367
            } else { /* VMLA */
3368
                gen_neon_add(size);
3369
            }
3370
            break;
3371
        case 19: /* VMUL */
3372
            if (u) { /* polynomial */
3373
                gen_op_neon_mul_p8();
3374
            } else { /* Integer */
3375
                switch (size) {
3376
                case 0: gen_op_neon_mul_u8(); break;
3377
                case 1: gen_op_neon_mul_u16(); break;
3378
                case 2: gen_op_mul_T0_T1(); break;
3379
                default: return 1;
3380
                }
3381
            }
3382
            break;
3383
        case 20: /* VPMAX */
3384
            GEN_NEON_INTEGER_OP(pmax);
3385
            break;
3386
        case 21: /* VPMIN */
3387
            GEN_NEON_INTEGER_OP(pmin);
3388
            break;
3389
        case 22: /* Hultiply high.  */
3390
            if (!u) { /* VQDMULH */
3391
                switch (size) {
3392
                case 1: gen_op_neon_qdmulh_s16(); break;
3393
                case 2: gen_op_neon_qdmulh_s32(); break;
3394
                default: return 1;
3395
                }
3396
            } else { /* VQRDHMUL */
3397
                switch (size) {
3398
                case 1: gen_op_neon_qrdmulh_s16(); break;
3399
                case 2: gen_op_neon_qrdmulh_s32(); break;
3400
                default: return 1;
3401
                }
3402
            }
3403
            break;
3404
        case 23: /* VPADD */
3405
            if (u)
3406
                return 1;
3407
            switch (size) {
3408
            case 0: gen_op_neon_padd_u8(); break;
3409
            case 1: gen_op_neon_padd_u16(); break;
3410
            case 2: gen_op_addl_T0_T1(); break;
3411
            default: return 1;
3412
            }
3413
            break;
3414
        case 26: /* Floating point arithnetic.  */
3415
            switch ((u << 2) | size) {
3416
            case 0: /* VADD */
3417
                gen_op_neon_add_f32();
3418
                break;
3419
            case 2: /* VSUB */
3420
                gen_op_neon_sub_f32();
3421
                break;
3422
            case 4: /* VPADD */
3423
                gen_op_neon_add_f32();
3424
                break;
3425
            case 6: /* VABD */
3426
                gen_op_neon_abd_f32();
3427
                break;
3428
            default:
3429
                return 1;
3430
            }
3431
            break;
3432
        case 27: /* Float multiply.  */
3433
            gen_op_neon_mul_f32();
3434
            if (!u) {
3435
                NEON_GET_REG(T1, rd, pass);
3436
                if (size == 0) {
3437
                    gen_op_neon_add_f32();
3438
                } else {
3439
                    gen_op_neon_rsb_f32();
3440
                }
3441
            }
3442
            break;
3443
        case 28: /* Float compare.  */
3444
            if (!u) {
3445
                gen_op_neon_ceq_f32();
3446
            } else {
3447
                if (size == 0)
3448
                    gen_op_neon_cge_f32();
3449
                else
3450
                    gen_op_neon_cgt_f32();
3451
            }
3452
            break;
3453
        case 29: /* Float compare absolute.  */
3454
            if (!u)
3455
                return 1;
3456
            if (size == 0)
3457
                gen_op_neon_acge_f32();
3458
            else
3459
                gen_op_neon_acgt_f32();
3460
            break;
3461
        case 30: /* Float min/max.  */
3462
            if (size == 0)
3463
                gen_op_neon_max_f32();
3464
            else
3465
                gen_op_neon_min_f32();
3466
            break;
3467
        case 31:
3468
            if (size == 0)
3469
                gen_op_neon_recps_f32();
3470
            else
3471
                gen_op_neon_rsqrts_f32();
3472
            break;
3473
        default:
3474
            abort();
3475
        }
3476
        /* Save the result.  For elementwise operations we can put it
3477
           straight into the destination register.  For pairwise operations
3478
           we have to be careful to avoid clobbering the source operands.  */
3479
        if (pairwise && rd == rm) {
3480
            gen_neon_movl_scratch_T0(pass);
3481
        } else {
3482
            NEON_SET_REG(T0, rd, pass);
3483
        }
3484

    
3485
        } /* for pass */
3486
        if (pairwise && rd == rm) {
3487
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3488
                gen_neon_movl_T0_scratch(pass);
3489
                NEON_SET_REG(T0, rd, pass);
3490
            }
3491
        }
3492
    } else if (insn & (1 << 4)) {
3493
        if ((insn & 0x00380080) != 0) {
3494
            /* Two registers and shift.  */
3495
            op = (insn >> 8) & 0xf;
3496
            if (insn & (1 << 7)) {
3497
                /* 64-bit shift.   */
3498
                size = 3;
3499
            } else {
3500
                size = 2;
3501
                while ((insn & (1 << (size + 19))) == 0)
3502
                    size--;
3503
            }
3504
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3505
            /* To avoid excessive dumplication of ops we implement shift
3506
               by immediate using the variable shift operations.  */
3507
            if (op < 8) {
3508
                /* Shift by immediate:
3509
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
3510
                /* Right shifts are encoded as N - shift, where N is the
3511
                   element size in bits.  */
3512
                if (op <= 4)
3513
                    shift = shift - (1 << (size + 3));
3514
                else
3515
                    shift++;
3516
                if (size == 3) {
3517
                    count = q + 1;
3518
                } else {
3519
                    count = q ? 4: 2;
3520
                }
3521
                switch (size) {
3522
                case 0:
3523
                    imm = (uint8_t) shift;
3524
                    imm |= imm << 8;
3525
                    imm |= imm << 16;
3526
                    break;
3527
                case 1:
3528
                    imm = (uint16_t) shift;
3529
                    imm |= imm << 16;
3530
                    break;
3531
                case 2:
3532
                case 3:
3533
                    imm = shift;
3534
                    break;
3535
                default:
3536
                    abort();
3537
                }
3538

    
3539
                for (pass = 0; pass < count; pass++) {
3540
                    if (size < 3) {
3541
                        /* Operands in T0 and T1.  */
3542
                        gen_op_movl_T1_im(imm);
3543
                        NEON_GET_REG(T0, rm, pass);
3544
                    } else {
3545
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3546
                        gen_op_movl_T0_im(imm);
3547
                        gen_neon_movl_scratch_T0(0);
3548
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3549
                        gen_neon_movl_scratch_T0(1);
3550
                        NEON_GET_REG(T0, rm, pass * 2);
3551
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
3552
                    }
3553

    
3554
                    if (gen_neon_shift_im[op][u][size] == NULL)
3555
                        return 1;
3556
                    gen_neon_shift_im[op][u][size]();
3557

    
3558
                    if (op == 1 || op == 3) {
3559
                        /* Accumulate.  */
3560
                        if (size == 3) {
3561
                            gen_neon_movl_scratch_T0(0);
3562
                            gen_neon_movl_scratch_T1(1);
3563
                            NEON_GET_REG(T0, rd, pass * 2);
3564
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
3565
                            gen_op_neon_addl_u64();
3566
                        } else {
3567
                            NEON_GET_REG(T1, rd, pass);
3568
                            gen_neon_add(size);
3569
                        }
3570
                    } else if (op == 4 || (op == 5 && u)) {
3571
                        /* Insert */
3572
                        if (size == 3) {
3573
                            cpu_abort(env, "VS[LR]I.64 not implemented");
3574
                        }
3575
                        switch (size) {
3576
                        case 0:
3577
                            if (op == 4)
3578
                                imm = 0xff >> -shift;
3579
                            else
3580
                                imm = (uint8_t)(0xff << shift);
3581
                            imm |= imm << 8;
3582
                            imm |= imm << 16;
3583
                            break;
3584
                        case 1:
3585
                            if (op == 4)
3586
                                imm = 0xffff >> -shift;
3587
                            else
3588
                                imm = (uint16_t)(0xffff << shift);
3589
                            imm |= imm << 16;
3590
                            break;
3591
                        case 2:
3592
                            if (op == 4)
3593
                                imm = 0xffffffffu >> -shift;
3594
                            else
3595
                                imm = 0xffffffffu << shift;
3596
                            break;
3597
                        default:
3598
                            abort();
3599
                        }
3600
                        NEON_GET_REG(T1, rd, pass);
3601
                        gen_op_movl_T2_im(imm);
3602
                        gen_op_neon_bsl();
3603
                    }
3604
                    if (size == 3) {
3605
                        NEON_SET_REG(T0, rd, pass * 2);
3606
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
3607
                    } else {
3608
                        NEON_SET_REG(T0, rd, pass);
3609
                    }
3610
                } /* for pass */
3611
            } else if (op < 10) {
3612
                /* Shift by immedaiate and narrow:
3613
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
3614
                shift = shift - (1 << (size + 3));
3615
                size++;
3616
                if (size == 3) {
3617
                    count = q + 1;
3618
                } else {
3619
                    count = q ? 4: 2;
3620
                }
3621
                switch (size) {
3622
                case 1:
3623
                    imm = (uint16_t) shift;
3624
                    imm |= imm << 16;
3625
                    break;
3626
                case 2:
3627
                case 3:
3628
                    imm = shift;
3629
                    break;
3630
                default:
3631
                    abort();
3632
                }
3633

    
3634
                /* Processing MSB first means we need to do less shuffling at
3635
                   the end.  */
3636
                for (pass =  count - 1; pass >= 0; pass--) {
3637
                    /* Avoid clobbering the second operand before it has been
3638
                       written.  */
3639
                    n = pass;
3640
                    if (rd == rm)
3641
                        n ^= (count - 1);
3642
                    else
3643
                        n = pass;
3644

    
3645
                    if (size < 3) {
3646
                        /* Operands in T0 and T1.  */
3647
                        gen_op_movl_T1_im(imm);
3648
                        NEON_GET_REG(T0, rm, n);
3649
                    } else {
3650
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3651
                        gen_op_movl_T0_im(imm);
3652
                        gen_neon_movl_scratch_T0(0);
3653
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3654
                        gen_neon_movl_scratch_T0(1);
3655
                        NEON_GET_REG(T0, rm, n * 2);
3656
                        NEON_GET_REG(T0, rm, n * 2 + 1);
3657
                    }
3658

    
3659
                    gen_neon_shift_im_narrow[q][u][size - 1]();
3660

    
3661
                    if (size < 3 && (pass & 1) == 0) {
3662
                        gen_neon_movl_scratch_T0(0);
3663
                    } else {
3664
                        uint32_t offset;
3665

    
3666
                        if (size < 3)
3667
                            gen_neon_movl_T1_scratch(0);
3668

    
3669
                        if (op == 8 && !u) {
3670
                            gen_neon_narrow[size - 1]();
3671
                        } else {
3672
                            if (op == 8)
3673
                                gen_neon_narrow_sats[size - 2]();
3674
                            else
3675
                                gen_neon_narrow_satu[size - 1]();
3676
                        }
3677
                        if (size == 3)
3678
                            offset = neon_reg_offset(rd, n);
3679
                        else
3680
                            offset = neon_reg_offset(rd, n >> 1);
3681
                        gen_op_neon_setreg_T0(offset);
3682
                    }
3683
                } /* for pass */
3684
            } else if (op == 10) {
3685
                /* VSHLL */
3686
                if (q)
3687
                    return 1;
3688
                for (pass = 0; pass < 2; pass++) {
3689
                    /* Avoid clobbering the input operand.  */
3690
                    if (rd == rm)
3691
                        n = 1 - pass;
3692
                    else
3693
                        n = pass;
3694

    
3695
                    NEON_GET_REG(T0, rm, n);
3696
                    GEN_NEON_INTEGER_OP(widen);
3697
                    if (shift != 0) {
3698
                        /* The shift is less than the width of the source
3699
                           type, so in some cases we can just
3700
                           shift the whole register.  */
3701
                        if (size == 1 || (size == 0 && u)) {
3702
                            gen_op_shll_T0_im(shift);
3703
                            gen_op_shll_T1_im(shift);
3704
                        } else {
3705
                            switch (size) {
3706
                            case 0: gen_op_neon_shll_u16(shift); break;
3707
                            case 2: gen_op_neon_shll_u64(shift); break;
3708
                            default: abort();
3709
                            }
3710
                        }
3711
                    }
3712
                    NEON_SET_REG(T0, rd, n * 2);
3713
                    NEON_SET_REG(T1, rd, n * 2 + 1);
3714
                }
3715
            } else if (op == 15 || op == 16) {
3716
                /* VCVT fixed-point.  */
3717
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
3718
                    gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
3719
                    if (op & 1) {
3720
                        if (u)
3721
                            gen_op_vfp_ultos(shift);
3722
                        else
3723
                            gen_op_vfp_sltos(shift);
3724
                    } else {
3725
                        if (u)
3726
                            gen_op_vfp_touls(shift);
3727
                        else
3728
                            gen_op_vfp_tosls(shift);
3729
                    }
3730
                    gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
3731
                }
3732
            } else {
3733
                return 1;
3734
            }
3735
        } else { /* (insn & 0x00380080) == 0 */
3736
            int invert;
3737

    
3738
            op = (insn >> 8) & 0xf;
3739
            /* One register and immediate.  */
3740
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
3741
            invert = (insn & (1 << 5)) != 0;
3742
            switch (op) {
3743
            case 0: case 1:
3744
                /* no-op */
3745
                break;
3746
            case 2: case 3:
3747
                imm <<= 8;
3748
                break;
3749
            case 4: case 5:
3750
                imm <<= 16;
3751
                break;
3752
            case 6: case 7:
3753
                imm <<= 24;
3754
                break;
3755
            case 8: case 9:
3756
                imm |= imm << 16;
3757
                break;
3758
            case 10: case 11:
3759
                imm = (imm << 8) | (imm << 24);
3760
                break;
3761
            case 12:
3762
                imm = (imm < 8) | 0xff;
3763
                break;
3764
            case 13:
3765
                imm = (imm << 16) | 0xffff;
3766
                break;
3767
            case 14:
3768
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
3769
                if (invert)
3770
                    imm = ~imm;
3771
                break;
3772
            case 15:
3773
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
3774
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
3775
                break;
3776
            }
3777
            if (invert)
3778
                imm = ~imm;
3779

    
3780
            if (op != 14 || !invert)
3781
                gen_op_movl_T1_im(imm);
3782

    
3783
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3784
                if (op & 1 && op < 12) {
3785
                    NEON_GET_REG(T0, rd, pass);
3786
                    if (invert) {
3787
                        /* The immediate value has already been inverted, so
3788
                           BIC becomes AND.  */
3789
                        gen_op_andl_T0_T1();
3790
                    } else {
3791
                        gen_op_orl_T0_T1();
3792
                    }
3793
                    NEON_SET_REG(T0, rd, pass);
3794
                } else {
3795
                    if (op == 14 && invert) {
3796
                        uint32_t tmp;
3797
                        tmp = 0;
3798
                        for (n = 0; n < 4; n++) {
3799
                            if (imm & (1 << (n + (pass & 1) * 4)))
3800
                                tmp |= 0xff << (n * 8);
3801
                        }
3802
                        gen_op_movl_T1_im(tmp);
3803
                    }
3804
                    /* VMOV, VMVN.  */
3805
                    NEON_SET_REG(T1, rd, pass);
3806
                }
3807
            }
3808
        }
3809
    } else { /* (insn & 0x00800010 == 0x00800010) */
3810
        if (size != 3) {
3811
            op = (insn >> 8) & 0xf;
3812
            if ((insn & (1 << 6)) == 0) {
3813
                /* Three registers of different lengths.  */
3814
                int src1_wide;
3815
                int src2_wide;
3816
                int prewiden;
3817
                /* prewiden, src1_wide, src2_wide */
3818
                static const int neon_3reg_wide[16][3] = {
3819
                    {1, 0, 0}, /* VADDL */
3820
                    {1, 1, 0}, /* VADDW */
3821
                    {1, 0, 0}, /* VSUBL */
3822
                    {1, 1, 0}, /* VSUBW */
3823
                    {0, 1, 1}, /* VADDHN */
3824
                    {0, 0, 0}, /* VABAL */
3825
                    {0, 1, 1}, /* VSUBHN */
3826
                    {0, 0, 0}, /* VABDL */
3827
                    {0, 0, 0}, /* VMLAL */
3828
                    {0, 0, 0}, /* VQDMLAL */
3829
                    {0, 0, 0}, /* VMLSL */
3830
                    {0, 0, 0}, /* VQDMLSL */
3831
                    {0, 0, 0}, /* Integer VMULL */
3832
                    {0, 0, 0}, /* VQDMULL */
3833
                    {0, 0, 0}  /* Polynomial VMULL */
3834
                };
3835

    
3836
                prewiden = neon_3reg_wide[op][0];
3837
                src1_wide = neon_3reg_wide[op][1];
3838
                src2_wide = neon_3reg_wide[op][2];
3839

    
3840
                /* Avoid overlapping operands.  Wide source operands are
3841
                   always aligned so will never overlap with wide
3842
                   destinations in problematic ways.  */
3843
                if (rd == rm) {
3844
                    NEON_GET_REG(T2, rm, 1);
3845
                } else if (rd == rn) {
3846
                    NEON_GET_REG(T2, rn, 1);
3847
                }
3848
                for (pass = 0; pass < 2; pass++) {
3849
                    /* Load the second operand into env->vfp.scratch.
3850
                       Also widen narrow operands.  */
3851
                    if (pass == 1 && rd == rm) {
3852
                        if (prewiden) {
3853
                            gen_op_movl_T0_T2();
3854
                        } else {
3855
                            gen_op_movl_T1_T2();
3856
                        }
3857
                    } else {
3858
                        if (src2_wide) {
3859
                            NEON_GET_REG(T0, rm, pass * 2);
3860
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
3861
                        } else {
3862
                            if (prewiden) {
3863
                                NEON_GET_REG(T0, rm, pass);
3864
                            } else {
3865
                                NEON_GET_REG(T1, rm, pass);
3866
                            }
3867
                        }
3868
                    }
3869
                    if (prewiden && !src2_wide) {
3870
                        GEN_NEON_INTEGER_OP(widen);
3871
                    }
3872
                    if (prewiden || src2_wide) {
3873
                        gen_neon_movl_scratch_T0(0);
3874
                        gen_neon_movl_scratch_T1(1);
3875
                    }
3876

    
3877
                    /* Load the first operand.  */
3878
                    if (pass == 1 && rd == rn) {
3879
                        gen_op_movl_T0_T2();
3880
                    } else {
3881
                        if (src1_wide) {
3882
                            NEON_GET_REG(T0, rn, pass * 2);
3883
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
3884
                        } else {
3885
                            NEON_GET_REG(T0, rn, pass);
3886
                        }
3887
                    }
3888
                    if (prewiden && !src1_wide) {
3889
                        GEN_NEON_INTEGER_OP(widen);
3890
                    }
3891
                    switch (op) {
3892
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
3893
                        switch (size) {
3894
                        case 0: gen_op_neon_addl_u16(); break;
3895
                        case 1: gen_op_neon_addl_u32(); break;
3896
                        case 2: gen_op_neon_addl_u64(); break;
3897
                        default: abort();
3898
                        }
3899
                        break;
3900
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
3901
                        switch (size) {
3902
                        case 0: gen_op_neon_subl_u16(); break;
3903
                        case 1: gen_op_neon_subl_u32(); break;
3904
                        case 2: gen_op_neon_subl_u64(); break;
3905
                        default: abort();
3906
                        }
3907
                        break;
3908
                    case 5: case 7: /* VABAL, VABDL */
3909
                        switch ((size << 1) | u) {
3910
                        case 0: gen_op_neon_abdl_s16(); break;
3911
                        case 1: gen_op_neon_abdl_u16(); break;
3912
                        case 2: gen_op_neon_abdl_s32(); break;
3913
                        case 3: gen_op_neon_abdl_u32(); break;
3914
                        case 4: gen_op_neon_abdl_s64(); break;
3915
                        case 5: gen_op_neon_abdl_u64(); break;
3916
                        default: abort();
3917
                        }
3918
                        break;
3919
                    case 8: case 9: case 10: case 11: case 12: case 13:
3920
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
3921
                        switch ((size << 1) | u) {
3922
                        case 0: gen_op_neon_mull_s8(); break;
3923
                        case 1: gen_op_neon_mull_u8(); break;
3924
                        case 2: gen_op_neon_mull_s16(); break;
3925
                        case 3: gen_op_neon_mull_u16(); break;
3926
                        case 4: gen_op_imull_T0_T1(); break;
3927
                        case 5: gen_op_mull_T0_T1(); break;
3928
                        default: abort();
3929
                        }
3930
                        break;
3931
                    case 14: /* Polynomial VMULL */
3932
                        cpu_abort(env, "Polynomial VMULL not implemented");
3933

    
3934
                    default: /* 15 is RESERVED.  */
3935
                        return 1;
3936
                    }
3937
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
3938
                        /* Accumulate.  */
3939
                        if (op == 10 || op == 11) {
3940
                            switch (size) {
3941
                            case 0: gen_op_neon_negl_u16(); break;
3942
                            case 1: gen_op_neon_negl_u32(); break;
3943
                            case 2: gen_op_neon_negl_u64(); break;
3944
                            default: abort();
3945
                            }
3946
                        }
3947

    
3948
                        gen_neon_movl_scratch_T0(0);
3949
                        gen_neon_movl_scratch_T1(1);
3950

    
3951
                        if (op != 13) {
3952
                            NEON_GET_REG(T0, rd, pass * 2);
3953
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
3954
                        }
3955

    
3956
                        switch (op) {
3957
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
3958
                            switch (size) {
3959
                            case 0: gen_op_neon_addl_u16(); break;
3960
                            case 1: gen_op_neon_addl_u32(); break;
3961
                            case 2: gen_op_neon_addl_u64(); break;
3962
                            default: abort();
3963
                            }
3964
                            break;
3965
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
3966
                            switch (size) {
3967
                            case 1: gen_op_neon_addl_saturate_s32(); break;
3968
                            case 2: gen_op_neon_addl_saturate_s64(); break;
3969
                            default: abort();
3970
                            }
3971
                            /* Fall through.  */
3972
                        case 13: /* VQDMULL */
3973
                            switch (size) {
3974
                            case 1: gen_op_neon_addl_saturate_s32(); break;
3975
                            case 2: gen_op_neon_addl_saturate_s64(); break;
3976
                            default: abort();
3977
                            }
3978
                            break;
3979
                        default:
3980
                            abort();
3981
                        }
3982
                        NEON_SET_REG(T0, rd, pass * 2);
3983
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
3984
                    } else if (op == 4 || op == 6) {
3985
                        /* Narrowing operation.  */
3986
                        if (u) {
3987
                            switch (size) {
3988
                            case 0: gen_op_neon_narrow_high_u8(); break;
3989
                            case 1: gen_op_neon_narrow_high_u16(); break;
3990
                            case 2: gen_op_movl_T0_T1(); break;
3991
                            default: abort();
3992
                            }
3993
                        } else {
3994
                            switch (size) {
3995
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
3996
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
3997
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
3998
                            default: abort();
3999
                            }
4000
                        }
4001
                        NEON_SET_REG(T0, rd, pass);
4002
                    } else {
4003
                        /* Write back the result.  */
4004
                        NEON_SET_REG(T0, rd, pass * 2);
4005
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4006
                    }
4007
                }
4008
            } else {
4009
                /* Two registers and a scalar.  */
4010
                switch (op) {
4011
                case 0: /* Integer VMLA scalar */
4012
                case 1: /* Float VMLA scalar */
4013
                case 4: /* Integer VMLS scalar */
4014
                case 5: /* Floating point VMLS scalar */
4015
                case 8: /* Integer VMUL scalar */
4016
                case 9: /* Floating point VMUL scalar */
4017
                case 12: /* VQDMULH scalar */
4018
                case 13: /* VQRDMULH scalar */
4019
                    gen_neon_get_scalar(size, rm);
4020
                    gen_op_movl_T2_T0();
4021
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4022
                        if (pass != 0)
4023
                            gen_op_movl_T0_T2();
4024
                        NEON_GET_REG(T1, rn, pass);
4025
                        if (op == 12) {
4026
                            if (size == 1) {
4027
                                gen_op_neon_qdmulh_s16();
4028
                            } else {
4029
                                gen_op_neon_qdmulh_s32();
4030
                            }
4031
                        } else if (op == 13) {
4032
                            if (size == 1) {
4033
                                gen_op_neon_qrdmulh_s16();
4034
                            } else {
4035
                                gen_op_neon_qrdmulh_s32();
4036
                            }
4037
                        } else if (op & 1) {
4038
                            gen_op_neon_mul_f32();
4039
                        } else {
4040
                            switch (size) {
4041
                            case 0: gen_op_neon_mul_u8(); break;
4042
                            case 1: gen_op_neon_mul_u16(); break;
4043
                            case 2: gen_op_mul_T0_T1(); break;
4044
                            default: return 1;
4045
                            }
4046
                        }
4047
                        if (op < 8) {
4048
                            /* Accumulate.  */
4049
                            NEON_GET_REG(T1, rd, pass);
4050
                            switch (op) {
4051
                            case 0:
4052
                                gen_neon_add(size);
4053
                                break;
4054
                            case 1:
4055
                                gen_op_neon_add_f32();
4056
                                break;
4057
                            case 4:
4058
                                switch (size) {
4059
                                case 0: gen_op_neon_rsb_u8(); break;
4060
                                case 1: gen_op_neon_rsb_u16(); break;
4061
                                case 2: gen_op_rsbl_T0_T1(); break;
4062
                                default: return 1;
4063
                                }
4064
                                break;
4065
                            case 5:
4066
                                gen_op_neon_rsb_f32();
4067
                                break;
4068
                            default:
4069
                                abort();
4070
                            }
4071
                        }
4072
                        NEON_SET_REG(T0, rd, pass);
4073
                    }
4074
                    break;
4075
                case 2: /* VMLAL sclar */
4076
                case 3: /* VQDMLAL scalar */
4077
                case 6: /* VMLSL scalar */
4078
                case 7: /* VQDMLSL scalar */
4079
                case 10: /* VMULL scalar */
4080
                case 11: /* VQDMULL scalar */
4081
                    if (rd == rn) {
4082
                        /* Save overlapping operands before they are
4083
                           clobbered.  */
4084
                        NEON_GET_REG(T0, rn, 1);
4085
                        gen_neon_movl_scratch_T0(2);
4086
                    }
4087
                    gen_neon_get_scalar(size, rm);
4088
                    gen_op_movl_T2_T0();
4089
                    for (pass = 0; pass < 2; pass++) {
4090
                        if (pass != 0) {
4091
                            gen_op_movl_T0_T2();
4092
                        }
4093
                        if (pass != 0 && rd == rn) {
4094
                            gen_neon_movl_T1_scratch(2);
4095
                        } else {
4096
                            NEON_GET_REG(T1, rn, pass);
4097
                        }
4098
                        switch ((size << 1) | u) {
4099
                        case 0: gen_op_neon_mull_s8(); break;
4100
                        case 1: gen_op_neon_mull_u8(); break;
4101
                        case 2: gen_op_neon_mull_s16(); break;
4102
                        case 3: gen_op_neon_mull_u16(); break;
4103
                        case 4: gen_op_imull_T0_T1(); break;
4104
                        case 5: gen_op_mull_T0_T1(); break;
4105
                        default: abort();
4106
                        }
4107
                        if (op == 6 || op == 7) {
4108
                            switch (size) {
4109
                            case 0: gen_op_neon_negl_u16(); break;
4110
                            case 1: gen_op_neon_negl_u32(); break;
4111
                            case 2: gen_op_neon_negl_u64(); break;
4112
                            default: abort();
4113
                            }
4114
                        }
4115
                        gen_neon_movl_scratch_T0(0);
4116
                        gen_neon_movl_scratch_T1(1);
4117
                        NEON_GET_REG(T0, rd, pass * 2);
4118
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4119
                        switch (op) {
4120
                        case 2: case 6:
4121
                            switch (size) {
4122
                            case 0: gen_op_neon_addl_u16(); break;
4123
                            case 1: gen_op_neon_addl_u32(); break;
4124
                            case 2: gen_op_neon_addl_u64(); break;
4125
                            default: abort();
4126
                            }
4127
                            break;
4128
                        case 3: case 7:
4129
                            switch (size) {
4130
                            case 1:
4131
                                gen_op_neon_addl_saturate_s32();
4132
                                gen_op_neon_addl_saturate_s32();
4133
                                break;
4134
                            case 2:
4135
                                gen_op_neon_addl_saturate_s64();
4136
                                gen_op_neon_addl_saturate_s64();
4137
                                break;
4138
                            default: abort();
4139
                            }
4140
                            break;
4141
                        case 10:
4142
                            /* no-op */
4143
                            break;
4144
                        case 11:
4145
                            switch (size) {
4146
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4147
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4148
                            default: abort();
4149
                            }
4150
                            break;
4151
                        default:
4152
                            abort();
4153
                        }
4154
                        NEON_SET_REG(T0, rd, pass * 2);
4155
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4156
                    }
4157
                    break;
4158
                default: /* 14 and 15 are RESERVED */
4159
                    return 1;
4160
                }
4161
            }
4162
        } else { /* size == 3 */
4163
            if (!u) {
4164
                /* Extract.  */
4165
                int reg;
4166
                imm = (insn >> 8) & 0xf;
4167
                reg = rn;
4168
                count = q ? 4 : 2;
4169
                n = imm >> 2;
4170
                NEON_GET_REG(T0, reg, n);
4171
                for (pass = 0; pass < count; pass++) {
4172
                    n++;
4173
                    if (n > count) {
4174
                        reg = rm;
4175
                        n -= count;
4176
                    }
4177
                    if (imm & 3) {
4178
                        NEON_GET_REG(T1, reg, n);
4179
                        gen_op_neon_extract((insn << 3) & 0x1f);
4180
                    }
4181
                    /* ??? This is broken if rd and rm overlap */
4182
                    NEON_SET_REG(T0, rd, pass);
4183
                    if (imm & 3) {
4184
                        gen_op_movl_T0_T1();
4185
                    } else {
4186
                        NEON_GET_REG(T0, reg, n);
4187
                    }
4188
                }
4189
            } else if ((insn & (1 << 11)) == 0) {
4190
                /* Two register misc.  */
4191
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4192
                size = (insn >> 18) & 3;
4193
                switch (op) {
4194
                case 0: /* VREV64 */
4195
                    if (size == 3)
4196
                        return 1;
4197
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4198
                        NEON_GET_REG(T0, rm, pass * 2);
4199
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4200
                        switch (size) {
4201
                        case 0: gen_op_rev_T0(); break;
4202
                        case 1: gen_op_revh_T0(); break;
4203
                        case 2: /* no-op */ break;
4204
                        default: abort();
4205
                        }
4206
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4207
                        if (size == 2) {
4208
                            NEON_SET_REG(T1, rd, pass * 2);
4209
                        } else {
4210
                            gen_op_movl_T0_T1();
4211
                            switch (size) {
4212
                            case 0: gen_op_rev_T0(); break;
4213
                            case 1: gen_op_revh_T0(); break;
4214
                            default: abort();
4215
                            }
4216
                            NEON_SET_REG(T0, rd, pass * 2);
4217
                        }
4218
                    }
4219
                    break;
4220
                case 4: case 5: /* VPADDL */
4221
                case 12: case 13: /* VPADAL */
4222
                    if (size < 2)
4223
                        goto elementwise;
4224
                    if (size == 3)
4225
                        return 1;
4226
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4227
                        NEON_GET_REG(T0, rm, pass * 2);
4228
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4229
                        if (op & 1)
4230
                            gen_op_neon_paddl_u32();
4231
                        else
4232
                            gen_op_neon_paddl_s32();
4233
                        if (op >= 12) {
4234
                            /* Accumulate.  */
4235
                            gen_neon_movl_scratch_T0(0);
4236
                            gen_neon_movl_scratch_T1(1);
4237

    
4238
                            NEON_GET_REG(T0, rd, pass * 2);
4239
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4240
                            gen_op_neon_addl_u64();
4241
                        }
4242
                        NEON_SET_REG(T0, rd, pass * 2);
4243
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4244
                    }
4245
                    break;
4246
                case 33: /* VTRN */
4247
                    if (size == 2) {
4248
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4249
                            NEON_GET_REG(T0, rm, n);
4250
                            NEON_GET_REG(T1, rd, n + 1);
4251
                            NEON_SET_REG(T1, rm, n);
4252
                            NEON_SET_REG(T0, rd, n + 1);
4253
                        }
4254
                    } else {
4255
                        goto elementwise;
4256
                    }
4257
                    break;
4258
                case 34: /* VUZP */
4259
                    /* Reg  Before       After
4260
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4261
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4262
                     */
4263
                    if (size == 3)
4264
                        return 1;
4265
                    gen_neon_unzip(rd, q, 0, size);
4266
                    gen_neon_unzip(rm, q, 4, size);
4267
                    if (q) {
4268
                        static int unzip_order_q[8] =
4269
                            {0, 2, 4, 6, 1, 3, 5, 7};
4270
                        for (n = 0; n < 8; n++) {
4271
                            int reg = (n < 4) ? rd : rm;
4272
                            gen_neon_movl_T0_scratch(unzip_order_q[n]);
4273
                            NEON_SET_REG(T0, reg, n % 4);
4274
                        }
4275
                    } else {
4276
                        static int unzip_order[4] =
4277
                            {0, 4, 1, 5};
4278
                        for (n = 0; n < 4; n++) {
4279
                            int reg = (n < 2) ? rd : rm;
4280
                            gen_neon_movl_T0_scratch(unzip_order[n]);
4281
                            NEON_SET_REG(T0, reg, n % 2);
4282
                        }
4283
                    }
4284
                    break;
4285
                case 35: /* VZIP */
4286
                    /* Reg  Before       After
4287
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
4288
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
4289
                     */
4290
                    if (size == 3)
4291
                        return 1;
4292
                    count = (q ? 4 : 2);
4293
                    for (n = 0; n < count; n++) {
4294
                        NEON_GET_REG(T0, rd, n);
4295
                        NEON_GET_REG(T1, rd, n);
4296
                        switch (size) {
4297
                        case 0: gen_op_neon_zip_u8(); break;
4298
                        case 1: gen_op_neon_zip_u16(); break;
4299
                        case 2: /* no-op */; break;
4300
                        default: abort();
4301
                        }
4302
                        gen_neon_movl_scratch_T0(n * 2);
4303
                        gen_neon_movl_scratch_T1(n * 2 + 1);
4304
                    }
4305
                    for (n = 0; n < count * 2; n++) {
4306
                        int reg = (n < count) ? rd : rm;
4307
                        gen_neon_movl_T0_scratch(n);
4308
                        NEON_SET_REG(T0, reg, n % count);
4309
                    }
4310
                    break;
4311
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4312
                    for (pass = 0; pass < 2; pass++) {
4313
                        if (rd == rm + 1) {
4314
                            n = 1 - pass;
4315
                        } else {
4316
                            n = pass;
4317
                        }
4318
                        NEON_GET_REG(T0, rm, n * 2);
4319
                        NEON_GET_REG(T1, rm, n * 2 + 1);
4320
                        if (op == 36 && q == 0) {
4321
                            switch (size) {
4322
                            case 0: gen_op_neon_narrow_u8(); break;
4323
                            case 1: gen_op_neon_narrow_u16(); break;
4324
                            case 2: /* no-op */ break;
4325
                            default: return 1;
4326
                            }
4327
                        } else if (q) {
4328
                            switch (size) {
4329
                            case 0: gen_op_neon_narrow_sat_u8(); break;
4330
                            case 1: gen_op_neon_narrow_sat_u16(); break;
4331
                            case 2: gen_op_neon_narrow_sat_u32(); break;
4332
                            default: return 1;
4333
                            }
4334
                        } else {
4335
                            switch (size) {
4336
                            case 0: gen_op_neon_narrow_sat_s8(); break;
4337
                            case 1: gen_op_neon_narrow_sat_s16(); break;
4338
                            case 2: gen_op_neon_narrow_sat_s32(); break;
4339
                            default: return 1;
4340
                            }
4341
                        }
4342
                        NEON_SET_REG(T0, rd, n);
4343
                    }
4344
                    break;
4345
                case 38: /* VSHLL */
4346
                    if (q)
4347
                        return 1;
4348
                    if (rm == rd) {
4349
                        NEON_GET_REG(T2, rm, 1);
4350
                    }
4351
                    for (pass = 0; pass < 2; pass++) {
4352
                        if (pass == 1 && rm == rd) {
4353
                            gen_op_movl_T0_T2();
4354
                        } else {
4355
                            NEON_GET_REG(T0, rm, pass);
4356
                        }
4357
                        switch (size) {
4358
                        case 0: gen_op_neon_widen_high_u8(); break;
4359
                        case 1: gen_op_neon_widen_high_u16(); break;
4360
                        case 2:
4361
                            gen_op_movl_T1_T0();
4362
                            gen_op_movl_T0_im(0);
4363
                            break;
4364
                        default: return 1;
4365
                        }
4366
                        NEON_SET_REG(T0, rd, pass * 2);
4367
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4368
                    }
4369
                    break;
4370
                default:
4371
                elementwise:
4372
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373
                        if (op == 30 || op == 31 || op >= 58) {
4374
                            gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4375
                        } else {
4376
                            NEON_GET_REG(T0, rm, pass);
4377
                        }
4378
                        switch (op) {
4379
                        case 1: /* VREV32 */
4380
                            switch (size) {
4381
                            case 0: gen_op_rev_T0(); break;
4382
                            case 1: gen_op_revh_T0(); break;
4383
                            default: return 1;
4384
                            }
4385
                            break;
4386
                        case 2: /* VREV16 */
4387
                            if (size != 0)
4388
                                return 1;
4389
                            gen_op_rev16_T0();
4390
                            break;
4391
                        case 4: case 5: /* VPADDL */
4392
                        case 12: case 13: /* VPADAL */
4393
                            switch ((size << 1) | (op & 1)) {
4394
                            case 0: gen_op_neon_paddl_s8(); break;
4395
                            case 1: gen_op_neon_paddl_u8(); break;
4396
                            case 2: gen_op_neon_paddl_s16(); break;
4397
                            case 3: gen_op_neon_paddl_u16(); break;
4398
                            default: abort();
4399
                            }
4400
                            if (op >= 12) {
4401
                                /* Accumulate */
4402
                                NEON_GET_REG(T1, rd, pass);
4403
                                switch (size) {
4404
                                case 0: gen_op_neon_add_u16(); break;
4405
                                case 1: gen_op_addl_T0_T1(); break;
4406
                                default: abort();
4407
                                }
4408
                            }
4409
                            break;
4410
                        case 8: /* CLS */
4411
                            switch (size) {
4412
                            case 0: gen_op_neon_cls_s8(); break;
4413
                            case 1: gen_op_neon_cls_s16(); break;
4414
                            case 2: gen_op_neon_cls_s32(); break;
4415
                            default: return 1;
4416
                            }
4417
                            break;
4418
                        case 9: /* CLZ */
4419
                            switch (size) {
4420
                            case 0: gen_op_neon_clz_u8(); break;
4421
                            case 1: gen_op_neon_clz_u16(); break;
4422
                            case 2: gen_op_clz_T0(); break;
4423
                            default: return 1;
4424
                            }
4425
                            break;
4426
                        case 10: /* CNT */
4427
                            if (size != 0)
4428
                                return 1;
4429
                            gen_op_neon_cnt_u8();
4430
                            break;
4431
                        case 11: /* VNOT */
4432
                            if (size != 0)
4433
                                return 1;
4434
                            gen_op_notl_T0();
4435
                            break;
4436
                        case 14: /* VQABS */
4437
                            switch (size) {
4438
                            case 0: gen_op_neon_qabs_s8(); break;
4439
                            case 1: gen_op_neon_qabs_s16(); break;
4440
                            case 2: gen_op_neon_qabs_s32(); break;
4441
                            default: return 1;
4442
                            }
4443
                            break;
4444
                        case 15: /* VQNEG */
4445
                            switch (size) {
4446
                            case 0: gen_op_neon_qneg_s8(); break;
4447
                            case 1: gen_op_neon_qneg_s16(); break;
4448
                            case 2: gen_op_neon_qneg_s32(); break;
4449
                            default: return 1;
4450
                            }
4451
                            break;
4452
                        case 16: case 19: /* VCGT #0, VCLE #0 */
4453
                            gen_op_movl_T1_im(0);
4454
                            switch(size) {
4455
                            case 0: gen_op_neon_cgt_s8(); break;
4456
                            case 1: gen_op_neon_cgt_s16(); break;
4457
                            case 2: gen_op_neon_cgt_s32(); break;
4458
                            default: return 1;
4459
                            }
4460
                            if (op == 19)
4461
                                gen_op_notl_T0();
4462
                            break;
4463
                        case 17: case 20: /* VCGE #0, VCLT #0 */
4464
                            gen_op_movl_T1_im(0);
4465
                            switch(size) {
4466
                            case 0: gen_op_neon_cge_s8(); break;
4467
                            case 1: gen_op_neon_cge_s16(); break;
4468
                            case 2: gen_op_neon_cge_s32(); break;
4469
                            default: return 1;
4470
                            }
4471
                            if (op == 20)
4472
                                gen_op_notl_T0();
4473
                            break;
4474
                        case 18: /* VCEQ #0 */
4475
                            gen_op_movl_T1_im(0);
4476
                            switch(size) {
4477
                            case 0: gen_op_neon_ceq_u8(); break;
4478
                            case 1: gen_op_neon_ceq_u16(); break;
4479
                            case 2: gen_op_neon_ceq_u32(); break;
4480
                            default: return 1;
4481
                            }
4482
                            break;
4483
                        case 22: /* VABS */
4484
                            switch(size) {
4485
                            case 0: gen_op_neon_abs_s8(); break;
4486
                            case 1: gen_op_neon_abs_s16(); break;
4487
                            case 2: gen_op_neon_abs_s32(); break;
4488
                            default: return 1;
4489
                            }
4490
                            break;
4491
                        case 23: /* VNEG */
4492
                            gen_op_movl_T1_im(0);
4493
                            switch(size) {
4494
                            case 0: gen_op_neon_rsb_u8(); break;
4495
                            case 1: gen_op_neon_rsb_u16(); break;
4496
                            case 2: gen_op_rsbl_T0_T1(); break;
4497
                            default: return 1;
4498
                            }
4499
                            break;
4500
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4501
                            gen_op_movl_T1_im(0);
4502
                            gen_op_neon_cgt_f32();
4503
                            if (op == 27)
4504
                                gen_op_notl_T0();
4505
                            break;
4506
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4507
                            gen_op_movl_T1_im(0);
4508
                            gen_op_neon_cge_f32();
4509
                            if (op == 28)
4510
                                gen_op_notl_T0();
4511
                            break;
4512
                        case 26: /* Float VCEQ #0 */
4513
                            gen_op_movl_T1_im(0);
4514
                            gen_op_neon_ceq_f32();
4515
                            break;
4516
                        case 30: /* Float VABS */
4517
                            gen_op_vfp_abss();
4518
                            break;
4519
                        case 31: /* Float VNEG */
4520
                            gen_op_vfp_negs();
4521
                            break;
4522
                        case 32: /* VSWP */
4523
                            NEON_GET_REG(T1, rd, pass);
4524
                            NEON_SET_REG(T1, rm, pass);
4525
                            break;
4526
                        case 33: /* VTRN */
4527
                            NEON_GET_REG(T1, rd, pass);
4528
                            switch (size) {
4529
                            case 0: gen_op_neon_trn_u8(); break;
4530
                            case 1: gen_op_neon_trn_u16(); break;
4531
                            case 2: abort();
4532
                            default: return 1;
4533
                            }
4534
                            NEON_SET_REG(T1, rm, pass);
4535
                            break;
4536
                        case 56: /* Integer VRECPE */
4537
                            gen_op_neon_recpe_u32();
4538
                            break;
4539
                        case 57: /* Integer VRSQRTE */
4540
                            gen_op_neon_rsqrte_u32();
4541
                            break;
4542
                        case 58: /* Float VRECPE */
4543
                            gen_op_neon_recpe_f32();
4544
                            break;
4545
                        case 59: /* Float VRSQRTE */
4546
                            gen_op_neon_rsqrte_f32();
4547
                            break;
4548
                        case 60: /* VCVT.F32.S32 */
4549
                            gen_op_vfp_tosizs();
4550
                            break;
4551
                        case 61: /* VCVT.F32.U32 */
4552
                            gen_op_vfp_touizs();
4553
                            break;
4554
                        case 62: /* VCVT.S32.F32 */
4555
                            gen_op_vfp_sitos();
4556
                            break;
4557
                        case 63: /* VCVT.U32.F32 */
4558
                            gen_op_vfp_uitos();
4559
                            break;
4560
                        default:
4561
                            /* Reserved: 21, 29, 39-56 */
4562
                            return 1;
4563
                        }
4564
                        if (op == 30 || op == 31 || op >= 58) {
4565
                            gen_op_vfp_setreg_F0s(neon_reg_offset(rm, pass));
4566
                        } else {
4567
                            NEON_SET_REG(T0, rd, pass);
4568
                        }
4569
                    }
4570
                    break;
4571
                }
4572
            } else if ((insn & (1 << 10)) == 0) {
4573
                /* VTBL, VTBX.  */
4574
                n = (insn >> 5) & 0x18;
4575
                NEON_GET_REG(T1, rm, 0);
4576
                if (insn & (1 << 6)) {
4577
                    NEON_GET_REG(T0, rd, 0);
4578
                } else {
4579
                    gen_op_movl_T0_im(0);
4580
                }
4581
                gen_op_neon_tbl(rn, n);
4582
                gen_op_movl_T2_T0();
4583
                NEON_GET_REG(T1, rm, 1);
4584
                if (insn & (1 << 6)) {
4585
                    NEON_GET_REG(T0, rd, 0);
4586
                } else {
4587
                    gen_op_movl_T0_im(0);
4588
                }
4589
                gen_op_neon_tbl(rn, n);
4590
                NEON_SET_REG(T2, rd, 0);
4591
                NEON_SET_REG(T0, rd, 1);
4592
            } else if ((insn & 0x380) == 0) {
4593
                /* VDUP */
4594
                if (insn & (1 << 19)) {
4595
                    NEON_SET_REG(T0, rm, 1);
4596
                } else {
4597
                    NEON_SET_REG(T0, rm, 0);
4598
                }
4599
                if (insn & (1 << 16)) {
4600
                    gen_op_neon_dup_u8(((insn >> 17) & 3) * 8);
4601
                } else if (insn & (1 << 17)) {
4602
                    if ((insn >> 18) & 1)
4603
                        gen_op_neon_dup_high16();
4604
                    else
4605
                        gen_op_neon_dup_low16();
4606
                }
4607
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4608
                    NEON_SET_REG(T0, rd, pass);
4609
                }
4610
            } else {
4611
                return 1;
4612
            }
4613
        }
4614
    }
4615
    return 0;
4616
}
4617

    
4618
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
4619
{
4620
    int cpnum;
4621

    
4622
    cpnum = (insn >> 8) & 0xf;
4623
    if (arm_feature(env, ARM_FEATURE_XSCALE)
4624
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
4625
        return 1;
4626

    
4627
    switch (cpnum) {
4628
      case 0:
4629
      case 1:
4630
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4631
            return disas_iwmmxt_insn(env, s, insn);
4632
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
4633
            return disas_dsp_insn(env, s, insn);
4634
        }
4635
        return 1;
4636
    case 10:
4637
    case 11:
4638
        return disas_vfp_insn (env, s, insn);
4639
    case 15:
4640
        return disas_cp15_insn (env, s, insn);
4641
    default:
4642
        /* Unknown coprocessor.  See if the board has hooked it.  */
4643
        return disas_cp_insn (env, s, insn);
4644
    }
4645
}
4646

    
4647
static void disas_arm_insn(CPUState * env, DisasContext *s)
4648
{
4649
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
4650

    
4651
    insn = ldl_code(s->pc);
4652
    s->pc += 4;
4653

    
4654
    /* M variants do not implement ARM mode.  */
4655
    if (IS_M(env))
4656
        goto illegal_op;
4657
    cond = insn >> 28;
4658
    if (cond == 0xf){
4659
        /* Unconditional instructions.  */
4660
        if (((insn >> 25) & 7) == 1) {
4661
            /* NEON Data processing.  */
4662
            if (!arm_feature(env, ARM_FEATURE_NEON))
4663
                goto illegal_op;
4664