[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Emulator extensions to decode ModRM.MOD == 3.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1166627773 0 # Node ID 4fb80f21c77df84f6a6d7f61fdce4c337d538291 # Parent ed815cbdc90e4991da69ec57a4b9e2793bb43b7b [XEN] Emulator extensions to decode ModRM.MOD == 3. This allows emulation of register-only instructions. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/tests/test_x86_emulator.c | 44 +++---- xen/arch/x86/x86_32/seg_fixup.c | 5 xen/arch/x86/x86_emulate.c | 229 +++++++++++++++++++++++----------------- 3 files changed, 155 insertions(+), 123 deletions(-) diff -r ed815cbdc90e -r 4fb80f21c77d tools/tests/test_x86_emulator.c --- a/tools/tests/test_x86_emulator.c Wed Dec 20 13:54:04 2006 +0000 +++ b/tools/tests/test_x86_emulator.c Wed Dec 20 15:16:13 2006 +0000 @@ -15,8 +15,6 @@ typedef int64_t s64; #include <asm-x86/x86_emulate.h> #include <sys/mman.h> -#define PFEC_write_access (1U<<1) - static int read( unsigned int seg, unsigned long offset, @@ -119,12 +117,26 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; - regs.error_code = PFEC_write_access; regs.eax = (unsigned long)res; *res = 0x7FFFFFFF; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x92345677) || + (regs.eflags != 0xa94) || + (regs.eip != (unsigned long)&instr[2]) ) + goto fail; + printf("okay\n"); + + printf("%-40s", "Testing addl %%ecx,%%eax..."); + instr[0] = 0x01; instr[1] = 0xc8; + regs.eflags = 0x200; + regs.eip = (unsigned long)&instr[0]; + regs.ecx = 0x12345678; + regs.eax = 0x7FFFFFFF; + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || + (regs.ecx != 0x12345678) || + (regs.eax != 0x92345677) || (regs.eflags != 0xa94) || (regs.eip != (unsigned long)&instr[2]) ) goto fail; @@ -140,7 +152,6 @@ int main(int argc, char **argv) regs.ecx = 0x12345678UL; #endif regs.eax = (unsigned long)res; - regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x92345677) || @@ -155,7 +166,6 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.ecx = ~0UL; regs.eax = (unsigned long)res; - regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x92345677) || @@ -171,7 +181,6 @@ int main(int argc, char **argv) regs.eax = 0x92345677UL; regs.ecx = 0xAA; regs.ebx = (unsigned long)res; - regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x923456AA) || @@ -188,7 +197,6 @@ int main(int argc, char **argv) regs.eax = 0xAABBCC77UL; regs.ecx = 0xFF; regs.ebx = (unsigned long)res; - regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x923456AA) || @@ -205,7 +213,6 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.ecx = 0x12345678; regs.eax = (unsigned long)res; - regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x12345678) || @@ -223,7 +230,6 @@ int main(int argc, char **argv) regs.eax = 0x923456AAUL; regs.ecx = 0xDDEEFF00L; regs.ebx = (unsigned long)res; - regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0xDDEEFF00) || @@ -241,7 +247,6 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.esi = (unsigned long)res + 0; regs.edi = (unsigned long)res + 2; - regs.error_code = 0; /* read fault */ rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x44554455) || @@ -259,9 +264,8 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - regs.error_code = PFEC_write_access; - rc = x86_emulate_memop(&ctxt, &emulops); - if ( (rc != 0) || + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || (*res != 0x2233445D) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[4]) ) @@ -275,9 +279,8 @@ int main(int argc, char **argv) regs.eip = (unsigned long)&instr[0]; regs.eax = -32; regs.edi = (unsigned long)(res+1); - regs.error_code = PFEC_write_access; - rc = x86_emulate_memop(&ctxt, &emulops); - if ( (rc != 0) || + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || (*res != 0x2233445E) || ((regs.eflags&0x201) != 0x201) || (regs.eip != (unsigned long)&instr[3]) ) @@ -296,9 +299,8 @@ int main(int argc, char **argv) regs.ecx = 0xCCCCFFFF; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - regs.error_code = PFEC_write_access; - rc = x86_emulate_memop(&ctxt, &emulops); - if ( (rc != 0) || + rc = x86_emulate_memop(&ctxt, &emulops); + if ( (rc != 0) || (res[0] != 0x9999AAAA) || (res[1] != 0xCCCCFFFF) || ((regs.eflags&0x240) != 0x240) || @@ -311,7 +313,6 @@ int main(int argc, char **argv) regs.eflags = 0x200; regs.eip = (unsigned long)&instr[0]; regs.edi = (unsigned long)res; - regs.error_code = PFEC_write_access; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (res[0] != 0x9999AAAA) || @@ -330,7 +331,6 @@ int main(int argc, char **argv) regs.ecx = 0x12345678; regs.eax = (unsigned long)res; *res = 0x82; - regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x82) || @@ -347,7 +347,6 @@ int main(int argc, char **argv) regs.ecx = 0x12345678; regs.eax = (unsigned long)res; *res = 0x1234aa82; - regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x1234aa82) || @@ -364,7 +363,6 @@ int main(int argc, char **argv) regs.ecx = (unsigned long)res; regs.eax = 0x12345678; *res = 0x11111111; - regs.error_code = 0; rc = x86_emulate_memop(&ctxt, &emulops); if ( (rc != 0) || (*res != 0x11116789) || diff -r ed815cbdc90e -r 4fb80f21c77d xen/arch/x86/x86_32/seg_fixup.c --- a/xen/arch/x86/x86_32/seg_fixup.c Wed Dec 20 13:54:04 2006 +0000 +++ b/xen/arch/x86/x86_32/seg_fixup.c Wed Dec 20 15:16:13 2006 +0000 @@ -268,7 +268,7 @@ int gpf_emulate_4gb(struct cpu_user_regs struct trap_info *ti; struct trap_bounce *tb; u8 modrm, mod, reg, rm, decode; - void *memreg, *regreg; + void *memreg; unsigned long offset; u8 disp8; u32 disp32 = 0; @@ -384,8 +384,7 @@ int gpf_emulate_4gb(struct cpu_user_regs goto fixme; } - /* Decode Reg and R/M fields. */ - regreg = decode_register(reg, regs, 0); + /* Decode R/M field. */ memreg = decode_register(rm, regs, 0); /* Decode Mod field. */ diff -r ed815cbdc90e -r 4fb80f21c77d xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Wed Dec 20 13:54:04 2006 +0000 +++ b/xen/arch/x86/x86_emulate.c Wed Dec 20 15:16:13 2006 +0000 @@ -192,11 +192,15 @@ struct operand { enum { OP_REG, OP_MEM, OP_IMM } type; unsigned int bytes; unsigned long val, orig_val; - /* OP_REG: Pointer to register field. */ - unsigned long *reg; - /* OP_MEM: Segment and offset. */ - enum x86_segment mem_seg; - unsigned long mem_off; + union { + /* OP_REG: Pointer to register field. */ + unsigned long *reg; + /* OP_MEM: Segment and offset. */ + struct { + enum x86_segment seg; + unsigned long off; + } mem; + }; }; /* EFLAGS bit definitions. */ @@ -451,8 +455,13 @@ x86_emulate_memop( struct operand src, dst; int mode = ctxt->mode; - enum x86_segment ea_seg = x86_seg_ds; - unsigned long ea_off = 0; + /* Data operand effective address (usually computed from ModRM). */ + struct operand ea; + + /* Default is a memory operand relative to segment DS. */ + ea.type = OP_MEM; + ea.mem.seg = x86_seg_ds; + ea.mem.off = 0; switch ( mode ) { @@ -488,22 +497,22 @@ x86_emulate_memop( ad_bytes ^= 6; /* switch between 2/4 bytes */ break; case 0x2e: /* CS override */ - ea_seg = x86_seg_cs; + ea.mem.seg = x86_seg_cs; break; case 0x3e: /* DS override */ - ea_seg = x86_seg_ds; + ea.mem.seg = x86_seg_ds; break; case 0x26: /* ES override */ - ea_seg = x86_seg_es; + ea.mem.seg = x86_seg_es; break; case 0x64: /* FS override */ - ea_seg = x86_seg_fs; + ea.mem.seg = x86_seg_fs; break; case 0x65: /* GS override */ - ea_seg = x86_seg_gs; + ea.mem.seg = x86_seg_gs; break; case 0x36: /* SS override */ - ea_seg = x86_seg_ss; + ea.mem.seg = x86_seg_ss; break; case 0xf0: /* LOCK */ lock_prefix = 1; @@ -554,35 +563,39 @@ x86_emulate_memop( modrm_rm = modrm & 0x07; if ( modrm_mod == 3 ) - goto cannot_emulate; - - if ( ad_bytes == 2 ) + { + ea.type = OP_REG; + ea.reg = decode_register( + modrm_rm, &_regs, (d & ByteOp) && (rex_prefix == 0)); + } + else if ( ad_bytes == 2 ) { /* 16-bit ModR/M decode. */ switch ( modrm_rm ) { - case 0: ea_off = _regs.ebx + _regs.esi; break; - case 1: ea_off = _regs.ebx + _regs.edi; break; - case 2: ea_off = _regs.ebp + _regs.esi; break; - case 3: ea_off = _regs.ebp + _regs.edi; break; - case 4: ea_off = _regs.esi; break; - case 5: ea_off = _regs.edi; break; - case 6: ea_off = _regs.ebp; break; - case 7: ea_off = _regs.ebx; break; + case 0: ea.mem.off = _regs.ebx + _regs.esi; break; + case 1: ea.mem.off = _regs.ebx + _regs.edi; break; + case 2: ea.mem.off = _regs.ebp + _regs.esi; break; + case 3: ea.mem.off = _regs.ebp + _regs.edi; break; + case 4: ea.mem.off = _regs.esi; break; + case 5: ea.mem.off = _regs.edi; break; + case 6: ea.mem.off = _regs.ebp; break; + case 7: ea.mem.off = _regs.ebx; break; } switch ( modrm_mod ) { case 0: if ( modrm_rm == 6 ) - ea_off = insn_fetch_type(int16_t); + ea.mem.off = insn_fetch_type(int16_t); break; case 1: - ea_off += insn_fetch_type(int8_t); + ea.mem.off += insn_fetch_type(int8_t); break; case 2: - ea_off += insn_fetch_type(int16_t); + ea.mem.off += insn_fetch_type(int16_t); break; } + ea.mem.off = truncate_ea(ea.mem.off); } else { @@ -593,49 +606,48 @@ x86_emulate_memop( sib_index = ((sib >> 3) & 7) | ((rex_prefix << 2) & 8); sib_base = (sib & 7) | ((rex_prefix << 3) & 8); if ( sib_index != 4 ) - ea_off = *(long *)decode_register(sib_index, &_regs, 0); - ea_off <<= (sib >> 6) & 3; + ea.mem.off = *(long*)decode_register(sib_index, &_regs, 0); + ea.mem.off <<= (sib >> 6) & 3; if ( (modrm_mod == 0) && ((sib_base & 7) == 5) ) - ea_off += insn_fetch_type(int32_t); + ea.mem.off += insn_fetch_type(int32_t); else - ea_off += *(long *)decode_register(sib_base, &_regs, 0); + ea.mem.off += *(long*)decode_register(sib_base, &_regs, 0); } else { modrm_rm |= (rex_prefix & 1) << 3; - ea_off = *(long *)decode_register(modrm_rm, &_regs, 0); + ea.mem.off = *(long *)decode_register(modrm_rm, &_regs, 0); } switch ( modrm_mod ) { case 0: if ( (modrm_rm & 7) != 5 ) break; - ea_off = insn_fetch_type(int32_t); + ea.mem.off = insn_fetch_type(int32_t); if ( mode != X86EMUL_MODE_PROT64 ) break; /* Relative to RIP of next instruction. Argh! */ - ea_off += _regs.eip; + ea.mem.off += _regs.eip; if ( (d & SrcMask) == SrcImm ) - ea_off += (d & ByteOp) ? 1 : + ea.mem.off += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); else if ( (d & SrcMask) == SrcImmByte ) - ea_off += 1; + ea.mem.off += 1; else if ( ((b == 0xf6) || (b == 0xf7)) && ((modrm_reg & 7) <= 1) ) /* Special case in Grp3: test has immediate operand. */ - ea_off += (d & ByteOp) ? 1 + ea.mem.off += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes); break; case 1: - ea_off += insn_fetch_type(int8_t); + ea.mem.off += insn_fetch_type(int8_t); break; case 2: - ea_off += insn_fetch_type(int32_t); + ea.mem.off += insn_fetch_type(int32_t); break; } - } - - ea_off = truncate_ea(ea_off); + ea.mem.off = truncate_ea(ea.mem.off); + } } /* Special instructions do their own operand decoding. */ @@ -652,7 +664,7 @@ x86_emulate_memop( if ( d & ByteOp ) { src.reg = decode_register(modrm_reg, &_regs, (rex_prefix == 0)); - src.val = src.orig_val = *(uint8_t *)src.reg; + src.val = *(uint8_t *)src.reg; src.bytes = 1; } else @@ -660,28 +672,35 @@ x86_emulate_memop( src.reg = decode_register(modrm_reg, &_regs, 0); switch ( (src.bytes = op_bytes) ) { - case 2: src.val = src.orig_val = *(uint16_t *)src.reg; break; - case 4: src.val = src.orig_val = *(uint32_t *)src.reg; break; - case 8: src.val = src.orig_val = *(uint64_t *)src.reg; break; + case 2: src.val = *(uint16_t *)src.reg; break; + case 4: src.val = *(uint32_t *)src.reg; break; + case 8: src.val = *(uint64_t *)src.reg; break; } } break; case SrcMem16: - src.bytes = 2; + ea.bytes = 2; goto srcmem_common; case SrcMem32: - src.bytes = 4; + ea.bytes = 4; goto srcmem_common; case SrcMem: - src.bytes = (d & ByteOp) ? 1 : op_bytes; + ea.bytes = (d & ByteOp) ? 1 : op_bytes; srcmem_common: - src.type = OP_MEM; - src.mem_seg = ea_seg; - src.mem_off = ea_off; - if ( (rc = ops->read(src.mem_seg, src.mem_off, - &src.val, src.bytes, ctxt)) != 0 ) + src = ea; + if ( src.type == OP_REG ) + { + switch ( src.bytes ) + { + case 1: src.val = *(uint8_t *)src.reg; break; + case 2: src.val = *(uint16_t *)src.reg; break; + case 4: src.val = *(uint32_t *)src.reg; break; + case 8: src.val = *(uint64_t *)src.reg; break; + } + } + else if ( (rc = ops->read(src.mem.seg, src.mem.off, + &src.val, src.bytes, ctxt)) ) goto done; - src.orig_val = src.val; break; case SrcImm: src.type = OP_IMM; @@ -725,8 +744,7 @@ x86_emulate_memop( } break; case DstBitBase: - dst.mem_off = ea_off; - if ( (d & SrcMask) == SrcImmByte ) + if ( ((d & SrcMask) == SrcImmByte) || (ea.type == OP_REG) ) { src.val &= (op_bytes << 3) - 1; } @@ -746,28 +764,34 @@ x86_emulate_memop( { unsigned long byte_offset; byte_offset = op_bytes + (((-src.val-1) >> 3) & ~(op_bytes-1)); - dst.mem_off -= byte_offset; + ea.mem.off -= byte_offset; src.val = (byte_offset << 3) + src.val; } else { - dst.mem_off += (src.val >> 3) & ~(op_bytes - 1); + ea.mem.off += (src.val >> 3) & ~(op_bytes - 1); src.val &= (op_bytes << 3) - 1; } } /* Becomes a normal DstMem operation from here on. */ d = (d & ~DstMask) | DstMem; - goto dstmem_common; case DstMem: - dst.mem_off = ea_off; - dstmem_common: - dst.mem_seg = ea_seg; - dst.type = OP_MEM; - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ - ((rc = ops->read(dst.mem_seg, dst.mem_off, - &dst.val, dst.bytes, ctxt)) != 0) ) - goto done; + ea.bytes = (d & ByteOp) ? 1 : op_bytes; + dst = ea; + if ( dst.type == OP_REG ) + { + switch ( dst.bytes ) + { + case 1: dst.val = *(uint8_t *)dst.reg; break; + case 2: dst.val = *(uint16_t *)dst.reg; break; + case 4: dst.val = *(uint32_t *)dst.reg; break; + case 8: dst.val = *(uint64_t *)dst.reg; break; + } + } + else if ( !(d & Mov) && /* optimisation - avoid slow emulated read */ + (rc = ops->read(dst.mem.seg, dst.mem.off, + &dst.val, dst.bytes, ctxt)) ) + goto done; break; } dst.orig_val = dst.val; @@ -920,7 +944,7 @@ x86_emulate_memop( if ( mode == X86EMUL_MODE_PROT64 ) { dst.bytes = 8; - if ( (rc = ops->read(dst.mem_seg, dst.mem_off, + if ( (rc = ops->read(dst.mem.seg, dst.mem.off, &dst.val, 8, ctxt)) != 0 ) goto done; } @@ -954,11 +978,11 @@ x86_emulate_memop( case OP_MEM: if ( lock_prefix ) rc = ops->cmpxchg( - dst.mem_seg, dst.mem_off, dst.orig_val, + dst.mem.seg, dst.mem.off, dst.orig_val, dst.val, dst.bytes, ctxt); else rc = ops->write( - dst.mem_seg, dst.mem_off, dst.val, dst.bytes, ctxt); + dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt); if ( rc != 0 ) goto done; default: @@ -987,29 +1011,29 @@ x86_emulate_memop( } switch ( b ) { - case 0xa0 ... 0xa1: /* mov moffs,{%al,%ax,%eax,%rax} */ + case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ /* Source EA is not encoded via ModRM. */ dst.type = OP_REG; dst.reg = (unsigned long *)&_regs.eax; dst.bytes = (d & ByteOp) ? 1 : op_bytes; - if ( (rc = ops->read(ea_seg, insn_fetch_bytes(ad_bytes), + if ( (rc = ops->read(ea.mem.seg, insn_fetch_bytes(ad_bytes), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; break; - case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},moffs */ + case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */ /* Destination EA is not encoded via ModRM. */ - dst.type = OP_MEM; - dst.mem_seg = ea_seg; - dst.mem_off = insn_fetch_bytes(ad_bytes); - dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.val = (unsigned long)_regs.eax; + dst.type = OP_MEM; + dst.mem.seg = ea.mem.seg; + dst.mem.off = insn_fetch_bytes(ad_bytes); + dst.bytes = (d & ByteOp) ? 1 : op_bytes; + dst.val = (unsigned long)_regs.eax; break; case 0xa4 ... 0xa5: /* movs */ dst.type = OP_MEM; dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.mem_seg = x86_seg_es; - dst.mem_off = truncate_ea(_regs.edi); - if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi), + dst.mem.seg = x86_seg_es; + dst.mem.off = truncate_ea(_regs.edi); + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; register_address_increment( @@ -1020,8 +1044,8 @@ x86_emulate_memop( case 0xaa ... 0xab: /* stos */ dst.type = OP_MEM; dst.bytes = (d & ByteOp) ? 1 : op_bytes; - dst.mem_seg = x86_seg_es; - dst.mem_off = truncate_ea(_regs.edi); + dst.mem.seg = x86_seg_es; + dst.mem.off = truncate_ea(_regs.edi); dst.val = _regs.eax; register_address_increment( _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); @@ -1030,7 +1054,7 @@ x86_emulate_memop( dst.type = OP_REG; dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.reg = (unsigned long *)&_regs.eax; - if ( (rc = ops->read(ea_seg, truncate_ea(_regs.esi), + if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; register_address_increment( @@ -1105,9 +1129,14 @@ x86_emulate_memop( case 0xab: bts: /* bts */ emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags); break; - case 0xb6 ... 0xb7: /* movzx */ + case 0xb6: /* movzx rm8,r{16,32,64} */ + /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ + dst.reg = decode_register(modrm_reg, &_regs, 0); dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (uint8_t)src.val : (uint16_t)src.val; + dst.val = (uint8_t)src.val; + break; + case 0xb7: /* movzx rm16,r{16,32,64} */ + dst.val = (uint16_t)src.val; break; case 0xbb: btc: /* btc */ emulate_2op_SrcV_nobyte("btc", src, dst, _regs.eflags); @@ -1121,9 +1150,14 @@ x86_emulate_memop( case 3: goto btc; } break; - case 0xbe ... 0xbf: /* movsx */ + case 0xbe: /* movsx rm8,r{16,32,64} */ + /* Recompute DstReg as we may have decoded AH/BH/CH/DH. */ + dst.reg = decode_register(modrm_reg, &_regs, 0); dst.bytes = op_bytes; - dst.val = (d & ByteOp) ? (int8_t)src.val : (int16_t)src.val; + dst.val = (int8_t)src.val; + break; + case 0xbf: /* movsx rm16,r{16,32,64} */ + dst.val = (int16_t)src.val; break; case 0xc0 ... 0xc1: /* xadd */ /* Write back the register source. */ @@ -1150,8 +1184,8 @@ x86_emulate_memop( #if defined(__i386__) { unsigned long old_lo, old_hi; - if ( ((rc = ops->read(ea_seg, ea_off+0, &old_lo, 4, ctxt)) != 0) || - ((rc = ops->read(ea_seg, ea_off+4, &old_hi, 4, ctxt)) != 0) ) + if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) || + (rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) ) goto done; if ( (old_lo != _regs.eax) || (old_hi != _regs.edx) ) { @@ -1166,7 +1200,7 @@ x86_emulate_memop( } else { - if ( (rc = ops->cmpxchg8b(ea_seg, ea_off, old_lo, old_hi, + if ( (rc = ops->cmpxchg8b(ea.mem.seg, ea.mem.off, old_lo, old_hi, _regs.ebx, _regs.ecx, ctxt)) != 0 ) goto done; _regs.eflags |= EFLG_ZF; @@ -1176,7 +1210,7 @@ x86_emulate_memop( #elif defined(__x86_64__) { unsigned long old, new; - if ( (rc = ops->read(ea_seg, ea_off, &old, 8, ctxt)) != 0 ) + if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 ) goto done; if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) || ((uint32_t)(old>>32) != (uint32_t)_regs.edx) ) @@ -1188,7 +1222,8 @@ x86_emulate_memop( else { new = (_regs.ecx<<32)|(uint32_t)_regs.ebx; - if ( (rc = ops->cmpxchg(ea_seg, ea_off, old, new, 8, ctxt)) != 0 ) + if ( (rc = ops->cmpxchg(ea.mem.seg, ea.mem.off, old, + new, 8, ctxt)) != 0 ) goto done; _regs.eflags |= EFLG_ZF; } @@ -1201,10 +1236,10 @@ x86_emulate_memop( cannot_emulate: #ifdef __XEN__ gdprintk(XENLOG_DEBUG, "Instr:"); - for ( ea_off = ctxt->regs->eip; ea_off < _regs.eip; ea_off++ ) + for ( ea.mem.off = ctxt->regs->eip; ea.mem.off < _regs.eip; ea.mem.off++ ) { unsigned long x; - ops->insn_fetch(x86_seg_cs, ea_off, &x, 1, ctxt); + ops->insn_fetch(x86_seg_cs, ea.mem.off, &x, 1, ctxt); printk(" %02x", (uint8_t)x); } printk("\n"); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |