/* 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 G3Type { G3Type_NOT = 2, G3Type_NEG = 3, G3Type_MUL = 4, G3Type_iMUL = 5, // partial implementation, iMul has additional forms in ix86.cpp G3Type_DIV = 6, G3Type_iDIV = 7 }; ////////////////////////////////////////////////////////////////////////////////////////// // template< G3Type InstType > class xImpl_Group3 { public: // ------------------------------------------------------------------------ template< typename T > __emitinline void operator()( const xRegister& from ) const { prefix16(); xWrite8(Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( InstType, from ); } // ------------------------------------------------------------------------ template< typename T > __emitinline void operator()( const ModSibStrict& from ) const { prefix16(); xWrite8( Is8BitOp() ? 0xf6 : 0xf7 ); EmitSibMagic( InstType, from ); } template< typename T > __emitinline void operator()( const xDirectOrIndirect& from ) const { _DoI_helpermess( *this, from ); } xImpl_Group3() {} }; // ------------------------------------------------------------------------ // This class combines x86 and SSE/SSE2 instructions for iMUL and iDIV. // template< G3Type InstType, u16 OpcodeSSE > class ImplMulDivBase : public xImpl_Group3 { public: ImplMulDivBase() {} const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; }; ////////////////////////////////////////////////////////////////////////////////////////// // class xImpl_iDiv : public ImplMulDivBase { public: using ImplMulDivBase::operator(); }; ////////////////////////////////////////////////////////////////////////////////////////// // The following iMul-specific forms are valid for 16 and 32 bit register operands only! // class xImpl_iMul : public ImplMulDivBase { template< typename T1, typename T2, typename ImmType > static __forceinline void ImmStyle( const T1& param1, const T2& param2, ImmType imm8 ) { xOpWrite0F( (sizeof(ImmType) == 2) ? 0x66 : 0, is_s8( imm8 ) ? 0x6b : 0x69, param1, param2 ); if( is_s8( imm8 ) ) xWrite8( (u8)imm8 ); else xWrite( imm8 ); } public: using ImplMulDivBase::operator(); __forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( 0xaf, to, from ); } __forceinline void operator()( const xRegister32& to, const ModSibBase& src ) const { xOpWrite0F( 0xaf, to, src ); } __forceinline void operator()( const xRegister32& to, const xRegister32& from, s32 imm ) const{ ImmStyle( to, from, imm ); } __forceinline void operator()( const xRegister32& to, const ModSibBase& from, s32 imm ) const { ImmStyle( to, from, imm ); } __forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, 0xaf, to, from ); } __forceinline void operator()( const xRegister16& to, const ModSibBase& src ) const { xOpWrite0F( 0x66, 0xaf, to, src ); } __forceinline void operator()( const xRegister16& to, const xRegister16& from, s16 imm ) const{ ImmStyle( to, from, imm ); } __forceinline void operator()( const xRegister16& to, const ModSibBase& from, s16 imm ) const { ImmStyle( to, from, imm ); } xImpl_iMul() {} };