ia64/xen-unstable
changeset 12572:e4bb22422b50
[XEN] Clean up EA computation in emulator.
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author | kaf24@localhost.localdomain |
---|---|
date | Sun Nov 26 13:52:48 2006 +0000 (2006-11-26) |
parents | d37b210bb8a7 |
children | 91951de7592c |
files | xen/arch/x86/x86_emulate.c |
line diff
1.1 --- a/xen/arch/x86/x86_emulate.c Sun Nov 26 13:37:27 2006 +0000 1.2 +++ b/xen/arch/x86/x86_emulate.c Sun Nov 26 13:52:48 2006 +0000 1.3 @@ -379,9 +379,11 @@ do{ __asm__ __volatile__ ( 1.4 1.5 /* Access/update address held in a register, based on addressing mode. */ 1.6 #define register_address(sel, reg) \ 1.7 +({ unsigned long __reg = (reg); \ 1.8 (((mode == X86EMUL_MODE_REAL) ? ((unsigned long)(sel) << 4) : 0) + \ 1.9 - ((ad_bytes == sizeof(unsigned long)) ? (reg) : \ 1.10 - ((reg) & ((1UL << (ad_bytes << 3)) - 1)))) 1.11 + ((ad_bytes == sizeof(unsigned long)) ? __reg : \ 1.12 + (__reg & ((1UL << (ad_bytes << 3)) - 1)))); \ 1.13 +}) 1.14 #define register_address_increment(reg, inc) \ 1.15 do { \ 1.16 int _inc = (inc); /* signed type ensures sign extension to long */ \ 1.17 @@ -399,7 +401,7 @@ do { 1.18 * effective address it is okay for us to fail the emulation. 1.19 */ 1.20 #define page_boundary_test() do { \ 1.21 - if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 3) != 0) ) \ 1.22 + if ( ((cr2 & (PAGE_SIZE-1)) == 0) && ((ea & 7) != 0) ) \ 1.23 goto bad_ea; \ 1.24 } while ( 0 ) 1.25 1.26 @@ -448,18 +450,18 @@ x86_emulate_memop( 1.27 struct x86_emulate_ctxt *ctxt, 1.28 struct x86_emulate_ops *ops) 1.29 { 1.30 + /* Shadow copy of register state. Committed on successful emulation. */ 1.31 + struct cpu_user_regs _regs = *ctxt->regs; 1.32 + 1.33 uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0; 1.34 uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0; 1.35 - uint16_t *seg = NULL; /* override segment */ 1.36 + uint16_t *seg = &_regs.ds; /* override segment */ 1.37 unsigned int op_bytes, ad_bytes, lock_prefix = 0, rep_prefix = 0, i; 1.38 int rc = 0; 1.39 struct operand src, dst; 1.40 unsigned long ea = 0, cr2 = ctxt->cr2; 1.41 int mode = ctxt->mode; 1.42 1.43 - /* Shadow copy of register state. Committed on successful emulation. */ 1.44 - struct cpu_user_regs _regs = *ctxt->regs; 1.45 - 1.46 /* 1.47 * We do not emulate faults on instruction fetch. We assume that the 1.48 * guest never executes out of a special memory area. 1.49 @@ -592,7 +594,6 @@ x86_emulate_memop( 1.50 case 1: ea += insn_fetch(uint8_t); break; 1.51 case 2: ea += insn_fetch(uint16_t); break; 1.52 } 1.53 - ea = (uint16_t)ea; 1.54 } 1.55 else 1.56 { 1.57 @@ -638,10 +639,9 @@ x86_emulate_memop( 1.58 case 1: ea += insn_fetch(uint8_t); break; 1.59 case 2: ea += insn_fetch(uint32_t); break; 1.60 } 1.61 - if ( ad_bytes == 4 ) 1.62 - ea = (uint32_t)ea; 1.63 } 1.64 1.65 + ea = register_address(*seg, ea); 1.66 page_boundary_test(); 1.67 } 1.68 1.69 @@ -809,12 +809,14 @@ x86_emulate_memop( 1.70 case 0xa0 ... 0xa1: /* mov */ 1.71 dst.ptr = (unsigned long *)&_regs.eax; 1.72 dst.val = src.val; 1.73 - ea = _insn_fetch(ad_bytes); /* src effective address */ 1.74 + /* Source EA is not encoded via ModRM. */ 1.75 + ea = register_address(*seg, _insn_fetch(ad_bytes)); 1.76 page_boundary_test(); 1.77 break; 1.78 case 0xa2 ... 0xa3: /* mov */ 1.79 dst.val = (unsigned long)_regs.eax; 1.80 - ea = _insn_fetch(ad_bytes); /* dst effective address */ 1.81 + /* Destination EA is not encoded via ModRM. */ 1.82 + ea = register_address(*seg, _insn_fetch(ad_bytes)); 1.83 page_boundary_test(); 1.84 break; 1.85 case 0x88 ... 0x8b: /* mov */ 1.86 @@ -991,11 +993,10 @@ x86_emulate_memop( 1.87 { 1.88 /* Write fault: destination is special memory. */ 1.89 dst.ptr = (unsigned long *)cr2; 1.90 - if ( (rc = ops->read_std(register_address(seg ? *seg : _regs.ds, 1.91 - _regs.esi), 1.92 + if ( (rc = ops->read_std(register_address(*seg, _regs.esi), 1.93 &dst.val, dst.bytes, ctxt)) != 0 ) 1.94 goto done; 1.95 - ea = _regs.edi & ((1UL << (ad_bytes*8)) - 1UL); 1.96 + ea = register_address(_regs.es, _regs.edi); 1.97 } 1.98 else 1.99 { 1.100 @@ -1004,7 +1005,7 @@ x86_emulate_memop( 1.101 if ( (rc = ops->read_emulated(cr2, &dst.val, 1.102 dst.bytes, ctxt)) != 0 ) 1.103 goto done; 1.104 - ea = _regs.esi & ((1UL << (ad_bytes*8)) - 1UL); 1.105 + ea = register_address(*seg, _regs.esi); 1.106 } 1.107 register_address_increment( 1.108 _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); 1.109 @@ -1019,7 +1020,7 @@ x86_emulate_memop( 1.110 dst.val = _regs.eax; 1.111 register_address_increment( 1.112 _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); 1.113 - ea = _regs.edi & ((1UL << (ad_bytes*8)) - 1UL); 1.114 + ea = register_address(_regs.es, _regs.edi); 1.115 page_boundary_test(); 1.116 break; 1.117 case 0xac ... 0xad: /* lods */ 1.118 @@ -1030,7 +1031,7 @@ x86_emulate_memop( 1.119 goto done; 1.120 register_address_increment( 1.121 _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); 1.122 - ea = _regs.esi & ((1UL << (ad_bytes*8)) - 1UL); 1.123 + ea = register_address(*seg, _regs.esi); 1.124 page_boundary_test(); 1.125 break; 1.126 }