diff options
author | Jan Beulich <jbeulich@suse.com> | 2013-09-20 11:03:12 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2013-09-20 11:03:12 +0200 |
commit | bc6c4576616ef9cf62667a5fb315cd984499d51c (patch) | |
tree | 05dba9af581130f3634d1cf18e37999f25502bdf /xen | |
parent | cbad67c5d291a3428bed341909e22953ea0d80df (diff) | |
download | xen-bc6c4576616ef9cf62667a5fb315cd984499d51c.tar.gz xen-bc6c4576616ef9cf62667a5fb315cd984499d51c.tar.bz2 xen-bc6c4576616ef9cf62667a5fb315cd984499d51c.zip |
x86_emulate: MOVSXD must read source operand just once
... for the case of accessing MMIO.
Also streamline the ARPL emulation a little, and add tests for both
instructions (the MOVSXD one requires a few other adjustments, as we
now need to run in a mode where the emulator's mode_64bit() returns
true).
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen')
-rw-r--r-- | xen/arch/x86/x86_emulate/x86_emulate.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 8794b8219f..e8cde124bd 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -92,7 +92,7 @@ static uint8_t opcode_table[256] = { ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, /* 0x60 - 0x67 */ - ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcMem16|ModRM|Mov, + ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcNone|ModRM|Mov, 0, 0, 0, 0, /* 0x68 - 0x6F */ ImplicitOps|Mov, DstReg|SrcImm|ModRM|Mov, @@ -2021,9 +2021,9 @@ x86_emulate( if ( mode_64bit() ) { /* movsxd */ - if ( src.type == OP_REG ) - src.val = *(int32_t *)src.reg; - else if ( (rc = read_ulong(src.mem.seg, src.mem.off, + if ( ea.type == OP_REG ) + src.val = *ea.reg; + else if ( (rc = read_ulong(ea.mem.seg, ea.mem.off, &src.val, 4, ctxt, ops)) ) goto done; dst.val = (int32_t)src.val; @@ -2031,14 +2031,25 @@ x86_emulate( else { /* arpl */ - uint16_t src_val = dst.val; - dst = src; - _regs.eflags &= ~EFLG_ZF; - _regs.eflags |= ((src_val & 3) > (dst.val & 3)) ? EFLG_ZF : 0; - if ( _regs.eflags & EFLG_ZF ) - dst.val = (dst.val & ~3) | (src_val & 3); + unsigned int src_rpl = dst.val & 3; + + dst = ea; + dst.bytes = 2; + if ( dst.type == OP_REG ) + dst.val = *dst.reg; + else if ( (rc = read_ulong(dst.mem.seg, dst.mem.off, + &dst.val, 2, ctxt, ops)) ) + goto done; + if ( src_rpl > (dst.val & 3) ) + { + _regs.eflags |= EFLG_ZF; + dst.val = (dst.val & ~3) | src_rpl; + } else + { + _regs.eflags &= ~EFLG_ZF; dst.type = OP_NONE; + } generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1); } break; |