Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:12.2:ARM
xen
24275-x86-emul-lzcnt.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 24275-x86-emul-lzcnt.patch of Package xen
# HG changeset patch # User Jan Beulich <jbeulich@suse.com> # Date 1322725849 -3600 # Node ID 76ea126f21724b72c120aff59460f7bbe9e6960d # Parent 07cf778d517fdf661a34027af653a489489bf222 x86/emulator: properly handle lzcnt and tzcnt These instructions are prefix selected flavors of bsf and bsr respectively, and hence the presences of the F3 prefix must be handled in the emulation code in order to avoid running into problems on newer CPUs. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -990,6 +990,9 @@ static bool_t vcpu_has( return rc == X86EMUL_OKAY; } +#define vcpu_has_lzcnt() vcpu_has(0x80000001, ECX, 5, ctxt, ops) +#define vcpu_has_bmi1() vcpu_has(0x00000007, EBX, 3, ctxt, ops) + #define vcpu_must_have(leaf, reg, bit) \ generate_exception_if(!vcpu_has(leaf, reg, bit, ctxt, ops), EXC_UD, -1) #define vcpu_must_have_sse2() vcpu_must_have(0x00000001, EDX, 26) @@ -4114,13 +4117,24 @@ x86_emulate( dst.val = (uint8_t)src.val; break; - case 0xbc: /* bsf */ { - int zf; + case 0xbc: /* bsf or tzcnt */ { + bool_t zf; asm ( "bsf %2,%0; setz %b1" : "=r" (dst.val), "=q" (zf) - : "r" (src.val), "1" (0) ); + : "r" (src.val) ); _regs.eflags &= ~EFLG_ZF; - if ( zf ) + if ( (rep_prefix == REPE_PREFIX) && vcpu_has_bmi1() ) + { + _regs.eflags &= ~EFLG_CF; + if ( zf ) + { + _regs.eflags |= EFLG_CF; + dst.val = op_bytes * 8; + } + else if ( !dst.val ) + _regs.eflags |= EFLG_ZF; + } + else if ( zf ) { _regs.eflags |= EFLG_ZF; dst.type = OP_NONE; @@ -4128,13 +4142,28 @@ x86_emulate( break; } - case 0xbd: /* bsr */ { - int zf; + case 0xbd: /* bsr or lzcnt */ { + bool_t zf; asm ( "bsr %2,%0; setz %b1" : "=r" (dst.val), "=q" (zf) - : "r" (src.val), "1" (0) ); + : "r" (src.val) ); _regs.eflags &= ~EFLG_ZF; - if ( zf ) + if ( (rep_prefix == REPE_PREFIX) && vcpu_has_lzcnt() ) + { + _regs.eflags &= ~EFLG_CF; + if ( zf ) + { + _regs.eflags |= EFLG_CF; + dst.val = op_bytes * 8; + } + else + { + dst.val = op_bytes * 8 - 1 - dst.val; + if ( !dst.val ) + _regs.eflags |= EFLG_ZF; + } + } + else if ( zf ) { _regs.eflags |= EFLG_ZF; dst.type = OP_NONE;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor