/* 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. * * 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 . */ #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 }; // ------------------------------------------------------------------- // template< G1Type InstType > class xImpl_Group1 { public: // ------------------------------------------------------------------------ template< typename T > __forceinline void operator()( const xRegister& to, const xRegister& from ) const { prefix16(); xWrite8( (Is8BitOp() ? 0 : 1) | (InstType<<3) ); EmitSibMagic( from, to ); } // ------------------------------------------------------------------------ template< typename T > __noinline void operator()( const ModSibBase& sibdest, const xRegister& from ) const { prefix16(); xWrite8( (Is8BitOp() ? 0 : 1) | (InstType<<3) ); EmitSibMagic( from, sibdest ); } // ------------------------------------------------------------------------ template< typename T > __noinline void operator()( const xRegister& to, const ModSibBase& sibsrc ) const { prefix16(); xWrite8( (Is8BitOp() ? 2 : 3) | (InstType<<3) ); EmitSibMagic( to, sibsrc ); } // ------------------------------------------------------------------------ // 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& sibdest, int imm ) const { if( Is8BitOp() ) { xWrite8( 0x80 ); EmitSibMagic( InstType, sibdest ); xWrite( imm ); } else { prefix16(); xWrite8( is_s8( imm ) ? 0x83 : 0x81 ); EmitSibMagic( InstType, sibdest ); if( is_s8( imm ) ) xWrite( imm ); else xWrite( imm ); } } // ------------------------------------------------------------------------ template< typename T > __forceinline void operator()( const xRegister& to, int imm ) const { prefix16(); if( !Is8BitOp() && is_s8( imm ) ) { xWrite8( 0x83 ); EmitSibMagic( InstType, to ); xWrite( imm ); } else { if( to.IsAccumulator() ) xWrite8( (Is8BitOp() ? 4 : 5) | (InstType<<3) ); else { xWrite8( Is8BitOp() ? 0x80 : 0x81 ); EmitSibMagic( InstType, to ); } xWrite( imm ); } } // ------------------------------------------------------------------------ template< typename T > __noinline void operator()( const ModSibBase& to, const xImmReg& immOrReg ) const { _DoI_helpermess( *this, to, immOrReg ); } template< typename T > __noinline void operator()( const xDirectOrIndirect& to, const xImmReg& immOrReg ) const { _DoI_helpermess( *this, to, immOrReg ); } template< typename T > __noinline void operator()( const xDirectOrIndirect& to, int imm ) const { _DoI_helpermess( *this, to, imm ); } template< typename T > __noinline void operator()( const xDirectOrIndirect& to, const xDirectOrIndirect& from ) const { _DoI_helpermess( *this, to, from ); } template< typename T > __noinline void operator()( const xRegister& to, const xDirectOrIndirect& from ) const { _DoI_helpermess( *this, xDirectOrIndirect( to ), from ); } template< typename T > __noinline void operator()( const xDirectOrIndirect& to, const xRegister& from ) const { _DoI_helpermess( *this, to, xDirectOrIndirect( from ) ); } xImpl_Group1() {} // Why does GCC need these? }; // ------------------------------------------------------------------------ // This class combines x86 with SSE/SSE2 logic operations (ADD, OR, and NOT). // Note: ANDN [AndNot] is handled below separately. // template< G1Type InstType, u16 OpcodeSSE > class xImpl_G1Logic : public xImpl_Group1 { public: using xImpl_Group1::operator(); const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; // packed single precision const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; // packed double precision xImpl_G1Logic() {} }; // ------------------------------------------------------------------------ // This class combines x86 with SSE/SSE2 arithmetic operations (ADD/SUB). // template< G1Type InstType, u16 OpcodeSSE > class xImpl_G1Arith : public xImpl_G1Logic { public: using xImpl_Group1::operator(); const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; // scalar single precision const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; // scalar double precision xImpl_G1Arith() {} }; // ------------------------------------------------------------------------ class xImpl_G1Compare : xImpl_Group1< G1Type_CMP > { protected: template< u8 Prefix > struct Woot { __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 ); } Woot() {} }; public: using xImpl_Group1::operator(); const Woot<0x00> PS; const Woot<0x66> PD; const Woot<0xf3> SS; const Woot<0xf2> SD; xImpl_G1Compare() {} //GCWhat? };