diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index f238a8c12e..d81664fa89 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -2925,6 +2925,10 @@
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
>
+
+
diff --git a/pcsx2/x86/ix86/ix86.cpp b/pcsx2/x86/ix86/ix86.cpp
index c1aed679ea..ec41c81e50 100644
--- a/pcsx2/x86/ix86/ix86.cpp
+++ b/pcsx2/x86/ix86/ix86.cpp
@@ -74,7 +74,7 @@ const x86IndexerTypeExplicit<1> ptr8;
// ------------------------------------------------------------------------
template< int OperandSize > const iRegister iRegister::Empty;
-const x86IndexReg x86IndexReg::Empty;
+const x86IndexReg x86IndexReg::Empty;
const iRegister32
eax( 0 ), ebx( 3 ),
@@ -89,10 +89,12 @@ 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
{
@@ -250,8 +252,11 @@ const Group2ImplAll iSHL;
const Group2ImplAll iSHR;
const Group2ImplAll iSAR;
-const MovExtendImplAll iMOVSX;
const MovExtendImplAll iMOVZX;
+const MovExtendImplAll iMOVSX;
+
+const Internal::DwordShiftImplAll iSHLD;
+const Internal::DwordShiftImplAll 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& from )
+{
+ if( OperandSize == 2 ) iWrite( 0x66 );
+ iWrite( (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( 0x66 );
+ iWrite( (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( 0x66 ); }
+
+public:
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const iRegister& from )
+ {
+ prefix16();
+ write16( 0xaf0f );
+ ModRM( ModRm_Direct, to.Id, from.Id );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const void* src )
+ {
+ prefix16();
+ write16( 0xaf0f );
+ iWriteDisp( to.Id, src );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const ModSibBase& src )
+ {
+ prefix16();
+ write16( 0xaf0f );
+ EmitSibMagic( to.Id, src );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const iRegister& 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( imm );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& 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( imm );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& 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( imm );
+ }
+};
+
+namespace Internal
+{
+ typedef iMulImpl iMUL32;
+ typedef iMulImpl 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
diff --git a/pcsx2/x86/ix86/ix86_impl_group2.h b/pcsx2/x86/ix86/ix86_impl_group2.h
index 23cb8c78a3..dd551713d1 100644
--- a/pcsx2/x86/ix86/ix86_impl_group2.h
+++ b/pcsx2/x86/ix86/ix86_impl_group2.h
@@ -52,10 +52,8 @@ protected:
static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); }
public:
- static __emitinline void Emit( const iRegister& to, const iRegister8& from )
+ static __emitinline void Emit( const iRegister& to )
{
- jASSUME( from == cl ); // cl is the only valid shift register. (turn this into a compile time check?)
-
prefix16();
iWrite( Is8BitOperand() ? 0xd2 : 0xd3 );
ModRM( 3, InstType, to.Id );
@@ -80,13 +78,11 @@ public:
}
}
- static __emitinline void Emit( const ModSibStrict& sibdest, const iRegister8& from )
+ static __emitinline void Emit( const ModSibStrict& sibdest )
{
- jASSUME( from == cl ); // cl is the only valid shift register. (turn this into a compile time check?)
-
prefix16();
iWrite( Is8BitOperand() ? 0xd2 : 0xd3 );
- EmitSibMagic( from.Id, sibdest );
+ EmitSibMagic( InstType, sibdest );
}
static __emitinline void Emit( const ModSibStrict& 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 ); }
diff --git a/pcsx2/x86/ix86/ix86_instructions.h b/pcsx2/x86/ix86/ix86_instructions.h
index 3b8b885a11..533c2dbd57 100644
--- a/pcsx2/x86/ix86/ix86_instructions.h
+++ b/pcsx2/x86/ix86/ix86_instructions.h
@@ -82,6 +82,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!
diff --git a/pcsx2/x86/ix86/ix86_legacy.cpp b/pcsx2/x86/ix86/ix86_legacy.cpp
index d0fd220455..3f12a7f818 100644
--- a/pcsx2/x86/ix86/ix86_legacy.cpp
+++ b/pcsx2/x86/ix86/ix86_legacy.cpp
@@ -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< 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& 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 operator+( const s32 imm ) const { return ModSibStrict( *this ).Add( imm ); }
- __forceinline ModSibStrict operator-( const s32 imm ) const { return ModSibStrict( *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& Add( s32 imm )
+ {
+ Displacement += imm;
+ return *this;
+ }
+
+ __forceinline ModSibStrict operator+( const s32 imm ) const { return ModSibStrict( *this ).Add( imm ); }
+ __forceinline ModSibStrict operator-( const s32 imm ) const { return ModSibStrict( *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 iSHR;
extern const Internal::Group2ImplAll iSAR;
+ extern const Internal::MovExtendImplAll iMOVZX;
extern const Internal::MovExtendImplAll iMOVSX;
- extern const Internal::MovExtendImplAll iMOVZX;
+
+ extern const Internal::DwordShiftImplAll iSHLD;
+ extern const Internal::DwordShiftImplAll iSHRD;
extern const Internal::CMovImplGeneric iCMOV;