mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
5fb6505e9d
commit
c19de231f6
|
@ -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)
|
||||
using namespace x86Emitter;
|
||||
x86IndexReg thisreg( x86reg );
|
||||
iAddressReg thisreg( x86reg );
|
||||
|
||||
if ( _X ) iMOV(ptr32[thisreg+offset], 0x00000000);
|
||||
if ( _Y ) iMOV(ptr32[thisreg+offset+4], 0x00000000);
|
||||
|
|
|
@ -34,8 +34,8 @@ void MOV128_MtoM( x86IntRegType destRm, x86IntRegType srcRm )
|
|||
{
|
||||
// (this is one of my test cases for the new emitter --air)
|
||||
|
||||
x86IndexReg src( srcRm );
|
||||
x86IndexReg dest( destRm );
|
||||
iAddressReg src( srcRm );
|
||||
iAddressReg dest( destRm );
|
||||
|
||||
iMOV( eax, ptr[src] );
|
||||
iMOV( ptr[dest], eax );
|
||||
|
|
|
@ -18,22 +18,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// This helper function is used for instructions which enter XMM form when the 0x66 prefix
|
||||
// is specified (indicating alternate operand type selection).
|
||||
template< typename OperandType >
|
||||
static __forceinline void preXMM( u8 opcode )
|
||||
{
|
||||
if( sizeof( OperandType ) == 16 )
|
||||
iWrite<u16>( 0x0f66 );
|
||||
else
|
||||
iWrite<u8>( 0x0f );
|
||||
iWrite<u8>( opcode );
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MMX / SSE Helper Functions!
|
||||
|
||||
// prefix - 0 indicates MMX, anything assumes XMM.
|
||||
static __forceinline void SimdPrefix( u8 opcode, u8 prefix=0 )
|
||||
template< typename T >
|
||||
__emitinline void SimdPrefix( u8 opcode, u8 prefix )
|
||||
{
|
||||
if( prefix != 0 )
|
||||
if( sizeof( T ) == 16 && prefix != 0 )
|
||||
{
|
||||
iWrite<u16>( 0x0f00 | prefix );
|
||||
iWrite<u8>( opcode );
|
||||
|
@ -43,67 +34,81 @@ static __forceinline void SimdPrefix( u8 opcode, u8 prefix=0 )
|
|||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// MOVD has valid forms for MMX and XMM registers.
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
template< typename T >
|
||||
static __forceinline void iMOVDZX( const iRegisterSIMD<T>& to, const iRegister32& from )
|
||||
template< u8 Prefix, typename OperandType >
|
||||
class MovapsImpl
|
||||
{
|
||||
preXMM<T>( 0x6e );
|
||||
ModRM_Direct( to.Id, from.Id );
|
||||
}
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
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 )
|
||||
{
|
||||
preXMM<T>( 0x6e );
|
||||
iWriteDisp( to.Id, src );
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const void* from )
|
||||
{
|
||||
writeXMMop<Prefix,OperandType>( opcode, to, from );
|
||||
}
|
||||
|
||||
template< typename T>
|
||||
static __forceinline void iMOVDZX( const iRegisterSIMD<T>& to, const ModSibBase& src )
|
||||
{
|
||||
preXMM<T>( 0x6e );
|
||||
EmitSibMagic( to.Id, src );
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const ModSibBase& from )
|
||||
{
|
||||
writeXMMop<Prefix,OperandType>( opcode, to, from );
|
||||
}
|
||||
|
||||
template< typename T>
|
||||
static __emitinline void iMOVD( const iRegister32& to, const iRegisterSIMD<T>& from )
|
||||
{
|
||||
preXMM<T>( 0x7e );
|
||||
ModRM_Direct( from.Id, to.Id );
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// Generally a Movaps/dqa instruction form only.
|
||||
// Most SSE/MMX instructions don't have this form.
|
||||
static __emitinline void Emit( u8 opcode, const void* to, const iRegisterSIMD<OperandType>& from )
|
||||
{
|
||||
writeXMMop<Prefix,OperandType>( opcode, from, to );
|
||||
}
|
||||
|
||||
template< typename T>
|
||||
static __forceinline void iMOVD( void* dest, const iRegisterSIMD<T>& from )
|
||||
{
|
||||
preXMM<T>( 0x7e );
|
||||
iWriteDisp( from.Id, dest );
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
// Generally a Movaps/dqa instruction form only.
|
||||
// Most SSE/MMX instructions don't have this form.
|
||||
static __emitinline void Emit( u8 opcode, const ModSibBase& to, const iRegisterSIMD<OperandType>& from )
|
||||
{
|
||||
writeXMMop<Prefix,OperandType>( opcode, from, to );
|
||||
}
|
||||
|
||||
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 );
|
||||
EmitSibMagic( from.Id, dest );
|
||||
}
|
||||
protected:
|
||||
typedef MovapsImpl<Prefix, u128> m_128;
|
||||
|
||||
public:
|
||||
__forceinline void operator()( const iRegisterSSE& to, const iRegisterSSE& from ) const { m_128::Emit( Opcode, to, from ); }
|
||||
__forceinline void operator()( const iRegisterSSE& to, const void* from ) const { m_128::Emit( Opcode, to, from ); }
|
||||
__forceinline void operator()( const void* to, const iRegisterSSE& from ) const { m_128::Emit( OpcodeAlt, to, from ); }
|
||||
__noinline void operator()( const iRegisterSSE& to, const ModSibBase& from ) const { m_128::Emit( Opcode, to, from ); }
|
||||
__noinline void operator()( const ModSibBase& to, const iRegisterSSE& from ) const { m_128::Emit( OpcodeAlt, to, from ); }
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM] = { XMMT_INT };
|
|||
namespace x86Emitter {
|
||||
|
||||
const iAddressIndexerBase ptr;
|
||||
const iAddressIndexer<u128> ptr128;
|
||||
const iAddressIndexer<u64> ptr64;
|
||||
const iAddressIndexer<u32> ptr32;
|
||||
const iAddressIndexer<u16> ptr16;
|
||||
const iAddressIndexer<u8> ptr8;
|
||||
|
@ -74,7 +76,19 @@ const iAddressIndexer<u8> ptr8;
|
|||
// ------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
eax( 0 ), ebx( 3 ),
|
||||
|
@ -378,6 +392,86 @@ __emitinline void iAdvancePtr( uint 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
|
||||
// to optimize special forms of the Lea instructions accordingly, such
|
||||
|
@ -641,99 +735,57 @@ __emitinline void iBSWAP( const iRegister32& to )
|
|||
// MMX / XMM Instructions
|
||||
// (these will get put in their own file later)
|
||||
|
||||
__emitinline void iMOVQ( const iRegisterMMX& to, const iRegisterMMX& from )
|
||||
{
|
||||
writeXMMop<0>( to, from, 0x6f );
|
||||
}
|
||||
const MovapsImplAll< 0, 0x28, 0x29 > iMOVAPS;
|
||||
const MovapsImplAll< 0, 0x10, 0x11 > iMOVUPS;
|
||||
const MovapsImplAll< 0x66, 0x28, 0x29 > iMOVAPD;
|
||||
const MovapsImplAll< 0x66, 0x10, 0x11 > iMOVUPD;
|
||||
|
||||
__noinline void iMOVQ( const iRegisterMMX& to, const ModSibBase& src )
|
||||
{
|
||||
writeXMMop<0>( to, src, 0x6f );
|
||||
}
|
||||
|
||||
__emitinline void iMOVQ( const iRegisterMMX& to, const void* src )
|
||||
{
|
||||
writeXMMop<0>( to, src, 0x6f );
|
||||
}
|
||||
const MovapsImplAll< 0x66, 0x6f, 0x7f > iMOVDQA;
|
||||
const MovapsImplAll< 0xf3, 0x6f, 0x7f > iMOVDQU;
|
||||
|
||||
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
|
||||
// being cleared to zero.
|
||||
__emitinline void iMOVQZX( const iRegisterXMM& to, const iRegisterXMM& from )
|
||||
{
|
||||
writeXMMop<0xf3>( to, from, 0x7e );
|
||||
}
|
||||
__emitinline void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from ) { writeXMMop<0xf3>( 0x7e, to, from ); }
|
||||
|
||||
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
|
||||
// being cleared to zero.
|
||||
__noinline void iMOVQZX( const iRegisterXMM& to, const ModSibBase& src )
|
||||
{
|
||||
writeXMMop<0xf3>( to, src, 0x7e );
|
||||
}
|
||||
__noinline void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
|
||||
|
||||
// Moves from XMM to XMM, with the *upper 64 bits* of the destination register
|
||||
// being cleared to zero.
|
||||
__emitinline void iMOVQZX( const iRegisterXMM& to, const void* src )
|
||||
{
|
||||
writeXMMop<0xf3>( to, src, 0x7e );
|
||||
}
|
||||
__emitinline void iMOVQZX( const iRegisterSSE& to, const void* src ) { writeXMMop<0xf3>( 0x7e, to, src ); }
|
||||
|
||||
__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 )
|
||||
{
|
||||
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 );
|
||||
SimdPrefix<u128>( 0xd6, 0xf2 );
|
||||
ModRM_Direct( to.Id, from.Id );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
__forceinline void iMOVSS( const iRegisterXMM& to, const iRegisterXMM& from )
|
||||
{
|
||||
if( to != from )
|
||||
writeXMMop<0xf3>( to, from, 0x10 );
|
||||
}
|
||||
#define IMPLEMENT_iMOVS( ssd, prefix ) \
|
||||
__forceinline void iMOV##ssd( const iRegisterSSE& to, const iRegisterSSE& from ) { if( to != from ) writeXMMop<prefix>( 0x10, to, from ); } \
|
||||
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const void* from ) { writeXMMop<prefix>( 0x10, to, from ); } \
|
||||
__forceinline void iMOV##ssd##ZX( const iRegisterSSE& to, const ModSibBase& from ) { writeXMMop<prefix>( 0x10, to, from ); } \
|
||||
__forceinline void iMOV##ssd( const void* to, const iRegisterSSE& from ) { writeXMMop<prefix>( 0x11, from, to ); } \
|
||||
__forceinline void iMOV##ssd( const ModSibBase& to, const iRegisterSSE& from ) { writeXMMop<prefix>( 0x11, from, to ); }
|
||||
|
||||
__forceinline void iMOVSSZX( const iRegisterXMM& to, const void* from )
|
||||
{
|
||||
writeXMMop<0xf3>( to, from, 0x10 );
|
||||
}
|
||||
IMPLEMENT_iMOVS( SS, 0xf3 )
|
||||
IMPLEMENT_iMOVS( SD, 0xf2 )
|
||||
|
||||
__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 );
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
}
|
||||
|
|
|
@ -53,27 +53,27 @@ namespace x86Emitter
|
|||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// x86Register Method Implementations
|
||||
//
|
||||
__forceinline iAddressInfo x86IndexReg::operator+( const x86IndexReg& right ) const
|
||||
__forceinline iAddressInfo iAddressReg::operator+( const iAddressReg& right ) const
|
||||
{
|
||||
return iAddressInfo( *this, right );
|
||||
}
|
||||
|
||||
__forceinline iAddressInfo x86IndexReg::operator+( const iAddressInfo& right ) const
|
||||
__forceinline iAddressInfo iAddressReg::operator+( const iAddressInfo& right ) const
|
||||
{
|
||||
return right + *this;
|
||||
}
|
||||
|
||||
__forceinline iAddressInfo x86IndexReg::operator+( s32 right ) const
|
||||
__forceinline iAddressInfo iAddressReg::operator+( s32 right ) const
|
||||
{
|
||||
return iAddressInfo( *this, right );
|
||||
}
|
||||
|
||||
__forceinline iAddressInfo x86IndexReg::operator*( u32 right ) const
|
||||
__forceinline iAddressInfo iAddressReg::operator*( u32 right ) const
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -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 ),
|
||||
Index( index ),
|
||||
Scale( scale ),
|
||||
|
@ -112,82 +112,10 @@ namespace x86Emitter
|
|||
// 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
|
||||
//
|
||||
__forceinline iAddressInfo& iAddressInfo::Add( const x86IndexReg& src )
|
||||
__forceinline iAddressInfo& iAddressInfo::Add( const iAddressReg& src )
|
||||
{
|
||||
if( src == Index )
|
||||
{
|
||||
|
@ -196,7 +124,7 @@ namespace x86Emitter
|
|||
else if( src == Base )
|
||||
{
|
||||
// Compound the existing register reference into the Index/Scale pair.
|
||||
Base = x86IndexReg::Empty;
|
||||
Base = iAddressReg::Empty;
|
||||
|
||||
if( src == Index )
|
||||
Factor++;
|
||||
|
|
|
@ -325,30 +325,77 @@ namespace x86Emitter
|
|||
// 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 iRegisterXMM& from );
|
||||
extern void iMOVQ( const iRegisterXMM& to, const iRegisterMMX& from );
|
||||
extern void iMOVQ( const iRegisterMMX& to, const iRegisterSSE& from );
|
||||
extern void iMOVQ( const iRegisterSSE& to, const iRegisterMMX& from );
|
||||
|
||||
extern void iMOVQ( void* dest, const iRegisterXMM& from );
|
||||
extern void iMOVQ( const ModSibBase& dest, const iRegisterXMM& from );
|
||||
extern void iMOVQ( void* dest, const iRegisterSSE& from );
|
||||
extern void iMOVQ( const ModSibBase& dest, const iRegisterSSE& from );
|
||||
extern void iMOVQ( void* 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 ModSibBase& src );
|
||||
|
||||
extern void iMOVQZX( const iRegisterXMM& to, const void* src );
|
||||
extern void iMOVQZX( const iRegisterXMM& to, const ModSibBase& src );
|
||||
extern void iMOVQZX( const iRegisterXMM& to, const iRegisterXMM& from );
|
||||
extern void iMOVQZX( const iRegisterSSE& to, const void* src );
|
||||
extern void iMOVQZX( const iRegisterSSE& to, const ModSibBase& src );
|
||||
extern void iMOVQZX( const iRegisterSSE& to, const iRegisterSSE& from );
|
||||
|
||||
extern void iMOVSS( const iRegisterXMM& to, const iRegisterXMM& from );
|
||||
extern void iMOVSS( const void* to, const iRegisterXMM& from );
|
||||
extern void iMOVSS( const ModSibBase& to, const iRegisterXMM& from );
|
||||
extern void iMOVSS( const iRegisterSSE& to, const iRegisterSSE& from );
|
||||
extern void iMOVSS( const void* to, const iRegisterSSE& 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 iRegisterXMM& to, const ModSibBase& from );
|
||||
extern void iMOVSSZX( const iRegisterSSE& to, const void* 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 );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -48,13 +48,13 @@ static __forceinline ModSibBase _mrmhlp( x86IntRegType src )
|
|||
template< typename ImmType >
|
||||
static __forceinline ModSibStrict<ImmType> _mhlp( x86IntRegType src )
|
||||
{
|
||||
return ModSibStrict<ImmType>( x86IndexReg::Empty, x86IndexReg(src) );
|
||||
return ModSibStrict<ImmType>( iAddressReg::Empty, iAddressReg(src) );
|
||||
}
|
||||
|
||||
template< typename ImmType >
|
||||
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 ) \
|
||||
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] ); }
|
||||
|
||||
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 TEST32ItoM( uptr to, u32 from ) { iTEST( ptr32[to], 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 TEST16ItoM( uptr to, u16 from ) { iTEST( ptr16[to], 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 TEST8ItoM( uptr to, u8 from ) { iTEST( ptr8[to], 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]
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
iMOV( iRegister8(to), ptr[(x86IndexReg(from1)<<scale) + from2] );
|
||||
iMOV( iRegister8(to), ptr[(iAddressReg(from1)<<scale) + from2] );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] );
|
||||
iLEA( iRegister32( to ), ptr[iAddressReg(from)+offset] );
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
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 ); }
|
||||
|
|
|
@ -483,14 +483,14 @@ emitterT void MOVQRtoR( x86MMXRegType to, x86MMXRegType from )
|
|||
|
||||
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 );
|
||||
//WriteRmOffsetFrom( to, from, 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 );
|
||||
//WriteRmOffsetFrom( from, to, offset );
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ emitterT void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from )
|
|||
|
||||
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 );
|
||||
//WriteRmOffsetFrom( to, from, offset );
|
||||
}
|
||||
|
@ -536,7 +536,7 @@ emitterT void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from )
|
|||
|
||||
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 );
|
||||
//WriteRmOffsetFrom( from, to, offset );
|
||||
}
|
||||
|
|
|
@ -294,31 +294,39 @@ emitterT void SSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from, int offset
|
|||
//**********************************************************************************/
|
||||
//MOVAPS: Move aligned Packed Single Precision FP values *
|
||||
//**********************************************************************************
|
||||
emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); }
|
||||
emitterT void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); }
|
||||
emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSERtoR( 0x280f ); } }
|
||||
//emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); }
|
||||
//emitterT void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); }
|
||||
//emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSERtoR( 0x280f ); } }
|
||||
//emitterT void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); }
|
||||
//emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); }
|
||||
|
||||
emitterT void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); }
|
||||
emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); }
|
||||
emitterT void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { iMOVAPS( iRegisterSSE(to), (void*)from ); }
|
||||
emitterT void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { iMOVAPS( (void*)to, iRegisterSSE(from) ); }
|
||||
emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVAPS( iRegisterSSE(to), iRegisterSSE(from) ); }
|
||||
emitterT void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { iMOVUPS( iRegisterSSE(to), (void*)from ); }
|
||||
emitterT void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { iMOVUPS( (void*)to, iRegisterSSE(from) ); }
|
||||
|
||||
emitterT void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x100f); }
|
||||
emitterT void SSE2_MOVSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x100f, 0); }
|
||||
emitterT void SSE2_MOVSD_XMM_to_M64( uptr to, x86SSERegType from ) { SSE_SD_RtoM( 0x110f, 0); }
|
||||
emitterT void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) { iMOVQZX( iRegisterSSE(to), (void*)from ); }
|
||||
emitterT void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { iMOVQZX( iRegisterSSE(to), iRegisterSSE(from) ); }
|
||||
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 *
|
||||
//**********************************************************************************
|
||||
emitterT void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { iMOVSSZX( iRegisterXMM(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_XMM( x86SSERegType to, x86SSERegType from ) { iMOVSS( iRegisterXMM(to), iRegisterXMM(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_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { iMOVSS( ptr[x86IndexReg(to)+offset], iRegisterXMM(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, iRegisterSSE(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( iRegisterSSE(to), ptr[iAddressReg(from)+offset] ); }
|
||||
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_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); }
|
||||
|
|
|
@ -266,7 +266,7 @@ namespace x86Emitter
|
|||
// all about the the templated code in haphazard fashion. Yay.. >_<
|
||||
//
|
||||
|
||||
typedef iRegisterSIMD<u128> iRegisterXMM;
|
||||
typedef iRegisterSIMD<u128> iRegisterSSE;
|
||||
typedef iRegisterSIMD<u64> iRegisterMMX;
|
||||
typedef iRegister<u32> iRegister32;
|
||||
typedef iRegister<u16> iRegister16;
|
||||
|
@ -278,7 +278,7 @@ namespace x86Emitter
|
|||
iRegisterCL(): iRegister8( 1 ) {}
|
||||
};
|
||||
|
||||
extern const iRegisterXMM
|
||||
extern const iRegisterSSE
|
||||
xmm0, xmm1, xmm2, xmm3,
|
||||
xmm4, xmm5, xmm6, xmm7;
|
||||
|
||||
|
@ -302,30 +302,30 @@ namespace x86Emitter
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 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:
|
||||
static const x86IndexReg Empty; // defined as an empty/unused value (-1)
|
||||
static const iAddressReg Empty; // defined as an empty/unused value (-1)
|
||||
|
||||
public:
|
||||
x86IndexReg(): iRegister32() {}
|
||||
x86IndexReg( const x86IndexReg& src ) : iRegister32( src.Id ) {}
|
||||
x86IndexReg( const iRegister32& src ) : iRegister32( src ) {}
|
||||
explicit x86IndexReg( int regId ) : iRegister32( regId ) {}
|
||||
iAddressReg(): iRegister32() {}
|
||||
iAddressReg( const iAddressReg& src ) : iRegister32( src.Id ) {}
|
||||
iAddressReg( const iRegister32& src ) : iRegister32( src ) {}
|
||||
explicit iAddressReg( int regId ) : iRegister32( regId ) {}
|
||||
|
||||
// Returns true if the register is the stack pointer: ESP.
|
||||
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+( s32 right ) const;
|
||||
|
||||
iAddressInfo operator*( u32 factor ) const;
|
||||
iAddressInfo operator<<( u32 shift ) const;
|
||||
|
||||
x86IndexReg& operator=( const iRegister32& src )
|
||||
iAddressReg& operator=( const iRegister32& src )
|
||||
{
|
||||
Id = src.Id;
|
||||
return *this;
|
||||
|
@ -337,13 +337,13 @@ namespace x86Emitter
|
|||
class iAddressInfo
|
||||
{
|
||||
public:
|
||||
x86IndexReg Base; // base register (no scale)
|
||||
x86IndexReg Index; // index reg gets multiplied by the scale
|
||||
iAddressReg Base; // base register (no scale)
|
||||
iAddressReg Index; // index reg gets multiplied by the scale
|
||||
int Factor; // scale applied to the index register, in factor form (not a shift!)
|
||||
s32 Displacement; // address displacement
|
||||
|
||||
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 ),
|
||||
Index( index ),
|
||||
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(),
|
||||
Index( index ),
|
||||
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:
|
||||
bool IsByteSizeDisp() const { return is_s8( Displacement ); }
|
||||
|
@ -378,10 +378,10 @@ namespace x86Emitter
|
|||
return *this;
|
||||
}
|
||||
|
||||
__forceinline iAddressInfo& Add( const x86IndexReg& src );
|
||||
__forceinline iAddressInfo& Add( const iAddressReg& 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+( 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
|
||||
{
|
||||
public:
|
||||
x86IndexReg Base; // base register (no scale)
|
||||
x86IndexReg Index; // index reg gets multiplied by the scale
|
||||
iAddressReg Base; // base register (no scale)
|
||||
iAddressReg Index; // index reg gets multiplied by the scale
|
||||
uint Scale; // scale applied to the index register, in scale/shift form
|
||||
s32 Displacement; // offset applied to the Base/Index registers.
|
||||
|
||||
public:
|
||||
explicit ModSibBase( const iAddressInfo& src );
|
||||
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 ); }
|
||||
|
||||
|
@ -424,7 +424,7 @@ namespace x86Emitter
|
|||
__forceinline ModSibBase operator-( const s32 imm ) const { return ModSibBase( *this ).Add( -imm ); }
|
||||
|
||||
protected:
|
||||
__forceinline void Reduce();
|
||||
void Reduce();
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -439,7 +439,7 @@ namespace x86Emitter
|
|||
|
||||
__forceinline explicit ModSibStrict( const iAddressInfo& src ) : ModSibBase( src ) {}
|
||||
__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 ) {}
|
||||
|
||||
__forceinline ModSibStrict<OperandType>& Add( s32 imm )
|
||||
|
@ -461,9 +461,9 @@ namespace x86Emitter
|
|||
// without doing anything and without compiler error.
|
||||
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
|
||||
|
@ -497,9 +497,9 @@ namespace x86Emitter
|
|||
// without doing anything and without compiler error.
|
||||
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
|
||||
|
@ -523,6 +523,8 @@ namespace x86Emitter
|
|||
// ptr[] - use this form for instructions which can resolve the address operand size from
|
||||
// the other register operand sizes.
|
||||
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<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
|
||||
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue