Statistics
| Branch: | Revision:

root / target-arm / translate.c @ 157777ef

History | View | Annotate | Download (63.7 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
    struct TranslationBlock *tb;
36
} DisasContext;
37

    
38
#define DISAS_JUMP_NEXT 4
39

    
40
/* XXX: move that elsewhere */
41
static uint16_t *gen_opc_ptr;
42
static uint32_t *gen_opparam_ptr;
43
extern FILE *logfile;
44
extern int loglevel;
45

    
46
enum {
47
#define DEF(s, n, copy_size) INDEX_op_ ## s,
48
#include "opc.h"
49
#undef DEF
50
    NB_OPS,
51
};
52

    
53
#include "gen-op.h"
54

    
55
static GenOpFunc2 *gen_test_cc[14] = {
56
    gen_op_test_eq,
57
    gen_op_test_ne,
58
    gen_op_test_cs,
59
    gen_op_test_cc,
60
    gen_op_test_mi,
61
    gen_op_test_pl,
62
    gen_op_test_vs,
63
    gen_op_test_vc,
64
    gen_op_test_hi,
65
    gen_op_test_ls,
66
    gen_op_test_ge,
67
    gen_op_test_lt,
68
    gen_op_test_gt,
69
    gen_op_test_le,
70
};
71

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

    
98
static GenOpFunc *gen_shift_T1_0[4] = {
99
    NULL,
100
    gen_op_shrl_T1_0,
101
    gen_op_sarl_T1_0,
102
    gen_op_rrxl_T1,
103
};
104

    
105
static GenOpFunc1 *gen_shift_T2_im[4] = {
106
    gen_op_shll_T2_im,
107
    gen_op_shrl_T2_im,
108
    gen_op_sarl_T2_im,
109
    gen_op_rorl_T2_im,
110
};
111

    
112
static GenOpFunc *gen_shift_T2_0[4] = {
113
    NULL,
114
    gen_op_shrl_T2_0,
115
    gen_op_sarl_T2_0,
116
    gen_op_rrxl_T2,
117
};
118

    
119
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
120
    gen_op_shll_T1_im_cc,
121
    gen_op_shrl_T1_im_cc,
122
    gen_op_sarl_T1_im_cc,
123
    gen_op_rorl_T1_im_cc,
124
};
125

    
126
static GenOpFunc *gen_shift_T1_0_cc[4] = {
127
    NULL,
128
    gen_op_shrl_T1_0_cc,
129
    gen_op_sarl_T1_0_cc,
130
    gen_op_rrxl_T1_cc,
131
};
132

    
133
static GenOpFunc *gen_shift_T1_T0[4] = {
134
    gen_op_shll_T1_T0,
135
    gen_op_shrl_T1_T0,
136
    gen_op_sarl_T1_T0,
137
    gen_op_rorl_T1_T0,
138
};
139

    
140
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
141
    gen_op_shll_T1_T0_cc,
142
    gen_op_shrl_T1_T0_cc,
143
    gen_op_sarl_T1_T0_cc,
144
    gen_op_rorl_T1_T0_cc,
145
};
146

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

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

    
243
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
244
    gen_op_movl_T0_im,
245
    gen_op_movl_T1_im,
246
    gen_op_movl_T2_im,
247
};
248

    
249
static GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
250
    gen_op_shll_T0_im_thumb,
251
    gen_op_shrl_T0_im_thumb,
252
    gen_op_sarl_T0_im_thumb,
253
};
254

    
255
static inline void gen_bx(DisasContext *s)
256
{
257
  s->is_jmp = DISAS_UPDATE;
258
  gen_op_bx_T0();
259
}
260

    
261
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
262
{
263
    int val;
264

    
265
    if (reg == 15) {
266
        /* normaly, since we updated PC, we need only to add 4 */
267
        val = (long)s->pc + 4;
268
        gen_op_movl_TN_im[t](val);
269
    } else {
270
        gen_op_movl_TN_reg[t][reg]();
271
    }
272
}
273

    
274
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
275
{
276
    gen_movl_TN_reg(s, reg, 0);
277
}
278

    
279
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
280
{
281
    gen_movl_TN_reg(s, reg, 1);
282
}
283

    
284
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
285
{
286
    gen_movl_TN_reg(s, reg, 2);
287
}
288

    
289
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
290
{
291
    gen_op_movl_reg_TN[t][reg]();
292
    if (reg == 15) {
293
        s->is_jmp = DISAS_JUMP;
294
    }
295
}
296

    
297
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
298
{
299
    gen_movl_reg_TN(s, reg, 0);
300
}
301

    
302
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
303
{
304
    gen_movl_reg_TN(s, reg, 1);
305
}
306

    
307
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
308
{
309
    int val, rm, shift, shiftop;
310

    
311
    if (!(insn & (1 << 25))) {
312
        /* immediate */
313
        val = insn & 0xfff;
314
        if (!(insn & (1 << 23)))
315
            val = -val;
316
        if (val != 0)
317
            gen_op_addl_T1_im(val);
318
    } else {
319
        /* shift/register */
320
        rm = (insn) & 0xf;
321
        shift = (insn >> 7) & 0x1f;
322
        gen_movl_T2_reg(s, rm);
323
        shiftop = (insn >> 5) & 3;
324
        if (shift != 0) {
325
            gen_shift_T2_im[shiftop](shift);
326
        } else if (shiftop != 0) {
327
            gen_shift_T2_0[shiftop]();
328
        }
329
        if (!(insn & (1 << 23)))
330
            gen_op_subl_T1_T2();
331
        else
332
            gen_op_addl_T1_T2();
333
    }
334
}
335

    
336
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
337
{
338
    int val, rm;
339
    
340
    if (insn & (1 << 22)) {
341
        /* immediate */
342
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
343
        if (!(insn & (1 << 23)))
344
            val = -val;
345
        if (val != 0)
346
            gen_op_addl_T1_im(val);
347
    } else {
348
        /* register */
349
        rm = (insn) & 0xf;
350
        gen_movl_T2_reg(s, rm);
351
        if (!(insn & (1 << 23)))
352
            gen_op_subl_T1_T2();
353
        else
354
            gen_op_addl_T1_T2();
355
    }
356
}
357

    
358
#define VFP_OP(name)                      \
359
static inline void gen_vfp_##name(int dp) \
360
{                                         \
361
    if (dp)                               \
362
        gen_op_vfp_##name##d();           \
363
    else                                  \
364
        gen_op_vfp_##name##s();           \
365
}
366

    
367
VFP_OP(add)
368
VFP_OP(sub)
369
VFP_OP(mul)
370
VFP_OP(div)
371
VFP_OP(neg)
372
VFP_OP(abs)
373
VFP_OP(sqrt)
374
VFP_OP(cmp)
375
VFP_OP(cmpe)
376
VFP_OP(F1_ld0)
377
VFP_OP(uito)
378
VFP_OP(sito)
379
VFP_OP(toui)
380
VFP_OP(touiz)
381
VFP_OP(tosi)
382
VFP_OP(tosiz)
383
VFP_OP(ld)
384
VFP_OP(st)
385

    
386
#undef VFP_OP
387

    
388
static inline void gen_mov_F0_vreg(int dp, int reg)
389
{
390
    if (dp)
391
        gen_op_vfp_getreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
392
    else
393
        gen_op_vfp_getreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
394
}
395

    
396
static inline void gen_mov_F1_vreg(int dp, int reg)
397
{
398
    if (dp)
399
        gen_op_vfp_getreg_F1d(offsetof(CPUARMState, vfp.regs.d[reg]));
400
    else
401
        gen_op_vfp_getreg_F1s(offsetof(CPUARMState, vfp.regs.s[reg]));
402
}
403

    
404
static inline void gen_mov_vreg_F0(int dp, int reg)
405
{
406
    if (dp)
407
        gen_op_vfp_setreg_F0d(offsetof(CPUARMState, vfp.regs.d[reg]));
408
    else
409
        gen_op_vfp_setreg_F0s(offsetof(CPUARMState, vfp.regs.s[reg]));
410
}
411

    
412
/* Disassemble a VFP instruction.  Returns nonzero if an error occured
413
   (ie. an undefined instruction).  */
414
static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
415
{
416
    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
417
    int dp, veclen;
418

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

    
519
                if (op == 15 && (rn == 15 || rn > 17)) {
520
                    /* Integer or single precision destination.  */
521
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
522
                } else {
523
                    if (insn & (1 << 22))
524
                        return 1;
525
                    rd = (insn >> 12) & 0xf;
526
                }
527

    
528
                if (op == 15 && (rn == 16 || rn == 17)) {
529
                    /* Integer source.  */
530
                    rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
531
                } else {
532
                    if (insn & (1 << 5))
533
                        return 1;
534
                    rm = insn & 0xf;
535
                }
536
            } else {
537
                rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
538
                if (op == 15 && rn == 15) {
539
                    /* Double precision destination.  */
540
                    if (insn & (1 << 22))
541
                        return 1;
542
                    rd = (insn >> 12) & 0xf;
543
                } else
544
                    rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
545
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
546
            }
547

    
548
            veclen = env->vfp.vec_len;
549
            if (op == 15 && rn > 3)
550
                veclen = 0;
551

    
552
            /* Shut up compiler warnings.  */
553
            delta_m = 0;
554
            delta_d = 0;
555
            bank_mask = 0;
556
            
557
            if (veclen > 0) {
558
                if (dp)
559
                    bank_mask = 0xc;
560
                else
561
                    bank_mask = 0x18;
562

    
563
                /* Figure out what type of vector operation this is.  */
564
                if ((rd & bank_mask) == 0) {
565
                    /* scalar */
566
                    veclen = 0;
567
                } else {
568
                    if (dp)
569
                        delta_d = (env->vfp.vec_stride >> 1) + 1;
570
                    else
571
                        delta_d = env->vfp.vec_stride + 1;
572

    
573
                    if ((rm & bank_mask) == 0) {
574
                        /* mixed scalar/vector */
575
                        delta_m = 0;
576
                    } else {
577
                        /* vector */
578
                        delta_m = delta_d;
579
                    }
580
                }
581
            }
582

    
583
            /* Load the initial operands.  */
584
            if (op == 15) {
585
                switch (rn) {
586
                case 16:
587
                case 17:
588
                    /* Integer source */
589
                    gen_mov_F0_vreg(0, rm);
590
                    break;
591
                case 8:
592
                case 9:
593
                    /* Compare */
594
                    gen_mov_F0_vreg(dp, rd);
595
                    gen_mov_F1_vreg(dp, rm);
596
                    break;
597
                case 10:
598
                case 11:
599
                    /* Compare with zero */
600
                    gen_mov_F0_vreg(dp, rd);
601
                    gen_vfp_F1_ld0(dp);
602
                    break;
603
                default:
604
                    /* One source operand.  */
605
                    gen_mov_F0_vreg(dp, rm);
606
                }
607
            } else {
608
                /* Two source operands.  */
609
                gen_mov_F0_vreg(dp, rn);
610
                gen_mov_F1_vreg(dp, rm);
611
            }
612

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

    
715
                /* Write back the result.  */
716
                if (op == 15 && (rn >= 8 && rn <= 11))
717
                    ; /* Comparison, do nothing.  */
718
                else if (op == 15 && rn > 17)
719
                    /* Integer result.  */
720
                    gen_mov_vreg_F0(0, rd);
721
                else if (op == 15 && rn == 15)
722
                    /* conversion */
723
                    gen_mov_vreg_F0(!dp, rd);
724
                else
725
                    gen_mov_vreg_F0(dp, rd);
726

    
727
                /* break out of the loop if we have finished  */
728
                if (veclen == 0)
729
                    break;
730

    
731
                if (op == 15 && delta_m == 0) {
732
                    /* single source one-many */
733
                    while (veclen--) {
734
                        rd = ((rd + delta_d) & (bank_mask - 1))
735
                             | (rd & bank_mask);
736
                        gen_mov_vreg_F0(dp, rd);
737
                    }
738
                    break;
739
                }
740
                /* Setup the next operands.  */
741
                veclen--;
742
                rd = ((rd + delta_d) & (bank_mask - 1))
743
                     | (rd & bank_mask);
744

    
745
                if (op == 15) {
746
                    /* One source operand.  */
747
                    rm = ((rm + delta_m) & (bank_mask - 1))
748
                         | (rm & bank_mask);
749
                    gen_mov_F0_vreg(dp, rm);
750
                } else {
751
                    /* Two source operands.  */
752
                    rn = ((rn + delta_d) & (bank_mask - 1))
753
                         | (rn & bank_mask);
754
                    gen_mov_F0_vreg(dp, rn);
755
                    if (delta_m) {
756
                        rm = ((rm + delta_m) & (bank_mask - 1))
757
                             | (rm & bank_mask);
758
                        gen_mov_F1_vreg(dp, rm);
759
                    }
760
                }
761
            }
762
        }
763
        break;
764
    case 0xc:
765
    case 0xd:
766
        if (dp && (insn & (1 << 22))) {
767
            /* two-register transfer */
768
            rn = (insn >> 16) & 0xf;
769
            rd = (insn >> 12) & 0xf;
770
            if (dp) {
771
                if (insn & (1 << 5))
772
                    return 1;
773
                rm = insn & 0xf;
774
            } else
775
                rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
776

    
777
            if (insn & (1 << 20)) {
778
                /* vfp->arm */
779
                if (dp) {
780
                    gen_mov_F0_vreg(1, rm);
781
                    gen_op_vfp_mrrd();
782
                    gen_movl_reg_T0(s, rd);
783
                    gen_movl_reg_T1(s, rn);
784
                } else {
785
                    gen_mov_F0_vreg(0, rm);
786
                    gen_op_vfp_mrs();
787
                    gen_movl_reg_T0(s, rn);
788
                    gen_mov_F0_vreg(0, rm + 1);
789
                    gen_op_vfp_mrs();
790
                    gen_movl_reg_T0(s, rd);
791
                }
792
            } else {
793
                /* arm->vfp */
794
                if (dp) {
795
                    gen_movl_T0_reg(s, rd);
796
                    gen_movl_T1_reg(s, rn);
797
                    gen_op_vfp_mdrr();
798
                    gen_mov_vreg_F0(1, rm);
799
                } else {
800
                    gen_movl_T0_reg(s, rn);
801
                    gen_op_vfp_msr();
802
                    gen_mov_vreg_F0(0, rm);
803
                    gen_movl_T0_reg(s, rd);
804
                    gen_op_vfp_msr();
805
                    gen_mov_vreg_F0(0, rm + 1);
806
                }
807
            }
808
        } else {
809
            /* Load/store */
810
            rn = (insn >> 16) & 0xf;
811
            if (dp)
812
                rd = (insn >> 12) & 0xf;
813
            else
814
                rd = ((insn >> 11) & 0x1e) | ((insn >> 22) & 1);
815
            gen_movl_T1_reg(s, rn);
816
            if ((insn & 0x01200000) == 0x01000000) {
817
                /* Single load/store */
818
                offset = (insn & 0xff) << 2;
819
                if ((insn & (1 << 23)) == 0)
820
                    offset = -offset;
821
                gen_op_addl_T1_im(offset);
822
                if (insn & (1 << 20)) {
823
                    gen_vfp_ld(dp);
824
                    gen_mov_vreg_F0(dp, rd);
825
                } else {
826
                    gen_mov_F0_vreg(dp, rd);
827
                    gen_vfp_st(dp);
828
                }
829
            } else {
830
                /* load/store multiple */
831
                if (dp)
832
                    n = (insn >> 1) & 0x7f;
833
                else
834
                    n = insn & 0xff;
835

    
836
                if (insn & (1 << 24)) /* pre-decrement */
837
                    gen_op_addl_T1_im(-((insn & 0xff) << 2));
838

    
839
                if (dp)
840
                    offset = 8;
841
                else
842
                    offset = 4;
843
                for (i = 0; i < n; i++) {
844
                    if (insn & (1 << 20)) {
845
                        /* load */
846
                        gen_vfp_ld(dp);
847
                        gen_mov_vreg_F0(dp, rd + i);
848
                    } else {
849
                        /* store */
850
                        gen_mov_F0_vreg(dp, rd + i);
851
                        gen_vfp_st(dp);
852
                    }
853
                    gen_op_addl_T1_im(offset);
854
                }
855
                if (insn & (1 << 21)) {
856
                    /* writeback */
857
                    if (insn & (1 << 24))
858
                        offset = -offset * n;
859
                    else if (dp && (insn & 1))
860
                        offset = 4;
861
                    else
862
                        offset = 0;
863

    
864
                    if (offset != 0)
865
                        gen_op_addl_T1_im(offset);
866
                    gen_movl_reg_T1(s, rn);
867
                }
868
            }
869
        }
870
        break;
871
    default:
872
        /* Should never happen.  */
873
        return 1;
874
    }
875
    return 0;
876
}
877

    
878
static void disas_arm_insn(CPUState * env, DisasContext *s)
879
{
880
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
881
    
882
    insn = ldl(s->pc);
883
    s->pc += 4;
884
    
885
    cond = insn >> 28;
886
    if (cond == 0xf){
887
        /* Unconditional instructions.  */
888
        if ((insn & 0x0d70f000) == 0x0550f000)
889
            return; /* PLD */
890
        else if ((insn & 0x0e000000) == 0x0a000000) {
891
            /* branch link and change to thumb (blx <offset>) */
892
            int32_t offset;
893

    
894
            val = (uint32_t)s->pc;
895
            gen_op_movl_T0_im(val);
896
            gen_movl_reg_T0(s, 14);
897
            /* Sign-extend the 24-bit offset */
898
            offset = (((int32_t)insn) << 8) >> 8;
899
            /* offset * 4 + bit24 * 2 + (thumb bit) */
900
            val += (offset << 2) | ((insn >> 23) & 2) | 1;
901
            /* pipeline offset */
902
            val += 4;
903
            gen_op_movl_T0_im(val);
904
            gen_bx(s);
905
            return;
906
        } else if ((insn & 0x0fe00000) == 0x0c400000) {
907
            /* Coprocessor double register transfer.  */
908
        } else if ((insn & 0x0f000010) == 0x0e000010) {
909
            /* Additional coprocessor register transfer.  */
910
        }
911
        goto illegal_op;
912
    }
913
    if (cond != 0xe) {
914
        /* if not always execute, we generate a conditional jump to
915
           next instruction */
916
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
917
        s->is_jmp = DISAS_JUMP_NEXT;
918
    }
919
    if ((insn & 0x0f900000) == 0x03000000) {
920
        if ((insn & 0x0ff0f000) != 0x0360f000)
921
            goto illegal_op;
922
        /* CPSR = immediate */
923
        val = insn & 0xff;
924
        shift = ((insn >> 8) & 0xf) * 2;
925
        if (shift)
926
            val = (val >> shift) | (val << (32 - shift));
927
        gen_op_movl_T0_im(val);
928
        if (insn & (1 << 19))
929
            gen_op_movl_psr_T0();
930
    } else if ((insn & 0x0f900000) == 0x01000000
931
               && (insn & 0x00000090) != 0x00000090) {
932
        /* miscellaneous instructions */
933
        op1 = (insn >> 21) & 3;
934
        sh = (insn >> 4) & 0xf;
935
        rm = insn & 0xf;
936
        switch (sh) {
937
        case 0x0: /* move program status register */
938
            if (op1 & 2) {
939
                /* SPSR not accessible in user mode */
940
                goto illegal_op;
941
            }
942
            if (op1 & 1) {
943
                /* CPSR = reg */
944
                gen_movl_T0_reg(s, rm);
945
                if (insn & (1 << 19))
946
                    gen_op_movl_psr_T0();
947
            } else {
948
                /* reg = CPSR */
949
                rd = (insn >> 12) & 0xf;
950
                gen_op_movl_T0_psr();
951
                gen_movl_reg_T0(s, rd);
952
            }
953
            break;
954
        case 0x1:
955
            if (op1 == 1) {
956
                /* branch/exchange thumb (bx).  */
957
                gen_movl_T0_reg(s, rm);
958
                gen_bx(s);
959
            } else if (op1 == 3) {
960
                /* clz */
961
                rd = (insn >> 12) & 0xf;
962
                gen_movl_T0_reg(s, rm);
963
                gen_op_clz_T0();
964
                gen_movl_reg_T0(s, rd);
965
            } else {
966
                goto illegal_op;
967
            }
968
            break;
969
        case 0x3:
970
            if (op1 != 1)
971
              goto illegal_op;
972

    
973
            /* branch link/exchange thumb (blx) */
974
            val = (uint32_t)s->pc;
975
            gen_op_movl_T0_im(val);
976
            gen_movl_reg_T0(s, 14);
977
            gen_movl_T0_reg(s, rm);
978
            gen_bx(s);
979
            break;
980
        case 0x5: /* saturating add/subtract */
981
            rd = (insn >> 12) & 0xf;
982
            rn = (insn >> 16) & 0xf;
983
            gen_movl_T0_reg(s, rn);
984
            if (op1 & 2) {
985
                gen_movl_T1_reg(s, rn);
986
                if (op1 & 1) 
987
                    gen_op_subl_T0_T1_saturate();
988
                else
989
                    gen_op_addl_T0_T1_saturate();
990
            }
991
            gen_movl_T1_reg(s, rm);
992
            if (op1 & 1)
993
                gen_op_subl_T0_T1_saturate();
994
            else
995
                gen_op_addl_T0_T1_saturate();
996
            gen_movl_reg_T0(s, rn);
997
            break;
998
        case 0x8: /* signed multiply */
999
        case 0xa:
1000
        case 0xc:
1001
        case 0xe:
1002
            rs = (insn >> 8) & 0xf;
1003
            rn = (insn >> 12) & 0xf;
1004
            rd = (insn >> 16) & 0xf;
1005
            if (op1 == 1) {
1006
                /* (32 * 16) >> 16 */
1007
                gen_movl_T0_reg(s, rm);
1008
                gen_movl_T1_reg(s, rs);
1009
                if (sh & 4)
1010
                    gen_op_sarl_T1_im(16);
1011
                else
1012
                    gen_op_sxl_T1();
1013
                gen_op_imulw_T0_T1();
1014
                if ((sh & 2) == 0) {
1015
                    gen_movl_T1_reg(s, rn);
1016
                    gen_op_addl_T0_T1_setq();
1017
                }
1018
                gen_movl_reg_T0(s, rd);
1019
            } else {
1020
                /* 16 * 16 */
1021
                gen_movl_T0_reg(s, rm);
1022
                if (sh & 2)
1023
                    gen_op_sarl_T0_im(16);
1024
                else
1025
                    gen_op_sxl_T0();
1026
                gen_movl_T1_reg(s, rs);
1027
                if (sh & 4)
1028
                    gen_op_sarl_T1_im(16);
1029
                else
1030
                    gen_op_sxl_T1();
1031
                if (op1 == 2) {
1032
                    gen_op_imull_T0_T1();
1033
                    gen_op_addq_T0_T1(rn, rd);
1034
                    gen_movl_reg_T0(s, rn);
1035
                    gen_movl_reg_T1(s, rd);
1036
                } else {
1037
                    gen_op_mul_T0_T1();
1038
                    if (op1 == 0) {
1039
                        gen_movl_T1_reg(s, rn);
1040
                        gen_op_addl_T0_T1_setq();
1041
                    }
1042
                    gen_movl_reg_T0(s, rd);
1043
                }
1044
            }
1045
            break;
1046
        default:
1047
            goto illegal_op;
1048
        }
1049
    } else if (((insn & 0x0e000000) == 0 &&
1050
                (insn & 0x00000090) != 0x90) ||
1051
               ((insn & 0x0e000000) == (1 << 25))) {
1052
        int set_cc, logic_cc, shiftop;
1053
        
1054
        op1 = (insn >> 21) & 0xf;
1055
        set_cc = (insn >> 20) & 1;
1056
        logic_cc = table_logic_cc[op1] & set_cc;
1057

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

    
1497
static void disas_thumb_insn(DisasContext *s)
1498
{
1499
    uint32_t val, insn, op, rm, rn, rd, shift, cond;
1500
    int32_t offset;
1501
    int i;
1502

    
1503
    insn = lduw(s->pc);
1504
    s->pc += 2;
1505
    
1506
    switch (insn >> 12) {
1507
    case 0: case 1:
1508
        rd = insn & 7;
1509
        op = (insn >> 11) & 3;
1510
        if (op == 3) {
1511
            /* add/subtract */
1512
            rn = (insn >> 3) & 7;
1513
            gen_movl_T0_reg(s, rn);
1514
            if (insn & (1 << 10)) {
1515
                /* immediate */
1516
                gen_op_movl_T1_im((insn >> 6) & 7);
1517
            } else {
1518
                /* reg */
1519
                rm = (insn >> 6) & 7;
1520
                gen_movl_T1_reg(s, rm);
1521
            }
1522
            if (insn & (1 << 9))
1523
                gen_op_addl_T0_T1_cc();
1524
            else
1525
                gen_op_addl_T0_T1_cc();
1526
            gen_movl_reg_T0(s, rd);
1527
        } else {
1528
            /* shift immediate */
1529
            rm = (insn >> 3) & 7;
1530
            shift = (insn >> 6) & 0x1f;
1531
            gen_movl_T0_reg(s, rm);
1532
            gen_shift_T0_im_thumb[op](shift);
1533
            gen_movl_reg_T0(s, rd);
1534
        }
1535
        break;
1536
    case 2: case 3:
1537
        /* arithmetic large immediate */
1538
        op = (insn >> 11) & 3;
1539
        rd = (insn >> 8) & 0x7;
1540
        if (op == 0) {
1541
            gen_op_movl_T0_im(insn & 0xff);
1542
        } else {
1543
            gen_movl_T0_reg(s, rd);
1544
            gen_op_movl_T1_im(insn & 0xff);
1545
        }
1546
        switch (op) {
1547
        case 0: /* mov */
1548
            gen_op_logic_T0_cc();
1549
            break;
1550
        case 1: /* cmp */
1551
            gen_op_subl_T0_T1_cc();
1552
            break;
1553
        case 2: /* add */
1554
            gen_op_addl_T0_T1_cc();
1555
            break;
1556
        case 3: /* sub */
1557
            gen_op_subl_T0_T1_cc();
1558
            break;
1559
        }
1560
        if (op != 1)
1561
            gen_movl_reg_T0(s, rd);
1562
        break;
1563
    case 4:
1564
        if (insn & (1 << 11)) {
1565
            rd = (insn >> 8) & 7;
1566
            /* load pc-relative */
1567
            val = (insn & 0xff) * 4;
1568
            gen_op_movl_T1_im(val);
1569
            gen_movl_T2_reg(s, 15);
1570
            gen_op_addl_T1_T2();
1571
            gen_op_ldl_T0_T1();
1572
            gen_movl_reg_T0(s, rd);
1573
            break;
1574
        }
1575
        if (insn & (1 << 10)) {
1576
            /* data processing extended or blx */
1577
            rd = (insn & 7) | ((insn >> 4) & 8);
1578
            rm = (insn >> 3) & 0xf;
1579
            op = (insn >> 8) & 3;
1580
            switch (op) {
1581
            case 0: /* add */
1582
                gen_movl_T0_reg(s, rd);
1583
                gen_movl_T1_reg(s, rm);
1584
                gen_op_addl_T0_T1();
1585
                gen_movl_reg_T0(s, rd);
1586
                break;
1587
            case 1: /* cmp */
1588
                gen_movl_T0_reg(s, rd);
1589
                gen_movl_T1_reg(s, rm);
1590
                gen_op_subl_T0_T1_cc();
1591
                break;
1592
            case 2: /* mov/cpy */
1593
                gen_movl_T0_reg(s, rm);
1594
                gen_movl_reg_T0(s, rd);
1595
                break;
1596
            case 3:/* branch [and link] exchange thumb register */
1597
                if (insn & (1 << 7)) {
1598
                    val = (uint32_t)s->pc | 1;
1599
                    gen_op_movl_T1_im(val);
1600
                    gen_movl_reg_T1(s, 14);
1601
                }
1602
                gen_movl_T0_reg(s, rm);
1603
                gen_bx(s);
1604
                break;
1605
            }
1606
            break;
1607
        }
1608

    
1609
        /* data processing register */
1610
        rd = insn & 7;
1611
        rm = (insn >> 3) & 7;
1612
        op = (insn >> 6) & 0xf;
1613
        if (op == 2 || op == 3 || op == 4 || op == 7) {
1614
            /* the shift/rotate ops want the operands backwards */
1615
            val = rm;
1616
            rm = rd;
1617
            rd = val;
1618
            val = 1;
1619
        } else {
1620
            val = 0;
1621
        }
1622

    
1623
        if (op == 9) /* neg */
1624
            gen_op_movl_T0_im(0);
1625
        else if (op != 0xf) /* mvn doesn't read its first operand */
1626
            gen_movl_T0_reg(s, rd);
1627

    
1628
        gen_movl_T1_reg(s, rm);
1629
        switch (insn >> 6) {
1630
        case 0x0: /* and */
1631
            gen_op_andl_T0_T1();
1632
            gen_op_logic_T0_cc();
1633
            break;
1634
        case 0x1: /* eor */
1635
            gen_op_xorl_T0_T1();
1636
            gen_op_logic_T0_cc();
1637
            break;
1638
        case 0x2: /* lsl */
1639
            gen_op_shll_T1_T0_cc();
1640
            break;
1641
        case 0x3: /* lsr */
1642
            gen_op_shrl_T1_T0_cc();
1643
            break;
1644
        case 0x4: /* asr */
1645
            gen_op_sarl_T1_T0_cc();
1646
            break;
1647
        case 0x5: /* adc */
1648
            gen_op_adcl_T0_T1_cc();
1649
            break;
1650
        case 0x6: /* sbc */
1651
            gen_op_sbcl_T0_T1_cc();
1652
            break;
1653
        case 0x7: /* ror */
1654
            gen_op_rorl_T1_T0_cc();
1655
            break;
1656
        case 0x8: /* tst */
1657
            gen_op_andl_T0_T1();
1658
            gen_op_logic_T0_cc();
1659
            rd = 16;
1660
        case 0x9: /* neg */
1661
            gen_op_rsbl_T0_T1_cc();
1662
            break;
1663
        case 0xa: /* cmp */
1664
            gen_op_subl_T0_T1_cc();
1665
            rd = 16;
1666
            break;
1667
        case 0xb: /* cmn */
1668
            gen_op_addl_T0_T1_cc();
1669
            rd = 16;
1670
            break;
1671
        case 0xc: /* orr */
1672
            gen_op_orl_T0_T1();
1673
            gen_op_logic_T0_cc();
1674
            break;
1675
        case 0xd: /* mul */
1676
            gen_op_mull_T0_T1();
1677
            gen_op_logic_T0_cc();
1678
            break;
1679
        case 0xe: /* bic */
1680
            gen_op_bicl_T0_T1();
1681
            gen_op_logic_T0_cc();
1682
            break;
1683
        case 0xf: /* mvn */
1684
            gen_op_notl_T1();
1685
            gen_op_logic_T1_cc();
1686
            val = 1;
1687
            break;
1688
        }
1689
        if (rd != 16) {
1690
            if (val)
1691
                gen_movl_reg_T1(s, rd);
1692
            else
1693
                gen_movl_reg_T0(s, rd);
1694
        }
1695
        break;
1696

    
1697
    case 5:
1698
        /* load/store register offset.  */
1699
        rd = insn & 7;
1700
        rn = (insn >> 3) & 7;
1701
        rm = (insn >> 6) & 7;
1702
        op = (insn >> 9) & 7;
1703
        gen_movl_T1_reg(s, rn);
1704
        gen_movl_T2_reg(s, rm);
1705
        gen_op_addl_T1_T2();
1706

    
1707
        if (op < 3) /* store */
1708
            gen_movl_T0_reg(s, rd);
1709

    
1710
        switch (op) {
1711
        case 0: /* str */
1712
            gen_op_stl_T0_T1();
1713
            break;
1714
        case 1: /* strh */
1715
            gen_op_stw_T0_T1();
1716
            break;
1717
        case 2: /* strb */
1718
            gen_op_stb_T0_T1();
1719
            break;
1720
        case 3: /* ldrsb */
1721
            gen_op_ldsb_T0_T1();
1722
            break;
1723
        case 4: /* ldr */
1724
            gen_op_ldl_T0_T1();
1725
            break;
1726
        case 5: /* ldrh */
1727
            gen_op_ldsw_T0_T1();
1728
            break;
1729
        case 6: /* ldrb */
1730
            gen_op_ldub_T0_T1();
1731
            break;
1732
        case 7: /* ldrsh */
1733
            gen_op_ldsw_T0_T1();
1734
            break;
1735
        }
1736
        if (op >= 3) /* load */
1737
            gen_movl_reg_T0(s, rd);
1738
        break;
1739

    
1740
    case 6:
1741
        /* load/store word immediate offset */
1742
        rd = insn & 7;
1743
        rn = (insn >> 3) & 7;
1744
        gen_movl_T1_reg(s, rn);
1745
        val = (insn >> 4) & 0x7c;
1746
        gen_op_movl_T2_im(val);
1747
        gen_op_addl_T1_T2();
1748

    
1749
        if (insn & (1 << 11)) {
1750
            /* load */
1751
            gen_op_ldl_T0_T1();
1752
            gen_movl_reg_T0(s, rd);
1753
        } else {
1754
            /* store */
1755
            gen_movl_T0_reg(s, rd);
1756
            gen_op_stl_T0_T1();
1757
        }
1758
        break;
1759

    
1760
    case 7:
1761
        /* load/store byte immediate offset */
1762
        rd = insn & 7;
1763
        rn = (insn >> 3) & 7;
1764
        gen_movl_T1_reg(s, rn);
1765
        val = (insn >> 6) & 0x1f;
1766
        gen_op_movl_T2_im(val);
1767
        gen_op_addl_T1_T2();
1768

    
1769
        if (insn & (1 << 11)) {
1770
            /* load */
1771
            gen_op_ldub_T0_T1();
1772
            gen_movl_reg_T0(s, rd);
1773
        } else {
1774
            /* store */
1775
            gen_movl_T0_reg(s, rd);
1776
            gen_op_stb_T0_T1();
1777
        }
1778
        break;
1779

    
1780
    case 8:
1781
        /* load/store halfword immediate offset */
1782
        rd = insn & 7;
1783
        rn = (insn >> 3) & 7;
1784
        gen_movl_T1_reg(s, rn);
1785
        val = (insn >> 5) & 0x3e;
1786
        gen_op_movl_T2_im(val);
1787
        gen_op_addl_T1_T2();
1788

    
1789
        if (insn & (1 << 11)) {
1790
            /* load */
1791
            gen_op_lduw_T0_T1();
1792
            gen_movl_reg_T0(s, rd);
1793
        } else {
1794
            /* store */
1795
            gen_movl_T0_reg(s, rd);
1796
            gen_op_stw_T0_T1();
1797
        }
1798
        break;
1799

    
1800
    case 9:
1801
        /* load/store from stack */
1802
        rd = (insn >> 8) & 7;
1803
        gen_movl_T1_reg(s, 13);
1804
        val = (insn & 0xff) * 4;
1805
        gen_op_movl_T2_im(val);
1806
        gen_op_addl_T1_T2();
1807

    
1808
        if (insn & (1 << 11)) {
1809
            /* load */
1810
            gen_op_ldl_T0_T1();
1811
            gen_movl_reg_T0(s, rd);
1812
        } else {
1813
            /* store */
1814
            gen_movl_T0_reg(s, rd);
1815
            gen_op_stl_T0_T1();
1816
        }
1817
        break;
1818

    
1819
    case 10:
1820
        /* add to high reg */
1821
        rd = (insn >> 8) & 7;
1822
        if (insn & (1 << 11))
1823
            rm = 13; /* sp */
1824
        else
1825
            rm = 15; /* pc */
1826
        gen_movl_T0_reg(s, rm);
1827
        val = (insn & 0xff) * 4;
1828
        gen_op_movl_T1_im(val);
1829
        gen_op_addl_T0_T1();
1830
        gen_movl_reg_T0(s, rd);
1831
        break;
1832

    
1833
    case 11:
1834
        /* misc */
1835
        op = (insn >> 8) & 0xf;
1836
        switch (op) {
1837
        case 0:
1838
            /* adjust stack pointer */
1839
            gen_movl_T1_reg(s, 13);
1840
            val = (insn & 0x7f) * 4;
1841
            if (insn & (1 << 7))
1842
              val = -(int32_t)val;
1843
            gen_op_movl_T2_im(val);
1844
            gen_op_addl_T1_T2();
1845
            gen_movl_reg_T1(s, 13);
1846
            break;
1847

    
1848
        case 4: case 5: case 0xc: case 0xd:
1849
            /* push/pop */
1850
            gen_movl_T1_reg(s, 13);
1851
            if (insn & (1 << 11))
1852
                val = 4;
1853
            else
1854
                val = -4;
1855
            gen_op_movl_T2_im(val);
1856
            for (i = 0; i < 8; i++) {
1857
                if (insn & (1 << i)) {
1858
                    if (insn & (1 << 11)) {
1859
                        /* pop */
1860
                        gen_op_ldl_T0_T1();
1861
                        gen_movl_reg_T0(s, i);
1862
                    } else {
1863
                        /* push */
1864
                        gen_movl_T0_reg(s, i);
1865
                        gen_op_stl_T0_T1();
1866
                    }
1867
                    /* move to the next address */
1868
                    gen_op_addl_T1_T2();
1869
                }
1870
            }
1871
            if (insn & (1 << 8)) {
1872
                if (insn & (1 << 11)) {
1873
                    /* pop pc */
1874
                    gen_op_ldl_T0_T1();
1875
                    /* don't set the pc until the rest of the instruction
1876
                       has completed */
1877
                } else {
1878
                    /* push lr */
1879
                    gen_movl_T0_reg(s, 14);
1880
                    gen_op_stl_T0_T1();
1881
                }
1882
                gen_op_addl_T1_T2();
1883
            }
1884

    
1885
            /* write back the new stack pointer */
1886
            gen_movl_reg_T1(s, 13);
1887
            /* set the new PC value */
1888
            if ((insn & 0x0900) == 0x0900)
1889
                gen_bx(s);
1890
            break;
1891

    
1892
        default:
1893
            goto undef;
1894
        }
1895
        break;
1896

    
1897
    case 12:
1898
        /* load/store multiple */
1899
        rn = (insn >> 8) & 0x7;
1900
        gen_movl_T1_reg(s, rn);
1901
        gen_op_movl_T2_im(4);
1902
        val = 0;
1903
        for (i = 0; i < 8; i++) {
1904
            if (insn & (1 << i)) {
1905
                /* advance to the next address */
1906
                if (val)
1907
                    gen_op_addl_T1_T2();
1908
                else
1909
                    val = 1;
1910
                if (insn & (1 << 11)) {
1911
                    /* load */
1912
                    gen_op_ldl_T0_T1();
1913
                    gen_movl_reg_T0(s, i);
1914
                } else {
1915
                    /* store */
1916
                    gen_movl_T0_reg(s, i);
1917
                    gen_op_stl_T0_T1();
1918
                }
1919
            }
1920
        }
1921
        break;
1922

    
1923
    case 13:
1924
        /* conditional branch or swi */
1925
        cond = (insn >> 8) & 0xf;
1926
        if (cond == 0xe)
1927
            goto undef;
1928

    
1929
        if (cond == 0xf) {
1930
            /* swi */
1931
            gen_op_movl_T0_im((long)s->pc | 1);
1932
            /* Don't set r15.  */
1933
            gen_op_movl_reg_TN[0][15]();
1934
            gen_op_swi();
1935
            s->is_jmp = DISAS_JUMP;
1936
            break;
1937
        }
1938
        /* generate a conditional jump to next instruction */
1939
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1940
        s->is_jmp = DISAS_JUMP_NEXT;
1941
        gen_movl_T1_reg(s, 15);
1942

    
1943
        /* jump to the offset */
1944
        val = (uint32_t)s->pc;
1945
        offset = ((int32_t)insn << 24) >> 24;
1946
        val += (offset << 1) + 2;
1947
        gen_op_jmp((long)s->tb, val);
1948
        s->is_jmp = DISAS_TB_JUMP;
1949
        break;
1950

    
1951
    case 14:
1952
        /* unconditional branch */
1953
        if (insn & (1 << 11))
1954
            goto undef; /* Second half of a blx */
1955
        val = (uint32_t)s->pc;
1956
        offset = ((int32_t)insn << 21) >> 21;
1957
        val += (offset << 1) + 2;
1958
        gen_op_jmp((long)s->tb, val);
1959
        s->is_jmp = DISAS_TB_JUMP;
1960
        break;
1961

    
1962
    case 15:
1963
        /* branch and link [and switch to arm] */
1964
        offset = ((int32_t)insn << 21) >> 10;
1965
        insn = lduw(s->pc);
1966
        offset |= insn & 0x7ff;
1967

    
1968
        val = (uint32_t)s->pc + 2;
1969
        gen_op_movl_T1_im(val | 1);
1970
        gen_movl_reg_T1(s, 14);
1971
        
1972
        val += offset;
1973
        if (insn & (1 << 11)) {
1974
            /* bl */
1975
            gen_op_jmp((long)s->tb, val);
1976
            s->is_jmp = DISAS_TB_JUMP;
1977
        } else {
1978
            /* blx */
1979
            gen_op_movl_T0_im(val);
1980
            gen_bx(s);
1981
        }
1982
    }
1983
    return;
1984
undef:
1985
    gen_op_movl_T0_im((long)s->pc - 4);
1986
    gen_op_movl_reg_TN[0][15]();
1987
    gen_op_undef_insn();
1988
    s->is_jmp = DISAS_JUMP;
1989
}
1990

    
1991
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1992
   basic block 'tb'. If search_pc is TRUE, also generate PC
1993
   information for each intermediate instruction. */
1994
static inline int gen_intermediate_code_internal(CPUState *env, 
1995
                                                 TranslationBlock *tb, 
1996
                                                 int search_pc)
1997
{
1998
    DisasContext dc1, *dc = &dc1;
1999
    uint16_t *gen_opc_end;
2000
    int j, lj;
2001
    target_ulong pc_start;
2002
    
2003
    /* generate intermediate code */
2004
    pc_start = tb->pc;
2005
       
2006
    dc->tb = tb;
2007

    
2008
    gen_opc_ptr = gen_opc_buf;
2009
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
2010
    gen_opparam_ptr = gen_opparam_buf;
2011

    
2012
    dc->is_jmp = DISAS_NEXT;
2013
    dc->pc = pc_start;
2014
    lj = -1;
2015
    do {
2016
        if (search_pc) {
2017
            j = gen_opc_ptr - gen_opc_buf;
2018
            if (lj < j) {
2019
                lj++;
2020
                while (lj < j)
2021
                    gen_opc_instr_start[lj++] = 0;
2022
            }
2023
            gen_opc_pc[lj] = dc->pc;
2024
            gen_opc_instr_start[lj] = 1;
2025
        }
2026
        if (env->thumb)
2027
          disas_thumb_insn(dc);
2028
        else
2029
          disas_arm_insn(env, dc);
2030
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
2031
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
2032
    switch(dc->is_jmp) {
2033
    case DISAS_JUMP_NEXT:
2034
    case DISAS_NEXT:
2035
        gen_op_jmp((long)dc->tb, (long)dc->pc);
2036
        break;
2037
    default:
2038
    case DISAS_JUMP:
2039
    case DISAS_UPDATE:
2040
        /* indicate that the hash table must be used to find the next TB */
2041
        gen_op_movl_T0_0();
2042
        gen_op_exit_tb();
2043
        break;
2044
    case DISAS_TB_JUMP:
2045
        /* nothing more to generate */
2046
        break;
2047
    }
2048
    *gen_opc_ptr = INDEX_op_end;
2049

    
2050
#ifdef DEBUG_DISAS
2051
    if (loglevel & CPU_LOG_TB_IN_ASM) {
2052
        fprintf(logfile, "----------------\n");
2053
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
2054
        target_disas(logfile, pc_start, dc->pc - pc_start, 0);
2055
        fprintf(logfile, "\n");
2056
        if (loglevel & (CPU_LOG_TB_OP)) {
2057
            fprintf(logfile, "OP:\n");
2058
            dump_ops(gen_opc_buf, gen_opparam_buf);
2059
            fprintf(logfile, "\n");
2060
        }
2061
    }
2062
#endif
2063
    if (!search_pc)
2064
        tb->size = dc->pc - pc_start;
2065
    return 0;
2066
}
2067

    
2068
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
2069
{
2070
    return gen_intermediate_code_internal(env, tb, 0);
2071
}
2072

    
2073
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2074
{
2075
    return gen_intermediate_code_internal(env, tb, 1);
2076
}
2077

    
2078
CPUARMState *cpu_arm_init(void)
2079
{
2080
    CPUARMState *env;
2081

    
2082
    cpu_exec_init();
2083

    
2084
    env = malloc(sizeof(CPUARMState));
2085
    if (!env)
2086
        return NULL;
2087
    memset(env, 0, sizeof(CPUARMState));
2088
    cpu_single_env = env;
2089
    return env;
2090
}
2091

    
2092
void cpu_arm_close(CPUARMState *env)
2093
{
2094
    free(env);
2095
}
2096

    
2097
void cpu_dump_state(CPUState *env, FILE *f, 
2098
                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
2099
                    int flags)
2100
{
2101
    int i;
2102
    struct {
2103
        uint32_t i;
2104
        float s;
2105
    } s0, s1;
2106
    CPU_DoubleU d;
2107

    
2108
    for(i=0;i<16;i++) {
2109
        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2110
        if ((i % 4) == 3)
2111
            cpu_fprintf(f, "\n");
2112
        else
2113
            cpu_fprintf(f, " ");
2114
    }
2115
    cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
2116
             env->cpsr, 
2117
            env->cpsr & (1 << 31) ? 'N' : '-',
2118
            env->cpsr & (1 << 30) ? 'Z' : '-',
2119
            env->cpsr & (1 << 29) ? 'C' : '-',
2120
            env->cpsr & (1 << 28) ? 'V' : '-');
2121

    
2122
    for (i = 0; i < 16; i++) {
2123
        s0.s = env->vfp.regs.s[i * 2];
2124
        s1.s = env->vfp.regs.s[i * 2 + 1];
2125
        d.d = env->vfp.regs.d[i];
2126
        cpu_fprintf(f, "s%02d=%08x(%8f) s%02d=%08x(%8f) d%02d=%08x%08x(%8f)\n",
2127
                    i * 2, (int)s0.i, s0.s,
2128
                    i * 2 + 1, (int)s0.i, s0.s,
2129
                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2130
                    d.d);
2131
        cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
2132
    }
2133
}
2134

    
2135
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
2136
{
2137
    return addr;
2138
}
2139

    
2140
#if defined(CONFIG_USER_ONLY) 
2141

    
2142
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
2143
                              int is_user, int is_softmmu)
2144
{
2145
    env->cp15_6 = address;
2146
    if (rw == 2) {
2147
        env->exception_index = EXCP_PREFETCH_ABORT;
2148
    } else {
2149
        env->exception_index = EXCP_DATA_ABORT;
2150
    }
2151
    return 1;
2152
}
2153

    
2154
#else
2155

    
2156
#error not implemented
2157

    
2158
#endif