Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 66230e0d

History | View | Annotate | Download (294.7 kB)

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

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

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

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

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

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

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

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

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

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

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

    
87
/* initialize TCG globals.  */
88
void arm_translate_init(void)
89
{
90
    cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
91

    
92
    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG1, "T0");
93
    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I32, TCG_AREG2, "T1");
94
}
95

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

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

    
109
    if (GET_TCGV(temps[num_temps]))
110
      return temps[num_temps++];
111

    
112
    tmp = tcg_temp_new(TCG_TYPE_I32);
113
    temps[num_temps++] = tmp;
114
    return tmp;
115
}
116

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

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

    
136
static inline TCGv load_cpu_offset(int offset)
137
{
138
    TCGv tmp = new_tmp();
139
    tcg_gen_ld_i32(tmp, cpu_env, offset);
140
    return tmp;
141
}
142

    
143
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
144

    
145
static inline void store_cpu_offset(TCGv var, int offset)
146
{
147
    tcg_gen_st_i32(var, cpu_env, offset);
148
    dead_tmp(var);
149
}
150

    
151
#define store_cpu_field(var, name) \
152
    store_cpu_offset(var, offsetof(CPUState, name))
153

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

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

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

    
190

    
191
/* Basic operations.  */
192
#define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
193
#define gen_op_movl_T1_T0() tcg_gen_mov_i32(cpu_T[1], 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

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

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

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

    
217
#define gen_op_shll_T0_im(im) tcg_gen_shli_i32(cpu_T[0], cpu_T[0], im)
218
#define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
219
#define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
220
#define gen_op_sarl_T1_im(im) tcg_gen_sari_i32(cpu_T[1], cpu_T[1], im)
221
#define gen_op_rorl_T1_im(im) tcg_gen_rori_i32(cpu_T[1], cpu_T[1], im)
222

    
223
/* Value extensions.  */
224
#define gen_uxtb(var) tcg_gen_andi_i32(var, var, 0xff)
225
#define gen_uxth(var) tcg_gen_andi_i32(var, var, 0xffff)
226
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
227
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
228

    
229
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
230
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
231

    
232
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
233

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

    
238
static void gen_exception(int excp)
239
{
240
    TCGv tmp = new_tmp();
241
    tcg_gen_movi_i32(tmp, excp);
242
    gen_helper_exception(tmp);
243
    dead_tmp(tmp);
244
}
245

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

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

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

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

    
293
/* Signed bitfield extract.  */
294
static void gen_sbfx(TCGv var, int shift, int width)
295
{
296
    uint32_t signbit;
297

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

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

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

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

    
332
    tcg_gen_extu_i32_i64(tmp1, a);
333
    dead_tmp(a);
334
    tcg_gen_extu_i32_i64(tmp2, b);
335
    dead_tmp(b);
336
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337
    return tmp1;
338
}
339

    
340
static TCGv gen_muls_i64_i32(TCGv a, TCGv b)
341
{
342
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
343
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
344

    
345
    tcg_gen_ext_i32_i64(tmp1, a);
346
    dead_tmp(a);
347
    tcg_gen_ext_i32_i64(tmp2, b);
348
    dead_tmp(b);
349
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
350
    return tmp1;
351
}
352

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

    
359
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
360
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
361
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
362
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
363
    tcg_gen_shri_i64(tmp1, tmp1, 32);
364
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
365
}
366

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

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

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

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

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

    
412
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
413

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

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

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

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

    
451
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
452
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
453

    
454
/* FIXME:  Implement this natively.  */
455
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
456
{
457
    tcg_gen_xori_i32(t0, t1, ~0);
458
}
459

    
460
/* FIXME:  Implement this natively.  */
461
static inline void tcg_gen_neg_i64(TCGv dest, TCGv src)
462
{
463
    tcg_gen_sub_i64(dest, tcg_const_i64(0), src);
464
}
465

    
466
/* T0 &= ~T1.  Clobbers T1.  */
467
/* FIXME: Implement bic natively.  */
468
static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
469
{
470
    TCGv tmp = new_tmp();
471
    tcg_gen_not_i32(tmp, t1);
472
    tcg_gen_and_i32(dest, t0, tmp);
473
    dead_tmp(tmp);
474
}
475
static inline void gen_op_bicl_T0_T1(void)
476
{
477
    gen_op_notl_T1();
478
    gen_op_andl_T0_T1();
479
}
480

    
481
/* FIXME:  Implement this natively.  */
482
#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
483

    
484
/* FIXME:  Implement this natively.  */
485
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
486
{
487
    TCGv tmp;
488

    
489
    if (i == 0)
490
        return;
491

    
492
    tmp = new_tmp();
493
    tcg_gen_shri_i32(tmp, t1, i);
494
    tcg_gen_shli_i32(t1, t1, 32 - i);
495
    tcg_gen_or_i32(t0, t1, tmp);
496
    dead_tmp(tmp);
497
}
498

    
499
static void shifter_out_im(TCGv var, int shift)
500
{
501
    TCGv tmp = new_tmp();
502
    if (shift == 0) {
503
        tcg_gen_andi_i32(tmp, var, 1);
504
    } else {
505
        tcg_gen_shri_i32(tmp, var, shift);
506
        if (shift != 31);
507
            tcg_gen_andi_i32(tmp, tmp, 1);
508
    }
509
    gen_set_CF(tmp);
510
    dead_tmp(tmp);
511
}
512

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

    
563
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
564
                                     TCGv shift, int flags)
565
{
566
    if (flags) {
567
        switch (shiftop) {
568
        case 0: gen_helper_shl_cc(var, var, shift); break;
569
        case 1: gen_helper_shr_cc(var, var, shift); break;
570
        case 2: gen_helper_sar_cc(var, var, shift); break;
571
        case 3: gen_helper_ror_cc(var, var, shift); break;
572
        }
573
    } else {
574
        switch (shiftop) {
575
        case 0: gen_helper_shl(var, var, shift); break;
576
        case 1: gen_helper_shr(var, var, shift); break;
577
        case 2: gen_helper_sar(var, var, shift); break;
578
        case 3: gen_helper_ror(var, var, shift); break;
579
        }
580
    }
581
    dead_tmp(shift);
582
}
583

    
584
#define PAS_OP(pfx) \
585
    switch (op2) {  \
586
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
587
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
588
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
589
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
590
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
591
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
592
    }
593
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
594
{
595
    TCGv tmp;
596

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

    
628
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
629
#define PAS_OP(pfx) \
630
    switch (op2) {  \
631
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
632
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
633
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
634
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
635
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
636
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
637
    }
638
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
639
{
640
    TCGv tmp;
641

    
642
    switch (op1) {
643
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
644
    case 0:
645
        tmp = tcg_temp_new(TCG_TYPE_PTR);
646
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
647
        PAS_OP(s)
648
        break;
649
    case 4:
650
        tmp = tcg_temp_new(TCG_TYPE_PTR);
651
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
652
        PAS_OP(u)
653
        break;
654
#undef gen_pas_helper
655
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
656
    case 1:
657
        PAS_OP(q);
658
        break;
659
    case 2:
660
        PAS_OP(sh);
661
        break;
662
    case 5:
663
        PAS_OP(uq);
664
        break;
665
    case 6:
666
        PAS_OP(uh);
667
        break;
668
#undef gen_pas_helper
669
    }
670
}
671
#undef PAS_OP
672

    
673
static void gen_test_cc(int cc, int label)
674
{
675
    TCGv tmp;
676
    TCGv tmp2;
677
    TCGv zero;
678
    int inv;
679

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

    
773
const uint8_t table_logic_cc[16] = {
774
    1, /* and */
775
    1, /* xor */
776
    0, /* sub */
777
    0, /* rsb */
778
    0, /* add */
779
    0, /* adc */
780
    0, /* sbc */
781
    0, /* rsc */
782
    1, /* andl */
783
    1, /* xorl */
784
    0, /* cmp */
785
    0, /* cmn */
786
    1, /* orr */
787
    1, /* mov */
788
    1, /* bic */
789
    1, /* mvn */
790
};
791

    
792
/* Set PC and Thumb state from an immediate address.  */
793
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
794
{
795
    TCGv tmp;
796

    
797
    s->is_jmp = DISAS_UPDATE;
798
    tmp = new_tmp();
799
    if (s->thumb != (addr & 1)) {
800
        tcg_gen_movi_i32(tmp, addr & 1);
801
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
802
    }
803
    tcg_gen_movi_i32(tmp, addr & ~1);
804
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
805
    dead_tmp(tmp);
806
}
807

    
808
/* Set PC and Thumb state from var.  var is marked as dead.  */
809
static inline void gen_bx(DisasContext *s, TCGv var)
810
{
811
    TCGv tmp;
812

    
813
    s->is_jmp = DISAS_UPDATE;
814
    tmp = new_tmp();
815
    tcg_gen_andi_i32(tmp, var, 1);
816
    store_cpu_field(tmp, thumb);
817
    tcg_gen_andi_i32(var, var, ~1);
818
    store_cpu_field(var, regs[15]);
819
}
820

    
821
/* TODO: This should be removed.  Use gen_bx instead.  */
822
static inline void gen_bx_T0(DisasContext *s)
823
{
824
    TCGv tmp = new_tmp();
825
    tcg_gen_mov_i32(tmp, cpu_T[0]);
826
    gen_bx(s, tmp);
827
}
828

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

    
886
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
887
{
888
    load_reg_var(s, cpu_T[0], reg);
889
}
890

    
891
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
892
{
893
    load_reg_var(s, cpu_T[1], reg);
894
}
895

    
896
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
897
{
898
    load_reg_var(s, cpu_T[2], reg);
899
}
900

    
901
static inline void gen_set_pc_im(uint32_t val)
902
{
903
    TCGv tmp = new_tmp();
904
    tcg_gen_movi_i32(tmp, val);
905
    store_cpu_field(tmp, regs[15]);
906
}
907

    
908
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
909
{
910
    TCGv tmp;
911
    if (reg == 15) {
912
        tmp = new_tmp();
913
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
914
    } else {
915
        tmp = cpu_T[t];
916
    }
917
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
918
    if (reg == 15) {
919
        dead_tmp(tmp);
920
        s->is_jmp = DISAS_JUMP;
921
    }
922
}
923

    
924
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
925
{
926
    gen_movl_reg_TN(s, reg, 0);
927
}
928

    
929
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
930
{
931
    gen_movl_reg_TN(s, reg, 1);
932
}
933

    
934
/* Force a TB lookup after an instruction that changes the CPU state.  */
935
static inline void gen_lookup_tb(DisasContext *s)
936
{
937
    gen_op_movl_T0_im(s->pc);
938
    gen_movl_reg_T0(s, 15);
939
    s->is_jmp = DISAS_UPDATE;
940
}
941

    
942
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
943
                                       TCGv var)
944
{
945
    int val, rm, shift, shiftop;
946
    TCGv offset;
947

    
948
    if (!(insn & (1 << 25))) {
949
        /* immediate */
950
        val = insn & 0xfff;
951
        if (!(insn & (1 << 23)))
952
            val = -val;
953
        if (val != 0)
954
            tcg_gen_addi_i32(var, var, val);
955
    } else {
956
        /* shift/register */
957
        rm = (insn) & 0xf;
958
        shift = (insn >> 7) & 0x1f;
959
        shiftop = (insn >> 5) & 3;
960
        offset = load_reg(s, rm);
961
        gen_arm_shift_im(offset, shiftop, shift, 0);
962
        if (!(insn & (1 << 23)))
963
            tcg_gen_sub_i32(var, var, offset);
964
        else
965
            tcg_gen_add_i32(var, var, offset);
966
        dead_tmp(offset);
967
    }
968
}
969

    
970
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
971
                                        int extra, TCGv var)
972
{
973
    int val, rm;
974
    TCGv offset;
975

    
976
    if (insn & (1 << 22)) {
977
        /* immediate */
978
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
979
        if (!(insn & (1 << 23)))
980
            val = -val;
981
        val += extra;
982
        if (val != 0)
983
            tcg_gen_addi_i32(var, var, val);
984
    } else {
985
        /* register */
986
        if (extra)
987
            tcg_gen_addi_i32(var, var, extra);
988
        rm = (insn) & 0xf;
989
        offset = load_reg(s, rm);
990
        if (!(insn & (1 << 23)))
991
            tcg_gen_sub_i32(var, var, offset);
992
        else
993
            tcg_gen_add_i32(var, var, offset);
994
        dead_tmp(offset);
995
    }
996
}
997

    
998
#define VFP_OP2(name)                                                 \
999
static inline void gen_vfp_##name(int dp)                             \
1000
{                                                                     \
1001
    if (dp)                                                           \
1002
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
1003
    else                                                              \
1004
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1005
}
1006

    
1007
#define VFP_OP1(name)                               \
1008
static inline void gen_vfp_##name(int dp, int arg)  \
1009
{                                                   \
1010
    if (dp)                                         \
1011
        gen_op_vfp_##name##d(arg);                  \
1012
    else                                            \
1013
        gen_op_vfp_##name##s(arg);                  \
1014
}
1015

    
1016
VFP_OP2(add)
1017
VFP_OP2(sub)
1018
VFP_OP2(mul)
1019
VFP_OP2(div)
1020

    
1021
#undef VFP_OP2
1022

    
1023
static inline void gen_vfp_abs(int dp)
1024
{
1025
    if (dp)
1026
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1027
    else
1028
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1029
}
1030

    
1031
static inline void gen_vfp_neg(int dp)
1032
{
1033
    if (dp)
1034
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1035
    else
1036
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1037
}
1038

    
1039
static inline void gen_vfp_sqrt(int dp)
1040
{
1041
    if (dp)
1042
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1043
    else
1044
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1045
}
1046

    
1047
static inline void gen_vfp_cmp(int dp)
1048
{
1049
    if (dp)
1050
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1051
    else
1052
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1053
}
1054

    
1055
static inline void gen_vfp_cmpe(int dp)
1056
{
1057
    if (dp)
1058
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1059
    else
1060
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1061
}
1062

    
1063
static inline void gen_vfp_F1_ld0(int dp)
1064
{
1065
    if (dp)
1066
        tcg_gen_movi_i64(cpu_F1d, 0);
1067
    else
1068
        tcg_gen_movi_i32(cpu_F1s, 0);
1069
}
1070

    
1071
static inline void gen_vfp_uito(int dp)
1072
{
1073
    if (dp)
1074
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1075
    else
1076
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1077
}
1078

    
1079
static inline void gen_vfp_sito(int dp)
1080
{
1081
    if (dp)
1082
        gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
1083
    else
1084
        gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
1085
}
1086

    
1087
static inline void gen_vfp_toui(int dp)
1088
{
1089
    if (dp)
1090
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1091
    else
1092
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1093
}
1094

    
1095
static inline void gen_vfp_touiz(int dp)
1096
{
1097
    if (dp)
1098
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1099
    else
1100
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1101
}
1102

    
1103
static inline void gen_vfp_tosi(int dp)
1104
{
1105
    if (dp)
1106
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1107
    else
1108
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1109
}
1110

    
1111
static inline void gen_vfp_tosiz(int dp)
1112
{
1113
    if (dp)
1114
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1115
    else
1116
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1117
}
1118

    
1119
#define VFP_GEN_FIX(name) \
1120
static inline void gen_vfp_##name(int dp, int shift) \
1121
{ \
1122
    if (dp) \
1123
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1124
    else \
1125
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1126
}
1127
VFP_GEN_FIX(tosh)
1128
VFP_GEN_FIX(tosl)
1129
VFP_GEN_FIX(touh)
1130
VFP_GEN_FIX(toul)
1131
VFP_GEN_FIX(shto)
1132
VFP_GEN_FIX(slto)
1133
VFP_GEN_FIX(uhto)
1134
VFP_GEN_FIX(ulto)
1135
#undef VFP_GEN_FIX
1136

    
1137
static inline void gen_vfp_ld(DisasContext *s, int dp)
1138
{
1139
    if (dp)
1140
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1141
    else
1142
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1143
}
1144

    
1145
static inline void gen_vfp_st(DisasContext *s, int dp)
1146
{
1147
    if (dp)
1148
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1149
    else
1150
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1151
}
1152

    
1153
static inline long
1154
vfp_reg_offset (int dp, int reg)
1155
{
1156
    if (dp)
1157
        return offsetof(CPUARMState, vfp.regs[reg]);
1158
    else if (reg & 1) {
1159
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1160
          + offsetof(CPU_DoubleU, l.upper);
1161
    } else {
1162
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1163
          + offsetof(CPU_DoubleU, l.lower);
1164
    }
1165
}
1166

    
1167
/* Return the offset of a 32-bit piece of a NEON register.
1168
   zero is the least significant end of the register.  */
1169
static inline long
1170
neon_reg_offset (int reg, int n)
1171
{
1172
    int sreg;
1173
    sreg = reg * 2 + n;
1174
    return vfp_reg_offset(0, sreg);
1175
}
1176

    
1177
/* FIXME: Remove these.  */
1178
#define neon_T0 cpu_T[0]
1179
#define neon_T1 cpu_T[1]
1180
#define NEON_GET_REG(T, reg, n) \
1181
  tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1182
#define NEON_SET_REG(T, reg, n) \
1183
  tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1184

    
1185
static TCGv neon_load_reg(int reg, int pass)
1186
{
1187
    TCGv tmp = new_tmp();
1188
    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1189
    return tmp;
1190
}
1191

    
1192
static void neon_store_reg(int reg, int pass, TCGv var)
1193
{
1194
    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1195
    dead_tmp(var);
1196
}
1197

    
1198
static inline void neon_load_reg64(TCGv var, int reg)
1199
{
1200
    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1201
}
1202

    
1203
static inline void neon_store_reg64(TCGv var, int reg)
1204
{
1205
    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1206
}
1207

    
1208
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1209
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1210
#define tcg_gen_st_f32 tcg_gen_st_i32
1211
#define tcg_gen_st_f64 tcg_gen_st_i64
1212

    
1213
static inline void gen_mov_F0_vreg(int dp, int reg)
1214
{
1215
    if (dp)
1216
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1217
    else
1218
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1219
}
1220

    
1221
static inline void gen_mov_F1_vreg(int dp, int reg)
1222
{
1223
    if (dp)
1224
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1225
    else
1226
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1227
}
1228

    
1229
static inline void gen_mov_vreg_F0(int dp, int reg)
1230
{
1231
    if (dp)
1232
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1233
    else
1234
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1235
}
1236

    
1237
#define ARM_CP_RW_BIT        (1 << 20)
1238

    
1239
static inline void iwmmxt_load_reg(TCGv var, int reg)
1240
{
1241
    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1242
}
1243

    
1244
static inline void iwmmxt_store_reg(TCGv var, int reg)
1245
{
1246
    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1247
}
1248

    
1249
static inline void gen_op_iwmmxt_movl_wCx_T0(int reg)
1250
{
1251
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1252
}
1253

    
1254
static inline void gen_op_iwmmxt_movl_T0_wCx(int reg)
1255
{
1256
    tcg_gen_ld_i32(cpu_T[0], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1257
}
1258

    
1259
static inline void gen_op_iwmmxt_movl_T1_wCx(int reg)
1260
{
1261
    tcg_gen_ld_i32(cpu_T[1], cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1262
}
1263

    
1264
static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1265
{
1266
    iwmmxt_store_reg(cpu_M0, rn);
1267
}
1268

    
1269
static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1270
{
1271
    iwmmxt_load_reg(cpu_M0, rn);
1272
}
1273

    
1274
static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1275
{
1276
    iwmmxt_load_reg(cpu_V1, rn);
1277
    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1278
}
1279

    
1280
static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1281
{
1282
    iwmmxt_load_reg(cpu_V1, rn);
1283
    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1284
}
1285

    
1286
static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1287
{
1288
    iwmmxt_load_reg(cpu_V1, rn);
1289
    tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1290
}
1291

    
1292
#define IWMMXT_OP(name) \
1293
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1294
{ \
1295
    iwmmxt_load_reg(cpu_V1, rn); \
1296
    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1297
}
1298

    
1299
#define IWMMXT_OP_ENV(name) \
1300
static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1301
{ \
1302
    iwmmxt_load_reg(cpu_V1, rn); \
1303
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1304
}
1305

    
1306
#define IWMMXT_OP_ENV_SIZE(name) \
1307
IWMMXT_OP_ENV(name##b) \
1308
IWMMXT_OP_ENV(name##w) \
1309
IWMMXT_OP_ENV(name##l)
1310

    
1311
#define IWMMXT_OP_ENV1(name) \
1312
static inline void gen_op_iwmmxt_##name##_M0(void) \
1313
{ \
1314
    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1315
}
1316

    
1317
IWMMXT_OP(maddsq)
1318
IWMMXT_OP(madduq)
1319
IWMMXT_OP(sadb)
1320
IWMMXT_OP(sadw)
1321
IWMMXT_OP(mulslw)
1322
IWMMXT_OP(mulshw)
1323
IWMMXT_OP(mululw)
1324
IWMMXT_OP(muluhw)
1325
IWMMXT_OP(macsw)
1326
IWMMXT_OP(macuw)
1327

    
1328
IWMMXT_OP_ENV_SIZE(unpackl)
1329
IWMMXT_OP_ENV_SIZE(unpackh)
1330

    
1331
IWMMXT_OP_ENV1(unpacklub)
1332
IWMMXT_OP_ENV1(unpackluw)
1333
IWMMXT_OP_ENV1(unpacklul)
1334
IWMMXT_OP_ENV1(unpackhub)
1335
IWMMXT_OP_ENV1(unpackhuw)
1336
IWMMXT_OP_ENV1(unpackhul)
1337
IWMMXT_OP_ENV1(unpacklsb)
1338
IWMMXT_OP_ENV1(unpacklsw)
1339
IWMMXT_OP_ENV1(unpacklsl)
1340
IWMMXT_OP_ENV1(unpackhsb)
1341
IWMMXT_OP_ENV1(unpackhsw)
1342
IWMMXT_OP_ENV1(unpackhsl)
1343

    
1344
IWMMXT_OP_ENV_SIZE(cmpeq)
1345
IWMMXT_OP_ENV_SIZE(cmpgtu)
1346
IWMMXT_OP_ENV_SIZE(cmpgts)
1347

    
1348
IWMMXT_OP_ENV_SIZE(mins)
1349
IWMMXT_OP_ENV_SIZE(minu)
1350
IWMMXT_OP_ENV_SIZE(maxs)
1351
IWMMXT_OP_ENV_SIZE(maxu)
1352

    
1353
IWMMXT_OP_ENV_SIZE(subn)
1354
IWMMXT_OP_ENV_SIZE(addn)
1355
IWMMXT_OP_ENV_SIZE(subu)
1356
IWMMXT_OP_ENV_SIZE(addu)
1357
IWMMXT_OP_ENV_SIZE(subs)
1358
IWMMXT_OP_ENV_SIZE(adds)
1359

    
1360
IWMMXT_OP_ENV(avgb0)
1361
IWMMXT_OP_ENV(avgb1)
1362
IWMMXT_OP_ENV(avgw0)
1363
IWMMXT_OP_ENV(avgw1)
1364

    
1365
IWMMXT_OP(msadb)
1366

    
1367
IWMMXT_OP_ENV(packuw)
1368
IWMMXT_OP_ENV(packul)
1369
IWMMXT_OP_ENV(packuq)
1370
IWMMXT_OP_ENV(packsw)
1371
IWMMXT_OP_ENV(packsl)
1372
IWMMXT_OP_ENV(packsq)
1373

    
1374
static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1375
{
1376
    gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1377
}
1378

    
1379
static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1380
{
1381
    gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1382
}
1383

    
1384
static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1385
{
1386
    gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1]);
1387
}
1388

    
1389
static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn)
1390
{
1391
    iwmmxt_load_reg(cpu_V1, rn);
1392
    gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, cpu_T[0]);
1393
}
1394

    
1395
static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift)
1396
{
1397
    TCGv tmp = tcg_const_i32(shift);
1398
    gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, cpu_T[0], cpu_T[1], tmp);
1399
}
1400

    
1401
static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift)
1402
{
1403
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1404
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1405
    tcg_gen_ext8s_i32(cpu_T[0], cpu_T[0]);
1406
}
1407

    
1408
static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift)
1409
{
1410
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1411
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1412
    tcg_gen_ext16s_i32(cpu_T[0], cpu_T[0]);
1413
}
1414

    
1415
static inline void gen_op_iwmmxt_extru_T0_M0(int shift, uint32_t mask)
1416
{
1417
    tcg_gen_shri_i64(cpu_M0, cpu_M0, shift);
1418
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_M0);
1419
    if (mask != ~0u)
1420
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
1421
}
1422

    
1423
static void gen_op_iwmmxt_set_mup(void)
1424
{
1425
    TCGv tmp;
1426
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1427
    tcg_gen_ori_i32(tmp, tmp, 2);
1428
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1429
}
1430

    
1431
static void gen_op_iwmmxt_set_cup(void)
1432
{
1433
    TCGv tmp;
1434
    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1435
    tcg_gen_ori_i32(tmp, tmp, 1);
1436
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1437
}
1438

    
1439
static void gen_op_iwmmxt_setpsr_nz(void)
1440
{
1441
    TCGv tmp = new_tmp();
1442
    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1443
    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1444
}
1445

    
1446
static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1447
{
1448
    iwmmxt_load_reg(cpu_V1, rn);
1449
    tcg_gen_andi_i64(cpu_V1, cpu_V1, 0xffffffffu);
1450
    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1451
}
1452

    
1453

    
1454
static void gen_iwmmxt_movl_T0_T1_wRn(int rn)
1455
{
1456
    iwmmxt_load_reg(cpu_V0, rn);
1457
    tcg_gen_trunc_i64_i32(cpu_T[0], cpu_V0);
1458
    tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1459
    tcg_gen_trunc_i64_i32(cpu_T[1], cpu_V0);
1460
}
1461

    
1462
static void gen_iwmmxt_movl_wRn_T0_T1(int rn)
1463
{
1464
    tcg_gen_extu_i32_i64(cpu_V0, cpu_T[0]);
1465
    tcg_gen_extu_i32_i64(cpu_V1, cpu_T[0]);
1466
    tcg_gen_shli_i64(cpu_V1, cpu_V1, 32);
1467
    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
1468
    iwmmxt_store_reg(cpu_V0, rn);
1469
}
1470

    
1471
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1472
{
1473
    int rd;
1474
    uint32_t offset;
1475

    
1476
    rd = (insn >> 16) & 0xf;
1477
    gen_movl_T1_reg(s, rd);
1478

    
1479
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1480
    if (insn & (1 << 24)) {
1481
        /* Pre indexed */
1482
        if (insn & (1 << 23))
1483
            gen_op_addl_T1_im(offset);
1484
        else
1485
            gen_op_addl_T1_im(-offset);
1486

    
1487
        if (insn & (1 << 21))
1488
            gen_movl_reg_T1(s, rd);
1489
    } else if (insn & (1 << 21)) {
1490
        /* Post indexed */
1491
        if (insn & (1 << 23))
1492
            gen_op_movl_T0_im(offset);
1493
        else
1494
            gen_op_movl_T0_im(- offset);
1495
        gen_op_addl_T0_T1();
1496
        gen_movl_reg_T0(s, rd);
1497
    } else if (!(insn & (1 << 23)))
1498
        return 1;
1499
    return 0;
1500
}
1501

    
1502
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1503
{
1504
    int rd = (insn >> 0) & 0xf;
1505

    
1506
    if (insn & (1 << 8))
1507
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1508
            return 1;
1509
        else
1510
            gen_op_iwmmxt_movl_T0_wCx(rd);
1511
    else
1512
        gen_iwmmxt_movl_T0_T1_wRn(rd);
1513

    
1514
    gen_op_movl_T1_im(mask);
1515
    gen_op_andl_T0_T1();
1516
    return 0;
1517
}
1518

    
1519
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1520
   (ie. an undefined instruction).  */
1521
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1522
{
1523
    int rd, wrd;
1524
    int rdhi, rdlo, rd0, rd1, i;
1525
    TCGv tmp;
1526

    
1527
    if ((insn & 0x0e000e00) == 0x0c000000) {
1528
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1529
            wrd = insn & 0xf;
1530
            rdlo = (insn >> 12) & 0xf;
1531
            rdhi = (insn >> 16) & 0xf;
1532
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1533
                gen_iwmmxt_movl_T0_T1_wRn(wrd);
1534
                gen_movl_reg_T0(s, rdlo);
1535
                gen_movl_reg_T1(s, rdhi);
1536
            } else {                                        /* TMCRR */
1537
                gen_movl_T0_reg(s, rdlo);
1538
                gen_movl_T1_reg(s, rdhi);
1539
                gen_iwmmxt_movl_wRn_T0_T1(wrd);
1540
                gen_op_iwmmxt_set_mup();
1541
            }
1542
            return 0;
1543
        }
1544

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

    
1607
    if ((insn & 0x0f000000) != 0x0e000000)
1608
        return 1;
1609

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

    
2482
    return 0;
2483
}
2484

    
2485
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2486
   (ie. an undefined instruction).  */
2487
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2488
{
2489
    int acc, rd0, rd1, rdhi, rdlo;
2490

    
2491
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2492
        /* Multiply with Internal Accumulate Format */
2493
        rd0 = (insn >> 12) & 0xf;
2494
        rd1 = insn & 0xf;
2495
        acc = (insn >> 5) & 7;
2496

    
2497
        if (acc != 0)
2498
            return 1;
2499

    
2500
        switch ((insn >> 16) & 0xf) {
2501
        case 0x0:                                        /* MIA */
2502
            gen_movl_T0_reg(s, rd0);
2503
            gen_movl_T1_reg(s, rd1);
2504
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2505
            break;
2506
        case 0x8:                                        /* MIAPH */
2507
            gen_movl_T0_reg(s, rd0);
2508
            gen_movl_T1_reg(s, rd1);
2509
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2510
            break;
2511
        case 0xc:                                        /* MIABB */
2512
        case 0xd:                                        /* MIABT */
2513
        case 0xe:                                        /* MIATB */
2514
        case 0xf:                                        /* MIATT */
2515
            gen_movl_T1_reg(s, rd0);
2516
            if (insn & (1 << 16))
2517
                gen_op_shrl_T1_im(16);
2518
            gen_op_movl_T0_T1();
2519
            gen_movl_T1_reg(s, rd1);
2520
            if (insn & (1 << 17))
2521
                gen_op_shrl_T1_im(16);
2522
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2523
            break;
2524
        default:
2525
            return 1;
2526
        }
2527

    
2528
        gen_op_iwmmxt_movq_wRn_M0(acc);
2529
        return 0;
2530
    }
2531

    
2532
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2533
        /* Internal Accumulator Access Format */
2534
        rdhi = (insn >> 16) & 0xf;
2535
        rdlo = (insn >> 12) & 0xf;
2536
        acc = insn & 7;
2537

    
2538
        if (acc != 0)
2539
            return 1;
2540

    
2541
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2542
            gen_iwmmxt_movl_T0_T1_wRn(acc);
2543
            gen_movl_reg_T0(s, rdlo);
2544
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2545
            gen_op_andl_T0_T1();
2546
            gen_movl_reg_T0(s, rdhi);
2547
        } else {                                        /* MAR */
2548
            gen_movl_T0_reg(s, rdlo);
2549
            gen_movl_T1_reg(s, rdhi);
2550
            gen_iwmmxt_movl_wRn_T0_T1(acc);
2551
        }
2552
        return 0;
2553
    }
2554

    
2555
    return 1;
2556
}
2557

    
2558
/* Disassemble system coprocessor instruction.  Return nonzero if
2559
   instruction is not defined.  */
2560
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2561
{
2562
    TCGv tmp;
2563
    uint32_t rd = (insn >> 12) & 0xf;
2564
    uint32_t cp = (insn >> 8) & 0xf;
2565
    if (IS_USER(s)) {
2566
        return 1;
2567
    }
2568

    
2569
    if (insn & ARM_CP_RW_BIT) {
2570
        if (!env->cp[cp].cp_read)
2571
            return 1;
2572
        gen_set_pc_im(s->pc);
2573
        tmp = new_tmp();
2574
        gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2575
        store_reg(s, rd, tmp);
2576
    } else {
2577
        if (!env->cp[cp].cp_write)
2578
            return 1;
2579
        gen_set_pc_im(s->pc);
2580
        tmp = load_reg(s, rd);
2581
        gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2582
    }
2583
    return 0;
2584
}
2585

    
2586
static int cp15_user_ok(uint32_t insn)
2587
{
2588
    int cpn = (insn >> 16) & 0xf;
2589
    int cpm = insn & 0xf;
2590
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2591

    
2592
    if (cpn == 13 && cpm == 0) {
2593
        /* TLS register.  */
2594
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2595
            return 1;
2596
    }
2597
    if (cpn == 7) {
2598
        /* ISB, DSB, DMB.  */
2599
        if ((cpm == 5 && op == 4)
2600
                || (cpm == 10 && (op == 4 || op == 5)))
2601
            return 1;
2602
    }
2603
    return 0;
2604
}
2605

    
2606
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2607
   instruction is not defined.  */
2608
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2609
{
2610
    uint32_t rd;
2611
    TCGv tmp;
2612

    
2613
    /* M profile cores use memory mapped registers instead of cp15.  */
2614
    if (arm_feature(env, ARM_FEATURE_M))
2615
        return 1;
2616

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

    
2662
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2663
#define VFP_SREG(insn, bigbit, smallbit) \
2664
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2665
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2666
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2667
        reg = (((insn) >> (bigbit)) & 0x0f) \
2668
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2669
    } else { \
2670
        if (insn & (1 << (smallbit))) \
2671
            return 1; \
2672
        reg = ((insn) >> (bigbit)) & 0x0f; \
2673
    }} while (0)
2674

    
2675
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2676
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2677
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2678
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2679
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2680
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2681

    
2682
/* Move between integer and VFP cores.  */
2683
static TCGv gen_vfp_mrs(void)
2684
{
2685
    TCGv tmp = new_tmp();
2686
    tcg_gen_mov_i32(tmp, cpu_F0s);
2687
    return tmp;
2688
}
2689

    
2690
static void gen_vfp_msr(TCGv tmp)
2691
{
2692
    tcg_gen_mov_i32(cpu_F0s, tmp);
2693
    dead_tmp(tmp);
2694
}
2695

    
2696
static inline int
2697
vfp_enabled(CPUState * env)
2698
{
2699
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2700
}
2701

    
2702
static void gen_neon_dup_u8(TCGv var, int shift)
2703
{
2704
    TCGv tmp = new_tmp();
2705
    if (shift)
2706
        tcg_gen_shri_i32(var, var, shift);
2707
    tcg_gen_andi_i32(var, var, 0xff);
2708
    tcg_gen_shli_i32(tmp, var, 8);
2709
    tcg_gen_or_i32(var, var, tmp);
2710
    tcg_gen_shli_i32(tmp, var, 16);
2711
    tcg_gen_or_i32(var, var, tmp);
2712
    dead_tmp(tmp);
2713
}
2714

    
2715
static void gen_neon_dup_low16(TCGv var)
2716
{
2717
    TCGv tmp = new_tmp();
2718
    tcg_gen_andi_i32(var, var, 0xffff);
2719
    tcg_gen_shli_i32(tmp, var, 16);
2720
    tcg_gen_or_i32(var, var, tmp);
2721
    dead_tmp(tmp);
2722
}
2723

    
2724
static void gen_neon_dup_high16(TCGv var)
2725
{
2726
    TCGv tmp = new_tmp();
2727
    tcg_gen_andi_i32(var, var, 0xffff0000);
2728
    tcg_gen_shri_i32(tmp, var, 16);
2729
    tcg_gen_or_i32(var, var, tmp);
2730
    dead_tmp(tmp);
2731
}
2732

    
2733
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2734
   (ie. an undefined instruction).  */
2735
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2736
{
2737
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2738
    int dp, veclen;
2739
    TCGv tmp;
2740
    TCGv tmp2;
2741

    
2742
    if (!arm_feature(env, ARM_FEATURE_VFP))
2743
        return 1;
2744

    
2745
    if (!vfp_enabled(env)) {
2746
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2747
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2748
            return 1;
2749
        rn = (insn >> 16) & 0xf;
2750
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2751
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2752
            return 1;
2753
    }
2754
    dp = ((insn & 0xf00) == 0xb00);
2755
    switch ((insn >> 24) & 0xf) {
2756
    case 0xe:
2757
        if (insn & (1 << 4)) {
2758
            /* single register transfer */
2759
            rd = (insn >> 12) & 0xf;
2760
            if (dp) {
2761
                int size;
2762
                int pass;
2763

    
2764
                VFP_DREG_N(rn, insn);
2765
                if (insn & 0xf)
2766
                    return 1;
2767
                if (insn & 0x00c00060
2768
                    && !arm_feature(env, ARM_FEATURE_NEON))
2769
                    return 1;
2770

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

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

    
2958
                if (op == 15 && (rn == 15 || rn > 17)) {
2959
                    /* Integer or single precision destination.  */
2960
                    rd = VFP_SREG_D(insn);
2961
                } else {
2962
                    VFP_DREG_D(rd, insn);
2963
                }
2964

    
2965
                if (op == 15 && (rn == 16 || rn == 17)) {
2966
                    /* Integer source.  */
2967
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2968
                } else {
2969
                    VFP_DREG_M(rm, insn);
2970
                }
2971
            } else {
2972
                rn = VFP_SREG_N(insn);
2973
                if (op == 15 && rn == 15) {
2974
                    /* Double precision destination.  */
2975
                    VFP_DREG_D(rd, insn);
2976
                } else {
2977
                    rd = VFP_SREG_D(insn);
2978
                }
2979
                rm = VFP_SREG_M(insn);
2980
            }
2981

    
2982
            veclen = env->vfp.vec_len;
2983
            if (op == 15 && rn > 3)
2984
                veclen = 0;
2985

    
2986
            /* Shut up compiler warnings.  */
2987
            delta_m = 0;
2988
            delta_d = 0;
2989
            bank_mask = 0;
2990

    
2991
            if (veclen > 0) {
2992
                if (dp)
2993
                    bank_mask = 0xc;
2994
                else
2995
                    bank_mask = 0x18;
2996

    
2997
                /* Figure out what type of vector operation this is.  */
2998
                if ((rd & bank_mask) == 0) {
2999
                    /* scalar */
3000
                    veclen = 0;
3001
                } else {
3002
                    if (dp)
3003
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
3004
                    else
3005
                        delta_d = env->vfp.vec_stride + 1;
3006

    
3007
                    if ((rm & bank_mask) == 0) {
3008
                        /* mixed scalar/vector */
3009
                        delta_m = 0;
3010
                    } else {
3011
                        /* vector */
3012
                        delta_m = delta_d;
3013
                    }
3014
                }
3015
            }
3016

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

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

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

    
3219
                /* Write back the result.  */
3220
                if (op == 15 && (rn >= 8 && rn <= 11))
3221
                    ; /* Comparison, do nothing.  */
3222
                else if (op == 15 && rn > 17)
3223
                    /* Integer result.  */
3224
                    gen_mov_vreg_F0(0, rd);
3225
                else if (op == 15 && rn == 15)
3226
                    /* conversion */
3227
                    gen_mov_vreg_F0(!dp, rd);
3228
                else
3229
                    gen_mov_vreg_F0(dp, rd);
3230

    
3231
                /* break out of the loop if we have finished  */
3232
                if (veclen == 0)
3233
                    break;
3234

    
3235
                if (op == 15 && delta_m == 0) {
3236
                    /* single source one-many */
3237
                    while (veclen--) {
3238
                        rd = ((rd + delta_d) & (bank_mask - 1))
3239
                             | (rd & bank_mask);
3240
                        gen_mov_vreg_F0(dp, rd);
3241
                    }
3242
                    break;
3243
                }
3244
                /* Setup the next operands.  */
3245
                veclen--;
3246
                rd = ((rd + delta_d) & (bank_mask - 1))
3247
                     | (rd & bank_mask);
3248

    
3249
                if (op == 15) {
3250
                    /* One source operand.  */
3251
                    rm = ((rm + delta_m) & (bank_mask - 1))
3252
                         | (rm & bank_mask);
3253
                    gen_mov_F0_vreg(dp, rm);
3254
                } else {
3255
                    /* Two source operands.  */
3256
                    rn = ((rn + delta_d) & (bank_mask - 1))
3257
                         | (rn & bank_mask);
3258
                    gen_mov_F0_vreg(dp, rn);
3259
                    if (delta_m) {
3260
                        rm = ((rm + delta_m) & (bank_mask - 1))
3261
                             | (rm & bank_mask);
3262
                        gen_mov_F1_vreg(dp, rm);
3263
                    }
3264
                }
3265
            }
3266
        }
3267
        break;
3268
    case 0xc:
3269
    case 0xd:
3270
        if (dp && (insn & 0x03e00000) == 0x00400000) {
3271
            /* two-register transfer */
3272
            rn = (insn >> 16) & 0xf;
3273
            rd = (insn >> 12) & 0xf;
3274
            if (dp) {
3275
                VFP_DREG_M(rm, insn);
3276
            } else {
3277
                rm = VFP_SREG_M(insn);
3278
            }
3279

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

    
3347
                if (insn & (1 << 24)) /* pre-decrement */
3348
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3349

    
3350
                if (dp)
3351
                    offset = 8;
3352
                else
3353
                    offset = 4;
3354
                for (i = 0; i < n; i++) {
3355
                    if (insn & ARM_CP_RW_BIT) {
3356
                        /* load */
3357
                        gen_vfp_ld(s, dp);
3358
                        gen_mov_vreg_F0(dp, rd + i);
3359
                    } else {
3360
                        /* store */
3361
                        gen_mov_F0_vreg(dp, rd + i);
3362
                        gen_vfp_st(s, dp);
3363
                    }
3364
                    gen_op_addl_T1_im(offset);
3365
                }
3366
                if (insn & (1 << 21)) {
3367
                    /* writeback */
3368
                    if (insn & (1 << 24))
3369
                        offset = -offset * n;
3370
                    else if (dp && (insn & 1))
3371
                        offset = 4;
3372
                    else
3373
                        offset = 0;
3374

    
3375
                    if (offset != 0)
3376
                        gen_op_addl_T1_im(offset);
3377
                    gen_movl_reg_T1(s, rn);
3378
                }
3379
            }
3380
        }
3381
        break;
3382
    default:
3383
        /* Should never happen.  */
3384
        return 1;
3385
    }
3386
    return 0;
3387
}
3388

    
3389
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3390
{
3391
    TranslationBlock *tb;
3392

    
3393
    tb = s->tb;
3394
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3395
        tcg_gen_goto_tb(n);
3396
        gen_set_pc_im(dest);
3397
        tcg_gen_exit_tb((long)tb + n);
3398
    } else {
3399
        gen_set_pc_im(dest);
3400
        tcg_gen_exit_tb(0);
3401
    }
3402
}
3403

    
3404
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3405
{
3406
    if (__builtin_expect(s->singlestep_enabled, 0)) {
3407
        /* An indirect jump so that we still trigger the debug exception.  */
3408
        if (s->thumb)
3409
            dest |= 1;
3410
        gen_bx_im(s, dest);
3411
    } else {
3412
        gen_goto_tb(s, 0, dest);
3413
        s->is_jmp = DISAS_TB_JUMP;
3414
    }
3415
}
3416

    
3417
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3418
{
3419
    if (x)
3420
        tcg_gen_sari_i32(t0, t0, 16);
3421
    else
3422
        gen_sxth(t0);
3423
    if (y)
3424
        tcg_gen_sari_i32(t1, t1, 16);
3425
    else
3426
        gen_sxth(t1);
3427
    tcg_gen_mul_i32(t0, t0, t1);
3428
}
3429

    
3430
/* Return the mask of PSR bits set by a MSR instruction.  */
3431
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3432
    uint32_t mask;
3433

    
3434
    mask = 0;
3435
    if (flags & (1 << 0))
3436
        mask |= 0xff;
3437
    if (flags & (1 << 1))
3438
        mask |= 0xff00;
3439
    if (flags & (1 << 2))
3440
        mask |= 0xff0000;
3441
    if (flags & (1 << 3))
3442
        mask |= 0xff000000;
3443

    
3444
    /* Mask out undefined bits.  */
3445
    mask &= ~CPSR_RESERVED;
3446
    if (!arm_feature(env, ARM_FEATURE_V6))
3447
        mask &= ~(CPSR_E | CPSR_GE);
3448
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3449
        mask &= ~CPSR_IT;
3450
    /* Mask out execution state bits.  */
3451
    if (!spsr)
3452
        mask &= ~CPSR_EXEC;
3453
    /* Mask out privileged bits.  */
3454
    if (IS_USER(s))
3455
        mask &= CPSR_USER;
3456
    return mask;
3457
}
3458

    
3459
/* Returns nonzero if access to the PSR is not permitted.  */
3460
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3461
{
3462
    TCGv tmp;
3463
    if (spsr) {
3464
        /* ??? This is also undefined in system mode.  */
3465
        if (IS_USER(s))
3466
            return 1;
3467

    
3468
        tmp = load_cpu_field(spsr);
3469
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3470
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3471
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3472
        store_cpu_field(tmp, spsr);
3473
    } else {
3474
        gen_set_cpsr(cpu_T[0], mask);
3475
    }
3476
    gen_lookup_tb(s);
3477
    return 0;
3478
}
3479

    
3480
/* Generate an old-style exception return.  */
3481
static void gen_exception_return(DisasContext *s)
3482
{
3483
    TCGv tmp;
3484
    gen_movl_reg_T0(s, 15);
3485
    tmp = load_cpu_field(spsr);
3486
    gen_set_cpsr(tmp, 0xffffffff);
3487
    dead_tmp(tmp);
3488
    s->is_jmp = DISAS_UPDATE;
3489
}
3490

    
3491
/* Generate a v6 exception return.  Marks both values as dead.  */
3492
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3493
{
3494
    gen_set_cpsr(cpsr, 0xffffffff);
3495
    dead_tmp(cpsr);
3496
    store_reg(s, 15, pc);
3497
    s->is_jmp = DISAS_UPDATE;
3498
}
3499

    
3500
static inline void
3501
gen_set_condexec (DisasContext *s)
3502
{
3503
    if (s->condexec_mask) {
3504
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3505
        TCGv tmp = new_tmp();
3506
        tcg_gen_movi_i32(tmp, val);
3507
        store_cpu_field(tmp, condexec_bits);
3508
    }
3509
}
3510

    
3511
static void gen_nop_hint(DisasContext *s, int val)
3512
{
3513
    switch (val) {
3514
    case 3: /* wfi */
3515
        gen_set_pc_im(s->pc);
3516
        s->is_jmp = DISAS_WFI;
3517
        break;
3518
    case 2: /* wfe */
3519
    case 4: /* sev */
3520
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3521
    default: /* nop */
3522
        break;
3523
    }
3524
}
3525

    
3526
/* These macros help make the code more readable when migrating from the
3527
   old dyngen helpers.  They should probably be removed when
3528
   T0/T1 are removed.  */
3529
#define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3530
#define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3531

    
3532
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3533

    
3534
static inline int gen_neon_add(int size)
3535
{
3536
    switch (size) {
3537
    case 0: gen_helper_neon_add_u8(CPU_T001); break;
3538
    case 1: gen_helper_neon_add_u16(CPU_T001); break;
3539
    case 2: gen_op_addl_T0_T1(); break;
3540
    default: return 1;
3541
    }
3542
    return 0;
3543
}
3544

    
3545
static inline void gen_neon_rsb(int size)
3546
{
3547
    switch (size) {
3548
    case 0: gen_helper_neon_sub_u8(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3549
    case 1: gen_helper_neon_sub_u16(cpu_T[0], cpu_T[1], cpu_T[0]); break;
3550
    case 2: gen_op_rsbl_T0_T1(); break;
3551
    default: return;
3552
    }
3553
}
3554

    
3555
/* 32-bit pairwise ops end up the same as the elementwise versions.  */
3556
#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
3557
#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
3558
#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
3559
#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
3560

    
3561
/* FIXME: This is wrong.  They set the wrong overflow bit.  */
3562
#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3563
#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3564
#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3565
#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3566

    
3567
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3568
    switch ((size << 1) | u) { \
3569
    case 0: \
3570
        gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3571
        break; \
3572
    case 1: \
3573
        gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3574
        break; \
3575
    case 2: \
3576
        gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3577
        break; \
3578
    case 3: \
3579
        gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3580
        break; \
3581
    case 4: \
3582
        gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3583
        break; \
3584
    case 5: \
3585
        gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3586
        break; \
3587
    default: return 1; \
3588
    }} while (0)
3589

    
3590
#define GEN_NEON_INTEGER_OP(name) do { \
3591
    switch ((size << 1) | u) { \
3592
    case 0: \
3593
        gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3594
        break; \
3595
    case 1: \
3596
        gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3597
        break; \
3598
    case 2: \
3599
        gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3600
        break; \
3601
    case 3: \
3602
        gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3603
        break; \
3604
    case 4: \
3605
        gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3606
        break; \
3607
    case 5: \
3608
        gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3609
        break; \
3610
    default: return 1; \
3611
    }} while (0)
3612

    
3613
static inline void
3614
gen_neon_movl_scratch_T0(int scratch)
3615
{
3616
  uint32_t offset;
3617

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

    
3622
static inline void
3623
gen_neon_movl_scratch_T1(int scratch)
3624
{
3625
  uint32_t offset;
3626

    
3627
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3628
  tcg_gen_st_i32(cpu_T[1], cpu_env, offset);
3629
}
3630

    
3631
static inline void
3632
gen_neon_movl_T0_scratch(int scratch)
3633
{
3634
  uint32_t offset;
3635

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

    
3640
static inline void
3641
gen_neon_movl_T1_scratch(int scratch)
3642
{
3643
  uint32_t offset;
3644

    
3645
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3646
  tcg_gen_ld_i32(cpu_T[1], cpu_env, offset);
3647
}
3648

    
3649
static inline void gen_neon_get_scalar(int size, int reg)
3650
{
3651
    if (size == 1) {
3652
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3653
    } else {
3654
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3655
        if (reg & 1)
3656
            gen_neon_dup_low16(cpu_T[0]);
3657
        else
3658
            gen_neon_dup_high16(cpu_T[0]);
3659
    }
3660
}
3661

    
3662
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3663
{
3664
    int n;
3665

    
3666
    for (n = 0; n < q + 1; n += 2) {
3667
        NEON_GET_REG(T0, reg, n);
3668
        NEON_GET_REG(T0, reg, n + n);
3669
        switch (size) {
3670
        case 0: gen_helper_neon_unzip_u8(); break;
3671
        case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same.  */
3672
        case 2: /* no-op */; break;
3673
        default: abort();
3674
        }
3675
        gen_neon_movl_scratch_T0(tmp + n);
3676
        gen_neon_movl_scratch_T1(tmp + n + 1);
3677
    }
3678
}
3679

    
3680
static struct {
3681
    int nregs;
3682
    int interleave;
3683
    int spacing;
3684
} neon_ls_element_type[11] = {
3685
    {4, 4, 1},
3686
    {4, 4, 2},
3687
    {4, 1, 1},
3688
    {4, 2, 1},
3689
    {3, 3, 1},
3690
    {3, 3, 2},
3691
    {3, 1, 1},
3692
    {1, 1, 1},
3693
    {2, 2, 1},
3694
    {2, 2, 2},
3695
    {2, 1, 1}
3696
};
3697

    
3698
/* Translate a NEON load/store element instruction.  Return nonzero if the
3699
   instruction is invalid.  */
3700
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3701
{
3702
    int rd, rn, rm;
3703
    int op;
3704
    int nregs;
3705
    int interleave;
3706
    int stride;
3707
    int size;
3708
    int reg;
3709
    int pass;
3710
    int load;
3711
    int shift;
3712
    int n;
3713
    TCGv tmp;
3714
    TCGv tmp2;
3715

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

    
3899
        base = load_reg(s, rn);
3900
        if (rm == 13) {
3901
            tcg_gen_addi_i32(base, base, stride);
3902
        } else {
3903
            TCGv index;
3904
            index = load_reg(s, rm);
3905
            tcg_gen_add_i32(base, base, index);
3906
            dead_tmp(index);
3907
        }
3908
        store_reg(s, rn, base);
3909
    }
3910
    return 0;
3911
}
3912

    
3913
/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
3914
static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3915
{
3916
    tcg_gen_and_i32(t, t, c);
3917
    tcg_gen_bic_i32(f, f, c);
3918
    tcg_gen_or_i32(dest, t, f);
3919
}
3920

    
3921
static inline void gen_neon_narrow(int size, TCGv dest, TCGv src)
3922
{
3923
    switch (size) {
3924
    case 0: gen_helper_neon_narrow_u8(dest, src); break;
3925
    case 1: gen_helper_neon_narrow_u16(dest, src); break;
3926
    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3927
    default: abort();
3928
    }
3929
}
3930

    
3931
static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv src)
3932
{
3933
    switch (size) {
3934
    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3935
    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3936
    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3937
    default: abort();
3938
    }
3939
}
3940

    
3941
static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv src)
3942
{
3943
    switch (size) {
3944
    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3945
    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3946
    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3947
    default: abort();
3948
    }
3949
}
3950

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

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

    
4005
static inline void gen_neon_addl(int size)
4006
{
4007
    switch (size) {
4008
    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4009
    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4010
    case 2: tcg_gen_add_i64(CPU_V001); break;
4011
    default: abort();
4012
    }
4013
}
4014

    
4015
static inline void gen_neon_subl(int size)
4016
{
4017
    switch (size) {
4018
    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4019
    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4020
    case 2: tcg_gen_sub_i64(CPU_V001); break;
4021
    default: abort();
4022
    }
4023
}
4024

    
4025
static inline void gen_neon_negl(TCGv var, int size)
4026
{
4027
    switch (size) {
4028
    case 0: gen_helper_neon_negl_u16(var, var); break;
4029
    case 1: gen_helper_neon_negl_u32(var, var); break;
4030
    case 2: gen_helper_neon_negl_u64(var, var); break;
4031
    default: abort();
4032
    }
4033
}
4034

    
4035
static inline void gen_neon_addl_saturate(TCGv op0, TCGv op1, int size)
4036
{
4037
    switch (size) {
4038
    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4039
    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4040
    default: abort();
4041
    }
4042
}
4043

    
4044
static inline void gen_neon_mull(TCGv dest, TCGv a, TCGv b, int size, int u)
4045
{
4046
    TCGv tmp;
4047

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

    
4069
/* Translate a NEON data processing instruction.  Return nonzero if the
4070
   instruction is invalid.
4071
   We process data in a mixture of 32-bit and 64-bit chunks.
4072
   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
4073

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

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

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

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

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

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

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

    
4709
                    gen_neon_widen(cpu_V0, tmp, size, u);
4710

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

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