diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 51852e0cdc..6df72ec1ea 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -2980,6 +2980,10 @@ + + @@ -3004,6 +3008,10 @@ RelativePath="..\..\x86\ix86\implement\movs.h" > + + +class Group8Impl +{ +protected: + static const uint OperandSize = sizeof(ImmType); + + static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); } + +public: + Group8Impl() {} // For the love of GCC. + + static __emitinline void Emit( const iRegister& bitbase, const iRegister& bitoffset ) + { + prefix16(); + iWrite( 0x0f ); + iWrite( 0xa3 | (InstType << 2) ); + ModRM_Direct( bitoffset.Id, bitbase.Id ); + } + + static __emitinline void Emit( void* bitbase, const iRegister& bitoffset ) + { + prefix16(); + iWrite( 0x0f ); + iWrite( 0xa3 | (InstType << 2) ); + iWriteDisp( bitoffset.Id, bitbase.Id ); + } + + static __emitinline void Emit( const ModSibBase& bitbase, const iRegister& bitoffset ) + { + prefix16(); + iWrite( 0x0f ); + iWrite( 0xa3 | (InstType << 2) ); + EmitSibMagic( bitoffset.Id, bitbase ); + } + + static __emitinline void Emit( const iRegister& bitbase, u8 immoffset ) + { + prefix16(); + iWrite( 0xba0f ); + ModRM_Direct( InstType, bitbase.Id ); + iWrite( immoffset ); + } + + static __emitinline void Emit( const ModSibStrict& bitbase, u8 immoffset ) + { + prefix16(); + iWrite( 0xba0f ); + EmitSibMagic( InstType, bitbase ); + iWrite( immoffset ); + } +}; + +// ------------------------------------------------------------------- +// +template< G8Type InstType > +class Group8ImplAll +{ +protected: + typedef Group8Impl m_32; + typedef Group8Impl m_16; + +public: + __forceinline void operator()( const iRegister32& bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); } + __forceinline void operator()( const iRegister16& bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); } + __forceinline void operator()( void* bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); } + __forceinline void operator()( void* bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); } + __noinline void operator()( const ModSibBase& bitbase, const iRegister32& bitoffset ) const { m_32::Emit( bitbase, bitoffset ); } + __noinline void operator()( const ModSibBase& bitbase, const iRegister16& bitoffset ) const { m_16::Emit( bitbase, bitoffset ); } + + // Note on Imm forms : use int as the source operand since it's "reasonably inert" from a compiler + // perspective. (using uint tends to make the compiler try and fail to match signed immediates with + // one of the other overloads). + + __noinline void operator()( const ModSibStrict& bitbase, u8 immoffset ) const { m_32::Emit( bitbase, immoffset ); } + __noinline void operator()( const ModSibStrict& bitbase, u8 immoffset ) const { m_16::Emit( bitbase, immoffset ); } + void operator()( const iRegister& bitbase, u8 immoffset ) const { m_32::Emit( bitbase, immoffset ); } + void operator()( const iRegister& bitbase, u8 immoffset ) const { m_16::Emit( bitbase, immoffset ); } + + Group8ImplAll() {} +}; diff --git a/pcsx2/x86/ix86/implement/movs.h b/pcsx2/x86/ix86/implement/movs.h index 6b14e58702..80ff2a4cdd 100644 --- a/pcsx2/x86/ix86/implement/movs.h +++ b/pcsx2/x86/ix86/implement/movs.h @@ -27,10 +27,8 @@ template< typename ImmType > class MovImpl { -public: - static const uint OperandSize = sizeof(ImmType); - protected: + static const uint OperandSize = sizeof(ImmType); static bool Is8BitOperand() { return OperandSize == 1; } static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); } @@ -44,7 +42,7 @@ public: prefix16(); iWrite( Is8BitOperand() ? 0x88 : 0x89 ); - ModRM( 3, from.Id, to.Id ); + ModRM_Direct( from.Id, to.Id ); } // ------------------------------------------------------------------------ @@ -187,14 +185,16 @@ public: ////////////////////////////////////////////////////////////////////////////////////////// // CMOV !! [in all of it's disappointing lack-of glory] +// Caution! This instruction can look exciting and cool, until you realize that it cannot +// load immediate values into registers. -_- // -template< typename ImmType > -class CMovImpl +template< typename ImmType, int InstBaseVal > +class CMovSetImpl { protected: static const uint OperandSize = sizeof(ImmType); - static bool Is8BitOperand() {return OperandSize == 1; } + static bool Is8BitOperand() { return OperandSize == 1; } static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); } static __forceinline void emit_base( JccComparisonType cc ) @@ -202,11 +202,11 @@ protected: jASSUME( cc >= 0 && cc <= 0x0f ); prefix16(); write8( 0x0f ); - write8( 0x40 | cc ); + write8( InstBaseVal | cc ); } public: - CMovImpl() {} + CMovSetImpl() {} static __emitinline void Emit( JccComparisonType cc, const iRegister& to, const iRegister& from ) { @@ -226,6 +226,27 @@ public: emit_base( cc ); EmitSibMagic( to.Id, sibsrc ); } + + // This form is provided for SETcc only (not available in CMOV) + static __emitinline void EmitSet( JccComparisonType cc, const iRegister& to ) + { + emit_base( cc ); + ModRM_Direct( 0, to.Id ); + } + + // This form is provided for SETcc only (not available in CMOV) + static __emitinline void EmitSet( JccComparisonType cc, const void* src ) + { + emit_base( cc ); + iWriteDisp( 0, src ); + } + + // This form is provided for SETcc only (not available in CMOV) + static __emitinline void EmitSet( JccComparisonType cc, const ModSibStrict& sibsrc ) + { + emit_base( cc ); + EmitSibMagic( 0, sibsrc ); + } }; // ------------------------------------------------------------------------ @@ -235,8 +256,8 @@ public: class CMovImplGeneric { protected: - typedef CMovImpl m_32; - typedef CMovImpl m_16; + typedef CMovSetImpl m_32; // 0x40 is the cmov base instruction id + typedef CMovSetImpl m_16; // 0x40 is the cmov base instruction id public: __forceinline void operator()( JccComparisonType ccType, const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); } @@ -255,8 +276,8 @@ template< JccComparisonType ccType > class CMovImplAll { protected: - typedef CMovImpl m_32; - typedef CMovImpl m_16; + typedef CMovSetImpl m_32; + typedef CMovSetImpl m_16; public: __forceinline void operator()( const iRegister32& to, const iRegister32& from ) const { m_32::Emit( ccType, to, from ); } @@ -270,6 +291,36 @@ public: CMovImplAll() {} // don't ask. }; +// ------------------------------------------------------------------------ +class SetImplGeneric +{ +protected: + typedef CMovSetImpl Impl; // 0x90 is the SETcc base instruction id + +public: + __forceinline void operator()( JccComparisonType cc, const iRegister8& to ) const { Impl::EmitSet( cc, to ); } + __forceinline void operator()( JccComparisonType cc, void* dest ) const { Impl::EmitSet( cc, dest ); } + __noinline void operator()( JccComparisonType cc, const ModSibStrict& dest ) const { Impl::EmitSet( cc, dest ); } + + SetImplGeneric() {} // if you do, ask GCC. +}; + +// ------------------------------------------------------------------------ +template< JccComparisonType ccType > +class SetImplAll +{ +protected: + typedef CMovSetImpl Impl; // 0x90 is the SETcc base instruction id + +public: + __forceinline void operator()( const iRegister8& to ) const { Impl::EmitSet( ccType, to ); } + __forceinline void operator()( void* dest ) const { Impl::EmitSet( ccType, dest ); } + __noinline void operator()( const ModSibStrict& dest ) const { Impl::EmitSet( ccType, dest ); } + + SetImplAll() {} // if you do, ask GCC. +}; + + ////////////////////////////////////////////////////////////////////////////////////////// // Mov with sign/zero extension implementations (movsx / movzx) // diff --git a/pcsx2/x86/ix86/implement/test.h b/pcsx2/x86/ix86/implement/test.h new file mode 100644 index 0000000000..c7b2fa58b2 --- /dev/null +++ b/pcsx2/x86/ix86/implement/test.h @@ -0,0 +1,83 @@ +/* Pcsx2 - Pc Ps2 Emulator + * Copyright (C) 2002-2009 Pcsx2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once + +////////////////////////////////////////////////////////////////////////////////////////// +// MOV instruction Implementation + +template< typename ImmType > +class TestImpl +{ +protected: + static const uint OperandSize = sizeof(ImmType); + static bool Is8BitOperand() { return OperandSize == 1; } + static void prefix16() { if( OperandSize == 2 ) iWrite( 0x66 ); } + +public: + TestImpl() {} + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const iRegister& to, const iRegister& from ) + { + prefix16(); + iWrite( Is8BitOperand() ? 0x84 : 0x85 ); + ModRM_Direct( from.Id, to.Id ); + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const iRegister& to, ImmType imm ) + { + prefix16(); + + if( to.IsAccumulator() ) + iWrite( Is8BitOperand() ? 0xa8 : 0xa9 ); + else + { + iWrite( Is8BitOperand() ? 0xf6 : 0xf7 ); + ModRM_Direct( 0, to.Id ); + } + iWrite( imm ); + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( ModSibStrict dest, ImmType imm ) + { + prefix16(); + iWrite( Is8BitOperand() ? 0xf6 : 0xf7 ); + EmitSibMagic( 0, dest ); + iWrite( imm ); + } +}; + +// ------------------------------------------------------------------- +// +class TestImplAll +{ +public: + template< typename T > + __forceinline void operator()( const iRegister& to, const iRegister& from ) const { TestImpl::Emit( to, from ); } + + template< typename T > + __noinline void operator()( const ModSibStrict& sibdest, T imm ) const { TestImpl::Emit( sibdest, imm ); } + template< typename T > + void operator()( const iRegister& to, T imm ) const { TestImpl::Emit( to, imm ); } + + TestImplAll() {} // Why does GCC need these? +}; + diff --git a/pcsx2/x86/ix86/ix86.cpp b/pcsx2/x86/ix86/ix86.cpp index d9d9d0ecda..004ac9f4f9 100644 --- a/pcsx2/x86/ix86/ix86.cpp +++ b/pcsx2/x86/ix86/ix86.cpp @@ -241,6 +241,7 @@ namespace Internal using namespace Internal; const MovImplAll iMOV; +const TestImplAll iTEST; const Group1ImplAll iADD; const Group1ImplAll iOR; @@ -271,9 +272,15 @@ const IncDecImplAll iDEC; const MovExtendImplAll iMOVZX; const MovExtendImplAll iMOVSX; -const Internal::DwordShiftImplAll iSHLD; -const Internal::DwordShiftImplAll iSHRD; +const DwordShiftImplAll iSHLD; +const DwordShiftImplAll iSHRD; +const Group8ImplAll iBT; +const Group8ImplAll iBTR; +const Group8ImplAll iBTS; +const Group8ImplAll iBTC; + +// ------------------------------------------------------------------------ const CMovImplGeneric iCMOV; const CMovImplAll iCMOVA; @@ -301,6 +308,35 @@ const CMovImplAll iCMOVNS; const CMovImplAll iCMOVPE; const CMovImplAll iCMOVPO; +// ------------------------------------------------------------------------ +const SetImplGeneric iSET; + +const SetImplAll iSETA; +const SetImplAll iSETAE; +const SetImplAll iSETB; +const SetImplAll iSETBE; + +const SetImplAll iSETG; +const SetImplAll iSETGE; +const SetImplAll iSETL; +const SetImplAll iSETLE; + +const SetImplAll iSETZ; +const SetImplAll iSETE; +const SetImplAll iSETNZ; +const SetImplAll iSETNE; + +const SetImplAll iSETO; +const SetImplAll iSETNO; +const SetImplAll iSETC; +const SetImplAll iSETNC; + +const SetImplAll iSETS; +const SetImplAll iSETNS; +const SetImplAll iSETPE; +const SetImplAll iSETPO; + + // ------------------------------------------------------------------------ // Assigns the current emitter buffer target address. // This is provided instead of using x86Ptr directly, since we may in the future find @@ -582,13 +618,13 @@ __noinline void iSMUL( const iRegister16& to, const ModSibBase& from, s16 imm ) __emitinline void iPOP( const ModSibBase& from ) { iWrite( 0x8f ); - Internal::EmitSibMagic( 0, from ); + EmitSibMagic( 0, from ); } __emitinline void iPUSH( const ModSibBase& from ) { iWrite( 0xff ); - Internal::EmitSibMagic( 6, from ); + EmitSibMagic( 6, from ); } diff --git a/pcsx2/x86/ix86/ix86_instructions.h b/pcsx2/x86/ix86/ix86_instructions.h index d625b6a7c5..9a59620ce6 100644 --- a/pcsx2/x86/ix86/ix86_instructions.h +++ b/pcsx2/x86/ix86/ix86_instructions.h @@ -119,7 +119,6 @@ namespace x86Emitter typedef iForwardJump iForwardJump8; typedef iForwardJump iForwardJump32; - DEFINE_FORWARD_JUMP( JA, Jcc_Above ); DEFINE_FORWARD_JUMP( JB, Jcc_Below ); diff --git a/pcsx2/x86/ix86/ix86_legacy.cpp b/pcsx2/x86/ix86/ix86_legacy.cpp index 79f442a190..0ecac70f31 100644 --- a/pcsx2/x86/ix86/ix86_legacy.cpp +++ b/pcsx2/x86/ix86/ix86_legacy.cpp @@ -145,6 +145,20 @@ DEFINE_LEGACY_MOVEXTEND( ZX, 32, 8 ) DEFINE_LEGACY_MOVEXTEND( SX, 16, 8 ) DEFINE_LEGACY_MOVEXTEND( ZX, 16, 8 ) +emitterT void TEST32ItoR( x86IntRegType to, u32 from ) { iTEST( iRegister32(to), from ); } +emitterT void TEST32ItoM( uptr to, u32 from ) { iTEST( ptr32[to], from ); } +emitterT void TEST32RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister32(to), iRegister32(from) ); } +emitterT void TEST32ItoRm( x86IntRegType to, u32 from ) { iTEST( ptr32[x86IndexReg(to)], from ); } + +emitterT void TEST16ItoR( x86IntRegType to, u16 from ) { iTEST( iRegister16(to), from ); } +emitterT void TEST16ItoM( uptr to, u16 from ) { iTEST( ptr16[to], from ); } +emitterT void TEST16RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister16(to), iRegister16(from) ); } +emitterT void TEST16ItoRm( x86IntRegType to, u16 from ) { iTEST( ptr16[x86IndexReg(to)], from ); } + +emitterT void TEST8ItoR( x86IntRegType to, u8 from ) { iTEST( iRegister8(to), from ); } +emitterT void TEST8ItoM( uptr to, u8 from ) { iTEST( ptr8[to], from ); } +emitterT void TEST8RtoR( x86IntRegType to, x86IntRegType from ) { iTEST( iRegister8(to), iRegister8(from) ); } +emitterT void TEST8ItoRm( x86IntRegType to, u8 from ) { iTEST( ptr8[x86IndexReg(to)], from ); } // mov r32 to [r32<(to), from ); @@ -251,6 +263,53 @@ emitterT void LEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) iLEA( iRegister16( to ), ptr[x86IndexReg(from)*(1< iROL; extern const Internal::Group2ImplAll iROR; @@ -672,6 +675,12 @@ namespace x86Emitter extern const Internal::DwordShiftImplAll iSHLD; extern const Internal::DwordShiftImplAll iSHRD; + extern const Internal::Group8ImplAll iBT; + extern const Internal::Group8ImplAll iBTR; + extern const Internal::Group8ImplAll iBTS; + extern const Internal::Group8ImplAll iBTC; + + // ------------------------------------------------------------------------ extern const Internal::CMovImplGeneric iCMOV; extern const Internal::CMovImplAll iCMOVA; @@ -698,6 +707,35 @@ namespace x86Emitter extern const Internal::CMovImplAll iCMOVNS; extern const Internal::CMovImplAll iCMOVPE; extern const Internal::CMovImplAll iCMOVPO; + + // ------------------------------------------------------------------------ + extern const Internal::SetImplGeneric iSET; + + extern const Internal::SetImplAll iSETA; + extern const Internal::SetImplAll iSETAE; + extern const Internal::SetImplAll iSETB; + extern const Internal::SetImplAll iSETBE; + + extern const Internal::SetImplAll iSETG; + extern const Internal::SetImplAll iSETGE; + extern const Internal::SetImplAll iSETL; + extern const Internal::SetImplAll iSETLE; + + extern const Internal::SetImplAll iSETZ; + extern const Internal::SetImplAll iSETE; + extern const Internal::SetImplAll iSETNZ; + extern const Internal::SetImplAll iSETNE; + + extern const Internal::SetImplAll iSETO; + extern const Internal::SetImplAll iSETNO; + extern const Internal::SetImplAll iSETC; + extern const Internal::SetImplAll iSETNC; + + extern const Internal::SetImplAll iSETS; + extern const Internal::SetImplAll iSETNS; + extern const Internal::SetImplAll iSETPE; + extern const Internal::SetImplAll iSETPO; + }