Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 5e3f878a

History | View | Annotate | Download (283.3 kB)

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

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

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

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

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

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

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

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

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

    
79
static TCGv cpu_env;
80
/* FIXME:  These should be removed.  */
81
static TCGv cpu_T[3];
82
static TCGv cpu_F0s, cpu_F1s, cpu_F0d, cpu_F1d;
83

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
188

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

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

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

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

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

    
224
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
225
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
226

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

    
229
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
230
/* Set NZCV flags from the high 4 bits of var.  */
231
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
232

    
233
static void gen_exception(int excp)
234
{
235
    TCGv tmp = new_tmp();
236
    tcg_gen_movi_i32(tmp, excp);
237
    gen_helper_exception(tmp);
238
    dead_tmp(tmp);
239
}
240

    
241
static void gen_smul_dual(TCGv a, TCGv b)
242
{
243
    TCGv tmp1 = new_tmp();
244
    TCGv tmp2 = new_tmp();
245
    tcg_gen_ext8s_i32(tmp1, a);
246
    tcg_gen_ext8s_i32(tmp2, b);
247
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
248
    dead_tmp(tmp2);
249
    tcg_gen_sari_i32(a, a, 16);
250
    tcg_gen_sari_i32(b, b, 16);
251
    tcg_gen_mul_i32(b, b, a);
252
    tcg_gen_mov_i32(a, tmp1);
253
    dead_tmp(tmp1);
254
}
255

    
256
/* Byteswap each halfword.  */
257
static void gen_rev16(TCGv var)
258
{
259
    TCGv tmp = new_tmp();
260
    tcg_gen_shri_i32(tmp, var, 8);
261
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
262
    tcg_gen_shli_i32(var, var, 8);
263
    tcg_gen_andi_i32(var, var, 0xff00ff00);
264
    tcg_gen_or_i32(var, var, tmp);
265
    dead_tmp(tmp);
266
}
267

    
268
/* Byteswap low halfword and sign extend.  */
269
static void gen_revsh(TCGv var)
270
{
271
    TCGv tmp = new_tmp();
272
    tcg_gen_shri_i32(tmp, var, 8);
273
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
274
    tcg_gen_shli_i32(var, var, 8);
275
    tcg_gen_ext8s_i32(var, var);
276
    tcg_gen_or_i32(var, var, tmp);
277
    dead_tmp(tmp);
278
}
279

    
280
/* Unsigned bitfield extract.  */
281
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
282
{
283
    if (shift)
284
        tcg_gen_shri_i32(var, var, shift);
285
    tcg_gen_andi_i32(var, var, mask);
286
}
287

    
288
/* Signed bitfield extract.  */
289
static void gen_sbfx(TCGv var, int shift, int width)
290
{
291
    uint32_t signbit;
292

    
293
    if (shift)
294
        tcg_gen_sari_i32(var, var, shift);
295
    if (shift + width < 32) {
296
        signbit = 1u << (width - 1);
297
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
298
        tcg_gen_xori_i32(var, var, signbit);
299
        tcg_gen_subi_i32(var, var, signbit);
300
    }
301
}
302

    
303
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
304
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
305
{
306
    tcg_gen_shli_i32(val, val, shift);
307
    tcg_gen_andi_i32(val, val, mask);
308
    tcg_gen_andi_i32(base, base, ~mask);
309
    tcg_gen_or_i32(dest, base, val);
310
}
311

    
312
/* Round the top 32 bits of a 64-bit value.  */
313
static void gen_roundqd(TCGv a, TCGv b)
314
{
315
    tcg_gen_shri_i32(a, a, 31);
316
    tcg_gen_add_i32(a, a, b);
317
}
318

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

    
327
    tcg_gen_extu_i32_i64(tmp1, a);
328
    dead_tmp(a);
329
    tcg_gen_extu_i32_i64(tmp2, b);
330
    dead_tmp(b);
331
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
332
    return tmp1;
333
}
334

    
335
static TCGv gen_muls_i64_i32(TCGv a, TCGv b)
336
{
337
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
338
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
339

    
340
    tcg_gen_ext_i32_i64(tmp1, a);
341
    dead_tmp(a);
342
    tcg_gen_ext_i32_i64(tmp2, b);
343
    dead_tmp(b);
344
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
345
    return tmp1;
346
}
347

    
348
/* Unsigned 32x32->64 multiply.  */
349
static void gen_op_mull_T0_T1(void)
350
{
351
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
352
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
353

    
354
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
355
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
356
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
357
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
358
    tcg_gen_shri_i64(tmp1, tmp1, 32);
359
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
360
}
361

    
362
/* Signed 32x32->64 multiply.  */
363
static void gen_imull(TCGv a, TCGv b)
364
{
365
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
366
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
367

    
368
    tcg_gen_ext_i32_i64(tmp1, a);
369
    tcg_gen_ext_i32_i64(tmp2, b);
370
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
371
    tcg_gen_trunc_i64_i32(a, tmp1);
372
    tcg_gen_shri_i64(tmp1, tmp1, 32);
373
    tcg_gen_trunc_i64_i32(b, tmp1);
374
}
375
#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1])
376

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

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

    
394
static void gen_add16(TCGv t0, TCGv t1)
395
{
396
    TCGv tmp = new_tmp();
397
    tcg_gen_xor_i32(tmp, t0, t1);
398
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
399
    tcg_gen_andi_i32(t0, t0, ~0x8000);
400
    tcg_gen_andi_i32(t1, t1, ~0x8000);
401
    tcg_gen_add_i32(t0, t0, t1);
402
    tcg_gen_xor_i32(t0, t0, tmp);
403
    dead_tmp(tmp);
404
    dead_tmp(t1);
405
}
406

    
407
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
408

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

    
418
/* Set N and Z flags from var.  */
419
static inline void gen_logic_CC(TCGv var)
420
{
421
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
422
}
423

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

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

    
445
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
446
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
447

    
448
/* FIXME:  Implement this natively.  */
449
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
450
{
451
    tcg_gen_xori_i32(t0, t1, ~0);
452
}
453

    
454
/* T0 &= ~T1.  Clobbers T1.  */
455
/* FIXME: Implement bic natively.  */
456
static inline void gen_op_bicl_T0_T1(void)
457
{
458
    gen_op_notl_T1();
459
    gen_op_andl_T0_T1();
460
}
461

    
462
/* FIXME:  Implement this natively.  */
463
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
464
{
465
    TCGv tmp;
466

    
467
    if (i == 0)
468
        return;
469

    
470
    tmp = new_tmp();
471
    tcg_gen_shri_i32(tmp, t1, i);
472
    tcg_gen_shli_i32(t1, t1, 32 - i);
473
    tcg_gen_or_i32(t0, t1, tmp);
474
    dead_tmp(tmp);
475
}
476

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

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

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

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

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

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

    
630
static void gen_test_cc(int cc, int label)
631
{
632
    TCGv tmp;
633
    TCGv tmp2;
634
    TCGv zero;
635
    int inv;
636

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

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

    
749
static GenOpFunc *gen_shift_T1_T0[4] = {
750
    gen_op_shll_T1_T0,
751
    gen_op_shrl_T1_T0,
752
    gen_op_sarl_T1_T0,
753
    gen_op_rorl_T1_T0,
754
};
755

    
756
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
757
    gen_op_shll_T1_T0_cc,
758
    gen_op_shrl_T1_T0_cc,
759
    gen_op_sarl_T1_T0_cc,
760
    gen_op_rorl_T1_T0_cc,
761
};
762

    
763
/* Set PC and Thumb state from an immediate address.  */
764
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
765
{
766
    TCGv tmp;
767

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

    
779
/* Set PC and Thumb state from var.  var is marked as dead.  */
780
static inline void gen_bx(DisasContext *s, TCGv var)
781
{
782
    TCGv tmp;
783

    
784
    s->is_jmp = DISAS_UPDATE;
785
    tmp = new_tmp();
786
    tcg_gen_andi_i32(tmp, var, 1);
787
    store_cpu_field(tmp, thumb);
788
    tcg_gen_andi_i32(var, var, ~1);
789
    store_cpu_field(var, regs[15]);
790
}
791

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

    
800
#if defined(CONFIG_USER_ONLY)
801
#define gen_ldst(name, s) gen_op_##name##_raw()
802
#else
803
#define gen_ldst(name, s) do { \
804
    s->is_mem = 1; \
805
    if (IS_USER(s)) \
806
        gen_op_##name##_user(); \
807
    else \
808
        gen_op_##name##_kernel(); \
809
    } while (0)
810
#endif
811
static inline TCGv gen_ld8s(TCGv addr, int index)
812
{
813
    TCGv tmp = new_tmp();
814
    tcg_gen_qemu_ld8s(tmp, addr, index);
815
    return tmp;
816
}
817
static inline TCGv gen_ld8u(TCGv addr, int index)
818
{
819
    TCGv tmp = new_tmp();
820
    tcg_gen_qemu_ld8u(tmp, addr, index);
821
    return tmp;
822
}
823
static inline TCGv gen_ld16s(TCGv addr, int index)
824
{
825
    TCGv tmp = new_tmp();
826
    tcg_gen_qemu_ld16s(tmp, addr, index);
827
    return tmp;
828
}
829
static inline TCGv gen_ld16u(TCGv addr, int index)
830
{
831
    TCGv tmp = new_tmp();
832
    tcg_gen_qemu_ld16u(tmp, addr, index);
833
    return tmp;
834
}
835
static inline TCGv gen_ld32(TCGv addr, int index)
836
{
837
    TCGv tmp = new_tmp();
838
    tcg_gen_qemu_ld32u(tmp, addr, index);
839
    return tmp;
840
}
841
static inline void gen_st8(TCGv val, TCGv addr, int index)
842
{
843
    tcg_gen_qemu_st8(val, addr, index);
844
    dead_tmp(val);
845
}
846
static inline void gen_st16(TCGv val, TCGv addr, int index)
847
{
848
    tcg_gen_qemu_st16(val, addr, index);
849
    dead_tmp(val);
850
}
851
static inline void gen_st32(TCGv val, TCGv addr, int index)
852
{
853
    tcg_gen_qemu_st32(val, addr, index);
854
    dead_tmp(val);
855
}
856

    
857
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
858
{
859
    load_reg_var(s, cpu_T[0], reg);
860
}
861

    
862
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
863
{
864
    load_reg_var(s, cpu_T[1], reg);
865
}
866

    
867
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
868
{
869
    load_reg_var(s, cpu_T[2], reg);
870
}
871

    
872
static inline void gen_set_pc_im(uint32_t val)
873
{
874
    TCGv tmp = new_tmp();
875
    tcg_gen_movi_i32(tmp, val);
876
    store_cpu_field(tmp, regs[15]);
877
}
878

    
879
static inline void gen_set_pc_T0(void)
880
{
881
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
882
}
883

    
884
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
885
{
886
    TCGv tmp;
887
    if (reg == 15) {
888
        tmp = new_tmp();
889
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
890
    } else {
891
        tmp = cpu_T[t];
892
    }
893
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
894
    if (reg == 15) {
895
        dead_tmp(tmp);
896
        s->is_jmp = DISAS_JUMP;
897
    }
898
}
899

    
900
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
901
{
902
    gen_movl_reg_TN(s, reg, 0);
903
}
904

    
905
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
906
{
907
    gen_movl_reg_TN(s, reg, 1);
908
}
909

    
910
/* Force a TB lookup after an instruction that changes the CPU state.  */
911
static inline void gen_lookup_tb(DisasContext *s)
912
{
913
    gen_op_movl_T0_im(s->pc);
914
    gen_movl_reg_T0(s, 15);
915
    s->is_jmp = DISAS_UPDATE;
916
}
917

    
918
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
919
                                       TCGv var)
920
{
921
    int val, rm, shift, shiftop;
922
    TCGv offset;
923

    
924
    if (!(insn & (1 << 25))) {
925
        /* immediate */
926
        val = insn & 0xfff;
927
        if (!(insn & (1 << 23)))
928
            val = -val;
929
        if (val != 0)
930
            tcg_gen_addi_i32(var, var, val);
931
    } else {
932
        /* shift/register */
933
        rm = (insn) & 0xf;
934
        shift = (insn >> 7) & 0x1f;
935
        shiftop = (insn >> 5) & 3;
936
        offset = load_reg(s, rm);
937
        gen_arm_shift_im(offset, shiftop, shift, 0);
938
        if (!(insn & (1 << 23)))
939
            tcg_gen_sub_i32(var, var, offset);
940
        else
941
            tcg_gen_add_i32(var, var, offset);
942
        dead_tmp(offset);
943
    }
944
}
945

    
946
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
947
                                        int extra, TCGv var)
948
{
949
    int val, rm;
950
    TCGv offset;
951

    
952
    if (insn & (1 << 22)) {
953
        /* immediate */
954
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
955
        if (!(insn & (1 << 23)))
956
            val = -val;
957
        val += extra;
958
        if (val != 0)
959
            tcg_gen_addi_i32(var, var, val);
960
    } else {
961
        /* register */
962
        if (extra)
963
            tcg_gen_addi_i32(var, var, extra);
964
        rm = (insn) & 0xf;
965
        offset = load_reg(s, rm);
966
        if (!(insn & (1 << 23)))
967
            tcg_gen_sub_i32(var, var, offset);
968
        else
969
            tcg_gen_add_i32(var, var, offset);
970
        dead_tmp(offset);
971
    }
972
}
973

    
974
#define VFP_OP2(name)                                                 \
975
static inline void gen_vfp_##name(int dp)                             \
976
{                                                                     \
977
    if (dp)                                                           \
978
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
979
    else                                                              \
980
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
981
}
982

    
983
#define VFP_OP1i(name)                               \
984
static inline void gen_vfp_##name(int dp, int arg)  \
985
{                                                   \
986
    if (dp)                                         \
987
        gen_op_vfp_##name##d(arg);                  \
988
    else                                            \
989
        gen_op_vfp_##name##s(arg);                  \
990
}
991

    
992
VFP_OP2(add)
993
VFP_OP2(sub)
994
VFP_OP2(mul)
995
VFP_OP2(div)
996

    
997
#undef VFP_OP2
998

    
999
static inline void gen_vfp_abs(int dp)
1000
{
1001
    if (dp)
1002
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1003
    else
1004
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1005
}
1006

    
1007
static inline void gen_vfp_neg(int dp)
1008
{
1009
    if (dp)
1010
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1011
    else
1012
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1013
}
1014

    
1015
static inline void gen_vfp_sqrt(int dp)
1016
{
1017
    if (dp)
1018
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1019
    else
1020
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1021
}
1022

    
1023
static inline void gen_vfp_cmp(int dp)
1024
{
1025
    if (dp)
1026
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1027
    else
1028
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1029
}
1030

    
1031
static inline void gen_vfp_cmpe(int dp)
1032
{
1033
    if (dp)
1034
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1035
    else
1036
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1037
}
1038

    
1039
static inline void gen_vfp_F1_ld0(int dp)
1040
{
1041
    if (dp)
1042
        tcg_gen_movi_i64(cpu_F0d, 0);
1043
    else
1044
        tcg_gen_movi_i32(cpu_F0s, 0);
1045
}
1046

    
1047
static inline void gen_vfp_uito(int dp)
1048
{
1049
    if (dp)
1050
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1051
    else
1052
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1053
}
1054

    
1055
static inline void gen_vfp_sito(int dp)
1056
{
1057
    if (dp)
1058
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1059
    else
1060
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1061
}
1062

    
1063
static inline void gen_vfp_toui(int dp)
1064
{
1065
    if (dp)
1066
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1067
    else
1068
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1069
}
1070

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

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

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

    
1095
#define VFP_GEN_FIX(name) \
1096
static inline void gen_vfp_##name(int dp, int shift) \
1097
{ \
1098
    if (dp) \
1099
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1100
    else \
1101
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1102
}
1103
VFP_GEN_FIX(tosh)
1104
VFP_GEN_FIX(tosl)
1105
VFP_GEN_FIX(touh)
1106
VFP_GEN_FIX(toul)
1107
VFP_GEN_FIX(shto)
1108
VFP_GEN_FIX(slto)
1109
VFP_GEN_FIX(uhto)
1110
VFP_GEN_FIX(ulto)
1111
#undef VFP_GEN_FIX
1112

    
1113
static inline void gen_vfp_ld(DisasContext *s, int dp)
1114
{
1115
    if (dp)
1116
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1117
    else
1118
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1119
}
1120

    
1121
static inline void gen_vfp_st(DisasContext *s, int dp)
1122
{
1123
    if (dp)
1124
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1125
    else
1126
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1127
}
1128

    
1129
static inline long
1130
vfp_reg_offset (int dp, int reg)
1131
{
1132
    if (dp)
1133
        return offsetof(CPUARMState, vfp.regs[reg]);
1134
    else if (reg & 1) {
1135
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1136
          + offsetof(CPU_DoubleU, l.upper);
1137
    } else {
1138
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1139
          + offsetof(CPU_DoubleU, l.lower);
1140
    }
1141
}
1142

    
1143
/* Return the offset of a 32-bit piece of a NEON register.
1144
   zero is the least significant end of the register.  */
1145
static inline long
1146
neon_reg_offset (int reg, int n)
1147
{
1148
    int sreg;
1149
    sreg = reg * 2 + n;
1150
    return vfp_reg_offset(0, sreg);
1151
}
1152

    
1153
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
1154
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
1155

    
1156
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1157
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1158
#define tcg_gen_st_f32 tcg_gen_st_i32
1159
#define tcg_gen_st_f64 tcg_gen_st_i64
1160

    
1161
static inline void gen_mov_F0_vreg(int dp, int reg)
1162
{
1163
    if (dp)
1164
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1165
    else
1166
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1167
}
1168

    
1169
static inline void gen_mov_F1_vreg(int dp, int reg)
1170
{
1171
    if (dp)
1172
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1173
    else
1174
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1175
}
1176

    
1177
static inline void gen_mov_vreg_F0(int dp, int reg)
1178
{
1179
    if (dp)
1180
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1181
    else
1182
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1183
}
1184

    
1185
#define ARM_CP_RW_BIT        (1 << 20)
1186

    
1187
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1188
{
1189
    int rd;
1190
    uint32_t offset;
1191

    
1192
    rd = (insn >> 16) & 0xf;
1193
    gen_movl_T1_reg(s, rd);
1194

    
1195
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1196
    if (insn & (1 << 24)) {
1197
        /* Pre indexed */
1198
        if (insn & (1 << 23))
1199
            gen_op_addl_T1_im(offset);
1200
        else
1201
            gen_op_addl_T1_im(-offset);
1202

    
1203
        if (insn & (1 << 21))
1204
            gen_movl_reg_T1(s, rd);
1205
    } else if (insn & (1 << 21)) {
1206
        /* Post indexed */
1207
        if (insn & (1 << 23))
1208
            gen_op_movl_T0_im(offset);
1209
        else
1210
            gen_op_movl_T0_im(- offset);
1211
        gen_op_addl_T0_T1();
1212
        gen_movl_reg_T0(s, rd);
1213
    } else if (!(insn & (1 << 23)))
1214
        return 1;
1215
    return 0;
1216
}
1217

    
1218
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1219
{
1220
    int rd = (insn >> 0) & 0xf;
1221

    
1222
    if (insn & (1 << 8))
1223
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1224
            return 1;
1225
        else
1226
            gen_op_iwmmxt_movl_T0_wCx(rd);
1227
    else
1228
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
1229

    
1230
    gen_op_movl_T1_im(mask);
1231
    gen_op_andl_T0_T1();
1232
    return 0;
1233
}
1234

    
1235
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1236
   (ie. an undefined instruction).  */
1237
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1238
{
1239
    int rd, wrd;
1240
    int rdhi, rdlo, rd0, rd1, i;
1241
    TCGv tmp;
1242

    
1243
    if ((insn & 0x0e000e00) == 0x0c000000) {
1244
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1245
            wrd = insn & 0xf;
1246
            rdlo = (insn >> 12) & 0xf;
1247
            rdhi = (insn >> 16) & 0xf;
1248
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1249
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
1250
                gen_movl_reg_T0(s, rdlo);
1251
                gen_movl_reg_T1(s, rdhi);
1252
            } else {                                        /* TMCRR */
1253
                gen_movl_T0_reg(s, rdlo);
1254
                gen_movl_T1_reg(s, rdhi);
1255
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
1256
                gen_op_iwmmxt_set_mup();
1257
            }
1258
            return 0;
1259
        }
1260

    
1261
        wrd = (insn >> 12) & 0xf;
1262
        if (gen_iwmmxt_address(s, insn))
1263
            return 1;
1264
        if (insn & ARM_CP_RW_BIT) {
1265
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1266
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1267
                tcg_gen_mov_i32(cpu_T[0], tmp);
1268
                dead_tmp(tmp);
1269
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1270
            } else {
1271
                if (insn & (1 << 8))
1272
                    if (insn & (1 << 22))                /* WLDRD */
1273
                        gen_ldst(iwmmxt_ldq, s);
1274
                    else                                /* WLDRW wRd */
1275
                        gen_ldst(iwmmxt_ldl, s);
1276
                else
1277
                    if (insn & (1 << 22))                /* WLDRH */
1278
                        gen_ldst(iwmmxt_ldw, s);
1279
                    else                                /* WLDRB */
1280
                        gen_ldst(iwmmxt_ldb, s);
1281
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1282
            }
1283
        } else {
1284
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1285
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1286
                tmp = new_tmp();
1287
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1288
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1289
            } else {
1290
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1291
                if (insn & (1 << 8))
1292
                    if (insn & (1 << 22))                /* WSTRD */
1293
                        gen_ldst(iwmmxt_stq, s);
1294
                    else                                /* WSTRW wRd */
1295
                        gen_ldst(iwmmxt_stl, s);
1296
                else
1297
                    if (insn & (1 << 22))                /* WSTRH */
1298
                        gen_ldst(iwmmxt_ldw, s);
1299
                    else                                /* WSTRB */
1300
                        gen_ldst(iwmmxt_stb, s);
1301
            }
1302
        }
1303
        return 0;
1304
    }
1305

    
1306
    if ((insn & 0x0f000000) != 0x0e000000)
1307
        return 1;
1308

    
1309
    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1310
    case 0x000:                                                /* WOR */
1311
        wrd = (insn >> 12) & 0xf;
1312
        rd0 = (insn >> 0) & 0xf;
1313
        rd1 = (insn >> 16) & 0xf;
1314
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1315
        gen_op_iwmmxt_orq_M0_wRn(rd1);
1316
        gen_op_iwmmxt_setpsr_nz();
1317
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1318
        gen_op_iwmmxt_set_mup();
1319
        gen_op_iwmmxt_set_cup();
1320
        break;
1321
    case 0x011:                                                /* TMCR */
1322
        if (insn & 0xf)
1323
            return 1;
1324
        rd = (insn >> 12) & 0xf;
1325
        wrd = (insn >> 16) & 0xf;
1326
        switch (wrd) {
1327
        case ARM_IWMMXT_wCID:
1328
        case ARM_IWMMXT_wCASF:
1329
            break;
1330
        case ARM_IWMMXT_wCon:
1331
            gen_op_iwmmxt_set_cup();
1332
            /* Fall through.  */
1333
        case ARM_IWMMXT_wCSSF:
1334
            gen_op_iwmmxt_movl_T0_wCx(wrd);
1335
            gen_movl_T1_reg(s, rd);
1336
            gen_op_bicl_T0_T1();
1337
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1338
            break;
1339
        case ARM_IWMMXT_wCGR0:
1340
        case ARM_IWMMXT_wCGR1:
1341
        case ARM_IWMMXT_wCGR2:
1342
        case ARM_IWMMXT_wCGR3:
1343
            gen_op_iwmmxt_set_cup();
1344
            gen_movl_reg_T0(s, rd);
1345
            gen_op_iwmmxt_movl_wCx_T0(wrd);
1346
            break;
1347
        default:
1348
            return 1;
1349
        }
1350
        break;
1351
    case 0x100:                                                /* WXOR */
1352
        wrd = (insn >> 12) & 0xf;
1353
        rd0 = (insn >> 0) & 0xf;
1354
        rd1 = (insn >> 16) & 0xf;
1355
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1356
        gen_op_iwmmxt_xorq_M0_wRn(rd1);
1357
        gen_op_iwmmxt_setpsr_nz();
1358
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1359
        gen_op_iwmmxt_set_mup();
1360
        gen_op_iwmmxt_set_cup();
1361
        break;
1362
    case 0x111:                                                /* TMRC */
1363
        if (insn & 0xf)
1364
            return 1;
1365
        rd = (insn >> 12) & 0xf;
1366
        wrd = (insn >> 16) & 0xf;
1367
        gen_op_iwmmxt_movl_T0_wCx(wrd);
1368
        gen_movl_reg_T0(s, rd);
1369
        break;
1370
    case 0x300:                                                /* WANDN */
1371
        wrd = (insn >> 12) & 0xf;
1372
        rd0 = (insn >> 0) & 0xf;
1373
        rd1 = (insn >> 16) & 0xf;
1374
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1375
        gen_op_iwmmxt_negq_M0();
1376
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1377
        gen_op_iwmmxt_setpsr_nz();
1378
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1379
        gen_op_iwmmxt_set_mup();
1380
        gen_op_iwmmxt_set_cup();
1381
        break;
1382
    case 0x200:                                                /* WAND */
1383
        wrd = (insn >> 12) & 0xf;
1384
        rd0 = (insn >> 0) & 0xf;
1385
        rd1 = (insn >> 16) & 0xf;
1386
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1387
        gen_op_iwmmxt_andq_M0_wRn(rd1);
1388
        gen_op_iwmmxt_setpsr_nz();
1389
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1390
        gen_op_iwmmxt_set_mup();
1391
        gen_op_iwmmxt_set_cup();
1392
        break;
1393
    case 0x810: case 0xa10:                                /* WMADD */
1394
        wrd = (insn >> 12) & 0xf;
1395
        rd0 = (insn >> 0) & 0xf;
1396
        rd1 = (insn >> 16) & 0xf;
1397
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1398
        if (insn & (1 << 21))
1399
            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1400
        else
1401
            gen_op_iwmmxt_madduq_M0_wRn(rd1);
1402
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1403
        gen_op_iwmmxt_set_mup();
1404
        break;
1405
    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:        /* WUNPCKIL */
1406
        wrd = (insn >> 12) & 0xf;
1407
        rd0 = (insn >> 16) & 0xf;
1408
        rd1 = (insn >> 0) & 0xf;
1409
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1410
        switch ((insn >> 22) & 3) {
1411
        case 0:
1412
            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1413
            break;
1414
        case 1:
1415
            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1416
            break;
1417
        case 2:
1418
            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1419
            break;
1420
        case 3:
1421
            return 1;
1422
        }
1423
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1424
        gen_op_iwmmxt_set_mup();
1425
        gen_op_iwmmxt_set_cup();
1426
        break;
1427
    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:        /* WUNPCKIH */
1428
        wrd = (insn >> 12) & 0xf;
1429
        rd0 = (insn >> 16) & 0xf;
1430
        rd1 = (insn >> 0) & 0xf;
1431
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1432
        switch ((insn >> 22) & 3) {
1433
        case 0:
1434
            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1435
            break;
1436
        case 1:
1437
            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1438
            break;
1439
        case 2:
1440
            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1441
            break;
1442
        case 3:
1443
            return 1;
1444
        }
1445
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1446
        gen_op_iwmmxt_set_mup();
1447
        gen_op_iwmmxt_set_cup();
1448
        break;
1449
    case 0x012: case 0x112: case 0x412: case 0x512:        /* WSAD */
1450
        wrd = (insn >> 12) & 0xf;
1451
        rd0 = (insn >> 16) & 0xf;
1452
        rd1 = (insn >> 0) & 0xf;
1453
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1454
        if (insn & (1 << 22))
1455
            gen_op_iwmmxt_sadw_M0_wRn(rd1);
1456
        else
1457
            gen_op_iwmmxt_sadb_M0_wRn(rd1);
1458
        if (!(insn & (1 << 20)))
1459
            gen_op_iwmmxt_addl_M0_wRn(wrd);
1460
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1461
        gen_op_iwmmxt_set_mup();
1462
        break;
1463
    case 0x010: case 0x110: case 0x210: case 0x310:        /* WMUL */
1464
        wrd = (insn >> 12) & 0xf;
1465
        rd0 = (insn >> 16) & 0xf;
1466
        rd1 = (insn >> 0) & 0xf;
1467
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1468
        if (insn & (1 << 21))
1469
            gen_op_iwmmxt_mulsw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1470
        else
1471
            gen_op_iwmmxt_muluw_M0_wRn(rd1, (insn & (1 << 20)) ? 16 : 0);
1472
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1473
        gen_op_iwmmxt_set_mup();
1474
        break;
1475
    case 0x410: case 0x510: case 0x610: case 0x710:        /* WMAC */
1476
        wrd = (insn >> 12) & 0xf;
1477
        rd0 = (insn >> 16) & 0xf;
1478
        rd1 = (insn >> 0) & 0xf;
1479
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1480
        if (insn & (1 << 21))
1481
            gen_op_iwmmxt_macsw_M0_wRn(rd1);
1482
        else
1483
            gen_op_iwmmxt_macuw_M0_wRn(rd1);
1484
        if (!(insn & (1 << 20))) {
1485
            if (insn & (1 << 21))
1486
                gen_op_iwmmxt_addsq_M0_wRn(wrd);
1487
            else
1488
                gen_op_iwmmxt_adduq_M0_wRn(wrd);
1489
        }
1490
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1491
        gen_op_iwmmxt_set_mup();
1492
        break;
1493
    case 0x006: case 0x406: case 0x806: case 0xc06:        /* WCMPEQ */
1494
        wrd = (insn >> 12) & 0xf;
1495
        rd0 = (insn >> 16) & 0xf;
1496
        rd1 = (insn >> 0) & 0xf;
1497
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1498
        switch ((insn >> 22) & 3) {
1499
        case 0:
1500
            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1501
            break;
1502
        case 1:
1503
            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1504
            break;
1505
        case 2:
1506
            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1507
            break;
1508
        case 3:
1509
            return 1;
1510
        }
1511
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1512
        gen_op_iwmmxt_set_mup();
1513
        gen_op_iwmmxt_set_cup();
1514
        break;
1515
    case 0x800: case 0x900: case 0xc00: case 0xd00:        /* WAVG2 */
1516
        wrd = (insn >> 12) & 0xf;
1517
        rd0 = (insn >> 16) & 0xf;
1518
        rd1 = (insn >> 0) & 0xf;
1519
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1520
        if (insn & (1 << 22))
1521
            gen_op_iwmmxt_avgw_M0_wRn(rd1, (insn >> 20) & 1);
1522
        else
1523
            gen_op_iwmmxt_avgb_M0_wRn(rd1, (insn >> 20) & 1);
1524
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1525
        gen_op_iwmmxt_set_mup();
1526
        gen_op_iwmmxt_set_cup();
1527
        break;
1528
    case 0x802: case 0x902: case 0xa02: case 0xb02:        /* WALIGNR */
1529
        wrd = (insn >> 12) & 0xf;
1530
        rd0 = (insn >> 16) & 0xf;
1531
        rd1 = (insn >> 0) & 0xf;
1532
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1533
        gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1534
        gen_op_movl_T1_im(7);
1535
        gen_op_andl_T0_T1();
1536
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1537
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1538
        gen_op_iwmmxt_set_mup();
1539
        break;
1540
    case 0x601: case 0x605: case 0x609: case 0x60d:        /* TINSR */
1541
        rd = (insn >> 12) & 0xf;
1542
        wrd = (insn >> 16) & 0xf;
1543
        gen_movl_T0_reg(s, rd);
1544
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1545
        switch ((insn >> 6) & 3) {
1546
        case 0:
1547
            gen_op_movl_T1_im(0xff);
1548
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 7) << 3);
1549
            break;
1550
        case 1:
1551
            gen_op_movl_T1_im(0xffff);
1552
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 3) << 4);
1553
            break;
1554
        case 2:
1555
            gen_op_movl_T1_im(0xffffffff);
1556
            gen_op_iwmmxt_insr_M0_T0_T1((insn & 1) << 5);
1557
            break;
1558
        case 3:
1559
            return 1;
1560
        }
1561
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1562
        gen_op_iwmmxt_set_mup();
1563
        break;
1564
    case 0x107: case 0x507: case 0x907: case 0xd07:        /* TEXTRM */
1565
        rd = (insn >> 12) & 0xf;
1566
        wrd = (insn >> 16) & 0xf;
1567
        if (rd == 15)
1568
            return 1;
1569
        gen_op_iwmmxt_movq_M0_wRn(wrd);
1570
        switch ((insn >> 22) & 3) {
1571
        case 0:
1572
            if (insn & 8)
1573
                gen_op_iwmmxt_extrsb_T0_M0((insn & 7) << 3);
1574
            else {
1575
                gen_op_movl_T1_im(0xff);
1576
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 7) << 3);
1577
            }
1578
            break;
1579
        case 1:
1580
            if (insn & 8)
1581
                gen_op_iwmmxt_extrsw_T0_M0((insn & 3) << 4);
1582
            else {
1583
                gen_op_movl_T1_im(0xffff);
1584
                gen_op_iwmmxt_extru_T0_M0_T1((insn & 3) << 4);
1585
            }
1586
            break;
1587
        case 2:
1588
            gen_op_movl_T1_im(0xffffffff);
1589
            gen_op_iwmmxt_extru_T0_M0_T1((insn & 1) << 5);
1590
            break;
1591
        case 3:
1592
            return 1;
1593
        }
1594
        gen_movl_reg_T0(s, rd);
1595
        break;
1596
    case 0x117: case 0x517: case 0x917: case 0xd17:        /* TEXTRC */
1597
        if ((insn & 0x000ff008) != 0x0003f000)
1598
            return 1;
1599
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1600
        switch ((insn >> 22) & 3) {
1601
        case 0:
1602
            gen_op_shrl_T1_im(((insn & 7) << 2) + 0);
1603
            break;
1604
        case 1:
1605
            gen_op_shrl_T1_im(((insn & 3) << 3) + 4);
1606
            break;
1607
        case 2:
1608
            gen_op_shrl_T1_im(((insn & 1) << 4) + 12);
1609
            break;
1610
        case 3:
1611
            return 1;
1612
        }
1613
        gen_op_shll_T1_im(28);
1614
        gen_set_nzcv(cpu_T[1]);
1615
        break;
1616
    case 0x401: case 0x405: case 0x409: case 0x40d:        /* TBCST */
1617
        rd = (insn >> 12) & 0xf;
1618
        wrd = (insn >> 16) & 0xf;
1619
        gen_movl_T0_reg(s, rd);
1620
        switch ((insn >> 6) & 3) {
1621
        case 0:
1622
            gen_op_iwmmxt_bcstb_M0_T0();
1623
            break;
1624
        case 1:
1625
            gen_op_iwmmxt_bcstw_M0_T0();
1626
            break;
1627
        case 2:
1628
            gen_op_iwmmxt_bcstl_M0_T0();
1629
            break;
1630
        case 3:
1631
            return 1;
1632
        }
1633
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1634
        gen_op_iwmmxt_set_mup();
1635
        break;
1636
    case 0x113: case 0x513: case 0x913: case 0xd13:        /* TANDC */
1637
        if ((insn & 0x000ff00f) != 0x0003f000)
1638
            return 1;
1639
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1640
        switch ((insn >> 22) & 3) {
1641
        case 0:
1642
            for (i = 0; i < 7; i ++) {
1643
                gen_op_shll_T1_im(4);
1644
                gen_op_andl_T0_T1();
1645
            }
1646
            break;
1647
        case 1:
1648
            for (i = 0; i < 3; i ++) {
1649
                gen_op_shll_T1_im(8);
1650
                gen_op_andl_T0_T1();
1651
            }
1652
            break;
1653
        case 2:
1654
            gen_op_shll_T1_im(16);
1655
            gen_op_andl_T0_T1();
1656
            break;
1657
        case 3:
1658
            return 1;
1659
        }
1660
        gen_set_nzcv(cpu_T[0]);
1661
        break;
1662
    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:        /* WACC */
1663
        wrd = (insn >> 12) & 0xf;
1664
        rd0 = (insn >> 16) & 0xf;
1665
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1666
        switch ((insn >> 22) & 3) {
1667
        case 0:
1668
            gen_op_iwmmxt_addcb_M0();
1669
            break;
1670
        case 1:
1671
            gen_op_iwmmxt_addcw_M0();
1672
            break;
1673
        case 2:
1674
            gen_op_iwmmxt_addcl_M0();
1675
            break;
1676
        case 3:
1677
            return 1;
1678
        }
1679
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1680
        gen_op_iwmmxt_set_mup();
1681
        break;
1682
    case 0x115: case 0x515: case 0x915: case 0xd15:        /* TORC */
1683
        if ((insn & 0x000ff00f) != 0x0003f000)
1684
            return 1;
1685
        gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF);
1686
        switch ((insn >> 22) & 3) {
1687
        case 0:
1688
            for (i = 0; i < 7; i ++) {
1689
                gen_op_shll_T1_im(4);
1690
                gen_op_orl_T0_T1();
1691
            }
1692
            break;
1693
        case 1:
1694
            for (i = 0; i < 3; i ++) {
1695
                gen_op_shll_T1_im(8);
1696
                gen_op_orl_T0_T1();
1697
            }
1698
            break;
1699
        case 2:
1700
            gen_op_shll_T1_im(16);
1701
            gen_op_orl_T0_T1();
1702
            break;
1703
        case 3:
1704
            return 1;
1705
        }
1706
        gen_set_nzcv(cpu_T[0]);
1707
        break;
1708
    case 0x103: case 0x503: case 0x903: case 0xd03:        /* TMOVMSK */
1709
        rd = (insn >> 12) & 0xf;
1710
        rd0 = (insn >> 16) & 0xf;
1711
        if ((insn & 0xf) != 0)
1712
            return 1;
1713
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1714
        switch ((insn >> 22) & 3) {
1715
        case 0:
1716
            gen_op_iwmmxt_msbb_T0_M0();
1717
            break;
1718
        case 1:
1719
            gen_op_iwmmxt_msbw_T0_M0();
1720
            break;
1721
        case 2:
1722
            gen_op_iwmmxt_msbl_T0_M0();
1723
            break;
1724
        case 3:
1725
            return 1;
1726
        }
1727
        gen_movl_reg_T0(s, rd);
1728
        break;
1729
    case 0x106: case 0x306: case 0x506: case 0x706:        /* WCMPGT */
1730
    case 0x906: case 0xb06: case 0xd06: case 0xf06:
1731
        wrd = (insn >> 12) & 0xf;
1732
        rd0 = (insn >> 16) & 0xf;
1733
        rd1 = (insn >> 0) & 0xf;
1734
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1735
        switch ((insn >> 22) & 3) {
1736
        case 0:
1737
            if (insn & (1 << 21))
1738
                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1739
            else
1740
                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1741
            break;
1742
        case 1:
1743
            if (insn & (1 << 21))
1744
                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1745
            else
1746
                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1747
            break;
1748
        case 2:
1749
            if (insn & (1 << 21))
1750
                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1751
            else
1752
                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1753
            break;
1754
        case 3:
1755
            return 1;
1756
        }
1757
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1758
        gen_op_iwmmxt_set_mup();
1759
        gen_op_iwmmxt_set_cup();
1760
        break;
1761
    case 0x00e: case 0x20e: case 0x40e: case 0x60e:        /* WUNPCKEL */
1762
    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1763
        wrd = (insn >> 12) & 0xf;
1764
        rd0 = (insn >> 16) & 0xf;
1765
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1766
        switch ((insn >> 22) & 3) {
1767
        case 0:
1768
            if (insn & (1 << 21))
1769
                gen_op_iwmmxt_unpacklsb_M0();
1770
            else
1771
                gen_op_iwmmxt_unpacklub_M0();
1772
            break;
1773
        case 1:
1774
            if (insn & (1 << 21))
1775
                gen_op_iwmmxt_unpacklsw_M0();
1776
            else
1777
                gen_op_iwmmxt_unpackluw_M0();
1778
            break;
1779
        case 2:
1780
            if (insn & (1 << 21))
1781
                gen_op_iwmmxt_unpacklsl_M0();
1782
            else
1783
                gen_op_iwmmxt_unpacklul_M0();
1784
            break;
1785
        case 3:
1786
            return 1;
1787
        }
1788
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1789
        gen_op_iwmmxt_set_mup();
1790
        gen_op_iwmmxt_set_cup();
1791
        break;
1792
    case 0x00c: case 0x20c: case 0x40c: case 0x60c:        /* WUNPCKEH */
1793
    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1794
        wrd = (insn >> 12) & 0xf;
1795
        rd0 = (insn >> 16) & 0xf;
1796
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1797
        switch ((insn >> 22) & 3) {
1798
        case 0:
1799
            if (insn & (1 << 21))
1800
                gen_op_iwmmxt_unpackhsb_M0();
1801
            else
1802
                gen_op_iwmmxt_unpackhub_M0();
1803
            break;
1804
        case 1:
1805
            if (insn & (1 << 21))
1806
                gen_op_iwmmxt_unpackhsw_M0();
1807
            else
1808
                gen_op_iwmmxt_unpackhuw_M0();
1809
            break;
1810
        case 2:
1811
            if (insn & (1 << 21))
1812
                gen_op_iwmmxt_unpackhsl_M0();
1813
            else
1814
                gen_op_iwmmxt_unpackhul_M0();
1815
            break;
1816
        case 3:
1817
            return 1;
1818
        }
1819
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1820
        gen_op_iwmmxt_set_mup();
1821
        gen_op_iwmmxt_set_cup();
1822
        break;
1823
    case 0x204: case 0x604: case 0xa04: case 0xe04:        /* WSRL */
1824
    case 0x214: case 0x614: case 0xa14: case 0xe14:
1825
        wrd = (insn >> 12) & 0xf;
1826
        rd0 = (insn >> 16) & 0xf;
1827
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1828
        if (gen_iwmmxt_shift(insn, 0xff))
1829
            return 1;
1830
        switch ((insn >> 22) & 3) {
1831
        case 0:
1832
            return 1;
1833
        case 1:
1834
            gen_op_iwmmxt_srlw_M0_T0();
1835
            break;
1836
        case 2:
1837
            gen_op_iwmmxt_srll_M0_T0();
1838
            break;
1839
        case 3:
1840
            gen_op_iwmmxt_srlq_M0_T0();
1841
            break;
1842
        }
1843
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1844
        gen_op_iwmmxt_set_mup();
1845
        gen_op_iwmmxt_set_cup();
1846
        break;
1847
    case 0x004: case 0x404: case 0x804: case 0xc04:        /* WSRA */
1848
    case 0x014: case 0x414: case 0x814: case 0xc14:
1849
        wrd = (insn >> 12) & 0xf;
1850
        rd0 = (insn >> 16) & 0xf;
1851
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1852
        if (gen_iwmmxt_shift(insn, 0xff))
1853
            return 1;
1854
        switch ((insn >> 22) & 3) {
1855
        case 0:
1856
            return 1;
1857
        case 1:
1858
            gen_op_iwmmxt_sraw_M0_T0();
1859
            break;
1860
        case 2:
1861
            gen_op_iwmmxt_sral_M0_T0();
1862
            break;
1863
        case 3:
1864
            gen_op_iwmmxt_sraq_M0_T0();
1865
            break;
1866
        }
1867
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1868
        gen_op_iwmmxt_set_mup();
1869
        gen_op_iwmmxt_set_cup();
1870
        break;
1871
    case 0x104: case 0x504: case 0x904: case 0xd04:        /* WSLL */
1872
    case 0x114: case 0x514: case 0x914: case 0xd14:
1873
        wrd = (insn >> 12) & 0xf;
1874
        rd0 = (insn >> 16) & 0xf;
1875
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1876
        if (gen_iwmmxt_shift(insn, 0xff))
1877
            return 1;
1878
        switch ((insn >> 22) & 3) {
1879
        case 0:
1880
            return 1;
1881
        case 1:
1882
            gen_op_iwmmxt_sllw_M0_T0();
1883
            break;
1884
        case 2:
1885
            gen_op_iwmmxt_slll_M0_T0();
1886
            break;
1887
        case 3:
1888
            gen_op_iwmmxt_sllq_M0_T0();
1889
            break;
1890
        }
1891
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1892
        gen_op_iwmmxt_set_mup();
1893
        gen_op_iwmmxt_set_cup();
1894
        break;
1895
    case 0x304: case 0x704: case 0xb04: case 0xf04:        /* WROR */
1896
    case 0x314: case 0x714: case 0xb14: case 0xf14:
1897
        wrd = (insn >> 12) & 0xf;
1898
        rd0 = (insn >> 16) & 0xf;
1899
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1900
        switch ((insn >> 22) & 3) {
1901
        case 0:
1902
            return 1;
1903
        case 1:
1904
            if (gen_iwmmxt_shift(insn, 0xf))
1905
                return 1;
1906
            gen_op_iwmmxt_rorw_M0_T0();
1907
            break;
1908
        case 2:
1909
            if (gen_iwmmxt_shift(insn, 0x1f))
1910
                return 1;
1911
            gen_op_iwmmxt_rorl_M0_T0();
1912
            break;
1913
        case 3:
1914
            if (gen_iwmmxt_shift(insn, 0x3f))
1915
                return 1;
1916
            gen_op_iwmmxt_rorq_M0_T0();
1917
            break;
1918
        }
1919
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1920
        gen_op_iwmmxt_set_mup();
1921
        gen_op_iwmmxt_set_cup();
1922
        break;
1923
    case 0x116: case 0x316: case 0x516: case 0x716:        /* WMIN */
1924
    case 0x916: case 0xb16: case 0xd16: case 0xf16:
1925
        wrd = (insn >> 12) & 0xf;
1926
        rd0 = (insn >> 16) & 0xf;
1927
        rd1 = (insn >> 0) & 0xf;
1928
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1929
        switch ((insn >> 22) & 3) {
1930
        case 0:
1931
            if (insn & (1 << 21))
1932
                gen_op_iwmmxt_minsb_M0_wRn(rd1);
1933
            else
1934
                gen_op_iwmmxt_minub_M0_wRn(rd1);
1935
            break;
1936
        case 1:
1937
            if (insn & (1 << 21))
1938
                gen_op_iwmmxt_minsw_M0_wRn(rd1);
1939
            else
1940
                gen_op_iwmmxt_minuw_M0_wRn(rd1);
1941
            break;
1942
        case 2:
1943
            if (insn & (1 << 21))
1944
                gen_op_iwmmxt_minsl_M0_wRn(rd1);
1945
            else
1946
                gen_op_iwmmxt_minul_M0_wRn(rd1);
1947
            break;
1948
        case 3:
1949
            return 1;
1950
        }
1951
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1952
        gen_op_iwmmxt_set_mup();
1953
        break;
1954
    case 0x016: case 0x216: case 0x416: case 0x616:        /* WMAX */
1955
    case 0x816: case 0xa16: case 0xc16: case 0xe16:
1956
        wrd = (insn >> 12) & 0xf;
1957
        rd0 = (insn >> 16) & 0xf;
1958
        rd1 = (insn >> 0) & 0xf;
1959
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1960
        switch ((insn >> 22) & 3) {
1961
        case 0:
1962
            if (insn & (1 << 21))
1963
                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
1964
            else
1965
                gen_op_iwmmxt_maxub_M0_wRn(rd1);
1966
            break;
1967
        case 1:
1968
            if (insn & (1 << 21))
1969
                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
1970
            else
1971
                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
1972
            break;
1973
        case 2:
1974
            if (insn & (1 << 21))
1975
                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
1976
            else
1977
                gen_op_iwmmxt_maxul_M0_wRn(rd1);
1978
            break;
1979
        case 3:
1980
            return 1;
1981
        }
1982
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1983
        gen_op_iwmmxt_set_mup();
1984
        break;
1985
    case 0x002: case 0x102: case 0x202: case 0x302:        /* WALIGNI */
1986
    case 0x402: case 0x502: case 0x602: case 0x702:
1987
        wrd = (insn >> 12) & 0xf;
1988
        rd0 = (insn >> 16) & 0xf;
1989
        rd1 = (insn >> 0) & 0xf;
1990
        gen_op_iwmmxt_movq_M0_wRn(rd0);
1991
        gen_op_movl_T0_im((insn >> 20) & 3);
1992
        gen_op_iwmmxt_align_M0_T0_wRn(rd1);
1993
        gen_op_iwmmxt_movq_wRn_M0(wrd);
1994
        gen_op_iwmmxt_set_mup();
1995
        break;
1996
    case 0x01a: case 0x11a: case 0x21a: case 0x31a:        /* WSUB */
1997
    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
1998
    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
1999
    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2000
        wrd = (insn >> 12) & 0xf;
2001
        rd0 = (insn >> 16) & 0xf;
2002
        rd1 = (insn >> 0) & 0xf;
2003
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2004
        switch ((insn >> 20) & 0xf) {
2005
        case 0x0:
2006
            gen_op_iwmmxt_subnb_M0_wRn(rd1);
2007
            break;
2008
        case 0x1:
2009
            gen_op_iwmmxt_subub_M0_wRn(rd1);
2010
            break;
2011
        case 0x3:
2012
            gen_op_iwmmxt_subsb_M0_wRn(rd1);
2013
            break;
2014
        case 0x4:
2015
            gen_op_iwmmxt_subnw_M0_wRn(rd1);
2016
            break;
2017
        case 0x5:
2018
            gen_op_iwmmxt_subuw_M0_wRn(rd1);
2019
            break;
2020
        case 0x7:
2021
            gen_op_iwmmxt_subsw_M0_wRn(rd1);
2022
            break;
2023
        case 0x8:
2024
            gen_op_iwmmxt_subnl_M0_wRn(rd1);
2025
            break;
2026
        case 0x9:
2027
            gen_op_iwmmxt_subul_M0_wRn(rd1);
2028
            break;
2029
        case 0xb:
2030
            gen_op_iwmmxt_subsl_M0_wRn(rd1);
2031
            break;
2032
        default:
2033
            return 1;
2034
        }
2035
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2036
        gen_op_iwmmxt_set_mup();
2037
        gen_op_iwmmxt_set_cup();
2038
        break;
2039
    case 0x01e: case 0x11e: case 0x21e: case 0x31e:        /* WSHUFH */
2040
    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2041
    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2042
    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2043
        wrd = (insn >> 12) & 0xf;
2044
        rd0 = (insn >> 16) & 0xf;
2045
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2046
        gen_op_movl_T0_im(((insn >> 16) & 0xf0) | (insn & 0x0f));
2047
        gen_op_iwmmxt_shufh_M0_T0();
2048
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2049
        gen_op_iwmmxt_set_mup();
2050
        gen_op_iwmmxt_set_cup();
2051
        break;
2052
    case 0x018: case 0x118: case 0x218: case 0x318:        /* WADD */
2053
    case 0x418: case 0x518: case 0x618: case 0x718:
2054
    case 0x818: case 0x918: case 0xa18: case 0xb18:
2055
    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2056
        wrd = (insn >> 12) & 0xf;
2057
        rd0 = (insn >> 16) & 0xf;
2058
        rd1 = (insn >> 0) & 0xf;
2059
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2060
        switch ((insn >> 20) & 0xf) {
2061
        case 0x0:
2062
            gen_op_iwmmxt_addnb_M0_wRn(rd1);
2063
            break;
2064
        case 0x1:
2065
            gen_op_iwmmxt_addub_M0_wRn(rd1);
2066
            break;
2067
        case 0x3:
2068
            gen_op_iwmmxt_addsb_M0_wRn(rd1);
2069
            break;
2070
        case 0x4:
2071
            gen_op_iwmmxt_addnw_M0_wRn(rd1);
2072
            break;
2073
        case 0x5:
2074
            gen_op_iwmmxt_adduw_M0_wRn(rd1);
2075
            break;
2076
        case 0x7:
2077
            gen_op_iwmmxt_addsw_M0_wRn(rd1);
2078
            break;
2079
        case 0x8:
2080
            gen_op_iwmmxt_addnl_M0_wRn(rd1);
2081
            break;
2082
        case 0x9:
2083
            gen_op_iwmmxt_addul_M0_wRn(rd1);
2084
            break;
2085
        case 0xb:
2086
            gen_op_iwmmxt_addsl_M0_wRn(rd1);
2087
            break;
2088
        default:
2089
            return 1;
2090
        }
2091
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2092
        gen_op_iwmmxt_set_mup();
2093
        gen_op_iwmmxt_set_cup();
2094
        break;
2095
    case 0x008: case 0x108: case 0x208: case 0x308:        /* WPACK */
2096
    case 0x408: case 0x508: case 0x608: case 0x708:
2097
    case 0x808: case 0x908: case 0xa08: case 0xb08:
2098
    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2099
        wrd = (insn >> 12) & 0xf;
2100
        rd0 = (insn >> 16) & 0xf;
2101
        rd1 = (insn >> 0) & 0xf;
2102
        gen_op_iwmmxt_movq_M0_wRn(rd0);
2103
        if (!(insn & (1 << 20)))
2104
            return 1;
2105
        switch ((insn >> 22) & 3) {
2106
        case 0:
2107
            return 1;
2108
        case 1:
2109
            if (insn & (1 << 21))
2110
                gen_op_iwmmxt_packsw_M0_wRn(rd1);
2111
            else
2112
                gen_op_iwmmxt_packuw_M0_wRn(rd1);
2113
            break;
2114
        case 2:
2115
            if (insn & (1 << 21))
2116
                gen_op_iwmmxt_packsl_M0_wRn(rd1);
2117
            else
2118
                gen_op_iwmmxt_packul_M0_wRn(rd1);
2119
            break;
2120
        case 3:
2121
            if (insn & (1 << 21))
2122
                gen_op_iwmmxt_packsq_M0_wRn(rd1);
2123
            else
2124
                gen_op_iwmmxt_packuq_M0_wRn(rd1);
2125
            break;
2126
        }
2127
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2128
        gen_op_iwmmxt_set_mup();
2129
        gen_op_iwmmxt_set_cup();
2130
        break;
2131
    case 0x201: case 0x203: case 0x205: case 0x207:
2132
    case 0x209: case 0x20b: case 0x20d: case 0x20f:
2133
    case 0x211: case 0x213: case 0x215: case 0x217:
2134
    case 0x219: case 0x21b: case 0x21d: case 0x21f:
2135
        wrd = (insn >> 5) & 0xf;
2136
        rd0 = (insn >> 12) & 0xf;
2137
        rd1 = (insn >> 0) & 0xf;
2138
        if (rd0 == 0xf || rd1 == 0xf)
2139
            return 1;
2140
        gen_op_iwmmxt_movq_M0_wRn(wrd);
2141
        switch ((insn >> 16) & 0xf) {
2142
        case 0x0:                                        /* TMIA */
2143
            gen_movl_T0_reg(s, rd0);
2144
            gen_movl_T1_reg(s, rd1);
2145
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2146
            break;
2147
        case 0x8:                                        /* TMIAPH */
2148
            gen_movl_T0_reg(s, rd0);
2149
            gen_movl_T1_reg(s, rd1);
2150
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2151
            break;
2152
        case 0xc: case 0xd: case 0xe: case 0xf:                /* TMIAxy */
2153
            gen_movl_T1_reg(s, rd0);
2154
            if (insn & (1 << 16))
2155
                gen_op_shrl_T1_im(16);
2156
            gen_op_movl_T0_T1();
2157
            gen_movl_T1_reg(s, rd1);
2158
            if (insn & (1 << 17))
2159
                gen_op_shrl_T1_im(16);
2160
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2161
            break;
2162
        default:
2163
            return 1;
2164
        }
2165
        gen_op_iwmmxt_movq_wRn_M0(wrd);
2166
        gen_op_iwmmxt_set_mup();
2167
        break;
2168
    default:
2169
        return 1;
2170
    }
2171

    
2172
    return 0;
2173
}
2174

    
2175
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2176
   (ie. an undefined instruction).  */
2177
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2178
{
2179
    int acc, rd0, rd1, rdhi, rdlo;
2180

    
2181
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2182
        /* Multiply with Internal Accumulate Format */
2183
        rd0 = (insn >> 12) & 0xf;
2184
        rd1 = insn & 0xf;
2185
        acc = (insn >> 5) & 7;
2186

    
2187
        if (acc != 0)
2188
            return 1;
2189

    
2190
        switch ((insn >> 16) & 0xf) {
2191
        case 0x0:                                        /* MIA */
2192
            gen_movl_T0_reg(s, rd0);
2193
            gen_movl_T1_reg(s, rd1);
2194
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2195
            break;
2196
        case 0x8:                                        /* MIAPH */
2197
            gen_movl_T0_reg(s, rd0);
2198
            gen_movl_T1_reg(s, rd1);
2199
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2200
            break;
2201
        case 0xc:                                        /* MIABB */
2202
        case 0xd:                                        /* MIABT */
2203
        case 0xe:                                        /* MIATB */
2204
        case 0xf:                                        /* MIATT */
2205
            gen_movl_T1_reg(s, rd0);
2206
            if (insn & (1 << 16))
2207
                gen_op_shrl_T1_im(16);
2208
            gen_op_movl_T0_T1();
2209
            gen_movl_T1_reg(s, rd1);
2210
            if (insn & (1 << 17))
2211
                gen_op_shrl_T1_im(16);
2212
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2213
            break;
2214
        default:
2215
            return 1;
2216
        }
2217

    
2218
        gen_op_iwmmxt_movq_wRn_M0(acc);
2219
        return 0;
2220
    }
2221

    
2222
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2223
        /* Internal Accumulator Access Format */
2224
        rdhi = (insn >> 16) & 0xf;
2225
        rdlo = (insn >> 12) & 0xf;
2226
        acc = insn & 7;
2227

    
2228
        if (acc != 0)
2229
            return 1;
2230

    
2231
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2232
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
2233
            gen_movl_reg_T0(s, rdlo);
2234
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2235
            gen_op_andl_T0_T1();
2236
            gen_movl_reg_T0(s, rdhi);
2237
        } else {                                        /* MAR */
2238
            gen_movl_T0_reg(s, rdlo);
2239
            gen_movl_T1_reg(s, rdhi);
2240
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
2241
        }
2242
        return 0;
2243
    }
2244

    
2245
    return 1;
2246
}
2247

    
2248
/* Disassemble system coprocessor instruction.  Return nonzero if
2249
   instruction is not defined.  */
2250
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2251
{
2252
    uint32_t rd = (insn >> 12) & 0xf;
2253
    uint32_t cp = (insn >> 8) & 0xf;
2254
    if (IS_USER(s)) {
2255
        return 1;
2256
    }
2257

    
2258
    if (insn & ARM_CP_RW_BIT) {
2259
        if (!env->cp[cp].cp_read)
2260
            return 1;
2261
        gen_op_movl_T0_im((uint32_t) s->pc);
2262
        gen_set_pc_T0();
2263
        gen_op_movl_T0_cp(insn);
2264
        gen_movl_reg_T0(s, rd);
2265
    } else {
2266
        if (!env->cp[cp].cp_write)
2267
            return 1;
2268
        gen_op_movl_T0_im((uint32_t) s->pc);
2269
        gen_set_pc_T0();
2270
        gen_movl_T0_reg(s, rd);
2271
        gen_op_movl_cp_T0(insn);
2272
    }
2273
    return 0;
2274
}
2275

    
2276
static int cp15_user_ok(uint32_t insn)
2277
{
2278
    int cpn = (insn >> 16) & 0xf;
2279
    int cpm = insn & 0xf;
2280
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2281

    
2282
    if (cpn == 13 && cpm == 0) {
2283
        /* TLS register.  */
2284
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2285
            return 1;
2286
    }
2287
    if (cpn == 7) {
2288
        /* ISB, DSB, DMB.  */
2289
        if ((cpm == 5 && op == 4)
2290
                || (cpm == 10 && (op == 4 || op == 5)))
2291
            return 1;
2292
    }
2293
    return 0;
2294
}
2295

    
2296
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2297
   instruction is not defined.  */
2298
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2299
{
2300
    uint32_t rd;
2301

    
2302
    /* M profile cores use memory mapped registers instead of cp15.  */
2303
    if (arm_feature(env, ARM_FEATURE_M))
2304
        return 1;
2305

    
2306
    if ((insn & (1 << 25)) == 0) {
2307
        if (insn & (1 << 20)) {
2308
            /* mrrc */
2309
            return 1;
2310
        }
2311
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2312
        return 0;
2313
    }
2314
    if ((insn & (1 << 4)) == 0) {
2315
        /* cdp */
2316
        return 1;
2317
    }
2318
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2319
        return 1;
2320
    }
2321
    if ((insn & 0x0fff0fff) == 0x0e070f90
2322
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2323
        /* Wait for interrupt.  */
2324
        gen_op_movl_T0_im((long)s->pc);
2325
        gen_set_pc_T0();
2326
        s->is_jmp = DISAS_WFI;
2327
        return 0;
2328
    }
2329
    rd = (insn >> 12) & 0xf;
2330
    if (insn & ARM_CP_RW_BIT) {
2331
        gen_op_movl_T0_cp15(insn);
2332
        /* If the destination register is r15 then sets condition codes.  */
2333
        if (rd != 15)
2334
            gen_movl_reg_T0(s, rd);
2335
    } else {
2336
        gen_movl_T0_reg(s, rd);
2337
        gen_op_movl_cp15_T0(insn);
2338
        /* Normally we would always end the TB here, but Linux
2339
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2340
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2341
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2342
                (insn & 0x0fff0fff) != 0x0e010f10)
2343
            gen_lookup_tb(s);
2344
    }
2345
    return 0;
2346
}
2347

    
2348
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2349
#define VFP_SREG(insn, bigbit, smallbit) \
2350
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2351
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2352
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2353
        reg = (((insn) >> (bigbit)) & 0x0f) \
2354
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2355
    } else { \
2356
        if (insn & (1 << (smallbit))) \
2357
            return 1; \
2358
        reg = ((insn) >> (bigbit)) & 0x0f; \
2359
    }} while (0)
2360

    
2361
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2362
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2363
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2364
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2365
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2366
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2367

    
2368
/* Move between integer and VFP cores.  */
2369
static TCGv gen_vfp_mrs(void)
2370
{
2371
    TCGv tmp = new_tmp();
2372
    tcg_gen_mov_i32(tmp, cpu_F0s);
2373
    return tmp;
2374
}
2375

    
2376
static void gen_vfp_msr(TCGv tmp)
2377
{
2378
    tcg_gen_mov_i32(cpu_F0s, tmp);
2379
    dead_tmp(tmp);
2380
}
2381

    
2382
static inline int
2383
vfp_enabled(CPUState * env)
2384
{
2385
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2386
}
2387

    
2388
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2389
   (ie. an undefined instruction).  */
2390
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2391
{
2392
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2393
    int dp, veclen;
2394
    TCGv tmp;
2395

    
2396
    if (!arm_feature(env, ARM_FEATURE_VFP))
2397
        return 1;
2398

    
2399
    if (!vfp_enabled(env)) {
2400
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2401
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2402
            return 1;
2403
        rn = (insn >> 16) & 0xf;
2404
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2405
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2406
            return 1;
2407
    }
2408
    dp = ((insn & 0xf00) == 0xb00);
2409
    switch ((insn >> 24) & 0xf) {
2410
    case 0xe:
2411
        if (insn & (1 << 4)) {
2412
            /* single register transfer */
2413
            rd = (insn >> 12) & 0xf;
2414
            if (dp) {
2415
                int size;
2416
                int pass;
2417

    
2418
                VFP_DREG_N(rn, insn);
2419
                if (insn & 0xf)
2420
                    return 1;
2421
                if (insn & 0x00c00060
2422
                    && !arm_feature(env, ARM_FEATURE_NEON))
2423
                    return 1;
2424

    
2425
                pass = (insn >> 21) & 1;
2426
                if (insn & (1 << 22)) {
2427
                    size = 0;
2428
                    offset = ((insn >> 5) & 3) * 8;
2429
                } else if (insn & (1 << 5)) {
2430
                    size = 1;
2431
                    offset = (insn & (1 << 6)) ? 16 : 0;
2432
                } else {
2433
                    size = 2;
2434
                    offset = 0;
2435
                }
2436
                if (insn & ARM_CP_RW_BIT) {
2437
                    /* vfp->arm */
2438
                    switch (size) {
2439
                    case 0:
2440
                        NEON_GET_REG(T1, rn, pass);
2441
                        if (offset)
2442
                            gen_op_shrl_T1_im(offset);
2443
                        if (insn & (1 << 23))
2444
                            gen_uxtb(cpu_T[1]);
2445
                        else
2446
                            gen_sxtb(cpu_T[1]);
2447
                        break;
2448
                    case 1:
2449
                        NEON_GET_REG(T1, rn, pass);
2450
                        if (insn & (1 << 23)) {
2451
                            if (offset) {
2452
                                gen_op_shrl_T1_im(16);
2453
                            } else {
2454
                                gen_uxth(cpu_T[1]);
2455
                            }
2456
                        } else {
2457
                            if (offset) {
2458
                                gen_op_sarl_T1_im(16);
2459
                            } else {
2460
                                gen_sxth(cpu_T[1]);
2461
                            }
2462
                        }
2463
                        break;
2464
                    case 2:
2465
                        NEON_GET_REG(T1, rn, pass);
2466
                        break;
2467
                    }
2468
                    gen_movl_reg_T1(s, rd);
2469
                } else {
2470
                    /* arm->vfp */
2471
                    gen_movl_T0_reg(s, rd);
2472
                    if (insn & (1 << 23)) {
2473
                        /* VDUP */
2474
                        if (size == 0) {
2475
                            gen_op_neon_dup_u8(0);
2476
                        } else if (size == 1) {
2477
                            gen_op_neon_dup_low16();
2478
                        }
2479
                        NEON_SET_REG(T0, rn, 0);
2480
                        NEON_SET_REG(T0, rn, 1);
2481
                    } else {
2482
                        /* VMOV */
2483
                        switch (size) {
2484
                        case 0:
2485
                            NEON_GET_REG(T2, rn, pass);
2486
                            gen_op_movl_T1_im(0xff);
2487
                            gen_op_andl_T0_T1();
2488
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
2489
                            NEON_SET_REG(T2, rn, pass);
2490
                            break;
2491
                        case 1:
2492
                            NEON_GET_REG(T2, rn, pass);
2493
                            gen_op_movl_T1_im(0xffff);
2494
                            gen_op_andl_T0_T1();
2495
                            bank_mask = offset ? 0xffff : 0xffff0000;
2496
                            gen_op_neon_insert_elt(offset, bank_mask);
2497
                            NEON_SET_REG(T2, rn, pass);
2498
                            break;
2499
                        case 2:
2500
                            NEON_SET_REG(T0, rn, pass);
2501
                            break;
2502
                        }
2503
                    }
2504
                }
2505
            } else { /* !dp */
2506
                if ((insn & 0x6f) != 0x00)
2507
                    return 1;
2508
                rn = VFP_SREG_N(insn);
2509
                if (insn & ARM_CP_RW_BIT) {
2510
                    /* vfp->arm */
2511
                    if (insn & (1 << 21)) {
2512
                        /* system register */
2513
                        rn >>= 1;
2514

    
2515
                        switch (rn) {
2516
                        case ARM_VFP_FPSID:
2517
                            /* VFP2 allows access to FSID from userspace.
2518
                               VFP3 restricts all id registers to privileged
2519
                               accesses.  */
2520
                            if (IS_USER(s)
2521
                                && arm_feature(env, ARM_FEATURE_VFP3))
2522
                                return 1;
2523
                            tmp = load_cpu_field(vfp.xregs[rn]);
2524
                            break;
2525
                        case ARM_VFP_FPEXC:
2526
                            if (IS_USER(s))
2527
                                return 1;
2528
                            tmp = load_cpu_field(vfp.xregs[rn]);
2529
                            break;
2530
                        case ARM_VFP_FPINST:
2531
                        case ARM_VFP_FPINST2:
2532
                            /* Not present in VFP3.  */
2533
                            if (IS_USER(s)
2534
                                || arm_feature(env, ARM_FEATURE_VFP3))
2535
                                return 1;
2536
                            tmp = load_cpu_field(vfp.xregs[rn]);
2537
                            break;
2538
                        case ARM_VFP_FPSCR:
2539
                            if (rd == 15) {
2540
                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2541
                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2542
                            } else {
2543
                                tmp = new_tmp();
2544
                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
2545
                            }
2546
                            break;
2547
                        case ARM_VFP_MVFR0:
2548
                        case ARM_VFP_MVFR1:
2549
                            if (IS_USER(s)
2550
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2551
                                return 1;
2552
                            tmp = load_cpu_field(vfp.xregs[rn]);
2553
                            break;
2554
                        default:
2555
                            return 1;
2556
                        }
2557
                    } else {
2558
                        gen_mov_F0_vreg(0, rn);
2559
                        tmp = gen_vfp_mrs();
2560
                    }
2561
                    if (rd == 15) {
2562
                        /* Set the 4 flag bits in the CPSR.  */
2563
                        gen_set_nzcv(tmp);
2564
                        dead_tmp(tmp);
2565
                    } else {
2566
                        store_reg(s, rd, tmp);
2567
                    }
2568
                } else {
2569
                    /* arm->vfp */
2570
                    tmp = load_reg(s, rd);
2571
                    if (insn & (1 << 21)) {
2572
                        rn >>= 1;
2573
                        /* system register */
2574
                        switch (rn) {
2575
                        case ARM_VFP_FPSID:
2576
                        case ARM_VFP_MVFR0:
2577
                        case ARM_VFP_MVFR1:
2578
                            /* Writes are ignored.  */
2579
                            break;
2580
                        case ARM_VFP_FPSCR:
2581
                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
2582
                            dead_tmp(tmp);
2583
                            gen_lookup_tb(s);
2584
                            break;
2585
                        case ARM_VFP_FPEXC:
2586
                            if (IS_USER(s))
2587
                                return 1;
2588
                            store_cpu_field(tmp, vfp.xregs[rn]);
2589
                            gen_lookup_tb(s);
2590
                            break;
2591
                        case ARM_VFP_FPINST:
2592
                        case ARM_VFP_FPINST2:
2593
                            store_cpu_field(tmp, vfp.xregs[rn]);
2594
                            break;
2595
                        default:
2596
                            return 1;
2597
                        }
2598
                    } else {
2599
                        gen_vfp_msr(tmp);
2600
                        gen_mov_vreg_F0(0, rn);
2601
                    }
2602
                }
2603
            }
2604
        } else {
2605
            /* data processing */
2606
            /* The opcode is in bits 23, 21, 20 and 6.  */
2607
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2608
            if (dp) {
2609
                if (op == 15) {
2610
                    /* rn is opcode */
2611
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2612
                } else {
2613
                    /* rn is register number */
2614
                    VFP_DREG_N(rn, insn);
2615
                }
2616

    
2617
                if (op == 15 && (rn == 15 || rn > 17)) {
2618
                    /* Integer or single precision destination.  */
2619
                    rd = VFP_SREG_D(insn);
2620
                } else {
2621
                    VFP_DREG_D(rd, insn);
2622
                }
2623

    
2624
                if (op == 15 && (rn == 16 || rn == 17)) {
2625
                    /* Integer source.  */
2626
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2627
                } else {
2628
                    VFP_DREG_M(rm, insn);
2629
                }
2630
            } else {
2631
                rn = VFP_SREG_N(insn);
2632
                if (op == 15 && rn == 15) {
2633
                    /* Double precision destination.  */
2634
                    VFP_DREG_D(rd, insn);
2635
                } else {
2636
                    rd = VFP_SREG_D(insn);
2637
                }
2638
                rm = VFP_SREG_M(insn);
2639
            }
2640

    
2641
            veclen = env->vfp.vec_len;
2642
            if (op == 15 && rn > 3)
2643
                veclen = 0;
2644

    
2645
            /* Shut up compiler warnings.  */
2646
            delta_m = 0;
2647
            delta_d = 0;
2648
            bank_mask = 0;
2649

    
2650
            if (veclen > 0) {
2651
                if (dp)
2652
                    bank_mask = 0xc;
2653
                else
2654
                    bank_mask = 0x18;
2655

    
2656
                /* Figure out what type of vector operation this is.  */
2657
                if ((rd & bank_mask) == 0) {
2658
                    /* scalar */
2659
                    veclen = 0;
2660
                } else {
2661
                    if (dp)
2662
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2663
                    else
2664
                        delta_d = env->vfp.vec_stride + 1;
2665

    
2666
                    if ((rm & bank_mask) == 0) {
2667
                        /* mixed scalar/vector */
2668
                        delta_m = 0;
2669
                    } else {
2670
                        /* vector */
2671
                        delta_m = delta_d;
2672
                    }
2673
                }
2674
            }
2675

    
2676
            /* Load the initial operands.  */
2677
            if (op == 15) {
2678
                switch (rn) {
2679
                case 16:
2680
                case 17:
2681
                    /* Integer source */
2682
                    gen_mov_F0_vreg(0, rm);
2683
                    break;
2684
                case 8:
2685
                case 9:
2686
                    /* Compare */
2687
                    gen_mov_F0_vreg(dp, rd);
2688
                    gen_mov_F1_vreg(dp, rm);
2689
                    break;
2690
                case 10:
2691
                case 11:
2692
                    /* Compare with zero */
2693
                    gen_mov_F0_vreg(dp, rd);
2694
                    gen_vfp_F1_ld0(dp);
2695
                    break;
2696
                case 20:
2697
                case 21:
2698
                case 22:
2699
                case 23:
2700
                    /* Source and destination the same.  */
2701
                    gen_mov_F0_vreg(dp, rd);
2702
                    break;
2703
                default:
2704
                    /* One source operand.  */
2705
                    gen_mov_F0_vreg(dp, rm);
2706
                    break;
2707
                }
2708
            } else {
2709
                /* Two source operands.  */
2710
                gen_mov_F0_vreg(dp, rn);
2711
                gen_mov_F1_vreg(dp, rm);
2712
            }
2713

    
2714
            for (;;) {
2715
                /* Perform the calculation.  */
2716
                switch (op) {
2717
                case 0: /* mac: fd + (fn * fm) */
2718
                    gen_vfp_mul(dp);
2719
                    gen_mov_F1_vreg(dp, rd);
2720
                    gen_vfp_add(dp);
2721
                    break;
2722
                case 1: /* nmac: fd - (fn * fm) */
2723
                    gen_vfp_mul(dp);
2724
                    gen_vfp_neg(dp);
2725
                    gen_mov_F1_vreg(dp, rd);
2726
                    gen_vfp_add(dp);
2727
                    break;
2728
                case 2: /* msc: -fd + (fn * fm) */
2729
                    gen_vfp_mul(dp);
2730
                    gen_mov_F1_vreg(dp, rd);
2731
                    gen_vfp_sub(dp);
2732
                    break;
2733
                case 3: /* nmsc: -fd - (fn * fm)  */
2734
                    gen_vfp_mul(dp);
2735
                    gen_mov_F1_vreg(dp, rd);
2736
                    gen_vfp_add(dp);
2737
                    gen_vfp_neg(dp);
2738
                    break;
2739
                case 4: /* mul: fn * fm */
2740
                    gen_vfp_mul(dp);
2741
                    break;
2742
                case 5: /* nmul: -(fn * fm) */
2743
                    gen_vfp_mul(dp);
2744
                    gen_vfp_neg(dp);
2745
                    break;
2746
                case 6: /* add: fn + fm */
2747
                    gen_vfp_add(dp);
2748
                    break;
2749
                case 7: /* sub: fn - fm */
2750
                    gen_vfp_sub(dp);
2751
                    break;
2752
                case 8: /* div: fn / fm */
2753
                    gen_vfp_div(dp);
2754
                    break;
2755
                case 14: /* fconst */
2756
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2757
                      return 1;
2758

    
2759
                    n = (insn << 12) & 0x80000000;
2760
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2761
                    if (dp) {
2762
                        if (i & 0x40)
2763
                            i |= 0x3f80;
2764
                        else
2765
                            i |= 0x4000;
2766
                        n |= i << 16;
2767
                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2768
                    } else {
2769
                        if (i & 0x40)
2770
                            i |= 0x780;
2771
                        else
2772
                            i |= 0x800;
2773
                        n |= i << 19;
2774
                        tcg_gen_movi_i32(cpu_F0d, ((uint64_t)n) << 32);
2775
                    }
2776
                    break;
2777
                case 15: /* extension space */
2778
                    switch (rn) {
2779
                    case 0: /* cpy */
2780
                        /* no-op */
2781
                        break;
2782
                    case 1: /* abs */
2783
                        gen_vfp_abs(dp);
2784
                        break;
2785
                    case 2: /* neg */
2786
                        gen_vfp_neg(dp);
2787
                        break;
2788
                    case 3: /* sqrt */
2789
                        gen_vfp_sqrt(dp);
2790
                        break;
2791
                    case 8: /* cmp */
2792
                        gen_vfp_cmp(dp);
2793
                        break;
2794
                    case 9: /* cmpe */
2795
                        gen_vfp_cmpe(dp);
2796
                        break;
2797
                    case 10: /* cmpz */
2798
                        gen_vfp_cmp(dp);
2799
                        break;
2800
                    case 11: /* cmpez */
2801
                        gen_vfp_F1_ld0(dp);
2802
                        gen_vfp_cmpe(dp);
2803
                        break;
2804
                    case 15: /* single<->double conversion */
2805
                        if (dp)
2806
                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
2807
                        else
2808
                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
2809
                        break;
2810
                    case 16: /* fuito */
2811
                        gen_vfp_uito(dp);
2812
                        break;
2813
                    case 17: /* fsito */
2814
                        gen_vfp_sito(dp);
2815
                        break;
2816
                    case 20: /* fshto */
2817
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2818
                          return 1;
2819
                        gen_vfp_shto(dp, rm);
2820
                        break;
2821
                    case 21: /* fslto */
2822
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2823
                          return 1;
2824
                        gen_vfp_slto(dp, rm);
2825
                        break;
2826
                    case 22: /* fuhto */
2827
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2828
                          return 1;
2829
                        gen_vfp_uhto(dp, rm);
2830
                        break;
2831
                    case 23: /* fulto */
2832
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2833
                          return 1;
2834
                        gen_vfp_ulto(dp, rm);
2835
                        break;
2836
                    case 24: /* ftoui */
2837
                        gen_vfp_toui(dp);
2838
                        break;
2839
                    case 25: /* ftouiz */
2840
                        gen_vfp_touiz(dp);
2841
                        break;
2842
                    case 26: /* ftosi */
2843
                        gen_vfp_tosi(dp);
2844
                        break;
2845
                    case 27: /* ftosiz */
2846
                        gen_vfp_tosiz(dp);
2847
                        break;
2848
                    case 28: /* ftosh */
2849
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2850
                          return 1;
2851
                        gen_vfp_tosh(dp, rm);
2852
                        break;
2853
                    case 29: /* ftosl */
2854
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2855
                          return 1;
2856
                        gen_vfp_tosl(dp, rm);
2857
                        break;
2858
                    case 30: /* ftouh */
2859
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2860
                          return 1;
2861
                        gen_vfp_touh(dp, rm);
2862
                        break;
2863
                    case 31: /* ftoul */
2864
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2865
                          return 1;
2866
                        gen_vfp_toul(dp, rm);
2867
                        break;
2868
                    default: /* undefined */
2869
                        printf ("rn:%d\n", rn);
2870
                        return 1;
2871
                    }
2872
                    break;
2873
                default: /* undefined */
2874
                    printf ("op:%d\n", op);
2875
                    return 1;
2876
                }
2877

    
2878
                /* Write back the result.  */
2879
                if (op == 15 && (rn >= 8 && rn <= 11))
2880
                    ; /* Comparison, do nothing.  */
2881
                else if (op == 15 && rn > 17)
2882
                    /* Integer result.  */
2883
                    gen_mov_vreg_F0(0, rd);
2884
                else if (op == 15 && rn == 15)
2885
                    /* conversion */
2886
                    gen_mov_vreg_F0(!dp, rd);
2887
                else
2888
                    gen_mov_vreg_F0(dp, rd);
2889

    
2890
                /* break out of the loop if we have finished  */
2891
                if (veclen == 0)
2892
                    break;
2893

    
2894
                if (op == 15 && delta_m == 0) {
2895
                    /* single source one-many */
2896
                    while (veclen--) {
2897
                        rd = ((rd + delta_d) & (bank_mask - 1))
2898
                             | (rd & bank_mask);
2899
                        gen_mov_vreg_F0(dp, rd);
2900
                    }
2901
                    break;
2902
                }
2903
                /* Setup the next operands.  */
2904
                veclen--;
2905
                rd = ((rd + delta_d) & (bank_mask - 1))
2906
                     | (rd & bank_mask);
2907

    
2908
                if (op == 15) {
2909
                    /* One source operand.  */
2910
                    rm = ((rm + delta_m) & (bank_mask - 1))
2911
                         | (rm & bank_mask);
2912
                    gen_mov_F0_vreg(dp, rm);
2913
                } else {
2914
                    /* Two source operands.  */
2915
                    rn = ((rn + delta_d) & (bank_mask - 1))
2916
                         | (rn & bank_mask);
2917
                    gen_mov_F0_vreg(dp, rn);
2918
                    if (delta_m) {
2919
                        rm = ((rm + delta_m) & (bank_mask - 1))
2920
                             | (rm & bank_mask);
2921
                        gen_mov_F1_vreg(dp, rm);
2922
                    }
2923
                }
2924
            }
2925
        }
2926
        break;
2927
    case 0xc:
2928
    case 0xd:
2929
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2930
            /* two-register transfer */
2931
            rn = (insn >> 16) & 0xf;
2932
            rd = (insn >> 12) & 0xf;
2933
            if (dp) {
2934
                VFP_DREG_M(rm, insn);
2935
            } else {
2936
                rm = VFP_SREG_M(insn);
2937
            }
2938

    
2939
            if (insn & ARM_CP_RW_BIT) {
2940
                /* vfp->arm */
2941
                if (dp) {
2942
                    gen_mov_F0_vreg(0, rm * 2);
2943
                    tmp = gen_vfp_mrs();
2944
                    store_reg(s, rd, tmp);
2945
                    gen_mov_F0_vreg(0, rm * 2 + 1);
2946
                    tmp = gen_vfp_mrs();
2947
                    store_reg(s, rn, tmp);
2948
                } else {
2949
                    gen_mov_F0_vreg(0, rm);
2950
                    tmp = gen_vfp_mrs();
2951
                    store_reg(s, rn, tmp);
2952
                    gen_mov_F0_vreg(0, rm + 1);
2953
                    tmp = gen_vfp_mrs();
2954
                    store_reg(s, rd, tmp);
2955
                }
2956
            } else {
2957
                /* arm->vfp */
2958
                if (dp) {
2959
                    tmp = load_reg(s, rd);
2960
                    gen_vfp_msr(tmp);
2961
                    gen_mov_vreg_F0(0, rm * 2);
2962
                    tmp = load_reg(s, rn);
2963
                    gen_vfp_msr(tmp);
2964
                    gen_mov_vreg_F0(0, rm * 2 + 1);
2965
                } else {
2966
                    tmp = load_reg(s, rn);
2967
                    gen_vfp_msr(tmp);
2968
                    gen_mov_vreg_F0(0, rm);
2969
                    tmp = load_reg(s, rd);
2970
                    gen_vfp_msr(tmp);
2971
                    gen_mov_vreg_F0(0, rm + 1);
2972
                }
2973
            }
2974
        } else {
2975
            /* Load/store */
2976
            rn = (insn >> 16) & 0xf;
2977
            if (dp)
2978
                VFP_DREG_D(rd, insn);
2979
            else
2980
                rd = VFP_SREG_D(insn);
2981
            if (s->thumb && rn == 15) {
2982
                gen_op_movl_T1_im(s->pc & ~2);
2983
            } else {
2984
                gen_movl_T1_reg(s, rn);
2985
            }
2986
            if ((insn & 0x01200000) == 0x01000000) {
2987
                /* Single load/store */
2988
                offset = (insn & 0xff) << 2;
2989
                if ((insn & (1 << 23)) == 0)
2990
                    offset = -offset;
2991
                gen_op_addl_T1_im(offset);
2992
                if (insn & (1 << 20)) {
2993
                    gen_vfp_ld(s, dp);
2994
                    gen_mov_vreg_F0(dp, rd);
2995
                } else {
2996
                    gen_mov_F0_vreg(dp, rd);
2997
                    gen_vfp_st(s, dp);
2998
                }
2999
            } else {
3000
                /* load/store multiple */
3001
                if (dp)
3002
                    n = (insn >> 1) & 0x7f;
3003
                else
3004
                    n = insn & 0xff;
3005

    
3006
                if (insn & (1 << 24)) /* pre-decrement */
3007
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3008

    
3009
                if (dp)
3010
                    offset = 8;
3011
                else
3012
                    offset = 4;
3013
                for (i = 0; i < n; i++) {
3014
                    if (insn & ARM_CP_RW_BIT) {
3015
                        /* load */
3016
                        gen_vfp_ld(s, dp);
3017
                        gen_mov_vreg_F0(dp, rd + i);
3018
                    } else {
3019
                        /* store */
3020
                        gen_mov_F0_vreg(dp, rd + i);
3021
                        gen_vfp_st(s, dp);
3022
                    }
3023
                    gen_op_addl_T1_im(offset);
3024
                }
3025
                if (insn & (1 << 21)) {
3026
                    /* writeback */
3027
                    if (insn & (1 << 24))
3028
                        offset = -offset * n;
3029
                    else if (dp && (insn & 1))
3030
                        offset = 4;
3031
                    else
3032
                        offset = 0;
3033

    
3034
                    if (offset != 0)
3035
                        gen_op_addl_T1_im(offset);
3036
                    gen_movl_reg_T1(s, rn);
3037
                }
3038
            }
3039
        }
3040
        break;
3041
    default:
3042
        /* Should never happen.  */
3043
        return 1;
3044
    }
3045
    return 0;
3046
}
3047

    
3048
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3049
{
3050
    TranslationBlock *tb;
3051

    
3052
    tb = s->tb;
3053
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3054
        tcg_gen_goto_tb(n);
3055
        gen_op_movl_T0_im(dest);
3056
        gen_set_pc_T0();
3057
        tcg_gen_exit_tb((long)tb + n);
3058
    } else {
3059
        gen_op_movl_T0_im(dest);
3060
        gen_set_pc_T0();
3061
        tcg_gen_exit_tb(0);
3062
    }
3063
}
3064

    
3065
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3066
{
3067
    if (__builtin_expect(s->singlestep_enabled, 0)) {
3068
        /* An indirect jump so that we still trigger the debug exception.  */
3069
        if (s->thumb)
3070
            dest |= 1;
3071
        gen_bx_im(s, dest);
3072
    } else {
3073
        gen_goto_tb(s, 0, dest);
3074
        s->is_jmp = DISAS_TB_JUMP;
3075
    }
3076
}
3077

    
3078
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3079
{
3080
    if (x)
3081
        tcg_gen_sari_i32(t0, t0, 16);
3082
    else
3083
        gen_sxth(t0);
3084
    if (y)
3085
        tcg_gen_sari_i32(t1, t1, 16);
3086
    else
3087
        gen_sxth(t1);
3088
    tcg_gen_mul_i32(t0, t0, t1);
3089
}
3090

    
3091
/* Return the mask of PSR bits set by a MSR instruction.  */
3092
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3093
    uint32_t mask;
3094

    
3095
    mask = 0;
3096
    if (flags & (1 << 0))
3097
        mask |= 0xff;
3098
    if (flags & (1 << 1))
3099
        mask |= 0xff00;
3100
    if (flags & (1 << 2))
3101
        mask |= 0xff0000;
3102
    if (flags & (1 << 3))
3103
        mask |= 0xff000000;
3104

    
3105
    /* Mask out undefined bits.  */
3106
    mask &= ~CPSR_RESERVED;
3107
    if (!arm_feature(env, ARM_FEATURE_V6))
3108
        mask &= ~(CPSR_E | CPSR_GE);
3109
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3110
        mask &= ~CPSR_IT;
3111
    /* Mask out execution state bits.  */
3112
    if (!spsr)
3113
        mask &= ~CPSR_EXEC;
3114
    /* Mask out privileged bits.  */
3115
    if (IS_USER(s))
3116
        mask &= CPSR_USER;
3117
    return mask;
3118
}
3119

    
3120
/* Returns nonzero if access to the PSR is not permitted.  */
3121
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3122
{
3123
    TCGv tmp;
3124
    if (spsr) {
3125
        /* ??? This is also undefined in system mode.  */
3126
        if (IS_USER(s))
3127
            return 1;
3128

    
3129
        tmp = load_cpu_field(spsr);
3130
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3131
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3132
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3133
        store_cpu_field(tmp, spsr);
3134
    } else {
3135
        gen_set_cpsr(cpu_T[0], mask);
3136
    }
3137
    gen_lookup_tb(s);
3138
    return 0;
3139
}
3140

    
3141
/* Generate an old-style exception return.  */
3142
static void gen_exception_return(DisasContext *s)
3143
{
3144
    TCGv tmp;
3145
    gen_set_pc_T0();
3146
    tmp = load_cpu_field(spsr);
3147
    gen_set_cpsr(tmp, 0xffffffff);
3148
    dead_tmp(tmp);
3149
    s->is_jmp = DISAS_UPDATE;
3150
}
3151

    
3152
/* Generate a v6 exception return.  Marks both values as dead.  */
3153
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3154
{
3155
    gen_set_cpsr(cpsr, 0xffffffff);
3156
    dead_tmp(cpsr);
3157
    store_reg(s, 15, pc);
3158
    s->is_jmp = DISAS_UPDATE;
3159
}
3160

    
3161
static inline void
3162
gen_set_condexec (DisasContext *s)
3163
{
3164
    if (s->condexec_mask) {
3165
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3166
        TCGv tmp = new_tmp();
3167
        tcg_gen_movi_i32(tmp, val);
3168
        store_cpu_field(tmp, condexec_bits);
3169
    }
3170
}
3171

    
3172
static void gen_nop_hint(DisasContext *s, int val)
3173
{
3174
    switch (val) {
3175
    case 3: /* wfi */
3176
        gen_op_movl_T0_im((long)s->pc);
3177
        gen_set_pc_T0();
3178
        s->is_jmp = DISAS_WFI;
3179
        break;
3180
    case 2: /* wfe */
3181
    case 4: /* sev */
3182
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3183
    default: /* nop */
3184
        break;
3185
    }
3186
}
3187

    
3188
/* Neon shift by constant.  The actual ops are the same as used for variable
3189
   shifts.  [OP][U][SIZE]  */
3190
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
3191
    { /* 0 */ /* VSHR */
3192
      {
3193
        gen_op_neon_shl_u8,
3194
        gen_op_neon_shl_u16,
3195
        gen_op_neon_shl_u32,
3196
        gen_op_neon_shl_u64
3197
      }, {
3198
        gen_op_neon_shl_s8,
3199
        gen_op_neon_shl_s16,
3200
        gen_op_neon_shl_s32,
3201
        gen_op_neon_shl_s64
3202
      }
3203
    }, { /* 1 */ /* VSRA */
3204
      {
3205
        gen_op_neon_shl_u8,
3206
        gen_op_neon_shl_u16,
3207
        gen_op_neon_shl_u32,
3208
        gen_op_neon_shl_u64
3209
      }, {
3210
        gen_op_neon_shl_s8,
3211
        gen_op_neon_shl_s16,
3212
        gen_op_neon_shl_s32,
3213
        gen_op_neon_shl_s64
3214
      }
3215
    }, { /* 2 */ /* VRSHR */
3216
      {
3217
        gen_op_neon_rshl_u8,
3218
        gen_op_neon_rshl_u16,
3219
        gen_op_neon_rshl_u32,
3220
        gen_op_neon_rshl_u64
3221
      }, {
3222
        gen_op_neon_rshl_s8,
3223
        gen_op_neon_rshl_s16,
3224
        gen_op_neon_rshl_s32,
3225
        gen_op_neon_rshl_s64
3226
      }
3227
    }, { /* 3 */ /* VRSRA */
3228
      {
3229
        gen_op_neon_rshl_u8,
3230
        gen_op_neon_rshl_u16,
3231
        gen_op_neon_rshl_u32,
3232
        gen_op_neon_rshl_u64
3233
      }, {
3234
        gen_op_neon_rshl_s8,
3235
        gen_op_neon_rshl_s16,
3236
        gen_op_neon_rshl_s32,
3237
        gen_op_neon_rshl_s64
3238
      }
3239
    }, { /* 4 */
3240
      {
3241
        NULL, NULL, NULL, NULL
3242
      }, { /* VSRI */
3243
        gen_op_neon_shl_u8,
3244
        gen_op_neon_shl_u16,
3245
        gen_op_neon_shl_u32,
3246
        gen_op_neon_shl_u64,
3247
      }
3248
    }, { /* 5 */
3249
      { /* VSHL */
3250
        gen_op_neon_shl_u8,
3251
        gen_op_neon_shl_u16,
3252
        gen_op_neon_shl_u32,
3253
        gen_op_neon_shl_u64,
3254
      }, { /* VSLI */
3255
        gen_op_neon_shl_u8,
3256
        gen_op_neon_shl_u16,
3257
        gen_op_neon_shl_u32,
3258
        gen_op_neon_shl_u64,
3259
      }
3260
    }, { /* 6 */ /* VQSHL */
3261
      {
3262
        gen_op_neon_qshl_u8,
3263
        gen_op_neon_qshl_u16,
3264
        gen_op_neon_qshl_u32,
3265
        gen_op_neon_qshl_u64
3266
      }, {
3267
        gen_op_neon_qshl_s8,
3268
        gen_op_neon_qshl_s16,
3269
        gen_op_neon_qshl_s32,
3270
        gen_op_neon_qshl_s64
3271
      }
3272
    }, { /* 7 */ /* VQSHLU */
3273
      {
3274
        gen_op_neon_qshl_u8,
3275
        gen_op_neon_qshl_u16,
3276
        gen_op_neon_qshl_u32,
3277
        gen_op_neon_qshl_u64
3278
      }, {
3279
        gen_op_neon_qshl_u8,
3280
        gen_op_neon_qshl_u16,
3281
        gen_op_neon_qshl_u32,
3282
        gen_op_neon_qshl_u64
3283
      }
3284
    }
3285
};
3286

    
3287
/* [R][U][size - 1] */
3288
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
3289
    {
3290
      {
3291
        gen_op_neon_shl_u16,
3292
        gen_op_neon_shl_u32,
3293
        gen_op_neon_shl_u64
3294
      }, {
3295
        gen_op_neon_shl_s16,
3296
        gen_op_neon_shl_s32,
3297
        gen_op_neon_shl_s64
3298
      }
3299
    }, {
3300
      {
3301
        gen_op_neon_rshl_u16,
3302
        gen_op_neon_rshl_u32,
3303
        gen_op_neon_rshl_u64
3304
      }, {
3305
        gen_op_neon_rshl_s16,
3306
        gen_op_neon_rshl_s32,
3307
        gen_op_neon_rshl_s64
3308
      }
3309
    }
3310
};
3311

    
3312
static inline void
3313
gen_op_neon_narrow_u32 ()
3314
{
3315
    /* No-op.  */
3316
}
3317

    
3318
static GenOpFunc *gen_neon_narrow[3] = {
3319
    gen_op_neon_narrow_u8,
3320
    gen_op_neon_narrow_u16,
3321
    gen_op_neon_narrow_u32
3322
};
3323

    
3324
static GenOpFunc *gen_neon_narrow_satu[3] = {
3325
    gen_op_neon_narrow_sat_u8,
3326
    gen_op_neon_narrow_sat_u16,
3327
    gen_op_neon_narrow_sat_u32
3328
};
3329

    
3330
static GenOpFunc *gen_neon_narrow_sats[3] = {
3331
    gen_op_neon_narrow_sat_s8,
3332
    gen_op_neon_narrow_sat_s16,
3333
    gen_op_neon_narrow_sat_s32
3334
};
3335

    
3336
static inline int gen_neon_add(int size)
3337
{
3338
    switch (size) {
3339
    case 0: gen_op_neon_add_u8(); break;
3340
    case 1: gen_op_neon_add_u16(); break;
3341
    case 2: gen_op_addl_T0_T1(); break;
3342
    default: return 1;
3343
    }
3344
    return 0;
3345
}
3346

    
3347
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
3348
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
3349
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
3350
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
3351
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
3352

    
3353
#define GEN_NEON_INTEGER_OP(name) do { \
3354
    switch ((size << 1) | u) { \
3355
    case 0: gen_op_neon_##name##_s8(); break; \
3356
    case 1: gen_op_neon_##name##_u8(); break; \
3357
    case 2: gen_op_neon_##name##_s16(); break; \
3358
    case 3: gen_op_neon_##name##_u16(); break; \
3359
    case 4: gen_op_neon_##name##_s32(); break; \
3360
    case 5: gen_op_neon_##name##_u32(); break; \
3361
    default: return 1; \
3362
    }} while (0)
3363

    
3364
static inline void
3365
gen_neon_movl_scratch_T0(int scratch)
3366
{
3367
  uint32_t offset;
3368

    
3369
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3370
  gen_op_neon_setreg_T0(offset);
3371
}
3372

    
3373
static inline void
3374
gen_neon_movl_scratch_T1(int scratch)
3375
{
3376
  uint32_t offset;
3377

    
3378
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3379
  gen_op_neon_setreg_T1(offset);
3380
}
3381

    
3382
static inline void
3383
gen_neon_movl_T0_scratch(int scratch)
3384
{
3385
  uint32_t offset;
3386

    
3387
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3388
  gen_op_neon_getreg_T0(offset);
3389
}
3390

    
3391
static inline void
3392
gen_neon_movl_T1_scratch(int scratch)
3393
{
3394
  uint32_t offset;
3395

    
3396
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3397
  gen_op_neon_getreg_T1(offset);
3398
}
3399

    
3400
static inline void gen_op_neon_widen_u32(void)
3401
{
3402
    gen_op_movl_T1_im(0);
3403
}
3404

    
3405
static inline void gen_neon_get_scalar(int size, int reg)
3406
{
3407
    if (size == 1) {
3408
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3409
    } else {
3410
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3411
        if (reg & 1)
3412
            gen_op_neon_dup_low16();
3413
        else
3414
            gen_op_neon_dup_high16();
3415
    }
3416
}
3417

    
3418
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3419
{
3420
    int n;
3421

    
3422
    for (n = 0; n < q + 1; n += 2) {
3423
        NEON_GET_REG(T0, reg, n);
3424
        NEON_GET_REG(T0, reg, n + n);
3425
        switch (size) {
3426
        case 0: gen_op_neon_unzip_u8(); break;
3427
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
3428
        case 2: /* no-op */; break;
3429
        default: abort();
3430
        }
3431
        gen_neon_movl_scratch_T0(tmp + n);
3432
        gen_neon_movl_scratch_T1(tmp + n + 1);
3433
    }
3434
}
3435

    
3436
static struct {
3437
    int nregs;
3438
    int interleave;
3439
    int spacing;
3440
} neon_ls_element_type[11] = {
3441
    {4, 4, 1},
3442
    {4, 4, 2},
3443
    {4, 1, 1},
3444
    {4, 2, 1},
3445
    {3, 3, 1},
3446
    {3, 3, 2},
3447
    {3, 1, 1},
3448
    {1, 1, 1},
3449
    {2, 2, 1},
3450
    {2, 2, 2},
3451
    {2, 1, 1}
3452
};
3453

    
3454
/* Translate a NEON load/store element instruction.  Return nonzero if the
3455
   instruction is invalid.  */
3456
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3457
{
3458
    int rd, rn, rm;
3459
    int op;
3460
    int nregs;
3461
    int interleave;
3462
    int stride;
3463
    int size;
3464
    int reg;
3465
    int pass;
3466
    int load;
3467
    int shift;
3468
    uint32_t mask;
3469
    int n;
3470
    TCGv tmp;
3471

    
3472
    if (!vfp_enabled(env))
3473
      return 1;
3474
    VFP_DREG_D(rd, insn);
3475
    rn = (insn >> 16) & 0xf;
3476
    rm = insn & 0xf;
3477
    load = (insn & (1 << 21)) != 0;
3478
    if ((insn & (1 << 23)) == 0) {
3479
        /* Load store all elements.  */
3480
        op = (insn >> 8) & 0xf;
3481
        size = (insn >> 6) & 3;
3482
        if (op > 10 || size == 3)
3483
            return 1;
3484
        nregs = neon_ls_element_type[op].nregs;
3485
        interleave = neon_ls_element_type[op].interleave;
3486
        gen_movl_T1_reg(s, rn);
3487
        stride = (1 << size) * interleave;
3488
        for (reg = 0; reg < nregs; reg++) {
3489
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3490
                gen_movl_T1_reg(s, rn);
3491
                gen_op_addl_T1_im((1 << size) * reg);
3492
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3493
                gen_movl_T1_reg(s, rn);
3494
                gen_op_addl_T1_im(1 << size);
3495
            }
3496
            for (pass = 0; pass < 2; pass++) {
3497
                if (size == 2) {
3498
                    if (load) {
3499
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3500
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3501
                        dead_tmp(tmp);
3502
                        NEON_SET_REG(T0, rd, pass);
3503
                    } else {
3504
                        NEON_GET_REG(T0, rd, pass);
3505
                        tmp = new_tmp();
3506
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3507
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3508
                    }
3509
                    gen_op_addl_T1_im(stride);
3510
                } else if (size == 1) {
3511
                    if (load) {
3512
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3513
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3514
                        dead_tmp(tmp);
3515
                        gen_op_addl_T1_im(stride);
3516
                        gen_op_movl_T2_T0();
3517
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3518
                        tcg_gen_mov_i32(cpu_T[0], tmp);
3519
                        dead_tmp(tmp);
3520
                        gen_op_addl_T1_im(stride);
3521
                        gen_op_neon_insert_elt(16, 0xffff);
3522
                        NEON_SET_REG(T2, rd, pass);
3523
                    } else {
3524
                        NEON_GET_REG(T2, rd, pass);
3525
                        gen_op_movl_T0_T2();
3526
                        tmp = new_tmp();
3527
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3528
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3529
                        gen_op_addl_T1_im(stride);
3530
                        gen_op_neon_extract_elt(16, 0xffff0000);
3531
                        tmp = new_tmp();
3532
                        tcg_gen_mov_i32(tmp, cpu_T[0]);
3533
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3534
                        gen_op_addl_T1_im(stride);
3535
                    }
3536
                } else /* size == 0 */ {
3537
                    if (load) {
3538
                        mask = 0xff;
3539
                        for (n = 0; n < 4; n++) {
3540
                            tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3541
                            tcg_gen_mov_i32(cpu_T[0], tmp);
3542
                            dead_tmp(tmp);
3543
                            gen_op_addl_T1_im(stride);
3544
                            if (n == 0) {
3545
                                gen_op_movl_T2_T0();
3546
                            } else {
3547
                                gen_op_neon_insert_elt(n * 8, ~mask);
3548
                            }
3549
                            mask <<= 8;
3550
                        }
3551
                        NEON_SET_REG(T2, rd, pass);
3552
                    } else {
3553
                        NEON_GET_REG(T2, rd, pass);
3554
                        mask = 0xff;
3555
                        for (n = 0; n < 4; n++) {
3556
                            if (n == 0) {
3557
                                gen_op_movl_T0_T2();
3558
                            } else {
3559
                                gen_op_neon_extract_elt(n * 8, mask);
3560
                            }
3561
                            tmp = new_tmp();
3562
                            tcg_gen_mov_i32(tmp, cpu_T[0]);
3563
                            gen_st8(tmp, cpu_T[1], IS_USER(s));
3564
                            gen_op_addl_T1_im(stride);
3565
                            mask <<= 8;
3566
                        }
3567
                    }
3568
                }
3569
            }
3570
            rd += neon_ls_element_type[op].spacing;
3571
        }
3572
        stride = nregs * 8;
3573
    } else {
3574
        size = (insn >> 10) & 3;
3575
        if (size == 3) {
3576
            /* Load single element to all lanes.  */
3577
            if (!load)
3578
                return 1;
3579
            size = (insn >> 6) & 3;
3580
            nregs = ((insn >> 8) & 3) + 1;
3581
            stride = (insn & (1 << 5)) ? 2 : 1;
3582
            gen_movl_T1_reg(s, rn);
3583
            for (reg = 0; reg < nregs; reg++) {
3584
                switch (size) {
3585
                case 0:
3586
                    tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3587
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3588
                    dead_tmp(tmp);
3589
                    gen_op_neon_dup_u8(0);
3590
                    break;
3591
                case 1:
3592
                    tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3593
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3594
                    dead_tmp(tmp);
3595
                    gen_op_neon_dup_low16();
3596
                    break;
3597
                case 2:
3598
                    tmp = gen_ld32(cpu_T[0], IS_USER(s));
3599
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3600
                    dead_tmp(tmp);
3601
                    break;
3602
                case 3:
3603
                    return 1;
3604
                }
3605
                gen_op_addl_T1_im(1 << size);
3606
                NEON_SET_REG(T0, rd, 0);
3607
                NEON_SET_REG(T0, rd, 1);
3608
                rd += stride;
3609
            }
3610
            stride = (1 << size) * nregs;
3611
        } else {
3612
            /* Single element.  */
3613
            pass = (insn >> 7) & 1;
3614
            switch (size) {
3615
            case 0:
3616
                shift = ((insn >> 5) & 3) * 8;
3617
                mask = 0xff << shift;
3618
                stride = 1;
3619
                break;
3620
            case 1:
3621
                shift = ((insn >> 6) & 1) * 16;
3622
                mask = shift ? 0xffff0000 : 0xffff;
3623
                stride = (insn & (1 << 5)) ? 2 : 1;
3624
                break;
3625
            case 2:
3626
                shift = 0;
3627
                mask = 0xffffffff;
3628
                stride = (insn & (1 << 6)) ? 2 : 1;
3629
                break;
3630
            default:
3631
                abort();
3632
            }
3633
            nregs = ((insn >> 8) & 3) + 1;
3634
            gen_movl_T1_reg(s, rn);
3635
            for (reg = 0; reg < nregs; reg++) {
3636
                if (load) {
3637
                    if (size != 2) {
3638
                        NEON_GET_REG(T2, rd, pass);
3639
                    }
3640
                    switch (size) {
3641
                    case 0:
3642
                        tmp = gen_ld8u(cpu_T[1], IS_USER(s));
3643
                        break;
3644
                    case 1:
3645
                        tmp = gen_ld16u(cpu_T[1], IS_USER(s));
3646
                        break;
3647
                    case 2:
3648
                        tmp = gen_ld32(cpu_T[1], IS_USER(s));
3649
                        break;
3650
                    }
3651
                    tcg_gen_mov_i32(cpu_T[0], tmp);
3652
                    dead_tmp(tmp);
3653
                    if (size != 2) {
3654
                        gen_op_neon_insert_elt(shift, ~mask);
3655
                        NEON_SET_REG(T0, rd, pass);
3656
                    } else {
3657
                        NEON_SET_REG(T0, rd, pass);
3658
                    }
3659
                } else { /* Store */
3660
                    if (size == 2) {
3661
                        NEON_GET_REG(T0, rd, pass);
3662
                    } else {
3663
                        NEON_GET_REG(T2, rd, pass);
3664
                        gen_op_neon_extract_elt(shift, mask);
3665
                    }
3666
                    tmp = new_tmp();
3667
                    tcg_gen_mov_i32(tmp, cpu_T[0]);
3668
                    switch (size) {
3669
                    case 0:
3670
                        gen_st8(tmp, cpu_T[1], IS_USER(s));
3671
                        break;
3672
                    case 1:
3673
                        gen_st16(tmp, cpu_T[1], IS_USER(s));
3674
                        break;
3675
                    case 2:
3676
                        gen_st32(tmp, cpu_T[1], IS_USER(s));
3677
                        break;
3678
                    }
3679
                }
3680
                rd += stride;
3681
                gen_op_addl_T1_im(1 << size);
3682
            }
3683
            stride = nregs * (1 << size);
3684
        }
3685
    }
3686
    if (rm != 15) {
3687
        TCGv base;
3688

    
3689
        base = load_reg(s, rn);
3690
        if (rm == 13) {
3691
            tcg_gen_addi_i32(base, base, stride);
3692
        } else {
3693
            TCGv index;
3694
            index = load_reg(s, rm);
3695
            tcg_gen_add_i32(base, base, index);
3696
            dead_tmp(index);
3697
        }
3698
        store_reg(s, rn, base);
3699
    }
3700
    return 0;
3701
}
3702

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

    
3710
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3711
{
3712
    int op;
3713
    int q;
3714
    int rd, rn, rm;
3715
    int size;
3716
    int shift;
3717
    int pass;
3718
    int count;
3719
    int pairwise;
3720
    int u;
3721
    int n;
3722
    uint32_t imm;
3723

    
3724
    if (!vfp_enabled(env))
3725
      return 1;
3726
    q = (insn & (1 << 6)) != 0;
3727
    u = (insn >> 24) & 1;
3728
    VFP_DREG_D(rd, insn);
3729
    VFP_DREG_N(rn, insn);
3730
    VFP_DREG_M(rm, insn);
3731
    size = (insn >> 20) & 3;
3732
    if ((insn & (1 << 23)) == 0) {
3733
        /* Three register same length.  */
3734
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3735
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3736
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3737
                NEON_GET_REG(T0, rm, pass * 2);
3738
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3739
                gen_neon_movl_scratch_T0(0);
3740
                gen_neon_movl_scratch_T1(1);
3741
                NEON_GET_REG(T0, rn, pass * 2);
3742
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3743
                switch (op) {
3744
                case 1: /* VQADD */
3745
                    if (u) {
3746
                        gen_op_neon_addl_saturate_u64();
3747
                    } else {
3748
                        gen_op_neon_addl_saturate_s64();
3749
                    }
3750
                    break;
3751
                case 5: /* VQSUB */
3752
                    if (u) {
3753
                        gen_op_neon_subl_saturate_u64();
3754
                    } else {
3755
                        gen_op_neon_subl_saturate_s64();
3756
                    }
3757
                    break;
3758
                case 16:
3759
                    if (u) {
3760
                        gen_op_neon_subl_u64();
3761
                    } else {
3762
                        gen_op_neon_addl_u64();
3763
                    }
3764
                    break;
3765
                default:
3766
                    abort();
3767
                }
3768
                NEON_SET_REG(T0, rd, pass * 2);
3769
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3770
            }
3771
            return 0;
3772
        }
3773
        switch (op) {
3774
        case 8: /* VSHL */
3775
        case 9: /* VQSHL */
3776
        case 10: /* VRSHL */
3777
        case 11: /* VQSHL */
3778
            /* Shift operations have Rn and Rm reversed.  */
3779
            {
3780
                int tmp;
3781
                tmp = rn;
3782
                rn = rm;
3783
                rm = tmp;
3784
                pairwise = 0;
3785
            }
3786
            break;
3787
        case 20: /* VPMAX */
3788
        case 21: /* VPMIN */
3789
        case 23: /* VPADD */
3790
            pairwise = 1;
3791
            break;
3792
        case 26: /* VPADD (float) */
3793
            pairwise = (u && size < 2);
3794
            break;
3795
        case 30: /* VPMIN/VPMAX (float) */
3796
            pairwise = u;
3797
            break;
3798
        default:
3799
            pairwise = 0;
3800
            break;
3801
        }
3802
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3803

    
3804
        if (pairwise) {
3805
            /* Pairwise.  */
3806
            if (q)
3807
                n = (pass & 1) * 2;
3808
            else
3809
                n = 0;
3810
            if (pass < q + 1) {
3811
                NEON_GET_REG(T0, rn, n);
3812
                NEON_GET_REG(T1, rn, n + 1);
3813
            } else {
3814
                NEON_GET_REG(T0, rm, n);
3815
                NEON_GET_REG(T1, rm, n + 1);
3816
            }
3817
        } else {
3818
            /* Elementwise.  */
3819
            NEON_GET_REG(T0, rn, pass);
3820
            NEON_GET_REG(T1, rm, pass);
3821
        }
3822
        switch (op) {
3823
        case 0: /* VHADD */
3824
            GEN_NEON_INTEGER_OP(hadd);
3825
            break;
3826
        case 1: /* VQADD */
3827
            switch (size << 1| u) {
3828
            case 0: gen_op_neon_qadd_s8(); break;
3829
            case 1: gen_op_neon_qadd_u8(); break;
3830
            case 2: gen_op_neon_qadd_s16(); break;
3831
            case 3: gen_op_neon_qadd_u16(); break;
3832
            case 4:
3833
                gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3834
                break;
3835
            case 5:
3836
                gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3837
                break;
3838
            default: abort();
3839
            }
3840
            break;
3841
        case 2: /* VRHADD */
3842
            GEN_NEON_INTEGER_OP(rhadd);
3843
            break;
3844
        case 3: /* Logic ops.  */
3845
            switch ((u << 2) | size) {
3846
            case 0: /* VAND */
3847
                gen_op_andl_T0_T1();
3848
                break;
3849
            case 1: /* BIC */
3850
                gen_op_bicl_T0_T1();
3851
                break;
3852
            case 2: /* VORR */
3853
                gen_op_orl_T0_T1();
3854
                break;
3855
            case 3: /* VORN */
3856
                gen_op_notl_T1();
3857
                gen_op_orl_T0_T1();
3858
                break;
3859
            case 4: /* VEOR */
3860
                gen_op_xorl_T0_T1();
3861
                break;
3862
            case 5: /* VBSL */
3863
                NEON_GET_REG(T2, rd, pass);
3864
                gen_op_neon_bsl();
3865
                break;
3866
            case 6: /* VBIT */
3867
                NEON_GET_REG(T2, rd, pass);
3868
                gen_op_neon_bit();
3869
                break;
3870
            case 7: /* VBIF */
3871
                NEON_GET_REG(T2, rd, pass);
3872
                gen_op_neon_bif();
3873
                break;
3874
            }
3875
            break;
3876
        case 4: /* VHSUB */
3877
            GEN_NEON_INTEGER_OP(hsub);
3878
            break;
3879
        case 5: /* VQSUB */
3880
            switch ((size << 1) | u) {
3881
            case 0: gen_op_neon_qsub_s8(); break;
3882
            case 1: gen_op_neon_qsub_u8(); break;
3883
            case 2: gen_op_neon_qsub_s16(); break;
3884
            case 3: gen_op_neon_qsub_u16(); break;
3885
            case 4:
3886
                gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3887
                break;
3888
            case 5:
3889
                gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1]);
3890
                break;
3891
            default: abort();
3892
            }
3893
            break;
3894
        case 6: /* VCGT */
3895
            GEN_NEON_INTEGER_OP(cgt);
3896
            break;
3897
        case 7: /* VCGE */
3898
            GEN_NEON_INTEGER_OP(cge);
3899
            break;
3900
        case 8: /* VSHL */
3901
            switch ((size << 1) | u) {
3902
            case 0: gen_op_neon_shl_s8(); break;
3903
            case 1: gen_op_neon_shl_u8(); break;
3904
            case 2: gen_op_neon_shl_s16(); break;
3905
            case 3: gen_op_neon_shl_u16(); break;
3906
            case 4: gen_op_neon_shl_s32(); break;
3907
            case 5: gen_op_neon_shl_u32(); break;
3908
#if 0
3909
            /* ??? Implementing these is tricky because the vector ops work
3910
               on 32-bit pieces.  */
3911
            case 6: gen_op_neon_shl_s64(); break;
3912
            case 7: gen_op_neon_shl_u64(); break;
3913
#else
3914
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3915
#endif
3916
            }
3917
            break;
3918
        case 9: /* VQSHL */
3919
            switch ((size << 1) | u) {
3920
            case 0: gen_op_neon_qshl_s8(); break;
3921
            case 1: gen_op_neon_qshl_u8(); break;
3922
            case 2: gen_op_neon_qshl_s16(); break;
3923
            case 3: gen_op_neon_qshl_u16(); break;
3924
            case 4: gen_op_neon_qshl_s32(); break;
3925
            case 5: gen_op_neon_qshl_u32(); break;
3926
#if 0
3927
            /* ??? Implementing these is tricky because the vector ops work
3928
               on 32-bit pieces.  */
3929
            case 6: gen_op_neon_qshl_s64(); break;
3930
            case 7: gen_op_neon_qshl_u64(); break;
3931
#else
3932
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3933
#endif
3934
            }
3935
            break;
3936
        case 10: /* VRSHL */
3937
            switch ((size << 1) | u) {
3938
            case 0: gen_op_neon_rshl_s8(); break;
3939
            case 1: gen_op_neon_rshl_u8(); break;
3940
            case 2: gen_op_neon_rshl_s16(); break;
3941
            case 3: gen_op_neon_rshl_u16(); break;
3942
            case 4: gen_op_neon_rshl_s32(); break;
3943
            case 5: gen_op_neon_rshl_u32(); break;
3944
#if 0
3945
            /* ??? Implementing these is tricky because the vector ops work
3946
               on 32-bit pieces.  */
3947
            case 6: gen_op_neon_rshl_s64(); break;
3948
            case 7: gen_op_neon_rshl_u64(); break;
3949
#else
3950
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3951
#endif
3952
            }
3953
            break;
3954
        case 11: /* VQRSHL */
3955
            switch ((size << 1) | u) {
3956
            case 0: gen_op_neon_qrshl_s8(); break;
3957
            case 1: gen_op_neon_qrshl_u8(); break;
3958
            case 2: gen_op_neon_qrshl_s16(); break;
3959
            case 3: gen_op_neon_qrshl_u16(); break;
3960
            case 4: gen_op_neon_qrshl_s32(); break;
3961
            case 5: gen_op_neon_qrshl_u32(); break;
3962
#if 0
3963
            /* ??? Implementing these is tricky because the vector ops work
3964
               on 32-bit pieces.  */
3965
            case 6: gen_op_neon_qrshl_s64(); break;
3966
            case 7: gen_op_neon_qrshl_u64(); break;
3967
#else
3968
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3969
#endif
3970
            }
3971
            break;
3972
        case 12: /* VMAX */
3973
            GEN_NEON_INTEGER_OP(max);
3974
            break;
3975
        case 13: /* VMIN */
3976
            GEN_NEON_INTEGER_OP(min);
3977
            break;
3978
        case 14: /* VABD */
3979
            GEN_NEON_INTEGER_OP(abd);
3980
            break;
3981
        case 15: /* VABA */
3982
            GEN_NEON_INTEGER_OP(abd);
3983
            NEON_GET_REG(T1, rd, pass);
3984
            gen_neon_add(size);
3985
            break;
3986
        case 16:
3987
            if (!u) { /* VADD */
3988
                if (gen_neon_add(size))
3989
                    return 1;
3990
            } else { /* VSUB */
3991
                switch (size) {
3992
                case 0: gen_op_neon_sub_u8(); break;
3993
                case 1: gen_op_neon_sub_u16(); break;
3994
                case 2: gen_op_subl_T0_T1(); break;
3995
                default: return 1;
3996
                }
3997
            }
3998
            break;
3999
        case 17:
4000
            if (!u) { /* VTST */
4001
                switch (size) {
4002
                case 0: gen_op_neon_tst_u8(); break;
4003
                case 1: gen_op_neon_tst_u16(); break;
4004
                case 2: gen_op_neon_tst_u32(); break;
4005
                default: return 1;
4006
                }
4007
            } else { /* VCEQ */
4008
                switch (size) {
4009
                case 0: gen_op_neon_ceq_u8(); break;
4010
                case 1: gen_op_neon_ceq_u16(); break;
4011
                case 2: gen_op_neon_ceq_u32(); break;
4012
                default: return 1;
4013
                }
4014
            }
4015
            break;
4016
        case 18: /* Multiply.  */
4017
            switch (size) {
4018
            case 0: gen_op_neon_mul_u8(); break;
4019
            case 1: gen_op_neon_mul_u16(); break;
4020
            case 2: gen_op_mul_T0_T1(); break;
4021
            default: return 1;
4022
            }
4023
            NEON_GET_REG(T1, rd, pass);
4024
            if (u) { /* VMLS */
4025
                switch (size) {
4026
                case 0: gen_op_neon_rsb_u8(); break;
4027
                case 1: gen_op_neon_rsb_u16(); break;
4028
                case 2: gen_op_rsbl_T0_T1(); break;
4029
                default: return 1;
4030
                }
4031
            } else { /* VMLA */
4032
                gen_neon_add(size);
4033
            }
4034
            break;
4035
        case 19: /* VMUL */
4036
            if (u) { /* polynomial */
4037
                gen_op_neon_mul_p8();
4038
            } else { /* Integer */
4039
                switch (size) {
4040
                case 0: gen_op_neon_mul_u8(); break;
4041
                case 1: gen_op_neon_mul_u16(); break;
4042
                case 2: gen_op_mul_T0_T1(); break;
4043
                default: return 1;
4044
                }
4045
            }
4046
            break;
4047
        case 20: /* VPMAX */
4048
            GEN_NEON_INTEGER_OP(pmax);
4049
            break;
4050
        case 21: /* VPMIN */
4051
            GEN_NEON_INTEGER_OP(pmin);
4052
            break;
4053
        case 22: /* Hultiply high.  */
4054
            if (!u) { /* VQDMULH */
4055
                switch (size) {
4056
                case 1: gen_op_neon_qdmulh_s16(); break;
4057
                case 2: gen_op_neon_qdmulh_s32(); break;
4058
                default: return 1;
4059
                }
4060
            } else { /* VQRDHMUL */
4061
                switch (size) {
4062
                case 1: gen_op_neon_qrdmulh_s16(); break;
4063
                case 2: gen_op_neon_qrdmulh_s32(); break;
4064
                default: return 1;
4065
                }
4066
            }
4067
            break;
4068
        case 23: /* VPADD */
4069
            if (u)
4070
                return 1;
4071
            switch (size) {
4072
            case 0: gen_op_neon_padd_u8(); break;
4073
            case 1: gen_op_neon_padd_u16(); break;
4074
            case 2: gen_op_addl_T0_T1(); break;
4075
            default: return 1;
4076
            }
4077
            break;
4078
        case 26: /* Floating point arithnetic.  */
4079
            switch ((u << 2) | size) {
4080
            case 0: /* VADD */
4081
                gen_op_neon_add_f32();
4082
                break;
4083
            case 2: /* VSUB */
4084
                gen_op_neon_sub_f32();
4085
                break;
4086
            case 4: /* VPADD */
4087
                gen_op_neon_add_f32();
4088
                break;
4089
            case 6: /* VABD */
4090
                gen_op_neon_abd_f32();
4091
                break;
4092
            default:
4093
                return 1;
4094
            }
4095
            break;
4096
        case 27: /* Float multiply.  */
4097
            gen_op_neon_mul_f32();
4098
            if (!u) {
4099
                NEON_GET_REG(T1, rd, pass);
4100
                if (size == 0) {
4101
                    gen_op_neon_add_f32();
4102
                } else {
4103
                    gen_op_neon_rsb_f32();
4104
                }
4105
            }
4106
            break;
4107
        case 28: /* Float compare.  */
4108
            if (!u) {
4109
                gen_op_neon_ceq_f32();
4110
            } else {
4111
                if (size == 0)
4112
                    gen_op_neon_cge_f32();
4113
                else
4114
                    gen_op_neon_cgt_f32();
4115
            }
4116
            break;
4117
        case 29: /* Float compare absolute.  */
4118
            if (!u)
4119
                return 1;
4120
            if (size == 0)
4121
                gen_op_neon_acge_f32();
4122
            else
4123
                gen_op_neon_acgt_f32();
4124
            break;
4125
        case 30: /* Float min/max.  */
4126
            if (size == 0)
4127
                gen_op_neon_max_f32();
4128
            else
4129
                gen_op_neon_min_f32();
4130
            break;
4131
        case 31:
4132
            if (size == 0)
4133
                gen_helper_recps_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4134
            else
4135
                gen_helper_rsqrts_f32(cpu_T[0], cpu_T[0], cpu_T[1], cpu_env);
4136
            break;
4137
        default:
4138
            abort();
4139
        }
4140
        /* Save the result.  For elementwise operations we can put it
4141
           straight into the destination register.  For pairwise operations
4142
           we have to be careful to avoid clobbering the source operands.  */
4143
        if (pairwise && rd == rm) {
4144
            gen_neon_movl_scratch_T0(pass);
4145
        } else {
4146
            NEON_SET_REG(T0, rd, pass);
4147
        }
4148

    
4149
        } /* for pass */
4150
        if (pairwise && rd == rm) {
4151
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4152
                gen_neon_movl_T0_scratch(pass);
4153
                NEON_SET_REG(T0, rd, pass);
4154
            }
4155
        }
4156
    } else if (insn & (1 << 4)) {
4157
        if ((insn & 0x00380080) != 0) {
4158
            /* Two registers and shift.  */
4159
            op = (insn >> 8) & 0xf;
4160
            if (insn & (1 << 7)) {
4161
                /* 64-bit shift.   */
4162
                size = 3;
4163
            } else {
4164
                size = 2;
4165
                while ((insn & (1 << (size + 19))) == 0)
4166
                    size--;
4167
            }
4168
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4169
            /* To avoid excessive dumplication of ops we implement shift
4170
               by immediate using the variable shift operations.  */
4171
            if (op < 8) {
4172
                /* Shift by immediate:
4173
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
4174
                /* Right shifts are encoded as N - shift, where N is the
4175
                   element size in bits.  */
4176
                if (op <= 4)
4177
                    shift = shift - (1 << (size + 3));
4178
                else
4179
                    shift++;
4180
                if (size == 3) {
4181
                    count = q + 1;
4182
                } else {
4183
                    count = q ? 4: 2;
4184
                }
4185
                switch (size) {
4186
                case 0:
4187
                    imm = (uint8_t) shift;
4188
                    imm |= imm << 8;
4189
                    imm |= imm << 16;
4190
                    break;
4191
                case 1:
4192
                    imm = (uint16_t) shift;
4193
                    imm |= imm << 16;
4194
                    break;
4195
                case 2:
4196
                case 3:
4197
                    imm = shift;
4198
                    break;
4199
                default:
4200
                    abort();
4201
                }
4202

    
4203
                for (pass = 0; pass < count; pass++) {
4204
                    if (size < 3) {
4205
                        /* Operands in T0 and T1.  */
4206
                        gen_op_movl_T1_im(imm);
4207
                        NEON_GET_REG(T0, rm, pass);
4208
                    } else {
4209
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4210
                        gen_op_movl_T0_im(imm);
4211
                        gen_neon_movl_scratch_T0(0);
4212
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4213
                        gen_neon_movl_scratch_T0(1);
4214
                        NEON_GET_REG(T0, rm, pass * 2);
4215
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4216
                    }
4217

    
4218
                    if (gen_neon_shift_im[op][u][size] == NULL)
4219
                        return 1;
4220
                    gen_neon_shift_im[op][u][size]();
4221

    
4222
                    if (op == 1 || op == 3) {
4223
                        /* Accumulate.  */
4224
                        if (size == 3) {
4225
                            gen_neon_movl_scratch_T0(0);
4226
                            gen_neon_movl_scratch_T1(1);
4227
                            NEON_GET_REG(T0, rd, pass * 2);
4228
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4229
                            gen_op_neon_addl_u64();
4230
                        } else {
4231
                            NEON_GET_REG(T1, rd, pass);
4232
                            gen_neon_add(size);
4233
                        }
4234
                    } else if (op == 4 || (op == 5 && u)) {
4235
                        /* Insert */
4236
                        if (size == 3) {
4237
                            cpu_abort(env, "VS[LR]I.64 not implemented");
4238
                        }
4239
                        switch (size) {
4240
                        case 0:
4241
                            if (op == 4)
4242
                                imm = 0xff >> -shift;
4243
                            else
4244
                                imm = (uint8_t)(0xff << shift);
4245
                            imm |= imm << 8;
4246
                            imm |= imm << 16;
4247
                            break;
4248
                        case 1:
4249
                            if (op == 4)
4250
                                imm = 0xffff >> -shift;
4251
                            else
4252
                                imm = (uint16_t)(0xffff << shift);
4253
                            imm |= imm << 16;
4254
                            break;
4255
                        case 2:
4256
                            if (op == 4)
4257
                                imm = 0xffffffffu >> -shift;
4258
                            else
4259
                                imm = 0xffffffffu << shift;
4260
                            break;
4261
                        default:
4262
                            abort();
4263
                        }
4264
                        NEON_GET_REG(T1, rd, pass);
4265
                        gen_op_movl_T2_im(imm);
4266
                        gen_op_neon_bsl();
4267
                    }
4268
                    if (size == 3) {
4269
                        NEON_SET_REG(T0, rd, pass * 2);
4270
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4271
                    } else {
4272
                        NEON_SET_REG(T0, rd, pass);
4273
                    }
4274
                } /* for pass */
4275
            } else if (op < 10) {
4276
                /* Shift by immedaiate and narrow:
4277
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
4278
                shift = shift - (1 << (size + 3));
4279
                size++;
4280
                if (size == 3) {
4281
                    count = q + 1;
4282
                } else {
4283
                    count = q ? 4: 2;
4284
                }
4285
                switch (size) {
4286
                case 1:
4287
                    imm = (uint16_t) shift;
4288
                    imm |= imm << 16;
4289
                    break;
4290
                case 2:
4291
                case 3:
4292
                    imm = shift;
4293
                    break;
4294
                default:
4295
                    abort();
4296
                }
4297

    
4298
                /* Processing MSB first means we need to do less shuffling at
4299
                   the end.  */
4300
                for (pass =  count - 1; pass >= 0; pass--) {
4301
                    /* Avoid clobbering the second operand before it has been
4302
                       written.  */
4303
                    n = pass;
4304
                    if (rd == rm)
4305
                        n ^= (count - 1);
4306
                    else
4307
                        n = pass;
4308

    
4309
                    if (size < 3) {
4310
                        /* Operands in T0 and T1.  */
4311
                        gen_op_movl_T1_im(imm);
4312
                        NEON_GET_REG(T0, rm, n);
4313
                    } else {
4314
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4315
                        gen_op_movl_T0_im(imm);
4316
                        gen_neon_movl_scratch_T0(0);
4317
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4318
                        gen_neon_movl_scratch_T0(1);
4319
                        NEON_GET_REG(T0, rm, n * 2);
4320
                        NEON_GET_REG(T0, rm, n * 2 + 1);
4321
                    }
4322

    
4323
                    gen_neon_shift_im_narrow[q][u][size - 1]();
4324

    
4325
                    if (size < 3 && (pass & 1) == 0) {
4326
                        gen_neon_movl_scratch_T0(0);
4327
                    } else {
4328
                        uint32_t offset;
4329

    
4330
                        if (size < 3)
4331
                            gen_neon_movl_T1_scratch(0);
4332

    
4333
                        if (op == 8 && !u) {
4334
                            gen_neon_narrow[size - 1]();
4335
                        } else {
4336
                            if (op == 8)
4337
                                gen_neon_narrow_sats[size - 2]();
4338
                            else
4339
                                gen_neon_narrow_satu[size - 1]();
4340
                        }
4341
                        if (size == 3)
4342
                            offset = neon_reg_offset(rd, n);
4343
                        else
4344
                            offset = neon_reg_offset(rd, n >> 1);
4345
                        gen_op_neon_setreg_T0(offset);
4346
                    }
4347
                } /* for pass */
4348
            } else if (op == 10) {
4349
                /* VSHLL */
4350
                if (q)
4351
                    return 1;
4352
                for (pass = 0; pass < 2; pass++) {
4353
                    /* Avoid clobbering the input operand.  */
4354
                    if (rd == rm)
4355
                        n = 1 - pass;
4356
                    else
4357
                        n = pass;
4358

    
4359
                    NEON_GET_REG(T0, rm, n);
4360
                    GEN_NEON_INTEGER_OP(widen);
4361
                    if (shift != 0) {
4362
                        /* The shift is less than the width of the source
4363
                           type, so in some cases we can just
4364
                           shift the whole register.  */
4365
                        if (size == 1 || (size == 0 && u)) {
4366
                            gen_op_shll_T0_im(shift);
4367
                            gen_op_shll_T1_im(shift);
4368
                        } else {
4369
                            switch (size) {
4370
                            case 0: gen_op_neon_shll_u16(shift); break;
4371
                            case 2: gen_op_neon_shll_u64(shift); break;
4372
                            default: abort();
4373
                            }
4374
                        }
4375
                    }
4376
                    NEON_SET_REG(T0, rd, n * 2);
4377
                    NEON_SET_REG(T1, rd, n * 2 + 1);
4378
                }
4379
            } else if (op == 15 || op == 16) {
4380
                /* VCVT fixed-point.  */
4381
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4382
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4383
                    if (op & 1) {
4384
                        if (u)
4385
                            gen_vfp_ulto(0, shift);
4386
                        else
4387
                            gen_vfp_slto(0, shift);
4388
                    } else {
4389
                        if (u)
4390
                            gen_vfp_toul(0, shift);
4391
                        else
4392
                            gen_vfp_tosl(0, shift);
4393
                    }
4394
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4395
                }
4396
            } else {
4397
                return 1;
4398
            }
4399
        } else { /* (insn & 0x00380080) == 0 */
4400
            int invert;
4401

    
4402
            op = (insn >> 8) & 0xf;
4403
            /* One register and immediate.  */
4404
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4405
            invert = (insn & (1 << 5)) != 0;
4406
            switch (op) {
4407
            case 0: case 1:
4408
                /* no-op */
4409
                break;
4410
            case 2: case 3:
4411
                imm <<= 8;
4412
                break;
4413
            case 4: case 5:
4414
                imm <<= 16;
4415
                break;
4416
            case 6: case 7:
4417
                imm <<= 24;
4418
                break;
4419
            case 8: case 9:
4420
                imm |= imm << 16;
4421
                break;
4422
            case 10: case 11:
4423
                imm = (imm << 8) | (imm << 24);
4424
                break;
4425
            case 12:
4426
                imm = (imm < 8) | 0xff;
4427
                break;
4428
            case 13:
4429
                imm = (imm << 16) | 0xffff;
4430
                break;
4431
            case 14:
4432
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4433
                if (invert)
4434
                    imm = ~imm;
4435
                break;
4436
            case 15:
4437
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4438
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4439
                break;
4440
            }
4441
            if (invert)
4442
                imm = ~imm;
4443

    
4444
            if (op != 14 || !invert)
4445
                gen_op_movl_T1_im(imm);
4446

    
4447
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4448
                if (op & 1 && op < 12) {
4449
                    NEON_GET_REG(T0, rd, pass);
4450
                    if (invert) {
4451
                        /* The immediate value has already been inverted, so
4452
                           BIC becomes AND.  */
4453
                        gen_op_andl_T0_T1();
4454
                    } else {
4455
                        gen_op_orl_T0_T1();
4456
                    }
4457
                    NEON_SET_REG(T0, rd, pass);
4458
                } else {
4459
                    if (op == 14 && invert) {
4460
                        uint32_t tmp;
4461
                        tmp = 0;
4462
                        for (n = 0; n < 4; n++) {
4463
                            if (imm & (1 << (n + (pass & 1) * 4)))
4464
                                tmp |= 0xff << (n * 8);
4465
                        }
4466
                        gen_op_movl_T1_im(tmp);
4467
                    }
4468
                    /* VMOV, VMVN.  */
4469
                    NEON_SET_REG(T1, rd, pass);
4470
                }
4471
            }
4472
        }
4473
    } else { /* (insn & 0x00800010 == 0x00800010) */
4474
        if (size != 3) {
4475
            op = (insn >> 8) & 0xf;
4476
            if ((insn & (1 << 6)) == 0) {
4477
                /* Three registers of different lengths.  */
4478
                int src1_wide;
4479
                int src2_wide;
4480
                int prewiden;
4481
                /* prewiden, src1_wide, src2_wide */
4482
                static const int neon_3reg_wide[16][3] = {
4483
                    {1, 0, 0}, /* VADDL */
4484
                    {1, 1, 0}, /* VADDW */
4485
                    {1, 0, 0}, /* VSUBL */
4486
                    {1, 1, 0}, /* VSUBW */
4487
                    {0, 1, 1}, /* VADDHN */
4488
                    {0, 0, 0}, /* VABAL */
4489
                    {0, 1, 1}, /* VSUBHN */
4490
                    {0, 0, 0}, /* VABDL */
4491
                    {0, 0, 0}, /* VMLAL */
4492
                    {0, 0, 0}, /* VQDMLAL */
4493
                    {0, 0, 0}, /* VMLSL */
4494
                    {0, 0, 0}, /* VQDMLSL */
4495
                    {0, 0, 0}, /* Integer VMULL */
4496
                    {0, 0, 0}, /* VQDMULL */
4497
                    {0, 0, 0}  /* Polynomial VMULL */
4498
                };
4499

    
4500
                prewiden = neon_3reg_wide[op][0];
4501
                src1_wide = neon_3reg_wide[op][1];
4502
                src2_wide = neon_3reg_wide[op][2];
4503

    
4504
                /* Avoid overlapping operands.  Wide source operands are
4505
                   always aligned so will never overlap with wide
4506
                   destinations in problematic ways.  */
4507
                if (rd == rm) {
4508
                    NEON_GET_REG(T2, rm, 1);
4509
                } else if (rd == rn) {
4510
                    NEON_GET_REG(T2, rn, 1);
4511
                }
4512
                for (pass = 0; pass < 2; pass++) {
4513
                    /* Load the second operand into env->vfp.scratch.
4514
                       Also widen narrow operands.  */
4515
                    if (pass == 1 && rd == rm) {
4516
                        if (prewiden) {
4517
                            gen_op_movl_T0_T2();
4518
                        } else {
4519
                            gen_op_movl_T1_T2();
4520
                        }
4521
                    } else {
4522
                        if (src2_wide) {
4523
                            NEON_GET_REG(T0, rm, pass * 2);
4524
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
4525
                        } else {
4526
                            if (prewiden) {
4527
                                NEON_GET_REG(T0, rm, pass);
4528
                            } else {
4529
                                NEON_GET_REG(T1, rm, pass);
4530
                            }
4531
                        }
4532
                    }
4533
                    if (prewiden && !src2_wide) {
4534
                        GEN_NEON_INTEGER_OP(widen);
4535
                    }
4536
                    if (prewiden || src2_wide) {
4537
                        gen_neon_movl_scratch_T0(0);
4538
                        gen_neon_movl_scratch_T1(1);
4539
                    }
4540

    
4541
                    /* Load the first operand.  */
4542
                    if (pass == 1 && rd == rn) {
4543
                        gen_op_movl_T0_T2();
4544
                    } else {
4545
                        if (src1_wide) {
4546
                            NEON_GET_REG(T0, rn, pass * 2);
4547
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
4548
                        } else {
4549
                            NEON_GET_REG(T0, rn, pass);
4550
                        }
4551
                    }
4552
                    if (prewiden && !src1_wide) {
4553
                        GEN_NEON_INTEGER_OP(widen);
4554
                    }
4555
                    switch (op) {
4556
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4557
                        switch (size) {
4558
                        case 0: gen_op_neon_addl_u16(); break;
4559
                        case 1: gen_op_neon_addl_u32(); break;
4560
                        case 2: gen_op_neon_addl_u64(); break;
4561
                        default: abort();
4562
                        }
4563
                        break;
4564
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4565
                        switch (size) {
4566
                        case 0: gen_op_neon_subl_u16(); break;
4567
                        case 1: gen_op_neon_subl_u32(); break;
4568
                        case 2: gen_op_neon_subl_u64(); break;
4569
                        default: abort();
4570
                        }
4571
                        break;
4572
                    case 5: case 7: /* VABAL, VABDL */
4573
                        switch ((size << 1) | u) {
4574
                        case 0: gen_op_neon_abdl_s16(); break;
4575
                        case 1: gen_op_neon_abdl_u16(); break;
4576
                        case 2: gen_op_neon_abdl_s32(); break;
4577
                        case 3: gen_op_neon_abdl_u32(); break;
4578
                        case 4: gen_op_neon_abdl_s64(); break;
4579
                        case 5: gen_op_neon_abdl_u64(); break;
4580
                        default: abort();
4581
                        }
4582
                        break;
4583
                    case 8: case 9: case 10: case 11: case 12: case 13:
4584
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4585
                        switch ((size << 1) | u) {
4586
                        case 0: gen_op_neon_mull_s8(); break;
4587
                        case 1: gen_op_neon_mull_u8(); break;
4588
                        case 2: gen_op_neon_mull_s16(); break;
4589
                        case 3: gen_op_neon_mull_u16(); break;
4590
                        case 4: gen_op_imull_T0_T1(); break;
4591
                        case 5: gen_op_mull_T0_T1(); break;
4592
                        default: abort();
4593
                        }
4594
                        break;
4595
                    case 14: /* Polynomial VMULL */
4596
                        cpu_abort(env, "Polynomial VMULL not implemented");
4597

    
4598
                    default: /* 15 is RESERVED.  */
4599
                        return 1;
4600
                    }
4601
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4602
                        /* Accumulate.  */
4603
                        if (op == 10 || op == 11) {
4604
                            switch (size) {
4605
                            case 0: gen_op_neon_negl_u16(); break;
4606
                            case 1: gen_op_neon_negl_u32(); break;
4607
                            case 2: gen_op_neon_negl_u64(); break;
4608
                            default: abort();
4609
                            }
4610
                        }
4611

    
4612
                        gen_neon_movl_scratch_T0(0);
4613
                        gen_neon_movl_scratch_T1(1);
4614

    
4615
                        if (op != 13) {
4616
                            NEON_GET_REG(T0, rd, pass * 2);
4617
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4618
                        }
4619

    
4620
                        switch (op) {
4621
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4622
                            switch (size) {
4623
                            case 0: gen_op_neon_addl_u16(); break;
4624
                            case 1: gen_op_neon_addl_u32(); break;
4625
                            case 2: gen_op_neon_addl_u64(); break;
4626
                            default: abort();
4627
                            }
4628
                            break;
4629
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4630
                            switch (size) {
4631
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4632
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4633
                            default: abort();
4634
                            }
4635
                            /* Fall through.  */
4636
                        case 13: /* VQDMULL */
4637
                            switch (size) {
4638
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4639
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4640
                            default: abort();
4641
                            }
4642
                            break;
4643
                        default:
4644
                            abort();
4645
                        }
4646
                        NEON_SET_REG(T0, rd, pass * 2);
4647
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4648
                    } else if (op == 4 || op == 6) {
4649
                        /* Narrowing operation.  */
4650
                        if (u) {
4651
                            switch (size) {
4652
                            case 0: gen_op_neon_narrow_high_u8(); break;
4653
                            case 1: gen_op_neon_narrow_high_u16(); break;
4654
                            case 2: gen_op_movl_T0_T1(); break;
4655
                            default: abort();
4656
                            }
4657
                        } else {
4658
                            switch (size) {
4659
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4660
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4661
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4662
                            default: abort();
4663
                            }
4664
                        }
4665
                        NEON_SET_REG(T0, rd, pass);
4666
                    } else {
4667
                        /* Write back the result.  */
4668
                        NEON_SET_REG(T0, rd, pass * 2);
4669
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4670
                    }
4671
                }
4672
            } else {
4673
                /* Two registers and a scalar.  */
4674
                switch (op) {
4675
                case 0: /* Integer VMLA scalar */
4676
                case 1: /* Float VMLA scalar */
4677
                case 4: /* Integer VMLS scalar */
4678
                case 5: /* Floating point VMLS scalar */
4679
                case 8: /* Integer VMUL scalar */
4680
                case 9: /* Floating point VMUL scalar */
4681
                case 12: /* VQDMULH scalar */
4682
                case 13: /* VQRDMULH scalar */
4683
                    gen_neon_get_scalar(size, rm);
4684
                    gen_op_movl_T2_T0();
4685
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4686
                        if (pass != 0)
4687
                            gen_op_movl_T0_T2();
4688
                        NEON_GET_REG(T1, rn, pass);
4689
                        if (op == 12) {
4690
                            if (size == 1) {
4691
                                gen_op_neon_qdmulh_s16();
4692
                            } else {
4693
                                gen_op_neon_qdmulh_s32();
4694
                            }
4695
                        } else if (op == 13) {
4696
                            if (size == 1) {
4697
                                gen_op_neon_qrdmulh_s16();
4698
                            } else {
4699
                                gen_op_neon_qrdmulh_s32();
4700
                            }
4701
                        } else if (op & 1) {
4702
                            gen_op_neon_mul_f32();
4703
                        } else {
4704
                            switch (size) {
4705
                            case 0: gen_op_neon_mul_u8(); break;
4706
                            case 1: gen_op_neon_mul_u16(); break;
4707
                            case 2: gen_op_mul_T0_T1(); break;
4708
                            default: return 1;
4709
                            }
4710
                        }
4711
                        if (op < 8) {
4712
                            /* Accumulate.  */
4713
                            NEON_GET_REG(T1, rd, pass);
4714
                            switch (op) {
4715
                            case 0:
4716
                                gen_neon_add(size);
4717
                                break;
4718
                            case 1:
4719
                                gen_op_neon_add_f32();
4720
                                break;
4721
                            case 4:
4722
                                switch (size) {
4723
                                case 0: gen_op_neon_rsb_u8(); break;
4724
                                case 1: gen_op_neon_rsb_u16(); break;
4725
                                case 2: gen_op_rsbl_T0_T1(); break;
4726
                                default: return 1;
4727
                                }
4728
                                break;
4729
                            case 5:
4730
                                gen_op_neon_rsb_f32();
4731
                                break;
4732
                            default:
4733
                                abort();
4734
                            }
4735
                        }
4736
                        NEON_SET_REG(T0, rd, pass);
4737
                    }
4738
                    break;
4739
                case 2: /* VMLAL sclar */
4740