Statistics
| Branch: | Revision:

root / target-arm / translate.c @ d1d9f421

History | View | Annotate | Download (23.5 kB)

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

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

    
30
/* internal defines */
31
typedef struct DisasContext {
32
    uint8_t *pc;
33
    int is_jmp;
34
    struct TranslationBlock *tb;
35
} DisasContext;
36

    
37
#define DISAS_JUMP_NEXT 4
38

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

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

    
52
#include "gen-op.h"
53

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

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

    
97
static GenOpFunc1 *gen_shift_T2_im[4] = {
98
    gen_op_shll_T2_im,
99
    gen_op_shrl_T2_im,
100
    gen_op_sarl_T2_im,
101
    gen_op_rorl_T2_im,
102
};
103

    
104
static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
105
    gen_op_shll_T1_im_cc,
106
    gen_op_shrl_T1_im_cc,
107
    gen_op_sarl_T1_im_cc,
108
    gen_op_rorl_T1_im_cc,
109
};
110

    
111
static GenOpFunc *gen_shift_T1_T0[4] = {
112
    gen_op_shll_T1_T0,
113
    gen_op_shrl_T1_T0,
114
    gen_op_sarl_T1_T0,
115
    gen_op_rorl_T1_T0,
116
};
117

    
118
static GenOpFunc *gen_shift_T1_T0_cc[4] = {
119
    gen_op_shll_T1_T0_cc,
120
    gen_op_shrl_T1_T0_cc,
121
    gen_op_sarl_T1_T0_cc,
122
    gen_op_rorl_T1_T0_cc,
123
};
124

    
125
static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
126
    {
127
        gen_op_movl_T0_r0,
128
        gen_op_movl_T0_r1,
129
        gen_op_movl_T0_r2,
130
        gen_op_movl_T0_r3,
131
        gen_op_movl_T0_r4,
132
        gen_op_movl_T0_r5,
133
        gen_op_movl_T0_r6,
134
        gen_op_movl_T0_r7,
135
        gen_op_movl_T0_r8,
136
        gen_op_movl_T0_r9,
137
        gen_op_movl_T0_r10,
138
        gen_op_movl_T0_r11,
139
        gen_op_movl_T0_r12,
140
        gen_op_movl_T0_r13,
141
        gen_op_movl_T0_r14,
142
        gen_op_movl_T0_r15,
143
    },
144
    {
145
        gen_op_movl_T1_r0,
146
        gen_op_movl_T1_r1,
147
        gen_op_movl_T1_r2,
148
        gen_op_movl_T1_r3,
149
        gen_op_movl_T1_r4,
150
        gen_op_movl_T1_r5,
151
        gen_op_movl_T1_r6,
152
        gen_op_movl_T1_r7,
153
        gen_op_movl_T1_r8,
154
        gen_op_movl_T1_r9,
155
        gen_op_movl_T1_r10,
156
        gen_op_movl_T1_r11,
157
        gen_op_movl_T1_r12,
158
        gen_op_movl_T1_r13,
159
        gen_op_movl_T1_r14,
160
        gen_op_movl_T1_r15,
161
    },
162
    {
163
        gen_op_movl_T2_r0,
164
        gen_op_movl_T2_r1,
165
        gen_op_movl_T2_r2,
166
        gen_op_movl_T2_r3,
167
        gen_op_movl_T2_r4,
168
        gen_op_movl_T2_r5,
169
        gen_op_movl_T2_r6,
170
        gen_op_movl_T2_r7,
171
        gen_op_movl_T2_r8,
172
        gen_op_movl_T2_r9,
173
        gen_op_movl_T2_r10,
174
        gen_op_movl_T2_r11,
175
        gen_op_movl_T2_r12,
176
        gen_op_movl_T2_r13,
177
        gen_op_movl_T2_r14,
178
        gen_op_movl_T2_r15,
179
    },
180
};
181

    
182
static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
183
    {
184
        gen_op_movl_r0_T0,
185
        gen_op_movl_r1_T0,
186
        gen_op_movl_r2_T0,
187
        gen_op_movl_r3_T0,
188
        gen_op_movl_r4_T0,
189
        gen_op_movl_r5_T0,
190
        gen_op_movl_r6_T0,
191
        gen_op_movl_r7_T0,
192
        gen_op_movl_r8_T0,
193
        gen_op_movl_r9_T0,
194
        gen_op_movl_r10_T0,
195
        gen_op_movl_r11_T0,
196
        gen_op_movl_r12_T0,
197
        gen_op_movl_r13_T0,
198
        gen_op_movl_r14_T0,
199
        gen_op_movl_r15_T0,
200
    },
201
    {
202
        gen_op_movl_r0_T1,
203
        gen_op_movl_r1_T1,
204
        gen_op_movl_r2_T1,
205
        gen_op_movl_r3_T1,
206
        gen_op_movl_r4_T1,
207
        gen_op_movl_r5_T1,
208
        gen_op_movl_r6_T1,
209
        gen_op_movl_r7_T1,
210
        gen_op_movl_r8_T1,
211
        gen_op_movl_r9_T1,
212
        gen_op_movl_r10_T1,
213
        gen_op_movl_r11_T1,
214
        gen_op_movl_r12_T1,
215
        gen_op_movl_r13_T1,
216
        gen_op_movl_r14_T1,
217
        gen_op_movl_r15_T1,
218
    },
219
};
220

    
221
static GenOpFunc1 *gen_op_movl_TN_im[3] = {
222
    gen_op_movl_T0_im,
223
    gen_op_movl_T1_im,
224
    gen_op_movl_T2_im,
225
};
226

    
227
static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
228
{
229
    int val;
230

    
231
    if (reg == 15) {
232
        /* normaly, since we updated PC, we need only to add 4 */
233
        val = (long)s->pc + 4;
234
        gen_op_movl_TN_im[t](val);
235
    } else {
236
        gen_op_movl_TN_reg[t][reg]();
237
    }
238
}
239

    
240
static inline void gen_movl_T0_reg(DisasContext *s, int reg)
241
{
242
    gen_movl_TN_reg(s, reg, 0);
243
}
244

    
245
static inline void gen_movl_T1_reg(DisasContext *s, int reg)
246
{
247
    gen_movl_TN_reg(s, reg, 1);
248
}
249

    
250
static inline void gen_movl_T2_reg(DisasContext *s, int reg)
251
{
252
    gen_movl_TN_reg(s, reg, 2);
253
}
254

    
255
static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
256
{
257
    gen_op_movl_reg_TN[t][reg]();
258
    if (reg == 15) {
259
        s->is_jmp = DISAS_JUMP;
260
    }
261
}
262

    
263
static inline void gen_movl_reg_T0(DisasContext *s, int reg)
264
{
265
    gen_movl_reg_TN(s, reg, 0);
266
}
267

    
268
static inline void gen_movl_reg_T1(DisasContext *s, int reg)
269
{
270
    gen_movl_reg_TN(s, reg, 1);
271
}
272

    
273
static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
274
{
275
    int val, rm, shift;
276

    
277
    if (!(insn & (1 << 25))) {
278
        /* immediate */
279
        val = insn & 0xfff;
280
        if (!(insn & (1 << 23)))
281
            val = -val;
282
        if (val != 0)
283
            gen_op_addl_T1_im(val);
284
    } else {
285
        /* shift/register */
286
        rm = (insn) & 0xf;
287
        shift = (insn >> 7) & 0x1f;
288
        gen_movl_T2_reg(s, rm);
289
        if (shift != 0) {
290
            gen_shift_T2_im[(insn >> 5) & 3](shift);
291
        }
292
        if (!(insn & (1 << 23)))
293
            gen_op_subl_T1_T2();
294
        else
295
            gen_op_addl_T1_T2();
296
    }
297
}
298

    
299
static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
300
{
301
    int val, rm;
302
    
303
    if (insn & (1 << 22)) {
304
        /* immediate */
305
        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
306
        if (!(insn & (1 << 23)))
307
            val = -val;
308
        if (val != 0)
309
            gen_op_addl_T1_im(val);
310
    } else {
311
        /* register */
312
        rm = (insn) & 0xf;
313
        gen_movl_T2_reg(s, rm);
314
        if (!(insn & (1 << 23)))
315
            gen_op_subl_T1_T2();
316
        else
317
            gen_op_addl_T1_T2();
318
    }
319
}
320

    
321
static void disas_arm_insn(DisasContext *s)
322
{
323
    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
324
    
325
    insn = ldl(s->pc);
326
    s->pc += 4;
327
    
328
    cond = insn >> 28;
329
    if (cond == 0xf)
330
        goto illegal_op;
331
    if (cond != 0xe) {
332
        /* if not always execute, we generate a conditional jump to
333
           next instruction */
334
        gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
335
        s->is_jmp = DISAS_JUMP_NEXT;
336
    }
337
    if (((insn & 0x0e000000) == 0 &&
338
         (insn & 0x00000090) != 0x90) ||
339
        ((insn & 0x0e000000) == (1 << 25))) {
340
        int set_cc, logic_cc, shiftop;
341
        
342
        op1 = (insn >> 21) & 0xf;
343
        set_cc = (insn >> 20) & 1;
344
        logic_cc = table_logic_cc[op1] & set_cc;
345

    
346
        /* data processing instruction */
347
        if (insn & (1 << 25)) {
348
            /* immediate operand */
349
            val = insn & 0xff;
350
            shift = ((insn >> 8) & 0xf) * 2;
351
            if (shift)
352
                val = (val >> shift) | (val << (32 - shift));
353
            gen_op_movl_T1_im(val);
354
            /* XXX: is CF modified ? */
355
        } else {
356
            /* register */
357
            rm = (insn) & 0xf;
358
            gen_movl_T1_reg(s, rm);
359
            shiftop = (insn >> 5) & 3;
360
            if (!(insn & (1 << 4))) {
361
                shift = (insn >> 7) & 0x1f;
362
                if (shift != 0) {
363
                    if (logic_cc) {
364
                        gen_shift_T1_im_cc[shiftop](shift);
365
                    } else {
366
                        gen_shift_T1_im[shiftop](shift);
367
                    }
368
                }
369
            } else {
370
                rs = (insn >> 8) & 0xf;
371
                gen_movl_T0_reg(s, rs);
372
                if (logic_cc) {
373
                    gen_shift_T1_T0_cc[shiftop]();
374
                } else {
375
                    gen_shift_T1_T0[shiftop]();
376
                }
377
            }
378
        }
379
        if (op1 != 0x0f && op1 != 0x0d) {
380
            rn = (insn >> 16) & 0xf;
381
            gen_movl_T0_reg(s, rn);
382
        }
383
        rd = (insn >> 12) & 0xf;
384
        switch(op1) {
385
        case 0x00:
386
            gen_op_andl_T0_T1();
387
            gen_movl_reg_T0(s, rd);
388
            if (logic_cc)
389
                gen_op_logic_T0_cc();
390
            break;
391
        case 0x01:
392
            gen_op_xorl_T0_T1();
393
            gen_movl_reg_T0(s, rd);
394
            if (logic_cc)
395
                gen_op_logic_T0_cc();
396
            break;
397
        case 0x02:
398
            if (set_cc)
399
                gen_op_subl_T0_T1_cc();
400
            else
401
                gen_op_subl_T0_T1();
402
            gen_movl_reg_T0(s, rd);
403
            break;
404
        case 0x03:
405
            if (set_cc)
406
                gen_op_rsbl_T0_T1_cc();
407
            else
408
                gen_op_rsbl_T0_T1();
409
            gen_movl_reg_T0(s, rd);
410
            break;
411
        case 0x04:
412
            if (set_cc)
413
                gen_op_addl_T0_T1_cc();
414
            else
415
                gen_op_addl_T0_T1();
416
            gen_movl_reg_T0(s, rd);
417
            break;
418
        case 0x05:
419
            if (set_cc)
420
                gen_op_adcl_T0_T1_cc();
421
            else
422
                gen_op_adcl_T0_T1();
423
            gen_movl_reg_T0(s, rd);
424
            break;
425
        case 0x06:
426
            if (set_cc)
427
                gen_op_sbcl_T0_T1_cc();
428
            else
429
                gen_op_sbcl_T0_T1();
430
            gen_movl_reg_T0(s, rd);
431
            break;
432
        case 0x07:
433
            if (set_cc)
434
                gen_op_rscl_T0_T1_cc();
435
            else
436
                gen_op_rscl_T0_T1();
437
            gen_movl_reg_T0(s, rd);
438
            break;
439
        case 0x08:
440
            if (set_cc) {
441
                gen_op_andl_T0_T1();
442
                gen_op_logic_T0_cc();
443
            }
444
            break;
445
        case 0x09:
446
            if (set_cc) {
447
                gen_op_xorl_T0_T1();
448
                gen_op_logic_T0_cc();
449
            }
450
            break;
451
        case 0x0a:
452
            if (set_cc) {
453
                gen_op_subl_T0_T1_cc();
454
            }
455
            break;
456
        case 0x0b:
457
            if (set_cc) {
458
                gen_op_addl_T0_T1_cc();
459
            }
460
            break;
461
        case 0x0c:
462
            gen_op_orl_T0_T1();
463
            gen_movl_reg_T0(s, rd);
464
            if (logic_cc)
465
                gen_op_logic_T0_cc();
466
            break;
467
        case 0x0d:
468
            gen_movl_reg_T1(s, rd);
469
            if (logic_cc)
470
                gen_op_logic_T1_cc();
471
            break;
472
        case 0x0e:
473
            gen_op_bicl_T0_T1();
474
            gen_movl_reg_T0(s, rd);
475
            if (logic_cc)
476
                gen_op_logic_T0_cc();
477
            break;
478
        default:
479
        case 0x0f:
480
            gen_op_notl_T1();
481
            gen_movl_reg_T1(s, rd);
482
            if (logic_cc)
483
                gen_op_logic_T1_cc();
484
            break;
485
        }
486
    } else {
487
        /* other instructions */
488
        op1 = (insn >> 24) & 0xf;
489
        switch(op1) {
490
        case 0x0:
491
        case 0x1:
492
            sh = (insn >> 5) & 3;
493
            if (sh == 0) {
494
                if (op1 == 0x0) {
495
                    rd = (insn >> 16) & 0xf;
496
                    rn = (insn >> 12) & 0xf;
497
                    rs = (insn >> 8) & 0xf;
498
                    rm = (insn) & 0xf;
499
                    if (!(insn & (1 << 23))) {
500
                        /* 32 bit mul */
501
                        gen_movl_T0_reg(s, rs);
502
                        gen_movl_T1_reg(s, rm);
503
                        gen_op_mul_T0_T1();
504
                        if (insn & (1 << 21)) {
505
                            gen_movl_T1_reg(s, rn);
506
                            gen_op_addl_T0_T1();
507
                        }
508
                        if (insn & (1 << 20)) 
509
                            gen_op_logic_T0_cc();
510
                        gen_movl_reg_T0(s, rd);
511
                    } else {
512
                        /* 64 bit mul */
513
                        gen_movl_T0_reg(s, rs);
514
                        gen_movl_T1_reg(s, rm);
515
                        if (insn & (1 << 22)) 
516
                            gen_op_imull_T0_T1();
517
                        else
518
                            gen_op_mull_T0_T1();
519
                        if (insn & (1 << 21)) 
520
                            gen_op_addq_T0_T1(rn, rd);
521
                        if (insn & (1 << 20)) 
522
                            gen_op_logicq_cc();
523
                        gen_movl_reg_T0(s, rn);
524
                        gen_movl_reg_T1(s, rd);
525
                    }
526
                } else {
527
                    /* SWP instruction */
528
                    rn = (insn >> 16) & 0xf;
529
                    rd = (insn >> 12) & 0xf;
530
                    rm = (insn) & 0xf;
531
                    
532
                    gen_movl_T0_reg(s, rm);
533
                    gen_movl_T1_reg(s, rn);
534
                    if (insn & (1 << 22)) {
535
                        gen_op_swpb_T0_T1();
536
                    } else {
537
                        gen_op_swpl_T0_T1();
538
                    }
539
                    gen_movl_reg_T0(s, rd);
540
                }
541
            } else {
542
                /* load/store half word */
543
                rn = (insn >> 16) & 0xf;
544
                rd = (insn >> 12) & 0xf;
545
                gen_movl_T1_reg(s, rn);
546
                if (insn & (1 << 24))
547
                    gen_add_datah_offset(s, insn);
548
                if (insn & (1 << 20)) {
549
                    /* load */
550
                    switch(sh) {
551
                    case 1:
552
                        gen_op_lduw_T0_T1();
553
                        break;
554
                    case 2:
555
                        gen_op_ldsb_T0_T1();
556
                        break;
557
                    default:
558
                    case 3:
559
                        gen_op_ldsw_T0_T1();
560
                        break;
561
                    }
562
                    gen_movl_reg_T0(s, rd);
563
                } else {
564
                    /* store */
565
                    gen_movl_T0_reg(s, rd);
566
                    gen_op_stw_T0_T1();
567
                }
568
                if (!(insn & (1 << 24))) {
569
                    gen_add_datah_offset(s, insn);
570
                    gen_movl_reg_T1(s, rn);
571
                } else if (insn & (1 << 21)) {
572
                    gen_movl_reg_T1(s, rn);
573
                }
574
            }
575
            break;
576
        case 0x4:
577
        case 0x5:
578
        case 0x6:
579
        case 0x7:
580
            /* load/store byte/word */
581
            rn = (insn >> 16) & 0xf;
582
            rd = (insn >> 12) & 0xf;
583
            gen_movl_T1_reg(s, rn);
584
            if (insn & (1 << 24))
585
                gen_add_data_offset(s, insn);
586
            if (insn & (1 << 20)) {
587
                /* load */
588
                if (insn & (1 << 22))
589
                    gen_op_ldub_T0_T1();
590
                else
591
                    gen_op_ldl_T0_T1();
592
                gen_movl_reg_T0(s, rd);
593
            } else {
594
                /* store */
595
                gen_movl_T0_reg(s, rd);
596
                if (insn & (1 << 22))
597
                    gen_op_stb_T0_T1();
598
                else
599
                    gen_op_stl_T0_T1();
600
            }
601
            if (!(insn & (1 << 24))) {
602
                gen_add_data_offset(s, insn);
603
                gen_movl_reg_T1(s, rn);
604
            } else if (insn & (1 << 21))
605
                gen_movl_reg_T1(s, rn); {
606
            }
607
            break;
608
        case 0x08:
609
        case 0x09:
610
            {
611
                int j, n;
612
                /* load/store multiple words */
613
                /* XXX: store correct base if write back */
614
                if (insn & (1 << 22))
615
                    goto illegal_op; /* only usable in supervisor mode */
616
                rn = (insn >> 16) & 0xf;
617
                gen_movl_T1_reg(s, rn);
618
                
619
                /* compute total size */
620
                n = 0;
621
                for(i=0;i<16;i++) {
622
                    if (insn & (1 << i))
623
                        n++;
624
                }
625
                /* XXX: test invalid n == 0 case ? */
626
                if (insn & (1 << 23)) {
627
                    if (insn & (1 << 24)) {
628
                        /* pre increment */
629
                        gen_op_addl_T1_im(4);
630
                    } else {
631
                        /* post increment */
632
                    }
633
                } else {
634
                    if (insn & (1 << 24)) {
635
                        /* pre decrement */
636
                        gen_op_addl_T1_im(-(n * 4));
637
                    } else {
638
                        /* post decrement */
639
                        if (n != 1)
640
                            gen_op_addl_T1_im(-((n - 1) * 4));
641
                    }
642
                }
643
                j = 0;
644
                for(i=0;i<16;i++) {
645
                    if (insn & (1 << i)) {
646
                        if (insn & (1 << 20)) {
647
                            /* load */
648
                            gen_op_ldl_T0_T1();
649
                            gen_movl_reg_T0(s, i);
650
                        } else {
651
                            /* store */
652
                            if (i == 15) {
653
                                /* special case: r15 = PC + 12 */
654
                                val = (long)s->pc + 8;
655
                                gen_op_movl_TN_im[0](val);
656
                            } else {
657
                                gen_movl_T0_reg(s, i);
658
                            }
659
                            gen_op_stl_T0_T1();
660
                        }
661
                        j++;
662
                        /* no need to add after the last transfer */
663
                        if (j != n)
664
                            gen_op_addl_T1_im(4);
665
                    }
666
                }
667
                if (insn & (1 << 21)) {
668
                    /* write back */
669
                    if (insn & (1 << 23)) {
670
                        if (insn & (1 << 24)) {
671
                            /* pre increment */
672
                        } else {
673
                            /* post increment */
674
                            gen_op_addl_T1_im(4);
675
                        }
676
                    } else {
677
                        if (insn & (1 << 24)) {
678
                            /* pre decrement */
679
                            if (n != 1)
680
                                gen_op_addl_T1_im(-((n - 1) * 4));
681
                        } else {
682
                            /* post decrement */
683
                            gen_op_addl_T1_im(-(n * 4));
684
                        }
685
                    }
686
                    gen_movl_reg_T1(s, rn);
687
                }
688
            }
689
            break;
690
        case 0xa:
691
        case 0xb:
692
            {
693
                int offset;
694
                
695
                /* branch (and link) */
696
                val = (int)s->pc;
697
                if (insn & (1 << 24)) {
698
                    gen_op_movl_T0_im(val);
699
                    gen_op_movl_reg_TN[0][14]();
700
                }
701
                offset = (((int)insn << 8) >> 8);
702
                val += (offset << 2) + 4;
703
                gen_op_jmp((long)s->tb, val);
704
                s->is_jmp = DISAS_TB_JUMP;
705
            }
706
            break;
707
        case 0xf:
708
            /* swi */
709
            gen_op_movl_T0_im((long)s->pc);
710
            gen_op_movl_reg_TN[0][15]();
711
            gen_op_swi();
712
            s->is_jmp = DISAS_JUMP;
713
            break;
714
        default:
715
        illegal_op:
716
            gen_op_movl_T0_im((long)s->pc - 4);
717
            gen_op_movl_reg_TN[0][15]();
718
            gen_op_undef_insn();
719
            s->is_jmp = DISAS_JUMP;
720
            break;
721
        }
722
    }
723
}
724

    
725
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
726
   basic block 'tb'. If search_pc is TRUE, also generate PC
727
   information for each intermediate instruction. */
728
static inline int gen_intermediate_code_internal(CPUState *env, 
729
                                                 TranslationBlock *tb, 
730
                                                 int search_pc)
731
{
732
    DisasContext dc1, *dc = &dc1;
733
    uint16_t *gen_opc_end;
734
    int j, lj;
735
    uint8_t *pc_start;
736
    
737
    /* generate intermediate code */
738
    pc_start = (uint8_t *)tb->pc;
739
       
740
    dc->tb = tb;
741

    
742
    gen_opc_ptr = gen_opc_buf;
743
    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
744
    gen_opparam_ptr = gen_opparam_buf;
745

    
746
    dc->is_jmp = DISAS_NEXT;
747
    dc->pc = pc_start;
748
    lj = -1;
749
    do {
750
        if (search_pc) {
751
            j = gen_opc_ptr - gen_opc_buf;
752
            if (lj < j) {
753
                lj++;
754
                while (lj < j)
755
                    gen_opc_instr_start[lj++] = 0;
756
            }
757
            gen_opc_pc[lj] = (uint32_t)dc->pc;
758
            gen_opc_instr_start[lj] = 1;
759
        }
760
        disas_arm_insn(dc);
761
    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
762
             (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
763
    switch(dc->is_jmp) {
764
    case DISAS_JUMP_NEXT:
765
    case DISAS_NEXT:
766
        gen_op_jmp((long)dc->tb, (long)dc->pc);
767
        break;
768
    default:
769
    case DISAS_JUMP:
770
        /* indicate that the hash table must be used to find the next TB */
771
        gen_op_movl_T0_0();
772
        gen_op_exit_tb();
773
        break;
774
    case DISAS_TB_JUMP:
775
        /* nothing more to generate */
776
        break;
777
    }
778
    *gen_opc_ptr = INDEX_op_end;
779

    
780
#ifdef DEBUG_DISAS
781
    if (loglevel & CPU_LOG_TB_IN_ASM) {
782
        fprintf(logfile, "----------------\n");
783
        fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
784
        disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
785
        fprintf(logfile, "\n");
786
        if (loglevel & (CPU_LOG_TB_OP)) {
787
            fprintf(logfile, "OP:\n");
788
            dump_ops(gen_opc_buf, gen_opparam_buf);
789
            fprintf(logfile, "\n");
790
        }
791
    }
792
#endif
793
    if (!search_pc)
794
        tb->size = dc->pc - pc_start;
795
    return 0;
796
}
797

    
798
int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
799
{
800
    return gen_intermediate_code_internal(env, tb, 0);
801
}
802

    
803
int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
804
{
805
    return gen_intermediate_code_internal(env, tb, 1);
806
}
807

    
808
CPUARMState *cpu_arm_init(void)
809
{
810
    CPUARMState *env;
811

    
812
    cpu_exec_init();
813

    
814
    env = malloc(sizeof(CPUARMState));
815
    if (!env)
816
        return NULL;
817
    memset(env, 0, sizeof(CPUARMState));
818
    cpu_single_env = env;
819
    return env;
820
}
821

    
822
void cpu_arm_close(CPUARMState *env)
823
{
824
    free(env);
825
}
826

    
827
void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
828
{
829
    int i;
830

    
831
    for(i=0;i<16;i++) {
832
        fprintf(f, "R%02d=%08x", i, env->regs[i]);
833
        if ((i % 4) == 3)
834
            fprintf(f, "\n");
835
        else
836
            fprintf(f, " ");
837
    }
838
    fprintf(f, "PSR=%08x %c%c%c%c\n", 
839
            env->cpsr, 
840
            env->cpsr & (1 << 31) ? 'N' : '-',
841
            env->cpsr & (1 << 30) ? 'Z' : '-',
842
            env->cpsr & (1 << 29) ? 'C' : '-',
843
            env->cpsr & (1 << 28) ? 'V' : '-');
844
}
845

    
846
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
847
{
848
    return addr;
849
}