Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 8984bd2e

History | View | Annotate | Download (285 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_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
205
#define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206
#define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
207
#define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208
#define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
209
#define gen_op_rscl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[1], cpu_T[0])
210

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

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

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

    
231
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
232
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
233

    
234
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
235

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
414
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
415

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

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

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

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

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

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

    
461
/* T0 &= ~T1.  Clobbers T1.  */
462
/* FIXME: Implement bic natively.  */
463
static inline void gen_op_bicl_T0_T1(void)
464
{
465
    gen_op_notl_T1();
466
    gen_op_andl_T0_T1();
467
}
468

    
469
/* FIXME:  Implement this natively.  */
470
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
471
{
472
    TCGv tmp;
473

    
474
    if (i == 0)
475
        return;
476

    
477
    tmp = new_tmp();
478
    tcg_gen_shri_i32(tmp, t1, i);
479
    tcg_gen_shli_i32(t1, t1, 32 - i);
480
    tcg_gen_or_i32(t0, t1, tmp);
481
    dead_tmp(tmp);
482
}
483

    
484
static void shifter_out_im(TCGv var, int shift)
485
{
486
    TCGv tmp = new_tmp();
487
    if (shift == 0) {
488
        tcg_gen_andi_i32(tmp, var, 1);
489
    } else {
490
        tcg_gen_shri_i32(tmp, var, shift);
491
        if (shift != 31);
492
            tcg_gen_andi_i32(tmp, tmp, 1);
493
    }
494
    gen_set_CF(tmp);
495
    dead_tmp(tmp);
496
}
497

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

    
548
static inline void gen_arm_shift_reg(TCGv var, int shiftop,
549
                                     TCGv shift, int flags)
550
{
551
    if (flags) {
552
        switch (shiftop) {
553
        case 0: gen_helper_shl_cc(var, var, shift); break;
554
        case 1: gen_helper_shr_cc(var, var, shift); break;
555
        case 2: gen_helper_sar_cc(var, var, shift); break;
556
        case 3: gen_helper_ror_cc(var, var, shift); break;
557
        }
558
    } else {
559
        switch (shiftop) {
560
        case 0: gen_helper_shl(var, var, shift); break;
561
        case 1: gen_helper_shr(var, var, shift); break;
562
        case 2: gen_helper_sar(var, var, shift); break;
563
        case 3: gen_helper_ror(var, var, shift); break;
564
        }
565
    }
566
    dead_tmp(shift);
567
}
568

    
569
#define PAS_OP(pfx) \
570
    switch (op2) {  \
571
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
572
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
573
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
574
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
575
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
576
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
577
    }
578
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
579
{
580
    TCGv tmp;
581

    
582
    switch (op1) {
583
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
584
    case 1:
585
        tmp = tcg_temp_new(TCG_TYPE_PTR);
586
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
587
        PAS_OP(s)
588
        break;
589
    case 5:
590
        tmp = tcg_temp_new(TCG_TYPE_PTR);
591
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
592
        PAS_OP(u)
593
        break;
594
#undef gen_pas_helper
595
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
596
    case 2:
597
        PAS_OP(q);
598
        break;
599
    case 3:
600
        PAS_OP(sh);
601
        break;
602
    case 6:
603
        PAS_OP(uq);
604
        break;
605
    case 7:
606
        PAS_OP(uh);
607
        break;
608
#undef gen_pas_helper
609
    }
610
}
611
#undef PAS_OP
612

    
613
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
614
#define PAS_OP(pfx) \
615
    switch (op2) {  \
616
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
617
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
618
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
619
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
620
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
621
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
622
    }
623
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
624
{
625
    TCGv tmp;
626

    
627
    switch (op1) {
628
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
629
    case 0:
630
        tmp = tcg_temp_new(TCG_TYPE_PTR);
631
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
632
        PAS_OP(s)
633
        break;
634
    case 4:
635
        tmp = tcg_temp_new(TCG_TYPE_PTR);
636
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
637
        PAS_OP(u)
638
        break;
639
#undef gen_pas_helper
640
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
641
    case 1:
642
        PAS_OP(q);
643
        break;
644
    case 2:
645
        PAS_OP(sh);
646
        break;
647
    case 5:
648
        PAS_OP(uq);
649
        break;
650
    case 6:
651
        PAS_OP(uh);
652
        break;
653
#undef gen_pas_helper
654
    }
655
}
656
#undef PAS_OP
657

    
658
static void gen_test_cc(int cc, int label)
659
{
660
    TCGv tmp;
661
    TCGv tmp2;
662
    TCGv zero;
663
    int inv;
664

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

    
758
const uint8_t table_logic_cc[16] = {
759
    1, /* and */
760
    1, /* xor */
761
    0, /* sub */
762
    0, /* rsb */
763
    0, /* add */
764
    0, /* adc */
765
    0, /* sbc */
766
    0, /* rsc */
767
    1, /* andl */
768
    1, /* xorl */
769
    0, /* cmp */
770
    0, /* cmn */
771
    1, /* orr */
772
    1, /* mov */
773
    1, /* bic */
774
    1, /* mvn */
775
};
776

    
777
/* Set PC and Thumb state from an immediate address.  */
778
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
779
{
780
    TCGv tmp;
781

    
782
    s->is_jmp = DISAS_UPDATE;
783
    tmp = new_tmp();
784
    if (s->thumb != (addr & 1)) {
785
        tcg_gen_movi_i32(tmp, addr & 1);
786
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
787
    }
788
    tcg_gen_movi_i32(tmp, addr & ~1);
789
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));
790
    dead_tmp(tmp);
791
}
792

    
793
/* Set PC and Thumb state from var.  var is marked as dead.  */
794
static inline void gen_bx(DisasContext *s, TCGv var)
795
{
796
    TCGv tmp;
797

    
798
    s->is_jmp = DISAS_UPDATE;
799
    tmp = new_tmp();
800
    tcg_gen_andi_i32(tmp, var, 1);
801
    store_cpu_field(tmp, thumb);
802
    tcg_gen_andi_i32(var, var, ~1);
803
    store_cpu_field(var, regs[15]);
804
}
805

    
806
/* TODO: This should be removed.  Use gen_bx instead.  */
807
static inline void gen_bx_T0(DisasContext *s)
808
{
809
    TCGv tmp = new_tmp();
810
    tcg_gen_mov_i32(tmp, cpu_T[0]);
811
    gen_bx(s, tmp);
812
}
813

    
814
#if defined(CONFIG_USER_ONLY)
815
#define gen_ldst(name, s) gen_op_##name##_raw()
816
#else
817
#define gen_ldst(name, s) do { \
818
    s->is_mem = 1; \
819
    if (IS_USER(s)) \
820
        gen_op_##name##_user(); \
821
    else \
822
        gen_op_##name##_kernel(); \
823
    } while (0)
824
#endif
825
static inline TCGv gen_ld8s(TCGv addr, int index)
826
{
827
    TCGv tmp = new_tmp();
828
    tcg_gen_qemu_ld8s(tmp, addr, index);
829
    return tmp;
830
}
831
static inline TCGv gen_ld8u(TCGv addr, int index)
832
{
833
    TCGv tmp = new_tmp();
834
    tcg_gen_qemu_ld8u(tmp, addr, index);
835
    return tmp;
836
}
837
static inline TCGv gen_ld16s(TCGv addr, int index)
838
{
839
    TCGv tmp = new_tmp();
840
    tcg_gen_qemu_ld16s(tmp, addr, index);
841
    return tmp;
842
}
843
static inline TCGv gen_ld16u(TCGv addr, int index)
844
{
845
    TCGv tmp = new_tmp();
846
    tcg_gen_qemu_ld16u(tmp, addr, index);
847
    return tmp;
848
}
849
static inline TCGv gen_ld32(TCGv addr, int index)
850
{
851
    TCGv tmp = new_tmp();
852
    tcg_gen_qemu_ld32u(tmp, addr, index);
853
    return tmp;
854
}
855
static inline void gen_st8(TCGv val, TCGv addr, int index)
856
{
857
    tcg_gen_qemu_st8(val, addr, index);
858
    dead_tmp(val);
859
}
860
static inline void gen_st16(TCGv val, TCGv addr, int index)
861
{
862
    tcg_gen_qemu_st16(val, addr, index);
863
    dead_tmp(val);
864
}
865
static inline void gen_st32(TCGv val, TCGv addr, int index)
866
{
867
    tcg_gen_qemu_st32(val, addr, index);
868
    dead_tmp(val);
869
}
870

    
871
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
872
{
873
    load_reg_var(s, cpu_T[0], reg);
874
}
875

    
876
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
877
{
878
    load_reg_var(s, cpu_T[1], reg);
879
}
880

    
881
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
882
{
883
    load_reg_var(s, cpu_T[2], reg);
884
}
885

    
886
static inline void gen_set_pc_im(uint32_t val)
887
{
888
    TCGv tmp = new_tmp();
889
    tcg_gen_movi_i32(tmp, val);
890
    store_cpu_field(tmp, regs[15]);
891
}
892

    
893
static inline void gen_set_pc_T0(void)
894
{
895
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
896
}
897

    
898
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
899
{
900
    TCGv tmp;
901
    if (reg == 15) {
902
        tmp = new_tmp();
903
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
904
    } else {
905
        tmp = cpu_T[t];
906
    }
907
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
908
    if (reg == 15) {
909
        dead_tmp(tmp);
910
        s->is_jmp = DISAS_JUMP;
911
    }
912
}
913

    
914
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
915
{
916
    gen_movl_reg_TN(s, reg, 0);
917
}
918

    
919
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
920
{
921
    gen_movl_reg_TN(s, reg, 1);
922
}
923

    
924
/* Force a TB lookup after an instruction that changes the CPU state.  */
925
static inline void gen_lookup_tb(DisasContext *s)
926
{
927
    gen_op_movl_T0_im(s->pc);
928
    gen_movl_reg_T0(s, 15);
929
    s->is_jmp = DISAS_UPDATE;
930
}
931

    
932
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
933
                                       TCGv var)
934
{
935
    int val, rm, shift, shiftop;
936
    TCGv offset;
937

    
938
    if (!(insn & (1 << 25))) {
939
        /* immediate */
940
        val = insn & 0xfff;
941
        if (!(insn & (1 << 23)))
942
            val = -val;
943
        if (val != 0)
944
            tcg_gen_addi_i32(var, var, val);
945
    } else {
946
        /* shift/register */
947
        rm = (insn) & 0xf;
948
        shift = (insn >> 7) & 0x1f;
949
        shiftop = (insn >> 5) & 3;
950
        offset = load_reg(s, rm);
951
        gen_arm_shift_im(offset, shiftop, shift, 0);
952
        if (!(insn & (1 << 23)))
953
            tcg_gen_sub_i32(var, var, offset);
954
        else
955
            tcg_gen_add_i32(var, var, offset);
956
        dead_tmp(offset);
957
    }
958
}
959

    
960
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
961
                                        int extra, TCGv var)
962
{
963
    int val, rm;
964
    TCGv offset;
965

    
966
    if (insn & (1 << 22)) {
967
        /* immediate */
968
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
969
        if (!(insn & (1 << 23)))
970
            val = -val;
971
        val += extra;
972
        if (val != 0)
973
            tcg_gen_addi_i32(var, var, val);
974
    } else {
975
        /* register */
976
        if (extra)
977
            tcg_gen_addi_i32(var, var, extra);
978
        rm = (insn) & 0xf;
979
        offset = load_reg(s, rm);
980
        if (!(insn & (1 << 23)))
981
            tcg_gen_sub_i32(var, var, offset);
982
        else
983
            tcg_gen_add_i32(var, var, offset);
984
        dead_tmp(offset);
985
    }
986
}
987

    
988
#define VFP_OP2(name)                                                 \
989
static inline void gen_vfp_##name(int dp)                             \
990
{                                                                     \
991
    if (dp)                                                           \
992
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
993
    else                                                              \
994
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
995
}
996

    
997
#define VFP_OP1i(name)                               \
998
static inline void gen_vfp_##name(int dp, int arg)  \
999
{                                                   \
1000
    if (dp)                                         \
1001
        gen_op_vfp_##name##d(arg);                  \
1002
    else                                            \
1003
        gen_op_vfp_##name##s(arg);                  \
1004
}
1005

    
1006
VFP_OP2(add)
1007
VFP_OP2(sub)
1008
VFP_OP2(mul)
1009
VFP_OP2(div)
1010

    
1011
#undef VFP_OP2
1012

    
1013
static inline void gen_vfp_abs(int dp)
1014
{
1015
    if (dp)
1016
        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1017
    else
1018
        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1019
}
1020

    
1021
static inline void gen_vfp_neg(int dp)
1022
{
1023
    if (dp)
1024
        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1025
    else
1026
        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1027
}
1028

    
1029
static inline void gen_vfp_sqrt(int dp)
1030
{
1031
    if (dp)
1032
        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1033
    else
1034
        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1035
}
1036

    
1037
static inline void gen_vfp_cmp(int dp)
1038
{
1039
    if (dp)
1040
        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1041
    else
1042
        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1043
}
1044

    
1045
static inline void gen_vfp_cmpe(int dp)
1046
{
1047
    if (dp)
1048
        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1049
    else
1050
        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1051
}
1052

    
1053
static inline void gen_vfp_F1_ld0(int dp)
1054
{
1055
    if (dp)
1056
        tcg_gen_movi_i64(cpu_F0d, 0);
1057
    else
1058
        tcg_gen_movi_i32(cpu_F0s, 0);
1059
}
1060

    
1061
static inline void gen_vfp_uito(int dp)
1062
{
1063
    if (dp)
1064
        gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
1065
    else
1066
        gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
1067
}
1068

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

    
1077
static inline void gen_vfp_toui(int dp)
1078
{
1079
    if (dp)
1080
        gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
1081
    else
1082
        gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
1083
}
1084

    
1085
static inline void gen_vfp_touiz(int dp)
1086
{
1087
    if (dp)
1088
        gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
1089
    else
1090
        gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
1091
}
1092

    
1093
static inline void gen_vfp_tosi(int dp)
1094
{
1095
    if (dp)
1096
        gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
1097
    else
1098
        gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1099
}
1100

    
1101
static inline void gen_vfp_tosiz(int dp)
1102
{
1103
    if (dp)
1104
        gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1105
    else
1106
        gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1107
}
1108

    
1109
#define VFP_GEN_FIX(name) \
1110
static inline void gen_vfp_##name(int dp, int shift) \
1111
{ \
1112
    if (dp) \
1113
        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1114
    else \
1115
        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1116
}
1117
VFP_GEN_FIX(tosh)
1118
VFP_GEN_FIX(tosl)
1119
VFP_GEN_FIX(touh)
1120
VFP_GEN_FIX(toul)
1121
VFP_GEN_FIX(shto)
1122
VFP_GEN_FIX(slto)
1123
VFP_GEN_FIX(uhto)
1124
VFP_GEN_FIX(ulto)
1125
#undef VFP_GEN_FIX
1126

    
1127
static inline void gen_vfp_ld(DisasContext *s, int dp)
1128
{
1129
    if (dp)
1130
        tcg_gen_qemu_ld64(cpu_F0d, cpu_T[1], IS_USER(s));
1131
    else
1132
        tcg_gen_qemu_ld32u(cpu_F0s, cpu_T[1], IS_USER(s));
1133
}
1134

    
1135
static inline void gen_vfp_st(DisasContext *s, int dp)
1136
{
1137
    if (dp)
1138
        tcg_gen_qemu_st64(cpu_F0d, cpu_T[1], IS_USER(s));
1139
    else
1140
        tcg_gen_qemu_st32(cpu_F0s, cpu_T[1], IS_USER(s));
1141
}
1142

    
1143
static inline long
1144
vfp_reg_offset (int dp, int reg)
1145
{
1146
    if (dp)
1147
        return offsetof(CPUARMState, vfp.regs[reg]);
1148
    else if (reg & 1) {
1149
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1150
          + offsetof(CPU_DoubleU, l.upper);
1151
    } else {
1152
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
1153
          + offsetof(CPU_DoubleU, l.lower);
1154
    }
1155
}
1156

    
1157
/* Return the offset of a 32-bit piece of a NEON register.
1158
   zero is the least significant end of the register.  */
1159
static inline long
1160
neon_reg_offset (int reg, int n)
1161
{
1162
    int sreg;
1163
    sreg = reg * 2 + n;
1164
    return vfp_reg_offset(0, sreg);
1165
}
1166

    
1167
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
1168
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
1169

    
1170
#define tcg_gen_ld_f32 tcg_gen_ld_i32
1171
#define tcg_gen_ld_f64 tcg_gen_ld_i64
1172
#define tcg_gen_st_f32 tcg_gen_st_i32
1173
#define tcg_gen_st_f64 tcg_gen_st_i64
1174

    
1175
static inline void gen_mov_F0_vreg(int dp, int reg)
1176
{
1177
    if (dp)
1178
        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1179
    else
1180
        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1181
}
1182

    
1183
static inline void gen_mov_F1_vreg(int dp, int reg)
1184
{
1185
    if (dp)
1186
        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1187
    else
1188
        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1189
}
1190

    
1191
static inline void gen_mov_vreg_F0(int dp, int reg)
1192
{
1193
    if (dp)
1194
        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1195
    else
1196
        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1197
}
1198

    
1199
#define ARM_CP_RW_BIT        (1 << 20)
1200

    
1201
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
1202
{
1203
    int rd;
1204
    uint32_t offset;
1205

    
1206
    rd = (insn >> 16) & 0xf;
1207
    gen_movl_T1_reg(s, rd);
1208

    
1209
    offset = (insn & 0xff) << ((insn >> 7) & 2);
1210
    if (insn & (1 << 24)) {
1211
        /* Pre indexed */
1212
        if (insn & (1 << 23))
1213
            gen_op_addl_T1_im(offset);
1214
        else
1215
            gen_op_addl_T1_im(-offset);
1216

    
1217
        if (insn & (1 << 21))
1218
            gen_movl_reg_T1(s, rd);
1219
    } else if (insn & (1 << 21)) {
1220
        /* Post indexed */
1221
        if (insn & (1 << 23))
1222
            gen_op_movl_T0_im(offset);
1223
        else
1224
            gen_op_movl_T0_im(- offset);
1225
        gen_op_addl_T0_T1();
1226
        gen_movl_reg_T0(s, rd);
1227
    } else if (!(insn & (1 << 23)))
1228
        return 1;
1229
    return 0;
1230
}
1231

    
1232
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
1233
{
1234
    int rd = (insn >> 0) & 0xf;
1235

    
1236
    if (insn & (1 << 8))
1237
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
1238
            return 1;
1239
        else
1240
            gen_op_iwmmxt_movl_T0_wCx(rd);
1241
    else
1242
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
1243

    
1244
    gen_op_movl_T1_im(mask);
1245
    gen_op_andl_T0_T1();
1246
    return 0;
1247
}
1248

    
1249
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
1250
   (ie. an undefined instruction).  */
1251
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1252
{
1253
    int rd, wrd;
1254
    int rdhi, rdlo, rd0, rd1, i;
1255
    TCGv tmp;
1256

    
1257
    if ((insn & 0x0e000e00) == 0x0c000000) {
1258
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
1259
            wrd = insn & 0xf;
1260
            rdlo = (insn >> 12) & 0xf;
1261
            rdhi = (insn >> 16) & 0xf;
1262
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
1263
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
1264
                gen_movl_reg_T0(s, rdlo);
1265
                gen_movl_reg_T1(s, rdhi);
1266
            } else {                                        /* TMCRR */
1267
                gen_movl_T0_reg(s, rdlo);
1268
                gen_movl_T1_reg(s, rdhi);
1269
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
1270
                gen_op_iwmmxt_set_mup();
1271
            }
1272
            return 0;
1273
        }
1274

    
1275
        wrd = (insn >> 12) & 0xf;
1276
        if (gen_iwmmxt_address(s, insn))
1277
            return 1;
1278
        if (insn & ARM_CP_RW_BIT) {
1279
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
1280
                tmp = gen_ld32(cpu_T[1], IS_USER(s));
1281
                tcg_gen_mov_i32(cpu_T[0], tmp);
1282
                dead_tmp(tmp);
1283
                gen_op_iwmmxt_movl_wCx_T0(wrd);
1284
            } else {
1285
                if (insn & (1 << 8))
1286
                    if (insn & (1 << 22))                /* WLDRD */
1287
                        gen_ldst(iwmmxt_ldq, s);
1288
                    else                                /* WLDRW wRd */
1289
                        gen_ldst(iwmmxt_ldl, s);
1290
                else
1291
                    if (insn & (1 << 22))                /* WLDRH */
1292
                        gen_ldst(iwmmxt_ldw, s);
1293
                    else                                /* WLDRB */
1294
                        gen_ldst(iwmmxt_ldb, s);
1295
                gen_op_iwmmxt_movq_wRn_M0(wrd);
1296
            }
1297
        } else {
1298
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
1299
                gen_op_iwmmxt_movl_T0_wCx(wrd);
1300
                tmp = new_tmp();
1301
                tcg_gen_mov_i32(tmp, cpu_T[0]);
1302
                gen_st32(tmp, cpu_T[1], IS_USER(s));
1303
            } else {
1304
                gen_op_iwmmxt_movq_M0_wRn(wrd);
1305
                if (insn & (1 << 8))
1306
                    if (insn & (1 << 22))                /* WSTRD */
1307
                        gen_ldst(iwmmxt_stq, s);
1308
                    else                                /* WSTRW wRd */
1309
                        gen_ldst(iwmmxt_stl, s);
1310
                else
1311
                    if (insn & (1 << 22))                /* WSTRH */
1312
                        gen_ldst(iwmmxt_ldw, s);
1313
                    else                                /* WSTRB */
1314
                        gen_ldst(iwmmxt_stb, s);
1315
            }
1316
        }
1317
        return 0;
1318
    }
1319

    
1320
    if ((insn & 0x0f000000) != 0x0e000000)
1321
        return 1;
1322

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

    
2186
    return 0;
2187
}
2188

    
2189
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
2190
   (ie. an undefined instruction).  */
2191
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2192
{
2193
    int acc, rd0, rd1, rdhi, rdlo;
2194

    
2195
    if ((insn & 0x0ff00f10) == 0x0e200010) {
2196
        /* Multiply with Internal Accumulate Format */
2197
        rd0 = (insn >> 12) & 0xf;
2198
        rd1 = insn & 0xf;
2199
        acc = (insn >> 5) & 7;
2200

    
2201
        if (acc != 0)
2202
            return 1;
2203

    
2204
        switch ((insn >> 16) & 0xf) {
2205
        case 0x0:                                        /* MIA */
2206
            gen_movl_T0_reg(s, rd0);
2207
            gen_movl_T1_reg(s, rd1);
2208
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
2209
            break;
2210
        case 0x8:                                        /* MIAPH */
2211
            gen_movl_T0_reg(s, rd0);
2212
            gen_movl_T1_reg(s, rd1);
2213
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
2214
            break;
2215
        case 0xc:                                        /* MIABB */
2216
        case 0xd:                                        /* MIABT */
2217
        case 0xe:                                        /* MIATB */
2218
        case 0xf:                                        /* MIATT */
2219
            gen_movl_T1_reg(s, rd0);
2220
            if (insn & (1 << 16))
2221
                gen_op_shrl_T1_im(16);
2222
            gen_op_movl_T0_T1();
2223
            gen_movl_T1_reg(s, rd1);
2224
            if (insn & (1 << 17))
2225
                gen_op_shrl_T1_im(16);
2226
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
2227
            break;
2228
        default:
2229
            return 1;
2230
        }
2231

    
2232
        gen_op_iwmmxt_movq_wRn_M0(acc);
2233
        return 0;
2234
    }
2235

    
2236
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
2237
        /* Internal Accumulator Access Format */
2238
        rdhi = (insn >> 16) & 0xf;
2239
        rdlo = (insn >> 12) & 0xf;
2240
        acc = insn & 7;
2241

    
2242
        if (acc != 0)
2243
            return 1;
2244

    
2245
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
2246
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
2247
            gen_movl_reg_T0(s, rdlo);
2248
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2249
            gen_op_andl_T0_T1();
2250
            gen_movl_reg_T0(s, rdhi);
2251
        } else {                                        /* MAR */
2252
            gen_movl_T0_reg(s, rdlo);
2253
            gen_movl_T1_reg(s, rdhi);
2254
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
2255
        }
2256
        return 0;
2257
    }
2258

    
2259
    return 1;
2260
}
2261

    
2262
/* Disassemble system coprocessor instruction.  Return nonzero if
2263
   instruction is not defined.  */
2264
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2265
{
2266
    TCGv tmp;
2267
    uint32_t rd = (insn >> 12) & 0xf;
2268
    uint32_t cp = (insn >> 8) & 0xf;
2269
    if (IS_USER(s)) {
2270
        return 1;
2271
    }
2272

    
2273
    if (insn & ARM_CP_RW_BIT) {
2274
        if (!env->cp[cp].cp_read)
2275
            return 1;
2276
        gen_set_pc_im(s->pc);
2277
        tmp = new_tmp();
2278
        gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2279
        store_reg(s, rd, tmp);
2280
    } else {
2281
        if (!env->cp[cp].cp_write)
2282
            return 1;
2283
        gen_set_pc_im(s->pc);
2284
        tmp = load_reg(s, rd);
2285
        gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2286
    }
2287
    return 0;
2288
}
2289

    
2290
static int cp15_user_ok(uint32_t insn)
2291
{
2292
    int cpn = (insn >> 16) & 0xf;
2293
    int cpm = insn & 0xf;
2294
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2295

    
2296
    if (cpn == 13 && cpm == 0) {
2297
        /* TLS register.  */
2298
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2299
            return 1;
2300
    }
2301
    if (cpn == 7) {
2302
        /* ISB, DSB, DMB.  */
2303
        if ((cpm == 5 && op == 4)
2304
                || (cpm == 10 && (op == 4 || op == 5)))
2305
            return 1;
2306
    }
2307
    return 0;
2308
}
2309

    
2310
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2311
   instruction is not defined.  */
2312
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2313
{
2314
    uint32_t rd;
2315
    TCGv tmp;
2316

    
2317
    /* M profile cores use memory mapped registers instead of cp15.  */
2318
    if (arm_feature(env, ARM_FEATURE_M))
2319
        return 1;
2320

    
2321
    if ((insn & (1 << 25)) == 0) {
2322
        if (insn & (1 << 20)) {
2323
            /* mrrc */
2324
            return 1;
2325
        }
2326
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2327
        return 0;
2328
    }
2329
    if ((insn & (1 << 4)) == 0) {
2330
        /* cdp */
2331
        return 1;
2332
    }
2333
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2334
        return 1;
2335
    }
2336
    if ((insn & 0x0fff0fff) == 0x0e070f90
2337
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2338
        /* Wait for interrupt.  */
2339
        gen_set_pc_im(s->pc);
2340
        s->is_jmp = DISAS_WFI;
2341
        return 0;
2342
    }
2343
    rd = (insn >> 12) & 0xf;
2344
    if (insn & ARM_CP_RW_BIT) {
2345
        tmp = new_tmp();
2346
        gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2347
        /* If the destination register is r15 then sets condition codes.  */
2348
        if (rd != 15)
2349
            store_reg(s, rd, tmp);
2350
        else
2351
            dead_tmp(tmp);
2352
    } else {
2353
        tmp = load_reg(s, rd);
2354
        gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2355
        dead_tmp(tmp);
2356
        /* Normally we would always end the TB here, but Linux
2357
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2358
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2359
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2360
                (insn & 0x0fff0fff) != 0x0e010f10)
2361
            gen_lookup_tb(s);
2362
    }
2363
    return 0;
2364
}
2365

    
2366
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2367
#define VFP_SREG(insn, bigbit, smallbit) \
2368
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2369
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2370
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2371
        reg = (((insn) >> (bigbit)) & 0x0f) \
2372
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2373
    } else { \
2374
        if (insn & (1 << (smallbit))) \
2375
            return 1; \
2376
        reg = ((insn) >> (bigbit)) & 0x0f; \
2377
    }} while (0)
2378

    
2379
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2380
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2381
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2382
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2383
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2384
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2385

    
2386
/* Move between integer and VFP cores.  */
2387
static TCGv gen_vfp_mrs(void)
2388
{
2389
    TCGv tmp = new_tmp();
2390
    tcg_gen_mov_i32(tmp, cpu_F0s);
2391
    return tmp;
2392
}
2393

    
2394
static void gen_vfp_msr(TCGv tmp)
2395
{
2396
    tcg_gen_mov_i32(cpu_F0s, tmp);
2397
    dead_tmp(tmp);
2398
}
2399

    
2400
static inline int
2401
vfp_enabled(CPUState * env)
2402
{
2403
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2404
}
2405

    
2406
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2407
   (ie. an undefined instruction).  */
2408
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2409
{
2410
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2411
    int dp, veclen;
2412
    TCGv tmp;
2413

    
2414
    if (!arm_feature(env, ARM_FEATURE_VFP))
2415
        return 1;
2416

    
2417
    if (!vfp_enabled(env)) {
2418
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2419
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2420
            return 1;
2421
        rn = (insn >> 16) & 0xf;
2422
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2423
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2424
            return 1;
2425
    }
2426
    dp = ((insn & 0xf00) == 0xb00);
2427
    switch ((insn >> 24) & 0xf) {
2428
    case 0xe:
2429
        if (insn & (1 << 4)) {
2430
            /* single register transfer */
2431
            rd = (insn >> 12) & 0xf;
2432
            if (dp) {
2433
                int size;
2434
                int pass;
2435

    
2436
                VFP_DREG_N(rn, insn);
2437
                if (insn & 0xf)
2438
                    return 1;
2439
                if (insn & 0x00c00060
2440
                    && !arm_feature(env, ARM_FEATURE_NEON))
2441
                    return 1;
2442

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

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

    
2635
                if (op == 15 && (rn == 15 || rn > 17)) {
2636
                    /* Integer or single precision destination.  */
2637
                    rd = VFP_SREG_D(insn);
2638
                } else {
2639
                    VFP_DREG_D(rd, insn);
2640
                }
2641

    
2642
                if (op == 15 && (rn == 16 || rn == 17)) {
2643
                    /* Integer source.  */
2644
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2645
                } else {
2646
                    VFP_DREG_M(rm, insn);
2647
                }
2648
            } else {
2649
                rn = VFP_SREG_N(insn);
2650
                if (op == 15 && rn == 15) {
2651
                    /* Double precision destination.  */
2652
                    VFP_DREG_D(rd, insn);
2653
                } else {
2654
                    rd = VFP_SREG_D(insn);
2655
                }
2656
                rm = VFP_SREG_M(insn);
2657
            }
2658

    
2659
            veclen = env->vfp.vec_len;
2660
            if (op == 15 && rn > 3)
2661
                veclen = 0;
2662

    
2663
            /* Shut up compiler warnings.  */
2664
            delta_m = 0;
2665
            delta_d = 0;
2666
            bank_mask = 0;
2667

    
2668
            if (veclen > 0) {
2669
                if (dp)
2670
                    bank_mask = 0xc;
2671
                else
2672
                    bank_mask = 0x18;
2673

    
2674
                /* Figure out what type of vector operation this is.  */
2675
                if ((rd & bank_mask) == 0) {
2676
                    /* scalar */
2677
                    veclen = 0;
2678
                } else {
2679
                    if (dp)
2680
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2681
                    else
2682
                        delta_d = env->vfp.vec_stride + 1;
2683

    
2684
                    if ((rm & bank_mask) == 0) {
2685
                        /* mixed scalar/vector */
2686
                        delta_m = 0;
2687
                    } else {
2688
                        /* vector */
2689
                        delta_m = delta_d;
2690
                    }
2691
                }
2692
            }
2693

    
2694
            /* Load the initial operands.  */
2695
            if (op == 15) {
2696
                switch (rn) {
2697
                case 16:
2698
                case 17:
2699
                    /* Integer source */
2700
                    gen_mov_F0_vreg(0, rm);
2701
                    break;
2702
                case 8:
2703
                case 9:
2704
                    /* Compare */
2705
                    gen_mov_F0_vreg(dp, rd);
2706
                    gen_mov_F1_vreg(dp, rm);
2707
                    break;
2708
                case 10:
2709
                case 11:
2710
                    /* Compare with zero */
2711
                    gen_mov_F0_vreg(dp, rd);
2712
                    gen_vfp_F1_ld0(dp);
2713
                    break;
2714
                case 20:
2715
                case 21:
2716
                case 22:
2717
                case 23:
2718
                    /* Source and destination the same.  */
2719
                    gen_mov_F0_vreg(dp, rd);
2720
                    break;
2721
                default:
2722
                    /* One source operand.  */
2723
                    gen_mov_F0_vreg(dp, rm);
2724
                    break;
2725
                }
2726
            } else {
2727
                /* Two source operands.  */
2728
                gen_mov_F0_vreg(dp, rn);
2729
                gen_mov_F1_vreg(dp, rm);
2730
            }
2731

    
2732
            for (;;) {
2733
                /* Perform the calculation.  */
2734
                switch (op) {
2735
                case 0: /* mac: fd + (fn * fm) */
2736
                    gen_vfp_mul(dp);
2737
                    gen_mov_F1_vreg(dp, rd);
2738
                    gen_vfp_add(dp);
2739
                    break;
2740
                case 1: /* nmac: fd - (fn * fm) */
2741
                    gen_vfp_mul(dp);
2742
                    gen_vfp_neg(dp);
2743
                    gen_mov_F1_vreg(dp, rd);
2744
                    gen_vfp_add(dp);
2745
                    break;
2746
                case 2: /* msc: -fd + (fn * fm) */
2747
                    gen_vfp_mul(dp);
2748
                    gen_mov_F1_vreg(dp, rd);
2749
                    gen_vfp_sub(dp);
2750
                    break;
2751
                case 3: /* nmsc: -fd - (fn * fm)  */
2752
                    gen_vfp_mul(dp);
2753
                    gen_mov_F1_vreg(dp, rd);
2754
                    gen_vfp_add(dp);
2755
                    gen_vfp_neg(dp);
2756
                    break;
2757
                case 4: /* mul: fn * fm */
2758
                    gen_vfp_mul(dp);
2759
                    break;
2760
                case 5: /* nmul: -(fn * fm) */
2761
                    gen_vfp_mul(dp);
2762
                    gen_vfp_neg(dp);
2763
                    break;
2764
                case 6: /* add: fn + fm */
2765
                    gen_vfp_add(dp);
2766
                    break;
2767
                case 7: /* sub: fn - fm */
2768
                    gen_vfp_sub(dp);
2769
                    break;
2770
                case 8: /* div: fn / fm */
2771
                    gen_vfp_div(dp);
2772
                    break;
2773
                case 14: /* fconst */
2774
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2775
                      return 1;
2776

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

    
2896
                /* Write back the result.  */
2897
                if (op == 15 && (rn >= 8 && rn <= 11))
2898
                    ; /* Comparison, do nothing.  */
2899
                else if (op == 15 && rn > 17)
2900
                    /* Integer result.  */
2901
                    gen_mov_vreg_F0(0, rd);
2902
                else if (op == 15 && rn == 15)
2903
                    /* conversion */
2904
                    gen_mov_vreg_F0(!dp, rd);
2905
                else
2906
                    gen_mov_vreg_F0(dp, rd);
2907

    
2908
                /* break out of the loop if we have finished  */
2909
                if (veclen == 0)
2910
                    break;
2911

    
2912
                if (op == 15 && delta_m == 0) {
2913
                    /* single source one-many */
2914
                    while (veclen--) {
2915
                        rd = ((rd + delta_d) & (bank_mask - 1))
2916
                             | (rd & bank_mask);
2917
                        gen_mov_vreg_F0(dp, rd);
2918
                    }
2919
                    break;
2920
                }
2921
                /* Setup the next operands.  */
2922
                veclen--;
2923
                rd = ((rd + delta_d) & (bank_mask - 1))
2924
                     | (rd & bank_mask);
2925

    
2926
                if (op == 15) {
2927
                    /* One source operand.  */
2928
                    rm = ((rm + delta_m) & (bank_mask - 1))
2929
                         | (rm & bank_mask);
2930
                    gen_mov_F0_vreg(dp, rm);
2931
                } else {
2932
                    /* Two source operands.  */
2933
                    rn = ((rn + delta_d) & (bank_mask - 1))
2934
                         | (rn & bank_mask);
2935
                    gen_mov_F0_vreg(dp, rn);
2936
                    if (delta_m) {
2937
                        rm = ((rm + delta_m) & (bank_mask - 1))
2938
                             | (rm & bank_mask);
2939
                        gen_mov_F1_vreg(dp, rm);
2940
                    }
2941
                }
2942
            }
2943
        }
2944
        break;
2945
    case 0xc:
2946
    case 0xd:
2947
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2948
            /* two-register transfer */
2949
            rn = (insn >> 16) & 0xf;
2950
            rd = (insn >> 12) & 0xf;
2951
            if (dp) {
2952
                VFP_DREG_M(rm, insn);
2953
            } else {
2954
                rm = VFP_SREG_M(insn);
2955
            }
2956

    
2957
            if (insn & ARM_CP_RW_BIT) {
2958
                /* vfp->arm */
2959
                if (dp) {
2960
                    gen_mov_F0_vreg(0, rm * 2);
2961
                    tmp = gen_vfp_mrs();
2962
                    store_reg(s, rd, tmp);
2963
                    gen_mov_F0_vreg(0, rm * 2 + 1);
2964
                    tmp = gen_vfp_mrs();
2965
                    store_reg(s, rn, tmp);
2966
                } else {
2967
                    gen_mov_F0_vreg(0, rm);
2968
                    tmp = gen_vfp_mrs();
2969
                    store_reg(s, rn, tmp);
2970
                    gen_mov_F0_vreg(0, rm + 1);
2971
                    tmp = gen_vfp_mrs();
2972
                    store_reg(s, rd, tmp);
2973
                }
2974
            } else {
2975
                /* arm->vfp */
2976
                if (dp) {
2977
                    tmp = load_reg(s, rd);
2978
                    gen_vfp_msr(tmp);
2979
                    gen_mov_vreg_F0(0, rm * 2);
2980
                    tmp = load_reg(s, rn);
2981
                    gen_vfp_msr(tmp);
2982
                    gen_mov_vreg_F0(0, rm * 2 + 1);
2983
                } else {
2984
                    tmp = load_reg(s, rn);
2985
                    gen_vfp_msr(tmp);
2986
                    gen_mov_vreg_F0(0, rm);
2987
                    tmp = load_reg(s, rd);
2988
                    gen_vfp_msr(tmp);
2989
                    gen_mov_vreg_F0(0, rm + 1);
2990
                }
2991
            }
2992
        } else {
2993
            /* Load/store */
2994
            rn = (insn >> 16) & 0xf;
2995
            if (dp)
2996
                VFP_DREG_D(rd, insn);
2997
            else
2998
                rd = VFP_SREG_D(insn);
2999
            if (s->thumb && rn == 15) {
3000
                gen_op_movl_T1_im(s->pc & ~2);
3001
            } else {
3002
                gen_movl_T1_reg(s, rn);
3003
            }
3004
            if ((insn & 0x01200000) == 0x01000000) {
3005
                /* Single load/store */
3006
                offset = (insn & 0xff) << 2;
3007
                if ((insn & (1 << 23)) == 0)
3008
                    offset = -offset;
3009
                gen_op_addl_T1_im(offset);
3010
                if (insn & (1 << 20)) {
3011
                    gen_vfp_ld(s, dp);
3012
                    gen_mov_vreg_F0(dp, rd);
3013
                } else {
3014
                    gen_mov_F0_vreg(dp, rd);
3015
                    gen_vfp_st(s, dp);
3016
                }
3017
            } else {
3018
                /* load/store multiple */
3019
                if (dp)
3020
                    n = (insn >> 1) & 0x7f;
3021
                else
3022
                    n = insn & 0xff;
3023

    
3024
                if (insn & (1 << 24)) /* pre-decrement */
3025
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
3026

    
3027
                if (dp)
3028
                    offset = 8;
3029
                else
3030
                    offset = 4;
3031
                for (i = 0; i < n; i++) {
3032
                    if (insn & ARM_CP_RW_BIT) {
3033
                        /* load */
3034
                        gen_vfp_ld(s, dp);
3035
                        gen_mov_vreg_F0(dp, rd + i);
3036
                    } else {
3037
                        /* store */
3038
                        gen_mov_F0_vreg(dp, rd + i);
3039
                        gen_vfp_st(s, dp);
3040
                    }
3041
                    gen_op_addl_T1_im(offset);
3042
                }
3043
                if (insn & (1 << 21)) {
3044
                    /* writeback */
3045
                    if (insn & (1 << 24))
3046
                        offset = -offset * n;
3047
                    else if (dp && (insn & 1))
3048
                        offset = 4;
3049
                    else
3050
                        offset = 0;
3051

    
3052
                    if (offset != 0)
3053
                        gen_op_addl_T1_im(offset);
3054
                    gen_movl_reg_T1(s, rn);
3055
                }
3056
            }
3057
        }
3058
        break;
3059
    default:
3060
        /* Should never happen.  */
3061
        return 1;
3062
    }
3063
    return 0;
3064
}
3065

    
3066
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3067
{
3068
    TranslationBlock *tb;
3069

    
3070
    tb = s->tb;
3071
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3072
        tcg_gen_goto_tb(n);
3073
        gen_set_pc_im(dest);
3074
        tcg_gen_exit_tb((long)tb + n);
3075
    } else {
3076
        gen_set_pc_im(dest);
3077
        tcg_gen_exit_tb(0);
3078
    }
3079
}
3080

    
3081
static inline void gen_jmp (DisasContext *s, uint32_t dest)
3082
{
3083
    if (__builtin_expect(s->singlestep_enabled, 0)) {
3084
        /* An indirect jump so that we still trigger the debug exception.  */
3085
        if (s->thumb)
3086
            dest |= 1;
3087
        gen_bx_im(s, dest);
3088
    } else {
3089
        gen_goto_tb(s, 0, dest);
3090
        s->is_jmp = DISAS_TB_JUMP;
3091
    }
3092
}
3093

    
3094
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3095
{
3096
    if (x)
3097
        tcg_gen_sari_i32(t0, t0, 16);
3098
    else
3099
        gen_sxth(t0);
3100
    if (y)
3101
        tcg_gen_sari_i32(t1, t1, 16);
3102
    else
3103
        gen_sxth(t1);
3104
    tcg_gen_mul_i32(t0, t0, t1);
3105
}
3106

    
3107
/* Return the mask of PSR bits set by a MSR instruction.  */
3108
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3109
    uint32_t mask;
3110

    
3111
    mask = 0;
3112
    if (flags & (1 << 0))
3113
        mask |= 0xff;
3114
    if (flags & (1 << 1))
3115
        mask |= 0xff00;
3116
    if (flags & (1 << 2))
3117
        mask |= 0xff0000;
3118
    if (flags & (1 << 3))
3119
        mask |= 0xff000000;
3120

    
3121
    /* Mask out undefined bits.  */
3122
    mask &= ~CPSR_RESERVED;
3123
    if (!arm_feature(env, ARM_FEATURE_V6))
3124
        mask &= ~(CPSR_E | CPSR_GE);
3125
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
3126
        mask &= ~CPSR_IT;
3127
    /* Mask out execution state bits.  */
3128
    if (!spsr)
3129
        mask &= ~CPSR_EXEC;
3130
    /* Mask out privileged bits.  */
3131
    if (IS_USER(s))
3132
        mask &= CPSR_USER;
3133
    return mask;
3134
}
3135

    
3136
/* Returns nonzero if access to the PSR is not permitted.  */
3137
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
3138
{
3139
    TCGv tmp;
3140
    if (spsr) {
3141
        /* ??? This is also undefined in system mode.  */
3142
        if (IS_USER(s))
3143
            return 1;
3144

    
3145
        tmp = load_cpu_field(spsr);
3146
        tcg_gen_andi_i32(tmp, tmp, ~mask);
3147
        tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask);
3148
        tcg_gen_or_i32(tmp, tmp, cpu_T[0]);
3149
        store_cpu_field(tmp, spsr);
3150
    } else {
3151
        gen_set_cpsr(cpu_T[0], mask);
3152
    }
3153
    gen_lookup_tb(s);
3154
    return 0;
3155
}
3156

    
3157
/* Generate an old-style exception return.  */
3158
static void gen_exception_return(DisasContext *s)
3159
{
3160
    TCGv tmp;
3161
    gen_set_pc_T0();
3162
    tmp = load_cpu_field(spsr);
3163
    gen_set_cpsr(tmp, 0xffffffff);
3164
    dead_tmp(tmp);
3165
    s->is_jmp = DISAS_UPDATE;
3166
}
3167

    
3168
/* Generate a v6 exception return.  Marks both values as dead.  */
3169
static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3170
{
3171
    gen_set_cpsr(cpsr, 0xffffffff);
3172
    dead_tmp(cpsr);
3173
    store_reg(s, 15, pc);
3174
    s->is_jmp = DISAS_UPDATE;
3175
}
3176

    
3177
static inline void
3178
gen_set_condexec (DisasContext *s)
3179
{
3180
    if (s->condexec_mask) {
3181
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3182
        TCGv tmp = new_tmp();
3183
        tcg_gen_movi_i32(tmp, val);
3184
        store_cpu_field(tmp, condexec_bits);
3185
    }
3186
}
3187

    
3188
static void gen_nop_hint(DisasContext *s, int val)
3189
{
3190
    switch (val) {
3191
    case 3: /* wfi */
3192
        gen_set_pc_im(s->pc);
3193
        s->is_jmp = DISAS_WFI;
3194
        break;
3195
    case 2: /* wfe */
3196
    case 4: /* sev */
3197
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
3198
    default: /* nop */
3199
        break;
3200
    }
3201
}
3202

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

    
3302
/* [R][U][size - 1] */
3303
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
3304
    {
3305
      {
3306
        gen_op_neon_shl_u16,
3307
        gen_op_neon_shl_u32,
3308
        gen_op_neon_shl_u64
3309
      }, {
3310
        gen_op_neon_shl_s16,
3311
        gen_op_neon_shl_s32,
3312
        gen_op_neon_shl_s64
3313
      }
3314
    }, {
3315
      {
3316
        gen_op_neon_rshl_u16,
3317
        gen_op_neon_rshl_u32,
3318
        gen_op_neon_rshl_u64
3319
      }, {
3320
        gen_op_neon_rshl_s16,
3321
        gen_op_neon_rshl_s32,
3322
        gen_op_neon_rshl_s64
3323
      }
3324
    }
3325
};
3326

    
3327
static inline void
3328
gen_op_neon_narrow_u32 ()
3329
{
3330
    /* No-op.  */
3331
}
3332

    
3333
static GenOpFunc *gen_neon_narrow[3] = {
3334
    gen_op_neon_narrow_u8,
3335
    gen_op_neon_narrow_u16,
3336
    gen_op_neon_narrow_u32
3337
};
3338

    
3339
static GenOpFunc *gen_neon_narrow_satu[3] = {
3340
    gen_op_neon_narrow_sat_u8,
3341
    gen_op_neon_narrow_sat_u16,
3342
    gen_op_neon_narrow_sat_u32
3343
};
3344

    
3345
static GenOpFunc *gen_neon_narrow_sats[3] = {
3346
    gen_op_neon_narrow_sat_s8,
3347
    gen_op_neon_narrow_sat_s16,
3348
    gen_op_neon_narrow_sat_s32
3349
};
3350

    
3351
static inline int gen_neon_add(int size)
3352
{
3353
    switch (size) {
3354
    case 0: gen_op_neon_add_u8(); break;
3355
    case 1: gen_op_neon_add_u16(); break;
3356
    case 2: gen_op_addl_T0_T1(); break;
3357
    default: return 1;
3358
    }
3359
    return 0;
3360
}
3361

    
3362
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
3363
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
3364
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
3365
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
3366
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
3367

    
3368
#define GEN_NEON_INTEGER_OP(name) do { \
3369
    switch ((size << 1) | u) { \
3370
    case 0: gen_op_neon_##name##_s8(); break; \
3371
    case 1: gen_op_neon_##name##_u8(); break; \
3372
    case 2: gen_op_neon_##name##_s16(); break; \
3373
    case 3: gen_op_neon_##name##_u16(); break; \
3374
    case 4: gen_op_neon_##name##_s32(); break; \
3375
    case 5: gen_op_neon_##name##_u32(); break; \
3376
    default: return 1; \
3377
    }} while (0)
3378

    
3379
static inline void
3380
gen_neon_movl_scratch_T0(int scratch)
3381
{
3382
  uint32_t offset;
3383

    
3384
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3385
  gen_op_neon_setreg_T0(offset);
3386
}
3387

    
3388
static inline void
3389
gen_neon_movl_scratch_T1(int scratch)
3390
{
3391
  uint32_t offset;
3392

    
3393
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3394
  gen_op_neon_setreg_T1(offset);
3395
}
3396

    
3397
static inline void
3398
gen_neon_movl_T0_scratch(int scratch)
3399
{
3400
  uint32_t offset;
3401

    
3402
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3403
  gen_op_neon_getreg_T0(offset);
3404
}
3405

    
3406
static inline void
3407
gen_neon_movl_T1_scratch(int scratch)
3408
{
3409
  uint32_t offset;
3410

    
3411
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3412
  gen_op_neon_getreg_T1(offset);
3413
}
3414

    
3415
static inline void gen_op_neon_widen_u32(void)
3416
{
3417
    gen_op_movl_T1_im(0);
3418
}
3419

    
3420
static inline void gen_neon_get_scalar(int size, int reg)
3421
{
3422
    if (size == 1) {
3423
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3424
    } else {
3425
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3426
        if (reg & 1)
3427
            gen_op_neon_dup_low16();
3428
        else
3429
            gen_op_neon_dup_high16();
3430
    }
3431
}
3432

    
3433
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3434
{
3435
    int n;
3436

    
3437
    for (n = 0; n < q + 1; n += 2) {
3438
        NEON_GET_REG(T0, reg, n);
3439
        NEON_GET_REG(T0, reg, n + n);
3440
        switch (size) {
3441
        case 0: gen_op_neon_unzip_u8(); break;
3442
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
3443
        case 2: /* no-op */; break;
3444
        default: abort();
3445
        }
3446
        gen_neon_movl_scratch_T0(tmp + n);
3447
        gen_neon_movl_scratch_T1(tmp + n + 1);
3448
    }
3449
}
3450

    
3451
static struct {
3452
    int nregs;
3453
    int interleave;
3454
    int spacing;
3455
} neon_ls_element_type[11] = {
3456
    {4, 4, 1},
3457
    {4, 4, 2},
3458
    {4, 1, 1},
3459
    {4, 2, 1},
3460
    {3, 3, 1},
3461
    {3, 3, 2},
3462
    {3, 1, 1},
3463
    {1, 1, 1},
3464
    {2, 2, 1},
3465
    {2, 2, 2},
3466
    {2, 1, 1}
3467
};
3468

    
3469
/* Translate a NEON load/store element instruction.  Return nonzero if the
3470
   instruction is invalid.  */
3471
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3472
{
3473
    int rd, rn, rm;
3474
    int op;
3475
    int nregs;
3476
    int interleave;
3477
    int stride;
3478
    int size;
3479
    int reg;
3480
    int pass;
3481
    int load;
3482
    int shift;
3483
    uint32_t mask;
3484
    int n;
3485
    TCGv tmp;
3486

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

    
3704
        base = load_reg(s, rn);
3705
        if (rm == 13) {
3706
            tcg_gen_addi_i32(base, base, stride);
3707
        } else {
3708
            TCGv index;
3709
            index = load_reg(s, rm);
3710
            tcg_gen_add_i32(base, base, index);
3711
            dead_tmp(index);
3712
        }
3713
        store_reg(s, rn, base);
3714
    }
3715
    return 0;
3716
}
3717

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

    
3725
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3726
{
3727
    int op;
3728
    int q;
3729
    int rd, rn, rm;
3730
    int size;
3731
    int shift;
3732
    int pass;
3733
    int count;
3734
    int pairwise;
3735
    int u;
3736
    int n;
3737
    uint32_t imm;
3738

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

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

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

    
4218
                for (pass = 0; pass < count; pass++) {
4219
                    if (size < 3) {
4220
                        /* Operands in T0 and T1.  */
4221
                        gen_op_movl_T1_im(imm);
4222
                        NEON_GET_REG(T0, rm, pass);
4223
                    } else {
4224
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4225
                        gen_op_movl_T0_im(imm);
4226
                        gen_neon_movl_scratch_T0(0);
4227
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4228
                        gen_neon_movl_scratch_T0(1);
4229
                        NEON_GET_REG(T0, rm, pass * 2);
4230
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4231
                    }
4232

    
4233
                    if (gen_neon_shift_im[op][u][size] == NULL)
4234
                        return 1;
4235
                    gen_neon_shift_im[op][u][size]();
4236

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

    
4313
                /* Processing MSB first means we need to do less shuffling at
4314
                   the end.  */
4315
                for (pass =  count - 1; pass >= 0; pass--) {
4316
                    /* Avoid clobbering the second operand before it has been
4317
                       written.  */
4318
                    n = pass;
4319
                    if (rd == rm)
4320
                        n ^= (count - 1);
4321
                    else
4322
                        n = pass;
4323

    
4324
                    if (size < 3) {
4325
                        /* Operands in T0 and T1.  */
4326
                        gen_op_movl_T1_im(imm);
4327
                        NEON_GET_REG(T0, rm, n);
4328
                    } else {
4329
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
4330
                        gen_op_movl_T0_im(imm);
4331
                        gen_neon_movl_scratch_T0(0);
4332
                        gen_op_movl_T0_im((int32_t)imm >> 31);
4333
                        gen_neon_movl_scratch_T0(1);
4334
                        NEON_GET_REG(T0, rm, n * 2);
4335
                        NEON_GET_REG(T0, rm, n * 2 + 1);
4336
                    }
4337

    
4338
                    gen_neon_shift_im_narrow[q][u][size - 1]();
4339

    
4340
                    if (size < 3 && (pass & 1) == 0) {
4341
                        gen_neon_movl_scratch_T0(0);
4342
                    } else {
4343
                        uint32_t offset;
4344

    
4345
                        if (size < 3)
4346
                            gen_neon_movl_T1_scratch(0);
4347

    
4348
                        if (op == 8 && !u) {
4349
                            gen_neon_narrow[size - 1]();
4350
                        } else {
4351
                            if (op == 8)
4352
                                gen_neon_narrow_sats[size - 2]();
4353
                            else
4354
                                gen_neon_narrow_satu[size - 1]();
4355
                        }
4356
                        if (size == 3)
4357
                            offset = neon_reg_offset(rd, n);
4358
                        else
4359
                            offset = neon_reg_offset(rd, n >> 1);
4360
                        gen_op_neon_setreg_T0(offset);
4361
                    }
4362
                } /* for pass */
4363
            } else if (op == 10) {
4364
                /* VSHLL */
4365
                if (q)
4366
                    return 1;
4367
                for (pass = 0; pass < 2; pass++) {
4368
                    /* Avoid clobbering the input operand.  */
4369
                    if (rd == rm)
4370
                        n = 1 - pass;
4371
                    else
4372
                        n = pass;
4373

    
4374
                    NEON_GET_REG(T0, rm, n);
4375
                    GEN_NEON_INTEGER_OP(widen);
4376
                    if (shift != 0) {
4377
                        /* The shift is less than the width of the source
4378
                           type, so in some cases we can just
4379
                           shift the whole register.  */
4380
                        if (size == 1 || (size == 0 && u)) {
4381
                            gen_op_shll_T0_im(shift);
4382
                            gen_op_shll_T1_im(shift);
4383
                        } else {
4384
                            switch (size) {
4385
                            case 0: gen_op_neon_shll_u16(shift); break;
4386
                            case 2: gen_op_neon_shll_u64(shift); break;
4387
                            default: abort();
4388
                            }
4389
                        }
4390
                    }
4391
                    NEON_SET_REG(T0, rd, n * 2);
4392
                    NEON_SET_REG(T1, rd, n * 2 + 1);
4393
                }
4394
            } else if (op == 15 || op == 16) {
4395
                /* VCVT fixed-point.  */
4396
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4397
                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4398
                    if (op & 1) {
4399
                        if (u)
4400
                            gen_vfp_ulto(0, shift);
4401
                        else
4402
                            gen_vfp_slto(0, shift);
4403
                    } else {
4404
                        if (u)
4405
                            gen_vfp_toul(0, shift);
4406
                        else
4407
                            gen_vfp_tosl(0, shift);
4408
                    }
4409
                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4410
                }
4411
            } else {
4412
                return 1;
4413
            }
4414
        } else { /* (insn & 0x00380080) == 0 */
4415
            int invert;
4416

    
4417
            op = (insn >> 8) & 0xf;
4418
            /* One register and immediate.  */
4419
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4420
            invert = (insn & (1 << 5)) != 0;
4421
            switch (op) {
4422
            case 0: case 1:
4423
                /* no-op */
4424
                break;
4425
            case 2: case 3:
4426
                imm <<= 8;
4427
                break;
4428
            case 4: case 5:
4429
                imm <<= 16;
4430
                break;
4431
            case 6: case 7:
4432
                imm <<= 24;
4433
                break;
4434
            case 8: case 9:
4435
                imm |= imm << 16;
4436
                break;
4437
            case 10: case 11:
4438
                imm = (imm << 8) | (imm << 24);
4439
                break;
4440
            case 12:
4441
                imm = (imm < 8) | 0xff;
4442
                break;
4443
            case 13:
4444
                imm = (imm << 16) | 0xffff;
4445
                break;
4446
            case 14:
4447
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4448
                if (invert)
4449
                    imm = ~imm;
4450
                break;
4451
            case 15:
4452
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4453
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4454
                break;
4455
            }
4456
            if (invert)
4457
                imm = ~imm;
4458

    
4459
            if (op != 14 || !invert)
4460
                gen_op_movl_T1_im(imm);
4461

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

    
4515
                prewiden = neon_3reg_wide[op][0];
4516
                src1_wide = neon_3reg_wide[op][1];
4517
                src2_wide = neon_3reg_wide[op][2];
4518

    
4519
                /* Avoid overlapping operands.  Wide source operands are
4520
                   always aligned so will never overlap with wide
4521
                   destinations in problematic ways.  */
4522
                if (rd == rm) {
4523
                    NEON_GET_REG(T2, rm, 1);
4524
                } else if (rd == rn) {
4525
                    NEON_GET_REG(T2, rn, 1);
4526
                }
4527
                for (pass = 0; pass < 2; pass++) {
4528
                    /* Load the second operand into env->vfp.scratch.
4529
                       Also widen narrow operands.  */
4530
                    if (pass == 1 && rd == rm) {
4531
                        if (prewiden) {
4532
                            gen_op_movl_T0_T2();
4533
                        } else {
4534
                            gen_op_movl_T1_T2();
4535
                        }
4536
                    } else {
4537
                        if (src2_wide) {
4538
                            NEON_GET_REG(T0, rm, pass * 2);
4539
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
4540
                        } else {
4541
                            if (prewiden) {
4542
                                NEON_GET_REG(T0, rm, pass);
4543
                            } else {
4544
                                NEON_GET_REG(T1, rm, pass);
4545
                            }
4546
                        }
4547
                    }
4548
                    if (prewiden && !src2_wide) {
4549
                        GEN_NEON_INTEGER_OP(widen);
4550
                    }
4551
                    if (prewiden || src2_wide) {
4552
                        gen_neon_movl_scratch_T0(0);
4553
                        gen_neon_movl_scratch_T1(1);
4554
                    }
4555

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

    
4613
                    default: /* 15 is RESERVED.  */
4614
                        return 1;
4615
                    }
4616
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4617
                        /* Accumulate.  */
4618
                        if (op == 10 || op == 11) {
4619
                            switch (size) {
4620
                            case 0: gen_op_neon_negl_u16(); break;
4621
                            case 1: gen_op_neon_negl_u32(); break;
4622
                            case 2: gen_op_neon_negl_u64(); break;
4623
                            default: abort();
4624
                            }
4625
                        }
4626

    
4627
                        gen_neon_movl_scratch_T0(0);
4628
                        gen_neon_movl_scratch_T1(1);
4629

    
4630
                        if (op != 13) {
4631
                            NEON_GET_REG(T0, rd, pass * 2);
4632
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4633
                        }
4634

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