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