]> git.proxmox.com Git - mirror_qemu.git/blob - target-arm/translate.c
ARM shift fix (Paul Brook)
[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 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 } else if (shiftop == 3) {
369 if (logic_cc)
370 gen_op_rrxl_T1_cc();
371 else
372 gen_op_rrxl_T1();
373 }
374 } else {
375 rs = (insn >> 8) & 0xf;
376 gen_movl_T0_reg(s, rs);
377 if (logic_cc) {
378 gen_shift_T1_T0_cc[shiftop]();
379 } else {
380 gen_shift_T1_T0[shiftop]();
381 }
382 }
383 }
384 if (op1 != 0x0f && op1 != 0x0d) {
385 rn = (insn >> 16) & 0xf;
386 gen_movl_T0_reg(s, rn);
387 }
388 rd = (insn >> 12) & 0xf;
389 switch(op1) {
390 case 0x00:
391 gen_op_andl_T0_T1();
392 gen_movl_reg_T0(s, rd);
393 if (logic_cc)
394 gen_op_logic_T0_cc();
395 break;
396 case 0x01:
397 gen_op_xorl_T0_T1();
398 gen_movl_reg_T0(s, rd);
399 if (logic_cc)
400 gen_op_logic_T0_cc();
401 break;
402 case 0x02:
403 if (set_cc)
404 gen_op_subl_T0_T1_cc();
405 else
406 gen_op_subl_T0_T1();
407 gen_movl_reg_T0(s, rd);
408 break;
409 case 0x03:
410 if (set_cc)
411 gen_op_rsbl_T0_T1_cc();
412 else
413 gen_op_rsbl_T0_T1();
414 gen_movl_reg_T0(s, rd);
415 break;
416 case 0x04:
417 if (set_cc)
418 gen_op_addl_T0_T1_cc();
419 else
420 gen_op_addl_T0_T1();
421 gen_movl_reg_T0(s, rd);
422 break;
423 case 0x05:
424 if (set_cc)
425 gen_op_adcl_T0_T1_cc();
426 else
427 gen_op_adcl_T0_T1();
428 gen_movl_reg_T0(s, rd);
429 break;
430 case 0x06:
431 if (set_cc)
432 gen_op_sbcl_T0_T1_cc();
433 else
434 gen_op_sbcl_T0_T1();
435 gen_movl_reg_T0(s, rd);
436 break;
437 case 0x07:
438 if (set_cc)
439 gen_op_rscl_T0_T1_cc();
440 else
441 gen_op_rscl_T0_T1();
442 gen_movl_reg_T0(s, rd);
443 break;
444 case 0x08:
445 if (set_cc) {
446 gen_op_andl_T0_T1();
447 gen_op_logic_T0_cc();
448 }
449 break;
450 case 0x09:
451 if (set_cc) {
452 gen_op_xorl_T0_T1();
453 gen_op_logic_T0_cc();
454 }
455 break;
456 case 0x0a:
457 if (set_cc) {
458 gen_op_subl_T0_T1_cc();
459 }
460 break;
461 case 0x0b:
462 if (set_cc) {
463 gen_op_addl_T0_T1_cc();
464 }
465 break;
466 case 0x0c:
467 gen_op_orl_T0_T1();
468 gen_movl_reg_T0(s, rd);
469 if (logic_cc)
470 gen_op_logic_T0_cc();
471 break;
472 case 0x0d:
473 gen_movl_reg_T1(s, rd);
474 if (logic_cc)
475 gen_op_logic_T1_cc();
476 break;
477 case 0x0e:
478 gen_op_bicl_T0_T1();
479 gen_movl_reg_T0(s, rd);
480 if (logic_cc)
481 gen_op_logic_T0_cc();
482 break;
483 default:
484 case 0x0f:
485 gen_op_notl_T1();
486 gen_movl_reg_T1(s, rd);
487 if (logic_cc)
488 gen_op_logic_T1_cc();
489 break;
490 }
491 } else {
492 /* other instructions */
493 op1 = (insn >> 24) & 0xf;
494 switch(op1) {
495 case 0x0:
496 case 0x1:
497 sh = (insn >> 5) & 3;
498 if (sh == 0) {
499 if (op1 == 0x0) {
500 rd = (insn >> 16) & 0xf;
501 rn = (insn >> 12) & 0xf;
502 rs = (insn >> 8) & 0xf;
503 rm = (insn) & 0xf;
504 if (!(insn & (1 << 23))) {
505 /* 32 bit mul */
506 gen_movl_T0_reg(s, rs);
507 gen_movl_T1_reg(s, rm);
508 gen_op_mul_T0_T1();
509 if (insn & (1 << 21)) {
510 gen_movl_T1_reg(s, rn);
511 gen_op_addl_T0_T1();
512 }
513 if (insn & (1 << 20))
514 gen_op_logic_T0_cc();
515 gen_movl_reg_T0(s, rd);
516 } else {
517 /* 64 bit mul */
518 gen_movl_T0_reg(s, rs);
519 gen_movl_T1_reg(s, rm);
520 if (insn & (1 << 22))
521 gen_op_imull_T0_T1();
522 else
523 gen_op_mull_T0_T1();
524 if (insn & (1 << 21))
525 gen_op_addq_T0_T1(rn, rd);
526 if (insn & (1 << 20))
527 gen_op_logicq_cc();
528 gen_movl_reg_T0(s, rn);
529 gen_movl_reg_T1(s, rd);
530 }
531 } else {
532 /* SWP instruction */
533 rn = (insn >> 16) & 0xf;
534 rd = (insn >> 12) & 0xf;
535 rm = (insn) & 0xf;
536
537 gen_movl_T0_reg(s, rm);
538 gen_movl_T1_reg(s, rn);
539 if (insn & (1 << 22)) {
540 gen_op_swpb_T0_T1();
541 } else {
542 gen_op_swpl_T0_T1();
543 }
544 gen_movl_reg_T0(s, rd);
545 }
546 } else {
547 /* load/store half word */
548 rn = (insn >> 16) & 0xf;
549 rd = (insn >> 12) & 0xf;
550 gen_movl_T1_reg(s, rn);
551 if (insn & (1 << 24))
552 gen_add_datah_offset(s, insn);
553 if (insn & (1 << 20)) {
554 /* load */
555 switch(sh) {
556 case 1:
557 gen_op_lduw_T0_T1();
558 break;
559 case 2:
560 gen_op_ldsb_T0_T1();
561 break;
562 default:
563 case 3:
564 gen_op_ldsw_T0_T1();
565 break;
566 }
567 gen_movl_reg_T0(s, rd);
568 } else {
569 /* store */
570 gen_movl_T0_reg(s, rd);
571 gen_op_stw_T0_T1();
572 }
573 if (!(insn & (1 << 24))) {
574 gen_add_datah_offset(s, insn);
575 gen_movl_reg_T1(s, rn);
576 } else if (insn & (1 << 21)) {
577 gen_movl_reg_T1(s, rn);
578 }
579 }
580 break;
581 case 0x4:
582 case 0x5:
583 case 0x6:
584 case 0x7:
585 /* load/store byte/word */
586 rn = (insn >> 16) & 0xf;
587 rd = (insn >> 12) & 0xf;
588 gen_movl_T1_reg(s, rn);
589 if (insn & (1 << 24))
590 gen_add_data_offset(s, insn);
591 if (insn & (1 << 20)) {
592 /* load */
593 if (insn & (1 << 22))
594 gen_op_ldub_T0_T1();
595 else
596 gen_op_ldl_T0_T1();
597 gen_movl_reg_T0(s, rd);
598 } else {
599 /* store */
600 gen_movl_T0_reg(s, rd);
601 if (insn & (1 << 22))
602 gen_op_stb_T0_T1();
603 else
604 gen_op_stl_T0_T1();
605 }
606 if (!(insn & (1 << 24))) {
607 gen_add_data_offset(s, insn);
608 gen_movl_reg_T1(s, rn);
609 } else if (insn & (1 << 21))
610 gen_movl_reg_T1(s, rn); {
611 }
612 break;
613 case 0x08:
614 case 0x09:
615 {
616 int j, n;
617 /* load/store multiple words */
618 /* XXX: store correct base if write back */
619 if (insn & (1 << 22))
620 goto illegal_op; /* only usable in supervisor mode */
621 rn = (insn >> 16) & 0xf;
622 gen_movl_T1_reg(s, rn);
623
624 /* compute total size */
625 n = 0;
626 for(i=0;i<16;i++) {
627 if (insn & (1 << i))
628 n++;
629 }
630 /* XXX: test invalid n == 0 case ? */
631 if (insn & (1 << 23)) {
632 if (insn & (1 << 24)) {
633 /* pre increment */
634 gen_op_addl_T1_im(4);
635 } else {
636 /* post increment */
637 }
638 } else {
639 if (insn & (1 << 24)) {
640 /* pre decrement */
641 gen_op_addl_T1_im(-(n * 4));
642 } else {
643 /* post decrement */
644 if (n != 1)
645 gen_op_addl_T1_im(-((n - 1) * 4));
646 }
647 }
648 j = 0;
649 for(i=0;i<16;i++) {
650 if (insn & (1 << i)) {
651 if (insn & (1 << 20)) {
652 /* load */
653 gen_op_ldl_T0_T1();
654 gen_movl_reg_T0(s, i);
655 } else {
656 /* store */
657 if (i == 15) {
658 /* special case: r15 = PC + 12 */
659 val = (long)s->pc + 8;
660 gen_op_movl_TN_im[0](val);
661 } else {
662 gen_movl_T0_reg(s, i);
663 }
664 gen_op_stl_T0_T1();
665 }
666 j++;
667 /* no need to add after the last transfer */
668 if (j != n)
669 gen_op_addl_T1_im(4);
670 }
671 }
672 if (insn & (1 << 21)) {
673 /* write back */
674 if (insn & (1 << 23)) {
675 if (insn & (1 << 24)) {
676 /* pre increment */
677 } else {
678 /* post increment */
679 gen_op_addl_T1_im(4);
680 }
681 } else {
682 if (insn & (1 << 24)) {
683 /* pre decrement */
684 if (n != 1)
685 gen_op_addl_T1_im(-((n - 1) * 4));
686 } else {
687 /* post decrement */
688 gen_op_addl_T1_im(-(n * 4));
689 }
690 }
691 gen_movl_reg_T1(s, rn);
692 }
693 }
694 break;
695 case 0xa:
696 case 0xb:
697 {
698 int offset;
699
700 /* branch (and link) */
701 val = (int)s->pc;
702 if (insn & (1 << 24)) {
703 gen_op_movl_T0_im(val);
704 gen_op_movl_reg_TN[0][14]();
705 }
706 offset = (((int)insn << 8) >> 8);
707 val += (offset << 2) + 4;
708 gen_op_jmp((long)s->tb, val);
709 s->is_jmp = DISAS_TB_JUMP;
710 }
711 break;
712 case 0xf:
713 /* swi */
714 gen_op_movl_T0_im((long)s->pc);
715 gen_op_movl_reg_TN[0][15]();
716 gen_op_swi();
717 s->is_jmp = DISAS_JUMP;
718 break;
719 default:
720 illegal_op:
721 gen_op_movl_T0_im((long)s->pc - 4);
722 gen_op_movl_reg_TN[0][15]();
723 gen_op_undef_insn();
724 s->is_jmp = DISAS_JUMP;
725 break;
726 }
727 }
728 }
729
730 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
731 basic block 'tb'. If search_pc is TRUE, also generate PC
732 information for each intermediate instruction. */
733 static inline int gen_intermediate_code_internal(CPUState *env,
734 TranslationBlock *tb,
735 int search_pc)
736 {
737 DisasContext dc1, *dc = &dc1;
738 uint16_t *gen_opc_end;
739 int j, lj;
740 uint8_t *pc_start;
741
742 /* generate intermediate code */
743 pc_start = (uint8_t *)tb->pc;
744
745 dc->tb = tb;
746
747 gen_opc_ptr = gen_opc_buf;
748 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
749 gen_opparam_ptr = gen_opparam_buf;
750
751 dc->is_jmp = DISAS_NEXT;
752 dc->pc = pc_start;
753 lj = -1;
754 do {
755 if (search_pc) {
756 j = gen_opc_ptr - gen_opc_buf;
757 if (lj < j) {
758 lj++;
759 while (lj < j)
760 gen_opc_instr_start[lj++] = 0;
761 }
762 gen_opc_pc[lj] = (uint32_t)dc->pc;
763 gen_opc_instr_start[lj] = 1;
764 }
765 disas_arm_insn(dc);
766 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
767 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
768 switch(dc->is_jmp) {
769 case DISAS_JUMP_NEXT:
770 case DISAS_NEXT:
771 gen_op_jmp((long)dc->tb, (long)dc->pc);
772 break;
773 default:
774 case DISAS_JUMP:
775 /* indicate that the hash table must be used to find the next TB */
776 gen_op_movl_T0_0();
777 gen_op_exit_tb();
778 break;
779 case DISAS_TB_JUMP:
780 /* nothing more to generate */
781 break;
782 }
783 *gen_opc_ptr = INDEX_op_end;
784
785 #ifdef DEBUG_DISAS
786 if (loglevel & CPU_LOG_TB_IN_ASM) {
787 fprintf(logfile, "----------------\n");
788 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
789 disas(logfile, pc_start, dc->pc - pc_start, 0, 0);
790 fprintf(logfile, "\n");
791 if (loglevel & (CPU_LOG_TB_OP)) {
792 fprintf(logfile, "OP:\n");
793 dump_ops(gen_opc_buf, gen_opparam_buf);
794 fprintf(logfile, "\n");
795 }
796 }
797 #endif
798 if (!search_pc)
799 tb->size = dc->pc - pc_start;
800 return 0;
801 }
802
803 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
804 {
805 return gen_intermediate_code_internal(env, tb, 0);
806 }
807
808 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
809 {
810 return gen_intermediate_code_internal(env, tb, 1);
811 }
812
813 CPUARMState *cpu_arm_init(void)
814 {
815 CPUARMState *env;
816
817 cpu_exec_init();
818
819 env = malloc(sizeof(CPUARMState));
820 if (!env)
821 return NULL;
822 memset(env, 0, sizeof(CPUARMState));
823 cpu_single_env = env;
824 return env;
825 }
826
827 void cpu_arm_close(CPUARMState *env)
828 {
829 free(env);
830 }
831
832 void cpu_dump_state(CPUState *env, FILE *f,
833 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
834 int flags)
835 {
836 int i;
837
838 for(i=0;i<16;i++) {
839 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
840 if ((i % 4) == 3)
841 cpu_fprintf(f, "\n");
842 else
843 cpu_fprintf(f, " ");
844 }
845 cpu_fprintf(f, "PSR=%08x %c%c%c%c\n",
846 env->cpsr,
847 env->cpsr & (1 << 31) ? 'N' : '-',
848 env->cpsr & (1 << 30) ? 'Z' : '-',
849 env->cpsr & (1 << 29) ? 'C' : '-',
850 env->cpsr & (1 << 28) ? 'V' : '-');
851 }
852
853 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
854 {
855 return addr;
856 }