Statistics
| Branch: | Revision:

root / target-arm / translate.c @ e19e89a5

History | View | Annotate | Download (23.4 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
                gen_add_datah_offset(s, insn);
547
                if (insn & (1 << 20)) {
548
                    /* load */
549
                    switch(sh) {
550
                    case 1:
551
                        gen_op_lduw_T0_T1();
552
                        break;
553
                    case 2:
554
                        gen_op_ldsb_T0_T1();
555
                        break;
556
                    default:
557
                    case 3:
558
                        gen_op_ldsw_T0_T1();
559
                        break;
560
                    }
561
                    gen_movl_reg_T0(s, rd);
562
                } else {
563
                    /* store */
564
                    gen_movl_T0_reg(s, rd);
565
                    gen_op_stw_T0_T1();
566
                }
567
                if (!(insn & (1 << 24))) {
568
                    gen_add_datah_offset(s, insn);
569
                    gen_movl_reg_T1(s, rn);
570
                } else if (insn & (1 << 21)) {
571
                    gen_movl_reg_T1(s, rn);
572
                }
573
            }
574
            break;
575
        case 0x4:
576
        case 0x5:
577
        case 0x6:
578
        case 0x7:
579
            /* load/store byte/word */
580
            rn = (insn >> 16) & 0xf;
581
            rd = (insn >> 12) & 0xf;
582
            gen_movl_T1_reg(s, rn);
583
            if (insn & (1 << 24))
584
                gen_add_data_offset(s, insn);
585
            if (insn & (1 << 20)) {
586
                /* load */
587
                if (insn & (1 << 22))
588
                    gen_op_ldub_T0_T1();
589
                else
590
                    gen_op_ldl_T0_T1();
591
                gen_movl_reg_T0(s, rd);
592
            } else {
593
                /* store */
594
                gen_movl_T0_reg(s, rd);
595
                if (insn & (1 << 22))
596
                    gen_op_stb_T0_T1();
597
                else
598
                    gen_op_stl_T0_T1();
599
            }
600
            if (!(insn & (1 << 24))) {
601
                gen_add_data_offset(s, insn);
602
                gen_movl_reg_T1(s, rn);
603
            } else if (insn & (1 << 21))
604
                gen_movl_reg_T1(s, rn); {
605
            }
606
            break;
607
        case 0x08:
608
        case 0x09:
609
            {
610
                int j, n;
611
                /* load/store multiple words */
612
                /* XXX: store correct base if write back */
613
                if (insn & (1 << 22))
614
                    goto illegal_op; /* only usable in supervisor mode */
615
                rn = (insn >> 16) & 0xf;
616
                gen_movl_T1_reg(s, rn);
617
                
618
                /* compute total size */
619
                n = 0;
620
                for(i=0;i<16;i++) {
621
                    if (insn & (1 << i))
622
                        n++;
623
                }
624
                /* XXX: test invalid n == 0 case ? */
625
                if (insn & (1 << 23)) {
626
                    if (insn & (1 << 24)) {
627
                        /* pre increment */
628
                        gen_op_addl_T1_im(4);
629
                    } else {
630
                        /* post increment */
631
                    }
632
                } else {
633
                    if (insn & (1 << 24)) {
634
                        /* pre decrement */
635
                        gen_op_addl_T1_im(-(n * 4));
636
                    } else {
637
                        /* post decrement */
638
                        if (n != 1)
639
                            gen_op_addl_T1_im(-((n - 1) * 4));
640
                    }
641
                }
642
                j = 0;
643
                for(i=0;i<16;i++) {
644
                    if (insn & (1 << i)) {
645
                        if (insn & (1 << 20)) {
646
                            /* load */
647
                            gen_op_ldl_T0_T1();
648
                            gen_movl_reg_T0(s, i);
649
                        } else {
650
                            /* store */
651
                            if (i == 15) {
652
                                /* special case: r15 = PC + 12 */
653
                                val = (long)s->pc + 8;
654
                                gen_op_movl_TN_im[0](val);
655
                            } else {
656
                                gen_movl_T0_reg(s, i);
657
                            }
658
                            gen_op_stl_T0_T1();
659
                        }
660
                        j++;
661
                        /* no need to add after the last transfer */
662
                        if (j != n)
663
                            gen_op_addl_T1_im(4);
664
                    }
665
                }
666
                if (insn & (1 << 21)) {
667
                    /* write back */
668
                    if (insn & (1 << 23)) {
669
                        if (insn & (1 << 24)) {
670
                            /* pre increment */
671
                        } else {
672
                            /* post increment */
673
                            gen_op_addl_T1_im(4);
674
                        }
675
                    } else {
676
                        if (insn & (1 << 24)) {
677
                            /* pre decrement */
678
                            if (n != 1)
679
                                gen_op_addl_T1_im(-((n - 1) * 4));
680
                        } else {
681
                            /* post decrement */
682
                            gen_op_addl_T1_im(-(n * 4));
683
                        }
684
                    }
685
                    gen_movl_reg_T1(s, rn);
686
                }
687
            }
688
            break;
689
        case 0xa:
690
        case 0xb:
691
            {
692
                int offset;
693
                
694
                /* branch (and link) */
695
                val = (int)s->pc;
696
                if (insn & (1 << 24)) {
697
                    gen_op_movl_T0_im(val);
698
                    gen_op_movl_reg_TN[0][14]();
699
                }
700
                offset = (((int)insn << 8) >> 8);
701
                val += (offset << 2) + 4;
702
                gen_op_jmp((long)s->tb, val);
703
                s->is_jmp = DISAS_TB_JUMP;
704
            }
705
            break;
706
        case 0xf:
707
            /* swi */
708
            gen_op_movl_T0_im((long)s->pc);
709
            gen_op_movl_reg_TN[0][15]();
710
            gen_op_swi();
711
            s->is_jmp = DISAS_JUMP;
712
            break;
713
        default:
714
        illegal_op:
715
            gen_op_movl_T0_im((long)s->pc - 4);
716
            gen_op_movl_reg_TN[0][15]();
717
            gen_op_undef_insn();
718
            s->is_jmp = DISAS_JUMP;
719
            break;
720
        }
721
    }
722
}
723

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

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

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

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

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

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

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

    
811
    cpu_exec_init();
812

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

    
820
void cpu_arm_close(CPUARMState *env)
821
{
822
    free(env);
823
}
824

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

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

    
844
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
845
{
846
    return addr;
847
}