2009-09-08 12:08:10 +00:00
|
|
|
/* PCSX2 - PS2 Emulator for PCs
|
|
|
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
|
|
|
*
|
|
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
2009-04-15 21:00:32 +00:00
|
|
|
*
|
2009-09-08 12:08:10 +00:00
|
|
|
* PCSX2 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 PCSX2.
|
|
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
2009-04-15 21:00:32 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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
|
|
|
|
{
|
|
|
|
G1Type_ADD=0,
|
|
|
|
G1Type_OR,
|
|
|
|
G1Type_ADC,
|
|
|
|
G1Type_SBB,
|
|
|
|
G1Type_AND,
|
|
|
|
G1Type_SUB,
|
|
|
|
G1Type_XOR,
|
|
|
|
G1Type_CMP
|
|
|
|
};
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------
|
2009-04-20 19:25:35 +00:00
|
|
|
//
|
|
|
|
template< G1Type InstType >
|
|
|
|
class xImpl_Group1
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
public:
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
template< typename T > __forceinline void operator()( const xRegister<T>& to, const xRegister<T>& from ) const
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
prefix16<T>();
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
|
|
|
EmitSibMagic( from, to );
|
2009-04-15 21:00:32 +00:00
|
|
|
}
|
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
template< typename T > __noinline void operator()( const ModSibBase& sibdest, const xRegister<T>& from ) const
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
prefix16<T>();
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( (Is8BitOp<T>() ? 0 : 1) | (InstType<<3) );
|
|
|
|
EmitSibMagic( from, sibdest );
|
2009-04-15 21:00:32 +00:00
|
|
|
}
|
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
template< typename T > __noinline void operator()( const xRegister<T>& to, const ModSibBase& sibsrc ) const
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
prefix16<T>();
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( (Is8BitOp<T>() ? 2 : 3) | (InstType<<3) );
|
|
|
|
EmitSibMagic( to, sibsrc );
|
2009-04-15 21:00:32 +00:00
|
|
|
}
|
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
// 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<T>& sibdest, int imm ) const
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
if( Is8BitOp<T>() )
|
2009-04-15 21:00:32 +00:00
|
|
|
{
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( 0x80 );
|
2009-04-15 21:00:32 +00:00
|
|
|
EmitSibMagic( InstType, sibdest );
|
2009-04-20 19:25:35 +00:00
|
|
|
xWrite<s8>( imm );
|
2009-04-15 21:00:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-04-20 19:25:35 +00:00
|
|
|
prefix16<T>();
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( is_s8( imm ) ? 0x83 : 0x81 );
|
2009-04-15 21:00:32 +00:00
|
|
|
EmitSibMagic( InstType, sibdest );
|
|
|
|
if( is_s8( imm ) )
|
2009-04-20 03:10:05 +00:00
|
|
|
xWrite<s8>( imm );
|
2009-04-15 21:00:32 +00:00
|
|
|
else
|
2009-04-20 19:25:35 +00:00
|
|
|
xWrite<T>( imm );
|
2009-04-15 21:00:32 +00:00
|
|
|
}
|
|
|
|
}
|
2009-04-16 22:38:55 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
template< typename T > __forceinline void operator()( const xRegister<T>& to, int imm ) const
|
|
|
|
{
|
|
|
|
prefix16<T>();
|
|
|
|
if( !Is8BitOp<T>() && is_s8( imm ) )
|
|
|
|
{
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( 0x83 );
|
|
|
|
EmitSibMagic( InstType, to );
|
2009-04-20 19:25:35 +00:00
|
|
|
xWrite<s8>( imm );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( to.IsAccumulator() )
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( (Is8BitOp<T>() ? 4 : 5) | (InstType<<3) );
|
2009-04-20 19:25:35 +00:00
|
|
|
else
|
|
|
|
{
|
2009-04-24 11:25:10 +00:00
|
|
|
xWrite8( Is8BitOp<T>() ? 0x80 : 0x81 );
|
|
|
|
EmitSibMagic( InstType, to );
|
2009-04-20 19:25:35 +00:00
|
|
|
}
|
|
|
|
xWrite<T>( imm );
|
|
|
|
}
|
|
|
|
}
|
2009-07-03 00:49:40 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
template< typename T > __noinline void operator()( const ModSibBase& to, const xImmReg<T>& immOrReg ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, to, immOrReg );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > __noinline void operator()( const xDirectOrIndirect<T>& to, const xImmReg<T>& immOrReg ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, to, immOrReg );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > __noinline void operator()( const xDirectOrIndirect<T>& to, int imm ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, to, imm );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > __noinline void operator()( const xDirectOrIndirect<T>& to, const xDirectOrIndirect<T>& from ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, to, from );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > __noinline void operator()( const xRegister<T>& to, const xDirectOrIndirect<T>& from ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, xDirectOrIndirect<T>( to ), from );
|
|
|
|
}
|
|
|
|
|
|
|
|
template< typename T > __noinline void operator()( const xDirectOrIndirect<T>& to, const xRegister<T>& from ) const
|
|
|
|
{
|
|
|
|
_DoI_helpermess( *this, to, xDirectOrIndirect<T>( from ) );
|
|
|
|
}
|
2009-04-15 21:00:32 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
xImpl_Group1() {} // Why does GCC need these?
|
2009-04-15 21:00:32 +00:00
|
|
|
};
|
|
|
|
|
2009-04-20 03:10:05 +00:00
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
// This class combines x86 with SSE/SSE2 logic operations (ADD, OR, and NOT).
|
|
|
|
// Note: ANDN [AndNot] is handled below separately.
|
|
|
|
//
|
2009-04-21 01:40:45 +00:00
|
|
|
template< G1Type InstType, u16 OpcodeSSE >
|
2009-04-20 19:25:35 +00:00
|
|
|
class xImpl_G1Logic : public xImpl_Group1<InstType>
|
2009-04-20 00:06:51 +00:00
|
|
|
{
|
|
|
|
public:
|
2009-04-20 19:25:35 +00:00
|
|
|
using xImpl_Group1<InstType>::operator();
|
2009-04-20 03:10:05 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; // packed single precision
|
|
|
|
const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; // packed double precision
|
2009-04-20 00:06:51 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
xImpl_G1Logic() {}
|
2009-04-20 00:06:51 +00:00
|
|
|
};
|
|
|
|
|
2009-04-20 03:10:05 +00:00
|
|
|
// ------------------------------------------------------------------------
|
2009-04-20 19:25:35 +00:00
|
|
|
// This class combines x86 with SSE/SSE2 arithmetic operations (ADD/SUB).
|
2009-04-20 03:10:05 +00:00
|
|
|
//
|
2009-04-21 01:40:45 +00:00
|
|
|
template< G1Type InstType, u16 OpcodeSSE >
|
2009-04-20 19:25:35 +00:00
|
|
|
class xImpl_G1Arith : public xImpl_G1Logic<InstType, OpcodeSSE >
|
2009-04-20 00:06:51 +00:00
|
|
|
{
|
|
|
|
public:
|
2009-04-20 19:25:35 +00:00
|
|
|
using xImpl_Group1<InstType>::operator();
|
2009-04-20 03:10:05 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; // scalar single precision
|
|
|
|
const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; // scalar double precision
|
2009-04-20 00:06:51 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
xImpl_G1Arith() {}
|
2009-04-20 00:06:51 +00:00
|
|
|
};
|
|
|
|
|
2009-04-20 03:10:05 +00:00
|
|
|
// ------------------------------------------------------------------------
|
2009-04-20 19:25:35 +00:00
|
|
|
class xImpl_G1Compare : xImpl_Group1< G1Type_CMP >
|
2009-04-20 00:06:51 +00:00
|
|
|
{
|
2009-04-20 03:10:05 +00:00
|
|
|
protected:
|
|
|
|
template< u8 Prefix > struct Woot
|
|
|
|
{
|
2009-04-24 11:25:10 +00:00
|
|
|
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, SSE2_ComparisonType cmptype ) const{ xOpWrite0F( Prefix, 0xc2, to, from, (u8)cmptype ); }
|
|
|
|
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, SSE2_ComparisonType cmptype ) const { xOpWrite0F( Prefix, 0xc2, to, from, (u8)cmptype ); }
|
2009-04-20 15:22:02 +00:00
|
|
|
Woot() {}
|
2009-04-20 03:10:05 +00:00
|
|
|
};
|
|
|
|
|
2009-04-20 00:06:51 +00:00
|
|
|
public:
|
2009-04-24 11:25:10 +00:00
|
|
|
using xImpl_Group1<G1Type_CMP>::operator();
|
2009-04-20 03:10:05 +00:00
|
|
|
|
2009-04-20 15:22:02 +00:00
|
|
|
const Woot<0x00> PS;
|
|
|
|
const Woot<0x66> PD;
|
|
|
|
const Woot<0xf3> SS;
|
|
|
|
const Woot<0xf2> SD;
|
2009-04-20 00:06:51 +00:00
|
|
|
|
2009-04-20 19:25:35 +00:00
|
|
|
xImpl_G1Compare() {} //GCWhat?
|
2009-04-20 03:10:05 +00:00
|
|
|
};
|