mirror of https://github.com/PCSX2/pcsx2.git
Emitter:
* Added MUL/DIV/IMUL/IDIV to the emitter, renamed as UMUL/SMUL respectively (to remove ambiguity of the instruction behaviors). * Fixed a bug in the shift instruction emitter that would have caused it to emit the wrong instruction type (like a SHR instead of a SHL, for example). * Added type strictness to the shift instructions that take the CL register as a parameter. Passing anything other than CL will generate compile time errors now. * Fixed a syntax error in one of the legacy defines. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@986 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
f228a91c93
commit
4658529970
|
@ -2925,6 +2925,10 @@
|
|||
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_dwshift.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_group1.h"
|
||||
>
|
||||
|
|
|
@ -89,11 +89,13 @@ const iRegister16
|
|||
bp( 5 ), sp( 4 );
|
||||
|
||||
const iRegister8
|
||||
al( 0 ), cl( 1 ),
|
||||
al( 0 ),
|
||||
dl( 2 ), bl( 3 ),
|
||||
ah( 4 ), ch( 5 ),
|
||||
dh( 6 ), bh( 7 );
|
||||
|
||||
const iRegisterCL cl;
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
// Performance note: VC++ wants to use byte/word register form for the following
|
||||
|
@ -250,8 +252,11 @@ const Group2ImplAll<G2Type_SHL> iSHL;
|
|||
const Group2ImplAll<G2Type_SHR> iSHR;
|
||||
const Group2ImplAll<G2Type_SAR> iSAR;
|
||||
|
||||
const MovExtendImplAll<true> iMOVSX;
|
||||
const MovExtendImplAll<false> iMOVZX;
|
||||
const MovExtendImplAll<true> iMOVSX;
|
||||
|
||||
const Internal::DwordShiftImplAll<false> iSHLD;
|
||||
const Internal::DwordShiftImplAll<true> iSHRD;
|
||||
|
||||
const CMovImplGeneric iCMOV;
|
||||
|
||||
|
@ -641,6 +646,150 @@ void iMOV( const iRegister8& to, u8 imm, bool preserve_flags )
|
|||
MOV8::Emit( to, imm );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DIV/MUL/IDIV/IMUL instructions (Implemented!)
|
||||
|
||||
// F6 is r8, F7 is r32.
|
||||
// MUL is 4, DIV is 6.
|
||||
|
||||
enum MulDivType
|
||||
{
|
||||
MDT_Mul = 4,
|
||||
MDT_iMul = 5,
|
||||
MDT_Div = 6,
|
||||
MDT_iDiv = 7
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// EAX form emitter for Mul/Div/iMUL/iDIV
|
||||
//
|
||||
template< int OperandSize >
|
||||
static __forceinline void EmitMulDiv_OneRegForm( MulDivType InstType, const iRegister<OperandSize>& from )
|
||||
{
|
||||
if( OperandSize == 2 ) iWrite<u8>( 0x66 );
|
||||
iWrite<u8>( (OperandSize == 1) ? 0xf6 : 0xf7 );
|
||||
ModRM( ModRm_Direct, InstType, from.Id );
|
||||
}
|
||||
|
||||
static __forceinline void EmitMulDiv_OneRegForm( MulDivType InstType, const ModSibSized& sibsrc )
|
||||
{
|
||||
if( sibsrc.OperandSize == 2 ) iWrite<u8>( 0x66 );
|
||||
iWrite<u8>( (sibsrc.OperandSize == 1) ? 0xf6 : 0xf7 );
|
||||
EmitSibMagic( InstType, sibsrc );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// All ioMul forms are valid for 16 and 32 bit register operands only!
|
||||
|
||||
template< typename ImmType >
|
||||
class iMulImpl
|
||||
{
|
||||
public:
|
||||
static const uint OperandSize = sizeof(ImmType);
|
||||
|
||||
protected:
|
||||
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const iRegister<OperandSize>& from )
|
||||
{
|
||||
prefix16();
|
||||
write16( 0xaf0f );
|
||||
ModRM( ModRm_Direct, to.Id, from.Id );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const void* src )
|
||||
{
|
||||
prefix16();
|
||||
write16( 0xaf0f );
|
||||
iWriteDisp( to.Id, src );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const ModSibBase& src )
|
||||
{
|
||||
prefix16();
|
||||
write16( 0xaf0f );
|
||||
EmitSibMagic( to.Id, src );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const iRegister<OperandSize>& from, ImmType imm )
|
||||
{
|
||||
prefix16();
|
||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
||||
ModRM( ModRm_Direct, to.Id, from.Id );
|
||||
if( is_s8( imm ) )
|
||||
write8( imm );
|
||||
else
|
||||
iWrite<ImmType>( imm );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const void* src, ImmType imm )
|
||||
{
|
||||
prefix16();
|
||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
||||
iWriteDisp( to.Id, src );
|
||||
if( is_s8( imm ) )
|
||||
write8( imm );
|
||||
else
|
||||
iWrite<ImmType>( imm );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
static __forceinline void Emit( const iRegister<OperandSize>& to, const ModSibBase& src, ImmType imm )
|
||||
{
|
||||
prefix16();
|
||||
write16( is_s8( imm ) ? 0x6b : 0x69 );
|
||||
EmitSibMagic( to.Id, src );
|
||||
if( is_s8( imm ) )
|
||||
write8( imm );
|
||||
else
|
||||
iWrite<ImmType>( imm );
|
||||
}
|
||||
};
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
typedef iMulImpl<u32> iMUL32;
|
||||
typedef iMulImpl<u16> iMUL16;
|
||||
}
|
||||
|
||||
__forceinline void iUMUL( const iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
__forceinline void iUMUL( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
__forceinline void iUMUL( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
__noinline void iUMUL( const ModSibSized& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
|
||||
__forceinline void iUDIV( const iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_Div, from ); }
|
||||
__forceinline void iUDIV( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_Div, from ); }
|
||||
__forceinline void iUDIV( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_Div, from ); }
|
||||
__noinline void iUDIV( const ModSibSized& from ) { EmitMulDiv_OneRegForm( MDT_Div, from ); }
|
||||
|
||||
__forceinline void iSDIV( const iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_iDiv, from ); }
|
||||
__forceinline void iSDIV( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_iDiv, from ); }
|
||||
__forceinline void iSDIV( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_iDiv, from ); }
|
||||
__noinline void iSDIV( const ModSibSized& from ) { EmitMulDiv_OneRegForm( MDT_iDiv, from ); }
|
||||
|
||||
__forceinline void iSMUL( const iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
|
||||
__forceinline void iSMUL( const iRegister32& to, const iRegister32& from ) { iMUL32::Emit( to, from ); }
|
||||
__forceinline void iSMUL( const iRegister32& to, const void* src ) { iMUL32::Emit( to, src ); }
|
||||
__forceinline void iSMUL( const iRegister32& to, const iRegister32& from, s32 imm ) { iMUL32::Emit( to, from, imm ); }
|
||||
__noinline void iSMUL( const iRegister32& to, const ModSibBase& src ) { iMUL32::Emit( to, src ); }
|
||||
__noinline void iSMUL( const iRegister32& to, const ModSibBase& from, s32 imm ) { iMUL32::Emit( to, from, imm ); }
|
||||
|
||||
__forceinline void iSMUL( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
|
||||
__forceinline void iSMUL( const iRegister16& to, const iRegister16& from ) { iMUL16::Emit( to, from ); }
|
||||
__forceinline void iSMUL( const iRegister16& to, const void* src ) { iMUL16::Emit( to, src ); }
|
||||
__forceinline void iSMUL( const iRegister16& to, const iRegister16& from, s16 imm ) { iMUL16::Emit( to, from, imm ); }
|
||||
__noinline void iSMUL( const iRegister16& to, const ModSibBase& src ) { iMUL16::Emit( to, src ); }
|
||||
__noinline void iSMUL( const iRegister16& to, const ModSibBase& from, s16 imm ) { iMUL16::Emit( to, from, imm ); }
|
||||
|
||||
__forceinline void iSMUL( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
|
||||
__noinline void iSMUL( const ModSibSized& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Push / Pop Emitters
|
||||
|
|
|
@ -52,10 +52,8 @@ protected:
|
|||
static void prefix16() { if( OperandSize == 2 ) iWrite<u8>( 0x66 ); }
|
||||
|
||||
public:
|
||||
static __emitinline void Emit( const iRegister<OperandSize>& to, const iRegister8& from )
|
||||
static __emitinline void Emit( const iRegister<OperandSize>& to )
|
||||
{
|
||||
jASSUME( from == cl ); // cl is the only valid shift register. (turn this into a compile time check?)
|
||||
|
||||
prefix16();
|
||||
iWrite<u8>( Is8BitOperand() ? 0xd2 : 0xd3 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
|
@ -80,13 +78,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static __emitinline void Emit( const ModSibStrict<OperandSize>& sibdest, const iRegister8& from )
|
||||
static __emitinline void Emit( const ModSibStrict<OperandSize>& sibdest )
|
||||
{
|
||||
jASSUME( from == cl ); // cl is the only valid shift register. (turn this into a compile time check?)
|
||||
|
||||
prefix16();
|
||||
iWrite<u8>( Is8BitOperand() ? 0xd2 : 0xd3 );
|
||||
EmitSibMagic( from.Id, sibdest );
|
||||
EmitSibMagic( InstType, sibdest );
|
||||
}
|
||||
|
||||
static __emitinline void Emit( const ModSibStrict<OperandSize>& sibdest, u8 imm )
|
||||
|
@ -130,20 +126,20 @@ protected:
|
|||
|
||||
public:
|
||||
// ---------- 32 Bit Interface -----------
|
||||
__forceinline void operator()( const iRegister32& to, const iRegister8& from ) const { m_32::Emit( to, from ); }
|
||||
__noinline void operator()( const ModSibStrict<4>& sibdest, const iRegister8& from ) const { m_32::Emit( sibdest, from ); }
|
||||
__forceinline void operator()( const iRegister32& to, __unused const iRegisterCL& from ) const{ m_32::Emit( to ); }
|
||||
__noinline void operator()( const ModSibStrict<4>& sibdest, __unused const iRegisterCL& from ) const{ m_32::Emit( sibdest ); }
|
||||
__noinline void operator()( const ModSibStrict<4>& sibdest, u8 imm ) const { m_32::Emit( sibdest, imm ); }
|
||||
void operator()( const iRegister32& to, u8 imm ) const { m_32::Emit( to, imm ); }
|
||||
|
||||
// ---------- 16 Bit Interface -----------
|
||||
__forceinline void operator()( const iRegister16& to, const iRegister8& from ) const { m_16::Emit( to, from ); }
|
||||
__noinline void operator()( const ModSibStrict<2>& sibdest, const iRegister8& from ) const { m_16::Emit( sibdest, from ); }
|
||||
__forceinline void operator()( const iRegister16& to, __unused const iRegisterCL& from ) const{ m_16::Emit( to ); }
|
||||
__noinline void operator()( const ModSibStrict<2>& sibdest, __unused const iRegisterCL& from ) const{ m_16::Emit( sibdest ); }
|
||||
__noinline void operator()( const ModSibStrict<2>& sibdest, u8 imm ) const { m_16::Emit( sibdest, imm ); }
|
||||
void operator()( const iRegister16& to, u8 imm ) const { m_16::Emit( to, imm ); }
|
||||
|
||||
// ---------- 8 Bit Interface -----------
|
||||
__forceinline void operator()( const iRegister8& to, const iRegister8& from ) const { m_8::Emit( to, from ); }
|
||||
__noinline void operator()( const ModSibStrict<1>& sibdest, const iRegister8& from ) const { m_8::Emit( sibdest, from ); }
|
||||
__forceinline void operator()( const iRegister8& to, __unused const iRegisterCL& from ) const{ m_8::Emit( to ); }
|
||||
__noinline void operator()( const ModSibStrict<1>& sibdest, __unused const iRegisterCL& from ) const{ m_8::Emit( sibdest ); }
|
||||
__noinline void operator()( const ModSibStrict<1>& sibdest, u8 imm ) const { m_8::Emit( sibdest, imm ); }
|
||||
void operator()( const iRegister8& to, u8 imm ) const { m_8::Emit( to, imm ); }
|
||||
|
||||
|
|
|
@ -83,6 +83,42 @@ namespace x86Emitter
|
|||
// NOP 1-byte
|
||||
__forceinline void iNOP() { write8(0x90); }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MUL / DIV instructions
|
||||
|
||||
extern void iUMUL( const iRegister32& from );
|
||||
extern void iUMUL( const iRegister16& from );
|
||||
extern void iUMUL( const iRegister8& from );
|
||||
extern void iUMUL( const ModSibSized& from );
|
||||
|
||||
extern void iUDIV( const iRegister32& from );
|
||||
extern void iUDIV( const iRegister16& from );
|
||||
extern void iUDIV( const iRegister8& from );
|
||||
extern void iUDIV( const ModSibSized& from );
|
||||
|
||||
extern void iSDIV( const iRegister32& from );
|
||||
extern void iSDIV( const iRegister16& from );
|
||||
extern void iSDIV( const iRegister8& from );
|
||||
extern void iSDIV( const ModSibSized& from );
|
||||
|
||||
extern void iSMUL( const iRegister32& from );
|
||||
extern void iSMUL( const iRegister32& to, const iRegister32& from );
|
||||
extern void iSMUL( const iRegister32& to, const void* src );
|
||||
extern void iSMUL( const iRegister32& to, const iRegister32& from, s32 imm );
|
||||
extern void iSMUL( const iRegister32& to, const ModSibBase& src );
|
||||
extern void iSMUL( const iRegister32& to, const ModSibBase& src, s32 imm );
|
||||
|
||||
extern void iSMUL( const iRegister16& from );
|
||||
extern void iSMUL( const iRegister16& to, const iRegister16& from );
|
||||
extern void iSMUL( const iRegister16& to, const void* src );
|
||||
extern void iSMUL( const iRegister16& to, const iRegister16& from, s16 imm );
|
||||
extern void iSMUL( const iRegister16& to, const ModSibBase& src );
|
||||
extern void iSMUL( const iRegister16& to, const ModSibBase& src, s16 imm );
|
||||
|
||||
extern void iSMUL( const iRegister8& from );
|
||||
extern void iSMUL( const ModSibSized& from );
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MOV instructions!
|
||||
// ---------- 32 Bit Interface -----------
|
||||
|
|
|
@ -117,9 +117,9 @@ DEFINE_OPCODE_LEGACY( MOV )
|
|||
|
||||
// ------------------------------------------------------------------------
|
||||
#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##M##srcbits##toR( x86IntRegType to, u32 from ) { iMOV##form##( iRegister##destbits( to ), ptr##srcbits[from] ); }
|
||||
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##M##srcbits##toR( x86IntRegType to, u32 from ) { iMOV##form( iRegister##destbits( to ), ptr##srcbits[from] ); }
|
||||
|
||||
DEFINE_LEGACY_MOVEXTEND( SX, 32, 16 )
|
||||
DEFINE_LEGACY_MOVEXTEND( ZX, 32, 16 )
|
||||
|
@ -164,7 +164,53 @@ emitterT void CMOVE32RtoR( x86IntRegType to, x86IntRegType from )
|
|||
iCMOVE( iRegister32(to), iRegister32(from) );
|
||||
}
|
||||
|
||||
// shld imm8 to r32
|
||||
emitterT void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
|
||||
{
|
||||
iSHLD( iRegister32(to), iRegister32(from), shift );
|
||||
}
|
||||
|
||||
// shrd imm8 to r32
|
||||
emitterT void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
|
||||
{
|
||||
iSHRD( iRegister32(to), iRegister32(from), shift );
|
||||
}
|
||||
|
||||
emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] );
|
||||
}
|
||||
|
||||
emitterT void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] );
|
||||
}
|
||||
|
||||
// Don't inline recursive functions
|
||||
emitterT void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from)*(1<<scale)] );
|
||||
}
|
||||
|
||||
// to = from + offset
|
||||
emitterT void LEA16RtoR(x86IntRegType to, x86IntRegType from, s16 offset)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from)+offset] );
|
||||
}
|
||||
|
||||
// to = from0 + from1
|
||||
emitterT void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] );
|
||||
}
|
||||
|
||||
// to = from << scale (max is 3)
|
||||
emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from)*(1<<scale)] );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Note: the 'to' field can either be a register or a special opcode extension specifier
|
||||
// depending on the opcode's encoding.
|
||||
|
||||
|
@ -368,96 +414,28 @@ emitterT void DEC16M( u32 to )
|
|||
}
|
||||
|
||||
/* mul eax by r32 to edx:eax */
|
||||
emitterT void MUL32R( x86IntRegType from )
|
||||
{
|
||||
RexB(0,from);
|
||||
write8( 0xF7 );
|
||||
ModRM( 3, 4, from );
|
||||
}
|
||||
|
||||
emitterT void MUL32R( x86IntRegType from ) { iUMUL( iRegister32(from) ); }
|
||||
/* imul eax by r32 to edx:eax */
|
||||
emitterT void IMUL32R( x86IntRegType from )
|
||||
{
|
||||
RexB(0,from);
|
||||
write8( 0xF7 );
|
||||
ModRM( 3, 5, from );
|
||||
}
|
||||
|
||||
emitterT void IMUL32R( x86IntRegType from ) { iSMUL( iRegister32(from) ); }
|
||||
/* mul eax by m32 to edx:eax */
|
||||
emitterT void MUL32M( u32 from )
|
||||
{
|
||||
write8( 0xF7 );
|
||||
ModRM( 0, 4, DISP32 );
|
||||
write32( MEMADDR(from, 4) );
|
||||
}
|
||||
|
||||
emitterT void MUL32M( u32 from ) { iUMUL( ptr32[from] ); }
|
||||
/* imul eax by m32 to edx:eax */
|
||||
emitterT void IMUL32M( u32 from )
|
||||
{
|
||||
write8( 0xF7 );
|
||||
ModRM( 0, 5, DISP32 );
|
||||
write32( MEMADDR(from, 4) );
|
||||
}
|
||||
emitterT void IMUL32M( u32 from ) { iSMUL( ptr32[from] ); }
|
||||
|
||||
/* imul r32 by r32 to r32 */
|
||||
emitterT void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
|
||||
{
|
||||
RexRB(0,to,from);
|
||||
write16( 0xAF0F );
|
||||
ModRM( 3, to, from );
|
||||
iSMUL( iRegister32(to), iRegister32(from) );
|
||||
}
|
||||
|
||||
/* div eax by r32 to edx:eax */
|
||||
emitterT void DIV32R( x86IntRegType from )
|
||||
{
|
||||
RexB(0,from);
|
||||
write8( 0xF7 );
|
||||
ModRM( 3, 6, from );
|
||||
}
|
||||
|
||||
emitterT void DIV32R( x86IntRegType from ) { iUDIV( iRegister32(from) ); }
|
||||
/* idiv eax by r32 to edx:eax */
|
||||
emitterT void IDIV32R( x86IntRegType from )
|
||||
{
|
||||
RexB(0,from);
|
||||
write8( 0xF7 );
|
||||
ModRM( 3, 7, from );
|
||||
}
|
||||
|
||||
emitterT void IDIV32R( x86IntRegType from ) { iSDIV( iRegister32(from) ); }
|
||||
/* div eax by m32 to edx:eax */
|
||||
emitterT void DIV32M( u32 from )
|
||||
{
|
||||
write8( 0xF7 );
|
||||
ModRM( 0, 6, DISP32 );
|
||||
write32( MEMADDR(from, 4) );
|
||||
}
|
||||
|
||||
emitterT void DIV32M( u32 from ) { iUDIV( ptr32[from] ); }
|
||||
/* idiv eax by m32 to edx:eax */
|
||||
emitterT void IDIV32M( u32 from )
|
||||
{
|
||||
write8( 0xF7 );
|
||||
ModRM( 0, 7, DISP32 );
|
||||
write32( MEMADDR(from, 4) );
|
||||
}
|
||||
|
||||
// shld imm8 to r32
|
||||
emitterT void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
|
||||
{
|
||||
RexRB(0,from,to);
|
||||
write8( 0x0F );
|
||||
write8( 0xA4 );
|
||||
ModRM( 3, from, to );
|
||||
write8( shift );
|
||||
}
|
||||
|
||||
// shrd imm8 to r32
|
||||
emitterT void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
|
||||
{
|
||||
RexRB(0,from,to);
|
||||
write8( 0x0F );
|
||||
write8( 0xAC );
|
||||
ModRM( 3, from, to );
|
||||
write8( shift );
|
||||
}
|
||||
emitterT void IDIV32M( u32 from ) { iSDIV( ptr32[from] ); }
|
||||
|
||||
////////////////////////////////////
|
||||
// logical instructions /
|
||||
|
@ -1011,37 +989,3 @@ emitterT void BSWAP32R( x86IntRegType to )
|
|||
write8( 0x0F );
|
||||
write8( 0xC8 + to );
|
||||
}
|
||||
|
||||
emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] );
|
||||
}
|
||||
|
||||
emitterT void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] );
|
||||
}
|
||||
|
||||
// Don't inline recursive functions
|
||||
emitterT void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
|
||||
{
|
||||
iLEA( iRegister32( to ), ptr[x86IndexReg(from)*(1<<scale)] );
|
||||
}
|
||||
|
||||
// to = from + offset
|
||||
emitterT void LEA16RtoR(x86IntRegType to, x86IntRegType from, s16 offset)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from)+offset] );
|
||||
}
|
||||
|
||||
// to = from0 + from1
|
||||
emitterT void LEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from0)+x86IndexReg(from1)] );
|
||||
}
|
||||
|
||||
// to = from << scale (max is 3)
|
||||
emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale)
|
||||
{
|
||||
iLEA( iRegister16( to ), ptr[x86IndexReg(from)*(1<<scale)] );
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ namespace x86Emitter
|
|||
# define __noinline
|
||||
#endif
|
||||
|
||||
static const int ModRm_Direct = 3; // when used as the first parameter, specifies direct register operation (no mem)
|
||||
static const int ModRm_UseSib = 4; // same index value as ESP (used in RM field)
|
||||
static const int ModRm_UseDisp32 = 5; // same index value as EBP (used in Mod field)
|
||||
|
||||
|
@ -233,32 +234,25 @@ namespace x86Emitter
|
|||
typedef iRegister<2> iRegister16;
|
||||
typedef iRegister<1> iRegister8;
|
||||
|
||||
extern const iRegister32 eax;
|
||||
extern const iRegister32 ebx;
|
||||
extern const iRegister32 ecx;
|
||||
extern const iRegister32 edx;
|
||||
extern const iRegister32 esi;
|
||||
extern const iRegister32 edi;
|
||||
extern const iRegister32 ebp;
|
||||
extern const iRegister32 esp;
|
||||
class iRegisterCL : public iRegister8
|
||||
{
|
||||
public:
|
||||
iRegisterCL(): iRegister8( 1 ) {}
|
||||
};
|
||||
|
||||
extern const iRegister16 ax;
|
||||
extern const iRegister16 bx;
|
||||
extern const iRegister16 cx;
|
||||
extern const iRegister16 dx;
|
||||
extern const iRegister16 si;
|
||||
extern const iRegister16 di;
|
||||
extern const iRegister16 bp;
|
||||
extern const iRegister16 sp;
|
||||
extern const iRegister32
|
||||
eax, ebx, ecx, edx,
|
||||
esi, edi, ebp, esp;
|
||||
|
||||
extern const iRegister8 al;
|
||||
extern const iRegister8 cl;
|
||||
extern const iRegister8 dl;
|
||||
extern const iRegister8 bl;
|
||||
extern const iRegister8 ah;
|
||||
extern const iRegister8 ch;
|
||||
extern const iRegister8 dh;
|
||||
extern const iRegister8 bh;
|
||||
extern const iRegister16
|
||||
ax, bx, cx, dx,
|
||||
si, di, bp, sp;
|
||||
|
||||
extern const iRegister8
|
||||
al, dl, bl,
|
||||
ah, ch, dh, bh;
|
||||
|
||||
extern const iRegisterCL cl; // I'm special!
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Use 32 bit registers as out index register (for ModSib memory address calculations)
|
||||
|
@ -346,6 +340,13 @@ namespace x86Emitter
|
|||
__forceinline iAddressInfo operator-( s32 imm ) const { return iAddressInfo( *this ).Add( -imm ); }
|
||||
};
|
||||
|
||||
enum OperandSizeType
|
||||
{
|
||||
OpSize_8 = 1,
|
||||
OpSize_16 = 2,
|
||||
OpSize_32 = 4,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ModSib - Internal low-level representation of the ModRM/SIB information.
|
||||
//
|
||||
|
@ -387,26 +388,64 @@ namespace x86Emitter
|
|||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Strictly-typed version of ModSibBase, which is used to apply operand size information
|
||||
// to ImmToMem operations.
|
||||
//
|
||||
template< int OperandSize >
|
||||
class ModSibStrict : public ModSibBase
|
||||
class ModSibSized : public ModSibBase
|
||||
{
|
||||
public:
|
||||
__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 ) :
|
||||
ModSibBase( base, index, scale, displacement ) {}
|
||||
int OperandSize;
|
||||
|
||||
__forceinline ModSibStrict<OperandSize>& Add( s32 imm )
|
||||
ModSibSized( int opsize, const iAddressInfo& src ) :
|
||||
ModSibBase( src ),
|
||||
OperandSize( opsize )
|
||||
{
|
||||
jASSUME( OperandSize == 1 || OperandSize == 2 || OperandSize == 4 );
|
||||
}
|
||||
|
||||
ModSibSized( int opsize, s32 disp ) :
|
||||
ModSibBase( disp ),
|
||||
OperandSize( opsize )
|
||||
{
|
||||
jASSUME( OperandSize == 1 || OperandSize == 2 || OperandSize == 4 );
|
||||
}
|
||||
|
||||
ModSibSized( int opsize, x86IndexReg base, x86IndexReg index, int scale=0, s32 displacement=0 ) :
|
||||
ModSibBase( base, index, scale, displacement ),
|
||||
OperandSize( opsize )
|
||||
{
|
||||
jASSUME( OperandSize == 1 || OperandSize == 2 || OperandSize == 4 );
|
||||
}
|
||||
|
||||
__forceinline ModSibSized& Add( s32 imm )
|
||||
{
|
||||
Displacement += imm;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__forceinline ModSibStrict<OperandSize> operator+( const s32 imm ) const { return ModSibStrict<OperandSize>( *this ).Add( imm ); }
|
||||
__forceinline ModSibStrict<OperandSize> operator-( const s32 imm ) const { return ModSibStrict<OperandSize>( *this ).Add( -imm ); }
|
||||
__forceinline ModSibSized operator+( const s32 imm ) const { return ModSibSized( *this ).Add( imm ); }
|
||||
__forceinline ModSibSized operator-( const s32 imm ) const { return ModSibSized( *this ).Add( -imm ); }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Strictly-typed version of ModSibBase, which is used to apply operand size information
|
||||
// to ImmToMem operations.
|
||||
//
|
||||
template< int OpSize >
|
||||
class ModSibStrict : public ModSibSized
|
||||
{
|
||||
public:
|
||||
__forceinline explicit ModSibStrict( const iAddressInfo& src ) : ModSibSized( OpSize, src ) {}
|
||||
__forceinline explicit ModSibStrict( s32 disp ) : ModSibSized( OpSize, disp ) {}
|
||||
__forceinline ModSibStrict( x86IndexReg base, x86IndexReg index, int scale=0, s32 displacement=0 ) :
|
||||
ModSibSized( OpSize, base, index, scale, displacement ) {}
|
||||
|
||||
__forceinline ModSibStrict<OpSize>& Add( s32 imm )
|
||||
{
|
||||
Displacement += imm;
|
||||
return *this;
|
||||
}
|
||||
|
||||
__forceinline ModSibStrict<OpSize> operator+( const s32 imm ) const { return ModSibStrict<OpSize>( *this ).Add( imm ); }
|
||||
__forceinline ModSibStrict<OpSize> operator-( const s32 imm ) const { return ModSibStrict<OpSize>( *this ).Add( -imm ); }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -605,7 +644,8 @@ namespace x86Emitter
|
|||
|
||||
#include "ix86_impl_group1.h"
|
||||
#include "ix86_impl_group2.h"
|
||||
#include "ix86_impl_movs.h"
|
||||
#include "ix86_impl_movs.h" // cmov and movsx/zx
|
||||
#include "ix86_impl_dwshift.h" // dowubleword shifts!
|
||||
|
||||
// if the immediate is zero, we can replace the instruction, or ignore it
|
||||
// entirely, depending on the instruction being issued. That's what we do here.
|
||||
|
@ -675,8 +715,11 @@ namespace x86Emitter
|
|||
extern const Internal::Group2ImplAll<Internal::G2Type_SHR> iSHR;
|
||||
extern const Internal::Group2ImplAll<Internal::G2Type_SAR> iSAR;
|
||||
|
||||
extern const Internal::MovExtendImplAll<true> iMOVSX;
|
||||
extern const Internal::MovExtendImplAll<false> iMOVZX;
|
||||
extern const Internal::MovExtendImplAll<true> iMOVSX;
|
||||
|
||||
extern const Internal::DwordShiftImplAll<false> iSHLD;
|
||||
extern const Internal::DwordShiftImplAll<true> iSHRD;
|
||||
|
||||
extern const Internal::CMovImplGeneric iCMOV;
|
||||
|
||||
|
|
Loading…
Reference in New Issue