64 bit fix
[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     target_ulong 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 GenOpFunc *gen_shift_T1_0[4] = {
98     NULL,
99     gen_op_shrl_T1_0,
100     gen_op_sarl_T1_0,
101     gen_op_rrxl_T1,
102 };
103
104 static GenOpFunc1 *gen_shift_T2_im[4] = {
105     gen_op_shll_T2_im,
106     gen_op_shrl_T2_im,
107     gen_op_sarl_T2_im,
108     gen_op_rorl_T2_im,
109 };
110
111 static GenOpFunc *gen_shift_T2_0[4] = {
112     NULL,
113     gen_op_shrl_T2_0,
114     gen_op_sarl_T2_0,
115     gen_op_rrxl_T2,
116 };
117
118 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
119     gen_op_shll_T1_im_cc,
120     gen_op_shrl_T1_im_cc,
121     gen_op_sarl_T1_im_cc,
122     gen_op_rorl_T1_im_cc,
123 };
124
125 static GenOpFunc *gen_shift_T1_0_cc[4] = {
126     NULL,
127     gen_op_shrl_T1_0_cc,
128     gen_op_sarl_T1_0_cc,
129     gen_op_rrxl_T1_cc,
130 };
131
132 static GenOpFunc *gen_shift_T1_T0[4] = {
133     gen_op_shll_T1_T0,
134     gen_op_shrl_T1_T0,
135     gen_op_sarl_T1_T0,
136     gen_op_rorl_T1_T0,
137 };
138
139 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
140     gen_op_shll_T1_T0_cc,
141     gen_op_shrl_T1_T0_cc,
142     gen_op_sarl_T1_T0_cc,
143     gen_op_rorl_T1_T0_cc,
144 };
145
146 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
147     {
148         gen_op_movl_T0_r0,
149         gen_op_movl_T0_r1,
150         gen_op_movl_T0_r2,
151         gen_op_movl_T0_r3,
152         gen_op_movl_T0_r4,
153         gen_op_movl_T0_r5,
154         gen_op_movl_T0_r6,
155         gen_op_movl_T0_r7,
156         gen_op_movl_T0_r8,
157         gen_op_movl_T0_r9,
158         gen_op_movl_T0_r10,
159         gen_op_movl_T0_r11,
160         gen_op_movl_T0_r12,
161         gen_op_movl_T0_r13,
162         gen_op_movl_T0_r14,
163         gen_op_movl_T0_r15,
164     },
165     {
166         gen_op_movl_T1_r0,
167         gen_op_movl_T1_r1,
168         gen_op_movl_T1_r2,
169         gen_op_movl_T1_r3,
170         gen_op_movl_T1_r4,
171         gen_op_movl_T1_r5,
172         gen_op_movl_T1_r6,
173         gen_op_movl_T1_r7,
174         gen_op_movl_T1_r8,
175         gen_op_movl_T1_r9,
176         gen_op_movl_T1_r10,
177         gen_op_movl_T1_r11,
178         gen_op_movl_T1_r12,
179         gen_op_movl_T1_r13,
180         gen_op_movl_T1_r14,
181         gen_op_movl_T1_r15,
182     },
183     {
184         gen_op_movl_T2_r0,
185         gen_op_movl_T2_r1,
186         gen_op_movl_T2_r2,
187         gen_op_movl_T2_r3,
188         gen_op_movl_T2_r4,
189         gen_op_movl_T2_r5,
190         gen_op_movl_T2_r6,
191         gen_op_movl_T2_r7,
192         gen_op_movl_T2_r8,
193         gen_op_movl_T2_r9,
194         gen_op_movl_T2_r10,
195         gen_op_movl_T2_r11,
196         gen_op_movl_T2_r12,
197         gen_op_movl_T2_r13,
198         gen_op_movl_T2_r14,
199         gen_op_movl_T2_r15,
200     },
201 };
202
203 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
204     {
205         gen_op_movl_r0_T0,
206         gen_op_movl_r1_T0,
207         gen_op_movl_r2_T0,
208         gen_op_movl_r3_T0,
209         gen_op_movl_r4_T0,
210         gen_op_movl_r5_T0,
211         gen_op_movl_r6_T0,
212         gen_op_movl_r7_T0,
213         gen_op_movl_r8_T0,
214         gen_op_movl_r9_T0,
215         gen_op_movl_r10_T0,
216         gen_op_movl_r11_T0,
217         gen_op_movl_r12_T0,
218         gen_op_movl_r13_T0,
219         gen_op_movl_r14_T0,
220         gen_op_movl_r15_T0,
221     },
222     {
223         gen_op_movl_r0_T1,
224         gen_op_movl_r1_T1,
225         gen_op_movl_r2_T1,
226         gen_op_movl_r3_T1,
227         gen_op_movl_r4_T1,
228         gen_op_movl_r5_T1,
229         gen_op_movl_r6_T1,
230         gen_op_movl_r7_T1,
231         gen_op_movl_r8_T1,
232         gen_op_movl_r9_T1,
233         gen_op_movl_r10_T1,
234         gen_op_movl_r11_T1,
235         gen_op_movl_r12_T1,
236         gen_op_movl_r13_T1,
237         gen_op_movl_r14_T1,
238         gen_op_movl_r15_T1,
239     },
240 };
241
242 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
243     gen_op_movl_T0_im,
244     gen_op_movl_T1_im,
245     gen_op_movl_T2_im,
246 };
247
248 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
249 {
250     int val;
251
252     if (reg == 15) {
253         /* normaly, since we updated PC, we need only to add 4 */
254         val = (long)s->pc + 4;
255         gen_op_movl_TN_im[t](val);
256     } else {
257         gen_op_movl_TN_reg[t][reg]();
258     }
259 }
260
261 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
262 {
263     gen_movl_TN_reg(s, reg, 0);
264 }
265
266 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
267 {
268     gen_movl_TN_reg(s, reg, 1);
269 }
270
271 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
272 {
273     gen_movl_TN_reg(s, reg, 2);
274 }
275
276 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
277 {
278     gen_op_movl_reg_TN[t][reg]();
279     if (reg == 15) {
280         s->is_jmp = DISAS_JUMP;
281     }
282 }
283
284 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
285 {
286     gen_movl_reg_TN(s, reg, 0);
287 }
288
289 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
290 {
291     gen_movl_reg_TN(s, reg, 1);
292 }
293
294 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
295 {
296     int val, rm, shift, shiftop;
297
298     if (!(insn & (1 << 25))) {
299         /* immediate */
300         val = insn & 0xfff;
301         if (!(insn & (1 << 23)))
302             val = -val;
303         if (val != 0)
304             gen_op_addl_T1_im(val);
305     } else {
306         /* shift/register */
307         rm = (insn) & 0xf;
308         shift = (insn >> 7) & 0x1f;
309         gen_movl_T2_reg(s, rm);
310         shiftop = (insn >> 5) & 3;
311         if (shift != 0) {
312             gen_shift_T2_im[shiftop](shift);
313         } else if (shiftop != 0) {
314             gen_shift_T2_0[shiftop]();
315         }
316         if (!(insn & (1 << 23)))
317             gen_op_subl_T1_T2();
318         else
319             gen_op_addl_T1_T2();
320     }
321 }
322
323 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
324 {
325     int val, rm;
326     
327     if (insn & (1 << 22)) {
328         /* immediate */
329         val = (insn & 0xf) | ((insn >> 4) & 0xf0);
330         if (!(insn & (1 << 23)))
331             val = -val;
332         if (val != 0)
333             gen_op_addl_T1_im(val);
334     } else {
335         /* register */
336         rm = (insn) & 0xf;
337         gen_movl_T2_reg(s, rm);
338         if (!(insn & (1 << 23)))
339             gen_op_subl_T1_T2();
340         else
341             gen_op_addl_T1_T2();
342     }
343 }
344
345 static void disas_arm_insn(DisasContext *s)
346 {
347     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
348     
349     insn = ldl(s->pc);
350     s->pc += 4;
351     
352     cond = insn >> 28;
353     if (cond == 0xf)
354         goto illegal_op;
355     if (cond != 0xe) {
356         /* if not always execute, we generate a conditional jump to
357            next instruction */
358         gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
359         s->is_jmp = DISAS_JUMP_NEXT;
360     }
361     if (((insn & 0x0e000000) == 0 &&
362          (insn & 0x00000090) != 0x90) ||
363         ((insn & 0x0e000000) == (1 << 25))) {
364         int set_cc, logic_cc, shiftop;
365         
366         op1 = (insn >> 21) & 0xf;
367         set_cc = (insn >> 20) & 1;
368         logic_cc = table_logic_cc[op1] & set_cc;
369
370         /* data processing instruction */
371         if (insn & (1 << 25)) {
372             /* immediate operand */
373             val = insn & 0xff;
374             shift = ((insn >> 8) & 0xf) * 2;
375             if (shift)
376                 val = (val >> shift) | (val << (32 - shift));
377             gen_op_movl_T1_im(val);
378             /* XXX: is CF modified ? */
379         } else {
380             /* register */
381             rm = (insn) & 0xf;
382             gen_movl_T1_reg(s, rm);
383             shiftop = (insn >> 5) & 3;
384             if (!(insn & (1 << 4))) {
385                 shift = (insn >> 7) & 0x1f;
386                 if (shift != 0) {
387                     if (logic_cc) {
388                         gen_shift_T1_im_cc[shiftop](shift);
389                     } else {
390                         gen_shift_T1_im[shiftop](shift);
391                     }
392                 } else if (shiftop != 0) {
393                     if (logic_cc) {
394                         gen_shift_T1_0_cc[shiftop]();
395                     } else {
396                         gen_shift_T1_0[shiftop]();
397                     }
398                 }
399             } else {
400                 rs = (insn >> 8) & 0xf;
401                 gen_movl_T0_reg(s, rs);
402                 if (logic_cc) {
403                     gen_shift_T1_T0_cc[shiftop]();
404                 } else {
405                     gen_shift_T1_T0[shiftop]();
406                 }
407             }
408         }
409         if (op1 != 0x0f && op1 != 0x0d) {
410             rn = (insn >> 16) & 0xf;
411             gen_movl_T0_reg(s, rn);
412         }
413         rd = (insn >> 12) & 0xf;
414         switch(op1) {
415         case 0x00:
416             gen_op_andl_T0_T1();
417             gen_movl_reg_T0(s, rd);
418             if (logic_cc)
419                 gen_op_logic_T0_cc();
420             break;
421         case 0x01:
422             gen_op_xorl_T0_T1();
423             gen_movl_reg_T0(s, rd);
424             if (logic_cc)
425                 gen_op_logic_T0_cc();
426             break;
427         case 0x02:
428             if (set_cc)
429                 gen_op_subl_T0_T1_cc();
430             else
431                 gen_op_subl_T0_T1();
432             gen_movl_reg_T0(s, rd);
433             break;
434         case 0x03:
435             if (set_cc)
436                 gen_op_rsbl_T0_T1_cc();
437             else
438                 gen_op_rsbl_T0_T1();
439             gen_movl_reg_T0(s, rd);
440             break;
441         case 0x04:
442             if (set_cc)
443                 gen_op_addl_T0_T1_cc();
444             else
445                 gen_op_addl_T0_T1();
446             gen_movl_reg_T0(s, rd);
447             break;
448         case 0x05:
449             if (set_cc)
450                 gen_op_adcl_T0_T1_cc();
451             else
452                 gen_op_adcl_T0_T1();
453             gen_movl_reg_T0(s, rd);
454             break;
455         case 0x06:
456             if (set_cc)
457                 gen_op_sbcl_T0_T1_cc();
458             else
459                 gen_op_sbcl_T0_T1();
460             gen_movl_reg_T0(s, rd);
461             break;
462         case 0x07:
463             if (set_cc)
464                 gen_op_rscl_T0_T1_cc();
465             else
466                 gen_op_rscl_T0_T1();
467             gen_movl_reg_T0(s, rd);
468             break;
469         case 0x08:
470             if (set_cc) {
471                 gen_op_andl_T0_T1();
472                 gen_op_logic_T0_cc();
473             }
474             break;
475         case 0x09:
476             if (set_cc) {
477                 gen_op_xorl_T0_T1();
478                 gen_op_logic_T0_cc();
479             }
480             break;
481         case 0x0a:
482             if (set_cc) {
483                 gen_op_subl_T0_T1_cc();
484             }
485             break;
486         case 0x0b:
487             if (set_cc) {
488                 gen_op_addl_T0_T1_cc();
489             }
490             break;
491         case 0x0c:
492             gen_op_orl_T0_T1();
493             gen_movl_reg_T0(s, rd);
494             if (logic_cc)
495                 gen_op_logic_T0_cc();
496             break;
497         case 0x0d:
498             gen_movl_reg_T1(s, rd);
499             if (logic_cc)
500                 gen_op_logic_T1_cc();
501             break;
502         case 0x0e:
503             gen_op_bicl_T0_T1();
504             gen_movl_reg_T0(s, rd);
505             if (logic_cc)
506                 gen_op_logic_T0_cc();
507             break;
508         default:
509         case 0x0f:
510             gen_op_notl_T1();
511             gen_movl_reg_T1(s, rd);
512             if (logic_cc)
513                 gen_op_logic_T1_cc();
514             break;
515         }
516     } else {
517         /* other instructions */
518         op1 = (insn >> 24) & 0xf;
519         switch(op1) {
520         case 0x0:
521         case 0x1:
522             sh = (insn >> 5) & 3;
523             if (sh == 0) {
524                 if (op1 == 0x0) {
525                     rd = (insn >> 16) & 0xf;
526                     rn = (insn >> 12) & 0xf;
527                     rs = (insn >> 8) & 0xf;
528                     rm = (insn) & 0xf;
529                     if (!(insn & (1 << 23))) {
530                         /* 32 bit mul */
531                         gen_movl_T0_reg(s, rs);
532                         gen_movl_T1_reg(s, rm);
533                         gen_op_mul_T0_T1();
534                         if (insn & (1 << 21)) {
535                             gen_movl_T1_reg(s, rn);
536                             gen_op_addl_T0_T1();
537                         }
538                         if (insn & (1 << 20)) 
539                             gen_op_logic_T0_cc();
540                         gen_movl_reg_T0(s, rd);
541                     } else {
542                         /* 64 bit mul */
543                         gen_movl_T0_reg(s, rs);
544                         gen_movl_T1_reg(s, rm);
545                         if (insn & (1 << 22)) 
546                             gen_op_imull_T0_T1();
547                         else
548                             gen_op_mull_T0_T1();
549                         if (insn & (1 << 21)) 
550                             gen_op_addq_T0_T1(rn, rd);
551                         if (insn & (1 << 20)) 
552                             gen_op_logicq_cc();
553                         gen_movl_reg_T0(s, rn);
554                         gen_movl_reg_T1(s, rd);
555                     }
556                 } else {
557                     /* SWP instruction */
558                     rn = (insn >> 16) & 0xf;
559                     rd = (insn >> 12) & 0xf;
560                     rm = (insn) & 0xf;
561                     
562                     gen_movl_T0_reg(s, rm);
563                     gen_movl_T1_reg(s, rn);
564                     if (insn & (1 << 22)) {
565                         gen_op_swpb_T0_T1();
566                     } else {
567                         gen_op_swpl_T0_T1();
568                     }
569                     gen_movl_reg_T0(s, rd);
570                 }
571             } else {
572                 /* load/store half word */
573                 rn = (insn >> 16) & 0xf;
574                 rd = (insn >> 12) & 0xf;
575                 gen_movl_T1_reg(s, rn);
576                 if (insn & (1 << 24))
577                     gen_add_datah_offset(s, insn);
578                 if (insn & (1 << 20)) {
579                     /* load */
580                     switch(sh) {
581                     case 1:
582                         gen_op_lduw_T0_T1();
583                         break;
584                     case 2:
585                         gen_op_ldsb_T0_T1();
586                         break;
587                     default:
588                     case 3:
589                         gen_op_ldsw_T0_T1();
590                         break;
591                     }
592                     gen_movl_reg_T0(s, rd);
593                 } else {
594                     /* store */
595                     gen_movl_T0_reg(s, rd);
596                     gen_op_stw_T0_T1();
597                 }
598                 if (!(insn & (1 << 24))) {
599                     gen_add_datah_offset(s, insn);
600                     gen_movl_reg_T1(s, rn);
601                 } else if (insn & (1 << 21)) {
602                     gen_movl_reg_T1(s, rn);
603                 }
604             }
605             break;
606         case 0x4:
607         case 0x5:
608         case 0x6:
609         case 0x7:
610             /* load/store byte/word */
611             rn = (insn >> 16) & 0xf;
612             rd = (insn >> 12) & 0xf;
613             gen_movl_T1_reg(s, rn);
614             if (insn & (1 << 24))
615                 gen_add_data_offset(s, insn);
616             if (insn & (1 << 20)) {
617                 /* load */
618                 if (insn & (1 << 22))
619                     gen_op_ldub_T0_T1();
620                 else
621                     gen_op_ldl_T0_T1();
622                 gen_movl_reg_T0(s, rd);
623             } else {
624                 /* store */
625                 gen_movl_T0_reg(s, rd);
626                 if (insn & (1 << 22))
627                     gen_op_stb_T0_T1();
628                 else
629                     gen_op_stl_T0_T1();
630             }
631             if (!(insn & (1 << 24))) {
632                 gen_add_data_offset(s, insn);
633                 gen_movl_reg_T1(s, rn);
634             } else if (insn & (1 << 21))
635                 gen_movl_reg_T1(s, rn); {
636             }
637             break;
638         case 0x08:
639         case 0x09:
640             {
641                 int j, n;
642                 /* load/store multiple words */
643                 /* XXX: store correct base if write back */
644                 if (insn & (1 << 22))
645                     goto illegal_op; /* only usable in supervisor mode */
646                 rn = (insn >> 16) & 0xf;
647                 gen_movl_T1_reg(s, rn);
648                 
649                 /* compute total size */
650                 n = 0;
651                 for(i=0;i<16;i++) {
652                     if (insn & (1 << i))
653                         n++;
654                 }
655                 /* XXX: test invalid n == 0 case ? */
656                 if (insn & (1 << 23)) {
657                     if (insn & (1 << 24)) {
658                         /* pre increment */
659                         gen_op_addl_T1_im(4);
660                     } else {
661                         /* post increment */
662                     }
663                 } else {
664                     if (insn & (1 << 24)) {
665                         /* pre decrement */
666                         gen_op_addl_T1_im(-(n * 4));
667                     } else {
668                         /* post decrement */
669                         if (n != 1)
670                             gen_op_addl_T1_im(-((n - 1) * 4));
671                     }
672                 }
673                 j = 0;
674                 for(i=0;i<16;i++) {
675                     if (insn & (1 << i)) {
676                         if (insn & (1 << 20)) {
677                             /* load */
678                             gen_op_ldl_T0_T1();
679                             gen_movl_reg_T0(s, i);
680                         } else {
681                             /* store */
682                             if (i == 15) {
683                                 /* special case: r15 = PC + 12 */
684                                 val = (long)s->pc + 8;
685                                 gen_op_movl_TN_im[0](val);
686                             } else {
687                                 gen_movl_T0_reg(s, i);
688                             }
689                             gen_op_stl_T0_T1();
690                         }
691                         j++;
692                         /* no need to add after the last transfer */
693                         if (j != n)
694                             gen_op_addl_T1_im(4);
695                     }
696                 }
697                 if (insn & (1 << 21)) {
698                     /* write back */
699                     if (insn & (1 << 23)) {
700                         if (insn & (1 << 24)) {
701                             /* pre increment */
702                         } else {
703                             /* post increment */
704                             gen_op_addl_T1_im(4);
705                         }
706                     } else {
707                         if (insn & (1 << 24)) {
708                             /* pre decrement */
709                             if (n != 1)
710                                 gen_op_addl_T1_im(-((n - 1) * 4));
711                         } else {
712                             /* post decrement */
713                             gen_op_addl_T1_im(-(n * 4));
714                         }
715                     }
716                     gen_movl_reg_T1(s, rn);
717                 }
718             }
719             break;
720         case 0xa:
721         case 0xb:
722             {
723                 int offset;
724                 
725                 /* branch (and link) */
726                 val = (int)s->pc;
727                 if (insn & (1 << 24)) {
728                     gen_op_movl_T0_im(val);
729                     gen_op_movl_reg_TN[0][14]();
730                 }
731                 offset = (((int)insn << 8) >> 8);
732                 val += (offset << 2) + 4;
733                 gen_op_jmp((long)s->tb, val);
734                 s->is_jmp = DISAS_TB_JUMP;
735             }
736             break;
737         case 0xf:
738             /* swi */
739             gen_op_movl_T0_im((long)s->pc);
740             gen_op_movl_reg_TN[0][15]();
741             gen_op_swi();
742             s->is_jmp = DISAS_JUMP;
743             break;
744         default:
745         illegal_op:
746             gen_op_movl_T0_im((long)s->pc - 4);
747             gen_op_movl_reg_TN[0][15]();
748             gen_op_undef_insn();
749             s->is_jmp = DISAS_JUMP;
750             break;
751         }
752     }
753 }
754
755 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
756    basic block 'tb'. If search_pc is TRUE, also generate PC
757    information for each intermediate instruction. */
758 static inline int gen_intermediate_code_internal(CPUState *env, 
759                                                  TranslationBlock *tb, 
760                                                  int search_pc)
761 {
762     DisasContext dc1, *dc = &dc1;
763     uint16_t *gen_opc_end;
764     int j, lj;
765     target_ulong pc_start;
766     
767     /* generate intermediate code */
768     pc_start = tb->pc;
769        
770     dc->tb = tb;
771
772     gen_opc_ptr = gen_opc_buf;
773     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
774     gen_opparam_ptr = gen_opparam_buf;
775
776     dc->is_jmp = DISAS_NEXT;
777     dc->pc = pc_start;
778     lj = -1;
779     do {
780         if (search_pc) {
781             j = gen_opc_ptr - gen_opc_buf;
782             if (lj < j) {
783                 lj++;
784                 while (lj < j)
785                     gen_opc_instr_start[lj++] = 0;
786             }
787             gen_opc_pc[lj] = dc->pc;
788             gen_opc_instr_start[lj] = 1;
789         }
790         disas_arm_insn(dc);
791     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 
792              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
793     switch(dc->is_jmp) {
794     case DISAS_JUMP_NEXT:
795     case DISAS_NEXT:
796         gen_op_jmp((long)dc->tb, (long)dc->pc);
797         break;
798     default:
799     case DISAS_JUMP:
800         /* indicate that the hash table must be used to find the next TB */
801         gen_op_movl_T0_0();
802         gen_op_exit_tb();
803         break;
804     case DISAS_TB_JUMP:
805         /* nothing more to generate */
806         break;
807     }
808     *gen_opc_ptr = INDEX_op_end;
809
810 #ifdef DEBUG_DISAS
811     if (loglevel & CPU_LOG_TB_IN_ASM) {
812         fprintf(logfile, "----------------\n");
813         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
814         target_disas(logfile, pc_start, dc->pc - pc_start, 0);
815         fprintf(logfile, "\n");
816         if (loglevel & (CPU_LOG_TB_OP)) {
817             fprintf(logfile, "OP:\n");
818             dump_ops(gen_opc_buf, gen_opparam_buf);
819             fprintf(logfile, "\n");
820         }
821     }
822 #endif
823     if (!search_pc)
824         tb->size = dc->pc - pc_start;
825     return 0;
826 }
827
828 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
829 {
830     return gen_intermediate_code_internal(env, tb, 0);
831 }
832
833 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
834 {
835     return gen_intermediate_code_internal(env, tb, 1);
836 }
837
838 CPUARMState *cpu_arm_init(void)
839 {
840     CPUARMState *env;
841
842     cpu_exec_init();
843
844     env = malloc(sizeof(CPUARMState));
845     if (!env)
846         return NULL;
847     memset(env, 0, sizeof(CPUARMState));
848     cpu_single_env = env;
849     return env;
850 }
851
852 void cpu_arm_close(CPUARMState *env)
853 {
854     free(env);
855 }
856
857 void cpu_dump_state(CPUState *env, FILE *f, 
858                     int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
859                     int flags)
860 {
861     int i;
862
863     for(i=0;i<16;i++) {
864         cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
865         if ((i % 4) == 3)
866             cpu_fprintf(f, "\n");
867         else
868             cpu_fprintf(f, " ");
869     }
870     cpu_fprintf(f, "PSR=%08x %c%c%c%c\n", 
871             env->cpsr, 
872             env->cpsr & (1 << 31) ? 'N' : '-',
873             env->cpsr & (1 << 30) ? 'Z' : '-',
874             env->cpsr & (1 << 29) ? 'C' : '-',
875             env->cpsr & (1 << 28) ? 'V' : '-');
876 }
877
878 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
879 {
880     return addr;
881 }