diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2007-09-18 05:27:19 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:47 -0500 |
commit | 8b4caf6650808024c37ec4b29cf81b308af998b1 (patch) | |
tree | 2179c0830c938ebfdbc3baa4b7c2eee4dc81a7ae /drivers/kvm/x86_emulate.c | |
parent | e4e03deda83b1f2fc37ccbfc1eef27e86e8ed4e9 (diff) |
KVM: x86 emulator: move all decoding process to function x86_decode_insn()
Split the decoding process into a new function x86_decode_insn().
Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index d7026cb8fc70..540589c5d427 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -517,20 +517,16 @@ static int test_cc(unsigned int condition, unsigned int flags) | |||
517 | } | 517 | } |
518 | 518 | ||
519 | int | 519 | int |
520 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 520 | x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
521 | { | 521 | { |
522 | struct decode_cache *c = &ctxt->decode; | 522 | struct decode_cache *c = &ctxt->decode; |
523 | u8 sib, rex_prefix = 0; | 523 | u8 sib, rex_prefix = 0; |
524 | unsigned int i; | 524 | unsigned int i; |
525 | int rc = 0; | 525 | int rc = 0; |
526 | unsigned long cr2 = ctxt->cr2; | ||
527 | int mode = ctxt->mode; | 526 | int mode = ctxt->mode; |
528 | int index_reg = 0, base_reg = 0, scale, rip_relative = 0; | 527 | int index_reg = 0, base_reg = 0, scale, rip_relative = 0; |
529 | int no_wb = 0; | ||
530 | u64 msr_data; | ||
531 | 528 | ||
532 | /* Shadow copy of register state. Committed on successful emulation. */ | 529 | /* Shadow copy of register state. Committed on successful emulation. */ |
533 | unsigned long _eflags = ctxt->eflags; | ||
534 | 530 | ||
535 | memset(c, 0, sizeof(struct decode_cache)); | 531 | memset(c, 0, sizeof(struct decode_cache)); |
536 | c->eip = ctxt->vcpu->rip; | 532 | c->eip = ctxt->vcpu->rip; |
@@ -622,8 +618,10 @@ done_prefixes: | |||
622 | } | 618 | } |
623 | 619 | ||
624 | /* Unrecognised? */ | 620 | /* Unrecognised? */ |
625 | if (c->d == 0) | 621 | if (c->d == 0) { |
626 | goto cannot_emulate; | 622 | DPRINTF("Cannot emulate %02x\n", c->b); |
623 | return -1; | ||
624 | } | ||
627 | } | 625 | } |
628 | 626 | ||
629 | /* ModRM and SIB bytes. */ | 627 | /* ModRM and SIB bytes. */ |
@@ -776,7 +774,6 @@ done_prefixes: | |||
776 | } | 774 | } |
777 | if (c->ad_bytes != 8) | 775 | if (c->ad_bytes != 8) |
778 | c->modrm_ea = (u32)c->modrm_ea; | 776 | c->modrm_ea = (u32)c->modrm_ea; |
779 | cr2 = c->modrm_ea; | ||
780 | modrm_done: | 777 | modrm_done: |
781 | ; | 778 | ; |
782 | } | 779 | } |
@@ -838,13 +835,6 @@ done_prefixes: | |||
838 | break; | 835 | break; |
839 | } | 836 | } |
840 | c->src.type = OP_MEM; | 837 | c->src.type = OP_MEM; |
841 | c->src.ptr = (unsigned long *)cr2; | ||
842 | c->src.val = 0; | ||
843 | if ((rc = ops->read_emulated((unsigned long)c->src.ptr, | ||
844 | &c->src.val, | ||
845 | c->src.bytes, ctxt->vcpu)) != 0) | ||
846 | goto done; | ||
847 | c->src.orig_val = c->src.val; | ||
848 | break; | 838 | break; |
849 | case SrcImm: | 839 | case SrcImm: |
850 | c->src.type = OP_IMM; | 840 | c->src.type = OP_IMM; |
@@ -877,7 +867,7 @@ done_prefixes: | |||
877 | switch (c->d & DstMask) { | 867 | switch (c->d & DstMask) { |
878 | case ImplicitOps: | 868 | case ImplicitOps: |
879 | /* Special instructions do their own operand decoding. */ | 869 | /* Special instructions do their own operand decoding. */ |
880 | goto special_insn; | 870 | return 0; |
881 | case DstReg: | 871 | case DstReg: |
882 | c->dst.type = OP_REG; | 872 | c->dst.type = OP_REG; |
883 | if ((c->d & ByteOp) | 873 | if ((c->d & ByteOp) |
@@ -905,14 +895,54 @@ done_prefixes: | |||
905 | } | 895 | } |
906 | break; | 896 | break; |
907 | case DstMem: | 897 | case DstMem: |
908 | c->dst.type = OP_MEM; | ||
909 | c->dst.ptr = (unsigned long *)cr2; | ||
910 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | ||
911 | c->dst.val = 0; | ||
912 | if ((c->d & ModRM) && c->modrm_mod == 3) { | 898 | if ((c->d & ModRM) && c->modrm_mod == 3) { |
913 | c->dst.type = OP_REG; | 899 | c->dst.type = OP_REG; |
914 | break; | 900 | break; |
915 | } | 901 | } |
902 | c->dst.type = OP_MEM; | ||
903 | break; | ||
904 | } | ||
905 | |||
906 | done: | ||
907 | return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0; | ||
908 | } | ||
909 | |||
910 | int | ||
911 | x86_emulate_memop(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | ||
912 | { | ||
913 | unsigned long cr2 = ctxt->cr2; | ||
914 | int no_wb = 0; | ||
915 | u64 msr_data; | ||
916 | unsigned long _eflags = ctxt->eflags; | ||
917 | struct decode_cache *c = &ctxt->decode; | ||
918 | int rc; | ||
919 | |||
920 | rc = x86_decode_insn(ctxt, ops); | ||
921 | if (rc) | ||
922 | return rc; | ||
923 | |||
924 | if ((c->d & ModRM) && (c->modrm_mod != 3)) | ||
925 | cr2 = c->modrm_ea; | ||
926 | |||
927 | if (c->src.type == OP_MEM) { | ||
928 | c->src.ptr = (unsigned long *)cr2; | ||
929 | c->src.val = 0; | ||
930 | if ((rc = ops->read_emulated((unsigned long)c->src.ptr, | ||
931 | &c->src.val, | ||
932 | c->src.bytes, | ||
933 | ctxt->vcpu)) != 0) | ||
934 | goto done; | ||
935 | c->src.orig_val = c->src.val; | ||
936 | } | ||
937 | |||
938 | if ((c->d & DstMask) == ImplicitOps) | ||
939 | goto special_insn; | ||
940 | |||
941 | |||
942 | if (c->dst.type == OP_MEM) { | ||
943 | c->dst.ptr = (unsigned long *)cr2; | ||
944 | c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; | ||
945 | c->dst.val = 0; | ||
916 | if (c->d & BitOp) { | 946 | if (c->d & BitOp) { |
917 | unsigned long mask = ~(c->dst.bytes * 8 - 1); | 947 | unsigned long mask = ~(c->dst.bytes * 8 - 1); |
918 | 948 | ||
@@ -925,7 +955,6 @@ done_prefixes: | |||
925 | &c->dst.val, | 955 | &c->dst.val, |
926 | c->dst.bytes, ctxt->vcpu)) != 0)) | 956 | c->dst.bytes, ctxt->vcpu)) != 0)) |
927 | goto done; | 957 | goto done; |
928 | break; | ||
929 | } | 958 | } |
930 | c->dst.orig_val = c->dst.val; | 959 | c->dst.orig_val = c->dst.val; |
931 | 960 | ||
@@ -983,7 +1012,7 @@ done_prefixes: | |||
983 | emulate_2op_SrcV("cmp", c->src, c->dst, _eflags); | 1012 | emulate_2op_SrcV("cmp", c->src, c->dst, _eflags); |
984 | break; | 1013 | break; |
985 | case 0x63: /* movsxd */ | 1014 | case 0x63: /* movsxd */ |
986 | if (mode != X86EMUL_MODE_PROT64) | 1015 | if (ctxt->mode != X86EMUL_MODE_PROT64) |
987 | goto cannot_emulate; | 1016 | goto cannot_emulate; |
988 | c->dst.val = (s32) c->src.val; | 1017 | c->dst.val = (s32) c->src.val; |
989 | break; | 1018 | break; |
@@ -1041,7 +1070,7 @@ done_prefixes: | |||
1041 | break; | 1070 | break; |
1042 | case 0x8f: /* pop (sole member of Grp1a) */ | 1071 | case 0x8f: /* pop (sole member of Grp1a) */ |
1043 | /* 64-bit mode: POP always pops a 64-bit operand. */ | 1072 | /* 64-bit mode: POP always pops a 64-bit operand. */ |
1044 | if (mode == X86EMUL_MODE_PROT64) | 1073 | if (ctxt->mode == X86EMUL_MODE_PROT64) |
1045 | c->dst.bytes = 8; | 1074 | c->dst.bytes = 8; |
1046 | if ((rc = ops->read_std(register_address( | 1075 | if ((rc = ops->read_std(register_address( |
1047 | ctxt->ss_base, | 1076 | ctxt->ss_base, |
@@ -1152,7 +1181,7 @@ done_prefixes: | |||
1152 | break; | 1181 | break; |
1153 | case 6: /* push */ | 1182 | case 6: /* push */ |
1154 | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ | 1183 | /* 64-bit mode: PUSH always pushes a 64-bit operand. */ |
1155 | if (mode == X86EMUL_MODE_PROT64) { | 1184 | if (ctxt->mode == X86EMUL_MODE_PROT64) { |
1156 | c->dst.bytes = 8; | 1185 | c->dst.bytes = 8; |
1157 | if ((rc = ops->read_std( | 1186 | if ((rc = ops->read_std( |
1158 | (unsigned long)c->dst.ptr, | 1187 | (unsigned long)c->dst.ptr, |