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)
using namespace x86Emitter;
x86IndexReg thisreg( x86reg );
iAddressReg thisreg( x86reg );
if ( _X ) iMOV(ptr32[thisreg+offset], 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)
x86IndexReg src( srcRm );
x86IndexReg dest( destRm );
iAddressReg src( srcRm );
iAddressReg dest( destRm );
iMOV( eax, ptr[src] );
iMOV( ptr[dest], eax );

View File

@ -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 )
// ------------------------------------------------------------------------
static __emitinline void Emit( u8 opcode, const iRegisterSIMD<OperandType>& to, const void* from )
{
preXMM<T>( 0x6e );
iWriteDisp( to.Id, src );
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
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 );
EmitSibMagic( to.Id, src );
writeXMMop<Prefix,OperandType>( opcode, to, from );
}
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.
static __emitinline void Emit( u8 opcode, const void* to, const iRegisterSIMD<OperandType>& from )
{
preXMM<T>( 0x7e );
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.
static __emitinline void Emit( u8 opcode, const ModSibBase& to, const iRegisterSIMD<OperandType>& from )
{
preXMM<T>( 0x7e );
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 );
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 ); }
};

View File

@ -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 );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
}

View File

@ -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++;

View File

@ -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 );
}

View File

@ -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 ); }

View File

@ -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 );
}

View File

@ -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 ); }

View File

@ -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"