Merge pull request #1123 from PCSX2/emitter-Trex

Emitter trex
This commit is contained in:
Gregory Hainaut 2016-01-21 22:32:37 +01:00
commit 9e773ff980
5 changed files with 153 additions and 167 deletions

View File

@ -31,11 +31,12 @@ namespace x86Emitter {
extern void EmitSibMagic( const xRegisterBase& reg1, const void* src ); extern void EmitSibMagic( const xRegisterBase& reg1, const void* src );
extern void EmitSibMagic( const xRegisterBase& reg1, const xIndirectVoid& sib ); extern void EmitSibMagic( const xRegisterBase& reg1, const xIndirectVoid& sib );
void EmitRex( const xRegisterBase& reg1, const xRegisterBase& reg2 ); extern void EmitRex( uint regfield, const void* address );
void EmitRex( const xRegisterBase& reg1, const void* src ); extern void EmitRex( uint regfield, const xIndirectVoid& info );
void EmitRex( const xRegisterBase& reg1, const xIndirectVoid& sib ); extern void EmitRex( uint reg1, const xRegisterBase& reg2 );
void EmitRex( const xRegisterBase& reg1 ); extern void EmitRex( const xRegisterBase& reg1, const xRegisterBase& reg2 );
void EmitRex( const xIndirectVoid& sib ); extern void EmitRex( const xRegisterBase& reg1, const void* src );
extern void EmitRex( const xRegisterBase& reg1, const xIndirectVoid& sib );
extern void _xMovRtoR( const xRegisterInt& to, const xRegisterInt& from ); extern void _xMovRtoR( const xRegisterInt& to, const xRegisterInt& from );
@ -49,18 +50,42 @@ namespace x86Emitter {
template< typename T1, typename T2 > __emitinline template< typename T1, typename T2 > __emitinline
void xOpWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 ) void xOpWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 )
{ {
if( prefix != 0 ) if( prefix != 0 ) xWrite8( prefix );
xWrite16( (opcode<<8) | prefix ); EmitRex( param1, param2 );
else
xWrite8( opcode ); xWrite8( opcode );
EmitSibMagic( param1, param2 ); EmitSibMagic( param1, param2 );
} }
template< typename T1, typename T2 > __emitinline
void xOpAccWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 )
{
if( prefix != 0 ) xWrite8( prefix );
EmitRex( param1, param2 );
xWrite8( opcode );
}
//////////////////////////////////////////////////////////////////////////////////////////
// emitter helpers for xmm instruction with prefixes, most of which are using
// the basic opcode format (items inside braces denote optional or conditional
// emission):
//
// [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB]
//
// Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or
// 0x3a [and other value will result in assertion failue].
//
template< typename T1, typename T2 > __emitinline template< typename T1, typename T2 > __emitinline
void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2 ) void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2 )
{ {
SimdPrefix( prefix, opcode ); if( prefix != 0 ) xWrite8( prefix );
EmitRex( param1, param2 );
SimdPrefix( 0, opcode );
EmitSibMagic( param1, param2 ); EmitSibMagic( param1, param2 );
} }

View File

@ -45,15 +45,15 @@ static void _g1_IndirectImm( G1Type InstType, const xIndirect64orLess& sibdest,
{ {
if( sibdest.Is8BitOp() ) if( sibdest.Is8BitOp() )
{ {
xWrite8( 0x80 ); xOpWrite( sibdest.GetPrefix16(), 0x80, InstType, sibdest );
EmitSibMagic( InstType, sibdest );
xWrite<s8>( imm ); xWrite<s8>( imm );
} }
else else
{ {
sibdest.prefix16(); u8 opcode = is_s8( imm ) ? 0x83 : 0x81;
xWrite8( is_s8( imm ) ? 0x83 : 0x81 ); xOpWrite( sibdest.GetPrefix16(), opcode, InstType, sibdest );
EmitSibMagic( InstType, sibdest );
if( is_s8( imm ) ) if( is_s8( imm ) )
xWrite<s8>( imm ); xWrite<s8>( imm );
else else
@ -64,42 +64,40 @@ static void _g1_IndirectImm( G1Type InstType, const xIndirect64orLess& sibdest,
void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xRegisterInt& from ) void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xRegisterInt& from )
{ {
pxAssert( to.GetOperandSize() == from.GetOperandSize() ); pxAssert( to.GetOperandSize() == from.GetOperandSize() );
to.prefix16();
xWrite8( (to.Is8BitOp() ? 0 : 1) | (InstType<<3) ); u8 opcode = (to.Is8BitOp() ? 0 : 1) | (InstType<<3);
EmitSibMagic( from, to ); xOpWrite( to.GetPrefix16(), opcode, from, to );
} }
static void _g1_EmitOp( G1Type InstType, const xIndirectVoid& sibdest, const xRegisterInt& from ) static void _g1_EmitOp( G1Type InstType, const xIndirectVoid& sibdest, const xRegisterInt& from )
{ {
from.prefix16(); u8 opcode = (from.Is8BitOp() ? 0 : 1) | (InstType<<3);
xWrite8( (from.Is8BitOp() ? 0 : 1) | (InstType<<3) ); xOpWrite( from.GetPrefix16(), opcode, from, sibdest );
EmitSibMagic( from, sibdest );
} }
static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xIndirectVoid& sibsrc ) static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xIndirectVoid& sibsrc )
{ {
to.prefix16(); u8 opcode = (to.Is8BitOp() ? 2 : 3) | (InstType<<3);
xWrite8( (to.Is8BitOp() ? 2 : 3) | (InstType<<3) ); xOpWrite( to.GetPrefix16(), opcode, to, sibsrc );
EmitSibMagic( to, sibsrc );
} }
static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, int imm ) static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, int imm )
{ {
to.prefix16();
if( !to.Is8BitOp() && is_s8( imm ) ) if( !to.Is8BitOp() && is_s8( imm ) )
{ {
xWrite8( 0x83 ); xOpWrite( to.GetPrefix16(), 0x83, InstType, to );
EmitSibMagic( InstType, to );
xWrite<s8>( imm ); xWrite<s8>( imm );
} }
else else
{ {
if( to.IsAccumulator() ) if( to.IsAccumulator() ) {
xWrite8( (to.Is8BitOp() ? 4 : 5) | (InstType<<3) ); u8 opcode = (to.Is8BitOp() ? 4 : 5) | (InstType<<3);
xOpAccWrite( to.GetPrefix16(), opcode, InstType, to );
}
else else
{ {
xWrite8( to.Is8BitOp() ? 0x80 : 0x81 ); u8 opcode = to.Is8BitOp() ? 0x80 : 0x81;
EmitSibMagic( InstType, to ); xOpWrite( to.GetPrefix16(), opcode, InstType, to );
} }
to.xWriteImm( imm ); to.xWriteImm( imm );
} }
@ -134,52 +132,42 @@ const xImpl_Group1 xSBB = { G1Type_SBB };
void xImpl_Group2::operator()( const xRegisterInt& to, const xRegisterCL& /* from */ ) const void xImpl_Group2::operator()( const xRegisterInt& to, const xRegisterCL& /* from */ ) const
{ {
to.prefix16(); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xd2 : 0xd3, InstType, to );
xWrite8( to.Is8BitOp() ? 0xd2 : 0xd3 );
EmitSibMagic( InstType, to );
} }
void xImpl_Group2::operator()(const xRegisterInt& to, u8 imm ) const void xImpl_Group2::operator()(const xRegisterInt& to, u8 imm ) const
{ {
if( imm == 0 ) return; if( imm == 0 ) return;
to.prefix16();
if( imm == 1 ) if( imm == 1 )
{ {
// special encoding of 1's // special encoding of 1's
xWrite8( to.Is8BitOp() ? 0xd0 : 0xd1 ); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xd0 : 0xd1, InstType, to );
EmitSibMagic( InstType, to );
} }
else else
{ {
xWrite8( to.Is8BitOp() ? 0xc0 : 0xc1 ); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xc0 : 0xc1, InstType, to );
EmitSibMagic( InstType, to );
xWrite8( imm ); xWrite8( imm );
} }
} }
void xImpl_Group2::operator()( const xIndirect64orLess& sibdest, const xRegisterCL& /* from */ ) const void xImpl_Group2::operator()( const xIndirect64orLess& sibdest, const xRegisterCL& /* from */ ) const
{ {
sibdest.prefix16(); xOpWrite( sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xd2 : 0xd3, InstType, sibdest );
xWrite8( sibdest.Is8BitOp() ? 0xd2 : 0xd3 );
EmitSibMagic( InstType, sibdest );
} }
void xImpl_Group2::operator()( const xIndirect64orLess& sibdest, u8 imm ) const void xImpl_Group2::operator()( const xIndirect64orLess& sibdest, u8 imm ) const
{ {
if( imm == 0 ) return; if( imm == 0 ) return;
sibdest.prefix16();
if( imm == 1 ) if( imm == 1 )
{ {
// special encoding of 1's // special encoding of 1's
xWrite8( sibdest.Is8BitOp() ? 0xd0 : 0xd1 ); xOpWrite( sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xd0 : 0xd1, InstType, sibdest );
EmitSibMagic( InstType, sibdest );
} }
else else
{ {
xWrite8( sibdest.Is8BitOp() ? 0xc0 : 0xc1 ); xOpWrite( sibdest.GetPrefix16(), sibdest.Is8BitOp() ? 0xc0 : 0xc1, InstType, sibdest );
EmitSibMagic( InstType, sibdest );
xWrite8( imm ); xWrite8( imm );
} }
} }
@ -199,16 +187,12 @@ const xImpl_Group2 xSAR = { G2Type_SAR };
static void _g3_EmitOp( G3Type InstType, const xRegisterInt& from ) static void _g3_EmitOp( G3Type InstType, const xRegisterInt& from )
{ {
from.prefix16(); xOpWrite( from.GetPrefix16(), from.Is8BitOp() ? 0xf6 : 0xf7, InstType, from );
xWrite8(from.Is8BitOp() ? 0xf6 : 0xf7 );
EmitSibMagic( InstType, from );
} }
static void _g3_EmitOp( G3Type InstType, const xIndirect64orLess& from ) static void _g3_EmitOp( G3Type InstType, const xIndirect64orLess& from )
{ {
from.prefix16(); xOpWrite( from.GetPrefix16(), from.Is8BitOp() ? 0xf6 : 0xf7, InstType, from );
xWrite8( from.Is8BitOp() ? 0xf6 : 0xf7 );
EmitSibMagic( InstType, from );
} }
void xImpl_Group3::operator()( const xRegisterInt& from ) const { _g3_EmitOp( InstType, from ); } void xImpl_Group3::operator()( const xRegisterInt& from ) const { _g3_EmitOp( InstType, from ); }
@ -220,13 +204,9 @@ void xImpl_iDiv::operator()( const xIndirect64orLess& from ) const { _g3_EmitO
template< typename SrcType > template< typename SrcType >
static void _imul_ImmStyle( const xRegisterInt& param1, const SrcType& param2, int imm ) static void _imul_ImmStyle( const xRegisterInt& param1, const SrcType& param2, int imm )
{ {
// for iMul OpSize is allowed to be 16 or 32 bit only. pxAssert( param1.GetOperandSize() == param2.GetOperandSize() );
const uint OpSize = param1.GetOperandSize();
pxAssert( OpSize == param2.GetOperandSize() ); xOpWrite0F( param1.GetPrefix16(), is_s8( imm ) ? 0x6b : 0x69, param1, param2 );
pxAssert( OpSize > 1 );
xOpWrite0F( (OpSize == 2) ? 0x66 : 0, is_s8( imm ) ? 0x6b : 0x69, param1, param2 );
if( is_s8( imm ) ) if( is_s8( imm ) )
xWrite8( (u8)imm ); xWrite8( (u8)imm );

View File

@ -40,9 +40,7 @@ void _xMovRtoR( const xRegisterInt& to, const xRegisterInt& from )
if( to == from ) return; // ignore redundant MOVs. if( to == from ) return; // ignore redundant MOVs.
from.prefix16(); xOpWrite( from.GetPrefix16(), from.Is8BitOp() ? 0x88 : 0x89, from, to );
xWrite8( from.Is8BitOp() ? 0x88 : 0x89 );
EmitSibMagic( from, to );
} }
void xImpl_Mov::operator()( const xRegisterInt& to, const xRegisterInt& from ) const void xImpl_Mov::operator()( const xRegisterInt& to, const xRegisterInt& from ) const
@ -53,47 +51,47 @@ void xImpl_Mov::operator()( const xRegisterInt& to, const xRegisterInt& from ) c
void xImpl_Mov::operator()( const xIndirectVoid& dest, const xRegisterInt& from ) const void xImpl_Mov::operator()( const xIndirectVoid& dest, const xRegisterInt& from ) const
{ {
from.prefix16();
// mov eax has a special from when writing directly to a DISP32 address // mov eax has a special from when writing directly to a DISP32 address
// (sans any register index/base registers). // (sans any register index/base registers).
if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() ) if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() )
{ {
xWrite8( from.Is8BitOp() ? 0xa2 : 0xa3 ); // FIXME: in 64 bits, it could be 8B whereas Displacement is limited to 4B normally
#ifdef __x86_64__
pxAssert(0);
#endif
xOpAccWrite( from.GetPrefix16(), from.Is8BitOp() ? 0xa2 : 0xa3, from.Id, dest );
xWrite32( dest.Displacement ); xWrite32( dest.Displacement );
} }
else else
{ {
xWrite8( from.Is8BitOp() ? 0x88 : 0x89 ); xOpWrite( from.GetPrefix16(), from.Is8BitOp() ? 0x88 : 0x89, from.Id, dest );
EmitSibMagic( from.Id, dest );
} }
} }
void xImpl_Mov::operator()( const xRegisterInt& to, const xIndirectVoid& src ) const void xImpl_Mov::operator()( const xRegisterInt& to, const xIndirectVoid& src ) const
{ {
to.prefix16();
// mov eax has a special from when reading directly from a DISP32 address // mov eax has a special from when reading directly from a DISP32 address
// (sans any register index/base registers). // (sans any register index/base registers).
if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() ) if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() )
{ {
xWrite8( to.Is8BitOp() ? 0xa0 : 0xa1 ); // FIXME: in 64 bits, it could be 8B whereas Displacement is limited to 4B normally
#ifdef __x86_64__
pxAssert(0);
#endif
xOpAccWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xa0 : 0xa1, to, src );
xWrite32( src.Displacement ); xWrite32( src.Displacement );
} }
else else
{ {
xWrite8( to.Is8BitOp() ? 0x8a : 0x8b ); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0x8a : 0x8b, to, src );
EmitSibMagic( to, src );
} }
} }
void xImpl_Mov::operator()( const xIndirect64orLess& dest, int imm ) const void xImpl_Mov::operator()( const xIndirect64orLess& dest, int imm ) const
{ {
dest.prefix16(); xOpWrite( dest.GetPrefix16(), dest.Is8BitOp() ? 0xc6 : 0xc7, 0, dest );
xWrite8( dest.Is8BitOp() ? 0xc6 : 0xc7 );
EmitSibMagic( 0, dest );
dest.xWriteImm( imm ); dest.xWriteImm( imm );
} }
@ -106,9 +104,8 @@ void xImpl_Mov::operator()( const xRegisterInt& to, int imm, bool preserve_flags
else else
{ {
// Note: MOV does not have (reg16/32,imm8) forms. // Note: MOV does not have (reg16/32,imm8) forms.
u8 opcode = (to.Is8BitOp() ? 0xb0 : 0xb8) | to.Id;
to.prefix16(); xOpAccWrite( to.GetPrefix16(), opcode, 0, to);
xWrite8( (to.Is8BitOp() ? 0xb0 : 0xb8) | to.Id );
to.xWriteImm( imm ); to.xWriteImm( imm );
} }
} }

View File

@ -90,6 +90,9 @@ namespace x86Emitter {
// //
__emitinline void SimdPrefix( u8 prefix, u16 opcode ) __emitinline void SimdPrefix( u8 prefix, u16 opcode )
{ {
#ifdef __x86_64__
pxAssertMsg(prefix == 0, "REX prefix must be just before the opcode");
#endif
const bool is16BitOpcode = ((opcode & 0xff) == 0x38) || ((opcode & 0xff) == 0x3a); const bool is16BitOpcode = ((opcode & 0xff) == 0x38) || ((opcode & 0xff) == 0x3a);
// If the lower byte is not a valid prefix and the upper byte is non-zero it // If the lower byte is not a valid prefix and the upper byte is non-zero it
@ -220,15 +223,13 @@ void _SimdShiftHelper::operator()( const xRegisterMMX& to, const xIndirectVoid&
void _SimdShiftHelper::operator()( const xRegisterSSE& to, u8 imm8 ) const void _SimdShiftHelper::operator()( const xRegisterSSE& to, u8 imm8 ) const
{ {
SimdPrefix( 0x66, OpcodeImm ); xOpWrite0F( 0x66, OpcodeImm, (int)Modcode, to );
EmitSibMagic( (int)Modcode, to );
xWrite8( imm8 ); xWrite8( imm8 );
} }
void _SimdShiftHelper::operator()( const xRegisterMMX& to, u8 imm8 ) const void _SimdShiftHelper::operator()( const xRegisterMMX& to, u8 imm8 ) const
{ {
SimdPrefix( 0x00, OpcodeImm ); xOpWrite0F( 0x00, OpcodeImm, (int)Modcode, to );
EmitSibMagic( (int)Modcode, to );
xWrite8( imm8 ); xWrite8( imm8 );
} }
@ -747,8 +748,7 @@ IMPLEMENT_xMOVS( SD, 0xf2 )
__fi void xMOVNTDQA( const xRegisterSSE& to, const xIndirectVoid& from ) __fi void xMOVNTDQA( const xRegisterSSE& to, const xIndirectVoid& from )
{ {
xWrite32( 0x2A380f66 ); xOpWrite0F( 0x66, 0x2a38, to.Id, from);
EmitSibMagic( to.Id, from );
} }
__fi void xMOVNTDQA( const xIndirectVoid& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xe7, from, to ); } __fi void xMOVNTDQA( const xIndirectVoid& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xe7, from, to ); }
@ -833,31 +833,27 @@ __fi void xEMMS() { xWrite16( 0x770F ); }
// Store Streaming SIMD Extension Control/Status to Mem32. // Store Streaming SIMD Extension Control/Status to Mem32.
__emitinline void xSTMXCSR( const xIndirect32& dest ) __emitinline void xSTMXCSR( const xIndirect32& dest )
{ {
SimdPrefix( 0, 0xae ); xOpWrite0F( 0, 0xae, 3, dest );
EmitSibMagic( 3, dest );
} }
// Load Streaming SIMD Extension Control/Status from Mem32. // Load Streaming SIMD Extension Control/Status from Mem32.
__emitinline void xLDMXCSR( const xIndirect32& src ) __emitinline void xLDMXCSR( const xIndirect32& src )
{ {
SimdPrefix( 0, 0xae ); xOpWrite0F( 0, 0xae, 2, src );
EmitSibMagic( 2, src );
} }
// Save x87 FPU, MMX Technology, and SSE State to buffer // Save x87 FPU, MMX Technology, and SSE State to buffer
// Target buffer must be at least 512 bytes in length to hold the result. // Target buffer must be at least 512 bytes in length to hold the result.
__emitinline void xFXSAVE( const xIndirectVoid& dest ) __emitinline void xFXSAVE( const xIndirectVoid& dest )
{ {
SimdPrefix( 0, 0xae ); xOpWrite0F( 0, 0xae, 0, dest );
EmitSibMagic( 0, dest );
} }
// Restore x87 FPU, MMX , XMM, and MXCSR State. // Restore x87 FPU, MMX , XMM, and MXCSR State.
// Source buffer should be 512 bytes in length. // Source buffer should be 512 bytes in length.
__emitinline void xFXRSTOR( const xIndirectVoid& src ) __emitinline void xFXRSTOR( const xIndirectVoid& src )
{ {
SimdPrefix( 0, 0xae ); xOpWrite0F( 0, 0xae, 1, src );
EmitSibMagic( 1, src );
} }
} }

View File

@ -266,34 +266,6 @@ void EmitSibMagic( uint regfield, const void* address )
xWrite<s32>( (s32)displacement ); xWrite<s32>( (s32)displacement );
} }
//////////////////////////////////////////////////////////////////////////////////////////
// emitter helpers for xmm instruction with prefixes, most of which are using
// the basic opcode format (items inside braces denote optional or conditional
// emission):
//
// [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB]
//
// Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or
// 0x3a [and other value will result in assertion failue].
//
__emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const xIndirectVoid& sib )
{
SimdPrefix( prefix, opcode );
EmitSibMagic( instId, sib );
}
__emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data )
{
SimdPrefix( prefix, opcode );
EmitSibMagic( instId, data );
}
__emitinline void xOpWrite0F( u16 opcode, int instId, const xIndirectVoid& sib )
{
xOpWrite0F( 0, opcode, instId, sib );
}
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// returns TRUE if this instruction requires SIB to be encoded, or FALSE if the // returns TRUE if this instruction requires SIB to be encoded, or FALSE if the
// instruction ca be encoded as ModRm alone. // instruction ca be encoded as ModRm alone.
@ -406,51 +378,71 @@ void EmitSibMagic( const xRegisterBase& reg1, const xIndirectVoid& sib )
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
__emitinline static void EmitRex(bool w, bool r, bool x, bool b)
{
#ifdef __x86_64__
u8 rex = 0x40 | (w << 3) | (r << 2) | (x << 1) | b;
if (rex != 0x40)
xWrite8(rex);
#endif
}
void EmitRex( uint regfield, const void* address )
{
pxAssert(0);
bool w = false;
bool r = false;
bool x = false;
bool b = false;
EmitRex(w, r, x, b);
}
void EmitRex( uint regfield, const xIndirectVoid& info )
{
bool w = info.Base.IsWide();
bool r = false;
bool x = false;
bool b = info.IsExtended();
EmitRex(w, r, x, b);
}
void EmitRex( uint reg1, const xRegisterBase& reg2 )
{
bool w = reg2.IsWide();
bool r = false;
bool x = false;
bool b = reg2.IsExtended();
EmitRex(w, r, x, b);
}
void EmitRex( const xRegisterBase& reg1, const xRegisterBase& reg2 ) void EmitRex( const xRegisterBase& reg1, const xRegisterBase& reg2 )
{ {
u8 w = reg1.IsWide() << 3; bool w = reg1.IsWide();
u8 r = reg1.IsExtended() << 2; bool r = reg1.IsExtended();
u8 x = 0; bool x = false;
u8 b = reg2.IsExtended(); bool b = reg2.IsExtended();
xWrite8( 0x40 | w | r | x | b ); EmitRex(w, r, x, b);
} }
void EmitRex( const xRegisterBase& reg1, const void* src ) void EmitRex( const xRegisterBase& reg1, const void* src )
{ {
pxAssert(0); //see fixme pxAssert(0); //see fixme
u8 w = reg1.IsWide() << 3; bool w = reg1.IsWide();
u8 r = reg1.IsExtended() << 2; bool r = reg1.IsExtended();
u8 x = 0; bool x = false;
u8 b = 0; // FIXME src.IsExtended(); bool b = false; // FIXME src.IsExtended();
xWrite8( 0x40 | w | r | x | b ); EmitRex(w, r, x, b);
} }
void EmitRex( const xRegisterBase& reg1, const xIndirectVoid& sib ) void EmitRex( const xRegisterBase& reg1, const xIndirectVoid& sib )
{ {
u8 w = reg1.IsWide() << 3; u8 w = reg1.IsWide();
u8 r = reg1.IsExtended() << 2; u8 r = reg1.IsExtended();
u8 x = sib.Index.IsExtended() << 1; u8 x = sib.Index.IsExtended();
u8 b = sib.Base.IsExtended(); u8 b = sib.Base.IsExtended();
xWrite8( 0x40 | w | r | x | b ); EmitRex(w, r, x, b);
} }
void EmitRex( const xRegisterBase& reg1)
{
u8 w = reg1.IsWide() << 3;
u8 r = 0;
u8 x = 0;
u8 b = reg1.IsExtended();
xWrite8( 0x40 | w | r | x | b );
}
void EmitRex( const xIndirectVoid& sib)
{
u8 w = sib.Base.IsWide() << 3;
u8 r = 0;
u8 x = 0;
u8 b = sib.IsExtended();
xWrite8( 0x40 | w | r | x | b );
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// xSetPtr / xAlignPtr / xGetPtr / xAdvancePtr // xSetPtr / xAlignPtr / xGetPtr / xAdvancePtr
@ -929,29 +921,21 @@ __emitinline void xLEA( xRegister16 to, const xIndirectVoid& src, bool preserve_
void xImpl_Test::operator()( const xRegisterInt& to, const xRegisterInt& from ) const void xImpl_Test::operator()( const xRegisterInt& to, const xRegisterInt& from ) const
{ {
pxAssert( to.GetOperandSize() == from.GetOperandSize() ); pxAssert( to.GetOperandSize() == from.GetOperandSize() );
to.prefix16(); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0x84 : 0x85, from, to );
xWrite8( to.Is8BitOp() ? 0x84 : 0x85 );
EmitSibMagic( from, to );
} }
void xImpl_Test::operator()( const xIndirect64orLess& dest, int imm ) const void xImpl_Test::operator()( const xIndirect64orLess& dest, int imm ) const
{ {
dest.prefix16(); xOpWrite( dest.GetPrefix16(), dest.Is8BitOp() ? 0xf6 : 0xf7, 0, dest );
xWrite8( dest.Is8BitOp() ? 0xf6 : 0xf7 );
EmitSibMagic( 0, dest );
dest.xWriteImm( imm ); dest.xWriteImm( imm );
} }
void xImpl_Test::operator()( const xRegisterInt& to, int imm ) const void xImpl_Test::operator()( const xRegisterInt& to, int imm ) const
{ {
to.prefix16(); if( to.IsAccumulator() ) {
xOpAccWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xa8 : 0xa9, 0, to );
if( to.IsAccumulator() ) } else {
xWrite8( to.Is8BitOp() ? 0xa8 : 0xa9 ); xOpWrite( to.GetPrefix16(), to.Is8BitOp() ? 0xf6 : 0xf7, 0, to );
else
{
xWrite8( to.Is8BitOp() ? 0xf6 : 0xf7 );
EmitSibMagic( 0, to );
} }
to.xWriteImm( imm ); to.xWriteImm( imm );
} }
@ -969,11 +953,15 @@ void xImpl_IncDec::operator()( const xRegisterInt& to ) const
{ {
if( to.Is8BitOp() ) if( to.Is8BitOp() )
{ {
xWrite8( 0xfe ); u8 regfield = isDec ? 1 : 0;
EmitSibMagic( isDec ? 1 : 0, to ); xOpWrite( to.GetPrefix16(), 0xfe, regfield, to);
} }
else else
{ {
#ifdef __x86_64__
pxAssertMsg(0, "Single Byte INC/DEC aren't valid in 64 bits."
"You need to use the ModR/M form (FF/0 FF/1 opcodes)");
#endif
to.prefix16(); to.prefix16();
xWrite8( (isDec ? 0x48 : 0x40) | to.Id ); xWrite8( (isDec ? 0x48 : 0x40) | to.Id );
} }