Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 6ddbc6e4

History | View | Annotate | Download (267.3 kB)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
169

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

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

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

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

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

    
205
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
206
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
207
#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0])
208

    
209
#define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
210

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

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

    
225
static void gen_smul_dual(TCGv a, TCGv b)
226
{
227
    TCGv tmp1 = new_tmp();
228
    TCGv tmp2 = new_tmp();
229
    tcg_gen_ext8s_i32(tmp1, a);
230
    tcg_gen_ext8s_i32(tmp2, b);
231
    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
232
    dead_tmp(tmp2);
233
    tcg_gen_sari_i32(a, a, 16);
234
    tcg_gen_sari_i32(b, b, 16);
235
    tcg_gen_mul_i32(b, b, a);
236
    tcg_gen_mov_i32(a, tmp1);
237
    dead_tmp(tmp1);
238
}
239

    
240
/* Byteswap each halfword.  */
241
static void gen_rev16(TCGv var)
242
{
243
    TCGv tmp = new_tmp();
244
    tcg_gen_shri_i32(tmp, var, 8);
245
    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
246
    tcg_gen_shli_i32(var, var, 8);
247
    tcg_gen_andi_i32(var, var, 0xff00ff00);
248
    tcg_gen_or_i32(var, var, tmp);
249
    dead_tmp(tmp);
250
}
251

    
252
/* Byteswap low halfword and sign extend.  */
253
static void gen_revsh(TCGv var)
254
{
255
    TCGv tmp = new_tmp();
256
    tcg_gen_shri_i32(tmp, var, 8);
257
    tcg_gen_andi_i32(tmp, tmp, 0x00ff);
258
    tcg_gen_shli_i32(var, var, 8);
259
    tcg_gen_ext8s_i32(var, var);
260
    tcg_gen_or_i32(var, var, tmp);
261
    dead_tmp(tmp);
262
}
263

    
264
/* Unsigned bitfield extract.  */
265
static void gen_ubfx(TCGv var, int shift, uint32_t mask)
266
{
267
    if (shift)
268
        tcg_gen_shri_i32(var, var, shift);
269
    tcg_gen_andi_i32(var, var, mask);
270
}
271

    
272
/* Signed bitfield extract.  */
273
static void gen_sbfx(TCGv var, int shift, int width)
274
{
275
    uint32_t signbit;
276

    
277
    if (shift)
278
        tcg_gen_sari_i32(var, var, shift);
279
    if (shift + width < 32) {
280
        signbit = 1u << (width - 1);
281
        tcg_gen_andi_i32(var, var, (1u << width) - 1);
282
        tcg_gen_xori_i32(var, var, signbit);
283
        tcg_gen_subi_i32(var, var, signbit);
284
    }
285
}
286

    
287
/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
288
static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
289
{
290
    tcg_gen_shli_i32(val, val, shift);
291
    tcg_gen_andi_i32(val, val, mask);
292
    tcg_gen_andi_i32(base, base, ~mask);
293
    tcg_gen_or_i32(dest, base, val);
294
}
295

    
296
static void gen_op_roundqd_T0_T1(void)
297
{
298
    tcg_gen_shri_i32(cpu_T[0], cpu_T[0], 31);
299
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1]);
300
}
301

    
302
/* FIXME: Most targets have native widening multiplication.
303
   It would be good to use that instead of a full wide multiply.  */
304
/* Unsigned 32x32->64 multiply.  */
305
static void gen_op_mull_T0_T1(void)
306
{
307
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
308
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
309

    
310
    tcg_gen_extu_i32_i64(tmp1, cpu_T[0]);
311
    tcg_gen_extu_i32_i64(tmp2, cpu_T[1]);
312
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
313
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
314
    tcg_gen_shri_i64(tmp1, tmp1, 32);
315
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
316
}
317

    
318
/* Signed 32x32->64 multiply.  */
319
static void gen_op_imull_T0_T1(void)
320
{
321
    TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64);
322
    TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64);
323

    
324
    tcg_gen_ext_i32_i64(tmp1, cpu_T[0]);
325
    tcg_gen_ext_i32_i64(tmp2, cpu_T[1]);
326
    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
327
    tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
328
    tcg_gen_shri_i64(tmp1, tmp1, 32);
329
    tcg_gen_trunc_i64_i32(cpu_T[1], tmp1);
330
}
331

    
332
/* Swap low and high halfwords.  */
333
static void gen_swap_half(TCGv var)
334
{
335
    TCGv tmp = new_tmp();
336
    tcg_gen_shri_i32(tmp, var, 16);
337
    tcg_gen_shli_i32(var, var, 16);
338
    tcg_gen_or_i32(var, var, tmp);
339
    dead_tmp(tmp);
340
}
341

    
342
/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
343
    tmp = (t0 ^ t1) & 0x8000;
344
    t0 &= ~0x8000;
345
    t1 &= ~0x8000;
346
    t0 = (t0 + t1) ^ tmp;
347
 */
348

    
349
static void gen_add16(TCGv t0, TCGv t1)
350
{
351
    TCGv tmp = new_tmp();
352
    tcg_gen_xor_i32(tmp, t0, t1);
353
    tcg_gen_andi_i32(tmp, tmp, 0x8000);
354
    tcg_gen_andi_i32(t0, t0, ~0x8000);
355
    tcg_gen_andi_i32(t1, t1, ~0x8000);
356
    tcg_gen_add_i32(t0, t0, t1);
357
    tcg_gen_xor_i32(t0, t0, tmp);
358
    dead_tmp(tmp);
359
    dead_tmp(t1);
360
}
361

    
362
#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
363

    
364
/* Set CF to the top bit of var.  */
365
static void gen_set_CF_bit31(TCGv var)
366
{
367
    TCGv tmp = new_tmp();
368
    tcg_gen_shri_i32(tmp, var, 31);
369
    gen_set_CF(var);
370
    dead_tmp(tmp);
371
}
372

    
373
/* Set N and Z flags from var.  */
374
static inline void gen_logic_CC(TCGv var)
375
{
376
    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NZF));
377
}
378

    
379
/* T0 += T1 + CF.  */
380
static void gen_adc_T0_T1(void)
381
{
382
    TCGv tmp = new_tmp();
383
    gen_op_addl_T0_T1();
384
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
385
    tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp);
386
    dead_tmp(tmp);
387
}
388

    
389
/* dest = T0 - T1 + CF - 1.  */
390
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
391
{
392
    TCGv tmp = new_tmp();
393
    tcg_gen_sub_i32(dest, t0, t1);
394
    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
395
    tcg_gen_add_i32(dest, dest, tmp);
396
    tcg_gen_subi_i32(dest, dest, 1);
397
    dead_tmp(tmp);
398
}
399

    
400
#define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
401
#define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
402

    
403
/* FIXME:  Implement this natively.  */
404
static inline void tcg_gen_not_i32(TCGv t0, TCGv t1)
405
{
406
    tcg_gen_xori_i32(t0, t1, ~0);
407
}
408

    
409
/* T0 &= ~T1.  Clobbers T1.  */
410
/* FIXME: Implement bic natively.  */
411
static inline void gen_op_bicl_T0_T1(void)
412
{
413
    gen_op_notl_T1();
414
    gen_op_andl_T0_T1();
415
}
416

    
417
/* FIXME:  Implement this natively.  */
418
static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
419
{
420
    TCGv tmp;
421

    
422
    if (i == 0)
423
        return;
424

    
425
    tmp = new_tmp();
426
    tcg_gen_shri_i32(tmp, t1, i);
427
    tcg_gen_shli_i32(t1, t1, 32 - i);
428
    tcg_gen_or_i32(t0, t1, tmp);
429
    dead_tmp(tmp);
430
}
431

    
432
static void shifter_out_im(TCGv var, int shift)
433
{
434
    TCGv tmp = new_tmp();
435
    if (shift == 0) {
436
        tcg_gen_andi_i32(tmp, var, 1);
437
    } else {
438
        tcg_gen_shri_i32(tmp, var, shift);
439
        if (shift != 31);
440
            tcg_gen_andi_i32(tmp, tmp, 1);
441
    }
442
    gen_set_CF(tmp);
443
    dead_tmp(tmp);
444
}
445

    
446
/* Shift by immediate.  Includes special handling for shift == 0.  */
447
static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
448
{
449
    switch (shiftop) {
450
    case 0: /* LSL */
451
        if (shift != 0) {
452
            if (flags)
453
                shifter_out_im(var, 32 - shift);
454
            tcg_gen_shli_i32(var, var, shift);
455
        }
456
        break;
457
    case 1: /* LSR */
458
        if (shift == 0) {
459
            if (flags) {
460
                tcg_gen_shri_i32(var, var, 31);
461
                gen_set_CF(var);
462
            }
463
            tcg_gen_movi_i32(var, 0);
464
        } else {
465
            if (flags)
466
                shifter_out_im(var, shift - 1);
467
            tcg_gen_shri_i32(var, var, shift);
468
        }
469
        break;
470
    case 2: /* ASR */
471
        if (shift == 0)
472
            shift = 32;
473
        if (flags)
474
            shifter_out_im(var, shift - 1);
475
        if (shift == 32)
476
          shift = 31;
477
        tcg_gen_sari_i32(var, var, shift);
478
        break;
479
    case 3: /* ROR/RRX */
480
        if (shift != 0) {
481
            if (flags)
482
                shifter_out_im(var, shift - 1);
483
            tcg_gen_rori_i32(var, var, shift); break;
484
        } else {
485
            TCGv tmp = new_tmp();
486
            tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
487
            if (flags)
488
                shifter_out_im(var, 0);
489
            tcg_gen_shri_i32(var, var, 1);
490
            tcg_gen_shli_i32(tmp, tmp, 31);
491
            tcg_gen_or_i32(var, var, tmp);
492
            dead_tmp(tmp);
493
        }
494
    }
495
};
496

    
497
#define PAS_OP(pfx) \
498
    switch (op2) {  \
499
    case 0: gen_pas_helper(glue(pfx,add16)); break; \
500
    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
501
    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
502
    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
503
    case 4: gen_pas_helper(glue(pfx,add8)); break; \
504
    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
505
    }
506
void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
507
{
508
    TCGv tmp;
509

    
510
    switch (op1) {
511
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
512
    case 1:
513
        tmp = tcg_temp_new(TCG_TYPE_PTR);
514
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
515
        PAS_OP(s)
516
        break;
517
    case 5:
518
        tmp = tcg_temp_new(TCG_TYPE_PTR);
519
        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
520
        PAS_OP(u)
521
        break;
522
#undef gen_pas_helper
523
#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
524
    case 2:
525
        PAS_OP(q);
526
        break;
527
    case 3:
528
        PAS_OP(sh);
529
        break;
530
    case 6:
531
        PAS_OP(uq);
532
        break;
533
    case 7:
534
        PAS_OP(uh);
535
        break;
536
#undef gen_pas_helper
537
    }
538
}
539
#undef PAS_OP
540

    
541
/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
542
#define PAS_OP(pfx) \
543
    switch (op2) {  \
544
    case 0: gen_pas_helper(glue(pfx,add8)); break; \
545
    case 1: gen_pas_helper(glue(pfx,add16)); break; \
546
    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
547
    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
548
    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
549
    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
550
    }
551
void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
552
{
553
    TCGv tmp;
554

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

    
586
static GenOpFunc1 *gen_test_cc[14] = {
587
    gen_op_test_eq,
588
    gen_op_test_ne,
589
    gen_op_test_cs,
590
    gen_op_test_cc,
591
    gen_op_test_mi,
592
    gen_op_test_pl,
593
    gen_op_test_vs,
594
    gen_op_test_vc,
595
    gen_op_test_hi,
596
    gen_op_test_ls,
597
    gen_op_test_ge,
598
    gen_op_test_lt,
599
    gen_op_test_gt,
600
    gen_op_test_le,
601
};
602

    
603
const uint8_t table_logic_cc[16] = {
604
    1, /* and */
605
    1, /* xor */
606
    0, /* sub */
607
    0, /* rsb */
608
    0, /* add */
609
    0, /* adc */
610
    0, /* sbc */
611
    0, /* rsc */
612
    1, /* andl */
613
    1, /* xorl */
614
    0, /* cmp */
615
    0, /* cmn */
616
    1, /* orr */
617
    1, /* mov */
618
    1, /* bic */
619
    1, /* mvn */
620
};
621

    
622
static GenOpFunc *gen_shift_T1_T0[4] = {
623
    gen_op_shll_T1_T0,
624
    gen_op_shrl_T1_T0,
625
    gen_op_sarl_T1_T0,
626
    gen_op_rorl_T1_T0,
627
};
628

    
629
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
630
    gen_op_shll_T1_T0_cc,
631
    gen_op_shrl_T1_T0_cc,
632
    gen_op_sarl_T1_T0_cc,
633
    gen_op_rorl_T1_T0_cc,
634
};
635

    
636
/* Set PC and thumb state from T0.  Clobbers T0.  */
637
static inline void gen_bx(DisasContext *s)
638
{
639
    TCGv tmp;
640

    
641
    s->is_jmp = DISAS_UPDATE;
642
    tmp = new_tmp();
643
    tcg_gen_andi_i32(tmp, cpu_T[0], 1);
644
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
645
    dead_tmp(tmp);
646
    tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ~1);
647
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
648
}
649

    
650
#if defined(CONFIG_USER_ONLY)
651
#define gen_ldst(name, s) gen_op_##name##_raw()
652
#else
653
#define gen_ldst(name, s) do { \
654
    s->is_mem = 1; \
655
    if (IS_USER(s)) \
656
        gen_op_##name##_user(); \
657
    else \
658
        gen_op_##name##_kernel(); \
659
    } while (0)
660
#endif
661

    
662
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
663
{
664
    load_reg_var(s, cpu_T[0], reg);
665
}
666

    
667
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
668
{
669
    load_reg_var(s, cpu_T[1], reg);
670
}
671

    
672
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
673
{
674
    load_reg_var(s, cpu_T[2], reg);
675
}
676

    
677
static inline void gen_set_pc_T0(void)
678
{
679
    tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15]));
680
}
681

    
682
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
683
{
684
    TCGv tmp;
685
    if (reg == 15) {
686
        tmp = new_tmp();
687
        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);
688
    } else {
689
        tmp = cpu_T[t];
690
    }
691
    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));
692
    if (reg == 15) {
693
        dead_tmp(tmp);
694
        s->is_jmp = DISAS_JUMP;
695
    }
696
}
697

    
698
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
699
{
700
    gen_movl_reg_TN(s, reg, 0);
701
}
702

    
703
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
704
{
705
    gen_movl_reg_TN(s, reg, 1);
706
}
707

    
708
/* Force a TB lookup after an instruction that changes the CPU state.  */
709
static inline void gen_lookup_tb(DisasContext *s)
710
{
711
    gen_op_movl_T0_im(s->pc);
712
    gen_movl_reg_T0(s, 15);
713
    s->is_jmp = DISAS_UPDATE;
714
}
715

    
716
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
717
{
718
    int val, rm, shift, shiftop;
719
    TCGv offset;
720

    
721
    if (!(insn & (1 << 25))) {
722
        /* immediate */
723
        val = insn & 0xfff;
724
        if (!(insn & (1 << 23)))
725
            val = -val;
726
        if (val != 0)
727
            gen_op_addl_T1_im(val);
728
    } else {
729
        /* shift/register */
730
        rm = (insn) & 0xf;
731
        shift = (insn >> 7) & 0x1f;
732
        shiftop = (insn >> 5) & 3;
733
        offset = load_reg(s, rm);
734
        gen_arm_shift_im(offset, shiftop, shift, 0);
735
        if (!(insn & (1 << 23)))
736
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
737
        else
738
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
739
        dead_tmp(offset);
740
    }
741
}
742

    
743
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
744
                                        int extra)
745
{
746
    int val, rm;
747
    TCGv offset;
748

    
749
    if (insn & (1 << 22)) {
750
        /* immediate */
751
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
752
        if (!(insn & (1 << 23)))
753
            val = -val;
754
        val += extra;
755
        if (val != 0)
756
            gen_op_addl_T1_im(val);
757
    } else {
758
        /* register */
759
        if (extra)
760
            gen_op_addl_T1_im(extra);
761
        rm = (insn) & 0xf;
762
        offset = load_reg(s, rm);
763
        if (!(insn & (1 << 23)))
764
            tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset);
765
        else
766
            tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset);
767
        dead_tmp(offset);
768
    }
769
}
770

    
771
#define VFP_OP(name)                      \
772
static inline void gen_vfp_##name(int dp) \
773
{                                         \
774
    if (dp)                               \
775
        gen_op_vfp_##name##d();           \
776
    else                                  \
777
        gen_op_vfp_##name##s();           \
778
}
779

    
780
#define VFP_OP1(name)                               \
781
static inline void gen_vfp_##name(int dp, int arg)  \
782
{                                                   \
783
    if (dp)                                         \
784
        gen_op_vfp_##name##d(arg);                  \
785
    else                                            \
786
        gen_op_vfp_##name##s(arg);                  \
787
}
788

    
789
VFP_OP(add)
790
VFP_OP(sub)
791
VFP_OP(mul)
792
VFP_OP(div)
793
VFP_OP(neg)
794
VFP_OP(abs)
795
VFP_OP(sqrt)
796
VFP_OP(cmp)
797
VFP_OP(cmpe)
798
VFP_OP(F1_ld0)
799
VFP_OP(uito)
800
VFP_OP(sito)
801
VFP_OP(toui)
802
VFP_OP(touiz)
803
VFP_OP(tosi)
804
VFP_OP(tosiz)
805
VFP_OP1(tosh)
806
VFP_OP1(tosl)
807
VFP_OP1(touh)
808
VFP_OP1(toul)
809
VFP_OP1(shto)
810
VFP_OP1(slto)
811
VFP_OP1(uhto)
812
VFP_OP1(ulto)
813

    
814
#undef VFP_OP
815

    
816
static inline void gen_vfp_fconst(int dp, uint32_t val)
817
{
818
    if (dp)
819
        gen_op_vfp_fconstd(val);
820
    else
821
        gen_op_vfp_fconsts(val);
822
}
823

    
824
static inline void gen_vfp_ld(DisasContext *s, int dp)
825
{
826
    if (dp)
827
        gen_ldst(vfp_ldd, s);
828
    else
829
        gen_ldst(vfp_lds, s);
830
}
831

    
832
static inline void gen_vfp_st(DisasContext *s, int dp)
833
{
834
    if (dp)
835
        gen_ldst(vfp_std, s);
836
    else
837
        gen_ldst(vfp_sts, s);
838
}
839

    
840
static inline long
841
vfp_reg_offset (int dp, int reg)
842
{
843
    if (dp)
844
        return offsetof(CPUARMState, vfp.regs[reg]);
845
    else if (reg & 1) {
846
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
847
          + offsetof(CPU_DoubleU, l.upper);
848
    } else {
849
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
850
          + offsetof(CPU_DoubleU, l.lower);
851
    }
852
}
853

    
854
/* Return the offset of a 32-bit piece of a NEON register.
855
   zero is the least significant end of the register.  */
856
static inline long
857
neon_reg_offset (int reg, int n)
858
{
859
    int sreg;
860
    sreg = reg * 2 + n;
861
    return vfp_reg_offset(0, sreg);
862
}
863

    
864
#define NEON_GET_REG(T, reg, n) gen_op_neon_getreg_##T(neon_reg_offset(reg, n))
865
#define NEON_SET_REG(T, reg, n) gen_op_neon_setreg_##T(neon_reg_offset(reg, n))
866

    
867
static inline void gen_mov_F0_vreg(int dp, int reg)
868
{
869
    if (dp)
870
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
871
    else
872
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
873
}
874

    
875
static inline void gen_mov_F1_vreg(int dp, int reg)
876
{
877
    if (dp)
878
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
879
    else
880
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
881
}
882

    
883
static inline void gen_mov_vreg_F0(int dp, int reg)
884
{
885
    if (dp)
886
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
887
    else
888
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
889
}
890

    
891
#define ARM_CP_RW_BIT        (1 << 20)
892

    
893
static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn)
894
{
895
    int rd;
896
    uint32_t offset;
897

    
898
    rd = (insn >> 16) & 0xf;
899
    gen_movl_T1_reg(s, rd);
900

    
901
    offset = (insn & 0xff) << ((insn >> 7) & 2);
902
    if (insn & (1 << 24)) {
903
        /* Pre indexed */
904
        if (insn & (1 << 23))
905
            gen_op_addl_T1_im(offset);
906
        else
907
            gen_op_addl_T1_im(-offset);
908

    
909
        if (insn & (1 << 21))
910
            gen_movl_reg_T1(s, rd);
911
    } else if (insn & (1 << 21)) {
912
        /* Post indexed */
913
        if (insn & (1 << 23))
914
            gen_op_movl_T0_im(offset);
915
        else
916
            gen_op_movl_T0_im(- offset);
917
        gen_op_addl_T0_T1();
918
        gen_movl_reg_T0(s, rd);
919
    } else if (!(insn & (1 << 23)))
920
        return 1;
921
    return 0;
922
}
923

    
924
static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask)
925
{
926
    int rd = (insn >> 0) & 0xf;
927

    
928
    if (insn & (1 << 8))
929
        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3)
930
            return 1;
931
        else
932
            gen_op_iwmmxt_movl_T0_wCx(rd);
933
    else
934
        gen_op_iwmmxt_movl_T0_T1_wRn(rd);
935

    
936
    gen_op_movl_T1_im(mask);
937
    gen_op_andl_T0_T1();
938
    return 0;
939
}
940

    
941
/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occured
942
   (ie. an undefined instruction).  */
943
static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
944
{
945
    int rd, wrd;
946
    int rdhi, rdlo, rd0, rd1, i;
947

    
948
    if ((insn & 0x0e000e00) == 0x0c000000) {
949
        if ((insn & 0x0fe00ff0) == 0x0c400000) {
950
            wrd = insn & 0xf;
951
            rdlo = (insn >> 12) & 0xf;
952
            rdhi = (insn >> 16) & 0xf;
953
            if (insn & ARM_CP_RW_BIT) {                        /* TMRRC */
954
                gen_op_iwmmxt_movl_T0_T1_wRn(wrd);
955
                gen_movl_reg_T0(s, rdlo);
956
                gen_movl_reg_T1(s, rdhi);
957
            } else {                                        /* TMCRR */
958
                gen_movl_T0_reg(s, rdlo);
959
                gen_movl_T1_reg(s, rdhi);
960
                gen_op_iwmmxt_movl_wRn_T0_T1(wrd);
961
                gen_op_iwmmxt_set_mup();
962
            }
963
            return 0;
964
        }
965

    
966
        wrd = (insn >> 12) & 0xf;
967
        if (gen_iwmmxt_address(s, insn))
968
            return 1;
969
        if (insn & ARM_CP_RW_BIT) {
970
            if ((insn >> 28) == 0xf) {                        /* WLDRW wCx */
971
                gen_ldst(ldl, s);
972
                gen_op_iwmmxt_movl_wCx_T0(wrd);
973
            } else {
974
                if (insn & (1 << 8))
975
                    if (insn & (1 << 22))                /* WLDRD */
976
                        gen_ldst(iwmmxt_ldq, s);
977
                    else                                /* WLDRW wRd */
978
                        gen_ldst(iwmmxt_ldl, s);
979
                else
980
                    if (insn & (1 << 22))                /* WLDRH */
981
                        gen_ldst(iwmmxt_ldw, s);
982
                    else                                /* WLDRB */
983
                        gen_ldst(iwmmxt_ldb, s);
984
                gen_op_iwmmxt_movq_wRn_M0(wrd);
985
            }
986
        } else {
987
            if ((insn >> 28) == 0xf) {                        /* WSTRW wCx */
988
                gen_op_iwmmxt_movl_T0_wCx(wrd);
989
                gen_ldst(stl, s);
990
            } else {
991
                gen_op_iwmmxt_movq_M0_wRn(wrd);
992
                if (insn & (1 << 8))
993
                    if (insn & (1 << 22))                /* WSTRD */
994
                        gen_ldst(iwmmxt_stq, s);
995
                    else                                /* WSTRW wRd */
996
                        gen_ldst(iwmmxt_stl, s);
997
                else
998
                    if (insn & (1 << 22))                /* WSTRH */
999
                        gen_ldst(iwmmxt_ldw, s);
1000
                    else                                /* WSTRB */
1001
                        gen_ldst(iwmmxt_stb, s);
1002
            }
1003
        }
1004
        return 0;
1005
    }
1006

    
1007
    if ((insn & 0x0f000000) != 0x0e000000)
1008
        return 1;
1009

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

    
1876
    return 0;
1877
}
1878

    
1879
/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occured
1880
   (ie. an undefined instruction).  */
1881
static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1882
{
1883
    int acc, rd0, rd1, rdhi, rdlo;
1884

    
1885
    if ((insn & 0x0ff00f10) == 0x0e200010) {
1886
        /* Multiply with Internal Accumulate Format */
1887
        rd0 = (insn >> 12) & 0xf;
1888
        rd1 = insn & 0xf;
1889
        acc = (insn >> 5) & 7;
1890

    
1891
        if (acc != 0)
1892
            return 1;
1893

    
1894
        switch ((insn >> 16) & 0xf) {
1895
        case 0x0:                                        /* MIA */
1896
            gen_movl_T0_reg(s, rd0);
1897
            gen_movl_T1_reg(s, rd1);
1898
            gen_op_iwmmxt_muladdsl_M0_T0_T1();
1899
            break;
1900
        case 0x8:                                        /* MIAPH */
1901
            gen_movl_T0_reg(s, rd0);
1902
            gen_movl_T1_reg(s, rd1);
1903
            gen_op_iwmmxt_muladdsw_M0_T0_T1();
1904
            break;
1905
        case 0xc:                                        /* MIABB */
1906
        case 0xd:                                        /* MIABT */
1907
        case 0xe:                                        /* MIATB */
1908
        case 0xf:                                        /* MIATT */
1909
            gen_movl_T1_reg(s, rd0);
1910
            if (insn & (1 << 16))
1911
                gen_op_shrl_T1_im(16);
1912
            gen_op_movl_T0_T1();
1913
            gen_movl_T1_reg(s, rd1);
1914
            if (insn & (1 << 17))
1915
                gen_op_shrl_T1_im(16);
1916
            gen_op_iwmmxt_muladdswl_M0_T0_T1();
1917
            break;
1918
        default:
1919
            return 1;
1920
        }
1921

    
1922
        gen_op_iwmmxt_movq_wRn_M0(acc);
1923
        return 0;
1924
    }
1925

    
1926
    if ((insn & 0x0fe00ff8) == 0x0c400000) {
1927
        /* Internal Accumulator Access Format */
1928
        rdhi = (insn >> 16) & 0xf;
1929
        rdlo = (insn >> 12) & 0xf;
1930
        acc = insn & 7;
1931

    
1932
        if (acc != 0)
1933
            return 1;
1934

    
1935
        if (insn & ARM_CP_RW_BIT) {                        /* MRA */
1936
            gen_op_iwmmxt_movl_T0_T1_wRn(acc);
1937
            gen_movl_reg_T0(s, rdlo);
1938
            gen_op_movl_T0_im((1 << (40 - 32)) - 1);
1939
            gen_op_andl_T0_T1();
1940
            gen_movl_reg_T0(s, rdhi);
1941
        } else {                                        /* MAR */
1942
            gen_movl_T0_reg(s, rdlo);
1943
            gen_movl_T1_reg(s, rdhi);
1944
            gen_op_iwmmxt_movl_wRn_T0_T1(acc);
1945
        }
1946
        return 0;
1947
    }
1948

    
1949
    return 1;
1950
}
1951

    
1952
/* Disassemble system coprocessor instruction.  Return nonzero if
1953
   instruction is not defined.  */
1954
static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
1955
{
1956
    uint32_t rd = (insn >> 12) & 0xf;
1957
    uint32_t cp = (insn >> 8) & 0xf;
1958
    if (IS_USER(s)) {
1959
        return 1;
1960
    }
1961

    
1962
    if (insn & ARM_CP_RW_BIT) {
1963
        if (!env->cp[cp].cp_read)
1964
            return 1;
1965
        gen_op_movl_T0_im((uint32_t) s->pc);
1966
        gen_set_pc_T0();
1967
        gen_op_movl_T0_cp(insn);
1968
        gen_movl_reg_T0(s, rd);
1969
    } else {
1970
        if (!env->cp[cp].cp_write)
1971
            return 1;
1972
        gen_op_movl_T0_im((uint32_t) s->pc);
1973
        gen_set_pc_T0();
1974
        gen_movl_T0_reg(s, rd);
1975
        gen_op_movl_cp_T0(insn);
1976
    }
1977
    return 0;
1978
}
1979

    
1980
static int cp15_user_ok(uint32_t insn)
1981
{
1982
    int cpn = (insn >> 16) & 0xf;
1983
    int cpm = insn & 0xf;
1984
    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
1985

    
1986
    if (cpn == 13 && cpm == 0) {
1987
        /* TLS register.  */
1988
        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
1989
            return 1;
1990
    }
1991
    if (cpn == 7) {
1992
        /* ISB, DSB, DMB.  */
1993
        if ((cpm == 5 && op == 4)
1994
                || (cpm == 10 && (op == 4 || op == 5)))
1995
            return 1;
1996
    }
1997
    return 0;
1998
}
1999

    
2000
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
2001
   instruction is not defined.  */
2002
static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2003
{
2004
    uint32_t rd;
2005

    
2006
    /* M profile cores use memory mapped registers instead of cp15.  */
2007
    if (arm_feature(env, ARM_FEATURE_M))
2008
        return 1;
2009

    
2010
    if ((insn & (1 << 25)) == 0) {
2011
        if (insn & (1 << 20)) {
2012
            /* mrrc */
2013
            return 1;
2014
        }
2015
        /* mcrr.  Used for block cache operations, so implement as no-op.  */
2016
        return 0;
2017
    }
2018
    if ((insn & (1 << 4)) == 0) {
2019
        /* cdp */
2020
        return 1;
2021
    }
2022
    if (IS_USER(s) && !cp15_user_ok(insn)) {
2023
        return 1;
2024
    }
2025
    if ((insn & 0x0fff0fff) == 0x0e070f90
2026
        || (insn & 0x0fff0fff) == 0x0e070f58) {
2027
        /* Wait for interrupt.  */
2028
        gen_op_movl_T0_im((long)s->pc);
2029
        gen_set_pc_T0();
2030
        s->is_jmp = DISAS_WFI;
2031
        return 0;
2032
    }
2033
    rd = (insn >> 12) & 0xf;
2034
    if (insn & ARM_CP_RW_BIT) {
2035
        gen_op_movl_T0_cp15(insn);
2036
        /* If the destination register is r15 then sets condition codes.  */
2037
        if (rd != 15)
2038
            gen_movl_reg_T0(s, rd);
2039
    } else {
2040
        gen_movl_T0_reg(s, rd);
2041
        gen_op_movl_cp15_T0(insn);
2042
        /* Normally we would always end the TB here, but Linux
2043
         * arch/arm/mach-pxa/sleep.S expects two instructions following
2044
         * an MMU enable to execute from cache.  Imitate this behaviour.  */
2045
        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2046
                (insn & 0x0fff0fff) != 0x0e010f10)
2047
            gen_lookup_tb(s);
2048
    }
2049
    return 0;
2050
}
2051

    
2052
#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2053
#define VFP_SREG(insn, bigbit, smallbit) \
2054
  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2055
#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2056
    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2057
        reg = (((insn) >> (bigbit)) & 0x0f) \
2058
              | (((insn) >> ((smallbit) - 4)) & 0x10); \
2059
    } else { \
2060
        if (insn & (1 << (smallbit))) \
2061
            return 1; \
2062
        reg = ((insn) >> (bigbit)) & 0x0f; \
2063
    }} while (0)
2064

    
2065
#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2066
#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2067
#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
2068
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
2069
#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
2070
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
2071

    
2072
static inline int
2073
vfp_enabled(CPUState * env)
2074
{
2075
    return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2076
}
2077

    
2078
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
2079
   (ie. an undefined instruction).  */
2080
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2081
{
2082
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2083
    int dp, veclen;
2084

    
2085
    if (!arm_feature(env, ARM_FEATURE_VFP))
2086
        return 1;
2087

    
2088
    if (!vfp_enabled(env)) {
2089
        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
2090
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
2091
            return 1;
2092
        rn = (insn >> 16) & 0xf;
2093
        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2094
            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2095
            return 1;
2096
    }
2097
    dp = ((insn & 0xf00) == 0xb00);
2098
    switch ((insn >> 24) & 0xf) {
2099
    case 0xe:
2100
        if (insn & (1 << 4)) {
2101
            /* single register transfer */
2102
            rd = (insn >> 12) & 0xf;
2103
            if (dp) {
2104
                int size;
2105
                int pass;
2106

    
2107
                VFP_DREG_N(rn, insn);
2108
                if (insn & 0xf)
2109
                    return 1;
2110
                if (insn & 0x00c00060
2111
                    && !arm_feature(env, ARM_FEATURE_NEON))
2112
                    return 1;
2113

    
2114
                pass = (insn >> 21) & 1;
2115
                if (insn & (1 << 22)) {
2116
                    size = 0;
2117
                    offset = ((insn >> 5) & 3) * 8;
2118
                } else if (insn & (1 << 5)) {
2119
                    size = 1;
2120
                    offset = (insn & (1 << 6)) ? 16 : 0;
2121
                } else {
2122
                    size = 2;
2123
                    offset = 0;
2124
                }
2125
                if (insn & ARM_CP_RW_BIT) {
2126
                    /* vfp->arm */
2127
                    switch (size) {
2128
                    case 0:
2129
                        NEON_GET_REG(T1, rn, pass);
2130
                        if (offset)
2131
                            gen_op_shrl_T1_im(offset);
2132
                        if (insn & (1 << 23))
2133
                            gen_uxtb(cpu_T[1]);
2134
                        else
2135
                            gen_sxtb(cpu_T[1]);
2136
                        break;
2137
                    case 1:
2138
                        NEON_GET_REG(T1, rn, pass);
2139
                        if (insn & (1 << 23)) {
2140
                            if (offset) {
2141
                                gen_op_shrl_T1_im(16);
2142
                            } else {
2143
                                gen_uxth(cpu_T[1]);
2144
                            }
2145
                        } else {
2146
                            if (offset) {
2147
                                gen_op_sarl_T1_im(16);
2148
                            } else {
2149
                                gen_sxth(cpu_T[1]);
2150
                            }
2151
                        }
2152
                        break;
2153
                    case 2:
2154
                        NEON_GET_REG(T1, rn, pass);
2155
                        break;
2156
                    }
2157
                    gen_movl_reg_T1(s, rd);
2158
                } else {
2159
                    /* arm->vfp */
2160
                    gen_movl_T0_reg(s, rd);
2161
                    if (insn & (1 << 23)) {
2162
                        /* VDUP */
2163
                        if (size == 0) {
2164
                            gen_op_neon_dup_u8(0);
2165
                        } else if (size == 1) {
2166
                            gen_op_neon_dup_low16();
2167
                        }
2168
                        NEON_SET_REG(T0, rn, 0);
2169
                        NEON_SET_REG(T0, rn, 1);
2170
                    } else {
2171
                        /* VMOV */
2172
                        switch (size) {
2173
                        case 0:
2174
                            NEON_GET_REG(T2, rn, pass);
2175
                            gen_op_movl_T1_im(0xff);
2176
                            gen_op_andl_T0_T1();
2177
                            gen_op_neon_insert_elt(offset, ~(0xff << offset));
2178
                            NEON_SET_REG(T2, rn, pass);
2179
                            break;
2180
                        case 1:
2181
                            NEON_GET_REG(T2, rn, pass);
2182
                            gen_op_movl_T1_im(0xffff);
2183
                            gen_op_andl_T0_T1();
2184
                            bank_mask = offset ? 0xffff : 0xffff0000;
2185
                            gen_op_neon_insert_elt(offset, bank_mask);
2186
                            NEON_SET_REG(T2, rn, pass);
2187
                            break;
2188
                        case 2:
2189
                            NEON_SET_REG(T0, rn, pass);
2190
                            break;
2191
                        }
2192
                    }
2193
                }
2194
            } else { /* !dp */
2195
                if ((insn & 0x6f) != 0x00)
2196
                    return 1;
2197
                rn = VFP_SREG_N(insn);
2198
                if (insn & ARM_CP_RW_BIT) {
2199
                    /* vfp->arm */
2200
                    if (insn & (1 << 21)) {
2201
                        /* system register */
2202
                        rn >>= 1;
2203

    
2204
                        switch (rn) {
2205
                        case ARM_VFP_FPSID:
2206
                            /* VFP2 allows access for FSID from userspace.
2207
                               VFP3 restricts all id registers to privileged
2208
                               accesses.  */
2209
                            if (IS_USER(s)
2210
                                && arm_feature(env, ARM_FEATURE_VFP3))
2211
                                return 1;
2212
                            gen_op_vfp_movl_T0_xreg(rn);
2213
                            break;
2214
                        case ARM_VFP_FPEXC:
2215
                            if (IS_USER(s))
2216
                                return 1;
2217
                            gen_op_vfp_movl_T0_xreg(rn);
2218
                            break;
2219
                        case ARM_VFP_FPINST:
2220
                        case ARM_VFP_FPINST2:
2221
                            /* Not present in VFP3.  */
2222
                            if (IS_USER(s)
2223
                                || arm_feature(env, ARM_FEATURE_VFP3))
2224
                                return 1;
2225
                            gen_op_vfp_movl_T0_xreg(rn);
2226
                            break;
2227
                        case ARM_VFP_FPSCR:
2228
                            if (rd == 15)
2229
                                gen_op_vfp_movl_T0_fpscr_flags();
2230
                            else
2231
                                gen_op_vfp_movl_T0_fpscr();
2232
                            break;
2233
                        case ARM_VFP_MVFR0:
2234
                        case ARM_VFP_MVFR1:
2235
                            if (IS_USER(s)
2236
                                || !arm_feature(env, ARM_FEATURE_VFP3))
2237
                                return 1;
2238
                            gen_op_vfp_movl_T0_xreg(rn);
2239
                            break;
2240
                        default:
2241
                            return 1;
2242
                        }
2243
                    } else {
2244
                        gen_mov_F0_vreg(0, rn);
2245
                        gen_op_vfp_mrs();
2246
                    }
2247
                    if (rd == 15) {
2248
                        /* Set the 4 flag bits in the CPSR.  */
2249
                        gen_op_movl_cpsr_T0(0xf0000000);
2250
                    } else
2251
                        gen_movl_reg_T0(s, rd);
2252
                } else {
2253
                    /* arm->vfp */
2254
                    gen_movl_T0_reg(s, rd);
2255
                    if (insn & (1 << 21)) {
2256
                        rn >>= 1;
2257
                        /* system register */
2258
                        switch (rn) {
2259
                        case ARM_VFP_FPSID:
2260
                        case ARM_VFP_MVFR0:
2261
                        case ARM_VFP_MVFR1:
2262
                            /* Writes are ignored.  */
2263
                            break;
2264
                        case ARM_VFP_FPSCR:
2265
                            gen_op_vfp_movl_fpscr_T0();
2266
                            gen_lookup_tb(s);
2267
                            break;
2268
                        case ARM_VFP_FPEXC:
2269
                            if (IS_USER(s))
2270
                                return 1;
2271
                            gen_op_vfp_movl_xreg_T0(rn);
2272
                            gen_lookup_tb(s);
2273
                            break;
2274
                        case ARM_VFP_FPINST:
2275
                        case ARM_VFP_FPINST2:
2276
                            gen_op_vfp_movl_xreg_T0(rn);
2277
                            break;
2278
                        default:
2279
                            return 1;
2280
                        }
2281
                    } else {
2282
                        gen_op_vfp_msr();
2283
                        gen_mov_vreg_F0(0, rn);
2284
                    }
2285
                }
2286
            }
2287
        } else {
2288
            /* data processing */
2289
            /* The opcode is in bits 23, 21, 20 and 6.  */
2290
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2291
            if (dp) {
2292
                if (op == 15) {
2293
                    /* rn is opcode */
2294
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2295
                } else {
2296
                    /* rn is register number */
2297
                    VFP_DREG_N(rn, insn);
2298
                }
2299

    
2300
                if (op == 15 && (rn == 15 || rn > 17)) {
2301
                    /* Integer or single precision destination.  */
2302
                    rd = VFP_SREG_D(insn);
2303
                } else {
2304
                    VFP_DREG_D(rd, insn);
2305
                }
2306

    
2307
                if (op == 15 && (rn == 16 || rn == 17)) {
2308
                    /* Integer source.  */
2309
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2310
                } else {
2311
                    VFP_DREG_M(rm, insn);
2312
                }
2313
            } else {
2314
                rn = VFP_SREG_N(insn);
2315
                if (op == 15 && rn == 15) {
2316
                    /* Double precision destination.  */
2317
                    VFP_DREG_D(rd, insn);
2318
                } else {
2319
                    rd = VFP_SREG_D(insn);
2320
                }
2321
                rm = VFP_SREG_M(insn);
2322
            }
2323

    
2324
            veclen = env->vfp.vec_len;
2325
            if (op == 15 && rn > 3)
2326
                veclen = 0;
2327

    
2328
            /* Shut up compiler warnings.  */
2329
            delta_m = 0;
2330
            delta_d = 0;
2331
            bank_mask = 0;
2332

    
2333
            if (veclen > 0) {
2334
                if (dp)
2335
                    bank_mask = 0xc;
2336
                else
2337
                    bank_mask = 0x18;
2338

    
2339
                /* Figure out what type of vector operation this is.  */
2340
                if ((rd & bank_mask) == 0) {
2341
                    /* scalar */
2342
                    veclen = 0;
2343
                } else {
2344
                    if (dp)
2345
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
2346
                    else
2347
                        delta_d = env->vfp.vec_stride + 1;
2348

    
2349
                    if ((rm & bank_mask) == 0) {
2350
                        /* mixed scalar/vector */
2351
                        delta_m = 0;
2352
                    } else {
2353
                        /* vector */
2354
                        delta_m = delta_d;
2355
                    }
2356
                }
2357
            }
2358

    
2359
            /* Load the initial operands.  */
2360
            if (op == 15) {
2361
                switch (rn) {
2362
                case 16:
2363
                case 17:
2364
                    /* Integer source */
2365
                    gen_mov_F0_vreg(0, rm);
2366
                    break;
2367
                case 8:
2368
                case 9:
2369
                    /* Compare */
2370
                    gen_mov_F0_vreg(dp, rd);
2371
                    gen_mov_F1_vreg(dp, rm);
2372
                    break;
2373
                case 10:
2374
                case 11:
2375
                    /* Compare with zero */
2376
                    gen_mov_F0_vreg(dp, rd);
2377
                    gen_vfp_F1_ld0(dp);
2378
                    break;
2379
                case 20:
2380
                case 21:
2381
                case 22:
2382
                case 23:
2383
                    /* Source and destination the same.  */
2384
                    gen_mov_F0_vreg(dp, rd);
2385
                    break;
2386
                default:
2387
                    /* One source operand.  */
2388
                    gen_mov_F0_vreg(dp, rm);
2389
                    break;
2390
                }
2391
            } else {
2392
                /* Two source operands.  */
2393
                gen_mov_F0_vreg(dp, rn);
2394
                gen_mov_F1_vreg(dp, rm);
2395
            }
2396

    
2397
            for (;;) {
2398
                /* Perform the calculation.  */
2399
                switch (op) {
2400
                case 0: /* mac: fd + (fn * fm) */
2401
                    gen_vfp_mul(dp);
2402
                    gen_mov_F1_vreg(dp, rd);
2403
                    gen_vfp_add(dp);
2404
                    break;
2405
                case 1: /* nmac: fd - (fn * fm) */
2406
                    gen_vfp_mul(dp);
2407
                    gen_vfp_neg(dp);
2408
                    gen_mov_F1_vreg(dp, rd);
2409
                    gen_vfp_add(dp);
2410
                    break;
2411
                case 2: /* msc: -fd + (fn * fm) */
2412
                    gen_vfp_mul(dp);
2413
                    gen_mov_F1_vreg(dp, rd);
2414
                    gen_vfp_sub(dp);
2415
                    break;
2416
                case 3: /* nmsc: -fd - (fn * fm)  */
2417
                    gen_vfp_mul(dp);
2418
                    gen_mov_F1_vreg(dp, rd);
2419
                    gen_vfp_add(dp);
2420
                    gen_vfp_neg(dp);
2421
                    break;
2422
                case 4: /* mul: fn * fm */
2423
                    gen_vfp_mul(dp);
2424
                    break;
2425
                case 5: /* nmul: -(fn * fm) */
2426
                    gen_vfp_mul(dp);
2427
                    gen_vfp_neg(dp);
2428
                    break;
2429
                case 6: /* add: fn + fm */
2430
                    gen_vfp_add(dp);
2431
                    break;
2432
                case 7: /* sub: fn - fm */
2433
                    gen_vfp_sub(dp);
2434
                    break;
2435
                case 8: /* div: fn / fm */
2436
                    gen_vfp_div(dp);
2437
                    break;
2438
                case 14: /* fconst */
2439
                    if (!arm_feature(env, ARM_FEATURE_VFP3))
2440
                      return 1;
2441

    
2442
                    n = (insn << 12) & 0x80000000;
2443
                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
2444
                    if (dp) {
2445
                        if (i & 0x40)
2446
                            i |= 0x3f80;
2447
                        else
2448
                            i |= 0x4000;
2449
                        n |= i << 16;
2450
                    } else {
2451
                        if (i & 0x40)
2452
                            i |= 0x780;
2453
                        else
2454
                            i |= 0x800;
2455
                        n |= i << 19;
2456
                    }
2457
                    gen_vfp_fconst(dp, n);
2458
                    break;
2459
                case 15: /* extension space */
2460
                    switch (rn) {
2461
                    case 0: /* cpy */
2462
                        /* no-op */
2463
                        break;
2464
                    case 1: /* abs */
2465
                        gen_vfp_abs(dp);
2466
                        break;
2467
                    case 2: /* neg */
2468
                        gen_vfp_neg(dp);
2469
                        break;
2470
                    case 3: /* sqrt */
2471
                        gen_vfp_sqrt(dp);
2472
                        break;
2473
                    case 8: /* cmp */
2474
                        gen_vfp_cmp(dp);
2475
                        break;
2476
                    case 9: /* cmpe */
2477
                        gen_vfp_cmpe(dp);
2478
                        break;
2479
                    case 10: /* cmpz */
2480
                        gen_vfp_cmp(dp);
2481
                        break;
2482
                    case 11: /* cmpez */
2483
                        gen_vfp_F1_ld0(dp);
2484
                        gen_vfp_cmpe(dp);
2485
                        break;
2486
                    case 15: /* single<->double conversion */
2487
                        if (dp)
2488
                            gen_op_vfp_fcvtsd();
2489
                        else
2490
                            gen_op_vfp_fcvtds();
2491
                        break;
2492
                    case 16: /* fuito */
2493
                        gen_vfp_uito(dp);
2494
                        break;
2495
                    case 17: /* fsito */
2496
                        gen_vfp_sito(dp);
2497
                        break;
2498
                    case 20: /* fshto */
2499
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2500
                          return 1;
2501
                        gen_vfp_shto(dp, rm);
2502
                        break;
2503
                    case 21: /* fslto */
2504
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2505
                          return 1;
2506
                        gen_vfp_slto(dp, rm);
2507
                        break;
2508
                    case 22: /* fuhto */
2509
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2510
                          return 1;
2511
                        gen_vfp_uhto(dp, rm);
2512
                        break;
2513
                    case 23: /* fulto */
2514
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2515
                          return 1;
2516
                        gen_vfp_ulto(dp, rm);
2517
                        break;
2518
                    case 24: /* ftoui */
2519
                        gen_vfp_toui(dp);
2520
                        break;
2521
                    case 25: /* ftouiz */
2522
                        gen_vfp_touiz(dp);
2523
                        break;
2524
                    case 26: /* ftosi */
2525
                        gen_vfp_tosi(dp);
2526
                        break;
2527
                    case 27: /* ftosiz */
2528
                        gen_vfp_tosiz(dp);
2529
                        break;
2530
                    case 28: /* ftosh */
2531
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2532
                          return 1;
2533
                        gen_vfp_tosh(dp, rm);
2534
                        break;
2535
                    case 29: /* ftosl */
2536
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2537
                          return 1;
2538
                        gen_vfp_tosl(dp, rm);
2539
                        break;
2540
                    case 30: /* ftouh */
2541
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2542
                          return 1;
2543
                        gen_vfp_touh(dp, rm);
2544
                        break;
2545
                    case 31: /* ftoul */
2546
                        if (!arm_feature(env, ARM_FEATURE_VFP3))
2547
                          return 1;
2548
                        gen_vfp_toul(dp, rm);
2549
                        break;
2550
                    default: /* undefined */
2551
                        printf ("rn:%d\n", rn);
2552
                        return 1;
2553
                    }
2554
                    break;
2555
                default: /* undefined */
2556
                    printf ("op:%d\n", op);
2557
                    return 1;
2558
                }
2559

    
2560
                /* Write back the result.  */
2561
                if (op == 15 && (rn >= 8 && rn <= 11))
2562
                    ; /* Comparison, do nothing.  */
2563
                else if (op == 15 && rn > 17)
2564
                    /* Integer result.  */
2565
                    gen_mov_vreg_F0(0, rd);
2566
                else if (op == 15 && rn == 15)
2567
                    /* conversion */
2568
                    gen_mov_vreg_F0(!dp, rd);
2569
                else
2570
                    gen_mov_vreg_F0(dp, rd);
2571

    
2572
                /* break out of the loop if we have finished  */
2573
                if (veclen == 0)
2574
                    break;
2575

    
2576
                if (op == 15 && delta_m == 0) {
2577
                    /* single source one-many */
2578
                    while (veclen--) {
2579
                        rd = ((rd + delta_d) & (bank_mask - 1))
2580
                             | (rd & bank_mask);
2581
                        gen_mov_vreg_F0(dp, rd);
2582
                    }
2583
                    break;
2584
                }
2585
                /* Setup the next operands.  */
2586
                veclen--;
2587
                rd = ((rd + delta_d) & (bank_mask - 1))
2588
                     | (rd & bank_mask);
2589

    
2590
                if (op == 15) {
2591
                    /* One source operand.  */
2592
                    rm = ((rm + delta_m) & (bank_mask - 1))
2593
                         | (rm & bank_mask);
2594
                    gen_mov_F0_vreg(dp, rm);
2595
                } else {
2596
                    /* Two source operands.  */
2597
                    rn = ((rn + delta_d) & (bank_mask - 1))
2598
                         | (rn & bank_mask);
2599
                    gen_mov_F0_vreg(dp, rn);
2600
                    if (delta_m) {
2601
                        rm = ((rm + delta_m) & (bank_mask - 1))
2602
                             | (rm & bank_mask);
2603
                        gen_mov_F1_vreg(dp, rm);
2604
                    }
2605
                }
2606
            }
2607
        }
2608
        break;
2609
    case 0xc:
2610
    case 0xd:
2611
        if (dp && (insn & 0x03e00000) == 0x00400000) {
2612
            /* two-register transfer */
2613
            rn = (insn >> 16) & 0xf;
2614
            rd = (insn >> 12) & 0xf;
2615
            if (dp) {
2616
                VFP_DREG_M(rm, insn);
2617
            } else {
2618
                rm = VFP_SREG_M(insn);
2619
            }
2620

    
2621
            if (insn & ARM_CP_RW_BIT) {
2622
                /* vfp->arm */
2623
                if (dp) {
2624
                    gen_mov_F0_vreg(1, rm);
2625
                    gen_op_vfp_mrrd();
2626
                    gen_movl_reg_T0(s, rd);
2627
                    gen_movl_reg_T1(s, rn);
2628
                } else {
2629
                    gen_mov_F0_vreg(0, rm);
2630
                    gen_op_vfp_mrs();
2631
                    gen_movl_reg_T0(s, rn);
2632
                    gen_mov_F0_vreg(0, rm + 1);
2633
                    gen_op_vfp_mrs();
2634
                    gen_movl_reg_T0(s, rd);
2635
                }
2636
            } else {
2637
                /* arm->vfp */
2638
                if (dp) {
2639
                    gen_movl_T0_reg(s, rd);
2640
                    gen_movl_T1_reg(s, rn);
2641
                    gen_op_vfp_mdrr();
2642
                    gen_mov_vreg_F0(1, rm);
2643
                } else {
2644
                    gen_movl_T0_reg(s, rn);
2645
                    gen_op_vfp_msr();
2646
                    gen_mov_vreg_F0(0, rm);
2647
                    gen_movl_T0_reg(s, rd);
2648
                    gen_op_vfp_msr();
2649
                    gen_mov_vreg_F0(0, rm + 1);
2650
                }
2651
            }
2652
        } else {
2653
            /* Load/store */
2654
            rn = (insn >> 16) & 0xf;
2655
            if (dp)
2656
                VFP_DREG_D(rd, insn);
2657
            else
2658
                rd = VFP_SREG_D(insn);
2659
            if (s->thumb && rn == 15) {
2660
                gen_op_movl_T1_im(s->pc & ~2);
2661
            } else {
2662
                gen_movl_T1_reg(s, rn);
2663
            }
2664
            if ((insn & 0x01200000) == 0x01000000) {
2665
                /* Single load/store */
2666
                offset = (insn & 0xff) << 2;
2667
                if ((insn & (1 << 23)) == 0)
2668
                    offset = -offset;
2669
                gen_op_addl_T1_im(offset);
2670
                if (insn & (1 << 20)) {
2671
                    gen_vfp_ld(s, dp);
2672
                    gen_mov_vreg_F0(dp, rd);
2673
                } else {
2674
                    gen_mov_F0_vreg(dp, rd);
2675
                    gen_vfp_st(s, dp);
2676
                }
2677
            } else {
2678
                /* load/store multiple */
2679
                if (dp)
2680
                    n = (insn >> 1) & 0x7f;
2681
                else
2682
                    n = insn & 0xff;
2683

    
2684
                if (insn & (1 << 24)) /* pre-decrement */
2685
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
2686

    
2687
                if (dp)
2688
                    offset = 8;
2689
                else
2690
                    offset = 4;
2691
                for (i = 0; i < n; i++) {
2692
                    if (insn & ARM_CP_RW_BIT) {
2693
                        /* load */
2694
                        gen_vfp_ld(s, dp);
2695
                        gen_mov_vreg_F0(dp, rd + i);
2696
                    } else {
2697
                        /* store */
2698
                        gen_mov_F0_vreg(dp, rd + i);
2699
                        gen_vfp_st(s, dp);
2700
                    }
2701
                    gen_op_addl_T1_im(offset);
2702
                }
2703
                if (insn & (1 << 21)) {
2704
                    /* writeback */
2705
                    if (insn & (1 << 24))
2706
                        offset = -offset * n;
2707
                    else if (dp && (insn & 1))
2708
                        offset = 4;
2709
                    else
2710
                        offset = 0;
2711

    
2712
                    if (offset != 0)
2713
                        gen_op_addl_T1_im(offset);
2714
                    gen_movl_reg_T1(s, rn);
2715
                }
2716
            }
2717
        }
2718
        break;
2719
    default:
2720
        /* Should never happen.  */
2721
        return 1;
2722
    }
2723
    return 0;
2724
}
2725

    
2726
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
2727
{
2728
    TranslationBlock *tb;
2729

    
2730
    tb = s->tb;
2731
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
2732
        tcg_gen_goto_tb(n);
2733
        gen_op_movl_T0_im(dest);
2734
        gen_set_pc_T0();
2735
        tcg_gen_exit_tb((long)tb + n);
2736
    } else {
2737
        gen_op_movl_T0_im(dest);
2738
        gen_set_pc_T0();
2739
        tcg_gen_exit_tb(0);
2740
    }
2741
}
2742

    
2743
static inline void gen_jmp (DisasContext *s, uint32_t dest)
2744
{
2745
    if (__builtin_expect(s->singlestep_enabled, 0)) {
2746
        /* An indirect jump so that we still trigger the debug exception.  */
2747
        if (s->thumb)
2748
          dest |= 1;
2749
        gen_op_movl_T0_im(dest);
2750
        gen_bx(s);
2751
    } else {
2752
        gen_goto_tb(s, 0, dest);
2753
        s->is_jmp = DISAS_TB_JUMP;
2754
    }
2755
}
2756

    
2757
static inline void gen_mulxy(int x, int y)
2758
{
2759
    if (x)
2760
        tcg_gen_sari_i32(cpu_T[0], cpu_T[0], 16);
2761
    else
2762
        gen_sxth(cpu_T[0]);
2763
    if (y)
2764
        gen_op_sarl_T1_im(16);
2765
    else
2766
        gen_sxth(cpu_T[1]);
2767
    gen_op_mul_T0_T1();
2768
}
2769

    
2770
/* Return the mask of PSR bits set by a MSR instruction.  */
2771
static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
2772
    uint32_t mask;
2773

    
2774
    mask = 0;
2775
    if (flags & (1 << 0))
2776
        mask |= 0xff;
2777
    if (flags & (1 << 1))
2778
        mask |= 0xff00;
2779
    if (flags & (1 << 2))
2780
        mask |= 0xff0000;
2781
    if (flags & (1 << 3))
2782
        mask |= 0xff000000;
2783

    
2784
    /* Mask out undefined bits.  */
2785
    mask &= ~CPSR_RESERVED;
2786
    if (!arm_feature(env, ARM_FEATURE_V6))
2787
        mask &= ~(CPSR_E | CPSR_GE);
2788
    if (!arm_feature(env, ARM_FEATURE_THUMB2))
2789
        mask &= ~CPSR_IT;
2790
    /* Mask out execution state bits.  */
2791
    if (!spsr)
2792
        mask &= ~CPSR_EXEC;
2793
    /* Mask out privileged bits.  */
2794
    if (IS_USER(s))
2795
        mask &= CPSR_USER;
2796
    return mask;
2797
}
2798

    
2799
/* Returns nonzero if access to the PSR is not permitted.  */
2800
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
2801
{
2802
    if (spsr) {
2803
        /* ??? This is also undefined in system mode.  */
2804
        if (IS_USER(s))
2805
            return 1;
2806
        gen_op_movl_spsr_T0(mask);
2807
    } else {
2808
        gen_op_movl_cpsr_T0(mask);
2809
    }
2810
    gen_lookup_tb(s);
2811
    return 0;
2812
}
2813

    
2814
/* Generate an old-style exception return.  */
2815
static void gen_exception_return(DisasContext *s)
2816
{
2817
    gen_set_pc_T0();
2818
    gen_op_movl_T0_spsr();
2819
    gen_op_movl_cpsr_T0(0xffffffff);
2820
    s->is_jmp = DISAS_UPDATE;
2821
}
2822

    
2823
/* Generate a v6 exception return.  */
2824
static void gen_rfe(DisasContext *s)
2825
{
2826
    gen_op_movl_cpsr_T0(0xffffffff);
2827
    gen_op_movl_T0_T2();
2828
    gen_set_pc_T0();
2829
    s->is_jmp = DISAS_UPDATE;
2830
}
2831

    
2832
static inline void
2833
gen_set_condexec (DisasContext *s)
2834
{
2835
    if (s->condexec_mask) {
2836
        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
2837
        TCGv tmp = new_tmp();
2838
        tcg_gen_movi_i32(tmp, val);
2839
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits));
2840
        dead_tmp(tmp);
2841
    }
2842
}
2843

    
2844
static void gen_nop_hint(DisasContext *s, int val)
2845
{
2846
    switch (val) {
2847
    case 3: /* wfi */
2848
        gen_op_movl_T0_im((long)s->pc);
2849
        gen_set_pc_T0();
2850
        s->is_jmp = DISAS_WFI;
2851
        break;
2852
    case 2: /* wfe */
2853
    case 4: /* sev */
2854
        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
2855
    default: /* nop */
2856
        break;
2857
    }
2858
}
2859

    
2860
/* Neon shift by constant.  The actual ops are the same as used for variable
2861
   shifts.  [OP][U][SIZE]  */
2862
static GenOpFunc *gen_neon_shift_im[8][2][4] = {
2863
    { /* 0 */ /* VSHR */
2864
      {
2865
        gen_op_neon_shl_u8,
2866
        gen_op_neon_shl_u16,
2867
        gen_op_neon_shl_u32,
2868
        gen_op_neon_shl_u64
2869
      }, {
2870
        gen_op_neon_shl_s8,
2871
        gen_op_neon_shl_s16,
2872
        gen_op_neon_shl_s32,
2873
        gen_op_neon_shl_s64
2874
      }
2875
    }, { /* 1 */ /* VSRA */
2876
      {
2877
        gen_op_neon_shl_u8,
2878
        gen_op_neon_shl_u16,
2879
        gen_op_neon_shl_u32,
2880
        gen_op_neon_shl_u64
2881
      }, {
2882
        gen_op_neon_shl_s8,
2883
        gen_op_neon_shl_s16,
2884
        gen_op_neon_shl_s32,
2885
        gen_op_neon_shl_s64
2886
      }
2887
    }, { /* 2 */ /* VRSHR */
2888
      {
2889
        gen_op_neon_rshl_u8,
2890
        gen_op_neon_rshl_u16,
2891
        gen_op_neon_rshl_u32,
2892
        gen_op_neon_rshl_u64
2893
      }, {
2894
        gen_op_neon_rshl_s8,
2895
        gen_op_neon_rshl_s16,
2896
        gen_op_neon_rshl_s32,
2897
        gen_op_neon_rshl_s64
2898
      }
2899
    }, { /* 3 */ /* VRSRA */
2900
      {
2901
        gen_op_neon_rshl_u8,
2902
        gen_op_neon_rshl_u16,
2903
        gen_op_neon_rshl_u32,
2904
        gen_op_neon_rshl_u64
2905
      }, {
2906
        gen_op_neon_rshl_s8,
2907
        gen_op_neon_rshl_s16,
2908
        gen_op_neon_rshl_s32,
2909
        gen_op_neon_rshl_s64
2910
      }
2911
    }, { /* 4 */
2912
      {
2913
        NULL, NULL, NULL, NULL
2914
      }, { /* VSRI */
2915
        gen_op_neon_shl_u8,
2916
        gen_op_neon_shl_u16,
2917
        gen_op_neon_shl_u32,
2918
        gen_op_neon_shl_u64,
2919
      }
2920
    }, { /* 5 */
2921
      { /* VSHL */
2922
        gen_op_neon_shl_u8,
2923
        gen_op_neon_shl_u16,
2924
        gen_op_neon_shl_u32,
2925
        gen_op_neon_shl_u64,
2926
      }, { /* VSLI */
2927
        gen_op_neon_shl_u8,
2928
        gen_op_neon_shl_u16,
2929
        gen_op_neon_shl_u32,
2930
        gen_op_neon_shl_u64,
2931
      }
2932
    }, { /* 6 */ /* VQSHL */
2933
      {
2934
        gen_op_neon_qshl_u8,
2935
        gen_op_neon_qshl_u16,
2936
        gen_op_neon_qshl_u32,
2937
        gen_op_neon_qshl_u64
2938
      }, {
2939
        gen_op_neon_qshl_s8,
2940
        gen_op_neon_qshl_s16,
2941
        gen_op_neon_qshl_s32,
2942
        gen_op_neon_qshl_s64
2943
      }
2944
    }, { /* 7 */ /* VQSHLU */
2945
      {
2946
        gen_op_neon_qshl_u8,
2947
        gen_op_neon_qshl_u16,
2948
        gen_op_neon_qshl_u32,
2949
        gen_op_neon_qshl_u64
2950
      }, {
2951
        gen_op_neon_qshl_u8,
2952
        gen_op_neon_qshl_u16,
2953
        gen_op_neon_qshl_u32,
2954
        gen_op_neon_qshl_u64
2955
      }
2956
    }
2957
};
2958

    
2959
/* [R][U][size - 1] */
2960
static GenOpFunc *gen_neon_shift_im_narrow[2][2][3] = {
2961
    {
2962
      {
2963
        gen_op_neon_shl_u16,
2964
        gen_op_neon_shl_u32,
2965
        gen_op_neon_shl_u64
2966
      }, {
2967
        gen_op_neon_shl_s16,
2968
        gen_op_neon_shl_s32,
2969
        gen_op_neon_shl_s64
2970
      }
2971
    }, {
2972
      {
2973
        gen_op_neon_rshl_u16,
2974
        gen_op_neon_rshl_u32,
2975
        gen_op_neon_rshl_u64
2976
      }, {
2977
        gen_op_neon_rshl_s16,
2978
        gen_op_neon_rshl_s32,
2979
        gen_op_neon_rshl_s64
2980
      }
2981
    }
2982
};
2983

    
2984
static inline void
2985
gen_op_neon_narrow_u32 ()
2986
{
2987
    /* No-op.  */
2988
}
2989

    
2990
static GenOpFunc *gen_neon_narrow[3] = {
2991
    gen_op_neon_narrow_u8,
2992
    gen_op_neon_narrow_u16,
2993
    gen_op_neon_narrow_u32
2994
};
2995

    
2996
static GenOpFunc *gen_neon_narrow_satu[3] = {
2997
    gen_op_neon_narrow_sat_u8,
2998
    gen_op_neon_narrow_sat_u16,
2999
    gen_op_neon_narrow_sat_u32
3000
};
3001

    
3002
static GenOpFunc *gen_neon_narrow_sats[3] = {
3003
    gen_op_neon_narrow_sat_s8,
3004
    gen_op_neon_narrow_sat_s16,
3005
    gen_op_neon_narrow_sat_s32
3006
};
3007

    
3008
static inline int gen_neon_add(int size)
3009
{
3010
    switch (size) {
3011
    case 0: gen_op_neon_add_u8(); break;
3012
    case 1: gen_op_neon_add_u16(); break;
3013
    case 2: gen_op_addl_T0_T1(); break;
3014
    default: return 1;
3015
    }
3016
    return 0;
3017
}
3018

    
3019
/* 32-bit pairwise ops end up the same as the elementsise versions.  */
3020
#define gen_op_neon_pmax_s32  gen_op_neon_max_s32
3021
#define gen_op_neon_pmax_u32  gen_op_neon_max_u32
3022
#define gen_op_neon_pmin_s32  gen_op_neon_min_s32
3023
#define gen_op_neon_pmin_u32  gen_op_neon_min_u32
3024

    
3025
#define GEN_NEON_INTEGER_OP(name) do { \
3026
    switch ((size << 1) | u) { \
3027
    case 0: gen_op_neon_##name##_s8(); break; \
3028
    case 1: gen_op_neon_##name##_u8(); break; \
3029
    case 2: gen_op_neon_##name##_s16(); break; \
3030
    case 3: gen_op_neon_##name##_u16(); break; \
3031
    case 4: gen_op_neon_##name##_s32(); break; \
3032
    case 5: gen_op_neon_##name##_u32(); break; \
3033
    default: return 1; \
3034
    }} while (0)
3035

    
3036
static inline void
3037
gen_neon_movl_scratch_T0(int scratch)
3038
{
3039
  uint32_t offset;
3040

    
3041
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3042
  gen_op_neon_setreg_T0(offset);
3043
}
3044

    
3045
static inline void
3046
gen_neon_movl_scratch_T1(int scratch)
3047
{
3048
  uint32_t offset;
3049

    
3050
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3051
  gen_op_neon_setreg_T1(offset);
3052
}
3053

    
3054
static inline void
3055
gen_neon_movl_T0_scratch(int scratch)
3056
{
3057
  uint32_t offset;
3058

    
3059
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3060
  gen_op_neon_getreg_T0(offset);
3061
}
3062

    
3063
static inline void
3064
gen_neon_movl_T1_scratch(int scratch)
3065
{
3066
  uint32_t offset;
3067

    
3068
  offset = offsetof(CPUARMState, vfp.scratch[scratch]);
3069
  gen_op_neon_getreg_T1(offset);
3070
}
3071

    
3072
static inline void gen_op_neon_widen_u32(void)
3073
{
3074
    gen_op_movl_T1_im(0);
3075
}
3076

    
3077
static inline void gen_neon_get_scalar(int size, int reg)
3078
{
3079
    if (size == 1) {
3080
        NEON_GET_REG(T0, reg >> 1, reg & 1);
3081
    } else {
3082
        NEON_GET_REG(T0, reg >> 2, (reg >> 1) & 1);
3083
        if (reg & 1)
3084
            gen_op_neon_dup_low16();
3085
        else
3086
            gen_op_neon_dup_high16();
3087
    }
3088
}
3089

    
3090
static void gen_neon_unzip(int reg, int q, int tmp, int size)
3091
{
3092
    int n;
3093

    
3094
    for (n = 0; n < q + 1; n += 2) {
3095
        NEON_GET_REG(T0, reg, n);
3096
        NEON_GET_REG(T0, reg, n + n);
3097
        switch (size) {
3098
        case 0: gen_op_neon_unzip_u8(); break;
3099
        case 1: gen_op_neon_zip_u16(); break; /* zip and unzip are the same.  */
3100
        case 2: /* no-op */; break;
3101
        default: abort();
3102
        }
3103
        gen_neon_movl_scratch_T0(tmp + n);
3104
        gen_neon_movl_scratch_T1(tmp + n + 1);
3105
    }
3106
}
3107

    
3108
static struct {
3109
    int nregs;
3110
    int interleave;
3111
    int spacing;
3112
} neon_ls_element_type[11] = {
3113
    {4, 4, 1},
3114
    {4, 4, 2},
3115
    {4, 1, 1},
3116
    {4, 2, 1},
3117
    {3, 3, 1},
3118
    {3, 3, 2},
3119
    {3, 1, 1},
3120
    {1, 1, 1},
3121
    {2, 2, 1},
3122
    {2, 2, 2},
3123
    {2, 1, 1}
3124
};
3125

    
3126
/* Translate a NEON load/store element instruction.  Return nonzero if the
3127
   instruction is invalid.  */
3128
static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3129
{
3130
    int rd, rn, rm;
3131
    int op;
3132
    int nregs;
3133
    int interleave;
3134
    int stride;
3135
    int size;
3136
    int reg;
3137
    int pass;
3138
    int load;
3139
    int shift;
3140
    uint32_t mask;
3141
    int n;
3142

    
3143
    if (!vfp_enabled(env))
3144
      return 1;
3145
    VFP_DREG_D(rd, insn);
3146
    rn = (insn >> 16) & 0xf;
3147
    rm = insn & 0xf;
3148
    load = (insn & (1 << 21)) != 0;
3149
    if ((insn & (1 << 23)) == 0) {
3150
        /* Load store all elements.  */
3151
        op = (insn >> 8) & 0xf;
3152
        size = (insn >> 6) & 3;
3153
        if (op > 10 || size == 3)
3154
            return 1;
3155
        nregs = neon_ls_element_type[op].nregs;
3156
        interleave = neon_ls_element_type[op].interleave;
3157
        gen_movl_T1_reg(s, rn);
3158
        stride = (1 << size) * interleave;
3159
        for (reg = 0; reg < nregs; reg++) {
3160
            if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3161
                gen_movl_T1_reg(s, rn);
3162
                gen_op_addl_T1_im((1 << size) * reg);
3163
            } else if (interleave == 2 && nregs == 4 && reg == 2) {
3164
                gen_movl_T1_reg(s, rn);
3165
                gen_op_addl_T1_im(1 << size);
3166
            }
3167
            for (pass = 0; pass < 2; pass++) {
3168
                if (size == 2) {
3169
                    if (load) {
3170
                        gen_ldst(ldl, s);
3171
                        NEON_SET_REG(T0, rd, pass);
3172
                    } else {
3173
                        NEON_GET_REG(T0, rd, pass);
3174
                        gen_ldst(stl, s);
3175
                    }
3176
                    gen_op_addl_T1_im(stride);
3177
                } else if (size == 1) {
3178
                    if (load) {
3179
                        gen_ldst(lduw, s);
3180
                        gen_op_addl_T1_im(stride);
3181
                        gen_op_movl_T2_T0();
3182
                        gen_ldst(lduw, s);
3183
                        gen_op_addl_T1_im(stride);
3184
                        gen_op_neon_insert_elt(16, 0xffff);
3185
                        NEON_SET_REG(T2, rd, pass);
3186
                    } else {
3187
                        NEON_GET_REG(T2, rd, pass);
3188
                        gen_op_movl_T0_T2();
3189
                        gen_ldst(stw, s);
3190
                        gen_op_addl_T1_im(stride);
3191
                        gen_op_neon_extract_elt(16, 0xffff0000);
3192
                        gen_ldst(stw, s);
3193
                        gen_op_addl_T1_im(stride);
3194
                    }
3195
                } else /* size == 0 */ {
3196
                    if (load) {
3197
                        mask = 0xff;
3198
                        for (n = 0; n < 4; n++) {
3199
                            gen_ldst(ldub, s);
3200
                            gen_op_addl_T1_im(stride);
3201
                            if (n == 0) {
3202
                                gen_op_movl_T2_T0();
3203
                            } else {
3204
                                gen_op_neon_insert_elt(n * 8, ~mask);
3205
                            }
3206
                            mask <<= 8;
3207
                        }
3208
                        NEON_SET_REG(T2, rd, pass);
3209
                    } else {
3210
                        NEON_GET_REG(T2, rd, pass);
3211
                        mask = 0xff;
3212
                        for (n = 0; n < 4; n++) {
3213
                            if (n == 0) {
3214
                                gen_op_movl_T0_T2();
3215
                            } else {
3216
                                gen_op_neon_extract_elt(n * 8, mask);
3217
                            }
3218
                            gen_ldst(stb, s);
3219
                            gen_op_addl_T1_im(stride);
3220
                            mask <<= 8;
3221
                        }
3222
                    }
3223
                }
3224
            }
3225
            rd += neon_ls_element_type[op].spacing;
3226
        }
3227
        stride = nregs * 8;
3228
    } else {
3229
        size = (insn >> 10) & 3;
3230
        if (size == 3) {
3231
            /* Load single element to all lanes.  */
3232
            if (!load)
3233
                return 1;
3234
            size = (insn >> 6) & 3;
3235
            nregs = ((insn >> 8) & 3) + 1;
3236
            stride = (insn & (1 << 5)) ? 2 : 1;
3237
            gen_movl_T1_reg(s, rn);
3238
            for (reg = 0; reg < nregs; reg++) {
3239
                switch (size) {
3240
                case 0:
3241
                    gen_ldst(ldub, s);
3242
                    gen_op_neon_dup_u8(0);
3243
                    break;
3244
                case 1:
3245
                    gen_ldst(lduw, s);
3246
                    gen_op_neon_dup_low16();
3247
                    break;
3248
                case 2:
3249
                    gen_ldst(ldl, s);
3250
                    break;
3251
                case 3:
3252
                    return 1;
3253
                }
3254
                gen_op_addl_T1_im(1 << size);
3255
                NEON_SET_REG(T0, rd, 0);
3256
                NEON_SET_REG(T0, rd, 1);
3257
                rd += stride;
3258
            }
3259
            stride = (1 << size) * nregs;
3260
        } else {
3261
            /* Single element.  */
3262
            pass = (insn >> 7) & 1;
3263
            switch (size) {
3264
            case 0:
3265
                shift = ((insn >> 5) & 3) * 8;
3266
                mask = 0xff << shift;
3267
                stride = 1;
3268
                break;
3269
            case 1:
3270
                shift = ((insn >> 6) & 1) * 16;
3271
                mask = shift ? 0xffff0000 : 0xffff;
3272
                stride = (insn & (1 << 5)) ? 2 : 1;
3273
                break;
3274
            case 2:
3275
                shift = 0;
3276
                mask = 0xffffffff;
3277
                stride = (insn & (1 << 6)) ? 2 : 1;
3278
                break;
3279
            default:
3280
                abort();
3281
            }
3282
            nregs = ((insn >> 8) & 3) + 1;
3283
            gen_movl_T1_reg(s, rn);
3284
            for (reg = 0; reg < nregs; reg++) {
3285
                if (load) {
3286
                    if (size != 2) {
3287
                        NEON_GET_REG(T2, rd, pass);
3288
                    }
3289
                    switch (size) {
3290
                    case 0:
3291
                        gen_ldst(ldub, s);
3292
                        break;
3293
                    case 1:
3294
                        gen_ldst(lduw, s);
3295
                        break;
3296
                    case 2:
3297
                        gen_ldst(ldl, s);
3298
                        NEON_SET_REG(T0, rd, pass);
3299
                        break;
3300
                    }
3301
                    if (size != 2) {
3302
                        gen_op_neon_insert_elt(shift, ~mask);
3303
                        NEON_SET_REG(T0, rd, pass);
3304
                    }
3305
                } else { /* Store */
3306
                    if (size == 2) {
3307
                        NEON_GET_REG(T0, rd, pass);
3308
                    } else {
3309
                        NEON_GET_REG(T2, rd, pass);
3310
                        gen_op_neon_extract_elt(shift, mask);
3311
                    }
3312
                    switch (size) {
3313
                    case 0:
3314
                        gen_ldst(stb, s);
3315
                        break;
3316
                    case 1:
3317
                        gen_ldst(stw, s);
3318
                        break;
3319
                    case 2:
3320
                        gen_ldst(stl, s);
3321
                        break;
3322
                    }
3323
                }
3324
                rd += stride;
3325
                gen_op_addl_T1_im(1 << size);
3326
            }
3327
            stride = nregs * (1 << size);
3328
        }
3329
    }
3330
    if (rm != 15) {
3331
        TCGv base;
3332

    
3333
        base = load_reg(s, rn);
3334
        if (rm == 13) {
3335
            tcg_gen_addi_i32(base, base, stride);
3336
        } else {
3337
            TCGv index;
3338
            index = load_reg(s, rm);
3339
            tcg_gen_add_i32(base, base, index);
3340
            dead_tmp(index);
3341
        }
3342
        store_reg(s, rn, base);
3343
    }
3344
    return 0;
3345
}
3346

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

    
3354
static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
3355
{
3356
    int op;
3357
    int q;
3358
    int rd, rn, rm;
3359
    int size;
3360
    int shift;
3361
    int pass;
3362
    int count;
3363
    int pairwise;
3364
    int u;
3365
    int n;
3366
    uint32_t imm;
3367

    
3368
    if (!vfp_enabled(env))
3369
      return 1;
3370
    q = (insn & (1 << 6)) != 0;
3371
    u = (insn >> 24) & 1;
3372
    VFP_DREG_D(rd, insn);
3373
    VFP_DREG_N(rn, insn);
3374
    VFP_DREG_M(rm, insn);
3375
    size = (insn >> 20) & 3;
3376
    if ((insn & (1 << 23)) == 0) {
3377
        /* Three register same length.  */
3378
        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
3379
        if (size == 3 && (op == 1 || op == 5 || op == 16)) {
3380
            for (pass = 0; pass < (q ? 2 : 1); pass++) {
3381
                NEON_GET_REG(T0, rm, pass * 2);
3382
                NEON_GET_REG(T1, rm, pass * 2 + 1);
3383
                gen_neon_movl_scratch_T0(0);
3384
                gen_neon_movl_scratch_T1(1);
3385
                NEON_GET_REG(T0, rn, pass * 2);
3386
                NEON_GET_REG(T1, rn, pass * 2 + 1);
3387
                switch (op) {
3388
                case 1: /* VQADD */
3389
                    if (u) {
3390
                        gen_op_neon_addl_saturate_u64();
3391
                    } else {
3392
                        gen_op_neon_addl_saturate_s64();
3393
                    }
3394
                    break;
3395
                case 5: /* VQSUB */
3396
                    if (u) {
3397
                        gen_op_neon_subl_saturate_u64();
3398
                    } else {
3399
                        gen_op_neon_subl_saturate_s64();
3400
                    }
3401
                    break;
3402
                case 16:
3403
                    if (u) {
3404
                        gen_op_neon_subl_u64();
3405
                    } else {
3406
                        gen_op_neon_addl_u64();
3407
                    }
3408
                    break;
3409
                default:
3410
                    abort();
3411
                }
3412
                NEON_SET_REG(T0, rd, pass * 2);
3413
                NEON_SET_REG(T1, rd, pass * 2 + 1);
3414
            }
3415
            return 0;
3416
        }
3417
        switch (op) {
3418
        case 8: /* VSHL */
3419
        case 9: /* VQSHL */
3420
        case 10: /* VRSHL */
3421
        case 11: /* VQSHL */
3422
            /* Shift operations have Rn and Rm reversed.  */
3423
            {
3424
                int tmp;
3425
                tmp = rn;
3426
                rn = rm;
3427
                rm = tmp;
3428
                pairwise = 0;
3429
            }
3430
            break;
3431
        case 20: /* VPMAX */
3432
        case 21: /* VPMIN */
3433
        case 23: /* VPADD */
3434
            pairwise = 1;
3435
            break;
3436
        case 26: /* VPADD (float) */
3437
            pairwise = (u && size < 2);
3438
            break;
3439
        case 30: /* VPMIN/VPMAX (float) */
3440
            pairwise = u;
3441
            break;
3442
        default:
3443
            pairwise = 0;
3444
            break;
3445
        }
3446
        for (pass = 0; pass < (q ? 4 : 2); pass++) {
3447

    
3448
        if (pairwise) {
3449
            /* Pairwise.  */
3450
            if (q)
3451
                n = (pass & 1) * 2;
3452
            else
3453
                n = 0;
3454
            if (pass < q + 1) {
3455
                NEON_GET_REG(T0, rn, n);
3456
                NEON_GET_REG(T1, rn, n + 1);
3457
            } else {
3458
                NEON_GET_REG(T0, rm, n);
3459
                NEON_GET_REG(T1, rm, n + 1);
3460
            }
3461
        } else {
3462
            /* Elementwise.  */
3463
            NEON_GET_REG(T0, rn, pass);
3464
            NEON_GET_REG(T1, rm, pass);
3465
        }
3466
        switch (op) {
3467
        case 0: /* VHADD */
3468
            GEN_NEON_INTEGER_OP(hadd);
3469
            break;
3470
        case 1: /* VQADD */
3471
            switch (size << 1| u) {
3472
            case 0: gen_op_neon_qadd_s8(); break;
3473
            case 1: gen_op_neon_qadd_u8(); break;
3474
            case 2: gen_op_neon_qadd_s16(); break;
3475
            case 3: gen_op_neon_qadd_u16(); break;
3476
            case 4: gen_op_addl_T0_T1_saturate(); break;
3477
            case 5: gen_op_addl_T0_T1_usaturate(); break;
3478
            default: abort();
3479
            }
3480
            break;
3481
        case 2: /* VRHADD */
3482
            GEN_NEON_INTEGER_OP(rhadd);
3483
            break;
3484
        case 3: /* Logic ops.  */
3485
            switch ((u << 2) | size) {
3486
            case 0: /* VAND */
3487
                gen_op_andl_T0_T1();
3488
                break;
3489
            case 1: /* BIC */
3490
                gen_op_bicl_T0_T1();
3491
                break;
3492
            case 2: /* VORR */
3493
                gen_op_orl_T0_T1();
3494
                break;
3495
            case 3: /* VORN */
3496
                gen_op_notl_T1();
3497
                gen_op_orl_T0_T1();
3498
                break;
3499
            case 4: /* VEOR */
3500
                gen_op_xorl_T0_T1();
3501
                break;
3502
            case 5: /* VBSL */
3503
                NEON_GET_REG(T2, rd, pass);
3504
                gen_op_neon_bsl();
3505
                break;
3506
            case 6: /* VBIT */
3507
                NEON_GET_REG(T2, rd, pass);
3508
                gen_op_neon_bit();
3509
                break;
3510
            case 7: /* VBIF */
3511
                NEON_GET_REG(T2, rd, pass);
3512
                gen_op_neon_bif();
3513
                break;
3514
            }
3515
            break;
3516
        case 4: /* VHSUB */
3517
            GEN_NEON_INTEGER_OP(hsub);
3518
            break;
3519
        case 5: /* VQSUB */
3520
            switch ((size << 1) | u) {
3521
            case 0: gen_op_neon_qsub_s8(); break;
3522
            case 1: gen_op_neon_qsub_u8(); break;
3523
            case 2: gen_op_neon_qsub_s16(); break;
3524
            case 3: gen_op_neon_qsub_u16(); break;
3525
            case 4: gen_op_subl_T0_T1_saturate(); break;
3526
            case 5: gen_op_subl_T0_T1_usaturate(); break;
3527
            default: abort();
3528
            }
3529
            break;
3530
        case 6: /* VCGT */
3531
            GEN_NEON_INTEGER_OP(cgt);
3532
            break;
3533
        case 7: /* VCGE */
3534
            GEN_NEON_INTEGER_OP(cge);
3535
            break;
3536
        case 8: /* VSHL */
3537
            switch ((size << 1) | u) {
3538
            case 0: gen_op_neon_shl_s8(); break;
3539
            case 1: gen_op_neon_shl_u8(); break;
3540
            case 2: gen_op_neon_shl_s16(); break;
3541
            case 3: gen_op_neon_shl_u16(); break;
3542
            case 4: gen_op_neon_shl_s32(); break;
3543
            case 5: gen_op_neon_shl_u32(); break;
3544
#if 0
3545
            /* ??? Implementing these is tricky because the vector ops work
3546
               on 32-bit pieces.  */
3547
            case 6: gen_op_neon_shl_s64(); break;
3548
            case 7: gen_op_neon_shl_u64(); break;
3549
#else
3550
            case 6: case 7: cpu_abort(env, "VSHL.64 not implemented");
3551
#endif
3552
            }
3553
            break;
3554
        case 9: /* VQSHL */
3555
            switch ((size << 1) | u) {
3556
            case 0: gen_op_neon_qshl_s8(); break;
3557
            case 1: gen_op_neon_qshl_u8(); break;
3558
            case 2: gen_op_neon_qshl_s16(); break;
3559
            case 3: gen_op_neon_qshl_u16(); break;
3560
            case 4: gen_op_neon_qshl_s32(); break;
3561
            case 5: gen_op_neon_qshl_u32(); break;
3562
#if 0
3563
            /* ??? Implementing these is tricky because the vector ops work
3564
               on 32-bit pieces.  */
3565
            case 6: gen_op_neon_qshl_s64(); break;
3566
            case 7: gen_op_neon_qshl_u64(); break;
3567
#else
3568
            case 6: case 7: cpu_abort(env, "VQSHL.64 not implemented");
3569
#endif
3570
            }
3571
            break;
3572
        case 10: /* VRSHL */
3573
            switch ((size << 1) | u) {
3574
            case 0: gen_op_neon_rshl_s8(); break;
3575
            case 1: gen_op_neon_rshl_u8(); break;
3576
            case 2: gen_op_neon_rshl_s16(); break;
3577
            case 3: gen_op_neon_rshl_u16(); break;
3578
            case 4: gen_op_neon_rshl_s32(); break;
3579
            case 5: gen_op_neon_rshl_u32(); break;
3580
#if 0
3581
            /* ??? Implementing these is tricky because the vector ops work
3582
               on 32-bit pieces.  */
3583
            case 6: gen_op_neon_rshl_s64(); break;
3584
            case 7: gen_op_neon_rshl_u64(); break;
3585
#else
3586
            case 6: case 7: cpu_abort(env, "VRSHL.64 not implemented");
3587
#endif
3588
            }
3589
            break;
3590
        case 11: /* VQRSHL */
3591
            switch ((size << 1) | u) {
3592
            case 0: gen_op_neon_qrshl_s8(); break;
3593
            case 1: gen_op_neon_qrshl_u8(); break;
3594
            case 2: gen_op_neon_qrshl_s16(); break;
3595
            case 3: gen_op_neon_qrshl_u16(); break;
3596
            case 4: gen_op_neon_qrshl_s32(); break;
3597
            case 5: gen_op_neon_qrshl_u32(); break;
3598
#if 0
3599
            /* ??? Implementing these is tricky because the vector ops work
3600
               on 32-bit pieces.  */
3601
            case 6: gen_op_neon_qrshl_s64(); break;
3602
            case 7: gen_op_neon_qrshl_u64(); break;
3603
#else
3604
            case 6: case 7: cpu_abort(env, "VQRSHL.64 not implemented");
3605
#endif
3606
            }
3607
            break;
3608
        case 12: /* VMAX */
3609
            GEN_NEON_INTEGER_OP(max);
3610
            break;
3611
        case 13: /* VMIN */
3612
            GEN_NEON_INTEGER_OP(min);
3613
            break;
3614
        case 14: /* VABD */
3615
            GEN_NEON_INTEGER_OP(abd);
3616
            break;
3617
        case 15: /* VABA */
3618
            GEN_NEON_INTEGER_OP(abd);
3619
            NEON_GET_REG(T1, rd, pass);
3620
            gen_neon_add(size);
3621
            break;
3622
        case 16:
3623
            if (!u) { /* VADD */
3624
                if (gen_neon_add(size))
3625
                    return 1;
3626
            } else { /* VSUB */
3627
                switch (size) {
3628
                case 0: gen_op_neon_sub_u8(); break;
3629
                case 1: gen_op_neon_sub_u16(); break;
3630
                case 2: gen_op_subl_T0_T1(); break;
3631
                default: return 1;
3632
                }
3633
            }
3634
            break;
3635
        case 17:
3636
            if (!u) { /* VTST */
3637
                switch (size) {
3638
                case 0: gen_op_neon_tst_u8(); break;
3639
                case 1: gen_op_neon_tst_u16(); break;
3640
                case 2: gen_op_neon_tst_u32(); break;
3641
                default: return 1;
3642
                }
3643
            } else { /* VCEQ */
3644
                switch (size) {
3645
                case 0: gen_op_neon_ceq_u8(); break;
3646
                case 1: gen_op_neon_ceq_u16(); break;
3647
                case 2: gen_op_neon_ceq_u32(); break;
3648
                default: return 1;
3649
                }
3650
            }
3651
            break;
3652
        case 18: /* Multiply.  */
3653
            switch (size) {
3654
            case 0: gen_op_neon_mul_u8(); break;
3655
            case 1: gen_op_neon_mul_u16(); break;
3656
            case 2: gen_op_mul_T0_T1(); break;
3657
            default: return 1;
3658
            }
3659
            NEON_GET_REG(T1, rd, pass);
3660
            if (u) { /* VMLS */
3661
                switch (size) {
3662
                case 0: gen_op_neon_rsb_u8(); break;
3663
                case 1: gen_op_neon_rsb_u16(); break;
3664
                case 2: gen_op_rsbl_T0_T1(); break;
3665
                default: return 1;
3666
                }
3667
            } else { /* VMLA */
3668
                gen_neon_add(size);
3669
            }
3670
            break;
3671
        case 19: /* VMUL */
3672
            if (u) { /* polynomial */
3673
                gen_op_neon_mul_p8();
3674
            } else { /* Integer */
3675
                switch (size) {
3676
                case 0: gen_op_neon_mul_u8(); break;
3677
                case 1: gen_op_neon_mul_u16(); break;
3678
                case 2: gen_op_mul_T0_T1(); break;
3679
                default: return 1;
3680
                }
3681
            }
3682
            break;
3683
        case 20: /* VPMAX */
3684
            GEN_NEON_INTEGER_OP(pmax);
3685
            break;
3686
        case 21: /* VPMIN */
3687
            GEN_NEON_INTEGER_OP(pmin);
3688
            break;
3689
        case 22: /* Hultiply high.  */
3690
            if (!u) { /* VQDMULH */
3691
                switch (size) {
3692
                case 1: gen_op_neon_qdmulh_s16(); break;
3693
                case 2: gen_op_neon_qdmulh_s32(); break;
3694
                default: return 1;
3695
                }
3696
            } else { /* VQRDHMUL */
3697
                switch (size) {
3698
                case 1: gen_op_neon_qrdmulh_s16(); break;
3699
                case 2: gen_op_neon_qrdmulh_s32(); break;
3700
                default: return 1;
3701
                }
3702
            }
3703
            break;
3704
        case 23: /* VPADD */
3705
            if (u)
3706
                return 1;
3707
            switch (size) {
3708
            case 0: gen_op_neon_padd_u8(); break;
3709
            case 1: gen_op_neon_padd_u16(); break;
3710
            case 2: gen_op_addl_T0_T1(); break;
3711
            default: return 1;
3712
            }
3713
            break;
3714
        case 26: /* Floating point arithnetic.  */
3715
            switch ((u << 2) | size) {
3716
            case 0: /* VADD */
3717
                gen_op_neon_add_f32();
3718
                break;
3719
            case 2: /* VSUB */
3720
                gen_op_neon_sub_f32();
3721
                break;
3722
            case 4: /* VPADD */
3723
                gen_op_neon_add_f32();
3724
                break;
3725
            case 6: /* VABD */
3726
                gen_op_neon_abd_f32();
3727
                break;
3728
            default:
3729
                return 1;
3730
            }
3731
            break;
3732
        case 27: /* Float multiply.  */
3733
            gen_op_neon_mul_f32();
3734
            if (!u) {
3735
                NEON_GET_REG(T1, rd, pass);
3736
                if (size == 0) {
3737
                    gen_op_neon_add_f32();
3738
                } else {
3739
                    gen_op_neon_rsb_f32();
3740
                }
3741
            }
3742
            break;
3743
        case 28: /* Float compare.  */
3744
            if (!u) {
3745
                gen_op_neon_ceq_f32();
3746
            } else {
3747
                if (size == 0)
3748
                    gen_op_neon_cge_f32();
3749
                else
3750
                    gen_op_neon_cgt_f32();
3751
            }
3752
            break;
3753
        case 29: /* Float compare absolute.  */
3754
            if (!u)
3755
                return 1;
3756
            if (size == 0)
3757
                gen_op_neon_acge_f32();
3758
            else
3759
                gen_op_neon_acgt_f32();
3760
            break;
3761
        case 30: /* Float min/max.  */
3762
            if (size == 0)
3763
                gen_op_neon_max_f32();
3764
            else
3765
                gen_op_neon_min_f32();
3766
            break;
3767
        case 31:
3768
            if (size == 0)
3769
                gen_op_neon_recps_f32();
3770
            else
3771
                gen_op_neon_rsqrts_f32();
3772
            break;
3773
        default:
3774
            abort();
3775
        }
3776
        /* Save the result.  For elementwise operations we can put it
3777
           straight into the destination register.  For pairwise operations
3778
           we have to be careful to avoid clobbering the source operands.  */
3779
        if (pairwise && rd == rm) {
3780
            gen_neon_movl_scratch_T0(pass);
3781
        } else {
3782
            NEON_SET_REG(T0, rd, pass);
3783
        }
3784

    
3785
        } /* for pass */
3786
        if (pairwise && rd == rm) {
3787
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
3788
                gen_neon_movl_T0_scratch(pass);
3789
                NEON_SET_REG(T0, rd, pass);
3790
            }
3791
        }
3792
    } else if (insn & (1 << 4)) {
3793
        if ((insn & 0x00380080) != 0) {
3794
            /* Two registers and shift.  */
3795
            op = (insn >> 8) & 0xf;
3796
            if (insn & (1 << 7)) {
3797
                /* 64-bit shift.   */
3798
                size = 3;
3799
            } else {
3800
                size = 2;
3801
                while ((insn & (1 << (size + 19))) == 0)
3802
                    size--;
3803
            }
3804
            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
3805
            /* To avoid excessive dumplication of ops we implement shift
3806
               by immediate using the variable shift operations.  */
3807
            if (op < 8) {
3808
                /* Shift by immediate:
3809
                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
3810
                /* Right shifts are encoded as N - shift, where N is the
3811
                   element size in bits.  */
3812
                if (op <= 4)
3813
                    shift = shift - (1 << (size + 3));
3814
                else
3815
                    shift++;
3816
                if (size == 3) {
3817
                    count = q + 1;
3818
                } else {
3819
                    count = q ? 4: 2;
3820
                }
3821
                switch (size) {
3822
                case 0:
3823
                    imm = (uint8_t) shift;
3824
                    imm |= imm << 8;
3825
                    imm |= imm << 16;
3826
                    break;
3827
                case 1:
3828
                    imm = (uint16_t) shift;
3829
                    imm |= imm << 16;
3830
                    break;
3831
                case 2:
3832
                case 3:
3833
                    imm = shift;
3834
                    break;
3835
                default:
3836
                    abort();
3837
                }
3838

    
3839
                for (pass = 0; pass < count; pass++) {
3840
                    if (size < 3) {
3841
                        /* Operands in T0 and T1.  */
3842
                        gen_op_movl_T1_im(imm);
3843
                        NEON_GET_REG(T0, rm, pass);
3844
                    } else {
3845
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3846
                        gen_op_movl_T0_im(imm);
3847
                        gen_neon_movl_scratch_T0(0);
3848
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3849
                        gen_neon_movl_scratch_T0(1);
3850
                        NEON_GET_REG(T0, rm, pass * 2);
3851
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
3852
                    }
3853

    
3854
                    if (gen_neon_shift_im[op][u][size] == NULL)
3855
                        return 1;
3856
                    gen_neon_shift_im[op][u][size]();
3857

    
3858
                    if (op == 1 || op == 3) {
3859
                        /* Accumulate.  */
3860
                        if (size == 3) {
3861
                            gen_neon_movl_scratch_T0(0);
3862
                            gen_neon_movl_scratch_T1(1);
3863
                            NEON_GET_REG(T0, rd, pass * 2);
3864
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
3865
                            gen_op_neon_addl_u64();
3866
                        } else {
3867
                            NEON_GET_REG(T1, rd, pass);
3868
                            gen_neon_add(size);
3869
                        }
3870
                    } else if (op == 4 || (op == 5 && u)) {
3871
                        /* Insert */
3872
                        if (size == 3) {
3873
                            cpu_abort(env, "VS[LR]I.64 not implemented");
3874
                        }
3875
                        switch (size) {
3876
                        case 0:
3877
                            if (op == 4)
3878
                                imm = 0xff >> -shift;
3879
                            else
3880
                                imm = (uint8_t)(0xff << shift);
3881
                            imm |= imm << 8;
3882
                            imm |= imm << 16;
3883
                            break;
3884
                        case 1:
3885
                            if (op == 4)
3886
                                imm = 0xffff >> -shift;
3887
                            else
3888
                                imm = (uint16_t)(0xffff << shift);
3889
                            imm |= imm << 16;
3890
                            break;
3891
                        case 2:
3892
                            if (op == 4)
3893
                                imm = 0xffffffffu >> -shift;
3894
                            else
3895
                                imm = 0xffffffffu << shift;
3896
                            break;
3897
                        default:
3898
                            abort();
3899
                        }
3900
                        NEON_GET_REG(T1, rd, pass);
3901
                        gen_op_movl_T2_im(imm);
3902
                        gen_op_neon_bsl();
3903
                    }
3904
                    if (size == 3) {
3905
                        NEON_SET_REG(T0, rd, pass * 2);
3906
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
3907
                    } else {
3908
                        NEON_SET_REG(T0, rd, pass);
3909
                    }
3910
                } /* for pass */
3911
            } else if (op < 10) {
3912
                /* Shift by immedaiate and narrow:
3913
                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
3914
                shift = shift - (1 << (size + 3));
3915
                size++;
3916
                if (size == 3) {
3917
                    count = q + 1;
3918
                } else {
3919
                    count = q ? 4: 2;
3920
                }
3921
                switch (size) {
3922
                case 1:
3923
                    imm = (uint16_t) shift;
3924
                    imm |= imm << 16;
3925
                    break;
3926
                case 2:
3927
                case 3:
3928
                    imm = shift;
3929
                    break;
3930
                default:
3931
                    abort();
3932
                }
3933

    
3934
                /* Processing MSB first means we need to do less shuffling at
3935
                   the end.  */
3936
                for (pass =  count - 1; pass >= 0; pass--) {
3937
                    /* Avoid clobbering the second operand before it has been
3938
                       written.  */
3939
                    n = pass;
3940
                    if (rd == rm)
3941
                        n ^= (count - 1);
3942
                    else
3943
                        n = pass;
3944

    
3945
                    if (size < 3) {
3946
                        /* Operands in T0 and T1.  */
3947
                        gen_op_movl_T1_im(imm);
3948
                        NEON_GET_REG(T0, rm, n);
3949
                    } else {
3950
                        /* Operands in {T0, T1} and env->vfp.scratch.  */
3951
                        gen_op_movl_T0_im(imm);
3952
                        gen_neon_movl_scratch_T0(0);
3953
                        gen_op_movl_T0_im((int32_t)imm >> 31);
3954
                        gen_neon_movl_scratch_T0(1);
3955
                        NEON_GET_REG(T0, rm, n * 2);
3956
                        NEON_GET_REG(T0, rm, n * 2 + 1);
3957
                    }
3958

    
3959
                    gen_neon_shift_im_narrow[q][u][size - 1]();
3960

    
3961
                    if (size < 3 && (pass & 1) == 0) {
3962
                        gen_neon_movl_scratch_T0(0);
3963
                    } else {
3964
                        uint32_t offset;
3965

    
3966
                        if (size < 3)
3967
                            gen_neon_movl_T1_scratch(0);
3968

    
3969
                        if (op == 8 && !u) {
3970
                            gen_neon_narrow[size - 1]();
3971
                        } else {
3972
                            if (op == 8)
3973
                                gen_neon_narrow_sats[size - 2]();
3974
                            else
3975
                                gen_neon_narrow_satu[size - 1]();
3976
                        }
3977
                        if (size == 3)
3978
                            offset = neon_reg_offset(rd, n);
3979
                        else
3980
                            offset = neon_reg_offset(rd, n >> 1);
3981
                        gen_op_neon_setreg_T0(offset);
3982
                    }
3983
                } /* for pass */
3984
            } else if (op == 10) {
3985
                /* VSHLL */
3986
                if (q)
3987
                    return 1;
3988
                for (pass = 0; pass < 2; pass++) {
3989
                    /* Avoid clobbering the input operand.  */
3990
                    if (rd == rm)
3991
                        n = 1 - pass;
3992
                    else
3993
                        n = pass;
3994

    
3995
                    NEON_GET_REG(T0, rm, n);
3996
                    GEN_NEON_INTEGER_OP(widen);
3997
                    if (shift != 0) {
3998
                        /* The shift is less than the width of the source
3999
                           type, so in some cases we can just
4000
                           shift the whole register.  */
4001
                        if (size == 1 || (size == 0 && u)) {
4002
                            gen_op_shll_T0_im(shift);
4003
                            gen_op_shll_T1_im(shift);
4004
                        } else {
4005
                            switch (size) {
4006
                            case 0: gen_op_neon_shll_u16(shift); break;
4007
                            case 2: gen_op_neon_shll_u64(shift); break;
4008
                            default: abort();
4009
                            }
4010
                        }
4011
                    }
4012
                    NEON_SET_REG(T0, rd, n * 2);
4013
                    NEON_SET_REG(T1, rd, n * 2 + 1);
4014
                }
4015
            } else if (op == 15 || op == 16) {
4016
                /* VCVT fixed-point.  */
4017
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4018
                    gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4019
                    if (op & 1) {
4020
                        if (u)
4021
                            gen_op_vfp_ultos(shift);
4022
                        else
4023
                            gen_op_vfp_sltos(shift);
4024
                    } else {
4025
                        if (u)
4026
                            gen_op_vfp_touls(shift);
4027
                        else
4028
                            gen_op_vfp_tosls(shift);
4029
                    }
4030
                    gen_op_vfp_setreg_F0s(neon_reg_offset(rd, pass));
4031
                }
4032
            } else {
4033
                return 1;
4034
            }
4035
        } else { /* (insn & 0x00380080) == 0 */
4036
            int invert;
4037

    
4038
            op = (insn >> 8) & 0xf;
4039
            /* One register and immediate.  */
4040
            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4041
            invert = (insn & (1 << 5)) != 0;
4042
            switch (op) {
4043
            case 0: case 1:
4044
                /* no-op */
4045
                break;
4046
            case 2: case 3:
4047
                imm <<= 8;
4048
                break;
4049
            case 4: case 5:
4050
                imm <<= 16;
4051
                break;
4052
            case 6: case 7:
4053
                imm <<= 24;
4054
                break;
4055
            case 8: case 9:
4056
                imm |= imm << 16;
4057
                break;
4058
            case 10: case 11:
4059
                imm = (imm << 8) | (imm << 24);
4060
                break;
4061
            case 12:
4062
                imm = (imm < 8) | 0xff;
4063
                break;
4064
            case 13:
4065
                imm = (imm << 16) | 0xffff;
4066
                break;
4067
            case 14:
4068
                imm |= (imm << 8) | (imm << 16) | (imm << 24);
4069
                if (invert)
4070
                    imm = ~imm;
4071
                break;
4072
            case 15:
4073
                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4074
                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4075
                break;
4076
            }
4077
            if (invert)
4078
                imm = ~imm;
4079

    
4080
            if (op != 14 || !invert)
4081
                gen_op_movl_T1_im(imm);
4082

    
4083
            for (pass = 0; pass < (q ? 4 : 2); pass++) {
4084
                if (op & 1 && op < 12) {
4085
                    NEON_GET_REG(T0, rd, pass);
4086
                    if (invert) {
4087
                        /* The immediate value has already been inverted, so
4088
                           BIC becomes AND.  */
4089
                        gen_op_andl_T0_T1();
4090
                    } else {
4091
                        gen_op_orl_T0_T1();
4092
                    }
4093
                    NEON_SET_REG(T0, rd, pass);
4094
                } else {
4095
                    if (op == 14 && invert) {
4096
                        uint32_t tmp;
4097
                        tmp = 0;
4098
                        for (n = 0; n < 4; n++) {
4099
                            if (imm & (1 << (n + (pass & 1) * 4)))
4100
                                tmp |= 0xff << (n * 8);
4101
                        }
4102
                        gen_op_movl_T1_im(tmp);
4103
                    }
4104
                    /* VMOV, VMVN.  */
4105
                    NEON_SET_REG(T1, rd, pass);
4106
                }
4107
            }
4108
        }
4109
    } else { /* (insn & 0x00800010 == 0x00800010) */
4110
        if (size != 3) {
4111
            op = (insn >> 8) & 0xf;
4112
            if ((insn & (1 << 6)) == 0) {
4113
                /* Three registers of different lengths.  */
4114
                int src1_wide;
4115
                int src2_wide;
4116
                int prewiden;
4117
                /* prewiden, src1_wide, src2_wide */
4118
                static const int neon_3reg_wide[16][3] = {
4119
                    {1, 0, 0}, /* VADDL */
4120
                    {1, 1, 0}, /* VADDW */
4121
                    {1, 0, 0}, /* VSUBL */
4122
                    {1, 1, 0}, /* VSUBW */
4123
                    {0, 1, 1}, /* VADDHN */
4124
                    {0, 0, 0}, /* VABAL */
4125
                    {0, 1, 1}, /* VSUBHN */
4126
                    {0, 0, 0}, /* VABDL */
4127
                    {0, 0, 0}, /* VMLAL */
4128
                    {0, 0, 0}, /* VQDMLAL */
4129
                    {0, 0, 0}, /* VMLSL */
4130
                    {0, 0, 0}, /* VQDMLSL */
4131
                    {0, 0, 0}, /* Integer VMULL */
4132
                    {0, 0, 0}, /* VQDMULL */
4133
                    {0, 0, 0}  /* Polynomial VMULL */
4134
                };
4135

    
4136
                prewiden = neon_3reg_wide[op][0];
4137
                src1_wide = neon_3reg_wide[op][1];
4138
                src2_wide = neon_3reg_wide[op][2];
4139

    
4140
                /* Avoid overlapping operands.  Wide source operands are
4141
                   always aligned so will never overlap with wide
4142
                   destinations in problematic ways.  */
4143
                if (rd == rm) {
4144
                    NEON_GET_REG(T2, rm, 1);
4145
                } else if (rd == rn) {
4146
                    NEON_GET_REG(T2, rn, 1);
4147
                }
4148
                for (pass = 0; pass < 2; pass++) {
4149
                    /* Load the second operand into env->vfp.scratch.
4150
                       Also widen narrow operands.  */
4151
                    if (pass == 1 && rd == rm) {
4152
                        if (prewiden) {
4153
                            gen_op_movl_T0_T2();
4154
                        } else {
4155
                            gen_op_movl_T1_T2();
4156
                        }
4157
                    } else {
4158
                        if (src2_wide) {
4159
                            NEON_GET_REG(T0, rm, pass * 2);
4160
                            NEON_GET_REG(T1, rm, pass * 2 + 1);
4161
                        } else {
4162
                            if (prewiden) {
4163
                                NEON_GET_REG(T0, rm, pass);
4164
                            } else {
4165
                                NEON_GET_REG(T1, rm, pass);
4166
                            }
4167
                        }
4168
                    }
4169
                    if (prewiden && !src2_wide) {
4170
                        GEN_NEON_INTEGER_OP(widen);
4171
                    }
4172
                    if (prewiden || src2_wide) {
4173
                        gen_neon_movl_scratch_T0(0);
4174
                        gen_neon_movl_scratch_T1(1);
4175
                    }
4176

    
4177
                    /* Load the first operand.  */
4178
                    if (pass == 1 && rd == rn) {
4179
                        gen_op_movl_T0_T2();
4180
                    } else {
4181
                        if (src1_wide) {
4182
                            NEON_GET_REG(T0, rn, pass * 2);
4183
                            NEON_GET_REG(T1, rn, pass * 2 + 1);
4184
                        } else {
4185
                            NEON_GET_REG(T0, rn, pass);
4186
                        }
4187
                    }
4188
                    if (prewiden && !src1_wide) {
4189
                        GEN_NEON_INTEGER_OP(widen);
4190
                    }
4191
                    switch (op) {
4192
                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4193
                        switch (size) {
4194
                        case 0: gen_op_neon_addl_u16(); break;
4195
                        case 1: gen_op_neon_addl_u32(); break;
4196
                        case 2: gen_op_neon_addl_u64(); break;
4197
                        default: abort();
4198
                        }
4199
                        break;
4200
                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4201
                        switch (size) {
4202
                        case 0: gen_op_neon_subl_u16(); break;
4203
                        case 1: gen_op_neon_subl_u32(); break;
4204
                        case 2: gen_op_neon_subl_u64(); break;
4205
                        default: abort();
4206
                        }
4207
                        break;
4208
                    case 5: case 7: /* VABAL, VABDL */
4209
                        switch ((size << 1) | u) {
4210
                        case 0: gen_op_neon_abdl_s16(); break;
4211
                        case 1: gen_op_neon_abdl_u16(); break;
4212
                        case 2: gen_op_neon_abdl_s32(); break;
4213
                        case 3: gen_op_neon_abdl_u32(); break;
4214
                        case 4: gen_op_neon_abdl_s64(); break;
4215
                        case 5: gen_op_neon_abdl_u64(); break;
4216
                        default: abort();
4217
                        }
4218
                        break;
4219
                    case 8: case 9: case 10: case 11: case 12: case 13:
4220
                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4221
                        switch ((size << 1) | u) {
4222
                        case 0: gen_op_neon_mull_s8(); break;
4223
                        case 1: gen_op_neon_mull_u8(); break;
4224
                        case 2: gen_op_neon_mull_s16(); break;
4225
                        case 3: gen_op_neon_mull_u16(); break;
4226
                        case 4: gen_op_imull_T0_T1(); break;
4227
                        case 5: gen_op_mull_T0_T1(); break;
4228
                        default: abort();
4229
                        }
4230
                        break;
4231
                    case 14: /* Polynomial VMULL */
4232
                        cpu_abort(env, "Polynomial VMULL not implemented");
4233

    
4234
                    default: /* 15 is RESERVED.  */
4235
                        return 1;
4236
                    }
4237
                    if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4238
                        /* Accumulate.  */
4239
                        if (op == 10 || op == 11) {
4240
                            switch (size) {
4241
                            case 0: gen_op_neon_negl_u16(); break;
4242
                            case 1: gen_op_neon_negl_u32(); break;
4243
                            case 2: gen_op_neon_negl_u64(); break;
4244
                            default: abort();
4245
                            }
4246
                        }
4247

    
4248
                        gen_neon_movl_scratch_T0(0);
4249
                        gen_neon_movl_scratch_T1(1);
4250

    
4251
                        if (op != 13) {
4252
                            NEON_GET_REG(T0, rd, pass * 2);
4253
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4254
                        }
4255

    
4256
                        switch (op) {
4257
                        case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4258
                            switch (size) {
4259
                            case 0: gen_op_neon_addl_u16(); break;
4260
                            case 1: gen_op_neon_addl_u32(); break;
4261
                            case 2: gen_op_neon_addl_u64(); break;
4262
                            default: abort();
4263
                            }
4264
                            break;
4265
                        case 9: case 11: /* VQDMLAL, VQDMLSL */
4266
                            switch (size) {
4267
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4268
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4269
                            default: abort();
4270
                            }
4271
                            /* Fall through.  */
4272
                        case 13: /* VQDMULL */
4273
                            switch (size) {
4274
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4275
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4276
                            default: abort();
4277
                            }
4278
                            break;
4279
                        default:
4280
                            abort();
4281
                        }
4282
                        NEON_SET_REG(T0, rd, pass * 2);
4283
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4284
                    } else if (op == 4 || op == 6) {
4285
                        /* Narrowing operation.  */
4286
                        if (u) {
4287
                            switch (size) {
4288
                            case 0: gen_op_neon_narrow_high_u8(); break;
4289
                            case 1: gen_op_neon_narrow_high_u16(); break;
4290
                            case 2: gen_op_movl_T0_T1(); break;
4291
                            default: abort();
4292
                            }
4293
                        } else {
4294
                            switch (size) {
4295
                            case 0: gen_op_neon_narrow_high_round_u8(); break;
4296
                            case 1: gen_op_neon_narrow_high_round_u16(); break;
4297
                            case 2: gen_op_neon_narrow_high_round_u32(); break;
4298
                            default: abort();
4299
                            }
4300
                        }
4301
                        NEON_SET_REG(T0, rd, pass);
4302
                    } else {
4303
                        /* Write back the result.  */
4304
                        NEON_SET_REG(T0, rd, pass * 2);
4305
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4306
                    }
4307
                }
4308
            } else {
4309
                /* Two registers and a scalar.  */
4310
                switch (op) {
4311
                case 0: /* Integer VMLA scalar */
4312
                case 1: /* Float VMLA scalar */
4313
                case 4: /* Integer VMLS scalar */
4314
                case 5: /* Floating point VMLS scalar */
4315
                case 8: /* Integer VMUL scalar */
4316
                case 9: /* Floating point VMUL scalar */
4317
                case 12: /* VQDMULH scalar */
4318
                case 13: /* VQRDMULH scalar */
4319
                    gen_neon_get_scalar(size, rm);
4320
                    gen_op_movl_T2_T0();
4321
                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
4322
                        if (pass != 0)
4323
                            gen_op_movl_T0_T2();
4324
                        NEON_GET_REG(T1, rn, pass);
4325
                        if (op == 12) {
4326
                            if (size == 1) {
4327
                                gen_op_neon_qdmulh_s16();
4328
                            } else {
4329
                                gen_op_neon_qdmulh_s32();
4330
                            }
4331
                        } else if (op == 13) {
4332
                            if (size == 1) {
4333
                                gen_op_neon_qrdmulh_s16();
4334
                            } else {
4335
                                gen_op_neon_qrdmulh_s32();
4336
                            }
4337
                        } else if (op & 1) {
4338
                            gen_op_neon_mul_f32();
4339
                        } else {
4340
                            switch (size) {
4341
                            case 0: gen_op_neon_mul_u8(); break;
4342
                            case 1: gen_op_neon_mul_u16(); break;
4343
                            case 2: gen_op_mul_T0_T1(); break;
4344
                            default: return 1;
4345
                            }
4346
                        }
4347
                        if (op < 8) {
4348
                            /* Accumulate.  */
4349
                            NEON_GET_REG(T1, rd, pass);
4350
                            switch (op) {
4351
                            case 0:
4352
                                gen_neon_add(size);
4353
                                break;
4354
                            case 1:
4355
                                gen_op_neon_add_f32();
4356
                                break;
4357
                            case 4:
4358
                                switch (size) {
4359
                                case 0: gen_op_neon_rsb_u8(); break;
4360
                                case 1: gen_op_neon_rsb_u16(); break;
4361
                                case 2: gen_op_rsbl_T0_T1(); break;
4362
                                default: return 1;
4363
                                }
4364
                                break;
4365
                            case 5:
4366
                                gen_op_neon_rsb_f32();
4367
                                break;
4368
                            default:
4369
                                abort();
4370
                            }
4371
                        }
4372
                        NEON_SET_REG(T0, rd, pass);
4373
                    }
4374
                    break;
4375
                case 2: /* VMLAL sclar */
4376
                case 3: /* VQDMLAL scalar */
4377
                case 6: /* VMLSL scalar */
4378
                case 7: /* VQDMLSL scalar */
4379
                case 10: /* VMULL scalar */
4380
                case 11: /* VQDMULL scalar */
4381
                    if (rd == rn) {
4382
                        /* Save overlapping operands before they are
4383
                           clobbered.  */
4384
                        NEON_GET_REG(T0, rn, 1);
4385
                        gen_neon_movl_scratch_T0(2);
4386
                    }
4387
                    gen_neon_get_scalar(size, rm);
4388
                    gen_op_movl_T2_T0();
4389
                    for (pass = 0; pass < 2; pass++) {
4390
                        if (pass != 0) {
4391
                            gen_op_movl_T0_T2();
4392
                        }
4393
                        if (pass != 0 && rd == rn) {
4394
                            gen_neon_movl_T1_scratch(2);
4395
                        } else {
4396
                            NEON_GET_REG(T1, rn, pass);
4397
                        }
4398
                        switch ((size << 1) | u) {
4399
                        case 0: gen_op_neon_mull_s8(); break;
4400
                        case 1: gen_op_neon_mull_u8(); break;
4401
                        case 2: gen_op_neon_mull_s16(); break;
4402
                        case 3: gen_op_neon_mull_u16(); break;
4403
                        case 4: gen_op_imull_T0_T1(); break;
4404
                        case 5: gen_op_mull_T0_T1(); break;
4405
                        default: abort();
4406
                        }
4407
                        if (op == 6 || op == 7) {
4408
                            switch (size) {
4409
                            case 0: gen_op_neon_negl_u16(); break;
4410
                            case 1: gen_op_neon_negl_u32(); break;
4411
                            case 2: gen_op_neon_negl_u64(); break;
4412
                            default: abort();
4413
                            }
4414
                        }
4415
                        gen_neon_movl_scratch_T0(0);
4416
                        gen_neon_movl_scratch_T1(1);
4417
                        NEON_GET_REG(T0, rd, pass * 2);
4418
                        NEON_GET_REG(T1, rd, pass * 2 + 1);
4419
                        switch (op) {
4420
                        case 2: case 6:
4421
                            switch (size) {
4422
                            case 0: gen_op_neon_addl_u16(); break;
4423
                            case 1: gen_op_neon_addl_u32(); break;
4424
                            case 2: gen_op_neon_addl_u64(); break;
4425
                            default: abort();
4426
                            }
4427
                            break;
4428
                        case 3: case 7:
4429
                            switch (size) {
4430
                            case 1:
4431
                                gen_op_neon_addl_saturate_s32();
4432
                                gen_op_neon_addl_saturate_s32();
4433
                                break;
4434
                            case 2:
4435
                                gen_op_neon_addl_saturate_s64();
4436
                                gen_op_neon_addl_saturate_s64();
4437
                                break;
4438
                            default: abort();
4439
                            }
4440
                            break;
4441
                        case 10:
4442
                            /* no-op */
4443
                            break;
4444
                        case 11:
4445
                            switch (size) {
4446
                            case 1: gen_op_neon_addl_saturate_s32(); break;
4447
                            case 2: gen_op_neon_addl_saturate_s64(); break;
4448
                            default: abort();
4449
                            }
4450
                            break;
4451
                        default:
4452
                            abort();
4453
                        }
4454
                        NEON_SET_REG(T0, rd, pass * 2);
4455
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4456
                    }
4457
                    break;
4458
                default: /* 14 and 15 are RESERVED */
4459
                    return 1;
4460
                }
4461
            }
4462
        } else { /* size == 3 */
4463
            if (!u) {
4464
                /* Extract.  */
4465
                int reg;
4466
                imm = (insn >> 8) & 0xf;
4467
                reg = rn;
4468
                count = q ? 4 : 2;
4469
                n = imm >> 2;
4470
                NEON_GET_REG(T0, reg, n);
4471
                for (pass = 0; pass < count; pass++) {
4472
                    n++;
4473
                    if (n > count) {
4474
                        reg = rm;
4475
                        n -= count;
4476
                    }
4477
                    if (imm & 3) {
4478
                        NEON_GET_REG(T1, reg, n);
4479
                        gen_op_neon_extract((insn << 3) & 0x1f);
4480
                    }
4481
                    /* ??? This is broken if rd and rm overlap */
4482
                    NEON_SET_REG(T0, rd, pass);
4483
                    if (imm & 3) {
4484
                        gen_op_movl_T0_T1();
4485
                    } else {
4486
                        NEON_GET_REG(T0, reg, n);
4487
                    }
4488
                }
4489
            } else if ((insn & (1 << 11)) == 0) {
4490
                /* Two register misc.  */
4491
                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
4492
                size = (insn >> 18) & 3;
4493
                switch (op) {
4494
                case 0: /* VREV64 */
4495
                    if (size == 3)
4496
                        return 1;
4497
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4498
                        NEON_GET_REG(T0, rm, pass * 2);
4499
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4500
                        switch (size) {
4501
                        case 0: gen_op_rev_T0(); break;
4502
                        case 1: gen_swap_half(cpu_T[0]); break;
4503
                        case 2: /* no-op */ break;
4504
                        default: abort();
4505
                        }
4506
                        NEON_SET_REG(T0, rd, pass * 2 + 1);
4507
                        if (size == 2) {
4508
                            NEON_SET_REG(T1, rd, pass * 2);
4509
                        } else {
4510
                            gen_op_movl_T0_T1();
4511
                            switch (size) {
4512
                            case 0: gen_op_rev_T0(); break;
4513
                            case 1: gen_swap_half(cpu_T[0]); break;
4514
                            default: abort();
4515
                            }
4516
                            NEON_SET_REG(T0, rd, pass * 2);
4517
                        }
4518
                    }
4519
                    break;
4520
                case 4: case 5: /* VPADDL */
4521
                case 12: case 13: /* VPADAL */
4522
                    if (size < 2)
4523
                        goto elementwise;
4524
                    if (size == 3)
4525
                        return 1;
4526
                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
4527
                        NEON_GET_REG(T0, rm, pass * 2);
4528
                        NEON_GET_REG(T1, rm, pass * 2 + 1);
4529
                        if (op & 1)
4530
                            gen_op_neon_paddl_u32();
4531
                        else
4532
                            gen_op_neon_paddl_s32();
4533
                        if (op >= 12) {
4534
                            /* Accumulate.  */
4535
                            gen_neon_movl_scratch_T0(0);
4536
                            gen_neon_movl_scratch_T1(1);
4537

    
4538
                            NEON_GET_REG(T0, rd, pass * 2);
4539
                            NEON_GET_REG(T1, rd, pass * 2 + 1);
4540
                            gen_op_neon_addl_u64();
4541
                        }
4542
                        NEON_SET_REG(T0, rd, pass * 2);
4543
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4544
                    }
4545
                    break;
4546
                case 33: /* VTRN */
4547
                    if (size == 2) {
4548
                        for (n = 0; n < (q ? 4 : 2); n += 2) {
4549
                            NEON_GET_REG(T0, rm, n);
4550
                            NEON_GET_REG(T1, rd, n + 1);
4551
                            NEON_SET_REG(T1, rm, n);
4552
                            NEON_SET_REG(T0, rd, n + 1);
4553
                        }
4554
                    } else {
4555
                        goto elementwise;
4556
                    }
4557
                    break;
4558
                case 34: /* VUZP */
4559
                    /* Reg  Before       After
4560
                       Rd   A3 A2 A1 A0  B2 B0 A2 A0
4561
                       Rm   B3 B2 B1 B0  B3 B1 A3 A1
4562
                     */
4563
                    if (size == 3)
4564
                        return 1;
4565
                    gen_neon_unzip(rd, q, 0, size);
4566
                    gen_neon_unzip(rm, q, 4, size);
4567
                    if (q) {
4568
                        static int unzip_order_q[8] =
4569
                            {0, 2, 4, 6, 1, 3, 5, 7};
4570
                        for (n = 0; n < 8; n++) {
4571
                            int reg = (n < 4) ? rd : rm;
4572
                            gen_neon_movl_T0_scratch(unzip_order_q[n]);
4573
                            NEON_SET_REG(T0, reg, n % 4);
4574
                        }
4575
                    } else {
4576
                        static int unzip_order[4] =
4577
                            {0, 4, 1, 5};
4578
                        for (n = 0; n < 4; n++) {
4579
                            int reg = (n < 2) ? rd : rm;
4580
                            gen_neon_movl_T0_scratch(unzip_order[n]);
4581
                            NEON_SET_REG(T0, reg, n % 2);
4582
                        }
4583
                    }
4584
                    break;
4585
                case 35: /* VZIP */
4586
                    /* Reg  Before       After
4587
                       Rd   A3 A2 A1 A0  B1 A1 B0 A0
4588
                       Rm   B3 B2 B1 B0  B3 A3 B2 A2
4589
                     */
4590
                    if (size == 3)
4591
                        return 1;
4592
                    count = (q ? 4 : 2);
4593
                    for (n = 0; n < count; n++) {
4594
                        NEON_GET_REG(T0, rd, n);
4595
                        NEON_GET_REG(T1, rd, n);
4596
                        switch (size) {
4597
                        case 0: gen_op_neon_zip_u8(); break;
4598
                        case 1: gen_op_neon_zip_u16(); break;
4599
                        case 2: /* no-op */; break;
4600
                        default: abort();
4601
                        }
4602
                        gen_neon_movl_scratch_T0(n * 2);
4603
                        gen_neon_movl_scratch_T1(n * 2 + 1);
4604
                    }
4605
                    for (n = 0; n < count * 2; n++) {
4606
                        int reg = (n < count) ? rd : rm;
4607
                        gen_neon_movl_T0_scratch(n);
4608
                        NEON_SET_REG(T0, reg, n % count);
4609
                    }
4610
                    break;
4611
                case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
4612
                    for (pass = 0; pass < 2; pass++) {
4613
                        if (rd == rm + 1) {
4614
                            n = 1 - pass;
4615
                        } else {
4616
                            n = pass;
4617
                        }
4618
                        NEON_GET_REG(T0, rm, n * 2);
4619
                        NEON_GET_REG(T1, rm, n * 2 + 1);
4620
                        if (op == 36 && q == 0) {
4621
                            switch (size) {
4622
                            case 0: gen_op_neon_narrow_u8(); break;
4623
                            case 1: gen_op_neon_narrow_u16(); break;
4624
                            case 2: /* no-op */ break;
4625
                            default: return 1;
4626
                            }
4627
                        } else if (q) {
4628
                            switch (size) {
4629
                            case 0: gen_op_neon_narrow_sat_u8(); break;
4630
                            case 1: gen_op_neon_narrow_sat_u16(); break;
4631
                            case 2: gen_op_neon_narrow_sat_u32(); break;
4632
                            default: return 1;
4633
                            }
4634
                        } else {
4635
                            switch (size) {
4636
                            case 0: gen_op_neon_narrow_sat_s8(); break;
4637
                            case 1: gen_op_neon_narrow_sat_s16(); break;
4638
                            case 2: gen_op_neon_narrow_sat_s32(); break;
4639
                            default: return 1;
4640
                            }
4641
                        }
4642
                        NEON_SET_REG(T0, rd, n);
4643
                    }
4644
                    break;
4645
                case 38: /* VSHLL */
4646
                    if (q)
4647
                        return 1;
4648
                    if (rm == rd) {
4649
                        NEON_GET_REG(T2, rm, 1);
4650
                    }
4651
                    for (pass = 0; pass < 2; pass++) {
4652
                        if (pass == 1 && rm == rd) {
4653
                            gen_op_movl_T0_T2();
4654
                        } else {
4655
                            NEON_GET_REG(T0, rm, pass);
4656
                        }
4657
                        switch (size) {
4658
                        case 0: gen_op_neon_widen_high_u8(); break;
4659
                        case 1: gen_op_neon_widen_high_u16(); break;
4660
                        case 2:
4661
                            gen_op_movl_T1_T0();
4662
                            gen_op_movl_T0_im(0);
4663
                            break;
4664
                        default: return 1;
4665
                        }
4666
                        NEON_SET_REG(T0, rd, pass * 2);
4667
                        NEON_SET_REG(T1, rd, pass * 2 + 1);
4668
                    }
4669
                    break;
4670
                default:
4671
                elementwise:
4672
                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
4673
                        if (op == 30 || op == 31 || op >= 58) {
4674
                            gen_op_vfp_getreg_F0s(neon_reg_offset(rm, pass));
4675
                        } else {
4676
                            NEON_GET_REG(T0, rm, pass);
4677
                        }
4678
                        switch (op) {
4679
                        case 1: /* VREV32 */
4680
                            switch (size) {
4681
                            case 0: gen_op_rev_T0(); break;
4682
                            case 1: gen_swap_half(cpu_T[0]); break;
4683
                            default: return 1;
4684
                            }
4685
                            break;
4686
                        case 2: /* VREV16 */
4687
                            if (size != 0)
4688
                                return 1;
4689
                            gen_rev16(cpu_T[0]);
4690
                            break;
4691
                        case 4: case 5: /* VPADDL */
4692
                        case 12: case 13: /* VPADAL */
4693
                            switch ((size << 1) | (op & 1)) {
4694
                            case 0: gen_op_neon_paddl_s8(); break;
4695
                            case 1: gen_op_neon_paddl_u8(); break;
4696
                            case 2: gen_op_neon_paddl_s16(); break;
4697
                            case 3: gen_op_neon_paddl_u16(); break;
4698
                            default: abort();
4699
                            }
4700
                            if (op >= 12) {
4701
                                /* Accumulate */
4702
                                NEON_GET_REG(T1, rd, pass);
4703
                                switch (size) {
4704
                                case 0: gen_op_neon_add_u16(); break;
4705
                                case 1: gen_op_addl_T0_T1(); break;
4706
                                default: abort();
4707
                                }
4708
                            }
4709
                            break;
4710
                        case 8: /* CLS */
4711
                            switch (size) {
4712
                            case 0: gen_op_neon_cls_s8(); break;
4713
                            case 1: gen_op_neon_cls_s16(); break;
4714
                            case 2: gen_op_neon_cls_s32(); break;
4715
                            default: return 1;
4716
                            }
4717
                            break;
4718
                        case 9: /* CLZ */
4719
                            switch (size) {
4720
                            case 0: gen_op_neon_clz_u8(); break;
4721
                            case 1: gen_op_neon_clz_u16(); break;
4722
                            case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
4723
                            default: return 1;
4724
                            }
4725
                            break;
4726
                        case 10: /* CNT */
4727
                            if (size != 0)
4728
                                return 1;
4729
                            gen_op_neon_cnt_u8();
4730
                            break;
4731
                        case 11: /* VNOT */
4732
                            if (size != 0)
4733
                                return 1;
4734
                            gen_op_notl_T0();
4735
                            break;
4736
                        case 14: /* VQABS */
4737
                            switch (size) {
4738
                            case 0: gen_op_neon_qabs_s8(); break;
4739
                            case 1: gen_op_neon_qabs_s16(); break;
4740
                            case 2: gen_op_neon_qabs_s32(); break;
4741
                            default: return 1;
4742
                            }
4743
                            break;
4744
                        case 15: /* VQNEG */
4745
                            switch (size) {
4746
                            case 0: gen_op_neon_qneg_s8(); break;
4747
                            case 1: gen_op_neon_qneg_s16(); break;
4748
                            case 2: gen_op_neon_qneg_s32(); break;
4749
                            default: return 1;
4750
                            }
4751
                            break;
4752
                        case 16: case 19: /* VCGT #0, VCLE #0 */
4753
                            gen_op_movl_T1_im(0);
4754
                            switch(size) {
4755
                            case 0: gen_op_neon_cgt_s8(); break;
4756
                            case 1: gen_op_neon_cgt_s16(); break;
4757
                            case 2: gen_op_neon_cgt_s32(); break;
4758
                            default: return 1;
4759
                            }
4760
                            if (op == 19)
4761
                                gen_op_notl_T0();
4762
                            break;
4763
                        case 17: case 20: /* VCGE #0, VCLT #0 */
4764
                            gen_op_movl_T1_im(0);
4765
                            switch(size) {
4766
                            case 0: gen_op_neon_cge_s8(); break;
4767
                            case 1: gen_op_neon_cge_s16(); break;
4768
                            case 2: gen_op_neon_cge_s32(); break;
4769
                            default: return 1;
4770
                            }
4771
                            if (op == 20)
4772
                                gen_op_notl_T0();
4773
                            break;
4774
                        case 18: /* VCEQ #0 */
4775
                            gen_op_movl_T1_im(0);
4776
                            switch(size) {
4777
                            case 0: gen_op_neon_ceq_u8(); break;
4778
                            case 1: gen_op_neon_ceq_u16(); break;
4779
                            case 2: gen_op_neon_ceq_u32(); break;
4780
                            default: return 1;
4781
                            }
4782
                            break;
4783
                        case 22: /* VABS */
4784
                            switch(size) {
4785
                            case 0: gen_op_neon_abs_s8(); break;
4786
                            case 1: gen_op_neon_abs_s16(); break;
4787
                            case 2: gen_op_neon_abs_s32(); break;
4788
                            default: return 1;
4789
                            }
4790
                            break;
4791
                        case 23: /* VNEG */
4792
                            gen_op_movl_T1_im(0);
4793
                            switch(size) {
4794
                            case 0: gen_op_neon_rsb_u8(); break;
4795
                            case 1: gen_op_neon_rsb_u16(); break;
4796
                            case 2: gen_op_rsbl_T0_T1(); break;
4797
                            default: return 1;
4798
                            }
4799
                            break;
4800
                        case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
4801
                            gen_op_movl_T1_im(0);
4802
                            gen_op_neon_cgt_f32();
4803
                            if (op == 27)
4804
                                gen_op_notl_T0();
4805
                            break;
4806
                        case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
4807
                            gen_op_movl_T1_im(0);
4808
                            gen_op_neon_cge_f32();
4809
                            if (op == 28)
4810
                                gen_op_notl_T0();
4811
                            break;
4812
                        case 26: /* Float VCEQ #0 */
4813
                            gen_op_movl_T1_im(0);
4814
                            gen_op_neon_ceq_f32();
4815
                            break;
4816
                        case 30: /* Float VABS */
4817
                            gen_op_vfp_abss();
4818
                            break;
4819
                        case 31: /* Float VNEG */
4820
                            gen_op_vfp_negs();
4821
                            break;
4822
                        case 32: /* VSWP */
4823
                            NEON_GET_REG(T1, rd, pass);
4824
                            NEON_SET_REG(T1, rm, pass);
4825
                            break;
4826
                        case 33: /* VTRN */
4827
                            NEON_GET_REG(T1, rd, pass);
4828
                            switch (size) {
4829
                            case 0: gen_op_neon_trn_u8(); break;
4830
                            case 1: gen_op_neon_trn_u16(); break;
4831
                            case 2: abort();
4832
                            default: return 1;
4833
                            }
4834
                            NEON_SET_REG(T1, rm, pass);
4835
                            break;
4836
                        case 56: /* Integer VRECPE */
4837
                            gen_op_neon_recpe_u32();
4838
                            break;
4839
                        case 57: /* Integer VRSQRTE */
4840
                            gen_op_neon_rsqrte_u32();
4841
                            break;
4842
                        case 58: /* Float VRECPE */
4843
                            gen_op_neon_recpe_f32();
4844
                            break;
4845
                        case 59: /* Float VRSQRTE */
4846
                            gen_op_neon_rsqrte_f32();
4847
                            break;
4848
                        case 60: /* VCVT.F32.S32 */
4849
                            gen_op_vfp_tosizs();
4850
                            break;
4851
                        case 61: /* VCVT.F32.U32 */
4852
                            gen_op_vfp_touizs();
4853
                            break;
4854
                        case 62: /* VCVT.S32.F32 */
4855
                            gen_op_vfp_sitos();
4856
                            break;
4857
                        case 63: /* VCVT.U32.F32 */
4858
                            gen_op_vfp_uitos();
4859
                            break;
4860
                        default:
4861
                            /* Reserved: 21, 29, 39-56 */
4862
                            return 1;
4863
                        }
4864
                        if (op == 30 || op == 31 || op >= 58) {
4865
                            gen_op_vfp_setreg_F0s(neon_reg_offset(rm, pass));
4866
                        } else {
4867
                            NEON_SET_REG(T0, rd, pass);
4868
                        }
4869
                    }
4870
                    break;
4871
                }
4872
            } else if ((insn & (1 << 10)) == 0) {
4873
                /* VTBL, VTBX.  */
4874
                n = (insn >> 5) & 0x18;
4875
                NEON_GET_REG(T1, rm, 0);
4876
                if (insn & (1 << 6)) {
4877
                    NEON_GET_REG(T0, rd, 0);
4878
                } else {
4879
                    gen_op_movl_T0_im(0);
4880
                }
4881
                gen_op_neon_tbl(rn, n);
4882
                gen_op_movl_T2_T0();
4883
                NEON_GET_REG(T1, rm, 1);
4884
                if (insn & (1 << 6)) {
4885
                    NEON_GET_REG(T0, rd, 0);
4886
                } else {
4887
                    gen_op_movl_T0_im(0);
4888
                }
4889
                gen_op_neon_tbl(rn, n);
4890
                NEON_SET_REG(T2, rd, 0);
4891
                NEON_SET_REG(T0, rd, 1);
4892
            } else if ((insn & 0x380) == 0) {
4893
                /* VDUP */
4894
                if (insn & (1 << 19)) {
4895
                    NEON_SET_REG(T0, rm, 1);
4896
                } else {
4897
                    NEON_SET_REG(T0, rm, 0);
4898
                }
4899
                if (insn & (1 << 16)) {
4900
                    gen_op_neon_dup_u8(((insn >> 17) & 3) * 8);
4901
                } else if (insn & (1 << 17)) {
4902
                    if ((insn >> 18) & 1)
4903
                        gen_op_neon_dup_high16();
4904
                    else
4905
                        gen_op_neon_dup_low16();
4906
                }
4907
                for (pass = 0; pass < (q ? 4 : 2); pass++) {
4908
                    NEON_SET_REG(T0, rd, pass);
4909
                }
4910
            } else {
4911
                return 1;
4912
            }
4913
        }
4914
    }
4915
    return 0;
4916
}
4917

    
4918
static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
4919
{
4920
    int cpnum;
4921

    
4922
    cpnum = (insn >> 8) & 0xf;
4923
    if (arm_feature(env, ARM_FEATURE_XSCALE)
4924
            && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
4925
        return 1;
4926

    
4927
    switch (cpnum) {
4928
      case 0:
4929
      case 1:
4930
        if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
4931
            return disas_iwmmxt_insn(env, s, insn);
4932
        } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
4933
            return disas_dsp_insn(env, s, insn);
4934
        }
4935
        return 1;
4936
    case 10:
4937
    case 11:
4938
        return disas_vfp_insn (env, s, insn);
4939
    case 15:
4940
        return disas_cp15_insn (env, s, insn);
4941
    default:
4942
        /* Unknown coprocessor.  See if the board has hooked it.  */
4943
        return disas_cp_insn (env, s, insn);
4944
    }
4945
}
4946

    
4947
static void disas_arm_insn(CPUState * env, DisasContext *s)
4948
{
4949
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
4950
    TCGv tmp;
4951
    TCGv tmp2;
4952
    TCGv tmp3;
4953

    
4954
    insn = ldl_code(s->pc);
4955
    s->pc += 4;
4956

    
4957
    /* M variants do not implement ARM mode.  */
4958
    if (IS_M(env))
4959
        goto illegal_op;
4960
    cond = insn >> 28;
4961
    if (cond == 0xf){
4962
        /* Unconditional instructions.  */
4963
        if (((insn >> 25) & 7) == 1) {
4964
            /* NEON Data processing.  */
4965
            if (!arm_feature(env, ARM_FEATURE_NEON))
4966
                goto illegal_op;
4967

    
4968
            if (disas_neon_data_insn(env, s, insn))
4969
                goto illegal_op;
4970
            return;
4971
        }
4972
        if ((insn & 0x0f100000) == 0x04000000) {
4973
            /* NEON load/store.  */
4974
            if (!arm_feature(env, ARM_FEATURE_NEON))
4975
                goto illegal_op;
4976

    
4977
            if (disas_neon_ls_insn(env, s, insn))
4978
                goto illegal_op;
4979
            return;
4980
        }
4981
        if ((insn & 0x0d70f000) == 0x0550f000)
4982
            return; /* PLD */
4983
        else if ((insn & 0x0ffffdff) == 0x01010000) {
4984
            ARCH(6);
4985
            /* setend */
4986
            if (insn & (1 << 9)) {
4987
                /* BE8 mode not implemented.  */
4988
                goto illegal_op;
4989
            }
4990
            return;
4991
        } else if ((insn & 0x0fffff00) == 0x057ff000) {
4992
            switch ((insn >> 4) & 0xf) {
4993
            case 1: /* clrex */
4994
                ARCH(6K);
4995
                gen_op_clrex();
4996
                return;
4997
            case 4: /* dsb */
4998
            case 5: /* dmb */
4999
            case 6: /* isb */
5000
                ARCH(7);
5001
                /* We don't emulate caches so these are a no-op.  */
5002
                return;
5003
            default:
5004
                goto illegal_op;
5005
            }
5006
        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5007
            /* srs */
5008
            uint32_t offset;
5009
            if (IS_USER(s))
5010
                goto illegal_op;
5011
            ARCH(6);
5012
            op1 = (insn & 0x1f);
5013
            if (op1 == (env->uncached_cpsr & CPSR_M)) {
5014
                gen_movl_T1_reg(s, 13);
5015
            } else {
5016
                gen_op_movl_T1_r13_banked(op1);
5017
            }
5018
            i = (insn >> 23) & 3;
5019
            switch (i) {
5020
            case 0: offset = -4; break; /* DA */
5021
            case 1: offset = -8; break; /* DB */
5022
            case 2: offset = 0; break; /* IA */
5023
            case 3: offset = 4; break; /* IB */
5024
            default: abort();
5025
            }
5026
            if (offset)
5027
                gen_op_addl_T1_im(offset);
5028
            gen_movl_T0_reg(s, 14);
5029
            gen_ldst(stl, s);
5030
            gen_op_movl_T0_cpsr();
5031
            gen_op_addl_T1_im(4);
5032
            gen_ldst(stl, s);
5033
            if (insn & (1 << 21)) {
5034
                /* Base writeback.  */
5035
                switch (i) {
5036
                case 0: offset = -8; break;
5037
                case 1: offset = -4; break;
5038
                case 2: offset = 4; break;
5039
                case 3: offset = 0; break;
5040
                default: abort();
5041
                }
5042
                if (offset)
5043
                    gen_op_addl_T1_im(offset);
5044
                if (op1 == (env->uncached_cpsr & CPSR_M)) {
5045
                    gen_movl_reg_T1(s, 13);
5046
                } else {
5047
                    gen_op_movl_r13_T1_banked(op1);
5048
                }
5049
            }
5050
        } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5051
            /* rfe */
5052
            uint32_t offset;
5053
            if (IS_USER(s))
5054
                goto illegal_op;
5055
            ARCH(6);
5056
            rn = (insn >> 16) & 0xf;
5057
            gen_movl_T1_reg(s, rn);
5058
            i = (insn >> 23) & 3;
5059
            switch (i) {
5060
            case 0: offset = 0; break; /* DA */
5061
            case 1: offset = -4; break; /* DB */
5062
            case 2: offset = 4; break; /* IA */
5063
            case 3: offset = 8; break; /* IB */
5064
            default: abort();
5065
            }
5066
            if (offset)
5067
                gen_op_addl_T1_im(offset);
5068
            /* Load CPSR into T2 and PC into T0.  */
5069
            gen_ldst(ldl, s);
5070
            gen_op_movl_T2_T0();
5071
            gen_op_addl_T1_im(-4);
5072
            gen_ldst(ldl, s);
5073
            if (insn & (1 << 21)) {
5074
                /* Base writeback.  */
5075
                switch (i) {
5076
                case 0: offset = -4; break;
5077
                case 1: offset = 0; break;
5078
                case 2: offset = 8; break;
5079
                case 3: offset = 4; break;
5080
                default: abort();
5081
                }
5082
                if (offset)
5083
                    gen_op_addl_T1_im(offset);
5084
                gen_movl_reg_T1(s, rn);
5085
            }
5086
            gen_rfe(s);
5087
        } else if ((insn & 0x0e000000) == 0x0a000000) {
5088
            /* branch link and change to thumb (blx <offset>) */
5089
            int32_t offset;
5090

    
5091
            val = (uint32_t)s->pc;
5092
            gen_op_movl_T0_im(val);
5093
            gen_movl_reg_T0(s, 14);
5094
            /* Sign-extend the 24-bit offset */
5095
            offset = (((int32_t)insn) << 8) >> 8;
5096
            /* offset * 4 + bit24 * 2 + (thumb bit) */
5097
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
5098
            /* pipeline offset */
5099
            val += 4;
5100
            gen_op_movl_T0_im(val);
5101
            gen_bx(s);
5102
            return;
5103
        } else if ((insn & 0x0e000f00) == 0x0c000100) {
5104
            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5105
                /* iWMMXt register transfer.  */
5106
                if (env->cp15.c15_cpar & (1 << 1))
5107
                    if (!disas_iwmmxt_insn(env, s, insn))
5108
                        return;
5109
            }
5110
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
5111
            /* Coprocessor double register transfer.  */
5112
        } else if ((insn & 0x0f000010) == 0x0e000010) {
5113
            /* Additional coprocessor register transfer.  */
5114
        } else if ((insn & 0x0ff10010) == 0x01000000) {
5115
            uint32_t mask;
5116
            uint32_t val;
5117
            /* cps (privileged) */
5118
            if (IS_USER(s))
5119
                return;
5120
            mask = val = 0;
5121
            if (insn & (1 << 19)) {
5122
                if (insn & (1 << 8))
5123
                    mask |= CPSR_A;
5124
                if (insn & (1 << 7))
5125
                    mask |= CPSR_I;
5126
                if (insn & (1 << 6))
5127
                    mask |= CPSR_F;
5128
                if (insn & (1 << 18))
5129
                    val |= mask;
5130
            }
5131
            if (insn & (1 << 14)) {
5132
                mask |= CPSR_M;
5133
                val |= (insn & 0x1f);
5134
            }
5135
            if (mask) {
5136
                gen_op_movl_T0_im(val);
5137
                gen_set_psr_T0(s, mask, 0);
5138
            }
5139
            return;
5140
        }
5141
        goto illegal_op;
5142
    }
5143
    if (cond != 0xe) {
5144
        /* if not always execute, we generate a conditional jump to
5145
           next instruction */
5146
        s->condlabel = gen_new_label();
5147
        gen_test_cc[cond ^ 1](s->condlabel);
5148
        s->condjmp = 1;
5149
    }
5150
    if ((insn & 0x0f900000) == 0x03000000) {
5151
        if ((insn & (1 << 21)) == 0) {
5152
            ARCH(6T2);
5153
            rd = (insn >> 12) & 0xf;
5154
            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5155
            if ((insn & (1 << 22)) == 0) {
5156
                /* MOVW */
5157
                gen_op_movl_T0_im(val);
5158
            } else {
5159
                /* MOVT */
5160
                gen_movl_T0_reg(s, rd);
5161
                gen_op_movl_T1_im(0xffff);
5162
                gen_op_andl_T0_T1();
5163
                gen_op_movl_T1_im(val << 16);
5164
                gen_op_orl_T0_T1();
5165
            }
5166
            gen_movl_reg_T0(s, rd);
5167
        } else {
5168
            if (((insn >> 12) & 0xf) != 0xf)
5169
                goto illegal_op;
5170
            if (((insn >> 16) & 0xf) == 0) {
5171
                gen_nop_hint(s, insn & 0xff);
5172
            } else {
5173
                /* CPSR = immediate */
5174
                val = insn & 0xff;
5175
                shift = ((insn >> 8) & 0xf) * 2;
5176
                if (shift)
5177
                    val = (val >> shift) | (val << (32 - shift));
5178
                gen_op_movl_T0_im(val);
5179
                i = ((insn & (1 << 22)) != 0);
5180
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5181
                    goto illegal_op;
5182
            }
5183
        }
5184
    } else if ((insn & 0x0f900000) == 0x01000000
5185
               && (insn & 0x00000090) != 0x00000090) {
5186
        /* miscellaneous instructions */
5187
        op1 = (insn >> 21) & 3;
5188
        sh = (insn >> 4) & 0xf;
5189
        rm = insn & 0xf;
5190
        switch (sh) {
5191
        case 0x0: /* move program status register */
5192
            if (op1 & 1) {
5193
                /* PSR = reg */
5194
                gen_movl_T0_reg(s, rm);
5195
                i = ((op1 & 2) != 0);
5196
                if (gen_set_psr_T0(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i))
5197
                    goto illegal_op;
5198
            } else {
5199
                /* reg = PSR */
5200
                rd = (insn >> 12) & 0xf;
5201
                if (op1 & 2) {
5202
                    if (IS_USER(s))
5203
                        goto illegal_op;
5204
                    gen_op_movl_T0_spsr();
5205
                } else {
5206
                    gen_op_movl_T0_cpsr();
5207
                }
5208
                gen_movl_reg_T0(s, rd);
5209
            }
5210
            break;
5211
        case 0x1:
5212
            if (op1 == 1) {
5213
                /* branch/exchange thumb (bx).  */
5214
                gen_movl_T0_reg(s, rm);
5215
                gen_bx(s);
5216
            } else if (op1 == 3) {
5217
                /* clz */
5218
                rd = (insn >> 12) & 0xf;
5219
                tmp = load_reg(s, rm);
5220
                gen_helper_clz(tmp, tmp);
5221
                store_reg(s, rd, tmp);
5222
            } else {
5223
                goto illegal_op;
5224
            }
5225
            break;
5226
        case 0x2:
5227
            if (op1 == 1) {
5228
                ARCH(5J); /* bxj */
5229
                /* Trivial implementation equivalent to bx.  */
5230
                gen_movl_T0_reg(s, rm);
5231
                gen_bx(s);
5232
            } else {
5233
                goto illegal_op;
5234
            }
5235
            break;
5236
        case 0x3:
5237
            if (op1 != 1)
5238
              goto illegal_op;
5239

    
5240
            /* branch link/exchange thumb (blx) */
5241
            val = (uint32_t)s->pc;
5242
            gen_op_movl_T1_im(val);
5243
            gen_movl_T0_reg(s, rm);
5244
            gen_movl_reg_T1(s, 14);
5245
            gen_bx(s);
5246
            break;
5247
        case 0x5: /* saturating add/subtract */
5248
            rd = (insn >> 12) & 0xf;
5249
            rn = (insn >> 16) & 0xf;
5250
            gen_movl_T0_reg(s, rm);
5251
            gen_movl_T1_reg(s, rn);
5252
            if (op1 & 2)
5253
                gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
5254
            if (op1 & 1)
5255
                gen_op_subl_T0_T1_saturate();
5256
            else
5257
                gen_op_addl_T0_T1_saturate();
5258
            gen_movl_reg_T0(s, rd);
5259
            break;
5260
        case 7: /* bkpt */
5261
            gen_set_condexec(s);
5262
            gen_op_movl_T0_im((long)s->pc - 4);
5263
            gen_set_pc_T0();
5264
            gen_op_bkpt();
5265
            s->is_jmp = DISAS_JUMP;
5266
            break;
5267
        case 0x8: /* signed multiply */
5268
        case 0xa:
5269
        case 0xc:
5270
        case 0xe:
5271
            rs = (insn >> 8) & 0xf;
5272
            rn = (insn >> 12) & 0xf;
5273
            rd = (insn >> 16) & 0xf;
5274
            if (op1 == 1) {
5275
                /* (32 * 16) >> 16 */
5276
                gen_movl_T0_reg(s, rm);
5277
                gen_movl_T1_reg(s, rs);
5278
                if (sh & 4)
5279
                    gen_op_sarl_T1_im(16);
5280
                else
5281
                    gen_sxth(cpu_T[1]);
5282
                gen_op_imulw_T0_T1();
5283
                if ((sh & 2) == 0) {
5284
                    gen_movl_T1_reg(s, rn);
5285
                    gen_op_addl_T0_T1_setq();
5286
                }
5287
                gen_movl_reg_T0(s, rd);
5288
            } else {
5289
                /* 16 * 16 */
5290
                gen_movl_T0_reg(s, rm);
5291
                gen_movl_T1_reg(s, rs);
5292
                gen_mulxy(sh & 2, sh & 4);
5293
                if (op1 == 2) {
5294
                    gen_op_signbit_T1_T0();
5295
                    gen_op_addq_T0_T1(rn, rd);
5296
                    gen_movl_reg_T0(s, rn);
5297
                    gen_movl_reg_T1(s, rd);
5298
                } else {
5299
                    if (op1 == 0) {
5300
                        gen_movl_T1_reg(s, rn);
5301
                        gen_op_addl_T0_T1_setq();
5302
                    }
5303
                    gen_movl_reg_T0(s, rd);
5304
                }
5305
            }
5306
            break;
5307
        default:
5308
            goto illegal_op;
5309
        }
5310
    } else if (((insn & 0x0e000000) == 0 &&
5311
                (insn & 0x00000090) != 0x90) ||
5312
               ((insn & 0x0e000000) == (1 << 25))) {
5313
        int set_cc, logic_cc, shiftop;
5314

    
5315
        op1 = (insn >> 21) & 0xf;
5316
        set_cc = (insn >> 20) & 1;
5317
        logic_cc = table_logic_cc[op1] & set_cc;
5318

    
5319
        /* data processing instruction */
5320
        if (insn & (1 << 25)) {
5321
            /* immediate operand */
5322
            val = insn & 0xff;
5323
            shift = ((insn >> 8) & 0xf) * 2;
5324
            if (shift)
5325
                val = (val >> shift) | (val << (32 - shift));
5326
            gen_op_movl_T1_im(val);
5327
            if (logic_cc && shift)
5328
                gen_set_CF_bit31(cpu_T[1]);
5329
        } else {
5330
            /* register */
5331
            rm = (insn) & 0xf;
5332
            gen_movl_T1_reg(s, rm);
5333
            shiftop = (insn >> 5) & 3;
5334
            if (!(insn & (1 << 4))) {
5335
                shift = (insn >> 7) & 0x1f;
5336
                gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
5337
            } else {
5338
                rs = (insn >> 8) & 0xf;
5339
                gen_movl_T0_reg(s, rs);
5340
                if (logic_cc) {
5341
                    gen_shift_T1_T0_cc[shiftop]();
5342
                } else {
5343
                    gen_shift_T1_T0[shiftop]();
5344
                }
5345
            }
5346
        }
5347
        if (op1 != 0x0f && op1 != 0x0d) {
5348
            rn = (insn >> 16) & 0xf;
5349
            gen_movl_T0_reg(s, rn);
5350
        }
5351
        rd = (insn >> 12) & 0xf;
5352
        switch(op1) {
5353
        case 0x00:
5354
            gen_op_andl_T0_T1();
5355
            gen_movl_reg_T0(s, rd);
5356
            if (logic_cc)
5357
                gen_op_logic_T0_cc();
5358
            break;
5359
        case 0x01:
5360
            gen_op_xorl_T0_T1();
5361
            gen_movl_reg_T0(s, rd);
5362
            if (logic_cc)
5363
                gen_op_logic_T0_cc();
5364
            break;
5365
        case 0x02:
5366
            if (set_cc && rd == 15) {
5367
                /* SUBS r15, ... is used for exception return.  */
5368
                if (IS_USER(s))
5369
                    goto illegal_op;
5370
                gen_op_subl_T0_T1_cc();
5371
                gen_exception_return(s);
5372
            } else {
5373
                if (set_cc)
5374
                    gen_op_subl_T0_T1_cc();
5375
                else
5376
                    gen_op_subl_T0_T1();
5377
                gen_movl_reg_T0(s, rd);
5378
            }
5379
            break;
5380
        case 0x03:
5381
            if (set_cc)
5382
                gen_op_rsbl_T0_T1_cc();
5383
            else
5384
                gen_op_rsbl_T0_T1();
5385
            gen_movl_reg_T0(s, rd);
5386
            break;
5387
        case 0x04:
5388
            if (set_cc)
5389
                gen_op_addl_T0_T1_cc();
5390
            else
5391
                gen_op_addl_T0_T1();
5392
            gen_movl_reg_T0(s, rd);
5393
            break;
5394
        case 0x05:
5395
            if (set_cc)
5396
                gen_op_adcl_T0_T1_cc();
5397
            else
5398
                gen_adc_T0_T1();
5399
            gen_movl_reg_T0(s, rd);
5400
            break;
5401
        case 0x06:
5402
            if (set_cc)
5403
                gen_op_sbcl_T0_T1_cc();
5404
            else
5405
                gen_sbc_T0_T1();
5406
            gen_movl_reg_T0(s, rd);
5407
            break;
5408
        case 0x07:
5409
            if (set_cc)
5410
                gen_op_rscl_T0_T1_cc();
5411
            else
5412
                gen_rsc_T0_T1();
5413
            gen_movl_reg_T0(s, rd);
5414
            break;
5415
        case 0x08:
5416
            if (set_cc) {
5417
                gen_op_andl_T0_T1();
5418
                gen_op_logic_T0_cc();
5419
            }
5420
            break;
5421
        case 0x09:
5422
            if (set_cc) {
5423
                gen_op_xorl_T0_T1();
5424
                gen_op_logic_T0_cc();
5425
            }
5426
            break;
5427
        case 0x0a:
5428
            if (set_cc) {
5429
                gen_op_subl_T0_T1_cc();
5430
            }
5431
            break;
5432
        case 0x0b:
5433
            if (set_cc) {
5434
                gen_op_addl_T0_T1_cc();
5435
            }
5436
            break;
5437
        case 0x0c:
5438
            gen_op_orl_T0_T1();
5439
            gen_movl_reg_T0(s, rd);
5440
            if (logic_cc)
5441
                gen_op_logic_T0_cc();
5442
            break;
5443
        case 0x0d:
5444
            if (logic_cc && rd == 15) {
5445
                /* MOVS r15, ... is used for exception return.  */
5446
                if (IS_USER(s))
5447
                    goto illegal_op;
5448
                gen_op_movl_T0_T1();
5449
                gen_exception_return(s);
5450
            } else {
5451
                gen_movl_reg_T1(s, rd);
5452
                if (logic_cc)
5453
                    gen_op_logic_T1_cc();
5454
            }
5455
            break;
5456
        case 0x0e:
5457
            gen_op_bicl_T0_T1();
5458
            gen_movl_reg_T0(s, rd);
5459
            if (logic_cc)
5460
                gen_op_logic_T0_cc();
5461
            break;
5462
        default:
5463
        case 0x0f:
5464
            gen_op_notl_T1();
5465
            gen_movl_reg_T1(s, rd);
5466
            if (logic_cc)
5467
                gen_op_logic_T1_cc();
5468
            break;
5469
        }
5470
    } else {
5471
        /* other instructions */
5472
        op1 = (insn >> 24) & 0xf;
5473
        switch(op1) {
5474
        case 0x0:
5475
        case 0x1:
5476
            /* multiplies, extra load/stores */
5477
            sh = (insn >> 5) & 3;
5478
            if (sh == 0) {
5479
                if (op1 == 0x0) {
5480
                    rd = (insn >> 16) & 0xf;
5481
                    rn = (insn >> 12) & 0xf;
5482
                    rs = (insn >> 8) & 0xf;
5483
                    rm = (insn) & 0xf;
5484
                    op1 = (insn >> 20) & 0xf;
5485
                    switch (op1) {
5486
                    case 0: case 1: case 2: case 3: case 6:
5487
                        /* 32 bit mul */
5488
                        gen_movl_T0_reg(s, rs);
5489
                        gen_movl_T1_reg(s, rm);
5490
                        gen_op_mul_T0_T1();
5491
                        if (insn & (1 << 22)) {
5492
                            /* Subtract (mls) */
5493
                            ARCH(6T2);
5494
                            gen_movl_T1_reg(s, rn);
5495
                            gen_op_rsbl_T0_T1();
5496
                        } else if (insn & (1 << 21)) {
5497
                            /* Add */
5498
                            gen_movl_T1_reg(s, rn);
5499
                            gen_op_addl_T0_T1();
5500
                        }
5501
                        if (insn & (1 << 20))
5502
                            gen_op_logic_T0_cc();
5503
                        gen_movl_reg_T0(s, rd);
5504
                        break;
5505
                    default:
5506
                        /* 64 bit mul */
5507
                        gen_movl_T0_reg(s, rs);
5508
                        gen_movl_T1_reg(s, rm);
5509
                        if (insn & (1 << 22))
5510
                            gen_op_imull_T0_T1();
5511
                        else
5512
                            gen_op_mull_T0_T1();
5513
                        if (insn & (1 << 21)) /* mult accumulate */
5514
                            gen_op_addq_T0_T1(rn, rd);
5515
                        if (!(insn & (1 << 23))) { /* double accumulate */
5516
                            ARCH(6);
5517
                            gen_op_addq_lo_T0_T1(rn);
5518
                            gen_op_addq_lo_T0_T1(rd);
5519
                        }
5520
                        if (insn & (1 << 20))
5521
                            gen_op_logicq_cc();
5522
                        gen_movl_reg_T0(s, rn);
5523
                        gen_movl_reg_T1(s, rd);
5524
                        break;
5525
                    }
5526
                } else {
5527
                    rn = (insn >> 16) & 0xf;
5528
                    rd = (insn >> 12) & 0xf;
5529
                    if (insn & (1 << 23)) {
5530
                        /* load/store exclusive */
5531
                        gen_movl_T1_reg(s, rn);
5532
                        if (insn & (1 << 20)) {
5533
                            gen_ldst(ldlex, s);
5534
                        } else {
5535
                            rm = insn & 0xf;
5536
                            gen_movl_T0_reg(s, rm);
5537
                            gen_ldst(stlex, s);
5538
                        }
5539
                        gen_movl_reg_T0(s, rd);
5540
                    } else {
5541
                        /* SWP instruction */
5542
                        rm = (insn) & 0xf;
5543

    
5544
                        gen_movl_T0_reg(s, rm);
5545
                        gen_movl_T1_reg(s, rn);
5546
                        if (insn & (1 << 22)) {
5547
                            gen_ldst(swpb, s);
5548
                        } else {
5549
                            gen_ldst(swpl, s);
5550
                        }
5551
                        gen_movl_reg_T0(s, rd);
5552
                    }
5553
                }
5554
            } else {
5555
                int address_offset;
5556
                int load;
5557
                /* Misc load/store */
5558
                rn = (insn >> 16) & 0xf;
5559
                rd = (insn >> 12) & 0xf;
5560
                gen_movl_T1_reg(s, rn);
5561
                if (insn & (1 << 24))
5562
                    gen_add_datah_offset(s, insn, 0);
5563
                address_offset = 0;
5564
                if (insn & (1 << 20)) {
5565
                    /* load */
5566
                    switch(sh) {
5567
                    case 1:
5568
                        gen_ldst(lduw, s);
5569
                        break;
5570
                    case 2:
5571
                        gen_ldst(ldsb, s);
5572
                        break;
5573
                    default:
5574
                    case 3:
5575
                        gen_ldst(ldsw, s);
5576
                        break;
5577
                    }
5578
                    load = 1;
5579
                } else if (sh & 2) {
5580
                    /* doubleword */
5581
                    if (sh & 1) {
5582
                        /* store */
5583
                        gen_movl_T0_reg(s, rd);
5584
                        gen_ldst(stl, s);
5585
                        gen_op_addl_T1_im(4);
5586
                        gen_movl_T0_reg(s, rd + 1);
5587
                        gen_ldst(stl, s);
5588
                        load = 0;
5589
                    } else {
5590
                        /* load */
5591
                        gen_ldst(ldl, s);
5592
                        gen_movl_reg_T0(s, rd);
5593
                        gen_op_addl_T1_im(4);
5594
                        gen_ldst(ldl, s);
5595
                        rd++;
5596
                        load = 1;
5597
                    }
5598
                    address_offset = -4;
5599
                } else {
5600
                    /* store */
5601
                    gen_movl_T0_reg(s, rd);
5602
                    gen_ldst(stw, s);
5603
                    load = 0;
5604
                }
5605
                /* Perform base writeback before the loaded value to
5606
                   ensure correct behavior with overlapping index registers.
5607
                   ldrd with base writeback is is undefined if the
5608
                   destination and index registers overlap.  */
5609
                if (!(insn & (1 << 24))) {
5610
                    gen_add_datah_offset(s, insn, address_offset);
5611
                    gen_movl_reg_T1(s, rn);
5612
                } else if (insn & (1 << 21)) {
5613
                    if (address_offset)
5614
                        gen_op_addl_T1_im(address_offset);
5615
                    gen_movl_reg_T1(s, rn);
5616
                }
5617
                if (load) {
5618
                    /* Complete the load.  */
5619
                    gen_movl_reg_T0(s, rd);
5620
                }
5621
            }
5622
            break;
5623
        case 0x4:
5624
        case 0x5:
5625
            goto do_ldst;
5626
        case 0x6:
5627
        case 0x7:
5628
            if (insn & (1 << 4)) {
5629
                ARCH(6);
5630
                /* Armv6 Media instructions.  */
5631
                rm = insn & 0xf;
5632
                rn = (insn >> 16) & 0xf;
5633
                rd = (insn >> 12) & 0xf;
5634
                rs = (insn >> 8) & 0xf;
5635
                switch ((insn >> 23) & 3) {
5636
                case 0: /* Parallel add/subtract.  */
5637
                    op1 = (insn >> 20) & 7;
5638
                    tmp = load_reg(s, rn);
5639
                    tmp2 = load_reg(s, rm);
5640
                    sh = (insn >> 5) & 7;
5641
                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
5642
                        goto illegal_op;
5643
                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
5644
                    dead_tmp(tmp2);
5645
                    store_reg(s, rd, tmp);
5646
                    break;
5647
                case 1:
5648
                    if ((insn & 0x00700020) == 0) {
5649
                        /* Hafword pack.  */
5650
                        tmp = load_reg(s, rn);
5651
                        tmp2 = load_reg(s, rm);
5652
                        shift = (insn >> 7) & 0x1f;
5653
                        if (shift)
5654
                            tcg_gen_shli_i32(tmp2, tmp2, shift);
5655
                        if (insn & (1 << 6)) {
5656
                            /* pkhtb */
5657
                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
5658
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
5659
                        } else {
5660
                            /* pkhbt */
5661
                            tcg_gen_andi_i32(tmp, tmp, 0xffff);
5662
                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
5663
                        }
5664
                        tcg_gen_or_i32(tmp, tmp, tmp2);
5665
                        store_reg(s, rd, tmp);
5666
                    } else if ((insn & 0x00200020) == 0x00200000) {
5667
                        /* [us]sat */
5668
                        tmp = load_reg(s, rm);
5669
                        shift = (insn >> 7) & 0x1f;
5670
                        if (insn & (1 << 6)) {
5671
                            if (shift == 0)
5672
                                shift = 31;
5673
                            tcg_gen_sari_i32(tmp, tmp, shift);
5674
                        } else {
5675
                            tcg_gen_shli_i32(tmp, tmp, shift);
5676
                        }
5677
                        sh = (insn >> 16) & 0x1f;
5678
                        if (sh != 0) {
5679
                            if (insn & (1 << 22))
5680
                                gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
5681
                            else
5682
                                gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
5683
                        }
5684
                        store_reg(s, rd, tmp);
5685
                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
5686
                        /* [us]sat16 */
5687
                        tmp = load_reg(s, rm);
5688
                        sh = (insn >> 16) & 0x1f;
5689
                        if (sh != 0) {
5690
                            if (insn & (1 << 22))
5691
                                gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
5692
                            else
5693
                                gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
5694
                        }
5695
                        store_reg(s, rd, tmp);
5696
                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
5697
                        /* Select bytes.  */
5698
                        tmp = load_reg(s, rn);
5699
                        tmp2 = load_reg(s, rm);
5700
                        tmp3 = new_tmp();
5701
                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
5702
                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
5703
                        dead_tmp(tmp3);
5704
                        dead_tmp(tmp2);
5705
                        store_reg(s, rd, tmp);
5706
                    } else if ((insn & 0x000003e0) == 0x00000060) {
5707
                        gen_movl_T1_reg(s, rm);
5708
                        shift = (insn >> 10) & 3;
5709
                        /* ??? In many cases it's not neccessary to do a
5710
                           rotate, a shift is sufficient.  */
5711
                        if (shift != 0)
5712
                            gen_op_rorl_T1_im(shift * 8);
5713
                        op1 = (insn >> 20) & 7;
5714
                        switch (op1) {
5715
                        case 0: gen_sxtb16(cpu_T[1]); break;
5716
                        case 2: gen_sxtb(cpu_T[1]);   break;
5717
                        case 3: gen_sxth(cpu_T[1]);   break;
5718
                        case 4: gen_uxtb16(cpu_T[1]); break;
5719
                        case 6: gen_uxtb(cpu_T[1]);   break;
5720
                        case 7: gen_uxth(cpu_T[1]);   break;
5721
                        default: goto illegal_op;
5722
                        }
5723
                        if (rn != 15) {
5724
                            tmp = load_reg(s, rn);
5725
                            if ((op1 & 3) == 0) {
5726
                                gen_add16(cpu_T[1], tmp);
5727
                            } else {
5728
                                tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
5729
                                dead_tmp(tmp);
5730
                            }
5731
                        }
5732
                        gen_movl_reg_T1(s, rd);
5733
                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
5734
                        /* rev */
5735
                        gen_movl_T0_reg(s, rm);
5736
                        if (insn & (1 << 22)) {
5737
                            if (insn & (1 << 7)) {
5738
                                gen_revsh(cpu_T[0]);
5739
                            } else {
5740
                                ARCH(6T2);
5741
                                gen_helper_rbit(cpu_T[0], cpu_T[0]);
5742
                            }
5743
                        } else {
5744
                            if (insn & (1 << 7))
5745
                                gen_rev16(cpu_T[0]);
5746
                            else
5747
                                gen_op_rev_T0();
5748
                        }
5749
                        gen_movl_reg_T0(s, rd);
5750
                    } else {
5751
                        goto illegal_op;
5752
                    }
5753
                    break;
5754
                case 2: /* Multiplies (Type 3).  */
5755
                    gen_movl_T0_reg(s, rm);
5756
                    gen_movl_T1_reg(s, rs);
5757
                    if (insn & (1 << 20)) {
5758
                        /* Signed multiply most significant [accumulate].  */
5759
                        gen_op_imull_T0_T1();
5760
                        if (insn & (1 << 5))
5761
                            gen_op_roundqd_T0_T1();
5762
                        else
5763
                            gen_op_movl_T0_T1();
5764
                        if (rn != 15) {
5765
                            gen_movl_T1_reg(s, rn);
5766
                            if (insn & (1 << 6)) {
5767
                                gen_op_addl_T0_T1();
5768
                            } else {
5769
                                gen_op_rsbl_T0_T1();
5770
                            }
5771
                        }
5772
                        gen_movl_reg_T0(s, rd);
5773
                    } else {
5774
                        if (insn & (1 << 5))
5775
                            gen_swap_half(cpu_T[1]);
5776
                        gen_smul_dual(cpu_T[0], cpu_T[1]);
5777
                        if (insn & (1 << 22)) {
5778
                            if (insn & (1 << 6)) {
5779
                                /* smlald */
5780
                                gen_op_addq_T0_T1_dual(rn, rd);
5781
                            } else {
5782
                                /* smlsld */
5783
                                gen_op_subq_T0_T1_dual(rn, rd);
5784
                            }
5785
                        } else {
5786
                            /* This addition cannot overflow.  */
5787
                            if (insn & (1 << 6)) {
5788
                                /* sm[ul]sd */
5789
                                gen_op_subl_T0_T1();
5790
                            } else {
5791
                                /* sm[ul]ad */
5792
                                gen_op_addl_T0_T1();
5793
                            }
5794
                            if (rn != 15)
5795
                              {
5796
                                gen_movl_T1_reg(s, rn);
5797
                                gen_op_addl_T0_T1_setq();
5798
                              }
5799
                            gen_movl_reg_T0(s, rd);
5800
                        }
5801
                    }
5802
                    break;
5803
                case 3:
5804
                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
5805
                    switch (op1) {
5806
                    case 0: /* Unsigned sum of absolute differences.  */
5807
                        ARCH(6);
5808
                        tmp = load_reg(s, rm);
5809
                        tmp2 = load_reg(s, rs);
5810
                        gen_helper_usad8(tmp, tmp, tmp2);
5811
                        dead_tmp(tmp2);
5812
                        if (rn != 15) {
5813
                            tmp2 = load_reg(s, rn);
5814
                            tcg_gen_add_i32(tmp, tmp, tmp2);
5815
                            dead_tmp(tmp2);
5816
                        }
5817
                        store_reg(s, rd, tmp);
5818
                        break;
5819
                    case 0x20: case 0x24: case 0x28: case 0x2c:
5820
                        /* Bitfield insert/clear.  */
5821
                        ARCH(6T2);
5822
                        shift = (insn >> 7) & 0x1f;
5823
                        i = (insn >> 16) & 0x1f;
5824
                        i = i + 1 - shift;
5825
                        if (rm == 15) {
5826
                            gen_op_movl_T1_im(0);
5827
                        } else {
5828
                            gen_movl_T1_reg(s, rm);
5829
                        }
5830
                        if (i != 32) {
5831
                            gen_movl_T0_reg(s, rd);
5832
                            gen_bfi(cpu_T[1], cpu_T[0], cpu_T[1],
5833
                                    shift, ((1u << i) - 1) << shift);
5834
                        }
5835
                        gen_movl_reg_T1(s, rd);
5836
                        break;
5837
                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
5838
                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
5839
                        gen_movl_T1_reg(s, rm);
5840
                        shift = (insn >> 7) & 0x1f;
5841
                        i = ((insn >> 16) & 0x1f) + 1;
5842
                        if (shift + i > 32)
5843
                            goto illegal_op;
5844
                        if (i < 32) {
5845
                            if (op1 & 0x20) {
5846
                                gen_ubfx(cpu_T[1], shift, (1u << i) - 1);
5847
                            } else {
5848
                                gen_sbfx(cpu_T[1], shift, i);
5849
                            }
5850
                        }
5851
                        gen_movl_reg_T1(s, rd);
5852
                        break;
5853
                    default:
5854
                        goto illegal_op;
5855
                    }
5856
                    break;
5857
                }
5858
                break;
5859
            }
5860
        do_ldst:
5861
            /* Check for undefined extension instructions
5862
             * per the ARM Bible IE:
5863
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
5864
             */
5865
            sh = (0xf << 20) | (0xf << 4);
5866
            if (op1 == 0x7 && ((insn & sh) == sh))
5867
            {
5868
                goto illegal_op;
5869
            }
5870
            /* load/store byte/word */
5871
            rn = (insn >> 16) & 0xf;
5872
            rd = (insn >> 12) & 0xf;
5873
            gen_movl_T1_reg(s, rn);
5874
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
5875
            if (insn & (1 << 24))
5876
                gen_add_data_offset(s, insn);
5877
            if (insn & (1 << 20)) {
5878
                /* load */
5879
                s->is_mem = 1;
5880
#if defined(CONFIG_USER_ONLY)
5881
                if (insn & (1 << 22))
5882
                    gen_op_ldub_raw();
5883
                else
5884
                    gen_op_ldl_raw();
5885
#else
5886
                if (insn & (1 << 22)) {
5887
                    if (i)
5888
                        gen_op_ldub_user();
5889
                    else
5890
                        gen_op_ldub_kernel();
5891
                } else {
5892
                    if (i)
5893
                        gen_op_ldl_user();
5894
                    else
5895
                        gen_op_ldl_kernel();
5896
                }
5897
#endif
5898
            } else {
5899
                /* store */
5900
                gen_movl_T0_reg(s, rd);
5901
#if defined(CONFIG_USER_ONLY)
5902
                if (insn & (1 << 22))
5903
                    gen_op_stb_raw();
5904
                else
5905
                    gen_op_stl_raw();
5906
#else
5907
                if (insn & (1 << 22)) {
5908
                    if (i)
5909
                        gen_op_stb_user();
5910
                    else
5911
                        gen_op_stb_kernel();
5912
                } else {
5913
                    if (i)
5914
                        gen_op_stl_user();
5915
                    else
5916
                        gen_op_stl_kernel();
5917
                }
5918
#endif
5919
            }
5920
            if (!(insn & (1 << 24))) {
5921
                gen_add_data_offset(s, insn);
5922
                gen_movl_reg_T1(s, rn);
5923
            } else if (insn & (1 << 21))
5924
                gen_movl_reg_T1(s, rn); {
5925
            }
5926
            if (insn & (1 << 20)) {
5927
                /* Complete the load.  */
5928
                if (rd == 15)
5929
                    gen_bx(s);
5930
                else
5931
                    gen_movl_reg_T0(s, rd);
5932
            }
5933
            break;
5934
        case 0x08:
5935
        case 0x09:
5936
            {
5937
                int j, n, user, loaded_base;
5938
                /* load/store multiple words */
5939
                /* XXX: store correct base if write back */
5940
                user = 0;
5941
                if (insn & (1 << 22)) {
5942
                    if (IS_USER(s))
5943
                        goto illegal_op; /* only usable in supervisor mode */
5944

    
5945
                    if ((insn & (1 << 15)) == 0)
5946
                        user = 1;
5947
                }
5948
                rn = (insn >> 16) & 0xf;
5949
                gen_movl_T1_reg(s, rn);
5950

    
5951
                /* compute total size */
5952
                loaded_base = 0;
5953
                n = 0;
5954
                for(i=0;i<16;i++) {
5955
                    if (insn & (1 << i))
5956
                        n++;
5957
                }
5958
                /* XXX: test invalid n == 0 case ? */
5959
                if (insn & (1 << 23)) {
5960
                    if (insn & (1 << 24)) {
5961
                        /* pre increment */
5962
                        gen_op_addl_T1_im(4);
5963
                    } else {
5964
                        /* post increment */
5965
                    }
5966
                } else {
5967
                    if (insn & (1 << 24)) {
5968
                        /* pre decrement */
5969
                        gen_op_addl_T1_im(-(n * 4));
5970
                    } else {
5971
                        /* post decrement */
5972
                        if (n != 1)
5973
                            gen_op_addl_T1_im(-((n - 1) * 4));
5974
                    }
5975
                }
5976
                j = 0;
5977
                for(i=0;i<16;i++) {
5978
                    if (insn & (1 << i)) {
5979
                        if (insn & (1 << 20)) {
5980
                            /* load */
5981
                            gen_ldst(ldl, s);
5982
                            if (i == 15) {
5983
                                gen_bx(s);
5984
                            } else if (user) {
5985
                                gen_op_movl_user_T0(i);
5986
                            } else if (i == rn) {
5987
                                gen_op_movl_T2_T0();
5988
                                loaded_base = 1;
5989
                            } else {
5990
                                gen_movl_reg_T0(s, i);
5991
                            }
5992
                        } else {
5993
                            /* store */
5994
                            if (i == 15) {
5995
                                /* special case: r15 = PC + 8 */
5996
                                val = (long)s->pc + 4;
5997
                                gen_op_movl_T0_im(val);
5998
                            } else if (user) {
5999
                                gen_op_movl_T0_user(i);
6000
                            } else {
6001
                                gen_movl_T0_reg(s, i);
6002
                            }
6003
                            gen_ldst(stl, s);
6004
                        }
6005
                        j++;
6006
                        /* no need to add after the last transfer */
6007
                        if (j != n)
6008
                            gen_op_addl_T1_im(4);
6009
                    }
6010
                }
6011
                if (insn & (1 << 21)) {
6012
                    /* write back */
6013
                    if (insn & (1 << 23)) {
6014
                        if (insn & (1 << 24)) {
6015
                            /* pre increment */
6016
                        } else {
6017
                            /* post increment */
6018
                            gen_op_addl_T1_im(4);
6019
                        }
6020
                    } else {
6021
                        if (insn & (1 << 24)) {
6022
                            /* pre decrement */
6023
                            if (n != 1)
6024
                                gen_op_addl_T1_im(-((n - 1) * 4));
6025
                        } else {
6026
                            /* post decrement */
6027
                            gen_op_addl_T1_im(-(n * 4));
6028
                        }
6029
                    }
6030
                    gen_movl_reg_T1(s, rn);
6031
                }
6032
                if (loaded_base) {
6033
                    gen_op_movl_T0_T2();
6034
                    gen_movl_reg_T0(s, rn);
6035
                }
6036
                if ((insn & (1 << 22)) && !user) {
6037
                    /* Restore CPSR from SPSR.  */
6038
                    gen_op_movl_T0_spsr();
6039
                    gen_op_movl_cpsr_T0(0xffffffff);
6040
                    s->is_jmp = DISAS_UPDATE;
6041
                }
6042
            }
6043
            break;
6044
        case 0xa:
6045
        case 0xb:
6046
            {
6047
                int32_t offset;
6048

    
6049
                /* branch (and link) */
6050
                val = (int32_t)s->pc;
6051
                if (insn & (1 << 24)) {
6052
                    gen_op_movl_T0_im(val);
6053
                    gen_movl_reg_T0(s, 14);
6054
                }
6055
                offset = (((int32_t)insn << 8) >> 8);
6056
                val += (offset << 2) + 4;
6057
                gen_jmp(s, val);
6058
            }
6059
            break;
6060
        case 0xc:
6061
        case 0xd:
6062
        case 0xe:
6063
            /* Coprocessor.  */
6064
            if (disas_coproc_insn(env, s, insn))
6065
                goto illegal_op;
6066
            break;
6067
        case 0xf:
6068
            /* swi */
6069
            gen_op_movl_T0_im((long)s->pc);
6070
            gen_set_pc_T0();
6071
            s->is_jmp = DISAS_SWI;
6072
            break;
6073
        default:
6074
        illegal_op:
6075
            gen_set_condexec(s);
6076
            gen_op_movl_T0_im((long)s->pc - 4);
6077
            gen_set_pc_T0();
6078
            gen_op_undef_insn();
6079
            s->is_jmp = DISAS_JUMP;
6080
            break;
6081
        }
6082
    }
6083
}
6084

    
6085
/* Return true if this is a Thumb-2 logical op.  */
6086
static int
6087
thumb2_logic_op(int op)
6088
{
6089
    return (op < 8);
6090
}
6091

    
6092
/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
6093
   then set condition code flags based on the result of the operation.
6094
   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6095
   to the high bit of T1.
6096
   Returns zero if the opcode is valid.  */
6097

    
6098
static int
6099
gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out)
6100
{
6101
    int logic_cc;
6102

    
6103
    logic_cc = 0;
6104
    switch (op) {
6105
    case 0: /* and */
6106
        gen_op_andl_T0_T1();
6107
        logic_cc = conds;
6108
        break;
6109
    case 1: /* bic */
6110
        gen_op_bicl_T0_T1();
6111
        logic_cc = conds;
6112
        break;
6113
    case 2: /* orr */
6114
        gen_op_orl_T0_T1();
6115
        logic_cc = conds;
6116
        break;
6117
    case 3: /* orn */
6118
        gen_op_notl_T1();
6119
        gen_op_orl_T0_T1();
6120
        logic_cc = conds;
6121
        break;
6122
    case 4: /* eor */
6123
        gen_op_xorl_T0_T1();
6124
        logic_cc = conds;
6125
        break;
6126
    case 8: /* add */
6127
        if (conds)
6128
            gen_op_addl_T0_T1_cc();
6129
        else
6130
            gen_op_addl_T0_T1();
6131
        break;
6132
    case 10: /* adc */
6133
        if (conds)
6134
            gen_op_adcl_T0_T1_cc();
6135
        else
6136
            gen_adc_T0_T1();
6137
        break;
6138
    case 11: /* sbc */
6139
        if (conds)
6140
            gen_op_sbcl_T0_T1_cc();
6141
        else
6142
            gen_sbc_T0_T1();
6143
        break;
6144
    case 13: /* sub */
6145
        if (conds)
6146
            gen_op_subl_T0_T1_cc();
6147
        else
6148
            gen_op_subl_T0_T1();
6149
        break;
6150
    case 14: /* rsb */
6151
        if (conds)
6152
            gen_op_rsbl_T0_T1_cc();
6153
        else
6154
            gen_op_rsbl_T0_T1();
6155
        break;
6156
    default: /* 5, 6, 7, 9, 12, 15. */
6157
        return 1;
6158
    }
6159
    if (logic_cc) {
6160
        gen_op_logic_T0_cc();
6161
        if (shifter_out)
6162
            gen_set_CF_bit31(cpu_T[1]);
6163
    }
6164
    return 0;
6165
}
6166

    
6167
/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
6168
   is not legal.  */
6169
static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
6170
{
6171
    uint32_t insn, imm, shift, offset, addr;
6172
    uint32_t rd, rn, rm, rs;
6173
    TCGv tmp;
6174
    TCGv tmp2;
6175
    TCGv tmp3;
6176
    int op;
6177
    int shiftop;
6178
    int conds;
6179
    int logic_cc;
6180

    
6181
    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
6182
          || arm_feature (env, ARM_FEATURE_M))) {
6183
        /* Thumb-1 cores may need to tread bl and blx as a pair of
6184
           16-bit instructions to get correct prefetch abort behavior.  */
6185
        insn = insn_hw1;
6186
        if ((insn & (1 << 12)) == 0) {
6187
            /* Second half of blx.  */
6188
            offset = ((insn & 0x7ff) << 1);
6189
            gen_movl_T0_reg(s, 14);
6190
            gen_op_movl_T1_im(offset);
6191
            gen_op_addl_T0_T1();
6192
            gen_op_movl_T1_im(0xfffffffc);
6193
            gen_op_andl_T0_T1();
6194

    
6195
            addr = (uint32_t)s->pc;
6196
            gen_op_movl_T1_im(addr | 1);
6197
            gen_movl_reg_T1(s, 14);
6198
            gen_bx(s);
6199
            return 0;
6200
        }
6201
        if (insn & (1 << 11)) {
6202
            /* Second half of bl.  */
6203
            offset = ((insn & 0x7ff) << 1) | 1;
6204
            gen_movl_T0_reg(s, 14);
6205
            gen_op_movl_T1_im(offset);
6206
            gen_op_addl_T0_T1();
6207

    
6208
            addr = (uint32_t)s->pc;
6209
            gen_op_movl_T1_im(addr | 1);
6210
            gen_movl_reg_T1(s, 14);
6211
            gen_bx(s);
6212
            return 0;
6213
        }
6214
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
6215
            /* Instruction spans a page boundary.  Implement it as two
6216
               16-bit instructions in case the second half causes an
6217
               prefetch abort.  */
6218
            offset = ((int32_t)insn << 21) >> 9;
6219
            addr = s->pc + 2 + offset;
6220
            gen_op_movl_T0_im(addr);
6221
            gen_movl_reg_T0(s, 14);
6222
            return 0;
6223
        }
6224
        /* Fall through to 32-bit decode.  */
6225
    }
6226

    
6227
    insn = lduw_code(s->pc);
6228
    s->pc += 2;
6229
    insn |= (uint32_t)insn_hw1 << 16;
6230

    
6231
    if ((insn & 0xf800e800) != 0xf000e800) {
6232
        ARCH(6T2);
6233
    }
6234

    
6235
    rn = (insn >> 16) & 0xf;
6236
    rs = (insn >> 12) & 0xf;
6237
    rd = (insn >> 8) & 0xf;
6238
    rm = insn & 0xf;
6239
    switch ((insn >> 25) & 0xf) {
6240
    case 0: case 1: case 2: case 3:
6241
        /* 16-bit instructions.  Should never happen.  */
6242
        abort();
6243
    case 4:
6244
        if (insn & (1 << 22)) {
6245
            /* Other load/store, table branch.  */
6246
            if (insn & 0x01200000) {
6247
                /* Load/store doubleword.  */
6248
                if (rn == 15) {
6249
                    gen_op_movl_T1_im(s->pc & ~3);
6250
                } else {
6251
                    gen_movl_T1_reg(s, rn);
6252
                }
6253
                offset = (insn & 0xff) * 4;
6254
                if ((insn & (1 << 23)) == 0)
6255
                    offset = -offset;
6256
                if (insn & (1 << 24)) {
6257
                    gen_op_addl_T1_im(offset);
6258
                    offset = 0;
6259
                }
6260
                if (insn & (1 << 20)) {
6261
                    /* ldrd */
6262
                    gen_ldst(ldl, s);
6263
                    gen_movl_reg_T0(s, rs);
6264
                    gen_op_addl_T1_im(4);
6265
                    gen_ldst(ldl, s);
6266
                    gen_movl_reg_T0(s, rd);
6267
                } else {
6268
                    /* strd */
6269
                    gen_movl_T0_reg(s, rs);
6270
                    gen_ldst(stl, s);
6271
                    gen_op_addl_T1_im(4);
6272
                    gen_movl_T0_reg(s, rd);
6273
                    gen_ldst(stl, s);
6274
                }
6275
                if (insn & (1 << 21)) {
6276
                    /* Base writeback.  */
6277
                    if (rn == 15)
6278
                        goto illegal_op;
6279
                    gen_op_addl_T1_im(offset - 4);
6280
                    gen_movl_reg_T1(s, rn);
6281
                }
6282
            } else if ((insn & (1 << 23)) == 0) {
6283
                /* Load/store exclusive word.  */
6284
                gen_movl_T0_reg(s, rd);
6285
                gen_movl_T1_reg(s, rn);
6286
                if (insn & (1 << 20)) {
6287
                    gen_ldst(ldlex, s);
6288
                } else {
6289
                    gen_ldst(stlex, s);
6290
                }
6291
                gen_movl_reg_T0(s, rd);
6292
            } else if ((insn & (1 << 6)) == 0) {
6293
                /* Table Branch.  */
6294
                if (rn == 15) {
6295
                    gen_op_movl_T1_im(s->pc);
6296
                } else {
6297
                    gen_movl_T1_reg(s, rn);
6298
                }
6299
                tmp = load_reg(s, rm);
6300
                tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6301
                if (insn & (1 << 4)) {
6302
                    /* tbh */
6303
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6304
                    dead_tmp(tmp);
6305
                    gen_ldst(lduw, s);
6306
                } else { /* tbb */
6307
                    dead_tmp(tmp);
6308
                    gen_ldst(ldub, s);
6309
                }
6310
                tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 1);
6311
                tcg_gen_addi_i32(cpu_T[0], cpu_T[0], s->pc);
6312
                gen_movl_reg_T0(s, 15);
6313
            } else {
6314
                /* Load/store exclusive byte/halfword/doubleword.  */
6315
                op = (insn >> 4) & 0x3;
6316
                gen_movl_T1_reg(s, rn);
6317
                if (insn & (1 << 20)) {
6318
                    switch (op) {
6319
                    case 0:
6320
                        gen_ldst(ldbex, s);
6321
                        break;
6322
                    case 1:
6323
                        gen_ldst(ldwex, s);
6324
                        break;
6325
                    case 3:
6326
                        gen_ldst(ldqex, s);
6327
                        gen_movl_reg_T1(s, rd);
6328
                        break;
6329
                    default:
6330
                        goto illegal_op;
6331
                    }
6332
                    gen_movl_reg_T0(s, rs);
6333
                } else {
6334
                    gen_movl_T0_reg(s, rs);
6335
                    switch (op) {
6336
                    case 0:
6337
                        gen_ldst(stbex, s);
6338
                        break;
6339
                    case 1:
6340
                        gen_ldst(stwex, s);
6341
                        break;
6342
                    case 3:
6343
                        gen_movl_T2_reg(s, rd);
6344
                        gen_ldst(stqex, s);
6345
                        break;
6346
                    default:
6347
                        goto illegal_op;
6348
                    }
6349
                    gen_movl_reg_T0(s, rm);
6350
                }
6351
            }
6352
        } else {
6353
            /* Load/store multiple, RFE, SRS.  */
6354
            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
6355
                /* Not available in user mode.  */
6356
                if (!IS_USER(s))
6357
                    goto illegal_op;
6358
                if (insn & (1 << 20)) {
6359
                    /* rfe */
6360
                    gen_movl_T1_reg(s, rn);
6361
                    if (insn & (1 << 24)) {
6362
                        gen_op_addl_T1_im(4);
6363
                    } else {
6364
                        gen_op_addl_T1_im(-4);
6365
                    }
6366
                    /* Load CPSR into T2 and PC into T0.  */
6367
                    gen_ldst(ldl, s);
6368
                    gen_op_movl_T2_T0();
6369
                    gen_op_addl_T1_im(-4);
6370
                    gen_ldst(ldl, s);
6371
                    if (insn & (1 << 21)) {
6372
                        /* Base writeback.  */
6373
                        if (insn & (1 << 24))
6374
                            gen_op_addl_T1_im(8);
6375
                        gen_movl_reg_T1(s, rn);
6376
                    }
6377
                    gen_rfe(s);
6378
                } else {
6379
                    /* srs */
6380
                    op = (insn & 0x1f);
6381
                    if (op == (env->uncached_cpsr & CPSR_M)) {
6382
                        gen_movl_T1_reg(s, 13);
6383
                    } else {
6384
                        gen_op_movl_T1_r13_banked(op);
6385
                    }
6386
                    if ((insn & (1 << 24)) == 0) {
6387
                        gen_op_addl_T1_im(-8);
6388
                    }
6389
                    gen_movl_T0_reg(s, 14);
6390
                    gen_ldst(stl, s);
6391
                    gen_op_movl_T0_cpsr();
6392
                    gen_op_addl_T1_im(4);
6393
                    gen_ldst(stl, s);
6394
                    if (insn & (1 << 21)) {
6395
                        if ((insn & (1 << 24)) == 0) {
6396
                            gen_op_addl_T1_im(-4);
6397
                        } else {
6398
                            gen_op_addl_T1_im(4);
6399
                        }
6400
                        if (op == (env->uncached_cpsr & CPSR_M)) {
6401
                            gen_movl_reg_T1(s, 13);
6402
                        } else {
6403
                            gen_op_movl_r13_T1_banked(op);
6404
                        }
6405
                    }
6406
                }
6407
            } else {
6408
                int i;
6409
                /* Load/store multiple.  */
6410
                gen_movl_T1_reg(s, rn);
6411
                offset = 0;
6412
                for (i = 0; i < 16; i++) {
6413
                    if (insn & (1 << i))
6414
                        offset += 4;
6415
                }
6416
                if (insn & (1 << 24)) {
6417
                    gen_op_addl_T1_im(-offset);
6418
                }
6419

    
6420
                for (i = 0; i < 16; i++) {
6421
                    if ((insn & (1 << i)) == 0)
6422
                        continue;
6423
                    if (insn & (1 << 20)) {
6424
                        /* Load.  */
6425
                        gen_ldst(ldl, s);
6426
                        if (i == 15) {
6427
                            gen_bx(s);
6428
                        } else {
6429
                            gen_movl_reg_T0(s, i);
6430
                        }
6431
                    } else {
6432
                        /* Store.  */
6433
                        gen_movl_T0_reg(s, i);
6434
                        gen_ldst(stl, s);
6435
                    }
6436
                    gen_op_addl_T1_im(4);
6437
                }
6438
                if (insn & (1 << 21)) {
6439
                    /* Base register writeback.  */
6440
                    if (insn & (1 << 24)) {
6441
                        gen_op_addl_T1_im(-offset);
6442
                    }
6443
                    /* Fault if writeback register is in register list.  */
6444
                    if (insn & (1 << rn))
6445
                        goto illegal_op;
6446
                    gen_movl_reg_T1(s, rn);
6447
                }
6448
            }
6449
        }
6450
        break;
6451
    case 5: /* Data processing register constant shift.  */
6452
        if (rn == 15)
6453
            gen_op_movl_T0_im(0);
6454
        else
6455
            gen_movl_T0_reg(s, rn);
6456
        gen_movl_T1_reg(s, rm);
6457
        op = (insn >> 21) & 0xf;
6458
        shiftop = (insn >> 4) & 3;
6459
        shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6460
        conds = (insn & (1 << 20)) != 0;
6461
        logic_cc = (conds && thumb2_logic_op(op));
6462
        gen_arm_shift_im(cpu_T[1], shiftop, shift, logic_cc);
6463
        if (gen_thumb2_data_op(s, op, conds, 0))
6464
            goto illegal_op;
6465
        if (rd != 15)
6466
            gen_movl_reg_T0(s, rd);
6467
        break;
6468
    case 13: /* Misc data processing.  */
6469
        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
6470
        if (op < 4 && (insn & 0xf000) != 0xf000)
6471
            goto illegal_op;
6472
        switch (op) {
6473
        case 0: /* Register controlled shift.  */
6474
            gen_movl_T0_reg(s, rm);
6475
            gen_movl_T1_reg(s, rn);
6476
            if ((insn & 0x70) != 0)
6477
                goto illegal_op;
6478
            op = (insn >> 21) & 3;
6479
            if (insn & (1 << 20)) {
6480
                gen_shift_T1_T0_cc[op]();
6481
                gen_op_logic_T1_cc();
6482
            } else {
6483
                gen_shift_T1_T0[op]();
6484
            }
6485
            gen_movl_reg_T1(s, rd);
6486
            break;
6487
        case 1: /* Sign/zero extend.  */
6488
            gen_movl_T1_reg(s, rm);
6489
            shift = (insn >> 4) & 3;
6490
            /* ??? In many cases it's not neccessary to do a
6491
               rotate, a shift is sufficient.  */
6492
            if (shift != 0)
6493
                gen_op_rorl_T1_im(shift * 8);
6494
            op = (insn >> 20) & 7;
6495
            switch (op) {
6496
            case 0: gen_sxth(cpu_T[1]);   break;
6497
            case 1: gen_uxth(cpu_T[1]);   break;
6498
            case 2: gen_sxtb16(cpu_T[1]); break;
6499
            case 3: gen_uxtb16(cpu_T[1]); break;
6500
            case 4: gen_sxtb(cpu_T[1]);   break;
6501
            case 5: gen_uxtb(cpu_T[1]);   break;
6502
            default: goto illegal_op;
6503
            }
6504
            if (rn != 15) {
6505
                tmp = load_reg(s, rn);
6506
                if ((op >> 1) == 1) {
6507
                    gen_add16(cpu_T[1], tmp);
6508
                } else {
6509
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
6510
                    dead_tmp(tmp);
6511
                }
6512
            }
6513
            gen_movl_reg_T1(s, rd);
6514
            break;
6515
        case 2: /* SIMD add/subtract.  */
6516
            op = (insn >> 20) & 7;
6517
            shift = (insn >> 4) & 7;
6518
            if ((op & 3) == 3 || (shift & 3) == 3)
6519
                goto illegal_op;
6520
            tmp = load_reg(s, rn);
6521
            tmp2 = load_reg(s, rm);
6522
            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
6523
            dead_tmp(tmp2);
6524
            store_reg(s, rd, tmp);
6525
            break;
6526
        case 3: /* Other data processing.  */
6527
            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
6528
            if (op < 4) {
6529
                /* Saturating add/subtract.  */
6530
                gen_movl_T0_reg(s, rm);
6531
                gen_movl_T1_reg(s, rn);
6532
                if (op & 2)
6533
                    gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
6534
                if (op & 1)
6535
                    gen_op_subl_T0_T1_saturate();
6536
                else
6537
                    gen_op_addl_T0_T1_saturate();
6538
            } else {
6539
                gen_movl_T0_reg(s, rn);
6540
                switch (op) {
6541
                case 0x0a: /* rbit */
6542
                    gen_helper_rbit(cpu_T[0], cpu_T[0]);
6543
                    break;
6544
                case 0x08: /* rev */
6545
                    gen_op_rev_T0();
6546
                    break;
6547
                case 0x09: /* rev16 */
6548
                    gen_rev16(cpu_T[0]);
6549
                    break;
6550
                case 0x0b: /* revsh */
6551
                    gen_revsh(cpu_T[0]);
6552
                    break;
6553
                case 0x10: /* sel */
6554
                    gen_movl_T1_reg(s, rm);
6555
                    tmp3 = new_tmp();
6556
                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6557
                    gen_helper_sel_flags(cpu_T[0], tmp3, cpu_T[0], cpu_T[1]);
6558
                    dead_tmp(tmp3);
6559
                    break;
6560
                case 0x18: /* clz */
6561
                    gen_helper_clz(cpu_T[0], cpu_T[0]);
6562
                    break;
6563
                default:
6564
                    goto illegal_op;
6565
                }
6566
            }
6567
            gen_movl_reg_T0(s, rd);
6568
            break;
6569
        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
6570
            op = (insn >> 4) & 0xf;
6571
            gen_movl_T0_reg(s, rn);
6572
            gen_movl_T1_reg(s, rm);
6573
            switch ((insn >> 20) & 7) {
6574
            case 0: /* 32 x 32 -> 32 */
6575
                gen_op_mul_T0_T1();
6576
                if (rs != 15) {
6577
                    gen_movl_T1_reg(s, rs);
6578
                    if (op)
6579
                        gen_op_rsbl_T0_T1();
6580
                    else
6581
                        gen_op_addl_T0_T1();
6582
                }
6583
                gen_movl_reg_T0(s, rd);
6584
                break;
6585
            case 1: /* 16 x 16 -> 32 */
6586
                gen_mulxy(op & 2, op & 1);
6587
                if (rs != 15) {
6588
                    gen_movl_T1_reg(s, rs);
6589
                    gen_op_addl_T0_T1_setq();
6590
                }
6591
                gen_movl_reg_T0(s, rd);
6592
                break;
6593
            case 2: /* Dual multiply add.  */
6594
            case 4: /* Dual multiply subtract.  */
6595
                if (op)
6596
                    gen_swap_half(cpu_T[1]);
6597
                gen_smul_dual(cpu_T[0], cpu_T[1]);
6598
                /* This addition cannot overflow.  */
6599
                if (insn & (1 << 22)) {
6600
                    gen_op_subl_T0_T1();
6601
                } else {
6602
                    gen_op_addl_T0_T1();
6603
                }
6604
                if (rs != 15)
6605
                  {
6606
                    gen_movl_T1_reg(s, rs);
6607
                    gen_op_addl_T0_T1_setq();
6608
                  }
6609
                gen_movl_reg_T0(s, rd);
6610
                break;
6611
            case 3: /* 32 * 16 -> 32msb */
6612
                if (op)
6613
                    gen_op_sarl_T1_im(16);
6614
                else
6615
                    gen_sxth(cpu_T[1]);
6616
                gen_op_imulw_T0_T1();
6617
                if (rs != 15)
6618
                  {
6619
                    gen_movl_T1_reg(s, rs);
6620
                    gen_op_addl_T0_T1_setq();
6621
                  }
6622
                gen_movl_reg_T0(s, rd);
6623
                break;
6624
            case 5: case 6: /* 32 * 32 -> 32msb */
6625
                gen_op_imull_T0_T1();
6626
                if (insn & (1 << 5))
6627
                    gen_op_roundqd_T0_T1();
6628
                else
6629
                    gen_op_movl_T0_T1();
6630
                if (rs != 15) {
6631
                    gen_movl_T1_reg(s, rs);
6632
                    if (insn & (1 << 21)) {
6633
                        gen_op_addl_T0_T1();
6634
                    } else {
6635
                        gen_op_rsbl_T0_T1();
6636
                    }
6637
                }
6638
                gen_movl_reg_T0(s, rd);
6639
                break;
6640
            case 7: /* Unsigned sum of absolute differences.  */
6641
                gen_helper_usad8(cpu_T[0], cpu_T[0], cpu_T[1]);
6642
                if (rs != 15) {
6643
                    gen_movl_T1_reg(s, rs);
6644
                    gen_op_addl_T0_T1();
6645
                }
6646
                gen_movl_reg_T0(s, rd);
6647
                break;
6648
            }
6649
            break;
6650
        case 6: case 7: /* 64-bit multiply, Divide.  */
6651
            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
6652
            gen_movl_T0_reg(s, rn);
6653
            gen_movl_T1_reg(s, rm);
6654
            if ((op & 0x50) == 0x10) {
6655
                /* sdiv, udiv */
6656
                if (!arm_feature(env, ARM_FEATURE_DIV))
6657
                    goto illegal_op;
6658
                if (op & 0x20)
6659
                    gen_helper_udiv(cpu_T[0], cpu_T[0], cpu_T[1]);
6660
                else
6661
                    gen_helper_sdiv(cpu_T[0], cpu_T[0], cpu_T[1]);
6662
                gen_movl_reg_T0(s, rd);
6663
            } else if ((op & 0xe) == 0xc) {
6664
                /* Dual multiply accumulate long.  */
6665
                if (op & 1)
6666
                    gen_swap_half(cpu_T[1]);
6667
                gen_smul_dual(cpu_T[0], cpu_T[1]);
6668
                if (op & 0x10) {
6669
                    gen_op_subl_T0_T1();
6670
                } else {
6671
                    gen_op_addl_T0_T1();
6672
                }
6673
                gen_op_signbit_T1_T0();
6674
                gen_op_addq_T0_T1(rs, rd);
6675
                gen_movl_reg_T0(s, rs);
6676
                gen_movl_reg_T1(s, rd);
6677
            } else {
6678
                if (op & 0x20) {
6679
                    /* Unsigned 64-bit multiply  */
6680
                    gen_op_mull_T0_T1();
6681
                } else {
6682
                    if (op & 8) {
6683
                        /* smlalxy */
6684
                        gen_mulxy(op & 2, op & 1);
6685
                        gen_op_signbit_T1_T0();
6686
                    } else {
6687
                        /* Signed 64-bit multiply  */
6688
                        gen_op_imull_T0_T1();
6689
                    }
6690
                }
6691
                if (op & 4) {
6692
                    /* umaal */
6693
                    gen_op_addq_lo_T0_T1(rs);
6694
                    gen_op_addq_lo_T0_T1(rd);
6695
                } else if (op & 0x40) {
6696
                    /* 64-bit accumulate.  */
6697
                    gen_op_addq_T0_T1(rs, rd);
6698
                }
6699
                gen_movl_reg_T0(s, rs);
6700
                gen_movl_reg_T1(s, rd);
6701
            }
6702
            break;
6703
        }
6704
        break;
6705
    case 6: case 7: case 14: case 15:
6706
        /* Coprocessor.  */
6707
        if (((insn >> 24) & 3) == 3) {
6708
            /* Translate into the equivalent ARM encoding.  */
6709
            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
6710
            if (disas_neon_data_insn(env, s, insn))
6711
                goto illegal_op;
6712
        } else {
6713
            if (insn & (1 << 28))
6714
                goto illegal_op;
6715
            if (disas_coproc_insn (env, s, insn))
6716
                goto illegal_op;
6717
        }
6718
        break;
6719
    case 8: case 9: case 10: case 11:
6720
        if (insn & (1 << 15)) {
6721
            /* Branches, misc control.  */
6722
            if (insn & 0x5000) {
6723
                /* Unconditional branch.  */
6724
                /* signextend(hw1[10:0]) -> offset[:12].  */
6725
                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
6726
                /* hw1[10:0] -> offset[11:1].  */
6727
                offset |= (insn & 0x7ff) << 1;
6728
                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
6729
                   offset[24:22] already have the same value because of the
6730
                   sign extension above.  */
6731
                offset ^= ((~insn) & (1 << 13)) << 10;
6732
                offset ^= ((~insn) & (1 << 11)) << 11;
6733

    
6734
                addr = s->pc;
6735
                if (insn & (1 << 14)) {
6736
                    /* Branch and link.  */
6737
                    gen_op_movl_T1_im(addr | 1);
6738
                    gen_movl_reg_T1(s, 14);
6739
                }
6740

    
6741
                addr += offset;
6742
                if (insn & (1 << 12)) {
6743
                    /* b/bl */
6744
                    gen_jmp(s, addr);
6745
                } else {
6746
                    /* blx */
6747
                    addr &= ~(uint32_t)2;
6748
                    gen_op_movl_T0_im(addr);
6749
                    gen_bx(s);
6750
                }
6751
            } else if (((insn >> 23) & 7) == 7) {
6752
                /* Misc control */
6753
                if (insn & (1 << 13))
6754
                    goto illegal_op;
6755

    
6756
                if (insn & (1 << 26)) {
6757
                    /* Secure monitor call (v6Z) */
6758
                    goto illegal_op; /* not implemented.  */
6759
                } else {
6760
                    op = (insn >> 20) & 7;
6761
                    switch (op) {
6762
                    case 0: /* msr cpsr.  */
6763
                        if (IS_M(env)) {
6764
                            gen_op_v7m_msr_T0(insn & 0xff);
6765
                            gen_movl_reg_T0(s, rn);
6766
                            gen_lookup_tb(s);
6767
                            break;
6768
                        }
6769
                        /* fall through */
6770
                    case 1: /* msr spsr.  */
6771
                        if (IS_M(env))
6772
                            goto illegal_op;
6773
                        gen_movl_T0_reg(s, rn);
6774
                        if (gen_set_psr_T0(s,
6775
                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
6776
                              op == 1))
6777
                            goto illegal_op;
6778
                        break;
6779
                    case 2: /* cps, nop-hint.  */
6780
                        if (((insn >> 8) & 7) == 0) {
6781
                            gen_nop_hint(s, insn & 0xff);
6782
                        }
6783
                        /* Implemented as NOP in user mode.  */
6784
                        if (IS_USER(s))
6785
                            break;
6786
                        offset = 0;
6787
                        imm = 0;
6788
                        if (insn & (1 << 10)) {
6789
                            if (insn & (1 << 7))
6790
                                offset |= CPSR_A;
6791
                            if (insn & (1 << 6))
6792
                                offset |= CPSR_I;
6793
                            if (insn & (1 << 5))
6794
                                offset |= CPSR_F;
6795
                            if (insn & (1 << 9))
6796
                                imm = CPSR_A | CPSR_I | CPSR_F;
6797
                        }
6798
                        if (insn & (1 << 8)) {
6799
                            offset |= 0x1f;
6800
                            imm |= (insn & 0x1f);
6801
                        }
6802
                        if (offset) {
6803
                            gen_op_movl_T0_im(imm);
6804
                            gen_set_psr_T0(s, offset, 0);
6805
                        }
6806
                        break;
6807
                    case 3: /* Special control operations.  */
6808
                        op = (insn >> 4) & 0xf;
6809
                        switch (op) {
6810
                        case 2: /* clrex */
6811
                            gen_op_clrex();
6812
                            break;
6813
                        case 4: /* dsb */
6814
                        case 5: /* dmb */
6815
                        case 6: /* isb */
6816
                            /* These execute as NOPs.  */
6817
                            ARCH(7);
6818
                            break;
6819
                        default:
6820
                            goto illegal_op;
6821
                        }
6822
                        break;
6823
                    case 4: /* bxj */
6824
                        /* Trivial implementation equivalent to bx.  */
6825
                        gen_movl_T0_reg(s, rn);
6826
                        gen_bx(s);
6827
                        break;
6828
                    case 5: /* Exception return.  */
6829
                        /* Unpredictable in user mode.  */
6830
                        goto illegal_op;
6831
                    case 6: /* mrs cpsr.  */
6832
                        if (IS_M(env)) {
6833
                            gen_op_v7m_mrs_T0(insn & 0xff);
6834
                        } else {
6835
                            gen_op_movl_T0_cpsr();
6836
                        }
6837
                        gen_movl_reg_T0(s, rd);
6838
                        break;
6839
                    case 7: /* mrs spsr.  */
6840
                        /* Not accessible in user mode.  */
6841
                        if (IS_USER(s) || IS_M(env))
6842
                            goto illegal_op;
6843
                        gen_op_movl_T0_spsr();
6844
                        gen_movl_reg_T0(s, rd);
6845
                        break;
6846
                    }
6847
                }
6848
            } else {
6849
                /* Conditional branch.  */
6850
                op = (insn >> 22) & 0xf;
6851
                /* Generate a conditional jump to next instruction.  */
6852
                s->condlabel = gen_new_label();
6853
                gen_test_cc[op ^ 1](s->condlabel);
6854
                s->condjmp = 1;
6855

    
6856
                /* offset[11:1] = insn[10:0] */
6857
                offset = (insn & 0x7ff) << 1;
6858
                /* offset[17:12] = insn[21:16].  */
6859
                offset |= (insn & 0x003f0000) >> 4;
6860
                /* offset[31:20] = insn[26].  */
6861
                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
6862
                /* offset[18] = insn[13].  */
6863
                offset |= (insn & (1 << 13)) << 5;
6864
                /* offset[19] = insn[11].  */
6865
                offset |= (insn & (1 << 11)) << 8;
6866

    
6867
                /* jump to the offset */
6868
                addr = s->pc + offset;
6869
                gen_jmp(s, addr);
6870
            }
6871
        } else {
6872
            /* Data processing immediate.  */
6873
            if (insn & (1 << 25)) {
6874
                if (insn & (1 << 24)) {
6875
                    if (insn & (1 << 20))
6876
                        goto illegal_op;
6877
                    /* Bitfield/Saturate.  */
6878
                    op = (insn >> 21) & 7;
6879
                    imm = insn & 0x1f;
6880
                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6881
                    if (rn == 15) {
6882
                        tmp = new_tmp();
6883
                        tcg_gen_movi_i32(tmp, 0);
6884
                    } else {
6885
                        tmp = load_reg(s, rn);
6886
                    }
6887
                    switch (op) {
6888
                    case 2: /* Signed bitfield extract.  */
6889
                        imm++;
6890
                        if (shift + imm > 32)
6891
                            goto illegal_op;
6892
                        if (imm < 32)
6893
                            gen_sbfx(tmp, shift, imm);
6894
                        break;
6895
                    case 6: /* Unsigned bitfield extract.  */
6896
                        imm++;
6897
                        if (shift + imm > 32)
6898
                            goto illegal_op;
6899
                        if (imm < 32)
6900
                            gen_ubfx(tmp, shift, (1u << imm) - 1);
6901
                        break;
6902
                    case 3: /* Bitfield insert/clear.  */
6903
                        if (imm < shift)
6904
                            goto illegal_op;
6905
                        imm = imm + 1 - shift;
6906
                        if (imm != 32) {
6907
                            tmp2 = load_reg(s, rd);
6908
                            gen_bfi(tmp, tmp2, tmp,
6909
                                    shift, ((1u << imm) - 1) << shift);
6910
                            dead_tmp(tmp2);
6911
                        }
6912
                        break;
6913
                    case 7:
6914
                        goto illegal_op;
6915
                    default: /* Saturate.  */
6916
                        if (shift) {
6917
                            if (op & 1)
6918
                                tcg_gen_sari_i32(tmp, tmp, shift);
6919
                            else
6920
                                tcg_gen_shli_i32(tmp, tmp, shift);
6921
                        }
6922
                        tmp2 = tcg_const_i32(imm);
6923
                        if (op & 4) {
6924
                            /* Unsigned.  */
6925
                            if ((op & 1) && shift == 0)
6926
                                gen_helper_usat16(tmp, tmp, tmp2);
6927
                            else
6928
                                gen_helper_usat(tmp, tmp, tmp2);
6929
                        } else {
6930
                            /* Signed.  */
6931
                            if ((op & 1) && shift == 0)
6932
                                gen_helper_ssat16(tmp, tmp, tmp2);
6933
                            else
6934
                                gen_helper_ssat(tmp, tmp, tmp2);
6935
                        }
6936
                        break;
6937
                    }
6938
                    store_reg(s, rd, tmp);
6939
                } else {
6940
                    imm = ((insn & 0x04000000) >> 15)
6941
                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
6942
                    if (insn & (1 << 22)) {
6943
                        /* 16-bit immediate.  */
6944
                        imm |= (insn >> 4) & 0xf000;
6945
                        if (insn & (1 << 23)) {
6946
                            /* movt */
6947
                            gen_movl_T0_reg(s, rd);
6948
                            tcg_gen_andi_i32(cpu_T[0], cpu_T[0], 0xffff);
6949
                            tcg_gen_ori_i32(cpu_T[0], cpu_T[0], imm << 16);
6950
                        } else {
6951
                            /* movw */
6952
                            gen_op_movl_T0_im(imm);
6953
                        }
6954
                    } else {
6955
                        /* Add/sub 12-bit immediate.  */
6956
                        if (rn == 15) {
6957
                            addr = s->pc & ~(uint32_t)3;
6958
                            if (insn & (1 << 23))
6959
                                addr -= imm;
6960
                            else
6961
                                addr += imm;
6962
                            gen_op_movl_T0_im(addr);
6963
                        } else {
6964
                            gen_movl_T0_reg(s, rn);
6965
                            gen_op_movl_T1_im(imm);
6966
                            if (insn & (1 << 23))
6967
                                gen_op_subl_T0_T1();
6968
                            else
6969
                                gen_op_addl_T0_T1();
6970
                        }
6971
                    }
6972
                    gen_movl_reg_T0(s, rd);
6973
                }
6974
            } else {
6975
                int shifter_out = 0;
6976
                /* modified 12-bit immediate.  */
6977
                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
6978
                imm = (insn & 0xff);
6979
                switch (shift) {
6980
                case 0: /* XY */
6981
                    /* Nothing to do.  */
6982
                    break;
6983
                case 1: /* 00XY00XY */
6984
                    imm |= imm << 16;
6985
                    break;
6986
                case 2: /* XY00XY00 */
6987
                    imm |= imm << 16;
6988
                    imm <<= 8;
6989
                    break;
6990
                case 3: /* XYXYXYXY */
6991
                    imm |= imm << 16;
6992
                    imm |= imm << 8;
6993
                    break;
6994
                default: /* Rotated constant.  */
6995
                    shift = (shift << 1) | (imm >> 7);
6996
                    imm |= 0x80;
6997
                    imm = imm << (32 - shift);
6998
                    shifter_out = 1;
6999
                    break;
7000
                }
7001
                gen_op_movl_T1_im(imm);
7002
                rn = (insn >> 16) & 0xf;
7003
                if (rn == 15)
7004
                    gen_op_movl_T0_im(0);
7005
                else
7006
                    gen_movl_T0_reg(s, rn);
7007
                op = (insn >> 21) & 0xf;
7008
                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7009
                                       shifter_out))
7010
                    goto illegal_op;
7011
                rd = (insn >> 8) & 0xf;
7012
                if (rd != 15) {
7013
                    gen_movl_reg_T0(s, rd);
7014
                }
7015
            }
7016
        }
7017
        break;
7018
    case 12: /* Load/store single data item.  */
7019
        {
7020
        int postinc = 0;
7021
        int writeback = 0;
7022
        if ((insn & 0x01100000) == 0x01000000) {
7023
            if (disas_neon_ls_insn(env, s, insn))
7024
                goto illegal_op;
7025
            break;
7026
        }
7027
        if (rn == 15) {
7028
            /* PC relative.  */
7029
            /* s->pc has already been incremented by 4.  */
7030
            imm = s->pc & 0xfffffffc;
7031
            if (insn & (1 << 23))
7032
                imm += insn & 0xfff;
7033
            else
7034
                imm -= insn & 0xfff;
7035
            gen_op_movl_T1_im(imm);
7036
        } else {
7037
            gen_movl_T1_reg(s, rn);
7038
            if (insn & (1 << 23)) {
7039
                /* Positive offset.  */
7040
                imm = insn & 0xfff;
7041
                gen_op_addl_T1_im(imm);
7042
            } else {
7043
                op = (insn >> 8) & 7;
7044
                imm = insn & 0xff;
7045
                switch (op) {
7046
                case 0: case 8: /* Shifted Register.  */
7047
                    shift = (insn >> 4) & 0xf;
7048
                    if (shift > 3)
7049
                        goto illegal_op;
7050
                    tmp = load_reg(s, rm);
7051
                    if (shift)
7052
                        tcg_gen_shli_i32(tmp, tmp, shift);
7053
                    tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
7054
                    dead_tmp(tmp);
7055
                    break;
7056
                case 4: /* Negative offset.  */
7057
                    gen_op_addl_T1_im(-imm);
7058
                    break;
7059
                case 6: /* User privilege.  */
7060
                    gen_op_addl_T1_im(imm);
7061
                    break;
7062
                case 1: /* Post-decrement.  */
7063
                    imm = -imm;
7064
                    /* Fall through.  */
7065
                case 3: /* Post-increment.  */
7066
                    postinc = 1;
7067
                    writeback = 1;
7068
                    break;
7069
                case 5: /* Pre-decrement.  */
7070
                    imm = -imm;
7071
                    /* Fall through.  */
7072
                case 7: /* Pre-increment.  */
7073
                    gen_op_addl_T1_im(imm);
7074
                    writeback = 1;
7075
                    break;
7076
                default:
7077
                    goto illegal_op;
7078
                }
7079
            }
7080
        }
7081
        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
7082
        if (insn & (1 << 20)) {
7083
            /* Load.  */
7084
            if (rs == 15 && op != 2) {
7085
                if (op & 2)
7086
                    goto illegal_op;
7087
                /* Memory hint.  Implemented as NOP.  */
7088
            } else {
7089
                switch (op) {
7090
                case 0: gen_ldst(ldub, s); break;
7091
                case 4: gen_ldst(ldsb, s); break;
7092
                case 1: gen_ldst(lduw, s); break;
7093
                case 5: gen_ldst(ldsw, s); break;
7094
                case 2: gen_ldst(ldl, s); break;
7095
                default: goto illegal_op;
7096
                }
7097
                if (rs == 15) {
7098
                    gen_bx(s);
7099
                } else {
7100
                    gen_movl_reg_T0(s, rs);
7101
                }
7102
            }
7103
        } else {
7104
            /* Store.  */
7105
            if (rs == 15)
7106
                goto illegal_op;
7107
            gen_movl_T0_reg(s, rs);
7108
            switch (op) {
7109
            case 0: gen_ldst(stb, s); break;
7110
            case 1: gen_ldst(stw, s); break;
7111
            case 2: gen_ldst(stl, s); break;
7112
            default: goto illegal_op;
7113
            }
7114
        }
7115
        if (postinc)
7116
            gen_op_addl_T1_im(imm);
7117
        if (writeback)
7118
            gen_movl_reg_T1(s, rn);
7119
        }
7120
        break;
7121
    default:
7122
        goto illegal_op;
7123
    }
7124
    return 0;
7125
illegal_op:
7126
    return 1;
7127
}
7128

    
7129
static void disas_thumb_insn(CPUState *env, DisasContext *s)
7130
{
7131
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
7132
    int32_t offset;
7133
    int i;
7134
    TCGv tmp;
7135

    
7136
    if (s->condexec_mask) {
7137
        cond = s->condexec_cond;
7138
        s->condlabel = gen_new_label();
7139
        gen_test_cc[cond ^ 1](s->condlabel);
7140
        s->condjmp = 1;
7141
    }
7142

    
7143
    insn = lduw_code(s->pc);
7144
    s->pc += 2;
7145

    
7146
    switch (insn >> 12) {
7147
    case 0: case 1:
7148
        rd = insn & 7;
7149
        op = (insn >> 11) & 3;
7150
        if (op == 3) {
7151
            /* add/subtract */
7152
            rn = (insn >> 3) & 7;
7153
            gen_movl_T0_reg(s, rn);
7154
            if (insn & (1 << 10)) {
7155
                /* immediate */
7156
                gen_op_movl_T1_im((insn >> 6) & 7);
7157
            } else {
7158
                /* reg */
7159
                rm = (insn >> 6) & 7;
7160
                gen_movl_T1_reg(s, rm);
7161
            }
7162
            if (insn & (1 << 9)) {
7163
                if (s->condexec_mask)
7164
                    gen_op_subl_T0_T1();
7165
                else
7166
                    gen_op_subl_T0_T1_cc();
7167
            } else {
7168
                if (s->condexec_mask)
7169
                    gen_op_addl_T0_T1();
7170
                else
7171
                    gen_op_addl_T0_T1_cc();
7172
            }
7173
            gen_movl_reg_T0(s, rd);
7174
        } else {
7175
            /* shift immediate */
7176
            rm = (insn >> 3) & 7;
7177
            shift = (insn >> 6) & 0x1f;
7178
            tmp = load_reg(s, rm);
7179
            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
7180
            if (!s->condexec_mask)
7181
                gen_logic_CC(tmp);
7182
            store_reg(s, rd, tmp);
7183
        }
7184
        break;
7185
    case 2: case 3:
7186
        /* arithmetic large immediate */
7187
        op = (insn >> 11) & 3;
7188
        rd = (insn >> 8) & 0x7;
7189
        if (op == 0) {
7190
            gen_op_movl_T0_im(insn & 0xff);
7191
        } else {
7192
            gen_movl_T0_reg(s, rd);
7193
            gen_op_movl_T1_im(insn & 0xff);
7194
        }
7195
        switch (op) {
7196
        case 0: /* mov */
7197
            if (!s->condexec_mask)
7198
                gen_op_logic_T0_cc();
7199
            break;
7200
        case 1: /* cmp */
7201
            gen_op_subl_T0_T1_cc();
7202
            break;
7203
        case 2: /* add */
7204
            if (s->condexec_mask)
7205
                gen_op_addl_T0_T1();
7206
            else
7207
                gen_op_addl_T0_T1_cc();
7208
            break;
7209
        case 3: /* sub */
7210
            if (s->condexec_mask)
7211
                gen_op_subl_T0_T1();
7212
            else
7213
                gen_op_subl_T0_T1_cc();
7214
            break;
7215
        }
7216
        if (op != 1)
7217
            gen_movl_reg_T0(s, rd);
7218
        break;
7219
    case 4:
7220
        if (insn & (1 << 11)) {
7221
            rd = (insn >> 8) & 7;
7222
            /* load pc-relative.  Bit 1 of PC is ignored.  */
7223
            val = s->pc + 2 + ((insn & 0xff) * 4);
7224
            val &= ~(uint32_t)2;
7225
            gen_op_movl_T1_im(val);
7226
            gen_ldst(ldl, s);
7227
            gen_movl_reg_T0(s, rd);
7228
            break;
7229
        }
7230
        if (insn & (1 << 10)) {
7231
            /* data processing extended or blx */
7232
            rd = (insn & 7) | ((insn >> 4) & 8);
7233
            rm = (insn >> 3) & 0xf;
7234
            op = (insn >> 8) & 3;
7235
            switch (op) {
7236
            case 0: /* add */
7237
                gen_movl_T0_reg(s, rd);
7238
                gen_movl_T1_reg(s, rm);
7239
                gen_op_addl_T0_T1();
7240
                gen_movl_reg_T0(s, rd);
7241
                break;
7242
            case 1: /* cmp */
7243
                gen_movl_T0_reg(s, rd);
7244
                gen_movl_T1_reg(s, rm);
7245
                gen_op_subl_T0_T1_cc();
7246
                break;
7247
            case 2: /* mov/cpy */
7248
                gen_movl_T0_reg(s, rm);
7249
                gen_movl_reg_T0(s, rd);
7250
                break;
7251
            case 3:/* branch [and link] exchange thumb register */
7252
                if (insn & (1 << 7)) {
7253
                    val = (uint32_t)s->pc | 1;
7254
                    gen_op_movl_T1_im(val);
7255
                    gen_movl_reg_T1(s, 14);
7256
                }
7257
                gen_movl_T0_reg(s, rm);
7258
                gen_bx(s);
7259
                break;
7260
            }
7261
            break;
7262
        }
7263

    
7264
        /* data processing register */
7265
        rd = insn & 7;
7266
        rm = (insn >> 3) & 7;
7267
        op = (insn >> 6) & 0xf;
7268
        if (op == 2 || op == 3 || op == 4 || op == 7) {
7269
            /* the shift/rotate ops want the operands backwards */
7270
            val = rm;
7271
            rm = rd;
7272
            rd = val;
7273
            val = 1;
7274
        } else {
7275
            val = 0;
7276
        }
7277

    
7278
        if (op == 9) /* neg */
7279
            gen_op_movl_T0_im(0);
7280
        else if (op != 0xf) /* mvn doesn't read its first operand */
7281
            gen_movl_T0_reg(s, rd);
7282

    
7283
        gen_movl_T1_reg(s, rm);
7284
        switch (op) {
7285
        case 0x0: /* and */
7286
            gen_op_andl_T0_T1();
7287
            if (!s->condexec_mask)
7288
                gen_op_logic_T0_cc();
7289
            break;
7290
        case 0x1: /* eor */
7291
            gen_op_xorl_T0_T1();
7292
            if (!s->condexec_mask)
7293
                gen_op_logic_T0_cc();
7294
            break;
7295
        case 0x2: /* lsl */
7296
            if (s->condexec_mask) {
7297
                gen_op_shll_T1_T0();
7298
            } else {
7299
                gen_op_shll_T1_T0_cc();
7300
                gen_op_logic_T1_cc();
7301
            }
7302
            break;
7303
        case 0x3: /* lsr */
7304
            if (s->condexec_mask) {
7305
                gen_op_shrl_T1_T0();
7306
            } else {
7307
                gen_op_shrl_T1_T0_cc();
7308
                gen_op_logic_T1_cc();
7309
            }
7310
            break;
7311
        case 0x4: /* asr */
7312
            if (s->condexec_mask) {
7313
                gen_op_sarl_T1_T0();
7314
            } else {
7315
                gen_op_sarl_T1_T0_cc();
7316
                gen_op_logic_T1_cc();
7317
            }
7318
            break;
7319
        case 0x5: /* adc */
7320
            if (s->condexec_mask)
7321
                gen_adc_T0_T1();
7322
            else
7323
                gen_op_adcl_T0_T1_cc();
7324
            break;
7325
        case 0x6: /* sbc */
7326
            if (s->condexec_mask)
7327
                gen_sbc_T0_T1();
7328
            else
7329
                gen_op_sbcl_T0_T1_cc();
7330
            break;
7331
        case 0x7: /* ror */
7332
            if (s->condexec_mask) {
7333
                gen_op_rorl_T1_T0();
7334
            } else {
7335
                gen_op_rorl_T1_T0_cc();
7336
                gen_op_logic_T1_cc();
7337
            }
7338
            break;
7339
        case 0x8: /* tst */
7340
            gen_op_andl_T0_T1();
7341
            gen_op_logic_T0_cc();
7342
            rd = 16;
7343
            break;
7344
        case 0x9: /* neg */
7345
            if (s->condexec_mask)
7346
                gen_op_subl_T0_T1();
7347
            else
7348
                gen_op_subl_T0_T1_cc();
7349
            break;
7350
        case 0xa: /* cmp */
7351
            gen_op_subl_T0_T1_cc();
7352
            rd = 16;
7353
            break;
7354
        case 0xb: /* cmn */
7355
            gen_op_addl_T0_T1_cc();
7356
            rd = 16;
7357
            break;
7358
        case 0xc: /* orr */
7359
            gen_op_orl_T0_T1();
7360
            if (!s->condexec_mask)
7361
                gen_op_logic_T0_cc();
7362
            break;
7363
        case 0xd: /* mul */
7364
            gen_op_mull_T0_T1();
7365
            if (!s->condexec_mask)
7366
                gen_op_logic_T0_cc();
7367
            break;
7368
        case 0xe: /* bic */
7369
            gen_op_bicl_T0_T1();
7370
            if (!s->condexec_mask)
7371
                gen_op_logic_T0_cc();
7372
            break;
7373
        case 0xf: /* mvn */
7374
            gen_op_notl_T1();
7375
            if (!s->condexec_mask)
7376
                gen_op_logic_T1_cc();
7377
            val = 1;
7378
            rm = rd;
7379
            break;
7380
        }
7381
        if (rd != 16) {
7382
            if (val)
7383
                gen_movl_reg_T1(s, rm);
7384
            else
7385
                gen_movl_reg_T0(s, rd);
7386
        }
7387
        break;
7388

    
7389
    case 5:
7390
        /* load/store register offset.  */
7391
        rd = insn & 7;
7392
        rn = (insn >> 3) & 7;
7393
        rm = (insn >> 6) & 7;
7394
        op = (insn >> 9) & 7;
7395
        gen_movl_T1_reg(s, rn);
7396
        tmp = load_reg(s, rm);
7397
        tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp);
7398
        dead_tmp(tmp);
7399

    
7400
        if (op < 3) /* store */
7401
            gen_movl_T0_reg(s, rd);
7402

    
7403
        switch (op) {
7404
        case 0: /* str */
7405
            gen_ldst(stl, s);
7406
            break;
7407
        case 1: /* strh */
7408
            gen_ldst(stw, s);
7409
            break;
7410
        case 2: /* strb */
7411
            gen_ldst(stb, s);
7412
            break;
7413
        case 3: /* ldrsb */
7414
            gen_ldst(ldsb, s);
7415
            break;
7416
        case 4: /* ldr */
7417
            gen_ldst(ldl, s);
7418
            break;
7419
        case 5: /* ldrh */
7420
            gen_ldst(lduw, s);
7421
            break;
7422
        case 6: /* ldrb */
7423
            gen_ldst(ldub, s);
7424
            break;
7425
        case 7: /* ldrsh */
7426
            gen_ldst(ldsw, s);
7427
            break;
7428
        }
7429
        if (op >= 3) /* load */
7430
            gen_movl_reg_T0(s, rd);
7431
        break;
7432

    
7433
    case 6:
7434
        /* load/store word immediate offset */
7435
        rd = insn & 7;
7436
        rn = (insn >> 3) & 7;
7437
        gen_movl_T1_reg(s, rn);
7438
        val = (insn >> 4) & 0x7c;
7439
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7440

    
7441
        if (insn & (1 << 11)) {
7442
            /* load */
7443
            gen_ldst(ldl, s);
7444
            gen_movl_reg_T0(s, rd);
7445
        } else {
7446
            /* store */
7447
            gen_movl_T0_reg(s, rd);
7448
            gen_ldst(stl, s);
7449
        }
7450
        break;
7451

    
7452
    case 7:
7453
        /* load/store byte immediate offset */
7454
        rd = insn & 7;
7455
        rn = (insn >> 3) & 7;
7456
        gen_movl_T1_reg(s, rn);
7457
        val = (insn >> 6) & 0x1f;
7458
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7459

    
7460
        if (insn & (1 << 11)) {
7461
            /* load */
7462
            gen_ldst(ldub, s);
7463
            gen_movl_reg_T0(s, rd);
7464
        } else {
7465
            /* store */
7466
            gen_movl_T0_reg(s, rd);
7467
            gen_ldst(stb, s);
7468
        }
7469
        break;
7470

    
7471
    case 8:
7472
        /* load/store halfword immediate offset */
7473
        rd = insn & 7;
7474
        rn = (insn >> 3) & 7;
7475
        gen_movl_T1_reg(s, rn);
7476
        val = (insn >> 5) & 0x3e;
7477
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7478

    
7479
        if (insn & (1 << 11)) {
7480
            /* load */
7481
            gen_ldst(lduw, s);
7482
            gen_movl_reg_T0(s, rd);
7483
        } else {
7484
            /* store */
7485
            gen_movl_T0_reg(s, rd);
7486
            gen_ldst(stw, s);
7487
        }
7488
        break;
7489

    
7490
    case 9:
7491
        /* load/store from stack */
7492
        rd = (insn >> 8) & 7;
7493
        gen_movl_T1_reg(s, 13);
7494
        val = (insn & 0xff) * 4;
7495
        tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val);
7496

    
7497
        if (insn & (1 << 11)) {
7498
            /* load */
7499
            gen_ldst(ldl, s);
7500
            gen_movl_reg_T0(s, rd);
7501
        } else {
7502
            /* store */
7503
            gen_movl_T0_reg(s, rd);
7504
            gen_ldst(stl, s);
7505
        }
7506
        break;
7507

    
7508
    case 10:
7509
        /* add to high reg */
7510
        rd = (insn >> 8) & 7;
7511
        if (insn & (1 << 11)) {
7512
            /* SP */
7513
            gen_movl_T0_reg(s, 13);
7514
        } else {
7515
            /* PC. bit 1 is ignored.  */
7516
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
7517
        }
7518
        val = (insn & 0xff) * 4;
7519
        gen_op_movl_T1_im(val);
7520
        gen_op_addl_T0_T1();
7521
        gen_movl_reg_T0(s, rd);
7522
        break;
7523

    
7524
    case 11:
7525
        /* misc */
7526
        op = (insn >> 8) & 0xf;
7527
        switch (op) {
7528
        case 0:
7529
            /* adjust stack pointer */
7530
            tmp = load_reg(s, 13);
7531
            val = (insn & 0x7f) * 4;
7532
            if (insn & (1 << 7))
7533
              val = -(int32_t)val;
7534
            tcg_gen_addi_i32(tmp, tmp, val);
7535
            store_reg(s, 13, tmp);
7536
            break;
7537

    
7538
        case 2: /* sign/zero extend.  */
7539
            ARCH(6);
7540
            rd = insn & 7;
7541
            rm = (insn >> 3) & 7;
7542
            gen_movl_T1_reg(s, rm);
7543
            switch ((insn >> 6) & 3) {
7544
            case 0: gen_sxth(cpu_T[1]); break;
7545
            case 1: gen_sxtb(cpu_T[1]); break;
7546
            case 2: gen_uxth(cpu_T[1]); break;
7547
            case 3: gen_uxtb(cpu_T[1]); break;
7548
            }
7549
            gen_movl_reg_T1(s, rd);
7550
            break;
7551
        case 4: case 5: case 0xc: case 0xd:
7552
            /* push/pop */
7553
            gen_movl_T1_reg(s, 13);
7554
            if (insn & (1 << 8))
7555
                offset = 4;
7556
            else
7557
                offset = 0;
7558
            for (i = 0; i < 8; i++) {
7559
                if (insn & (1 << i))
7560
                    offset += 4;
7561
            }
7562
            if ((insn & (1 << 11)) == 0) {
7563
                gen_op_addl_T1_im(-offset);
7564
            }
7565
            for (i = 0; i < 8; i++) {
7566
                if (insn & (1 << i)) {
7567
                    if (insn & (1 << 11)) {
7568
                        /* pop */
7569
                        gen_ldst(ldl, s);
7570
                        gen_movl_reg_T0(s, i);
7571
                    } else {
7572
                        /* push */
7573
                        gen_movl_T0_reg(s, i);
7574
                        gen_ldst(stl, s);
7575
                    }
7576
                    /* advance to the next address.  */
7577
                    gen_op_addl_T1_im(4);
7578
                }
7579
            }
7580
            if (insn & (1 << 8)) {
7581
                if (insn & (1 << 11)) {
7582
                    /* pop pc */
7583
                    gen_ldst(ldl, s);
7584
                    /* don't set the pc until the rest of the instruction
7585
                       has completed */
7586
                } else {
7587
                    /* push lr */
7588
                    gen_movl_T0_reg(s, 14);
7589
                    gen_ldst(stl, s);
7590
                }
7591
                gen_op_addl_T1_im(4);
7592
            }
7593
            if ((insn & (1 << 11)) == 0) {
7594
                gen_op_addl_T1_im(-offset);
7595
            }
7596
            /* write back the new stack pointer */
7597
            gen_movl_reg_T1(s, 13);
7598
            /* set the new PC value */
7599
            if ((insn & 0x0900) == 0x0900)
7600
                gen_bx(s);
7601
            break;
7602

    
7603
        case 1: case 3: case 9: case 11: /* czb */
7604
            rm = insn & 7;
7605
            gen_movl_T0_reg(s, rm);
7606
            s->condlabel = gen_new_label();
7607
            s->condjmp = 1;
7608
            if (insn & (1 << 11))
7609
                gen_op_testn_T0(s->condlabel);
7610
            else
7611
                gen_op_test_T0(s->condlabel);
7612

    
7613
            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
7614
            val = (uint32_t)s->pc + 2;
7615
            val += offset;
7616
            gen_jmp(s, val);
7617
            break;
7618

    
7619
        case 15: /* IT, nop-hint.  */
7620
            if ((insn & 0xf) == 0) {
7621
                gen_nop_hint(s, (insn >> 4) & 0xf);
7622
                break;
7623
            }
7624
            /* If Then.  */
7625
            s->condexec_cond = (insn >> 4) & 0xe;
7626
            s->condexec_mask = insn & 0x1f;
7627
            /* No actual code generated for this insn, just setup state.  */
7628
            break;
7629

    
7630
        case 0xe: /* bkpt */
7631
            gen_set_condexec(s);
7632
            gen_op_movl_T0_im((long)s->pc - 2);
7633
            gen_set_pc_T0();
7634
            gen_op_bkpt();
7635
            s->is_jmp = DISAS_JUMP;
7636
            break;
7637

    
7638
        case 0xa: /* rev */
7639
            ARCH(6);
7640
            rn = (insn >> 3) & 0x7;
7641
            rd = insn & 0x7;
7642
            gen_movl_T0_reg(s, rn);
7643
            switch ((insn >> 6) & 3) {
7644
            case 0: gen_op_rev_T0(); break;
7645
            case 1: gen_rev16(cpu_T[0]); break;
7646
            case 3: gen_revsh(cpu_T[0]); break;
7647
            default: goto illegal_op;
7648
            }
7649
            gen_movl_reg_T0(s, rd);
7650
            break;
7651

    
7652
        case 6: /* cps */
7653
            ARCH(6);
7654
            if (IS_USER(s))
7655
                break;
7656
            if (IS_M(env)) {
7657
                val = (insn & (1 << 4)) != 0;
7658
                gen_op_movl_T0_im(val);
7659
                /* PRIMASK */
7660
                if (insn & 1)
7661
                    gen_op_v7m_msr_T0(16);
7662
                /* FAULTMASK */
7663
                if (insn & 2)
7664
                    gen_op_v7m_msr_T0(17);
7665

    
7666
                gen_lookup_tb(s);
7667
            } else {
7668
                if (insn & (1 << 4))
7669
                    shift = CPSR_A | CPSR_I | CPSR_F;
7670
                else
7671
                    shift = 0;
7672

    
7673
                val = ((insn & 7) << 6) & shift;
7674
                gen_op_movl_T0_im(val);
7675
                gen_set_psr_T0(s, shift, 0);
7676
            }
7677
            break;
7678

    
7679
        default:
7680
            goto undef;
7681
        }
7682
        break;
7683

    
7684
    case 12:
7685
        /* load/store multiple */
7686
        rn = (insn >> 8) & 0x7;
7687
        gen_movl_T1_reg(s, rn);
7688
        for (i = 0; i < 8; i++) {
7689
            if (insn & (1 << i)) {
7690
                if (insn & (1 << 11)) {
7691
                    /* load */
7692
                    gen_ldst(ldl, s);
7693
                    gen_movl_reg_T0(s, i);
7694
                } else {
7695
                    /* store */
7696
                    gen_movl_T0_reg(s, i);
7697
                    gen_ldst(stl, s);
7698
                }
7699
                /* advance to the next address */
7700
                gen_op_addl_T1_im(4);
7701
            }
7702
        }
7703
        /* Base register writeback.  */
7704
        if ((insn & (1 << rn)) == 0)
7705
            gen_movl_reg_T1(s, rn);
7706
        break;
7707

    
7708
    case 13:
7709
        /* conditional branch or swi */
7710
        cond = (insn >> 8) & 0xf;
7711
        if (cond == 0xe)
7712
            goto undef;
7713

    
7714
        if (cond == 0xf) {
7715
            /* swi */
7716
            gen_set_condexec(s);
7717
            gen_op_movl_T0_im((long)s->pc | 1);
7718
            /* Don't set r15.  */
7719
            gen_set_pc_T0();
7720
            s->is_jmp = DISAS_SWI;
7721
            break;
7722
        }
7723
        /* generate a conditional jump to next instruction */
7724
        s->condlabel = gen_new_label();
7725
        gen_test_cc[cond ^ 1](s->condlabel);
7726
        s->condjmp = 1;
7727
        gen_movl_T1_reg(s, 15);
7728

    
7729
        /* jump to the offset */
7730
        val = (uint32_t)s->pc + 2;
7731
        offset = ((int32_t)insn << 24) >> 24;
7732
        val += offset << 1;
7733
        gen_jmp(s, val);
7734
        break;
7735

    
7736
    case 14:
7737
        if (insn & (1 << 11)) {
7738
            if (disas_thumb2_insn(env, s, insn))
7739
              goto undef32;
7740
            break;
7741
        }
7742
        /* unconditional branch */
7743
        val = (uint32_t)s->pc;
7744
        offset = ((int32_t)insn << 21) >> 21;
7745
        val += (offset << 1) + 2;
7746
        gen_jmp(s, val);
7747
        break;
7748

    
7749
    case 15:
7750
        if (disas_thumb2_insn(env, s, insn))
7751
          goto undef32;
7752
        break;
7753
    }
7754
    return;
7755
undef32:
7756
    gen_set_condexec(s);
7757
    gen_op_movl_T0_im((long)s->pc - 4);
7758
    gen_set_pc_T0();
7759
    gen_op_undef_insn();
7760
    s->is_jmp = DISAS_JUMP;
7761
    return;
7762
illegal_op:
7763
undef:
7764
    gen_set_condexec(s);
7765
    gen_op_movl_T0_im((long)s->pc - 2);
7766
    gen_set_pc_T0();
7767
    gen_op_undef_insn();
7768
    s->is_jmp = DISAS_JUMP;
7769
}
7770

    
7771
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
7772
   basic block 'tb'. If search_pc is TRUE, also generate PC
7773
   information for each intermediate instruction. */
7774
static inline int gen_intermediate_code_internal(CPUState *env,
7775
                                                 TranslationBlock *tb,
7776
                                                 int search_pc)
7777
{
7778
    DisasContext dc1, *dc = &dc1;
7779
    uint16_t *gen_opc_end;
7780
    int j, lj;
7781
    target_ulong pc_start;
7782
    uint32_t next_page_start;
7783

    
7784
    /* generate intermediate code */
7785
    num_temps = 0;
7786
    memset(temps, 0, sizeof(temps));
7787

    
7788
    pc_start = tb->pc;
7789

    
7790
    dc->tb = tb;
7791

    
7792
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7793

    
7794
    dc->is_jmp = DISAS_NEXT;
7795
    dc->pc = pc_start;
7796
    dc->singlestep_enabled = env->singlestep_enabled;
7797
    dc->condjmp = 0;
7798
    dc->thumb = env->thumb;
7799
    dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
7800
    dc->condexec_cond = env->condexec_bits >> 4;
7801
    dc->is_mem = 0;
7802
#if !defined(CONFIG_USER_ONLY)
7803
    if (IS_M(env)) {
7804
        dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
7805
    } else {
7806
        dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
7807
    }
7808
#endif
7809
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
7810
    lj = -1;
7811
    /* Reset the conditional execution bits immediately. This avoids
7812
       complications trying to do it at the end of the block.  */
7813
    if (env->condexec_bits)
7814
      {
7815
        TCGv tmp = new_tmp();
7816
        tcg_gen_movi_i32(tmp, 0);
7817
        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits));
7818
        dead_tmp(tmp);
7819
      }
7820
    do {
7821
#ifndef CONFIG_USER_ONLY
7822
        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
7823
            /* We always get here via a jump, so know we are not in a
7824
               conditional execution block.  */
7825
            gen_op_exception_exit();
7826
        }
7827
#endif
7828

    
7829
        if (env->nb_breakpoints > 0) {
7830
            for(j = 0; j < env->nb_breakpoints; j++) {
7831
                if (env->breakpoints[j] == dc->pc) {
7832
                    gen_set_condexec(dc);
7833
                    gen_op_movl_T0_im((long)dc->pc);
7834
                    gen_set_pc_T0();
7835
                    gen_op_debug();
7836
                    dc->is_jmp = DISAS_JUMP;
7837
                    /* Advance PC so that clearing the breakpoint will
7838
                       invalidate this TB.  */
7839
                    dc->pc += 2;
7840
                    goto done_generating;
7841
                    break;
7842
                }
7843
            }
7844
        }
7845
        if (search_pc) {
7846
            j = gen_opc_ptr - gen_opc_buf;
7847
            if (lj < j) {
7848
                lj++;
7849
                while (lj < j)
7850
                    gen_opc_instr_start[lj++] = 0;
7851
            }
7852
            gen_opc_pc[lj] = dc->pc;
7853
            gen_opc_instr_start[lj] = 1;
7854
        }
7855

    
7856
        if (env->thumb) {
7857
            disas_thumb_insn(env, dc);
7858
            if (dc->condexec_mask) {
7859
                dc->condexec_cond = (dc->condexec_cond & 0xe)
7860
                                   | ((dc->condexec_mask >> 4) & 1);
7861
                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
7862
                if (dc->condexec_mask == 0) {
7863
                    dc->condexec_cond = 0;
7864
                }
7865
            }
7866
        } else {
7867
            disas_arm_insn(env, dc);
7868
        }
7869
        if (num_temps) {
7870
            fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
7871
            num_temps = 0;
7872
        }
7873

    
7874
        if (dc->condjmp && !dc->is_jmp) {
7875
            gen_set_label(dc->condlabel);
7876
            dc->condjmp = 0;
7877
        }
7878
        /* Terminate the TB on memory ops if watchpoints are present.  */
7879
        /* FIXME: This should be replacd by the deterministic execution
7880
         * IRQ raising bits.  */
7881
        if (dc->is_mem && env->nb_watchpoints)
7882
            break;
7883

    
7884
        /* Translation stops when a conditional branch is enoutered.
7885
         * Otherwise the subsequent code could get translated several times.
7886
         * Also stop translation when a page boundary is reached.  This
7887
         * ensures prefech aborts occur at the right place.  */
7888
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
7889
             !env->singlestep_enabled &&
7890
             dc->pc < next_page_start);
7891

    
7892
    /* At this stage dc->condjmp will only be set when the skipped
7893
       instruction was a conditional branch or trap, and the PC has
7894
       already been written.  */
7895
    if (__builtin_expect(env->singlestep_enabled, 0)) {
7896
        /* Make sure the pc is updated, and raise a debug exception.  */
7897
        if (dc->condjmp) {
7898
            gen_set_condexec(dc);
7899
            if (dc->is_jmp == DISAS_SWI) {
7900
                gen_op_swi();
7901
            } else {
7902
                gen_op_debug();
7903
            }
7904
            gen_set_label(dc->condlabel);
7905
        }
7906
        if (dc->condjmp || !dc->is_jmp) {
7907
            gen_op_movl_T0_im((long)dc->pc);
7908
            gen_set_pc_T0();
7909
            dc->condjmp = 0;
7910
        }
7911
        gen_set_condexec(dc);
7912
        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
7913
            gen_op_swi();
7914
        } else {
7915
            /* FIXME: Single stepping a WFI insn will not halt
7916
               the CPU.  */
7917
            gen_op_debug();
7918
        }
7919
    } else {
7920
        /* While branches must always occur at the end of an IT block,
7921
           there are a few other things that can cause us to terminate
7922
           the TB in the middel of an IT block:
7923
            - Exception generating instructions (bkpt, swi, undefined).
7924
            - Page boundaries.
7925
            - Hardware watchpoints.
7926
           Hardware breakpoints have already been handled and skip this code.
7927
         */
7928
        gen_set_condexec(dc);
7929
        switch(dc->is_jmp) {
7930
        case DISAS_NEXT:
7931
            gen_goto_tb(dc, 1, dc->pc);
7932
            break;
7933
        default:
7934
        case DISAS_JUMP:
7935
        case DISAS_UPDATE:
7936
            /* indicate that the hash table must be used to find the next TB */
7937
            tcg_gen_exit_tb(0);
7938
            break;
7939
        case DISAS_TB_JUMP:
7940
            /* nothing more to generate */
7941
            break;
7942
        case DISAS_WFI:
7943
            gen_op_wfi();
7944
            break;
7945
        case DISAS_SWI:
7946
            gen_op_swi();
7947
            break;
7948
        }
7949
        if (dc->condjmp) {
7950
            gen_set_label(dc->condlabel);
7951
            gen_set_condexec(dc);
7952
            gen_goto_tb(dc, 1, dc->pc);
7953
            dc->condjmp = 0;
7954
        }
7955
    }
7956
done_generating:
7957
    *gen_opc_ptr = INDEX_op_end;
7958

    
7959
#ifdef DEBUG_DISAS
7960
    if (loglevel & CPU_LOG_TB_IN_ASM) {
7961
        fprintf(logfile, "----------------\n");
7962
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
7963
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
7964
        fprintf(logfile, "\n");
7965
    }
7966
#endif
7967
    if (search_pc) {
7968
        j = gen_opc_ptr - gen_opc_buf;
7969
        lj++;
7970
        while (lj <= j)
7971
            gen_opc_instr_start[lj++] = 0;
7972
    } else {
7973
        tb->size = dc->pc - pc_start;
7974
    }
7975
    return 0;
7976
}
7977

    
7978
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
7979
{
7980
    return gen_intermediate_code_internal(env, tb, 0);
7981
}
7982

    
7983
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
7984
{
7985
    return gen_intermediate_code_internal(env, tb, 1);
7986
}
7987

    
7988
static const char *cpu_mode_names[16] = {
7989
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
7990
  "???", "???", "???", "und", "???", "???", "???", "sys"
7991
};
7992

    
7993
void cpu_dump_state(CPUState *env, FILE *f,
7994
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7995
                    int flags)
7996
{
7997
    int i;
7998
    union {
7999
        uint32_t i;
8000
        float s;
8001
    } s0, s1;
8002
    CPU_DoubleU d;
8003
    /* ??? This assumes float64 and double have the same layout.
8004
       Oh well, it's only debug dumps.  */
8005
    union {
8006
        float64 f64;
8007
        double d;
8008
    } d0;
8009
    uint32_t psr;
8010

    
8011
    for(i=0;i<16;i++) {
8012
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
8013
        if ((i % 4) == 3)
8014
            cpu_fprintf(f, "\n");
8015
        else
8016
            cpu_fprintf(f, " ");
8017
    }
8018
    psr = cpsr_read(env);
8019
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
8020
                psr,
8021
                psr & (1 << 31) ? 'N' : '-',
8022
                psr & (1 << 30) ? 'Z' : '-',
8023
                psr & (1 << 29) ? 'C' : '-',
8024
                psr & (1 << 28) ? 'V' : '-',
8025
                psr & CPSR_T ? 'T' : 'A',
8026
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
8027

    
8028
    for (i = 0; i < 16; i++) {
8029
        d.d = env->vfp.regs[i];
8030
        s0.i = d.l.lower;
8031
        s1.i = d.l.upper;
8032
        d0.f64 = d.d;
8033
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
8034
                    i * 2, (int)s0.i, s0.s,
8035
                    i * 2 + 1, (int)s1.i, s1.s,
8036
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
8037
                    d0.d);
8038
    }
8039
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
8040
}
8041