diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
index 7f961b7061..51852e0cdc 100644
--- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
+++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj
@@ -2977,10 +2977,6 @@
RelativePath="..\..\x86\ix86\ix86_types.h"
>
-
-
@@ -2996,10 +2992,18 @@
RelativePath="..\..\x86\ix86\implement\group2.h"
>
+
+
+
+
-class DwordShiftImpl
+class DwordShiftImpl : public ImplementationHelper< ImmType >
{
-public:
- static const uint OperandSize = sizeof(ImmType);
-
- DwordShiftImpl() {} // because GCC doesn't like static classes
-
protected:
- static bool Is8BitOperand() { return OperandSize == 1; }
- static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); }
static void basesibform( bool isCL )
{
prefix16();
@@ -44,15 +37,17 @@ protected:
write8( (isCL ? 0xa5 : 0xa4) | (isShiftRight ? 0x8 : 0) );
}
-public:
- static __emitinline void Emit( const iRegister& to, const iRegister& from )
+public:
+ DwordShiftImpl() {} // because GCC doesn't like static classes
+
+ static __emitinline void Emit( const iRegister& to, const iRegister& from )
{
prefix16();
write16( 0xa50f | (isShiftRight ? 0x800 : 0) );
ModRM_Direct( from.Id, to.Id );
}
- static __emitinline void Emit( const iRegister& to, const iRegister& from, u8 imm )
+ static __emitinline void Emit( const iRegister& to, const iRegister& from, u8 imm )
{
if( imm == 0 ) return;
prefix16();
@@ -61,13 +56,13 @@ public:
write8( imm );
}
- static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from, __unused const iRegisterCL& clreg )
+ static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from, __unused const iRegisterCL& clreg )
{
basesibform();
EmitSibMagic( from.Id, sibdest );
}
- static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from, u8 imm )
+ static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from, u8 imm )
{
basesibform();
EmitSibMagic( from.Id, sibdest );
@@ -75,14 +70,14 @@ public:
}
// dest data type is inferred from the 'from' register, so we can do void* resolution :)
- static __emitinline void Emit( void* dest, const iRegister& from, __unused const iRegisterCL& clreg )
+ static __emitinline void Emit( void* dest, const iRegister& from, __unused const iRegisterCL& clreg )
{
basesibform();
iWriteDisp( from.Id, dest );
}
// dest data type is inferred from the 'from' register, so we can do void* resolution :)
- static __emitinline void Emit( void* dest, const iRegister& from, u8 imm )
+ static __emitinline void Emit( void* dest, const iRegister& from, u8 imm )
{
basesibform();
iWriteDisp( from.Id, dest );
@@ -92,6 +87,8 @@ public:
// -------------------------------------------------------------------
+// I use explicit method declarations here instead of templates, in order to provide
+// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in SHLD/SHRD).
//
template< bool isShiftRight >
class DwordShiftImplAll
@@ -100,8 +97,6 @@ protected:
typedef DwordShiftImpl m_32;
typedef DwordShiftImpl m_16;
- // (Note: I'm not going to macro this since it would likely clobber intellisense parameter resolution)
-
public:
// ---------- 32 Bit Interface -----------
__forceinline void operator()( const iRegister32& to, const iRegister32& from, __unused const iRegisterCL& clreg ) const { m_32::Emit( to, from ); }
diff --git a/pcsx2/x86/ix86/implement/group1.h b/pcsx2/x86/ix86/implement/group1.h
index c9b313cb85..2837960f73 100644
--- a/pcsx2/x86/ix86/implement/group1.h
+++ b/pcsx2/x86/ix86/implement/group1.h
@@ -34,55 +34,48 @@ enum G1Type
};
// -------------------------------------------------------------------
-template< typename ImmType, G1Type InstType >
-class Group1Impl
+template< G1Type InstType, typename ImmType >
+class Group1Impl : public ImplementationHelper< ImmType >
{
public:
- static const uint OperandSize = sizeof(ImmType);
-
Group1Impl() {} // because GCC doesn't like static classes
-protected:
- static bool Is8BitOperand() { return OperandSize == 1; }
- static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); }
-
-public:
- static __emitinline void Emit( const iRegister& to, const iRegister& from )
+ static __emitinline void Emit( const iRegister& to, const iRegister& from )
{
prefix16();
iWrite( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
ModRM_Direct( from.Id, to.Id );
}
- static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from )
+ static __emitinline void Emit( const ModSibBase& sibdest, const iRegister& from )
{
prefix16();
iWrite( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
EmitSibMagic( from.Id, sibdest );
}
- static __emitinline void Emit( const iRegister& to, const ModSibBase& sibsrc )
+ static __emitinline void Emit( const iRegister& to, const ModSibBase& sibsrc )
{
prefix16();
iWrite( (Is8BitOperand() ? 2 : 3) | (InstType<<3) );
EmitSibMagic( to.Id, sibsrc );
}
- static __emitinline void Emit( void* dest, const iRegister& from )
+ static __emitinline void Emit( void* dest, const iRegister& from )
{
prefix16();
iWrite( (Is8BitOperand() ? 0 : 1) | (InstType<<3) );
iWriteDisp( from.Id, dest );
}
- static __emitinline void Emit( const iRegister& to, const void* src )
+ static __emitinline void Emit( const iRegister& to, const void* src )
{
prefix16();
iWrite( (Is8BitOperand() ? 2 : 3) | (InstType<<3) );
iWriteDisp( to.Id, src );
}
- static __emitinline void Emit( const iRegister& to, ImmType imm )
+ static __emitinline void Emit( const iRegister& to, int imm )
{
prefix16();
if( !Is8BitOperand() && is_s8( imm ) )
@@ -104,7 +97,7 @@ public:
}
}
- static __emitinline void Emit( const ModSibStrict& sibdest, ImmType imm )
+ static __emitinline void Emit( const ModSibStrict& sibdest, int imm )
{
if( Is8BitOperand() )
{
@@ -131,43 +124,27 @@ public:
template< G1Type InstType >
class Group1ImplAll
{
-protected:
- typedef Group1Impl m_32;
- typedef Group1Impl m_16;
- typedef Group1Impl m_8;
-
- // (Note: I'm not going to macro this since it would likely clobber intellisense parameter resolution)
-
public:
- // ---------- 32 Bit Interface -----------
- __forceinline void operator()( const iRegister32& to, const iRegister32& from ) const { m_32::Emit( to, from ); }
- __forceinline void operator()( const iRegister32& to, const void* src ) const { m_32::Emit( to, src ); }
- __forceinline void operator()( void* dest, const iRegister32& from ) const { m_32::Emit( dest, from ); }
- __noinline void operator()( const ModSibBase& sibdest, const iRegister32& from ) const { m_32::Emit( sibdest, from ); }
- __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 ); }
+ template< typename T >
+ __forceinline void operator()( const iRegister& to, const iRegister& from ) const { Group1Impl::Emit( to, from ); }
+ template< typename T >
+ __forceinline void operator()( const iRegister& to, const void* src ) const { Group1Impl::Emit( to, src ); }
+ template< typename T >
+ __forceinline void operator()( void* dest, const iRegister& from ) const { Group1Impl::Emit( dest, from ); }
+ template< typename T >
+ __noinline void operator()( const ModSibBase& sibdest, const iRegister& from ) const { Group1Impl::Emit( sibdest, from ); }
+ template< typename T >
+ __noinline void operator()( const iRegister& to, const ModSibBase& sibsrc ) const { Group1Impl::Emit( to, sibsrc ); }
- void operator()( const iRegister32& to, u32 imm ) const { m_32::Emit( to, imm ); }
+ // 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).
+
+ template< typename T >
+ __noinline void operator()( const ModSibStrict& sibdest, int imm ) const { Group1Impl::Emit( sibdest, imm ); }
+ template< typename T >
+ void operator()( const iRegister& to, int imm ) const { Group1Impl::Emit( to, imm ); }
- // ---------- 16 Bit Interface -----------
- __forceinline void operator()( const iRegister16& to, const iRegister16& from ) const { m_16::Emit( to, from ); }
- __forceinline void operator()( const iRegister16& to, const void* src ) const { m_16::Emit( to, src ); }
- __forceinline void operator()( void* dest, const iRegister16& from ) const { m_16::Emit( dest, from ); }
- __noinline void operator()( const ModSibBase& sibdest, const iRegister16& from ) const { m_16::Emit( sibdest, from ); }
- __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 ) const { m_16::Emit( to, imm ); }
-
- // ---------- 8 Bit Interface -----------
- __forceinline void operator()( const iRegister8& to, const iRegister8& from ) const { m_8::Emit( to, from ); }
- __forceinline void operator()( const iRegister8& to, const void* src ) const { m_8::Emit( to, src ); }
- __forceinline void operator()( void* dest, const iRegister8& from ) const { m_8::Emit( dest, from ); }
- __noinline void operator()( const ModSibBase& sibdest, const iRegister8& from ) const { m_8::Emit( sibdest, from ); }
- __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 ) const { m_8::Emit( to, imm ); }
Group1ImplAll() {} // Why does GCC need these?
};
diff --git a/pcsx2/x86/ix86/implement/group2.h b/pcsx2/x86/ix86/implement/group2.h
index 481e3b37d8..74979f8c91 100644
--- a/pcsx2/x86/ix86/implement/group2.h
+++ b/pcsx2/x86/ix86/implement/group2.h
@@ -38,27 +38,20 @@ enum G2Type
// Optimization Note: For Imm forms, we ignore the instruction if the shift count is zero.
// This is a safe optimization since any zero-value shift does not affect any flags.
//
-template< typename ImmType, G2Type InstType >
-class Group2Impl
+template< G2Type InstType, typename ImmType >
+class Group2Impl : public ImplementationHelper< ImmType >
{
public:
- static const uint OperandSize = sizeof(ImmType);
-
Group2Impl() {} // For the love of GCC.
-protected:
- static bool Is8BitOperand() { return OperandSize == 1; }
- static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); }
-
-public:
- static __emitinline void Emit( const iRegister& to )
+ static __emitinline void Emit( const iRegister& to )
{
prefix16();
iWrite( Is8BitOperand() ? 0xd2 : 0xd3 );
ModRM_Direct( InstType, to.Id );
}
- static __emitinline void Emit( const iRegister& to, u8 imm )
+ static __emitinline void Emit( const iRegister& to, u8 imm )
{
if( imm == 0 ) return;
@@ -77,14 +70,14 @@ public:
}
}
- static __emitinline void Emit( const ModSibStrict& sibdest )
+ static __emitinline void Emit( const ModSibStrict& sibdest )
{
prefix16();
iWrite( Is8BitOperand() ? 0xd2 : 0xd3 );
EmitSibMagic( InstType, sibdest );
}
- static __emitinline void Emit( const ModSibStrict& sibdest, u8 imm )
+ static __emitinline void Emit( const ModSibStrict& sibdest, u8 imm )
{
if( imm == 0 ) return;
@@ -109,11 +102,6 @@ public:
template< G2Type InstType >
class Group2ImplAll
{
-protected:
- typedef Group2Impl m_32;
- typedef Group2Impl m_16;
- typedef Group2Impl m_8;
-
// Inlining Notes:
// I've set up the inlining to be as practical and intelligent as possible, which means
// forcing inlining for (void*) forms of ModRM, which thanks to constprop reduce to
@@ -125,22 +113,17 @@ protected:
public:
// ---------- 32 Bit Interface -----------
- __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 ); }
+ template< typename T > __forceinline void operator()( const iRegister& to, __unused const iRegisterCL& from ) const
+ { Group2Impl::Emit( to ); }
- // ---------- 16 Bit Interface -----------
- __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 ); }
+ template< typename T > __noinline void operator()( const ModSibStrict& sibdest, __unused const iRegisterCL& from ) const
+ { Group2Impl::Emit( sibdest ); }
- // ---------- 8 Bit Interface -----------
- __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 ); }
+ template< typename T > __noinline void operator()( const ModSibStrict& sibdest, u8 imm ) const
+ { Group2Impl::Emit( sibdest, imm ); }
+
+ template< typename T > void operator()( const iRegister& to, u8 imm ) const
+ { Group2Impl::Emit( to, imm ); }
Group2ImplAll() {} // I am a class with no members, so I need an explicit constructor! Sense abounds.
};
diff --git a/pcsx2/x86/ix86/implement/group3.h b/pcsx2/x86/ix86/implement/group3.h
new file mode 100644
index 0000000000..9cf60b2256
--- /dev/null
+++ b/pcsx2/x86/ix86/implement/group3.h
@@ -0,0 +1,66 @@
+/* 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
+
+// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
+// Instructions implemented in this header are as follows -->>
+
+enum G3Type
+{
+ G3Type_NOT = 2,
+ G3Type_NEG = 3,
+ G3Type_MUL = 4,
+ G3Type_iMUL = 5, // partial implementation, iMul has additional forms in ix86.cpp
+ G3Type_DIV = 6,
+ G3Type_iDIV = 7
+};
+
+template< typename ImmType >
+class Group3Impl : public ImplementationHelper
+{
+public:
+ Group3Impl() {} // For the love of GCC.
+
+ static __emitinline void Emit( G3Type InstType, const iRegister& from )
+ {
+ prefix16();
+ iWrite( Is8BitOperand() ? 0xf6 : 0xf7 );
+ ModRM_Direct( InstType, from.Id );
+ }
+
+ static __emitinline void Emit( G3Type InstType, const ModSibStrict& sibsrc )
+ {
+ prefix16();
+ iWrite( Is8BitOperand() ? 0xf6 : 0xf7 );
+ EmitSibMagic( InstType, sibsrc );
+ }
+};
+
+// -------------------------------------------------------------------
+//
+template< G3Type InstType >
+class Group3ImplAll
+{
+public:
+ template< typename T >
+ __forceinline void operator()( const iRegister& from ) const { Group3Impl::Emit( InstType, from ); }
+
+ template< typename T >
+ __noinline void operator()( const ModSibStrict& from ) const { Group3Impl::Emit( InstType, from ); }
+};
\ No newline at end of file
diff --git a/pcsx2/x86/ix86/implement/incdec.h b/pcsx2/x86/ix86/implement/incdec.h
index 3a3f9690eb..0cf5a08c62 100644
--- a/pcsx2/x86/ix86/implement/incdec.h
+++ b/pcsx2/x86/ix86/implement/incdec.h
@@ -20,3 +20,54 @@
// Implementations found here: Increment and Decrement Instructions!
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
+
+template< typename ImmType >
+class IncDecImpl : public ImplementationHelper
+{
+public:
+ IncDecImpl() {} // For the love of GCC.
+
+ static __emitinline void Emit( bool isDec, const iRegister& to )
+ {
+ // There is no valid 8-bit form of direct register inc/dec, so fall
+ // back on Mod/RM format instead:
+ if( Is8BitOperand() )
+ {
+ write8( 0xfe );
+ ModRM_Direct( isDec ? 1 : 0, to.Id );
+ }
+ else
+ {
+ prefix16();
+ write8( (isDec ? 0x48 : 0x40) | to.Id );
+ }
+ }
+
+ static __emitinline void Emit( bool isDec, const ModSibStrict& dest )
+ {
+ write8( Is8BitOperand() ? 0xfe : 0xff );
+ EmitSibMagic( isDec ? 1: 0, dest );
+ }
+};
+
+// ------------------------------------------------------------------------
+template< bool isDec >
+class IncDecImplAll
+{
+protected:
+ typedef IncDecImpl m_32;
+ typedef IncDecImpl m_16;
+ typedef IncDecImpl m_8;
+
+public:
+ __forceinline void operator()( const iRegister32& to ) const { m_32::Emit( isDec, to ); }
+ __noinline void operator()( const ModSibStrict& sibdest ) const { m_32::Emit( isDec, sibdest ); }
+
+ __forceinline void operator()( const iRegister16& to ) const { m_16::Emit( isDec, to ); }
+ __noinline void operator()( const ModSibStrict& sibdest ) const { m_16::Emit( isDec, sibdest ); }
+
+ __forceinline void operator()( const iRegister8& to ) const { m_8::Emit( isDec, to ); }
+ __noinline void operator()( const ModSibStrict& sibdest ) const { m_8::Emit( isDec, sibdest ); }
+
+ IncDecImplAll() {} // don't ask.
+};
diff --git a/pcsx2/x86/ix86/implement/movs.h b/pcsx2/x86/ix86/implement/movs.h
index 2ba18be506..2899659930 100644
--- a/pcsx2/x86/ix86/implement/movs.h
+++ b/pcsx2/x86/ix86/implement/movs.h
@@ -21,11 +21,164 @@
// Header: ix86_impl_movs.h -- covers cmov and movsx/movzx.
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
+//////////////////////////////////////////////////////////////////////////////////////////
+// MOV instruction Implementation
+
+template< typename ImmType >
+class MovImpl : ImplementationHelper< ImmType >
+{
+public:
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const iRegister& from )
+ {
+ if( to == from ) return; // ignore redundant MOVs.
+
+ prefix16();
+ iWrite( Is8BitOperand() ? 0x88 : 0x89 );
+ ModRM( 3, from.Id, to.Id );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const ModSibBase& dest, const iRegister& from )
+ {
+ prefix16();
+
+ // mov eax has a special from when writing directly to a DISP32 address
+ // (sans any register index/base registers).
+
+ if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() )
+ {
+ iWrite( Is8BitOperand() ? 0xa2 : 0xa3 );
+ iWrite( dest.Displacement );
+ }
+ else
+ {
+ iWrite( Is8BitOperand() ? 0x88 : 0x89 );
+ EmitSibMagic( from.Id, dest );
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const ModSibBase& src )
+ {
+ prefix16();
+
+ // mov eax has a special from when reading directly from a DISP32 address
+ // (sans any register index/base registers).
+
+ if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() )
+ {
+ iWrite( Is8BitOperand() ? 0xa0 : 0xa1 );
+ iWrite( src.Displacement );
+ }
+ else
+ {
+ iWrite( Is8BitOperand() ? 0x8a : 0x8b );
+ EmitSibMagic( to.Id, src );
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( void* dest, const iRegister& from )
+ {
+ prefix16();
+
+ // mov eax has a special from when writing directly to a DISP32 address
+
+ if( from.IsAccumulator() )
+ {
+ iWrite( Is8BitOperand() ? 0xa2 : 0xa3 );
+ iWrite( (s32)dest );
+ }
+ else
+ {
+ iWrite( Is8BitOperand() ? 0x88 : 0x89 );
+ iWriteDisp( from.Id, dest );
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, const void* src )
+ {
+ prefix16();
+
+ // mov eax has a special from when reading directly from a DISP32 address
+
+ if( to.IsAccumulator() )
+ {
+ iWrite( Is8BitOperand() ? 0xa0 : 0xa1 );
+ iWrite( (s32)src );
+ }
+ else
+ {
+ iWrite( Is8BitOperand() ? 0x8a : 0x8b );
+ iWriteDisp( to.Id, src );
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( const iRegister& to, ImmType imm )
+ {
+ // Note: MOV does not have (reg16/32,imm8) forms.
+
+ prefix16();
+ iWrite( (Is8BitOperand() ? 0xb0 : 0xb8) | to.Id );
+ iWrite( imm );
+ }
+
+ // ------------------------------------------------------------------------
+ static __forceinline void Emit( ModSibStrict dest, ImmType imm )
+ {
+ prefix16();
+ iWrite( Is8BitOperand() ? 0xc6 : 0xc7 );
+ EmitSibMagic( 0, dest );
+ iWrite( imm );
+ }
+};
+
+// Inlining Notes:
+// I've set up the inlining to be as practical and intelligent as possible, which means
+// forcing inlining for (void*) forms of ModRM, which thanks to constprop reduce to
+// virtually no code. In the case of (Reg, Imm) forms, the inlinign is up to the dis-
+// cretion of the compiler.
+//
+
+class MovImplAll
+{
+public:
+ template< typename T>
+ __forceinline void operator()( const iRegister& to, const iRegister& from ) const { MovImpl::Emit( to, from ); }
+ template< typename T>
+ __forceinline void operator()( const iRegister& to, const void* src ) const { MovImpl::Emit( to, src ); }
+ template< typename T>
+ __forceinline void operator()( void* dest, const iRegister& from ) const { MovImpl::Emit( dest, from ); }
+ template< typename T>
+ __noinline void operator()( const ModSibBase& sibdest, const iRegister& from ) const { MovImpl::Emit( sibdest, from ); }
+ template< typename T>
+ __noinline void operator()( const iRegister& to, const ModSibBase& sibsrc ) const { MovImpl::Emit( to, sibsrc ); }
+
+ template< typename T>
+ __noinline void operator()( const ModSibStrict& sibdest, int imm ) const { MovImpl::Emit( sibdest, imm ); }
+
+ // preserve_flags - set to true to disable optimizations which could alter the state of
+ // the flags (namely replacing mov reg,0 with xor).
+
+ template< typename T >
+ __emitinline void operator()( const iRegister& to, int imm, bool preserve_flags=false ) const
+ {
+ if( !preserve_flags && (imm == 0) )
+ iXOR( to, to );
+ else
+ MovImpl::Emit( to, imm );
+ }
+};
+
+
//////////////////////////////////////////////////////////////////////////////////////////
// CMOV !! [in all of it's disappointing lack-of glory]
//
-template< int OperandSize >
-class CMovImpl
+template< typename ImmType >
+class CMovImpl : public ImplementationHelper< ImmType >
{
protected:
static bool Is8BitOperand() { return OperandSize == 1; }
@@ -42,20 +195,20 @@ protected:
public:
CMovImpl() {}
- static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const iRegister& from )
+ static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const iRegister& from )
{
if( to == from ) return;
emit_base( cc );
- ModRM( ModRm_Direct, to.Id, from.Id );
+ ModRM_Direct( to.Id, from.Id );
}
- static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const void* src )
+ static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const void* src )
{
emit_base( cc );
iWriteDisp( to.Id, src );
}
- static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const ModSibBase& sibsrc )
+ static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const ModSibBase& sibsrc )
{
emit_base( cc );
EmitSibMagic( to.Id, sibsrc );
@@ -64,11 +217,14 @@ public:
};
// ------------------------------------------------------------------------
+// I use explicit method declarations here instead of templates, in order to provide
+// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in CMOV).
+//
class CMovImplGeneric
{
protected:
- typedef CMovImpl<4> m_32;
- typedef CMovImpl<2> m_16;
+ typedef CMovImpl m_32;
+ typedef CMovImpl m_16;
public:
__forceinline void operator()( JccComparisonType ccType, const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); }
@@ -87,8 +243,8 @@ template< JccComparisonType ccType >
class CMovImplAll
{
protected:
- typedef CMovImpl<4> m_32;
- typedef CMovImpl<2> m_16;
+ typedef CMovImpl m_32;
+ typedef CMovImpl m_16;
public:
__forceinline void operator()( const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); }
@@ -105,10 +261,13 @@ public:
//////////////////////////////////////////////////////////////////////////////////////////
// Mov with sign/zero extension implementations (movsx / movzx)
//
-template< int DestOperandSize, int SrcOperandSize >
+template< typename DestImmType, typename SrcImmType >
class MovExtendImpl
{
protected:
+ static const uint DestOperandSize = sizeof( DestImmType );
+ static const uint SrcOperandSize = sizeof( SrcImmType );
+
static bool Is8BitOperand() { return SrcOperandSize == 1; }
static void prefix16() { if( DestOperandSize == 2 ) iWrite( 0x66 ); }
static __forceinline void emit_base( bool SignExtend )
@@ -121,13 +280,13 @@ protected:
public:
MovExtendImpl() {} // For the love of GCC.
- static __emitinline void Emit( const iRegister& to, const iRegister& from, bool SignExtend )
+ static __emitinline void Emit( const iRegister& to, const iRegister& from, bool SignExtend )
{
emit_base( SignExtend );
ModRM_Direct( to.Id, from.Id );
}
- static __emitinline void Emit( const iRegister& to, const ModSibStrict& sibsrc, bool SignExtend )
+ static __emitinline void Emit( const iRegister& to, const ModSibStrict& sibsrc, bool SignExtend )
{
emit_base( SignExtend );
EmitSibMagic( to.Id, sibsrc );
@@ -139,19 +298,19 @@ template< bool SignExtend >
class MovExtendImplAll
{
protected:
- typedef MovExtendImpl<4, 2> m_16to32;
- typedef MovExtendImpl<4, 1> m_8to32;
- typedef MovExtendImpl<2, 1> m_8to16;
+ typedef MovExtendImpl m_16to32;
+ typedef MovExtendImpl m_8to32;
+ typedef MovExtendImpl m_8to16;
public:
__forceinline void operator()( const iRegister32& to, const iRegister16& from ) const { m_16to32::Emit( to, from, SignExtend ); }
- __noinline void operator()( const iRegister32& to, const ModSibStrict<2>& sibsrc ) const { m_16to32::Emit( to, sibsrc, SignExtend ); }
+ __noinline void operator()( const iRegister32& to, const ModSibStrict& sibsrc ) const { m_16to32::Emit( to, sibsrc, SignExtend ); }
__forceinline void operator()( const iRegister32& to, const iRegister8& from ) const { m_8to32::Emit( to, from, SignExtend ); }
- __noinline void operator()( const iRegister32& to, const ModSibStrict<1>& sibsrc ) const { m_8to32::Emit( to, sibsrc, SignExtend ); }
+ __noinline void operator()( const iRegister32& to, const ModSibStrict& sibsrc ) const { m_8to32::Emit( to, sibsrc, SignExtend ); }
__forceinline void operator()( const iRegister16& to, const iRegister8& from ) const { m_8to16::Emit( to, from, SignExtend ); }
- __noinline void operator()( const iRegister16& to, const ModSibStrict<1>& sibsrc ) const { m_8to16::Emit( to, sibsrc, SignExtend ); }
+ __noinline void operator()( const iRegister16& to, const ModSibStrict& sibsrc ) const { m_8to16::Emit( to, sibsrc, SignExtend ); }
MovExtendImplAll() {} // don't ask.
};
diff --git a/pcsx2/x86/ix86/ix86.cpp b/pcsx2/x86/ix86/ix86.cpp
index 7a1d4ec89a..11020fa647 100644
--- a/pcsx2/x86/ix86/ix86.cpp
+++ b/pcsx2/x86/ix86/ix86.cpp
@@ -67,13 +67,13 @@ __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM] = { XMMT_INT };
namespace x86Emitter {
const x86IndexerType ptr;
-const x86IndexerTypeExplicit<4> ptr32;
-const x86IndexerTypeExplicit<2> ptr16;
-const x86IndexerTypeExplicit<1> ptr8;
+const x86IndexerTypeExplicit ptr32;
+const x86IndexerTypeExplicit ptr16;
+const x86IndexerTypeExplicit ptr8;
// ------------------------------------------------------------------------
-template< int OperandSize > const iRegister iRegister::Empty;
+template< typename OperandType > const iRegister iRegister::Empty;
const x86IndexReg x86IndexReg::Empty;
const iRegister32
@@ -240,6 +240,8 @@ namespace Internal
using namespace Internal;
+const MovImplAll iMOV;
+
const Group1ImplAll iADD;
const Group1ImplAll iOR;
const Group1ImplAll iADC;
@@ -257,6 +259,15 @@ const Group2ImplAll iSHL;
const Group2ImplAll iSHR;
const Group2ImplAll iSAR;
+const Group3ImplAll iNOT;
+const Group3ImplAll iNEG;
+const Group3ImplAll iUMUL;
+const Group3ImplAll iUDIV;
+const Group3ImplAll iSDIV;
+
+const IncDecImplAll iINC;
+const IncDecImplAll iDEC;
+
const MovExtendImplAll iMOVZX;
const MovExtendImplAll iMOVSX;
@@ -336,9 +347,11 @@ __emitinline void iAdvancePtr( uint bytes )
// preserve_flags - set to ture to disable use of SHL on [Index*Base] forms
// of LEA, which alters flags states.
//
-template< typename ToReg >
-static void EmitLeaMagic( ToReg to, const ModSibBase& src, bool preserve_flags )
+template< typename OperandType >
+static void EmitLeaMagic( iRegister to, const ModSibBase& src, bool preserve_flags )
{
+ typedef iRegister ToReg;
+
int displacement_size = (src.Displacement == 0) ? 0 :
( ( src.IsByteSizeDisp() ) ? 1 : 2 );
@@ -465,226 +478,7 @@ __emitinline void iLEA( iRegister16 to, const ModSibBase& src, bool preserve_fla
}
//////////////////////////////////////////////////////////////////////////////////////////
-// MOV instruction Implementation
-
-template< typename ImmType >
-class MovImpl
-{
-public:
- static const uint OperandSize = sizeof(ImmType);
-
-protected:
- static bool Is8BitOperand() { return OperandSize == 1; }
- static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); }
-
-public:
- // ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const iRegister& from )
- {
- if( to == from ) return; // ignore redundant MOVs.
-
- prefix16();
- iWrite( Is8BitOperand() ? 0x88 : 0x89 );
- ModRM( 3, from.Id, to.Id );
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( const ModSibBase& dest, const iRegister& from )
- {
- prefix16();
-
- // mov eax has a special from when writing directly to a DISP32 address
- // (sans any register index/base registers).
-
- if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() )
- {
- iWrite( Is8BitOperand() ? 0xa2 : 0xa3 );
- iWrite( dest.Displacement );
- }
- else
- {
- iWrite( Is8BitOperand() ? 0x88 : 0x89 );
- EmitSibMagic( from.Id, dest );
- }
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const ModSibBase& src )
- {
- prefix16();
-
- // mov eax has a special from when reading directly from a DISP32 address
- // (sans any register index/base registers).
-
- if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() )
- {
- iWrite( Is8BitOperand() ? 0xa0 : 0xa1 );
- iWrite( src.Displacement );
- }
- else
- {
- iWrite( Is8BitOperand() ? 0x8a : 0x8b );
- EmitSibMagic( to.Id, src );
- }
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( void* dest, const iRegister& from )
- {
- prefix16();
-
- // mov eax has a special from when writing directly to a DISP32 address
-
- if( from.IsAccumulator() )
- {
- iWrite( Is8BitOperand() ? 0xa2 : 0xa3 );
- iWrite( (s32)dest );
- }
- else
- {
- iWrite( Is8BitOperand() ? 0x88 : 0x89 );
- iWriteDisp( from.Id, dest );
- }
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const void* src )
- {
- prefix16();
-
- // mov eax has a special from when reading directly from a DISP32 address
-
- if( to.IsAccumulator() )
- {
- iWrite( Is8BitOperand() ? 0xa0 : 0xa1 );
- iWrite( (s32)src );
- }
- else
- {
- iWrite( Is8BitOperand() ? 0x8a : 0x8b );
- iWriteDisp( to.Id, src );
- }
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, ImmType imm )
- {
- // Note: MOV does not have (reg16/32,imm8) forms.
-
- prefix16();
- iWrite( (Is8BitOperand() ? 0xb0 : 0xb8) | to.Id );
- iWrite( imm );
- }
-
- // ------------------------------------------------------------------------
- static __forceinline void Emit( ModSibStrict dest, ImmType imm )
- {
- prefix16();
- iWrite( Is8BitOperand() ? 0xc6 : 0xc7 );
- EmitSibMagic( 0, dest );
- iWrite( imm );
- }
-};
-
-namespace Internal
-{
- typedef MovImpl MOV32;
- typedef MovImpl MOV16;
- typedef MovImpl MOV8;
-}
-
-// Inlining Notes:
-// I've set up the inlining to be as practical and intelligent as possible, which means
-// forcing inlining for (void*) forms of ModRM, which thanks to constprop reduce to
-// virtually no code. In the case of (Reg, Imm) forms, the inlinign is up to the dis-
-// cretion of the compiler.
-//
-
-// TODO : Turn this into a macro after it's been debugged and accuracy-approved! :D
-
-// ---------- 32 Bit Interface -----------
-__forceinline void iMOV( const iRegister32& to, const iRegister32& from ) { MOV32::Emit( to, from ); }
-__forceinline void iMOV( const iRegister32& to, const void* src ) { MOV32::Emit( to, ptr32[src] ); }
-__forceinline void iMOV( void* dest, const iRegister32& from ) { MOV32::Emit( ptr32[dest], from ); }
-__noinline void iMOV( const ModSibBase& sibdest, const iRegister32& from ) { MOV32::Emit( sibdest, from ); }
-__noinline void iMOV( const iRegister32& to, const ModSibBase& sibsrc ) { MOV32::Emit( to, sibsrc ); }
-__noinline void iMOV( const ModSibStrict<4>& sibdest,u32 imm ) { MOV32::Emit( sibdest, imm ); }
-
-void iMOV( const iRegister32& to, u32 imm, bool preserve_flags )
-{
- if( !preserve_flags && (imm == 0) )
- iXOR( to, to );
- else
- MOV32::Emit( to, imm );
-}
-
-
-// ---------- 16 Bit Interface -----------
-__forceinline void iMOV( const iRegister16& to, const iRegister16& from ) { MOV16::Emit( to, from ); }
-__forceinline void iMOV( const iRegister16& to, const void* src ) { MOV16::Emit( to, ptr16[src] ); }
-__forceinline void iMOV( void* dest, const iRegister16& from ) { MOV16::Emit( ptr16[dest], from ); }
-__noinline void iMOV( const ModSibBase& sibdest, const iRegister16& from ) { MOV16::Emit( sibdest, from ); }
-__noinline void iMOV( const iRegister16& to, const ModSibBase& sibsrc ) { MOV16::Emit( to, sibsrc ); }
-__noinline void iMOV( const ModSibStrict<2>& sibdest,u16 imm ) { MOV16::Emit( sibdest, imm ); }
-
-void iMOV( const iRegister16& to, u16 imm, bool preserve_flags )
-{
- if( !preserve_flags && (imm == 0) )
- iXOR( to, to );
- else
- MOV16::Emit( to, imm );
-}
-
-// ---------- 8 Bit Interface -----------
-__forceinline void iMOV( const iRegister8& to, const iRegister8& from ) { MOV8::Emit( to, from ); }
-__forceinline void iMOV( const iRegister8& to, const void* src ) { MOV8::Emit( to, ptr8[src] ); }
-__forceinline void iMOV( void* dest, const iRegister8& from ) { MOV8::Emit( ptr8[dest], from ); }
-__noinline void iMOV( const ModSibBase& sibdest, const iRegister8& from ) { MOV8::Emit( sibdest, from ); }
-__noinline void iMOV( const iRegister8& to, const ModSibBase& sibsrc ) { MOV8::Emit( to, sibsrc ); }
-__noinline void iMOV( const ModSibStrict<1>& sibdest,u8 imm ) { MOV8::Emit( sibdest, imm ); }
-
-void iMOV( const iRegister8& to, u8 imm, bool preserve_flags )
-{
- if( !preserve_flags && (imm == 0) )
- iXOR( to, to );
- else
- 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 iMul forms are valid for 16 and 32 bit register operands only!
+// The following iMul-specific forms are valid for 16 and 32 bit register operands only!
template< typename ImmType >
class iMulImpl
@@ -697,15 +491,15 @@ protected:
public:
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const iRegister& from )
+ static __emitinline void Emit( const iRegister& to, const iRegister& from )
{
prefix16();
write16( 0xaf0f );
- ModRM( ModRm_Direct, to.Id, from.Id );
+ ModRM_Direct( to.Id, from.Id );
}
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const void* src )
+ static __emitinline void Emit( const iRegister& to, const void* src )
{
prefix16();
write16( 0xaf0f );
@@ -713,7 +507,7 @@ public:
}
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const ModSibBase& src )
+ static __emitinline void Emit( const iRegister& to, const ModSibBase& src )
{
prefix16();
write16( 0xaf0f );
@@ -721,11 +515,11 @@ public:
}
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const iRegister& from, ImmType imm )
+ static __emitinline void Emit( const iRegister& to, const iRegister& from, ImmType imm )
{
prefix16();
write16( is_s8( imm ) ? 0x6b : 0x69 );
- ModRM( ModRm_Direct, to.Id, from.Id );
+ ModRM_Direct( to.Id, from.Id );
if( is_s8( imm ) )
write8( imm );
else
@@ -733,7 +527,7 @@ public:
}
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const void* src, ImmType imm )
+ static __emitinline void Emit( const iRegister& to, const void* src, ImmType imm )
{
prefix16();
write16( is_s8( imm ) ? 0x6b : 0x69 );
@@ -745,7 +539,7 @@ public:
}
// ------------------------------------------------------------------------
- static __forceinline void Emit( const iRegister& to, const ModSibBase& src, ImmType imm )
+ static __emitinline void Emit( const iRegister& to, const ModSibBase& src, ImmType imm )
{
prefix16();
write16( is_s8( imm ) ? 0x6b : 0x69 );
@@ -757,28 +551,9 @@ public:
}
};
-__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 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)
+// iMUL's special forms (unique to iMUL alone), and valid for 32/16 bit operands only,
+// thus noi templates are used.
namespace Internal
{
diff --git a/pcsx2/x86/ix86/ix86_instructions.h b/pcsx2/x86/ix86/ix86_instructions.h
index 533c2dbd57..d625b6a7c5 100644
--- a/pcsx2/x86/ix86/ix86_instructions.h
+++ b/pcsx2/x86/ix86/ix86_instructions.h
@@ -37,7 +37,6 @@ namespace x86Emitter
{
extern void iJccKnownTarget( JccComparisonType comparison, void* target, bool slideForward=false );
-
// ----- Lea Instructions (Load Effective Address) -----
// Note: alternate (void*) forms of these instructions are not provided since those
// forms are functionally equivalent to Mov reg,imm, and thus better written as MOVs
@@ -86,74 +85,22 @@ namespace x86Emitter
//////////////////////////////////////////////////////////////////////////////////////////
// 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 -----------
- extern void iMOV( const iRegister32& to, const iRegister32& from );
- extern void iMOV( const ModSibBase& sibdest, const iRegister32& from );
- extern void iMOV( const iRegister32& to, const ModSibBase& sibsrc );
- extern void iMOV( const iRegister32& to, const void* src );
- extern void iMOV( void* dest, const iRegister32& from );
-
- // preserve_flags - set to true to disable optimizations which could alter the state of
- // the flags (namely replacing mov reg,0 with xor).
- extern void iMOV( const iRegister32& to, u32 imm, bool preserve_flags=false );
- extern void iMOV( const ModSibStrict<4>& sibdest, u32 imm );
-
- // ---------- 16 Bit Interface -----------
- extern void iMOV( const iRegister16& to, const iRegister16& from );
- extern void iMOV( const ModSibBase& sibdest, const iRegister16& from );
- extern void iMOV( const iRegister16& to, const ModSibBase& sibsrc );
- extern void iMOV( const iRegister16& to, const void* src );
- extern void iMOV( void* dest, const iRegister16& from );
-
- // preserve_flags - set to true to disable optimizations which could alter the state of
- // the flags (namely replacing mov reg,0 with xor).
- extern void iMOV( const iRegister16& to, u16 imm, bool preserve_flags=false );
- extern void iMOV( const ModSibStrict<2>& sibdest, u16 imm );
-
- // ---------- 8 Bit Interface -----------
- extern void iMOV( const iRegister8& to, const iRegister8& from );
- extern void iMOV( const ModSibBase& sibdest, const iRegister8& from );
- extern void iMOV( const iRegister8& to, const ModSibBase& sibsrc );
- extern void iMOV( const iRegister8& to, const void* src );
- extern void iMOV( void* dest, const iRegister8& from );
-
- extern void iMOV( const iRegister8& to, u8 imm, bool preserve_flags=false );
- extern void iMOV( const ModSibStrict<1>& sibdest, u8 imm );
+ template< typename T >
+ __forceinline void iSMUL( const iRegister& from ) { Internal::Group3Impl::Emit( Internal::G3Type_iMUL, from ); }
+ template< typename T >
+ __noinline void iSMUL( const ModSibStrict& from ) { Internal::Group3Impl::Emit( Internal::G3Type_iMUL, from ); }
//////////////////////////////////////////////////////////////////////////////////////////
// JMP / Jcc Instructions!
diff --git a/pcsx2/x86/ix86/ix86_legacy.cpp b/pcsx2/x86/ix86/ix86_legacy.cpp
index 2fc12afd89..79f442a190 100644
--- a/pcsx2/x86/ix86/ix86_legacy.cpp
+++ b/pcsx2/x86/ix86/ix86_legacy.cpp
@@ -34,55 +34,60 @@
using namespace x86Emitter;
-template< int OperandSize >
-static __forceinline iRegister _reghlp( x86IntRegType src )
+template< typename ImmType >
+static __forceinline iRegister _reghlp( x86IntRegType src )
{
- return iRegister( src );
+ return iRegister( src );
}
static __forceinline ModSibBase _mrmhlp( x86IntRegType src )
{
- return ptr[_reghlp<4>(src)];
+ return ptr[_reghlp(src)];
}
-template< int OperandSize >
-static __forceinline ModSibStrict _mhlp( x86IntRegType src )
+template< typename ImmType >
+static __forceinline ModSibStrict _mhlp( x86IntRegType src )
{
- return ModSibStrict( x86IndexReg::Empty, x86IndexReg(src) );
+ return ModSibStrict( x86IndexReg::Empty, x86IndexReg(src) );
}
-template< int OperandSize >
-static __forceinline ModSibStrict