[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 02/17] x86emul: support MMX/SSE{, 2, 3} moves
On 28/02/17 12:50, Jan Beulich wrote: > Previously supported insns are being converted to the new model, and > several new ones are being added. > > To keep the stub handling reasonably simple, integrate SET_SSE_PREFIX() > into copy_REX_VEX(), at once switching the stubs to use an empty REX > prefix instead of a double DS: one (no byte registers are being > accessed, so an empty REX prefix has no effect), except (of course) for > the 32-bit test harness build. Why switch a %ds override to REX? There doesn't appear to be any benefit. > --- a/xen/arch/x86/x86_emulate/x86_emulate.c > +++ b/xen/arch/x86/x86_emulate/x86_emulate.c > @@ -364,11 +369,6 @@ enum vex_pfx { > > static const uint8_t sse_prefix[] = { 0x66, 0xf3, 0xf2 }; > > -#define SET_SSE_PREFIX(dst, vex_pfx) do { \ > - if ( vex_pfx ) \ > - (dst) = sse_prefix[(vex_pfx) - 1]; \ > -} while (0) > - > union vex { > uint8_t raw[2]; > struct { > @@ -383,15 +383,35 @@ union vex { > }; > }; > > +#ifdef __x86_64__ > +# define PFX2 REX_PREFIX > +#else > +# define PFX2 0x3e > +#endif > +#define PFX_BYTES 3 > +#define init_prefixes(stub) ({ \ > + uint8_t *buf_ = get_stub(stub); \ > + buf_[0] = 0x3e; \ > + buf_[1] = PFX2; \ > + buf_[2] = 0x0f; \ > + buf_ + 3; \ > +}) > + > #define copy_REX_VEX(ptr, rex, vex) do { \ > if ( (vex).opcx != vex_none ) \ > { \ > if ( !mode_64bit() ) \ > vex.reg |= 8; \ > - ptr[0] = 0xc4, ptr[1] = (vex).raw[0], ptr[2] = (vex).raw[1]; \ > + (ptr)[0 - PFX_BYTES] = 0xc4; \ > + (ptr)[1 - PFX_BYTES] = (vex).raw[0]; \ > + (ptr)[2 - PFX_BYTES] = (vex).raw[1]; \ > + } \ > + else \ > + { \ > + if ( (vex).pfx ) \ > + (ptr)[0 - PFX_BYTES] = sse_prefix[(vex).pfx - 1]; \ > + (ptr)[1 - PFX_BYTES] |= rex; \ This is no longer guarded by mode_64bit(). Won't this result in %ds | rex in the 32bit test stubs? > } \ > - else if ( mode_64bit() ) \ > - ptr[1] = rex | REX_PREFIX; \ > } while (0) > > union evex { > @@ -5429,6 +5496,57 @@ x86_emulate( > singlestep = _regs._eflags & X86_EFLAGS_TF; > break; > > + CASE_SIMD_PACKED_FP(, 0x0f, 0x50): /* movmskp{s,d} xmm,reg */ > + CASE_SIMD_PACKED_FP(_VEX, 0x0f, 0x50): /* vmovmskp{s,d} {x,y}mm,reg */ > + CASE_SIMD_PACKED_INT(0x0f, 0xd7): /* pmovmskb {,x}mm,reg */ > + case X86EMUL_OPC_VEX_66(0x0f, 0xd7): /* vpmovmskb {x,y}mm,reg */ > + generate_exception_if(ea.type != OP_REG, EXC_UD); > + > + if ( vex.opcx == vex_none ) > + { > + if ( vex.pfx & VEX_PREFIX_DOUBLE_MASK ) > + vcpu_must_have(sse2); > + else > + { > + if ( b != 0x50 ) > + host_and_vcpu_must_have(mmx); > + vcpu_must_have(sse); > + } > + if ( b == 0x50 || (vex.pfx & VEX_PREFIX_DOUBLE_MASK) ) > + get_fpu(X86EMUL_FPU_xmm, &fic); > + else > + get_fpu(X86EMUL_FPU_mmx, &fic); > + } > + else > + { > + generate_exception_if(vex.reg != 0xf, EXC_UD); Isn't this TwoOp? > + if ( b == 0x50 || !vex.l ) > + host_and_vcpu_must_have(avx); > + else > + host_and_vcpu_must_have(avx2); > + get_fpu(X86EMUL_FPU_ymm, &fic); > + } > + > + opc = init_prefixes(stub); > + opc[0] = b; > + /* Convert GPR destination to %rAX. */ > + rex_prefix &= ~REX_R; > + vex.r = 1; > + if ( !mode_64bit() ) > + vex.w = 0; > + opc[1] = modrm & 0xc7; > + fic.insn_bytes = PFX_BYTES + 2; > + opc[2] = 0xc3; > + > + copy_REX_VEX(opc, rex_prefix, vex); > + invoke_stub("", "", "=a" (dst.val) : [dummy] "i" (0)); > + > + put_stub(stub); > + put_fpu(&fic); > + > + dst.bytes = 4; Somewhere there should probably be an ASSERT() that state->simd_size is 0, so we don't try to invoke the stub twice. > + break; > + > CASE_SIMD_PACKED_INT(0x0f, 0x60): /* punpcklbw {,x}mm/mem,{,x}mm */ > case X86EMUL_OPC_VEX_66(0x0f, 0x60): /* vpunpcklbw > {x,y}mm/mem,{x,y}mm,{x,y}mm */ > CASE_SIMD_PACKED_INT(0x0f, 0x61): /* punpcklwd {,x}mm/mem,{,x}mm */ > @@ -6553,23 +6686,14 @@ x86_emulate( > > if ( state->simd_size ) > { > -#ifdef __XEN__ > - uint8_t *buf = stub.ptr; > -#else > - uint8_t *buf = get_stub(stub); > -#endif > - > generate_exception_if(!op_bytes, EXC_UD); > generate_exception_if(vex.opcx && (d & TwoOp) && vex.reg != 0xf, > EXC_UD); > > - if ( !buf ) > + if ( !opc ) > BUG(); > - if ( vex.opcx == vex_none ) > - SET_SSE_PREFIX(buf[0], vex.pfx); > - > - buf[fic.insn_bytes] = 0xc3; > - copy_REX_VEX(buf, rex_prefix, vex); > + opc[fic.insn_bytes - PFX_BYTES] = 0xc3; fic.insn_bytes - PFX_BYTES is in the middle of the opcode, isn't it? ~Andrew > + copy_REX_VEX(opc, rex_prefix, vex); > > if ( ea.type == OP_MEM ) > { _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |