ia64/xen-unstable

changeset 12572:e4bb22422b50

[XEN] Clean up EA computation in emulator.
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      }