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" RelativePath="..\..\x86\ix86\ix86_fpu.cpp"
> >
</File> </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 <File
RelativePath="..\..\x86\ix86\ix86_inlines.inl" RelativePath="..\..\x86\ix86\ix86_inlines.inl"
> >
@ -2993,6 +2977,30 @@
RelativePath="..\..\x86\ix86\ix86_types.h" RelativePath="..\..\x86\ix86\ix86_types.h"
> >
</File> </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> </Filter>
<File <File
RelativePath=".\ClassDiagram1.cd" RelativePath=".\ClassDiagram1.cd"

View File

@ -18,7 +18,7 @@
#pragma once #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. // Note: This header is meant to be included from within the x86Emitter::Internal namespace.
@ -49,7 +49,7 @@ public:
{ {
prefix16(); prefix16();
write16( 0xa50f | (isShiftRight ? 0x800 : 0) ); 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 ) static __emitinline void Emit( const iRegister<OperandSize>& to, const iRegister<OperandSize>& from, u8 imm )
@ -57,7 +57,7 @@ public:
if( imm == 0 ) return; if( imm == 0 ) return;
prefix16(); prefix16();
write16( 0xa40f | (isShiftRight ? 0x800 : 0) ); write16( 0xa40f | (isShiftRight ? 0x800 : 0) );
ModRM( 3, from.Id, to.Id ); ModRM_Direct( from.Id, to.Id );
write8( imm ); write8( imm );
} }

View File

@ -19,7 +19,6 @@
#pragma once #pragma once
// Note: This header is meant to be included from within the x86Emitter::Internal namespace. // Note: This header is meant to be included from within the x86Emitter::Internal namespace.
// Instructions implemented in this header are as follows -->> // Instructions implemented in this header are as follows -->>
enum G1Type enum G1Type
@ -52,7 +51,7 @@ public:
{ {
prefix16(); prefix16();
iWrite<u8>( (Is8BitOperand() ? 0 : 1) | (InstType<<3) ); 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 ) static __emitinline void Emit( const ModSibBase& sibdest, const iRegister<OperandSize>& from )
@ -89,7 +88,7 @@ public:
if( !Is8BitOperand() && is_s8( imm ) ) if( !Is8BitOperand() && is_s8( imm ) )
{ {
iWrite<u8>( 0x83 ); iWrite<u8>( 0x83 );
ModRM( 3, InstType, to.Id ); ModRM_Direct( InstType, to.Id );
iWrite<s8>( imm ); iWrite<s8>( imm );
} }
else else
@ -99,7 +98,7 @@ public:
else else
{ {
iWrite<u8>( Is8BitOperand() ? 0x80 : 0x81 ); iWrite<u8>( Is8BitOperand() ? 0x80 : 0x81 );
ModRM( 3, InstType, to.Id ); ModRM_Direct( InstType, to.Id );
} }
iWrite<ImmType>( imm ); 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 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 ); } __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 void operator()( const iRegister32& to, u32 imm ) const { m_32::Emit( to, imm ); }
{
//if( needs_flags || (imm != 0) || !_optimize_imm0() )
m_32::Emit( to, imm );
}
// ---------- 16 Bit Interface ----------- // ---------- 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 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 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 ); } __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 ----------- // ---------- 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 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 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 ); } __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? Group1ImplAll() {} // Why does GCC need these?
}; };

View File

@ -19,7 +19,6 @@
#pragma once #pragma once
// Note: This header is meant to be included from within the x86Emitter::Internal namespace. // Note: This header is meant to be included from within the x86Emitter::Internal namespace.
// Instructions implemented in this header are as follows -->> // Instructions implemented in this header are as follows -->>
enum G2Type enum G2Type
@ -56,7 +55,7 @@ public:
{ {
prefix16(); prefix16();
iWrite<u8>( Is8BitOperand() ? 0xd2 : 0xd3 ); 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 ) static __emitinline void Emit( const iRegister<OperandSize>& to, u8 imm )
@ -68,12 +67,12 @@ public:
{ {
// special encoding of 1's // special encoding of 1's
iWrite<u8>( Is8BitOperand() ? 0xd0 : 0xd1 ); iWrite<u8>( Is8BitOperand() ? 0xd0 : 0xd1 );
ModRM( 3, InstType, to.Id ); ModRM_Direct( InstType, to.Id );
} }
else else
{ {
iWrite<u8>( Is8BitOperand() ? 0xc0 : 0xc1 ); iWrite<u8>( Is8BitOperand() ? 0xc0 : 0xc1 );
ModRM( 3, InstType, to.Id ); ModRM_Direct( InstType, to.Id );
iWrite<u8>( imm ); 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 ) static __emitinline void Emit( JccComparisonType cc, const iRegister<OperandSize>& to, const iRegister<OperandSize>& from )
{ {
if( to == from ) return;
emit_base( cc ); 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 ) 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 ) static __emitinline void Emit( const iRegister<DestOperandSize>& to, const iRegister<SrcOperandSize>& from, bool SignExtend )
{ {
emit_base( 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 ) static __emitinline void Emit( const iRegister<DestOperandSize>& to, const ModSibStrict<SrcOperandSize>& sibsrc, bool SignExtend )

View File

@ -128,6 +128,11 @@ namespace Internal
//x86Ptr++; //x86Ptr++;
} }
__forceinline void ModRM_Direct( uint reg, uint rm )
{
ModRM( Mod_Direct, reg, rm );
}
__forceinline void SibSB( u32 ss, u32 index, u32 base ) __forceinline void SibSB( u32 ss, u32 index, u32 base )
{ {
iWrite<u8>( (ss << 6) | (index << 3) | 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 > template< typename ImmType >
class iMulImpl 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 iRegister32& from ) { EmitMulDiv_OneRegForm( MDT_Mul, from ); }
__forceinline void iUMUL( const iRegister16& 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 ); } __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 ); } __forceinline void iSDIV( const iRegister8& from ) { EmitMulDiv_OneRegForm( MDT_iDiv, from ); }
__noinline void iSDIV( const ModSibSized& 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 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 void* src ) { iMUL32::Emit( to, src ); }
__forceinline void iSMUL( const iRegister32& to, const iRegister32& from, s32 imm ) { iMUL32::Emit( to, from, imm ); } __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& src ) { iMUL32::Emit( to, src ); }
__noinline void iSMUL( const iRegister32& to, const ModSibBase& from, s32 imm ) { iMUL32::Emit( to, from, imm ); } __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 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 void* src ) { iMUL16::Emit( to, src ); }
__forceinline void iSMUL( const iRegister16& to, const iRegister16& from, s16 imm ) { iMUL16::Emit( to, from, imm ); } __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& src ) { iMUL16::Emit( to, src ); }
__noinline void iSMUL( const iRegister16& to, const ModSibBase& from, s16 imm ) { iMUL16::Emit( to, from, imm ); } __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 ); 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) emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset)
{ {
iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] ); iLEA( iRegister32( to ), ptr[x86IndexReg(from)+offset] );
@ -413,30 +438,6 @@ emitterT void DEC16M( u32 to )
write32( MEMADDR(to, 4) ); 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 / // logical instructions /
//////////////////////////////////// ////////////////////////////////////

View File

@ -147,6 +147,15 @@ namespace x86Emitter
# define __noinline # define __noinline
#endif #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_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_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) static const int ModRm_UseDisp32 = 5; // same index value as EBP (used in Mod field)
@ -636,57 +645,17 @@ namespace x86Emitter
namespace Internal namespace Internal
{ {
extern void ModRM( uint mod, uint reg, uint rm ); 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 SibSB( u32 ss, u32 index, u32 base );
extern void iWriteDisp( int regfield, s32 displacement ); extern void iWriteDisp( int regfield, s32 displacement );
extern void iWriteDisp( int regfield, const void* address ); extern void iWriteDisp( int regfield, const void* address );
extern void EmitSibMagic( uint regfield, const ModSibBase& info ); extern void EmitSibMagic( uint regfield, const ModSibBase& info );
#include "ix86_impl_group1.h" #include "implement/group1.h"
#include "ix86_impl_group2.h" #include "implement/group2.h"
#include "ix86_impl_movs.h" // cmov and movsx/zx #include "implement/movs.h" // cmov and movsx/zx
#include "ix86_impl_dwshift.h" // dowubleword shifts! #include "implement/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;
}*/
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------