Statistics
| Branch: | Revision:

root / target-arm / translate.c @ beb811bd

History | View | Annotate | Download (77.5 kB)

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

    
27
#include "cpu.h"
28
#include "exec-all.h"
29
#include "disas.h"
30

    
31
#define ENABLE_ARCH_5J  0
32
#define ENABLE_ARCH_6   1
33
#define ENABLE_ARCH_6T2 1
34

    
35
#define ARCH(x) if (!ENABLE_ARCH_##x) goto illegal_op;
36

    
37
/* internal defines */
38
typedef struct DisasContext {
39
    target_ulong pc;
40
    int is_jmp;
41
    /* Nonzero if this instruction has been conditionally skipped.  */
42
    int condjmp;
43
    /* The label that will be jumped to when the instruction is skipped.  */
44
    int condlabel;
45
    struct TranslationBlock *tb;
46
    int singlestep_enabled;
47
    int thumb;
48
    int is_mem;
49
#if !defined(CONFIG_USER_ONLY)
50
    int user;
51
#endif
52
} DisasContext;
53

    
54
#if defined(CONFIG_USER_ONLY)
55
#define IS_USER(s) 1
56
#else
57
#define IS_USER(s) (s->user)
58
#endif
59

    
60
#define DISAS_JUMP_NEXT 4
61

    
62
#ifdef USE_DIRECT_JUMP
63
#define TBPARAM(x)
64
#else
65
#define TBPARAM(x) (long)(x)
66
#endif
67

    
68
/* XXX: move that elsewhere */
69
static uint16_t *gen_opc_ptr;
70
static uint32_t *gen_opparam_ptr;
71
extern FILE *logfile;
72
extern int loglevel;
73

    
74
enum {
75
#define DEF(s, n, copy_size) INDEX_op_ ## s,
76
#include "opc.h"
77
#undef DEF
78
    NB_OPS,
79
};
80

    
81
#include "gen-op.h"
82

    
83
static GenOpFunc1 *gen_test_cc[14] = {
84
    gen_op_test_eq,
85
    gen_op_test_ne,
86
    gen_op_test_cs,
87
    gen_op_test_cc,
88
    gen_op_test_mi,
89
    gen_op_test_pl,
90
    gen_op_test_vs,
91
    gen_op_test_vc,
92
    gen_op_test_hi,
93
    gen_op_test_ls,
94
    gen_op_test_ge,
95
    gen_op_test_lt,
96
    gen_op_test_gt,
97
    gen_op_test_le,
98
};
99

    
100
const uint8_t table_logic_cc[16] = {
101
    1, /* and */
102
    1, /* xor */
103
    0, /* sub */
104
    0, /* rsb */
105
    0, /* add */
106
    0, /* adc */
107
    0, /* sbc */
108
    0, /* rsc */
109
    1, /* andl */
110
    1, /* xorl */
111
    0, /* cmp */
112
    0, /* cmn */
113
    1, /* orr */
114
    1, /* mov */
115
    1, /* bic */
116
    1, /* mvn */
117
};
118
    
119
static GenOpFunc1 *gen_shift_T1_im[4] = {
120
    gen_op_shll_T1_im,
121
    gen_op_shrl_T1_im,
122
    gen_op_sarl_T1_im,
123
    gen_op_rorl_T1_im,
124
};
125

    
126
static GenOpFunc *gen_shift_T1_0[4] = {
127
    NULL,
128
    gen_op_shrl_T1_0,
129
    gen_op_sarl_T1_0,
130
    gen_op_rrxl_T1,
131
};
132

    
133
static GenOpFunc1 *gen_shift_T2_im[4] = {
134
    gen_op_shll_T2_im,
135
    gen_op_shrl_T2_im,
136
    gen_op_sarl_T2_im,
137
    gen_op_rorl_T2_im,
138
};
139

    
140
static GenOpFunc *gen_shift_T2_0[4] = {
141
    NULL,
142
    gen_op_shrl_T2_0,
143
    gen_op_sarl_T2_0,
144
    gen_op_rrxl_T2,
145
};
146

    
147
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
148
    gen_op_shll_T1_im_cc,
149
    gen_op_shrl_T1_im_cc,
150
    gen_op_sarl_T1_im_cc,
151
    gen_op_rorl_T1_im_cc,
152
};
153

    
154
static GenOpFunc *gen_shift_T1_0_cc[4] = {
155
    NULL,
156
    gen_op_shrl_T1_0_cc,
157
    gen_op_sarl_T1_0_cc,
158
    gen_op_rrxl_T1_cc,
159
};
160

    
161
static GenOpFunc *gen_shift_T1_T0[4] = {
162
    gen_op_shll_T1_T0,
163
    gen_op_shrl_T1_T0,
164
    gen_op_sarl_T1_T0,
165
    gen_op_rorl_T1_T0,
166
};
167

    
168
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
169
    gen_op_shll_T1_T0_cc,
170
    gen_op_shrl_T1_T0_cc,
171
    gen_op_sarl_T1_T0_cc,
172
    gen_op_rorl_T1_T0_cc,
173
};
174

    
175
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
176
    {
177
        gen_op_movl_T0_r0,
178
        gen_op_movl_T0_r1,
179
        gen_op_movl_T0_r2,
180
        gen_op_movl_T0_r3,
181
        gen_op_movl_T0_r4,
182
        gen_op_movl_T0_r5,
183
        gen_op_movl_T0_r6,
184
        gen_op_movl_T0_r7,
185
        gen_op_movl_T0_r8,
186
        gen_op_movl_T0_r9,
187
        gen_op_movl_T0_r10,
188
        gen_op_movl_T0_r11,
189
        gen_op_movl_T0_r12,
190
        gen_op_movl_T0_r13,
191
        gen_op_movl_T0_r14,
192
        gen_op_movl_T0_r15,
193
    },
194
    {
195
        gen_op_movl_T1_r0,
196
        gen_op_movl_T1_r1,
197
        gen_op_movl_T1_r2,
198
        gen_op_movl_T1_r3,
199
        gen_op_movl_T1_r4,
200
        gen_op_movl_T1_r5,
201
        gen_op_movl_T1_r6,
202
        gen_op_movl_T1_r7,
203
        gen_op_movl_T1_r8,
204
        gen_op_movl_T1_r9,
205
        gen_op_movl_T1_r10,
206
        gen_op_movl_T1_r11,
207
        gen_op_movl_T1_r12,
208
        gen_op_movl_T1_r13,
209
        gen_op_movl_T1_r14,
210
        gen_op_movl_T1_r15,
211
    },
212
    {
213
        gen_op_movl_T2_r0,
214
        gen_op_movl_T2_r1,
215
        gen_op_movl_T2_r2,
216
        gen_op_movl_T2_r3,
217
        gen_op_movl_T2_r4,
218
        gen_op_movl_T2_r5,
219
        gen_op_movl_T2_r6,
220
        gen_op_movl_T2_r7,
221
        gen_op_movl_T2_r8,
222
        gen_op_movl_T2_r9,
223
        gen_op_movl_T2_r10,
224
        gen_op_movl_T2_r11,
225
        gen_op_movl_T2_r12,
226
        gen_op_movl_T2_r13,
227
        gen_op_movl_T2_r14,
228
        gen_op_movl_T2_r15,
229
    },
230
};
231

    
232
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
233
    {
234
        gen_op_movl_r0_T0,
235
        gen_op_movl_r1_T0,
236
        gen_op_movl_r2_T0,
237
        gen_op_movl_r3_T0,
238
        gen_op_movl_r4_T0,
239
        gen_op_movl_r5_T0,
240
        gen_op_movl_r6_T0,
241
        gen_op_movl_r7_T0,
242
        gen_op_movl_r8_T0,
243
        gen_op_movl_r9_T0,
244
        gen_op_movl_r10_T0,
245
        gen_op_movl_r11_T0,
246
        gen_op_movl_r12_T0,
247
        gen_op_movl_r13_T0,
248
        gen_op_movl_r14_T0,
249
        gen_op_movl_r15_T0,
250
    },
251
    {
252
        gen_op_movl_r0_T1,
253
        gen_op_movl_r1_T1,
254
        gen_op_movl_r2_T1,
255
        gen_op_movl_r3_T1,
256
        gen_op_movl_r4_T1,
257
        gen_op_movl_r5_T1,
258
        gen_op_movl_r6_T1,
259
        gen_op_movl_r7_T1,
260
        gen_op_movl_r8_T1,
261
        gen_op_movl_r9_T1,
262
        gen_op_movl_r10_T1,
263
        gen_op_movl_r11_T1,
264
        gen_op_movl_r12_T1,
265
        gen_op_movl_r13_T1,
266
        gen_op_movl_r14_T1,
267
        gen_op_movl_r15_T1,
268
    },
269
};
270

    
271
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
272
    gen_op_movl_T0_im,
273
    gen_op_movl_T1_im,
274
    gen_op_movl_T2_im,
275
};
276

    
277
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
278
    gen_op_shll_T0_im_thumb,
279
    gen_op_shrl_T0_im_thumb,
280
    gen_op_sarl_T0_im_thumb,
281
};
282

    
283
static inline void gen_bx(DisasContext *s)
284
{
285
  s->is_jmp = DISAS_UPDATE;
286
  gen_op_bx_T0();
287
}
288

    
289

    
290
#if defined(CONFIG_USER_ONLY)
291
#define gen_ldst(name, s) gen_op_##name##_raw()
292
#else
293
#define gen_ldst(name, s) do { \
294
    s->is_mem = 1; \
295
    if (IS_USER(s)) \
296
        gen_op_##name##_user(); \
297
    else \
298
        gen_op_##name##_kernel(); \
299
    } while (0)
300
#endif
301

    
302
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
303
{
304
    int val;
305

    
306
    if (reg == 15) {
307
        /* normaly, since we updated PC, we need only to add one insn */
308
        if (s->thumb)
309
            val = (long)s->pc + 2;
310
        else
311
            val = (long)s->pc + 4;
312
        gen_op_movl_TN_im[t](val);
313
    } else {
314
        gen_op_movl_TN_reg[t][reg]();
315
    }
316
}
317

    
318
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
319
{
320
    gen_movl_TN_reg(s, reg, 0);
321
}
322

    
323
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
324
{
325
    gen_movl_TN_reg(s, reg, 1);
326
}
327

    
328
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
329
{
330
    gen_movl_TN_reg(s, reg, 2);
331
}
332

    
333
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
334
{
335
    gen_op_movl_reg_TN[t][reg]();
336
    if (reg == 15) {
337
        s->is_jmp = DISAS_JUMP;
338
    }
339
}
340

    
341
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
342
{
343
    gen_movl_reg_TN(s, reg, 0);
344
}
345

    
346
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
347
{
348
    gen_movl_reg_TN(s, reg, 1);
349
}
350

    
351
/* Force a TB lookup after an instruction that changes the CPU state.  */
352
static inline void gen_lookup_tb(DisasContext *s)
353
{
354
    gen_op_movl_T0_im(s->pc);
355
    gen_movl_reg_T0(s, 15);
356
    s->is_jmp = DISAS_UPDATE;
357
}
358

    
359
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
360
{
361
    int val, rm, shift, shiftop;
362

    
363
    if (!(insn & (1 << 25))) {
364
        /* immediate */
365
        val = insn & 0xfff;
366
        if (!(insn & (1 << 23)))
367
            val = -val;
368
        if (val != 0)
369
            gen_op_addl_T1_im(val);
370
    } else {
371
        /* shift/register */
372
        rm = (insn) & 0xf;
373
        shift = (insn >> 7) & 0x1f;
374
        gen_movl_T2_reg(s, rm);
375
        shiftop = (insn >> 5) & 3;
376
        if (shift != 0) {
377
            gen_shift_T2_im[shiftop](shift);
378
        } else if (shiftop != 0) {
379
            gen_shift_T2_0[shiftop]();
380
        }
381
        if (!(insn & (1 << 23)))
382
            gen_op_subl_T1_T2();
383
        else
384
            gen_op_addl_T1_T2();
385
    }
386
}
387

    
388
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
389
                                        int extra)
390
{
391
    int val, rm;
392
    
393
    if (insn & (1 << 22)) {
394
        /* immediate */
395
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
396
        if (!(insn & (1 << 23)))
397
            val = -val;
398
        val += extra;
399
        if (val != 0)
400
            gen_op_addl_T1_im(val);
401
    } else {
402
        /* register */
403
        if (extra)
404
            gen_op_addl_T1_im(extra);
405
        rm = (insn) & 0xf;
406
        gen_movl_T2_reg(s, rm);
407
        if (!(insn & (1 << 23)))
408
            gen_op_subl_T1_T2();
409
        else
410
            gen_op_addl_T1_T2();
411
    }
412
}
413

    
414
#define VFP_OP(name)                      \
415
static inline void gen_vfp_##name(int dp) \
416
{                                         \
417
    if (dp)                               \
418
        gen_op_vfp_##name##d();           \
419
    else                                  \
420
        gen_op_vfp_##name##s();           \
421
}
422

    
423
VFP_OP(add)
424
VFP_OP(sub)
425
VFP_OP(mul)
426
VFP_OP(div)
427
VFP_OP(neg)
428
VFP_OP(abs)
429
VFP_OP(sqrt)
430
VFP_OP(cmp)
431
VFP_OP(cmpe)
432
VFP_OP(F1_ld0)
433
VFP_OP(uito)
434
VFP_OP(sito)
435
VFP_OP(toui)
436
VFP_OP(touiz)
437
VFP_OP(tosi)
438
VFP_OP(tosiz)
439

    
440
#undef VFP_OP
441

    
442
static inline void gen_vfp_ld(DisasContext *s, int dp)
443
{
444
    if (dp)
445
        gen_ldst(vfp_ldd, s);
446
    else
447
        gen_ldst(vfp_lds, s);
448
}
449

    
450
static inline void gen_vfp_st(DisasContext *s, int dp)
451
{
452
    if (dp)
453
        gen_ldst(vfp_std, s);
454
    else
455
        gen_ldst(vfp_sts, s);
456
}
457

    
458
static inline long
459
vfp_reg_offset (int dp, int reg)
460
{
461
    if (dp)
462
        return offsetof(CPUARMState, vfp.regs[reg]);
463
    else if (reg & 1) {
464
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
465
          + offsetof(CPU_DoubleU, l.upper);
466
    } else {
467
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
468
          + offsetof(CPU_DoubleU, l.lower);
469
    }
470
}
471
static inline void gen_mov_F0_vreg(int dp, int reg)
472
{
473
    if (dp)
474
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
475
    else
476
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
477
}
478

    
479
static inline void gen_mov_F1_vreg(int dp, int reg)
480
{
481
    if (dp)
482
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
483
    else
484
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
485
}
486

    
487
static inline void gen_mov_vreg_F0(int dp, int reg)
488
{
489
    if (dp)
490
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
491
    else
492
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
493
}
494

    
495
/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
496
   instruction is not defined.  */
497
static int disas_cp15_insn(DisasContext *s, uint32_t insn)
498
{
499
    uint32_t rd;
500

    
501
    /* ??? Some cp15 registers are accessible from userspace.  */
502
    if (IS_USER(s)) {
503
        return 1;
504
    }
505
    if ((insn & 0x0fff0fff) == 0x0e070f90
506
        || (insn & 0x0fff0fff) == 0x0e070f58) {
507
        /* Wait for interrupt.  */
508
        gen_op_movl_T0_im((long)s->pc);
509
        gen_op_movl_reg_TN[0][15]();
510
        gen_op_wfi();
511
        s->is_jmp = DISAS_JUMP;
512
        return 0;
513
    }
514
    rd = (insn >> 12) & 0xf;
515
    if (insn & (1 << 20)) {
516
        gen_op_movl_T0_cp15(insn);
517
        /* If the destination register is r15 then sets condition codes.  */
518
        if (rd != 15)
519
            gen_movl_reg_T0(s, rd);
520
    } else {
521
        gen_movl_T0_reg(s, rd);
522
        gen_op_movl_cp15_T0(insn);
523
    }
524
    gen_lookup_tb(s);
525
    return 0;
526
}
527

    
528
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
529
   (ie. an undefined instruction).  */
530
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
531
{
532
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
533
    int dp, veclen;
534

    
535
    if (!arm_feature(env, ARM_FEATURE_VFP))
536
        return 1;
537

    
538
    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
539
        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */
540
        if ((insn & 0x0fe00fff) != 0x0ee00a10)
541
            return 1;
542
        rn = (insn >> 16) & 0xf;
543
        if (rn != 0 && rn != 8)
544
            return 1;
545
    }
546
    dp = ((insn & 0xf00) == 0xb00);
547
    switch ((insn >> 24) & 0xf) {
548
    case 0xe:
549
        if (insn & (1 << 4)) {
550
            /* single register transfer */
551
            if ((insn & 0x6f) != 0x00)
552
                return 1;
553
            rd = (insn >> 12) & 0xf;
554
            if (dp) {
555
                if (insn & 0x80)
556
                    return 1;
557
                rn = (insn >> 16) & 0xf;
558
                /* Get the existing value even for arm->vfp moves because
559
                   we only set half the register.  */
560
                gen_mov_F0_vreg(1, rn);
561
                gen_op_vfp_mrrd();
562
                if (insn & (1 << 20)) {
563
                    /* vfp->arm */
564
                    if (insn & (1 << 21))
565
                        gen_movl_reg_T1(s, rd);
566
                    else
567
                        gen_movl_reg_T0(s, rd);
568
                } else {
569
                    /* arm->vfp */
570
                    if (insn & (1 << 21))
571
                        gen_movl_T1_reg(s, rd);
572
                    else
573
                        gen_movl_T0_reg(s, rd);
574
                    gen_op_vfp_mdrr();
575
                    gen_mov_vreg_F0(dp, rn);
576
                }
577
            } else {
578
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
579
                if (insn & (1 << 20)) {
580
                    /* vfp->arm */
581
                    if (insn & (1 << 21)) {
582
                        /* system register */
583
                        rn >>= 1;
584
                        switch (rn) {
585
                        case ARM_VFP_FPSID:
586
                        case ARM_VFP_FPEXC:
587
                        case ARM_VFP_FPINST:
588
                        case ARM_VFP_FPINST2:
589
                            gen_op_vfp_movl_T0_xreg(rn);
590
                            break;
591
                        case ARM_VFP_FPSCR:
592
                            if (rd == 15)
593
                                gen_op_vfp_movl_T0_fpscr_flags();
594
                            else
595
                                gen_op_vfp_movl_T0_fpscr();
596
                            break;
597
                        default:
598
                            return 1;
599
                        }
600
                    } else {
601
                        gen_mov_F0_vreg(0, rn);
602
                        gen_op_vfp_mrs();
603
                    }
604
                    if (rd == 15) {
605
                        /* Set the 4 flag bits in the CPSR.  */
606
                        gen_op_movl_cpsr_T0(0xf0000000);
607
                    } else
608
                        gen_movl_reg_T0(s, rd);
609
                } else {
610
                    /* arm->vfp */
611
                    gen_movl_T0_reg(s, rd);
612
                    if (insn & (1 << 21)) {
613
                        rn >>= 1;
614
                        /* system register */
615
                        switch (rn) {
616
                        case ARM_VFP_FPSID:
617
                            /* Writes are ignored.  */
618
                            break;
619
                        case ARM_VFP_FPSCR:
620
                            gen_op_vfp_movl_fpscr_T0();
621
                            gen_lookup_tb(s);
622
                            break;
623
                        case ARM_VFP_FPEXC:
624
                            gen_op_vfp_movl_xreg_T0(rn);
625
                            gen_lookup_tb(s);
626
                            break;
627
                        case ARM_VFP_FPINST:
628
                        case ARM_VFP_FPINST2:
629
                            gen_op_vfp_movl_xreg_T0(rn);
630
                            break;
631
                        default:
632
                            return 1;
633
                        }
634
                    } else {
635
                        gen_op_vfp_msr();
636
                        gen_mov_vreg_F0(0, rn);
637
                    }
638
                }
639
            }
640
        } else {
641
            /* data processing */
642
            /* The opcode is in bits 23, 21, 20 and 6.  */
643
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
644
            if (dp) {
645
                if (op == 15) {
646
                    /* rn is opcode */
647
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
648
                } else {
649
                    /* rn is register number */
650
                    if (insn & (1 << 7))
651
                        return 1;
652
                    rn = (insn >> 16) & 0xf;
653
                }
654

    
655
                if (op == 15 && (rn == 15 || rn > 17)) {
656
                    /* Integer or single precision destination.  */
657
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
658
                } else {
659
                    if (insn & (1 << 22))
660
                        return 1;
661
                    rd = (insn >> 12) & 0xf;
662
                }
663

    
664
                if (op == 15 && (rn == 16 || rn == 17)) {
665
                    /* Integer source.  */
666
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
667
                } else {
668
                    if (insn & (1 << 5))
669
                        return 1;
670
                    rm = insn & 0xf;
671
                }
672
            } else {
673
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
674
                if (op == 15 && rn == 15) {
675
                    /* Double precision destination.  */
676
                    if (insn & (1 << 22))
677
                        return 1;
678
                    rd = (insn >> 12) & 0xf;
679
                } else
680
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
681
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
682
            }
683

    
684
            veclen = env->vfp.vec_len;
685
            if (op == 15 && rn > 3)
686
                veclen = 0;
687

    
688
            /* Shut up compiler warnings.  */
689
            delta_m = 0;
690
            delta_d = 0;
691
            bank_mask = 0;
692
            
693
            if (veclen > 0) {
694
                if (dp)
695
                    bank_mask = 0xc;
696
                else
697
                    bank_mask = 0x18;
698

    
699
                /* Figure out what type of vector operation this is.  */
700
                if ((rd & bank_mask) == 0) {
701
                    /* scalar */
702
                    veclen = 0;
703
                } else {
704
                    if (dp)
705
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
706
                    else
707
                        delta_d = env->vfp.vec_stride + 1;
708

    
709
                    if ((rm & bank_mask) == 0) {
710
                        /* mixed scalar/vector */
711
                        delta_m = 0;
712
                    } else {
713
                        /* vector */
714
                        delta_m = delta_d;
715
                    }
716
                }
717
            }
718

    
719
            /* Load the initial operands.  */
720
            if (op == 15) {
721
                switch (rn) {
722
                case 16:
723
                case 17:
724
                    /* Integer source */
725
                    gen_mov_F0_vreg(0, rm);
726
                    break;
727
                case 8:
728
                case 9:
729
                    /* Compare */
730
                    gen_mov_F0_vreg(dp, rd);
731
                    gen_mov_F1_vreg(dp, rm);
732
                    break;
733
                case 10:
734
                case 11:
735
                    /* Compare with zero */
736
                    gen_mov_F0_vreg(dp, rd);
737
                    gen_vfp_F1_ld0(dp);
738
                    break;
739
                default:
740
                    /* One source operand.  */
741
                    gen_mov_F0_vreg(dp, rm);
742
                }
743
            } else {
744
                /* Two source operands.  */
745
                gen_mov_F0_vreg(dp, rn);
746
                gen_mov_F1_vreg(dp, rm);
747
            }
748

    
749
            for (;;) {
750
                /* Perform the calculation.  */
751
                switch (op) {
752
                case 0: /* mac: fd + (fn * fm) */
753
                    gen_vfp_mul(dp);
754
                    gen_mov_F1_vreg(dp, rd);
755
                    gen_vfp_add(dp);
756
                    break;
757
                case 1: /* nmac: fd - (fn * fm) */
758
                    gen_vfp_mul(dp);
759
                    gen_vfp_neg(dp);
760
                    gen_mov_F1_vreg(dp, rd);
761
                    gen_vfp_add(dp);
762
                    break;
763
                case 2: /* msc: -fd + (fn * fm) */
764
                    gen_vfp_mul(dp);
765
                    gen_mov_F1_vreg(dp, rd);
766
                    gen_vfp_sub(dp);
767
                    break;
768
                case 3: /* nmsc: -fd - (fn * fm)  */
769
                    gen_vfp_mul(dp);
770
                    gen_mov_F1_vreg(dp, rd);
771
                    gen_vfp_add(dp);
772
                    gen_vfp_neg(dp);
773
                    break;
774
                case 4: /* mul: fn * fm */
775
                    gen_vfp_mul(dp);
776
                    break;
777
                case 5: /* nmul: -(fn * fm) */
778
                    gen_vfp_mul(dp);
779
                    gen_vfp_neg(dp);
780
                    break;
781
                case 6: /* add: fn + fm */
782
                    gen_vfp_add(dp);
783
                    break;
784
                case 7: /* sub: fn - fm */
785
                    gen_vfp_sub(dp);
786
                    break;
787
                case 8: /* div: fn / fm */
788
                    gen_vfp_div(dp);
789
                    break;
790
                case 15: /* extension space */
791
                    switch (rn) {
792
                    case 0: /* cpy */
793
                        /* no-op */
794
                        break;
795
                    case 1: /* abs */
796
                        gen_vfp_abs(dp);
797
                        break;
798
                    case 2: /* neg */
799
                        gen_vfp_neg(dp);
800
                        break;
801
                    case 3: /* sqrt */
802
                        gen_vfp_sqrt(dp);
803
                        break;
804
                    case 8: /* cmp */
805
                        gen_vfp_cmp(dp);
806
                        break;
807
                    case 9: /* cmpe */
808
                        gen_vfp_cmpe(dp);
809
                        break;
810
                    case 10: /* cmpz */
811
                        gen_vfp_cmp(dp);
812
                        break;
813
                    case 11: /* cmpez */
814
                        gen_vfp_F1_ld0(dp);
815
                        gen_vfp_cmpe(dp);
816
                        break;
817
                    case 15: /* single<->double conversion */
818
                        if (dp)
819
                            gen_op_vfp_fcvtsd();
820
                        else
821
                            gen_op_vfp_fcvtds();
822
                        break;
823
                    case 16: /* fuito */
824
                        gen_vfp_uito(dp);
825
                        break;
826
                    case 17: /* fsito */
827
                        gen_vfp_sito(dp);
828
                        break;
829
                    case 24: /* ftoui */
830
                        gen_vfp_toui(dp);
831
                        break;
832
                    case 25: /* ftouiz */
833
                        gen_vfp_touiz(dp);
834
                        break;
835
                    case 26: /* ftosi */
836
                        gen_vfp_tosi(dp);
837
                        break;
838
                    case 27: /* ftosiz */
839
                        gen_vfp_tosiz(dp);
840
                        break;
841
                    default: /* undefined */
842
                        printf ("rn:%d\n", rn);
843
                        return 1;
844
                    }
845
                    break;
846
                default: /* undefined */
847
                    printf ("op:%d\n", op);
848
                    return 1;
849
                }
850

    
851
                /* Write back the result.  */
852
                if (op == 15 && (rn >= 8 && rn <= 11))
853
                    ; /* Comparison, do nothing.  */
854
                else if (op == 15 && rn > 17)
855
                    /* Integer result.  */
856
                    gen_mov_vreg_F0(0, rd);
857
                else if (op == 15 && rn == 15)
858
                    /* conversion */
859
                    gen_mov_vreg_F0(!dp, rd);
860
                else
861
                    gen_mov_vreg_F0(dp, rd);
862

    
863
                /* break out of the loop if we have finished  */
864
                if (veclen == 0)
865
                    break;
866

    
867
                if (op == 15 && delta_m == 0) {
868
                    /* single source one-many */
869
                    while (veclen--) {
870
                        rd = ((rd + delta_d) & (bank_mask - 1))
871
                             | (rd & bank_mask);
872
                        gen_mov_vreg_F0(dp, rd);
873
                    }
874
                    break;
875
                }
876
                /* Setup the next operands.  */
877
                veclen--;
878
                rd = ((rd + delta_d) & (bank_mask - 1))
879
                     | (rd & bank_mask);
880

    
881
                if (op == 15) {
882
                    /* One source operand.  */
883
                    rm = ((rm + delta_m) & (bank_mask - 1))
884
                         | (rm & bank_mask);
885
                    gen_mov_F0_vreg(dp, rm);
886
                } else {
887
                    /* Two source operands.  */
888
                    rn = ((rn + delta_d) & (bank_mask - 1))
889
                         | (rn & bank_mask);
890
                    gen_mov_F0_vreg(dp, rn);
891
                    if (delta_m) {
892
                        rm = ((rm + delta_m) & (bank_mask - 1))
893
                             | (rm & bank_mask);
894
                        gen_mov_F1_vreg(dp, rm);
895
                    }
896
                }
897
            }
898
        }
899
        break;
900
    case 0xc:
901
    case 0xd:
902
        if (dp && (insn & (1 << 22))) {
903
            /* two-register transfer */
904
            rn = (insn >> 16) & 0xf;
905
            rd = (insn >> 12) & 0xf;
906
            if (dp) {
907
                if (insn & (1 << 5))
908
                    return 1;
909
                rm = insn & 0xf;
910
            } else
911
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
912

    
913
            if (insn & (1 << 20)) {
914
                /* vfp->arm */
915
                if (dp) {
916
                    gen_mov_F0_vreg(1, rm);
917
                    gen_op_vfp_mrrd();
918
                    gen_movl_reg_T0(s, rd);
919
                    gen_movl_reg_T1(s, rn);
920
                } else {
921
                    gen_mov_F0_vreg(0, rm);
922
                    gen_op_vfp_mrs();
923
                    gen_movl_reg_T0(s, rn);
924
                    gen_mov_F0_vreg(0, rm + 1);
925
                    gen_op_vfp_mrs();
926
                    gen_movl_reg_T0(s, rd);
927
                }
928
            } else {
929
                /* arm->vfp */
930
                if (dp) {
931
                    gen_movl_T0_reg(s, rd);
932
                    gen_movl_T1_reg(s, rn);
933
                    gen_op_vfp_mdrr();
934
                    gen_mov_vreg_F0(1, rm);
935
                } else {
936
                    gen_movl_T0_reg(s, rn);
937
                    gen_op_vfp_msr();
938
                    gen_mov_vreg_F0(0, rm);
939
                    gen_movl_T0_reg(s, rd);
940
                    gen_op_vfp_msr();
941
                    gen_mov_vreg_F0(0, rm + 1);
942
                }
943
            }
944
        } else {
945
            /* Load/store */
946
            rn = (insn >> 16) & 0xf;
947
            if (dp)
948
                rd = (insn >> 12) & 0xf;
949
            else
950
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
951
            gen_movl_T1_reg(s, rn);
952
            if ((insn & 0x01200000) == 0x01000000) {
953
                /* Single load/store */
954
                offset = (insn & 0xff) << 2;
955
                if ((insn & (1 << 23)) == 0)
956
                    offset = -offset;
957
                gen_op_addl_T1_im(offset);
958
                if (insn & (1 << 20)) {
959
                    gen_vfp_ld(s, dp);
960
                    gen_mov_vreg_F0(dp, rd);
961
                } else {
962
                    gen_mov_F0_vreg(dp, rd);
963
                    gen_vfp_st(s, dp);
964
                }
965
            } else {
966
                /* load/store multiple */
967
                if (dp)
968
                    n = (insn >> 1) & 0x7f;
969
                else
970
                    n = insn & 0xff;
971

    
972
                if (insn & (1 << 24)) /* pre-decrement */
973
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
974

    
975
                if (dp)
976
                    offset = 8;
977
                else
978
                    offset = 4;
979
                for (i = 0; i < n; i++) {
980
                    if (insn & (1 << 20)) {
981
                        /* load */
982
                        gen_vfp_ld(s, dp);
983
                        gen_mov_vreg_F0(dp, rd + i);
984
                    } else {
985
                        /* store */
986
                        gen_mov_F0_vreg(dp, rd + i);
987
                        gen_vfp_st(s, dp);
988
                    }
989
                    gen_op_addl_T1_im(offset);
990
                }
991
                if (insn & (1 << 21)) {
992
                    /* writeback */
993
                    if (insn & (1 << 24))
994
                        offset = -offset * n;
995
                    else if (dp && (insn & 1))
996
                        offset = 4;
997
                    else
998
                        offset = 0;
999

    
1000
                    if (offset != 0)
1001
                        gen_op_addl_T1_im(offset);
1002
                    gen_movl_reg_T1(s, rn);
1003
                }
1004
            }
1005
        }
1006
        break;
1007
    default:
1008
        /* Should never happen.  */
1009
        return 1;
1010
    }
1011
    return 0;
1012
}
1013

    
1014
static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
1015
{
1016
    TranslationBlock *tb;
1017

    
1018
    tb = s->tb;
1019
    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
1020
        if (n == 0)
1021
            gen_op_goto_tb0(TBPARAM(tb));
1022
        else
1023
            gen_op_goto_tb1(TBPARAM(tb));
1024
        gen_op_movl_T0_im(dest);
1025
        gen_op_movl_r15_T0();
1026
        gen_op_movl_T0_im((long)tb + n);
1027
        gen_op_exit_tb();
1028
    } else {
1029
        gen_op_movl_T0_im(dest);
1030
        gen_op_movl_r15_T0();
1031
        gen_op_movl_T0_0();
1032
        gen_op_exit_tb();
1033
    }
1034
}
1035

    
1036
static inline void gen_jmp (DisasContext *s, uint32_t dest)
1037
{
1038
    if (__builtin_expect(s->singlestep_enabled, 0)) {
1039
        /* An indirect jump so that we still trigger the debug exception.  */
1040
        if (s->thumb)
1041
          dest |= 1;
1042
        gen_op_movl_T0_im(dest);
1043
        gen_bx(s);
1044
    } else {
1045
        gen_goto_tb(s, 0, dest);
1046
        s->is_jmp = DISAS_TB_JUMP;
1047
    }
1048
}
1049

    
1050
static inline void gen_mulxy(int x, int y)
1051
{
1052
    if (x)
1053
        gen_op_sarl_T0_im(16);
1054
    else
1055
        gen_op_sxth_T0();
1056
    if (y)
1057
        gen_op_sarl_T1_im(16);
1058
    else
1059
        gen_op_sxth_T1();
1060
    gen_op_mul_T0_T1();
1061
}
1062

    
1063
/* Return the mask of PSR bits set by a MSR instruction.  */
1064
static uint32_t msr_mask(DisasContext *s, int flags, int spsr) {
1065
    uint32_t mask;
1066

    
1067
    mask = 0;
1068
    if (flags & (1 << 0))
1069
        mask |= 0xff;
1070
    if (flags & (1 << 1))
1071
        mask |= 0xff00;
1072
    if (flags & (1 << 2))
1073
        mask |= 0xff0000;
1074
    if (flags & (1 << 3))
1075
        mask |= 0xff000000;
1076
    /* Mask out undefined bits.  */
1077
    mask &= 0xf90f03ff;
1078
    /* Mask out state bits.  */
1079
    if (!spsr)
1080
        mask &= ~0x01000020;
1081
    /* Mask out privileged bits.  */
1082
    if (IS_USER(s))
1083
        mask &= 0xf80f0200;
1084
    return mask;
1085
}
1086

    
1087
/* Returns nonzero if access to the PSR is not permitted.  */
1088
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr)
1089
{
1090
    if (spsr) {
1091
        /* ??? This is also undefined in system mode.  */
1092
        if (IS_USER(s))
1093
            return 1;
1094
        gen_op_movl_spsr_T0(mask);
1095
    } else {
1096
        gen_op_movl_cpsr_T0(mask);
1097
    }
1098
    gen_lookup_tb(s);
1099
    return 0;
1100
}
1101

    
1102
static void gen_exception_return(DisasContext *s)
1103
{
1104
    gen_op_movl_reg_TN[0][15]();
1105
    gen_op_movl_T0_spsr();
1106
    gen_op_movl_cpsr_T0(0xffffffff);
1107
    s->is_jmp = DISAS_UPDATE;
1108
}
1109

    
1110
static void disas_arm_insn(CPUState * env, DisasContext *s)
1111
{
1112
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
1113
    
1114
    insn = ldl_code(s->pc);
1115
    s->pc += 4;
1116
    
1117
    cond = insn >> 28;
1118
    if (cond == 0xf){
1119
        /* Unconditional instructions.  */
1120
        if ((insn & 0x0d70f000) == 0x0550f000)
1121
            return; /* PLD */
1122
        else if ((insn & 0x0e000000) == 0x0a000000) {
1123
            /* branch link and change to thumb (blx <offset>) */
1124
            int32_t offset;
1125

    
1126
            val = (uint32_t)s->pc;
1127
            gen_op_movl_T0_im(val);
1128
            gen_movl_reg_T0(s, 14);
1129
            /* Sign-extend the 24-bit offset */
1130
            offset = (((int32_t)insn) << 8) >> 8;
1131
            /* offset * 4 + bit24 * 2 + (thumb bit) */
1132
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
1133
            /* pipeline offset */
1134
            val += 4;
1135
            gen_op_movl_T0_im(val);
1136
            gen_bx(s);
1137
            return;
1138
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
1139
            /* Coprocessor double register transfer.  */
1140
        } else if ((insn & 0x0f000010) == 0x0e000010) {
1141
            /* Additional coprocessor register transfer.  */
1142
        } else if ((insn & 0x0ff10010) == 0x01000000) {
1143
            /* cps (privileged) */
1144
        } else if ((insn & 0x0ffffdff) == 0x01010000) {
1145
            /* setend */
1146
            if (insn & (1 << 9)) {
1147
                /* BE8 mode not implemented.  */
1148
                goto illegal_op;
1149
            }
1150
            return;
1151
        }
1152
        goto illegal_op;
1153
    }
1154
    if (cond != 0xe) {
1155
        /* if not always execute, we generate a conditional jump to
1156
           next instruction */
1157
        s->condlabel = gen_new_label();
1158
        gen_test_cc[cond ^ 1](s->condlabel);
1159
        s->condjmp = 1;
1160
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1161
        //s->is_jmp = DISAS_JUMP_NEXT;
1162
    }
1163
    if ((insn & 0x0f900000) == 0x03000000) {
1164
        if ((insn & 0x0fb0f000) != 0x0320f000)
1165
            goto illegal_op;
1166
        /* CPSR = immediate */
1167
        val = insn & 0xff;
1168
        shift = ((insn >> 8) & 0xf) * 2;
1169
        if (shift)
1170
            val = (val >> shift) | (val << (32 - shift));
1171
        gen_op_movl_T0_im(val);
1172
        i = ((insn & (1 << 22)) != 0);
1173
        if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1174
            goto illegal_op;
1175
    } else if ((insn & 0x0f900000) == 0x01000000
1176
               && (insn & 0x00000090) != 0x00000090) {
1177
        /* miscellaneous instructions */
1178
        op1 = (insn >> 21) & 3;
1179
        sh = (insn >> 4) & 0xf;
1180
        rm = insn & 0xf;
1181
        switch (sh) {
1182
        case 0x0: /* move program status register */
1183
            if (op1 & 1) {
1184
                /* PSR = reg */
1185
                gen_movl_T0_reg(s, rm);
1186
                i = ((op1 & 2) != 0);
1187
                if (gen_set_psr_T0(s, msr_mask(s, (insn >> 16) & 0xf, i), i))
1188
                    goto illegal_op;
1189
            } else {
1190
                /* reg = PSR */
1191
                rd = (insn >> 12) & 0xf;
1192
                if (op1 & 2) {
1193
                    if (IS_USER(s))
1194
                        goto illegal_op;
1195
                    gen_op_movl_T0_spsr();
1196
                } else {
1197
                    gen_op_movl_T0_cpsr();
1198
                }
1199
                gen_movl_reg_T0(s, rd);
1200
            }
1201
            break;
1202
        case 0x1:
1203
            if (op1 == 1) {
1204
                /* branch/exchange thumb (bx).  */
1205
                gen_movl_T0_reg(s, rm);
1206
                gen_bx(s);
1207
            } else if (op1 == 3) {
1208
                /* clz */
1209
                rd = (insn >> 12) & 0xf;
1210
                gen_movl_T0_reg(s, rm);
1211
                gen_op_clz_T0();
1212
                gen_movl_reg_T0(s, rd);
1213
            } else {
1214
                goto illegal_op;
1215
            }
1216
            break;
1217
        case 0x2:
1218
            if (op1 == 1) {
1219
                ARCH(5J); /* bxj */
1220
                /* Trivial implementation equivalent to bx.  */
1221
                gen_movl_T0_reg(s, rm);
1222
                gen_bx(s);
1223
            } else {
1224
                goto illegal_op;
1225
            }
1226
            break;
1227
        case 0x3:
1228
            if (op1 != 1)
1229
              goto illegal_op;
1230

    
1231
            /* branch link/exchange thumb (blx) */
1232
            val = (uint32_t)s->pc;
1233
            gen_op_movl_T0_im(val);
1234
            gen_movl_reg_T0(s, 14);
1235
            gen_movl_T0_reg(s, rm);
1236
            gen_bx(s);
1237
            break;
1238
        case 0x5: /* saturating add/subtract */
1239
            rd = (insn >> 12) & 0xf;
1240
            rn = (insn >> 16) & 0xf;
1241
            gen_movl_T0_reg(s, rm);
1242
            gen_movl_T1_reg(s, rn);
1243
            if (op1 & 2)
1244
                gen_op_double_T1_saturate();
1245
            if (op1 & 1)
1246
                gen_op_subl_T0_T1_saturate();
1247
            else
1248
                gen_op_addl_T0_T1_saturate();
1249
            gen_movl_reg_T0(s, rd);
1250
            break;
1251
        case 7: /* bkpt */
1252
            gen_op_movl_T0_im((long)s->pc - 4);
1253
            gen_op_movl_reg_TN[0][15]();
1254
            gen_op_bkpt();
1255
            s->is_jmp = DISAS_JUMP;
1256
            break;
1257
        case 0x8: /* signed multiply */
1258
        case 0xa:
1259
        case 0xc:
1260
        case 0xe:
1261
            rs = (insn >> 8) & 0xf;
1262
            rn = (insn >> 12) & 0xf;
1263
            rd = (insn >> 16) & 0xf;
1264
            if (op1 == 1) {
1265
                /* (32 * 16) >> 16 */
1266
                gen_movl_T0_reg(s, rm);
1267
                gen_movl_T1_reg(s, rs);
1268
                if (sh & 4)
1269
                    gen_op_sarl_T1_im(16);
1270
                else
1271
                    gen_op_sxth_T1();
1272
                gen_op_imulw_T0_T1();
1273
                if ((sh & 2) == 0) {
1274
                    gen_movl_T1_reg(s, rn);
1275
                    gen_op_addl_T0_T1_setq();
1276
                }
1277
                gen_movl_reg_T0(s, rd);
1278
            } else {
1279
                /* 16 * 16 */
1280
                gen_movl_T0_reg(s, rm);
1281
                gen_movl_T1_reg(s, rs);
1282
                gen_mulxy(sh & 2, sh & 4);
1283
                if (op1 == 2) {
1284
                    gen_op_signbit_T1_T0();
1285
                    gen_op_addq_T0_T1(rn, rd);
1286
                    gen_movl_reg_T0(s, rn);
1287
                    gen_movl_reg_T1(s, rd);
1288
                } else {
1289
                    if (op1 == 0) {
1290
                        gen_movl_T1_reg(s, rn);
1291
                        gen_op_addl_T0_T1_setq();
1292
                    }
1293
                    gen_movl_reg_T0(s, rd);
1294
                }
1295
            }
1296
            break;
1297
        default:
1298
            goto illegal_op;
1299
        }
1300
    } else if (((insn & 0x0e000000) == 0 &&
1301
                (insn & 0x00000090) != 0x90) ||
1302
               ((insn & 0x0e000000) == (1 << 25))) {
1303
        int set_cc, logic_cc, shiftop;
1304
        
1305
        op1 = (insn >> 21) & 0xf;
1306
        set_cc = (insn >> 20) & 1;
1307
        logic_cc = table_logic_cc[op1] & set_cc;
1308

    
1309
        /* data processing instruction */
1310
        if (insn & (1 << 25)) {
1311
            /* immediate operand */
1312
            val = insn & 0xff;
1313
            shift = ((insn >> 8) & 0xf) * 2;
1314
            if (shift)
1315
                val = (val >> shift) | (val << (32 - shift));
1316
            gen_op_movl_T1_im(val);
1317
            if (logic_cc && shift)
1318
                gen_op_mov_CF_T1();
1319
        } else {
1320
            /* register */
1321
            rm = (insn) & 0xf;
1322
            gen_movl_T1_reg(s, rm);
1323
            shiftop = (insn >> 5) & 3;
1324
            if (!(insn & (1 << 4))) {
1325
                shift = (insn >> 7) & 0x1f;
1326
                if (shift != 0) {
1327
                    if (logic_cc) {
1328
                        gen_shift_T1_im_cc[shiftop](shift);
1329
                    } else {
1330
                        gen_shift_T1_im[shiftop](shift);
1331
                    }
1332
                } else if (shiftop != 0) {
1333
                    if (logic_cc) {
1334
                        gen_shift_T1_0_cc[shiftop]();
1335
                    } else {
1336
                        gen_shift_T1_0[shiftop]();
1337
                    }
1338
                }
1339
            } else {
1340
                rs = (insn >> 8) & 0xf;
1341
                gen_movl_T0_reg(s, rs);
1342
                if (logic_cc) {
1343
                    gen_shift_T1_T0_cc[shiftop]();
1344
                } else {
1345
                    gen_shift_T1_T0[shiftop]();
1346
                }
1347
            }
1348
        }
1349
        if (op1 != 0x0f && op1 != 0x0d) {
1350
            rn = (insn >> 16) & 0xf;
1351
            gen_movl_T0_reg(s, rn);
1352
        }
1353
        rd = (insn >> 12) & 0xf;
1354
        switch(op1) {
1355
        case 0x00:
1356
            gen_op_andl_T0_T1();
1357
            gen_movl_reg_T0(s, rd);
1358
            if (logic_cc)
1359
                gen_op_logic_T0_cc();
1360
            break;
1361
        case 0x01:
1362
            gen_op_xorl_T0_T1();
1363
            gen_movl_reg_T0(s, rd);
1364
            if (logic_cc)
1365
                gen_op_logic_T0_cc();
1366
            break;
1367
        case 0x02:
1368
            if (set_cc && rd == 15) {
1369
                /* SUBS r15, ... is used for exception return.  */
1370
                if (IS_USER(s))
1371
                    goto illegal_op;
1372
                gen_op_subl_T0_T1_cc();
1373
                gen_exception_return(s);
1374
            } else {
1375
                if (set_cc)
1376
                    gen_op_subl_T0_T1_cc();
1377
                else
1378
                    gen_op_subl_T0_T1();
1379
                gen_movl_reg_T0(s, rd);
1380
            }
1381
            break;
1382
        case 0x03:
1383
            if (set_cc)
1384
                gen_op_rsbl_T0_T1_cc();
1385
            else
1386
                gen_op_rsbl_T0_T1();
1387
            gen_movl_reg_T0(s, rd);
1388
            break;
1389
        case 0x04:
1390
            if (set_cc)
1391
                gen_op_addl_T0_T1_cc();
1392
            else
1393
                gen_op_addl_T0_T1();
1394
            gen_movl_reg_T0(s, rd);
1395
            break;
1396
        case 0x05:
1397
            if (set_cc)
1398
                gen_op_adcl_T0_T1_cc();
1399
            else
1400
                gen_op_adcl_T0_T1();
1401
            gen_movl_reg_T0(s, rd);
1402
            break;
1403
        case 0x06:
1404
            if (set_cc)
1405
                gen_op_sbcl_T0_T1_cc();
1406
            else
1407
                gen_op_sbcl_T0_T1();
1408
            gen_movl_reg_T0(s, rd);
1409
            break;
1410
        case 0x07:
1411
            if (set_cc)
1412
                gen_op_rscl_T0_T1_cc();
1413
            else
1414
                gen_op_rscl_T0_T1();
1415
            gen_movl_reg_T0(s, rd);
1416
            break;
1417
        case 0x08:
1418
            if (set_cc) {
1419
                gen_op_andl_T0_T1();
1420
                gen_op_logic_T0_cc();
1421
            }
1422
            break;
1423
        case 0x09:
1424
            if (set_cc) {
1425
                gen_op_xorl_T0_T1();
1426
                gen_op_logic_T0_cc();
1427
            }
1428
            break;
1429
        case 0x0a:
1430
            if (set_cc) {
1431
                gen_op_subl_T0_T1_cc();
1432
            }
1433
            break;
1434
        case 0x0b:
1435
            if (set_cc) {
1436
                gen_op_addl_T0_T1_cc();
1437
            }
1438
            break;
1439
        case 0x0c:
1440
            gen_op_orl_T0_T1();
1441
            gen_movl_reg_T0(s, rd);
1442
            if (logic_cc)
1443
                gen_op_logic_T0_cc();
1444
            break;
1445
        case 0x0d:
1446
            if (logic_cc && rd == 15) {
1447
                /* MOVS r15, ... is used for exception return.  */
1448
                if (IS_USER(s))
1449
                    goto illegal_op;
1450
                gen_op_movl_T0_T1();
1451
                gen_exception_return(s);
1452
            } else {
1453
                gen_movl_reg_T1(s, rd);
1454
                if (logic_cc)
1455
                    gen_op_logic_T1_cc();
1456
            }
1457
            break;
1458
        case 0x0e:
1459
            gen_op_bicl_T0_T1();
1460
            gen_movl_reg_T0(s, rd);
1461
            if (logic_cc)
1462
                gen_op_logic_T0_cc();
1463
            break;
1464
        default:
1465
        case 0x0f:
1466
            gen_op_notl_T1();
1467
            gen_movl_reg_T1(s, rd);
1468
            if (logic_cc)
1469
                gen_op_logic_T1_cc();
1470
            break;
1471
        }
1472
    } else {
1473
        /* other instructions */
1474
        op1 = (insn >> 24) & 0xf;
1475
        switch(op1) {
1476
        case 0x0:
1477
        case 0x1:
1478
            /* multiplies, extra load/stores */
1479
            sh = (insn >> 5) & 3;
1480
            if (sh == 0) {
1481
                if (op1 == 0x0) {
1482
                    rd = (insn >> 16) & 0xf;
1483
                    rn = (insn >> 12) & 0xf;
1484
                    rs = (insn >> 8) & 0xf;
1485
                    rm = (insn) & 0xf;
1486
                    if (((insn >> 22) & 3) == 0) {
1487
                        /* 32 bit mul */
1488
                        gen_movl_T0_reg(s, rs);
1489
                        gen_movl_T1_reg(s, rm);
1490
                        gen_op_mul_T0_T1();
1491
                        if (insn & (1 << 21)) {
1492
                            gen_movl_T1_reg(s, rn);
1493
                            gen_op_addl_T0_T1();
1494
                        }
1495
                        if (insn & (1 << 20)) 
1496
                            gen_op_logic_T0_cc();
1497
                        gen_movl_reg_T0(s, rd);
1498
                    } else {
1499
                        /* 64 bit mul */
1500
                        gen_movl_T0_reg(s, rs);
1501
                        gen_movl_T1_reg(s, rm);
1502
                        if (insn & (1 << 22)) 
1503
                            gen_op_imull_T0_T1();
1504
                        else
1505
                            gen_op_mull_T0_T1();
1506
                        if (insn & (1 << 21)) /* mult accumulate */
1507
                            gen_op_addq_T0_T1(rn, rd);
1508
                        if (!(insn & (1 << 23))) { /* double accumulate */
1509
                            ARCH(6);
1510
                            gen_op_addq_lo_T0_T1(rn);
1511
                            gen_op_addq_lo_T0_T1(rd);
1512
                        }
1513
                        if (insn & (1 << 20)) 
1514
                            gen_op_logicq_cc();
1515
                        gen_movl_reg_T0(s, rn);
1516
                        gen_movl_reg_T1(s, rd);
1517
                    }
1518
                } else {
1519
                    rn = (insn >> 16) & 0xf;
1520
                    rd = (insn >> 12) & 0xf;
1521
                    if (insn & (1 << 23)) {
1522
                        /* load/store exclusive */
1523
                        goto illegal_op;
1524
                    } else {
1525
                        /* SWP instruction */
1526
                        rm = (insn) & 0xf;
1527
                        
1528
                        gen_movl_T0_reg(s, rm);
1529
                        gen_movl_T1_reg(s, rn);
1530
                        if (insn & (1 << 22)) {
1531
                            gen_ldst(swpb, s);
1532
                        } else {
1533
                            gen_ldst(swpl, s);
1534
                        }
1535
                        gen_movl_reg_T0(s, rd);
1536
                    }
1537
                }
1538
            } else {
1539
                int address_offset;
1540
                int load;
1541
                /* Misc load/store */
1542
                rn = (insn >> 16) & 0xf;
1543
                rd = (insn >> 12) & 0xf;
1544
                gen_movl_T1_reg(s, rn);
1545
                if (insn & (1 << 24))
1546
                    gen_add_datah_offset(s, insn, 0);
1547
                address_offset = 0;
1548
                if (insn & (1 << 20)) {
1549
                    /* load */
1550
                    switch(sh) {
1551
                    case 1:
1552
                        gen_ldst(lduw, s);
1553
                        break;
1554
                    case 2:
1555
                        gen_ldst(ldsb, s);
1556
                        break;
1557
                    default:
1558
                    case 3:
1559
                        gen_ldst(ldsw, s);
1560
                        break;
1561
                    }
1562
                    load = 1;
1563
                } else if (sh & 2) {
1564
                    /* doubleword */
1565
                    if (sh & 1) {
1566
                        /* store */
1567
                        gen_movl_T0_reg(s, rd);
1568
                        gen_ldst(stl, s);
1569
                        gen_op_addl_T1_im(4);
1570
                        gen_movl_T0_reg(s, rd + 1);
1571
                        gen_ldst(stl, s);
1572
                        load = 0;
1573
                    } else {
1574
                        /* load */
1575
                        gen_ldst(ldl, s);
1576
                        gen_movl_reg_T0(s, rd);
1577
                        gen_op_addl_T1_im(4);
1578
                        gen_ldst(ldl, s);
1579
                        rd++;
1580
                        load = 1;
1581
                    }
1582
                    address_offset = -4;
1583
                } else {
1584
                    /* store */
1585
                    gen_movl_T0_reg(s, rd);
1586
                    gen_ldst(stw, s);
1587
                    load = 0;
1588
                }
1589
                /* Perform base writeback before the loaded value to
1590
                   ensure correct behavior with overlapping index registers.
1591
                   ldrd with base writeback is is undefined if the
1592
                   destination and index registers overlap.  */
1593
                if (!(insn & (1 << 24))) {
1594
                    gen_add_datah_offset(s, insn, address_offset);
1595
                    gen_movl_reg_T1(s, rn);
1596
                } else if (insn & (1 << 21)) {
1597
                    if (address_offset)
1598
                        gen_op_addl_T1_im(address_offset);
1599
                    gen_movl_reg_T1(s, rn);
1600
                }
1601
                if (load) {
1602
                    /* Complete the load.  */
1603
                    gen_movl_reg_T0(s, rd);
1604
                }
1605
            }
1606
            break;
1607
        case 0x4:
1608
        case 0x5:
1609
        case 0x6:
1610
        case 0x7:
1611
            /* Check for undefined extension instructions
1612
             * per the ARM Bible IE:
1613
             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
1614
             */
1615
            sh = (0xf << 20) | (0xf << 4);
1616
            if (op1 == 0x7 && ((insn & sh) == sh))
1617
            {
1618
                goto illegal_op;
1619
            }
1620
            /* load/store byte/word */
1621
            rn = (insn >> 16) & 0xf;
1622
            rd = (insn >> 12) & 0xf;
1623
            gen_movl_T1_reg(s, rn);
1624
            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
1625
            if (insn & (1 << 24))
1626
                gen_add_data_offset(s, insn);
1627
            if (insn & (1 << 20)) {
1628
                /* load */
1629
                s->is_mem = 1;
1630
#if defined(CONFIG_USER_ONLY)
1631
                if (insn & (1 << 22))
1632
                    gen_op_ldub_raw();
1633
                else
1634
                    gen_op_ldl_raw();
1635
#else
1636
                if (insn & (1 << 22)) {
1637
                    if (i)
1638
                        gen_op_ldub_user();
1639
                    else
1640
                        gen_op_ldub_kernel();
1641
                } else {
1642
                    if (i)
1643
                        gen_op_ldl_user();
1644
                    else
1645
                        gen_op_ldl_kernel();
1646
                }
1647
#endif
1648
            } else {
1649
                /* store */
1650
                gen_movl_T0_reg(s, rd);
1651
#if defined(CONFIG_USER_ONLY)
1652
                if (insn & (1 << 22))
1653
                    gen_op_stb_raw();
1654
                else
1655
                    gen_op_stl_raw();
1656
#else
1657
                if (insn & (1 << 22)) {
1658
                    if (i)
1659
                        gen_op_stb_user();
1660
                    else
1661
                        gen_op_stb_kernel();
1662
                } else {
1663
                    if (i)
1664
                        gen_op_stl_user();
1665
                    else
1666
                        gen_op_stl_kernel();
1667
                }
1668
#endif
1669
            }
1670
            if (!(insn & (1 << 24))) {
1671
                gen_add_data_offset(s, insn);
1672
                gen_movl_reg_T1(s, rn);
1673
            } else if (insn & (1 << 21))
1674
                gen_movl_reg_T1(s, rn); {
1675
            }
1676
            if (insn & (1 << 20)) {
1677
                /* Complete the load.  */
1678
                if (rd == 15)
1679
                    gen_bx(s);
1680
                else
1681
                    gen_movl_reg_T0(s, rd);
1682
            }
1683
            break;
1684
        case 0x08:
1685
        case 0x09:
1686
            {
1687
                int j, n, user, loaded_base;
1688
                /* load/store multiple words */
1689
                /* XXX: store correct base if write back */
1690
                user = 0;
1691
                if (insn & (1 << 22)) {
1692
                    if (IS_USER(s))
1693
                        goto illegal_op; /* only usable in supervisor mode */
1694

    
1695
                    if ((insn & (1 << 15)) == 0)
1696
                        user = 1;
1697
                }
1698
                rn = (insn >> 16) & 0xf;
1699
                gen_movl_T1_reg(s, rn);
1700
                
1701
                /* compute total size */
1702
                loaded_base = 0;
1703
                n = 0;
1704
                for(i=0;i<16;i++) {
1705
                    if (insn & (1 << i))
1706
                        n++;
1707
                }
1708
                /* XXX: test invalid n == 0 case ? */
1709
                if (insn & (1 << 23)) {
1710
                    if (insn & (1 << 24)) {
1711
                        /* pre increment */
1712
                        gen_op_addl_T1_im(4);
1713
                    } else {
1714
                        /* post increment */
1715
                    }
1716
                } else {
1717
                    if (insn & (1 << 24)) {
1718
                        /* pre decrement */
1719
                        gen_op_addl_T1_im(-(n * 4));
1720
                    } else {
1721
                        /* post decrement */
1722
                        if (n != 1)
1723
                            gen_op_addl_T1_im(-((n - 1) * 4));
1724
                    }
1725
                }
1726
                j = 0;
1727
                for(i=0;i<16;i++) {
1728
                    if (insn & (1 << i)) {
1729
                        if (insn & (1 << 20)) {
1730
                            /* load */
1731
                            gen_ldst(ldl, s);
1732
                            if (i == 15) {
1733
                                gen_bx(s);
1734
                            } else if (user) {
1735
                                gen_op_movl_user_T0(i);
1736
                            } else if (i == rn) {
1737
                                gen_op_movl_T2_T0();
1738
                                loaded_base = 1;
1739
                            } else {
1740
                                gen_movl_reg_T0(s, i);
1741
                            }
1742
                        } else {
1743
                            /* store */
1744
                            if (i == 15) {
1745
                                /* special case: r15 = PC + 12 */
1746
                                val = (long)s->pc + 8;
1747
                                gen_op_movl_TN_im[0](val);
1748
                            } else if (user) {
1749
                                gen_op_movl_T0_user(i);
1750
                            } else {
1751
                                gen_movl_T0_reg(s, i);
1752
                            }
1753
                            gen_ldst(stl, s);
1754
                        }
1755
                        j++;
1756
                        /* no need to add after the last transfer */
1757
                        if (j != n)
1758
                            gen_op_addl_T1_im(4);
1759
                    }
1760
                }
1761
                if (insn & (1 << 21)) {
1762
                    /* write back */
1763
                    if (insn & (1 << 23)) {
1764
                        if (insn & (1 << 24)) {
1765
                            /* pre increment */
1766
                        } else {
1767
                            /* post increment */
1768
                            gen_op_addl_T1_im(4);
1769
                        }
1770
                    } else {
1771
                        if (insn & (1 << 24)) {
1772
                            /* pre decrement */
1773
                            if (n != 1)
1774
                                gen_op_addl_T1_im(-((n - 1) * 4));
1775
                        } else {
1776
                            /* post decrement */
1777
                            gen_op_addl_T1_im(-(n * 4));
1778
                        }
1779
                    }
1780
                    gen_movl_reg_T1(s, rn);
1781
                }
1782
                if (loaded_base) {
1783
                    gen_op_movl_T0_T2();
1784
                    gen_movl_reg_T0(s, rn);
1785
                }
1786
                if ((insn & (1 << 22)) && !user) {
1787
                    /* Restore CPSR from SPSR.  */
1788
                    gen_op_movl_T0_spsr();
1789
                    gen_op_movl_cpsr_T0(0xffffffff);
1790
                    s->is_jmp = DISAS_UPDATE;
1791
                }
1792
            }
1793
            break;
1794
        case 0xa:
1795
        case 0xb:
1796
            {
1797
                int32_t offset;
1798
                
1799
                /* branch (and link) */
1800
                val = (int32_t)s->pc;
1801
                if (insn & (1 << 24)) {
1802
                    gen_op_movl_T0_im(val);
1803
                    gen_op_movl_reg_TN[0][14]();
1804
                }
1805
                offset = (((int32_t)insn << 8) >> 8);
1806
                val += (offset << 2) + 4;
1807
                gen_jmp(s, val);
1808
            }
1809
            break;
1810
        case 0xc:
1811
        case 0xd:
1812
        case 0xe:
1813
            /* Coprocessor.  */
1814
            op1 = (insn >> 8) & 0xf;
1815
            switch (op1) {
1816
            case 10:
1817
            case 11:
1818
                if (disas_vfp_insn (env, s, insn))
1819
                    goto illegal_op;
1820
                break;
1821
            case 15:
1822
                if (disas_cp15_insn (s, insn))
1823
                    goto illegal_op;
1824
                break;
1825
            default:
1826
                /* unknown coprocessor.  */
1827
                goto illegal_op;
1828
            }
1829
            break;
1830
        case 0xf:
1831
            /* swi */
1832
            gen_op_movl_T0_im((long)s->pc);
1833
            gen_op_movl_reg_TN[0][15]();
1834
            gen_op_swi();
1835
            s->is_jmp = DISAS_JUMP;
1836
            break;
1837
        default:
1838
        illegal_op:
1839
            gen_op_movl_T0_im((long)s->pc - 4);
1840
            gen_op_movl_reg_TN[0][15]();
1841
            gen_op_undef_insn();
1842
            s->is_jmp = DISAS_JUMP;
1843
            break;
1844
        }
1845
    }
1846
}
1847

    
1848
static void disas_thumb_insn(DisasContext *s)
1849
{
1850
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1851
    int32_t offset;
1852
    int i;
1853

    
1854
    insn = lduw_code(s->pc);
1855
    s->pc += 2;
1856

    
1857
    switch (insn >> 12) {
1858
    case 0: case 1:
1859
        rd = insn & 7;
1860
        op = (insn >> 11) & 3;
1861
        if (op == 3) {
1862
            /* add/subtract */
1863
            rn = (insn >> 3) & 7;
1864
            gen_movl_T0_reg(s, rn);
1865
            if (insn & (1 << 10)) {
1866
                /* immediate */
1867
                gen_op_movl_T1_im((insn >> 6) & 7);
1868
            } else {
1869
                /* reg */
1870
                rm = (insn >> 6) & 7;
1871
                gen_movl_T1_reg(s, rm);
1872
            }
1873
            if (insn & (1 << 9))
1874
                gen_op_subl_T0_T1_cc();
1875
            else
1876
                gen_op_addl_T0_T1_cc();
1877
            gen_movl_reg_T0(s, rd);
1878
        } else {
1879
            /* shift immediate */
1880
            rm = (insn >> 3) & 7;
1881
            shift = (insn >> 6) & 0x1f;
1882
            gen_movl_T0_reg(s, rm);
1883
            gen_shift_T0_im_thumb[op](shift);
1884
            gen_movl_reg_T0(s, rd);
1885
        }
1886
        break;
1887
    case 2: case 3:
1888
        /* arithmetic large immediate */
1889
        op = (insn >> 11) & 3;
1890
        rd = (insn >> 8) & 0x7;
1891
        if (op == 0) {
1892
            gen_op_movl_T0_im(insn & 0xff);
1893
        } else {
1894
            gen_movl_T0_reg(s, rd);
1895
            gen_op_movl_T1_im(insn & 0xff);
1896
        }
1897
        switch (op) {
1898
        case 0: /* mov */
1899
            gen_op_logic_T0_cc();
1900
            break;
1901
        case 1: /* cmp */
1902
            gen_op_subl_T0_T1_cc();
1903
            break;
1904
        case 2: /* add */
1905
            gen_op_addl_T0_T1_cc();
1906
            break;
1907
        case 3: /* sub */
1908
            gen_op_subl_T0_T1_cc();
1909
            break;
1910
        }
1911
        if (op != 1)
1912
            gen_movl_reg_T0(s, rd);
1913
        break;
1914
    case 4:
1915
        if (insn & (1 << 11)) {
1916
            rd = (insn >> 8) & 7;
1917
            /* load pc-relative.  Bit 1 of PC is ignored.  */
1918
            val = s->pc + 2 + ((insn & 0xff) * 4);
1919
            val &= ~(uint32_t)2;
1920
            gen_op_movl_T1_im(val);
1921
            gen_ldst(ldl, s);
1922
            gen_movl_reg_T0(s, rd);
1923
            break;
1924
        }
1925
        if (insn & (1 << 10)) {
1926
            /* data processing extended or blx */
1927
            rd = (insn & 7) | ((insn >> 4) & 8);
1928
            rm = (insn >> 3) & 0xf;
1929
            op = (insn >> 8) & 3;
1930
            switch (op) {
1931
            case 0: /* add */
1932
                gen_movl_T0_reg(s, rd);
1933
                gen_movl_T1_reg(s, rm);
1934
                gen_op_addl_T0_T1();
1935
                gen_movl_reg_T0(s, rd);
1936
                break;
1937
            case 1: /* cmp */
1938
                gen_movl_T0_reg(s, rd);
1939
                gen_movl_T1_reg(s, rm);
1940
                gen_op_subl_T0_T1_cc();
1941
                break;
1942
            case 2: /* mov/cpy */
1943
                gen_movl_T0_reg(s, rm);
1944
                gen_movl_reg_T0(s, rd);
1945
                break;
1946
            case 3:/* branch [and link] exchange thumb register */
1947
                if (insn & (1 << 7)) {
1948
                    val = (uint32_t)s->pc | 1;
1949
                    gen_op_movl_T1_im(val);
1950
                    gen_movl_reg_T1(s, 14);
1951
                }
1952
                gen_movl_T0_reg(s, rm);
1953
                gen_bx(s);
1954
                break;
1955
            }
1956
            break;
1957
        }
1958

    
1959
        /* data processing register */
1960
        rd = insn & 7;
1961
        rm = (insn >> 3) & 7;
1962
        op = (insn >> 6) & 0xf;
1963
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1964
            /* the shift/rotate ops want the operands backwards */
1965
            val = rm;
1966
            rm = rd;
1967
            rd = val;
1968
            val = 1;
1969
        } else {
1970
            val = 0;
1971
        }
1972

    
1973
        if (op == 9) /* neg */
1974
            gen_op_movl_T0_im(0);
1975
        else if (op != 0xf) /* mvn doesn't read its first operand */
1976
            gen_movl_T0_reg(s, rd);
1977

    
1978
        gen_movl_T1_reg(s, rm);
1979
        switch (op) {
1980
        case 0x0: /* and */
1981
            gen_op_andl_T0_T1();
1982
            gen_op_logic_T0_cc();
1983
            break;
1984
        case 0x1: /* eor */
1985
            gen_op_xorl_T0_T1();
1986
            gen_op_logic_T0_cc();
1987
            break;
1988
        case 0x2: /* lsl */
1989
            gen_op_shll_T1_T0_cc();
1990
            gen_op_logic_T1_cc();
1991
            break;
1992
        case 0x3: /* lsr */
1993
            gen_op_shrl_T1_T0_cc();
1994
            gen_op_logic_T1_cc();
1995
            break;
1996
        case 0x4: /* asr */
1997
            gen_op_sarl_T1_T0_cc();
1998
            gen_op_logic_T1_cc();
1999
            break;
2000
        case 0x5: /* adc */
2001
            gen_op_adcl_T0_T1_cc();
2002
            break;
2003
        case 0x6: /* sbc */
2004
            gen_op_sbcl_T0_T1_cc();
2005
            break;
2006
        case 0x7: /* ror */
2007
            gen_op_rorl_T1_T0_cc();
2008
            gen_op_logic_T1_cc();
2009
            break;
2010
        case 0x8: /* tst */
2011
            gen_op_andl_T0_T1();
2012
            gen_op_logic_T0_cc();
2013
            rd = 16;
2014
            break;
2015
        case 0x9: /* neg */
2016
            gen_op_subl_T0_T1_cc();
2017
            break;
2018
        case 0xa: /* cmp */
2019
            gen_op_subl_T0_T1_cc();
2020
            rd = 16;
2021
            break;
2022
        case 0xb: /* cmn */
2023
            gen_op_addl_T0_T1_cc();
2024
            rd = 16;
2025
            break;
2026
        case 0xc: /* orr */
2027
            gen_op_orl_T0_T1();
2028
            gen_op_logic_T0_cc();
2029
            break;
2030
        case 0xd: /* mul */
2031
            gen_op_mull_T0_T1();
2032
            gen_op_logic_T0_cc();
2033
            break;
2034
        case 0xe: /* bic */
2035
            gen_op_bicl_T0_T1();
2036
            gen_op_logic_T0_cc();
2037
            break;
2038
        case 0xf: /* mvn */
2039
            gen_op_notl_T1();
2040
            gen_op_logic_T1_cc();
2041
            val = 1;
2042
            rm = rd;
2043
            break;
2044
        }
2045
        if (rd != 16) {
2046
            if (val)
2047
                gen_movl_reg_T1(s, rm);
2048
            else
2049
                gen_movl_reg_T0(s, rd);
2050
        }
2051
        break;
2052

    
2053
    case 5:
2054
        /* load/store register offset.  */
2055
        rd = insn & 7;
2056
        rn = (insn >> 3) & 7;
2057
        rm = (insn >> 6) & 7;
2058
        op = (insn >> 9) & 7;
2059
        gen_movl_T1_reg(s, rn);
2060
        gen_movl_T2_reg(s, rm);
2061
        gen_op_addl_T1_T2();
2062

    
2063
        if (op < 3) /* store */
2064
            gen_movl_T0_reg(s, rd);
2065

    
2066
        switch (op) {
2067
        case 0: /* str */
2068
            gen_ldst(stl, s);
2069
            break;
2070
        case 1: /* strh */
2071
            gen_ldst(stw, s);
2072
            break;
2073
        case 2: /* strb */
2074
            gen_ldst(stb, s);
2075
            break;
2076
        case 3: /* ldrsb */
2077
            gen_ldst(ldsb, s);
2078
            break;
2079
        case 4: /* ldr */
2080
            gen_ldst(ldl, s);
2081
            break;
2082
        case 5: /* ldrh */
2083
            gen_ldst(lduw, s);
2084
            break;
2085
        case 6: /* ldrb */
2086
            gen_ldst(ldub, s);
2087
            break;
2088
        case 7: /* ldrsh */
2089
            gen_ldst(ldsw, s);
2090
            break;
2091
        }
2092
        if (op >= 3) /* load */
2093
            gen_movl_reg_T0(s, rd);
2094
        break;
2095

    
2096
    case 6:
2097
        /* load/store word immediate offset */
2098
        rd = insn & 7;
2099
        rn = (insn >> 3) & 7;
2100
        gen_movl_T1_reg(s, rn);
2101
        val = (insn >> 4) & 0x7c;
2102
        gen_op_movl_T2_im(val);
2103
        gen_op_addl_T1_T2();
2104

    
2105
        if (insn & (1 << 11)) {
2106
            /* load */
2107
            gen_ldst(ldl, s);
2108
            gen_movl_reg_T0(s, rd);
2109
        } else {
2110
            /* store */
2111
            gen_movl_T0_reg(s, rd);
2112
            gen_ldst(stl, s);
2113
        }
2114
        break;
2115

    
2116
    case 7:
2117
        /* load/store byte immediate offset */
2118
        rd = insn & 7;
2119
        rn = (insn >> 3) & 7;
2120
        gen_movl_T1_reg(s, rn);
2121
        val = (insn >> 6) & 0x1f;
2122
        gen_op_movl_T2_im(val);
2123
        gen_op_addl_T1_T2();
2124

    
2125
        if (insn & (1 << 11)) {
2126
            /* load */
2127
            gen_ldst(ldub, s);
2128
            gen_movl_reg_T0(s, rd);
2129
        } else {
2130
            /* store */
2131
            gen_movl_T0_reg(s, rd);
2132
            gen_ldst(stb, s);
2133
        }
2134
        break;
2135

    
2136
    case 8:
2137
        /* load/store halfword immediate offset */
2138
        rd = insn & 7;
2139
        rn = (insn >> 3) & 7;
2140
        gen_movl_T1_reg(s, rn);
2141
        val = (insn >> 5) & 0x3e;
2142
        gen_op_movl_T2_im(val);
2143
        gen_op_addl_T1_T2();
2144

    
2145
        if (insn & (1 << 11)) {
2146
            /* load */
2147
            gen_ldst(lduw, s);
2148
            gen_movl_reg_T0(s, rd);
2149
        } else {
2150
            /* store */
2151
            gen_movl_T0_reg(s, rd);
2152
            gen_ldst(stw, s);
2153
        }
2154
        break;
2155

    
2156
    case 9:
2157
        /* load/store from stack */
2158
        rd = (insn >> 8) & 7;
2159
        gen_movl_T1_reg(s, 13);
2160
        val = (insn & 0xff) * 4;
2161
        gen_op_movl_T2_im(val);
2162
        gen_op_addl_T1_T2();
2163

    
2164
        if (insn & (1 << 11)) {
2165
            /* load */
2166
            gen_ldst(ldl, s);
2167
            gen_movl_reg_T0(s, rd);
2168
        } else {
2169
            /* store */
2170
            gen_movl_T0_reg(s, rd);
2171
            gen_ldst(stl, s);
2172
        }
2173
        break;
2174

    
2175
    case 10:
2176
        /* add to high reg */
2177
        rd = (insn >> 8) & 7;
2178
        if (insn & (1 << 11)) {
2179
            /* SP */
2180
            gen_movl_T0_reg(s, 13);
2181
        } else {
2182
            /* PC. bit 1 is ignored.  */
2183
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
2184
        }
2185
        val = (insn & 0xff) * 4;
2186
        gen_op_movl_T1_im(val);
2187
        gen_op_addl_T0_T1();
2188
        gen_movl_reg_T0(s, rd);
2189
        break;
2190

    
2191
    case 11:
2192
        /* misc */
2193
        op = (insn >> 8) & 0xf;
2194
        switch (op) {
2195
        case 0:
2196
            /* adjust stack pointer */
2197
            gen_movl_T1_reg(s, 13);
2198
            val = (insn & 0x7f) * 4;
2199
            if (insn & (1 << 7))
2200
              val = -(int32_t)val;
2201
            gen_op_movl_T2_im(val);
2202
            gen_op_addl_T1_T2();
2203
            gen_movl_reg_T1(s, 13);
2204
            break;
2205

    
2206
        case 4: case 5: case 0xc: case 0xd:
2207
            /* push/pop */
2208
            gen_movl_T1_reg(s, 13);
2209
            if (insn & (1 << 8))
2210
                offset = 4;
2211
            else
2212
                offset = 0;
2213
            for (i = 0; i < 8; i++) {
2214
                if (insn & (1 << i))
2215
                    offset += 4;
2216
            }
2217
            if ((insn & (1 << 11)) == 0) {
2218
                gen_op_movl_T2_im(-offset);
2219
                gen_op_addl_T1_T2();
2220
            }
2221
            gen_op_movl_T2_im(4);
2222
            for (i = 0; i < 8; i++) {
2223
                if (insn & (1 << i)) {
2224
                    if (insn & (1 << 11)) {
2225
                        /* pop */
2226
                        gen_ldst(ldl, s);
2227
                        gen_movl_reg_T0(s, i);
2228
                    } else {
2229
                        /* push */
2230
                        gen_movl_T0_reg(s, i);
2231
                        gen_ldst(stl, s);
2232
                    }
2233
                    /* advance to the next address.  */
2234
                    gen_op_addl_T1_T2();
2235
                }
2236
            }
2237
            if (insn & (1 << 8)) {
2238
                if (insn & (1 << 11)) {
2239
                    /* pop pc */
2240
                    gen_ldst(ldl, s);
2241
                    /* don't set the pc until the rest of the instruction
2242
                       has completed */
2243
                } else {
2244
                    /* push lr */
2245
                    gen_movl_T0_reg(s, 14);
2246
                    gen_ldst(stl, s);
2247
                }
2248
                gen_op_addl_T1_T2();
2249
            }
2250
            if ((insn & (1 << 11)) == 0) {
2251
                gen_op_movl_T2_im(-offset);
2252
                gen_op_addl_T1_T2();
2253
            }
2254
            /* write back the new stack pointer */
2255
            gen_movl_reg_T1(s, 13);
2256
            /* set the new PC value */
2257
            if ((insn & 0x0900) == 0x0900)
2258
                gen_bx(s);
2259
            break;
2260

    
2261
        case 0xe: /* bkpt */
2262
            gen_op_movl_T0_im((long)s->pc - 2);
2263
            gen_op_movl_reg_TN[0][15]();
2264
            gen_op_bkpt();
2265
            s->is_jmp = DISAS_JUMP;
2266
            break;
2267

    
2268
        default:
2269
            goto undef;
2270
        }
2271
        break;
2272

    
2273
    case 12:
2274
        /* load/store multiple */
2275
        rn = (insn >> 8) & 0x7;
2276
        gen_movl_T1_reg(s, rn);
2277
        gen_op_movl_T2_im(4);
2278
        for (i = 0; i < 8; i++) {
2279
            if (insn & (1 << i)) {
2280
                if (insn & (1 << 11)) {
2281
                    /* load */
2282
                    gen_ldst(ldl, s);
2283
                    gen_movl_reg_T0(s, i);
2284
                } else {
2285
                    /* store */
2286
                    gen_movl_T0_reg(s, i);
2287
                    gen_ldst(stl, s);
2288
                }
2289
                /* advance to the next address */
2290
                gen_op_addl_T1_T2();
2291
            }
2292
        }
2293
        /* Base register writeback.  */
2294
        if ((insn & (1 << rn)) == 0)
2295
            gen_movl_reg_T1(s, rn);
2296
        break;
2297

    
2298
    case 13:
2299
        /* conditional branch or swi */
2300
        cond = (insn >> 8) & 0xf;
2301
        if (cond == 0xe)
2302
            goto undef;
2303

    
2304
        if (cond == 0xf) {
2305
            /* swi */
2306
            gen_op_movl_T0_im((long)s->pc | 1);
2307
            /* Don't set r15.  */
2308
            gen_op_movl_reg_TN[0][15]();
2309
            gen_op_swi();
2310
            s->is_jmp = DISAS_JUMP;
2311
            break;
2312
        }
2313
        /* generate a conditional jump to next instruction */
2314
        s->condlabel = gen_new_label();
2315
        gen_test_cc[cond ^ 1](s->condlabel);
2316
        s->condjmp = 1;
2317
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
2318
        //s->is_jmp = DISAS_JUMP_NEXT;
2319
        gen_movl_T1_reg(s, 15);
2320

    
2321
        /* jump to the offset */
2322
        val = (uint32_t)s->pc + 2;
2323
        offset = ((int32_t)insn << 24) >> 24;
2324
        val += offset << 1;
2325
        gen_jmp(s, val);
2326
        break;
2327

    
2328
    case 14:
2329
        /* unconditional branch */
2330
        if (insn & (1 << 11)) {
2331
            /* Second half of blx.  */
2332
            offset = ((insn & 0x7ff) << 1);
2333
            gen_movl_T0_reg(s, 14);
2334
            gen_op_movl_T1_im(offset);
2335
            gen_op_addl_T0_T1();
2336
            gen_op_movl_T1_im(0xfffffffc);
2337
            gen_op_andl_T0_T1();
2338

    
2339
            val = (uint32_t)s->pc;
2340
            gen_op_movl_T1_im(val | 1);
2341
            gen_movl_reg_T1(s, 14);
2342
            gen_bx(s);
2343
            break;
2344
        }
2345
        val = (uint32_t)s->pc;
2346
        offset = ((int32_t)insn << 21) >> 21;
2347
        val += (offset << 1) + 2;
2348
        gen_jmp(s, val);
2349
        break;
2350

    
2351
    case 15:
2352
        /* branch and link [and switch to arm] */
2353
        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
2354
            /* Instruction spans a page boundary.  Implement it as two
2355
               16-bit instructions in case the second half causes an
2356
               prefetch abort.  */
2357
            offset = ((int32_t)insn << 21) >> 9;
2358
            val = s->pc + 2 + offset;
2359
            gen_op_movl_T0_im(val);
2360
            gen_movl_reg_T0(s, 14);
2361
            break;
2362
        }
2363
        if (insn & (1 << 11)) {
2364
            /* Second half of bl.  */
2365
            offset = ((insn & 0x7ff) << 1) | 1;
2366
            gen_movl_T0_reg(s, 14);
2367
            gen_op_movl_T1_im(offset);
2368
            gen_op_addl_T0_T1();
2369

    
2370
            val = (uint32_t)s->pc;
2371
            gen_op_movl_T1_im(val | 1);
2372
            gen_movl_reg_T1(s, 14);
2373
            gen_bx(s);
2374
            break;
2375
        }
2376
        offset = ((int32_t)insn << 21) >> 10;
2377
        insn = lduw_code(s->pc);
2378
        offset |= insn & 0x7ff;
2379

    
2380
        val = (uint32_t)s->pc + 2;
2381
        gen_op_movl_T1_im(val | 1);
2382
        gen_movl_reg_T1(s, 14);
2383
        
2384
        val += offset << 1;
2385
        if (insn & (1 << 12)) {
2386
            /* bl */
2387
            gen_jmp(s, val);
2388
        } else {
2389
            /* blx */
2390
            val &= ~(uint32_t)2;
2391
            gen_op_movl_T0_im(val);
2392
            gen_bx(s);
2393
        }
2394
    }
2395
    return;
2396
undef:
2397
    gen_op_movl_T0_im((long)s->pc - 2);
2398
    gen_op_movl_reg_TN[0][15]();
2399
    gen_op_undef_insn();
2400
    s->is_jmp = DISAS_JUMP;
2401
}
2402

    
2403
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2404
   basic block 'tb'. If search_pc is TRUE, also generate PC
2405
   information for each intermediate instruction. */
2406
static inline int gen_intermediate_code_internal(CPUState *env, 
2407
                                                 TranslationBlock *tb, 
2408
                                                 int search_pc)
2409
{
2410
    DisasContext dc1, *dc = &dc1;
2411
    uint16_t *gen_opc_end;
2412
    int j, lj;
2413
    target_ulong pc_start;
2414
    uint32_t next_page_start;
2415
    
2416
    /* generate intermediate code */
2417
    pc_start = tb->pc;
2418
       
2419
    dc->tb = tb;
2420

    
2421
    gen_opc_ptr = gen_opc_buf;
2422
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2423
    gen_opparam_ptr = gen_opparam_buf;
2424

    
2425
    dc->is_jmp = DISAS_NEXT;
2426
    dc->pc = pc_start;
2427
    dc->singlestep_enabled = env->singlestep_enabled;
2428
    dc->condjmp = 0;
2429
    dc->thumb = env->thumb;
2430
    dc->is_mem = 0;
2431
#if !defined(CONFIG_USER_ONLY)
2432
    dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
2433
#endif
2434
    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
2435
    nb_gen_labels = 0;
2436
    lj = -1;
2437
    do {
2438
        if (env->nb_breakpoints > 0) {
2439
            for(j = 0; j < env->nb_breakpoints; j++) {
2440
                if (env->breakpoints[j] == dc->pc) {
2441
                    gen_op_movl_T0_im((long)dc->pc);
2442
                    gen_op_movl_reg_TN[0][15]();
2443
                    gen_op_debug();
2444
                    dc->is_jmp = DISAS_JUMP;
2445
                    break;
2446
                }
2447
            }
2448
        }
2449
        if (search_pc) {
2450
            j = gen_opc_ptr - gen_opc_buf;
2451
            if (lj < j) {
2452
                lj++;
2453
                while (lj < j)
2454
                    gen_opc_instr_start[lj++] = 0;
2455
            }
2456
            gen_opc_pc[lj] = dc->pc;
2457
            gen_opc_instr_start[lj] = 1;
2458
        }
2459

    
2460
        if (env->thumb)
2461
          disas_thumb_insn(dc);
2462
        else
2463
          disas_arm_insn(env, dc);
2464

    
2465
        if (dc->condjmp && !dc->is_jmp) {
2466
            gen_set_label(dc->condlabel);
2467
            dc->condjmp = 0;
2468
        }
2469
        /* Terminate the TB on memory ops if watchpoints are present.  */
2470
        /* FIXME: This should be replacd by the deterministic execution
2471
         * IRQ raising bits.  */
2472
        if (dc->is_mem && env->nb_watchpoints)
2473
            break;
2474

    
2475
        /* Translation stops when a conditional branch is enoutered.
2476
         * Otherwise the subsequent code could get translated several times.
2477
         * Also stop translation when a page boundary is reached.  This
2478
         * ensures prefech aborts occur at the right place.  */
2479
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2480
             !env->singlestep_enabled &&
2481
             dc->pc < next_page_start);
2482
    /* At this stage dc->condjmp will only be set when the skipped
2483
     * instruction was a conditional branch, and the PC has already been
2484
     * written.  */
2485
    if (__builtin_expect(env->singlestep_enabled, 0)) {
2486
        /* Make sure the pc is updated, and raise a debug exception.  */
2487
        if (dc->condjmp) {
2488
            gen_op_debug();
2489
            gen_set_label(dc->condlabel);
2490
        }
2491
        if (dc->condjmp || !dc->is_jmp) {
2492
            gen_op_movl_T0_im((long)dc->pc);
2493
            gen_op_movl_reg_TN[0][15]();
2494
            dc->condjmp = 0;
2495
        }
2496
        gen_op_debug();
2497
    } else {
2498
        switch(dc->is_jmp) {
2499
        case DISAS_NEXT:
2500
            gen_goto_tb(dc, 1, dc->pc);
2501
            break;
2502
        default:
2503
        case DISAS_JUMP:
2504
        case DISAS_UPDATE:
2505
            /* indicate that the hash table must be used to find the next TB */
2506
            gen_op_movl_T0_0();
2507
            gen_op_exit_tb();
2508
            break;
2509
        case DISAS_TB_JUMP:
2510
            /* nothing more to generate */
2511
            break;
2512
        }
2513
        if (dc->condjmp) {
2514
            gen_set_label(dc->condlabel);
2515
            gen_goto_tb(dc, 1, dc->pc);
2516
            dc->condjmp = 0;
2517
        }
2518
    }
2519
    *gen_opc_ptr = INDEX_op_end;
2520

    
2521
#ifdef DEBUG_DISAS
2522
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2523
        fprintf(logfile, "----------------\n");
2524
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2525
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2526
        fprintf(logfile, "\n");
2527
        if (loglevel & (CPU_LOG_TB_OP)) {
2528
            fprintf(logfile, "OP:\n");
2529
            dump_ops(gen_opc_buf, gen_opparam_buf);
2530
            fprintf(logfile, "\n");
2531
        }
2532
    }
2533
#endif
2534
    if (search_pc) {
2535
        j = gen_opc_ptr - gen_opc_buf;
2536
        lj++;
2537
        while (lj <= j)
2538
            gen_opc_instr_start[lj++] = 0;
2539
        tb->size = 0;
2540
    } else {
2541
        tb->size = dc->pc - pc_start;
2542
    }
2543
    return 0;
2544
}
2545

    
2546
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2547
{
2548
    return gen_intermediate_code_internal(env, tb, 0);
2549
}
2550

    
2551
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2552
{
2553
    return gen_intermediate_code_internal(env, tb, 1);
2554
}
2555

    
2556
static const char *cpu_mode_names[16] = {
2557
  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
2558
  "???", "???", "???", "und", "???", "???", "???", "sys"
2559
};
2560
void cpu_dump_state(CPUState *env, FILE *f, 
2561
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2562
                    int flags)
2563
{
2564
    int i;
2565
    union {
2566
        uint32_t i;
2567
        float s;
2568
    } s0, s1;
2569
    CPU_DoubleU d;
2570
    /* ??? This assumes float64 and double have the same layout.
2571
       Oh well, it's only debug dumps.  */
2572
    union {
2573
        float64 f64;
2574
        double d;
2575
    } d0;
2576
    uint32_t psr;
2577

    
2578
    for(i=0;i<16;i++) {
2579
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2580
        if ((i % 4) == 3)
2581
            cpu_fprintf(f, "\n");
2582
        else
2583
            cpu_fprintf(f, " ");
2584
    }
2585
    psr = cpsr_read(env);
2586
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
2587
                psr,
2588
                psr & (1 << 31) ? 'N' : '-',
2589
                psr & (1 << 30) ? 'Z' : '-',
2590
                psr & (1 << 29) ? 'C' : '-',
2591
                psr & (1 << 28) ? 'V' : '-',
2592
                psr & CPSR_T ? 'T' : 'A', 
2593
                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
2594

    
2595
    for (i = 0; i < 16; i++) {
2596
        d.d = env->vfp.regs[i];
2597
        s0.i = d.l.lower;
2598
        s1.i = d.l.upper;
2599
        d0.f64 = d.d;
2600
        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
2601
                    i * 2, (int)s0.i, s0.s,
2602
                    i * 2 + 1, (int)s1.i, s1.s,
2603
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2604
                    d0.d);
2605
    }
2606
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
2607
}
2608