mirror of https://github.com/PCSX2/pcsx2.git
Emitter: fixed a bug in MOVSX/ZX's reg->reg form [resolves Issue 159 - missing geometry in DQ8], and moved some files around.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@988 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
986b4fdf93
commit
ac2f5713fc
|
@ -2925,22 +2925,6 @@
|
|||
RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_dwshift.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_group1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_group2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_impl_movs.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\ix86_inlines.inl"
|
||||
>
|
||||
|
@ -2993,6 +2977,30 @@
|
|||
RelativePath="..\..\x86\ix86\ix86_types.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\implement\movs.h"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Implement"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\implement\dwshift.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\implement\group1.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\implement\group2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\x86\ix86\implement\incdec.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ClassDiagram1.cd"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// Header: ix86_impl_dwshift.h -- covers SHLD and SHRD.
|
||||
// Implementations here cover SHLD and SHRD.
|
||||
// Note: This header is meant to be included from within the x86Emitter::Internal namespace.
|
||||
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
|||
{
|
||||
prefix16();
|
||||
write16( 0xa50f | (isShiftRight ? 0x800 : 0) );
|
||||
ModRM( 3, from.Id, to.Id );
|
||||
ModRM_Direct( from.Id, to.Id );
|
||||
}
|
||||
|
||||
static __emitinline void Emit( const iRegister<OperandSize>& to, const iRegister<OperandSize>& 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 );
|
||||
}
|
||||
|
|
@ -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<u8>( (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<OperandSize>& from )
|
||||
|
@ -89,7 +88,7 @@ public:
|
|||
if( !Is8BitOperand() && is_s8( imm ) )
|
||||
{
|
||||
iWrite<u8>( 0x83 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
ModRM_Direct( InstType, to.Id );
|
||||
iWrite<s8>( imm );
|
||||
}
|
||||
else
|
||||
|
@ -99,7 +98,7 @@ public:
|
|||
else
|
||||
{
|
||||
iWrite<u8>( Is8BitOperand() ? 0x80 : 0x81 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
ModRM_Direct( InstType, to.Id );
|
||||
}
|
||||
iWrite<ImmType>( 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?
|
||||
};
|
|
@ -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<u8>( Is8BitOperand() ? 0xd2 : 0xd3 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
ModRM_Direct( InstType, to.Id );
|
||||
}
|
||||
|
||||
static __emitinline void Emit( const iRegister<OperandSize>& to, u8 imm )
|
||||
|
@ -68,12 +67,12 @@ public:
|
|||
{
|
||||
// special encoding of 1's
|
||||
iWrite<u8>( Is8BitOperand() ? 0xd0 : 0xd1 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
ModRM_Direct( InstType, to.Id );
|
||||
}
|
||||
else
|
||||
{
|
||||
iWrite<u8>( Is8BitOperand() ? 0xc0 : 0xc1 );
|
||||
ModRM( 3, InstType, to.Id );
|
||||
ModRM_Direct( InstType, to.Id );
|
||||
iWrite<u8>( imm );
|
||||
}
|
||||
}
|
|
@ -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.
|
|
@ -44,8 +44,9 @@ public:
|
|||
|
||||
static __emitinline void Emit( JccComparisonType cc, const iRegister<OperandSize>& to, const iRegister<OperandSize>& 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<OperandSize>& to, const void* src )
|
||||
|
@ -123,7 +124,7 @@ public:
|
|||
static __emitinline void Emit( const iRegister<DestOperandSize>& to, const iRegister<SrcOperandSize>& from, bool SignExtend )
|
||||
{
|
||||
emit_base( SignExtend );
|
||||
ModRM( 3, from.Id, to.Id );
|
||||
ModRM_Direct( to.Id, from.Id );
|
||||
}
|
||||
|
||||
static __emitinline void Emit( const iRegister<DestOperandSize>& to, const ModSibStrict<SrcOperandSize>& sibsrc, bool SignExtend )
|
|
@ -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<u8>( (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<u32> iMUL32;
|
||||
typedef iMulImpl<u16> iMUL16;
|
||||
}
|
||||
|
||||
__forceinline void iUMUL( const iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
__forceinline void iUMUL( const iRegister16& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
__forceinline void iUMUL( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
|
||||
|
@ -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<u32> iMUL32;
|
||||
typedef iMulImpl<u16> 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 ); }
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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 /
|
||||
////////////////////////////////////
|
||||
|
|
|
@ -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!
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue