suppressed unneeded header
[qemu] / target-arm / translate.c
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     return env;
819 }
820
821 void cpu_arm_close(CPUARMState *env)
822 {
823     free(env);
824 }
825
826 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
827 {
828     int i;
829
830     for(i=0;i<16;i++) {
831         fprintf(f, "R%02d=%08x", i, env->regs[i]);
832         if ((i % 4) == 3)
833             fprintf(f, "\n");
834         else
835             fprintf(f, " ");
836     }
837     fprintf(f, "PSR=%08x %c%c%c%c\n", 
838             env->cpsr, 
839             env->cpsr & (1 << 31) ? 'N' : '-',
840             env->cpsr & (1 << 30) ? 'Z' : '-',
841             env->cpsr & (1 << 29) ? 'C' : '-',
842             env->cpsr & (1 << 28) ? 'V' : '-');
843 }
844
845 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
846 {
847     return addr;
848 }