Emitter: Implemented MOVAPS/MOVDQA, and renamed some vars/classes.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1015 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-19 05:24:20 +00:00
parent 5fb6505e9d
commit c19de231f6
10 changed files with 344 additions and 292 deletions

View File

@ -802,7 +802,7 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info)
// (this is one of my test cases for the new emitter --air) // (this is one of my test cases for the new emitter --air)
using namespace x86Emitter; using namespace x86Emitter;
x86IndexReg thisreg( x86reg ); iAddressReg thisreg( x86reg );
if ( _X ) iMOV(ptr32[thisreg+offset], 0x00000000); if ( _X ) iMOV(ptr32[thisreg+offset], 0x00000000);
if ( _Y ) iMOV(ptr32[thisreg+offset+4], 0x00000000); if ( _Y ) iMOV(ptr32[thisreg+offset+4], 0x00000000);

View File

@ -34,8 +34,8 @@ void MOV128_MtoM( x86IntRegType destRm, x86IntRegType srcRm )
{ {
// (this is one of my test cases for the new emitter --air) // (this is one of my test cases for the new emitter --air)
x86IndexReg src( srcRm ); iAddressReg src( srcRm );
x86IndexReg dest( destRm ); iAddressReg dest( destRm );
iMOV( eax, ptr[src] ); iMOV( eax, ptr[src] );
iMOV( ptr[dest], eax ); iMOV( ptr[dest], eax );

View File

@ -18,22 +18,13 @@
#pragma once #pragma once
// This helper function is used for instructions which enter XMM form when the 0x66 prefix //////////////////////////////////////////////////////////////////////////////////////////
// is specified (indicating alternate operand type selection). // MMX / SSE Helper Functions!
template< typename OperandType >
static __forceinline void preXMM( u8 opcode )
{
if( sizeof( OperandType ) == 16 )
iWrite<u16>( 0x0f66 );
else
iWrite<u8>( 0x0f );
iWrite<u8>( opcode );
}
// prefix - 0 indicates MMX, anything assumes XMM. template< typename T >
static __forceinline void SimdPrefix( u8 opcode, u8 prefix=0 ) __emitinline void SimdPrefix( u8 opcode, u8 prefix )
{ {
if( prefix != 0 ) if( sizeof( T ) == 16 && prefix != 0 )
{ {
iWrite<u16>( 0x0f00 | prefix ); iWrite<u16>( 0x0f00 | prefix );
iWrite<u8>( opcode ); iWrite<u8>( opcode );
@ -43,67 +34,81 @@ static __forceinline void SimdPrefix( u8 opcode, u8 prefix=0 )
} }
template< u8 prefix, typename T, typename T2 > template< u8 prefix, typename T, typename T2 >
static __forceinline void writeXMMop( const iRegister<T>& to, const iRegister<T2>& from, u8 opcode ) __emitinline void writeXMMop( u8 opcode, const iRegister<T>& to, const iRegister<T2>& from )
{ {
SimdPrefix( opcode, prefix ); SimdPrefix<T>( opcode, prefix );
ModRM_Direct( to.Id, from.Id ); ModRM_Direct( to.Id, from.Id );
} }
template< u8 prefix, typename T > template< u8 prefix, typename T >
static __noinline void writeXMMop( const iRegister<T>& reg, const ModSibBase& sib, u8 opcode ) void writeXMMop( u8 opcode, const iRegister<T>& reg, const ModSibBase& sib )
{ {
SimdPrefix( opcode, prefix ); SimdPrefix<T>( opcode, prefix );
EmitSibMagic( reg.Id, sib ); EmitSibMagic( reg.Id, sib );
} }
template< u8 prefix, typename T > template< u8 prefix, typename T >
static __forceinline void writeXMMop( const iRegister<T>& reg, const void* data, u8 opcode ) __emitinline void writeXMMop( u8 opcode, const iRegister<T>& reg, const void* data )
{ {
SimdPrefix( opcode, prefix ); SimdPrefix<T>( opcode, prefix );
iWriteDisp( reg.Id, data ); iWriteDisp( reg.Id, data );
} }
// ------------------------------------------------------------------------ //////////////////////////////////////////////////////////////////////////////////////////
// MOVD has valid forms for MMX and XMM registers.
// //
template< typename T > template< u8 Prefix, typename OperandType >
static __forceinline void iMOVDZX( const iRegisterSIMD<T>& to, const iRegister32& from ) class MovapsImpl
{ {
preXMM<T>( 0x6e ); public:
ModRM_Direct( to.Id, from.Id ); // ------------------------------------------------------------------------
} static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const iRegisterSIMD<OperandType> from )
{
if( to != from )
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
template< typename T> // ------------------------------------------------------------------------
static __forceinline void iMOVDZX( const iRegisterSIMD<T>& to, const void* src ) static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const void* from )
{ {
preXMM<T>( 0x6e ); writeXMMop<Prefix,OperandType>( opcode, to, from );
iWriteDisp( to.Id, src ); }
}
template< typename T> // ------------------------------------------------------------------------
static __forceinline void iMOVDZX( const iRegisterSIMD<T>& to, const ModSibBase& src ) static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const ModSibBase& from )
{ {
preXMM<T>( 0x6e ); writeXMMop<Prefix,OperandType>( opcode, to, from );
EmitSibMagic( to.Id, src ); }
}
template< typename T> // ------------------------------------------------------------------------
static __emitinline void iMOVD( const iRegister32& to, const iRegisterSIMD<T>& from ) // Generally a Movaps/dqa instruction form only.
{ // Most SSE/MMX instructions don't have this form.
preXMM<T>( 0x7e ); static __emitinline void Emit( u8 opcode, const void* to, const iRegisterSIMD<OperandType>& from )
ModRM_Direct( from.Id, to.Id ); {
} writeXMMop<Prefix,OperandType>( opcode, from, to );
}
template< typename T> // ------------------------------------------------------------------------
static __forceinline void iMOVD( void* dest, const iRegisterSIMD<T>& from ) // Generally a Movaps/dqa instruction form only.
{ // Most SSE/MMX instructions don't have this form.
preXMM<T>( 0x7e ); static __emitinline void Emit( u8 opcode, const ModSibBase& to, const iRegisterSIMD<OperandType>& from )
iWriteDisp( from.Id, dest ); {
} writeXMMop<Prefix,OperandType>( opcode, from, to );
}
template< typename T> };
static __noinline void iMOVD( const ModSibBase& dest, const iRegisterSIMD<T>& from )
// ------------------------------------------------------------------------
template< u8 Prefix, u8 Opcode, u8 OpcodeAlt >
class MovapsImplAll
{ {
preXMM<T>( 0x7e ); protected:
EmitSibMagic( from.Id, dest ); 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 ); }
};

View File

@ -67,6 +67,8 @@ __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM] = { XMMT_INT };
namespace x86Emitter { namespace x86Emitter {
const iAddressIndexerBase ptr; const iAddressIndexerBase ptr;
const iAddressIndexer<u128> ptr128;
const iAddressIndexer<u64> ptr64;
const iAddressIndexer<u32> ptr32; const iAddressIndexer<u32> ptr32;
const iAddressIndexer<u16> ptr16; const iAddressIndexer<u16> ptr16;
const iAddressIndexer<u8> ptr8; const iAddressIndexer<u8> ptr8;
@ -74,7 +76,19 @@ const iAddressIndexer<u8> ptr8;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
template< typename OperandType > const iRegister<OperandType> iRegister<OperandType>::Empty; template< typename OperandType > const iRegister<OperandType> iRegister<OperandType>::Empty;
const x86IndexReg x86IndexReg::Empty; const iAddressReg iAddressReg::Empty;
const iRegisterSSE
xmm0( 0 ), xmm1( 1 ),
xmm2( 2 ), xmm3( 3 ),
xmm4( 4 ), xmm5( 5 ),
xmm6( 6 ), xmm7( 7 );
const iRegisterMMX
mm0( 0 ), mm1( 1 ),
mm2( 2 ), mm3( 3 ),
mm4( 4 ), mm5( 5 ),
mm6( 6 ), mm7( 7 );
const iRegister32 const iRegister32
eax( 0 ), ebx( 3 ), eax( 0 ), ebx( 3 ),
@ -378,6 +392,86 @@ __emitinline void iAdvancePtr( uint bytes )
x86Ptr += bytes; x86Ptr += bytes;
} }
// ------------------------------------------------------------------------
// Generates a 'reduced' ModSib form, which has valid Base, Index, and Scale values.
// Necessary because by default ModSib compounds registers into Index when possible.
//
// If the ModSib is in illegal form ([Base + Index*5] for example) then an assertion
// followed by an InvalidParameter Exception will be tossed around in haphazard
// fashion.
//
// Optimization Note: Currently VC does a piss poor job of inlining this, even though
// constant propagation *should* resove it to little or no code (VC's constprop fails
// on C++ class initializers). There is a work around [using array initializers instead]
// but it's too much trouble for code that isn't performance critical anyway.
// And, with luck, maybe VC10 will optimize it better and make it a non-issue. :D
//
void ModSibBase::Reduce()
{
if( Index.IsStackPointer() )
{
// esp cannot be encoded as the index, so move it to the Base, if possible.
// note: intentionally leave index assigned to esp also (generates correct
// encoding later, since ESP cannot be encoded 'alone')
jASSUME( Scale == 0 ); // esp can't have an index modifier!
jASSUME( Base.IsEmpty() ); // base must be empty or else!
Base = Index;
return;
}
// If no index reg, then load the base register into the index slot.
if( Index.IsEmpty() )
{
Index = Base;
Scale = 0;
if( !Base.IsStackPointer() ) // prevent ESP from being encoded 'alone'
Base = iAddressReg::Empty;
return;
}
// The Scale has a series of valid forms, all shown here:
switch( Scale )
{
case 0: break;
case 1: Scale = 0; break;
case 2: Scale = 1; break;
case 3: // becomes [reg*2+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 1;
break;
case 4: Scale = 2; break;
case 5: // becomes [reg*4+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 2;
break;
case 6: // invalid!
assert( false );
break;
case 7: // so invalid!
assert( false );
break;
case 8: Scale = 3; break;
case 9: // becomes [reg*8+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 3;
break;
}
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Internal implementation of EmitSibMagic which has been custom tailored // Internal implementation of EmitSibMagic which has been custom tailored
// to optimize special forms of the Lea instructions accordingly, such // to optimize special forms of the Lea instructions accordingly, such
@ -641,99 +735,57 @@ __emitinline void iBSWAP( const iRegister32& to )
// MMX / XMM Instructions // MMX / XMM Instructions
// (these will get put in their own file later) // (these will get put in their own file later)
__emitinline void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from ) const MovapsImplAll< 0, 0x28, 0x29 > iMOVAPS;
{ const MovapsImplAll< 0, 0x10, 0x11 > iMOVUPS;
writeXMMop<0>( to, from, 0x6f ); const MovapsImplAll< 0x66, 0x28, 0x29 > iMOVAPD;
} const MovapsImplAll< 0x66, 0x10, 0x11 > iMOVUPD;
__noinline void iMOVQ( const iRegisterMMX& to, const ModSibBase& src ) const MovapsImplAll< 0x66, 0x6f, 0x7f > iMOVDQA;
{ const MovapsImplAll< 0xf3, 0x6f, 0x7f > iMOVDQU;
writeXMMop<0>( to, src, 0x6f );
}
__emitinline void iMOVQ( const iRegisterMMX& to, const void* src )
{
writeXMMop<0>( to, src, 0x6f );
}
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register // Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero. // being cleared to zero.
__emitinline void iMOVQZX( const iRegisterXMM& to, const iRegisterXMM& from ) __emitinline void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop<0xf3>( 0x7e, to, from ); }
{
writeXMMop<0xf3>( to, from, 0x7e );
}
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register // Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero. // being cleared to zero.
__noinline void iMOVQZX( const iRegisterXMM& to, const ModSibBase& src ) __noinline void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
{
writeXMMop<0xf3>( to, src, 0x7e );
}
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register // Moves from XMM to XMM, with the *upper 64 bits* of the destination register
// being cleared to zero. // being cleared to zero.
__emitinline void iMOVQZX( const iRegisterXMM& to, const void* src ) __emitinline void iMOVQZX( const iRegisterSSE& to, const void* src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
{
writeXMMop<0xf3>( to, src, 0x7e );
}
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterMMX& from ) __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 iRegisterSSE& from )
{ {
writeXMMop<0>( from, dest, 0x7f ); // Manual implementation of this form of MOVQ, since its parameters are unique in a way
} // that breaks the template inference of writeXMMop();
__forceinline void iMOVQ( void* dest, const iRegisterMMX& from ) SimdPrefix<u128>( 0xd6, 0xf2 );
{ ModRM_Direct( to.Id, from.Id );
writeXMMop<0>( from, dest, 0x7f );
}
__forceinline void iMOVQ( const ModSibBase& dest, const iRegisterXMM& from )
{
writeXMMop<0xf3>( from, dest, 0x7e );
}
__forceinline void iMOVQ( void* dest, const iRegisterXMM& from )
{
writeXMMop<0xf3>( from, dest, 0x7e );
}
__forceinline void iMOVQ( const iRegisterXMM& to, const iRegisterMMX& from )
{
writeXMMop<0xf3>( to, from, 0xd6 );
}
__forceinline void iMOVQ( const iRegisterMMX& to, const iRegisterXMM& from )
{
writeXMMop<0xf2>( to, from, 0xd6 );
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
__forceinline void iMOVSS( const iRegisterXMM& to, const iRegisterXMM& from ) #define IMPLEMENT_iMOVS( ssd, prefix ) \
{ __forceinline void iMOV##ssd( const iRegisterSSE& to, const iRegisterSSE& from ) { if( to != from ) writeXMMop<prefix>( 0x10, to, from ); } \
if( to != from ) __forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const void* from ) { writeXMMop<prefix>( 0x10, to, from ); } \
writeXMMop<0xf3>( to, from, 0x10 ); __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 iMOVSSZX( const iRegisterXMM& to, const void* from ) IMPLEMENT_iMOVS( SS, 0xf3 )
{ IMPLEMENT_iMOVS( SD, 0xf2 )
writeXMMop<0xf3>( to, from, 0x10 );
}
__forceinline void iMOVSSZX( const iRegisterXMM& to, const ModSibBase& from ) //////////////////////////////////////////////////////////////////////////////////////////
{ //
writeXMMop<0xf3>( to, from, 0x10 );
}
__forceinline void iMOVSS( const void* to, const iRegisterXMM& from )
{
writeXMMop<0xf3>( from, to, 0x11 );
}
__forceinline void iMOVSS( const ModSibBase& to, const iRegisterXMM& from )
{
writeXMMop<0xf3>( from, to, 0x11 );
}
} }

View File

@ -53,27 +53,27 @@ namespace x86Emitter
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// x86Register Method Implementations // x86Register Method Implementations
// //
__forceinline iAddressInfo x86IndexReg::operator+( const x86IndexReg& right ) const __forceinline iAddressInfo iAddressReg::operator+( const iAddressReg& right ) const
{ {
return iAddressInfo( *this, right ); return iAddressInfo( *this, right );
} }
__forceinline iAddressInfo x86IndexReg::operator+( const iAddressInfo& right ) const __forceinline iAddressInfo iAddressReg::operator+( const iAddressInfo& right ) const
{ {
return right + *this; return right + *this;
} }
__forceinline iAddressInfo x86IndexReg::operator+( s32 right ) const __forceinline iAddressInfo iAddressReg::operator+( s32 right ) const
{ {
return iAddressInfo( *this, right ); return iAddressInfo( *this, right );
} }
__forceinline iAddressInfo x86IndexReg::operator*( u32 right ) const __forceinline iAddressInfo iAddressReg::operator*( u32 right ) const
{ {
return iAddressInfo( Empty, *this, right ); return iAddressInfo( Empty, *this, right );
} }
__forceinline iAddressInfo x86IndexReg::operator<<( u32 shift ) const __forceinline iAddressInfo iAddressReg::operator<<( u32 shift ) const
{ {
return iAddressInfo( Empty, *this, 1<<shift ); return iAddressInfo( Empty, *this, 1<<shift );
} }
@ -93,7 +93,7 @@ namespace x86Emitter
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
__forceinline ModSibBase::ModSibBase( x86IndexReg base, x86IndexReg index, int scale, s32 displacement ) : __forceinline ModSibBase::ModSibBase( iAddressReg base, iAddressReg index, int scale, s32 displacement ) :
Base( base ), Base( base ),
Index( index ), Index( index ),
Scale( scale ), Scale( scale ),
@ -112,82 +112,10 @@ namespace x86Emitter
// no reduction necessary :D // no reduction necessary :D
} }
// ------------------------------------------------------------------------
// Generates a 'reduced' ModSib form, which has valid Base, Index, and Scale values.
// Necessary because by default ModSib compounds registers into Index when possible.
//
// If the ModSib is in illegal form ([Base + Index*5] for example) then an assertion
// followed by an InvalidParameter Exception will be tossed around in haphazard
// fashion.
__forceinline void ModSibBase::Reduce()
{
if( Index.IsStackPointer() )
{
// esp cannot be encoded as the index, so move it to the Base, if possible.
// note: intentionally leave index assigned to esp also (generates correct
// encoding later, since ESP cannot be encoded 'alone')
jASSUME( Scale == 0 ); // esp can't have an index modifier!
jASSUME( Base.IsEmpty() ); // base must be empty or else!
Base = Index;
return;
}
// If no index reg, then load the base register into the index slot.
if( Index.IsEmpty() )
{
Index = Base;
Scale = 0;
if( !Base.IsStackPointer() ) // prevent ESP from being encoded 'alone'
Base = x86IndexReg::Empty;
return;
}
// The Scale has a series of valid forms, all shown here:
switch( Scale )
{
case 0: break;
case 1: Scale = 0; break;
case 2: Scale = 1; break;
case 3: // becomes [reg*2+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 1;
break;
case 4: Scale = 2; break;
case 5: // becomes [reg*4+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 2;
break;
case 6: // invalid!
assert( false );
break;
case 7: // so invalid!
assert( false );
break;
case 8: Scale = 3; break;
case 9: // becomes [reg*8+reg]
jASSUME( Base.IsEmpty() );
Base = Index;
Scale = 3;
break;
}
}
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// iAddressInfo Method Implementations // iAddressInfo Method Implementations
// //
__forceinline iAddressInfo& iAddressInfo::Add( const x86IndexReg& src ) __forceinline iAddressInfo& iAddressInfo::Add( const iAddressReg& src )
{ {
if( src == Index ) if( src == Index )
{ {
@ -196,7 +124,7 @@ namespace x86Emitter
else if( src == Base ) else if( src == Base )
{ {
// Compound the existing register reference into the Index/Scale pair. // Compound the existing register reference into the Index/Scale pair.
Base = x86IndexReg::Empty; Base = iAddressReg::Empty;
if( src == Index ) if( src == Index )
Factor++; Factor++;

View File

@ -325,30 +325,77 @@ namespace x86Emitter
// since that's what they do (MOVD clears upper 32/96 bits, etc). // since that's what they do (MOVD clears upper 32/96 bits, etc).
// //
using Internal::iMOVD; // ------------------------------------------------------------------------
using Internal::iMOVDZX; // MOVD has valid forms for MMX and XMM registers.
//
template< typename T >
__emitinline void iMOVDZX( const iRegisterSIMD<T>& to, const iRegister32& 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 );
}
template< typename T >
void iMOVDZX( const iRegisterSIMD<T>& to, const ModSibBase& 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 );
}
template< typename T >
__emitinline void iMOVD( void* dest, const iRegisterSIMD<T>& from )
{
Internal::writeXMMop<0x66>( 0x7e, from, dest );
}
template< typename T >
void iMOVD( const ModSibBase& dest, const iRegisterSIMD<T>& from )
{
Internal::writeXMMop<0x66>( 0x7e, from, dest );
}
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
extern void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from ); extern void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from );
extern void iMOVQ( const iRegisterMMX& to, const iRegisterXMM& from ); extern void iMOVQ( const iRegisterMMX& to, const iRegisterSSE& from );
extern void iMOVQ( const iRegisterXMM& to, const iRegisterMMX& from ); extern void iMOVQ( const iRegisterSSE& to, const iRegisterMMX& from );
extern void iMOVQ( void* dest, const iRegisterXMM& from ); extern void iMOVQ( void* dest, const iRegisterSSE& from );
extern void iMOVQ( const ModSibBase& dest, const iRegisterXMM& from ); extern void iMOVQ( const ModSibBase& dest, const iRegisterSSE& from );
extern void iMOVQ( void* dest, const iRegisterMMX& from ); extern void iMOVQ( void* dest, const iRegisterMMX& from );
extern void iMOVQ( const ModSibBase& dest, const iRegisterMMX& from ); extern void iMOVQ( const ModSibBase& dest, const iRegisterMMX& from );
extern void iMOVQ( const iRegisterMMX& to, const void* src ); extern void iMOVQ( const iRegisterMMX& to, const void* src );
extern void iMOVQ( const iRegisterMMX& to, const ModSibBase& src ); extern void iMOVQ( const iRegisterMMX& to, const ModSibBase& src );
extern void iMOVQZX( const iRegisterXMM& to, const void* src ); extern void iMOVQZX( const iRegisterSSE& to, const void* src );
extern void iMOVQZX( const iRegisterXMM& to, const ModSibBase& src ); extern void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src );
extern void iMOVQZX( const iRegisterXMM& to, const iRegisterXMM& from ); extern void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVSS( const iRegisterXMM& to, const iRegisterXMM& from ); extern void iMOVSS( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVSS( const void* to, const iRegisterXMM& from ); extern void iMOVSS( const void* to, const iRegisterSSE& from );
extern void iMOVSS( const ModSibBase& to, const iRegisterXMM& from ); extern void iMOVSS( const ModSibBase& to, const iRegisterSSE& from );
extern void iMOVSD( const iRegisterSSE& to, const iRegisterSSE& from );
extern void iMOVSD( const void* to, const iRegisterSSE& from );
extern void iMOVSD( const ModSibBase& to, const iRegisterSSE& from );
extern void iMOVSSZX( const iRegisterXMM& to, const void* from ); extern void iMOVSSZX( const iRegisterSSE& to, const void* from );
extern void iMOVSSZX( const iRegisterXMM& to, const ModSibBase& from ); extern void iMOVSSZX( const iRegisterSSE& to, const ModSibBase& from );
extern void iMOVSDZX( const iRegisterSSE& to, const void* from );
extern void iMOVSDZX( const iRegisterSSE& to, const ModSibBase& from );
} }

View File

@ -48,13 +48,13 @@ static __forceinline ModSibBase _mrmhlp( x86IntRegType src )
template< typename ImmType > template< typename ImmType >
static __forceinline ModSibStrict<ImmType> _mhlp( x86IntRegType src ) static __forceinline ModSibStrict<ImmType> _mhlp( x86IntRegType src )
{ {
return ModSibStrict<ImmType>( x86IndexReg::Empty, x86IndexReg(src) ); return ModSibStrict<ImmType>( iAddressReg::Empty, iAddressReg(src) );
} }
template< typename ImmType > template< typename ImmType >
static __forceinline ModSibStrict<ImmType> _mhlp2( x86IntRegType src1, x86IntRegType src2 ) static __forceinline ModSibStrict<ImmType> _mhlp2( x86IntRegType src1, x86IntRegType src2 )
{ {
return ModSibStrict<ImmType>( x86IndexReg(src2), x86IndexReg(src1) ); return ModSibStrict<ImmType>( iAddressReg(src2), iAddressReg(src1) );
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -134,7 +134,7 @@ DEFINE_OPCODE_ONEREG_LEGACY( NEG )
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
#define DEFINE_LEGACY_MOVEXTEND( form, destbits, srcbits ) \ #define DEFINE_LEGACY_MOVEXTEND( form, destbits, srcbits ) \
emitterT void MOV##form##destbits##R##srcbits##toR( x86IntRegType to, x86IntRegType from ) { iMOV##form( iRegister##destbits( to ), iRegister##srcbits( from ) ); } \ emitterT void MOV##form##destbits##R##srcbits##toR( x86IntRegType to, x86IntRegType from ) { iMOV##form( iRegister##destbits( to ), iRegister##srcbits( from ) ); } \
emitterT void MOV##form##destbits##Rm##srcbits##toR( x86IntRegType to, x86IntRegType from, int offset ) { iMOV##form( iRegister##destbits( to ), ptr##srcbits[x86IndexReg( from ) + offset] ); } \ emitterT void MOV##form##destbits##Rm##srcbits##toR( x86IntRegType to, x86IntRegType from, int offset ) { iMOV##form( iRegister##destbits( to ), ptr##srcbits[iAddressReg( from ) + offset] ); } \
emitterT void MOV##form##destbits##M##srcbits##toR( x86IntRegType to, u32 from ) { iMOV##form( iRegister##destbits( to ), ptr##srcbits[from] ); } emitterT void MOV##form##destbits##M##srcbits##toR( x86IntRegType to, u32 from ) { iMOV##form( iRegister##destbits( to ), ptr##srcbits[from] ); }
DEFINE_LEGACY_MOVEXTEND( SX, 32, 16 ) DEFINE_LEGACY_MOVEXTEND( SX, 32, 16 )
@ -148,32 +148,32 @@ DEFINE_LEGACY_MOVEXTEND( ZX, 16, 8 )
emitterT void TEST32ItoR( x86IntRegType to, u32 from ) { iTEST( iRegister32(to), from ); } emitterT void TEST32ItoR( x86IntRegType to, u32 from ) { iTEST( iRegister32(to), from ); }
emitterT void TEST32ItoM( uptr to, u32 from ) { iTEST( ptr32[to], from ); } emitterT void TEST32ItoM( uptr to, u32 from ) { iTEST( ptr32[to], from ); }
emitterT void TEST32RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister32(to), iRegister32(from) ); } emitterT void TEST32RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister32(to), iRegister32(from) ); }
emitterT void TEST32ItoRm( x86IntRegType to, u32 from ) { iTEST( ptr32[x86IndexReg(to)], from ); } emitterT void TEST32ItoRm( x86IntRegType to, u32 from ) { iTEST( ptr32[iAddressReg(to)], from ); }
emitterT void TEST16ItoR( x86IntRegType to, u16 from ) { iTEST( iRegister16(to), from ); } emitterT void TEST16ItoR( x86IntRegType to, u16 from ) { iTEST( iRegister16(to), from ); }
emitterT void TEST16ItoM( uptr to, u16 from ) { iTEST( ptr16[to], from ); } emitterT void TEST16ItoM( uptr to, u16 from ) { iTEST( ptr16[to], from ); }
emitterT void TEST16RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister16(to), iRegister16(from) ); } emitterT void TEST16RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister16(to), iRegister16(from) ); }
emitterT void TEST16ItoRm( x86IntRegType to, u16 from ) { iTEST( ptr16[x86IndexReg(to)], from ); } emitterT void TEST16ItoRm( x86IntRegType to, u16 from ) { iTEST( ptr16[iAddressReg(to)], from ); }
emitterT void TEST8ItoR( x86IntRegType to, u8 from ) { iTEST( iRegister8(to), from ); } emitterT void TEST8ItoR( x86IntRegType to, u8 from ) { iTEST( iRegister8(to), from ); }
emitterT void TEST8ItoM( uptr to, u8 from ) { iTEST( ptr8[to], from ); } emitterT void TEST8ItoM( uptr to, u8 from ) { iTEST( ptr8[to], from ); }
emitterT void TEST8RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister8(to), iRegister8(from) ); } emitterT void TEST8RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister8(to), iRegister8(from) ); }
emitterT void TEST8ItoRm( x86IntRegType to, u8 from ) { iTEST( ptr8[x86IndexReg(to)], from ); } emitterT void TEST8ItoRm( x86IntRegType to, u8 from ) { iTEST( ptr8[iAddressReg(to)], from ); }
// mov r32 to [r32<<scale+from2] // mov r32 to [r32<<scale+from2]
emitterT void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale ) emitterT void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale )
{ {
iMOV( iRegister32(to), ptr[(x86IndexReg(from1)<<scale) + from2] ); iMOV( iRegister32(to), ptr[(iAddressReg(from1)<<scale) + from2] );
} }
emitterT void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale ) emitterT void MOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale )
{ {
iMOV( iRegister16(to), ptr[(x86IndexReg(from1)<<scale) + from2] ); iMOV( iRegister16(to), ptr[(iAddressReg(from1)<<scale) + from2] );
} }
emitterT void MOV8RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale ) emitterT void MOV8RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale )
{ {
iMOV( iRegister8(to), ptr[(x86IndexReg(from1)<<scale) + from2] ); iMOV( iRegister8(to), ptr[(iAddressReg(from1)<<scale) + from2] );
} }
emitterT void AND32I8toR( x86IntRegType to, s8 from ) emitterT void AND32I8toR( x86IntRegType to, s8 from )
@ -231,36 +231,36 @@ emitterT void IDIV32M( u32 from ) { iSDIV( ptr32[from] ); }
emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset) emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
{ {
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] ); iLEA( iRegister32( to ), ptr[iAddressReg(from)+offset] );
} }
emitterT void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) emitterT void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
{ {
iLEA( iRegister32( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] ); iLEA( iRegister32( to ), ptr[iAddressReg(from0)+iAddressReg(from1)] );
} }
// Don't inline recursive functions // Don't inline recursive functions
emitterT void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) emitterT void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
{ {
iLEA( iRegister32( to ), ptr[x86IndexReg(from)*(1<<scale)] ); iLEA( iRegister32( to ), ptr[iAddressReg(from)*(1<<scale)] );
} }
// to = from + offset // to = from + offset
emitterT void LEA16RtoR(x86IntRegType to, x86IntRegType from, s16 offset) emitterT void LEA16RtoR(x86IntRegType to, x86IntRegType from, s16 offset)
{ {
iLEA( iRegister16( to ), ptr[x86IndexReg(from)+offset] ); iLEA( iRegister16( to ), ptr[iAddressReg(from)+offset] );
} }
// to = from0 + from1 // to = from0 + from1
emitterT void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) emitterT void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
{ {
iLEA( iRegister16( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] ); iLEA( iRegister16( to ), ptr[iAddressReg(from0)+iAddressReg(from1)] );
} }
// to = from << scale (max is 3) // to = from << scale (max is 3)
emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
{ {
iLEA( iRegister16( to ), ptr[x86IndexReg(from)*(1<<scale)] ); iLEA( iRegister16( to ), ptr[iAddressReg(from)*(1<<scale)] );
} }
emitterT void BT32ItoR( x86IntRegType to, u8 from ) { iBT( iRegister32(to), from ); } emitterT void BT32ItoR( x86IntRegType to, u8 from ) { iBT( iRegister32(to), from ); }

View File

@ -483,14 +483,14 @@ emitterT void MOVQRtoR( x86MMXRegType to, x86MMXRegType from )
emitterT void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset ) emitterT void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset )
{ {
iMOVQ( iRegisterMMX(to), ptr[x86IndexReg(from)+offset] ); iMOVQ( iRegisterMMX(to), ptr[iAddressReg(from)+offset] );
//write16( 0x6F0F ); //write16( 0x6F0F );
//WriteRmOffsetFrom( to, from, offset ); //WriteRmOffsetFrom( to, from, offset );
} }
emitterT void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset ) emitterT void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset )
{ {
iMOVQ( ptr[x86IndexReg(to)+offset], iRegisterMMX(from) ); iMOVQ( ptr[iAddressReg(to)+offset], iRegisterMMX(from) );
//write16( 0x7F0F ); //write16( 0x7F0F );
//WriteRmOffsetFrom( from, to, offset ); //WriteRmOffsetFrom( from, to, offset );
} }
@ -522,7 +522,7 @@ emitterT void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from )
emitterT void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset ) emitterT void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset )
{ {
iMOVDZX( iRegisterMMX(to), ptr[x86IndexReg(from)+offset] ); iMOVDZX( iRegisterMMX(to), ptr[iAddressReg(from)+offset] );
//write16( 0x6E0F ); //write16( 0x6E0F );
//WriteRmOffsetFrom( to, from, offset ); //WriteRmOffsetFrom( to, from, offset );
} }
@ -536,7 +536,7 @@ emitterT void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from )
emitterT void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset ) emitterT void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset )
{ {
iMOVD( ptr[x86IndexReg(to)+offset], iRegisterMMX(from) ); iMOVD( ptr[iAddressReg(to)+offset], iRegisterMMX(from) );
//write16( 0x7E0F ); //write16( 0x7E0F );
//WriteRmOffsetFrom( from, to, offset ); //WriteRmOffsetFrom( from, to, offset );
} }

View File

@ -294,31 +294,39 @@ emitterT void SSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from, int offset
//**********************************************************************************/ //**********************************************************************************/
//MOVAPS: Move aligned Packed Single Precision FP values * //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_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_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_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_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); } emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { iMOVAPS( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } 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_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x100f); } emitterT void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVQZX( iRegisterSSE(to), (void*)from ); }
emitterT void SSE2_MOVSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x100f, 0); } emitterT void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVQZX( iRegisterSSE(to), iRegisterSSE(from) ); }
emitterT void SSE2_MOVSD_XMM_to_M64( uptr to, x86SSERegType from ) { SSE_SD_RtoM( 0x110f, 0); } emitterT void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) { iMOVQ( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) { iMOVQ( iRegisterMMX(to), iRegisterSSE(from) ); }
emitterT void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) { iMOVQ( iRegisterSSE(to), iRegisterMMX(from) ); }
emitterT void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVQZX( iRegisterXMM(to), (void*)from ); }
emitterT void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVQZX( iRegisterXMM(to), iRegisterXMM(from) ); }
emitterT void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) { iMOVQ( (void*)to, iRegisterXMM(from) ); }
emitterT void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) { iMOVQ( iRegisterMMX(to), iRegisterXMM(from) ); }
emitterT void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) { iMOVQ( iRegisterXMM(to), iRegisterMMX(from) ); }
//**********************************************************************************/ //**********************************************************************************/
//MOVSS: Move Scalar Single-Precision FP value * //MOVSS: Move Scalar Single-Precision FP value *
//********************************************************************************** //**********************************************************************************
emitterT void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { iMOVSSZX( iRegisterXMM(to), (void*)from ); } emitterT void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { iMOVSSZX( iRegisterSSE(to), (void*)from ); }
emitterT void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { iMOVSS( (void*)to, iRegisterXMM(from) ); } emitterT void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { iMOVSS( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVSS( iRegisterXMM(to), iRegisterXMM(from) ); } emitterT void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVSS( iRegisterSSE(to), iRegisterSSE(from) ); }
emitterT void SSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { iMOVSSZX( iRegisterXMM(to), ptr[x86IndexReg(from)+offset] ); } emitterT void SSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { iMOVSSZX( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); }
emitterT void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVSS( ptr[x86IndexReg(to)+offset], iRegisterXMM(from) ); } emitterT void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVSS( ptr[iAddressReg(to)+offset], iRegisterSSE(from) ); }
emitterT void SSE2_MOVSD_M32_to_XMM( x86SSERegType to, uptr from ) { iMOVSDZX( iRegisterSSE(to), (void*)from ); }
emitterT void SSE2_MOVSD_XMM_to_M32( u32 to, x86SSERegType from ) { iMOVSD( (void*)to, iRegisterSSE(from) ); }
emitterT void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVSD( iRegisterSSE(to), iRegisterSSE(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_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_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); }

View File

@ -266,7 +266,7 @@ namespace x86Emitter
// all about the the templated code in haphazard fashion. Yay.. >_< // all about the the templated code in haphazard fashion. Yay.. >_<
// //
typedef iRegisterSIMD<u128> iRegisterXMM; typedef iRegisterSIMD<u128> iRegisterSSE;
typedef iRegisterSIMD<u64> iRegisterMMX; typedef iRegisterSIMD<u64> iRegisterMMX;
typedef iRegister<u32> iRegister32; typedef iRegister<u32> iRegister32;
typedef iRegister<u16> iRegister16; typedef iRegister<u16> iRegister16;
@ -278,7 +278,7 @@ namespace x86Emitter
iRegisterCL(): iRegister8( 1 ) {} iRegisterCL(): iRegister8( 1 ) {}
}; };
extern const iRegisterXMM extern const iRegisterSSE
xmm0, xmm1, xmm2, xmm3, xmm0, xmm1, xmm2, xmm3,
xmm4, xmm5, xmm6, xmm7; xmm4, xmm5, xmm6, xmm7;
@ -302,30 +302,30 @@ namespace x86Emitter
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Use 32 bit registers as out index register (for ModSib memory address calculations) // Use 32 bit registers as out index register (for ModSib memory address calculations)
// Only x86IndexReg provides operators for constructing iAddressInfo types. // Only iAddressReg provides operators for constructing iAddressInfo types.
// //
class x86IndexReg : public iRegister32 class iAddressReg : public iRegister32
{ {
public: public:
static const x86IndexReg Empty; // defined as an empty/unused value (-1) static const iAddressReg Empty; // defined as an empty/unused value (-1)
public: public:
x86IndexReg(): iRegister32() {} iAddressReg(): iRegister32() {}
x86IndexReg( const x86IndexReg& src ) : iRegister32( src.Id ) {} iAddressReg( const iAddressReg& src ) : iRegister32( src.Id ) {}
x86IndexReg( const iRegister32& src ) : iRegister32( src ) {} iAddressReg( const iRegister32& src ) : iRegister32( src ) {}
explicit x86IndexReg( int regId ) : iRegister32( regId ) {} explicit iAddressReg( int regId ) : iRegister32( regId ) {}
// Returns true if the register is the stack pointer: ESP. // Returns true if the register is the stack pointer: ESP.
bool IsStackPointer() const { return Id == 4; } bool IsStackPointer() const { return Id == 4; }
iAddressInfo operator+( const x86IndexReg& right ) const; iAddressInfo operator+( const iAddressReg& right ) const;
iAddressInfo operator+( const iAddressInfo& right ) const; iAddressInfo operator+( const iAddressInfo& right ) const;
iAddressInfo operator+( s32 right ) const; iAddressInfo operator+( s32 right ) const;
iAddressInfo operator*( u32 factor ) const; iAddressInfo operator*( u32 factor ) const;
iAddressInfo operator<<( u32 shift ) const; iAddressInfo operator<<( u32 shift ) const;
x86IndexReg& operator=( const iRegister32& src ) iAddressReg& operator=( const iRegister32& src )
{ {
Id = src.Id; Id = src.Id;
return *this; return *this;
@ -337,13 +337,13 @@ namespace x86Emitter
class iAddressInfo class iAddressInfo
{ {
public: public:
x86IndexReg Base; // base register (no scale) iAddressReg Base; // base register (no scale)
x86IndexReg Index; // index reg gets multiplied by the scale iAddressReg Index; // index reg gets multiplied by the scale
int Factor; // scale applied to the index register, in factor form (not a shift!) int Factor; // scale applied to the index register, in factor form (not a shift!)
s32 Displacement; // address displacement s32 Displacement; // address displacement
public: public:
__forceinline iAddressInfo( const x86IndexReg& base, const x86IndexReg& index, int factor=1, s32 displacement=0 ) : __forceinline iAddressInfo( const iAddressReg& base, const iAddressReg& index, int factor=1, s32 displacement=0 ) :
Base( base ), Base( base ),
Index( index ), Index( index ),
Factor( factor ), Factor( factor ),
@ -351,7 +351,7 @@ namespace x86Emitter
{ {
} }
__forceinline explicit iAddressInfo( const x86IndexReg& index, int displacement=0 ) : __forceinline explicit iAddressInfo( const iAddressReg& index, int displacement=0 ) :
Base(), Base(),
Index( index ), Index( index ),
Factor(0), Factor(0),
@ -367,7 +367,7 @@ namespace x86Emitter
{ {
} }
static iAddressInfo FromIndexReg( const x86IndexReg& index, int scale=0, s32 displacement=0 ); static iAddressInfo FromIndexReg( const iAddressReg& index, int scale=0, s32 displacement=0 );
public: public:
bool IsByteSizeDisp() const { return is_s8( Displacement ); } bool IsByteSizeDisp() const { return is_s8( Displacement ); }
@ -378,10 +378,10 @@ namespace x86Emitter
return *this; return *this;
} }
__forceinline iAddressInfo& Add( const x86IndexReg& src ); __forceinline iAddressInfo& Add( const iAddressReg& src );
__forceinline iAddressInfo& Add( const iAddressInfo& src ); __forceinline iAddressInfo& Add( const iAddressInfo& src );
__forceinline iAddressInfo operator+( const x86IndexReg& right ) const { return iAddressInfo( *this ).Add( right ); } __forceinline iAddressInfo operator+( const iAddressReg& right ) const { return iAddressInfo( *this ).Add( right ); }
__forceinline iAddressInfo operator+( const iAddressInfo& right ) const { return iAddressInfo( *this ).Add( right ); } __forceinline iAddressInfo operator+( const iAddressInfo& right ) const { return iAddressInfo( *this ).Add( right ); }
__forceinline iAddressInfo operator+( s32 imm ) const { return iAddressInfo( *this ).Add( imm ); } __forceinline iAddressInfo operator+( s32 imm ) const { return iAddressInfo( *this ).Add( imm ); }
__forceinline iAddressInfo operator-( s32 imm ) const { return iAddressInfo( *this ).Add( -imm ); } __forceinline iAddressInfo operator-( s32 imm ) const { return iAddressInfo( *this ).Add( -imm ); }
@ -402,15 +402,15 @@ namespace x86Emitter
class ModSibBase class ModSibBase
{ {
public: public:
x86IndexReg Base; // base register (no scale) iAddressReg Base; // base register (no scale)
x86IndexReg Index; // index reg gets multiplied by the scale iAddressReg Index; // index reg gets multiplied by the scale
uint Scale; // scale applied to the index register, in scale/shift form uint Scale; // scale applied to the index register, in scale/shift form
s32 Displacement; // offset applied to the Base/Index registers. s32 Displacement; // offset applied to the Base/Index registers.
public: public:
explicit ModSibBase( const iAddressInfo& src ); explicit ModSibBase( const iAddressInfo& src );
explicit ModSibBase( s32 disp ); explicit ModSibBase( s32 disp );
ModSibBase( x86IndexReg base, x86IndexReg index, int scale=0, s32 displacement=0 ); ModSibBase( iAddressReg base, iAddressReg index, int scale=0, s32 displacement=0 );
bool IsByteSizeDisp() const { return is_s8( Displacement ); } bool IsByteSizeDisp() const { return is_s8( Displacement ); }
@ -424,7 +424,7 @@ namespace x86Emitter
__forceinline ModSibBase operator-( const s32 imm ) const { return ModSibBase( *this ).Add( -imm ); } __forceinline ModSibBase operator-( const s32 imm ) const { return ModSibBase( *this ).Add( -imm ); }
protected: protected:
__forceinline void Reduce(); void Reduce();
}; };
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -439,7 +439,7 @@ namespace x86Emitter
__forceinline explicit ModSibStrict( const iAddressInfo& src ) : ModSibBase( src ) {} __forceinline explicit ModSibStrict( const iAddressInfo& src ) : ModSibBase( src ) {}
__forceinline explicit ModSibStrict( s32 disp ) : ModSibBase( disp ) {} __forceinline explicit ModSibStrict( s32 disp ) : ModSibBase( disp ) {}
__forceinline ModSibStrict( x86IndexReg base, x86IndexReg index, int scale=0, s32 displacement=0 ) : __forceinline ModSibStrict( iAddressReg base, iAddressReg index, int scale=0, s32 displacement=0 ) :
ModSibBase( base, index, scale, displacement ) {} ModSibBase( base, index, scale, displacement ) {}
__forceinline ModSibStrict<OperandType>& Add( s32 imm ) __forceinline ModSibStrict<OperandType>& Add( s32 imm )
@ -461,9 +461,9 @@ namespace x86Emitter
// without doing anything and without compiler error. // without doing anything and without compiler error.
const ModSibBase& operator[]( const ModSibBase& src ) const { return src; } const ModSibBase& operator[]( const ModSibBase& src ) const { return src; }
__forceinline ModSibBase operator[]( x86IndexReg src ) const __forceinline ModSibBase operator[]( iAddressReg src ) const
{ {
return ModSibBase( src, x86IndexReg::Empty ); return ModSibBase( src, iAddressReg::Empty );
} }
__forceinline ModSibBase operator[]( const iAddressInfo& src ) const __forceinline ModSibBase operator[]( const iAddressInfo& src ) const
@ -497,9 +497,9 @@ namespace x86Emitter
// without doing anything and without compiler error. // without doing anything and without compiler error.
const ModSibStrict<OperandType>& operator[]( const ModSibStrict<OperandType>& src ) const { return src; } const ModSibStrict<OperandType>& operator[]( const ModSibStrict<OperandType>& src ) const { return src; }
__forceinline ModSibStrict<OperandType> operator[]( x86IndexReg src ) const __forceinline ModSibStrict<OperandType> operator[]( iAddressReg src ) const
{ {
return ModSibStrict<OperandType>( src, x86IndexReg::Empty ); return ModSibStrict<OperandType>( src, iAddressReg::Empty );
} }
__forceinline ModSibStrict<OperandType> operator[]( const iAddressInfo& src ) const __forceinline ModSibStrict<OperandType> operator[]( const iAddressInfo& src ) const
@ -523,6 +523,8 @@ namespace x86Emitter
// ptr[] - use this form for instructions which can resolve the address operand size from // ptr[] - use this form for instructions which can resolve the address operand size from
// the other register operand sizes. // the other register operand sizes.
extern const iAddressIndexerBase ptr; extern const iAddressIndexerBase ptr;
extern const iAddressIndexer<u128> ptr128;
extern const iAddressIndexer<u64> ptr64;
extern const iAddressIndexer<u32> ptr32; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms extern const iAddressIndexer<u32> ptr32; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms
extern const iAddressIndexer<u16> ptr16; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms extern const iAddressIndexer<u16> ptr16; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms
extern const iAddressIndexer<u8> ptr8; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms extern const iAddressIndexer<u8> ptr8; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms
@ -674,6 +676,16 @@ namespace x86Emitter
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
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;
extern const Internal::MovapsImplAll< 0x66, 0x6f, 0x7f > iMOVDQA;
extern const Internal::MovapsImplAll< 0xf3, 0x6f, 0x7f > iMOVDQU;
} }
#include "ix86_inlines.inl" #include "ix86_inlines.inl"