moved IDE driver to ide.c
[qemu/qemu_0_9_1_stable.git] / target-arm / translate.c
blob808fa2b34fe5042d246db297fc6ce25f2448dfdf
1 /*
2 * ARM translation
3 *
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
26 #include "cpu.h"
27 #include "exec-all.h"
28 #include "disas.h"
30 /* internal defines */
31 typedef struct DisasContext {
32 uint8_t *pc;
33 int is_jmp;
34 struct TranslationBlock *tb;
35 } DisasContext;
37 #define DISAS_JUMP_NEXT 4
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;
45 enum {
46 #define DEF(s, n, copy_size) INDEX_op_ ## s,
47 #include "opc.h"
48 #undef DEF
49 NB_OPS,
52 #include "gen-op.h"
54 typedef void (GenOpFunc)(void);
55 typedef void (GenOpFunc1)(long);
56 typedef void (GenOpFunc2)(long, long);
57 typedef void (GenOpFunc3)(long, long, long);
59 static GenOpFunc2 *gen_test_cc[14] = {
60 gen_op_test_eq,
61 gen_op_test_ne,
62 gen_op_test_cs,
63 gen_op_test_cc,
64 gen_op_test_mi,
65 gen_op_test_pl,
66 gen_op_test_vs,
67 gen_op_test_vc,
68 gen_op_test_hi,
69 gen_op_test_ls,
70 gen_op_test_ge,
71 gen_op_test_lt,
72 gen_op_test_gt,
73 gen_op_test_le,
76 const uint8_t table_logic_cc[16] = {
77 1, /* and */
78 1, /* xor */
79 0, /* sub */
80 0, /* rsb */
81 0, /* add */
82 0, /* adc */
83 0, /* sbc */
84 0, /* rsc */
85 1, /* andl */
86 1, /* xorl */
87 0, /* cmp */
88 0, /* cmn */
89 1, /* orr */
90 1, /* mov */
91 1, /* bic */
92 1, /* mvn */
95 static GenOpFunc1 *gen_shift_T1_im[4] = {
96 gen_op_shll_T1_im,
97 gen_op_shrl_T1_im,
98 gen_op_sarl_T1_im,
99 gen_op_rorl_T1_im,
102 static GenOpFunc1 *gen_shift_T2_im[4] = {
103 gen_op_shll_T2_im,
104 gen_op_shrl_T2_im,
105 gen_op_sarl_T2_im,
106 gen_op_rorl_T2_im,
109 static GenOpFunc1 *gen_shift_T1_im_cc[4] = {
110 gen_op_shll_T1_im_cc,
111 gen_op_shrl_T1_im_cc,
112 gen_op_sarl_T1_im_cc,
113 gen_op_rorl_T1_im_cc,
116 static GenOpFunc *gen_shift_T1_T0[4] = {
117 gen_op_shll_T1_T0,
118 gen_op_shrl_T1_T0,
119 gen_op_sarl_T1_T0,
120 gen_op_rorl_T1_T0,
123 static GenOpFunc *gen_shift_T1_T0_cc[4] = {
124 gen_op_shll_T1_T0_cc,
125 gen_op_shrl_T1_T0_cc,
126 gen_op_sarl_T1_T0_cc,
127 gen_op_rorl_T1_T0_cc,
130 static GenOpFunc *gen_op_movl_TN_reg[3][16] = {
132 gen_op_movl_T0_r0,
133 gen_op_movl_T0_r1,
134 gen_op_movl_T0_r2,
135 gen_op_movl_T0_r3,
136 gen_op_movl_T0_r4,
137 gen_op_movl_T0_r5,
138 gen_op_movl_T0_r6,
139 gen_op_movl_T0_r7,
140 gen_op_movl_T0_r8,
141 gen_op_movl_T0_r9,
142 gen_op_movl_T0_r10,
143 gen_op_movl_T0_r11,
144 gen_op_movl_T0_r12,
145 gen_op_movl_T0_r13,
146 gen_op_movl_T0_r14,
147 gen_op_movl_T0_r15,
150 gen_op_movl_T1_r0,
151 gen_op_movl_T1_r1,
152 gen_op_movl_T1_r2,
153 gen_op_movl_T1_r3,
154 gen_op_movl_T1_r4,
155 gen_op_movl_T1_r5,
156 gen_op_movl_T1_r6,
157 gen_op_movl_T1_r7,
158 gen_op_movl_T1_r8,
159 gen_op_movl_T1_r9,
160 gen_op_movl_T1_r10,
161 gen_op_movl_T1_r11,
162 gen_op_movl_T1_r12,
163 gen_op_movl_T1_r13,
164 gen_op_movl_T1_r14,
165 gen_op_movl_T1_r15,
168 gen_op_movl_T2_r0,
169 gen_op_movl_T2_r1,
170 gen_op_movl_T2_r2,
171 gen_op_movl_T2_r3,
172 gen_op_movl_T2_r4,
173 gen_op_movl_T2_r5,
174 gen_op_movl_T2_r6,
175 gen_op_movl_T2_r7,
176 gen_op_movl_T2_r8,
177 gen_op_movl_T2_r9,
178 gen_op_movl_T2_r10,
179 gen_op_movl_T2_r11,
180 gen_op_movl_T2_r12,
181 gen_op_movl_T2_r13,
182 gen_op_movl_T2_r14,
183 gen_op_movl_T2_r15,
187 static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
189 gen_op_movl_r0_T0,
190 gen_op_movl_r1_T0,
191 gen_op_movl_r2_T0,
192 gen_op_movl_r3_T0,
193 gen_op_movl_r4_T0,
194 gen_op_movl_r5_T0,
195 gen_op_movl_r6_T0,
196 gen_op_movl_r7_T0,
197 gen_op_movl_r8_T0,
198 gen_op_movl_r9_T0,
199 gen_op_movl_r10_T0,
200 gen_op_movl_r11_T0,
201 gen_op_movl_r12_T0,
202 gen_op_movl_r13_T0,
203 gen_op_movl_r14_T0,
204 gen_op_movl_r15_T0,
207 gen_op_movl_r0_T1,
208 gen_op_movl_r1_T1,
209 gen_op_movl_r2_T1,
210 gen_op_movl_r3_T1,
211 gen_op_movl_r4_T1,
212 gen_op_movl_r5_T1,
213 gen_op_movl_r6_T1,
214 gen_op_movl_r7_T1,
215 gen_op_movl_r8_T1,
216 gen_op_movl_r9_T1,
217 gen_op_movl_r10_T1,
218 gen_op_movl_r11_T1,
219 gen_op_movl_r12_T1,
220 gen_op_movl_r13_T1,
221 gen_op_movl_r14_T1,
222 gen_op_movl_r15_T1,
226 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
227 gen_op_movl_T0_im,
228 gen_op_movl_T1_im,
229 gen_op_movl_T2_im,
232 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
234 int val;
236 if (reg == 15) {
237 /* normaly, since we updated PC, we need only to add 4 */
238 val = (long)s->pc + 4;
239 gen_op_movl_TN_im[t](val);
240 } else {
241 gen_op_movl_TN_reg[t][reg]();
245 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
247 gen_movl_TN_reg(s, reg, 0);
250 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
252 gen_movl_TN_reg(s, reg, 1);
255 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
257 gen_movl_TN_reg(s, reg, 2);
260 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
262 gen_op_movl_reg_TN[t][reg]();
263 if (reg == 15) {
264 s->is_jmp = DISAS_JUMP;
268 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
270 gen_movl_reg_TN(s, reg, 0);
273 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
275 gen_movl_reg_TN(s, reg, 1);
278 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
280 int val, rm, shift;
282 if (!(insn & (1 << 25))) {
283 /* immediate */
284 val = insn & 0xfff;
285 if (!(insn & (1 << 23)))
286 val = -val;
287 gen_op_addl_T1_im(val);
288 } else {
289 /* shift/register */
290 rm = (insn) & 0xf;
291 shift = (insn >> 7) & 0x1f;
292 gen_movl_T2_reg(s, rm);
293 if (shift != 0) {
294 gen_shift_T2_im[(insn >> 5) & 3](shift);
296 if (!(insn & (1 << 23)))
297 gen_op_subl_T1_T2();
298 else
299 gen_op_addl_T1_T2();
303 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
305 int val, rm;
307 if (insn & (1 << 22)) {
308 /* immediate */
309 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
310 if (!(insn & (1 << 23)))
311 val = -val;
312 gen_op_addl_T1_im(val);
313 } else {
314 /* register */
315 rm = (insn) & 0xf;
316 gen_movl_T2_reg(s, rm);
317 if (!(insn & (1 << 23)))
318 gen_op_subl_T1_T2();
319 else
320 gen_op_addl_T1_T2();
324 static void disas_arm_insn(DisasContext *s)
326 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
328 insn = ldl(s->pc);
329 s->pc += 4;
331 cond = insn >> 28;
332 if (cond == 0xf)
333 goto illegal_op;
334 if (cond != 0xe) {
335 /* if not always execute, we generate a conditional jump to
336 next instruction */
337 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
338 s->is_jmp = DISAS_JUMP_NEXT;
340 if (((insn & 0x0e000000) == 0 &&
341 (insn & 0x00000090) != 0x90) ||
342 ((insn & 0x0e000000) == (1 << 25))) {
343 int set_cc, logic_cc, shiftop;
345 op1 = (insn >> 21) & 0xf;
346 set_cc = (insn >> 20) & 1;
347 logic_cc = table_logic_cc[op1] & set_cc;
349 /* data processing instruction */
350 if (insn & (1 << 25)) {
351 /* immediate operand */
352 val = insn & 0xff;
353 shift = ((insn >> 8) & 0xf) * 2;
354 if (shift)
355 val = (val >> shift) | (val << (32 - shift));
356 gen_op_movl_T1_im(val);
357 /* XXX: is CF modified ? */
358 } else {
359 /* register */
360 rm = (insn) & 0xf;
361 gen_movl_T1_reg(s, rm);
362 shiftop = (insn >> 5) & 3;
363 if (!(insn & (1 << 4))) {
364 shift = (insn >> 7) & 0x1f;
365 if (shift != 0) {
366 if (logic_cc) {
367 gen_shift_T1_im_cc[shiftop](shift);
368 } else {
369 gen_shift_T1_im[shiftop](shift);
372 } else {
373 rs = (insn >> 8) & 0xf;
374 gen_movl_T0_reg(s, rs);
375 if (logic_cc) {
376 gen_shift_T1_T0_cc[shiftop]();
377 } else {
378 gen_shift_T1_T0[shiftop]();
382 if (op1 != 0x0f && op1 != 0x0d) {
383 rn = (insn >> 16) & 0xf;
384 gen_movl_T0_reg(s, rn);
386 rd = (insn >> 12) & 0xf;
387 switch(op1) {
388 case 0x00:
389 gen_op_andl_T0_T1();
390 gen_movl_reg_T0(s, rd);
391 if (logic_cc)
392 gen_op_logic_T0_cc();
393 break;
394 case 0x01:
395 gen_op_xorl_T0_T1();
396 gen_movl_reg_T0(s, rd);
397 if (logic_cc)
398 gen_op_logic_T0_cc();
399 break;
400 case 0x02:
401 if (set_cc)
402 gen_op_subl_T0_T1_cc();
403 else
404 gen_op_subl_T0_T1();
405 gen_movl_reg_T0(s, rd);
406 break;
407 case 0x03:
408 if (set_cc)
409 gen_op_rsbl_T0_T1_cc();
410 else
411 gen_op_rsbl_T0_T1();
412 gen_movl_reg_T0(s, rd);
413 break;
414 case 0x04:
415 if (set_cc)
416 gen_op_addl_T0_T1_cc();
417 else
418 gen_op_addl_T0_T1();
419 gen_movl_reg_T0(s, rd);
420 break;
421 case 0x05:
422 if (set_cc)
423 gen_op_adcl_T0_T1_cc();
424 else
425 gen_op_adcl_T0_T1();
426 gen_movl_reg_T0(s, rd);
427 break;
428 case 0x06:
429 if (set_cc)
430 gen_op_sbcl_T0_T1_cc();
431 else
432 gen_op_sbcl_T0_T1();
433 gen_movl_reg_T0(s, rd);
434 break;
435 case 0x07:
436 if (set_cc)
437 gen_op_rscl_T0_T1_cc();
438 else
439 gen_op_rscl_T0_T1();
440 gen_movl_reg_T0(s, rd);
441 break;
442 case 0x08:
443 if (set_cc) {
444 gen_op_andl_T0_T1();
445 gen_op_logic_T0_cc();
447 break;
448 case 0x09:
449 if (set_cc) {
450 gen_op_xorl_T0_T1();
451 gen_op_logic_T0_cc();
453 break;
454 case 0x0a:
455 if (set_cc) {
456 gen_op_subl_T0_T1_cc();
458 break;
459 case 0x0b:
460 if (set_cc) {
461 gen_op_addl_T0_T1_cc();
463 break;
464 case 0x0c:
465 gen_op_orl_T0_T1();
466 gen_movl_reg_T0(s, rd);
467 if (logic_cc)
468 gen_op_logic_T0_cc();
469 break;
470 case 0x0d:
471 gen_movl_reg_T1(s, rd);
472 if (logic_cc)
473 gen_op_logic_T1_cc();
474 break;
475 case 0x0e:
476 gen_op_bicl_T0_T1();
477 gen_movl_reg_T0(s, rd);
478 if (logic_cc)
479 gen_op_logic_T0_cc();
480 break;
481 default:
482 case 0x0f:
483 gen_op_notl_T1();
484 gen_movl_reg_T1(s, rd);
485 if (logic_cc)
486 gen_op_logic_T1_cc();
487 break;
489 } else {
490 /* other instructions */
491 op1 = (insn >> 24) & 0xf;
492 switch(op1) {
493 case 0x0:
494 case 0x1:
495 sh = (insn >> 5) & 3;
496 if (sh == 0) {
497 if (op1 == 0x0) {
498 rd = (insn >> 16) & 0xf;
499 rn = (insn >> 12) & 0xf;
500 rs = (insn >> 8) & 0xf;
501 rm = (insn) & 0xf;
502 if (!(insn & (1 << 23))) {
503 /* 32 bit mul */
504 gen_movl_T0_reg(s, rs);
505 gen_movl_T1_reg(s, rm);
506 gen_op_mul_T0_T1();
507 if (insn & (1 << 21)) {
508 gen_movl_T1_reg(s, rn);
509 gen_op_addl_T0_T1();
511 if (insn & (1 << 20))
512 gen_op_logic_T0_cc();
513 gen_movl_reg_T0(s, rd);
514 } else {
515 /* 64 bit mul */
516 gen_movl_T0_reg(s, rs);
517 gen_movl_T1_reg(s, rm);
518 if (insn & (1 << 22))
519 gen_op_mull_T0_T1();
520 else
521 gen_op_imull_T0_T1();
522 if (insn & (1 << 21))
523 gen_op_addq_T0_T1(rn, rd);
524 if (insn & (1 << 20))
525 gen_op_logicq_cc();
526 gen_movl_reg_T0(s, rn);
527 gen_movl_reg_T1(s, rd);
529 } else {
530 /* SWP instruction */
531 rn = (insn >> 16) & 0xf;
532 rd = (insn >> 12) & 0xf;
533 rm = (insn) & 0xf;
535 gen_movl_T0_reg(s, rm);
536 gen_movl_T1_reg(s, rn);
537 if (insn & (1 << 22)) {
538 gen_op_swpb_T0_T1();
539 } else {
540 gen_op_swpl_T0_T1();
542 gen_movl_reg_T0(s, rd);
544 } else {
545 /* load/store half word */
546 rn = (insn >> 16) & 0xf;
547 rd = (insn >> 12) & 0xf;
548 gen_movl_T1_reg(s, rn);
549 gen_add_datah_offset(s, insn);
550 if (insn & (1 << 20)) {
551 /* load */
552 switch(sh) {
553 case 1:
554 gen_op_lduw_T0_T1();
555 break;
556 case 2:
557 gen_op_ldsb_T0_T1();
558 break;
559 default:
560 case 3:
561 gen_op_ldsw_T0_T1();
562 break;
564 gen_movl_reg_T0(s, rd);
565 } else {
566 /* store */
567 gen_movl_T0_reg(s, rd);
568 gen_op_stw_T0_T1();
570 if (!(insn & (1 << 24))) {
571 gen_add_datah_offset(s, insn);
572 gen_movl_reg_T1(s, rn);
573 } else if (insn & (1 << 21)) {
574 gen_movl_reg_T1(s, rn);
577 break;
578 case 0x4:
579 case 0x5:
580 case 0x6:
581 case 0x7:
582 /* load/store byte/word */
583 rn = (insn >> 16) & 0xf;
584 rd = (insn >> 12) & 0xf;
585 gen_movl_T1_reg(s, rn);
586 if (insn & (1 << 24))
587 gen_add_data_offset(s, insn);
588 if (insn & (1 << 20)) {
589 /* load */
590 if (insn & (1 << 22))
591 gen_op_ldub_T0_T1();
592 else
593 gen_op_ldl_T0_T1();
594 gen_movl_reg_T0(s, rd);
595 } else {
596 /* store */
597 gen_movl_T0_reg(s, rd);
598 if (insn & (1 << 22))
599 gen_op_stb_T0_T1();
600 else
601 gen_op_stl_T0_T1();
603 if (!(insn & (1 << 24))) {
604 gen_add_data_offset(s, insn);
605 gen_movl_reg_T1(s, rn);
606 } else if (insn & (1 << 21))
607 gen_movl_reg_T1(s, rn); {
609 break;
610 case 0x08:
611 case 0x09:
613 int j, n;
614 /* load/store multiple words */
615 /* XXX: store correct base if write back */
616 if (insn & (1 << 22))
617 goto illegal_op; /* only usable in supervisor mode */
618 rn = (insn >> 16) & 0xf;
619 gen_movl_T1_reg(s, rn);
621 /* compute total size */
622 n = 0;
623 for(i=0;i<16;i++) {
624 if (insn & (1 << i))
625 n++;
627 /* XXX: test invalid n == 0 case ? */
628 if (insn & (1 << 23)) {
629 if (insn & (1 << 24)) {
630 /* pre increment */
631 gen_op_addl_T1_im(4);
632 } else {
633 /* post increment */
635 } else {
636 if (insn & (1 << 24)) {
637 /* pre decrement */
638 gen_op_addl_T1_im(-(n * 4));
639 } else {
640 /* post decrement */
641 if (n != 1)
642 gen_op_addl_T1_im(-((n - 1) * 4));
645 j = 0;
646 for(i=0;i<16;i++) {
647 if (insn & (1 << i)) {
648 if (insn & (1 << 20)) {
649 /* load */
650 gen_op_ldl_T0_T1();
651 gen_movl_reg_T0(s, i);
652 } else {
653 /* store */
654 if (i == 15) {
655 /* special case: r15 = PC + 12 */
656 val = (long)s->pc + 8;
657 gen_op_movl_TN_im[0](val);
658 } else {
659 gen_movl_T0_reg(s, i);
661 gen_op_stl_T0_T1();
663 j++;
664 /* no need to add after the last transfer */
665 if (j != n)
666 gen_op_addl_T1_im(4);
669 if (insn & (1 << 21)) {
670 /* write back */
671 if (insn & (1 << 23)) {
672 if (insn & (1 << 24)) {
673 /* pre increment */
674 } else {
675 /* post increment */
676 gen_op_addl_T1_im(4);
678 } else {
679 if (insn & (1 << 24)) {
680 /* pre decrement */
681 if (n != 1)
682 gen_op_addl_T1_im(-((n - 1) * 4));
683 } else {
684 /* post decrement */
685 gen_op_addl_T1_im(-(n * 4));
688 gen_movl_reg_T1(s, rn);
691 break;
692 case 0xa:
693 case 0xb:
695 int offset;
697 /* branch (and link) */
698 val = (int)s->pc;
699 if (insn & (1 << 24)) {
700 gen_op_movl_T0_im(val);
701 gen_op_movl_reg_TN[0][14]();
703 offset = (((int)insn << 8) >> 8);
704 val += (offset << 2) + 4;
705 gen_op_jmp((long)s->tb, val);
706 s->is_jmp = DISAS_TB_JUMP;
708 break;
709 case 0xf:
710 /* swi */
711 gen_op_movl_T0_im((long)s->pc);
712 gen_op_movl_reg_TN[0][15]();
713 gen_op_swi();
714 s->is_jmp = DISAS_JUMP;
715 break;
716 case 0xc:
717 case 0xd:
718 rd = (insn >> 12) & 0x7;
719 rn = (insn >> 16) & 0xf;
720 gen_movl_T1_reg(s, rn);
721 val = (insn) & 0xff;
722 if (!(insn & (1 << 23)))
723 val = -val;
724 switch((insn >> 8) & 0xf) {
725 case 0x1:
726 /* load/store */
727 if ((insn & (1 << 24)))
728 gen_op_addl_T1_im(val);
729 /* XXX: do it */
730 if (!(insn & (1 << 24)))
731 gen_op_addl_T1_im(val);
732 if (insn & (1 << 21))
733 gen_movl_reg_T1(s, rn);
734 break;
735 case 0x2:
737 int n, i;
738 /* load store multiple */
739 if ((insn & (1 << 24)))
740 gen_op_addl_T1_im(val);
741 switch(insn & 0x00408000) {
742 case 0x00008000: n = 1; break;
743 case 0x00400000: n = 2; break;
744 case 0x00408000: n = 3; break;
745 default: n = 4; break;
747 for(i = 0;i < n; i++) {
748 /* XXX: do it */
750 if (!(insn & (1 << 24)))
751 gen_op_addl_T1_im(val);
752 if (insn & (1 << 21))
753 gen_movl_reg_T1(s, rn);
755 break;
756 default:
757 goto illegal_op;
759 break;
760 case 0x0e:
761 /* float ops */
762 /* XXX: do it */
763 switch((insn >> 20) & 0xf) {
764 case 0x2: /* wfs */
765 break;
766 case 0x3: /* rfs */
767 break;
768 case 0x4: /* wfc */
769 break;
770 case 0x5: /* rfc */
771 break;
772 default:
773 goto illegal_op;
775 break;
776 default:
777 illegal_op:
778 gen_op_movl_T0_im((long)s->pc - 4);
779 gen_op_movl_reg_TN[0][15]();
780 gen_op_undef_insn();
781 s->is_jmp = DISAS_JUMP;
782 break;
787 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
788 basic block 'tb'. If search_pc is TRUE, also generate PC
789 information for each intermediate instruction. */
790 static inline int gen_intermediate_code_internal(CPUState *env,
791 TranslationBlock *tb,
792 int search_pc)
794 DisasContext dc1, *dc = &dc1;
795 uint16_t *gen_opc_end;
796 int j, lj;
797 uint8_t *pc_start;
799 /* generate intermediate code */
800 pc_start = (uint8_t *)tb->pc;
802 dc->tb = tb;
804 gen_opc_ptr = gen_opc_buf;
805 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
806 gen_opparam_ptr = gen_opparam_buf;
808 dc->is_jmp = DISAS_NEXT;
809 dc->pc = pc_start;
810 lj = -1;
811 do {
812 if (search_pc) {
813 j = gen_opc_ptr - gen_opc_buf;
814 if (lj < j) {
815 lj++;
816 while (lj < j)
817 gen_opc_instr_start[lj++] = 0;
819 gen_opc_pc[lj] = (uint32_t)dc->pc;
820 gen_opc_instr_start[lj] = 1;
822 disas_arm_insn(dc);
823 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
824 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
825 switch(dc->is_jmp) {
826 case DISAS_JUMP_NEXT:
827 case DISAS_NEXT:
828 gen_op_jmp((long)dc->tb, (long)dc->pc);
829 break;
830 default:
831 case DISAS_JUMP:
832 /* indicate that the hash table must be used to find the next TB */
833 gen_op_movl_T0_0();
834 gen_op_exit_tb();
835 break;
836 case DISAS_TB_JUMP:
837 /* nothing more to generate */
838 break;
840 *gen_opc_ptr = INDEX_op_end;
842 #ifdef DEBUG_DISAS
843 if (loglevel) {
844 fprintf(logfile, "----------------\n");
845 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
846 disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
847 fprintf(logfile, "\n");
849 fprintf(logfile, "OP:\n");
850 dump_ops(gen_opc_buf, gen_opparam_buf);
851 fprintf(logfile, "\n");
853 #endif
854 if (!search_pc)
855 tb->size = dc->pc - pc_start;
856 return 0;
859 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
861 return gen_intermediate_code_internal(env, tb, 0);
864 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
866 return gen_intermediate_code_internal(env, tb, 1);
869 CPUARMState *cpu_arm_init(void)
871 CPUARMState *env;
873 cpu_exec_init();
875 env = malloc(sizeof(CPUARMState));
876 if (!env)
877 return NULL;
878 memset(env, 0, sizeof(CPUARMState));
879 return env;
882 void cpu_arm_close(CPUARMState *env)
884 free(env);
887 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
889 int i;
891 for(i=0;i<16;i++) {
892 fprintf(f, "R%02d=%08x", i, env->regs[i]);
893 if ((i % 4) == 3)
894 fprintf(f, "\n");
895 else
896 fprintf(f, " ");
898 fprintf(f, "PSR=%08x %c%c%c%c\n",
899 env->cpsr,
900 env->cpsr & (1 << 31) ? 'N' : '-',
901 env->cpsr & (1 << 30) ? 'Z' : '-',
902 env->cpsr & (1 << 29) ? 'C' : '-',
903 env->cpsr & (1 << 28) ? 'V' : '-');