diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index d81664fa89..7f961b7061 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -2925,22 +2925,6 @@
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
>
-
-
-
-
-
-
-
-
@@ -2993,6 +2977,30 @@
RelativePath="..\..\x86\ix86\ix86_types.h"
>
+
+
+
+
+
+
+
+
+
+
+
+
& to, const iRegister& from, u8 imm )
@@ -57,7 +57,7 @@ public:
if( imm == 0 ) return;
prefix16();
write16( 0xa40f | (isShiftRight ? 0x800 : 0) );
- ModRM( 3, from.Id, to.Id );
+ ModRM_Direct( from.Id, to.Id );
write8( imm );
}
diff --git a/pcsx2/x86/ix86/ix86_impl_group1.h b/pcsx2/x86/ix86/implement/group1.h
similarity index 92%
rename from pcsx2/x86/ix86/ix86_impl_group1.h
rename to pcsx2/x86/ix86/implement/group1.h
index b948700b9b..c9b313cb85 100644
--- a/pcsx2/x86/ix86/ix86_impl_group1.h
+++ b/pcsx2/x86/ix86/implement/group1.h
@@ -19,7 +19,6 @@
#pragma once
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
-
// Instructions implemented in this header are as follows -->>
enum G1Type
@@ -52,7 +51,7 @@ public:
{
prefix16();
iWrite( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
- ModRM( 3, from.Id, to.Id );
+ ModRM_Direct( from.Id, to.Id );
}
static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from )
@@ -89,7 +88,7 @@ public:
if( !Is8BitOperand() && is_s8( imm ) )
{
iWrite( 0x83 );
- ModRM( 3, InstType, to.Id );
+ ModRM_Direct( InstType, to.Id );
iWrite( imm );
}
else
@@ -99,7 +98,7 @@ public:
else
{
iWrite( Is8BitOperand() ? 0x80 : 0x81 );
- ModRM( 3, InstType, to.Id );
+ ModRM_Direct( InstType, to.Id );
}
iWrite( imm );
}
@@ -148,11 +147,7 @@ public:
__noinline void operator()( const iRegister32& to, const ModSibBase& sibsrc ) const{ m_32::Emit( to, sibsrc ); }
__noinline void operator()( const ModSibStrict<4>& sibdest, u32 imm ) const { m_32::Emit( sibdest, imm ); }
- void operator()( const iRegister32& to, u32 imm, bool needs_flags=false ) const
- {
- //if( needs_flags || (imm != 0) || !_optimize_imm0() )
- m_32::Emit( to, imm );
- }
+ void operator()( const iRegister32& to, u32 imm ) const { m_32::Emit( to, imm ); }
// ---------- 16 Bit Interface -----------
__forceinline void operator()( const iRegister16& to, const iRegister16& from ) const { m_16::Emit( to, from ); }
@@ -162,7 +157,7 @@ public:
__noinline void operator()( const iRegister16& to, const ModSibBase& sibsrc ) const{ m_16::Emit( to, sibsrc ); }
__noinline void operator()( const ModSibStrict<2>& sibdest, u16 imm ) const { m_16::Emit( sibdest, imm ); }
- void operator()( const iRegister16& to, u16 imm, bool needs_flags=false ) const { m_16::Emit( to, imm ); }
+ void operator()( const iRegister16& to, u16 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 ); }
@@ -172,7 +167,7 @@ public:
__noinline void operator()( const iRegister8& to, const ModSibBase& sibsrc ) const{ m_8::Emit( to, sibsrc ); }
__noinline void operator()( const ModSibStrict<1>& sibdest, u8 imm ) const { m_8::Emit( sibdest, imm ); }
- void operator()( const iRegister8& to, u8 imm, bool needs_flags=false ) const { m_8::Emit( to, imm ); }
+ void operator()( const iRegister8& to, u8 imm ) const { m_8::Emit( to, imm ); }
Group1ImplAll() {} // Why does GCC need these?
};
diff --git a/pcsx2/x86/ix86/ix86_impl_group2.h b/pcsx2/x86/ix86/implement/group2.h
similarity index 97%
rename from pcsx2/x86/ix86/ix86_impl_group2.h
rename to pcsx2/x86/ix86/implement/group2.h
index dd551713d1..481e3b37d8 100644
--- a/pcsx2/x86/ix86/ix86_impl_group2.h
+++ b/pcsx2/x86/ix86/implement/group2.h
@@ -19,7 +19,6 @@
#pragma once
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
-
// Instructions implemented in this header are as follows -->>
enum G2Type
@@ -56,7 +55,7 @@ public:
{
prefix16();
iWrite( Is8BitOperand() ? 0xd2 : 0xd3 );
- ModRM( 3, InstType, to.Id );
+ ModRM_Direct( InstType, to.Id );
}
static __emitinline void Emit( const iRegister& to, u8 imm )
@@ -68,12 +67,12 @@ public:
{
// special encoding of 1's
iWrite( Is8BitOperand() ? 0xd0 : 0xd1 );
- ModRM( 3, InstType, to.Id );
+ ModRM_Direct( InstType, to.Id );
}
else
{
iWrite( Is8BitOperand() ? 0xc0 : 0xc1 );
- ModRM( 3, InstType, to.Id );
+ ModRM_Direct( InstType, to.Id );
iWrite( imm );
}
}
diff --git a/pcsx2/x86/ix86/implement/incdec.h b/pcsx2/x86/ix86/implement/incdec.h
new file mode 100644
index 0000000000..3a3f9690eb
--- /dev/null
+++ b/pcsx2/x86/ix86/implement/incdec.h
@@ -0,0 +1,22 @@
+/* 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: Increment and Decrement Instructions!
+// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
diff --git a/pcsx2/x86/ix86/ix86_impl_movs.h b/pcsx2/x86/ix86/implement/movs.h
similarity index 98%
rename from pcsx2/x86/ix86/ix86_impl_movs.h
rename to pcsx2/x86/ix86/implement/movs.h
index b9b67460b9..2ba18be506 100644
--- a/pcsx2/x86/ix86/ix86_impl_movs.h
+++ b/pcsx2/x86/ix86/implement/movs.h
@@ -44,8 +44,9 @@ public:
static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const iRegister& from )
{
+ if( to == from ) return;
emit_base( cc );
- ModRM( 3, to.Id, from.Id );
+ ModRM( ModRm_Direct, to.Id, from.Id );
}
static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const void* src )
@@ -123,7 +124,7 @@ public:
static __emitinline void Emit( const iRegister& to, const iRegister& from, bool SignExtend )
{
emit_base( SignExtend );
- ModRM( 3, from.Id, to.Id );
+ ModRM_Direct( to.Id, from.Id );
}
static __emitinline void Emit( const iRegister& to, const ModSibStrict& sibsrc, bool SignExtend )
diff --git a/pcsx2/x86/ix86/ix86.cpp b/pcsx2/x86/ix86/ix86.cpp
index ec41c81e50..7a1d4ec89a 100644
--- a/pcsx2/x86/ix86/ix86.cpp
+++ b/pcsx2/x86/ix86/ix86.cpp
@@ -128,6 +128,11 @@ namespace Internal
//x86Ptr++;
}
+ __forceinline void ModRM_Direct( uint reg, uint rm )
+ {
+ ModRM( Mod_Direct, reg, rm );
+ }
+
__forceinline void SibSB( u32 ss, u32 index, u32 base )
{
iWrite( (ss << 6) | (index << 3) | base );
@@ -679,7 +684,7 @@ static __forceinline void EmitMulDiv_OneRegForm( MulDivType InstType, const ModS
}
//////////////////////////////////////////////////////////////////////////////////////////
-// All ioMul forms are valid for 16 and 32 bit register operands only!
+// All iMul forms are valid for 16 and 32 bit register operands only!
template< typename ImmType >
class iMulImpl
@@ -752,12 +757,6 @@ public:
}
};
-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 ); }
@@ -773,22 +772,32 @@ __forceinline void iSDIV( const iRegister16& from ) { EmitMulDiv_OneRegForm( MD
__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& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
+__forceinline void iSMUL( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
+__forceinline void iSMUL( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
+__noinline void iSMUL( const ModSibSized& from ) { EmitMulDiv_OneRegForm( MDT_iMul, from ); }
+
+// ------------------------------------------------------------------------
+// iMUL's special forms (unique to iMUL alone)
+
+namespace Internal
+{
+ typedef iMulImpl iMUL32;
+ typedef iMulImpl iMUL16;
+}
+
__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 ); }
//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/pcsx2/x86/ix86/ix86_legacy.cpp b/pcsx2/x86/ix86/ix86_legacy.cpp
index 3f12a7f818..2fc12afd89 100644
--- a/pcsx2/x86/ix86/ix86_legacy.cpp
+++ b/pcsx2/x86/ix86/ix86_legacy.cpp
@@ -176,6 +176,31 @@ emitterT void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift )
iSHRD( iRegister32(to), iRegister32(from), shift );
}
+/* mul eax by r32 to edx:eax */
+emitterT void MUL32R( x86IntRegType from ) { iUMUL( iRegister32(from) ); }
+/* imul eax by r32 to edx:eax */
+emitterT void IMUL32R( x86IntRegType from ) { iSMUL( iRegister32(from) ); }
+/* mul eax by m32 to edx:eax */
+emitterT void MUL32M( u32 from ) { iUMUL( ptr32[from] ); }
+/* imul eax by m32 to edx:eax */
+emitterT void IMUL32M( u32 from ) { iSMUL( ptr32[from] ); }
+
+/* imul r32 by r32 to r32 */
+emitterT void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
+{
+ iSMUL( iRegister32(to), iRegister32(from) );
+}
+
+/* div eax by r32 to edx:eax */
+emitterT void DIV32R( x86IntRegType from ) { iUDIV( iRegister32(from) ); }
+/* idiv eax by r32 to edx:eax */
+emitterT void IDIV32R( x86IntRegType from ) { iSDIV( iRegister32(from) ); }
+/* div eax by m32 to edx:eax */
+emitterT void DIV32M( u32 from ) { iUDIV( ptr32[from] ); }
+/* idiv eax by m32 to edx:eax */
+emitterT void IDIV32M( u32 from ) { iSDIV( ptr32[from] ); }
+
+
emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
{
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] );
@@ -413,30 +438,6 @@ emitterT void DEC16M( u32 to )
write32( MEMADDR(to, 4) );
}
-/* mul eax by r32 to edx:eax */
-emitterT void MUL32R( x86IntRegType from ) { iUMUL( iRegister32(from) ); }
-/* imul eax by r32 to edx:eax */
-emitterT void IMUL32R( x86IntRegType from ) { iSMUL( iRegister32(from) ); }
-/* mul eax by m32 to edx:eax */
-emitterT void MUL32M( u32 from ) { iUMUL( ptr32[from] ); }
-/* imul eax by m32 to edx:eax */
-emitterT void IMUL32M( u32 from ) { iSMUL( ptr32[from] ); }
-
-/* imul r32 by r32 to r32 */
-emitterT void IMUL32RtoR( x86IntRegType to, x86IntRegType from )
-{
- iSMUL( iRegister32(to), iRegister32(from) );
-}
-
-/* div eax by r32 to edx:eax */
-emitterT void DIV32R( x86IntRegType from ) { iUDIV( iRegister32(from) ); }
-/* idiv eax by r32 to edx:eax */
-emitterT void IDIV32R( x86IntRegType from ) { iSDIV( iRegister32(from) ); }
-/* div eax by m32 to edx:eax */
-emitterT void DIV32M( u32 from ) { iUDIV( ptr32[from] ); }
-/* idiv eax by m32 to edx:eax */
-emitterT void IDIV32M( u32 from ) { iSDIV( ptr32[from] ); }
-
////////////////////////////////////
// logical instructions /
////////////////////////////////////
diff --git a/pcsx2/x86/ix86/ix86_types.h b/pcsx2/x86/ix86/ix86_types.h
index e2f3c16a1e..af473c5c8a 100644
--- a/pcsx2/x86/ix86/ix86_types.h
+++ b/pcsx2/x86/ix86/ix86_types.h
@@ -147,6 +147,15 @@ namespace x86Emitter
# define __noinline
#endif
+ // ModRM 'mod' field enumeration. Provided mostly for reference:
+ enum ModRm_ModField
+ {
+ Mod_NoDisp = 0, // effective address operation with no displacement, in the form of [reg] (or uses special Disp32-only encoding in the case of [ebp] form)
+ Mod_Disp8, // effective address operation with 8 bit displacement, in the form of [reg+disp8]
+ Mod_Disp32, // effective address operation with 32 bit displacement, in the form of [reg+disp32],
+ Mod_Direct, // direct reg/reg operation
+ };
+
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)
@@ -636,57 +645,17 @@ namespace x86Emitter
namespace Internal
{
extern void ModRM( uint mod, uint reg, uint rm );
+ extern void ModRM_Direct( uint reg, uint rm );
extern void SibSB( u32 ss, u32 index, u32 base );
extern void iWriteDisp( int regfield, s32 displacement );
extern void iWriteDisp( int regfield, const void* address );
extern void EmitSibMagic( uint regfield, const ModSibBase& info );
- #include "ix86_impl_group1.h"
- #include "ix86_impl_group2.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.
- // (returns FALSE if no optimization is performed)
- // [TODO] : Work-in-progress!
- //template< G1Type InstType, typename RegType >
- //static __forceinline void _optimize_imm0( RegType to );
-
- /*template< G1Type InstType, typename RegType >
- static __forceinline void _optimize_imm0( const RegType& to )
- {
- switch( InstType )
- {
- // ADD, SUB, and OR can be ignored if the imm is zero..
- case G1Type_ADD:
- case G1Type_SUB:
- case G1Type_OR:
- return true;
-
- // ADC and SBB can never be ignored (could have carry bits)
- // XOR behavior is distinct as well [or is it the same as NEG or NOT?]
- case G1Type_ADC:
- case G1Type_SBB:
- case G1Type_XOR:
- return false;
-
- // replace AND with XOR (or SUB works too.. whatever!)
- case G1Type_AND:
- iXOR( to, to );
- return true;
-
- // replace CMP with OR reg,reg:
- case G1Type_CMP:
- iOR( to, to );
- return true;
-
- jNO_DEFAULT
- }
- return false;
- }*/
-
+ #include "implement/group1.h"
+ #include "implement/group2.h"
+ #include "implement/movs.h" // cmov and movsx/zx
+ #include "implement/dwshift.h" // dowubleword shifts!
}
// ------------------------------------------------------------------------