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:
Jake.Stine 2009-04-16 14:45:13 +00:00
parent 986b4fdf93
commit ac2f5713fc
9 changed files with 120 additions and 116 deletions

View File

@ -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"

View File

@ -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 );
}

View File

@ -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?
};

View File

@ -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 );
}
}

View File

@ -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.

View File

@ -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 )

View File

@ -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 ); }
//////////////////////////////////////////////////////////////////////////////////////////

View File

@ -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 /
////////////////////////////////////

View File

@ -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!
}
// ------------------------------------------------------------------------