Statistics
| Branch: | Revision:

root / target-arm / translate.c @ d9ba4830

History | View | Annotate | Download (272.3 kB)

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

    
28
#include "cpu.h"
29
#include "exec-all.h"
30
#include "disas.h"
31
#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
static inline TCGv load_cpu_offset(int offset)
134
{
135
    TCGv tmp = new_tmp();
136
    tcg_gen_ld_i32(tmp, cpu_env, offset);
137
    return tmp;
138
}
139

    
140
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
141

    
142
static inline void store_cpu_offset(TCGv var, int offset)
143
{
144
    tcg_gen_st_i32(var, cpu_env, offset);
145
    dead_tmp(var);
146
}
147

    
148
#define store_cpu_field(var, name) \
149
    store_cpu_offset(var, offsetof(CPUState, name))
150

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

    
167
/* Create a new temporary and set it to the value of a CPU register.  */
168
static inline TCGv load_reg(DisasContext *s, int reg)
169
{
170
    TCGv tmp = new_tmp();
171
    load_reg_var(s, tmp, reg);
172
    return tmp;
173
}
174

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

    
187

    
188
/* Basic operations.  */
189
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
190
#define gen_op_movl_T0_T2() tcg_gen_mov_i32(cpu_T[0], cpu_T[2])
191
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], cpu_T[0])
192
#define gen_op_movl_T1_T2() tcg_gen_mov_i32(cpu_T[1], cpu_T[2])
193
#define gen_op_movl_T2_T0() tcg_gen_mov_i32(cpu_T[2], cpu_T[0])
194
#define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
195
#define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
196
#define gen_op_movl_T2_im(im) tcg_gen_movi_i32(cpu_T[2], im)
197

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

    
203
#define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
204
#define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
205
#define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
206
#define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
207
#define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
208
#define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
209
#define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
210

    
211
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
212
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
213
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
214
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
215
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
216

    
217
/* Value extensions.  */
218
#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
219
#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
220
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
221
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
222

    
223
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
224
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
225
#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0])
226

    
227
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
228

    
229
#define gen_op_addl_T0_T1_setq() \
230
    gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
231
#define gen_op_addl_T0_T1_saturate() \
232
    gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
233
#define gen_op_subl_T0_T1_saturate() \
234
    gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
235
#define gen_op_addl_T0_T1_usaturate() \
236
    gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
237
#define gen_op_subl_T0_T1_usaturate() \
238
    gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
239

    
240
/* Copy the most significant bit of T0 to all bits of T1.  */
241
#define gen_op_signbit_T1_T0() tcg_gen_sari_i32(cpu_T[1], cpu_T[0], 31)
242

    
243
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
244
/* Set NZCV flags from the high 4 bits of var.  */
245
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
246

    
247
static void gen_exception(int excp)
248
{
249
    TCGv tmp = new_tmp();
250
    tcg_gen_movi_i32(tmp, excp);
251
    gen_helper_exception(tmp);
252
    dead_tmp(tmp);
253
}
254

    
255
static void gen_smul_dual(TCGv a, TCGv b)
256
{
257
    TCGv tmp1 = new_tmp();
258
    TCGv tmp2 = new_tmp();
259
    tcg_gen_ext8s_i32(tmp1, a);
260
    tcg_gen_ext8s_i32(tmp2, b);
261
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
262
    dead_tmp(tmp2);
263
    tcg_gen_sari_i32(a, a, 16);
264
    tcg_gen_sari_i32(b, b, 16);
265
    tcg_gen_mul_i32(b, b, a);
266
    tcg_gen_mov_i32(a, tmp1);
267
    dead_tmp(tmp1);
268
}
269

    
270
/* Byteswap each halfword.  */
271
static void gen_rev16(TCGv var)
272
{
273
    TCGv tmp = new_tmp();
274
    tcg_gen_shri_i32(tmp, var, 8);
275
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
276
    tcg_gen_shli_i32(var, var, 8);
277
    tcg_gen_andi_i32(var, var, 0xff00ff00);
278
    tcg_gen_or_i32(var, var, tmp);
279
    dead_tmp(tmp);
280
}
281

    
282
/* Byteswap low halfword and sign extend.  */
283
static void gen_revsh(TCGv var)
284
{
285
    TCGv tmp = new_tmp();
286
    tcg_gen_shri_i32(tmp, var, 8);
287
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
288
    tcg_gen_shli_i32(var, var, 8);
289
    tcg_gen_ext8s_i32(var, var);
290
    tcg_gen_or_i32(var, var, tmp);
291
    dead_tmp(tmp);
292
}
293

    
294
/* Unsigned bitfield extract.  */
295
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
296
{
297
    if (shift)
298
        tcg_gen_shri_i32(var, var, shift);
299
    tcg_gen_andi_i32(var, var, mask);
300
}
301

    
302
/* Signed bitfield extract.  */
303
static void gen_sbfx(TCGv var, int shift, int width)
304
{
305
    uint32_t signbit;
306

    
307
    if (shift)
308
        tcg_gen_sari_i32(var, var, shift);
309
    if (shift + width < 32) {
310
        signbit = 1u << (width - 1);
311
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
312
        tcg_gen_xori_i32(var, var, signbit);
313
        tcg_gen_subi_i32(var, var, signbit);
314
    }
315
}
316

    
317
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
318
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
319
{
320
    tcg_gen_shli_i32(val, val, shift);
321
    tcg_gen_andi_i32(val, val, mask);
322
    tcg_gen_andi_i32(base, base, ~mask);
323
    tcg_gen_or_i32(dest, base, val);
324
}
325

    
326
/* Round the top 32 bits of a 64-bit value.  */
327
static void gen_roundqd(TCGv a, TCGv b)
328
{
329
    tcg_gen_shri_i32(a, a, 31);
330
    tcg_gen_add_i32(a, a, b);
331
}
332

    
333
/* FIXME: Most targets have native widening multiplication.
334
   It would be good to use that instead of a full wide multiply.  */
335
/* Unsigned 32x32->64 multiply.  */
336
static void gen_op_mull_T0_T1(void)
337
{
338
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
339
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
340

    
341
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
342
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
343
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
344
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
345
    tcg_gen_shri_i64(tmp1, tmp1, 32);
346
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
347
}
348

    
349
/* Signed 32x32->64 multiply.  */
350
static void gen_imull(TCGv a, TCGv b)
351
{
352
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
353
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
354

    
355
    tcg_gen_ext_i32_i64(tmp1, a);
356
    tcg_gen_ext_i32_i64(tmp2, b);
357
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
358
    tcg_gen_trunc_i64_i32(a, tmp1);
359
    tcg_gen_shri_i64(tmp1, tmp1, 32);
360
    tcg_gen_trunc_i64_i32(b, tmp1);
361
}
362
#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
363

    
364
/* Signed 32x16 multiply, top 32 bits.  */
365
static void gen_imulw(TCGv a, TCGv b)
366
{
367
  gen_imull(a, b);
368
  tcg_gen_shri_i32(a, a, 16);
369
  tcg_gen_shli_i32(b, b, 16);
370
  tcg_gen_or_i32(a, a, b);
371
}
372

    
373
/* Swap low and high halfwords.  */
374
static void gen_swap_half(TCGv var)
375
{
376
    TCGv tmp = new_tmp();
377
    tcg_gen_shri_i32(tmp, var, 16);
378
    tcg_gen_shli_i32(var, var, 16);
379
    tcg_gen_or_i32(var, var, tmp);
380
    dead_tmp(tmp);
381
}
382

    
383
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
384
    tmp = (t0 ^ t1) & 0x8000;
385
    t0 &= ~0x8000;
386
    t1 &= ~0x8000;
387
    t0 = (t0 + t1) ^ tmp;
388
 */
389

    
390
static void gen_add16(TCGv t0, TCGv t1)
391
{
392
    TCGv tmp = new_tmp();
393
    tcg_gen_xor_i32(tmp, t0, t1);
394
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
395
    tcg_gen_andi_i32(t0, t0, ~0x8000);
396
    tcg_gen_andi_i32(t1, t1, ~0x8000);
397
    tcg_gen_add_i32(t0, t0, t1);
398
    tcg_gen_xor_i32(t0, t0, tmp);
399
    dead_tmp(tmp);
400
    dead_tmp(t1);
401
}
402

    
403
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
404

    
405
/* Set CF to the top bit of var.  */
406
static void gen_set_CF_bit31(TCGv var)
407
{
408
    TCGv tmp = new_tmp();
409
    tcg_gen_shri_i32(tmp, var, 31);
410
    gen_set_CF(var);
411
    dead_tmp(tmp);
412
}
413

    
414
/* Set N and Z flags from var.  */
415
static inline void gen_logic_CC(TCGv var)
416
{
417
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
418
}
419

    
420
/* T0 += T1 + CF.  */
421
static void gen_adc_T0_T1(void)
422
{
423
    TCGv tmp;
424
    gen_op_addl_T0_T1();
425
    tmp = load_cpu_field(CF);
426
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
427
    dead_tmp(tmp);
428
}
429

    
430
/* dest = T0 - T1 + CF - 1.  */
431
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
432
{
433
    TCGv tmp;
434
    tcg_gen_sub_i32(dest, t0, t1);
435
    tmp = load_cpu_field(CF);
436
    tcg_gen_add_i32(dest, dest, tmp);
437
    tcg_gen_subi_i32(dest, dest, 1);
438
    dead_tmp(tmp);
439
}
440

    
441
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
442
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
443

    
444
/* FIXME:  Implement this natively.  */
445
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
446
{
447
    tcg_gen_xori_i32(t0, t1, ~0);
448
}
449

    
450
/* T0 &= ~T1.  Clobbers T1.  */
451
/* FIXME: Implement bic natively.  */
452
static inline void gen_op_bicl_T0_T1(void)
453
{
454
    gen_op_notl_T1();
455
    gen_op_andl_T0_T1();
456
}
457

    
458
/* FIXME:  Implement this natively.  */
459
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
460
{
461
    TCGv tmp;
462

    
463
    if (i == 0)
464
        return;
465

    
466
    tmp = new_tmp();
467
    tcg_gen_shri_i32(tmp, t1, i);
468
    tcg_gen_shli_i32(t1, t1, 32 - i);
469
    tcg_gen_or_i32(t0, t1, tmp);
470
    dead_tmp(tmp);
471
}
472

    
473
static void shifter_out_im(TCGv var, int shift)
474
{
475
    TCGv tmp = new_tmp();
476
    if (shift == 0) {
477
        tcg_gen_andi_i32(tmp, var, 1);
478
    } else {
479
        tcg_gen_shri_i32(tmp, var, shift);
480
        if (shift != 31);
481
            tcg_gen_andi_i32(tmp, tmp, 1);
482
    }
483
    gen_set_CF(tmp);
484
    dead_tmp(tmp);
485
}
486

    
487
/* Shift by immediate.  Includes special handling for shift == 0.  */
488
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
489
{
490
    switch (shiftop) {
491
    case 0: /* LSL */
492
        if (shift != 0) {
493
            if (flags)
494
                shifter_out_im(var, 32 - shift);
495
            tcg_gen_shli_i32(var, var, shift);
496
        }
497
        break;
498
    case 1: /* LSR */
499
        if (shift == 0) {
500
            if (flags) {
501
                tcg_gen_shri_i32(var, var, 31);
502
                gen_set_CF(var);
503
            }
504
            tcg_gen_movi_i32(var, 0);
505
        } else {
506
            if (flags)
507
                shifter_out_im(var, shift - 1);
508
            tcg_gen_shri_i32(var, var, shift);
509
        }
510
        break;
511
    case 2: /* ASR */
512
        if (shift == 0)
513
            shift = 32;
514
        if (flags)
515
            shifter_out_im(var, shift - 1);
516
        if (shift == 32)
517
          shift = 31;
518
        tcg_gen_sari_i32(var, var, shift);
519
        break;
520
    case 3: /* ROR/RRX */
521
        if (shift != 0) {
522
            if (flags)
523
                shifter_out_im(var, shift - 1);
524
            tcg_gen_rori_i32(var, var, shift); break;
525
        } else {
526
            TCGv tmp = load_cpu_field(CF);
527
            if (flags)
528
                shifter_out_im(var, 0);
529
            tcg_gen_shri_i32(var, var, 1);
530
            tcg_gen_shli_i32(tmp, tmp, 31);
531
            tcg_gen_or_i32(var, var, tmp);
532
            dead_tmp(tmp);
533
        }
534
    }
535
};
536

    
537
#define PAS_OP(pfx) \
538
    switch (op2) {  \
539
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
540
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
541
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
542
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
543
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
544
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
545
    }
546
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
547
{
548
    TCGv tmp;
549

    
550
    switch (op1) {
551
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
552
    case 1:
553
        tmp = tcg_temp_new(TCG_TYPE_PTR);
554
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
555
        PAS_OP(s)
556
        break;
557
    case 5:
558
        tmp = tcg_temp_new(TCG_TYPE_PTR);
559
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
560
        PAS_OP(u)
561
        break;
562
#undef gen_pas_helper
563
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
564
    case 2:
565
        PAS_OP(q);
566
        break;
567
    case 3:
568
        PAS_OP(sh);
569
        break;
570
    case 6:
571
        PAS_OP(uq);
572
        break;
573
    case 7:
574
        PAS_OP(uh);
575
        break;
576
#undef gen_pas_helper
577
    }
578
}
579
#undef PAS_OP
580

    
581
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
582
#define PAS_OP(pfx) \
583
    switch (op2) {  \
584
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
585
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
586
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
587
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
588
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
589
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
590
    }
591
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
592
{
593
    TCGv tmp;
594

    
595
    switch (op1) {
596
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
597
    case 0:
598
        tmp = tcg_temp_new(TCG_TYPE_PTR);
599
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
600
        PAS_OP(s)
601
        break;
602
    case 4:
603
        tmp = tcg_temp_new(TCG_TYPE_PTR);
604
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
605
        PAS_OP(u)
606
        break;
607
#undef gen_pas_helper
608
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
609
    case 1:
610
        PAS_OP(q);
611
        break;
612
    case 2:
613
        PAS_OP(sh);
614
        break;
615
    case 5:
616
        PAS_OP(uq);
617
        break;
618
    case 6:
619
        PAS_OP(uh);
620
        break;
621
#undef gen_pas_helper
622
    }
623
}
624
#undef PAS_OP
625

    
626
static void gen_test_cc(int cc, int label)
627
{
628
    TCGv tmp;
629
    TCGv tmp2;
630
    TCGv zero;
631
    int inv;
632

    
633
    zero = tcg_const_i32(0);
634
    switch (cc) {
635
    case 0: /* eq: Z */
636
        tmp = load_cpu_field(NZF);
637
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
638
        break;
639
    case 1: /* ne: !Z */
640
        tmp = load_cpu_field(NZF);
641
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
642
        break;
643
    case 2: /* cs: C */
644
        tmp = load_cpu_field(CF);
645
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
646
        break;
647
    case 3: /* cc: !C */
648
        tmp = load_cpu_field(CF);
649
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
650
        break;
651
    case 4: /* mi: N */
652
        tmp = load_cpu_field(NZF);
653
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
654
        break;
655
    case 5: /* pl: !N */
656
        tmp = load_cpu_field(NZF);
657
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
658
        break;
659
    case 6: /* vs: V */
660
        tmp = load_cpu_field(VF);
661
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
662
        break;
663
    case 7: /* vc: !V */
664
        tmp = load_cpu_field(VF);
665
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
666
        break;
667
    case 8: /* hi: C && !Z */
668
        inv = gen_new_label();
669
        tmp = load_cpu_field(CF);
670
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
671
        dead_tmp(tmp);
672
        tmp = load_cpu_field(NZF);
673
        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);
674
        gen_set_label(inv);
675
        break;
676
    case 9: /* ls: !C || Z */
677
        tmp = load_cpu_field(CF);
678
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
679
        dead_tmp(tmp);
680
        tmp = load_cpu_field(NZF);
681
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
682
        break;
683
    case 10: /* ge: N == V -> N ^ V == 0 */
684
        tmp = load_cpu_field(VF);
685
        tmp2 = load_cpu_field(NZF);
686
        tcg_gen_xor_i32(tmp, tmp, tmp2);
687
        dead_tmp(tmp2);
688
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
689
        break;
690
    case 11: /* lt: N != V -> N ^ V != 0 */
691
        tmp = load_cpu_field(VF);
692
        tmp2 = load_cpu_field(NZF);
693
        tcg_gen_xor_i32(tmp, tmp, tmp2);
694
        dead_tmp(tmp2);
695
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
696
        break;
697
    case 12: /* gt: !Z && N == V */
698
        inv = gen_new_label();
699
        tmp = load_cpu_field(NZF);
700
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);
701
        dead_tmp(tmp);
702
        tmp = load_cpu_field(VF);
703
        tmp2 = load_cpu_field(NZF);
704
        tcg_gen_xor_i32(tmp, tmp, tmp2);
705
        dead_tmp(tmp2);
706
        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);
707
        gen_set_label(inv);
708
        break;
709
    case 13: /* le: Z || N != V */
710
        tmp = load_cpu_field(NZF);
711
        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);
712
        dead_tmp(tmp);
713
        tmp = load_cpu_field(VF);
714
        tmp2 = load_cpu_field(NZF);
715
        tcg_gen_xor_i32(tmp, tmp, tmp2);
716
        dead_tmp(tmp2);
717
        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);
718
        break;
719
    default:
720
        fprintf(stderr, "Bad condition code 0x%x\n", cc);
721
        abort();
722
    }
723
    dead_tmp(tmp);
724
}
725

    
726
const uint8_t table_logic_cc[16] = {
727
    1, /* and */
728
    1, /* xor */
729
    0, /* sub */
730
    0, /* rsb */
731
    0, /* add */
732
    0, /* adc */
733
    0, /* sbc */
734
    0, /* rsc */
735
    1, /* andl */
736
    1, /* xorl */
737
    0, /* cmp */
738
    0, /* cmn */
739
    1, /* orr */
740
    1, /* mov */
741
    1, /* bic */
742
    1, /* mvn */
743
};
744

    
745
static GenOpFunc *gen_shift_T1_T0[4] = {
746
    gen_op_shll_T1_T0,
747
    gen_op_shrl_T1_T0,
748
    gen_op_sarl_T1_T0,
749
    gen_op_rorl_T1_T0,
750
};
751

    
752
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
753
    gen_op_shll_T1_T0_cc,
754
    gen_op_shrl_T1_T0_cc,
755
    gen_op_sarl_T1_T0_cc,
756
    gen_op_rorl_T1_T0_cc,
757
};
758

    
759
/* Set PC and Thumb state from an immediate address.  */
760
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
761
{
762
    TCGv tmp;
763

    
764
    s->is_jmp = DISAS_UPDATE;
765
    tmp = new_tmp();
766
    if (s->thumb != (addr & 1)) {
767
        tcg_gen_movi_i32(tmp, addr & 1);
768
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
769
    }
770
    tcg_gen_movi_i32(tmp, addr & ~1);
771
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
772
    dead_tmp(tmp);
773
}
774

    
775
/* Set PC and Thumb state from var.  var is marked as dead.  */
776
static inline void gen_bx(DisasContext *s, TCGv var)
777
{
778
    TCGv tmp;
779

    
780
    s->is_jmp = DISAS_UPDATE;
781
    tmp = new_tmp();
782
    tcg_gen_andi_i32(tmp, var, 1);
783
    store_cpu_field(tmp, thumb);
784
    tcg_gen_andi_i32(var, var, ~1);
785
    store_cpu_field(var, regs[15]);
786
}
787

    
788
/* TODO: This should be removed.  Use gen_bx instead.  */
789
static inline void gen_bx_T0(DisasContext *s)
790
{
791
    TCGv tmp = new_tmp();
792
    tcg_gen_mov_i32(tmp, cpu_T[0]);
793
    gen_bx(s, tmp);
794
}
795

    
796
#if defined(CONFIG_USER_ONLY)
797
#define gen_ldst(name, s) gen_op_##name##_raw()
798
#else
799
#define gen_ldst(name, s) do { \
800
    s->is_mem = 1; \
801
    if (IS_USER(s)) \
802
        gen_op_##name##_user(); \
803
    else \
804
        gen_op_##name##_kernel(); \
805
    } while (0)
806
#endif
807

    
808
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
809
{
810
    load_reg_var(s, cpu_T[0], reg);
811
}
812

    
813
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
814
{
815
    load_reg_var(s, cpu_T[1], reg);
816
}
817

    
818
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
819
{
820
    load_reg_var(s, cpu_T[2], reg);
821
}
822

    
823
static inline void gen_set_pc_T0(void)
824
{
825
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
826
}
827

    
828
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
829
{
830
    TCGv tmp;
831
    if (reg == 15) {
832
        tmp = new_tmp();
833
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
834
    } else {
835
        tmp = cpu_T[t];
836
    }
837
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
838
    if (reg == 15) {
839
        dead_tmp(tmp);
840
        s->is_jmp = DISAS_JUMP;
841
    }
842
}
843

    
844
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
845
{
846
    gen_movl_reg_TN(s, reg, 0);
847
}
848

    
849
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
850
{
851
    gen_movl_reg_TN(s, reg, 1);
852
}
853

    
854
/* Force a TB lookup after an instruction that changes the CPU state.  */
855
static inline void gen_lookup_tb(DisasContext *s)
856
{
857
    gen_op_movl_T0_im(s->pc);
858
    gen_movl_reg_T0(s, 15);
859
    s->is_jmp = DISAS_UPDATE;
860
}
861

    
862
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
863
{
864
    int val, rm, shift, shiftop;
865
    TCGv offset;
866

    
867
    if (!(insn & (1 << 25))) {
868
        /* immediate */
869
        val = insn & 0xfff;
870
        if (!(insn & (1 << 23)))
871
            val = -val;
872
        if (val != 0)
873
            gen_op_addl_T1_im(val);
874
    } else {
875
        /* shift/register */
876
        rm = (insn) & 0xf;
877
        shift = (insn >> 7) & 0x1f;
878
        shiftop = (insn >> 5) & 3;
879
        offset = load_reg(s, rm);
880
        gen_arm_shift_im(offset, shiftop, shift, 0);
881
        if (!(insn & (1 << 23)))
882
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
883
        else
884
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
885
        dead_tmp(offset);
886
    }
887
}
888

    
889
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
890
                                        int extra)
891
{
892
    int val, rm;
893
    TCGv offset;
894

    
895
    if (insn & (1 << 22)) {
896
        /* immediate */
897
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
898
        if (!(insn & (1 << 23)))
899
            val = -val;
900
        val += extra;
901
        if (val != 0)
902
            gen_op_addl_T1_im(val);
903
    } else {
904
        /* register */
905
        if (extra)
906
            gen_op_addl_T1_im(extra);
907
        rm = (insn) & 0xf;
908
        offset = load_reg(s, rm);
909
        if (!(insn & (1 << 23)))
910
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
911
        else
912
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
913
        dead_tmp(offset);
914
    }
915
}
916

    
917
#define VFP_OP(name)                      \
918
static inline void gen_vfp_##name(int dp) \
919
{                                         \
920
    if (dp)                               \
921
        gen_op_vfp_##name##d();           \
922
    else                                  \
923
        gen_op_vfp_##name##s();           \
924
}
925

    
926
#define VFP_OP1(name)                               \
927
static inline void gen_vfp_##name(int dp, int arg)  \
928
{                                                   \
929
    if (dp)                                         \
930
        gen_op_vfp_##name##d(arg);                  \
931
    else                                            \
932
        gen_op_vfp_##name##s(arg);                  \
933
}
934

    
935
VFP_OP(add)
936
VFP_OP(sub)
937
VFP_OP(mul)
938
VFP_OP(div)
939
VFP_OP(neg)
940
VFP_OP(abs)
941
VFP_OP(sqrt)
942
VFP_OP(cmp)
943
VFP_OP(cmpe)
944
VFP_OP(F1_ld0)
945
VFP_OP(uito)
946
VFP_OP(sito)
947
VFP_OP(toui)
948
VFP_OP(touiz)
949
VFP_OP(tosi)
950
VFP_OP(tosiz)
951
VFP_OP1(tosh)
952
VFP_OP1(tosl)
953
VFP_OP1(touh)
954
VFP_OP1(toul)
955
VFP_OP1(shto)
956
VFP_OP1(slto)
957
VFP_OP1(uhto)
958
VFP_OP1(ulto)
959

    
960
#undef VFP_OP
961

    
962
static inline void gen_vfp_fconst(int dp, uint32_t val)
963
{
964
    if (dp)
965
        gen_op_vfp_fconstd(val);
966
    else
967
        gen_op_vfp_fconsts(val);
968
}
969

    
970
static inline void gen_vfp_ld(DisasContext *s, int dp)
971
{
972
    if (dp)
973
        gen_ldst(vfp_ldd, s);
974
    else
975
        gen_ldst(vfp_lds, s);
976
}
977

    
978
static inline void gen_vfp_st(DisasContext *s, int dp)
979
{
980
    if (dp)
981
        gen_ldst(vfp_std, s);
982
    else
983
        gen_ldst(vfp_sts, s);
984
}
985

    
986
static inline long
987
vfp_reg_offset (int dp, int reg)
988
{
989
    if (dp)
990
        return offsetof(CPUARMState, vfp.regs[reg]);
991
    else if (reg & 1) {
992
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
993
          + offsetof(CPU_DoubleU, l.upper);
994
    } else {
995
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
996
          + offsetof(CPU_DoubleU, l.lower);
997
    }
998
}
999

    
1000
/* Return the offset of a 32-bit piece of a NEON register.
1001
   zero is the least significant end of the register.  */
1002
static inline long
1003
neon_reg_offset (int reg, int n)
1004
{
1005
    int sreg;
1006
    sreg = reg * 2 + n;
1007
    return vfp_reg_offset(0, sreg);
1008
}
1009

    
1010
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
1011
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
1012

    
1013
static inline void gen_mov_F0_vreg(int dp, int reg)
1014
{
1015
    if (dp)
1016
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
1017
    else
1018
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
1019
}
1020

    
1021
static inline void gen_mov_F1_vreg(int dp, int reg)
1022
{
1023
    if (dp)
1024
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
1025
    else
1026
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
1027
}
1028

    
1029
static inline void gen_mov_vreg_F0(int dp, int reg)
1030
{
1031
    if (dp)
1032
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
1033
    else
1034
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
1035
}
1036

    
1037
#define ARM_CP_RW_BIT        (1 << 20)
1038

    
1039
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1040
{
1041
    int rd;
1042
    uint32_t offset;
1043

    
1044
    rd = (insn >> 16) & 0xf;
1045
    gen_movl_T1_reg(s, rd);
1046

    
1047
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1048
    if (insn & (1 << 24)) {
1049
        /* Pre indexed */
1050
        if (insn & (1 << 23))
1051
            gen_op_addl_T1_im(offset);
1052
        else
1053
            gen_op_addl_T1_im(-offset);
1054

    
1055
        if (insn & (1 << 21))
1056
            gen_movl_reg_T1(s, rd);
1057
    } else if (insn & (1 << 21)) {
1058
        /* Post indexed */
1059
        if (insn & (1 << 23))
1060
            gen_op_movl_T0_im(offset);
1061
        else
1062
            gen_op_movl_T0_im(- offset);
1063
        gen_op_addl_T0_T1();
1064
        gen_movl_reg_T0(s, rd);
1065
    } else if (!(insn & (1 << 23)))
1066
        return 1;
1067
    return 0;
1068
}
1069

    
1070
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1071
{
1072
    int rd = (insn >> 0) & 0xf;
1073

    
1074
    if (insn & (1 << 8))
1075
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1076
            return 1;
1077
        else
1078
            gen_op_iwmmxt_movl_T0_wCx(rd);
1079
    else
1080
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
1081

    
1082
    gen_op_movl_T1_im(mask);
1083
    gen_op_andl_T0_T1();
1084
    return 0;
1085
}
1086

    
1087
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1088
   (ie. an undefined instruction).  */
1089
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1090
{
1091
    int rd, wrd;
1092
    int rdhi, rdlo, rd0, rd1, i;
1093

    
1094
    if ((insn & 0x0e000e00) == 0x0c000000) {
1095
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1096
            wrd = insn & 0xf;
1097
            rdlo = (insn >> 12) & 0xf;
1098
            rdhi = (insn >> 16) & 0xf;
1099
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1100
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
1101
                gen_movl_reg_T0(s, rdlo);
1102
                gen_movl_reg_T1(s, rdhi);
1103
            } else {                                        /* TMCRR */
1104
                gen_movl_T0_reg(s, rdlo);
1105
                gen_movl_T1_reg(s, rdhi);
1106
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
1107
                gen_op_iwmmxt_set_mup();
1108
            }
1109
            return 0;
1110
        }
1111

    
1112
        wrd = (insn >> 12) & 0xf;
1113
        if (gen_iwmmxt_address(s, insn))
1114
            return 1;
1115
        if (insn & ARM_CP_RW_BIT) {
1116
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1117
                gen_ldst(ldl, s);
1118
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1119
            } else {
1120
                if (insn & (1 << 8))
1121
                    if (insn & (1 << 22))                /* WLDRD */
1122
                        gen_ldst(iwmmxt_ldq, s);
1123
                    else                                /* WLDRW wRd */
1124
                        gen_ldst(iwmmxt_ldl, s);
1125
                else
1126
                    if (insn & (1 << 22))                /* WLDRH */
1127
                        gen_ldst(iwmmxt_ldw, s);
1128
                    else                                /* WLDRB */
1129
                        gen_ldst(iwmmxt_ldb, s);
1130
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1131
            }
1132
        } else {
1133
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1134
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1135
                gen_ldst(stl, s);
1136
            } else {
1137
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1138
                if (insn & (1 << 8))
1139
                    if (insn & (1 << 22))                /* WSTRD */
1140
                        gen_ldst(iwmmxt_stq, s);
1141
                    else                                /* WSTRW wRd */
1142
                        gen_ldst(iwmmxt_stl, s);
1143
                else
1144
                    if (insn & (1 << 22))                /* WSTRH */
1145
                        gen_ldst(iwmmxt_ldw, s);
1146
                    else                                /* WSTRB */
1147
                        gen_ldst(iwmmxt_stb, s);
1148
            }
1149
        }
1150
        return 0;
1151
    }
1152

    
1153
    if ((insn & 0x0f000000) != 0x0e000000)
1154
        return 1;
1155

    
1156
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1157
    case 0x000:                                                /* WOR */
1158
        wrd = (insn >> 12) & 0xf;
1159
        rd0 = (insn >> 0) & 0xf;
1160
        rd1 = (insn >> 16) & 0xf;
1161
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1162
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1163
        gen_op_iwmmxt_setpsr_nz();
1164
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1165
        gen_op_iwmmxt_set_mup();
1166
        gen_op_iwmmxt_set_cup();
1167
        break;
1168
    case 0x011:                                                /* TMCR */
1169
        if (insn & 0xf)
1170
            return 1;
1171
        rd = (insn >> 12) & 0xf;
1172
        wrd = (insn >> 16) & 0xf;
1173
        switch (wrd) {
1174
        case ARM_IWMMXT_wCID:
1175
        case ARM_IWMMXT_wCASF:
1176
            break;
1177
        case ARM_IWMMXT_wCon:
1178
            gen_op_iwmmxt_set_cup();
1179
            /* Fall through.  */
1180
        case ARM_IWMMXT_wCSSF:
1181
            gen_op_iwmmxt_movl_T0_wCx(wrd);
1182
            gen_movl_T1_reg(s, rd);
1183
            gen_op_bicl_T0_T1();
1184
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1185
            break;
1186
        case ARM_IWMMXT_wCGR0:
1187
        case ARM_IWMMXT_wCGR1:
1188
        case ARM_IWMMXT_wCGR2:
1189
        case ARM_IWMMXT_wCGR3:
1190
            gen_op_iwmmxt_set_cup();
1191
            gen_movl_reg_T0(s, rd);
1192
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1193
            break;
1194
        default:
1195
            return 1;
1196
        }
1197
        break;
1198
    case 0x100:                                                /* WXOR */
1199
        wrd = (insn >> 12) & 0xf;
1200
        rd0 = (insn >> 0) & 0xf;
1201
        rd1 = (insn >> 16) & 0xf;
1202
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1203
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1204
        gen_op_iwmmxt_setpsr_nz();
1205
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1206
        gen_op_iwmmxt_set_mup();
1207
        gen_op_iwmmxt_set_cup();
1208
        break;
1209
    case 0x111:                                                /* TMRC */
1210
        if (insn & 0xf)
1211
            return 1;
1212
        rd = (insn >> 12) & 0xf;
1213
        wrd = (insn >> 16) & 0xf;
1214
        gen_op_iwmmxt_movl_T0_wCx(wrd);
1215
        gen_movl_reg_T0(s, rd);
1216
        break;
1217
    case 0x300:                                                /* WANDN */
1218
        wrd = (insn >> 12) & 0xf;
1219
        rd0 = (insn >> 0) & 0xf;
1220
        rd1 = (insn >> 16) & 0xf;
1221
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1222
        gen_op_iwmmxt_negq_M0();
1223
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1224
        gen_op_iwmmxt_setpsr_nz();
1225
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1226
        gen_op_iwmmxt_set_mup();
1227
        gen_op_iwmmxt_set_cup();
1228
        break;
1229
    case 0x200:                                                /* WAND */
1230
        wrd = (insn >> 12) & 0xf;
1231
        rd0 = (insn >> 0) & 0xf;
1232
        rd1 = (insn >> 16) & 0xf;
1233
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1234
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1235
        gen_op_iwmmxt_setpsr_nz();
1236
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1237
        gen_op_iwmmxt_set_mup();
1238
        gen_op_iwmmxt_set_cup();
1239
        break;
1240
    case 0x810: case 0xa10:                                /* WMADD */
1241
        wrd = (insn >> 12) & 0xf;
1242
        rd0 = (insn >> 0) & 0xf;
1243
        rd1 = (insn >> 16) & 0xf;
1244
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1245
        if (insn & (1 << 21))
1246
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1247
        else
1248
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1249
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1250
        gen_op_iwmmxt_set_mup();
1251
        break;
1252
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1253
        wrd = (insn >> 12) & 0xf;
1254
        rd0 = (insn >> 16) & 0xf;
1255
        rd1 = (insn >> 0) & 0xf;
1256
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1257
        switch ((insn >> 22) & 3) {
1258
        case 0:
1259
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1260
            break;
1261
        case 1:
1262
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1263
            break;
1264
        case 2:
1265
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1266
            break;
1267
        case 3:
1268
            return 1;
1269
        }
1270
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1271
        gen_op_iwmmxt_set_mup();
1272
        gen_op_iwmmxt_set_cup();
1273
        break;
1274
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1275
        wrd = (insn >> 12) & 0xf;
1276
        rd0 = (insn >> 16) & 0xf;
1277
        rd1 = (insn >> 0) & 0xf;
1278
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1279
        switch ((insn >> 22) & 3) {
1280
        case 0:
1281
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1282
            break;
1283
        case 1:
1284
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1285
            break;
1286
        case 2:
1287
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1288
            break;
1289
        case 3:
1290
            return 1;
1291
        }
1292
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1293
        gen_op_iwmmxt_set_mup();
1294
        gen_op_iwmmxt_set_cup();
1295
        break;
1296
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1297
        wrd = (insn >> 12) & 0xf;
1298
        rd0 = (insn >> 16) & 0xf;
1299
        rd1 = (insn >> 0) & 0xf;
1300
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1301
        if (insn & (1 << 22))
1302
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1303
        else
1304
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1305
        if (!(insn & (1 << 20)))
1306
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1307
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1308
        gen_op_iwmmxt_set_mup();
1309
        break;
1310
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1311
        wrd = (insn >> 12) & 0xf;
1312
        rd0 = (insn >> 16) & 0xf;
1313
        rd1 = (insn >> 0) & 0xf;
1314
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1315
        if (insn & (1 << 21))
1316
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1317
        else
1318
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1319
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1320
        gen_op_iwmmxt_set_mup();
1321
        break;
1322
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1323
        wrd = (insn >> 12) & 0xf;
1324
        rd0 = (insn >> 16) & 0xf;
1325
        rd1 = (insn >> 0) & 0xf;
1326
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1327
        if (insn & (1 << 21))
1328
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1329
        else
1330
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1331
        if (!(insn & (1 << 20))) {
1332
            if (insn & (1 << 21))
1333
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
1334
            else
1335
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
1336
        }
1337
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1338
        gen_op_iwmmxt_set_mup();
1339
        break;
1340
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1341
        wrd = (insn >> 12) & 0xf;
1342
        rd0 = (insn >> 16) & 0xf;
1343
        rd1 = (insn >> 0) & 0xf;
1344
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1345
        switch ((insn >> 22) & 3) {
1346
        case 0:
1347
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1348
            break;
1349
        case 1:
1350
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1351
            break;
1352
        case 2:
1353
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1354
            break;
1355
        case 3:
1356
            return 1;
1357
        }
1358
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1359
        gen_op_iwmmxt_set_mup();
1360
        gen_op_iwmmxt_set_cup();
1361
        break;
1362
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1363
        wrd = (insn >> 12) & 0xf;
1364
        rd0 = (insn >> 16) & 0xf;
1365
        rd1 = (insn >> 0) & 0xf;
1366
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1367
        if (insn & (1 << 22))
1368
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
1369
        else
1370
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
1371
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1372
        gen_op_iwmmxt_set_mup();
1373
        gen_op_iwmmxt_set_cup();
1374
        break;
1375
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1376
        wrd = (insn >> 12) & 0xf;
1377
        rd0 = (insn >> 16) & 0xf;
1378
        rd1 = (insn >> 0) & 0xf;
1379
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1380
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1381
        gen_op_movl_T1_im(7);
1382
        gen_op_andl_T0_T1();
1383
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1384
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1385
        gen_op_iwmmxt_set_mup();
1386
        break;
1387
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1388
        rd = (insn >> 12) & 0xf;
1389
        wrd = (insn >> 16) & 0xf;
1390
        gen_movl_T0_reg(s, rd);
1391
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1392
        switch ((insn >> 6) & 3) {
1393
        case 0:
1394
            gen_op_movl_T1_im(0xff);
1395
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1396
            break;
1397
        case 1:
1398
            gen_op_movl_T1_im(0xffff);
1399
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1400
            break;
1401
        case 2:
1402
            gen_op_movl_T1_im(0xffffffff);
1403
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1404
            break;
1405
        case 3:
1406
            return 1;
1407
        }
1408
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1409
        gen_op_iwmmxt_set_mup();
1410
        break;
1411
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1412
        rd = (insn >> 12) & 0xf;
1413
        wrd = (insn >> 16) & 0xf;
1414
        if (rd == 15)
1415
            return 1;
1416
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1417
        switch ((insn >> 22) & 3) {
1418
        case 0:
1419
            if (insn & 8)
1420
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1421
            else {
1422
                gen_op_movl_T1_im(0xff);
1423
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
1424
            }
1425
            break;
1426
        case 1:
1427
            if (insn & 8)
1428
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1429
            else {
1430
                gen_op_movl_T1_im(0xffff);
1431
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
1432
            }
1433
            break;
1434
        case 2:
1435
            gen_op_movl_T1_im(0xffffffff);
1436
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
1437
            break;
1438
        case 3:
1439
            return 1;
1440
        }
1441
        gen_movl_reg_T0(s, rd);
1442
        break;
1443
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1444
        if ((insn & 0x000ff008) != 0x0003f000)
1445
            return 1;
1446
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1447
        switch ((insn >> 22) & 3) {
1448
        case 0:
1449
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1450
            break;
1451
        case 1:
1452
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1453
            break;
1454
        case 2:
1455
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1456
            break;
1457
        case 3:
1458
            return 1;
1459
        }
1460
        gen_op_shll_T1_im(28);
1461
        gen_set_nzcv(cpu_T[1]);
1462
        break;
1463
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1464
        rd = (insn >> 12) & 0xf;
1465
        wrd = (insn >> 16) & 0xf;
1466
        gen_movl_T0_reg(s, rd);
1467
        switch ((insn >> 6) & 3) {
1468
        case 0:
1469
            gen_op_iwmmxt_bcstb_M0_T0();
1470
            break;
1471
        case 1:
1472
            gen_op_iwmmxt_bcstw_M0_T0();
1473
            break;
1474
        case 2:
1475
            gen_op_iwmmxt_bcstl_M0_T0();
1476
            break;
1477
        case 3:
1478
            return 1;
1479
        }
1480
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1481
        gen_op_iwmmxt_set_mup();
1482
        break;
1483
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1484
        if ((insn & 0x000ff00f) != 0x0003f000)
1485
            return 1;
1486
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1487
        switch ((insn >> 22) & 3) {
1488
        case 0:
1489
            for (i = 0; i < 7; i ++) {
1490
                gen_op_shll_T1_im(4);
1491
                gen_op_andl_T0_T1();
1492
            }
1493
            break;
1494
        case 1:
1495
            for (i = 0; i < 3; i ++) {
1496
                gen_op_shll_T1_im(8);
1497
                gen_op_andl_T0_T1();
1498
            }
1499
            break;
1500
        case 2:
1501
            gen_op_shll_T1_im(16);
1502
            gen_op_andl_T0_T1();
1503
            break;
1504
        case 3:
1505
            return 1;
1506
        }
1507
        gen_set_nzcv(cpu_T[0]);
1508
        break;
1509
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1510
        wrd = (insn >> 12) & 0xf;
1511
        rd0 = (insn >> 16) & 0xf;
1512
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1513
        switch ((insn >> 22) & 3) {
1514
        case 0:
1515
            gen_op_iwmmxt_addcb_M0();
1516
            break;
1517
        case 1:
1518
            gen_op_iwmmxt_addcw_M0();
1519
            break;
1520
        case 2:
1521
            gen_op_iwmmxt_addcl_M0();
1522
            break;
1523
        case 3:
1524
            return 1;
1525
        }
1526
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1527
        gen_op_iwmmxt_set_mup();
1528
        break;
1529
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1530
        if ((insn & 0x000ff00f) != 0x0003f000)
1531
            return 1;
1532
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1533
        switch ((insn >> 22) & 3) {
1534
        case 0:
1535
            for (i = 0; i < 7; i ++) {
1536
                gen_op_shll_T1_im(4);
1537
                gen_op_orl_T0_T1();
1538
            }
1539
            break;
1540
        case 1:
1541
            for (i = 0; i < 3; i ++) {
1542
                gen_op_shll_T1_im(8);
1543
                gen_op_orl_T0_T1();
1544
            }
1545
            break;
1546
        case 2:
1547
            gen_op_shll_T1_im(16);
1548
            gen_op_orl_T0_T1();
1549
            break;
1550
        case 3:
1551
            return 1;
1552
        }
1553
        gen_set_nzcv(cpu_T[0]);
1554
        break;
1555
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1556
        rd = (insn >> 12) & 0xf;
1557
        rd0 = (insn >> 16) & 0xf;
1558
        if ((insn & 0xf) != 0)
1559
            return 1;
1560
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1561
        switch ((insn >> 22) & 3) {
1562
        case 0:
1563
            gen_op_iwmmxt_msbb_T0_M0();
1564
            break;
1565
        case 1:
1566
            gen_op_iwmmxt_msbw_T0_M0();
1567
            break;
1568
        case 2:
1569
            gen_op_iwmmxt_msbl_T0_M0();
1570
            break;
1571
        case 3:
1572
            return 1;
1573
        }
1574
        gen_movl_reg_T0(s, rd);
1575
        break;
1576
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1577
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1578
        wrd = (insn >> 12) & 0xf;
1579
        rd0 = (insn >> 16) & 0xf;
1580
        rd1 = (insn >> 0) & 0xf;
1581
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1582
        switch ((insn >> 22) & 3) {
1583
        case 0:
1584
            if (insn & (1 << 21))
1585
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1586
            else
1587
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1588
            break;
1589
        case 1:
1590
            if (insn & (1 << 21))
1591
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1592
            else
1593
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1594
            break;
1595
        case 2:
1596
            if (insn & (1 << 21))
1597
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1598
            else
1599
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1600
            break;
1601
        case 3:
1602
            return 1;
1603
        }
1604
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1605
        gen_op_iwmmxt_set_mup();
1606
        gen_op_iwmmxt_set_cup();
1607
        break;
1608
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1609
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1610
        wrd = (insn >> 12) & 0xf;
1611
        rd0 = (insn >> 16) & 0xf;
1612
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1613
        switch ((insn >> 22) & 3) {
1614
        case 0:
1615
            if (insn & (1 << 21))
1616
                gen_op_iwmmxt_unpacklsb_M0();
1617
            else
1618
                gen_op_iwmmxt_unpacklub_M0();
1619
            break;
1620
        case 1:
1621
            if (insn & (1 << 21))
1622
                gen_op_iwmmxt_unpacklsw_M0();
1623
            else
1624
                gen_op_iwmmxt_unpackluw_M0();
1625
            break;
1626
        case 2:
1627
            if (insn & (1 << 21))
1628
                gen_op_iwmmxt_unpacklsl_M0();
1629
            else
1630
                gen_op_iwmmxt_unpacklul_M0();
1631
            break;
1632
        case 3:
1633
            return 1;
1634
        }
1635
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1636
        gen_op_iwmmxt_set_mup();
1637
        gen_op_iwmmxt_set_cup();
1638
        break;
1639
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1640
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1641
        wrd = (insn >> 12) & 0xf;
1642
        rd0 = (insn >> 16) & 0xf;
1643
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1644
        switch ((insn >> 22) & 3) {
1645
        case 0:
1646
            if (insn & (1 << 21))
1647
                gen_op_iwmmxt_unpackhsb_M0();
1648
            else
1649
                gen_op_iwmmxt_unpackhub_M0();
1650
            break;
1651
        case 1:
1652
            if (insn & (1 << 21))
1653
                gen_op_iwmmxt_unpackhsw_M0();
1654
            else
1655
                gen_op_iwmmxt_unpackhuw_M0();
1656
            break;
1657
        case 2:
1658
            if (insn & (1 << 21))
1659
                gen_op_iwmmxt_unpackhsl_M0();
1660
            else
1661
                gen_op_iwmmxt_unpackhul_M0();
1662
            break;
1663
        case 3:
1664
            return 1;
1665
        }
1666
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1667
        gen_op_iwmmxt_set_mup();
1668
        gen_op_iwmmxt_set_cup();
1669
        break;
1670
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1671
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1672
        wrd = (insn >> 12) & 0xf;
1673
        rd0 = (insn >> 16) & 0xf;
1674
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1675
        if (gen_iwmmxt_shift(insn, 0xff))
1676
            return 1;
1677
        switch ((insn >> 22) & 3) {
1678
        case 0:
1679
            return 1;
1680
        case 1:
1681
            gen_op_iwmmxt_srlw_M0_T0();
1682
            break;
1683
        case 2:
1684
            gen_op_iwmmxt_srll_M0_T0();
1685
            break;
1686
        case 3:
1687
            gen_op_iwmmxt_srlq_M0_T0();
1688
            break;
1689
        }
1690
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1691
        gen_op_iwmmxt_set_mup();
1692
        gen_op_iwmmxt_set_cup();
1693
        break;
1694
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1695
    case 0x014: case 0x414: case 0x814: case 0xc14:
1696
        wrd = (insn >> 12) & 0xf;
1697
        rd0 = (insn >> 16) & 0xf;
1698
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1699
        if (gen_iwmmxt_shift(insn, 0xff))
1700
            return 1;
1701
        switch ((insn >> 22) & 3) {
1702
        case 0:
1703
            return 1;
1704
        case 1:
1705
            gen_op_iwmmxt_sraw_M0_T0();
1706
            break;
1707
        case 2:
1708
            gen_op_iwmmxt_sral_M0_T0();
1709
            break;
1710
        case 3:
1711
            gen_op_iwmmxt_sraq_M0_T0();
1712
            break;
1713
        }
1714
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1715
        gen_op_iwmmxt_set_mup();
1716
        gen_op_iwmmxt_set_cup();
1717
        break;
1718
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1719
    case 0x114: case 0x514: case 0x914: case 0xd14:
1720
        wrd = (insn >> 12) & 0xf;
1721
        rd0 = (insn >> 16) & 0xf;
1722
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1723
        if (gen_iwmmxt_shift(insn, 0xff))
1724
            return 1;
1725
        switch ((insn >> 22) & 3) {
1726
        case 0:
1727
            return 1;
1728
        case 1:
1729
            gen_op_iwmmxt_sllw_M0_T0();
1730
            break;
1731
        case 2:
1732
            gen_op_iwmmxt_slll_M0_T0();
1733
            break;
1734
        case 3:
1735
            gen_op_iwmmxt_sllq_M0_T0();
1736
            break;
1737
        }
1738
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1739
        gen_op_iwmmxt_set_mup();
1740
        gen_op_iwmmxt_set_cup();
1741
        break;
1742
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1743
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1744
        wrd = (insn >> 12) & 0xf;
1745
        rd0 = (insn >> 16) & 0xf;
1746
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1747
        switch ((insn >> 22) & 3) {
1748
        case 0:
1749
            return 1;
1750
        case 1:
1751
            if (gen_iwmmxt_shift(insn, 0xf))
1752
                return 1;
1753
            gen_op_iwmmxt_rorw_M0_T0();
1754
            break;
1755
        case 2:
1756
            if (gen_iwmmxt_shift(insn, 0x1f))
1757
                return 1;
1758
            gen_op_iwmmxt_rorl_M0_T0();
1759
            break;
1760
        case 3:
1761
            if (gen_iwmmxt_shift(insn, 0x3f))
1762
                return 1;
1763
            gen_op_iwmmxt_rorq_M0_T0();
1764
            break;
1765
        }
1766
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1767
        gen_op_iwmmxt_set_mup();
1768
        gen_op_iwmmxt_set_cup();
1769
        break;
1770
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1771
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1772
        wrd = (insn >> 12) & 0xf;
1773
        rd0 = (insn >> 16) & 0xf;
1774
        rd1 = (insn >> 0) & 0xf;
1775
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1776
        switch ((insn >> 22) & 3) {
1777
        case 0:
1778
            if (insn & (1 << 21))
1779
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1780
            else
1781
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1782
            break;
1783
        case 1:
1784
            if (insn & (1 << 21))
1785
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1786
            else
1787
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1788
            break;
1789
        case 2:
1790
            if (insn & (1 << 21))
1791
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1792
            else
1793
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1794
            break;
1795
        case 3:
1796
            return 1;
1797
        }
1798
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1799
        gen_op_iwmmxt_set_mup();
1800
        break;
1801
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1802
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1803
        wrd = (insn >> 12) & 0xf;
1804
        rd0 = (insn >> 16) & 0xf;
1805
        rd1 = (insn >> 0) & 0xf;
1806
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1807
        switch ((insn >> 22) & 3) {
1808
        case 0:
1809
            if (insn & (1 << 21))
1810
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1811
            else
1812
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1813
            break;
1814
        case 1:
1815
            if (insn & (1 << 21))
1816
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1817
            else
1818
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1819
            break;
1820
        case 2:
1821
            if (insn & (1 << 21))
1822
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1823
            else
1824
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1825
            break;
1826
        case 3:
1827
            return 1;
1828
        }
1829
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1830
        gen_op_iwmmxt_set_mup();
1831
        break;
1832
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1833
    case 0x402: case 0x502: case 0x602: case 0x702:
1834
        wrd = (insn >> 12) & 0xf;
1835
        rd0 = (insn >> 16) & 0xf;
1836
        rd1 = (insn >> 0) & 0xf;
1837
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1838
        gen_op_movl_T0_im((insn >> 20) & 3);
1839
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1840
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1841
        gen_op_iwmmxt_set_mup();
1842
        break;
1843
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1844
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1845
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1846
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
1847
        wrd = (insn >> 12) & 0xf;
1848
        rd0 = (insn >> 16) & 0xf;
1849
        rd1 = (insn >> 0) & 0xf;
1850
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1851
        switch ((insn >> 20) & 0xf) {
1852
        case 0x0:
1853
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
1854
            break;
1855
        case 0x1:
1856
            gen_op_iwmmxt_subub_M0_wRn(rd1);
1857
            break;
1858
        case 0x3:
1859
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
1860
            break;
1861
        case 0x4:
1862
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
1863
            break;
1864
        case 0x5:
1865
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
1866
            break;
1867
        case 0x7:
1868
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
1869
            break;
1870
        case 0x8:
1871
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
1872
            break;
1873
        case 0x9:
1874
            gen_op_iwmmxt_subul_M0_wRn(rd1);
1875
            break;
1876
        case 0xb:
1877
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
1878
            break;
1879
        default:
1880
            return 1;
1881
        }
1882
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1883
        gen_op_iwmmxt_set_mup();
1884
        gen_op_iwmmxt_set_cup();
1885
        break;
1886
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
1887
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
1888
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
1889
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
1890
        wrd = (insn >> 12) & 0xf;
1891
        rd0 = (insn >> 16) & 0xf;
1892
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1893
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
1894
        gen_op_iwmmxt_shufh_M0_T0();
1895
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1896
        gen_op_iwmmxt_set_mup();
1897
        gen_op_iwmmxt_set_cup();
1898
        break;
1899
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
1900
    case 0x418: case 0x518: case 0x618: case 0x718:
1901
    case 0x818: case 0x918: case 0xa18: case 0xb18:
1902
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
1903
        wrd = (insn >> 12) & 0xf;
1904
        rd0 = (insn >> 16) & 0xf;
1905
        rd1 = (insn >> 0) & 0xf;
1906
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1907
        switch ((insn >> 20) & 0xf) {
1908
        case 0x0:
1909
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
1910
            break;
1911
        case 0x1:
1912
            gen_op_iwmmxt_addub_M0_wRn(rd1);
1913
            break;
1914
        case 0x3:
1915
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
1916
            break;
1917
        case 0x4:
1918
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
1919
            break;
1920
        case 0x5:
1921
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
1922
            break;
1923
        case 0x7:
1924
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
1925
            break;
1926
        case 0x8:
1927
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
1928
            break;
1929
        case 0x9:
1930
            gen_op_iwmmxt_addul_M0_wRn(rd1);
1931
            break;
1932
        case 0xb:
1933
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
1934
            break;
1935
        default:
1936
            return 1;
1937
        }
1938
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1939
        gen_op_iwmmxt_set_mup();
1940
        gen_op_iwmmxt_set_cup();
1941
        break;
1942
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
1943
    case 0x408: case 0x508: case 0x608: case 0x708:
1944
    case 0x808: case 0x908: case 0xa08: case 0xb08:
1945
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
1946
        wrd = (insn >> 12) & 0xf;
1947
        rd0 = (insn >> 16) & 0xf;
1948
        rd1 = (insn >> 0) & 0xf;
1949
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1950
        if (!(insn & (1 << 20)))
1951
            return 1;
1952
        switch ((insn >> 22) & 3) {
1953
        case 0:
1954
            return 1;
1955
        case 1:
1956
            if (insn & (1 << 21))
1957
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
1958
            else
1959
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
1960
            break;
1961
        case 2:
1962
            if (insn & (1 << 21))
1963
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
1964
            else
1965
                gen_op_iwmmxt_packul_M0_wRn(rd1);
1966
            break;
1967
        case 3:
1968
            if (insn & (1 << 21))
1969
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
1970
            else
1971
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
1972
            break;
1973
        }
1974
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1975
        gen_op_iwmmxt_set_mup();
1976
        gen_op_iwmmxt_set_cup();
1977
        break;
1978
    case 0x201: case 0x203: case 0x205: case 0x207:
1979
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
1980
    case 0x211: case 0x213: case 0x215: case 0x217:
1981
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
1982
        wrd = (insn >> 5) & 0xf;
1983
        rd0 = (insn >> 12) & 0xf;
1984
        rd1 = (insn >> 0) & 0xf;
1985
        if (rd0 == 0xf || rd1 == 0xf)
1986
            return 1;
1987
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1988
        switch ((insn >> 16) & 0xf) {
1989
        case 0x0:                                        /* TMIA */
1990
            gen_movl_T0_reg(s, rd0);
1991
            gen_movl_T1_reg(s, rd1);
1992
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1993
            break;
1994
        case 0x8:                                        /* TMIAPH */
1995
            gen_movl_T0_reg(s, rd0);
1996
            gen_movl_T1_reg(s, rd1);
1997
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1998
            break;
1999
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2000
            gen_movl_T1_reg(s, rd0);
2001
            if (insn & (1 << 16))
2002
                gen_op_shrl_T1_im(16);
2003
            gen_op_movl_T0_T1();
2004
            gen_movl_T1_reg(s, rd1);
2005
            if (insn & (1 << 17))
2006
                gen_op_shrl_T1_im(16);
2007
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2008
            break;
2009
        default:
2010
            return 1;
2011
        }
2012
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2013
        gen_op_iwmmxt_set_mup();
2014
        break;
2015
    default:
2016
        return 1;
2017
    }
2018

    
2019
    return 0;
2020
}
2021

    
2022
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2023
   (ie. an undefined instruction).  */
2024
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2025
{
2026
    int acc, rd0, rd1, rdhi, rdlo;
2027

    
2028
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2029
        /* Multiply with Internal Accumulate Format */
2030
        rd0 = (insn >> 12) & 0xf;
2031
        rd1 = insn & 0xf;
2032
        acc = (insn >> 5) & 7;
2033

    
2034
        if (acc != 0)
2035
            return 1;
2036

    
2037
        switch ((insn >> 16) & 0xf) {
2038
        case 0x0:                                        /* MIA */
2039
            gen_movl_T0_reg(s, rd0);
2040
            gen_movl_T1_reg(s, rd1);
2041
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2042
            break;
2043
        case 0x8:                                        /* MIAPH */
2044
            gen_movl_T0_reg(s, rd0);
2045
            gen_movl_T1_reg(s, rd1);
2046
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2047
            break;
2048
        case 0xc:                                        /* MIABB */
2049
        case 0xd:                                        /* MIABT */
2050
        case 0xe:                                        /* MIATB */
2051
        case 0xf:                                        /* MIATT */
2052
            gen_movl_T1_reg(s, rd0);
2053
            if (insn & (1 << 16))
2054
                gen_op_shrl_T1_im(16);
2055
            gen_op_movl_T0_T1();
2056
            gen_movl_T1_reg(s, rd1);
2057
            if (insn & (1 << 17))
2058
                gen_op_shrl_T1_im(16);
2059
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2060
            break;
2061
        default:
2062
            return 1;
2063
        }
2064

    
2065
        gen_op_iwmmxt_movq_wRn_M0(acc);
2066
        return 0;
2067
    }
2068

    
2069
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2070
        /* Internal Accumulator Access Format */
2071
        rdhi = (insn >> 16) & 0xf;
2072
        rdlo = (insn >> 12) & 0xf;
2073
        acc = insn & 7;
2074

    
2075
        if (acc != 0)
2076
            return 1;
2077

    
2078
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2079
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
2080
            gen_movl_reg_T0(s, rdlo);
2081
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2082
            gen_op_andl_T0_T1();
2083
            gen_movl_reg_T0(s, rdhi);
2084
        } else {                                        /* MAR */
2085
            gen_movl_T0_reg(s, rdlo);
2086
            gen_movl_T1_reg(s, rdhi);
2087
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
2088
        }
2089
        return 0;
2090
    }
2091

    
2092
    return 1;
2093
}
2094

    
2095
/* Disassemble system coprocessor instruction.  Return nonzero if
2096
   instruction is not defined.  */
2097
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2098
{
2099
    uint32_t rd = (insn >> 12) & 0xf;
2100
    uint32_t cp = (insn >> 8) & 0xf;
2101
    if (IS_USER(s)) {
2102
        return 1;
2103
    }
2104

    
2105
    if (insn & ARM_CP_RW_BIT) {
2106
        if (!env->cp[cp].cp_read)
2107
            return 1;
2108
        gen_op_movl_T0_im((uint32_t) s->pc);
2109
        gen_set_pc_T0();
2110
        gen_op_movl_T0_cp(insn);
2111
        gen_movl_reg_T0(s, rd);
2112
    } else {
2113
        if (!env->cp[cp].cp_write)
2114
            return 1;
2115
        gen_op_movl_T0_im((uint32_t) s->pc);
2116
        gen_set_pc_T0();
2117
        gen_movl_T0_reg(s, rd);
2118
        gen_op_movl_cp_T0(insn);
2119
    }
2120
    return 0;
2121
}
2122

    
2123
static int cp15_user_ok(uint32_t insn)
2124
{
2125
    int cpn = (insn >> 16) & 0xf;
2126
    int cpm = insn & 0xf;
2127
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2128

    
2129
    if (cpn == 13 && cpm == 0) {
2130
        /* TLS register.  */
2131
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2132
            return 1;
2133
    }
2134
    if (cpn == 7) {
2135
        /* ISB, DSB, DMB.  */
2136
        if ((cpm == 5 && op == 4)
2137
                || (cpm == 10 && (op == 4 || op == 5)))
2138
            return 1;
2139
    }
2140
    return 0;
2141
}
2142

    
2143
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2144
   instruction is not defined.  */
2145
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2146
{
2147
    uint32_t rd;
2148

    
2149
    /* M profile cores use memory mapped registers instead of cp15.  */
2150
    if (arm_feature(env, ARM_FEATURE_M))
2151
        return 1;
2152

    
2153
    if ((insn & (1 << 25)) == 0) {
2154
        if (insn & (1 << 20)) {
2155
            /* mrrc */
2156
            return 1;
2157
        }
2158
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2159
        return 0;
2160
    }
2161
    if ((insn & (1 << 4)) == 0) {
2162
        /* cdp */
2163
        return 1;
2164
    }
2165
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2166
        return 1;
2167
    }
2168
    if ((insn & 0x0fff0fff) == 0x0e070f90
2169
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2170
        /* Wait for interrupt.  */
2171
        gen_op_movl_T0_im((long)s->pc);
2172
        gen_set_pc_T0();
2173
        s->is_jmp = DISAS_WFI;
2174
        return 0;
2175
    }
2176
    rd = (insn >> 12) & 0xf;
2177
    if (insn & ARM_CP_RW_BIT) {
2178
        gen_op_movl_T0_cp15(insn);
2179
        /* If the destination register is r15 then sets condition codes.  */
2180
        if (rd != 15)
2181
            gen_movl_reg_T0(s, rd);
2182
    } else {
2183
        gen_movl_T0_reg(s, rd);
2184
        gen_op_movl_cp15_T0(insn);
2185
        /* Normally we would always end the TB here, but Linux
2186
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2187
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2188
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2189
                (insn & 0x0fff0fff) != 0x0e010f10)
2190
            gen_lookup_tb(s);
2191
    }
2192
    return 0;
2193
}
2194

    
2195
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2196
#define VFP_SREG(insn, bigbit, smallbit) \
2197
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2198
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2199
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2200
        reg = (((insn) >> (bigbit)) & 0x0f) \
2201
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2202
    } else { \
2203
        if (insn & (1 << (smallbit))) \
2204
            return 1; \
2205
        reg = ((insn) >> (bigbit)) & 0x0f; \
2206
    }} while (0)
2207

    
2208
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2209
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2210
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2211
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2212
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2213
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2214

    
2215
static inline int
2216
vfp_enabled(CPUState * env)
2217
{
2218
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2219
}
2220

    
2221
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2222
   (ie. an undefined instruction).  */
2223
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2224
{
2225
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2226
    int dp, veclen;
2227

    
2228
    if (!arm_feature(env, ARM_FEATURE_VFP))
2229
        return 1;
2230

    
2231
    if (!vfp_enabled(env)) {
2232
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2233
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2234
            return 1;
2235
        rn = (insn >> 16) & 0xf;
2236
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2237
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2238
            return 1;
2239
    }
2240
    dp = ((insn & 0xf00) == 0xb00);
2241
    switch ((insn >> 24) & 0xf) {
2242
    case 0xe:
2243
        if (insn & (1 << 4)) {
2244
            /* single register transfer */
2245
            rd = (insn >> 12) & 0xf;
2246
            if (dp) {
2247
                int size;
2248
                int pass;
2249

    
2250
                VFP_DREG_N(rn, insn);
2251
                if (insn & 0xf)
2252
                    return 1;
2253
                if (insn & 0x00c00060
2254
                    && !arm_feature(env, ARM_FEATURE_NEON))
2255
                    return 1;
2256

    
2257
                pass = (insn >> 21) & 1;
2258
                if (insn & (1 << 22)) {
2259
                    size = 0;
2260
                    offset = ((insn >> 5) & 3) * 8;
2261
                } else if (insn & (1 << 5)) {
2262
                    size = 1;
2263
                    offset = (insn & (1 << 6)) ? 16 : 0;
2264
                } else {
2265
                    size = 2;
2266
                    offset = 0;
2267
                }
2268
                if (insn & ARM_CP_RW_BIT) {
2269
                    /* vfp->arm */
2270
                    switch (size) {
2271
                    case 0:
2272
                        NEON_GET_REG(T1, rn, pass);
2273
                        if (offset)
2274
                            gen_op_shrl_T1_im(offset);
2275
                        if (insn & (1 << 23))
2276
                            gen_uxtb(cpu_T[1]);
2277
                        else
2278
                            gen_sxtb(cpu_T[1]);
2279
                        break;
2280
                    case 1:
2281
                        NEON_GET_REG(T1, rn, pass);
2282
                        if (insn & (1 << 23)) {
2283
                            if (offset) {
2284
                                gen_op_shrl_T1_im(16);
2285
                            } else {
2286
                                gen_uxth(cpu_T[1]);
2287
                            }
2288
                        } else {
2289
                            if (offset) {
2290
                                gen_op_sarl_T1_im(16);
2291
                            } else {
2292
                                gen_sxth(cpu_T[1]);
2293
                            }
2294
                        }
2295
                        break;
2296
                    case 2:
2297
                        NEON_GET_REG(T1, rn, pass);
2298
                        break;
2299
                    }
2300
                    gen_movl_reg_T1(s, rd);
2301
                } else {
2302
                    /* arm->vfp */
2303
                    gen_movl_T0_reg(s, rd);
2304
                    if (insn & (1 << 23)) {
2305
                        /* VDUP */
2306
                        if (size == 0) {
2307
                            gen_op_neon_dup_u8(0);
2308
                        } else if (size == 1) {
2309
                            gen_op_neon_dup_low16();
2310
                        }
2311
                        NEON_SET_REG(T0, rn, 0);
2312
                        NEON_SET_REG(T0, rn, 1);
2313
                    } else {
2314
                        /* VMOV */
2315
                        switch (size) {
2316
                        case 0:
2317
                            NEON_GET_REG(T2, rn, pass);
2318
                            gen_op_movl_T1_im(0xff);
2319
                            gen_op_andl_T0_T1();
2320
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
2321
                            NEON_SET_REG(T2, rn, pass);
2322
                            break;
2323
                        case 1:
2324
                            NEON_GET_REG(T2, rn, pass);
2325
                            gen_op_movl_T1_im(0xffff);
2326
                            gen_op_andl_T0_T1();
2327
                            bank_mask = offset ? 0xffff : 0xffff0000;
2328
                            gen_op_neon_insert_elt(offset, bank_mask);
2329
                            NEON_SET_REG(T2, rn, pass);
2330
                            break;
2331
                        case 2:
2332
                            NEON_SET_REG(T0, rn, pass);
2333
                            break;
2334
                        }
2335
                    }
2336
                }
2337
            } else { /* !dp */
2338
                if ((insn & 0x6f) != 0x00)
2339
                    return 1;
2340
                rn = VFP_SREG_N(insn);
2341
                if (insn & ARM_CP_RW_BIT) {
2342
                    /* vfp->arm */
2343
                    if (insn & (1 << 21)) {
2344
                        /* system register */
2345
                        rn >>= 1;
2346

    
2347
                        switch (rn) {
2348
                        case ARM_VFP_FPSID:
2349
                            /* VFP2 allows access for FSID from userspace.
2350
                               VFP3 restricts all id registers to privileged
2351
                               accesses.  */
2352
                            if (IS_USER(s)
2353
                                && arm_feature(env, ARM_FEATURE_VFP3))
2354
                                return 1;
2355
                            gen_op_vfp_movl_T0_xreg(rn);
2356
                            break;
2357
                        case ARM_VFP_FPEXC:
2358
                            if (IS_USER(s))
2359
                                return 1;
2360
                            gen_op_vfp_movl_T0_xreg(rn);
2361
                            break;
2362
                        case ARM_VFP_FPINST:
2363
                        case ARM_VFP_FPINST2:
2364
                            /* Not present in VFP3.  */
2365
                            if (IS_USER(s)
2366
                                || arm_feature(env, ARM_FEATURE_VFP3))
2367
                                return 1;
2368
                            gen_op_vfp_movl_T0_xreg(rn);
2369
                            break;
2370
                        case ARM_VFP_FPSCR:
2371
                            if (rd == 15)
2372
                                gen_op_vfp_movl_T0_fpscr_flags();
2373
                            else
2374
                                gen_op_vfp_movl_T0_fpscr();
2375
                            break;
2376
                        case ARM_VFP_MVFR0:
2377
                        case ARM_VFP_MVFR1:
2378
                            if (IS_USER(s)
2379
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2380
                                return 1;
2381
                            gen_op_vfp_movl_T0_xreg(rn);
2382
                            break;
2383
                        default:
2384
                            return 1;
2385
                        }
2386
                    } else {
2387
                        gen_mov_F0_vreg(0, rn);
2388
                        gen_op_vfp_mrs();
2389
                    }
2390
                    if (rd == 15) {
2391
                        /* Set the 4 flag bits in the CPSR.  */
2392
                        gen_set_nzcv(cpu_T[0]);
2393
                    } else
2394
                        gen_movl_reg_T0(s, rd);
2395
                } else {
2396
                    /* arm->vfp */
2397
                    gen_movl_T0_reg(s, rd);
2398
                    if (insn & (1 << 21)) {
2399
                        rn >>= 1;
2400
                        /* system register */
2401
                        switch (rn) {
2402
                        case ARM_VFP_FPSID:
2403
                        case ARM_VFP_MVFR0:
2404
                        case ARM_VFP_MVFR1:
2405
                            /* Writes are ignored.  */
2406
                            break;
2407
                        case ARM_VFP_FPSCR:
2408
                            gen_op_vfp_movl_fpscr_T0();
2409
                            gen_lookup_tb(s);
2410
                            break;
2411
                        case ARM_VFP_FPEXC:
2412
                            if (IS_USER(s))
2413
                                return 1;
2414
                            gen_op_vfp_movl_xreg_T0(rn);
2415
                            gen_lookup_tb(s);
2416
                            break;
2417
                        case ARM_VFP_FPINST:
2418
                        case ARM_VFP_FPINST2:
2419
                            gen_op_vfp_movl_xreg_T0(rn);
2420
                            break;
2421
                        default:
2422
                            return 1;
2423
                        }
2424
                    } else {
2425
                        gen_op_vfp_msr();
2426
                        gen_mov_vreg_F0(0, rn);
2427
                    }
2428
                }
2429
            }
2430
        } else {
2431
            /* data processing */
2432
            /* The opcode is in bits 23, 21, 20 and 6.  */
2433
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2434
            if (dp) {
2435
                if (op == 15) {
2436
                    /* rn is opcode */
2437
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2438
                } else {
2439
                    /* rn is register number */
2440
                    VFP_DREG_N(rn, insn);
2441
                }
2442

    
2443
                if (op == 15 && (rn == 15 || rn > 17)) {
2444
                    /* Integer or single precision destination.  */
2445
                    rd = VFP_SREG_D(insn);
2446
                } else {
2447
                    VFP_DREG_D(rd, insn);
2448
                }
2449

    
2450
                if (op == 15 && (rn == 16 || rn == 17)) {
2451
                    /* Integer source.  */
2452
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2453
                } else {
2454
                    VFP_DREG_M(rm, insn);
2455
                }
2456
            } else {
2457
                rn = VFP_SREG_N(insn);
2458
                if (op == 15 && rn == 15) {
2459
                    /* Double precision destination.  */
2460
                    VFP_DREG_D(rd, insn);
2461
                } else {
2462
                    rd = VFP_SREG_D(insn);
2463
                }
2464
                rm = VFP_SREG_M(insn);
2465
            }
2466

    
2467
            veclen = env->vfp.vec_len;
2468
            if (op == 15 && rn > 3)
2469
                veclen = 0;
2470

    
2471
            /* Shut up compiler warnings.  */
2472
            delta_m = 0;
2473
            delta_d = 0;
2474
            bank_mask = 0;
2475

    
2476
            if (veclen > 0) {
2477
                if (dp)
2478
                    bank_mask = 0xc;
2479
                else
2480
                    bank_mask = 0x18;
2481

    
2482
                /* Figure out what type of vector operation this is.  */
2483
                if ((rd & bank_mask) == 0) {
2484
                    /* scalar */
2485
                    veclen = 0;
2486
                } else {
2487
                    if (dp)
2488
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2489
                    else
2490
                        delta_d = env->vfp.vec_stride + 1;
2491

    
2492
                    if ((rm & bank_mask) == 0) {
2493
                        /* mixed scalar/vector */
2494
                        delta_m = 0;
2495
                    } else {
2496
                        /* vector */
2497
                        delta_m = delta_d;
2498
                    }
2499
                }
2500
            }
2501

    
2502
            /* Load the initial operands.  */
2503
            if (op == 15) {
2504
                switch (rn) {
2505
                case 16:
2506
                case 17:
2507
                    /* Integer source */
2508
                    gen_mov_F0_vreg(0, rm);
2509
                    break;
2510
                case 8:
2511
                case 9:
2512
                    /* Compare */
2513
                    gen_mov_F0_vreg(dp, rd);
2514
                    gen_mov_F1_vreg(dp, rm);
2515
                    break;
2516
                case 10:
2517
                case 11:
2518
                    /* Compare with zero */
2519
                    gen_mov_F0_vreg(dp, rd);
2520
                    gen_vfp_F1_ld0(dp);
2521
                    break;
2522
                case 20:
2523
                case 21:
2524
                case 22:
2525
                case 23:
2526
                    /* Source and destination the same.  */
2527
                    gen_mov_F0_vreg(dp, rd);
2528
                    break;
2529
                default:
2530
                    /* One source operand.  */
2531
                    gen_mov_F0_vreg(dp, rm);
2532
                    break;
2533
                }
2534
            } else {
2535
                /* Two source operands.  */
2536
                gen_mov_F0_vreg(dp, rn);
2537
                gen_mov_F1_vreg(dp, rm);
2538
            }
2539

    
2540
            for (;;) {
2541
                /* Perform the calculation.  */
2542
                switch (op) {
2543
                case 0: /* mac: fd + (fn * fm) */
2544
                    gen_vfp_mul(dp);
2545
                    gen_mov_F1_vreg(dp, rd);
2546
                    gen_vfp_add(dp);
2547
                    break;
2548
                case 1: /* nmac: fd - (fn * fm) */
2549
                    gen_vfp_mul(dp);
2550
                    gen_vfp_neg(dp);
2551
                    gen_mov_F1_vreg(dp, rd);
2552
                    gen_vfp_add(dp);
2553
                    break;
2554
                case 2: /* msc: -fd + (fn * fm) */
2555
                    gen_vfp_mul(dp);
2556
                    gen_mov_F1_vreg(dp, rd);
2557
                    gen_vfp_sub(dp);
2558
                    break;
2559
                case 3: /* nmsc: -fd - (fn * fm)  */
2560
                    gen_vfp_mul(dp);
2561
                    gen_mov_F1_vreg(dp, rd);
2562
                    gen_vfp_add(dp);
2563
                    gen_vfp_neg(dp);
2564
                    break;
2565
                case 4: /* mul: fn * fm */
2566
                    gen_vfp_mul(dp);
2567
                    break;
2568
                case 5: /* nmul: -(fn * fm) */
2569
                    gen_vfp_mul(dp);
2570
                    gen_vfp_neg(dp);
2571
                    break;
2572
                case 6: /* add: fn + fm */
2573
                    gen_vfp_add(dp);
2574
                    break;
2575
                case 7: /* sub: fn - fm */
2576
                    gen_vfp_sub(dp);
2577
                    break;
2578
                case 8: /* div: fn / fm */
2579
                    gen_vfp_div(dp);
2580
                    break;
2581
                case 14: /* fconst */
2582
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2583
                      return 1;
2584

    
2585
                    n = (insn << 12) & 0x80000000;
2586
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2587
                    if (dp) {
2588
                        if (i & 0x40)
2589
                            i |= 0x3f80;
2590
                        else
2591
                            i |= 0x4000;
2592
                        n |= i << 16;
2593
                    } else {
2594
                        if (i & 0x40)
2595
                            i |= 0x780;
2596
                        else
2597
                            i |= 0x800;
2598
                        n |= i << 19;
2599
                    }
2600
                    gen_vfp_fconst(dp, n);
2601
                    break;
2602
                case 15: /* extension space */
2603
                    switch (rn) {
2604
                    case 0: /* cpy */
2605
                        /* no-op */
2606
                        break;
2607
                    case 1: /* abs */
2608
                        gen_vfp_abs(dp);
2609
                        break;
2610
                    case 2: /* neg */
2611
                        gen_vfp_neg(dp);
2612
                        break;
2613
                    case 3: /* sqrt */
2614
                        gen_vfp_sqrt(dp);
2615
                        break;
2616
                    case 8: /* cmp */
2617
                        gen_vfp_cmp(dp);
2618
                        break;
2619
                    case 9: /* cmpe */
2620
                        gen_vfp_cmpe(dp);
2621
                        break;
2622
                    case 10: /* cmpz */
2623
                        gen_vfp_cmp(dp);
2624
                        break;
2625
                    case 11: /* cmpez */
2626
                        gen_vfp_F1_ld0(dp);
2627
                        gen_vfp_cmpe(dp);
2628
                        break;
2629
                    case 15: /* single<->double conversion */
2630
                        if (dp)
2631
                            gen_op_vfp_fcvtsd();
2632
                        else
2633
                            gen_op_vfp_fcvtds();
2634
                        break;
2635
                    case 16: /* fuito */
2636
                        gen_vfp_uito(dp);
2637
                        break;
2638
                    case 17: /* fsito */
2639
                        gen_vfp_sito(dp);
2640
                        break;
2641
                    case 20: /* fshto */
2642
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2643
                          return 1;
2644
                        gen_vfp_shto(dp, rm);
2645
                        break;
2646
                    case 21: /* fslto */
2647
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2648
                          return 1;
2649
                        gen_vfp_slto(dp, rm);
2650
                        break;
2651
                    case 22: /* fuhto */
2652
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2653
                          return 1;
2654
                        gen_vfp_uhto(dp, rm);
2655
                        break;
2656
                    case 23: /* fulto */
2657
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2658
                          return 1;
2659
                        gen_vfp_ulto(dp, rm);
2660
                        break;
2661
                    case 24: /* ftoui */
2662
                        gen_vfp_toui(dp);
2663
                        break;
2664
                    case 25: /* ftouiz */
2665
                        gen_vfp_touiz(dp);
2666
                        break;
2667
                    case 26: /* ftosi */
2668
                        gen_vfp_tosi(dp);
2669
                        break;
2670
                    case 27: /* ftosiz */
2671
                        gen_vfp_tosiz(dp);
2672
                        break;
2673
                    case 28: /* ftosh */
2674
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2675
                          return 1;
2676
                        gen_vfp_tosh(dp, rm);
2677
                        break;
2678
                    case 29: /* ftosl */
2679
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2680
                          return 1;
2681
                        gen_vfp_tosl(dp, rm);
2682
                        break;
2683
                    case 30: /* ftouh */
2684
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2685
                          return 1;
2686
                        gen_vfp_touh(dp, rm);
2687
                        break;
2688
                    case 31: /* ftoul */
2689
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2690
                          return 1;
2691
                        gen_vfp_toul(dp, rm);
2692
                        break;
2693
                    default: /* undefined */
2694
                        printf ("rn:%d\n", rn);
2695
                        return 1;
2696
                    }
2697
                    break;
2698
                default: /* undefined */
2699
                    printf ("op:%d\n", op);
2700
                    return 1;
2701
                }
2702

    
2703
                /* Write back the result.  */
2704
                if (op == 15 && (rn >= 8 && rn <= 11))
2705
                    ; /* Comparison, do nothing.  */
2706
                else if (op == 15 && rn > 17)
2707
                    /* Integer result.  */
2708
                    gen_mov_vreg_F0(0, rd);
2709
                else if (op == 15 && rn == 15)
2710
                    /* conversion */
2711
                    gen_mov_vreg_F0(!dp, rd);
2712
                else
2713
                    gen_mov_vreg_F0(dp, rd);
2714

    
2715
                /* break out of the loop if we have finished  */
2716
                if (veclen == 0)
2717
                    break;
2718

    
2719
                if (op == 15 && delta_m == 0) {
2720
                    /* single source one-many */
2721
                    while (veclen--) {
2722
                        rd = ((rd + delta_d) & (bank_mask - 1))
2723
                             | (rd & bank_mask);
2724
                        gen_mov_vreg_F0(dp, rd);
2725
                    }
2726
                    break;
2727
                }
2728
                /* Setup the next operands.  */
2729
                veclen--;
2730
                rd = ((rd + delta_d) & (bank_mask - 1))
2731
                     | (rd & bank_mask);
2732

    
2733
                if (op == 15) {
2734
                    /* One source operand.  */
2735
                    rm = ((rm + delta_m) & (bank_mask - 1))
2736
                         | (rm & bank_mask);
2737
                    gen_mov_F0_vreg(dp, rm);
2738
                } else {
2739
                    /* Two source operands.  */
2740
                    rn = ((rn + delta_d) & (bank_mask - 1))
2741
                         | (rn & bank_mask);
2742
                    gen_mov_F0_vreg(dp, rn);
2743
                    if (delta_m) {
2744
                        rm = ((rm + delta_m) & (bank_mask - 1))
2745
                             | (rm & bank_mask);
2746
                        gen_mov_F1_vreg(dp, rm);
2747
                    }
2748
                }
2749
            }
2750
        }
2751
        break;
2752
    case 0xc:
2753
    case 0xd:
2754
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2755
            /* two-register transfer */
2756
            rn = (insn >> 16) & 0xf;
2757
            rd = (insn >> 12) & 0xf;
2758
            if (dp) {
2759
                VFP_DREG_M(rm, insn);
2760
            } else {
2761
                rm = VFP_SREG_M(insn);
2762
            }
2763

    
2764
            if (insn & ARM_CP_RW_BIT) {
2765
                /* vfp->arm */
2766
                if (dp) {
2767
                    gen_mov_F0_vreg(1, rm);
2768
                    gen_op_vfp_mrrd();
2769
                    gen_movl_reg_T0(s, rd);
2770
                    gen_movl_reg_T1(s, rn);
2771
                } else {
2772
                    gen_mov_F0_vreg(0, rm);
2773
                    gen_op_vfp_mrs();
2774
                    gen_movl_reg_T0(s, rn);
2775
                    gen_mov_F0_vreg(0, rm + 1);
2776
                    gen_op_vfp_mrs();
2777
                    gen_movl_reg_T0(s, rd);
2778
                }
2779
            } else {
2780
                /* arm->vfp */
2781
                if (dp) {
2782
                    gen_movl_T0_reg(s, rd);
2783
                    gen_movl_T1_reg(s, rn);
2784
                    gen_op_vfp_mdrr();
2785
                    gen_mov_vreg_F0(1, rm);
2786
                } else {
2787
                    gen_movl_T0_reg(s, rn);
2788
                    gen_op_vfp_msr();
2789
                    gen_mov_vreg_F0(0, rm);
2790
                    gen_movl_T0_reg(s, rd);
2791
                    gen_op_vfp_msr();
2792
                    gen_mov_vreg_F0(0, rm + 1);
2793
                }
2794
            }
2795
        } else {
2796
            /* Load/store */
2797
            rn = (insn >> 16) & 0xf;
2798
            if (dp)
2799
                VFP_DREG_D(rd, insn);
2800
            else
2801
                rd = VFP_SREG_D(insn);
2802
            if (s->thumb && rn == 15) {
2803
                gen_op_movl_T1_im(s->pc & ~2);
2804
            } else {
2805
                gen_movl_T1_reg(s, rn);
2806
            }
2807
            if ((insn & 0x01200000) == 0x01000000) {
2808
                /* Single load/store */
2809
                offset = (insn & 0xff) << 2;
2810
                if ((insn & (1 << 23)) == 0)
2811
                    offset = -offset;
2812
                gen_op_addl_T1_im(offset);
2813
                if (insn & (1 << 20)) {
2814
                    gen_vfp_ld(s, dp);
2815
                    gen_mov_vreg_F0(dp, rd);
2816
                } else {
2817
                    gen_mov_F0_vreg(dp, rd);
2818
                    gen_vfp_st(s, dp);
2819
                }
2820
            } else {
2821
                /* load/store multiple */
2822
                if (dp)
2823
                    n = (insn >> 1) & 0x7f;
2824
                else
2825
                    n = insn & 0xff;
2826

    
2827
                if (insn & (1 << 24)) /* pre-decrement */
2828
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2829

    
2830
                if (dp)
2831
                    offset = 8;
2832
                else
2833
                    offset = 4;
2834
                for (i = 0; i < n; i++) {
2835
                    if (insn & ARM_CP_RW_BIT) {
2836
                        /* load */
2837
                        gen_vfp_ld(s, dp);
2838
                        gen_mov_vreg_F0(dp, rd + i);
2839
                    } else {
2840
                        /* store */
2841
                        gen_mov_F0_vreg(dp, rd + i);
2842
                        gen_vfp_st(s, dp);
2843
                    }
2844
                    gen_op_addl_T1_im(offset);
2845
                }
2846
                if (insn & (1 << 21)) {
2847
                    /* writeback */
2848
                    if (insn & (1 << 24))
2849
                        offset = -offset * n;
2850
                    else if (dp && (insn & 1))
2851
                        offset = 4;
2852
                    else
2853
                        offset = 0;
2854

    
2855
                    if (offset != 0)
2856
                        gen_op_addl_T1_im(offset);
2857
                    gen_movl_reg_T1(s, rn);
2858
                }
2859
            }
2860
        }
2861
        break;
2862
    default:
2863
        /* Should never happen.  */
2864
        return 1;
2865
    }
2866
    return 0;
2867
}
2868

    
2869
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2870
{
2871
    TranslationBlock *tb;
2872

    
2873
    tb = s->tb;
2874
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2875
        tcg_gen_goto_tb(n);
2876
        gen_op_movl_T0_im(dest);
2877
        gen_set_pc_T0();
2878
        tcg_gen_exit_tb((long)tb + n);
2879
    } else {
2880
        gen_op_movl_T0_im(dest);
2881
        gen_set_pc_T0();
2882
        tcg_gen_exit_tb(0);
2883
    }
2884
}
2885

    
2886
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2887
{
2888
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2889
        /* An indirect jump so that we still trigger the debug exception.  */
2890
        if (s->thumb)
2891
            dest |= 1;
2892
        gen_bx_im(s, dest);
2893
    } else {
2894
        gen_goto_tb(s, 0, dest);
2895
        s->is_jmp = DISAS_TB_JUMP;
2896
    }
2897
}
2898

    
2899
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
2900
{
2901
    if (x)
2902
        tcg_gen_sari_i32(t0, t0, 16);
2903
    else
2904
        gen_sxth(t0);
2905
    if (y)
2906
        tcg_gen_sari_i32(t1, t1, 16);
2907
    else
2908
        gen_sxth(t1);
2909
    tcg_gen_mul_i32(t0, t0, t1);
2910
}
2911

    
2912
/* Return the mask of PSR bits set by a MSR instruction.  */
2913
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2914
    uint32_t mask;
2915

    
2916
    mask = 0;
2917
    if (flags & (1 << 0))
2918
        mask |= 0xff;
2919
    if (flags & (1 << 1))
2920
        mask |= 0xff00;
2921
    if (flags & (1 << 2))
2922
        mask |= 0xff0000;
2923
    if (flags & (1 << 3))
2924
        mask |= 0xff000000;
2925

    
2926
    /* Mask out undefined bits.  */
2927
    mask &= ~CPSR_RESERVED;
2928
    if (!arm_feature(env, ARM_FEATURE_V6))
2929
        mask &= ~(CPSR_E | CPSR_GE);
2930
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2931
        mask &= ~CPSR_IT;
2932
    /* Mask out execution state bits.  */
2933
    if (!spsr)
2934
        mask &= ~CPSR_EXEC;
2935
    /* Mask out privileged bits.  */
2936
    if (IS_USER(s))
2937
        mask &= CPSR_USER;
2938
    return mask;
2939
}
2940

    
2941
/* Returns nonzero if access to the PSR is not permitted.  */
2942
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2943
{
2944
    TCGv tmp;
2945
    if (spsr) {
2946
        /* ??? This is also undefined in system mode.  */
2947
        if (IS_USER(s))
2948
            return 1;
2949

    
2950
        tmp = load_cpu_field(spsr);
2951
        tcg_gen_andi_i32(tmp, tmp, ~mask);
2952
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
2953
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
2954
        store_cpu_field(tmp, spsr);
2955
    } else {
2956
        gen_set_cpsr(cpu_T[0], mask);
2957
    }
2958
    gen_lookup_tb(s);
2959
    return 0;
2960
}
2961

    
2962
/* Generate an old-style exception return.  */
2963
static void gen_exception_return(DisasContext *s)
2964
{
2965
    TCGv tmp;
2966
    gen_set_pc_T0();
2967
    tmp = load_cpu_field(spsr);
2968
    gen_set_cpsr(tmp, 0xffffffff);
2969
    dead_tmp(tmp);
2970
    s->is_jmp = DISAS_UPDATE;
2971
}
2972

    
2973
/* Generate a v6 exception return.  */
2974
static void gen_rfe(DisasContext *s)
2975
{
2976
    gen_set_cpsr(cpu_T[0], 0xffffffff);
2977
    gen_op_movl_T0_T2();
2978
    gen_set_pc_T0();
2979
    s->is_jmp = DISAS_UPDATE;
2980
}
2981

    
2982
static inline void
2983
gen_set_condexec (DisasContext *s)
2984
{
2985
    if (s->condexec_mask) {
2986
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
2987
        TCGv tmp = new_tmp();
2988
        tcg_gen_movi_i32(tmp, val);
2989
        store_cpu_field(tmp, condexec_bits);
2990
    }
2991
}
2992

    
2993
static void gen_nop_hint(DisasContext *s, int val)
2994
{
2995
    switch (val) {
2996
    case 3: /* wfi */
2997
        gen_op_movl_T0_im((long)s->pc);
2998
        gen_set_pc_T0();
2999
        s->is_jmp = DISAS_WFI;
3000
        break;
3001
    case 2: /* wfe */
3002
    case 4: /* sev */
3003
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3004
    default: /* nop */
3005
        break;
3006
    }
3007
}
3008

    
3009
/* Neon shift by constant.  The actual ops are the same as used for variable
3010
   shifts.  [OP][U][SIZE]  */
3011
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
3012
    { /* 0 */ /* VSHR */
3013
      {
3014
        gen_op_neon_shl_u8,
3015
        gen_op_neon_shl_u16,
3016
        gen_op_neon_shl_u32,
3017
        gen_op_neon_shl_u64
3018
      }, {
3019
        gen_op_neon_shl_s8,
3020
        gen_op_neon_shl_s16,
3021
        gen_op_neon_shl_s32,
3022
        gen_op_neon_shl_s64
3023
      }
3024
    }, { /* 1 */ /* VSRA */
3025
      {
3026
        gen_op_neon_shl_u8,
3027
        gen_op_neon_shl_u16,
3028
        gen_op_neon_shl_u32,
3029
        gen_op_neon_shl_u64
3030
      }, {
3031
        gen_op_neon_shl_s8,
3032
        gen_op_neon_shl_s16,
3033
        gen_op_neon_shl_s32,
3034
        gen_op_neon_shl_s64
3035
      }
3036
    }, { /* 2 */ /* VRSHR */
3037
      {
3038
        gen_op_neon_rshl_u8,
3039
        gen_op_neon_rshl_u16,
3040
        gen_op_neon_rshl_u32,
3041
        gen_op_neon_rshl_u64
3042
      }, {
3043
        gen_op_neon_rshl_s8,
3044
        gen_op_neon_rshl_s16,
3045
        gen_op_neon_rshl_s32,
3046
        gen_op_neon_rshl_s64
3047
      }
3048
    }, { /* 3 */ /* VRSRA */
3049
      {
3050
        gen_op_neon_rshl_u8,
3051
        gen_op_neon_rshl_u16,
3052
        gen_op_neon_rshl_u32,
3053
        gen_op_neon_rshl_u64
3054
      }, {
3055
        gen_op_neon_rshl_s8,
3056
        gen_op_neon_rshl_s16,
3057
        gen_op_neon_rshl_s32,
3058
        gen_op_neon_rshl_s64
3059
      }
3060
    }, { /* 4 */
3061
      {
3062
        NULL, NULL, NULL, NULL
3063
      }, { /* VSRI */
3064
        gen_op_neon_shl_u8,
3065
        gen_op_neon_shl_u16,
3066
        gen_op_neon_shl_u32,
3067
        gen_op_neon_shl_u64,
3068
      }
3069
    }, { /* 5 */
3070
      { /* VSHL */
3071
        gen_op_neon_shl_u8,
3072
        gen_op_neon_shl_u16,
3073
        gen_op_neon_shl_u32,
3074
        gen_op_neon_shl_u64,
3075
      }, { /* VSLI */
3076
        gen_op_neon_shl_u8,
3077
        gen_op_neon_shl_u16,
3078
        gen_op_neon_shl_u32,
3079
        gen_op_neon_shl_u64,
3080
      }
3081
    }, { /* 6 */ /* VQSHL */
3082
      {
3083
        gen_op_neon_qshl_u8,
3084
        gen_op_neon_qshl_u16,
3085
        gen_op_neon_qshl_u32,
3086
        gen_op_neon_qshl_u64
3087
      }, {
3088
        gen_op_neon_qshl_s8,
3089
        gen_op_neon_qshl_s16,
3090
        gen_op_neon_qshl_s32,
3091
        gen_op_neon_qshl_s64
3092
      }
3093
    }, { /* 7 */ /* VQSHLU */
3094
      {
3095
        gen_op_neon_qshl_u8,
3096
        gen_op_neon_qshl_u16,
3097
        gen_op_neon_qshl_u32,
3098
        gen_op_neon_qshl_u64
3099
      }, {
3100
        gen_op_neon_qshl_u8,
3101
        gen_op_neon_qshl_u16,
3102
        gen_op_neon_qshl_u32,
3103
        gen_op_neon_qshl_u64
3104
      }
3105
    }
3106
};
3107

    
3108
/* [R][U][size - 1] */
3109
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
3110
    {
3111
      {
3112
        gen_op_neon_shl_u16,
3113
        gen_op_neon_shl_u32,
3114
        gen_op_neon_shl_u64
3115
      }, {
3116
        gen_op_neon_shl_s16,
3117
        gen_op_neon_shl_s32,
3118
        gen_op_neon_shl_s64
3119
      }
3120
    }, {
3121
      {
3122
        gen_op_neon_rshl_u16,
3123
        gen_op_neon_rshl_u32,
3124
        gen_op_neon_rshl_u64
3125
      }, {
3126
        gen_op_neon_rshl_s16,
3127
        gen_op_neon_rshl_s32,
3128
        gen_op_neon_rshl_s64
3129
      }
3130
    }
3131
};
3132

    
3133
static inline void
3134
gen_op_neon_narrow_u32 ()
3135
{
3136
    /* No-op.  */
3137
}
3138

    
3139
static GenOpFunc *gen_neon_narrow[3] = {
3140
    gen_op_neon_narrow_u8,
3141
    gen_op_neon_narrow_u16,
3142
    gen_op_neon_narrow_u32
3143
};
3144

    
3145
static GenOpFunc *gen_neon_narrow_satu[3] = {
3146
    gen_op_neon_narrow_sat_u8,
3147
    gen_op_neon_narrow_sat_u16,
3148
    gen_op_neon_narrow_sat_u32
3149
};
3150

    
3151
static GenOpFunc *gen_neon_narrow_sats[3] = {
3152
    gen_op_neon_narrow_sat_s8,
3153
    gen_op_neon_narrow_sat_s16,
3154
    gen_op_neon_narrow_sat_s32
3155
};
3156

    
3157
static inline int gen_neon_add(int size)
3158
{
3159
    switch (size) {
3160
    case 0: gen_op_neon_add_u8(); break;
3161
    case 1: gen_op_neon_add_u16(); break;
3162
    case 2: gen_op_addl_T0_T1(); break;
3163
    default: return 1;
3164
    }
3165
    return 0;
3166
}
3167

    
3168
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
3169
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
3170
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
3171
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
3172
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
3173

    
3174
#define GEN_NEON_INTEGER_OP(name) do { \
3175
    switch ((size << 1) | u) { \
3176
    case 0: gen_op_neon_##name##_s8(); break; \
3177
    case 1: gen_op_neon_##name##_u8(); break; \
3178
    case 2: gen_op_neon_##name##_s16(); break; \
3179
    case 3: gen_op_neon_##name##_u16(); break; \
3180
    case 4: gen_op_neon_##name##_s32(); break; \
3181
    case 5: gen_op_neon_##name##_u32(); break; \
3182
    default: return 1; \
3183
    }} while (0)
3184

    
3185
static inline void
3186
gen_neon_movl_scratch_T0(int scratch)
3187
{
3188
  uint32_t offset;
3189

    
3190
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3191
  gen_op_neon_setreg_T0(offset);
3192
}
3193

    
3194
static inline void
3195
gen_neon_movl_scratch_T1(int scratch)
3196
{
3197
  uint32_t offset;
3198

    
3199
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3200
  gen_op_neon_setreg_T1(offset);
3201
}
3202

    
3203
static inline void
3204
gen_neon_movl_T0_scratch(int scratch)
3205
{
3206
  uint32_t offset;
3207

    
3208
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3209
  gen_op_neon_getreg_T0(offset);
3210
}
3211

    
3212
static inline void
3213
gen_neon_movl_T1_scratch(int scratch)
3214
{
3215
  uint32_t offset;
3216

    
3217
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3218
  gen_op_neon_getreg_T1(offset);
3219
}
3220

    
3221
static inline void gen_op_neon_widen_u32(void)
3222
{
3223
    gen_op_movl_T1_im(0);
3224
}
3225

    
3226
static inline void gen_neon_get_scalar(int size, int reg)
3227
{
3228
    if (size == 1) {
3229
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3230
    } else {
3231
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3232
        if (reg & 1)
3233
            gen_op_neon_dup_low16();
3234
        else
3235
            gen_op_neon_dup_high16();
3236
    }
3237
}
3238

    
3239
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3240
{
3241
    int n;
3242

    
3243
    for (n = 0; n < q + 1; n += 2) {
3244
        NEON_GET_REG(T0, reg, n);
3245
        NEON_GET_REG(T0, reg, n + n);
3246
        switch (size) {
3247
        case 0: gen_op_neon_unzip_u8(); break;
3248
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
3249
        case 2: /* no-op */; break;
3250
        default: abort();
3251
        }
3252
        gen_neon_movl_scratch_T0(tmp + n);
3253
        gen_neon_movl_scratch_T1(tmp + n + 1);
3254
    }
3255
}
3256

    
3257
static struct {
3258
    int nregs;
3259
    int interleave;
3260
    int spacing;
3261
} neon_ls_element_type[11] = {
3262
    {4, 4, 1},
3263
    {4, 4, 2},
3264
    {4, 1, 1},
3265
    {4, 2, 1},
3266
    {3, 3, 1},
3267
    {3, 3, 2},
3268
    {3, 1, 1},
3269
    {1, 1, 1},
3270
    {2, 2, 1},
3271
    {2, 2, 2},
3272
    {2, 1, 1}
3273
};
3274

    
3275
/* Translate a NEON load/store element instruction.  Return nonzero if the
3276
   instruction is invalid.  */
3277
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3278
{
3279
    int rd, rn, rm;
3280
    int op;
3281
    int nregs;
3282
    int interleave;
3283
    int stride;
3284
    int size;
3285
    int reg;
3286
    int pass;
3287
    int load;
3288
    int shift;
3289
    uint32_t mask;
3290
    int n;
3291

    
3292
    if (!vfp_enabled(env))
3293
      return 1;
3294
    VFP_DREG_D(rd, insn);
3295
    rn = (insn >> 16) & 0xf;
3296
    rm = insn & 0xf;
3297
    load = (insn & (1 << 21)) != 0;
3298
    if ((insn & (1 << 23)) == 0) {
3299
        /* Load store all elements.  */
3300
        op = (insn >> 8) & 0xf;
3301
        size = (insn >> 6) & 3;
3302
        if (op > 10 || size == 3)
3303
            return 1;
3304
        nregs = neon_ls_element_type[op].nregs;
3305
        interleave = neon_ls_element_type[op].interleave;
3306
        gen_movl_T1_reg(s, rn);
3307
        stride = (1 << size) * interleave;
3308
        for (reg = 0; reg < nregs; reg++) {
3309
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3310
                gen_movl_T1_reg(s, rn);
3311
                gen_op_addl_T1_im((1 << size) * reg);
3312
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3313
                gen_movl_T1_reg(s, rn);
3314
                gen_op_addl_T1_im(1 << size);
3315
            }
3316
            for (pass = 0; pass < 2; pass++) {
3317
                if (size == 2) {
3318
                    if (load) {
3319
                        gen_ldst(ldl, s);
3320
                        NEON_SET_REG(T0, rd, pass);
3321
                    } else {
3322
                        NEON_GET_REG(T0, rd, pass);
3323
                        gen_ldst(stl, s);
3324
                    }
3325
                    gen_op_addl_T1_im(stride);
3326
                } else if (size == 1) {
3327
                    if (load) {
3328
                        gen_ldst(lduw, s);
3329
                        gen_op_addl_T1_im(stride);
3330
                        gen_op_movl_T2_T0();
3331
                        gen_ldst(lduw, s);
3332
                        gen_op_addl_T1_im(stride);
3333
                        gen_op_neon_insert_elt(16, 0xffff);
3334
                        NEON_SET_REG(T2, rd, pass);
3335
                    } else {
3336
                        NEON_GET_REG(T2, rd, pass);
3337
                        gen_op_movl_T0_T2();
3338
                        gen_ldst(stw, s);
3339
                        gen_op_addl_T1_im(stride);
3340
                        gen_op_neon_extract_elt(16, 0xffff0000);
3341
                        gen_ldst(stw, s);
3342
                        gen_op_addl_T1_im(stride);
3343
                    }
3344
                } else /* size == 0 */ {
3345
                    if (load) {
3346
                        mask = 0xff;
3347
                        for (n = 0; n < 4; n++) {
3348
                            gen_ldst(ldub, s);
3349
                            gen_op_addl_T1_im(stride);
3350
                            if (n == 0) {
3351
                                gen_op_movl_T2_T0();
3352
                            } else {
3353
                                gen_op_neon_insert_elt(n * 8, ~mask);
3354
                            }
3355
                            mask <<= 8;
3356
                        }
3357
                        NEON_SET_REG(T2, rd, pass);
3358
                    } else {
3359
                        NEON_GET_REG(T2, rd, pass);
3360
                        mask = 0xff;
3361
                        for (n = 0; n < 4; n++) {
3362
                            if (n == 0) {
3363
                                gen_op_movl_T0_T2();
3364
                            } else {
3365
                                gen_op_neon_extract_elt(n * 8, mask);
3366
                            }
3367
                            gen_ldst(stb, s);
3368
                            gen_op_addl_T1_im(stride);
3369
                            mask <<= 8;
3370
                        }
3371
                    }
3372
                }
3373
            }
3374
            rd += neon_ls_element_type[op].spacing;
3375
        }
3376
        stride = nregs * 8;
3377
    } else {
3378
        size = (insn >> 10) & 3;
3379
        if (size == 3) {
3380
            /* Load single element to all lanes.  */
3381
            if (!load)
3382
                return 1;
3383
            size = (insn >> 6) & 3;
3384
            nregs = ((insn >> 8) & 3) + 1;
3385
            stride = (insn & (1 << 5)) ? 2 : 1;
3386
            gen_movl_T1_reg(s, rn);
3387
            for (reg = 0; reg < nregs; reg++) {
3388
                switch (size) {
3389
                case 0:
3390
                    gen_ldst(ldub, s);
3391
                    gen_op_neon_dup_u8(0);
3392
                    break;
3393
                case 1:
3394
                    gen_ldst(lduw, s);
3395
                    gen_op_neon_dup_low16();
3396
                    break;
3397
                case 2:
3398
                    gen_ldst(ldl, s);
3399
                    break;
3400
                case 3:
3401
                    return 1;
3402
                }
3403
                gen_op_addl_T1_im(1 << size);
3404
                NEON_SET_REG(T0, rd, 0);
3405
                NEON_SET_REG(T0, rd, 1);
3406
                rd += stride;
3407
            }
3408
            stride = (1 << size) * nregs;
3409
        } else {
3410
            /* Single element.  */
3411
            pass = (insn >> 7) & 1;
3412
            switch (size) {
3413
            case 0:
3414
                shift = ((insn >> 5) & 3) * 8;
3415
                mask = 0xff << shift;
3416
                stride = 1;
3417
                break;
3418
            case 1:
3419
                shift = ((insn >> 6) & 1) * 16;
3420
                mask = shift ? 0xffff0000 : 0xffff;
3421
                stride = (insn & (1 << 5)) ? 2 : 1;
3422
                break;
3423
            case 2:
3424
                shift = 0;
3425
                mask = 0xffffffff;
3426
                stride = (insn & (1 << 6)) ? 2 : 1;
3427
                break;
3428
            default:
3429
                abort();
3430
            }
3431
            nregs = ((insn >> 8) & 3) + 1;
3432
            gen_movl_T1_reg(s, rn);
3433
            for (reg = 0; reg < nregs; reg++) {
3434
                if (load) {
3435
                    if (size != 2) {
3436
                        NEON_GET_REG(T2, rd, pass);
3437
                    }
3438
                    switch (size) {
3439
                    case 0:
3440
                        gen_ldst(ldub, s);
3441
                        break;
3442
                    case 1:
3443
                        gen_ldst(lduw, s);
3444
                        break;
3445
                    case 2:
3446
                        gen_ldst(ldl, s);
3447
                        NEON_SET_REG(T0, rd, pass);
3448
                        break;
3449
                    }
3450
                    if (size != 2) {
3451
                        gen_op_neon_insert_elt(shift, ~mask);
3452
                        NEON_SET_REG(T0, rd, pass);
3453
                    }
3454
                } else { /* Store */
3455
                    if (size == 2) {
3456
                        NEON_GET_REG(T0, rd, pass);
3457
                    } else {
3458
                        NEON_GET_REG(T2, rd, pass);
3459
                        gen_op_neon_extract_elt(shift, mask);
3460
                    }
3461
                    switch (size) {
3462
                    case 0:
3463
                        gen_ldst(stb, s);
3464
                        break;
3465
                    case 1:
3466
                        gen_ldst(stw, s);
3467
                        break;
3468
                    case 2:
3469
                        gen_ldst(stl, s);
3470
                        break;
3471
                    }
3472
                }
3473
                rd += stride;
3474
                gen_op_addl_T1_im(1 << size);
3475
            }
3476
            stride = nregs * (1 << size);
3477
        }
3478
    }
3479
    if (rm != 15) {
3480
        TCGv base;
3481

    
3482
        base = load_reg(s, rn);
3483
        if (rm == 13) {
3484
            tcg_gen_addi_i32(base, base, stride);
3485
        } else {
3486
            TCGv index;
3487
            index = load_reg(s, rm);
3488
            tcg_gen_add_i32(base, base, index);
3489
            dead_tmp(index);
3490
        }
3491
        store_reg(s, rn, base);
3492
    }
3493
    return 0;
3494
}
3495

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

    
3503
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3504
{
3505
    int op;
3506
    int q;
3507
    int rd, rn, rm;
3508
    int size;
3509
    int shift;
3510
    int pass;
3511
    int count;
3512
    int pairwise;
3513
    int u;
3514
    int n;
3515
    uint32_t imm;
3516

    
3517
    if (!vfp_enabled(env))
3518
      return 1;
3519
    q = (insn & (1 << 6)) != 0;
3520
    u = (insn >> 24) & 1;
3521
    VFP_DREG_D(rd, insn);
3522
    VFP_DREG_N(rn, insn);
3523
    VFP_DREG_M(rm, insn);
3524
    size = (insn >> 20) & 3;
3525
    if ((insn & (1 << 23)) == 0) {
3526
        /* Three register same length.  */
3527
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3528
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3529
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3530
                NEON_GET_REG(T0, rm, pass * 2);
3531
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3532
                gen_neon_movl_scratch_T0(0);
3533
                gen_neon_movl_scratch_T1(1);
3534
                NEON_GET_REG(T0, rn, pass * 2);
3535
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3536
                switch (op) {
3537
                case 1: /* VQADD */
3538
                    if (u) {
3539
                        gen_op_neon_addl_saturate_u64();
3540
                    } else {
3541
                        gen_op_neon_addl_saturate_s64();
3542
                    }
3543
                    break;
3544
                case 5: /* VQSUB */
3545
                    if (u) {
3546
                        gen_op_neon_subl_saturate_u64();
3547
                    } else {
3548
                        gen_op_neon_subl_saturate_s64();
3549
                    }
3550
                    break;
3551
                case 16:
3552
                    if (u) {
3553
                        gen_op_neon_subl_u64();
3554
                    } else {
3555
                        gen_op_neon_addl_u64();
3556
                    }
3557
                    break;
3558
                default:
3559
                    abort();
3560
                }
3561
                NEON_SET_REG(T0, rd, pass * 2);
3562
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3563
            }
3564
            return 0;
3565
        }
3566
        switch (op) {
3567
        case 8: /* VSHL */
3568
        case 9: /* VQSHL */
3569
        case 10: /* VRSHL */
3570
        case 11: /* VQSHL */
3571
            /* Shift operations have Rn and Rm reversed.  */
3572
            {
3573
                int tmp;
3574
                tmp = rn;
3575
                rn = rm;
3576
                rm = tmp;
3577
                pairwise = 0;
3578
            }
3579
            break;
3580
        case 20: /* VPMAX */
3581
        case 21: /* VPMIN */
3582
        case 23: /* VPADD */
3583
            pairwise = 1;
3584
            break;
3585
        case 26: /* VPADD (float) */
3586
            pairwise = (u && size < 2);
3587
            break;
3588
        case 30: /* VPMIN/VPMAX (float) */
3589
            pairwise = u;
3590
            break;
3591
        default:
3592
            pairwise = 0;
3593
            break;
3594
        }
3595
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3596

    
3597
        if (pairwise) {
3598
            /* Pairwise.  */
3599
            if (q)
3600
                n = (pass & 1) * 2;
3601
            else
3602
                n = 0;
3603
            if (pass < q + 1) {
3604
                NEON_GET_REG(T0, rn, n);
3605
                NEON_GET_REG(T1, rn, n + 1);
3606
            } else {
3607
                NEON_GET_REG(T0, rm, n);
3608
                NEON_GET_REG(T1, rm, n + 1);
3609
            }
3610
        } else {
3611
            /* Elementwise.  */
3612
            NEON_GET_REG(T0, rn, pass);
3613
            NEON_GET_REG(T1, rm, pass);
3614
        }
3615
        switch (op) {
3616
        case 0: /* VHADD */
3617
            GEN_NEON_INTEGER_OP(hadd);
3618
            break;
3619
        case 1: /* VQADD */
3620
            switch (size << 1| u) {
3621
            case 0: gen_op_neon_qadd_s8(); break;
3622
            case 1: gen_op_neon_qadd_u8(); break;
3623
            case 2: gen_op_neon_qadd_s16(); break;
3624
            case 3: gen_op_neon_qadd_u16(); break;
3625
            case 4: gen_op_addl_T0_T1_saturate(); break;
3626
            case 5: gen_op_addl_T0_T1_usaturate(); break;
3627
            default: abort();
3628
            }
3629
            break;
3630
        case 2: /* VRHADD */
3631
            GEN_NEON_INTEGER_OP(rhadd);
3632
            break;
3633
        case 3: /* Logic ops.  */
3634
            switch ((u << 2) | size) {
3635
            case 0: /* VAND */
3636
                gen_op_andl_T0_T1();
3637
                break;
3638
            case 1: /* BIC */
3639
                gen_op_bicl_T0_T1();
3640
                break;
3641
            case 2: /* VORR */
3642
                gen_op_orl_T0_T1();
3643
                break;
3644
            case 3: /* VORN */
3645
                gen_op_notl_T1();
3646
                gen_op_orl_T0_T1();
3647
                break;
3648
            case 4: /* VEOR */
3649
                gen_op_xorl_T0_T1();
3650
                break;
3651
            case 5: /* VBSL */
3652
                NEON_GET_REG(T2, rd, pass);
3653
                gen_op_neon_bsl();
3654
                break;
3655
            case 6: /* VBIT */
3656
                NEON_GET_REG(T2, rd, pass);
3657
                gen_op_neon_bit();
3658
                break;
3659
            case 7: /* VBIF */
3660
                NEON_GET_REG(T2, rd, pass);
3661
                gen_op_neon_bif();
3662
                break;
3663
            }
3664
            break;
3665
        case 4: /* VHSUB */
3666
            GEN_NEON_INTEGER_OP(hsub);
3667
            break;
3668
        case 5: /* VQSUB */
3669
            switch ((size << 1) | u) {
3670
            case 0: gen_op_neon_qsub_s8(); break;
3671
            case 1: gen_op_neon_qsub_u8(); break;
3672
            case 2: gen_op_neon_qsub_s16(); break;
3673
            case 3: gen_op_neon_qsub_u16(); break;
3674
            case 4: gen_op_subl_T0_T1_saturate(); break;
3675
            case 5: gen_op_subl_T0_T1_usaturate(); break;
3676
            default: abort();
3677
            }
3678
            break;
3679
        case 6: /* VCGT */
3680
            GEN_NEON_INTEGER_OP(cgt);
3681
            break;
3682
        case 7: /* VCGE */
3683
            GEN_NEON_INTEGER_OP(cge);
3684
            break;
3685
        case 8: /* VSHL */
3686
            switch ((size << 1) | u) {
3687
            case 0: gen_op_neon_shl_s8(); break;
3688
            case 1: gen_op_neon_shl_u8(); break;
3689
            case 2: gen_op_neon_shl_s16(); break;
3690
            case 3: gen_op_neon_shl_u16(); break;
3691
            case 4: gen_op_neon_shl_s32(); break;
3692
            case 5: gen_op_neon_shl_u32(); break;
3693
#if 0
3694
            /* ??? Implementing these is tricky because the vector ops work
3695
               on 32-bit pieces.  */
3696
            case 6: gen_op_neon_shl_s64(); break;
3697
            case 7: gen_op_neon_shl_u64(); break;
3698
#else
3699
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3700
#endif
3701
            }
3702
            break;
3703
        case 9: /* VQSHL */
3704
            switch ((size << 1) | u) {
3705
            case 0: gen_op_neon_qshl_s8(); break;
3706
            case 1: gen_op_neon_qshl_u8(); break;
3707
            case 2: gen_op_neon_qshl_s16(); break;
3708
            case 3: gen_op_neon_qshl_u16(); break;
3709
            case 4: gen_op_neon_qshl_s32(); break;
3710
            case 5: gen_op_neon_qshl_u32(); break;
3711
#if 0
3712
            /* ??? Implementing these is tricky because the vector ops work
3713
               on 32-bit pieces.  */
3714
            case 6: gen_op_neon_qshl_s64(); break;
3715
            case 7: gen_op_neon_qshl_u64(); break;
3716
#else
3717
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3718
#endif
3719
            }
3720
            break;
3721
        case 10: /* VRSHL */
3722
            switch ((size << 1) | u) {
3723
            case 0: gen_op_neon_rshl_s8(); break;
3724
            case 1: gen_op_neon_rshl_u8(); break;
3725
            case 2: gen_op_neon_rshl_s16(); break;
3726
            case 3: gen_op_neon_rshl_u16(); break;
3727
            case 4: gen_op_neon_rshl_s32(); break;
3728
            case 5: gen_op_neon_rshl_u32(); break;
3729
#if 0
3730
            /* ??? Implementing these is tricky because the vector ops work
3731
               on 32-bit pieces.  */
3732
            case 6: gen_op_neon_rshl_s64(); break;
3733
            case 7: gen_op_neon_rshl_u64(); break;
3734
#else
3735
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3736
#endif
3737
            }
3738
            break;
3739
        case 11: /* VQRSHL */
3740
            switch ((size << 1) | u) {
3741
            case 0: gen_op_neon_qrshl_s8(); break;
3742
            case 1: gen_op_neon_qrshl_u8(); break;
3743
            case 2: gen_op_neon_qrshl_s16(); break;
3744
            case 3: gen_op_neon_qrshl_u16(); break;
3745
            case 4: gen_op_neon_qrshl_s32(); break;
3746
            case 5: gen_op_neon_qrshl_u32(); break;
3747
#if 0
3748
            /* ??? Implementing these is tricky because the vector ops work
3749
               on 32-bit pieces.  */
3750
            case 6: gen_op_neon_qrshl_s64(); break;
3751
            case 7: gen_op_neon_qrshl_u64(); break;
3752
#else
3753
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3754
#endif
3755
            }
3756
            break;
3757
        case 12: /* VMAX */
3758
            GEN_NEON_INTEGER_OP(max);
3759
            break;
3760
        case 13: /* VMIN */
3761
            GEN_NEON_INTEGER_OP(min);
3762
            break;
3763
        case 14: /* VABD */
3764
            GEN_NEON_INTEGER_OP(abd);
3765
            break;
3766
        case 15: /* VABA */
3767
            GEN_NEON_INTEGER_OP(abd);
3768
            NEON_GET_REG(T1, rd, pass);
3769
            gen_neon_add(size);
3770
            break;
3771
        case 16:
3772
            if (!u) { /* VADD */
3773
                if (gen_neon_add(size))
3774
                    return 1;
3775
            } else { /* VSUB */
3776
                switch (size) {
3777
                case 0: gen_op_neon_sub_u8(); break;
3778
                case 1: gen_op_neon_sub_u16(); break;
3779
                case 2: gen_op_subl_T0_T1(); break;
3780
                default: return 1;
3781
                }
3782
            }
3783
            break;
3784
        case 17:
3785
            if (!u) { /* VTST */
3786
                switch (size) {
3787
                case 0: gen_op_neon_tst_u8(); break;
3788
                case 1: gen_op_neon_tst_u16(); break;
3789
                case 2: gen_op_neon_tst_u32(); break;
3790
                default: return 1;
3791
                }
3792
            } else { /* VCEQ */
3793
                switch (size) {
3794
                case 0: gen_op_neon_ceq_u8(); break;
3795
                case 1: gen_op_neon_ceq_u16(); break;
3796
                case 2: gen_op_neon_ceq_u32(); break;
3797
                default: return 1;
3798
                }
3799
            }
3800
            break;
3801
        case 18: /* Multiply.  */
3802
            switch (size) {
3803
            case 0: gen_op_neon_mul_u8(); break;
3804
            case 1: gen_op_neon_mul_u16(); break;
3805
            case 2: gen_op_mul_T0_T1(); break;
3806
            default: return 1;
3807
            }
3808
            NEON_GET_REG(T1, rd, pass);
3809
            if (u) { /* VMLS */
3810
                switch (size) {
3811
                case 0: gen_op_neon_rsb_u8(); break;
3812
                case 1: gen_op_neon_rsb_u16(); break;
3813
                case 2: gen_op_rsbl_T0_T1(); break;
3814
                default: return 1;
3815
                }
3816
            } else { /* VMLA */
3817
                gen_neon_add(size);
3818
            }
3819
            break;
3820
        case 19: /* VMUL */
3821
            if (u) { /* polynomial */
3822
                gen_op_neon_mul_p8();
3823
            } else { /* Integer */
3824
                switch (size) {
3825
                case 0: gen_op_neon_mul_u8(); break;
3826
                case 1: gen_op_neon_mul_u16(); break;
3827
                case 2: gen_op_mul_T0_T1(); break;
3828
                default: return 1;
3829
                }
3830
            }
3831
            break;
3832
        case 20: /* VPMAX */
3833
            GEN_NEON_INTEGER_OP(pmax);
3834
            break;
3835
        case 21: /* VPMIN */
3836
            GEN_NEON_INTEGER_OP(pmin);
3837
            break;
3838
        case 22: /* Hultiply high.  */
3839
            if (!u) { /* VQDMULH */
3840
                switch (size) {
3841
                case 1: gen_op_neon_qdmulh_s16(); break;
3842
                case 2: gen_op_neon_qdmulh_s32(); break;
3843
                default: return 1;
3844
                }
3845
            } else { /* VQRDHMUL */
3846
                switch (size) {
3847
                case 1: gen_op_neon_qrdmulh_s16(); break;
3848
                case 2: gen_op_neon_qrdmulh_s32(); break;
3849
                default: return 1;
3850
                }
3851
            }
3852
            break;
3853
        case 23: /* VPADD */
3854
            if (u)
3855
                return 1;
3856
            switch (size) {
3857
            case 0: gen_op_neon_padd_u8(); break;
3858
            case 1: gen_op_neon_padd_u16(); break;
3859
            case 2: gen_op_addl_T0_T1(); break;
3860
            default: return 1;
3861
            }
3862
            break;
3863
        case 26: /* Floating point arithnetic.  */
3864
            switch ((u << 2) | size) {
3865
            case 0: /* VADD */
3866
                gen_op_neon_add_f32();
3867
                break;
3868
            case 2: /* VSUB */
3869
                gen_op_neon_sub_f32();
3870
                break;
3871
            case 4: /* VPADD */
3872
                gen_op_neon_add_f32();
3873
                break;
3874
            case 6: /* VABD */
3875
                gen_op_neon_abd_f32();
3876
                break;
3877
            default:
3878
                return 1;
3879
            }
3880
            break;
3881
        case 27: /* Float multiply.  */
3882
            gen_op_neon_mul_f32();
3883
            if (!u) {
3884
                NEON_GET_REG(T1, rd, pass);
3885
                if (size == 0) {
3886
                    gen_op_neon_add_f32();
3887
                } else {
3888
                    gen_op_neon_rsb_f32();
3889
                }
3890
            }
3891
            break;
3892
        case 28: /* Float compare.  */
3893
            if (!u) {
3894
                gen_op_neon_ceq_f32();
3895
            } else {
3896
                if (size == 0)
3897
                    gen_op_neon_cge_f32();
3898
                else
3899
                    gen_op_neon_cgt_f32();
3900
            }
3901
            break;
3902
        case 29: /* Float compare absolute.  */
3903
            if (!u)
3904
                return 1;
3905
            if (size == 0)
3906
                gen_op_neon_acge_f32();
3907
            else
3908
                gen_op_neon_acgt_f32();
3909
            break;
3910
        case 30: /* Float min/max.  */
3911
            if (size == 0)
3912
                gen_op_neon_max_f32();
3913
            else
3914
                gen_op_neon_min_f32();
3915
            break;
3916
        case 31:
3917
            if (size == 0)
3918
                gen_op_neon_recps_f32();
3919
            else
3920
                gen_op_neon_rsqrts_f32();
3921
            break;
3922
        default:
3923
            abort();
3924
        }
3925
        /* Save the result.  For elementwise operations we can put it
3926
           straight into the destination register.  For pairwise operations
3927
           we have to be careful to avoid clobbering the source operands.  */
3928
        if (pairwise && rd == rm) {
3929
            gen_neon_movl_scratch_T0(pass);
3930
        } else {
3931
            NEON_SET_REG(T0, rd, pass);
3932
        }
3933

    
3934
        } /* for pass */
3935
        if (pairwise && rd == rm) {
3936
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3937
                gen_neon_movl_T0_scratch(pass);
3938
                NEON_SET_REG(T0, rd, pass);
3939
            }
3940
        }
3941
    } else if (insn & (1 << 4)) {
3942
        if ((insn & 0x00380080) != 0) {
3943
            /* Two registers and shift.  */
3944
            op = (insn >> 8) & 0xf;
3945
            if (insn & (1 << 7)) {
3946
                /* 64-bit shift.   */
3947
                size = 3;
3948
            } else {
3949
                size = 2;
3950
                while ((insn & (1 << (size + 19))) == 0)
3951
                    size--;
3952
            }
3953
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3954
            /* To avoid excessive dumplication of ops we implement shift
3955
               by immediate using the variable shift operations.  */
3956
            if (op < 8) {
3957
                /* Shift by immediate:
3958
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
3959
                /* Right shifts are encoded as N - shift, where N is the
3960
                   element size in bits.  */
3961
                if (op <= 4)
3962
                    shift = shift - (1 << (size + 3));
3963
                else
3964
                    shift++;
3965
                if (size == 3) {
3966
                    count = q + 1;
3967
                } else {
3968
                    count = q ? 4: 2;
3969
                }
3970
                switch (size) {
3971
                case 0:
3972
                    imm = (uint8_t) shift;
3973
                    imm |= imm << 8;
3974
                    imm |= imm << 16;
3975
                    break;
3976
                case 1:
3977
                    imm = (uint16_t) shift;
3978
                    imm |= imm << 16;
3979
                    break;
3980
                case 2:
3981
                case 3:
3982
                    imm = shift;
3983
                    break;
3984
                default:
3985
                    abort();
3986
                }
3987

    
3988
                for (pass = 0; pass < count; pass++) {
3989
                    if (size < 3) {
3990
                        /* Operands in T0 and T1.  */
3991
                        gen_op_movl_T1_im(imm);
3992
                        NEON_GET_REG(T0, rm, pass);
3993
                    } else {
3994
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3995
                        gen_op_movl_T0_im(imm);
3996
                        gen_neon_movl_scratch_T0(0);
3997
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3998
                        gen_neon_movl_scratch_T0(1);
3999
                        NEON_GET_REG(T0, rm, pass * 2);
4000
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4001
                    }
4002

    
4003
                    if (gen_neon_shift_im[op][u][size] == NULL)
4004
                        return 1;
4005
                    gen_neon_shift_im[op][u][size]();
4006

    
4007
                    if (op == 1 || op == 3) {
4008
                        /* Accumulate.  */
4009
                        if (size == 3) {
4010
                            gen_neon_movl_scratch_T0(0);
4011
                            gen_neon_movl_scratch_T1(1);
4012
                            NEON_GET_REG(T0, rd, pass * 2);
4013
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4014
                            gen_op_neon_addl_u64();
4015
                        } else {
4016
                            NEON_GET_REG(T1, rd, pass);
4017
                            gen_neon_add(size);
4018
                        }
4019
                    } else if (op == 4 || (op == 5 && u)) {
4020
                        /* Insert */
4021
                        if (size == 3) {
4022
                            cpu_abort(env, "VS[LR]I.64 not implemented");
4023
                        }
4024
                        switch (size) {
4025
                        case 0:
4026
                            if (op == 4)
4027
                                imm = 0xff >> -shift;
4028
                            else
4029
                                imm = (uint8_t)(0xff << shift);
4030
                            imm |= imm << 8;
4031
                            imm |= imm << 16;
4032
                            break;
4033
                        case 1:
4034
                            if (op == 4)
4035
                                imm = 0xffff >> -shift;
4036
                            else
4037
                                imm = (uint16_t)(0xffff << shift);
4038
                            imm |= imm << 16;
4039
                            break;
4040
                        case 2:
4041
                            if (op == 4)
4042
                                imm = 0xffffffffu >> -shift;
4043
                            else
4044
                                imm = 0xffffffffu << shift;
4045
                            break;
4046
                        default:
4047
                            abort();
4048
                        }
4049
                        NEON_GET_REG(T1, rd, pass);
4050
                        gen_op_movl_T2_im(imm);
4051
                        gen_op_neon_bsl();
4052
                    }
4053
                    if (size == 3) {
4054
                        NEON_SET_REG(T0, rd, pass * 2);
4055
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4056
                    } else {
4057
                        NEON_SET_REG(T0, rd, pass);
4058
                    }
4059
                } /* for pass */
4060
            } else if (op < 10) {
4061
                /* Shift by immedaiate and narrow:
4062
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4063
                shift = shift - (1 << (size + 3));
4064
                size++;
4065
                if (size == 3) {
4066
                    count = q + 1;
4067
                } else {
4068
                    count = q ? 4: 2;
4069
                }
4070
                switch (size) {
4071
                case 1:
4072
                    imm = (uint16_t) shift;
4073
                    imm |= imm << 16;
4074
                    break;
4075
                case 2:
4076
                case 3:
4077
                    imm = shift;
4078
                    break;
4079
                default:
4080
                    abort();
4081
                }
4082

    
4083
                /* Processing MSB first means we need to do less shuffling at
4084
                   the end.  */
4085
                for (pass =  count - 1; pass >= 0; pass--) {
4086
                    /* Avoid clobbering the second operand before it has been
4087
                       written.  */
4088
                    n = pass;
4089
                    if (rd == rm)
4090
                        n ^= (count - 1);
4091
                    else
4092
                        n = pass;
4093

    
4094
                    if (size < 3) {
4095
                        /* Operands in T0 and T1.  */
4096
                        gen_op_movl_T1_im(imm);
4097
                        NEON_GET_REG(T0, rm, n);
4098
                    } else {
4099
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4100
                        gen_op_movl_T0_im(imm);
4101
                        gen_neon_movl_scratch_T0(0);
4102
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4103
                        gen_neon_movl_scratch_T0(1);
4104
                        NEON_GET_REG(T0, rm, n * 2);
4105
                        NEON_GET_REG(T0, rm, n * 2 + 1);
4106
                    }
4107

    
4108
                    gen_neon_shift_im_narrow[q][u][size - 1]();
4109

    
4110
                    if (size < 3 && (pass & 1) == 0) {
4111
                        gen_neon_movl_scratch_T0(0);
4112
                    } else {
4113
                        uint32_t offset;
4114

    
4115
                        if (size < 3)
4116
                            gen_neon_movl_T1_scratch(0);
4117

    
4118
                        if (op == 8 && !u) {
4119
                            gen_neon_narrow[size - 1]();
4120
                        } else {
4121
                            if (op == 8)
4122
                                gen_neon_narrow_sats[size - 2]();
4123
                            else
4124
                                gen_neon_narrow_satu[size - 1]();
4125
                        }
4126
                        if (size == 3)
4127
                            offset = neon_reg_offset(rd, n);
4128
                        else
4129
                            offset = neon_reg_offset(rd, n >> 1);
4130
                        gen_op_neon_setreg_T0(offset);
4131
                    }
4132
                } /* for pass */
4133
            } else if (op == 10) {
4134
                /* VSHLL */
4135
                if (q)
4136
                    return 1;
4137
                for (pass = 0; pass < 2; pass++) {
4138
                    /* Avoid clobbering the input operand.  */
4139
                    if (rd == rm)
4140
                        n = 1 - pass;
4141
                    else
4142
                        n = pass;
4143

    
4144
                    NEON_GET_REG(T0, rm, n);
4145
                    GEN_NEON_INTEGER_OP(widen);
4146
                    if (shift != 0) {
4147
                        /* The shift is less than the width of the source
4148
                           type, so in some cases we can just
4149
                           shift the whole register.  */
4150
                        if (size == 1 || (size == 0 && u)) {
4151
                            gen_op_shll_T0_im(shift);
4152
                            gen_op_shll_T1_im(shift);
4153
                        } else {
4154
                            switch (size) {
4155
                            case 0: gen_op_neon_shll_u16(shift); break;
4156
                            case 2: gen_op_neon_shll_u64(shift); break;
4157
                            default: abort();
4158
                            }
4159
                        }
4160
                    }
4161
                    NEON_SET_REG(T0, rd, n * 2);
4162
                    NEON_SET_REG(T1, rd, n * 2 + 1);
4163
                }
4164
            } else if (op == 15 || op == 16) {
4165
                /* VCVT fixed-point.  */
4166
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4167
                    gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4168
                    if (op & 1) {
4169
                        if (u)
4170
                            gen_op_vfp_ultos(shift);
4171
                        else
4172
                            gen_op_vfp_sltos(shift);
4173
                    } else {
4174
                        if (u)
4175
                            gen_op_vfp_touls(shift);
4176
                        else
4177
                            gen_op_vfp_tosls(shift);
4178
                    }
4179
                    gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
4180
                }
4181
            } else {
4182
                return 1;
4183
            }
4184
        } else { /* (insn & 0x00380080) == 0 */
4185
            int invert;
4186

    
4187
            op = (insn >> 8) & 0xf;
4188
            /* One register and immediate.  */
4189
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4190
            invert = (insn & (1 << 5)) != 0;
4191
            switch (op) {
4192
            case 0: case 1:
4193
                /* no-op */
4194
                break;
4195
            case 2: case 3:
4196
                imm <<= 8;
4197
                break;
4198
            case 4: case 5:
4199
                imm <<= 16;
4200
                break;
4201
            case 6: case 7:
4202
                imm <<= 24;
4203
                break;
4204
            case 8: case 9:
4205
                imm |= imm << 16;
4206
                break;
4207
            case 10: case 11:
4208
                imm = (imm << 8) | (imm << 24);
4209
                break;
4210
            case 12:
4211
                imm = (imm < 8) | 0xff;
4212
                break;
4213
            case 13:
4214
                imm = (imm << 16) | 0xffff;
4215
                break;
4216
            case 14:
4217
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4218
                if (invert)
4219
                    imm = ~imm;
4220
                break;
4221
            case 15:
4222
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4223
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4224
                break;
4225
            }
4226
            if (invert)
4227
                imm = ~imm;
4228

    
4229
            if (op != 14 || !invert)
4230
                gen_op_movl_T1_im(imm);
4231

    
4232
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4233
                if (op & 1 && op < 12) {
4234
                    NEON_GET_REG(T0, rd, pass);
4235
                    if (invert) {
4236
                        /* The immediate value has already been inverted, so
4237
                           BIC becomes AND.  */
4238
                        gen_op_andl_T0_T1();
4239
                    } else {
4240
                        gen_op_orl_T0_T1();
4241
                    }
4242
                    NEON_SET_REG(T0, rd, pass);
4243
                } else {
4244
                    if (op == 14 && invert) {
4245
                        uint32_t tmp;
4246
                        tmp = 0;
4247
                        for (n = 0; n < 4; n++) {
4248
                            if (imm & (1 << (n + (pass & 1) * 4)))
4249
                                tmp |= 0xff << (n * 8);
4250
                        }
4251
                        gen_op_movl_T1_im(tmp);
4252
                    }
4253
                    /* VMOV, VMVN.  */
4254
                    NEON_SET_REG(T1, rd, pass);
4255
                }
4256
            }
4257
        }
4258
    } else { /* (insn & 0x00800010 == 0x00800010) */
4259
        if (size != 3) {
4260
            op = (insn >> 8) & 0xf;
4261
            if ((insn & (1 << 6)) == 0) {
4262
                /* Three registers of different lengths.  */
4263
                int src1_wide;
4264
                int src2_wide;
4265
                int prewiden;
4266
                /* prewiden, src1_wide, src2_wide */
4267
                static const int neon_3reg_wide[16][3] = {
4268
                    {1, 0, 0}, /* VADDL */
4269
                    {1, 1, 0}, /* VADDW */
4270
                    {1, 0, 0}, /* VSUBL */
4271
                    {1, 1, 0}, /* VSUBW */
4272
                    {0, 1, 1}, /* VADDHN */
4273
                    {0, 0, 0}, /* VABAL */
4274
                    {0, 1, 1}, /* VSUBHN */
4275
                    {0, 0, 0}, /* VABDL */
4276
                    {0, 0, 0}, /* VMLAL */
4277
                    {0, 0, 0}, /* VQDMLAL */
4278
                    {0, 0, 0}, /* VMLSL */
4279
                    {0, 0, 0}, /* VQDMLSL */
4280
                    {0, 0, 0}, /* Integer VMULL */
4281
                    {0, 0, 0}, /* VQDMULL */
4282
                    {0, 0, 0}  /* Polynomial VMULL */
4283
                };
4284

    
4285
                prewiden = neon_3reg_wide[op][0];
4286
                src1_wide = neon_3reg_wide[op][1];
4287
                src2_wide = neon_3reg_wide[op][2];
4288

    
4289
                /* Avoid overlapping operands.  Wide source operands are
4290
                   always aligned so will never overlap with wide
4291
                   destinations in problematic ways.  */
4292
                if (rd == rm) {
4293
                    NEON_GET_REG(T2, rm, 1);
4294
                } else if (rd == rn) {
4295
                    NEON_GET_REG(T2, rn, 1);
4296
                }
4297
                for (pass = 0; pass < 2; pass++) {
4298
                    /* Load the second operand into env->vfp.scratch.
4299
                       Also widen narrow operands.  */
4300
                    if (pass == 1 && rd == rm) {
4301
                        if (prewiden) {
4302
                            gen_op_movl_T0_T2();
4303
                        } else {
4304
                            gen_op_movl_T1_T2();
4305
                        }
4306
                    } else {
4307
                        if (src2_wide) {
4308
                            NEON_GET_REG(T0, rm, pass * 2);
4309
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
4310
                        } else {
4311
                            if (prewiden) {
4312
                                NEON_GET_REG(T0, rm, pass);
4313
                            } else {
4314
                                NEON_GET_REG(T1, rm, pass);
4315
                            }
4316
                        }
4317
                    }
4318
                    if (prewiden && !src2_wide) {
4319
                        GEN_NEON_INTEGER_OP(widen);
4320
                    }
4321
                    if (prewiden || src2_wide) {
4322
                        gen_neon_movl_scratch_T0(0);
4323
                        gen_neon_movl_scratch_T1(1);
4324
                    }
4325

    
4326
                    /* Load the first operand.  */
4327
                    if (pass == 1 && rd == rn) {
4328
                        gen_op_movl_T0_T2();
4329
                    } else {
4330
                        if (src1_wide) {
4331
                            NEON_GET_REG(T0, rn, pass * 2);
4332
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
4333
                        } else {
4334
                            NEON_GET_REG(T0, rn, pass);
4335
                        }
4336
                    }
4337
                    if (prewiden && !src1_wide) {
4338
                        GEN_NEON_INTEGER_OP(widen);
4339
                    }
4340
                    switch (op) {
4341
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4342
                        switch (size) {
4343
                        case 0: gen_op_neon_addl_u16(); break;
4344
                        case 1: gen_op_neon_addl_u32(); break;
4345
                        case 2: gen_op_neon_addl_u64(); break;
4346
                        default: abort();
4347
                        }
4348
                        break;
4349
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4350
                        switch (size) {
4351
                        case 0: gen_op_neon_subl_u16(); break;
4352
                        case 1: gen_op_neon_subl_u32(); break;
4353
                        case 2: gen_op_neon_subl_u64(); break;
4354
                        default: abort();
4355
                        }
4356
                        break;
4357
                    case 5: case 7: /* VABAL, VABDL */
4358
                        switch ((size << 1) | u) {
4359
                        case 0: gen_op_neon_abdl_s16(); break;
4360
                        case 1: gen_op_neon_abdl_u16(); break;
4361
                        case 2: gen_op_neon_abdl_s32(); break;
4362
                        case 3: gen_op_neon_abdl_u32(); break;
4363
                        case 4: gen_op_neon_abdl_s64(); break;
4364
                        case 5: gen_op_neon_abdl_u64(); break;
4365
                        default: abort();
4366
                        }
4367
                        break;
4368
                    case 8: case 9: case 10: case 11: case 12: case 13:
4369
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4370
                        switch ((size << 1) | u) {
4371
                        case 0: gen_op_neon_mull_s8(); break;
4372
                        case 1: gen_op_neon_mull_u8(); break;
4373
                        case 2: gen_op_neon_mull_s16(); break;
4374
                        case 3: gen_op_neon_mull_u16(); break;
4375
                        case 4: gen_op_imull_T0_T1(); break;
4376
                        case 5: gen_op_mull_T0_T1(); break;
4377
                        default: abort();
4378
                        }
4379
                        break;
4380
                    case 14: /* Polynomial VMULL */
4381
                        cpu_abort(env, "Polynomial VMULL not implemented");
4382

    
4383
                    default: /* 15 is RESERVED.  */
4384
                        return 1;
4385
                    }
4386
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4387
                        /* Accumulate.  */
4388
                        if (op == 10 || op == 11) {
4389
                            switch (size) {
4390
                            case 0: gen_op_neon_negl_u16(); break;
4391
                            case 1: gen_op_neon_negl_u32(); break;
4392
                            case 2: gen_op_neon_negl_u64(); break;
4393
                            default: abort();
4394
                            }
4395
                        }
4396

    
4397
                        gen_neon_movl_scratch_T0(0);
4398
                        gen_neon_movl_scratch_T1(1);
4399

    
4400
                        if (op != 13) {
4401
                            NEON_GET_REG(T0, rd, pass * 2);
4402
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4403
                        }
4404

    
4405
                        switch (op) {
4406
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4407
                            switch (size) {
4408
                            case 0: gen_op_neon_addl_u16(); break;
4409
                            case 1: gen_op_neon_addl_u32(); break;
4410
                            case 2: gen_op_neon_addl_u64(); break;
4411
                            default: abort();
4412
                            }
4413
                            break;
4414
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4415
                            switch (size) {
4416
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4417
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4418
                            default: abort();
4419
                            }
4420
                            /* Fall through.  */
4421
                        case 13: /* VQDMULL */
4422
                            switch (size) {
4423
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4424
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4425
                            default: abort();
4426
                            }
4427
                            break;
4428
                        default:
4429
                            abort();
4430
                        }
4431
                        NEON_SET_REG(T0, rd, pass * 2);
4432
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4433
                    } else if (op == 4 || op == 6) {
4434
                        /* Narrowing operation.  */
4435
                        if (u) {
4436
                            switch (size) {
4437
                            case 0: gen_op_neon_narrow_high_u8(); break;
4438
                            case 1: gen_op_neon_narrow_high_u16(); break;
4439
                            case 2: gen_op_movl_T0_T1(); break;
4440
                            default: abort();
4441
                            }
4442
                        } else {
4443
                            switch (size) {
4444
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4445
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4446
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4447
                            default: abort();
4448
                            }
4449
                        }
4450
                        NEON_SET_REG(T0, rd, pass);
4451
                    } else {
4452
                        /* Write back the result.  */
4453
                        NEON_SET_REG(T0, rd, pass * 2);
4454
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4455
                    }
4456
                }
4457
            } else {
4458
                /* Two registers and a scalar.  */
4459
                switch (op) {
4460
                case 0: /* Integer VMLA scalar */
4461
                case 1: /* Float VMLA scalar */
4462
                case 4: /* Integer VMLS scalar */
4463
                case 5: /* Floating point VMLS scalar */
4464
                case 8: /* Integer VMUL scalar */
4465
                case 9: /* Floating point VMUL scalar */
4466
                case 12: /* VQDMULH scalar */
4467
                case 13: /* VQRDMULH scalar */
4468
                    gen_neon_get_scalar(size, rm);
4469
                    gen_op_movl_T2_T0();
4470
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4471
                        if (pass != 0)
4472
                            gen_op_movl_T0_T2();
4473
                        NEON_GET_REG(T1, rn, pass);
4474
                        if (op == 12) {
4475
                            if (size == 1) {
4476
                                gen_op_neon_qdmulh_s16();
4477
                            } else {
4478
                                gen_op_neon_qdmulh_s32();
4479
                            }
4480
                        } else if (op == 13) {
4481
                            if (size == 1) {
4482
                                gen_op_neon_qrdmulh_s16();
4483
                            } else {
4484
                                gen_op_neon_qrdmulh_s32();
4485
                            }
4486
                        } else if (op & 1) {
4487
                            gen_op_neon_mul_f32();
4488
                        } else {
4489
                            switch (size) {
4490
                            case 0: gen_op_neon_mul_u8(); break;
4491
                            case 1: gen_op_neon_mul_u16(); break;
4492
                            case 2: gen_op_mul_T0_T1(); break;
4493
                            default: return 1;
4494
                            }
4495
                        }
4496
                        if (op < 8) {
4497
                            /* Accumulate.  */
4498
                            NEON_GET_REG(T1, rd, pass);
4499
                            switch (op) {
4500
                            case 0:
4501
                                gen_neon_add(size);
4502
                                break;
4503
                            case 1:
4504
                                gen_op_neon_add_f32();
4505
                                break;
4506
                            case 4:
4507
                                switch (size) {
4508
                                case 0: gen_op_neon_rsb_u8(); break;
4509
                                case 1: gen_op_neon_rsb_u16(); break;
4510
                                case 2: gen_op_rsbl_T0_T1(); break;
4511
                                default: return 1;
4512
                                }
4513
                                break;
4514
                            case 5:
4515
                                gen_op_neon_rsb_f32();
4516
                                break;
4517
                            default:
4518
                                abort();
4519
                            }
4520
                        }
4521
                        NEON_SET_REG(T0, rd, pass);
4522
                    }
4523
                    break;
4524
                case 2: /* VMLAL sclar */
4525
                case 3: /* VQDMLAL scalar */
4526
                case 6: /* VMLSL scalar */
4527
                case 7: /* VQDMLSL scalar */
4528
                case 10: /* VMULL scalar */
4529
                case 11: /* VQDMULL scalar */
4530
                    if (rd == rn) {
4531
                        /* Save overlapping operands before they are
4532
                           clobbered.  */
4533
                        NEON_GET_REG(T0, rn, 1);
4534
                        gen_neon_movl_scratch_T0(2);
4535
                    }
4536
                    gen_neon_get_scalar(size, rm);
4537
                    gen_op_movl_T2_T0();
4538
                    for (pass = 0; pass < 2; pass++) {
4539
                        if (pass != 0) {
4540
                            gen_op_movl_T0_T2();
4541
                        }
4542
                        if (pass != 0 && rd == rn) {
4543
                            gen_neon_movl_T1_scratch(2);
4544
                        } else {
4545
                            NEON_GET_REG(T1, rn, pass);
4546
                        }
4547
                        switch ((size << 1) | u) {
4548
                        case 0: gen_op_neon_mull_s8(); break;
4549
                        case 1: gen_op_neon_mull_u8(); break;
4550
                        case 2: gen_op_neon_mull_s16(); break;
4551
                        case 3: gen_op_neon_mull_u16(); break;
4552
                        case 4: gen_op_imull_T0_T1(); break;
4553
                        case 5: gen_op_mull_T0_T1(); break;
4554
                        default: abort();
4555
                        }
4556
                        if (op == 6 || op == 7) {
4557
                            switch (size) {
4558
                            case 0: gen_op_neon_negl_u16(); break;
4559
                            case 1: gen_op_neon_negl_u32(); break;
4560
                            case 2: gen_op_neon_negl_u64(); break;
4561
                            default: abort();
4562
                            }
4563
                        }
4564
                        gen_neon_movl_scratch_T0(0);
4565
                        gen_neon_movl_scratch_T1(1);
4566
                        NEON_GET_REG(T0, rd, pass * 2);
4567
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4568
                        switch (op) {
4569
                        case 2: case 6:
4570
                            switch (size) {
4571
                            case 0: gen_op_neon_addl_u16(); break;
4572
                            case 1: gen_op_neon_addl_u32(); break;
4573
                            case 2: gen_op_neon_addl_u64(); break;
4574
                            default: abort();
4575
                            }
4576
                            break;
4577
                        case 3: case 7:
4578
                            switch (size) {
4579
                            case 1:
4580
                                gen_op_neon_addl_saturate_s32();
4581
                                gen_op_neon_addl_saturate_s32();
4582
                                break;
4583
                            case 2:
4584
                                gen_op_neon_addl_saturate_s64();
4585
                                gen_op_neon_addl_saturate_s64();
4586
                                break;
4587
                            default: abort();
4588
                            }
4589
                            break;
4590
                        case 10:
4591
                            /* no-op */
4592
                            break;
4593
                        case 11:
4594
                            switch (size) {
4595
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4596
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4597
                            default: abort();
4598
                            }
4599
                            break;
4600
                        default:
4601
                            abort();
4602
                        }
4603
                        NEON_SET_REG(T0, rd, pass * 2);
4604
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4605
                    }
4606
                    break;
4607
                default: /* 14 and 15 are RESERVED */
4608
                    return 1;
4609
                }
4610
            }
4611
        } else { /* size == 3 */
4612
            if (!u) {
4613
                /* Extract.  */
4614
                int reg;
4615
                imm = (insn >> 8) & 0xf;
4616
                reg = rn;
4617
                count = q ? 4 : 2;
4618
                n = imm >> 2;
4619
                NEON_GET_REG(T0, reg, n);
4620
                for (pass = 0; pass < count; pass++) {
4621
                    n++;
4622
                    if (n > count) {
4623
                        reg = rm;
4624
                        n -= count;
4625
                    }
4626
                    if (imm & 3) {
4627
                        NEON_GET_REG(T1, reg, n);
4628
                        gen_op_neon_extract((insn << 3) & 0x1f);
4629
                    }
4630
                    /* ??? This is broken if rd and rm overlap */
4631
                    NEON_SET_REG(T0, rd, pass);
4632
                    if (imm & 3) {
4633
                        gen_op_movl_T0_T1();
4634
                    } else {
4635
                        NEON_GET_REG(T0, reg, n);
4636
                    }
4637
                }
4638
            } else if ((insn & (1 << 11)) == 0) {
4639
                /* Two register misc.  */
4640
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4641
                size = (insn >> 18) & 3;
4642
                switch (op) {
4643
                case 0: /* VREV64 */
4644
                    if (size == 3)
4645
                        return 1;
4646
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4647
                        NEON_GET_REG(T0, rm, pass * 2);
4648
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4649
                        switch (size) {
4650
                        case 0: gen_op_rev_T0(); break;
4651
                        case 1: gen_swap_half(cpu_T[0]); break;
4652
                        case 2: /* no-op */ break;
4653
                        default: abort();
4654
                        }
4655
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4656
                        if (size == 2) {
4657
                            NEON_SET_REG(T1, rd, pass * 2);
4658
                        } else {
4659
                            gen_op_movl_T0_T1();
4660
                            switch (size) {
4661
                            case 0: gen_op_rev_T0(); break;
4662
                            case 1: gen_swap_half(cpu_T[0]); break;
4663
                            default: abort();
4664
                            }
4665
                            NEON_SET_REG(T0, rd, pass * 2);
4666
                        }
4667
                    }
4668
                    break;
4669
                case 4: case 5: /* VPADDL */
4670
                case 12: case 13: /* VPADAL */
4671
                    if (size < 2)
4672
                        goto elementwise;
4673
                    if (size == 3)
4674
                        return 1;
4675
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4676
                        NEON_GET_REG(T0, rm, pass * 2);
4677
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4678
                        if (op & 1)
4679
                            gen_op_neon_paddl_u32();
4680
                        else
4681
                            gen_op_neon_paddl_s32();
4682
                        if (op >= 12) {
4683
                            /* Accumulate.  */
4684
                            gen_neon_movl_scratch_T0(0);
4685
                            gen_neon_movl_scratch_T1(1);
4686

    
4687
                            NEON_GET_REG(T0, rd, pass * 2);
4688
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4689
                            gen_op_neon_addl_u64();
4690
                        }
4691
                        NEON_SET_REG(T0, rd, pass * 2);
4692
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4693
                    }
4694
                    break;
4695
                case 33: /* VTRN */
4696
                    if (size == 2) {
4697
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4698
                            NEON_GET_REG(T0, rm, n);
4699
                            NEON_GET_REG(T1, rd, n + 1);
4700
                            NEON_SET_REG(T1, rm, n);
4701
                            NEON_SET_REG(T0, rd, n + 1);
4702
                        }
4703
                    } else {
4704
                        goto elementwise;
4705
                    }
4706
                    break;
4707
                case 34: /* VUZP */
4708
                    /* Reg  Before       After
4709
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4710
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4711
                     */
4712
                    if (size == 3)
4713
                        return 1;
4714