x86emul: use SrcEax/DstEax where suitable for string insns LODS, SCAS, and STOS all use the accumulator as one of their operands. This avoids come open coding of things, but requires switching around operands of SCAS. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -135,9 +135,9 @@ static const opcode_desc_t opcode_table[ ByteOp|ImplicitOps, ImplicitOps, /* 0xA8 - 0xAF */ ByteOp|DstEax|SrcImm, DstEax|SrcImm, - ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, - ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, - ByteOp|ImplicitOps, ImplicitOps, + ByteOp|DstImplicit|SrcEax|Mov, DstImplicit|SrcEax|Mov, + ByteOp|DstEax|SrcImplicit|Mov, DstEax|SrcImplicit|Mov, + ByteOp|DstImplicit|SrcEax, DstImplicit|SrcEax, /* 0xB0 - 0xB7 */ ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov, @@ -3249,15 +3249,15 @@ x86_emulate( case 0xaa ... 0xab: /* stos */ { unsigned long nr_reps = get_rep_prefix(false, true); - dst.bytes = (d & ByteOp) ? 1 : op_bytes; + dst.bytes = src.bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); if ( (nr_reps == 1) || !ops->rep_stos || - ((rc = ops->rep_stos(&_regs.eax, + ((rc = ops->rep_stos(&src.val, dst.mem.seg, dst.mem.off, dst.bytes, &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) { - dst.val = _regs.eax; + dst.val = src.val; dst.type = OP_MEM; nr_reps = 1; } @@ -3272,9 +3272,6 @@ x86_emulate( case 0xac ... 0xad: /* lods */ get_rep_prefix(true, false); - dst.type = OP_REG; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.reg = (unsigned long *)&_regs.eax; if ( (rc = read_ulong(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt, ops)) != 0 ) goto done; @@ -3287,16 +3284,15 @@ x86_emulate( unsigned long next_eip = _regs.eip; get_rep_prefix(false, true); - src.bytes = dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.val = _regs.eax; if ( (rc = read_ulong(x86_seg_es, truncate_ea(_regs.edi), - &src.val, src.bytes, ctxt, ops)) != 0 ) + &dst.val, src.bytes, ctxt, ops)) != 0 ) goto done; register_address_increment( _regs.edi, (_regs.eflags & EFLG_DF) ? -src.bytes : src.bytes); put_rep_prefix(1); - /* cmp: dst - src ==> src=*%%edi,dst=%%eax ==> %%eax - *%%edi */ - emulate_2op_SrcV("cmp", src, dst, _regs.eflags); + /* cmp: %%eax - *%%edi ==> src=%%eax,dst=*%%edi ==> src - dst */ + dst.bytes = src.bytes; + emulate_2op_SrcV("cmp", dst, src, _regs.eflags); if ( (repe_prefix() && !(_regs.eflags & EFLG_ZF)) || (repne_prefix() && (_regs.eflags & EFLG_ZF)) ) _regs.eip = next_eip;