]> git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
armv5te support (Paul Brook)
[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 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 GenOpFunc1 *gen_shift_T0_im_thumb[3] = {
249 gen_op_shll_T0_im_thumb,
250 gen_op_shrl_T0_im_thumb,
251 gen_op_sarl_T0_im_thumb,
252 };
253
254 static inline void gen_bx(DisasContext *s)
255 {
256 s->is_jmp = DISAS_UPDATE;
257 gen_op_bx_T0();
258 }
259
260 static inline void gen_movl_TN_reg(DisasContext *s, int reg, int t)
261 {
262 int val;
263
264 if (reg == 15) {
265 /* normaly, since we updated PC, we need only to add 4 */
266 val = (long)s->pc + 4;
267 gen_op_movl_TN_im[t](val);
268 } else {
269 gen_op_movl_TN_reg[t][reg]();
270 }
271 }
272
273 static inline void gen_movl_T0_reg(DisasContext *s, int reg)
274 {
275 gen_movl_TN_reg(s, reg, 0);
276 }
277
278 static inline void gen_movl_T1_reg(DisasContext *s, int reg)
279 {
280 gen_movl_TN_reg(s, reg, 1);
281 }
282
283 static inline void gen_movl_T2_reg(DisasContext *s, int reg)
284 {
285 gen_movl_TN_reg(s, reg, 2);
286 }
287
288 static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t)
289 {
290 gen_op_movl_reg_TN[t][reg]();
291 if (reg == 15) {
292 s->is_jmp = DISAS_JUMP;
293 }
294 }
295
296 static inline void gen_movl_reg_T0(DisasContext *s, int reg)
297 {
298 gen_movl_reg_TN(s, reg, 0);
299 }
300
301 static inline void gen_movl_reg_T1(DisasContext *s, int reg)
302 {
303 gen_movl_reg_TN(s, reg, 1);
304 }
305
306 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn)
307 {
308 int val, rm, shift, shiftop;
309
310 if (!(insn & (1 << 25))) {
311 /* immediate */
312 val = insn & 0xfff;
313 if (!(insn & (1 << 23)))
314 val = -val;
315 if (val != 0)
316 gen_op_addl_T1_im(val);
317 } else {
318 /* shift/register */
319 rm = (insn) & 0xf;
320 shift = (insn >> 7) & 0x1f;
321 gen_movl_T2_reg(s, rm);
322 shiftop = (insn >> 5) & 3;
323 if (shift != 0) {
324 gen_shift_T2_im[shiftop](shift);
325 } else if (shiftop != 0) {
326 gen_shift_T2_0[shiftop]();
327 }
328 if (!(insn & (1 << 23)))
329 gen_op_subl_T1_T2();
330 else
331 gen_op_addl_T1_T2();
332 }
333 }
334
335 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn)
336 {
337 int val, rm;
338
339 if (insn & (1 << 22)) {
340 /* immediate */
341 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
342 if (!(insn & (1 << 23)))
343 val = -val;
344 if (val != 0)
345 gen_op_addl_T1_im(val);
346 } else {
347 /* register */
348 rm = (insn) & 0xf;
349 gen_movl_T2_reg(s, rm);
350 if (!(insn & (1 << 23)))
351 gen_op_subl_T1_T2();
352 else
353 gen_op_addl_T1_T2();
354 }
355 }
356
357 static void disas_arm_insn(DisasContext *s)
358 {
359 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
360
361 insn = ldl(s->pc);
362 s->pc += 4;
363
364 cond = insn >> 28;
365 if (cond == 0xf){
366 if ((insn & 0x0d70f000) == 0x0550f000)
367 return; /* PLD */
368 else if ((insn & 0x0e000000) == 0x0a000000) {
369 /* branch link and change to thumb (blx <offset>) */
370 int32_t offset;
371
372 val = (uint32_t)s->pc;
373 gen_op_movl_T0_im(val);
374 gen_movl_reg_T0(s, 14);
375 /* Sign-extend the 24-bit offset */
376 offset = (((int32_t)insn) << 8) >> 8;
377 /* offset * 4 + bit24 * 2 + (thumb bit) */
378 val += (offset << 2) | ((insn >> 23) & 2) | 1;
379 /* pipeline offset */
380 val += 4;
381 gen_op_movl_T0_im(val);
382 gen_bx(s);
383 return;
384 }
385 goto illegal_op;
386 }
387 if (cond != 0xe) {
388 /* if not always execute, we generate a conditional jump to
389 next instruction */
390 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
391 s->is_jmp = DISAS_JUMP_NEXT;
392 }
393 if ((insn & 0x0f900000) == 0x03000000) {
394 if ((insn & 0x0ff0f000) != 0x0360f000)
395 goto illegal_op;
396 /* CPSR = immediate */
397 val = insn & 0xff;
398 shift = ((insn >> 8) & 0xf) * 2;
399 if (shift)
400 val = (val >> shift) | (val << (32 - shift));
401 gen_op_movl_T0_im(val);
402 if (insn & (1 << 19))
403 gen_op_movl_psr_T0();
404 } else if ((insn & 0x0f900000) == 0x01000000
405 && (insn & 0x00000090) != 0x00000090) {
406 /* miscellaneous instructions */
407 op1 = (insn >> 21) & 3;
408 sh = (insn >> 4) & 0xf;
409 rm = insn & 0xf;
410 switch (sh) {
411 case 0x0: /* move program status register */
412 if (op1 & 2) {
413 /* SPSR not accessible in user mode */
414 goto illegal_op;
415 }
416 if (op1 & 1) {
417 /* CPSR = reg */
418 gen_movl_T0_reg(s, rm);
419 if (insn & (1 << 19))
420 gen_op_movl_psr_T0();
421 } else {
422 /* reg = CPSR */
423 rd = (insn >> 12) & 0xf;
424 gen_op_movl_T0_psr();
425 gen_movl_reg_T0(s, rd);
426 }
427 case 0x1:
428 if (op1 == 1) {
429 /* branch/exchange thumb (bx). */
430 gen_movl_T0_reg(s, rm);
431 gen_bx(s);
432 } else if (op1 == 3) {
433 /* clz */
434 rd = (insn >> 12) & 0xf;
435 gen_movl_T0_reg(s, rm);
436 gen_op_clz_T0();
437 gen_movl_reg_T0(s, rd);
438 } else {
439 goto illegal_op;
440 }
441 break;
442 case 0x3:
443 if (op1 != 1)
444 goto illegal_op;
445
446 /* branch link/exchange thumb (blx) */
447 val = (uint32_t)s->pc;
448 gen_op_movl_T0_im(val);
449 gen_movl_reg_T0(s, 14);
450 gen_movl_T0_reg(s, rm);
451 gen_bx(s);
452 break;
453 case 0x5: /* saturating add/subtract */
454 rd = (insn >> 12) & 0xf;
455 rn = (insn >> 16) & 0xf;
456 gen_movl_T0_reg(s, rn);
457 if (op1 & 2) {
458 gen_movl_T1_reg(s, rn);
459 if (op1 & 1)
460 gen_op_subl_T0_T1_saturate();
461 else
462 gen_op_addl_T0_T1_saturate();
463 }
464 gen_movl_T1_reg(s, rm);
465 if (op1 & 1)
466 gen_op_subl_T0_T1_saturate();
467 else
468 gen_op_addl_T0_T1_saturate();
469 gen_movl_reg_T0(s, rn);
470 break;
471 case 0x8: /* signed multiply */
472 case 0xa:
473 case 0xc:
474 case 0xe:
475 rs = (insn >> 8) & 0xf;
476 rn = (insn >> 12) & 0xf;
477 rd = (insn >> 16) & 0xf;
478 if (op1 == 1) {
479 /* (32 * 16) >> 16 */
480 gen_movl_T0_reg(s, rm);
481 gen_movl_T1_reg(s, rs);
482 if (sh & 4)
483 gen_op_sarl_T1_im(16);
484 else
485 gen_op_sxl_T1();
486 gen_op_imulw_T0_T1();
487 if ((sh & 2) == 0) {
488 gen_movl_T1_reg(s, rn);
489 gen_op_addl_T0_T1_setq();
490 }
491 gen_movl_reg_T0(s, rd);
492 } else {
493 /* 16 * 16 */
494 gen_movl_T0_reg(s, rm);
495 if (sh & 2)
496 gen_op_sarl_T0_im(16);
497 else
498 gen_op_sxl_T0();
499 gen_movl_T1_reg(s, rs);
500 if (sh & 4)
501 gen_op_sarl_T1_im(16);
502 else
503 gen_op_sxl_T1();
504 if (op1 == 2) {
505 gen_op_imull_T0_T1();
506 gen_op_addq_T0_T1(rn, rd);
507 gen_movl_reg_T0(s, rn);
508 gen_movl_reg_T1(s, rd);
509 } else {
510 gen_op_mul_T0_T1();
511 if (op1 == 0) {
512 gen_movl_T1_reg(s, rn);
513 gen_op_addl_T0_T1_setq();
514 }
515 gen_movl_reg_T0(s, rd);
516 }
517 }
518 break;
519 default:
520 goto illegal_op;
521 }
522 } else if (((insn & 0x0e000000) == 0 &&
523 (insn & 0x00000090) != 0x90) ||
524 ((insn & 0x0e000000) == (1 << 25))) {
525 int set_cc, logic_cc, shiftop;
526
527 op1 = (insn >> 21) & 0xf;
528 set_cc = (insn >> 20) & 1;
529 logic_cc = table_logic_cc[op1] & set_cc;
530
531 /* data processing instruction */
532 if (insn & (1 << 25)) {
533 /* immediate operand */
534 val = insn & 0xff;
535 shift = ((insn >> 8) & 0xf) * 2;
536 if (shift)
537 val = (val >> shift) | (val << (32 - shift));
538 gen_op_movl_T1_im(val);
539 /* XXX: is CF modified ? */
540 } else {
541 /* register */
542 rm = (insn) & 0xf;
543 gen_movl_T1_reg(s, rm);
544 shiftop = (insn >> 5) & 3;
545 if (!(insn & (1 << 4))) {
546 shift = (insn >> 7) & 0x1f;
547 if (shift != 0) {
548 if (logic_cc) {
549 gen_shift_T1_im_cc[shiftop](shift);
550 } else {
551 gen_shift_T1_im[shiftop](shift);
552 }
553 } else if (shiftop != 0) {
554 if (logic_cc) {
555 gen_shift_T1_0_cc[shiftop]();
556 } else {
557 gen_shift_T1_0[shiftop]();
558 }
559 }
560 } else {
561 rs = (insn >> 8) & 0xf;
562 gen_movl_T0_reg(s, rs);
563 if (logic_cc) {
564 gen_shift_T1_T0_cc[shiftop]();
565 } else {
566 gen_shift_T1_T0[shiftop]();
567 }
568 }
569 }
570 if (op1 != 0x0f && op1 != 0x0d) {
571 rn = (insn >> 16) & 0xf;
572 gen_movl_T0_reg(s, rn);
573 }
574 rd = (insn >> 12) & 0xf;
575 switch(op1) {
576 case 0x00:
577 gen_op_andl_T0_T1();
578 gen_movl_reg_T0(s, rd);
579 if (logic_cc)
580 gen_op_logic_T0_cc();
581 break;
582 case 0x01:
583 gen_op_xorl_T0_T1();
584 gen_movl_reg_T0(s, rd);
585 if (logic_cc)
586 gen_op_logic_T0_cc();
587 break;
588 case 0x02:
589 if (set_cc)
590 gen_op_subl_T0_T1_cc();
591 else
592 gen_op_subl_T0_T1();
593 gen_movl_reg_T0(s, rd);
594 break;
595 case 0x03:
596 if (set_cc)
597 gen_op_rsbl_T0_T1_cc();
598 else
599 gen_op_rsbl_T0_T1();
600 gen_movl_reg_T0(s, rd);
601 break;
602 case 0x04:
603 if (set_cc)
604 gen_op_addl_T0_T1_cc();
605 else
606 gen_op_addl_T0_T1();
607 gen_movl_reg_T0(s, rd);
608 break;
609 case 0x05:
610 if (set_cc)
611 gen_op_adcl_T0_T1_cc();
612 else
613 gen_op_adcl_T0_T1();
614 gen_movl_reg_T0(s, rd);
615 break;
616 case 0x06:
617 if (set_cc)
618 gen_op_sbcl_T0_T1_cc();
619 else
620 gen_op_sbcl_T0_T1();
621 gen_movl_reg_T0(s, rd);
622 break;
623 case 0x07:
624 if (set_cc)
625 gen_op_rscl_T0_T1_cc();
626 else
627 gen_op_rscl_T0_T1();
628 gen_movl_reg_T0(s, rd);
629 break;
630 case 0x08:
631 if (set_cc) {
632 gen_op_andl_T0_T1();
633 gen_op_logic_T0_cc();
634 }
635 break;
636 case 0x09:
637 if (set_cc) {
638 gen_op_xorl_T0_T1();
639 gen_op_logic_T0_cc();
640 }
641 break;
642 case 0x0a:
643 if (set_cc) {
644 gen_op_subl_T0_T1_cc();
645 }
646 break;
647 case 0x0b:
648 if (set_cc) {
649 gen_op_addl_T0_T1_cc();
650 }
651 break;
652 case 0x0c:
653 gen_op_orl_T0_T1();
654 gen_movl_reg_T0(s, rd);
655 if (logic_cc)
656 gen_op_logic_T0_cc();
657 break;
658 case 0x0d:
659 gen_movl_reg_T1(s, rd);
660 if (logic_cc)
661 gen_op_logic_T1_cc();
662 break;
663 case 0x0e:
664 gen_op_bicl_T0_T1();
665 gen_movl_reg_T0(s, rd);
666 if (logic_cc)
667 gen_op_logic_T0_cc();
668 break;
669 default:
670 case 0x0f:
671 gen_op_notl_T1();
672 gen_movl_reg_T1(s, rd);
673 if (logic_cc)
674 gen_op_logic_T1_cc();
675 break;
676 }
677 } else {
678 /* other instructions */
679 op1 = (insn >> 24) & 0xf;
680 switch(op1) {
681 case 0x0:
682 case 0x1:
683 /* multiplies, extra load/stores */
684 sh = (insn >> 5) & 3;
685 if (sh == 0) {
686 if (op1 == 0x0) {
687 rd = (insn >> 16) & 0xf;
688 rn = (insn >> 12) & 0xf;
689 rs = (insn >> 8) & 0xf;
690 rm = (insn) & 0xf;
691 if (((insn >> 22) & 3) == 0) {
692 /* 32 bit mul */
693 gen_movl_T0_reg(s, rs);
694 gen_movl_T1_reg(s, rm);
695 gen_op_mul_T0_T1();
696 if (insn & (1 << 21)) {
697 gen_movl_T1_reg(s, rn);
698 gen_op_addl_T0_T1();
699 }
700 if (insn & (1 << 20))
701 gen_op_logic_T0_cc();
702 gen_movl_reg_T0(s, rd);
703 } else {
704 /* 64 bit mul */
705 gen_movl_T0_reg(s, rs);
706 gen_movl_T1_reg(s, rm);
707 if (insn & (1 << 22))
708 gen_op_imull_T0_T1();
709 else
710 gen_op_mull_T0_T1();
711 if (insn & (1 << 21)) /* mult accumulate */
712 gen_op_addq_T0_T1(rn, rd);
713 if (!(insn & (1 << 23))) { /* double accumulate */
714 gen_op_addq_lo_T0_T1(rn);
715 gen_op_addq_lo_T0_T1(rd);
716 }
717 if (insn & (1 << 20))
718 gen_op_logicq_cc();
719 gen_movl_reg_T0(s, rn);
720 gen_movl_reg_T1(s, rd);
721 }
722 } else {
723 rn = (insn >> 16) & 0xf;
724 rd = (insn >> 12) & 0xf;
725 if (insn & (1 << 23)) {
726 /* load/store exclusive */
727 goto illegal_op;
728 } else {
729 /* SWP instruction */
730 rm = (insn) & 0xf;
731
732 gen_movl_T0_reg(s, rm);
733 gen_movl_T1_reg(s, rn);
734 if (insn & (1 << 22)) {
735 gen_op_swpb_T0_T1();
736 } else {
737 gen_op_swpl_T0_T1();
738 }
739 gen_movl_reg_T0(s, rd);
740 }
741 }
742 } else {
743 /* Misc load/store */
744 rn = (insn >> 16) & 0xf;
745 rd = (insn >> 12) & 0xf;
746 gen_movl_T1_reg(s, rn);
747 if (insn & (1 << 24))
748 gen_add_datah_offset(s, insn);
749 if (insn & (1 << 20)) {
750 /* load */
751 switch(sh) {
752 case 1:
753 gen_op_lduw_T0_T1();
754 break;
755 case 2:
756 gen_op_ldsb_T0_T1();
757 break;
758 default:
759 case 3:
760 gen_op_ldsw_T0_T1();
761 break;
762 }
763 gen_movl_reg_T0(s, rd);
764 } else if (sh & 2) {
765 /* doubleword */
766 if (sh & 1) {
767 /* store */
768 gen_movl_T0_reg(s, rd);
769 gen_op_stl_T0_T1();
770 gen_op_addl_T1_im(4);
771 gen_movl_T0_reg(s, rd + 1);
772 gen_op_stl_T0_T1();
773 if ((insn & (1 << 24)) || (insn & (1 << 20)))
774 gen_op_addl_T1_im(-4);
775 } else {
776 /* load */
777 gen_op_ldl_T0_T1();
778 gen_movl_reg_T0(s, rd);
779 gen_op_addl_T1_im(4);
780 gen_op_ldl_T0_T1();
781 gen_movl_reg_T0(s, rd + 1);
782 if ((insn & (1 << 24)) || (insn & (1 << 20)))
783 gen_op_addl_T1_im(-4);
784 }
785 } else {
786 /* store */
787 gen_movl_T0_reg(s, rd);
788 gen_op_stw_T0_T1();
789 }
790 if (!(insn & (1 << 24))) {
791 gen_add_datah_offset(s, insn);
792 gen_movl_reg_T1(s, rn);
793 } else if (insn & (1 << 21)) {
794 gen_movl_reg_T1(s, rn);
795 }
796 }
797 break;
798 case 0x4:
799 case 0x5:
800 case 0x6:
801 case 0x7:
802 /* load/store byte/word */
803 rn = (insn >> 16) & 0xf;
804 rd = (insn >> 12) & 0xf;
805 gen_movl_T1_reg(s, rn);
806 if (insn & (1 << 24))
807 gen_add_data_offset(s, insn);
808 if (insn & (1 << 20)) {
809 /* load */
810 if (insn & (1 << 22))
811 gen_op_ldub_T0_T1();
812 else
813 gen_op_ldl_T0_T1();
814 if (rd == 15)
815 gen_bx(s);
816 else
817 gen_movl_reg_T0(s, rd);
818 } else {
819 /* store */
820 gen_movl_T0_reg(s, rd);
821 if (insn & (1 << 22))
822 gen_op_stb_T0_T1();
823 else
824 gen_op_stl_T0_T1();
825 }
826 if (!(insn & (1 << 24))) {
827 gen_add_data_offset(s, insn);
828 gen_movl_reg_T1(s, rn);
829 } else if (insn & (1 << 21))
830 gen_movl_reg_T1(s, rn); {
831 }
832 break;
833 case 0x08:
834 case 0x09:
835 {
836 int j, n;
837 /* load/store multiple words */
838 /* XXX: store correct base if write back */
839 if (insn & (1 << 22))
840 goto illegal_op; /* only usable in supervisor mode */
841 rn = (insn >> 16) & 0xf;
842 gen_movl_T1_reg(s, rn);
843
844 /* compute total size */
845 n = 0;
846 for(i=0;i<16;i++) {
847 if (insn & (1 << i))
848 n++;
849 }
850 /* XXX: test invalid n == 0 case ? */
851 if (insn & (1 << 23)) {
852 if (insn & (1 << 24)) {
853 /* pre increment */
854 gen_op_addl_T1_im(4);
855 } else {
856 /* post increment */
857 }
858 } else {
859 if (insn & (1 << 24)) {
860 /* pre decrement */
861 gen_op_addl_T1_im(-(n * 4));
862 } else {
863 /* post decrement */
864 if (n != 1)
865 gen_op_addl_T1_im(-((n - 1) * 4));
866 }
867 }
868 j = 0;
869 for(i=0;i<16;i++) {
870 if (insn & (1 << i)) {
871 if (insn & (1 << 20)) {
872 /* load */
873 gen_op_ldl_T0_T1();
874 if (i == 15)
875 gen_bx(s);
876 else
877 gen_movl_reg_T0(s, i);
878 } else {
879 /* store */
880 if (i == 15) {
881 /* special case: r15 = PC + 12 */
882 val = (long)s->pc + 8;
883 gen_op_movl_TN_im[0](val);
884 } else {
885 gen_movl_T0_reg(s, i);
886 }
887 gen_op_stl_T0_T1();
888 }
889 j++;
890 /* no need to add after the last transfer */
891 if (j != n)
892 gen_op_addl_T1_im(4);
893 }
894 }
895 if (insn & (1 << 21)) {
896 /* write back */
897 if (insn & (1 << 23)) {
898 if (insn & (1 << 24)) {
899 /* pre increment */
900 } else {
901 /* post increment */
902 gen_op_addl_T1_im(4);
903 }
904 } else {
905 if (insn & (1 << 24)) {
906 /* pre decrement */
907 if (n != 1)
908 gen_op_addl_T1_im(-((n - 1) * 4));
909 } else {
910 /* post decrement */
911 gen_op_addl_T1_im(-(n * 4));
912 }
913 }
914 gen_movl_reg_T1(s, rn);
915 }
916 }
917 break;
918 case 0xa:
919 case 0xb:
920 {
921 int32_t offset;
922
923 /* branch (and link) */
924 val = (int32_t)s->pc;
925 if (insn & (1 << 24)) {
926 gen_op_movl_T0_im(val);
927 gen_op_movl_reg_TN[0][14]();
928 }
929 offset = (((int32_t)insn << 8) >> 8);
930 val += (offset << 2) + 4;
931 gen_op_jmp((long)s->tb, val);
932 s->is_jmp = DISAS_TB_JUMP;
933 }
934 break;
935 case 0xf:
936 /* swi */
937 gen_op_movl_T0_im((long)s->pc);
938 gen_op_movl_reg_TN[0][15]();
939 gen_op_swi();
940 s->is_jmp = DISAS_JUMP;
941 break;
942 default:
943 illegal_op:
944 gen_op_movl_T0_im((long)s->pc - 4);
945 gen_op_movl_reg_TN[0][15]();
946 gen_op_undef_insn();
947 s->is_jmp = DISAS_JUMP;
948 break;
949 }
950 }
951 }
952
953 static void disas_thumb_insn(DisasContext *s)
954 {
955 uint32_t val, insn, op, rm, rn, rd, shift, cond;
956 int32_t offset;
957 int i;
958
959 insn = lduw(s->pc);
960 s->pc += 2;
961
962 switch (insn >> 12) {
963 case 0: case 1:
964 rd = insn & 7;
965 op = (insn >> 11) & 3;
966 if (op == 3) {
967 /* add/subtract */
968 rn = (insn >> 3) & 7;
969 gen_movl_T0_reg(s, rn);
970 if (insn & (1 << 10)) {
971 /* immediate */
972 gen_op_movl_T1_im((insn >> 6) & 7);
973 } else {
974 /* reg */
975 rm = (insn >> 6) & 7;
976 gen_movl_T1_reg(s, rm);
977 }
978 if (insn & (1 << 9))
979 gen_op_addl_T0_T1_cc();
980 else
981 gen_op_addl_T0_T1_cc();
982 gen_movl_reg_T0(s, rd);
983 } else {
984 /* shift immediate */
985 rm = (insn >> 3) & 7;
986 shift = (insn >> 6) & 0x1f;
987 gen_movl_T0_reg(s, rm);
988 gen_shift_T0_im_thumb[op](shift);
989 gen_movl_reg_T0(s, rd);
990 }
991 break;
992 case 2: case 3:
993 /* arithmetic large immediate */
994 op = (insn >> 11) & 3;
995 rd = (insn >> 8) & 0x7;
996 if (op == 0) {
997 gen_op_movl_T0_im(insn & 0xff);
998 } else {
999 gen_movl_T0_reg(s, rd);
1000 gen_op_movl_T1_im(insn & 0xff);
1001 }
1002 switch (op) {
1003 case 0: /* mov */
1004 gen_op_logic_T0_cc();
1005 break;
1006 case 1: /* cmp */
1007 gen_op_subl_T0_T1_cc();
1008 break;
1009 case 2: /* add */
1010 gen_op_addl_T0_T1_cc();
1011 break;
1012 case 3: /* sub */
1013 gen_op_subl_T0_T1_cc();
1014 break;
1015 }
1016 if (op != 1)
1017 gen_movl_reg_T0(s, rd);
1018 break;
1019 case 4:
1020 if (insn & (1 << 11)) {
1021 rd = (insn >> 8) & 7;
1022 /* load pc-relative */
1023 val = (insn & 0xff) * 4;
1024 gen_op_movl_T1_im(val);
1025 gen_movl_T2_reg(s, 15);
1026 gen_op_addl_T1_T2();
1027 gen_op_ldl_T0_T1();
1028 gen_movl_reg_T0(s, rd);
1029 break;
1030 }
1031 if (insn & (1 << 10)) {
1032 /* data processing extended or blx */
1033 rd = (insn & 7) | ((insn >> 4) & 8);
1034 rm = (insn >> 3) & 0xf;
1035 op = (insn >> 8) & 3;
1036 switch (op) {
1037 case 0: /* add */
1038 gen_movl_T0_reg(s, rd);
1039 gen_movl_T1_reg(s, rm);
1040 gen_op_addl_T0_T1();
1041 gen_movl_reg_T0(s, rd);
1042 break;
1043 case 1: /* cmp */
1044 gen_movl_T0_reg(s, rd);
1045 gen_movl_T1_reg(s, rm);
1046 gen_op_subl_T0_T1_cc();
1047 break;
1048 case 2: /* mov/cpy */
1049 gen_movl_T0_reg(s, rm);
1050 gen_movl_reg_T0(s, rd);
1051 break;
1052 case 3:/* branch [and link] exchange thumb register */
1053 if (insn & (1 << 7)) {
1054 val = (uint32_t)s->pc | 1;
1055 gen_op_movl_T1_im(val);
1056 gen_movl_reg_T1(s, 14);
1057 }
1058 gen_movl_T0_reg(s, rm);
1059 gen_bx(s);
1060 break;
1061 }
1062 break;
1063 }
1064
1065 /* data processing register */
1066 rd = insn & 7;
1067 rm = (insn >> 3) & 7;
1068 op = (insn >> 6) & 0xf;
1069 if (op == 2 || op == 3 || op == 4 || op == 7) {
1070 /* the shift/rotate ops want the operands backwards */
1071 val = rm;
1072 rm = rd;
1073 rd = val;
1074 val = 1;
1075 } else {
1076 val = 0;
1077 }
1078
1079 if (op == 9) /* neg */
1080 gen_op_movl_T0_im(0);
1081 else if (op != 0xf) /* mvn doesn't read its first operand */
1082 gen_movl_T0_reg(s, rd);
1083
1084 gen_movl_T1_reg(s, rm);
1085 switch (insn >> 6) {
1086 case 0x0: /* and */
1087 gen_op_andl_T0_T1();
1088 gen_op_logic_T0_cc();
1089 break;
1090 case 0x1: /* eor */
1091 gen_op_xorl_T0_T1();
1092 gen_op_logic_T0_cc();
1093 break;
1094 case 0x2: /* lsl */
1095 gen_op_shll_T1_T0_cc();
1096 break;
1097 case 0x3: /* lsr */
1098 gen_op_shrl_T1_T0_cc();
1099 break;
1100 case 0x4: /* asr */
1101 gen_op_sarl_T1_T0_cc();
1102 break;
1103 case 0x5: /* adc */
1104 gen_op_adcl_T0_T1_cc();
1105 break;
1106 case 0x6: /* sbc */
1107 gen_op_sbcl_T0_T1_cc();
1108 break;
1109 case 0x7: /* ror */
1110 gen_op_rorl_T1_T0_cc();
1111 break;
1112 case 0x8: /* tst */
1113 gen_op_andl_T0_T1();
1114 gen_op_logic_T0_cc();
1115 rd = 16;
1116 case 0x9: /* neg */
1117 gen_op_rsbl_T0_T1_cc();
1118 break;
1119 case 0xa: /* cmp */
1120 gen_op_subl_T0_T1_cc();
1121 rd = 16;
1122 break;
1123 case 0xb: /* cmn */
1124 gen_op_addl_T0_T1_cc();
1125 rd = 16;
1126 break;
1127 case 0xc: /* orr */
1128 gen_op_orl_T0_T1();
1129 gen_op_logic_T0_cc();
1130 break;
1131 case 0xd: /* mul */
1132 gen_op_mull_T0_T1();
1133 gen_op_logic_T0_cc();
1134 break;
1135 case 0xe: /* bic */
1136 gen_op_bicl_T0_T1();
1137 gen_op_logic_T0_cc();
1138 break;
1139 case 0xf: /* mvn */
1140 gen_op_notl_T1();
1141 gen_op_logic_T1_cc();
1142 val = 1;
1143 break;
1144 }
1145 if (rd != 16) {
1146 if (val)
1147 gen_movl_reg_T1(s, rd);
1148 else
1149 gen_movl_reg_T0(s, rd);
1150 }
1151 break;
1152
1153 case 5:
1154 /* load/store register offset. */
1155 rd = insn & 7;
1156 rn = (insn >> 3) & 7;
1157 rm = (insn >> 6) & 7;
1158 op = (insn >> 9) & 7;
1159 gen_movl_T1_reg(s, rn);
1160 gen_movl_T2_reg(s, rm);
1161 gen_op_addl_T1_T2();
1162
1163 if (op < 3) /* store */
1164 gen_movl_T0_reg(s, rd);
1165
1166 switch (op) {
1167 case 0: /* str */
1168 gen_op_stl_T0_T1();
1169 break;
1170 case 1: /* strh */
1171 gen_op_stw_T0_T1();
1172 break;
1173 case 2: /* strb */
1174 gen_op_stb_T0_T1();
1175 break;
1176 case 3: /* ldrsb */
1177 gen_op_ldsb_T0_T1();
1178 break;
1179 case 4: /* ldr */
1180 gen_op_ldl_T0_T1();
1181 break;
1182 case 5: /* ldrh */
1183 gen_op_ldsw_T0_T1();
1184 break;
1185 case 6: /* ldrb */
1186 gen_op_ldub_T0_T1();
1187 break;
1188 case 7: /* ldrsh */
1189 gen_op_ldsw_T0_T1();
1190 break;
1191 }
1192 if (op >= 3) /* load */
1193 gen_movl_reg_T0(s, rd);
1194 break;
1195
1196 case 6:
1197 /* load/store word immediate offset */
1198 rd = insn & 7;
1199 rn = (insn >> 3) & 7;
1200 gen_movl_T1_reg(s, rn);
1201 val = (insn >> 4) & 0x7c;
1202 gen_op_movl_T2_im(val);
1203 gen_op_addl_T1_T2();
1204
1205 if (insn & (1 << 11)) {
1206 /* load */
1207 gen_op_ldl_T0_T1();
1208 gen_movl_reg_T0(s, rd);
1209 } else {
1210 /* store */
1211 gen_movl_T0_reg(s, rd);
1212 gen_op_stl_T0_T1();
1213 }
1214 break;
1215
1216 case 7:
1217 /* load/store byte immediate offset */
1218 rd = insn & 7;
1219 rn = (insn >> 3) & 7;
1220 gen_movl_T1_reg(s, rn);
1221 val = (insn >> 6) & 0x1f;
1222 gen_op_movl_T2_im(val);
1223 gen_op_addl_T1_T2();
1224
1225 if (insn & (1 << 11)) {
1226 /* load */
1227 gen_op_ldub_T0_T1();
1228 gen_movl_reg_T0(s, rd);
1229 } else {
1230 /* store */
1231 gen_movl_T0_reg(s, rd);
1232 gen_op_stb_T0_T1();
1233 }
1234 break;
1235
1236 case 8:
1237 /* load/store halfword immediate offset */
1238 rd = insn & 7;
1239 rn = (insn >> 3) & 7;
1240 gen_movl_T1_reg(s, rn);
1241 val = (insn >> 5) & 0x3e;
1242 gen_op_movl_T2_im(val);
1243 gen_op_addl_T1_T2();
1244
1245 if (insn & (1 << 11)) {
1246 /* load */
1247 gen_op_lduw_T0_T1();
1248 gen_movl_reg_T0(s, rd);
1249 } else {
1250 /* store */
1251 gen_movl_T0_reg(s, rd);
1252 gen_op_stw_T0_T1();
1253 }
1254 break;
1255
1256 case 9:
1257 /* load/store from stack */
1258 rd = (insn >> 8) & 7;
1259 gen_movl_T1_reg(s, 13);
1260 val = (insn & 0xff) * 4;
1261 gen_op_movl_T2_im(val);
1262 gen_op_addl_T1_T2();
1263
1264 if (insn & (1 << 11)) {
1265 /* load */
1266 gen_op_ldl_T0_T1();
1267 gen_movl_reg_T0(s, rd);
1268 } else {
1269 /* store */
1270 gen_movl_T0_reg(s, rd);
1271 gen_op_stl_T0_T1();
1272 }
1273 break;
1274
1275 case 10:
1276 /* add to high reg */
1277 rd = (insn >> 8) & 7;
1278 if (insn & (1 << 11))
1279 rm = 13; /* sp */
1280 else
1281 rm = 15; /* pc */
1282 gen_movl_T0_reg(s, rm);
1283 val = (insn & 0xff) * 4;
1284 gen_op_movl_T1_im(val);
1285 gen_op_addl_T0_T1();
1286 gen_movl_reg_T0(s, rd);
1287 break;
1288
1289 case 11:
1290 /* misc */
1291 op = (insn >> 8) & 0xf;
1292 switch (op) {
1293 case 0:
1294 /* adjust stack pointer */
1295 gen_movl_T1_reg(s, 13);
1296 val = (insn & 0x7f) * 4;
1297 if (insn & (1 << 7))
1298 val = -(int32_t)val;
1299 gen_op_movl_T2_im(val);
1300 gen_op_addl_T1_T2();
1301 gen_movl_reg_T1(s, 13);
1302 break;
1303
1304 case 4: case 5: case 0xc: case 0xd:
1305 /* push/pop */
1306 gen_movl_T1_reg(s, 13);
1307 if (insn & (1 << 11))
1308 val = 4;
1309 else
1310 val = -4;
1311 gen_op_movl_T2_im(val);
1312 for (i = 0; i < 8; i++) {
1313 if (insn & (1 << i)) {
1314 if (insn & (1 << 11)) {
1315 /* pop */
1316 gen_op_ldl_T0_T1();
1317 gen_movl_reg_T0(s, i);
1318 } else {
1319 /* push */
1320 gen_movl_T0_reg(s, i);
1321 gen_op_stl_T0_T1();
1322 }
1323 /* move to the next address */
1324 gen_op_addl_T1_T2();
1325 }
1326 }
1327 if (insn & (1 << 8)) {
1328 if (insn & (1 << 11)) {
1329 /* pop pc */
1330 gen_op_ldl_T0_T1();
1331 /* don't set the pc until the rest of the instruction
1332 has completed */
1333 } else {
1334 /* push lr */
1335 gen_movl_T0_reg(s, 14);
1336 gen_op_stl_T0_T1();
1337 }
1338 gen_op_addl_T1_T2();
1339 }
1340
1341 /* write back the new stack pointer */
1342 gen_movl_reg_T1(s, 13);
1343 /* set the new PC value */
1344 if ((insn & 0x0900) == 0x0900)
1345 gen_bx(s);
1346 break;
1347
1348 default:
1349 goto undef;
1350 }
1351 break;
1352
1353 case 12:
1354 /* load/store multiple */
1355 rn = (insn >> 8) & 0x7;
1356 gen_movl_T1_reg(s, rn);
1357 gen_op_movl_T2_im(4);
1358 val = 0;
1359 for (i = 0; i < 8; i++) {
1360 if (insn & (1 << i)) {
1361 /* advance to the next address */
1362 if (val)
1363 gen_op_addl_T1_T2();
1364 else
1365 val = 1;
1366 if (insn & (1 << 11)) {
1367 /* load */
1368 gen_op_ldl_T0_T1();
1369 gen_movl_reg_T0(s, i);
1370 } else {
1371 /* store */
1372 gen_movl_T0_reg(s, i);
1373 gen_op_stl_T0_T1();
1374 }
1375 }
1376 }
1377 break;
1378
1379 case 13:
1380 /* conditional branch or swi */
1381 cond = (insn >> 8) & 0xf;
1382 if (cond == 0xe)
1383 goto undef;
1384
1385 if (cond == 0xf) {
1386 /* swi */
1387 gen_op_movl_T0_im((long)s->pc | 1);
1388 /* Don't set r15. */
1389 gen_op_movl_reg_TN[0][15]();
1390 gen_op_swi();
1391 s->is_jmp = DISAS_JUMP;
1392 break;
1393 }
1394 /* generate a conditional jump to next instruction */
1395 gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
1396 s->is_jmp = DISAS_JUMP_NEXT;
1397 gen_movl_T1_reg(s, 15);
1398
1399 /* jump to the offset */
1400 val = (uint32_t)s->pc;
1401 offset = ((int32_t)insn << 24) >> 24;
1402 val += (offset << 1) + 2;
1403 gen_op_jmp((long)s->tb, val);
1404 s->is_jmp = DISAS_TB_JUMP;
1405 break;
1406
1407 case 14:
1408 /* unconditional branch */
1409 if (insn & (1 << 11))
1410 goto undef; /* Second half of a blx */
1411 val = (uint32_t)s->pc;
1412 offset = ((int32_t)insn << 21) >> 21;
1413 val += (offset << 1) + 2;
1414 gen_op_jmp((long)s->tb, val);
1415 s->is_jmp = DISAS_TB_JUMP;
1416 break;
1417
1418 case 15:
1419 /* branch and link [and switch to arm] */
1420 offset = ((int32_t)insn << 21) >> 10;
1421 insn = lduw(s->pc);
1422 offset |= insn & 0x7ff;
1423
1424 val = (uint32_t)s->pc + 2;
1425 gen_op_movl_T1_im(val | 1);
1426 gen_movl_reg_T1(s, 14);
1427
1428 val += offset;
1429 if (insn & (1 << 11)) {
1430 /* bl */
1431 gen_op_jmp((long)s->tb, val);
1432 s->is_jmp = DISAS_TB_JUMP;
1433 } else {
1434 /* blx */
1435 gen_op_movl_T0_im(val);
1436 gen_bx(s);
1437 }
1438 }
1439 return;
1440 undef:
1441 gen_op_movl_T0_im((long)s->pc - 4);
1442 gen_op_movl_reg_TN[0][15]();
1443 gen_op_undef_insn();
1444 s->is_jmp = DISAS_JUMP;
1445 }
1446
1447 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
1448 basic block 'tb'. If search_pc is TRUE, also generate PC
1449 information for each intermediate instruction. */
1450 static inline int gen_intermediate_code_internal(CPUState *env,
1451 TranslationBlock *tb,
1452 int search_pc)
1453 {
1454 DisasContext dc1, *dc = &dc1;
1455 uint16_t *gen_opc_end;
1456 int j, lj;
1457 target_ulong pc_start;
1458
1459 /* generate intermediate code */
1460 pc_start = tb->pc;
1461
1462 dc->tb = tb;
1463
1464 gen_opc_ptr = gen_opc_buf;
1465 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
1466 gen_opparam_ptr = gen_opparam_buf;
1467
1468 dc->is_jmp = DISAS_NEXT;
1469 dc->pc = pc_start;
1470 lj = -1;
1471 do {
1472 if (search_pc) {
1473 j = gen_opc_ptr - gen_opc_buf;
1474 if (lj < j) {
1475 lj++;
1476 while (lj < j)
1477 gen_opc_instr_start[lj++] = 0;
1478 }
1479 gen_opc_pc[lj] = dc->pc;
1480 gen_opc_instr_start[lj] = 1;
1481 }
1482 if (env->thumb)
1483 disas_thumb_insn(dc);
1484 else
1485 disas_arm_insn(dc);
1486 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
1487 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
1488 switch(dc->is_jmp) {
1489 case DISAS_JUMP_NEXT:
1490 case DISAS_NEXT:
1491 gen_op_jmp((long)dc->tb, (long)dc->pc);
1492 break;
1493 default:
1494 case DISAS_JUMP:
1495 case DISAS_UPDATE:
1496 /* indicate that the hash table must be used to find the next TB */
1497 gen_op_movl_T0_0();
1498 gen_op_exit_tb();
1499 break;
1500 case DISAS_TB_JUMP:
1501 /* nothing more to generate */
1502 break;
1503 }
1504 *gen_opc_ptr = INDEX_op_end;
1505
1506 #ifdef DEBUG_DISAS
1507 if (loglevel & CPU_LOG_TB_IN_ASM) {
1508 fprintf(logfile, "----------------\n");
1509 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
1510 target_disas(logfile, pc_start, dc->pc - pc_start, 0);
1511 fprintf(logfile, "\n");
1512 if (loglevel & (CPU_LOG_TB_OP)) {
1513 fprintf(logfile, "OP:\n");
1514 dump_ops(gen_opc_buf, gen_opparam_buf);
1515 fprintf(logfile, "\n");
1516 }
1517 }
1518 #endif
1519 if (!search_pc)
1520 tb->size = dc->pc - pc_start;
1521 return 0;
1522 }
1523
1524 int gen_intermediate_code(CPUState *env, TranslationBlock *tb)
1525 {
1526 return gen_intermediate_code_internal(env, tb, 0);
1527 }
1528
1529 int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
1530 {
1531 return gen_intermediate_code_internal(env, tb, 1);
1532 }
1533
1534 CPUARMState *cpu_arm_init(void)
1535 {
1536 CPUARMState *env;
1537
1538 cpu_exec_init();
1539
1540 env = malloc(sizeof(CPUARMState));
1541 if (!env)
1542 return NULL;
1543 memset(env, 0, sizeof(CPUARMState));
1544 cpu_single_env = env;
1545 return env;
1546 }
1547
1548 void cpu_arm_close(CPUARMState *env)
1549 {
1550 free(env);
1551 }
1552
1553 void cpu_dump_state(CPUState *env, FILE *f,
1554 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
1555 int flags)
1556 {
1557 int i;
1558
1559 for(i=0;i<16;i++) {
1560 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
1561 if ((i % 4) == 3)
1562 cpu_fprintf(f, "\n");
1563 else
1564 cpu_fprintf(f, " ");
1565 }
1566 cpu_fprintf(f, "PSR=%08x %c%c%c%c\n",
1567 env->cpsr,
1568 env->cpsr & (1 << 31) ? 'N' : '-',
1569 env->cpsr & (1 << 30) ? 'Z' : '-',
1570 env->cpsr & (1 << 29) ? 'C' : '-',
1571 env->cpsr & (1 << 28) ? 'V' : '-');
1572 }
1573
1574 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
1575 {
1576 return addr;
1577 }