aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-01 00:31:28 -0400
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:52:59 -0500
commit1c73ef66502311d9aff7fed7d7f970288329c6cb (patch)
tree1bafc99b5c6e0786670d9198fef2caf113fa820a /drivers/kvm/x86_emulate.c
parent3b6fff198c2ae3ca87ee8c9103d52ac9e8f40dd5 (diff)
KVM: x86 emulator: Hoist modrm and abs decoding into separate functions
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c337
1 files changed, 177 insertions, 160 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index b352a6c4d4a2..64888a6edc27 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -548,14 +548,182 @@ static void decode_register_operand(struct operand *op,
548 op->orig_val = op->val; 548 op->orig_val = op->val;
549} 549}
550 550
551static int decode_modrm(struct x86_emulate_ctxt *ctxt,
552 struct x86_emulate_ops *ops)
553{
554 struct decode_cache *c = &ctxt->decode;
555 u8 sib;
556 int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
557 int rc = 0;
558
559 if (c->rex_prefix) {
560 c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
561 index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
562 c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
563 }
564
565 c->modrm = insn_fetch(u8, 1, c->eip);
566 c->modrm_mod |= (c->modrm & 0xc0) >> 6;
567 c->modrm_reg |= (c->modrm & 0x38) >> 3;
568 c->modrm_rm |= (c->modrm & 0x07);
569 c->modrm_ea = 0;
570 c->use_modrm_ea = 1;
571
572 if (c->modrm_mod == 3) {
573 c->modrm_val = *(unsigned long *)
574 decode_register(c->modrm_rm, c->regs, c->d & ByteOp);
575 return rc;
576 }
577
578 if (c->ad_bytes == 2) {
579 unsigned bx = c->regs[VCPU_REGS_RBX];
580 unsigned bp = c->regs[VCPU_REGS_RBP];
581 unsigned si = c->regs[VCPU_REGS_RSI];
582 unsigned di = c->regs[VCPU_REGS_RDI];
583
584 /* 16-bit ModR/M decode. */
585 switch (c->modrm_mod) {
586 case 0:
587 if (c->modrm_rm == 6)
588 c->modrm_ea += insn_fetch(u16, 2, c->eip);
589 break;
590 case 1:
591 c->modrm_ea += insn_fetch(s8, 1, c->eip);
592 break;
593 case 2:
594 c->modrm_ea += insn_fetch(u16, 2, c->eip);
595 break;
596 }
597 switch (c->modrm_rm) {
598 case 0:
599 c->modrm_ea += bx + si;
600 break;
601 case 1:
602 c->modrm_ea += bx + di;
603 break;
604 case 2:
605 c->modrm_ea += bp + si;
606 break;
607 case 3:
608 c->modrm_ea += bp + di;
609 break;
610 case 4:
611 c->modrm_ea += si;
612 break;
613 case 5:
614 c->modrm_ea += di;
615 break;
616 case 6:
617 if (c->modrm_mod != 0)
618 c->modrm_ea += bp;
619 break;
620 case 7:
621 c->modrm_ea += bx;
622 break;
623 }
624 if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
625 (c->modrm_rm == 6 && c->modrm_mod != 0))
626 if (!c->override_base)
627 c->override_base = &ctxt->ss_base;
628 c->modrm_ea = (u16)c->modrm_ea;
629 } else {
630 /* 32/64-bit ModR/M decode. */
631 switch (c->modrm_rm) {
632 case 4:
633 case 12:
634 sib = insn_fetch(u8, 1, c->eip);
635 index_reg |= (sib >> 3) & 7;
636 base_reg |= sib & 7;
637 scale = sib >> 6;
638
639 switch (base_reg) {
640 case 5:
641 if (c->modrm_mod != 0)
642 c->modrm_ea += c->regs[base_reg];
643 else
644 c->modrm_ea +=
645 insn_fetch(s32, 4, c->eip);
646 break;
647 default:
648 c->modrm_ea += c->regs[base_reg];
649 }
650 switch (index_reg) {
651 case 4:
652 break;
653 default:
654 c->modrm_ea += c->regs[index_reg] << scale;
655 }
656 break;
657 case 5:
658 if (c->modrm_mod != 0)
659 c->modrm_ea += c->regs[c->modrm_rm];
660 else if (ctxt->mode == X86EMUL_MODE_PROT64)
661 rip_relative = 1;
662 break;
663 default:
664 c->modrm_ea += c->regs[c->modrm_rm];
665 break;
666 }
667 switch (c->modrm_mod) {
668 case 0:
669 if (c->modrm_rm == 5)
670 c->modrm_ea += insn_fetch(s32, 4, c->eip);
671 break;
672 case 1:
673 c->modrm_ea += insn_fetch(s8, 1, c->eip);
674 break;
675 case 2:
676 c->modrm_ea += insn_fetch(s32, 4, c->eip);
677 break;
678 }
679 }
680 if (rip_relative) {
681 c->modrm_ea += c->eip;
682 switch (c->d & SrcMask) {
683 case SrcImmByte:
684 c->modrm_ea += 1;
685 break;
686 case SrcImm:
687 if (c->d & ByteOp)
688 c->modrm_ea += 1;
689 else
690 if (c->op_bytes == 8)
691 c->modrm_ea += 4;
692 else
693 c->modrm_ea += c->op_bytes;
694 }
695 }
696done:
697 return rc;
698}
699
700static int decode_abs(struct x86_emulate_ctxt *ctxt,
701 struct x86_emulate_ops *ops)
702{
703 struct decode_cache *c = &ctxt->decode;
704 int rc = 0;
705
706 switch (c->ad_bytes) {
707 case 2:
708 c->modrm_ea = insn_fetch(u16, 2, c->eip);
709 break;
710 case 4:
711 c->modrm_ea = insn_fetch(u32, 4, c->eip);
712 break;
713 case 8:
714 c->modrm_ea = insn_fetch(u64, 8, c->eip);
715 break;
716 }
717done:
718 return rc;
719}
720
551int 721int
552x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) 722x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
553{ 723{
554 struct decode_cache *c = &ctxt->decode; 724 struct decode_cache *c = &ctxt->decode;
555 u8 sib;
556 int rc = 0; 725 int rc = 0;
557 int mode = ctxt->mode; 726 int mode = ctxt->mode;
558 int index_reg = 0, base_reg = 0, scale, rip_relative = 0;
559 727
560 /* Shadow copy of register state. Committed on successful emulation. */ 728 /* Shadow copy of register state. Committed on successful emulation. */
561 729
@@ -637,13 +805,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
637done_prefixes: 805done_prefixes:
638 806
639 /* REX prefix. */ 807 /* REX prefix. */
640 if (c->rex_prefix) { 808 if (c->rex_prefix)
641 if (c->rex_prefix & 8) 809 if (c->rex_prefix & 8)
642 c->op_bytes = 8; /* REX.W */ 810 c->op_bytes = 8; /* REX.W */
643 c->modrm_reg = (c->rex_prefix & 4) << 1; /* REX.R */
644 index_reg = (c->rex_prefix & 2) << 2; /* REX.X */
645 c->modrm_rm = base_reg = (c->rex_prefix & 1) << 3; /* REG.B */
646 }
647 811
648 /* Opcode byte(s). */ 812 /* Opcode byte(s). */
649 c->d = opcode_table[c->b]; 813 c->d = opcode_table[c->b];
@@ -663,159 +827,12 @@ done_prefixes:
663 } 827 }
664 828
665 /* ModRM and SIB bytes. */ 829 /* ModRM and SIB bytes. */
666 if (c->d & ModRM) { 830 if (c->d & ModRM)
667 c->modrm = insn_fetch(u8, 1, c->eip); 831 rc = decode_modrm(ctxt, ops);
668 c->modrm_mod |= (c->modrm & 0xc0) >> 6; 832 else if (c->d & MemAbs)
669 c->modrm_reg |= (c->modrm & 0x38) >> 3; 833 rc = decode_abs(ctxt, ops);
670 c->modrm_rm |= (c->modrm & 0x07); 834 if (rc)
671 c->modrm_ea = 0; 835 goto done;
672 c->use_modrm_ea = 1;
673
674 if (c->modrm_mod == 3) {
675 c->modrm_val = *(unsigned long *)
676 decode_register(c->modrm_rm, c->regs, c->d & ByteOp);
677 goto modrm_done;
678 }
679
680 if (c->ad_bytes == 2) {
681 unsigned bx = c->regs[VCPU_REGS_RBX];
682 unsigned bp = c->regs[VCPU_REGS_RBP];
683 unsigned si = c->regs[VCPU_REGS_RSI];
684 unsigned di = c->regs[VCPU_REGS_RDI];
685
686 /* 16-bit ModR/M decode. */
687 switch (c->modrm_mod) {
688 case 0:
689 if (c->modrm_rm == 6)
690 c->modrm_ea +=
691 insn_fetch(u16, 2, c->eip);
692 break;
693 case 1:
694 c->modrm_ea += insn_fetch(s8, 1, c->eip);
695 break;
696 case 2:
697 c->modrm_ea += insn_fetch(u16, 2, c->eip);
698 break;
699 }
700 switch (c->modrm_rm) {
701 case 0:
702 c->modrm_ea += bx + si;
703 break;
704 case 1:
705 c->modrm_ea += bx + di;
706 break;
707 case 2:
708 c->modrm_ea += bp + si;
709 break;
710 case 3:
711 c->modrm_ea += bp + di;
712 break;
713 case 4:
714 c->modrm_ea += si;
715 break;
716 case 5:
717 c->modrm_ea += di;
718 break;
719 case 6:
720 if (c->modrm_mod != 0)
721 c->modrm_ea += bp;
722 break;
723 case 7:
724 c->modrm_ea += bx;
725 break;
726 }
727 if (c->modrm_rm == 2 || c->modrm_rm == 3 ||
728 (c->modrm_rm == 6 && c->modrm_mod != 0))
729 if (!c->override_base)
730 c->override_base = &ctxt->ss_base;
731 c->modrm_ea = (u16)c->modrm_ea;
732 } else {
733 /* 32/64-bit ModR/M decode. */
734 switch (c->modrm_rm) {
735 case 4:
736 case 12:
737 sib = insn_fetch(u8, 1, c->eip);
738 index_reg |= (sib >> 3) & 7;
739 base_reg |= sib & 7;
740 scale = sib >> 6;
741
742 switch (base_reg) {
743 case 5:
744 if (c->modrm_mod != 0)
745 c->modrm_ea +=
746 c->regs[base_reg];
747 else
748 c->modrm_ea +=
749 insn_fetch(s32, 4, c->eip);
750 break;
751 default:
752 c->modrm_ea += c->regs[base_reg];
753 }
754 switch (index_reg) {
755 case 4:
756 break;
757 default:
758 c->modrm_ea +=
759 c->regs[index_reg] << scale;
760
761 }
762 break;
763 case 5:
764 if (c->modrm_mod != 0)
765 c->modrm_ea += c->regs[c->modrm_rm];
766 else if (mode == X86EMUL_MODE_PROT64)
767 rip_relative = 1;
768 break;
769 default:
770 c->modrm_ea += c->regs[c->modrm_rm];
771 break;
772 }
773 switch (c->modrm_mod) {
774 case 0:
775 if (c->modrm_rm == 5)
776 c->modrm_ea +=
777 insn_fetch(s32, 4, c->eip);
778 break;
779 case 1:
780 c->modrm_ea += insn_fetch(s8, 1, c->eip);
781 break;
782 case 2:
783 c->modrm_ea += insn_fetch(s32, 4, c->eip);
784 break;
785 }
786 }
787 if (rip_relative) {
788 c->modrm_ea += c->eip;
789 switch (c->d & SrcMask) {
790 case SrcImmByte:
791 c->modrm_ea += 1;
792 break;
793 case SrcImm:
794 if (c->d & ByteOp)
795 c->modrm_ea += 1;
796 else
797 if (c->op_bytes == 8)
798 c->modrm_ea += 4;
799 else
800 c->modrm_ea += c->op_bytes;
801 }
802 }
803modrm_done:
804 ;
805 } else if (c->d & MemAbs) {
806 switch (c->ad_bytes) {
807 case 2:
808 c->modrm_ea = insn_fetch(u16, 2, c->eip);
809 break;
810 case 4:
811 c->modrm_ea = insn_fetch(u32, 4, c->eip);
812 break;
813 case 8:
814 c->modrm_ea = insn_fetch(u64, 8, c->eip);
815 break;
816 }
817
818 }
819 836
820 if (!c->override_base) 837 if (!c->override_base)
821 c->override_base = &ctxt->ds_base; 838 c->override_base = &ctxt->ds_base;