34 |
struct TranslationBlock *tb; |
struct TranslationBlock *tb; |
35 |
} DisasContext; |
} DisasContext; |
36 |
|
|
37 |
|
#define DISAS_JUMP_NEXT 4 |
38 |
|
|
39 |
/* XXX: move that elsewhere */ |
/* XXX: move that elsewhere */ |
40 |
static uint16_t *gen_opc_ptr; |
static uint16_t *gen_opc_ptr; |
41 |
static uint32_t *gen_opparam_ptr; |
static uint32_t *gen_opparam_ptr; |
335 |
/* if not always execute, we generate a conditional jump to |
/* if not always execute, we generate a conditional jump to |
336 |
next instruction */ |
next instruction */ |
337 |
gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc); |
338 |
s->is_jmp = 1; |
s->is_jmp = DISAS_JUMP_NEXT; |
339 |
} |
} |
340 |
if ((insn & 0x0c000000) == 0 && |
if (((insn & 0x0e000000) == 0 && |
341 |
(insn & 0x00000090) != 0x90) { |
(insn & 0x00000090) != 0x90) || |
342 |
|
((insn & 0x0e000000) == (1 << 25))) { |
343 |
int set_cc, logic_cc, shiftop; |
int set_cc, logic_cc, shiftop; |
344 |
|
|
345 |
op1 = (insn >> 21) & 0xf; |
op1 = (insn >> 21) & 0xf; |
370 |
} |
} |
371 |
} |
} |
372 |
} else { |
} else { |
373 |
rs = (insn >> 16) & 0xf; |
rs = (insn >> 8) & 0xf; |
374 |
gen_movl_T0_reg(s, rs); |
gen_movl_T0_reg(s, rs); |
375 |
if (logic_cc) { |
if (logic_cc) { |
376 |
gen_shift_T1_T0_cc[shiftop](); |
gen_shift_T1_T0_cc[shiftop](); |
388 |
case 0x00: |
case 0x00: |
389 |
gen_op_andl_T0_T1(); |
gen_op_andl_T0_T1(); |
390 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
391 |
|
if (logic_cc) |
392 |
|
gen_op_logic_T0_cc(); |
393 |
break; |
break; |
394 |
case 0x01: |
case 0x01: |
395 |
gen_op_xorl_T0_T1(); |
gen_op_xorl_T0_T1(); |
396 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
397 |
|
if (logic_cc) |
398 |
|
gen_op_logic_T0_cc(); |
399 |
break; |
break; |
400 |
case 0x02: |
case 0x02: |
401 |
if (set_cc) |
if (set_cc) |
442 |
case 0x08: |
case 0x08: |
443 |
if (set_cc) { |
if (set_cc) { |
444 |
gen_op_andl_T0_T1(); |
gen_op_andl_T0_T1(); |
445 |
|
gen_op_logic_T0_cc(); |
446 |
} |
} |
447 |
break; |
break; |
448 |
case 0x09: |
case 0x09: |
449 |
if (set_cc) { |
if (set_cc) { |
450 |
gen_op_xorl_T0_T1(); |
gen_op_xorl_T0_T1(); |
451 |
|
gen_op_logic_T0_cc(); |
452 |
} |
} |
453 |
break; |
break; |
454 |
case 0x0a: |
case 0x0a: |
464 |
case 0x0c: |
case 0x0c: |
465 |
gen_op_orl_T0_T1(); |
gen_op_orl_T0_T1(); |
466 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
467 |
|
if (logic_cc) |
468 |
|
gen_op_logic_T0_cc(); |
469 |
break; |
break; |
470 |
case 0x0d: |
case 0x0d: |
471 |
gen_movl_reg_T1(s, rd); |
gen_movl_reg_T1(s, rd); |
472 |
|
if (logic_cc) |
473 |
|
gen_op_logic_T1_cc(); |
474 |
break; |
break; |
475 |
case 0x0e: |
case 0x0e: |
476 |
gen_op_bicl_T0_T1(); |
gen_op_bicl_T0_T1(); |
477 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
478 |
|
if (logic_cc) |
479 |
|
gen_op_logic_T0_cc(); |
480 |
break; |
break; |
481 |
default: |
default: |
482 |
case 0x0f: |
case 0x0f: |
483 |
gen_op_notl_T1(); |
gen_op_notl_T1(); |
484 |
gen_movl_reg_T1(s, rd); |
gen_movl_reg_T1(s, rd); |
485 |
|
if (logic_cc) |
486 |
|
gen_op_logic_T1_cc(); |
487 |
break; |
break; |
488 |
} |
} |
|
if (logic_cc) |
|
|
gen_op_logic_cc(); |
|
489 |
} else { |
} else { |
490 |
/* other instructions */ |
/* other instructions */ |
491 |
op1 = (insn >> 24) & 0xf; |
op1 = (insn >> 24) & 0xf; |
509 |
gen_op_addl_T0_T1(); |
gen_op_addl_T0_T1(); |
510 |
} |
} |
511 |
if (insn & (1 << 20)) |
if (insn & (1 << 20)) |
512 |
gen_op_logic_cc(); |
gen_op_logic_T0_cc(); |
513 |
gen_movl_reg_T0(s, rd); |
gen_movl_reg_T0(s, rd); |
514 |
} else { |
} else { |
515 |
/* 64 bit mul */ |
/* 64 bit mul */ |
566 |
/* store */ |
/* store */ |
567 |
gen_op_stw_T0_T1(); |
gen_op_stw_T0_T1(); |
568 |
} |
} |
569 |
if (!(insn & (1 << 24))) |
if (!(insn & (1 << 24))) { |
570 |
gen_add_datah_offset(s, insn); |
gen_add_datah_offset(s, insn); |
|
if (insn & (1 << 21)) |
|
571 |
gen_movl_reg_T1(s, rn); |
gen_movl_reg_T1(s, rn); |
572 |
|
} else if (insn & (1 << 21)) { |
573 |
|
gen_movl_reg_T1(s, rn); |
574 |
|
} |
575 |
} |
} |
576 |
break; |
break; |
577 |
case 0x4: |
case 0x4: |
599 |
else |
else |
600 |
gen_op_stl_T0_T1(); |
gen_op_stl_T0_T1(); |
601 |
} |
} |
602 |
if (!(insn & (1 << 24))) |
if (!(insn & (1 << 24))) { |
603 |
gen_add_data_offset(s, insn); |
gen_add_data_offset(s, insn); |
|
if (insn & (1 << 21)) |
|
604 |
gen_movl_reg_T1(s, rn); |
gen_movl_reg_T1(s, rn); |
605 |
|
} else if (insn & (1 << 21)) |
606 |
|
gen_movl_reg_T1(s, rn); { |
607 |
|
} |
608 |
break; |
break; |
609 |
case 0x08: |
case 0x08: |
610 |
case 0x09: |
case 0x09: |
611 |
/* load/store multiple words */ |
{ |
612 |
if (insn & (1 << 22)) |
int j, n; |
613 |
goto illegal_op; /* only usable in supervisor mode */ |
/* load/store multiple words */ |
614 |
rn = (insn >> 16) & 0xf; |
/* XXX: store correct base if write back */ |
615 |
gen_movl_T1_reg(s, rn); |
if (insn & (1 << 22)) |
616 |
val = 4; |
goto illegal_op; /* only usable in supervisor mode */ |
617 |
if (!(insn & (1 << 23))) |
rn = (insn >> 16) & 0xf; |
618 |
val = -val; |
gen_movl_T1_reg(s, rn); |
619 |
for(i=0;i<16;i++) { |
|
620 |
if (insn & (1 << i)) { |
/* compute total size */ |
621 |
if (insn & (1 << 24)) |
n = 0; |
622 |
gen_op_addl_T1_im(val); |
for(i=0;i<16;i++) { |
623 |
if (insn & (1 << 20)) { |
if (insn & (1 << i)) |
624 |
/* load */ |
n++; |
625 |
gen_op_ldl_T0_T1(); |
} |
626 |
gen_movl_reg_T0(s, i); |
/* XXX: test invalid n == 0 case ? */ |
627 |
|
if (insn & (1 << 23)) { |
628 |
|
if (insn & (1 << 24)) { |
629 |
|
/* pre increment */ |
630 |
|
gen_op_addl_T1_im(4); |
631 |
} else { |
} else { |
632 |
/* store */ |
/* post increment */ |
633 |
gen_movl_T0_reg(s, i); |
} |
634 |
gen_op_stl_T0_T1(); |
} else { |
635 |
|
if (insn & (1 << 24)) { |
636 |
|
/* pre decrement */ |
637 |
|
gen_op_addl_T1_im(-(n * 4)); |
638 |
|
} else { |
639 |
|
/* post decrement */ |
640 |
|
if (n != 1) |
641 |
|
gen_op_addl_T1_im(-((n - 1) * 4)); |
642 |
|
} |
643 |
|
} |
644 |
|
j = 0; |
645 |
|
for(i=0;i<16;i++) { |
646 |
|
if (insn & (1 << i)) { |
647 |
|
if (insn & (1 << 20)) { |
648 |
|
/* load */ |
649 |
|
gen_op_ldl_T0_T1(); |
650 |
|
gen_movl_reg_T0(s, i); |
651 |
|
} else { |
652 |
|
/* store */ |
653 |
|
if (i == 15) { |
654 |
|
/* special case: r15 = PC + 12 */ |
655 |
|
val = (long)s->pc + 8; |
656 |
|
gen_op_movl_TN_im[0](val); |
657 |
|
} else { |
658 |
|
gen_movl_T0_reg(s, i); |
659 |
|
} |
660 |
|
gen_op_stl_T0_T1(); |
661 |
|
} |
662 |
|
j++; |
663 |
|
/* no need to add after the last transfer */ |
664 |
|
if (j != n) |
665 |
|
gen_op_addl_T1_im(4); |
666 |
} |
} |
667 |
if (!(insn & (1 << 24))) |
} |
668 |
gen_op_addl_T1_im(val); |
if (insn & (1 << 21)) { |
669 |
|
/* write back */ |
670 |
|
if (insn & (1 << 23)) { |
671 |
|
if (insn & (1 << 24)) { |
672 |
|
/* pre increment */ |
673 |
|
} else { |
674 |
|
/* post increment */ |
675 |
|
gen_op_addl_T1_im(4); |
676 |
|
} |
677 |
|
} else { |
678 |
|
if (insn & (1 << 24)) { |
679 |
|
/* pre decrement */ |
680 |
|
if (n != 1) |
681 |
|
gen_op_addl_T1_im(-((n - 1) * 4)); |
682 |
|
} else { |
683 |
|
/* post decrement */ |
684 |
|
gen_op_addl_T1_im(-(n * 4)); |
685 |
|
} |
686 |
|
} |
687 |
|
gen_movl_reg_T1(s, rn); |
688 |
} |
} |
689 |
} |
} |
|
if (insn & (1 << 21)) |
|
|
gen_movl_reg_T1(s, rn); |
|
690 |
break; |
break; |
691 |
case 0xa: |
case 0xa: |
692 |
case 0xb: |
case 0xb: |
712 |
gen_op_swi(); |
gen_op_swi(); |
713 |
s->is_jmp = DISAS_JUMP; |
s->is_jmp = DISAS_JUMP; |
714 |
break; |
break; |
715 |
|
case 0xc: |
716 |
|
case 0xd: |
717 |
|
rd = (insn >> 12) & 0x7; |
718 |
|
rn = (insn >> 16) & 0xf; |
719 |
|
gen_movl_T1_reg(s, rn); |
720 |
|
val = (insn) & 0xff; |
721 |
|
if (!(insn & (1 << 23))) |
722 |
|
val = -val; |
723 |
|
switch((insn >> 8) & 0xf) { |
724 |
|
case 0x1: |
725 |
|
/* load/store */ |
726 |
|
if ((insn & (1 << 24))) |
727 |
|
gen_op_addl_T1_im(val); |
728 |
|
/* XXX: do it */ |
729 |
|
if (!(insn & (1 << 24))) |
730 |
|
gen_op_addl_T1_im(val); |
731 |
|
if (insn & (1 << 21)) |
732 |
|
gen_movl_reg_T1(s, rn); |
733 |
|
break; |
734 |
|
case 0x2: |
735 |
|
{ |
736 |
|
int n, i; |
737 |
|
/* load store multiple */ |
738 |
|
if ((insn & (1 << 24))) |
739 |
|
gen_op_addl_T1_im(val); |
740 |
|
switch(insn & 0x00408000) { |
741 |
|
case 0x00008000: n = 1; break; |
742 |
|
case 0x00400000: n = 2; break; |
743 |
|
case 0x00408000: n = 3; break; |
744 |
|
default: n = 4; break; |
745 |
|
} |
746 |
|
for(i = 0;i < n; i++) { |
747 |
|
/* XXX: do it */ |
748 |
|
} |
749 |
|
if (!(insn & (1 << 24))) |
750 |
|
gen_op_addl_T1_im(val); |
751 |
|
if (insn & (1 << 21)) |
752 |
|
gen_movl_reg_T1(s, rn); |
753 |
|
} |
754 |
|
break; |
755 |
|
default: |
756 |
|
goto illegal_op; |
757 |
|
} |
758 |
|
break; |
759 |
|
case 0x0e: |
760 |
|
/* float ops */ |
761 |
|
/* XXX: do it */ |
762 |
|
switch((insn >> 20) & 0xf) { |
763 |
|
case 0x2: /* wfs */ |
764 |
|
break; |
765 |
|
case 0x3: /* rfs */ |
766 |
|
break; |
767 |
|
case 0x4: /* wfc */ |
768 |
|
break; |
769 |
|
case 0x5: /* rfc */ |
770 |
|
break; |
771 |
|
default: |
772 |
|
goto illegal_op; |
773 |
|
} |
774 |
|
break; |
775 |
default: |
default: |
776 |
illegal_op: |
illegal_op: |
777 |
gen_op_movl_T0_im((long)s->pc - 4); |
gen_op_movl_T0_im((long)s->pc - 4); |
819 |
disas_arm_insn(dc); |
disas_arm_insn(dc); |
820 |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && |
821 |
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); |
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); |
822 |
/* we must store the eflags state if it is not already done */ |
switch(dc->is_jmp) { |
823 |
if (dc->is_jmp != DISAS_TB_JUMP && |
case DISAS_JUMP_NEXT: |
824 |
dc->is_jmp != DISAS_JUMP) { |
case DISAS_NEXT: |
825 |
gen_op_movl_T0_im((long)dc->pc - 4); |
gen_op_jmp((long)dc->tb, (long)dc->pc); |
826 |
gen_op_movl_reg_TN[0][15](); |
break; |
827 |
} |
default: |
828 |
if (dc->is_jmp != DISAS_TB_JUMP) { |
case DISAS_JUMP: |
829 |
/* indicate that the hash table must be used to find the next TB */ |
/* indicate that the hash table must be used to find the next TB */ |
830 |
gen_op_movl_T0_0(); |
gen_op_movl_T0_0(); |
831 |
|
break; |
832 |
|
case DISAS_TB_JUMP: |
833 |
|
/* nothing more to generate */ |
834 |
|
break; |
835 |
} |
} |
836 |
*gen_opc_ptr = INDEX_op_end; |
*gen_opc_ptr = INDEX_op_end; |
837 |
|
|
891 |
else |
else |
892 |
fprintf(f, " "); |
fprintf(f, " "); |
893 |
} |
} |
894 |
fprintf(f, "CPSR=%08x", env->cpsr); |
fprintf(f, "PSR=%08x %c%c%c%c\n", |
895 |
|
env->cpsr, |
896 |
|
env->cpsr & (1 << 31) ? 'N' : '-', |
897 |
|
env->cpsr & (1 << 30) ? 'Z' : '-', |
898 |
|
env->cpsr & (1 << 29) ? 'C' : '-', |
899 |
|
env->cpsr & (1 << 28) ? 'V' : '-'); |
900 |
} |
} |