diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2010-08-16 21:17:30 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:06 -0400 |
commit | 31be40b3985f09c0c89b9e28a8206df32adba842 (patch) | |
tree | e111e9c112a62f5c9225c51b17dd062ad4f7e47e /arch/x86/kvm/emulate.c | |
parent | 646bab55a278ceb1cf43b1f80d3dd468be62a421 (diff) |
KVM: x86 emulator: put register operand write back to a function
Introduce function write_register_operand() to write back the
register operand.
Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 55 |
1 files changed, 23 insertions, 32 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index f6b124fcc3fd..003713041ce6 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1020,6 +1020,25 @@ exception: | |||
1020 | return X86EMUL_PROPAGATE_FAULT; | 1020 | return X86EMUL_PROPAGATE_FAULT; |
1021 | } | 1021 | } |
1022 | 1022 | ||
1023 | static void write_register_operand(struct operand *op) | ||
1024 | { | ||
1025 | /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ | ||
1026 | switch (op->bytes) { | ||
1027 | case 1: | ||
1028 | *(u8 *)op->addr.reg = (u8)op->val; | ||
1029 | break; | ||
1030 | case 2: | ||
1031 | *(u16 *)op->addr.reg = (u16)op->val; | ||
1032 | break; | ||
1033 | case 4: | ||
1034 | *op->addr.reg = (u32)op->val; | ||
1035 | break; /* 64b: zero-extend */ | ||
1036 | case 8: | ||
1037 | *op->addr.reg = op->val; | ||
1038 | break; | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1023 | static inline int writeback(struct x86_emulate_ctxt *ctxt, | 1042 | static inline int writeback(struct x86_emulate_ctxt *ctxt, |
1024 | struct x86_emulate_ops *ops) | 1043 | struct x86_emulate_ops *ops) |
1025 | { | 1044 | { |
@@ -1029,23 +1048,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt, | |||
1029 | 1048 | ||
1030 | switch (c->dst.type) { | 1049 | switch (c->dst.type) { |
1031 | case OP_REG: | 1050 | case OP_REG: |
1032 | /* The 4-byte case *is* correct: | 1051 | write_register_operand(&c->dst); |
1033 | * in 64-bit mode we zero-extend. | ||
1034 | */ | ||
1035 | switch (c->dst.bytes) { | ||
1036 | case 1: | ||
1037 | *(u8 *)c->dst.addr.reg = (u8)c->dst.val; | ||
1038 | break; | ||
1039 | case 2: | ||
1040 | *(u16 *)c->dst.addr.reg = (u16)c->dst.val; | ||
1041 | break; | ||
1042 | case 4: | ||
1043 | *c->dst.addr.reg = (u32)c->dst.val; | ||
1044 | break; /* 64b: zero-ext */ | ||
1045 | case 8: | ||
1046 | *c->dst.addr.reg = c->dst.val; | ||
1047 | break; | ||
1048 | } | ||
1049 | break; | 1052 | break; |
1050 | case OP_MEM: | 1053 | case OP_MEM: |
1051 | if (c->lock_prefix) | 1054 | if (c->lock_prefix) |
@@ -2970,25 +2973,13 @@ special_insn: | |||
2970 | case 0x86 ... 0x87: /* xchg */ | 2973 | case 0x86 ... 0x87: /* xchg */ |
2971 | xchg: | 2974 | xchg: |
2972 | /* Write back the register source. */ | 2975 | /* Write back the register source. */ |
2973 | switch (c->dst.bytes) { | 2976 | c->src.val = c->dst.val; |
2974 | case 1: | 2977 | write_register_operand(&c->src); |
2975 | *(u8 *) c->src.addr.reg = (u8) c->dst.val; | ||
2976 | break; | ||
2977 | case 2: | ||
2978 | *(u16 *) c->src.addr.reg = (u16) c->dst.val; | ||
2979 | break; | ||
2980 | case 4: | ||
2981 | *c->src.addr.reg = (u32) c->dst.val; | ||
2982 | break; /* 64b reg: zero-extend */ | ||
2983 | case 8: | ||
2984 | *c->src.addr.reg = c->dst.val; | ||
2985 | break; | ||
2986 | } | ||
2987 | /* | 2978 | /* |
2988 | * Write back the memory destination with implicit LOCK | 2979 | * Write back the memory destination with implicit LOCK |
2989 | * prefix. | 2980 | * prefix. |
2990 | */ | 2981 | */ |
2991 | c->dst.val = c->src.val; | 2982 | c->dst.val = c->src.orig_val; |
2992 | c->lock_prefix = 1; | 2983 | c->lock_prefix = 1; |
2993 | break; | 2984 | break; |
2994 | case 0x88 ... 0x8b: /* mov */ | 2985 | case 0x88 ... 0x8b: /* mov */ |