Emitter: Yay! More instructions! All forms of PADD/PSUB/PSRL/PSLL. I'm getting closer!

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1032 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-20 19:25:35 +00:00
parent cc48702b17
commit 73e50f49ea
9 changed files with 452 additions and 825 deletions

View File

@ -34,57 +34,81 @@ enum G1Type
};
// -------------------------------------------------------------------
template< typename ImmType >
class Group1Impl
//
template< G1Type InstType >
class xImpl_Group1
{
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
public:
Group1Impl() {} // because GCC doesn't like static classes
static __emitinline void Emit( G1Type InstType, const xRegister<ImmType>& to, const xRegister<ImmType>& from )
public:
// ------------------------------------------------------------------------
template< typename T > __forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const
{
prefix16();
xWrite<u8>( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
prefix16<T>();
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
ModRM_Direct( from.Id, to.Id );
}
static __emitinline void Emit( G1Type InstType, const ModSibBase& sibdest, const xRegister<ImmType>& from )
// ------------------------------------------------------------------------
template< typename T > __forceinline void operator()( const xRegister<T>& to, const void* src ) const
{
prefix16();
xWrite<u8>( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
EmitSibMagic( from.Id, sibdest );
prefix16<T>();
xWrite<u8>( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
xWriteDisp( to.Id, src );
}
static __emitinline void Emit( G1Type InstType, const xRegister<ImmType>& to, const ModSibBase& sibsrc )
// ------------------------------------------------------------------------
template< typename T > __forceinline void operator()( void* dest, const xRegister<T>& from ) const
{
prefix16();
xWrite<u8>( (Is8BitOperand() ? 2 : 3) | (InstType<<3) );
EmitSibMagic( to.Id, sibsrc );
}
static __emitinline void Emit( G1Type InstType, void* dest, const xRegister<ImmType>& from )
{
prefix16();
xWrite<u8>( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
prefix16<T>();
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
xWriteDisp( from.Id, dest );
}
static __emitinline void Emit( G1Type InstType, const xRegister<ImmType>& to, const void* src )
// ------------------------------------------------------------------------
template< typename T > __noinline void operator()( const ModSibBase& sibdest, const xRegister<T>& from ) const
{
prefix16();
xWrite<u8>( (Is8BitOperand() ? 2 : 3) | (InstType<<3) );
xWriteDisp( to.Id, src );
prefix16<T>();
xWrite<u8>( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
EmitSibMagic( from.Id, sibdest );
}
static __emitinline void Emit( G1Type InstType, const xRegister<ImmType>& to, int imm )
// ------------------------------------------------------------------------
template< typename T > __noinline void operator()( const xRegister<T>& to, const ModSibBase& sibsrc ) const
{
prefix16();
if( !Is8BitOperand() && is_s8( imm ) )
prefix16<T>();
xWrite<u8>( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
EmitSibMagic( to.Id, sibsrc );
}
// ------------------------------------------------------------------------
// Note on Imm forms : use int as the source operand since it's "reasonably inert" from a compiler
// perspective. (using uint tends to make the compiler try and fail to match signed immediates with
// one of the other overloads).
template< typename T > __noinline void operator()( const ModSibStrict<T>& sibdest, int imm ) const
{
if( Is8BitOp<T>() )
{
xWrite<u8>( 0x80 );
EmitSibMagic( InstType, sibdest );
xWrite<s8>( imm );
}
else
{
prefix16<T>();
xWrite<u8>( is_s8( imm ) ? 0x83 : 0x81 );
EmitSibMagic( InstType, sibdest );
if( is_s8( imm ) )
xWrite<s8>( imm );
else
xWrite<T>( imm );
}
}
// ------------------------------------------------------------------------
template< typename T > __forceinline void operator()( const xRegister<T>& to, int imm ) const
{
prefix16<T>();
if( !Is8BitOp<T>() && is_s8( imm ) )
{
xWrite<u8>( 0x83 );
ModRM_Direct( InstType, to.Id );
@ -93,65 +117,17 @@ public:
else
{
if( to.IsAccumulator() )
xWrite<u8>( (Is8BitOperand() ? 4 : 5) | (InstType<<3) );
xWrite<u8>( (Is8BitOp<T>() ? 4 : 5) | (InstType<<3) );
else
{
xWrite<u8>( Is8BitOperand() ? 0x80 : 0x81 );
xWrite<u8>( Is8BitOp<T>() ? 0x80 : 0x81 );
ModRM_Direct( InstType, to.Id );
}
xWrite<ImmType>( imm );
xWrite<T>( imm );
}
}
static __emitinline void Emit( G1Type InstType, const ModSibStrict<ImmType>& sibdest, int imm )
{
if( Is8BitOperand() )
{
xWrite<u8>( 0x80 );
EmitSibMagic( InstType, sibdest );
xWrite<ImmType>( imm );
}
else
{
prefix16();
xWrite<u8>( is_s8( imm ) ? 0x83 : 0x81 );
EmitSibMagic( InstType, sibdest );
if( is_s8( imm ) )
xWrite<s8>( imm );
else
xWrite<ImmType>( imm );
}
}
};
// -------------------------------------------------------------------
//
template< G1Type InstType >
class Group1ImplAll
{
public:
template< typename T >
__forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const { Group1Impl<T>::Emit( InstType, to, from ); }
template< typename T >
__forceinline void operator()( const xRegister<T>& to, const void* src ) const { Group1Impl<T>::Emit( InstType, to, src ); }
template< typename T >
__forceinline void operator()( void* dest, const xRegister<T>& from ) const { Group1Impl<T>::Emit( InstType, dest, from ); }
template< typename T >
__noinline void operator()( const ModSibBase& sibdest, const xRegister<T>& from ) const { Group1Impl<T>::Emit( InstType, sibdest, from ); }
template< typename T >
__noinline void operator()( const xRegister<T>& to, const ModSibBase& sibsrc ) const { Group1Impl<T>::Emit( InstType, to, sibsrc ); }
// Note on Imm forms : use int as the source operand since it's "reasonably inert" from a compiler
// perspective. (using uint tends to make the compiler try and fail to match signed immediates with
// one of the other overloads).
template< typename T >
__noinline void operator()( const ModSibStrict<T>& sibdest, int imm ) const { Group1Impl<T>::Emit( InstType, sibdest, imm ); }
template< typename T >
__forceinline void operator()( const xRegister<T>& to, int imm ) const { Group1Impl<T>::Emit( InstType, to, imm ); }
Group1ImplAll() {} // Why does GCC need these?
xImpl_Group1() {} // Why does GCC need these?
};
// ------------------------------------------------------------------------
@ -159,34 +135,34 @@ public:
// Note: ANDN [AndNot] is handled below separately.
//
template< G1Type InstType, u8 OpcodeSSE >
class G1LogicImpl_PlusSSE : public Group1ImplAll<InstType>
class xImpl_G1Logic : public xImpl_Group1<InstType>
{
public:
using Group1ImplAll<InstType>::operator();
using xImpl_Group1<InstType>::operator();
const SSELogicImpl<0x00,OpcodeSSE> PS; // packed single precision
const SSELogicImpl<0x66,OpcodeSSE> PD; // packed double precision
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; // packed single precision
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; // packed double precision
G1LogicImpl_PlusSSE() {}
xImpl_G1Logic() {}
};
// ------------------------------------------------------------------------
// This calss combines x86 with SSE/SSE2 arithmetic operations (ADD/SUB).
// This class combines x86 with SSE/SSE2 arithmetic operations (ADD/SUB).
//
template< G1Type InstType, u8 OpcodeSSE >
class G1ArithmeticImpl_PlusSSE : public G1LogicImpl_PlusSSE<InstType, OpcodeSSE >
class xImpl_G1Arith : public xImpl_G1Logic<InstType, OpcodeSSE >
{
public:
using Group1ImplAll<InstType>::operator();
using xImpl_Group1<InstType>::operator();
const SSELogicImpl<0xf3,OpcodeSSE> SS; // scalar single precision
const SSELogicImpl<0xf2,OpcodeSSE> SD; // scalar double precision
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; // scalar single precision
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; // scalar double precision
G1ArithmeticImpl_PlusSSE() {}
xImpl_G1Arith() {}
};
// ------------------------------------------------------------------------
class G1CompareImpl_PlusSSE : Group1ImplAll< G1Type_CMP >
class xImpl_G1Compare : xImpl_Group1< G1Type_CMP >
{
protected:
template< u8 Prefix > struct Woot
@ -198,12 +174,12 @@ protected:
};
public:
using Group1ImplAll< G1Type_CMP >::operator();
using xImpl_Group1< G1Type_CMP >::operator();
const Woot<0x00> PS;
const Woot<0x66> PD;
const Woot<0xf3> SS;
const Woot<0xf2> SD;
G1CompareImpl_PlusSSE() {} //GCWhat?
xImpl_G1Compare() {} //GCWhat?
};

View File

@ -38,92 +38,61 @@ enum G2Type
// Optimization Note: For Imm forms, we ignore the instruction if the shift count is zero.
// This is a safe optimization since any zero-value shift does not affect any flags.
//
template< G2Type InstType, typename ImmType >
class Group2Impl
{
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
public:
Group2Impl() {} // For the love of GCC.
// ------------------------------------------------------------------------
static __emitinline void Emit( const xRegister<ImmType>& to )
{
prefix16();
xWrite<u8>( Is8BitOperand() ? 0xd2 : 0xd3 );
ModRM_Direct( InstType, to.Id );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( const xRegister<ImmType>& to, u8 imm )
{
if( imm == 0 ) return;
prefix16();
if( imm == 1 )
{
// special encoding of 1's
xWrite<u8>( Is8BitOperand() ? 0xd0 : 0xd1 );
ModRM_Direct( InstType, to.Id );
}
else
{
xWrite<u8>( Is8BitOperand() ? 0xc0 : 0xc1 );
ModRM_Direct( InstType, to.Id );
xWrite<u8>( imm );
}
}
// ------------------------------------------------------------------------
static __emitinline void Emit( const ModSibStrict<ImmType>& sibdest )
{
prefix16();
xWrite<u8>( Is8BitOperand() ? 0xd2 : 0xd3 );
EmitSibMagic( InstType, sibdest );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( const ModSibStrict<ImmType>& sibdest, u8 imm )
{
if( imm == 0 ) return;
prefix16();
if( imm == 1 )
{
// special encoding of 1's
xWrite<u8>( Is8BitOperand() ? 0xd0 : 0xd1 );
EmitSibMagic( InstType, sibdest );
}
else
{
xWrite<u8>( Is8BitOperand() ? 0xc0 : 0xc1 );
EmitSibMagic( InstType, sibdest );
xWrite<u8>( imm );
}
}
};
// -------------------------------------------------------------------
//
template< G2Type InstType >
class Group2ImplAll
{
public:
template< typename T > __forceinline void operator()( const xRegister<T>& to, __unused const xRegisterCL& from ) const
{ Group2Impl<InstType,T>::Emit( to ); }
{
prefix16<T>();
xWrite<u8>( Is8BitOp<T>() ? 0xd2 : 0xd3 );
ModRM_Direct( InstType, to.Id );
}
template< typename T > __noinline void operator()( const ModSibStrict<T>& sibdest, __unused const xRegisterCL& from ) const
{ Group2Impl<InstType,T>::Emit( sibdest ); }
{
prefix16<T>();
xWrite<u8>( Is8BitOp<T>() ? 0xd2 : 0xd3 );
EmitSibMagic( InstType, sibdest );
}
template< typename T > __noinline void operator()( const ModSibStrict<T>& sibdest, u8 imm ) const
{ Group2Impl<InstType,T>::Emit( sibdest, imm ); }
{
if( imm == 0 ) return;
prefix16<T>();
if( imm == 1 )
{
// special encoding of 1's
xWrite<u8>( Is8BitOp<T>() ? 0xd0 : 0xd1 );
EmitSibMagic( InstType, sibdest );
}
else
{
xWrite<u8>( Is8BitOp<T>() ? 0xc0 : 0xc1 );
EmitSibMagic( InstType, sibdest );
xWrite<u8>( imm );
}
}
template< typename T > __forceinline void operator()( const xRegister<T>& to, u8 imm ) const
{ Group2Impl<InstType,T>::Emit( to, imm ); }
{
if( imm == 0 ) return;
prefix16<T>();
if( imm == 1 )
{
// special encoding of 1's
xWrite<u8>( Is8BitOp<T>() ? 0xd0 : 0xd1 );
ModRM_Direct( InstType, to.Id );
}
else
{
xWrite<u8>( Is8BitOp<T>() ? 0xc0 : 0xc1 );
ModRM_Direct( InstType, to.Id );
xWrite<u8>( imm );
}
}
Group2ImplAll() {} // I am a class with no members, so I need an explicit constructor! Sense abounds.
};

View File

@ -31,45 +31,27 @@ enum G3Type
G3Type_iDIV = 7
};
// ------------------------------------------------------------------------
template< typename ImmType >
class Group3Impl
{
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) xWrite<u8>( 0x66 ); }
public:
Group3Impl() {} // For the love of GCC.
static __emitinline void Emit( G3Type InstType, const xRegister<ImmType>& from )
{
prefix16();
xWrite<u8>(Is8BitOperand() ? 0xf6 : 0xf7 );
ModRM_Direct( InstType, from.Id );
}
static __emitinline void Emit( G3Type InstType, const ModSibStrict<ImmType>& sibsrc )
{
prefix16();
xWrite<u8>( Is8BitOperand() ? 0xf6 : 0xf7 );
EmitSibMagic( InstType, sibsrc );
}
};
// -------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////
//
template< G3Type InstType >
class Group3ImplAll
{
public:
template< typename T >
__forceinline void operator()( const xRegister<T>& from ) const { Group3Impl<T>::Emit( InstType, from ); }
// ------------------------------------------------------------------------
template< typename T > __forceinline void operator()( const xRegister<T>& from ) const
{
prefix16<T>();
xWrite<u8>(Is8BitOp<T>() ? 0xf6 : 0xf7 );
ModRM_Direct( InstType, from.Id );
}
template< typename T >
__noinline void operator()( const ModSibStrict<T>& from ) const { Group3Impl<T>::Emit( InstType, from ); }
// ------------------------------------------------------------------------
template< typename T > __noinline void operator()( const ModSibStrict<T>& from ) const
{
prefix16<T>();
xWrite<u8>( Is8BitOp<T>() ? 0xf6 : 0xf7 );
EmitSibMagic( InstType, from );
}
Group3ImplAll() {}
};
@ -78,15 +60,15 @@ public:
// This class combines x86 and SSE/SSE2 instructions for iMUL and iDIV.
//
template< G3Type InstType, u8 OpcodeSSE >
class G3Impl_PlusSSE : public Group3ImplAll<InstType>
class xImpl_Group3 : public Group3ImplAll<InstType>
{
public:
const SSELogicImpl<0x00,OpcodeSSE> PS;
const SSELogicImpl<0x66,OpcodeSSE> PD;
const SSELogicImpl<0xf3,OpcodeSSE> SS;
const SSELogicImpl<0xf2,OpcodeSSE> SD;
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS;
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD;
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS;
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD;
G3Impl_PlusSSE() {}
xImpl_Group3() {}
};
//////////////////////////////////////////////////////////////////////////////////////////
@ -162,14 +144,14 @@ public:
};
// ------------------------------------------------------------------------
class iMul_PlusSSE : public G3Impl_PlusSSE<G3Type_iMUL,0x59>
class xImpl_iMul : public xImpl_Group3<G3Type_iMUL,0x59>
{
protected:
typedef iMulImpl<u32> iMUL32;
typedef iMulImpl<u16> iMUL16;
public:
using G3Impl_PlusSSE<G3Type_iMUL,0x59>::operator();
using xImpl_Group3<G3Type_iMUL,0x59>::operator();
__forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { iMUL32::Emit( to, from ); }
__forceinline void operator()( const xRegister32& to, const void* src ) const { iMUL32::Emit( to, src ); }
@ -183,5 +165,5 @@ public:
__noinline void operator()( const xRegister16& to, const ModSibBase& src ) const { iMUL16::Emit( to, src ); }
__noinline void operator()( const xRegister16& to, const ModSibBase& from, s16 imm ) const { iMUL16::Emit( to, from, imm ); }
iMul_PlusSSE() {}
xImpl_iMul() {}
};

View File

@ -129,11 +129,11 @@ public:
};
//////////////////////////////////////////////////////////////////////////////////////////
// PLogicImplAll - Implements logic forms for MMX/SSE instructions, and can be used for
// SimdImpl_PackedLogic - Implements logic forms for MMX/SSE instructions, and can be used for
// a few other various instruction too (anything which comes in simdreg,simdreg/ModRM forms).
//
template< u8 Opcode >
class PLogicImplAll
class SimdImpl_PackedLogic
{
public:
template< typename T >
@ -143,21 +143,40 @@ public:
template< typename T >
__noinline void operator()( const xRegisterSIMD<T>& to, const ModSibBase& from ) const { writeXMMop( 0x66, Opcode, to, from ); }
PLogicImplAll() {} //GCWho?
SimdImpl_PackedLogic() {} //GCWho?
};
// ------------------------------------------------------------------------
// For implementing SSE-only logic operations, like ANDPS/ANDPD
// For implementing SSE-only logic operations that have reg,reg/rm forms only,
// like ANDPS/ANDPD
//
template< u8 Prefix, u8 Opcode >
class SSELogicImpl
class SimdImpl_DestRegSSE
{
public:
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__forceinline void operator()( const xRegisterSSE& to, const void* from ) const { writeXMMop( Prefix, Opcode, to, from ); }
__noinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
SSELogicImpl() {} //GCWho?
SimdImpl_DestRegSSE() {} //GCWho?
};
// ------------------------------------------------------------------------
// For implementing MMX/SSE operations that have reg,reg/rm forms only,
// but accept either MM or XMM destinations (most PADD/PSUB and other P srithmetic ops).
//
template< u8 Prefix, u8 Opcode >
class SimdImpl_DestRegEither
{
public:
template< typename DestOperandType >
__forceinline void operator()( const xRegisterSIMD<DestOperandType>& to, const xRegisterSIMD<DestOperandType>& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
template< typename DestOperandType >
__forceinline void operator()( const xRegisterSIMD<DestOperandType>& to, const void* from ) const { writeXMMop( Prefix, Opcode, to, from ); }
template< typename DestOperandType >
__noinline void operator()( const xRegisterSIMD<DestOperandType>& to, const ModSibBase& from ) const { writeXMMop( Prefix, Opcode, to, from ); }
SimdImpl_DestRegEither() {} //GCWho?
};
// ------------------------------------------------------------------------
@ -165,76 +184,76 @@ public:
// can be regDirect or ModRM (indirect).
//
template< u8 Prefix, u8 Opcode, typename DestRegType, typename SrcRegType, typename SrcOperandType >
class SSEImpl_DestRegForm
class SimdImpl_DestRegStrict
{
public:
__forceinline void operator()( const DestRegType& to, const SrcRegType& from ) const { writeXMMop( Prefix, Opcode, to, from, true ); }
__forceinline void operator()( const DestRegType& to, const SrcOperandType* from ) const { writeXMMop( Prefix, Opcode, to, from, true ); }
__noinline void operator()( const DestRegType& to, const ModSibStrict<SrcOperandType>& from ) const { writeXMMop( Prefix, Opcode, to, from, true ); }
SSEImpl_DestRegForm() {} //GCWho?
SimdImpl_DestRegStrict() {} //GCWho?
};
// ------------------------------------------------------------------------
template< u8 OpcodeSSE >
class SSEImpl_PSPD_SSSD
class SimdImpl_PSPD_SSSD
{
public:
const SSELogicImpl<0x00,OpcodeSSE> PS; // packed single precision
const SSELogicImpl<0x66,OpcodeSSE> PD; // packed double precision
const SSELogicImpl<0xf3,OpcodeSSE> SS; // scalar single precision
const SSELogicImpl<0xf2,OpcodeSSE> SD; // scalar double precision
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; // packed single precision
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; // packed double precision
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; // scalar single precision
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; // scalar double precision
SSEImpl_PSPD_SSSD() {} //GChow?
SimdImpl_PSPD_SSSD() {} //GChow?
};
// ------------------------------------------------------------------------
//
template< u8 OpcodeSSE >
class SSEAndNotImpl
class SimdImpl_AndNot
{
public:
const SSELogicImpl<0x00,OpcodeSSE> PS;
const SSELogicImpl<0x66,OpcodeSSE> PD;
SSEAndNotImpl() {}
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS;
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD;
SimdImpl_AndNot() {}
};
// ------------------------------------------------------------------------
// For instructions that have SS/SD form only (UCOMI, etc)
// AltPrefix - prefixed used for doubles (SD form).
template< u8 AltPrefix, u8 OpcodeSSE >
class SSEImpl_SS_SD
class SimdImpl_SS_SD
{
public:
const SSELogicImpl<0x00,OpcodeSSE> SS;
const SSELogicImpl<AltPrefix,OpcodeSSE> SD;
SSEImpl_SS_SD() {}
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> SS;
const SimdImpl_DestRegSSE<AltPrefix,OpcodeSSE> SD;
SimdImpl_SS_SD() {}
};
// ------------------------------------------------------------------------
// For instructions that have PS/SS form only (most commonly reciprocal Sqrt functions)
template< u8 OpcodeSSE >
class SSE_rSqrtImpl
class SimdImpl_rSqrt
{
public:
const SSELogicImpl<0x00,OpcodeSSE> PS;
const SSELogicImpl<0xf3,OpcodeSSE> SS;
SSE_rSqrtImpl() {}
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS;
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS;
SimdImpl_rSqrt() {}
};
// ------------------------------------------------------------------------
// For instructions that have PS/SS/SD form only (most commonly Sqrt functions)
template< u8 OpcodeSSE >
class SSE_SqrtImpl : public SSE_rSqrtImpl<OpcodeSSE>
class SimdImpl_Sqrt : public SimdImpl_rSqrt<OpcodeSSE>
{
public:
const SSELogicImpl<0xf2,OpcodeSSE> SD;
SSE_SqrtImpl() {}
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD;
SimdImpl_Sqrt() {}
};
// ------------------------------------------------------------------------
template< u8 OpcodeSSE >
class SSEImpl_Shuffle
class SimdImpl_Shuffle
{
protected:
template< u8 Prefix > struct Woot
@ -249,12 +268,12 @@ public:
const Woot<0x00> PS;
const Woot<0x66> PD;
SSEImpl_Shuffle() {} //GCWhat?
SimdImpl_Shuffle() {} //GCWhat?
};
// ------------------------------------------------------------------------
template< SSE2_ComparisonType CType >
class SSECompareImpl
class SimdImpl_Compare
{
protected:
template< u8 Prefix > struct Woot
@ -270,5 +289,87 @@ public:
const Woot<0x66> PD;
const Woot<0xf3> SS;
const Woot<0xf2> SD;
SSECompareImpl() {} //GCWhat?
SimdImpl_Compare() {} //GCWhat?
};
//////////////////////////////////////////////////////////////////////////////////////////
//
//
template< u8 Opcode1, u8 OpcodeImm, u8 Modcode >
class SimdImpl_Shift
{
public:
SimdImpl_Shift() {}
template< typename OperandType >
__forceinline void operator()( const xRegisterSIMD<OperandType>& to, const xRegisterSIMD<OperandType>& from ) const
{
writeXMMop( 0x66, Opcode1, to, from );
}
template< typename OperandType >
__forceinline void operator()( const xRegisterSIMD<OperandType>& to, const void* from ) const
{
writeXMMop( 0x66, Opcode1, to, from );
}
template< typename OperandType >
__noinline void operator()( const xRegisterSIMD<OperandType>& to, const ModSibBase& from ) const
{
writeXMMop( 0x66, Opcode1, to, from );
}
template< typename OperandType >
__emitinline void operator()( const xRegisterSIMD<OperandType>& to, u8 imm ) const
{
SimdPrefix( (sizeof( OperandType ) == 16) ? 0x66 : 0, OpcodeImm );
ModRM( 3, (int)Modcode, to.Id );
xWrite<u8>( imm );
}
};
// ------------------------------------------------------------------------
template< u8 OpcodeBase1, u8 OpcodeBaseImm, u8 Modcode >
class SimdImpl_ShiftAll
{
public:
const SimdImpl_Shift<OpcodeBase1+1,OpcodeBaseImm+1,Modcode> W;
const SimdImpl_Shift<OpcodeBase1+2,OpcodeBaseImm+2,Modcode> D;
const SimdImpl_Shift<OpcodeBase1+3,OpcodeBaseImm+3,Modcode> Q;
void DQ( const xRegisterSSE& to, u8 imm ) const
{
SimdPrefix( 0x66, OpcodeBaseImm+3 );
ModRM( 3, (int)Modcode+1, to.Id );
xWrite<u8>( imm );
}
SimdImpl_ShiftAll() {}
};
//////////////////////////////////////////////////////////////////////////////////////////
//
template< u8 OpcodeB, u8 OpcodeS, u8 OpcodeUS, u8 OpcodeQ >
class SimdImpl_AddSub
{
public:
const SimdImpl_DestRegEither<0x66,OpcodeB> B;
const SimdImpl_DestRegEither<0x66,OpcodeB+1> W;
const SimdImpl_DestRegEither<0x66,OpcodeB+2> D;
const SimdImpl_DestRegEither<0x66,OpcodeQ> Q;
// Add/Sub packed signed byte [8bit] integers from src into dest, and saturate the results.
const SimdImpl_DestRegEither<0x66,OpcodeS> SB;
// Add/Sub packed signed word [16bit] integers from src into dest, and saturate the results.
const SimdImpl_DestRegEither<0x66,OpcodeS+1> SW;
// Add/Sub packed unsigned byte [8bit] integers from src into dest, and saturate the results.
const SimdImpl_DestRegEither<0x66,OpcodeUS> USB;
// Add/Sub packed unsigned word [16bit] integers from src into dest, and saturate the results.
const SimdImpl_DestRegEither<0x66,OpcodeUS+1> USW;
SimdImpl_AddSub() {}
};

View File

@ -253,16 +253,16 @@ using namespace Internal;
const MovImplAll xMOV;
const TestImplAll xTEST;
const G1LogicImpl_PlusSSE<G1Type_AND,0x54> xAND;
const G1LogicImpl_PlusSSE<G1Type_OR,0x56> xOR;
const G1LogicImpl_PlusSSE<G1Type_XOR,0x57> xXOR;
const xImpl_G1Logic<G1Type_AND,0x54> xAND;
const xImpl_G1Logic<G1Type_OR,0x56> xOR;
const xImpl_G1Logic<G1Type_XOR,0x57> xXOR;
const G1ArithmeticImpl_PlusSSE<G1Type_ADD,0x58> xADD;
const G1ArithmeticImpl_PlusSSE<G1Type_SUB,0x5c> xSUB;
const xImpl_G1Arith<G1Type_ADD,0x58> xADD;
const xImpl_G1Arith<G1Type_SUB,0x5c> xSUB;
const Group1ImplAll<G1Type_ADC> xADC;
const Group1ImplAll<G1Type_SBB> xSBB;
const G1CompareImpl_PlusSSE xCMP;
const xImpl_Group1<G1Type_ADC> xADC;
const xImpl_Group1<G1Type_SBB> xSBB;
const xImpl_G1Compare xCMP;
const Group2ImplAll<G2Type_ROL> xROL;
const Group2ImplAll<G2Type_ROR> xROR;
@ -276,8 +276,8 @@ const Group3ImplAll<G3Type_NOT> xNOT;
const Group3ImplAll<G3Type_NEG> xNEG;
const Group3ImplAll<G3Type_MUL> xUMUL;
const Group3ImplAll<G3Type_DIV> xUDIV;
const G3Impl_PlusSSE<G3Type_iDIV,0x5e> xDIV;
const iMul_PlusSSE xMUL;
const xImpl_Group3<G3Type_iDIV,0x5e> xDIV;
const xImpl_iMul xMUL;
const IncDecImplAll<false> xINC;
const IncDecImplAll<true> xDEC;
@ -670,21 +670,32 @@ const MovhlImplAll<0x12> xMOVL;
const MovhlImpl_RtoR<0x16> xMOVLH;
const MovhlImpl_RtoR<0x12> xMOVHL;
const PLogicImplAll<0xdb> xPAND;
const PLogicImplAll<0xdf> xPANDN;
const PLogicImplAll<0xeb> xPOR;
const PLogicImplAll<0xef> xPXOR;
const SimdImpl_PackedLogic<0xdb> xPAND;
const SimdImpl_PackedLogic<0xdf> xPANDN;
const SimdImpl_PackedLogic<0xeb> xPOR;
const SimdImpl_PackedLogic<0xef> xPXOR;
const SSEAndNotImpl<0x55> xANDN;
const SimdImpl_AndNot<0x55> xANDN;
const SSEImpl_SS_SD<0x66,0x2e> xUCOMI;
const SSE_rSqrtImpl<0x53> xRCP;
const SSE_rSqrtImpl<0x52> xRSQRT;
const SSE_SqrtImpl<0x51> xSQRT;
const SimdImpl_SS_SD<0x66,0x2e> xUCOMI;
const SimdImpl_rSqrt<0x53> xRCP;
const SimdImpl_rSqrt<0x52> xRSQRT;
const SimdImpl_Sqrt<0x51> xSQRT;
const SSEImpl_PSPD_SSSD<0x5f> xMAX;
const SSEImpl_PSPD_SSSD<0x5d> xMIN;
const SSEImpl_Shuffle<0xc6> xSHUF;
const SimdImpl_PSPD_SSSD<0x5f> xMAX;
const SimdImpl_PSPD_SSSD<0x5d> xMIN;
const SimdImpl_Shuffle<0xc6> xSHUF;
// ------------------------------------------------------------------------
const SimdImpl_Compare<SSE2_Equal> xCMPEQ;
const SimdImpl_Compare<SSE2_Less> xCMPLT;
const SimdImpl_Compare<SSE2_LessOrEqual> xCMPLE;
const SimdImpl_Compare<SSE2_Unordered> xCMPUNORD;
const SimdImpl_Compare<SSE2_NotEqual> xCMPNE;
const SimdImpl_Compare<SSE2_NotLess> xCMPNLT;
const SimdImpl_Compare<SSE2_NotLessOrEqual> xCMPNLE;
const SimdImpl_Compare<SSE2_Ordered> xCMPORD;
// ------------------------------------------------------------------------
// SSE Conversion Operations, as looney as they are.
@ -692,46 +703,43 @@ const SSEImpl_Shuffle<0xc6> xSHUF;
// These enforce pointer strictness for Indirect forms, due to the otherwise completely confusing
// nature of the functions. (so if a function expects an m32, you must use (u32*) or ptr32[]).
//
const SSEImpl_DestRegForm<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD;
const SSEImpl_DestRegForm<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS;
const SimdImpl_DestRegStrict<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD;
const SimdImpl_DestRegStrict<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS;
const SSEImpl_DestRegForm<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ;
const SSEImpl_DestRegForm<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI;
const SSEImpl_DestRegForm<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS;
const SimdImpl_DestRegStrict<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ;
const SimdImpl_DestRegStrict<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI;
const SimdImpl_DestRegStrict<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS;
const SSEImpl_DestRegForm<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD;
const SSEImpl_DestRegForm<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS;
const SimdImpl_DestRegStrict<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD;
const SimdImpl_DestRegStrict<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS;
const SSEImpl_DestRegForm<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ;
const SSEImpl_DestRegForm<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD;
const SSEImpl_DestRegForm<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI;
const SimdImpl_DestRegStrict<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ;
const SimdImpl_DestRegStrict<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD;
const SimdImpl_DestRegStrict<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI;
const SSEImpl_DestRegForm<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI;
const SSEImpl_DestRegForm<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS;
const SSEImpl_DestRegForm<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD;
const SSEImpl_DestRegForm<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS;
const SimdImpl_DestRegStrict<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI;
const SimdImpl_DestRegStrict<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS;
const SimdImpl_DestRegStrict<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD;
const SimdImpl_DestRegStrict<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS;
const SSEImpl_DestRegForm<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD;
const SSEImpl_DestRegForm<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI;
const SimdImpl_DestRegStrict<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD;
const SimdImpl_DestRegStrict<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI;
const SSEImpl_DestRegForm<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ;
const SSEImpl_DestRegForm<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI;
const SSEImpl_DestRegForm<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ;
const SSEImpl_DestRegForm<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI;
const SimdImpl_DestRegStrict<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ;
const SimdImpl_DestRegStrict<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI;
const SimdImpl_DestRegStrict<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ;
const SimdImpl_DestRegStrict<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI;
const SSEImpl_DestRegForm<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI;
const SSEImpl_DestRegForm<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI;
const SimdImpl_DestRegStrict<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI;
const SimdImpl_DestRegStrict<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI;
// ------------------------------------------------------------------------
const SSECompareImpl<SSE2_Equal> xCMPEQ;
const SSECompareImpl<SSE2_Less> xCMPLT;
const SSECompareImpl<SSE2_LessOrEqual> xCMPLE;
const SSECompareImpl<SSE2_Unordered> xCMPUNORD;
const SSECompareImpl<SSE2_NotEqual> xCMPNE;
const SSECompareImpl<SSE2_NotLess> xCMPNLT;
const SSECompareImpl<SSE2_NotLessOrEqual> xCMPNLE;
const SSECompareImpl<SSE2_Ordered> xCMPORD;
const SimdImpl_ShiftAll<0xd0, 0x70, 2> xPSRL;
const SimdImpl_ShiftAll<0xf0, 0x70, 6> xPSLL;
const SimdImpl_AddSub<0xfc, 0xec, 0xdc, 0xd4> xPADD;
const SimdImpl_AddSub<0xf8, 0xe8, 0xd8, 0xfb> xPSUB;
//////////////////////////////////////////////////////////////////////////////////////////

View File

@ -38,16 +38,16 @@ namespace x86Emitter
// ------------------------------------------------------------------------
// Group 1 Instruction Class
extern const Internal::G1LogicImpl_PlusSSE<Internal::G1Type_AND,0x54> xAND;
extern const Internal::G1LogicImpl_PlusSSE<Internal::G1Type_OR,0x56> xOR;
extern const Internal::G1LogicImpl_PlusSSE<Internal::G1Type_XOR,0x57> xXOR;
extern const Internal::xImpl_G1Logic<Internal::G1Type_AND,0x54> xAND;
extern const Internal::xImpl_G1Logic<Internal::G1Type_OR,0x56> xOR;
extern const Internal::xImpl_G1Logic<Internal::G1Type_XOR,0x57> xXOR;
extern const Internal::G1ArithmeticImpl_PlusSSE<Internal::G1Type_ADD,0x58> xADD;
extern const Internal::G1ArithmeticImpl_PlusSSE<Internal::G1Type_SUB,0x5c> xSUB;
extern const Internal::G1CompareImpl_PlusSSE xCMP;
extern const Internal::xImpl_G1Arith<Internal::G1Type_ADD,0x58> xADD;
extern const Internal::xImpl_G1Arith<Internal::G1Type_SUB,0x5c> xSUB;
extern const Internal::xImpl_G1Compare xCMP;
extern const Internal::Group1ImplAll<Internal::G1Type_ADC> xADC;
extern const Internal::Group1ImplAll<Internal::G1Type_SBB> xSBB;
extern const Internal::xImpl_Group1<Internal::G1Type_ADC> xADC;
extern const Internal::xImpl_Group1<Internal::G1Type_SBB> xSBB;
// ------------------------------------------------------------------------
// Group 2 Instruction Class
@ -74,8 +74,8 @@ namespace x86Emitter
extern const Internal::Group3ImplAll<Internal::G3Type_NEG> xNEG;
extern const Internal::Group3ImplAll<Internal::G3Type_MUL> xUMUL;
extern const Internal::Group3ImplAll<Internal::G3Type_DIV> xUDIV;
extern const Internal::G3Impl_PlusSSE<Internal::G3Type_iDIV,0x5e> xDIV;
extern const Internal::iMul_PlusSSE xMUL;
extern const Internal::xImpl_Group3<Internal::G3Type_iDIV,0x5e> xDIV;
extern const Internal::xImpl_iMul xMUL;
extern const Internal::IncDecImplAll<false> xINC;
extern const Internal::IncDecImplAll<true> xDEC;
@ -435,65 +435,73 @@ namespace x86Emitter
// ------------------------------------------------------------------------
extern const Internal::PLogicImplAll<0xdb> xPAND;
extern const Internal::PLogicImplAll<0xdf> xPANDN;
extern const Internal::PLogicImplAll<0xeb> xPOR;
extern const Internal::PLogicImplAll<0xef> xPXOR;
extern const Internal::SimdImpl_PackedLogic<0xdb> xPAND;
extern const Internal::SimdImpl_PackedLogic<0xdf> xPANDN;
extern const Internal::SimdImpl_PackedLogic<0xeb> xPOR;
extern const Internal::SimdImpl_PackedLogic<0xef> xPXOR;
extern const Internal::SSEAndNotImpl<0x55> xANDN;
extern const Internal::SimdImpl_AndNot<0x55> xANDN;
extern const Internal::SSEImpl_SS_SD<0x66,0x2e> xUCOMI;
extern const Internal::SSE_rSqrtImpl<0x53> xRCP;
extern const Internal::SSE_rSqrtImpl<0x52> xRSQRT;
extern const Internal::SSE_SqrtImpl<0x51> xSQRT;
extern const Internal::SimdImpl_SS_SD<0x66,0x2e> xUCOMI;
extern const Internal::SimdImpl_rSqrt<0x53> xRCP;
extern const Internal::SimdImpl_rSqrt<0x52> xRSQRT;
extern const Internal::SimdImpl_Sqrt<0x51> xSQRT;
extern const Internal::SSEImpl_PSPD_SSSD<0x5f> xMAX;
extern const Internal::SSEImpl_PSPD_SSSD<0x5d> xMIN;
extern const Internal::SSEImpl_Shuffle<0xc6> xSHUF;
extern const Internal::SimdImpl_PSPD_SSSD<0x5f> xMAX;
extern const Internal::SimdImpl_PSPD_SSSD<0x5d> xMIN;
extern const Internal::SimdImpl_Shuffle<0xc6> xSHUF;
// ------------------------------------------------------------------------
extern const Internal::SSECompareImpl<SSE2_Equal> xCMPEQ;
extern const Internal::SSECompareImpl<SSE2_Less> xCMPLT;
extern const Internal::SSECompareImpl<SSE2_LessOrEqual> xCMPLE;
extern const Internal::SSECompareImpl<SSE2_Unordered> xCMPUNORD;
extern const Internal::SSECompareImpl<SSE2_NotEqual> xCMPNE;
extern const Internal::SSECompareImpl<SSE2_NotLess> xCMPNLT;
extern const Internal::SSECompareImpl<SSE2_NotLessOrEqual> xCMPNLE;
extern const Internal::SSECompareImpl<SSE2_Ordered> xCMPORD;
extern const Internal::SimdImpl_Compare<SSE2_Equal> xCMPEQ;
extern const Internal::SimdImpl_Compare<SSE2_Less> xCMPLT;
extern const Internal::SimdImpl_Compare<SSE2_LessOrEqual> xCMPLE;
extern const Internal::SimdImpl_Compare<SSE2_Unordered> xCMPUNORD;
extern const Internal::SimdImpl_Compare<SSE2_NotEqual> xCMPNE;
extern const Internal::SimdImpl_Compare<SSE2_NotLess> xCMPNLT;
extern const Internal::SimdImpl_Compare<SSE2_NotLessOrEqual> xCMPNLE;
extern const Internal::SimdImpl_Compare<SSE2_Ordered> xCMPORD;
// ------------------------------------------------------------------------
// OMG Evil. I went cross-eyed an hour ago doing this.
//
extern const Internal::SSEImpl_DestRegForm<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD;
extern const Internal::SSEImpl_DestRegForm<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD;
extern const Internal::SimdImpl_DestRegStrict<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS;
extern const Internal::SSEImpl_DestRegForm<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ;
extern const Internal::SSEImpl_DestRegForm<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI;
extern const Internal::SSEImpl_DestRegForm<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS;
extern const Internal::SimdImpl_DestRegStrict<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ;
extern const Internal::SimdImpl_DestRegStrict<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI;
extern const Internal::SimdImpl_DestRegStrict<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS;
extern const Internal::SSEImpl_DestRegForm<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD;
extern const Internal::SSEImpl_DestRegForm<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS;
extern const Internal::SimdImpl_DestRegStrict<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD;
extern const Internal::SimdImpl_DestRegStrict<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS;
extern const Internal::SSEImpl_DestRegForm<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ;
extern const Internal::SSEImpl_DestRegForm<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD;
extern const Internal::SSEImpl_DestRegForm<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI;
extern const Internal::SimdImpl_DestRegStrict<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ;
extern const Internal::SimdImpl_DestRegStrict<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD;
extern const Internal::SimdImpl_DestRegStrict<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI;
extern const Internal::SSEImpl_DestRegForm<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI;
extern const Internal::SSEImpl_DestRegForm<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS;
extern const Internal::SSEImpl_DestRegForm<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD;
extern const Internal::SSEImpl_DestRegForm<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS;
extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI;
extern const Internal::SimdImpl_DestRegStrict<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS;
extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS;
extern const Internal::SSEImpl_DestRegForm<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD;
extern const Internal::SSEImpl_DestRegForm<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI;
extern const Internal::SSEImpl_DestRegForm<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ;
extern const Internal::SSEImpl_DestRegForm<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI;
extern const Internal::SSEImpl_DestRegForm<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ;
extern const Internal::SSEImpl_DestRegForm<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI;
extern const Internal::SimdImpl_DestRegStrict<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ;
extern const Internal::SimdImpl_DestRegStrict<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ;
extern const Internal::SimdImpl_DestRegStrict<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI;
extern const Internal::SSEImpl_DestRegForm<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI;
extern const Internal::SSEImpl_DestRegForm<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI;
extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI;
extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI;
// ------------------------------------------------------------------------
extern const Internal::SimdImpl_ShiftAll<0xd0, 0x70, 2> xPSRL;
extern const Internal::SimdImpl_ShiftAll<0xf0, 0x70, 6> xPSLL;
extern const Internal::SimdImpl_AddSub<0xfc, 0xec, 0xdc, 0xd4> xPADD;
extern const Internal::SimdImpl_AddSub<0xf8, 0xe8, 0xd8, 0xfb> xPSUB;
}

View File

@ -48,132 +48,51 @@ emitterT void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) { xPMOVMSKB
emitterT void SSE2_P##mod##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod( xRegisterSSE(to), xRegisterSSE(from) ); } \
emitterT void SSE2_P##mod##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod( xRegisterSSE(to), (void*)from ); }
#define DEFINE_LEGACY_ARITHMETIC( mod, sub ) \
emitterT void P##mod##sub##RtoR( x86MMXRegType to, x86MMXRegType from ) { xP##mod.sub( xRegisterMMX(to), xRegisterMMX(from) ); } \
emitterT void P##mod##sub##MtoR( x86MMXRegType to, uptr from ) { xP##mod.sub( xRegisterMMX(to), (void*)from ); } \
emitterT void SSE2_P##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod.sub( xRegisterSSE(to), xRegisterSSE(from) ); } \
emitterT void SSE2_P##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod.sub( xRegisterSSE(to), (void*)from ); }
#define DEFINE_LEGACY_SHIFT_STUFF( mod, sub ) \
emitterT void P##mod##sub##RtoR( x86MMXRegType to, x86MMXRegType from ) { xP##mod.sub( xRegisterMMX(to), xRegisterMMX(from) ); } \
emitterT void P##mod##sub##MtoR( x86MMXRegType to, uptr from ) { xP##mod.sub( xRegisterMMX(to), (void*)from ); } \
emitterT void P##mod##sub##ItoR( x86MMXRegType to, u8 imm ) { xP##mod.sub( xRegisterMMX(to), imm ); } \
emitterT void SSE2_P##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod.sub( xRegisterSSE(to), xRegisterSSE(from) ); } \
emitterT void SSE2_P##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod.sub( xRegisterSSE(to), (void*)from ); } \
emitterT void SSE2_P##mod##sub##_I8_to_XMM( x86SSERegType to, u8 imm ) { xP##mod.sub( xRegisterSSE(to), imm ); }
#define DEFINE_LEGACY_SHIFT_OPCODE( mod ) \
DEFINE_LEGACY_SHIFT_STUFF( mod, Q ) \
DEFINE_LEGACY_SHIFT_STUFF( mod, D ) \
DEFINE_LEGACY_SHIFT_STUFF( mod, W ) \
emitterT void SSE2_P##mod##DQ_I8_to_XMM( x86MMXRegType to, u8 imm ) { xP##mod.DQ( xRegisterSSE(to), imm ); }
DEFINE_LEGACY_LOGIC_OPCODE( AND )
DEFINE_LEGACY_LOGIC_OPCODE( ANDN )
DEFINE_LEGACY_LOGIC_OPCODE( OR )
DEFINE_LEGACY_LOGIC_OPCODE( XOR )
DEFINE_LEGACY_SHIFT_OPCODE( SLL )
DEFINE_LEGACY_SHIFT_OPCODE( SRL )
/* psllq r64 to r64 */
emitterT void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xF30F );
ModRM( 3, to, from );
}
DEFINE_LEGACY_ARITHMETIC( ADD, B )
DEFINE_LEGACY_ARITHMETIC( ADD, W )
DEFINE_LEGACY_ARITHMETIC( ADD, D )
DEFINE_LEGACY_ARITHMETIC( ADD, Q )
DEFINE_LEGACY_ARITHMETIC( ADD, SB )
DEFINE_LEGACY_ARITHMETIC( ADD, SW )
DEFINE_LEGACY_ARITHMETIC( ADD, USB )
DEFINE_LEGACY_ARITHMETIC( ADD, USW )
/* psllq m64 to r64 */
emitterT void PSLLQMtoR( x86MMXRegType to, uptr from )
{
write16( 0xF30F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* psllq imm8 to r64 */
emitterT void PSLLQItoR( x86MMXRegType to, u8 from )
{
write16( 0x730F );
ModRM( 3, 6, to);
write8( from );
}
/* psrlq r64 to r64 */
emitterT void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xD30F );
ModRM( 3, to, from );
}
/* psrlq m64 to r64 */
emitterT void PSRLQMtoR( x86MMXRegType to, uptr from )
{
write16( 0xD30F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* psrlq imm8 to r64 */
emitterT void PSRLQItoR( x86MMXRegType to, u8 from )
{
write16( 0x730F );
ModRM( 3, 2, to);
write8( from );
}
/* paddusb r64 to r64 */
emitterT void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xDC0F );
ModRM( 3, to, from );
}
/* paddusb m64 to r64 */
emitterT void PADDUSBMtoR( x86MMXRegType to, uptr from )
{
write16( 0xDC0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* paddusw r64 to r64 */
emitterT void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xDD0F );
ModRM( 3, to, from );
}
/* paddusw m64 to r64 */
emitterT void PADDUSWMtoR( x86MMXRegType to, uptr from )
{
write16( 0xDD0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* paddb r64 to r64 */
emitterT void PADDBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xFC0F );
ModRM( 3, to, from );
}
/* paddb m64 to r64 */
emitterT void PADDBMtoR( x86MMXRegType to, uptr from )
{
write16( 0xFC0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* paddw r64 to r64 */
emitterT void PADDWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xFD0F );
ModRM( 3, to, from );
}
/* paddw m64 to r64 */
emitterT void PADDWMtoR( x86MMXRegType to, uptr from )
{
write16( 0xFD0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
/* paddd r64 to r64 */
emitterT void PADDDRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xFE0F );
ModRM( 3, to, from );
}
/* paddd m64 to r64 */
emitterT void PADDDMtoR( x86MMXRegType to, uptr from )
{
write16( 0xFE0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
DEFINE_LEGACY_ARITHMETIC( SUB, B )
DEFINE_LEGACY_ARITHMETIC( SUB, W )
DEFINE_LEGACY_ARITHMETIC( SUB, D )
DEFINE_LEGACY_ARITHMETIC( SUB, Q )
DEFINE_LEGACY_ARITHMETIC( SUB, SB )
DEFINE_LEGACY_ARITHMETIC( SUB, SW )
DEFINE_LEGACY_ARITHMETIC( SUB, USB )
DEFINE_LEGACY_ARITHMETIC( SUB, USW )
/* emms */
emitterT void EMMS()
@ -181,98 +100,6 @@ emitterT void EMMS()
write16( 0x770F );
}
emitterT void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xEC0F );
ModRM( 3, to, from );
}
emitterT void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xED0F );
ModRM( 3, to, from );
}
// paddq m64 to r64 (sse2 only?)
emitterT void PADDQMtoR( x86MMXRegType to, uptr from )
{
write16( 0xD40F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
// paddq r64 to r64 (sse2 only?)
emitterT void PADDQRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xD40F );
ModRM( 3, to, from );
}
emitterT void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xE80F );
ModRM( 3, to, from );
}
emitterT void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xE90F );
ModRM( 3, to, from );
}
emitterT void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xF80F );
ModRM( 3, to, from );
}
emitterT void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xF90F );
ModRM( 3, to, from );
}
emitterT void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xFA0F );
ModRM( 3, to, from );
}
emitterT void PSUBDMtoR( x86MMXRegType to, uptr from )
{
write16( 0xFA0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
emitterT void PSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xD80F );
ModRM( 3, to, from );
}
emitterT void PSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xD90F );
ModRM( 3, to, from );
}
// psubq m64 to r64 (sse2 only?)
emitterT void PSUBQMtoR( x86MMXRegType to, uptr from )
{
write16( 0xFB0F );
ModRM( 0, to, DISP32 );
write32( MEMADDR(from, 4) );
}
// psubq r64 to r64 (sse2 only?)
emitterT void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xFB0F );
ModRM( 3, to, from );
}
// pmuludq m64 to r64 (sse2 only?)
emitterT void PMULUDQMtoR( x86MMXRegType to, uptr from )
{
@ -338,46 +165,6 @@ emitterT void PCMPGTDMtoR( x86MMXRegType to, uptr from )
write32( MEMADDR(from, 4) );
}
emitterT void PSRLWItoR( x86MMXRegType to, u8 from )
{
write16( 0x710F );
ModRM( 3, 2 , to );
write8( from );
}
emitterT void PSRLDItoR( x86MMXRegType to, u8 from )
{
write16( 0x720F );
ModRM( 3, 2 , to );
write8( from );
}
emitterT void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xD20F );
ModRM( 3, to, from );
}
emitterT void PSLLWItoR( x86MMXRegType to, u8 from )
{
write16( 0x710F );
ModRM( 3, 6 , to );
write8( from );
}
emitterT void PSLLDItoR( x86MMXRegType to, u8 from )
{
write16( 0x720F );
ModRM( 3, 6 , to );
write8( from );
}
emitterT void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from )
{
write16( 0xF20F );
ModRM( 3, to, from );
}
emitterT void PSRAWItoR( x86MMXRegType to, u8 from )
{
write16( 0x710F );

View File

@ -34,29 +34,6 @@ using namespace x86Emitter;
ModRM( 0, to, DISP32 ), \
write32( MEMADDR(from, 4 + overb) )
#define SSERtoM( code, overb ) \
assert( from < iREGCNT_XMM), \
RexR(0, from), \
write16( code ), \
ModRM( 0, from, DISP32 ), \
write32( MEMADDR(to, 4 + overb) )
#define SSE_SS_MtoR( code, overb ) \
assert( to < iREGCNT_XMM ), \
write8( 0xf3 ), \
RexR(0, to), \
write16( code ), \
ModRM( 0, to, DISP32 ), \
write32( MEMADDR(from, 4 + overb) )
#define SSE_SS_RtoM( code, overb ) \
assert( from < iREGCNT_XMM), \
write8( 0xf3 ), \
RexR(0, from), \
write16( code ), \
ModRM( 0, from, DISP32 ), \
write32( MEMADDR(to, 4 + overb) )
#define SSERtoR( code ) \
assert( to < iREGCNT_XMM && from < iREGCNT_XMM), \
RexRB(0, to, from), \
@ -95,14 +72,7 @@ using namespace x86Emitter;
RexR(0, to), \
write16( code ), \
ModRM( 0, to, DISP32 ), \
write32( MEMADDR(from, 4 + overb) ) \
#define SSE_SD_RtoR( code ) \
assert( to < iREGCNT_XMM && from < iREGCNT_XMM) , \
write8( 0xf2 ), \
RexRB(0, to, from), \
write16( code ), \
ModRM( 3, to, from )
write32( MEMADDR(from, 4 + overb) )
#define DEFINE_LEGACY_MOV_OPCODE( mod, sse ) \
emitterT void sse##_MOV##mod##_M128_to_XMM( x86SSERegType to, uptr from ) { xMOV##mod( xRegisterSSE(to), (void*)from ); } \
@ -220,21 +190,20 @@ emitterT void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) {
emitterT void SSE2_MOVSD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVSDZX( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); }
emitterT void SSE2_MOVSD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVSD( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); }
emitterT void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMASKMOV( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVL.PS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVL.PS( (void*)to, xRegisterSSE(from) ); }
emitterT void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVL.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); }
emitterT void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVL.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); }
emitterT void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVL.PS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVL.PS( (void*)to, xRegisterSSE(from) ); }
emitterT void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVL.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); }
emitterT void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVL.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); }
emitterT void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVH.PS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVH.PS( (void*)to, xRegisterSSE(from) ); }
emitterT void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVH.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); }
emitterT void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVH.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); }
emitterT void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVH.PS( xRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVH.PS( (void*)to, xRegisterSSE(from) ); }
emitterT void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVH.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); }
emitterT void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVH.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); }
emitterT void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVLH.PS( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVHL.PS( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMASKMOV( xRegisterSSE(to), xRegisterSSE(from) ); }
emitterT void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { xPMOVMSKB( xRegister32(to), xRegisterSSE(from) ); }
emitterT void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xSHUF.PS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); }
@ -277,47 +246,6 @@ emitterT void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from )
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//emitterT void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x2a0f, 0 ); }
// emitterT void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); }
//
// emitterT void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ) { SSEMtoR( 0x2d0f, 0 ); }
// emitterT void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); }
/*
emitterT void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { write8(0xf3); SSEMtoR(0x2c0f, 0); }
emitterT void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from)
{
write8(0xf3);
RexRB(0, to, from);
write16(0x2c0f);
ModRM(3, to, from);
}
*/
/*emitterT void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x2a0f, 0); }
emitterT void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from)
{
write8(0xf3);
RexRB(0, to, from);
write16(0x2a0f);
ModRM(3, to, from);
}
emitterT void SSE2_CVTSS2SD_M32_to_XMM( x86SSERegType to, uptr from) { SSE_SS_MtoR(0x5a0f, 0); }
emitterT void SSE2_CVTSS2SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x5a0f); }
*/
/*emitterT void SSE2_CVTSD2SS_M64_to_XMM( x86SSERegType to, uptr from) { SSE_SD_MtoR(0x5a0f, 0); }
emitterT void SSE2_CVTSD2SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SD_RtoR(0x5a0f); }
emitterT void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5b0f, 0 ); }
emitterT void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); }
emitterT void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x5b0f ); }
emitterT void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); }
emitterT void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ write8(0xf3); SSERtoR(0x5b0f); }*/
///////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
@ -389,19 +317,6 @@ emitterT void SSE_LDMXCSR( uptr from ) {
write32( MEMADDR(from, 4) );
}
/////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//PADDB,PADDW,PADDD : Add Packed Integers *
//**********************************************************************************
emitterT void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); }
emitterT void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFC0F ); }
emitterT void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); }
emitterT void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFD0F ); }
emitterT void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); }
emitterT void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFE0F ); }
emitterT void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); }
emitterT void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr from ) { SSEMtoR66( 0xD40F ); }
///////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//PCMPxx: Compare Packed Integers *
@ -426,65 +341,8 @@ emitterT void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66(
emitterT void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); }
emitterT void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); }
////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************/
//PSUBx: Subtract Packed Integers *
//**********************************************************************************
emitterT void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); }
emitterT void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF80F ); }
emitterT void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); }
emitterT void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF90F ); }
emitterT void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); }
emitterT void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFA0F ); }
emitterT void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); }
emitterT void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFB0F ); }
///////////////////////////////////////////////////////////////////////////////////////
// shift right logical
emitterT void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); }
emitterT void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD10F); }
emitterT void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x710F );
ModRM( 3, 2 , to );
write8( imm8 );
}
emitterT void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); }
emitterT void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD20F); }
emitterT void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x720F );
ModRM( 3, 2 , to );
write8( imm8 );
}
emitterT void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); }
emitterT void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD30F); }
emitterT void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x730F );
ModRM( 3, 2 , to );
write8( imm8 );
}
emitterT void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x730F );
ModRM( 3, 3 , to );
write8( imm8 );
}
// shift right arithmetic
emitterT void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); }
@ -509,50 +367,6 @@ emitterT void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8)
write8( imm8 );
}
// shift left logical
emitterT void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); }
emitterT void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF10F); }
emitterT void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x710F );
ModRM( 3, 6 , to );
write8( imm8 );
}
emitterT void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); }
emitterT void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF20F); }
emitterT void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x720F );
ModRM( 3, 6 , to );
write8( imm8 );
}
emitterT void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); }
emitterT void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF30F); }
emitterT void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x730F );
ModRM( 3, 6 , to );
write8( imm8 );
}
emitterT void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8)
{
write8( 0x66 );
RexB(0, to);
write16( 0x730F );
ModRM( 3, 7 , to );
write8( imm8 );
}
emitterT void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEE0F ); }
emitterT void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEE0F ); }
@ -565,28 +379,6 @@ emitterT void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR
emitterT void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDA0F ); }
emitterT void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDA0F ); }
emitterT void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEC0F ); }
emitterT void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEC0F ); }
emitterT void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xED0F ); }
emitterT void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xED0F ); }
emitterT void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xE80F ); }
emitterT void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xE80F ); }
emitterT void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xE90F ); }
emitterT void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xE90F ); }
emitterT void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); }
emitterT void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD80F ); }
emitterT void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); }
emitterT void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD90F ); }
emitterT void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); }
emitterT void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDC0F ); }
emitterT void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); }
emitterT void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDD0F ); }
//**********************************************************************************/
//PACKSSWB,PACKSSDW: Pack Saturate Signed Word
//**********************************************************************************

View File

@ -693,6 +693,10 @@ namespace x86Emitter
extern void EmitSibMagic( uint regfield, const ModSibBase& info );
// ------------------------------------------------------------------------
template< typename T > bool Is8BitOp() { return sizeof(T) == 1; }
template< typename T > void prefix16() { if( sizeof(T) == 2 ) xWrite<u8>( 0x66 ); }
#include "implement/xmm/movqss.h"
#include "implement/group1.h"
#include "implement/group2.h"