# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID e4bb22422b50871e26120d39b5667c9091d49f62
# Parent d37b210bb8a7fc3154c72adb6b673f47d57864c4
[XEN] Clean up EA computation in emulator.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/x86_emulate.c | 41 +++++++++++++++++++++--------------------
1 files changed, 21 insertions(+), 20 deletions(-)
diff -r d37b210bb8a7 -r e4bb22422b50 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Sun Nov 26 13:37:27 2006 +0000
+++ b/xen/arch/x86/x86_emulate.c Sun Nov 26 13:52:48 2006 +0000
@@ -379,9 +379,11 @@ do{ __asm__ __volatile__ (
/* Access/update address held in a register, based on addressing mode. */
#define register_address(sel, reg) \
+({ unsigned long __reg = (reg); \
(((mode == X86EMUL_MODE_REAL) ? ((unsigned long)(sel) << 4) : 0) + \
- ((ad_bytes == sizeof(unsigned long)) ? (reg) : \
- ((reg) & ((1UL << (ad_bytes << 3)) - 1))))
+ ((ad_bytes == sizeof(unsigned long)) ? __reg : \
+ (__reg & ((1UL << (ad_bytes << 3)) - 1)))); \
+})
#define register_address_increment(reg, inc) \
do { \
int _inc = (inc); /* signed type ensures sign extension to long */ \
@@ -399,7 +401,7 @@ do {
* effective address it is okay for us to fail the emulation.
*/
#define page_boundary_test() do { \
- if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 3) != 0) ) \
+ if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 7) != 0) ) \
goto bad_ea; \
} while ( 0 )
@@ -448,17 +450,17 @@ x86_emulate_memop(
struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops)
{
+ /* Shadow copy of register state. Committed on successful emulation. */
+ struct cpu_user_regs _regs = *ctxt->regs;
+
uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
- uint16_t *seg = NULL; /* override segment */
+ uint16_t *seg = &_regs.ds; /* override segment */
unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i;
int rc = 0;
struct operand src, dst;
unsigned long ea = 0, cr2 = ctxt->cr2;
int mode = ctxt->mode;
-
- /* Shadow copy of register state. Committed on successful emulation. */
- struct cpu_user_regs _regs = *ctxt->regs;
/*
* We do not emulate faults on instruction fetch. We assume that the
@@ -592,7 +594,6 @@ x86_emulate_memop(
case 1: ea += insn_fetch(uint8_t); break;
case 2: ea += insn_fetch(uint16_t); break;
}
- ea = (uint16_t)ea;
}
else
{
@@ -638,10 +639,9 @@ x86_emulate_memop(
case 1: ea += insn_fetch(uint8_t); break;
case 2: ea += insn_fetch(uint32_t); break;
}
- if ( ad_bytes == 4 )
- ea = (uint32_t)ea;
- }
-
+ }
+
+ ea = register_address(*seg, ea);
page_boundary_test();
}
@@ -809,12 +809,14 @@ x86_emulate_memop(
case 0xa0 ... 0xa1: /* mov */
dst.ptr = (unsigned long *)&_regs.eax;
dst.val = src.val;
- ea = _insn_fetch(ad_bytes); /* src effective address */
+ /* Source EA is not encoded via ModRM. */
+ ea = register_address(*seg, _insn_fetch(ad_bytes));
page_boundary_test();
break;
case 0xa2 ... 0xa3: /* mov */
dst.val = (unsigned long)_regs.eax;
- ea = _insn_fetch(ad_bytes); /* dst effective address */
+ /* Destination EA is not encoded via ModRM. */
+ ea = register_address(*seg, _insn_fetch(ad_bytes));
page_boundary_test();
break;
case 0x88 ... 0x8b: /* mov */
@@ -991,11 +993,10 @@ x86_emulate_memop(
{
/* Write fault: destination is special memory. */
dst.ptr = (unsigned long *)cr2;
- if ( (rc = ops->read_std(register_address(seg ? *seg : _regs.ds,
- _regs.esi),
+ if ( (rc = ops->read_std(register_address(*seg, _regs.esi),
&dst.val, dst.bytes, ctxt)) != 0 )
goto done;
- ea = _regs.edi & ((1UL << (ad_bytes*8)) - 1UL);
+ ea = register_address(_regs.es, _regs.edi);
}
else
{
@@ -1004,7 +1005,7 @@ x86_emulate_memop(
if ( (rc = ops->read_emulated(cr2, &dst.val,
dst.bytes, ctxt)) != 0 )
goto done;
- ea = _regs.esi & ((1UL << (ad_bytes*8)) - 1UL);
+ ea = register_address(*seg, _regs.esi);
}
register_address_increment(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
@@ -1019,7 +1020,7 @@ x86_emulate_memop(
dst.val = _regs.eax;
register_address_increment(
_regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
- ea = _regs.edi & ((1UL << (ad_bytes*8)) - 1UL);
+ ea = register_address(_regs.es, _regs.edi);
page_boundary_test();
break;
case 0xac ... 0xad: /* lods */
@@ -1030,7 +1031,7 @@ x86_emulate_memop(
goto done;
register_address_increment(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
- ea = _regs.esi & ((1UL << (ad_bytes*8)) - 1UL);
+ ea = register_address(*seg, _regs.esi);
page_boundary_test();
break;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|