SDL static config fix (Roman Zippel)
[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                 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 }