Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 1497c961

History | View | Annotate | Download (260.2 kB)

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

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

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

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

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

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

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

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

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

    
79
static TCGv cpu_env;
80
/* FIXME:  These should be removed.  */
81
static TCGv cpu_T[3];
82

    
83
/* initialize TCG globals.  */
84
void arm_translate_init(void)
85
{
86
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
87

    
88
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
89
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
90
    cpu_T[2] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG3, "T2");
91
}
92

    
93
/* The code generator doesn't like lots of temporaries, so maintain our own
94
   cache for reuse within a function.  */
95
#define MAX_TEMPS 8
96
static int num_temps;
97
static TCGv temps[MAX_TEMPS];
98

    
99
/* Allocate a temporary variable.  */
100
static TCGv new_tmp(void)
101
{
102
    TCGv tmp;
103
    if (num_temps == MAX_TEMPS)
104
        abort();
105

    
106
    if (GET_TCGV(temps[num_temps]))
107
      return temps[num_temps++];
108

    
109
    tmp = tcg_temp_new(TCG_TYPE_I32);
110
    temps[num_temps++] = tmp;
111
    return tmp;
112
}
113

    
114
/* Release a temporary variable.  */
115
static void dead_tmp(TCGv tmp)
116
{
117
    int i;
118
    num_temps--;
119
    i = num_temps;
120
    if (GET_TCGV(temps[i]) == GET_TCGV(tmp))
121
        return;
122

    
123
    /* Shuffle this temp to the last slot.  */
124
    while (GET_TCGV(temps[i]) != GET_TCGV(tmp))
125
        i--;
126
    while (i < num_temps) {
127
        temps[i] = temps[i + 1];
128
        i++;
129
    }
130
    temps[i] = tmp;
131
}
132

    
133
/* Set a variable to the value of a CPU register.  */
134
static void load_reg_var(DisasContext *s, TCGv var, int reg)
135
{
136
    if (reg == 15) {
137
        uint32_t addr;
138
        /* normaly, since we updated PC, we need only to add one insn */
139
        if (s->thumb)
140
            addr = (long)s->pc + 2;
141
        else
142
            addr = (long)s->pc + 4;
143
        tcg_gen_movi_i32(var, addr);
144
    } else {
145
        tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
146
    }
147
}
148

    
149
/* Create a new temporary and set it to the value of a CPU register.  */
150
static inline TCGv load_reg(DisasContext *s, int reg)
151
{
152
    TCGv tmp = new_tmp();
153
    load_reg_var(s, tmp, reg);
154
    return tmp;
155
}
156

    
157
/* Set a CPU register.  The source must be a temporary and will be
158
   marked as dead.  */
159
static void store_reg(DisasContext *s, int reg, TCGv var)
160
{
161
    if (reg == 15) {
162
        tcg_gen_andi_i32(var, var, ~1);
163
        s->is_jmp = DISAS_JUMP;
164
    }
165
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, regs[reg]));
166
    dead_tmp(var);
167
}
168

    
169

    
170
/* Basic operations.  */
171
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
172
#define gen_op_movl_T0_T2() tcg_gen_mov_i32(cpu_T[0], cpu_T[2])
173
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
174
#define gen_op_movl_T1_T2() tcg_gen_mov_i32(cpu_T[1], cpu_T[2])
175
#define gen_op_movl_T2_T0() tcg_gen_mov_i32(cpu_T[2], cpu_T[0])
176
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
177
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
178
#define gen_op_movl_T2_im(im) tcg_gen_movi_i32(cpu_T[2], im)
179

    
180
#define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
181
#define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
182
#define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
183
#define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
184

    
185
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
186
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
187
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
188
#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
189
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
190
#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
191
#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
192

    
193
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
194
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
195
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
196
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
197
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
198

    
199
/* Value extensions.  */
200
#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
201
#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
202
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
203
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
204

    
205
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
207

    
208
#define gen_op_addl_T0_T1_setq() \
209
    gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
210
#define gen_op_addl_T0_T1_saturate() \
211
    gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
212
#define gen_op_subl_T0_T1_saturate() \
213
    gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
214
#define gen_op_addl_T0_T1_usaturate() \
215
    gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
216
#define gen_op_subl_T0_T1_usaturate() \
217
    gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
218

    
219
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
220
    tmp = (t0 ^ t1) & 0x8000;
221
    t0 &= ~0x8000;
222
    t1 &= ~0x8000;
223
    t0 = (t0 + t1) ^ tmp;
224
 */
225

    
226
static void gen_add16(TCGv t0, TCGv t1)
227
{
228
    TCGv tmp = new_tmp();
229
    tcg_gen_xor_i32(tmp, t0, t1);
230
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
231
    tcg_gen_andi_i32(t0, t0, ~0x8000);
232
    tcg_gen_andi_i32(t1, t1, ~0x8000);
233
    tcg_gen_add_i32(t0, t0, t1);
234
    tcg_gen_xor_i32(t0, t0, tmp);
235
    dead_tmp(tmp);
236
    dead_tmp(t1);
237
}
238

    
239
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
240

    
241
/* Set CF to the top bit of var.  */
242
static void gen_set_CF_bit31(TCGv var)
243
{
244
    TCGv tmp = new_tmp();
245
    tcg_gen_shri_i32(tmp, var, 31);
246
    gen_set_CF(var);
247
    dead_tmp(tmp);
248
}
249

    
250
/* Set N and Z flags from var.  */
251
static inline void gen_logic_CC(TCGv var)
252
{
253
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
254
}
255

    
256
/* T0 += T1 + CF.  */
257
static void gen_adc_T0_T1(void)
258
{
259
    TCGv tmp = new_tmp();
260
    gen_op_addl_T0_T1();
261
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
262
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
263
    dead_tmp(tmp);
264
}
265

    
266
/* FIXME:  Implement this natively.  */
267
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
268
{
269
    tcg_gen_xori_i32(t0, t1, ~0);
270
}
271

    
272
/* T0 &= ~T1.  Clobbers T1.  */
273
/* FIXME: Implement bic natively.  */
274
static inline void gen_op_bicl_T0_T1(void)
275
{
276
    gen_op_notl_T1();
277
    gen_op_andl_T0_T1();
278
}
279

    
280
/* FIXME:  Implement this natively.  */
281
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
282
{
283
    TCGv tmp;
284

    
285
    if (i == 0)
286
        return;
287

    
288
    tmp = new_tmp();
289
    tcg_gen_shri_i32(tmp, t1, i);
290
    tcg_gen_shli_i32(t1, t1, 32 - i);
291
    tcg_gen_or_i32(t0, t1, tmp);
292
    dead_tmp(tmp);
293
}
294

    
295
static void shifter_out_im(TCGv var, int shift)
296
{
297
    TCGv tmp = new_tmp();
298
    if (shift == 0) {
299
        tcg_gen_andi_i32(tmp, var, 1);
300
    } else {
301
        tcg_gen_shri_i32(tmp, var, shift);
302
        if (shift != 31);
303
            tcg_gen_andi_i32(tmp, tmp, 1);
304
    }
305
    gen_set_CF(tmp);
306
    dead_tmp(tmp);
307
}
308

    
309
/* Shift by immediate.  Includes special handling for shift == 0.  */
310
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
311
{
312
    switch (shiftop) {
313
    case 0: /* LSL */
314
        if (shift != 0) {
315
            if (flags)
316
                shifter_out_im(var, 32 - shift);
317
            tcg_gen_shli_i32(var, var, shift);
318
        }
319
        break;
320
    case 1: /* LSR */
321
        if (shift == 0) {
322
            if (flags) {
323
                tcg_gen_shri_i32(var, var, 31);
324
                gen_set_CF(var);
325
            }
326
            tcg_gen_movi_i32(var, 0);
327
        } else {
328
            if (flags)
329
                shifter_out_im(var, shift - 1);
330
            tcg_gen_shri_i32(var, var, shift);
331
        }
332
        break;
333
    case 2: /* ASR */
334
        if (shift == 0)
335
            shift = 32;
336
        if (flags)
337
            shifter_out_im(var, shift - 1);
338
        if (shift == 32)
339
          shift = 31;
340
        tcg_gen_sari_i32(var, var, shift);
341
        break;
342
    case 3: /* ROR/RRX */
343
        if (shift != 0) {
344
            if (flags)
345
                shifter_out_im(var, shift - 1);
346
            tcg_gen_rori_i32(var, var, shift); break;
347
        } else {
348
            TCGv tmp = new_tmp();
349
            tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
350
            if (flags)
351
                shifter_out_im(var, 0);
352
            tcg_gen_shri_i32(var, var, 1);
353
            tcg_gen_shli_i32(tmp, tmp, 31);
354
            tcg_gen_or_i32(var, var, tmp);
355
            dead_tmp(tmp);
356
        }
357
    }
358
};
359

    
360
#define PAS_OP(pfx) {  \
361
    gen_op_ ## pfx ## add16_T0_T1, \
362
    gen_op_ ## pfx ## addsubx_T0_T1, \
363
    gen_op_ ## pfx ## subaddx_T0_T1, \
364
    gen_op_ ## pfx ## sub16_T0_T1, \
365
    gen_op_ ## pfx ## add8_T0_T1, \
366
    NULL, \
367
    NULL, \
368
    gen_op_ ## pfx ## sub8_T0_T1 }
369

    
370
static GenOpFunc *gen_arm_parallel_addsub[8][8] = {
371
    {},
372
    PAS_OP(s),
373
    PAS_OP(q),
374
    PAS_OP(sh),
375
    {},
376
    PAS_OP(u),
377
    PAS_OP(uq),
378
    PAS_OP(uh),
379
};
380
#undef PAS_OP
381

    
382
/* For unknown reasons Arm and Thumb-2 use arbitrarily diffenet encodings.  */
383
#define PAS_OP(pfx) {  \
384
    gen_op_ ## pfx ## add8_T0_T1, \
385
    gen_op_ ## pfx ## add16_T0_T1, \
386
    gen_op_ ## pfx ## addsubx_T0_T1, \
387
    NULL, \
388
    gen_op_ ## pfx ## sub8_T0_T1, \
389
    gen_op_ ## pfx ## sub16_T0_T1, \
390
    gen_op_ ## pfx ## subaddx_T0_T1, \
391
    NULL }
392

    
393
static GenOpFunc *gen_thumb2_parallel_addsub[8][8] = {
394
    PAS_OP(s),
395
    PAS_OP(q),
396
    PAS_OP(sh),
397
    {},
398
    PAS_OP(u),
399
    PAS_OP(uq),
400
    PAS_OP(uh),
401
    {}
402
};
403
#undef PAS_OP
404

    
405
static GenOpFunc1 *gen_test_cc[14] = {
406
    gen_op_test_eq,
407
    gen_op_test_ne,
408
    gen_op_test_cs,
409
    gen_op_test_cc,
410
    gen_op_test_mi,
411
    gen_op_test_pl,
412
    gen_op_test_vs,
413
    gen_op_test_vc,
414
    gen_op_test_hi,
415
    gen_op_test_ls,
416
    gen_op_test_ge,
417
    gen_op_test_lt,
418
    gen_op_test_gt,
419
    gen_op_test_le,
420
};
421

    
422
const uint8_t table_logic_cc[16] = {
423
    1, /* and */
424
    1, /* xor */
425
    0, /* sub */
426
    0, /* rsb */
427
    0, /* add */
428
    0, /* adc */
429
    0, /* sbc */
430
    0, /* rsc */
431
    1, /* andl */
432
    1, /* xorl */
433
    0, /* cmp */
434
    0, /* cmn */
435
    1, /* orr */
436
    1, /* mov */
437
    1, /* bic */
438
    1, /* mvn */
439
};
440

    
441
static GenOpFunc *gen_shift_T1_T0[4] = {
442
    gen_op_shll_T1_T0,
443
    gen_op_shrl_T1_T0,
444
    gen_op_sarl_T1_T0,
445
    gen_op_rorl_T1_T0,
446
};
447

    
448
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
449
    gen_op_shll_T1_T0_cc,
450
    gen_op_shrl_T1_T0_cc,
451
    gen_op_sarl_T1_T0_cc,
452
    gen_op_rorl_T1_T0_cc,
453
};
454

    
455
/* Set PC and thumb state from T0.  Clobbers T0.  */
456
static inline void gen_bx(DisasContext *s)
457
{
458
    TCGv tmp;
459

    
460
    s->is_jmp = DISAS_UPDATE;
461
    tmp = new_tmp();
462
    tcg_gen_andi_i32(tmp, cpu_T[0], 1);
463
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
464
    dead_tmp(tmp);
465
    tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ~1);
466
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
467
}
468

    
469
#if defined(CONFIG_USER_ONLY)
470
#define gen_ldst(name, s) gen_op_##name##_raw()
471
#else
472
#define gen_ldst(name, s) do { \
473
    s->is_mem = 1; \
474
    if (IS_USER(s)) \
475
        gen_op_##name##_user(); \
476
    else \
477
        gen_op_##name##_kernel(); \
478
    } while (0)
479
#endif
480

    
481
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
482
{
483
    load_reg_var(s, cpu_T[0], reg);
484
}
485

    
486
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
487
{
488
    load_reg_var(s, cpu_T[1], reg);
489
}
490

    
491
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
492
{
493
    load_reg_var(s, cpu_T[2], reg);
494
}
495

    
496
static inline void gen_set_pc_T0(void)
497
{
498
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
499
}
500

    
501
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
502
{
503
    TCGv tmp;
504
    if (reg == 15) {
505
        tmp = new_tmp();
506
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
507
    } else {
508
        tmp = cpu_T[t];
509
    }
510
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
511
    if (reg == 15) {
512
        dead_tmp(tmp);
513
        s->is_jmp = DISAS_JUMP;
514
    }
515
}
516

    
517
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
518
{
519
    gen_movl_reg_TN(s, reg, 0);
520
}
521

    
522
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
523
{
524
    gen_movl_reg_TN(s, reg, 1);
525
}
526

    
527
/* Force a TB lookup after an instruction that changes the CPU state.  */
528
static inline void gen_lookup_tb(DisasContext *s)
529
{
530
    gen_op_movl_T0_im(s->pc);
531
    gen_movl_reg_T0(s, 15);
532
    s->is_jmp = DISAS_UPDATE;
533
}
534

    
535
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
536
{
537
    int val, rm, shift, shiftop;
538
    TCGv offset;
539

    
540
    if (!(insn & (1 << 25))) {
541
        /* immediate */
542
        val = insn & 0xfff;
543
        if (!(insn & (1 << 23)))
544
            val = -val;
545
        if (val != 0)
546
            gen_op_addl_T1_im(val);
547
    } else {
548
        /* shift/register */
549
        rm = (insn) & 0xf;
550
        shift = (insn >> 7) & 0x1f;
551
        shiftop = (insn >> 5) & 3;
552
        offset = load_reg(s, rm);
553
        gen_arm_shift_im(offset, shiftop, shift, 0);
554
        if (!(insn & (1 << 23)))
555
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
556
        else
557
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
558
        dead_tmp(offset);
559
    }
560
}
561

    
562
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
563
                                        int extra)
564
{
565
    int val, rm;
566
    TCGv offset;
567

    
568
    if (insn & (1 << 22)) {
569
        /* immediate */
570
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
571
        if (!(insn & (1 << 23)))
572
            val = -val;
573
        val += extra;
574
        if (val != 0)
575
            gen_op_addl_T1_im(val);
576
    } else {
577
        /* register */
578
        if (extra)
579
            gen_op_addl_T1_im(extra);
580
        rm = (insn) & 0xf;
581
        offset = load_reg(s, rm);
582
        if (!(insn & (1 << 23)))
583
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
584
        else
585
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
586
        dead_tmp(offset);
587
    }
588
}
589

    
590
#define VFP_OP(name)                      \
591
static inline void gen_vfp_##name(int dp) \
592
{                                         \
593
    if (dp)                               \
594
        gen_op_vfp_##name##d();           \
595
    else                                  \
596
        gen_op_vfp_##name##s();           \
597
}
598

    
599
#define VFP_OP1(name)                               \
600
static inline void gen_vfp_##name(int dp, int arg)  \
601
{                                                   \
602
    if (dp)                                         \
603
        gen_op_vfp_##name##d(arg);                  \
604
    else                                            \
605
        gen_op_vfp_##name##s(arg);                  \
606
}
607

    
608
VFP_OP(add)
609
VFP_OP(sub)
610
VFP_OP(mul)
611
VFP_OP(div)
612
VFP_OP(neg)
613
VFP_OP(abs)
614
VFP_OP(sqrt)
615
VFP_OP(cmp)
616
VFP_OP(cmpe)
617
VFP_OP(F1_ld0)
618
VFP_OP(uito)
619
VFP_OP(sito)
620
VFP_OP(toui)
621
VFP_OP(touiz)
622
VFP_OP(tosi)
623
VFP_OP(tosiz)
624
VFP_OP1(tosh)
625
VFP_OP1(tosl)
626
VFP_OP1(touh)
627
VFP_OP1(toul)
628
VFP_OP1(shto)
629
VFP_OP1(slto)
630
VFP_OP1(uhto)
631
VFP_OP1(ulto)
632

    
633
#undef VFP_OP
634

    
635
static inline void gen_vfp_fconst(int dp, uint32_t val)
636
{
637
    if (dp)
638
        gen_op_vfp_fconstd(val);
639
    else
640
        gen_op_vfp_fconsts(val);
641
}
642

    
643
static inline void gen_vfp_ld(DisasContext *s, int dp)
644
{
645
    if (dp)
646
        gen_ldst(vfp_ldd, s);
647
    else
648
        gen_ldst(vfp_lds, s);
649
}
650

    
651
static inline void gen_vfp_st(DisasContext *s, int dp)
652
{
653
    if (dp)
654
        gen_ldst(vfp_std, s);
655
    else
656
        gen_ldst(vfp_sts, s);
657
}
658

    
659
static inline long
660
vfp_reg_offset (int dp, int reg)
661
{
662
    if (dp)
663
        return offsetof(CPUARMState, vfp.regs[reg]);
664
    else if (reg & 1) {
665
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
666
          + offsetof(CPU_DoubleU, l.upper);
667
    } else {
668
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
669
          + offsetof(CPU_DoubleU, l.lower);
670
    }
671
}
672

    
673
/* Return the offset of a 32-bit piece of a NEON register.
674
   zero is the least significant end of the register.  */
675
static inline long
676
neon_reg_offset (int reg, int n)
677
{
678
    int sreg;
679
    sreg = reg * 2 + n;
680
    return vfp_reg_offset(0, sreg);
681
}
682

    
683
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
684
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
685

    
686
static inline void gen_mov_F0_vreg(int dp, int reg)
687
{
688
    if (dp)
689
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
690
    else
691
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
692
}
693

    
694
static inline void gen_mov_F1_vreg(int dp, int reg)
695
{
696
    if (dp)
697
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
698
    else
699
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
700
}
701

    
702
static inline void gen_mov_vreg_F0(int dp, int reg)
703
{
704
    if (dp)
705
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
706
    else
707
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
708
}
709

    
710
#define ARM_CP_RW_BIT        (1 << 20)
711

    
712
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
713
{
714
    int rd;
715
    uint32_t offset;
716

    
717
    rd = (insn >> 16) & 0xf;
718
    gen_movl_T1_reg(s, rd);
719

    
720
    offset = (insn & 0xff) << ((insn >> 7) & 2);
721
    if (insn & (1 << 24)) {
722
        /* Pre indexed */
723
        if (insn & (1 << 23))
724
            gen_op_addl_T1_im(offset);
725
        else
726
            gen_op_addl_T1_im(-offset);
727

    
728
        if (insn & (1 << 21))
729
            gen_movl_reg_T1(s, rd);
730
    } else if (insn & (1 << 21)) {
731
        /* Post indexed */
732
        if (insn & (1 << 23))
733
            gen_op_movl_T0_im(offset);
734
        else
735
            gen_op_movl_T0_im(- offset);
736
        gen_op_addl_T0_T1();
737
        gen_movl_reg_T0(s, rd);
738
    } else if (!(insn & (1 << 23)))
739
        return 1;
740
    return 0;
741
}
742

    
743
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
744
{
745
    int rd = (insn >> 0) & 0xf;
746

    
747
    if (insn & (1 << 8))
748
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
749
            return 1;
750
        else
751
            gen_op_iwmmxt_movl_T0_wCx(rd);
752
    else
753
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
754

    
755
    gen_op_movl_T1_im(mask);
756
    gen_op_andl_T0_T1();
757
    return 0;
758
}
759

    
760
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
761
   (ie. an undefined instruction).  */
762
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
763
{
764
    int rd, wrd;
765
    int rdhi, rdlo, rd0, rd1, i;
766

    
767
    if ((insn & 0x0e000e00) == 0x0c000000) {
768
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
769
            wrd = insn & 0xf;
770
            rdlo = (insn >> 12) & 0xf;
771
            rdhi = (insn >> 16) & 0xf;
772
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
773
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
774
                gen_movl_reg_T0(s, rdlo);
775
                gen_movl_reg_T1(s, rdhi);
776
            } else {                                        /* TMCRR */
777
                gen_movl_T0_reg(s, rdlo);
778
                gen_movl_T1_reg(s, rdhi);
779
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
780
                gen_op_iwmmxt_set_mup();
781
            }
782
            return 0;
783
        }
784

    
785
        wrd = (insn >> 12) & 0xf;
786
        if (gen_iwmmxt_address(s, insn))
787
            return 1;
788
        if (insn & ARM_CP_RW_BIT) {
789
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
790
                gen_ldst(ldl, s);
791
                gen_op_iwmmxt_movl_wCx_T0(wrd);
792
            } else {
793
                if (insn & (1 << 8))
794
                    if (insn & (1 << 22))                /* WLDRD */
795
                        gen_ldst(iwmmxt_ldq, s);
796
                    else                                /* WLDRW wRd */
797
                        gen_ldst(iwmmxt_ldl, s);
798
                else
799
                    if (insn & (1 << 22))                /* WLDRH */
800
                        gen_ldst(iwmmxt_ldw, s);
801
                    else                                /* WLDRB */
802
                        gen_ldst(iwmmxt_ldb, s);
803
                gen_op_iwmmxt_movq_wRn_M0(wrd);
804
            }
805
        } else {
806
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
807
                gen_op_iwmmxt_movl_T0_wCx(wrd);
808
                gen_ldst(stl, s);
809
            } else {
810
                gen_op_iwmmxt_movq_M0_wRn(wrd);
811
                if (insn & (1 << 8))
812
                    if (insn & (1 << 22))                /* WSTRD */
813
                        gen_ldst(iwmmxt_stq, s);
814
                    else                                /* WSTRW wRd */
815
                        gen_ldst(iwmmxt_stl, s);
816
                else
817
                    if (insn & (1 << 22))                /* WSTRH */
818
                        gen_ldst(iwmmxt_ldw, s);
819
                    else                                /* WSTRB */
820
                        gen_ldst(iwmmxt_stb, s);
821
            }
822
        }
823
        return 0;
824
    }
825

    
826
    if ((insn & 0x0f000000) != 0x0e000000)
827
        return 1;
828

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

    
1695
    return 0;
1696
}
1697

    
1698
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
1699
   (ie. an undefined instruction).  */
1700
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1701
{
1702
    int acc, rd0, rd1, rdhi, rdlo;
1703

    
1704
    if ((insn & 0x0ff00f10) == 0x0e200010) {
1705
        /* Multiply with Internal Accumulate Format */
1706
        rd0 = (insn >> 12) & 0xf;
1707
        rd1 = insn & 0xf;
1708
        acc = (insn >> 5) & 7;
1709

    
1710
        if (acc != 0)
1711
            return 1;
1712

    
1713
        switch ((insn >> 16) & 0xf) {
1714
        case 0x0:                                        /* MIA */
1715
            gen_movl_T0_reg(s, rd0);
1716
            gen_movl_T1_reg(s, rd1);
1717
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1718
            break;
1719
        case 0x8:                                        /* MIAPH */
1720
            gen_movl_T0_reg(s, rd0);
1721
            gen_movl_T1_reg(s, rd1);
1722
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1723
            break;
1724
        case 0xc:                                        /* MIABB */
1725
        case 0xd:                                        /* MIABT */
1726
        case 0xe:                                        /* MIATB */
1727
        case 0xf:                                        /* MIATT */
1728
            gen_movl_T1_reg(s, rd0);
1729
            if (insn & (1 << 16))
1730
                gen_op_shrl_T1_im(16);
1731
            gen_op_movl_T0_T1();
1732
            gen_movl_T1_reg(s, rd1);
1733
            if (insn & (1 << 17))
1734
                gen_op_shrl_T1_im(16);
1735
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1736
            break;
1737
        default:
1738
            return 1;
1739
        }
1740

    
1741
        gen_op_iwmmxt_movq_wRn_M0(acc);
1742
        return 0;
1743
    }
1744

    
1745
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
1746
        /* Internal Accumulator Access Format */
1747
        rdhi = (insn >> 16) & 0xf;
1748
        rdlo = (insn >> 12) & 0xf;
1749
        acc = insn & 7;
1750

    
1751
        if (acc != 0)
1752
            return 1;
1753

    
1754
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
1755
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
1756
            gen_movl_reg_T0(s, rdlo);
1757
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1758
            gen_op_andl_T0_T1();
1759
            gen_movl_reg_T0(s, rdhi);
1760
        } else {                                        /* MAR */
1761
            gen_movl_T0_reg(s, rdlo);
1762
            gen_movl_T1_reg(s, rdhi);
1763
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1764
        }
1765
        return 0;
1766
    }
1767

    
1768
    return 1;
1769
}
1770

    
1771
/* Disassemble system coprocessor instruction.  Return nonzero if
1772
   instruction is not defined.  */
1773
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1774
{
1775
    uint32_t rd = (insn >> 12) & 0xf;
1776
    uint32_t cp = (insn >> 8) & 0xf;
1777
    if (IS_USER(s)) {
1778
        return 1;
1779
    }
1780

    
1781
    if (insn & ARM_CP_RW_BIT) {
1782
        if (!env->cp[cp].cp_read)
1783
            return 1;
1784
        gen_op_movl_T0_im((uint32_t) s->pc);
1785
        gen_set_pc_T0();
1786
        gen_op_movl_T0_cp(insn);
1787
        gen_movl_reg_T0(s, rd);
1788
    } else {
1789
        if (!env->cp[cp].cp_write)
1790
            return 1;
1791
        gen_op_movl_T0_im((uint32_t) s->pc);
1792
        gen_set_pc_T0();
1793
        gen_movl_T0_reg(s, rd);
1794
        gen_op_movl_cp_T0(insn);
1795
    }
1796
    return 0;
1797
}
1798

    
1799
static int cp15_user_ok(uint32_t insn)
1800
{
1801
    int cpn = (insn >> 16) & 0xf;
1802
    int cpm = insn & 0xf;
1803
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1804

    
1805
    if (cpn == 13 && cpm == 0) {
1806
        /* TLS register.  */
1807
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1808
            return 1;
1809
    }
1810
    if (cpn == 7) {
1811
        /* ISB, DSB, DMB.  */
1812
        if ((cpm == 5 && op == 4)
1813
                || (cpm == 10 && (op == 4 || op == 5)))
1814
            return 1;
1815
    }
1816
    return 0;
1817
}
1818

    
1819
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
1820
   instruction is not defined.  */
1821
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
1822
{
1823
    uint32_t rd;
1824

    
1825
    /* M profile cores use memory mapped registers instead of cp15.  */
1826
    if (arm_feature(env, ARM_FEATURE_M))
1827
        return 1;
1828

    
1829
    if ((insn & (1 << 25)) == 0) {
1830
        if (insn & (1 << 20)) {
1831
            /* mrrc */
1832
            return 1;
1833
        }
1834
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
1835
        return 0;
1836
    }
1837
    if ((insn & (1 << 4)) == 0) {
1838
        /* cdp */
1839
        return 1;
1840
    }
1841
    if (IS_USER(s) && !cp15_user_ok(insn)) {
1842
        return 1;
1843
    }
1844
    if ((insn & 0x0fff0fff) == 0x0e070f90
1845
        || (insn & 0x0fff0fff) == 0x0e070f58) {
1846
        /* Wait for interrupt.  */
1847
        gen_op_movl_T0_im((long)s->pc);
1848
        gen_set_pc_T0();
1849
        s->is_jmp = DISAS_WFI;
1850
        return 0;
1851
    }
1852
    rd = (insn >> 12) & 0xf;
1853
    if (insn & ARM_CP_RW_BIT) {
1854
        gen_op_movl_T0_cp15(insn);
1855
        /* If the destination register is r15 then sets condition codes.  */
1856
        if (rd != 15)
1857
            gen_movl_reg_T0(s, rd);
1858
    } else {
1859
        gen_movl_T0_reg(s, rd);
1860
        gen_op_movl_cp15_T0(insn);
1861
        /* Normally we would always end the TB here, but Linux
1862
         * arch/arm/mach-pxa/sleep.S expects two instructions following
1863
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
1864
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
1865
                (insn & 0x0fff0fff) != 0x0e010f10)
1866
            gen_lookup_tb(s);
1867
    }
1868
    return 0;
1869
}
1870

    
1871
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
1872
#define VFP_SREG(insn, bigbit, smallbit) \
1873
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
1874
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
1875
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
1876
        reg = (((insn) >> (bigbit)) & 0x0f) \
1877
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
1878
    } else { \
1879
        if (insn & (1 << (smallbit))) \
1880
            return 1; \
1881
        reg = ((insn) >> (bigbit)) & 0x0f; \
1882
    }} while (0)
1883

    
1884
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
1885
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
1886
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
1887
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
1888
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
1889
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
1890

    
1891
static inline int
1892
vfp_enabled(CPUState * env)
1893
{
1894
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
1895
}
1896

    
1897
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
1898
   (ie. an undefined instruction).  */
1899
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
1900
{
1901
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
1902
    int dp, veclen;
1903

    
1904
    if (!arm_feature(env, ARM_FEATURE_VFP))
1905
        return 1;
1906

    
1907
    if (!vfp_enabled(env)) {
1908
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
1909
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
1910
            return 1;
1911
        rn = (insn >> 16) & 0xf;
1912
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
1913
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
1914
            return 1;
1915
    }
1916
    dp = ((insn & 0xf00) == 0xb00);
1917
    switch ((insn >> 24) & 0xf) {
1918
    case 0xe:
1919
        if (insn & (1 << 4)) {
1920
            /* single register transfer */
1921
            rd = (insn >> 12) & 0xf;
1922
            if (dp) {
1923
                int size;
1924
                int pass;
1925

    
1926
                VFP_DREG_N(rn, insn);
1927
                if (insn & 0xf)
1928
                    return 1;
1929
                if (insn & 0x00c00060
1930
                    && !arm_feature(env, ARM_FEATURE_NEON))
1931
                    return 1;
1932

    
1933
                pass = (insn >> 21) & 1;
1934
                if (insn & (1 << 22)) {
1935
                    size = 0;
1936
                    offset = ((insn >> 5) & 3) * 8;
1937
                } else if (insn & (1 << 5)) {
1938
                    size = 1;
1939
                    offset = (insn & (1 << 6)) ? 16 : 0;
1940
                } else {
1941
                    size = 2;
1942
                    offset = 0;
1943
                }
1944
                if (insn & ARM_CP_RW_BIT) {
1945
                    /* vfp->arm */
1946
                    switch (size) {
1947
                    case 0:
1948
                        NEON_GET_REG(T1, rn, pass);
1949
                        if (offset)
1950
                            gen_op_shrl_T1_im(offset);
1951
                        if (insn & (1 << 23))
1952
                            gen_uxtb(cpu_T[1]);
1953
                        else
1954
                            gen_sxtb(cpu_T[1]);
1955
                        break;
1956
                    case 1:
1957
                        NEON_GET_REG(T1, rn, pass);
1958
                        if (insn & (1 << 23)) {
1959
                            if (offset) {
1960
                                gen_op_shrl_T1_im(16);
1961
                            } else {
1962
                                gen_uxth(cpu_T[1]);
1963
                            }
1964
                        } else {
1965
                            if (offset) {
1966
                                gen_op_sarl_T1_im(16);
1967
                            } else {
1968
                                gen_sxth(cpu_T[1]);
1969
                            }
1970
                        }
1971
                        break;
1972
                    case 2:
1973
                        NEON_GET_REG(T1, rn, pass);
1974
                        break;
1975
                    }
1976
                    gen_movl_reg_T1(s, rd);
1977
                } else {
1978
                    /* arm->vfp */
1979
                    gen_movl_T0_reg(s, rd);
1980
                    if (insn & (1 << 23)) {
1981
                        /* VDUP */
1982
                        if (size == 0) {
1983
                            gen_op_neon_dup_u8(0);
1984
                        } else if (size == 1) {
1985
                            gen_op_neon_dup_low16();
1986
                        }
1987
                        NEON_SET_REG(T0, rn, 0);
1988
                        NEON_SET_REG(T0, rn, 1);
1989
                    } else {
1990
                        /* VMOV */
1991
                        switch (size) {
1992
                        case 0:
1993
                            NEON_GET_REG(T2, rn, pass);
1994
                            gen_op_movl_T1_im(0xff);
1995
                            gen_op_andl_T0_T1();
1996
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
1997
                            NEON_SET_REG(T2, rn, pass);
1998
                            break;
1999
                        case 1:
2000
                            NEON_GET_REG(T2, rn, pass);
2001
                            gen_op_movl_T1_im(0xffff);
2002
                            gen_op_andl_T0_T1();
2003
                            bank_mask = offset ? 0xffff : 0xffff0000;
2004
                            gen_op_neon_insert_elt(offset, bank_mask);
2005
                            NEON_SET_REG(T2, rn, pass);
2006
                            break;
2007
                        case 2:
2008
                            NEON_SET_REG(T0, rn, pass);
2009
                            break;
2010
                        }
2011
                    }
2012
                }
2013
            } else { /* !dp */
2014
                if ((insn & 0x6f) != 0x00)
2015
                    return 1;
2016
                rn = VFP_SREG_N(insn);
2017
                if (insn & ARM_CP_RW_BIT) {
2018
                    /* vfp->arm */
2019
                    if (insn & (1 << 21)) {
2020
                        /* system register */
2021
                        rn >>= 1;
2022

    
2023
                        switch (rn) {
2024
                        case ARM_VFP_FPSID:
2025
                            /* VFP2 allows access for FSID from userspace.
2026
                               VFP3 restricts all id registers to privileged
2027
                               accesses.  */
2028
                            if (IS_USER(s)
2029
                                && arm_feature(env, ARM_FEATURE_VFP3))
2030
                                return 1;
2031
                            gen_op_vfp_movl_T0_xreg(rn);
2032
                            break;
2033
                        case ARM_VFP_FPEXC:
2034
                            if (IS_USER(s))
2035
                                return 1;
2036
                            gen_op_vfp_movl_T0_xreg(rn);
2037
                            break;
2038
                        case ARM_VFP_FPINST:
2039
                        case ARM_VFP_FPINST2:
2040
                            /* Not present in VFP3.  */
2041
                            if (IS_USER(s)
2042
                                || arm_feature(env, ARM_FEATURE_VFP3))
2043
                                return 1;
2044
                            gen_op_vfp_movl_T0_xreg(rn);
2045
                            break;
2046
                        case ARM_VFP_FPSCR:
2047
                            if (rd == 15)
2048
                                gen_op_vfp_movl_T0_fpscr_flags();
2049
                            else
2050
                                gen_op_vfp_movl_T0_fpscr();
2051
                            break;
2052
                        case ARM_VFP_MVFR0:
2053
                        case ARM_VFP_MVFR1:
2054
                            if (IS_USER(s)
2055
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2056
                                return 1;
2057
                            gen_op_vfp_movl_T0_xreg(rn);
2058
                            break;
2059
                        default:
2060
                            return 1;
2061
                        }
2062
                    } else {
2063
                        gen_mov_F0_vreg(0, rn);
2064
                        gen_op_vfp_mrs();
2065
                    }
2066
                    if (rd == 15) {
2067
                        /* Set the 4 flag bits in the CPSR.  */
2068
                        gen_op_movl_cpsr_T0(0xf0000000);
2069
                    } else
2070
                        gen_movl_reg_T0(s, rd);
2071
                } else {
2072
                    /* arm->vfp */
2073
                    gen_movl_T0_reg(s, rd);
2074
                    if (insn & (1 << 21)) {
2075
                        rn >>= 1;
2076
                        /* system register */
2077
                        switch (rn) {
2078
                        case ARM_VFP_FPSID:
2079
                        case ARM_VFP_MVFR0:
2080
                        case ARM_VFP_MVFR1:
2081
                            /* Writes are ignored.  */
2082
                            break;
2083
                        case ARM_VFP_FPSCR:
2084
                            gen_op_vfp_movl_fpscr_T0();
2085
                            gen_lookup_tb(s);
2086
                            break;
2087
                        case ARM_VFP_FPEXC:
2088
                            if (IS_USER(s))
2089
                                return 1;
2090
                            gen_op_vfp_movl_xreg_T0(rn);
2091
                            gen_lookup_tb(s);
2092
                            break;
2093
                        case ARM_VFP_FPINST:
2094
                        case ARM_VFP_FPINST2:
2095
                            gen_op_vfp_movl_xreg_T0(rn);
2096
                            break;
2097
                        default:
2098
                            return 1;
2099
                        }
2100
                    } else {
2101
                        gen_op_vfp_msr();
2102
                        gen_mov_vreg_F0(0, rn);
2103
                    }
2104
                }
2105
            }
2106
        } else {
2107
            /* data processing */
2108
            /* The opcode is in bits 23, 21, 20 and 6.  */
2109
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2110
            if (dp) {
2111
                if (op == 15) {
2112
                    /* rn is opcode */
2113
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2114
                } else {
2115
                    /* rn is register number */
2116
                    VFP_DREG_N(rn, insn);
2117
                }
2118

    
2119
                if (op == 15 && (rn == 15 || rn > 17)) {
2120
                    /* Integer or single precision destination.  */
2121
                    rd = VFP_SREG_D(insn);
2122
                } else {
2123
                    VFP_DREG_D(rd, insn);
2124
                }
2125

    
2126
                if (op == 15 && (rn == 16 || rn == 17)) {
2127
                    /* Integer source.  */
2128
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2129
                } else {
2130
                    VFP_DREG_M(rm, insn);
2131
                }
2132
            } else {
2133
                rn = VFP_SREG_N(insn);
2134
                if (op == 15 && rn == 15) {
2135
                    /* Double precision destination.  */
2136
                    VFP_DREG_D(rd, insn);
2137
                } else {
2138
                    rd = VFP_SREG_D(insn);
2139
                }
2140
                rm = VFP_SREG_M(insn);
2141
            }
2142

    
2143
            veclen = env->vfp.vec_len;
2144
            if (op == 15 && rn > 3)
2145
                veclen = 0;
2146

    
2147
            /* Shut up compiler warnings.  */
2148
            delta_m = 0;
2149
            delta_d = 0;
2150
            bank_mask = 0;
2151

    
2152
            if (veclen > 0) {
2153
                if (dp)
2154
                    bank_mask = 0xc;
2155
                else
2156
                    bank_mask = 0x18;
2157

    
2158
                /* Figure out what type of vector operation this is.  */
2159
                if ((rd & bank_mask) == 0) {
2160
                    /* scalar */
2161
                    veclen = 0;
2162
                } else {
2163
                    if (dp)
2164
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2165
                    else
2166
                        delta_d = env->vfp.vec_stride + 1;
2167

    
2168
                    if ((rm & bank_mask) == 0) {
2169
                        /* mixed scalar/vector */
2170
                        delta_m = 0;
2171
                    } else {
2172
                        /* vector */
2173
                        delta_m = delta_d;
2174
                    }
2175
                }
2176
            }
2177

    
2178
            /* Load the initial operands.  */
2179
            if (op == 15) {
2180
                switch (rn) {
2181
                case 16:
2182
                case 17:
2183
                    /* Integer source */
2184
                    gen_mov_F0_vreg(0, rm);
2185
                    break;
2186
                case 8:
2187
                case 9:
2188
                    /* Compare */
2189
                    gen_mov_F0_vreg(dp, rd);
2190
                    gen_mov_F1_vreg(dp, rm);
2191
                    break;
2192
                case 10:
2193
                case 11:
2194
                    /* Compare with zero */
2195
                    gen_mov_F0_vreg(dp, rd);
2196
                    gen_vfp_F1_ld0(dp);
2197
                    break;
2198
                case 20:
2199
                case 21:
2200
                case 22:
2201
                case 23:
2202
                    /* Source and destination the same.  */
2203
                    gen_mov_F0_vreg(dp, rd);
2204
                    break;
2205
                default:
2206
                    /* One source operand.  */
2207
                    gen_mov_F0_vreg(dp, rm);
2208
                    break;
2209
                }
2210
            } else {
2211
                /* Two source operands.  */
2212
                gen_mov_F0_vreg(dp, rn);
2213
                gen_mov_F1_vreg(dp, rm);
2214
            }
2215

    
2216
            for (;;) {
2217
                /* Perform the calculation.  */
2218
                switch (op) {
2219
                case 0: /* mac: fd + (fn * fm) */
2220
                    gen_vfp_mul(dp);
2221
                    gen_mov_F1_vreg(dp, rd);
2222
                    gen_vfp_add(dp);
2223
                    break;
2224
                case 1: /* nmac: fd - (fn * fm) */
2225
                    gen_vfp_mul(dp);
2226
                    gen_vfp_neg(dp);
2227
                    gen_mov_F1_vreg(dp, rd);
2228
                    gen_vfp_add(dp);
2229
                    break;
2230
                case 2: /* msc: -fd + (fn * fm) */
2231
                    gen_vfp_mul(dp);
2232
                    gen_mov_F1_vreg(dp, rd);
2233
                    gen_vfp_sub(dp);
2234
                    break;
2235
                case 3: /* nmsc: -fd - (fn * fm)  */
2236
                    gen_vfp_mul(dp);
2237
                    gen_mov_F1_vreg(dp, rd);
2238
                    gen_vfp_add(dp);
2239
                    gen_vfp_neg(dp);
2240
                    break;
2241
                case 4: /* mul: fn * fm */
2242
                    gen_vfp_mul(dp);
2243
                    break;
2244
                case 5: /* nmul: -(fn * fm) */
2245
                    gen_vfp_mul(dp);
2246
                    gen_vfp_neg(dp);
2247
                    break;
2248
                case 6: /* add: fn + fm */
2249
                    gen_vfp_add(dp);
2250
                    break;
2251
                case 7: /* sub: fn - fm */
2252
                    gen_vfp_sub(dp);
2253
                    break;
2254
                case 8: /* div: fn / fm */
2255
                    gen_vfp_div(dp);
2256
                    break;
2257
                case 14: /* fconst */
2258
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2259
                      return 1;
2260

    
2261
                    n = (insn << 12) & 0x80000000;
2262
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2263
                    if (dp) {
2264
                        if (i & 0x40)
2265
                            i |= 0x3f80;
2266
                        else
2267
                            i |= 0x4000;
2268
                        n |= i << 16;
2269
                    } else {
2270
                        if (i & 0x40)
2271
                            i |= 0x780;
2272
                        else
2273
                            i |= 0x800;
2274
                        n |= i << 19;
2275
                    }
2276
                    gen_vfp_fconst(dp, n);
2277
                    break;
2278
                case 15: /* extension space */
2279
                    switch (rn) {
2280
                    case 0: /* cpy */
2281
                        /* no-op */
2282
                        break;
2283
                    case 1: /* abs */
2284
                        gen_vfp_abs(dp);
2285
                        break;
2286
                    case 2: /* neg */
2287
                        gen_vfp_neg(dp);
2288
                        break;
2289
                    case 3: /* sqrt */
2290
                        gen_vfp_sqrt(dp);
2291
                        break;
2292
                    case 8: /* cmp */
2293
                        gen_vfp_cmp(dp);
2294
                        break;
2295
                    case 9: /* cmpe */
2296
                        gen_vfp_cmpe(dp);
2297
                        break;
2298
                    case 10: /* cmpz */
2299
                        gen_vfp_cmp(dp);
2300
                        break;
2301
                    case 11: /* cmpez */
2302
                        gen_vfp_F1_ld0(dp);
2303
                        gen_vfp_cmpe(dp);
2304
                        break;
2305
                    case 15: /* single<->double conversion */
2306
                        if (dp)
2307
                            gen_op_vfp_fcvtsd();
2308
                        else
2309
                            gen_op_vfp_fcvtds();
2310
                        break;
2311
                    case 16: /* fuito */
2312
                        gen_vfp_uito(dp);
2313
                        break;
2314
                    case 17: /* fsito */
2315
                        gen_vfp_sito(dp);
2316
                        break;
2317
                    case 20: /* fshto */
2318
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2319
                          return 1;
2320
                        gen_vfp_shto(dp, rm);
2321
                        break;
2322
                    case 21: /* fslto */
2323
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2324
                          return 1;
2325
                        gen_vfp_slto(dp, rm);
2326
                        break;
2327
                    case 22: /* fuhto */
2328
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2329
                          return 1;
2330
                        gen_vfp_uhto(dp, rm);
2331
                        break;
2332
                    case 23: /* fulto */
2333
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2334
                          return 1;
2335
                        gen_vfp_ulto(dp, rm);
2336
                        break;
2337
                    case 24: /* ftoui */
2338
                        gen_vfp_toui(dp);
2339
                        break;
2340
                    case 25: /* ftouiz */
2341
                        gen_vfp_touiz(dp);
2342
                        break;
2343
                    case 26: /* ftosi */
2344
                        gen_vfp_tosi(dp);
2345
                        break;
2346
                    case 27: /* ftosiz */
2347
                        gen_vfp_tosiz(dp);
2348
                        break;
2349
                    case 28: /* ftosh */
2350
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2351
                          return 1;
2352
                        gen_vfp_tosh(dp, rm);
2353
                        break;
2354
                    case 29: /* ftosl */
2355
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2356
                          return 1;
2357
                        gen_vfp_tosl(dp, rm);
2358
                        break;
2359
                    case 30: /* ftouh */
2360
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2361
                          return 1;
2362
                        gen_vfp_touh(dp, rm);
2363
                        break;
2364
                    case 31: /* ftoul */
2365
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2366
                          return 1;
2367
                        gen_vfp_toul(dp, rm);
2368
                        break;
2369
                    default: /* undefined */
2370
                        printf ("rn:%d\n", rn);
2371
                        return 1;
2372
                    }
2373
                    break;
2374
                default: /* undefined */
2375
                    printf ("op:%d\n", op);
2376
                    return 1;
2377
                }
2378

    
2379
                /* Write back the result.  */
2380
                if (op == 15 && (rn >= 8 && rn <= 11))
2381
                    ; /* Comparison, do nothing.  */
2382
                else if (op == 15 && rn > 17)
2383
                    /* Integer result.  */
2384
                    gen_mov_vreg_F0(0, rd);
2385
                else if (op == 15 && rn == 15)
2386
                    /* conversion */
2387
                    gen_mov_vreg_F0(!dp, rd);
2388
                else
2389
                    gen_mov_vreg_F0(dp, rd);
2390

    
2391
                /* break out of the loop if we have finished  */
2392
                if (veclen == 0)
2393
                    break;
2394

    
2395
                if (op == 15 && delta_m == 0) {
2396
                    /* single source one-many */
2397
                    while (veclen--) {
2398
                        rd = ((rd + delta_d) & (bank_mask - 1))
2399
                             | (rd & bank_mask);
2400
                        gen_mov_vreg_F0(dp, rd);
2401
                    }
2402
                    break;
2403
                }
2404
                /* Setup the next operands.  */
2405
                veclen--;
2406
                rd = ((rd + delta_d) & (bank_mask - 1))
2407
                     | (rd & bank_mask);
2408

    
2409
                if (op == 15) {
2410
                    /* One source operand.  */
2411
                    rm = ((rm + delta_m) & (bank_mask - 1))
2412
                         | (rm & bank_mask);
2413
                    gen_mov_F0_vreg(dp, rm);
2414
                } else {
2415
                    /* Two source operands.  */
2416
                    rn = ((rn + delta_d) & (bank_mask - 1))
2417
                         | (rn & bank_mask);
2418
                    gen_mov_F0_vreg(dp, rn);
2419
                    if (delta_m) {
2420
                        rm = ((rm + delta_m) & (bank_mask - 1))
2421
                             | (rm & bank_mask);
2422
                        gen_mov_F1_vreg(dp, rm);
2423
                    }
2424
                }
2425
            }
2426
        }
2427
        break;
2428
    case 0xc:
2429
    case 0xd:
2430
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2431
            /* two-register transfer */
2432
            rn = (insn >> 16) & 0xf;
2433
            rd = (insn >> 12) & 0xf;
2434
            if (dp) {
2435
                VFP_DREG_M(rm, insn);
2436
            } else {
2437
                rm = VFP_SREG_M(insn);
2438
            }
2439

    
2440
            if (insn & ARM_CP_RW_BIT) {
2441
                /* vfp->arm */
2442
                if (dp) {
2443
                    gen_mov_F0_vreg(1, rm);
2444
                    gen_op_vfp_mrrd();
2445
                    gen_movl_reg_T0(s, rd);
2446
                    gen_movl_reg_T1(s, rn);
2447
                } else {
2448
                    gen_mov_F0_vreg(0, rm);
2449
                    gen_op_vfp_mrs();
2450
                    gen_movl_reg_T0(s, rn);
2451
                    gen_mov_F0_vreg(0, rm + 1);
2452
                    gen_op_vfp_mrs();
2453
                    gen_movl_reg_T0(s, rd);
2454
                }
2455
            } else {
2456
                /* arm->vfp */
2457
                if (dp) {
2458
                    gen_movl_T0_reg(s, rd);
2459
                    gen_movl_T1_reg(s, rn);
2460
                    gen_op_vfp_mdrr();
2461
                    gen_mov_vreg_F0(1, rm);
2462
                } else {
2463
                    gen_movl_T0_reg(s, rn);
2464
                    gen_op_vfp_msr();
2465
                    gen_mov_vreg_F0(0, rm);
2466
                    gen_movl_T0_reg(s, rd);
2467
                    gen_op_vfp_msr();
2468
                    gen_mov_vreg_F0(0, rm + 1);
2469
                }
2470
            }
2471
        } else {
2472
            /* Load/store */
2473
            rn = (insn >> 16) & 0xf;
2474
            if (dp)
2475
                VFP_DREG_D(rd, insn);
2476
            else
2477
                rd = VFP_SREG_D(insn);
2478
            if (s->thumb && rn == 15) {
2479
                gen_op_movl_T1_im(s->pc & ~2);
2480
            } else {
2481
                gen_movl_T1_reg(s, rn);
2482
            }
2483
            if ((insn & 0x01200000) == 0x01000000) {
2484
                /* Single load/store */
2485
                offset = (insn & 0xff) << 2;
2486
                if ((insn & (1 << 23)) == 0)
2487
                    offset = -offset;
2488
                gen_op_addl_T1_im(offset);
2489
                if (insn & (1 << 20)) {
2490
                    gen_vfp_ld(s, dp);
2491
                    gen_mov_vreg_F0(dp, rd);
2492
                } else {
2493
                    gen_mov_F0_vreg(dp, rd);
2494
                    gen_vfp_st(s, dp);
2495
                }
2496
            } else {
2497
                /* load/store multiple */
2498
                if (dp)
2499
                    n = (insn >> 1) & 0x7f;
2500
                else
2501
                    n = insn & 0xff;
2502

    
2503
                if (insn & (1 << 24)) /* pre-decrement */
2504
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2505

    
2506
                if (dp)
2507
                    offset = 8;
2508
                else
2509
                    offset = 4;
2510
                for (i = 0; i < n; i++) {
2511
                    if (insn & ARM_CP_RW_BIT) {
2512
                        /* load */
2513
                        gen_vfp_ld(s, dp);
2514
                        gen_mov_vreg_F0(dp, rd + i);
2515
                    } else {
2516
                        /* store */
2517
                        gen_mov_F0_vreg(dp, rd + i);
2518
                        gen_vfp_st(s, dp);
2519
                    }
2520
                    gen_op_addl_T1_im(offset);
2521
                }
2522
                if (insn & (1 << 21)) {
2523
                    /* writeback */
2524
                    if (insn & (1 << 24))
2525
                        offset = -offset * n;
2526
                    else if (dp && (insn & 1))
2527
                        offset = 4;
2528
                    else
2529
                        offset = 0;
2530

    
2531
                    if (offset != 0)
2532
                        gen_op_addl_T1_im(offset);
2533
                    gen_movl_reg_T1(s, rn);
2534
                }
2535
            }
2536
        }
2537
        break;
2538
    default:
2539
        /* Should never happen.  */
2540
        return 1;
2541
    }
2542
    return 0;
2543
}
2544

    
2545
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2546
{
2547
    TranslationBlock *tb;
2548

    
2549
    tb = s->tb;
2550
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2551
        tcg_gen_goto_tb(n);
2552
        gen_op_movl_T0_im(dest);
2553
        gen_set_pc_T0();
2554
        tcg_gen_exit_tb((long)tb + n);
2555
    } else {
2556
        gen_op_movl_T0_im(dest);
2557
        gen_set_pc_T0();
2558
        tcg_gen_exit_tb(0);
2559
    }
2560
}
2561

    
2562
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2563
{
2564
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2565
        /* An indirect jump so that we still trigger the debug exception.  */
2566
        if (s->thumb)
2567
          dest |= 1;
2568
        gen_op_movl_T0_im(dest);
2569
        gen_bx(s);
2570
    } else {
2571
        gen_goto_tb(s, 0, dest);
2572
        s->is_jmp = DISAS_TB_JUMP;
2573
    }
2574
}
2575

    
2576
static inline void gen_mulxy(int x, int y)
2577
{
2578
    if (x)
2579
        tcg_gen_sari_i32(cpu_T[0], cpu_T[0], 16);
2580
    else
2581
        gen_sxth(cpu_T[0]);
2582
    if (y)
2583
        gen_op_sarl_T1_im(16);
2584
    else
2585
        gen_sxth(cpu_T[1]);
2586
    gen_op_mul_T0_T1();
2587
}
2588

    
2589
/* Return the mask of PSR bits set by a MSR instruction.  */
2590
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2591
    uint32_t mask;
2592

    
2593
    mask = 0;
2594
    if (flags & (1 << 0))
2595
        mask |= 0xff;
2596
    if (flags & (1 << 1))
2597
        mask |= 0xff00;
2598
    if (flags & (1 << 2))
2599
        mask |= 0xff0000;
2600
    if (flags & (1 << 3))
2601
        mask |= 0xff000000;
2602

    
2603
    /* Mask out undefined bits.  */
2604
    mask &= ~CPSR_RESERVED;
2605
    if (!arm_feature(env, ARM_FEATURE_V6))
2606
        mask &= ~(CPSR_E | CPSR_GE);
2607
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2608
        mask &= ~CPSR_IT;
2609
    /* Mask out execution state bits.  */
2610
    if (!spsr)
2611
        mask &= ~CPSR_EXEC;
2612
    /* Mask out privileged bits.  */
2613
    if (IS_USER(s))
2614
        mask &= CPSR_USER;
2615
    return mask;
2616
}
2617

    
2618
/* Returns nonzero if access to the PSR is not permitted.  */
2619
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2620
{
2621
    if (spsr) {
2622
        /* ??? This is also undefined in system mode.  */
2623
        if (IS_USER(s))
2624
            return 1;
2625
        gen_op_movl_spsr_T0(mask);
2626
    } else {
2627
        gen_op_movl_cpsr_T0(mask);
2628
    }
2629
    gen_lookup_tb(s);
2630
    return 0;
2631
}
2632

    
2633
/* Generate an old-style exception return.  */
2634
static void gen_exception_return(DisasContext *s)
2635
{
2636
    gen_set_pc_T0();
2637
    gen_op_movl_T0_spsr();
2638
    gen_op_movl_cpsr_T0(0xffffffff);
2639
    s->is_jmp = DISAS_UPDATE;
2640
}
2641

    
2642
/* Generate a v6 exception return.  */
2643
static void gen_rfe(DisasContext *s)
2644
{
2645
    gen_op_movl_cpsr_T0(0xffffffff);
2646
    gen_op_movl_T0_T2();
2647
    gen_set_pc_T0();
2648
    s->is_jmp = DISAS_UPDATE;
2649
}
2650

    
2651
static inline void
2652
gen_set_condexec (DisasContext *s)
2653
{
2654
    if (s->condexec_mask) {
2655
        gen_op_set_condexec((s->condexec_cond << 4) | (s->condexec_mask >> 1));
2656
    }
2657
}
2658

    
2659
static void gen_nop_hint(DisasContext *s, int val)
2660
{
2661
    switch (val) {
2662
    case 3: /* wfi */
2663
        gen_op_movl_T0_im((long)s->pc);
2664
        gen_set_pc_T0();
2665
        s->is_jmp = DISAS_WFI;
2666
        break;
2667
    case 2: /* wfe */
2668
    case 4: /* sev */
2669
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
2670
    default: /* nop */
2671
        break;
2672
    }
2673
}
2674

    
2675
/* Neon shift by constant.  The actual ops are the same as used for variable
2676
   shifts.  [OP][U][SIZE]  */
2677
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2678
    { /* 0 */ /* VSHR */
2679
      {
2680
        gen_op_neon_shl_u8,
2681
        gen_op_neon_shl_u16,
2682
        gen_op_neon_shl_u32,
2683
        gen_op_neon_shl_u64
2684
      }, {
2685
        gen_op_neon_shl_s8,
2686
        gen_op_neon_shl_s16,
2687
        gen_op_neon_shl_s32,
2688
        gen_op_neon_shl_s64
2689
      }
2690
    }, { /* 1 */ /* VSRA */
2691
      {
2692
        gen_op_neon_shl_u8,
2693
        gen_op_neon_shl_u16,
2694
        gen_op_neon_shl_u32,
2695
        gen_op_neon_shl_u64
2696
      }, {
2697
        gen_op_neon_shl_s8,
2698
        gen_op_neon_shl_s16,
2699
        gen_op_neon_shl_s32,
2700
        gen_op_neon_shl_s64
2701
      }
2702
    }, { /* 2 */ /* VRSHR */
2703
      {
2704
        gen_op_neon_rshl_u8,
2705
        gen_op_neon_rshl_u16,
2706
        gen_op_neon_rshl_u32,
2707
        gen_op_neon_rshl_u64
2708
      }, {
2709
        gen_op_neon_rshl_s8,
2710
        gen_op_neon_rshl_s16,
2711
        gen_op_neon_rshl_s32,
2712
        gen_op_neon_rshl_s64
2713
      }
2714
    }, { /* 3 */ /* VRSRA */
2715
      {
2716
        gen_op_neon_rshl_u8,
2717
        gen_op_neon_rshl_u16,
2718
        gen_op_neon_rshl_u32,
2719
        gen_op_neon_rshl_u64
2720
      }, {
2721
        gen_op_neon_rshl_s8,
2722
        gen_op_neon_rshl_s16,
2723
        gen_op_neon_rshl_s32,
2724
        gen_op_neon_rshl_s64
2725
      }
2726
    }, { /* 4 */
2727
      {
2728
        NULL, NULL, NULL, NULL
2729
      }, { /* VSRI */
2730
        gen_op_neon_shl_u8,
2731
        gen_op_neon_shl_u16,
2732
        gen_op_neon_shl_u32,
2733
        gen_op_neon_shl_u64,
2734
      }
2735
    }, { /* 5 */
2736
      { /* VSHL */
2737
        gen_op_neon_shl_u8,
2738
        gen_op_neon_shl_u16,
2739
        gen_op_neon_shl_u32,
2740
        gen_op_neon_shl_u64,
2741
      }, { /* VSLI */
2742
        gen_op_neon_shl_u8,
2743
        gen_op_neon_shl_u16,
2744
        gen_op_neon_shl_u32,
2745
        gen_op_neon_shl_u64,
2746
      }
2747
    }, { /* 6 */ /* VQSHL */
2748
      {
2749
        gen_op_neon_qshl_u8,
2750
        gen_op_neon_qshl_u16,
2751
        gen_op_neon_qshl_u32,
2752
        gen_op_neon_qshl_u64
2753
      }, {
2754
        gen_op_neon_qshl_s8,
2755
        gen_op_neon_qshl_s16,
2756
        gen_op_neon_qshl_s32,
2757
        gen_op_neon_qshl_s64
2758
      }
2759
    }, { /* 7 */ /* VQSHLU */
2760
      {
2761
        gen_op_neon_qshl_u8,
2762
        gen_op_neon_qshl_u16,
2763
        gen_op_neon_qshl_u32,
2764
        gen_op_neon_qshl_u64
2765
      }, {
2766
        gen_op_neon_qshl_u8,
2767
        gen_op_neon_qshl_u16,
2768
        gen_op_neon_qshl_u32,
2769
        gen_op_neon_qshl_u64
2770
      }
2771
    }
2772
};
2773

    
2774
/* [R][U][size - 1] */
2775
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2776
    {
2777
      {
2778
        gen_op_neon_shl_u16,
2779
        gen_op_neon_shl_u32,
2780
        gen_op_neon_shl_u64
2781
      }, {
2782
        gen_op_neon_shl_s16,
2783
        gen_op_neon_shl_s32,
2784
        gen_op_neon_shl_s64
2785
      }
2786
    }, {
2787
      {
2788
        gen_op_neon_rshl_u16,
2789
        gen_op_neon_rshl_u32,
2790
        gen_op_neon_rshl_u64
2791
      }, {
2792
        gen_op_neon_rshl_s16,
2793
        gen_op_neon_rshl_s32,
2794
        gen_op_neon_rshl_s64
2795
      }
2796
    }
2797
};
2798

    
2799
static inline void
2800
gen_op_neon_narrow_u32 ()
2801
{
2802
    /* No-op.  */
2803
}
2804

    
2805
static GenOpFunc *gen_neon_narrow[3] = {
2806
    gen_op_neon_narrow_u8,
2807
    gen_op_neon_narrow_u16,
2808
    gen_op_neon_narrow_u32
2809
};
2810

    
2811
static GenOpFunc *gen_neon_narrow_satu[3] = {
2812
    gen_op_neon_narrow_sat_u8,
2813
    gen_op_neon_narrow_sat_u16,
2814
    gen_op_neon_narrow_sat_u32
2815
};
2816

    
2817
static GenOpFunc *gen_neon_narrow_sats[3] = {
2818
    gen_op_neon_narrow_sat_s8,
2819
    gen_op_neon_narrow_sat_s16,
2820
    gen_op_neon_narrow_sat_s32
2821
};
2822

    
2823
static inline int gen_neon_add(int size)
2824
{
2825
    switch (size) {
2826
    case 0: gen_op_neon_add_u8(); break;
2827
    case 1: gen_op_neon_add_u16(); break;
2828
    case 2: gen_op_addl_T0_T1(); break;
2829
    default: return 1;
2830
    }
2831
    return 0;
2832
}
2833

    
2834
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
2835
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
2836
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
2837
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
2838
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
2839

    
2840
#define GEN_NEON_INTEGER_OP(name) do { \
2841
    switch ((size << 1) | u) { \
2842
    case 0: gen_op_neon_##name##_s8(); break; \
2843
    case 1: gen_op_neon_##name##_u8(); break; \
2844
    case 2: gen_op_neon_##name##_s16(); break; \
2845
    case 3: gen_op_neon_##name##_u16(); break; \
2846
    case 4: gen_op_neon_##name##_s32(); break; \
2847
    case 5: gen_op_neon_##name##_u32(); break; \
2848
    default: return 1; \
2849
    }} while (0)
2850

    
2851
static inline void
2852
gen_neon_movl_scratch_T0(int scratch)
2853
{
2854
  uint32_t offset;
2855

    
2856
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2857
  gen_op_neon_setreg_T0(offset);
2858
}
2859

    
2860
static inline void
2861
gen_neon_movl_scratch_T1(int scratch)
2862
{
2863
  uint32_t offset;
2864

    
2865
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2866
  gen_op_neon_setreg_T1(offset);
2867
}
2868

    
2869
static inline void
2870
gen_neon_movl_T0_scratch(int scratch)
2871
{
2872
  uint32_t offset;
2873

    
2874
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2875
  gen_op_neon_getreg_T0(offset);
2876
}
2877

    
2878
static inline void
2879
gen_neon_movl_T1_scratch(int scratch)
2880
{
2881
  uint32_t offset;
2882

    
2883
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
2884
  gen_op_neon_getreg_T1(offset);
2885
}
2886

    
2887
static inline void gen_op_neon_widen_u32(void)
2888
{
2889
    gen_op_movl_T1_im(0);
2890
}
2891

    
2892
static inline void gen_neon_get_scalar(int size, int reg)
2893
{
2894
    if (size == 1) {
2895
        NEON_GET_REG(T0, reg >> 1, reg & 1);
2896
    } else {
2897
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
2898
        if (reg & 1)
2899
            gen_op_neon_dup_low16();
2900
        else
2901
            gen_op_neon_dup_high16();
2902
    }
2903
}
2904

    
2905
static void gen_neon_unzip(int reg, int q, int tmp, int size)
2906
{
2907
    int n;
2908

    
2909
    for (n = 0; n < q + 1; n += 2) {
2910
        NEON_GET_REG(T0, reg, n);
2911
        NEON_GET_REG(T0, reg, n + n);
2912
        switch (size) {
2913
        case 0: gen_op_neon_unzip_u8(); break;
2914
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
2915
        case 2: /* no-op */; break;
2916
        default: abort();
2917
        }
2918
        gen_neon_movl_scratch_T0(tmp + n);
2919
        gen_neon_movl_scratch_T1(tmp + n + 1);
2920
    }
2921
}
2922

    
2923
static struct {
2924
    int nregs;
2925
    int interleave;
2926
    int spacing;
2927
} neon_ls_element_type[11] = {
2928
    {4, 4, 1},
2929
    {4, 4, 2},
2930
    {4, 1, 1},
2931
    {4, 2, 1},
2932
    {3, 3, 1},
2933
    {3, 3, 2},
2934
    {3, 1, 1},
2935
    {1, 1, 1},
2936
    {2, 2, 1},
2937
    {2, 2, 2},
2938
    {2, 1, 1}
2939
};
2940

    
2941
/* Translate a NEON load/store element instruction.  Return nonzero if the
2942
   instruction is invalid.  */
2943
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
2944
{
2945
    int rd, rn, rm;
2946
    int op;
2947
    int nregs;
2948
    int interleave;
2949
    int stride;
2950
    int size;
2951
    int reg;
2952
    int pass;
2953
    int load;
2954
    int shift;
2955
    uint32_t mask;
2956
    int n;
2957

    
2958
    if (!vfp_enabled(env))
2959
      return 1;
2960
    VFP_DREG_D(rd, insn);
2961
    rn = (insn >> 16) & 0xf;
2962
    rm = insn & 0xf;
2963
    load = (insn & (1 << 21)) != 0;
2964
    if ((insn & (1 << 23)) == 0) {
2965
        /* Load store all elements.  */
2966
        op = (insn >> 8) & 0xf;
2967
        size = (insn >> 6) & 3;
2968
        if (op > 10 || size == 3)
2969
            return 1;
2970
        nregs = neon_ls_element_type[op].nregs;
2971
        interleave = neon_ls_element_type[op].interleave;
2972
        gen_movl_T1_reg(s, rn);
2973
        stride = (1 << size) * interleave;
2974
        for (reg = 0; reg < nregs; reg++) {
2975
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
2976
                gen_movl_T1_reg(s, rn);
2977
                gen_op_addl_T1_im((1 << size) * reg);
2978
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
2979
                gen_movl_T1_reg(s, rn);
2980
                gen_op_addl_T1_im(1 << size);
2981
            }
2982
            for (pass = 0; pass < 2; pass++) {
2983
                if (size == 2) {
2984
                    if (load) {
2985
                        gen_ldst(ldl, s);
2986
                        NEON_SET_REG(T0, rd, pass);
2987
                    } else {
2988
                        NEON_GET_REG(T0, rd, pass);
2989
                        gen_ldst(stl, s);
2990
                    }
2991
                    gen_op_addl_T1_im(stride);
2992
                } else if (size == 1) {
2993
                    if (load) {
2994
                        gen_ldst(lduw, s);
2995
                        gen_op_addl_T1_im(stride);
2996
                        gen_op_movl_T2_T0();
2997
                        gen_ldst(lduw, s);
2998
                        gen_op_addl_T1_im(stride);
2999
                        gen_op_neon_insert_elt(16, 0xffff);
3000
                        NEON_SET_REG(T2, rd, pass);
3001
                    } else {
3002
                        NEON_GET_REG(T2, rd, pass);
3003
                        gen_op_movl_T0_T2();
3004
                        gen_ldst(stw, s);
3005
                        gen_op_addl_T1_im(stride);
3006
                        gen_op_neon_extract_elt(16, 0xffff0000);
3007
                        gen_ldst(stw, s);
3008
                        gen_op_addl_T1_im(stride);
3009
                    }
3010
                } else /* size == 0 */ {
3011
                    if (load) {
3012
                        mask = 0xff;
3013
                        for (n = 0; n < 4; n++) {
3014
                            gen_ldst(ldub, s);
3015
                            gen_op_addl_T1_im(stride);
3016
                            if (n == 0) {
3017
                                gen_op_movl_T2_T0();
3018
                            } else {
3019
                                gen_op_neon_insert_elt(n * 8, ~mask);
3020
                            }
3021
                            mask <<= 8;
3022
                        }
3023
                        NEON_SET_REG(T2, rd, pass);
3024
                    } else {
3025
                        NEON_GET_REG(T2, rd, pass);
3026
                        mask = 0xff;
3027
                        for (n = 0; n < 4; n++) {
3028
                            if (n == 0) {
3029
                                gen_op_movl_T0_T2();
3030
                            } else {
3031
                                gen_op_neon_extract_elt(n * 8, mask);
3032
                            }
3033
                            gen_ldst(stb, s);
3034
                            gen_op_addl_T1_im(stride);
3035
                            mask <<= 8;
3036
                        }
3037
                    }
3038
                }
3039
            }
3040
            rd += neon_ls_element_type[op].spacing;
3041
        }
3042
        stride = nregs * 8;
3043
    } else {
3044
        size = (insn >> 10) & 3;
3045
        if (size == 3) {
3046
            /* Load single element to all lanes.  */
3047
            if (!load)
3048
                return 1;
3049
            size = (insn >> 6) & 3;
3050
            nregs = ((insn >> 8) & 3) + 1;
3051
            stride = (insn & (1 << 5)) ? 2 : 1;
3052
            gen_movl_T1_reg(s, rn);
3053
            for (reg = 0; reg < nregs; reg++) {
3054
                switch (size) {
3055
                case 0:
3056
                    gen_ldst(ldub, s);
3057
                    gen_op_neon_dup_u8(0);
3058
                    break;
3059
                case 1:
3060
                    gen_ldst(lduw, s);
3061
                    gen_op_neon_dup_low16();
3062
                    break;
3063
                case 2:
3064
                    gen_ldst(ldl, s);
3065
                    break;
3066
                case 3:
3067
                    return 1;
3068
                }
3069
                gen_op_addl_T1_im(1 << size);
3070
                NEON_SET_REG(T0, rd, 0);
3071
                NEON_SET_REG(T0, rd, 1);
3072
                rd += stride;
3073
            }
3074
            stride = (1 << size) * nregs;
3075
        } else {
3076
            /* Single element.  */
3077
            pass = (insn >> 7) & 1;
3078
            switch (size) {
3079
            case 0:
3080
                shift = ((insn >> 5) & 3) * 8;
3081
                mask = 0xff << shift;
3082
                stride = 1;
3083
                break;
3084
            case 1:
3085
                shift = ((insn >> 6) & 1) * 16;
3086
                mask = shift ? 0xffff0000 : 0xffff;
3087
                stride = (insn & (1 << 5)) ? 2 : 1;
3088
                break;
3089
            case 2:
3090
                shift = 0;
3091
                mask = 0xffffffff;
3092
                stride = (insn & (1 << 6)) ? 2 : 1;
3093
                break;
3094
            default:
3095
                abort();
3096
            }
3097
            nregs = ((insn >> 8) & 3) + 1;
3098
            gen_movl_T1_reg(s, rn);
3099
            for (reg = 0; reg < nregs; reg++) {
3100
                if (load) {
3101
                    if (size != 2) {
3102
                        NEON_GET_REG(T2, rd, pass);
3103
                    }
3104
                    switch (size) {
3105
                    case 0:
3106
                        gen_ldst(ldub, s);
3107
                        break;
3108
                    case 1:
3109
                        gen_ldst(lduw, s);
3110
                        break;
3111
                    case 2:
3112
                        gen_ldst(ldl, s);
3113
                        NEON_SET_REG(T0, rd, pass);
3114
                        break;
3115
                    }
3116
                    if (size != 2) {
3117
                        gen_op_neon_insert_elt(shift, ~mask);
3118
                        NEON_SET_REG(T0, rd, pass);
3119
                    }
3120
                } else { /* Store */
3121
                    if (size == 2) {
3122
                        NEON_GET_REG(T0, rd, pass);
3123
                    } else {
3124
                        NEON_GET_REG(T2, rd, pass);
3125
                        gen_op_neon_extract_elt(shift, mask);
3126
                    }
3127
                    switch (size) {
3128
                    case 0:
3129
                        gen_ldst(stb, s);
3130
                        break;
3131
                    case 1:
3132
                        gen_ldst(stw, s);
3133
                        break;
3134
                    case 2:
3135
                        gen_ldst(stl, s);
3136
                        break;
3137
                    }
3138
                }
3139
                rd += stride;
3140
                gen_op_addl_T1_im(1 << size);
3141
            }
3142
            stride = nregs * (1 << size);
3143
        }
3144
    }
3145
    if (rm != 15) {
3146
        TCGv base;
3147

    
3148
        base = load_reg(s, rn);
3149
        if (rm == 13) {
3150
            tcg_gen_addi_i32(base, base, stride);
3151
        } else {
3152
            TCGv index;
3153
            index = load_reg(s, rm);
3154
            tcg_gen_add_i32(base, base, index);
3155
            dead_tmp(index);
3156
        }
3157
        store_reg(s, rn, base);
3158
    }
3159
    return 0;
3160
}
3161

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

    
3169
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3170
{
3171
    int op;
3172
    int q;
3173
    int rd, rn, rm;
3174
    int size;
3175
    int shift;
3176
    int pass;
3177
    int count;
3178
    int pairwise;
3179
    int u;
3180
    int n;
3181
    uint32_t imm;
3182

    
3183
    if (!vfp_enabled(env))
3184
      return 1;
3185
    q = (insn & (1 << 6)) != 0;
3186
    u = (insn >> 24) & 1;
3187
    VFP_DREG_D(rd, insn);
3188
    VFP_DREG_N(rn, insn);
3189
    VFP_DREG_M(rm, insn);
3190
    size = (insn >> 20) & 3;
3191
    if ((insn & (1 << 23)) == 0) {
3192
        /* Three register same length.  */
3193
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3194
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3195
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3196
                NEON_GET_REG(T0, rm, pass * 2);
3197
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3198
                gen_neon_movl_scratch_T0(0);
3199
                gen_neon_movl_scratch_T1(1);
3200
                NEON_GET_REG(T0, rn, pass * 2);
3201
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3202
                switch (op) {
3203
                case 1: /* VQADD */
3204
                    if (u) {
3205
                        gen_op_neon_addl_saturate_u64();
3206
                    } else {
3207
                        gen_op_neon_addl_saturate_s64();
3208
                    }
3209
                    break;
3210
                case 5: /* VQSUB */
3211
                    if (u) {
3212
                        gen_op_neon_subl_saturate_u64();
3213
                    } else {
3214
                        gen_op_neon_subl_saturate_s64();
3215
                    }
3216
                    break;
3217
                case 16:
3218
                    if (u) {
3219
                        gen_op_neon_subl_u64();
3220
                    } else {
3221
                        gen_op_neon_addl_u64();
3222
                    }
3223
                    break;
3224
                default:
3225
                    abort();
3226
                }
3227
                NEON_SET_REG(T0, rd, pass * 2);
3228
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3229
            }
3230
            return 0;
3231
        }
3232
        switch (op) {
3233
        case 8: /* VSHL */
3234
        case 9: /* VQSHL */
3235
        case 10: /* VRSHL */
3236
        case 11: /* VQSHL */
3237
            /* Shift operations have Rn and Rm reversed.  */
3238
            {
3239
                int tmp;
3240
                tmp = rn;
3241
                rn = rm;
3242
                rm = tmp;
3243
                pairwise = 0;
3244
            }
3245
            break;
3246
        case 20: /* VPMAX */
3247
        case 21: /* VPMIN */
3248
        case 23: /* VPADD */
3249
            pairwise = 1;
3250
            break;
3251
        case 26: /* VPADD (float) */
3252
            pairwise = (u && size < 2);
3253
            break;
3254
        case 30: /* VPMIN/VPMAX (float) */
3255
            pairwise = u;
3256
            break;
3257
        default:
3258
            pairwise = 0;
3259
            break;
3260
        }
3261
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3262

    
3263
        if (pairwise) {
3264
            /* Pairwise.  */
3265
            if (q)
3266
                n = (pass & 1) * 2;
3267
            else
3268
                n = 0;
3269
            if (pass < q + 1) {
3270
                NEON_GET_REG(T0, rn, n);
3271
                NEON_GET_REG(T1, rn, n + 1);
3272
            } else {
3273
                NEON_GET_REG(T0, rm, n);
3274
                NEON_GET_REG(T1, rm, n + 1);
3275
            }
3276
        } else {
3277
            /* Elementwise.  */
3278
            NEON_GET_REG(T0, rn, pass);
3279
            NEON_GET_REG(T1, rm, pass);
3280
        }
3281
        switch (op) {
3282
        case 0: /* VHADD */
3283
            GEN_NEON_INTEGER_OP(hadd);
3284
            break;
3285
        case 1: /* VQADD */
3286
            switch (size << 1| u) {
3287
            case 0: gen_op_neon_qadd_s8(); break;
3288
            case 1: gen_op_neon_qadd_u8(); break;
3289
            case 2: gen_op_neon_qadd_s16(); break;
3290
            case 3: gen_op_neon_qadd_u16(); break;
3291
            case 4: gen_op_addl_T0_T1_saturate(); break;
3292
            case 5: gen_op_addl_T0_T1_usaturate(); break;
3293
            default: abort();
3294
            }
3295
            break;
3296
        case 2: /* VRHADD */
3297
            GEN_NEON_INTEGER_OP(rhadd);
3298
            break;
3299
        case 3: /* Logic ops.  */
3300
            switch ((u << 2) | size) {
3301
            case 0: /* VAND */
3302
                gen_op_andl_T0_T1();
3303
                break;
3304
            case 1: /* BIC */
3305
                gen_op_bicl_T0_T1();
3306
                break;
3307
            case 2: /* VORR */
3308
                gen_op_orl_T0_T1();
3309
                break;
3310
            case 3: /* VORN */
3311
                gen_op_notl_T1();
3312
                gen_op_orl_T0_T1();
3313
                break;
3314
            case 4: /* VEOR */
3315
                gen_op_xorl_T0_T1();
3316
                break;
3317
            case 5: /* VBSL */
3318
                NEON_GET_REG(T2, rd, pass);
3319
                gen_op_neon_bsl();
3320
                break;
3321
            case 6: /* VBIT */
3322
                NEON_GET_REG(T2, rd, pass);
3323
                gen_op_neon_bit();
3324
                break;
3325
            case 7: /* VBIF */
3326
                NEON_GET_REG(T2, rd, pass);
3327
                gen_op_neon_bif();
3328
                break;
3329
            }
3330
            break;
3331
        case 4: /* VHSUB */
3332
            GEN_NEON_INTEGER_OP(hsub);
3333
            break;
3334
        case 5: /* VQSUB */
3335
            switch ((size << 1) | u) {
3336
            case 0: gen_op_neon_qsub_s8(); break;
3337
            case 1: gen_op_neon_qsub_u8(); break;
3338
            case 2: gen_op_neon_qsub_s16(); break;
3339
            case 3: gen_op_neon_qsub_u16(); break;
3340
            case 4: gen_op_subl_T0_T1_saturate(); break;
3341
            case 5: gen_op_subl_T0_T1_usaturate(); break;
3342
            default: abort();
3343
            }
3344
            break;
3345
        case 6: /* VCGT */
3346
            GEN_NEON_INTEGER_OP(cgt);
3347
            break;
3348
        case 7: /* VCGE */
3349
            GEN_NEON_INTEGER_OP(cge);
3350
            break;
3351
        case 8: /* VSHL */
3352
            switch ((size << 1) | u) {
3353
            case 0: gen_op_neon_shl_s8(); break;
3354
            case 1: gen_op_neon_shl_u8(); break;
3355
            case 2: gen_op_neon_shl_s16(); break;
3356
            case 3: gen_op_neon_shl_u16(); break;
3357
            case 4: gen_op_neon_shl_s32(); break;
3358
            case 5: gen_op_neon_shl_u32(); break;
3359
#if 0
3360
            /* ??? Implementing these is tricky because the vector ops work
3361
               on 32-bit pieces.  */
3362
            case 6: gen_op_neon_shl_s64(); break;
3363
            case 7: gen_op_neon_shl_u64(); break;
3364
#else
3365
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3366
#endif
3367
            }
3368
            break;
3369
        case 9: /* VQSHL */
3370
            switch ((size << 1) | u) {
3371
            case 0: gen_op_neon_qshl_s8(); break;
3372
            case 1: gen_op_neon_qshl_u8(); break;
3373
            case 2: gen_op_neon_qshl_s16(); break;
3374
            case 3: gen_op_neon_qshl_u16(); break;
3375
            case 4: gen_op_neon_qshl_s32(); break;
3376
            case 5: gen_op_neon_qshl_u32(); break;
3377
#if 0
3378
            /* ??? Implementing these is tricky because the vector ops work
3379
               on 32-bit pieces.  */
3380
            case 6: gen_op_neon_qshl_s64(); break;
3381
            case 7: gen_op_neon_qshl_u64(); break;
3382
#else
3383
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3384
#endif
3385
            }
3386
            break;
3387
        case 10: /* VRSHL */
3388
            switch ((size << 1) | u) {
3389
            case 0: gen_op_neon_rshl_s8(); break;
3390
            case 1: gen_op_neon_rshl_u8(); break;
3391
            case 2: gen_op_neon_rshl_s16(); break;
3392
            case 3: gen_op_neon_rshl_u16(); break;
3393
            case 4: gen_op_neon_rshl_s32(); break;
3394
            case 5: gen_op_neon_rshl_u32(); break;
3395
#if 0
3396
            /* ??? Implementing these is tricky because the vector ops work
3397
               on 32-bit pieces.  */
3398
            case 6: gen_op_neon_rshl_s64(); break;
3399
            case 7: gen_op_neon_rshl_u64(); break;
3400
#else
3401
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3402
#endif
3403
            }
3404
            break;
3405
        case 11: /* VQRSHL */
3406
            switch ((size << 1) | u) {
3407
            case 0: gen_op_neon_qrshl_s8(); break;
3408
            case 1: gen_op_neon_qrshl_u8(); break;
3409
            case 2: gen_op_neon_qrshl_s16(); break;
3410
            case 3: gen_op_neon_qrshl_u16(); break;
3411
            case 4: gen_op_neon_qrshl_s32(); break;
3412
            case 5: gen_op_neon_qrshl_u32(); break;
3413
#if 0
3414
            /* ??? Implementing these is tricky because the vector ops work
3415
               on 32-bit pieces.  */
3416
            case 6: gen_op_neon_qrshl_s64(); break;
3417
            case 7: gen_op_neon_qrshl_u64(); break;
3418
#else
3419
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3420
#endif
3421
            }
3422
            break;
3423
        case 12: /* VMAX */
3424
            GEN_NEON_INTEGER_OP(max);
3425
            break;
3426
        case 13: /* VMIN */
3427
            GEN_NEON_INTEGER_OP(min);
3428
            break;
3429
        case 14: /* VABD */
3430
            GEN_NEON_INTEGER_OP(abd);
3431
            break;
3432
        case 15: /* VABA */
3433
            GEN_NEON_INTEGER_OP(abd);
3434
            NEON_GET_REG(T1, rd, pass);
3435
            gen_neon_add(size);
3436
            break;
3437
        case 16:
3438
            if (!u) { /* VADD */
3439
                if (gen_neon_add(size))
3440
                    return 1;
3441
            } else { /* VSUB */
3442
                switch (size) {
3443
                case 0: gen_op_neon_sub_u8(); break;
3444
                case 1: gen_op_neon_sub_u16(); break;
3445
                case 2: gen_op_subl_T0_T1(); break;
3446
                default: return 1;
3447
                }
3448
            }
3449
            break;
3450
        case 17:
3451
            if (!u) { /* VTST */
3452
                switch (size) {
3453
                case 0: gen_op_neon_tst_u8(); break;
3454
                case 1: gen_op_neon_tst_u16(); break;
3455
                case 2: gen_op_neon_tst_u32(); break;
3456
                default: return 1;
3457
                }
3458
            } else { /* VCEQ */
3459
                switch (size) {
3460
                case 0: gen_op_neon_ceq_u8(); break;
3461
                case 1: gen_op_neon_ceq_u16(); break;
3462
                case 2: gen_op_neon_ceq_u32(); break;
3463
                default: return 1;
3464
                }
3465
            }
3466
            break;
3467
        case 18: /* Multiply.  */
3468
            switch (size) {
3469
            case 0: gen_op_neon_mul_u8(); break;
3470
            case 1: gen_op_neon_mul_u16(); break;
3471
            case 2: gen_op_mul_T0_T1(); break;
3472
            default: return 1;
3473
            }
3474
            NEON_GET_REG(T1, rd, pass);
3475
            if (u) { /* VMLS */
3476
                switch (size) {
3477
                case 0: gen_op_neon_rsb_u8(); break;
3478
                case 1: gen_op_neon_rsb_u16(); break;
3479
                case 2: gen_op_rsbl_T0_T1(); break;
3480
                default: return 1;
3481
                }
3482
            } else { /* VMLA */
3483
                gen_neon_add(size);
3484
            }
3485
            break;
3486
        case 19: /* VMUL */
3487
            if (u) { /* polynomial */
3488
                gen_op_neon_mul_p8();
3489
            } else { /* Integer */
3490
                switch (size) {
3491
                case 0: gen_op_neon_mul_u8(); break;
3492
                case 1: gen_op_neon_mul_u16(); break;
3493
                case 2: gen_op_mul_T0_T1(); break;
3494
                default: return 1;
3495
                }
3496
            }
3497
            break;
3498
        case 20: /* VPMAX */
3499
            GEN_NEON_INTEGER_OP(pmax);
3500
            break;
3501
        case 21: /* VPMIN */
3502
            GEN_NEON_INTEGER_OP(pmin);
3503
            break;
3504
        case 22: /* Hultiply high.  */
3505
            if (!u) { /* VQDMULH */
3506
                switch (size) {
3507
                case 1: gen_op_neon_qdmulh_s16(); break;
3508
                case 2: gen_op_neon_qdmulh_s32(); break;
3509
                default: return 1;
3510
                }
3511
            } else { /* VQRDHMUL */
3512
                switch (size) {
3513
                case 1: gen_op_neon_qrdmulh_s16(); break;
3514
                case 2: gen_op_neon_qrdmulh_s32(); break;
3515
                default: return 1;
3516
                }
3517
            }
3518
            break;
3519
        case 23: /* VPADD */
3520
            if (u)
3521
                return 1;
3522
            switch (size) {
3523
            case 0: gen_op_neon_padd_u8(); break;
3524
            case 1: gen_op_neon_padd_u16(); break;
3525
            case 2: gen_op_addl_T0_T1(); break;
3526
            default: return 1;
3527
            }
3528
            break;
3529
        case 26: /* Floating point arithnetic.  */
3530
            switch ((u << 2) | size) {
3531
            case 0: /* VADD */
3532
                gen_op_neon_add_f32();
3533
                break;
3534
            case 2: /* VSUB */
3535
                gen_op_neon_sub_f32();
3536
                break;
3537
            case 4: /* VPADD */
3538
                gen_op_neon_add_f32();
3539
                break;
3540
            case 6: /* VABD */
3541
                gen_op_neon_abd_f32();
3542
                break;
3543
            default:
3544
                return 1;
3545
            }
3546
            break;
3547
        case 27: /* Float multiply.  */
3548
            gen_op_neon_mul_f32();
3549
            if (!u) {
3550
                NEON_GET_REG(T1, rd, pass);
3551
                if (size == 0) {
3552
                    gen_op_neon_add_f32();
3553
                } else {
3554
                    gen_op_neon_rsb_f32();
3555
                }
3556
            }
3557
            break;
3558
        case 28: /* Float compare.  */
3559
            if (!u) {
3560
                gen_op_neon_ceq_f32();
3561
            } else {
3562
                if (size == 0)
3563
                    gen_op_neon_cge_f32();
3564
                else
3565
                    gen_op_neon_cgt_f32();
3566
            }
3567
            break;
3568
        case 29: /* Float compare absolute.  */
3569
            if (!u)
3570
                return 1;
3571
            if (size == 0)
3572
                gen_op_neon_acge_f32();
3573
            else
3574
                gen_op_neon_acgt_f32();
3575
            break;
3576
        case 30: /* Float min/max.  */
3577
            if (size == 0)
3578
                gen_op_neon_max_f32();
3579
            else
3580
                gen_op_neon_min_f32();
3581
            break;
3582
        case 31:
3583
            if (size == 0)
3584
                gen_op_neon_recps_f32();
3585
            else
3586
                gen_op_neon_rsqrts_f32();
3587
            break;
3588
        default:
3589
            abort();
3590
        }
3591
        /* Save the result.  For elementwise operations we can put it
3592
           straight into the destination register.  For pairwise operations
3593
           we have to be careful to avoid clobbering the source operands.  */
3594
        if (pairwise && rd == rm) {
3595
            gen_neon_movl_scratch_T0(pass);
3596
        } else {
3597
            NEON_SET_REG(T0, rd, pass);
3598
        }
3599

    
3600
        } /* for pass */
3601
        if (pairwise && rd == rm) {
3602
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3603
                gen_neon_movl_T0_scratch(pass);
3604
                NEON_SET_REG(T0, rd, pass);
3605
            }
3606
        }
3607
    } else if (insn & (1 << 4)) {
3608
        if ((insn & 0x00380080) != 0) {
3609
            /* Two registers and shift.  */
3610
            op = (insn >> 8) & 0xf;
3611
            if (insn & (1 << 7)) {
3612
                /* 64-bit shift.   */
3613
                size = 3;
3614
            } else {
3615
                size = 2;
3616
                while ((insn & (1 << (size + 19))) == 0)
3617
                    size--;
3618
            }
3619
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3620
            /* To avoid excessive dumplication of ops we implement shift
3621
               by immediate using the variable shift operations.  */
3622
            if (op < 8) {
3623
                /* Shift by immediate:
3624
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
3625
                /* Right shifts are encoded as N - shift, where N is the
3626
                   element size in bits.  */
3627
                if (op <= 4)
3628
                    shift = shift - (1 << (size + 3));
3629
                else
3630
                    shift++;
3631
                if (size == 3) {
3632
                    count = q + 1;
3633
                } else {
3634
                    count = q ? 4: 2;
3635
                }
3636
                switch (size) {
3637
                case 0:
3638
                    imm = (uint8_t) shift;
3639
                    imm |= imm << 8;
3640
                    imm |= imm << 16;
3641
                    break;
3642
                case 1:
3643
                    imm = (uint16_t) shift;
3644
                    imm |= imm << 16;
3645
                    break;
3646
                case 2:
3647
                case 3:
3648
                    imm = shift;
3649
                    break;
3650
                default:
3651
                    abort();
3652
                }
3653

    
3654
                for (pass = 0; pass < count; pass++) {
3655
                    if (size < 3) {
3656
                        /* Operands in T0 and T1.  */
3657
                        gen_op_movl_T1_im(imm);
3658
                        NEON_GET_REG(T0, rm, pass);
3659
                    } else {
3660
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3661
                        gen_op_movl_T0_im(imm);
3662
                        gen_neon_movl_scratch_T0(0);
3663
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3664
                        gen_neon_movl_scratch_T0(1);
3665
                        NEON_GET_REG(T0, rm, pass * 2);
3666
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
3667
                    }
3668

    
3669
                    if (gen_neon_shift_im[op][u][size] == NULL)
3670
                        return 1;
3671
                    gen_neon_shift_im[op][u][size]();
3672

    
3673
                    if (op == 1 || op == 3) {
3674
                        /* Accumulate.  */
3675
                        if (size == 3) {
3676
                            gen_neon_movl_scratch_T0(0);
3677
                            gen_neon_movl_scratch_T1(1);
3678
                            NEON_GET_REG(T0, rd, pass * 2);
3679
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
3680
                            gen_op_neon_addl_u64();
3681
                        } else {
3682
                            NEON_GET_REG(T1, rd, pass);
3683
                            gen_neon_add(size);
3684
                        }
3685
                    } else if (op == 4 || (op == 5 && u)) {
3686
                        /* Insert */
3687
                        if (size == 3) {
3688
                            cpu_abort(env, "VS[LR]I.64 not implemented");
3689
                        }
3690
                        switch (size) {
3691
                        case 0:
3692
                            if (op == 4)
3693
                                imm = 0xff >> -shift;
3694
                            else
3695
                                imm = (uint8_t)(0xff << shift);
3696
                            imm |= imm << 8;
3697
                            imm |= imm << 16;
3698
                            break;
3699
                        case 1:
3700
                            if (op == 4)
3701
                                imm = 0xffff >> -shift;
3702
                            else
3703
                                imm = (uint16_t)(0xffff << shift);
3704
                            imm |= imm << 16;
3705
                            break;
3706
                        case 2:
3707
                            if (op == 4)
3708
                                imm = 0xffffffffu >> -shift;
3709
                            else
3710
                                imm = 0xffffffffu << shift;
3711
                            break;
3712
                        default:
3713
                            abort();
3714
                        }
3715
                        NEON_GET_REG(T1, rd, pass);
3716
                        gen_op_movl_T2_im(imm);
3717
                        gen_op_neon_bsl();
3718
                    }
3719
                    if (size == 3) {
3720
                        NEON_SET_REG(T0, rd, pass * 2);
3721
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
3722
                    } else {
3723
                        NEON_SET_REG(T0, rd, pass);
3724
                    }
3725
                } /* for pass */
3726
            } else if (op < 10) {
3727
                /* Shift by immedaiate and narrow:
3728
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
3729
                shift = shift - (1 << (size + 3));
3730
                size++;
3731
                if (size == 3) {
3732
                    count = q + 1;
3733
                } else {
3734
                    count = q ? 4: 2;
3735
                }
3736
                switch (size) {
3737
                case 1:
3738
                    imm = (uint16_t) shift;
3739
                    imm |= imm << 16;
3740
                    break;
3741
                case 2:
3742
                case 3:
3743
                    imm = shift;
3744
                    break;
3745
                default:
3746
                    abort();
3747
                }
3748

    
3749
                /* Processing MSB first means we need to do less shuffling at
3750
                   the end.  */
3751
                for (pass =  count - 1; pass >= 0; pass--) {
3752
                    /* Avoid clobbering the second operand before it has been
3753
                       written.  */
3754
                    n = pass;
3755
                    if (rd == rm)
3756
                        n ^= (count - 1);
3757
                    else
3758
                        n = pass;
3759

    
3760
                    if (size < 3) {
3761
                        /* Operands in T0 and T1.  */
3762
                        gen_op_movl_T1_im(imm);
3763
                        NEON_GET_REG(T0, rm, n);
3764
                    } else {
3765
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3766
                        gen_op_movl_T0_im(imm);
3767
                        gen_neon_movl_scratch_T0(0);
3768
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3769
                        gen_neon_movl_scratch_T0(1);
3770
                        NEON_GET_REG(T0, rm, n * 2);
3771
                        NEON_GET_REG(T0, rm, n * 2 + 1);
3772
                    }
3773

    
3774
                    gen_neon_shift_im_narrow[q][u][size - 1]();
3775

    
3776
                    if (size < 3 && (pass & 1) == 0) {
3777
                        gen_neon_movl_scratch_T0(0);
3778
                    } else {
3779
                        uint32_t offset;
3780

    
3781
                        if (size < 3)
3782
                            gen_neon_movl_T1_scratch(0);
3783

    
3784
                        if (op == 8 && !u) {
3785
                            gen_neon_narrow[size - 1]();
3786
                        } else {
3787
                            if (op == 8)
3788
                                gen_neon_narrow_sats[size - 2]();
3789
                            else
3790
                                gen_neon_narrow_satu[size - 1]();
3791
                        }
3792
                        if (size == 3)
3793
                            offset = neon_reg_offset(rd, n);
3794
                        else
3795
                            offset = neon_reg_offset(rd, n >> 1);
3796
                        gen_op_neon_setreg_T0(offset);
3797
                    }
3798
                } /* for pass */
3799
            } else if (op == 10) {
3800
                /* VSHLL */
3801
                if (q)
3802
                    return 1;
3803
                for (pass = 0; pass < 2; pass++) {
3804
                    /* Avoid clobbering the input operand.  */
3805
                    if (rd == rm)
3806
                        n = 1 - pass;
3807
                    else
3808
                        n = pass;
3809

    
3810
                    NEON_GET_REG(T0, rm, n);
3811
                    GEN_NEON_INTEGER_OP(widen);
3812
                    if (shift != 0) {
3813
                        /* The shift is less than the width of the source
3814
                           type, so in some cases we can just
3815
                           shift the whole register.  */
3816
                        if (size == 1 || (size == 0 && u)) {
3817
                            gen_op_shll_T0_im(shift);
3818
                            gen_op_shll_T1_im(shift);
3819
                        } else {
3820
                            switch (size) {
3821
                            case 0: gen_op_neon_shll_u16(shift); break;
3822
                            case 2: gen_op_neon_shll_u64(shift); break;
3823
                            default: abort();
3824
                            }
3825
                        }
3826
                    }
3827
                    NEON_SET_REG(T0, rd, n * 2);
3828
                    NEON_SET_REG(T1, rd, n * 2 + 1);
3829
                }
3830
            } else if (op == 15 || op == 16) {
3831
                /* VCVT fixed-point.  */
3832
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
3833
                    gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
3834
                    if (op & 1) {
3835
                        if (u)
3836
                            gen_op_vfp_ultos(shift);
3837
                        else
3838
                            gen_op_vfp_sltos(shift);
3839
                    } else {
3840
                        if (u)
3841
                            gen_op_vfp_touls(shift);
3842
                        else
3843
                            gen_op_vfp_tosls(shift);
3844
                    }
3845
                    gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
3846
                }
3847
            } else {
3848
                return 1;
3849
            }
3850
        } else { /* (insn & 0x00380080) == 0 */
3851
            int invert;
3852

    
3853
            op = (insn >> 8) & 0xf;
3854
            /* One register and immediate.  */
3855
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
3856
            invert = (insn & (1 << 5)) != 0;
3857
            switch (op) {
3858
            case 0: case 1:
3859
                /* no-op */
3860
                break;
3861
            case 2: case 3:
3862
                imm <<= 8;
3863
                break;
3864
            case 4: case 5:
3865
                imm <<= 16;
3866
                break;
3867
            case 6: case 7:
3868
                imm <<= 24;
3869
                break;
3870
            case 8: case 9:
3871
                imm |= imm << 16;
3872
                break;
3873
            case 10: case 11:
3874
                imm = (imm << 8) | (imm << 24);
3875
                break;
3876
            case 12:
3877
                imm = (imm < 8) | 0xff;
3878
                break;
3879
            case 13:
3880
                imm = (imm << 16) | 0xffff;
3881
                break;
3882
            case 14:
3883
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
3884
                if (invert)
3885
                    imm = ~imm;
3886
                break;
3887
            case 15:
3888
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
3889
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
3890
                break;
3891
            }
3892
            if (invert)
3893
                imm = ~imm;
3894

    
3895
            if (op != 14 || !invert)
3896
                gen_op_movl_T1_im(imm);
3897

    
3898
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3899
                if (op & 1 && op < 12) {
3900
                    NEON_GET_REG(T0, rd, pass);
3901
                    if (invert) {
3902
                        /* The immediate value has already been inverted, so
3903
                           BIC becomes AND.  */
3904
                        gen_op_andl_T0_T1();
3905
                    } else {
3906
                        gen_op_orl_T0_T1();
3907
                    }
3908
                    NEON_SET_REG(T0, rd, pass);
3909
                } else {
3910
                    if (op == 14 && invert) {
3911
                        uint32_t tmp;
3912
                        tmp = 0;
3913
                        for (n = 0; n < 4; n++) {
3914
                            if (imm & (1 << (n + (pass & 1) * 4)))
3915
                                tmp |= 0xff << (n * 8);
3916
                        }
3917
                        gen_op_movl_T1_im(tmp);
3918
                    }
3919
                    /* VMOV, VMVN.  */
3920
                    NEON_SET_REG(T1, rd, pass);
3921
                }
3922
            }
3923
        }
3924
    } else { /* (insn & 0x00800010 == 0x00800010) */
3925
        if (size != 3) {
3926
            op = (insn >> 8) & 0xf;
3927
            if ((insn & (1 << 6)) == 0) {
3928
                /* Three registers of different lengths.  */
3929
                int src1_wide;
3930
                int src2_wide;
3931
                int prewiden;
3932
                /* prewiden, src1_wide, src2_wide */
3933
                static const int neon_3reg_wide[16][3] = {
3934
                    {1, 0, 0}, /* VADDL */
3935
                    {1, 1, 0}, /* VADDW */
3936
                    {1, 0, 0}, /* VSUBL */
3937
                    {1, 1, 0}, /* VSUBW */
3938
                    {0, 1, 1}, /* VADDHN */
3939
                    {0, 0, 0}, /* VABAL */
3940
                    {0, 1, 1}, /* VSUBHN */
3941
                    {0, 0, 0}, /* VABDL */
3942
                    {0, 0, 0}, /* VMLAL */
3943
                    {0, 0, 0}, /* VQDMLAL */
3944
                    {0, 0, 0}, /* VMLSL */
3945
                    {0, 0, 0}, /* VQDMLSL */
3946
                    {0, 0, 0}, /* Integer VMULL */
3947
                    {0, 0, 0}, /* VQDMULL */
3948
                    {0, 0, 0}  /* Polynomial VMULL */
3949
                };
3950

    
3951
                prewiden = neon_3reg_wide[op][0];
3952
                src1_wide = neon_3reg_wide[op][1];
3953
                src2_wide = neon_3reg_wide[op][2];
3954

    
3955
                /* Avoid overlapping operands.  Wide source operands are
3956
                   always aligned so will never overlap with wide
3957
                   destinations in problematic ways.  */
3958
                if (rd == rm) {
3959
                    NEON_GET_REG(T2, rm, 1);
3960
                } else if (rd == rn) {
3961
                    NEON_GET_REG(T2, rn, 1);
3962
                }
3963
                for (pass = 0; pass < 2; pass++) {
3964
                    /* Load the second operand into env->vfp.scratch.
3965
                       Also widen narrow operands.  */
3966
                    if (pass == 1 && rd == rm) {
3967
                        if (prewiden) {
3968
                            gen_op_movl_T0_T2();
3969
                        } else {
3970
                            gen_op_movl_T1_T2();
3971
                        }
3972
                    } else {
3973
                        if (src2_wide) {
3974
                            NEON_GET_REG(T0, rm, pass * 2);
3975
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
3976
                        } else {
3977
                            if (prewiden) {
3978
                                NEON_GET_REG(T0, rm, pass);
3979
                            } else {
3980
                                NEON_GET_REG(T1, rm, pass);
3981
                            }
3982
                        }
3983
                    }
3984
                    if (prewiden && !src2_wide) {
3985
                        GEN_NEON_INTEGER_OP(widen);
3986
                    }
3987
                    if (prewiden || src2_wide) {
3988
                        gen_neon_movl_scratch_T0(0);
3989
                        gen_neon_movl_scratch_T1(1);
3990
                    }
3991

    
3992
                    /* Load the first operand.  */
3993
                    if (pass == 1 && rd == rn) {
3994
                        gen_op_movl_T0_T2();
3995
                    } else {
3996
                        if (src1_wide) {
3997
                            NEON_GET_REG(T0, rn, pass * 2);
3998
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
3999
                        } else {
4000
                            NEON_GET_REG(T0, rn, pass);
4001
                        }
4002
                    }
4003
                    if (prewiden && !src1_wide) {
4004
                        GEN_NEON_INTEGER_OP(widen);
4005
                    }
4006
                    switch (op) {
4007
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4008
                        switch (size) {
4009
                        case 0: gen_op_neon_addl_u16(); break;
4010
                        case 1: gen_op_neon_addl_u32(); break;
4011
                        case 2: gen_op_neon_addl_u64(); break;
4012
                        default: abort();
4013
                        }
4014
                        break;
4015
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4016
                        switch (size) {
4017
                        case 0: gen_op_neon_subl_u16(); break;
4018
                        case 1: gen_op_neon_subl_u32(); break;
4019
                        case 2: gen_op_neon_subl_u64(); break;
4020
                        default: abort();
4021
                        }
4022
                        break;
4023
                    case 5: case 7: /* VABAL, VABDL */
4024
                        switch ((size << 1) | u) {
4025
                        case 0: gen_op_neon_abdl_s16(); break;
4026
                        case 1: gen_op_neon_abdl_u16(); break;
4027
                        case 2: gen_op_neon_abdl_s32(); break;
4028
                        case 3: gen_op_neon_abdl_u32(); break;
4029
                        case 4: gen_op_neon_abdl_s64(); break;
4030
                        case 5: gen_op_neon_abdl_u64(); break;
4031
                        default: abort();
4032
                        }
4033
                        break;
4034
                    case 8: case 9: case 10: case 11: case 12: case 13:
4035
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4036
                        switch ((size << 1) | u) {
4037
                        case 0: gen_op_neon_mull_s8(); break;
4038
                        case 1: gen_op_neon_mull_u8(); break;
4039
                        case 2: gen_op_neon_mull_s16(); break;
4040
                        case 3: gen_op_neon_mull_u16(); break;
4041
                        case 4: gen_op_imull_T0_T1(); break;
4042
                        case 5: gen_op_mull_T0_T1(); break;
4043
                        default: abort();
4044
                        }
4045
                        break;
4046
                    case 14: /* Polynomial VMULL */
4047
                        cpu_abort(env, "Polynomial VMULL not implemented");
4048

    
4049
                    default: /* 15 is RESERVED.  */
4050
                        return 1;
4051
                    }
4052
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4053
                        /* Accumulate.  */
4054
                        if (op == 10 || op == 11) {
4055
                            switch (size) {
4056
                            case 0: gen_op_neon_negl_u16(); break;
4057
                            case 1: gen_op_neon_negl_u32(); break;
4058
                            case 2: gen_op_neon_negl_u64(); break;
4059
                            default: abort();
4060
                            }
4061
                        }
4062

    
4063
                        gen_neon_movl_scratch_T0(0);
4064
                        gen_neon_movl_scratch_T1(1);
4065

    
4066
                        if (op != 13) {
4067
                            NEON_GET_REG(T0, rd, pass * 2);
4068
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4069
                        }
4070

    
4071
                        switch (op) {
4072
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4073
                            switch (size) {
4074
                            case 0: gen_op_neon_addl_u16(); break;
4075
                            case 1: gen_op_neon_addl_u32(); break;
4076
                            case 2: gen_op_neon_addl_u64(); break;
4077
                            default: abort();
4078
                            }
4079
                            break;
4080
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4081
                            switch (size) {
4082
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4083
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4084
                            default: abort();
4085
                            }
4086
                            /* Fall through.  */
4087
                        case 13: /* VQDMULL */
4088
                            switch (size) {
4089
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4090
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4091
                            default: abort();
4092
                            }
4093
                            break;
4094
                        default:
4095
                            abort();
4096
                        }
4097
                        NEON_SET_REG(T0, rd, pass * 2);
4098
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4099
                    } else if (op == 4 || op == 6) {
4100
                        /* Narrowing operation.  */
4101
                        if (u) {
4102
                            switch (size) {
4103
                            case 0: gen_op_neon_narrow_high_u8(); break;
4104
                            case 1: gen_op_neon_narrow_high_u16(); break;
4105
                            case 2: gen_op_movl_T0_T1(); break;
4106
                            default: abort();
4107
                            }
4108
                        } else {
4109
                            switch (size) {
4110
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4111
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4112
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4113
                            default: abort();
4114
                            }
4115
                        }
4116
                        NEON_SET_REG(T0, rd, pass);
4117
                    } else {
4118
                        /* Write back the result.  */
4119
                        NEON_SET_REG(T0, rd, pass * 2);
4120
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4121
                    }
4122
                }
4123
            } else {
4124
                /* Two registers and a scalar.  */
4125
                switch (op) {
4126
                case 0: /* Integer VMLA scalar */
4127
                case 1: /* Float VMLA scalar */
4128
                case 4: /* Integer VMLS scalar */
4129
                case 5: /* Floating point VMLS scalar */
4130
                case 8: /* Integer VMUL scalar */
4131
                case 9: /* Floating point VMUL scalar */
4132
                case 12: /* VQDMULH scalar */
4133
                case 13: /* VQRDMULH scalar */
4134
                    gen_neon_get_scalar(size, rm);
4135
                    gen_op_movl_T2_T0();
4136
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4137
                        if (pass != 0)
4138
                            gen_op_movl_T0_T2();
4139
                        NEON_GET_REG(T1, rn, pass);
4140
                        if (op == 12) {
4141
                            if (size == 1) {
4142
                                gen_op_neon_qdmulh_s16();
4143
                            } else {
4144
                                gen_op_neon_qdmulh_s32();
4145
                            }
4146
                        } else if (op == 13) {
4147
                            if (size == 1) {
4148
                                gen_op_neon_qrdmulh_s16();
4149
                            } else {
4150
                                gen_op_neon_qrdmulh_s32();
4151
                            }
4152
                        } else if (op & 1) {
4153
                            gen_op_neon_mul_f32();
4154
                        } else {
4155
                            switch (size) {
4156
                            case 0: gen_op_neon_mul_u8(); break;
4157
                            case 1: gen_op_neon_mul_u16(); break;
4158
                            case 2: gen_op_mul_T0_T1(); break;
4159
                            default: return 1;
4160
                            }
4161
                        }
4162
                        if (op < 8) {
4163
                            /* Accumulate.  */
4164
                            NEON_GET_REG(T1, rd, pass);
4165
                            switch (op) {
4166
                            case 0:
4167
                                gen_neon_add(size);
4168
                                break;
4169
                            case 1:
4170
                                gen_op_neon_add_f32();
4171
                                break;
4172
                            case 4:
4173
                                switch (size) {
4174
                                case 0: gen_op_neon_rsb_u8(); break;
4175
                                case 1: gen_op_neon_rsb_u16(); break;
4176
                                case 2: gen_op_rsbl_T0_T1(); break;
4177
                                default: return 1;
4178
                                }
4179
                                break;
4180
                            case 5:
4181
                                gen_op_neon_rsb_f32();
4182
                                break;
4183
                            default:
4184
                                abort();
4185
                            }
4186
                        }
4187
                        NEON_SET_REG(T0, rd, pass);
4188
                    }
4189
                    break;
4190
                case 2: /* VMLAL sclar */
4191
                case 3: /* VQDMLAL scalar */
4192
                case 6: /* VMLSL scalar */
4193
                case 7: /* VQDMLSL scalar */
4194
                case 10: /* VMULL scalar */
4195
                case 11: /* VQDMULL scalar */
4196
                    if (rd == rn) {
4197
                        /* Save overlapping operands before they are
4198
                           clobbered.  */
4199
                        NEON_GET_REG(T0, rn, 1);
4200
                        gen_neon_movl_scratch_T0(2);
4201
                    }
4202
                    gen_neon_get_scalar(size, rm);
4203
                    gen_op_movl_T2_T0();
4204
                    for (pass = 0; pass < 2; pass++) {
4205
                        if (pass != 0) {
4206
                            gen_op_movl_T0_T2();
4207
                        }
4208
                        if (pass != 0 && rd == rn) {
4209
                            gen_neon_movl_T1_scratch(2);
4210
                        } else {
4211
                            NEON_GET_REG(T1, rn, pass);
4212
                        }
4213
                        switch ((size << 1) | u) {
4214
                        case 0: gen_op_neon_mull_s8(); break;
4215
                        case 1: gen_op_neon_mull_u8(); break;
4216
                        case 2: gen_op_neon_mull_s16(); break;
4217
                        case 3: gen_op_neon_mull_u16(); break;
4218
                        case 4: gen_op_imull_T0_T1(); break;
4219
                        case 5: gen_op_mull_T0_T1(); break;
4220
                        default: abort();
4221
                        }
4222
                        if (op == 6 || op == 7) {
4223
                            switch (size) {
4224
                            case 0: gen_op_neon_negl_u16(); break;
4225
                            case 1: gen_op_neon_negl_u32(); break;
4226
                            case 2: gen_op_neon_negl_u64(); break;
4227
                            default: abort();
4228
                            }
4229
                        }
4230
                        gen_neon_movl_scratch_T0(0);
4231
                        gen_neon_movl_scratch_T1(1);
4232
                        NEON_GET_REG(T0, rd, pass * 2);
4233
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4234
                        switch (op) {
4235
                        case 2: case 6:
4236
                            switch (size) {
4237
                            case 0: gen_op_neon_addl_u16(); break;
4238
                            case 1: gen_op_neon_addl_u32(); break;
4239
                            case 2: gen_op_neon_addl_u64(); break;
4240
                            default: abort();
4241
                            }
4242
                            break;
4243
                        case 3: case 7:
4244
                            switch (size) {
4245
                            case 1:
4246
                                gen_op_neon_addl_saturate_s32();
4247
                                gen_op_neon_addl_saturate_s32();
4248
                                break;
4249
                            case 2:
4250
                                gen_op_neon_addl_saturate_s64();
4251
                                gen_op_neon_addl_saturate_s64();
4252
                                break;
4253
                            default: abort();
4254
                            }
4255
                            break;
4256
                        case 10:
4257
                            /* no-op */
4258
                            break;
4259
                        case 11:
4260
                            switch (size) {
4261
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4262
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4263
                            default: abort();
4264
                            }
4265
                            break;
4266
                        default:
4267
                            abort();
4268
                        }
4269
                        NEON_SET_REG(T0, rd, pass * 2);
4270
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4271
                    }
4272
                    break;
4273
                default: /* 14 and 15 are RESERVED */
4274
                    return 1;
4275
                }
4276
            }
4277
        } else { /* size == 3 */
4278
            if (!u) {
4279
                /* Extract.  */
4280
                int reg;
4281
                imm = (insn >> 8) & 0xf;
4282
                reg = rn;
4283
                count = q ? 4 : 2;
4284
                n = imm >> 2;
4285
                NEON_GET_REG(T0, reg, n);
4286
                for (pass = 0; pass < count; pass++) {
4287
                    n++;
4288
                    if (n > count) {
4289
                        reg = rm;
4290
                        n -= count;
4291
                    }
4292
                    if (imm & 3) {
4293
                        NEON_GET_REG(T1, reg, n);
4294
                        gen_op_neon_extract((insn << 3) & 0x1f);
4295
                    }
4296
                    /* ??? This is broken if rd and rm overlap */
4297
                    NEON_SET_REG(T0, rd, pass);
4298
                    if (imm & 3) {
4299
                        gen_op_movl_T0_T1();
4300
                    } else {
4301
                        NEON_GET_REG(T0, reg, n);
4302
                    }
4303
                }
4304
            } else if ((insn & (1 << 11)) == 0) {
4305
                /* Two register misc.  */
4306
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4307
                size = (insn >> 18) & 3;
4308
                switch (op) {
4309
                case 0: /* VREV64 */
4310
                    if (size == 3)
4311
                        return 1;
4312
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4313
                        NEON_GET_REG(T0, rm, pass * 2);
4314
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4315
                        switch (size) {
4316
                        case 0: gen_op_rev_T0(); break;
4317
                        case 1: gen_op_revh_T0(); break;
4318
                        case 2: /* no-op */ break;
4319
                        default: abort();
4320
                        }
4321
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4322
                        if (size == 2) {
4323
                            NEON_SET_REG(T1, rd, pass * 2);
4324
                        } else {
4325
                            gen_op_movl_T0_T1();
4326
                            switch (size) {
4327
                            case 0: gen_op_rev_T0(); break;
4328
                            case 1: gen_op_revh_T0(); break;
4329
                            default: abort();
4330
                            }
4331
                            NEON_SET_REG(T0, rd, pass * 2);
4332
                        }
4333
                    }
4334
                    break;
4335
                case 4: case 5: /* VPADDL */
4336
                case 12: case 13: /* VPADAL */
4337
                    if (size < 2)
4338
                        goto elementwise;
4339
                    if (size == 3)
4340
                        return 1;
4341
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4342
                        NEON_GET_REG(T0, rm, pass * 2);
4343
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4344
                        if (op & 1)
4345
                            gen_op_neon_paddl_u32();
4346
                        else
4347
                            gen_op_neon_paddl_s32();
4348
                        if (op >= 12) {
4349
                            /* Accumulate.  */
4350
                            gen_neon_movl_scratch_T0(0);
4351
                            gen_neon_movl_scratch_T1(1);
4352

    
4353
                            NEON_GET_REG(T0, rd, pass * 2);
4354
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4355
                            gen_op_neon_addl_u64();
4356
                        }
4357
                        NEON_SET_REG(T0, rd, pass * 2);
4358
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4359
                    }
4360
                    break;
4361
                case 33: /* VTRN */
4362
                    if (size == 2) {
4363
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4364
                            NEON_GET_REG(T0, rm, n);
4365
                            NEON_GET_REG(T1, rd, n + 1);
4366
                            NEON_SET_REG(T1, rm, n);
4367
                            NEON_SET_REG(T0, rd, n + 1);
4368
                        }
4369
                    } else {
4370
                        goto elementwise;
4371
                    }
4372
                    break;
4373
                case 34: /* VUZP */
4374
                    /* Reg  Before       After
4375
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4376
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4377
                     */
4378
                    if (size == 3)
4379
                        return 1;
4380
                    gen_neon_unzip(rd, q, 0, size);
4381
                    gen_neon_unzip(rm, q, 4, size);
4382
                    if (q) {
4383
                        static int unzip_order_q[8] =
4384
                            {0, 2, 4, 6, 1, 3, 5, 7};
4385
                        for (n = 0; n < 8; n++) {
4386
                            int reg = (n < 4) ? rd : rm;
4387
                            gen_neon_movl_T0_scratch(unzip_order_q[n]);
4388
                            NEON_SET_REG(T0, reg, n % 4);
4389
                        }
4390
                    } else {
4391
                        static int unzip_order[4] =
4392
                            {0, 4, 1, 5};
4393
                        for (n = 0; n < 4; n++) {
4394
                            int reg = (n < 2) ? rd : rm;
4395
                            gen_neon_movl_T0_scratch(unzip_order[n]);
4396
                            NEON_SET_REG(T0, reg, n % 2);
4397
                        }
4398
                    }
4399
                    break;
4400
                case 35: /* VZIP */
4401
                    /* Reg  Before       After
4402
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
4403
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
4404
                     */
4405
                    if (size == 3)
4406
                        return 1;
4407
                    count = (q ? 4 : 2);
4408
                    for (n = 0; n < count; n++) {
4409
                        NEON_GET_REG(T0, rd, n);
4410
                        NEON_GET_REG(T1, rd, n);
4411
                        switch (size) {
4412
                        case 0: gen_op_neon_zip_u8(); break;
4413
                        case 1: gen_op_neon_zip_u16(); break;
4414
                        case 2: /* no-op */; break;
4415
                        default: abort();
4416
                        }
4417
                        gen_neon_movl_scratch_T0(n * 2);
4418
                        gen_neon_movl_scratch_T1(n * 2 + 1);
4419
                    }
4420
                    for (n = 0; n < count * 2; n++) {
4421
                        int reg = (n < count) ? rd : rm;
4422
                        gen_neon_movl_T0_scratch(n);
4423
                        NEON_SET_REG(T0, reg, n % count);
4424
                    }
4425
                    break;
4426
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4427
                    for (pass = 0; pass < 2; pass++) {
4428
                        if (rd == rm + 1) {
4429
                            n = 1 - pass;
4430
                        } else {
4431
                            n = pass;
4432
                        }
4433
                        NEON_GET_REG(T0, rm, n * 2);
4434
                        NEON_GET_REG(T1, rm, n * 2 + 1);
4435
                        if (op == 36 && q == 0) {
4436
                            switch (size) {
4437
                            case 0: gen_op_neon_narrow_u8(); break;
4438
                            case 1: gen_op_neon_narrow_u16(); break;
4439
                            case 2: /* no-op */ break;
4440
                            default: return 1;
4441
                            }
4442
                        } else if (q) {
4443
                            switch (size) {
4444
                            case 0: gen_op_neon_narrow_sat_u8(); break;
4445
                            case 1: gen_op_neon_narrow_sat_u16(); break;
4446
                            case 2: gen_op_neon_narrow_sat_u32(); break;
4447
                            default: return 1;
4448
                            }
4449
                        } else {
4450
                            switch (size) {
4451
                            case 0: gen_op_neon_narrow_sat_s8(); break;
4452
                            case 1: gen_op_neon_narrow_sat_s16(); break;
4453
                            case 2: gen_op_neon_narrow_sat_s32(); break;
4454
                            default: return 1;
4455
                            }
4456
                        }
4457
                        NEON_SET_REG(T0, rd, n);
4458
                    }
4459
                    break;
4460
                case 38: /* VSHLL */
4461
                    if (q)
4462
                        return 1;
4463
                    if (rm == rd) {
4464
                        NEON_GET_REG(T2, rm, 1);
4465
                    }
4466
                    for (pass = 0; pass < 2; pass++) {
4467
                        if (pass == 1 && rm == rd) {
4468
                            gen_op_movl_T0_T2();
4469
                        } else {
4470
                            NEON_GET_REG(T0, rm, pass);
4471
                        }
4472
                        switch (size) {
4473
                        case 0: gen_op_neon_widen_high_u8(); break;
4474
                        case 1: gen_op_neon_widen_high_u16(); break;
4475
                        case 2:
4476
                            gen_op_movl_T1_T0();
4477
                            gen_op_movl_T0_im(0);
4478
                            break;
4479
                        default: return 1;
4480
                        }
4481
                        NEON_SET_REG(T0, rd, pass * 2);
4482
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4483
                    }
4484
                    break;
4485
                default:
4486
                elementwise:
4487
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
4488
                        if (op == 30 || op == 31 || op >= 58) {
4489
                            gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4490
                        } else {
4491
                            NEON_GET_REG(T0, rm, pass);
4492
                        }
4493
                        switch (op) {
4494
                        case 1: /* VREV32 */
4495
                            switch (size) {
4496
                            case 0: gen_op_rev_T0(); break;
4497
                            case 1: gen_op_revh_T0(); break;
4498
                            default: return 1;
4499
                            }
4500
                            break;
4501
                        case 2: /* VREV16 */
4502
                            if (size != 0)
4503
                                return 1;
4504
                            gen_op_rev16_T0();
4505
                            break;
4506
                        case 4: case 5: /* VPADDL */
4507
                        case 12: case 13: /* VPADAL */
4508
                            switch ((size << 1) | (op & 1)) {
4509
                            case 0: gen_op_neon_paddl_s8(); break;
4510
                            case 1: gen_op_neon_paddl_u8(); break;
4511
                            case 2: gen_op_neon_paddl_s16(); break;
4512
                            case 3: gen_op_neon_paddl_u16(); break;
4513
                            default: abort();
4514
                            }
4515
                            if (op >= 12) {
4516
                                /* Accumulate */
4517
                                NEON_GET_REG(T1, rd, pass);
4518
                                switch (size) {
4519
                                case 0: gen_op_neon_add_u16(); break;
4520
                                case 1: gen_op_addl_T0_T1(); break;
4521
                                default: abort();
4522
                                }
4523
                            }
4524
                            break;
4525
                        case 8: /* CLS */
4526
                            switch (size) {
4527
                            case 0: gen_op_neon_cls_s8(); break;
4528
                            case 1: gen_op_neon_cls_s16(); break;
4529
                            case 2: gen_op_neon_cls_s32(); break;
4530
                            default: return 1;
4531
                            }
4532
                            break;
4533
                        case 9: /* CLZ */
4534
                            switch (size) {
4535
                            case 0: gen_op_neon_clz_u8(); break;
4536
                            case 1: gen_op_neon_clz_u16(); break;
4537
                            case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
4538
                            default: return 1;
4539
                            }
4540
                            break;
4541
                        case 10: /* CNT */
4542
                            if (size != 0)
4543
                                return 1;
4544
                            gen_op_neon_cnt_u8();
4545
                            break;
4546
                        case 11: /* VNOT */
4547
                            if (size != 0)
4548
                                return 1;
4549
                            gen_op_notl_T0();
4550
                            break;
4551
                        case 14: /* VQABS */
4552
                            switch (size) {
4553
                            case 0: gen_op_neon_qabs_s8(); break;
4554
                            case 1: gen_op_neon_qabs_s16(); break;
4555
                            case 2: gen_op_neon_qabs_s32(); break;
4556
                            default: return 1;
4557
                            }
4558
                            break;
4559
                        case 15: /* VQNEG */
4560
                            switch (size) {
4561
                            case 0: gen_op_neon_qneg_s8(); break;
4562
                            case 1: gen_op_neon_qneg_s16(); break;
4563
                            case 2: gen_op_neon_qneg_s32(); break;
4564
                            default: return 1;
4565
                            }
4566
                            break;
4567
                        case 16: case 19: /* VCGT #0, VCLE #0 */
4568
                            gen_op_movl_T1_im(0);
4569
                            switch(size) {
4570
                            case 0: gen_op_neon_cgt_s8(); break;
4571
                            case 1: gen_op_neon_cgt_s16(); break;
4572
                            case 2: gen_op_neon_cgt_s32(); break;
4573
                            default: return 1;
4574
                            }
4575
                            if (op == 19)
4576
                                gen_op_notl_T0();
4577
                            break;
4578
                        case 17: case 20: /* VCGE #0, VCLT #0 */
4579
                            gen_op_movl_T1_im(0);
4580
                            switch(size) {
4581
                            case 0: gen_op_neon_cge_s8(); break;
4582
                            case 1: gen_op_neon_cge_s16(); break;
4583
                            case 2: gen_op_neon_cge_s32(); break;
4584
                            default: return 1;
4585
                            }
4586
                            if (op == 20)
4587
                                gen_op_notl_T0();
4588
                            break;
4589
                        case 18: /* VCEQ #0 */
4590
                            gen_op_movl_T1_im(0);
4591
                            switch(size) {
4592
                            case 0: gen_op_neon_ceq_u8(); break;
4593
                            case 1: gen_op_neon_ceq_u16(); break;
4594
                            case 2: gen_op_neon_ceq_u32(); break;
4595
                            default: return 1;
4596
                            }
4597
                            break;
4598
                        case 22: /* VABS */
4599
                            switch(size) {
4600
                            case 0: gen_op_neon_abs_s8(); break;
4601
                            case 1: gen_op_neon_abs_s16(); break;
4602
                            case 2: gen_op_neon_abs_s32(); break;
4603
                            default: return 1;
4604
                            }
4605
                            break;
4606
                        case 23: /* VNEG */
4607
                            gen_op_movl_T1_im(0);
4608
                            switch(size) {
4609
                            case 0: gen_op_neon_rsb_u8(); break;
4610
                            case 1: gen_op_neon_rsb_u16(); break;
4611
                            case 2: gen_op_rsbl_T0_T1(); break;
4612
                            default: return 1;
4613
                            }
4614
                            break;
4615
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4616
                            gen_op_movl_T1_im(0);
4617
                            gen_op_neon_cgt_f32();
4618
                            if (op == 27)
4619
                                gen_op_notl_T0();
4620
                            break;
4621
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4622
                            gen_op_movl_T1_im(0);
4623
                            gen_op_neon_cge_f32();
4624
                            if (op == 28)
4625
                                gen_op_notl_T0();
4626
                            break;
4627
                        case 26: /* Float VCEQ #0 */
4628
                            gen_op_movl_T1_im(0);
4629
                            gen_op_neon_ceq_f32();
4630
                            break;
4631
                        case 30: /* Float VABS */
4632
                            gen_op_vfp_abss();
4633
                            break;
4634
                        case 31: /* Float VNEG */
4635
                            gen_op_vfp_negs();
4636
                            break;
4637
                        case 32: /* VSWP */
4638
                            NEON_GET_REG(T1, rd, pass);
4639
                            NEON_SET_REG(T1, rm, pass);
4640
                            break;
4641
                        case 33: /* VTRN */
4642
                            NEON_GET_REG(T1, rd, pass);
4643
                            switch (size) {
4644
                            case 0: gen_op_neon_trn_u8(); break;
4645
                            case 1: gen_op_neon_trn_u16(); break;
4646
                            case 2: abort();
4647
                            default: return 1;
4648<