Emitter: Added BTS/SETcc/TEST instructions.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1001 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-04-17 18:47:04 +00:00
parent 62604d359a
commit 029a94ce3f
8 changed files with 411 additions and 203 deletions

View File

@ -2980,6 +2980,10 @@
<Filter
Name="Implement"
>
<File
RelativePath="..\..\x86\ix86\implement\bittest.h"
>
</File>
<File
RelativePath="..\..\x86\ix86\implement\dwshift.h"
>
@ -3004,6 +3008,10 @@
RelativePath="..\..\x86\ix86\implement\movs.h"
>
</File>
<File
RelativePath="..\..\x86\ix86\implement\test.h"
>
</File>
</Filter>
</Filter>
<File

View File

@ -0,0 +1,117 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
// Implementations found here: BTS/BT/BTC/BTR!
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
// These instructions are in the 'Group8' as per Intel's manual, but since they all have
// a unified purpose, I've named them for that instead.
enum G8Type
{
G8Type_BT = 4,
G8Type_BTS,
G8Type_BTR,
G8Type_BTC,
};
//////////////////////////////////////////////////////////////////////////////////////////
// Notes: Bit Test instructions are valid on 16/32 bit operands only.
//
template< G8Type InstType, typename ImmType >
class Group8Impl
{
protected:
static const uint OperandSize = sizeof(ImmType);
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
public:
Group8Impl() {} // For the love of GCC.
static __emitinline void Emit( const iRegister<ImmType>& bitbase, const iRegister<ImmType>& bitoffset )
{
prefix16();
iWrite<u8>( 0x0f );
iWrite<u8>( 0xa3 | (InstType << 2) );
ModRM_Direct( bitoffset.Id, bitbase.Id );
}
static __emitinline void Emit( void* bitbase, const iRegister<ImmType>& bitoffset )
{
prefix16();
iWrite<u8>( 0x0f );
iWrite<u8>( 0xa3 | (InstType << 2) );
iWriteDisp( bitoffset.Id, bitbase.Id );
}
static __emitinline void Emit( const ModSibBase& bitbase, const iRegister<ImmType>& bitoffset )
{
prefix16();
iWrite<u8>( 0x0f );
iWrite<u8>( 0xa3 | (InstType << 2) );
EmitSibMagic( bitoffset.Id, bitbase );
}
static __emitinline void Emit( const iRegister<ImmType>& bitbase, u8 immoffset )
{
prefix16();
iWrite<u16>( 0xba0f );
ModRM_Direct( InstType, bitbase.Id );
iWrite<u8>( immoffset );
}
static __emitinline void Emit( const ModSibStrict<ImmType>& bitbase, u8 immoffset )
{
prefix16();
iWrite<u16>( 0xba0f );
EmitSibMagic( InstType, bitbase );
iWrite<u8>( immoffset );
}
};
// -------------------------------------------------------------------
//
template< G8Type InstType >
class Group8ImplAll
{
protected:
typedef Group8Impl<InstType,u32> m_32;
typedef Group8Impl<InstType,u32> m_16;
public:
__forceinline void operator()( const iRegister32& bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); }
__forceinline void operator()( const iRegister16& bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); }
__forceinline void operator()( void* bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); }
__forceinline void operator()( void* bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); }
__noinline void operator()( const ModSibBase& bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); }
__noinline void operator()( const ModSibBase& bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); }
// Note on Imm forms : use int as the source operand since it's "reasonably inert" from a compiler
// perspective. (using uint tends to make the compiler try and fail to match signed immediates with
// one of the other overloads).
__noinline void operator()( const ModSibStrict<u32>& bitbase, u8 immoffset ) const { m_32::Emit( bitbase, immoffset ); }
__noinline void operator()( const ModSibStrict<u16>& bitbase, u8 immoffset ) const { m_16::Emit( bitbase, immoffset ); }
void operator()( const iRegister<u32>& bitbase, u8 immoffset ) const { m_32::Emit( bitbase, immoffset ); }
void operator()( const iRegister<u16>& bitbase, u8 immoffset ) const { m_16::Emit( bitbase, immoffset ); }
Group8ImplAll() {}
};

View File

@ -27,10 +27,8 @@
template< typename ImmType >
class MovImpl
{
public:
static const uint OperandSize = sizeof(ImmType);
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
@ -44,7 +42,7 @@ public:
prefix16();
iWrite<u8>( Is8BitOperand() ? 0x88 : 0x89 );
ModRM( 3, from.Id, to.Id );
ModRM_Direct( from.Id, to.Id );
}
// ------------------------------------------------------------------------
@ -187,14 +185,16 @@ public:
//////////////////////////////////////////////////////////////////////////////////////////
// CMOV !! [in all of it's disappointing lack-of glory]
// Caution! This instruction can look exciting and cool, until you realize that it cannot
// load immediate values into registers. -_-
//
template< typename ImmType >
class CMovImpl
template< typename ImmType, int InstBaseVal >
class CMovSetImpl
{
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() {return OperandSize == 1; }
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
static __forceinline void emit_base( JccComparisonType cc )
@ -202,11 +202,11 @@ protected:
jASSUME( cc >= 0 && cc <= 0x0f );
prefix16();
write8( 0x0f );
write8( 0x40 | cc );
write8( InstBaseVal | cc );
}
public:
CMovImpl() {}
CMovSetImpl() {}
static __emitinline void Emit( JccComparisonType cc, const iRegister<ImmType>& to, const iRegister<ImmType>& from )
{
@ -226,6 +226,27 @@ public:
emit_base( cc );
EmitSibMagic( to.Id, sibsrc );
}
// This form is provided for SETcc only (not available in CMOV)
static __emitinline void EmitSet( JccComparisonType cc, const iRegister<ImmType>& to )
{
emit_base( cc );
ModRM_Direct( 0, to.Id );
}
// This form is provided for SETcc only (not available in CMOV)
static __emitinline void EmitSet( JccComparisonType cc, const void* src )
{
emit_base( cc );
iWriteDisp( 0, src );
}
// This form is provided for SETcc only (not available in CMOV)
static __emitinline void EmitSet( JccComparisonType cc, const ModSibStrict<ImmType>& sibsrc )
{
emit_base( cc );
EmitSibMagic( 0, sibsrc );
}
};
// ------------------------------------------------------------------------
@ -235,8 +256,8 @@ public:
class CMovImplGeneric
{
protected:
typedef CMovImpl<u32> m_32;
typedef CMovImpl<u16> m_16;
typedef CMovSetImpl<u32, 0x40> m_32; // 0x40 is the cmov base instruction id
typedef CMovSetImpl<u16, 0x40> m_16; // 0x40 is the cmov base instruction id
public:
__forceinline void operator()( JccComparisonType ccType, const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); }
@ -255,8 +276,8 @@ template< JccComparisonType ccType >
class CMovImplAll
{
protected:
typedef CMovImpl<u32> m_32;
typedef CMovImpl<u16> m_16;
typedef CMovSetImpl<u32, 0x40> m_32;
typedef CMovSetImpl<u16, 0x40> m_16;
public:
__forceinline void operator()( const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); }
@ -270,6 +291,36 @@ public:
CMovImplAll() {} // don't ask.
};
// ------------------------------------------------------------------------
class SetImplGeneric
{
protected:
typedef CMovSetImpl<u8, 0x90> Impl; // 0x90 is the SETcc base instruction id
public:
__forceinline void operator()( JccComparisonType cc, const iRegister8& to ) const { Impl::EmitSet( cc, to ); }
__forceinline void operator()( JccComparisonType cc, void* dest ) const { Impl::EmitSet( cc, dest ); }
__noinline void operator()( JccComparisonType cc, const ModSibStrict<u8>& dest ) const { Impl::EmitSet( cc, dest ); }
SetImplGeneric() {} // if you do, ask GCC.
};
// ------------------------------------------------------------------------
template< JccComparisonType ccType >
class SetImplAll
{
protected:
typedef CMovSetImpl<u8, 0x90> Impl; // 0x90 is the SETcc base instruction id
public:
__forceinline void operator()( const iRegister8& to ) const { Impl::EmitSet( ccType, to ); }
__forceinline void operator()( void* dest ) const { Impl::EmitSet( ccType, dest ); }
__noinline void operator()( const ModSibStrict<u8>& dest ) const { Impl::EmitSet( ccType, dest ); }
SetImplAll() {} // if you do, ask GCC.
};
//////////////////////////////////////////////////////////////////////////////////////////
// Mov with sign/zero extension implementations (movsx / movzx)
//

View File

@ -0,0 +1,83 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
//////////////////////////////////////////////////////////////////////////////////////////
// MOV instruction Implementation
template< typename ImmType >
class TestImpl
{
protected:
static const uint OperandSize = sizeof(ImmType);
static bool Is8BitOperand() { return OperandSize == 1; }
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
public:
TestImpl() {}
// ------------------------------------------------------------------------
static __emitinline void Emit( const iRegister<ImmType>& to, const iRegister<ImmType>& from )
{
prefix16();
iWrite<u8>( Is8BitOperand() ? 0x84 : 0x85 );
ModRM_Direct( from.Id, to.Id );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( const iRegister<ImmType>& to, ImmType imm )
{
prefix16();
if( to.IsAccumulator() )
iWrite<u8>( Is8BitOperand() ? 0xa8 : 0xa9 );
else
{
iWrite<u8>( Is8BitOperand() ? 0xf6 : 0xf7 );
ModRM_Direct( 0, to.Id );
}
iWrite<ImmType>( imm );
}
// ------------------------------------------------------------------------
static __emitinline void Emit( ModSibStrict<ImmType> dest, ImmType imm )
{
prefix16();
iWrite<u8>( Is8BitOperand() ? 0xf6 : 0xf7 );
EmitSibMagic( 0, dest );
iWrite<ImmType>( imm );
}
};
// -------------------------------------------------------------------
//
class TestImplAll
{
public:
template< typename T >
__forceinline void operator()( const iRegister<T>& to, const iRegister<T>& from ) const { TestImpl<T>::Emit( to, from ); }
template< typename T >
__noinline void operator()( const ModSibStrict<T>& sibdest, T imm ) const { TestImpl<T>::Emit( sibdest, imm ); }
template< typename T >
void operator()( const iRegister<T>& to, T imm ) const { TestImpl<T>::Emit( to, imm ); }
TestImplAll() {} // Why does GCC need these?
};

View File

@ -241,6 +241,7 @@ namespace Internal
using namespace Internal;
const MovImplAll iMOV;
const TestImplAll iTEST;
const Group1ImplAll<G1Type_ADD> iADD;
const Group1ImplAll<G1Type_OR> iOR;
@ -271,9 +272,15 @@ const IncDecImplAll<true> iDEC;
const MovExtendImplAll<false> iMOVZX;
const MovExtendImplAll<true> iMOVSX;
const Internal::DwordShiftImplAll<false> iSHLD;
const Internal::DwordShiftImplAll<true> iSHRD;
const DwordShiftImplAll<false> iSHLD;
const DwordShiftImplAll<true> iSHRD;
const Group8ImplAll<G8Type_BT> iBT;
const Group8ImplAll<G8Type_BTR> iBTR;
const Group8ImplAll<G8Type_BTS> iBTS;
const Group8ImplAll<G8Type_BTC> iBTC;
// ------------------------------------------------------------------------
const CMovImplGeneric iCMOV;
const CMovImplAll<Jcc_Above> iCMOVA;
@ -301,6 +308,35 @@ const CMovImplAll<Jcc_Unsigned> iCMOVNS;
const CMovImplAll<Jcc_ParityEven> iCMOVPE;
const CMovImplAll<Jcc_ParityOdd> iCMOVPO;
// ------------------------------------------------------------------------
const SetImplGeneric iSET;
const SetImplAll<Jcc_Above> iSETA;
const SetImplAll<Jcc_AboveOrEqual> iSETAE;
const SetImplAll<Jcc_Below> iSETB;
const SetImplAll<Jcc_BelowOrEqual> iSETBE;
const SetImplAll<Jcc_Greater> iSETG;
const SetImplAll<Jcc_GreaterOrEqual> iSETGE;
const SetImplAll<Jcc_Less> iSETL;
const SetImplAll<Jcc_LessOrEqual> iSETLE;
const SetImplAll<Jcc_Zero> iSETZ;
const SetImplAll<Jcc_Equal> iSETE;
const SetImplAll<Jcc_NotZero> iSETNZ;
const SetImplAll<Jcc_NotEqual> iSETNE;
const SetImplAll<Jcc_Overflow> iSETO;
const SetImplAll<Jcc_NotOverflow> iSETNO;
const SetImplAll<Jcc_Carry> iSETC;
const SetImplAll<Jcc_NotCarry> iSETNC;
const SetImplAll<Jcc_Signed> iSETS;
const SetImplAll<Jcc_Unsigned> iSETNS;
const SetImplAll<Jcc_ParityEven> iSETPE;
const SetImplAll<Jcc_ParityOdd> iSETPO;
// ------------------------------------------------------------------------
// Assigns the current emitter buffer target address.
// This is provided instead of using x86Ptr directly, since we may in the future find
@ -582,13 +618,13 @@ __noinline void iSMUL( const iRegister16& to, const ModSibBase& from, s16 imm )
__emitinline void iPOP( const ModSibBase& from )
{
iWrite<u8>( 0x8f );
Internal::EmitSibMagic( 0, from );
EmitSibMagic( 0, from );
}
__emitinline void iPUSH( const ModSibBase& from )
{
iWrite<u8>( 0xff );
Internal::EmitSibMagic( 6, from );
EmitSibMagic( 6, from );
}

View File

@ -119,7 +119,6 @@ namespace x86Emitter
typedef iForwardJump<s8> iForwardJump8;
typedef iForwardJump<s32> iForwardJump32;
DEFINE_FORWARD_JUMP( JA, Jcc_Above );
DEFINE_FORWARD_JUMP( JB, Jcc_Below );

View File

@ -145,6 +145,20 @@ DEFINE_LEGACY_MOVEXTEND( ZX, 32, 8 )
DEFINE_LEGACY_MOVEXTEND( SX, 16, 8 )
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 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 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 ); }
// mov r32 to [r32<<scale+from2]
emitterT void MOV32RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2, int scale )
@ -162,8 +176,6 @@ emitterT void MOV8RmSOffsettoR( x86IntRegType to, x86IntRegType from1, s32 from2
iMOV( iRegister8(to), ptr[(x86IndexReg(from1)<<scale) + from2] );
}
// Special forms needed by the legacy emitter syntax:
emitterT void AND32I8toR( x86IntRegType to, s8 from )
{
iAND( _reghlp<u32>(to), from );
@ -251,6 +263,53 @@ emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
iLEA( iRegister16( to ), ptr[x86IndexReg(from)*(1<<scale)] );
}
emitterT void BT32ItoR( x86IntRegType to, u8 from ) { iBT( iRegister32(to), from ); }
emitterT void BTR32ItoR( x86IntRegType to, u8 from ) { iBTR( iRegister32(to), from ); }
emitterT void SETS8R( x86IntRegType to ) { iSETS( iRegister8(to) ); }
emitterT void SETL8R( x86IntRegType to ) { iSETL( iRegister8(to) ); }
emitterT void SETGE8R( x86IntRegType to ) { iSETGE( iRegister8(to) ); }
emitterT void SETG8R( x86IntRegType to ) { iSETG( iRegister8(to) ); }
emitterT void SETA8R( x86IntRegType to ) { iSETA( iRegister8(to) ); }
emitterT void SETAE8R( x86IntRegType to ) { iSETAE( iRegister8(to) ); }
emitterT void SETB8R( x86IntRegType to ) { iSETB( iRegister8(to) ); }
emitterT void SETNZ8R( x86IntRegType to ) { iSETNZ( iRegister8(to) ); }
emitterT void SETZ8R( x86IntRegType to ) { iSETZ( iRegister8(to) ); }
emitterT void SETE8R( x86IntRegType to ) { iSETE( iRegister8(to) ); }
/* push imm32 */
emitterT void PUSH32I( u32 from ) { iPUSH( from ); }
/* push r32 */
emitterT void PUSH32R( x86IntRegType from ) { iPUSH( iRegister32( from ) ); }
/* push m32 */
emitterT void PUSH32M( u32 from )
{
iPUSH( ptr[from] );
}
/* pop r32 */
emitterT void POP32R( x86IntRegType from ) { iPOP( iRegister32( from ) ); }
emitterT void PUSHFD( void ) { iPUSHFD(); }
emitterT void POPFD( void ) { iPOPFD(); }
emitterT void RET( void ) { iRET(); }
emitterT void CBW( void ) { iCBW(); }
emitterT void CWD( void ) { iCWD(); }
emitterT void CDQ( void ) { iCDQ(); }
emitterT void CWDE() { iCWDE(); }
emitterT void LAHF() { iLAHF(); }
emitterT void SAHF() { iSAHF(); }
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// From here on are instructions that have NOT been implemented in the new emitter.
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Note: the 'to' field can either be a register or a special opcode extension specifier
// depending on the opcode's encoding.
@ -288,14 +347,6 @@ emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset
}
}
emitterT void SET8R( int cc, int to )
{
RexB(0, to);
write8( 0x0F );
write8( cc );
write8( 0xC0 | ( to ) );
}
emitterT u8* J8Rel( int cc, int to )
{
write8( cc );
@ -712,181 +763,6 @@ emitterT void CALL32M( u32 to )
write32( MEMADDR(to, 4) );
}
////////////////////////////////////
// misc instructions /
////////////////////////////////////
/* test imm32 to r32 */
emitterT void TEST32ItoR( x86IntRegType to, u32 from )
{
RexB(0,to);
if ( to == EAX )
{
write8( 0xA9 );
}
else
{
write8( 0xF7 );
ModRM( 3, 0, to );
}
write32( from );
}
emitterT void TEST32ItoM( uptr to, u32 from )
{
write8( 0xF7 );
ModRM( 0, 0, DISP32 );
write32( MEMADDR(to, 8) );
write32( from );
}
/* test r32 to r32 */
emitterT void TEST32RtoR( x86IntRegType to, x86IntRegType from )
{
RexRB(0,from,to);
write8( 0x85 );
ModRM( 3, from, to );
}
// test imm32 to [r32]
emitterT void TEST32ItoRm( x86IntRegType to, u32 from )
{
RexB(0,to);
write8( 0xF7 );
ModRM( 0, 0, to );
write32(from);
}
// test imm16 to r16
emitterT void TEST16ItoR( x86IntRegType to, u16 from )
{
write8(0x66);
RexB(0,to);
if ( to == EAX )
{
write8( 0xA9 );
}
else
{
write8( 0xF7 );
ModRM( 3, 0, to );
}
write16( from );
}
// test r16 to r16
emitterT void TEST16RtoR( x86IntRegType to, x86IntRegType from )
{
write8(0x66);
RexRB(0,from,to);
write8( 0x85 );
ModRM( 3, from, to );
}
// test r8 to r8
emitterT void TEST8RtoR( x86IntRegType to, x86IntRegType from )
{
RexRB(0, from, to);
write8( 0x84 );
ModRM( 3, from, to );
}
// test imm8 to r8
emitterT void TEST8ItoR( x86IntRegType to, u8 from )
{
RexB(0,to);
if ( to == EAX )
{
write8( 0xA8 );
}
else
{
write8( 0xF6 );
ModRM( 3, 0, to );
}
write8( from );
}
// test imm8 to r8
emitterT void TEST8ItoM( uptr to, u8 from )
{
write8( 0xF6 );
ModRM( 0, 0, DISP32 );
write32( MEMADDR(to, 5) );
write8( from );
}
/* sets r8 */
emitterT void SETS8R( x86IntRegType to )
{
SET8R( 0x98, to );
}
/* setl r8 */
emitterT void SETL8R( x86IntRegType to )
{
SET8R( 0x9C, to );
}
// setge r8
emitterT void SETGE8R( x86IntRegType to ) { SET8R(0x9d, to); }
// setg r8
emitterT void SETG8R( x86IntRegType to ) { SET8R(0x9f, to); }
// seta r8
emitterT void SETA8R( x86IntRegType to ) { SET8R(0x97, to); }
// setae r8
emitterT void SETAE8R( x86IntRegType to ) { SET8R(0x99, to); }
/* setb r8 */
emitterT void SETB8R( x86IntRegType to ) { SET8R( 0x92, to ); }
/* setb r8 */
emitterT void SETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); }
// setz r8
emitterT void SETZ8R( x86IntRegType to ) { SET8R(0x94, to); }
// sete r8
emitterT void SETE8R( x86IntRegType to ) { SET8R(0x94, to); }
/* push imm32 */
emitterT void PUSH32I( u32 from ) { iPUSH( from ); }
/* push r32 */
emitterT void PUSH32R( x86IntRegType from ) { iPUSH( iRegister32( from ) ); }
/* push m32 */
emitterT void PUSH32M( u32 from )
{
iPUSH( ptr[from] );
}
/* pop r32 */
emitterT void POP32R( x86IntRegType from ) { iPOP( iRegister32( from ) ); }
emitterT void PUSHFD( void ) { write8( 0x9C ); }
emitterT void POPFD( void ) { write8( 0x9D ); }
emitterT void RET( void ) { iRET(); }
emitterT void CBW( void ) { iCBW(); }
emitterT void CWD( void ) { iCWD(); }
emitterT void CDQ( void ) { iCDQ(); }
emitterT void CWDE() { iCWDE(); }
emitterT void LAHF() { iLAHF(); }
emitterT void SAHF() { iSAHF(); }
emitterT void BT32ItoR( x86IntRegType to, u8 from )
{
write16( 0xBA0F );
ModRM(3, 4, to);
write8( from );
}
emitterT void BTR32ItoR( x86IntRegType to, u8 from )
{
write16( 0xBA0F );
ModRM(3, 6, to);
write8( from );
}
emitterT void BSRRtoR(x86IntRegType to, x86IntRegType from)
{
write16( 0xBD0F );

View File

@ -625,6 +625,8 @@ namespace x86Emitter
#include "implement/movs.h" // cmov and movsx/zx
#include "implement/dwshift.h" // doubleword shifts!
#include "implement/incdec.h"
#include "implement/bittest.h"
#include "implement/test.h"
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -646,6 +648,7 @@ namespace x86Emitter
// flags.
extern const Internal::MovImplAll iMOV;
extern const Internal::TestImplAll iTEST;
extern const Internal::Group2ImplAll<Internal::G2Type_ROL> iROL;
extern const Internal::Group2ImplAll<Internal::G2Type_ROR> iROR;
@ -672,6 +675,12 @@ namespace x86Emitter
extern const Internal::DwordShiftImplAll<false> iSHLD;
extern const Internal::DwordShiftImplAll<true> iSHRD;
extern const Internal::Group8ImplAll<Internal::G8Type_BT> iBT;
extern const Internal::Group8ImplAll<Internal::G8Type_BTR> iBTR;
extern const Internal::Group8ImplAll<Internal::G8Type_BTS> iBTS;
extern const Internal::Group8ImplAll<Internal::G8Type_BTC> iBTC;
// ------------------------------------------------------------------------
extern const Internal::CMovImplGeneric iCMOV;
extern const Internal::CMovImplAll<Jcc_Above> iCMOVA;
@ -698,6 +707,35 @@ namespace x86Emitter
extern const Internal::CMovImplAll<Jcc_Unsigned> iCMOVNS;
extern const Internal::CMovImplAll<Jcc_ParityEven> iCMOVPE;
extern const Internal::CMovImplAll<Jcc_ParityOdd> iCMOVPO;
// ------------------------------------------------------------------------
extern const Internal::SetImplGeneric iSET;
extern const Internal::SetImplAll<Jcc_Above> iSETA;
extern const Internal::SetImplAll<Jcc_AboveOrEqual> iSETAE;
extern const Internal::SetImplAll<Jcc_Below> iSETB;
extern const Internal::SetImplAll<Jcc_BelowOrEqual> iSETBE;
extern const Internal::SetImplAll<Jcc_Greater> iSETG;
extern const Internal::SetImplAll<Jcc_GreaterOrEqual> iSETGE;
extern const Internal::SetImplAll<Jcc_Less> iSETL;
extern const Internal::SetImplAll<Jcc_LessOrEqual> iSETLE;
extern const Internal::SetImplAll<Jcc_Zero> iSETZ;
extern const Internal::SetImplAll<Jcc_Equal> iSETE;
extern const Internal::SetImplAll<Jcc_NotZero> iSETNZ;
extern const Internal::SetImplAll<Jcc_NotEqual> iSETNE;
extern const Internal::SetImplAll<Jcc_Overflow> iSETO;
extern const Internal::SetImplAll<Jcc_NotOverflow> iSETNO;
extern const Internal::SetImplAll<Jcc_Carry> iSETC;
extern const Internal::SetImplAll<Jcc_NotCarry> iSETNC;
extern const Internal::SetImplAll<Jcc_Signed> iSETS;
extern const Internal::SetImplAll<Jcc_Unsigned> iSETNS;
extern const Internal::SetImplAll<Jcc_ParityEven> iSETPE;
extern const Internal::SetImplAll<Jcc_ParityOdd> iSETPO;
}