Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 1e8a7cfd

History | View | Annotate | Download (66.6 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
/* internal defines */
32
typedef struct DisasContext {
33
    target_ulong pc;
34
    int is_jmp;
35
    /* Nonzero if this instruction has been conditionally skipped.  */
36
    int condjmp;
37
    /* The label that will be jumped to when the instruction is skipped.  */
38
    int condlabel;
39
    struct TranslationBlock *tb;
40
    int singlestep_enabled;
41
    int thumb;
42
} DisasContext;
43

    
44
#define DISAS_JUMP_NEXT 4
45

    
46
/* XXX: move that elsewhere */
47
static uint16_t *gen_opc_ptr;
48
static uint32_t *gen_opparam_ptr;
49
extern FILE *logfile;
50
extern int loglevel;
51

    
52
enum {
53
#define DEF(s, n, copy_size) INDEX_op_ ## s,
54
#include "opc.h"
55
#undef DEF
56
    NB_OPS,
57
};
58

    
59
#include "gen-op.h"
60

    
61
static GenOpFunc1 *gen_test_cc[14] = {
62
    gen_op_test_eq,
63
    gen_op_test_ne,
64
    gen_op_test_cs,
65
    gen_op_test_cc,
66
    gen_op_test_mi,
67
    gen_op_test_pl,
68
    gen_op_test_vs,
69
    gen_op_test_vc,
70
    gen_op_test_hi,
71
    gen_op_test_ls,
72
    gen_op_test_ge,
73
    gen_op_test_lt,
74
    gen_op_test_gt,
75
    gen_op_test_le,
76
};
77

    
78
const uint8_t table_logic_cc[16] = {
79
    1, /* and */
80
    1, /* xor */
81
    0, /* sub */
82
    0, /* rsb */
83
    0, /* add */
84
    0, /* adc */
85
    0, /* sbc */
86
    0, /* rsc */
87
    1, /* andl */
88
    1, /* xorl */
89
    0, /* cmp */
90
    0, /* cmn */
91
    1, /* orr */
92
    1, /* mov */
93
    1, /* bic */
94
    1, /* mvn */
95
};
96
    
97
static GenOpFunc1 *gen_shift_T1_im[4] = {
98
    gen_op_shll_T1_im,
99
    gen_op_shrl_T1_im,
100
    gen_op_sarl_T1_im,
101
    gen_op_rorl_T1_im,
102
};
103

    
104
static GenOpFunc *gen_shift_T1_0[4] = {
105
    NULL,
106
    gen_op_shrl_T1_0,
107
    gen_op_sarl_T1_0,
108
    gen_op_rrxl_T1,
109
};
110

    
111
static GenOpFunc1 *gen_shift_T2_im[4] = {
112
    gen_op_shll_T2_im,
113
    gen_op_shrl_T2_im,
114
    gen_op_sarl_T2_im,
115
    gen_op_rorl_T2_im,
116
};
117

    
118
static GenOpFunc *gen_shift_T2_0[4] = {
119
    NULL,
120
    gen_op_shrl_T2_0,
121
    gen_op_sarl_T2_0,
122
    gen_op_rrxl_T2,
123
};
124

    
125
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
126
    gen_op_shll_T1_im_cc,
127
    gen_op_shrl_T1_im_cc,
128
    gen_op_sarl_T1_im_cc,
129
    gen_op_rorl_T1_im_cc,
130
};
131

    
132
static GenOpFunc *gen_shift_T1_0_cc[4] = {
133
    NULL,
134
    gen_op_shrl_T1_0_cc,
135
    gen_op_sarl_T1_0_cc,
136
    gen_op_rrxl_T1_cc,
137
};
138

    
139
static GenOpFunc *gen_shift_T1_T0[4] = {
140
    gen_op_shll_T1_T0,
141
    gen_op_shrl_T1_T0,
142
    gen_op_sarl_T1_T0,
143
    gen_op_rorl_T1_T0,
144
};
145

    
146
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
147
    gen_op_shll_T1_T0_cc,
148
    gen_op_shrl_T1_T0_cc,
149
    gen_op_sarl_T1_T0_cc,
150
    gen_op_rorl_T1_T0_cc,
151
};
152

    
153
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
154
    {
155
        gen_op_movl_T0_r0,
156
        gen_op_movl_T0_r1,
157
        gen_op_movl_T0_r2,
158
        gen_op_movl_T0_r3,
159
        gen_op_movl_T0_r4,
160
        gen_op_movl_T0_r5,
161
        gen_op_movl_T0_r6,
162
        gen_op_movl_T0_r7,
163
        gen_op_movl_T0_r8,
164
        gen_op_movl_T0_r9,
165
        gen_op_movl_T0_r10,
166
        gen_op_movl_T0_r11,
167
        gen_op_movl_T0_r12,
168
        gen_op_movl_T0_r13,
169
        gen_op_movl_T0_r14,
170
        gen_op_movl_T0_r15,
171
    },
172
    {
173
        gen_op_movl_T1_r0,
174
        gen_op_movl_T1_r1,
175
        gen_op_movl_T1_r2,
176
        gen_op_movl_T1_r3,
177
        gen_op_movl_T1_r4,
178
        gen_op_movl_T1_r5,
179
        gen_op_movl_T1_r6,
180
        gen_op_movl_T1_r7,
181
        gen_op_movl_T1_r8,
182
        gen_op_movl_T1_r9,
183
        gen_op_movl_T1_r10,
184
        gen_op_movl_T1_r11,
185
        gen_op_movl_T1_r12,
186
        gen_op_movl_T1_r13,
187
        gen_op_movl_T1_r14,
188
        gen_op_movl_T1_r15,
189
    },
190
    {
191
        gen_op_movl_T2_r0,
192
        gen_op_movl_T2_r1,
193
        gen_op_movl_T2_r2,
194
        gen_op_movl_T2_r3,
195
        gen_op_movl_T2_r4,
196
        gen_op_movl_T2_r5,
197
        gen_op_movl_T2_r6,
198
        gen_op_movl_T2_r7,
199
        gen_op_movl_T2_r8,
200
        gen_op_movl_T2_r9,
201
        gen_op_movl_T2_r10,
202
        gen_op_movl_T2_r11,
203
        gen_op_movl_T2_r12,
204
        gen_op_movl_T2_r13,
205
        gen_op_movl_T2_r14,
206
        gen_op_movl_T2_r15,
207
    },
208
};
209

    
210
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
211
    {
212
        gen_op_movl_r0_T0,
213
        gen_op_movl_r1_T0,
214
        gen_op_movl_r2_T0,
215
        gen_op_movl_r3_T0,
216
        gen_op_movl_r4_T0,
217
        gen_op_movl_r5_T0,
218
        gen_op_movl_r6_T0,
219
        gen_op_movl_r7_T0,
220
        gen_op_movl_r8_T0,
221
        gen_op_movl_r9_T0,
222
        gen_op_movl_r10_T0,
223
        gen_op_movl_r11_T0,
224
        gen_op_movl_r12_T0,
225
        gen_op_movl_r13_T0,
226
        gen_op_movl_r14_T0,
227
        gen_op_movl_r15_T0,
228
    },
229
    {
230
        gen_op_movl_r0_T1,
231
        gen_op_movl_r1_T1,
232
        gen_op_movl_r2_T1,
233
        gen_op_movl_r3_T1,
234
        gen_op_movl_r4_T1,
235
        gen_op_movl_r5_T1,
236
        gen_op_movl_r6_T1,
237
        gen_op_movl_r7_T1,
238
        gen_op_movl_r8_T1,
239
        gen_op_movl_r9_T1,
240
        gen_op_movl_r10_T1,
241
        gen_op_movl_r11_T1,
242
        gen_op_movl_r12_T1,
243
        gen_op_movl_r13_T1,
244
        gen_op_movl_r14_T1,
245
        gen_op_movl_r15_T1,
246
    },
247
};
248

    
249
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
250
    gen_op_movl_T0_im,
251
    gen_op_movl_T1_im,
252
    gen_op_movl_T2_im,
253
};
254

    
255
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
256
    gen_op_shll_T0_im_thumb,
257
    gen_op_shrl_T0_im_thumb,
258
    gen_op_sarl_T0_im_thumb,
259
};
260

    
261
static inline void gen_bx(DisasContext *s)
262
{
263
  s->is_jmp = DISAS_UPDATE;
264
  gen_op_bx_T0();
265
}
266

    
267
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
268
{
269
    int val;
270

    
271
    if (reg == 15) {
272
        /* normaly, since we updated PC, we need only to add one insn */
273
        if (s->thumb)
274
            val = (long)s->pc + 2;
275
        else
276
            val = (long)s->pc + 4;
277
        gen_op_movl_TN_im[t](val);
278
    } else {
279
        gen_op_movl_TN_reg[t][reg]();
280
    }
281
}
282

    
283
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
284
{
285
    gen_movl_TN_reg(s, reg, 0);
286
}
287

    
288
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
289
{
290
    gen_movl_TN_reg(s, reg, 1);
291
}
292

    
293
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
294
{
295
    gen_movl_TN_reg(s, reg, 2);
296
}
297

    
298
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
299
{
300
    gen_op_movl_reg_TN[t][reg]();
301
    if (reg == 15) {
302
        s->is_jmp = DISAS_JUMP;
303
    }
304
}
305

    
306
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
307
{
308
    gen_movl_reg_TN(s, reg, 0);
309
}
310

    
311
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
312
{
313
    gen_movl_reg_TN(s, reg, 1);
314
}
315

    
316
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
317
{
318
    int val, rm, shift, shiftop;
319

    
320
    if (!(insn & (1 << 25))) {
321
        /* immediate */
322
        val = insn & 0xfff;
323
        if (!(insn & (1 << 23)))
324
            val = -val;
325
        if (val != 0)
326
            gen_op_addl_T1_im(val);
327
    } else {
328
        /* shift/register */
329
        rm = (insn) & 0xf;
330
        shift = (insn >> 7) & 0x1f;
331
        gen_movl_T2_reg(s, rm);
332
        shiftop = (insn >> 5) & 3;
333
        if (shift != 0) {
334
            gen_shift_T2_im[shiftop](shift);
335
        } else if (shiftop != 0) {
336
            gen_shift_T2_0[shiftop]();
337
        }
338
        if (!(insn & (1 << 23)))
339
            gen_op_subl_T1_T2();
340
        else
341
            gen_op_addl_T1_T2();
342
    }
343
}
344

    
345
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
346
{
347
    int val, rm;
348
    
349
    if (insn & (1 << 22)) {
350
        /* immediate */
351
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
352
        if (!(insn & (1 << 23)))
353
            val = -val;
354
        if (val != 0)
355
            gen_op_addl_T1_im(val);
356
    } else {
357
        /* register */
358
        rm = (insn) & 0xf;
359
        gen_movl_T2_reg(s, rm);
360
        if (!(insn & (1 << 23)))
361
            gen_op_subl_T1_T2();
362
        else
363
            gen_op_addl_T1_T2();
364
    }
365
}
366

    
367
#define VFP_OP(name)                      \
368
static inline void gen_vfp_##name(int dp) \
369
{                                         \
370
    if (dp)                               \
371
        gen_op_vfp_##name##d();           \
372
    else                                  \
373
        gen_op_vfp_##name##s();           \
374
}
375

    
376
VFP_OP(add)
377
VFP_OP(sub)
378
VFP_OP(mul)
379
VFP_OP(div)
380
VFP_OP(neg)
381
VFP_OP(abs)
382
VFP_OP(sqrt)
383
VFP_OP(cmp)
384
VFP_OP(cmpe)
385
VFP_OP(F1_ld0)
386
VFP_OP(uito)
387
VFP_OP(sito)
388
VFP_OP(toui)
389
VFP_OP(touiz)
390
VFP_OP(tosi)
391
VFP_OP(tosiz)
392
VFP_OP(ld)
393
VFP_OP(st)
394

    
395
#undef VFP_OP
396

    
397
static inline long
398
vfp_reg_offset (int dp, int reg)
399
{
400
    if (dp)
401
        return offsetof(CPUARMState, vfp.regs[reg]);
402
    else if (reg & 1) {
403
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
404
          + offsetof(CPU_DoubleU, l.upper);
405
    } else {
406
        return offsetof(CPUARMState, vfp.regs[reg >> 1])
407
          + offsetof(CPU_DoubleU, l.lower);
408
    }
409
}
410
static inline void gen_mov_F0_vreg(int dp, int reg)
411
{
412
    if (dp)
413
        gen_op_vfp_getreg_F0d(vfp_reg_offset(dp, reg));
414
    else
415
        gen_op_vfp_getreg_F0s(vfp_reg_offset(dp, reg));
416
}
417

    
418
static inline void gen_mov_F1_vreg(int dp, int reg)
419
{
420
    if (dp)
421
        gen_op_vfp_getreg_F1d(vfp_reg_offset(dp, reg));
422
    else
423
        gen_op_vfp_getreg_F1s(vfp_reg_offset(dp, reg));
424
}
425

    
426
static inline void gen_mov_vreg_F0(int dp, int reg)
427
{
428
    if (dp)
429
        gen_op_vfp_setreg_F0d(vfp_reg_offset(dp, reg));
430
    else
431
        gen_op_vfp_setreg_F0s(vfp_reg_offset(dp, reg));
432
}
433

    
434
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
435
   (ie. an undefined instruction).  */
436
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
437
{
438
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
439
    int dp, veclen;
440

    
441
    dp = ((insn & 0xf00) == 0xb00);
442
    switch ((insn >> 24) & 0xf) {
443
    case 0xe:
444
        if (insn & (1 << 4)) {
445
            /* single register transfer */
446
            if ((insn & 0x6f) != 0x00)
447
                return 1;
448
            rd = (insn >> 12) & 0xf;
449
            if (dp) {
450
                if (insn & 0x80)
451
                    return 1;
452
                rn = (insn >> 16) & 0xf;
453
                /* Get the existing value even for arm->vfp moves because
454
                   we only set half the register.  */
455
                gen_mov_F0_vreg(1, rn);
456
                gen_op_vfp_mrrd();
457
                if (insn & (1 << 20)) {
458
                    /* vfp->arm */
459
                    if (insn & (1 << 21))
460
                        gen_movl_reg_T1(s, rd);
461
                    else
462
                        gen_movl_reg_T0(s, rd);
463
                } else {
464
                    /* arm->vfp */
465
                    if (insn & (1 << 21))
466
                        gen_movl_T1_reg(s, rd);
467
                    else
468
                        gen_movl_T0_reg(s, rd);
469
                    gen_op_vfp_mdrr();
470
                    gen_mov_vreg_F0(dp, rn);
471
                }
472
            } else {
473
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
474
                if (insn & (1 << 20)) {
475
                    /* vfp->arm */
476
                    if (insn & (1 << 21)) {
477
                        /* system register */
478
                        switch (rn) {
479
                        case 0: /* fpsid */
480
                            n = 0x0091A0000;
481
                            break;
482
                        case 2: /* fpscr */
483
                            if (rd == 15)
484
                                gen_op_vfp_movl_T0_fpscr_flags();
485
                            else
486
                                gen_op_vfp_movl_T0_fpscr();
487
                            break;
488
                        default:
489
                            return 1;
490
                        }
491
                    } else {
492
                        gen_mov_F0_vreg(0, rn);
493
                        gen_op_vfp_mrs();
494
                    }
495
                    if (rd == 15) {
496
                        /* This will only set the 4 flag bits */
497
                        gen_op_movl_psr_T0();
498
                    } else
499
                        gen_movl_reg_T0(s, rd);
500
                } else {
501
                    /* arm->vfp */
502
                    gen_movl_T0_reg(s, rd);
503
                    if (insn & (1 << 21)) {
504
                        /* system register */
505
                        switch (rn) {
506
                        case 0: /* fpsid */
507
                            /* Writes are ignored.  */
508
                            break;
509
                        case 2: /* fpscr */
510
                            gen_op_vfp_movl_fpscr_T0();
511
                            /* This could change vector settings, so jump to
512
                               the next instuction.  */
513
                            gen_op_movl_T0_im(s->pc);
514
                            gen_movl_reg_T0(s, 15);
515
                            s->is_jmp = DISAS_UPDATE;
516
                            break;
517
                        default:
518
                            return 1;
519
                        }
520
                    } else {
521
                        gen_op_vfp_msr();
522
                        gen_mov_vreg_F0(0, rn);
523
                    }
524
                }
525
            }
526
        } else {
527
            /* data processing */
528
            /* The opcode is in bits 23, 21, 20 and 6.  */
529
            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
530
            if (dp) {
531
                if (op == 15) {
532
                    /* rn is opcode */
533
                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
534
                } else {
535
                    /* rn is register number */
536
                    if (insn & (1 << 7))
537
                        return 1;
538
                    rn = (insn >> 16) & 0xf;
539
                }
540

    
541
                if (op == 15 && (rn == 15 || rn > 17)) {
542
                    /* Integer or single precision destination.  */
543
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
544
                } else {
545
                    if (insn & (1 << 22))
546
                        return 1;
547
                    rd = (insn >> 12) & 0xf;
548
                }
549

    
550
                if (op == 15 && (rn == 16 || rn == 17)) {
551
                    /* Integer source.  */
552
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
553
                } else {
554
                    if (insn & (1 << 5))
555
                        return 1;
556
                    rm = insn & 0xf;
557
                }
558
            } else {
559
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
560
                if (op == 15 && rn == 15) {
561
                    /* Double precision destination.  */
562
                    if (insn & (1 << 22))
563
                        return 1;
564
                    rd = (insn >> 12) & 0xf;
565
                } else
566
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
567
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
568
            }
569

    
570
            veclen = env->vfp.vec_len;
571
            if (op == 15 && rn > 3)
572
                veclen = 0;
573

    
574
            /* Shut up compiler warnings.  */
575
            delta_m = 0;
576
            delta_d = 0;
577
            bank_mask = 0;
578
            
579
            if (veclen > 0) {
580
                if (dp)
581
                    bank_mask = 0xc;
582
                else
583
                    bank_mask = 0x18;
584

    
585
                /* Figure out what type of vector operation this is.  */
586
                if ((rd & bank_mask) == 0) {
587
                    /* scalar */
588
                    veclen = 0;
589
                } else {
590
                    if (dp)
591
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
592
                    else
593
                        delta_d = env->vfp.vec_stride + 1;
594

    
595
                    if ((rm & bank_mask) == 0) {
596
                        /* mixed scalar/vector */
597
                        delta_m = 0;
598
                    } else {
599
                        /* vector */
600
                        delta_m = delta_d;
601
                    }
602
                }
603
            }
604

    
605
            /* Load the initial operands.  */
606
            if (op == 15) {
607
                switch (rn) {
608
                case 16:
609
                case 17:
610
                    /* Integer source */
611
                    gen_mov_F0_vreg(0, rm);
612
                    break;
613
                case 8:
614
                case 9:
615
                    /* Compare */
616
                    gen_mov_F0_vreg(dp, rd);
617
                    gen_mov_F1_vreg(dp, rm);
618
                    break;
619
                case 10:
620
                case 11:
621
                    /* Compare with zero */
622
                    gen_mov_F0_vreg(dp, rd);
623
                    gen_vfp_F1_ld0(dp);
624
                    break;
625
                default:
626
                    /* One source operand.  */
627
                    gen_mov_F0_vreg(dp, rm);
628
                }
629
            } else {
630
                /* Two source operands.  */
631
                gen_mov_F0_vreg(dp, rn);
632
                gen_mov_F1_vreg(dp, rm);
633
            }
634

    
635
            for (;;) {
636
                /* Perform the calculation.  */
637
                switch (op) {
638
                case 0: /* mac: fd + (fn * fm) */
639
                    gen_vfp_mul(dp);
640
                    gen_mov_F1_vreg(dp, rd);
641
                    gen_vfp_add(dp);
642
                    break;
643
                case 1: /* nmac: fd - (fn * fm) */
644
                    gen_vfp_mul(dp);
645
                    gen_vfp_neg(dp);
646
                    gen_mov_F1_vreg(dp, rd);
647
                    gen_vfp_add(dp);
648
                    break;
649
                case 2: /* msc: -fd + (fn * fm) */
650
                    gen_vfp_mul(dp);
651
                    gen_mov_F1_vreg(dp, rd);
652
                    gen_vfp_sub(dp);
653
                    break;
654
                case 3: /* nmsc: -fd - (fn * fm)  */
655
                    gen_vfp_mul(dp);
656
                    gen_mov_F1_vreg(dp, rd);
657
                    gen_vfp_add(dp);
658
                    gen_vfp_neg(dp);
659
                    break;
660
                case 4: /* mul: fn * fm */
661
                    gen_vfp_mul(dp);
662
                    break;
663
                case 5: /* nmul: -(fn * fm) */
664
                    gen_vfp_mul(dp);
665
                    gen_vfp_neg(dp);
666
                    break;
667
                case 6: /* add: fn + fm */
668
                    gen_vfp_add(dp);
669
                    break;
670
                case 7: /* sub: fn - fm */
671
                    gen_vfp_sub(dp);
672
                    break;
673
                case 8: /* div: fn / fm */
674
                    gen_vfp_div(dp);
675
                    break;
676
                case 15: /* extension space */
677
                    switch (rn) {
678
                    case 0: /* cpy */
679
                        /* no-op */
680
                        break;
681
                    case 1: /* abs */
682
                        gen_vfp_abs(dp);
683
                        break;
684
                    case 2: /* neg */
685
                        gen_vfp_neg(dp);
686
                        break;
687
                    case 3: /* sqrt */
688
                        gen_vfp_sqrt(dp);
689
                        break;
690
                    case 8: /* cmp */
691
                        gen_vfp_cmp(dp);
692
                        break;
693
                    case 9: /* cmpe */
694
                        gen_vfp_cmpe(dp);
695
                        break;
696
                    case 10: /* cmpz */
697
                        gen_vfp_cmp(dp);
698
                        break;
699
                    case 11: /* cmpez */
700
                        gen_vfp_F1_ld0(dp);
701
                        gen_vfp_cmpe(dp);
702
                        break;
703
                    case 15: /* single<->double conversion */
704
                        if (dp)
705
                            gen_op_vfp_fcvtsd();
706
                        else
707
                            gen_op_vfp_fcvtds();
708
                        break;
709
                    case 16: /* fuito */
710
                        gen_vfp_uito(dp);
711
                        break;
712
                    case 17: /* fsito */
713
                        gen_vfp_sito(dp);
714
                        break;
715
                    case 24: /* ftoui */
716
                        gen_vfp_toui(dp);
717
                        break;
718
                    case 25: /* ftouiz */
719
                        gen_vfp_touiz(dp);
720
                        break;
721
                    case 26: /* ftosi */
722
                        gen_vfp_tosi(dp);
723
                        break;
724
                    case 27: /* ftosiz */
725
                        gen_vfp_tosiz(dp);
726
                        break;
727
                    default: /* undefined */
728
                        printf ("rn:%d\n", rn);
729
                        return 1;
730
                    }
731
                    break;
732
                default: /* undefined */
733
                    printf ("op:%d\n", op);
734
                    return 1;
735
                }
736

    
737
                /* Write back the result.  */
738
                if (op == 15 && (rn >= 8 && rn <= 11))
739
                    ; /* Comparison, do nothing.  */
740
                else if (op == 15 && rn > 17)
741
                    /* Integer result.  */
742
                    gen_mov_vreg_F0(0, rd);
743
                else if (op == 15 && rn == 15)
744
                    /* conversion */
745
                    gen_mov_vreg_F0(!dp, rd);
746
                else
747
                    gen_mov_vreg_F0(dp, rd);
748

    
749
                /* break out of the loop if we have finished  */
750
                if (veclen == 0)
751
                    break;
752

    
753
                if (op == 15 && delta_m == 0) {
754
                    /* single source one-many */
755
                    while (veclen--) {
756
                        rd = ((rd + delta_d) & (bank_mask - 1))
757
                             | (rd & bank_mask);
758
                        gen_mov_vreg_F0(dp, rd);
759
                    }
760
                    break;
761
                }
762
                /* Setup the next operands.  */
763
                veclen--;
764
                rd = ((rd + delta_d) & (bank_mask - 1))
765
                     | (rd & bank_mask);
766

    
767
                if (op == 15) {
768
                    /* One source operand.  */
769
                    rm = ((rm + delta_m) & (bank_mask - 1))
770
                         | (rm & bank_mask);
771
                    gen_mov_F0_vreg(dp, rm);
772
                } else {
773
                    /* Two source operands.  */
774
                    rn = ((rn + delta_d) & (bank_mask - 1))
775
                         | (rn & bank_mask);
776
                    gen_mov_F0_vreg(dp, rn);
777
                    if (delta_m) {
778
                        rm = ((rm + delta_m) & (bank_mask - 1))
779
                             | (rm & bank_mask);
780
                        gen_mov_F1_vreg(dp, rm);
781
                    }
782
                }
783
            }
784
        }
785
        break;
786
    case 0xc:
787
    case 0xd:
788
        if (dp && (insn & (1 << 22))) {
789
            /* two-register transfer */
790
            rn = (insn >> 16) & 0xf;
791
            rd = (insn >> 12) & 0xf;
792
            if (dp) {
793
                if (insn & (1 << 5))
794
                    return 1;
795
                rm = insn & 0xf;
796
            } else
797
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
798

    
799
            if (insn & (1 << 20)) {
800
                /* vfp->arm */
801
                if (dp) {
802
                    gen_mov_F0_vreg(1, rm);
803
                    gen_op_vfp_mrrd();
804
                    gen_movl_reg_T0(s, rd);
805
                    gen_movl_reg_T1(s, rn);
806
                } else {
807
                    gen_mov_F0_vreg(0, rm);
808
                    gen_op_vfp_mrs();
809
                    gen_movl_reg_T0(s, rn);
810
                    gen_mov_F0_vreg(0, rm + 1);
811
                    gen_op_vfp_mrs();
812
                    gen_movl_reg_T0(s, rd);
813
                }
814
            } else {
815
                /* arm->vfp */
816
                if (dp) {
817
                    gen_movl_T0_reg(s, rd);
818
                    gen_movl_T1_reg(s, rn);
819
                    gen_op_vfp_mdrr();
820
                    gen_mov_vreg_F0(1, rm);
821
                } else {
822
                    gen_movl_T0_reg(s, rn);
823
                    gen_op_vfp_msr();
824
                    gen_mov_vreg_F0(0, rm);
825
                    gen_movl_T0_reg(s, rd);
826
                    gen_op_vfp_msr();
827
                    gen_mov_vreg_F0(0, rm + 1);
828
                }
829
            }
830
        } else {
831
            /* Load/store */
832
            rn = (insn >> 16) & 0xf;
833
            if (dp)
834
                rd = (insn >> 12) & 0xf;
835
            else
836
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
837
            gen_movl_T1_reg(s, rn);
838
            if ((insn & 0x01200000) == 0x01000000) {
839
                /* Single load/store */
840
                offset = (insn & 0xff) << 2;
841
                if ((insn & (1 << 23)) == 0)
842
                    offset = -offset;
843
                gen_op_addl_T1_im(offset);
844
                if (insn & (1 << 20)) {
845
                    gen_vfp_ld(dp);
846
                    gen_mov_vreg_F0(dp, rd);
847
                } else {
848
                    gen_mov_F0_vreg(dp, rd);
849
                    gen_vfp_st(dp);
850
                }
851
            } else {
852
                /* load/store multiple */
853
                if (dp)
854
                    n = (insn >> 1) & 0x7f;
855
                else
856
                    n = insn & 0xff;
857

    
858
                if (insn & (1 << 24)) /* pre-decrement */
859
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
860

    
861
                if (dp)
862
                    offset = 8;
863
                else
864
                    offset = 4;
865
                for (i = 0; i < n; i++) {
866
                    if (insn & (1 << 20)) {
867
                        /* load */
868
                        gen_vfp_ld(dp);
869
                        gen_mov_vreg_F0(dp, rd + i);
870
                    } else {
871
                        /* store */
872
                        gen_mov_F0_vreg(dp, rd + i);
873
                        gen_vfp_st(dp);
874
                    }
875
                    gen_op_addl_T1_im(offset);
876
                }
877
                if (insn & (1 << 21)) {
878
                    /* writeback */
879
                    if (insn & (1 << 24))
880
                        offset = -offset * n;
881
                    else if (dp && (insn & 1))
882
                        offset = 4;
883
                    else
884
                        offset = 0;
885

    
886
                    if (offset != 0)
887
                        gen_op_addl_T1_im(offset);
888
                    gen_movl_reg_T1(s, rn);
889
                }
890
            }
891
        }
892
        break;
893
    default:
894
        /* Should never happen.  */
895
        return 1;
896
    }
897
    return 0;
898
}
899

    
900
static inline void gen_jmp (DisasContext *s, uint32_t dest)
901
{
902
    if (__builtin_expect(s->singlestep_enabled, 0)) {
903
        /* An indirect jump so that we still trigger the debug exception.  */
904
        if (s->thumb)
905
          dest |= 1;
906
        gen_op_movl_T0_im(dest);
907
        gen_bx(s);
908
    } else {
909
        gen_op_jmp0((long)s->tb, dest);
910
        s->is_jmp = DISAS_TB_JUMP;
911
    }
912
}
913

    
914
static void disas_arm_insn(CPUState * env, DisasContext *s)
915
{
916
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
917
    
918
    insn = ldl(s->pc);
919
    s->pc += 4;
920
    
921
    cond = insn >> 28;
922
    if (cond == 0xf){
923
        /* Unconditional instructions.  */
924
        if ((insn & 0x0d70f000) == 0x0550f000)
925
            return; /* PLD */
926
        else if ((insn & 0x0e000000) == 0x0a000000) {
927
            /* branch link and change to thumb (blx <offset>) */
928
            int32_t offset;
929

    
930
            val = (uint32_t)s->pc;
931
            gen_op_movl_T0_im(val);
932
            gen_movl_reg_T0(s, 14);
933
            /* Sign-extend the 24-bit offset */
934
            offset = (((int32_t)insn) << 8) >> 8;
935
            /* offset * 4 + bit24 * 2 + (thumb bit) */
936
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
937
            /* pipeline offset */
938
            val += 4;
939
            gen_op_movl_T0_im(val);
940
            gen_bx(s);
941
            return;
942
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
943
            /* Coprocessor double register transfer.  */
944
        } else if ((insn & 0x0f000010) == 0x0e000010) {
945
            /* Additional coprocessor register transfer.  */
946
        }
947
        goto illegal_op;
948
    }
949
    if (cond != 0xe) {
950
        /* if not always execute, we generate a conditional jump to
951
           next instruction */
952
        s->condlabel = gen_new_label();
953
        gen_test_cc[cond ^ 1](s->condlabel);
954
        s->condjmp = 1;
955
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
956
        //s->is_jmp = DISAS_JUMP_NEXT;
957
    }
958
    if ((insn & 0x0f900000) == 0x03000000) {
959
        if ((insn & 0x0ff0f000) != 0x0360f000)
960
            goto illegal_op;
961
        /* CPSR = immediate */
962
        val = insn & 0xff;
963
        shift = ((insn >> 8) & 0xf) * 2;
964
        if (shift)
965
            val = (val >> shift) | (val << (32 - shift));
966
        gen_op_movl_T0_im(val);
967
        if (insn & (1 << 19))
968
            gen_op_movl_psr_T0();
969
    } else if ((insn & 0x0f900000) == 0x01000000
970
               && (insn & 0x00000090) != 0x00000090) {
971
        /* miscellaneous instructions */
972
        op1 = (insn >> 21) & 3;
973
        sh = (insn >> 4) & 0xf;
974
        rm = insn & 0xf;
975
        switch (sh) {
976
        case 0x0: /* move program status register */
977
            if (op1 & 2) {
978
                /* SPSR not accessible in user mode */
979
                goto illegal_op;
980
            }
981
            if (op1 & 1) {
982
                /* CPSR = reg */
983
                gen_movl_T0_reg(s, rm);
984
                if (insn & (1 << 19))
985
                    gen_op_movl_psr_T0();
986
            } else {
987
                /* reg = CPSR */
988
                rd = (insn >> 12) & 0xf;
989
                gen_op_movl_T0_psr();
990
                gen_movl_reg_T0(s, rd);
991
            }
992
            break;
993
        case 0x1:
994
            if (op1 == 1) {
995
                /* branch/exchange thumb (bx).  */
996
                gen_movl_T0_reg(s, rm);
997
                gen_bx(s);
998
            } else if (op1 == 3) {
999
                /* clz */
1000
                rd = (insn >> 12) & 0xf;
1001
                gen_movl_T0_reg(s, rm);
1002
                gen_op_clz_T0();
1003
                gen_movl_reg_T0(s, rd);
1004
            } else {
1005
                goto illegal_op;
1006
            }
1007
            break;
1008
        case 0x3:
1009
            if (op1 != 1)
1010
              goto illegal_op;
1011

    
1012
            /* branch link/exchange thumb (blx) */
1013
            val = (uint32_t)s->pc;
1014
            gen_op_movl_T0_im(val);
1015
            gen_movl_reg_T0(s, 14);
1016
            gen_movl_T0_reg(s, rm);
1017
            gen_bx(s);
1018
            break;
1019
        case 0x5: /* saturating add/subtract */
1020
            rd = (insn >> 12) & 0xf;
1021
            rn = (insn >> 16) & 0xf;
1022
            gen_movl_T0_reg(s, rm);
1023
            gen_movl_T1_reg(s, rn);
1024
            if (op1 & 2)
1025
                gen_op_double_T1_saturate();
1026
            if (op1 & 1)
1027
                gen_op_subl_T0_T1_saturate();
1028
            else
1029
                gen_op_addl_T0_T1_saturate();
1030
            gen_movl_reg_T0(s, rd);
1031
            break;
1032
        case 0x8: /* signed multiply */
1033
        case 0xa:
1034
        case 0xc:
1035
        case 0xe:
1036
            rs = (insn >> 8) & 0xf;
1037
            rn = (insn >> 12) & 0xf;
1038
            rd = (insn >> 16) & 0xf;
1039
            if (op1 == 1) {
1040
                /* (32 * 16) >> 16 */
1041
                gen_movl_T0_reg(s, rm);
1042
                gen_movl_T1_reg(s, rs);
1043
                if (sh & 4)
1044
                    gen_op_sarl_T1_im(16);
1045
                else
1046
                    gen_op_sxl_T1();
1047
                gen_op_imulw_T0_T1();
1048
                if ((sh & 2) == 0) {
1049
                    gen_movl_T1_reg(s, rn);
1050
                    gen_op_addl_T0_T1_setq();
1051
                }
1052
                gen_movl_reg_T0(s, rd);
1053
            } else {
1054
                /* 16 * 16 */
1055
                gen_movl_T0_reg(s, rm);
1056
                if (sh & 2)
1057
                    gen_op_sarl_T0_im(16);
1058
                else
1059
                    gen_op_sxl_T0();
1060
                gen_movl_T1_reg(s, rs);
1061
                if (sh & 4)
1062
                    gen_op_sarl_T1_im(16);
1063
                else
1064
                    gen_op_sxl_T1();
1065
                if (op1 == 2) {
1066
                    gen_op_imull_T0_T1();
1067
                    gen_op_addq_T0_T1(rn, rd);
1068
                    gen_movl_reg_T0(s, rn);
1069
                    gen_movl_reg_T1(s, rd);
1070
                } else {
1071
                    gen_op_mul_T0_T1();
1072
                    if (op1 == 0) {
1073
                        gen_movl_T1_reg(s, rn);
1074
                        gen_op_addl_T0_T1_setq();
1075
                    }
1076
                    gen_movl_reg_T0(s, rd);
1077
                }
1078
            }
1079
            break;
1080
        default:
1081
            goto illegal_op;
1082
        }
1083
    } else if (((insn & 0x0e000000) == 0 &&
1084
                (insn & 0x00000090) != 0x90) ||
1085
               ((insn & 0x0e000000) == (1 << 25))) {
1086
        int set_cc, logic_cc, shiftop;
1087
        
1088
        op1 = (insn >> 21) & 0xf;
1089
        set_cc = (insn >> 20) & 1;
1090
        logic_cc = table_logic_cc[op1] & set_cc;
1091

    
1092
        /* data processing instruction */
1093
        if (insn & (1 << 25)) {
1094
            /* immediate operand */
1095
            val = insn & 0xff;
1096
            shift = ((insn >> 8) & 0xf) * 2;
1097
            if (shift)
1098
                val = (val >> shift) | (val << (32 - shift));
1099
            gen_op_movl_T1_im(val);
1100
            if (logic_cc && shift)
1101
                gen_op_mov_CF_T1();
1102
        } else {
1103
            /* register */
1104
            rm = (insn) & 0xf;
1105
            gen_movl_T1_reg(s, rm);
1106
            shiftop = (insn >> 5) & 3;
1107
            if (!(insn & (1 << 4))) {
1108
                shift = (insn >> 7) & 0x1f;
1109
                if (shift != 0) {
1110
                    if (logic_cc) {
1111
                        gen_shift_T1_im_cc[shiftop](shift);
1112
                    } else {
1113
                        gen_shift_T1_im[shiftop](shift);
1114
                    }
1115
                } else if (shiftop != 0) {
1116
                    if (logic_cc) {
1117
                        gen_shift_T1_0_cc[shiftop]();
1118
                    } else {
1119
                        gen_shift_T1_0[shiftop]();
1120
                    }
1121
                }
1122
            } else {
1123
                rs = (insn >> 8) & 0xf;
1124
                gen_movl_T0_reg(s, rs);
1125
                if (logic_cc) {
1126
                    gen_shift_T1_T0_cc[shiftop]();
1127
                } else {
1128
                    gen_shift_T1_T0[shiftop]();
1129
                }
1130
            }
1131
        }
1132
        if (op1 != 0x0f && op1 != 0x0d) {
1133
            rn = (insn >> 16) & 0xf;
1134
            gen_movl_T0_reg(s, rn);
1135
        }
1136
        rd = (insn >> 12) & 0xf;
1137
        switch(op1) {
1138
        case 0x00:
1139
            gen_op_andl_T0_T1();
1140
            gen_movl_reg_T0(s, rd);
1141
            if (logic_cc)
1142
                gen_op_logic_T0_cc();
1143
            break;
1144
        case 0x01:
1145
            gen_op_xorl_T0_T1();
1146
            gen_movl_reg_T0(s, rd);
1147
            if (logic_cc)
1148
                gen_op_logic_T0_cc();
1149
            break;
1150
        case 0x02:
1151
            if (set_cc)
1152
                gen_op_subl_T0_T1_cc();
1153
            else
1154
                gen_op_subl_T0_T1();
1155
            gen_movl_reg_T0(s, rd);
1156
            break;
1157
        case 0x03:
1158
            if (set_cc)
1159
                gen_op_rsbl_T0_T1_cc();
1160
            else
1161
                gen_op_rsbl_T0_T1();
1162
            gen_movl_reg_T0(s, rd);
1163
            break;
1164
        case 0x04:
1165
            if (set_cc)
1166
                gen_op_addl_T0_T1_cc();
1167
            else
1168
                gen_op_addl_T0_T1();
1169
            gen_movl_reg_T0(s, rd);
1170
            break;
1171
        case 0x05:
1172
            if (set_cc)
1173
                gen_op_adcl_T0_T1_cc();
1174
            else
1175
                gen_op_adcl_T0_T1();
1176
            gen_movl_reg_T0(s, rd);
1177
            break;
1178
        case 0x06:
1179
            if (set_cc)
1180
                gen_op_sbcl_T0_T1_cc();
1181
            else
1182
                gen_op_sbcl_T0_T1();
1183
            gen_movl_reg_T0(s, rd);
1184
            break;
1185
        case 0x07:
1186
            if (set_cc)
1187
                gen_op_rscl_T0_T1_cc();
1188
            else
1189
                gen_op_rscl_T0_T1();
1190
            gen_movl_reg_T0(s, rd);
1191
            break;
1192
        case 0x08:
1193
            if (set_cc) {
1194
                gen_op_andl_T0_T1();
1195
                gen_op_logic_T0_cc();
1196
            }
1197
            break;
1198
        case 0x09:
1199
            if (set_cc) {
1200
                gen_op_xorl_T0_T1();
1201
                gen_op_logic_T0_cc();
1202
            }
1203
            break;
1204
        case 0x0a:
1205
            if (set_cc) {
1206
                gen_op_subl_T0_T1_cc();
1207
            }
1208
            break;
1209
        case 0x0b:
1210
            if (set_cc) {
1211
                gen_op_addl_T0_T1_cc();
1212
            }
1213
            break;
1214
        case 0x0c:
1215
            gen_op_orl_T0_T1();
1216
            gen_movl_reg_T0(s, rd);
1217
            if (logic_cc)
1218
                gen_op_logic_T0_cc();
1219
            break;
1220
        case 0x0d:
1221
            gen_movl_reg_T1(s, rd);
1222
            if (logic_cc)
1223
                gen_op_logic_T1_cc();
1224
            break;
1225
        case 0x0e:
1226
            gen_op_bicl_T0_T1();
1227
            gen_movl_reg_T0(s, rd);
1228
            if (logic_cc)
1229
                gen_op_logic_T0_cc();
1230
            break;
1231
        default:
1232
        case 0x0f:
1233
            gen_op_notl_T1();
1234
            gen_movl_reg_T1(s, rd);
1235
            if (logic_cc)
1236
                gen_op_logic_T1_cc();
1237
            break;
1238
        }
1239
    } else {
1240
        /* other instructions */
1241
        op1 = (insn >> 24) & 0xf;
1242
        switch(op1) {
1243
        case 0x0:
1244
        case 0x1:
1245
            /* multiplies, extra load/stores */
1246
            sh = (insn >> 5) & 3;
1247
            if (sh == 0) {
1248
                if (op1 == 0x0) {
1249
                    rd = (insn >> 16) & 0xf;
1250
                    rn = (insn >> 12) & 0xf;
1251
                    rs = (insn >> 8) & 0xf;
1252
                    rm = (insn) & 0xf;
1253
                    if (((insn >> 22) & 3) == 0) {
1254
                        /* 32 bit mul */
1255
                        gen_movl_T0_reg(s, rs);
1256
                        gen_movl_T1_reg(s, rm);
1257
                        gen_op_mul_T0_T1();
1258
                        if (insn & (1 << 21)) {
1259
                            gen_movl_T1_reg(s, rn);
1260
                            gen_op_addl_T0_T1();
1261
                        }
1262
                        if (insn & (1 << 20)) 
1263
                            gen_op_logic_T0_cc();
1264
                        gen_movl_reg_T0(s, rd);
1265
                    } else {
1266
                        /* 64 bit mul */
1267
                        gen_movl_T0_reg(s, rs);
1268
                        gen_movl_T1_reg(s, rm);
1269
                        if (insn & (1 << 22)) 
1270
                            gen_op_imull_T0_T1();
1271
                        else
1272
                            gen_op_mull_T0_T1();
1273
                        if (insn & (1 << 21)) /* mult accumulate */
1274
                            gen_op_addq_T0_T1(rn, rd);
1275
                        if (!(insn & (1 << 23))) { /* double accumulate */
1276
                            gen_op_addq_lo_T0_T1(rn);
1277
                            gen_op_addq_lo_T0_T1(rd);
1278
                        }
1279
                        if (insn & (1 << 20)) 
1280
                            gen_op_logicq_cc();
1281
                        gen_movl_reg_T0(s, rn);
1282
                        gen_movl_reg_T1(s, rd);
1283
                    }
1284
                } else {
1285
                    rn = (insn >> 16) & 0xf;
1286
                    rd = (insn >> 12) & 0xf;
1287
                    if (insn & (1 << 23)) {
1288
                        /* load/store exclusive */
1289
                        goto illegal_op;
1290
                    } else {
1291
                        /* SWP instruction */
1292
                        rm = (insn) & 0xf;
1293
                        
1294
                        gen_movl_T0_reg(s, rm);
1295
                        gen_movl_T1_reg(s, rn);
1296
                        if (insn & (1 << 22)) {
1297
                            gen_op_swpb_T0_T1();
1298
                        } else {
1299
                            gen_op_swpl_T0_T1();
1300
                        }
1301
                        gen_movl_reg_T0(s, rd);
1302
                    }
1303
                }
1304
            } else {
1305
                /* Misc load/store */
1306
                rn = (insn >> 16) & 0xf;
1307
                rd = (insn >> 12) & 0xf;
1308
                gen_movl_T1_reg(s, rn);
1309
                if (insn & (1 << 24))
1310
                    gen_add_datah_offset(s, insn);
1311
                if (insn & (1 << 20)) {
1312
                    /* load */
1313
                    switch(sh) {
1314
                    case 1:
1315
                        gen_op_lduw_T0_T1();
1316
                        break;
1317
                    case 2:
1318
                        gen_op_ldsb_T0_T1();
1319
                        break;
1320
                    default:
1321
                    case 3:
1322
                        gen_op_ldsw_T0_T1();
1323
                        break;
1324
                    }
1325
                    gen_movl_reg_T0(s, rd);
1326
                } else if (sh & 2) {
1327
                    /* doubleword */
1328
                    if (sh & 1) {
1329
                        /* store */
1330
                        gen_movl_T0_reg(s, rd);
1331
                        gen_op_stl_T0_T1();
1332
                        gen_op_addl_T1_im(4);
1333
                        gen_movl_T0_reg(s, rd + 1);
1334
                        gen_op_stl_T0_T1();
1335
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1336
                            gen_op_addl_T1_im(-4);
1337
                    } else {
1338
                        /* load */
1339
                        gen_op_ldl_T0_T1();
1340
                        gen_movl_reg_T0(s, rd);
1341
                        gen_op_addl_T1_im(4);
1342
                        gen_op_ldl_T0_T1();
1343
                        gen_movl_reg_T0(s, rd + 1);
1344
                        if ((insn & (1 << 24)) || (insn & (1 << 20)))
1345
                            gen_op_addl_T1_im(-4);
1346
                    }
1347
                } else {
1348
                    /* store */
1349
                    gen_movl_T0_reg(s, rd);
1350
                    gen_op_stw_T0_T1();
1351
                }
1352
                if (!(insn & (1 << 24))) {
1353
                    gen_add_datah_offset(s, insn);
1354
                    gen_movl_reg_T1(s, rn);
1355
                } else if (insn & (1 << 21)) {
1356
                    gen_movl_reg_T1(s, rn);
1357
                }
1358
            }
1359
            break;
1360
        case 0x4:
1361
        case 0x5:
1362
        case 0x6:
1363
        case 0x7:
1364
            /* load/store byte/word */
1365
            rn = (insn >> 16) & 0xf;
1366
            rd = (insn >> 12) & 0xf;
1367
            gen_movl_T1_reg(s, rn);
1368
            if (insn & (1 << 24))
1369
                gen_add_data_offset(s, insn);
1370
            if (insn & (1 << 20)) {
1371
                /* load */
1372
                if (insn & (1 << 22))
1373
                    gen_op_ldub_T0_T1();
1374
                else
1375
                    gen_op_ldl_T0_T1();
1376
                if (rd == 15)
1377
                    gen_bx(s);
1378
                else
1379
                    gen_movl_reg_T0(s, rd);
1380
            } else {
1381
                /* store */
1382
                gen_movl_T0_reg(s, rd);
1383
                if (insn & (1 << 22))
1384
                    gen_op_stb_T0_T1();
1385
                else
1386
                    gen_op_stl_T0_T1();
1387
            }
1388
            if (!(insn & (1 << 24))) {
1389
                gen_add_data_offset(s, insn);
1390
                gen_movl_reg_T1(s, rn);
1391
            } else if (insn & (1 << 21))
1392
                gen_movl_reg_T1(s, rn); {
1393
            }
1394
            break;
1395
        case 0x08:
1396
        case 0x09:
1397
            {
1398
                int j, n;
1399
                /* load/store multiple words */
1400
                /* XXX: store correct base if write back */
1401
                if (insn & (1 << 22))
1402
                    goto illegal_op; /* only usable in supervisor mode */
1403
                rn = (insn >> 16) & 0xf;
1404
                gen_movl_T1_reg(s, rn);
1405
                
1406
                /* compute total size */
1407
                n = 0;
1408
                for(i=0;i<16;i++) {
1409
                    if (insn & (1 << i))
1410
                        n++;
1411
                }
1412
                /* XXX: test invalid n == 0 case ? */
1413
                if (insn & (1 << 23)) {
1414
                    if (insn & (1 << 24)) {
1415
                        /* pre increment */
1416
                        gen_op_addl_T1_im(4);
1417
                    } else {
1418
                        /* post increment */
1419
                    }
1420
                } else {
1421
                    if (insn & (1 << 24)) {
1422
                        /* pre decrement */
1423
                        gen_op_addl_T1_im(-(n * 4));
1424
                    } else {
1425
                        /* post decrement */
1426
                        if (n != 1)
1427
                            gen_op_addl_T1_im(-((n - 1) * 4));
1428
                    }
1429
                }
1430
                j = 0;
1431
                for(i=0;i<16;i++) {
1432
                    if (insn & (1 << i)) {
1433
                        if (insn & (1 << 20)) {
1434
                            /* load */
1435
                            gen_op_ldl_T0_T1();
1436
                            if (i == 15)
1437
                                gen_bx(s);
1438
                            else
1439
                                gen_movl_reg_T0(s, i);
1440
                        } else {
1441
                            /* store */
1442
                            if (i == 15) {
1443
                                /* special case: r15 = PC + 12 */
1444
                                val = (long)s->pc + 8;
1445
                                gen_op_movl_TN_im[0](val);
1446
                            } else {
1447
                                gen_movl_T0_reg(s, i);
1448
                            }
1449
                            gen_op_stl_T0_T1();
1450
                        }
1451
                        j++;
1452
                        /* no need to add after the last transfer */
1453
                        if (j != n)
1454
                            gen_op_addl_T1_im(4);
1455
                    }
1456
                }
1457
                if (insn & (1 << 21)) {
1458
                    /* write back */
1459
                    if (insn & (1 << 23)) {
1460
                        if (insn & (1 << 24)) {
1461
                            /* pre increment */
1462
                        } else {
1463
                            /* post increment */
1464
                            gen_op_addl_T1_im(4);
1465
                        }
1466
                    } else {
1467
                        if (insn & (1 << 24)) {
1468
                            /* pre decrement */
1469
                            if (n != 1)
1470
                                gen_op_addl_T1_im(-((n - 1) * 4));
1471
                        } else {
1472
                            /* post decrement */
1473
                            gen_op_addl_T1_im(-(n * 4));
1474
                        }
1475
                    }
1476
                    gen_movl_reg_T1(s, rn);
1477
                }
1478
            }
1479
            break;
1480
        case 0xa:
1481
        case 0xb:
1482
            {
1483
                int32_t offset;
1484
                
1485
                /* branch (and link) */
1486
                val = (int32_t)s->pc;
1487
                if (insn & (1 << 24)) {
1488
                    gen_op_movl_T0_im(val);
1489
                    gen_op_movl_reg_TN[0][14]();
1490
                }
1491
                offset = (((int32_t)insn << 8) >> 8);
1492
                val += (offset << 2) + 4;
1493
                gen_jmp(s, val);
1494
            }
1495
            break;
1496
        case 0xc:
1497
        case 0xd:
1498
        case 0xe:
1499
            /* Coprocessor.  */
1500
            op1 = (insn >> 8) & 0xf;
1501
            switch (op1) {
1502
            case 10:
1503
            case 11:
1504
                if (disas_vfp_insn (env, s, insn))
1505
                    goto illegal_op;
1506
                break;
1507
            default:
1508
                /* unknown coprocessor.  */
1509
                goto illegal_op;
1510
            }
1511
            break;
1512
        case 0xf:
1513
            /* swi */
1514
            gen_op_movl_T0_im((long)s->pc);
1515
            gen_op_movl_reg_TN[0][15]();
1516
            gen_op_swi();
1517
            s->is_jmp = DISAS_JUMP;
1518
            break;
1519
        default:
1520
        illegal_op:
1521
            gen_op_movl_T0_im((long)s->pc - 4);
1522
            gen_op_movl_reg_TN[0][15]();
1523
            gen_op_undef_insn();
1524
            s->is_jmp = DISAS_JUMP;
1525
            break;
1526
        }
1527
    }
1528
}
1529

    
1530
static void disas_thumb_insn(DisasContext *s)
1531
{
1532
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1533
    int32_t offset;
1534
    int i;
1535

    
1536
    insn = lduw(s->pc);
1537
    s->pc += 2;
1538
    
1539
    switch (insn >> 12) {
1540
    case 0: case 1:
1541
        rd = insn & 7;
1542
        op = (insn >> 11) & 3;
1543
        if (op == 3) {
1544
            /* add/subtract */
1545
            rn = (insn >> 3) & 7;
1546
            gen_movl_T0_reg(s, rn);
1547
            if (insn & (1 << 10)) {
1548
                /* immediate */
1549
                gen_op_movl_T1_im((insn >> 6) & 7);
1550
            } else {
1551
                /* reg */
1552
                rm = (insn >> 6) & 7;
1553
                gen_movl_T1_reg(s, rm);
1554
            }
1555
            if (insn & (1 << 9))
1556
                gen_op_subl_T0_T1_cc();
1557
            else
1558
                gen_op_addl_T0_T1_cc();
1559
            gen_movl_reg_T0(s, rd);
1560
        } else {
1561
            /* shift immediate */
1562
            rm = (insn >> 3) & 7;
1563
            shift = (insn >> 6) & 0x1f;
1564
            gen_movl_T0_reg(s, rm);
1565
            gen_shift_T0_im_thumb[op](shift);
1566
            gen_movl_reg_T0(s, rd);
1567
        }
1568
        break;
1569
    case 2: case 3:
1570
        /* arithmetic large immediate */
1571
        op = (insn >> 11) & 3;
1572
        rd = (insn >> 8) & 0x7;
1573
        if (op == 0) {
1574
            gen_op_movl_T0_im(insn & 0xff);
1575
        } else {
1576
            gen_movl_T0_reg(s, rd);
1577
            gen_op_movl_T1_im(insn & 0xff);
1578
        }
1579
        switch (op) {
1580
        case 0: /* mov */
1581
            gen_op_logic_T0_cc();
1582
            break;
1583
        case 1: /* cmp */
1584
            gen_op_subl_T0_T1_cc();
1585
            break;
1586
        case 2: /* add */
1587
            gen_op_addl_T0_T1_cc();
1588
            break;
1589
        case 3: /* sub */
1590
            gen_op_subl_T0_T1_cc();
1591
            break;
1592
        }
1593
        if (op != 1)
1594
            gen_movl_reg_T0(s, rd);
1595
        break;
1596
    case 4:
1597
        if (insn & (1 << 11)) {
1598
            rd = (insn >> 8) & 7;
1599
            /* load pc-relative.  Bit 1 of PC is ignored.  */
1600
            val = s->pc + 2 + ((insn & 0xff) * 4);
1601
            val &= ~(uint32_t)2;
1602
            gen_op_movl_T1_im(val);
1603
            gen_op_ldl_T0_T1();
1604
            gen_movl_reg_T0(s, rd);
1605
            break;
1606
        }
1607
        if (insn & (1 << 10)) {
1608
            /* data processing extended or blx */
1609
            rd = (insn & 7) | ((insn >> 4) & 8);
1610
            rm = (insn >> 3) & 0xf;
1611
            op = (insn >> 8) & 3;
1612
            switch (op) {
1613
            case 0: /* add */
1614
                gen_movl_T0_reg(s, rd);
1615
                gen_movl_T1_reg(s, rm);
1616
                gen_op_addl_T0_T1();
1617
                gen_movl_reg_T0(s, rd);
1618
                break;
1619
            case 1: /* cmp */
1620
                gen_movl_T0_reg(s, rd);
1621
                gen_movl_T1_reg(s, rm);
1622
                gen_op_subl_T0_T1_cc();
1623
                break;
1624
            case 2: /* mov/cpy */
1625
                gen_movl_T0_reg(s, rm);
1626
                gen_movl_reg_T0(s, rd);
1627
                break;
1628
            case 3:/* branch [and link] exchange thumb register */
1629
                if (insn & (1 << 7)) {
1630
                    val = (uint32_t)s->pc | 1;
1631
                    gen_op_movl_T1_im(val);
1632
                    gen_movl_reg_T1(s, 14);
1633
                }
1634
                gen_movl_T0_reg(s, rm);
1635
                gen_bx(s);
1636
                break;
1637
            }
1638
            break;
1639
        }
1640

    
1641
        /* data processing register */
1642
        rd = insn & 7;
1643
        rm = (insn >> 3) & 7;
1644
        op = (insn >> 6) & 0xf;
1645
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1646
            /* the shift/rotate ops want the operands backwards */
1647
            val = rm;
1648
            rm = rd;
1649
            rd = val;
1650
            val = 1;
1651
        } else {
1652
            val = 0;
1653
        }
1654

    
1655
        if (op == 9) /* neg */
1656
            gen_op_movl_T0_im(0);
1657
        else if (op != 0xf) /* mvn doesn't read its first operand */
1658
            gen_movl_T0_reg(s, rd);
1659

    
1660
        gen_movl_T1_reg(s, rm);
1661
        switch (op) {
1662
        case 0x0: /* and */
1663
            gen_op_andl_T0_T1();
1664
            gen_op_logic_T0_cc();
1665
            break;
1666
        case 0x1: /* eor */
1667
            gen_op_xorl_T0_T1();
1668
            gen_op_logic_T0_cc();
1669
            break;
1670
        case 0x2: /* lsl */
1671
            gen_op_shll_T1_T0_cc();
1672
            break;
1673
        case 0x3: /* lsr */
1674
            gen_op_shrl_T1_T0_cc();
1675
            break;
1676
        case 0x4: /* asr */
1677
            gen_op_sarl_T1_T0_cc();
1678
            break;
1679
        case 0x5: /* adc */
1680
            gen_op_adcl_T0_T1_cc();
1681
            break;
1682
        case 0x6: /* sbc */
1683
            gen_op_sbcl_T0_T1_cc();
1684
            break;
1685
        case 0x7: /* ror */
1686
            gen_op_rorl_T1_T0_cc();
1687
            break;
1688
        case 0x8: /* tst */
1689
            gen_op_andl_T0_T1();
1690
            gen_op_logic_T0_cc();
1691
            rd = 16;
1692
            break;
1693
        case 0x9: /* neg */
1694
            gen_op_subl_T0_T1_cc();
1695
            break;
1696
        case 0xa: /* cmp */
1697
            gen_op_subl_T0_T1_cc();
1698
            rd = 16;
1699
            break;
1700
        case 0xb: /* cmn */
1701
            gen_op_addl_T0_T1_cc();
1702
            rd = 16;
1703
            break;
1704
        case 0xc: /* orr */
1705
            gen_op_orl_T0_T1();
1706
            gen_op_logic_T0_cc();
1707
            break;
1708
        case 0xd: /* mul */
1709
            gen_op_mull_T0_T1();
1710
            gen_op_logic_T0_cc();
1711
            break;
1712
        case 0xe: /* bic */
1713
            gen_op_bicl_T0_T1();
1714
            gen_op_logic_T0_cc();
1715
            break;
1716
        case 0xf: /* mvn */
1717
            gen_op_notl_T1();
1718
            gen_op_logic_T1_cc();
1719
            val = 1;
1720
            rm = rd;
1721
            break;
1722
        }
1723
        if (rd != 16) {
1724
            if (val)
1725
                gen_movl_reg_T1(s, rm);
1726
            else
1727
                gen_movl_reg_T0(s, rd);
1728
        }
1729
        break;
1730

    
1731
    case 5:
1732
        /* load/store register offset.  */
1733
        rd = insn & 7;
1734
        rn = (insn >> 3) & 7;
1735
        rm = (insn >> 6) & 7;
1736
        op = (insn >> 9) & 7;
1737
        gen_movl_T1_reg(s, rn);
1738
        gen_movl_T2_reg(s, rm);
1739
        gen_op_addl_T1_T2();
1740

    
1741
        if (op < 3) /* store */
1742
            gen_movl_T0_reg(s, rd);
1743

    
1744
        switch (op) {
1745
        case 0: /* str */
1746
            gen_op_stl_T0_T1();
1747
            break;
1748
        case 1: /* strh */
1749
            gen_op_stw_T0_T1();
1750
            break;
1751
        case 2: /* strb */
1752
            gen_op_stb_T0_T1();
1753
            break;
1754
        case 3: /* ldrsb */
1755
            gen_op_ldsb_T0_T1();
1756
            break;
1757
        case 4: /* ldr */
1758
            gen_op_ldl_T0_T1();
1759
            break;
1760
        case 5: /* ldrh */
1761
            gen_op_lduw_T0_T1();
1762
            break;
1763
        case 6: /* ldrb */
1764
            gen_op_ldub_T0_T1();
1765
            break;
1766
        case 7: /* ldrsh */
1767
            gen_op_ldsw_T0_T1();
1768
            break;
1769
        }
1770
        if (op >= 3) /* load */
1771
            gen_movl_reg_T0(s, rd);
1772
        break;
1773

    
1774
    case 6:
1775
        /* load/store word immediate offset */
1776
        rd = insn & 7;
1777
        rn = (insn >> 3) & 7;
1778
        gen_movl_T1_reg(s, rn);
1779
        val = (insn >> 4) & 0x7c;
1780
        gen_op_movl_T2_im(val);
1781
        gen_op_addl_T1_T2();
1782

    
1783
        if (insn & (1 << 11)) {
1784
            /* load */
1785
            gen_op_ldl_T0_T1();
1786
            gen_movl_reg_T0(s, rd);
1787
        } else {
1788
            /* store */
1789
            gen_movl_T0_reg(s, rd);
1790
            gen_op_stl_T0_T1();
1791
        }
1792
        break;
1793

    
1794
    case 7:
1795
        /* load/store byte immediate offset */
1796
        rd = insn & 7;
1797
        rn = (insn >> 3) & 7;
1798
        gen_movl_T1_reg(s, rn);
1799
        val = (insn >> 6) & 0x1f;
1800
        gen_op_movl_T2_im(val);
1801
        gen_op_addl_T1_T2();
1802

    
1803
        if (insn & (1 << 11)) {
1804
            /* load */
1805
            gen_op_ldub_T0_T1();
1806
            gen_movl_reg_T0(s, rd);
1807
        } else {
1808
            /* store */
1809
            gen_movl_T0_reg(s, rd);
1810
            gen_op_stb_T0_T1();
1811
        }
1812
        break;
1813

    
1814
    case 8:
1815
        /* load/store halfword immediate offset */
1816
        rd = insn & 7;
1817
        rn = (insn >> 3) & 7;
1818
        gen_movl_T1_reg(s, rn);
1819
        val = (insn >> 5) & 0x3e;
1820
        gen_op_movl_T2_im(val);
1821
        gen_op_addl_T1_T2();
1822

    
1823
        if (insn & (1 << 11)) {
1824
            /* load */
1825
            gen_op_lduw_T0_T1();
1826
            gen_movl_reg_T0(s, rd);
1827
        } else {
1828
            /* store */
1829
            gen_movl_T0_reg(s, rd);
1830
            gen_op_stw_T0_T1();
1831
        }
1832
        break;
1833

    
1834
    case 9:
1835
        /* load/store from stack */
1836
        rd = (insn >> 8) & 7;
1837
        gen_movl_T1_reg(s, 13);
1838
        val = (insn & 0xff) * 4;
1839
        gen_op_movl_T2_im(val);
1840
        gen_op_addl_T1_T2();
1841

    
1842
        if (insn & (1 << 11)) {
1843
            /* load */
1844
            gen_op_ldl_T0_T1();
1845
            gen_movl_reg_T0(s, rd);
1846
        } else {
1847
            /* store */
1848
            gen_movl_T0_reg(s, rd);
1849
            gen_op_stl_T0_T1();
1850
        }
1851
        break;
1852

    
1853
    case 10:
1854
        /* add to high reg */
1855
        rd = (insn >> 8) & 7;
1856
        if (insn & (1 << 11)) {
1857
            /* SP */
1858
            gen_movl_T0_reg(s, 13);
1859
        } else {
1860
            /* PC. bit 1 is ignored.  */
1861
            gen_op_movl_T0_im((s->pc + 2) & ~(uint32_t)2);
1862
        }
1863
        val = (insn & 0xff) * 4;
1864
        gen_op_movl_T1_im(val);
1865
        gen_op_addl_T0_T1();
1866
        gen_movl_reg_T0(s, rd);
1867
        break;
1868

    
1869
    case 11:
1870
        /* misc */
1871
        op = (insn >> 8) & 0xf;
1872
        switch (op) {
1873
        case 0:
1874
            /* adjust stack pointer */
1875
            gen_movl_T1_reg(s, 13);
1876
            val = (insn & 0x7f) * 4;
1877
            if (insn & (1 << 7))
1878
              val = -(int32_t)val;
1879
            gen_op_movl_T2_im(val);
1880
            gen_op_addl_T1_T2();
1881
            gen_movl_reg_T1(s, 13);
1882
            break;
1883

    
1884
        case 4: case 5: case 0xc: case 0xd:
1885
            /* push/pop */
1886
            gen_movl_T1_reg(s, 13);
1887
            if (insn & (1 << 8))
1888
                offset = 4;
1889
            else
1890
                offset = 0;
1891
            for (i = 0; i < 8; i++) {
1892
                if (insn & (1 << i))
1893
                    offset += 4;
1894
            }
1895
            if ((insn & (1 << 11)) == 0) {
1896
                gen_op_movl_T2_im(-offset);
1897
                gen_op_addl_T1_T2();
1898
            }
1899
            gen_op_movl_T2_im(4);
1900
            for (i = 0; i < 8; i++) {
1901
                if (insn & (1 << i)) {
1902
                    if (insn & (1 << 11)) {
1903
                        /* pop */
1904
                        gen_op_ldl_T0_T1();
1905
                        gen_movl_reg_T0(s, i);
1906
                    } else {
1907
                        /* push */
1908
                        gen_movl_T0_reg(s, i);
1909
                        gen_op_stl_T0_T1();
1910
                    }
1911
                    /* advance to the next address.  */
1912
                    gen_op_addl_T1_T2();
1913
                }
1914
            }
1915
            if (insn & (1 << 8)) {
1916
                if (insn & (1 << 11)) {
1917
                    /* pop pc */
1918
                    gen_op_ldl_T0_T1();
1919
                    /* don't set the pc until the rest of the instruction
1920
                       has completed */
1921
                } else {
1922
                    /* push lr */
1923
                    gen_movl_T0_reg(s, 14);
1924
                    gen_op_stl_T0_T1();
1925
                }
1926
                gen_op_addl_T1_T2();
1927
            }
1928
            if ((insn & (1 << 11)) == 0) {
1929
                gen_op_movl_T2_im(-offset);
1930
                gen_op_addl_T1_T2();
1931
            }
1932
            /* write back the new stack pointer */
1933
            gen_movl_reg_T1(s, 13);
1934
            /* set the new PC value */
1935
            if ((insn & 0x0900) == 0x0900)
1936
                gen_bx(s);
1937
            break;
1938

    
1939
        default:
1940
            goto undef;
1941
        }
1942
        break;
1943

    
1944
    case 12:
1945
        /* load/store multiple */
1946
        rn = (insn >> 8) & 0x7;
1947
        gen_movl_T1_reg(s, rn);
1948
        gen_op_movl_T2_im(4);
1949
        for (i = 0; i < 8; i++) {
1950
            if (insn & (1 << i)) {
1951
                if (insn & (1 << 11)) {
1952
                    /* load */
1953
                    gen_op_ldl_T0_T1();
1954
                    gen_movl_reg_T0(s, i);
1955
                } else {
1956
                    /* store */
1957
                    gen_movl_T0_reg(s, i);
1958
                    gen_op_stl_T0_T1();
1959
                }
1960
                /* advance to the next address */
1961
                gen_op_addl_T1_T2();
1962
            }
1963
        }
1964
        /* Base register writeback.  */
1965
        gen_movl_reg_T1(s, rn);
1966
        break;
1967

    
1968
    case 13:
1969
        /* conditional branch or swi */
1970
        cond = (insn >> 8) & 0xf;
1971
        if (cond == 0xe)
1972
            goto undef;
1973

    
1974
        if (cond == 0xf) {
1975
            /* swi */
1976
            gen_op_movl_T0_im((long)s->pc | 1);
1977
            /* Don't set r15.  */
1978
            gen_op_movl_reg_TN[0][15]();
1979
            gen_op_swi();
1980
            s->is_jmp = DISAS_JUMP;
1981
            break;
1982
        }
1983
        /* generate a conditional jump to next instruction */
1984
        s->condlabel = gen_new_label();
1985
        gen_test_cc[cond ^ 1](s->condlabel);
1986
        s->condjmp = 1;
1987
        //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1988
        //s->is_jmp = DISAS_JUMP_NEXT;
1989
        gen_movl_T1_reg(s, 15);
1990

    
1991
        /* jump to the offset */
1992
        val = (uint32_t)s->pc + 2;
1993
        offset = ((int32_t)insn << 24) >> 24;
1994
        val += offset << 1;
1995
        gen_jmp(s, val);
1996
        break;
1997

    
1998
    case 14:
1999
        /* unconditional branch */
2000
        if (insn & (1 << 11))
2001
            goto undef; /* Second half of a blx */
2002
        val = (uint32_t)s->pc;
2003
        offset = ((int32_t)insn << 21) >> 21;
2004
        val += (offset << 1) + 2;
2005
        gen_jmp(s, val);
2006
        break;
2007

    
2008
    case 15:
2009
        /* branch and link [and switch to arm] */
2010
        offset = ((int32_t)insn << 21) >> 10;
2011
        insn = lduw(s->pc);
2012
        offset |= insn & 0x7ff;
2013

    
2014
        val = (uint32_t)s->pc + 2;
2015
        gen_op_movl_T1_im(val | 1);
2016
        gen_movl_reg_T1(s, 14);
2017
        
2018
        val += offset << 1;
2019
        if (insn & (1 << 11)) {
2020
            /* bl */
2021
            gen_jmp(s, val);
2022
        } else {
2023
            /* blx */
2024
            val &= ~(uint32_t)2;
2025
            gen_op_movl_T0_im(val);
2026
            gen_bx(s);
2027
        }
2028
    }
2029
    return;
2030
undef:
2031
    gen_op_movl_T0_im((long)s->pc - 2);
2032
    gen_op_movl_reg_TN[0][15]();
2033
    gen_op_undef_insn();
2034
    s->is_jmp = DISAS_JUMP;
2035
}
2036

    
2037
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
2038
   basic block 'tb'. If search_pc is TRUE, also generate PC
2039
   information for each intermediate instruction. */
2040
static inline int gen_intermediate_code_internal(CPUState *env, 
2041
                                                 TranslationBlock *tb, 
2042
                                                 int search_pc)
2043
{
2044
    DisasContext dc1, *dc = &dc1;
2045
    uint16_t *gen_opc_end;
2046
    int j, lj;
2047
    target_ulong pc_start;
2048
    
2049
    /* generate intermediate code */
2050
    pc_start = tb->pc;
2051
       
2052
    dc->tb = tb;
2053

    
2054
    gen_opc_ptr = gen_opc_buf;
2055
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2056
    gen_opparam_ptr = gen_opparam_buf;
2057

    
2058
    dc->is_jmp = DISAS_NEXT;
2059
    dc->pc = pc_start;
2060
    dc->singlestep_enabled = env->singlestep_enabled;
2061
    dc->condjmp = 0;
2062
    dc->thumb = env->thumb;
2063
    nb_gen_labels = 0;
2064
    lj = -1;
2065
    do {
2066
        if (env->nb_breakpoints > 0) {
2067
            for(j = 0; j < env->nb_breakpoints; j++) {
2068
                if (env->breakpoints[j] == dc->pc) {
2069
                    gen_op_movl_T0_im((long)dc->pc);
2070
                    gen_op_movl_reg_TN[0][15]();
2071
                    gen_op_debug();
2072
                    dc->is_jmp = DISAS_JUMP;
2073
                    break;
2074
                }
2075
            }
2076
        }
2077
        if (search_pc) {
2078
            j = gen_opc_ptr - gen_opc_buf;
2079
            if (lj < j) {
2080
                lj++;
2081
                while (lj < j)
2082
                    gen_opc_instr_start[lj++] = 0;
2083
            }
2084
            gen_opc_pc[lj] = dc->pc;
2085
            gen_opc_instr_start[lj] = 1;
2086
        }
2087

    
2088
        if (env->thumb)
2089
          disas_thumb_insn(dc);
2090
        else
2091
          disas_arm_insn(env, dc);
2092

    
2093
        if (dc->condjmp && !dc->is_jmp) {
2094
            gen_set_label(dc->condlabel);
2095
            dc->condjmp = 0;
2096
        }
2097
        /* Translation stops when a conditional branch is enoutered.
2098
         * Otherwise the subsequent code could get translated several times.
2099
         */
2100
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2101
             !env->singlestep_enabled &&
2102
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2103
    /* It this stage dc->condjmp will only be set when the skipped
2104
     * instruction was a conditional branch, and teh PC has already been
2105
     * written.  */
2106
    if (__builtin_expect(env->singlestep_enabled, 0)) {
2107
        /* Make sure the pc is updated, and raise a debug exception.  */
2108
        if (dc->condjmp) {
2109
            gen_op_debug();
2110
            gen_set_label(dc->condlabel);
2111
        }
2112
        if (dc->condjmp || !dc->is_jmp) {
2113
            gen_op_movl_T0_im((long)dc->pc);
2114
            gen_op_movl_reg_TN[0][15]();
2115
            dc->condjmp = 0;
2116
        }
2117
        gen_op_debug();
2118
    } else {
2119
        switch(dc->is_jmp) {
2120
        case DISAS_NEXT:
2121
            gen_op_jmp1((long)dc->tb, (long)dc->pc);
2122
            break;
2123
        default:
2124
        case DISAS_JUMP:
2125
        case DISAS_UPDATE:
2126
            /* indicate that the hash table must be used to find the next TB */
2127
            gen_op_movl_T0_0();
2128
            gen_op_exit_tb();
2129
            break;
2130
        case DISAS_TB_JUMP:
2131
            /* nothing more to generate */
2132
            break;
2133
        }
2134
        if (dc->condjmp) {
2135
            gen_set_label(dc->condlabel);
2136
            gen_op_jmp1((long)dc->tb, (long)dc->pc);
2137
            dc->condjmp = 0;
2138
        }
2139
    }
2140
    *gen_opc_ptr = INDEX_op_end;
2141

    
2142
#ifdef DEBUG_DISAS
2143
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2144
        fprintf(logfile, "----------------\n");
2145
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2146
        target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
2147
        fprintf(logfile, "\n");
2148
        if (loglevel & (CPU_LOG_TB_OP)) {
2149
            fprintf(logfile, "OP:\n");
2150
            dump_ops(gen_opc_buf, gen_opparam_buf);
2151
            fprintf(logfile, "\n");
2152
        }
2153
    }
2154
#endif
2155
    if (!search_pc)
2156
        tb->size = dc->pc - pc_start;
2157
    return 0;
2158
}
2159

    
2160
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2161
{
2162
    return gen_intermediate_code_internal(env, tb, 0);
2163
}
2164

    
2165
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2166
{
2167
    return gen_intermediate_code_internal(env, tb, 1);
2168
}
2169

    
2170
CPUARMState *cpu_arm_init(void)
2171
{
2172
    CPUARMState *env;
2173

    
2174
    cpu_exec_init();
2175

    
2176
    env = malloc(sizeof(CPUARMState));
2177
    if (!env)
2178
        return NULL;
2179
    memset(env, 0, sizeof(CPUARMState));
2180
    cpu_single_env = env;
2181
    return env;
2182
}
2183

    
2184
void cpu_arm_close(CPUARMState *env)
2185
{
2186
    free(env);
2187
}
2188

    
2189
void cpu_dump_state(CPUState *env, FILE *f, 
2190
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2191
                    int flags)
2192
{
2193
    int i;
2194
    union {
2195
        uint32_t i;
2196
        float s;
2197
    } s0, s1;
2198
    CPU_DoubleU d;
2199

    
2200
    for(i=0;i<16;i++) {
2201
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2202
        if ((i % 4) == 3)
2203
            cpu_fprintf(f, "\n");
2204
        else
2205
            cpu_fprintf(f, " ");
2206
    }
2207
    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c\n", 
2208
             env->cpsr, 
2209
            env->cpsr & (1 << 31) ? 'N' : '-',
2210
            env->cpsr & (1 << 30) ? 'Z' : '-',
2211
            env->cpsr & (1 << 29) ? 'C' : '-',
2212
            env->cpsr & (1 << 28) ? 'V' : '-',
2213
            env->thumb ? 'T' : 'A');
2214

    
2215
    for (i = 0; i < 16; i++) {
2216
        d.d = env->vfp.regs[i];
2217
        s0.i = d.l.lower;
2218
        s1.i = d.l.upper;
2219
        cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2220
                    i * 2, (int)s0.i, s0.s,
2221
                    i * 2 + 1, (int)s0.i, s0.s,
2222
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2223
                    d.d);
2224
    }
2225
    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2226
}
2227

    
2228
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2229
{
2230
    return addr;
2231
}
2232

    
2233
#if defined(CONFIG_USER_ONLY) 
2234

    
2235
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2236
                              int is_user, int is_softmmu)
2237
{
2238
    env->cp15_6 = address;
2239
    if (rw == 2) {
2240
        env->exception_index = EXCP_PREFETCH_ABORT;
2241
    } else {
2242
        env->exception_index = EXCP_DATA_ABORT;
2243
    }
2244
    return 1;
2245
}
2246

    
2247
#else
2248

    
2249
#error not implemented
2250

    
2251
#endif