]> git.proxmox.com Git - mirror_qemu.git/blob - target-arm/translate.c
added cpu_get_phys_page_debug()
[mirror_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 gen_op_addl_T1_im(val);
283 } else {
284 /* shift/register */
285 rm = (insn) & 0xf;
286 shift = (insn >> 7) & 0x1f;
287 gen_movl_T2_reg(s, rm);
288 if (shift != 0) {
289 gen_shift_T2_im[(insn >> 5) & 3](shift);
290 }
291 if (!(insn & (1 << 23)))
292 gen_op_subl_T1_T2();
293 else
294 gen_op_addl_T1_T2();
295 }
296 }
297
298 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
299 {
300 int val, rm;
301
302 if (insn & (1 << 22)) {
303 /* immediate */
304 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
305 if (!(insn & (1 << 23)))
306 val = -val;
307 gen_op_addl_T1_im(val);
308 } else {
309 /* register */
310 rm = (insn) & 0xf;
311 gen_movl_T2_reg(s, rm);
312 if (!(insn & (1 << 23)))
313 gen_op_subl_T1_T2();
314 else
315 gen_op_addl_T1_T2();
316 }
317 }
318
319 static void disas_arm_insn(DisasContext *s)
320 {
321 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
322
323 insn = ldl(s->pc);
324 s->pc += 4;
325
326 cond = insn >> 28;
327 if (cond == 0xf)
328 goto illegal_op;
329 if (cond != 0xe) {
330 /* if not always execute, we generate a conditional jump to
331 next instruction */
332 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
333 s->is_jmp = DISAS_JUMP_NEXT;
334 }
335 if (((insn & 0x0e000000) == 0 &&
336 (insn & 0x00000090) != 0x90) ||
337 ((insn & 0x0e000000) == (1 << 25))) {
338 int set_cc, logic_cc, shiftop;
339
340 op1 = (insn >> 21) & 0xf;
341 set_cc = (insn >> 20) & 1;
342 logic_cc = table_logic_cc[op1] & set_cc;
343
344 /* data processing instruction */
345 if (insn & (1 << 25)) {
346 /* immediate operand */
347 val = insn & 0xff;
348 shift = ((insn >> 8) & 0xf) * 2;
349 if (shift)
350 val = (val >> shift) | (val << (32 - shift));
351 gen_op_movl_T1_im(val);
352 /* XXX: is CF modified ? */
353 } else {
354 /* register */
355 rm = (insn) & 0xf;
356 gen_movl_T1_reg(s, rm);
357 shiftop = (insn >> 5) & 3;
358 if (!(insn & (1 << 4))) {
359 shift = (insn >> 7) & 0x1f;
360 if (shift != 0) {
361 if (logic_cc) {
362 gen_shift_T1_im_cc[shiftop](shift);
363 } else {
364 gen_shift_T1_im[shiftop](shift);
365 }
366 }
367 } else {
368 rs = (insn >> 8) & 0xf;
369 gen_movl_T0_reg(s, rs);
370 if (logic_cc) {
371 gen_shift_T1_T0_cc[shiftop]();
372 } else {
373 gen_shift_T1_T0[shiftop]();
374 }
375 }
376 }
377 if (op1 != 0x0f && op1 != 0x0d) {
378 rn = (insn >> 16) & 0xf;
379 gen_movl_T0_reg(s, rn);
380 }
381 rd = (insn >> 12) & 0xf;
382 switch(op1) {
383 case 0x00:
384 gen_op_andl_T0_T1();
385 gen_movl_reg_T0(s, rd);
386 if (logic_cc)
387 gen_op_logic_T0_cc();
388 break;
389 case 0x01:
390 gen_op_xorl_T0_T1();
391 gen_movl_reg_T0(s, rd);
392 if (logic_cc)
393 gen_op_logic_T0_cc();
394 break;
395 case 0x02:
396 if (set_cc)
397 gen_op_subl_T0_T1_cc();
398 else
399 gen_op_subl_T0_T1();
400 gen_movl_reg_T0(s, rd);
401 break;
402 case 0x03:
403 if (set_cc)
404 gen_op_rsbl_T0_T1_cc();
405 else
406 gen_op_rsbl_T0_T1();
407 gen_movl_reg_T0(s, rd);
408 break;
409 case 0x04:
410 if (set_cc)
411 gen_op_addl_T0_T1_cc();
412 else
413 gen_op_addl_T0_T1();
414 gen_movl_reg_T0(s, rd);
415 break;
416 case 0x05:
417 if (set_cc)
418 gen_op_adcl_T0_T1_cc();
419 else
420 gen_op_adcl_T0_T1();
421 gen_movl_reg_T0(s, rd);
422 break;
423 case 0x06:
424 if (set_cc)
425 gen_op_sbcl_T0_T1_cc();
426 else
427 gen_op_sbcl_T0_T1();
428 gen_movl_reg_T0(s, rd);
429 break;
430 case 0x07:
431 if (set_cc)
432 gen_op_rscl_T0_T1_cc();
433 else
434 gen_op_rscl_T0_T1();
435 gen_movl_reg_T0(s, rd);
436 break;
437 case 0x08:
438 if (set_cc) {
439 gen_op_andl_T0_T1();
440 gen_op_logic_T0_cc();
441 }
442 break;
443 case 0x09:
444 if (set_cc) {
445 gen_op_xorl_T0_T1();
446 gen_op_logic_T0_cc();
447 }
448 break;
449 case 0x0a:
450 if (set_cc) {
451 gen_op_subl_T0_T1_cc();
452 }
453 break;
454 case 0x0b:
455 if (set_cc) {
456 gen_op_addl_T0_T1_cc();
457 }
458 break;
459 case 0x0c:
460 gen_op_orl_T0_T1();
461 gen_movl_reg_T0(s, rd);
462 if (logic_cc)
463 gen_op_logic_T0_cc();
464 break;
465 case 0x0d:
466 gen_movl_reg_T1(s, rd);
467 if (logic_cc)
468 gen_op_logic_T1_cc();
469 break;
470 case 0x0e:
471 gen_op_bicl_T0_T1();
472 gen_movl_reg_T0(s, rd);
473 if (logic_cc)
474 gen_op_logic_T0_cc();
475 break;
476 default:
477 case 0x0f:
478 gen_op_notl_T1();
479 gen_movl_reg_T1(s, rd);
480 if (logic_cc)
481 gen_op_logic_T1_cc();
482 break;
483 }
484 } else {
485 /* other instructions */
486 op1 = (insn >> 24) & 0xf;
487 switch(op1) {
488 case 0x0:
489 case 0x1:
490 sh = (insn >> 5) & 3;
491 if (sh == 0) {
492 if (op1 == 0x0) {
493 rd = (insn >> 16) & 0xf;
494 rn = (insn >> 12) & 0xf;
495 rs = (insn >> 8) & 0xf;
496 rm = (insn) & 0xf;
497 if (!(insn & (1 << 23))) {
498 /* 32 bit mul */
499 gen_movl_T0_reg(s, rs);
500 gen_movl_T1_reg(s, rm);
501 gen_op_mul_T0_T1();
502 if (insn & (1 << 21)) {
503 gen_movl_T1_reg(s, rn);
504 gen_op_addl_T0_T1();
505 }
506 if (insn & (1 << 20))
507 gen_op_logic_T0_cc();
508 gen_movl_reg_T0(s, rd);
509 } else {
510 /* 64 bit mul */
511 gen_movl_T0_reg(s, rs);
512 gen_movl_T1_reg(s, rm);
513 if (insn & (1 << 22))
514 gen_op_imull_T0_T1();
515 else
516 gen_op_mull_T0_T1();
517 if (insn & (1 << 21))
518 gen_op_addq_T0_T1(rn, rd);
519 if (insn & (1 << 20))
520 gen_op_logicq_cc();
521 gen_movl_reg_T0(s, rn);
522 gen_movl_reg_T1(s, rd);
523 }
524 } else {
525 /* SWP instruction */
526 rn = (insn >> 16) & 0xf;
527 rd = (insn >> 12) & 0xf;
528 rm = (insn) & 0xf;
529
530 gen_movl_T0_reg(s, rm);
531 gen_movl_T1_reg(s, rn);
532 if (insn & (1 << 22)) {
533 gen_op_swpb_T0_T1();
534 } else {
535 gen_op_swpl_T0_T1();
536 }
537 gen_movl_reg_T0(s, rd);
538 }
539 } else {
540 /* load/store half word */
541 rn = (insn >> 16) & 0xf;
542 rd = (insn >> 12) & 0xf;
543 gen_movl_T1_reg(s, rn);
544 gen_add_datah_offset(s, insn);
545 if (insn & (1 << 20)) {
546 /* load */
547 switch(sh) {
548 case 1:
549 gen_op_lduw_T0_T1();
550 break;
551 case 2:
552 gen_op_ldsb_T0_T1();
553 break;
554 default:
555 case 3:
556 gen_op_ldsw_T0_T1();
557 break;
558 }
559 gen_movl_reg_T0(s, rd);
560 } else {
561 /* store */
562 gen_movl_T0_reg(s, rd);
563 gen_op_stw_T0_T1();
564 }
565 if (!(insn & (1 << 24))) {
566 gen_add_datah_offset(s, insn);
567 gen_movl_reg_T1(s, rn);
568 } else if (insn & (1 << 21)) {
569 gen_movl_reg_T1(s, rn);
570 }
571 }
572 break;
573 case 0x4:
574 case 0x5:
575 case 0x6:
576 case 0x7:
577 /* load/store byte/word */
578 rn = (insn >> 16) & 0xf;
579 rd = (insn >> 12) & 0xf;
580 gen_movl_T1_reg(s, rn);
581 if (insn & (1 << 24))
582 gen_add_data_offset(s, insn);
583 if (insn & (1 << 20)) {
584 /* load */
585 if (insn & (1 << 22))
586 gen_op_ldub_T0_T1();
587 else
588 gen_op_ldl_T0_T1();
589 gen_movl_reg_T0(s, rd);
590 } else {
591 /* store */
592 gen_movl_T0_reg(s, rd);
593 if (insn & (1 << 22))
594 gen_op_stb_T0_T1();
595 else
596 gen_op_stl_T0_T1();
597 }
598 if (!(insn & (1 << 24))) {
599 gen_add_data_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 break;
605 case 0x08:
606 case 0x09:
607 {
608 int j, n;
609 /* load/store multiple words */
610 /* XXX: store correct base if write back */
611 if (insn & (1 << 22))
612 goto illegal_op; /* only usable in supervisor mode */
613 rn = (insn >> 16) & 0xf;
614 gen_movl_T1_reg(s, rn);
615
616 /* compute total size */
617 n = 0;
618 for(i=0;i<16;i++) {
619 if (insn & (1 << i))
620 n++;
621 }
622 /* XXX: test invalid n == 0 case ? */
623 if (insn & (1 << 23)) {
624 if (insn & (1 << 24)) {
625 /* pre increment */
626 gen_op_addl_T1_im(4);
627 } else {
628 /* post increment */
629 }
630 } else {
631 if (insn & (1 << 24)) {
632 /* pre decrement */
633 gen_op_addl_T1_im(-(n * 4));
634 } else {
635 /* post decrement */
636 if (n != 1)
637 gen_op_addl_T1_im(-((n - 1) * 4));
638 }
639 }
640 j = 0;
641 for(i=0;i<16;i++) {
642 if (insn & (1 << i)) {
643 if (insn & (1 << 20)) {
644 /* load */
645 gen_op_ldl_T0_T1();
646 gen_movl_reg_T0(s, i);
647 } else {
648 /* store */
649 if (i == 15) {
650 /* special case: r15 = PC + 12 */
651 val = (long)s->pc + 8;
652 gen_op_movl_TN_im[0](val);
653 } else {
654 gen_movl_T0_reg(s, i);
655 }
656 gen_op_stl_T0_T1();
657 }
658 j++;
659 /* no need to add after the last transfer */
660 if (j != n)
661 gen_op_addl_T1_im(4);
662 }
663 }
664 if (insn & (1 << 21)) {
665 /* write back */
666 if (insn & (1 << 23)) {
667 if (insn & (1 << 24)) {
668 /* pre increment */
669 } else {
670 /* post increment */
671 gen_op_addl_T1_im(4);
672 }
673 } else {
674 if (insn & (1 << 24)) {
675 /* pre decrement */
676 if (n != 1)
677 gen_op_addl_T1_im(-((n - 1) * 4));
678 } else {
679 /* post decrement */
680 gen_op_addl_T1_im(-(n * 4));
681 }
682 }
683 gen_movl_reg_T1(s, rn);
684 }
685 }
686 break;
687 case 0xa:
688 case 0xb:
689 {
690 int offset;
691
692 /* branch (and link) */
693 val = (int)s->pc;
694 if (insn & (1 << 24)) {
695 gen_op_movl_T0_im(val);
696 gen_op_movl_reg_TN[0][14]();
697 }
698 offset = (((int)insn << 8) >> 8);
699 val += (offset << 2) + 4;
700 gen_op_jmp((long)s->tb, val);
701 s->is_jmp = DISAS_TB_JUMP;
702 }
703 break;
704 case 0xf:
705 /* swi */
706 gen_op_movl_T0_im((long)s->pc);
707 gen_op_movl_reg_TN[0][15]();
708 gen_op_swi();
709 s->is_jmp = DISAS_JUMP;
710 break;
711 case 0xc:
712 case 0xd:
713 rd = (insn >> 12) & 0x7;
714 rn = (insn >> 16) & 0xf;
715 gen_movl_T1_reg(s, rn);
716 val = (insn) & 0xff;
717 if (!(insn & (1 << 23)))
718 val = -val;
719 switch((insn >> 8) & 0xf) {
720 case 0x1:
721 /* load/store */
722 if ((insn & (1 << 24)))
723 gen_op_addl_T1_im(val);
724 /* XXX: do it */
725 if (!(insn & (1 << 24)))
726 gen_op_addl_T1_im(val);
727 if (insn & (1 << 21))
728 gen_movl_reg_T1(s, rn);
729 break;
730 case 0x2:
731 {
732 int n, i;
733 /* load store multiple */
734 if ((insn & (1 << 24)))
735 gen_op_addl_T1_im(val);
736 switch(insn & 0x00408000) {
737 case 0x00008000: n = 1; break;
738 case 0x00400000: n = 2; break;
739 case 0x00408000: n = 3; break;
740 default: n = 4; break;
741 }
742 for(i = 0;i < n; i++) {
743 /* XXX: do it */
744 }
745 if (!(insn & (1 << 24)))
746 gen_op_addl_T1_im(val);
747 if (insn & (1 << 21))
748 gen_movl_reg_T1(s, rn);
749 }
750 break;
751 default:
752 goto illegal_op;
753 }
754 break;
755 case 0x0e:
756 /* float ops */
757 /* XXX: do it */
758 switch((insn >> 20) & 0xf) {
759 case 0x2: /* wfs */
760 break;
761 case 0x3: /* rfs */
762 break;
763 case 0x4: /* wfc */
764 break;
765 case 0x5: /* rfc */
766 break;
767 default:
768 goto illegal_op;
769 }
770 break;
771 default:
772 illegal_op:
773 gen_op_movl_T0_im((long)s->pc - 4);
774 gen_op_movl_reg_TN[0][15]();
775 gen_op_undef_insn();
776 s->is_jmp = DISAS_JUMP;
777 break;
778 }
779 }
780 }
781
782 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
783 basic block 'tb'. If search_pc is TRUE, also generate PC
784 information for each intermediate instruction. */
785 static inline int gen_intermediate_code_internal(CPUState *env,
786 TranslationBlock *tb,
787 int search_pc)
788 {
789 DisasContext dc1, *dc = &dc1;
790 uint16_t *gen_opc_end;
791 int j, lj;
792 uint8_t *pc_start;
793
794 /* generate intermediate code */
795 pc_start = (uint8_t *)tb->pc;
796
797 dc->tb = tb;
798
799 gen_opc_ptr = gen_opc_buf;
800 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
801 gen_opparam_ptr = gen_opparam_buf;
802
803 dc->is_jmp = DISAS_NEXT;
804 dc->pc = pc_start;
805 lj = -1;
806 do {
807 if (search_pc) {
808 j = gen_opc_ptr - gen_opc_buf;
809 if (lj < j) {
810 lj++;
811 while (lj < j)
812 gen_opc_instr_start[lj++] = 0;
813 }
814 gen_opc_pc[lj] = (uint32_t)dc->pc;
815 gen_opc_instr_start[lj] = 1;
816 }
817 disas_arm_insn(dc);
818 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
819 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
820 switch(dc->is_jmp) {
821 case DISAS_JUMP_NEXT:
822 case DISAS_NEXT:
823 gen_op_jmp((long)dc->tb, (long)dc->pc);
824 break;
825 default:
826 case DISAS_JUMP:
827 /* indicate that the hash table must be used to find the next TB */
828 gen_op_movl_T0_0();
829 gen_op_exit_tb();
830 break;
831 case DISAS_TB_JUMP:
832 /* nothing more to generate */
833 break;
834 }
835 *gen_opc_ptr = INDEX_op_end;
836
837 #ifdef DEBUG_DISAS
838 if (loglevel) {
839 fprintf(logfile, "----------------\n");
840 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
841 disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
842 fprintf(logfile, "\n");
843
844 fprintf(logfile, "OP:\n");
845 dump_ops(gen_opc_buf, gen_opparam_buf);
846 fprintf(logfile, "\n");
847 }
848 #endif
849 if (!search_pc)
850 tb->size = dc->pc - pc_start;
851 return 0;
852 }
853
854 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
855 {
856 return gen_intermediate_code_internal(env, tb, 0);
857 }
858
859 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
860 {
861 return gen_intermediate_code_internal(env, tb, 1);
862 }
863
864 CPUARMState *cpu_arm_init(void)
865 {
866 CPUARMState *env;
867
868 cpu_exec_init();
869
870 env = malloc(sizeof(CPUARMState));
871 if (!env)
872 return NULL;
873 memset(env, 0, sizeof(CPUARMState));
874 return env;
875 }
876
877 void cpu_arm_close(CPUARMState *env)
878 {
879 free(env);
880 }
881
882 void cpu_arm_dump_state(CPUARMState *env, FILE *f, int flags)
883 {
884 int i;
885
886 for(i=0;i<16;i++) {
887 fprintf(f, "R%02d=%08x", i, env->regs[i]);
888 if ((i % 4) == 3)
889 fprintf(f, "\n");
890 else
891 fprintf(f, " ");
892 }
893 fprintf(f, "PSR=%08x %c%c%c%c\n",
894 env->cpsr,
895 env->cpsr & (1 << 31) ? 'N' : '-',
896 env->cpsr & (1 << 30) ? 'Z' : '-',
897 env->cpsr & (1 << 29) ? 'C' : '-',
898 env->cpsr & (1 << 28) ? 'V' : '-');
899 }
900
901 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
902 {
903 return addr;
904 }