]>
git.proxmox.com Git - qemu.git/blob - target-arm/translate.c
4 * Copyright (c) 2003 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 /* internal defines */
31 typedef struct DisasContext
{
34 struct TranslationBlock
*tb
;
37 #define DISAS_JUMP_NEXT 4
39 /* XXX: move that elsewhere */
40 static uint16_t *gen_opc_ptr
;
41 static uint32_t *gen_opparam_ptr
;
46 #define DEF(s, n, copy_size) INDEX_op_ ## s,
54 static GenOpFunc2
*gen_test_cc
[14] = {
71 const uint8_t table_logic_cc
[16] = {
90 static GenOpFunc1
*gen_shift_T1_im
[4] = {
97 static GenOpFunc
*gen_shift_T1_0
[4] = {
104 static GenOpFunc1
*gen_shift_T2_im
[4] = {
111 static GenOpFunc
*gen_shift_T2_0
[4] = {
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
,
125 static GenOpFunc
*gen_shift_T1_0_cc
[4] = {
132 static GenOpFunc
*gen_shift_T1_T0
[4] = {
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
,
146 static GenOpFunc
*gen_op_movl_TN_reg
[3][16] = {
203 static GenOpFunc
*gen_op_movl_reg_TN
[2][16] = {
242 static GenOpFunc1
*gen_op_movl_TN_im
[3] = {
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
,
254 static inline void gen_bx(DisasContext
*s
)
256 s
->is_jmp
= DISAS_UPDATE
;
260 static inline void gen_movl_TN_reg(DisasContext
*s
, int reg
, int t
)
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
);
269 gen_op_movl_TN_reg
[t
][reg
]();
273 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
275 gen_movl_TN_reg(s
, reg
, 0);
278 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
280 gen_movl_TN_reg(s
, reg
, 1);
283 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
285 gen_movl_TN_reg(s
, reg
, 2);
288 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
290 gen_op_movl_reg_TN
[t
][reg
]();
292 s
->is_jmp
= DISAS_JUMP
;
296 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
298 gen_movl_reg_TN(s
, reg
, 0);
301 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
303 gen_movl_reg_TN(s
, reg
, 1);
306 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
)
308 int val
, rm
, shift
, shiftop
;
310 if (!(insn
& (1 << 25))) {
313 if (!(insn
& (1 << 23)))
316 gen_op_addl_T1_im(val
);
320 shift
= (insn
>> 7) & 0x1f;
321 gen_movl_T2_reg(s
, rm
);
322 shiftop
= (insn
>> 5) & 3;
324 gen_shift_T2_im
[shiftop
](shift
);
325 } else if (shiftop
!= 0) {
326 gen_shift_T2_0
[shiftop
]();
328 if (!(insn
& (1 << 23)))
335 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
)
339 if (insn
& (1 << 22)) {
341 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
342 if (!(insn
& (1 << 23)))
345 gen_op_addl_T1_im(val
);
349 gen_movl_T2_reg(s
, rm
);
350 if (!(insn
& (1 << 23)))
357 static void disas_arm_insn(DisasContext
*s
)
359 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
366 if ((insn
& 0x0d70f000) == 0x0550f000)
368 else if ((insn
& 0x0e000000) == 0x0a000000) {
369 /* branch link and change to thumb (blx <offset>) */
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 */
381 gen_op_movl_T0_im(val
);
388 /* if not always execute, we generate a conditional jump to
390 gen_test_cc
[cond
^ 1]((long)s
->tb
, (long)s
->pc
);
391 s
->is_jmp
= DISAS_JUMP_NEXT
;
393 if ((insn
& 0x0f900000) == 0x03000000) {
394 if ((insn
& 0x0ff0f000) != 0x0360f000)
396 /* CPSR = immediate */
398 shift
= ((insn
>> 8) & 0xf) * 2;
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;
411 case 0x0: /* move program status register */
413 /* SPSR not accessible in user mode */
418 gen_movl_T0_reg(s
, rm
);
419 if (insn
& (1 << 19))
420 gen_op_movl_psr_T0();
423 rd
= (insn
>> 12) & 0xf;
424 gen_op_movl_T0_psr();
425 gen_movl_reg_T0(s
, rd
);
429 /* branch/exchange thumb (bx). */
430 gen_movl_T0_reg(s
, rm
);
432 } else if (op1
== 3) {
434 rd
= (insn
>> 12) & 0xf;
435 gen_movl_T0_reg(s
, rm
);
437 gen_movl_reg_T0(s
, rd
);
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
);
453 case 0x5: /* saturating add/subtract */
454 rd
= (insn
>> 12) & 0xf;
455 rn
= (insn
>> 16) & 0xf;
456 gen_movl_T0_reg(s
, rn
);
458 gen_movl_T1_reg(s
, rn
);
460 gen_op_subl_T0_T1_saturate();
462 gen_op_addl_T0_T1_saturate();
464 gen_movl_T1_reg(s
, rm
);
466 gen_op_subl_T0_T1_saturate();
468 gen_op_addl_T0_T1_saturate();
469 gen_movl_reg_T0(s
, rn
);
471 case 0x8: /* signed multiply */
475 rs
= (insn
>> 8) & 0xf;
476 rn
= (insn
>> 12) & 0xf;
477 rd
= (insn
>> 16) & 0xf;
479 /* (32 * 16) >> 16 */
480 gen_movl_T0_reg(s
, rm
);
481 gen_movl_T1_reg(s
, rs
);
483 gen_op_sarl_T1_im(16);
486 gen_op_imulw_T0_T1();
488 gen_movl_T1_reg(s
, rn
);
489 gen_op_addl_T0_T1_setq();
491 gen_movl_reg_T0(s
, rd
);
494 gen_movl_T0_reg(s
, rm
);
496 gen_op_sarl_T0_im(16);
499 gen_movl_T1_reg(s
, rs
);
501 gen_op_sarl_T1_im(16);
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
);
512 gen_movl_T1_reg(s
, rn
);
513 gen_op_addl_T0_T1_setq();
515 gen_movl_reg_T0(s
, rd
);
522 } else if (((insn
& 0x0e000000) == 0 &&
523 (insn
& 0x00000090) != 0x90) ||
524 ((insn
& 0x0e000000) == (1 << 25))) {
525 int set_cc
, logic_cc
, shiftop
;
527 op1
= (insn
>> 21) & 0xf;
528 set_cc
= (insn
>> 20) & 1;
529 logic_cc
= table_logic_cc
[op1
] & set_cc
;
531 /* data processing instruction */
532 if (insn
& (1 << 25)) {
533 /* immediate operand */
535 shift
= ((insn
>> 8) & 0xf) * 2;
537 val
= (val
>> shift
) | (val
<< (32 - shift
));
538 gen_op_movl_T1_im(val
);
539 /* XXX: is CF modified ? */
543 gen_movl_T1_reg(s
, rm
);
544 shiftop
= (insn
>> 5) & 3;
545 if (!(insn
& (1 << 4))) {
546 shift
= (insn
>> 7) & 0x1f;
549 gen_shift_T1_im_cc
[shiftop
](shift
);
551 gen_shift_T1_im
[shiftop
](shift
);
553 } else if (shiftop
!= 0) {
555 gen_shift_T1_0_cc
[shiftop
]();
557 gen_shift_T1_0
[shiftop
]();
561 rs
= (insn
>> 8) & 0xf;
562 gen_movl_T0_reg(s
, rs
);
564 gen_shift_T1_T0_cc
[shiftop
]();
566 gen_shift_T1_T0
[shiftop
]();
570 if (op1
!= 0x0f && op1
!= 0x0d) {
571 rn
= (insn
>> 16) & 0xf;
572 gen_movl_T0_reg(s
, rn
);
574 rd
= (insn
>> 12) & 0xf;
578 gen_movl_reg_T0(s
, rd
);
580 gen_op_logic_T0_cc();
584 gen_movl_reg_T0(s
, rd
);
586 gen_op_logic_T0_cc();
590 gen_op_subl_T0_T1_cc();
593 gen_movl_reg_T0(s
, rd
);
597 gen_op_rsbl_T0_T1_cc();
600 gen_movl_reg_T0(s
, rd
);
604 gen_op_addl_T0_T1_cc();
607 gen_movl_reg_T0(s
, rd
);
611 gen_op_adcl_T0_T1_cc();
614 gen_movl_reg_T0(s
, rd
);
618 gen_op_sbcl_T0_T1_cc();
621 gen_movl_reg_T0(s
, rd
);
625 gen_op_rscl_T0_T1_cc();
628 gen_movl_reg_T0(s
, rd
);
633 gen_op_logic_T0_cc();
639 gen_op_logic_T0_cc();
644 gen_op_subl_T0_T1_cc();
649 gen_op_addl_T0_T1_cc();
654 gen_movl_reg_T0(s
, rd
);
656 gen_op_logic_T0_cc();
659 gen_movl_reg_T1(s
, rd
);
661 gen_op_logic_T1_cc();
665 gen_movl_reg_T0(s
, rd
);
667 gen_op_logic_T0_cc();
672 gen_movl_reg_T1(s
, rd
);
674 gen_op_logic_T1_cc();
678 /* other instructions */
679 op1
= (insn
>> 24) & 0xf;
683 /* multiplies, extra load/stores */
684 sh
= (insn
>> 5) & 3;
687 rd
= (insn
>> 16) & 0xf;
688 rn
= (insn
>> 12) & 0xf;
689 rs
= (insn
>> 8) & 0xf;
691 if (((insn
>> 22) & 3) == 0) {
693 gen_movl_T0_reg(s
, rs
);
694 gen_movl_T1_reg(s
, rm
);
696 if (insn
& (1 << 21)) {
697 gen_movl_T1_reg(s
, rn
);
700 if (insn
& (1 << 20))
701 gen_op_logic_T0_cc();
702 gen_movl_reg_T0(s
, rd
);
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();
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
);
717 if (insn
& (1 << 20))
719 gen_movl_reg_T0(s
, rn
);
720 gen_movl_reg_T1(s
, rd
);
723 rn
= (insn
>> 16) & 0xf;
724 rd
= (insn
>> 12) & 0xf;
725 if (insn
& (1 << 23)) {
726 /* load/store exclusive */
729 /* SWP instruction */
732 gen_movl_T0_reg(s
, rm
);
733 gen_movl_T1_reg(s
, rn
);
734 if (insn
& (1 << 22)) {
739 gen_movl_reg_T0(s
, rd
);
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)) {
763 gen_movl_reg_T0(s
, rd
);
768 gen_movl_T0_reg(s
, rd
);
770 gen_op_addl_T1_im(4);
771 gen_movl_T0_reg(s
, rd
+ 1);
773 if ((insn
& (1 << 24)) || (insn
& (1 << 20)))
774 gen_op_addl_T1_im(-4);
778 gen_movl_reg_T0(s
, rd
);
779 gen_op_addl_T1_im(4);
781 gen_movl_reg_T0(s
, rd
+ 1);
782 if ((insn
& (1 << 24)) || (insn
& (1 << 20)))
783 gen_op_addl_T1_im(-4);
787 gen_movl_T0_reg(s
, rd
);
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
);
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)) {
810 if (insn
& (1 << 22))
817 gen_movl_reg_T0(s
, rd
);
820 gen_movl_T0_reg(s
, rd
);
821 if (insn
& (1 << 22))
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
); {
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
);
844 /* compute total size */
850 /* XXX: test invalid n == 0 case ? */
851 if (insn
& (1 << 23)) {
852 if (insn
& (1 << 24)) {
854 gen_op_addl_T1_im(4);
859 if (insn
& (1 << 24)) {
861 gen_op_addl_T1_im(-(n
* 4));
865 gen_op_addl_T1_im(-((n
- 1) * 4));
870 if (insn
& (1 << i
)) {
871 if (insn
& (1 << 20)) {
877 gen_movl_reg_T0(s
, i
);
881 /* special case: r15 = PC + 12 */
882 val
= (long)s
->pc
+ 8;
883 gen_op_movl_TN_im
[0](val
);
885 gen_movl_T0_reg(s
, i
);
890 /* no need to add after the last transfer */
892 gen_op_addl_T1_im(4);
895 if (insn
& (1 << 21)) {
897 if (insn
& (1 << 23)) {
898 if (insn
& (1 << 24)) {
902 gen_op_addl_T1_im(4);
905 if (insn
& (1 << 24)) {
908 gen_op_addl_T1_im(-((n
- 1) * 4));
911 gen_op_addl_T1_im(-(n
* 4));
914 gen_movl_reg_T1(s
, rn
);
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]();
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
;
937 gen_op_movl_T0_im((long)s
->pc
);
938 gen_op_movl_reg_TN
[0][15]();
940 s
->is_jmp
= DISAS_JUMP
;
944 gen_op_movl_T0_im((long)s
->pc
- 4);
945 gen_op_movl_reg_TN
[0][15]();
947 s
->is_jmp
= DISAS_JUMP
;
953 static void disas_thumb_insn(DisasContext
*s
)
955 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
962 switch (insn
>> 12) {
965 op
= (insn
>> 11) & 3;
968 rn
= (insn
>> 3) & 7;
969 gen_movl_T0_reg(s
, rn
);
970 if (insn
& (1 << 10)) {
972 gen_op_movl_T1_im((insn
>> 6) & 7);
975 rm
= (insn
>> 6) & 7;
976 gen_movl_T1_reg(s
, rm
);
979 gen_op_addl_T0_T1_cc();
981 gen_op_addl_T0_T1_cc();
982 gen_movl_reg_T0(s
, rd
);
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
);
993 /* arithmetic large immediate */
994 op
= (insn
>> 11) & 3;
995 rd
= (insn
>> 8) & 0x7;
997 gen_op_movl_T0_im(insn
& 0xff);
999 gen_movl_T0_reg(s
, rd
);
1000 gen_op_movl_T1_im(insn
& 0xff);
1004 gen_op_logic_T0_cc();
1007 gen_op_subl_T0_T1_cc();
1010 gen_op_addl_T0_T1_cc();
1013 gen_op_subl_T0_T1_cc();
1017 gen_movl_reg_T0(s
, rd
);
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();
1028 gen_movl_reg_T0(s
, rd
);
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;
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
);
1044 gen_movl_T0_reg(s
, rd
);
1045 gen_movl_T1_reg(s
, rm
);
1046 gen_op_subl_T0_T1_cc();
1048 case 2: /* mov/cpy */
1049 gen_movl_T0_reg(s
, rm
);
1050 gen_movl_reg_T0(s
, rd
);
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);
1058 gen_movl_T0_reg(s
, rm
);
1065 /* data processing register */
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 */
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
);
1084 gen_movl_T1_reg(s
, rm
);
1085 switch (insn
>> 6) {
1087 gen_op_andl_T0_T1();
1088 gen_op_logic_T0_cc();
1091 gen_op_xorl_T0_T1();
1092 gen_op_logic_T0_cc();
1095 gen_op_shll_T1_T0_cc();
1098 gen_op_shrl_T1_T0_cc();
1101 gen_op_sarl_T1_T0_cc();
1104 gen_op_adcl_T0_T1_cc();
1107 gen_op_sbcl_T0_T1_cc();
1110 gen_op_rorl_T1_T0_cc();
1113 gen_op_andl_T0_T1();
1114 gen_op_logic_T0_cc();
1117 gen_op_rsbl_T0_T1_cc();
1120 gen_op_subl_T0_T1_cc();
1124 gen_op_addl_T0_T1_cc();
1129 gen_op_logic_T0_cc();
1132 gen_op_mull_T0_T1();
1133 gen_op_logic_T0_cc();
1136 gen_op_bicl_T0_T1();
1137 gen_op_logic_T0_cc();
1141 gen_op_logic_T1_cc();
1147 gen_movl_reg_T1(s
, rd
);
1149 gen_movl_reg_T0(s
, rd
);
1154 /* load/store register offset. */
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();
1163 if (op
< 3) /* store */
1164 gen_movl_T0_reg(s
, rd
);
1177 gen_op_ldsb_T0_T1();
1183 gen_op_ldsw_T0_T1();
1186 gen_op_ldub_T0_T1();
1189 gen_op_ldsw_T0_T1();
1192 if (op
>= 3) /* load */
1193 gen_movl_reg_T0(s
, rd
);
1197 /* load/store word immediate offset */
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();
1205 if (insn
& (1 << 11)) {
1208 gen_movl_reg_T0(s
, rd
);
1211 gen_movl_T0_reg(s
, rd
);
1217 /* load/store byte immediate offset */
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();
1225 if (insn
& (1 << 11)) {
1227 gen_op_ldub_T0_T1();
1228 gen_movl_reg_T0(s
, rd
);
1231 gen_movl_T0_reg(s
, rd
);
1237 /* load/store halfword immediate offset */
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();
1245 if (insn
& (1 << 11)) {
1247 gen_op_lduw_T0_T1();
1248 gen_movl_reg_T0(s
, rd
);
1251 gen_movl_T0_reg(s
, rd
);
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();
1264 if (insn
& (1 << 11)) {
1267 gen_movl_reg_T0(s
, rd
);
1270 gen_movl_T0_reg(s
, rd
);
1276 /* add to high reg */
1277 rd
= (insn
>> 8) & 7;
1278 if (insn
& (1 << 11))
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
);
1291 op
= (insn
>> 8) & 0xf;
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);
1304 case 4: case 5: case 0xc: case 0xd:
1306 gen_movl_T1_reg(s
, 13);
1307 if (insn
& (1 << 11))
1311 gen_op_movl_T2_im(val
);
1312 for (i
= 0; i
< 8; i
++) {
1313 if (insn
& (1 << i
)) {
1314 if (insn
& (1 << 11)) {
1317 gen_movl_reg_T0(s
, i
);
1320 gen_movl_T0_reg(s
, i
);
1323 /* move to the next address */
1324 gen_op_addl_T1_T2();
1327 if (insn
& (1 << 8)) {
1328 if (insn
& (1 << 11)) {
1331 /* don't set the pc until the rest of the instruction
1335 gen_movl_T0_reg(s
, 14);
1338 gen_op_addl_T1_T2();
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)
1354 /* load/store multiple */
1355 rn
= (insn
>> 8) & 0x7;
1356 gen_movl_T1_reg(s
, rn
);
1357 gen_op_movl_T2_im(4);
1359 for (i
= 0; i
< 8; i
++) {
1360 if (insn
& (1 << i
)) {
1361 /* advance to the next address */
1363 gen_op_addl_T1_T2();
1366 if (insn
& (1 << 11)) {
1369 gen_movl_reg_T0(s
, i
);
1372 gen_movl_T0_reg(s
, i
);
1380 /* conditional branch or swi */
1381 cond
= (insn
>> 8) & 0xf;
1387 gen_op_movl_T0_im((long)s
->pc
| 1);
1388 /* Don't set r15. */
1389 gen_op_movl_reg_TN
[0][15]();
1391 s
->is_jmp
= DISAS_JUMP
;
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);
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
;
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
;
1419 /* branch and link [and switch to arm] */
1420 offset
= ((int32_t)insn
<< 21) >> 10;
1422 offset
|= insn
& 0x7ff;
1424 val
= (uint32_t)s
->pc
+ 2;
1425 gen_op_movl_T1_im(val
| 1);
1426 gen_movl_reg_T1(s
, 14);
1429 if (insn
& (1 << 11)) {
1431 gen_op_jmp((long)s
->tb
, val
);
1432 s
->is_jmp
= DISAS_TB_JUMP
;
1435 gen_op_movl_T0_im(val
);
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
;
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
,
1454 DisasContext dc1
, *dc
= &dc1
;
1455 uint16_t *gen_opc_end
;
1457 target_ulong pc_start
;
1459 /* generate intermediate code */
1464 gen_opc_ptr
= gen_opc_buf
;
1465 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
1466 gen_opparam_ptr
= gen_opparam_buf
;
1468 dc
->is_jmp
= DISAS_NEXT
;
1473 j
= gen_opc_ptr
- gen_opc_buf
;
1477 gen_opc_instr_start
[lj
++] = 0;
1479 gen_opc_pc
[lj
] = dc
->pc
;
1480 gen_opc_instr_start
[lj
] = 1;
1483 disas_thumb_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
:
1491 gen_op_jmp((long)dc
->tb
, (long)dc
->pc
);
1496 /* indicate that the hash table must be used to find the next TB */
1501 /* nothing more to generate */
1504 *gen_opc_ptr
= INDEX_op_end
;
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");
1520 tb
->size
= dc
->pc
- pc_start
;
1524 int gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
1526 return gen_intermediate_code_internal(env
, tb
, 0);
1529 int gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
1531 return gen_intermediate_code_internal(env
, tb
, 1);
1534 CPUARMState
*cpu_arm_init(void)
1540 env
= malloc(sizeof(CPUARMState
));
1543 memset(env
, 0, sizeof(CPUARMState
));
1544 cpu_single_env
= env
;
1548 void cpu_arm_close(CPUARMState
*env
)
1553 void cpu_dump_state(CPUState
*env
, FILE *f
,
1554 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
1560 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
1562 cpu_fprintf(f
, "\n");
1564 cpu_fprintf(f
, " ");
1566 cpu_fprintf(f
, "PSR=%08x %c%c%c%c\n",
1568 env
->cpsr
& (1 << 31) ? 'N' : '-',
1569 env
->cpsr
& (1 << 30) ? 'Z' : '-',
1570 env
->cpsr
& (1 << 29) ? 'C' : '-',
1571 env
->cpsr
& (1 << 28) ? 'V' : '-');
1574 target_ulong
cpu_get_phys_page_debug(CPUState
*env
, target_ulong addr
)