mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
62604d359a
commit
029a94ce3f
|
@ -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
|
||||
|
|
|
@ -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() {}
|
||||
};
|
|
@ -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)
|
||||
//
|
||||
|
|
|
@ -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?
|
||||
};
|
||||
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue