ia64/xen-unstable

changeset 16465:6d129d093394

x86_emulate: Emulate CMPS and SCAS string-compare instructions.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Sun Nov 25 18:07:33 2007 +0000 (2007-11-25)
parents 7c6944d861b2
children bb961bda7eff
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Sun Nov 25 18:06:30 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Sun Nov 25 18:07:33 2007 +0000
     1.3 @@ -131,11 +131,13 @@ static uint8_t opcode_table[256] = {
     1.4      /* 0xA0 - 0xA7 */
     1.5      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     1.6      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     1.7 -    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
     1.8 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
     1.9 +    ByteOp|ImplicitOps, ImplicitOps,
    1.10      /* 0xA8 - 0xAF */
    1.11      ByteOp|DstReg|SrcImm, DstReg|SrcImm,
    1.12      ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.13 -    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
    1.14 +    ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
    1.15 +    ByteOp|ImplicitOps, ImplicitOps,
    1.16      /* 0xB0 - 0xB7 */
    1.17      ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov,
    1.18      ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov,
    1.19 @@ -828,6 +830,8 @@ x86_emulate(
    1.20      uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
    1.21      uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
    1.22      unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes;
    1.23 +#define REPE_PREFIX  1
    1.24 +#define REPNE_PREFIX 2
    1.25      unsigned int lock_prefix = 0, rep_prefix = 0;
    1.26      int override_seg = -1, rc = X86EMUL_OKAY;
    1.27      struct operand src, dst;
    1.28 @@ -882,8 +886,10 @@ x86_emulate(
    1.29              lock_prefix = 1;
    1.30              break;
    1.31          case 0xf2: /* REPNE/REPNZ */
    1.32 +            rep_prefix = REPNE_PREFIX;
    1.33 +            break;
    1.34          case 0xf3: /* REP/REPE/REPZ */
    1.35 -            rep_prefix = 1;
    1.36 +            rep_prefix = REPE_PREFIX;
    1.37              break;
    1.38          case 0x40 ... 0x4f: /* REX */
    1.39              if ( !mode_64bit() )
    1.40 @@ -2161,6 +2167,27 @@ x86_emulate(
    1.41              _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
    1.42          break;
    1.43  
    1.44 +    case 0xa6 ... 0xa7: /* cmps */ {
    1.45 +        unsigned long next_eip = _regs.eip;
    1.46 +        handle_rep_prefix();
    1.47 +        src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
    1.48 +        if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
    1.49 +                             &dst.val, dst.bytes, ctxt)) ||
    1.50 +             (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
    1.51 +                             &src.val, src.bytes, ctxt)) )
    1.52 +            goto done;
    1.53 +        register_address_increment(
    1.54 +            _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
    1.55 +        register_address_increment(
    1.56 +            _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
    1.57 +        /* cmp: dst - src ==> src=*%%edi,dst=*%%esi ==> *%%esi - *%%edi */
    1.58 +        emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
    1.59 +        if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
    1.60 +             ((rep_prefix == REPNE_PREFIX) && (_regs.eflags & EFLG_ZF)) )
    1.61 +            _regs.eip = next_eip;
    1.62 +        break;
    1.63 +    }
    1.64 +
    1.65      case 0xaa ... 0xab: /* stos */
    1.66          handle_rep_prefix();
    1.67          dst.type  = OP_MEM;
    1.68 @@ -2184,6 +2211,24 @@ x86_emulate(
    1.69              _regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
    1.70          break;
    1.71  
    1.72 +    case 0xae ... 0xaf: /* scas */ {
    1.73 +        unsigned long next_eip = _regs.eip;
    1.74 +        handle_rep_prefix();
    1.75 +        src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes;
    1.76 +        dst.val = _regs.eax;
    1.77 +        if ( (rc = ops->read(x86_seg_es, truncate_ea(_regs.edi),
    1.78 +                             &src.val, src.bytes, ctxt)) != 0 )
    1.79 +            goto done;
    1.80 +        register_address_increment(
    1.81 +            _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes);
    1.82 +        /* cmp: dst - src ==> src=*%%edi,dst=%%eax ==> %%eax - *%%edi */
    1.83 +        emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
    1.84 +        if ( ((rep_prefix == REPE_PREFIX) && !(_regs.eflags & EFLG_ZF)) ||
    1.85 +             ((rep_prefix == REPNE_PREFIX) && (_regs.eflags & EFLG_ZF)) )
    1.86 +            _regs.eip = next_eip;
    1.87 +        break;
    1.88 +    }
    1.89 +
    1.90      case 0xc2: /* ret imm16 (near) */
    1.91      case 0xc3: /* ret (near) */ {
    1.92          int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0;