Emitter: Fixed a GCC compilation error; Implemented MOVNT/MOVLH/MOVHL/PMOVMSKB, and tied in all old emitter references to MOVAPS/MOVDQA to the new versions.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1020 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-19 16:34:29 +00:00
parent bb7dc87819
commit d91eb6d1c8
8 changed files with 236 additions and 419 deletions

View File

@ -56,15 +56,14 @@ public:
}
// ------------------------------------------------------------------------
#ifndef __LINUX__
static __emitinline void Emit( void* bitbase, const iRegister<ImmType>& bitoffset )
{
prefix16();
iWrite<u8>( 0x0f );
iWrite<u8>( 0xa3 | (InstType << 2) );
iWriteDisp( bitoffset.Id, bitbase.Id );
iWriteDisp( bitoffset.Id, bitbase );
}
#endif
// ------------------------------------------------------------------------
static __emitinline void Emit( const ModSibBase& bitbase, const iRegister<ImmType>& bitoffset )
{

View File

@ -22,7 +22,7 @@
// MMX / SSE Helper Functions!
template< typename T >
__emitinline void SimdPrefix( u8 opcode, u8 prefix )
__emitinline void SimdPrefix( u8 opcode, u8 prefix=0 )
{
if( sizeof( T ) == 16 && prefix != 0 )
{
@ -33,84 +33,84 @@ __emitinline void SimdPrefix( u8 opcode, u8 prefix )
iWrite<u16>( (opcode<<8) | 0x0f );
}
template< u8 prefix, typename T, typename T2 >
__emitinline void writeXMMop( u8 opcode, const iRegister<T>& to, const iRegister<T2>& from )
// ------------------------------------------------------------------------
// xmm emitter helpers for xmm instruction with prefixes.
// These functions also support deducing the use of the prefix from the template parameters,
// since most xmm instructions use a prefix and most mmx instructions do not. (some mov
// instructions violate this "guideline.")
//
template< typename T, typename T2 >
__emitinline void writeXMMop( u8 prefix, u8 opcode, const iRegister<T>& to, const iRegister<T2>& from )
{
SimdPrefix<T>( opcode, prefix );
ModRM_Direct( to.Id, from.Id );
}
template< u8 prefix, typename T >
void writeXMMop( u8 opcode, const iRegister<T>& reg, const ModSibBase& sib )
template< typename T >
void writeXMMop( u8 prefix, u8 opcode, const iRegister<T>& reg, const ModSibBase& sib )
{
SimdPrefix<T>( opcode, prefix );
EmitSibMagic( reg.Id, sib );
}
template< u8 prefix, typename T >
__emitinline void writeXMMop( u8 opcode, const iRegister<T>& reg, const void* data )
template< typename T >
__emitinline void writeXMMop( u8 prefix, u8 opcode, const iRegister<T>& reg, const void* data )
{
SimdPrefix<T>( opcode, prefix );
iWriteDisp( reg.Id, data );
}
// ------------------------------------------------------------------------
// xmm emitter helpers for xmm instructions *without* prefixes.
// These are normally used for special instructions that have MMX forms only (non-SSE), however
// some special forms of sse/xmm mov instructions also use them due to prefixing inconsistencies.
//
template< typename T, typename T2 >
__emitinline void writeXMMop( u8 opcode, const iRegister<T>& to, const iRegister<T2>& from )
{
SimdPrefix<T>( opcode );
ModRM_Direct( to.Id, from.Id );
}
template< typename T >
void writeXMMop( u8 opcode, const iRegister<T>& reg, const ModSibBase& sib )
{
SimdPrefix<T>( opcode );
EmitSibMagic( reg.Id, sib );
}
template< typename T >
__emitinline void writeXMMop( u8 opcode, const iRegister<T>& reg, const void* data )
{
SimdPrefix<T>( opcode );
iWriteDisp( reg.Id, data );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
template< u8 Prefix, typename OperandType >
class MovapsImpl
// Moves to/from high/low portions of an xmm register.
// These instructions cannot be used in reg/reg form.
template< u8 Prefix, u8 Opcode >
class MovhlImplAll
{
public:
// ------------------------------------------------------------------------
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const iRegisterSIMD<OperandType> from )
{
if( to != from )
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const void* from )
{
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const ModSibBase& from )
{
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
// ------------------------------------------------------------------------
// Generally a Movaps/dqa instruction form only.
// Most SSE/MMX instructions don't have this form.
static __emitinline void Emit( u8 opcode, const void* to, const iRegisterSIMD<OperandType>& from )
{
writeXMMop<Prefix,OperandType>( opcode, from, to );
}
// ------------------------------------------------------------------------
// Generally a Movaps/dqa instruction form only.
// Most SSE/MMX instructions don't have this form.
static __emitinline void Emit( u8 opcode, const ModSibBase& to, const iRegisterSIMD<OperandType>& from )
{
writeXMMop<Prefix,OperandType>( opcode, from, to );
}
__forceinline void operator()( const iRegisterSSE& to, const void* from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__forceinline void operator()( const void* to, const iRegisterSSE& from ) const { writeXMMop( Prefix, Opcode+1, from, to ); }
__noinline void operator()( const iRegisterSSE& to, const ModSibBase& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__noinline void operator()( const ModSibBase& to, const iRegisterSSE& from ) const { writeXMMop( Prefix, Opcode+1, from, to ); }
MovhlImplAll() {} //GCC.
};
// ------------------------------------------------------------------------
template< u8 Prefix, u8 Opcode, u8 OpcodeAlt >
class MovapsImplAll
{
protected:
typedef MovapsImpl<Prefix, u128> m_128;
public:
__forceinline void operator()( const iRegisterSSE& to, const iRegisterSSE& from ) const { m_128::Emit( Opcode, to, from ); }
__forceinline void operator()( const iRegisterSSE& to, const void* from ) const { m_128::Emit( Opcode, to, from ); }
__forceinline void operator()( const void* to, const iRegisterSSE& from ) const { m_128::Emit( OpcodeAlt, to, from ); }
__noinline void operator()( const iRegisterSSE& to, const ModSibBase& from ) const { m_128::Emit( Opcode, to, from ); }
__noinline void operator()( const ModSibBase& to, const iRegisterSSE& from ) const { m_128::Emit( OpcodeAlt, to, from ); }
__forceinline void operator()( const iRegisterSSE& to, const iRegisterSSE& from ) const { if( to != from ) writeXMMop( Prefix, Opcode, to, from ); }
__forceinline void operator()( const iRegisterSSE& to, const void* from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__forceinline void operator()( const void* to, const iRegisterSSE& from ) const { writeXMMop( Prefix, OpcodeAlt, from, to ); }
__noinline void operator()( const iRegisterSSE& to, const ModSibBase& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__noinline void operator()( const ModSibBase& to, const iRegisterSSE& from ) const { writeXMMop( Prefix, OpcodeAlt, from, to ); }
MovapsImplAll() {} //GCC.
};

View File

@ -740,29 +740,40 @@ const MovapsImplAll< 0, 0x10, 0x11 > iMOVUPS;
const MovapsImplAll< 0x66, 0x28, 0x29 > iMOVAPD;
const MovapsImplAll< 0x66, 0x10, 0x11 > iMOVUPD;
#ifdef ALWAYS_USE_MOVAPS
const MovapsImplAll< 0x66, 0x6f, 0x7f > iMOVDQA;
const MovapsImplAll< 0xf3, 0x6f, 0x7f > iMOVDQU;
#else
const MovapsImplAll< 0, 0x28, 0x29 > iMOVDQA;
const MovapsImplAll< 0, 0x10, 0x11 > iMOVDQU;
#endif
const MovhlImplAll< 0, 0x16 > iMOVHPS;
const MovhlImplAll< 0, 0x12 > iMOVLPS;
const MovhlImplAll< 0x66, 0x16 > iMOVHPD;
const MovhlImplAll< 0x66, 0x12 > iMOVLPD;
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero.
__emitinline void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop<0xf3>( 0x7e, to, from ); }
__forceinline void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop( 0xf3, 0x7e, to, from ); }
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero.
__noinline void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
__noinline void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src ) { writeXMMop( 0xf3, 0x7e, to, src ); }
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero.
__emitinline void iMOVQZX( const iRegisterSSE& to, const void* src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
__forceinline void iMOVQZX( const iRegisterSSE& to, const void* src ) { writeXMMop( 0xf3, 0x7e, to, src ); }
__emitinline void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from ) { if( to != from ) writeXMMop<0>( 0x6f, to, from ); }
__noinline void iMOVQ( const iRegisterMMX& to, const ModSibBase& src ) { writeXMMop<0>( 0x6f, to, src ); }
__emitinline void iMOVQ( const iRegisterMMX& to, const void* src ) { writeXMMop<0>( 0x6f, to, src ); }
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterMMX& from ) { writeXMMop<0>( 0x7f, from, dest ); }
__forceinline void iMOVQ( void* dest, const iRegisterMMX& from ) { writeXMMop<0>( 0x7f, from, dest ); }
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterSSE& from ) { writeXMMop<0xf3>( 0x7e, from, dest ); }
__forceinline void iMOVQ( void* dest, const iRegisterSSE& from ) { writeXMMop<0xf3>( 0x7e, from, dest ); }
__forceinline void iMOVQ( const iRegisterSSE& to, const iRegisterMMX& from ) { writeXMMop<0xf3>( 0xd6, to, from ); }
__forceinline void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from ) { if( to != from ) writeXMMop( 0x6f, to, from ); }
__noinline void iMOVQ( const iRegisterMMX& to, const ModSibBase& src ) { writeXMMop( 0x6f, to, src ); }
__forceinline void iMOVQ( const iRegisterMMX& to, const void* src ) { writeXMMop( 0x6f, to, src ); }
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterMMX& from ) { writeXMMop( 0x7f, from, dest ); }
__forceinline void iMOVQ( void* dest, const iRegisterMMX& from ) { writeXMMop( 0x7f, from, dest ); }
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterSSE& from ) { writeXMMop( 0xf3, 0x7e, from, dest ); }
__forceinline void iMOVQ( void* dest, const iRegisterSSE& from ) { writeXMMop( 0xf3, 0x7e, from, dest ); }
__forceinline void iMOVQ( const iRegisterSSE& to, const iRegisterMMX& from ) { writeXMMop( 0xf3, 0xd6, to, from ); }
__forceinline void iMOVQ( const iRegisterMMX& to, const iRegisterSSE& from )
{
// Manual implementation of this form of MOVQ, since its parameters are unique in a way
@ -776,16 +787,52 @@ __forceinline void iMOVQ( const iRegisterMMX& to, const iRegisterSSE& from )
//
#define IMPLEMENT_iMOVS( ssd, prefix ) \
__forceinline void iMOV##ssd( const iRegisterSSE& to, const iRegisterSSE& from ) { if( to != from ) writeXMMop<prefix>( 0x10, to, from ); } \
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const void* from ) { writeXMMop<prefix>( 0x10, to, from ); } \
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const ModSibBase& from ) { writeXMMop<prefix>( 0x10, to, from ); } \
__forceinline void iMOV##ssd( const void* to, const iRegisterSSE& from ) { writeXMMop<prefix>( 0x11, from, to ); } \
__forceinline void iMOV##ssd( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop<prefix>( 0x11, from, to ); }
__forceinline void iMOV##ssd( const iRegisterSSE& to, const iRegisterSSE& from ) { if( to != from ) writeXMMop( prefix, 0x10, to, from ); } \
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const void* from ) { writeXMMop( prefix, 0x10, to, from ); } \
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const ModSibBase& from ) { writeXMMop( prefix, 0x10, to, from ); } \
__forceinline void iMOV##ssd( const void* to, const iRegisterSSE& from ) { writeXMMop( prefix, 0x11, from, to ); } \
__forceinline void iMOV##ssd( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop( prefix, 0x11, from, to ); }
IMPLEMENT_iMOVS( SS, 0xf3 )
IMPLEMENT_iMOVS( SD, 0xf2 )
//////////////////////////////////////////////////////////////////////////////////////////
// Non-temporal movs only support a register as a target (ie, load form only, no stores)
//
__forceinline void iMOVNTDQA( const iRegisterSSE& to, const void* from )
{
iWrite<u32>( 0x2A380f66 );
iWriteDisp( to.Id, from );
}
__noinline void iMOVNTDQA( const iRegisterSSE& to, const ModSibBase& from )
{
iWrite<u32>( 0x2A380f66 );
EmitSibMagic( to.Id, from );
}
__forceinline void iMOVNTDQ( void* to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0xe7, from, to ); }
__noinline void iMOVNTDQA( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0xe7, from, to ); }
__forceinline void iMOVNTPD( void* to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0x2b, from, to ); }
__noinline void iMOVNTPD( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0x2b, from, to ); }
__forceinline void iMOVNTPS( void* to, const iRegisterSSE& from ) { writeXMMop( 0x2b, from, to ); }
__noinline void iMOVNTPS( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop( 0x2b, from, to ); }
__forceinline void iMOVNTQ( void* to, const iRegisterMMX& from ) { writeXMMop( 0xe7, from, to ); }
__noinline void iMOVNTQ( const ModSibBase& to, const iRegisterMMX& from ) { writeXMMop( 0xe7, from, to ); }
//////////////////////////////////////////////////////////////////////////////////////////
// Mov Low to High / High to Low
//
// These instructions come in xmmreg,xmmreg forms only!
//
__forceinline void iMOVLHPS( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop( 0x16, to, from ); }
__forceinline void iMOVHLPS( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop( 0x12, to, from ); }
__forceinline void iMOVLHPD( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0x16, to, from ); }
__forceinline void iMOVHLPD( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop( 0x66, 0x12, to, from ); }
}

View File

@ -331,42 +331,60 @@ namespace x86Emitter
template< typename T >
__emitinline void iMOVDZX( const iRegisterSIMD<T>& to, const iRegister32& from )
{
Internal::writeXMMop<0x66>( 0x6e, to, from );
Internal::writeXMMop( 0x66, 0x6e, to, from );
}
template< typename T >
__emitinline void iMOVDZX( const iRegisterSIMD<T>& to, const void* src )
{
Internal::writeXMMop<0x66>( 0x6e, to, src );
Internal::writeXMMop( 0x66, 0x6e, to, src );
}
template< typename T >
void iMOVDZX( const iRegisterSIMD<T>& to, const ModSibBase& src )
{
Internal::writeXMMop<0x66>( 0x6e, to, src );
Internal::writeXMMop( 0x66, 0x6e, to, src );
}
template< typename T >
__emitinline void iMOVD( const iRegister32& to, const iRegisterSIMD<T>& from )
{
Internal::writeXMMop<0x66>( 0x7e, from, to );
Internal::writeXMMop( 0x66, 0x7e, from, to );
}
template< typename T >
__emitinline void iMOVD( void* dest, const iRegisterSIMD<T>& from )
{
Internal::writeXMMop<0x66>( 0x7e, from, dest );
Internal::writeXMMop( 0x66, 0x7e, from, dest );
}
template< typename T >
void iMOVD( const ModSibBase& dest, const iRegisterSIMD<T>& from )
{
Internal::writeXMMop<0x66>( 0x7e, from, dest );
Internal::writeXMMop( 0x66, 0x7e, from, dest );
}
// ------------------------------------------------------------------------
// iMASKMOV:
// Selectively write bytes from mm1/xmm1 to memory location using the byte mask in mm2/xmm2.
// The default memory location is specified by DS:EDI. The most significant bit in each byte
// of the mask operand determines whether the corresponding byte in the source operand is
// written to the corresponding byte location in memory.
template< typename T >
static __forceinline void iMASKMOV( const iRegisterSIMD<T>& to, const iRegisterSIMD<T>& from ) { Internal::writeXMMop( 0x66, 0xf7, to, from ); }
// iPMOVMSKB:
// Creates a mask made up of the most significant bit of each byte of the source
// operand and stores the result in the low byte or word of the destination operand.
// Upper bits of the destination are cleared to zero.
//
// When operating on a 64-bit (MMX) source, the byte mask is 8 bits; when operating on
// 128-bit (SSE) source, the byte mask is 16-bits.
//
template< typename T >
static __forceinline void iPMOVMSKB( const iRegister32& to, const iRegisterSIMD<T>& from ) { Internal::writeXMMop( 0x66, 0xd7, to, from ); }
// ------------------------------------------------------------------------
@ -397,5 +415,22 @@ namespace x86Emitter
extern void iMOVSDZX( const iRegisterSSE& to, const void* from );
extern void iMOVSDZX( const iRegisterSSE& to, const ModSibBase& from );
extern void iMOVNTDQA( const iRegisterSSE& to, const void* from );
extern void iMOVNTDQA( const iRegisterSSE& to, const ModSibBase& from );
extern void iMOVNTDQ( void* to, const iRegisterSSE& from );
extern void iMOVNTDQA( const ModSibBase& to, const iRegisterSSE& from );
extern void iMOVNTPD( void* to, const iRegisterSSE& from );
extern void iMOVNTPD( const ModSibBase& to, const iRegisterSSE& from );
extern void iMOVNTPS( void* to, const iRegisterSSE& from );
extern void iMOVNTPS( const ModSibBase& to, const iRegisterSSE& from );
extern void iMOVNTQ( void* to, const iRegisterMMX& from );
extern void iMOVNTQ( const ModSibBase& to, const iRegisterMMX& from );
extern void iMOVLHPS( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVHLPS( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVLHPD( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVHLPD( const iRegisterSSE& to, const iRegisterSSE& from );
}

View File

@ -977,19 +977,13 @@ extern void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offs
extern void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
extern void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
extern void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from );
extern void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 );
extern void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from );
extern void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from, int offset=0 );
extern void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 );
extern void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 );
extern void SSE_MOVAPSRtoRm( x86IntRegType to, x86SSERegType from, int offset=0 );
extern void SSE_MOVAPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 );
extern void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 );
extern void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale=0 );
extern void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from );
extern void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from );
extern void SSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from );
extern void SSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from );
extern void SSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 );
extern void SSE_MOVUPSRtoRm( x86SSERegType to, x86IntRegType from, int offset=0 );

View File

@ -27,23 +27,27 @@
using namespace x86Emitter;
/* movq m64 to r64 */
emitterT void MOVQMtoR( x86MMXRegType to, uptr from )
emitterT void MOVQMtoR( x86MMXRegType to, uptr from ) { iMOVQ( iRegisterMMX(to), (void*)from ); }
emitterT void MOVQRtoM( uptr to, x86MMXRegType from ) { iMOVQ( (void*)to, iRegisterMMX(from) ); }
emitterT void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) { iMOVQ( iRegisterMMX(to), iRegisterMMX(from) ); }
emitterT void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset ) { iMOVQ( iRegisterMMX(to), ptr[iAddressReg(from)+offset] ); }
emitterT void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset ) { iMOVQ( ptr[iAddressReg(to)+offset], iRegisterMMX(from) ); }
emitterT void MOVDMtoMMX( x86MMXRegType to, uptr from ) { iMOVDZX( iRegisterMMX(to), (void*)from ); }
emitterT void MOVDMMXtoM( uptr to, x86MMXRegType from ) { iMOVD( (void*)to, iRegisterMMX(from) ); }
emitterT void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) { iMOVDZX( iRegisterMMX(to), iRegister32(from) ); }
emitterT void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset ) { iMOVDZX( iRegisterMMX(to), ptr[iAddressReg(from)+offset] ); }
emitterT void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) { iMOVD( iRegister32(to), iRegisterMMX(from) ); }
emitterT void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset ) { iMOVD( ptr[iAddressReg(to)+offset], iRegisterMMX(from) ); }
emitterT void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from)
{
iMOVQ( iRegisterMMX(to), (void*)from );
//write16( 0x6F0F );
//ModRM( 0, to, DISP32 );
//write32( MEMADDR(from, 4) );
iPMOVMSKB( iRegister32(to), iRegisterMMX(from) );
}
/* movq r64 to m64 */
emitterT void MOVQRtoM( uptr to, x86MMXRegType from )
{
iMOVQ( (void*)to, iRegisterMMX(from) );
//write16( 0x7F0F );
//ModRM( 0, from, DISP32 );
//write32(MEMADDR(to, 4));
}
/* pand r64 to r64 */
emitterT void PANDRtoR( x86MMXRegType to, x86MMXRegType from )
@ -474,73 +478,6 @@ emitterT void PUNPCKLDQMtoR( x86MMXRegType to, uptr from )
write32( MEMADDR(from, 4) );
}
emitterT void MOVQRtoR( x86MMXRegType to, x86MMXRegType from )
{
iMOVQ( iRegisterMMX(to), iRegisterMMX(from) );
//write16( 0x6F0F );
//ModRM( 3, to, from );
}
emitterT void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset )
{
iMOVQ( iRegisterMMX(to), ptr[iAddressReg(from)+offset] );
//write16( 0x6F0F );
//WriteRmOffsetFrom( to, from, offset );
}
emitterT void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset )
{
iMOVQ( ptr[iAddressReg(to)+offset], iRegisterMMX(from) );
//write16( 0x7F0F );
//WriteRmOffsetFrom( from, to, offset );
}
/* movd m32 to r64 */
emitterT void MOVDMtoMMX( x86MMXRegType to, uptr from )
{
iMOVDZX( iRegisterMMX(to), (void*)from );
//write16( 0x6E0F );
//ModRM( 0, to, DISP32 );
//write32( MEMADDR(from, 4) );
}
/* movd r64 to m32 */
emitterT void MOVDMMXtoM( uptr to, x86MMXRegType from )
{
iMOVD( (void*)to, iRegisterMMX(from) );
//write16( 0x7E0F );
//ModRM( 0, from, DISP32 );
//write32( MEMADDR(to, 4) );
}
emitterT void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from )
{
iMOVDZX( iRegisterMMX(to), iRegister32(from) );
//write16( 0x6E0F );
//ModRM( 3, to, from );
}
emitterT void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset )
{
iMOVDZX( iRegisterMMX(to), ptr[iAddressReg(from)+offset] );
//write16( 0x6E0F );
//WriteRmOffsetFrom( to, from, offset );
}
emitterT void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from )
{
iMOVD( iRegister32(to), iRegisterMMX(from) );
//write16( 0x7E0F );
//ModRM( 3, from, to );
}
emitterT void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset )
{
iMOVD( ptr[iAddressReg(to)+offset], iRegisterMMX(from) );
//write16( 0x7E0F );
//WriteRmOffsetFrom( from, to, offset );
}
// untested
emitterT void PACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from)
{
@ -554,12 +491,6 @@ emitterT void PACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from)
ModRM( 3, to, from );
}
emitterT void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from)
{
write16( 0xD70F );
ModRM( 3, to, from );
}
emitterT void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 )
{
if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3);
@ -583,8 +514,4 @@ emitterT void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8)
write8(imm8);
}
emitterT void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from)
{
write16(0xf70f);
ModRM( 3, to, from );
}
emitterT void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) { iMASKMOV( iRegisterMMX(to), iRegisterMMX(from) ); }

View File

@ -22,17 +22,6 @@
using namespace x86Emitter;
//////////////////////////////////////////////////////////////////////////////////////////
// AlwaysUseMovaps [const]
//
// This tells the recompiler's emitter to always use movaps instead of movdqa. Both instructions
// do the exact same thing, but movaps is 1 byte shorter, and thus results in a cleaner L1 cache
// and some marginal speed gains as a result. (it's possible someday in the future the per-
// formance of the two instructions could change, so this constant is provided to restore MOVDQA
// use easily at a later time, if needed).
//
static const bool AlwaysUseMovaps = true;
//------------------------------------------------------------------
// SSE instructions
@ -147,164 +136,28 @@ static const bool AlwaysUseMovaps = true;
SSE_SD_RtoR( 0xc20f ), \
write8( op )
/* movups [r32][r32*scale] to xmm1 */
emitterT void SSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
{
RexRXB(0, to, from2, from);
write16( 0x100f );
ModRM( 0, to, 0x4 );
SibSB( scale, from2, from );
}
#define DEFINE_LEGACY_MOV_OPCODE( mod, sse ) \
emitterT void sse##_MOV##mod##_M128_to_XMM( x86SSERegType to, uptr from ) { iMOV##mod( iRegisterSSE(to), (void*)from ); } \
emitterT void sse##_MOV##mod##_XMM_to_M128( uptr to, x86SSERegType from ) { iMOV##mod( (void*)to, iRegisterSSE(from) ); } \
emitterT void sse##_MOV##mod##RmtoR( x86SSERegType to, x86IntRegType from, int offset ) { iMOV##mod( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); } \
emitterT void sse##_MOV##mod##RtoRm( x86IntRegType to, x86SSERegType from, int offset ) { iMOV##mod( ptr[iAddressReg(to)+offset], iRegisterSSE(from) ); } \
emitterT void sse##_MOV##mod##RmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) \
{ iMOV##mod( iRegisterSSE(to), ptr[iAddressReg(from)+iAddressReg(from2)] ); } \
emitterT void sse##_MOV##mod##RtoRmS( x86IntRegType to, x86SSERegType from, x86IntRegType from2, int scale ) \
{ iMOV##mod( ptr[iAddressReg(to)+iAddressReg(from2)], iRegisterSSE(from) ); }
/* movups xmm1 to [r32][r32*scale] */
emitterT void SSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
{
RexRXB(1, to, from2, from);
write16( 0x110f );
ModRM( 0, to, 0x4 );
SibSB( scale, from2, from );
}
/* movups [r32] to r32 */
emitterT void SSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from )
{
RexRB(0, to, from);
write16( 0x100f );
ModRM( 0, to, from );
}
/* movups r32 to [r32] */
emitterT void SSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from )
{
RexRB(0, from, to);
write16( 0x110f );
ModRM( 0, from, to );
}
/* movlps [r32] to r32 */
emitterT void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from )
{
RexRB(1, to, from);
write16( 0x120f );
ModRM( 0, to, from );
}
emitterT void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, to, from);
write16( 0x120f );
WriteRmOffsetFrom(to, from, offset);
}
/* movaps r32 to [r32] */
emitterT void SSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from )
{
RexRB(0, from, to);
write16( 0x130f );
ModRM( 0, from, to );
}
emitterT void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, from, to);
write16( 0x130f );
WriteRmOffsetFrom(from, to, offset);
}
/* movaps [r32][r32*scale] to xmm1 */
emitterT void SSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
{
assert( from != EBP );
RexRXB(0, to, from2, from);
write16( 0x280f );
ModRM( 0, to, 0x4 );
SibSB( scale, from2, from );
}
/* movaps xmm1 to [r32][r32*scale] */
emitterT void SSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale )
{
assert( from != EBP );
RexRXB(0, to, from2, from);
write16( 0x290f );
ModRM( 0, to, 0x4 );
SibSB( scale, from2, from );
}
// movaps [r32+offset] to r32
emitterT void SSE_MOVAPSRmtoR( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, to, from);
write16( 0x280f );
WriteRmOffsetFrom(to, from, offset);
}
// movaps r32 to [r32+offset]
emitterT void SSE_MOVAPSRtoRm( x86IntRegType to, x86SSERegType from, int offset )
{
RexRB(0, from, to);
write16( 0x290f );
WriteRmOffsetFrom(from, to, offset);
}
// movdqa [r32+offset] to r32
emitterT void SSE2_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset )
{
if( AlwaysUseMovaps )
SSE_MOVAPSRmtoR( to, from, offset );
else
{
write8(0x66);
RexRB(0, to, from);
write16( 0x6f0f );
WriteRmOffsetFrom(to, from, offset);
}
}
// movdqa r32 to [r32+offset]
emitterT void SSE2_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset )
{
if( AlwaysUseMovaps )
SSE_MOVAPSRtoRm( to, from, offset );
else
{
write8(0x66);
RexRB(0, from, to);
write16( 0x7f0f );
WriteRmOffsetFrom(from, to, offset);
}
}
// movups [r32+offset] to r32
emitterT void SSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, to, from);
write16( 0x100f );
WriteRmOffsetFrom(to, from, offset);
}
// movups r32 to [r32+offset]
emitterT void SSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from, int offset )
{
RexRB(0, from, to);
write16( 0x110f );
WriteRmOffsetFrom(from, to, offset);
}
DEFINE_LEGACY_MOV_OPCODE( UPS, SSE )
DEFINE_LEGACY_MOV_OPCODE( APS, SSE )
DEFINE_LEGACY_MOV_OPCODE( LPS, SSE )
DEFINE_LEGACY_MOV_OPCODE( HPS, SSE )
DEFINE_LEGACY_MOV_OPCODE( DQA, SSE2 )
DEFINE_LEGACY_MOV_OPCODE( DQU, SSE2 )
//**********************************************************************************/
//MOVAPS: Move aligned Packed Single Precision FP values *
//**********************************************************************************
//emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); }
//emitterT void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); }
//emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSERtoR( 0x280f ); } }
//emitterT void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); }
//emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); }
emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { iMOVAPS( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { iMOVAPS( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVAPS( iRegisterSSE(to), iRegisterSSE(from) ); }
emitterT void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { iMOVUPS( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { iMOVUPS( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVQZX( iRegisterSSE(to), (void*)from ); }
emitterT void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVQZX( iRegisterSSE(to), iRegisterSSE(from) ); }
@ -328,78 +181,41 @@ emitterT void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) {
emitterT void SSE2_MOVSD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { iMOVSDZX( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); }
emitterT void SSE2_MOVSD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVSD( ptr[iAddressReg(to)+offset], iRegisterSSE(from) ); }
/*emitterT void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x100f, 0 ); }
emitterT void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); }
emitterT void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSE_SS_RtoR( 0x100f ); } }
emitterT void SSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
{
write8(0xf3);
RexRB(0, to, from);
write16( 0x100f );
WriteRmOffsetFrom(to, from, offset);
}
emitterT void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset )
{
write8(0xf3);
RexRB(0, from, to);
write16(0x110f);
WriteRmOffsetFrom(from, to, offset);
}*/
emitterT void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); }
emitterT void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMASKMOV( iRegisterSSE(to), iRegisterSSE(from) ); }
//**********************************************************************************/
//MOVLPS: Move low Packed Single-Precision FP *
//**********************************************************************************
emitterT void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x120f, 0 ); }
emitterT void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); }
emitterT void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, to, from);
write16( 0x120f );
WriteRmOffsetFrom(to, from, offset);
}
emitterT void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset )
{
RexRB(0, from, to);
write16(0x130f);
WriteRmOffsetFrom(from, to, offset);
}
emitterT void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVLPS( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { iMOVLPS( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { iMOVLPS( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); }
emitterT void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVLPS( ptr[iAddressReg(to)+offset], iRegisterSSE(from) ); }
/////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//MOVHPS: Move High Packed Single-Precision FP *
//**********************************************************************************
emitterT void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x160f, 0 ); }
emitterT void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); }
emitterT void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset )
{
RexRB(0, to, from);
write16( 0x160f );
WriteRmOffsetFrom(to, from, offset);
}
emitterT void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset )
{
RexRB(0, from, to);
write16(0x170f);
WriteRmOffsetFrom(from, to, offset);
}
emitterT void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVHPS( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { iMOVHPS( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { iMOVHPS( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); }
emitterT void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVHPS( ptr[iAddressReg(to)+offset], iRegisterSSE(from) ); }
/////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//MOVLHPS: Moved packed Single-Precision FP low to high *
//**********************************************************************************
emitterT void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); }
emitterT void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVLHPS( iRegisterSSE(to), iRegisterSSE(from) ); }
//////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//MOVHLPS: Moved packed Single-Precision FP High to Low *
//**********************************************************************************
emitterT void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); }
emitterT void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVHLPS( iRegisterSSE(to), iRegisterSSE(from) ); }
emitterT void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { iPMOVMSKB( iRegister32(to), iRegisterSSE(from) ); }
///////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
@ -938,30 +754,8 @@ emitterT void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SS
emitterT void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEF0F ); }
///////////////////////////////////////////////////////////////////////////////////////
emitterT void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from) { if( AlwaysUseMovaps ) SSE_MOVAPS_M128_to_XMM( to, from ); else SSEMtoR66(0x6F0F); }
emitterT void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ) { if( AlwaysUseMovaps ) SSE_MOVAPS_XMM_to_M128( to, from ); else SSERtoM66(0x7F0F); }
emitterT void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { if( AlwaysUseMovaps ) SSE_MOVAPS_XMM_to_XMM( to, from ); else if( to != from ) SSERtoR66(0x6F0F); }
emitterT void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from)
{
if( AlwaysUseMovaps )
SSE_MOVUPS_M128_to_XMM( to, from );
else
{
write8(0xF3);
SSEMtoR(0x6F0F, 0);
}
}
emitterT void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from)
{
if( AlwaysUseMovaps )
SSE_MOVUPS_XMM_to_M128( to, from );
else
{
write8(0xF3);
SSERtoM(0x7F0F, 0);
}
}
// shift right logical
@ -1153,8 +947,6 @@ emitterT void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR6
emitterT void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); }
emitterT void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xF40F ); }
emitterT void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); }
emitterT void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); }
emitterT void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); }

View File

@ -675,16 +675,39 @@ namespace x86Emitter
}
//////////////////////////////////////////////////////////////////////////////////////////
// ALWAYS_USE_MOVAPS [define] / AlwaysUseMovaps [const]
//
// This tells the recompiler's emitter to always use movaps instead of movdqa. Both instructions
// do the exact same thing, but movaps is 1 byte shorter, and thus results in a cleaner L1 cache
// and some marginal speed gains as a result. (it's possible someday in the future the per-
// formance of the two instructions could change, so this constant is provided to restore MOVDQA
// use easily at a later time, if needed).
#define ALWAYS_USE_MOVAPS
extern const Internal::MovapsImplAll< 0, 0x28, 0x29 > iMOVAPS;
#ifdef ALWAYS_USE_MOVAPS
static const bool AlwaysUseMovaps = true;
#else
static const bool AlwaysUseMovaps = false;
#endif
extern const Internal::MovapsImplAll< 0, 0x28, 0x29 > iMOVAPS;
extern const Internal::MovapsImplAll< 0, 0x10, 0x11 > iMOVUPS;
extern const Internal::MovapsImplAll< 0x66, 0x28, 0x29 > iMOVAPD;
extern const Internal::MovapsImplAll< 0x66, 0x10, 0x11 > iMOVUPD;
#ifdef ALWAYS_USE_MOVAPS
extern const Internal::MovapsImplAll< 0x66, 0x6f, 0x7f > iMOVDQA;
extern const Internal::MovapsImplAll< 0xf3, 0x6f, 0x7f > iMOVDQU;
#else
extern const Internal::MovapsImplAll< 0, 0x28, 0x29 > iMOVDQA;
extern const Internal::MovapsImplAll< 0, 0x10, 0x11 > iMOVDQU;
#endif
extern const Internal::MovhlImplAll< 0, 0x16 > iMOVHPS;
extern const Internal::MovhlImplAll< 0, 0x12 > iMOVLPS;
extern const Internal::MovhlImplAll< 0x66, 0x16 > iMOVHPD;
extern const Internal::MovhlImplAll< 0x66, 0x12 > iMOVLPD;
}