debuggers.hg
changeset 16503:6d129d093394
x86_emulate: Emulate CMPS and SCAS string-compare instructions.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
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;