diff --git a/3rdparty/wxWidgets/build/msw/wx_base_2008.vcproj b/3rdparty/wxWidgets/build/msw/wx_base_2008.vcproj index 8d32a73274..ba94108894 100644 --- a/3rdparty/wxWidgets/build/msw/wx_base_2008.vcproj +++ b/3rdparty/wxWidgets/build/msw/wx_base_2008.vcproj @@ -26,6 +26,7 @@ InheritedPropertySheets="..\..\..\3rdparty.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" + CharacterSet="1" WholeProgramOptimization="1" > @@ -112,7 +112,7 @@ @@ -122,7 +122,7 @@ @@ -136,7 +136,7 @@ @@ -146,7 +146,7 @@ @@ -156,7 +156,7 @@ diff --git a/3rdparty/wxWidgets/build/msw/wx_core_2008.vcproj b/3rdparty/wxWidgets/build/msw/wx_core_2008.vcproj index a51ddfc57b..2ca9b74a58 100644 --- a/3rdparty/wxWidgets/build/msw/wx_core_2008.vcproj +++ b/3rdparty/wxWidgets/build/msw/wx_core_2008.vcproj @@ -26,6 +26,7 @@ InheritedPropertySheets="..\..\..\3rdparty.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" + CharacterSet="1" > DaZ, FtZ, "chop" #define DEFAULT_sseVUMXCSR 0xffc0 //VU rounding > DaZ, FtZ, "chop" -#define CHECK_FRAMELIMIT (Config.Options&PCSX2_FRAMELIMIT_MASK) +//------------ Recompiler defines - Comment to disable a recompiler --------------- +// Yay! These work now! (air) ... almost (air) -#define CHECK_VU0REC (!g_Session.ForceDisableVU0rec && Config.Options&PCSX2_VU0REC) -#define CHECK_VU1REC (!g_Session.ForceDisableVU1rec && (Config.Options&PCSX2_VU1REC)) +#define SHIFT_RECOMPILE // Speed majorly reduced if disabled +#define BRANCH_RECOMPILE // Speed extremely reduced if disabled - more then shift + +// Disabling all the recompilers in this block is interesting, as it still runs at a reasonable rate. +// It also adds a few glitches. Really reminds me of the old Linux 64-bit version. --arcum42 +#define ARITHMETICIMM_RECOMPILE +#define ARITHMETIC_RECOMPILE +#define MULTDIV_RECOMPILE +#define JUMP_RECOMPILE +#define LOADSTORE_RECOMPILE +#define MOVE_RECOMPILE +#define MMI_RECOMPILE +#define MMI0_RECOMPILE +#define MMI1_RECOMPILE +#define MMI2_RECOMPILE +#define MMI3_RECOMPILE +#define FPU_RECOMPILE +#define CP0_RECOMPILE +#define CP2_RECOMPILE + +// You can't recompile ARITHMETICIMM without ARITHMETIC. +#ifndef ARITHMETIC_RECOMPILE +#undef ARITHMETICIMM_RECOMPILE +#endif + +#define EE_CONST_PROP // rec2 - enables constant propagation (faster) // Memory Card configuration, per slot. struct McdConfig @@ -133,7 +161,15 @@ public: int PsxType; int Patch; int CustomFps; - int Hacks; + struct Hacks_t { + int EECycleRate; + bool IOPCycleDouble; + bool WaitCycleExt; + bool INTCSTATSlow; + int VUCycleSteal; + bool IdleLoopFF; + bool ESCExits; // this is a hack!? + } Hacks; int GameFixes; int CustomFrameSkip; int CustomConsecutiveFrames; diff --git a/pcsx2/AsciiString.cpp b/pcsx2/AsciiString.cpp new file mode 100644 index 0000000000..c1c101abc5 --- /dev/null +++ b/pcsx2/AsciiString.cpp @@ -0,0 +1,251 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" + +#include "SafeArray.h" +#include "AsciiString.h" + +using namespace Threading; + +namespace AsciiStringAllocator +{ + struct PrivateHandle + { + AsciiStringAllocatorHandle* PublicHandle; + }; + + static const uint UnitLength = 256; + static const uint UnitLengthMask = UnitLength-1; + + static const uint AllocationCleanupThreshold = 256; + static const uint InitialBufferLength = 0x100000; // 1MB! + static const AsciiStringAllocatorHandle* PublicHandleAllocated = (AsciiStringAllocatorHandle*)1; + + static uint m_release_counter( 0 ); + + static SafeArray m_PrivateHandles( InitialBufferLength / UnitLength ); + static SafeArray m_StringBuffer( InitialBufferLength ); + + static int m_NextPrivateHandle; + static int m_NextBufferIndex; + + static MutexLock m_Lock; + + static char* GetPtr( const AsciiStringAllocatorHandle& handle ) + { + return &m_StringBuffer[ m_PrivateHandles[ handle.Index ] ]; + } + + static void DoCompact() + { + if( m_release_counter < AllocationCleanupThreshold ) return; + + ScopedLock locker( m_Lock ); + int handlecount = m_PrivateHandles.GetLength(); + int writepos = 0; + for( int readpos=0; readposIndex = cwpos; + + // todo: replace this with a hardcoded XMM inline copy of 256 bytes. :) + + memcpy_fast( + m_StringBuffer.GetPtr(cwpos*UnitLength), + m_StringBuffer.GetPtr(readpos*UnitLength), + UnitLength + ); + } + } + } + + void New( AsciiStringAllocatorHandle& dest, int length ) + { + int numblocks = (length / UnitLength)+1; + length = numblocks * UnitLength; + + ScopedLock locker( m_Lock ); + AsciiStringAllocatorHandle retval( m_NextPrivateHandle, length ); + m_PrivateHandles[m_NextPrivateHandle++].PublicHandle = &dest; + for( int p=numblocks-1; p; --p, ++m_NextPrivateHandle ) + m_PrivateHandles[m_NextPrivateHandle].PublicHandle = PublicHandleAllocated; + + m_StringBuffer.MakeRoomFor( m_NextPrivateHandle * UnitLength ); + + return retval; + } + + bool Grow( AsciiStringAllocatorHandle& dest ) + { + ScopedLock locker( m_lock ); + + if( m_PrivateHandles[m_NextPrivateHandle].PublicHandle == NULL ) + { + m_PrivateHandles[m_NextPrivateHandle].PublicHandle = PublicHandleAllocated; + return true; + } + return false; + } + + // releases the block without clearing the handle structure information + // and without doing a block compact check. + static int _release( AsciiStringAllocatorHandle& handle ) + { + const int numblocks = handle.Length / UnitLength; + const int endblock = handle.Index + numblocks; + + ScopedLock locker( m_Lock ); + for( int i=handle.Index; i= AllocationCleanupThreshold ) + DoCleanup(); + } + + // Allocates a new handle and copies the old string contents to the new reserve. + void Reallocate( AsciiStringAllocatorHandle& handle, int newsize ) + { + int newblocks = (newsize / UnitLength)+1; + newsize = newblocks * UnitLength; + + ScopedLock locker( m_Lock ); + _release( handle ); + + m_StringBuffer.MakeRoomFor( m_NextPrivateHandle + newblocks ); + if( m_NextPrivateHandle != handle.Index ) + { + memcpy_fast( + m_StringBuffer.GetPtr( m_NextPrivateHandle ), + m_StringBuffer(handle.Index), + handle.Length + ); + handle.Index = m_NextPrivateHandle; + } + handle.Length = newsize; + } +}; + +AsciiStringAllocatorHandle::GetPtr() const +{ + return AsciiStringAllocator::GetPtr( *this ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// + +AsciiString::AsciiString( int length_reserve ) +{ + AsciiStringAllocator::New( m_MemoryHandle, len ) +} + +const wxCharBuffer AsciiString::mb_str() const +{ + // use wxCharBuffer here for sake of safety, since parallel string operations could + // result in the pointer to this string becoming invalid. + ScopedLock locker( AsciiStringAllocator::m_Lock ); + return wxCharBuffer( AsciiStringAllocator::GetPtr( m_MemoryHandle ) ); +} + +AsciiStringLock::operator char*() +{ + return m_buffer; +} + +char& AsciiStringLock::operator[]( int idx ) +{ + return m_buffer[idx]; +} + +char AsciiStringLock::GetCharAt( int idx ) const +{ + return m_buffer[idx]; +} + +char* AsciiStringLock::GetPtr() +{ + return m_buffer; +} + +AsciiStringLock::AsciiStringLock( AsciiString& str ) : + m_string( str ) +{ + m_string.Lock(); +} + +AsciiStringLock::~AsciiStringLock() +{ + m_string.Unlock(); +} + +AsciiStringLock::operator char*() +{ + AsciiStringAllocator::GetPtr( m_handle ); +} + +AsciiString AsciiString::operator+( const AsciiString& right ) +{ + int len = GetLength() + right.GetLength(); + + AsciiString dest( len+1 ); + + char* lockptr = m_MemoryHandle.GetPtr(); + memcpy_fast( lockptr, GetBufferPtr(), GetLength() ); + memcpy_fast( lockptr+GetLength(), right.GetBufferPtr(), right.GetLength() ); + lockptr[dest.GetLength()] = 0; +} + +AsciiString& AsciiString::Append( const AsciiString& src ) +{ + int needlen = src.GetLength() + GetLength()+1; + if( needlen >= m_MemoryHandle.Length ) + { + // The new string is too large -- looks like we're going to need to allocate + // a larger block. We try and use Grow first, if the appending string is very + // short (it sometimes saves the need to copy the block to a new location) + + if( src.GetLength() >= AsciiStringAllocator::UnitLength || !AsciiStringAllocator::Grow( m_MemoryHandle ) ) + AsciiStringAllocator::Reallocate( m_MemoryHandle, needlen ); + } + + char* lockptr = m_MemoryHandle.GetPtr(); + memcpy_fast( lockptr+GetLength(), src.GetBufferPtr(), src.GetLength() ); + lockptr[GetLength()] = 0; +} diff --git a/pcsx2/AsciiString.h b/pcsx2/AsciiString.h new file mode 100644 index 0000000000..8309043ac5 --- /dev/null +++ b/pcsx2/AsciiString.h @@ -0,0 +1,84 @@ +/* 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 + +class AsciiStringAllocatorHandle +{ +public: + const int Index; + const int Length; + +public: + AsciiStringAllocatorHandle( int handle, int len ) : + Index( handle ), + Length( len ) + { + } + + char* GetPtr() const; + void Lock(); + void Unlock(); +}; + +class AsciiString +{ +protected: + AsciiStringAllocatorHandle m_MemoryHandle; + int m_Length; + +public: + AsciiString(); + AsciiString( AsciiString& copycat ); + AsciiString( const char* src ); + AsciiString( const char* src, int length ); + AsciiString( const char* src, int startpos, int length ); + AsciiString( int length_reserve ); + + const char* mb_str() const; + char mb_str_unsafe(); + + int GetLength() const + { + return m_Length; + } + + AsciiString operator+( const AsciiString& right ); + AsciiString& Append( const AsciiString& src ); + + void Lock(); + void Unlock(); +}; + + +class AsciiStringLock +{ +protected: + AsciiString& m_string; + char* m_buffer; + +public: + AsciiStringLock( const AsciiStringAllocatorHandle& handle ); + ~AsciiStringLock(); + + char* GetPtr(); + char GetCharAt( int idx ) const; + operator char*(); + char& operator[]( int idx ); + const char& operator[]( int idx ) const { return GetCharAt( idx ); } +}; \ No newline at end of file diff --git a/pcsx2/CDVD.cpp b/pcsx2/CDVD.cpp index 30d527bfc1..14c7bc98ca 100644 --- a/pcsx2/CDVD.cpp +++ b/pcsx2/CDVD.cpp @@ -19,6 +19,7 @@ #include "PrecompiledHeader.h" #include +#include #include "IopCommon.h" #include "CDVDiso.h" @@ -240,12 +241,12 @@ FILE *_cdvdOpenMechaVer() { FILE* fd; // get the name of the bios file - string Bios( Path::Combine( Config.BiosDir, Config.Bios ) ); // use the bios filename to get the name of the mecha ver file - // [TODO] : Upgrade this to use std::string! + // [TODO] : Upgrade this to use wxString! - strcpy(file, Bios.c_str()); + strcpy(file, g_Conf.Files.Bios().ToAscii().data() ); + ptr = file; i = (int)strlen(file); while (i > 0) { if (ptr[i] == '.') break; i--; } ptr[i+1] = '\0'; @@ -254,11 +255,14 @@ FILE *_cdvdOpenMechaVer() { // if file doesnt exist, create empty one fd = fopen(file, "r+b"); if (fd == NULL) { - Console::Notice("MEC File Not Found , Creating Blank File"); + Console::Notice( "MEC File Not Found, Creating Blank File..." ); fd = fopen(file, "wb"); - if (fd == NULL) { - Msgbox::Alert("_cdvdOpenMechaVer: Error creating %s", params file); - exit(1); + if (fd == NULL) + { + Console::Error( "\tMEC File Creation failed!" ); + throw Exception::CreateStream( file ); + //Msgbox::Alert( "_cdvdOpenMechaVer: Error creating %s", params file); + //exit(1); } fputc(0x03, fd); fputc(0x06, fd); @@ -285,12 +289,11 @@ FILE *_cdvdOpenNVM() { FILE* fd; // get the name of the bios file - string Bios( Path::Combine( Config.BiosDir, Config.Bios ) ); // use the bios filename to get the name of the nvm file // [TODO] : Upgrade this to use std::string! - strcpy( file, Bios.c_str() ); + strcpy( file, g_Conf.Files.Bios().ToAscii().data() ); ptr = file; i = (int)strlen(file); while (i > 0) { if (ptr[i] == '.') break; i--; } ptr[i+1] = '\0'; @@ -301,9 +304,11 @@ FILE *_cdvdOpenNVM() { if (fd == NULL) { Console::Notice("NVM File Not Found , Creating Blank File"); fd = fopen(file, "wb"); - if (fd == NULL) { - Msgbox::Alert("_cdvdOpenNVM: Error creating %s", params file); - exit(1); + if (fd == NULL) + { + throw Exception::CreateStream( file ); + //Msgbox::Alert("_cdvdOpenNVM: Error creating %s", params file); + //exit(1); } for (i=0; i<1024; i++) fputc(0, fd); } @@ -470,7 +475,7 @@ s32 cdvdWriteConfig(const u8* config) void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { - char str[g_MaxPath]; + wxString fname; int numbers; int letters; unsigned int key_0_3; @@ -479,7 +484,9 @@ void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key) { char exeName[12]; // get main elf name - GetPS2ElfName(str); + GetPS2ElfName(fname); + const wxCharBuffer crap( fname.ToAscii() ); + const char* str = crap.data(); sprintf(exeName, "%c%c%c%c%c%c%c%c%c%c%c",str[8],str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16],str[17],str[18]); DevCon::Notice("exeName = %s", params &str[8]); @@ -693,7 +700,7 @@ __forceinline void cdvdGetDiskType() cdvd.Type = CDVDgetDiskType(); if (cdvd.Type == CDVD_TYPE_PS2CD) // && needReset == 1) { - char str[g_MaxPath]; + wxString str; if (GetPS2ElfName(str) == 1) { cdvd.Type = CDVD_TYPE_PSCD; @@ -768,12 +775,18 @@ void cdvdReset() cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM ); // any random valid date will do - cdvd.RTC.hour = 1; - cdvd.RTC.day = 25; - cdvd.RTC.month = 5; - cdvd.RTC.year = 7; //2007 - - cdvdSetSystemTime( cdvd ); + //cdvd.RTC.hour = 1; + //cdvd.RTC.day = 25; + //cdvd.RTC.month = 5; + //cdvd.RTC.year = 7; //2007 + + wxDateTime curtime( wxDateTime::GetTimeNow() ); + cdvd.RTC.second = (u8)curtime.GetSecond(); + cdvd.RTC.minute = (u8)curtime.GetMinute(); + cdvd.RTC.hour = (u8)(curtime.GetHour()+1) % 24; + cdvd.RTC.day = (u8)curtime.GetDay(); + cdvd.RTC.month = (u8)curtime.GetMonth(); + cdvd.RTC.year = (u8)(curtime.GetYear() - 2000); } struct Freeze_v10Compat @@ -805,7 +818,7 @@ void cdvdNewDiskCB() { cdvd.Type = CDVDgetDiskType(); if(cdvd.Type == CDVD_TYPE_PS2CD) { - char str[g_MaxPath]; + wxString str; if(GetPS2ElfName(str) == 1) { cdvd.Type = CDVD_TYPE_PSCD; } // ENDIF- Does the SYSTEM.CNF file only say "BOOT="? PS1 CD then. diff --git a/pcsx2/CDVD.h b/pcsx2/CDVD.h index 9eec464375..2fd5311ea6 100644 --- a/pcsx2/CDVD.h +++ b/pcsx2/CDVD.h @@ -141,7 +141,4 @@ void cdvdWrite17(u8 rt); void cdvdWrite18(u8 rt); void cdvdWrite3A(u8 rt); -// Platform dependent system time assignment (see WinMisc / LnxMisc) -extern void cdvdSetSystemTime( cdvdStruct& setme ); - #endif /* __CDVD_H__ */ diff --git a/pcsx2/COP0.cpp b/pcsx2/COP0.cpp index 49e16e7ee8..181636f78b 100644 --- a/pcsx2/COP0.cpp +++ b/pcsx2/COP0.cpp @@ -308,8 +308,8 @@ namespace COP0 { void MFC0() { // Note on _Rd_ Condition 9: CP0.Count should be updated even if _Rt_ is 0. - if( (_Rd_ != 9) && !_Rt_ ) return; - if(_Rd_ != 9) { COP0_LOG("%s", disR5900Current.getCString() ); } + if ((_Rd_ != 9) && !_Rt_ ) return; + if (_Rd_ != 9) { COP0_LOG("%s", disR5900Current.getCString() ); } //if(bExecBIOS == FALSE && _Rd_ == 25) Console::WriteLn("MFC0 _Rd_ %x = %x", params _Rd_, cpuRegs.CP0.r[_Rd_]); switch (_Rd_) @@ -412,30 +412,37 @@ int CPCOND0() { //#define CPCOND0 1 -#define BC0(cond) \ +/*#define BC0(cond) \ if (CPCOND0() cond) { \ intDoBranch(_BranchTarget_); \ - } + }*/ void BC0F() { - BC0(== 0); + if (CPCOND0() == 0) intDoBranch(_BranchTarget_); } void BC0T() { - BC0(== 1); + if (CPCOND0() == 1) intDoBranch(_BranchTarget_); } -#define BC0L(cond) \ +/*#define BC0L(cond) \ if (CPCOND0() cond) { \ intDoBranch(_BranchTarget_); \ - } else cpuRegs.pc+= 4; - + } else cpuRegs.pc+= 4;*/ + void BC0FL() { - BC0L(== 0); + if (CPCOND0() == 0) + intDoBranch(_BranchTarget_); + else + cpuRegs.pc+= 4; + } void BC0TL() { - BC0L(== 1); + if (CPCOND0() == 1) + intDoBranch(_BranchTarget_); + else + cpuRegs.pc+= 4; } void TLBR() { @@ -482,8 +489,7 @@ void TLBWR() { void TLBP() { int i; - - + union { struct { u32 VPN2:19; @@ -494,13 +500,13 @@ void TLBP() { u32 u; } EntryHi32; - EntryHi32.u=cpuRegs.CP0.n.EntryHi; + EntryHi32.u = cpuRegs.CP0.n.EntryHi; cpuRegs.CP0.n.Index=0xFFFFFFFF; for(i=0;i<48;i++){ - if(tlb[i].VPN2==((~tlb[i].Mask)&(EntryHi32.s.VPN2)) - &&((tlb[i].G&1)||((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { - cpuRegs.CP0.n.Index=i; + if (tlb[i].VPN2 == ((~tlb[i].Mask) & (EntryHi32.s.VPN2)) + && ((tlb[i].G&1) || ((tlb[i].ASID & 0xff) == EntryHi32.s.ASID))) { + cpuRegs.CP0.n.Index = i; break; } } diff --git a/pcsx2/COP2.cpp b/pcsx2/COP2.cpp index d57df3915b..e227ea3f42 100644 --- a/pcsx2/COP2.cpp +++ b/pcsx2/COP2.cpp @@ -25,10 +25,6 @@ #include "VUops.h" #include "VUmicro.h" -//namespace R5900 { -//namespace Interpreter { -//namespace OpcodeImpl{ - using namespace R5900; using namespace R5900::Interpreter; @@ -85,5 +81,3 @@ void BC2TL() cpuRegs.pc+= 4; } } - -//}}} diff --git a/pcsx2/CdRom.cpp b/pcsx2/CdRom.cpp index 8cf2359a4f..03681db115 100644 --- a/pcsx2/CdRom.cpp +++ b/pcsx2/CdRom.cpp @@ -937,6 +937,34 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr) { psxDmaInterrupt(3); } +#ifdef ENABLE_NEW_IOPDMA +s32 cdvdDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +{ + // hacked up from the code above + + if (cdr.Readed == 0) + { + //CDR_LOG("*** DMA 3 *** NOT READY"); + wordsProcessed = 0; + return 10000; + } + + memcpy_fast(data, cdr.pTransfer, wordsLeft); + //psxCpu->Clear(madr, cdsize/4); + cdr.pTransfer+=wordsLeft; + *wordsProcessed = wordsLeft; + + Console::Status("New IOP DMA handled CDVD DMA: channel %d, data %p, remaining %08x, processed %08x.", params channel,data,wordsLeft, *wordsProcessed); + return 0; +} + +void cdvdDmaInterrupt(s32 channel) +{ + cdrInterrupt(); +} + +#endif + void cdrReset() { memzero_obj(cdr); cdr.CurTrack=1; diff --git a/pcsx2/Common.h b/pcsx2/Common.h index 1461bb83bd..4daeee5663 100644 --- a/pcsx2/Common.h +++ b/pcsx2/Common.h @@ -29,6 +29,8 @@ #define PCSX2_VERSION "(beta)" +#include "System.h" + #include "Plugins.h" #include "SaveState.h" @@ -40,7 +42,4 @@ #include "Elfheader.h" #include "Patch.h" -#include "System.h" -#include "Pcsx2Config.h" - #endif /* __COMMON_H__ */ diff --git a/pcsx2/Config.h b/pcsx2/Config.h new file mode 100644 index 0000000000..664b38ffa1 --- /dev/null +++ b/pcsx2/Config.h @@ -0,0 +1,190 @@ +/* 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 + +class IniInterface; + + +////////////////////////////////////////////////////////////////////////////////////////// +// Pcsx2 Application Configuration. +// +// [TODO] : Rename this once we get to the point where the old Pcsx2Config stuff isn't in +// the way anymore. :) +// +class AppConfig +{ +public: + struct ConsoleLogOptions + { + bool Visible; + // if true, DisplayPos is ignored and the console is automatically docked to the main window. + bool AutoDock; + // Display position used if AutoDock is false (ignored otherwise) + wxPoint DisplayPosition; + wxSize DisplaySize; + + void LoadSave( IniInterface& conf ); + }; + + struct FolderOptions + { + wxDirName Plugins; + wxDirName Bios; + wxDirName Snapshots; + wxDirName Savestates; + wxDirName MemoryCards; + wxDirName Dumps; + }; + + struct FilenameOptions + { + wxFileName Bios; + wxFileName CDVD; + wxFileName GS; + wxFileName PAD1; + wxFileName PAD2; + wxFileName SPU2; + wxFileName USB; + wxFileName FW; + wxFileName DEV9; + }; + + // Options struct for each memory card. + struct McdOptions + { + wxFileName Filename; // user-configured location of this memory card + bool Enabled; // memory card enabled (if false, memcard will not show up in-game) + }; + + struct McdSysOptions + { + McdOptions Mcd[2]; + bool EnableNTFS; // enables automatic ntfs compression of memory cards (Win32 only) + bool EnableEjection; // enables simulated ejection of memory cards when loading savestates + + void LoadSave( IniInterface& conf ); + }; + + + struct CpuRecompilerOptions + { + struct + { + bool + Enabled:1, // universal toggle for the profiler. + RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented] + RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented] + RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented] + + } Profiler; + + struct + { + bool + EnableEE:1, + EnableIOP:1, + EnableVU0:1, + EnableVU1:1; + + } Recompiler; + + void LoadSave( IniInterface& conf ); + }; + + struct VideoOptions + { + bool MultithreadGS; // Uses the multithreaded GS interface. + bool closeOnEsc; // Closes the GS/Video port on escape (good for fullscreen activity) + bool UseFramelimiter; + + int RegionMode; // 0=NTSC and 1=PAL + int CustomFps; + int CustomFrameSkip; + int CustomConsecutiveFrames; + int CustomConsecutiveSkip; + + void LoadSave( IniInterface& conf ); + }; + + struct GamefixOptions + { + bool + VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. + VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu. + FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again). + FpuMulHack:1; // Fix for Tales of Destiny hangs. + + void LoadSave(); + }; + + struct SpeedhackOptions + { + int + EECycleRate:3, // EE cyclerate selector (1.0, 1.5, 2.0, 3.0) + IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate + ExtWaitcycles:1, // enables extended waitcycles duration + IntcStat:1; // tells Pcsx2 to fast-forward through intc_stat waits. + + void LoadSave( IniInterface& conf ); + }; + + // Helper functions for returning full pathnames of various Folders and files + struct FullpathHelpers + { + FullpathHelpers( const AppConfig& conf ) : m_conf( conf ) {} + + const AppConfig& m_conf; + + wxString Bios() const; + wxString CDVD() const; + wxString GS() const; + wxString PAD1() const; + wxString PAD2() const; + wxString SPU2() const; + wxString DEV9() const; + wxString USB() const; + wxString FW() const; + + wxString Mcd( uint mcdidx ) const; + }; + +public: + AppConfig() : Files( *this ) + { + } + + FullpathHelpers Files; + + wxPoint MainGuiPosition; + bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console + + CpuRecompilerOptions Cpu; + SpeedhackOptions Speedhacks; + GamefixOptions Gamefixes; + VideoOptions Video; + ConsoleLogOptions ConLogBox; + FolderOptions Folders; + FilenameOptions BaseFilenames; + McdSysOptions MemoryCards; + +public: + void LoadSave( IniInterface& ini ); +}; + +extern AppConfig g_Conf; diff --git a/pcsx2/Console.cpp b/pcsx2/Console.cpp index 19c7366b74..ff466c52fb 100644 --- a/pcsx2/Console.cpp +++ b/pcsx2/Console.cpp @@ -36,6 +36,7 @@ namespace Console MutexLock m_writelock; std::string m_format_buffer; + // ------------------------------------------------------------------------ void __fastcall SetTitle( const wxString& title ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -43,6 +44,7 @@ namespace Console FrameHandle->SetTitle( title ); } + // ------------------------------------------------------------------------ void __fastcall SetColor( Colors color ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -57,6 +59,7 @@ namespace Console FrameHandle->ClearColor(); } + // ------------------------------------------------------------------------ bool Newline() { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -67,6 +70,7 @@ namespace Console return false; } + // ------------------------------------------------------------------------ bool __fastcall Write( const char* fmt ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -91,8 +95,34 @@ namespace Console return false; } - // Writes an unformatted string of text to the console (fast!) - // A newline is automatically appended. + // ------------------------------------------------------------------------ + bool __fastcall Write( const wxString& fmt ) + { + ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); + if( FrameHandle != NULL ) + FrameHandle->Write( fmt ); + + wxCharBuffer jones( fmt.ToAscii() ); + fwrite( fmt, 1, strlen( jones.data() ), emuLog ); + return false; + } + + bool __fastcall Write( Colors color, const wxString& fmt ) + { + ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); + if( FrameHandle != NULL ) + { + FrameHandle->SetColor( color ); + FrameHandle->Write( fmt ); + FrameHandle->ClearColor(); + } + + wxCharBuffer jones( fmt.ToAscii() ); + fwrite( fmt, 1, strlen( jones.data() ), emuLog ); + return false; + } + + // ------------------------------------------------------------------------ bool __fastcall WriteLn( const char* fmt ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -106,8 +136,6 @@ namespace Console return false; } - // Writes an unformatted string of text to the console (fast!) - // A newline is automatically appended. bool __fastcall WriteLn( Colors color, const char* fmt ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -123,6 +151,38 @@ namespace Console return false; } + // ------------------------------------------------------------------------ + bool __fastcall WriteLn( const wxString& fmt ) + { + ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); + if( FrameHandle != NULL ) + { + FrameHandle->Write( fmt.c_str() ); + FrameHandle->Newline(); + } + + wxCharBuffer jones( fmt.ToAscii() ); + fputs( jones.data(), emuLog ); + return false; + } + + bool __fastcall WriteLn( Colors color, const wxString& fmt ) + { + ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); + if( FrameHandle != NULL ) + { + FrameHandle->SetColor( color ); + FrameHandle->Write( fmt ); + FrameHandle->Newline(); + FrameHandle->ClearColor(); + } + + wxCharBuffer jones( fmt.ToAscii() ); + fputs( jones.data(), emuLog ); + return false; + } + + // ------------------------------------------------------------------------ __forceinline void __fastcall _WriteLn( Colors color, const char* fmt, va_list args ) { ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame(); @@ -147,12 +207,13 @@ namespace Console if( color == Color_Red || color == Color_Yellow ) fputs( cstr, stderr ); // log notices and errors to stderr - wxASSERT_MSG( 0, cstr ); + wxASSERT_MSG_A( 0, cstr ); } fputs( cstr, emuLog ); } + // ------------------------------------------------------------------------ bool Write( const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -184,6 +245,7 @@ namespace Console return false; } + // ------------------------------------------------------------------------ bool WriteLn( const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -198,7 +260,7 @@ namespace Console return false; } - // Writes a line of colored text to the console, with automatic newline appendage. + // ------------------------------------------------------------------------ bool WriteLn( Colors color, const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -210,8 +272,7 @@ namespace Console return false; } - // Displays a message in the console with red emphasis. - // Newline is automatically appended. + // ------------------------------------------------------------------------ bool Error( const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -223,8 +284,7 @@ namespace Console return false; } - // Displays a message in the console with yellow emphasis. - // Newline is automatically appended. + // ------------------------------------------------------------------------ bool Notice( const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -236,8 +296,7 @@ namespace Console return false; } - // Displays a message in the console with green emphasis. - // Newline is automatically appended. + // ------------------------------------------------------------------------ bool Status( const char* fmt, VARG_PARAM dummy, ... ) { varg_assert(); @@ -249,57 +308,57 @@ namespace Console return false; } - // Displays a message in the console with red emphasis. - // Newline is automatically appended. + // ------------------------------------------------------------------------ bool __fastcall Error( const char* fmt ) { WriteLn( Color_Red, fmt ); return false; } - // Displays a message in the console with yellow emphasis. - // Newline is automatically appended. bool __fastcall Notice( const char* fmt ) { WriteLn( Color_Yellow, fmt ); return false; } - // Displays a message in the console with green emphasis. - // Newline is automatically appended. bool __fastcall Status( const char* fmt ) { WriteLn( Color_Green, fmt ); return false; } + // ------------------------------------------------------------------------ + bool __fastcall Error( const wxString& src ) + { + WriteLn( Color_Red, src ); + return false; + } + + bool __fastcall Notice( const wxString& src ) + { + WriteLn( Color_Yellow, src ); + return false; + } + + bool __fastcall Status( const wxString& src ) + { + WriteLn( Color_Green, src ); + return false; + } + } namespace Msgbox { - bool Alert(const char* text) + bool Alert( const wxString& text ) { - wxMessageBox( text, "Pcsx2 Message", wxOK, wxGetApp().GetTopWindow() ); + wxMessageBox( text, wxT("Pcsx2 Message"), wxOK, wxGetApp().GetTopWindow() ); return false; } - bool Alert(const char* fmt, VARG_PARAM dummy, ...) + bool OkCancel( const wxString& text ) { - va_list list; - va_start(list, dummy); - Alert( vfmt_string( fmt, list ).c_str() ); - va_end(list); - - return false; - } - - bool OkCancel( const char* fmt, VARG_PARAM dummy, ... ) - { - va_list list; - va_start(list, dummy); - int result = wxMessageBox( vfmt_string( fmt, list ), "Pcsx2 Message", wxOK | wxCANCEL, wxGetApp().GetTopWindow() ); - va_end(list); - - return result == wxOK; + int result = wxMessageBox( text, wxT("Pcsx2 Message"), wxOK | wxCANCEL, wxGetApp().GetTopWindow() ); + return result == wxOK; } } \ No newline at end of file diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index a58ec1d0a3..b9b9a7c9ed 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -164,7 +164,7 @@ struct vSyncTimingInfo static vSyncTimingInfo vSyncInfo; -static __forceinline void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scansPerFrame ) +static void vSyncInfoCalc( vSyncTimingInfo* info, u32 framesPerSecond, u32 scansPerFrame ) { // Important: Cannot use floats or doubles here. The emulator changes rounding modes // depending on user-set speedhack options, and it can break float/double code @@ -270,8 +270,6 @@ u32 UpdateVSyncRate() return (u32)m_iTicks; } -extern u32 vu0time; - void frameLimitReset() { m_iStart = GetCPUTicks(); @@ -282,13 +280,13 @@ void frameLimitReset() // See the GS FrameSkip function for details on why this is here and not in the GS. static __forceinline void frameLimit() { + if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_NORMAL ) return; + if( Config.CustomFps >= 999 ) return; // means the user would rather just have framelimiting turned off... + s64 sDeltaTime; u64 uExpectedEnd; u64 iEnd; - if( CHECK_FRAMELIMIT == PCSX2_FRAMELIMIT_NORMAL ) return; - if( Config.CustomFps >= 999 ) return; // means the user would rather just have framelimiting turned off... - uExpectedEnd = m_iStart + m_iTicks; iEnd = GetCPUTicks(); @@ -465,7 +463,7 @@ __forceinline bool rcntUpdate_vSync() return false; } -static __forceinline void __fastcall _cpuTestTarget( int i ) +static __forceinline void _cpuTestTarget( int i ) { if (counters[i].count < counters[i].target) return; @@ -538,7 +536,7 @@ __forceinline bool rcntUpdate() return retval; } -static void _rcntSetGate( int index ) +static __forceinline void _rcntSetGate( int index ) { if (counters[index].mode.EnableGate) { @@ -563,7 +561,7 @@ static void _rcntSetGate( int index ) } // mode - 0 means hblank source, 8 means vblank source. -void __fastcall rcntStartGate(bool isVblank, u32 sCycle) +__forceinline void rcntStartGate(bool isVblank, u32 sCycle) { int i; @@ -624,7 +622,7 @@ void __fastcall rcntStartGate(bool isVblank, u32 sCycle) } // mode - 0 means hblank signal, 8 means vblank signal. -void __fastcall rcntEndGate(bool isVblank , u32 sCycle) +__forceinline void rcntEndGate(bool isVblank , u32 sCycle) { int i; @@ -665,7 +663,7 @@ void __fastcall rcntEndGate(bool isVblank , u32 sCycle) // rcntUpdate, since we're being called from there anyway. } -void __fastcall rcntWmode(int index, u32 value) +__forceinline void rcntWmode(int index, u32 value) { if(counters[index].mode.IsCounting) { if(counters[index].mode.ClockSource != 0x3) { @@ -696,7 +694,7 @@ void __fastcall rcntWmode(int index, u32 value) _rcntSet( index ); } -void __fastcall rcntWcount(int index, u32 value) +__forceinline void rcntWcount(int index, u32 value) { EECNT_LOG("EE Counter[%d] writeCount = %x, oldcount=%x, target=%x", index, value, counters[index].count, counters[index].target ); @@ -722,7 +720,7 @@ void __fastcall rcntWcount(int index, u32 value) _rcntSet( index ); } -void __fastcall rcntWtarget(int index, u32 value) +__forceinline void rcntWtarget(int index, u32 value) { EECNT_LOG("EE Counter[%d] writeTarget = %x", index, value); @@ -738,13 +736,13 @@ void __fastcall rcntWtarget(int index, u32 value) _rcntSet( index ); } -void __fastcall rcntWhold(int index, u32 value) +__forceinline void rcntWhold(int index, u32 value) { EECNT_LOG("EE Counter[%d] Hold Write = %x", index, value); counters[index].hold = value; } -u32 __fastcall rcntRcount(int index) +__forceinline u32 rcntRcount(int index) { u32 ret; @@ -759,7 +757,7 @@ u32 __fastcall rcntRcount(int index) return ret; } -u32 __fastcall rcntCycle(int index) +__forceinline u32 rcntCycle(int index) { if (counters[index].mode.IsCounting && (counters[index].mode.ClockSource != 0x3)) return counters[index].count + ((cpuRegs.cycle - counters[index].sCycleT) / counters[index].rate); diff --git a/pcsx2/Counters.h b/pcsx2/Counters.h index 6e20dda0c2..5333bcb111 100644 --- a/pcsx2/Counters.h +++ b/pcsx2/Counters.h @@ -139,14 +139,14 @@ extern bool rcntUpdate_vSync(); extern bool rcntUpdate(); extern void rcntInit(); -extern void __fastcall rcntStartGate(bool mode, u32 sCycle); -extern void __fastcall rcntEndGate(bool mode, u32 sCycle); -extern void __fastcall rcntWcount(int index, u32 value); -extern void __fastcall rcntWmode(int index, u32 value); -extern void __fastcall rcntWtarget(int index, u32 value); -extern void __fastcall rcntWhold(int index, u32 value); -extern u32 __fastcall rcntRcount(int index); -extern u32 __fastcall rcntCycle(int index); +extern void rcntStartGate(bool mode, u32 sCycle); +extern void rcntEndGate(bool mode, u32 sCycle); +extern void rcntWcount(int index, u32 value); +extern void rcntWmode(int index, u32 value); +extern void rcntWtarget(int index, u32 value); +extern void rcntWhold(int index, u32 value); +extern u32 rcntRcount(int index); +extern u32 rcntCycle(int index); u32 UpdateVSyncRate(); void frameLimitReset(); diff --git a/pcsx2/DebugTools/Debug.h b/pcsx2/DebugTools/Debug.h index c35dc2f03b..3f965fe000 100644 --- a/pcsx2/DebugTools/Debug.h +++ b/pcsx2/DebugTools/Debug.h @@ -216,6 +216,8 @@ extern bool SrcLog_GPU( const char* fmt, ... ); #define MEMCARDS_LOG 0&& #endif +//#define VIFUNPACKDEBUG //enable unpack debugging output + #ifdef VIFUNPACKDEBUG #define VIFUNPACK_LOG VIF_LOG #else diff --git a/pcsx2/DebugTools/DisR5900asm.cpp b/pcsx2/DebugTools/DisR5900asm.cpp index ab4c098408..4a3172a426 100644 --- a/pcsx2/DebugTools/DisR5900asm.cpp +++ b/pcsx2/DebugTools/DisR5900asm.cpp @@ -606,7 +606,7 @@ void (*COP2SPECIAL2PrintTable[128])( string& output ) = //**************************TABLES CALLS*********************** -void disR5900Fasm(string& output, u32 code, u32 pc) +void disR5900Fasm( string& output, u32 code, u32 pc ) { string dbuf; char obuf[48]; diff --git a/pcsx2/Dump.cpp b/pcsx2/Dump.cpp new file mode 100644 index 0000000000..6652cd14b1 --- /dev/null +++ b/pcsx2/Dump.cpp @@ -0,0 +1,303 @@ +/* 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 + */ + +//////////////////////////////////////////////////// +#include "PrecompiledHeader.h" +#include "IopCommon.h" +#include "Counters.h" +#include "iCore.h" +#include "iR5900.h" +#include "IPU/IPU.h" + +using namespace R5900; +// fixme: currently should not be uncommented. +//#define TEST_BROKEN_DUMP_ROUTINES + +#ifdef TEST_BROKEN_DUMP_ROUTINES +//extern u32 psxdump; +//extern int rdram_devices; // put 8 for TOOL and 2 for PS2 and PSX +//extern int rdram_sdevid; +extern tIPU_BP g_BP; + +#define VF_VAL(x) ((x==0x80000000)?0:(x)) +#endif + + +// iR5900-32.cpp +extern EEINST* s_pInstCache; +extern u32 s_nEndBlock; // what pc the current block ends + + +void iDumpPsxRegisters(u32 startpc, u32 temp) +{ +// [TODO] fixme : thie code is broken and has no labels. Needs a rewrite to be useful. + +#ifdef TEST_BROKEN_DUMP_ROUTINES + int i; + const char* pstr = temp ? "t" : ""; + + // fixme: PSXM doesn't exist any more. + //__Log("%spsxreg: %x %x ra:%x k0: %x %x", pstr, startpc, psxRegs.cycle, psxRegs.GPR.n.ra, psxRegs.GPR.n.k0, *(int*)PSXM(0x13c128)); + + for(i = 0; i < 34; i+=2) __Log("%spsx%s: %x %x", pstr, disRNameGPR[i], psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); + + __Log("%scycle: %x %x %x; counters %x %x", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, + psxNextsCounter, psxNextCounter); + + __Log("psxdma%d c%x b%x m%x t%x", 2, HW_DMA2_CHCR, HW_DMA2_BCR, HW_DMA2_MADR, HW_DMA2_TADR); + __Log("psxdma%d c%x b%x m%x", 3, HW_DMA3_CHCR, HW_DMA3_BCR, HW_DMA3_MADR); + __Log("psxdma%d c%x b%x m%x t%x", 4, HW_DMA4_CHCR, HW_DMA4_BCR, HW_DMA4_MADR, HW_DMA4_TADR); + __Log("psxdma%d c%x b%x m%x", 6, HW_DMA6_CHCR, HW_DMA6_BCR, HW_DMA6_MADR); + __Log("psxdma%d c%x b%x m%x", 7, HW_DMA7_CHCR, HW_DMA7_BCR, HW_DMA7_MADR); + __Log("psxdma%d c%x b%x m%x", 8, HW_DMA8_CHCR, HW_DMA8_BCR, HW_DMA8_MADR); + __Log("psxdma%d c%x b%x m%x t%x", 9, HW_DMA9_CHCR, HW_DMA9_BCR, HW_DMA9_MADR, HW_DMA9_TADR); + __Log("psxdma%d c%x b%x m%x", 10, HW_DMA10_CHCR, HW_DMA10_BCR, HW_DMA10_MADR); + __Log("psxdma%d c%x b%x m%x", 11, HW_DMA11_CHCR, HW_DMA11_BCR, HW_DMA11_MADR); + __Log("psxdma%d c%x b%x m%x", 12, HW_DMA12_CHCR, HW_DMA12_BCR, HW_DMA12_MADR); + + for(i = 0; i < 7; ++i) + __Log("%scounter%d: mode %x count %I64x rate %x scycle %x target %I64x", pstr, i, psxCounters[i].mode, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT, psxCounters[i].target); +#endif +} + +void iDumpRegisters(u32 startpc, u32 temp) +{ +// [TODO] fixme : this code is broken and has no labels. Needs a rewrite to be useful. + +#ifdef TEST_BROKEN_DUMP_ROUTINES + + int i; + const char* pstr;// = temp ? "t" : ""; + const u32 dmacs[] = {0x8000, 0x9000, 0xa000, 0xb000, 0xb400, 0xc000, 0xc400, 0xc800, 0xd000, 0xd400 }; + const char* psymb; + + if (temp) + pstr = "t"; + else + pstr = ""; + + psymb = disR5900GetSym(startpc); + + if( psymb != NULL ) + __Log("%sreg(%s): %x %x c:%x", pstr, psymb, startpc, cpuRegs.interrupt, cpuRegs.cycle); + else + __Log("%sreg: %x %x c:%x", pstr, startpc, cpuRegs.interrupt, cpuRegs.cycle); + + for(i = 1; i < 32; ++i) __Log("%s: %x_%x_%x_%x", disRNameGPR[i], cpuRegs.GPR.r[i].UL[3], cpuRegs.GPR.r[i].UL[2], cpuRegs.GPR.r[i].UL[1], cpuRegs.GPR.r[i].UL[0]); + + //for(i = 0; i < 32; i+=4) __Log("cp%d: %x_%x_%x_%x", i, cpuRegs.CP0.r[i], cpuRegs.CP0.r[i+1], cpuRegs.CP0.r[i+2], cpuRegs.CP0.r[i+3]); + //for(i = 0; i < 32; ++i) __Log("%sf%d: %f %x", pstr, i, fpuRegs.fpr[i].f, fpuRegs.fprc[i]); + //for(i = 1; i < 32; ++i) __Log("%svf%d: %f %f %f %f, vi: %x", pstr, i, VU0.VF[i].F[3], VU0.VF[i].F[2], VU0.VF[i].F[1], VU0.VF[i].F[0], VU0.VI[i].UL); + + for(i = 0; i < 32; ++i) __Log("%sf%d: %x %x", pstr, i, fpuRegs.fpr[i].UL, fpuRegs.fprc[i]); + for(i = 1; i < 32; ++i) __Log("%svf%d: %x %x %x %x, vi: %x", pstr, i, VU0.VF[i].UL[3], VU0.VF[i].UL[2], VU0.VF[i].UL[1], VU0.VF[i].UL[0], VU0.VI[i].UL); + + __Log("%svfACC: %x %x %x %x", pstr, VU0.ACC.UL[3], VU0.ACC.UL[2], VU0.ACC.UL[1], VU0.ACC.UL[0]); + __Log("%sLO: %x_%x_%x_%x, HI: %x_%x_%x_%x", pstr, cpuRegs.LO.UL[3], cpuRegs.LO.UL[2], cpuRegs.LO.UL[1], cpuRegs.LO.UL[0], + cpuRegs.HI.UL[3], cpuRegs.HI.UL[2], cpuRegs.HI.UL[1], cpuRegs.HI.UL[0]); + __Log("%sCycle: %x %x, Count: %x", pstr, cpuRegs.cycle, g_nextBranchCycle, cpuRegs.CP0.n.Count); + + iDumpPsxRegisters(psxRegs.pc, temp); + + __Log("f410,30,40: %x %x %x, %d %d", psHu32(0xf410), psHu32(0xf430), psHu32(0xf440), rdram_sdevid, rdram_devices); + __Log("cyc11: %x %x; vu0: %x, vu1: %x", cpuRegs.sCycle[1], cpuRegs.eCycle[1], VU0.cycle, VU1.cycle); + + __Log("%scounters: %x %x; psx: %x %x", pstr, nextsCounter, nextCounter, psxNextsCounter, psxNextCounter); + + // fixme: The members of the counters[i] struct are wrong here. + /*for(i = 0; i < 4; ++i) { + __Log("eetimer%d: count: %x mode: %x target: %x %x; %x %x; %x %x %x %x", i, + counters[i].count, counters[i].mode, counters[i].target, counters[i].hold, counters[i].rate, + counters[i].interrupt, counters[i].Cycle, counters[i].sCycle, counters[i].CycleT, counters[i].sCycleT); + }*/ + __Log("VIF0_STAT = %x, VIF1_STAT = %x", psHu32(0x3800), psHu32(0x3C00)); + __Log("ipu %x %x %x %x; bp: %x %x %x %x", psHu32(0x2000), psHu32(0x2010), psHu32(0x2020), psHu32(0x2030), g_BP.BP, g_BP.bufferhasnew, g_BP.FP, g_BP.IFC); + __Log("gif: %x %x %x", psHu32(0x3000), psHu32(0x3010), psHu32(0x3020)); + + for(i = 0; i < ArraySize(dmacs); ++i) { + DMACh* p = (DMACh*)(PS2MEM_HW+dmacs[i]); + __Log("dma%d c%x m%x q%x t%x s%x", i, p->chcr, p->madr, p->qwc, p->tadr, p->sadr); + } + __Log("dmac %x %x %x %x", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); + __Log("intc %x %x", psHu32(INTC_STAT), psHu32(INTC_MASK)); + __Log("sif: %x %x %x %x %x", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); +#endif +} + +void iDumpVU0Registers() +{ + // fixme: This code is outdated, broken, and lacks printed labels. + // Needs heavy mods to be useful. +#ifdef TEST_BROKEN_DUMP_ROUTINES + int i; + + for(i = 1; i < 32; ++i) { + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), + VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); + if( i == REG_Q || i == REG_P ) + __Log("%f\n", VU0.VI[i].F); + else if( i == REG_MAC_FLAG ) + __Log("%x\n", 0);//VU0.VI[i].UL&0xff); + else if( i == REG_STATUS_FLAG ) + __Log("%x\n", 0);//VU0.VI[i].UL&0x03); + else if( i == REG_CLIP_FLAG ) + __Log("0\n"); + else + __Log("%x\n", VU0.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); +#endif +} + +void iDumpVU1Registers() +{ + // fixme: This code is outdated, broken, and lacks printed labels. + // Needs heavy mods to be useful. +#ifdef TEST_BROKEN_DUMP_ROUTINES + int i; + +// static int icount = 0; +// __Log("%x\n", icount); + + for(i = 1; i < 32; ++i) { + +// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2], +// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]); + //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); + + __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); + + if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); + //else __Log("%x\n", VU1.VI[i].UL); + else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL); + } + __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); +#endif +} + + +#ifdef PCSX2_DEVBUILD +// and not sure what these might have once been used for... (air) +//static const char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n"; +//static const char *txt0RC = "EAX = %x : EBX = %x : ECX = %x : EDX = %x : ESI = %x : EDI = %x\n"; +//static const char *txt1 = "REG[%d] = %x_%x\n"; +//static const char *txt2 = "M32 = %x\n"; +#endif +//////////////////////////////////////////////////// + +#include "Utilities/AsciiFile.h" + +// Originally from iR5900-32.cpp +void iDumpBlock( int startpc, u8 * ptr ) +{ + u8 used[34]; + u8 fpuused[33]; + int numused, fpunumused; + + Console::Status( "dump1 %x:%x, %x", params startpc, pc, cpuRegs.cycle ); + + g_Conf.Folders.Dumps.Mkdir(); + AsciiFile eff( + Path::Combine( g_Conf.Folders.Dumps, wxsFormat(wxT("R5900dump%.8X.txt"), startpc) ), + wxFile::write + ); + + if( disR5900GetSym(startpc) != NULL ) + { + eff.Printf( disR5900GetSym( startpc ) ); + eff.Printf( "\n" ); + } + + for ( uint i = startpc; i < s_nEndBlock; i += 4 ) + { + string output; + disR5900Fasm( output, memRead32( i ), i ); + eff.Printf( output.c_str() ); + } + + // write the instruction info + + eff.Printf( "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", + EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED + ); + + memzero_obj(used); + numused = 0; + for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) { + if( s_pInstCache->regs[i] & EEINST_USED ) { + used[i] = 1; + numused++; + } + } + + memzero_obj(fpuused); + fpunumused = 0; + for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { + if( s_pInstCache->fpuregs[i] & EEINST_USED ) { + fpuused[i] = 1; + fpunumused++; + } + } + + eff.Printf( " " ); + for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) { + if( used[i] ) eff.Printf( "%2d ", i ); + } + eff.Printf( "\n" ); + for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) eff.Printf( "%2d ", i ); + } + + eff.Printf( "\n" ); + eff.Printf( " " ); + + // TODO : Finish converting this over to wxWidgers wxFile stuff... + /* + int count; + EEINST* pcur; + + for(uint i = 0; i < ArraySize(s_pInstCache->regs); ++i) { + if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + } + for(uint i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { + if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); + } + fprintf(f, "\n"); + + pcur = s_pInstCache+1; + for( uint i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { + fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + + count = 1; + for(uint j = 0; j < ArraySize(s_pInstCache->regs); j++) { + if( used[j] ) { + fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { + if( fpuused[j] ) { + fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count 264 ) ) { // 4 + 4 + 256 @@ -209,11 +215,12 @@ static uint parseCommandLine( const char *filename ) return 0; } +#endif //--------------- struct ElfObject { - string filename; + wxString filename; SafeArray data; ELF_HEADER& header; ELF_PHR* proghead; @@ -223,7 +230,7 @@ struct ElfObject // C++ does all the cleanup automagically for us. ~ElfObject() { } - ElfObject( const string& srcfile, uint hdrsize ) : + ElfObject( const wxString& srcfile, uint hdrsize ) : filename( srcfile ) , data( hdrsize, "ELF headers" ) , header( *(ELF_HEADER*)data.GetPtr() ) @@ -296,10 +303,11 @@ struct ElfObject void readFile() { int rsize = 0; - if ((strnicmp( filename.c_str(), "cdrom0:", strlen("cdromN:")) == 0) || - (strnicmp( filename.c_str(), "cdrom1:", strlen("cdromN:")) == 0)) + const wxCharBuffer work( filename.ToAscii() ); + if ((strnicmp( work.data(), "cdrom0:", strlen("cdromN:")) == 0) || + (strnicmp( work.data(), "cdrom1:", strlen("cdromN:")) == 0)) { - int fi = CDVDFS_open(filename.c_str() + strlen("cdromN:"), 1);//RDONLY + int fi = CDVDFS_open(work.data() + strlen("cdromN:"), 1);//RDONLY if (fi < 0) throw Exception::FileNotFound( filename ); @@ -311,7 +319,7 @@ struct ElfObject { FILE *f; - f = fopen( filename.c_str(), "rb" ); + f = fopen( work.data(), "rb" ); if( f == NULL ) Exception::FileNotFound( filename ); fseek( f, 0, SEEK_SET ); @@ -404,8 +412,9 @@ struct ElfObject { ELF_LOG( "Elf32 Section Header [%x] %s", i, §ions_names[ secthead[ i ].sh_name ] ); - if ( secthead[i].sh_flags & 0x2 ) - args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff ); + // used by parseCommandLine + //if ( secthead[i].sh_flags & 0x2 ) + // args_ptr = min( args_ptr, secthead[ i ].sh_addr & 0x1ffffff ); #ifdef PCSX2_DEVBULD ELF_LOG("\n"); @@ -462,21 +471,20 @@ struct ElfObject void ElfApplyPatches() { - string filename; - ssprintf( filename, "%8.8x", ElfCRC ); + wxString filename( wxsFormat( wxT("%8.8x"), ElfCRC ) ); // if patches found the following status msg will be overwritten - Console::SetTitle( fmt_string( "Game running [CRC=%hs]", &filename ) ); + Console::SetTitle( wxsFormat( _("Game running [CRC=%s]"), filename.c_str() ) ); if( !Config.Patch ) return; if(LoadPatch( filename ) != 0) { - Console::WriteLn("XML Loader returned an error. Trying to load a pnach..."); - inifile_read( filename.c_str() ); + Console::WriteLn( "XML Loader returned an error. Trying to load a pnach..." ); + inifile_read( filename.ToAscii().data() ); } else - Console::WriteLn("XML Loading success. Will not load from pnach..."); + Console::WriteLn( "XML Loading success. Will not load from pnach..." ); applypatch( 0 ); } @@ -491,20 +499,20 @@ u32 loadElfCRC( const char* filename ) return 0; DevCon::Status( "loadElfFile: %d bytes", params toc.fileSize ); - u32 crcval = ElfObject( filename, toc.fileSize ).GetCRC(); + u32 crcval = ElfObject( wxString::FromAscii( filename ), toc.fileSize ).GetCRC(); Console::Status( "loadElfFile: %s; CRC = %8.8X", params filename, crcval ); return crcval; } -int loadElfFile(const char *filename) +int loadElfFile(const wxString& filename) { // Reset all recompilers prior to initiating a BIOS or new ELF. The cleaner the // slate, the happier the recompiler! SysClearExecutionCache(); - if( filename == NULL || filename[0] == 0 ) + if( filename.IsEmpty() ) { Console::Notice( "Running the PS2 BIOS..." ); return -1; @@ -514,35 +522,42 @@ int loadElfFile(const char *filename) cpuExecuteBios(); int elfsize; + Console::Status( wxsFormat( L"loadElfFile: %s", filename.c_str() ) ); - Console::Status("loadElfFile: %s", params filename); - if (strnicmp( filename, "cdrom0:", strlen( "cdromN:" ) ) && - strnicmp( filename, "cdrom1:", strlen( "cdromN:" ) ) ) + const wxCharBuffer buffer( filename.ToAscii() ); + const char* fnptr = buffer.data(); + + if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) ) { // Loading from a file (or non-cd image) - struct stat sbuf; - if ( stat( filename, &sbuf ) != 0 ) - return -1; - elfsize = sbuf.st_size; + + elfsize = Path::GetFileSize( filename ); } else { // Loading from a CD rom or CD image. TocEntry toc; CDVDFS_init( ); - if ( CDVD_findfile( filename + strlen( "cdromN:" ), &toc ) == -1 ) + if ( CDVD_findfile( fnptr + strlen( "cdromN:" ), &toc ) == -1 ) return -1; elfsize = toc.fileSize; } - Console::Status( "loadElfFile: %d", params elfsize); + Console::Status( wxsFormat(L"loadElfFile: %d", elfsize) ); + if( elfsize == 0 ) return -1; + ElfObject elfobj( filename, elfsize ); if( elfobj.proghead == NULL ) - throw Exception::CpuStateShutdown( fmt_string( "%s > This ELF has no program headers; Pcsx2 can't run what doesn't exist...", filename ) ); + { + throw Exception::CpuStateShutdown( + wxsFormat( wxT("Invalid ELF header encountered in file:\n\t%s"), elfobj.filename ), + wxsFormat(_("Invalid ELF header, file: %s"), elfobj.filename ) + ); + } //2002-09-19 (Florin) - args_ptr = 0xFFFFFFFF; //big value, searching for minimum + //args_ptr = 0xFFFFFFFF; //big value, searching for minimum [used by parseCommandLine] elfobj.loadProgramHeaders(); elfobj.loadSectionHeaders(); @@ -552,17 +567,19 @@ int loadElfFile(const char *filename) cpuRegs.GPR.n.sp.UL[0] = 0x81f00000; cpuRegs.GPR.n.gp.UL[0] = 0x81f80000; // might not be 100% ok - cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); + //cpuRegs.GPR.n.a0.UL[0] = parseCommandLine( filename ); // see #ifdef'd out parseCommendLine for details. - for ( uint i = 0; i < 0x100000; i++ ) { - if ( strcmp( "rom0:OSDSYS", (char*)PSM( i ) ) == 0 ) { - strcpy( (char*)PSM( i ), filename ); - DevCon::Status( "addr %x \"%s\" -> \"%s\"", params i, "rom0:OSDSYS", filename ); + for( uint i = 0; i < 0x100000; i++ ) + { + if( memcmp( "rom0:OSDSYS", (char*)PSM( i ), 11 ) == 0 ) + { + strcpy( (char*)PSM( i ), fnptr ); + DevCon::Status( "loadElfFile: addr %x \"%s\" -> \"%s\"", params i, "rom0:OSDSYS", fnptr ); } } ElfCRC = elfobj.GetCRC(); - Console::Status( "loadElfFile: %s; CRC = %8.8X", params filename, ElfCRC); + Console::Status( wxsFormat( L"loadElfFile: %s; CRC = %8.8X", filename.c_str(), ElfCRC ) ); ElfApplyPatches(); LoadGameSpecificSettings(); diff --git a/pcsx2/Elfheader.h b/pcsx2/Elfheader.h index c6c93beb1d..cc61fa18cd 100644 --- a/pcsx2/Elfheader.h +++ b/pcsx2/Elfheader.h @@ -24,7 +24,7 @@ extern char args[256]; //to be filled by GUI extern unsigned int args_ptr; //------------------- -int loadElfFile(const char *filename); +int loadElfFile(const wxString& filename); u32 loadElfCRC(const char *filename); void LoadGameSpecificSettings(); void ElfApplyPatches(); diff --git a/pcsx2/Exceptions.cpp b/pcsx2/Exceptions.cpp new file mode 100644 index 0000000000..faee842f57 --- /dev/null +++ b/pcsx2/Exceptions.cpp @@ -0,0 +1,165 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" + +wxLocale* g_EnglishLocale = NULL; +//g_EnglishLocale = new wxLocale( wxLANGUAGE_ENGLISH ); + +wxString GetEnglish( const char* msg ) +{ + if( g_EnglishLocale == NULL ) return wxString::FromAscii(msg); + return g_EnglishLocale->GetString( wxString::FromAscii(msg).c_str() ); +} + +wxString GetTranslation( const char* msg ) +{ + return wxGetTranslation( wxString::FromAscii(msg).c_str() ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +namespace Exception +{ + // ------------------------------------------------------------------------ + BaseException::~BaseException() throw() {} + + BaseException::BaseException( const wxString& msg_eng, const wxString& msg_xlt ) : + m_message_eng( msg_eng ), + m_message( msg_xlt ), + m_stacktrace( wxEmptyString ) // unsupported yet + { + // Major hack. After a couple of tries, I'm still not managing to get Linux to catch these exceptions, so that the user actually + // gets the messages. Since Console is unavailable at this level, I'm using a simple printf, which of course, means it doesn't get + // logged. But at least the user sees it. + // + // I'll rip this out once I get Linux to actually catch these exceptions. Say, in BeginExecution or StartGui, like I would expect. + // -- arcum42 +#ifdef __LINUX__ + printf(msg.c_str()); +#endif + } + + // given message is assumed to be a translation key, and will be stored in translated + // and untranslated forms. + BaseException::BaseException( const char* msg_eng ) : + m_message_eng( GetEnglish( msg_eng ) ), + m_message( GetTranslation( msg_eng ) ), + m_stacktrace( wxEmptyString ) // unsupported yet + { + } + + wxString BaseException::LogMessage() const + { + return m_message_eng + wxT("\n\n") + m_stacktrace; + } + + // ------------------------------------------------------------------------ + wxString Stream::LogMessage() const + { + return wxsFormat( + wxT("Stream exception: %s\n\tObject name: %s"), + m_message_eng, StreamName.c_str() + ) + m_stacktrace; + } + + wxString Stream::DisplayMessage() const + { + return m_message + wxT("\n") + StreamName.c_str(); + } + + // ------------------------------------------------------------------------ + wxString PluginFailure::LogMessage() const + { + return wxsFormat( + wxT("%s plugin has encountered an error.\n\n"), + plugin_name.c_str() + ) + m_stacktrace; + } + + wxString PluginFailure::DisplayMessage() const + { + return wxsFormat( m_message, plugin_name ); + } + + // ------------------------------------------------------------------------ + wxString FreezePluginFailure::LogMessage() const + { + return wxsFormat( + wxT("%s plugin returned an error while %s the state.\n\n"), + plugin_name.c_str(), + freeze_action.c_str() + ) + m_stacktrace; + } + + wxString FreezePluginFailure::DisplayMessage() const + { + return m_message; + } + + // ------------------------------------------------------------------------ + wxString UnsupportedStateVersion::LogMessage() const + { + // Note: no stacktrace needed for this one... + return wxsFormat( wxT("Unknown or unsupported savestate version: 0x%x"), Version ); + } + + wxString UnsupportedStateVersion::DisplayMessage() const + { + // m_message contains a recoverable savestate error which is helpful to the user. + return wxsFormat( + m_message + wxT("\n\n") + + wxsFormat( _("Unknown savestate version: 0x%x"), Version ) + ); + } + + // ------------------------------------------------------------------------ + wxString StateCrcMismatch::LogMessage() const + { + // Note: no stacktrace needed for this one... + return wxsFormat( + wxT("Game/CDVD does not match the savestate CRC.\n") + wxT("\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n"), + Crc_Savestate, Crc_Cdvd + ); + } + + wxString StateCrcMismatch::DisplayMessage() const + { + return wxsFormat( + m_message + wxT("\n\n") + + wxsFormat( _( + "Savestate game/crc mismatch. Cdvd CRC: 0x%X Game CRC: 0x%X\n"), + Crc_Savestate, Crc_Cdvd + ) + ); + } + + // ------------------------------------------------------------------------ + wxString IndexBoundsFault::LogMessage() const + { + return wxT("Index out of bounds on SafeArray: ") + ArrayName + + wxsFormat( wxT("(index=%d, size=%d)"), BadIndex, ArrayLength ); + } + + wxString IndexBoundsFault::DisplayMessage() const + { + return m_message; + } +} + diff --git a/pcsx2/Exceptions.h b/pcsx2/Exceptions.h index abc9119b99..b1c8c8172b 100644 --- a/pcsx2/Exceptions.h +++ b/pcsx2/Exceptions.h @@ -16,12 +16,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef _PCSX2_EXCEPTIONS_H_ -#define _PCSX2_EXCEPTIONS_H_ - -#include -#include "StringUtils.h" +#pragma once +////////////////////////////////////////////////////////////////////////////////////////// // This class provides an easy and clean method for ensuring objects are not copyable. class NoncopyableObject { @@ -39,12 +36,12 @@ private: const NoncopyableObject& operator=( const NoncopyableObject& ); }; - +////////////////////////////////////////////////////////////////////////////////////////// // Base class used to implement type-safe sealed classes. -// This class should never be used directly. Use the Sealed -// macro instead, which ensures all sealed classes derive from a unique BaseSealed -// (preventing them from accidentally cirumventing sealing by inheriting from -// multiple sealed classes. +// This class should never be used directly. Use the Sealed macro instead, which ensures +// all sealed classes derive from a unique BaseSealed (preventing them from accidentally +// circumventing sealing by inheriting from multiple sealed classes. +// template < int T > class __BaseSealed { @@ -54,52 +51,70 @@ protected: } }; -// Use this macro/class as a base to seal a class from being derrived from. +// Use this macro/class as a base to seal a class from being derived from. // This macro works by providing a unique base class with a protected constructor // for every class that derives from it. #define Sealed private virtual __BaseSealed<__COUNTER__> +extern wxLocale* g_EnglishLocale; + +extern wxString GetEnglish( const char* msg ); +extern wxString GetTranslation( const char* msg ); + namespace Exception { ////////////////////////////////////////////////////////////////////////////////// - // std::exception sucks, so I made a replacement. + // std::exception sucks, and isn't entirely cross-platform reliable in its implementation, + // so I made a replacement. + // // Note, this class is "abstract" which means you shouldn't use it directly like, ever. - // Use Exception::RuntimeError or Exception::LogicError instead. + // Use Exception::RuntimeError or Exception::LogicError instead for generic exceptions. + // class BaseException { protected: - const wxString m_message; // a "detailed" message of what disasterous thing has occured! + const wxString m_message_eng; // (untranslated) a "detailed" message of what disastrous thing has occurred! + const wxString m_message; // (translated) a "detailed" message of what disastrous thing has occurred! + const wxString m_stacktrace; // contains the stack trace string dump (unimplemented) public: virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode. - explicit BaseException( const wxString& msg="Unhandled exception." ) : - m_message( msg ) - { - // Major hack. After a couple of tries, I'm still not managing to get Linux to catch these exceptions, so that the user actually - // gets the messages. Since Console is unavailable at this level, I'm using a simple printf, which of course, means it doesn't get - // logged. But at least the user sees it. - // - // I'll rip this out once I get Linux to actually catch these exceptions. Say, in BeginExecution or StartGui, like I would expect. - // -- arcum42 -#ifdef __LINUX__ - printf(msg.c_str()); -#endif - } + + // copy construct + BaseException( const BaseException& src ) : + m_message_eng( src.m_message_eng ), + m_message( src.m_message ), + m_stacktrace( src.m_stacktrace ) { } + + // Contruction using two pre-formatted pre-translated messages + BaseException( const wxString& msg_eng, const wxString& msg_xlt ); - const wxString& Message() const { return m_message; } - const char* cMessage() const { return m_message.c_str(); } + // Construction using one translation key. + explicit BaseException( const char* msg_eng ); + + // Returns a message suitable for diagnostic / logging purposes. + // This message is always in english, and includes a full stack trace. + virtual wxString LogMessage() const; + + // Returns a message suitable for end-user display. + // This message is usually meant for display in a user popup or such. + virtual wxString DisplayMessage() const { return m_message; } }; + ////////////////////////////////////////////////////////////////////////////////////////// // This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc). + // Translation Note: These exceptions are never translated, except to issue a general + // error message to the user (which is xspecified below). + // class Ps2Generic : public BaseException { public: virtual ~Ps2Generic() throw() {} - explicit Ps2Generic( const wxString& msg="The Ps2/MIPS state encountered a general exception." ) : - Exception::BaseException( msg ) - { - } + explicit Ps2Generic( const char* msg="Ps2/MIPS cpu caused a general exception" ) : + BaseException( msg ) { } + explicit Ps2Generic( const wxString& msg_eng, const wxString& msg_xlt=_("Ps2/MIPS cpu caused a general exception") ) : + BaseException( msg_eng, msg_xlt ) { } virtual u32 GetPc() const=0; virtual bool IsDelaySlot() const=0; @@ -111,18 +126,29 @@ namespace Exception { public: virtual ~RuntimeError() throw() {} - explicit RuntimeError( const wxString& msg="An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter." ) : - BaseException( msg ) - {} + + RuntimeError( const RuntimeError& src ) : BaseException( src ) {} + + explicit RuntimeError( const char* msg="An unhandled runtime error has occurred, somewhere in the depths of Pcsx2's cluttered brain-matter." ) : + BaseException( msg ) { } + + explicit RuntimeError( const wxString& msg_eng, const wxString& msg_xlt ) : + BaseException( msg_eng, msg_xlt ) { } }; + // ------------------------------------------------------------------------ class LogicError : public BaseException { public: virtual ~LogicError() throw() {} - explicit LogicError( const wxString& msg="An unhandled logic error has occured." ) : - BaseException( msg ) - {} + + LogicError( const LogicError& src ) : BaseException( src ) {} + + explicit LogicError( const char* msg="An unhandled logic error has occurred." ) : + BaseException( msg ) { } + + explicit LogicError( const wxString& msg_eng, const wxString& msg_xlt ) : + BaseException( msg_eng, msg_xlt ) { } }; ////////////////////////////////////////////////////////////////////////////////// @@ -130,46 +156,75 @@ namespace Exception class OutOfMemory : public RuntimeError { public: - explicit OutOfMemory( const wxString& msg="Out of memory!" ) : - RuntimeError( msg ) {} virtual ~OutOfMemory() throw() {} + explicit OutOfMemory( const char* msg="Out of memory" ) : + RuntimeError( msg ) {} + + explicit OutOfMemory( const wxString& msg_eng, const wxString& msg_xlt=_("Out of memory") ) : + RuntimeError( msg_eng, msg_xlt ) { } }; + // ------------------------------------------------------------------------ // This exception thrown any time an operation is attempted when an object // is in an uninitialized state. class InvalidOperation : public LogicError { public: virtual ~InvalidOperation() throw() {} - explicit InvalidOperation( const wxString& msg="Attempted method call is invalid for the current object or program state." ) : + explicit InvalidOperation( const char* msg="Attempted method call is invalid for the current object or program state." ) : LogicError( msg ) {} + + explicit InvalidOperation( const wxString& msg_eng, const wxString& msg_xlt ) : + LogicError( msg_eng, msg_xlt ) { } }; + // ------------------------------------------------------------------------ // This exception thrown any time an operation is attempted when an object // is in an uninitialized state. class InvalidArgument : public LogicError { public: virtual ~InvalidArgument() throw() {} - explicit InvalidArgument( const wxString& msg="Invalid argument passed to a function." ) : - LogicError( msg ) {} + explicit InvalidArgument( const char* msg="Invalid argument passed to a function." ) : + LogicError( msg ) + { + // assertions make debugging easier sometimes. :) + wxASSERT( msg ); + } }; + // ------------------------------------------------------------------------ // Keep those array indexers in bounds when using the SafeArray type, or you'll be // seeing these. class IndexBoundsFault : public LogicError { + public: + const wxString ArrayName; + const int ArrayLength; + const int BadIndex; + public: virtual ~IndexBoundsFault() throw() {} - explicit IndexBoundsFault( const wxString& msg="Array index is outsides the bounds of an array." ) : - LogicError( msg ) {} + explicit IndexBoundsFault( const wxString& objname, int index, int arrsize ) : + LogicError( "Index is outside the bounds of an array." ), + ArrayName( objname ), + ArrayLength( arrsize ), + BadIndex( index ) + { + // assertions make debugging easier sometimes. :) + wxASSERT( wxT("Index is outside the bounds of an array") ); + } + + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; + // ------------------------------------------------------------------------ class ParseError : public RuntimeError { public: virtual ~ParseError() throw() {} - explicit ParseError( const wxString& msg="Parse error" ) : + explicit ParseError( const char* msg="Parse error" ) : RuntimeError( msg ) {} }; @@ -178,11 +233,12 @@ namespace Exception class HardwareDeficiency : public RuntimeError { public: - explicit HardwareDeficiency( const wxString& msg="Your machine's hardware is incapable of running Pcsx2. Sorry dood." ) : + explicit HardwareDeficiency( const char* msg="Your machine's hardware is incapable of running Pcsx2. Sorry dood." ) : RuntimeError( msg ) {} virtual ~HardwareDeficiency() throw() {} }; + // ------------------------------------------------------------------------ // This exception is thrown by the PS2 emulation (R5900, etc) when bad things happen // that force the emulation state to terminate. The GUI should handle them by returning // the user to the GUI. @@ -190,66 +246,72 @@ namespace Exception { public: virtual ~CpuStateShutdown() throw() {} - explicit CpuStateShutdown( const wxString& msg="The PS2 emulated state was shut down unexpectedly." ) : + explicit CpuStateShutdown( const char* msg="Unexpected emulation shutdown" ) : RuntimeError( msg ) {} + + explicit CpuStateShutdown( const wxString& msg_eng, const wxString& msg_xlt=wxString() ) : + RuntimeError( msg_eng, msg_xlt.IsEmpty() ? _("Unexpected emulation shutdown") : msg_xlt ) { } }; + // ------------------------------------------------------------------------ class PluginFailure : public RuntimeError { public: wxString plugin_name; // name of the plugin virtual ~PluginFailure() throw() {} - explicit PluginFailure( const wxString& plugin, const wxString& msg = "A plugin encountered a critical error." ) : + + explicit PluginFailure( const char* plugin, const char* msg="%s plugin encountered a critical error" ) : RuntimeError( msg ) - , plugin_name( plugin ) {} + , plugin_name( wxString::FromAscii(plugin) ) {} + + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; + // ------------------------------------------------------------------------ class ThreadCreationError : public RuntimeError { public: virtual ~ThreadCreationError() throw() {} - explicit ThreadCreationError( const wxString& msg="Thread could not be created." ) : - RuntimeError( msg ) {} - }; - - // This is a "special" exception that's primarily included for safe functioning in the - // Win32's ASCII API (ie, the non-Unicode one). Many of the old Win32 APIs don't support - // paths over 256 characters. - class PathTooLong : public RuntimeError - { - public: - virtual ~PathTooLong() throw() {} - explicit PathTooLong( const wxString& msg= - "A Pcsx2 pathname was too long for the system. Please move or reinstall Pcsx2 to\n" - "a location on your hard drive that has a shorter path." ) : + explicit ThreadCreationError( const char* msg="Thread could not be created." ) : RuntimeError( msg ) {} }; ////////////////////////////////////////////////////////////////////////////////// // STREAMING EXCEPTIONS + // ------------------------------------------------------------------------ // Generic stream error. Contains the name of the stream and a message. - // This exception is usually thrown via derrived classes, except in the (rare) case of a generic / unknown error. + // This exception is usually thrown via derived classes, except in the (rare) case of a generic / unknown error. class Stream : public RuntimeError { public: - wxString stream_name; // name of the stream (if applicable) + wxString StreamName; // name of the stream (if applicable) virtual ~Stream() throw() {} // copy construct! Stream( const Stream& src ) : - RuntimeError( src.Message() ) - , stream_name( src.stream_name ) {} + RuntimeError( src ), + StreamName( src.StreamName ) {} explicit Stream( const wxString& objname=wxString(), - const wxString& msg="Invalid stream object" ) : - RuntimeError( msg + "\n\tFilename: " + objname ) - , stream_name( objname ) {} + const char* msg="General file operation error" // general error while accessing or operating on a file or stream + ) : + RuntimeError( msg ), + StreamName( objname ) {} + + explicit Stream( const wxString& objname, const wxString& msg_eng, const wxString& msg_xlt=_("General file operation error") ) : + RuntimeError( msg_eng, msg_xlt ), + StreamName( objname ) {} + + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; + // ------------------------------------------------------------------------ // A generic base error class for bad streams -- corrupted data, sudden closures, loss of // connection, or anything else that would indicate a failure to read the data after the // stream was successfully opened. @@ -259,50 +321,63 @@ namespace Exception virtual ~BadStream() throw() {} explicit BadStream( const wxString& objname=wxString(), - const wxString& msg="Stream data is corrupted or incomplete, or the stream connection closed unexpectedly" ) : - Stream( objname, msg ) {} + const char* msg="File data is corrupted or incomplete, or the stream connection closed unexpectedly" + ) : + Stream( objname, msg ) {} }; + // ------------------------------------------------------------------------ // A generic exception for odd-ball stream creation errors. class CreateStream : public Stream { public: virtual ~CreateStream() throw() {} + + explicit CreateStream( + const char* objname, + const char* msg="File could not be created or opened" ) : + Stream( wxString::FromAscii( objname ), msg ) {} + explicit CreateStream( const wxString& objname=wxString(), - const wxString& msg="Stream could not be created or opened" ) : + const char* msg="File could not be created or opened" ) : Stream( objname, msg ) {} }; + // ------------------------------------------------------------------------ // Exception thrown when an attempt to open a non-existent file is made. // (this exception can also mean file permissions are invalid) class FileNotFound : public CreateStream { public: virtual ~FileNotFound() throw() {} + explicit FileNotFound( const wxString& objname=wxString(), - const wxString& msg="File not found" ) : + const char* msg="File not found" ) : + CreateStream( objname, msg ) {} }; + // ------------------------------------------------------------------------ class AccessDenied : public CreateStream { public: virtual ~AccessDenied() throw() {} explicit AccessDenied( const wxString& objname=wxString(), - const wxString& msg="Permission denied to file or stream" ) : + const char* msg="Permission denied to file" ) : CreateStream( objname, msg ) {} }; + // ------------------------------------------------------------------------ // Generic End of Stream exception (sometimes an error, and sometimes just used as a // shortcut for manual feof checks). class EndOfStream : public Stream { public: virtual ~EndOfStream() throw() {} - explicit EndOfStream( const wxString& objname=wxString(), const wxString& msg="End of stream was encountered" ) : + explicit EndOfStream( const wxString& objname, const char* msg="End of file" ) : Stream( objname, msg ) {} }; @@ -316,10 +391,11 @@ namespace Exception virtual ~BadSavedState() throw() {} explicit BadSavedState( const wxString& objname=wxString(), - const wxString& msg="Savestate data is corrupted or incomplete" ) : + const char* msg="Savestate data is corrupted" ) : // or incomplete BadStream( objname, msg ) {} }; + // ------------------------------------------------------------------------ // Exception thrown by SaveState class when a critical plugin or gzread class FreezePluginFailure : public RuntimeError { @@ -328,12 +404,18 @@ namespace Exception wxString freeze_action; virtual ~FreezePluginFailure() throw() {} - explicit FreezePluginFailure( const wxString& plugin, const wxString& action ) : - RuntimeError( plugin + " plugin returned an error while " + action + " the state." ) - , plugin_name( plugin ) - , freeze_action( action ){} + explicit FreezePluginFailure( const char* plugin, const char* action, + const wxString& msg_xlt=_("Plugin error occurred while loading/saving state") ) + : + RuntimeError( wxString(), msg_xlt ) // LogMessage / DisplayMessage build their own messages + , plugin_name( wxString::FromAscii(plugin) ) + , freeze_action( wxString::FromAscii(action) ){} + + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; + // ------------------------------------------------------------------------ // The savestate code throws Recoverable errors when it fails prior to actually modifying // the current emulation state. Recoverable errors are always thrown from the SaveState // object construction (and never from Freeze methods). @@ -341,10 +423,11 @@ namespace Exception { public: virtual ~StateLoadError_Recoverable() throw() {} - explicit StateLoadError_Recoverable( const wxString& msg="Recoverable error while loading savestate (existing emulation state is still intact)." ) : + explicit StateLoadError_Recoverable( const char* msg="Recoverable savestate load error" ) : RuntimeError( msg ) {} }; + // ------------------------------------------------------------------------ // A recoverable exception thrown when the savestate being loaded isn't supported. class UnsupportedStateVersion : public StateLoadError_Recoverable { @@ -354,13 +437,15 @@ namespace Exception public: virtual ~UnsupportedStateVersion() throw() {} explicit UnsupportedStateVersion( int version ) : - StateLoadError_Recoverable( fmt_string( "Unknown or unsupported savestate version: 0x%x", version ) ) + StateLoadError_Recoverable(), + Version( version ) {} - explicit UnsupportedStateVersion( __unused int version, const wxString& msg ) : - StateLoadError_Recoverable( msg ) {} + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; + // ------------------------------------------------------------------------ // A recoverable exception thrown when the CRC of the savestate does not match the // CRC returned by the Cdvd driver. // [feature not implemented yet] @@ -373,20 +458,12 @@ namespace Exception public: virtual ~StateCrcMismatch() throw() {} explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd ) - : StateLoadError_Recoverable( fmt_string( - "Game/CDVD does not match the savestate CRC.\n" - "\tCdvd CRC: 0x%X\n\tGame CRC: 0x%X\n", params crc_save, crc_cdvd - ) ) + : StateLoadError_Recoverable() , Crc_Savestate( crc_save ) , Crc_Cdvd( crc_cdvd ) {} - explicit StateCrcMismatch( u32 crc_save, u32 crc_cdvd, const wxString& msg ) - : StateLoadError_Recoverable( msg ) - , Crc_Savestate( crc_save ) - , Crc_Cdvd( crc_cdvd ) - {} + virtual wxString LogMessage() const; + virtual wxString DisplayMessage() const; }; } - -#endif diff --git a/pcsx2/GS.cpp b/pcsx2/GS.cpp index 8772c51056..4ff204c57d 100644 --- a/pcsx2/GS.cpp +++ b/pcsx2/GS.cpp @@ -24,16 +24,27 @@ #include "GS.h" #include "iR5900.h" #include "Counters.h" - #include "VifDma.h" using namespace Threading; using namespace std; - using namespace R5900; static bool m_gsOpened = false; +u32 CSRw; + +PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] ); +extern int m_nCounters[]; + +// FrameSkipping Stuff +// Yuck, iSlowStart is needed by the MTGS, so can't make it static yet. + +u64 m_iSlowStart=0; +static s64 m_iSlowTicks=0; +static bool m_justSkipped = false; +static bool m_StrictSkipping = false; + #ifdef PCSX2_DEVBUILD // GS Playback @@ -98,21 +109,6 @@ __forceinline void GSVSYNC(void) { } #endif -u32 CSRw; - -PCSX2_ALIGNED16( u8 g_RealGSMem[0x2000] ); -#define PS2GS_BASE(mem) (g_RealGSMem+(mem&0x13ff)) - -extern int m_nCounters[]; - -// FrameSkipping Stuff -// Yuck, iSlowStart is needed by the MTGS, so can't make it static yet. - -u64 m_iSlowStart=0; -static s64 m_iSlowTicks=0; -static bool m_justSkipped = false; -static bool m_StrictSkipping = false; - void _gs_ChangeTimings( u32 framerate, u32 iTicks ) { m_iSlowStart = GetCPUTicks(); @@ -839,8 +835,6 @@ void RunGSState( gzLoadingState& f ) list::iterator it = packets.begin(); g_SaveGSStream = 3; - //int skipfirst = 1; - // first extract the data while(1) { @@ -877,4 +871,4 @@ void RunGSState( gzLoadingState& f ) #endif -#undef GIFchain +//#undef GIFchain diff --git a/pcsx2/Gif.cpp b/pcsx2/Gif.cpp index a36c17f775..edb8ee7069 100644 --- a/pcsx2/Gif.cpp +++ b/pcsx2/Gif.cpp @@ -28,18 +28,17 @@ using std::min; -#define gif ((DMACh*)&psH[0xA000]) -#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) - +#define gifsplit 64 enum gifstate_t { - GIF_STATE_EMPTY = 0, - GIF_STATE_STALL, - GIF_STATE_DONE + GIF_STATE_READY = 0, + GIF_STATE_STALL = 1, + GIF_STATE_DONE = 2, + GIF_STATE_EMPTY = 0x10 }; // A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished). -static gifstate_t gifstate = GIF_STATE_EMPTY; +static int gifstate = GIF_STATE_READY; static u64 s_gstag = 0; // used for querying the last tag @@ -49,6 +48,7 @@ static int gspath3done = 0; static u32 gscycles = 0, prevcycles = 0, mfifocycles = 0; static u32 gifqwc = 0; +bool gifmfifoirq = FALSE; __forceinline void gsInterrupt() { GIF_LOG("gsInterrupt: %8.8x", cpuRegs.cycle); @@ -57,8 +57,8 @@ __forceinline void gsInterrupt() { //Console::WriteLn("Eh? why are you still interrupting! chcr %x, qwc %x, done = %x", params gif->chcr, gif->qwc, done); return; } - if(gif->qwc > 0 || gspath3done == 0) { - if( !(psHu32(DMAC_CTRL) & 0x1) ) { + if (gif->qwc > 0 || gspath3done == 0) { + if (!(psHu32(DMAC_CTRL) & 0x1)) { Console::Notice("gs dma masked, re-scheduling..."); // re-raise the int shortly in the future CPU_INT( 2, 64 ); @@ -73,7 +73,7 @@ __forceinline void gsInterrupt() { /*if (!(vif1Regs->mskpath3 && (vif1ch->chcr & 0x100)) || (psHu32(GIF_MODE) & 0x1)) CPU_INT( 2, 64 );*/ #endif - if(gspath3done == 0) return; + if(gspath3done == 0 || gif->qwc > 0) return; } gspath3done = 0; @@ -85,6 +85,7 @@ __forceinline void gsInterrupt() { psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 psHu32(GIF_STAT)&= ~0x1F000000; // QFC=0 hwDmacIrq(DMAC_GIF); + GIF_LOG("GIF DMA end"); } @@ -127,7 +128,7 @@ static void WRITERING_DMA(u32 *pMem, u32 qwc) int _GIFchain() { #ifdef GSPATH3FIX - u32 qwc = ((psHu32(GIF_MODE) & 0x4) && (vif1Regs->mskpath3)) ? min(8, (int)gif->qwc) : gif->qwc; + u32 qwc = ((psHu32(GIF_MODE) & 0x4) && (vif1Regs->mskpath3)) ? min(8, (int)gif->qwc) : min( gifsplit, (int)gif->qwc ); #else u32 qwc = gif->qwc; #endif @@ -151,7 +152,7 @@ int _GIFchain() { return (qwc)*2; } -__forceinline void GIFchain() +static __forceinline void GIFchain() { FreezeRegs(1); if (gif->qwc) gscycles+= _GIFchain(); /* guessing */ @@ -163,7 +164,7 @@ static __forceinline void dmaGIFend() if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); else - CPU_INT(2, gif->qwc /** BIAS*/); + CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/); } // These could probably be consolidated into one function, @@ -174,7 +175,7 @@ static __forceinline void GIFdmaEnd() if (psHu32(GIF_MODE) & 0x4) CPU_INT(2, min( 8, (int)gif->qwc ) /** BIAS*/); else - CPU_INT(2, gif->qwc /** BIAS*/); + CPU_INT(2, min( gifsplit, (int)gif->qwc ) /** BIAS*/); } void GIFdma() @@ -189,7 +190,7 @@ void GIFdma() return; } - GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1); + #ifndef GSPATH3FIX if ( !(psHu32(GIF_MODE) & 0x4) ) { @@ -225,7 +226,7 @@ void GIFdma() ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR if (ptag == NULL) { //Is ptag empty? - psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + psHu32(DMAC_STAT) |= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register return; } gscycles += 2; @@ -243,14 +244,10 @@ void GIFdma() } } } - // When MTGS is enabled, Gifchain calls WRITERING_DMA, which calls GSRINGBUF_DONECOPY, which freezes - // the registers inside of the FreezeXMMRegs calls here and in the other two below.. - // I'm not really sure that is intentional. --arcum42 + GIFchain(); - // Theres a comment below that says not to unfreeze the xmm regs, so not sure about freezing and unfreezing in GIFchain. if((gif->qwc == 0) && ((gspath3done == 1) || (gif->chcr & 0xc) == 0)){ - //if(gif->qwc > 0) Console::WriteLn("Hurray!"); // We *know* it is 0! gspath3done = 0; gif->chcr &= ~0x100; GSCSRr &= ~0xC000; @@ -272,17 +269,20 @@ void GIFdma() if (((gif->qwc == 0) && (gif->chcr & 0xc) == 0)) gspath3done = 1; - else + else if(gif->qwc > 0) + { GIFdmaEnd(); return; } - else { + } + if ((gif->chcr & 0xc) == 0x4 && gspath3done == 0) + { // Chain Mode - while ((gspath3done == 0) && (gif->qwc == 0)) { //Loop if the transfers aren't intermittent + //while ((gspath3done == 0) && (gif->qwc == 0)) { //Loop if the transfers aren't intermittent ptag = (u32*)dmaGetAddr(gif->tadr); //Set memory pointer to TADR if (ptag == NULL) { //Is ptag empty? - psHu32(DMAC_STAT)|= 1<<15; //If yes, set BEIS (BUSERR) in DMAC_STAT register + psHu32(DMAC_STAT)|= DMAC_STAT_BEIS; //If yes, set BEIS (BUSERR) in DMAC_STAT register return; } gscycles+=2; // Add 1 cycles from the QW read for the tag @@ -300,7 +300,7 @@ void GIFdma() if ((psHu32(DMAC_CTRL) & 0xC0) == 0x80) { // STD == GIF // there are still bugs, need to also check if gif->madr +16*qwc >= stadr, if not, stall - if(!gspath3done && gif->madr + (gif->qwc * 16) > psHu32(DMAC_STADR) && id == 4) { + if(!gspath3done && ((gif->madr + (gif->qwc * 16)) > psHu32(DMAC_STADR)) && (id == 4)) { // stalled Console::WriteLn("GS Stall Control Source = %x, Drain = %x\n MADR = %x, STADR = %x", params (psHu32(0xe000) >> 4) & 0x3, (psHu32(0xe000) >> 6) & 0x3,gif->madr, psHu32(DMAC_STADR)); prevcycles = gscycles; @@ -313,20 +313,20 @@ void GIFdma() } GIFchain(); //Transfers the data set by the switch - if ((gif->chcr & 0x80) && ptag[0] >> 31) { //Check TIE bit of CHCR and IRQ bit of tag + if ((gif->chcr & 0x80) && (ptag[0] >> 31)) { //Check TIE bit of CHCR and IRQ bit of tag GIF_LOG("dmaIrq Set"); gspath3done = 1; } - } + //} } prevcycles = 0; if (!(vif1Regs->mskpath3 || (psHu32(GIF_MODE) & 0x1))) { - if (gspath3done == 0) + if (gspath3done == 0 || gif->qwc > 0) { - if ((psHu32(GIF_MODE) & 0x4) && gif->qwc != 0) + if (gif->qwc != 0) { - CPU_INT(2, min( 8, (int)gif->qwc )/** BIAS*/); + GIFdmaEnd(); } else { @@ -346,9 +346,9 @@ void GIFdma() void dmaGIF() { //We used to addd wait time for the buffer to fill here, fixing some timing problems in path 3 masking //It takes the time of 24 QW for the BUS to become ready - The Punisher, And1 Streetball - + GIF_LOG("dmaGIFstart chcr = %lx, madr = %lx, qwc = %lx\n tadr = %lx, asr0 = %lx, asr1 = %lx", gif->chcr, gif->madr, gif->qwc, gif->tadr, gif->asr0, gif->asr1); if ((psHu32(DMAC_CTRL) & 0xC) == 0xC ) { // GIF MFIFO - Console::WriteLn("GIF MFIFO"); + //Console::WriteLn("GIF MFIFO"); gifMFIFOInterrupt(); return; } @@ -365,7 +365,8 @@ void dmaGIF() { gif->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag gif->chcr = ( gif->chcr & 0xFFFF ) | ( (*ptag) & 0xFFFF0000 ); //Transfer upper part of tag to CHCR bits 31-15 - dmaGIFend(); + //gspath3done = hwDmacSrcChainWithStack(gif, (ptag[0] >> 28) & 0x7); + GIFdmaEnd(); gif->qwc = 0; return; } @@ -414,8 +415,8 @@ static __forceinline int mfifoGIFrbTransfer() { gifqwc -= mfifoqwc; gif->qwc -= mfifoqwc; - gif->madr+= mfifoqwc*16; - mfifocycles+= (mfifoqwc) * 2; /* guessing */ + gif->madr += mfifoqwc*16; + //mfifocycles += (mfifoqwc) * 2; /* guessing */ return 0; } @@ -438,14 +439,13 @@ static __forceinline int mfifoGIFchain() { if (pMem == NULL) return -1; WRITERING_DMA(pMem, mfifoqwc); - gif->madr+= mfifoqwc*16; + gif->madr += mfifoqwc*16; gif->qwc -= mfifoqwc; - mfifocycles+= (mfifoqwc) * 2; /* guessing */ + mfifocycles += (mfifoqwc) * 2; /* guessing */ } return 0; } -bool gifmfifoirq = FALSE; void mfifoGIFtransfer(int qwc) { u32 *ptag; @@ -457,14 +457,14 @@ void mfifoGIFtransfer(int qwc) { if(qwc > 0 ) { gifqwc += qwc; - if(!(gif->chcr & 0x100))return; - if(gifstate == GIF_STATE_STALL) return; + if (gifstate != GIF_STATE_EMPTY) return; + gifstate &= ~GIF_STATE_EMPTY; } SPR_LOG("mfifoGIFtransfer %x madr %x, tadr %x", gif->chcr, gif->madr, gif->tadr); - if(gif->qwc == 0){ - if(gif->tadr == spr0->madr) { + if (gif->qwc == 0) { + if (gif->tadr == spr0->madr) { //if( gifqwc > 1 ) DevCon::WriteLn("gif mfifo tadr==madr but qwc = %d", params gifqwc); //hwDmacIrq(14); @@ -492,20 +492,20 @@ void mfifoGIFtransfer(int qwc) { case 1: // CNT - Transfer QWC following the tag. gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag gif->tadr = psHu32(DMAC_RBOR) + ((gif->madr + (gif->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data - gifstate = GIF_STATE_EMPTY; + gifstate = GIF_STATE_READY; break; case 2: // Next - Transfer QWC following tag. TADR = ADDR temp = gif->madr; //Temporarily Store ADDR gif->madr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag gif->tadr = temp; //Copy temporarily stored ADDR to Tag - gifstate = GIF_STATE_EMPTY; + gifstate = GIF_STATE_READY; break; case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) gif->tadr = psHu32(DMAC_RBOR) + ((gif->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag - gifstate = GIF_STATE_EMPTY; + gifstate = GIF_STATE_READY; break; case 7: // End - Transfer QWC following the tag @@ -521,12 +521,15 @@ void mfifoGIFtransfer(int qwc) { gifmfifoirq = TRUE; } } + FreezeRegs(1); + if (mfifoGIFchain() == -1) { Console::WriteLn("GIF dmaChain error size=%d, madr=%lx, tadr=%lx", params gif->qwc, gif->madr, gif->tadr); gifstate = GIF_STATE_STALL; } + FreezeRegs(0); if(gif->qwc == 0 && gifstate == GIF_STATE_DONE) gifstate = GIF_STATE_STALL; @@ -542,10 +545,16 @@ void gifMFIFOInterrupt() cpuRegs.interrupt &= ~(1 << 11); return ; } + if((spr0->chcr & 0x100) && spr0->qwc == 0) + { + spr0->chcr &= ~0x100; + hwDmacIrq(8); + } if(gifstate != GIF_STATE_STALL) { if(gifqwc <= 0) { //Console::WriteLn("Empty"); + gifstate |= GIF_STATE_EMPTY; psHu32(GIF_STAT)&= ~0xE00; // OPH=0 | APATH=0 hwDmacIrq(14); return; @@ -554,14 +563,14 @@ void gifMFIFOInterrupt() return; } #ifdef PCSX2_DEVBUILD - if(gifstate == GIF_STATE_EMPTY || gif->qwc > 0) { + if(gifstate == GIF_STATE_READY || gif->qwc > 0) { Console::Error("gifMFIFO Panic > Shouldn't go here!"); return; } #endif //if(gifqwc > 0) Console::WriteLn("GIF MFIFO ending with stuff in it %x", params gifqwc); if (!gifmfifoirq) gifqwc = 0; - gifstate = GIF_STATE_EMPTY; + gifstate = GIF_STATE_READY; gif->chcr &= ~0x100; hwDmacIrq(DMAC_GIF); GSCSRr &= ~0xC000; //Clear FIFO stuff diff --git a/pcsx2/HostGui.h b/pcsx2/HostGui.h index 886f657011..6f44b2a655 100644 --- a/pcsx2/HostGui.h +++ b/pcsx2/HostGui.h @@ -93,8 +93,8 @@ namespace HostGui // For issuing notices to both the status bar and the console at the same time. // Single-line text only please! Multi-line msgs should be directed to the // console directly, thanks. - extern void Notice( const std::string& text ); + extern void Notice( const wxString& text ); // sets the contents of the pcsx2 window status bar. - extern void SetStatusMsg( const std::string& text ); + extern void SetStatusMsg( const wxString& text ); }; \ No newline at end of file diff --git a/pcsx2/Hw.cpp b/pcsx2/Hw.cpp index bb3087bfce..3ff49efc15 100644 --- a/pcsx2/Hw.cpp +++ b/pcsx2/Hw.cpp @@ -148,31 +148,31 @@ int hwMFIFOWrite(u32 addr, u8 *data, u32 size) { } -int hwDmacSrcChainWithStack(DMACh *dma, int id) { - u32 temp; - +bool hwDmacSrcChainWithStack(DMACh *dma, int id) { switch (id) { case 0: // Refe - Transfer Packet According to ADDR field - return 1; //End Transfer + return true; //End Transfer case 1: // CNT - Transfer QWC following the tag. dma->madr = dma->tadr + 16; //Set MADR to QW after Tag dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data - return 0; + return false; case 2: // Next - Transfer QWC following tag. TADR = ADDR - temp = dma->madr; //Temporarily Store ADDR + { + u32 temp = dma->madr; //Temporarily Store ADDR dma->madr = dma->tadr + 16; //Set MADR to QW following the tag dma->tadr = temp; //Copy temporarily stored ADDR to Tag - return 0; - + return false; + } case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) dma->tadr += 16; //Set TADR to next tag - return 0; + return false; case 5: // Call - Transfer QWC following the tag, save succeeding tag - temp = dma->madr; //Temporarily Store ADDR + { + u32 temp = dma->madr; //Temporarily Store ADDR dma->madr = dma->tadr + 16; //Set MADR to data following the tag @@ -185,12 +185,12 @@ int hwDmacSrcChainWithStack(DMACh *dma, int id) { dma->asr1 = dma->madr + (dma->qwc << 4); //If no store Succeeding tag in ASR1 }else { Console::Notice("Call Stack Overflow (report if it fixes/breaks anything)"); - return 1; //Return done + return true; //Return done } dma->tadr = temp; //Set TADR to temporarily stored ADDR - return 0; - + return false; + } case 6: // Ret - Transfer QWC following the tag, load next tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag @@ -209,668 +209,45 @@ int hwDmacSrcChainWithStack(DMACh *dma, int id) { return 1; //End Transfer } } - return 0; + return false; case 7: // End - Transfer QWC following the tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag //Dont Increment tadr, breaks Soul Calibur II and III - return 1; //End Transfer + return true; //End Transfer } - return -1; + return false; } -int hwDmacSrcChain(DMACh *dma, int id) { +bool hwDmacSrcChain(DMACh *dma, int id) { u32 temp; switch (id) { case 0: // Refe - Transfer Packet According to ADDR field - return 1; //End Transfer + return true; //End Transfer case 1: // CNT - Transfer QWC following the tag. dma->madr = dma->tadr + 16; //Set MADR to QW after Tag dma->tadr = dma->madr + (dma->qwc << 4); //Set TADR to QW following the data - return 0; + return false; case 2: // Next - Transfer QWC following tag. TADR = ADDR temp = dma->madr; //Temporarily Store ADDR dma->madr = dma->tadr + 16; //Set MADR to QW following the tag dma->tadr = temp; //Copy temporarily stored ADDR to Tag - return 0; + return false; case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) dma->tadr += 16; //Set TADR to next tag - return 0; + return false; case 7: // End - Transfer QWC following the tag dma->madr = dma->tadr + 16; //Set MADR to data following the tag //Dont Increment tadr, breaks Soul Calibur II and III - return 1; //End Transfer + return true; //End Transfer } - return -1; + return false; } - -// Original hwRead/Write32 functions .. left in for now, for troubleshooting purposes. -#if 0 -mem32_t __fastcall hwRead32(u32 mem) -{ - // *Performance Warning* This function is called -A-LOT. Be weary when making changes. It - // could impact FPS significantly. - - // Optimization Note: - // Shortcut for the INTC_STAT register, which is checked *very* frequently as part of the EE's - // vsynch timers. INTC_STAT has the disadvantage of being in the 0x1000f000 case, which has - // a lot of additional registers in it, and combined with it's call frequency is a bad thing. - - if(mem == INTC_STAT) - { - // This one is checked alot, so leave it commented out unless you love 600 meg logfiles. - //HW_LOG("DMAC_STAT Read 32bit %x\n", psHu32(0xe010)); - return psHu32(INTC_STAT); - } - - const u16 masked_mem = mem & 0xffff; - - // We optimize the hw register reads by breaking them into manageable 4k chunks (for a total of - // 16 cases spanning the 64k PS2 hw register memory map). It helps also that the EE is, for - // the most part, designed so that various classes of registers are sectioned off into these - // 4k segments. - - // Notes: Breaks from the switch statement will return a standard hw memory read. - // Special case handling of reads should use "return" directly. - - switch( masked_mem>>12 ) // switch out as according to the 4k page of the access. - { - // Counters Registers - // This code uses some optimized trickery to produce more compact output. - // See below for the "reference" block to get a better idea what this code does. :) - - case 0x0: // counters 0 and 1 - case 0x1: // counters 2 and 3 - { - const uint cntidx = masked_mem >> 11; // neat trick to scale the counter HW address into 0-3 range. - switch( (masked_mem>>4) & 0xf ) - { - case 0x0: return (u16)rcntRcount(cntidx); - case 0x1: return (u16)counters[cntidx].modeval; - case 0x2: return (u16)counters[cntidx].target; - case 0x3: return (u16)counters[cntidx].hold; - } - } - -#if 0 // Counters Reference Block (original case setup) - case 0x10000000: return (u16)rcntRcount(0); - case 0x10000010: return (u16)counters[0].modeval; - case 0x10000020: return (u16)counters[0].target; - case 0x10000030: return (u16)counters[0].hold; - - case 0x10000800: return (u16)rcntRcount(1); - case 0x10000810: return (u16)counters[1].modeval; - case 0x10000820: return (u16)counters[1].target; - case 0x10000830: return (u16)counters[1].hold; - - case 0x10001000: return (u16)rcntRcount(2); - case 0x10001010: return (u16)counters[2].modeval; - case 0x10001020: return (u16)counters[2].target; - - case 0x10001800: return (u16)rcntRcount(3); - case 0x10001810: return (u16)counters[3].modeval; - case 0x10001820: return (u16)counters[3].target; -#endif - - break; - - case 0x2: return ipuRead32( mem ); - - case 0xf: - switch( (masked_mem >> 4) & 0xff ) - { - case 0x01: - HW_LOG("INTC_MASK Read32, value=0x%x", psHu32(INTC_MASK)); - break; - - case 0x13: // 0x1000f130 - case 0x26: // 0x1000f260 SBUS? - case 0x41: // 0x1000f410 - case 0x43: // MCH_RICM - return 0; - - case 0x24: // 0x1000f240: SBUS - return psHu32(0xf240) | 0xF0000102; - - case 0x44: // 0x1000f440: MCH_DRD - - if( !((psHu32(0xf430) >> 6) & 0xF) ) - { - switch ((psHu32(0xf430)>>16) & 0xFFF) - { - //MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5 - - case 0x21://INIT - if(rdram_sdevid < rdram_devices) - { - rdram_sdevid++; - return 0x1F; - } - return 0; - - case 0x23://CNFGA - return 0x0D0D; //PVER=3 | MVER=16 | DBL=1 | REFBIT=5 - - case 0x24://CNFGB - //0x0110 for PSX SVER=0 | CORG=8(5x9x7) | SPT=1 | DEVTYP=0 | BYTE=0 - return 0x0090; //SVER=0 | CORG=4(5x9x6) | SPT=1 | DEVTYP=0 | BYTE=0 - - case 0x40://DEVID - return psHu32(0xf430) & 0x1F; // =SDEV - } - } - return 0; - } - break; - - /////////////////////////////////////////////////////// - // Most of the following case handlers are for developer builds only (logging). - // It'll all optimize to ziltch in public release builds. - - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0a: - { - const char* regName = "Unknown"; - - switch( mem ) - { - case D2_CHCR: regName = "DMA2_CHCR"; break; - case D2_MADR: regName = "DMA2_MADR"; break; - case D2_QWC: regName = "DMA2_QWC"; break; - case D2_TADR: regName = "DMA2_TADDR"; break; - case D2_ASR0: regName = "DMA2_ASR0"; break; - case D2_ASR1: regName = "DMA2_ASR1"; break; - case D2_SADR: regName = "DMA2_SADDR"; break; - } - - HW_LOG( "Hardware Read32 at 0x%x (%s), value=0x%x", mem, regName, psHu32(mem) ); - } - break; - - case 0x0b: - if( mem == D4_CHCR ) - HW_LOG("Hardware Read32 at 0x%x (IPU1:DMA4_CHCR), value=0x%x", mem, psHu32(mem)); - break; - - case 0x0c: - case 0x0d: - case 0x0e: - if( mem == DMAC_STAT ) - HW_LOG("DMAC_STAT Read32, value=0x%x", psHu32(DMAC_STAT)); - break; - - jNO_DEFAULT; - } - - // Optimization note: We masked 'mem' earlier, so it's safe to access PS2MEM_HW directly. - // (checked disasm, and MSVC 2008 fails to optimize it on its own) - - //return psHu32(mem); - return *((u32*)&PS2MEM_HW[masked_mem]); -} - - -__forceinline void __fastcall hwWrite32(u32 mem, u32 value) -{ - - if ((mem>=0x10002000) && (mem<0x10003000)) { //IPU regs - ipuWrite32(mem,value); - return; - } - if ((mem>=0x10003800) && (mem<0x10003c00)) { - vif0Write32(mem, value); - return; - } - if ((mem>=0x10003c00) && (mem<0x10004000)) { - vif1Write32(mem, value); - return; - } - - switch (mem) { - case 0x10000000: rcntWcount(0, value); break; - case 0x10000010: rcntWmode(0, value); break; - case 0x10000020: rcntWtarget(0, value); break; - case 0x10000030: rcntWhold(0, value); break; - - case 0x10000800: rcntWcount(1, value); break; - case 0x10000810: rcntWmode(1, value); break; - case 0x10000820: rcntWtarget(1, value); break; - case 0x10000830: rcntWhold(1, value); break; - - case 0x10001000: rcntWcount(2, value); break; - case 0x10001010: rcntWmode(2, value); break; - case 0x10001020: rcntWtarget(2, value); break; - - case 0x10001800: rcntWcount(3, value); break; - case 0x10001810: rcntWmode(3, value); break; - case 0x10001820: rcntWtarget(3, value); break; - - case GIF_CTRL: - //Console::WriteLn("GIF_CTRL write %x", params value); - psHu32(mem) = value & 0x8; - - if (value & 0x1) - gsGIFReset(); - else if( value & 8 ) - psHu32(GIF_STAT) |= 8; - else - psHu32(GIF_STAT) &= ~8; - - return; - - case GIF_MODE: - // need to set GIF_MODE (hamster ball) - psHu32(GIF_MODE) = value; - - if (value & 0x1) - psHu32(GIF_STAT)|= 0x1; - else - psHu32(GIF_STAT)&= ~0x1; - - if (value & 0x4) - psHu32(GIF_STAT)|= 0x4; - else - psHu32(GIF_STAT)&= ~0x4; - - break; - - case GIF_STAT: // stat is readonly - Console::WriteLn("Gifstat write value = %x", params value); - return; - - case 0x10008000: // dma0 - vif0 - DMA_LOG("VIF0dma %lx", value); - DmaExec(dmaVIF0, mem, value); - break; - - case 0x10009000: // dma1 - vif1 - chcr - DMA_LOG("VIF1dma CHCR %lx", value); - DmaExec(dmaVIF1, mem, value); - break; - -#ifdef PCSX2_DEVBUILD - case 0x10009010: // dma1 - vif1 - madr - HW_LOG("VIF1dma Madr %lx", value); - psHu32(mem) = value;//dma1 madr - break; - - case 0x10009020: // dma1 - vif1 - qwc - HW_LOG("VIF1dma QWC %lx", value); - psHu32(mem) = value;//dma1 qwc - break; - - case 0x10009030: // dma1 - vif1 - tadr - HW_LOG("VIF1dma TADR %lx", value); - psHu32(mem) = value;//dma1 tadr - break; - - case 0x10009040: // dma1 - vif1 - asr0 - HW_LOG("VIF1dma ASR0 %lx", value); - psHu32(mem) = value;//dma1 asr0 - break; - - case 0x10009050: // dma1 - vif1 - asr1 - HW_LOG("VIF1dma ASR1 %lx", value); - psHu32(mem) = value;//dma1 asr1 - break; - - case 0x10009080: // dma1 - vif1 - sadr - HW_LOG("VIF1dma SADR %lx", value); - psHu32(mem) = value;//dma1 sadr - break; -#endif - - case 0x1000a000: // dma2 - gif - DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value); - DmaExec(dmaGIF, mem, value); - break; - -#ifdef PCSX2_DEVBUILD - case 0x1000a010: - psHu32(mem) = value;//dma2 madr - HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value); - break; - - case 0x1000a020: - psHu32(mem) = value;//dma2 qwc - HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value); - break; - - case 0x1000a030: - psHu32(mem) = value;//dma2 taddr - HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value); - break; - - case 0x1000a040: - psHu32(mem) = value;//dma2 asr0 - HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value); - break; - - case 0x1000a050: - psHu32(mem) = value;//dma2 asr1 - HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value); - break; - - case 0x1000a080: - psHu32(mem) = value;//dma2 saddr - HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value); - break; -#endif - - case 0x1000b000: // dma3 - fromIPU - DMA_LOG("IPU0dma %lx", value); - DmaExec(dmaIPU0, mem, value); - break; - -#ifdef PCSX2_DEVBUILD - case 0x1000b010: - psHu32(mem) = value;//dma2 madr - HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value); - break; - - case 0x1000b020: - psHu32(mem) = value;//dma2 madr - HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value); - break; - - case 0x1000b030: - psHu32(mem) = value;//dma2 tadr - HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value); - break; - - case 0x1000b080: - psHu32(mem) = value;//dma2 saddr - HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value); - break; -#endif - - case 0x1000b400: // dma4 - toIPU - DMA_LOG("IPU1dma %lx", value); - DmaExec(dmaIPU1, mem, value); - break; - -#ifdef PCSX2_DEVBUILD - case 0x1000b410: - psHu32(mem) = value;//dma2 madr - HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value); - break; - - case 0x1000b420: - psHu32(mem) = value;//dma2 madr - HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value); - break; - - case 0x1000b430: - psHu32(mem) = value;//dma2 tadr - HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value); - break; - - case 0x1000b480: - psHu32(mem) = value;//dma2 saddr - HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value); - break; -#endif - case 0x1000c000: // dma5 - sif0 - DMA_LOG("SIF0dma %lx", value); - DmaExec(dmaSIF0, mem, value); - break; - - case 0x1000c400: // dma6 - sif1 - DMA_LOG("SIF1dma %lx", value); - DmaExec(dmaSIF1, mem, value); - break; - -#ifdef PCSX2_DEVBUILD - case 0x1000c420: // dma6 - sif1 - qwc - HW_LOG("SIF1dma QWC = %lx", value); - psHu32(mem) = value; - break; - - case 0x1000c430: // dma6 - sif1 - tadr - HW_LOG("SIF1dma TADR = %lx", value); - psHu32(mem) = value; - break; -#endif - case 0x1000c800: // dma7 - sif2 - DMA_LOG("SIF2dma %lx", value); - DmaExec(dmaSIF2, mem, value); - break; - - case 0x1000d000: // dma8 - fromSPR - DMA_LOG("fromSPRdma %lx", value); - DmaExec(dmaSPR0, mem, value); - break; - - case 0x1000d400: // dma9 - toSPR - DMA_LOG("toSPRdma %lx", value); - DmaExec(dmaSPR1, mem, value); - break; - - case 0x1000e000: // DMAC_CTRL - HW_LOG("DMAC_CTRL Write 32bit %x", value); - psHu32(0xe000) = value; - break; - - case 0x1000e010: // DMAC_STAT - HW_LOG("DMAC_STAT Write 32bit %x", value); - psHu16(0xe010)&= ~(value & 0xffff); // clear on 1 - psHu16(0xe012) ^= (u16)(value >> 16); - - cpuTestDMACInts(); - break; - - case 0x1000f000: // INTC_STAT - HW_LOG("INTC_STAT Write 32bit %x", value); - psHu32(0xf000)&=~value; - break; - - case 0x1000f010: // INTC_MASK - HW_LOG("INTC_MASK Write 32bit %x", value); - psHu32(0xf010) ^= (u16)value; - cpuTestINTCInts(); - break; - - case 0x1000f430://MCH_RICM: x:4|SA:12|x:5|SDEV:1|SOP:4|SBC:1|SDEV:5 - if ((((value >> 16) & 0xFFF) == 0x21) && (((value >> 6) & 0xF) == 1) && (((psHu32(0xf440) >> 7) & 1) == 0))//INIT & SRP=0 - rdram_sdevid = 0; // if SIO repeater is cleared, reset sdevid - psHu32(mem) = value & ~0x80000000; //kill the busy bit - break; - - case 0x1000f440://MCH_DRD: - psHu32(mem) = value; - break; - - case 0x1000f590: // DMAC_ENABLEW - HW_LOG("DMAC_ENABLEW Write 32bit %lx", value); - psHu32(0xf590) = value; - psHu32(0xf520) = value; - return; - - case 0x1000f200: - psHu32(mem) = value; - break; - - case 0x1000f220: - psHu32(mem) |= value; - break; - - case 0x1000f230: - psHu32(mem) &= ~value; - break; - - case 0x1000f240: - if(!(value & 0x100)) - psHu32(mem) &= ~0x100; - else - psHu32(mem) |= 0x100; - break; - - case 0x1000f260: - psHu32(mem) = 0; - break; - - case 0x1000f130: - case 0x1000f410: - HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val); - break; - - default: - psHu32(mem) = value; - HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)", mem, value, cpuRegs.CP0.n.Status.val); - break; - } -} - -#endif - -/* -__forceinline void hwWrite64(u32 mem, u64 value) -{ - u32 val32; - int i; - - if ((mem>=0x10002000) && (mem<=0x10002030)) { - ipuWrite64(mem, value); - return; - } - - if ((mem>=0x10003800) && (mem<0x10003c00)) { - vif0Write32(mem, value); return; - } - if ((mem>=0x10003c00) && (mem<0x10004000)) { - vif1Write32(mem, value); return; - } - - switch (mem) { - case GIF_CTRL: - DevCon::Status("GIF_CTRL write 64", params value); - psHu32(mem) = value & 0x8; - if(value & 0x1) { - gsGIFReset(); - //gsReset(); - } - else { - if( value & 8 ) psHu32(GIF_STAT) |= 8; - else psHu32(GIF_STAT) &= ~8; - } - - return; - - case GIF_MODE: -#ifdef GSPATH3FIX - Console::Status("GIFMODE64 %x", params value); -#endif - psHu64(GIF_MODE) = value; - if (value & 0x1) psHu32(GIF_STAT)|= 0x1; - else psHu32(GIF_STAT)&= ~0x1; - if (value & 0x4) psHu32(GIF_STAT)|= 0x4; - else psHu32(GIF_STAT)&= ~0x4; - break; - - case GIF_STAT: // stat is readonly - return; - - case 0x1000a000: // dma2 - gif - DMA_LOG("0x%8.8x hwWrite64: GSdma %lx", cpuRegs.cycle, value); - DmaExec(dmaGIF, mem, value); - break; - - case 0x1000e000: // DMAC_CTRL - HW_LOG("DMAC_CTRL Write 64bit %x", value); - psHu64(mem) = value; - break; - - case 0x1000e010: // DMAC_STAT - HW_LOG("DMAC_STAT Write 64bit %x", value); - val32 = (u32)value; - psHu16(0xe010)&= ~(val32 & 0xffff); // clear on 1 - val32 = val32 >> 16; - for (i=0; i<16; i++) { // reverse on 1 - if (val32 & (1<= 0x10004000 && mem < 0x10008000) { - WriteFIFO(mem, value); return; - } - - switch (mem) { - case 0x1000f590: // DMAC_ENABLEW - psHu32(0xf590) = *(u32*)value; - psHu32(0xf520) = *(u32*)value; - break; - case 0x1000f130: - case 0x1000f410: - case 0x1000f430: - break; - - default: - - psHu64(mem ) = value[0]; - psHu64(mem+8) = value[1]; - - HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)", mem, value[1], value[0], cpuRegs.CP0.n.Status.val); - break; - } -} -*/ \ No newline at end of file diff --git a/pcsx2/Hw.h b/pcsx2/Hw.h index 07f21049ce..2c7774f39f 100644 --- a/pcsx2/Hw.h +++ b/pcsx2/Hw.h @@ -21,25 +21,16 @@ extern u8 *psH; // hw mem -#define psHs8(mem) (*(s8 *)&PS2MEM_HW[(mem) & 0xffff]) -#define psHs16(mem) (*(s16*)&PS2MEM_HW[(mem) & 0xffff]) -#define psHs32(mem) (*(s32*)&PS2MEM_HW[(mem) & 0xffff]) -#define psHs64(mem) (*(s64*)&PS2MEM_HW[(mem) & 0xffff]) -#define psHu8(mem) (*(u8 *)&PS2MEM_HW[(mem) & 0xffff]) -#define psHu16(mem) (*(u16*)&PS2MEM_HW[(mem) & 0xffff]) -#define psHu32(mem) (*(u32*)&PS2MEM_HW[(mem) & 0xffff]) -#define psHu64(mem) (*(u64*)&PS2MEM_HW[(mem) & 0xffff]) - extern void CPU_INT( u32 n, s32 ecycle ); ////////////////////////////////////////////////////////////////////////// // Hardware FIFOs (128 bit access only!) // -// VIF0 -- 0x10004000 -- psH[0x4000] -// VIF1 -- 0x10005000 -- psH[0x5000] -// GIF -- 0x10006000 -- psH[0x6000] -// IPUout -- 0x10007000 -- psH[0x7000] -// IPUin -- 0x10007010 -- psH[0x7010] +// VIF0 -- 0x10004000 -- PS2MEM_HW[0x4000] +// VIF1 -- 0x10005000 -- PS2MEM_HW[0x5000] +// GIF -- 0x10006000 -- PS2MEM_HW[0x6000] +// IPUout -- 0x10007000 -- PS2MEM_HW[0x7000] +// IPUin -- 0x10007010 -- PS2MEM_HW[0x7010] void __fastcall ReadFIFO_page_4(u32 mem, mem128_t *out); void __fastcall ReadFIFO_page_5(u32 mem, mem128_t *out); @@ -73,177 +64,183 @@ struct DMACh { }; // HW defines +enum HWaddress +{ + RCNT0_COUNT = 0x10000000, + RCNT0_MODE = 0x10000010, + RCNT0_TARGET = 0x10000020, + RCNT0_HOLD = 0x10000030, -#define RCNT0_COUNT 0x10000000 -#define RCNT0_MODE 0x10000010 -#define RCNT0_TARGET 0x10000020 -#define RCNT0_HOLD 0x10000030 + RCNT1_COUNT = 0x10000800, + RCNT1_MODE = 0x10000810, + RCNT1_TARGET = 0x10000820, + RCNT1_HOLD = 0x10000830, -#define RCNT1_COUNT 0x10000800 -#define RCNT1_MODE 0x10000810 -#define RCNT1_TARGET 0x10000820 -#define RCNT1_HOLD 0x10000830 + RCNT2_COUNT = 0x10001000, + RCNT2_MODE = 0x10001010, + RCNT2_TARGET = 0x10001020, -#define RCNT2_COUNT 0x10001000 -#define RCNT2_MODE 0x10001010 -#define RCNT2_TARGET 0x10001020 + RCNT3_COUNT = 0x10001800, + RCNT3_MODE = 0x10001810, + RCNT3_TARGET = 0x10001820, -#define RCNT3_COUNT 0x10001800 -#define RCNT3_MODE 0x10001810 -#define RCNT3_TARGET 0x10001820 + IPU_CMD = 0x10002000, + IPU_CTRL = 0x10002010, + IPU_BP = 0x10002020, + IPU_TOP = 0x10002030, -#define IPU_CMD 0x10002000 -#define IPU_CTRL 0x10002010 -#define IPU_BP 0x10002020 -#define IPU_TOP 0x10002030 + GIF_CTRL = 0x10003000, + GIF_MODE = 0x10003010, + GIF_STAT = 0x10003020, + GIF_TAG0 = 0x10003040, + GIF_TAG1 = 0x10003050, + GIF_TAG2 = 0x10003060, + GIF_TAG3 = 0x10003070, + GIF_CNT = 0x10003080, + GIF_P3CNT = 0x10003090, + GIF_P3TAG = 0x100030A0, + GIF_FIFO = 0x10006000, -#define GIF_CTRL 0x10003000 -#define GIF_MODE 0x10003010 -#define GIF_STAT 0x10003020 -#define GIF_TAG0 0x10003040 -#define GIF_TAG1 0x10003050 -#define GIF_TAG2 0x10003060 -#define GIF_TAG3 0x10003070 -#define GIF_CNT 0x10003080 -#define GIF_P3CNT 0x10003090 -#define GIF_P3TAG 0x100030A0 - -#define GIF_FIFO 0x10006000 - -#define IPUout_FIFO 0x10007000 -#define IPUin_FIFO 0x10007010 + IPUout_FIFO = 0x10007000, + IPUin_FIFO = 0x10007010, //VIF0 -#define D0_CHCR 0x10008000 -#define D0_MADR 0x10008010 -#define D0_QWC 0x10008020 + D0_CHCR = 0x10008000, + D0_MADR = 0x10008010, + D0_QWC = 0x10008020, //VIF1 -#define D1_CHCR 0x10009000 -#define D1_MADR 0x10009010 -#define D1_QWC 0x10009020 -#define D1_TADR 0x10009030 -#define D1_ASR0 0x10009040 -#define D1_ASR1 0x10009050 -#define D1_SADR 0x10009080 + D1_CHCR = 0x10009000, + D1_MADR = 0x10009010, + D1_QWC = 0x10009020, + D1_TADR = 0x10009030, + D1_ASR0 = 0x10009040, + D1_ASR1 = 0x10009050, + D1_SADR = 0x10009080, //GS -#define D2_CHCR 0x1000A000 -#define D2_MADR 0x1000A010 -#define D2_QWC 0x1000A020 -#define D2_TADR 0x1000A030 -#define D2_ASR0 0x1000A040 -#define D2_ASR1 0x1000A050 -#define D2_SADR 0x1000A080 + D2_CHCR = 0x1000A000, + D2_MADR = 0x1000A010, + D2_QWC = 0x1000A020, + D2_TADR = 0x1000A030, + D2_ASR0 = 0x1000A040, + D2_ASR1 = 0x1000A050, + D2_SADR = 0x1000A080, //fromIPU -#define D3_CHCR 0x1000B000 -#define D3_MADR 0x1000B010 -#define D3_QWC 0x1000B020 -#define D3_TADR 0x1000B030 -#define D3_SADR 0x1000B080 + D3_CHCR = 0x1000B000, + D3_MADR = 0x1000B010, + D3_QWC = 0x1000B020, + D3_TADR = 0x1000B030, + D3_SADR = 0x1000B080, //toIPU -#define D4_CHCR 0x1000B400 -#define D4_MADR 0x1000B410 -#define D4_QWC 0x1000B420 -#define D4_TADR 0x1000B430 -#define D4_SADR 0x1000B480 + D4_CHCR = 0x1000B400, + D4_MADR = 0x1000B410, + D4_QWC = 0x1000B420, + D4_TADR = 0x1000B430, + D4_SADR = 0x1000B480, //SIF0 -#define D5_CHCR 0x1000C000 -#define D5_MADR 0x1000C010 -#define D5_QWC 0x1000C020 + D5_CHCR = 0x1000C000, + D5_MADR = 0x1000C010, + D5_QWC = 0x1000C020, //SIF1 -#define D6_CHCR 0x1000C400 -#define D6_MADR 0x1000C410 -#define D6_QWC 0x1000C420 + D6_CHCR = 0x1000C400, + D6_MADR = 0x1000C410, + D6_QWC = 0x1000C420, //SIF2 -#define D7_CHCR 0x1000C800 -#define D7_MADR 0x1000C810 -#define D7_QWC 0x1000C820 + D7_CHCR = 0x1000C800, + D7_MADR = 0x1000C810, + D7_QWC = 0x1000C820, //fromSPR -#define D8_CHCR 0x1000D000 -#define D8_MADR 0x1000D010 -#define D8_QWC 0x1000D020 -#define D8_SADR 0x1000D080 + D8_CHCR = 0x1000D000, + D8_MADR = 0x1000D010, + D8_QWC = 0x1000D020, + D8_SADR = 0x1000D080, + DMAC_CTRL = 0x1000E000, + DMAC_STAT = 0x1000E010, + DMAC_PCR = 0x1000E020, + DMAC_SQWC = 0x1000E030, + DMAC_RBSR = 0x1000E040, + DMAC_RBOR = 0x1000E050, + DMAC_STADR = 0x1000E060, -#define DMAC_CTRL 0x1000E000 -#define DMAC_STAT 0x1000E010 -#define DMAC_PCR 0x1000E020 -#define DMAC_SQWC 0x1000E030 -#define DMAC_RBSR 0x1000E040 -#define DMAC_RBOR 0x1000E050 -#define DMAC_STADR 0x1000E060 + INTC_STAT = 0x1000F000, + INTC_MASK = 0x1000F010, -#define INTC_STAT 0x1000F000 -#define INTC_MASK 0x1000F010 + SBUS_F220 = 0x1000F220, + SBUS_SMFLG = 0x1000F230, + SBUS_F240 = 0x1000F240, -#define SBUS_F220 0x1000F220 -#define SBUS_SMFLG 0x1000F230 -#define SBUS_F240 0x1000F240 + DMAC_ENABLER = 0x1000F520, + DMAC_ENABLEW = 0x1000F590, -#define DMAC_ENABLER 0x1000F520 -#define DMAC_ENABLEW 0x1000F590 + GS_PMODE = 0x12000000, + GS_SMODE1 = 0x12000010, + GS_SMODE2 = 0x12000020, + GS_SRFSH = 0x12000030, + GS_SYNCH1 = 0x12000040, + GS_SYNCH2 = 0x12000050, + GS_SYNCV = 0x12000060, + GS_DISPFB1 = 0x12000070, + GS_DISPLAY1 = 0x12000080, + GS_DISPFB2 = 0x12000090, + GS_DISPLAY2 = 0x120000A0, + GS_EXTBUF = 0x120000B0, + GS_EXTDATA = 0x120000C0, + GS_EXTWRITE = 0x120000D0, + GS_BGCOLOR = 0x120000E0, + GS_CSR = 0x12001000, + GS_IMR = 0x12001010, + GS_BUSDIR = 0x12001040, + GS_SIGLBLID = 0x12001080 +}; -#define SBFLG_IOPALIVE 0x10000 -#define SBFLG_IOPSYNC 0x40000 - -#define GS_PMODE 0x12000000 -#define GS_SMODE1 0x12000010 -#define GS_SMODE2 0x12000020 -#define GS_SRFSH 0x12000030 -#define GS_SYNCH1 0x12000040 -#define GS_SYNCH2 0x12000050 -#define GS_SYNCV 0x12000060 -#define GS_DISPFB1 0x12000070 -#define GS_DISPLAY1 0x12000080 -#define GS_DISPFB2 0x12000090 -#define GS_DISPLAY2 0x120000A0 -#define GS_EXTBUF 0x120000B0 -#define GS_EXTDATA 0x120000C0 -#define GS_EXTWRITE 0x120000D0 -#define GS_BGCOLOR 0x120000E0 -#define GS_CSR 0x12001000 -#define GS_IMR 0x12001010 -#define GS_BUSDIR 0x12001040 -#define GS_SIGLBLID 0x12001080 - -#define INTC_GS 0 -#define INTC_SBUS 1 -#define INTC_VBLANK_S 2 -#define INTC_VBLANK_E 3 -#define INTC_VIF0 4 -#define INTC_VIF1 5 -#define INTC_VU0 6 -#define INTC_VU1 7 -#define INTC_IPU 8 -#define INTC_TIM0 9 -#define INTC_TIM1 10 -#define INTC_TIM2 11 -#define INTC_TIM3 12 +#define SBFLG_IOPALIVE 0x10000 +#define SBFLG_IOPSYNC 0x40000 +enum INTCIrqs +{ + INTC_GS = 0, + INTC_SBUS, + INTC_VBLANK_S, + INTC_VBLANK_E, + INTC_VIF0, + INTC_VIF1, + INTC_VU0, + INTC_VU1, + INTC_IPU, + INTC_TIM0, + INTC_TIM1, + INTC_TIM2, + INTC_TIM3, +}; + #define DMAC_STAT_SIS (1<<13) // stall condition #define DMAC_STAT_MEIS (1<<14) // mfifo empty #define DMAC_STAT_BEIS (1<<15) // bus error #define DMAC_STAT_SIM (1<<29) // stall mask #define DMAC_STAT_MEIM (1<<30) // mfifo mask -#define DMAC_VIF0 0 -#define DMAC_VIF1 1 -#define DMAC_GIF 2 -#define DMAC_FROM_IPU 3 -#define DMAC_TO_IPU 4 -#define DMAC_SIF0 5 -#define DMAC_SIF1 6 -#define DMAC_SIF2 7 -#define DMAC_FROM_SPR 8 -#define DMAC_TO_SPR 9 -#define DMAC_ERROR 15 +enum DMACIrqs +{ + DMAC_VIF0 = 0, + DMAC_VIF1, + DMAC_GIF, + DMAC_FROM_IPU, + DMAC_TO_IPU, + DMAC_SIF0, + DMAC_SIF1, + DMAC_SIF2, + DMAC_FROM_SPR, + DMAC_TO_SPR, + DMAC_ERROR = 15, +}; #define VIF0_STAT_VPS_W (1) #define VIF0_STAT_VPS_D (2) @@ -275,35 +272,39 @@ struct DMACh { #define VIF1_STAT_ER1 (1<<13) #define VIF1_STAT_FDR (1<<23) +#define VIF_STAT_VPS_W (1) +#define VIF_STAT_VPS_D (2) +#define VIF_STAT_VPS_T (3) +#define VIF_STAT_VPS (3) +#define VIF_STAT_VEW (1<<2) +#define VIF_STAT_VGW (1<<3) +#define VIF_STAT_MRK (1<<6) +#define VIF_STAT_DBF (1<<7) +#define VIF_STAT_VSS (1<<8) +#define VIF_STAT_VFS (1<<9) +#define VIF_STAT_VIS (1<<10) +#define VIF_STAT_INT (1<<11) +#define VIF_STAT_ER0 (1<<12) +#define VIF_STAT_ER1 (1<<13) +#define VIF_STAT_FDR (1<<23) + //DMA interrupts & masks -#define BEISintr (0x8000) -#define VIF0intr (0x10001) -#define VIF1intr (0x20002) -#define GIFintr (0x40004) -#define IPU0intr (0x80008) -#define IPU1intr (0x100010) -#define SIF0intr (0x200020) -#define SIF1intr (0x400040) -#define SIF2intr (0x800080) -#define SPR0intr (0x1000100) -#define SPR1intr (0x2000200) -#define SISintr (0x20002000) -#define MEISintr (0x40004000) - -#define DMAend(dma, num) { \ - dma->chcr &= ~0x100; \ - psHu32(DMAC_STAT)|= 1<chcr &= ~0x100; + } + + return ptr; +} void hwInit(); void hwReset(); @@ -422,8 +438,8 @@ void hwDmacIrq(int n); int hwMFIFORead(u32 addr, u8 *data, u32 size); int hwMFIFOWrite(u32 addr, u8 *data, u32 size); -int hwDmacSrcChainWithStack(DMACh *dma, int id); -int hwDmacSrcChain(DMACh *dma, int id); +bool hwDmacSrcChainWithStack(DMACh *dma, int id); +bool hwDmacSrcChain(DMACh *dma, int id); int hwConstRead8 (u32 x86reg, u32 mem, u32 sign); int hwConstRead16(u32 x86reg, u32 mem, u32 sign); diff --git a/pcsx2/HwRead.cpp b/pcsx2/HwRead.cpp index bedf07fc46..2104c8acb8 100644 --- a/pcsx2/HwRead.cpp +++ b/pcsx2/HwRead.cpp @@ -61,34 +61,35 @@ __forceinline u8 hwRead8(u32 mem) switch (mem) { - case 0x10000000: ret = (u8)rcntRcount(0); break; - case 0x10000010: ret = (u8)counters[0].modeval; break; - case 0x10000020: ret = (u8)counters[0].target; break; - case 0x10000030: ret = (u8)counters[0].hold; break; + // Note: the values without defines = the defines + 1. + case RCNT0_COUNT: ret = (u8)rcntRcount(0); break; + case RCNT0_MODE: ret = (u8)counters[0].modeval; break; + case RCNT0_TARGET: ret = (u8)counters[0].target; break; + case RCNT0_HOLD: ret = (u8)counters[0].hold; break; case 0x10000001: ret = (u8)(rcntRcount(0)>>8); break; case 0x10000011: ret = (u8)(counters[0].modeval>>8); break; case 0x10000021: ret = (u8)(counters[0].target>>8); break; case 0x10000031: ret = (u8)(counters[0].hold>>8); break; - case 0x10000800: ret = (u8)rcntRcount(1); break; - case 0x10000810: ret = (u8)counters[1].modeval; break; - case 0x10000820: ret = (u8)counters[1].target; break; - case 0x10000830: ret = (u8)counters[1].hold; break; + case RCNT1_COUNT: ret = (u8)rcntRcount(1); break; + case RCNT1_MODE: ret = (u8)counters[1].modeval; break; + case RCNT1_TARGET: ret = (u8)counters[1].target; break; + case RCNT1_HOLD: ret = (u8)counters[1].hold; break; case 0x10000801: ret = (u8)(rcntRcount(1)>>8); break; case 0x10000811: ret = (u8)(counters[1].modeval>>8); break; case 0x10000821: ret = (u8)(counters[1].target>>8); break; case 0x10000831: ret = (u8)(counters[1].hold>>8); break; - case 0x10001000: ret = (u8)rcntRcount(2); break; - case 0x10001010: ret = (u8)counters[2].modeval; break; - case 0x10001020: ret = (u8)counters[2].target; break; + case RCNT2_COUNT: ret = (u8)rcntRcount(2); break; + case RCNT2_MODE: ret = (u8)counters[2].modeval; break; + case RCNT2_TARGET: ret = (u8)counters[2].target; break; case 0x10001001: ret = (u8)(rcntRcount(2)>>8); break; case 0x10001011: ret = (u8)(counters[2].modeval>>8); break; case 0x10001021: ret = (u8)(counters[2].target>>8); break; - case 0x10001800: ret = (u8)rcntRcount(3); break; - case 0x10001810: ret = (u8)counters[3].modeval; break; - case 0x10001820: ret = (u8)counters[3].target; break; + case RCNT3_COUNT: ret = (u8)rcntRcount(3); break; + case RCNT3_MODE: ret = (u8)counters[3].modeval; break; + case RCNT3_TARGET: ret = (u8)counters[3].target; break; case 0x10001801: ret = (u8)(rcntRcount(3)>>8); break; case 0x10001811: ret = (u8)(counters[3].modeval>>8); break; case 0x10001821: ret = (u8)(counters[3].target>>8); break; @@ -97,7 +98,7 @@ __forceinline u8 hwRead8(u32 mem) if ((mem & 0xffffff0f) == 0x1000f200) { if(mem == 0x1000f260) ret = 0; - else if(mem == 0x1000F240) { + else if(mem == SBUS_F240) { ret = psHu32(mem); //psHu32(mem) &= ~0x4000; } @@ -120,34 +121,34 @@ __forceinline u16 hwRead16(u32 mem) { u16 ret; - if( mem >= 0x10002000 && mem < 0x10008000 ) + if( mem >= IPU_CMD && mem < D0_CHCR ) Console::Notice("Unexpected hwRead16 from 0x%x", params mem); switch (mem) { - case 0x10000000: ret = (u16)rcntRcount(0); break; - case 0x10000010: ret = (u16)counters[0].modeval; break; - case 0x10000020: ret = (u16)counters[0].target; break; - case 0x10000030: ret = (u16)counters[0].hold; break; + case RCNT0_COUNT: ret = (u16)rcntRcount(0); break; + case RCNT0_MODE: ret = (u16)counters[0].modeval; break; + case RCNT0_TARGET: ret = (u16)counters[0].target; break; + case RCNT0_HOLD: ret = (u16)counters[0].hold; break; - case 0x10000800: ret = (u16)rcntRcount(1); break; - case 0x10000810: ret = (u16)counters[1].modeval; break; - case 0x10000820: ret = (u16)counters[1].target; break; - case 0x10000830: ret = (u16)counters[1].hold; break; + case RCNT1_COUNT: ret = (u16)rcntRcount(1); break; + case RCNT1_MODE: ret = (u16)counters[1].modeval; break; + case RCNT1_TARGET: ret = (u16)counters[1].target; break; + case RCNT1_HOLD: ret = (u16)counters[1].hold; break; - case 0x10001000: ret = (u16)rcntRcount(2); break; - case 0x10001010: ret = (u16)counters[2].modeval; break; - case 0x10001020: ret = (u16)counters[2].target; break; + case RCNT2_COUNT: ret = (u16)rcntRcount(2); break; + case RCNT2_MODE: ret = (u16)counters[2].modeval; break; + case RCNT2_TARGET: ret = (u16)counters[2].target; break; - case 0x10001800: ret = (u16)rcntRcount(3); break; - case 0x10001810: ret = (u16)counters[3].modeval; break; - case 0x10001820: ret = (u16)counters[3].target; break; + case RCNT3_COUNT: ret = (u16)rcntRcount(3); break; + case RCNT3_MODE: ret = (u16)counters[3].modeval; break; + case RCNT3_TARGET: ret = (u16)counters[3].target; break; default: if ((mem & 0xffffff0f) == 0x1000f200) { if(mem == 0x1000f260) ret = 0; - else if(mem == 0x1000F240) { + else if(mem == SBUS_F240) { ret = psHu16(mem) | 0x0102; psHu32(mem) &= ~0x4000; } diff --git a/pcsx2/HwWrite.cpp b/pcsx2/HwWrite.cpp index d3ef5196dd..fa5fbdd4ff 100644 --- a/pcsx2/HwWrite.cpp +++ b/pcsx2/HwWrite.cpp @@ -40,11 +40,22 @@ using namespace R5900; // dark cloud2 uses 8 bit DMAs register writes static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value ) { + u32 qwcRegister = (mem | 0x20) & ~0x1; //Need to remove the lower bit else we end up clearing TADR + //Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC if((value & 0x1) && (psHu8(mem) & 0x1) == 0x1 && (psHu32(DMAC_CTRL) & 0x1) == 1) { DMA_LOG( "DMAExec8 Attempt to run DMA while one is already active mem = %x", mem ); - return; } + + // Upper 16bits of QWC should not be written since QWC is 16bits in size. + if ((psHu32(qwcRegister) >> 16) != 0) + { + DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n", + qwcRegister, + psHu32(qwcRegister) >> 16); + psHu32(qwcRegister) = 0; + } + psHu8(mem) = (u8)value; if ((psHu8(mem) & 0x1) && (psHu32(DMAC_CTRL) & 0x1)) { @@ -55,11 +66,22 @@ static __forceinline void DmaExec8( void (*func)(), u32 mem, u8 value ) static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value ) { + u32 qwcRegister = mem | 0x20; + //Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC if((value & 0x100) && (psHu32(mem) & 0x100) == 0x100 && (psHu32(DMAC_CTRL) & 0x1) == 1) { DMA_LOG( "DMAExec16 Attempt to run DMA while one is already active mem = %x", mem); - return; } + + // Upper 16bits of QWC should not be written since QWC is 16bits in size. + if ((psHu32(qwcRegister) >> 16) != 0) + { + DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n", + qwcRegister, + psHu32(qwcRegister) >> 16); + psHu32(qwcRegister) = 0; + } + psHu16(mem) = (u16)value; if ((psHu16(mem) & 0x100) && (psHu32(DMAC_CTRL) & 0x1)) { @@ -70,11 +92,22 @@ static __forceinline void DmaExec16( void (*func)(), u32 mem, u16 value ) static void DmaExec( void (*func)(), u32 mem, u32 value ) { + u32 qwcRegister = mem | 0x20; + //Its invalid for the hardware to write a DMA while it is active, not without Suspending the DMAC if((value & 0x100) && (psHu32(mem) & 0x100) == 0x100 && (psHu32(DMAC_CTRL) & 0x1) == 1) { DMA_LOG( "DMAExec32 Attempt to run DMA while one is already active mem = %x", mem ); - return; } + + // Upper 16bits of QWC should not be written since QWC is 16bits in size. + if ((psHu32(qwcRegister) >> 16) != 0) + { + DMA_LOG("DMA QWC (%x) upper 16bits set to %x\n", + qwcRegister, + psHu32(qwcRegister) >> 16); + psHu32(qwcRegister) = 0; + } + /* Keep the old tag if in chain mode and hw doesnt set it*/ if( (value & 0xc) == 0x4 && (value & 0xffff0000) == 0) psHu32(mem) = (psHu32(mem) & 0xFFFF0000) | (u16)value; @@ -112,27 +145,27 @@ void hwWrite8(u32 mem, u8 value) { DevCon::Notice( "hwWrite8 to 0x%x = 0x%x", params mem, value ); switch (mem) { - case 0x10000000: rcntWcount(0, value); break; - case 0x10000010: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break; + case RCNT0_COUNT: rcntWcount(0, value); break; + case RCNT0_MODE: rcntWmode(0, (counters[0].modeval & 0xff00) | value); break; case 0x10000011: rcntWmode(0, (counters[0].modeval & 0xff) | value << 8); break; - case 0x10000020: rcntWtarget(0, value); break; - case 0x10000030: rcntWhold(0, value); break; + case RCNT0_TARGET: rcntWtarget(0, value); break; + case RCNT0_HOLD: rcntWhold(0, value); break; - case 0x10000800: rcntWcount(1, value); break; - case 0x10000810: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break; + case RCNT1_COUNT: rcntWcount(1, value); break; + case RCNT1_MODE: rcntWmode(1, (counters[1].modeval & 0xff00) | value); break; case 0x10000811: rcntWmode(1, (counters[1].modeval & 0xff) | value << 8); break; - case 0x10000820: rcntWtarget(1, value); break; - case 0x10000830: rcntWhold(1, value); break; + case RCNT1_TARGET: rcntWtarget(1, value); break; + case RCNT1_HOLD: rcntWhold(1, value); break; - case 0x10001000: rcntWcount(2, value); break; - case 0x10001010: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break; + case RCNT2_COUNT: rcntWcount(2, value); break; + case RCNT2_MODE: rcntWmode(2, (counters[2].modeval & 0xff00) | value); break; case 0x10001011: rcntWmode(2, (counters[2].modeval & 0xff) | value << 8); break; - case 0x10001020: rcntWtarget(2, value); break; + case RCNT2_TARGET: rcntWtarget(2, value); break; - case 0x10001800: rcntWcount(3, value); break; - case 0x10001810: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break; + case RCNT3_COUNT: rcntWcount(3, value); break; + case RCNT3_MODE: rcntWmode(3, (counters[3].modeval & 0xff00) | value); break; case 0x10001811: rcntWmode(3, (counters[3].modeval & 0xff) | value << 8); break; - case 0x10001820: rcntWtarget(3, value); break; + case RCNT3_TARGET: rcntWtarget(3, value); break; case 0x1000f180: if (value == '\n') { @@ -166,7 +199,7 @@ void hwWrite8(u32 mem, u8 value) { DevCon::Notice("8 bit VIF1 DMA Start while DMAC Disabled\n"); QueuedDMA |= 0x2; } - if(value & 0x1) vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO + if(value & 0x1) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO DmaExec8(dmaVIF1, mem, value); break; @@ -288,25 +321,25 @@ __forceinline void hwWrite16(u32 mem, u16 value) switch(mem) { - case 0x10000000: rcntWcount(0, value); break; - case 0x10000010: rcntWmode(0, value); break; - case 0x10000020: rcntWtarget(0, value); break; - case 0x10000030: rcntWhold(0, value); break; + case RCNT0_COUNT: rcntWcount(0, value); break; + case RCNT0_MODE: rcntWmode(0, value); break; + case RCNT0_TARGET: rcntWtarget(0, value); break; + case RCNT0_HOLD: rcntWhold(0, value); break; - case 0x10000800: rcntWcount(1, value); break; - case 0x10000810: rcntWmode(1, value); break; - case 0x10000820: rcntWtarget(1, value); break; - case 0x10000830: rcntWhold(1, value); break; + case RCNT1_COUNT: rcntWcount(1, value); break; + case RCNT1_MODE: rcntWmode(1, value); break; + case RCNT1_TARGET: rcntWtarget(1, value); break; + case RCNT1_HOLD: rcntWhold(1, value); break; - case 0x10001000: rcntWcount(2, value); break; - case 0x10001010: rcntWmode(2, value); break; - case 0x10001020: rcntWtarget(2, value); break; + case RCNT2_COUNT: rcntWcount(2, value); break; + case RCNT2_MODE: rcntWmode(2, value); break; + case RCNT2_TARGET: rcntWtarget(2, value); break; - case 0x10001800: rcntWcount(3, value); break; - case 0x10001810: rcntWmode(3, value); break; - case 0x10001820: rcntWtarget(3, value); break; + case RCNT3_COUNT: rcntWcount(3, value); break; + case RCNT3_MODE: rcntWmode(3, value); break; + case RCNT3_TARGET: rcntWtarget(3, value); break; - case 0x10008000: // dma0 - vif0 + case D0_CHCR: // dma0 - vif0 DMA_LOG("VIF0dma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -316,46 +349,46 @@ __forceinline void hwWrite16(u32 mem, u16 value) DmaExec16(dmaVIF0, mem, value); break; - case 0x10009000: // dma1 - vif1 - chcr + case D1_CHCR: // dma1 - vif1 - chcr DMA_LOG("VIF1dma CHCR %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { DevCon::Notice("16 bit VIF1 DMA Start while DMAC Disabled\n"); QueuedDMA |= 0x2; } - if(value & 0x100) vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO + if(value & 0x100) vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO DmaExec16(dmaVIF1, mem, value); break; #ifdef PCSX2_DEVBUILD - case 0x10009010: // dma1 - vif1 - madr + case D1_MADR: // dma1 - vif1 - madr HW_LOG("VIF1dma Madr %lx", value); psHu16(mem) = value;//dma1 madr break; - case 0x10009020: // dma1 - vif1 - qwc + case D1_QWC: // dma1 - vif1 - qwc HW_LOG("VIF1dma QWC %lx", value); psHu16(mem) = value;//dma1 qwc break; - case 0x10009030: // dma1 - vif1 - tadr + case D1_TADR: // dma1 - vif1 - tadr HW_LOG("VIF1dma TADR %lx", value); psHu16(mem) = value;//dma1 tadr break; - case 0x10009040: // dma1 - vif1 - asr0 + case D1_ASR0: // dma1 - vif1 - asr0 HW_LOG("VIF1dma ASR0 %lx", value); psHu16(mem) = value;//dma1 asr0 break; - case 0x10009050: // dma1 - vif1 - asr1 + case D1_ASR1: // dma1 - vif1 - asr1 HW_LOG("VIF1dma ASR1 %lx", value); psHu16(mem) = value;//dma1 asr1 break; - case 0x10009080: // dma1 - vif1 - sadr + case D1_SADR: // dma1 - vif1 - sadr HW_LOG("VIF1dma SADR %lx", value); psHu16(mem) = value;//dma1 sadr break; #endif // --------------------------------------------------- - case 0x1000a000: // dma2 - gif + case D2_CHCR: // dma2 - gif DMA_LOG("0x%8.8x hwWrite32: GSdma %lx", cpuRegs.cycle, value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -366,33 +399,33 @@ __forceinline void hwWrite16(u32 mem, u16 value) break; #ifdef PCSX2_DEVBUILD - case 0x1000a010: + case D2_MADR: psHu16(mem) = value;//dma2 madr HW_LOG("Hardware write DMA2_MADR 32bit at %x with value %x",mem,value); break; - case 0x1000a020: - psHu16(mem) = value;//dma2 qwc - HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value); - break; - case 0x1000a030: - psHu16(mem) = value;//dma2 taddr - HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value); - break; - case 0x1000a040: - psHu16(mem) = value;//dma2 asr0 - HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value); - break; - case 0x1000a050: - psHu16(mem) = value;//dma2 asr1 - HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value); - break; - case 0x1000a080: - psHu16(mem) = value;//dma2 saddr - HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value); - break; + case D2_QWC: + psHu16(mem) = value;//dma2 qwc + HW_LOG("Hardware write DMA2_QWC 32bit at %x with value %x",mem,value); + break; + case D2_TADR: + psHu16(mem) = value;//dma2 taddr + HW_LOG("Hardware write DMA2_TADDR 32bit at %x with value %x",mem,value); + break; + case D2_ASR0: + psHu16(mem) = value;//dma2 asr0 + HW_LOG("Hardware write DMA2_ASR0 32bit at %x with value %x",mem,value); + break; + case D2_ASR1: + psHu16(mem) = value;//dma2 asr1 + HW_LOG("Hardware write DMA2_ASR1 32bit at %x with value %x",mem,value); + break; + case D2_SADR: + psHu16(mem) = value;//dma2 saddr + HW_LOG("Hardware write DMA2_SADDR 32bit at %x with value %x",mem,value); + break; #endif - case 0x1000b000: // dma3 - fromIPU + case D3_CHCR: // dma3 - fromIPU DMA_LOG("IPU0dma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -403,25 +436,25 @@ __forceinline void hwWrite16(u32 mem, u16 value) break; #ifdef PCSX2_DEVBUILD - case 0x1000b010: + case D3_MADR: psHu16(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_MADR 32bit at %x with value %x",mem,value); break; - case 0x1000b020: - psHu16(mem) = value;//dma2 madr + case D3_QWC: + psHu16(mem) = value;//dma2 madr HW_LOG("Hardware write IPU0DMA_QWC 32bit at %x with value %x",mem,value); break; - case 0x1000b030: + case D3_TADR: psHu16(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU0DMA_TADR 32bit at %x with value %x",mem,value); break; - case 0x1000b080: + case D3_SADR: psHu16(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU0DMA_SADDR 32bit at %x with value %x",mem,value); break; #endif - case 0x1000b400: // dma4 - toIPU + case D4_CHCR: // dma4 - toIPU DMA_LOG("IPU1dma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -432,24 +465,24 @@ __forceinline void hwWrite16(u32 mem, u16 value) break; #ifdef PCSX2_DEVBUILD - case 0x1000b410: - psHu16(mem) = value;//dma2 madr + case D4_MADR: + psHu16(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_MADR 32bit at %x with value %x",mem,value); break; - case 0x1000b420: - psHu16(mem) = value;//dma2 madr + case D4_QWC: + psHu16(mem) = value;//dma2 madr HW_LOG("Hardware write IPU1DMA_QWC 32bit at %x with value %x",mem,value); break; - case 0x1000b430: + case D4_TADR: psHu16(mem) = value;//dma2 tadr HW_LOG("Hardware write IPU1DMA_TADR 32bit at %x with value %x",mem,value); break; - case 0x1000b480: + case D4_SADR: psHu16(mem) = value;//dma2 saddr HW_LOG("Hardware write IPU1DMA_SADDR 32bit at %x with value %x",mem,value); break; #endif - case 0x1000c000: // dma5 - sif0 + case D5_CHCR: // dma5 - sif0 DMA_LOG("SIF0dma %lx", value); // if (value == 0) psxSu32(0x30) = 0x40000; if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) @@ -463,7 +496,7 @@ __forceinline void hwWrite16(u32 mem, u16 value) case 0x1000c002: //? break; - case 0x1000c400: // dma6 - sif1 + case D6_CHCR: // dma6 - sif1 DMA_LOG("SIF1dma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -474,7 +507,8 @@ __forceinline void hwWrite16(u32 mem, u16 value) break; #ifdef PCSX2_DEVBUILD - case 0x1000c420: // dma6 - sif1 - qwc + // No D6_MADR, and a TADR address that's not in the defines? + case D6_QWC: // dma6 - sif1 - qwc HW_LOG("SIF1dma QWC = %lx", value); psHu16(mem) = value; break; @@ -485,7 +519,7 @@ __forceinline void hwWrite16(u32 mem, u16 value) break; #endif - case 0x1000c800: // dma7 - sif2 + case D7_CHCR: // dma7 - sif2 DMA_LOG("SIF2dma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -497,7 +531,7 @@ __forceinline void hwWrite16(u32 mem, u16 value) case 0x1000c802: //? break; - case 0x1000d000: // dma8 - fromSPR + case D8_CHCR: // dma8 - fromSPR DMA_LOG("fromSPRdma %lx", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -532,13 +566,13 @@ __forceinline void hwWrite16(u32 mem, u16 value) psHu16(mem) = value; break; - case 0x1000f220: + case SBUS_F220: psHu16(mem) |= value; break; - case 0x1000f230: + case SBUS_SMFLG: psHu16(mem) &= ~value; break; - case 0x1000f240: + case SBUS_F240: if(!(value & 0x100)) psHu16(mem) &= ~0x100; else @@ -762,13 +796,13 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value ) case HELPSWITCH(0x1000f200): psHu32(mem) = value; break; - case HELPSWITCH(0x1000f220): + case HELPSWITCH(SBUS_F220): psHu32(mem) |= value; break; - case HELPSWITCH(0x1000f230): + case HELPSWITCH(SBUS_SMFLG): psHu32(mem) &= ~value; break; - case HELPSWITCH(0x1000f240): + case HELPSWITCH(SBUS_F240): if(!(value & 0x100)) psHu32(mem) &= ~0x100; else @@ -782,7 +816,7 @@ void __fastcall hwWrite32_page_0F( u32 mem, u32 value ) psHu32(mem) = value; break; - case HELPSWITCH(0x1000f590): // DMAC_ENABLEW + case HELPSWITCH(DMAC_ENABLEW): // DMAC_ENABLEW HW_LOG("DMAC_ENABLEW Write 32bit %lx", value); psHu32(0xf590) = value; psHu32(0xf520) = value; @@ -826,7 +860,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) } if(value & 0x100) { - vif1.done = 0; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO + vif1.done = false; //This must be done here! some games (ala Crash of the Titans) pause the dma to start MFIFO } DmaExec(dmaVIF1, mem, value); return; @@ -850,14 +884,14 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) return; case D2_MADR: regName = "GIFdma MADR"; break; - case D2_QWC: regName = "GIFdma QWC"; break; - case D2_TADR: regName = "GIFdma TADDR"; break; - case D2_ASR0: regName = "GIFdma ASR0"; break; - case D2_ASR1: regName = "GIFdma ASR1"; break; - case D2_SADR: regName = "GIFdma SADDR"; break; + case D2_QWC: regName = "GIFdma QWC"; break; + case D2_TADR: regName = "GIFdma TADDR"; break; + case D2_ASR0: regName = "GIFdma ASR0"; break; + case D2_ASR1: regName = "GIFdma ASR1"; break; + case D2_SADR: regName = "GIFdma SADDR"; break; //------------------------------------------------------------------ - case 0x1000c000: // dma5 - sif0 + case D5_CHCR: // dma5 - sif0 DMA_LOG("SIF0dma EXECUTE, value=0x%x", value); //if (value == 0) psxSu32(0x30) = 0x40000; if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) @@ -868,7 +902,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) DmaExec(dmaSIF0, mem, value); return; //------------------------------------------------------------------ - case 0x1000c400: // dma6 - sif1 + case D6_CHCR: // dma6 - sif1 DMA_LOG("SIF1dma EXECUTE, value=0x%x", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -878,11 +912,12 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) DmaExec(dmaSIF1, mem, value); return; - case 0x1000c420: regName = "SIF1dma QWC"; break; + // Again, no MADR, and an undefined TADR. + case D6_QWC: regName = "SIF1dma QWC"; break; case 0x1000c430: regName = "SIF1dma TADR"; break; //------------------------------------------------------------------ - case 0x1000c800: // dma7 - sif2 + case D7_CHCR: // dma7 - sif2 DMA_LOG("SIF2dma EXECUTE, value=0x%x", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -892,7 +927,7 @@ void __fastcall hwWrite32_generic( u32 mem, u32 value ) DmaExec(dmaSIF2, mem, value); return; //------------------------------------------------------------------ - case 0x1000d000: // dma8 - fromSPR + case D8_CHCR: // dma8 - fromSPR DMA_LOG("SPR0dma EXECUTE (fromSPR), value=0x%x", value); if ((value & 0x100) && !(psHu32(DMAC_CTRL) & 0x1)) { @@ -1015,7 +1050,7 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval ) switch (mem) { - case 0x1000a000: // dma2 - gif + case D2_CHCR: // dma2 - gif DMA_LOG("0x%8.8x hwWrite64: GSdma %x", cpuRegs.cycle, value); DmaExec(dmaGIF, mem, value); break; @@ -1037,7 +1072,7 @@ void __fastcall hwWrite64_generic( u32 mem, const mem64_t* srcval ) case 0x1000f430: break; - case 0x1000f590: // DMAC_ENABLEW + case DMAC_ENABLEW: // DMAC_ENABLEW psHu32(0xf590) = value; psHu32(0xf520) = value; break; @@ -1070,7 +1105,7 @@ void __fastcall hwWrite128_generic(u32 mem, const mem128_t *srcval) cpuTestINTCInts(); break; - case 0x1000f590: // DMAC_ENABLEW + case DMAC_ENABLEW: // DMAC_ENABLEW psHu32(0xf590) = srcval[0]; psHu32(0xf520) = srcval[0]; break; diff --git a/pcsx2/IPU/IPU.cpp b/pcsx2/IPU/IPU.cpp index 3c481ccb0a..e8f9fa72a6 100644 --- a/pcsx2/IPU/IPU.cpp +++ b/pcsx2/IPU/IPU.cpp @@ -48,11 +48,6 @@ using namespace std; // for min / max # define IPU_FORCEINLINE __forceinline #endif -//IPUregisters g_ipuRegsReal; - -#define ipu0dma ((DMACh *)&PS2MEM_HW[0xb000]) -#define ipu1dma ((DMACh *)&PS2MEM_HW[0xb400]) - #define IPU_DMA_GIFSTALL 1 #define IPU_DMA_TIE0 2 #define IPU_DMA_TIE1 4 @@ -369,7 +364,7 @@ __forceinline void ipuWrite64(u32 mem, u64 value) switch (mem) { - case 0x10: + case 0x00: IPU_LOG("Ipu write64: IPU_CMD=0x%08X", value); IPUCMD_WRITE((u32)value); break; @@ -1372,9 +1367,11 @@ int FIFOto_write(u32* pMem, int size) g_nDMATransfer |= IPU_DMA_ACTV1; \ return totalqwc; \ } \ - } \ + } \ } +extern void gsInterrupt(); + int IPU1dma() { u32 *ptag, *pMem; @@ -1388,6 +1385,13 @@ int IPU1dma() assert(!(g_nDMATransfer & IPU_DMA_TIE1)); + //We need to make sure GIF has flushed before sending IPU data, it seems to REALLY screw FFX videos + while(gif->chcr & 0x100) + { + GIF_LOG("Flushing gif chcr %x tadr %x madr %x qwc %x", gif->chcr, gif->tadr, gif->madr, gif->qwc); + gsInterrupt(); + } + // in kh, qwc == 0 when dma_actv1 is set if ((g_nDMATransfer & IPU_DMA_ACTV1) && ipu1dma->qwc > 0) { @@ -1404,8 +1408,6 @@ int IPU1dma() return totalqwc; } - g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1); - if ((ipu1dma->chcr&0xc) == 0) { IPU_INT_TO(totalqwc*BIAS); @@ -1449,6 +1451,8 @@ int IPU1dma() return totalqwc; } } + + g_nDMATransfer &= ~(IPU_DMA_ACTV1 | IPU_DMA_DOTIE1); } if ((ipu1dma->chcr & 0xc) == 0 && ipu1dma->qwc == 0) // Normal Mode diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index 533c6ca1a5..9e915c6de3 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -112,7 +112,8 @@ void __fastcall intDoBranch(u32 target) } } -void intSetBranch() { +void intSetBranch() +{ branch2 = /*cpuRegs.branch =*/ 1; } @@ -133,90 +134,223 @@ namespace OpcodeImpl { * Format: OP target * *********************************************************/ -void J() { +void J() +{ doBranch(_JumpTarget_); } -void JAL() { - _SetLink(31); doBranch(_JumpTarget_); +void JAL() +{ + _SetLink(31); + doBranch(_JumpTarget_); } /********************************************************* * Register branch logic * * Format: OP rs, rt, offset * *********************************************************/ -#define RepBranchi32(op) \ - if (cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) doBranch(_BranchTarget_); \ - else intEventTest(); +void BEQ() // Branch if Rs == Rt +{ + if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) + doBranch(_BranchTarget_); + else + intEventTest(); +} -void BEQ() { RepBranchi32(==) } // Branch if Rs == Rt -void BNE() { RepBranchi32(!=) } // Branch if Rs != Rt +void BNE() // Branch if Rs != Rt +{ + if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) + doBranch(_BranchTarget_); + else + intEventTest(); +} /********************************************************* * Register branch logic * * Format: OP rs, offset * *********************************************************/ -#define RepZBranchi32(op) \ - if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ - doBranch(_BranchTarget_); \ - } -#define RepZBranchLinki32(op) \ +void BGEZ() // Branch if Rs >= 0 +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0) + { + doBranch(_BranchTarget_); + } +} + +void BGEZAL() // Branch if Rs >= 0 and link +{ + _SetLink(31); + + if (cpuRegs.GPR.r[_Rs_].SD[0] >= 0) + { + doBranch(_BranchTarget_); + } +} + +void BGTZ() // Branch if Rs > 0 +{ + if (cpuRegs.GPR.r[_Rs_].SD[0] > 0) + { + doBranch(_BranchTarget_); + } +} + +void BLEZ() // Branch if Rs <= 0 +{ + if (cpuRegs.GPR.r[_Rs_].SD[0] <= 0) + { + doBranch(_BranchTarget_); + } +} + +void BLTZ() // Branch if Rs < 0 +{ + if (cpuRegs.GPR.r[_Rs_].SD[0] < 0) + { + doBranch(_BranchTarget_); + } +} + +void BLTZAL() // Branch if Rs < 0 and link +{ _SetLink(31); \ - if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ - doBranch(_BranchTarget_); \ + if (cpuRegs.GPR.r[_Rs_].SD[0] < 0) + { + doBranch(_BranchTarget_); } - -void BGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 -void BGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link -void BGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 -void BLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 -void BLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 -void BLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link - +} /********************************************************* * Register branch logic Likely * * Format: OP rs, offset * *********************************************************/ -#define RepZBranchi32Likely(op) \ - if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ - doBranch(_BranchTarget_); \ - } else { cpuRegs.pc +=4; intEventTest(); } - -#define RepZBranchLinki32Likely(op) \ - _SetLink(31); \ - if(cpuRegs.GPR.r[_Rs_].SD[0] op 0) { \ - doBranch(_BranchTarget_); \ - } else { cpuRegs.pc +=4; intEventTest(); } - -#define RepBranchi32Likely(op) \ - if(cpuRegs.GPR.r[_Rs_].SD[0] op cpuRegs.GPR.r[_Rt_].SD[0]) { \ - doBranch(_BranchTarget_); \ - } else { cpuRegs.pc +=4; intEventTest(); } -void BEQL() { RepBranchi32Likely(==) } // Branch if Rs == Rt -void BNEL() { RepBranchi32Likely(!=) } // Branch if Rs != Rt -void BLEZL() { RepZBranchi32Likely(<=) } // Branch if Rs <= 0 -void BGTZL() { RepZBranchi32Likely(>) } // Branch if Rs > 0 -void BLTZL() { RepZBranchi32Likely(<) } // Branch if Rs < 0 -void BGEZL() { RepZBranchi32Likely(>=) } // Branch if Rs >= 0 -void BLTZALL() { RepZBranchLinki32Likely(<) } // Branch if Rs < 0 and link -void BGEZALL() { RepZBranchLinki32Likely(>=) } // Branch if Rs >= 0 and link +void BEQL() // Branch if Rs == Rt +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BNEL() // Branch if Rs != Rt +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BLEZL() // Branch if Rs <= 0 +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] <= 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BGTZL() // Branch if Rs > 0 +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] > 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BLTZL() // Branch if Rs < 0 +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] < 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BGEZL() // Branch if Rs >= 0 +{ + if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BLTZALL() // Branch if Rs < 0 and link +{ + _SetLink(31); + + if(cpuRegs.GPR.r[_Rs_].SD[0] < 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} + +void BGEZALL() // Branch if Rs >= 0 and link +{ + _SetLink(31); + + if(cpuRegs.GPR.r[_Rs_].SD[0] >= 0) + { + doBranch(_BranchTarget_); + } + else + { + cpuRegs.pc +=4; + intEventTest(); + } +} /********************************************************* * Register jump * * Format: OP rs, rd * *********************************************************/ -void JR() { +void JR() +{ doBranch(cpuRegs.GPR.r[_Rs_].UL[0]); } -void JALR() { +void JALR() +{ u32 temp = cpuRegs.GPR.r[_Rs_].UL[0]; - if (_Rd_) { _SetLink(_Rd_); } + + if (_Rd_) _SetLink(_Rd_); + doBranch(temp); } @@ -235,7 +369,7 @@ void intReset() branch2 = 0; } -bool intEventTest() + bool intEventTest() { // Perform counters, ints, and IOP updates: return _cpuBranchTest_Shared(); diff --git a/pcsx2/IopCommon.h b/pcsx2/IopCommon.h index 27b8341f4d..18b2161e32 100644 --- a/pcsx2/IopCommon.h +++ b/pcsx2/IopCommon.h @@ -29,10 +29,10 @@ #include "Sio.h" #include "Sif.h" +#include "IopDma.h" #include "IopMem.h" #include "IopHw.h" #include "IopBios.h" -#include "IopDma.h" #include "IopCounters.h" #include "IopSio2.h" diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index 1152854a19..664dceb228 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -38,8 +38,7 @@ #define PSXPIXEL ((int)(PSXCLK / 13500000)) #define PSXSOUNDCLK ((int)(48000)) - -psxCounter psxCounters[8]; +psxCounter psxCounters[NUM_COUNTERS]; s32 psxNextCounter; u32 psxNextsCounter; u8 psxhblankgate = 0; @@ -141,6 +140,12 @@ void psxRcntInit() { psxCounters[7].mode = 0x8; } +#ifdef ENABLE_NEW_IOPDMA + psxCounters[8].rate = 2000; + psxCounters[8].CycleT = psxCounters[7].rate; + psxCounters[8].mode = 0x8; +#endif + for (i=0; i<8; i++) psxCounters[i].sCycleT = psxRegs.cycle; @@ -453,6 +458,24 @@ void psxRcntUpdate() if (c < psxNextCounter) psxNextCounter = c; } +#ifdef ENABLE_NEW_IOPDMA + + // New Iop DMA handler WIP + { + const s32 difference = psxRegs.cycle - psxCounters[8].sCycleT; + s32 c = psxCounters[8].CycleT; + + if(difference >= psxCounters[8].CycleT) + { + psxCounters[8].sCycleT = psxRegs.cycle; + psxCounters[8].CycleT = psxCounters[8].rate; + IopDmaUpdate(difference); + } + else c -= difference; + if (c < psxNextCounter) psxNextCounter = c; + } +#endif + for (i=0; i<6; i++) _rcntSet( i ); } diff --git a/pcsx2/IopCounters.h b/pcsx2/IopCounters.h index 69c56acd74..8a743408f0 100644 --- a/pcsx2/IopCounters.h +++ b/pcsx2/IopCounters.h @@ -27,7 +27,13 @@ struct psxCounter { s32 CycleT; }; -extern psxCounter psxCounters[8]; +#ifdef ENABLE_NEW_IOPDMA +# define NUM_COUNTERS 9 +#else +# define NUM_COUNTERS 8 +#endif + +extern psxCounter psxCounters[NUM_COUNTERS]; extern s32 psxNextCounter; extern u32 psxNextsCounter; diff --git a/pcsx2/IopDma.cpp b/pcsx2/IopDma.cpp index 7798779a92..1af6cef622 100644 --- a/pcsx2/IopDma.cpp +++ b/pcsx2/IopDma.cpp @@ -28,6 +28,7 @@ using namespace R3000A; // Should be a bool, and will be next time I break savestate. --arcum42 int iopsifbusy[2] = { 0, 0 }; +extern int eesifbusy[2]; static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc, _SPU2readDMA4Mem spu2ReadFunc) { @@ -74,6 +75,14 @@ static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _ } } +void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU +{ + HW_DMA2_CHCR &= ~0x01000000; + psxDmaInterrupt(2); +} + +/* psxDma3 is in CdRom.cpp */ + void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0 { psxDmaGeneric(madr, bcr, chcr, 0, SPU2writeDMA4Mem, SPU2readDMA4Mem); @@ -87,12 +96,6 @@ int psxDma4Interrupt() return 1; } -void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU -{ - HW_DMA2_CHCR &= ~0x01000000; - psxDmaInterrupt(2); -} - void psxDma6(u32 madr, u32 bcr, u32 chcr) { u32 *mem = (u32 *)iopPhysMem(madr); @@ -130,7 +133,32 @@ int psxDma7Interrupt() return 1; } -extern int eesifbusy[2]; + +void psxDma8(u32 madr, u32 bcr, u32 chcr) +{ + + const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8; + + switch (chcr & 0x01000201) + { + case 0x01000201: //cpu to dev9 transfer + PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr); + DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size); + break; + + case 0x01000200: //dev9 to cpu transfer + PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr); + DEV9readDMA8Mem((u32*)iopPhysMem(madr), size); + break; + + default: + PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr); + break; + } + HW_DMA8_CHCR &= ~0x01000000; + psxDmaInterrupt2(1); +} + void psxDma9(u32 madr, u32 bcr, u32 chcr) { SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx", chcr, madr, bcr, HW_DMA9_TADR); @@ -164,32 +192,9 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) } } -void psxDma8(u32 madr, u32 bcr, u32 chcr) -{ +/* psxDma11 & psxDma 12 are in IopSio2,cpp, along with the appropriate interrupt functions. */ - const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8; - - switch (chcr & 0x01000201) - { - case 0x01000201: //cpu to dev9 transfer - PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr); - DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size); - break; - - case 0x01000200: //dev9 to cpu transfer - PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr); - DEV9readDMA8Mem((u32*)iopPhysMem(madr), size); - break; - - default: - PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx", chcr, madr, bcr); - break; - } - HW_DMA8_CHCR &= ~0x01000000; - psxDmaInterrupt2(1); -} - -void dev9Interrupt() +void dev9Interrupt() { if ((dev9Handler != NULL) && (dev9Handler() != 1)) return; @@ -202,7 +207,7 @@ void dev9Irq(int cycles) PSX_INT(IopEvt_DEV9, cycles); } -void usbInterrupt() +void usbInterrupt() { if (usbHandler != NULL && (usbHandler() != 1)) return; @@ -253,35 +258,96 @@ void iopIntcIrq(uint irqType) // // fixme: Is this in progress? -#if FALSE +#ifdef ENABLE_NEW_IOPDMA -typedef s32(* DmaHandler)(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); -typedef void (* DmaIHandler)(s32 channel); - -s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); -s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed); - -struct DmaHandlerInfo +s32 spu2DmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - DmaHandler Read; - DmaHandler Write; - DmaIHandler Interrupt; -}; + // FIXME: change the plugin interfaces so that they are aware of this new dma handler -struct DmaStatusInfo + /* + u32 bytes = 1024; + if(bytesLeft<1024) + bytes=bytesLeft; + */ + u32 bytes=bytesLeft; + + // Update the spu2 to the current cycle before initiating the DMA + if (SPU2async) + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); + + psxCounters[6].sCycleT = psxRegs.cycle; + psxCounters[6].CycleT = bytes * 3; + + psxNextCounter -= (psxRegs.cycle - psxNextsCounter); + psxNextsCounter = psxRegs.cycle; + if (psxCounters[6].CycleT < psxNextCounter) + psxNextCounter = psxCounters[6].CycleT; + } + + if(channel==7) + SPU2readDMA7Mem((u16 *)data, bytes/2); + else + SPU2readDMA4Mem((u16 *)data, bytes/2); + + *bytesProcessed = bytes; + + return 0; +} + +s32 spu2DmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - u32 Control; - u32 Width; // bytes/word, for timing purposes - u32 MemAddr; - u32 ByteCount; - u32 Target; -}; + // FIXME: change the plugin interfaces so that they are aware of this new dma handler -// FIXME: Dummy constants, to be "filled in" with proper values later -#define DMA_CTRL_ACTIVE 0x80000000 -#define DMA_CTRL_DIRECTION 0x00000001 -#define DMA_CHANNEL_MAX 16 /* ? */ + /* + u32 bytes = 1024; + if(bytesLeft<1024) + bytes=bytesLeft; + */ + u32 bytes=bytesLeft; + + + // Update the spu2 to the current cycle before initiating the DMA + if (SPU2async) + { + SPU2async(psxRegs.cycle - psxCounters[6].sCycleT); + //Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT); + + psxCounters[6].sCycleT = psxRegs.cycle; + psxCounters[6].CycleT = bytes * 3; + + psxNextCounter -= (psxRegs.cycle - psxNextsCounter); + psxNextsCounter = psxRegs.cycle; + if (psxCounters[6].CycleT < psxNextCounter) + psxNextCounter = psxCounters[6].CycleT; + } + + if(channel==7) + SPU2writeDMA7Mem((u16 *)data, bytes/2); + else + SPU2writeDMA4Mem((u16 *)data, bytes/2); + + + *bytesProcessed = bytes; + + return 0; +} + +void spu2DmaInterrupt(s32 channel) +{ + if(channel==7) + SPU2interruptDMA7(); + else + SPU2interruptDMA4(); +} + +//typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +//typedef void (* DmaIHandler)(s32 channel); + +s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); DmaStatusInfo IopChannels[DMA_CHANNEL_MAX]; // I dont' knwo how many there are, 10? @@ -295,9 +361,9 @@ DmaHandlerInfo IopDmaHandlers[DMA_CHANNEL_MAX] = {0}, //5 {0}, //6: OT? {spu2DmaRead, spu2DmaWrite, spu2DmaInterrupt}, //7: Spu Core1 - {dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9 - {sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0 - {sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1 + {0},//{dev9DmaRead, dev9DmaWrite, dev9DmaInterrupt}, //8: Dev9 + {0},//{sif0DmaRead, sif0DmaWrite, sif0DmaInterrupt}, //9: SIF0 + {0},//{sif1DmaRead, sif1DmaWrite, sif1DmaInterrupt}, //10: SIF1 {0}, // Sio2 {0}, // Sio2 }; @@ -319,26 +385,37 @@ const char* IopDmaNames[DMA_CHANNEL_MAX] = "Sio2", "?", "?", "?" }; -}; // Prototypes. To be implemented later (or in other parts of the emulator) -void SetDmaUpdateTarget(u32 delay); -void RaiseDmaIrq(u32 channel); +void SetDmaUpdateTarget(u32 delay) +{ + psxCounters[8].CycleT = delay; +} + +void RaiseDmaIrq(u32 channel) +{ + if(channel<7) + psxDmaInterrupt(channel); + else + psxDmaInterrupt2(channel-7); +} // WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS! void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr) { // I dont' really understand this, but it's used above. Is this BYTES OR WHAT? - int size = (bcr >> 16) * (bcr & 0xFFFF); + int size = 4* (bcr >> 16) * (bcr & 0xFFFF); IopChannels[channel].Control = chcr | DMA_CTRL_ACTIVE; IopChannels[channel].MemAddr = madr; IopChannels[channel].ByteCount = size; + + SetDmaUpdateTarget(0); } void IopDmaUpdate(u32 elapsed) { - u32 MinDelay = 0xFFFFFFFF; + s32 MinDelay = 0x7FFFFFFF; for (int i = 0;i < DMA_CHANNEL_MAX;i++) { @@ -358,12 +435,17 @@ void IopDmaUpdate(u32 elapsed) else { // TODO: Make sure it's the right order - DmaHandler handler = (ch->Control & DMA_CTRL_DIRECTION) ? IopDmaHandlers[i].Read : IopDmaHandlers[i].Write; + DmaHandler handler = (ch->Control & DMA_CTRL_DIRECTION) ? IopDmaHandlers[i].Write : IopDmaHandlers[i].Read; u32 BCount = 0; - s32 Target = (handler) ? handler(i, (u32*)PSXM(ch->MemAddr), ch->ByteCount, &BCount) : 0; + s32 Target = (handler) ? handler(i, (u32*)iopPhysMem(ch->MemAddr), ch->ByteCount, &BCount) : 0; - ch->Target = 100; + if(BCount>0) + { + psxCpu->Clear(ch->MemAddr, BCount/4); + } + + int TTarget = 100; if (Target < 0) { // TODO: ... What to do if the plugin errors? :P @@ -373,29 +455,38 @@ void IopDmaUpdate(u32 elapsed) ch->MemAddr += BCount; ch->ByteCount -= BCount; - ch->Target = BCount / ch->Width; + TTarget = BCount; // / ch->Width; } - if (Target != 0) ch->Target = Target; + if (Target != 0) TTarget = Target; + + if (ch->TargetTarget += TTarget; } } } } + + if(MinDelay<0x7FFFFFFF) + SetDmaUpdateTarget(MinDelay); + else + SetDmaUpdateTarget(10000); } -s32 errDmaRead(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +s32 errDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]); + Console::Error("ERROR: Tried to read using DMA %d (%s). Ignoring.", params 0, channel, IopDmaNames[channel]); - *wordsProcessed = wordsLeft; + *bytesProcessed = bytesLeft; return 0; } -s32 errDmaWrite(s32 channel, u32* data, u32 wordsLeft, u32* wordsProcessed) +s32 errDmaWrite(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) { - Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", 0, channel, IopDmaNames[channel]); + Console::Error("ERROR: Tried to write using DMA %d (%s). Ignoring.", params 0, channel, IopDmaNames[channel]); - *wordsProcessed = wordsLeft; + *bytesProcessed = bytesLeft; return 0; } diff --git a/pcsx2/IopDma.h b/pcsx2/IopDma.h index 416d941e29..c4136fe334 100644 --- a/pcsx2/IopDma.h +++ b/pcsx2/IopDma.h @@ -21,6 +21,46 @@ #include "PS2Edefs.h" +//#define ENABLE_NEW_IOPDMA + +#ifdef ENABLE_NEW_IOPDMA + +typedef s32(* DmaHandler)(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +typedef void (* DmaIHandler)(s32 channel); + +struct DmaHandlerInfo +{ + DmaHandler Read; + DmaHandler Write; + DmaIHandler Interrupt; +}; + +struct DmaStatusInfo +{ + u32 Control; + u32 Width; // bytes/word, for timing purposes + u32 MemAddr; + u32 ByteCount; + s32 Target; +}; + +// FIXME: Dummy constants, to be "filled in" with proper values later +#define DMA_CTRL_ACTIVE 0x01000000 +#define DMA_CTRL_DIRECTION 0x00000001 + +#define DMA_CHANNEL_MAX 16 /* ? */ + +// WARNING: CALLER ****[MUST]**** CALL IopDmaUpdate RIGHT AFTER THIS! +void IopDmaStart(int channel, u32 chcr, u32 madr, u32 bcr); +void IopDmaUpdate(u32 elapsed); + +// external dma handlers +extern s32 cdvdDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed); +extern void cdvdDmaInterrupt(s32 channel); + +//#else +#endif + void psxDma2(u32 madr, u32 bcr, u32 chcr); void psxDma3(u32 madr, u32 bcr, u32 chcr); void psxDma4(u32 madr, u32 bcr, u32 chcr); diff --git a/pcsx2/IopHw.cpp b/pcsx2/IopHw.cpp index 57344bbc99..b973f43ac0 100644 --- a/pcsx2/IopHw.cpp +++ b/pcsx2/IopHw.cpp @@ -41,7 +41,7 @@ void psxHwReset() { u8 psxHwRead8(u32 add) { u8 hard; - if (add >= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { return USBread8(add); } @@ -53,24 +53,24 @@ u8 psxHwRead8(u32 add) { return DEV9read8(add); #ifdef PCSX2_DEVBUILD - case 0x1f801100: - case 0x1f801104: - case 0x1f801108: - case 0x1f801110: - case 0x1f801114: - case 0x1f801118: - case 0x1f801120: - case 0x1f801124: - case 0x1f801128: - case 0x1f801480: - case 0x1f801484: - case 0x1f801488: - case 0x1f801490: - case 0x1f801494: - case 0x1f801498: - case 0x1f8014a0: - case 0x1f8014a4: - case 0x1f8014a8: + case IOP_T0_COUNT: + case IOP_T0_MODE: + case IOP_T0_TARGET: + case IOP_T1_COUNT: + case IOP_T1_MODE: + case IOP_T1_TARGET: + case IOP_T2_COUNT: + case IOP_T2_MODE: + case IOP_T2_TARGET: + case IOP_T3_COUNT: + case IOP_T3_MODE: + case IOP_T3_TARGET: + case IOP_T4_COUNT: + case IOP_T4_MODE: + case IOP_T4_TARGET: + case IOP_T5_COUNT: + case IOP_T5_MODE: + case IOP_T5_TARGET: DevCon::Notice( "IOP Counter Read8 from addr0x%x = 0x%x", params add, psxHu8(add) ); return psxHu8(add); #endif @@ -102,7 +102,7 @@ u8 psxHwRead8(u32 add) { u16 psxHwRead16(u32 add) { u16 hard; - if (add >= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { return USBread16(add); } @@ -136,50 +136,50 @@ u16 psxHwRead16(u32 add) { return hard; //Serial port stuff not support now ;P - // case 0x1f801050: hard = serial_read16(); break; - // case 0x1f801054: hard = serial_status_read(); break; - // case 0x1f80105a: hard = serial_control_read(); break; - // case 0x1f80105e: hard = serial_baud_read(); break; +// case 0x1f801050: hard = serial_read16(); break; +// case 0x1f801054: hard = serial_status_read(); break; +// case 0x1f80105a: hard = serial_control_read(); break; +// case 0x1f80105e: hard = serial_baud_read(); break; - case 0x1f801100: + case IOP_T0_COUNT: hard = (u16)psxRcntRcount16(0); PSXCNT_LOG("T0 count read16: %x", hard); return hard; - case 0x1f801104: + case IOP_T0_MODE: hard = psxCounters[0].mode; - psxCounters[0].mode &= ~0x1800; + psxCounters[0].mode &= ~0x1800; psxCounters[0].mode |= 0x400; PSXCNT_LOG("T0 mode read16: %x", hard); return hard; - case 0x1f801108: + case IOP_T0_TARGET: hard = psxCounters[0].target; PSXCNT_LOG("T0 target read16: %x", hard); return hard; - case 0x1f801110: + case IOP_T1_COUNT: hard = (u16)psxRcntRcount16(1); PSXCNT_LOG("T1 count read16: %x", hard); return hard; - case 0x1f801114: + case IOP_T1_MODE: hard = psxCounters[1].mode; psxCounters[1].mode &= ~0x1800; psxCounters[1].mode |= 0x400; PSXCNT_LOG("T1 mode read16: %x", hard); return hard; - case 0x1f801118: + case IOP_T1_TARGET: hard = psxCounters[1].target; PSXCNT_LOG("T1 target read16: %x", hard); return hard; - case 0x1f801120: + case IOP_T2_COUNT: hard = (u16)psxRcntRcount16(2); PSXCNT_LOG("T2 count read16: %x", hard); return hard; - case 0x1f801124: + case IOP_T2_MODE: hard = psxCounters[2].mode; psxCounters[2].mode &= ~0x1800; psxCounters[2].mode |= 0x400; PSXCNT_LOG("T2 mode read16: %x", hard); return hard; - case 0x1f801128: + case IOP_T2_TARGET: hard = psxCounters[2].target; PSXCNT_LOG("T2 target read16: %x", hard); return hard; @@ -187,45 +187,45 @@ u16 psxHwRead16(u32 add) { case 0x1f80146e: // DEV9_R_REV return DEV9read16(add); - case 0x1f801480: + case IOP_T3_COUNT: hard = (u16)psxRcntRcount32(3); PSXCNT_LOG("T3 count read16: %lx", hard); return hard; - case 0x1f801484: + case IOP_T3_MODE: hard = psxCounters[3].mode; psxCounters[3].mode &= ~0x1800; psxCounters[3].mode |= 0x400; PSXCNT_LOG("T3 mode read16: %lx", hard); return hard; - case 0x1f801488: + case IOP_T3_TARGET: hard = psxCounters[3].target; PSXCNT_LOG("T3 target read16: %lx", hard); return hard; - case 0x1f801490: + case IOP_T4_COUNT: hard = (u16)psxRcntRcount32(4); PSXCNT_LOG("T4 count read16: %lx", hard); return hard; - case 0x1f801494: + case IOP_T4_MODE: hard = psxCounters[4].mode; psxCounters[4].mode &= ~0x1800; psxCounters[4].mode |= 0x400; PSXCNT_LOG("T4 mode read16: %lx", hard); return hard; - case 0x1f801498: + case IOP_T4_TARGET: hard = psxCounters[4].target; PSXCNT_LOG("T4 target read16: %lx", hard); return hard; - case 0x1f8014a0: + case IOP_T5_COUNT: hard = (u16)psxRcntRcount32(5); PSXCNT_LOG("T5 count read16: %lx", hard); return hard; - case 0x1f8014a4: + case IOP_T5_MODE: hard = psxCounters[5].mode; psxCounters[5].mode &= ~0x1800; psxCounters[5].mode |= 0x400; PSXCNT_LOG("T5 mode read16: %lx", hard); return hard; - case 0x1f8014a8: + case IOP_T5_TARGET: hard = psxCounters[5].target; PSXCNT_LOG("T5 target read16: %lx", hard); return hard; @@ -238,11 +238,11 @@ u16 psxHwRead16(u32 add) { hard = psxHu16(0x1506); PSXHW_LOG("DMA7 BCR_count 16bit read %lx", hard); return hard; - //case 0x1f802030: hard = //int_2000???? - //case 0x1f802040: hard =//dip switches...?? +// case 0x1f802030: hard = //int_2000???? +// case 0x1f802040: hard =//dip switches...?? default: - if (add>=0x1f801c00 && add<0x1f801e00) { + if (add>=HW_SPU2_START && add= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { return USBread32(add); } - if (add >= 0x1f808400 && add <= 0x1f808550) {//the size is a complete guess.. + if (add >= HW_FW_START && add <= HW_FW_END) {//the size is a complete guess.. return FWread32(add); } @@ -275,7 +275,7 @@ u32 psxHwRead32(u32 add) { PAD_LOG("sio read32 ;ret = %lx", hard); return hard; - // case 0x1f801050: hard = serial_read32(); break;//serial port +// case 0x1f801050: hard = serial_read32(); break;//serial port case 0x1f801060: PSXHW_LOG("RAM size read %lx", psxHu32(0x1060)); return psxHu32(0x1060); @@ -289,18 +289,17 @@ u32 psxHwRead32(u32 add) { psxHu32(0x1078) = 0; return hard; -/* case 0x1f801810: +// case 0x1f801810: // hard = GPU_readData(); - PSXHW_LOG("GPU DATA 32bit read %lx", hard); - return hard;*/ -/* case 0x1f801814: - hard = GPU_readStatus(); - PSXHW_LOG("GPU STATUS 32bit read %lx", hard); - return hard; -*/ -/* case 0x1f801820: hard = mdecRead0(); break; - case 0x1f801824: hard = mdecRead1(); break; -*/ +// PSXHW_LOG("GPU DATA 32bit read %lx", hard); +// return hard; +// case 0x1f801814: +// hard = GPU_readStatus(); +// PSXHW_LOG("GPU STATUS 32bit read %lx", hard); +// return hard; +// +// case 0x1f801820: hard = mdecRead0(); break; +// case 0x1f801824: hard = mdecRead1(); break; case 0x1f8010a0: PSXHW_LOG("DMA2 MADR 32bit read %lx", psxHu32(0x10a0)); @@ -352,7 +351,7 @@ u32 psxHwRead32(u32 add) { PSXHW_LOG("DMA ICR 32bit read %lx", HW_DMA_ICR); return HW_DMA_ICR; -//SSBus registers + //SSBus registers case 0x1f801000: hard = psxHu32(0x1000); PSXHW_LOG("SSBUS 32bit read %lx", hard); @@ -432,79 +431,78 @@ u32 psxHwRead32(u32 add) { case 0x1f8010c8: PSXHW_LOG("DMA4 CHCR 32bit read %lx", HW_DMA4_CHCR); - return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) + return HW_DMA4_CHCR; // DMA4 chcr (SPU DMA) // time for rootcounters :) - case 0x1f801100: + case IOP_T0_COUNT: hard = (u16)psxRcntRcount16(0); PSXCNT_LOG("T0 count read32: %lx", hard); return hard; - case 0x1f801104: + case IOP_T0_MODE: hard = (u16)psxCounters[0].mode; PSXCNT_LOG("T0 mode read32: %lx", hard); return hard; - case 0x1f801108: + case IOP_T0_TARGET: hard = psxCounters[0].target; PSXCNT_LOG("T0 target read32: %lx", hard); return hard; - case 0x1f801110: + case IOP_T1_COUNT: hard = (u16)psxRcntRcount16(1); PSXCNT_LOG("T1 count read32: %lx", hard); return hard; - case 0x1f801114: + case IOP_T1_MODE: hard = (u16)psxCounters[1].mode; PSXCNT_LOG("T1 mode read32: %lx", hard); return hard; - case 0x1f801118: + case IOP_T1_TARGET: hard = psxCounters[1].target; PSXCNT_LOG("T1 target read32: %lx", hard); return hard; - case 0x1f801120: + case IOP_T2_COUNT: hard = (u16)psxRcntRcount16(2); PSXCNT_LOG("T2 count read32: %lx", hard); return hard; - case 0x1f801124: + case IOP_T2_MODE: hard = (u16)psxCounters[2].mode; PSXCNT_LOG("T2 mode read32: %lx", hard); return hard; - case 0x1f801128: + case IOP_T2_TARGET: hard = psxCounters[2].target; PSXCNT_LOG("T2 target read32: %lx", hard); return hard; - - case 0x1f801480: + case IOP_T3_COUNT: hard = (u32)psxRcntRcount32(3); PSXCNT_LOG("T3 count read32: %lx", hard); return hard; - case 0x1f801484: + case IOP_T3_MODE: hard = (u16)psxCounters[3].mode; PSXCNT_LOG("T3 mode read32: %lx", hard); return hard; - case 0x1f801488: + case IOP_T3_TARGET: hard = psxCounters[3].target; PSXCNT_LOG("T3 target read32: %lx", hard); return hard; - case 0x1f801490: + case IOP_T4_COUNT: hard = (u32)psxRcntRcount32(4); PSXCNT_LOG("T4 count read32: %lx", hard); return hard; - case 0x1f801494: + case IOP_T4_MODE: hard = (u16)psxCounters[4].mode; PSXCNT_LOG("T4 mode read32: %lx", hard); return hard; - case 0x1f801498: + case IOP_T4_TARGET: hard = psxCounters[4].target; PSXCNT_LOG("T4 target read32: %lx", hard); return hard; - case 0x1f8014a0: + case IOP_T5_COUNT: hard = (u32)psxRcntRcount32(5); PSXCNT_LOG("T5 count read32: %lx", hard); return hard; - case 0x1f8014a4: + case IOP_T5_MODE: hard = (u16)psxCounters[5].mode; PSXCNT_LOG("T5 mode read32: %lx", hard); return hard; - case 0x1f8014a8: + case IOP_T5_TARGET: hard = psxCounters[5].target; PSXCNT_LOG("T5 target read32: %lx", hard); return hard; @@ -619,18 +617,11 @@ u32 psxHwRead32(u32 add) { return hard; } -int g_pbufi; +// A buffer that stores messages until it gets a /n or the number of chars (g_pbufi) is more then 1023. s8 g_pbuf[1024]; - -#define DmaExec(n) { \ - if (HW_DMA##n##_CHCR & 0x01000000 && \ - HW_DMA_PCR & (8 << (n * 4))) { \ - psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ - } \ -} - +int g_pbufi; void psxHwWrite8(u32 add, u8 value) { - if (add >= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { USBwrite8(add, value); return; } if((add & 0xf) == 0xa) @@ -638,28 +629,28 @@ void psxHwWrite8(u32 add, u8 value) { switch (add) { case 0x1f801040: - sioWrite8(value); - break; - // case 0x1f801050: serial_write8(value); break;//serial port + sioWrite8(value); + break; +// case 0x1f801050: serial_write8(value); break;//serial port - case 0x1f801100: - case 0x1f801104: - case 0x1f801108: - case 0x1f801110: - case 0x1f801114: - case 0x1f801118: - case 0x1f801120: - case 0x1f801124: - case 0x1f801128: - case 0x1f801480: - case 0x1f801484: - case 0x1f801488: - case 0x1f801490: - case 0x1f801494: - case 0x1f801498: - case 0x1f8014a0: - case 0x1f8014a4: - case 0x1f8014a8: + case IOP_T0_COUNT: + case IOP_T0_MODE: + case IOP_T0_TARGET: + case IOP_T1_COUNT: + case IOP_T1_MODE: + case IOP_T1_TARGET: + case IOP_T2_COUNT: + case IOP_T2_MODE: + case IOP_T2_TARGET: + case IOP_T3_COUNT: + case IOP_T3_MODE: + case IOP_T3_TARGET: + case IOP_T4_COUNT: + case IOP_T4_MODE: + case IOP_T4_TARGET: + case IOP_T5_COUNT: + case IOP_T5_MODE: + case IOP_T5_TARGET: DevCon::Notice( "IOP Counter Write8 to addr 0x%x = 0x%x", params add, value ); psxHu8(add) = value; return; @@ -676,17 +667,19 @@ void psxHwWrite8(u32 add, u8 value) { case 0x1f80380c: if (value == '\r') break; - if (value == '\n' || g_pbufi >= 1023) { - g_pbuf[g_pbufi++] = 0; g_pbufi = 0; + if (value == '\n' || g_pbufi >= 1023) { // A line break, or the buffer is about to overflow. + g_pbuf[g_pbufi++] = 0; + g_pbufi = 0; DevCon::WriteLn( Color_Cyan, g_pbuf ); } else g_pbuf[g_pbufi++] = value; - psxHu8(add) = value; + psxHu8(add) = value; return; case 0x1F808260: PSXHW_LOG("SIO2 write8 DATAIN <- %08X", value); - sio2_serialIn(value);return;//serial data feed/fifo + sio2_serialIn(value); + return;//serial data feed/fifo default: psxHu8(add) = value; @@ -698,7 +691,7 @@ void psxHwWrite8(u32 add, u8 value) { } void psxHwWrite16(u32 add, u16 value) { - if (add >= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { USBwrite16(add, value); return; } @@ -727,10 +720,10 @@ void psxHwWrite16(u32 add, u16 value) { return; //serial port ;P - // case 0x1f801050: serial_write16(value); break; - // case 0x1f80105a: serial_control_write(value);break; - // case 0x1f80105e: serial_baud_write(value); break; - // case 0x1f801054: serial_status_write(value); break; +// case 0x1f801050: serial_write16(value); break; +// case 0x1f80105a: serial_control_write(value);break; +// case 0x1f80105e: serial_baud_write(value); break; +// case 0x1f801054: serial_status_write(value); break; case 0x1f801070: PSXHW_LOG("IREG 16bit write %x", value); @@ -760,33 +753,33 @@ void psxHwWrite16(u32 add, u16 value) { PSXHW_LOG("DMA4 BCR_count 16bit write %lx", value); psxHu16(0x10c6) = value; return; // DMA4 bcr_count - case 0x1f801100: + case IOP_T0_COUNT: PSXCNT_LOG("COUNTER 0 COUNT 16bit write %x", value); psxRcntWcount16(0, value); return; - case 0x1f801104: + case IOP_T0_MODE: PSXCNT_LOG("COUNTER 0 MODE 16bit write %x", value); psxRcnt0Wmode(value); return; - case 0x1f801108: + case IOP_T0_TARGET: PSXCNT_LOG("COUNTER 0 TARGET 16bit write %x", value); psxRcntWtarget16(0, value); return; - case 0x1f801110: + case IOP_T1_COUNT: PSXCNT_LOG("COUNTER 1 COUNT 16bit write %x", value); psxRcntWcount16(1, value); return; - case 0x1f801114: + case IOP_T1_MODE: PSXCNT_LOG("COUNTER 1 MODE 16bit write %x", value); psxRcnt1Wmode(value); return; - case 0x1f801118: + case IOP_T1_TARGET: PSXCNT_LOG("COUNTER 1 TARGET 16bit write %x", value); psxRcntWtarget16(1, value); return; - case 0x1f801120: + case IOP_T2_COUNT: PSXCNT_LOG("COUNTER 2 COUNT 16bit write %x", value); psxRcntWcount16(2, value); return; - case 0x1f801124: + case IOP_T2_MODE: PSXCNT_LOG("COUNTER 2 MODE 16bit write %x", value); psxRcnt2Wmode(value); return; - case 0x1f801128: + case IOP_T2_TARGET: PSXCNT_LOG("COUNTER 2 TARGET 16bit write %x", value); psxRcntWtarget16(2, value); return; @@ -795,33 +788,33 @@ void psxHwWrite16(u32 add, u16 value) { psxHu16(0x1450) = value/* & (~0x8)*/; return; - case 0x1f801480: + case IOP_T3_COUNT: PSXCNT_LOG("COUNTER 3 COUNT 16bit write %lx", value); psxRcntWcount32(3, value); return; - case 0x1f801484: + case IOP_T3_MODE: PSXCNT_LOG("COUNTER 3 MODE 16bit write %lx", value); psxRcnt3Wmode(value); return; - case 0x1f801488: + case IOP_T3_TARGET: PSXCNT_LOG("COUNTER 3 TARGET 16bit write %lx", value); psxRcntWtarget32(3, value); return; - case 0x1f801490: + case IOP_T4_COUNT: PSXCNT_LOG("COUNTER 4 COUNT 16bit write %lx", value); psxRcntWcount32(4, value); return; - case 0x1f801494: + case IOP_T4_MODE: PSXCNT_LOG("COUNTER 4 MODE 16bit write %lx", value); psxRcnt4Wmode(value); return; - case 0x1f801498: + case IOP_T4_TARGET: PSXCNT_LOG("COUNTER 4 TARGET 16bit write %lx", value); psxRcntWtarget32(4, value); return; - case 0x1f8014a0: + case IOP_T5_COUNT: PSXCNT_LOG("COUNTER 5 COUNT 16bit write %lx", value); psxRcntWcount32(5, value); return; - case 0x1f8014a4: + case IOP_T5_MODE: PSXCNT_LOG("COUNTER 5 MODE 16bit write %lx", value); psxRcnt5Wmode(value); return; - case 0x1f8014a8: + case IOP_T5_TARGET: PSXCNT_LOG("COUNTER 5 TARGET 16bit write %lx", value); psxRcntWtarget32(5, value); return; @@ -834,7 +827,7 @@ void psxHwWrite16(u32 add, u16 value) { PSXHW_LOG("DMA7 BCR_count 16bit write %lx", value); return; default: - if (add>=0x1f801c00 && add<0x1f801e00) { + if (add>=HW_SPU2_START && add= 0x1f801600 && add < 0x1f801700) { + if (add >= HW_USB_START && add < HW_USB_END) { USBwrite32(add, value); return; } - if (add >= 0x1f808400 && add <= 0x1f808550) { + if (add >= HW_FW_START && add <= HW_FW_END) { FWwrite32(add, value); return; } switch (add) { @@ -1034,7 +1020,7 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f8010c8: PSXHW_LOG("DMA4 CHCR 32bit write %lx", value); HW_DMA4_CHCR = value; // DMA4 chcr (SPU DMA) - DmaExec(4); + DmaExecNew(4); return; //------------------------------------------------------------------ @@ -1067,7 +1053,7 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f801508: PSXHW_LOG("DMA7 CHCR 32bit write %lx", value); HW_DMA7_CHCR = value; // DMA7 chcr (SPU2) - DmaExec2(7); + DmaExecNew2(7); return; //------------------------------------------------------------------ @@ -1179,63 +1165,63 @@ void psxHwWrite32(u32 add, u32 value) { case 0x1f801824: mdecWrite1(value); break; */ - case 0x1f801100: + case IOP_T0_COUNT: PSXCNT_LOG("COUNTER 0 COUNT 32bit write %lx", value); psxRcntWcount16(0, value ); return; - case 0x1f801104: + case IOP_T0_MODE: PSXCNT_LOG("COUNTER 0 MODE 32bit write %lx", value); psxRcnt0Wmode(value); return; - case 0x1f801108: + case IOP_T0_TARGET: PSXCNT_LOG("COUNTER 0 TARGET 32bit write %lx", value); psxRcntWtarget16(0, value ); return; - case 0x1f801110: + case IOP_T1_COUNT: PSXCNT_LOG("COUNTER 1 COUNT 32bit write %lx", value); psxRcntWcount16(1, value ); return; - case 0x1f801114: + case IOP_T1_MODE: PSXCNT_LOG("COUNTER 1 MODE 32bit write %lx", value); psxRcnt1Wmode(value); return; - case 0x1f801118: + case IOP_T1_TARGET: PSXCNT_LOG("COUNTER 1 TARGET 32bit write %lx", value); psxRcntWtarget16(1, value ); return; - case 0x1f801120: + case IOP_T2_COUNT: PSXCNT_LOG("COUNTER 2 COUNT 32bit write %lx", value); psxRcntWcount16(2, value ); return; - case 0x1f801124: + case IOP_T2_MODE: PSXCNT_LOG("COUNTER 2 MODE 32bit write %lx", value); psxRcnt2Wmode(value); return; - case 0x1f801128: + case IOP_T2_TARGET: PSXCNT_LOG("COUNTER 2 TARGET 32bit write %lx", value); psxRcntWtarget16(2, value); return; - case 0x1f801480: + case IOP_T3_COUNT: PSXCNT_LOG("COUNTER 3 COUNT 32bit write %lx", value); psxRcntWcount32(3, value); return; - case 0x1f801484: + case IOP_T3_MODE: PSXCNT_LOG("COUNTER 3 MODE 32bit write %lx", value); psxRcnt3Wmode(value); return; - case 0x1f801488: + case IOP_T3_TARGET: PSXCNT_LOG("COUNTER 3 TARGET 32bit write %lx", value); psxRcntWtarget32(3, value); return; - case 0x1f801490: + case IOP_T4_COUNT: PSXCNT_LOG("COUNTER 4 COUNT 32bit write %lx", value); psxRcntWcount32(4, value); return; - case 0x1f801494: + case IOP_T4_MODE: PSXCNT_LOG("COUNTER 4 MODE 32bit write %lx", value); psxRcnt4Wmode(value); return; - case 0x1f801498: + case IOP_T4_TARGET: PSXCNT_LOG("COUNTER 4 TARGET 32bit write %lx", value); psxRcntWtarget32(4, value); return; - case 0x1f8014a0: + case IOP_T5_COUNT: PSXCNT_LOG("COUNTER 5 COUNT 32bit write %lx", value); psxRcntWcount32(5, value); return; - case 0x1f8014a4: + case IOP_T5_MODE: PSXCNT_LOG("COUNTER 5 MODE 32bit write %lx", value); psxRcnt5Wmode(value); return; - case 0x1f8014a8: + case IOP_T5_TARGET: PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx", value); psxRcntWtarget32(5, value); return; diff --git a/pcsx2/IopHw.h b/pcsx2/IopHw.h index 1b7a5400f6..5579161b9c 100644 --- a/pcsx2/IopHw.h +++ b/pcsx2/IopHw.h @@ -22,6 +22,72 @@ #include "R3000A.h" #include "IopMem.h" +#define HW_USB_START 0x1f801600 +#define HW_USB_END 0x1f801700 +#define HW_FW_START 0x1f808400 +#define HW_FW_END 0x1f808550 +#define HW_SPU2_START 0x1f801c00 +#define HW_SPU2_END 0x1f801e00 + +/* Registers for the IOP Counters */ +enum IOPCountRegs +{ + IOP_T0_COUNT = 0x1f801100, + IOP_T1_COUNT = 0x1f801110, + IOP_T2_COUNT = 0x1f801120, + IOP_T3_COUNT = 0x1f801480, + IOP_T4_COUNT = 0x1f801490, + IOP_T5_COUNT = 0x1f8014a0, + + IOP_T0_MODE = 0x1f801104, + IOP_T1_MODE = 0x1f801114, + IOP_T2_MODE = 0x1f801124, + IOP_T3_MODE = 0x1f801484, + IOP_T4_MODE = 0x1f801494, + IOP_T5_MODE = 0x1f8014a4, + + IOP_T0_TARGET= 0x1f801108, + IOP_T1_TARGET = 0x1f801118, + IOP_T2_TARGET = 0x1f801128, + IOP_T3_TARGET = 0x1f801488, + IOP_T4_TARGET = 0x1f801498, + IOP_T5_TARGET = 0x1f8014a8 +}; + +// fixme: I'm sure there's a better way to do this. --arcum42 +#define DmaExec(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +#define DmaExec2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, HW_DMA##n##_CHCR); \ + } \ +} + +#ifdef ENABLE_NEW_IOPDMA +#define DmaExecNew(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR & (8 << (n * 4))) { \ + IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \ + } \ +} + +#define DmaExecNew2(n) { \ + if (HW_DMA##n##_CHCR & 0x01000000 && \ + HW_DMA_PCR2 & (8 << ((n-7) * 4))) { \ + IopDmaStart(n, HW_DMA##n##_CHCR, HW_DMA##n##_MADR, HW_DMA##n##_BCR); \ + } \ +} +#else +#define DmaExecNew(n) DmaExec(n) +#define DmaExecNew2(n) DmaExec2(n) +#endif + #define HW_DMA0_MADR (psxHu32(0x1080)) // MDEC in DMA #define HW_DMA0_BCR (psxHu32(0x1084)) #define HW_DMA0_CHCR (psxHu32(0x1088)) diff --git a/pcsx2/Linux/HacksDlg.cpp b/pcsx2/Linux/HacksDlg.cpp index 1f4a29936f..0177d60930 100644 --- a/pcsx2/Linux/HacksDlg.cpp +++ b/pcsx2/Linux/HacksDlg.cpp @@ -53,59 +53,65 @@ void on_Game_Fix_OK(GtkButton *button, gpointer user_data) gtk_main_quit(); } +void on_vu_slider_changed(GtkRange *range, gpointer user_data) +{ + int i; + + i = gtk_range_get_value(range); + gtk_label_set_text(GTK_LABEL(lookup_widget(SpeedHacksDlg,"vu_cycle_stealing_label")),vu_stealing_labels[i]); +} + +void on_ee_slider_changed(GtkRange *range, gpointer user_data) +{ + int i; + + i = gtk_range_get_value(range); + gtk_label_set_text(GTK_LABEL(lookup_widget(SpeedHacksDlg,"ee_cycle_label")),ee_cycle_labels[i]); +} + void on_Speed_Hacks(GtkMenuItem *menuitem, gpointer user_data) { SpeedHacksDlg = create_SpeedHacksDlg(); + GtkRange *vuScale = GTK_RANGE(lookup_widget(SpeedHacksDlg, "VUCycleHackScale")); + GtkRange *eeScale = GTK_RANGE(lookup_widget(SpeedHacksDlg, "EECycleHackScale")); + + set_checked(SpeedHacksDlg, "check_iop_cycle_rate", Config.Hacks.IOPCycleDouble); + set_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack", Config.Hacks.WaitCycleExt); + set_checked(SpeedHacksDlg, "check_intc_sync_hack", Config.Hacks.INTCSTATSlow); + set_checked(SpeedHacksDlg, "check_idle_loop_fastforward", Config.Hacks.IdleLoopFF); - switch (CHECK_EE_CYCLERATE) - { - case 0: - set_checked(SpeedHacksDlg, "check_default_cycle_rate", true); - break; - case 1: - set_checked(SpeedHacksDlg, "check_1_5_cycle_rate", true); - break; - case 2: - set_checked(SpeedHacksDlg, "check_2_cycle_rate", true); - break; - case 3: - set_checked(SpeedHacksDlg, "check_3_cycle_rate", true); - break; - default: - set_checked(SpeedHacksDlg, "check_default_cycle_rate", true); - break; - } - - set_checked(SpeedHacksDlg, "check_iop_cycle_rate", CHECK_IOP_CYCLERATE); - set_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack", CHECK_WAITCYCLE_HACK); - set_checked(SpeedHacksDlg, "check_intc_sync_hack", CHECK_INTC_STAT_HACK); - set_checked(SpeedHacksDlg, "check_ESC_hack", CHECK_ESCAPE_HACK); - + gtk_range_set_value(vuScale, Config.Hacks.VUCycleSteal); + on_vu_slider_changed(vuScale, NULL); + gtk_range_set_value(eeScale, Config.Hacks.EECycleRate); + on_ee_slider_changed(eeScale, NULL); + gtk_widget_show_all(SpeedHacksDlg); gtk_widget_set_sensitive(MainWindow, FALSE); gtk_main(); } + + void on_Speed_Hack_OK(GtkButton *button, gpointer user_data) { - Config.Hacks = 0; - - if is_checked(SpeedHacksDlg, "check_default_cycle_rate") - Config.Hacks = 0; - else if is_checked(SpeedHacksDlg, "check_1_5_cycle_rate") - Config.Hacks = 1; - else if is_checked(SpeedHacksDlg, "check_2_cycle_rate") - Config.Hacks = 2; - else if is_checked(SpeedHacksDlg, "check_3_cycle_rate") - Config.Hacks = 3; - - Config.Hacks |= is_checked(SpeedHacksDlg, "check_iop_cycle_rate") << 3; - Config.Hacks |= is_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack") << 4; - Config.Hacks |= is_checked(SpeedHacksDlg, "check_intc_sync_hack") << 5; - Config.Hacks |= is_checked(SpeedHacksDlg, "check_ESC_hack") << 10; - - SaveConfig(); - + PcsxConfig::Hacks_t newhacks; + newhacks.EECycleRate = 0; + + newhacks.IOPCycleDouble = is_checked(SpeedHacksDlg, "check_iop_cycle_rate"); + newhacks.WaitCycleExt = is_checked(SpeedHacksDlg, "check_wait_cycles_sync_hack"); + newhacks.INTCSTATSlow = is_checked(SpeedHacksDlg, "check_intc_sync_hack"); + newhacks.IdleLoopFF = is_checked(SpeedHacksDlg, "check_idle_loop_fastforward"); + + newhacks.VUCycleSteal = gtk_range_get_value(GTK_RANGE(lookup_widget(SpeedHacksDlg, "VUCycleHackScale"))); + newhacks.EECycleRate = gtk_range_get_value(GTK_RANGE(lookup_widget(SpeedHacksDlg, "EECycleHackScale"))); + + if (memcmp(&newhacks, &Config.Hacks, sizeof(newhacks))) + { + SysRestorableReset(); + Config.Hacks = newhacks; + SaveConfig(); + } + gtk_widget_destroy(SpeedHacksDlg); gtk_widget_set_sensitive(MainWindow, TRUE); gtk_main_quit(); diff --git a/pcsx2/Linux/Linux.h b/pcsx2/Linux/Linux.h index 5ca6f7f9f8..e1cf6b6272 100644 --- a/pcsx2/Linux/Linux.h +++ b/pcsx2/Linux/Linux.h @@ -101,6 +101,21 @@ char iop_log_names[9][32] = "GPU Log" }; +char vu_stealing_labels[5][256] = +{ + "0: No speedup.", + "1: Slight speedup, should work with most games.", + "2: Moderate speedup, should work with most games with minor problems.", + "3: Large speedup, may break many games and make others skip frames.", + "4: Very large speedup, will break games in interesting ways." +}; + +char ee_cycle_labels[3][256] = +{ + "Default Cycle Rate: Most compatible option - recommended for everyone with high-end machines.", + "x1.5 Cycle Rate: Moderate speedup, and works well with most games.", + "x2 Cycle Rate: Big speedup! Works well with many games." +}; //Tri-Ace - IDC_GAMEFIX2 #define FLAG_VU_ADD_SUB 0x1 // Persona3/4 - IDC_GAMEFIX4 diff --git a/pcsx2/Linux/LnxMisc.cpp b/pcsx2/Linux/LnxMisc.cpp index b0a3febff2..297c82ab9c 100644 --- a/pcsx2/Linux/LnxMisc.cpp +++ b/pcsx2/Linux/LnxMisc.cpp @@ -39,18 +39,3 @@ u64 GetCPUTicks() gettimeofday(&t, NULL); return ((u64)t.tv_sec*GetTickFrequency())+t.tv_usec; } - -void cdvdSetSystemTime( cdvdStruct& cdvd ) -{ - time_t traw; - struct tm* ptlocal; - time(&traw); - ptlocal = localtime(&traw); - - cdvd.RTC.second = ptlocal->tm_sec; - cdvd.RTC.minute = ptlocal->tm_min; - cdvd.RTC.hour = ptlocal->tm_hour; - cdvd.RTC.day = ptlocal->tm_mday; - cdvd.RTC.month = ptlocal->tm_mon; - cdvd.RTC.year = ptlocal->tm_year; -} diff --git a/pcsx2/Linux/Pref.cpp b/pcsx2/Linux/Pref.cpp index f2097abce9..7db9dd2d4f 100644 --- a/pcsx2/Linux/Pref.cpp +++ b/pcsx2/Linux/Pref.cpp @@ -100,7 +100,19 @@ int LoadConfig() GetValuel("varLog", varLog); #endif GetValuel("Options", Config.Options); - GetValuel("Hacks", Config.Hacks); + + GetValuel("EECycleRate", Config.Hacks.EECycleRate); + if (Config.Hacks.EECycleRate > 2) + Config.Hacks.EECycleRate = 2; + GetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble); + GetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt); + GetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow); + GetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal); + GetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF); + GetValuel("ESCExits", Config.Hacks.ESCExits); + + if (Config.Hacks.VUCycleSteal < 0 || Config.Hacks.VUCycleSteal > 4) + Config.Hacks.VUCycleSteal = 0; GetValuel("Fixes", Config.GameFixes); GetValuel("CustomFps", Config.CustomFps); @@ -162,7 +174,14 @@ void SaveConfig() SetValuel("Options", Config.Options); - SetValuel("Hacks", Config.Hacks); + SetValuel("EECycleRate", Config.Hacks.EECycleRate); + SetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble); + SetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt); + SetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow); + SetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal); + SetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF); + SetValuel("ESCExits", Config.Hacks.ESCExits); + SetValuel("Fixes", Config.GameFixes); SetValuel("Patch", Config.Patch); diff --git a/pcsx2/Linux/callbacks.h b/pcsx2/Linux/callbacks.h index a70ca55935..771418a3ca 100644 --- a/pcsx2/Linux/callbacks.h +++ b/pcsx2/Linux/callbacks.h @@ -13,6 +13,14 @@ void On_Dialog_Cancelled (GtkButton *button, gpointer user_data); +void +on_ee_slider_changed (GtkRange *range, + gpointer user_data); + +void +on_vu_slider_changed (GtkRange *range, + gpointer user_data); + void on_Speed_Hack_OK (GtkButton *button, gpointer user_data); diff --git a/pcsx2/Linux/interface.c b/pcsx2/Linux/interface.c index f62270e3d4..035bc3fe03 100644 --- a/pcsx2/Linux/interface.c +++ b/pcsx2/Linux/interface.c @@ -615,21 +615,21 @@ create_SpeedHacksDlg (void) GtkWidget *vbox59; GtkWidget *label88; GtkWidget *hbox39; + GtkWidget *vbox72; GtkWidget *frame37; GtkWidget *alignment32; GtkWidget *vbox61; - GtkWidget *check_default_cycle_rate; - GSList *check_default_cycle_rate_group = NULL; - GtkWidget *label98; - GtkWidget *check_1_5_cycle_rate; - GtkWidget *label93; - GtkWidget *check_2_cycle_rate; - GtkWidget *label94; - GtkWidget *check_3_cycle_rate; - GtkWidget *label95; - GtkWidget *hseparator1; + GtkWidget *EECycleHackScale; + GtkWidget *ee_cycle_label; + GtkWidget *hseparator2; GtkWidget *label91; GtkWidget *label105; + GtkWidget *frame39; + GtkWidget *alignment34; + GtkWidget *vbox73; + GtkWidget *VUCycleHackScale; + GtkWidget *vu_cycle_stealing_label; + GtkWidget *label111; GtkWidget *vbox60; GtkWidget *check_iop_cycle_rate; GtkWidget *label96; @@ -637,10 +637,10 @@ create_SpeedHacksDlg (void) GtkWidget *label97; GtkWidget *check_intc_sync_hack; GtkWidget *label101; - GtkWidget *frame36; - GtkWidget *alignment31; - GtkWidget *check_ESC_hack; - GtkWidget *label89; + GtkWidget *vbox71; + GtkWidget *check_idle_loop_fastforward; + GtkWidget *label110; + GtkWidget *hseparator1; GtkWidget *dialog_action_area3; GtkWidget *button99; GtkWidget *button98; @@ -669,10 +669,15 @@ create_SpeedHacksDlg (void) gtk_widget_show (hbox39); gtk_box_pack_start (GTK_BOX (vbox59), hbox39, TRUE, TRUE, 0); + vbox72 = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (vbox72, "vbox72"); + gtk_widget_show (vbox72); + gtk_box_pack_start (GTK_BOX (hbox39), vbox72, TRUE, TRUE, 0); + frame37 = gtk_frame_new (NULL); gtk_widget_set_name (frame37, "frame37"); gtk_widget_show (frame37); - gtk_box_pack_start (GTK_BOX (hbox39), frame37, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox72), frame37, TRUE, TRUE, 0); alignment32 = gtk_alignment_new (0.5, 0.5, 1, 1); gtk_widget_set_name (alignment32, "alignment32"); @@ -685,68 +690,25 @@ create_SpeedHacksDlg (void) gtk_widget_show (vbox61); gtk_container_add (GTK_CONTAINER (alignment32), vbox61); - check_default_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Default Cycle Rate")); - gtk_widget_set_name (check_default_cycle_rate, "check_default_cycle_rate"); - gtk_widget_show (check_default_cycle_rate); - gtk_box_pack_start (GTK_BOX (vbox61), check_default_cycle_rate, FALSE, FALSE, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_default_cycle_rate), check_default_cycle_rate_group); - check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_default_cycle_rate)); + EECycleHackScale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 2, 1, 0, 0))); + gtk_widget_set_name (EECycleHackScale, "EECycleHackScale"); + gtk_widget_show (EECycleHackScale); + gtk_box_pack_start (GTK_BOX (vbox61), EECycleHackScale, FALSE, FALSE, 0); + gtk_scale_set_draw_value (GTK_SCALE (EECycleHackScale), FALSE); + gtk_scale_set_digits (GTK_SCALE (EECycleHackScale), 0); - label98 = gtk_label_new (_("Most compatible option - recommended for everyone with high-end machines.")); - gtk_widget_set_name (label98, "label98"); - gtk_widget_show (label98); - gtk_box_pack_start (GTK_BOX (vbox61), label98, FALSE, FALSE, 0); - gtk_label_set_line_wrap (GTK_LABEL (label98), TRUE); - gtk_misc_set_alignment (GTK_MISC (label98), 0.29, 0.5); + ee_cycle_label = gtk_label_new (_("Most compatible option - recommended for everyone with high-end machines.")); + gtk_widget_set_name (ee_cycle_label, "ee_cycle_label"); + gtk_widget_show (ee_cycle_label); + gtk_box_pack_start (GTK_BOX (vbox61), ee_cycle_label, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (ee_cycle_label), TRUE); - check_1_5_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x1.5 Cycle Rate")); - gtk_widget_set_name (check_1_5_cycle_rate, "check_1_5_cycle_rate"); - gtk_widget_show (check_1_5_cycle_rate); - gtk_box_pack_start (GTK_BOX (vbox61), check_1_5_cycle_rate, FALSE, FALSE, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_1_5_cycle_rate), check_default_cycle_rate_group); - check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_1_5_cycle_rate)); + hseparator2 = gtk_hseparator_new (); + gtk_widget_set_name (hseparator2, "hseparator2"); + gtk_widget_show (hseparator2); + gtk_box_pack_start (GTK_BOX (vbox61), hseparator2, FALSE, FALSE, 0); - label93 = gtk_label_new (_("Moderate speedup, and works well with most games.")); - gtk_widget_set_name (label93, "label93"); - gtk_widget_show (label93); - gtk_box_pack_start (GTK_BOX (vbox61), label93, FALSE, FALSE, 0); - gtk_label_set_line_wrap (GTK_LABEL (label93), TRUE); - gtk_misc_set_alignment (GTK_MISC (label93), 0.29, 0.5); - - check_2_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x2 Cycle Rate")); - gtk_widget_set_name (check_2_cycle_rate, "check_2_cycle_rate"); - gtk_widget_show (check_2_cycle_rate); - gtk_box_pack_start (GTK_BOX (vbox61), check_2_cycle_rate, FALSE, FALSE, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_2_cycle_rate), check_default_cycle_rate_group); - check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_2_cycle_rate)); - - label94 = gtk_label_new (_("Big speedup! Works well with many games.")); - gtk_widget_set_name (label94, "label94"); - gtk_widget_show (label94); - gtk_box_pack_start (GTK_BOX (vbox61), label94, FALSE, FALSE, 0); - gtk_label_set_line_wrap (GTK_LABEL (label94), TRUE); - gtk_misc_set_alignment (GTK_MISC (label94), 0.36, 0.5); - - check_3_cycle_rate = gtk_radio_button_new_with_mnemonic (NULL, _("Use x3 Cycle Rate")); - gtk_widget_set_name (check_3_cycle_rate, "check_3_cycle_rate"); - gtk_widget_show (check_3_cycle_rate); - gtk_box_pack_start (GTK_BOX (vbox61), check_3_cycle_rate, FALSE, FALSE, 0); - gtk_radio_button_set_group (GTK_RADIO_BUTTON (check_3_cycle_rate), check_default_cycle_rate_group); - check_default_cycle_rate_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (check_3_cycle_rate)); - - label95 = gtk_label_new (_("Big speedup, but causes flickering or missing geometry on many games.")); - gtk_widget_set_name (label95, "label95"); - gtk_widget_show (label95); - gtk_box_pack_start (GTK_BOX (vbox61), label95, FALSE, FALSE, 0); - gtk_label_set_line_wrap (GTK_LABEL (label95), TRUE); - gtk_misc_set_alignment (GTK_MISC (label95), 0.24, 0.5); - - hseparator1 = gtk_hseparator_new (); - gtk_widget_set_name (hseparator1, "hseparator1"); - gtk_widget_show (hseparator1); - gtk_box_pack_start (GTK_BOX (vbox61), hseparator1, FALSE, FALSE, 0); - - label91 = gtk_label_new (_("Important: X2 & X3 sync hacks *will* cause choppy/skippy audio on many FMV movies.\nKnown to work well with a couple games, namely Shadow of the Colossus (but breaks most other games).")); + label91 = gtk_label_new (_("Important: the X2 sync hack *will* cause choppy/skippy audio on many FMV movies.")); gtk_widget_set_name (label91, "label91"); gtk_widget_show (label91); gtk_box_pack_start (GTK_BOX (vbox61), label91, FALSE, FALSE, 0); @@ -758,6 +720,41 @@ create_SpeedHacksDlg (void) gtk_frame_set_label_widget (GTK_FRAME (frame37), label105); gtk_label_set_use_markup (GTK_LABEL (label105), TRUE); + frame39 = gtk_frame_new (NULL); + gtk_widget_set_name (frame39, "frame39"); + gtk_widget_show (frame39); + gtk_box_pack_start (GTK_BOX (vbox72), frame39, TRUE, TRUE, 0); + + alignment34 = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_widget_set_name (alignment34, "alignment34"); + gtk_widget_show (alignment34); + gtk_container_add (GTK_CONTAINER (frame39), alignment34); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment34), 0, 0, 12, 0); + + vbox73 = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (vbox73, "vbox73"); + gtk_widget_show (vbox73); + gtk_container_add (GTK_CONTAINER (alignment34), vbox73); + + VUCycleHackScale = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, 4, 1, 0, 0))); + gtk_widget_set_name (VUCycleHackScale, "VUCycleHackScale"); + gtk_widget_show (VUCycleHackScale); + gtk_box_pack_start (GTK_BOX (vbox73), VUCycleHackScale, TRUE, TRUE, 0); + gtk_scale_set_draw_value (GTK_SCALE (VUCycleHackScale), FALSE); + gtk_scale_set_digits (GTK_SCALE (VUCycleHackScale), 0); + + vu_cycle_stealing_label = gtk_label_new (_("2: Moderate speedup, should work with most games with minor problems.")); + gtk_widget_set_name (vu_cycle_stealing_label, "vu_cycle_stealing_label"); + gtk_widget_show (vu_cycle_stealing_label); + gtk_box_pack_start (GTK_BOX (vbox73), vu_cycle_stealing_label, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (vu_cycle_stealing_label), TRUE); + + label111 = gtk_label_new (_("VU Cycle Stealing (Speedup for 3d geometry)")); + gtk_widget_set_name (label111, "label111"); + gtk_widget_show (label111); + gtk_frame_set_label_widget (GTK_FRAME (frame39), label111); + gtk_label_set_use_markup (GTK_LABEL (label111), TRUE); + vbox60 = gtk_vbox_new (FALSE, 0); gtk_widget_set_name (vbox60, "vbox60"); gtk_widget_show (vbox60); @@ -785,7 +782,7 @@ create_SpeedHacksDlg (void) gtk_box_pack_start (GTK_BOX (vbox60), label97, FALSE, FALSE, 0); gtk_label_set_line_wrap (GTK_LABEL (label97), TRUE); - check_intc_sync_hack = gtk_check_button_new_with_mnemonic (_("INTC Sync Hack (experimental)")); + check_intc_sync_hack = gtk_check_button_new_with_mnemonic (_("INTC Sync Hack")); gtk_widget_set_name (check_intc_sync_hack, "check_intc_sync_hack"); gtk_widget_show (check_intc_sync_hack); gtk_box_pack_start (GTK_BOX (vbox60), check_intc_sync_hack, FALSE, FALSE, 0); @@ -796,27 +793,26 @@ create_SpeedHacksDlg (void) gtk_box_pack_start (GTK_BOX (vbox60), label101, FALSE, FALSE, 0); gtk_label_set_line_wrap (GTK_LABEL (label101), TRUE); - frame36 = gtk_frame_new (NULL); - gtk_widget_set_name (frame36, "frame36"); - gtk_widget_show (frame36); - gtk_box_pack_start (GTK_BOX (vbox59), frame36, FALSE, FALSE, 0); + vbox71 = gtk_vbox_new (FALSE, 0); + gtk_widget_set_name (vbox71, "vbox71"); + gtk_widget_show (vbox71); + gtk_box_pack_start (GTK_BOX (vbox60), vbox71, TRUE, TRUE, 0); - alignment31 = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_set_name (alignment31, "alignment31"); - gtk_widget_show (alignment31); - gtk_container_add (GTK_CONTAINER (frame36), alignment31); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment31), 0, 0, 12, 0); + check_idle_loop_fastforward = gtk_check_button_new_with_mnemonic (_("Idle Loop Fast-Forward (experimental)")); + gtk_widget_set_name (check_idle_loop_fastforward, "check_idle_loop_fastforward"); + gtk_widget_show (check_idle_loop_fastforward); + gtk_box_pack_start (GTK_BOX (vbox71), check_idle_loop_fastforward, FALSE, FALSE, 0); - check_ESC_hack = gtk_check_button_new_with_mnemonic (_("Escape Hack - Use Esc key to fully exit PCSX2.")); - gtk_widget_set_name (check_ESC_hack, "check_ESC_hack"); - gtk_widget_show (check_ESC_hack); - gtk_container_add (GTK_CONTAINER (alignment31), check_ESC_hack); + label110 = gtk_label_new (_("Speedup for a few games, including FFX with no known side effects. More later.")); + gtk_widget_set_name (label110, "label110"); + gtk_widget_show (label110); + gtk_box_pack_start (GTK_BOX (vbox71), label110, FALSE, FALSE, 0); + gtk_label_set_line_wrap (GTK_LABEL (label110), TRUE); - label89 = gtk_label_new (_("Miscellaneous")); - gtk_widget_set_name (label89, "label89"); - gtk_widget_show (label89); - gtk_frame_set_label_widget (GTK_FRAME (frame36), label89); - gtk_label_set_use_markup (GTK_LABEL (label89), TRUE); + hseparator1 = gtk_hseparator_new (); + gtk_widget_set_name (hseparator1, "hseparator1"); + gtk_widget_show (hseparator1); + gtk_box_pack_start (GTK_BOX (vbox60), hseparator1, FALSE, FALSE, 0); dialog_action_area3 = GTK_DIALOG (SpeedHacksDlg)->action_area; gtk_widget_set_name (dialog_action_area3, "dialog_action_area3"); @@ -835,6 +831,12 @@ create_SpeedHacksDlg (void) gtk_dialog_add_action_widget (GTK_DIALOG (SpeedHacksDlg), button98, GTK_RESPONSE_CANCEL); GTK_WIDGET_SET_FLAGS (button98, GTK_CAN_DEFAULT); + g_signal_connect ((gpointer) EECycleHackScale, "value_changed", + G_CALLBACK (on_ee_slider_changed), + NULL); + g_signal_connect ((gpointer) VUCycleHackScale, "value_changed", + G_CALLBACK (on_vu_slider_changed), + NULL); g_signal_connect ((gpointer) button99, "clicked", G_CALLBACK (on_Speed_Hack_OK), NULL); @@ -848,20 +850,21 @@ create_SpeedHacksDlg (void) GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox59, "vbox59"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label88, "label88"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hbox39, "hbox39"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox72, "vbox72"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame37, "frame37"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment32, "alignment32"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox61, "vbox61"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_default_cycle_rate, "check_default_cycle_rate"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label98, "label98"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_1_5_cycle_rate, "check_1_5_cycle_rate"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label93, "label93"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_2_cycle_rate, "check_2_cycle_rate"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label94, "label94"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_3_cycle_rate, "check_3_cycle_rate"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label95, "label95"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator1, "hseparator1"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, EECycleHackScale, "EECycleHackScale"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, ee_cycle_label, "ee_cycle_label"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator2, "hseparator2"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label91, "label91"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label105, "label105"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame39, "frame39"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment34, "alignment34"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox73, "vbox73"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, VUCycleHackScale, "VUCycleHackScale"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vu_cycle_stealing_label, "vu_cycle_stealing_label"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label111, "label111"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox60, "vbox60"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_iop_cycle_rate, "check_iop_cycle_rate"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label96, "label96"); @@ -869,10 +872,10 @@ create_SpeedHacksDlg (void) GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label97, "label97"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_intc_sync_hack, "check_intc_sync_hack"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label101, "label101"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, frame36, "frame36"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, alignment31, "alignment31"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_ESC_hack, "check_ESC_hack"); - GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label89, "label89"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, vbox71, "vbox71"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, check_idle_loop_fastforward, "check_idle_loop_fastforward"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, label110, "label110"); + GLADE_HOOKUP_OBJECT (SpeedHacksDlg, hseparator1, "hseparator1"); GLADE_HOOKUP_OBJECT_NO_REF (SpeedHacksDlg, dialog_action_area3, "dialog_action_area3"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, button99, "button99"); GLADE_HOOKUP_OBJECT (SpeedHacksDlg, button98, "button98"); diff --git a/pcsx2/Linux/pcsx2.glade b/pcsx2/Linux/pcsx2.glade index 4e2513352c..ae3a436467 100644 --- a/pcsx2/Linux/pcsx2.glade +++ b/pcsx2/Linux/pcsx2.glade @@ -1275,270 +1275,250 @@ If you have problems, Disable all of these and try again. 0 - + True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN + False + 0 - + True - 0.5 - 0.5 - 1 - 1 - 0 - 0 - 12 - 0 + 0 + 0.5 + GTK_SHADOW_ETCHED_IN - + True - False - 2 + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 - + True - True - Default Cycle Rate - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - + False + 2 - - - True - Most compatible option - recommended for everyone with high-end machines. - False - False - GTK_JUSTIFY_LEFT - True - False - 0.289999991655 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - + + + True + True + False + GTK_POS_TOP + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 2 1 0 0 + + + + 0 + False + False + + - - - True - True - Use x1.5 Cycle Rate - True - GTK_RELIEF_NORMAL - True - False - False - True - check_default_cycle_rate - - - 0 - False - False - - + + + True + Most compatible option - recommended for everyone with high-end machines. + False + False + GTK_JUSTIFY_LEFT + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + - - - True - Moderate speedup, and works well with most games. - False - False - GTK_JUSTIFY_LEFT - True - False - 0.289999991655 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - + + + True + + + 0 + False + False + + - - - True - True - Use x2 Cycle Rate - True - GTK_RELIEF_NORMAL - True - False - False - True - check_default_cycle_rate + + + True + Important: the X2 sync hack *will* cause choppy/skippy audio on many FMV movies. + False + False + GTK_JUSTIFY_LEFT + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + - - 0 - False - False - - - - - - True - Big speedup! Works well with many games. - False - False - GTK_JUSTIFY_LEFT - True - False - 0.360000014305 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - True - Use x3 Cycle Rate - True - GTK_RELIEF_NORMAL - True - False - False - True - check_default_cycle_rate - - - 0 - False - False - - - - - - True - Big speedup, but causes flickering or missing geometry on many games. - False - False - GTK_JUSTIFY_LEFT - True - False - 0.239999994636 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - - - - - - True - - - 0 - False - False - - - - - - True - Important: X2 & X3 sync hacks *will* cause choppy/skippy audio on many FMV movies. -Known to work well with a couple games, namely Shadow of the Colossus (but breaks most other games). - False - False - GTK_JUSTIFY_LEFT - True - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - 0 - False - False - + + + + True + <b>EmotionEngine (EE) Sync Hacks</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + + + 0 + True + True + - + True - <b>EmotionEngine (EE) Sync Hacks</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 + 0 + 0.5 + GTK_SHADOW_ETCHED_IN + + + + True + 0.5 + 0.5 + 1 + 1 + 0 + 0 + 12 + 0 + + + + True + False + 0 + + + + True + True + False + GTK_POS_TOP + 0 + GTK_UPDATE_CONTINUOUS + False + 0 0 4 1 0 0 + + + + 0 + True + True + + + + + + True + 2: Moderate speedup, should work with most games with minor problems. + False + False + GTK_JUSTIFY_LEFT + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + + + + + True + <b>VU Cycle Stealing (Speedup for 3d geometry)</b> + False + True + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + label_item + + - label_item + 0 + True + True @@ -1649,7 +1629,7 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break True True - INTC Sync Hack (experimental) + INTC Sync Hack True GTK_RELIEF_NORMAL True @@ -1688,6 +1668,74 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break False + + + + True + False + 0 + + + + True + True + Idle Loop Fast-Forward (experimental) + True + GTK_RELIEF_NORMAL + True + False + False + True + + + 0 + False + False + + + + + + True + Speedup for a few games, including FFX with no known side effects. More later. + False + False + GTK_JUSTIFY_LEFT + True + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + 0 + True + True + + + + + + True + + + 0 + False + False + + 0 @@ -1702,71 +1750,6 @@ Known to work well with a couple games, namely Shadow of the Colossus (but break True - - - - True - 0 - 0.5 - GTK_SHADOW_ETCHED_IN - - - - True - 0.5 - 0.5 - 1 - 1 - 0 - 0 - 12 - 0 - - - - True - True - Escape Hack - Use Esc key to fully exit PCSX2. - True - GTK_RELIEF_NORMAL - True - False - False - True - - - - - - - - True - <b>Miscellaneous</b> - False - True - GTK_JUSTIFY_LEFT - False - False - 0.5 - 0.5 - 0 - 0 - PANGO_ELLIPSIZE_NONE - -1 - False - 0 - - - label_item - - - - - 0 - False - False - - 0 diff --git a/pcsx2/MMI.cpp b/pcsx2/MMI.cpp index 49b525d705..448c1bacff 100644 --- a/pcsx2/MMI.cpp +++ b/pcsx2/MMI.cpp @@ -177,11 +177,15 @@ void PLZCW() { _PLZCW (1); } -#define PMFHL_CLAMP(dst, src) \ - if ((int)src > (int)0x00007fff) dst = 0x7fff; \ - else \ - if ((int)src < (int)0xffff8000) dst = 0x8000; \ - else dst = (u16)src; +__forceinline void PMFHL_CLAMP(u16 dst, u16 src) +{ + if ((int)src > (int)0x00007fff) + dst = 0x7fff; + else if ((int)src < (int)0xffff8000) + dst = 0x8000; + else + dst = (u16)src; +} void PMFHL() { if (!_Rd_) return; diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp index dacea2eeea..72d3223137 100644 --- a/pcsx2/MTGS.cpp +++ b/pcsx2/MTGS.cpp @@ -224,7 +224,7 @@ void mtgsThreadObject::Start() m_post_InitDone.Wait(); if( m_returncode != 0 ) // means the thread failed to init the GS plugin - throw Exception::PluginFailure( "GS", "The GS plugin failed to open/initialize." ); + throw Exception::PluginFailure( "GS", wxLt("%s plugin initialization failed.") ); // plugin returned an error after having been asked very nicely to initialize itself." ); } mtgsThreadObject::~mtgsThreadObject() diff --git a/pcsx2/Makefile.am b/pcsx2/Makefile.am index 50069e2d73..087fc797d7 100644 --- a/pcsx2/Makefile.am +++ b/pcsx2/Makefile.am @@ -11,7 +11,7 @@ R3000AInterpreter.cpp R3000AOpcodeTables.cpp R5900.cpp R5900OpcodeImpl.cpp R5900 SPR.cpp SaveState.cpp Sif.cpp Sio.cpp SourceLog.cpp Stats.cpp System.cpp ThreadTools.cpp \ VU0.cpp VU0micro.cpp VU0microInterp.cpp VU1micro.cpp VU1microInterp.cpp VUflags.cpp VUmicroMem.cpp VUops.cpp \ Vif.cpp VifDma.cpp vssprintf.cpp vtlb.cpp xmlpatchloader.cpp AlignedMalloc.cpp \ -RecoverySystem.cpp Saveslots.cpp +RecoverySystem.cpp Saveslots.cpp Dump.cpp @@ -20,7 +20,8 @@ CDVD.h CDVDiso.h CDVDisodrv.h CDVDlib.h COP0.h Cache.h CdRom.h Common.h Counters Elfheader.h Exceptions.h GS.h Hw.h IopBios.h IopBios2.h IopCounters.h IopDma.h IopHw.h IopMem.h IopSio2.h Memcpyfast.h \ Memory.h MemoryCard.h Misc.h Patch.h Paths.h Plugins.h PrecompiledHeader.h IopCommon.h R3000A.h R5900.h R5900OpcodeTables.h \ SPR.h SamplProf.h SaveState.h Sif.h Sifcmd.h Sio.h SafeArray.h Stats.h StringUtils.h System.h Threading.h \ -VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h HostGui.h Pcsx2Config.h +VU.h VUflags.h VUmicro.h VUops.h Vif.h VifDma.h cheatscpp.h vtlb.h NakedAsm.h R5900Exceptions.h HostGui.h Pcsx2Config.h \ +Dump.h SUBDIRS = x86 . DebugTools IPU RDebug tinyxml NewGUI #Linux \ No newline at end of file diff --git a/pcsx2/Memory.cpp b/pcsx2/Memory.cpp index b30a545335..d279b010f5 100644 --- a/pcsx2/Memory.cpp +++ b/pcsx2/Memory.cpp @@ -42,6 +42,7 @@ BIOS #pragma warning(disable:4799) // No EMMS at end of function #include +#include #include "IopCommon.h" #include "iR5900.h" @@ -85,26 +86,26 @@ u16 ba0R16(u32 mem) // Attempts to load a BIOS rom file, by trying multiple combinations of base filename // and extension. The bios specified in Config.Bios is used as the base. -void loadBiosRom( const char *ext, u8 *dest, long maxSize ) +void loadBiosRom( const wxChar *ext, u8 *dest, long maxSize ) { - string Bios1; + wxString Bios1; long filesize; - string Bios( Path::Combine( Config.BiosDir, Config.Bios ) ); - // Try first a basic extension concatenation (normally results in something like name.bin.rom1) - ssprintf(Bios1, "%hs.%s", &Bios, ext); - if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 ) + const wxString Bios( g_Conf.Files.Bios() ); + Bios1.Printf( wxS("%s.%s"), Bios.c_str(), ext); + + if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 ) { // Try the name properly extensioned next (name.rom1) Bios1 = Path::ReplaceExtension( Bios, ext ); - if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 ) + if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 ) { // Try for the old-style method (rom1.bin) - Bios1 = Path::Combine( Config.BiosDir, ext ) + ".bin"; - if( (filesize=Path::getFileSize( Bios1 ) ) <= 0 ) + Bios1 = Path::Combine( g_Conf.Folders.Bios, (wxString)ext ) + wxT(".bin"); + if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 ) { - Console::Notice( "Bios Warning > %s not found.", params ext ); + Console::Notice( "Load Bios Warning: %s not found (this is not an error!)", params wxString(ext).ToAscii().data() ); return; } } @@ -112,9 +113,8 @@ void loadBiosRom( const char *ext, u8 *dest, long maxSize ) // if we made it this far, we have a successful file found: - FILE *fp = fopen(Bios1.c_str(), "rb"); - fread(dest, 1, min( maxSize, filesize ), fp); - fclose(fp); + wxFile fp( Bios1 ); + fp.Read( dest, min( maxSize, filesize ) ); } static u32 psMPWC[(Ps2MemSize::Base/32)>>12]; @@ -517,8 +517,8 @@ void __fastcall vuMicroRead128(u32 addr,mem128_t* data) data[1]=*(u64*)&vu->Micro[addr+8]; } -// [TODO] : Profile this code and see how often the VUs get written, and how -// often it changes the values being written (invoking a cpuClear). +// Profiled VU writes: Happen very infrequently, with exception of BIOS initialization (at most twice per +// frame in-game, and usually none at all after BIOS), so cpu clears aren't much of a big deal. template void __fastcall vuMicroWrite8(u32 addr,mem8_t data) @@ -738,8 +738,8 @@ void memReset() _ext_memWrite8<1>, _ext_memWrite16<1>, hwWrite32_page_0E, hwWrite64_page_0E, hwWrite128_generic ); - vtlbMemR32FP* page0F32( CHECK_INTC_STAT_HACK ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F ); - vtlbMemR64FP* page0F64( CHECK_INTC_STAT_HACK ? hwRead64_generic_INTC_HACK : hwRead64_generic ); + vtlbMemR32FP* page0F32( Config.Hacks.INTCSTATSlow ? hwRead32_page_0F_INTC_HACK : hwRead32_page_0F ); + vtlbMemR64FP* page0F64( Config.Hacks.INTCSTATSlow ? hwRead64_generic_INTC_HACK : hwRead64_generic ); hw_by_page[0xf] = vtlb_RegisterHandler( _ext_memRead8<1>, _ext_memRead16<1>, page0F32, page0F64, hwRead128_generic, @@ -780,29 +780,28 @@ void memReset() vtlb_VMap(0x00000000,0x00000000,0x20000000); vtlb_VMapUnmap(0x20000000,0x60000000); - FILE *fp; - string Bios( Path::Combine( Config.BiosDir, Config.Bios ) ); + wxString Bios( g_Conf.Files.Bios() ); - long filesize; - if( ( filesize = Path::getFileSize( Bios ) ) <= 0 ) + long filesize = Path::GetFileSize( Bios ); + if( filesize <= 0 ) { - //Console::Error("Unable to load bios: '%s', PCSX2 can't run without that", params Bios); - throw Exception::FileNotFound( Bios, - "The specified Bios file was not found. A bios is required for Pcsx2 to run.\n\nFile not found" ); + wxFile fp( Bios.c_str() ); + fp.Read( PS2MEM_ROM, min( (long)Ps2MemSize::Rom, filesize ) ); + } + else + { + // Translated: Bios file not found or not specified ... A bios is required for Pcsx2 to run! + throw Exception::FileNotFound( Bios, wxLt("Bios not found") ); } - - fp = fopen(Bios.c_str(), "rb"); - fread(PS2MEM_ROM, 1, min( (long)Ps2MemSize::Rom, filesize ), fp); - fclose(fp); BiosVersion = GetBiosVersion(); Console::Status("Bios Version %d.%d", params BiosVersion >> 8, BiosVersion & 0xff); //injectIRX("host.irx"); //not fully tested; still buggy - loadBiosRom("rom1", PS2MEM_ROM1, Ps2MemSize::Rom1); - loadBiosRom("rom2", PS2MEM_ROM2, Ps2MemSize::Rom2); - loadBiosRom("erom", PS2MEM_EROM, Ps2MemSize::ERom); + loadBiosRom( wxT("rom1"), PS2MEM_ROM1, Ps2MemSize::Rom1 ); + loadBiosRom( wxT("rom2"), PS2MEM_ROM2, Ps2MemSize::Rom2 ); + loadBiosRom( wxT("erom"), PS2MEM_EROM, Ps2MemSize::ERom ); } int mmap_GetRamPageInfo(void* ptr) @@ -820,6 +819,7 @@ void mmap_MarkCountedRamPage(void* ptr,u32 vaddr) u32 offset=((u8*)ptr-psM); offset>>=12; + psMPWC[(offset/32)] &= ~(1<<(offset&31)); for (u32 i=0;i #ifdef WIN32 -extern void NTFS_CompressFile( const char* file, bool compressMode ); +extern void NTFS_CompressFile( const wxString& file, bool compressMode ); #endif -FILE* MemoryCard::cardfile[2] = { NULL, NULL }; +wxFile MemoryCard::cardfile[2]; // Ensures memory card files are created/initialized. @@ -34,8 +35,8 @@ void MemoryCard::Init() { for( int i=0; i<2; i++ ) { - if( Config.Mcd[i].Enabled && cardfile[i] == NULL ) - cardfile[i] = Load(i); + if( Config.Mcd[i].Enabled && !cardfile[i].IsOpened() ) + Load( i ); } } @@ -48,88 +49,79 @@ void MemoryCard::Shutdown() void MemoryCard::Unload( uint mcd ) { jASSUME( mcd < 2 ); - - if(cardfile[mcd] == NULL) return; - fclose( cardfile[mcd] ); - cardfile[mcd] = NULL; + cardfile[mcd].Close(); } bool MemoryCard::IsPresent( uint mcd ) { jASSUME( mcd < 2 ); - return cardfile[mcd] != NULL; + return cardfile[mcd].IsOpened(); } -FILE *MemoryCard::Load( uint mcd ) +void MemoryCard::Load( uint mcd ) { - FILE *f; - jASSUME( mcd < 2 ); - string str( Config.Mcd[mcd].Filename ); + wxFileName fname( g_Conf.Files.Mcd( mcd ) ); + wxString str( fname.GetFullPath() ); - if( str.empty() ) - str = Path::Combine( MEMCARDS_DIR, fmt_string( "Mcd00%d.ps2", mcd ) ); - - if( !Path::Exists(str) ) - Create( str.c_str() ); + if( !fname.FileExists() ) + Create( str ); #ifdef WIN32 - NTFS_CompressFile( str.c_str(), Config.McdEnableNTFS ); + NTFS_CompressFile( str, Config.McdEnableNTFS ); #endif - f = fopen( str.c_str(), "r+b" ); + cardfile[mcd].Open( str.c_str(), wxFile::write ); - if (f == NULL) + if( !cardfile[mcd].IsOpened() ) { - Msgbox::Alert("Failed loading MemoryCard from file: %hs", params &str); - return NULL; + // Translation note: detailed description should mention that the memory card will be disabled + // for the duration of this session. + Msgbox::Alert( wxsFormat( _("Could not load MemoryCard from file: %s"), str.c_str() ) ); } - - return f; } -void MemoryCard::Seek( FILE *f, u32 adr ) +void MemoryCard::Seek( wxFile& f, u32 adr ) { - u32 size; - - fseek(f, 0, SEEK_END); size = ftell(f); + u32 size = f.Length(); + if (size == MCD_SIZE + 64) - fseek(f, adr + 64, SEEK_SET); + f.Seek( adr + 64 ); else if (size == MCD_SIZE + 3904) - fseek(f, adr + 3904, SEEK_SET); + f.Seek( adr + 3904 ); else - fseek(f, adr, SEEK_SET); + f.Seek( adr ); } void MemoryCard::Read( uint mcd, u8 *data, u32 adr, int size ) { jASSUME( mcd < 2 ); - FILE* const mcfp = cardfile[mcd]; + wxFile& mcfp( cardfile[mcd] ); - if( mcfp == NULL ) + if( !mcfp.IsOpened() ) { - Console::Error( "MemoryCard > Ignoring attempted read from disabled card." ); + DevCon::Error( "MemoryCard > Ignoring attempted read from disabled card." ); memset(data, 0, size); return; } Seek(mcfp, adr); - fread(data, 1, size, mcfp); + mcfp.Read( data, size ); } void MemoryCard::Save( uint mcd, const u8 *data, u32 adr, int size ) { jASSUME( mcd < 2 ); - FILE* const mcfp = cardfile[mcd]; + wxFile& mcfp( cardfile[mcd] ); - if( mcfp == NULL ) + if( !mcfp.IsOpened() ) { - Console::Error( "MemoryCard > Ignoring attempted save/write to disabled card." ); + DevCon::Error( "MemoryCard > Ignoring attempted save/write to disabled card." ); return; } Seek(mcfp, adr); u8 *currentdata = (u8 *)malloc(size); - fread(currentdata, 1, size, mcfp); + mcfp.Read( currentdata, size); for (int i=0; i(data); // clears to -1's jASSUME( mcd < 2 ); - FILE* const mcfp = cardfile[mcd]; + wxFile& mcfp( cardfile[mcd] ); - if( mcfp == NULL ) + if( !mcfp.IsOpened() ) { - DevCon::Notice( "MemoryCard > Ignoring seek for disabled card." ); + DevCon::Error( "MemoryCard > Ignoring seek for disabled card." ); return; } Seek(mcfp, adr); - fwrite(data, 1, 528*16, mcfp); + mcfp.Write( data, 528*16 ); } -void MemoryCard::Create( const char *mcdFile ) +void MemoryCard::Create( const wxString& mcdFile ) { //int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0}; - FILE* fp = fopen( mcdFile, "wb" ); - if( fp == NULL ) return; + wxFile fp( mcdFile, wxFile::write ); + if( !fp.IsOpened() ) return; + + u8 effeffs[528]; + memset8_obj<0xff>( effeffs ); + for( uint i=0; i<16384; i++ ) { - for( uint j=0; j<528; j++ ) fputc( 0xFF,fp ); - // for(j=0; j<16; j++) fputc(enc[j],fp); + for( uint j=0; j<528; j++ ) + fp.Write( effeffs, sizeof(effeffs) ); + + //for(j=0; j<16; j++) fputc(enc[j],fp); } - fclose( fp ); } u64 MemoryCard::GetCRC( uint mcd ) { jASSUME( mcd < 2 ); - FILE* const mcfp = cardfile[mcd]; - if( mcfp == NULL ) return 0; + wxFile& mcfp( cardfile[mcd] ); + if( !mcfp.IsOpened() ) return 0; Seek( mcfp, 0 ); u64 retval = 0; for( uint i=MC2_SIZE/sizeof(u64); i; --i ) { - u64 temp; fread( &temp, sizeof(temp), 1, mcfp ); + u64 temp; mcfp.Read( &temp, sizeof(temp) ); retval ^= temp; } diff --git a/pcsx2/MemoryCard.h b/pcsx2/MemoryCard.h index a098e1f2ad..397f412ea7 100644 --- a/pcsx2/MemoryCard.h +++ b/pcsx2/MemoryCard.h @@ -25,11 +25,12 @@ static const int MC2_SIZE = 1024 * 528 * 16; class MemoryCard { protected: - static FILE* cardfile[2]; - - static FILE* Load( uint mcdId ); - static void Seek( FILE* mcdfp, u32 adr ); - static void Create( const char *mcd ); + static wxFile cardfile[2]; + +public: + static void Load( uint mcdId ); + static void Seek( wxFile& mcdfp, u32 adr ); + static void Create( const wxString& mcd ); public: static void Init(); diff --git a/pcsx2/Misc.cpp b/pcsx2/Misc.cpp index 265e332a8a..78dacf8df6 100644 --- a/pcsx2/Misc.cpp +++ b/pcsx2/Misc.cpp @@ -25,6 +25,7 @@ #endif #include +#include #include "IopCommon.h" #include "HostGui.h" @@ -40,14 +41,13 @@ #include "COP0.h" #include "Cache.h" -#include "Paths.h" +#include "Dump.h" using namespace std; using namespace R5900; PcsxConfig Config; u32 BiosVersion; -char CdromId[12]; static int g_Pcsx2Recording = 0; // true 1 if recording video and sound bool renderswitch = 0; @@ -64,7 +64,8 @@ extern wxString strgametitle; #pragma pack(1) #endif -struct romdir{ +struct romdir +{ char fileName[10]; u16 extInfoSize; u32 fileSize; @@ -115,43 +116,46 @@ u32 GetBiosVersion() { } //2002-09-22 (Florin) -int IsBIOS(const char *filename, char *description) +bool IsBIOS(const wxString& filename, wxString& description) { - char ROMVER[14+1]; - FILE *fp; - unsigned int fileOffset=0, found=FALSE; - struct romdir rd; + uint fileOffset=0; + romdir rd; - wxString Bios( Path::Combine( Config.BiosDir, filename ) ); + wxFileName Bios( g_Conf.Folders.Bios + filename ); + wxFile fp( Bios.GetFullPath().c_str() ); - int biosFileSize = Path::getFileSize( Bios ); - if( biosFileSize <= 0) return FALSE; + if( !fp.IsOpened() ) return FALSE; - fp = fopen(Bios.c_str(), "rb"); - if (fp == NULL) return FALSE; + int biosFileSize = fp.Length(); + if( biosFileSize <= 0) return FALSE; - while ((ftell(fp)<512*1024) && (fread(&rd, DIRENTRY_SIZE, 1, fp)==1)) + while( (fp.Tell() < 512*1024) && (fp.Read( &rd, DIRENTRY_SIZE ) == DIRENTRY_SIZE) ) + { if (strcmp(rd.fileName, "RESET") == 0) - break; /* found romdir */ + break; // found romdir + } if ((strcmp(rd.fileName, "RESET") != 0) || (rd.fileSize == 0)) { - fclose(fp); return FALSE; //Unable to locate ROMDIR structure in file or a ioprpXXX.img } + bool found = false; + while(strlen(rd.fileName) > 0) { if (strcmp(rd.fileName, "ROMVER") == 0) // found romver { - uint filepos = ftell(fp); - fseek(fp, fileOffset, SEEK_SET); - if (fread(&ROMVER, 14, 1, fp) == 0) break; - fseek(fp, filepos, SEEK_SET);//go back + char aROMVER[14+1]; // ascii version loaded from disk. - const char zonefail[2] = { ROMVER[4], '\0' }; // the default "zone" (unknown code) + uint filepos = fp.Tell(); + fp.Seek( fileOffset ); + if( fp.Read( &aROMVER, 14 ) == 0 ) break; + fp.Seek( filepos ); //go back + + const char zonefail[2] = { aROMVER[4], '\0' }; // the default "zone" (unknown code) const char* zone = zonefail; - switch(ROMVER[4]) + switch(aROMVER[4]) { case 'T': zone = "T10K "; break; case 'X': zone = "Test "; break; @@ -163,15 +167,17 @@ int IsBIOS(const char *filename, char *description) case 'C': zone = "China "; break; } - sprintf(description, "%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s", zone, - ROMVER[0], ROMVER[1], // ver major - ROMVER[2], ROMVER[3], // ver minor - ROMVER[12], ROMVER[13], // day - ROMVER[10], ROMVER[11], // month - ROMVER[6], ROMVER[7], ROMVER[8], ROMVER[9], // year! - (ROMVER[5]=='C') ? "Console" : (ROMVER[5]=='D') ? "Devel" : "" + const wxString romver( wxString::FromAscii(aROMVER) ); + + description.Printf( wxT("%s v%c%c.%c%c(%c%c/%c%c/%c%c%c%c) %s"), wxString::FromAscii(zone).ToAscii().data(), + romver[0], romver[1], // ver major + romver[2], romver[3], // ver minor + romver[12], romver[13], // day + romver[10], romver[11], // month + romver[6], romver[7], romver[8], romver[9], // year! + (aROMVER[5]=='C') ? wxT("Console") : (aROMVER[5]=='D') ? wxT("Devel") : wxT("") ); - found = TRUE; + found = true; } if ((rd.fileSize % 0x10)==0) @@ -179,29 +185,26 @@ int IsBIOS(const char *filename, char *description) else fileOffset += (rd.fileSize + 0x10) & 0xfffffff0; - if (fread(&rd, DIRENTRY_SIZE, 1, fp)==0) break; + if (fp.Read( &rd, DIRENTRY_SIZE ) != DIRENTRY_SIZE) break; } fileOffset-=((rd.fileSize + 0x10) & 0xfffffff0) - rd.fileSize; - fclose(fp); - if (found) { - char percent[6]; - if ( biosFileSize < (int)fileOffset) { - sprintf(percent, " %d%%", biosFileSize*100/(int)fileOffset); - strcat(description, percent);//we force users to have correct bioses, - //not that lame scph10000 of 513KB ;-) + description << ((biosFileSize*100)/(int)fileOffset) << wxT("%"); + // we force users to have correct bioses, + // not that lame scph10000 of 513KB ;-) } - return TRUE; + return true; } - return FALSE; //fail quietly + return false; //fail quietly } -int GetPS2ElfName(char *name){ +int GetPS2ElfName( wxString& name ) +{ int f; char buffer[g_MaxPath];//if a file is longer...it should be shorter :D char *pos; @@ -231,18 +234,17 @@ int GetPS2ElfName(char *name){ return 1; } pos+=strlen("BOOT2"); - while (pos && *pos && pos<=&buffer[255] + while (pos && *pos && pos<&buffer[g_MaxPath] && (*pos<'A' || (*pos>'Z' && *pos<'a') || *pos>'z')) pos++; if (!pos || *pos==0) return 0; - sscanf(pos, "%s", name); + // the filename is everything up to the first CR/LF/tab.. ? + // Or up to any whitespace? (I'm opting for first CRLF/tab, although the old code + // apparently stopped on spaces too) --air + name = wxStringTokenizer( wxString::FromAscii( pos ) ).GetNextToken(); - if (strncmp("cdrom0:\\", name, 8) == 0) { - strncpy(CdromId, name+8, 11); CdromId[11] = 0; - } - #ifdef PCSX2_DEVBUILD FILE *fp; int i; @@ -281,7 +283,7 @@ void SaveGSState(const wxString& file) if( g_SaveGSStream ) return; Console::WriteLn( "Saving GS State..." ); - Console::WriteLn( "\t%hs", params file.c_str() ); + Console::WriteLn( "\t%s", params file.mb_str() ); g_fGSSave = new gzSavingState( file ); @@ -305,9 +307,9 @@ void LoadGSState(const wxString& file) catch( Exception::FileNotFound& ) { // file not found? try prefixing with sstates folder: - if( !Path::isRooted( file ) ) + if( !Path::IsRooted( file ) ) { - f = new gzLoadingState( Path::Combine( SSTATES_DIR, file ).c_str() ); + f = new gzLoadingState( Path::Combine( g_Conf.Folders.Savestates, file ) ); // If this load attempt fails, then let the exception bubble up to // the caller to deal with... @@ -350,9 +352,7 @@ char* mystrlwr( char* string ) static wxString GetGSStateFilename() { - wxString gsText; - gsText.Printf( "/%8.8X.%d.gs", ElfCRC, StatesC ); - return Path::Combine( SSTATES_DIR, gsText ); + return Path::Combine( g_Conf.Folders.Savestates, wxsFormat( wxT("/%8.8X.%d.gs"), ElfCRC, StatesC ) ); } void CycleFrameLimit(int dir) @@ -430,10 +430,11 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod) catch( Exception::BaseException& ex ) { // 99% of the time this is a file permission error and the - // cpu state is intact so just display a passive msg to console. + // cpu state is intact so just display a passive msg to console without + // raising an exception. - Console::Error( "Error > Could not save state to slot %d", params StatesC ); - Console::Error( ex.cMessage() ); + Console::Error( "Error! Could not save state to slot %d", params StatesC ); + Console::Error( ex.LogMessage() ); } break; @@ -446,7 +447,7 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod) Console::Notice( " > Selected savestate slot %d", params StatesC); if( GSchangeSaveState != NULL ) - GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).c_str()); + GSchangeSaveState(StatesC, SaveState::GetFilename(StatesC).mb_str()); break; case 3: @@ -471,16 +472,15 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod) // This is the bad one. Chances are the cpu has been reset, so emulation has // to be aborted. Sorry user! We'll give you some info for your trouble: - Console::Error( "An error occured while trying to load saveslot %d", params StatesC ); - Console::Error( ex.cMessage() ); - Msgbox::Alert( - "Pcsx2 encountered an error while trying to load the savestate\n" - "and emulation had to be aborted." ); - ClosePlugins( true ); throw Exception::CpuStateShutdown( - "Saveslot load failed; PS2 emulated state had to be shut down." ); // let the GUI handle the error "gracefully" + // english log message: + wxsFormat( wxT("Error! Could not load from saveslot %d\n"), StatesC ) + ex.LogMessage(), + + // translated message: + wxsFormat( _("Error loading saveslot %d. Emulator reset."), StatesC ) + ); } break; @@ -490,7 +490,7 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod) // note: VK_F5-VK_F7 are reserved for GS case 8: - GSmakeSnapshot( SNAPSHOTS_DIR "/" ); + GSmakeSnapshot( g_Conf.Folders.Snapshots.ToAscii().data() ); break; case 9: //gsdx "on the fly" renderer switching @@ -539,16 +539,16 @@ void ProcessFKeys(int fkey, struct KeyModifiers *keymod) // only take the first two words wxString gsText; - wxStringTokenizer parts( strgametitle, " " ); + wxStringTokenizer parts( strgametitle, L" " ); wxString name( parts.GetNextToken() ); // first part wxString part2( parts.GetNextToken() ); - - if( !!part2 ) - name += "_" + part2; - gsText.Printf( "%s.%d.gs", name.c_str(), StatesC ); - Text = Path::Combine( SSTATES_DIR, gsText ); + if( !!part2 ) + name += wxT("_") + part2; + + gsText.Printf( wxT("%s.%d.gs"), name.c_str(), StatesC ); + Text = Path::Combine( g_Conf.Folders.Savestates, gsText ); } else { diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index 2186be1774..f9dd17dfbf 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -34,7 +34,7 @@ extern uptr pDsp; //Used in GS, MTGS, Plugins, Misc u32 GetBiosVersion(); // Used in Misc, Memory extern u32 BiosVersion; // Used in Memory, Misc, CDVD -int GetPS2ElfName(char*); // Used in Misc, System, Linux, CDVD +int GetPS2ElfName( wxString& dest ); // Used in Misc, System, Linux, CDVD // Not sure what header these should go in. Probably not this one. void SetCPUState(u32 sseMXCSR, u32 sseVUMXCSR); @@ -65,7 +65,7 @@ extern u64 GetTickFrequency(); // Used in Misc,and Windows/Linux files. extern void ProcessFKeys(int fkey, struct KeyModifiers *keymod); // processes fkey related commands value 1-12 -extern int IsBIOS(const char *filename, char *description); +extern bool IsBIOS(const wxString& filename, wxString& description); //extern const char *LabelAuthors; //extern const char *LabelGreets; diff --git a/pcsx2/NakedAsm.h b/pcsx2/NakedAsm.h index 359f95183f..589bdc2957 100644 --- a/pcsx2/NakedAsm.h +++ b/pcsx2/NakedAsm.h @@ -63,4 +63,5 @@ void DispatcherReg(); } #endif -#endif \ No newline at end of file +#endif + diff --git a/pcsx2/NewGUI/App.h b/pcsx2/NewGUI/App.h index 780705e98a..93de21c39e 100644 --- a/pcsx2/NewGUI/App.h +++ b/pcsx2/NewGUI/App.h @@ -24,190 +24,7 @@ #include "System.h" class MainEmuFrame; - -class IniInterface // abstract base class! -{ -protected: - wxConfigBase& m_Config; - -public: - virtual ~IniInterface(); - explicit IniInterface(); - explicit IniInterface( wxConfigBase& config ); - - void SetPath( const wxString& path ); - void Flush(); - - virtual void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() )=0; - virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0; - virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0; - virtual void Entry( const wxString& var, bool& value, const bool defvalue=0 )=0; - - virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0; - virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0; - virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0; - - virtual void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 )=0; -}; - -class IniLoader : public IniInterface -{ -public: - virtual ~IniLoader(); - explicit IniLoader(); - explicit IniLoader( wxConfigBase& config ); - - void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() ); - void Entry( const wxString& var, int& value, const int defvalue=0 ); - void Entry( const wxString& var, uint& value, const uint defvalue=0 ); - void Entry( const wxString& var, bool& value, const bool defvalue=false ); - - void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition ); - void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize ); - void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect ); - - void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 ); -}; - - -class IniSaver : public IniInterface -{ -public: - virtual ~IniSaver(); - explicit IniSaver(); - explicit IniSaver( wxConfigBase& config ); - - void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() ); - void Entry( const wxString& var, int& value, const int defvalue=0 ); - void Entry( const wxString& var, uint& value, const uint defvalue=0 ); - void Entry( const wxString& var, bool& value, const bool defvalue=false ); - - void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition ); - void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize ); - void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect ); - - void EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue=0 ); -}; - -////////////////////////////////////////////////////////////////////////////////////////// -// -class AppConfig -{ -public: - struct ConsoleLogOptions - { - bool Visible; - // if true, DisplayPos is ignored and the console is automatically docked to the main window. - bool AutoDock; - // Display position used if AutoDock is false (ignored otherwise) - wxPoint DisplayPosition; - wxSize DisplaySize; - - void LoadSave( IniInterface& conf ); - }; - - struct FolderOptions - { - wxString Plugins; - wxString Bios; - wxString Snapshots; - wxString Savestates; - wxString MemoryCards; - }; - - // Options struct for each memory card. - struct McdOptions - { - wxString Filename; // user-configured location of this memory card - bool Enabled; // memory card enabled (if false, memcard will not show up in-game) - }; - - struct McdSysOptions - { - McdOptions Mcd[2]; - bool EnableNTFS; // enables automatic ntfs compression of memory cards (Win32 only) - bool EnableEjection; // enables simulated ejection of memory cards when loading savestates - - void LoadSave( IniInterface& conf ); - }; - - - struct CpuRecompilerOptions - { - struct - { - bool - Enabled:1, // universal toggle for the profiler. - RecBlocks_EE:1, // Enables per-block profiling for the EE recompiler [unimplemented] - RecBlocks_IOP:1, // Enables per-block profiling for the IOP recompiler [unimplemented] - RecBlocks_VU1:1; // Enables per-block profiling for the VU1 recompiler [unimplemented] - - } Profiler; - - struct - { - bool - EnableEE:1, - EnableIOP:1, - EnableVU0:1, - EnableVU1:1; - - } Recompiler; - - void LoadSave( IniInterface& conf ); - }; - - struct VideoOptions - { - bool MultithreadGS; // Uses the multithreaded GS interface. - bool closeOnEsc; // Closes the GS/Video port on escape (good for fullscreen activity) - bool UseFramelimiter; - - int RegionMode; // 0=NTSC and 1=PAL - int CustomFps; - int CustomFrameSkip; - int CustomConsecutiveFrames; - int CustomConsecutiveSkip; - - void LoadSave( IniInterface& conf ); - }; - - struct GamefixOptions - { - bool - VuAddSubHack:1, // Fix for Tri-ace games, they use an encryption algorithm that requires VU addi opcode to be bit-accurate. - VuClipFlagHack:1, // Fix for Digimon Rumble Arena 2, fixes spinning/hanging on intro-menu. - FpuCompareHack:1, // Fix for Persona games, maybe others. It's to do with the VU clip flag (again). - FpuMulHack:1; // Fix for Tales of Destiny hangs. - - void LoadSave(); - }; - - struct SpeedhackOptions - { - int - EECycleRate:3, // EE cyclerate selector (1.0, 1.5, 2.0, 3.0) - IopCycleRate_X2:1, // enables the x2 multiplier of the IOP cyclerate - ExtWaitcycles:1, // enables extended waitcycles duration - IntcStat:1; // tells Pcsx2 to fast-forward through intc_stat waits. - - void LoadSave( IniInterface& conf ); - }; - -public: - wxPoint MainGuiPosition; - bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console - - CpuRecompilerOptions Cpu; - SpeedhackOptions Speedhacks; - GamefixOptions Gamefixes; - VideoOptions Video; - ConsoleLogOptions ConLogBox; - FolderOptions Folders; - -public: - void LoadSave( IniInterface& ini ); -}; +class IniInterface; ////////////////////////////////////////////////////////////////////////////////////////// // @@ -229,6 +46,7 @@ public: virtual void OnClear(wxCommandEvent& event); virtual void Write( const wxChar* text ); + virtual void Write( const char* text ); void Newline(); void SetColor( Console::Colors color ); @@ -264,8 +82,12 @@ protected: public: Pcsx2App(); + wxFrame* GetMainWindow() const; + bool OnInit(); int OnExit(); + void OnInitCmdLine( wxCmdLineParser& parser ); + bool OnCmdLineParsed( wxCmdLineParser& parser ); const wxBitmap& GetLogoBitmap() const; MainEmuFrame& GetMainFrame() const @@ -281,5 +103,3 @@ public: }; DECLARE_APP(Pcsx2App) - -extern AppConfig g_Conf; diff --git a/pcsx2/NewGUI/AppConfig.cpp b/pcsx2/NewGUI/AppConfig.cpp index c44a262aa5..587262c4a2 100644 --- a/pcsx2/NewGUI/AppConfig.cpp +++ b/pcsx2/NewGUI/AppConfig.cpp @@ -18,147 +18,130 @@ #include "PrecompiledHeader.h" #include "App.h" +#include "IniInterface.h" -IniInterface::IniInterface( wxConfigBase& config ) : - m_Config( config ) -{ -} - -IniInterface::IniInterface() : - m_Config( *wxConfigBase::Get() ) -{ -} - -IniInterface::~IniInterface() -{ - Flush(); -} - -void IniInterface::SetPath( const wxString& path ) -{ - m_Config.SetPath( path ); -} - -void IniInterface::Flush() -{ - m_Config.Flush(); -} +#include ////////////////////////////////////////////////////////////////////////////////////////// +// PathDefs Namespace -- contains default values for various pcsx2 path names and locations. // - -IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config ) +// Note: The members of this namespace are intended for default value initialization only. +// Most of the time you should use the path folder assignments in Conf() instead, since those +// are user-configurable. +// +namespace PathDefs { -} - -IniLoader::IniLoader() : IniInterface() {} -IniLoader::~IniLoader() {} - - -void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue ) -{ - m_Config.Read( var, &value, defvalue ); -} - -void IniLoader::Entry( const wxString& var, int& value, const int defvalue ) -{ - m_Config.Read( var, &value, defvalue ); -} - -void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue ) -{ - m_Config.Read( var, (int*)&value, (int)defvalue ); -} - -void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue ) -{ - wxString dest; - m_Config.Read( var, &dest, defvalue ? "enabled" : "disabled" ); - value = (dest == "enabled") || (dest == "1"); -} - -void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) -{ - TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); -} - -void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize& defvalue ) -{ - TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); -} - -void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect& defvalue ) -{ - TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); -} - -void IniLoader::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue ) -{ - wxString retval; - m_Config.Read( var, &retval, enumArray[defvalue] ); - - int i=0; - while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++; - - if( enumArray[i] == NULL ) + const wxDirName Snapshots( wxT("snaps") ); + const wxDirName Savestates( wxT("sstates") ); + const wxDirName MemoryCards( wxT("memcards") ); + const wxDirName Configs( wxT("inis") ); + const wxDirName Plugins( wxT("plugins") ); + + // Fetches the path location for user-consumable documents -- stuff users are likely to want to + // share with other programs: screenshots, memory cards, and savestates. + wxDirName GetDocuments() { - Console::Notice( "Loadini Warning > Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.", - params retval.c_str(), var.c_str(), enumArray[defvalue] ); - value = defvalue; + return (wxDirName)wxStandardPaths::Get().GetDocumentsDir() + (wxDirName)wxGetApp().GetAppName(); } - else - value = i; -} -////////////////////////////////////////////////////////////////////////////////////////// -// + wxDirName GetSnapshots() + { + return (wxDirName)GetDocuments() + Snapshots; + } + + wxDirName GetBios() + { + return (wxDirName)wxT("bios"); + } + + wxDirName GetSavestates() + { + return (wxDirName)GetDocuments() + Savestates; + } + + wxDirName GetMemoryCards() + { + return (wxDirName)GetDocuments() + MemoryCards; + } + + wxDirName GetConfigs() + { + return (wxDirName)GetDocuments()+ Configs; + } -IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config ) + wxDirName GetPlugins() + { + return (wxDirName)Plugins; + } +}; + +namespace FilenameDefs { -} + wxFileName GetConfig() + { + // TODO : ini extension on Win32 is normal. Linux ini filename default might differ + // from this? like pcsx2_conf or something ... ? -IniSaver::IniSaver() : IniInterface() {} -IniSaver::~IniSaver() {} + return wxGetApp().GetAppName() + wxT(".ini"); + } + + wxFileName Memcard[2] = + { + wxT("Mcd001.ps2"), + wxT("Mcd002.ps2") + }; +}; -void IniSaver::Entry( const wxString& var, wxString& value, const wxString& defvalue ) +// ------------------------------------------------------------------------ +wxFileName wxDirName::Combine( const wxFileName& right ) const { - m_Config.Write( var, value ); + wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wxDirName concatenation." ); + if( right.IsAbsolute() ) + return right; + + // Append any directory parts from right, and then set the filename. + // Except we can't do that because our m_members are private (argh!) and there is no API + // for getting each component of the path. So instead let's use Normalize: + + wxFileName result( right ); + result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS, GetPath() ); + return result; } -void IniSaver::Entry( const wxString& var, int& value, const int defvalue ) +wxDirName wxDirName::Combine( const wxDirName& right ) const { - m_Config.Write( var, value ); + wxASSERT_MSG( IsDir() && right.IsDir(), L"Warning: Malformed directory name detected during wDirName concatenation." ); + + wxDirName result( right ); + result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS, GetPath() ); + return result; } -void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue ) +void wxDirName::Rmdir() { - m_Config.Write( var, (int)value ); + if( !Exists() ) return; + wxFileName::Rmdir(); + // TODO : Throw exception if operation failed? Do we care? } -void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue ) +bool wxDirName::Mkdir() { - m_Config.Write( var, value ? "enabled" : "disabled" ); + if( Exists() ) return true; + return wxFileName::Mkdir(); } -void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) -{ - m_Config.Write( var, ToString( value ) ); -} +// ------------------------------------------------------------------------ +wxString AppConfig::FullpathHelpers::Bios() const { return Path::Combine( m_conf.Folders.Bios, m_conf.BaseFilenames.Bios ); } +wxString AppConfig::FullpathHelpers::CDVD() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.CDVD ); } +wxString AppConfig::FullpathHelpers::GS() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.GS ); } +wxString AppConfig::FullpathHelpers::PAD1() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.PAD1 ); } +wxString AppConfig::FullpathHelpers::PAD2() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.PAD2 ); } +wxString AppConfig::FullpathHelpers::SPU2() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.SPU2 ); } +wxString AppConfig::FullpathHelpers::DEV9() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.DEV9 ); } +wxString AppConfig::FullpathHelpers::USB() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.USB ); } +wxString AppConfig::FullpathHelpers::FW() const { return Path::Combine( m_conf.Folders.Plugins, m_conf.BaseFilenames.FW ); } -void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize& defvalue ) -{ - m_Config.Write( var, ToString( value ) ); -} - -void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect& defvalue ) -{ - m_Config.Write( var, ToString( value ) ); -} - -void IniSaver::EnumEntry( const wxString& var, int& value, const char* const* enumArray, const int defvalue ) -{ - m_Config.Write( var, enumArray[value] ); -} +wxString AppConfig::FullpathHelpers::Mcd( uint mcdidx ) const { return Path::Combine( m_conf.Folders.MemoryCards, m_conf.MemoryCards.Mcd[mcdidx].Filename ); } ////////////////////////////////////////////////////////////////////////////////////////// // diff --git a/pcsx2/NewGUI/ConsoleLogger.cpp b/pcsx2/NewGUI/ConsoleLogger.cpp index 4c2d2dd96d..d97e8e4006 100644 --- a/pcsx2/NewGUI/ConsoleLogger.cpp +++ b/pcsx2/NewGUI/ConsoleLogger.cpp @@ -59,7 +59,7 @@ static bool OpenLogFile(wxFile& file, wxString& filename, wxWindow *parent) return false; default: - wxFAIL_MSG( "invalid message box return value" ); + wxFAIL_MSG( L"invalid message box return value" ); } return ( bAppend ) ? @@ -211,3 +211,14 @@ void ConsoleLogFrame::Write( const wxChar* text ) m_TextCtrl.AppendText( text ); } + +void ConsoleLogFrame::Write( const char* text ) +{ + // remove selection (WriteText is in fact ReplaceSelection) +#ifdef __WXMSW__ + wxTextPos nLen = m_TextCtrl.GetLastPosition(); + m_TextCtrl.SetSelection(nLen, nLen); +#endif + + m_TextCtrl.AppendText( wxString::FromAscii(text) ); +} diff --git a/pcsx2/NewGUI/Dialogs/AboutBoxDialog.cpp b/pcsx2/NewGUI/Dialogs/AboutBoxDialog.cpp index 815699e4d4..b55d063b20 100644 --- a/pcsx2/NewGUI/Dialogs/AboutBoxDialog.cpp +++ b/pcsx2/NewGUI/Dialogs/AboutBoxDialog.cpp @@ -52,7 +52,7 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): m_bitmap_ps2system( this, wxID_ANY, wxBitmap( EmbeddedImage().GetImage() ), wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN ) { - static const wxString LabelAuthors = _( + static const wxString LabelAuthors = wxString::FromAscii( "PCSX2, a PS2 emulator\n\n" "Active Devs: Arcum42, Refraction," "drk||raziel, cottonvibes, gigaherz," @@ -69,7 +69,7 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ): "Webmasters: CKemu, Falcon4ever" ); - static const wxString LabelGreets = _( + static const wxString LabelGreets = wxString::FromAscii( "Contributors: Hiryu and Sjeep for libcvd (the iso parsing and\n" "filesystem driver code), nneeve, pseudonym\n" "\n" diff --git a/pcsx2/NewGUI/HostGui.cpp b/pcsx2/NewGUI/HostGui.cpp new file mode 100644 index 0000000000..112fd9d272 --- /dev/null +++ b/pcsx2/NewGUI/HostGui.cpp @@ -0,0 +1,52 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "App.h" + +// This API is likely obsolete for the most part, so I've just included a few dummies +// to keep things compiling until I can get to the point of tying up loose ends. + +namespace HostGui +{ + // Sets the status bar message without mirroring the output to the console. + void SetStatusMsg( const wxString& text ) + { + wxGetApp().GetMainWindow()->SetStatusText( text ); + } + + void Notice( const wxString& text ) + { + // mirror output to the console! + Console::Status( text.c_str() ); + SetStatusMsg( text ); + } + + void ResetMenuSlots() + { + // Probably obsolete if we do a savestate dialog. + } + + void BeginExecution() + { + } + + void __fastcall KeyEvent( keyEvent* ev ) + { + } +} \ No newline at end of file diff --git a/pcsx2/NewGUI/IniInterface.cpp b/pcsx2/NewGUI/IniInterface.cpp new file mode 100644 index 0000000000..f29c5e63a3 --- /dev/null +++ b/pcsx2/NewGUI/IniInterface.cpp @@ -0,0 +1,165 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "System.h" +#include "IniInterface.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// +IniInterface::IniInterface( wxConfigBase& config ) : + m_Config( config ) +{ +} + +IniInterface::IniInterface() : + m_Config( *wxConfigBase::Get() ) +{ +} + +IniInterface::~IniInterface() +{ + Flush(); +} + +void IniInterface::SetPath( const wxString& path ) +{ + m_Config.SetPath( path ); +} + +void IniInterface::Flush() +{ + m_Config.Flush(); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// + +IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config ) +{ +} + +IniLoader::IniLoader() : IniInterface() {} +IniLoader::~IniLoader() {} + + +void IniLoader::Entry( const wxString& var, wxString& value, const wxString& defvalue ) +{ + m_Config.Read( var, &value, defvalue ); +} + +void IniLoader::Entry( const wxString& var, int& value, const int defvalue ) +{ + m_Config.Read( var, &value, defvalue ); +} + +void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue ) +{ + m_Config.Read( var, (int*)&value, (int)defvalue ); +} + +void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue ) +{ + wxString dest; + m_Config.Read( var, &dest, defvalue ? L"enabled" : L"disabled" ); + value = (dest == L"enabled") || (dest == L"1"); +} + +void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) +{ + TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); +} + +void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize& defvalue ) +{ + TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); +} + +void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect& defvalue ) +{ + TryParse( value, m_Config.Read( var, ToString( defvalue ) ), defvalue ); +} + +void IniLoader::EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue ) +{ + wxString retval; + m_Config.Read( var, &retval, enumArray[defvalue] ); + + int i=0; + while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++; + + if( enumArray[i] == NULL ) + { + Console::Notice( wxsFormat( L"Loadini Warning: Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.", + params retval.c_str(), var.c_str(), enumArray[defvalue] + ) ); + value = defvalue; + } + else + value = i; +} + +////////////////////////////////////////////////////////////////////////////////////////// +// + +IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config ) +{ +} + +IniSaver::IniSaver() : IniInterface() {} +IniSaver::~IniSaver() {} + +void IniSaver::Entry( const wxString& var, wxString& value, const wxString& defvalue ) +{ + m_Config.Write( var, value ); +} + +void IniSaver::Entry( const wxString& var, int& value, const int defvalue ) +{ + m_Config.Write( var, value ); +} + +void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue ) +{ + m_Config.Write( var, (int)value ); +} + +void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue ) +{ + m_Config.Write( var, value ? L"enabled" : L"disabled" ); +} + +void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue ) +{ + m_Config.Write( var, ToString( value ) ); +} + +void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize& defvalue ) +{ + m_Config.Write( var, ToString( value ) ); +} + +void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect& defvalue ) +{ + m_Config.Write( var, ToString( value ) ); +} + +void IniSaver::EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue ) +{ + m_Config.Write( var, enumArray[value] ); +} diff --git a/pcsx2/NewGUI/IniInterface.h b/pcsx2/NewGUI/IniInterface.h new file mode 100644 index 0000000000..0523c46bdc --- /dev/null +++ b/pcsx2/NewGUI/IniInterface.h @@ -0,0 +1,109 @@ +/* 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 + +#include + +////////////////////////////////////////////////////////////////////////////////////////// +// IniInterface class (abstract base class) +// +// This is used as an interchangable interface for both loading and saving options from an +// ini/configuration file. The LoadSave code takes an IniInterface, and the interface +// implementation defines whether the options are read or written. +// +// See also: IniLoader, IniSaver +// +class IniInterface +{ +protected: + wxConfigBase& m_Config; + +public: + virtual ~IniInterface(); + explicit IniInterface(); + explicit IniInterface( wxConfigBase& config ); + + void SetPath( const wxString& path ); + void Flush(); + + virtual void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() )=0; + virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0; + virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0; + virtual void Entry( const wxString& var, bool& value, const bool defvalue=0 )=0; + + virtual void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition )=0; + virtual void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize )=0; + virtual void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect )=0; + + virtual void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 )=0; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// IniLoader class +// +// Implementation of the IniInterface base class, which maps ini actions to loading from +// an ini source file. +// +// See also: IniInterface +// +class IniLoader : public IniInterface +{ +public: + virtual ~IniLoader(); + explicit IniLoader(); + explicit IniLoader( wxConfigBase& config ); + + void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() ); + void Entry( const wxString& var, int& value, const int defvalue=0 ); + void Entry( const wxString& var, uint& value, const uint defvalue=0 ); + void Entry( const wxString& var, bool& value, const bool defvalue=false ); + + void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition ); + void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize ); + void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect ); + + void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 ); +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// IniSaver class +// +// Implementation of the IniInterface base class, which maps ini actions to saving to +// an ini dest file. +// +// See also: IniInterface +// +class IniSaver : public IniInterface +{ +public: + virtual ~IniSaver(); + explicit IniSaver(); + explicit IniSaver( wxConfigBase& config ); + + void Entry( const wxString& var, wxString& value, const wxString& defvalue=wxString() ); + void Entry( const wxString& var, int& value, const int defvalue=0 ); + void Entry( const wxString& var, uint& value, const uint defvalue=0 ); + void Entry( const wxString& var, bool& value, const bool defvalue=false ); + + void Entry( const wxString& var, wxPoint& value, const wxPoint& defvalue=wxDefaultPosition ); + void Entry( const wxString& var, wxSize& value, const wxSize& defvalue=wxDefaultSize ); + void Entry( const wxString& var, wxRect& value, const wxRect& defvalue=wxDefaultRect ); + + void EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, const int defvalue=0 ); +}; diff --git a/pcsx2/NewGUI/MainFrame.cpp b/pcsx2/NewGUI/MainFrame.cpp index 34fad05afc..09273717c2 100644 --- a/pcsx2/NewGUI/MainFrame.cpp +++ b/pcsx2/NewGUI/MainFrame.cpp @@ -140,7 +140,7 @@ void MainEmuFrame::OnLogBoxHidden() MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, const wxPoint& pos, const wxSize& size, long style): wxFrame(parent, id, title, pos, size, wxCAPTION|wxCLOSE_BOX|wxSYSTEM_MENU|wxBORDER_THEME), - m_logbox( this, "Pcsx2 Log" ), + m_logbox( this, L"Pcsx2 Log" ), m_statusbar( *CreateStatusBar(2, 0) ), m_background( this, wxID_ANY, wxGetApp().GetLogoBitmap() ), @@ -161,7 +161,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, int id, const wxString& title, cons m_LoadStatesSubmenu( *MakeStatesSubMenu( Menu_State_Load01 ) ), m_SaveStatesSubmenu( *MakeStatesSubMenu( Menu_State_Save01 ) ), - m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, _T("Show Console"), wxEmptyString, wxITEM_CHECK ) ) + m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, Menu_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ) { wxGetApp().SetConsoleFrame( m_logbox ); diff --git a/pcsx2/NewGUI/main.cpp b/pcsx2/NewGUI/main.cpp index 8ae072a86d..5108eb7cd8 100644 --- a/pcsx2/NewGUI/main.cpp +++ b/pcsx2/NewGUI/main.cpp @@ -17,12 +17,13 @@ */ #include "PrecompiledHeader.h" +#include "IniInterface.h" #include "MainFrame.h" #include "Resources/EmbeddedImage.h" #include "Resources/BackgroundLogo.h" -#include +#include IMPLEMENT_APP(Pcsx2App) @@ -30,81 +31,14 @@ AppConfig g_Conf; const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord ); -////////////////////////////////////////////////////////////////////////////////////////// -// PathDefs Namespace -- contains default values for various pcsx2 path names and locations. -// -// Note: The members of this namespace are intended for default value initialization only. -// Most of the time you should use the path folder assignments in Conf() instead, since those -// are user-configurable. -// -namespace PathDefs -{ - const wxString Snapshots( "snaps" ); - const wxString Savestates( "sstates" ); - const wxString MemoryCards( "memcards" ); - const wxString Configs( "inis" ); - const wxString Plugins( "plugins" ); - - // Fetches the path location for user-consumable documents -- stuff users are likely to want to - // share with other programs: screenshots, memory cards, and savestates. - wxString GetDocuments() - { - return Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() ); - } - - wxString GetSnapshots() - { - return Path::Combine( GetDocuments(), Snapshots ); - } - - wxString GetBios() - { - return "bios"; - } - - wxString GetSavestates() - { - return Path::Combine( GetDocuments(), Savestates ); - } - - wxString GetMemoryCards() - { - return Path::Combine( GetDocuments(), MemoryCards ); - } - - wxString GetConfigs() - { - return Path::Combine( GetDocuments(), Configs ); - } - - wxString GetPlugins() - { - return Plugins; - } - - wxString GetWorking() - { - return wxGetCwd(); - } -}; - -namespace FilenameDefs -{ - wxString GetConfig() - { - // TODO : ini extension on Win32 is normal. Linux ini filename default might differ - // from this? like pcsx2_conf or something ... ? - - return wxGetApp().GetAppName() + ".ini"; - } -}; - Pcsx2App::Pcsx2App() : m_ConsoleFrame( NULL ) { - SetAppName( "Pcsx2" ); + SetAppName( L"Pcsx2" ); } +wxFrame* Pcsx2App::GetMainWindow() const { return m_MainFrame; } + wxFileConfig* OpenConfig( const wxString& filename ) { return new wxFileConfig( wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH ); @@ -114,21 +48,65 @@ wxFileConfig* OpenConfig( const wxString& filename ) // returns false if not (in which case the calling code should fall back on using OpenConfigUserLocal()) bool Pcsx2App::TryOpenConfigCwd() { - wxString inipath_cwd( Path::Combine( wxGetCwd(), PathDefs::Configs ) ); - if( !Path::isDirectory( inipath_cwd ) ) return false; + wxDirName inipath_cwd( (wxDirName)wxGetCwd() + PathDefs::Configs ); + if( !inipath_cwd.IsReadable() ) return false; wxString inifile_cwd( Path::Combine( inipath_cwd, FilenameDefs::GetConfig() ) ); - if( !Path::isFile( inifile_cwd ) ) return false; - if( Path::getFileSize( inifile_cwd ) <= 1 ) return false; + if( !Path::IsFile( inifile_cwd ) ) return false; + if( Path::GetFileSize( inifile_cwd ) <= 1 ) return false; wxConfigBase::Set( OpenConfig( inifile_cwd ) ); return true; } +void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser ) +{ + parser.SetLogo( _( + " >> Pcsx2 -- A Playstation2 Emulator for the PC\n" + ) ); + + parser.AddParam( _( "CDVD/ELF" ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL ); + + parser.AddSwitch( wxT("h"), wxT("help"), _("displays this list of command line options"), wxCMD_LINE_OPTION_HELP ); + parser.AddSwitch( wxT("nogui"), wxT("nogui"), _("disables display of the gui and enables the Escape Hack.") ); + + parser.AddOption( wxT("bootmode"), wxEmptyString, _("0 - quick (default), 1 - bios, 2 - load elf"), wxCMD_LINE_VAL_NUMBER ); + parser.AddOption( wxEmptyString, wxT("cfg"), _("configuration file override"), wxCMD_LINE_VAL_STRING ); + + parser.AddOption( wxEmptyString,wxT("cdvd"), _("uses filename as the CDVD plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("gs"), _("uses filename as the GS plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("spu"), _("uses filename as the SPU2 plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("pad"), _("uses filename as *both* PAD plugins for this session only.") ); + parser.AddOption( wxEmptyString,wxT("pad1"), _("uses filename as the PAD1 plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("pad2"), _("uses filename as the PAD2 plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("dev9"), _("uses filename as the DEV9 plugin for this session only.") ); + parser.AddOption( wxEmptyString,wxT("usb"), _("uses filename as the USB plugin for this session only.") ); + + parser.SetSwitchChars( wxT("-") ); +} + +bool Pcsx2App::OnCmdLineParsed(wxCmdLineParser& parser) +{ + if( parser.GetParamCount() >= 1 ) + { + // [TODO] : Unnamed parameter is taken as an "autorun" option for a cdvd/iso. + parser.GetParam( 0 ); + } + + // Suppress wxWidgets automatic options parsing since none of them pertain to Pcsx2 needs. + //wxApp::OnCmdLineParsed( parser ); + + bool yay = parser.Found( wxT("nogui") ); + + return true; +} + bool Pcsx2App::OnInit() { wxInitAllImageHandlers(); + wxApp::OnInit(); + // Ini Startup: The ini file could be in one of two locations, depending on how Pcsx2 has // been installed or configured. The first place we look is in our program's working // directory. If the ini there exist, and is *not* empty, then we'll use it. Otherwise @@ -136,8 +114,8 @@ bool Pcsx2App::OnInit() if( !TryOpenConfigCwd() ) { - Path::CreateDirectory( PathDefs::GetDocuments() ); - Path::CreateDirectory( PathDefs::GetConfigs() ); + PathDefs::GetDocuments().Mkdir(); + PathDefs::GetConfigs().Mkdir(); // Allow wx to use our config, and enforces auto-cleanup as well wxConfigBase::Set( OpenConfig( Path::Combine( PathDefs::GetConfigs(), FilenameDefs::GetConfig() ) ) ); diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 5209ff6fa9..52f08247d7 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -24,7 +24,6 @@ #define _PC_ // disables MIPS opcode macros. #include "IopCommon.h" -#include "Paths.h" #include "Patch.h" #include "VU.h" @@ -462,20 +461,25 @@ void patchFunc_comment( char * text1, char * text2 ) void patchFunc_gametitle( char * text1, char * text2 ) { Console::WriteLn( "gametitle: %s", params text2 ); - strgametitle = text2; - Console::SetTitle(strgametitle); + strgametitle.FromAscii( text2 ); + Console::SetTitle( strgametitle ); } void patchFunc_patch( char * cmd, char * param ) { - char * pText; + char* pText; if ( patchnumber >= MAX_PATCH ) { + // TODO : Use wxLogError for this, once we have full unicode compliance on cmd/params vars. + //wxLogError( wxT("Patch ERROR: Maximum number of patches reached: %s=%s"), cmd, param ); Console::Error( "Patch ERROR: Maximum number of patches reached: %s=%s", params cmd, param ); return; } + //SafeList pieces; + //SplitString( pieces, param, "," ); + pText = strtok( param, "," ); pText = param; @@ -536,7 +540,10 @@ void inifile_command( char * cmd ) code = PatchTableExecute( command, parameter, commands ); } -void inifile_trim( char * buffer ) +#define USE_CRAZY_BASHIT_INSANE_TRIM +#ifdef USE_CRAZY_BASHIT_INSANE_TRIM + +void inifile_trim( char* buffer ) { char * pInit = buffer; char * pEnd = NULL; @@ -574,6 +581,33 @@ void inifile_trim( char * buffer ) buffer[ pEnd - pInit + 1 ] = '\0'; } +#else + +// New version of trim (untested), which I coded but can't use yet because the +// rest of Patch needs to be more wxString-involved first. + +void inifile_trim( wxString& buffer ) +{ + buffer.Trim( false ); // trims left side. + + if( buffer.Length() <= 1 ) // this I'm not sure about... - air + { + buffer.Clear(); + return; + } + + if( buffer.Left( 2 ) == "//" ) + { + buffer.Clear(); + return; + } + + buffer.Trim(true); // trims right side. +} + +#endif + + void inisection_process( FILE * f1 ) { char buffer[ 1024 ]; @@ -621,7 +655,7 @@ void inifile_read( const char * name ) if( !f1 ) { - Console::WriteLn("No patch found.Resuming execution without a patch (this is NOT an error)." ); + Console::WriteLn("No patch found. Resuming execution without a patch (this is NOT an error)." ); return; } diff --git a/pcsx2/Patch.h b/pcsx2/Patch.h index e032614d51..53fb108762 100644 --- a/pcsx2/Patch.h +++ b/pcsx2/Patch.h @@ -115,8 +115,8 @@ extern int g_ZeroGSOptions; extern u32 g_sseMXCSR; extern u32 g_sseVUMXCSR; -void SetRoundMode(u32 ee, u32 vu); -int LoadPatch(const std::string& patchfile); +extern void SetRoundMode(u32 ee, u32 vu); +extern int LoadPatch(const wxString& patchfile); #endif /* __PATCH_H__ */ diff --git a/pcsx2/PathUtils.cpp b/pcsx2/PathUtils.cpp index 3b7fbe4fcd..e94132a7c1 100644 --- a/pcsx2/PathUtils.cpp +++ b/pcsx2/PathUtils.cpp @@ -36,65 +36,79 @@ namespace Path #ifdef WIN32 // Path Separator used when creating new paths. -static const char Separator( '\\' ); +static const wxChar Separator( wxT('\\') ); // Path separators used when breaking existing paths into parts and pieces. -static const wxString Delimiters( "\\/" ); +static const wxString Delimiters( wxT("\\/") ); + +static const wxChar SeparatorExt( wxT('.') ); + #else static const char Separator = '/'; static const char Delimiters( '/' ); #endif +static bool IsPathSeparator( wxChar src ) +{ +#ifdef WIN32 + return (src == Separator) || (src == wxT('/')); +#else + return src == Separator; +#endif +} + bool Exists( const wxString& path ) { - struct stat sbuf; - return stat( path.c_str(), &sbuf ) == 0; + wxStructStat sbuf; + return wxStat( path.c_str(), &sbuf ) == 0; } // This function returns false if the path does not exist, or if the path exists and // is a file. -bool isDirectory( const wxString& path ) +bool IsDirectory( const wxString& path ) { - struct stat sbuf; - if( stat( path.c_str(), &sbuf ) == -1 ) return false; + wxStructStat sbuf; + if( wxStat( path.c_str(), &sbuf ) == -1 ) return false; return !!(sbuf.st_mode & _S_IFDIR); } // This function returns false if the path does not exist, or if the path exists and // is a directory. -bool isFile( const wxString& path ) +bool IsFile( const wxString& path ) { - struct stat sbuf; - if( stat( path.c_str(), &sbuf ) == -1 ) return false; + wxStructStat sbuf; + if( wxStat( path.c_str(), &sbuf ) == -1 ) return false; return !!(sbuf.st_mode & _S_IFREG); } // Returns the length of the file. // returns -1 if the file is not found. -int getFileSize( const wxString& path ) +int GetFileSize( const wxString& path ) { - struct stat sbuf; - if( stat( path.c_str(), &sbuf ) == -1 ) return -1; + wxStructStat sbuf; + if( wxStat( path.c_str(), &sbuf ) == -1 ) return -1; return sbuf.st_size; } -bool isRooted( const wxString& path ) +bool IsRooted( const wxString& path ) { // if the first character is a backslash or period, or the second character // a colon, it's a safe bet we're rooted. - if( path[0] == 0 ) return FALSE; + if( path[0] == 0 ) return false; #ifdef WIN32 - return (path[0] == '/') || (path[0] == '\\') || (path[1] == ':'); + return IsPathSeparator(path[0]) || ( (path[1] == ':') && IsPathSeparator(path[2]) ); #else - return (path[0] == Separator); + return IsPathSeparator(path[0]); #endif } +// ------------------------------------------------------------------------ // Concatenates two pathnames together, inserting delimiters (backslash on win32) // as needed! Assumes the 'dest' is allocated to at least g_MaxPath length. wxString Combine( const wxString& srcPath, const wxString& srcFile ) { - int pathlen, guesslen; +#if 0 + int pathlen; if( srcFile.empty() ) { @@ -102,7 +116,7 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile ) return srcPath; } - if( isRooted( srcFile ) || srcPath.empty() ) + if( IsRooted( srcFile ) || srcPath.empty() ) { // No source path? Or source filename is rooted? // Return the filename unmodified. @@ -114,7 +128,7 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile ) // This might be a problem on Linux builds or maybe it doesn't matter? pathlen = srcPath.length(); - while( pathlen > 0 && ((srcPath[pathlen-1] == '\\') || (srcPath[pathlen-1] == '/')) ) + while( pathlen > 0 && IsPathSeparator(srcPath[pathlen-1]) ) --pathlen; // Concatenate strings: @@ -129,14 +143,31 @@ wxString Combine( const wxString& srcPath, const wxString& srcFile ) dest += Separator; dest += srcFile; return dest; + +#else + // Use wx's Path system for concatenation because it's pretty smart. + + return (wxDirName( srcPath ) + srcFile).GetFullPath(); +#endif +} + +wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile ) +{ + return (srcPath + srcFile).GetFullPath(); +} + +wxString Combine( const wxString& srcPath, const wxDirName& srcFile ) +{ + return ((wxDirName)srcPath + srcFile).ToString(); } // Replaces the extension of the file with the one given. +// This function works for path names as well as file names. wxString ReplaceExtension( const wxString& src, const wxString& ext ) { wxString dest; - int pos = src.find_last_of( '.' ); + int pos = src.find_last_of( SeparatorExt ); if( pos == wxString::npos || pos == 0 ) dest = src; else @@ -151,97 +182,32 @@ wxString ReplaceExtension( const wxString& src, const wxString& ext ) return dest; } -// finds the starting character position of a filename for the given source path. -static int _findFilenamePosition( const wxString& src) -{ - // note: the source path could have multiple trailing slashes. We want to ignore those. - - unsigned int startpos = src.find_last_not_of( Delimiters ); - - if(startpos == wxString::npos ) - return 0; - - int pos; - - if( startpos < src.length() ) - { - wxString trimmed( src.begin(), src.begin()+startpos ); - pos = trimmed.find_last_of( Delimiters ); - } - else - { - pos = src.find_last_of( Delimiters ); - } - - if( pos == wxString::npos ) - return 0; - - return pos; -} - wxString ReplaceFilename( const wxString& src, const wxString& newfilename ) { - wxString dest; - int pos = _findFilenamePosition( src ); + // Implementation note: use wxWidgets to do this job. - if( pos == 0 ) - dest = src; - else - dest.assign( src.begin(), src.begin()+pos ); - - if( !newfilename.empty() ) - { - dest += Separator; - dest += newfilename; - } - return dest; + wxFileName jojo( src ); + jojo.SetFullName( newfilename ); + return jojo.GetFullPath(); } wxString GetFilename( const wxString& src ) { - int pos = _findFilenamePosition( src ); - return wxString( src.begin()+pos, src.end() ); + return wxFileName(src).GetFullName(); } wxString GetFilenameWithoutExt( const wxString& src ) { - wxString fname( GetFilename( src ) ); - - int pos = fname.find_last_of( '.' ); - if( pos == wxString::npos || pos == 0 ) - return fname; - else - return wxString( fname.begin(), fname.begin()+pos ); + return wxFileName(src).GetName(); } wxString GetDirectory( const wxString& src ) { - int pos = _findFilenamePosition( src ); - if( pos == 0 ) - return wxString(); - else - return wxString( src.begin(), src.begin()+pos ); + return wxFileName(src).GetPath(); } -// This function mimics the old ANSI C splitpath function. It's more or less superceeded -// by one of the many other Path utility functions, but someone might find it useful. -void Split( const wxString& src, wxString& destpath, wxString& destfile ) -{ - int pos = _findFilenamePosition( src ); - if( pos == 0 ) - { - destpath.clear(); - destfile = src; - } - else - { - destpath.assign( src.begin(), src.begin()+pos ); - destfile.assign( src.begin()+pos, src.end() ); - } -} - -// Assigns the base/root directory of the given path into dest. +// returns the base/root directory of the given path. // Example /this/that/something.txt -> dest == "/" wxString GetRootDirectory( const wxString& src ) { @@ -254,11 +220,12 @@ wxString GetRootDirectory( const wxString& src ) void CreateDirectory( const wxString& src ) { -#ifdef _WIN32 - _mkdir( src.c_str() ); -#else - mkdir( src.c_str(), 0755); -#endif + wxFileName::Mkdir( src ); +} + +void RemoveDirectory( const wxString& src ) +{ + wxFileName::Rmdir( src ); } } diff --git a/pcsx2/Paths.h b/pcsx2/Paths.h index 4d118878a8..2c9c8a4e6c 100644 --- a/pcsx2/Paths.h +++ b/pcsx2/Paths.h @@ -7,6 +7,11 @@ extern char MAIN_DIR[g_MaxPath]; #endif +////////////////////////////////////////////////////////////////////////////////////////// +// Obsolete Values in wxWidgets Branch! +// The following set of macros has been superceeded by the PathDefs and FilenameDefs namespaces, +// and furethermore by a set of user-configurable paths in g_Conf. +// #define DEFAULT_INIS_DIR "inis" #define DEFAULT_BIOS_DIR "bios" #define DEFAULT_PLUGINS_DIR "plugins" @@ -25,25 +30,170 @@ extern char MAIN_DIR[g_MaxPath]; // Windows.h namespace pollution! #undef CreateDirectory +////////////////////////////////////////////////////////////////////////////////////////// +// +class wxDirName : protected wxFileName +{ +public: + explicit wxDirName( const wxFileName& src ) + { + wxASSERT_MSG( src.IsDir(), L"Warning: Creating a directory from what looks to be a filename..." ); + Assign( src.GetPath() ); + } + + wxDirName() : wxFileName() {} + wxDirName( const wxDirName& src ) : wxFileName( src ) { } + explicit wxDirName( const char* src ) { Assign( wxString::FromAscii(src) ); } + explicit wxDirName( const wxString& src ) { Assign( src ); } + + // ------------------------------------------------------------------------ + void Assign( const wxString& volume, const wxString& path ) + { + wxFileName::Assign( volume, path, wxEmptyString ); + } + + void Assign( const wxString& path ) + { + wxFileName::Assign( path, wxEmptyString ); + } + + void Assign( const wxDirName& path ) + { + wxFileName::Assign( path ); + } + + void Clear() { wxFileName::Clear(); } + + wxCharBuffer ToAscii() const { return GetPath().ToAscii(); } + wxString ToString() const { return GetPath(); } + + // ------------------------------------------------------------------------ + bool IsWritable() const { return IsDirWritable(); } + bool IsReadable() const { return IsDirReadable(); } + bool Exists() const { return DirExists(); } + bool IsOk() const { return wxFileName::IsOk(); } + + bool SameAs( const wxDirName& filepath ) const + { + return wxFileName::SameAs( filepath ); + } + + // Returns the number of sub folders in this directory path + size_t GetCount() const { return GetDirCount(); } + + // ------------------------------------------------------------------------ + wxFileName Combine( const wxFileName& right ) const; + wxDirName Combine( const wxDirName& right ) const; + + // removes the lastmost directory from the path + void RemoveLast() { wxFileName::RemoveDir(GetCount() - 1); } + + // ------------------------------------------------------------------------ + bool Normalize( int flags = wxPATH_NORM_ALL, const wxString& cwd = wxEmptyString ) + { + wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." ); + return wxFileName::Normalize( flags, cwd ); + } + + bool MakeRelativeTo( const wxString& pathBase = wxEmptyString ) + { + wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." ); + return wxFileName::MakeRelativeTo( pathBase ); + } + + bool MakeAbsolute( const wxString& cwd = wxEmptyString ) + { + wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." ); + return wxFileName::MakeAbsolute( cwd ); + } + + // ------------------------------------------------------------------------ + + void AssignCwd( const wxString& volume = wxEmptyString ) { wxFileName::AssignCwd( volume ); } + bool SetCwd() { wxFileName::SetCwd(); } + + // wxWidgets is missing the const qualifier for this one! Shame! + void Rmdir(); + bool Mkdir(); + + // ------------------------------------------------------------------------ + + wxDirName& operator=(const wxDirName& dirname) { Assign( dirname ); return *this; } + wxDirName& operator=(const wxString& dirname) { Assign( dirname ); return *this; } + wxDirName& operator=(const char* dirname) { Assign( wxString::FromAscii(dirname) ); return *this; } + + wxFileName operator+( const wxFileName& right ) const { return Combine( right ); } + wxDirName operator+( const wxDirName& right ) const { return Combine( right ); } + + bool operator==(const wxDirName& filename) const { return SameAs(filename); } + bool operator!=(const wxDirName& filename) const { return !SameAs(filename); } + + bool operator==(const wxFileName& filename) const { return SameAs(wxDirName(filename)); } + bool operator!=(const wxFileName& filename) const { return !SameAs(wxDirName(filename)); } + + // compare with a filename string interpreted as a native file name + bool operator==(const wxString& filename) const { return SameAs(wxDirName(filename)); } + bool operator!=(const wxString& filename) const { return !SameAs(wxDirName(filename)); } +}; + +// remove windows.h namespace pollution: +#undef GetFileSize +#undef CreateDirectory + +////////////////////////////////////////////////////////////////////////////////////////// +// Path Namespace +// Cross-platform utilities for manipulation of paths and filenames. +// namespace Path { - extern bool isRooted( const wxString& path ); - extern bool isDirectory( const wxString& path ); - extern bool isFile( const wxString& path ); + extern bool IsRooted( const wxString& path ); + extern bool IsDirectory( const wxString& path ); + extern bool IsFile( const wxString& path ); extern bool Exists( const wxString& path ); - extern int getFileSize( const wxString& path ); + extern int GetFileSize( const wxString& path ); extern wxString Combine( const wxString& srcPath, const wxString& srcFile ); + extern wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile ); + extern wxString Combine( const wxString& srcPath, const wxDirName& srcFile ); extern wxString ReplaceExtension( const wxString& src, const wxString& ext ); extern wxString ReplaceFilename( const wxString& src, const wxString& newfilename ); extern wxString GetFilename( const wxString& src ); extern wxString GetDirectory( const wxString& src ); extern wxString GetFilenameWithoutExt( const string& src ); extern wxString GetRootDirectory( const wxString& src ); - extern void Split( const wxString& src, wxString& destpath, wxString& destfile ); extern void CreateDirectory( const wxString& src ); - + extern void RemoveDirectory( const wxString& src ); } +////////////////////////////////////////////////////////////////////////////////////////// +// PathDefs Namespace -- contains default values for various pcsx2 path names and locations. +// +// Note: The members of this namespace are intended for default value initialization only. +// Most of the time you should use the path folder assignments in g_Conf instead, since those +// are user-configurable. +// +namespace PathDefs +{ + extern const wxDirName Snapshots; + extern const wxDirName Savestates; + extern const wxDirName MemoryCards; + extern const wxDirName Configs; + extern const wxDirName Plugins; + + extern wxDirName GetDocuments(); + extern wxDirName GetSnapshots(); + extern wxDirName GetBios(); + extern wxDirName GetSavestates(); + extern wxDirName GetMemoryCards(); + extern wxDirName GetConfigs(); + extern wxDirName GetPlugins(); +} + +namespace FilenameDefs +{ + extern wxFileName GetConfig(); + extern wxFileName Memcard[2]; +}; + #endif diff --git a/pcsx2/Plugins.cpp b/pcsx2/Plugins.cpp index de048465cb..6c7ff2033d 100644 --- a/pcsx2/Plugins.cpp +++ b/pcsx2/Plugins.cpp @@ -216,6 +216,9 @@ _FWabout FWabout; DEV9handler dev9Handler; USBhandler usbHandler; +uptr pDsp; + +#ifdef _not_wxWidgets_Land_ #define Sfy(x) #x #define Strfy(x) Sfy(x) @@ -695,7 +698,6 @@ void ShutdownPlugins() initp = false; } -uptr pDsp; extern void spu2DMA4Irq(); extern void spu2DMA7Irq(); extern void spu2Irq(); @@ -922,3 +924,25 @@ void PluginsResetGS() int ret = GSinit(); if (ret != 0) { Msgbox::Alert("GSinit error: %d", params ret); } } + +#else + +int OpenPlugins(const char* pTitleFilename) +{ + return 0; +} + + +void ClosePlugins( bool closegs ) +{ +} + +void ShutdownPlugins() +{ +} + +void CloseGS() +{ +} + +#endif \ No newline at end of file diff --git a/pcsx2/PrecompiledHeader.h b/pcsx2/PrecompiledHeader.h index aa80bcc7ee..b00207fd7b 100644 --- a/pcsx2/PrecompiledHeader.h +++ b/pcsx2/PrecompiledHeader.h @@ -36,12 +36,16 @@ #include #include #include // for wxPoint/wxRect stuff +#include +#include +#include extern const wxRect wxDefaultRect; // wxWidgets lacks one of its own. ////////////////////////////////////////////////////////////////////////////////////////// // Include the STL junk that's actually handy. +#include #include #include #include @@ -67,10 +71,19 @@ using std::max; typedef int BOOL; -# undef TRUE -# undef FALSE -# define TRUE 1 -# define FALSE 0 +#undef TRUE +#undef FALSE +#define TRUE 1 +#define FALSE 0 + +// This should prove useful.... +#define wxsFormat wxString::Format + +// macro provided for tagging translation strings, without actually running them through the +// translator (which the _() does automatically, and sometimes we don't want that) +#define wxLt(a) a + +#define wxASSERT_MSG_A( cond, msg ) wxASSERT_MSG( cond, wxString::FromAscii(msg).c_str() ); ////////////////////////////////////////////////////////////////////////////////////////// // Begin Pcsx2 Includes: Add items here that are local to Pcsx2 but stay relatively @@ -79,6 +92,8 @@ typedef int BOOL; #include "zlib/zlib.h" #include "PS2Etypes.h" +#include "Paths.h" +#include "Config.h" #include "StringUtils.h" #include "Exceptions.h" #include "MemcpyFast.h" @@ -141,24 +156,33 @@ static __forceinline u32 timeGetTime() # define __releaseinline __forceinline #endif -////////////////////////////////////////////////////////////////////////////////////////// -// Emitter Instance Identifiers. If you add a new emitter, do it here also. -// Note: Currently most of the instances map back to 0, since existing dynarec code all -// shares iCore and must therefore all share the same emitter instance. -// (note: these don't really belong here per-se, but it's an easy spot to use for now) -enum -{ - EmitterId_R5900 = 0, - EmitterId_R3000a = EmitterId_R5900, - EmitterId_VU0micro = EmitterId_R5900, - EmitterId_VU1micro = EmitterId_R5900, - - // Cotton's new microVU, which is iCore-free - EmitterId_microVU0, - EmitterId_microVU1, +////////////////////////////////////////////////////////////// +// Dev / Debug conditionals -- +// Consts for using if() statements instead of uglier #ifdef macros. +// Abbreviated macros for dev/debug only consoles and msgboxes. - // Air's eventual IopRec, which will also be iCore-free - EmitterId_R3000air, - - EmitterId_Count // must always be last! -}; +#ifdef PCSX2_DEVBUILD + +# define DevCon Console +# define DevMsg MsgBox + static const bool IsDevBuild = true; + +#else + +# define DevCon 0&&Console +# define DevMsg + static const bool IsDevBuild = false; + +#endif + +#ifdef _DEBUG + +# define DbgCon Console + static const bool IsDebugBuild = true; + +#else + +# define DbgCon 0&&Console + static const bool IsDebugBuild = false; + +#endif diff --git a/pcsx2/R3000A.cpp b/pcsx2/R3000A.cpp index 50931387a3..c821733549 100644 --- a/pcsx2/R3000A.cpp +++ b/pcsx2/R3000A.cpp @@ -224,7 +224,7 @@ static __forceinline void _psxTestInterrupts() } } -void psxBranchTest() +__releaseinline void psxBranchTest() { if( psxTestCycle( psxNextsCounter, psxNextCounter ) ) { diff --git a/pcsx2/R3000A.h b/pcsx2/R3000A.h index 7ab13663e8..49aee70828 100644 --- a/pcsx2/R3000A.h +++ b/pcsx2/R3000A.h @@ -126,14 +126,14 @@ extern s32 psxCycleEE; // tracks IOP's current sych status with the EE #ifndef _PC_ -#define _i32(x) (s32)x -#define _u32(x) (u32)x +#define _i32(x) (s32)x //R3000A +#define _u32(x) (u32)x //R3000A -#define _i16(x) (s16)x -#define _u16(x) (u16)x +#define _i16(x) (s16)x // Not used +#define _u16(x) (u16)x // Not used -#define _i8(x) (s8)x -#define _u8(x) (u8)x +#define _i8(x) (s8)x // Not used +#define _u8(x) (u8)x //R3000A - once /**** R3000A Instruction Macros ****/ #define _PC_ psxRegs.pc // The next PC to be executed @@ -200,7 +200,7 @@ extern R3000Acpu psxRec; void psxReset(); void psxShutdown(); void psxException(u32 code, u32 step); -void psxBranchTest(); +extern void psxBranchTest(); void psxExecuteBios(); void psxMemReset(); diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index b19d06dd0b..bb9234e87d 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -35,8 +35,6 @@ #include "SPR.h" #include "Sif.h" -#include "Paths.h" - #include "R5900Exceptions.h" using namespace R5900; // for R5900 disasm tools @@ -82,11 +80,11 @@ void cpuReset() g_nextBranchCycle = cpuRegs.cycle + 4; EEsCycle = 0; EEoCycle = cpuRegs.cycle; - eeWaitCycles = CHECK_WAITCYCLE_HACK ? 3072 : 768; + eeWaitCycles = Config.Hacks.WaitCycleExt ? 3072 : 768; // Cyclerate hacks effectively speed up the rate of event tests, so we can safely boost // the WaitCycles value here for x2 and x3 modes: - if( CHECK_EE_CYCLERATE > 1 ) + if( Config.Hacks.EECycleRate > 1 ) eeWaitCycles += 1024; hwReset(); @@ -106,7 +104,7 @@ void cpuShutdown() disR5900FreeSyms(); } -__releaseinline void __fastcall cpuException(u32 code, u32 bd) +__releaseinline void cpuException(u32 code, u32 bd) { cpuRegs.branch = 0; // Tells the interpreter that an exception occurred during a branch. bool errLevel2, checkStatus; @@ -244,7 +242,7 @@ void cpuTestMissingHwInts() { } // sets a branch test to occur some time from an arbitrary starting point. -__forceinline int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta ) +__forceinline void cpuSetNextBranch( u32 startCycle, s32 delta ) { // typecast the conditional to signed so that things don't blow up // if startCycle is greater than our next branch cycle. @@ -252,20 +250,18 @@ __forceinline int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta ) if( (int)(g_nextBranchCycle - startCycle) > delta ) { g_nextBranchCycle = startCycle + delta; - return 1; } - return 0; } // sets a branch to occur some time from the current cycle -__forceinline int __fastcall cpuSetNextBranchDelta( s32 delta ) +__forceinline void cpuSetNextBranchDelta( s32 delta ) { - return cpuSetNextBranch( cpuRegs.cycle, delta ); + cpuSetNextBranch( cpuRegs.cycle, delta ); } // tests the cpu cycle agaisnt the given start and delta values. // Returns true if the delta time has passed. -__forceinline int __fastcall cpuTestCycle( u32 startCycle, s32 delta ) +__forceinline int cpuTestCycle( u32 startCycle, s32 delta ) { // typecast the conditional to signed so that things don't explode // if the startCycle is ahead of our current cpu cycle. @@ -279,7 +275,7 @@ __forceinline void cpuSetBranch() g_nextBranchCycle = cpuRegs.cycle; } -void cpuClearInt( uint i ) +__forceinline void cpuClearInt( uint i ) { jASSUME( i < 32 ); cpuRegs.interrupt &= ~(1 << i); diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index b2dd4db46f..7dedb6c329 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -121,16 +121,16 @@ union CP0regs { }; struct cpuRegisters { - GPRregs GPR; // GPR regs + GPRregs GPR; // GPR regs // NOTE: don't change order since recompiler uses it GPR_reg HI; GPR_reg LO; // hi & log 128bit wide CP0regs CP0; // is COP0 32bit? u32 sa; // shift amount (32bit), needs to be 16 byte aligned u32 IsDelaySlot; // set true when the current instruction is a delay slot. - u32 pc; // Program counter, when changing offset in struct, check iR5900-X.S to make sure offset is correct - u32 code; // current instruction - PERFregs PERF; + u32 pc; // Program counter, when changing offset in struct, check iR5900-X.S to make sure offset is correct + u32 code; // current instruction + PERFregs PERF; u32 eCycle[32]; u32 sCycle[32]; // for internal counters u32 cycle; // calculate cpucycles.. @@ -180,7 +180,7 @@ struct tlbs #ifndef _PC_ -#define _i64(x) (s64)x +/*#define _i64(x) (s64)x #define _u64(x) (u64)x #define _i32(x) (s32)x @@ -190,12 +190,12 @@ struct tlbs #define _u16(x) (u16)x #define _i8(x) (s8)x -#define _u8(x) (u8)x +#define _u8(x) (u8)x*/ //////////////////////////////////////////////////////////////////// // R5900 Instruction Macros -#define _PC_ cpuRegs.pc // The next PC to be executed +#define _PC_ cpuRegs.pc // The next PC to be executed - only used in this header and R3000A.h #define _Funct_ ((cpuRegs.code ) & 0x3F) // The funct part of the instruction register #define _Rd_ ((cpuRegs.code >> 11) & 0x1F) // The rd part of the instruction register @@ -257,14 +257,14 @@ extern void cpuInit(); extern void cpuReset(); // can throw Exception::FileNotFound. extern void cpuShutdown(); extern void cpuExecuteBios(); -extern void __fastcall cpuException(u32 code, u32 bd); +extern void cpuException(u32 code, u32 bd); extern void cpuTlbMissR(u32 addr, u32 bd); extern void cpuTlbMissW(u32 addr, u32 bd); extern void cpuTestHwInts(); -extern int __fastcall cpuSetNextBranch( u32 startCycle, s32 delta ); -extern int __fastcall cpuSetNextBranchDelta( s32 delta ); -extern int __fastcall cpuTestCycle( u32 startCycle, s32 delta ); +extern void cpuSetNextBranch( u32 startCycle, s32 delta ); +extern void cpuSetNextBranchDelta( s32 delta ); +extern int cpuTestCycle( u32 startCycle, s32 delta ); extern void cpuSetBranch(); extern bool _cpuBranchTest_Shared(); // for internal use by the Dynarecs and Ints inside R5900: diff --git a/pcsx2/R5900Exceptions.h b/pcsx2/R5900Exceptions.h index 9a77225f6c..bcb10ae20c 100644 --- a/pcsx2/R5900Exceptions.h +++ b/pcsx2/R5900Exceptions.h @@ -23,10 +23,13 @@ namespace R5900Exception { using Exception::Ps2Generic; - ////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////// // Abstract base class for R5900 exceptions; contains the cpuRegs instance at the // time the exception is raised. // + // Translation note: EE Emulation exceptions are untranslated only. There's really no + // point in providing translations for this hardcore mess. :) + // class BaseExcept : public Ps2Generic { public: @@ -35,8 +38,8 @@ namespace R5900Exception public: virtual ~BaseExcept() throw()=0; - explicit BaseExcept( const std::string& msg ) : - Exception::Ps2Generic( "(EE) " + msg ), + explicit BaseExcept( const wxString& msg ) : + Exception::Ps2Generic( wxT("(EE) ") + msg ), cpuState( cpuRegs ) { } @@ -57,7 +60,7 @@ namespace R5900Exception virtual ~AddressError() throw() {} explicit AddressError( u32 ps2addr, bool onWrite ) : - BaseExcept( fmt_string( "Address error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + BaseExcept( wxsFormat( wxT("Address error, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ), OnWrite( onWrite ), Address( ps2addr ) {} @@ -75,7 +78,7 @@ namespace R5900Exception virtual ~TLBMiss() throw() {} explicit TLBMiss( u32 ps2addr, bool onWrite ) : - BaseExcept( fmt_string( "Tlb Miss, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + BaseExcept( wxsFormat( wxT("Tlb Miss, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ), OnWrite( onWrite ), Address( ps2addr ) {} @@ -94,7 +97,7 @@ namespace R5900Exception // explicit BusError( u32 ps2addr, bool onWrite ) : - BaseExcept( fmt_string( "Bus Error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + BaseExcept( wxsFormat( wxT("Bus Error, addr=0x%x [%s]"), ps2addr, onWrite ? wxT("store") : wxT("load") ) ), OnWrite( onWrite ), Address( ps2addr ) {} @@ -108,7 +111,7 @@ namespace R5900Exception virtual ~SystemCall() throw() {} explicit SystemCall() : - BaseExcept( "SystemCall [SYSCALL]" ) + BaseExcept( wxT("SystemCall [SYSCALL]") ) {} }; @@ -124,14 +127,14 @@ namespace R5900Exception // Generates a trap for immediate-style Trap opcodes explicit Trap() : - BaseExcept( "Trap" ), + BaseExcept( wxT("Trap") ), TrapCode( 0 ) {} // Generates a trap for register-style Trap instructions, which contain an // error code in the opcode explicit Trap( u16 trapcode ) : - BaseExcept( "Trap" ), + BaseExcept( wxT("Trap") ), TrapCode( trapcode ) {} }; @@ -144,7 +147,7 @@ namespace R5900Exception virtual ~Break() throw() {} explicit Break() : - BaseExcept( "Break Instruction" ) + BaseExcept( wxT("Break Instruction") ) {} }; @@ -156,7 +159,7 @@ namespace R5900Exception virtual ~Overflow() throw() {} explicit Overflow() : - BaseExcept( "Overflow" ) + BaseExcept( wxT("Overflow") ) {} }; @@ -168,7 +171,7 @@ namespace R5900Exception virtual ~DebugBreakpoint() throw() {} explicit DebugBreakpoint() : - BaseExcept( "Debug Breakpoint" ) + BaseExcept( wxT("Debug Breakpoint") ) {} }; } diff --git a/pcsx2/R5900OpcodeTables.cpp b/pcsx2/R5900OpcodeTables.cpp index 4c52c052d6..69077098bb 100644 --- a/pcsx2/R5900OpcodeTables.cpp +++ b/pcsx2/R5900OpcodeTables.cpp @@ -106,13 +106,10 @@ namespace R5900 static const int MMI_Div = 22*8; static const int MMI_Default = 14; - static const int FPU_Mult = 12; + static const int FPU_Mult = 4*8; - static const int Store = 28; - static const int Load = 22; - - static const int StoreFast = 14; - static const int LoadFast = 12; + static const int Store = 8; + static const int Load = 8; } using namespace Cycles; @@ -263,28 +260,28 @@ namespace R5900 MakeOpcode( LB, Load ); MakeOpcode( LH, Load ); MakeOpcode( LWL, Load ); - MakeOpcode( LW, LoadFast ); + MakeOpcode( LW, Load ); MakeOpcode( LBU, Load ); MakeOpcode( LHU, Load ); MakeOpcode( LWR, Load ); MakeOpcode( LWU, Load ); MakeOpcode( LWC1, Load ); MakeOpcode( LQC2, Load ); - MakeOpcode( LD, LoadFast ); + MakeOpcode( LD, Load ); // Stores! MakeOpcode( SQ, Store ); - MakeOpcode( SB, Store );//slow - MakeOpcode( SH, Store );//slow + MakeOpcode( SB, Store ); + MakeOpcode( SH, Store ); MakeOpcode( SWL, Store ); - MakeOpcode( SW, StoreFast ); + MakeOpcode( SW, Store ); MakeOpcode( SDL, Store ); MakeOpcode( SDR, Store ); MakeOpcode( SWR, Store ); MakeOpcode( SWC1, Store ); MakeOpcode( SQC2, Store ); - MakeOpcode( SD, StoreFast ); + MakeOpcode( SD, Store ); // Multimedia Instructions! @@ -435,9 +432,9 @@ namespace R5900 MakeOpcode1( MIN_S, CopDefault ); MakeOpcode1( MUL_S, FPU_Mult ); - MakeOpcode1( DIV_S, 3*8 ); - MakeOpcode1( SQRT_S, 3*8 ); - MakeOpcode1( RSQRT_S, 4*8 ); + MakeOpcode1( DIV_S, 6*8 ); + MakeOpcode1( SQRT_S, 6*8 ); + MakeOpcode1( RSQRT_S, 8*8 ); MakeOpcode1( MULA_S, FPU_Mult ); MakeOpcode1( MADD_S, FPU_Mult ); MakeOpcode1( MSUB_S, FPU_Mult ); diff --git a/pcsx2/R5900OpcodeTables.h b/pcsx2/R5900OpcodeTables.h index 8f4d956848..cd2a5e499c 100644 --- a/pcsx2/R5900OpcodeTables.h +++ b/pcsx2/R5900OpcodeTables.h @@ -18,8 +18,6 @@ #ifndef _R5900_OPCODETABLES_H #define _R5900_OPCODETABLES_H -#include - #include "PS2Etypes.h" // TODO : Move these into the OpcodeTables namespace diff --git a/pcsx2/RecoverySystem.cpp b/pcsx2/RecoverySystem.cpp index 67e5817d61..7db75ebc05 100644 --- a/pcsx2/RecoverySystem.cpp +++ b/pcsx2/RecoverySystem.cpp @@ -120,10 +120,10 @@ namespace StateRecovery { // have likely been cleared out. So save from the Recovery buffer instead of // doing a "standard" save: - gzFile fileptr = gzopen( file.c_str(), "wb" ); + gzFile fileptr = gzopen( file.ToAscii().data(), "wb" ); if( fileptr == NULL ) { - Msgbox::Alert( "File permissions error while trying to save to file:\n\t%ts", params &file ); + Msgbox::Alert( wxsFormat( _("Error while trying to save to file: %s"), file.c_str() ) ); return; } gzwrite( fileptr, &g_SaveVersion, sizeof( u32 ) ); @@ -138,7 +138,7 @@ namespace StateRecovery { { if( !g_EmulationInProgress ) { - Msgbox::Alert( "You need to start a game first before you can save it's state." ); + Msgbox::Alert( _("No emulation state to save") ); // translate: You need to start a game first before you can save it's state return; } @@ -187,9 +187,10 @@ namespace StateRecovery { } catch( Exception::RuntimeError& ex ) { - Msgbox::Alert( - "Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n" - "Error: %s", params ex.cMessage() ); + Msgbox::Alert( wxsFormat( // fixme: this error needs proper translation stuffs. + wxT("Pcsx2 gamestate recovery failed. Some options may have been reverted to protect your game's state.\n") + wxT("Error: %s"), ex.DisplayMessage().c_str() ) + ); safe_delete( g_RecoveryState ); } } diff --git a/pcsx2/SPR.cpp b/pcsx2/SPR.cpp index bb47768ba8..5c5291fad0 100644 --- a/pcsx2/SPR.cpp +++ b/pcsx2/SPR.cpp @@ -23,10 +23,6 @@ #include "iR5900.h" #include "VUmicro.h" -#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) -#define spr1 ((DMACh*)&PS2MEM_HW[0xD400]) -#define gif ((DMACh*)&PS2MEM_HW[0xA000]) - extern void mfifoGIFtransfer(int); /* Both of these should be bools. Again, next savestate break. --arcum42 */ @@ -66,12 +62,15 @@ int _SPR0chain() if ((psHu32(DMAC_CTRL) & 0xC) >= 0x8) // 0x8 VIF1 MFIFO, 0xC GIF MFIFO { - if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("SPR MFIFO Write outside MFIFO area"); + if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) + Console::WriteLn("SPR MFIFO Write outside MFIFO area"); + else + mfifotransferred += spr0->qwc; hwMFIFOWrite(spr0->madr, (u8*)&PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4); spr0->madr += spr0->qwc << 4; spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); - mfifotransferred += spr0->qwc; + } else { @@ -88,9 +87,11 @@ int _SPR0chain() return (spr0->qwc) * BIAS; // bus is 1/2 the ee speed } -#define SPR0chain() \ - cycles += _SPR0chain(); \ +__forceinline void SPR0chain() +{ + _SPR0chain(); spr0->qwc = 0; +} void _SPR0interleave() @@ -98,7 +99,6 @@ void _SPR0interleave() int qwc = spr0->qwc; int sqwc = psHu32(DMAC_SQWC) & 0xff; int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; - //int cycles = 0; u32 *pMem; if (tqwc == 0) tqwc = qwc; @@ -123,9 +123,8 @@ void _SPR0interleave() TestClearVUs(spr0->madr, spr0->qwc << 2); memcpy_fast((u8*)pMem, &PS2MEM_SCRATCH[spr0->sadr & 0x3fff], spr0->qwc << 4); } - //cycles += tqwc * BIAS; spr0->sadr += spr0->qwc * 16; - spr0->madr += (sqwc + spr0->qwc) * 16; //qwc-= sqwc; + spr0->madr += (sqwc + spr0->qwc) * 16; } spr0->qwc = 0; @@ -142,15 +141,12 @@ static __forceinline void _dmaSPR0() // Transfer Dn_QWC from SPR to Dn_MADR if ((spr0->chcr & 0xc) == 0x0) // Normal Mode { - int cycles = 0; SPR0chain(); spr0finished = 1; - return; } else if ((spr0->chcr & 0xc) == 0x4) { - int cycles = 0; u32 *ptag; int id; bool done = FALSE; @@ -166,7 +162,6 @@ static __forceinline void _dmaSPR0() spr0->sadr += 16; // Transfer dma tag if tte is set - spr0->chcr = (spr0->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag @@ -200,7 +195,6 @@ static __forceinline void _dmaSPR0() { //Console::WriteLn("SPR0 TIE"); done = TRUE; - spr0->qwc = 0; } spr0finished = (done) ? 1 : 0; @@ -208,9 +202,7 @@ static __forceinline void _dmaSPR0() if (!done) { ptag = (u32*) & PS2MEM_SCRATCH[spr0->sadr & 0x3fff]; //Set memory pointer to SADR - //spr0->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag - CPU_INT(8, ((u16)ptag[0]) / BIAS); //spr0->qwc / BIAS); - spr0->qwc = 0; + CPU_INT(8, ((u16)ptag[0]) / BIAS); // the lower 16bits of the tag / BIAS); return; } SPR_LOG("spr0 dmaChain complete %8.8x_%8.8x size=%d, id=%d, addr=%lx spr=%lx", @@ -226,23 +218,27 @@ void SPRFROMinterrupt() { _dmaSPR0(); - if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) // GIF MFIFO + if(mfifotransferred != 0) { - if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area"); - spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); - //Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr); - mfifoGIFtransfer(mfifotransferred); - mfifotransferred = 0; - } - else - if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO + if ((psHu32(DMAC_CTRL) & 0xC) == 0xC) // GIF MFIFO + { + if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("GIF MFIFO Write outside MFIFO area"); + spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); + //Console::WriteLn("mfifoGIFtransfer %x madr %x, tadr %x", params gif->chcr, gif->madr, gif->tadr); + mfifoGIFtransfer(mfifotransferred); + mfifotransferred = 0; + return; + } + else if ((psHu32(DMAC_CTRL) & 0xC) == 0x8) // VIF1 MFIFO { if ((spr0->madr & ~psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("VIF MFIFO Write outside MFIFO area"); spr0->madr = psHu32(DMAC_RBOR) + (spr0->madr & psHu32(DMAC_RBSR)); //Console::WriteLn("mfifoVIF1transfer %x madr %x, tadr %x", params vif1ch->chcr, vif1ch->madr, vif1ch->tadr); mfifoVIF1transfer(mfifotransferred); mfifotransferred = 0; + return; } + } if (spr0finished == 0) return; spr0->chcr &= ~0x100; hwDmacIrq(8); @@ -289,9 +285,11 @@ int _SPR1chain() return (spr1->qwc) * BIAS; } -#define SPR1chain() \ - cycles += _SPR1chain(); \ - spr1->qwc = 0; +__forceinline void SPR1chain() +{ + _SPR1chain(); + spr1->qwc = 0; +} void _SPR1interleave() @@ -299,7 +297,6 @@ void _SPR1interleave() int qwc = spr1->qwc; int sqwc = psHu32(DMAC_SQWC) & 0xff; int tqwc = (psHu32(DMAC_SQWC) >> 16) & 0xff; - //int cycles = 0; u32 *pMem; if (tqwc == 0) tqwc = qwc; @@ -313,8 +310,7 @@ void _SPR1interleave() pMem = (u32*)dmaGetAddr(spr1->madr); memcpy_fast(&PS2MEM_SCRATCH[spr1->sadr & 0x3fff], (u8*)pMem, spr1->qwc << 4); spr1->sadr += spr1->qwc * 16; - //cycles += spr1->qwc * BIAS; - spr1->madr += (sqwc + spr1->qwc) * 16; //qwc-= sqwc; + spr1->madr += (sqwc + spr1->qwc) * 16; } spr1->qwc = 0; @@ -325,7 +321,7 @@ void _dmaSPR1() // toSPR work function { if ((spr1->chcr & 0xc) == 0) // Normal Mode { - int cycles = 0; + //int cycles = 0; // Transfer Dn_QWC from Dn_MADR to SPR1 SPR1chain(); spr1finished = 1; @@ -333,7 +329,6 @@ void _dmaSPR1() // toSPR work function } else if ((spr1->chcr & 0xc) == 0x4) { - int cycles = 0; u32 *ptag; int id; bool done = FALSE; @@ -360,7 +355,7 @@ void _dmaSPR1() // toSPR work function spr1->chcr = (spr1->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); //Transfer upper part of tag to CHCR bits 31-15 id = (ptag[0] >> 28) & 0x7; //ID for DmaChain copied from bit 28 of the tag - spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag + spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag until SPR1chain is called in a few lines. spr1->madr = ptag[1]; //MADR = ADDR field // Transfer dma tag if tte is set @@ -381,7 +376,6 @@ void _dmaSPR1() // toSPR work function SPR_LOG("dmaIrq Set"); //Console::WriteLn("SPR1 TIE"); - spr1->qwc = 0; done = TRUE; } @@ -389,9 +383,7 @@ void _dmaSPR1() // toSPR work function if (!done) { ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR - //spr1->qwc = (u16)ptag[0]; //QWC set to lower 16bits of the tag - CPU_INT(9, (((u16)ptag[0]) / BIAS));// spr1->qwc / BIAS); - spr1->qwc = 0; + CPU_INT(9, (((u16)ptag[0]) / BIAS));// the lower 16 bits of the tag / BIAS); } } else // Interleave Mode @@ -408,7 +400,7 @@ void dmaSPR1() // toSPR spr1->chcr, spr1->madr, spr1->qwc, spr1->tadr, spr1->sadr); - if ((spr1->chcr & 0xc) == 0x4 && spr1->qwc == 0) + if (((spr1->chcr & 0xc) == 0x4) && (spr1->qwc == 0)) { u32 *ptag; ptag = (u32*)dmaGetAddr(spr1->tadr); //Set memory pointer to TADR diff --git a/pcsx2/SafeArray.h b/pcsx2/SafeArray.h index 5d1da5d46a..5ecabaa337 100644 --- a/pcsx2/SafeArray.h +++ b/pcsx2/SafeArray.h @@ -76,25 +76,25 @@ public: static const int DefaultChunkSize = 0x1000 * sizeof(T); public: - const std::string Name; // user-assigned block name + const wxString Name; // user-assigned block name int ChunkSize; protected: T* m_ptr; int m_size; // size of the allocation of memory - const static std::string m_str_Unnamed; + const static wxString m_str_Unnamed; protected: // Internal constructor for use by derived classes. This allows a derived class to // use its own memory allocation (with an aligned memory, for example). // Throws: // Exception::OutOfMemory if the allocated_mem pointer is NULL. - explicit SafeArray( const std::string& name, T* allocated_mem, int initSize ) : - Name( name ) - , ChunkSize( DefaultChunkSize ) - , m_ptr( allocated_mem ) - , m_size( initSize ) + explicit SafeArray( const wxString& name, T* allocated_mem, int initSize ) : + Name( name ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( allocated_mem ) + , m_size( initSize ) { if( m_ptr == NULL ) throw Exception::OutOfMemory(); @@ -111,19 +111,37 @@ public: safe_free( m_ptr ); } - explicit SafeArray( const std::string& name="Unnamed" ) : - Name( name ) - , ChunkSize( DefaultChunkSize ) - , m_ptr( NULL ) - , m_size( 0 ) + explicit SafeArray( const wxString& name=wxT("Unnamed") ) : + Name( name ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( NULL ) + , m_size( 0 ) { } - explicit SafeArray( int initialSize, const std::string& name="Unnamed" ) : - Name( name ) - , ChunkSize( DefaultChunkSize ) - , m_ptr( (T*)malloc( initialSize * sizeof(T) ) ) - , m_size( initialSize ) + explicit SafeArray( const char* name ) : + Name( wxString::FromAscii(name) ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( NULL ) + , m_size( 0 ) + { + } + + explicit SafeArray( int initialSize, const wxString& name=wxT("Unnamed") ) : + Name( name ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( (T*)malloc( initialSize * sizeof(T) ) ) + , m_size( initialSize ) + { + if( m_ptr == NULL ) + throw Exception::OutOfMemory(); + } + + explicit SafeArray( int initialSize, const char* name ) : + Name( wxString::FromAscii(name) ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( (T*)malloc( initialSize * sizeof(T) ) ) + , m_size( initialSize ) { if( m_ptr == NULL ) throw Exception::OutOfMemory(); @@ -145,9 +163,11 @@ public: if( m_ptr == NULL ) { throw Exception::OutOfMemory( - "Out-of-memory on block re-allocation. " - "Old size: " + to_string( m_size ) + " bytes, " - "New size: " + to_string( newalloc ) + " bytes" + wxsFormat( // english (for diagnostic) + wxT("Out-of-memory on SafeArray block re-allocation.\n") + wxT("Old size: %d bytes, New size: %d bytes."), + m_size, newalloc + ) ); } m_size = newalloc; @@ -181,15 +201,8 @@ protected: T* _getPtr( uint i ) const { #ifdef PCSX2_DEVBUILD - if( i >= (uint)m_size ) - { - assert( 0 ); // makes debugging easier sometimes. :) - throw Exception::IndexBoundsFault( - "Index out of bounds on SafeArray: " + Name + - " (index=" + to_string(i) + - ", size=" + to_string(m_size) + ")" - ); - } + if( IsDevBuild && i >= (uint)m_size ) + throw Exception::IndexBoundsFault( Name, i, m_size ); #endif return &m_ptr[i]; } @@ -206,7 +219,7 @@ public: static const int DefaultChunkSize = 0x80 * sizeof(T); public: - const std::string Name; // user-assigned block name + const wxString Name; // user-assigned block name int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time. protected: @@ -214,7 +227,7 @@ protected: int m_allocsize; // size of the allocation of memory uint m_length; // length of the array (active items, not buffer allocation) - const static std::string m_str_Unnamed; + const static wxString m_str_Unnamed; protected: virtual T* _virtual_realloc( int newsize ) @@ -224,17 +237,8 @@ protected: void _boundsCheck( uint i ) const { -#ifdef PCSX2_DEVBUILD - if( i >= (uint)m_length ) - { - assert( 0 ); // makes debugging easier sometimes. :) - throw Exception::IndexBoundsFault( - "Index out of bounds on SafeArray: " + Name + - " (index=" + to_string(i) + - ", length=" + to_string(m_length) + ")" - ); - } -#endif + if( IsDevBuild && i >= (uint)m_length ) + throw Exception::IndexBoundsFault( Name, i, m_length ); } public: @@ -242,7 +246,7 @@ public: { } - explicit SafeList( const std::string& name="Unnamed" ) : + explicit SafeList( const wxString& name=wxT("Unnamed") ) : Name( name ) , ChunkSize( DefaultChunkSize ) , m_ptr( NULL ) @@ -251,7 +255,16 @@ public: { } - explicit SafeList( int initialSize, const std::string& name="Unnamed" ) : + explicit SafeList( const char* name ) : + Name( wxString::FromAscii(name) ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( NULL ) + , m_allocsize( 0 ) + , m_length( 0 ) + { + } + + explicit SafeList( int initialSize, const wxString& name=wxT("Unnamed") ) : Name( name ) , ChunkSize( DefaultChunkSize ) , m_ptr( (T*)malloc( initialSize * sizeof(T) ) ) @@ -262,6 +275,17 @@ public: throw Exception::OutOfMemory(); } + explicit SafeList( int initialSize, const char* name ) : + Name( wxString::FromAscii(name) ) + , ChunkSize( DefaultChunkSize ) + , m_ptr( (T*)malloc( initialSize * sizeof(T) ) ) + , m_allocsize( initialSize ) + , m_length( 0 ) + { + if( m_ptr == NULL ) + throw Exception::OutOfMemory(); + } + // Returns the size of the list, as according to the array type. This includes // mapped items only. The actual size of the allocation may differ. int GetLength() const { return m_length; } @@ -281,9 +305,12 @@ public: if( m_ptr == NULL ) { throw Exception::OutOfMemory( - "Out-of-memory on list re-allocation. " - "Old size: " + to_string( m_allocsize ) + " bytes, " - "New size: " + to_string( newalloc ) + " bytes" + // English Diagonstic message: + wxsFormat( + wxT("Out-of-memory on SafeList block re-allocation.\n") + wxT("Old size: %d bytes, New size: %d bytes"), + m_allocsize, newalloc + ) ); } m_allocsize = newalloc; @@ -350,12 +377,12 @@ protected: // Appends "(align: xx)" to the name of the allocation in devel builds. // Maybe useful,maybe not... no harm in attaching it. :D - string _getName( const string& src ) + wxString _getName( const wxString& src ) { -#ifdef PCSX2_DEVBUILD - return src + "(align:" + to_string(Alignment) + ")"; -#endif - return src; + if( IsDevBuild ) + return src + wxsFormat( wxT("(align: %d)"), Alignment ); + else + return src; } public: @@ -365,12 +392,17 @@ public: // mptr is set to null, so the parent class's destructor won't re-free it. } - explicit SafeAlignedArray( const std::string& name="Unnamed" ) : + explicit SafeAlignedArray( const wxString& name=wxT("Unnamed") ) : SafeArray::SafeArray( name ) { } - explicit SafeAlignedArray( int initialSize, const std::string& name="Unnamed" ) : + explicit SafeAlignedArray( const char* name ) : + SafeArray::SafeArray( name ) + { + } + + explicit SafeAlignedArray( int initialSize, const wxString& name=wxT("Unnamed") ) : SafeArray::SafeArray( _getName(name), (T*)_aligned_malloc( initialSize * sizeof(T), Alignment ), @@ -379,6 +411,15 @@ public: { } + explicit SafeAlignedArray( int initialSize, const char* name ) : + SafeArray::SafeArray( + _getName(wxString::FromAscii(name)), + (T*)_aligned_malloc( initialSize * sizeof(T), Alignment ), + initialSize + ) + { + } + virtual SafeAlignedArray* Clone() const { SafeAlignedArray* retval = new SafeAlignedArray( this->m_size ); @@ -387,4 +428,9 @@ public: } }; + +// For lack of a better place for now (they depend on SafeList so they can't go in StringUtil) +extern void SplitString( SafeList& dest, const wxString& src, const wxString& delims ); +extern void JoinString( wxString& dest, const SafeList& src, const wxString& separator ); + #endif diff --git a/pcsx2/SamplProf.h b/pcsx2/SamplProf.h index 465318ac26..566da2caa0 100644 --- a/pcsx2/SamplProf.h +++ b/pcsx2/SamplProf.h @@ -6,7 +6,7 @@ // The profiler does not have a Linux version yet. // So for now we turn it into duds for non-Win32 platforms. -#ifdef _WIN32 +#ifdef WIN32 void ProfilerInit(); void ProfilerTerm(); diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index d5e3fab511..103a751c09 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -50,16 +50,15 @@ static void PostLoadPrep() wxString SaveState::GetFilename( int slot ) { - wxString arrgh; - arrgh.Printf( "%8.8X.%3.3d", ElfCRC, slot ); - return Path::Combine( SSTATES_DIR, arrgh ); + return (g_Conf.Folders.Savestates + + wxsFormat( wxT("%8.8X.%3.3d"), ElfCRC, slot )).GetFullPath(); } SaveState::SaveState( const char* msg, const wxString& destination ) : m_version( g_SaveVersion ) , m_tagspace( 128 ) { - Console::WriteLn( "%s %hs", params msg, &destination ); + Console::WriteLn( "%s %s", params msg, destination.ToAscii().data() ); } s32 CALLBACK gsSafeFreeze( int mode, freezeData *data ) @@ -92,7 +91,10 @@ void SaveState::FreezeTag( const char* src ) if( strcmp( m_tagspace.GetPtr(), src ) != 0 ) { assert( 0 ); - throw Exception::BadSavedState( string( "Tag: " )+src ); + throw Exception::BadSavedState( + // Untranslated diagnostic msg (use default msg for translation) + wxT("Savestate data corruption detected while reading tag: ") + wxString::FromAscii(src) + ); } } @@ -105,10 +107,10 @@ void SaveState::FreezeAll() // doesn't match the bios currently being used (chances are it'll still // work fine, but some games are very picky). - char descout[128], descin[128]; - memzero_obj( descout ); - IsBIOS( Config.Bios, descout ); - memcpy_fast( descin, descout, 128 ); + char descin[128]; + wxString descout; + IsBIOS( g_Conf.Files.Bios(), descout ); + memcpy_fast( descin, descout.ToAscii().data(), 128 ); Freeze( descin ); if( memcmp( descin, descout, 128 ) != 0 ) @@ -117,7 +119,7 @@ void SaveState::FreezeAll() "\n\tWarning: BIOS Version Mismatch, savestate may be unstable!\n" "\t\tCurrent BIOS: %s\n" "\t\tSavestate BIOS: %s\n", - params descout, descin + params descout.ToAscii().data(), descin ); } @@ -205,7 +207,7 @@ gzBaseStateInfo::~gzBaseStateInfo() gzSavingState::gzSavingState( const wxString& filename ) : gzBaseStateInfo( "Saving state to: ", filename ) { - m_file = gzopen(filename.c_str(), "wb"); + m_file = gzopen(filename.ToAscii().data(), "wb"); if( m_file == NULL ) throw Exception::FileNotFound(); @@ -217,7 +219,7 @@ gzSavingState::gzSavingState( const wxString& filename ) : gzLoadingState::gzLoadingState( const wxString& filename ) : gzBaseStateInfo( "Loading state from: ", filename ) { - m_file = gzopen(filename.c_str(), "rb"); + m_file = gzopen(filename.ToAscii().data(), "rb"); if( m_file == NULL ) throw Exception::FileNotFound(); @@ -299,9 +301,9 @@ void gzLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(int // uncompressed to/from memory state saves implementation memBaseStateInfo::memBaseStateInfo( SafeArray& memblock, const char* msg ) : - SaveState( msg, "Memory" ) -, m_memory( memblock ) -, m_idx( 0 ) + SaveState( msg, wxT("Memory") ) +, m_memory( memblock ) +, m_idx( 0 ) { // Always clear the MTGS thread state. mtgsWaitGS(); @@ -376,7 +378,7 @@ void memLoadingState::FreezePlugin( const char* name, s32 (CALLBACK *freezer)(in if( ( fP.size + m_idx ) > m_memory.GetSizeInBytes() ) { assert(0); - throw Exception::BadSavedState( "memory" ); + throw Exception::BadSavedState( wxT("memory") ); } fP.data = ((s8*)m_memory.GetPtr()) + m_idx; diff --git a/pcsx2/SaveState.h b/pcsx2/SaveState.h index a4c4d1cdb3..9a4e18e3bb 100644 --- a/pcsx2/SaveState.h +++ b/pcsx2/SaveState.h @@ -217,4 +217,5 @@ namespace StateRecovery extern void Clear(); } -#endif \ No newline at end of file +#endif + diff --git a/pcsx2/Saveslots.cpp b/pcsx2/Saveslots.cpp index 8d17c58022..d018489ac7 100644 --- a/pcsx2/Saveslots.cpp +++ b/pcsx2/Saveslots.cpp @@ -34,7 +34,7 @@ bool States_isSlotUsed(int num) if (ElfCRC == 0) return false; else - return Path::isFile(SaveState::GetFilename( num )); + return wxFileExists( SaveState::GetFilename( num ) ); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -62,11 +62,11 @@ void States_Load( const wxString& file ) try { _loadStateOrExcept( file ); - HostGui::Notice( fmt_string( "*PCSX2*: Loaded State %s", file.c_str() ) ); + HostGui::Notice( wxsFormat( _("Loaded State %s"), file.c_str() ) ); } catch( Exception::StateLoadError_Recoverable& ex) { - Console::Notice( "Could not load savestate file: %hs.\n\n%s", params &file, ex.cMessage() ); + Console::Notice( ex.LogMessage() ); // At this point the cpu hasn't been reset, so we can return // control to the user safely... (that's why we use a console notice instead of a popup) @@ -76,16 +76,12 @@ void States_Load( const wxString& file ) catch( Exception::BaseException& ex ) { // The emulation state is ruined. Might as well give them a popup and start the gui. + // Translation Tip: Since the savestate load was incomplete, the emulator has been reset. - string message( fmt_string( - "Encountered an error while loading savestate from file: %s.\n", file.c_str() ) ); - - if( g_EmulationInProgress ) - message += "Since the savestate load was incomplete, the emulator must reset.\n"; - - message += "\nError: " + ex.Message(); - - Msgbox::Alert( message.c_str() ); + Msgbox::Alert( + wxsFormat( _("Error loading savestate from file: %s"), file.c_str() ) + + L"\n\n" + _("Error details:") + ex.DisplayMessage() + ); SysReset(); return; } @@ -94,9 +90,9 @@ void States_Load( const wxString& file ) void States_Load(int num) { - string file( SaveState::GetFilename( num ) ); + wxString file( SaveState::GetFilename( num ) ); - if( !Path::isFile( file ) ) + if( !Path::IsFile( file ) ) { Console::Notice( "Saveslot %d is empty.", params num ); return; @@ -105,11 +101,11 @@ void States_Load(int num) try { _loadStateOrExcept( file ); - HostGui::Notice( fmt_string( "*PCSX2*: Loaded State %d", num ) ); + HostGui::Notice( wxsFormat( _("Loaded State %d"), num ) ); } catch( Exception::StateLoadError_Recoverable& ex) { - Console::Notice( "Could not load savestate slot %d.\n\n%s", params num, ex.cMessage() ); + Console::Notice( wxsFormat( L"Could not load savestate slot %d.\n\n%s", num, ex.LogMessage() ) ); // At this point the cpu hasn't been reset, so we can return // control to the user safely... (that's why we use a console notice instead of a popup) @@ -119,16 +115,13 @@ void States_Load(int num) catch( Exception::BaseException& ex ) { // The emulation state is ruined. Might as well give them a popup and start the gui. + // Translation Tip: Since the savestate load was incomplete, the emulator has been reset. - string message( fmt_string( - "Encountered an error while loading savestate from slot %d.\n", num ) ); + Msgbox::Alert( + wxsFormat( _("Error loading savestate from slot %d"), file.c_str() ) + + L"\n\n" + _("Error details:") + ex.DisplayMessage() + ); - if( g_EmulationInProgress ) - message += "Since the savestate load was incomplete, the emulator has been reset.\n"; - - message += "\nError: " + ex.Message(); - - Msgbox::Alert( message.c_str() ); SysEndExecution(); return; } @@ -144,13 +137,23 @@ void States_Save( const wxString& file ) try { StateRecovery::SaveToFile( file ); - HostGui::Notice( fmt_string( "State saved to file: %s", file.c_str() ) ); + HostGui::Notice( wxsFormat( _("State saved to file: %s"), file.c_str() ) ); } catch( Exception::BaseException& ex ) { - Console::Error( (fmt_string( - "An error occurred while trying to save to file %s\n", file.c_str() ) + - "Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str() + // TODO: Implement a "pause the action and issue a popup" thing here. + // *OR* some kind of GS overlay... [for now we use the console] + + // Translation Tip: "Your emulation state has not been saved!" + + /*Msgbox::Alert( + wxsFormat( _("Error saving state to file: %s"), file.c_str() ) + + L"\n\n" + _("Error details:") + ex.DisplayMessage() + );*/ + + Console::Error( wxsFormat( + L"An error occurred while trying to save to file %s\n", file.c_str() ) + + L"Your emulation state has not been saved!\n\nError: " + ex.LogMessage() ); } @@ -163,14 +166,17 @@ void States_Save(int num) try { StateRecovery::SaveToSlot( num ); - HostGui::Notice( fmt_string( "State saved to slot %d", num ) ); + HostGui::Notice( wxsFormat( _("State saved to slot %d"), num ) ); } catch( Exception::BaseException& ex ) { - Console::Error( (fmt_string( - "An error occurred while trying to save to slot %d\n", num ) + - "Your emulation state has not been saved!\n\nError: " + ex.Message()).c_str() - ); + // TODO: Implement a "pause the action and issue a popup" thing here. + // *OR* some kind of GS overlay... [for now we use the console] + + Console::Error( wxsFormat( + L"An error occurred while trying to save to slot %d\n", num ) + + L"Your emulation state has not been saved!\n\nError: " + ex.LogMessage() + ); } HostGui::ResetMenuSlots(); } diff --git a/pcsx2/Sif.cpp b/pcsx2/Sif.cpp index 796be3f9c7..23576f767f 100644 --- a/pcsx2/Sif.cpp +++ b/pcsx2/Sif.cpp @@ -25,10 +25,6 @@ using namespace std; -#define sif0dma ((DMACh*)&PS2MEM_HW[0xc000]) -#define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) -#define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) - DMACh *sif0ch; DMACh *sif1ch; DMACh *sif2ch; @@ -206,7 +202,10 @@ __forceinline void SIF0Dma() //SIF_LOG(" EE SIF doing transfer %04Xqw to %08X", readSize, sif0dma->madr); SIF_LOG("----------- %lX of %lX", readSize << 2, size << 2); - _dmaGetAddr(sif0dma, ptag, sif0dma->madr, 5); + ptag = _dmaGetAddr(sif0dma, sif0dma->madr, 5); + if (ptag == NULL) return; + + //_dmaGetAddr(sif0dma, *ptag, sif0dma->madr, 5); SIF0read((u32*)ptag, readSize << 2); @@ -285,7 +284,12 @@ __forceinline void SIF1Dma() { // Process DMA tag at sif1dma->tadr done = FALSE; - _dmaGetAddr(sif1dma, ptag, sif1dma->tadr, 6); + ptag = _dmaGetAddr(sif1dma, sif1dma->tadr, 6); + if (ptag == NULL) return; + + //_dmaGetAddr(sif1dma, *ptag, sif1dma->tadr, 6); + + sif1dma->chcr = (sif1dma->chcr & 0xFFFF) | ((*ptag) & 0xFFFF0000); // Copy the tag sif1dma->qwc = (u16)ptag[0]; @@ -348,7 +352,10 @@ __forceinline void SIF1Dma() int qwTransfer = sif1dma->qwc; u32 *data; - _dmaGetAddr(sif1dma, data, sif1dma->madr, 6); + data = _dmaGetAddr(sif1dma, sif1dma->madr, 6); + if (data == NULL) return; + + //_dmaGetAddr(sif1dma, *data, sif1dma->madr, 6); if (qwTransfer > (FIFO_SIF1_W - sif1.fifoSize) / 4) // Copy part of sif1dma into FIFO qwTransfer = (FIFO_SIF1_W - sif1.fifoSize) / 4; diff --git a/pcsx2/Sio.cpp b/pcsx2/Sio.cpp index b40fdbccbd..52687d7698 100644 --- a/pcsx2/Sio.cpp +++ b/pcsx2/Sio.cpp @@ -152,7 +152,6 @@ void SIO_CommandWrite(u8 value,int way) { case 3: // No pad connected. sio.parp++; - sio.bufcount = 6; if (sio.parp == sio.bufcount) { sio.padst = 0; return; } SIO_INT(); return; @@ -451,16 +450,16 @@ void SIO_CommandWrite(u8 value,int way) { break; case 0x21: // Set pad slot. - sio.mtapst = 0x21; + sio.mtapst = value; sio.bufcount = 6; // No idea why this is 6, saved from old code. break; case 0x22: // Set memcard slot. - sio.mtapst = 0x22; + sio.mtapst = value; sio.bufcount = 6; // No idea why this is 6, saved from old code. break; } - // Commented out values are from original code. Break multitap in bios. + // Commented out values are from original code. They break multitap in bios. sio.buf[sio.bufcount-1]=0;//'+'; sio.buf[sio.bufcount]=0;//'Z'; return; @@ -508,7 +507,7 @@ void InitializeSIO(u8 value) sio.StatReg &= ~TX_EMPTY; // Now the Buffer is not empty sio.StatReg |= RX_RDY; // Transfer is Ready - sio.bufcount = 2; + sio.bufcount = 4; // Default size, when no pad connected. sio.parp = 0; sio.padst = 1; sio.packetsize = 1; @@ -517,7 +516,7 @@ void InitializeSIO(u8 value) switch (sio.CtrlReg&0x2002) { case 0x0002: - if (!PAD1setSlot(1, 1+sio.activePadSlot[0])) { + if (!PAD1setSlot(1, 1+sio.activePadSlot[0]) && sio.activePadSlot[0]) { // Pad is not present. Don't send poll, just return a bunch of 0's. sio2.packet.recvVal1 = 0x1D100; sio.padst = 3; @@ -527,7 +526,7 @@ void InitializeSIO(u8 value) } break; case 0x2002: - if (!PAD2setSlot(1, 1+sio.activePadSlot[1])) { + if (!PAD2setSlot(2, 1+sio.activePadSlot[1]) && sio.activePadSlot[1]) { // Pad is not present. Don't send poll, just return a bunch of 0's. sio2.packet.recvVal1 = 0x1D100; sio.padst = 3; @@ -554,6 +553,7 @@ void InitializeSIO(u8 value) int port = sio.GetMultitapPort(); if (!IsMtapPresent(port)) { + // If "unplug" multitap mid game, set active slots to 0. sio.activePadSlot[port] = 0; sio.activeMemcardSlot[port] = 0; } diff --git a/pcsx2/SourceLog.cpp b/pcsx2/SourceLog.cpp index 8173aa9d30..4e5c46b5c6 100644 --- a/pcsx2/SourceLog.cpp +++ b/pcsx2/SourceLog.cpp @@ -66,7 +66,7 @@ void __Log( const char* fmt, ... ) assert( length <= 2020 ); if( length > 2020 ) { - Msgbox::Alert("Source Log Stack Corruption Detected. Program execution may become unstable."); + Msgbox::Alert( _("Source log buffer overrun") ); // fixme: should throw an exception here once we have proper exception handling implemented. } @@ -97,7 +97,7 @@ static __forceinline void _vSourceLog( u16 protocol, u8 source, u32 cpuPc, u32 c assert( length <= 2020 ); if( length > 2020 ) { - Msgbox::Alert("Source Log Stack Corruption Detected. Program execution may become unstable."); + Msgbox::Alert( _("Source log buffer overrun") ); // fixme: should throw an exception here once we have proper exception handling implemented. } diff --git a/pcsx2/Stats.cpp b/pcsx2/Stats.cpp index 0f8fb593e8..8448a97d6c 100644 --- a/pcsx2/Stats.cpp +++ b/pcsx2/Stats.cpp @@ -23,8 +23,6 @@ #include "IopCommon.h" #include "Stats.h" -#include "Paths.h" - void statsOpen() { stats.vsyncCount = 0; stats.vsyncTime = time(NULL); diff --git a/pcsx2/StringUtils.h b/pcsx2/StringUtils.h index e6c306a4b3..0635b7499a 100644 --- a/pcsx2/StringUtils.h +++ b/pcsx2/StringUtils.h @@ -36,6 +36,7 @@ std::string to_string(const T& value) } ////////////////////////////////////////////////////////////////////////////////////////// +// Helpers for wxWidgets stuff! // extern wxString ToString( const wxPoint& src, const wxString& separator=wxT(",") ); extern wxString ToString( const wxSize& src, const wxString& separator=wxT(",") ); diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 8bb3ea92d0..a43cb6195d 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -37,12 +37,6 @@ SessionOverrideFlags g_Session = {false}; bool sysInitialized = false; -namespace Exception -{ - BaseException::~BaseException() throw() {} -} - - // I can't believe I had to make my own version of trim. C++'s STL is totally whack. // And I still had to fix it too. I found three samples of trim online and *all* three // were buggy. People really need to learn to code before they start posting trim @@ -172,16 +166,16 @@ bool SysAllocateMem() psxMemAlloc(); vuMicroMemAlloc(); } - catch( Exception::OutOfMemory& ex ) + catch( Exception::OutOfMemory& ) { + // TODO : Should this error be handled here or allowed to be handled by the main + // exception handler? + // Failures on the core initialization of memory is bad, since it means the emulator is - // completely non-functional. If the failure is in the VM build then we can try running - // the VTLB build instead. If it's the VTLB build then ... ouch. - - // VTLB build must fail outright... - Msgbox::Alert( "Failed to allocate memory needed to run pcsx2.\n\nError: %s", params ex.cMessage() ); + // completely non-functional. + + //Msgbox::Alert( "Failed to allocate memory needed to run pcsx2.\n\nError: %s", params ex.cMessage() ); SysShutdownMem(); - return false; } @@ -207,14 +201,17 @@ void SysAllocateDynarecs() recCpu.Allocate(); psxRec.Allocate(); } - catch( Exception::BaseException& ex ) + catch( Exception::BaseException& ) { - Msgbox::Alert( + // TODO : Fix this message. It should respond according to the user's + // currently configured recompiler.interpreter options, for example. + + /*Msgbox::Alert( "The EE/IOP recompiler failed to initialize with the following error:\n\n" "%s" "\n\nThe EE/IOP interpreter will be used instead (slow!).", params ex.cMessage() - ); + );*/ g_Session.ForceDisableEErec = true; @@ -226,14 +223,19 @@ void SysAllocateDynarecs() { VU0micro::recAlloc(); } - catch( Exception::BaseException& ex ) + catch( Exception::BaseException& ) { + + // TODO : Fix this message. It should respond according to the user's + // currently configured recompiler.interpreter options, for example. +/* Msgbox::Alert( "The VU0 recompiler failed to initialize with the following error:\n\n" "%s" "\n\nThe VU0 interpreter will be used for this session (may slow down some games).", params ex.cMessage() ); +*/ g_Session.ForceDisableVU0rec = true; VU0micro::recShutdown(); @@ -243,14 +245,19 @@ void SysAllocateDynarecs() { VU1micro::recAlloc(); } - catch( Exception::BaseException& ex ) + catch( Exception::BaseException& ) { + + // TODO : Fix this message. It should respond according to the user's + // currently configured recompiler.interpreter options, for example. +/* Msgbox::Alert( "The VU1 recompiler failed to initialize with the following error:\n\n" "%s" "\n\nThe VU1 interpreter will be used for this session (will slow down most games).", params ex.cMessage() ); +*/ g_Session.ForceDisableVU1rec = true; VU1micro::recShutdown(); @@ -362,7 +369,7 @@ void SysExecute() } catch( R5900Exception::BaseExcept& ex ) { - Console::Error( ex.cMessage() ); + Console::Error( ex.LogMessage() ); Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle: 0x%8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() ); } } @@ -383,7 +390,7 @@ void SysEndExecution() // Used by Run::FromCD, and Run->Execute when no active emulation state is present. // elf_file - if NULL, the CDVD plugin is queried for the ELF file. // use_bios - forces the game to boot through the PS2 bios, instead of bypassing it. -void SysPrepareExecution( const char* elf_file, bool use_bios ) +void SysPrepareExecution( const wxString& elf_file, bool use_bios ) { if( !g_EmulationInProgress ) { @@ -393,22 +400,21 @@ void SysPrepareExecution( const char* elf_file, bool use_bios ) } catch( Exception::BaseException& ex ) { - Msgbox::Alert( ex.cMessage() ); + Msgbox::Alert( ex.DisplayMessage() ); return; } if (OpenPlugins(NULL) == -1) return; - if( elf_file == NULL ) + if( elf_file.IsEmpty() ) { if( !StateRecovery::HasState() ) { // Not recovering a state, so need to execute the bios and load the ELF information. // (note: gsRecoveries are done from ExecuteCpu) - char ename[g_MaxPath]; - ename[0] = 0; + wxString ename; if( !use_bios ) GetPS2ElfName( ename ); @@ -440,8 +446,8 @@ void SysReset() // so the status bar won't receive the WM_PAINT messages needed to update itself anyway. // Oops! (air) - HostGui::Notice("Resetting..."); - Console::SetTitle("Resetting..."); + HostGui::Notice( _("Resetting...") ); + Console::SetTitle( _("Resetting...") ); g_EmulationInProgress = false; StateRecovery::Clear(); @@ -454,8 +460,8 @@ void SysReset() // Note : No need to call cpuReset() here. It gets called automatically before the // emulator resumes execution. - HostGui::Notice("Ready"); - Console::SetTitle("*PCSX2* Emulation state is reset."); + HostGui::Notice( _("Ready") ); + Console::SetTitle( _("Emulation state is reset.") ); } u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) @@ -482,8 +488,3 @@ u8 *SysMmapEx(uptr base, u32 size, uptr bounds, const char *caller) } return Mem; } - -void *SysLoadLibrary(const char *lib) { return HostSys::LoadLibrary( lib ); } -void *SysLoadSym(void *lib, const char *sym) { return HostSys::LoadSym( lib, sym ); } -const char *SysLibError() { return HostSys::LibError(); } -void SysCloseLibrary(void *lib) { HostSys::CloseLibrary( lib ); } diff --git a/pcsx2/System.h b/pcsx2/System.h index 0fc21491b0..736c9b5e2b 100644 --- a/pcsx2/System.h +++ b/pcsx2/System.h @@ -21,7 +21,6 @@ #include "PS2Etypes.h" #include "Pcsx2Config.h" -#include "Paths.h" #include "SafeArray.h" #include "Misc.h" #include "Threading.h" // to use threading stuff, include the Threading namespace in your file. @@ -39,14 +38,6 @@ enum PageProtectionMode // versions defined in System.h/cpp. namespace HostSys { - // Damn windows.h namespace pollution!! - #undef LoadLibrary - - extern void *LoadLibrary(const char *lib); // Loads Library - extern void *LoadSym(void *lib, const char *sym); // Loads Symbol from Library - extern const char *LibError(); // Gets previous error loading symbols - extern void CloseLibrary(void *lib); // Closes Library - // Maps a block of memory for use as a recompiled code buffer. // The allocated block has code execution privileges. // Returns NULL on allocation failure. @@ -76,7 +67,7 @@ extern void SysShutdownMem(); extern void SysRestorableReset(); // Saves the current emulation state prior to spu reset. extern void SysClearExecutionCache(); // clears recompiled execution caches! extern void SysEndExecution(); // terminates plugins, saves GS state (if enabled), and signals emulation loop to end. -extern void SysPrepareExecution( const char* elf_file, bool use_bios=false ); +extern void SysPrepareExecution( const wxString& elf_file, bool use_bios=false ); // initiates high-speed execution of the emulation state. This function is currently // designed to be run from an event loop, but will eventually be re-tooled with threading @@ -85,13 +76,6 @@ extern void SysPrepareExecution( const char* elf_file, bool use_bios=false ); extern void SysExecute(); -// Library Helpers for HostSys functions, left in for now for convenience. - -extern void *SysLoadLibrary(const char *lib); // Loads Library -extern void *SysLoadSym(void *lib, const char *sym); // Loads Symbol from Library -extern const char *SysLibError(); // Gets previous error loading symbols -extern void SysCloseLibrary(void *lib); // Closes Library - // Maps a block of memory for use as a recompiled code buffer, and ensures that the // allocation is below a certain memory address (specified in "bounds" parameter). // The allocated block has code execution privileges. @@ -183,6 +167,16 @@ namespace Console // Newline is automatically appended. extern bool Status( const char* fmt, VARG_PARAM dummy, ... ); extern bool __fastcall Status( const char* text ); + + + extern bool __fastcall Write( const wxString& text ); + extern bool __fastcall Write( Colors color, const wxString& text ); + extern bool __fastcall WriteLn( const wxString& text ); + extern bool __fastcall WriteLn( Colors color, const wxString& text ); + + extern bool __fastcall Error( const wxString& text ); + extern bool __fastcall Notice( const wxString& text ); + extern bool __fastcall Status( const wxString& text ); } // Different types of message boxes that the emulator can employ from the friendly confines @@ -193,12 +187,11 @@ namespace Msgbox { // Pops up an alert Dialog Box with a singular "OK" button. // Always returns false. Replacement for SysMessage. - extern bool Alert( const char* fmt, VARG_PARAM dummy, ... ); - extern bool Alert( const char* text ); + extern bool Alert( const wxString& text ); // Pops up a dialog box with Ok/Cancel buttons. Returns the result of the inquiry, // true if OK, false if cancel. - extern bool OkCancel( const char* fmt, VARG_PARAM dummy, ... ); + extern bool OkCancel( const wxString& text ); } using Console::Color_Red; @@ -209,35 +202,4 @@ using Console::Color_Cyan; using Console::Color_Yellow; using Console::Color_White; -////////////////////////////////////////////////////////////// -// Dev / Debug conditionals -- -// Consts for using if() statements instead of uglier #ifdef macros. -// Abbreviated macros for dev/debug only consoles and msgboxes. - -#ifdef PCSX2_DEVBUILD - -# define DevCon Console -# define DevMsg MsgBox - static const bool IsDevBuild = true; - -#else - -# define DevCon 0&&Console -# define DevMsg - static const bool IsDevBuild = false; - -#endif - -#ifdef _DEBUG - -# define DbgCon Console - static const bool IsDebugBuild = true; - -#else - -# define DbgCon 0&&Console - static const bool IsDebugBuild = false; - -#endif - #endif /* __SYSTEM_H__ */ diff --git a/pcsx2/Utilities/AsciiFile.h b/pcsx2/Utilities/AsciiFile.h new file mode 100644 index 0000000000..7719653ac4 --- /dev/null +++ b/pcsx2/Utilities/AsciiFile.h @@ -0,0 +1,46 @@ +/* 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 + +#include + +////////////////////////////////////////////////////////////////////////////////////////// +// Helper class for wxFile which provides old-school ASCII interfaces (char* style), +// for saving some scrodom-kicking pain involved in converting log dumps and stuff over +// to unicode. +// +// This is an ideal solution on several fronts since it is both faster, and fully func- +// tional (since the dumps are only ever english/ascii only). +// +class AsciiFile : public wxFile +{ +public: + using wxFile::Write; + + AsciiFile( const wxString& src, OpenMode mode = read ) : + wxFile( src, mode ) {} + + void Printf( const char* fmt, ... ); + + void Write( const char* fmt ) + { + Write( fmt, strlen( fmt ) ); + } + +}; diff --git a/pcsx2/Utilities/FileUtils.cpp b/pcsx2/Utilities/FileUtils.cpp new file mode 100644 index 0000000000..514569a2c7 --- /dev/null +++ b/pcsx2/Utilities/FileUtils.cpp @@ -0,0 +1,29 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "AsciiFile.h" + +void AsciiFile::Printf( const char* fmt, ... ) +{ + va_list list; + va_start( list, fmt ); + string writeme; vssprintf( writeme, fmt, list ); + va_end( list ); + Write( writeme.c_str(), writeme.length() ); +} diff --git a/pcsx2/Utilities/folderdesc.txt b/pcsx2/Utilities/folderdesc.txt new file mode 100644 index 0000000000..50ca5c8dd4 --- /dev/null +++ b/pcsx2/Utilities/folderdesc.txt @@ -0,0 +1,7 @@ +Folder: pcsx2/Utilities +Purpose: To hold general non-pcsx2-specific utility classes which may (or may not) be shared out into a + common folder at a later date. This includes unicode utils, file manipulators, threading, etc. + +Details: I plan to move files into this folder here ont he wxGui branch over time, and then move the + whole lot over to common as a whole library of sorts. I thinkit'll be easier that way than trying + to piecemeal individual files over (especially since some of them have inter-dependencies) \ No newline at end of file diff --git a/pcsx2/VU0micro.cpp b/pcsx2/VU0micro.cpp index 77a19202ab..772d8ecda3 100644 --- a/pcsx2/VU0micro.cpp +++ b/pcsx2/VU0micro.cpp @@ -38,26 +38,6 @@ using namespace R5900; #define VF_VAL(x) ((x==0x80000000)?0:(x)) -void iDumpVU0Registers() -{ - // fixme: This code is outdated, broken, and lacks printed labels. - // Needs heavy mods to be useful. -#if 0 - int i; - - for(i = 1; i < 32; ++i) { - __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU0.VF[i].UL[3]), VF_VAL(VU0.VF[i].UL[2]), - VF_VAL(VU0.VF[i].UL[1]), VF_VAL(VU0.VF[i].UL[0])); - if( i == REG_Q || i == REG_P ) __Log("%f\n", VU0.VI[i].F); - else if( i == REG_MAC_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0xff); - else if( i == REG_STATUS_FLAG ) __Log("%x\n", 0);//VU0.VI[i].UL&0x03); - else if( i == REG_CLIP_FLAG ) __Log("0\n"); - else __Log("%x\n", VU0.VI[i].UL); - } - __Log("vfACC: %f %f %f %f\n", VU0.ACC.F[3], VU0.ACC.F[2], VU0.ACC.F[1], VU0.ACC.F[0]); -#endif -} - // This is called by the COP2 as per the CTC instruction void vu0ResetRegs() { diff --git a/pcsx2/VU1micro.cpp b/pcsx2/VU1micro.cpp index 669feef7a6..dfc3151127 100644 --- a/pcsx2/VU1micro.cpp +++ b/pcsx2/VU1micro.cpp @@ -38,27 +38,6 @@ u32 vudump = 0; #define VF_VAL(x) ((x==0x80000000)?0:(x)) -void iDumpVU1Registers() -{ - // fixme: This code is outdated, broken, and lacks printed labels. - // Needs heavy mods to be useful. -#if 0 - int i; -// static int icount = 0; -// __Log("%x\n", icount); - for(i = 1; i < 32; ++i) { -// __Log("v%d: w%f(%x) z%f(%x) y%f(%x) x%f(%x), vi: ", i, VU1.VF[i].F[3], VU1.VF[i].UL[3], VU1.VF[i].F[2], VU1.VF[i].UL[2], -// VU1.VF[i].F[1], VU1.VF[i].UL[1], VU1.VF[i].F[0], VU1.VF[i].UL[0]); - //__Log("v%d: %f %f %f %f, vi: ", i, VU1.VF[i].F[3], VU1.VF[i].F[2], VU1.VF[i].F[1], VU1.VF[i].F[0]); - __Log("v%d: %x %x %x %x, vi: ", i, VF_VAL(VU1.VF[i].UL[3]), VF_VAL(VU1.VF[i].UL[2]), VF_VAL(VU1.VF[i].UL[1]), VF_VAL(VU1.VF[i].UL[0])); - if( i == REG_Q || i == REG_P ) __Log("%f\n", VU1.VI[i].F); - //else __Log("%x\n", VU1.VI[i].UL); - else __Log("%x\n", (i==REG_STATUS_FLAG||i==REG_MAC_FLAG||i==REG_CLIP_FLAG)?0:VU1.VI[i].UL); - } - __Log("vfACC: %f %f %f %f\n", VU1.ACC.F[3], VU1.ACC.F[2], VU1.ACC.F[1], VU1.ACC.F[0]); -#endif -} - // This is called by the COP2 as per the CTC instruction void vu1ResetRegs() { diff --git a/pcsx2/VUops.cpp b/pcsx2/VUops.cpp index e043760350..c0341158b7 100644 --- a/pcsx2/VUops.cpp +++ b/pcsx2/VUops.cpp @@ -1585,7 +1585,7 @@ void _vuLQ(VURegs * VU) { if (_Ft_ == 0) return; imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); - addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; @@ -1601,7 +1601,7 @@ void _vuLQD( VURegs * VU ) { if (_Fs_ != 0) VU->VI[_Fs_].US[0]--; if (_Ft_ == 0) return; - addr = VU->VI[_Fs_].US[0] * 16; + addr = (VU->VI[_Fs_].US[0] * 16) & (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; @@ -1614,7 +1614,7 @@ void _vuLQI(VURegs * VU) { u32 addr; u32 *ptr; - addr = VU->VI[_Fs_].US[0] * 16; + addr = (VU->VI[_Fs_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) VU->VF[_Ft_].UL[0] = ptr[0]; if (_Y) VU->VF[_Ft_].UL[1] = ptr[1]; @@ -1631,7 +1631,7 @@ void _vuSQ(VURegs * VU) { u32 *ptr; imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); - addr = (imm + VU->VI[_Ft_].SS[0]) * 16; + addr = ((imm + VU->VI[_Ft_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; @@ -1644,7 +1644,7 @@ void _vuSQD(VURegs * VU) { u32 *ptr; if(_Ft_ != 0) VU->VI[_Ft_].US[0]--; - addr = VU->VI[_Ft_].US[0] * 16; + addr = (VU->VI[_Ft_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; @@ -1656,7 +1656,7 @@ void _vuSQI(VURegs * VU) { u32 addr; u32 *ptr; - addr = VU->VI[_Ft_].US[0] * 16; + addr = (VU->VI[_Ft_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u32*)GET_VU_MEM(VU, addr); if (_X) ptr[0] = VU->VF[_Fs_].UL[0]; if (_Y) ptr[1] = VU->VF[_Fs_].UL[1]; @@ -1673,7 +1673,7 @@ void _vuILW(VURegs * VU) { if (_Ft_ == 0) return; imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); - addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u16*)GET_VU_MEM(VU, addr); if (_X) VU->VI[_Ft_].US[0] = ptr[0]; if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; @@ -1687,7 +1687,7 @@ void _vuISW(VURegs * VU) { u16 *ptr; imm = (VU->code & 0x400) ? (VU->code & 0x3ff) | 0xfc00 : (VU->code & 0x3ff); - addr = (imm + VU->VI[_Fs_].SS[0]) * 16; + addr = ((imm + VU->VI[_Fs_].SS[0]) * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u16*)GET_VU_MEM(VU, addr); if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } @@ -1700,7 +1700,7 @@ void _vuILWR(VURegs * VU) { u16 *ptr; if (_Ft_ == 0) return; - addr = VU->VI[_Fs_].US[0] * 16; + addr = (VU->VI[_Fs_].US[0] * 16)& (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u16*)GET_VU_MEM(VU, addr); if (_X) VU->VI[_Ft_].US[0] = ptr[0]; if (_Y) VU->VI[_Ft_].US[0] = ptr[2]; @@ -1712,7 +1712,7 @@ void _vuISWR(VURegs * VU) { u32 addr; u16 *ptr; - addr = VU->VI[_Fs_].US[0] * 16; + addr = (VU->VI[_Fs_].US[0] * 16) & (VU == &VU1 ? 0x3fff : 0xfff); ptr = (u16*)GET_VU_MEM(VU, addr); if (_X) { ptr[0] = VU->VI[_Ft_].US[0]; ptr[1] = 0; } if (_Y) { ptr[2] = VU->VI[_Ft_].US[0]; ptr[3] = 0; } @@ -2045,9 +2045,20 @@ void _vuXITOP(VURegs * VU) { void _vuXGKICK(VURegs * VU) { + u32* ptr = (u32*)GET_VU_MEM(VU, (VU->VI[_Fs_].US[0]*16) & (VU == &VU1 ? 0x3fff : 0xfff)); +// int temp = 0x4000 - ((VU->VI[_Fs_].US[0]*16) & 0x3fff); +// u32 tempmem[0x8000]; + // flush all pipelines first (in the right order) _vuFlushAll(VU); - GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); + + //Gonna be slow but reshuffles the memory so overflows wont occur + /* memset(tempmem, 0, sizeof(tempmem)); + memcpy(tempmem, ptr, temp); + ptr = (u32*)GET_VU_MEM(VU, 0); + memcpy(&tempmem[temp], ptr, ((VU->VI[_Fs_].US[0]*16) & 0x3fff)); + GSGIFTRANSFER1((u32*)&tempmem[0], 0); + } else*/ GSGIFTRANSFER1((u32*)VU->Mem, (VU->VI[_Fs_].US[0]*16) & 0x3fff); } void _vuXTOP(VURegs * VU) { @@ -2508,13 +2519,23 @@ void _vuRegsMTIR(VURegs * VU, _VURegsNum *VUregsn) { VUregsn->pipe = VUPIPE_FMAC; VUregsn->VFwrite = 0; VUregsn->VFread0 = _Fs_; - VUregsn->VFr0xyzw= _XYZW; + VUregsn->VFr0xyzw= 1 << (3-_Fsf_); VUregsn->VFread1 = 0; VUregsn->VIwrite = 1 << _Ft_; VUregsn->VIread = GET_VF0_FLAG(_Fs_); } -VUREGS_FTFS(MR32); +void _vuRegsMR32(VURegs * VU, _VURegsNum *VUregsn) { + VUregsn->pipe = VUPIPE_FMAC; + VUregsn->VFwrite = _Ft_; + VUregsn->VFwxyzw = _XYZW; + VUregsn->VFread0 = _Fs_; + VUregsn->VFr0xyzw= (_XYZW >> 1) | ((_XYZW << 3) & 0xf); //rotate + VUregsn->VFread1 = 0; + VUregsn->VFr1xyzw = 0xff; + VUregsn->VIwrite = 0; + VUregsn->VIread = (_Ft_ ? GET_VF0_FLAG(_Fs_) : 0); +} void _vuRegsLQ(VURegs * VU, _VURegsNum *VUregsn) { VUregsn->pipe = VUPIPE_FMAC; diff --git a/pcsx2/Vif.cpp b/pcsx2/Vif.cpp index d4ece5c0d3..0da6e70175 100644 --- a/pcsx2/Vif.cpp +++ b/pcsx2/Vif.cpp @@ -25,10 +25,11 @@ #include "Vif.h" #include "VifDma.h" -VIFregisters *_vifRegs; -u32* _vifRow = NULL, *_vifCol = NULL; -u32* _vifMaskRegs = NULL; -vifStruct *_vif; +VIFregisters *vifRegs; +u32* vifRow = NULL; +u32* vifMaskRegs = NULL; +vifStruct *vif; +u16 vifqwc = 0; PCSX2_ALIGNED16(u32 g_vifRow0[4]); PCSX2_ALIGNED16(u32 g_vifCol0[4]); @@ -36,43 +37,44 @@ PCSX2_ALIGNED16(u32 g_vifRow1[4]); PCSX2_ALIGNED16(u32 g_vifCol1[4]); extern int g_vifCycles; -u16 vifqwc = 0; -bool mfifodmairq = FALSE; +bool mfifodmairq = false; enum UnpackOffset { OFFSET_X = 0, - OFFSET_Y, - OFFSET_Z, - OFFSET_W + OFFSET_Y = 1, + OFFSET_Z = 2, + OFFSET_W = 3 }; -#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) - __forceinline static int _limit(int a, int max) { return (a > max) ? max : a; } -static __releaseinline void writeX(u32 *dest, u32 data) +static __releaseinline void writeXYZW(u32 offnum, u32 &dest, u32 data) { int n; + u32 vifRowReg = getVifRowRegs(offnum); - if (_vifRegs->code & 0x10000000) + if (vifRegs->code & 0x10000000) { - switch (_vif->cl) + switch (vif->cl) { case 0: - n = (_vifRegs->mask) & 0x3; + if (offnum == OFFSET_X) + n = (vifRegs->mask) & 0x3; + else + n = (vifRegs->mask >> (offnum * 2)) & 0x3; break; case 1: - n = (_vifRegs->mask >> 8) & 0x3; + n = (vifRegs->mask >> ( 8 + (offnum * 2))) & 0x3; break; case 2: - n = (_vifRegs->mask >> 16) & 0x3; + n = (vifRegs->mask >> (16 + (offnum * 2))) & 0x3; break; default: - n = (_vifRegs->mask >> 24) & 0x3; + n = (vifRegs->mask >> (24 + (offnum * 2))) & 0x3; break; } } @@ -81,488 +83,260 @@ static __releaseinline void writeX(u32 *dest, u32 data) switch (n) { case 0: - if ((_vif->cmd & 0x6F) == 0x6f) + if ((vif->cmd & 0x6F) == 0x6f) { - *dest = data; + dest = data; } - else if (_vifRegs->mode == 1) + else switch (vifRegs->mode) { - *dest = data + _vifRegs->r0; - } - else if (_vifRegs->mode == 2) - { - _vifRegs->r0 += data; - *dest = _vifRegs->r0; - } - else - { - *dest = data; + case 1: + dest = data + vifRowReg; + break; + case 2: + // vifRowReg isn't used after this, or I would make it equal to dest here. + dest = setVifRowRegs(offnum, vifRowReg + data); + break; + default: + dest = data; + break; } break; case 1: - *dest = _vifRegs->r0; + dest = vifRowReg; break; case 2: - switch (_vif->cl) - { - case 0: - *dest = _vifRegs->c0; - break; - case 1: - *dest = _vifRegs->c1; - break; - case 2: - *dest = _vifRegs->c2; - break; - default: - *dest = _vifRegs->c3; - break; - } + dest = getVifColRegs((vif->cl > 2) ? 3 : vif->cl); + break; + case 3: break; } -// VIF_LOG("writeX %8.8x : Mode %d, r0 = %x, data %8.8x", *dest,_vifRegs->mode,_vifRegs->r0,data); +// VIF_LOG("writeX %8.8x : Mode %d, r0 = %x, data %8.8x", *dest,vifRegs->mode,vifRegs->r0,data); } -static __releaseinline void writeY(u32 *dest, u32 data) +template +void __fastcall UNPACK_S(u32 *dest, T *data, int size) { - int n; + //S-# will always be a complete packet, no matter what. So we can skip the offset bits + writeXYZW(OFFSET_X, *dest++, *data); + writeXYZW(OFFSET_Y, *dest++, *data); + writeXYZW(OFFSET_Z, *dest++, *data); + writeXYZW(OFFSET_W, *dest , *data); +} + +template +void __fastcall UNPACK_V2(u32 *dest, T *data, int size) +{ + if (vifRegs->offset == OFFSET_X) + { + if (size > 0) + { + writeXYZW(vifRegs->offset, *dest++, *data++); + vifRegs->offset = OFFSET_Y; + size--; + } + } - if (_vifRegs->code & 0x10000000) + if (vifRegs->offset == OFFSET_Y) { - switch (_vif->cl) + if (size > 0) { - case 0: - n = (_vifRegs->mask >> 2) & 0x3; - break; - case 1: - n = (_vifRegs->mask >> 10) & 0x3; - break; - case 2: - n = (_vifRegs->mask >> 18) & 0x3; - break; - default: - n = (_vifRegs->mask >> 26) & 0x3; - break; + writeXYZW(vifRegs->offset, *dest++, *data); + vifRegs->offset = OFFSET_Z; + size--; } } - else n = 0; - - switch (n) - { - case 0: - if ((_vif->cmd & 0x6F) == 0x6f) - { - *dest = data; - } - else if (_vifRegs->mode == 1) - { - *dest = data + _vifRegs->r1; - } - else if (_vifRegs->mode == 2) - { - _vifRegs->r1 += data; - *dest = _vifRegs->r1; - } - else - { - *dest = data; - } - break; - case 1: - *dest = _vifRegs->r1; - break; - case 2: - switch (_vif->cl) - { - case 0: - *dest = _vifRegs->c0; - break; - case 1: - *dest = _vifRegs->c1; - break; - case 2: - *dest = _vifRegs->c2; - break; - default: - *dest = _vifRegs->c3; - break; - } - break; - } -// VIF_LOG("writeY %8.8x : Mode %d, r1 = %x, data %8.8x", *dest,_vifRegs->mode,_vifRegs->r1,data); -} - -static __releaseinline void writeZ(u32 *dest, u32 data) -{ - int n; - if (_vifRegs->code & 0x10000000) + if (vifRegs->offset == OFFSET_Z) { - switch (_vif->cl) - { - case 0: - n = (_vifRegs->mask >> 4) & 0x3; - break; - case 1: - n = (_vifRegs->mask >> 12) & 0x3; - break; - case 2: - n = (_vifRegs->mask >> 20) & 0x3; - break; - default: - n = (_vifRegs->mask >> 28) & 0x3; - break; - } + writeXYZW(vifRegs->offset, *dest++, *dest-2); + vifRegs->offset = OFFSET_W; } - else n = 0; - - switch (n) - { - case 0: - if ((_vif->cmd & 0x6F) == 0x6f) - { - *dest = data; - } - else if (_vifRegs->mode == 1) - { - *dest = data + _vifRegs->r2; - } - else if (_vifRegs->mode == 2) - { - _vifRegs->r2 += data; - *dest = _vifRegs->r2; - } - else - { - *dest = data; - } - break; - case 1: - *dest = _vifRegs->r2; - break; - case 2: - switch (_vif->cl) - { - case 0: - *dest = _vifRegs->c0; - break; - case 1: - *dest = _vifRegs->c1; - break; - case 2: - *dest = _vifRegs->c2; - break; - default: - *dest = _vifRegs->c3; - break; - } - break; - } -// VIF_LOG("writeZ %8.8x : Mode %d, r2 = %x, data %8.8x", *dest,_vifRegs->mode,_vifRegs->r2,data); -} - -static __releaseinline void writeW(u32 *dest, u32 data) -{ - int n; - if (_vifRegs->code & 0x10000000) + if (vifRegs->offset == OFFSET_W) { - switch (_vif->cl) + writeXYZW(vifRegs->offset, *dest, *data); + vifRegs->offset = OFFSET_X; + } +} + +template +void __fastcall UNPACK_V3(u32 *dest, T *data, int size) +{ + if(vifRegs->offset == OFFSET_X) + { + if (size > 0) { - case 0: - n = (_vifRegs->mask >> 6) & 0x3; - break; - case 1: - n = (_vifRegs->mask >> 14) & 0x3; - break; - case 2: - n = (_vifRegs->mask >> 22) & 0x3; - break; - default: - n = (_vifRegs->mask >> 30) & 0x3; - break; + writeXYZW(vifRegs->offset, *dest++, *data++); + vifRegs->offset = OFFSET_Y; + size--; } } - else n = 0; - - switch (n) + + if(vifRegs->offset == OFFSET_Y) { - case 0: - if ((_vif->cmd & 0x6F) == 0x6f) - { - *dest = data; - } - else if (_vifRegs->mode == 1) - { - *dest = data + _vifRegs->r3; - } - else if (_vifRegs->mode == 2) - { - _vifRegs->r3 += data; - *dest = _vifRegs->r3; - } - else - { - *dest = data; - } - break; - case 1: - *dest = _vifRegs->r3; - break; - case 2: - switch (_vif->cl) - { - case 0: - *dest = _vifRegs->c0; - break; - case 1: - *dest = _vifRegs->c1; - break; - case 2: - *dest = _vifRegs->c2; - break; - default: - *dest = _vifRegs->c3; - break; - } - break; - } -// VIF_LOG("writeW %8.8x : Mode %d, r3 = %x, data %8.8x", *dest,_vifRegs->mode,_vifRegs->r3,data); -} - -static __forceinline bool __fastcall _UNPACKpart(u32 offnum, u32 *x, u32 y) -{ - if (_vifRegs->offset == offnum) - { - switch (offnum) + if (size > 0) { - case OFFSET_X: - writeX(x,y); - break; - case OFFSET_Y: - writeY(x,y); - break; - case OFFSET_Z: - writeZ(x,y); - break; - case OFFSET_W: - writeW(x,y); - break; - default: - break; + writeXYZW(vifRegs->offset, *dest++, *data++); + vifRegs->offset = OFFSET_Z; + size--; } - _vifRegs->offset++; - - return TRUE; } - return FALSE; + + if(vifRegs->offset == OFFSET_Z) + { + if (size > 0) + { + writeXYZW(vifRegs->offset, *dest++, *data++); + vifRegs->offset = OFFSET_W; + size--; + } + } + + if(vifRegs->offset == OFFSET_W) + { + //V3-# does some bizzare thing with alignment, every 6qw of data the W becomes 0 (strange console!) + //Ape Escape doesnt seem to like it tho (what the hell?) gonna have to investigate + writeXYZW(vifRegs->offset, *dest, *data); + vifRegs->offset = OFFSET_X; + } } -void __fastcall UNPACK_S_32(u32 *dest, u32 *data, int size) +template +void __fastcall UNPACK_V4(u32 *dest, T *data , int size) { - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *data)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *data)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *data)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *data)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + while (size > 0) + { + writeXYZW(vifRegs->offset, *dest++, *data++); + vifRegs->offset++; + size--; + } + + if (vifRegs->offset > OFFSET_W) vifRegs->offset = OFFSET_X; } -void __fastcall UNPACK_S_16s(u32 *dest, u32 *data, int size) +void __fastcall UNPACK_V4_5(u32 *dest, u32 *data, int size) { - s16 *sdata = (s16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest, *sdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + //As with S-#, this will always be a complete packet + writeXYZW(OFFSET_X, *dest++, ((*data & 0x001f) << 3)); + writeXYZW(OFFSET_Y, *dest++, ((*data & 0x03e0) >> 2)); + writeXYZW(OFFSET_Z, *dest++, ((*data & 0x7c00) >> 7)); + writeXYZW(OFFSET_W, *dest, ((*data & 0x8000) >> 8)); } -void __fastcall UNPACK_S_16u(u32 *dest, u32 *data, int size) +void __fastcall UNPACK_S_32(u32 *dest, u32 *data, int size) { - const u16 *sdata = (u16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *sdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_S(dest, data, size); +} + +void __fastcall UNPACK_S_16s(u32 *dest, u32 *data, int size) +{ + s16 *sdata = (s16*)data; + UNPACK_S(dest, sdata, size); +} + +void __fastcall UNPACK_S_16u(u32 *dest, u32 *data, int size) +{ + u16 *sdata = (u16*)data; + UNPACK_S(dest, sdata, size); } void __fastcall UNPACK_S_8s(u32 *dest, u32 *data, int size) { s8 *cdata = (s8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *cdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_S(dest, cdata, size); } void __fastcall UNPACK_S_8u(u32 *dest, u32 *data, int size) { u8 *cdata = (u8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata))size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *cdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_S(dest, cdata, size); } void __fastcall UNPACK_V2_32(u32 *dest, u32 *data, int size) { - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *data--)) size--; - _UNPACKpart(OFFSET_Z, dest++, *data); - _UNPACKpart(OFFSET_W, dest, 0); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; - + UNPACK_V2(dest, data, size); } void __fastcall UNPACK_V2_16s(u32 *dest, u32 *data, int size) { s16 *sdata = (s16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata--)) size--; - _UNPACKpart(OFFSET_Z, dest++, *sdata++); - _UNPACKpart(OFFSET_W, dest , *sdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V2(dest, sdata, size); } void __fastcall UNPACK_V2_16u(u32 *dest, u32 *data, int size) { u16 *sdata = (u16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata--)) size--; - _UNPACKpart(OFFSET_Z, dest++, *sdata++); - _UNPACKpart(OFFSET_W, dest , *sdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V2(dest, sdata, size); } void __fastcall UNPACK_V2_8s(u32 *dest, u32 *data, int size) { s8 *cdata = (s8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata--)) size--; - _UNPACKpart(OFFSET_Z, dest++, *cdata++); - _UNPACKpart(OFFSET_W, dest , *cdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V2(dest, cdata, size); } void __fastcall UNPACK_V2_8u(u32 *dest, u32 *data, int size) { u8 *cdata = (u8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata--)) size--; - _UNPACKpart(OFFSET_Z, dest++, *cdata++); - _UNPACKpart(OFFSET_W, dest , *cdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V2(dest, cdata, size); } void __fastcall UNPACK_V3_32(u32 *dest, u32 *data, int size) { - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *data++)) size--; - _UNPACKpart(OFFSET_W, dest, *data); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V3(dest, data, size); } void __fastcall UNPACK_V3_16s(u32 *dest, u32 *data, int size) { s16 *sdata = (s16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata++)) size--; - _UNPACKpart(OFFSET_W, dest, *sdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V3(dest, sdata, size); } void __fastcall UNPACK_V3_16u(u32 *dest, u32 *data, int size) { u16 *sdata = (u16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata++)) size--; - _UNPACKpart(OFFSET_W, dest, *sdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V3(dest, sdata, size); } void __fastcall UNPACK_V3_8s(u32 *dest, u32 *data, int size) { s8 *cdata = (s8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata++)) size--; - _UNPACKpart(OFFSET_W, dest, *cdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V3(dest, cdata, size); } void __fastcall UNPACK_V3_8u(u32 *dest, u32 *data, int size) { u8 *cdata = (u8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata++)) size--; - _UNPACKpart(OFFSET_W, dest, *cdata); - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V3(dest, cdata, size); } void __fastcall UNPACK_V4_32(u32 *dest, u32 *data , int size) { - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *data++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *data)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V4(dest, data, size); } void __fastcall UNPACK_V4_16s(u32 *dest, u32 *data, int size) { s16 *sdata = (s16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , *sdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V4(dest, sdata, size); } void __fastcall UNPACK_V4_16u(u32 *dest, u32 *data, int size) { u16 *sdata = (u16*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *sdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest, *sdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V4(dest, sdata, size); } void __fastcall UNPACK_V4_8s(u32 *dest, u32 *data, int size) { s8 *cdata = (s8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest, *cdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V4(dest, cdata, size); } void __fastcall UNPACK_V4_8u(u32 *dest, u32 *data, int size) { u8 *cdata = (u8*)data; - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, *cdata++)) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest, *cdata)) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; -} - -void __fastcall UNPACK_V4_5(u32 *dest, u32 *data, int size) -{ - - if (size > 0) if (_UNPACKpart(OFFSET_X, dest++, ((*data & 0x001f) << 3))) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Y, dest++, ((*data & 0x03e0) >> 2))) size--; - if (size > 0) if (_UNPACKpart(OFFSET_Z, dest++, ((*data & 0x7c00) >> 7))) size--; - if (size > 0) if (_UNPACKpart(OFFSET_W, dest , ((*data & 0x8000) >> 8))) size--; - if (_vifRegs->offset == 4) _vifRegs->offset = 0; + UNPACK_V4(dest, cdata, size); } static __forceinline int mfifoVIF1rbTransfer() @@ -583,7 +357,7 @@ static __forceinline int mfifoVIF1rbTransfer() src = (u32*)PSM(vif1ch->madr); if (src == NULL) return -1; - if (vif1.vifstalled == 1) + if (vif1.vifstalled) ret = VIF1transfer(src + vif1.irqoffset, s1 - vif1.irqoffset, 0); else ret = VIF1transfer(src, s1, 0); @@ -605,7 +379,7 @@ static __forceinline int mfifoVIF1rbTransfer() src = (u32*)PSM(vif1ch->madr); if (src == NULL) return -1; - if (vif1.vifstalled == 1) + if (vif1.vifstalled) ret = VIF1transfer(src + vif1.irqoffset, mfifoqwc * 4 - vif1.irqoffset, 0); else ret = VIF1transfer(src, mfifoqwc << 2, 0); @@ -616,12 +390,12 @@ static __forceinline int mfifoVIF1rbTransfer() return ret; } -static __forceinline int mfifoVIF1chain() +static __forceinline int mfifo_VIF1chain() { int ret; /* Is QWC = 0? if so there is nothing to transfer */ - if (vif1ch->qwc == 0 && vif1.vifstalled == 0) + if ((vif1ch->qwc == 0) && (!vif1.vifstalled)) { vif1.inprogress = 0; return 0; @@ -640,7 +414,7 @@ static __forceinline int mfifoVIF1chain() SPR_LOG("Non-MFIFO Location"); if (pMem == NULL) return -1; - if (vif1.vifstalled == 1) + if (vif1.vifstalled) ret = VIF1transfer(pMem + vif1.irqoffset, vif1ch->qwc * 4 - vif1.irqoffset, 0); else ret = VIF1transfer(pMem, vif1ch->qwc << 2, 0); @@ -653,28 +427,29 @@ void mfifoVIF1transfer(int qwc) { u32 *ptag; int id; - int ret, temp; + int ret; g_vifCycles = 0; if (qwc > 0) { vifqwc += qwc; + SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done); if (vif1.inprogress & 0x10) { if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR))) - CPU_INT(10, min((int)vifqwc, (int)vif1ch->qwc) * BIAS); + CPU_INT(10, 0); else CPU_INT(10, vif1ch->qwc * BIAS); vif1Regs->stat |= 0x10000000; // FQC=16 } vif1.inprogress &= ~0x10; - SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch->chcr, vif1.vifstalled, vif1.done); + return; } - mfifodmairq = FALSE; //Clear any previous TIE interrupt + mfifodmairq = false; //Clear any previous TIE interrupt if (vif1ch->qwc == 0) { @@ -682,7 +457,7 @@ void mfifoVIF1transfer(int qwc) if (vif1ch->chcr & 0x40) { - if (vif1.stallontag == 1) + if (vif1.stallontag) ret = VIF1transfer(ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, 1); //Transfer Tag on Stall else ret = VIF1transfer(ptag + 2, 2, 1); //Transfer Tag @@ -690,7 +465,7 @@ void mfifoVIF1transfer(int qwc) if (ret == -2) { VIF_LOG("MFIFO Stallon tag"); - vif1.stallontag = 1; + vif1.stallontag = true; return; //IRQ set by VIFTransfer } } @@ -709,41 +484,43 @@ void mfifoVIF1transfer(int qwc) { case 0: // Refe - Transfer Packet According to ADDR field vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); - vif1.done = 1; //End Transfer + vif1.done = true; //End Transfer break; case 1: // CNT - Transfer QWC following the tag. vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW after Tag vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data - vif1.done = 0; + vif1.done = false; break; case 2: // Next - Transfer QWC following tag. TADR = ADDR - temp = vif1ch->madr; //Temporarily Store ADDR + { + int temp = vif1ch->madr; //Temporarily Store ADDR vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to QW following the tag vif1ch->tadr = temp; //Copy temporarily stored ADDR to Tag if ((temp & psHu32(DMAC_RBSR)) != psHu32(DMAC_RBOR)) Console::WriteLn("Next tag = %x outside ring %x size %x", params temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR)); - vif1.done = 0; + vif1.done = false; break; + } case 3: // Ref - Transfer QWC from ADDR field case 4: // Refs - Transfer QWC from ADDR field (Stall Control) vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set TADR to next tag - vif1.done = 0; + vif1.done = false; break; case 7: // End - Transfer QWC following the tag vif1ch->madr = psHu32(DMAC_RBOR) + ((vif1ch->tadr + 16) & psHu32(DMAC_RBSR)); //Set MADR to data following the tag vif1ch->tadr = psHu32(DMAC_RBOR) + ((vif1ch->madr + (vif1ch->qwc << 4)) & psHu32(DMAC_RBSR)); //Set TADR to QW following the data - vif1.done = 1; //End Transfer + vif1.done = true; //End Transfer break; } if ((vif1ch->chcr & 0x80) && (ptag[0] >> 31)) { VIF_LOG("dmaIrq Set"); - vif1.done = 1; - mfifodmairq = TRUE; //Let the handler know we have prematurely ended MFIFO + vif1.done = true; + mfifodmairq = true; //Let the handler know we have prematurely ended MFIFO } } @@ -756,7 +533,13 @@ void vifMFIFOInterrupt() { g_vifCycles = 0; - if (vif1.inprogress == 1) mfifoVIF1chain(); + if((spr0->chcr & 0x100) && spr0->qwc == 0) + { + spr0->chcr &= ~0x100; + hwDmacIrq(8); + } + + if (vif1.inprogress == 1) mfifo_VIF1chain(); if (vif1.irq && vif1.tag.size == 0) { @@ -771,7 +554,7 @@ void vifMFIFOInterrupt() } } - if (vif1.done != 1 || vif1.inprogress & 1) + if (!vif1.done || vif1.inprogress & 1) { if (vifqwc <= 0) { @@ -784,10 +567,11 @@ void vifMFIFOInterrupt() if (!(vif1.inprogress & 0x1)) mfifoVIF1transfer(0); if (vif1ch->madr >= psHu32(DMAC_RBOR) && vif1ch->madr <= (psHu32(DMAC_RBOR) + psHu32(DMAC_RBSR))) - CPU_INT(10, min((int)vifqwc, (int)vif1ch->qwc) * BIAS); + CPU_INT(10, 0); else CPU_INT(10, vif1ch->qwc * BIAS); + return; } else if (vifqwc <= 0) diff --git a/pcsx2/Vif.h b/pcsx2/Vif.h index 4ad1cb233e..2f84369b5a 100644 --- a/pcsx2/Vif.h +++ b/pcsx2/Vif.h @@ -24,6 +24,7 @@ struct vifCycle { u8 pad[2]; }; +// r0-r3 and c0-c3 would be more managable as arrays. struct VIFregisters { u32 stat; u32 pad0[3]; @@ -80,12 +81,94 @@ struct VIFregisters { extern "C" { // these use cdecl for Asm code references. - extern VIFregisters *_vifRegs; - extern u32* _vifMaskRegs; - extern u32* _vifRow; + extern VIFregisters *vifRegs; + extern u32* vifMaskRegs; + extern u32* vifRow; extern u32* _vifCol; } +static __forceinline u32 setVifRowRegs(u32 reg, u32 data) +{ + switch (reg) + { + case 0: + vifRegs->r0 += data; + break; + case 1: + vifRegs->r1 += data; + break; + case 2: + vifRegs->r2 += data; + break; + case 3: + vifRegs->r3 += data; + break; + jNO_DEFAULT; + } + return data; +} + +static __forceinline u32 getVifRowRegs(u32 reg) +{ + switch (reg) + { + case 0: + return vifRegs->r0; + break; + case 1: + return vifRegs->r1; + break; + case 2: + return vifRegs->r2; + break; + case 3: + return vifRegs->r3; + break; + jNO_DEFAULT; + } +} + +static __forceinline u32 setVifColRegs(u32 reg, u32 data) +{ + switch (reg) + { + case 0: + vifRegs->c0 = data; + break; + case 1: + vifRegs->c1 = data; + break; + case 2: + vifRegs->c2 = data; + break; + case 3: + vifRegs->c3 = data; + break; + jNO_DEFAULT; + } + return data; +} + +static __forceinline u32 getVifColRegs(u32 reg) +{ + switch (reg) + { + case 0: + return vifRegs->c0; + break; + case 1: + return vifRegs->c1; + break; + case 2: + return vifRegs->c2; + break; + case 3: + return vifRegs->c3; + break; + jNO_DEFAULT; + } +} + #define vif0Regs ((VIFregisters*)&PS2MEM_HW[0x3800]) #define vif1Regs ((VIFregisters*)&PS2MEM_HW[0x3c00]) diff --git a/pcsx2/VifDma.cpp b/pcsx2/VifDma.cpp index 02361285c2..7452378f4f 100644 --- a/pcsx2/VifDma.cpp +++ b/pcsx2/VifDma.cpp @@ -29,18 +29,13 @@ using namespace std; // for min / max -//#define VIFUNPACKDEBUG //enable unpack debugging output - -#define gif ((DMACh*)&PS2MEM_HW[0xA000]) - // Extern variables extern "C" { // Need cdecl on these for ASM references. - extern VIFregisters *_vifRegs; - extern u32* _vifMaskRegs; - extern u32* _vifRow; - extern u32* _vifCol; + extern VIFregisters *vifRegs; + extern u32* vifMaskRegs; + extern u32* vifRow; } PCSX2_ALIGNED16_EXTERN(u32 g_vifRow0[4]); @@ -48,7 +43,7 @@ PCSX2_ALIGNED16_EXTERN(u32 g_vifCol0[4]); PCSX2_ALIGNED16_EXTERN(u32 g_vifRow1[4]); PCSX2_ALIGNED16_EXTERN(u32 g_vifCol1[4]); -extern vifStruct *_vif; +extern vifStruct *vif; vifStruct vif0, vif1; @@ -63,8 +58,11 @@ static const unsigned int VIF0dmanum = 0; static const unsigned int VIF1dmanum = 1; int g_vifCycles = 0; -bool path3hack = FALSE; -bool Path3transfer = FALSE; +bool path3hack = false; +bool Path3transfer = false; + +u32 splittransfer[4]; +u32 splitptr = 0; typedef void (__fastcall *UNPACKFUNCTYPE)(u32 *dest, u32 *data, int size); typedef int (*UNPACKPARTFUNCTYPESSE)(u32 *dest, u32 *data, int size); @@ -81,10 +79,10 @@ struct VIFUnpackFuncTable UNPACKFUNCTYPE funcU; UNPACKFUNCTYPE funcS; - int bsize; // currently unused - int dsize; // byte size of one channel - int gsize; // size of data in bytes used for each write cycle - int qsize; // used for unpack parts, num of vectors that + u32 bsize; // currently unused + u32 dsize; // byte size of one channel + u32 gsize; // size of data in bytes used for each write cycle + u32 qsize; // used for unpack parts, num of vectors that // will be decompressed from data for 1 cycle }; @@ -254,57 +252,45 @@ __forceinline static int _limit(int a, int max) static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int VIFdmanum) { const VIFUnpackFuncTable *unpack; - vifStruct *vif; - VIFregisters *vifRegs; + unpack = &VIFfuncTable[ unpackType ]; - if (VIFdmanum == 0) - { - vif = &vif0; - vifRegs = vif0Regs; - } - else - { - vif = &vif1; - vifRegs = vif1Regs; - } - switch (unpackType) { case 0x0: - vif->tag.addr += size * 4; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing S-32 skip, size = %d", size); break; case 0x1: - vif->tag.addr += size * 8; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing S-16 skip, size = %d", size); break; case 0x2: - vif->tag.addr += size * 16; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing S-8 skip, size = %d", size); break; case 0x4: - vif->tag.addr += size + ((size / unpack->gsize) * 8); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V2-32 skip, size = %d", size); break; case 0x5: - vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 8); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V2-16 skip, size = %d", size); break; case 0x6: - vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 8); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V2-8 skip, size = %d", size); break; case 0x8: - vif->tag.addr += size + ((size / unpack->gsize) * 4); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V3-32 skip, size = %d", size); break; case 0x9: - vif->tag.addr += (size * 2) + ((size / unpack->gsize) * 4); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V3-16 skip, size = %d", size); break; case 0xA: - vif->tag.addr += (size * 4) + ((size / unpack->gsize) * 4); + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V3-8 skip, size = %d", size); break; case 0xC: @@ -312,15 +298,15 @@ static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int VIFUNPACK_LOG("Processing V4-32 skip, size = %d, CL = %d, WL = %d", size, vif1Regs->cycle.cl, vif1Regs->cycle.wl); break; case 0xD: - vif->tag.addr += size * 2; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V4-16 skip, size = %d", size); break; case 0xE: - vif->tag.addr += size * 4; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V4-8 skip, size = %d", size); break; case 0xF: - vif->tag.addr += size * 8; + vif->tag.addr += (size / unpack->gsize) * 16; VIFUNPACK_LOG("Processing V4-5 skip, size = %d", size); break; default: @@ -328,87 +314,61 @@ static void ProcessMemSkip(int size, unsigned int unpackType, const unsigned int break; } - if ((vif->tag.addr & 0xf) == unpack->gsize) + //Append any skips in to the equasion + + if (vifRegs->cycle.cl > vifRegs->cycle.wl) { - vif->tag.addr += 16 - unpack->gsize; + VIFUNPACK_LOG("Old addr %x CL %x WL %x", vif->tag.addr, vifRegs->cycle.cl, vifRegs->cycle.wl); + vif->tag.addr += (size / (unpack->gsize*vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl)*16); + VIFUNPACK_LOG("New addr %x CL %x WL %x", vif->tag.addr, vifRegs->cycle.cl, vifRegs->cycle.wl); } + + //This is sorted out later + if((vif->tag.addr & 0xf) != (vifRegs->offset * 4)) + { + VIFUNPACK_LOG("addr aligned to %x", vif->tag.addr); + vif->tag.addr = (vif->tag.addr & ~0xf) + (vifRegs->offset * 4); + } + } -static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdmanum) +static int VIFalign(u32 *data, vifCode *v, unsigned int size, const unsigned int VIFdmanum) { u32 *dest; u32 unpackType; UNPACKFUNCTYPE func; const VIFUnpackFuncTable *ft; - vifStruct *vif; - VIFregisters *vifRegs; VURegs * VU; u8 *cdata = (u8*)data; + #ifdef _DEBUG u32 memsize = VIFdmanum ? 0x4000 : 0x1000; #endif - _mm_prefetch((char*)data, _MM_HINT_NTA); - if (VIFdmanum == 0) { VU = &VU0; - vif = &vif0; vifRegs = vif0Regs; assert(v->addr < memsize); } else { - VU = &VU1; - vif = &vif1; vifRegs = vif1Regs; assert(v->addr < memsize); - - if (vu1MicroIsSkipping()) - { - // don't process since the frame is dummy - vif->tag.addr += (size / (VIFfuncTable[ vif->cmd & 0xf ].gsize * vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16); - return; - } } dest = (u32*)(VU->Mem + v->addr); - VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x", - VIFdmanum, v->cmd & 0xf, v->size, size, v->addr); - -#ifdef _DEBUG - if (v->size != size) - { - VIF_LOG("*PCSX2*: warning v->size != size"); - } - - if ((v->addr + size*4) > memsize) - { - Console::Notice("*PCSX2*: fixme unpack overflow"); - Console::WriteLn("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x", - params VIFdmanum, v->cmd & 0xf, v->size, size, v->addr); - } -#endif + VIF_LOG("VIF%d UNPACK Align: Mode=%x, v->size=%d, size=%d, v->addr=%x v->num=%x", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr, vifRegs->num); // The unpack type unpackType = v->cmd & 0xf; - - if (size == 0) - { - VIFUNPACK_LOG("*PCSX2*: Unpack %x with size 0!! v->size = %d cl = %d, wl = %d, mode %d mask %x", v->cmd, v->size, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->mode, vifRegs->mask); - } - - _mm_prefetch((char*)data + 128, _MM_HINT_NTA); - _vifRegs = (VIFregisters*)vifRegs; - _vifMaskRegs = VIFdmanum ? g_vif1Masks : g_vif0Masks; - _vif = vif; - _vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; ft = &VIFfuncTable[ unpackType ]; - func = _vif->usn ? ft->funcU : ft->funcS; + func = vif->usn ? ft->funcU : ft->funcS; size <<= 2; @@ -416,56 +376,64 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma memsize = size; #endif - if (_vifRegs->offset > 0) - { - int destinc, unpacksize; + if(vif1Regs->offset != 0) + { + int unpacksize; + + //This is just to make sure the alignment isnt loopy on a split packet + if(vifRegs->offset != ((vif->tag.addr & 0xf) >> 2)) + { + DevCon::Error("Warning: Unpack alignment error"); + } VIFUNPACK_LOG("Aligning packet size = %d offset %d addr %x", size, vifRegs->offset, vif->tag.addr); - // SSE doesn't handle such small data - if (v->size != (size >> 2)) - ProcessMemSkip(size, unpackType, VIFdmanum); - - if (vifRegs->offset < (u32)ft->qsize) + if(((size / ft->dsize) + vifRegs->offset) < (u32)ft->qsize) + VIFUNPACK_LOG("Warning! Size needed to align %x size chunks available %x offset %x", ft->qsize - ((size / ft->dsize) + vifRegs->offset), vifRegs->offset); + + if (((u32)size / (u32)ft->dsize) < ((u32)ft->qsize - vifRegs->offset)) { - if (((u32)size / (u32)ft->dsize) < ((u32)ft->qsize - vifRegs->offset)) - { - Console::WriteLn("Wasn't enough left size/dsize = %x left to write %x", params(size / ft->dsize), (ft->qsize - vifRegs->offset)); - } + DevCon::Error("Wasn't enough left size/dsize = %x left to write %x", params(size / ft->dsize), (ft->qsize - vifRegs->offset)); + } unpacksize = min(((u32)size / (u32)ft->dsize), ((u32)ft->qsize - vifRegs->offset)); - } - else - { - unpacksize = 0; - Console::WriteLn("Unpack align offset = 0"); - } - destinc = (4 - ft->qsize) + unpacksize; + + VIFUNPACK_LOG("Increasing dest by %x from offset %x", (4 - ft->qsize) + unpacksize, vifRegs->offset); + func(dest, (u32*)cdata, unpacksize); size -= unpacksize * ft->dsize; - cdata += unpacksize * ft->dsize; - + vifRegs->num--; ++vif->cl; + if (vif->cl == vifRegs->cycle.wl) { if (vifRegs->cycle.cl != vifRegs->cycle.wl) - dest += ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + destinc; + { + vif->tag.addr += (((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + ((4 - ft->qsize) + unpacksize)) * 4; + //dest += ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + destinc; + } else - dest += destinc; + { + vif->tag.addr += ((4 - ft->qsize) + unpacksize) * 4; + //dest += destinc; + } vif->cl = 0; + VIFUNPACK_LOG("Aligning packet done size = %d offset %d addr %x", size, vifRegs->offset, vif->tag.addr); + return size >> 2; + } else { - dest += destinc; + vif->tag.addr += ((4 - ft->qsize) + unpacksize) * 4; + dest += (4 - ft->qsize) + unpacksize; + cdata += unpacksize * ft->dsize; + VIFUNPACK_LOG("Aligning packet done size = %d offset %d addr %x", size, vifRegs->offset, vif->tag.addr); } - VIFUNPACK_LOG("Aligning packet done size = %d offset %d addr %x", size, vifRegs->offset, vif->tag.addr); - } - else if (v->size != (size >> 2)) - ProcessMemSkip(size, unpackType, VIFdmanum); + - if (vifRegs->cycle.cl >= vifRegs->cycle.wl) // skipping write + if (vif->cl != 0) //Check alignment for SSE unpacks { #ifdef _DEBUG @@ -474,7 +442,7 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma int incdest; - if (vif->cl != 0) + if (vifRegs->cycle.cl >= vifRegs->cycle.wl) // skipping write { // continuation from last stream @@ -491,22 +459,119 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma if (vif->cl == vifRegs->cycle.wl) { dest += incdest; + vif->tag.addr += incdest * 4; vif->cl = 0; break; } dest += 4; + vif->tag.addr += 16; } - // have to update - _vifRow[0] = _vifRegs->r0; - _vifRow[1] = _vifRegs->r1; - _vifRow[2] = _vifRegs->r2; - _vifRow[3] = _vifRegs->r3; + if(vifRegs->mode == 2) + { + //Update the reg rows for SSE + vifRow = VIFdmanum ? g_vifRow1 : g_vifRow0; + vifRow[0] = vifRegs->r0; + vifRow[1] = vifRegs->r1; + vifRow[2] = vifRegs->r2; + vifRow[3] = vifRegs->r3; + } } + } + return size>>2; +} - if ((size >= ft->gsize) && !(v->addr&0xf)) + +static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned int VIFdmanum) +{ + u32 *dest; + u32 unpackType; + UNPACKFUNCTYPE func; + const VIFUnpackFuncTable *ft; + VURegs * VU; + u8 *cdata = (u8*)data; + u32 tempsize = 0; + +#ifdef _DEBUG + u32 memsize = VIFdmanum ? 0x4000 : 0x1000; +#endif + + _mm_prefetch((char*)data, _MM_HINT_NTA); + + if (VIFdmanum == 0) + { + VU = &VU0; + vifRegs = vif0Regs; + assert(v->addr < memsize); + } + else + { + + VU = &VU1; + vifRegs = vif1Regs; + assert(v->addr < memsize); + + if (vu1MicroIsSkipping()) + { + // don't process since the frame is dummy + vif->tag.addr += (size / (VIFfuncTable[ vif->cmd & 0xf ].gsize * vifRegs->cycle.wl)) * ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16); + return; + } + } + + dest = (u32*)(VU->Mem + v->addr); + + VIF_LOG("VIF%d UNPACK: Mode=%x, v->size=%d, size=%d, v->addr=%x v->num=%x", + VIFdmanum, v->cmd & 0xf, v->size, size, v->addr, vifRegs->num); + + VIFUNPACK_LOG("USN %x Masking %x Mask %x Mode %x CL %x WL %x Offset %x", vif->usn, (vifRegs->code & 0x10000000) >> 28, vifRegs->mask, vifRegs->mode, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->offset); + + // The unpack type + unpackType = v->cmd & 0xf; + + _mm_prefetch((char*)data + 128, _MM_HINT_NTA); + + ft = &VIFfuncTable[ unpackType ]; + func = vif->usn ? ft->funcU : ft->funcS; + + size <<= 2; + +#ifdef _DEBUG + memsize = size; +#endif + + if (vifRegs->cycle.cl >= vifRegs->cycle.wl) // skipping write + { + +#ifdef _DEBUG + static int s_count = 0; +#endif + + tempsize = (vif->tag.addr + (size / (ft->gsize * vifRegs->cycle.wl)) * + ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16)) + ((size / ft->gsize) * 16); + + //Sanity Check (memory overflow) + if(tempsize > (u32)(VIFdmanum ? 0x4000 : 0x1000)) + { + + //DevCon::Notice("VIF%x Unpack ending %x > %x", params VIFdmanum, tempsize, VIFdmanum ? 0x4000 : 0x1000); + if(vifRegs->cycle.cl == 1 && ((u32)(VIFdmanum ? 0x4000 : 0x1000) + ((vifRegs->cycle.cl - vifRegs->cycle.wl) * 16)) == tempsize + || tempsize == (u32)(VIFdmanum ? 0x4000 : 0x1000)) + { + //Its a red herring! so ignore it! SSE unpacks will be much quicker + tempsize = 0; + } + else + { + tempsize = size; + size = 0; + } + } else tempsize = 0; + + + if (size >= ft->gsize) { const UNPACKPARTFUNCTYPESSE* pfn; int writemask; @@ -554,6 +619,16 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma if (oldcycle != -1) *(u32*)&vifRegs->cycle = oldcycle; + if(vifRegs->mode == 2) + { + //Update the reg rows for non SSE + vifRegs->r0 = vifRow[0]; + vifRegs->r1 = vifRow[1]; + vifRegs->r2 = vifRow[2]; + vifRegs->r3 = vifRow[3]; + } + + // if size is left over, update the src,dst pointers if (writemask > 0) { @@ -561,107 +636,107 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma cdata += left * ft->gsize; dest = (u32*)((u8*)dest + ((left / vifRegs->cycle.wl) * vifRegs->cycle.cl + left % vifRegs->cycle.wl) * 16); vifRegs->num -= left; - _vif->cl = (size % (ft->gsize * vifRegs->cycle.wl)) / ft->gsize; + vif->cl = (size % (ft->gsize * vifRegs->cycle.wl)) / ft->gsize; + size = writemask; + + if (size >= ft->dsize && vifRegs->num > 0) + { + //VIF_LOG("warning, end with size = %d", size); + + /* unpack one qword */ + //vif->tag.addr += (size / ft->dsize) * 4; + func(dest, (u32*)cdata, size / ft->dsize); + size = 0; + + if(vifRegs->mode == 2) + { + //Update the reg rows for SSE + vifRow[0] = vifRegs->r0; + vifRow[1] = vifRegs->r1; + vifRow[2] = vifRegs->r2; + vifRow[3] = vifRegs->r3; + } + VIFUNPACK_LOG("leftover done, size %d, vifnum %d, addr %x", size, vifRegs->num, vif->tag.addr); + } } else { vifRegs->num -= size / ft->gsize; - if (vifRegs->num > 0) _vif->cl = (size % (ft->gsize * vifRegs->cycle.wl)) / ft->gsize; + if (vifRegs->num > 0) vif->cl = (size % (ft->gsize * vifRegs->cycle.wl)) / ft->gsize; + size = 0; } - size = writemask; - - _vifRegs->r0 = _vifRow[0]; - _vifRegs->r1 = _vifRow[1]; - _vifRegs->r2 = _vifRow[2]; - _vifRegs->r3 = _vifRow[3]; - } - else + } + else if(tempsize) { - - if ((unpackType == 0xC) && (vifRegs->cycle.cl == vifRegs->cycle.wl)) //No use when SSE is available - { - // v4-32 - if ((vifRegs->mode == 0) && !(vifRegs->code & 0x10000000) && (vif->usn == 0)) - { - vifRegs->num -= size >> 4; - memcpy_fast((u8*)dest, cdata, size); - size = 0; - return; - } - } - - incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + 4; - - while ((size >= ft->gsize) && (vifRegs->num > 0)) + int incdest = ((vifRegs->cycle.cl - vifRegs->cycle.wl) << 2) + 4; + size = 0; + + + while ((tempsize >= ft->gsize) && (vifRegs->num > 0)) { + //VIFUNPACK_LOG("sorting tempsize :p, size %d, vifnum %d, addr %x", tempsize, vifRegs->num, vif->tag.addr); func(dest, (u32*)cdata, ft->qsize); cdata += ft->gsize; - size -= ft->gsize; + tempsize -= ft->gsize; vifRegs->num--; ++vif->cl; if (vif->cl == vifRegs->cycle.wl) { dest += incdest; + v->addr = (v->addr + (incdest * 4)) & (VIFdmanum ? 0x3fff : 0xfff); + if(v->addr <= (u32)(VIFdmanum ? 0x3000 : 0x500)) dest = (u32*)(VU->Mem + v->addr); vif->cl = 0; } else { dest += 4; + v->addr = (v->addr + 16) & (VIFdmanum ? 0x3fff : 0xfff); + if(v->addr <= (u32)(VIFdmanum ? 0x3000 : 0x500)) dest = (u32*)(VU->Mem + v->addr); } } - // have to update - _vifRow[0] = _vifRegs->r0; - _vifRow[1] = _vifRegs->r1; - _vifRow[2] = _vifRegs->r2; - _vifRow[3] = _vifRegs->r3; + if(vifRegs->mode == 2) + { + //Update the reg rows for SSE + vifRow[0] = vifRegs->r0; + vifRow[1] = vifRegs->r1; + vifRow[2] = vifRegs->r2; + vifRow[3] = vifRegs->r3; + } + if(tempsize > 0) size = tempsize; + } - - // used for debugging vif -// { -// int i, j, k; -// u32* curdest = olddest; -// FILE* ftemp = fopen("temp.txt", s_count?"a+":"w"); -// fprintf(ftemp, "%x %x %x\n", s_count, size, vif->tag.addr); -// fprintf(ftemp, "%x %x %x\n", vifRegs->code>>24, vifRegs->mode, *(u32*)&vifRegs->cycle); -// fprintf(ftemp, "row: %x %x %x %x\n", _vifRow[0], _vifRow[1], _vifRow[2], _vifRow[3]); -// //fprintf(ftemp, "row2: %x %x %x %x\n", _vifRegs->r0, _vifRegs->r1, _vifRegs->r2, _vifRegs->r3); -// -// for(i = 0; i < memsize; ) { -// for(k = 0; k < vifRegs->cycle.wl; ++k) { -// for(j = 0; j <= ((vifRegs->code>>26)&3); ++j) { -// fprintf(ftemp, "%x ", curdest[4*k+j]); -// } -// } -// -// fprintf(ftemp, "\n"); -// curdest += 4*vifRegs->cycle.cl; -// i += (((vifRegs->code>>26)&3)+1)*ft->dsize*vifRegs->cycle.wl; -// } -// fclose(ftemp); -// } -// s_count++; - - if (size >= ft->dsize && vifRegs->num > 0) + if (size >= ft->dsize && vifRegs->num > 0) //Else write what we do have { //VIF_LOG("warning, end with size = %d", size); /* unpack one qword */ + //vif->tag.addr += (size / ft->dsize) * 4; func(dest, (u32*)cdata, size / ft->dsize); size = 0; + if(vifRegs->mode == 2) + { + //Update the reg rows for SSE + vifRow[0] = vifRegs->r0; + vifRow[1] = vifRegs->r1; + vifRow[2] = vifRegs->r2; + vifRow[3] = vifRegs->r3; + } VIFUNPACK_LOG("leftover done, size %d, vifnum %d, addr %x", size, vifRegs->num, vif->tag.addr); } - } else /* filling write */ { - VIF_LOG("VIFunpack - filling write"); + if(vifRegs->cycle.cl > 0) // Quicker and avoids zero division :P + if((u32)(((size / ft->gsize) / vifRegs->cycle.cl) * vifRegs->cycle.wl) < vifRegs->num) + DevCon::Notice("Filling write warning! %x < %x and CL = %x WL = %x", params (size / ft->gsize), vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl); + VIFUNPACK_LOG("filling write %d cl %d, wl %d mask %x mode %x unpacktype %x", vifRegs->num, vifRegs->cycle.cl, vifRegs->cycle.wl, vifRegs->mask, vifRegs->mode, unpackType); - while (size >= ft->gsize || vifRegs->num > 0) + while (vifRegs->num > 0) { if (vif->cl == vifRegs->cycle.wl) { @@ -670,6 +745,11 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma if (vif->cl < vifRegs->cycle.cl) /* unpack one qword */ { + if(size < ft->gsize) + { + VIF_LOG("Out of Filling write data"); + break; + } func(dest, (u32*)cdata, ft->qsize); cdata += ft->gsize; size -= ft->gsize; @@ -678,7 +758,7 @@ static void VIFunpack(u32 *data, vifCode *v, int size, const unsigned int VIFdma if (vif->cl == vifRegs->cycle.wl) { vif->cl = 0; - } + } } else { @@ -786,17 +866,20 @@ static __forceinline void vif0UNPACK(u32 *data) len = ((((32 >> vl) * (vn + 1)) * n) + 31) >> 5; } - vif0.wl = 0; vif0.cl = 0; vif0.tag.cmd = vif0.cmd; vif0.tag.addr &= 0xfff; vif0.tag.size = len; vif0Regs->offset = 0; + + vifMaskRegs = g_vif0Masks; + vif = &vif0; + vifRow = g_vifRow0; } -static __forceinline void _vif0mpgTransfer(u32 addr, u32 *data, int size) +static __forceinline void vif0mpgTransfer(u32 addr, u32 *data, int size) { - /* Console::WriteLn("_vif0mpgTransfer addr=%x; size=%x", params addr, size); + /* Console::WriteLn("vif0mpgTransfer addr=%x; size=%x", params addr, size); { FILE *f = fopen("vu1.raw", "wb"); fwrite(data, 1, size*4, f); @@ -900,7 +983,7 @@ static int __fastcall Vif0TransMPG(u32 *data) // MPG { if (vif0.vifpacketsize < vif0.tag.size) { - _vif0mpgTransfer(vif0.tag.addr, data, vif0.vifpacketsize); + vif0mpgTransfer(vif0.tag.addr, data, vif0.vifpacketsize); vif0.tag.addr += vif0.vifpacketsize << 2; vif0.tag.size -= vif0.vifpacketsize; return vif0.vifpacketsize; @@ -909,7 +992,7 @@ static int __fastcall Vif0TransMPG(u32 *data) // MPG { int ret; - _vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); + vif0mpgTransfer(vif0.tag.addr, data, vif0.tag.size); ret = vif0.tag.size; vif0.tag.size = 0; vif0.cmd = 0; @@ -919,27 +1002,54 @@ static int __fastcall Vif0TransMPG(u32 *data) // MPG static int __fastcall Vif0TransUnpack(u32 *data) // UNPACK { + int ret; + FreezeXMMRegs(1); if (vif0.vifpacketsize < vif0.tag.size) { + if(vif0Regs->offset != 0 || vif0.cl != 0) + { + ret = vif0.tag.size; + vif0.tag.size -= vif0.vifpacketsize - VIFalign(data, &vif0.tag, vif0.vifpacketsize, VIF0dmanum); + ret = ret - vif0.tag.size; + data += ret; + if(vif0.vifpacketsize > 0) VIFunpack(data, &vif0.tag, vif0.vifpacketsize - ret, VIF0dmanum); + ProcessMemSkip((vif0.vifpacketsize - ret) << 2, (vif0.cmd & 0xf), VIF0dmanum); + vif0.tag.size -= (vif0.vifpacketsize - ret); + FreezeXMMRegs(0); + return vif0.vifpacketsize; + } /* size is less that the total size, transfer is 'in pieces' */ VIFunpack(data, &vif0.tag, vif0.vifpacketsize, VIF0dmanum); - vif0.tag.size -= vif0.vifpacketsize; - FreezeXMMRegs(0); - return vif0.vifpacketsize; + + ProcessMemSkip(vif0.vifpacketsize << 2, (vif0.cmd & 0xf), VIF0dmanum); + + ret = vif0.vifpacketsize; + vif0.tag.size -= ret; } else { /* we got all the data, transfer it fully */ - int ret; - - VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); ret = vif0.tag.size; + + //Align data after a split transfer first + if ((vif0Regs->offset != 0) || (vif0.cl != 0)) + { + vif0.tag.size = VIFalign(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + data += ret - vif0.tag.size; + if(vif0.tag.size > 0) VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + } + else + { + VIFunpack(data, &vif0.tag, vif0.tag.size, VIF0dmanum); + } + vif0.tag.size = 0; vif0.cmd = 0; - FreezeXMMRegs(0); - return ret; } + + FreezeXMMRegs(0); + return ret; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1034,8 +1144,8 @@ int VIF0transfer(u32 *data, int size, int istag) int transferred = vif0.vifstalled ? vif0.irqoffset : 0; // irqoffset necessary to add up the right qws, or else will spin (spiderman) VIF_LOG("VIF0transfer: size %x (vif0.cmd %x)", size, vif0.cmd); - vif0.stallontag = 0; - vif0.vifstalled = 0; + vif0.stallontag = false; + vif0.vifstalled = false; vif0.vifpacketsize = size; while (vif0.vifpacketsize > 0) @@ -1097,7 +1207,7 @@ int VIF0transfer(u32 *data, int size, int istag) ++vif0.irq; - if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = 1; + if (istag && vif0.tag.size <= vif0.vifpacketsize) vif0.stallontag = true; if (vif0.tag.size == 0) break; } @@ -1111,7 +1221,7 @@ int VIF0transfer(u32 *data, int size, int istag) if (vif0.irq && (vif0.tag.size == 0)) { - vif0.vifstalled = 1; + vif0.vifstalled = true; if (((vif0Regs->code >> 24) & 0x7f) != 0x7)vif0Regs->stat |= VIF0_STAT_VIS; //else Console::WriteLn("VIF0 IRQ on MARK"); @@ -1147,7 +1257,7 @@ int _VIF0chain() u32 *pMem; u32 ret; - if (vif0ch->qwc == 0 && vif0.vifstalled == 0) return 0; + if ((vif0ch->qwc == 0) && !vif0.vifstalled) return 0; pMem = (u32*)dmaGetAddr(vif0ch->madr); if (pMem == NULL) return -1; @@ -1185,8 +1295,10 @@ int _chainVIF0() if (vif0ch->chcr & 0x40) { - if (vif0.vifstalled == 1) ret = VIF0transfer(vif0ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, 1); //Transfer Tag on stall - else ret = VIF0transfer(vif0ptag + 2, 2, 1); //Transfer Tag + if (vif0.vifstalled) + ret = VIF0transfer(vif0ptag + (2 + vif0.irqoffset), 2 - vif0.irqoffset, 1); //Transfer Tag on stall + else + ret = VIF0transfer(vif0ptag + 2, 2, 1); //Transfer Tag if (ret == -1) return -1; //There has been an error if (ret == -2) return -2; //IRQ set by VIFTransfer } @@ -1202,10 +1314,10 @@ int _chainVIF0() { VIF_LOG("dmaIrq Set\n"); - vif0.done = 1; - return vif0.done; //End Transfer + vif0.done = true; + return (vif0.done)?1:0; //End Transfer } - return vif0.done; //Return Done + return (vif0.done)?1:0; //Return Done } void vif0Interrupt() @@ -1227,7 +1339,7 @@ void vif0Interrupt() } if (vif0ch->qwc > 0 || vif0.irqoffset > 0) { - if (vif0.stallontag == 1) + if (vif0.stallontag) _chainVIF0(); else _VIF0chain(); @@ -1239,7 +1351,7 @@ void vif0Interrupt() if ((vif0ch->chcr & 0x100) == 0) Console::WriteLn("Vif0 running when CHCR = %x", params vif0ch->chcr); - if ((vif0ch->chcr & 0x4) && (vif0.done == 0) && (vif0.vifstalled == 0)) + if ((vif0ch->chcr & 0x4) && (!vif0.done) && (!vif0.vifstalled)) { if (!(psHu32(DMAC_CTRL) & 0x1)) @@ -1316,16 +1428,16 @@ void dmaVIF0() if (_VIF0chain() == -2) { Console::WriteLn("Stall on normal %x", params vif0Regs->stat); - vif0.vifstalled = 1; + vif0.vifstalled = true; return; } - vif0.done = 1; + vif0.done = true; CPU_INT(0, g_vifCycles); return; } // Chain Mode - vif0.done = 0; + vif0.done = false; CPU_INT(0, 0); } @@ -1353,7 +1465,7 @@ void vif0Write32(u32 mem, u32 value) cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's psHu64(0x10004000) = 0; psHu64(0x10004008) = 0; - vif0.done = 1; + vif0.done = true; vif0Regs->err = 0; vif0Regs->stat &= ~(0xF000000 | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0 } @@ -1364,7 +1476,7 @@ void vif0Write32(u32 mem, u32 value) cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's vif0Regs->stat |= VIF0_STAT_VFS; vif0Regs->stat &= ~VIF0_STAT_VPS; - vif0.vifstalled = 1; + vif0.vifstalled = true; Console::WriteLn("vif0 force break"); } if (value & 0x4) @@ -1374,15 +1486,15 @@ void vif0Write32(u32 mem, u32 value) // just stoppin the VIF (linuz). vif0Regs->stat |= VIF0_STAT_VSS; vif0Regs->stat &= ~VIF0_STAT_VPS; - vif0.vifstalled = 1; + vif0.vifstalled = true; } if (value & 0x8) { - bool cancel = FALSE; + bool cancel = false; /* Cancel stall, first check if there is a stall to cancel, and then clear VIF0_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ if (vif0Regs->stat & (VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS)) - cancel = TRUE; + cancel = true; vif0Regs->stat &= ~(VIF0_STAT_VSS | VIF0_STAT_VFS | VIF0_STAT_VIS | VIF0_STAT_INT | VIF0_STAT_ER0 | VIF0_STAT_ER1); @@ -1393,7 +1505,7 @@ void vif0Write32(u32 mem, u32 value) g_vifCycles = 0; // loop necessary for spiderman - if (vif0.stallontag == 1) + if (vif0.stallontag) _chainVIF0(); else _VIF0chain(); @@ -1443,7 +1555,7 @@ void vif0Reset() psHu64(0x10004000) = 0; psHu64(0x10004008) = 0; vif0Regs->stat &= ~VIF0_STAT_VPS; - vif0.done = 1; + vif0.done = true; vif0Regs->stat &= ~0xF000000; // FQC=0 } @@ -1516,15 +1628,19 @@ static __forceinline void vif1UNPACK(u32 *data) else vif1.tag.addr = vif1Regs->code & 0x3ff; + vif1Regs->offset = 0; vif1.cl = 0; vif1.tag.addr <<= 4; - vif1.tag.cmd = vif1.cmd; + + vifMaskRegs = g_vif1Masks; + vif = &vif1; + vifRow = g_vifRow1; } -static __forceinline void _vif1mpgTransfer(u32 addr, u32 *data, int size) +static __forceinline void vif1mpgTransfer(u32 addr, u32 *data, int size) { - /* Console::WriteLn("_vif1mpgTransfer addr=%x; size=%x", params addr, size); + /* Console::WriteLn("vif1mpgTransfer addr=%x; size=%x", params addr, size); { FILE *f = fopen("vu1.raw", "wb"); fwrite(data, 1, size*4, f); @@ -1626,7 +1742,7 @@ static int __fastcall Vif1TransMPG(u32 *data) { if (vif1.vifpacketsize < vif1.tag.size) { - _vif1mpgTransfer(vif1.tag.addr, data, vif1.vifpacketsize); + vif1mpgTransfer(vif1.tag.addr, data, vif1.vifpacketsize); vif1.tag.addr += vif1.vifpacketsize << 2; vif1.tag.size -= vif1.vifpacketsize; return vif1.vifpacketsize; @@ -1634,15 +1750,13 @@ static int __fastcall Vif1TransMPG(u32 *data) else { int ret; - _vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); + vif1mpgTransfer(vif1.tag.addr, data, vif1.tag.size); ret = vif1.tag.size; vif1.tag.size = 0; vif1.cmd = 0; return ret; } } -u32 splittransfer[4]; -u32 splitptr = 0; static int __fastcall Vif1TransDirectHL(u32 *data) { @@ -1732,23 +1846,50 @@ static int __fastcall Vif1TransUnpack(u32 *data) if (vif1.vifpacketsize < vif1.tag.size) { + int ret = vif1.tag.size; /* size is less that the total size, transfer is 'in pieces' */ + if(vif1Regs->offset != 0 || vif1.cl != 0) + { + vif1.tag.size -= vif1.vifpacketsize - VIFalign(data, &vif1.tag, vif1.vifpacketsize, VIF1dmanum); + ret = ret - vif1.tag.size; + data += ret; + if((vif1.vifpacketsize - ret) > 0) VIFunpack(data, &vif1.tag, vif1.vifpacketsize - ret, VIF1dmanum); + ProcessMemSkip((vif1.vifpacketsize - ret) << 2, (vif1.cmd & 0xf), VIF1dmanum); + vif1.tag.size -= (vif1.vifpacketsize - ret); + FreezeXMMRegs(0); + return vif1.vifpacketsize; + } VIFunpack(data, &vif1.tag, vif1.vifpacketsize, VIF1dmanum); + + ProcessMemSkip(vif1.vifpacketsize << 2, (vif1.cmd & 0xf), VIF1dmanum); vif1.tag.size -= vif1.vifpacketsize; FreezeXMMRegs(0); return vif1.vifpacketsize; } else { - int ret; - /* we got all the data, transfer it fully */ - VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); - ret = vif1.tag.size; - vif1.tag.size = 0; - vif1.cmd = 0; - FreezeXMMRegs(0); - return ret; + int ret = vif1.tag.size; + + if(vif1Regs->offset != 0 || vif1.cl != 0) + { + vif1.tag.size = VIFalign(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + data += ret - vif1.tag.size; + if(vif1.tag.size > 0) VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + vif1.tag.size = 0; + vif1.cmd = 0; + FreezeXMMRegs(0); + return ret; + } + else + { + /* we got all the data, transfer it fully */ + VIFunpack(data, &vif1.tag, vif1.tag.size, VIF1dmanum); + vif1.tag.size = 0; + vif1.cmd = 0; + FreezeXMMRegs(0); + return ret; + } } } @@ -1963,8 +2104,8 @@ int VIF1transfer(u32 *data, int size, int istag) VIF_LOG("VIF1transfer: size %x (vif1.cmd %x)", size, vif1.cmd); vif1.irqoffset = 0; - vif1.vifstalled = 0; - vif1.stallontag = 0; + vif1.vifstalled = false; + vif1.stallontag = false; vif1.vifpacketsize = size; while (vif1.vifpacketsize > 0) @@ -2022,7 +2163,7 @@ int VIF1transfer(u32 *data, int size, int istag) ++vif1.irq; - if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = 1; + if (istag && vif1.tag.size <= vif1.vifpacketsize) vif1.stallontag = true; if (vif1.tag.size == 0) break; } @@ -2036,7 +2177,7 @@ int VIF1transfer(u32 *data, int size, int istag) if (vif1.irq && vif1.cmd == 0) { - vif1.vifstalled = 1; + vif1.vifstalled = true; if (((vif1Regs->code >> 24) & 0x7f) != 0x7)vif1Regs->stat |= VIF1_STAT_VIS; // Note: commenting this out fixes WALL-E @@ -2081,7 +2222,7 @@ void vif1TransferFromMemory() { Console::WriteLn("Vif1 Tag BUSERR"); psHu32(DMAC_STAT) |= 1 << 15; //If yes, set BEIS (BUSERR) in DMAC_STAT register - vif1.done = 1; + vif1.done = true; vif1Regs->stat &= ~0x1f000000; vif1ch->qwc = 0; CPU_INT(1, 0); @@ -2157,7 +2298,7 @@ int _VIF1chain() return ret; } -int _chainVIF1() +bool _chainVIF1() { return vif1.done;//Return Done } @@ -2169,7 +2310,7 @@ __forceinline void vif1SetupTransfer() case 0: //Normal case 1: //Normal (From memory) vif1.inprogress = 1; - vif1.done = 1; + vif1.done = true; break; case 2: //Chain @@ -2214,7 +2355,7 @@ __forceinline void vif1SetupTransfer() if (vif1ch->chcr & 0x40) { - if (vif1.vifstalled == 1) + if (vif1.vifstalled) ret = VIF1transfer(vif1ptag + (2 + vif1.irqoffset), 2 - vif1.irqoffset, 1); //Transfer Tag on stall else ret = VIF1transfer(vif1ptag + 2, 2, 1); //Transfer Tag @@ -2233,7 +2374,7 @@ __forceinline void vif1SetupTransfer() { VIF_LOG("dmaIrq Set"); - vif1.done = 1; + vif1.done = true; return; //End Transfer } break; @@ -2263,16 +2404,16 @@ __forceinline void vif1Interrupt() } else if ((vif1ch->qwc > 0) || (vif1.irqoffset > 0)) { - if (vif1.stallontag == 1) + if (vif1.stallontag) vif1SetupTransfer(); else _VIF1chain();//CPU_INT(13, vif1ch->qwc * BIAS); } } - if (vif1.inprogress == 1) _VIF1chain(); + if (vif1.inprogress) _VIF1chain(); - if ((vif1.done == 0) || (vif1.inprogress == 1)) + if ((!vif1.done) || (vif1.inprogress & 0x1)) { if (!(psHu32(DMAC_CTRL) & 0x1)) @@ -2281,13 +2422,13 @@ __forceinline void vif1Interrupt() return; } - if (vif1.inprogress == 0) vif1SetupTransfer(); + if ((vif1.inprogress & 0x1) == 0) vif1SetupTransfer(); CPU_INT(1, vif1ch->qwc * BIAS); return; } - if(vif1.vifstalled && vif1.irq) + if (vif1.vifstalled && vif1.irq) { CPU_INT(1, 0); return; //Dont want to end if vif is stalled. @@ -2303,7 +2444,6 @@ __forceinline void vif1Interrupt() if (vif1Regs->mskpath3 == 0 || (vif1ch->chcr & 0x1) == 0x1)vif1Regs->stat &= ~0x1F000000; // FQC=0 } -#define spr0 ((DMACh*)&PS2MEM_HW[0xD000]) void dmaVIF1() { @@ -2319,7 +2459,7 @@ void dmaVIF1() if (((psHu32(DMAC_CTRL) & 0xC) == 0x8)) // VIF MFIFO { -// Console::WriteLn("VIFMFIFO\n"); + //Console::WriteLn("VIFMFIFO\n"); if (!(vif1ch->chcr & 0x4)) Console::WriteLn("MFIFO mode != Chain! %x", params vif1ch->chcr); vifMFIFOInterrupt(); return; @@ -2350,7 +2490,7 @@ void dmaVIF1() } // Chain Mode - vif1.done = 0; + vif1.done = false; CPU_INT(1, 0); } @@ -2378,7 +2518,7 @@ void vif1Write32(u32 mem, u32 value) vif1ch->qwc = 0; //? psHu64(0x10005000) = 0; psHu64(0x10005008) = 0; - vif1.done = 1; + vif1.done = true; vif1Regs->err = 0; vif1.inprogress = 0; vif1Regs->stat &= ~(0x1F800000 | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); // FQC=0 @@ -2390,7 +2530,7 @@ void vif1Write32(u32 mem, u32 value) vif1Regs->stat |= VIF1_STAT_VFS; vif1Regs->stat &= ~VIF1_STAT_VPS; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1.vifstalled = 1; + vif1.vifstalled = true; Console::WriteLn("vif1 force break"); } if (value & 0x4) @@ -2401,16 +2541,16 @@ void vif1Write32(u32 mem, u32 value) vif1Regs->stat |= VIF1_STAT_VSS; vif1Regs->stat &= ~VIF1_STAT_VPS; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's - vif1.vifstalled = 1; + vif1.vifstalled = true; } if (value & 0x8) { - bool cancel = FALSE; + bool cancel = false; /* Cancel stall, first check if there is a stall to cancel, and then clear VIF1_STAT VSS|VFS|VIS|INT|ER0|ER1 bits */ if (vif1Regs->stat & (VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS)) { - cancel = TRUE; + cancel = true; } vif1Regs->stat &= ~(VIF1_STAT_VSS | VIF1_STAT_VFS | VIF1_STAT_VIS | @@ -2468,8 +2608,8 @@ void vif1Write32(u32 mem, u32 value) else { vif1ch->qwc = 0; - vif1.vifstalled = 0; - vif1.done = 1; + vif1.vifstalled = false; + vif1.done = true; vif1Regs->stat &= ~0x1F000000; // FQC=0 } break; @@ -2507,7 +2647,7 @@ void vif1Reset() psHu64(0x10005000) = 0; psHu64(0x10005008) = 0; vif1Regs->stat &= ~VIF1_STAT_VPS; - vif1.done = 1; + vif1.done = true; cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's vif1Regs->stat &= ~0x1F000000; // FQC=0 } diff --git a/pcsx2/VifDma.h b/pcsx2/VifDma.h index a7fed1c30b..21d45e4a4e 100644 --- a/pcsx2/VifDma.h +++ b/pcsx2/VifDma.h @@ -32,16 +32,15 @@ struct vifStruct { int cmd; int irq; int cl; - int wl; + int qwcalign; u8 usn; - // The next three should be boolean, and will be next time I break savestate compatability. --arcum42 - u8 done; - u8 vifstalled; - u8 stallontag; + bool done; + bool vifstalled; + bool stallontag; u8 irqoffset; // 32bit offset where next vif code is - u32 savedtag; // need this for backwards compat with save states + u32 savedtag; // need this for backwards compat with save states u32 vifpacketsize; u8 inprogress; u8 dmamode; @@ -50,9 +49,6 @@ struct vifStruct { extern vifStruct vif0, vif1; extern bool Path3transfer; -#define vif0ch ((DMACh*)&PS2MEM_HW[0x8000]) -#define vif1ch ((DMACh*)&PS2MEM_HW[0x9000]) - void __fastcall UNPACK_S_32( u32 *dest, u32 *data, int size ); void __fastcall UNPACK_S_16u( u32 *dest, u32 *data, int size ); diff --git a/pcsx2/vssprintf.cpp b/pcsx2/vssprintf.cpp index 7657683e54..234017f0e1 100644 --- a/pcsx2/vssprintf.cpp +++ b/pcsx2/vssprintf.cpp @@ -460,7 +460,7 @@ static void cropzeros(char *buffer) stop = buffer--; while (*buffer == '0') buffer--; if (*buffer == '.') buffer--; - while (*++buffer = *stop++) ; + while (*++buffer = *stop++); } } diff --git a/pcsx2/windows/HacksDlg.cpp b/pcsx2/windows/HacksDlg.cpp deleted file mode 100644 index 045705f6bd..0000000000 --- a/pcsx2/windows/HacksDlg.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* 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 - */ - - -#include "win32.h" - -BOOL APIENTRY HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: - - CheckRadioButton( hDlg, IDC_EESYNC_DEFAULT, IDC_EESYNC3, IDC_EESYNC_DEFAULT + CHECK_EE_CYCLERATE ); - - if(CHECK_IOP_CYCLERATE) CheckDlgButton(hDlg, IDC_IOPSYNC, TRUE); - if(CHECK_WAITCYCLE_HACK) CheckDlgButton(hDlg, IDC_WAITCYCLES, TRUE); - if(CHECK_INTC_STAT_HACK) CheckDlgButton(hDlg, IDC_INTCSTATHACK, TRUE); - if(CHECK_ESCAPE_HACK) CheckDlgButton(hDlg, IDC_ESCHACK, TRUE); - - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - { - int newhacks = 0; - for( int i=1; i<4; i++ ) - { - if( IsDlgButtonChecked(hDlg, IDC_EESYNC_DEFAULT+i) ) - { - newhacks = i; - break; - } - } - - newhacks |= IsDlgButtonChecked(hDlg, IDC_IOPSYNC) << 3; - newhacks |= IsDlgButtonChecked(hDlg, IDC_WAITCYCLES) << 4; - newhacks |= IsDlgButtonChecked(hDlg, IDC_INTCSTATHACK) << 5; - newhacks |= IsDlgButtonChecked(hDlg, IDC_ESCHACK) << 10; - - EndDialog(hDlg, TRUE); - - if( newhacks != Config.Hacks ) - { - SysRestorableReset(); - Config.Hacks = newhacks; - SaveConfig(); - } - } - return FALSE; - - case IDCANCEL: - EndDialog(hDlg, FALSE); - return FALSE; - } - return TRUE; - } - - return FALSE; -} diff --git a/pcsx2/windows/HostSys.cpp b/pcsx2/windows/HostSys.cpp new file mode 100644 index 0000000000..5f39743845 --- /dev/null +++ b/pcsx2/windows/HostSys.cpp @@ -0,0 +1,59 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "Win32.h" +#include + +namespace HostSys +{ + void *Mmap(uptr base, u32 size) + { + return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); + } + + void Munmap(uptr base, u32 size) + { + if( base == NULL ) return; + VirtualFree((void*)base, size, MEM_DECOMMIT); + VirtualFree((void*)base, 0, MEM_RELEASE); + } + + void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution ) + { + DWORD winmode = 0; + + switch( mode ) + { + case Protect_NoAccess: + winmode = ( allowExecution ) ? PAGE_EXECUTE : PAGE_NOACCESS; + break; + + case Protect_ReadOnly: + winmode = ( allowExecution ) ? PAGE_EXECUTE_READ : PAGE_READONLY; + break; + + case Protect_ReadWrite: + winmode = ( allowExecution ) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; + break; + } + + DWORD OldProtect; // enjoy my uselessness, yo! + VirtualProtect( baseaddr, size, winmode, &OldProtect ); + } +} diff --git a/pcsx2/windows/Hyperlinks.cpp b/pcsx2/windows/Hyperlinks.cpp deleted file mode 100644 index 4f72d379e8..0000000000 --- a/pcsx2/windows/Hyperlinks.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// Hyperlinks.cpp -// -// Copyright 2002 Neal Stublen -// All rights reserved. -// -// http://www.awesoftware.com -// - -// This taken as found on Codeguru: http://www.codeguru.com/cpp/controls/staticctrl/article.php/c5803 - -#include "Win32.h" -#include "Hyperlinks.h" - - -#define PROP_ORIGINAL_FONT TEXT("_Hyperlink_Original_Font_") -#define PROP_ORIGINAL_PROC TEXT("_Hyperlink_Original_Proc_") -#define PROP_STATIC_HYPERLINK TEXT("_Hyperlink_From_Static_") -#define PROP_UNDERLINE_FONT TEXT("_Hyperlink_Underline_Font_") - - -LRESULT CALLBACK _HyperlinkParentProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC pfnOrigProc = (WNDPROC) GetProp(hwnd, PROP_ORIGINAL_PROC); - - switch (message) - { - case WM_CTLCOLORSTATIC: - { - HDC hdc = (HDC) wParam; - HWND hwndCtl = (HWND) lParam; - - BOOL fHyperlink = (NULL != GetProp(hwndCtl, PROP_STATIC_HYPERLINK)); - if (fHyperlink) - { - LRESULT lr = CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam); - SetTextColor(hdc, RGB(0, 0, 192)); - return lr; - } - - break; - } - case WM_DESTROY: - { - SetWindowLong(hwnd, GWL_WNDPROC, (LONG) pfnOrigProc); - RemoveProp(hwnd, PROP_ORIGINAL_PROC); - break; - } - } - return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam); -} - -LRESULT CALLBACK _HyperlinkProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - WNDPROC pfnOrigProc = (WNDPROC) GetProp(hwnd, PROP_ORIGINAL_PROC); - - switch (message) - { - case WM_DESTROY: - { - SetWindowLong(hwnd, GWL_WNDPROC, (LONG) pfnOrigProc); - RemoveProp(hwnd, PROP_ORIGINAL_PROC); - - HFONT hOrigFont = (HFONT) GetProp(hwnd, PROP_ORIGINAL_FONT); - SendMessage(hwnd, WM_SETFONT, (WPARAM) hOrigFont, 0); - RemoveProp(hwnd, PROP_ORIGINAL_FONT); - - HFONT hFont = (HFONT) GetProp(hwnd, PROP_UNDERLINE_FONT); - DeleteObject(hFont); - RemoveProp(hwnd, PROP_UNDERLINE_FONT); - - RemoveProp(hwnd, PROP_STATIC_HYPERLINK); - - break; - } - case WM_MOUSEMOVE: - { - if (GetCapture() != hwnd) - { - HFONT hFont = (HFONT) GetProp(hwnd, PROP_UNDERLINE_FONT); - SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, FALSE); - InvalidateRect(hwnd, NULL, FALSE); - SetCapture(hwnd); - } - else - { - RECT rect; - GetWindowRect(hwnd, &rect); - - POINT pt = { LOWORD(lParam), HIWORD(lParam) }; - ClientToScreen(hwnd, &pt); - - if (!PtInRect(&rect, pt)) - { - HFONT hFont = (HFONT) GetProp(hwnd, PROP_ORIGINAL_FONT); - SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, FALSE); - InvalidateRect(hwnd, NULL, FALSE); - ReleaseCapture(); - } - } - break; - } - case WM_SETCURSOR: - { - // Since IDC_HAND is not available on all operating systems, - // we will load the arrow cursor if IDC_HAND is not present. - HCURSOR hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_HAND)); - if (NULL == hCursor) - { - hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); - } - SetCursor(hCursor); - return TRUE; - } - } - - return CallWindowProc(pfnOrigProc, hwnd, message, wParam, lParam); -} - -BOOL ConvertStaticToHyperlink(HWND hwndCtl) -{ - // Subclass the parent so we can color the controls as we desire. - - HWND hwndParent = GetParent(hwndCtl); - if (NULL != hwndParent) - { - WNDPROC pfnOrigProc = (WNDPROC) GetWindowLong(hwndParent, GWL_WNDPROC); - if (pfnOrigProc != _HyperlinkParentProc) - { - SetProp(hwndParent, PROP_ORIGINAL_PROC, (HANDLE) pfnOrigProc); - SetWindowLong(hwndParent, GWL_WNDPROC, (LONG) (WNDPROC) _HyperlinkParentProc); - } - } - - // Make sure the control will send notifications. - - DWORD dwStyle = GetWindowLong(hwndCtl, GWL_STYLE); - SetWindowLong(hwndCtl, GWL_STYLE, dwStyle | SS_NOTIFY); - - // Subclass the existing control. - - WNDPROC pfnOrigProc = (WNDPROC) GetWindowLong(hwndCtl, GWL_WNDPROC); - SetProp(hwndCtl, PROP_ORIGINAL_PROC, (HANDLE) pfnOrigProc); - SetWindowLong(hwndCtl, GWL_WNDPROC, (LONG) (WNDPROC) _HyperlinkProc); - - // Create an updated font by adding an underline. - - HFONT hOrigFont = (HFONT) SendMessage(hwndCtl, WM_GETFONT, 0, 0); - SetProp(hwndCtl, PROP_ORIGINAL_FONT, (HANDLE) hOrigFont); - - LOGFONT lf; - GetObject(hOrigFont, sizeof(lf), &lf); - lf.lfUnderline = TRUE; - - HFONT hFont = CreateFontIndirect(&lf); - SetProp(hwndCtl, PROP_UNDERLINE_FONT, (HANDLE) hFont); - - // Set a flag on the control so we know what color it should be. - - SetProp(hwndCtl, PROP_STATIC_HYPERLINK, (HANDLE) 1); - - return TRUE; -} - -BOOL ConvertStaticToHyperlink(HWND hwndParent, UINT uiCtlId) -{ - return ConvertStaticToHyperlink(GetDlgItem(hwndParent, uiCtlId)); -} diff --git a/pcsx2/windows/Hyperlinks.h b/pcsx2/windows/Hyperlinks.h deleted file mode 100644 index 3b92a4d3ee..0000000000 --- a/pcsx2/windows/Hyperlinks.h +++ /dev/null @@ -1,10 +0,0 @@ -// Hyperlinks.h -// -// Copyright 2002 Neal Stublen -// All rights reserved. -// -// http://www.awesoftware.com -// - -BOOL ConvertStaticToHyperlink(HWND hwndCtl); -BOOL ConvertStaticToHyperlink(HWND hwndParent, UINT uiCtlId); diff --git a/pcsx2/windows/SamplProf.cpp b/pcsx2/windows/SamplProf.cpp index 906a26da6d..e75a430fdf 100644 --- a/pcsx2/windows/SamplProf.cpp +++ b/pcsx2/windows/SamplProf.cpp @@ -7,28 +7,29 @@ using namespace std; -DWORD GetModuleFromPtr(IN void* ptr,OUT LPSTR lpFilename,IN DWORD nSize) +DWORD GetModuleFromPtr(IN void* ptr,OUT LPWSTR lpFilename,IN DWORD nSize) { MEMORY_BASIC_INFORMATION mbi; VirtualQuery(ptr,&mbi,sizeof(mbi)); return GetModuleFileName((HMODULE)mbi.AllocationBase,lpFilename,nSize); } + struct Module { uptr base; uptr end; uptr len; - string name; + wxString name; u32 ticks; - Module(const char* name, const void* ptr) + Module(const wxChar* name, const void* ptr) { if (name!=0) this->name=name; FromAddress(ptr,name==0); ticks=0; } - Module(const char* name, const void* b, u32 s) + Module(const wxChar* name, const void* b, u32 s) { this->name=name; FromValues(b,s); @@ -38,15 +39,15 @@ struct Module { return ticks>other.ticks; } - string ToString(u32 total_ticks) + wxString ToString(u32 total_ticks) { - return name + ": " + to_string(ticks*100/(float)total_ticks) + " "; + return wxsFormat( wxT("%s: %d "), name, (ticks*100) / (double)total_ticks ); } bool Inside(uptr val) { return val>=base && val<=end; } void FromAddress(const void* ptr,bool getname) { - char filename[512]; - char filename2[512]; + wxChar filename[512]; + wxChar filename2[512]; static const void* ptr_old=0; if (ptr_old==ptr) @@ -76,7 +77,7 @@ struct Module if (!GetModuleFileName((HMODULE)mbi.AllocationBase,filename2,512)) break; - if (strcmp(filename,filename2)!=0) + if (wxStrcmp(filename,filename2)!=0) break; len+=mbi.RegionSize; } @@ -92,7 +93,7 @@ struct Module } }; -typedef map MapType; +typedef map MapType; static vector ProfModules; static MapType ProfUnknownHash; @@ -105,7 +106,7 @@ static CRITICAL_SECTION ProfModulesLock; static volatile bool ProfRunning=false; -static bool _registeredName( const char* name ) +static bool _registeredName( const wxString& name ) { for( vector::const_iterator iter = ProfModules.begin(), @@ -122,8 +123,9 @@ void ProfilerRegisterSource(const char* Name, const void* buff, u32 sz) if( ProfRunning ) EnterCriticalSection( &ProfModulesLock ); - if( !_registeredName( Name ) ) - ProfModules.push_back( Module(Name, buff, sz) ); + wxString strName( wxString::FromAscii(Name) ); + if( !_registeredName( strName ) ) + ProfModules.push_back( Module( strName, buff, sz ) ); if( ProfRunning ) LeaveCriticalSection( &ProfModulesLock ); @@ -134,8 +136,9 @@ void ProfilerRegisterSource(const char* Name, const void* function) if( ProfRunning ) EnterCriticalSection( &ProfModulesLock ); - if( !_registeredName( Name ) ) - ProfModules.push_back( Module(Name,function) ); + wxString strName( wxString::FromAscii(Name) ); + if( !_registeredName( strName ) ) + ProfModules.push_back( Module(strName,function) ); if( ProfRunning ) LeaveCriticalSection( &ProfModulesLock ); @@ -143,11 +146,12 @@ void ProfilerRegisterSource(const char* Name, const void* function) void ProfilerTerminateSource( const char* Name ) { + wxString strName( wxString::FromAscii(Name) ); for( vector::const_iterator iter = ProfModules.begin(), end = ProfModules.end(); itername.compare( Name ) == 0 ) + if( iter->name.compare( strName ) == 0 ) { ProfModules.erase( iter ); break; @@ -176,15 +180,11 @@ static bool DispatchKnownModules( uint Eip ) static void MapUnknownSource( uint Eip ) { - char modulename[512]; + wxChar modulename[512]; DWORD sz=GetModuleFromPtr((void*)Eip,modulename,512); - string modulenam; - if (sz==0) - modulenam="[Unknown]"; - else - modulenam=modulename; + wxString modulenam( (sz==0) ? wxT("[Unknown]") : modulename ); - map::iterator iter=ProfUnknownHash.find(modulenam); + map::iterator iter = ProfUnknownHash.find(modulenam); if (iter!=ProfUnknownHash.end()) { iter->second.ticks++; @@ -208,7 +208,7 @@ int __stdcall ProfilerThread(void* nada) if (tick_count>500) { - string rv="|"; + wxString rv = wxT("|"); u32 subtotal=0; for (size_t i=0;i lst; for (MapType::iterator i=ProfUnknownHash.begin();i!=ProfUnknownHash.end();i++) { @@ -227,10 +227,10 @@ int __stdcall ProfilerThread(void* nada) sort(lst.begin(),lst.end()); for (size_t i=0;i", params rv.c_str()); + Console::WriteLn("+Sampling Profiler Results-\n%s\n+>", params rv.ToAscii().data() ); tick_count=0; diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index 8710dafc97..38c82aebd2 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -25,7 +25,7 @@ InheritedPropertySheets=".\vsprops\common.vsprops;..\..\..\common\vsprops\BaseProperties.vsprops;..\..\..\common\vsprops\3rdpartyDeps.vsprops;.\vsprops\debug.vsprops;.\vsprops\devbuild.vsprops;..\..\..\common\vsprops\pthreads.vsprops;..\..\..\common\vsprops\IncrementalLinking.vsprops" UseOfMFC="0" ATLMinimizesCRunTimeLibraryUsage="false" - CharacterSet="2" + CharacterSet="1" > + + + + + + - - - - - - - - - - - - - @@ -391,6 +374,7 @@ > + + + + + + + + + + + + + + + + + + + + + - - @@ -640,6 +689,18 @@ + + + + + + @@ -681,7 +742,6 @@ - - - @@ -737,18 +789,6 @@ RelativePath="..\..\SourceLog.cpp" > - - - - - - @@ -1009,14 +1049,6 @@ UsePrecompiledHeader="2" /> - - - @@ -1051,6 +1083,7 @@ > + + + + + + + + + + + + + + + + + + + + + + @@ -2740,10 +2824,70 @@ RelativePath="..\..\AlignedMalloc.cpp" > + + + + + + + + + + + + + + + + + + + + + + + + @@ -2756,9 +2900,34 @@ /> + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3219,6 +3375,10 @@ RelativePath="..\..\Common.h" > + + diff --git a/pcsx2/windows/Win32.h b/pcsx2/windows/Win32.h index 89192d1a14..b5f7401dc4 100644 --- a/pcsx2/windows/Win32.h +++ b/pcsx2/windows/Win32.h @@ -142,7 +142,7 @@ extern int ParseCommandLine( int tokenCount, TCHAR *const *const tokens ); extern BOOL CALLBACK PatchBDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); extern BOOL CALLBACK CpuDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); extern BOOL CALLBACK AdvancedOptionsProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam); -extern BOOL CALLBACK HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); +//extern BOOL CALLBACK HacksProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); extern AppData gApp; extern HWND hStatusWnd; @@ -158,18 +158,18 @@ extern int g_SaveGSStream; // Throws an exception based on the value returned from GetLastError. // Performs an option return value success/fail check on hresult. -extern void StreamException_ThrowLastError( const string& streamname, HANDLE result=INVALID_HANDLE_VALUE ); +extern void StreamException_ThrowLastError( const wxString& streamname, HANDLE result=INVALID_HANDLE_VALUE ); // Throws an exception based on the given error code (usually taken from ANSI C's errno) -extern void StreamException_ThrowFromErrno( const string& streamname, errno_t errcode ); +extern void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode ); -extern bool StreamException_LogFromErrno( const string& streamname, const char* action, errno_t result ); -extern bool StreamException_LogLastError( const string& streamname, const char* action, HANDLE result=INVALID_HANDLE_VALUE ); +extern bool StreamException_LogFromErrno( const wxString& streamname, const wxChar* action, errno_t result ); +extern bool StreamException_LogLastError( const wxString& streamname, const wxChar* action, HANDLE result=INVALID_HANDLE_VALUE ); // Sets the NTFS compression flag for a directory or file. This function does not operate // recursively. Set compressStatus to false to decompress compressed files (and do nothing // to already decompressed files). -extern void NTFS_CompressFile( const char* file, bool compressStatus=true ); +extern void NTFS_CompressFile( const wxString& file, bool compressStatus=true ); #endif diff --git a/pcsx2/windows/WinCompressNTFS.cpp b/pcsx2/windows/WinCompressNTFS.cpp index a1f608c7f5..57df006545 100644 --- a/pcsx2/windows/WinCompressNTFS.cpp +++ b/pcsx2/windows/WinCompressNTFS.cpp @@ -19,23 +19,23 @@ #include "Win32.h" // Translates an Errno code into an exception. -void StreamException_ThrowFromErrno( const string& streamname, errno_t errcode ) +void StreamException_ThrowFromErrno( const wxString& streamname, errno_t errcode ) { if( errcode == 0 ) return; switch( errcode ) { case EINVAL: - throw Exception::InvalidArgument( "Invalid argument." ); + throw Exception::InvalidArgument( "Invalid argument" ); case EACCES: // Access denied! throw Exception::AccessDenied( streamname ); case EMFILE: // Too many open files! - throw Exception::CreateStream( streamname, "File handle allocation failure - Too many open files" ); + throw Exception::CreateStream( streamname, "Too many open files" ); // File handle allocation failure case EEXIST: - throw Exception::CreateStream( streamname, "Cannot create - File already exists" ); + throw Exception::CreateStream( streamname, "File already exists" ); case ENOENT: // File not found! throw Exception::FileNotFound( streamname ); @@ -48,12 +48,12 @@ void StreamException_ThrowFromErrno( const string& streamname, errno_t errcode ) default: throw Exception::Stream( streamname, - fmt_string( "General file/stream error occured [errno: %d]", errcode ) + wxsFormat( wxT("General file/stream error [errno: %d]"), errcode ) ); } } -void StreamException_ThrowLastError( const string& streamname, HANDLE result ) +void StreamException_ThrowLastError( const wxString& streamname, HANDLE result ) { if( result != INVALID_HANDLE_VALUE ) return; @@ -68,28 +68,28 @@ void StreamException_ThrowLastError( const string& streamname, HANDLE result ) throw Exception::FileNotFound( streamname ); case ERROR_TOO_MANY_OPEN_FILES: - throw Exception::CreateStream( streamname, "File handle allocation failure - Too many open files " ); + throw Exception::CreateStream( streamname, "Too many open files" ); case ERROR_ACCESS_DENIED: throw Exception::AccessDenied( streamname ); case ERROR_INVALID_HANDLE: - throw Exception::InvalidOperation( "Stream object or handle is invalid." ); + throw Exception::InvalidOperation( "Stream object or handle is invalid" ); case ERROR_SHARING_VIOLATION: - throw Exception::AccessDenied( streamname, "Sharing violation." ); + throw Exception::AccessDenied( streamname, "Sharing violation" ); default: { throw Exception::Stream( streamname, - fmt_string( "General Win32 File/stream error [GetLastError: %d]", error ) + wxsFormat( wxT("General Win32 File/stream error [GetLastError: %d]"), error ) ); } } } // returns TRUE if an error occurred. -bool StreamException_LogFromErrno( const string& streamname, const char* action, errno_t result ) +bool StreamException_LogFromErrno( const wxString& streamname, const wxChar* action, errno_t result ) { try { @@ -97,14 +97,14 @@ bool StreamException_LogFromErrno( const string& streamname, const char* action, } catch( Exception::Stream& ex ) { - Console::Notice( "%s > %s", params action, ex.cMessage() ); + Console::Notice( wxsFormat( wxT("%s: %s"), action, ex.LogMessage().c_str() ) ); return true; } return false; } // returns TRUE if an error occurred. -bool StreamException_LogLastError( const string& streamname, const char* action, HANDLE result ) +bool StreamException_LogLastError( const wxString& streamname, const wxChar* action, HANDLE result ) { try { @@ -112,17 +112,20 @@ bool StreamException_LogLastError( const string& streamname, const char* action, } catch( Exception::Stream& ex ) { - Console::Notice( "%s > %s", params action, ex.cMessage() ); + Console::Notice( wxsFormat( wxT("%s: %s"), action, ex.LogMessage().c_str() ) ); return true; } return false; } // Exceptions thrown: None. Errors are logged to console. Failures are considered non-critical -void NTFS_CompressFile( const char* file, bool compressStatus ) +void NTFS_CompressFile( const wxString& file, bool compressStatus ) { - bool isFile = Path::isFile( file ); - + bool isFile = !wxDirExists( file ); + + if( isFile && !wxFileExists( file ) ) return; + if( !wxIsWritable( file ) ) return; + const DWORD flags = isFile ? FILE_ATTRIBUTE_NORMAL : (FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_DIRECTORY); HANDLE bloated_crap = CreateFile( file, @@ -136,7 +139,7 @@ void NTFS_CompressFile( const char* file, bool compressStatus ) // Fail silently -- non-compression of files and folders is not an errorable offense. - if( !StreamException_LogLastError( file, "NTFS Compress Notice", bloated_crap ) ) + if( !StreamException_LogLastError( file, wxT("NTFS Compress Notice"), bloated_crap ) ) { DWORD bytesReturned = 0; DWORD compressMode = compressStatus ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE; @@ -148,7 +151,7 @@ void NTFS_CompressFile( const char* file, bool compressStatus ) ); if( !result ) - StreamException_LogLastError( file, "NTFS Compress Notice" ); + StreamException_LogLastError( file, wxT("NTFS Compress Notice") ); CloseHandle( bloated_crap ); } diff --git a/pcsx2/windows/WinMisc.cpp b/pcsx2/windows/WinMisc.cpp index 23c812e0cf..953d22b661 100644 --- a/pcsx2/windows/WinMisc.cpp +++ b/pcsx2/windows/WinMisc.cpp @@ -37,16 +37,3 @@ u64 GetCPUTicks() QueryPerformanceCounter( &count ); return count.QuadPart; } - -void cdvdSetSystemTime( cdvdStruct& cdvd ) -{ - SYSTEMTIME st; - GetSystemTime(&st); - - cdvd.RTC.second = (u8)(st.wSecond); - cdvd.RTC.minute = (u8)(st.wMinute); - cdvd.RTC.hour = (u8)(st.wHour+1)%24; - cdvd.RTC.day = (u8)(st.wDay); - cdvd.RTC.month = (u8)(st.wMonth); - cdvd.RTC.year = (u8)(st.wYear - 2000); -} diff --git a/pcsx2/windows/WinSysExec.cpp b/pcsx2/windows/WinSysExec.cpp index f3284b383d..e5518ab20c 100644 --- a/pcsx2/windows/WinSysExec.cpp +++ b/pcsx2/windows/WinSysExec.cpp @@ -25,7 +25,7 @@ #include "iR5900.h" // temporary hack to keep this code compiling. -static const char* _( const char* src ) { return src; } +//static const char* _( const char* src ) { return src; } static bool sinit = false; @@ -41,8 +41,6 @@ AppData gApp; const char* g_pRunGSState = NULL; -#define CmdSwitchIs( text ) ( stricmp( command, text ) == 0 ) - int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) { const _EXCEPTION_RECORD& ExceptionRecord = *eps->ExceptionRecord; @@ -63,174 +61,6 @@ int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) return EXCEPTION_CONTINUE_EXECUTION; } - -// returns 1 if the user requested help (show help and exit) -// returns zero on success. -// returns -1 on failure (bad command line argument) -int ParseCommandLine( int tokenCount, TCHAR *const *const tokens ) -{ - int tidx = 0; - g_Startup.BootMode = BootMode_Bios; - - while( tidx < tokenCount ) - { - const TCHAR* command = tokens[tidx++]; - - if( command[0] != '-' ) - { - g_Startup.ImageName = command; - g_Startup.Enabled = true; - continue; - } - - // jump past the '-' switch char, and skip if this is a dud switch: - command++; - if( command[0] == 0 ) continue; - - if( CmdSwitchIs( "help" ) ) - { - return -1; - } - else if( CmdSwitchIs( "nogui" ) ) { - g_Startup.NoGui = true; - } - else if( CmdSwitchIs( "highpriority" ) ) { - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); - } - else - { - const TCHAR* param; - if( tidx >= tokenCount ) break; - - // None of the parameter-less toggles flagged. - // Check for switches that require one or more parameters here: - - param = tokens[tidx++]; - - if( CmdSwitchIs( "cfg" ) ) { - g_CustomConfigFile = param; - } - else if( CmdSwitchIs( "bootmode" ) ) { - g_Startup.BootMode = (StartupMode)atoi( param ); - g_Startup.Enabled = true; - } - else if( CmdSwitchIs( "loadgs" ) ) { - g_pRunGSState = param; - } - - // Options to configure plugins: - - else if( CmdSwitchIs( "gs" ) ) { - g_Startup.gsdll = param; - } - else if( CmdSwitchIs( "cdvd" ) ) { - g_Startup.cdvddll = param; - } - else if( CmdSwitchIs( "spu" ) ) { - g_Startup.spudll = param; - } - else if( CmdSwitchIs( "pad" ) ) { - g_Startup.pad1dll = param; - g_Startup.pad2dll = param; - } - else if( CmdSwitchIs( "pad1" ) ) { - g_Startup.pad1dll = param; - } - else if( CmdSwitchIs( "pad2" ) ) { - g_Startup.pad2dll = param; - } - else if( CmdSwitchIs( "dev9" ) ) { - g_Startup.dev9dll = param; - } - - } - } - return 0; -} - -void SysPrintf(const char *fmt, ...) -{ - va_list list; - char msg[512]; - - va_start(list,fmt); - vsprintf_s(msg,fmt,list); - msg[511] = '\0'; - va_end(list); - - Console::Write( msg ); -} - -static void strcatz(char *dst, char *src) -{ - int len = strlen(dst) + 1; - strcpy(dst + len, src); -} - -void OnStates_LoadOther() -{ - OPENFILENAME ofn; - char szFileName[g_MaxPath]; - char szFileTitle[g_MaxPath]; - char szFilter[g_MaxPath]; - - memzero_obj( szFileName ); - memzero_obj( szFileTitle ); - - strcpy(szFilter, _("PCSX2 State Format")); - strcatz(szFilter, "*.*;*.*"); - - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = gApp.hWnd; - ofn.lpstrFilter = szFilter; - ofn.lpstrCustomFilter = NULL; - ofn.nMaxCustFilter = 0; - ofn.nFilterIndex = 1; - ofn.lpstrFile = szFileName; - ofn.nMaxFile = g_MaxPath; - ofn.lpstrInitialDir = NULL; - ofn.lpstrFileTitle = szFileTitle; - ofn.nMaxFileTitle = g_MaxPath; - ofn.lpstrTitle = NULL; - ofn.lpstrDefExt = "EXE"; - ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER; - - if (GetOpenFileName ((LPOPENFILENAME)&ofn)) - States_Load( szFileName ); -} - -void OnStates_SaveOther() -{ - OPENFILENAME ofn; - char szFileName[g_MaxPath]; - char szFileTitle[g_MaxPath]; - char szFilter[g_MaxPath]; - - memzero_obj( szFileName ); - memzero_obj( szFileTitle ); - - strcpy(szFilter, _("PCSX2 State Format")); - strcatz(szFilter, "*.*;*.*"); - - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = gApp.hWnd; - ofn.lpstrFilter = szFilter; - ofn.lpstrCustomFilter = NULL; - ofn.nMaxCustFilter = 0; - ofn.nFilterIndex = 1; - ofn.lpstrFile = szFileName; - ofn.nMaxFile = g_MaxPath; - ofn.lpstrInitialDir = NULL; - ofn.lpstrFileTitle = szFileTitle; - ofn.nMaxFileTitle = g_MaxPath; - ofn.lpstrTitle = NULL; - ofn.lpstrDefExt = "EXE"; - ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER; - - if (GetOpenFileName ((LPOPENFILENAME)&ofn)) - States_Save( szFileName ); -} - static void CreateDirs() { Path::CreateDirectory(MEMCARDS_DIR); @@ -238,6 +68,7 @@ static void CreateDirs() Path::CreateDirectory(SNAPSHOTS_DIR); } +/* bool HostGuiInit() { if( sinit ) return true; @@ -267,45 +98,10 @@ bool HostGuiInit() return true; } - - -static const char *err = "Error Loading Symbol"; -static int errval; +*/ namespace HostSys { - void *LoadLibrary(const char *lib) - { - return LoadLibraryA( lib ); - } - - void *LoadSym(void *lib, const char *sym) - { - void *tmp = GetProcAddress((HINSTANCE)lib, sym); - if (tmp == NULL) errval = GetLastError(); - else errval = 0; - return tmp; - } - - const char *LibError() - { - if( errval ) - { - static char perr[4096]; - - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,GetLastError(),NULL,perr,4095,NULL); - - errval = 0; - return _(perr); - } - return NULL; - } - - void CloseLibrary(void *lib) - { - FreeLibrary((HINSTANCE)lib); - } - void *Mmap(uptr base, u32 size) { return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -341,138 +137,3 @@ namespace HostSys VirtualProtect( baseaddr, size, winmode, &OldProtect ); } } - -namespace HostGui -{ - // Sets the status bar message without mirroring the output to the console. - void SetStatusMsg( const string& text ) - { - // don't try this in GCC folks! - SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text.c_str() ); - } - - void Notice( const string& text ) - { - // mirror output to the console! - Console::Status( text.c_str() ); - SetStatusMsg( text ); - } - - void ResetMenuSlots() - { - for( int i=0; i<5; i++ ) - { - EnableMenuItem( GetSubMenu(gApp.hMenu, 0), - ID_FILE_STATES_LOAD_SLOT1+i, - States_isSlotUsed(i) ? MF_ENABLED : MF_GRAYED - ); - } - } - - // Because C++ lacks the finally clause >_< - static void _executeCpuFinally() - { - timeEndPeriod( 1 ); - ShowWindow( gApp.hWnd, SW_SHOW ); - SetForegroundWindow( gApp.hWnd ); - nDisableSC = false; - } - - void BeginExecution() - { - nDisableSC = true; - - // ... and hide the window. Ugly thing. - ShowWindow( gApp.hWnd, SW_HIDE ); - timeBeginPeriod( 1 ); // improves multithreaded responsiveness - - try - { - SysExecute(); - } - catch( Exception::BaseException& ) - { - _executeCpuFinally(); - throw; - } - - _executeCpuFinally(); - } - - void __fastcall KeyEvent( keyEvent* ev ) - { - struct KeyModifiers *keymod = &keymodifiers; - - if (ev == NULL) return; - if (ev->evt == KEYRELEASE) - { - switch (ev->key) - { - case VK_SHIFT: keymod->shift = FALSE; break; - case VK_CONTROL: keymod->control = FALSE; break; - /* They couldn't just name this something simple, like VK_ALT */ - case VK_MENU: keymod->alt = FALSE; break; - case VK_CAPITAL: keymod->capslock = FALSE; break; - - } - GSkeyEvent(ev); return; - } - - if (ev->evt != KEYPRESS) return; - - switch (ev->key) - { - case VK_SHIFT: keymod->shift = TRUE; break; - case VK_CONTROL: keymod->control = TRUE; break; - case VK_MENU: keymod->alt = TRUE; break; - case VK_CAPITAL: keymod->capslock = TRUE; break; - - case VK_F1: case VK_F2: case VK_F3: case VK_F4: - case VK_F5: case VK_F6: case VK_F7: case VK_F8: - case VK_F9: case VK_F10: case VK_F11: case VK_F12: - try - { - ProcessFKeys(ev->key-VK_F1 + 1, keymod); - } - catch( Exception::CpuStateShutdown& ) - { - // Woops! Something was unrecoverable (like state load). Bummer. - // Let's give the user a RunGui! - - g_EmulationInProgress = false; - SysEndExecution(); - } - break; - - case VK_TAB: - CycleFrameLimit(0); - break; - - case VK_ESCAPE: -#ifdef PCSX2_DEVBUILD - if( g_SaveGSStream >= 3 ) { - // gs state - g_SaveGSStream = 4; - break; - } -#endif - - if( CHECK_ESCAPE_HACK ) - { - g_EmulationInProgress = false; - DestroyWindow( gApp.hWnd ); - } - else - { - nDisableSC = 0; - } - - SysEndExecution(); - break; - - default: - GSkeyEvent(ev); - break; - } - } -} \ No newline at end of file diff --git a/pcsx2/windows/ini.cpp b/pcsx2/windows/ini.cpp index 7a49892594..991ac8e42a 100644 --- a/pcsx2/windows/ini.cpp +++ b/pcsx2/windows/ini.cpp @@ -21,7 +21,7 @@ #include "Common.h" #include "Paths.h" -static const u32 IniVersion = 101; +static const u32 IniVersion = 102; const char* g_CustomConfigFile; char g_WorkingFolder[g_MaxPath]; // Working folder at application startup @@ -223,7 +223,19 @@ void IniFile::DoConfig( PcsxConfig& Conf ) Entry( "sseVUMXCSR", Conf.sseVUMXCSR, DEFAULT_sseVUMXCSR ); Entry( "eeOptions", Conf.eeOptions, DEFAULT_eeOptions ); Entry( "vuOptions", Conf.vuOptions, DEFAULT_vuOptions ); - Entry( "SpeedHacks", Conf.Hacks ); + + SetCurrentSection("Hacks"); + Entry("EECycleRate", Config.Hacks.EECycleRate); + if (Config.Hacks.EECycleRate > 2) + Config.Hacks.EECycleRate = 2; + Entry("IOPCycleDouble", Config.Hacks.IOPCycleDouble); + Entry("WaitCycleExt", Config.Hacks.WaitCycleExt); + Entry("INTCSTATSlow", Config.Hacks.INTCSTATSlow); + Entry("VUCycleSteal", Config.Hacks.VUCycleSteal); + Entry("IdleLoopFF", Config.Hacks.IdleLoopFF); + if (Conf.Hacks.VUCycleSteal < 0 || Conf.Hacks.VUCycleSteal > 4) + Conf.Hacks.VUCycleSteal = 0; + Entry("ESCExits", Config.Hacks.ESCExits); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -254,7 +266,7 @@ bool LoadConfig() // sanity check to make sure the user doesn't have some kind of // crazy ass setup... why not! - if( Path::isDirectory( szIniFile ) ) + if( Path::IsDirectory( szIniFile ) ) throw Exception::Stream( "Cannot open or create the Pcsx2 ini file because a directory of\n" "the same name already exists! Please delete it or reinstall Pcsx2\n" diff --git a/pcsx2/windows/pcsx2.rc b/pcsx2/windows/pcsx2.rc index 63316593a2..e5934d0551 100644 --- a/pcsx2/windows/pcsx2.rc +++ b/pcsx2/windows/pcsx2.rc @@ -352,25 +352,29 @@ BEGIN CONTROL "Default Cycle Rate",IDC_EESYNC_DEFAULT,"Button",BS_AUTORADIOBUTTON,13,44,87,10 CONTROL "Use x1.5 Cycle Rate",IDC_EESYNC1,"Button",BS_AUTORADIOBUTTON,13,79,87,10 CONTROL "Use x2 Cycle Rate",IDC_EESYNC2,"Button",BS_AUTORADIOBUTTON,13,113,83,10 - CONTROL "Use x3 Cycle Rate",IDC_EESYNC3,"Button",BS_AUTORADIOBUTTON,13,147,80,10 CONTROL "Enable IOP x2 Cycle Rate",IDC_IOPSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,88,98,10 CONTROL "WaitCycles Sync Hack",IDC_WAITCYCLES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,127,90,10 CONTROL "Escape Hack - Use Esc key to fully exit PCSX2.",IDC_ESCHACK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,234,180,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,238,180,10 DEFPUSHBUTTON "OK",IDOK,217,242,50,14 PUSHBUTTON "Cancel",IDCANCEL,278,242,50,14 CTEXT "These hacks will speed up emulation but reduce emulation compatibility or cause visual errors. If you have problems, disable all these and try again!",IDC_HACKDESC,18,7,286,19 - GROUPBOX "EmotionEngine (EE) Sync Hacks",IDC_STATIC,7,31,159,185 - GROUPBOX "Miscellaneous",IDC_STATIC,7,220,194,33 - LTEXT "Important: X2 and X3 sync hacks *will* cause choppy/skippy audio on many FMV movies.",IDC_STATIC,20,188,137,25 - LTEXT "Known to work well with a couple games, namely Shadow of the Colossus (but breaks most other games).",IDC_STATIC,25,158,133,28 + GROUPBOX "EmotionEngine (EE) Sync Hacks",IDC_STATIC,7,31,159,143 + GROUPBOX "Miscellaneous",IDC_STATIC,7,223,194,33 + LTEXT "Important: the X2 sync hack *will* cause choppy/skippy audio on many FMV movies.",IDC_STATIC,13,149,137,22 LTEXT "Big speedup! Works well with many games.",IDC_STATIC,25,124,125,19 LTEXT "Most compatible option - recommended for everyone with high-end machines.",IDC_STATIC,25,55,136,19 LTEXT "Small speedup and works well with most games.",IDC_STATIC,186,100,134,22 LTEXT "Small speedup. Works well with most games, but may cause certain games to crash or freeze up during bootup or stage changes.",IDC_STATIC,186,139,141,39 LTEXT "Moderate speedup and works well with most games.",IDC_STATIC,25,90,129,19 - CONTROL "INTC Sync Hack (experimental)",IDC_INTCSTATHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,43,127,10 + CONTROL "INTC Sync Hack",IDC_INTCSTATHACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,43,127,10 LTEXT "Huge speedup in many games, and a pretty high compatibility rate (some games still work better with EE sync hacks).",IDC_STATIC,186,55,140,28 + CONTROL "",IDC_VUCYCLE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,13,178,36,15 + LTEXT "This space intentionally left blank",IDC_VUCYCLEDESC,25,196,142,24 + LTEXT "VU Cycle Stealing (experimental)",IDC_STATIC,49,183,105,8 + CONTROL "Idle Loop Fast-Forward (experimental)",IDC_IDLELOOPFF, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,174,179,139,10 + LTEXT "Speedup for a few games, including FFX with no known side effects. More later.",IDC_STATIC,186,193,142,26 END @@ -393,6 +397,8 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 328 VERTGUIDE, 13 + VERTGUIDE, 174 + VERTGUIDE, 186 TOPMARGIN, 7 BOTTOMMARGIN, 256 END diff --git a/pcsx2/windows/resource.h b/pcsx2/windows/resource.h index 6e9f1ab34c..e519a3275a 100644 --- a/pcsx2/windows/resource.h +++ b/pcsx2/windows/resource.h @@ -272,6 +272,10 @@ #define IDC_MCD_LABEL2 1325 #define IDC_INTCSTATHACK 1326 #define IDC_EE_CHECK3 1327 +#define IDC_SLIDER1 1327 +#define IDC_VUCYCLE 1327 +#define IDC_VUCYCLEDESC 1328 +#define IDC_IDLELOOPFF 1330 #define IDC_CPULOG 1500 #define IDC_MEMLOG 1501 #define IDC_HWLOG 1502 @@ -405,7 +409,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 141 #define _APS_NEXT_COMMAND_VALUE 40018 -#define _APS_NEXT_CONTROL_VALUE 1326 +#define _APS_NEXT_CONTROL_VALUE 1331 #define _APS_NEXT_SYMED_VALUE 104 #endif #endif diff --git a/pcsx2/x86/BaseblockEx.cpp b/pcsx2/x86/BaseblockEx.cpp index 22a6765e60..bb933f301d 100644 --- a/pcsx2/x86/BaseblockEx.cpp +++ b/pcsx2/x86/BaseblockEx.cpp @@ -70,10 +70,27 @@ int BaseBlocks::LastIndex(u32 startpc) const return imin; } -BASEBLOCKEX* BaseBlocks::GetByX86(uptr ip) const +BASEBLOCKEX* BaseBlocks::GetByX86(uptr ip) { - // TODO - return 0; + if (0 == blocks.size()) + return 0; + + int imin = 0, imax = blocks.size() - 1, imid; + + while(imin != imax) { + imid = (imin+imax+1)>>1; + + if (blocks[imid].fnptr > ip) + imax = imid - 1; + else + imin = imid; + } + + if (ip < blocks[imin].fnptr || + ip >= blocks[imin].fnptr + blocks[imin].x86size) + return 0; + + return &blocks[imin]; } void BaseBlocks::Link(u32 pc, uptr jumpptr) diff --git a/pcsx2/x86/BaseblockEx.h b/pcsx2/x86/BaseblockEx.h index 6ebe592d5e..6ef0261451 100644 --- a/pcsx2/x86/BaseblockEx.h +++ b/pcsx2/x86/BaseblockEx.h @@ -18,14 +18,9 @@ #pragma once -#include "PrecompiledHeader.h" -#include -#include +#include // used by BaseBlockEx #include -// used to keep block information -#define BLOCKTYPE_DELAYSLOT 1 // if bit set, delay slot - // Every potential jump point in the PS2's addressable memory has a BASEBLOCK // associated with it. So that means a BASEBLOCK for every 4 bytes of PS2 // addressable memory. Yay! @@ -73,7 +68,7 @@ public: BASEBLOCKEX* New(u32 startpc, uptr fnptr); int LastIndex (u32 startpc) const; - BASEBLOCKEX* GetByX86(uptr ip) const; + BASEBLOCKEX* GetByX86(uptr ip); inline int Index (u32 startpc) const { @@ -119,7 +114,6 @@ public: } }; -#define GET_BLOCKTYPE(b) ((b)->Type) #define PC_GETBLOCK_(x, reclut) ((BASEBLOCK*)(reclut[((u32)(x)) >> 16] + (x)*(sizeof(BASEBLOCK)/4))) static void recLUT_SetPage(uptr reclut[0x10000], uptr hwlut[0x10000], diff --git a/pcsx2/x86/aVif.S b/pcsx2/x86/aVif.S index 05a2e9248f..e4b64685f6 100644 --- a/pcsx2/x86/aVif.S +++ b/pcsx2/x86/aVif.S @@ -18,9 +18,9 @@ */ .intel_syntax noprefix -.extern _vifRegs -.extern _vifMaskRegs -.extern _vifRow +.extern vifRegs +.extern vifMaskRegs +.extern vifRow #define VIF_ESP esp #define VIF_SRC esi @@ -108,7 +108,7 @@ // setting up masks #define UNPACK_Setup_Mask_SSE(CL) \ - mov VIF_TMPADDR, _vifMaskRegs; \ + mov VIF_TMPADDR, vifMaskRegs; \ movdqa XMM_ROWMASK, xmmword ptr [VIF_TMPADDR + 64*(CL) + 16]; \ movdqa XMM_ROWCOLMASK, xmmword ptr [VIF_TMPADDR + 64*(CL) + 32]; \ movdqa XMM_WRITEMASK, xmmword ptr [VIF_TMPADDR + 64*(CL)]; \ @@ -118,7 +118,7 @@ #define UNPACK_Start_Setup_Mask_SSE_0(CL) UNPACK_Setup_Mask_SSE(CL) #define UNPACK_Start_Setup_Mask_SSE_1(CL) \ - mov VIF_TMPADDR, _vifMaskRegs; \ + mov VIF_TMPADDR, vifMaskRegs; \ movdqa XMM_ROWMASK, xmmword ptr [VIF_TMPADDR + 64*(CL) + 16]; \ movdqa XMM_ROWCOLMASK, xmmword ptr [VIF_TMPADDR + 64*(CL) + 32]; \ pand XMM_ROWMASK, XMM_ROW; \ @@ -129,12 +129,12 @@ #define UNPACK_Setup_Mask_SSE_0_1(CL) #define UNPACK_Setup_Mask_SSE_1_1(CL) \ - mov VIF_TMPADDR, _vifMaskRegs; \ + mov VIF_TMPADDR, vifMaskRegs; \ movdqa XMM_WRITEMASK, xmmword ptr [VIF_TMPADDR + 64*(0)]; \ // ignore CL, since vif.cycle.wl == 1 #define UNPACK_Setup_Mask_SSE_2_1(CL) \ - mov VIF_TMPADDR, _vifMaskRegs; \ + mov VIF_TMPADDR, vifMaskRegs; \ movdqa XMM_ROWMASK, xmmword ptr [VIF_TMPADDR + 64*(0) + 16]; \ movdqa XMM_ROWCOLMASK, xmmword ptr [VIF_TMPADDR + 64*(0) + 32]; \ movdqa XMM_WRITEMASK, xmmword ptr [VIF_TMPADDR + 64*(0)]; \ @@ -1312,9 +1312,9 @@ #pragma warning(disable:4731) #define SAVE_ROW_REG_BASE \ - mov VIF_TMPADDR, _vifRow; \ + mov VIF_TMPADDR, vifRow; \ movdqa xmmword ptr [VIF_TMPADDR], XMM_ROW; \ - mov VIF_TMPADDR, _vifRegs; \ + mov VIF_TMPADDR, vifRegs; \ movss dword ptr [VIF_TMPADDR+0x100], XMM_ROW; \ psrldq XMM_ROW, 4; \ movss dword ptr [VIF_TMPADDR+0x110], XMM_ROW; \ @@ -1349,7 +1349,7 @@ .globl UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType; \ UNPACK_SkippingWrite_##name##_##sign##_##MaskType##_##ModeType: \ INIT_ARGS(); \ - mov VIF_TMPADDR, _vifRegs; \ + mov VIF_TMPADDR, vifRegs; \ movzx VIF_INC, byte ptr [VIF_TMPADDR + 0x40]; \ movzx VIF_SAVEEBX, byte ptr [VIF_TMPADDR + 0x41]; \ sub VIF_INC, VIF_SAVEEBX; \ diff --git a/pcsx2/x86/iCore.cpp b/pcsx2/x86/iCore.cpp index 6ab0be3488..97600e541f 100644 --- a/pcsx2/x86/iCore.cpp +++ b/pcsx2/x86/iCore.cpp @@ -18,7 +18,7 @@ #include "PrecompiledHeader.h" -#include "Misc.h" +#include "System.h" #include "iR5900.h" #include "Vif.h" #include "VU.h" @@ -40,41 +40,14 @@ u32 g_recWriteback = 0; char g_globalXMMLocked = 0; #endif -_xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; +_xmmregs xmmregs[iREGCNT_XMM], s_saveXMMregs[iREGCNT_XMM]; // X86 caching -_x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; +_x86regs x86regs[iREGCNT_GPR], s_saveX86regs[iREGCNT_GPR]; #include using namespace std; -//void _eeSetLoadStoreReg(int gprreg, u32 offset, int x86reg) -//{ -// int regs[2] = {ESI, EDI}; -// -// int i = _checkX86reg(X86TYPE_MEMOFFSET, gprreg, MODE_WRITE); -// if( i < 0 ) { -// for(i = 0; i < 2; ++i) { -// if( !x86regs[regs[i]].inuse ) break; -// } -// -// assert( i < 2 ); -// i = regs[i]; -// } -// -// if( i != x86reg ) MOV32RtoR(x86reg, i); -// x86regs[i].extra = offset; -//} - -//int _eeGeLoadStoreReg(int gprreg, int* poffset) -//{ -// int i = _checkX86reg(X86TYPE_MEMOFFSET, gprreg, MODE_READ); -// if( i >= 0 ) return -1; -// -// if( poffset ) *poffset = x86regs[i].extra; -// return i; -//} - // XMM Caching #define VU_VFx_ADDR(x) (uptr)&VU->VF[x].UL[0] #define VU_ACCx_ADDR (uptr)&VU->ACC.UL[0] @@ -107,8 +80,7 @@ __forceinline void* _XMMGetAddr(int type, int reg, VURegs *VU) case XMMTYPE_FPACC: return &fpuRegs.ACC.f; - default: - assert(0); + jNO_DEFAULT } return NULL; @@ -119,16 +91,16 @@ int _getFreeXMMreg() int i, tempi; u32 bestcount = 0x10000; - for (i=0; iregs[xmmregs[i].reg] & (EEINST_LIVE0|EEINST_LIVE1|EEINST_LIVE2)) ) { @@ -139,7 +111,7 @@ int _getFreeXMMreg() } // check for future xmm usage - for (i=0; iregs[xmmregs[i].reg] & EEINST_XMM) ) { @@ -151,7 +123,7 @@ int _getFreeXMMreg() tempi = -1; bestcount = 0xffff; - for (i=0; iregs[xmmregs[i].reg]&EEINST_USED) ) { @@ -951,12 +923,12 @@ void _moveXMMreg(int xmmreg) int i; if( !xmmregs[xmmreg].inuse ) return; - for (i=0; ichcr, p->madr, p->qwc, p->tadr, p->sadr); - } - __Log("dmac %x %x %x %x", psHu32(DMAC_CTRL), psHu32(DMAC_STAT), psHu32(DMAC_RBSR), psHu32(DMAC_RBOR)); - __Log("intc %x %x", psHu32(INTC_STAT), psHu32(INTC_MASK)); - __Log("sif: %x %x %x %x %x", psHu32(0xf200), psHu32(0xf220), psHu32(0xf230), psHu32(0xf240), psHu32(0xf260)); -#endif -} diff --git a/pcsx2/x86/iCore.h b/pcsx2/x86/iCore.h index 3397805068..1352be4157 100644 --- a/pcsx2/x86/iCore.h +++ b/pcsx2/x86/iCore.h @@ -114,7 +114,7 @@ struct _x86regs { u32 extra; // extra info assoc with the reg }; -extern _x86regs x86regs[X86REGS], s_saveX86regs[X86REGS]; +extern _x86regs x86regs[iREGCNT_GPR], s_saveX86regs[iREGCNT_GPR]; uptr _x86GetAddr(int type, int reg); void _initX86regs(); @@ -287,7 +287,7 @@ extern u32 g_recWriteback; // used for jumps (VUrec mess!) extern u32 g_cpuRegHasLive1, g_cpuPrevRegHasLive1; extern u32 g_cpuRegHasSignExt, g_cpuPrevRegHasSignExt; -extern _xmmregs xmmregs[XMMREGS], s_saveXMMregs[XMMREGS]; +extern _xmmregs xmmregs[iREGCNT_XMM], s_saveXMMregs[iREGCNT_XMM]; extern u16 g_x86AllocCounter; extern u16 g_xmmAllocCounter; @@ -361,10 +361,10 @@ void _recMove128MtoRmOffset(u32 offset, u32 from); // a negative shift is for sign extension extern int _signExtendGPRtoMMX(x86MMXRegType to, u32 gprreg, int shift); -extern _mmxregs mmxregs[MMXREGS], s_saveMMXregs[MMXREGS]; +extern _mmxregs mmxregs[iREGCNT_MMX], s_saveMMXregs[iREGCNT_MMX]; extern u16 x86FpuState; -extern void iDumpRegisters(u32 startpc, u32 temp); +// extern void iDumpRegisters(u32 startpc, u32 temp); ////////////////////////////////////////////////////////////////////////// // iFlushCall / _psxFlushCall Parameters diff --git a/pcsx2/x86/iFPUd.cpp b/pcsx2/x86/iFPUd.cpp index ec7b489b76..33a9693cc3 100644 --- a/pcsx2/x86/iFPUd.cpp +++ b/pcsx2/x86/iFPUd.cpp @@ -116,7 +116,7 @@ static u64 PCSX2_ALIGNED16(dbl_ps2_overflow) = DOUBLE(0,1152,0); //overflow & cl static u64 PCSX2_ALIGNED16(dbl_underflow) = DOUBLE(0,897,0); //underflow if below static u64 PCSX2_ALIGNED16(dbl_s_pos[2]) = {0x7fffffffffffffffULL, 0}; -static u64 PCSX2_ALIGNED16(dbl_s_neg[2]) = {0x8000000000000000ULL, 0}; +//static u64 PCSX2_ALIGNED16(dbl_s_neg[2]) = {0x8000000000000000ULL, 0}; // converts small normal numbers to double equivalent // converts large normal numbers (which represent NaN/inf in IEEE) to double equivalent diff --git a/pcsx2/x86/iMMI.cpp b/pcsx2/x86/iMMI.cpp index 4fe4632b0a..265f105b03 100644 --- a/pcsx2/x86/iMMI.cpp +++ b/pcsx2/x86/iMMI.cpp @@ -182,7 +182,7 @@ void recPMFHL() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) + int info = eeRecompileCodeXMM( XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI ); int t0reg; @@ -248,16 +248,14 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO|XMMINFO_READHI) assert(0); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PMFHL, _Rd_ ); + _clearNeededXMMregs(); } void recPMTHL() { if ( _Sa_ != 0 ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI ); if ( cpucaps.hasStreamingSIMD4Extensions ) { SSE4_BLENDPS_XMM_to_XMM(EEREC_LO, EEREC_S, 0x5); @@ -271,13 +269,11 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRIT SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0x72); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PMTHL, 0 ); + _clearNeededXMMregs(); } // MMX helper routines -#define MMX_ALLOC_TEMP1(code) { \ +/*#define MMX_ALLOC_TEMP1(code) { \ int t0reg; \ t0reg = _allocMMXreg(-1, MMX_TEMP, 0); \ code; \ @@ -315,35 +311,22 @@ CPU_SSE_XMMCACHE_END _freeMMXreg(t1reg); \ _freeMMXreg(t2reg); \ _freeMMXreg(t3reg); \ -} \ +} \*/ //////////////////////////////////////////////////// void recPSRLH( void ) { if ( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( (_Sa_&0xf) == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSRLWItoR( t0reg, _Sa_&0xf ); - PSRLWItoR( t1reg, _Sa_&0xf ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( (_Sa_&0xf) == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -351,28 +334,15 @@ void recPSRLW( void ) { if( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( _Sa_ == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSRLDItoR( t0reg, _Sa_ ); - PSRLDItoR( t1reg, _Sa_ ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( _Sa_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRLD_I8_to_XMM(EEREC_D,_Sa_ ); + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -380,28 +350,15 @@ void recPSRAH( void ) { if ( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( (_Sa_&0xf) == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSRAWItoR( t0reg, _Sa_&0xf ); - PSRAWItoR( t1reg, _Sa_&0xf ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( (_Sa_&0xf) == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -409,28 +366,15 @@ void recPSRAW( void ) { if ( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( _Sa_ == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSRADItoR( t0reg, _Sa_ ); - PSRADItoR( t1reg, _Sa_ ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( _Sa_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSRAD_I8_to_XMM(EEREC_D,_Sa_ ); + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -438,28 +382,15 @@ void recPSLLH( void ) { if ( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( (_Sa_&0xf) == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSLLWItoR( t0reg, _Sa_&0xf ); - PSLLWItoR( t1reg, _Sa_&0xf ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( (_Sa_&0xf) == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLW_I8_to_XMM(EEREC_D,_Sa_&0xf ); + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -467,28 +398,15 @@ void recPSLLW( void ) { if ( !_Rd_ ) return; - CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) - if( _Sa_ == 0 ) { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); - } - CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSLLDItoR( t0reg, _Sa_ ); - PSLLDItoR( t1reg, _Sa_ ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); + if( _Sa_ == 0 ) { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSLLD_I8_to_XMM(EEREC_D,_Sa_ ); + } + _clearNeededXMMregs(); } /* @@ -550,7 +468,7 @@ void recPMAXW() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if ( cpucaps.hasStreamingSIMD4Extensions ) { if( EEREC_S == EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); else if( EEREC_D == EEREC_S ) SSE4_PMAXSD_XMM_to_XMM(EEREC_D, EEREC_T); @@ -593,9 +511,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); } } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PMAXW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -603,51 +519,39 @@ void recPPACW() { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(((_Rs_!=0)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) - if( _Rs_ == 0 ) { + int info = eeRecompileCodeXMM( ((_Rs_!=0)?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); + + if( _Rs_ == 0 ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); + SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + } + else { + int t0reg = _allocTempXMMreg(XMMT_INT, -1); + if( EEREC_D == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); - SSE2_PSRLDQ_I8_to_XMM(EEREC_D, 8); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); + _freeXMMreg(t0reg); } else { - int t0reg = _allocTempXMMreg(XMMT_INT, -1); - if( EEREC_D == EEREC_T ) { - SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_S, 0x88); - SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); - SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, t0reg); - _freeXMMreg(t0reg); - } - else { - SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); - SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); - SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); + SSE2_PSHUFD_XMM_to_XMM(t0reg, EEREC_T, 0x88); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x88); + SSE2_PUNPCKLQDQ_XMM_to_XMM(t0reg, EEREC_D); - // swap mmx regs.. don't ask - xmmregs[t0reg] = xmmregs[EEREC_D]; - xmmregs[EEREC_D].inuse = 0; - } + // swap mmx regs.. don't ask + xmmregs[t0reg] = xmmregs[EEREC_D]; + xmmregs[EEREC_D].inuse = 0; } -CPU_SSE_XMMCACHE_END + } - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - Crude but quicker than int - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); //Copy this one cos it could get overwritten - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[2]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], ECX); //This is where we bring it back - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); + _clearNeededXMMregs(); } void recPPACH( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x88); SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x88); @@ -667,28 +571,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - Crude but quicker than int - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[6]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[7], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[6]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[2]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[5], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[4]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[6], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[4]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[2], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[0]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[4], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[0], EAX); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -696,7 +579,7 @@ void recPPACB() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _hasFreeXMMreg() ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -728,9 +611,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PACKUSWB_XMM_to_XMM(EEREC_D, t0reg); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PPACB, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -738,7 +619,7 @@ void recPEXT5() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); @@ -766,9 +647,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); _freeXMMreg(t1reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PEXT5, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -776,7 +655,7 @@ void recPPAC5() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); @@ -806,9 +685,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); _freeXMMreg(t1reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PPAC5, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -816,29 +693,14 @@ void recPMAXH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PMAXSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - SSE_PMAXSW_MM_to_MM( t0reg, t1reg ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - SSE_PMAXSW_MM_to_MM( t2reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -846,7 +708,7 @@ void recPCGTB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D != EEREC_T ) { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, EEREC_T); @@ -858,24 +720,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSE2_PCMPGTB_XMM_to_XMM(EEREC_D, t0reg); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - PCMPGTBRtoR( t0reg, t1reg ); - - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PCMPGTBRtoR( t2reg, t3reg); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -883,7 +728,7 @@ void recPCGTH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D != EEREC_T ) { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, EEREC_T); @@ -895,24 +740,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSE2_PCMPGTW_XMM_to_XMM(EEREC_D, t0reg); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - - PCMPGTWRtoR( t0reg, t1reg ); - PCMPGTWRtoR( t2reg, t3reg); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -921,7 +749,7 @@ void recPCGTW( void ) //TODO:optimize RS | RT== 0 if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D != EEREC_T ) { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, EEREC_T); @@ -933,24 +761,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSE2_PCMPGTD_XMM_to_XMM(EEREC_D, t0reg); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - - PCMPGTDRtoR( t0reg, t1reg ); - PCMPGTDRtoR( t2reg, t3reg); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t2reg); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -958,29 +769,14 @@ void recPADDSB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PADDSB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDSBRtoR( t0reg, t2reg); - PADDSBRtoR( t1reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -988,29 +784,14 @@ void recPADDSH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PADDSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDSWRtoR( t0reg, t2reg); - PADDSWRtoR( t1reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1019,7 +800,7 @@ void recPADDSW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); int t2reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1063,16 +844,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); _freeXMMreg(t1reg); _freeXMMreg(t2reg); -CPU_SSE_XMMCACHE_END - - if( _Rd_ ) _deleteEEreg(_Rd_, 0); - _deleteEEreg(_Rs_, 1); - _deleteEEreg(_Rt_, 1); - _flushConstRegs(); - - MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); - MOV32ItoM( (uptr)&cpuRegs.pc, pc ); - CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PADDSW ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1080,7 +852,7 @@ void recPSUBSB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1093,22 +865,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBSB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSUBSBRtoR( t0reg, t2reg); - PSUBSBRtoR( t1reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1116,7 +873,7 @@ void recPSUBSH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1129,22 +886,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSUBSWRtoR( t0reg, t2reg); - PSUBSWRtoR( t1reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1153,7 +895,7 @@ void recPSUBSW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); int t2reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1200,16 +942,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); _freeXMMreg(t1reg); _freeXMMreg(t2reg); -CPU_SSE_XMMCACHE_END - - if( _Rd_ ) _deleteEEreg(_Rd_, 0); - _deleteEEreg(_Rs_, 1); - _deleteEEreg(_Rt_, 1); - _flushConstRegs(); - - MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); - MOV32ItoM( (uptr)&cpuRegs.pc, pc ); - CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PSUBSW ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1217,29 +950,14 @@ void recPADDB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PADDB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDBRtoR( t0reg, t2reg ); - PADDBRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1247,7 +965,7 @@ void recPADDH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); @@ -1263,22 +981,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMI SSE2_PADDW_XMM_to_XMM(EEREC_D, EEREC_T); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDWRtoR( t0reg, t2reg ); - PADDWRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1286,7 +989,7 @@ void recPADDW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); else SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); @@ -1302,22 +1005,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMI SSE2_PADDD_XMM_to_XMM(EEREC_D, EEREC_T); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDDRtoR( t0reg, t2reg ); - PADDDRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1325,7 +1013,7 @@ void recPSUBB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1338,22 +1026,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSUBBRtoR( t0reg, t2reg ); - PSUBBRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1361,7 +1034,7 @@ void recPSUBH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1374,22 +1047,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSUBWRtoR( t0reg, t2reg ); - PSUBWRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1397,7 +1055,7 @@ void recPSUBW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1410,22 +1068,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBD_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PSUBDRtoR( t0reg, t2reg); - PSUBDRtoR( t1reg, t3reg); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1433,7 +1076,7 @@ void recPEXTLW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); @@ -1452,27 +1095,14 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKLDQ_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 1 ] ); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ] ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); + _clearNeededXMMregs(); } void recPEXTLB( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); @@ -1491,53 +1121,14 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKLBW_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - Crude but quicker than int - //Console::WriteLn("PEXTLB"); - //Rs = cpuRegs.GPR.r[_Rs_]; Rt = cpuRegs.GPR.r[_Rt_]; - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[7]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[7]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[6]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[6]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[5]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[5]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[4]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[4]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[3]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[3]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[2]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[2]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[1]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[1]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[0]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[0]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); + _clearNeededXMMregs(); } void recPEXTLH( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); @@ -1556,28 +1147,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKLWD_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - Crude but quicker than int - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[3]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[7], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[3]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[6], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[2]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[5], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[4], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[1]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[1]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[2], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[0]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); - MOV16MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); - MOV16RtoM((uptr)&cpuRegs.GPR.r[_Rd_].US[0], EAX); + _clearNeededXMMregs(); } #endif @@ -1621,7 +1191,7 @@ void recPABSW() //needs clamping { if( !_Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_PCMPEQD_XMM_to_XMM(t0reg, t0reg); SSE2_PSLLD_I8_to_XMM(t0reg, 31); @@ -1640,15 +1210,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) } SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x80000000 -> 0x7fffffff _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - _deleteEEreg(_Rt_, 1); - _deleteEEreg(_Rd_, 0); - _flushConstRegs(); - - MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); - MOV32ItoM( (uptr)&cpuRegs.pc, pc ); - CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PABSW ); + _clearNeededXMMregs(); } @@ -1657,7 +1219,7 @@ void recPABSH() { if( !_Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_PCMPEQW_XMM_to_XMM(t0reg, t0reg); SSE2_PSLLW_I8_to_XMM(t0reg, 15); @@ -1676,15 +1238,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) } SSE2_PXOR_XMM_to_XMM(EEREC_D, t0reg); //0x8000 -> 0x7fff _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - _deleteEEreg(_Rt_, 1); - _deleteEEreg(_Rd_, 0); - _flushConstRegs(); - - MOV32ItoM( (uptr)&cpuRegs.code, cpuRegs.code ); - MOV32ItoM( (uptr)&cpuRegs.pc, pc ); - CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PABSW ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1692,7 +1246,7 @@ void recPMINW() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if ( cpucaps.hasStreamingSIMD4Extensions ) { if( EEREC_S == EEREC_T ) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); else if( EEREC_D == EEREC_S ) SSE4_PMINSD_XMM_to_XMM(EEREC_D, EEREC_T); @@ -1735,9 +1289,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); } } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PMINW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1745,7 +1297,7 @@ void recPADSBH() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); int t0reg; if( EEREC_S == EEREC_T ) { @@ -1776,9 +1328,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PADSBH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1786,7 +1336,7 @@ void recPADDUW() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rt_ == 0 ) { if( _Rs_ == 0 ) { @@ -1824,9 +1374,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR _freeXMMreg(t0reg); _freeXMMreg(t1reg); } - -CPU_SSE_XMMCACHE_END - recCall( Interp::PADDUW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1834,7 +1382,7 @@ void recPSUBUB() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1847,9 +1395,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBUSB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PSUBUB, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1857,7 +1403,7 @@ void recPSUBUH() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1870,9 +1416,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PSUBUSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PSUBUH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1880,7 +1424,7 @@ void recPSUBUW() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); @@ -1918,9 +1462,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) _freeXMMreg(t0reg); _freeXMMreg(t1reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PSUBUW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -1928,7 +1470,7 @@ void recPEXTUH() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLD_I8_to_XMM(EEREC_D, 16); @@ -1947,23 +1489,21 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PEXTUH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// // Both Macros are 16 bytes so we can use a shift instead of a Mul instruction #define QFSRVhelper0() { \ ajmp[0] = JMP32(0); \ - x86Ptr[0] += 11; \ + x86Ptr += 11; \ } #define QFSRVhelper(shift1, shift2) { \ SSE2_PSRLDQ_I8_to_XMM(EEREC_D, shift1); \ SSE2_PSLLDQ_I8_to_XMM(t0reg, shift2); \ ajmp[shift1] = JMP32(0); \ - x86Ptr[0] += 1; \ + x86Ptr += 1; \ } void recQFSRV() @@ -1971,42 +1511,41 @@ void recQFSRV() if ( !_Rd_ ) return; //Console::WriteLn("recQFSRV()"); - CPU_SSE2_XMMCACHE_START( XMMINFO_READS | XMMINFO_READT | XMMINFO_WRITED ) + int info = eeRecompileCodeXMM( XMMINFO_READS | XMMINFO_READT | XMMINFO_WRITED ); - u32 *ajmp[16]; - int i, j; - int t0reg = _allocTempXMMreg(XMMT_INT, -1); + u32 *ajmp[16]; + int i, j; + int t0reg = _allocTempXMMreg(XMMT_INT, -1); - SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); - SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); + SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_T); - MOV32MtoR(EAX, (uptr)&cpuRegs.sa); - SHL32ItoR(EAX, 4); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros) - AND32I8toR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes) - ADD32ItoEAX((uptr)x86Ptr[0] + 7); // ADD32 = 5 bytes, JMPR = 2 bytes - JMPR(EAX); // Jumps to a QFSRVhelper() case below (a total of 16 different cases) + MOV32MtoR(EAX, (uptr)&cpuRegs.sa); + SHL32ItoR(EAX, 4); // Multiply SA bytes by 16 bytes (the amount of bytes in QFSRVhelper() macros) + AND32ItoR(EAX, 0xf0); // This can possibly be removed but keeping it incase theres garbage in SA (cottonvibes) + ADD32ItoR(EAX, (uptr)x86Ptr + 7); // ADD32 = 5 bytes, JMPR = 2 bytes + JMPR(EAX); // Jumps to a QFSRVhelper() case below (a total of 16 different cases) + + // Case 0: + QFSRVhelper0(); + + // Cases 1 to 15: + for (i = 1, j = 15; i < 16; i++, j--) { + QFSRVhelper(i, j); + } + + // Set jump addresses for the JMP32's in QFSRVhelper() + for (i = 1; i < 16; i++) { + x86SetJ32(ajmp[i]); + } + + // Concatenate the regs after appropriate shifts have been made + SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); - // Case 0: - QFSRVhelper0(); + x86SetJ32(ajmp[0]); // Case 0 jumps to here (to skip the POR) + _freeXMMreg(t0reg); - // Cases 1 to 15: - for (i = 1, j = 15; i < 16; i++, j--) { - QFSRVhelper(i, j); - } - - // Set jump addresses for the JMP32's in QFSRVhelper() - for (i = 1; i < 16; i++) { - x86SetJ32(ajmp[i]); - } - - // Concatenate the regs after appropriate shifts have been made - SSE2_POR_XMM_to_XMM(EEREC_D, t0reg); - - x86SetJ32(ajmp[0]); // Case 0 jumps to here (to skip the POR) - _freeXMMreg(t0reg); - - CPU_SSE_XMMCACHE_END - //recCall( Interp::QFSRV, _Rd_ ); + _clearNeededXMMregs(); } @@ -2014,7 +1553,8 @@ void recPEXTUB( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); + if( _Rs_ == 0 ) { SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLW_I8_to_XMM(EEREC_D, 8); @@ -2033,44 +1573,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKHBW_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - Crude but faster than int - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[8]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[0], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[8]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[1], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[9]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[2], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[9]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[3], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[10]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[4], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[10]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[5], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[11]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[6], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[11]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[7], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[12]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[8], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[12]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[9], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[13]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[10], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[13]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[11], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[14]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[12], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[14]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[13], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UC[15]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[14], EAX); - MOV8MtoR(EAX, (uptr)&cpuRegs.GPR.r[_Rs_].UC[15]); - MOV8RtoM((uptr)&cpuRegs.GPR.r[_Rd_].UC[15], EAX); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2078,7 +1581,7 @@ void recPEXTUW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED ); if( _Rs_ == 0 ) { SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PSRLQ_I8_to_XMM(EEREC_D, 32); @@ -2097,20 +1600,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|XMMINFO_READT|XMMINFO_WRITED) SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_D, EEREC_S); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 2 ] ); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 2 ] ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], ECX ); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UL[ 3 ] ); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UL[ 3 ] ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], ECX ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2118,29 +1608,14 @@ void recPMINH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PMINSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - SSE_PMINSW_MM_to_MM( t0reg, t2reg ); - SSE_PMINSW_MM_to_MM( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2148,30 +1623,14 @@ void recPCEQB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPEQB_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PCMPEQBRtoR( t0reg, t2reg ); - PCMPEQBRtoR( t1reg, t3reg ); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2179,30 +1638,14 @@ void recPCEQH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPEQW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PCMPEQWRtoR( t0reg, t2reg ); - PCMPEQWRtoR( t1reg, t3reg ); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2210,30 +1653,14 @@ void recPCEQW( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PCMPEQD_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PCMPEQDRtoR( t0reg, t2reg ); - PCMPEQDRtoR( t1reg, t3reg ); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2241,7 +1668,7 @@ void recPADDUB( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rt_ ) { if( EEREC_D == EEREC_S ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PADDUSB_XMM_to_XMM(EEREC_D, EEREC_S); @@ -2251,22 +1678,7 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) } } else SSE2_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDUSBRtoR( t0reg, t2reg ); - PADDUSBRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2274,29 +1686,14 @@ void recPADDUH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); else if( EEREC_D == EEREC_T ) SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_S); else { SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSE2_PADDUSW_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP4( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t2reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQMtoR( t3reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PADDUSWRtoR( t0reg, t2reg ); - PADDUSWRtoR( t1reg, t3reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } #endif @@ -2342,7 +1739,8 @@ void recPMADDW() recCall( Interp::PMADDW, _Rd_ ); return; } -CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + + int info = eeRecompileCodeXMM( (((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI ); SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); // LO = {LO[0], HI[0], LO[2], HI[2]} if( _Rd_ ) { @@ -2377,7 +1775,7 @@ CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMM } SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_LO, EEREC_LO); SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_HI, EEREC_HI); -CPU_SSE_XMMCACHE_END + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2386,7 +1784,7 @@ void recPSLLVW() if ( ! _Rd_ ) return; EEINST_SETSIGNEXT(_Rd_); -CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) { SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); @@ -2444,8 +1842,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR _freeXMMreg(t0reg); _freeXMMreg(t1reg); } -CPU_SSE_XMMCACHE_END - recCall( Interp::PSLLVW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2454,7 +1851,7 @@ void recPSRLVW() if ( ! _Rd_ ) return; EEINST_SETSIGNEXT(_Rd_); -CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) { SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); @@ -2512,9 +1909,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR _freeXMMreg(t0reg); _freeXMMreg(t1reg); } - -CPU_SSE_XMMCACHE_END - recCall( Interp::PSRLVW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2527,7 +1922,7 @@ void recPMSUBW() recCall( Interp::PMSUBW, _Rd_ ); return; } -CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int info = eeRecompileCodeXMM( (((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI ); SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); // LO = {LO[0], HI[0], LO[2], HI[2]} if( _Rd_ ) { @@ -2568,7 +1963,7 @@ CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMM } SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_LO, EEREC_LO); SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_HI, EEREC_HI); -CPU_SSE_XMMCACHE_END + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2581,7 +1976,7 @@ void recPMULTW() recCall( Interp::PMULTW, _Rd_ ); return; } -CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI ); if( !_Rs_ || !_Rt_ ) { if( _Rd_ ) SSE2_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); SSE2_PXOR_XMM_to_XMM(EEREC_LO, EEREC_LO); @@ -2613,7 +2008,7 @@ CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMM SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_LO, EEREC_LO); SSE4_PMOVSXDQ_XMM_to_XMM(EEREC_HI, EEREC_HI); } -CPU_SSE_XMMCACHE_END + _clearNeededXMMregs(); } //////////////////////////////////////////////////// void recPDIVW() @@ -2636,7 +2031,7 @@ PCSX2_ALIGNED16(int s_mask1[4]) = {~0, 0, ~0, 0}; //contains the upper multiplication result (before the addition with the lower multiplication result) void recPHMADH() { -CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSEX_MOVDQA_XMM_to_XMM(t0reg, EEREC_S); @@ -2671,17 +2066,12 @@ CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMI SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PHMADH, _Rd_ ); + _clearNeededXMMregs(); } -//////////////////////////////////////////////////// -//upper word of each doubleword in LO and HI is undocumented/undefined -//contains the NOT of the upper multiplication result (before the substraction of the lower multiplication result) void recPMSUBH() { - CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); @@ -2735,20 +2125,15 @@ void recPMSUBH() _freeXMMreg(t0reg); _freeXMMreg(t1reg); -CPU_SSE_XMMCACHE_END - recCall( Interp::PMSUBH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// - -// rs = ... a1 a0 -// rt = ... b1 b0 -// rd = ... a1*b1 - a0*b0 -// hi = ... -// lo = ... (undefined by doc)NOT(a1*b1), a1*b1 - a0*b0 +//upper word of each doubleword in LO and HI is undocumented/undefined +//it contains the NOT of the upper multiplication result (before the substraction of the lower multiplication result) void recPHMSBH() { -CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITELO|XMMINFO_WRITEHI ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE2_PCMPEQD_XMM_to_XMM(EEREC_LO, EEREC_LO); @@ -2775,9 +2160,7 @@ CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMI SSE_SHUFPS_XMM_to_XMM(EEREC_HI, EEREC_HI, 0xd8); _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PHMSBH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2785,12 +2168,10 @@ void recPEXEH( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xc6); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PEXEH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2799,12 +2180,10 @@ void recPREVH( void ) if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0x1B); SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0x1B); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PREVH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -2812,7 +2191,7 @@ void recPINTH( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED ); if( EEREC_D == EEREC_S ) { int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSE_MOVHLPS_XMM_to_XMM(t0reg, EEREC_S); @@ -2824,80 +2203,30 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|XMMINFO_WRITED) SSE_MOVLHPS_XMM_to_XMM(EEREC_D, EEREC_T); SSE2_PUNPCKHWD_XMM_to_XMM(EEREC_D, EEREC_S); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //Done - Refraction - MOV16MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[4]); - MOV16MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].US[1]); - MOV16MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].US[2]); - MOV16MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].US[0]); - - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[1], EAX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[2], EBX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[4], ECX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[0], EDX); - - MOV16MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].US[5]); - MOV16MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rs_].US[6]); - MOV16MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rs_].US[7]); - MOV16MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].US[3]); - - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[3], EAX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[5], EBX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[7], ECX); - MOV16RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].US[6], EDX); + _clearNeededXMMregs(); } void recPEXEW( void ) { if (!_Rd_) return; -CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc6); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); - MOV32MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[1]); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); - MOV32MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[3]); - - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); + _clearNeededXMMregs(); } void recPROT3W( void ) { if (!_Rd_) return; -CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xc9); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MOV32MtoR( EAX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[1]); - MOV32MtoR( EBX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[2]); - MOV32MtoR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[0]); - MOV32MtoR( EDX, (uptr)&cpuRegs.GPR.r[_Rt_].UL[3]); - - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EBX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], ECX); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EDX); + _clearNeededXMMregs(); } void recPMULTH( void ) { -CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); @@ -2927,102 +2256,16 @@ CPU_SSE2_XMMCACHE_START(XMMINFO_READS|XMMINFO_READT|(_Rd_?XMMINFO_WRITED:0)|XMMI SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_HI, t0reg); _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - _deleteEEreg(XMMGPR_LO, 0); - _deleteEEreg(XMMGPR_HI, 0); - _deleteGPRtoXMMreg(_Rs_, 1); - _deleteGPRtoXMMreg(_Rt_, 1); - - if(!_Rt_ || !_Rs_) { - MOV32ItoM( (uptr)&cpuRegs.LO.UL[0], 0); - MOV32ItoM( (uptr)&cpuRegs.LO.UL[1], 0); - MOV32ItoM( (uptr)&cpuRegs.LO.UL[2], 0); - MOV32ItoM( (uptr)&cpuRegs.LO.UL[3], 0); - MOV32ItoM( (uptr)&cpuRegs.HI.UL[0], 0); - MOV32ItoM( (uptr)&cpuRegs.HI.UL[1], 0); - MOV32ItoM( (uptr)&cpuRegs.HI.UL[2], 0); - MOV32ItoM( (uptr)&cpuRegs.HI.UL[3], 0); - - if( _Rd_ ) { - MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], 0); - MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], 0); - MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], 0); - MOV32ItoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], 0); - } - return; - } - - //Done - Refraction - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[0]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[0]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.LO.UL[0], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[1]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[1]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.LO.UL[1], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[2]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[2]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.HI.UL[0], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[3]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[3]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.HI.UL[1], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[4]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[4]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.LO.UL[2], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[5]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[5]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.LO.UL[3], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[6]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[6]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.HI.UL[2], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[7]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[7]); - IMUL32RtoR( EAX, ECX); - MOV32RtoM( (uptr)&cpuRegs.HI.UL[3], EAX); - - if (_Rd_) { - MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[2]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[2]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); - } + _clearNeededXMMregs(); } void recPMFHI( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READHI) + int info = eeRecompileCodeXMM( XMMINFO_WRITED|XMMINFO_READHI ); SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_HI); -CPU_SSE_XMMCACHE_END - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.HI.UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.HI.UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3030,20 +2273,9 @@ void recPMFLO( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READLO) + int info = eeRecompileCodeXMM( XMMINFO_WRITED|XMMINFO_READLO ); SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_LO); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.LO.UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.LO.UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3051,7 +2283,7 @@ void recPAND( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + int info = eeRecompileCodeXMM( XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT ); if( EEREC_D == EEREC_T ) { SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_S); } @@ -3062,20 +2294,7 @@ CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSEX_PAND_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - PANDMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - PANDMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3083,7 +2302,7 @@ void recPXOR( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) + int info = eeRecompileCodeXMM( XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT ); if( EEREC_D == EEREC_T ) { SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_S); } @@ -3094,21 +2313,7 @@ CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|XMMINFO_READS|XMMINFO_READT) SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_T); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - PXORMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - PXORMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3116,39 +2321,28 @@ void recPCPYLD( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_WRITED|(( _Rs_== 0) ? 0:XMMINFO_READS)|XMMINFO_READT) - if( _Rs_ == 0 ) { - SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + int info = eeRecompileCodeXMM( XMMINFO_WRITED|(( _Rs_== 0) ? 0:XMMINFO_READS)|XMMINFO_READT ); + if( _Rs_ == 0 ) { + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + } + else { + if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); + else if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); } else { - if( EEREC_D == EEREC_T ) SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); - else if( EEREC_S == EEREC_T ) SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0x44); - else if( EEREC_D == EEREC_S ) { - SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); - } - else { - SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); - SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); - } + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_T); + SSE2_PUNPCKLQDQ_XMM_to_XMM(EEREC_D, EEREC_S); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t1reg ); - SetMMXstate(); - ) + } + _clearNeededXMMregs(); } void recPMADDH( void ) { - CPU_SSE2_XMMCACHE_START((_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (_Rd_?XMMINFO_WRITED:0)|XMMINFO_READS|XMMINFO_READT|XMMINFO_READLO|XMMINFO_READHI|XMMINFO_WRITELO|XMMINFO_WRITEHI ); int t0reg = _allocTempXMMreg(XMMT_INT, -1); int t1reg = _allocTempXMMreg(XMMT_INT, -1); @@ -3202,69 +2396,7 @@ void recPMADDH( void ) _freeXMMreg(t0reg); _freeXMMreg(t1reg); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - _deleteEEreg(XMMGPR_LO, 1); - _deleteEEreg(XMMGPR_HI, 1); - _deleteGPRtoXMMreg(_Rs_, 1); - _deleteGPRtoXMMreg(_Rt_, 1); - - if(_Rt_ && _Rs_){ - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[0]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[0]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.LO.UL[0], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[1]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[1]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.LO.UL[1], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[2]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[2]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.HI.UL[0], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[3]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[3]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.HI.UL[1], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[4]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[4]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.LO.UL[2], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[5]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[5]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.LO.UL[3], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[6]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[6]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.HI.UL[2], EAX); - - MOVSX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[_Rs_].SS[7]); - MOVSX32M16toR( ECX, (uptr)&cpuRegs.GPR.r[_Rt_].SS[7]); - IMUL32RtoR( EAX, ECX); - ADD32RtoM( (uptr)&cpuRegs.HI.UL[3], EAX); - - } - - if (_Rd_) { - MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[0], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[0]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[1], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.LO.UL[2]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[2], EAX); - MOV32MtoR( EAX, (uptr)&cpuRegs.HI.UL[2]); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[_Rd_].UL[3], EAX); - } + _clearNeededXMMregs(); } #endif @@ -3298,7 +2430,7 @@ void recPSRAVW() if ( ! _Rd_ ) return; EEINST_SETSIGNEXT(_Rd_); -CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) { SSEX_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); @@ -3357,13 +2489,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR _freeXMMreg(t1reg); } -CPU_SSE_XMMCACHE_END - - MOV32ItoM( (uptr)&cpuRegs.code, (u32)cpuRegs.code ); - MOV32ItoM( (uptr)&cpuRegs.pc, (u32)pc ); - iFlushCall(FLUSH_EVERYTHING); - if( _Rd_ > 0 ) _deleteEEreg(_Rd_, 0); - CALLFunc( (uptr)R5900::Interpreter::OpcodeImpl::MMI::PSRAVW ); + _clearNeededXMMregs(); } @@ -3374,7 +2500,7 @@ void recPINTEH() { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WRITED ); int t0reg = -1; @@ -3417,9 +2543,7 @@ CPU_SSE2_XMMCACHE_START((_Rs_?XMMINFO_READS:0)|(_Rt_?XMMINFO_READT:0)|XMMINFO_WR } if( t0reg >= 0 ) _freeXMMreg(t0reg); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PINTEH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3428,7 +2552,7 @@ void recPMULTUW() if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); EEINST_SETSIGNEXT(_Rs_); EEINST_SETSIGNEXT(_Rt_); -CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( (((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI ); if( !_Rs_ || !_Rt_ ) { if( _Rd_ ) SSE2_PXOR_XMM_to_XMM(EEREC_D, EEREC_D); SSE2_PXOR_XMM_to_XMM(EEREC_LO, EEREC_LO); @@ -3468,8 +2592,7 @@ CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMM _freeXMMreg(t0reg); } } -CPU_SSE_XMMCACHE_END - recCall( Interp::PMULTUW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3478,7 +2601,7 @@ void recPMADDUW() if( _Rd_ ) EEINST_SETSIGNEXT(_Rd_); EEINST_SETSIGNEXT(_Rs_); EEINST_SETSIGNEXT(_Rt_); -CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI) + int info = eeRecompileCodeXMM( (((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMMINFO_READT:0)|(_Rd_?XMMINFO_WRITED:0)|XMMINFO_WRITELO|XMMINFO_WRITEHI|XMMINFO_READLO|XMMINFO_READHI ); SSE_SHUFPS_XMM_to_XMM(EEREC_LO, EEREC_HI, 0x88); SSE2_PSHUFD_XMM_to_XMM(EEREC_LO, EEREC_LO, 0xd8); // LO = {LO[0], HI[0], LO[2], HI[2]} if( _Rd_ ) { @@ -3523,9 +2646,7 @@ CPU_SSE2_XMMCACHE_START((((_Rs_)&&(_Rt_))?XMMINFO_READS:0)|(((_Rs_)&&(_Rt_))?XMM SSE2_PUNPCKHDQ_XMM_to_XMM(EEREC_HI, t0reg); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - recCall( Interp::PMADDUW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3542,11 +2663,9 @@ void recPEXCW() { if (!_Rd_) return; -CPU_SSE_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); -CPU_SSE_XMMCACHE_END - -recCall( Interp::PEXCW, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3554,12 +2673,10 @@ void recPEXCH( void ) { if (!_Rd_) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0xd8); SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0xd8); -CPU_SSE_XMMCACHE_END - - recCall( Interp::PEXCH, _Rd_ ); + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3567,7 +2684,7 @@ void recPNOR( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) { @@ -3612,110 +2729,60 @@ CPU_SSE2_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMI SSEX_PXOR_XMM_to_XMM( EEREC_D, t0reg ); _freeXMMreg(t0reg); } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP3( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - PORMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - PORMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - PCMPEQDRtoR( t2reg, t2reg ); - PXORRtoR( t0reg, t2reg ); - PXORRtoR( t1reg, t2reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// void recPMTHI( void ) { -CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITEHI) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_WRITEHI ); SSEX_MOVDQA_XMM_to_XMM(EEREC_HI, EEREC_S); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(XMMGPR_HI, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.HI.UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.HI.UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// void recPMTLO( void ) { -CPU_SSE_XMMCACHE_START(XMMINFO_READS|XMMINFO_WRITELO) + int info = eeRecompileCodeXMM( XMMINFO_READS|XMMINFO_WRITELO ); SSEX_MOVDQA_XMM_to_XMM(EEREC_LO, EEREC_S); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(XMMGPR_LO, 0); - _deleteGPRtoXMMreg(_Rs_, 1); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.LO.UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.LO.UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// void recPCPYUD( void ) { - if ( ! _Rd_ ) return; + if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START(XMMINFO_READS|(( _Rt_ == 0) ? 0:XMMINFO_READT)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READS|(( _Rt_ == 0) ? 0:XMMINFO_READT)|XMMINFO_WRITED ); - if( _Rt_ == 0 ) { - if( EEREC_D == EEREC_S ) { - SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); - SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); - } - else { - SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); - SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); - } + if( _Rt_ == 0 ) { + if( EEREC_D == EEREC_S ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); } else { - if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); - else if( EEREC_D == EEREC_T ) { - //TODO - SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); - SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + SSE_MOVHLPS_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_MOVQ_XMM_to_XMM(EEREC_D, EEREC_D); + } + } + else { + if( EEREC_D == EEREC_S ) SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); + else if( EEREC_D == EEREC_T ) { + //TODO + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_D, 0x4e); + } + else { + if( EEREC_S == EEREC_T ) { + SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); } else { - if( EEREC_S == EEREC_T ) { - SSE2_PSHUFD_XMM_to_XMM(EEREC_D, EEREC_S, 0xee); - } - else { - SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); - SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); - } + SSEX_MOVDQA_XMM_to_XMM(EEREC_D, EEREC_S); + SSE2_PUNPCKHQDQ_XMM_to_XMM(EEREC_D, EEREC_T); } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + } + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3723,7 +2790,7 @@ void recPOR( void ) { if ( ! _Rd_ ) return; -CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( (_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMINFO_WRITED ); if( _Rs_ == 0 ) { if( _Rt_ == 0 ) { @@ -3752,23 +2819,7 @@ CPU_SSE_XMMCACHE_START((_Rs_!=0?XMMINFO_READS:0)|(_Rt_!=0?XMMINFO_READT:0)|XMMIN } } } -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - MMX_ALLOC_TEMP2( - MOVQMtoR( t0reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 0 ] ); - MOVQMtoR( t1reg, (uptr)&cpuRegs.GPR.r[ _Rs_ ].UD[ 1 ] ); - if ( _Rt_ != 0 ) - { - PORMtoR ( t0reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - PORMtoR ( t1reg, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - } - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 0 ], t0reg ); - MOVQRtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UD[ 1 ], t1reg ); - SetMMXstate(); - ) + _clearNeededXMMregs(); } //////////////////////////////////////////////////// @@ -3776,28 +2827,10 @@ void recPCPYH( void ) { if ( ! _Rd_ ) return; -CPU_SSE2_XMMCACHE_START(XMMINFO_READT|XMMINFO_WRITED) + int info = eeRecompileCodeXMM( XMMINFO_READT|XMMINFO_WRITED ); SSE2_PSHUFLW_XMM_to_XMM(EEREC_D, EEREC_T, 0); SSE2_PSHUFHW_XMM_to_XMM(EEREC_D, EEREC_D, 0); -CPU_SSE_XMMCACHE_END - - _flushCachedRegs(); - _deleteEEreg(_Rd_, 0); - - //PUSH32R( EBX ); - MOVZX32M16toR( EAX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 0 ] ); - MOV32RtoR( ECX, EAX ); - SHL32ItoR( ECX, 16 ); - OR32RtoR( EAX, ECX ); - MOVZX32M16toR( EDX, (uptr)&cpuRegs.GPR.r[ _Rt_ ].UD[ 1 ] ); - MOV32RtoR( ECX, EDX ); - SHL32ItoR( ECX, 16 ); - OR32RtoR( EDX, ECX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 0 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ], EAX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 2 ], EDX ); - MOV32RtoM( (uptr)&cpuRegs.GPR.r[ _Rd_ ].UL[ 3 ], EDX ); - //POP32R( EBX ); + _clearNeededXMMregs(); } #endif // else MMI3_RECOMPILE diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index a1b1ec756d..4ee56ee010 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -24,6 +24,8 @@ #include "PrecompiledHeader.h" #include "iR3000A.h" +#include "BaseblockEx.h" + #include #ifndef _WIN32 @@ -105,32 +107,29 @@ u32 psxdump = 0; //////////////////////////////////////////////////// #ifdef _DEBUG using namespace R3000A; +#include "Utilities/AsciiFile.h" + static void iIopDumpBlock( int startpc, u8 * ptr ) { - FILE *f; -#ifdef __LINUX__ - char command[256]; -#endif u32 i, j; EEINST* pcur; u8 used[34]; int numused, count; Console::WriteLn( "dump1 %x:%x, %x", params startpc, psxpc, psxRegs.cycle ); - Path::CreateDirectory( "dumps" ); + Path::CreateDirectory( L"dumps" ); - string filename( Path::Combine( "dumps", fmt_string( "psxdump%.8X.txt", startpc ) ) ); + AsciiFile f( + Path::Combine( g_Conf.Folders.Dumps, wxsFormat( L"psxdump%.8X.txt", startpc ) ), + wxFile::write + ); - fflush( stdout ); - - f = fopen( filename.c_str(), "w" ); - assert( f != NULL ); for ( i = startpc; i < s_nEndBlock; i += 4 ) { - fprintf( f, "%s\n", disR3000Fasm( iopMemRead32( i ), i ) ); + f.Printf("%s\n", disR3000Fasm( iopMemRead32( i ), i ) ); } // write the instruction info - fprintf(f, "\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); + f.Printf("\n\nlive0 - %x, lastuse - %x used - %x\n", EEINST_LIVE0, EEINST_LASTUSE, EEINST_USED); memzero_obj(used); numused = 0; @@ -141,37 +140,37 @@ static void iIopDumpBlock( int startpc, u8 * ptr ) } } - fprintf(f, " "); + f.Printf(" "); for(i = 0; i < ArraySize(s_pInstCache->regs); ++i) { - if( used[i] ) fprintf(f, "%2d ", i); + if( used[i] ) f.Printf("%2d ", i); } - fprintf(f, "\n"); + f.Printf("\n"); - fprintf(f, " "); + f.Printf(" "); for(i = 0; i < ArraySize(s_pInstCache->regs); ++i) { - if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); + if( used[i] ) f.Printf("%s ", disRNameGPR[i]); } - fprintf(f, "\n"); + f.Printf("\n"); pcur = s_pInstCache+1; for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { - fprintf(f, "%2d: %2.2x ", i+1, pcur->info); + f.Printf("%2d: %2.2x ", i+1, pcur->info); count = 1; for(j = 0; j < ArraySize(s_pInstCache->regs); j++) { if( used[j] ) { - fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countregs[j], ((count%8)&&count tempdump", filename ); system( command ); @@ -316,7 +315,7 @@ void _psxMoveGPRtoM(u32 to, int fromgpr) void _psxMoveGPRtoRm(x86IntRegType to, int fromgpr) { if( PSX_IS_CONST1(fromgpr) ) - MOV32ItoRmOffset( to, g_psxConstRegs[fromgpr], 0 ); + MOV32ItoRm( to, g_psxConstRegs[fromgpr] ); else { // check x86 MOV32MtoR(EAX, (uptr)&psxRegs.GPR.r[ fromgpr ] ); @@ -536,7 +535,7 @@ void recResetIOP() DevCon::Status( "iR3000A Resetting recompiler memory and structures" ); - memset_8<0xcd,RECMEM_SIZE>( recMem ); + memset_8<0xcc,RECMEM_SIZE>( recMem ); // 0xcc is INT3 iopClearRecLUT((BASEBLOCK*)m_recBlockAlloc, (((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4))); @@ -647,7 +646,7 @@ static void recExecute() //for (;;) R3000AExecute(); } -static s32 recExecuteBlock( s32 eeCycles ) +static __forceinline s32 recExecuteBlock( s32 eeCycles ) { psxBreak = 0; psxCycleEE = eeCycles; @@ -741,7 +740,7 @@ static __forceinline u32 psxRecClearMem(u32 pc) return upperextent - pc; } -static void recClear(u32 Addr, u32 Size) +static __forceinline void recClearIOP(u32 Addr, u32 Size) { u32 pc = Addr; while (pc < Addr + Size*4) @@ -772,7 +771,7 @@ void psxSetBranchReg(u32 reg) _psxFlushCall(FLUSH_EVERYTHING); iPsxBranchTest(0xffffffff, 1); - JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); + JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr + 5 )); } void psxSetBranchImm( u32 imm ) @@ -796,9 +795,9 @@ void psxSetBranchImm( u32 imm ) // So for now these are new settings that work. // (rama) -static u32 psxScaleBlockCycles() +static __forceinline u32 psxScaleBlockCycles() { - return s_psxBlockCycles * (CHECK_IOP_CYCLERATE ? 2 : 1); + return s_psxBlockCycles * (Config.Hacks.IOPCycleDouble ? 2 : 1); } static void iPsxBranchTest(u32 newpc, u32 cpuBranch) @@ -828,14 +827,14 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch) if( newpc != 0xffffffff ) { CMP32ItoM((uptr)&psxRegs.pc, newpc); - JNE32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 6 )); + JNE32((uptr)iopDispatcherReg - ( (uptr)x86Ptr + 6 )); } // Skip branch jump target here: x86SetJ8( j8Ptr[0] ); } -static const int *s_pCode; +//static const int *s_pCode; #if !defined(_MSC_VER) static void checkcodefn() @@ -864,7 +863,7 @@ void rpsxSYSCALL() ADD32ItoM((uptr)&psxRegs.cycle, psxScaleBlockCycles() ); SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 ); - JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); + JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr + 5 )); // jump target for skipping blockCycle updates x86SetJ8(j8Ptr[0]); @@ -884,7 +883,7 @@ void rpsxBREAK() j8Ptr[0] = JE8(0); ADD32ItoM((uptr)&psxRegs.cycle, psxScaleBlockCycles() ); SUB32ItoM((uptr)&psxCycleEE, psxScaleBlockCycles()*8 ); - JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); + JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr + 5 )); x86SetJ8(j8Ptr[0]); //if (!psxbranch) psxbranch = 2; @@ -930,41 +929,11 @@ void psxRecompileNextInstruction(int delayslot) _clearNeededX86regs(); } -#include "IopHw.h" - -void iDumpPsxRegisters(u32 startpc, u32 temp) -{ -// [TODO] fixme : thie code is broken and has no labels. Needs a rewrite to be useful. - -#if 0 - int i; - const char* pstr = temp ? "t" : ""; - - __Log("%spsxreg: %x %x ra:%x k0: %x %x", pstr, startpc, psxRegs.cycle, psxRegs.GPR.n.ra, psxRegs.GPR.n.k0, *(int*)PSXM(0x13c128)); - for(i = 0; i < 34; i+=2) __Log("%spsx%s: %x %x", pstr, disRNameGPR[i], psxRegs.GPR.r[i], psxRegs.GPR.r[i+1]); - __Log("%scycle: %x %x %x; counters %x %x", pstr, psxRegs.cycle, g_psxNextBranchCycle, EEsCycle, - psxNextsCounter, psxNextCounter); - - __Log("psxdma%d c%x b%x m%x t%x", 2, HW_DMA2_CHCR, HW_DMA2_BCR, HW_DMA2_MADR, HW_DMA2_TADR); - __Log("psxdma%d c%x b%x m%x", 3, HW_DMA3_CHCR, HW_DMA3_BCR, HW_DMA3_MADR); - __Log("psxdma%d c%x b%x m%x t%x", 4, HW_DMA4_CHCR, HW_DMA4_BCR, HW_DMA4_MADR, HW_DMA4_TADR); - __Log("psxdma%d c%x b%x m%x", 6, HW_DMA6_CHCR, HW_DMA6_BCR, HW_DMA6_MADR); - __Log("psxdma%d c%x b%x m%x", 7, HW_DMA7_CHCR, HW_DMA7_BCR, HW_DMA7_MADR); - __Log("psxdma%d c%x b%x m%x", 8, HW_DMA8_CHCR, HW_DMA8_BCR, HW_DMA8_MADR); - __Log("psxdma%d c%x b%x m%x t%x", 9, HW_DMA9_CHCR, HW_DMA9_BCR, HW_DMA9_MADR, HW_DMA9_TADR); - __Log("psxdma%d c%x b%x m%x", 10, HW_DMA10_CHCR, HW_DMA10_BCR, HW_DMA10_MADR); - __Log("psxdma%d c%x b%x m%x", 11, HW_DMA11_CHCR, HW_DMA11_BCR, HW_DMA11_MADR); - __Log("psxdma%d c%x b%x m%x", 12, HW_DMA12_CHCR, HW_DMA12_BCR, HW_DMA12_MADR); - for(i = 0; i < 7; ++i) - __Log("%scounter%d: mode %x count %I64x rate %x scycle %x target %I64x", pstr, i, psxCounters[i].mode, psxCounters[i].count, psxCounters[i].rate, psxCounters[i].sCycleT, psxCounters[i].target); -#endif -} - -void iDumpPsxRegisters(u32 startpc); - #ifdef _DEBUG static void printfn() { + extern void iDumpPsxRegisters(u32 startpc, u32 temp); + static int lastrec = 0; static int curcount = 0; const int skip = 0; @@ -992,6 +961,8 @@ void iopRecRecompile(u32 startpc) u32 willbranch3 = 0; #ifdef _DEBUG + extern void iDumpPsxRegisters(u32 startpc, u32 temp); + if( psxdump & 4 ) iDumpPsxRegisters(startpc, 0); #endif @@ -1004,7 +975,7 @@ void iopRecRecompile(u32 startpc) x86SetPtr( recPtr ); x86Align(16); - recPtr = x86Ptr[_EmitterId_]; + recPtr = x86Ptr; s_pCurBlock = PSX_GETBLOCK(startpc); @@ -1025,7 +996,7 @@ void iopRecRecompile(u32 startpc) psxbranch = 0; - s_pCurBlock->SetFnptr( (uptr)x86Ptr[0] ); + s_pCurBlock->SetFnptr( (uptr)x86Ptr ); s_psxBlockCycles = 0; // reset recomp state variables @@ -1160,7 +1131,7 @@ StartRecomp: iPsxBranchTest(0xffffffff, 1); - JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr[0] + 5 )); + JMP32((uptr)iopDispatcherReg - ( (uptr)x86Ptr + 5 )); } else { if( psxbranch ) assert( !willbranch3 ); @@ -1180,12 +1151,12 @@ StartRecomp: } } - assert( x86Ptr[0] < recMem+RECMEM_SIZE ); + assert( x86Ptr < recMem+RECMEM_SIZE ); - assert(x86Ptr[_EmitterId_] - recPtr < 0x10000); - s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr; + assert(x86Ptr - recPtr < 0x10000); + s_pCurBlockEx->x86size = x86Ptr - recPtr; - recPtr = x86Ptr[0]; + recPtr = x86Ptr; assert( (g_psxHasConstReg&g_psxFlushedConstReg) == g_psxHasConstReg ); @@ -1198,7 +1169,7 @@ R3000Acpu psxRec = { recResetIOP, recExecute, recExecuteBlock, - recClear, + recClearIOP, recShutdown }; diff --git a/pcsx2/x86/iR3000A.h b/pcsx2/x86/iR3000A.h index ebf78ec3cb..220eb33ff0 100644 --- a/pcsx2/x86/iR3000A.h +++ b/pcsx2/x86/iR3000A.h @@ -18,12 +18,10 @@ #ifndef _R3000A_SUPERREC_ #define _R3000A_SUPERREC_ -#define _EmitterId_ EmitterId_R3000a #include "ix86/ix86.h" #include "R3000A.h" #include "iCore.h" -#include "BaseblockEx.h" // Cycle penalties for particularly slow instructions. static const int psxInstCycles_Mult = 7; diff --git a/pcsx2/x86/iR3000Atables.cpp b/pcsx2/x86/iR3000Atables.cpp index 1b1f4486e6..fddd6f9690 100644 --- a/pcsx2/x86/iR3000Atables.cpp +++ b/pcsx2/x86/iR3000Atables.cpp @@ -1258,7 +1258,7 @@ void rpsxJALR() static void* s_pbranchjmp; static u32 s_do32 = 0; -#define JUMPVALID(pjmp) (( x86Ptr[0] - (u8*)pjmp ) <= 0x80) +#define JUMPVALID(pjmp) (( x86Ptr - (u8*)pjmp ) <= 0x80) void rpsxSetBranchEQ(int info, int process) { @@ -1305,7 +1305,7 @@ void rpsxBEQ_process(int info, int process) else { _psxFlushAllUnused(); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; s_do32 = 0; psxSaveBranchState(); @@ -1318,7 +1318,7 @@ void rpsxBEQ_process(int info, int process) x86SetJ8A( (u8*)s_pbranchjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); s_do32 = 1; psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); @@ -1369,7 +1369,7 @@ void rpsxBNE_process(int info, int process) } _psxFlushAllUnused(); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; s_do32 = 0; rpsxSetBranchEQ(info, process); @@ -1381,7 +1381,7 @@ void rpsxBNE_process(int info, int process) x86SetJ8A( (u8*)s_pbranchjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); s_do32 = 1; psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); @@ -1423,7 +1423,7 @@ void rpsxBLTZ() } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JL8(0); psxSaveBranchState(); @@ -1435,7 +1435,7 @@ void rpsxBLTZ() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); @@ -1470,7 +1470,7 @@ void rpsxBGEZ() } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JGE8(0); psxSaveBranchState(); @@ -1482,7 +1482,7 @@ void rpsxBGEZ() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); @@ -1524,7 +1524,7 @@ void rpsxBLTZAL() } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JL8(0); psxSaveBranchState(); @@ -1538,7 +1538,7 @@ void rpsxBLTZAL() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); @@ -1577,7 +1577,7 @@ void rpsxBGEZAL() } CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JGE8(0); MOV32ItoM((uptr)&psxRegs.GPR.r[31], psxpc+4); @@ -1591,7 +1591,7 @@ void rpsxBGEZAL() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); @@ -1631,7 +1631,7 @@ void rpsxBLEZ() _clearNeededX86regs(); CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JLE8(0); psxSaveBranchState(); @@ -1642,7 +1642,7 @@ void rpsxBLEZ() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); @@ -1679,7 +1679,7 @@ void rpsxBGTZ() _clearNeededX86regs(); CMP32ItoM((uptr)&psxRegs.GPR.r[_Rs_], 0); - u8* prevx86 = x86Ptr[0]; + u8* prevx86 = x86Ptr; u8* pjmp = JG8(0); psxSaveBranchState(); @@ -1690,7 +1690,7 @@ void rpsxBGTZ() x86SetJ8A( pjmp ); } else { - x86Ptr[0] = prevx86; + x86SetPtr( prevx86 ); psxpc -= 4; psxRegs.code = iopMemRead32( psxpc - 4 ); psxLoadBranchState(); diff --git a/pcsx2/x86/iR5900.h b/pcsx2/x86/iR5900.h index 15fc5ef33b..af168fc238 100644 --- a/pcsx2/x86/iR5900.h +++ b/pcsx2/x86/iR5900.h @@ -19,33 +19,12 @@ #ifndef __IR5900_H__ #define __IR5900_H__ -#define _EmitterId_ EmitterId_R5900 #include "ix86/ix86.h" #include "ix86/ix86_sse_helpers.h" #include "R5900.h" #include "VU.h" #include "iCore.h" -#include "BaseblockEx.h" // needed for recClear and stuff - -// Yay! These work now! (air) ... almost (air) -#define ARITHMETICIMM_RECOMPILE -#define ARITHMETIC_RECOMPILE -#define MULTDIV_RECOMPILE -#define SHIFT_RECOMPILE -#define BRANCH_RECOMPILE -#define JUMP_RECOMPILE -#define LOADSTORE_RECOMPILE -#define MOVE_RECOMPILE -#define MMI_RECOMPILE -#define MMI0_RECOMPILE -#define MMI1_RECOMPILE -#define MMI2_RECOMPILE -#define MMI3_RECOMPILE -#define FPU_RECOMPILE -#define CP0_RECOMPILE -#define CP2_RECOMPILE - -#define EE_CONST_PROP // rec2 - enables constant propagation (faster) +#include "Pcsx2Config.h" #define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT) @@ -251,19 +230,6 @@ void eeRecompileCodeConstSPECIAL(R5900FNPTR constcode, R5900FNPTR_INFO multicode #define XMMINFO_READACC 0x200 #define XMMINFO_WRITEACC 0x400 -#define CPU_SSE_XMMCACHE_START(xmminfo) \ - { \ - int info = eeRecompileCodeXMM(xmminfo); \ - -#define CPU_SSE2_XMMCACHE_START(xmminfo) \ - { \ - int info = eeRecompileCodeXMM(xmminfo); \ - -#define CPU_SSE_XMMCACHE_END \ - _clearNeededXMMregs(); \ - return; \ - } \ - #define FPURECOMPILE_CONSTCODE(fn, xmminfo) \ void rec##fn(void) \ { \ diff --git a/pcsx2/x86/iVU0micro.cpp b/pcsx2/x86/iVU0micro.cpp index 4b70381294..1a2ee09ea7 100644 --- a/pcsx2/x86/iVU0micro.cpp +++ b/pcsx2/x86/iVU0micro.cpp @@ -23,11 +23,12 @@ #include "VUmicro.h" #include "iVUzerorec.h" +#ifndef PCSX2_MICROVU_ namespace VU0micro { - void recAlloc() - { - SuperVUAlloc(0); + void recAlloc() + { + SuperVUAlloc(0); } void __fastcall recClear(u32 Addr, u32 Size) @@ -62,6 +63,34 @@ namespace VU0micro FreezeXMMRegs(0); } } +#else + +extern void initVUrec(VURegs* vuRegs, const int vuIndex); +extern void closeVUrec(const int vuIndex); +extern void resetVUrec(const int vuIndex); +extern void clearVUrec(u32 addr, u32 size, const int vuIndex); +extern void runVUrec(u32 startPC, u32 cycles, const int vuIndex); + +namespace VU0micro +{ + void recAlloc() { initVUrec(&VU0, 0); } + void __fastcall recClear(u32 Addr, u32 Size) { clearVUrec(Addr, Size, 0); } + void recShutdown() { closeVUrec(0); } + static void recReset() { resetVUrec(0); x86FpuState = FPU_STATE; } + static void recStep() {} + static void recExecuteBlock() + { + if((VU0.VI[REG_VPU_STAT].UL & 1) == 0) return; + + FreezeXMMRegs(1); + FreezeMMXRegs(1); + runVUrec(VU0.VI[REG_TPC].UL, 5000, 0); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + } + +} +#endif using namespace VU0micro; diff --git a/pcsx2/x86/iVU1micro.cpp b/pcsx2/x86/iVU1micro.cpp index 2c4cc00bb4..d282778f4c 100644 --- a/pcsx2/x86/iVU1micro.cpp +++ b/pcsx2/x86/iVU1micro.cpp @@ -29,7 +29,7 @@ #ifdef _DEBUG extern u32 vudump; #endif - +#ifndef PCSX2_MICROVU_ namespace VU1micro { void recAlloc() @@ -121,6 +121,34 @@ namespace VU1micro FreezeXMMRegs(0); } } +#else + +extern void initVUrec(VURegs* vuRegs, const int vuIndex); +extern void closeVUrec(const int vuIndex); +extern void resetVUrec(const int vuIndex); +extern void clearVUrec(u32 addr, u32 size, const int vuIndex); +extern void runVUrec(u32 startPC, u32 cycles, const int vuIndex); + +namespace VU1micro +{ + void recAlloc() { initVUrec(&VU1, 1); } + void __fastcall recClear(u32 Addr, u32 Size) { clearVUrec(Addr, Size, 1); } + void recShutdown() { closeVUrec(1); } + static void recReset() { resetVUrec(1); x86FpuState = FPU_STATE; } + static void recStep() {} + static void recExecuteBlock() { + + if((VU0.VI[REG_VPU_STAT].UL & 0x100) == 0) return; + assert( (VU1.VI[REG_TPC].UL&7) == 0 ); + + FreezeXMMRegs(1); + FreezeMMXRegs(1); + runVUrec(VU1.VI[REG_TPC].UL, 5000, 1); + FreezeXMMRegs(0); + FreezeMMXRegs(0); + } +} +#endif using namespace VU1micro; diff --git a/pcsx2/x86/iVUmicro.cpp b/pcsx2/x86/iVUmicro.cpp index 2422e5ad10..9335151798 100644 --- a/pcsx2/x86/iVUmicro.cpp +++ b/pcsx2/x86/iVUmicro.cpp @@ -280,6 +280,7 @@ void _recvuIALUTestStall(VURegs * VU, int reg) { VU->ialu[i].enable = 0; vucycle+= cycle; + _recvuTestPipes(VU, true); } void _recvuFMACAdd(VURegs * VU, int reg, int xyzw) { @@ -387,7 +388,7 @@ void _recvuFlushFDIV(VURegs * VU) { if (VU->fdiv.enable == 0) return; - cycle = VU->fdiv.Cycle - (vucycle - VU->fdiv.sCycle); + cycle = VU->fdiv.Cycle + 1 - (vucycle - VU->fdiv.sCycle); //VU->fdiv.Cycle contains the latency minus 1 (6 or 12) // Console::WriteLn("waiting FDIV pipe %d", params cycle); VU->fdiv.enable = 0; vucycle+= cycle; diff --git a/pcsx2/x86/iVUmicroLower.cpp b/pcsx2/x86/iVUmicroLower.cpp index 58156d0926..f98ed4549c 100644 --- a/pcsx2/x86/iVUmicroLower.cpp +++ b/pcsx2/x86/iVUmicroLower.cpp @@ -354,8 +354,8 @@ void recVUMI_IADD( VURegs *VU, int info ) if( fdreg == fsreg ) ADD32RtoR(fdreg, ftreg); else if( fdreg == ftreg ) ADD32RtoR(fdreg, fsreg); - else LEA16RRtoR(fdreg, fsreg, ftreg); - MOVZX32R16toR(fdreg, fdreg); // neeed since don't know if fdreg's upper bits are 0 + else LEA32RRtoR(fdreg, fsreg, ftreg); + MOVZX32R16toR(fdreg, fdreg); // needed since don't know if fdreg's upper bits are 0 } } //------------------------------------------------------------------ @@ -609,31 +609,31 @@ void _loadEAX(VURegs *VU, int x86reg, uptr offset, int info) if( x86reg >= 0 ) { switch(_X_Y_Z_W) { case 3: // ZW - SSE_MOVHPS_RmOffset_to_XMM(EEREC_T, x86reg, offset+8); + SSE_MOVHPS_Rm_to_XMM(EEREC_T, x86reg, offset+8); break; case 6: // YZ - SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0x9c); + SSE_SHUFPS_Rm_to_XMM(EEREC_T, x86reg, offset, 0x9c); SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0x78); break; case 8: // X - SSE_MOVSS_RmOffset_to_XMM(EEREC_TEMP, x86reg, offset); + SSE_MOVSS_Rm_to_XMM(EEREC_TEMP, x86reg, offset); SSE_MOVSS_XMM_to_XMM(EEREC_T, EEREC_TEMP); break; case 9: // XW - SSE_SHUFPS_RmOffset_to_XMM(EEREC_T, x86reg, offset, 0xc9); + SSE_SHUFPS_Rm_to_XMM(EEREC_T, x86reg, offset, 0xc9); SSE_SHUFPS_XMM_to_XMM(EEREC_T, EEREC_T, 0xd2); break; case 12: // XY - SSE_MOVLPS_RmOffset_to_XMM(EEREC_T, x86reg, offset); + SSE_MOVLPS_Rm_to_XMM(EEREC_T, x86reg, offset); break; case 15: - if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_T, x86reg, offset); - else SSE_MOVUPSRmtoROffset(EEREC_T, x86reg, offset); + if( VU == &VU1 ) SSE_MOVAPSRmtoR(EEREC_T, x86reg, offset); + else SSE_MOVUPSRmtoR(EEREC_T, x86reg, offset); break; default: - if( VU == &VU1 ) SSE_MOVAPSRmtoROffset(EEREC_TEMP, x86reg, offset); - else SSE_MOVUPSRmtoROffset(EEREC_TEMP, x86reg, offset); + if( VU == &VU1 ) SSE_MOVAPSRmtoR(EEREC_TEMP, x86reg, offset); + else SSE_MOVUPSRmtoR(EEREC_TEMP, x86reg, offset); VU_MERGE_REGS(EEREC_T, EEREC_TEMP); break; @@ -795,22 +795,19 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) if ( _Fs_ == 0 ) { if ( _XYZW_SS ) { u32 c = _W ? 0x3f800000 : 0; - if ( x86reg >= 0 ) MOV32ItoRmOffset(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); + if ( x86reg >= 0 ) MOV32ItoRm(x86reg, c, offset+(_W?12:(_Z?8:(_Y?4:0)))); else MOV32ItoM(offset+(_W?12:(_Z?8:(_Y?4:0))), c); } else { - if ( x86reg >= 0 ) { - if ( _X ) MOV32ItoRmOffset(x86reg, 0x00000000, offset); - if ( _Y ) MOV32ItoRmOffset(x86reg, 0x00000000, offset+4); - if ( _Z ) MOV32ItoRmOffset(x86reg, 0x00000000, offset+8); - if ( _W ) MOV32ItoRmOffset(x86reg, 0x3f800000, offset+12); - } - else { - if ( _X ) MOV32ItoM(offset, 0x00000000); - if ( _Y ) MOV32ItoM(offset+4, 0x00000000); - if ( _Z ) MOV32ItoM(offset+8, 0x00000000); - if ( _W ) MOV32ItoM(offset+12, 0x3f800000); - } + + // (this is one of my test cases for the new emitter --air) + using namespace x86Emitter; + xAddressReg thisreg( x86reg ); + + if ( _X ) xMOV(ptr32[thisreg+offset], 0x00000000); + if ( _Y ) xMOV(ptr32[thisreg+offset+4], 0x00000000); + if ( _Z ) xMOV(ptr32[thisreg+offset+8], 0x00000000); + if ( _W ) xMOV(ptr32[thisreg+offset+12], 0x3f800000); } return; } @@ -818,29 +815,29 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) switch ( _X_Y_Z_W ) { case 1: // W SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x27); - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12); else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); break; case 2: // Z SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8); else SSE_MOVSS_XMM_to_M32(offset+8, EEREC_TEMP); break; case 3: // ZW - if ( x86reg >= 0 ) SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + if ( x86reg >= 0 ) SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_S, offset+8); else SSE_MOVHPS_XMM_to_M64(offset+8, EEREC_S); break; case 4: // Y SSE2_PSHUFLW_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x4e); - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4); else SSE_MOVSS_XMM_to_M32(offset+4, EEREC_TEMP); break; case 5: // YW SSE_SHUFPS_XMM_to_XMM(EEREC_S, EEREC_S, 0xB1); SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); if ( x86reg >= 0 ) { - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset+4); - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset+4); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12); } else { SSE_MOVSS_XMM_to_M32(offset+4, EEREC_S); @@ -850,14 +847,14 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) break; case 6: // YZ SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0xc9); - if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4); + if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4); else SSE_MOVLPS_XMM_to_M64(offset+4, EEREC_TEMP); break; case 7: // YZW SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x93); //ZYXW if ( x86reg >= 0 ) { - SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+4); - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+4); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12); } else { SSE_MOVHPS_XMM_to_M64(offset+4, EEREC_TEMP); @@ -865,26 +862,24 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) } break; case 8: // X - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset); else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); break; case 9: // XW - SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset); else SSE_MOVSS_XMM_to_M32(offset, EEREC_S); - if ( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP); - else SSE_SHUFPS_XMM_to_XMM(EEREC_TEMP, EEREC_TEMP, 0x55); + SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0xff); //WWWW - if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + if ( x86reg >= 0 ) SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12); else SSE_MOVSS_XMM_to_M32(offset+12, EEREC_TEMP); break; case 10: //XZ SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); if ( x86reg >= 0 ) { - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8); } else { SSE_MOVSS_XMM_to_M32(offset, EEREC_S); @@ -893,8 +888,8 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) break; case 11: //XZW if ( x86reg >= 0 ) { - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_S, offset); - SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+8); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_S, offset); + SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_S, offset+8); } else { SSE_MOVSS_XMM_to_M32(offset, EEREC_S); @@ -902,14 +897,14 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) } break; case 12: // XY - if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); + if ( x86reg >= 0 ) SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_S, offset+0); else SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); break; case 13: // XYW SSE2_PSHUFD_XMM_to_XMM(EEREC_TEMP, EEREC_S, 0x4b); //YXZW if ( x86reg >= 0 ) { - SSE_MOVHPS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+0); - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+12); + SSE_MOVHPS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+0); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+12); } else { SSE_MOVHPS_XMM_to_M64(offset, EEREC_TEMP); @@ -919,8 +914,8 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) case 14: // XYZ SSE_MOVHLPS_XMM_to_XMM(EEREC_TEMP, EEREC_S); if ( x86reg >= 0 ) { - SSE_MOVLPS_XMM_to_RmOffset(x86reg, EEREC_S, offset+0); - SSE_MOVSS_XMM_to_RmOffset(x86reg, EEREC_TEMP, offset+8); + SSE_MOVLPS_XMM_to_Rm(x86reg, EEREC_S, offset+0); + SSE_MOVSS_XMM_to_Rm(x86reg, EEREC_TEMP, offset+8); } else { SSE_MOVLPS_XMM_to_M64(offset, EEREC_S); @@ -929,11 +924,11 @@ void _saveEAX(VURegs *VU, int x86reg, uptr offset, int info) break; case 15: // XYZW if ( VU == &VU1 ) { - if( x86reg >= 0 ) SSE_MOVAPSRtoRmOffset(x86reg, EEREC_S, offset+0); + if( x86reg >= 0 ) SSE_MOVAPSRtoRm(x86reg, EEREC_S, offset+0); else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); } else { - if( x86reg >= 0 ) SSE_MOVUPSRtoRmOffset(x86reg, EEREC_S, offset+0); + if( x86reg >= 0 ) SSE_MOVUPSRtoRm(x86reg, EEREC_S, offset+0); else { if( offset & 15 ) SSE_MOVUPS_XMM_to_M128(offset, EEREC_S); else SSE_MOVAPS_XMM_to_M128(offset, EEREC_S); @@ -1018,7 +1013,7 @@ void recVUMI_ILW(VURegs *VU, int info) } else { int fsreg = ALLOCVI(_Fs_, MODE_READ); - MOV32RmtoROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem + off); + MOV32RmtoR(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, imm), (uptr)VU->Mem + off); } } //------------------------------------------------------------------ @@ -1051,10 +1046,10 @@ void recVUMI_ISW( VURegs *VU, int info ) x86reg = recVUTransformAddr(fsreg, VU, _Fs_, imm); - if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem); - if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4); - if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8); - if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12); + if (_X) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem); + if (_Y) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+4); + if (_Z) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+8); + if (_W) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+12); } } //------------------------------------------------------------------ @@ -1082,7 +1077,7 @@ void recVUMI_ILWR( VURegs *VU, int info ) } else { int fsreg = ALLOCVI(_Fs_, MODE_READ); - MOVZX32Rm16toROffset(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem + off); + MOVZX32Rm16toR(ftreg, recVUTransformAddr(fsreg, VU, _Fs_, 0), (uptr)VU->Mem + off); } } //------------------------------------------------------------------ @@ -1109,10 +1104,10 @@ void recVUMI_ISWR( VURegs *VU, int info ) int fsreg = ALLOCVI(_Fs_, MODE_READ); x86reg = recVUTransformAddr(fsreg, VU, _Fs_, 0); - if (_X) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem); - if (_Y) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+4); - if (_Z) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+8); - if (_W) MOV32RtoRmOffset(x86reg, ftreg, (uptr)VU->Mem+12); + if (_X) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem); + if (_Y) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+4); + if (_Z) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+8); + if (_W) MOV32RtoRm(x86reg, ftreg, (uptr)VU->Mem+12); } } //------------------------------------------------------------------ diff --git a/pcsx2/x86/iVUmicroUpper.cpp b/pcsx2/x86/iVUmicroUpper.cpp index 26e3f1604d..61393c43fe 100644 --- a/pcsx2/x86/iVUmicroUpper.cpp +++ b/pcsx2/x86/iVUmicroUpper.cpp @@ -1640,7 +1640,7 @@ void recVUMI_MADD_iq_toD(VURegs *VU, uptr addr, int regd, int info) } if( regd == EEREC_ACC ) { - assert( EEREC_TEMP < XMMREGS ); + assert( EEREC_TEMP < iREGCNT_XMM ); SSE_MOVSS_M32_to_XMM(EEREC_TEMP, addr); SSE_MULSS_XMM_to_XMM(EEREC_TEMP, EEREC_S); if (CHECK_VU_EXTRA_OVERFLOW) { vuFloat_useEAX( info, EEREC_TEMP, 8); } diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 4dea960b87..ff3c76bb6e 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -21,10 +21,10 @@ #include "PrecompiledHeader.h" #include -#include #include #include -#include + +#include "Utilities/AsciiFile.h" #ifndef _WIN32 #include @@ -58,7 +58,7 @@ extern void iDumpVU1Registers(); #define SUPERVU_PROPAGATEFLAGS // the correct behavior of VUs, for some reason superman breaks gfx with it on... #ifndef _DEBUG -#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) +//#define SUPERVU_INTERCACHING // registers won't be flushed at block boundaries (faster) (nothing noticable speed-wise, causes SPS in Ratchet and clank (Nneeve) ) #endif #define SUPERVU_CHECKCONDITION 0 // has to be 0!! @@ -223,7 +223,7 @@ public: u32 vuxyz; // corresponding bit is set if reg's xyz channels are used only u32 vuxy; // corresponding bit is set if reg's xyz channels are used only - _xmmregs startregs[XMMREGS], endregs[XMMREGS]; + _xmmregs startregs[iREGCNT_XMM], endregs[iREGCNT_XMM]; int nStartx86, nEndx86; // indices into s_vecRegArray int allocX86Regs; @@ -328,7 +328,8 @@ void SuperVUAlloc(int vuindex) if( s_recVUMem == NULL ) { throw Exception::OutOfMemory( - fmt_string( "SuperVU Error > failed to allocate recompiler memory (addr: 0x%x)", (u32)s_recVUMem ) + // untranslated diagnostic msg, use exception's default for translation + wxsFormat( wxT("Error > SuperVU failed to allocate recompiler memory (addr: 0x%x)"), (u32)s_recVUMem ) ); } @@ -509,34 +510,32 @@ u32 SuperVUGetVIAddr(int reg, int read) void SuperVUDumpBlock(list& blocks, int vuindex) { - FILE *f; - char str[256]; u32 *mem; u32 i; - Path::CreateDirectory( "dumps" ); - string filename( Path::Combine( "dumps", fmt_string( "svu%cdump%.4X.txt", s_vu?'0':'1', s_pFnHeader->startpc ) ) ); - //Console::WriteLn( "dump1 %x => %s", params s_pFnHeader->startpc, filename ); + g_Conf.Folders.Dumps.Mkdir(); + AsciiFile eff( + Path::Combine( g_Conf.Folders.Dumps, wxsFormat(wxT("svu%cdump%.4X.txt"), s_vu?wxT('0'):wxT('1'), s_pFnHeader->startpc) ), + wxFile::write + ); - f = fopen( filename.c_str(), "w" ); - - fprintf(f, "Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); - fprintf(f, "Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" + eff.Printf("Format: upper_inst lower_inst\ntype f:vf_live_vars vf_used_vars i:vi_live_vars vi_used_vars inst_cycle pq_inst\n"); + eff.Printf("Type: %.2x - qread, %.2x - pread, %.2x - clip_write, %.2x - status_write\n" "%.2x - mac_write, %.2x -qflush\n", INST_Q_READ, INST_P_READ, INST_CLIP_WRITE, INST_STATUS_WRITE, INST_MAC_WRITE, INST_Q_WRITE); - fprintf(f, "XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); + eff.Printf("XMM: Upper: read0 read1 write acc temp; Lower: read0 read1 write acc temp\n\n"); list::iterator itblock; list::iterator itinst; VuBaseBlock::LISTBLOCKS::iterator itchild; FORIT(itblock, blocks) { - fprintf(f, "block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', + eff.Printf("block:%c %x-%x; children: ", ((*itblock)->type&BLOCKTYPE_HASEOP)?'*':' ', (*itblock)->startpc, (*itblock)->endpc-8); FORIT(itchild, (*itblock)->blocks) { - fprintf(f, "%x ", (*itchild)->startpc); + eff.Printf("%x ", (*itchild)->startpc); } - fprintf(f, "; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], + eff.Printf("; vuxyz = %x, vuxy = %x\n", (*itblock)->vuxyz&(*itblock)->insts.front().usedvars[1], (*itblock)->vuxy&(*itblock)->insts.front().usedvars[1]); itinst = (*itblock)->insts.begin(); @@ -546,46 +545,46 @@ void SuperVUDumpBlock(list& blocks, int vuindex) if( itinst->type & INST_DUMMY ) { if( itinst->nParentPc >= 0 && !(itinst->type&INST_DUMMY_)) { // search for the parent - fprintf(f, "writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); + eff.Printf("writeback 0x%x (%x)\n", itinst->type, itinst->nParentPc); } } else { mem = (u32*)&VU->Micro[i]; char* pstr = disVU1MicroUF( mem[1], i+4 ); - fprintf(f, "%.4x: %-40s", i, pstr); - if( mem[1] & 0x80000000 ) fprintf(f, " I=%f(%.8x)\n", *(float*)mem, mem[0]); - else fprintf(f, "%s\n", disVU1MicroLF( mem[0], i )); + eff.Printf("%.4x: %-40s", i, pstr); + if( mem[1] & 0x80000000 ) eff.Printf(" I=%f(%.8x)\n", *(float*)mem, mem[0]); + else eff.Printf("%s\n", disVU1MicroLF( mem[0], i )); i += 8; } ++itinst; } - fprintf(f, "\n"); + eff.Printf("\n"); _x86regs* pregs; if( (*itblock)->nStartx86 >= 0 || (*itblock)->nEndx86 >= 0 ) { - fprintf(f, "X86: AX CX DX BX SP BP SI DI\n"); + eff.Printf("X86: AX CX DX BX SP BP SI DI\n"); } if( (*itblock)->nStartx86 >= 0 ) { pregs = &s_vecRegArray[(*itblock)->nStartx86]; - fprintf(f, "STR: "); - for(i = 0; i < X86REGS; ++i) { - if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); - else fprintf(f, "-1 "); + eff.Printf("STR: "); + for(i = 0; i < iREGCNT_GPR; ++i) { + if( pregs[i].inuse ) eff.Printf("%.2d ", pregs[i].reg); + else eff.Printf("-1 "); } - fprintf(f, "\n"); + eff.Printf("\n"); } if( (*itblock)->nEndx86 >= 0 ) { - fprintf(f, "END: "); + eff.Printf("END: "); pregs = &s_vecRegArray[(*itblock)->nEndx86]; - for(i = 0; i < X86REGS; ++i) { - if( pregs[i].inuse ) fprintf(f, "%.2d ", pregs[i].reg); - else fprintf(f, "-1 "); + for(i = 0; i < iREGCNT_GPR; ++i) { + if( pregs[i].inuse ) eff.Printf("%.2d ", pregs[i].reg); + else eff.Printf("-1 "); } - fprintf(f, "\n"); + eff.Printf("\n"); } itinst = (*itblock)->insts.begin(); @@ -594,13 +593,14 @@ void SuperVUDumpBlock(list& blocks, int vuindex) if( itinst->type & INST_DUMMY ) { } else { + char str[256]; sprintf(str, "%.4x:%x f:%.8x_%.8x", i, itinst->type, itinst->livevars[1], itinst->usedvars[1]); - fprintf(f, "%-46s i:%.8x_%.8x c:%d pq:%d\n", str, + eff.Printf("%-46s i:%.8x_%.8x c:%d pq:%d\n", str, itinst->livevars[0], itinst->usedvars[0], (int)itinst->info.cycle, (int)itinst->pqcycles ); sprintf(str, "XMM r0:%d r1:%d w:%d a:%d t:%x;", itinst->vfread0[1], itinst->vfread1[1], itinst->vfwrite[1], itinst->vfacc[1], itinst->vffree[1]); - fprintf(f, "%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, + eff.Printf("%-46s r0:%d r1:%d w:%d a:%d t:%x\n", str, itinst->vfread0[0], itinst->vfread1[0], itinst->vfwrite[0], itinst->vfacc[0], itinst->vffree[0]); i += 8; } @@ -629,10 +629,8 @@ void SuperVUDumpBlock(list& blocks, int vuindex) } #endif - fprintf(f, "\n---------------\n"); + eff.Printf("\n---------------\n"); } - - fclose( f ); } // uncomment to count svu exec time @@ -833,7 +831,7 @@ static VuFunctionHeader* SuperVURecompileProgram(u32 startpc, int vuindex) SuperVURecompile(); - s_recVUPtr = x86Ptr[0]; + s_recVUPtr = x86Ptr; // set the function's range VuFunctionHeader::RANGE r; @@ -1879,17 +1877,17 @@ void VuBaseBlock::AssignVFRegs() if( type & BLOCKTYPE_ANALYZED ) { // check if changed - for(i = 0; i < XMMREGS; ++i) { + for(i = 0; i < iREGCNT_XMM; ++i) { if( xmmregs[i].inuse != startregs[i].inuse ) break; if( xmmregs[i].inuse && (xmmregs[i].reg != startregs[i].reg || xmmregs[i].type != startregs[i].type) ) break; } - if( i == XMMREGS ) return; // nothing changed + if( i == iREGCNT_XMM ) return; // nothing changed } - u8* oldX86 = x86Ptr[0]; + u8* oldX86 = x86Ptr; FORIT(itinst, insts) { @@ -1904,7 +1902,7 @@ void VuBaseBlock::AssignVFRegs() // redo the counters so that the proper regs are released - for(int j = 0; j < XMMREGS; ++j) { + for(int j = 0; j < iREGCNT_XMM; ++j) { if( xmmregs[j].inuse ) { if( xmmregs[j].type == XMMTYPE_VFREG ) { int count = 0; @@ -2044,7 +2042,8 @@ void VuBaseBlock::AssignVFRegs() else if( itinst->vfacc[i] >= 0 ) lastwrite = itinst->vfacc[i]; // always alloc at least 1 temp reg - int free0 = (i||regs->VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<VFwrite||regs->VFread0||regs->VFread1||(regs->VIwrite&(1<VIread&(1<vfwrite[1] >= 0 && (itinst->vfread0[0]==itinst->vfwrite[1]||itinst->vfread1[0]==itinst->vfwrite[1]) ) { @@ -2060,9 +2059,9 @@ void VuBaseBlock::AssignVFRegs() _freeXMMreg(free1); _freeXMMreg(free2); } - else if( regs->VIwrite & (1<VIwrite & (1<VIwrite & (1< 0 ); @@ -2210,10 +2209,10 @@ static void SuperVUAssignRegs() // assign the regs int regid = s_vecRegArray.size(); - s_vecRegArray.resize(regid+X86REGS); + s_vecRegArray.resize(regid+iREGCNT_GPR); _x86regs* mergedx86 = &s_vecRegArray[regid]; - memset(mergedx86, 0, sizeof(_x86regs)*X86REGS); + memset(mergedx86, 0, sizeof(_x86regs)*iREGCNT_GPR); if( !bfirst ) { *(u32*)usedregs = *((u32*)usedregs+1) = *((u32*)usedregs+2) = *((u32*)usedregs+3) = 0; @@ -2221,7 +2220,7 @@ static void SuperVUAssignRegs() FORIT(itblock2, s_markov.children) { assert( (*itblock2)->allocX86Regs >= 0 ); _x86regs* pregs = &s_vecRegArray[(*itblock2)->allocX86Regs]; - for(int i = 0; i < X86REGS; ++i) { + for(int i = 0; i < iREGCNT_GPR; ++i) { if( pregs[i].inuse && pregs[i].reg < 16) { //assert( pregs[i].reg < 16); usedregs[pregs[i].reg]++; @@ -2237,7 +2236,7 @@ static void SuperVUAssignRegs() mergedx86[num].reg = i; mergedx86[num].type = (s_vu?X86TYPE_VU1:0)|X86TYPE_VI; mergedx86[num].mode = MODE_READ; - if( ++num >= X86REGS ) + if( ++num >= iREGCNT_GPR ) break; if( num == ESP ) ++num; @@ -2294,6 +2293,13 @@ void SuperVUCleanupProgram(u32 startpc, int vuindex) VU = vuindex ? &VU1 : &VU0; VU->cycle += s_TotalVUCycles; + + //VU cycle stealing hack, 3000 cycle maximum so it doesn't get out of hand + if (s_TotalVUCycles < 3000) + cpuRegs.cycle += s_TotalVUCycles * Config.Hacks.VUCycleSteal; + else + cpuRegs.cycle += 3000 * Config.Hacks.VUCycleSteal; + if( (int)s_writeQ > 0 ) VU->VI[REG_Q] = VU->q; if( (int)s_writeP > 0 ) { assert(VU == &VU1); @@ -2302,10 +2308,11 @@ void SuperVUCleanupProgram(u32 startpc, int vuindex) //memset(recVUStack, 0, SUPERVU_STACKSIZE * 4); - // Clear allocation info to prevent bad data being used in other parts of pcsx2; doing this just incase (cottonvibes) - _initXMMregs(); - _initMMXregs(); - _initX86regs(); + // Could clear allocation info to prevent possibly bad data being used in other parts of pcsx2; + // not doing this because it's slow and not needed (rama) + // _initXMMregs(); + // _initMMXregs(); + // _initX86regs(); } #if defined(_MSC_VER) @@ -2466,7 +2473,7 @@ static void SuperVURecompile() AND32ItoM( (uptr)&VU->vifRegs->stat, ~0x4 ); MOV32ItoM((uptr)&VU->VI[REG_TPC], pchild->endpc); - JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr[0] + 5 )); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); } // only other case is when there are two branches else assert( (*itblock)->insts.back().regs[0].pipe == VUPIPE_BRANCH ); @@ -2557,7 +2564,7 @@ void svudispfntemp() // frees all regs taking into account the livevars void SuperVUFreeXMMregs(u32* livevars) { - for(int i = 0; i < XMMREGS; ++i) { + for(int i = 0; i < iREGCNT_XMM; ++i) { if( xmmregs[i].inuse ) { // same reg if( (xmmregs[i].mode & MODE_WRITE) ) { @@ -2606,11 +2613,11 @@ void SuperVUTestVU0Condition(u32 incstack) ADD32ItoR(ESP, incstack); //CALLFunc((u32)timeout); - JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr[0] + 5 )); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); x86SetJ8(ptr); } - else JAE32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr[0] + 6 ) ); + else JAE32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 6 ) ); } void VuBaseBlock::Recompile() @@ -2618,7 +2625,7 @@ void VuBaseBlock::Recompile() if( type & BLOCKTYPE_ANALYZED ) return; x86Align(16); - pcode = x86Ptr[0]; + pcode = x86Ptr; #ifdef _DEBUG MOV32ItoM((uptr)&s_vufnheader, s_pFnHeader->startpc); @@ -2726,7 +2733,7 @@ void VuBaseBlock::Recompile() AND32ItoM( (uptr)&VU0.VI[ REG_VPU_STAT ].UL, s_vu?~0x100:~0x001 ); // E flag AND32ItoM( (uptr)&VU->vifRegs->stat, ~0x4 ); if( !branch ) MOV32ItoM((uptr)&VU->VI[REG_TPC], endpc); - JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr[0] + 5 )); + JMP32( (uptr)SuperVUEndProgram - ( (uptr)x86Ptr + 5 )); } else { @@ -2770,7 +2777,7 @@ void VuBaseBlock::Recompile() #ifdef SUPERVU_X86CACHING if( nEndx86 >= 0 ) { _x86regs* endx86 = &s_vecRegArray[nEndx86]; - for(int i = 0; i < X86REGS; ++i) { + for(int i = 0; i < iREGCNT_GPR; ++i) { if( endx86[i].inuse ) { if( s_JumpX86 == i && x86regs[s_JumpX86].inuse ) { @@ -2868,7 +2875,7 @@ void VuBaseBlock::Recompile() } } - pendcode = x86Ptr[0]; + pendcode = x86Ptr; type |= BLOCKTYPE_ANALYZED; LISTBLOCKS::iterator itchild; @@ -2962,8 +2969,8 @@ int VuInstruction::SetCachedRegs(int upper, u32 vuxyz) void VuInstruction::Recompile(list::iterator& itinst, u32 vuxyz) { - static PCSX2_ALIGNED16(VECTOR _VF); - static PCSX2_ALIGNED16(VECTOR _VFc); + //static PCSX2_ALIGNED16(VECTOR _VF); + //static PCSX2_ALIGNED16(VECTOR _VFc); u32 *ptr; u8* pjmp; int vfregstore=0; @@ -3237,7 +3244,7 @@ void VuInstruction::Recompile(list::iterator& itinst, u32 vuxyz) #ifdef SUPERVU_X86CACHING // redo the counters so that the proper regs are released - for(int j = 0; j < X86REGS; ++j) { + for(int j = 0; j < iREGCNT_GPR; ++j) { if( x86regs[j].inuse && X86_ISVI(x86regs[j].type) ) { int count = 0; itinst2 = itinst; @@ -3568,8 +3575,8 @@ void recVUMI_BranchHandle() if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 || SUPERVU_CHECKCONDITION) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), bpc); - MOV32ItoR(s_JumpX86, 0); - s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr[0]-1; + MOV32ItoR(s_JumpX86, 1); // use 1 to disable optimization to XOR + s_pCurBlock->pChildJumps[curjump] = (u32*)x86Ptr-1; if( !(s_pCurInst->type & INST_BRANCH_DELAY) ) { j8Ptr[1] = JMP8(0); @@ -3577,8 +3584,8 @@ void recVUMI_BranchHandle() if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 || SUPERVU_CHECKCONDITION ) MOV32ItoM(SuperVUGetVIAddr(REG_TPC, 0), pc+8); - MOV32ItoR(s_JumpX86, 0); - s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr[0]-1; + MOV32ItoR(s_JumpX86, 1); // use 1 to disable optimization to XOR + s_pCurBlock->pChildJumps[curjump+1] = (u32*)x86Ptr-1; x86SetJ8( j8Ptr[ 1 ] ); } @@ -3814,8 +3821,8 @@ void recVUMI_B( VURegs* vuu, s32 info ) if( s_pCurBlock->blocks.size() > 1 ) { s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); - MOV32ItoR(s_JumpX86, 0); - s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr[0]-1; + MOV32ItoR(s_JumpX86, 1); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; s_UnconditionalDelay = 1; } @@ -3840,8 +3847,8 @@ void recVUMI_BAL( VURegs* vuu, s32 info ) if( s_pCurBlock->blocks.size() > 1 ) { s_JumpX86 = _allocX86reg(-1, X86TYPE_VUJUMP, 0, MODE_WRITE); - MOV32ItoR(s_JumpX86, 0); - s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr[0]-1; + MOV32ItoR(s_JumpX86, 1); + s_pCurBlock->pChildJumps[(s_pCurInst->type & INST_BRANCH_DELAY)?1:0] = (u32*)x86Ptr-1; s_UnconditionalDelay = 1; } @@ -3852,8 +3859,13 @@ void recVUMI_JR( VURegs* vuu, s32 info ) { int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); LEA32RStoR(EAX, fsreg, 3); - CWDE(); - + + //Mask the address to something valid + if(vuu == &VU0) + AND32ItoR(EAX, 0xfff); + else + AND32ItoR(EAX, 0x3fff); + if( (s_pCurBlock->type & BLOCKTYPE_HASEOP) || s_vu == 0 ) MOV32RtoM(SuperVUGetVIAddr(REG_TPC, 0), EAX); if( !(s_pCurBlock->type & BLOCKTYPE_HASEOP) ) { @@ -3869,7 +3881,12 @@ void recVUMI_JALR( VURegs* vuu, s32 info ) int fsreg = _allocX86reg(-1, X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Fs_, MODE_READ); LEA32RStoR(EAX, fsreg, 3); - CWDE(); // necessary, charlie and chocolate factory gives bad addrs, but graphics are ok + + //Mask the address to something valid + if(vuu == &VU0) + AND32ItoR(EAX, 0xfff); + else + AND32ItoR(EAX, 0x3fff); if ( _Ft_ ) { _deleteX86reg(X86TYPE_VI|(s_vu?X86TYPE_VU1:0), _Ft_, 2); diff --git a/pcsx2/x86/ix86-32/aVif_proc-32.asm b/pcsx2/x86/ix86-32/aVif_proc-32.asm index 12c8b969b4..62fd377795 100644 --- a/pcsx2/x86/ix86-32/aVif_proc-32.asm +++ b/pcsx2/x86/ix86-32/aVif_proc-32.asm @@ -5,9 +5,9 @@ .xmm -extern _vifRegs:ptr -extern _vifMaskRegs:ptr -extern _vifRow:ptr +extern vifRegs:ptr +extern vifMaskRegs:ptr +extern vifRow:ptr extern s_TempDecompress:ptr @@ -104,7 +104,7 @@ UNPACK_Regular_SSE_2 macro r0 UNPACK_Setup_Mask_SSE macro CL - mov eax, [_vifMaskRegs] + mov eax, [vifMaskRegs] movdqa xmm4, [eax + 64*(CL) + 16] movdqa xmm5, [eax + 64*(CL) + 32] movdqa xmm3, [eax + 64*(CL)] @@ -118,7 +118,7 @@ UNPACK_Start_Setup_Mask_SSE_0 macro CL endm UNPACK_Start_Setup_Mask_SSE_1 macro CL - mov eax, [_vifMaskRegs] + mov eax, [vifMaskRegs] movdqa xmm4, [eax + 64*(CL) + 16] movdqa xmm5, [eax + 64*(CL) + 32] pand xmm4, xmm6 @@ -132,14 +132,14 @@ UNPACK_Start_Setup_Mask_SSE_2 macro CL UNPACK_Setup_Mask_SSE_0_1 macro CL endm UNPACK_Setup_Mask_SSE_1_1 macro CL - mov eax, [_vifMaskRegs] + mov eax, [vifMaskRegs] movdqa xmm3, [eax + 64*(0)] endm UNPACK_Setup_Mask_SSE_2_1 macro CL - mov eax, [_vifMaskRegs] + mov eax, [vifMaskRegs] movdqa xmm4, [eax + 64*(0) + 16] movdqa xmm5, [eax + 64*(0) + 32] movdqa xmm3, [eax + 64*(0)] @@ -1521,9 +1521,9 @@ UNPACK_V4_5SSE_1A macro CL, TOTALCL, MaskType, ModeType SAVE_ROW_REG_BASE macro - mov eax, [_vifRow] + mov eax, [vifRow] movdqa [eax], xmm6 - mov eax, [_vifRegs] + mov eax, [vifRegs] movss dword ptr [eax+0100h], xmm6 psrldq xmm6, 4 movss dword ptr [eax+0110h], xmm6 @@ -1557,7 +1557,7 @@ defUNPACK_SkippingWrite macro name, MaskType, ModeType, qsize, sign, SAVE_ROW_RE push ebx INIT_ARGS - mov eax, [_vifRegs] + mov eax, [vifRegs] movzx ecx, byte ptr [eax + 040h] movzx ebx, byte ptr [eax + 041h] sub ecx, ebx diff --git a/pcsx2/x86/ix86-32/iCore-32.cpp b/pcsx2/x86/ix86-32/iCore-32.cpp index 1021644be3..e90e051a22 100644 --- a/pcsx2/x86/ix86-32/iCore-32.cpp +++ b/pcsx2/x86/ix86-32/iCore-32.cpp @@ -17,7 +17,7 @@ */ #include "PrecompiledHeader.h" -#include "Misc.h" +#include "System.h" #include "iR5900.h" #include "Vif.h" #include "VU.h" @@ -78,16 +78,16 @@ int _getFreeX86reg(int mode) int i, tempi; u32 bestcount = 0x10000; - int maxreg = (mode&MODE_8BITREG)?4:X86REGS; + int maxreg = (mode&MODE_8BITREG)?4:iREGCNT_GPR; - for (i=0; i= maxreg ) continue; if( (mode&MODE_NOFRAME) && reg==EBP ) continue; if (x86regs[reg].inuse == 0) { - g_x86checknext = (reg+1)%X86REGS; + g_x86checknext = (reg+1)%iREGCNT_GPR; return reg; } } @@ -161,7 +161,7 @@ void _flushConstRegs() zero_cnt++; } - rewindPtr = x86Ptr[_EmitterId_]; + rewindPtr = x86Ptr; for (i = 1, j = 0; i < 32; j++ && ++i, j %= 2) { if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1<= 0 && x86reg < X86REGS ); + assert( x86reg >= 0 && x86reg < iREGCNT_GPR ); if( x86regs[x86reg].inuse && (x86regs[x86reg].mode&MODE_WRITE) ) { x86regs[x86reg].mode &= ~MODE_WRITE; @@ -419,7 +419,7 @@ void _freeX86reg(int x86reg) void _freeX86regs() { int i; - for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { // mmxregs[i] is unsigned, and MMX_GPR == 0, so the first part is always true. if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR] & (EEINST_LIVE0|EEINST_LIVE1)) ) { @@ -483,7 +483,7 @@ int _getFreeMMXreg() } // check for future xmm usage - for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { if( !(g_pCurInstInfo->regs[mmxregs[i].reg] & EEINST_MMX) ) { @@ -493,7 +493,7 @@ int _getFreeMMXreg() } } - for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { if( !EEINST_ISLIVE64(mmxregs[i].reg-MMX_GPR) ) { @@ -721,7 +721,7 @@ u8 _hasFreeMMXreg() } // check for dead regs - for (i=0; i= MMX_GPR && mmxregs[i].reg < MMX_GPR+34 ) { if( !(g_pCurInstInfo->regs[mmxregs[i].reg-MMX_GPR]&EEINST_USED) ) { @@ -735,7 +735,7 @@ u8 _hasFreeMMXreg() void _freeMMXreg(int mmxreg) { - assert( mmxreg < MMXREGS ); + assert( mmxreg < iREGCNT_MMX ); if (!mmxregs[mmxreg].inuse) return; if (mmxregs[mmxreg].mode & MODE_WRITE ) { @@ -762,12 +762,12 @@ void _moveMMXreg(int mmxreg) int i; if( !mmxregs[mmxreg].inuse ) return; - for (i=0; i %s", filename ); -// system( command ); - - f = fopen( filename.c_str(), "w" ); - - std::string output; - - if( disR5900GetSym(startpc) != NULL ) - fprintf(f, "%s\n", disR5900GetSym(startpc)); - for ( i = startpc; i < s_nEndBlock; i += 4 ) { - disR5900Fasm( output, memRead32( i ), i ); - fprintf( f, output.c_str() ); - } - - // write the instruction info - - fprintf(f, "\n\nlive0 - %x, live1 - %x, live2 - %x, lastuse - %x\nmmx - %x, xmm - %x, used - %x\n", - EEINST_LIVE0, EEINST_LIVE1, EEINST_LIVE2, EEINST_LASTUSE, EEINST_MMX, EEINST_XMM, EEINST_USED); - - memzero_obj(used); - numused = 0; - for(i = 0; i < ArraySize(s_pInstCache->regs); ++i) { - if( s_pInstCache->regs[i] & EEINST_USED ) { - used[i] = 1; - numused++; - } - } - - memzero_obj(fpuused); - fpunumused = 0; - for(i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { - if( s_pInstCache->fpuregs[i] & EEINST_USED ) { - fpuused[i] = 1; - fpunumused++; - } - } - - fprintf(f, " "); - for(i = 0; i < ArraySize(s_pInstCache->regs); ++i) { - if( used[i] ) fprintf(f, "%2d ", i); - } - for(i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { - if( fpuused[i] ) fprintf(f, "%2d ", i); - } - fprintf(f, "\n"); - - fprintf(f, " "); - for(i = 0; i < ArraySize(s_pInstCache->regs); ++i) { - if( used[i] ) fprintf(f, "%s ", disRNameGPR[i]); - } - for(i = 0; i < ArraySize(s_pInstCache->fpuregs); ++i) { - if( fpuused[i] ) fprintf(f, "%s ", i<32?"FR":"FA"); - } - fprintf(f, "\n"); - - pcur = s_pInstCache+1; - for( i = 0; i < (s_nEndBlock-startpc)/4; ++i, ++pcur) { - fprintf(f, "%2d: %2.2x ", i+1, pcur->info); - - count = 1; - for(j = 0; j < ArraySize(s_pInstCache->regs); j++) { - if( used[j] ) { - fprintf(f, "%2.2x%s", pcur->regs[j], ((count%8)&&countfpuregs); j++) { - if( fpuused[j] ) { - fprintf(f, "%2.2x%s", pcur->fpuregs[j], ((count%8)&&count(recMem); + memset_8<0xcc, REC_CACHEMEM>(recMem); // 0xcc is INT3 memzero_ptr( m_recBlockAlloc ); ClearRecLUT((BASEBLOCK*)m_recBlockAlloc, (((Ps2MemSize::Base + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4))); @@ -579,8 +478,8 @@ void recResetEE( void ) // so a fix will have to wait until later. -_- (air) //x86SetPtr(recMem+REC_CACHEMEM); - //dyna_block_discard_recmem=(u8*)x86Ptr[0]; - //JMP32( (uptr)&dyna_block_discard - ( (u32)x86Ptr[0] + 5 )); + //dyna_block_discard_recmem=(u8*)x86Ptr; + //JMP32( (uptr)&dyna_block_discard - ( (u32)x86Ptr + 5 )); x86SetPtr(recMem); @@ -677,7 +576,7 @@ static void __naked DispatcherReg() } } -__forceinline void recExecute() +void recExecute() { // Optimization note : Compared pushad against manually pushing the regs one-by-one. // Manually pushing is faster, especially on Core2's and such. :) @@ -791,7 +690,7 @@ void recSYSCALL( void ) { CMP32ItoM((uptr)&cpuRegs.pc, pc); j8Ptr[0] = JE8(0); ADD32ItoM((uptr)&cpuRegs.cycle, eeScaleBlockCycles()); - JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 5 )); + JMP32((uptr)DispatcherReg - ( (uptr)x86Ptr + 5 )); x86SetJ8(j8Ptr[0]); //branch = 2; } @@ -1065,7 +964,7 @@ u32 eeScaleBlockCycles() // caused by sync hacks and such, since games seem to care a lot more about // these small blocks having accurate cycle counts. - if( s_nBlockCycles <= (5<<3) || (CHECK_EE_CYCLERATE == 0) ) + if( s_nBlockCycles <= (5<<3) || (Config.Hacks.EECycleRate == 0) ) return s_nBlockCycles >> 3; uint scalarLow, scalarMid, scalarHigh; @@ -1073,7 +972,7 @@ u32 eeScaleBlockCycles() // Note: larger blocks get a smaller scalar, to help keep // them from becoming "too fat" and delaying branch tests. - switch( CHECK_EE_CYCLERATE ) + switch( Config.Hacks.EECycleRate ) { case 0: return s_nBlockCycles >> 3; @@ -1141,19 +1040,27 @@ static void iBranchTest(u32 newpc, bool noDispatch) // Equiv code to: // cpuRegs.cycle += blockcycles; // if( cpuRegs.cycle > g_nextBranchCycle ) { DoEvents(); } - MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); - ADD32ItoR(EAX, eeScaleBlockCycles()); - MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles - SUB32MtoR(EAX, (uptr)&g_nextBranchCycle); - if (!noDispatch) { - if (newpc == 0xffffffff) - JS32((uptr)DispatcherReg - ( (uptr)x86Ptr[0] + 6 )); - else - iBranch(newpc, 1); + if (Config.Hacks.IdleLoopFF && s_nBlockFF) { + xMOV(eax, ptr32[&g_nextBranchCycle]); + xADD(ptr32[&cpuRegs.cycle], eeScaleBlockCycles()); + xCMP(eax, ptr32[&cpuRegs.cycle]); + xCMOVL(eax, ptr32[&cpuRegs.cycle]); + xMOV(ptr32[&cpuRegs.cycle], eax); + RET(); + } else { + MOV32MtoR(EAX, (uptr)&cpuRegs.cycle); + ADD32ItoR(EAX, eeScaleBlockCycles()); + MOV32RtoM((uptr)&cpuRegs.cycle, EAX); // update cycles + SUB32MtoR(EAX, (uptr)&g_nextBranchCycle); + if (!noDispatch) { + if (newpc == 0xffffffff) + JS32((uptr)DispatcherReg - ( (uptr)x86Ptr + 6 )); + else + iBranch(newpc, 1); + } + RET(); } - - RET(); } static void checkcodefn() @@ -1211,7 +1118,7 @@ void recompileNextInstruction(int delayslot) g_pCurInstInfo++; - for(i = 0; i < MMXREGS; ++i) { + for(i = 0; i < iREGCNT_MMX; ++i) { if( mmxregs[i].inuse ) { assert( MMX_ISGPR(mmxregs[i].reg) ); count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, XMMTYPE_GPRREG, mmxregs[i].reg-MMX_GPR); @@ -1220,7 +1127,7 @@ void recompileNextInstruction(int delayslot) } } - for(i = 0; i < XMMREGS; ++i) { + for(i = 0; i < iREGCNT_XMM; ++i) { if( xmmregs[i].inuse ) { count = _recIsRegWritten(g_pCurInstInfo, (s_nEndBlock-pc)/4 + 1, xmmregs[i].type, xmmregs[i].reg); if( count > 0 ) xmmregs[i].counter = 1000-count; @@ -1283,8 +1190,9 @@ void recompileNextInstruction(int delayslot) return; } } + //If thh COP0 DIE bit is disabled, double the cycles. Happens rarely. + s_nBlockCycles += opcode.cycles * (2 - ((cpuRegs.CP0.n.Config >> 18) & 0x1)); opcode.recompile(); - s_nBlockCycles += opcode.cycles; } if( !delayslot ) { @@ -1310,6 +1218,9 @@ void recompileNextInstruction(int delayslot) // _freeMMXregs(); // _flushCachedRegs(); // g_cpuHasConstReg = 1; + + if (!delayslot && x86Ptr - recPtr > 0x1000) + s_nEndBlock = pc; } extern u32 psxdump; @@ -1348,6 +1259,13 @@ void __fastcall dyna_block_discard(u32 start,u32 sz) Cpu->Clear(start,sz); } +void __fastcall dyna_block_reset(u32 start,u32 sz) +{ + DevCon::WriteLn("dyna_block_reset %08X , count %d", params start,sz); + Cpu->Clear(start & ~0xfffUL, 0x400); + mmap_MarkCountedRamPage(PSM(start), start & ~0xfffUL); +} + void recRecompile( const u32 startpc ) { u32 i = 0; @@ -1375,7 +1293,11 @@ void recRecompile( const u32 startpc ) x86SetPtr( recPtr ); x86Align(16); - recPtr = x86Ptr[_EmitterId_]; + recPtr = x86Ptr; + + s_nBlockFF = false; + if (HWADDR(startpc) == 0x81fc0) + s_nBlockFF = true; s_pCurBlock = PC_GETBLOCK(startpc); @@ -1581,7 +1503,7 @@ StartRecomp: // see how many stores there are u32 j; // use xmmregs since only supporting lwc1,lq,swc1,sq - for(j = i+8; j < s_nEndBlock && j < i+4*XMMREGS; j += 4 ) { + for(j = i+8; j < s_nEndBlock && j < i+4*iREGCNT_XMM; j += 4 ) { u32 nncode = *(u32*)PSM(j); if( (nncode>>26) != (curcode>>26) || ((curcode>>21)&0x1f) != ((nncode>>21)&0x1f) || _eeLoadWritesRs(nncode)) @@ -1590,7 +1512,7 @@ StartRecomp: if( j > i+8 ) { u32 num = (j-i)>>2; // number of stores that can coissue - assert( num <= XMMREGS ); + assert( num <= iREGCNT_XMM ); g_pCurInstInfo[0].numpeeps = num-1; g_pCurInstInfo[0].info |= EEINSTINFO_COREC; @@ -1688,9 +1610,10 @@ StartRecomp: iDumpBlock(startpc, recPtr); #endif + static u16 manual_page[Ps2MemSize::Base >> 12]; u32 sz=(s_nEndBlock-startpc)>>2; - u32 inpage_ptr=startpc; + u32 inpage_ptr=HWADDR(startpc); u32 inpage_sz=sz*4; while(inpage_sz) @@ -1701,12 +1624,14 @@ StartRecomp: if(PageType!=-1) { - if (PageType==0) + if (PageType==0) { mmap_MarkCountedRamPage(PSM(inpage_ptr),inpage_ptr&~0xFFF); + manual_page[inpage_ptr >> 12] = 0; + } else { - MOV32ItoR(ECX, startpc); - MOV32ItoR(EDX, sz); + MOV32ItoR(ECX, inpage_ptr); + MOV32ItoR(EDX, pgsz); u32 lpc=inpage_ptr; u32 stg=pgsz; @@ -1714,11 +1639,16 @@ StartRecomp: { // was dyna_block_discard_recmem. See note in recResetEE for details. CMP32ItoM((uptr)PSM(lpc),*(u32*)PSM(lpc)); - JNE32(((u32)&dyna_block_discard)- ( (u32)x86Ptr[0] + 6 )); + JNE32(((u32)&dyna_block_discard)- ( (u32)x86Ptr + 6 )); stg-=4; lpc+=4; } + if (startpc != 0x81fc0) { + xADD(ptr16[&manual_page[inpage_ptr >> 12]], 1); + xJC( dyna_block_reset ); + } + DbgCon::WriteLn("Manual block @ %08X : %08X %d %d %d %d", params startpc,inpage_ptr,pgsz,0x1000-inpage_offs,inpage_sz,sz*4); } @@ -1796,18 +1726,18 @@ StartRecomp: if( willbranch3 || !branch) { iFlushCall(FLUSH_EVERYTHING); - iBranch(pc, 0); + iBranchTest(pc); } } - assert( x86Ptr[0] < recMem+REC_CACHEMEM ); + assert( x86Ptr < recMem+REC_CACHEMEM ); assert( recStackPtr < recStack+RECSTACK_SIZE ); assert( x86FpuState == 0 ); - assert(x86Ptr[_EmitterId_] - recPtr < 0x10000); - s_pCurBlockEx->x86size = x86Ptr[_EmitterId_] - recPtr; + assert(x86Ptr - recPtr < 0x10000); + s_pCurBlockEx->x86size = x86Ptr - recPtr; - recPtr = x86Ptr[0]; + recPtr = x86Ptr; assert( (g_cpuHasConstReg&g_cpuFlushedConstReg) == g_cpuHasConstReg ); diff --git a/pcsx2/x86/ix86-32/iR5900Arit.cpp b/pcsx2/x86/ix86-32/iR5900Arit.cpp index ec344dc1fb..2106347b60 100644 --- a/pcsx2/x86/ix86-32/iR5900Arit.cpp +++ b/pcsx2/x86/ix86-32/iR5900Arit.cpp @@ -116,9 +116,18 @@ void recADD_constv(int info, int creg, int vreg) } else { if( _Rd_ == vreg ) { - ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); - if( EEINST_ISLIVE1(_Rd_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); - else EEINST_RESETHASLIVE1(_Rd_); + if( EEINST_ISLIVE1(_Rd_) ) + { + // must perform the ADD unconditionally, to maintain flags status: + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rd_ ].UL[ 1 ]); + } + else + { + if( g_cpuConstRegs[creg].UL[0] ) + ADD32ItoM((int)&cpuRegs.GPR.r[_Rd_].UL[ 0 ], g_cpuConstRegs[creg].UL[0]); + EEINST_RESETHASLIVE1(_Rd_); + } } else { MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ vreg ].UL[ 0 ] ); diff --git a/pcsx2/x86/ix86-32/iR5900AritImm.cpp b/pcsx2/x86/ix86-32/iR5900AritImm.cpp index 4d805768e3..7ae89bfe0a 100644 --- a/pcsx2/x86/ix86-32/iR5900AritImm.cpp +++ b/pcsx2/x86/ix86-32/iR5900AritImm.cpp @@ -111,9 +111,17 @@ void recADDI_(int info) } else { if ( _Rt_ == _Rs_ ) { - ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); - if ( EEINST_ISLIVE1(_Rt_) ) _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); - else EEINST_RESETHASLIVE1(_Rt_); + if ( EEINST_ISLIVE1(_Rt_) ) + { + // must perform the ADD unconditionally, to maintain flags status: + ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + _signExtendSFtoM( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 1 ]); + } + else + { + if( _Imm_ ) ADD32ItoM((int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ], _Imm_); + EEINST_RESETHASLIVE1(_Rt_); + } } else { MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] ); diff --git a/pcsx2/x86/ix86-32/iR5900LoadStore.cpp b/pcsx2/x86/ix86-32/iR5900LoadStore.cpp index 83925362c3..aaf93d1d47 100644 --- a/pcsx2/x86/ix86-32/iR5900LoadStore.cpp +++ b/pcsx2/x86/ix86-32/iR5900LoadStore.cpp @@ -1930,7 +1930,7 @@ void recLQC2( void ) dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); if( _Ft_ ) { - u8* rawreadptr = x86Ptr[0]; + u8* rawreadptr = x86Ptr; if( mmreg >= 0 ) { SSEX_MOVDQARmtoROffset(mmreg, ECX, PS2MEM_BASE_+s_nAddMemOffset); @@ -1945,7 +1945,7 @@ void recLQC2( void ) // check if writing to VUs CMP32ItoR(ECX, 0x11000000); - JAE8(rawreadptr - (x86Ptr[0]+2)); + JAE8(rawreadptr - (x86Ptr+2)); PUSH32I( (int)&VU0.VF[_Ft_].UD[0] ); CALLFunc( (int)recMemRead128 ); @@ -1999,7 +1999,7 @@ void recSQC2( void ) mmregs = _eePrepareReg(_Rs_); dohw = recSetMemLocation(_Rs_, _Imm_, mmregs, 2, 0); - rawreadptr = x86Ptr[0]; + rawreadptr = x86Ptr; if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { SSEX_MOVDQARtoRmOffset(ECX, mmreg, PS2MEM_BASE_+s_nAddMemOffset); @@ -2039,7 +2039,7 @@ void recSQC2( void ) // check if writing to VUs CMP32ItoR(ECX, 0x11000000); - JAE8(rawreadptr - (x86Ptr[0]+2)); + JAE8(rawreadptr - (x86Ptr+2)); // some type of hardware write if( (mmreg = _checkXMMreg(XMMTYPE_VFREG, _Ft_, MODE_READ)) >= 0) { @@ -2101,7 +2101,7 @@ void recLoad64( u32 bits, bool sign ) if ( _Imm_ != 0 ) ADD32ItoR( ECX, _Imm_ ); if( bits == 128 ) // force 16 byte alignment on 128 bit reads - AND32I8toR(ECX,0xF0); + AND32ItoR(ECX,~0x0F); // emitter automatically encodes this as an 8-bit sign-extended imm8 _eeOnLoadWrite(_Rt_); EEINST_RESETSIGNEXT(_Rt_); // remove the sign extension @@ -2198,7 +2198,7 @@ void recStore(u32 sz, bool edxAlreadyAssigned=false) if ( _Imm_ != 0 ) ADD32ItoR(ECX, _Imm_); if (sz==128) - AND32I8toR(ECX,0xF0); + AND32ItoR(ECX,~0x0F); vtlb_DynGenWrite(sz); } diff --git a/pcsx2/x86/ix86-32/iR5900Move.cpp b/pcsx2/x86/ix86-32/iR5900Move.cpp index d61ade09ab..0d1878e26b 100644 --- a/pcsx2/x86/ix86-32/iR5900Move.cpp +++ b/pcsx2/x86/ix86-32/iR5900Move.cpp @@ -316,7 +316,7 @@ void recMFHILO1(int hi) if( reghi >= 0 ) { if( regd >= 0 ) { - SSEX_MOVHLPS_XMM_to_XMM(regd, reghi); + SSE_MOVHLPS_XMM_to_XMM(regd, reghi); xmmregs[regd].mode |= MODE_WRITE; } else { diff --git a/pcsx2/x86/ix86-32/recVTLB.cpp b/pcsx2/x86/ix86-32/recVTLB.cpp index cbc567c68d..19e8fe8408 100644 --- a/pcsx2/x86/ix86-32/recVTLB.cpp +++ b/pcsx2/x86/ix86-32/recVTLB.cpp @@ -25,20 +25,29 @@ #include "iR5900.h" using namespace vtlb_private; +using namespace x86Emitter; // NOTICE: This function *destroys* EAX!! // Moves 128 bits of memory from the source register ptr to the dest register ptr. // (used as an equivalent to movaps, when a free XMM register is unavailable for some reason) void MOV128_MtoM( x86IntRegType destRm, x86IntRegType srcRm ) { - MOV32RmtoR(EAX,srcRm); - MOV32RtoRm(destRm,EAX); - MOV32RmtoROffset(EAX,srcRm,4); - MOV32RtoRmOffset(destRm,EAX,4); - MOV32RmtoROffset(EAX,srcRm,8); - MOV32RtoRmOffset(destRm,EAX,8); - MOV32RmtoROffset(EAX,srcRm,12); - MOV32RtoRmOffset(destRm,EAX,12); + // (this is one of my test cases for the new emitter --air) + + xAddressReg src( srcRm ); + xAddressReg dest( destRm ); + + xMOV( eax, ptr[src] ); + xMOV( ptr[dest], eax ); + + xMOV( eax, ptr[src+4] ); + xMOV( ptr[dest+4], eax ); + + xMOV( eax, ptr[src+8] ); + xMOV( ptr[dest+8], eax ); + + xMOV( eax, ptr[src+12] ); + xMOV( ptr[dest+12], eax ); } /* @@ -121,8 +130,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign ) if( _hasFreeMMXreg() ) { const int freereg = _allocMMXreg(-1, MMX_TEMP, 0); - MOVQRmtoROffset(freereg,ECX,0); - MOVQRtoRmOffset(EDX,freereg,0); + MOVQRmtoR(freereg,ECX); + MOVQRtoRm(EDX,freereg); _freeMMXreg(freereg); } else @@ -130,8 +139,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign ) MOV32RmtoR(EAX,ECX); MOV32RtoRm(EDX,EAX); - MOV32RmtoROffset(EAX,ECX,4); - MOV32RtoRmOffset(EDX,EAX,4); + MOV32RmtoR(EAX,ECX,4); + MOV32RtoRm(EDX,EAX,4); } break; @@ -139,8 +148,8 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign ) if( _hasFreeXMMreg() ) { const int freereg = _allocTempXMMreg( XMMT_INT, -1 ); - SSE2_MOVDQARmtoROffset(freereg,ECX,0); - SSE2_MOVDQARtoRmOffset(EDX,freereg,0); + SSE2_MOVDQARmtoR(freereg,ECX); + SSE2_MOVDQARtoRm(EDX,freereg); _freeXMMreg(freereg); } else @@ -156,6 +165,7 @@ static void _vtlb_DynGen_DirectRead( u32 bits, bool sign ) } } +// ------------------------------------------------------------------------ static void _vtlb_DynGen_IndirectRead( u32 bits ) { int szidx; @@ -178,6 +188,7 @@ static void _vtlb_DynGen_IndirectRead( u32 bits ) CALL32R(EAX); } +// ------------------------------------------------------------------------ // Recompiled input registers: // ecx = source addr to read from // edx = ptr to dest to write to @@ -189,17 +200,18 @@ void vtlb_DynGenRead64(u32 bits) SHR32ItoR(EAX,VTLB_PAGE_BITS); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); - u8* _fullread = JS8(0); + xForwardJS8 _fullread; _vtlb_DynGen_DirectRead( bits, false ); - u8* cont = JMP8(0); + xForwardJump8 cont; - x86SetJ8(_fullread); + _fullread.SetTarget(); + _vtlb_DynGen_IndirectRead( bits ); - - x86SetJ8(cont); + cont.SetTarget(); } +// ------------------------------------------------------------------------ // Recompiled input registers: // ecx - source address to read from // Returns read value in eax. @@ -211,12 +223,12 @@ void vtlb_DynGenRead32(u32 bits, bool sign) SHR32ItoR(EAX,VTLB_PAGE_BITS); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); - u8* _fullread = JS8(0); + xForwardJS8 _fullread; _vtlb_DynGen_DirectRead( bits, sign ); - u8* cont = JMP8(0); + xForwardJump8 cont; - x86SetJ8(_fullread); + _fullread.SetTarget(); _vtlb_DynGen_IndirectRead( bits ); // perform sign extension on the result: @@ -235,11 +247,10 @@ void vtlb_DynGenRead32(u32 bits, bool sign) else MOVZX32R16toR(EAX,EAX); } - - x86SetJ8(cont); + cont.SetTarget(); } -// +// ------------------------------------------------------------------------ // TLB lookup is performed in const, with the assumption that the COP0/TLB will clear the // recompiler if the TLB is changed. void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) @@ -255,7 +266,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) { const int freereg = _allocMMXreg(-1, MMX_TEMP, 0); MOVQMtoR(freereg,ppf); - MOVQRtoRmOffset(EDX,freereg,0); + MOVQRtoRm(EDX,freereg); _freeMMXreg(freereg); } else @@ -264,7 +275,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) MOV32RtoRm(EDX,EAX); MOV32MtoR(EAX,ppf+4); - MOV32RtoRmOffset(EDX,EAX,4); + MOV32RtoRm(EDX,EAX,4); } break; @@ -273,7 +284,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) { const int freereg = _allocTempXMMreg( XMMT_INT, -1 ); SSE2_MOVDQA_M128_to_XMM( freereg, ppf ); - SSE2_MOVDQARtoRmOffset(EDX,freereg,0); + SSE2_MOVDQARtoRm(EDX,freereg); _freeXMMreg(freereg); } else @@ -307,6 +318,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) } } +// ------------------------------------------------------------------------ // Recompiled input registers: // ecx - source address to read from // Returns read value in eax. @@ -355,7 +367,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const ) } // Shortcut for the INTC_STAT register, which many games like to spin on heavily. - if( (bits == 32) && !CHECK_INTC_STAT_HACK && (paddr == INTC_STAT) ) + if( (bits == 32) && !Config.Hacks.INTCSTATSlow && (paddr == INTC_STAT) ) { MOV32MtoR( EAX, (uptr)&psHu32( INTC_STAT ) ); } @@ -406,8 +418,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits ) if( _hasFreeMMXreg() ) { const int freereg = _allocMMXreg(-1, MMX_TEMP, 0); - MOVQRmtoROffset(freereg,EDX,0); - MOVQRtoRmOffset(ECX,freereg,0); + MOVQRmtoR(freereg,EDX); + MOVQRtoRm(ECX,freereg); _freeMMXreg( freereg ); } else @@ -415,8 +427,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits ) MOV32RmtoR(EAX,EDX); MOV32RtoRm(ECX,EAX); - MOV32RmtoROffset(EAX,EDX,4); - MOV32RtoRmOffset(ECX,EAX,4); + MOV32RmtoR(EAX,EDX,4); + MOV32RtoRm(ECX,EAX,4); } break; @@ -424,8 +436,8 @@ static void _vtlb_DynGen_DirectWrite( u32 bits ) if( _hasFreeXMMreg() ) { const int freereg = _allocTempXMMreg( XMMT_INT, -1 ); - SSE2_MOVDQARmtoROffset(freereg,EDX,0); - SSE2_MOVDQARtoRmOffset(ECX,freereg,0); + SSE2_MOVDQARmtoR(freereg,EDX); + SSE2_MOVDQARtoRm(ECX,freereg); _freeXMMreg( freereg ); } else @@ -439,6 +451,7 @@ static void _vtlb_DynGen_DirectWrite( u32 bits ) } } +// ------------------------------------------------------------------------ static void _vtlb_DynGen_IndirectWrite( u32 bits ) { int szidx=0; @@ -458,24 +471,26 @@ static void _vtlb_DynGen_IndirectWrite( u32 bits ) CALL32R(EAX); } +// ------------------------------------------------------------------------ void vtlb_DynGenWrite(u32 sz) { MOV32RtoR(EAX,ECX); SHR32ItoR(EAX,VTLB_PAGE_BITS); MOV32RmSOffsettoR(EAX,EAX,(int)vtlbdata.vmap,2); ADD32RtoR(ECX,EAX); - u8* _full=JS8(0); + xForwardJS8 _full; _vtlb_DynGen_DirectWrite( sz ); - u8* cont = JMP8(0); + xForwardJump8 cont; - x86SetJ8(_full); + _full.SetTarget(); _vtlb_DynGen_IndirectWrite( sz ); - x86SetJ8(cont); + cont.SetTarget(); } +// ------------------------------------------------------------------------ // Generates code for a store instruction, where the address is a known constant. // TLB lookup is performed in const, with the assumption that the COP0/TLB will clear the // recompiler if the TLB is changed. @@ -502,7 +517,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) if( _hasFreeMMXreg() ) { const int freereg = _allocMMXreg(-1, MMX_TEMP, 0); - MOVQRmtoROffset(freereg,EDX,0); + MOVQRmtoR(freereg,EDX); MOVQRtoM(ppf,freereg); _freeMMXreg( freereg ); } @@ -511,7 +526,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) MOV32RmtoR(EAX,EDX); MOV32RtoM(ppf,EAX); - MOV32RmtoROffset(EAX,EDX,4); + MOV32RmtoR(EAX,EDX,4); MOV32RtoM(ppf+4,EAX); } break; @@ -520,7 +535,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) if( _hasFreeXMMreg() ) { const int freereg = _allocTempXMMreg( XMMT_INT, -1 ); - SSE2_MOVDQARmtoROffset(freereg,EDX,0); + SSE2_MOVDQARmtoR(freereg,EDX); SSE2_MOVDQA_XMM_to_M128(ppf,freereg); _freeXMMreg( freereg ); } diff --git a/pcsx2/x86/ix86/Makefile.am b/pcsx2/x86/ix86/Makefile.am index 7f76f134be..a85187bb58 100644 --- a/pcsx2/x86/ix86/Makefile.am +++ b/pcsx2/x86/ix86/Makefile.am @@ -1,4 +1,10 @@ -INCLUDES = -I@srcdir@/.. -I@srcdir@/../../ -I@srcdir@/../../../common/include -I@srcdir@/../../../3rdparty +INCLUDES = -I@srcdir@/.. -I@srcdir@/../../ -I@srcdir@/../../../common/include -I@srcdir@/../../../3rdparty -I/implement -I/implement/xmm noinst_LIBRARIES = libix86.a -libix86_a_SOURCES = ix86.cpp ix86.inl ix86_3dnow.inl ix86.h ix86_fpu.inl ix86_mmx.inl ix86_sse.inl ix86_tools.cpp ix86_cpudetect.cpp ix86_macros.h \ No newline at end of file +libix86_a_SOURCES = \ +ix86.cpp ix86_cpudetect.cpp ix86_fpu.cpp ix86_jmp.cpp ix86_tools.cpp ix86_3dnow.cpp \ +ix86_legacy.cpp ix86_legacy_sse.cpp ix86_simd.cpp \ +ix86_internal.h ix86_legacy_instructions.h ix86_macros.h ix86_sse_helpers.h ix86.h ix86_legacy_internal.h \ +ix86_instructions.h ix86_legacy_types.h ix86_types.h \ +bittest.h dwshift.h group1.h group2.h group3.h incdec.h jmpcall.h movs.h test.h \ +movqss.h arithmetic.h shufflepack.h basehelpers.h comparisons.h moremovs.h xchg.h \ No newline at end of file diff --git a/pcsx2/x86/ix86/implement/dwshift.h b/pcsx2/x86/ix86/implement/dwshift.h new file mode 100644 index 0000000000..b0499f46e0 --- /dev/null +++ b/pcsx2/x86/ix86/implement/dwshift.h @@ -0,0 +1,55 @@ +/* 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 here cover SHLD and SHRD. +// Note: This header is meant to be included from within the x86Emitter::Internal namespace. + +////////////////////////////////////////////////////////////////////////////////////////// +// I use explicit method declarations here instead of templates, in order to provide +// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in SHLD/SHRD). +// +// Optimization Note: Imm shifts by 0 are ignore (no code generated). This is a safe optimization +// because shifts by 0 do *not* affect flags status. +// +template< bool isShiftRight > +class DwordShiftImplAll +{ + static const u8 m_shiftop = isShiftRight ? 0x8 : 0; + +public: + // ---------- 32 Bit Interface ----------- + __forceinline void operator()( const xRegister32& to, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, to, from ); } + __forceinline void operator()( void* dest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, from, dest ); } + __forceinline void operator()( const ModSibBase& dest, const xRegister32& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0xa5 | m_shiftop, from, dest ); } + __forceinline void operator()( const xRegister32& to, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, to, from ); } + __forceinline void operator()( void* dest, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, from, dest, shiftcnt ); } + __forceinline void operator()( const ModSibBase& dest, const xRegister32& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0xa4 | m_shiftop, from, dest, shiftcnt ); } + + // ---------- 16 Bit Interface ----------- + __forceinline void operator()( const xRegister16& to, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, to, from ); } + __forceinline void operator()( void* dest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, from, dest ); } + __forceinline void operator()( const ModSibBase& dest, const xRegister16& from, __unused const xRegisterCL& clreg ) const { xOpWrite0F( 0x66, 0xa5 | m_shiftop, from, dest ); } + __forceinline void operator()( const xRegister16& to, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, to, from ); } + __forceinline void operator()( void* dest, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, from, dest, shiftcnt ); } + __forceinline void operator()( const ModSibBase& dest, const xRegister16& from, u8 shiftcnt ) const { if( shiftcnt != 0 ) xOpWrite0F( 0x66, 0xa4 | m_shiftop, from, dest, shiftcnt ); } + + DwordShiftImplAll() {} // Why does GCC need these? +}; + diff --git a/pcsx2/x86/ix86/implement/group1.h b/pcsx2/x86/ix86/implement/group1.h new file mode 100644 index 0000000000..2afdc40303 --- /dev/null +++ b/pcsx2/x86/ix86/implement/group1.h @@ -0,0 +1,185 @@ +/* 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 + +// 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 > __forceinline void operator()( const xRegister& to, const void* src ) const + { + prefix16(); + xWrite8( (Is8BitOp() ? 2 : 3) | (InstType<<3) ); + EmitSibMagic( to, src ); + } + + // ------------------------------------------------------------------------ + template< typename T > __forceinline void operator()( void* dest, const xRegister& from ) const + { + prefix16(); + xWrite8( (Is8BitOp() ? 0 : 1) | (InstType<<3) ); + EmitSibMagic( from, dest ); + } + + // ------------------------------------------------------------------------ + 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 ); + } + } + + 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 void* 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? +}; diff --git a/pcsx2/x86/ix86/implement/group2.h b/pcsx2/x86/ix86/implement/group2.h new file mode 100644 index 0000000000..eab5bb2605 --- /dev/null +++ b/pcsx2/x86/ix86/implement/group2.h @@ -0,0 +1,98 @@ +/* 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 + +// Note: This header is meant to be included from within the x86Emitter::Internal namespace. +// Instructions implemented in this header are as follows -->> + +enum G2Type +{ + G2Type_ROL=0, + G2Type_ROR, + G2Type_RCL, + G2Type_RCR, + G2Type_SHL, + G2Type_SHR, + G2Type_Unused, + G2Type_SAR +}; + +// ------------------------------------------------------------------- +// Group 2 (shift) instructions have no Sib/ModRM forms. +// Optimization Note: For Imm forms, we ignore the instruction if the shift count is zero. +// This is a safe optimization since any zero-value shift does not affect any flags. +// +template< G2Type InstType > +class Group2ImplAll +{ +public: + template< typename T > __forceinline void operator()( const xRegister& to, __unused const xRegisterCL& from ) const + { + prefix16(); + xWrite8( Is8BitOp() ? 0xd2 : 0xd3 ); + EmitSibMagic( InstType, to ); + } + + template< typename T > __noinline void operator()( const ModSibStrict& sibdest, __unused const xRegisterCL& from ) const + { + prefix16(); + xWrite8( Is8BitOp() ? 0xd2 : 0xd3 ); + EmitSibMagic( InstType, sibdest ); + } + + template< typename T > __noinline void operator()( const ModSibStrict& sibdest, u8 imm ) const + { + if( imm == 0 ) return; + + prefix16(); + if( imm == 1 ) + { + // special encoding of 1's + xWrite8( Is8BitOp() ? 0xd0 : 0xd1 ); + EmitSibMagic( InstType, sibdest ); + } + else + { + xWrite8( Is8BitOp() ? 0xc0 : 0xc1 ); + EmitSibMagic( InstType, sibdest ); + xWrite8( imm ); + } + } + + template< typename T > __forceinline void operator()( const xRegister& to, u8 imm ) const + { + if( imm == 0 ) return; + + prefix16(); + if( imm == 1 ) + { + // special encoding of 1's + xWrite8( Is8BitOp() ? 0xd0 : 0xd1 ); + EmitSibMagic( InstType, to ); + } + else + { + xWrite8( Is8BitOp() ? 0xc0 : 0xc1 ); + EmitSibMagic( InstType, to ); + xWrite8( imm ); + } + } + + Group2ImplAll() {} // I am a class with no members, so I need an explicit constructor! Sense abounds. +}; diff --git a/pcsx2/x86/ix86/implement/group3.h b/pcsx2/x86/ix86/implement/group3.h new file mode 100644 index 0000000000..dc9bb169c2 --- /dev/null +++ b/pcsx2/x86/ix86/implement/group3.h @@ -0,0 +1,112 @@ +/* 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 + +// 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 ); + } + + 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( 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 void* src ) const { xOpWrite0F( 0xaf, to, src ); } + __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 void* src ) const { xOpWrite0F( 0x66, 0xaf, to, src ); } + __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() {} +}; diff --git a/pcsx2/x86/ix86/implement/incdec.h b/pcsx2/x86/ix86/implement/incdec.h new file mode 100644 index 0000000000..f33ed905ed --- /dev/null +++ b/pcsx2/x86/ix86/implement/incdec.h @@ -0,0 +1,53 @@ +/* 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. + + +template< bool isDec > +class xImpl_IncDec +{ +public: + template< typename T > + __forceinline void operator()( const xRegister& to ) const + { + if( Is8BitOp() ) + { + xWrite8( 0xfe ); + EmitSibMagic( isDec ? 1 : 0, to ); + } + else + { + prefix16(); + xWrite8( (isDec ? 0x48 : 0x40) | to.Id ); + } + } + + template< typename T > + __forceinline void operator()( const ModSibStrict& sibdest ) const + { + prefix16(); + xWrite8( Is8BitOp() ? 0xfe : 0xff ); + EmitSibMagic( isDec ? 1 : 0, sibdest ); + } + + xImpl_IncDec() {} // don't ask. +}; diff --git a/pcsx2/x86/ix86/implement/jmpcall.h b/pcsx2/x86/ix86/implement/jmpcall.h new file mode 100644 index 0000000000..2986410b10 --- /dev/null +++ b/pcsx2/x86/ix86/implement/jmpcall.h @@ -0,0 +1,55 @@ +/* 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: CALL and JMP! (unconditional only) +// Note: This header is meant to be included from within the x86Emitter::Internal namespace. + +// ------------------------------------------------------------------------ +template< bool isJmp > +class xImpl_JmpCall +{ +public: + xImpl_JmpCall() {} + + __forceinline void operator()( const xRegister32& absreg ) const { xOpWrite( 0x00, 0xff, isJmp ? 4 : 2, absreg ); } + __forceinline void operator()( const ModSibStrict& src ) const { xOpWrite( 0x00, 0xff, isJmp ? 4 : 2, src ); } + + __forceinline void operator()( const xRegister16& absreg ) const { xOpWrite( 0x66, 0xff, isJmp ? 4 : 2, absreg ); } + __forceinline void operator()( const ModSibStrict& src ) const { xOpWrite( 0x66, 0xff, isJmp ? 4 : 2, src ); } + + // Special form for calling functions. This form automatically resolves the + // correct displacement based on the size of the instruction being generated. + template< typename T > + __forceinline void operator()( T* func ) const + { + if( isJmp ) + xJccKnownTarget( Jcc_Unconditional, (void*)(uptr)func, false ); // double cast to/from (uptr) needed to appease GCC + else + { + // calls are relative to the instruction after this one, and length is + // always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic). + + sptr dest = (sptr)func - ((sptr)xGetPtr() + 5); + xWrite8( 0xe8 ); + xWrite32( dest ); + } + } +}; + diff --git a/pcsx2/x86/ix86/implement/movs.h b/pcsx2/x86/ix86/implement/movs.h new file mode 100644 index 0000000000..b8b5323db1 --- /dev/null +++ b/pcsx2/x86/ix86/implement/movs.h @@ -0,0 +1,308 @@ +/* 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 + +// Header: ix86_impl_movs.h -- covers mov, cmov, movsx/movzx, and SETcc (which shares +// with cmov many similarities). + +// Note: This header is meant to be included from within the x86Emitter::Internal namespace. + +////////////////////////////////////////////////////////////////////////////////////////// +// MOV instruction Implementation + +template< typename ImmType > +class MovImpl +{ +protected: + static const uint OperandSize = sizeof(ImmType); + static bool Is8BitOperand() { return OperandSize == 1; } + static void prefix16() { if( OperandSize == 2 ) xWrite8( 0x66 ); } + +public: + MovImpl() {} + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const xRegister& to, const xRegister& from ) + { + if( to == from ) return; // ignore redundant MOVs. + + prefix16(); + xWrite8( Is8BitOperand() ? 0x88 : 0x89 ); + EmitSibMagic( from, to ); + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const ModSibBase& dest, const xRegister& from ) + { + prefix16(); + + // mov eax has a special from when writing directly to a DISP32 address + // (sans any register index/base registers). + + if( from.IsAccumulator() && dest.Index.IsEmpty() && dest.Base.IsEmpty() ) + { + xWrite8( Is8BitOperand() ? 0xa2 : 0xa3 ); + xWrite32( dest.Displacement ); + } + else + { + xWrite8( Is8BitOperand() ? 0x88 : 0x89 ); + EmitSibMagic( from.Id, dest ); + } + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const xRegister& to, const ModSibBase& src ) + { + prefix16(); + + // mov eax has a special from when reading directly from a DISP32 address + // (sans any register index/base registers). + + if( to.IsAccumulator() && src.Index.IsEmpty() && src.Base.IsEmpty() ) + { + xWrite8( Is8BitOperand() ? 0xa0 : 0xa1 ); + xWrite32( src.Displacement ); + } + else + { + xWrite8( Is8BitOperand() ? 0x8a : 0x8b ); + EmitSibMagic( to, src ); + } + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( void* dest, const xRegister& from ) + { + prefix16(); + + // mov eax has a special from when writing directly to a DISP32 address + + if( from.IsAccumulator() ) + { + xWrite8( Is8BitOperand() ? 0xa2 : 0xa3 ); + xWrite( (s32)dest ); + } + else + { + xWrite8( Is8BitOperand() ? 0x88 : 0x89 ); + EmitSibMagic( from, dest ); + } + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const xRegister& to, const void* src ) + { + prefix16(); + + // mov eax has a special from when reading directly from a DISP32 address + + if( to.IsAccumulator() ) + { + xWrite8( Is8BitOperand() ? 0xa0 : 0xa1 ); + xWrite( (s32)src ); + } + else + { + xWrite8( Is8BitOperand() ? 0x8a : 0x8b ); + EmitSibMagic( to, src ); + } + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( const xRegister& to, ImmType imm ) + { + // Note: MOV does not have (reg16/32,imm8) forms. + + prefix16(); + xWrite8( (Is8BitOperand() ? 0xb0 : 0xb8) | to.Id ); + xWrite( imm ); + } + + // ------------------------------------------------------------------------ + static __emitinline void Emit( ModSibStrict dest, ImmType imm ) + { + prefix16(); + xWrite8( Is8BitOperand() ? 0xc6 : 0xc7 ); + EmitSibMagic( 0, dest ); + xWrite( imm ); + } +}; + +// ------------------------------------------------------------------------ +class MovImplAll +{ +public: + template< typename T > + __forceinline void operator()( const xRegister& to, const xRegister& from ) const { MovImpl::Emit( to, from ); } + template< typename T > + __forceinline void operator()( const xRegister& to, const void* src ) const { MovImpl::Emit( to, src ); } + template< typename T > + __forceinline void operator()( void* dest, const xRegister& from ) const { MovImpl::Emit( dest, from ); } + template< typename T > + __noinline void operator()( const ModSibBase& sibdest, const xRegister& from ) const { MovImpl::Emit( sibdest, from ); } + template< typename T > + __noinline void operator()( const xRegister& to, const ModSibBase& sibsrc ) const { MovImpl::Emit( to, sibsrc ); } + + template< typename T > + __noinline void operator()( const ModSibStrict& sibdest, int imm ) const { MovImpl::Emit( sibdest, imm ); } + + // preserve_flags - set to true to disable optimizations which could alter the state of + // the flags (namely replacing mov reg,0 with xor). + + template< typename T > + __emitinline void operator()( const xRegister& to, int imm, bool preserve_flags=false ) const + { + if( !preserve_flags && (imm == 0) ) + xXOR( to, to ); + else + MovImpl::Emit( to, imm ); + } + + MovImplAll() {} // Satisfy GCC's whims. +}; + +#define ccSane() jASSUME( ccType >= 0 && ccType <= 0x0f ) + +////////////////////////////////////////////////////////////////////////////////////////// +// CMOV !! [in all of it's disappointing lack-of glory] .. and .. +// SETcc!! [more glory, less lack!] +// +// CMOV Disclaimer: Caution! This instruction can look exciting and cool, until you +// realize that it cannot load immediate values into registers. -_- +// +// I use explicit method declarations here instead of templates, in order to provide +// *only* 32 and 16 bit register operand forms (8 bit registers are not valid in CMOV). +// +class CMovImplGeneric +{ +public: + __forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const xRegister32& from ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, from ); } + __forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const void* src ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, src ); } + __forceinline void operator()( JccComparisonType ccType, const xRegister32& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x40 | ccType, to, sibsrc ); } + + __forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const xRegister16& from ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, from ); } + __forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const void* src ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, src ); } + __forceinline void operator()( JccComparisonType ccType, const xRegister16& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x66, 0x40 | ccType, to, sibsrc ); } + + CMovImplGeneric() {} // don't ask. +}; + +// ------------------------------------------------------------------------ +template< JccComparisonType ccType > +class CMovImplAll +{ + static const u16 Opcode = 0x40 | ccType; + +public: + __forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { ccSane(); xOpWrite0F( Opcode, to, from ); } + __forceinline void operator()( const xRegister32& to, const void* src ) const { ccSane(); xOpWrite0F( Opcode, to, src ); } + __forceinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( Opcode, to, sibsrc ); } + + __forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, from ); } + __forceinline void operator()( const xRegister16& to, const void* src ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, src ); } + __forceinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { ccSane(); xOpWrite0F( 0x66, Opcode, to, sibsrc ); } + + CMovImplAll() {} // don't ask. +}; + +// ------------------------------------------------------------------------ +class SetImplGeneric +{ + // note: SETcc are 0x90, with 0 in the Reg field of ModRM. +public: + __forceinline void operator()( JccComparisonType ccType, const xRegister8& to ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, to ); } + __forceinline void operator()( JccComparisonType ccType, void* dest ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, dest ); } + __noinline void operator()( JccComparisonType ccType, const ModSibStrict& dest ) const { ccSane(); xOpWrite0F( 0x90 | ccType, 0, dest ); } + + SetImplGeneric() {} // if you do, ask GCC. +}; + +// ------------------------------------------------------------------------ +template< JccComparisonType ccType > +class SetImplAll +{ + static const u16 Opcode = 0x90 | ccType; // SETcc are 0x90 base opcode, with 0 in the Reg field of ModRM. + +public: + __forceinline void operator()( const xRegister8& to ) const { ccSane(); xOpWrite0F( Opcode, 0, to ); } + __forceinline void operator()( void* dest ) const { ccSane(); xOpWrite0F( Opcode, 0, dest ); } + __noinline void operator()( const ModSibStrict& dest ) const { ccSane(); xOpWrite0F( Opcode, 0, dest ); } + + SetImplAll() {} // if you do, ask GCC. +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// Mov with sign/zero extension implementations (movsx / movzx) +// +template< typename DestImmType, typename SrcImmType > +class MovExtendImpl +{ +protected: + static const uint DestOperandSize = sizeof( DestImmType ); + static const uint SrcOperandSize = sizeof( SrcImmType ); + + static bool Is8BitOperand() { return SrcOperandSize == 1; } + static void prefix16() { if( DestOperandSize == 2 ) xWrite8( 0x66 ); } + static __forceinline void emit_base( bool SignExtend ) + { + prefix16(); + xWrite8( 0x0f ); + xWrite8( 0xb6 | (Is8BitOperand() ? 0 : 1) | (SignExtend ? 8 : 0 ) ); + } + +public: + MovExtendImpl() {} // For the love of GCC. + + static __emitinline void Emit( const xRegister& to, const xRegister& from, bool SignExtend ) + { + emit_base( SignExtend ); + EmitSibMagic( to, from ); + } + + static __emitinline void Emit( const xRegister& to, const ModSibStrict& sibsrc, bool SignExtend ) + { + emit_base( SignExtend ); + EmitSibMagic( to, sibsrc ); + } +}; + +// ------------------------------------------------------------------------ +template< bool SignExtend > +class MovExtendImplAll +{ +protected: + typedef MovExtendImpl m_16to32; + typedef MovExtendImpl m_8to32; + typedef MovExtendImpl m_8to16; + +public: + __forceinline void operator()( const xRegister32& to, const xRegister16& from ) const { m_16to32::Emit( to, from, SignExtend ); } + __noinline void operator()( const xRegister32& to, const ModSibStrict& sibsrc ) const { m_16to32::Emit( to, sibsrc, SignExtend ); } + + __forceinline void operator()( const xRegister32& to, const xRegister8& from ) const { m_8to32::Emit( to, from, SignExtend ); } + __noinline void operator()( const xRegister32& to, const ModSibStrict& sibsrc ) const { m_8to32::Emit( to, sibsrc, SignExtend ); } + + __forceinline void operator()( const xRegister16& to, const xRegister8& from ) const { m_8to16::Emit( to, from, SignExtend ); } + __noinline void operator()( const xRegister16& to, const ModSibStrict& sibsrc ) const { m_8to16::Emit( to, sibsrc, SignExtend ); } + + MovExtendImplAll() {} // don't ask. +}; + diff --git a/pcsx2/x86/ix86/implement/test.h b/pcsx2/x86/ix86/implement/test.h new file mode 100644 index 0000000000..196c3cbba0 --- /dev/null +++ b/pcsx2/x86/ix86/implement/test.h @@ -0,0 +1,110 @@ +/* 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: TEST + BTS/BT/BTC/BTR + BSF/BSR! (for lack of better location) +// Note: This header is meant to be included from within the x86Emitter::Internal namespace. + +////////////////////////////////////////////////////////////////////////////////////////// +// TEST instruction Implementation +// +class xImpl_Test +{ +public: + // ------------------------------------------------------------------------ + template< typename T > __forceinline + void operator()( const xRegister& to, const xRegister& from ) const + { + prefix16(); + xWrite8( Is8BitOp() ? 0x84 : 0x85 ); + EmitSibMagic( from, to ); + } + + // ------------------------------------------------------------------------ + template< typename T > __forceinline + void operator()( const ModSibStrict& dest, int imm ) const + { + prefix16(); + xWrite8( Is8BitOp() ? 0xf6 : 0xf7 ); + EmitSibMagic( 0, dest ); + xWrite( imm ); + } + + // ------------------------------------------------------------------------ + template< typename T > __forceinline + void operator()( const xRegister& to, int imm ) const + { + prefix16(); + + if( to.IsAccumulator() ) + xWrite8( Is8BitOp() ? 0xa8 : 0xa9 ); + else + { + xWrite8( Is8BitOp() ? 0xf6 : 0xf7 ); + EmitSibMagic( 0, to ); + } + xWrite( imm ); + } + + xImpl_Test() {} // Why does GCC need these? +}; + +enum G8Type +{ + G8Type_BT = 4, + G8Type_BTS, + G8Type_BTR, + G8Type_BTC, +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// BSF / BSR -- 16/32 operands supported only. +// +// 0xbc [fwd] / 0xbd [rev] +// +template< u16 Opcode > +class xImpl_BitScan +{ +public: + xImpl_BitScan() {} + + __forceinline void operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( Opcode, to, from ); } + __forceinline void operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, Opcode, to, from ); } + __forceinline void operator()( const xRegister32& to, const void* src ) const { xOpWrite0F( Opcode, to, src ); } + __forceinline void operator()( const xRegister16& to, const void* src ) const { xOpWrite0F( 0x66, Opcode, to, src ); } + __forceinline void operator()( const xRegister32& to, const ModSibBase& sibsrc ) const { xOpWrite0F( Opcode, to, sibsrc ); } + __forceinline void operator()( const xRegister16& to, const ModSibBase& sibsrc ) const { xOpWrite0F( 0x66, Opcode, to, sibsrc ); } +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Bit Test Instructions - Valid on 16/32 bit instructions only. +// +template< G8Type InstType > +class xImpl_Group8 : public xImpl_BitScan<0xa3 | (InstType << 2)> +{ +public: + using xImpl_BitScan<0xa3 | (InstType << 2)>::operator(); + + __forceinline void operator()( const ModSibStrict& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase, bitoffset ); } + __forceinline void operator()( const ModSibStrict& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase, bitoffset ); } + void operator()( const xRegister& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase, bitoffset ); } + void operator()( const xRegister& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase, bitoffset ); } + + xImpl_Group8() {} +}; diff --git a/pcsx2/x86/ix86/implement/xchg.h b/pcsx2/x86/ix86/implement/xchg.h new file mode 100644 index 0000000000..2128728458 --- /dev/null +++ b/pcsx2/x86/ix86/implement/xchg.h @@ -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 + +// This header file is intended to be the future home of xchg, cmpxchg, xadd, and +// other threading-related exchange instructions. diff --git a/pcsx2/x86/ix86/implement/xmm/arithmetic.h b/pcsx2/x86/ix86/implement/xmm/arithmetic.h new file mode 100644 index 0000000000..328070ce2d --- /dev/null +++ b/pcsx2/x86/ix86/implement/xmm/arithmetic.h @@ -0,0 +1,369 @@ +/* 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 + +////////////////////////////////////////////////////////////////////////////////////////// +// ShiftHelper -- It's out here because C++ child class template semantics are generally +// not cross-compiler friendly. +// +template< u16 Opcode1, u16 OpcodeImm, u8 Modcode > +class _SimdShiftHelper +{ +public: + _SimdShiftHelper() {} + + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( 0x66, Opcode1, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( 0x66, Opcode1, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( 0x66, Opcode1, to, from ); } + + __forceinline void operator()( const xRegisterMMX& to, const xRegisterMMX& from ) const { xOpWrite0F( Opcode1, to, from ); } + __forceinline void operator()( const xRegisterMMX& to, const void* from ) const { xOpWrite0F( Opcode1, to, from ); } + __forceinline void operator()( const xRegisterMMX& to, const ModSibBase& from ) const { xOpWrite0F( Opcode1, to, from ); } + + + __emitinline void operator()( const xRegisterSSE& to, u8 imm8 ) const + { + SimdPrefix( 0x66, OpcodeImm ); + EmitSibMagic( (int)Modcode, to ); + xWrite8( imm8 ); + } + + __emitinline void operator()( const xRegisterMMX& to, u8 imm8 ) const + { + SimdPrefix( 0x00, OpcodeImm ); + EmitSibMagic( (int)Modcode, to ); + xWrite8( imm8 ); + } +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Used for PSRA, which lacks the Q form. +// +template< u16 OpcodeBase1, u8 Modcode > +class SimdImpl_ShiftWithoutQ +{ +public: + const _SimdShiftHelper W; + const _SimdShiftHelper D; + + SimdImpl_ShiftWithoutQ() {} +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Implements PSRL and PSLL +// +template< u16 OpcodeBase1, u8 Modcode > +class SimdImpl_Shift : public SimdImpl_ShiftWithoutQ +{ +public: + const _SimdShiftHelper Q; + + __forceinline void DQ( const xRegisterSSE& to, u8 imm8 ) const { xOpWrite0F( 0x66, 0x73, (int)Modcode+1, to, imm8 ); } + + SimdImpl_Shift() {} +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< u16 OpcodeB, u16 OpcodeQ > +class SimdImpl_AddSub +{ +public: + const SimdImpl_DestRegEither<0x66,OpcodeB+0x20> B; + const SimdImpl_DestRegEither<0x66,OpcodeB+0x21> W; + const SimdImpl_DestRegEither<0x66,OpcodeB+0x22> D; + const SimdImpl_DestRegEither<0x66,OpcodeQ> Q; + + // Add/Sub packed signed byte [8bit] integers from src into dest, and saturate the results. + const SimdImpl_DestRegEither<0x66,OpcodeB+0x10> SB; + + // Add/Sub packed signed word [16bit] integers from src into dest, and saturate the results. + const SimdImpl_DestRegEither<0x66,OpcodeB+0x11> SW; + + // Add/Sub packed unsigned byte [8bit] integers from src into dest, and saturate the results. + const SimdImpl_DestRegEither<0x66,OpcodeB> USB; + + // Add/Sub packed unsigned word [16bit] integers from src into dest, and saturate the results. + const SimdImpl_DestRegEither<0x66,OpcodeB+1> USW; + + SimdImpl_AddSub() {} +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_PMul +{ +public: + const SimdImpl_DestRegEither<0x66,0xd5> LW; + const SimdImpl_DestRegEither<0x66,0xe5> HW; + const SimdImpl_DestRegEither<0x66,0xe4> HUW; + const SimdImpl_DestRegEither<0x66,0xf4> UDQ; + + // [SSE-3] PMULHRSW multiplies vertically each signed 16-bit integer from dest with the + // corresponding signed 16-bit integer of source, producing intermediate signed 32-bit + // integers. Each intermediate 32-bit integer is truncated to the 18 most significant + // bits. Rounding is always performed by adding 1 to the least significant bit of the + // 18-bit intermediate result. The final result is obtained by selecting the 16 bits + // immediately to the right of the most significant bit of each 18-bit intermediate + // result and packed to the destination operand. + // + // Both operands can be MMX or XMM registers. Source can be register or memory. + // + const SimdImpl_DestRegEither<0x66,0x0b38> HRSW; + + // [SSE-4.1] Multiply the packed dword signed integers in dest with src, and store + // the low 32 bits of each product in xmm1. + const SimdImpl_DestRegSSE<0x66,0x4038> LD; + + // [SSE-4.1] Multiply the packed signed dword integers in dest with src. + const SimdImpl_DestRegSSE<0x66,0x2838> DQ; + + SimdImpl_PMul() {} +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// For instructions that have PS/SS form only (most commonly reciprocal Sqrt functions) +// +template< u16 OpcodeSSE > +class SimdImpl_rSqrt +{ +public: + const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; + const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; + SimdImpl_rSqrt() {} +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// SQRT has PS/SS/SD forms, but not the PD form. +// +template< u16 OpcodeSSE > +class SimdImpl_Sqrt : public SimdImpl_rSqrt +{ +public: + SimdImpl_Sqrt() {} + const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_AndNot +{ +public: + SimdImpl_AndNot() {} + const SimdImpl_DestRegSSE<0x00,0x55> PS; + const SimdImpl_DestRegSSE<0x66,0x55> PD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Packed absolute value. [sSSE3 only] +// +class SimdImpl_PAbsolute +{ +public: + SimdImpl_PAbsolute() {} + + // [sSSE-3] Computes the absolute value of bytes in the src, and stores the result + // in dest, as UNSIGNED. + const SimdImpl_DestRegEither<0x66, 0x1c38> B; + + // [sSSE-3] Computes the absolute value of word in the src, and stores the result + // in dest, as UNSIGNED. + const SimdImpl_DestRegEither<0x66, 0x1d38> W; + + // [sSSE-3] Computes the absolute value of doublewords in the src, and stores the + // result in dest, as UNSIGNED. + const SimdImpl_DestRegEither<0x66, 0x1e38> D; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Packed Sign [sSSE3 only] - Negate/zero/preserve packed integers in dest depending on the +// corresponding sign in src. +// +class SimdImpl_PSign +{ +public: + SimdImpl_PSign() {} + + // [sSSE-3] negates each byte element of dest if the signed integer value of the + // corresponding data element in src is less than zero. If the signed integer value + // of a data element in src is positive, the corresponding data element in dest is + // unchanged. If a data element in src is zero, the corresponding data element in + // dest is set to zero. + const SimdImpl_DestRegEither<0x66, 0x0838> B; + + // [sSSE-3] negates each word element of dest if the signed integer value of the + // corresponding data element in src is less than zero. If the signed integer value + // of a data element in src is positive, the corresponding data element in dest is + // unchanged. If a data element in src is zero, the corresponding data element in + // dest is set to zero. + const SimdImpl_DestRegEither<0x66, 0x0938> W; + + // [sSSE-3] negates each doubleword element of dest if the signed integer value + // of the corresponding data element in src is less than zero. If the signed integer + // value of a data element in src is positive, the corresponding data element in dest + // is unchanged. If a data element in src is zero, the corresponding data element in + // dest is set to zero. + const SimdImpl_DestRegEither<0x66, 0x0a38> D; + +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Packed Multiply and Add!! +// +class SimdImpl_PMultAdd +{ +public: + SimdImpl_PMultAdd() {} + + // Multiplies the individual signed words of dest by the corresponding signed words + // of src, producing temporary signed, doubleword results. The adjacent doubleword + // results are then summed and stored in the destination operand. + // + // DEST[31:0] = ( DEST[15:0] * SRC[15:0]) + (DEST[31:16] * SRC[31:16] ); + // DEST[63:32] = ( DEST[47:32] * SRC[47:32]) + (DEST[63:48] * SRC[63:48] ); + // [.. repeat in the case of XMM src/dest operands ..] + // + const SimdImpl_DestRegEither<0x66, 0xf5> WD; + + // [sSSE-3] multiplies vertically each unsigned byte of dest with the corresponding + // signed byte of src, producing intermediate signed 16-bit integers. Each adjacent + // pair of signed words is added and the saturated result is packed to dest. + // For example, the lowest-order bytes (bits 7-0) in src and dest are multiplied + // and the intermediate signed word result is added with the corresponding + // intermediate result from the 2nd lowest-order bytes (bits 15-8) of the operands; + // the sign-saturated result is stored in the lowest word of dest (bits 15-0). + // The same operation is performed on the other pairs of adjacent bytes. + // + // In Coder Speak: + // DEST[15-0] = SaturateToSignedWord( SRC[15-8] * DEST[15-8] + SRC[7-0] * DEST[7-0] ); + // DEST[31-16] = SaturateToSignedWord( SRC[31-24] * DEST[31-24] + SRC[23-16] * DEST[23-16] ); + // [.. repeat for each 16 bits up to 64 (mmx) or 128 (xmm) ..] + // + const SimdImpl_DestRegEither<0x66, 0xf438> UBSW; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Packed Horizontal Add [SSE3 only] +// +class SimdImpl_HorizAdd +{ +public: + SimdImpl_HorizAdd() {} + + // [SSE-3] Horizontal Add of Packed Data. A three step process: + // * Adds the single-precision floating-point values in the first and second dwords of + // dest and stores the result in the first dword of dest. + // * Adds single-precision floating-point values in the third and fourth dword of dest + // stores the result in the second dword of dest. + // * Adds single-precision floating-point values in the first and second dword of *src* + // and stores the result in the third dword of dest. + const SimdImpl_DestRegSSE<0xf2, 0x7c> PS; + + // [SSE-3] Horizontal Add of Packed Data. A two step process: + // * Adds the double-precision floating-point values in the high and low quadwords of + // dest and stores the result in the low quadword of dest. + // * Adds the double-precision floating-point values in the high and low quadwords of + // *src* stores the result in the high quadword of dest. + const SimdImpl_DestRegSSE<0x66, 0x7c> PD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// DotProduct calculation (SSE4.1 only!) +// +class SimdImpl_DotProduct +{ +public: + SimdImpl_DotProduct() {} + + // [SSE-4.1] Conditionally multiplies the packed single precision floating-point + // values in dest with the packed single-precision floats in src depending on a + // mask extracted from the high 4 bits of the immediate byte. If a condition mask + // bit in Imm8[7:4] is zero, the corresponding multiplication is replaced by a value + // of 0.0. The four resulting single-precision values are summed into an inter- + // mediate result. + // + // The intermediate result is conditionally broadcasted to the destination using a + // broadcast mask specified by bits [3:0] of the immediate byte. If a broadcast + // mask bit is 1, the intermediate result is copied to the corresponding dword + // element in dest. If a broadcast mask bit is zero, the corresponding element in + // the destination is set to zero. + // + SimdImpl_DestRegImmSSE<0x66,0x403a> PS; + + // [SSE-4.1] + SimdImpl_DestRegImmSSE<0x66,0x413a> PD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Rounds floating point values (packed or single scalar) by an arbitrary rounding mode. +// (SSE4.1 only!) +class SimdImpl_Round +{ +public: + SimdImpl_Round() {} + + // [SSE-4.1] Rounds the 4 packed single-precision src values and stores them in dest. + // + // Imm8 specifies control fields for the rounding operation: + // Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact) + // Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8. + // Bits 1:0 - Specifies a rounding mode for this instruction only. + // + // Rounding Mode Reference: + // 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate. + // + const SimdImpl_DestRegImmSSE<0x66,0x083a> PS; + + // [SSE-4.1] Rounds the 2 packed double-precision src values and stores them in dest. + // + // Imm8 specifies control fields for the rounding operation: + // Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact) + // Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8. + // Bits 1:0 - Specifies a rounding mode for this instruction only. + // + // Rounding Mode Reference: + // 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate. + // + const SimdImpl_DestRegImmSSE<0x66,0x093a> PD; + + // [SSE-4.1] Rounds the single-precision src value and stores in dest. + // + // Imm8 specifies control fields for the rounding operation: + // Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact) + // Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8. + // Bits 1:0 - Specifies a rounding mode for this instruction only. + // + // Rounding Mode Reference: + // 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate. + // + const SimdImpl_DestRegImmSSE<0x66,0x0a3a> SS; + + // [SSE-4.1] Rounds the double-precision src value and stores in dest. + // + // Imm8 specifies control fields for the rounding operation: + // Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact) + // Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8. + // Bits 1:0 - Specifies a rounding mode for this instruction only. + // + // Rounding Mode Reference: + // 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate. + // + const SimdImpl_DestRegImmSSE<0x66,0x0b3a> SD; +}; diff --git a/pcsx2/x86/ix86/implement/xmm/basehelpers.h b/pcsx2/x86/ix86/implement/xmm/basehelpers.h new file mode 100644 index 0000000000..05ef74d5a7 --- /dev/null +++ b/pcsx2/x86/ix86/implement/xmm/basehelpers.h @@ -0,0 +1,103 @@ +/* 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 + +////////////////////////////////////////////////////////////////////////////////////////// +// MMX / SSE Helper Functions! + +// ------------------------------------------------------------------------ +// For implementing SSE-only logic operations that have xmmreg,xmmreg/rm forms only, +// like ANDPS/ANDPD +// +template< u8 Prefix, u16 Opcode > +class SimdImpl_DestRegSSE +{ +public: + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + + SimdImpl_DestRegSSE() {} //GCWho? +}; + +// ------------------------------------------------------------------------ +// For implementing SSE-only logic operations that have xmmreg,reg/rm,imm forms only +// (PSHUFD / PSHUFHW / etc). +// +template< u8 Prefix, u16 Opcode > +class SimdImpl_DestRegImmSSE +{ +public: + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm ) const { xOpWrite0F( Prefix, Opcode, to, from, imm ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from, u8 imm ) const { xOpWrite0F( Prefix, Opcode, to, from, imm ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, u8 imm ) const { xOpWrite0F( Prefix, Opcode, to, from, imm ); } + + SimdImpl_DestRegImmSSE() {} //GCWho? +}; + +template< u8 Prefix, u16 Opcode > +class SimdImpl_DestRegImmMMX +{ +public: + __forceinline void operator()( const xRegisterMMX& to, const xRegisterMMX& from, u8 imm ) const { xOpWrite0F( Opcode, to, from, imm ); } + __forceinline void operator()( const xRegisterMMX& to, const void* from, u8 imm ) const { xOpWrite0F( Opcode, to, from, imm ); } + __forceinline void operator()( const xRegisterMMX& to, const ModSibBase& from, u8 imm ) const { xOpWrite0F( Opcode, to, from, imm ); } + + SimdImpl_DestRegImmMMX() {} //GCWho? +}; + +// ------------------------------------------------------------------------ +// For implementing MMX/SSE operations that have reg,reg/rm forms only, +// but accept either MM or XMM destinations (most PADD/PSUB and other P srithmetic ops). +// +template< u8 Prefix, u16 Opcode > +class SimdImpl_DestRegEither +{ +public: + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + + __forceinline void operator()( const xRegisterMMX& to, const xRegisterMMX& from ) const { xOpWrite0F( Opcode, to, from ); } + __forceinline void operator()( const xRegisterMMX& to, const void* from ) const { xOpWrite0F( Opcode, to, from ); } + __forceinline void operator()( const xRegisterMMX& to, const ModSibBase& from ) const { xOpWrite0F( Opcode, to, from ); } + + SimdImpl_DestRegEither() {} //GCWho? +}; + +// ------------------------------------------------------------------------ +// For implementing MMX/SSE operations where the destination *must* be a register, but the +// source can be Direct or Indirect (ModRM/SibSB). The SrcOperandType template parameter +// is used to enforce type strictness of the (void*) parameter and ModSib<> parameter, so +// that the programmer must be explicit in specifying desired operand size. +// +// IMPORTANT: This helper assumes the prefix opcode is written *always* -- regardless of +// MMX or XMM register status. +// +template< u8 Prefix, u16 Opcode, typename DestRegType, typename SrcRegType, typename SrcOperandType > +class SimdImpl_DestRegStrict +{ +public: + __forceinline void operator()( const DestRegType& to, const SrcRegType& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const DestRegType& to, const SrcOperandType* from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const DestRegType& to, const ModSibStrict& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + + SimdImpl_DestRegStrict() {} //GCWho? +}; + diff --git a/pcsx2/x86/ix86/implement/xmm/comparisons.h b/pcsx2/x86/ix86/implement/xmm/comparisons.h new file mode 100644 index 0000000000..e74d25b1f9 --- /dev/null +++ b/pcsx2/x86/ix86/implement/xmm/comparisons.h @@ -0,0 +1,130 @@ +/* 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 + + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< u16 OpcodeSSE > +class SimdImpl_MinMax +{ +public: + const SimdImpl_DestRegSSE<0x00,OpcodeSSE> PS; // packed single precision + const SimdImpl_DestRegSSE<0x66,OpcodeSSE> PD; // packed double precision + const SimdImpl_DestRegSSE<0xf3,OpcodeSSE> SS; // scalar single precision + const SimdImpl_DestRegSSE<0xf2,OpcodeSSE> SD; // scalar double precision + + SimdImpl_MinMax() {} //GChow? +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< SSE2_ComparisonType CType > +class SimdImpl_Compare +{ +protected: + template< u8 Prefix > struct Woot + { + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, 0xc2, to, from ); xWrite8( CType ); } + Woot() {} + }; + +public: + const Woot<0x00> PS; + const Woot<0x66> PD; + const Woot<0xf3> SS; + const Woot<0xf2> SD; + SimdImpl_Compare() {} //GCWhat? +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_PCompare +{ +public: + SimdImpl_PCompare() {} + + // Compare packed bytes for equality. + // If a data element in dest is equal to the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x74> EQB; + + // Compare packed words for equality. + // If a data element in dest is equal to the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x75> EQW; + + // Compare packed doublewords [32-bits] for equality. + // If a data element in dest is equal to the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x76> EQD; + + // Compare packed signed bytes for greater than. + // If a data element in dest is greater than the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x64> GTB; + + // Compare packed signed words for greater than. + // If a data element in dest is greater than the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x65> GTW; + + // Compare packed signed doublewords [32-bits] for greater than. + // If a data element in dest is greater than the corresponding date element src, the + // corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s. + const SimdImpl_DestRegEither<0x66,0x66> GTD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< u8 Opcode1, u16 Opcode2 > +class SimdImpl_PMinMax +{ +public: + SimdImpl_PMinMax() {} + + // Compare packed unsigned byte integers in dest to src and store packed min/max + // values in dest. + // Operation can be performed on either MMX or SSE operands. + const SimdImpl_DestRegEither<0x66,Opcode1> UB; + + // Compare packed signed word integers in dest to src and store packed min/max + // values in dest. + // Operation can be performed on either MMX or SSE operands. + const SimdImpl_DestRegEither<0x66,Opcode1+0x10> SW; + + // [SSE-4.1] Compare packed signed byte integers in dest to src and store + // packed min/max values in dest. (SSE operands only) + const SimdImpl_DestRegSSE<0x66,(Opcode2<<8)|0x38> SB; + + // [SSE-4.1] Compare packed signed doubleword integers in dest to src and store + // packed min/max values in dest. (SSE operands only) + const SimdImpl_DestRegSSE<0x66,((Opcode2+1)<<8)|0x38> SD; + + // [SSE-4.1] Compare packed unsigned word integers in dest to src and store + // packed min/max values in dest. (SSE operands only) + const SimdImpl_DestRegSSE<0x66,((Opcode2+2)<<8)|0x38> UW; + + // [SSE-4.1] Compare packed unsigned doubleword integers in dest to src and store + // packed min/max values in dest. (SSE operands only) + const SimdImpl_DestRegSSE<0x66,((Opcode2+3)<<8)|0x38> UD; +}; diff --git a/pcsx2/x86/ix86/implement/xmm/moremovs.h b/pcsx2/x86/ix86/implement/xmm/moremovs.h new file mode 100644 index 0000000000..98cfafc230 --- /dev/null +++ b/pcsx2/x86/ix86/implement/xmm/moremovs.h @@ -0,0 +1,239 @@ +/* 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 + +////////////////////////////////////////////////////////////////////////////////////////// +// Moves to/from high/low portions of an xmm register. +// These instructions cannot be used in reg/reg form. +// +template< u16 Opcode > +class MovhlImplAll +{ +protected: + template< u8 Prefix > + struct Woot + { + Woot() {} + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const void* to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode+1, from, to ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); } + __forceinline void operator()( const ModSibBase& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode+1, from, to ); } + }; + +public: + const Woot<0x00> PS; + const Woot<0x66> PD; + + MovhlImplAll() {} //GCC. +}; + +// ------------------------------------------------------------------------ +// RegtoReg forms of MOVHL/MOVLH -- these are the same opcodes as MOVH/MOVL but +// do something kinda different! Fun! +// +template< u16 Opcode > +class MovhlImpl_RtoR +{ +public: + __forceinline void PS( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Opcode, to, from ); } + __forceinline void PD( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( 0x66, Opcode, to, from ); } + + MovhlImpl_RtoR() {} //GCC. +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Legends in their own right: MOVAPS / MOVAPD / MOVUPS / MOVUPD +// +// All implementations of Unaligned Movs will, when possible, use aligned movs instead. +// This happens when using Mem,Reg or Reg,Mem forms where the address is simple displacement +// which can be checked for alignment at runtime. +// +template< u8 Prefix, bool isAligned > +class SimdImpl_MoveSSE +{ + static const u16 OpcodeA = 0x28; // Aligned [aps] form + static const u16 OpcodeU = 0x10; // unaligned [ups] form + +public: + SimdImpl_MoveSSE() {} //GCC. + + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const + { + if( to != from ) xOpWrite0F( Prefix, OpcodeA, to, from ); + } + + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const + { + xOpWrite0F( Prefix, (isAligned || ((uptr)from & 0x0f) == 0) ? OpcodeA : OpcodeU, to, from ); + } + + __forceinline void operator()( void* to, const xRegisterSSE& from ) const + { + xOpWrite0F( Prefix, (isAligned || ((uptr)to & 0x0f) == 0) ? OpcodeA+1 : OpcodeU+1, from, to ); + } + + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const + { + // ModSib form is aligned if it's displacement-only and the displacement is aligned: + bool isReallyAligned = isAligned || ( ((from.Displacement & 0x0f) == 0) && from.Index.IsEmpty() && from.Base.IsEmpty() ); + xOpWrite0F( Prefix, isReallyAligned ? OpcodeA : OpcodeU, to, from ); + } + + __forceinline void operator()( const ModSibBase& to, const xRegisterSSE& from ) const + { + // ModSib form is aligned if it's displacement-only and the displacement is aligned: + bool isReallyAligned = isAligned || ( (to.Displacement & 0x0f) == 0 && to.Index.IsEmpty() && to.Base.IsEmpty() ); + xOpWrite0F( Prefix, isReallyAligned ? OpcodeA+1 : OpcodeU+1, from, to ); + } +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Implementations for MOVDQA / MOVDQU +// +template< u8 Prefix, bool isAligned > +class SimdImpl_MoveDQ +{ + static const u8 PrefixA = 0x66; // Aligned [aps] form + static const u8 PrefixU = 0xf3; // unaligned [ups] form + + static const u16 Opcode = 0x6f; + static const u16 Opcode_Alt = 0x7f; // alternate ModRM encoding (reverse src/dst) + +public: + SimdImpl_MoveDQ() {} //GCC. + + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const + { + if( to != from ) xOpWrite0F( PrefixA, Opcode, to, from ); + } + + __forceinline void operator()( const xRegisterSSE& to, const void* from ) const + { + xOpWrite0F( (isAligned || ((uptr)from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode, to, from ); + } + + __forceinline void operator()( const void* to, const xRegisterSSE& from ) const + { + xOpWrite0F( (isAligned || ((uptr)from & 0x0f) == 0) ? PrefixA : PrefixU, Opcode_Alt, to, from ); + } + + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const + { + // ModSib form is aligned if it's displacement-only and the displacement is aligned: + bool isReallyAligned = isAligned || ( (from.Displacement & 0x0f) == 0 && from.Index.IsEmpty() && from.Base.IsEmpty() ); + xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode, to, from ); + } + + __forceinline void operator()( const ModSibBase& to, const xRegisterSSE& from ) const + { + // ModSib form is aligned if it's displacement-only and the displacement is aligned: + bool isReallyAligned = isAligned || ( (to.Displacement & 0x0f) == 0 && to.Index.IsEmpty() && to.Base.IsEmpty() ); + xOpWrite0F( isReallyAligned ? PrefixA : PrefixU, Opcode_Alt, from, to ); + } +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< u8 AltPrefix, u16 OpcodeSSE > +class SimdImpl_UcomI +{ +public: + const SimdImpl_DestRegSSE<0x00,OpcodeSSE> SS; + const SimdImpl_DestRegSSE SD; + SimdImpl_UcomI() {} +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Blend - Conditional copying of values in src into dest. +// +class SimdImpl_Blend +{ +public: + // [SSE-4.1] Conditionally copies dword values from src to dest, depending on the + // mask bits in the immediate operand (bits [3:0]). Each mask bit corresponds to a + // dword element in a 128-bit operand. + // + // If a mask bit is 1, then the corresponding dword in the source operand is copied + // to dest, else the dword element in dest is left unchanged. + // + SimdImpl_DestRegImmSSE<0x66,0x0c3a> PS; + + // [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the + // mask bits in the immediate operand (bits [1:0]). Each mask bit corresponds to a + // quadword element in a 128-bit operand. + // + // If a mask bit is 1, then the corresponding dword in the source operand is copied + // to dest, else the dword element in dest is left unchanged. + // + SimdImpl_DestRegImmSSE<0x66,0x0d3a> PD; + + // [SSE-4.1] Conditionally copies dword values from src to dest, depending on the + // mask (bits [3:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds + // to a dword element in the 128-bit operand. + // + // If a mask bit is 1, then the corresponding dword in the source operand is copied + // to dest, else the dword element in dest is left unchanged. + // + SimdImpl_DestRegSSE<0x66,0x1438> VPS; + + // [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the + // mask (bits [1:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds + // to a quadword element in the 128-bit operand. + // + // If a mask bit is 1, then the corresponding dword in the source operand is copied + // to dest, else the dword element in dest is left unchanged. + // + SimdImpl_DestRegSSE<0x66,0x1538> VPD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Packed Move with Sign or Zero extension. +// +template< bool SignExtend > +class SimdImpl_PMove +{ + static const u16 OpcodeBase = SignExtend ? 0x2038 : 0x3038; + +public: + // [SSE-4.1] Zero/Sign-extend the low byte values in src into word integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase,xRegisterSSE,xRegisterSSE,u64> BW; + + // [SSE-4.1] Zero/Sign-extend the low byte values in src into dword integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase+0x100,xRegisterSSE,xRegisterSSE,u32> BD; + + // [SSE-4.1] Zero/Sign-extend the low byte values in src into qword integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase+0x200,xRegisterSSE,xRegisterSSE,u16> BQ; + + // [SSE-4.1] Zero/Sign-extend the low word values in src into dword integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase+0x300,xRegisterSSE,xRegisterSSE,u64> WD; + + // [SSE-4.1] Zero/Sign-extend the low word values in src into qword integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase+0x400,xRegisterSSE,xRegisterSSE,u32> WQ; + + // [SSE-4.1] Zero/Sign-extend the low dword values in src into qword integers + // and store them in dest. + SimdImpl_DestRegStrict<0x66,OpcodeBase+0x500,xRegisterSSE,xRegisterSSE,u64> DQ; +}; + diff --git a/pcsx2/x86/ix86/implement/xmm/shufflepack.h b/pcsx2/x86/ix86/implement/xmm/shufflepack.h new file mode 100644 index 0000000000..f251393056 --- /dev/null +++ b/pcsx2/x86/ix86/implement/xmm/shufflepack.h @@ -0,0 +1,273 @@ +/* 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 + +////////////////////////////////////////////////////////////////////////////////////////// +// +template< u16 OpcodeSSE > +class SimdImpl_Shuffle +{ +protected: + template< u8 Prefix > struct Woot + { + __forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); } + __forceinline void operator()( const xRegisterSSE& to, const void* from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); } + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, u8 cmptype ) const { xOpWrite0F( Prefix, OpcodeSSE, to, from ); xWrite8( cmptype ); } + Woot() {} + }; + +public: + const Woot<0x00> PS; + const Woot<0x66> PD; + + SimdImpl_Shuffle() {} //GCWhat? +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_PShuffle +{ +public: + SimdImpl_PShuffle() {} + + // Copies words from src and inserts them into dest at word locations selected with + // the order operand (8 bit immediate). + const SimdImpl_DestRegImmMMX<0x00,0x70> W; + + // Copies doublewords from src and inserts them into dest at dword locations selected + // with the order operand (8 bit immediate). + const SimdImpl_DestRegImmSSE<0x66,0x70> D; + + // Copies words from the low quadword of src and inserts them into the low quadword + // of dest at word locations selected with the order operand (8 bit immediate). + // The high quadword of src is copied to the high quadword of dest. + const SimdImpl_DestRegImmSSE<0xf2,0x70> LW; + + // Copies words from the high quadword of src and inserts them into the high quadword + // of dest at word locations selected with the order operand (8 bit immediate). + // The low quadword of src is copied to the low quadword of dest. + const SimdImpl_DestRegImmSSE<0xf3,0x70> HW; + + // [sSSE-3] Performs in-place shuffles of bytes in dest according to the shuffle + // control mask in src. If the most significant bit (bit[7]) of each byte of the + // shuffle control mask is set, then constant zero is written in the result byte. + // Each byte in the shuffle control mask forms an index to permute the corresponding + // byte in dest. The value of each index is the least significant 4 bits (128-bit + // operation) or 3 bits (64-bit operation) of the shuffle control byte. + // + // Operands can be MMX or XMM registers. + const SimdImpl_DestRegEither<0x66,0x0038> B; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_PUnpack +{ +public: + SimdImpl_PUnpack() {} + + // Unpack and interleave low-order bytes from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x60> LBW; + // Unpack and interleave low-order words from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x61> LWD; + // Unpack and interleave low-order doublewords from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x62> LDQ; + // Unpack and interleave low-order quadwords from src and dest into dest. + const SimdImpl_DestRegSSE<0x66,0x6c> LQDQ; + + // Unpack and interleave high-order bytes from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x68> HBW; + // Unpack and interleave high-order words from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x69> HWD; + // Unpack and interleave high-order doublewords from src and dest into dest. + const SimdImpl_DestRegEither<0x66,0x6a> HDQ; + // Unpack and interleave high-order quadwords from src and dest into dest. + const SimdImpl_DestRegSSE<0x66,0x6d> HQDQ; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// Pack with Signed or Unsigned Saturation +// +class SimdImpl_Pack +{ +public: + SimdImpl_Pack() {} + + // Converts packed signed word integers from src and dest into packed signed + // byte integers in dest, using signed saturation. + const SimdImpl_DestRegEither<0x66,0x63> SSWB; + + // Converts packed signed dword integers from src and dest into packed signed + // word integers in dest, using signed saturation. + const SimdImpl_DestRegEither<0x66,0x6b> SSDW; + + // Converts packed unsigned word integers from src and dest into packed unsigned + // byte integers in dest, using unsigned saturation. + const SimdImpl_DestRegEither<0x66,0x67> USWB; + + // [SSE-4.1] Converts packed unsigned dword integers from src and dest into packed + // unsigned word integers in dest, using signed saturation. + const SimdImpl_DestRegSSE<0x66,0x2b38> USDW; +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// +class SimdImpl_Unpack +{ +public: + SimdImpl_Unpack() {} + + // Unpacks the high doubleword [single-precision] values from src and dest into + // dest, such that the result of dest looks like this: + // dest[0] <- dest[2] + // dest[1] <- src[2] + // dest[2] <- dest[3] + // dest[3] <- src[3] + // + const SimdImpl_DestRegSSE<0x00,0x15> HPS; + + // Unpacks the high quadword [double-precision] values from src and dest into + // dest, such that the result of dest looks like this: + // dest.lo <- dest.hi + // dest.hi <- src.hi + // + const SimdImpl_DestRegSSE<0x66,0x15> HPD; + + // Unpacks the low doubleword [single-precision] values from src and dest into + // dest, such that the result of dest looks like this: + // dest[3] <- src[1] + // dest[2] <- dest[1] + // dest[1] <- src[0] + // dest[0] <- dest[0] + // + const SimdImpl_DestRegSSE<0x00,0x14> LPS; + + // Unpacks the low quadword [double-precision] values from src and dest into + // dest, effectively moving the low portion of src into the upper portion of dest. + // The result of dest is loaded as such: + // dest.hi <- src.lo + // dest.lo <- dest.lo [remains unchanged!] + // + const SimdImpl_DestRegSSE<0x66,0x14> LPD; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// PINSRW/B/D [all but Word form are SSE4.1 only!] +// +class SimdImpl_PInsert +{ +protected: + template< u16 Opcode > + class ByteDwordForms + { + public: + ByteDwordForms() {} + + __forceinline void operator()( const xRegisterSSE& to, const xRegister32& from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, to, from, imm8 ); + } + + __forceinline void operator()( const xRegisterSSE& to, const void* from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, to, from, imm8 ); + } + + __forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, to, from, imm8 ); + } + }; + +public: + SimdImpl_PInsert() {} + + // Operation can be performed on either MMX or SSE src operands. + __forceinline void W( const xRegisterSSE& to, const xRegister32& from, u8 imm8 ) const { xOpWrite0F( 0x66, 0xc4, to, from, imm8 ); } + __forceinline void W( const xRegisterSSE& to, const void* from, u8 imm8 ) const { xOpWrite0F( 0x66, 0xc4, to, from, imm8 ); } + __forceinline void W( const xRegisterSSE& to, const ModSibBase& from, u8 imm8 ) const { xOpWrite0F( 0x66, 0xc4, to, from, imm8 ); } + + __forceinline void W( const xRegisterMMX& to, const xRegister32& from, u8 imm8 ) const { xOpWrite0F( 0xc4, to, from, imm8 ); } + __forceinline void W( const xRegisterMMX& to, const void* from, u8 imm8 ) const { xOpWrite0F( 0xc4, to, from, imm8 ); } + __forceinline void W( const xRegisterMMX& to, const ModSibBase& from, u8 imm8 ) const { xOpWrite0F( 0xc4, to, from, imm8 ); } + + // [SSE-4.1] + const ByteDwordForms<0x20> B; + + // [SSE-4.1] + const ByteDwordForms<0x22> D; +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// PEXTRW/B/D [all but Word form are SSE4.1 only!] +// +// Note: Word form's indirect memory form is only available in SSE4.1. +// +class SimdImpl_PExtract +{ +protected: + template< u16 Opcode > + class ByteDwordForms + { + public: + ByteDwordForms() {} + + __forceinline void operator()( const xRegister32& to, const xRegisterSSE& from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, to, from, imm8 ); + } + + __forceinline void operator()( void* dest, const xRegisterSSE& from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, from, dest, imm8 ); + } + + __forceinline void operator()( const ModSibBase& dest, const xRegisterSSE& from, u8 imm8 ) const + { + xOpWrite0F( 0x66, (Opcode<<8) | 0x3a, from, dest, imm8 ); + } + }; + +public: + SimdImpl_PExtract() {} + + // Copies the word element specified by imm8 from src to dest. The upper bits + // of dest are zero-extended (cleared). This can be used to extract any single packed + // word value from src into an x86 32 bit register. + // + // [SSE-4.1] Note: Indirect memory forms of this instruction are an SSE-4.1 extension! + // + __forceinline void W( const xRegister32& to, const xRegisterSSE& from, u8 imm8 ) const { xOpWrite0F( 0x66, 0xc5, to, from, imm8 ); } + __forceinline void W( const xRegister32& to, const xRegisterMMX& from, u8 imm8 ) const { xOpWrite0F( 0xc5, to, from, imm8 ); } + + __forceinline void W( void* dest, const xRegisterSSE& from, u8 imm8 ) const { xOpWrite0F( 0x66, 0x153a, from, dest, imm8 ); } + __forceinline void W( const ModSibBase& dest, const xRegisterSSE& from, u8 imm8 ) const { xOpWrite0F( 0x66, 0x153a, from, dest, imm8 ); } + + // [SSE-4.1] Copies the byte element specified by imm8 from src to dest. The upper bits + // of dest are zero-extended (cleared). This can be used to extract any single packed + // byte value from src into an x86 32 bit register. + const ByteDwordForms<0x14> B; + + // [SSE-4.1] Copies the dword element specified by imm8 from src to dest. This can be + // used to extract any single packed dword value from src into an x86 32 bit register. + const ByteDwordForms<0x16> D; +}; + diff --git a/pcsx2/x86/ix86/ix86.cpp b/pcsx2/x86/ix86/ix86.cpp index 11acfce6b5..e04a66ddd3 100644 --- a/pcsx2/x86/ix86/ix86.cpp +++ b/pcsx2/x86/ix86/ix86.cpp @@ -15,27 +15,699 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + /* - * ix86 core v0.6.2 - * Authors: linuzappz - * alexey silinov - * goldfinger - * zerofrog(@gmail.com) - * cottonvibes(@gmail.com) + * ix86 core v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) */ #include "PrecompiledHeader.h" #include "System.h" -#include "ix86.h" +#include "ix86_internal.h" -u8 *x86Ptr[EmitterId_Count]; +// ------------------------------------------------------------------------ +// Notes on Thread Local Storage: +// * TLS is pretty simple, and "just works" from a programmer perspective, with only +// some minor additional computational overhead (see performance notes below). +// +// * MSVC and GCC handle TLS differently internally, but behavior to the programmer is +// generally identical. +// +// Performance Considerations: +// * GCC's implementation involves an extra dereference from normal storage. +// +// * MSVC's implementation involves *two* extra dereferences from normal storage because +// it has to look up the TLS heap pointer from the Windows Thread Storage Area. (in +// generated ASM code, this dereference is denoted by access to the fs:[2ch] address). +// +// * However, in either case, the optimizer usually optimizes it to a register so the +// extra overhead is minimal over a series of instructions. (Note!! the Full Opt- +// imization [/Ox] option effectively disables TLS optimizations in MSVC, causing +// generally significant code bloat). +// -u8 *j8Ptr[32]; -u32 *j32Ptr[32]; -PCSX2_ALIGNED16(u32 p[4]); -PCSX2_ALIGNED16(u32 p2[4]); -PCSX2_ALIGNED16(float f[4]); +__threadlocal u8 *x86Ptr; +__threadlocal u8 *j8Ptr[32]; +__threadlocal u32 *j32Ptr[32]; -XMMSSEType g_xmmtypes[XMMREGS] = { XMMT_INT }; +__threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM] = { XMMT_INT }; + +namespace x86Emitter { + +__forceinline void xWrite8( u8 val ) +{ + xWrite( val ); +} + +__forceinline void xWrite16( u16 val ) +{ + xWrite( val ); +} + +__forceinline void xWrite32( u32 val ) +{ + xWrite( val ); +} + +__forceinline void xWrite64( u64 val ) +{ + xWrite( val ); +} + +const xAddressIndexerBase ptr; +const xAddressIndexer ptr128; +const xAddressIndexer ptr64; +const xAddressIndexer ptr32; +const xAddressIndexer ptr16; +const xAddressIndexer ptr8; + +// ------------------------------------------------------------------------ + +template< typename OperandType > const xRegisterBase xRegisterBase::Empty; +const xAddressReg xAddressReg::Empty; + +const xRegisterSSE + xmm0( 0 ), xmm1( 1 ), + xmm2( 2 ), xmm3( 3 ), + xmm4( 4 ), xmm5( 5 ), + xmm6( 6 ), xmm7( 7 ); + +const xRegisterMMX + mm0( 0 ), mm1( 1 ), + mm2( 2 ), mm3( 3 ), + mm4( 4 ), mm5( 5 ), + mm6( 6 ), mm7( 7 ); + +const xAddressReg + eax( 0 ), ebx( 3 ), + ecx( 1 ), edx( 2 ), + esi( 6 ), edi( 7 ), + ebp( 5 ), esp( 4 ); + +const xRegister16 + ax( 0 ), bx( 3 ), + cx( 1 ), dx( 2 ), + si( 6 ), di( 7 ), + bp( 5 ), sp( 4 ); + +const xRegister8 + al( 0 ), + dl( 2 ), bl( 3 ), + ah( 4 ), ch( 5 ), + dh( 6 ), bh( 7 ); + +const xRegisterCL cl; + +////////////////////////////////////////////////////////////////////////////////////////// + +namespace Internal +{ + ////////////////////////////////////////////////////////////////////////////////////////// + // Performance note: VC++ wants to use byte/word register form for the following + // ModRM/SibSB constructors when we use xWrite, and furthermore unrolls the + // the shift using a series of ADDs for the following results: + // add cl,cl + // add cl,cl + // add cl,cl + // or cl,bl + // add cl,cl + // ... etc. + // + // This is unquestionably bad optimization by Core2 standard, an generates tons of + // register aliases and false dependencies. (although may have been ideal for early- + // brand P4s with a broken barrel shifter?). The workaround is to do our own manual + // x86Ptr access and update using a u32 instead of u8. Thanks to little endianness, + // the same end result is achieved and no false dependencies are generated. The draw- + // back is that it clobbers 3 bytes past the end of the write, which could cause a + // headache for someone who himself is doing some kind of headache-inducing amount of + // recompiler SMC. So we don't do a work-around, and just hope for the compiler to + // stop sucking someday instead. :) + // + // (btw, I know this isn't a critical performance item by any means, but it's + // annoying simply because it *should* be an easy thing to optimize) + + static __forceinline void ModRM( uint mod, uint reg, uint rm ) + { + xWrite8( (mod << 6) | (reg << 3) | rm ); + } + + static __forceinline void SibSB( u32 ss, u32 index, u32 base ) + { + xWrite8( (ss << 6) | (index << 3) | base ); + } + + __forceinline void EmitSibMagic( uint regfield, const void* address ) + { + ModRM( 0, regfield, ModRm_UseDisp32 ); + xWrite( (s32)address ); + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // emitter helpers for xmm instruction with prefixes, most of which are using + // the basic opcode format (items inside braces denote optional or conditional + // emission): + // + // [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB] + // + // Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or + // 0x3a [and other value will result in assertion failue]. + // + __emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const ModSibBase& sib ) + { + SimdPrefix( prefix, opcode ); + EmitSibMagic( instId, sib ); + } + + __emitinline void xOpWrite0F( u8 prefix, u16 opcode, int instId, const void* data ) + { + SimdPrefix( prefix, opcode ); + EmitSibMagic( instId, data ); + } + + __emitinline void xOpWrite0F( u16 opcode, int instId, const ModSibBase& sib ) + { + xOpWrite0F( 0, opcode, instId, sib ); + } + + __emitinline void xOpWrite0F( u16 opcode, int instId, const void* data ) + { + xOpWrite0F( 0, opcode, instId, data ); + } + + + ////////////////////////////////////////////////////////////////////////////////////////// + // returns TRUE if this instruction requires SIB to be encoded, or FALSE if the + // instruction ca be encoded as ModRm alone. + static __forceinline bool NeedsSibMagic( const ModSibBase& info ) + { + // no registers? no sibs! + // (ModSibBase::Reduce always places a register in Index, and optionally leaves + // Base empty if only register is specified) + if( info.Index.IsEmpty() ) return false; + + // A scaled register needs a SIB + if( info.Scale != 0 ) return true; + + // two registers needs a SIB + if( !info.Base.IsEmpty() ) return true; + + return false; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // Conditionally generates Sib encoding information! + // + // regfield - register field to be written to the ModRm. This is either a register specifier + // or an opcode extension. In either case, the instruction determines the value for us. + // + __noinline void EmitSibMagic( uint regfield, const ModSibBase& info ) + { + jASSUME( regfield < 8 ); + + int displacement_size = (info.Displacement == 0) ? 0 : + ( ( info.IsByteSizeDisp() ) ? 1 : 2 ); + + if( !NeedsSibMagic( info ) ) + { + // Use ModRm-only encoding, with the rm field holding an index/base register, if + // one has been specified. If neither register is specified then use Disp32 form, + // which is encoded as "EBP w/o displacement" (which is why EBP must always be + // encoded *with* a displacement of 0, if it would otherwise not have one). + + if( info.Index.IsEmpty() ) + { + EmitSibMagic( regfield, (void*)info.Displacement ); + return; + } + else + { + if( info.Index == ebp && displacement_size == 0 ) + displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! + + ModRM( displacement_size, regfield, info.Index.Id ); + } + } + else + { + // In order to encode "just" index*scale (and no base), we have to encode + // it as a special [index*scale + displacement] form, which is done by + // specifying EBP as the base register and setting the displacement field + // to zero. (same as ModRm w/o SIB form above, basically, except the + // ModRm_UseDisp flag is specified in the SIB instead of the ModRM field). + + if( info.Base.IsEmpty() ) + { + ModRM( 0, regfield, ModRm_UseSib ); + SibSB( info.Scale, info.Index.Id, ModRm_UseDisp32 ); + xWrite( info.Displacement ); + return; + } + else + { + if( info.Base == ebp && displacement_size == 0 ) + displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! + + ModRM( displacement_size, regfield, ModRm_UseSib ); + SibSB( info.Scale, info.Index.Id, info.Base.Id ); + } + } + + if( displacement_size != 0 ) + { + if( displacement_size == 1 ) + xWrite( info.Displacement ); + else + xWrite( info.Displacement ); + } + } +} + +using namespace Internal; + +const MovImplAll xMOV; +const xImpl_Test xTEST; + +const xImpl_G1Logic xAND; +const xImpl_G1Logic xOR; +const xImpl_G1Logic xXOR; + +const xImpl_G1Arith xADD; +const xImpl_G1Arith xSUB; + +const xImpl_Group1 xADC; +const xImpl_Group1 xSBB; +const xImpl_G1Compare xCMP; + +const Group2ImplAll xROL; +const Group2ImplAll xROR; +const Group2ImplAll xRCL; +const Group2ImplAll xRCR; +const Group2ImplAll xSHL; +const Group2ImplAll xSHR; +const Group2ImplAll xSAR; + +const xImpl_Group3 xNOT; +const xImpl_Group3 xNEG; +const xImpl_Group3 xUMUL; +const xImpl_Group3 xUDIV; +const xImpl_iDiv xDIV; +const xImpl_iMul xMUL; + +const xImpl_IncDec xINC; +const xImpl_IncDec xDEC; + +const MovExtendImplAll xMOVZX; +const MovExtendImplAll xMOVSX; + +const DwordShiftImplAll xSHLD; +const DwordShiftImplAll xSHRD; + +const xImpl_Group8 xBT; +const xImpl_Group8 xBTR; +const xImpl_Group8 xBTS; +const xImpl_Group8 xBTC; + +const xImpl_BitScan<0xbc> xBSF; +const xImpl_BitScan<0xbd> xBSR; + +// ------------------------------------------------------------------------ +const CMovImplGeneric xCMOV; + +const CMovImplAll xCMOVA; +const CMovImplAll xCMOVAE; +const CMovImplAll xCMOVB; +const CMovImplAll xCMOVBE; + +const CMovImplAll xCMOVG; +const CMovImplAll xCMOVGE; +const CMovImplAll xCMOVL; +const CMovImplAll xCMOVLE; + +const CMovImplAll xCMOVZ; +const CMovImplAll xCMOVE; +const CMovImplAll xCMOVNZ; +const CMovImplAll xCMOVNE; + +const CMovImplAll xCMOVO; +const CMovImplAll xCMOVNO; +const CMovImplAll xCMOVC; +const CMovImplAll xCMOVNC; + +const CMovImplAll xCMOVS; +const CMovImplAll xCMOVNS; +const CMovImplAll xCMOVPE; +const CMovImplAll xCMOVPO; + +// ------------------------------------------------------------------------ +const SetImplGeneric xSET; + +const SetImplAll xSETA; +const SetImplAll xSETAE; +const SetImplAll xSETB; +const SetImplAll xSETBE; + +const SetImplAll xSETG; +const SetImplAll xSETGE; +const SetImplAll xSETL; +const SetImplAll xSETLE; + +const SetImplAll xSETZ; +const SetImplAll xSETE; +const SetImplAll xSETNZ; +const SetImplAll xSETNE; + +const SetImplAll xSETO; +const SetImplAll xSETNO; +const SetImplAll xSETC; +const SetImplAll xSETNC; + +const SetImplAll xSETS; +const SetImplAll xSETNS; +const SetImplAll xSETPE; +const SetImplAll xSETPO; + + +// ------------------------------------------------------------------------ +// Assigns the current emitter buffer target address. +// This is provided instead of using x86Ptr directly, since we may in the future find +// a need to change the storage class system for the x86Ptr 'under the hood.' +__emitinline void xSetPtr( void* ptr ) +{ + x86Ptr = (u8*)ptr; +} + +// ------------------------------------------------------------------------ +// Retrieves the current emitter buffer target address. +// This is provided instead of using x86Ptr directly, since we may in the future find +// a need to change the storage class system for the x86Ptr 'under the hood.' +__emitinline u8* xGetPtr() +{ + return x86Ptr; +} + +// ------------------------------------------------------------------------ +__emitinline void xAlignPtr( uint bytes ) +{ + // forward align + x86Ptr = (u8*)( ( (uptr)x86Ptr + bytes - 1) & ~(bytes - 1) ); +} + +// ------------------------------------------------------------------------ +__emitinline void xAdvancePtr( uint bytes ) +{ + if( IsDevBuild ) + { + // common debugger courtesy: advance with INT3 as filler. + for( uint i=0; i +static void EmitLeaMagic( xRegister to, const ModSibBase& src, bool preserve_flags ) +{ + typedef xRegister ToReg; + + int displacement_size = (src.Displacement == 0) ? 0 : + ( ( src.IsByteSizeDisp() ) ? 1 : 2 ); + + // See EmitSibMagic for commenting on SIB encoding. + + if( !NeedsSibMagic( src ) ) + { + // LEA Land: means we have either 1-register encoding or just an offset. + // offset is encodable as an immediate MOV, and a register is encodable + // as a register MOV. + + if( src.Index.IsEmpty() ) + { + xMOV( to, src.Displacement ); + return; + } + else if( displacement_size == 0 ) + { + xMOV( to, ToReg( src.Index.Id ) ); + return; + } + else + { + if( !preserve_flags ) + { + // encode as MOV and ADD combo. Make sure to use the immediate on the + // ADD since it can encode as an 8-bit sign-extended value. + + xMOV( to, ToReg( src.Index.Id ) ); + xADD( to, src.Displacement ); + return; + } + else + { + // note: no need to do ebp+0 check since we encode all 0 displacements as + // register assignments above (via MOV) + + xWrite8( 0x8d ); + ModRM( displacement_size, to.Id, src.Index.Id ); + } + } + } + else + { + if( src.Base.IsEmpty() ) + { + if( !preserve_flags && (displacement_size == 0) ) + { + // Encode [Index*Scale] as a combination of Mov and Shl. + // This is more efficient because of the bloated LEA format which requires + // a 32 bit displacement, and the compact nature of the alternative. + // + // (this does not apply to older model P4s with the broken barrel shifter, + // but we currently aren't optimizing for that target anyway). + + xMOV( to, ToReg( src.Index.Id ) ); + xSHL( to, src.Scale ); + return; + } + xWrite8( 0x8d ); + ModRM( 0, to.Id, ModRm_UseSib ); + SibSB( src.Scale, src.Index.Id, ModRm_UseDisp32 ); + xWrite32( src.Displacement ); + return; + } + else + { + if( src.Scale == 0 ) + { + if( !preserve_flags ) + { + if( src.Index == esp ) + { + // ESP is not encodable as an index (ix86 ignores it), thus: + xMOV( to, ToReg( src.Base.Id ) ); // will do the trick! + if( src.Displacement ) xADD( to, src.Displacement ); + return; + } + else if( src.Displacement == 0 ) + { + xMOV( to, ToReg( src.Base.Id ) ); + xADD( to, ToReg( src.Index.Id ) ); + return; + } + } + else if( (src.Index == esp) && (src.Displacement == 0) ) + { + // special case handling of ESP as Index, which is replaceable with + // a single MOV even when preserve_flags is set! :D + + xMOV( to, ToReg( src.Base.Id ) ); + return; + } + } + + if( src.Base == ebp && displacement_size == 0 ) + displacement_size = 1; // forces [ebp] to be encoded as [ebp+0]! + + xWrite8( 0x8d ); + ModRM( displacement_size, to.Id, ModRm_UseSib ); + SibSB( src.Scale, src.Index.Id, src.Base.Id ); + } + } + + if( displacement_size != 0 ) + { + if( displacement_size == 1 ) + xWrite( src.Displacement ); + else + xWrite( src.Displacement ); + } +} + +__emitinline void xLEA( xRegister32 to, const ModSibBase& src, bool preserve_flags ) +{ + EmitLeaMagic( to, src, preserve_flags ); +} + + +__emitinline void xLEA( xRegister16 to, const ModSibBase& src, bool preserve_flags ) +{ + xWrite8( 0x66 ); + EmitLeaMagic( to, src, preserve_flags ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// Push / Pop Emitters +// +// Note: pushad/popad implementations are intentionally left out. The instructions are +// invalid in x64, and are super slow on x32. Use multiple Push/Pop instructions instead. + +__emitinline void xPOP( const ModSibBase& from ) +{ + xWrite8( 0x8f ); + EmitSibMagic( 0, from ); +} + +__emitinline void xPUSH( const ModSibBase& from ) +{ + xWrite8( 0xff ); + EmitSibMagic( 6, from ); +} + +__forceinline void xPOP( xRegister32 from ) { xWrite8( 0x58 | from.Id ); } +__forceinline void xPOP( void* from ) { xPOP( ptr[from] ); } + +__forceinline void xPUSH( u32 imm ) { xWrite8( 0x68 ); xWrite32( imm ); } +__forceinline void xPUSH( xRegister32 from ) { xWrite8( 0x50 | from.Id ); } +__forceinline void xPUSH( void* from ) { xPUSH( ptr[from] ); } + +// pushes the EFLAGS register onto the stack +__forceinline void xPUSHFD() { xWrite8( 0x9C ); } +// pops the EFLAGS register from the stack +__forceinline void xPOPFD() { xWrite8( 0x9D ); } + + +////////////////////////////////////////////////////////////////////////////////////////// +// + +__forceinline void xRET() { xWrite8( 0xC3 ); } +__forceinline void xCBW() { xWrite16( 0x9866 ); } +__forceinline void xCWD() { xWrite8( 0x98 ); } +__forceinline void xCDQ() { xWrite8( 0x99 ); } +__forceinline void xCWDE() { xWrite8( 0x98 ); } + +__forceinline void xLAHF() { xWrite8( 0x9f ); } +__forceinline void xSAHF() { xWrite8( 0x9e ); } + +__forceinline void xSTC() { xWrite8( 0xF9 ); } +__forceinline void xCLC() { xWrite8( 0xF8 ); } + +// NOP 1-byte +__forceinline void xNOP() { xWrite8(0x90); } + +__emitinline void xBSWAP( const xRegister32& to ) +{ + xWrite8( 0x0F ); + xWrite8( 0xC8 | to.Id ); +} + +} diff --git a/pcsx2/x86/ix86/ix86.h b/pcsx2/x86/ix86/ix86.h index 797dc2eaf7..502cfcded9 100644 --- a/pcsx2/x86/ix86/ix86.h +++ b/pcsx2/x86/ix86/ix86.h @@ -15,118 +15,40 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + /* - * ix86 definitions v0.6.2 - * Authors: linuzappz - * alexey silinov - * goldfinger - * shadow < shadow@pcsx2.net > - * cottonvibes(@gmail.com) + * ix86 public header v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) */ +////////////////////////////////////////////////////////////////////////////////////////// +// New C++ Emitter! +// +// To use it just include the x86Emitter namespace into your file/class/function off choice. +// +// This header file is intended for use by public code. It includes the appropriate +// inlines and class definitions for efficient codegen. (code internal to the emitter +// should usually use ix86_internal.h instead, and manually include the +// ix86_inlines.inl file when it is known that inlining of ModSib functions are +// wanted). +// + #pragma once -#define _ix86_included_ // used for sanity checks by headers dependent on this one. #include "ix86_types.h" +#include "ix86_instructions.h" -//------------------------------------------------------------------ -// Helper Macros -//------------------------------------------------------------------ -#define emitterT template - -#define MEMADDR(addr, oplen) (addr) - -#define Rex(w,r,x,b) assert(0) -#define RexR(w, reg) assert( !(w || (reg)>=8) ) -#define RexB(w, base) assert( !(w || (base)>=8) ) -#define RexRB(w, reg, base) assert( !(w || (reg) >= 8 || (base)>=8) ) -#define RexRXB(w, reg, index, base) assert( !(w || (reg) >= 8 || (index) >= 8 || (base) >= 8) ) - -//------------------------------------------------------------------ -// write functions -//------------------------------------------------------------------ -extern u8 *x86Ptr[EmitterId_Count]; -extern u8 *j8Ptr[32]; -extern u32 *j32Ptr[32]; - -emitterT void write8( u8 val ) { - *x86Ptr[I] = (u8)val; - x86Ptr[I]++; -} - -emitterT void write16( u16 val ) { - *(u16*)x86Ptr[I] = (u16)val; - x86Ptr[I] += 2; -} - -emitterT void write24( u32 val ) { - *x86Ptr[I]++ = (u8)(val & 0xff); - *x86Ptr[I]++ = (u8)((val >> 8) & 0xff); - *x86Ptr[I]++ = (u8)((val >> 16) & 0xff); -} - -emitterT void write32( u32 val ) { - *(u32*)x86Ptr[I] = val; - x86Ptr[I] += 4; -} - -emitterT void write64( u64 val ){ - *(u64*)x86Ptr[I] = val; - x86Ptr[I] += 8; -} -//------------------------------------------------------------------ - -//------------------------------------------------------------------ -// jump/align functions -//------------------------------------------------------------------ -emitterT void ex86SetPtr( u8 *ptr ); -emitterT void ex86SetJ8( u8 *j8 ); -emitterT void ex86SetJ8A( u8 *j8 ); -emitterT void ex86SetJ16( u16 *j16 ); -emitterT void ex86SetJ16A( u16 *j16 ); -emitterT void ex86SetJ32( u32 *j32 ); -emitterT void ex86SetJ32A( u32 *j32 ); -emitterT void ex86Align( int bytes ); -emitterT void ex86AlignExecutable( int align ); -//------------------------------------------------------------------ - -//------------------------------------------------------------------ -// General Emitter Helper functions -//------------------------------------------------------------------ -emitterT void WriteRmOffset(x86IntRegType to, int offset); -emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset); -emitterT void ModRM( int mod, int reg, int rm ); -emitterT void SibSB( int ss, int index, int base ); -emitterT void SET8R( int cc, int to ); -emitterT void CMOV32RtoR( int cc, int to, int from ); -emitterT void CMOV32MtoR( int cc, int to, uptr from ); -emitterT u8* J8Rel( int cc, int to ); -emitterT u32* J32Rel( int cc, u32 to ); -emitterT u64 GetCPUTick( void ); -//------------------------------------------------------------------ - -emitterT void eMOV32RtoR( x86IntRegType to, x86IntRegType from ); -emitterT u32* eJMP32( uptr to ); -emitterT u8* eJMP8( u8 to ); -emitterT void eCALL32( u32 to ); -emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, u32 offset); -emitterT void eLEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale); -emitterT void eNOP( void ); -emitterT void eAND32I8toR( x86IntRegType to, u8 from ); -emitterT void eAND32ItoM( uptr to, u32 from ); -emitterT void eLEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1); -emitterT void eAND32I8toM( uptr to, u8 from ); -emitterT void eLEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale); - - - - -#define MMXONLY(code) code -#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask)) - -#include "ix86_macros.h" -#include "ix86.inl" -#include "ix86_3dnow.inl" -#include "ix86_fpu.inl" -#include "ix86_mmx.inl" -#include "ix86_sse.inl" +// Including legacy items for now, but these should be removed eventually, +// once most code is no longer dependent on them. +#include "ix86_legacy_types.h" +#include "ix86_legacy_instructions.h" diff --git a/pcsx2/x86/ix86/ix86.inl b/pcsx2/x86/ix86/ix86.inl deleted file mode 100644 index ae4f5829af..0000000000 --- a/pcsx2/x86/ix86/ix86.inl +++ /dev/null @@ -1,3363 +0,0 @@ -/* 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 -*/ -/* -* ix86 core v0.6.2 -* Authors: linuzappz -* alexey silinov -* goldfinger -* zerofrog(@gmail.com) -* cottonvibes(@gmail.com) -*/ - -#pragma once - -//------------------------------------------------------------------ -// ix86 instructions -//------------------------------------------------------------------ - -#include "PrecompiledHeader.h" -#include "System.h" -#include "ix86.h" - -emitterT void WriteRmOffset(x86IntRegType to, s32 offset) -{ - if( (to&7) == ESP ) { - if( offset == 0 ) { - ModRM( 0, 0, 4 ); - SibSB( 0, ESP, 4 ); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM( 1, 0, 4 ); - SibSB( 0, ESP, 4 ); - write8(offset); - } - else { - ModRM( 2, 0, 4 ); - SibSB( 0, ESP, 4 ); - write32(offset); - } - } - else { - if( offset == 0 ) { - ModRM( 0, 0, to ); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM( 1, 0, to ); - write8(offset); - } - else { - ModRM( 2, 0, to ); - write32(offset); - } - } -} - -emitterT void WriteRmOffsetFrom(x86IntRegType to, x86IntRegType from, int offset) -{ - if ((from&7) == ESP) { - if( offset == 0 ) { - ModRM( 0, to, 0x4 ); - SibSB( 0, 0x4, 0x4 ); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM( 1, to, 0x4 ); - SibSB( 0, 0x4, 0x4 ); - write8(offset); - } - else { - ModRM( 2, to, 0x4 ); - SibSB( 0, 0x4, 0x4 ); - write32(offset); - } - } - else { - if( offset == 0 ) { - ModRM( 0, to, from ); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM( 1, to, from ); - write8(offset); - } - else { - ModRM( 2, to, from ); - write32(offset); - } - } -} - -emitterT void ModRM( s32 mod, s32 reg, s32 rm ) -{ - write8( ( mod << 6 ) | ( (reg & 7) << 3 ) | ( rm & 7 ) ); -} - -emitterT void SibSB( s32 ss, s32 index, s32 base ) -{ - write8( ( ss << 6 ) | ( (index & 7) << 3 ) | ( base & 7 ) ); -} - -emitterT void SET8R( int cc, int to ) -{ - RexB(0, to); - write8( 0x0F ); - write8( cc ); - write8( 0xC0 | ( to ) ); -} - -emitterT u8* J8Rel( int cc, int to ) -{ - write8( cc ); - write8( to ); - return (u8*)(x86Ptr[I] - 1); -} - -emitterT u16* J16Rel( int cc, u32 to ) -{ - write16( 0x0F66 ); - write8( cc ); - write16( to ); - return (u16*)( x86Ptr[I] - 2 ); -} - -emitterT u32* J32Rel( int cc, u32 to ) -{ - write8( 0x0F ); - write8( cc ); - write32( to ); - return (u32*)( x86Ptr[I] - 4 ); -} - -emitterT void CMOV32RtoR( int cc, int to, int from ) -{ - RexRB(0, to, from); - write8( 0x0F ); - write8( cc ); - ModRM( 3, to, from ); -} - -emitterT void CMOV32MtoR( int cc, int to, uptr from ) -{ - RexR(0, to); - write8( 0x0F ); - write8( cc ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -//////////////////////////////////////////////////// -emitterT void ex86SetPtr( u8* ptr ) -{ - x86Ptr[I] = ptr; -} - -//////////////////////////////////////////////////// -emitterT void ex86SetJ8( u8* j8 ) -{ - u32 jump = ( x86Ptr[I] - j8 ) - 1; - - if ( jump > 0x7f ) { - Console::Error( "j8 greater than 0x7f!!" ); - assert(0); - } - *j8 = (u8)jump; -} - -emitterT void ex86SetJ8A( u8* j8 ) -{ - u32 jump = ( x86Ptr[I] - j8 ) - 1; - - if ( jump > 0x7f ) { - Console::Error( "j8 greater than 0x7f!!" ); - assert(0); - } - - if( ((uptr)x86Ptr[I]&0xf) > 4 ) { - - uptr newjump = jump + 16-((uptr)x86Ptr[I]&0xf); - - if( newjump <= 0x7f ) { - jump = newjump; - while((uptr)x86Ptr[I]&0xf) *x86Ptr[I]++ = 0x90; - } - } - *j8 = (u8)jump; -} - -emitterT void ex86SetJ16( u16 *j16 ) -{ - // doesn't work - u32 jump = ( x86Ptr[I] - (u8*)j16 ) - 2; - - if ( jump > 0x7fff ) { - Console::Error( "j16 greater than 0x7fff!!" ); - assert(0); - } - *j16 = (u16)jump; -} - -emitterT void ex86SetJ16A( u16 *j16 ) -{ - if( ((uptr)x86Ptr[I]&0xf) > 4 ) { - while((uptr)x86Ptr[I]&0xf) *x86Ptr[I]++ = 0x90; - } - ex86SetJ16(j16); -} - -//////////////////////////////////////////////////// -emitterT void ex86SetJ32( u32* j32 ) -{ - *j32 = ( x86Ptr[I] - (u8*)j32 ) - 4; -} - -emitterT void ex86SetJ32A( u32* j32 ) -{ - while((uptr)x86Ptr[I]&0xf) *x86Ptr[I]++ = 0x90; - ex86SetJ32(j32); -} - -//////////////////////////////////////////////////// -emitterT void ex86Align( int bytes ) -{ - // forward align - x86Ptr[I] = (u8*)( ( (uptr)x86Ptr[I] + bytes - 1) & ~( bytes - 1 ) ); -} - -//////////////////////////////////////////////////// -// Generates executable code to align to the given alignment (could be useful for the second leg -// of if/else conditionals, which usually fall through a jump target label). -emitterT void ex86AlignExecutable( int align ) -{ - uptr newx86 = ( (uptr)x86Ptr[I] + align - 1) & ~( align - 1 ); - uptr bytes = ( newx86 - (uptr)x86Ptr[I] ); - - switch( bytes ) - { - case 0: break; - - case 1: eNOP(); break; - case 2: eMOV32RtoR( ESI, ESI ); break; - case 3: write8(0x08D); write8(0x024); write8(0x024); break; - case 5: eNOP(); // falls through to 4... - case 4: write8(0x08D); write8(0x064); write8(0x024); write8(0); break; - case 6: write8(0x08D); write8(0x0B6); write32(0); break; - case 8: eNOP(); // falls through to 7... - case 7: write8(0x08D); write8(0x034); write8(0x035); write32(0); break; - - default: - { - // for larger alignments, just use a JMP... - u8* aligned_target = eJMP8(0); - x86Ptr[I] = (u8*)newx86; - ex86SetJ8( aligned_target ); - } - } - - jASSUME( x86Ptr[0] == (u8*)newx86 ); -} - -/********************/ -/* IX86 intructions */ -/********************/ - -emitterT void eSTC( void ) -{ - write8( 0xF9 ); -} - -emitterT void eCLC( void ) -{ - write8( 0xF8 ); -} - -// NOP 1-byte -emitterT void eNOP( void ) -{ - write8(0x90); -} - - -//////////////////////////////////// -// mov instructions / -//////////////////////////////////// - -/* mov r64 to r64 */ -emitterT void eMOV64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x89 ); - ModRM( 3, from, to ); -} - -/* mov r64 to m64 */ -emitterT void eMOV64RtoM( uptr to, x86IntRegType from ) -{ - RexR(1, from); - write8( 0x89 ); - ModRM( 0, from, DISP32 ); - write32( (u32)MEMADDR(to, 4) ); -} - -/* mov m64 to r64 */ -emitterT void eMOV64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x8B ); - ModRM( 0, to, DISP32 ); - write32( (u32)MEMADDR(from, 4) ); -} - -/* mov imm32 to m64 */ -emitterT void eMOV64I32toM(uptr to, u32 from ) -{ - Rex(1, 0, 0, 0); - write8( 0xC7 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -// mov imm64 to r64 -emitterT void eMOV64ItoR( x86IntRegType to, u64 from) -{ - RexB(1, to); - write8( 0xB8 | (to & 0x7) ); - write64( from ); -} - -/* mov imm32 to r64 */ -emitterT void eMOV64I32toR( x86IntRegType to, s32 from ) -{ - RexB(1, to); - write8( 0xC7 ); - ModRM( 0, 0, to ); - write32( from ); -} - -// mov imm64 to [r64+off] -emitterT void eMOV64ItoRmOffset( x86IntRegType to, u32 from, int offset) -{ - RexB(1,to); - write8( 0xC7 ); - WriteRmOffset(to, offset); - write32(from); -} - -// mov [r64+offset] to r64 -emitterT void eMOV64RmOffsettoR( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(1, to, from); - write8( 0x8B ); - WriteRmOffsetFrom(to, from, offset); -} - -/* mov [r64][r64*scale] to r64 */ -emitterT void eMOV64RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { - RexRXB(1, to, from2, from); - write8( 0x8B ); - ModRM( 0, to, 0x4 ); - SibSB(scale, from2, from ); -} - -/* mov r64 to [r64+offset] */ -emitterT void eMOV64RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(1,from,to); - write8( 0x89 ); - WriteRmOffsetFrom(from, to, offset); -} - -/* mov r64 to [r64][r64*scale] */ -emitterT void eMOV64RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { - RexRXB(1, to, from2, from); - write8( 0x89 ); - ModRM( 0, to, 0x4 ); - SibSB(scale, from2, from ); -} - - -/* mov r32 to r32 */ -emitterT void eMOV32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write8( 0x89 ); - ModRM( 3, from, to ); -} - -/* mov r32 to m32 */ -emitterT void eMOV32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0, from); - if (from == EAX) { - write8(0xA3); - } else { - write8( 0x89 ); - ModRM( 0, from, DISP32 ); - } - write32( MEMADDR(to, 4) ); -} - -/* mov m32 to r32 */ -emitterT void eMOV32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0, to); - if (to == EAX) { - write8(0xA1); - } else { - write8( 0x8B ); - ModRM( 0, to, DISP32 ); - } - write32( MEMADDR(from, 4) ); -} - -/* mov [r32] to r32 */ -emitterT void eMOV32RmtoR( x86IntRegType to, x86IntRegType from ) { - RexRB(0, to, from); - write8(0x8B); - WriteRmOffsetFrom(to, from, 0); -} - -emitterT void eMOV32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) { - RexRB(0, to, from); - write8( 0x8B ); - WriteRmOffsetFrom(to, from, offset); -} - -/* mov [r32+r32*scale] to r32 */ -emitterT void eMOV32RmStoR( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { - RexRXB(0,to,from2,from); - write8( 0x8B ); - ModRM( 0, to, 0x4 ); - SibSB(scale, from2, from ); -} - -// mov r32 to [r32<( 0x8B ); - ModRM( 0, to, 0x4 ); - ModRM( scale, from1, 5); - write32(from2); -} - -/* mov r32 to [r32] */ -emitterT void eMOV32RtoRm( x86IntRegType to, x86IntRegType from ) { - RexRB(0, from, to); - if ((to&7) == ESP) { - write8( 0x89 ); - ModRM( 0, from, 0x4 ); - SibSB( 0, 0x4, 0x4 ); - } - else { - write8( 0x89 ); - ModRM( 0, from, to ); - } -} - -/* mov r32 to [r32][r32*scale] */ -emitterT void eMOV32RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { - RexRXB(0, to, from2, from); - write8( 0x89 ); - ModRM( 0, to, 0x4 ); - SibSB(scale, from2, from ); -} - -/* mov imm32 to r32 */ -emitterT void eMOV32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0, to); - write8( 0xB8 | (to & 0x7) ); - write32( from ); -} - -/* mov imm32 to m32 */ -emitterT void eMOV32ItoM(uptr to, u32 from ) -{ - write8( 0xC7 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -// mov imm32 to [r32+off] -emitterT void eMOV32ItoRmOffset( x86IntRegType to, u32 from, int offset) -{ - RexB(0,to); - write8( 0xC7 ); - WriteRmOffset(to, offset); - write32(from); -} - -// mov r32 to [r32+off] -emitterT void eMOV32RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) -{ - RexRB(0,from,to); - write8( 0x89 ); - WriteRmOffsetFrom(from, to, offset); -} - -/* mov r16 to m16 */ -emitterT void eMOV16RtoM(uptr to, x86IntRegType from ) -{ - write8( 0x66 ); - RexR(0,from); - write8( 0x89 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* mov m16 to r16 */ -emitterT void eMOV16MtoR( x86IntRegType to, uptr from ) -{ - write8( 0x66 ); - RexR(0,to); - write8( 0x8B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void eMOV16RmtoR( x86IntRegType to, x86IntRegType from) -{ - write8( 0x66 ); - RexRB(0,to,from); - write8( 0x8B ); - WriteRmOffsetFrom(to, from, 0); -} - -emitterT void eMOV16RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - write8( 0x66 ); - RexRB(0,to,from); - write8( 0x8B ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eMOV16RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) -{ - write8(0x66); - RexRXB(0,to,from1,0); - write8( 0x8B ); - ModRM( 0, to, SIB ); - SibSB( scale, from1, SIBDISP); - write32(from2); -} - -emitterT void eMOV16RtoRm(x86IntRegType to, x86IntRegType from) -{ - write8( 0x66 ); - RexRB(0,from,to); - write8( 0x89 ); - ModRM( 0, from, to ); -} - -/* mov imm16 to m16 */ -emitterT void eMOV16ItoM( uptr to, u16 from ) -{ - write8( 0x66 ); - write8( 0xC7 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( from ); -} - -/* mov r16 to [r32][r32*scale] */ -emitterT void eMOV16RtoRmS( x86IntRegType to, x86IntRegType from, x86IntRegType from2, int scale) { - write8( 0x66 ); - RexRXB(0,to,from2,from); - write8( 0x89 ); - ModRM( 0, to, 0x4 ); - SibSB(scale, from2, from ); -} - -emitterT void eMOV16ItoR( x86IntRegType to, u16 from ) -{ - RexB(0, to); - write16( 0xB866 | ((to & 0x7)<<8) ); - write16( from ); -} - -// mov imm16 to [r16+off] -emitterT void eMOV16ItoRmOffset( x86IntRegType to, u16 from, u32 offset) -{ - write8(0x66); - RexB(0,to); - write8( 0xC7 ); - WriteRmOffset(to, offset); - write16(from); -} - -// mov r16 to [r16+off] -emitterT void eMOV16RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) -{ - write8(0x66); - RexRB(0,from,to); - write8( 0x89 ); - WriteRmOffsetFrom(from, to, offset); -} - -/* mov r8 to m8 */ -emitterT void eMOV8RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x88 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* mov m8 to r8 */ -emitterT void eMOV8MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x8A ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* mov [r32] to r8 */ -emitterT void eMOV8RmtoR(x86IntRegType to, x86IntRegType from) -{ - RexRB(0,to,from); - write8( 0x8A ); - WriteRmOffsetFrom(to, from, 0); -} - -emitterT void eMOV8RmtoROffset(x86IntRegType to, x86IntRegType from, int offset) -{ - RexRB(0,to,from); - write8( 0x8A ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eMOV8RmSOffsettoR( x86IntRegType to, x86IntRegType from1, u32 from2, int scale ) -{ - RexRXB(0,to,from1,0); - write8( 0x8A ); - ModRM( 0, to, SIB ); - SibSB( scale, from1, SIBDISP); - write32(from2); -} - -emitterT void eMOV8RtoRm(x86IntRegType to, x86IntRegType from) -{ - RexRB(0,from,to); - write8( 0x88 ); - WriteRmOffsetFrom(from, to, 0); -} - -/* mov imm8 to m8 */ -emitterT void eMOV8ItoM( uptr to, u8 from ) -{ - write8( 0xC6 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -// mov imm8 to r8 -emitterT void eMOV8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0, to); - write8( 0xB0 | (to & 0x7) ); - write8( from ); -} - -// mov imm8 to [r8+off] -emitterT void eMOV8ItoRmOffset( x86IntRegType to, u8 from, int offset) -{ - assert( to != ESP ); - RexB(0,to); - write8( 0xC6 ); - WriteRmOffset(to,offset); - write8(from); -} - -// mov r8 to [r8+off] -emitterT void eMOV8RtoRmOffset( x86IntRegType to, x86IntRegType from, int offset) -{ - assert( to != ESP ); - RexRB(0,from,to); - write8( 0x88 ); - WriteRmOffsetFrom(from,to,offset); -} - -/* movsx r8 to r32 */ -emitterT void eMOVSX32R8toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xBE0F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVSX32Rm8toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xBE0F ); - ModRM( 0, to, from ); -} - -emitterT void eMOVSX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(0,to,from); - write16( 0xBE0F ); - WriteRmOffsetFrom(to,from,offset); -} - -/* movsx m8 to r32 */ -emitterT void eMOVSX32M8toR( x86IntRegType to, u32 from ) -{ - RexR(0,to); - write16( 0xBE0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* movsx r16 to r32 */ -emitterT void eMOVSX32R16toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xBF0F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVSX32Rm16toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xBF0F ); - ModRM( 0, to, from ); -} - -emitterT void eMOVSX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(0,to,from); - write16( 0xBF0F ); - WriteRmOffsetFrom(to,from,offset); -} - -/* movsx m16 to r32 */ -emitterT void eMOVSX32M16toR( x86IntRegType to, u32 from ) -{ - RexR(0,to); - write16( 0xBF0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* movzx r8 to r32 */ -emitterT void eMOVZX32R8toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xB60F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVZX32Rm8toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xB60F ); - ModRM( 0, to, from ); -} - -emitterT void eMOVZX32Rm8toROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(0,to,from); - write16( 0xB60F ); - WriteRmOffsetFrom(to,from,offset); -} - -/* movzx m8 to r32 */ -emitterT void eMOVZX32M8toR( x86IntRegType to, u32 from ) -{ - RexR(0,to); - write16( 0xB60F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* movzx r16 to r32 */ -emitterT void eMOVZX32R16toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xB70F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVZX32Rm16toR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xB70F ); - ModRM( 0, to, from ); -} - -emitterT void eMOVZX32Rm16toROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(0,to,from); - write16( 0xB70F ); - WriteRmOffsetFrom(to,from,offset); -} - -/* movzx m16 to r32 */ -emitterT void eMOVZX32M16toR( x86IntRegType to, u32 from ) -{ - RexR(0,to); - write16( 0xB70F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* cmovbe r32 to r32 */ -emitterT void eCMOVBE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x46, to, from ); -} - -/* cmovbe m32 to r32*/ -emitterT void eCMOVBE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x46, to, from ); -} - -/* cmovb r32 to r32 */ -emitterT void eCMOVB32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x42, to, from ); -} - -/* cmovb m32 to r32*/ -emitterT void eCMOVB32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x42, to, from ); -} - -/* cmovae r32 to r32 */ -emitterT void eCMOVAE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x43, to, from ); -} - -/* cmovae m32 to r32*/ -emitterT void eCMOVAE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x43, to, from ); -} - -/* cmova r32 to r32 */ -emitterT void eCMOVA32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x47, to, from ); -} - -/* cmova m32 to r32*/ -emitterT void eCMOVA32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x47, to, from ); -} - -/* cmovo r32 to r32 */ -emitterT void eCMOVO32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x40, to, from ); -} - -/* cmovo m32 to r32 */ -emitterT void eCMOVO32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x40, to, from ); -} - -/* cmovp r32 to r32 */ -emitterT void eCMOVP32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4A, to, from ); -} - -/* cmovp m32 to r32 */ -emitterT void eCMOVP32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4A, to, from ); -} - -/* cmovs r32 to r32 */ -emitterT void eCMOVS32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x48, to, from ); -} - -/* cmovs m32 to r32 */ -emitterT void eCMOVS32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x48, to, from ); -} - -/* cmovno r32 to r32 */ -emitterT void eCMOVNO32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x41, to, from ); -} - -/* cmovno m32 to r32 */ -emitterT void eCMOVNO32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x41, to, from ); -} - -/* cmovnp r32 to r32 */ -emitterT void eCMOVNP32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4B, to, from ); -} - -/* cmovnp m32 to r32 */ -emitterT void eCMOVNP32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4B, to, from ); -} - -/* cmovns r32 to r32 */ -emitterT void eCMOVNS32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x49, to, from ); -} - -/* cmovns m32 to r32 */ -emitterT void eCMOVNS32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x49, to, from ); -} - -/* cmovne r32 to r32 */ -emitterT void eCMOVNE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x45, to, from ); -} - -/* cmovne m32 to r32*/ -emitterT void eCMOVNE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x45, to, from ); -} - -/* cmove r32 to r32*/ -emitterT void eCMOVE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x44, to, from ); -} - -/* cmove m32 to r32*/ -emitterT void eCMOVE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x44, to, from ); -} - -/* cmovg r32 to r32*/ -emitterT void eCMOVG32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4F, to, from ); -} - -/* cmovg m32 to r32*/ -emitterT void eCMOVG32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4F, to, from ); -} - -/* cmovge r32 to r32*/ -emitterT void eCMOVGE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4D, to, from ); -} - -/* cmovge m32 to r32*/ -emitterT void eCMOVGE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4D, to, from ); -} - -/* cmovl r32 to r32*/ -emitterT void eCMOVL32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4C, to, from ); -} - -/* cmovl m32 to r32*/ -emitterT void eCMOVL32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4C, to, from ); -} - -/* cmovle r32 to r32*/ -emitterT void eCMOVLE32RtoR( x86IntRegType to, x86IntRegType from ) -{ - CMOV32RtoR( 0x4E, to, from ); -} - -/* cmovle m32 to r32*/ -emitterT void eCMOVLE32MtoR( x86IntRegType to, uptr from ) -{ - CMOV32MtoR( 0x4E, to, from ); -} - -//////////////////////////////////// -// arithmetic instructions / -//////////////////////////////////// - -/* add imm32 to r64 */ -emitterT void eADD64ItoR( x86IntRegType to, u32 from ) -{ - Rex(1, 0, 0, to >> 3); - if ( to == EAX) { - write8( 0x05 ); - } - else { - write8( 0x81 ); - ModRM( 3, 0, to ); - } - write32( from ); -} - -/* add m64 to r64 */ -emitterT void eADD64MtoR( x86IntRegType to, uptr from ) -{ - Rex(1, to >> 3, 0, 0); - write8( 0x03 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* add r64 to r64 */ -emitterT void eADD64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x01 ); - ModRM( 3, from, to ); -} - -/* add imm32 to EAX */ -emitterT void eADD32ItoEAX( s32 imm ) -{ - write8( 0x05 ); - write32( imm ); -} - -/* add imm32 to r32 */ -emitterT void eADD32ItoR( x86IntRegType to, s32 imm ) -{ - RexB(0, to); - if (imm <= 127 && imm >= -128) - { - write8( 0x83 ); - ModRM( 3, 0, to ); - write8( (s8)imm ); - } - else - { - if ( to == EAX ) { - eADD32ItoEAX(imm); - } - else { - write8( 0x81 ); - ModRM( 3, 0, to ); - write32( imm ); - } - } -} - -/* add imm32 to m32 */ -emitterT void eADD32ItoM( uptr to, s32 imm ) -{ - if(imm <= 127 && imm >= -128) - { - write8( 0x83 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 8) ); - write8( imm ); - } - else - { - write8( 0x81 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( imm ); - } -} - -// add imm32 to [r32+off] -emitterT void eADD32ItoRmOffset( x86IntRegType to, s32 imm, s32 offset) -{ - RexB(0,to); - if(imm <= 127 && imm >= -128) - { - write8( 0x83 ); - WriteRmOffset(to,offset); - write8(imm); - } - else - { - write8( 0x81 ); - WriteRmOffset(to,offset); - write32(imm); - } -} - -/* add r32 to r32 */ -emitterT void eADD32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write8( 0x01 ); - ModRM( 3, from, to ); -} - -/* add r32 to m32 */ -emitterT void eADD32RtoM(uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x01 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* add m32 to r32 */ -emitterT void eADD32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x03 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// add r16 to r16 -emitterT void eADD16RtoR( x86IntRegType to , x86IntRegType from ) -{ - write8(0x66); - RexRB(0,to,from); - write8( 0x03 ); - ModRM( 3, to, from ); -} - -/* add imm16 to r16 */ -emitterT void eADD16ItoR( x86IntRegType to, s16 imm ) -{ - write8( 0x66 ); - RexB(0,to); - - if ( to == EAX) - { - write8( 0x05 ); - write16( imm ); - } - else if(imm <= 127 && imm >= -128) - { - write8( 0x83 ); - ModRM( 3, 0, to ); - write8((u8)imm ); - } - else - { - write8( 0x81 ); - ModRM( 3, 0, to ); - write16( imm ); - } -} - -/* add imm16 to m16 */ -emitterT void eADD16ItoM( uptr to, s16 imm ) -{ - write8( 0x66 ); - if(imm <= 127 && imm >= -128) - { - write8( 0x83 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 6) ); - write8((u8)imm ); - } - else - { - write8( 0x81 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( imm ); - } -} - -/* add r16 to m16 */ -emitterT void eADD16RtoM(uptr to, x86IntRegType from ) -{ - write8( 0x66 ); - RexR(0,from); - write8( 0x01 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* add m16 to r16 */ -emitterT void eADD16MtoR( x86IntRegType to, uptr from ) -{ - write8( 0x66 ); - RexR(0,to); - write8( 0x03 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// add m8 to r8 -emitterT void eADD8MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x02 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* adc imm32 to r32 */ -emitterT void eADC32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x15 ); - } - else { - write8( 0x81 ); - ModRM( 3, 2, to ); - } - write32( from ); -} - -/* adc imm32 to m32 */ -emitterT void eADC32ItoM( uptr to, u32 from ) -{ - write8( 0x81 ); - ModRM( 0, 2, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* adc r32 to r32 */ -emitterT void eADC32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x11 ); - ModRM( 3, from, to ); -} - -/* adc m32 to r32 */ -emitterT void eADC32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x13 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// adc r32 to m32 -emitterT void eADC32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x11 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* inc r32 */ -emitterT void eINC32R( x86IntRegType to ) -{ - write8( 0x40 + to ); -} - -/* inc m32 */ -emitterT void eINC32M( u32 to ) -{ - write8( 0xFF ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* inc r16 */ -emitterT void eINC16R( x86IntRegType to ) -{ - write8( 0x66 ); - write8( 0x40 + to ); -} - -/* inc m16 */ -emitterT void eINC16M( u32 to ) -{ - write8( 0x66 ); - write8( 0xFF ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 4) ); -} - - -/* sub imm32 to r64 */ -emitterT void eSUB64ItoR( x86IntRegType to, u32 from ) -{ - RexB(1, to); - if ( to == EAX ) { - write8( 0x2D ); - } - else { - write8( 0x81 ); - ModRM( 3, 5, to ); - } - write32( from ); -} - -/* sub r64 to r64 */ -emitterT void eSUB64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x29 ); - ModRM( 3, from, to ); -} - -/* sub m64 to r64 */ -emitterT void eSUB64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x2B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* sub imm32 to r32 */ -emitterT void eSUB32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x2D ); - } - else { - write8( 0x81 ); - ModRM( 3, 5, to ); - } - write32( from ); -} - -/* sub imm32 to m32 */ -emitterT void eSUB32ItoM( uptr to, u32 from ) -{ - write8( 0x81 ); - ModRM( 0, 5, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* sub r32 to r32 */ -emitterT void eSUB32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write8( 0x29 ); - ModRM( 3, from, to ); -} - -/* sub m32 to r32 */ -emitterT void eSUB32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x2B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// sub r32 to m32 -emitterT void eSUB32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x29 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -// sub r16 to r16 -emitterT void eSUB16RtoR( x86IntRegType to, u16 from ) -{ - write8(0x66); - RexRB(0,to,from); - write8( 0x2b ); - ModRM( 3, to, from ); -} - -/* sub imm16 to r16 */ -emitterT void eSUB16ItoR( x86IntRegType to, u16 from ) { - write8( 0x66 ); - RexB(0,to); - if ( to == EAX ) { - write8( 0x2D ); - } - else { - write8( 0x81 ); - ModRM( 3, 5, to ); - } - write16( from ); -} - -/* sub imm16 to m16 */ -emitterT void eSUB16ItoM( uptr to, u16 from ) { - write8( 0x66 ); - write8( 0x81 ); - ModRM( 0, 5, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( from ); -} - -/* sub m16 to r16 */ -emitterT void eSUB16MtoR( x86IntRegType to, uptr from ) { - write8( 0x66 ); - RexR(0,to); - write8( 0x2B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* sbb r64 to r64 */ -emitterT void eSBB64RtoR( x86IntRegType to, x86IntRegType from ) { - RexRB(1, from,to); - write8( 0x19 ); - ModRM( 3, from, to ); -} - -/* sbb imm32 to r32 */ -emitterT void eSBB32ItoR( x86IntRegType to, u32 from ) { - RexB(0,to); - if ( to == EAX ) { - write8( 0x1D ); - } - else { - write8( 0x81 ); - ModRM( 3, 3, to ); - } - write32( from ); -} - -/* sbb imm32 to m32 */ -emitterT void eSBB32ItoM( uptr to, u32 from ) { - write8( 0x81 ); - ModRM( 0, 3, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* sbb r32 to r32 */ -emitterT void eSBB32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x19 ); - ModRM( 3, from, to ); -} - -/* sbb m32 to r32 */ -emitterT void eSBB32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x1B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* sbb r32 to m32 */ -emitterT void eSBB32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x19 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* dec r32 */ -emitterT void eDEC32R( x86IntRegType to ) -{ - write8( 0x48 + to ); -} - -/* dec m32 */ -emitterT void eDEC32M( u32 to ) -{ - write8( 0xFF ); - ModRM( 0, 1, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* dec r16 */ -emitterT void eDEC16R( x86IntRegType to ) -{ - write8( 0x66 ); - write8( 0x48 + to ); -} - -/* dec m16 */ -emitterT void eDEC16M( u32 to ) -{ - write8( 0x66 ); - write8( 0xFF ); - ModRM( 0, 1, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* mul eax by r32 to edx:eax */ -emitterT void eMUL32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 4, from ); -} - -/* imul eax by r32 to edx:eax */ -emitterT void eIMUL32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 5, from ); -} - -/* mul eax by m32 to edx:eax */ -emitterT void eMUL32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 4, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* imul eax by m32 to edx:eax */ -emitterT void eIMUL32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 5, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* imul r32 by r32 to r32 */ -emitterT void eIMUL32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write16( 0xAF0F ); - ModRM( 3, to, from ); -} - -/* div eax by r32 to edx:eax */ -emitterT void eDIV32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 6, from ); -} - -/* idiv eax by r32 to edx:eax */ -emitterT void eIDIV32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 7, from ); -} - -/* div eax by m32 to edx:eax */ -emitterT void eDIV32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 6, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* idiv eax by m32 to edx:eax */ -emitterT void eIDIV32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 7, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -//////////////////////////////////// -// shifting instructions / -//////////////////////////////////// - -/* shl imm8 to r64 */ -emitterT void eSHL64ItoR( x86IntRegType to, u8 from ) -{ - RexB(1, to); - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 3, 4, to ); - return; - } - write8( 0xC1 ); - ModRM( 3, 4, to ); - write8( from ); -} - -/* shl cl to r64 */ -emitterT void eSHL64CLtoR( x86IntRegType to ) -{ - RexB(1, to); - write8( 0xD3 ); - ModRM( 3, 4, to ); -} - -/* shr imm8 to r64 */ -emitterT void eSHR64ItoR( x86IntRegType to, u8 from ) -{ - RexB(1,to); - if ( from == 1 ) { - write8( 0xD1 ); - ModRM( 3, 5, to ); - return; - } - write8( 0xC1 ); - ModRM( 3, 5, to ); - write8( from ); -} - -/* shr cl to r64 */ -emitterT void eSHR64CLtoR( x86IntRegType to ) -{ - RexB(1, to); - write8( 0xD3 ); - ModRM( 3, 5, to ); -} - -/* shl imm8 to r32 */ -emitterT void eSHL32ItoR( x86IntRegType to, u8 from ) -{ - RexB(0, to); - if ( from == 1 ) - { - write8( 0xD1 ); - write8( 0xE0 | (to & 0x7) ); - return; - } - write8( 0xC1 ); - ModRM( 3, 4, to ); - write8( from ); -} - -/* shl imm8 to m32 */ -emitterT void eSHL32ItoM( uptr to, u8 from ) -{ - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 0, 4, DISP32 ); - write32( MEMADDR(to, 4) ); - } - else - { - write8( 0xC1 ); - ModRM( 0, 4, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); - } -} - -/* shl cl to r32 */ -emitterT void eSHL32CLtoR( x86IntRegType to ) -{ - RexB(0,to); - write8( 0xD3 ); - ModRM( 3, 4, to ); -} - -// shl imm8 to r16 -emitterT void eSHL16ItoR( x86IntRegType to, u8 from ) -{ - write8(0x66); - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD1 ); - write8( 0xE0 | (to & 0x7) ); - return; - } - write8( 0xC1 ); - ModRM( 3, 4, to ); - write8( from ); -} - -// shl imm8 to r8 -emitterT void eSHL8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD0 ); - write8( 0xE0 | (to & 0x7) ); - return; - } - write8( 0xC0 ); - ModRM( 3, 4, to ); - write8( from ); -} - -/* shr imm8 to r32 */ -emitterT void eSHR32ItoR( x86IntRegType to, u8 from ) { - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD1 ); - write8( 0xE8 | (to & 0x7) ); - } - else - { - write8( 0xC1 ); - ModRM( 3, 5, to ); - write8( from ); - } -} - -/* shr imm8 to m32 */ -emitterT void eSHR32ItoM( uptr to, u8 from ) -{ - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 0, 5, DISP32 ); - write32( MEMADDR(to, 4) ); - } - else - { - write8( 0xC1 ); - ModRM( 0, 5, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); - } -} - -/* shr cl to r32 */ -emitterT void eSHR32CLtoR( x86IntRegType to ) -{ - RexB(0,to); - write8( 0xD3 ); - ModRM( 3, 5, to ); -} - -// shr imm8 to r16 -emitterT void eSHR16ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 3, 5, to ); - } - else - { - write8( 0xC1 ); - ModRM( 3, 5, to ); - write8( from ); - } -} - -// shr imm8 to r8 -emitterT void eSHR8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD0 ); - write8( 0xE8 | (to & 0x7) ); - } - else - { - write8( 0xC0 ); - ModRM( 3, 5, to ); - write8( from ); - } -} - -/* sar imm8 to r64 */ -emitterT void eSAR64ItoR( x86IntRegType to, u8 from ) -{ - RexB(1,to); - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 3, 7, to ); - return; - } - write8( 0xC1 ); - ModRM( 3, 7, to ); - write8( from ); -} - -/* sar cl to r64 */ -emitterT void eSAR64CLtoR( x86IntRegType to ) -{ - RexB(1, to); - write8( 0xD3 ); - ModRM( 3, 7, to ); -} - -/* sar imm8 to r32 */ -emitterT void eSAR32ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 3, 7, to ); - return; - } - write8( 0xC1 ); - ModRM( 3, 7, to ); - write8( from ); -} - -/* sar imm8 to m32 */ -emitterT void eSAR32ItoM( uptr to, u8 from ) -{ - write8( 0xC1 ); - ModRM( 0, 7, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -/* sar cl to r32 */ -emitterT void eSAR32CLtoR( x86IntRegType to ) -{ - RexB(0,to); - write8( 0xD3 ); - ModRM( 3, 7, to ); -} - -// sar imm8 to r16 -emitterT void eSAR16ItoR( x86IntRegType to, u8 from ) -{ - write8(0x66); - RexB(0,to); - if ( from == 1 ) - { - write8( 0xD1 ); - ModRM( 3, 7, to ); - return; - } - write8( 0xC1 ); - ModRM( 3, 7, to ); - write8( from ); -} - -emitterT void eROR32ItoR( x86IntRegType to,u8 from ) -{ - RexB(0,to); - if ( from == 1 ) { - write8( 0xd1 ); - write8( 0xc8 | to ); - } - else - { - write8( 0xc1 ); - write8( 0xc8 | to ); - write8( from ); - } -} - -emitterT void eRCR32ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) { - write8( 0xd1 ); - ModRM(3, 3, to); - } - else - { - write8( 0xc1 ); - ModRM(3, 3, to); - write8( from ); - } -} - -emitterT void eRCR32ItoM( uptr to, u8 from ) -{ - RexB(0,to); - if ( from == 1 ) { - write8( 0xd1 ); - ModRM( 0, 3, DISP32 ); - write32( MEMADDR(to, 8) ); - } - else - { - write8( 0xc1 ); - ModRM( 0, 3, DISP32 ); - write32( MEMADDR(to, 8) ); - write8( from ); - } -} - -// shld imm8 to r32 -emitterT void eSHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) -{ - RexRB(0,from,to); - write8( 0x0F ); - write8( 0xA4 ); - ModRM( 3, from, to ); - write8( shift ); -} - -// shrd imm8 to r32 -emitterT void eSHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) -{ - RexRB(0,from,to); - write8( 0x0F ); - write8( 0xAC ); - ModRM( 3, from, to ); - write8( shift ); -} - -//////////////////////////////////// -// logical instructions / -//////////////////////////////////// - -/* or imm32 to r32 */ -emitterT void eOR64ItoR( x86IntRegType to, u32 from ) -{ - RexB(1, to); - if ( to == EAX ) { - write8( 0x0D ); - } - else { - write8( 0x81 ); - ModRM( 3, 1, to ); - } - write32( from ); -} - -/* or m64 to r64 */ -emitterT void eOR64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x0B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* or r64 to r64 */ -emitterT void eOR64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x09 ); - ModRM( 3, from, to ); -} - -// or r32 to m64 -emitterT void eOR64RtoM(uptr to, x86IntRegType from ) -{ - RexR(1,from); - write8( 0x09 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* or imm32 to r32 */ -emitterT void eOR32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x0D ); - } - else { - write8( 0x81 ); - ModRM( 3, 1, to ); - } - write32( from ); -} - -/* or imm32 to m32 */ -emitterT void eOR32ItoM(uptr to, u32 from ) -{ - write8( 0x81 ); - ModRM( 0, 1, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* or r32 to r32 */ -emitterT void eOR32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x09 ); - ModRM( 3, from, to ); -} - -/* or r32 to m32 */ -emitterT void eOR32RtoM(uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x09 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* or m32 to r32 */ -emitterT void eOR32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x0B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// or r16 to r16 -emitterT void eOR16RtoR( x86IntRegType to, x86IntRegType from ) -{ - write8(0x66); - RexRB(0,from,to); - write8( 0x09 ); - ModRM( 3, from, to ); -} - -// or imm16 to r16 -emitterT void eOR16ItoR( x86IntRegType to, u16 from ) -{ - write8(0x66); - RexB(0,to); - if ( to == EAX ) { - write8( 0x0D ); - } - else { - write8( 0x81 ); - ModRM( 3, 1, to ); - } - write16( from ); -} - -// or imm16 to m316 -emitterT void eOR16ItoM( uptr to, u16 from ) -{ - write8(0x66); - write8( 0x81 ); - ModRM( 0, 1, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( from ); -} - -/* or m16 to r16 */ -emitterT void eOR16MtoR( x86IntRegType to, uptr from ) -{ - write8(0x66); - RexR(0,to); - write8( 0x0B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// or r16 to m16 -emitterT void eOR16RtoM( uptr to, x86IntRegType from ) -{ - write8(0x66); - RexR(0,from); - write8( 0x09 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -// or r8 to r8 -emitterT void eOR8RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x08 ); - ModRM( 3, from, to ); -} - -// or r8 to m8 -emitterT void eOR8RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x08 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -// or imm8 to m8 -emitterT void eOR8ItoM( uptr to, u8 from ) -{ - write8( 0x80 ); - ModRM( 0, 1, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -// or m8 to r8 -emitterT void eOR8MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x0A ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* xor imm32 to r64 */ -emitterT void eXOR64ItoR( x86IntRegType to, u32 from ) -{ - RexB(1,to); - if ( to == EAX ) { - write8( 0x35 ); - } else { - write8( 0x81 ); - ModRM( 3, 6, to ); - } - write32( from ); -} - -/* xor r64 to r64 */ -emitterT void eXOR64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x31 ); - ModRM( 3, from, to ); -} - -/* xor m64 to r64 */ -emitterT void eXOR64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x33 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* xor r64 to m64 */ -emitterT void eXOR64RtoM( uptr to, x86IntRegType from ) -{ - RexR(1,from); - write8( 0x31 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* xor imm32 to r32 */ -emitterT void eXOR32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x35 ); - } - else { - write8( 0x81 ); - ModRM( 3, 6, to ); - } - write32( from ); -} - -/* xor imm32 to m32 */ -emitterT void eXOR32ItoM( uptr to, u32 from ) -{ - write8( 0x81 ); - ModRM( 0, 6, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* xor r32 to r32 */ -emitterT void eXOR32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x31 ); - ModRM( 3, from, to ); -} - -/* xor r16 to r16 */ -emitterT void eXOR16RtoR( x86IntRegType to, x86IntRegType from ) -{ - write8( 0x66 ); - RexRB(0,from,to); - write8( 0x31 ); - ModRM( 3, from, to ); -} - -/* xor r32 to m32 */ -emitterT void eXOR32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x31 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* xor m32 to r32 */ -emitterT void eXOR32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x33 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// xor imm16 to r16 -emitterT void eXOR16ItoR( x86IntRegType to, u16 from ) -{ - write8(0x66); - RexB(0,to); - if ( to == EAX ) { - write8( 0x35 ); - } - else { - write8( 0x81 ); - ModRM( 3, 6, to ); - } - write16( from ); -} - -// xor r16 to m16 -emitterT void eXOR16RtoM( uptr to, x86IntRegType from ) -{ - write8(0x66); - RexR(0,from); - write8( 0x31 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* and imm32 to r64 */ -emitterT void eAND64I32toR( x86IntRegType to, u32 from ) -{ - RexB(1, to); - if ( to == EAX ) { - write8( 0x25 ); - } else { - write8( 0x81 ); - ModRM( 3, 0x4, to ); - } - write32( from ); -} - -/* and m64 to r64 */ -emitterT void eAND64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x23 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* and r64 to m64 */ -emitterT void eAND64RtoM( uptr to, x86IntRegType from ) -{ - RexR(1, from); - write8( 0x21 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* and r64 to r64 */ -emitterT void eAND64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1, from, to); - write8( 0x21 ); - ModRM( 3, from, to ); -} - -/* and imm32 to m64 */ -emitterT void eAND64I32toM( uptr to, u32 from ) -{ - Rex(1,0,0,0); - write8( 0x81 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* and imm32 to r32 */ -emitterT void eAND32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if(from < 0x80) { - eAND32I8toR(to, (u8)from); - } - else { - if ( to == EAX ) { - write8( 0x25 ); - } - else { - write8( 0x81 ); - ModRM( 3, 0x4, to ); - } - write32( from ); - } -} - -/* and sign ext imm8 to r32 */ -emitterT void eAND32I8toR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - write8( 0x83 ); - ModRM( 3, 0x4, to ); - write8( from ); -} - -/* and imm32 to m32 */ -emitterT void eAND32ItoM( uptr to, u32 from ) -{ - if(from < 0x80) { - eAND32I8toM(to, (u8)from); - } - else { - write8( 0x81 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); - } -} - - -/* and sign ext imm8 to m32 */ -emitterT void eAND32I8toM( uptr to, u8 from ) -{ - write8( 0x83 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -/* and r32 to r32 */ -emitterT void eAND32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x21 ); - ModRM( 3, from, to ); -} - -/* and r32 to m32 */ -emitterT void eAND32RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x21 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* and m32 to r32 */ -emitterT void eAND32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x23 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// Warning: Untested form of AND. -emitterT void eAND32RmtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write8( 0x23 ); - ModRM( 0, to, from ); -} - -// Warning: Untested form of AND. -emitterT void eAND32RmtoROffset( x86IntRegType to, x86IntRegType from, int offset ) -{ - RexRB(0,to,from); - write16( 0x23 ); - WriteRmOffsetFrom(to,from,offset); -} - -// and r16 to r16 -emitterT void eAND16RtoR( x86IntRegType to, x86IntRegType from ) -{ - write8(0x66); - RexRB(0,to,from); - write8( 0x23 ); - ModRM( 3, to, from ); -} - -/* and imm16 to r16 */ -emitterT void eAND16ItoR( x86IntRegType to, u16 from ) -{ - write8(0x66); - RexB(0,to); - - if ( to == EAX ) { - write8( 0x25 ); - write16( from ); - } - else if ( from < 0x80 ) { - write8( 0x83 ); - ModRM( 3, 0x4, to ); - write8((u8)from ); - } - else { - write8( 0x81 ); - ModRM( 3, 0x4, to ); - write16( from ); - } -} - -/* and imm16 to m16 */ -emitterT void eAND16ItoM( uptr to, u16 from ) -{ - write8(0x66); - if ( from < 0x80 ) { - write8( 0x83 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 6) ); - write8((u8)from ); - } - else - { - write8( 0x81 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( from ); - - } -} - -/* and r16 to m16 */ -emitterT void eAND16RtoM( uptr to, x86IntRegType from ) -{ - write8( 0x66 ); - RexR(0,from); - write8( 0x21 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* and m16 to r16 */ -emitterT void eAND16MtoR( x86IntRegType to, uptr from ) -{ - write8( 0x66 ); - RexR(0,to); - write8( 0x23 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4)); -} - -/* and imm8 to r8 */ -emitterT void eAND8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x24 ); - } - else { - write8( 0x80 ); - ModRM( 3, 0x4, to ); - } - write8( from ); -} - -/* and imm8 to m8 */ -emitterT void eAND8ItoM( uptr to, u8 from ) -{ - write8( 0x80 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -// and r8 to r8 -emitterT void eAND8RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,to,from); - write8( 0x22 ); - ModRM( 3, to, from ); -} - -/* and r8 to m8 */ -emitterT void eAND8RtoM( uptr to, x86IntRegType from ) -{ - RexR(0,from); - write8( 0x20 ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* and m8 to r8 */ -emitterT void eAND8MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x22 ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4)); -} - -/* not r64 */ -emitterT void eNOT64R( x86IntRegType from ) -{ - RexB(1, from); - write8( 0xF7 ); - ModRM( 3, 2, from ); -} - -/* not r32 */ -emitterT void eNOT32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 2, from ); -} - -// not m32 -emitterT void eNOT32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 2, DISP32 ); - write32( MEMADDR(from, 4)); -} - -/* neg r64 */ -emitterT void eNEG64R( x86IntRegType from ) -{ - RexB(1, from); - write8( 0xF7 ); - ModRM( 3, 3, from ); -} - -/* neg r32 */ -emitterT void eNEG32R( x86IntRegType from ) -{ - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 3, from ); -} - -emitterT void eNEG32M( u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 3, DISP32 ); - write32( MEMADDR(from, 4)); -} - -/* neg r16 */ -emitterT void eNEG16R( x86IntRegType from ) -{ - write8( 0x66 ); - RexB(0,from); - write8( 0xF7 ); - ModRM( 3, 3, from ); -} - -//////////////////////////////////// -// jump instructions / -//////////////////////////////////// - -emitterT u8* JMP( uptr to ) { - uptr jump = ( x86Ptr[0] - (u8*)to ) - 1; - - if ( jump > 0x7f ) { - assert( to <= 0xffffffff ); - return (u8*)eJMP32( to ); - } - else { - return (u8*)eJMP8( to ); - } -} - -/* jmp rel8 */ -emitterT u8* eJMP8( u8 to ) -{ - write8( 0xEB ); - write8( to ); - return x86Ptr[I] - 1; -} - -/* jmp rel32 */ -emitterT u32* eJMP32( uptr to ) -{ - assert( (sptr)to <= 0x7fffffff && (sptr)to >= -0x7fffffff ); - write8( 0xE9 ); - write32( to ); - return (u32*)(x86Ptr[I] - 4 ); -} - -/* jmp r32/r64 */ -emitterT void eJMPR( x86IntRegType to ) -{ - RexB(0, to); - write8( 0xFF ); - ModRM( 3, 4, to ); -} - -// jmp m32 -emitterT void eJMP32M( uptr to ) -{ - write8( 0xFF ); - ModRM( 0, 4, DISP32 ); - write32( MEMADDR(to, 4)); -} - -/* jp rel8 */ -emitterT u8* eJP8( u8 to ) { - return J8Rel( 0x7A, to ); -} - -/* jnp rel8 */ -emitterT u8* eJNP8( u8 to ) { - return J8Rel( 0x7B, to ); -} - -/* je rel8 */ -emitterT u8* eJE8( u8 to ) { - return J8Rel( 0x74, to ); -} - -/* jz rel8 */ -emitterT u8* eJZ8( u8 to ) -{ - return J8Rel( 0x74, to ); -} - -/* js rel8 */ -emitterT u8* eJS8( u8 to ) -{ - return J8Rel( 0x78, to ); -} - -/* jns rel8 */ -emitterT u8* eJNS8( u8 to ) -{ - return J8Rel( 0x79, to ); -} - -/* jg rel8 */ -emitterT u8* eJG8( u8 to ) -{ - return J8Rel( 0x7F, to ); -} - -/* jge rel8 */ -emitterT u8* eJGE8( u8 to ) -{ - return J8Rel( 0x7D, to ); -} - -/* jl rel8 */ -emitterT u8* eJL8( u8 to ) -{ - return J8Rel( 0x7C, to ); -} - -/* ja rel8 */ -emitterT u8* eJA8( u8 to ) -{ - return J8Rel( 0x77, to ); -} - -emitterT u8* eJAE8( u8 to ) -{ - return J8Rel( 0x73, to ); -} - -/* jb rel8 */ -emitterT u8* eJB8( u8 to ) -{ - return J8Rel( 0x72, to ); -} - -/* jbe rel8 */ -emitterT u8* eJBE8( u8 to ) -{ - return J8Rel( 0x76, to ); -} - -/* jle rel8 */ -emitterT u8* eJLE8( u8 to ) -{ - return J8Rel( 0x7E, to ); -} - -/* jne rel8 */ -emitterT u8* eJNE8( u8 to ) -{ - return J8Rel( 0x75, to ); -} - -/* jnz rel8 */ -emitterT u8* eJNZ8( u8 to ) -{ - return J8Rel( 0x75, to ); -} - -/* jng rel8 */ -emitterT u8* eJNG8( u8 to ) -{ - return J8Rel( 0x7E, to ); -} - -/* jnge rel8 */ -emitterT u8* eJNGE8( u8 to ) -{ - return J8Rel( 0x7C, to ); -} - -/* jnl rel8 */ -emitterT u8* eJNL8( u8 to ) -{ - return J8Rel( 0x7D, to ); -} - -/* jnle rel8 */ -emitterT u8* eJNLE8( u8 to ) -{ - return J8Rel( 0x7F, to ); -} - -/* jo rel8 */ -emitterT u8* eJO8( u8 to ) -{ - return J8Rel( 0x70, to ); -} - -/* jno rel8 */ -emitterT u8* eJNO8( u8 to ) -{ - return J8Rel( 0x71, to ); -} -/* Untested and slower, use 32bit versions instead -// ja rel16 -emitterT u16* eJA16( u16 to ) -{ -return J16Rel( 0x87, to ); -} - -// jb rel16 -emitterT u16* eJB16( u16 to ) -{ -return J16Rel( 0x82, to ); -} - -// je rel16 -emitterT u16* eJE16( u16 to ) -{ -return J16Rel( 0x84, to ); -} - -// jz rel16 -emitterT u16* eJZ16( u16 to ) -{ -return J16Rel( 0x84, to ); -} -*/ -// jb rel32 -emitterT u32* eJB32( u32 to ) -{ - return J32Rel( 0x82, to ); -} - -/* je rel32 */ -emitterT u32* eJE32( u32 to ) -{ - return J32Rel( 0x84, to ); -} - -/* jz rel32 */ -emitterT u32* eJZ32( u32 to ) -{ - return J32Rel( 0x84, to ); -} - -/* js rel32 */ -emitterT u32* eJS32( u32 to ) -{ - return J32Rel( 0x88, to ); -} - -/* jns rel32 */ -emitterT u32* eJNS32( u32 to ) -{ - return J32Rel( 0x89, to ); -} - -/* jg rel32 */ -emitterT u32* eJG32( u32 to ) -{ - return J32Rel( 0x8F, to ); -} - -/* jge rel32 */ -emitterT u32* eJGE32( u32 to ) -{ - return J32Rel( 0x8D, to ); -} - -/* jl rel32 */ -emitterT u32* eJL32( u32 to ) -{ - return J32Rel( 0x8C, to ); -} - -/* jle rel32 */ -emitterT u32* eJLE32( u32 to ) -{ - return J32Rel( 0x8E, to ); -} - -/* ja rel32 */ -emitterT u32* eJA32( u32 to ) -{ - return J32Rel( 0x87, to ); -} - -/* jae rel32 */ -emitterT u32* eJAE32( u32 to ) -{ - return J32Rel( 0x83, to ); -} - -/* jne rel32 */ -emitterT u32* eJNE32( u32 to ) -{ - return J32Rel( 0x85, to ); -} - -/* jnz rel32 */ -emitterT u32* eJNZ32( u32 to ) -{ - return J32Rel( 0x85, to ); -} - -/* jng rel32 */ -emitterT u32* eJNG32( u32 to ) -{ - return J32Rel( 0x8E, to ); -} - -/* jnge rel32 */ -emitterT u32* eJNGE32( u32 to ) -{ - return J32Rel( 0x8C, to ); -} - -/* jnl rel32 */ -emitterT u32* eJNL32( u32 to ) -{ - return J32Rel( 0x8D, to ); -} - -/* jnle rel32 */ -emitterT u32* eJNLE32( u32 to ) -{ - return J32Rel( 0x8F, to ); -} - -/* jo rel32 */ -emitterT u32* eJO32( u32 to ) -{ - return J32Rel( 0x80, to ); -} - -/* jno rel32 */ -emitterT u32* eJNO32( u32 to ) -{ - return J32Rel( 0x81, to ); -} - - - -/* call func */ -emitterT void eCALLFunc( uptr func ) -{ - func -= ( (uptr)x86Ptr[0] + 5 ); - assert( (sptr)func <= 0x7fffffff && (sptr)func >= -0x7fffffff ); - eCALL32(func); -} - -/* call rel32 */ -emitterT void eCALL32( u32 to ) -{ - write8( 0xE8 ); - write32( to ); -} - -/* call r32 */ -emitterT void eCALL32R( x86IntRegType to ) -{ - write8( 0xFF ); - ModRM( 3, 2, to ); -} - -/* call r64 */ -emitterT void eCALL64R( x86IntRegType to ) -{ - RexB(0, to); - write8( 0xFF ); - ModRM( 3, 2, to ); -} - -/* call m32 */ -emitterT void eCALL32M( u32 to ) -{ - write8( 0xFF ); - ModRM( 0, 2, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -//////////////////////////////////// -// misc instructions / -//////////////////////////////////// - -/* cmp imm32 to r64 */ -emitterT void eCMP64I32toR( x86IntRegType to, u32 from ) -{ - RexB(1, to); - if ( to == EAX ) { - write8( 0x3D ); - } - else { - write8( 0x81 ); - ModRM( 3, 7, to ); - } - write32( from ); -} - -/* cmp m64 to r64 */ -emitterT void eCMP64MtoR( x86IntRegType to, uptr from ) -{ - RexR(1, to); - write8( 0x3B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// cmp r64 to r64 -emitterT void eCMP64RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(1,from,to); - write8( 0x39 ); - ModRM( 3, from, to ); -} - -/* cmp imm32 to r32 */ -emitterT void eCMP32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) { - write8( 0x3D ); - } - else { - write8( 0x81 ); - ModRM( 3, 7, to ); - } - write32( from ); -} - -/* cmp imm32 to m32 */ -emitterT void eCMP32ItoM( uptr to, u32 from ) -{ - write8( 0x81 ); - ModRM( 0, 7, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* cmp r32 to r32 */ -emitterT void eCMP32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x39 ); - ModRM( 3, from, to ); -} - -/* cmp m32 to r32 */ -emitterT void eCMP32MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x3B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// cmp imm8 to [r32] -emitterT void eCMP32I8toRm( x86IntRegType to, u8 from) -{ - RexB(0,to); - write8( 0x83 ); - ModRM( 0, 7, to ); - write8(from); -} - -// cmp imm32 to [r32+off] -emitterT void eCMP32I8toRmOffset8( x86IntRegType to, u8 from, u8 off) -{ - RexB(0,to); - write8( 0x83 ); - ModRM( 1, 7, to ); - write8(off); - write8(from); -} - -// cmp imm8 to [r32] -emitterT void eCMP32I8toM( uptr to, u8 from) -{ - write8( 0x83 ); - ModRM( 0, 7, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -/* cmp imm16 to r16 */ -emitterT void eCMP16ItoR( x86IntRegType to, u16 from ) -{ - write8( 0x66 ); - RexB(0,to); - if ( to == EAX ) - { - write8( 0x3D ); - } - else - { - write8( 0x81 ); - ModRM( 3, 7, to ); - } - write16( from ); -} - -/* cmp imm16 to m16 */ -emitterT void eCMP16ItoM( uptr to, u16 from ) -{ - write8( 0x66 ); - write8( 0x81 ); - ModRM( 0, 7, DISP32 ); - write32( MEMADDR(to, 6) ); - write16( from ); -} - -/* cmp r16 to r16 */ -emitterT void eCMP16RtoR( x86IntRegType to, x86IntRegType from ) -{ - write8( 0x66 ); - RexRB(0,from,to); - write8( 0x39 ); - ModRM( 3, from, to ); -} - -/* cmp m16 to r16 */ -emitterT void eCMP16MtoR( x86IntRegType to, uptr from ) -{ - write8( 0x66 ); - RexR(0,to); - write8( 0x3B ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// cmp imm8 to r8 -emitterT void eCMP8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( to == EAX ) - { - write8( 0x3C ); - } - else - { - write8( 0x80 ); - ModRM( 3, 7, to ); - } - write8( from ); -} - -// cmp m8 to r8 -emitterT void eCMP8MtoR( x86IntRegType to, uptr from ) -{ - RexR(0,to); - write8( 0x3A ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* test imm32 to r32 */ -emitterT void eTEST32ItoR( x86IntRegType to, u32 from ) -{ - RexB(0,to); - if ( to == EAX ) - { - write8( 0xA9 ); - } - else - { - write8( 0xF7 ); - ModRM( 3, 0, to ); - } - write32( from ); -} - -emitterT void eTEST32ItoM( uptr to, u32 from ) -{ - write8( 0xF7 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 8) ); - write32( from ); -} - -/* test r32 to r32 */ -emitterT void eTEST32RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0,from,to); - write8( 0x85 ); - ModRM( 3, from, to ); -} - -// test imm32 to [r32] -emitterT void eTEST32ItoRm( x86IntRegType to, u32 from ) -{ - RexB(0,to); - write8( 0xF7 ); - ModRM( 0, 0, to ); - write32(from); -} - -// test imm16 to r16 -emitterT void eTEST16ItoR( x86IntRegType to, u16 from ) -{ - write8(0x66); - RexB(0,to); - if ( to == EAX ) - { - write8( 0xA9 ); - } - else - { - write8( 0xF7 ); - ModRM( 3, 0, to ); - } - write16( from ); -} - -// test r16 to r16 -emitterT void eTEST16RtoR( x86IntRegType to, x86IntRegType from ) -{ - write8(0x66); - RexRB(0,from,to); - write8( 0x85 ); - ModRM( 3, from, to ); -} - -// test r8 to r8 -emitterT void eTEST8RtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write8( 0x84 ); - ModRM( 3, from, to ); -} - - -// test imm8 to r8 -emitterT void eTEST8ItoR( x86IntRegType to, u8 from ) -{ - RexB(0,to); - if ( to == EAX ) - { - write8( 0xA8 ); - } - else - { - write8( 0xF6 ); - ModRM( 3, 0, to ); - } - write8( from ); -} - -// test imm8 to r8 -emitterT void eTEST8ItoM( uptr to, u8 from ) -{ - write8( 0xF6 ); - ModRM( 0, 0, DISP32 ); - write32( MEMADDR(to, 5) ); - write8( from ); -} - -/* sets r8 */ -emitterT void eSETS8R( x86IntRegType to ) -{ - SET8R( 0x98, to ); -} - -/* setl r8 */ -emitterT void eSETL8R( x86IntRegType to ) -{ - SET8R( 0x9C, to ); -} - -// setge r8 -emitterT void eSETGE8R( x86IntRegType to ) { SET8R(0x9d, to); } -// setg r8 -emitterT void eSETG8R( x86IntRegType to ) { SET8R(0x9f, to); } -// seta r8 -emitterT void eSETA8R( x86IntRegType to ) { SET8R(0x97, to); } -// setae r8 -emitterT void eSETAE8R( x86IntRegType to ) { SET8R(0x99, to); } -/* setb r8 */ -emitterT void eSETB8R( x86IntRegType to ) { SET8R( 0x92, to ); } -/* setb r8 */ -emitterT void eSETNZ8R( x86IntRegType to ) { SET8R( 0x95, to ); } -// setz r8 -emitterT void eSETZ8R( x86IntRegType to ) { SET8R(0x94, to); } -// sete r8 -emitterT void eSETE8R( x86IntRegType to ) { SET8R(0x94, to); } - -/* push imm32 */ -emitterT void ePUSH32I( u32 from ) -{; -write8( 0x68 ); -write32( from ); -} - -/* push r32 */ -emitterT void ePUSH32R( x86IntRegType from ) { write8( 0x50 | from ); } - -/* push m32 */ -emitterT void ePUSH32M( u32 from ) -{ - write8( 0xFF ); - ModRM( 0, 6, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* pop r32 */ -emitterT void ePOP32R( x86IntRegType from ) { write8( 0x58 | from ); } - -/* pushad */ -emitterT void ePUSHA32( void ) { write8( 0x60 ); } - -/* popad */ -emitterT void ePOPA32( void ) { write8( 0x61 ); } - -emitterT void ePUSHR(x86IntRegType from) { ePUSH32R(from); } -emitterT void ePOPR(x86IntRegType from) { ePOP32R(from); } - - -/* pushfd */ -emitterT void ePUSHFD( void ) { write8( 0x9C ); } -/* popfd */ -emitterT void ePOPFD( void ) { write8( 0x9D ); } - -emitterT void eRET( void ) { /*write8( 0xf3 ); <-- K8 opt?*/ write8( 0xC3 ); } - -emitterT void eCBW( void ) { write16( 0x9866 ); } -emitterT void eCWD( void ) { write8( 0x98 ); } -emitterT void eCDQ( void ) { write8( 0x99 ); } -emitterT void eCWDE() { write8(0x98); } - -emitterT void eLAHF() { write8(0x9f); } -emitterT void eSAHF() { write8(0x9e); } - -emitterT void eBT32ItoR( x86IntRegType to, u8 from ) -{ - write16( 0xBA0F ); - ModRM(3, 4, to); - write8( from ); -} - -emitterT void eBTR32ItoR( x86IntRegType to, u8 from ) -{ - write16( 0xBA0F ); - ModRM(3, 6, to); - write8( from ); -} - -emitterT void eBSRRtoR(x86IntRegType to, x86IntRegType from) -{ - write16( 0xBD0F ); - ModRM( 3, from, to ); -} - -emitterT void eBSWAP32R( x86IntRegType to ) -{ - write8( 0x0F ); - write8( 0xC8 + to ); -} - -// to = from + offset -emitterT void eLEA16RtoR(x86IntRegType to, x86IntRegType from, u16 offset) -{ - write8(0x66); - eLEA32RtoR(to, from, offset); -} - -emitterT void eLEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset) -{ - RexRB(0,to,from); - write8(0x8d); - - if( (from&7) == ESP ) { - if( offset == 0 ) { - ModRM(1, to, from); - write8(0x24); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM(1, to, from); - write8(0x24); - write8(offset); - } - else { - ModRM(2, to, from); - write8(0x24); - write32(offset); - } - } - else { - if( offset == 0 && from != EBP && from!=ESP ) { - ModRM(0, to, from); - } - else if( offset <= 127 && offset >= -128 ) { - ModRM(1, to, from); - write8(offset); - } - else { - ModRM(2, to, from); - write32(offset); - } - } -} - -// to = from0 + from1 -emitterT void eLEA16RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) -{ - write8(0x66); - eLEA32RRtoR(to, from0, from1); -} - -emitterT void eLEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) -{ - RexRXB(0, to, from0, from1); - write8(0x8d); - - if( (from1&7) == EBP ) { - ModRM(1, to, 4); - ModRM(0, from0, from1); - write8(0); - } - else { - ModRM(0, to, 4); - ModRM(0, from0, from1); - } -} - -// to = from << scale (max is 3) -emitterT void eLEA16RStoR(x86IntRegType to, x86IntRegType from, u32 scale) -{ - write8(0x66); - eLEA32RStoR(to, from, scale); -} - -// Don't inline recursive functions -emitterT void eLEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) -{ - if( to == from ) { - eSHL32ItoR(to, scale); - return; - } - - if( from != ESP ) { - RexRXB(0,to,from,0); - write8(0x8d); - ModRM(0, to, 4); - ModRM(scale, from, 5); - write32(0); - } - else { - assert( to != ESP ); - eMOV32RtoR(to, from); - eLEA32RStoR(to, to, scale); - } -} diff --git a/pcsx2/x86/ix86/ix86_3dnow.cpp b/pcsx2/x86/ix86/ix86_3dnow.cpp new file mode 100644 index 0000000000..0dc600d1be --- /dev/null +++ b/pcsx2/x86/ix86/ix86_3dnow.cpp @@ -0,0 +1,202 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "ix86_legacy_internal.h" + +//------------------------------------------------------------------ +// 3DNOW instructions [Anyone caught dead using these will be re-killed] +//------------------------------------------------------------------ + +/* femms */ +emitterT void FEMMS( void ) +{ + xWrite16( 0x0E0F ); +} + +emitterT void PFCMPEQMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0xB0 ); +} + +emitterT void PFCMPGTMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0xA0 ); +} + +emitterT void PFCMPGEMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x90 ); +} + +emitterT void PFADDMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x9E ); +} + +emitterT void PFADDRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x9E ); +} + +emitterT void PFSUBMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x9A ); +} + +emitterT void PFSUBRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x9A ); +} + +emitterT void PFMULMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0xB4 ); +} + +emitterT void PFMULRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0xB4 ); +} + +emitterT void PFRCPMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x96 ); +} + +emitterT void PFRCPRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x96 ); +} + +emitterT void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0xA6 ); +} + +emitterT void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0xB6 ); +} + +emitterT void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x97 ); +} + +emitterT void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0xA7 ); +} + +emitterT void PF2IDMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x1D ); +} + +emitterT void PF2IDRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x1D ); +} + +emitterT void PI2FDMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x0D ); +} + +emitterT void PI2FDRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x0D ); +} + +emitterT void PFMAXMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0xA4 ); +} + +emitterT void PFMAXRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0xA4 ); +} + +emitterT void PFMINMtoR( x86IntRegType to, uptr from ) +{ + xWrite16( 0x0F0F ); + ModRM( 0, to, DISP32 ); + xWrite32( from ); + xWrite8( 0x94 ); +} + +emitterT void PFMINRtoR( x86IntRegType to, x86IntRegType from ) +{ + xWrite16( 0x0F0F ); + ModRM( 3, to, from ); + xWrite8( 0x94 ); +} diff --git a/pcsx2/x86/ix86/ix86_3dnow.inl b/pcsx2/x86/ix86/ix86_3dnow.inl deleted file mode 100644 index 5fdcce2347..0000000000 --- a/pcsx2/x86/ix86/ix86_3dnow.inl +++ /dev/null @@ -1,201 +0,0 @@ -/* 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 - -//------------------------------------------------------------------ -// 3DNOW instructions -//------------------------------------------------------------------ - -/* femms */ -emitterT void eFEMMS( void ) -{ - write16( 0x0E0F ); -} - -emitterT void ePFCMPEQMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0xB0 ); -} - -emitterT void ePFCMPGTMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0xA0 ); -} - -emitterT void ePFCMPGEMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x90 ); -} - -emitterT void ePFADDMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x9E ); -} - -emitterT void ePFADDRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x9E ); -} - -emitterT void ePFSUBMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x9A ); -} - -emitterT void ePFSUBRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x9A ); -} - -emitterT void ePFMULMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0xB4 ); -} - -emitterT void ePFMULRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0xB4 ); -} - -emitterT void ePFRCPMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x96 ); -} - -emitterT void ePFRCPRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x96 ); -} - -emitterT void ePFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0xA6 ); -} - -emitterT void ePFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0xB6 ); -} - -emitterT void ePFRSQRTRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x97 ); -} - -emitterT void ePFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0xA7 ); -} - -emitterT void ePF2IDMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x1D ); -} - -emitterT void ePF2IDRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x1D ); -} - -emitterT void ePI2FDMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x0D ); -} - -emitterT void ePI2FDRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x0D ); -} - -emitterT void ePFMAXMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0xA4 ); -} - -emitterT void ePFMAXRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0xA4 ); -} - -emitterT void ePFMINMtoR( x86IntRegType to, uptr from ) -{ - write16( 0x0F0F ); - ModRM( 0, to, DISP32 ); - write32( from ); - write8( 0x94 ); -} - -emitterT void ePFMINRtoR( x86IntRegType to, x86IntRegType from ) -{ - write16( 0x0F0F ); - ModRM( 3, to, from ); - write8( 0x94 ); -} diff --git a/pcsx2/x86/ix86/ix86_cpudetect.cpp b/pcsx2/x86/ix86/ix86_cpudetect.cpp index bf88feeb32..083d72e1b2 100644 --- a/pcsx2/x86/ix86/ix86_cpudetect.cpp +++ b/pcsx2/x86/ix86/ix86_cpudetect.cpp @@ -18,11 +18,8 @@ #include "PrecompiledHeader.h" -#define _EmitterId_ 0 - -#include "ix86.h" -#include "Misc.h" -#include "Threading.h" +#include "System.h" +#include "ix86_legacy_internal.h" #include "RedtapeWindows.h" @@ -400,6 +397,7 @@ void cpudetectInit() cpudetectSSE3(recSSE); HostSys::Munmap( recSSE, 0x1000 ); } + else { Console::Error("Error: Failed to allocate memory for SSE3 State detection."); } ////////////////////////////////////// // Core Counting! diff --git a/pcsx2/x86/ix86/ix86_fpu.cpp b/pcsx2/x86/ix86/ix86_fpu.cpp new file mode 100644 index 0000000000..9394fc2156 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_fpu.cpp @@ -0,0 +1,276 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "ix86_legacy_internal.h" + +//------------------------------------------------------------------ +// FPU instructions +//------------------------------------------------------------------ + +/* fild m32 to fpu reg stack */ +emitterT void FILD32( u32 from ) +{ + xWrite8( 0xDB ); + ModRM( 0, 0x0, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fistp m32 from fpu reg stack */ +emitterT void FISTP32( u32 from ) +{ + xWrite8( 0xDB ); + ModRM( 0, 0x3, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fld m32 to fpu reg stack */ +emitterT void FLD32( u32 from ) +{ + xWrite8( 0xD9 ); + ModRM( 0, 0x0, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +// fld st(i) +emitterT void FLD(int st) { xWrite16(0xc0d9+(st<<8)); } +emitterT void FLD1() { xWrite16(0xe8d9); } +emitterT void FLDL2E() { xWrite16(0xead9); } + +/* fst m32 from fpu reg stack */ +emitterT void FST32( u32 to ) +{ + xWrite8( 0xD9 ); + ModRM( 0, 0x2, DISP32 ); + xWrite32( MEMADDR(to, 4) ); +} + +/* fstp m32 from fpu reg stack */ +emitterT void FSTP32( u32 to ) +{ + xWrite8( 0xD9 ); + ModRM( 0, 0x3, DISP32 ); + xWrite32( MEMADDR(to, 4) ); +} + +// fstp st(i) +emitterT void FSTP(int st) { xWrite16(0xd8dd+(st<<8)); } + +/* fldcw fpu control word from m16 */ +emitterT void FLDCW( u32 from ) +{ + xWrite8( 0xD9 ); + ModRM( 0, 0x5, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fnstcw fpu control word to m16 */ +emitterT void FNSTCW( u32 to ) +{ + xWrite8( 0xD9 ); + ModRM( 0, 0x7, DISP32 ); + xWrite32( MEMADDR(to, 4) ); +} + +emitterT void FNSTSWtoAX() { xWrite16(0xE0DF); } +emitterT void FXAM() { xWrite16(0xe5d9); } +emitterT void FDECSTP() { xWrite16(0xf6d9); } +emitterT void FRNDINT() { xWrite16(0xfcd9); } +emitterT void FXCH(int st) { xWrite16(0xc8d9+(st<<8)); } +emitterT void F2XM1() { xWrite16(0xf0d9); } +emitterT void FSCALE() { xWrite16(0xfdd9); } +emitterT void FPATAN(void) { xWrite16(0xf3d9); } +emitterT void FSIN(void) { xWrite16(0xfed9); } + +/* fadd ST(src) to fpu reg stack ST(0) */ +emitterT void FADD32Rto0( x86IntRegType src ) +{ + xWrite8( 0xD8 ); + xWrite8( 0xC0 + src ); +} + +/* fadd ST(0) to fpu reg stack ST(src) */ +emitterT void FADD320toR( x86IntRegType src ) +{ + xWrite8( 0xDC ); + xWrite8( 0xC0 + src ); +} + +/* fsub ST(src) to fpu reg stack ST(0) */ +emitterT void FSUB32Rto0( x86IntRegType src ) +{ + xWrite8( 0xD8 ); + xWrite8( 0xE0 + src ); +} + +/* fsub ST(0) to fpu reg stack ST(src) */ +emitterT void FSUB320toR( x86IntRegType src ) +{ + xWrite8( 0xDC ); + xWrite8( 0xE8 + src ); +} + +/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ +emitterT void FSUBP( void ) +{ + xWrite8( 0xDE ); + xWrite8( 0xE9 ); +} + +/* fmul ST(src) to fpu reg stack ST(0) */ +emitterT void FMUL32Rto0( x86IntRegType src ) +{ + xWrite8( 0xD8 ); + xWrite8( 0xC8 + src ); +} + +/* fmul ST(0) to fpu reg stack ST(src) */ +emitterT void FMUL320toR( x86IntRegType src ) +{ + xWrite8( 0xDC ); + xWrite8( 0xC8 + src ); +} + +/* fdiv ST(src) to fpu reg stack ST(0) */ +emitterT void FDIV32Rto0( x86IntRegType src ) +{ + xWrite8( 0xD8 ); + xWrite8( 0xF0 + src ); +} + +/* fdiv ST(0) to fpu reg stack ST(src) */ +emitterT void FDIV320toR( x86IntRegType src ) +{ + xWrite8( 0xDC ); + xWrite8( 0xF8 + src ); +} + +emitterT void FDIV320toRP( x86IntRegType src ) +{ + xWrite8( 0xDE ); + xWrite8( 0xF8 + src ); +} + +/* fadd m32 to fpu reg stack */ +emitterT void FADD32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x0, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fsub m32 to fpu reg stack */ +emitterT void FSUB32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x4, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fmul m32 to fpu reg stack */ +emitterT void FMUL32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x1, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fdiv m32 to fpu reg stack */ +emitterT void FDIV32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x6, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fabs fpu reg stack */ +emitterT void FABS( void ) +{ + xWrite16( 0xE1D9 ); +} + +/* fsqrt fpu reg stack */ +emitterT void FSQRT( void ) +{ + xWrite16( 0xFAD9 ); +} + +/* fchs fpu reg stack */ +emitterT void FCHS( void ) +{ + xWrite16( 0xE0D9 ); +} + +/* fcomi st, st(i) */ +emitterT void FCOMI( x86IntRegType src ) +{ + xWrite8( 0xDB ); + xWrite8( 0xF0 + src ); +} + +/* fcomip st, st(i) */ +emitterT void FCOMIP( x86IntRegType src ) +{ + xWrite8( 0xDF ); + xWrite8( 0xF0 + src ); +} + +/* fucomi st, st(i) */ +emitterT void FUCOMI( x86IntRegType src ) +{ + xWrite8( 0xDB ); + xWrite8( 0xE8 + src ); +} + +/* fucomip st, st(i) */ +emitterT void FUCOMIP( x86IntRegType src ) +{ + xWrite8( 0xDF ); + xWrite8( 0xE8 + src ); +} + +/* fcom m32 to fpu reg stack */ +emitterT void FCOM32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x2, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +/* fcomp m32 to fpu reg stack */ +emitterT void FCOMP32( u32 from ) +{ + xWrite8( 0xD8 ); + ModRM( 0, 0x3, DISP32 ); + xWrite32( MEMADDR(from, 4) ); +} + +#define FCMOV32( low, high ) \ + { \ + xWrite8( low ); \ + xWrite8( high + from ); \ + } + +emitterT void FCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } +emitterT void FCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } +emitterT void FCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } +emitterT void FCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } +emitterT void FCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } +emitterT void FCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } +emitterT void FCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } +emitterT void FCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } diff --git a/pcsx2/x86/ix86/ix86_fpu.inl b/pcsx2/x86/ix86/ix86_fpu.inl deleted file mode 100644 index ae20b6c4ec..0000000000 --- a/pcsx2/x86/ix86/ix86_fpu.inl +++ /dev/null @@ -1,276 +0,0 @@ -/* 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 -//#include "PrecompiledHeader.h" - -//------------------------------------------------------------------ -// FPU instructions -//------------------------------------------------------------------ - -/* fild m32 to fpu reg stack */ -emitterT void eFILD32( u32 from ) -{ - write8( 0xDB ); - ModRM( 0, 0x0, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fistp m32 from fpu reg stack */ -emitterT void eFISTP32( u32 from ) -{ - write8( 0xDB ); - ModRM( 0, 0x3, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fld m32 to fpu reg stack */ -emitterT void eFLD32( u32 from ) -{ - write8( 0xD9 ); - ModRM( 0, 0x0, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// fld st(i) -emitterT void eFLD(int st) { write16(0xc0d9+(st<<8)); } -emitterT void eFLD1() { write16(0xe8d9); } -emitterT void eFLDL2E() { write16(0xead9); } - -/* fst m32 from fpu reg stack */ -emitterT void eFST32( u32 to ) -{ - write8( 0xD9 ); - ModRM( 0, 0x2, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -/* fstp m32 from fpu reg stack */ -emitterT void eFSTP32( u32 to ) -{ - write8( 0xD9 ); - ModRM( 0, 0x3, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -// fstp st(i) -emitterT void eFSTP(int st) { write16(0xd8dd+(st<<8)); } - -/* fldcw fpu control word from m16 */ -emitterT void eFLDCW( u32 from ) -{ - write8( 0xD9 ); - ModRM( 0, 0x5, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fnstcw fpu control word to m16 */ -emitterT void eFNSTCW( u32 to ) -{ - write8( 0xD9 ); - ModRM( 0, 0x7, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -emitterT void eFNSTSWtoAX() { write16(0xE0DF); } -emitterT void eFXAM() { write16(0xe5d9); } -emitterT void eFDECSTP() { write16(0xf6d9); } -emitterT void eFRNDINT() { write16(0xfcd9); } -emitterT void eFXCH(int st) { write16(0xc8d9+(st<<8)); } -emitterT void eF2XM1() { write16(0xf0d9); } -emitterT void eFSCALE() { write16(0xfdd9); } -emitterT void eFPATAN(void) { write16(0xf3d9); } -emitterT void eFSIN(void) { write16(0xfed9); } - -/* fadd ST(src) to fpu reg stack ST(0) */ -emitterT void eFADD32Rto0( x86IntRegType src ) -{ - write8( 0xD8 ); - write8( 0xC0 + src ); -} - -/* fadd ST(0) to fpu reg stack ST(src) */ -emitterT void eFADD320toR( x86IntRegType src ) -{ - write8( 0xDC ); - write8( 0xC0 + src ); -} - -/* fsub ST(src) to fpu reg stack ST(0) */ -emitterT void eFSUB32Rto0( x86IntRegType src ) -{ - write8( 0xD8 ); - write8( 0xE0 + src ); -} - -/* fsub ST(0) to fpu reg stack ST(src) */ -emitterT void eFSUB320toR( x86IntRegType src ) -{ - write8( 0xDC ); - write8( 0xE8 + src ); -} - -/* fsubp -> substract ST(0) from ST(1), store in ST(1) and POP stack */ -emitterT void eFSUBP( void ) -{ - write8( 0xDE ); - write8( 0xE9 ); -} - -/* fmul ST(src) to fpu reg stack ST(0) */ -emitterT void eFMUL32Rto0( x86IntRegType src ) -{ - write8( 0xD8 ); - write8( 0xC8 + src ); -} - -/* fmul ST(0) to fpu reg stack ST(src) */ -emitterT void eFMUL320toR( x86IntRegType src ) -{ - write8( 0xDC ); - write8( 0xC8 + src ); -} - -/* fdiv ST(src) to fpu reg stack ST(0) */ -emitterT void eFDIV32Rto0( x86IntRegType src ) -{ - write8( 0xD8 ); - write8( 0xF0 + src ); -} - -/* fdiv ST(0) to fpu reg stack ST(src) */ -emitterT void eFDIV320toR( x86IntRegType src ) -{ - write8( 0xDC ); - write8( 0xF8 + src ); -} - -emitterT void eFDIV320toRP( x86IntRegType src ) -{ - write8( 0xDE ); - write8( 0xF8 + src ); -} - -/* fadd m32 to fpu reg stack */ -emitterT void eFADD32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x0, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fsub m32 to fpu reg stack */ -emitterT void eFSUB32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x4, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fmul m32 to fpu reg stack */ -emitterT void eFMUL32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x1, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fdiv m32 to fpu reg stack */ -emitterT void eFDIV32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x6, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fabs fpu reg stack */ -emitterT void eFABS( void ) -{ - write16( 0xE1D9 ); -} - -/* fsqrt fpu reg stack */ -emitterT void eFSQRT( void ) -{ - write16( 0xFAD9 ); -} - -/* fchs fpu reg stack */ -emitterT void eFCHS( void ) -{ - write16( 0xE0D9 ); -} - -/* fcomi st, st(i) */ -emitterT void eFCOMI( x86IntRegType src ) -{ - write8( 0xDB ); - write8( 0xF0 + src ); -} - -/* fcomip st, st(i) */ -emitterT void eFCOMIP( x86IntRegType src ) -{ - write8( 0xDF ); - write8( 0xF0 + src ); -} - -/* fucomi st, st(i) */ -emitterT void eFUCOMI( x86IntRegType src ) -{ - write8( 0xDB ); - write8( 0xE8 + src ); -} - -/* fucomip st, st(i) */ -emitterT void eFUCOMIP( x86IntRegType src ) -{ - write8( 0xDF ); - write8( 0xE8 + src ); -} - -/* fcom m32 to fpu reg stack */ -emitterT void eFCOM32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x2, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* fcomp m32 to fpu reg stack */ -emitterT void eFCOMP32( u32 from ) -{ - write8( 0xD8 ); - ModRM( 0, 0x3, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -#define FCMOV32( low, high ) \ - { \ - write8( low ); \ - write8( high + from ); \ - } - -emitterT void eFCMOVB32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC0 ); } -emitterT void eFCMOVE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xC8 ); } -emitterT void eFCMOVBE32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD0 ); } -emitterT void eFCMOVU32( x86IntRegType from ) { FCMOV32( 0xDA, 0xD8 ); } -emitterT void eFCMOVNB32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC0 ); } -emitterT void eFCMOVNE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xC8 ); } -emitterT void eFCMOVNBE32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD0 ); } -emitterT void eFCMOVNU32( x86IntRegType from ) { FCMOV32( 0xDB, 0xD8 ); } diff --git a/pcsx2/x86/ix86/ix86_inlines.inl b/pcsx2/x86/ix86/ix86_inlines.inl new file mode 100644 index 0000000000..9eedcb0b1a --- /dev/null +++ b/pcsx2/x86/ix86/ix86_inlines.inl @@ -0,0 +1,225 @@ +/* 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 + */ + +/* + * ix86 core v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) + */ + +#pragma once + +// This header module contains functions which, under most circumstances, inline +// nicely with constant propagation from the compiler, resulting in little or +// no actual codegen in the majority of emitter statements. (common forms include: +// RegToReg, PointerToReg, RegToPointer). These cannot be included in the class +// definitions in the .h file because of inter-dependencies with other classes. +// (score one for C++!!) +// +// In order for MSVC to work correctly with __forceinline on class members, +// however, we need to include these methods into all source files which might +// reference them. Without this MSVC generates linker errors. Or, in other words, +// global optimization fails to resolve the externals and junk. +// (score one for MSVC!) + +#include "System.h" + +namespace x86Emitter +{ + ////////////////////////////////////////////////////////////////////////////////////////// + // x86Register Method Implementations + // + __forceinline xAddressInfo xAddressReg::operator+( const xAddressReg& right ) const + { + return xAddressInfo( *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator+( const xAddressInfo& right ) const + { + return right + *this; + } + + __forceinline xAddressInfo xAddressReg::operator+( s32 right ) const + { + return xAddressInfo( *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator*( u32 right ) const + { + return xAddressInfo( Empty, *this, right ); + } + + __forceinline xAddressInfo xAddressReg::operator<<( u32 shift ) const + { + return xAddressInfo( Empty, *this, 1< + xForwardJump::xForwardJump( JccComparisonType cctype ) : + BasePtr( (s8*)xGetPtr() + + ((OperandSize == 1) ? 2 : // j8's are always 2 bytes. + ((cctype==Jcc_Unconditional) ? 5 : 6 )) // j32's are either 5 or 6 bytes + ) + { + jASSUME( cctype != Jcc_Unknown ); + jASSUME( OperandSize == 1 || OperandSize == 4 ); + + if( OperandSize == 1 ) + xWrite8( (cctype == Jcc_Unconditional) ? 0xeb : (0x70 | cctype) ); + else + { + if( cctype == Jcc_Unconditional ) + xWrite8( 0xe9 ); + else + { + xWrite8( 0x0f ); + xWrite8( 0x80 | cctype ); + } + } + + xAdvancePtr( OperandSize ); + } + + // ------------------------------------------------------------------------ + template< typename OperandType > + void xForwardJump::SetTarget() const + { + jASSUME( BasePtr != NULL ); + + sptr displacement = (sptr)xGetPtr() - (sptr)BasePtr; + if( OperandSize == 1 ) + { + if( !is_s8( displacement ) ) + { + assert( false ); + Console::Error( "Emitter Error: Invalid short jump displacement = 0x%x", params (int)displacement ); + } + BasePtr[-1] = (s8)displacement; + } + else + { + // full displacement, no sanity checks needed :D + ((s32*)BasePtr)[-1] = displacement; + } + } + +} diff --git a/pcsx2/x86/ix86/ix86_instructions.h b/pcsx2/x86/ix86/ix86_instructions.h new file mode 100644 index 0000000000..783adc6435 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_instructions.h @@ -0,0 +1,539 @@ +/* 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 + */ + +/* + * ix86 definitions v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) + */ + +#pragma once + +namespace x86Emitter +{ + // ------------------------------------------------------------------------ + // Group 1 Instruction Class + + extern const Internal::xImpl_G1Logic xAND; + extern const Internal::xImpl_G1Logic xOR; + extern const Internal::xImpl_G1Logic xXOR; + + extern const Internal::xImpl_G1Arith xADD; + extern const Internal::xImpl_G1Arith xSUB; + extern const Internal::xImpl_G1Compare xCMP; + + extern const Internal::xImpl_Group1 xADC; + extern const Internal::xImpl_Group1 xSBB; + + // ------------------------------------------------------------------------ + // Group 2 Instruction Class + // + // Optimization Note: For Imm forms, we ignore the instruction if the shift count is + // zero. This is a safe optimization since any zero-value shift does not affect any + // flags. + + extern const Internal::MovImplAll xMOV; + extern const Internal::xImpl_Test xTEST; + + extern const Internal::Group2ImplAll xROL; + extern const Internal::Group2ImplAll xROR; + extern const Internal::Group2ImplAll xRCL; + extern const Internal::Group2ImplAll xRCR; + extern const Internal::Group2ImplAll xSHL; + extern const Internal::Group2ImplAll xSHR; + extern const Internal::Group2ImplAll xSAR; + + // ------------------------------------------------------------------------ + // Group 3 Instruction Class + + extern const Internal::xImpl_Group3 xNOT; + extern const Internal::xImpl_Group3 xNEG; + extern const Internal::xImpl_Group3 xUMUL; + extern const Internal::xImpl_Group3 xUDIV; + extern const Internal::xImpl_iDiv xDIV; + extern const Internal::xImpl_iMul xMUL; + + extern const Internal::xImpl_IncDec xINC; + extern const Internal::xImpl_IncDec xDEC; + + extern const Internal::MovExtendImplAll xMOVZX; + extern const Internal::MovExtendImplAll xMOVSX; + + extern const Internal::DwordShiftImplAll xSHLD; + extern const Internal::DwordShiftImplAll xSHRD; + + extern const Internal::xImpl_Group8 xBT; + extern const Internal::xImpl_Group8 xBTR; + extern const Internal::xImpl_Group8 xBTS; + extern const Internal::xImpl_Group8 xBTC; + + extern const Internal::xImpl_JmpCall xJMP; + extern const Internal::xImpl_JmpCall xCALL; + + extern const Internal::xImpl_BitScan<0xbc> xBSF; + extern const Internal::xImpl_BitScan<0xbd> xBSR; + + // ------------------------------------------------------------------------ + extern const Internal::CMovImplGeneric xCMOV; + + extern const Internal::CMovImplAll xCMOVA; + extern const Internal::CMovImplAll xCMOVAE; + extern const Internal::CMovImplAll xCMOVB; + extern const Internal::CMovImplAll xCMOVBE; + + extern const Internal::CMovImplAll xCMOVG; + extern const Internal::CMovImplAll xCMOVGE; + extern const Internal::CMovImplAll xCMOVL; + extern const Internal::CMovImplAll xCMOVLE; + + extern const Internal::CMovImplAll xCMOVZ; + extern const Internal::CMovImplAll xCMOVE; + extern const Internal::CMovImplAll xCMOVNZ; + extern const Internal::CMovImplAll xCMOVNE; + + extern const Internal::CMovImplAll xCMOVO; + extern const Internal::CMovImplAll xCMOVNO; + extern const Internal::CMovImplAll xCMOVC; + extern const Internal::CMovImplAll xCMOVNC; + + extern const Internal::CMovImplAll xCMOVS; + extern const Internal::CMovImplAll xCMOVNS; + extern const Internal::CMovImplAll xCMOVPE; + extern const Internal::CMovImplAll xCMOVPO; + + // ------------------------------------------------------------------------ + extern const Internal::SetImplGeneric xSET; + + extern const Internal::SetImplAll xSETA; + extern const Internal::SetImplAll xSETAE; + extern const Internal::SetImplAll xSETB; + extern const Internal::SetImplAll xSETBE; + + extern const Internal::SetImplAll xSETG; + extern const Internal::SetImplAll xSETGE; + extern const Internal::SetImplAll xSETL; + extern const Internal::SetImplAll xSETLE; + + extern const Internal::SetImplAll xSETZ; + extern const Internal::SetImplAll xSETE; + extern const Internal::SetImplAll xSETNZ; + extern const Internal::SetImplAll xSETNE; + + extern const Internal::SetImplAll xSETO; + extern const Internal::SetImplAll xSETNO; + extern const Internal::SetImplAll xSETC; + extern const Internal::SetImplAll xSETNC; + + extern const Internal::SetImplAll xSETS; + extern const Internal::SetImplAll xSETNS; + extern const Internal::SetImplAll xSETPE; + extern const Internal::SetImplAll xSETPO; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Miscellaneous Instructions + // These are all defined inline or in ix86.cpp. + // + + extern void xBSWAP( const xRegister32& to ); + + // ----- Lea Instructions (Load Effective Address) ----- + // Note: alternate (void*) forms of these instructions are not provided since those + // forms are functionally equivalent to Mov reg,imm, and thus better written as MOVs + // instead. + + extern void xLEA( xRegister32 to, const ModSibBase& src, bool preserve_flags=false ); + extern void xLEA( xRegister16 to, const ModSibBase& src, bool preserve_flags=false ); + + // ----- Push / Pop Instructions ----- + // Note: pushad/popad implementations are intentionally left out. The instructions are + // invalid in x64, and are super slow on x32. Use multiple Push/Pop instructions instead. + + extern void xPOP( const ModSibBase& from ); + extern void xPUSH( const ModSibBase& from ); + + extern void xPOP( xRegister32 from ); + extern void xPOP( void* from ); + + extern void xPUSH( u32 imm ); + extern void xPUSH( xRegister32 from ); + extern void xPUSH( void* from ); + + // pushes the EFLAGS register onto the stack + extern void xPUSHFD(); + // pops the EFLAGS register from the stack + extern void xPOPFD(); + + // ----- Miscellaneous Instructions ----- + // Various Instructions with no parameter and no special encoding logic. + + extern void xRET(); + extern void xCBW(); + extern void xCWD(); + extern void xCDQ(); + extern void xCWDE(); + + extern void xLAHF(); + extern void xSAHF(); + + extern void xSTC(); + extern void xCLC(); + + // NOP 1-byte + extern void xNOP(); + + ////////////////////////////////////////////////////////////////////////////////////////// + // JMP / Jcc Instructions! + + extern void xJcc( JccComparisonType comparison, const void* target ); + + // ------------------------------------------------------------------------ + // Conditional jumps to fixed targets. + // Jumps accept any pointer as a valid target (function or data), and will generate either + // 8 or 32 bit displacement versions of the jump, depending on relative displacement of + // the target (efficient!) + // + + template< typename T > __forceinline void xJE( T* func ) { xJcc( Jcc_Equal, (void*)(uptr)func ); } + template< typename T > __forceinline void xJZ( T* func ) { xJcc( Jcc_Zero, (void*)(uptr)func ); } + template< typename T > __forceinline void xJNE( T* func ) { xJcc( Jcc_NotEqual, (void*)(uptr)func ); } + template< typename T > __forceinline void xJNZ( T* func ) { xJcc( Jcc_NotZero, (void*)(uptr)func ); } + + template< typename T > __forceinline void xJO( T* func ) { xJcc( Jcc_Overflow, (void*)(uptr)func ); } + template< typename T > __forceinline void xJNO( T* func ) { xJcc( Jcc_NotOverflow, (void*)(uptr)func ); } + template< typename T > __forceinline void xJC( T* func ) { xJcc( Jcc_Carry, (void*)(uptr)func ); } + template< typename T > __forceinline void xJNC( T* func ) { xJcc( Jcc_NotCarry, (void*)(uptr)func ); } + template< typename T > __forceinline void xJS( T* func ) { xJcc( Jcc_Signed, (void*)(uptr)func ); } + template< typename T > __forceinline void xJNS( T* func ) { xJcc( Jcc_Unsigned, (void*)(uptr)func ); } + + template< typename T > __forceinline void xJPE( T* func ) { xJcc( Jcc_ParityEven, (void*)(uptr)func ); } + template< typename T > __forceinline void xJPO( T* func ) { xJcc( Jcc_ParityOdd, (void*)(uptr)func ); } + + template< typename T > __forceinline void xJL( T* func ) { xJcc( Jcc_Less, (void*)(uptr)func ); } + template< typename T > __forceinline void xJLE( T* func ) { xJcc( Jcc_LessOrEqual, (void*)(uptr)func ); } + template< typename T > __forceinline void xJG( T* func ) { xJcc( Jcc_Greater, (void*)(uptr)func ); } + template< typename T > __forceinline void xJGE( T* func ) { xJcc( Jcc_GreaterOrEqual, (void*)(uptr)func ); } + + template< typename T > __forceinline void xJB( T* func ) { xJcc( Jcc_Below, (void*)(uptr)func ); } + template< typename T > __forceinline void xJBE( T* func ) { xJcc( Jcc_BelowOrEqual, (void*)(uptr)func ); } + template< typename T > __forceinline void xJA( T* func ) { xJcc( Jcc_Above, (void*)(uptr)func ); } + template< typename T > __forceinline void xJAE( T* func ) { xJcc( Jcc_AboveOrEqual, (void*)(uptr)func ); } + + // ------------------------------------------------------------------------ + // Forward Jump Helpers (act as labels!) + +#define DEFINE_FORWARD_JUMP( label, cond ) \ + template< typename OperandType > \ + class xForward##label : public xForwardJump \ + { \ + public: \ + xForward##label() : xForwardJump( cond ) {} \ + }; + + // ------------------------------------------------------------------------ + // Note: typedefs below are defined individually in order to appease Intellisense + // resolution. Including them into the class definition macro above breaks it. + + typedef xForwardJump xForwardJump8; + typedef xForwardJump xForwardJump32; + + DEFINE_FORWARD_JUMP( JA, Jcc_Above ); + DEFINE_FORWARD_JUMP( JB, Jcc_Below ); + DEFINE_FORWARD_JUMP( JAE, Jcc_AboveOrEqual ); + DEFINE_FORWARD_JUMP( JBE, Jcc_BelowOrEqual ); + + typedef xForwardJA xForwardJA8; + typedef xForwardJA xForwardJA32; + typedef xForwardJB xForwardJB8; + typedef xForwardJB xForwardJB32; + typedef xForwardJAE xForwardJAE8; + typedef xForwardJAE xForwardJAE32; + typedef xForwardJBE xForwardJBE8; + typedef xForwardJBE xForwardJBE32; + + DEFINE_FORWARD_JUMP( JG, Jcc_Greater ); + DEFINE_FORWARD_JUMP( JL, Jcc_Less ); + DEFINE_FORWARD_JUMP( JGE, Jcc_GreaterOrEqual ); + DEFINE_FORWARD_JUMP( JLE, Jcc_LessOrEqual ); + + typedef xForwardJG xForwardJG8; + typedef xForwardJG xForwardJG32; + typedef xForwardJL xForwardJL8; + typedef xForwardJL xForwardJL32; + typedef xForwardJGE xForwardJGE8; + typedef xForwardJGE xForwardJGE32; + typedef xForwardJLE xForwardJLE8; + typedef xForwardJLE xForwardJLE32; + + DEFINE_FORWARD_JUMP( JZ, Jcc_Zero ); + DEFINE_FORWARD_JUMP( JE, Jcc_Equal ); + DEFINE_FORWARD_JUMP( JNZ, Jcc_NotZero ); + DEFINE_FORWARD_JUMP( JNE, Jcc_NotEqual ); + + typedef xForwardJZ xForwardJZ8; + typedef xForwardJZ xForwardJZ32; + typedef xForwardJE xForwardJE8; + typedef xForwardJE xForwardJE32; + typedef xForwardJNZ xForwardJNZ8; + typedef xForwardJNZ xForwardJNZ32; + typedef xForwardJNE xForwardJNE8; + typedef xForwardJNE xForwardJNE32; + + DEFINE_FORWARD_JUMP( JS, Jcc_Signed ); + DEFINE_FORWARD_JUMP( JNS, Jcc_Unsigned ); + + typedef xForwardJS xForwardJS8; + typedef xForwardJS xForwardJS32; + typedef xForwardJNS xForwardJNS8; + typedef xForwardJNS xForwardJNS32; + + DEFINE_FORWARD_JUMP( JO, Jcc_Overflow ); + DEFINE_FORWARD_JUMP( JNO, Jcc_NotOverflow ); + + typedef xForwardJO xForwardJO8; + typedef xForwardJO xForwardJO32; + typedef xForwardJNO xForwardJNO8; + typedef xForwardJNO xForwardJNO32; + + DEFINE_FORWARD_JUMP( JC, Jcc_Carry ); + DEFINE_FORWARD_JUMP( JNC, Jcc_NotCarry ); + + typedef xForwardJC xForwardJC8; + typedef xForwardJC xForwardJC32; + typedef xForwardJNC xForwardJNC8; + typedef xForwardJNC xForwardJNC32; + + DEFINE_FORWARD_JUMP( JPE, Jcc_ParityEven ); + DEFINE_FORWARD_JUMP( JPO, Jcc_ParityOdd ); + + typedef xForwardJPE xForwardJPE8; + typedef xForwardJPE xForwardJPE32; + typedef xForwardJPO xForwardJPO8; + typedef xForwardJPO xForwardJPO32; + + // ------------------------------------------------------------------------ + + extern void xEMMS(); + extern void xSTMXCSR( u32* dest ); + extern void xLDMXCSR( const u32* src ); + + extern void xMOVDZX( const xRegisterSSE& to, const xRegister32& from ); + extern void xMOVDZX( const xRegisterSSE& to, const void* src ); + extern void xMOVDZX( const xRegisterSSE& to, const ModSibBase& src ); + + extern void xMOVDZX( const xRegisterMMX& to, const xRegister32& from ); + extern void xMOVDZX( const xRegisterMMX& to, const void* src ); + extern void xMOVDZX( const xRegisterMMX& to, const ModSibBase& src ); + + extern void xMOVD( const xRegister32& to, const xRegisterSSE& from ); + extern void xMOVD( void* dest, const xRegisterSSE& from ); + extern void xMOVD( const ModSibBase& dest, const xRegisterSSE& from ); + + extern void xMOVD( const xRegister32& to, const xRegisterMMX& from ); + extern void xMOVD( void* dest, const xRegisterMMX& from ); + extern void xMOVD( const ModSibBase& dest, const xRegisterMMX& from ); + + extern void xMOVQ( const xRegisterMMX& to, const xRegisterMMX& from ); + extern void xMOVQ( const xRegisterMMX& to, const xRegisterSSE& from ); + extern void xMOVQ( const xRegisterSSE& to, const xRegisterMMX& from ); + + extern void xMOVQ( void* dest, const xRegisterSSE& from ); + extern void xMOVQ( const ModSibBase& dest, const xRegisterSSE& from ); + extern void xMOVQ( void* dest, const xRegisterMMX& from ); + extern void xMOVQ( const ModSibBase& dest, const xRegisterMMX& from ); + extern void xMOVQ( const xRegisterMMX& to, const void* src ); + extern void xMOVQ( const xRegisterMMX& to, const ModSibBase& src ); + + extern void xMOVQZX( const xRegisterSSE& to, const void* src ); + extern void xMOVQZX( const xRegisterSSE& to, const ModSibBase& src ); + extern void xMOVQZX( const xRegisterSSE& to, const xRegisterSSE& from ); + + extern void xMOVSS( const xRegisterSSE& to, const xRegisterSSE& from ); + extern void xMOVSS( const void* to, const xRegisterSSE& from ); + extern void xMOVSS( const ModSibBase& to, const xRegisterSSE& from ); + extern void xMOVSD( const xRegisterSSE& to, const xRegisterSSE& from ); + extern void xMOVSD( const void* to, const xRegisterSSE& from ); + extern void xMOVSD( const ModSibBase& to, const xRegisterSSE& from ); + + extern void xMOVSSZX( const xRegisterSSE& to, const void* from ); + extern void xMOVSSZX( const xRegisterSSE& to, const ModSibBase& from ); + extern void xMOVSDZX( const xRegisterSSE& to, const void* from ); + extern void xMOVSDZX( const xRegisterSSE& to, const ModSibBase& from ); + + extern void xMOVNTDQA( const xRegisterSSE& to, const void* from ); + extern void xMOVNTDQA( const xRegisterSSE& to, const ModSibBase& from ); + extern void xMOVNTDQ( void* to, const xRegisterSSE& from ); + extern void xMOVNTDQA( const ModSibBase& to, const xRegisterSSE& from ); + + extern void xMOVNTPD( void* to, const xRegisterSSE& from ); + extern void xMOVNTPD( const ModSibBase& to, const xRegisterSSE& from ); + extern void xMOVNTPS( void* to, const xRegisterSSE& from ); + extern void xMOVNTPS( const ModSibBase& to, const xRegisterSSE& from ); + extern void xMOVNTQ( void* to, const xRegisterMMX& from ); + extern void xMOVNTQ( const ModSibBase& to, const xRegisterMMX& from ); + + extern void xMOVMSKPS( const xRegister32& to, const xRegisterSSE& from ); + extern void xMOVMSKPD( const xRegister32& to, const xRegisterSSE& from ); + + extern void xMASKMOV( const xRegisterSSE& to, const xRegisterSSE& from ); + extern void xMASKMOV( const xRegisterMMX& to, const xRegisterMMX& from ); + extern void xPMOVMSKB( const xRegister32& to, const xRegisterSSE& from ); + extern void xPMOVMSKB( const xRegister32& to, const xRegisterMMX& from ); + extern void xPALIGNR( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 ); + extern void xPALIGNR( const xRegisterMMX& to, const xRegisterMMX& from, u8 imm8 ); + + // ------------------------------------------------------------------------ + + extern const Internal::SimdImpl_MoveSSE<0x00,true> xMOVAPS; + extern const Internal::SimdImpl_MoveSSE<0x00,false> xMOVUPS; + +#ifdef ALWAYS_USE_MOVAPS + extern const Internal::SimdImpl_MoveSSE<0,true> xMOVDQA; + extern const Internal::SimdImpl_MoveSSE<0,false> xMOVDQU; + extern const Internal::SimdImpl_MoveSSE<0,true> xMOVAPD; + extern const Internal::SimdImpl_MoveSSE<0,false> xMOVUPD; +#else + extern const Internal::SimdImpl_MoveDQ<0x66, 0x6f, 0x7f> xMOVDQA; + extern const Internal::SimdImpl_MoveDQ<0xf3, 0x6f, 0x7f> xMOVDQU; + extern const Internal::SimdImpl_MoveSSE<0x66,true> xMOVAPD; + extern const Internal::SimdImpl_MoveSSE<0x66,false> xMOVUPD; +#endif + + extern const Internal::MovhlImpl_RtoR<0x16> xMOVLH; + extern const Internal::MovhlImpl_RtoR<0x12> xMOVHL; + + extern const Internal::MovhlImplAll<0x16> xMOVH; + extern const Internal::MovhlImplAll<0x12> xMOVL; + + extern const Internal::SimdImpl_DestRegSSE<0xf3,0x12> xMOVSLDUP; + extern const Internal::SimdImpl_DestRegSSE<0xf3,0x16> xMOVSHDUP; + + extern void xINSERTPS( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 ); + extern void xINSERTPS( const xRegisterSSE& to, const u32* from, u8 imm8 ); + extern void xINSERTPS( const xRegisterSSE& to, const ModSibStrict& from, u8 imm8 ); + + extern void xEXTRACTPS( const xRegister32& to, const xRegisterSSE& from, u8 imm8 ); + extern void xEXTRACTPS( u32* dest, const xRegisterSSE& from, u8 imm8 ); + extern void xEXTRACTPS( const ModSibStrict& dest, const xRegisterSSE& from, u8 imm8 ); + + // ------------------------------------------------------------------------ + + extern const Internal::SimdImpl_DestRegEither<0x66,0xdb> xPAND; + extern const Internal::SimdImpl_DestRegEither<0x66,0xdf> xPANDN; + extern const Internal::SimdImpl_DestRegEither<0x66,0xeb> xPOR; + extern const Internal::SimdImpl_DestRegEither<0x66,0xef> xPXOR; + + extern const Internal::SimdImpl_AndNot xANDN; + + extern const Internal::SimdImpl_UcomI<0x66,0x2e> xUCOMI; + extern const Internal::SimdImpl_rSqrt<0x53> xRCP; + extern const Internal::SimdImpl_rSqrt<0x52> xRSQRT; + extern const Internal::SimdImpl_Sqrt<0x51> xSQRT; + + extern const Internal::SimdImpl_MinMax<0x5f> xMAX; + extern const Internal::SimdImpl_MinMax<0x5d> xMIN; + extern const Internal::SimdImpl_Shuffle<0xc6> xSHUF; + + // ------------------------------------------------------------------------ + + extern const Internal::SimdImpl_DestRegSSE<0x66,0x1738> xPTEST; + + extern const Internal::SimdImpl_Compare xCMPEQ; + extern const Internal::SimdImpl_Compare xCMPLT; + extern const Internal::SimdImpl_Compare xCMPLE; + extern const Internal::SimdImpl_Compare xCMPUNORD; + extern const Internal::SimdImpl_Compare xCMPNE; + extern const Internal::SimdImpl_Compare xCMPNLT; + extern const Internal::SimdImpl_Compare xCMPNLE; + extern const Internal::SimdImpl_Compare xCMPORD; + + // ------------------------------------------------------------------------ + // OMG Evil. I went cross-eyed an hour ago doing this. + // + extern const Internal::SimdImpl_DestRegStrict<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD; + extern const Internal::SimdImpl_DestRegStrict<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS; + + extern const Internal::SimdImpl_DestRegStrict<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ; + extern const Internal::SimdImpl_DestRegStrict<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI; + extern const Internal::SimdImpl_DestRegStrict<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS; + + extern const Internal::SimdImpl_DestRegStrict<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD; + extern const Internal::SimdImpl_DestRegStrict<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS; + + extern const Internal::SimdImpl_DestRegStrict<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ; + extern const Internal::SimdImpl_DestRegStrict<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD; + extern const Internal::SimdImpl_DestRegStrict<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI; + + extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI; + extern const Internal::SimdImpl_DestRegStrict<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS; + extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD; + extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS; + + extern const Internal::SimdImpl_DestRegStrict<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD; + extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI; + + extern const Internal::SimdImpl_DestRegStrict<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ; + extern const Internal::SimdImpl_DestRegStrict<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI; + extern const Internal::SimdImpl_DestRegStrict<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ; + extern const Internal::SimdImpl_DestRegStrict<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI; + + extern const Internal::SimdImpl_DestRegStrict<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI; + extern const Internal::SimdImpl_DestRegStrict<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI; + + // ------------------------------------------------------------------------ + + extern const Internal::SimdImpl_Shift<0xf0, 6> xPSLL; + extern const Internal::SimdImpl_Shift<0xd0, 2> xPSRL; + extern const Internal::SimdImpl_ShiftWithoutQ<0xe0, 4> xPSRA; + + extern const Internal::SimdImpl_AddSub<0xdc, 0xd4> xPADD; + extern const Internal::SimdImpl_AddSub<0xd8, 0xfb> xPSUB; + extern const Internal::SimdImpl_PMinMax<0xde,0x3c> xPMAX; + extern const Internal::SimdImpl_PMinMax<0xda,0x38> xPMIN; + + extern const Internal::SimdImpl_PMul xPMUL; + extern const Internal::SimdImpl_PCompare xPCMP; + extern const Internal::SimdImpl_PShuffle xPSHUF; + extern const Internal::SimdImpl_PUnpack xPUNPCK; + extern const Internal::SimdImpl_Unpack xUNPCK; + extern const Internal::SimdImpl_Pack xPACK; + + extern const Internal::SimdImpl_PAbsolute xPABS; + extern const Internal::SimdImpl_PSign xPSIGN; + extern const Internal::SimdImpl_PInsert xPINSR; + extern const Internal::SimdImpl_PExtract xPEXTR; + extern const Internal::SimdImpl_PMultAdd xPMADD; + extern const Internal::SimdImpl_HorizAdd xHADD; + + extern const Internal::SimdImpl_Blend xBLEND; + extern const Internal::SimdImpl_DotProduct xDP; + extern const Internal::SimdImpl_Round xROUND; + + extern const Internal::SimdImpl_PMove xPMOVSX; + extern const Internal::SimdImpl_PMove xPMOVZX; + +} + diff --git a/pcsx2/x86/ix86/ix86_internal.h b/pcsx2/x86/ix86/ix86_internal.h new file mode 100644 index 0000000000..b8ed9269ca --- /dev/null +++ b/pcsx2/x86/ix86/ix86_internal.h @@ -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 + +#include "ix86_types.h" +#include "ix86_instructions.h" diff --git a/pcsx2/x86/ix86/ix86_jmp.cpp b/pcsx2/x86/ix86/ix86_jmp.cpp new file mode 100644 index 0000000000..ab5611ce9e --- /dev/null +++ b/pcsx2/x86/ix86/ix86_jmp.cpp @@ -0,0 +1,124 @@ +/* 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 + */ + +/* + * ix86 core v0.9.0 + * + * Original Authors (v0.6.2 and prior): + * linuzappz + * alexey silinov + * goldfinger + * zerofrog(@gmail.com) + * + * Authors of v0.9.0: + * Jake.Stine(@gmail.com) + * cottonvibes(@gmail.com) + * sudonim(1@gmail.com) + */ + +#include "PrecompiledHeader.h" + +#include "System.h" +#include "ix86_internal.h" + +namespace x86Emitter { + +using namespace Internal; + +const xImpl_JmpCall xJMP; +const xImpl_JmpCall xCALL; + +// ------------------------------------------------------------------------ +void xSmartJump::SetTarget() +{ + u8* target = xGetPtr(); + if( m_baseptr == NULL ) return; + + xSetPtr( m_baseptr ); + u8* const saveme = m_baseptr + GetMaxInstructionSize(); + xJccKnownTarget( m_cc, target, true ); + + // Copy recompiled data inward if the jump instruction didn't fill the + // alloted buffer (means that we optimized things to a j8!) + + const int spacer = (sptr)saveme - (sptr)xGetPtr(); + if( spacer != 0 ) + { + u8* destpos = xGetPtr(); + const int copylen = (sptr)target - (sptr)saveme; + + memcpy_fast( destpos, saveme, copylen ); + xSetPtr( target - spacer ); + } +} + +xSmartJump::~xSmartJump() +{ + SetTarget(); + m_baseptr = NULL; // just in case (sometimes helps in debugging too) +} + + +// ------------------------------------------------------------------------ +// Writes a jump at the current x86Ptr, which targets a pre-established target address. +// (usually a backwards jump) +// +// slideForward - used internally by xSmartJump to indicate that the jump target is going +// to slide forward in the event of an 8 bit displacement. +// +__emitinline void Internal::xJccKnownTarget( JccComparisonType comparison, const void* target, bool slideForward ) +{ + // Calculate the potential j8 displacement first, assuming an instruction length of 2: + sptr displacement8 = (sptr)target - ((sptr)xGetPtr() + 2); + + const int slideVal = slideForward ? ((comparison == Jcc_Unconditional) ? 3 : 4) : 0; + displacement8 -= slideVal; + + // if the following assert fails it means we accidentally used slideForard on a backward + // jump (which is an invalid operation since there's nothing to slide forward). + if( slideForward ) jASSUME( displacement8 >= 0 ); + + if( is_s8( displacement8 ) ) + { + xWrite8( (comparison == Jcc_Unconditional) ? 0xeb : (0x70 | comparison) ); + xWrite( displacement8 ); + } + else + { + // Perform a 32 bit jump instead. :( + + if( comparison == Jcc_Unconditional ) + xWrite8( 0xe9 ); + else + { + xWrite8( 0x0f ); + xWrite8( 0x80 | comparison ); + } + xWrite( (sptr)target - ((sptr)xGetPtr() + 4) ); + } +} + +// Low-level jump instruction! Specify a comparison type and a target in void* form, and +// a jump (either 8 or 32 bit) is generated. +__emitinline void xJcc( JccComparisonType comparison, const void* target ) +{ + xJccKnownTarget( comparison, target, false ); +} + +} + diff --git a/pcsx2/x86/ix86/ix86_legacy.cpp b/pcsx2/x86/ix86/ix86_legacy.cpp new file mode 100644 index 0000000000..8bf4bd3c4a --- /dev/null +++ b/pcsx2/x86/ix86/ix86_legacy.cpp @@ -0,0 +1,733 @@ +/* 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 +*/ +/* +* ix86 core v0.6.2 +* Authors: linuzappz +* alexey silinov +* goldfinger +* zerofrog(@gmail.com) +* cottonvibes(@gmail.com) +*/ + +//------------------------------------------------------------------ +// ix86 legacy emitter functions +//------------------------------------------------------------------ + +#include "PrecompiledHeader.h" +#include "System.h" +#include "ix86_legacy_internal.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// +emitterT void ModRM( uint mod, uint reg, uint rm ) +{ + // Note: Following ASSUMEs are for legacy support only. + // The new emitter performs these sanity checks during operand construction, so these + // assertions can probably be removed once all legacy emitter code has been removed. + jASSUME( mod < 4 ); + jASSUME( reg < 8 ); + jASSUME( rm < 8 ); + xWrite8( (mod << 6) | (reg << 3) | rm ); +} + +emitterT void SibSB( uint ss, uint index, uint base ) +{ + // Note: Following ASSUMEs are for legacy support only. + // The new emitter performs these sanity checks during operand construction, so these + // assertions can probably be removed once all legacy emitter code has been removed. + jASSUME( ss < 4 ); + jASSUME( index < 8 ); + jASSUME( base < 8 ); + xWrite8( (ss << 6) | (index << 3) | base ); +} + +using namespace x86Emitter; + +template< typename ImmType > +static __forceinline xRegister _reghlp( x86IntRegType src ) +{ + return xRegister( src ); +} + +static __forceinline ModSibBase _mrmhlp( x86IntRegType src ) +{ + return ptr[_reghlp(src)]; +} + +template< typename ImmType > +static __forceinline ModSibStrict _mhlp( x86IntRegType src ) +{ + return ModSibStrict( xAddressReg::Empty, xAddressReg(src) ); +} + +template< typename ImmType > +static __forceinline ModSibStrict _mhlp2( x86IntRegType src1, x86IntRegType src2 ) +{ + return ModSibStrict( xAddressReg(src2), xAddressReg(src1) ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// +#define DEFINE_LEGACY_HELPER( cod, bits ) \ + emitterT void cod##bits##RtoR( x86IntRegType to, x86IntRegType from ) { x##cod( _reghlp(to), _reghlp(from) ); } \ + emitterT void cod##bits##ItoR( x86IntRegType to, u##bits imm ) { x##cod( _reghlp(to), imm ); } \ + emitterT void cod##bits##MtoR( x86IntRegType to, uptr from ) { x##cod( _reghlp(to), (void*)from ); } \ + emitterT void cod##bits##RtoM( uptr to, x86IntRegType from ) { x##cod( (void*)to, _reghlp(from) ); } \ + emitterT void cod##bits##ItoM( uptr to, u##bits imm ) { x##cod( ptr##bits[to], imm ); } \ + emitterT void cod##bits##ItoRm( x86IntRegType to, u##bits imm, int offset ) { x##cod( _mhlp(to) + offset, imm ); } \ + emitterT void cod##bits##RmtoR( x86IntRegType to, x86IntRegType from, int offset ) { x##cod( _reghlp(to), _mhlp(from) + offset ); } \ + emitterT void cod##bits##RtoRm( x86IntRegType to, x86IntRegType from, int offset ) { x##cod( _mhlp(to) + offset, _reghlp(from) ); } \ + emitterT void cod##bits##RtoRmS( x86IntRegType to1, x86IntRegType to2, x86IntRegType from, int offset ) \ + { x##cod( _mhlp2(to1,to2) + offset, _reghlp(from) ); } \ + emitterT void cod##bits##RmStoR( x86IntRegType to, x86IntRegType from1, x86IntRegType from2, int offset ) \ + { x##cod( _reghlp(to), _mhlp2(from1,from2) + offset ); } + +#define DEFINE_LEGACY_SHIFT_HELPER( cod, bits ) \ + emitterT void cod##bits##CLtoR( x86IntRegType to ) { x##cod( _reghlp(to), cl ); } \ + emitterT void cod##bits##ItoR( x86IntRegType to, u8 imm ) { x##cod( _reghlp(to), imm ); } \ + emitterT void cod##bits##CLtoM( uptr to ) { x##cod( ptr##bits[to], cl ); } \ + emitterT void cod##bits##ItoM( uptr to, u8 imm ) { x##cod( ptr##bits[to], imm ); } \ + emitterT void cod##bits##ItoRm( x86IntRegType to, u8 imm, int offset ) { x##cod( _mhlp(to) + offset, imm ); } \ + emitterT void cod##bits##CLtoRm( x86IntRegType to, int offset ) { x##cod( _mhlp(to) + offset, cl ); } + +#define DEFINE_LEGACY_ONEREG_HELPER( cod, bits ) \ + emitterT void cod##bits##R( x86IntRegType to ) { x##cod( _reghlp(to) ); } \ + emitterT void cod##bits##M( uptr to ) { x##cod( ptr##bits[to] ); } \ + emitterT void cod##bits##Rm( x86IntRegType to, uptr offset ) { x##cod( _mhlp(to) + offset ); } + +//emitterT void cod##bits##RtoRmS( x86IntRegType to1, x86IntRegType to2, x86IntRegType from, int offset ) \ +// { cod( _mhlp2(to1,to2) + offset, _reghlp(from) ); } \ + +#define DEFINE_OPCODE_LEGACY( cod ) \ + DEFINE_LEGACY_HELPER( cod, 32 ) \ + DEFINE_LEGACY_HELPER( cod, 16 ) \ + DEFINE_LEGACY_HELPER( cod, 8 ) + +#define DEFINE_OPCODE_SHIFT_LEGACY( cod ) \ + DEFINE_LEGACY_SHIFT_HELPER( cod, 32 ) \ + DEFINE_LEGACY_SHIFT_HELPER( cod, 16 ) \ + DEFINE_LEGACY_SHIFT_HELPER( cod, 8 ) + +#define DEFINE_OPCODE_ONEREG_LEGACY( cod ) \ + DEFINE_LEGACY_ONEREG_HELPER( cod, 32 ) \ + DEFINE_LEGACY_ONEREG_HELPER( cod, 16 ) \ + DEFINE_LEGACY_ONEREG_HELPER( cod, 8 ) + +////////////////////////////////////////////////////////////////////////////////////////// +// +DEFINE_OPCODE_LEGACY( ADD ) +DEFINE_OPCODE_LEGACY( CMP ) +DEFINE_OPCODE_LEGACY( OR ) +DEFINE_OPCODE_LEGACY( ADC ) +DEFINE_OPCODE_LEGACY( SBB ) +DEFINE_OPCODE_LEGACY( AND ) +DEFINE_OPCODE_LEGACY( SUB ) +DEFINE_OPCODE_LEGACY( XOR ) + +DEFINE_OPCODE_SHIFT_LEGACY( ROL ) +DEFINE_OPCODE_SHIFT_LEGACY( ROR ) +DEFINE_OPCODE_SHIFT_LEGACY( RCL ) +DEFINE_OPCODE_SHIFT_LEGACY( RCR ) +DEFINE_OPCODE_SHIFT_LEGACY( SHL ) +DEFINE_OPCODE_SHIFT_LEGACY( SHR ) +DEFINE_OPCODE_SHIFT_LEGACY( SAR ) + +DEFINE_OPCODE_LEGACY( MOV ) + +DEFINE_OPCODE_ONEREG_LEGACY( INC ) +DEFINE_OPCODE_ONEREG_LEGACY( DEC ) +DEFINE_OPCODE_ONEREG_LEGACY( NOT ) +DEFINE_OPCODE_ONEREG_LEGACY( NEG ) + + +// ------------------------------------------------------------------------ +#define DEFINE_LEGACY_MOVEXTEND( form, destbits, srcbits ) \ + emitterT void MOV##form##destbits##R##srcbits##toR( x86IntRegType to, x86IntRegType from ) { xMOV##form( xRegister##destbits( to ), xRegister##srcbits( from ) ); } \ + emitterT void MOV##form##destbits##Rm##srcbits##toR( x86IntRegType to, x86IntRegType from, int offset ) { xMOV##form( xRegister##destbits( to ), ptr##srcbits[xAddressReg( from ) + offset] ); } \ + emitterT void MOV##form##destbits##M##srcbits##toR( x86IntRegType to, u32 from ) { xMOV##form( xRegister##destbits( to ), ptr##srcbits[from] ); } + +DEFINE_LEGACY_MOVEXTEND( SX, 32, 16 ) +DEFINE_LEGACY_MOVEXTEND( ZX, 32, 16 ) +DEFINE_LEGACY_MOVEXTEND( SX, 32, 8 ) +DEFINE_LEGACY_MOVEXTEND( ZX, 32, 8 ) + +DEFINE_LEGACY_MOVEXTEND( SX, 16, 8 ) +DEFINE_LEGACY_MOVEXTEND( ZX, 16, 8 ) + +emitterT void TEST32ItoR( x86IntRegType to, u32 from ) { xTEST( xRegister32(to), from ); } +emitterT void TEST32ItoM( uptr to, u32 from ) { xTEST( ptr32[to], from ); } +emitterT void TEST32RtoR( x86IntRegType to, x86IntRegType from ) { xTEST( xRegister32(to), xRegister32(from) ); } +emitterT void TEST32ItoRm( x86IntRegType to, u32 from ) { xTEST( ptr32[xAddressReg(to)], from ); } + +emitterT void TEST16ItoR( x86IntRegType to, u16 from ) { xTEST( xRegister16(to), from ); } +emitterT void TEST16ItoM( uptr to, u16 from ) { xTEST( ptr16[to], from ); } +emitterT void TEST16RtoR( x86IntRegType to, x86IntRegType from ) { xTEST( xRegister16(to), xRegister16(from) ); } +emitterT void TEST16ItoRm( x86IntRegType to, u16 from ) { xTEST( ptr16[xAddressReg(to)], from ); } + +emitterT void TEST8ItoR( x86IntRegType to, u8 from ) { xTEST( xRegister8(to), from ); } +emitterT void TEST8ItoM( uptr to, u8 from ) { xTEST( ptr8[to], from ); } +emitterT void TEST8RtoR( x86IntRegType to, x86IntRegType from ) { xTEST( xRegister8(to), xRegister8(from) ); } +emitterT void TEST8ItoRm( x86IntRegType to, u8 from ) { xTEST( ptr8[xAddressReg(to)], from ); } + +// mov r32 to [r32<(to), from ); +} + +emitterT void AND32I8toM( uptr to, s8 from ) +{ + xAND( ptr8[to], from ); +} + +/* cmove r32 to r32*/ +emitterT void CMOVE32RtoR( x86IntRegType to, x86IntRegType from ) +{ + xCMOVE( xRegister32(to), xRegister32(from) ); +} + +// shld imm8 to r32 +emitterT void SHLD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + xSHLD( xRegister32(to), xRegister32(from), shift ); +} + +// shrd imm8 to r32 +emitterT void SHRD32ItoR( x86IntRegType to, x86IntRegType from, u8 shift ) +{ + xSHRD( xRegister32(to), xRegister32(from), shift ); +} + +/* mul eax by r32 to edx:eax */ +emitterT void MUL32R( x86IntRegType from ) { xUMUL( xRegister32(from) ); } +/* imul eax by r32 to edx:eax */ +emitterT void IMUL32R( x86IntRegType from ) { xMUL( xRegister32(from) ); } +/* mul eax by m32 to edx:eax */ +emitterT void MUL32M( u32 from ) { xUMUL( ptr32[from] ); } +/* imul eax by m32 to edx:eax */ +emitterT void IMUL32M( u32 from ) { xMUL( ptr32[from] ); } + +/* imul r32 by r32 to r32 */ +emitterT void IMUL32RtoR( x86IntRegType to, x86IntRegType from ) +{ + xMUL( xRegister32(to), xRegister32(from) ); +} + +/* div eax by r32 to edx:eax */ +emitterT void DIV32R( x86IntRegType from ) { xUDIV( xRegister32(from) ); } +/* idiv eax by r32 to edx:eax */ +emitterT void IDIV32R( x86IntRegType from ) { xDIV( xRegister32(from) ); } +/* div eax by m32 to edx:eax */ +emitterT void DIV32M( u32 from ) { xUDIV( ptr32[from] ); } +/* idiv eax by m32 to edx:eax */ +emitterT void IDIV32M( u32 from ) { xDIV( ptr32[from] ); } + + +emitterT void LEA32RtoR(x86IntRegType to, x86IntRegType from, s32 offset) +{ + xLEA( xRegister32( to ), ptr[xAddressReg(from)+offset] ); +} + +emitterT void LEA32RRtoR(x86IntRegType to, x86IntRegType from0, x86IntRegType from1) +{ + xLEA( xRegister32( to ), ptr[xAddressReg(from0)+xAddressReg(from1)] ); +} + +// Don't inline recursive functions +emitterT void LEA32RStoR(x86IntRegType to, x86IntRegType from, u32 scale) +{ + xLEA( xRegister32( to ), ptr[xAddressReg(from)*(1< 0x7f ) { + Console::Error( "j8 greater than 0x7f!!" ); + assert(0); + } + *j8 = (u8)jump; +} + +void x86SetJ8A( u8* j8 ) +{ + u32 jump = ( x86Ptr - j8 ) - 1; + + if ( jump > 0x7f ) { + Console::Error( "j8 greater than 0x7f!!" ); + assert(0); + } + + if( ((uptr)x86Ptr&0xf) > 4 ) { + + uptr newjump = jump + 16-((uptr)x86Ptr&0xf); + + if( newjump <= 0x7f ) { + jump = newjump; + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + } + } + *j8 = (u8)jump; +} + +//////////////////////////////////////////////////// +emitterT void x86SetJ32( u32* j32 ) +{ + *j32 = ( x86Ptr - (u8*)j32 ) - 4; +} + +emitterT void x86SetJ32A( u32* j32 ) +{ + while((uptr)x86Ptr&0xf) *x86Ptr++ = 0x90; + x86SetJ32(j32); +} + +//////////////////////////////////////////////////// +emitterT void x86Align( int bytes ) +{ + // forward align + x86Ptr = (u8*)( ( (uptr)x86Ptr + bytes - 1) & ~( bytes - 1 ) ); +} + +/********************/ +/* IX86 instructions */ +/********************/ + +emitterT void STC( void ) { xSTC(); } +emitterT void CLC( void ) { xCLC(); } +emitterT void NOP( void ) { xNOP(); } + +//////////////////////////////////// +// jump instructions / +//////////////////////////////////// + +/* jmp rel8 */ +emitterT u8* JMP8( u8 to ) +{ + xWrite8( 0xEB ); + xWrite8( to ); + return x86Ptr - 1; +} + +/* jmp rel32 */ +emitterT u32* JMP32( uptr to ) +{ + assert( (sptr)to <= 0x7fffffff && (sptr)to >= -0x7fffffff ); + xWrite8( 0xE9 ); + xWrite32( to ); + return (u32*)(x86Ptr - 4 ); +} + +/* jmp r32/r64 */ +emitterT void JMPR( x86IntRegType to ) +{ + xJMP( xRegister32(to) ); +} + +// jmp m32 +emitterT void JMP32M( uptr to ) +{ + xJMP( ptr32[to] ); +} + +/* jp rel8 */ +emitterT u8* JP8( u8 to ) { + return J8Rel( 0x7A, to ); +} + +/* jnp rel8 */ +emitterT u8* JNP8( u8 to ) { + return J8Rel( 0x7B, to ); +} + +/* je rel8 */ +emitterT u8* JE8( u8 to ) { + return J8Rel( 0x74, to ); +} + +/* jz rel8 */ +emitterT u8* JZ8( u8 to ) +{ + return J8Rel( 0x74, to ); +} + +/* js rel8 */ +emitterT u8* JS8( u8 to ) +{ + return J8Rel( 0x78, to ); +} + +/* jns rel8 */ +emitterT u8* JNS8( u8 to ) +{ + return J8Rel( 0x79, to ); +} + +/* jg rel8 */ +emitterT u8* JG8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jge rel8 */ +emitterT u8* JGE8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jl rel8 */ +emitterT u8* JL8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* ja rel8 */ +emitterT u8* JA8( u8 to ) +{ + return J8Rel( 0x77, to ); +} + +emitterT u8* JAE8( u8 to ) +{ + return J8Rel( 0x73, to ); +} + +/* jb rel8 */ +emitterT u8* JB8( u8 to ) +{ + return J8Rel( 0x72, to ); +} + +/* jbe rel8 */ +emitterT u8* JBE8( u8 to ) +{ + return J8Rel( 0x76, to ); +} + +/* jle rel8 */ +emitterT u8* JLE8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jne rel8 */ +emitterT u8* JNE8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jnz rel8 */ +emitterT u8* JNZ8( u8 to ) +{ + return J8Rel( 0x75, to ); +} + +/* jng rel8 */ +emitterT u8* JNG8( u8 to ) +{ + return J8Rel( 0x7E, to ); +} + +/* jnge rel8 */ +emitterT u8* JNGE8( u8 to ) +{ + return J8Rel( 0x7C, to ); +} + +/* jnl rel8 */ +emitterT u8* JNL8( u8 to ) +{ + return J8Rel( 0x7D, to ); +} + +/* jnle rel8 */ +emitterT u8* JNLE8( u8 to ) +{ + return J8Rel( 0x7F, to ); +} + +/* jo rel8 */ +emitterT u8* JO8( u8 to ) +{ + return J8Rel( 0x70, to ); +} + +/* jno rel8 */ +emitterT u8* JNO8( u8 to ) +{ + return J8Rel( 0x71, to ); +} +// jb rel32 +emitterT u32* JB32( u32 to ) +{ + return J32Rel( 0x82, to ); +} + +/* je rel32 */ +emitterT u32* JE32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* jz rel32 */ +emitterT u32* JZ32( u32 to ) +{ + return J32Rel( 0x84, to ); +} + +/* js rel32 */ +emitterT u32* JS32( u32 to ) +{ + return J32Rel( 0x88, to ); +} + +/* jns rel32 */ +emitterT u32* JNS32( u32 to ) +{ + return J32Rel( 0x89, to ); +} + +/* jg rel32 */ +emitterT u32* JG32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jge rel32 */ +emitterT u32* JGE32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jl rel32 */ +emitterT u32* JL32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jle rel32 */ +emitterT u32* JLE32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* ja rel32 */ +emitterT u32* JA32( u32 to ) +{ + return J32Rel( 0x87, to ); +} + +/* jae rel32 */ +emitterT u32* JAE32( u32 to ) +{ + return J32Rel( 0x83, to ); +} + +/* jne rel32 */ +emitterT u32* JNE32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jnz rel32 */ +emitterT u32* JNZ32( u32 to ) +{ + return J32Rel( 0x85, to ); +} + +/* jng rel32 */ +emitterT u32* JNG32( u32 to ) +{ + return J32Rel( 0x8E, to ); +} + +/* jnge rel32 */ +emitterT u32* JNGE32( u32 to ) +{ + return J32Rel( 0x8C, to ); +} + +/* jnl rel32 */ +emitterT u32* JNL32( u32 to ) +{ + return J32Rel( 0x8D, to ); +} + +/* jnle rel32 */ +emitterT u32* JNLE32( u32 to ) +{ + return J32Rel( 0x8F, to ); +} + +/* jo rel32 */ +emitterT u32* JO32( u32 to ) +{ + return J32Rel( 0x80, to ); +} + +/* jno rel32 */ +emitterT u32* JNO32( u32 to ) +{ + return J32Rel( 0x81, to ); +} + + + +/* call func */ +emitterT void CALLFunc( uptr func ) +{ + xCALL( (void*)func ); +} + +/* call r32 */ +emitterT void CALL32R( x86IntRegType to ) +{ + xCALL( xRegister32( to ) ); +} + +/* call m32 */ +emitterT void CALL32M( u32 to ) +{ + xCALL( ptr32[to] ); +} + +emitterT void BSRRtoR(x86IntRegType to, x86IntRegType from) +{ + xBSR( xRegister32(to), xRegister32(from) ); +} + +emitterT void BSWAP32R( x86IntRegType to ) +{ + xBSWAP( xRegister32(to) ); +} diff --git a/pcsx2/x86/ix86/ix86_legacy_instructions.h b/pcsx2/x86/ix86/ix86_legacy_instructions.h new file mode 100644 index 0000000000..8e41e58f4c --- /dev/null +++ b/pcsx2/x86/ix86/ix86_legacy_instructions.h @@ -0,0 +1,1395 @@ +/* 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 + +//------------------------------------------------------------------ +// legacy jump/align functions +//------------------------------------------------------------------ +extern void x86SetPtr( u8 *ptr ); +extern void x86SetJ8( u8 *j8 ); +extern void x86SetJ8A( u8 *j8 ); +extern void x86SetJ16( u16 *j16 ); +extern void x86SetJ16A( u16 *j16 ); +extern void x86SetJ32( u32 *j32 ); +extern void x86SetJ32A( u32 *j32 ); +extern void x86Align( int bytes ); +extern void x86AlignExecutable( int align ); +//------------------------------------------------------------------ + +extern void CLC( void ); +extern void NOP( void ); + +//////////////////////////////////// +// mov instructions // +//////////////////////////////////// + +// mov r32 to r32 +extern void MOV32RtoR( x86IntRegType to, x86IntRegType from ); +// mov r32 to m32 +extern void MOV32RtoM( uptr to, x86IntRegType from ); +// mov m32 to r32 +extern void MOV32MtoR( x86IntRegType to, uptr from ); +// mov [r32] to r32 +extern void MOV32RmtoR( x86IntRegType to, x86IntRegType from, int offset=0 ); +// mov [r32][r32< subtract ST(0) from ST(1), store in ST(1) and POP stack +extern void FSUBP( void ); +// fmul ST(src) to fpu reg stack ST(0) +extern void FMUL32Rto0( x86IntRegType src ); +// fmul ST(0) to fpu reg stack ST(src) +extern void FMUL320toR( x86IntRegType src ); +// fdiv ST(src) to fpu reg stack ST(0) +extern void FDIV32Rto0( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src) +extern void FDIV320toR( x86IntRegType src ); +// fdiv ST(0) to fpu reg stack ST(src), pop stack, store in ST(src) +extern void FDIV320toRP( x86IntRegType src ); + +// fadd m32 to fpu reg stack +extern void FADD32( u32 from ); +// fsub m32 to fpu reg stack +extern void FSUB32( u32 from ); +// fmul m32 to fpu reg stack +extern void FMUL32( u32 from ); +// fdiv m32 to fpu reg stack +extern void FDIV32( u32 from ); +// fcomi st, st( i) +extern void FCOMI( x86IntRegType src ); +// fcomip st, st( i) +extern void FCOMIP( x86IntRegType src ); +// fucomi st, st( i) +extern void FUCOMI( x86IntRegType src ); +// fucomip st, st( i) +extern void FUCOMIP( x86IntRegType src ); +// fcom m32 to fpu reg stack +extern void FCOM32( u32 from ); +// fabs fpu reg stack +extern void FABS( void ); +// fsqrt fpu reg stack +extern void FSQRT( void ); +// ftan fpu reg stack +extern void FPATAN( void ); +// fsin fpu reg stack +extern void FSIN( void ); +// fchs fpu reg stack +extern void FCHS( void ); + +// fcmovb fpu reg to fpu reg stack +extern void FCMOVB32( x86IntRegType from ); +// fcmove fpu reg to fpu reg stack +extern void FCMOVE32( x86IntRegType from ); +// fcmovbe fpu reg to fpu reg stack +extern void FCMOVBE32( x86IntRegType from ); +// fcmovu fpu reg to fpu reg stack +extern void FCMOVU32( x86IntRegType from ); +// fcmovnb fpu reg to fpu reg stack +extern void FCMOVNB32( x86IntRegType from ); +// fcmovne fpu reg to fpu reg stack +extern void FCMOVNE32( x86IntRegType from ); +// fcmovnbe fpu reg to fpu reg stack +extern void FCMOVNBE32( x86IntRegType from ); +// fcmovnu fpu reg to fpu reg stack +extern void FCMOVNU32( x86IntRegType from ); +extern void FCOMP32( u32 from ); +extern void FNSTSWtoAX( void ); + +#define MMXONLY(code) code + +//****************** +// MMX instructions +//****************** + +// r64 = mm + +// movq m64 to r64 +extern void MOVQMtoR( x86MMXRegType to, uptr from ); +// movq r64 to m64 +extern void MOVQRtoM( uptr to, x86MMXRegType from ); + +// pand r64 to r64 +extern void PANDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pand m64 to r64 ; +extern void PANDMtoR( x86MMXRegType to, uptr from ); +// pandn r64 to r64 +extern void PANDNRtoR( x86MMXRegType to, x86MMXRegType from ); +// pandn r64 to r64 +extern void PANDNMtoR( x86MMXRegType to, uptr from ); +// por r64 to r64 +extern void PORRtoR( x86MMXRegType to, x86MMXRegType from ); +// por m64 to r64 +extern void PORMtoR( x86MMXRegType to, uptr from ); +// pxor r64 to r64 +extern void PXORRtoR( x86MMXRegType to, x86MMXRegType from ); +// pxor m64 to r64 +extern void PXORMtoR( x86MMXRegType to, uptr from ); + +// psllq r64 to r64 +extern void PSLLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psllq m64 to r64 +extern void PSLLQMtoR( x86MMXRegType to, uptr from ); +// psllq imm8 to r64 +extern void PSLLQItoR( x86MMXRegType to, u8 from ); +// psrlq r64 to r64 +extern void PSRLQRtoR( x86MMXRegType to, x86MMXRegType from ); +// psrlq m64 to r64 +extern void PSRLQMtoR( x86MMXRegType to, uptr from ); +// psrlq imm8 to r64 +extern void PSRLQItoR( x86MMXRegType to, u8 from ); + +// paddusb r64 to r64 +extern void PADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusb m64 to r64 +extern void PADDUSBMtoR( x86MMXRegType to, uptr from ); +// paddusw r64 to r64 +extern void PADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddusw m64 to r64 +extern void PADDUSWMtoR( x86MMXRegType to, uptr from ); + +// paddb r64 to r64 +extern void PADDBRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddb m64 to r64 +extern void PADDBMtoR( x86MMXRegType to, uptr from ); +// paddw r64 to r64 +extern void PADDWRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddw m64 to r64 +extern void PADDWMtoR( x86MMXRegType to, uptr from ); +// paddd r64 to r64 +extern void PADDDRtoR( x86MMXRegType to, x86MMXRegType from ); +// paddd m64 to r64 +extern void PADDDMtoR( x86MMXRegType to, uptr from ); +extern void PADDSBRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PADDSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +// paddq m64 to r64 (sse2 only?) +extern void PADDQMtoR( x86MMXRegType to, uptr from ); +// paddq r64 to r64 (sse2 only?) +extern void PADDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +extern void PSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ); + +extern void PSUBBRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSUBWRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSUBDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSUBDMtoR( x86MMXRegType to, uptr from ); + +// psubq m64 to r64 (sse2 only?) +extern void PSUBQMtoR( x86MMXRegType to, uptr from ); +// psubq r64 to r64 (sse2 only?) +extern void PSUBQRtoR( x86MMXRegType to, x86MMXRegType from ); + +// pmuludq m64 to r64 (sse2 only?) +extern void PMULUDQMtoR( x86MMXRegType to, uptr from ); +// pmuludq r64 to r64 (sse2 only?) +extern void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ); + +extern void PCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPEQDMtoR( x86MMXRegType to, uptr from ); +extern void PCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PCMPGTDMtoR( x86MMXRegType to, uptr from ); +extern void PSRLWItoR( x86MMXRegType to, u8 from ); +extern void PSRLDItoR( x86MMXRegType to, u8 from ); +extern void PSRLDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSLLWItoR( x86MMXRegType to, u8 from ); +extern void PSLLDItoR( x86MMXRegType to, u8 from ); +extern void PSLLDRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PSRAWItoR( x86MMXRegType to, u8 from ); +extern void PSRADItoR( x86MMXRegType to, u8 from ); +extern void PSRADRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PUNPCKLDQMtoR( x86MMXRegType to, uptr from ); +extern void PUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void PUNPCKHDQMtoR( x86MMXRegType to, uptr from ); +extern void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ); +extern void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset=0 ); +extern void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset=0 ); +extern void MOVDMtoMMX( x86MMXRegType to, uptr from ); +extern void MOVDMMXtoM( uptr to, x86MMXRegType from ); +extern void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ); +extern void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset=0 ); +extern void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ); +extern void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset=0 ); +extern void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ); +extern void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8); +extern void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8); +extern void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from); + +// emms +extern void EMMS( void ); + +extern void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from); + +//********************* +// SSE instructions * +//********************* +extern void SSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ); +extern void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ); + +extern void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ); +extern void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ); +extern void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 ); + +extern void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ); +extern void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 ); + +extern void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ); +extern void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 ); + +extern void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVLPSRtoRm( x86SSERegType to, x86IntRegType from, int offset=0 ); + +extern void SSE_MOVAPSRtoRm( x86IntRegType to, x86SSERegType from, int offset=0 ); +extern void SSE_MOVAPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVUPSRtoRm( x86IntRegType to, x86SSERegType from ); +extern void SSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from ); + +extern void SSE_MOVUPSRmtoR( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE_MOVUPSRtoRm( x86SSERegType to, x86IntRegType from, int offset=0 ); + +extern void SSE2_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset=0 ); +extern void SSE2_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset=0 ); + +extern void SSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from ); + +extern void SSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +extern void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ); +extern void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ); +extern void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ); +extern void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ); + +extern void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from); +extern void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from); +extern void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from); +extern void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from); + +extern void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE2_MAXPD_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MAXPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_MINPD_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MINPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +extern void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); +extern void SSE_SHUFPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ); +extern void SSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +// VectorPath +extern void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +extern void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +extern void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +extern void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); +extern void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +extern void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +extern void SSE2_SHUFPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ); +extern void SSE2_SHUFPD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ); + +extern void SSE_STMXCSR( uptr from ); +extern void SSE_LDMXCSR( uptr from ); + + +//********************* +// SSE 2 Instructions* +//********************* + +extern void SSE2_CVTSS2SD_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_CVTSS2SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_CVTSD2SS_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_CVTSD2SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from); +extern void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +extern void SSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from); +extern void SSE2_MOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from); + +extern void SSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSRLD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSRLQ_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSRAW_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSRAD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSLLW_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSLLD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PSLLQ_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8); +extern void SSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PMAXSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PMADDWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); + +extern void SSE2_ANDPD_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_ANDPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_UCOMISD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_UCOMISD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_SQRTSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_SQRTSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_MAXPD_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MAXPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_MAXSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MAXSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE2_XORPD_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_XORPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_ADDSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_ADDSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_SUBSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_SUBSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE2_MULSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MULSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_DIVSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_DIVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_MINSD_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MINSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +//**********************************************************************************/ +//PACKSSWB,PACKSSDW: Pack Saturate Signed Word +//********************************************************************************** +extern void SSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from); + +//**********************************************************************************/ +//PUNPCKHWD: Unpack 16bit high +//********************************************************************************** +extern void SSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from); + +// mult by half words +extern void SSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr from); + + +//**********************************************************************************/ +//PMOVMSKB: Create 16bit mask from signs of 8bit integers +//********************************************************************************** +extern void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +extern void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from); +extern void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from); + +//**********************************************************************************/ +//PEXTRW,PINSRW: Packed Extract/Insert Word * +//********************************************************************************** +extern void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ); +extern void SSE_PINSRW_R32_to_XMM(x86SSERegType from, x86IntRegType to, u8 imm8 ); + + +//**********************************************************************************/ +//PSUBx: Subtract Packed Integers * +//********************************************************************************** +extern void SSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBB_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ); +/////////////////////////////////////////////////////////////////////////////////////// +//**********************************************************************************/ +//PCMPxx: Compare Packed Integers * +//********************************************************************************** +extern void SSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ); + +//**********************************************************************************/ +//MOVD: Move Dword(32bit) to /from XMM reg * +//********************************************************************************** +extern void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ); +extern void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +extern void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ); +extern void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 ); + +extern void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); + +extern void SSE2_MOVQ_XMM_to_R( x86IntRegType to, x86SSERegType from ); +extern void SSE2_MOVQ_R_to_XMM( x86SSERegType to, x86IntRegType from ); +extern void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ); +extern void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ); + +//**********************************************************************************/ +//MOVD: Move Qword(64bit) to/from MMX/XMM reg * +//********************************************************************************** +extern void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from); +extern void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from); + + +//**********************************************************************************/ +//POR : SSE Bitwise OR * +//********************************************************************************** +extern void SSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSE2_POR_M128_to_XMM( x86SSERegType to, uptr from ); + +extern void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from); + +extern void SSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from); + +// SSSE3 + +extern void SSSE3_PABSB_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSSE3_PABSW_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSSE3_PABSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); + +// SSE4.1 + +#ifndef _MM_MK_INSERTPS_NDX +#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask)) +#endif + +extern void SSE4_DPPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8); +extern void SSE4_DPPS_M128_to_XMM(x86SSERegType to, uptr from, u8 imm8); +extern void SSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8); +extern void SSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8); +extern void SSE4_BLENDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8); +extern void SSE4_BLENDVPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_BLENDVPS_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE4_PMOVSXDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8); +extern void SSE4_PMAXSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_PMINSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_PMAXUD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_PMINUD_XMM_to_XMM(x86SSERegType to, x86SSERegType from); +extern void SSE4_PMAXSD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE4_PMINSD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE4_PMAXUD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE4_PMINUD_M128_to_XMM(x86SSERegType to, uptr from); +extern void SSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from); + +//********************* +// 3DNOW instructions * +//********************* +extern void FEMMS( void ); +extern void PFCMPEQMtoR( x86IntRegType to, uptr from ); +extern void PFCMPGTMtoR( x86IntRegType to, uptr from ); +extern void PFCMPGEMtoR( x86IntRegType to, uptr from ); +extern void PFADDMtoR( x86IntRegType to, uptr from ); +extern void PFADDRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFSUBMtoR( x86IntRegType to, uptr from ); +extern void PFSUBRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFMULMtoR( x86IntRegType to, uptr from ); +extern void PFMULRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFRCPMtoR( x86IntRegType to, uptr from ); +extern void PFRCPRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFRCPIT1RtoR( x86IntRegType to, x86IntRegType from ); +extern void PFRCPIT2RtoR( x86IntRegType to, x86IntRegType from ); +extern void PFRSQRTRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFRSQIT1RtoR( x86IntRegType to, x86IntRegType from ); +extern void PF2IDMtoR( x86IntRegType to, uptr from ); +extern void PI2FDMtoR( x86IntRegType to, uptr from ); +extern void PI2FDRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFMAXMtoR( x86IntRegType to, uptr from ); +extern void PFMAXRtoR( x86IntRegType to, x86IntRegType from ); +extern void PFMINMtoR( x86IntRegType to, uptr from ); +extern void PFMINRtoR( x86IntRegType to, x86IntRegType from ); + diff --git a/pcsx2/x86/ix86/ix86_legacy_internal.h b/pcsx2/x86/ix86/ix86_legacy_internal.h new file mode 100644 index 0000000000..90ba4aef49 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_legacy_internal.h @@ -0,0 +1,53 @@ +/* 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 + +#include "ix86_internal.h" + +//------------------------------------------------------------------ +// Legacy Helper Macros and Functions (depreciated) +//------------------------------------------------------------------ + +#define emitterT __forceinline + +using x86Emitter::xWrite8; +using x86Emitter::xWrite16; +using x86Emitter::xWrite32; +using x86Emitter::xWrite64; + +#include "ix86_legacy_types.h" +#include "ix86_legacy_instructions.h" + +#define MEMADDR(addr, oplen) (addr) + +#define Rex(w,r,x,b) assert(0) +#define RexR(w, reg) assert( !(w || (reg)>=8) ) +#define RexB(w, base) assert( !(w || (base)>=8) ) +#define RexRB(w, reg, base) assert( !(w || (reg) >= 8 || (base)>=8) ) +#define RexRXB(w, reg, index, base) assert( !(w || (reg) >= 8 || (index) >= 8 || (base) >= 8) ) + +#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask)) + +extern void ModRM( uint mod, uint reg, uint rm ); +extern void SibSB( uint ss, uint index, uint base ); +extern void SET8R( int cc, int to ); +extern u8* J8Rel( int cc, int to ); +extern u32* J32Rel( int cc, u32 to ); +extern u64 GetCPUTick( void ); + diff --git a/pcsx2/x86/ix86/ix86_legacy_sse.cpp b/pcsx2/x86/ix86/ix86_legacy_sse.cpp new file mode 100644 index 0000000000..169f6ac100 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_legacy_sse.cpp @@ -0,0 +1,533 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" +#include "ix86_legacy_internal.h" +#include "ix86_sse_helpers.h" + +using namespace x86Emitter; + +// ------------------------------------------------------------------------ +// MMX / SSE Mixed Bag +// ------------------------------------------------------------------------ + +emitterT void MOVQMtoR( x86MMXRegType to, uptr from ) { xMOVQ( xRegisterMMX(to), (void*)from ); } +emitterT void MOVQRtoM( uptr to, x86MMXRegType from ) { xMOVQ( (void*)to, xRegisterMMX(from) ); } +emitterT void MOVQRtoR( x86MMXRegType to, x86MMXRegType from ) { xMOVQ( xRegisterMMX(to), xRegisterMMX(from) ); } +emitterT void MOVQRmtoR( x86MMXRegType to, x86IntRegType from, int offset ) { xMOVQ( xRegisterMMX(to), ptr[xAddressReg(from)+offset] ); } +emitterT void MOVQRtoRm( x86IntRegType to, x86MMXRegType from, int offset ) { xMOVQ( ptr[xAddressReg(to)+offset], xRegisterMMX(from) ); } + +emitterT void MOVDMtoMMX( x86MMXRegType to, uptr from ) { xMOVDZX( xRegisterMMX(to), (void*)from ); } +emitterT void MOVDMMXtoM( uptr to, x86MMXRegType from ) { xMOVD( (void*)to, xRegisterMMX(from) ); } +emitterT void MOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) { xMOVDZX( xRegisterMMX(to), xRegister32(from) ); } +emitterT void MOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from, int offset ) { xMOVDZX( xRegisterMMX(to), ptr[xAddressReg(from)+offset] ); } +emitterT void MOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) { xMOVD( xRegister32(to), xRegisterMMX(from) ); } +emitterT void MOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from, int offset ) { xMOVD( ptr[xAddressReg(to)+offset], xRegisterMMX(from) ); } + +emitterT void PMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) { xPMOVMSKB( xRegister32(to), xRegisterMMX(from) ); } +emitterT void MASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) { xMASKMOV( xRegisterMMX(to), xRegisterMMX(from) ); } + +#define DEFINE_LEGACY_LOGIC_OPCODE( mod ) \ + emitterT void P##mod##RtoR( x86MMXRegType to, x86MMXRegType from ) { xP##mod( xRegisterMMX(to), xRegisterMMX(from) ); } \ + emitterT void P##mod##MtoR( x86MMXRegType to, uptr from ) { xP##mod( xRegisterMMX(to), (void*)from ); } \ + emitterT void SSE2_P##mod##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_P##mod##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod( xRegisterSSE(to), (void*)from ); } + +#define DEFINE_LEGACY_ARITHMETIC( mod, sub ) \ + emitterT void P##mod##sub##RtoR( x86MMXRegType to, x86MMXRegType from ) { xP##mod.sub( xRegisterMMX(to), xRegisterMMX(from) ); } \ + emitterT void P##mod##sub##MtoR( x86MMXRegType to, uptr from ) { xP##mod.sub( xRegisterMMX(to), (void*)from ); } \ + emitterT void SSE2_P##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod.sub( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_P##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod.sub( xRegisterSSE(to), (void*)from ); } + +#define DEFINE_LEGACY_SHIFT_STUFF( mod, sub ) \ + emitterT void P##mod##sub##RtoR( x86MMXRegType to, x86MMXRegType from ) { xP##mod.sub( xRegisterMMX(to), xRegisterMMX(from) ); } \ + emitterT void P##mod##sub##MtoR( x86MMXRegType to, uptr from ) { xP##mod.sub( xRegisterMMX(to), (void*)from ); } \ + emitterT void P##mod##sub##ItoR( x86MMXRegType to, u8 imm ) { xP##mod.sub( xRegisterMMX(to), imm ); } \ + emitterT void SSE2_P##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xP##mod.sub( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_P##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { xP##mod.sub( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_P##mod##sub##_I8_to_XMM( x86SSERegType to, u8 imm ) { xP##mod.sub( xRegisterSSE(to), imm ); } + +#define DEFINE_LEGACY_SHIFT_OPCODE( mod ) \ + DEFINE_LEGACY_SHIFT_STUFF( mod, Q ) \ + DEFINE_LEGACY_SHIFT_STUFF( mod, D ) \ + DEFINE_LEGACY_SHIFT_STUFF( mod, W ) \ + emitterT void SSE2_P##mod##DQ_I8_to_XMM( x86MMXRegType to, u8 imm ) { xP##mod.DQ( xRegisterSSE(to), imm ); } + +DEFINE_LEGACY_LOGIC_OPCODE( AND ) +DEFINE_LEGACY_LOGIC_OPCODE( ANDN ) +DEFINE_LEGACY_LOGIC_OPCODE( OR ) +DEFINE_LEGACY_LOGIC_OPCODE( XOR ) + +DEFINE_LEGACY_SHIFT_OPCODE( SLL ) +DEFINE_LEGACY_SHIFT_OPCODE( SRL ) +DEFINE_LEGACY_SHIFT_STUFF( SRA, D ) +DEFINE_LEGACY_SHIFT_STUFF( SRA, W ) + +DEFINE_LEGACY_ARITHMETIC( ADD, B ) +DEFINE_LEGACY_ARITHMETIC( ADD, W ) +DEFINE_LEGACY_ARITHMETIC( ADD, D ) +DEFINE_LEGACY_ARITHMETIC( ADD, Q ) +DEFINE_LEGACY_ARITHMETIC( ADD, SB ) +DEFINE_LEGACY_ARITHMETIC( ADD, SW ) +DEFINE_LEGACY_ARITHMETIC( ADD, USB ) +DEFINE_LEGACY_ARITHMETIC( ADD, USW ) + +DEFINE_LEGACY_ARITHMETIC( SUB, B ) +DEFINE_LEGACY_ARITHMETIC( SUB, W ) +DEFINE_LEGACY_ARITHMETIC( SUB, D ) +DEFINE_LEGACY_ARITHMETIC( SUB, Q ) +DEFINE_LEGACY_ARITHMETIC( SUB, SB ) +DEFINE_LEGACY_ARITHMETIC( SUB, SW ) +DEFINE_LEGACY_ARITHMETIC( SUB, USB ) +DEFINE_LEGACY_ARITHMETIC( SUB, USW ) + +DEFINE_LEGACY_ARITHMETIC( CMP, EQB ); +DEFINE_LEGACY_ARITHMETIC( CMP, EQW ); +DEFINE_LEGACY_ARITHMETIC( CMP, EQD ); +DEFINE_LEGACY_ARITHMETIC( CMP, GTB ); +DEFINE_LEGACY_ARITHMETIC( CMP, GTW ); +DEFINE_LEGACY_ARITHMETIC( CMP, GTD ); + +DEFINE_LEGACY_ARITHMETIC( UNPCK, HDQ ); +DEFINE_LEGACY_ARITHMETIC( UNPCK, LDQ ); +DEFINE_LEGACY_ARITHMETIC( UNPCK, HBW ); +DEFINE_LEGACY_ARITHMETIC( UNPCK, LBW ); + +DEFINE_LEGACY_ARITHMETIC( UNPCK, LWD ); +DEFINE_LEGACY_ARITHMETIC( UNPCK, HWD ); + + +emitterT void PMULUDQMtoR( x86MMXRegType to, uptr from ) { xPMUL.UDQ( xRegisterMMX( to ), (void*)from ); } +emitterT void PMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) { xPMUL.UDQ( xRegisterMMX( to ), xRegisterMMX( from ) ); } + +emitterT void PSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) { xPSHUF.W( xRegisterMMX(to), xRegisterMMX(from), imm8 ); } +emitterT void PSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8) { xPSHUF.W( xRegisterMMX(to), (void*)from, imm8 ); } + +emitterT void PINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) { xPINSR.W( xRegisterMMX(to), xRegister32(from), imm8 ); } + +emitterT void EMMS() { xEMMS(); } + +// ------------------------------------------------------------------------ +// Begin SSE-Only Part! +// ------------------------------------------------------------------------ + +#define DEFINE_LEGACY_MOV_OPCODE( mod, sse ) \ + emitterT void sse##_MOV##mod##_M128_to_XMM( x86SSERegType to, uptr from ) { xMOV##mod( xRegisterSSE(to), (void*)from ); } \ + emitterT void sse##_MOV##mod##_XMM_to_M128( uptr to, x86SSERegType from ) { xMOV##mod( (void*)to, xRegisterSSE(from) ); } \ + emitterT void sse##_MOV##mod##RmtoR( x86SSERegType to, x86IntRegType from, int offset ) { xMOV##mod( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); } \ + emitterT void sse##_MOV##mod##RtoRm( x86IntRegType to, x86SSERegType from, int offset ) { xMOV##mod( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); } \ + emitterT void sse##_MOV##mod##RmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) \ + { xMOV##mod( xRegisterSSE(to), ptr[xAddressReg(from)+xAddressReg(from2)] ); } \ + emitterT void sse##_MOV##mod##RtoRmS( x86IntRegType to, x86SSERegType from, x86IntRegType from2, int scale ) \ + { xMOV##mod( ptr[xAddressReg(to)+xAddressReg(from2)], xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_PSD_OPCODE( mod ) \ + emitterT void SSE_##mod##PS_M128_to_XMM( x86SSERegType to, uptr from ) { x##mod.PS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_##mod##PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.PS( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_##mod##PD_M128_to_XMM( x86SSERegType to, uptr from ) { x##mod.PD( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_##mod##PD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.PD( xRegisterSSE(to), xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_SSSD_OPCODE( mod ) \ + emitterT void SSE_##mod##SS_M32_to_XMM( x86SSERegType to, uptr from ) { x##mod.SS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_##mod##SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.SS( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_##mod##SD_M64_to_XMM( x86SSERegType to, uptr from ) { x##mod.SD( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_##mod##SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.SD( xRegisterSSE(to), xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_CMP_OPCODE( comp ) \ + emitterT void SSE_CMP##comp##PS_M128_to_XMM( x86SSERegType to, uptr from ) { xCMP##comp.PS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_CMP##comp##PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCMP##comp.PS( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_CMP##comp##PD_M128_to_XMM( x86SSERegType to, uptr from ) { xCMP##comp.PD( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_CMP##comp##PD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCMP##comp.PD( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE_CMP##comp##SS_M32_to_XMM( x86SSERegType to, uptr from ) { xCMP##comp.SS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_CMP##comp##SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCMP##comp.SS( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE2_CMP##comp##SD_M64_to_XMM( x86SSERegType to, uptr from ) { xCMP##comp.SD( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_CMP##comp##SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCMP##comp.SD( xRegisterSSE(to), xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_RSQRT_OPCODE(mod) \ + emitterT void SSE_##mod##PS_M128_to_XMM( x86SSERegType to, uptr from ) { x##mod.PS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_##mod##PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.PS( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE_##mod##SS_M32_to_XMM( x86SSERegType to, uptr from ) { x##mod.SS( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE_##mod##SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.SS( xRegisterSSE(to), xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_SQRT_OPCODE(mod) \ + DEFINE_LEGACY_RSQRT_OPCODE(mod) \ + emitterT void SSE2_##mod##SD_M64_to_XMM( x86SSERegType to, uptr from ) { x##mod.SD( xRegisterSSE(to), (void*)from ); } \ + emitterT void SSE2_##mod##SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.SD( xRegisterSSE(to), xRegisterSSE(from) ); } + +#define DEFINE_LEGACY_OP128( ssenum, mod, sub ) \ + emitterT void SSE##ssenum##_##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod.sub( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE##ssenum##_##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { x##mod.sub( xRegisterSSE(to), (void*)from ); } + +#define DEFINE_LEGACY_MOV128( ssenum, mod, sub ) \ + emitterT void SSE##ssenum##_##mod##sub##_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { x##mod##sub( xRegisterSSE(to), xRegisterSSE(from) ); } \ + emitterT void SSE##ssenum##_##mod##sub##_M128_to_XMM( x86SSERegType to, uptr from ) { x##mod##sub( xRegisterSSE(to), (void*)from ); } + + +#define DEFINE_LEGACY_PSSD_OPCODE( mod ) \ + DEFINE_LEGACY_PSD_OPCODE( mod ) \ + DEFINE_LEGACY_SSSD_OPCODE( mod ) + +DEFINE_LEGACY_MOV_OPCODE( UPS, SSE ) +DEFINE_LEGACY_MOV_OPCODE( APS, SSE ) +DEFINE_LEGACY_MOV_OPCODE( DQA, SSE2 ) +DEFINE_LEGACY_MOV_OPCODE( DQU, SSE2 ) + +DEFINE_LEGACY_PSD_OPCODE( AND ) +DEFINE_LEGACY_PSD_OPCODE( ANDN ) +DEFINE_LEGACY_PSD_OPCODE( OR ) +DEFINE_LEGACY_PSD_OPCODE( XOR ) + +DEFINE_LEGACY_PSSD_OPCODE( SUB ) +DEFINE_LEGACY_PSSD_OPCODE( ADD ) +DEFINE_LEGACY_PSSD_OPCODE( MUL ) +DEFINE_LEGACY_PSSD_OPCODE( DIV ) + +DEFINE_LEGACY_PSSD_OPCODE( MIN ) +DEFINE_LEGACY_PSSD_OPCODE( MAX ) + +DEFINE_LEGACY_CMP_OPCODE( EQ ) +DEFINE_LEGACY_CMP_OPCODE( LT ) +DEFINE_LEGACY_CMP_OPCODE( LE ) +DEFINE_LEGACY_CMP_OPCODE( UNORD ) +DEFINE_LEGACY_CMP_OPCODE( NE ) +DEFINE_LEGACY_CMP_OPCODE( NLT ) +DEFINE_LEGACY_CMP_OPCODE( NLE ) +DEFINE_LEGACY_CMP_OPCODE( ORD ) + +DEFINE_LEGACY_SSSD_OPCODE( UCOMI ) +DEFINE_LEGACY_RSQRT_OPCODE( RCP ) +DEFINE_LEGACY_RSQRT_OPCODE( RSQRT ) +DEFINE_LEGACY_SQRT_OPCODE( SQRT ) + +DEFINE_LEGACY_OP128( 2, PMUL, LW ) +DEFINE_LEGACY_OP128( 2, PMUL, HW ) +DEFINE_LEGACY_OP128( 2, PMUL, UDQ ) + +DEFINE_LEGACY_OP128( 2, PMAX, SW ) +DEFINE_LEGACY_OP128( 2, PMAX, UB ) +DEFINE_LEGACY_OP128( 2, PMIN, SW ) +DEFINE_LEGACY_OP128( 2, PMIN, UB ) + +DEFINE_LEGACY_OP128( 2, UNPCK, LPS ) +DEFINE_LEGACY_OP128( 2, UNPCK, HPS ) +DEFINE_LEGACY_OP128( 2, PUNPCK, LQDQ ) +DEFINE_LEGACY_OP128( 2, PUNPCK, HQDQ ) + +DEFINE_LEGACY_OP128( 2, PACK, SSWB ) +DEFINE_LEGACY_OP128( 2, PACK, SSDW ) +DEFINE_LEGACY_OP128( 2, PACK, USWB ) + +DEFINE_LEGACY_MOV128( 3, MOV, SLDUP ) +DEFINE_LEGACY_MOV128( 3, MOV, SHDUP ) + +DEFINE_LEGACY_OP128( 4, PMAX, SD ) +DEFINE_LEGACY_OP128( 4, PMIN, SD ) +DEFINE_LEGACY_OP128( 4, PMAX, UD ) +DEFINE_LEGACY_OP128( 4, PMIN, UD ) + + +emitterT void SSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVAPS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { xMOVDQA( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) { xMOVDZX( xRegisterSSE(to), (void*)from ); } +emitterT void SSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { xMOVDZX( xRegisterSSE(to), xRegister32(from) ); } +emitterT void SSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + xMOVDZX( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); +} + +emitterT void SSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { xMOVD( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { xMOVD( xRegister32(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) +{ + xMOVD( ptr[xAddressReg(from)+offset], xRegisterSSE(from) ); +} + +emitterT void SSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVQZX( xRegisterSSE(to), (void*)from ); } +emitterT void SSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVQZX( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVQ( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) { xMOVQ( xRegisterMMX(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) { xMOVQ( xRegisterSSE(to), xRegisterMMX(from) ); } + + +emitterT void SSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { xMOVSSZX( xRegisterSSE(to), (void*)from ); } +emitterT void SSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { xMOVSS( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVSS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE_MOVSS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVSSZX( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); } +emitterT void SSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVSS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); } + +emitterT void SSE2_MOVSD_M32_to_XMM( x86SSERegType to, uptr from ) { xMOVSDZX( xRegisterSSE(to), (void*)from ); } +emitterT void SSE2_MOVSD_XMM_to_M32( u32 to, x86SSERegType from ) { xMOVSD( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVSD( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVSD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVSDZX( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); } +emitterT void SSE2_MOVSD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVSD( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); } + +emitterT void SSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVL.PS( xRegisterSSE(to), (void*)from ); } +emitterT void SSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVL.PS( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE_MOVLPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVL.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); } +emitterT void SSE_MOVLPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVL.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); } + +emitterT void SSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { xMOVH.PS( xRegisterSSE(to), (void*)from ); } +emitterT void SSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { xMOVH.PS( (void*)to, xRegisterSSE(from) ); } +emitterT void SSE_MOVHPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) { xMOVH.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset] ); } +emitterT void SSE_MOVHPS_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) { xMOVH.PS( ptr[xAddressReg(to)+offset], xRegisterSSE(from) ); } + +emitterT void SSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVLH.PS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMOVHL.PS( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xMASKMOV( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { xPMOVMSKB( xRegister32(to), xRegisterSSE(from) ); } + +emitterT void SSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xSHUF.PS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xSHUF.PS( xRegisterSSE(to), (void*)from, imm8 ); } +emitterT void SSE_SHUFPS_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ) +{ + xSHUF.PS( xRegisterSSE(to), ptr[xAddressReg(from)+offset], imm8 ); +} + +emitterT void SSE_SHUFPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xSHUF.PD( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE_SHUFPD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xSHUF.PD( xRegisterSSE(to), (void*)from, imm8 ); } + +emitterT void SSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ) { xCVTPI2PS( xRegisterSSE(to), (u64*)from ); } +emitterT void SSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { xCVTPI2PS( xRegisterSSE(to), xRegisterMMX(from) ); } +emitterT void SSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ) { xCVTPS2PI( xRegisterMMX(to), (u64*)from ); } +emitterT void SSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { xCVTPS2PI( xRegisterMMX(to), xRegisterSSE(from) ); } +emitterT void SSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { xCVTTSS2SI( xRegister32(to), (u32*)from ); } +emitterT void SSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) { xCVTTSS2SI( xRegister32(to), xRegisterSSE(from) ); } +emitterT void SSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { xCVTSI2SS( xRegisterSSE(to), (u32*)from ); } +emitterT void SSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) { xCVTSI2SS( xRegisterSSE(to), xRegister32(from) ); } + +emitterT void SSE2_CVTSS2SD_M32_to_XMM( x86SSERegType to, uptr from) { xCVTSS2SD( xRegisterSSE(to), (u32*)from ); } +emitterT void SSE2_CVTSS2SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { xCVTSS2SD( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_CVTSD2SS_M64_to_XMM( x86SSERegType to, uptr from) { xCVTSD2SS( xRegisterSSE(to), (u64*)from ); } +emitterT void SSE2_CVTSD2SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { xCVTSD2SS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { xCVTDQ2PS( xRegisterSSE(to), (u128*)from ); } +emitterT void SSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCVTDQ2PS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ) { xCVTPS2DQ( xRegisterSSE(to), (u128*)from ); } +emitterT void SSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCVTPS2DQ( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xCVTTPS2DQ( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ) { xPMAX.SW( xRegisterMMX(to), xRegisterMMX(from) ); } +emitterT void SSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ) { xPMAX.SW( xRegisterMMX(to), xRegisterMMX(from) ); } + +emitterT void SSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xPSHUF.D( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE2_PSHUFD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xPSHUF.D( xRegisterSSE(to), (void*)from, imm8 ); } +emitterT void SSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xPSHUF.LW( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xPSHUF.LW( xRegisterSSE(to), (void*)from, imm8 ); } +emitterT void SSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { xPSHUF.HW( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { xPSHUF.HW( xRegisterSSE(to), (void*)from, imm8 ); } + +emitterT void SSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMUL.DQ( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ) { xUNPCK.LPS( xRegisterSSE(to), (void*)from ); } +emitterT void SSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xUNPCK.LPS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ) { xUNPCK.HPS( xRegisterSSE(to), (void*)from ); } +emitterT void SSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { xUNPCK.HPS( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { xMOVMSKPS( xRegister32(to), xRegisterSSE(from) ); } +emitterT void SSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { xMOVMSKPD( xRegister32(to), xRegisterSSE(from) ); } + +emitterT void SSSE3_PABSB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPABS.B( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSSE3_PABSW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPABS.W( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSSE3_PABSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPABS.D( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSSE3_PSIGNB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPSIGN.B( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSSE3_PSIGNW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPSIGN.W( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSSE3_PSIGND_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPSIGN.D( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ) { xPEXTR.W( xRegister32(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ) { xPINSR.W( xRegisterSSE(to), xRegister32(from), imm8 ); } + +emitterT void SSE2_PMADDWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMADD.WD( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xHADD.PS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from) { xHADD.PS( xRegisterSSE(to), (void*)from ); } + +emitterT void SSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8) { xPINSR.D( xRegisterSSE(to), xRegister32(from), imm8 ); } + +emitterT void SSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) { xINSERTPS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8) { xEXTRACTPS( xRegister32(to), xRegisterSSE(from), imm8 ); } + +emitterT void SSE4_DPPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) { xDP.PS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE4_DPPS_M128_to_XMM(x86SSERegType to, uptr from, u8 imm8) { xDP.PS( xRegisterSSE(to), (void*)from, imm8 ); } + +emitterT void SSE4_BLENDPS_XMM_to_XMM(x86IntRegType to, x86SSERegType from, u8 imm8) { xBLEND.PS( xRegisterSSE(to), xRegisterSSE(from), imm8 ); } +emitterT void SSE4_BLENDVPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xBLEND.VPS( xRegisterSSE(to), xRegisterSSE(from) ); } +emitterT void SSE4_BLENDVPS_M128_to_XMM(x86SSERegType to, uptr from) { xBLEND.VPS( xRegisterSSE(to), (void*)from ); } + +emitterT void SSE4_PMOVSXDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { xPMOVSX.DQ( xRegisterSSE(to), xRegisterSSE(from) ); } + +emitterT void SSE_LDMXCSR( uptr from ) { xLDMXCSR( (u32*)from ); } + + +////////////////////////////////////////////////////////////////////////////////////////// +// SSE-X Helpers (generates either INT or FLOAT versions of certain SSE instructions) +// +// Added AlwaysUseMovaps check to the relevant functions here, which helps reduce the +// overhead of dynarec instructions that use these, even thought the same check would +// have been done redundantly by the emitter function. + +emitterT void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); + else SSE_MOVAPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); + else SSE_MOVAPS_XMM_to_M128(to, from); +} + +emitterT void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); + else SSE_MOVAPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoR(to, from, offset); + else SSE_MOVAPSRmtoR(to, from, offset); +} + +emitterT void SSEX_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRm(to, from, offset); + else SSE_MOVAPSRtoRm(to, from, offset); +} + +emitterT void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); + else SSE_MOVUPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ) +{ + if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); + else SSE_MOVUPS_XMM_to_M128(to, from); +} + +emitterT void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); + else SSE_MOVSS_M32_to_XMM(to, from); +} + +emitterT void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); + else SSE_MOVSS_XMM_to_M32(to, from); +} + +emitterT void SSEX_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_Rm_to_XMM(to, from, offset); + else SSE_MOVSS_Rm_to_XMM(to, from, offset); +} + +emitterT void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from, offset); + else SSE_MOVSS_XMM_to_Rm(to, from, offset); +} + +emitterT void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); + else SSE_ORPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); + else SSE_ORPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); + else SSE_XORPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); + else SSE_XORPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); + else SSE_ANDPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); + else SSE_ANDPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr from ) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); + else SSE_ANDNPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); + else SSE_ANDNPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); + else SSE_UNPCKLPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); + else SSE_UNPCKLPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) +{ + if( g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); + else SSE_UNPCKHPS_M128_to_XMM(to, from); +} + +emitterT void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) +{ + if( g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); + else SSE_UNPCKHPS_XMM_to_XMM(to, from); +} + +emitterT void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) +{ + if( g_xmmtypes[from] == XMMT_INT ) { + SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); + if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); + } + else { + SSE_MOVHLPS_XMM_to_XMM(to, from); + } +} diff --git a/pcsx2/x86/ix86/ix86_legacy_types.h b/pcsx2/x86/ix86/ix86_legacy_types.h new file mode 100644 index 0000000000..eb936c3366 --- /dev/null +++ b/pcsx2/x86/ix86/ix86_legacy_types.h @@ -0,0 +1,140 @@ +/* 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 + +#define SIB 4 // maps to ESP +#define SIBDISP 5 // maps to EBP +#define DISP32 5 // maps to EBP + +// general types +typedef int x86IntRegType; + +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 + +#define X86ARG1 EAX +#define X86ARG2 ECX +#define X86ARG3 EDX +#define X86ARG4 EBX + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; +/* 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 + +#define SIB 4 // maps to ESP +#define SIBDISP 5 // maps to EBP +#define DISP32 5 // maps to EBP + +// general types +typedef int x86IntRegType; + +#define EAX 0 +#define EBX 3 +#define ECX 1 +#define EDX 2 +#define ESI 6 +#define EDI 7 +#define EBP 5 +#define ESP 4 + +#define X86ARG1 EAX +#define X86ARG2 ECX +#define X86ARG3 EDX +#define X86ARG4 EBX + +#define MM0 0 +#define MM1 1 +#define MM2 2 +#define MM3 3 +#define MM4 4 +#define MM5 5 +#define MM6 6 +#define MM7 7 + +typedef int x86MMXRegType; + +#define XMM0 0 +#define XMM1 1 +#define XMM2 2 +#define XMM3 3 +#define XMM4 4 +#define XMM5 5 +#define XMM6 6 +#define XMM7 7 +#define XMM8 8 +#define XMM9 9 +#define XMM10 10 +#define XMM11 11 +#define XMM12 12 +#define XMM13 13 +#define XMM14 14 +#define XMM15 15 + +typedef int x86SSERegType; diff --git a/pcsx2/x86/ix86/ix86_macros.h b/pcsx2/x86/ix86/ix86_macros.h index 2ad9cdfe47..6179fc7e1d 100644 --- a/pcsx2/x86/ix86/ix86_macros.h +++ b/pcsx2/x86/ix86/ix86_macros.h @@ -51,66 +51,51 @@ //------------------------------------------------------------------ // mov instructions //------------------------------------------------------------------ -#define MOV64RtoR eMOV64RtoR<_EmitterId_> -#define MOV64RtoM eMOV64RtoM<_EmitterId_> -#define MOV64MtoR eMOV64MtoR<_EmitterId_> -#define MOV64I32toM eMOV64I32toM<_EmitterId_> -#define MOV64I32toR eMOV64I32toR<_EmitterId_> -#define MOV64ItoR eMOV64ItoR<_EmitterId_> -#define MOV64ItoRmOffset eMOV64ItoRmOffset<_EmitterId_> -#define MOV64RmOffsettoR eMOV64RmOffsettoR<_EmitterId_> -#define MOV64RmStoR eMOV64RmStoR<_EmitterId_> -#define MOV64RtoRmOffset eMOV64RtoRmOffset<_EmitterId_> -#define MOV64RtoRmS eMOV64RtoRmS<_EmitterId_> #define MOV32RtoR eMOV32RtoR<_EmitterId_> #define MOV32RtoM eMOV32RtoM<_EmitterId_> #define MOV32MtoR eMOV32MtoR<_EmitterId_> #define MOV32RmtoR eMOV32RmtoR<_EmitterId_> -#define MOV32RmtoROffset eMOV32RmtoROffset<_EmitterId_> +#define MOV32RmtoR eMOV32RmtoR<_EmitterId_> #define MOV32RmStoR eMOV32RmStoR<_EmitterId_> #define MOV32RmSOffsettoR eMOV32RmSOffsettoR<_EmitterId_> #define MOV32RtoRm eMOV32RtoRm<_EmitterId_> #define MOV32RtoRmS eMOV32RtoRmS<_EmitterId_> #define MOV32ItoR eMOV32ItoR<_EmitterId_> #define MOV32ItoM eMOV32ItoM<_EmitterId_> -#define MOV32ItoRmOffset eMOV32ItoRmOffset<_EmitterId_> -#define MOV32RtoRmOffset eMOV32RtoRmOffset<_EmitterId_> +#define MOV32ItoRm eMOV32ItoRm<_EmitterId_> +#define MOV32RtoRm eMOV32RtoRm<_EmitterId_> #define MOV16RtoM eMOV16RtoM<_EmitterId_> #define MOV16MtoR eMOV16MtoR<_EmitterId_> #define MOV16RmtoR eMOV16RmtoR<_EmitterId_> -#define MOV16RmtoROffset eMOV16RmtoROffset<_EmitterId_> +#define MOV16RmtoR eMOV16RmtoR<_EmitterId_> #define MOV16RmSOffsettoR eMOV16RmSOffsettoR<_EmitterId_> #define MOV16RtoRm eMOV16RtoRm<_EmitterId_> #define MOV16ItoM eMOV16ItoM<_EmitterId_> #define MOV16RtoRmS eMOV16RtoRmS<_EmitterId_> #define MOV16ItoR eMOV16ItoR<_EmitterId_> -#define MOV16ItoRmOffset eMOV16ItoRmOffset<_EmitterId_> -#define MOV16RtoRmOffset eMOV16RtoRmOffset<_EmitterId_> +#define MOV16ItoRm eMOV16ItoRm<_EmitterId_> +#define MOV16RtoRm eMOV16RtoRm<_EmitterId_> #define MOV8RtoM eMOV8RtoM<_EmitterId_> #define MOV8MtoR eMOV8MtoR<_EmitterId_> #define MOV8RmtoR eMOV8RmtoR<_EmitterId_> -#define MOV8RmtoROffset eMOV8RmtoROffset<_EmitterId_> +#define MOV8RmtoR eMOV8RmtoR<_EmitterId_> #define MOV8RmSOffsettoR eMOV8RmSOffsettoR<_EmitterId_> #define MOV8RtoRm eMOV8RtoRm<_EmitterId_> #define MOV8ItoM eMOV8ItoM<_EmitterId_> #define MOV8ItoR eMOV8ItoR<_EmitterId_> -#define MOV8ItoRmOffset eMOV8ItoRmOffset<_EmitterId_> -#define MOV8RtoRmOffset eMOV8RtoRmOffset<_EmitterId_> +#define MOV8ItoRm eMOV8ItoRm<_EmitterId_> +#define MOV8RtoRm eMOV8RtoRm<_EmitterId_> #define MOVSX32R8toR eMOVSX32R8toR<_EmitterId_> #define MOVSX32Rm8toR eMOVSX32Rm8toR<_EmitterId_> -#define MOVSX32Rm8toROffset eMOVSX32Rm8toROffset<_EmitterId_> #define MOVSX32M8toR eMOVSX32M8toR<_EmitterId_> #define MOVSX32R16toR eMOVSX32R16toR<_EmitterId_> #define MOVSX32Rm16toR eMOVSX32Rm16toR<_EmitterId_> -#define MOVSX32Rm16toROffset eMOVSX32Rm16toROffset<_EmitterId_> #define MOVSX32M16toR eMOVSX32M16toR<_EmitterId_> #define MOVZX32R8toR eMOVZX32R8toR<_EmitterId_> #define MOVZX32Rm8toR eMOVZX32Rm8toR<_EmitterId_> -#define MOVZX32Rm8toROffset eMOVZX32Rm8toROffset<_EmitterId_> #define MOVZX32M8toR eMOVZX32M8toR<_EmitterId_> #define MOVZX32R16toR eMOVZX32R16toR<_EmitterId_> #define MOVZX32Rm16toR eMOVZX32Rm16toR<_EmitterId_> -#define MOVZX32Rm16toROffset eMOVZX32Rm16toROffset<_EmitterId_> #define MOVZX32M16toR eMOVZX32M16toR<_EmitterId_> #define CMOVBE32RtoR eCMOVBE32RtoR<_EmitterId_> #define CMOVBE32MtoR eCMOVBE32MtoR<_EmitterId_> @@ -147,12 +132,10 @@ //------------------------------------------------------------------ // arithmetic instructions //------------------------------------------------------------------ -#define ADD64ItoR eADD64ItoR<_EmitterId_> -#define ADD64MtoR eADD64MtoR<_EmitterId_> #define ADD32ItoEAX eADD32ItoEAX<_EmitterId_> #define ADD32ItoR eADD32ItoR<_EmitterId_> #define ADD32ItoM eADD32ItoM<_EmitterId_> -#define ADD32ItoRmOffset eADD32ItoRmOffset<_EmitterId_> +#define ADD32ItoRm eADD32ItoRm<_EmitterId_> #define ADD32RtoR eADD32RtoR<_EmitterId_> #define ADD32RtoM eADD32RtoM<_EmitterId_> #define ADD32MtoR eADD32MtoR<_EmitterId_> @@ -171,7 +154,6 @@ #define INC32M eINC32M<_EmitterId_> #define INC16R eINC16R<_EmitterId_> #define INC16M eINC16M<_EmitterId_> -#define SUB64MtoR eSUB64MtoR<_EmitterId_> #define SUB32ItoR eSUB32ItoR<_EmitterId_> #define SUB32ItoM eSUB32ItoM<_EmitterId_> #define SUB32RtoR eSUB32RtoR<_EmitterId_> @@ -181,7 +163,6 @@ #define SUB16ItoR eSUB16ItoR<_EmitterId_> #define SUB16ItoM eSUB16ItoM<_EmitterId_> #define SUB16MtoR eSUB16MtoR<_EmitterId_> -#define SBB64RtoR eSBB64RtoR<_EmitterId_> #define SBB32ItoR eSBB32ItoR<_EmitterId_> #define SBB32ItoM eSBB32ItoM<_EmitterId_> #define SBB32RtoR eSBB32RtoR<_EmitterId_> @@ -203,12 +184,6 @@ //------------------------------------------------------------------ // shifting instructions //------------------------------------------------------------------ -#define SHL64ItoR eSHL64ItoR<_EmitterId_> -#define SHL64CLtoR eSHL64CLtoR<_EmitterId_> -#define SHR64ItoR eSHR64ItoR<_EmitterId_> -#define SHR64CLtoR eSHR64CLtoR<_EmitterId_> -#define SAR64ItoR eSAR64ItoR<_EmitterId_> -#define SAR64CLtoR eSAR64CLtoR<_EmitterId_> #define SHL32ItoR eSHL32ItoR<_EmitterId_> #define SHL32ItoM eSHL32ItoM<_EmitterId_> #define SHL32CLtoR eSHL32CLtoR<_EmitterId_> @@ -231,10 +206,6 @@ //------------------------------------------------------------------ // logical instructions //------------------------------------------------------------------ -#define OR64ItoR eOR64ItoR<_EmitterId_> -#define OR64MtoR eOR64MtoR<_EmitterId_> -#define OR64RtoR eOR64RtoR<_EmitterId_> -#define OR64RtoM eOR64RtoM<_EmitterId_> #define OR32ItoR eOR32ItoR<_EmitterId_> #define OR32ItoM eOR32ItoM<_EmitterId_> #define OR32RtoR eOR32RtoR<_EmitterId_> @@ -249,11 +220,6 @@ #define OR8RtoM eOR8RtoM<_EmitterId_> #define OR8ItoM eOR8ItoM<_EmitterId_> #define OR8MtoR eOR8MtoR<_EmitterId_> -#define XOR64ItoR eXOR64ItoR<_EmitterId_> -#define XOR64RtoR eXOR64RtoR<_EmitterId_> -#define XOR64MtoR eXOR64MtoR<_EmitterId_> -#define XOR64RtoR eXOR64RtoR<_EmitterId_> -#define XOR64RtoM eXOR64RtoM<_EmitterId_> #define XOR32ItoR eXOR32ItoR<_EmitterId_> #define XOR32ItoM eXOR32ItoM<_EmitterId_> #define XOR32RtoR eXOR32RtoR<_EmitterId_> @@ -262,11 +228,6 @@ #define XOR32MtoR eXOR32MtoR<_EmitterId_> #define XOR16RtoM eXOR16RtoM<_EmitterId_> #define XOR16ItoR eXOR16ItoR<_EmitterId_> -#define AND64I32toR eAND64I32toR<_EmitterId_> -#define AND64MtoR eAND64MtoR<_EmitterId_> -#define AND64RtoM eAND64RtoM<_EmitterId_> -#define AND64RtoR eAND64RtoR<_EmitterId_> -#define AND64I32toM eAND64I32toM<_EmitterId_> #define AND32ItoR eAND32ItoR<_EmitterId_> #define AND32I8toR eAND32I8toR<_EmitterId_> #define AND32ItoM eAND32ItoM<_EmitterId_> @@ -275,7 +236,7 @@ #define AND32RtoM eAND32RtoM<_EmitterId_> #define AND32MtoR eAND32MtoR<_EmitterId_> #define AND32RmtoR eAND32RmtoR<_EmitterId_> -#define AND32RmtoROffset eAND32RmtoROffset<_EmitterId_> +#define AND32RmtoR eAND32RmtoR<_EmitterId_> #define AND16RtoR eAND16RtoR<_EmitterId_> #define AND16ItoR eAND16ItoR<_EmitterId_> #define AND16ItoM eAND16ItoM<_EmitterId_> @@ -286,10 +247,8 @@ #define AND8RtoM eAND8RtoM<_EmitterId_> #define AND8MtoR eAND8MtoR<_EmitterId_> #define AND8RtoR eAND8RtoR<_EmitterId_> -#define NOT64R eNOT64R<_EmitterId_> #define NOT32R eNOT32R<_EmitterId_> #define NOT32M eNOT32M<_EmitterId_> -#define NEG64R eNEG64R<_EmitterId_> #define NEG32R eNEG32R<_EmitterId_> #define NEG32M eNEG32M<_EmitterId_> #define NEG16R eNEG16R<_EmitterId_> @@ -349,15 +308,13 @@ //------------------------------------------------------------------ // misc instructions //------------------------------------------------------------------ -#define CMP64I32toR eCMP64I32toR<_EmitterId_> -#define CMP64MtoR eCMP64MtoR<_EmitterId_> -#define CMP64RtoR eCMP64RtoR<_EmitterId_> #define CMP32ItoR eCMP32ItoR<_EmitterId_> #define CMP32ItoM eCMP32ItoM<_EmitterId_> #define CMP32RtoR eCMP32RtoR<_EmitterId_> #define CMP32MtoR eCMP32MtoR<_EmitterId_> +#define CMP32ItoRm eCMP32ItoRm<_EmitterId_> +#define CMP8I8toRm eCMP8I8toRm<_EmitterId_> #define CMP32I8toRm eCMP32I8toRm<_EmitterId_> -#define CMP32I8toRmOffset8 eCMP32I8toRmOffset8<_EmitterId_> #define CMP32I8toM eCMP32I8toM<_EmitterId_> #define CMP16ItoR eCMP16ItoR<_EmitterId_> #define CMP16ItoM eCMP16ItoM<_EmitterId_> @@ -539,16 +496,16 @@ #define PUNPCKHDQMtoR ePUNPCKHDQMtoR<_EmitterId_> #define MOVQ64ItoR eMOVQ64ItoR<_EmitterId_> #define MOVQRtoR eMOVQRtoR<_EmitterId_> -#define MOVQRmtoROffset eMOVQRmtoROffset<_EmitterId_> -#define MOVQRtoRmOffset eMOVQRtoRmOffset<_EmitterId_> +#define MOVQRmtoR eMOVQRmtoR<_EmitterId_> +#define MOVQRtoRm eMOVQRtoRm<_EmitterId_> #define MOVDMtoMMX eMOVDMtoMMX<_EmitterId_> #define MOVDMMXtoM eMOVDMMXtoM<_EmitterId_> #define MOVD32RtoMMX eMOVD32RtoMMX<_EmitterId_> #define MOVD32RmtoMMX eMOVD32RmtoMMX<_EmitterId_> -#define MOVD32RmOffsettoMMX eMOVD32RmOffsettoMMX<_EmitterId_> +#define MOVD32RmtoMMX eMOVD32RmtoMMX<_EmitterId_> #define MOVD32MMXtoR eMOVD32MMXtoR<_EmitterId_> #define MOVD32MMXtoRm eMOVD32MMXtoRm<_EmitterId_> -#define MOVD32MMXtoRmOffset eMOVD32MMXtoRmOffset<_EmitterId_> +#define MOVD32MMXtoRm eMOVD32MMXtoRm<_EmitterId_> #define PINSRWRtoMMX ePINSRWRtoMMX<_EmitterId_> #define PSHUFWRtoR ePSHUFWRtoR<_EmitterId_> #define PSHUFWMtoR ePSHUFWMtoR<_EmitterId_> @@ -575,33 +532,31 @@ #define SSE_MOVSS_XMM_to_M32 eSSE_MOVSS_XMM_to_M32<_EmitterId_> #define SSE_MOVSS_XMM_to_Rm eSSE_MOVSS_XMM_to_Rm<_EmitterId_> #define SSE_MOVSS_XMM_to_XMM eSSE_MOVSS_XMM_to_XMM<_EmitterId_> -#define SSE_MOVSS_RmOffset_to_XMM eSSE_MOVSS_RmOffset_to_XMM<_EmitterId_> -#define SSE_MOVSS_XMM_to_RmOffset eSSE_MOVSS_XMM_to_RmOffset<_EmitterId_> +#define SSE_MOVSS_Rm_to_XMM eSSE_MOVSS_Rm_to_XMM<_EmitterId_> +#define SSE_MOVSS_XMM_to_Rm eSSE_MOVSS_XMM_to_Rm<_EmitterId_> #define SSE_MASKMOVDQU_XMM_to_XMM eSSE_MASKMOVDQU_XMM_to_XMM<_EmitterId_> #define SSE_MOVLPS_M64_to_XMM eSSE_MOVLPS_M64_to_XMM<_EmitterId_> #define SSE_MOVLPS_XMM_to_M64 eSSE_MOVLPS_XMM_to_M64<_EmitterId_> -#define SSE_MOVLPS_RmOffset_to_XMM eSSE_MOVLPS_RmOffset_to_XMM<_EmitterId_> -#define SSE_MOVLPS_XMM_to_RmOffset eSSE_MOVLPS_XMM_to_RmOffset<_EmitterId_> +#define SSE_MOVLPS_Rm_to_XMM eSSE_MOVLPS_Rm_to_XMM<_EmitterId_> +#define SSE_MOVLPS_XMM_to_Rm eSSE_MOVLPS_XMM_to_Rm<_EmitterId_> #define SSE_MOVHPS_M64_to_XMM eSSE_MOVHPS_M64_to_XMM<_EmitterId_> #define SSE_MOVHPS_XMM_to_M64 eSSE_MOVHPS_XMM_to_M64<_EmitterId_> -#define SSE_MOVHPS_RmOffset_to_XMM eSSE_MOVHPS_RmOffset_to_XMM<_EmitterId_> -#define SSE_MOVHPS_XMM_to_RmOffset eSSE_MOVHPS_XMM_to_RmOffset<_EmitterId_> +#define SSE_MOVHPS_Rm_to_XMM eSSE_MOVHPS_Rm_to_XMM<_EmitterId_> +#define SSE_MOVHPS_XMM_to_Rm eSSE_MOVHPS_XMM_to_Rm<_EmitterId_> #define SSE_MOVLHPS_XMM_to_XMM eSSE_MOVLHPS_XMM_to_XMM<_EmitterId_> #define SSE_MOVHLPS_XMM_to_XMM eSSE_MOVHLPS_XMM_to_XMM<_EmitterId_> #define SSE_MOVLPSRmtoR eSSE_MOVLPSRmtoR<_EmitterId_> -#define SSE_MOVLPSRmtoROffset eSSE_MOVLPSRmtoROffset<_EmitterId_> #define SSE_MOVLPSRtoRm eSSE_MOVLPSRtoRm<_EmitterId_> -#define SSE_MOVLPSRtoRmOffset eSSE_MOVLPSRtoRmOffset<_EmitterId_> #define SSE_MOVAPSRmStoR eSSE_MOVAPSRmStoR<_EmitterId_> #define SSE_MOVAPSRtoRmS eSSE_MOVAPSRtoRmS<_EmitterId_> -#define SSE_MOVAPSRtoRmOffset eSSE_MOVAPSRtoRmOffset<_EmitterId_> -#define SSE_MOVAPSRmtoROffset eSSE_MOVAPSRmtoROffset<_EmitterId_> +#define SSE_MOVAPSRtoRm eSSE_MOVAPSRtoRm<_EmitterId_> +#define SSE_MOVAPSRmtoR eSSE_MOVAPSRmtoR<_EmitterId_> #define SSE_MOVUPSRmStoR eSSE_MOVUPSRmStoR<_EmitterId_> #define SSE_MOVUPSRtoRmS eSSE_MOVUPSRtoRmS<_EmitterId_> #define SSE_MOVUPSRtoRm eSSE_MOVUPSRtoRm<_EmitterId_> #define SSE_MOVUPSRmtoR eSSE_MOVUPSRmtoR<_EmitterId_> -#define SSE_MOVUPSRmtoROffset eSSE_MOVUPSRmtoROffset<_EmitterId_> -#define SSE_MOVUPSRtoRmOffset eSSE_MOVUPSRtoRmOffset<_EmitterId_> +#define SSE_MOVUPSRmtoR eSSE_MOVUPSRmtoR<_EmitterId_> +#define SSE_MOVUPSRtoRm eSSE_MOVUPSRtoRm<_EmitterId_> #define SSE_RCPPS_XMM_to_XMM eSSE_RCPPS_XMM_to_XMM<_EmitterId_> #define SSE_RCPPS_M128_to_XMM eSSE_RCPPS_M128_to_XMM<_EmitterId_> #define SSE_RCPSS_XMM_to_XMM eSSE_RCPSS_XMM_to_XMM<_EmitterId_> @@ -676,7 +631,7 @@ #define SSE_UNPCKHPS_XMM_to_XMM eSSE_UNPCKHPS_XMM_to_XMM<_EmitterId_> #define SSE_SHUFPS_XMM_to_XMM eSSE_SHUFPS_XMM_to_XMM<_EmitterId_> #define SSE_SHUFPS_M128_to_XMM eSSE_SHUFPS_M128_to_XMM<_EmitterId_> -#define SSE_SHUFPS_RmOffset_to_XMM eSSE_SHUFPS_RmOffset_to_XMM<_EmitterId_> +#define SSE_SHUFPS_Rm_to_XMM eSSE_SHUFPS_Rm_to_XMM<_EmitterId_> #define SSE_CMPEQPS_M128_to_XMM eSSE_CMPEQPS_M128_to_XMM<_EmitterId_> #define SSE_CMPEQPS_XMM_to_XMM eSSE_CMPEQPS_XMM_to_XMM<_EmitterId_> #define SSE_CMPLTPS_M128_to_XMM eSSE_CMPLTPS_M128_to_XMM<_EmitterId_> @@ -780,8 +735,8 @@ #define SSE2_MOVQ_XMM_to_M64 eSSE2_MOVQ_XMM_to_M64<_EmitterId_> #define SSE2_MOVDQ2Q_XMM_to_MM eSSE2_MOVDQ2Q_XMM_to_MM<_EmitterId_> #define SSE2_MOVQ2DQ_MM_to_XMM eSSE2_MOVQ2DQ_MM_to_XMM<_EmitterId_> -#define SSE2_MOVDQARtoRmOffset eSSE2_MOVDQARtoRmOffset<_EmitterId_> -#define SSE2_MOVDQARmtoROffset eSSE2_MOVDQARmtoROffset<_EmitterId_> +#define SSE2_MOVDQARtoRm eSSE2_MOVDQARtoRm<_EmitterId_> +#define SSE2_MOVDQARmtoR eSSE2_MOVDQARmtoR<_EmitterId_> #define SSE2_CVTDQ2PS_M128_to_XMM eSSE2_CVTDQ2PS_M128_to_XMM<_EmitterId_> #define SSE2_CVTDQ2PS_XMM_to_XMM eSSE2_CVTDQ2PS_XMM_to_XMM<_EmitterId_> #define SSE2_CVTPS2DQ_M128_to_XMM eSSE2_CVTPS2DQ_M128_to_XMM<_EmitterId_> @@ -920,11 +875,11 @@ #define SSE2_MOVD_M32_to_XMM eSSE2_MOVD_M32_to_XMM<_EmitterId_> #define SSE2_MOVD_R_to_XMM eSSE2_MOVD_R_to_XMM<_EmitterId_> #define SSE2_MOVD_Rm_to_XMM eSSE2_MOVD_Rm_to_XMM<_EmitterId_> -#define SSE2_MOVD_RmOffset_to_XMM eSSE2_MOVD_RmOffset_to_XMM<_EmitterId_> +#define SSE2_MOVD_Rm_to_XMM eSSE2_MOVD_Rm_to_XMM<_EmitterId_> #define SSE2_MOVD_XMM_to_M32 eSSE2_MOVD_XMM_to_M32<_EmitterId_> #define SSE2_MOVD_XMM_to_R eSSE2_MOVD_XMM_to_R<_EmitterId_> #define SSE2_MOVD_XMM_to_Rm eSSE2_MOVD_XMM_to_Rm<_EmitterId_> -#define SSE2_MOVD_XMM_to_RmOffset eSSE2_MOVD_XMM_to_RmOffset<_EmitterId_> +#define SSE2_MOVD_XMM_to_Rm eSSE2_MOVD_XMM_to_Rm<_EmitterId_> #define SSE2_MOVQ_XMM_to_R eSSE2_MOVQ_XMM_to_R<_EmitterId_> #define SSE2_MOVQ_R_to_XMM eSSE2_MOVQ_R_to_XMM<_EmitterId_> //------------------------------------------------------------------ diff --git a/pcsx2/x86/ix86/ix86_mmx.inl b/pcsx2/x86/ix86/ix86_mmx.inl deleted file mode 100644 index 18126cd6e1..0000000000 --- a/pcsx2/x86/ix86/ix86_mmx.inl +++ /dev/null @@ -1,647 +0,0 @@ -/* 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 - -//------------------------------------------------------------------ -// MMX instructions -// -// note: r64 = mm -//------------------------------------------------------------------ - -/* movq m64 to r64 */ -emitterT void eMOVQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0x6F0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* movq r64 to m64 */ -emitterT void eMOVQRtoM( uptr to, x86MMXRegType from ) -{ - write16( 0x7F0F ); - ModRM( 0, from, DISP32 ); - write32(MEMADDR(to, 4)); -} - -/* pand r64 to r64 */ -emitterT void ePANDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xDB0F ); - ModRM( 3, to, from ); -} - -emitterT void ePANDNRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xDF0F ); - ModRM( 3, to, from ); -} - -/* por r64 to r64 */ -emitterT void ePORRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xEB0F ); - ModRM( 3, to, from ); -} - -/* pxor r64 to r64 */ -emitterT void ePXORRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xEF0F ); - ModRM( 3, to, from ); -} - -/* psllq r64 to r64 */ -emitterT void ePSLLQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xF30F ); - ModRM( 3, to, from ); -} - -/* psllq m64 to r64 */ -emitterT void ePSLLQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xF30F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* psllq imm8 to r64 */ -emitterT void ePSLLQItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x730F ); - ModRM( 3, 6, to); - write8( from ); -} - -/* psrlq r64 to r64 */ -emitterT void ePSRLQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xD30F ); - ModRM( 3, to, from ); -} - -/* psrlq m64 to r64 */ -emitterT void ePSRLQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xD30F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* psrlq imm8 to r64 */ -emitterT void ePSRLQItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x730F ); - ModRM( 3, 2, to); - write8( from ); -} - -/* paddusb r64 to r64 */ -emitterT void ePADDUSBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xDC0F ); - ModRM( 3, to, from ); -} - -/* paddusb m64 to r64 */ -emitterT void ePADDUSBMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xDC0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* paddusw r64 to r64 */ -emitterT void ePADDUSWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xDD0F ); - ModRM( 3, to, from ); -} - -/* paddusw m64 to r64 */ -emitterT void ePADDUSWMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xDD0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* paddb r64 to r64 */ -emitterT void ePADDBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xFC0F ); - ModRM( 3, to, from ); -} - -/* paddb m64 to r64 */ -emitterT void ePADDBMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xFC0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* paddw r64 to r64 */ -emitterT void ePADDWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xFD0F ); - ModRM( 3, to, from ); -} - -/* paddw m64 to r64 */ -emitterT void ePADDWMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xFD0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* paddd r64 to r64 */ -emitterT void ePADDDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xFE0F ); - ModRM( 3, to, from ); -} - -/* paddd m64 to r64 */ -emitterT void ePADDDMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xFE0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* emms */ -emitterT void eEMMS() -{ - write16( 0x770F ); -} - -emitterT void ePADDSBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xEC0F ); - ModRM( 3, to, from ); -} - -emitterT void ePADDSWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xED0F ); - ModRM( 3, to, from ); -} - -// paddq m64 to r64 (sse2 only?) -emitterT void ePADDQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xD40F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// paddq r64 to r64 (sse2 only?) -emitterT void ePADDQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xD40F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBSBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xE80F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBSWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xE90F ); - ModRM( 3, to, from ); -} - - -emitterT void ePSUBBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xF80F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xF90F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xFA0F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBDMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xFA0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePSUBUSBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xD80F ); - ModRM( 3, to, from ); -} - -emitterT void ePSUBUSWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xD90F ); - ModRM( 3, to, from ); -} - -// psubq m64 to r64 (sse2 only?) -emitterT void ePSUBQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xFB0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// psubq r64 to r64 (sse2 only?) -emitterT void ePSUBQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xFB0F ); - ModRM( 3, to, from ); -} - -// pmuludq m64 to r64 (sse2 only?) -emitterT void ePMULUDQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xF40F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -// pmuludq r64 to r64 (sse2 only?) -emitterT void ePMULUDQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xF40F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPEQBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x740F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPEQWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x750F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPEQDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x760F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPEQDMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0x760F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePCMPGTBRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x640F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPGTWRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x650F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPGTDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x660F ); - ModRM( 3, to, from ); -} - -emitterT void ePCMPGTDMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0x660F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePSRLWItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x710F ); - ModRM( 3, 2 , to ); - write8( from ); -} - -emitterT void ePSRLDItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x720F ); - ModRM( 3, 2 , to ); - write8( from ); -} - -emitterT void ePSRLDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xD20F ); - ModRM( 3, to, from ); -} - -emitterT void ePSLLWItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x710F ); - ModRM( 3, 6 , to ); - write8( from ); -} - -emitterT void ePSLLDItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x720F ); - ModRM( 3, 6 , to ); - write8( from ); -} - -emitterT void ePSLLDRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xF20F ); - ModRM( 3, to, from ); -} - -emitterT void ePSRAWItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x710F ); - ModRM( 3, 4 , to ); - write8( from ); -} - -emitterT void ePSRADItoR( x86MMXRegType to, u8 from ) -{ - write16( 0x720F ); - ModRM( 3, 4 , to ); - write8( from ); -} - -emitterT void ePSRADRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0xE20F ); - ModRM( 3, to, from ); -} - -/* por m64 to r64 */ -emitterT void ePORMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xEB0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* pxor m64 to r64 */ -emitterT void ePXORMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xEF0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* pand m64 to r64 */ -emitterT void ePANDMtoR( x86MMXRegType to, uptr from ) -{ - //u64 rip = (u64)x86Ptr[0] + 7; - write16( 0xDB0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePANDNMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0xDF0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePUNPCKHDQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x6A0F ); - ModRM( 3, to, from ); -} - -emitterT void ePUNPCKHDQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0x6A0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void ePUNPCKLDQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x620F ); - ModRM( 3, to, from ); -} - -emitterT void ePUNPCKLDQMtoR( x86MMXRegType to, uptr from ) -{ - write16( 0x620F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void eMOVQ64ItoR( x86MMXRegType reg, u64 i ) -{ - eMOVQMtoR( reg, ( uptr )(x86Ptr[0]) + 2 + 7 ); - eJMP8( 8 ); - write64( i ); -} - -emitterT void eMOVQRtoR( x86MMXRegType to, x86MMXRegType from ) -{ - write16( 0x6F0F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVQRmtoROffset( x86MMXRegType to, x86IntRegType from, u32 offset ) -{ - write16( 0x6F0F ); - - if( offset < 128 ) { - ModRM( 1, to, from ); - write8(offset); - } - else { - ModRM( 2, to, from ); - write32(offset); - } -} - -emitterT void eMOVQRtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) -{ - write16( 0x7F0F ); - - if( offset < 128 ) { - ModRM( 1, from , to ); - write8(offset); - } - else { - ModRM( 2, from, to ); - write32(offset); - } -} - -/* movd m32 to r64 */ -emitterT void eMOVDMtoMMX( x86MMXRegType to, uptr from ) -{ - write16( 0x6E0F ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -/* movd r64 to m32 */ -emitterT void eMOVDMMXtoM( uptr to, x86MMXRegType from ) -{ - write16( 0x7E0F ); - ModRM( 0, from, DISP32 ); - write32( MEMADDR(to, 4) ); -} - -emitterT void eMOVD32RtoMMX( x86MMXRegType to, x86IntRegType from ) -{ - write16( 0x6E0F ); - ModRM( 3, to, from ); -} - -emitterT void eMOVD32RmtoMMX( x86MMXRegType to, x86IntRegType from ) -{ - write16( 0x6E0F ); - ModRM( 0, to, from ); -} - -emitterT void eMOVD32RmOffsettoMMX( x86MMXRegType to, x86IntRegType from, u32 offset ) -{ - write16( 0x6E0F ); - - if( offset < 128 ) { - ModRM( 1, to, from ); - write8(offset); - } - else { - ModRM( 2, to, from ); - write32(offset); - } -} - -emitterT void eMOVD32MMXtoR( x86IntRegType to, x86MMXRegType from ) -{ - write16( 0x7E0F ); - ModRM( 3, from, to ); -} - -emitterT void eMOVD32MMXtoRm( x86IntRegType to, x86MMXRegType from ) -{ - write16( 0x7E0F ); - ModRM( 0, from, to ); - if( to >= 4 ) { - // no idea why - assert( to == ESP ); - write8(0x24); - } - -} - -emitterT void eMOVD32MMXtoRmOffset( x86IntRegType to, x86MMXRegType from, u32 offset ) -{ - write16( 0x7E0F ); - - if( offset < 128 ) { - ModRM( 1, from, to ); - write8(offset); - } - else { - ModRM( 2, from, to ); - write32(offset); - } -} - -///* movd r32 to r64 */ -//emitterT void eMOVD32MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) -//{ -// write16( 0x6E0F ); -// ModRM( 3, to, from ); -//} -// -///* movq r64 to r32 */ -//emitterT void eMOVD64MMXtoMMX( x86MMXRegType to, x86MMXRegType from ) -//{ -// write16( 0x7E0F ); -// ModRM( 3, from, to ); -//} - -// untested -emitterT void ePACKSSWBMMXtoMMX(x86MMXRegType to, x86MMXRegType from) -{ - write16( 0x630F ); - ModRM( 3, to, from ); -} - -emitterT void ePACKSSDWMMXtoMMX(x86MMXRegType to, x86MMXRegType from) -{ - write16( 0x6B0F ); - ModRM( 3, to, from ); -} - -emitterT void ePMOVMSKBMMXtoR(x86IntRegType to, x86MMXRegType from) -{ - write16( 0xD70F ); - ModRM( 3, to, from ); -} - -emitterT void ePINSRWRtoMMX( x86MMXRegType to, x86SSERegType from, u8 imm8 ) -{ - if (to > 7 || from > 7) Rex(1, to >> 3, 0, from >> 3); - write16( 0xc40f ); - ModRM( 3, to, from ); - write8( imm8 ); -} - -emitterT void ePSHUFWRtoR(x86MMXRegType to, x86MMXRegType from, u8 imm8) -{ - write16(0x700f); - ModRM( 3, to, from ); - write8(imm8); -} - -emitterT void ePSHUFWMtoR(x86MMXRegType to, uptr from, u8 imm8) -{ - write16( 0x700f ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); - write8(imm8); -} - -emitterT void eMASKMOVQRtoR(x86MMXRegType to, x86MMXRegType from) -{ - write16(0xf70f); - ModRM( 3, to, from ); -} diff --git a/pcsx2/x86/ix86/ix86_simd.cpp b/pcsx2/x86/ix86/ix86_simd.cpp new file mode 100644 index 0000000000..860e8ffc0a --- /dev/null +++ b/pcsx2/x86/ix86/ix86_simd.cpp @@ -0,0 +1,396 @@ +/* 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 + */ + +#include "PrecompiledHeader.h" + +#include "System.h" +#include "ix86_internal.h" + +namespace x86Emitter { + +using namespace Internal; + +// ------------------------------------------------------------------------ +// SimdPrefix - If the lower byte of the opcode is 0x38 or 0x3a, then the opcode is +// treated as a 16 bit value (in SSE 0x38 and 0x3a denote prefixes for extended SSE3/4 +// instructions). Any other lower value assumes the upper value is 0 and ignored. +// Non-zero upper bytes, when the lower byte is not the 0x38 or 0x3a prefix, will +// generate an assertion. +// +__emitinline void Internal::SimdPrefix( u8 prefix, u16 opcode ) +{ + const bool is16BitOpcode = ((opcode & 0xff) == 0x38) || ((opcode & 0xff) == 0x3a); + + // If the lower byte is not a valid prefix and the upper byte is non-zero it + // means we made a mistake! + if( !is16BitOpcode ) jASSUME( (opcode >> 8) == 0 ); + + if( prefix != 0 ) + { + if( is16BitOpcode ) + xWrite32( (opcode<<16) | 0x0f00 | prefix ); + else + { + xWrite16( 0x0f00 | prefix ); + xWrite8( opcode ); + } + } + else + { + if( is16BitOpcode ) + { + xWrite8( 0x0f ); + xWrite16( opcode ); + } + else + xWrite16( (opcode<<8) | 0x0f ); + } +} + +// [SSE-3] +const SimdImpl_DestRegSSE<0xf3,0x12> xMOVSLDUP; +// [SSE-3] +const SimdImpl_DestRegSSE<0xf3,0x16> xMOVSHDUP; + +const SimdImpl_MoveSSE<0x00,true> xMOVAPS; + +// Note: All implementations of Unaligned Movs will, when possible, use aligned movs instead. +// This happens when using Mem,Reg or Reg,Mem forms where the address is simple displacement +// which can be checked for alignment at runtime. +const SimdImpl_MoveSSE<0x00,false> xMOVUPS; + +#ifdef ALWAYS_USE_MOVAPS +const SimdImpl_MoveSSE<0,true> xMOVDQA; +const SimdImpl_MoveSSE<0,true> xMOVAPD; + +// Note: All implementations of Unaligned Movs will, when possible, use aligned movs instead. +// This happens when using Mem,Reg or Reg,Mem forms where the address is simple displacement +// which can be checked for alignment at runtime. +const SimdImpl_MoveSSE<0,false> xMOVDQU; +const SimdImpl_MoveSSE<0,false> xMOVUPD; +#else +const SimdImpl_MoveDQ<0x66, 0x6f, 0x7f> xMOVDQA; +const SimdImpl_MoveDQ<0xf3, 0x6f, 0x7f> xMOVDQU; +const SimdImpl_MoveSSE<0x66,true> xMOVAPD; +const SimdImpl_MoveSSE<0x66,false> xMOVUPD; +#endif + +const MovhlImplAll<0x16> xMOVH; +const MovhlImplAll<0x12> xMOVL; +const MovhlImpl_RtoR<0x16> xMOVLH; +const MovhlImpl_RtoR<0x12> xMOVHL; + +const SimdImpl_DestRegEither<0x66,0xdb> xPAND; +const SimdImpl_DestRegEither<0x66,0xdf> xPANDN; +const SimdImpl_DestRegEither<0x66,0xeb> xPOR; +const SimdImpl_DestRegEither<0x66,0xef> xPXOR; + +const SimdImpl_AndNot xANDN; + +const SimdImpl_UcomI<0x66,0x2e> xUCOMI; +const SimdImpl_rSqrt<0x53> xRCP; +const SimdImpl_rSqrt<0x52> xRSQRT; +const SimdImpl_Sqrt<0x51> xSQRT; + +const SimdImpl_MinMax<0x5f> xMAX; +const SimdImpl_MinMax<0x5d> xMIN; +const SimdImpl_Shuffle<0xc6> xSHUF; + +// ------------------------------------------------------------------------ + +// [SSE-4.1] Performs a bitwise AND of dest against src, and sets the ZF flag +// only if all bits in the result are 0. PTEST also sets the CF flag according +// to the following condition: (xmm2/m128 AND NOT xmm1) == 0; +extern const Internal::SimdImpl_DestRegSSE<0x66,0x1738> xPTEST; + +const SimdImpl_Compare xCMPEQ; +const SimdImpl_Compare xCMPLT; +const SimdImpl_Compare xCMPLE; +const SimdImpl_Compare xCMPUNORD; +const SimdImpl_Compare xCMPNE; +const SimdImpl_Compare xCMPNLT; +const SimdImpl_Compare xCMPNLE; +const SimdImpl_Compare xCMPORD; + +// ------------------------------------------------------------------------ +// SSE Conversion Operations, as looney as they are. +// +// These enforce pointer strictness for Indirect forms, due to the otherwise completely confusing +// nature of the functions. (so if a function expects an m32, you must use (u32*) or ptr32[]). +// +const SimdImpl_DestRegStrict<0xf3,0xe6,xRegisterSSE,xRegisterSSE,u64> xCVTDQ2PD; +const SimdImpl_DestRegStrict<0x00,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTDQ2PS; + +const SimdImpl_DestRegStrict<0xf2,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTPD2DQ; +const SimdImpl_DestRegStrict<0x66,0x2d,xRegisterMMX,xRegisterSSE,u128> xCVTPD2PI; +const SimdImpl_DestRegStrict<0x66,0x5a,xRegisterSSE,xRegisterSSE,u128> xCVTPD2PS; + +const SimdImpl_DestRegStrict<0x66,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PD; +const SimdImpl_DestRegStrict<0x00,0x2a,xRegisterSSE,xRegisterMMX,u64> xCVTPI2PS; + +const SimdImpl_DestRegStrict<0x66,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTPS2DQ; +const SimdImpl_DestRegStrict<0x00,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTPS2PD; +const SimdImpl_DestRegStrict<0x00,0x2d,xRegisterMMX,xRegisterSSE,u64> xCVTPS2PI; + +const SimdImpl_DestRegStrict<0xf2,0x2d,xRegister32, xRegisterSSE,u64> xCVTSD2SI; +const SimdImpl_DestRegStrict<0xf2,0x5a,xRegisterSSE,xRegisterSSE,u64> xCVTSD2SS; +const SimdImpl_DestRegStrict<0xf2,0x2a,xRegisterMMX,xRegister32, u32> xCVTSI2SD; +const SimdImpl_DestRegStrict<0xf3,0x2a,xRegisterSSE,xRegister32, u32> xCVTSI2SS; + +const SimdImpl_DestRegStrict<0xf3,0x5a,xRegisterSSE,xRegisterSSE,u32> xCVTSS2SD; +const SimdImpl_DestRegStrict<0xf3,0x2d,xRegister32, xRegisterSSE,u32> xCVTSS2SI; + +const SimdImpl_DestRegStrict<0x66,0xe6,xRegisterSSE,xRegisterSSE,u128> xCVTTPD2DQ; +const SimdImpl_DestRegStrict<0x66,0x2c,xRegisterMMX,xRegisterSSE,u128> xCVTTPD2PI; +const SimdImpl_DestRegStrict<0xf3,0x5b,xRegisterSSE,xRegisterSSE,u128> xCVTTPS2DQ; +const SimdImpl_DestRegStrict<0x00,0x2c,xRegisterMMX,xRegisterSSE,u64> xCVTTPS2PI; + +const SimdImpl_DestRegStrict<0xf2,0x2c,xRegister32, xRegisterSSE,u64> xCVTTSD2SI; +const SimdImpl_DestRegStrict<0xf3,0x2c,xRegister32, xRegisterSSE,u32> xCVTTSS2SI; + +// ------------------------------------------------------------------------ + +const SimdImpl_Shift<0xd0, 2> xPSRL; +const SimdImpl_Shift<0xf0, 6> xPSLL; +const SimdImpl_ShiftWithoutQ<0xe0, 4> xPSRA; + +const SimdImpl_AddSub<0xdc, 0xd4> xPADD; +const SimdImpl_AddSub<0xd8, 0xfb> xPSUB; +const SimdImpl_PMinMax<0xde,0x3c> xPMAX; +const SimdImpl_PMinMax<0xda,0x38> xPMIN; + +const SimdImpl_PMul xPMUL; +const SimdImpl_PCompare xPCMP; +const SimdImpl_PShuffle xPSHUF; +const SimdImpl_PUnpack xPUNPCK; +const SimdImpl_Unpack xUNPCK; +const SimdImpl_Pack xPACK; + +const SimdImpl_PAbsolute xPABS; +const SimdImpl_PSign xPSIGN; +const SimdImpl_PInsert xPINSR; +const SimdImpl_PExtract xPEXTR; +const SimdImpl_PMultAdd xPMADD; +const SimdImpl_HorizAdd xHADD; + +const SimdImpl_Blend xBLEND; +const SimdImpl_DotProduct xDP; +const SimdImpl_Round xROUND; + +const SimdImpl_PMove xPMOVSX; +const SimdImpl_PMove xPMOVZX; + + +////////////////////////////////////////////////////////////////////////////////////////// +// + +// Converts from MMX register mode to FPU register mode. The cpu enters MMX register mode +// when ever MMX instructions are run, and if FPU instructions are run without using EMMS, +// the FPU results will be invalid. +__forceinline void xEMMS() { xWrite16( 0x770F ); } + +// [3DNow] Same as EMMS, but an AMD special version which may (or may not) leave MMX regs +// in an undefined state (which is fine, since presumably you're done using them anyway). +// This instruction is thus faster than EMMS on K8s, but all newer AMD cpus use the same +// logic for either EMMS or FEMMS. +// Conclusion: Obsolete. Just use EMMS instead. +__forceinline void xFEMMS() { xWrite16( 0x0E0F ); } + + +// Store Streaming SIMD Extension Control/Status to Mem32. +__emitinline void xSTMXCSR( u32* dest ) +{ + SimdPrefix( 0, 0xae ); + EmitSibMagic( 3, dest ); +} + +// Load Streaming SIMD Extension Control/Status from Mem32. +__emitinline void xLDMXCSR( const u32* src ) +{ + SimdPrefix( 0, 0xae ); + EmitSibMagic( 2, src ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// MMX Mov Instructions (MOVD, MOVQ, MOVSS). +// +// Notes: +// * Some of the functions have been renamed to more clearly reflect what they actually +// do. Namely we've affixed "ZX" to several MOVs that take a register as a destination +// since that's what they do (MOVD clears upper 32/96 bits, etc). +// +// * MOVD has valid forms for MMX and XMM registers. +// + +__forceinline void xMOVDZX( const xRegisterSSE& to, const xRegister32& from ) { xOpWrite0F( 0x66, 0x6e, to, from ); } +__forceinline void xMOVDZX( const xRegisterSSE& to, const void* src ) { xOpWrite0F( 0x66, 0x6e, to, src ); } +__forceinline void xMOVDZX( const xRegisterSSE& to, const ModSibBase& src ) { xOpWrite0F( 0x66, 0x6e, to, src ); } + +__forceinline void xMOVDZX( const xRegisterMMX& to, const xRegister32& from ) { xOpWrite0F( 0x6e, to, from ); } +__forceinline void xMOVDZX( const xRegisterMMX& to, const void* src ) { xOpWrite0F( 0x6e, to, src ); } +__forceinline void xMOVDZX( const xRegisterMMX& to, const ModSibBase& src ) { xOpWrite0F( 0x6e, to, src ); } + +__forceinline void xMOVD( const xRegister32& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0x7e, from, to ); } +__forceinline void xMOVD( void* dest, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0x7e, from, dest ); } +__forceinline void xMOVD( const ModSibBase& dest, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0x7e, from, dest ); } + +__forceinline void xMOVD( const xRegister32& to, const xRegisterMMX& from ) { xOpWrite0F( 0x7e, from, to ); } +__forceinline void xMOVD( void* dest, const xRegisterMMX& from ) { xOpWrite0F( 0x7e, from, dest ); } +__forceinline void xMOVD( const ModSibBase& dest, const xRegisterMMX& from ) { xOpWrite0F( 0x7e, from, dest ); } + + +// Moves from XMM to XMM, with the *upper 64 bits* of the destination register +// being cleared to zero. +__forceinline void xMOVQZX( const xRegisterSSE& to, const xRegisterSSE& from ) { xOpWrite0F( 0xf3, 0x7e, to, from ); } + +// Moves from XMM to XMM, with the *upper 64 bits* of the destination register +// being cleared to zero. +__forceinline void xMOVQZX( const xRegisterSSE& to, const ModSibBase& src ) { xOpWrite0F( 0xf3, 0x7e, to, src ); } + +// Moves from XMM to XMM, with the *upper 64 bits* of the destination register +// being cleared to zero. +__forceinline void xMOVQZX( const xRegisterSSE& to, const void* src ) { xOpWrite0F( 0xf3, 0x7e, to, src ); } + +// Moves lower quad of XMM to ptr64 (no bits are cleared) +__forceinline void xMOVQ( const ModSibBase& dest, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xd6, from, dest ); } +// Moves lower quad of XMM to ptr64 (no bits are cleared) +__forceinline void xMOVQ( void* dest, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xd6, from, dest ); } + +__forceinline void xMOVQ( const xRegisterMMX& to, const xRegisterMMX& from ) { if( to != from ) xOpWrite0F( 0x6f, to, from ); } +__forceinline void xMOVQ( const xRegisterMMX& to, const ModSibBase& src ) { xOpWrite0F( 0x6f, to, src ); } +__forceinline void xMOVQ( const xRegisterMMX& to, const void* src ) { xOpWrite0F( 0x6f, to, src ); } +__forceinline void xMOVQ( const ModSibBase& dest, const xRegisterMMX& from ) { xOpWrite0F( 0x7f, from, dest ); } +__forceinline void xMOVQ( void* dest, const xRegisterMMX& from ) { xOpWrite0F( 0x7f, from, dest ); } + +// This form of xMOVQ is Intel's adeptly named 'MOVQ2DQ' +__forceinline void xMOVQ( const xRegisterSSE& to, const xRegisterMMX& from ) { xOpWrite0F( 0xf3, 0xd6, to, from ); } + +// This form of xMOVQ is Intel's adeptly named 'MOVDQ2Q' +__forceinline void xMOVQ( const xRegisterMMX& to, const xRegisterSSE& from ) +{ + // Manual implementation of this form of MOVQ, since its parameters are unique in a way + // that breaks the template inference of writeXMMop(); + + SimdPrefix( 0xf2, 0xd6 ); + EmitSibMagic( to, from ); +} + +////////////////////////////////////////////////////////////////////////////////////////// +// + +#define IMPLEMENT_xMOVS( ssd, prefix ) \ + __forceinline void xMOV##ssd( const xRegisterSSE& to, const xRegisterSSE& from ) { if( to != from ) xOpWrite0F( prefix, 0x10, to, from ); } \ + __forceinline void xMOV##ssd##ZX( const xRegisterSSE& to, const void* from ) { xOpWrite0F( prefix, 0x10, to, from ); } \ + __forceinline void xMOV##ssd##ZX( const xRegisterSSE& to, const ModSibBase& from ) { xOpWrite0F( prefix, 0x10, to, from ); } \ + __forceinline void xMOV##ssd( const void* to, const xRegisterSSE& from ) { xOpWrite0F( prefix, 0x11, from, to ); } \ + __forceinline void xMOV##ssd( const ModSibBase& to, const xRegisterSSE& from ) { xOpWrite0F( prefix, 0x11, from, to ); } + +IMPLEMENT_xMOVS( SS, 0xf3 ) +IMPLEMENT_xMOVS( SD, 0xf2 ) + +////////////////////////////////////////////////////////////////////////////////////////// +// Non-temporal movs only support a register as a target (ie, load form only, no stores) +// + +__forceinline void xMOVNTDQA( const xRegisterSSE& to, const void* from ) +{ + xWrite32( 0x2A380f66 ); + EmitSibMagic( to.Id, from ); +} + +__forceinline void xMOVNTDQA( const xRegisterSSE& to, const ModSibBase& from ) +{ + xWrite32( 0x2A380f66 ); + EmitSibMagic( to.Id, from ); +} + +__forceinline void xMOVNTDQ( void* to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xe7, from, to ); } +__forceinline void xMOVNTDQA( const ModSibBase& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xe7, from, to ); } + +__forceinline void xMOVNTPD( void* to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0x2b, from, to ); } +__forceinline void xMOVNTPD( const ModSibBase& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0x2b, from, to ); } +__forceinline void xMOVNTPS( void* to, const xRegisterSSE& from ) { xOpWrite0F( 0x2b, from, to ); } +__forceinline void xMOVNTPS( const ModSibBase& to, const xRegisterSSE& from ) { xOpWrite0F( 0x2b, from, to ); } + +__forceinline void xMOVNTQ( void* to, const xRegisterMMX& from ) { xOpWrite0F( 0xe7, from, to ); } +__forceinline void xMOVNTQ( const ModSibBase& to, const xRegisterMMX& from ) { xOpWrite0F( 0xe7, from, to ); } + +// ------------------------------------------------------------------------ + +__forceinline void xMOVMSKPS( const xRegister32& to, const xRegisterSSE& from) { xOpWrite0F( 0x50, to, from ); } +__forceinline void xMOVMSKPD( const xRegister32& to, const xRegisterSSE& from) { xOpWrite0F( 0x66, 0x50, to, from, true ); } + +// xMASKMOV: +// Selectively write bytes from mm1/xmm1 to memory location using the byte mask in mm2/xmm2. +// The default memory location is specified by DS:EDI. The most significant bit in each byte +// of the mask operand determines whether the corresponding byte in the source operand is +// written to the corresponding byte location in memory. +__forceinline void xMASKMOV( const xRegisterSSE& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xf7, to, from ); } +__forceinline void xMASKMOV( const xRegisterMMX& to, const xRegisterMMX& from ) { xOpWrite0F( 0xf7, to, from ); } + +// xPMOVMSKB: +// Creates a mask made up of the most significant bit of each byte of the source +// operand and stores the result in the low byte or word of the destination operand. +// Upper bits of the destination are cleared to zero. +// +// When operating on a 64-bit (MMX) source, the byte mask is 8 bits; when operating on +// 128-bit (SSE) source, the byte mask is 16-bits. +// +__forceinline void xPMOVMSKB( const xRegister32& to, const xRegisterSSE& from ) { xOpWrite0F( 0x66, 0xd7, to, from ); } +__forceinline void xPMOVMSKB( const xRegister32& to, const xRegisterMMX& from ) { xOpWrite0F( 0xd7, to, from ); } + +// [sSSE-3] Concatenates dest and source operands into an intermediate composite, +// shifts the composite at byte granularity to the right by a constant immediate, +// and extracts the right-aligned result into the destination. +// +__forceinline void xPALIGNR( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 ) { xOpWrite0F( 0x66, 0x0f3a, to, from, imm8 ); } +__forceinline void xPALIGNR( const xRegisterMMX& to, const xRegisterMMX& from, u8 imm8 ) { xOpWrite0F( 0x0f3a, to, from, imm8 ); } + + +////////////////////////////////////////////////////////////////////////////////////////// +// INSERTPS / EXTRACTPS [SSE4.1 only!] +// +// [TODO] these might be served better as classes, especially if other instructions use +// the M32,sse,imm form (I forget offhand if any do). + + +// [SSE-4.1] Insert a single-precision floating-point value from src into a specified +// location in dest, and selectively zero out the data elements in dest according to +// the mask field in the immediate byte. The source operand can be a memory location +// (32 bits) or an XMM register (lower 32 bits used). +// +// Imm8 provides three fields: +// * COUNT_S: The value of Imm8[7:6] selects the dword element from src. It is 0 if +// the source is a memory operand. +// * COUNT_D: The value of Imm8[5:4] selects the target dword element in dest. +// * ZMASK: Each bit of Imm8[3:0] selects a dword element in dest to be written +// with 0.0 if set to 1. +// +__emitinline void xINSERTPS( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 ) { xOpWrite0F( 0x66, 0x213a, to, from, imm8 ); } +__emitinline void xINSERTPS( const xRegisterSSE& to, const u32* from, u8 imm8 ) { xOpWrite0F( 0x66, 0x213a, to, from, imm8 ); } +__emitinline void xINSERTPS( const xRegisterSSE& to, const ModSibStrict& from, u8 imm8 ) { xOpWrite0F( 0x66, 0x213a, to, from, imm8 ); } + +// [SSE-4.1] Extract a single-precision floating-point value from src at an offset +// determined by imm8[1-0]*32. The extracted single precision floating-point value +// is stored into the low 32-bits of dest (or at a 32-bit memory pointer). +// +__emitinline void xEXTRACTPS( const xRegister32& to, const xRegisterSSE& from, u8 imm8 ) { xOpWrite0F( 0x66, 0x173a, to, from, imm8 ); } +__emitinline void xEXTRACTPS( u32* dest, const xRegisterSSE& from, u8 imm8 ) { xOpWrite0F( 0x66, 0x173a, from, dest, imm8 ); } +__emitinline void xEXTRACTPS( const ModSibStrict& dest, const xRegisterSSE& from, u8 imm8 ){ xOpWrite0F( 0x66, 0x173a, from, dest, imm8 ); } + +} \ No newline at end of file diff --git a/pcsx2/x86/ix86/ix86_sse.inl b/pcsx2/x86/ix86/ix86_sse.inl deleted file mode 100644 index 971a33af17..0000000000 --- a/pcsx2/x86/ix86/ix86_sse.inl +++ /dev/null @@ -1,1413 +0,0 @@ -/* 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 - -//------------------------------------------------------------------ -// SSE instructions -//------------------------------------------------------------------ - -// This tells the recompiler's emitter to always use movaps instead of movdqa. Both instructions -// do the exact same thing, but movaps is 1 byte shorter, and thus results in a cleaner L1 cache -// and some marginal speed gains as a result. (it's possible someday in the future the per- -// formance of the two instructions could change, so this constant is provided to restore MOVDQA -// use easily at a later time, if needed). - -static const bool AlwaysUseMovaps = true; - -#define SSEMtoR( code, overb ) \ - assert( to < XMMREGS ), \ - RexR(0, to), \ - write16( code ), \ - ModRM( 0, to, DISP32 ), \ - write32( MEMADDR(from, 4 + overb) ) - -#define SSERtoM( code, overb ) \ - assert( from < XMMREGS), \ - RexR(0, from), \ - write16( code ), \ - ModRM( 0, from, DISP32 ), \ - write32( MEMADDR(to, 4 + overb) ) - -#define SSE_SS_MtoR( code, overb ) \ - assert( to < XMMREGS ), \ - write8( 0xf3 ), \ - RexR(0, to), \ - write16( code ), \ - ModRM( 0, to, DISP32 ), \ - write32( MEMADDR(from, 4 + overb) ) - -#define SSE_SS_RtoM( code, overb ) \ - assert( from < XMMREGS), \ - write8( 0xf3 ), \ - RexR(0, from), \ - write16( code ), \ - ModRM( 0, from, DISP32 ), \ - write32( MEMADDR(to, 4 + overb) ) - -#define SSERtoR( code ) \ - assert( to < XMMREGS && from < XMMREGS), \ - RexRB(0, to, from), \ - write16( code ), \ - ModRM( 3, to, from ) - -#define SSEMtoR66( code ) \ - write8( 0x66 ), \ - SSEMtoR( code, 0 ) - -#define SSERtoM66( code ) \ - write8( 0x66 ), \ - SSERtoM( code, 0 ) - -#define SSERtoR66( code ) \ - write8( 0x66 ), \ - SSERtoR( code ) - -#define _SSERtoR66( code ) \ - assert( to < XMMREGS && from < XMMREGS), \ - write8( 0x66 ), \ - RexRB(0, from, to), \ - write16( code ), \ - ModRM( 3, from, to ) - -#define SSE_SS_RtoR( code ) \ - assert( to < XMMREGS && from < XMMREGS), \ - write8( 0xf3 ), \ - RexRB(0, to, from), \ - write16( code ), \ - ModRM( 3, to, from ) - -#define SSE_SD_MtoR( code, overb ) \ - assert( to < XMMREGS ) , \ - write8( 0xf2 ), \ - RexR(0, to), \ - write16( code ), \ - ModRM( 0, to, DISP32 ), \ - write32( MEMADDR(from, 4 + overb) ) \ - -#define SSE_SD_RtoM( code, overb ) \ - assert( from < XMMREGS) , \ - write8( 0xf2 ), \ - RexR(0, from), \ - write16( code ), \ - ModRM( 0, from, DISP32 ), \ - write32( MEMADDR(to, 4 + overb) ) \ - -#define SSE_SD_RtoR( code ) \ - assert( to < XMMREGS && from < XMMREGS) , \ - write8( 0xf2 ), \ - RexRB(0, to, from), \ - write16( code ), \ - ModRM( 3, to, from ) - -#define CMPPSMtoR( op ) \ - SSEMtoR( 0xc20f, 1 ), \ - write8( op ) - -#define CMPPSRtoR( op ) \ - SSERtoR( 0xc20f ), \ - write8( op ) - -#define CMPSSMtoR( op ) \ - SSE_SS_MtoR( 0xc20f, 1 ), \ - write8( op ) - -#define CMPSSRtoR( op ) \ - SSE_SS_RtoR( 0xc20f ), \ - write8( op ) - -#define CMPSDMtoR( op ) \ - SSE_SD_MtoR( 0xc20f, 1 ), \ - write8( op ) - -#define CMPSDRtoR( op ) \ - SSE_SD_RtoR( 0xc20f ), \ - write8( op ) - -/* movups [r32][r32*scale] to xmm1 */ -emitterT void eSSE_MOVUPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) -{ - RexRXB(0, to, from2, from); - write16( 0x100f ); - ModRM( 0, to, 0x4 ); - SibSB( scale, from2, from ); -} - -/* movups xmm1 to [r32][r32*scale] */ -emitterT void eSSE_MOVUPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) -{ - RexRXB(1, to, from2, from); - write16( 0x110f ); - ModRM( 0, to, 0x4 ); - SibSB( scale, from2, from ); -} - -/* movups [r32] to r32 */ -emitterT void eSSE_MOVUPSRmtoR( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, to, from); - write16( 0x100f ); - ModRM( 0, to, from ); -} - -/* movups r32 to [r32] */ -emitterT void eSSE_MOVUPSRtoRm( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write16( 0x110f ); - ModRM( 0, from, to ); -} - -/* movlps [r32] to r32 */ -emitterT void eSSE_MOVLPSRmtoR( x86SSERegType to, x86IntRegType from ) -{ - RexRB(1, to, from); - write16( 0x120f ); - ModRM( 0, to, from ); -} - -emitterT void eSSE_MOVLPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, to, from); - write16( 0x120f ); - WriteRmOffsetFrom(to, from, offset); -} - -/* movaps r32 to [r32] */ -emitterT void eSSE_MOVLPSRtoRm( x86IntRegType to, x86IntRegType from ) -{ - RexRB(0, from, to); - write16( 0x130f ); - ModRM( 0, from, to ); -} - -emitterT void eSSE_MOVLPSRtoRmOffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, from, to); - write16( 0x130f ); - WriteRmOffsetFrom(from, to, offset); -} - -/* movaps [r32][r32*scale] to xmm1 */ -emitterT void eSSE_MOVAPSRmStoR( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) -{ - assert( from != EBP ); - RexRXB(0, to, from2, from); - write16( 0x280f ); - ModRM( 0, to, 0x4 ); - SibSB( scale, from2, from ); -} - -/* movaps xmm1 to [r32][r32*scale] */ -emitterT void eSSE_MOVAPSRtoRmS( x86SSERegType to, x86IntRegType from, x86IntRegType from2, int scale ) -{ - assert( from != EBP ); - RexRXB(0, to, from2, from); - write16( 0x290f ); - ModRM( 0, to, 0x4 ); - SibSB( scale, from2, from ); -} - -// movaps [r32+offset] to r32 -emitterT void eSSE_MOVAPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, to, from); - write16( 0x280f ); - WriteRmOffsetFrom(to, from, offset); -} - -// movaps r32 to [r32+offset] -emitterT void eSSE_MOVAPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - RexRB(0, from, to); - write16( 0x290f ); - WriteRmOffsetFrom(from, to, offset); -} - -// movdqa [r32+offset] to r32 -emitterT void eSSE2_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - if( AlwaysUseMovaps ) - eSSE_MOVAPSRmtoROffset( to, from, offset ); - else - { - write8(0x66); - RexRB(0, to, from); - write16( 0x6f0f ); - WriteRmOffsetFrom(to, from, offset); - } -} - -// movdqa r32 to [r32+offset] -emitterT void eSSE2_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - if( AlwaysUseMovaps ) - eSSE_MOVAPSRtoRmOffset( to, from, offset ); - else - { - write8(0x66); - RexRB(0, from, to); - write16( 0x7f0f ); - WriteRmOffsetFrom(from, to, offset); - } -} - -// movups [r32+offset] to r32 -emitterT void eSSE_MOVUPSRmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, to, from); - write16( 0x100f ); - WriteRmOffsetFrom(to, from, offset); -} - -// movups r32 to [r32+offset] -emitterT void eSSE_MOVUPSRtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - RexRB(0, from, to); - write16( 0x110f ); - WriteRmOffsetFrom(from, to, offset); -} - -//**********************************************************************************/ -//MOVAPS: Move aligned Packed Single Precision FP values * -//********************************************************************************** -emitterT void eSSE_MOVAPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x280f, 0 ); } -emitterT void eSSE_MOVAPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x290f, 0 ); } -emitterT void eSSE_MOVAPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSERtoR( 0x280f ); } } - -emitterT void eSSE_MOVUPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x100f, 0 ); } -emitterT void eSSE_MOVUPS_XMM_to_M128( uptr to, x86SSERegType from ) { SSERtoM( 0x110f, 0 ); } - -emitterT void eSSE2_MOVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x100f); } -emitterT void eSSE2_MOVSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x100f, 0); } -emitterT void eSSE2_MOVSD_XMM_to_M64( uptr to, x86SSERegType from ) { SSE_SD_RtoM( 0x110f, 0); } - -emitterT void eSSE2_MOVQ_M64_to_XMM( x86SSERegType to, uptr from ) -{ - write8(0xf3); SSEMtoR( 0x7e0f, 0); -} - -emitterT void eSSE2_MOVQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - write8(0xf3); SSERtoR( 0x7e0f); -} - -emitterT void eSSE2_MOVQ_XMM_to_M64( u32 to, x86SSERegType from ) -{ - SSERtoM66(0xd60f); -} - -emitterT void eSSE2_MOVDQ2Q_XMM_to_MM( x86MMXRegType to, x86SSERegType from) -{ - write8(0xf2); - SSERtoR( 0xd60f); -} -emitterT void eSSE2_MOVQ2DQ_MM_to_XMM( x86SSERegType to, x86MMXRegType from) -{ - write8(0xf3); - SSERtoR( 0xd60f); -} - -//**********************************************************************************/ -//MOVSS: Move Scalar Single-Precision FP value * -//********************************************************************************** -emitterT void eSSE_MOVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x100f, 0 ); } -emitterT void eSSE_MOVSS_XMM_to_M32( u32 to, x86SSERegType from ) { SSE_SS_RtoM( 0x110f, 0 ); } -emitterT void eSSE_MOVSS_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) -{ - write8(0xf3); - RexRB(0, from, to); - write16(0x110f); - ModRM(0, from, to); -} - -emitterT void eSSE_MOVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { if (to != from) { SSE_SS_RtoR( 0x100f ); } } - -emitterT void eSSE_MOVSS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) -{ - write8(0xf3); - RexRB(0, to, from); - write16( 0x100f ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eSSE_MOVSS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - write8(0xf3); - RexRB(0, from, to); - write16(0x110f); - WriteRmOffsetFrom(from, to, offset); -} - -emitterT void eSSE_MASKMOVDQU_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xf70f ); } -//**********************************************************************************/ -//MOVLPS: Move low Packed Single-Precision FP * -//********************************************************************************** -emitterT void eSSE_MOVLPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x120f, 0 ); } -emitterT void eSSE_MOVLPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x130f, 0 ); } - -emitterT void eSSE_MOVLPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, to, from); - write16( 0x120f ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eSSE_MOVLPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - RexRB(0, from, to); - write16(0x130f); - WriteRmOffsetFrom(from, to, offset); -} - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MOVHPS: Move High Packed Single-Precision FP * -//********************************************************************************** -emitterT void eSSE_MOVHPS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x160f, 0 ); } -emitterT void eSSE_MOVHPS_XMM_to_M64( u32 to, x86SSERegType from ) { SSERtoM( 0x170f, 0 ); } - -emitterT void eSSE_MOVHPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) -{ - RexRB(0, to, from); - write16( 0x160f ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eSSE_MOVHPS_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - RexRB(0, from, to); - write16(0x170f); - WriteRmOffsetFrom(from, to, offset); -} - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MOVLHPS: Moved packed Single-Precision FP low to high * -//********************************************************************************** -emitterT void eSSE_MOVLHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x160f ); } - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MOVHLPS: Moved packed Single-Precision FP High to Low * -//********************************************************************************** -emitterT void eSSE_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x120f ); } - -/////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//ANDPS: Logical Bit-wise AND for Single FP * -//********************************************************************************** -emitterT void eSSE_ANDPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x540f, 0 ); } -emitterT void eSSE_ANDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x540f ); } - -emitterT void eSSE2_ANDPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x540f ); } -emitterT void eSSE2_ANDPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x540f ); } - -/////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//ANDNPS : Logical Bit-wise AND NOT of Single-precision FP values * -//********************************************************************************** -emitterT void eSSE_ANDNPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x550f, 0 ); } -emitterT void eSSE_ANDNPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR( 0x550f ); } - -emitterT void eSSE2_ANDNPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x550f ); } -emitterT void eSSE2_ANDNPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x550f ); } - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//RCPPS : Packed Single-Precision FP Reciprocal * -//********************************************************************************** -emitterT void eSSE_RCPPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x530f ); } -emitterT void eSSE_RCPPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x530f, 0 ); } - -emitterT void eSSE_RCPSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR(0x530f); } -emitterT void eSSE_RCPSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR(0x530f, 0); } - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//ORPS : Bit-wise Logical OR of Single-Precision FP Data * -//********************************************************************************** -emitterT void eSSE_ORPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x560f, 0 ); } -emitterT void eSSE_ORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x560f ); } - -emitterT void eSSE2_ORPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x560f ); } -emitterT void eSSE2_ORPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x560f ); } - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//XORPS : Bitwise Logical XOR of Single-Precision FP Values * -//********************************************************************************** -emitterT void eSSE_XORPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x570f, 0 ); } -emitterT void eSSE_XORPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x570f ); } - -emitterT void eSSE2_XORPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x570f ); } -emitterT void eSSE2_XORPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x570f ); } - -/////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//ADDPS : ADD Packed Single-Precision FP Values * -//********************************************************************************** -emitterT void eSSE_ADDPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x580f, 0 ); } -emitterT void eSSE_ADDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x580f ); } - -//////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//ADDSS : ADD Scalar Single-Precision FP Values * -//********************************************************************************** -emitterT void eSSE_ADDSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x580f, 0 ); } -emitterT void eSSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x580f ); } - -emitterT void eSSE2_ADDSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x580f, 0 ); } -emitterT void eSSE2_ADDSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x580f ); } - -///////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SUBPS: Packed Single-Precision FP Subtract * -//********************************************************************************** -emitterT void eSSE_SUBPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5c0f, 0 ); } -emitterT void eSSE_SUBPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5c0f ); } - -/////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SUBSS : Scalar Single-Precision FP Subtract * -//********************************************************************************** -emitterT void eSSE_SUBSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5c0f, 0 ); } -emitterT void eSSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5c0f ); } - -emitterT void eSSE2_SUBSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x5c0f, 0 ); } -emitterT void eSSE2_SUBSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x5c0f ); } - -///////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MULPS : Packed Single-Precision FP Multiply * -//********************************************************************************** -emitterT void eSSE_MULPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x590f, 0 ); } -emitterT void eSSE_MULPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x590f ); } - -//////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MULSS : Scalar Single-Precision FP Multiply * -//********************************************************************************** -emitterT void eSSE_MULSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x590f, 0 ); } -emitterT void eSSE_MULSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x590f ); } - -emitterT void eSSE2_MULSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x590f, 0 ); } -emitterT void eSSE2_MULSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x590f ); } - -//////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//Packed Single-Precission FP compare (CMPccPS) * -//********************************************************************************** -//missing SSE_CMPPS_I8_to_XMM -// SSE_CMPPS_M32_to_XMM -// SSE_CMPPS_XMM_to_XMM -emitterT void eSSE_CMPEQPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 0 ); } -emitterT void eSSE_CMPEQPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 0 ); } -emitterT void eSSE_CMPLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 1 ); } -emitterT void eSSE_CMPLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 1 ); } -emitterT void eSSE_CMPLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 2 ); } -emitterT void eSSE_CMPLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 2 ); } -emitterT void eSSE_CMPUNORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 3 ); } -emitterT void eSSE_CMPUNORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 3 ); } -emitterT void eSSE_CMPNEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 4 ); } -emitterT void eSSE_CMPNEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 4 ); } -emitterT void eSSE_CMPNLTPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 5 ); } -emitterT void eSSE_CMPNLTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 5 ); } -emitterT void eSSE_CMPNLEPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 6 ); } -emitterT void eSSE_CMPNLEPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 6 ); } -emitterT void eSSE_CMPORDPS_M128_to_XMM( x86SSERegType to, uptr from ) { CMPPSMtoR( 7 ); } -emitterT void eSSE_CMPORDPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPPSRtoR( 7 ); } - -/////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//Scalar Single-Precission FP compare (CMPccSS) * -//********************************************************************************** -//missing SSE_CMPSS_I8_to_XMM -// SSE_CMPSS_M32_to_XMM -// SSE_CMPSS_XMM_to_XMM -emitterT void eSSE_CMPEQSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 0 ); } -emitterT void eSSE_CMPEQSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 0 ); } -emitterT void eSSE_CMPLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 1 ); } -emitterT void eSSE_CMPLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 1 ); } -emitterT void eSSE_CMPLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 2 ); } -emitterT void eSSE_CMPLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 2 ); } -emitterT void eSSE_CMPUNORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 3 ); } -emitterT void eSSE_CMPUNORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 3 ); } -emitterT void eSSE_CMPNESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 4 ); } -emitterT void eSSE_CMPNESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 4 ); } -emitterT void eSSE_CMPNLTSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 5 ); } -emitterT void eSSE_CMPNLTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 5 ); } -emitterT void eSSE_CMPNLESS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 6 ); } -emitterT void eSSE_CMPNLESS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 6 ); } -emitterT void eSSE_CMPORDSS_M32_to_XMM( x86SSERegType to, uptr from ) { CMPSSMtoR( 7 ); } -emitterT void eSSE_CMPORDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSSRtoR( 7 ); } - -emitterT void eSSE2_CMPEQSD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 0 ); } -emitterT void eSSE2_CMPEQSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 0 ); } -emitterT void eSSE2_CMPLTSD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 1 ); } -emitterT void eSSE2_CMPLTSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 1 ); } -emitterT void eSSE2_CMPLESD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 2 ); } -emitterT void eSSE2_CMPLESD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 2 ); } -emitterT void eSSE2_CMPUNORDSD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 3 ); } -emitterT void eSSE2_CMPUNORDSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 3 ); } -emitterT void eSSE2_CMPNESD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 4 ); } -emitterT void eSSE2_CMPNESD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 4 ); } -emitterT void eSSE2_CMPNLTSD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 5 ); } -emitterT void eSSE2_CMPNLTSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 5 ); } -emitterT void eSSE2_CMPNLESD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 6 ); } -emitterT void eSSE2_CMPNLESD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 6 ); } -emitterT void eSSE2_CMPORDSD_M64_to_XMM( x86SSERegType to, uptr from ) { CMPSDMtoR( 7 ); } -emitterT void eSSE2_CMPORDSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { CMPSDRtoR( 7 ); } - -emitterT void eSSE_UCOMISS_M32_to_XMM( x86SSERegType to, uptr from ) -{ - RexR(0, to); - write16( 0x2e0f ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void eSSE_UCOMISS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - RexRB(0, to, from); - write16( 0x2e0f ); - ModRM( 3, to, from ); -} - -emitterT void eSSE2_UCOMISD_M64_to_XMM( x86SSERegType to, uptr from ) -{ - write8(0x66); - RexR(0, to); - write16( 0x2e0f ); - ModRM( 0, to, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -emitterT void eSSE2_UCOMISD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - write8(0x66); - RexRB(0, to, from); - write16( 0x2e0f ); - ModRM( 3, to, from ); -} - -////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//RSQRTPS : Packed Single-Precision FP Square Root Reciprocal * -//********************************************************************************** -emitterT void eSSE_RSQRTPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x520f, 0 ); } -emitterT void eSSE_RSQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x520f ); } - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//RSQRTSS : Scalar Single-Precision FP Square Root Reciprocal * -//********************************************************************************** -emitterT void eSSE_RSQRTSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x520f, 0 ); } -emitterT void eSSE_RSQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x520f ); } - -//////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SQRTPS : Packed Single-Precision FP Square Root * -//********************************************************************************** -emitterT void eSSE_SQRTPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x510f, 0 ); } -emitterT void eSSE_SQRTPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x510f ); } - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SQRTSS : Scalar Single-Precision FP Square Root * -//********************************************************************************** -emitterT void eSSE_SQRTSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x510f, 0 ); } -emitterT void eSSE_SQRTSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x510f ); } - -emitterT void eSSE2_SQRTSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x510f, 0 ); } -emitterT void eSSE2_SQRTSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ SSE_SD_RtoR( 0x510f ); } - -//////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MAXPS: Return Packed Single-Precision FP Maximum * -//********************************************************************************** -emitterT void eSSE_MAXPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5f0f, 0 ); } -emitterT void eSSE_MAXPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5f0f ); } - -emitterT void eSSE2_MAXPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x5f0f ); } -emitterT void eSSE2_MAXPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5f0f ); } - -///////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MAXSS: Return Scalar Single-Precision FP Maximum * -//********************************************************************************** -emitterT void eSSE_MAXSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5f0f, 0 ); } -emitterT void eSSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5f0f ); } - -emitterT void eSSE2_MAXSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x5f0f, 0 ); } -emitterT void eSSE2_MAXSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x5f0f ); } - -///////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//CVTPI2PS: Packed Signed INT32 to Packed Single FP Conversion * -//********************************************************************************** -emitterT void eSSE_CVTPI2PS_M64_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x2a0f, 0 ); } -emitterT void eSSE_CVTPI2PS_MM_to_XMM( x86SSERegType to, x86MMXRegType from ) { SSERtoR( 0x2a0f ); } - -/////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//CVTPS2PI: Packed Single FP to Packed Signed INT32 Conversion * -//********************************************************************************** -emitterT void eSSE_CVTPS2PI_M64_to_MM( x86MMXRegType to, uptr from ) { SSEMtoR( 0x2d0f, 0 ); } -emitterT void eSSE_CVTPS2PI_XMM_to_MM( x86MMXRegType to, x86SSERegType from ) { SSERtoR( 0x2d0f ); } - -emitterT void eSSE_CVTTSS2SI_M32_to_R32(x86IntRegType to, uptr from) { write8(0xf3); SSEMtoR(0x2c0f, 0); } -emitterT void eSSE_CVTTSS2SI_XMM_to_R32(x86IntRegType to, x86SSERegType from) -{ - write8(0xf3); - RexRB(0, to, from); - write16(0x2c0f); - ModRM(3, to, from); -} - -emitterT void eSSE_CVTSI2SS_M32_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x2a0f, 0); } -emitterT void eSSE_CVTSI2SS_R_to_XMM(x86SSERegType to, x86IntRegType from) -{ - write8(0xf3); - RexRB(0, to, from); - write16(0x2a0f); - ModRM(3, to, from); -} - -emitterT void eSSE2_CVTSS2SD_M32_to_XMM( x86SSERegType to, uptr from) { SSE_SS_MtoR(0x5a0f, 0); } -emitterT void eSSE2_CVTSS2SD_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SS_RtoR(0x5a0f); } - -emitterT void eSSE2_CVTSD2SS_M64_to_XMM( x86SSERegType to, uptr from) { SSE_SD_MtoR(0x5a0f, 0); } -emitterT void eSSE2_CVTSD2SS_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { SSE_SD_RtoR(0x5a0f); } - -/////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//CVTDQ2PS: Packed Signed INT32 to Packed Single Precision FP Conversion * -//********************************************************************************** -emitterT void eSSE2_CVTDQ2PS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5b0f, 0 ); } -emitterT void eSSE2_CVTDQ2PS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5b0f ); } - -//**********************************************************************************/ -//CVTPS2DQ: Packed Single Precision FP to Packed Signed INT32 Conversion * -//********************************************************************************** -emitterT void eSSE2_CVTPS2DQ_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x5b0f ); } -emitterT void eSSE2_CVTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5b0f ); } - -emitterT void eSSE2_CVTTPS2DQ_XMM_to_XMM( x86SSERegType to, x86SSERegType from ){ write8(0xf3); SSERtoR(0x5b0f); } -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MINPS: Return Packed Single-Precision FP Minimum * -//********************************************************************************** -emitterT void eSSE_MINPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5d0f, 0 ); } -emitterT void eSSE_MINPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5d0f ); } - -emitterT void eSSE2_MINPD_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0x5d0f ); } -emitterT void eSSE2_MINPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0x5d0f ); } - -////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MINSS: Return Scalar Single-Precision FP Minimum * -//********************************************************************************** -emitterT void eSSE_MINSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5d0f, 0 ); } -emitterT void eSSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5d0f ); } - -emitterT void eSSE2_MINSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x5d0f, 0 ); } -emitterT void eSSE2_MINSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x5d0f ); } - -/////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PMAXSW: Packed Signed Integer Word Maximum * -//********************************************************************************** -//missing - // SSE_PMAXSW_M64_to_MM -// SSE2_PMAXSW_M128_to_XMM -// SSE2_PMAXSW_XMM_to_XMM -emitterT void eSSE_PMAXSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEE0F ); } - -/////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PMINSW: Packed Signed Integer Word Minimum * -//********************************************************************************** -//missing - // SSE_PMINSW_M64_to_MM -// SSE2_PMINSW_M128_to_XMM -// SSE2_PMINSW_XMM_to_XMM -emitterT void eSSE_PMINSW_MM_to_MM( x86MMXRegType to, x86MMXRegType from ){ SSERtoR( 0xEA0F ); } - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SHUFPS: Shuffle Packed Single-Precision FP Values * -//********************************************************************************** -emitterT void eSSE_SHUFPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR( 0xC60F ); write8( imm8 ); } -emitterT void eSSE_SHUFPS_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR( 0xC60F, 1 ); write8( imm8 ); } - -emitterT void eSSE_SHUFPS_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset, u8 imm8 ) -{ - RexRB(0, to, from); - write16(0xc60f); - WriteRmOffsetFrom(to, from, offset); - write8(imm8); -} - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//SHUFPD: Shuffle Packed Double-Precision FP Values * -//********************************************************************************** -emitterT void eSSE2_SHUFPD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { SSERtoR66( 0xC60F ); write8( imm8 ); } -emitterT void eSSE2_SHUFPD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR66( 0xC60F ); write8( imm8 ); } - -//////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PSHUFD: Shuffle Packed DoubleWords * -//********************************************************************************** -emitterT void eSSE2_PSHUFD_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) -{ - SSERtoR66( 0x700F ); - write8( imm8 ); -} -emitterT void eSSE2_PSHUFD_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { SSEMtoR66( 0x700F ); write8( imm8 ); } - -emitterT void eSSE2_PSHUFLW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF2); SSERtoR(0x700F); write8(imm8); } -emitterT void eSSE2_PSHUFLW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { write8(0xF2); SSEMtoR(0x700F, 1); write8(imm8); } -emitterT void eSSE2_PSHUFHW_XMM_to_XMM( x86SSERegType to, x86SSERegType from, u8 imm8 ) { write8(0xF3); SSERtoR(0x700F); write8(imm8); } -emitterT void eSSE2_PSHUFHW_M128_to_XMM( x86SSERegType to, uptr from, u8 imm8 ) { write8(0xF3); SSEMtoR(0x700F, 1); write8(imm8); } - -/////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//UNPCKLPS: Unpack and Interleave low Packed Single-Precision FP Data * -//********************************************************************************** -emitterT void eSSE_UNPCKLPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR(0x140f, 0); } -emitterT void eSSE_UNPCKLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x140F ); } - -//////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//UNPCKHPS: Unpack and Interleave High Packed Single-Precision FP Data * -//********************************************************************************** -emitterT void eSSE_UNPCKHPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR(0x150f, 0); } -emitterT void eSSE_UNPCKHPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x150F ); } - -//////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//DIVPS : Packed Single-Precision FP Divide * -//********************************************************************************** -emitterT void eSSE_DIVPS_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR( 0x5e0F, 0 ); } -emitterT void eSSE_DIVPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR( 0x5e0F ); } - -////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//DIVSS : Scalar Single-Precision FP Divide * -//********************************************************************************** -emitterT void eSSE_DIVSS_M32_to_XMM( x86SSERegType to, uptr from ) { SSE_SS_MtoR( 0x5e0F, 0 ); } -emitterT void eSSE_DIVSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SS_RtoR( 0x5e0F ); } - -emitterT void eSSE2_DIVSD_M64_to_XMM( x86SSERegType to, uptr from ) { SSE_SD_MtoR( 0x5e0F, 0 ); } -emitterT void eSSE2_DIVSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSE_SD_RtoR( 0x5e0F ); } - -///////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//STMXCSR : Store Streaming SIMD Extension Control/Status * -//********************************************************************************** -emitterT void eSSE_STMXCSR( uptr from ) { - write16( 0xAE0F ); - ModRM( 0, 0x3, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//LDMXCSR : Load Streaming SIMD Extension Control/Status * -//********************************************************************************** -emitterT void eSSE_LDMXCSR( uptr from ) { - write16( 0xAE0F ); - ModRM( 0, 0x2, DISP32 ); - write32( MEMADDR(from, 4) ); -} - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PADDB,PADDW,PADDD : Add Packed Integers * -//********************************************************************************** -emitterT void eSSE2_PADDB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFC0F ); } -emitterT void eSSE2_PADDB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFC0F ); } -emitterT void eSSE2_PADDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFD0F ); } -emitterT void eSSE2_PADDW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFD0F ); } -emitterT void eSSE2_PADDD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFE0F ); } -emitterT void eSSE2_PADDD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFE0F ); } -emitterT void eSSE2_PADDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD40F ); } -emitterT void eSSE2_PADDQ_M128_to_XMM(x86SSERegType to, uptr from ) { SSEMtoR66( 0xD40F ); } - -/////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PCMPxx: Compare Packed Integers * -//********************************************************************************** -emitterT void eSSE2_PCMPGTB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x640F ); } -emitterT void eSSE2_PCMPGTB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x640F ); } -emitterT void eSSE2_PCMPGTW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x650F ); } -emitterT void eSSE2_PCMPGTW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x650F ); } -emitterT void eSSE2_PCMPGTD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x660F ); } -emitterT void eSSE2_PCMPGTD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x660F ); } -emitterT void eSSE2_PCMPEQB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x740F ); } -emitterT void eSSE2_PCMPEQB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x740F ); } -emitterT void eSSE2_PCMPEQW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x750F ); } -emitterT void eSSE2_PCMPEQW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x750F ); } -emitterT void eSSE2_PCMPEQD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0x760F ); } -emitterT void eSSE2_PCMPEQD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0x760F ); } - -//////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PEXTRW,PINSRW: Packed Extract/Insert Word * -//********************************************************************************** -emitterT void eSSE_PEXTRW_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8 ){ SSERtoR66(0xC50F); write8( imm8 ); } -emitterT void eSSE_PINSRW_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8 ){ SSERtoR66(0xC40F); write8( imm8 ); } - -//////////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PSUBx: Subtract Packed Integers * -//********************************************************************************** -emitterT void eSSE2_PSUBB_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF80F ); } -emitterT void eSSE2_PSUBB_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF80F ); } -emitterT void eSSE2_PSUBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xF90F ); } -emitterT void eSSE2_PSUBW_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xF90F ); } -emitterT void eSSE2_PSUBD_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFA0F ); } -emitterT void eSSE2_PSUBD_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFA0F ); } -emitterT void eSSE2_PSUBQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ){ SSERtoR66( 0xFB0F ); } -emitterT void eSSE2_PSUBQ_M128_to_XMM(x86SSERegType to, uptr from ){ SSEMtoR66( 0xFB0F ); } - -/////////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//MOVD: Move Dword(32bit) to /from XMM reg * -//********************************************************************************** -emitterT void eSSE2_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66(0x6E0F); } -emitterT void eSSE2_MOVD_R_to_XMM( x86SSERegType to, x86IntRegType from ) { SSERtoR66(0x6E0F); } - -emitterT void eSSE2_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from ) -{ - write8(0x66); - RexRB(0, to, from); - write16( 0x6e0f ); - ModRM( 0, to, from); -} - -emitterT void eSSE2_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) -{ - write8(0x66); - RexRB(0, to, from); - write16( 0x6e0f ); - WriteRmOffsetFrom(to, from, offset); -} - -emitterT void eSSE2_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) { SSERtoM66(0x7E0F); } -emitterT void eSSE2_MOVD_XMM_to_R( x86IntRegType to, x86SSERegType from ) { _SSERtoR66(0x7E0F); } - -emitterT void eSSE2_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) -{ - write8(0x66); - RexRB(0, from, to); - write16( 0x7e0f ); - ModRM( 0, from, to ); -} - -emitterT void eSSE2_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - write8(0x66); - RexRB(0, from, to); - write16( 0x7e0f ); - WriteRmOffsetFrom(from, to, offset); -} - -//////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//POR : SSE Bitwise OR * -//********************************************************************************** -emitterT void eSSE2_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEB0F ); } -emitterT void eSSE2_POR_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEB0F ); } - -// logical and to &= from -emitterT void eSSE2_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDB0F ); } -emitterT void eSSE2_PAND_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDB0F ); } - -// to = (~to) & from -emitterT void eSSE2_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDF0F ); } -emitterT void eSSE2_PANDN_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDF0F ); } - -///////////////////////////////////////////////////////////////////////////////////// -//**********************************************************************************/ -//PXOR : SSE Bitwise XOR * -//********************************************************************************** -emitterT void eSSE2_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEF0F ); } -emitterT void eSSE2_PXOR_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEF0F ); } -/////////////////////////////////////////////////////////////////////////////////////// - -emitterT void eSSE2_MOVDQA_M128_to_XMM(x86SSERegType to, uptr from) { if( AlwaysUseMovaps ) eSSE_MOVAPS_M128_to_XMM( to, from ); else SSEMtoR66(0x6F0F); } -emitterT void eSSE2_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ) { if( AlwaysUseMovaps ) eSSE_MOVAPS_XMM_to_M128( to, from ); else SSERtoM66(0x7F0F); } -emitterT void eSSE2_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from) { if( AlwaysUseMovaps ) eSSE_MOVAPS_XMM_to_XMM( to, from ); else if( to != from ) SSERtoR66(0x6F0F); } - -emitterT void eSSE2_MOVDQU_M128_to_XMM(x86SSERegType to, uptr from) -{ - if( AlwaysUseMovaps ) - eSSE_MOVUPS_M128_to_XMM( to, from ); - else - { - write8(0xF3); - SSEMtoR(0x6F0F, 0); - } -} -emitterT void eSSE2_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from) -{ - if( AlwaysUseMovaps ) - eSSE_MOVUPS_XMM_to_M128( to, from ); - else - { - write8(0xF3); - SSERtoM(0x7F0F, 0); - } -} - -// shift right logical - -emitterT void eSSE2_PSRLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD10F); } -emitterT void eSSE2_PSRLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD10F); } -emitterT void eSSE2_PSRLW_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x710F ); - ModRM( 3, 2 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSRLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD20F); } -emitterT void eSSE2_PSRLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD20F); } -emitterT void eSSE2_PSRLD_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x720F ); - ModRM( 3, 2 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSRLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xD30F); } -emitterT void eSSE2_PSRLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xD30F); } -emitterT void eSSE2_PSRLQ_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x730F ); - ModRM( 3, 2 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSRLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x730F ); - ModRM( 3, 3 , to ); - write8( imm8 ); -} - -// shift right arithmetic - -emitterT void eSSE2_PSRAW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE10F); } -emitterT void eSSE2_PSRAW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xE10F); } -emitterT void eSSE2_PSRAW_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x710F ); - ModRM( 3, 4 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSRAD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xE20F); } -emitterT void eSSE2_PSRAD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xE20F); } -emitterT void eSSE2_PSRAD_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x720F ); - ModRM( 3, 4 , to ); - write8( imm8 ); -} - -// shift left logical - -emitterT void eSSE2_PSLLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF10F); } -emitterT void eSSE2_PSLLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF10F); } -emitterT void eSSE2_PSLLW_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x710F ); - ModRM( 3, 6 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSLLD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF20F); } -emitterT void eSSE2_PSLLD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF20F); } -emitterT void eSSE2_PSLLD_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x720F ); - ModRM( 3, 6 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSLLQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF30F); } -emitterT void eSSE2_PSLLQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66(0xF30F); } -emitterT void eSSE2_PSLLQ_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x730F ); - ModRM( 3, 6 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PSLLDQ_I8_to_XMM(x86SSERegType to, u8 imm8) -{ - write8( 0x66 ); - RexB(0, to); - write16( 0x730F ); - ModRM( 3, 7 , to ); - write8( imm8 ); -} - -emitterT void eSSE2_PMAXSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEE0F ); } -emitterT void eSSE2_PMAXSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEE0F ); } - -emitterT void eSSE2_PMAXUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDE0F ); } -emitterT void eSSE2_PMAXUB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDE0F ); } - -emitterT void eSSE2_PMINSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEA0F ); } -emitterT void eSSE2_PMINSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEA0F ); } - -emitterT void eSSE2_PMINUB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDA0F ); } -emitterT void eSSE2_PMINUB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDA0F ); } - -emitterT void eSSE2_PADDSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xEC0F ); } -emitterT void eSSE2_PADDSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xEC0F ); } - -emitterT void eSSE2_PADDSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xED0F ); } -emitterT void eSSE2_PADDSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xED0F ); } - -emitterT void eSSE2_PSUBSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xE80F ); } -emitterT void eSSE2_PSUBSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xE80F ); } - -emitterT void eSSE2_PSUBSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xE90F ); } -emitterT void eSSE2_PSUBSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xE90F ); } - -emitterT void eSSE2_PSUBUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD80F ); } -emitterT void eSSE2_PSUBUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD80F ); } -emitterT void eSSE2_PSUBUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xD90F ); } -emitterT void eSSE2_PSUBUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xD90F ); } - -emitterT void eSSE2_PADDUSB_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDC0F ); } -emitterT void eSSE2_PADDUSB_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDC0F ); } -emitterT void eSSE2_PADDUSW_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) { SSERtoR66( 0xDD0F ); } -emitterT void eSSE2_PADDUSW_M128_to_XMM( x86SSERegType to, uptr from ) { SSEMtoR66( 0xDD0F ); } - -//**********************************************************************************/ -//PACKSSWB,PACKSSDW: Pack Saturate Signed Word -//********************************************************************************** -emitterT void eSSE2_PACKSSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x630F ); } -emitterT void eSSE2_PACKSSWB_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x630F ); } -emitterT void eSSE2_PACKSSDW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6B0F ); } -emitterT void eSSE2_PACKSSDW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6B0F ); } - -emitterT void eSSE2_PACKUSWB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x670F ); } -emitterT void eSSE2_PACKUSWB_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x670F ); } - -//**********************************************************************************/ -//PUNPCKHWD: Unpack 16bit high -//********************************************************************************** -emitterT void eSSE2_PUNPCKLBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x600F ); } -emitterT void eSSE2_PUNPCKLBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x600F ); } - -emitterT void eSSE2_PUNPCKHBW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x680F ); } -emitterT void eSSE2_PUNPCKHBW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x680F ); } - -emitterT void eSSE2_PUNPCKLWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x610F ); } -emitterT void eSSE2_PUNPCKLWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x610F ); } -emitterT void eSSE2_PUNPCKHWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x690F ); } -emitterT void eSSE2_PUNPCKHWD_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x690F ); } - -emitterT void eSSE2_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x620F ); } -emitterT void eSSE2_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x620F ); } -emitterT void eSSE2_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6A0F ); } -emitterT void eSSE2_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6A0F ); } - -emitterT void eSSE2_PUNPCKLQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6C0F ); } -emitterT void eSSE2_PUNPCKLQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6C0F ); } - -emitterT void eSSE2_PUNPCKHQDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0x6D0F ); } -emitterT void eSSE2_PUNPCKHQDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0x6D0F ); } - -emitterT void eSSE2_PMULLW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xD50F ); } -emitterT void eSSE2_PMULLW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xD50F ); } -emitterT void eSSE2_PMULHW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xE50F ); } -emitterT void eSSE2_PMULHW_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xE50F ); } - -emitterT void eSSE2_PMULUDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66( 0xF40F ); } -emitterT void eSSE2_PMULUDQ_M128_to_XMM(x86SSERegType to, uptr from) { SSEMtoR66( 0xF40F ); } - -emitterT void eSSE2_PMOVMSKB_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0xD70F); } - -emitterT void eSSE_MOVMSKPS_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR(0x500F); } -emitterT void eSSE2_MOVMSKPD_XMM_to_R32(x86IntRegType to, x86SSERegType from) { SSERtoR66(0x500F); } - -emitterT void eSSE2_PMADDWD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { SSERtoR66(0xF50F); } - -emitterT void eSSE3_HADDPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf2); SSERtoR( 0x7c0f ); } -emitterT void eSSE3_HADDPS_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xf2); SSEMtoR( 0x7c0f, 0 ); } - -emitterT void eSSE3_MOVSLDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { - write8(0xf3); - RexRB(0, to, from); - write16( 0x120f); - ModRM( 3, to, from ); -} - -emitterT void eSSE3_MOVSLDUP_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x120f, 0); } -emitterT void eSSE3_MOVSHDUP_XMM_to_XMM(x86SSERegType to, x86SSERegType from) { write8(0xf3); SSERtoR(0x160f); } -emitterT void eSSE3_MOVSHDUP_M128_to_XMM(x86SSERegType to, uptr from) { write8(0xf3); SSEMtoR(0x160f, 0); } - -// SSSE3 - -emitterT void eSSSE3_PABSB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x1C380F); - ModRM(3, to, from); -} - -emitterT void eSSSE3_PABSW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x1D380F); - ModRM(3, to, from); -} - -emitterT void eSSSE3_PABSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x1E380F); - ModRM(3, to, from); -} - -emitterT void eSSSE3_PALIGNR_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x0F3A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSSE3_PSIGNB_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x08380F); - ModRM(3, to, from); -} - -emitterT void eSSSE3_PSIGNW_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x09380F); - ModRM(3, to, from); -} - -emitterT void eSSSE3_PSIGND_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x0A380F); - ModRM(3, to, from); -} - -// SSE4.1 - -emitterT void eSSE4_DPPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) -{ - write8(0x66); - write24(0x403A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSE4_DPPS_M128_to_XMM(x86SSERegType to, uptr from, u8 imm8) -{ - write8(0x66); - write24(0x403A0F); - ModRM(0, to, DISP32); - write32(MEMADDR(from, 4)); - write8(imm8); -} - -emitterT void eSSE4_INSERTPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from, u8 imm8) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x213A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSE4_EXTRACTPS_XMM_to_R32(x86IntRegType to, x86SSERegType from, u8 imm8) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x173A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSE4_BLENDPS_XMM_to_XMM(x86IntRegType to, x86SSERegType from, u8 imm8) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x0C3A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSE4_BLENDVPS_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x14380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_BLENDVPS_M128_to_XMM(x86SSERegType to, uptr from) -{ - write8(0x66); - RexR(0, to); - write24(0x14380F); - ModRM(0, to, DISP32); - write32(MEMADDR(from, 4)); -} - -emitterT void eSSE4_PMOVSXDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x25380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PMOVZXDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x35380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PINSRD_R32_to_XMM(x86SSERegType to, x86IntRegType from, u8 imm8) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x223A0F); - ModRM(3, to, from); - write8(imm8); -} - -emitterT void eSSE4_PMAXSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x3D380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PMINSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x39380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PMAXUD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x3F380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PMINUD_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x3B380F); - ModRM(3, to, from); -} - -emitterT void eSSE4_PMAXSD_M128_to_XMM(x86SSERegType to, uptr from) -{ - write8(0x66); - RexR(0, to); - write24(0x3D380F); - ModRM( 0, to, DISP32 ); - write32(MEMADDR(from, 4)); -} - -emitterT void eSSE4_PMINSD_M128_to_XMM(x86SSERegType to, uptr from) -{ - write8(0x66); - RexR(0, to); - write24(0x39380F); - ModRM( 0, to, DISP32 ); - write32(MEMADDR(from, 4)); -} - -emitterT void eSSE4_PMAXUD_M128_to_XMM(x86SSERegType to, uptr from) -{ - write8(0x66); - RexR(0, to); - write24(0x3F380F); - ModRM( 0, to, DISP32 ); - write32(MEMADDR(from, 4)); -} - -emitterT void eSSE4_PMINUD_M128_to_XMM(x86SSERegType to, uptr from) -{ - write8(0x66); - RexR(0, to); - write24(0x3B380F); - ModRM( 0, to, DISP32 ); - write32(MEMADDR(from, 4)); -} - -emitterT void eSSE4_PMULDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - write8(0x66); - RexRB(0, to, from); - write24(0x28380F); - ModRM(3, to, from); -} diff --git a/pcsx2/x86/ix86/ix86_sse_helpers.h b/pcsx2/x86/ix86/ix86_sse_helpers.h index 9caa04c6a2..f568282d9e 100644 --- a/pcsx2/x86/ix86/ix86_sse_helpers.h +++ b/pcsx2/x86/ix86/ix86_sse_helpers.h @@ -22,164 +22,29 @@ // SSE-X Helpers (generates either INT or FLOAT versions of certain SSE instructions) // This header should always be included *after* ix86.h. -#ifndef _ix86_included_ -#error Dependency fail: Please define _EmitterId_ and include ix86.h first. -#endif - // Added AlwaysUseMovaps check to the relevant functions here, which helps reduce the // overhead of dynarec instructions that use these. -static __forceinline void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQA_M128_to_XMM(to, from); - else SSE_MOVAPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_M128(to, from); - else SSE_MOVAPS_XMM_to_M128(to, from); -} - -static __forceinline void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQA_XMM_to_XMM(to, from); - else SSE_MOVAPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_MOVDQARmtoROffset( x86SSERegType to, x86IntRegType from, int offset ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQARmtoROffset(to, from, offset); - else SSE_MOVAPSRmtoROffset(to, from, offset); -} - -static __forceinline void SSEX_MOVDQARtoRmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQARtoRmOffset(to, from, offset); - else SSE_MOVAPSRtoRmOffset(to, from, offset); -} - -static __forceinline void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[to] == XMMT_INT ) SSE2_MOVDQU_M128_to_XMM(to, from); - else SSE_MOVUPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ) -{ - if( !AlwaysUseMovaps && g_xmmtypes[from] == XMMT_INT ) SSE2_MOVDQU_XMM_to_M128(to, from); - else SSE_MOVUPS_XMM_to_M128(to, from); -} - -static __forceinline void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr from ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_M32_to_XMM(to, from); - else SSE_MOVSS_M32_to_XMM(to, from); -} - -static __forceinline void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_M32(to, from); - else SSE_MOVSS_XMM_to_M32(to, from); -} - -static __forceinline void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_Rm(to, from); - else SSE_MOVSS_XMM_to_Rm(to, from); -} - -static __forceinline void SSEX_MOVD_RmOffset_to_XMM( x86SSERegType to, x86IntRegType from, int offset ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_MOVD_RmOffset_to_XMM(to, from, offset); - else SSE_MOVSS_RmOffset_to_XMM(to, from, offset); -} - -static __forceinline void SSEX_MOVD_XMM_to_RmOffset( x86IntRegType to, x86SSERegType from, int offset ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_MOVD_XMM_to_RmOffset(to, from, offset); - else SSE_MOVSS_XMM_to_RmOffset(to, from, offset); -} - -static __forceinline void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_POR_M128_to_XMM(to, from); - else SSE_ORPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_POR_XMM_to_XMM(to, from); - else SSE_ORPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_PXOR_M128_to_XMM(to, from); - else SSE_XORPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_PXOR_XMM_to_XMM(to, from); - else SSE_XORPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_PAND_M128_to_XMM(to, from); - else SSE_ANDPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_PAND_XMM_to_XMM(to, from); - else SSE_ANDPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr from ) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_PANDN_M128_to_XMM(to, from); - else SSE_ANDNPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_PANDN_XMM_to_XMM(to, from); - else SSE_ANDNPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKLDQ_M128_to_XMM(to, from); - else SSE_UNPCKLPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKLDQ_XMM_to_XMM(to, from); - else SSE_UNPCKLPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from) -{ - if( g_xmmtypes[to] == XMMT_INT ) SSE2_PUNPCKHDQ_M128_to_XMM(to, from); - else SSE_UNPCKHPS_M128_to_XMM(to, from); -} - -static __forceinline void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from) -{ - if( g_xmmtypes[from] == XMMT_INT ) SSE2_PUNPCKHDQ_XMM_to_XMM(to, from); - else SSE_UNPCKHPS_XMM_to_XMM(to, from); -} - -static __forceinline void SSEX_MOVHLPS_XMM_to_XMM( x86SSERegType to, x86SSERegType from ) -{ - if( g_xmmtypes[from] == XMMT_INT ) { - SSE2_PUNPCKHQDQ_XMM_to_XMM(to, from); - if( to != from ) SSE2_PSHUFD_XMM_to_XMM(to, to, 0x4e); - } - else { - SSE_MOVHLPS_XMM_to_XMM(to, from); - } -} +extern void SSEX_MOVDQA_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_MOVDQA_XMM_to_M128( uptr to, x86SSERegType from ); +extern void SSEX_MOVDQA_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSEX_MOVDQARmtoR( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSEX_MOVDQARtoRm( x86IntRegType to, x86SSERegType from, int offset=0 ); +extern void SSEX_MOVDQU_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_MOVDQU_XMM_to_M128( uptr to, x86SSERegType from ); +extern void SSEX_MOVD_M32_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_MOVD_XMM_to_M32( u32 to, x86SSERegType from ); +extern void SSEX_MOVD_Rm_to_XMM( x86SSERegType to, x86IntRegType from, int offset=0 ); +extern void SSEX_MOVD_XMM_to_Rm( x86IntRegType to, x86SSERegType from, int offset=0 ); +extern void SSEX_POR_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_POR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSEX_PXOR_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_PXOR_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSEX_PAND_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_PAND_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSEX_PANDN_M128_to_XMM( x86SSERegType to, uptr from ); +extern void SSEX_PANDN_XMM_to_XMM( x86SSERegType to, x86SSERegType from ); +extern void SSEX_PUNPCKLDQ_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSEX_PUNPCKLDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); +extern void SSEX_PUNPCKHDQ_M128_to_XMM(x86SSERegType to, uptr from ); +extern void SSEX_PUNPCKHDQ_XMM_to_XMM(x86SSERegType to, x86SSERegType from ); diff --git a/pcsx2/x86/ix86/ix86_tools.cpp b/pcsx2/x86/ix86/ix86_tools.cpp index 5ef532ffcd..91a37d1333 100644 --- a/pcsx2/x86/ix86/ix86_tools.cpp +++ b/pcsx2/x86/ix86/ix86_tools.cpp @@ -18,8 +18,8 @@ #include "PrecompiledHeader.h" -#include "Misc.h" -#include "ix86/ix86.h" +#include "System.h" +#include "ix86.h" // used to make sure regs don't get changed while in recompiler // use FreezeMMXRegs, FreezeXMMRegs @@ -28,7 +28,7 @@ u8 g_globalMMXSaved = 0; u8 g_globalXMMSaved = 0; PCSX2_ALIGNED16( static u64 g_globalMMXData[8] ); -PCSX2_ALIGNED16( static u64 g_globalXMMData[2*XMMREGS] ); +PCSX2_ALIGNED16( static u64 g_globalXMMData[2*iREGCNT_XMM] ); ///////////////////////////////////////////////////////////////////// @@ -253,4 +253,5 @@ __forceinline void FreezeXMMRegs_(int save) } #ifndef __INTEL_COMPILER } -#endif \ No newline at end of file +#endif + diff --git a/pcsx2/x86/ix86/ix86_types.h b/pcsx2/x86/ix86/ix86_types.h index e4fb71d84d..78cd2538a5 100644 --- a/pcsx2/x86/ix86/ix86_types.h +++ b/pcsx2/x86/ix86/ix86_types.h @@ -18,75 +18,11 @@ #pragma once -// x86 opcode descriptors -#define XMMREGS 8 -#define X86REGS 8 -#define MMXREGS 8 +extern void cpudetectInit();//this is all that needs to be called and will fill up the below structs -#define SIB 4 -#define SIBDISP 5 -#define DISP32 5 - -// general types -typedef int x86IntRegType; -#define EAX 0 -#define EBX 3 -#define ECX 1 -#define EDX 2 -#define ESI 6 -#define EDI 7 -#define EBP 5 -#define ESP 4 - -#define X86ARG1 EAX -#define X86ARG2 ECX -#define X86ARG3 EDX -#define X86ARG4 EBX - -#define MM0 0 -#define MM1 1 -#define MM2 2 -#define MM3 3 -#define MM4 4 -#define MM5 5 -#define MM6 6 -#define MM7 7 - -typedef int x86MMXRegType; - -#define XMM0 0 -#define XMM1 1 -#define XMM2 2 -#define XMM3 3 -#define XMM4 4 -#define XMM5 5 -#define XMM6 6 -#define XMM7 7 -#define XMM8 8 -#define XMM9 9 -#define XMM10 10 -#define XMM11 11 -#define XMM12 12 -#define XMM13 13 -#define XMM14 14 -#define XMM15 15 - -typedef int x86SSERegType; - -enum XMMSSEType -{ - XMMT_INT = 0, // integer (sse2 only) - XMMT_FPS = 1, // floating point - //XMMT_FPD = 3, // double -}; - -extern XMMSSEType g_xmmtypes[XMMREGS]; - -extern void cpudetectInit( void );//this is all that needs to be called and will fill up the below structs - -typedef struct CAPABILITIES CAPABILITIES; //cpu capabilities structure -struct CAPABILITIES { +struct CAPABILITIES +{ u32 hasFloatingPointUnit; u32 hasVirtual8086ModeEnhancements; u32 hasDebuggingExtensions; @@ -128,8 +64,8 @@ struct CAPABILITIES { extern CAPABILITIES cpucaps; -struct CPUINFO{ - +struct CPUINFO +{ u32 x86Family; // Processor Family u32 x86Model; // Processor Model u32 x86PType; // Processor Type @@ -148,4 +84,683 @@ struct CPUINFO{ }; extern CPUINFO cpuinfo; + //------------------------------------------------------------------ +#ifdef _MSC_VER +#define __threadlocal __declspec(thread) +#else +#define __threadlocal __thread +#endif + +// Register counts for x86/32 mode: +static const uint iREGCNT_XMM = 8; +static const uint iREGCNT_GPR = 8; +static const uint iREGCNT_MMX = 8; + +enum XMMSSEType +{ + XMMT_INT = 0, // integer (sse2 only) + XMMT_FPS = 1, // floating point + //XMMT_FPD = 3, // double +}; + +extern __threadlocal u8 *x86Ptr; +extern __threadlocal u8 *j8Ptr[32]; // depreciated item. use local u8* vars instead. +extern __threadlocal u32 *j32Ptr[32]; // depreciated item. use local u32* vars instead. + +extern __threadlocal XMMSSEType g_xmmtypes[iREGCNT_XMM]; + +namespace x86Emitter +{ + +extern void xWrite8( u8 val ); +extern void xWrite16( u16 val ); +extern void xWrite32( u32 val ); +extern void xWrite64( u64 val ); + +//------------------------------------------------------------------ +// templated version of is_s8 is required, so that u16's get correct sign extension treatment. +template< typename T > +static __forceinline bool is_s8( T imm ) { return (s8)imm == (s32)imm; } + +template< typename T > +__forceinline void xWrite( T val ) +{ + *(T*)x86Ptr = val; + x86Ptr += sizeof(T); +} + + +////////////////////////////////////////////////////////////////////////////////////////// +// ALWAYS_USE_MOVAPS [define] / AlwaysUseMovaps [const] +// +// This tells the recompiler's emitter to always use movaps instead of movdqa. Both instructions +// do the exact same thing, but movaps is 1 byte shorter, and thus results in a cleaner L1 cache +// and some marginal speed gains as a result. (it's possible someday in the future the per- +// formance of the two instructions could change, so this constant is provided to restore MOVDQA +// use easily at a later time, if needed). +#define ALWAYS_USE_MOVAPS + +#ifdef ALWAYS_USE_MOVAPS + static const bool AlwaysUseMovaps = true; +#else + static const bool AlwaysUseMovaps = false; +#endif + +///////////////////////////////////////////////////////////////////////////////////////////// +// __emitline - preprocessors definition +// +// This is configured to inline emitter functions appropriately for release builds, and +// disables some of the more aggressive inlines for dev builds (which can be helpful when +// debugging). Additionally, I've set up the inlining to be as practical and intelligent +// as possible with regard to constant propagation. Namely this involves forcing inlining +// for (void*) forms of ModRM, which (thanks to constprop) reduce to virtually no code, and +// force-disabling inlining on complicated SibSB forms [since MSVC would sometimes inline +// despite being a generally bad idea]. +// +// In the case of (Reg, Imm) forms, the inlining is up to the discreation of the compiler. +// +// Note: I *intentionally* use __forceinline directly for most single-line class members, +// when needed. There's no point in using __emitline in these cases since the debugger +// can't trace into single-line functions anyway. +// +#ifdef PCSX2_DEVBUILD +# define __emitinline +#else +# define __emitinline __forceinline +#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_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) + + class xAddressInfo; + class ModSibBase; + + extern void xSetPtr( void* ptr ); + extern u8* xGetPtr(); + extern void xAlignPtr( uint bytes ); + extern void xAdvancePtr( uint bytes ); + + ////////////////////////////////////////////////////////////////////////////////////////// + // xRegisterBase + // Unless templating some fancy stuff, use the friendly xRegister32/16/8 typedefs instead. + // + template< typename OperandType > + class xRegisterBase + { + public: + static const uint OperandSize = sizeof( OperandType ); + static const xRegisterBase Empty; // defined as an empty/unused value (-1) + + int Id; + + xRegisterBase( const xRegisterBase& src ) : Id( src.Id ) {} + xRegisterBase(): Id( -1 ) {} + explicit xRegisterBase( int regId ) : Id( regId ) { jASSUME( Id >= -1 && Id < 8 ); } + + bool IsEmpty() const { return Id < 0; } + + // Returns true if the register is a valid accumulator: Eax, Ax, Al. + bool IsAccumulator() const { return Id == 0; } + + // returns true if the register is a valid MMX or XMM register. + bool IsSIMD() const { return OperandSize == 8 || OperandSize == 16; } + + bool operator==( const xRegisterBase& src ) const { return (Id == src.Id); } + bool operator!=( const xRegisterBase& src ) const { return (Id != src.Id); } + + xRegisterBase& operator=( const xRegisterBase& src ) + { + Id = src.Id; + return *this; + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + template< typename OperandType > + class xRegister : public xRegisterBase + { + public: + static const xRegister Empty; // defined as an empty/unused value (-1) + + public: + xRegister(): xRegisterBase() {} + xRegister( const xRegister& src ) : xRegisterBase( src.Id ) {} + explicit xRegister( const xRegisterBase& src ) : xRegisterBase( src ) {} + explicit xRegister( int regId ) : xRegisterBase( regId ) {} + + bool operator==( const xRegister& src ) const { return this->Id == src.Id; } + bool operator!=( const xRegister& src ) const { return this->Id != src.Id; } + + xRegister& operator=( const xRegister& src ) + { + this->Id = src.Id; + return *this; + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + template< typename OperandType > + class xRegisterSIMD : public xRegisterBase + { + public: + static const xRegisterSIMD Empty; // defined as an empty/unused value (-1) + + public: + xRegisterSIMD(): xRegisterBase() {} + xRegisterSIMD( const xRegisterSIMD& src ) : xRegisterBase( src.Id ) {} + explicit xRegisterSIMD( const xRegisterBase& src ) : xRegisterBase( src ) {} + explicit xRegisterSIMD( int regId ) : xRegisterBase( regId ) {} + + bool operator==( const xRegisterSIMD& src ) const { return this->Id == src.Id; } + bool operator!=( const xRegisterSIMD& src ) const { return this->Id != src.Id; } + + xRegisterSIMD& operator=( const xRegisterSIMD& src ) + { + this->Id = src.Id; + return *this; + } + }; + + // ------------------------------------------------------------------------ + // Note: GCC parses templates ahead of time apparently as a 'favor' to the programmer, which + // means it finds undeclared variables when MSVC does not (Since MSVC compiles templates + // when they are actually used). In practice this sucks since it means we have to move all + // our variable and function prototypes from a nicely/neatly unified location to being strewn + // all about the the templated code in haphazard fashion. Yay.. >_< + // + + typedef xRegisterSIMD xRegisterSSE; + typedef xRegisterSIMD xRegisterMMX; + typedef xRegister xRegister32; + typedef xRegister xRegister16; + typedef xRegister xRegister8; + + class xRegisterCL : public xRegister8 + { + public: + xRegisterCL(): xRegister8( 1 ) {} + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Use 32 bit registers as out index register (for ModSib memory address calculations) + // Only xAddressReg provides operators for constructing xAddressInfo types. + // + class xAddressReg : public xRegister32 + { + public: + static const xAddressReg Empty; // defined as an empty/unused value (-1) + + public: + xAddressReg(): xRegister32() {} + xAddressReg( const xAddressReg& src ) : xRegister32( src.Id ) {} + xAddressReg( const xRegister32& src ) : xRegister32( src ) {} + explicit xAddressReg( int regId ) : xRegister32( regId ) {} + + // Returns true if the register is the stack pointer: ESP. + bool IsStackPointer() const { return Id == 4; } + + xAddressInfo operator+( const xAddressReg& right ) const; + xAddressInfo operator+( const xAddressInfo& right ) const; + xAddressInfo operator+( s32 right ) const; + + xAddressInfo operator*( u32 factor ) const; + xAddressInfo operator<<( u32 shift ) const; + + xAddressReg& operator=( const xRegister32& src ) + { + Id = src.Id; + return *this; + } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + class xAddressInfo + { + public: + xAddressReg Base; // base register (no scale) + xAddressReg Index; // index reg gets multiplied by the scale + int Factor; // scale applied to the index register, in factor form (not a shift!) + s32 Displacement; // address displacement + + public: + __forceinline xAddressInfo( const xAddressReg& base, const xAddressReg& index, int factor=1, s32 displacement=0 ) : + Base( base ), + Index( index ), + Factor( factor ), + Displacement( displacement ) + { + } + + __forceinline explicit xAddressInfo( const xAddressReg& index, int displacement=0 ) : + Base(), + Index( index ), + Factor(0), + Displacement( displacement ) + { + } + + __forceinline explicit xAddressInfo( s32 displacement ) : + Base(), + Index(), + Factor(0), + Displacement( displacement ) + { + } + + static xAddressInfo FromIndexReg( const xAddressReg& index, int scale=0, s32 displacement=0 ); + + public: + bool IsByteSizeDisp() const { return is_s8( Displacement ); } + + __forceinline xAddressInfo& Add( s32 imm ) + { + Displacement += imm; + return *this; + } + + __forceinline xAddressInfo& Add( const xAddressReg& src ); + __forceinline xAddressInfo& Add( const xAddressInfo& src ); + + __forceinline xAddressInfo operator+( const xAddressReg& right ) const { return xAddressInfo( *this ).Add( right ); } + __forceinline xAddressInfo operator+( const xAddressInfo& right ) const { return xAddressInfo( *this ).Add( right ); } + __forceinline xAddressInfo operator+( s32 imm ) const { return xAddressInfo( *this ).Add( imm ); } + __forceinline xAddressInfo operator-( s32 imm ) const { return xAddressInfo( *this ).Add( -imm ); } + }; + + extern const xRegisterSSE + xmm0, xmm1, xmm2, xmm3, + xmm4, xmm5, xmm6, xmm7; + + extern const xRegisterMMX + mm0, mm1, mm2, mm3, + mm4, mm5, mm6, mm7; + + extern const xAddressReg + eax, ebx, ecx, edx, + esi, edi, ebp, esp; + + extern const xRegister16 + ax, bx, cx, dx, + si, di, bp, sp; + + extern const xRegister8 + al, dl, bl, + ah, ch, dh, bh; + + extern const xRegisterCL cl; // I'm special! + + ////////////////////////////////////////////////////////////////////////////////////////// + // ModSib - Internal low-level representation of the ModRM/SIB information. + // + // This class serves two purposes: It houses 'reduced' ModRM/SIB info only, which means + // that the Base, Index, Scale, and Displacement values are all in the correct arrange- + // ments, and it serves as a type-safe layer between the xRegister's operators (which + // generate xAddressInfo types) and the emitter's ModSib instruction forms. Without this, + // the xRegister would pass as a ModSib type implicitly, and that would cause ambiguity + // on a number of instructions. + // + // End users should always use xAddressInfo instead. + // + class ModSibBase + { + public: + xAddressReg Base; // base register (no scale) + xAddressReg Index; // index reg gets multiplied by the scale + uint Scale; // scale applied to the index register, in scale/shift form + s32 Displacement; // offset applied to the Base/Index registers. + + public: + explicit ModSibBase( const xAddressInfo& src ); + explicit ModSibBase( s32 disp ); + ModSibBase( xAddressReg base, xAddressReg index, int scale=0, s32 displacement=0 ); + + bool IsByteSizeDisp() const { return is_s8( Displacement ); } + + __forceinline ModSibBase& Add( s32 imm ) + { + Displacement += imm; + return *this; + } + + __forceinline ModSibBase operator+( const s32 imm ) const { return ModSibBase( *this ).Add( imm ); } + __forceinline ModSibBase operator-( const s32 imm ) const { return ModSibBase( *this ).Add( -imm ); } + + protected: + void Reduce(); + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Strictly-typed version of ModSibBase, which is used to apply operand size information + // to ImmToMem operations. + // + template< typename OperandType > + class ModSibStrict : public ModSibBase + { + public: + static const uint OperandSize = sizeof( OperandType ); + + __forceinline explicit ModSibStrict( const xAddressInfo& src ) : ModSibBase( src ) {} + __forceinline explicit ModSibStrict( s32 disp ) : ModSibBase( disp ) {} + __forceinline ModSibStrict( xAddressReg base, xAddressReg index, int scale=0, s32 displacement=0 ) : + ModSibBase( base, index, scale, displacement ) {} + + __forceinline ModSibStrict& Add( s32 imm ) + { + Displacement += imm; + return *this; + } + + __forceinline ModSibStrict operator+( const s32 imm ) const { return ModSibStrict( *this ).Add( imm ); } + __forceinline ModSibStrict operator-( const s32 imm ) const { return ModSibStrict( *this ).Add( -imm ); } + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // xAddressIndexerBase - This is a static class which provisions our ptr[] syntax. + // + struct xAddressIndexerBase + { + // passthrough instruction, allows ModSib to pass silently through ptr translation + // without doing anything and without compiler error. + const ModSibBase& operator[]( const ModSibBase& src ) const { return src; } + + __forceinline ModSibBase operator[]( xAddressReg src ) const + { + return ModSibBase( src, xAddressReg::Empty ); + } + + __forceinline ModSibBase operator[]( const xAddressInfo& src ) const + { + return ModSibBase( src ); + } + + __forceinline ModSibBase operator[]( uptr src ) const + { + return ModSibBase( src ); + } + + __forceinline ModSibBase operator[]( const void* src ) const + { + return ModSibBase( (uptr)src ); + } + + xAddressIndexerBase() {} // appease the GCC gods + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // Explicit version of ptr[], in the form of ptr32[], ptr16[], etc. which allows + // specification of the operand size for ImmToMem operations. + // + template< typename OperandType > + struct xAddressIndexer + { + static const uint OperandSize = sizeof( OperandType ); + + // passthrough instruction, allows ModSib to pass silently through ptr translation + // without doing anything and without compiler error. + const ModSibStrict& operator[]( const ModSibStrict& src ) const { return src; } + + __forceinline ModSibStrict operator[]( xAddressReg src ) const + { + return ModSibStrict( src, xAddressReg::Empty ); + } + + __forceinline ModSibStrict operator[]( const xAddressInfo& src ) const + { + return ModSibStrict( src ); + } + + __forceinline ModSibStrict operator[]( uptr src ) const + { + return ModSibStrict( src ); + } + + __forceinline ModSibStrict operator[]( const void* src ) const + { + return ModSibStrict( (uptr)src ); + } + + xAddressIndexer() {} // GCC initialization dummy + }; + + // ptr[] - use this form for instructions which can resolve the address operand size from + // the other register operand sizes. + extern const xAddressIndexerBase ptr; + extern const xAddressIndexer ptr128; + extern const xAddressIndexer ptr64; + extern const xAddressIndexer ptr32; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms + extern const xAddressIndexer ptr16; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms + extern const xAddressIndexer ptr8; // explicitly typed addressing, usually needed for '[dest],imm' instruction forms + + ////////////////////////////////////////////////////////////////////////////////////////// + // JccComparisonType - enumerated possibilities for inspired code branching! + // + enum JccComparisonType + { + Jcc_Unknown = -2, + Jcc_Unconditional = -1, + Jcc_Overflow = 0x0, + Jcc_NotOverflow = 0x1, + Jcc_Below = 0x2, + Jcc_Carry = 0x2, + Jcc_AboveOrEqual = 0x3, + Jcc_NotCarry = 0x3, + Jcc_Zero = 0x4, + Jcc_Equal = 0x4, + Jcc_NotZero = 0x5, + Jcc_NotEqual = 0x5, + Jcc_BelowOrEqual = 0x6, + Jcc_Above = 0x7, + Jcc_Signed = 0x8, + Jcc_Unsigned = 0x9, + Jcc_ParityEven = 0xa, + Jcc_ParityOdd = 0xb, + Jcc_Less = 0xc, + Jcc_GreaterOrEqual = 0xd, + Jcc_LessOrEqual = 0xe, + Jcc_Greater = 0xf, + }; + + // Not supported yet: + //E3 cb JECXZ rel8 Jump short if ECX register is 0. + + ////////////////////////////////////////////////////////////////////////////////////////// + // SSE2_ComparisonType - enumerated possibilities for SIMD data comparison! + // + enum SSE2_ComparisonType + { + SSE2_Equal = 0, + SSE2_Less, + SSE2_LessOrEqual, + SSE2_Unordered, + SSE2_NotEqual, + SSE2_NotLess, + SSE2_NotLessOrEqual, + SSE2_Ordered + }; + + + ////////////////////////////////////////////////////////////////////////////////////////// + // xSmartJump + // This class provides an interface for generating forward-based j8's or j32's "smartly" + // as per the measured displacement distance. If the displacement is a valid s8, then + // a j8 is inserted, else a j32. + // + // Note: This class is inherently unsafe, and so it's recommended to use xForwardJump8/32 + // whenever it is known that the jump destination is (or is not) short. Only use + // xSmartJump in cases where it's unknown what jump encoding will be ideal. + // + // Important: Use this tool with caution! xSmartJump cannot be used in cases where jump + // targets overlap, since the writeback of the second target will alter the position of + // the first target (which breaks the relative addressing). To assist in avoiding such + // errors, xSmartJump works based on C++ block scope, where the destruction of the + // xSmartJump object (invoked by a '}') signals the target of the jump. Example: + // + // { + // iCMP( EAX, ECX ); + // xSmartJump jumpTo( Jcc_Above ); + // [... conditional code ...] + // } // smartjump targets this spot. + // + // No code inside the scope can attempt to jump outside the scoped block (unless the jump + // uses an immediate addressing method, such as Register or Mod/RM forms of JMP/CALL). + // Multiple SmartJumps can be safely nested inside scopes, as long as they are properly + // scoped themselves. + // + // Performance Analysis: j8's use 4 less byes per opcode, and thus can provide minor + // speed benefits in the form of L1/L2 cache clutter, on any CPU. They're also notably + // faster on P4's, and mildly faster on AMDs. (Core2's and i7's don't care) + // + class xSmartJump : public NoncopyableObject + { + protected: + u8* m_baseptr; // base address of the instruction (passed to the instruction emitter) + JccComparisonType m_cc; // comparison type of the instruction + + public: + const int GetMaxInstructionSize() const + { + jASSUME( m_cc != Jcc_Unknown ); + return ( m_cc == Jcc_Unconditional ) ? 5 : 6; + } + + JccComparisonType GetCondition() const { return m_cc; } + virtual ~xSmartJump(); + + // ------------------------------------------------------------------------ + // ccType - Comparison type to be written back to the jump instruction position. + // + xSmartJump( JccComparisonType ccType ) + { + jASSUME( ccType != Jcc_Unknown ); + m_baseptr = xGetPtr(); + m_cc = ccType; + xAdvancePtr( GetMaxInstructionSize() ); + } + + protected: + void SetTarget(); + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // xForwardJump + // Primary use of this class is through the various xForwardJA8/xForwardJLE32/etc. helpers + // defined later in this header. :) + // + template< typename OperandType > + class xForwardJump + { + public: + static const uint OperandSize = sizeof( OperandType ); + + // pointer to base of the instruction *Following* the jump. The jump address will be + // relative to this address. + s8* const BasePtr; + + // The jump instruction is emitted at the point of object construction. The conditional + // type must be valid (Jcc_Unknown generates an assertion). + xForwardJump( JccComparisonType cctype = Jcc_Unconditional ); + + // Sets the jump target by writing back the current x86Ptr to the jump instruction. + // This method can be called multiple times, re-writing the jump instruction's target + // in each case. (the the last call is the one that takes effect). + void SetTarget() const; + }; + + ////////////////////////////////////////////////////////////////////////////////////////// + // + namespace Internal + { + extern void SimdPrefix( u8 prefix, u16 opcode ); + extern void EmitSibMagic( uint regfield, const void* address ); + extern void EmitSibMagic( uint regfield, const ModSibBase& info ); + extern void xJccKnownTarget( JccComparisonType comparison, const void* target, bool slideForward ); + + + // Writes a ModRM byte for "Direct" register access forms, which is used for all + // instructions taking a form of [reg,reg]. + template< typename T > __emitinline + void EmitSibMagic( uint reg1, const xRegisterBase& reg2 ) + { + xWrite8( (Mod_Direct << 6) | (reg1 << 3) | reg2.Id ); + } + + template< typename T1, typename T2 > __emitinline + void EmitSibMagic( const xRegisterBase reg1, const xRegisterBase& reg2 ) + { + xWrite8( (Mod_Direct << 6) | (reg1.Id << 3) | reg2.Id ); + } + + template< typename T1 > __emitinline + void EmitSibMagic( const xRegisterBase reg1, const void* src ) { EmitSibMagic( reg1.Id, src ); } + + template< typename T1 > __emitinline + void EmitSibMagic( const xRegisterBase reg1, const ModSibBase& sib ) { EmitSibMagic( reg1.Id, sib ); } + + // ------------------------------------------------------------------------ + template< typename T1, typename T2 > __emitinline + void xOpWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 ) + { + if( prefix != 0 ) + xWrite16( (opcode<<8) | prefix ); + else + xWrite8( opcode ); + + EmitSibMagic( param1, param2 ); + } + + // ------------------------------------------------------------------------ + template< typename T1, typename T2 > __emitinline + void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2 ) + { + SimdPrefix( prefix, opcode ); + EmitSibMagic( param1, param2 ); + } + + template< typename T1, typename T2 > __emitinline + void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2, u8 imm8 ) + { + xOpWrite0F( prefix, opcode, param1, param2 ); + xWrite8( imm8 ); + } + + template< typename T1, typename T2 > __emitinline + void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2 ) { xOpWrite0F( 0, opcode, param1, param2 ); } + + template< typename T1, typename T2 > __emitinline + void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2, u8 imm8 ) { xOpWrite0F( 0, opcode, param1, param2, imm8 ); } + + // ------------------------------------------------------------------------ + + template< typename T > bool Is8BitOp() { return sizeof(T) == 1; } + template< typename T > void prefix16() { if( sizeof(T) == 2 ) xWrite8( 0x66 ); } + + #include "implement/xmm/basehelpers.h" + #include "implement/xmm/moremovs.h" + #include "implement/xmm/arithmetic.h" + #include "implement/xmm/comparisons.h" + #include "implement/xmm/shufflepack.h" + #include "implement/group1.h" + #include "implement/group2.h" + #include "implement/group3.h" + #include "implement/movs.h" // cmov and movsx/zx + #include "implement/dwshift.h" // doubleword shifts! + #include "implement/incdec.h" + #include "implement/test.h" + #include "implement/jmpcall.h" + } +} + +#include "ix86_inlines.inl" diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 4613a13acb..daa5f01ad3 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -28,6 +28,7 @@ PCSX2_ALIGNED16(microVU microVU0); PCSX2_ALIGNED16(microVU microVU1); +FILE *mVUlogFile[2] = {NULL, NULL}; declareAllVariables // Declares All Global Variables :D //------------------------------------------------------------------ @@ -41,9 +42,11 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr) { mVU->regs = vuRegsPtr; mVU->index = vuIndex; mVU->microSize = (vuIndex ? 0x4000 : 0x1000); - mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 8; - mVU->cacheAddr = 0xC0000000 + (vuIndex ? mVU->cacheSize : 0); + mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4; mVU->cache = NULL; + memset(&mVU->prog, 0, sizeof(mVU->prog)); + mVUprint((vuIndex) ? "microVU1: init" : "microVU0: init"); + mVUsetupLog(); mVUreset(); } @@ -54,35 +57,56 @@ microVUt(void) mVUreset() { microVU* mVU = mVUx; mVUclose(); // Close + mVUprint((vuIndex) ? "microVU1: reset" : "microVU0: reset"); + + // Dynarec Cache + mVU->cache = SysMmapEx((vuIndex ? 0x1e840000 : 0x0e840000), mVU->cacheSize, 0, (vuIndex ? "Micro VU1" : "Micro VU0")); + if ( mVU->cache == NULL ) throw Exception::OutOfMemory(fmt_string( "microVU Error: Failed to allocate recompiler memory! (addr: 0x%x)", params (u32)mVU->cache)); + memset(mVU->cache, 0xcc, mVU->cacheSize); + + // Setup Entrance/Exit Points + x86SetPtr(mVU->cache); + mVUdispatcherA(); + mVUdispatcherB(); + + // Clear All Program Data + memset(&mVU->prog, 0, sizeof(mVU->prog)); + // Create Block Managers - for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < (mVU->progSize / 2); j++) { + for (int i = 0; i <= mVU->prog.max; i++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { mVU->prog.prog[i].block[j] = new microBlockManager(); } } - // Dynarec Cache - mVU->cache = SysMmapEx(mVU->cacheAddr, mVU->cacheSize, 0x10000000, (vuIndex ? "Micro VU1" : "Micro VU0")); - if ( mVU->cache == NULL ) throw Exception::OutOfMemory(fmt_string( "microVU Error: failed to allocate recompiler memory! (addr: 0x%x)", params (u32)mVU->cache)); - - // Other Variables - memset(&mVU->prog, 0, sizeof(mVU->prog)); + // Program Variables mVU->prog.finished = 1; mVU->prog.cleared = 1; mVU->prog.cur = -1; mVU->prog.total = -1; + //mVU->prog.lpState = &mVU->prog.prog[15].allocInfo.block.pState; // Blank Pipeline State (ToDo: finish implementation) + + // Setup Dynarec Cache Limits for Each Program + u8* z = (mVU->cache + 512); // Dispatcher Code is in first 512 bytes + for (int i = 0; i <= mVU->prog.max; i++) { + mVU->prog.prog[i].x86start = z; + mVU->prog.prog[i].x86ptr = z; + z += (mVU->cacheSize / (mVU->prog.max + 1)); + mVU->prog.prog[i].x86end = z; + } } // Free Allocated Resources microVUt(void) mVUclose() { microVU* mVU = mVUx; + mVUprint((vuIndex) ? "microVU1: close" : "microVU0: close"); if ( mVU->cache ) { HostSys::Munmap( mVU->cache, mVU->cacheSize ); mVU->cache = NULL; } // Delete Block Managers - for (int i; i <= mVU->prog.max; i++) { - for (u32 j; j < (mVU->progSize / 2); j++) { + for (int i = 0; i <= mVU->prog.max; i++) { + for (u32 j = 0; j < (mVU->progSize / 2); j++) { if (mVU->prog.prog[i].block[j]) delete mVU->prog.prog[i].block[j]; } } @@ -92,6 +116,7 @@ microVUt(void) mVUclose() { microVUt(void) mVUclear(u32 addr, u32 size) { microVU* mVU = mVUx; + memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState)); mVU->prog.cleared = 1; // Next execution searches/creates a new microprogram // Note: It might be better to copy old recompiled blocks to the new microprogram rec data // however, if games primarily do big writes, its probably not worth it. @@ -99,55 +124,34 @@ microVUt(void) mVUclear(u32 addr, u32 size) { // that its probably not worth it... } -// Executes for number of cycles -microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { -/* - Pseudocode: (ToDo: implement # of cycles) - 1) Search for existing program - 2) If program not found, goto 5 - 3) Search for recompiled block - 4) If recompiled block found, goto 6 - 5) Recompile as much blocks as possible - 6) Return start execution address of block -*/ - microVU* mVU = mVUx; - if ( mVUsearchProg(mVU) ) { // Found Program - //microBlock* block = mVU->prog.prog[mVU->prog.cur].block[startPC]->search(mVU->prog.lastPipelineState); - //if (block) return block->x86ptrStart; // Found Block - } - // Recompile code - return NULL; -} - -void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { - return mVUexecute<0>(startPC, cycles); -} -void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { - return mVUexecute<1>(startPC, cycles); -} - //------------------------------------------------------------------ // Micro VU - Private Functions //------------------------------------------------------------------ // Clears program data (Sets used to 1 because calling this function implies the program will be used at least once) -__forceinline void mVUclearProg(microVU* mVU, int progIndex) { +microVUt(void) mVUclearProg(int progIndex) { + microVU* mVU = mVUx; mVU->prog.prog[progIndex].used = 1; + mVU->prog.prog[progIndex].x86ptr = mVU->prog.prog[progIndex].x86start; for (u32 i = 0; i < (mVU->progSize / 2); i++) { mVU->prog.prog[progIndex].block[i]->reset(); } } // Caches Micro Program -__forceinline void mVUcacheProg(microVU* mVU, int progIndex) { +microVUt(void) mVUcacheProg(int progIndex) { + microVU* mVU = mVUx; memcpy_fast(mVU->prog.prog[progIndex].data, mVU->regs->Micro, mVU->microSize); + mVUdumpProg(progIndex); } // Finds the least used program, (if program list full clears and returns an old program; if not-full, returns free program) -__forceinline int mVUfindLeastUsedProg(microVU* mVU) { +microVUt(int) mVUfindLeastUsedProg() { + microVU* mVU = mVUx; if (mVU->prog.total < mVU->prog.max) { mVU->prog.total++; - mVUcacheProg(mVU, mVU->prog.total); // Cache Micro Program + mVUcacheProg(mVU->prog.total); // Cache Micro Program + Console::Notice("microVU: Program Total = %d", params mVU->prog.total); return mVU->prog.total; } else { @@ -159,33 +163,35 @@ __forceinline int mVUfindLeastUsedProg(microVU* mVU) { j = i; } } - mVUclearProg(mVU, j); // Clear old data if overwriting old program - mVUcacheProg(mVU, j); // Cache Micro Program + mVUclearProg(j); // Clear old data if overwriting old program + mVUcacheProg(j); // Cache Micro Program + Console::Notice("microVU: Program Cache got Full!"); return j; } } // Searches for Cached Micro Program and sets prog.cur to it (returns 1 if program found, else returns 0) -__forceinline int mVUsearchProg(microVU* mVU) { +microVUt(int) mVUsearchProg() { + microVU* mVU = mVUx; if (mVU->prog.cleared) { // If cleared, we need to search for new program for (int i = 0; i <= mVU->prog.total; i++) { //if (i == mVU->prog.cur) continue; // We can skip the current program. (ToDo: Verify that games don't clear, and send the same microprogram :/) if (!memcmp_mmx(mVU->prog.prog[i].data, mVU->regs->Micro, mVU->microSize)) { - if (i == mVU->prog.cur) SysPrintf("microVU: Same micro program sent!\n"); + //if (i == mVU->prog.cur) { mVUprint("microVU: Same micro program sent!"); } mVU->prog.cur = i; mVU->prog.cleared = 0; mVU->prog.prog[i].used++; return 1; } } - mVU->prog.cur = mVUfindLeastUsedProg(mVU); // If cleared and program not found, make a new program instance + mVU->prog.cur = mVUfindLeastUsedProg(); // If cleared and program not found, make a new program instance mVU->prog.cleared = 0; return 0; } mVU->prog.prog[mVU->prog.cur].used++; return 1; // If !cleared, then we're still on the same program as last-time ;) } - +/* // Block Invalidation __forceinline void mVUinvalidateBlock(microVU* mVU, u32 addr, u32 size) { @@ -205,99 +211,32 @@ __forceinline void mVUinvalidateBlock(microVU* mVU, u32 addr, u32 size) { mVU->prog.prog[mVU->prog.cur].block[i]->clearFast(); } } - -//------------------------------------------------------------------ -// Dispatcher Functions -//------------------------------------------------------------------ - -#ifdef _MSC_VER -// Runs VU0 for number of cycles -__declspec(naked) void __fastcall startVU0(u32 startPC, u32 cycles) { - __asm { - // __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left. - call mVUexecuteVU0 - - /*backup cpu state*/ - push ebx; - push ebp; - push esi; - push edi; - - ldmxcsr g_sseVUMXCSR - /* Should set xmmZ? */ - jmp eax - } -} - -// Runs VU1 for number of cycles -__declspec(naked) void __fastcall startVU1(u32 startPC, u32 cycles) { - __asm { - - call mVUexecuteVU1 - - /*backup cpu state*/ - push ebx; - push ebp; - push esi; - push edi; - - ldmxcsr g_sseVUMXCSR - - jmp eax - } -} - -// Exit point -__declspec(naked) void __fastcall endVU0(u32 startPC, u32 cycles) { - __asm { - - //call mVUcleanUpVU0 - - /*restore cpu state*/ - pop edi; - pop esi; - pop ebp; - pop ebx; - - ldmxcsr g_sseMXCSR - emms - - ret - } -} -#else -extern "C" { - extern void __fastcall startVU0(u32 startPC, u32 cycles); - extern void __fastcall startVU1(u32 startPC, u32 cycles); - extern void __fastcall endVU0(u32 startPC, u32 cycles); -} -#endif - +*/ //------------------------------------------------------------------ // Wrapper Functions - Called by other parts of the Emu //------------------------------------------------------------------ -__forceinline void initVUrec(VURegs* vuRegs, const int vuIndex) { +void initVUrec(VURegs* vuRegs, const int vuIndex) { if (!vuIndex) mVUinit<0>(vuRegs); else mVUinit<1>(vuRegs); } -__forceinline void closeVUrec(const int vuIndex) { +void closeVUrec(const int vuIndex) { if (!vuIndex) mVUclose<0>(); else mVUclose<1>(); } -__forceinline void resetVUrec(const int vuIndex) { +void resetVUrec(const int vuIndex) { if (!vuIndex) mVUreset<0>(); else mVUreset<1>(); } -__forceinline void clearVUrec(u32 addr, u32 size, const int vuIndex) { +void clearVUrec(u32 addr, u32 size, const int vuIndex) { if (!vuIndex) mVUclear<0>(addr, size); else mVUclear<1>(addr, size); } -__forceinline void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { +void runVUrec(u32 startPC, u32 cycles, const int vuIndex) { if (!vuIndex) startVU0(startPC, cycles); else startVU1(startPC, cycles); } diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index c37a084043..78cd364220 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -17,8 +17,8 @@ */ #pragma once -#define mVUdebug // Prints Extra Info to Console -#define _EmitterId_ (vuIndex+1) +#define mVUdebug // Prints Extra Info to Console +#define mVUlogProg // Dumps MicroPrograms into microVU0.txt/microVU1.txt #include "Common.h" #include "VU.h" #include "GS.h" @@ -26,75 +26,51 @@ #include "microVU_Alloc.h" #include "microVU_Misc.h" -struct microBlock { - microRegInfo pState; // Detailed State of Pipeline - u32 pipelineState; // | FDiv x 4 | EFU x 6 | Needs pState Info? x 1 | // Simple State of Pipeline - u8* x86ptrStart; // Start of code - u8* x86ptrEnd; // End of code (first byte outside of block) - u8* x86ptrBranch; // - u32 size; // Number of 64bit VU Instructions in Block -}; - #define mMaxBlocks 32 // Max Blocks With Different Pipeline States (For n = 1, 2, 4, 8, 16, etc...) class microBlockManager { private: static const int MaxBlocks = mMaxBlocks - 1; - u32 startPC; - u32 endPC; int listSize; // Total Items - 1 - int callerSize; // Total Callers - 1 microBlock blockList[mMaxBlocks]; - microBlock callersList[mMaxBlocks]; // Foreign Blocks that call Local Blocks public: - microBlockManager() { init(); } - ~microBlockManager() { close(); } - void init() { - listSize = -1; - callerSize = -1; - //ZeroMemory(&blockList, sizeof(blockList)); // Can be Omitted? - //ZeroMemory(&blockList, sizeof(callersList)); // Can be Omitted? - } - void reset() { init(); }; - void close() {}; // Can be Omitted? - /*void add(u32 pipelineState, u8* x86ptrStart) { - if (!search(pipelineState)) { + microBlockManager() { reset(); } + ~microBlockManager() {} + void reset() { listSize = -1; }; + microBlock* add(microBlock* pBlock) { + microBlock* thisBlock = search(&pBlock->pState); + if (!thisBlock) { listSize++; listSize &= MaxBlocks; - blockList[listSize].pipelineState = pipelineState; - blockList[listSize].x86ptrStart = x86ptrStart; + memcpy_fast(&blockList[listSize], pBlock, sizeof(microBlock)); + thisBlock = &blockList[listSize]; } - }*/ - microBlock* search(u32 pipelineState, microRegInfo* pState) { - if (pipelineState & 1) { // Needs Detailed Search (Exact Match of Pipeline State) - for (int i = 0; i < listSize; i++) { - if (!memcmp(pState, &blockList[i].pState, sizeof(microRegInfo))) return &blockList[i]; + return thisBlock; + } + microBlock* search(microRegInfo* pState) { + if (listSize < 0) return NULL; + //if (blockList[0].pState.needExactMatch) { // Needs Detailed Search (Exact Match of Pipeline State) + for (int i = 0; i <= listSize; i++) { + if (!memcmp(pState, &blockList[i].pState, sizeof(microRegInfo) - 1)) return &blockList[i]; } - } + /*} else { // Can do Simple Search (Only Matches the Important Pipeline Stuff) - for (int i = 0; i < listSize; i++) { - if (blockList[i].pipelineState == pipelineState) return &blockList[i]; + for (int i = 0; i <= listSize; i++) { + if ((blockList[i].pState.q == pState->q) && (blockList[i].pState.p == pState->p)) { return &blockList[i]; } } - } + }*/ return NULL; } - void clearFast() { - listSize = -1; - for ( ; callerSize >= 0; callerSize--) { - //callerList[callerSize]. // ToDo: Implement Branch Link Removal Code - } - } - int clear() { - if (listSize >= 0) { clearFast(); return 1; } - else return 0; - } }; template struct microProgram { - u32 data[progSize]; - u32 used; // Number of times its been used - microBlockManager* block[progSize / 2]; + u32 data[progSize/4]; + u32 used; // Number of times its been used + u8* x86ptr; // Pointer to program's recompilation code + u8* x86start; // Start of program's rec-cache + u8* x86end; // Limit of program's rec-cache + microBlockManager* block[progSize/8]; microAllocInfo allocInfo; }; @@ -107,36 +83,32 @@ struct microProgManager { int total; // Total Number of valid MicroPrograms minus 1 int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one) int finished; // Completed MicroProgram by E-bit Termination - u32 lastPipelineState; // Pipeline state from where it left off (useful for continuing execution) + microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution) }; struct microVU { u32 index; // VU Index (VU0 or VU1) u32 microSize; // VU Micro Memory Size - u32 progSize; // VU Micro Program Size (microSize/8) - u32 cacheAddr; // VU Cache Start Address - static const u32 cacheSize = 0x500000; // VU Cache Size + u32 progSize; // VU Micro Program Size (microSize/4) + static const u32 cacheSize = 0x800000; // VU Cache Size - microProgManager<0x1000> prog; // Micro Program Data + microProgManager<0x4000> prog; // Micro Program Data VURegs* regs; // VU Regs Struct u8* cache; // Dynarec Cache Start (where we will start writing the recompiled code to) - u8* ptr; // Pointer to next place to write recompiled code to + u8* startFunct; // Ptr Function to the Start code for recompiled programs + u8* exitFunct; // Ptr Function to the Exit code for recompiled programs u32 code; // Contains the current Instruction u32 iReg; // iReg (only used in recompilation, not execution) u32 clipFlag[4]; // 4 instances of clip flag (used in execution) u32 divFlag; // 1 instance of I/D flags - -/* - uptr x86eax; // Accumulator register. Used in arithmetic operations. - uptr x86ecx; // Counter register. Used in shift/rotate instructions. - uptr x86edx; // Data register. Used in arithmetic operations and I/O operations. - uptr x86ebx; // Base register. Used as a pointer to data (located in DS in segmented mode). - uptr x86esp; // Stack Pointer register. Pointer to the top of the stack. - uptr x86ebp; // Stack Base Pointer register. Used to point to the base of the stack. - uptr x86esi; // Source register. Used as a pointer to a source in stream operations. - uptr x86edi; // Destination register. Used as a pointer to a destination in stream operations. -*/ + u32 VIbackup[2]; // Holds a backup of a VI reg if modified before a branch + u32 branch; // Holds branch compare result (IBxx) OR Holds address to Jump to (JALR/JR) + u32 p; // Holds current P instance index + u32 q; // Holds current Q instance index + u32 espBackup; // Temp Backup for ESP + u32 totalCycles; + u32 cycles; }; // microVU rec structs @@ -147,19 +119,36 @@ extern PCSX2_ALIGNED16(microVU microVU1); extern void (*mVU_UPPER_OPCODE[64])( VURegs* VU, s32 info ); extern void (*mVU_LOWER_OPCODE[128])( VURegs* VU, s32 info ); -__forceinline void mVUclearProg(microVU* mVU, int progIndex); -__forceinline int mVUfindLeastUsedProg(microVU* mVU); -__forceinline int mVUsearchProg(microVU* mVU); -__forceinline void mVUcacheProg(microVU* mVU, int progIndex); +// Used for logging microPrograms +extern FILE *mVUlogFile[2]; -#ifdef __LINUX__ +// Main Functions +microVUt(void) mVUinit(VURegs*); microVUt(void) mVUreset(); microVUt(void) mVUclose(); +microVUt(void) mVUclear(u32, u32); + +// Private Functions +microVUt(void) mVUclearProg(microVU* mVU, int progIndex); +microVUt(int) mVUfindLeastUsedProg(microVU* mVU); +microVUt(int) mVUsearchProg(microVU* mVU); +microVUt(void) mVUcacheProg(microVU* mVU, int progIndex); +void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles); +void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles); + +#ifndef __LINUX__ +typedef void (__fastcall *mVUrecCall)(u32, u32); +#else +typedef void (*mVUrecCall)(u32, u32) __attribute__((__fastcall)); // Not sure if this is correct syntax (should be close xD) #endif // Include all the *.inl files (Needed because C++ sucks with templates and *.cpp files) #include "microVU_Misc.inl" +#include "microVU_Log.inl" #include "microVU_Analyze.inl" #include "microVU_Alloc.inl" +#include "microVU_Upper.inl" +#include "microVU_Lower.inl" #include "microVU_Tables.inl" #include "microVU_Compile.inl" +#include "microVU_Execute.inl" diff --git a/pcsx2/x86/microVU_Alloc.h b/pcsx2/x86/microVU_Alloc.h index c539eb1297..a16c3f4396 100644 --- a/pcsx2/x86/microVU_Alloc.h +++ b/pcsx2/x86/microVU_Alloc.h @@ -18,6 +18,7 @@ #pragma once + union regInfo { u32 reg; struct { @@ -33,6 +34,10 @@ struct microRegInfo { u8 VI[32]; u8 q; u8 p; + u8 r; + u8 xgkick; + u8 clip; + u8 needExactMatch; // If set, block needs an exact match of pipeline state (needs to be last byte in struct) }; struct microTempRegInfo { @@ -42,40 +47,25 @@ struct microTempRegInfo { u8 VIreg; // Index of the VI reg u8 q; // Holds cycle info for Q reg u8 p; // Holds cycle info for P reg + u8 r; // Holds cycle info for R reg (Will never cause stalls, but useful to know if R is modified) + u8 xgkick; // Holds the cycle info for XGkick +}; + +struct microBlock { + microRegInfo pState; // Detailed State of Pipeline + microRegInfo pStateEnd; // Detailed State of Pipeline at End of Block (needed by JR/JALR opcodes) + u8* x86ptrStart; // Start of code }; template struct microAllocInfo { - microRegInfo regs; // Pipeline info + microBlock block; // Block/Pipeline info microTempRegInfo regsTemp; // Temp Pipeline info (used so that new pipeline info isn't conflicting between upper and lower instructions in the same cycle) - u8 branch; // 0 = No Branch, 1 = Branch, 2 = Conditional Branch, 3 = Jump (JALR/JR) - u8 divFlag; // 0 = Transfer DS/IS flags normally, 1 = Clear DS/IS Flags, > 1 = set DS/IS flags to bit 2::1 of divFlag - u8 divFlagTimer; // Used to ensure divFlag's contents are merged at the appropriate time. - u8 maxStall; // Helps in computing stalls (stores the max amount of cycles to stall for the current opcodes) + u8 branch; // 0 = No Branch, 1 = B. 2 = BAL, 3~8 = Conditional Branches, 9 = JALR, 10 = JR u32 cycles; // Cycles for current block + u32 count; // Number of VU 64bit instructions ran (starts at 0 for each block) u32 curPC; // Current PC - u32 info[pSize]; // bit 00 = Lower Instruction is NOP - // bit 01 - // bit 02 - // bit 03 - // bit 04 - // bit 05 = Write to Q1 or Q2? - // bit 06 = Read Q1 or Q2? - // bit 07 = Read/Write to P1 or P2? - // bit 08 = Update Mac Flags? - // bit 09 = Update Status Flags? - // bit 10 = Used with bit 11 to make a 2-bit key for mac flag instance - // bit 11 - // bit 12 = Used with bit 13 to make a 2-bit key for status flag instance - // bit 13 - // bit 14 = Used with bit 15 to make a 2-bit key for clip flag instance - // bit 15 - // bit 16 = Used with bit 17 to make a 2-bit key for mac flag instance - // bit 17 - // bit 18 = Used with bit 19 to make a 2-bit key for status flag instance - // bit 19 - // bit 20 = Used with bit 21 to make a 2-bit key for clip flag instance - // bit 21 - // bit 22 = Read VI(Fs) from backup memory? - // bit 23 = Read VI(Ft) from backup memory? + u32 startPC; // Start PC for Cur Block + u32 info[pSize/8]; // Info for Instructions in current block + u8 stall[pSize/8]; // Info on how much each instruction stalled (stores the max amount of cycles to stall for the current opcodes) }; diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index ca6cee9e09..72c4a56f24 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -56,7 +56,7 @@ microVUt(void) mVUallocFMAC1b(int& Fd) { microVU* mVU = mVUx; if (!_Fd_) return; if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmT1, _X_Y_Z_W); - mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W); + mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 1); } //------------------------------------------------------------------ @@ -74,7 +74,7 @@ microVUt(void) mVUallocFMAC2b(int& Ft) { microVU* mVU = mVUx; if (!_Ft_) { SysPrintf("microVU: If a game does this, its retarded...\n"); return; } //if (CHECK_VU_OVERFLOW) mVUclamp1(Ft, xmmT1, _X_Y_Z_W); - mVUsaveReg(Ft, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(Ft, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } //------------------------------------------------------------------ @@ -89,7 +89,7 @@ microVUt(void) mVUallocFMAC2b(int& Ft) { #define getReg3(reg, _reg_) { \ mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], (1 << (3 - _bc_))); \ if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, (1 << (3 - _bc_))); \ - mVUunpack_xyzw(reg, reg, _bc_); \ + mVUunpack_xyzw(reg, reg, 0); \ } #define getZero3SS(reg) { \ @@ -100,7 +100,7 @@ microVUt(void) mVUallocFMAC2b(int& Ft) { #define getZero3(reg) { \ if (_bc_w) { \ mVUloadReg(reg, (uptr)&mVU->regs->VF[0].UL[0], 1); \ - mVUunpack_xyzw(reg, reg, _bc_); \ + mVUunpack_xyzw(reg, reg, 0); \ } \ else { SSE_XORPS_XMM_to_XMM(reg, reg); } \ } @@ -112,7 +112,7 @@ microVUt(void) mVUallocFMAC3a(int& Fd, int& Fs, int& Ft) { Fd = xmmFs; if (_XYZW_SS) { getReg6(Fs, _Fs_); - if ( (_Ft_ == _Fs_) && ((_X && _bc_x) || (_Y && _bc_y) || (_Z && _bc_w) || (_W && _bc_w)) ) { + if ( (_Ft_ == _Fs_) && ((_X && _bc_x) || (_Y && _bc_y) || (_Z && _bc_z) || (_W && _bc_w)) ) { Ft = Fs; } else if (!_Ft_) { getZero3SS(Ft); } @@ -201,11 +201,11 @@ microVUt(void) mVUallocFMAC5b(int& ACC, int& Fs) { // FMAC6 - Normal FMAC Opcodes (I Reg) //------------------------------------------------------------------ -#define getIreg(reg) { \ - MOV32ItoR(gprT1, mVU->iReg); \ - SSE2_MOVD_R_to_XMM(reg, gprT1); \ - if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 8); \ - if (!_XYZW_SS) { mVUunpack_xyzw(reg, reg, 0); } \ +#define getIreg(reg, modXYZW) { \ + MOV32MtoR(gprT1, (uptr)&mVU->regs->VI[REG_I].UL); \ + SSE2_MOVD_R_to_XMM(reg, gprT1); \ + if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 8); \ + if (!((_XYZW_SS && modXYZW) || (_X_Y_Z_W == 8))) { mVUunpack_xyzw(reg, reg, 0); } \ } microVUt(void) mVUallocFMAC6a(int& Fd, int& Fs, int& Ft) { @@ -213,7 +213,7 @@ microVUt(void) mVUallocFMAC6a(int& Fd, int& Fs, int& Ft) { Fs = xmmFs; Ft = xmmFt; Fd = xmmFs; - getIreg(Ft); + getIreg(Ft, 1); getReg6(Fs, _Fs_); } @@ -230,7 +230,7 @@ microVUt(void) mVUallocFMAC7a(int& ACC, int& Fs, int& Ft) { ACC = xmmACC; Fs = (_X_Y_Z_W == 15) ? xmmACC : xmmFs; Ft = xmmFt; - getIreg(Ft); + getIreg(Ft, 0); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } @@ -269,7 +269,7 @@ microVUt(void) mVUallocFMAC8b(int& Fd) { microVU* mVU = mVUx; if (!_Fd_) return; if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmT1, _xyzw_ACC); - mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W); + mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 0); } //------------------------------------------------------------------ @@ -282,7 +282,6 @@ microVUt(void) mVUallocFMAC9a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } @@ -296,13 +295,14 @@ microVUt(void) mVUallocFMAC9a(int& Fd, int& ACC, int& Fs, int& Ft) { else if (!_Ft_) { getZero4(Ft); } else { getReg4(Ft, _Ft_); } } + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); } microVUt(void) mVUallocFMAC9b(int& Fd) { microVU* mVU = mVUx; if (!_Fd_) return; if (CHECK_VU_OVERFLOW) mVUclamp1(Fd, xmmFt, _xyzw_ACC); - mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W); + mVUsaveReg(Fd, (uptr)&mVU->regs->VF[_Fd_].UL[0], _X_Y_Z_W, 0); } //------------------------------------------------------------------ @@ -344,7 +344,6 @@ microVUt(void) mVUallocFMAC11a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ( (_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } @@ -358,6 +357,7 @@ microVUt(void) mVUallocFMAC11a(int& Fd, int& ACC, int& Fs, int& Ft) { if (!_Ft_) { getZero3(Ft); } else { getReg3(Ft, _Ft_); } } + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); } microVUt(void) mVUallocFMAC11b(int& Fd) { @@ -374,7 +374,7 @@ microVUt(void) mVUallocFMAC12a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmFs; ACC = xmmACC; - getIreg(Ft); + getIreg(Ft, 0); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } @@ -394,11 +394,11 @@ microVUt(void) mVUallocFMAC13a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); - getIreg(Ft); + getIreg(Ft, 0); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); } microVUt(void) mVUallocFMAC13b(int& Fd) { @@ -415,8 +415,7 @@ microVUt(void) mVUallocFMAC14a(int& ACCw, int& ACCr, int& Fs, int& Ft) { Ft = xmmFt; ACCw = xmmACC; ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); - + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if (_Ft_ == _Fs_) { Ft = Fs; } @@ -430,6 +429,7 @@ microVUt(void) mVUallocFMAC14a(int& ACCw, int& ACCr, int& Fs, int& Ft) { else if (!_Ft_) { getZero4(Ft); } else { getReg4(Ft, _Ft_); } } + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); } microVUt(void) mVUallocFMAC14b(int& ACCw, int& ACCr) { @@ -448,8 +448,7 @@ microVUt(void) mVUallocFMAC15a(int& ACCw, int& ACCr, int& Fs, int& Ft) { Ft = xmmFt; ACCw = xmmACC; ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); - + if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); if ((_Ft_ == _Fs_) && _bc_x) { Ft = Fs; } @@ -463,6 +462,7 @@ microVUt(void) mVUallocFMAC15a(int& ACCw, int& ACCr, int& Fs, int& Ft) { if (!_Ft_) { getZero3(Ft); } else { getReg3(Ft, _Ft_); } } + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); } microVUt(void) mVUallocFMAC15b(int& ACCw, int& ACCr) { @@ -479,11 +479,11 @@ microVUt(void) mVUallocFMAC16a(int& ACCw, int& ACCr, int& Fs, int& Ft) { Ft = xmmFt; ACCw = xmmACC; ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); - getIreg(Ft); + getIreg(Ft, 0); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); } microVUt(void) mVUallocFMAC16b(int& ACCw, int& ACCr) { @@ -497,7 +497,7 @@ microVUt(void) mVUallocFMAC16b(int& ACCw, int& ACCr) { #define getReg9(reg, _reg_) { \ mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], 1); \ if (CHECK_VU_EXTRA_OVERFLOW) mVUclamp2(reg, xmmT1, 1); \ - mVUunpack_xyzw(reg, reg, 3); \ + mVUunpack_xyzw(reg, reg, 0); \ } microVUt(void) mVUallocFMAC17a(int& Fs, int& Ft) { @@ -542,8 +542,7 @@ microVUt(void) mVUallocFMAC19a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); - + if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } @@ -552,6 +551,7 @@ microVUt(void) mVUallocFMAC19a(int& Fd, int& ACC, int& Fs, int& Ft) { SSE2_PSHUFD_XMM_to_XMM(Fs, Fs, 0xC9); // WXZY SSE2_PSHUFD_XMM_to_XMM(Ft, Ft, 0xD2); // WYXZ + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); } microVUt(void) mVUallocFMAC19b(int& Fd) { @@ -629,11 +629,11 @@ microVUt(void) mVUallocFMAC25a(int& Fd, int& ACC, int& Fs, int& Ft) { Ft = xmmFt; Fd = xmmT1; ACC = xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); getQreg(Ft); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } + SSE_MOVAPS_XMM_to_XMM(ACC, xmmACC); } microVUt(void) mVUallocFMAC25b(int& Fd) { @@ -650,11 +650,11 @@ microVUt(void) mVUallocFMAC26a(int& ACCw, int& ACCr, int& Fs, int& Ft) { Ft = xmmFt; ACCw = xmmACC; ACCr = ((_X_Y_Z_W == 15) || (_X_Y_Z_W == 8)) ? xmmACC : xmmT1; - SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); getQreg(Ft); if (_X_Y_Z_W == 8) { getReg6(Fs, _Fs_); } else if (!_Fs_) { getZero4(Fs); } else { getReg4(Fs, _Fs_); } + SSE_MOVAPS_XMM_to_XMM(ACCr, xmmACC); } microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) { @@ -665,13 +665,13 @@ microVUt(void) mVUallocFMAC26b(int& ACCw, int& ACCr) { // Flag Allocators //------------------------------------------------------------------ -#define getFlagReg(regX, fInst) { \ - switch (fInst) { \ +#define getFlagReg(regX, fInst) { \ + switch (fInst) { \ case 0: regX = gprF0; break; \ case 1: regX = gprF1; break; \ case 2: regX = gprF2; break; \ case 3: regX = gprF3; break; \ - } \ + } \ } microVUt(void) mVUallocSFLAGa(int reg, int fInstance) { @@ -682,8 +682,7 @@ microVUt(void) mVUallocSFLAGa(int reg, int fInstance) { microVUt(void) mVUallocSFLAGb(int reg, int fInstance) { getFlagReg(fInstance, fInstance); - AND32ItoR(fInstance, 0xffff0000); - OR16RtoR(fInstance, reg); + MOV16RtoR(fInstance, reg); } microVUt(void) mVUallocMFLAGa(int reg, int fInstance) { @@ -701,26 +700,14 @@ microVUt(void) mVUallocMFLAGb(int reg, int fInstance) { microVUt(void) mVUallocCFLAGa(int reg, int fInstance) { microVU* mVU = mVUx; - MOV32MtoR(reg, mVU->clipFlag[fInstance]); + MOV32MtoR(reg, (uptr)&mVU->clipFlag[fInstance]); } microVUt(void) mVUallocCFLAGb(int reg, int fInstance) { microVU* mVU = mVUx; - MOV32RtoM(mVU->clipFlag[fInstance], reg); -} -/* -microVUt(void) mVUallocDFLAGa(int reg) { - microVU* mVU = mVUx; - //if (!mVUdivFlag) { MOV32MtoR(reg, (uptr)&mVU->divFlag[readQ]); AND32ItoR(reg, 0xc00); } - //else if (mVUdivFlag & 1) { XOR32RtoR(reg, reg); } - //else { MOV32ItoR(reg, (u32)((mVUdivFlag << 9) & 0xc00)); } + MOV32RtoM((uptr)&mVU->clipFlag[fInstance], reg); } -microVUt(void) mVUallocDFLAGb(int reg) { - microVU* mVU = mVUx; - //MOV32RtoM((uptr)&mVU->divFlag[writeQ], reg); -} -*/ //------------------------------------------------------------------ // VI Reg Allocators //------------------------------------------------------------------ @@ -734,6 +721,12 @@ microVUt(void) mVUallocVIa(int GPRreg, int _reg_) { microVUt(void) mVUallocVIb(int GPRreg, int _reg_) { microVU* mVU = mVUx; + if (backupVI) { // Backs up reg to memory (used when VI is modified b4 a branch) + MOV32RtoM((uptr)&mVU->VIbackup[1], GPRreg); + mVUallocVIa(GPRreg, _reg_); + MOV32RtoM((uptr)&mVU->VIbackup[0], GPRreg); + MOV32MtoR(GPRreg, (uptr)&mVU->VIbackup[1]); + } if (_reg_ == 0) { return; } else if (_reg_ < 9) { MOVD32RtoMMX(mmVI(_reg_), GPRreg); } else { MOV16RtoM((uptr)&mVU->regs->VI[_reg_].UL, GPRreg); } @@ -755,7 +748,7 @@ microVUt(void) mVUallocVIb(int GPRreg, int _reg_) { #define getReg5(reg, _reg_, _fxf_) { \ if (!_reg_) { \ if (_fxf_ < 3) { SSE_XORPS_XMM_to_XMM(reg, reg); } \ - else { mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], 3); } \ + else { mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], 1); } \ } \ else { \ mVUloadReg(reg, (uptr)&mVU->regs->VF[_reg_].UL[0], (1 << (3 - _fxf_))); \ diff --git a/pcsx2/x86/microVU_Analyze.inl b/pcsx2/x86/microVU_Analyze.inl index f35299ab28..7a1992570f 100644 --- a/pcsx2/x86/microVU_Analyze.inl +++ b/pcsx2/x86/microVU_Analyze.inl @@ -51,6 +51,7 @@ microVUt(void) mVUanalyzeFMAC1(int Fd, int Fs, int Ft) { microVU* mVU = mVUx; + //mVUprint("microVU: FMAC1 Opcode"); mVUinfo |= _doStatus; analyzeReg1(Fs); analyzeReg1(Ft); @@ -63,6 +64,7 @@ microVUt(void) mVUanalyzeFMAC1(int Fd, int Fs, int Ft) { microVUt(void) mVUanalyzeFMAC2(int Fs, int Ft) { microVU* mVU = mVUx; + //mVUprint("microVU: FMAC2 Opcode"); analyzeReg1(Fs); analyzeReg2(Ft); } @@ -82,6 +84,7 @@ microVUt(void) mVUanalyzeFMAC2(int Fs, int Ft) { microVUt(void) mVUanalyzeFMAC3(int Fd, int Fs, int Ft) { microVU* mVU = mVUx; + //mVUprint("microVU: FMAC3 Opcode"); mVUinfo |= _doStatus; analyzeReg1(Fs); analyzeReg3(Ft); @@ -98,10 +101,57 @@ microVUt(void) mVUanalyzeFMAC3(int Fd, int Fs, int Ft) { microVUt(void) mVUanalyzeFMAC4(int Fs, int Ft) { microVU* mVU = mVUx; + mVUinfo |= doClip; analyzeReg1(Fs); analyzeReg4(Ft); } +//------------------------------------------------------------------ +// IALU - IALU Opcodes +//------------------------------------------------------------------ + +#define analyzeVIreg1(reg) { if (reg) { mVUstall = aMax(mVUstall, mVUregs.VI[reg]); } } +#define analyzeVIreg2(reg, aCycles) { if (reg) { mVUregsTemp.VIreg = reg; mVUregsTemp.VI = aCycles; mVUinfo |= _writesVI; mVU->VIbackup[0] = reg; } } + +microVUt(void) mVUanalyzeIALU1(int Id, int Is, int It) { + microVU* mVU = mVUx; + //mVUprint("microVU: IALU1 Opcode"); + if (!Id) { mVUinfo |= _isNOP; } + analyzeVIreg1(Is); + analyzeVIreg1(It); + analyzeVIreg2(Id, 1); +} + +microVUt(void) mVUanalyzeIALU2(int Is, int It) { + microVU* mVU = mVUx; + //mVUprint("microVU: IALU2 Opcode"); + if (!It) { mVUinfo |= _isNOP; } + analyzeVIreg1(Is); + analyzeVIreg2(It, 1); +} + +//------------------------------------------------------------------ +// MR32 - MR32 Opcode +//------------------------------------------------------------------ + +// Flips xyzw stalls to yzwx +#define analyzeReg6(reg) { \ + if (reg) { \ + if (_X) { mVUstall = aMax(mVUstall, aReg(reg).y); } \ + if (_Y) { mVUstall = aMax(mVUstall, aReg(reg).z); } \ + if (_Z) { mVUstall = aMax(mVUstall, aReg(reg).w); } \ + if (_W) { mVUstall = aMax(mVUstall, aReg(reg).x); } \ + } \ +} + +microVUt(void) mVUanalyzeMR32(int Fs, int Ft) { + microVU* mVU = mVUx; + mVUprint("microVU: MR32 Opcode"); + if (!Ft) { mVUinfo |= _isNOP; } + analyzeReg6(Fs); + analyzeReg2(Ft); +} + //------------------------------------------------------------------ // FDIV - DIV/SQRT/RSQRT Opcodes //------------------------------------------------------------------ @@ -122,6 +172,7 @@ microVUt(void) mVUanalyzeFMAC4(int Fs, int Ft) { microVUt(void) mVUanalyzeFDIV(int Fs, int Fsf, int Ft, int Ftf, u8 xCycles) { microVU* mVU = mVUx; + mVUprint("microVU: DIV Opcode"); analyzeReg5(Fs, Fsf); analyzeReg5(Ft, Ftf); analyzeQreg(xCycles); @@ -133,14 +184,166 @@ microVUt(void) mVUanalyzeFDIV(int Fs, int Fsf, int Ft, int Ftf, u8 xCycles) { microVUt(void) mVUanalyzeEFU1(int Fs, int Fsf, u8 xCycles) { microVU* mVU = mVUx; + mVUprint("microVU: EFU Opcode"); analyzeReg5(Fs, Fsf); analyzePreg(xCycles); } microVUt(void) mVUanalyzeEFU2(int Fs, u8 xCycles) { microVU* mVU = mVUx; + mVUprint("microVU: EFU Opcode"); analyzeReg1(Fs); analyzePreg(xCycles); } +//------------------------------------------------------------------ +// MFP - MFP Opcode +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeMFP(int Ft) { + microVU* mVU = mVUx; + mVUprint("microVU: MFP Opcode"); + if (!Ft) { mVUinfo |= _isNOP; } + analyzeReg2(Ft); +} + +//------------------------------------------------------------------ +// LQx - LQ/LQD/LQI Opcodes +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeLQ(int Ft, int Is, bool writeIs) { + microVU* mVU = mVUx; + //mVUprint("microVU: LQ Opcode"); + analyzeVIreg1(Is); + analyzeReg2(Ft); + if (!Ft) { mVUinfo |= (writeIs && Is) ? _noWriteVF : _isNOP; } + if (writeIs) { analyzeVIreg2(Is, 1); } +} + +//------------------------------------------------------------------ +// SQx - SQ/SQD/SQI Opcodes +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeSQ(int Fs, int It, bool writeIt) { + microVU* mVU = mVUx; + analyzeReg1(Fs); + analyzeVIreg1(It); + if (writeIt) { analyzeVIreg2(It, 1); } +} + +//------------------------------------------------------------------ +// R*** - R Reg Opcodes +//------------------------------------------------------------------ + +#define analyzeRreg() { mVUregsTemp.r = 1; } + +microVUt(void) mVUanalyzeR1(int Fs, int Fsf) { + microVU* mVU = mVUx; + mVUprint("microVU: R-reg Opcode"); + analyzeReg5(Fs, Fsf); + analyzeRreg(); +} + +microVUt(void) mVUanalyzeR2(int Ft, bool canBeNOP) { + microVU* mVU = mVUx; + mVUprint("microVU: R-reg Opcode"); + if (!Ft) { mVUinfo |= ((canBeNOP) ? _isNOP : _noWriteVF); } + analyzeReg2(Ft); + analyzeRreg(); +} + +//------------------------------------------------------------------ +// Sflag - Status Flag Opcodes +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeSflag(int It) { + microVU* mVU = mVUx; + mVUprint("microVU: Sflag Opcode"); + if (!It) { mVUinfo |= _isNOP; } + else { // Sets _isSflag at instruction that FSxxx opcode reads it's status flag from + mVUinfo |= _swapOps; + if (mVUcount < 4) { mVUregs.needExactMatch = 1; } + if (mVUcount >= 1) { incPC2(-2); mVUinfo |= _isSflag; incPC2(2); } + // Note: _isSflag is used for status flag optimizations. + // Do to stalls, it can only be set one instruction prior to the status flag read instruction + // if we were guaranteed no-stalls were to happen, it could be set 4 instruction prior. + } + analyzeVIreg2(It, 1); +} + +microVUt(void) mVUanalyzeFSSET() { + microVU* mVU = mVUx; + mVUinfo |= _isFSSET; + mVUprint("microVU: FSSET Opcode"); + // mVUinfo &= ~_doStatus; + // Note: I'm not entirely sure if the non-sticky flags + // should be taken from the current upper instruction + // or if they should be taken from the previous instruction + // Uncomment the above line if the latter-case is true +} + +//------------------------------------------------------------------ +// Mflag - Mac Flag Opcodes +//------------------------------------------------------------------ + +microVUt(void) mVUanalyzeMflag(int Is, int It) { + microVU* mVU = mVUx; + mVUprint("microVU: Mflag Opcode"); + if (!It) { mVUinfo |= _isNOP; } + else { // Need set _doMac for 4 previous Ops (need to do all 4 because stalls could change the result needed) + mVUinfo |= _swapOps; + if (mVUcount < 4) { mVUregs.needExactMatch = 1; } + int curPC = iPC; + for (int i = mVUcount, j = 0; i > 1; i--, j++) { + incPC2(-2); + if (doStatus) { mVUinfo |= _doMac; if (j >= 3) { break; } } + } + iPC = curPC; + } + analyzeVIreg1(Is); + analyzeVIreg2(It, 1); +} + +//------------------------------------------------------------------ +// XGkick +//------------------------------------------------------------------ + +#define analyzeXGkick1() { mVUstall = aMax(mVUstall, mVUregs.xgkick); } +#define analyzeXGkick2(x) { mVUregsTemp.xgkick = x; } + +microVUt(void) mVUanalyzeXGkick(int Fs, int xCycles) { + microVU* mVU = mVUx; + analyzeVIreg1(Fs); + analyzeXGkick1(); + analyzeXGkick2(xCycles); +} + +//------------------------------------------------------------------ +// Branches - Branch Opcodes +//------------------------------------------------------------------ + +#define analyzeBranchVI(reg, infoVal) { \ + if (reg && (mVUcount > 0)) { /* Ensures branch is not first opcode in block */ \ + incPC(-2); \ + if (writesVI && (reg == mVU->VIbackup[0])) { /* If prev Op modified VI reg */ \ + mVUinfo |= _backupVI; \ + incPC(2); \ + mVUinfo |= infoVal; \ + } \ + else { incPC(2); } \ + } \ +} + +microVUt(void) mVUanalyzeBranch1(int Is) { + microVU* mVU = mVUx; + if (mVUregs.VI[Is]) { analyzeVIreg1(Is); } + else { analyzeBranchVI(Is, _memReadIs); } +} + +microVUt(void) mVUanalyzeBranch2(int Is, int It) { + microVU* mVU = mVUx; + if (mVUregs.VI[Is] || mVUregs.VI[It]) { analyzeVIreg1(Is); analyzeVIreg1(It); } + else { analyzeBranchVI(Is, _memReadIs); analyzeBranchVI(It, _memReadIt);} +} + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index 49c517de5e..aa60df2037 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -19,94 +19,394 @@ #pragma once #ifdef PCSX2_MICROVU -#ifdef mVUdebug -#define mVUdebugStuff1() { \ - if (curI & _Ibit_) { SysPrintf("microVU: I-bit set!\n"); } \ - if (curI & _Ebit_) { SysPrintf("microVU: E-bit set!\n"); } \ - if (curI & _Mbit_) { SysPrintf("microVU: M-bit set!\n"); } \ - if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \ - if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ -} -#else -#define mVUdebugStuff1() {} -#endif +//------------------------------------------------------------------ +// Helper Macros +//------------------------------------------------------------------ -#define createBlock(blockEndPtr) { \ - block.pipelineState = pipelineState; \ - block.x86ptrStart = x86ptrStart; \ - block.x86ptrEnd = blockEndPtr; \ - /*block.x86ptrBranch;*/ \ - if (!(pipelineState & 1)) { \ - memcpy_fast(&block.pState, pState, sizeof(microRegInfo)); \ - } \ +#define branchCase(JMPcc, nJMPcc) \ + mVUsetupBranch(bStatus, bMac); \ + mVUprint("mVUcompile branchCase"); \ + CMP16ItoM((uptr)&mVU->branch, 0); \ + incPC2(1); \ + bBlock = mVUblocks[iPC/2]->search((microRegInfo*)&mVUregs); \ + incPC2(-1); \ + if (bBlock) { nJMPcc((uptr)pBlock->x86ptrStart - ((uptr)x86Ptr + 6)); } \ + else { ajmp = JMPcc((uptr)0); } \ + break + +#define flagSetMacro(xFlag, pFlag, xF, yF, zF) { \ + yF += (mVUstall > 3) ? 3 : mVUstall; \ + if (yF > zF) { \ + pFlag += (yF-zF); \ + if (pFlag >= xFlag) pFlag = (xFlag-1); \ + zF++; \ + xF = (yF-zF); \ + zF = yF; \ + yF -= xF; \ + } \ + yF++; \ } -#define curI mVUcurProg.data[iPC] -#define setCode() { mVU->code = curI; } -#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } -#define startLoop() { mVUdebugStuff1(); mVUstall = 0; memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); } +#define startLoop() { mVUdebug1(); mVUstall = 0; memset(&mVUregsTemp, 0, sizeof(mVUregsTemp)); } +#define calcCycles(reg, x) { reg = ((reg > x) ? (reg - x) : 0); } +#define incP() { mVU->p = (mVU->p+1) & 1; } +#define incQ() { mVU->q = (mVU->q+1) & 1; } +#define doUpperOp() { mVUopU(); mVUdivSet(); } + +//------------------------------------------------------------------ +// Helper Functions +//------------------------------------------------------------------ + +// Optimizes out unneeded status flag updates +microVUt(void) mVUstatusFlagOp() { + microVU* mVU = mVUx; + int curPC = iPC; + int i = mVUcount; + bool runLoop = 1; + if (doStatus) { mVUinfo |= _isSflag; } + else { + for (; i > 0; i--) { + incPC2(-2); + if (isSflag) { runLoop = 0; break; } + if (doStatus) { mVUinfo |= _isSflag; break; } + } + } + if (runLoop) { + for (; i > 0; i--) { + incPC2(-2); + if (isSflag) break; + mVUinfo &= ~_doStatus; + } + } + iPC = curPC; +} + +// Note: Flag handling is 'very' complex, it requires full knowledge of how microVU recs work, so don't touch! +microVUt(void) mVUsetFlags(int* bStatus, int* bMac) { + microVU* mVU = mVUx; + + // Ensure last ~4+ instructions update mac flags + int endPC = iPC; + u32 aCount = 1; // Amount of instructions needed to get 4 valid status/mac flag instances + for (int i = mVUcount, iX = 0; i > 0; i--, aCount++) { + if (doStatus) { mVUinfo |= _doMac; iX++; if ((iX >= 4) || (aCount > 4)) { break; } } + incPC2(-2); + } + + // Status/Mac Flags Setup Code + int xStatus = 8, xMac = 8; // Flag Instances start at #0 on every block ((8&3) == 0) + int pStatus = 3, pMac = 3; + int xClip = mVUregs.clip + 8, pClip = mVUregs.clip + 7; // Clip Instance starts from where it left off + int xS = 0, yS = 1, zS = 0; + int xM = 0, yM = 1, zM = 0; + int xC = 0, yC = 1, zC = 0; + u32 xCount = mVUcount; // Backup count + iPC = mVUstartPC; + for (mVUcount = 0; mVUcount < xCount; mVUcount++) { + if (((xCount - mVUcount) > aCount) && isFSSET) mVUstatusFlagOp(); // Don't Optimize out on the last ~4+ instructions + + flagSetMacro(xStatus, pStatus, xS, yS, zS); // Handles _fvsinstances + flagSetMacro(xMac, pMac, xM, yM, zM); // Handles _fvminstances + flagSetMacro(xClip, pClip, xC, yC, zC); // Handles _fvcinstances + + mVUinfo |= (xStatus&3) << 12; // _fsInstance + mVUinfo |= (xMac&3) << 10; // _fmInstance + mVUinfo |= (xClip&3) << 14; // _fcInstance + + mVUinfo |= (pStatus&3) << 18; // _fvsInstance + mVUinfo |= (pMac&3) << 16; // _fvmInstance + mVUinfo |= (pClip&3) << 20; // _fvcInstance + + if (doStatus||isFSSET||doDivFlag) { xStatus = (xStatus+1); } + if (doMac) { xMac = (xMac+1); } + if (doClip) { xClip = (xClip+1); } + incPC2(2); + } + mVUcount = xCount; // Restore count + mVUregs.clip = xClip&3; // Note: Clip timing isn't cycle-accurate between block linking; but hopefully doesn't matter + + // Setup Last 4 instances of Status/Mac flags (needed for accurate block linking) + iPC = endPC; + for (int i = 3, j = 3, ii = 1, jj = 1; aCount > 0; ii++, jj++, aCount--) { + if ((doStatus||isFSSET||doDivFlag) && (i >= 0)) { + for (; (ii > 0 && i >= 0); i--, ii--) { xStatus = (xStatus-1) & 3; bStatus[i] = xStatus; } + } + if (doMac && (j >= 0)) { + for (; (jj > 0 && j >= 0); j--, jj--) { xMac = (xMac-1) & 3; bMac[j] = xMac; } + } + incPC2(-2); + } +} + +#define getFlagReg1(x) ((x == 3) ? gprF3 : ((x == 2) ? gprF2 : ((x == 1) ? gprF1 : gprF0))) +#define getFlagReg2(x) ((x == bStatus[3]) ? gprESP : ((x == bStatus[2]) ? gprR : ((x == bStatus[1]) ? gprT2 : gprT1))) + +// Recompiles Code for Proper Flags and Q/P regs on Block Linkings +microVUt(void) mVUsetupBranch(int* bStatus, int* bMac) { + microVU* mVU = mVUx; + mVUprint("mVUsetupBranch"); + + PUSH32R(gprR); // Backup gprR + MOV32RtoM((uptr)&mVU->espBackup, gprESP); + + MOV32RtoR(gprT1, getFlagReg1(bStatus[0])); + MOV32RtoR(gprT2, getFlagReg1(bStatus[1])); + MOV32RtoR(gprR, getFlagReg1(bStatus[2])); + MOV32RtoR(gprESP, getFlagReg1(bStatus[3])); + + MOV32RtoR(gprF0, gprT1); + MOV32RtoR(gprF1, gprT2); + MOV32RtoR(gprF2, gprR); + MOV32RtoR(gprF3, gprESP); + + AND32ItoR(gprT1, 0xffff0000); + AND32ItoR(gprT2, 0xffff0000); + AND32ItoR(gprR, 0xffff0000); + AND32ItoR(gprESP, 0xffff0000); + + AND32ItoR(gprF0, 0x0000ffff); + AND32ItoR(gprF1, 0x0000ffff); + AND32ItoR(gprF2, 0x0000ffff); + AND32ItoR(gprF3, 0x0000ffff); + + OR32RtoR(gprF0, getFlagReg2(bMac[0])); + OR32RtoR(gprF1, getFlagReg2(bMac[1])); + OR32RtoR(gprF2, getFlagReg2(bMac[2])); + OR32RtoR(gprF3, getFlagReg2(bMac[3])); + + MOV32MtoR(gprESP, (uptr)&mVU->espBackup); + POP32R(gprR); // Restore gprR + + // Shuffle P/Q regs since every block starts at instance #0 + if (mVU->p || mVU->q) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, shufflePQ); } +} + +microVUt(void) mVUincCycles(int x) { + microVU* mVU = mVUx; + mVUcycles += x; + for (int z = 31; z > 0; z--) { + calcCycles(mVUregs.VF[z].x, x); + calcCycles(mVUregs.VF[z].y, x); + calcCycles(mVUregs.VF[z].z, x); + calcCycles(mVUregs.VF[z].w, x); + } + for (int z = 16; z > 0; z--) { + calcCycles(mVUregs.VI[z], x); + } + if (mVUregs.q) { + if (mVUregs.q > 4) { calcCycles(mVUregs.q, x); if (mVUregs.q <= 4) { mVUinfo |= _doDivFlag; } } + else { calcCycles(mVUregs.q, x); } + if (!mVUregs.q) { incQ(); } + } + if (mVUregs.p) { + calcCycles(mVUregs.p, x); + if (!mVUregs.p) { incP(); } + } + calcCycles(mVUregs.r, x); + calcCycles(mVUregs.xgkick, x); +} microVUt(void) mVUsetCycles() { microVU* mVU = mVUx; incCycles(mVUstall); + if (mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1] && mVUregsTemp.VFreg[0]) { // If upper Op && lower Op write to same VF reg + mVUinfo |= (mVUregsTemp.r || mVUregsTemp.VI) ? _noWriteVF : _isNOP; // If lower Op doesn't modify anything else, then make it a NOP + mVUregsTemp.VF[1].x = aMax(mVUregsTemp.VF[0].x, mVUregsTemp.VF[1].x); // Use max cycles from each vector + mVUregsTemp.VF[1].y = aMax(mVUregsTemp.VF[0].y, mVUregsTemp.VF[1].y); + mVUregsTemp.VF[1].z = aMax(mVUregsTemp.VF[0].z, mVUregsTemp.VF[1].z); + mVUregsTemp.VF[1].w = aMax(mVUregsTemp.VF[0].w, mVUregsTemp.VF[1].w); + } mVUregs.VF[mVUregsTemp.VFreg[0]].reg = mVUregsTemp.VF[0].reg; - mVUregs.VF[mVUregsTemp.VFreg[1]].reg =(mVUregsTemp.VFreg[0] == mVUregsTemp.VFreg[1]) ? (aMax(mVUregsTemp.VF[0].reg, mVUregsTemp.VF[1].reg)) : (mVUregsTemp.VF[1].reg); + mVUregs.VF[mVUregsTemp.VFreg[1]].reg = mVUregsTemp.VF[1].reg; mVUregs.VI[mVUregsTemp.VIreg] = mVUregsTemp.VI; mVUregs.q = mVUregsTemp.q; mVUregs.p = mVUregsTemp.p; + mVUregs.r = mVUregsTemp.r; + mVUregs.xgkick = mVUregsTemp.xgkick; } -microVUx(void) mVUcompile(u32 startPC, u32 pipelineState, microRegInfo* pState, u8* x86ptrStart) { +microVUt(void) mVUdivSet() { microVU* mVU = mVUx; - microBlock block; - int branch; - iPC = startPC / 4; + int flagReg1, flagReg2; + if (doDivFlag) { + getFlagReg(flagReg1, fsInstance); + if (!doStatus) { getFlagReg(flagReg2, fpsInstance); MOV16RtoR(flagReg1, flagReg2); } + MOV32RtoR(gprT1, flagReg1); + AND32ItoR(gprT1, 0xffff0fcf); + OR32MtoR (gprT1, (uptr)&mVU->divFlag); + MOV32RtoR(flagReg1, gprT1); + } +} + +microVUt(void) mVUendProgram() { + microVU* mVU = mVUx; + incCycles(100); // Ensures Valid P/Q instances (And sets all cycle data to 0) + mVUcycles -= 100; + if (mVU->q) { SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, 0xe5); } + SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_Q].UL, xmmPQ); + SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, mVU->p ? 3 : 2); + SSE_MOVSS_XMM_to_M32((uptr)&mVU->regs->VI[REG_P].UL, xmmPQ); + + //memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); + //MOV32ItoM((uptr)&mVU->prog.lpState, (int)&mVUblock.pState); // Save pipeline state (clipflag instance) + AND32ItoM((uptr)µVU0.regs->VI[REG_VPU_STAT].UL, (vuIndex ? ~0x100 : ~0x001)); // VBS0/VBS1 flag + AND32ItoM((uptr)&mVU->regs->vifRegs->stat, ~0x4); // Clear VU 'is busy' signal for vif + MOV32ItoM((uptr)&mVU->regs->VI[REG_TPC].UL, xPC); + JMP32((uptr)mVU->exitFunct - ((uptr)x86Ptr + 5)); +} + +microVUt(void) mVUtestCycles() { + microVU* mVU = mVUx; + iPC = mVUstartPC; + CMP32ItoM((uptr)&mVU->cycles, 0); + u8* jmp8 = JG8(0); + mVUendProgram(); + x86SetJ8(jmp8); + SUB32ItoM((uptr)&mVU->cycles, mVUcycles); +} +//------------------------------------------------------------------ +// Recompiler +//------------------------------------------------------------------ + +microVUt(void*) __fastcall mVUcompile(u32 startPC, uptr pState) { + microVU* mVU = mVUx; + u8* thisPtr = x86Ptr; + + if (startPC > ((vuIndex) ? 0x3fff : 0xfff)) { mVUprint("microVU: invalid startPC"); } + startPC &= (vuIndex ? 0x3ff8 : 0xff8); // Searches for Existing Compiled Block (if found, then returns; else, compile) - microBlock* pblock = mVUblock[iPC]->search(pipelineState, pState); - if (block) { x86SetPtr(pblock->x86ptrEnd); return; } - + microBlock* pBlock = mVUblocks[startPC/8]->search((microRegInfo*)pState); + if (pBlock) { return pBlock->x86ptrStart; } + // First Pass + iPC = startPC / 4; setCode(); - branch = 0; - mVUbranch = 0; - mVUcycles = 1; // Skips "M" phase, and starts counting cycles at "T" stage - for (;;) { + mVUbranch = 0; + mVUstartPC = iPC; + mVUcount = 0; + mVUcycles = 0; // Skips "M" phase, and starts counting cycles at "T" stage + mVU->p = 0; // All blocks start at p index #0 + mVU->q = 0; // All blocks start at q index #0 + memcpy_fast(&mVUregs, (microRegInfo*)pState, sizeof(microRegInfo)); // Loads up Pipeline State Info + mVUblock.x86ptrStart = thisPtr; + pBlock = mVUblocks[startPC/8]->add(&mVUblock); // Add this block to block manager + + for (int branch = 0;; ) { + incPC(1); + mVUinfo = 0; + incCycles(1); startLoop(); mVUopU(); if (curI & _Ebit_) { branch = 1; } if (curI & _MDTbit_) { branch = 2; } - if (curI & _Ibit_) { incPC(1); mVUinfo |= _isNOP; } - else { incPC(1); mVUopL(); } + if (curI & _Ibit_) { mVUinfo |= _isNOP; } + else { incPC(-1); mVUopL(); incPC(1); } mVUsetCycles(); + if (mVU->p) { mVUinfo |= _readP; } + if (mVU->q) { mVUinfo |= _readQ; } + else { mVUinfo |= _writeQ; } if (branch >= 2) { mVUinfo |= _isEOB | ((branch == 3) ? _isBdelay : 0); if (mVUbranch) { Console::Error("microVU Warning: Branch in E-bit/Branch delay slot!"); mVUinfo |= _isNOP; } break; } else if (branch == 1) { branch = 2; } if (mVUbranch) { branch = 3; mVUbranch = 0; mVUinfo |= _isBranch; } incPC(1); + mVUcount++; } + // Sets Up Flag instances + int bStatus[4]; int bMac[4]; + mVUsetFlags(bStatus, bMac); + mVUtestCycles(); + // Second Pass - iPC = startPC; + iPC = mVUstartPC; setCode(); - for (bool x = 1; x; ) { - if (isEOB) { x = 0; } - else if (isBranch) { mVUopU(); incPC(2); } + mVUbranch = 0; + int x; + for (x = 0; x < (vuIndex ? (0x3fff/8) : (0xfff/8)); x++) { + if (isEOB) { x = 0xffff; } + if (isNOP) { incPC(1); doUpperOp(); if (curI & _Ibit_) { incPC(-1); MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, curI); incPC(1); } } + else if (!swapOps) { incPC(1); doUpperOp(); incPC(-1); mVUopL(); incPC(1); } + else { mVUopL(); incPC(1); doUpperOp(); } - mVUopU(); - if (isNop) { if (curI & _Ibit_) { incPC(1); mVU->iReg = curI; } else { incPC(1); } } - else { incPC(1); mVUopL(); } if (!isBdelay) { incPC(1); } - else { - incPC(-2); // Go back to Branch Opcode - mVUopL(); // Run Branch Opcode + else { + microBlock* bBlock = NULL; + u32* ajmp = 0; switch (mVUbranch) { - case 1: break; - case 2: break; - case 3: break; + case 3: branchCase(JZ32, JNZ32); // IBEQ + case 4: branchCase(JGE32, JNGE32); // IBGEZ + case 5: branchCase(JG32, JNG32); // IBGTZ + case 6: branchCase(JLE32, JNLE32); // IBLEQ + case 7: branchCase(JL32, JNL32); // IBLTZ + case 8: branchCase(JNZ32, JZ32); // IBNEQ + case 1: case 2: // B/BAL + + mVUprint("mVUcompile B/BAL"); + incPC(-3); // Go back to branch opcode (to get branch imm addr) + mVUsetupBranch(bStatus, bMac); + + // Check if branch-block has already been compiled + pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); + if (pBlock) { JMP32((uptr)pBlock->x86ptrStart - ((uptr)x86Ptr + 5)); } + else if (!vuIndex) { mVUcompileVU0(branchAddr, (uptr)&mVUregs); } + else { mVUcompileVU1(branchAddr, (uptr)&mVUregs); } + return thisPtr; + case 9: case 10: // JR/JALR + + mVUprint("mVUcompile JR/JALR"); + memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); + mVUsetupBranch(bStatus, bMac); + + PUSH32R(gprR); // Backup EDX + MOV32MtoR(gprT2, (uptr)&mVU->branch); // Get startPC (ECX first argument for __fastcall) + //AND32ItoR(gprT2, (vuIndex)?0x3ff8:0xff8); // Ensure valid jump address + MOV32ItoR(gprR, (u32)&pBlock->pStateEnd); // Get pState (EDX second argument for __fastcall) + + if (!vuIndex) CALLFunc((uptr)mVUcompileVU0); //(u32 startPC, uptr pState) + else CALLFunc((uptr)mVUcompileVU1); + POP32R(gprR); // Restore EDX + JMPR(gprT1); // Jump to rec-code address + return thisPtr; } - break; + // Conditional Branches + mVUprint("mVUcompile conditional branch"); + if (bBlock) { // Branch non-taken has already been compiled + incPC(-3); // Go back to branch opcode (to get branch imm addr) + // Check if branch-block has already been compiled + pBlock = mVUblocks[branchAddr/8]->search((microRegInfo*)&mVUregs); + if (pBlock) { JMP32((uptr)pBlock->x86ptrStart - ((uptr)x86Ptr + 5)); } + else if (!vuIndex) { mVUcompileVU0(branchAddr, (uptr)&mVUregs); } + else { mVUcompileVU1(branchAddr, (uptr)&mVUregs); } + } + else { + uptr jumpAddr; + u32 bPC = iPC; // mVUcompile can modify iPC and mVUregs, so back them up + memcpy_fast(&pBlock->pStateEnd, &mVUregs, sizeof(microRegInfo)); + + incPC2(1); // Get PC for branch not-taken + if (!vuIndex) mVUcompileVU0(xPC, (uptr)&mVUregs); + else mVUcompileVU1(xPC, (uptr)&mVUregs); + + iPC = bPC; + incPC(-3); // Go back to branch opcode (to get branch imm addr) + if (!vuIndex) jumpAddr = (uptr)mVUcompileVU0(branchAddr, (uptr)&pBlock->pStateEnd); + else jumpAddr = (uptr)mVUcompileVU1(branchAddr, (uptr)&pBlock->pStateEnd); + *ajmp = (jumpAddr - ((uptr)ajmp + 4)); + } + return thisPtr; } } + mVUprint("mVUcompile ebit"); + if (x == (vuIndex?(0x3fff/8):(0xfff/8))) { mVUprint("microVU: Possible infinite compiling loop!"); } + + // Do E-bit end stuff here + mVUendProgram(); + + return thisPtr; //ToDo: Save pipeline state? } +void* __fastcall mVUcompileVU0(u32 startPC, uptr pState) { return mVUcompile<0>(startPC, pState); } +void* __fastcall mVUcompileVU1(u32 startPC, uptr pState) { return mVUcompile<1>(startPC, pState); } + #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Execute.inl b/pcsx2/x86/microVU_Execute.inl new file mode 100644 index 0000000000..ff892ab0ca --- /dev/null +++ b/pcsx2/x86/microVU_Execute.inl @@ -0,0 +1,162 @@ +/* Pcsx2 - Pc Ps2 Emulator +* Copyright (C) 2009 Pcsx2-Playground 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 +#ifdef PCSX2_MICROVU + +//------------------------------------------------------------------ +// Dispatcher Functions +//------------------------------------------------------------------ + +void testFunction() { mVUprint("microVU: Entered Execution Mode"); } + +// Generates the code for entering recompiled blocks +microVUt(void) mVUdispatcherA() { + static u32 PCSX2_ALIGNED16(vuMXCSR); + microVU* mVU = mVUx; + mVU->startFunct = x86Ptr; + + // __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left. + if (!vuIndex) { CALLFunc((uptr)mVUexecuteVU0); } + else { CALLFunc((uptr)mVUexecuteVU1); } + + // Backup cpu state + PUSH32R(EBX); + PUSH32R(EBP); + PUSH32R(ESI); + PUSH32R(EDI); + + // Load VU's MXCSR state + vuMXCSR = g_sseVUMXCSR; + SSE_LDMXCSR((uptr)&vuMXCSR); + + // Load Regs + MOV32MtoR(gprR, (uptr)&mVU->regs->VI[REG_R].UL); + MOV32MtoR(gprF0, (uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL); + MOV32MtoR(gprF1, (uptr)&mVU->regs->VI[REG_MAC_FLAG].UL); + SHL32ItoR(gprF0, 16); + AND32ItoR(gprF1, 0xffff); + OR32RtoR (gprF0, gprF1); + MOV32RtoR(gprF1, gprF0); + MOV32RtoR(gprF2, gprF0); + MOV32RtoR(gprF3, gprF0); + + for (int i = 0; i < 8; i++) { + MOVQMtoR(i, (uptr)&mVU->regs->VI[i+1].UL); + } + + SSE_MOVAPS_M128_to_XMM(xmmACC, (uptr)&mVU->regs->ACC.UL[0]); + SSE_MOVAPS_M128_to_XMM(xmmMax, (uptr)mVU_maxvals); + SSE_MOVAPS_M128_to_XMM(xmmMin, (uptr)mVU_minvals); + SSE_MOVAPS_M128_to_XMM(xmmT1, (uptr)&mVU->regs->VI[REG_P].UL); + SSE_MOVAPS_M128_to_XMM(xmmPQ, (uptr)&mVU->regs->VI[REG_Q].UL); + SSE_SHUFPS_XMM_to_XMM(xmmPQ, xmmT1, 0); // wzyx = PPQQ + + //PUSH32R(EAX); + //CALLFunc((uptr)testFunction); + //POP32R(EAX); + //write8(0xcc); + + // Jump to Recompiled Code Block + JMPR(EAX); +} + +// Generates the code to exit from recompiled blocks +microVUt(void) mVUdispatcherB() { + static u32 PCSX2_ALIGNED16(eeMXCSR); + microVU* mVU = mVUx; + mVU->exitFunct = x86Ptr; + + // __fastcall = The first two DWORD or smaller arguments are passed in ECX and EDX registers; all other arguments are passed right to left. + if (!vuIndex) { CALLFunc((uptr)mVUcleanUpVU0); } + else { CALLFunc((uptr)mVUcleanUpVU1); } + + // Load EE's MXCSR state + eeMXCSR = g_sseMXCSR; + SSE_LDMXCSR((uptr)&eeMXCSR); + + // Save Regs + MOV32RtoR(gprT1, gprF0); // ToDo: Ensure Correct Flag instances + AND32ItoR(gprT1, 0xffff); + SHR32ItoR(gprF0, 16); + MOV32RtoM((uptr)&mVU->regs->VI[REG_R].UL, gprR); + MOV32RtoM((uptr)&mVU->regs->VI[REG_STATUS_FLAG].UL, gprT1); + MOV32RtoM((uptr)&mVU->regs->VI[REG_MAC_FLAG].UL, gprF0); + + for (int i = 0; i < 8; i++) { + MOVDMMXtoM((uptr)&mVU->regs->VI[i+1].UL, i); + } + + SSE_MOVAPS_XMM_to_M128((uptr)&mVU->regs->ACC.UL[0], xmmACC); + + // Restore cpu state + POP32R(EDI); + POP32R(ESI); + POP32R(EBP); + POP32R(EBX); + + //write8(0xcc); + + EMMS(); + RET(); + + mVUcacheCheck(x86Ptr, mVU->cache, 512); +} + +//------------------------------------------------------------------ +// Execution Functions +//------------------------------------------------------------------ + +// Executes for number of cycles +microVUt(void*) __fastcall mVUexecute(u32 startPC, u32 cycles) { + + microVU* mVU = mVUx; + //mVUprint("microVU%x: startPC = 0x%x, cycles = 0x%x", params vuIndex, startPC, cycles); + + mVUsearchProg(); // Find and set correct program + mVU->cycles = cycles; + mVU->totalCycles = cycles; + + x86SetPtr(mVUcurProg.x86ptr); // Set x86ptr to where program left off + if (!vuIndex) return mVUcompileVU0(startPC, (uptr)&mVU->prog.lpState); + else return mVUcompileVU1(startPC, (uptr)&mVU->prog.lpState); +} + +//------------------------------------------------------------------ +// Cleanup Functions +//------------------------------------------------------------------ + +microVUt(void) mVUcleanUp() { + microVU* mVU = mVUx; + //mVUprint("microVU: Program exited successfully!"); + mVUcurProg.x86ptr = x86Ptr; + mVUcacheCheck(x86Ptr, mVUcurProg.x86start, (uptr)(mVUcurProg.x86end - mVUcurProg.x86start)); +} + +//------------------------------------------------------------------ +// Caller Functions +//------------------------------------------------------------------ + +void __fastcall startVU0(u32 startPC, u32 cycles) { ((mVUrecCall)microVU0.startFunct)(startPC, cycles); } +void __fastcall startVU1(u32 startPC, u32 cycles) { ((mVUrecCall)microVU1.startFunct)(startPC, cycles); } +void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles) { return mVUexecute<0>(startPC, cycles); } +void* __fastcall mVUexecuteVU1(u32 startPC, u32 cycles) { return mVUexecute<1>(startPC, cycles); } +void __fastcall mVUcleanUpVU0() { mVUcleanUp<0>(); } +void __fastcall mVUcleanUpVU1() { mVUcleanUp<1>(); } + +#endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Log.inl b/pcsx2/x86/microVU_Log.inl new file mode 100644 index 0000000000..4aaf139880 --- /dev/null +++ b/pcsx2/x86/microVU_Log.inl @@ -0,0 +1,94 @@ +/* Pcsx2 - Pc Ps2 Emulator +* Copyright (C) 2009 Pcsx2-Playground 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 +#ifdef PCSX2_MICROVU + +microVUt(void) __mVUsetupLog() { + if (!vuIndex) { if (!mVUlogFile[0]) mVUlogFile[0] = fopen(LOGS_DIR "\\microVU0.txt", "w"); } + else { if (!mVUlogFile[1]) mVUlogFile[1] = fopen(LOGS_DIR "\\microVU1.txt", "w"); } +} + +// writes text directly to the microVU.txt, no newlines appended. +microVUx(void) __mVULog(const char* fmt, ...) { + char tmp[2024]; + va_list list; + + va_start(list, fmt); + + // concatenate the log message after the prefix: + int length = vsprintf(tmp, fmt, list); + va_end(list); + + if (mVUlogFile[vuIndex]) { + fputs(tmp, mVUlogFile[vuIndex]); + //fputs("\n", mVUlogFile[vuIndex]); + fflush(mVUlogFile[vuIndex]); + } +} + +#define commaIf() { if (bitX[6]) { mVUlog(","); bitX[6] = 0; } } + +microVUt(void) __mVUdumpProgram(int progIndex) { + microVU* mVU = mVUx; + bool bitX[7]; + //mVU->prog.cur = progIndex; // Needed in order to set iPC + mVUlog("*********************\n", progIndex); + mVUlog("* Micro-Program #%02d *\n", progIndex); + mVUlog("*********************\n\n", progIndex); + for (u32 i = 0; i < mVU->progSize; i+=2) { + + mVU->code = mVU->prog.prog[progIndex].data[i+1]; + mVUlog("[%04x] (%08x) ", i*4, mVU->code); + + bitX[0] = 0; + bitX[1] = 0; + bitX[2] = 0; + bitX[3] = 0; + bitX[4] = 0; + bitX[5] = 0; + bitX[6] = 0; + + if (mVU->code & _Ibit_) {bitX[0] = 1; bitX[5] = 1;} + if (mVU->code & _Ebit_) {bitX[1] = 1; bitX[5] = 1;} + if (mVU->code & _Mbit_) {bitX[2] = 1; bitX[5] = 1;} + if (mVU->code & _Dbit_) {bitX[3] = 1; bitX[5] = 1;} + if (mVU->code & _Tbit_) {bitX[4] = 1; bitX[5] = 1;} + + iPC = (i+1)/4; + mVUopU(); + + if (bitX[5]) { + mVUlog(" ("); + if (bitX[0]) { mVUlog("I"); bitX[6] = 1; } + if (bitX[1]) { commaIf(); mVUlog("E"); bitX[6] = 1; } + if (bitX[2]) { commaIf(); mVUlog("M"); bitX[6] = 1; } + if (bitX[3]) { commaIf(); mVUlog("D"); bitX[6] = 1; } + if (bitX[4]) { commaIf(); mVUlog("T"); } + mVUlog(")"); + } + + iPC = i/4; + mVU->code = mVU->prog.prog[progIndex].data[i]; + mVUlog("\n[%04x] (%08x) ", i*4, mVU->code); + mVUopL(); + mVUlog("\n\n"); + } +} + +#endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Lower.inl b/pcsx2/x86/microVU_Lower.inl index 8e7859e033..2522ef83a0 100644 --- a/pcsx2/x86/microVU_Lower.inl +++ b/pcsx2/x86/microVU_Lower.inl @@ -23,6 +23,10 @@ // Micro VU Micromode Lower instructions //------------------------------------------------------------------ +//------------------------------------------------------------------ +// DIV/SQRT/RSQRT +//------------------------------------------------------------------ + #define testZero(xmmReg, xmmTemp, gprTemp) { \ SSE_XORPS_XMM_to_XMM(xmmTemp, xmmTemp); /* Clear xmmTemp (make it 0) */ \ SSE_CMPEQPS_XMM_to_XMM(xmmTemp, xmmReg); /* Set all F's if zero */ \ @@ -41,8 +45,8 @@ microVUf(void) mVU_DIV() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFDIV(_Fs_, _Fsf_, _Ft_, _Ftf_, 7); } - else { + pass1 { mVUanalyzeFDIV(_Fs_, _Fsf_, _Ft_, _Ftf_, 7); } + pass2 { u8 *ajmp, *bjmp, *cjmp, *djmp; getReg5(xmmFs, _Fs_, _Fsf_); getReg5(xmmFt, _Ft_, _Ftf_); @@ -72,12 +76,13 @@ microVUf(void) mVU_DIV() { mVUunpack_xyzw(xmmFs, xmmFs, 0); mVUmergeRegs(xmmPQ, xmmFs, writeQ ? 4 : 8); } + pass3 { mVUlog("DIV"); } } microVUf(void) mVU_SQRT() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFDIV(0, 0, _Ft_, _Ftf_, 7); } - else { + pass1 { mVUanalyzeFDIV(0, 0, _Ft_, _Ftf_, 7); } + pass2 { u8 *ajmp; getReg5(xmmFt, _Ft_, _Ftf_); @@ -89,12 +94,13 @@ microVUf(void) mVU_SQRT() { mVUunpack_xyzw(xmmFt, xmmFt, 0); mVUmergeRegs(xmmPQ, xmmFt, writeQ ? 4 : 8); } + pass3 { mVUlog("SQRT"); } } microVUf(void) mVU_RSQRT() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFDIV(_Fs_, _Fsf_, _Ft_, _Ftf_, 13); } - else { + pass1 { mVUanalyzeFDIV(_Fs_, _Fsf_, _Ft_, _Ftf_, 13); } + pass2 { u8 *ajmp, *bjmp, *cjmp, *djmp; getReg5(xmmFs, _Fs_, _Fsf_); getReg5(xmmFt, _Ft_, _Ftf_); @@ -126,8 +132,13 @@ microVUf(void) mVU_RSQRT() { mVUunpack_xyzw(xmmFs, xmmFs, 0); mVUmergeRegs(xmmPQ, xmmFs, writeQ ? 4 : 8); } + pass3 { mVUlog("RSQRT"); } } +//------------------------------------------------------------------ +// EATAN/EEXP/ELENG/ERCPR/ERLENG/ERSADD/ERSQRT/ESADD/ESIN/ESQRT/ESUM +//------------------------------------------------------------------ + #define EATANhelper(addr) { \ SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ SSE_MULSS_XMM_to_XMM(xmmT1, xmmFs); \ @@ -158,8 +169,8 @@ microVUt(void) mVU_EATAN_() { microVUf(void) mVU_EATAN() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU1(_Fs_, _Fsf_, 54); } - else { + pass1 { mVUanalyzeEFU1(_Fs_, _Fsf_, 54); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance @@ -170,12 +181,13 @@ microVUf(void) mVU_EATAN() { mVU_EATAN_(); } + pass3 { mVUlog("EATAN"); } } microVUf(void) mVU_EATANxy() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 54); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 54); } + pass2 { getReg6(xmmFt, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmFs, xmmFt, 0x01); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance @@ -187,12 +199,13 @@ microVUf(void) mVU_EATANxy() { mVU_EATAN_(); } + pass3 { mVUlog("EATANxy"); } } microVUf(void) mVU_EATANxz() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 54); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 54); } + pass2 { getReg6(xmmFt, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmFs, xmmFt, 0x02); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance @@ -204,6 +217,7 @@ microVUf(void) mVU_EATANxz() { mVU_EATAN_(); } + pass3 { mVUlog("EATANxz"); } } #define eexpHelper(addr) { \ @@ -215,8 +229,8 @@ microVUf(void) mVU_EATANxz() { microVUf(void) mVU_EEXP() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU1(_Fs_, _Fsf_, 44); } - else { + pass1 { mVUanalyzeEFU1(_Fs_, _Fsf_, 44); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); @@ -243,6 +257,7 @@ microVUf(void) mVU_EEXP() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmT1); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("EEXP"); } } microVUt(void) mVU_sumXYZ() { @@ -263,20 +278,21 @@ microVUt(void) mVU_sumXYZ() { microVUf(void) mVU_ELENG() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 18); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 18); } + pass2 { getReg6(xmmFs, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance mVU_sumXYZ(); SSE_SQRTSS_XMM_to_XMM(xmmPQ, xmmPQ); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ELENG"); } } microVUf(void) mVU_ERCPR() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU1(_Fs_, _Fsf_, 12); } - else { + pass1 { mVUanalyzeEFU1(_Fs_, _Fsf_, 12); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); @@ -285,12 +301,13 @@ microVUf(void) mVU_ERCPR() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ERCPR"); } } microVUf(void) mVU_ERLENG() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 24); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 24); } + pass2 { getReg6(xmmFs, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance mVU_sumXYZ(); @@ -300,12 +317,13 @@ microVUf(void) mVU_ERLENG() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ERLENG"); } } microVUf(void) mVU_ERSADD() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 18); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 18); } + pass2 { getReg6(xmmFs, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance mVU_sumXYZ(); @@ -315,12 +333,13 @@ microVUf(void) mVU_ERSADD() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ERSADD"); } } microVUf(void) mVU_ERSQRT() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU1(_Fs_, _Fsf_, 18); } - else { + pass1 { mVUanalyzeEFU1(_Fs_, _Fsf_, 18); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE_SQRTSS_XMM_to_XMM(xmmPQ, xmmFs); @@ -329,17 +348,19 @@ microVUf(void) mVU_ERSQRT() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ERSQRT"); } } microVUf(void) mVU_ESADD() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 11); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 11); } + pass2 { getReg6(xmmFs, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance mVU_sumXYZ(); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ESADD"); } } #define esinHelper(addr) { \ @@ -351,8 +372,8 @@ microVUf(void) mVU_ESADD() { microVUf(void) mVU_ESIN() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 29); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 29); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); @@ -373,23 +394,25 @@ microVUf(void) mVU_ESIN() { SSE_ADDSS_XMM_to_XMM(xmmPQ, xmmT1); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ESIN"); } } microVUf(void) mVU_ESQRT() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU1(_Fs_, _Fsf_, 12); } - else { + pass1 { mVUanalyzeEFU1(_Fs_, _Fsf_, 12); } + pass2 { getReg5(xmmFs, _Fs_, _Fsf_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE_SQRTSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ESQRT"); } } microVUf(void) mVU_ESUM() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeEFU2(_Fs_, 12); } - else { + pass1 { mVUanalyzeEFU2(_Fs_, 12); } + pass2 { getReg6(xmmFs, _Fs_); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip xmmPQ to get Valid P instance SSE2_PSHUFD_XMM_to_XMM(xmmFt, xmmFs, 0x1b); @@ -399,78 +422,89 @@ microVUf(void) mVU_ESUM() { SSE_MOVSS_XMM_to_XMM(xmmPQ, xmmFs); SSE2_PSHUFD_XMM_to_XMM(xmmPQ, xmmPQ, writeP ? 0x27 : 0xC6); // Flip back } + pass3 { mVUlog("ESUM"); } } +//------------------------------------------------------------------ +// FCAND/FCEQ/FCGET/FCOR/FCSET +//------------------------------------------------------------------ + microVUf(void) mVU_FCAND() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass2 { mVUallocCFLAGa(gprT1, fvcInstance); AND32ItoR(gprT1, _Imm24_); ADD32ItoR(gprT1, 0xffffff); SHR32ItoR(gprT1, 24); mVUallocVIb(gprT1, 1); } + pass3 { mVUlog("FCAND"); } } microVUf(void) mVU_FCEQ() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass2 { mVUallocCFLAGa(gprT1, fvcInstance); XOR32ItoR(gprT1, _Imm24_); SUB32ItoR(gprT1, 1); SHR32ItoR(gprT1, 31); mVUallocVIb(gprT1, 1); } + pass3 { mVUlog("FCEQ"); } } microVUf(void) mVU_FCGET() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass2 { mVUallocCFLAGa(gprT1, fvcInstance); AND32ItoR(gprT1, 0xfff); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FCGET"); } } microVUf(void) mVU_FCOR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass2 { mVUallocCFLAGa(gprT1, fvcInstance); OR32ItoR(gprT1, _Imm24_); ADD32ItoR(gprT1, 1); // If 24 1's will make 25th bit 1, else 0 SHR32ItoR(gprT1, 24); // Get the 25th bit (also clears the rest of the garbage in the reg) mVUallocVIb(gprT1, 1); } + pass3 { mVUlog("FCOR"); } } microVUf(void) mVU_FCSET() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUinfo |= doClip; } + pass2 { MOV32ItoR(gprT1, _Imm24_); mVUallocCFLAGb(gprT1, fcInstance); } + pass3 { mVUlog("FCSET"); } } +//------------------------------------------------------------------ +// FMAND/FMEQ/FMOR +//------------------------------------------------------------------ + microVUf(void) mVU_FMAND() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeMflag(_Fs_, _Ft_); } + pass2 { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); AND16RtoR(gprT1, gprT2); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FMAND"); } } microVUf(void) mVU_FMEQ() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeMflag(_Fs_, _Ft_); } + pass2 { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); XOR32RtoR(gprT1, gprT2); @@ -478,68 +512,81 @@ microVUf(void) mVU_FMEQ() { SHR32ItoR(gprT1, 31); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FMEQ"); } } microVUf(void) mVU_FMOR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeMflag(_Fs_, _Ft_); } + pass2 { mVUallocMFLAGa(gprT1, fvmInstance); mVUallocVIa(gprT2, _Fs_); OR16RtoR(gprT1, gprT2); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FMOR"); } } +//------------------------------------------------------------------ +// FSAND/FSEQ/FSOR/FSSET +//------------------------------------------------------------------ + microVUf(void) mVU_FSAND() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSflag(_Ft_); } + pass2 { mVUallocSFLAGa(gprT1, fvsInstance); AND16ItoR(gprT1, _Imm12_); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FSAND"); } } microVUf(void) mVU_FSEQ() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSflag(_Ft_); } + pass2 { mVUallocSFLAGa(gprT1, fvsInstance); XOR16ItoR(gprT1, _Imm12_); SUB16ItoR(gprT1, 1); SHR16ItoR(gprT1, 15); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FSEQ"); } } microVUf(void) mVU_FSOR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSflag(_Ft_); } + pass2 { mVUallocSFLAGa(gprT1, fvsInstance); OR16ItoR(gprT1, _Imm12_); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("FSOR"); } } microVUf(void) mVU_FSSET() { microVU* mVU = mVUx; - if (!recPass) {} - else { - int flagReg; - getFlagReg(flagReg, fsInstance); - MOV16ItoR(gprT1, (_Imm12_ & 0xfc0)); - //if (_Imm12_ & 0xc00) { mVUdivFlag = _Imm12_ >> 9; } - //else { mVUdivFlag = 1; } - //mVUdivFlagT = 4; + pass1 { mVUanalyzeFSSET(); } + pass2 { + int flagReg1, flagReg2; + getFlagReg(flagReg1, fsInstance); + if (!(doStatus||doDivFlag)) { getFlagReg(flagReg2, fpsInstance); MOV16RtoR(flagReg1, flagReg2); } // Get status result from last status setting instruction + AND16ItoR(flagReg1, 0x03f); // Remember not to modify upper 16 bits because of mac flag + OR16ItoR (flagReg1, (_Imm12_ & 0xfc0)); } + pass3 { mVUlog("FSSET"); } } +//------------------------------------------------------------------ +// IADD/IADDI/IADDIU/IAND/IOR/ISUB/ISUBIU +//------------------------------------------------------------------ + microVUf(void) mVU_IADD() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU1(_Fd_, _Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); if (_Ft_ != _Fs_) { mVUallocVIa(gprT2, _Ft_); @@ -548,32 +595,35 @@ microVUf(void) mVU_IADD() { else ADD16RtoR(gprT1, gprT1); mVUallocVIb(gprT1, _Fd_); } + pass3 { mVUlog("IADD"); } } microVUf(void) mVU_IADDI() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU2(_Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); ADD16ItoR(gprT1, _Imm5_); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("IADDI"); } } microVUf(void) mVU_IADDIU() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU2(_Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); - ADD16ItoR(gprT1, _Imm12_); + ADD16ItoR(gprT1, _Imm15_); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("IADDIU"); } } microVUf(void) mVU_IAND() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU1(_Fd_, _Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); if (_Ft_ != _Fs_) { mVUallocVIa(gprT2, _Ft_); @@ -581,12 +631,13 @@ microVUf(void) mVU_IAND() { } mVUallocVIb(gprT1, _Fd_); } + pass3 { mVUlog("IAND"); } } microVUf(void) mVU_IOR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU1(_Fd_, _Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); if (_Ft_ != _Fs_) { mVUallocVIa(gprT2, _Ft_); @@ -594,16 +645,18 @@ microVUf(void) mVU_IOR() { } mVUallocVIb(gprT1, _Fd_); } + pass3 { mVUlog("IOR"); } } microVUf(void) mVU_ISUB() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU1(_Fd_, _Fs_, _Ft_); } + pass2 { if (_Ft_ != _Fs_) { mVUallocVIa(gprT1, _Fs_); mVUallocVIa(gprT2, _Ft_); SUB16RtoR(gprT1, gprT2); + mVUallocVIb(gprT1, _Fd_); } else if (!isMMX(_Fd_)) { XOR32RtoR(gprT1, gprT1); @@ -611,108 +664,129 @@ microVUf(void) mVU_ISUB() { } else { PXORRtoR(mmVI(_Fd_), mmVI(_Fd_)); } } + pass3 { mVUlog("ISUB"); } } microVUf(void) mVU_ISUBIU() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeIALU2(_Fs_, _Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); - SUB16ItoR(gprT1, _Imm12_); + SUB16ItoR(gprT1, _Imm15_); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("ISUBIU"); } } -microVUf(void) mVU_MOVE() { - microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_ || (_Ft_ == _Fs_)) nop();*/ } - else { - mVUloadReg(xmmT1, (uptr)&mVU->regs->VF[_Fs_].UL[0], _X_Y_Z_W); - mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); - } -} +//------------------------------------------------------------------ +// MFIR/MFP/MOVE/MR32/MTIR +//------------------------------------------------------------------ microVUf(void) mVU_MFIR() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeVIreg1(_Fs_); analyzeReg2(_Ft_); } + pass2 { mVUallocVIa(gprT1, _Fs_); MOVSX32R16toR(gprT1, gprT1); SSE2_MOVD_R_to_XMM(xmmT1, gprT1); if (!_XYZW_SS) { mVUunpack_xyzw(xmmT1, xmmT1, 0); } - mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } + pass3 { mVUlog("MFIR"); } } microVUf(void) mVU_MFP() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { mVUanalyzeMFP(_Ft_); } + pass2 { getPreg(xmmFt); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } + pass3 { mVUlog("MFP"); } } -microVUf(void) mVU_MTIR() { +microVUf(void) mVU_MOVE() { microVU* mVU = mVUx; - if (!recPass) {} - else { - MOVZX32M16toR(gprT1, (uptr)&mVU->regs->VF[_Fs_].UL[_Fsf_]); - mVUallocVIb(gprT1, _Ft_); + pass1 { if (!_Ft_ || (_Ft_ == _Fs_)) { mVUinfo |= _isNOP; } analyzeReg1(_Fs_); analyzeReg2(_Ft_); } + pass2 { + mVUloadReg(xmmT1, (uptr)&mVU->regs->VF[_Fs_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } + pass3 { mVUlog("MOVE"); } } microVUf(void) mVU_MR32() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { mVUanalyzeMR32(_Fs_, _Ft_); } + pass2 { mVUloadReg(xmmT1, (uptr)&mVU->regs->VF[_Fs_].UL[0], (_X_Y_Z_W == 8) ? 4 : 15); if (_X_Y_Z_W != 8) { SSE2_PSHUFD_XMM_to_XMM(xmmT1, xmmT1, 0x39); } - mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmT1, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 0); } + pass3 { mVUlog("MR32"); } } +microVUf(void) mVU_MTIR() { + microVU* mVU = mVUx; + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeReg5(_Fs_, _Fsf_); analyzeVIreg2(_Ft_, 1); } + pass2 { + MOVZX32M16toR(gprT1, (uptr)&mVU->regs->VF[_Fs_].UL[_Fsf_]); + mVUallocVIb(gprT1, _Ft_); + } + pass3 { mVUlog("MTIR"); } +} + +//------------------------------------------------------------------ +// ILW/ILWR +//------------------------------------------------------------------ + microVUf(void) mVU_ILW() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeVIreg1(_Fs_); analyzeVIreg2(_Ft_, 4); } + pass2 { if (!_Fs_) { - MOVZX32M16toR( gprT1, (uptr)mVU->regs->Mem + getVUmem(_Imm11_) + offsetSS ); + MOVZX32M16toR(gprT1, (uptr)mVU->regs->Mem + getVUmem(_Imm11_) + offsetSS); mVUallocVIb(gprT1, _Ft_); } else { mVUallocVIa(gprT1, _Fs_); ADD32ItoR(gprT1, _Imm11_); mVUaddrFix(gprT1); - MOV32RmSOffsettoR(gprT1, gprT1, (uptr)mVU->regs->Mem + offsetSS, 0); // ToDo: check if this works. + MOV32RmtoR(gprT1, gprT1, (uptr)mVU->regs->Mem + offsetSS); if (isMMX(_Ft_)) AND32ItoR(gprT1, 0xffff); mVUallocVIb(gprT1, _Ft_); } } + pass3 { mVUlog("ILW"); } } microVUf(void) mVU_ILWR() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeVIreg1(_Fs_); analyzeVIreg2(_Ft_, 4); } + pass2 { if (!_Fs_) { - MOVZX32M16toR( gprT1, (uptr)mVU->regs->Mem + offsetSS ); + MOVZX32M16toR(gprT1, (uptr)mVU->regs->Mem + offsetSS); mVUallocVIb(gprT1, _Ft_); } else { mVUallocVIa(gprT1, _Fs_); mVUaddrFix(gprT1); - MOV32RmSOffsettoR(gprT1, gprT1, (uptr)mVU->regs->Mem + offsetSS, 0); // ToDo: check if this works. + MOV32RmtoR(gprT1, gprT1, (uptr)mVU->regs->Mem + offsetSS); if (isMMX(_Ft_)) AND32ItoR(gprT1, 0xffff); mVUallocVIb(gprT1, _Ft_); } } + pass3 { mVUlog("ILWR"); } } +//------------------------------------------------------------------ +// ISW/ISWR +//------------------------------------------------------------------ + microVUf(void) mVU_ISW() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { analyzeVIreg1(_Fs_); analyzeVIreg1(_Ft_); } + pass2 { if (!_Fs_) { int imm = getVUmem(_Imm11_); mVUallocVIa(gprT1, _Ft_); @@ -726,18 +800,19 @@ microVUf(void) mVU_ISW() { mVUallocVIa(gprT2, _Ft_); ADD32ItoR(gprT1, _Imm11_); mVUaddrFix(gprT1); - if (_X) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem); - if (_Y) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+4); - if (_Z) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+8); - if (_W) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+12); + if (_X) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem); + if (_Y) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+4); + if (_Z) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+8); + if (_W) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+12); } } + pass3 { mVUlog("ISW"); } } microVUf(void) mVU_ISWR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { analyzeVIreg1(_Fs_); analyzeVIreg1(_Ft_); } + pass2 { if (!_Fs_) { mVUallocVIa(gprT1, _Ft_); if (_X) MOV32RtoM((uptr)mVU->regs->Mem, gprT1); @@ -749,82 +824,94 @@ microVUf(void) mVU_ISWR() { mVUallocVIa(gprT1, _Fs_); mVUallocVIa(gprT2, _Ft_); mVUaddrFix(gprT1); - if (_X) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem); - if (_Y) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+4); - if (_Z) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+8); - if (_W) MOV32RtoRmOffset(gprT1, gprT2, (uptr)mVU->regs->Mem+12); + if (_X) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem); + if (_Y) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+4); + if (_Z) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+8); + if (_W) MOV32RtoRm(gprT1, gprT2, (uptr)mVU->regs->Mem+12); } } + pass3 { mVUlog("ISWR"); } } +//------------------------------------------------------------------ +// LQ/LQD/LQI +//------------------------------------------------------------------ + microVUf(void) mVU_LQ() { microVU* mVU = mVUx; - if (!recPass) { /*If (!_Ft_) nop();*/ } - else { + pass1 { mVUanalyzeLQ(_Ft_, _Fs_, 0); } + pass2 { if (!_Fs_) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem + getVUmem(_Imm11_), _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } else { mVUallocVIa(gprT1, _Fs_); ADD32ItoR(gprT1, _Imm11_); mVUaddrFix(gprT1); mVUloadReg2(xmmFt, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } } + pass3 { mVUlog("LQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Ft_, _Fs_, _Imm11_); } } microVUf(void) mVU_LQD() { microVU* mVU = mVUx; - if (!recPass) {} - else { - if (!_Fs_ && _Ft_) { + pass1 { mVUanalyzeLQ(_Ft_, _Fs_, 1); } + pass2 { + if (!_Fs_ && !noWriteVF) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem, _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } else { mVUallocVIa(gprT1, _Fs_); SUB16ItoR(gprT1, 1); - mVUallocVIb(gprT1, _Fs_); // ToDo: Backup to memory check. - if (_Ft_) { + mVUallocVIb(gprT1, _Fs_); + if (!noWriteVF) { mVUaddrFix(gprT1); mVUloadReg2(xmmFt, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } } } + pass3 { mVUlog("LQD.%s vf%02d, --vi%02d", _XYZW_String, _Ft_, _Fs_); } } microVUf(void) mVU_LQI() { microVU* mVU = mVUx; - if (!recPass) {} - else { - if (!_Fs_ && _Ft_) { + pass1 { mVUanalyzeLQ(_Ft_, _Fs_, 1); } + pass2 { + if (!_Fs_ && !noWriteVF) { mVUloadReg(xmmFt, (uptr)mVU->regs->Mem, _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } else { - mVUallocVIa((_Ft_) ? gprT1 : gprT2, _Fs_); - if (_Ft_) { + mVUallocVIa((!noWriteVF) ? gprT1 : gprT2, _Fs_); + if (!noWriteVF) { MOV32RtoR(gprT2, gprT1); mVUaddrFix(gprT1); mVUloadReg2(xmmFt, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); - mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W); + mVUsaveReg(xmmFt, (uptr)&mVU->regs->VF[_Ft_].UL[0], _X_Y_Z_W, 1); } ADD16ItoR(gprT2, 1); - mVUallocVIb(gprT2, _Fs_); // ToDo: Backup to memory check. + mVUallocVIb(gprT2, _Fs_); } } + pass3 { mVUlog("LQI.%s vf%02d, vi%02d++", _XYZW_String, _Ft_, _Fs_); } } +//------------------------------------------------------------------ +// SQ/SQD/SQI +//------------------------------------------------------------------ + microVUf(void) mVU_SQ() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSQ(_Fs_, _Ft_, 0); } + pass2 { if (!_Ft_) { getReg7(xmmFs, _Fs_); - mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem + getVUmem(_Imm11_), _X_Y_Z_W); + mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem + getVUmem(_Imm11_), _X_Y_Z_W, 1); } else { mVUallocVIa(gprT1, _Ft_); @@ -834,34 +921,36 @@ microVUf(void) mVU_SQ() { mVUsaveReg2(xmmFs, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); } } + pass3 { mVUlog("SQ.%s vf%02d, vi%02d + %d", _XYZW_String, _Fs_, _Ft_, _Imm11_); } } microVUf(void) mVU_SQD() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSQ(_Fs_, _Ft_, 1); } + pass2 { if (!_Ft_) { getReg7(xmmFs, _Fs_); - mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem, _X_Y_Z_W); + mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem, _X_Y_Z_W, 1); } else { mVUallocVIa(gprT1, _Ft_); SUB16ItoR(gprT1, 1); - mVUallocVIb(gprT1, _Ft_); // ToDo: Backup to memory check. + mVUallocVIb(gprT1, _Ft_); mVUaddrFix(gprT1); getReg7(xmmFs, _Fs_); mVUsaveReg2(xmmFs, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); } } + pass3 { mVUlog("SQD.%s vf%02d, --vi%02d", _XYZW_String, _Fs_, _Ft_); } } microVUf(void) mVU_SQI() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeSQ(_Fs_, _Ft_, 1); } + pass2 { if (!_Ft_) { getReg7(xmmFs, _Fs_); - mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem, _X_Y_Z_W); + mVUsaveReg(xmmFs, (uptr)mVU->regs->Mem, _X_Y_Z_W, 1); } else { mVUallocVIa(gprT1, _Ft_); @@ -870,15 +959,20 @@ microVUf(void) mVU_SQI() { getReg7(xmmFs, _Fs_); mVUsaveReg2(xmmFs, gprT1, (uptr)mVU->regs->Mem, _X_Y_Z_W); ADD16ItoR(gprT2, 1); - mVUallocVIb(gprT2, _Ft_); // ToDo: Backup to memory check. + mVUallocVIb(gprT2, _Ft_); } } + pass3 { mVUlog("SQI.%s vf%02d, vi%02d++", _XYZW_String, _Fs_, _Ft_); } } +//------------------------------------------------------------------ +// RINIT/RGET/RNEXT/RXOR +//------------------------------------------------------------------ + microVUf(void) mVU_RINIT() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeR1(_Fs_, _Fsf_); } + pass2 { if (_Fs_ || (_Fsf_ == 3)) { getReg8(gprR, _Fs_, _Fsf_); AND32ItoR(gprR, 0x007fffff); @@ -886,11 +980,12 @@ microVUf(void) mVU_RINIT() { } else MOV32ItoR(gprR, 0x3f800000); } + pass3 { mVUlog("RINIT R, vf%02d%s", _Fs_, _Fsf_String); } } microVUt(void) mVU_RGET_() { microVU* mVU = mVUx; - if (_Ft_) { + if (!noWriteVF) { if (_X) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[0], gprR); if (_Y) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[1], gprR); if (_Z) MOV32RtoM((uptr)&mVU->regs->VF[_Ft_].UL[2], gprR); @@ -900,14 +995,15 @@ microVUt(void) mVU_RGET_() { microVUf(void) mVU_RGET() { microVU* mVU = mVUx; - if (!recPass) { /*if (!_Ft_) nop();*/ } - else { mVU_RGET_(); } + pass1 { mVUanalyzeR2(_Ft_, 1); } + pass2 { mVU_RGET_(); } + pass3 { mVUlog("RGET.%s vf%02d, R", _XYZW_String, _Ft_); } } microVUf(void) mVU_RNEXT() { microVU* mVU = mVUx; - if (!recPass) { /*if (!_Ft_) nop();*/ } - else { + pass1 { mVUanalyzeR2(_Ft_, 0); } + pass2 { // algorithm from www.project-fao.org MOV32RtoR(gprT1, gprR); SHR32ItoR(gprT1, 4); @@ -924,118 +1020,199 @@ microVUf(void) mVU_RNEXT() { OR32ItoR (gprR, 0x3f800000); mVU_RGET_(); } + pass3 { mVUlog("RNEXT.%s vf%02d, R", _XYZW_String, _Ft_); } } microVUf(void) mVU_RXOR() { microVU* mVU = mVUx; - if (!recPass) {} - else { + pass1 { mVUanalyzeR1(_Fs_, _Fsf_); } + pass2 { if (_Fs_ || (_Fsf_ == 3)) { getReg8(gprT1, _Fs_, _Fsf_); AND32ItoR(gprT1, 0x7fffff); XOR32RtoR(gprR, gprT1); } } + pass3 { mVUlog("RXOR R, vf%02d%s", _Fs_, _Fsf_String); } } +//------------------------------------------------------------------ +// WaitP/WaitQ +//------------------------------------------------------------------ + microVUf(void) mVU_WAITP() { microVU* mVU = mVUx; - if (!recPass) {} - else {} + pass1 { mVUstall = aMax(mVUstall, ((mVUregs.p) ? (mVUregs.p - 1) : 0)); } + pass3 { mVUlog("WAITP"); } } microVUf(void) mVU_WAITQ() { microVU* mVU = mVUx; - if (!recPass) {} - else {} + pass1 { mVUstall = aMax(mVUstall, mVUregs.q); } + pass3 { mVUlog("WAITQ"); } } +//------------------------------------------------------------------ +// XTOP/XITOP +//------------------------------------------------------------------ + microVUf(void) mVU_XTOP() { microVU* mVU = mVUx; - if (!recPass) {} - else { - MOVZX32M16toR( gprT1, (uptr)&mVU->regs->vifRegs->top); + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeVIreg2(_Ft_, 1); } + pass2 { + MOVZX32M16toR(gprT1, (uptr)&mVU->regs->vifRegs->top); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("XTOP vi%02d", _Ft_); } } microVUf(void) mVU_XITOP() { microVU* mVU = mVUx; - if (!recPass) {} - else { - MOVZX32M16toR( gprT1, (uptr)&mVU->regs->vifRegs->itop ); + pass1 { if (!_Ft_) { mVUinfo |= _isNOP; } analyzeVIreg2(_Ft_, 1); } + pass2 { + MOVZX32M16toR(gprT1, (uptr)&mVU->regs->vifRegs->itop); mVUallocVIb(gprT1, _Ft_); } -} - -microVUt(void) __fastcall mVU_XGKICK_(u32 addr) { - microVU* mVU = mVUx; - u32 *data = (u32*)(mVU->regs->Mem + (addr&0x3fff)); - u32 size = mtgsThread->PrepDataPacket( GIF_PATH_1, data, (0x4000-(addr&0x3fff)) >> 4); - u8 *pDest = mtgsThread->GetDataPacketPtr(); - memcpy_aligned(pDest, mVU->regs->Mem + addr, size<<4); - mtgsThread->SendDataPacket(); -} -void __fastcall mVU_XGKICK0(u32 addr) { mVU_XGKICK_<0>(addr); } -void __fastcall mVU_XGKICK1(u32 addr) { mVU_XGKICK_<1>(addr); } - -microVUf(void) mVU_XGKICK() { - microVU* mVU = mVUx; - if (!recPass) {} - else { - mVUallocVIa(gprT2, _Fs_); // gprT2 = ECX for __fastcall - if (!vuIndex) CALLFunc((uptr)mVU_XGKICK0); - else CALLFunc((uptr)mVU_XGKICK1); - } + pass3 { mVUlog("XITOP vi%02d", _Ft_); } } //------------------------------------------------------------------ -// Branches +// XGkick +//------------------------------------------------------------------ + +void __fastcall mVU_XGKICK_(u32 addr) { + u32 *data = (u32*)(microVU1.regs->Mem + (addr&0x3fff)); + u32 size = mtgsThread->PrepDataPacket( GIF_PATH_1, data, (0x4000-(addr&0x3fff)) >> 4); + u8 *pDest = mtgsThread->GetDataPacketPtr(); + memcpy_aligned(pDest, microVU1.regs->Mem + addr, size<<4); + mtgsThread->SendDataPacket(); +} + +microVUf(void) mVU_XGKICK() { + microVU* mVU = mVUx; + pass1 { mVUanalyzeXGkick(_Fs_, 4); } + pass2 { + mVUprint("XGkick"); + mVUallocVIa(gprT2, _Fs_); // gprT2 = ECX for __fastcall + PUSH32R(gprR); // gprR = EDX is volatile so backup + CALLFunc((uptr)mVU_XGKICK_); + POP32R(gprR); // Restore + } + pass3 { mVUlog("XGKICK vi%02d", _Fs_); } +} + +//------------------------------------------------------------------ +// Branches/Jumps //------------------------------------------------------------------ microVUf(void) mVU_B() { microVU* mVU = mVUx; - mVUbranch = 1; + mVUbranch = 1; + pass3 { mVUlog("B [%04x]", branchAddr); } } microVUf(void) mVU_BAL() { microVU* mVU = mVUx; - mVUbranch = 1; - if (recPass) { - MOV32ItoR(gprT1, (xPC + (2 * 8)) & 0xffff); + mVUbranch = 2; + pass1 { analyzeVIreg2(_Ft_, 1); } + pass2 { + MOV32ItoR(gprT1, bSaveAddr); mVUallocVIb(gprT1, _Ft_); } + pass3 { mVUlog("BAL vi%02d [%04x]", _Ft_, branchAddr); } } microVUf(void) mVU_IBEQ() { microVU* mVU = mVUx; - mVUbranch = 2; + mVUbranch = 3; + pass1 { mVUanalyzeBranch2(_Fs_, _Ft_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + if (memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else { mVUallocVIa(gprT2, _Ft_); XOR32RtoR(gprT1, gprT2); } + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBEQ vi%02d, vi%02d [%04x]", _Ft_, _Fs_, branchAddr); } } microVUf(void) mVU_IBGEZ() { microVU* mVU = mVUx; - mVUbranch = 2; + mVUbranch = 4; + pass1 { mVUanalyzeBranch1(_Fs_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBGEZ vi%02d [%04x]", _Fs_, branchAddr); } } microVUf(void) mVU_IBGTZ() { microVU* mVU = mVUx; - mVUbranch = 2; -} -microVUf(void) mVU_IBLTZ() { - microVU* mVU = mVUx; - mVUbranch = 2; + mVUbranch = 5; + pass1 { mVUanalyzeBranch1(_Fs_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBGTZ vi%02d [%04x]", _Fs_, branchAddr); } } microVUf(void) mVU_IBLEZ() { microVU* mVU = mVUx; - mVUbranch = 2; + mVUbranch = 6; + pass1 { mVUanalyzeBranch1(_Fs_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBLEZ vi%02d [%04x]", _Fs_, branchAddr); } +} +microVUf(void) mVU_IBLTZ() { + microVU* mVU = mVUx; + mVUbranch = 7; + pass1 { mVUanalyzeBranch1(_Fs_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBLTZ vi%02d [%04x]", _Fs_, branchAddr); } } microVUf(void) mVU_IBNE() { microVU* mVU = mVUx; - mVUbranch = 2; + mVUbranch = 8; + pass1 { mVUanalyzeBranch2(_Fs_, _Ft_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + if (memReadIt) XOR32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else { mVUallocVIa(gprT2, _Ft_); XOR32RtoR(gprT1, gprT2); } + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("IBNE vi%02d, vi%02d [%04x]", _Ft_, _Fs_, branchAddr); } } microVUf(void) mVU_JR() { microVU* mVU = mVUx; - mVUbranch = 3; + mVUbranch = 9; + pass1 { mVUanalyzeBranch1(_Fs_); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + } + pass3 { mVUlog("JR [vi%02d]", _Fs_); } } microVUf(void) mVU_JALR() { microVU* mVU = mVUx; - mVUbranch = 3; + mVUbranch = 10; + pass1 { mVUanalyzeBranch1(_Fs_); analyzeVIreg2(_Ft_, 1); } + pass2 { + if (memReadIs) MOV32MtoR(gprT1, (uptr)&mVU->VIbackup[0]); + else mVUallocVIa(gprT1, _Fs_); + MOV32RtoM((uptr)&mVU->branch, gprT1); + MOV32ItoR(gprT1, bSaveAddr); + mVUallocVIb(gprT1, _Ft_); + } + pass3 { mVUlog("JALR vi%02d, [vi%02d]", _Ft_, _Fs_); } } #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index ce9272f201..fb2eb21fec 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -66,9 +66,9 @@ declareAllVariables //------------------------------------------------------------------ // Helper Macros //------------------------------------------------------------------ -#define _Ft_ ((mVU->code >> 16) & 0x1F) // The rt part of the instruction register -#define _Fs_ ((mVU->code >> 11) & 0x1F) // The rd part of the instruction register -#define _Fd_ ((mVU->code >> 6) & 0x1F) // The sa part of the instruction register +#define _Ft_ ((mVU->code >> 16) & 0x1F) // The ft/it part of the instruction register +#define _Fs_ ((mVU->code >> 11) & 0x1F) // The fs/is part of the instruction register +#define _Fd_ ((mVU->code >> 6) & 0x1F) // The fd/id part of the instruction register #define _X ((mVU->code>>24) & 0x1) #define _Y ((mVU->code>>23) & 0x1) @@ -89,8 +89,8 @@ declareAllVariables #define _Ftf_ ((mVU->code >> 23) & 0x03) #define _Imm5_ (((mVU->code & 0x400) ? 0xfff0 : 0) | ((mVU->code >> 6) & 0xf)) -#define _Imm11_ (s32)(mVU->code & 0x400 ? 0xfffffc00 | (mVU->code & 0x3ff) : mVU->code & 0x3ff) -#define _Imm12_ (((mVU->code >> 21 ) & 0x1) << 11) | (mVU->code & 0x7ff) +#define _Imm11_ (s32)((mVU->code & 0x400) ? (0xfffffc00 | (mVU->code & 0x3ff)) : mVU->code & 0x3ff) +#define _Imm12_ (((mVU->code >> 21) & 0x1) << 11) | (mVU->code & 0x7ff) #define _Imm15_ (((mVU->code >> 10) & 0x7800) | (mVU->code & 0x7ff)) #define _Imm24_ (u32)(mVU->code & 0xffffff) @@ -138,25 +138,43 @@ declareAllVariables #define microVUf(aType) template aType #define microVUq(aType) template __forceinline aType +#define pass1 if (recPass == 0) +#define pass2 if (recPass == 1) +#define pass3 if (recPass == 2) + #define mVUcurProg mVU->prog.prog[mVU->prog.cur] -#define mVUblock mVU->prog.prog[mVU->prog.cur].block +#define mVUblocks mVU->prog.prog[mVU->prog.cur].block #define mVUallocInfo mVU->prog.prog[mVU->prog.cur].allocInfo #define mVUbranch mVUallocInfo.branch #define mVUcycles mVUallocInfo.cycles -#define mVUstall mVUallocInfo.maxStall -#define mVUdivFlag mVUallocInfo.divFlag -#define mVUdivFlagT mVUallocInfo.divFlagTimer -#define mVUregs mVUallocInfo.regs +#define mVUcount mVUallocInfo.count +#define mVUblock mVUallocInfo.block +#define mVUregs mVUallocInfo.block.pState #define mVUregsTemp mVUallocInfo.regsTemp -#define mVUinfo mVUallocInfo.info[mVUallocInfo.curPC / 2] #define iPC mVUallocInfo.curPC +#define mVUinfo mVUallocInfo.info[iPC / 2] +#define mVUstall mVUallocInfo.stall[iPC / 2] +#define mVUstartPC mVUallocInfo.startPC #define xPC ((iPC / 2) * 8) -#define incCycles(x) { mVUcycles += x; } +#define curI mVUcurProg.data[iPC] +#define setCode() { mVU->code = curI; } +#define incPC(x) { iPC = ((iPC + x) & (mVU->progSize-1)); setCode(); } +#define incPC2(x) { iPC = ((iPC + x) & (mVU->progSize-1)); } +#define incCycles(x) { mVUincCycles(x); } +#define bSaveAddr ((xPC + (2 * 8)) & ((vuIndex) ? 0x3ff8:0xff8)) +#define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & ((vuIndex) ? 0x3ff8:0xff8)) +#define shufflePQ (((mVU->q) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) +#define _Fsf_String ((_Fsf_ == 3) ? "w" : ((_Fsf_ == 2) ? "z" : ((_Fsf_ == 1) ? "y" : "x"))) +#define _Ftf_String ((_Ftf_ == 3) ? "w" : ((_Ftf_ == 2) ? "z" : ((_Ftf_ == 1) ? "y" : "x"))) +#define xyzwStr(x,s) (_X_Y_Z_W == x) ? s : +#define _XYZW_String (xyzwStr(1, "w") (xyzwStr(2, "z") (xyzwStr(3, "zw") (xyzwStr(4, "y") (xyzwStr(5, "yw") (xyzwStr(6, "yz") (xyzwStr(7, "yzw") (xyzwStr(8, "x") (xyzwStr(9, "xw") (xyzwStr(10, "xz") (xyzwStr(11, "xzw") (xyzwStr(12, "xy") (xyzwStr(13, "xyw") (xyzwStr(14, "xyz") "xyzw")))))))))))))) + #define _isNOP (1<<0) // Skip Lower Instruction #define _isBranch (1<<1) // Cur Instruction is a Branch #define _isEOB (1<<2) // End of Block #define _isBdelay (1<<3) // Cur Instruction in Branch Delay slot +#define _isSflag (1<<4) // Cur Instruction uses status flag #define _writeQ (1<<5) #define _readQ (1<<6) #define _writeP (1<<7) @@ -164,19 +182,29 @@ declareAllVariables #define _doFlags (3<<8) #define _doMac (1<<8) #define _doStatus (1<<9) -#define _fmInstance (3<<10) -#define _fsInstance (3<<12) -#define _fcInstance (3<<14) -#define _fpmInstance (3<<10) -#define _fpsInstance (3<<12) -#define _fvmInstance (3<<16) -#define _fvsInstance (3<<18) -#define _fvcInstance (3<<14) +#define _fmInstance (3<<10) // Mac Write Instance +#define _fsInstance (3<<12) // Status Write Instance +#define _fcInstance (3<<14) // Clip Write Instance +#define _fpsInstance (3<<12) // Prev.S. Write Instance +#define _fpcInstance (3<<14) // Prev.C. Write Instance +#define _fvmInstance (3<<16) // Mac Read Instance (at T-stage for lower instruction) +#define _fvsInstance (3<<18) // Status Read Instance (at T-stage for lower instruction) +#define _fvcInstance (3<<20) // Clip Read Instance (at T-stage for lower instruction) +#define _noWriteVF (1<<21) // Don't write back the result of a lower op to VF reg if upper op writes to same reg (or if VF = 0) +#define _backupVI (1<<22) // Backup VI reg to memory if modified before branch (branch uses old VI value unless opcode is ILW or ILWR) +#define _memReadIs (1<<23) // Read Is (VI reg) from memory (used by branches) +#define _memReadIt (1<<24) // Read If (VI reg) from memory (used by branches) +#define _writesVI (1<<25) // Current Instruction writes to VI +#define _swapOps (1<<26) // Runs Lower Instruction Before Upper Instruction +#define _isFSSET (1<<27) // Cur Instruction is FSSET +#define _doDivFlag (1<<28) // Transfer Div flag to Status Flag +#define _doClip (1<<29) #define isNOP (mVUinfo & (1<<0)) #define isBranch (mVUinfo & (1<<1)) #define isEOB (mVUinfo & (1<<2)) #define isBdelay (mVUinfo & (1<<3)) +#define isSflag (mVUinfo & (1<<4)) #define writeQ ((mVUinfo >> 5) & 1) #define readQ ((mVUinfo >> 6) & 1) #define writeP ((mVUinfo >> 7) & 1) @@ -192,11 +220,44 @@ declareAllVariables #define fvmInstance ((mVUinfo >> 16) & 3) #define fvsInstance ((mVUinfo >> 18) & 3) #define fvcInstance ((mVUinfo >> 20) & 3) - -//#define getFs (mVUinfo & (1<<13)) -//#define getFt (mVUinfo & (1<<14)) -//#define fpmInstance (((u8)((mVUinfo & (3<<10)) >> 10) - 1) & 0x3) +#define noWriteVF (mVUinfo & (1<<21)) +#define backupVI (mVUinfo & (1<<22)) +#define memReadIs (mVUinfo & (1<<23)) +#define memReadIt (mVUinfo & (1<<24)) +#define writesVI (mVUinfo & (1<<25)) +#define swapOps (mVUinfo & (1<<26)) +#define isFSSET (mVUinfo & (1<<27)) +#define doDivFlag (mVUinfo & (1<<28)) +#define doClip (mVUinfo & (1<<29)) #define isMMX(_VIreg_) (_VIreg_ >= 1 && _VIreg_ <=9) #define mmVI(_VIreg_) (_VIreg_ - 1) +#ifdef mVUdebug +#define mVUprint Console::Status +#define mVUdebug1() { \ + if (curI & _Ibit_) { SysPrintf("microVU: I-bit set!\n"); } \ + if (curI & _Ebit_) { SysPrintf("microVU: E-bit set!\n"); } \ + if (curI & _Mbit_) { SysPrintf("microVU: M-bit set!\n"); } \ + if (curI & _Dbit_) { SysPrintf("microVU: D-bit set!\n"); } \ + if (curI & _Tbit_) { SysPrintf("microVU: T-bit set!\n"); } \ +} +#else +#define mVUprint 0&& +#define mVUdebug1() {} +#endif + +#ifdef mVUlogProg +#define mVUlog __mVULog +#define mVUsetupLog __mVUsetupLog +#define mVUdumpProg __mVUdumpProgram +#else +#define mVUlog 0&& +#define mVUsetupLog() +#define mVUdumpProg 0&& +#endif + +#define mVUcacheCheck(ptr, start, limit) { \ + uptr diff = ptr - start; \ + if (diff >= limit) { Console::Error("microVU Error: Program went over it's cache limit. Size = %x", params diff); } \ +} diff --git a/pcsx2/x86/microVU_Misc.inl b/pcsx2/x86/microVU_Misc.inl index 6977b765e1..895507cc4e 100644 --- a/pcsx2/x86/microVU_Misc.inl +++ b/pcsx2/x86/microVU_Misc.inl @@ -85,101 +85,122 @@ microVUx(void) mVUloadReg(int reg, uptr offset, int xyzw) { microVUx(void) mVUloadReg2(int reg, int gprReg, uptr offset, int xyzw) { switch( xyzw ) { - case 8: SSE_MOVSS_RmOffset_to_XMM(reg, gprReg, offset); break; // X - case 4: SSE_MOVSS_RmOffset_to_XMM(reg, gprReg, offset+4); break; // Y - case 2: SSE_MOVSS_RmOffset_to_XMM(reg, gprReg, offset+8); break; // Z - case 1: SSE_MOVSS_RmOffset_to_XMM(reg, gprReg, offset+12); break; // W - default: SSE_MOVAPSRmtoROffset(reg, gprReg, offset); break; + case 8: SSE_MOVSS_Rm_to_XMM(reg, gprReg, offset); break; // X + case 4: SSE_MOVSS_Rm_to_XMM(reg, gprReg, offset+4); break; // Y + case 2: SSE_MOVSS_Rm_to_XMM(reg, gprReg, offset+8); break; // Z + case 1: SSE_MOVSS_Rm_to_XMM(reg, gprReg, offset+12); break; // W + default: SSE_MOVAPSRmtoR(reg, gprReg, offset); break; } } -microVUx(void) mVUsaveReg(int reg, uptr offset, int xyzw) { +// Modifies the Source Reg! +microVUx(void) mVUsaveReg(int reg, uptr offset, int xyzw, bool modXYZW) { + /*SSE_MOVAPS_M128_to_XMM(xmmT2, offset); + if (modXYZW && (xyzw == 8 || xyzw == 4 || xyzw == 2 || xyzw == 1)) { + mVUunpack_xyzw(reg, reg, 0); + } + mVUmergeRegs(xmmT2, reg, xyzw); + + SSE_MOVAPS_XMM_to_M128(offset, xmmT2); + return;*/ + switch ( xyzw ) { - case 5: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xB1); - SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); + case 5: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xe1); //WZXY SSE_MOVSS_XMM_to_M32(offset+4, reg); - SSE_MOVSS_XMM_to_M32(offset+12, xmmT1); + SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW + SSE_MOVSS_XMM_to_M32(offset+12, reg); break; // YW - case 6: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0xc9); - SSE_MOVLPS_XMM_to_M64(offset+4, xmmT1); + case 6: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xc9); + SSE_MOVLPS_XMM_to_M64(offset+4, reg); break; // YZ - case 7: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0x93); //ZYXW - SSE_MOVHPS_XMM_to_M64(offset+4, xmmT1); - SSE_MOVSS_XMM_to_M32(offset+12, xmmT1); + case 7: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x93); //ZYXW + SSE_MOVHPS_XMM_to_M64(offset+4, reg); + SSE_MOVSS_XMM_to_M32(offset+12, reg); break; // YZW - case 9: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVSS_XMM_to_M32(offset, reg); - if ( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(xmmT1, xmmT1); - else SSE2_PSHUFD_XMM_to_XMM(xmmT1, xmmT1, 0x55); - SSE_MOVSS_XMM_to_M32(offset+12, xmmT1); + case 9: SSE_MOVSS_XMM_to_M32(offset, reg); + SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW + SSE_MOVSS_XMM_to_M32(offset+12, reg); break; // XW - case 10: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVSS_XMM_to_M32(offset, reg); - SSE_MOVSS_XMM_to_M32(offset+8, xmmT1); + case 10: SSE_MOVSS_XMM_to_M32(offset, reg); + SSE_MOVHLPS_XMM_to_XMM(reg, reg); + SSE_MOVSS_XMM_to_M32(offset+8, reg); break; //XZ case 11: SSE_MOVSS_XMM_to_M32(offset, reg); SSE_MOVHPS_XMM_to_M64(offset+8, reg); break; //XZW - case 13: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0x4b); //YXZW - SSE_MOVHPS_XMM_to_M64(offset, xmmT1); - SSE_MOVSS_XMM_to_M32(offset+12, xmmT1); + case 13: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x4b); //YXZW + SSE_MOVHPS_XMM_to_M64(offset, reg); + SSE_MOVSS_XMM_to_M32(offset+12, reg); break; // XYW - case 14: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVLPS_XMM_to_M64(offset, reg); - SSE_MOVSS_XMM_to_M32(offset+8, xmmT1); + case 14: SSE_MOVLPS_XMM_to_M64(offset, reg); + SSE_MOVHLPS_XMM_to_XMM(reg, reg); + SSE_MOVSS_XMM_to_M32(offset+8, reg); break; // XYZ + case 4: if (!modXYZW) mVUunpack_xyzw(reg, reg, 1); + SSE_MOVSS_XMM_to_M32(offset+4, reg); + break; // Y + case 2: if (!modXYZW) mVUunpack_xyzw(reg, reg, 2); + SSE_MOVSS_XMM_to_M32(offset+8, reg); + break; // Z + case 1: if (!modXYZW) mVUunpack_xyzw(reg, reg, 3); + SSE_MOVSS_XMM_to_M32(offset+12, reg); + break; // W case 8: SSE_MOVSS_XMM_to_M32(offset, reg); break; // X - case 4: SSE_MOVSS_XMM_to_M32(offset+4, reg); break; // Y - case 2: SSE_MOVSS_XMM_to_M32(offset+8, reg); break; // Z - case 1: SSE_MOVSS_XMM_to_M32(offset+12, reg); break; // W case 12: SSE_MOVLPS_XMM_to_M64(offset, reg); break; // XY case 3: SSE_MOVHPS_XMM_to_M64(offset+8, reg); break; // ZW default: SSE_MOVAPS_XMM_to_M128(offset, reg); break; // XYZW } } +// Modifies the Source Reg! microVUx(void) mVUsaveReg2(int reg, int gprReg, u32 offset, int xyzw) { + /*SSE_MOVAPSRmtoR(xmmT2, gprReg, offset); + if (xyzw == 8 || xyzw == 4 || xyzw == 2 || xyzw == 1) { + mVUunpack_xyzw(reg, reg, 0); + } + mVUmergeRegs(xmmT2, reg, xyzw); + SSE_MOVAPSRtoRm(gprReg, xmmT2, offset); + return;*/ + switch ( xyzw ) { - case 5: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xB1); - SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+4, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+12, xmmT1); + case 5: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xe1); //WZXY + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+4); + SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+12); break; // YW - case 6: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0xc9); - SSE_MOVLPS_XMM_to_RmOffset(gprReg, offset+4, xmmT1); + case 6: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xc9); + SSE_MOVLPS_XMM_to_Rm(gprReg, reg, offset+4); break; // YZ - case 7: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0x93); //ZYXW - SSE_MOVHPS_XMM_to_RmOffset(gprReg, offset+4, xmmT1); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+12, xmmT1); + case 7: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x93); //ZYXW + SSE_MOVHPS_XMM_to_Rm(gprReg, reg, offset+4); + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+12); break; // YZW - case 9: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset, reg); - if ( cpucaps.hasStreamingSIMD3Extensions ) SSE3_MOVSLDUP_XMM_to_XMM(xmmT1, xmmT1); - else SSE2_PSHUFD_XMM_to_XMM(xmmT1, xmmT1, 0x55); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+12, xmmT1); + case 9: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset); + SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0xff); //WWWW + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+12); break; // XW - case 10: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+8, xmmT1); + case 10: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset); + SSE_MOVHLPS_XMM_to_XMM(reg, reg); + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+8); break; //XZ - case 11: SSE_MOVSS_XMM_to_RmOffset(gprReg, offset, reg); - SSE_MOVHPS_XMM_to_RmOffset(gprReg, offset+8, reg); + case 11: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset); + SSE_MOVHPS_XMM_to_Rm(gprReg, reg, offset+8); break; //XZW - case 13: SSE2_PSHUFD_XMM_to_XMM(xmmT1, reg, 0x4b); //YXZW - SSE_MOVHPS_XMM_to_RmOffset(gprReg, offset, xmmT1); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+12, xmmT1); + case 13: SSE2_PSHUFD_XMM_to_XMM(reg, reg, 0x4b); //YXZW + SSE_MOVHPS_XMM_to_Rm(gprReg, reg, offset); + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+12); break; // XYW - case 14: SSE_MOVHLPS_XMM_to_XMM(xmmT1, reg); - SSE_MOVLPS_XMM_to_RmOffset(gprReg, offset, reg); - SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+8, xmmT1); + case 14: SSE_MOVLPS_XMM_to_Rm(gprReg, reg, offset); + SSE_MOVHLPS_XMM_to_XMM(reg, reg); + SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+8); break; // XYZ - case 8: SSE_MOVSS_XMM_to_RmOffset(gprReg, offset, reg); break; // X - case 4: SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+4, reg); break; // Y - case 2: SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+8, reg); break; // Z - case 1: SSE_MOVSS_XMM_to_RmOffset(gprReg, offset+12, reg); break; // W - case 12: SSE_MOVLPS_XMM_to_RmOffset(gprReg, offset, reg); break; // XY - case 3: SSE_MOVHPS_XMM_to_RmOffset(gprReg, offset+8, reg); break; // ZW - default: SSE_MOVAPSRtoRmOffset(gprReg, offset, reg); break; // XYZW + case 8: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset); break; // X + case 4: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+4); break; // Y + case 2: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+8); break; // Z + case 1: SSE_MOVSS_XMM_to_Rm(gprReg, reg, offset+12); break; // W + case 12: SSE_MOVLPS_XMM_to_Rm(gprReg, reg, offset); break; // XY + case 3: SSE_MOVHPS_XMM_to_Rm(gprReg, reg, offset+8); break; // ZW + default: SSE_MOVAPSRtoRm(gprReg, reg, offset); break; // XYZW } } @@ -244,19 +265,19 @@ microVUx(void) mVUmergeRegs(int dest, int src, int xyzw) { // Transforms the Address in gprReg to valid VU0/VU1 Address microVUt(void) mVUaddrFix(int gprReg) { if ( vuIndex == 1 ) { - AND32ItoR(EAX, 0x3ff); // wrap around - SHL32ItoR(EAX, 4); + AND32ItoR(gprReg, 0x3ff); // wrap around + SHL32ItoR(gprReg, 4); } else { u8 *jmpA, *jmpB; - CMP32ItoR(EAX, 0x400); + CMP32ItoR(gprReg, 0x400); jmpA = JL8(0); // if addr >= 0x4000, reads VU1's VF regs and VI regs - AND32ItoR(EAX, 0x43f); + AND32ItoR(gprReg, 0x43f); // ToDo: theres a potential problem if VU0 overrides VU1's VF0/VI0 regs! jmpB = JMP8(0); x86SetJ8(jmpA); - AND32ItoR(EAX, 0xff); // if addr < 0x4000, wrap around + AND32ItoR(gprReg, 0xff); // if addr < 0x4000, wrap around x86SetJ8(jmpB); - SHL32ItoR(EAX, 4); // multiply by 16 (shift left by 4) + SHL32ItoR(gprReg, 4); // multiply by 16 (shift left by 4) } } diff --git a/pcsx2/x86/microVU_Tables.inl b/pcsx2/x86/microVU_Tables.inl index 22af9f2aaa..26dc6ea8cd 100644 --- a/pcsx2/x86/microVU_Tables.inl +++ b/pcsx2/x86/microVU_Tables.inl @@ -17,8 +17,6 @@ */ #pragma once -#include "microVU_Upper.inl" -#include "microVU_Lower.inl" #ifdef PCSX2_MICROVU //------------------------------------------------------------------ @@ -180,6 +178,76 @@ void (* mVULOWER_OPCODE11 [128])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, }; + +void (* mVULOWER_OPCODE02 [128])() = { + mVU_LQ<0,2> , mVU_SQ<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_ILW<0,2> , mVU_ISW<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_IADDIU<0,2> , mVU_ISUBIU<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_FCEQ<0,2> , mVU_FCSET<0,2> , mVU_FCAND<0,2> , mVU_FCOR<0,2>, /* 0x10 */ + mVU_FSEQ<0,2> , mVU_FSSET<0,2> , mVU_FSAND<0,2> , mVU_FSOR<0,2>, + mVU_FMEQ<0,2> , mVUunknown<0,2> , mVU_FMAND<0,2> , mVU_FMOR<0,2>, + mVU_FCGET<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_B<0,2> , mVU_BAL<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x20 */ + mVU_JR<0,2> , mVU_JALR<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_IBEQ<0,2> , mVU_IBNE<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_IBLTZ<0,2> , mVU_IBGTZ<0,2> , mVU_IBLEZ<0,2> , mVU_IBGEZ<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x30 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVULowerOP<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x40*/ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x50 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x60 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x70 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, +}; + +void (* mVULOWER_OPCODE12 [128])() = { + mVU_LQ<1,2> , mVU_SQ<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_ILW<1,2> , mVU_ISW<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_IADDIU<1,2> , mVU_ISUBIU<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_FCEQ<1,2> , mVU_FCSET<1,2> , mVU_FCAND<1,2> , mVU_FCOR<1,2>, /* 0x10 */ + mVU_FSEQ<1,2> , mVU_FSSET<1,2> , mVU_FSAND<1,2> , mVU_FSOR<1,2>, + mVU_FMEQ<1,2> , mVUunknown<1,2> , mVU_FMAND<1,2> , mVU_FMOR<1,2>, + mVU_FCGET<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_B<1,2> , mVU_BAL<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x20 */ + mVU_JR<1,2> , mVU_JALR<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_IBEQ<1,2> , mVU_IBNE<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_IBLTZ<1,2> , mVU_IBGTZ<1,2> , mVU_IBLEZ<1,2> , mVU_IBGEZ<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x30 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVULowerOP<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x40*/ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x50 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x60 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x70 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -228,6 +296,28 @@ void (* mVULowerOP_T3_00_OPCODE11 [32])() = { mVUunknown<1,1> , mVU_MFP<1,1> , mVU_XTOP<1,1> , mVU_XGKICK<1,1>, mVU_ESADD<1,1> , mVU_EATANxy<1,1> , mVU_ESQRT<1,1> , mVU_ESIN<1,1>, }; + +void (* mVULowerOP_T3_00_OPCODE02 [32])() = { + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_MOVE<0,2> , mVU_LQI<0,2> , mVU_DIV<0,2> , mVU_MTIR<0,2>, + mVU_RNEXT<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x10 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVU_MFP<0,2> , mVU_XTOP<0,2> , mVU_XGKICK<0,2>, + mVU_ESADD<0,2> , mVU_EATANxy<0,2> , mVU_ESQRT<0,2> , mVU_ESIN<0,2>, +}; + +void (* mVULowerOP_T3_00_OPCODE12 [32])() = { + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_MOVE<1,2> , mVU_LQI<1,2> , mVU_DIV<1,2> , mVU_MTIR<1,2>, + mVU_RNEXT<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x10 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVU_MFP<1,2> , mVU_XTOP<1,2> , mVU_XGKICK<1,2>, + mVU_ESADD<1,2> , mVU_EATANxy<1,2> , mVU_ESQRT<1,2> , mVU_ESIN<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -276,6 +366,29 @@ void (* mVULowerOP_T3_01_OPCODE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVU_XITOP<1,1> , mVUunknown<1,1>, mVU_ERSADD<1,1> , mVU_EATANxz<1,1> , mVU_ERSQRT<1,1> , mVU_EATAN<1,1>, }; + +void (* mVULowerOP_T3_01_OPCODE02 [32])() = { + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_MR32<0,2> , mVU_SQI<0,2> , mVU_SQRT<0,2> , mVU_MFIR<0,2>, + mVU_RGET<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x10 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVU_XITOP<0,2> , mVUunknown<0,2>, + mVU_ERSADD<0,2> , mVU_EATANxz<0,2> , mVU_ERSQRT<0,2> , mVU_EATAN<0,2>, +}; + +void (* mVULowerOP_T3_01_OPCODE12 [32])() = { + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_MR32<1,2> , mVU_SQI<1,2> , mVU_SQRT<1,2> , mVU_MFIR<1,2>, + mVU_RGET<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x10 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVU_XITOP<1,2> , mVUunknown<1,2>, + mVU_ERSADD<1,2> , mVU_EATANxz<1,2> , mVU_ERSQRT<1,2> , mVU_EATAN<1,2>, +}; + //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -324,6 +437,28 @@ void (* mVULowerOP_T3_10_OPCODE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVU_ELENG<1,1> , mVU_ESUM<1,1> , mVU_ERCPR<1,1> , mVU_EEXP<1,1>, }; + +void (* mVULowerOP_T3_10_OPCODE02 [32])() = { + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVU_LQD<0,2> , mVU_RSQRT<0,2> , mVU_ILWR<0,2>, + mVU_RINIT<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x10 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_ELENG<0,2> , mVU_ESUM<0,2> , mVU_ERCPR<0,2> , mVU_EEXP<0,2>, +}; + +void (* mVULowerOP_T3_10_OPCODE12 [32])() = { + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVU_LQD<1,2> , mVU_RSQRT<1,2> , mVU_ILWR<1,2>, + mVU_RINIT<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x10 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_ELENG<1,2> , mVU_ESUM<1,2> , mVU_ERCPR<1,2> , mVU_EEXP<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -372,6 +507,28 @@ void (* mVULowerOP_T3_11_OPCODE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVU_ERLENG<1,1> , mVUunknown<1,1> , mVU_WAITP<1,1> , mVUunknown<1,1>, }; + +void (* mVULowerOP_T3_11_OPCODE02 [32])() = { + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVU_SQD<0,2> , mVU_WAITQ<0,2> , mVU_ISWR<0,2>, + mVU_RXOR<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x10 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_ERLENG<0,2> , mVUunknown<0,2> , mVU_WAITP<0,2> , mVUunknown<0,2>, +}; + +void (* mVULowerOP_T3_11_OPCODE12 [32])() = { + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVU_SQD<1,2> , mVU_WAITQ<1,2> , mVU_ISWR<1,2>, + mVU_RXOR<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x10 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_ERLENG<1,2> , mVUunknown<1,2> , mVU_WAITP<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -452,6 +609,44 @@ void (* mVULowerOP_OPCODE11 [64])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVULowerOP_T3_00<1,1>, mVULowerOP_T3_01<1,1>, mVULowerOP_T3_10<1,1>, mVULowerOP_T3_11<1,1>, }; + +void (* mVULowerOP_OPCODE02 [64])() = { + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x10 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x20 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_IADD<0,2> , mVU_ISUB<0,2> , mVU_IADDI<0,2> , mVUunknown<0,2>, /* 0x30 */ + mVU_IAND<0,2> , mVU_IOR<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVULowerOP_T3_00<0,2>, mVULowerOP_T3_01<0,2>, mVULowerOP_T3_10<0,2>, mVULowerOP_T3_11<0,2>, +}; + +void (* mVULowerOP_OPCODE12 [64])() = { + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x10 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x20 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_IADD<1,2> , mVU_ISUB<1,2> , mVU_IADDI<1,2> , mVUunknown<1,2>, /* 0x30 */ + mVU_IAND<1,2> , mVU_IOR<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVULowerOP_T3_00<1,2>, mVULowerOP_T3_01<1,2>, mVULowerOP_T3_10<1,2>, mVULowerOP_T3_11<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -532,6 +727,44 @@ void (* mVU_UPPER_OPCODE11 [64])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVU_UPPER_FD_00<1,1>, mVU_UPPER_FD_01<1,1>, mVU_UPPER_FD_10<1,1>, mVU_UPPER_FD_11<1,1>, }; + +void (* mVU_UPPER_OPCODE02 [64])() = { + mVU_ADDx<0,2> , mVU_ADDy<0,2> , mVU_ADDz<0,2> , mVU_ADDw<0,2>, + mVU_SUBx<0,2> , mVU_SUBy<0,2> , mVU_SUBz<0,2> , mVU_SUBw<0,2>, + mVU_MADDx<0,2> , mVU_MADDy<0,2> , mVU_MADDz<0,2> , mVU_MADDw<0,2>, + mVU_MSUBx<0,2> , mVU_MSUBy<0,2> , mVU_MSUBz<0,2> , mVU_MSUBw<0,2>, + mVU_MAXx<0,2> , mVU_MAXy<0,2> , mVU_MAXz<0,2> , mVU_MAXw<0,2>, /* 0x10 */ + mVU_MINIx<0,2> , mVU_MINIy<0,2> , mVU_MINIz<0,2> , mVU_MINIw<0,2>, + mVU_MULx<0,2> , mVU_MULy<0,2> , mVU_MULz<0,2> , mVU_MULw<0,2>, + mVU_MULq<0,2> , mVU_MAXi<0,2> , mVU_MULi<0,2> , mVU_MINIi<0,2>, + mVU_ADDq<0,2> , mVU_MADDq<0,2> , mVU_ADDi<0,2> , mVU_MADDi<0,2>, /* 0x20 */ + mVU_SUBq<0,2> , mVU_MSUBq<0,2> , mVU_SUBi<0,2> , mVU_MSUBi<0,2>, + mVU_ADD<0,2> , mVU_MADD<0,2> , mVU_MUL<0,2> , mVU_MAX<0,2>, + mVU_SUB<0,2> , mVU_MSUB<0,2> , mVU_OPMSUB<0,2> , mVU_MINI<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, /* 0x30 */ + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVU_UPPER_FD_00<0,2>, mVU_UPPER_FD_01<0,2>, mVU_UPPER_FD_10<0,2>, mVU_UPPER_FD_11<0,2>, +}; + +void (* mVU_UPPER_OPCODE12 [64])() = { + mVU_ADDx<1,2> , mVU_ADDy<1,2> , mVU_ADDz<1,2> , mVU_ADDw<1,2>, + mVU_SUBx<1,2> , mVU_SUBy<1,2> , mVU_SUBz<1,2> , mVU_SUBw<1,2>, + mVU_MADDx<1,2> , mVU_MADDy<1,2> , mVU_MADDz<1,2> , mVU_MADDw<1,2>, + mVU_MSUBx<1,2> , mVU_MSUBy<1,2> , mVU_MSUBz<1,2> , mVU_MSUBw<1,2>, + mVU_MAXx<1,2> , mVU_MAXy<1,2> , mVU_MAXz<1,2> , mVU_MAXw<1,2>, /* 0x10 */ + mVU_MINIx<1,2> , mVU_MINIy<1,2> , mVU_MINIz<1,2> , mVU_MINIw<1,2>, + mVU_MULx<1,2> , mVU_MULy<1,2> , mVU_MULz<1,2> , mVU_MULw<1,2>, + mVU_MULq<1,2> , mVU_MAXi<1,2> , mVU_MULi<1,2> , mVU_MINIi<1,2>, + mVU_ADDq<1,2> , mVU_MADDq<1,2> , mVU_ADDi<1,2> , mVU_MADDi<1,2>, /* 0x20 */ + mVU_SUBq<1,2> , mVU_MSUBq<1,2> , mVU_SUBi<1,2> , mVU_MSUBi<1,2>, + mVU_ADD<1,2> , mVU_MADD<1,2> , mVU_MUL<1,2> , mVU_MAX<1,2>, + mVU_SUB<1,2> , mVU_MSUB<1,2> , mVU_OPMSUB<1,2> , mVU_MINI<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, /* 0x30 */ + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVU_UPPER_FD_00<1,2>, mVU_UPPER_FD_01<1,2>, mVU_UPPER_FD_10<1,2>, mVU_UPPER_FD_11<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -580,6 +813,28 @@ void (* mVU_UPPER_FD_00_TABLE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, }; + +void (* mVU_UPPER_FD_00_TABLE02 [32])() = { + mVU_ADDAx<0,2> , mVU_SUBAx<0,2> , mVU_MADDAx<0,2> , mVU_MSUBAx<0,2>, + mVU_ITOF0<0,2> , mVU_FTOI0<0,2> , mVU_MULAx<0,2> , mVU_MULAq<0,2>, + mVU_ADDAq<0,2> , mVU_SUBAq<0,2> , mVU_ADDA<0,2> , mVU_SUBA<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, +}; + +void (* mVU_UPPER_FD_00_TABLE12 [32])() = { + mVU_ADDAx<1,2> , mVU_SUBAx<1,2> , mVU_MADDAx<1,2> , mVU_MSUBAx<1,2>, + mVU_ITOF0<1,2> , mVU_FTOI0<1,2> , mVU_MULAx<1,2> , mVU_MULAq<1,2>, + mVU_ADDAq<1,2> , mVU_SUBAq<1,2> , mVU_ADDA<1,2> , mVU_SUBA<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -628,6 +883,28 @@ void (* mVU_UPPER_FD_01_TABLE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, }; + +void (* mVU_UPPER_FD_01_TABLE02 [32])() = { + mVU_ADDAy<0,2> , mVU_SUBAy<0,2> , mVU_MADDAy<0,2> , mVU_MSUBAy<0,2>, + mVU_ITOF4<0,2> , mVU_FTOI4<0,2> , mVU_MULAy<0,2> , mVU_ABS<0,2>, + mVU_MADDAq<0,2> , mVU_MSUBAq<0,2> , mVU_MADDA<0,2> , mVU_MSUBA<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, +}; + +void (* mVU_UPPER_FD_01_TABLE12 [32])() = { + mVU_ADDAy<1,2> , mVU_SUBAy<1,2> , mVU_MADDAy<1,2> , mVU_MSUBAy<1,2>, + mVU_ITOF4<1,2> , mVU_FTOI4<1,2> , mVU_MULAy<1,2> , mVU_ABS<1,2>, + mVU_MADDAq<1,2> , mVU_MSUBAq<1,2> , mVU_MADDA<1,2> , mVU_MSUBA<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -676,6 +953,28 @@ void (* mVU_UPPER_FD_10_TABLE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, }; + +void (* mVU_UPPER_FD_10_TABLE02 [32])() = { + mVU_ADDAz<0,2> , mVU_SUBAz<0,2> , mVU_MADDAz<0,2> , mVU_MSUBAz<0,2>, + mVU_ITOF12<0,2> , mVU_FTOI12<0,2> , mVU_MULAz<0,2> , mVU_MULAi<0,2>, + mVU_ADDAi<0,2> , mVU_SUBAi<0,2> , mVU_MULA<0,2> , mVU_OPMULA<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, +}; + +void (* mVU_UPPER_FD_10_TABLE12 [32])() = { + mVU_ADDAz<1,2> , mVU_SUBAz<1,2> , mVU_MADDAz<1,2> , mVU_MSUBAz<1,2>, + mVU_ITOF12<1,2> , mVU_FTOI12<1,2> , mVU_MULAz<1,2> , mVU_MULAi<1,2>, + mVU_ADDAi<1,2> , mVU_SUBAi<1,2> , mVU_MULA<1,2> , mVU_OPMULA<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -724,19 +1023,45 @@ void (* mVU_UPPER_FD_11_TABLE11 [32])() = { mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1> , mVUunknown<1,1>, }; + +void (* mVU_UPPER_FD_11_TABLE02 [32])() = { + mVU_ADDAw<0,2> , mVU_SUBAw<0,2> , mVU_MADDAw<0,2> , mVU_MSUBAw<0,2>, + mVU_ITOF15<0,2> , mVU_FTOI15<0,2> , mVU_MULAw<0,2> , mVU_CLIP<0,2>, + mVU_MADDAi<0,2> , mVU_MSUBAi<0,2> , mVUunknown<0,2> , mVU_NOP<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, + mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2> , mVUunknown<0,2>, +}; + +void (* mVU_UPPER_FD_11_TABLE12 [32])() = { + mVU_ADDAw<1,2> , mVU_SUBAw<1,2> , mVU_MADDAw<1,2> , mVU_MSUBAw<1,2>, + mVU_ITOF15<1,2> , mVU_FTOI15<1,2> , mVU_MULAw<1,2> , mVU_CLIP<1,2>, + mVU_MADDAi<1,2> , mVU_MSUBAi<1,2> , mVUunknown<1,2> , mVU_NOP<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, + mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2> , mVUunknown<1,2>, +}; //------------------------------------------------------------------ //------------------------------------------------------------------ // Table Functions //------------------------------------------------------------------ #define doTableStuff(tableName, args) { \ - if (recPass) { \ + pass1 { \ + if (vuIndex) tableName##10[ args ](); \ + else tableName##00[ args ](); \ + } \ + pass2 { \ if (vuIndex) tableName##11[ args ](); \ else tableName##01[ args ](); \ } \ - else { \ - if (vuIndex) tableName##10[ args ](); \ - else tableName##00[ args ](); \ + pass3 { \ + if (vuIndex) tableName##12[ args ](); \ + else tableName##02[ args ](); \ } \ } @@ -749,8 +1074,11 @@ microVUf(void) mVULowerOP_T3_00() { doTableStuff(mVULowerOP_T3_00_OPCODE, ((mVUg microVUf(void) mVULowerOP_T3_01() { doTableStuff(mVULowerOP_T3_01_OPCODE, ((mVUgetCode >> 6) & 0x1f)); } microVUf(void) mVULowerOP_T3_10() { doTableStuff(mVULowerOP_T3_10_OPCODE, ((mVUgetCode >> 6) & 0x1f)); } microVUf(void) mVULowerOP_T3_11() { doTableStuff(mVULowerOP_T3_11_OPCODE, ((mVUgetCode >> 6) & 0x1f)); } -microVUf(void) mVUunknown() { SysPrintf("mVUunknown<%d,%d> : Unknown Micro VU opcode called\n", vuIndex, recPass); } microVUf(void) mVUopU() { doTableStuff(mVU_UPPER_OPCODE, (mVUgetCode & 0x3f)); } // Gets Upper Opcode microVUf(void) mVUopL() { doTableStuff(mVULOWER_OPCODE, (mVUgetCode >> 25)); } // Gets Lower Opcode +microVUf(void) mVUunknown() { + pass2 { SysPrintf("microVU%d: Unknown Micro VU opcode called (%x)\n", vuIndex, mVUgetCode); } + pass3 { mVUlog("Unknown", mVUgetCode); } +} #endif //PCSX2_MICROVU diff --git a/pcsx2/x86/microVU_Upper.inl b/pcsx2/x86/microVU_Upper.inl index 1b02f1f37e..2d45895a63 100644 --- a/pcsx2/x86/microVU_Upper.inl +++ b/pcsx2/x86/microVU_Upper.inl @@ -31,7 +31,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX microVU* mVU = mVUx; int sReg, mReg = gprT1; static u8 *pjmp, *pjmp2; - static const int flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; + static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}; if (!doFlags) return; if (!doMac) { regT1 = reg; } @@ -52,7 +52,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MOVMSKPS_XMM_to_R32(mReg, regT2); // Move the sign bits of the t1reg - AND16ItoR(mReg, AND_XYZW ); // Grab "Is Signed" bits from the previous calculation + AND16ItoR(mReg, AND_XYZW); // Grab "Is Signed" bits from the previous calculation pjmp = JZ8(0); // Skip if none are if (doMac) SHL16ItoR(mReg, 4 + ADD_XYZW); if (doStatus) OR16ItoR(sReg, 0x82); // SS, S flags @@ -61,7 +61,7 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX //-------------------------Check for Zero flags------------------------------ - AND16ItoR(gprT2, AND_XYZW ); // Grab "Is Zero" bits from the previous calculation + AND16ItoR(gprT2, AND_XYZW); // Grab "Is Zero" bits from the previous calculation pjmp = JZ8(0); // Skip if none are if (doMac) { SHIFT_XYZW(gprT2); OR32RtoR(mReg, gprT2); } if (doStatus) { OR16ItoR(sReg, 0x41); } // ZS, Z flags @@ -79,88 +79,94 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX //------------------------------------------------------------------ // FMAC1 - Normal FMAC Opcodes -#define mVU_FMAC1(operation) { \ +#define mVU_FMAC1(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, Fs, Ft; \ mVUallocFMAC1a(Fd, Fs, Ft); \ if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 1); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \ mVUallocFMAC1b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC3 - BC(xyzw) FMAC Opcodes -#define mVU_FMAC3(operation) { \ +#define mVU_FMAC3(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, Fs, Ft; \ mVUallocFMAC3a(Fd, Fs, Ft); \ if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 1); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \ mVUallocFMAC3b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC4 - FMAC Opcodes Storing Result to ACC -#define mVU_FMAC4(operation) { \ +#define mVU_FMAC4(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ + pass2 { \ int ACC, Fs, Ft; \ mVUallocFMAC4a(ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC4b(ACC, Fs); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC5 - FMAC BC(xyzw) Opcodes Storing Result to ACC -#define mVU_FMAC5(operation) { \ +#define mVU_FMAC5(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC3(0, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC3(0, _Fs_, _Ft_); } \ + pass2 { \ int ACC, Fs, Ft; \ mVUallocFMAC5a(ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC5b(ACC, Fs); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC6 - Normal FMAC Opcodes (I Reg) -#define mVU_FMAC6(operation) { \ +#define mVU_FMAC6(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, Fs, Ft; \ mVUallocFMAC6a(Fd, Fs, Ft); \ if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 1); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \ mVUallocFMAC6b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC7 - FMAC Opcodes Storing Result to ACC (I Reg) -#define mVU_FMAC7(operation) { \ +#define mVU_FMAC7(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, 0); } \ + pass2 { \ int ACC, Fs, Ft; \ mVUallocFMAC7a(ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC7b(ACC, Fs); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC8 - MADD FMAC Opcode Storing Result to Fd -#define mVU_FMAC8(operation) { \ +#define mVU_FMAC8(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC8a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -171,15 +177,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \ } \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC8b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC9 - MSUB FMAC Opcode Storing Result to Fd -#define mVU_FMAC9(operation) { \ +#define mVU_FMAC9(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC9a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -190,15 +197,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \ } \ - mVUupdateFlags(Fd, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC9b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC10 - MADD FMAC BC(xyzw) Opcode Storing Result to Fd -#define mVU_FMAC10(operation) { \ +#define mVU_FMAC10(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC10a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -209,15 +217,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \ } \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC10b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC11 - MSUB FMAC BC(xyzw) Opcode Storing Result to Fd -#define mVU_FMAC11(operation) { \ +#define mVU_FMAC11(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC3(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC11a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -228,15 +237,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \ } \ - mVUupdateFlags(Fd, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC11b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC12 - MADD FMAC Opcode Storing Result to Fd (I Reg) -#define mVU_FMAC12(operation) { \ +#define mVU_FMAC12(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC12a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -247,15 +257,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \ } \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC12b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC13 - MSUB FMAC Opcode Storing Result to Fd (I Reg) -#define mVU_FMAC13(operation) { \ +#define mVU_FMAC13(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC13a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -266,15 +277,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \ } \ - mVUupdateFlags(Fd, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC13b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC14 - MADDA/MSUBA FMAC Opcode -#define mVU_FMAC14(operation) { \ +#define mVU_FMAC14(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ + pass2 { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC14a(ACCw, ACCr, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -285,15 +297,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ - mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC14b(ACCw, ACCr); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC15 - MADDA/MSUBA BC(xyzw) FMAC Opcode -#define mVU_FMAC15(operation) { \ +#define mVU_FMAC15(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC3(0, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC3(0, _Fs_, _Ft_); } \ + pass2 { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC15a(ACCw, ACCr, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -304,15 +317,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ - mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC15b(ACCw, ACCr); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC16 - MADDA/MSUBA FMAC Opcode (I Reg) -#define mVU_FMAC16(operation) { \ +#define mVU_FMAC16(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, 0); } \ + pass2 { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC16a(ACCw, ACCr, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -323,66 +337,71 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ - mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC16b(ACCw, ACCr); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC18 - OPMULA FMAC Opcode -#define mVU_FMAC18(operation) { \ +#define mVU_FMAC18(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, _Ft_); } \ + pass2 { \ int ACC, Fs, Ft; \ mVUallocFMAC18a(ACC, Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC18b(ACC, Fs); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC19 - OPMULA FMAC Opcode -#define mVU_FMAC19(operation) { \ +#define mVU_FMAC19(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, _Ft_); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC19a(Fd, ACC, Fs, Ft); \ SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \ - mVUupdateFlags(Fd, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC19b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC22 - Normal FMAC Opcodes (Q Reg) -#define mVU_FMAC22(operation) { \ +#define mVU_FMAC22(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, Fs, Ft; \ mVUallocFMAC22a(Fd, Fs, Ft); \ if (_XYZW_SS) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 1); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 1); \ mVUallocFMAC22b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC23 - FMAC Opcodes Storing Result to ACC (Q Reg) -#define mVU_FMAC23(operation) { \ +#define mVU_FMAC23(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, 0); } \ + pass2 { \ int ACC, Fs, Ft; \ mVUallocFMAC23a(ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) SSE_##operation##SS_XMM_to_XMM(Fs, Ft); \ else SSE_##operation##PS_XMM_to_XMM(Fs, Ft); \ - mVUupdateFlags(Fs, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fs, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC23b(ACC, Fs); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC24 - MADD FMAC Opcode Storing Result to Fd (Q Reg) -#define mVU_FMAC24(operation) { \ +#define mVU_FMAC24(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC24a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -393,15 +412,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(Fs, ACC); \ } \ - mVUupdateFlags(Fd, xmmT1, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, xmmT1, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC24b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC25 - MSUB FMAC Opcode Storing Result to Fd (Q Reg) -#define mVU_FMAC25(operation) { \ +#define mVU_FMAC25(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(_Fd_, _Fs_, 0); } \ + pass2 { \ int Fd, ACC, Fs, Ft; \ mVUallocFMAC25a(Fd, ACC, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -412,15 +432,16 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACC, Fs); \ } \ - mVUupdateFlags(Fd, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(Fd, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC25b(Fd); \ } \ + pass3 { mVUlog(OPname); } \ } // FMAC26 - MADDA/MSUBA FMAC Opcode (Q Reg) -#define mVU_FMAC26(operation) { \ +#define mVU_FMAC26(operation, OPname) { \ microVU* mVU = mVUx; \ - if (!recPass) { mVUanalyzeFMAC1(0, _Fs_, 0); } \ - else { \ + pass1 { mVUanalyzeFMAC1(0, _Fs_, 0); } \ + pass2 { \ int ACCw, ACCr, Fs, Ft; \ mVUallocFMAC26a(ACCw, ACCr, Fs, Ft); \ if (_X_Y_Z_W == 8) { \ @@ -431,9 +452,10 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX SSE_MULPS_XMM_to_XMM(Fs, Ft); \ SSE_##operation##PS_XMM_to_XMM(ACCr, Fs); \ } \ - mVUupdateFlags(ACCr, Fs, Ft, _X_Y_Z_W, 0); \ + mVUupdateFlags(ACCr, Fs, xmmT2, _X_Y_Z_W, 0); \ mVUallocFMAC26b(ACCw, ACCr); \ } \ + pass3 { mVUlog(OPname); } \ } //------------------------------------------------------------------ @@ -442,107 +464,104 @@ microVUt(void) mVUupdateFlags(int reg, int regT1, int regT2, int xyzw, bool modX microVUf(void) mVU_ABS() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFMAC2(_Fs_, _Ft_); } - else { + pass1 { mVUanalyzeFMAC2(_Fs_, _Ft_); } + pass2 { int Fs, Ft; mVUallocFMAC2a(Fs, Ft); SSE_ANDPS_M128_to_XMM(Fs, (uptr)mVU_absclip); mVUallocFMAC2b(Ft); } + pass3 { mVUlog("ABS"); } } -microVUf(void) mVU_ADD() { mVU_FMAC1(ADD); } -microVUf(void) mVU_ADDi() { mVU_FMAC6(ADD); } -microVUf(void) mVU_ADDq() { mVU_FMAC22(ADD); } -microVUf(void) mVU_ADDx() { mVU_FMAC3(ADD); } -microVUf(void) mVU_ADDy() { mVU_FMAC3(ADD); } -microVUf(void) mVU_ADDz() { mVU_FMAC3(ADD); } -microVUf(void) mVU_ADDw() { mVU_FMAC3(ADD); } -microVUf(void) mVU_ADDA() { mVU_FMAC4(ADD); } -microVUf(void) mVU_ADDAi() { mVU_FMAC7(ADD); } -microVUf(void) mVU_ADDAq() { mVU_FMAC23(ADD); } -microVUf(void) mVU_ADDAx() { mVU_FMAC5(ADD); } -microVUf(void) mVU_ADDAy() { mVU_FMAC5(ADD); } -microVUf(void) mVU_ADDAz() { mVU_FMAC5(ADD); } -microVUf(void) mVU_ADDAw() { mVU_FMAC5(ADD); } -microVUf(void) mVU_SUB() { mVU_FMAC1(SUB); } -microVUf(void) mVU_SUBi() { mVU_FMAC6(SUB); } -microVUf(void) mVU_SUBq() { mVU_FMAC22(SUB); } -microVUf(void) mVU_SUBx() { mVU_FMAC3(SUB); } -microVUf(void) mVU_SUBy() { mVU_FMAC3(SUB); } -microVUf(void) mVU_SUBz() { mVU_FMAC3(SUB); } -microVUf(void) mVU_SUBw() { mVU_FMAC3(SUB); } -microVUf(void) mVU_SUBA() { mVU_FMAC4(SUB); } -microVUf(void) mVU_SUBAi() { mVU_FMAC7(SUB); } -microVUf(void) mVU_SUBAq() { mVU_FMAC23(SUB); } -microVUf(void) mVU_SUBAx() { mVU_FMAC5(SUB); } -microVUf(void) mVU_SUBAy() { mVU_FMAC5(SUB); } -microVUf(void) mVU_SUBAz() { mVU_FMAC5(SUB); } -microVUf(void) mVU_SUBAw() { mVU_FMAC5(SUB); } -microVUf(void) mVU_MUL() { mVU_FMAC1(MUL); } -microVUf(void) mVU_MULi() { mVU_FMAC6(MUL); } -microVUf(void) mVU_MULq() { mVU_FMAC22(MUL); } -microVUf(void) mVU_MULx() { mVU_FMAC3(MUL); } -microVUf(void) mVU_MULy() { mVU_FMAC3(MUL); } -microVUf(void) mVU_MULz() { mVU_FMAC3(MUL); } -microVUf(void) mVU_MULw() { mVU_FMAC3(MUL); } -microVUf(void) mVU_MULA() { mVU_FMAC4(MUL); } -microVUf(void) mVU_MULAi() { mVU_FMAC7(MUL); } -microVUf(void) mVU_MULAq() { mVU_FMAC23(MUL); } -microVUf(void) mVU_MULAx() { mVU_FMAC5(MUL); } -microVUf(void) mVU_MULAy() { mVU_FMAC5(MUL); } -microVUf(void) mVU_MULAz() { mVU_FMAC5(MUL); } -microVUf(void) mVU_MULAw() { mVU_FMAC5(MUL); } -microVUf(void) mVU_MADD() { mVU_FMAC8(ADD); } -microVUf(void) mVU_MADDi() { mVU_FMAC12(ADD); } -microVUf(void) mVU_MADDq() { mVU_FMAC24(ADD); } -microVUf(void) mVU_MADDx() { mVU_FMAC10(ADD); } -microVUf(void) mVU_MADDy() { mVU_FMAC10(ADD); } -microVUf(void) mVU_MADDz() { mVU_FMAC10(ADD); } -microVUf(void) mVU_MADDw() { mVU_FMAC10(ADD); } -microVUf(void) mVU_MADDA() { mVU_FMAC14(ADD); } -microVUf(void) mVU_MADDAi() { mVU_FMAC16(ADD); } -microVUf(void) mVU_MADDAq() { mVU_FMAC26(ADD); } -microVUf(void) mVU_MADDAx() { mVU_FMAC15(ADD); } -microVUf(void) mVU_MADDAy() { mVU_FMAC15(ADD); } -microVUf(void) mVU_MADDAz() { mVU_FMAC15(ADD); } -microVUf(void) mVU_MADDAw() { mVU_FMAC15(ADD); } -microVUf(void) mVU_MSUB() { mVU_FMAC9(SUB); } -microVUf(void) mVU_MSUBi() { mVU_FMAC13(SUB); } -microVUf(void) mVU_MSUBq() { mVU_FMAC25(SUB); } -microVUf(void) mVU_MSUBx() { mVU_FMAC11(SUB); } -microVUf(void) mVU_MSUBy() { mVU_FMAC11(SUB); } -microVUf(void) mVU_MSUBz() { mVU_FMAC11(SUB); } -microVUf(void) mVU_MSUBw() { mVU_FMAC11(SUB); } -microVUf(void) mVU_MSUBA() { mVU_FMAC14(SUB); } -microVUf(void) mVU_MSUBAi() { mVU_FMAC16(SUB); } -microVUf(void) mVU_MSUBAq() { mVU_FMAC26(SUB); } -microVUf(void) mVU_MSUBAx() { mVU_FMAC15(SUB); } -microVUf(void) mVU_MSUBAy() { mVU_FMAC15(SUB); } -microVUf(void) mVU_MSUBAz() { mVU_FMAC15(SUB); } -microVUf(void) mVU_MSUBAw() { mVU_FMAC15(SUB); } -microVUf(void) mVU_MAX() { mVU_FMAC1(MAX); } -microVUf(void) mVU_MAXi() { mVU_FMAC6(MAX); } -microVUf(void) mVU_MAXx() { mVU_FMAC3(MAX); } -microVUf(void) mVU_MAXy() { mVU_FMAC3(MAX); } -microVUf(void) mVU_MAXz() { mVU_FMAC3(MAX); } -microVUf(void) mVU_MAXw() { mVU_FMAC3(MAX); } -microVUf(void) mVU_MINI() { mVU_FMAC1(MIN); } -microVUf(void) mVU_MINIi() { mVU_FMAC6(MIN); } -microVUf(void) mVU_MINIx() { mVU_FMAC3(MIN); } -microVUf(void) mVU_MINIy() { mVU_FMAC3(MIN); } -microVUf(void) mVU_MINIz() { mVU_FMAC3(MIN); } -microVUf(void) mVU_MINIw() { mVU_FMAC3(MIN); } -microVUf(void) mVU_OPMULA() { mVU_FMAC18(MUL); } -microVUf(void) mVU_OPMSUB() { mVU_FMAC19(SUB); } -microVUf(void) mVU_NOP() { - microVU* mVU = mVUx; - if (!recPass) {} - else {} -} +microVUf(void) mVU_ADD() { mVU_FMAC1 (ADD, "ADD"); } +microVUf(void) mVU_ADDi() { mVU_FMAC6 (ADD, "ADDi"); } +microVUf(void) mVU_ADDq() { mVU_FMAC22(ADD, "ADDq"); } +microVUf(void) mVU_ADDx() { mVU_FMAC3 (ADD, "ADDx"); } +microVUf(void) mVU_ADDy() { mVU_FMAC3 (ADD, "ADDy"); } +microVUf(void) mVU_ADDz() { mVU_FMAC3 (ADD, "ADDz"); } +microVUf(void) mVU_ADDw() { mVU_FMAC3 (ADD, "ADDw"); } +microVUf(void) mVU_ADDA() { mVU_FMAC4 (ADD, "ADDA"); } +microVUf(void) mVU_ADDAi() { mVU_FMAC7 (ADD, "ADDAi"); } +microVUf(void) mVU_ADDAq() { mVU_FMAC23(ADD, "ADDAq"); } +microVUf(void) mVU_ADDAx() { mVU_FMAC5 (ADD, "ADDAx"); } +microVUf(void) mVU_ADDAy() { mVU_FMAC5 (ADD, "ADDAy"); } +microVUf(void) mVU_ADDAz() { mVU_FMAC5 (ADD, "ADDAz"); } +microVUf(void) mVU_ADDAw() { mVU_FMAC5 (ADD, "ADDAw"); } +microVUf(void) mVU_SUB() { mVU_FMAC1 (SUB, "SUB"); } +microVUf(void) mVU_SUBi() { mVU_FMAC6 (SUB, "SUBi"); } +microVUf(void) mVU_SUBq() { mVU_FMAC22(SUB, "SUBq"); } +microVUf(void) mVU_SUBx() { mVU_FMAC3 (SUB, "SUBx"); } +microVUf(void) mVU_SUBy() { mVU_FMAC3 (SUB, "SUBy"); } +microVUf(void) mVU_SUBz() { mVU_FMAC3 (SUB, "SUBz"); } +microVUf(void) mVU_SUBw() { mVU_FMAC3 (SUB, "SUBw"); } +microVUf(void) mVU_SUBA() { mVU_FMAC4 (SUB, "SUBA"); } +microVUf(void) mVU_SUBAi() { mVU_FMAC7 (SUB, "SUBAi"); } +microVUf(void) mVU_SUBAq() { mVU_FMAC23(SUB, "SUBAq"); } +microVUf(void) mVU_SUBAx() { mVU_FMAC5 (SUB, "SUBAx"); } +microVUf(void) mVU_SUBAy() { mVU_FMAC5 (SUB, "SUBAy"); } +microVUf(void) mVU_SUBAz() { mVU_FMAC5 (SUB, "SUBAz"); } +microVUf(void) mVU_SUBAw() { mVU_FMAC5 (SUB, "SUBAw"); } +microVUf(void) mVU_MUL() { mVU_FMAC1 (MUL, "MUL"); } +microVUf(void) mVU_MULi() { mVU_FMAC6 (MUL, "MULi"); } +microVUf(void) mVU_MULq() { mVU_FMAC22(MUL, "MULq"); } +microVUf(void) mVU_MULx() { mVU_FMAC3 (MUL, "MULx"); } +microVUf(void) mVU_MULy() { mVU_FMAC3 (MUL, "MULy"); } +microVUf(void) mVU_MULz() { mVU_FMAC3 (MUL, "MULz"); } +microVUf(void) mVU_MULw() { mVU_FMAC3 (MUL, "MULw"); } +microVUf(void) mVU_MULA() { mVU_FMAC4 (MUL, "MULA"); } +microVUf(void) mVU_MULAi() { mVU_FMAC7 (MUL, "MULAi"); } +microVUf(void) mVU_MULAq() { mVU_FMAC23(MUL, "MULAq"); } +microVUf(void) mVU_MULAx() { mVU_FMAC5 (MUL, "MULAx"); } +microVUf(void) mVU_MULAy() { mVU_FMAC5 (MUL, "MULAy"); } +microVUf(void) mVU_MULAz() { mVU_FMAC5 (MUL, "MULAz"); } +microVUf(void) mVU_MULAw() { mVU_FMAC5 (MUL, "MULAw"); } +microVUf(void) mVU_MADD() { mVU_FMAC8 (ADD, "MADD"); } +microVUf(void) mVU_MADDi() { mVU_FMAC12(ADD, "MADDi"); } +microVUf(void) mVU_MADDq() { mVU_FMAC24(ADD, "MADDq"); } +microVUf(void) mVU_MADDx() { mVU_FMAC10(ADD, "MADDx"); } +microVUf(void) mVU_MADDy() { mVU_FMAC10(ADD, "MADDy"); } +microVUf(void) mVU_MADDz() { mVU_FMAC10(ADD, "MADDz"); } +microVUf(void) mVU_MADDw() { mVU_FMAC10(ADD, "MADDw"); } +microVUf(void) mVU_MADDA() { mVU_FMAC14(ADD, "MADDA"); } +microVUf(void) mVU_MADDAi() { mVU_FMAC16(ADD, "MADDAi"); } +microVUf(void) mVU_MADDAq() { mVU_FMAC26(ADD, "MADDAq"); } +microVUf(void) mVU_MADDAx() { mVU_FMAC15(ADD, "MADDAx"); } +microVUf(void) mVU_MADDAy() { mVU_FMAC15(ADD, "MADDAy"); } +microVUf(void) mVU_MADDAz() { mVU_FMAC15(ADD, "MADDAz"); } +microVUf(void) mVU_MADDAw() { mVU_FMAC15(ADD, "MADDAw"); } +microVUf(void) mVU_MSUB() { mVU_FMAC9 (SUB, "MSUB"); } +microVUf(void) mVU_MSUBi() { mVU_FMAC13(SUB, "MSUBi"); } +microVUf(void) mVU_MSUBq() { mVU_FMAC25(SUB, "MSUBq"); } +microVUf(void) mVU_MSUBx() { mVU_FMAC11(SUB, "MSUBx"); } +microVUf(void) mVU_MSUBy() { mVU_FMAC11(SUB, "MSUBy"); } +microVUf(void) mVU_MSUBz() { mVU_FMAC11(SUB, "MSUBz"); } +microVUf(void) mVU_MSUBw() { mVU_FMAC11(SUB, "MSUBw"); } +microVUf(void) mVU_MSUBA() { mVU_FMAC14(SUB, "MSUBA"); } +microVUf(void) mVU_MSUBAi() { mVU_FMAC16(SUB, "MSUBAi"); } +microVUf(void) mVU_MSUBAq() { mVU_FMAC26(SUB, "MSUBAq"); } +microVUf(void) mVU_MSUBAx() { mVU_FMAC15(SUB, "MSUBAx"); } +microVUf(void) mVU_MSUBAy() { mVU_FMAC15(SUB, "MSUBAy"); } +microVUf(void) mVU_MSUBAz() { mVU_FMAC15(SUB, "MSUBAz"); } +microVUf(void) mVU_MSUBAw() { mVU_FMAC15(SUB, "MSUBAw"); } +microVUf(void) mVU_MAX() { mVU_FMAC1 (MAX, "MAX"); } +microVUf(void) mVU_MAXi() { mVU_FMAC6 (MAX, "MAXi"); } +microVUf(void) mVU_MAXx() { mVU_FMAC3 (MAX, "MAXq"); } +microVUf(void) mVU_MAXy() { mVU_FMAC3 (MAX, "MAXy"); } +microVUf(void) mVU_MAXz() { mVU_FMAC3 (MAX, "MAXz"); } +microVUf(void) mVU_MAXw() { mVU_FMAC3 (MAX, "MAXw"); } +microVUf(void) mVU_MINI() { mVU_FMAC1 (MIN, "MINI"); } +microVUf(void) mVU_MINIi() { mVU_FMAC6 (MIN, "MINIi"); } +microVUf(void) mVU_MINIx() { mVU_FMAC3 (MIN, "MINIx"); } +microVUf(void) mVU_MINIy() { mVU_FMAC3 (MIN, "MINIy"); } +microVUf(void) mVU_MINIz() { mVU_FMAC3 (MIN, "MINIz"); } +microVUf(void) mVU_MINIw() { mVU_FMAC3 (MIN, "MINIw"); } +microVUf(void) mVU_OPMULA() { mVU_FMAC18(MUL, "OPMULA"); } +microVUf(void) mVU_OPMSUB() { mVU_FMAC19(SUB, "OPMSUB"); } +microVUf(void) mVU_NOP() { pass3 { mVUlog("NOP"); } } microVUq(void) mVU_FTOIx(uptr addr) { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFMAC2(_Fs_, _Ft_); } - else { + pass1 { mVUanalyzeFMAC2(_Fs_, _Ft_); } + pass2 { int Fs, Ft; mVUallocFMAC2a(Fs, Ft); @@ -560,14 +579,14 @@ microVUq(void) mVU_FTOIx(uptr addr) { mVUallocFMAC2b(Ft); } } -microVUf(void) mVU_FTOI0() { mVU_FTOIx(0); } -microVUf(void) mVU_FTOI4() { mVU_FTOIx((uptr)mVU_FTOI_4); } -microVUf(void) mVU_FTOI12() { mVU_FTOIx((uptr)mVU_FTOI_12); } -microVUf(void) mVU_FTOI15() { mVU_FTOIx((uptr)mVU_FTOI_15); } +microVUf(void) mVU_FTOI0() { mVU_FTOIx((uptr)0); pass3 { mVUlog("FTOI0"); } } +microVUf(void) mVU_FTOI4() { mVU_FTOIx((uptr)mVU_FTOI_4); pass3 { mVUlog("FTOI4"); } } +microVUf(void) mVU_FTOI12() { mVU_FTOIx((uptr)mVU_FTOI_12); pass3 { mVUlog("FTOI12"); } } +microVUf(void) mVU_FTOI15() { mVU_FTOIx((uptr)mVU_FTOI_15); pass3 { mVUlog("FTOI15"); } } microVUq(void) mVU_ITOFx(uptr addr) { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFMAC2(_Fs_, _Ft_); } - else { + pass1 { mVUanalyzeFMAC2(_Fs_, _Ft_); } + pass2 { int Fs, Ft; mVUallocFMAC2a(Fs, Ft); @@ -578,14 +597,14 @@ microVUq(void) mVU_ITOFx(uptr addr) { mVUallocFMAC2b(Ft); } } -microVUf(void) mVU_ITOF0() { mVU_ITOFx(0); } -microVUf(void) mVU_ITOF4() { mVU_ITOFx((uptr)mVU_ITOF_4); } -microVUf(void) mVU_ITOF12() { mVU_ITOFx((uptr)mVU_ITOF_12); } -microVUf(void) mVU_ITOF15() { mVU_ITOFx((uptr)mVU_ITOF_15); } +microVUf(void) mVU_ITOF0() { mVU_ITOFx((uptr)0); pass3 { mVUlog("ITOF0"); } } +microVUf(void) mVU_ITOF4() { mVU_ITOFx((uptr)mVU_ITOF_4); pass3 { mVUlog("ITOF4"); } } +microVUf(void) mVU_ITOF12() { mVU_ITOFx((uptr)mVU_ITOF_12); pass3 { mVUlog("ITOF12"); } } +microVUf(void) mVU_ITOF15() { mVU_ITOFx((uptr)mVU_ITOF_15); pass3 { mVUlog("ITOF15"); } } microVUf(void) mVU_CLIP() { microVU* mVU = mVUx; - if (!recPass) { mVUanalyzeFMAC4(_Fs_, _Ft_); } - else { + pass1 { mVUanalyzeFMAC4(_Fs_, _Ft_); } + pass2 { int Fs, Ft; mVUallocFMAC17a(Fs, Ft); mVUallocCFLAGa(gprT1, fpcInstance); @@ -614,5 +633,6 @@ microVUf(void) mVU_CLIP() { mVUallocCFLAGb(gprT1, fcInstance); } + pass3 { mVUlog("CLIP"); } } #endif //PCSX2_MICROVU diff --git a/pcsx2/xmlpatchloader.cpp b/pcsx2/xmlpatchloader.cpp index 75df7b31f7..afc737fa19 100644 --- a/pcsx2/xmlpatchloader.cpp +++ b/pcsx2/xmlpatchloader.cpp @@ -71,14 +71,12 @@ Patch Patch::operator =(const Patch&p) vector groups; vector patches; -int LoadPatch( const string& crc) +int LoadPatch( const wxString& crc ) { - char pfile[256]; - sprintf(pfile,"patches\\%hs.xml",&crc); - + wxString pfile( Path::Combine( L"patches", crc ) + L".xml" ); patchnumber=0; - TiXmlDocument doc( pfile ); + TiXmlDocument doc( pfile.ToAscii().data() ); bool loadOkay = doc.LoadFile(); if ( !loadOkay ) { @@ -109,8 +107,9 @@ int LoadPatch( const string& crc) return result; } - Console::SetTitle( - ((title==NULL) || (strlen(title)==0)) ? "" : title ); + wxString uTitle( wxString::FromAscii( title ) ); + if( uTitle.IsEmpty() ) uTitle = L""; + Console::SetTitle( uTitle ); return 0; } diff --git a/plugins/GSdx/GPURenderer.h b/plugins/GSdx/GPURenderer.h index 96ff0df01f..17df468a44 100644 --- a/plugins/GSdx/GPURenderer.h +++ b/plugins/GSdx/GPURenderer.h @@ -56,20 +56,15 @@ protected: { if(message == WM_KEYUP) { - if(wParam == VK_DELETE) + switch(wParam) { + case VK_DELETE: m_filter = (m_filter + 1) % 3; return 0; - } - - if(wParam == VK_END) - { + case VK_END: m_dither = m_dither ? 0 : 1; return 0; - } - - if(wParam == VK_NEXT) - { + case VK_NEXT: m_aspectratio = (m_aspectratio + 1) % 3; return 0; } diff --git a/plugins/GSdx/GS.cpp b/plugins/GSdx/GS.cpp index 0da874ce54..3dd274f709 100644 --- a/plugins/GSdx/GS.cpp +++ b/plugins/GSdx/GS.cpp @@ -106,10 +106,6 @@ static INT32 GSopen(void* dsp, char* title, int mt, int renderer) GSclose(); - // TODO - - int nloophack = AfxGetApp()->GetProfileInt(_T("Settings"), _T("nloophack"), 2); - GSRendererSettings rs; rs.m_interlace = AfxGetApp()->GetProfileInt(_T("Settings"), _T("interlace"), 0); @@ -125,14 +121,14 @@ static INT32 GSopen(void* dsp, char* title, int mt, int renderer) switch(renderer) { default: - case 0: s_gs = new GSRendererHW9(s_basemem, !!mt, s_irq, nloophack, rs); break; - case 1: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, nloophack, rs, threads); break; - case 2: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, nloophack, rs); break; - case 3: s_gs = new GSRendererHW10(s_basemem, !!mt, s_irq, nloophack, rs); break; - case 4: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, nloophack, rs, threads); break; - case 5: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, nloophack, rs); break; - case 6: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, nloophack, rs, threads); break; - case 7: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, nloophack, rs); break; + case 0: s_gs = new GSRendererHW9(s_basemem, !!mt, s_irq, rs); break; + case 1: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, rs, threads); break; + case 2: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, rs); break; + case 3: s_gs = new GSRendererHW10(s_basemem, !!mt, s_irq, rs); break; + case 4: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, rs, threads); break; + case 5: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, rs); break; + case 6: s_gs = new GSRendererSW(s_basemem, !!mt, s_irq, rs, threads); break; + case 7: s_gs = new GSRendererNull(s_basemem, !!mt, s_irq, rs); break; } s_hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); diff --git a/plugins/GSdx/GS.h b/plugins/GSdx/GS.h index 388af54658..f670531aa4 100644 --- a/plugins/GSdx/GS.h +++ b/plugins/GSdx/GS.h @@ -26,7 +26,7 @@ #pragma once -#define PLUGIN_VERSION 14 +#define PLUGIN_VERSION 15 #include "GSVector.h" diff --git a/plugins/GSdx/GSCrc.cpp b/plugins/GSdx/GSCrc.cpp index ae03ccbefb..584c9c4404 100644 --- a/plugins/GSdx/GSCrc.cpp +++ b/plugins/GSdx/GSCrc.cpp @@ -24,107 +24,108 @@ CRC::Game CRC::m_games[] = { - {0x00000000, None, Unknown, false}, - {0x2113EA2E, MetalSlug6, Unknown, false}, - {0x42E05BAF, TomoyoAfter, JP, false}, - {0x7800DC84, Clannad, JP, false}, - {0xa39517ab, FFX, EU, true}, - {0xa39517ae, FFX, FR, true}, - {0x941bb7d9, FFX, DE, true}, - {0xa39517a9, FFX, IT, true}, - {0x941bb7de, FFX, ES, true}, - {0xb4414ea1, FFX, RU, true}, - {0xee97db5b, FFX, RU, true}, - {0xaec495cc, FFX, RU, true}, - {0xbb3d833a, FFX, US, true}, - {0x6a4efe60, FFX, JP, true}, - {0x3866ca7e, FFX, ASIA, true}, // int. - {0x658597e2, FFX, JP, true}, // int. - {0x9aac5309, FFX2, EU, true}, - {0x9aac530c, FFX2, FR, true}, - {0x9aac530a, FFX2, FR, true}, // ? - {0x9aac530d, FFX2, DE, true}, - {0x9aac530b, FFX2, IT, true}, - {0x48fe0c71, FFX2, US, true}, - {0xe1fd9a2d, FFX2, JP, true}, // int. - {0x78da0252, FFXII, EU, false}, - {0xc1274668, FFXII, EU, false}, - {0xdc2a467e, FFXII, EU, false}, - {0xca284668, FFXII, EU, false}, - {0x280AD120, FFXII, JP, false}, - {0x8BE3D7B2, ShadowHearts, Unknown, false}, - {0xDEFA4763, ShadowHearts, US, false}, - {0x21068223, Okami, US, false}, - {0x891f223f, Okami, FR, false}, - {0xC5DEFEA0, Okami, JP, false}, - {0x053D2239, MetalGearSolid3, US, false}, - {0x086273D2, MetalGearSolid3, FR, false}, - {0x26A6E286, MetalGearSolid3, EU, false}, - {0xAA31B5BF, MetalGearSolid3, Unknown, false}, - {0x9F185CE1, MetalGearSolid3, Unknown, false}, - {0x98D4BC93, MetalGearSolid3, EU, false}, - {0x86BC3040, MetalGearSolid3, US, false}, //Subsistance disc 1 - {0x0481AD8A, MetalGearSolid3, JP, false}, - {0x79ED26AD, MetalGearSolid3, EU, false}, - {0x5E31EA42, MetalGearSolid3, EU, false}, - {0x278722BF, DBZBT2, US, false}, - {0xFE961D28, DBZBT2, US, false}, - {0x0393B6BE, DBZBT2, EU, false}, - {0xE2F289ED, DBZBT2, JP, false}, // Sparking Neo! - {0x35AA84D1, DBZBT2, Unknown, false}, - {0x428113C2, DBZBT3, US, false}, - {0xA422BB13, DBZBT3, EU, false}, - {0x983c53d2, DBZBT3, Unknown, false}, - {0x72B3802A, SFEX3, US, false}, - {0x71521863, SFEX3, US, false}, - {0x28703748, Bully, US, false}, - {0xC78A495D, BullyCC, US, false}, - {0xC19A374E, SoTC, US, false}, - {0x7D8F539A, SoTC, EU, false}, - {0x3122B508, OnePieceGrandAdventure, US, false}, - {0x6F8545DB, ICO, US, false}, - {0xB01A4C95, ICO, JP, false}, - {0x5C991F4E, ICO, Unknown, false}, - {0xAEAD1CA3, GT4, JP, false}, - {0x44A61C8F, GT4, Unknown, false}, - {0x0086E35B, GT4, Unknown, false}, - {0x77E61C8A, GT4, Unknown, false}, - {0xC164550A, WildArms5, JPUNDUB, false}, - {0xC1640D2C, WildArms5, US, false}, - {0x0FCF8FE4, WildArms5, EU, false}, - {0x2294D322, WildArms5, JP, false}, - {0x565B6170, WildArms5, JP, false}, - {0x8B029334, Manhunt2, Unknown, false}, - {0x09F49E37, CrashBandicootWoC, Unknown, false}, - {0x013E349D, ResidentEvil4, US, false}, - {0x6BA2F6B9, ResidentEvil4, Unknown, false}, - {0x60FA8C69, ResidentEvil4, JP, false}, - {0x72E1E60E, Spartan, Unknown, false}, - {0x5ED8FB53, AceCombat4, JP, false}, - {0x1B9B7563, AceCombat4, Unknown, false}, - {0xEC432B24, Drakengard2, Unknown, false}, - {0xFC46EA61, Tekken5, JP, false}, - {0x1F88EE37, Tekken5, Unknown, false}, - {0x652050D2, Tekken5, Unknown, false}, - {0x9E98B8AE, IkkiTousen, JP, false}, - {0xD6385328, GodOfWar, US, false}, - {0xFB0E6D72, GodOfWar, EU, false}, - {0xEB001875, GodOfWar, EU, false}, - {0xA61A4C6D, GodOfWar, Unknown, false}, - {0xE23D532B, GodOfWar, Unknown, false}, - {0x2F123FD8, GodOfWar2, RU, false}, - {0x2F123FD8, GodOfWar2, US, false}, - {0x44A8A22A, GodOfWar2, EU, false}, - {0x5D482F18, JackieChanAdv, Unknown, false}, - {0xf0a6d880, HarvestMoon, US, true}, - {0x75c01a04, NamcoXCapcom, US, false}, - {0xBF6F101F, GiTS, US, false}, - {0xA5768F53, GiTS, JP, false}, - {0x6BF11378, Onimusha3, US, false}, - {0xF442260C, MajokkoALaMode2, JP, false}, - {0x14FE77F7, TalesOfAbyss, US, false}, - {0x045D77E9, TalesOfAbyss, US, false}, // undub - {0xAA5EC3A3, TalesOfAbyss, JP, false}, + {0x00000000, None, Unknown}, + {0x2113EA2E, MetalSlug6, Unknown}, + {0x42E05BAF, TomoyoAfter, JP}, + {0x7800DC84, Clannad, JP}, + {0xa39517ab, FFX, EU}, + {0xa39517ae, FFX, FR}, + {0x941bb7d9, FFX, DE}, + {0xa39517a9, FFX, IT}, + {0x941bb7de, FFX, ES}, + {0xb4414ea1, FFX, RU}, + {0xee97db5b, FFX, RU}, + {0xaec495cc, FFX, RU}, + {0xbb3d833a, FFX, US}, + {0x6a4efe60, FFX, JP}, + {0x3866ca7e, FFX, ASIA}, // int. + {0x658597e2, FFX, JP}, // int. + {0x9aac5309, FFX2, EU}, + {0x9aac530c, FFX2, FR}, + {0x9aac530a, FFX2, FR}, // ? + {0x9aac530d, FFX2, DE}, + {0x9aac530b, FFX2, IT}, + {0x48fe0c71, FFX2, US}, + {0xe1fd9a2d, FFX2, JP}, // int. + {0x78da0252, FFXII, EU}, + {0xc1274668, FFXII, EU}, + {0xdc2a467e, FFXII, EU}, + {0xca284668, FFXII, EU}, + {0x280AD120, FFXII, JP}, + {0x8BE3D7B2, ShadowHearts, Unknown}, + {0xDEFA4763, ShadowHearts, US}, + {0x21068223, Okami, US}, + {0x891f223f, Okami, FR}, + {0xC5DEFEA0, Okami, JP}, + {0x053D2239, MetalGearSolid3, US}, + {0x086273D2, MetalGearSolid3, FR}, + {0x26A6E286, MetalGearSolid3, EU}, + {0xAA31B5BF, MetalGearSolid3, Unknown}, + {0x9F185CE1, MetalGearSolid3, Unknown}, + {0x98D4BC93, MetalGearSolid3, EU}, + {0x86BC3040, MetalGearSolid3, US}, //Subsistance disc 1 + {0x0481AD8A, MetalGearSolid3, JP}, + {0x79ED26AD, MetalGearSolid3, EU}, + {0x5E31EA42, MetalGearSolid3, EU}, + {0x278722BF, DBZBT2, US}, + {0xFE961D28, DBZBT2, US}, + {0x0393B6BE, DBZBT2, EU}, + {0xE2F289ED, DBZBT2, JP}, // Sparking Neo! + {0x35AA84D1, DBZBT2, Unknown}, + {0x428113C2, DBZBT3, US}, + {0xA422BB13, DBZBT3, EU}, + {0x983c53d2, DBZBT3, Unknown}, + {0x72B3802A, SFEX3, US}, + {0x71521863, SFEX3, US}, + {0x28703748, Bully, US}, + {0xC78A495D, BullyCC, US}, + {0xC19A374E, SoTC, US}, + {0x7D8F539A, SoTC, EU}, + {0x3122B508, OnePieceGrandAdventure, US}, + {0x6F8545DB, ICO, US}, + {0xB01A4C95, ICO, JP}, + {0x5C991F4E, ICO, Unknown}, + {0xAEAD1CA3, GT4, JP}, + {0x44A61C8F, GT4, Unknown}, + {0x0086E35B, GT4, Unknown}, + {0x77E61C8A, GT4, Unknown}, + {0xC164550A, WildArms5, JPUNDUB}, + {0xC1640D2C, WildArms5, US}, + {0x0FCF8FE4, WildArms5, EU}, + {0x2294D322, WildArms5, JP}, + {0x565B6170, WildArms5, JP}, + {0x8B029334, Manhunt2, Unknown}, + {0x09F49E37, CrashBandicootWoC, Unknown}, + {0x013E349D, ResidentEvil4, US}, + {0x6BA2F6B9, ResidentEvil4, Unknown}, + {0x60FA8C69, ResidentEvil4, JP}, + {0x72E1E60E, Spartan, Unknown}, + {0x5ED8FB53, AceCombat4, JP}, + {0x1B9B7563, AceCombat4, Unknown}, + {0xEC432B24, Drakengard2, Unknown}, + {0xFC46EA61, Tekken5, JP}, + {0x1F88EE37, Tekken5, Unknown}, + {0x652050D2, Tekken5, Unknown}, + {0x9E98B8AE, IkkiTousen, JP}, + {0xD6385328, GodOfWar, US}, + {0xFB0E6D72, GodOfWar, EU}, + {0xEB001875, GodOfWar, EU}, + {0xA61A4C6D, GodOfWar, Unknown}, + {0xE23D532B, GodOfWar, Unknown}, + {0x2F123FD8, GodOfWar2, RU}, + {0x2F123FD8, GodOfWar2, US}, + {0x44A8A22A, GodOfWar2, EU}, + {0X4340C7C6, GodOfWar2, Unknown}, + {0x5D482F18, JackieChanAdv, Unknown}, + {0xf0a6d880, HarvestMoon, US}, + {0x75c01a04, NamcoXCapcom, US}, + {0xBF6F101F, GiTS, US}, + {0xA5768F53, GiTS, JP}, + {0x6BF11378, Onimusha3, US}, + {0xF442260C, MajokkoALaMode2, JP}, + {0x14FE77F7, TalesOfAbyss, US}, + {0x045D77E9, TalesOfAbyss, US}, // undub + {0xAA5EC3A3, TalesOfAbyss, JP}, }; CAtlMap CRC::m_map; diff --git a/plugins/GSdx/GSCrc.h b/plugins/GSdx/GSCrc.h index 89efaf71d8..12f41bd93f 100644 --- a/plugins/GSdx/GSCrc.h +++ b/plugins/GSdx/GSCrc.h @@ -86,7 +86,6 @@ public: DWORD crc; Title title; Region region; - bool nloophack; }; private: diff --git a/plugins/GSdx/GSDevice9.cpp b/plugins/GSdx/GSDevice9.cpp index f8414a36e0..03984fc848 100644 --- a/plugins/GSdx/GSDevice9.cpp +++ b/plugins/GSdx/GSDevice9.cpp @@ -266,10 +266,7 @@ bool GSDevice9::Reset(int w, int h, bool fs) m_pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; } - if(!!AfxGetApp()->GetProfileInt(_T("Settings"), _T("tvout"), FALSE)) - { - m_pp.Flags |= D3DPRESENTFLAG_VIDEO; - } + // m_pp.Flags |= D3DPRESENTFLAG_VIDEO; // enables tv-out (but I don't think anyone would still use a regular tv...) int mw = AfxGetApp()->GetProfileInt(_T("Settings"), _T("ModeWidth"), 0); int mh = AfxGetApp()->GetProfileInt(_T("Settings"), _T("ModeHeight"), 0); diff --git a/plugins/GSdx/GSDrawingEnvironment.h b/plugins/GSdx/GSDrawingEnvironment.h index 557deab56b..dfca1aa953 100644 --- a/plugins/GSdx/GSDrawingEnvironment.h +++ b/plugins/GSdx/GSDrawingEnvironment.h @@ -43,7 +43,6 @@ public: GIFRegTRXDIR TRXDIR; GIFRegTRXPOS TRXPOS; GIFRegTRXREG TRXREG; - GIFRegTRXREG TRXREG2; GSDrawingContext CTXT[2]; GSDrawingEnvironment() @@ -67,7 +66,6 @@ public: memset(&TRXDIR, 0, sizeof(TRXDIR)); memset(&TRXPOS, 0, sizeof(TRXPOS)); memset(&TRXREG, 0, sizeof(TRXREG)); - memset(&TRXREG2, 0, sizeof(TRXREG2)); CTXT[0].Reset(); CTXT[1].Reset(); diff --git a/plugins/GSdx/GSLocalMemory.cpp b/plugins/GSdx/GSLocalMemory.cpp index 27a26e46a2..b86c6ce8b8 100644 --- a/plugins/GSdx/GSLocalMemory.cpp +++ b/plugins/GSdx/GSLocalMemory.cpp @@ -896,7 +896,7 @@ void GSLocalMemory::WriteImage(int& tx, int& ty, BYTE* src, int len, GIFRegBITBL if(TRXREG.RRW == 0) return; int l = (int)TRXPOS.DSAX; - int r = (int)TRXREG.RRW; + int r = l + (int)TRXREG.RRW; // finish the incomplete row first @@ -913,9 +913,7 @@ void GSLocalMemory::WriteImage(int& tx, int& ty, BYTE* src, int len, GIFRegBITBL int srcpitch = (r - l) * trbpp >> 3; int h = len / srcpitch; - // transfer width >= block width, and there is at least one full row - - if(ra - la >= bsx && h > 0) + if(ra - la >= bsx && h > 0) // "transfer width" >= "block width" && there is at least one full row { BYTE* s = &src[-l * trbpp >> 3]; @@ -1009,7 +1007,7 @@ void GSLocalMemory::WriteImage24(int& tx, int& ty, BYTE* src, int len, GIFRegBIT DWORD bp = BITBLTBUF.DBP; DWORD bw = BITBLTBUF.DBW; - int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) * 3; + int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW * 3; int th = len / srcpitch; bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); @@ -1035,6 +1033,7 @@ void GSLocalMemory::WriteImage24(int& tx, int& ty, BYTE* src, int len, GIFRegBIT ty = th; } } + void GSLocalMemory::WriteImage8H(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) { if(TRXREG.RRW == 0) return; @@ -1042,7 +1041,7 @@ void GSLocalMemory::WriteImage8H(int& tx, int& ty, BYTE* src, int len, GIFRegBIT DWORD bp = BITBLTBUF.DBP; DWORD bw = BITBLTBUF.DBW; - int tw = TRXREG.RRW, srcpitch = TRXREG.RRW - TRXPOS.DSAX; + int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW; int th = len / srcpitch; bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); @@ -1076,7 +1075,7 @@ void GSLocalMemory::WriteImage4HL(int& tx, int& ty, BYTE* src, int len, GIFRegBI DWORD bp = BITBLTBUF.DBP; DWORD bw = BITBLTBUF.DBW; - int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) / 2; + int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW / 2; int th = len / srcpitch; bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); @@ -1110,7 +1109,7 @@ void GSLocalMemory::WriteImage4HH(int& tx, int& ty, BYTE* src, int len, GIFRegBI DWORD bp = BITBLTBUF.DBP; DWORD bw = BITBLTBUF.DBW; - int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) / 2; + int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW / 2; int th = len / srcpitch; bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); @@ -1143,7 +1142,7 @@ void GSLocalMemory::WriteImage24Z(int& tx, int& ty, BYTE* src, int len, GIFRegBI DWORD bp = BITBLTBUF.DBP; DWORD bw = BITBLTBUF.DBW; - int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) * 3; + int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW * 3; int th = len / srcpitch; bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); @@ -1173,8 +1172,6 @@ void GSLocalMemory::WriteImageX(int& tx, int& ty, BYTE* src, int len, GIFRegBITB { if(len <= 0) return; - // if(ty >= (int)TRXREG.RRH) {ASSERT(0); return;} - BYTE* pb = (BYTE*)src; WORD* pw = (WORD*)src; DWORD* pd = (DWORD*)src; @@ -1186,7 +1183,7 @@ void GSLocalMemory::WriteImageX(int& tx, int& ty, BYTE* src, int len, GIFRegBITB int x = tx; int y = ty; int sx = (int)TRXPOS.DSAX; - int ex = (int)TRXREG.RRW; + int ex = sx + (int)TRXREG.RRW; switch(BITBLTBUF.DPSM) { @@ -1351,8 +1348,6 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, BYTE* dst, int len, GIFRegBITBL { if(len <= 0) return; - // if(ty >= (int)TRXREG.RRH) {ASSERT(0); return;} - BYTE* pb = (BYTE*)dst; WORD* pw = (WORD*)dst; DWORD* pd = (DWORD*)dst; @@ -1364,7 +1359,7 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, BYTE* dst, int len, GIFRegBITBL int x = tx; int y = ty; int sx = (int)TRXPOS.SSAX; - int ex = (int)TRXREG.RRW; + int ex = sx + (int)TRXREG.RRW; switch(BITBLTBUF.SPSM) { diff --git a/plugins/GSdx/GSRenderer.h b/plugins/GSdx/GSRenderer.h index f7a5b05df0..56bd999fb7 100644 --- a/plugins/GSdx/GSRenderer.h +++ b/plugins/GSdx/GSRenderer.h @@ -67,36 +67,25 @@ protected: { int step = (::GetAsyncKeyState(VK_SHIFT) & 0x8000) ? -1 : 1; - if(msg.wParam == VK_F5) + switch(msg.wParam) { + case VK_F5: m_interlace = (m_interlace + 7 + step) % 7; return true; - } - - if(msg.wParam == VK_F6) - { + case VK_F6: m_aspectratio = (m_aspectratio + 3 + step) % 3; return true; - } - - if(msg.wParam == VK_F7) - { + case VK_F7: m_wnd.SetWindowText(_T("PCSX2")); m_osd = !m_osd; return true; - } - - if(msg.wParam == VK_DELETE) - { + case VK_DELETE: m_aa1 = !m_aa1; return true; - } - - if(msg.wParam == VK_END) - { + case VK_END: m_blur = !m_blur; return true; - } + } } return false; @@ -106,8 +95,8 @@ public: GSWnd m_wnd; public: - GSRendererBase(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs) - : GSState(base, mt, irq, nloophack) + GSRendererBase(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs) + : GSState(base, mt, irq) , m_osd(true) { m_interlace = rs.m_interlace; @@ -398,17 +387,11 @@ protected: { if(msg.message == WM_KEYDOWN) { - if(msg.wParam == VK_F12) + switch(msg.wParam) { - if(m_capture.IsCapturing()) - { - m_capture.EndCapture(); - } - else - { - m_capture.BeginCapture(GetFPS()); - } - + case VK_F12: + if(m_capture.IsCapturing()) m_capture.EndCapture(); + else m_capture.BeginCapture(GetFPS()); return true; } } @@ -429,8 +412,8 @@ public: GSCapture m_capture; public: - GSRenderer(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, bool psrr) - : GSRendererBase(base, mt, irq, nloophack, rs) + GSRenderer(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs, bool psrr) + : GSRendererBase(base, mt, irq, rs) , m_psrr(psrr) { s_n = 0; @@ -704,8 +687,8 @@ protected: virtual void Draw() = 0; public: - GSRendererT(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, bool psrr = true) - : GSRenderer(base, mt, irq, nloophack, rs, psrr) + GSRendererT(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs, bool psrr = true) + : GSRenderer(base, mt, irq, rs, psrr) , m_count(0) , m_maxcount(0) , m_vertices(NULL) diff --git a/plugins/GSdx/GSRendererHW.h b/plugins/GSdx/GSRendererHW.h index 2ad320f9e8..31c5673c9b 100644 --- a/plugins/GSdx/GSRendererHW.h +++ b/plugins/GSdx/GSRendererHW.h @@ -349,8 +349,6 @@ protected: OverrideOutput(); - m_tc->InvalidateTextures(context->FRAME, context->ZBUF); - if(s_dump) { CString str; @@ -360,6 +358,8 @@ protected: if(s_savez) ds->m_texture.Save(str); // if(s_savez) m_dev.SaveToFileD32S8X24(ds->m_texture, str); // TODO } + + m_tc->InvalidateTextures(context->FRAME, context->ZBUF); } virtual void Draw(int prim, Texture& rt, Texture& ds, typename GSTextureCache::GSTexture* tex) = 0; @@ -507,6 +507,35 @@ protected: #pragma endregion + #pragma region GoW2 z buffer clear + + if(m_game.title == CRC::GodOfWar2) + { + DWORD FBP = m_context->FRAME.Block(); + DWORD FBW = m_context->FRAME.FBW; + DWORD FPSM = m_context->FRAME.PSM; + + if((FBP == 0x00f00 || FBP == 0x00100) && FPSM == PSM_PSMZ24) // ntsc 0xf00, pal 0x100 + { + GIFRegTEX0 TEX0; + + TEX0.TBP0 = FBP; + TEX0.TBW = FBW; + TEX0.PSM = FPSM; + + if(GSTextureCache::GSDepthStencil* ds = m_tc->GetDepthStencil(TEX0, m_width, m_height)) + { + m_dev.ClearDepth(ds->m_texture, 0); + } + + return false; + } + + return true; + } + + #pragma endregion + return true; } @@ -602,8 +631,8 @@ protected: } public: - GSRendererHW(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, bool psrr) - : GSRendererT(base, mt, irq, nloophack, rs, psrr) + GSRendererHW(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs, bool psrr) + : GSRendererT(base, mt, irq, rs, psrr) , m_width(1024) , m_height(1024) , m_skip(0) diff --git a/plugins/GSdx/GSRendererHW10.cpp b/plugins/GSdx/GSRendererHW10.cpp index 28447fbf44..3fd9ccb9d7 100644 --- a/plugins/GSdx/GSRendererHW10.cpp +++ b/plugins/GSdx/GSRendererHW10.cpp @@ -24,8 +24,8 @@ #include "GSCrc.h" #include "resource.h" -GSRendererHW10::GSRendererHW10(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs) - : GSRendererHW(base, mt, irq, nloophack, rs, true) +GSRendererHW10::GSRendererHW10(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs) + : GSRendererHW(base, mt, irq, rs, true) { InitVertexKick(); } diff --git a/plugins/GSdx/GSRendererHW10.h b/plugins/GSdx/GSRendererHW10.h index b1b069ee22..a9985dfc0f 100644 --- a/plugins/GSdx/GSRendererHW10.h +++ b/plugins/GSdx/GSRendererHW10.h @@ -48,7 +48,7 @@ protected: void SetupDATE(Texture& rt, Texture& ds); public: - GSRendererHW10(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs); + GSRendererHW10(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs); bool Create(LPCTSTR title); diff --git a/plugins/GSdx/GSRendererHW9.cpp b/plugins/GSdx/GSRendererHW9.cpp index 009d924f81..4459094f1d 100644 --- a/plugins/GSdx/GSRendererHW9.cpp +++ b/plugins/GSdx/GSRendererHW9.cpp @@ -24,8 +24,8 @@ #include "GSCrc.h" #include "resource.h" -GSRendererHW9::GSRendererHW9(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs) - : GSRendererHW(base, mt, irq, nloophack, rs, false) +GSRendererHW9::GSRendererHW9(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs) + : GSRendererHW(base, mt, irq, rs, false) { m_fba.enabled = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("fba"), TRUE); m_logz = !!AfxGetApp()->GetProfileInt(_T("Settings"), _T("logz"), FALSE); diff --git a/plugins/GSdx/GSRendererHW9.h b/plugins/GSdx/GSRendererHW9.h index bc9c7cb030..c91a0cb42d 100644 --- a/plugins/GSdx/GSRendererHW9.h +++ b/plugins/GSdx/GSRendererHW9.h @@ -57,7 +57,7 @@ protected: void UpdateFBA(Texture& rt); public: - GSRendererHW9(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs); + GSRendererHW9(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs); bool Create(LPCTSTR title); diff --git a/plugins/GSdx/GSRendererNull.h b/plugins/GSdx/GSRendererNull.h index 7af3baaa88..bb9152443e 100644 --- a/plugins/GSdx/GSRendererNull.h +++ b/plugins/GSdx/GSRendererNull.h @@ -37,8 +37,8 @@ protected: } public: - GSRendererNull(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs) - : GSRendererT(base, mt, irq, nloophack, rs) + GSRendererNull(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs) + : GSRendererT(base, mt, irq, rs) { InitVertexKick >(); } diff --git a/plugins/GSdx/GSRendererSW.h b/plugins/GSdx/GSRendererSW.h index 0d47499b06..178800736d 100644 --- a/plugins/GSdx/GSRendererSW.h +++ b/plugins/GSdx/GSRendererSW.h @@ -717,8 +717,8 @@ protected: } public: - GSRendererSW(BYTE* base, bool mt, void (*irq)(), int nloophack, const GSRendererSettings& rs, int threads) - : GSRendererT(base, mt, irq, nloophack, rs) + GSRendererSW(BYTE* base, bool mt, void (*irq)(), const GSRendererSettings& rs, int threads) + : GSRendererT(base, mt, irq, rs) { m_rl.Create(this, threads); diff --git a/plugins/GSdx/GSSettingsDlg.cpp b/plugins/GSdx/GSSettingsDlg.cpp index 1e1ed74446..333744a560 100644 --- a/plugins/GSdx/GSSettingsDlg.cpp +++ b/plugins/GSdx/GSSettingsDlg.cpp @@ -68,9 +68,7 @@ GSSetting GSSettingsDlg::g_aspectratio[] = IMPLEMENT_DYNAMIC(GSSettingsDlg, CDialog) GSSettingsDlg::GSSettingsDlg(CWnd* pParent /*=NULL*/) : CDialog(GSSettingsDlg::IDD, pParent) - , m_tvout(FALSE) , m_filter(1) - , m_nloophack(2) , m_nativeres(FALSE) , m_vsync(FALSE) , m_logz(FALSE) @@ -104,9 +102,7 @@ void GSSettingsDlg::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, IDC_COMBO4, m_psversion); DDX_Control(pDX, IDC_COMBO2, m_interlace); DDX_Control(pDX, IDC_COMBO5, m_aspectratio); - DDX_Check(pDX, IDC_CHECK3, m_tvout); DDX_Check(pDX, IDC_CHECK4, m_filter); - DDX_Check(pDX, IDC_CHECK6, m_nloophack); DDX_Control(pDX, IDC_SPIN1, m_resx); DDX_Control(pDX, IDC_SPIN2, m_resy); DDX_Control(pDX, IDC_SPIN3, m_swthreads); @@ -219,8 +215,6 @@ BOOL GSSettingsDlg::OnInitDialog() // m_filter = pApp->GetProfileInt(_T("Settings"), _T("filter"), 1); - m_tvout = pApp->GetProfileInt(_T("Settings"), _T("tvout"), FALSE); - m_nloophack = pApp->GetProfileInt(_T("Settings"), _T("nloophack"), 2); m_vsync = !!pApp->GetProfileInt(_T("Settings"), _T("vsync"), FALSE); m_logz = !!pApp->GetProfileInt(_T("Settings"), _T("logz"), FALSE); m_fba = !!pApp->GetProfileInt(_T("Settings"), _T("fba"), TRUE); @@ -284,8 +278,6 @@ void GSSettingsDlg::OnOK() } pApp->WriteProfileInt(_T("Settings"), _T("filter"), m_filter); - pApp->WriteProfileInt(_T("Settings"), _T("tvout"), m_tvout); - pApp->WriteProfileInt(_T("Settings"), _T("nloophack"), m_nloophack); pApp->WriteProfileInt(_T("Settings"), _T("vsync"), m_vsync); pApp->WriteProfileInt(_T("Settings"), _T("logz"), m_logz); pApp->WriteProfileInt(_T("Settings"), _T("fba"), m_fba); diff --git a/plugins/GSdx/GSSettingsDlg.h b/plugins/GSdx/GSSettingsDlg.h index b21137cd66..e2b68c41bf 100644 --- a/plugins/GSdx/GSSettingsDlg.h +++ b/plugins/GSdx/GSSettingsDlg.h @@ -47,9 +47,7 @@ public: CComboBox m_psversion; CComboBox m_interlace; CComboBox m_aspectratio; - BOOL m_tvout; int m_filter; - int m_nloophack; CSpinButtonCtrl m_resx; CSpinButtonCtrl m_resy; CSpinButtonCtrl m_swthreads; diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index ff17150ec4..11d681a337 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -22,11 +22,9 @@ #include "stdafx.h" #include "GSState.h" -GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) +GSState::GSState(BYTE* base, bool mt, void (*irq)()) : m_mt(mt) , m_irq(irq) - , m_nloophack_org(nloophack) - , m_nloophack(nloophack == 1) , m_crc(0) , m_options(0) , m_path3hack(0) @@ -54,7 +52,7 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) m_sssize += sizeof(m_env.TRXDIR); m_sssize += sizeof(m_env.TRXPOS); m_sssize += sizeof(m_env.TRXREG); - m_sssize += sizeof(m_env.TRXREG2); + m_sssize += sizeof(m_env.TRXREG); // obsolete for(int i = 0; i < 2; i++) { @@ -79,8 +77,8 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) m_sssize += sizeof(m_v.XYZ); m_sssize += sizeof(m_v.FOG); - m_sssize += sizeof(m_x); - m_sssize += sizeof(m_y); + m_sssize += sizeof(m_tr.x); + m_sssize += sizeof(m_tr.y); m_sssize += m_mem.m_vmsize; m_sssize += (sizeof(m_path[0].tag) + sizeof(m_path[0].nreg)) * 3; m_sssize += sizeof(m_q); @@ -95,11 +93,6 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) // CSR->rREV = 0x20; m_env.PRMODECONT.AC = 1; - m_x = m_y = 0; - m_bytes = 0; - m_maxbytes = 1024 * 1024 * 4; - m_buff = (BYTE*)_aligned_malloc(m_maxbytes, 16); - Reset(); ResetHandlers(); @@ -107,7 +100,6 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)(), int nloophack) GSState::~GSState() { - _aligned_free(m_buff); } void GSState::Reset() @@ -918,13 +910,12 @@ void GSState::GIFRegHandlerTRXPOS(GIFReg* r) void GSState::GIFRegHandlerTRXREG(GIFReg* r) { - if(!(m_env.TRXREG == (GSVector4i)r->TRXREG).alltrue() || !(m_env.TRXREG2 == (GSVector4i)r->TRXREG).alltrue()) + if(!(m_env.TRXREG == (GSVector4i)r->TRXREG).alltrue()) { FlushWrite(); } m_env.TRXREG = (GSVector4i)r->TRXREG; - m_env.TRXREG2 = (GSVector4i)r->TRXREG; } void GSState::GIFRegHandlerTRXDIR(GIFReg* r) @@ -936,16 +927,10 @@ void GSState::GIFRegHandlerTRXDIR(GIFReg* r) switch(m_env.TRXDIR.XDIR) { case 0: // host -> local - m_x = m_env.TRXPOS.DSAX; - m_y = m_env.TRXPOS.DSAY; - m_env.TRXREG.RRW = m_x + m_env.TRXREG2.RRW; - m_env.TRXREG.RRH = m_y + m_env.TRXREG2.RRH; + m_tr.Init(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY); break; case 1: // local -> host - m_x = m_env.TRXPOS.SSAX; - m_y = m_env.TRXPOS.SSAY; - m_env.TRXREG.RRW = m_x + m_env.TRXREG2.RRW; - m_env.TRXREG.RRH = m_y + m_env.TRXREG2.RRH; + m_tr.Init(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY); break; case 2: // local -> local Move(); @@ -999,113 +984,66 @@ void GSState::Flush() void GSState::FlushWrite() { - FlushWrite(m_buff, m_bytes); + int len = m_tr.end - m_tr.start; - m_bytes = 0; -} + if(len <= 0) return; -void GSState::FlushWrite(BYTE* mem, int len) -{ - if(len > 0) - { + int y = m_tr.y; + + GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi; + + (m_mem.*wi)(m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); + + m_tr.start += len; + + m_perfmon.Put(GSPerfMon::Swizzle, len); + + CRect r; + + r.left = m_env.TRXPOS.DSAX; + r.top = y; + r.right = r.left + m_env.TRXREG.RRW; + r.bottom = min(r.top + m_env.TRXREG.RRH, m_tr.x == r.left ? m_tr.y : m_tr.y + 1); + + InvalidateVideoMem(m_env.BITBLTBUF, r); /* -CSize bs = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].bs; - -if((m_x & (bs.cx - 1)) || (m_env.TRXREG.RRW & (bs.cx - 1)) -|| (m_y & (bs.cy - 1)) || (m_env.TRXREG.RRH & (bs.cy - 1)) -|| m_x != m_env.TRXPOS.DSAX) -{ - printf("*** [%d]: %d %d, %d %d %d %d\n", m_env.BITBLTBUF.DPSM, m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_x, m_y, m_env.TRXREG.RRW, m_env.TRXREG.RRH); -} - -if((len % ((m_env.TRXREG.RRW - m_x) * GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp / 8)) != 0) -{ - printf("*** [%d]: %d %d\n", m_env.BITBLTBUF.DPSM, len, ((m_env.TRXREG.RRW - m_x) * GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp / 8)); -} + static int n = 0; + CString str; + str.Format(_T("c:\\temp1\\[%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp"), + n++, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, + r.left, r.top, r.right, r.bottom); + m_mem.SaveBMP(str, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM, r.right, r.bottom); */ - int y = m_y; - - GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi; - - (m_mem.*wi)(m_x, m_y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); - - m_perfmon.Put(GSPerfMon::Swizzle, len); - - //ASSERT(m_env.TRXREG.RRH >= m_y - y); - - CRect r; - - r.left = m_env.TRXPOS.DSAX; - r.top = y; - r.right = m_env.TRXREG.RRW; - r.bottom = min(m_x == m_env.TRXPOS.DSAX ? m_y : m_y + 1, m_env.TRXREG.RRH); - - InvalidateVideoMem(m_env.BITBLTBUF, r); -/* - static int n = 0; - CString str; - str.Format(_T("c:\\temp1\\[%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp"), - n++, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, - r.left, r.top, r.right, r.bottom); - m_mem.SaveBMP(str, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM, r.right, r.bottom); -*/ - } } // void GSState::Write(BYTE* mem, int len) { -/* - TRACE(_T("Write len=%d DBP=%05x DBW=%d DPSM=%d DSAX=%d DSAY=%d RRW=%d RRH=%d\n"), - len, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, - (int)m_env.TRXPOS.DSAX, (int)m_env.TRXPOS.DSAY, - (int)m_env.TRXREG.RRW, (int)m_env.TRXREG.RRH); -*/ - if(len == 0) return; + int dx = m_env.TRXPOS.DSAX; + int dy = m_env.TRXPOS.DSAY; + int w = m_env.TRXREG.RRW; + int h = m_env.TRXREG.RRH; - if(m_y >= m_env.TRXREG.RRH) return; // TODO: handle overflow during writing data too (just chop len below somewhere) + // TRACE(_T("Write len=%d DBP=%05x DBW=%d DPSM=%d DSAX=%d DSAY=%d RRW=%d RRH=%d\n"), len, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, dx, dy, w, h); - // TODO: hmmmm + if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp, len)) + { + return; + } - if(PRIM->TME && (m_env.BITBLTBUF.DBP == m_context->TEX0.TBP0 || m_env.BITBLTBUF.DBP == m_context->TEX0.CBP)) + memcpy(&m_tr.buff[m_tr.end], mem, len); + + m_tr.end += len; + + if(PRIM->TME && (m_env.BITBLTBUF.DBP == m_context->TEX0.TBP0 || m_env.BITBLTBUF.DBP == m_context->TEX0.CBP)) // TODO: hmmmm { FlushPrim(); } - int bpp = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp; - - int pitch = (m_env.TRXREG.RRW - m_env.TRXPOS.DSAX) * bpp >> 3; - - if(pitch <= 0) {ASSERT(0); return;} - - int height = len / pitch; - - if(height > m_env.TRXREG.RRH - m_env.TRXPOS.DSAY) + if(m_tr.end >= m_tr.total) { - height = m_env.TRXREG.RRH - m_env.TRXPOS.DSAY; - - len = height * pitch; - } - - if(m_bytes > 0 || height < m_env.TRXREG.RRH - m_env.TRXPOS.DSAY) - { - ASSERT(len <= m_maxbytes); // more than 4mb into a 4mb local mem doesn't make sense - - len = min(m_maxbytes, len); - - if(m_bytes + len > m_maxbytes) - { - FlushWrite(); - } - - memcpy(&m_buff[m_bytes], mem, len); - - m_bytes += len; - } - else - { - FlushWrite(mem, len); + FlushWrite(); } m_mem.m_clut.Invalidate(); @@ -1113,25 +1051,26 @@ void GSState::Write(BYTE* mem, int len) void GSState::Read(BYTE* mem, int len) { - /* - TRACE(_T("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n"), - len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, - (int)m_env.TRXPOS.SSAX, (int)m_env.TRXPOS.SSAY, - (int)m_env.TRXREG.RRW, (int)m_env.TRXREG.RRH); - */ + if(len <= 0) return; - if(m_y >= (int)m_env.TRXREG.RRH) {ASSERT(0); return;} + int sx = m_env.TRXPOS.SSAX; + int sy = m_env.TRXPOS.SSAY; + int w = m_env.TRXREG.RRW; + int h = m_env.TRXREG.RRH; - if(m_x == m_env.TRXPOS.SSAX && m_y == m_env.TRXPOS.SSAY) + // TRACE(_T("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n"), len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h); + + if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len)) { - CRect r(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY, m_env.TRXREG.RRW, m_env.TRXREG.RRH); - - InvalidateLocalMem(m_env.BITBLTBUF, r); + return; } - // TODO + if(m_tr.x == sx && m_tr.y == sy) + { + InvalidateLocalMem(m_env.BITBLTBUF, CRect(CPoint(sx, sy), CSize(w, h))); + } - m_mem.ReadImageX(m_x, m_y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); + m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); } void GSState::Move() @@ -1140,19 +1079,20 @@ void GSState::Move() // guitar hero copies the far end of the board to do a similar blend too int sx = m_env.TRXPOS.SSAX; - int dx = m_env.TRXPOS.DSAX; int sy = m_env.TRXPOS.SSAY; + int dx = m_env.TRXPOS.DSAX; int dy = m_env.TRXPOS.DSAY; int w = m_env.TRXREG.RRW; int h = m_env.TRXREG.RRH; - int xinc = 1; - int yinc = 1; InvalidateLocalMem(m_env.BITBLTBUF, CRect(CPoint(sx, sy), CSize(w, h))); InvalidateVideoMem(m_env.BITBLTBUF, CRect(CPoint(dx, dy), CSize(w, h))); - if(sx < dx) sx += w-1, dx += w-1, xinc = -1; - if(sy < dy) sy += h-1, dy += h-1, yinc = -1; + int xinc = 1; + int yinc = 1; + + if(sx < dx) {sx += w - 1; dx += w - 1; xinc = -1;} + if(sy < dy) {sy += h - 1; dy += h - 1; yinc = -1;} /* GSLocalMemory::readPixel rp = GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].rp; @@ -1168,7 +1108,7 @@ void GSState::Move() if(m_env.BITBLTBUF.SPSM == PSM_PSMCT32 && m_env.BITBLTBUF.DPSM == PSM_PSMCT32) { - for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc*w, dx -= xinc*w) + for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w) { DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW); int* soffset = spsm.rowOffset[sy & 7]; @@ -1184,7 +1124,7 @@ void GSState::Move() } else { - for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc*w, dx -= xinc*w) + for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w) { DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW); int* soffset = spsm.rowOffset[sy & 7]; @@ -1241,8 +1181,6 @@ template void GSState::Transfer(BYTE* mem, UINT32 size) while(size > 0) { - bool eop = false; - if(path.tag.NLOOP == 0) { path.SetTag(mem); @@ -1250,41 +1188,29 @@ template void GSState::Transfer(BYTE* mem, UINT32 size) mem += sizeof(GIFTag); size--; - m_q = 1.0f; - if(index == 2 && path.tag.EOP) { m_path3hack = 1; } - if(path.tag.PRE) + if(path.tag.NLOOP > 0) // eeuser 7.2.2. GIFtag: "... when NLOOP is 0, the GIF does not output anything, and values other than the EOP field are disregarded." { - ASSERT(path.tag.FLG != GIF_FLG_IMAGE); // kingdom hearts, ffxii, tales of abyss, berserk + m_q = 1.0f; - if((path.tag.FLG & 2) == 0) + if(path.tag.PRE) { - GIFReg r; - r.i64 = path.tag.PRIM; - (this->*m_fpGIFRegHandlers[GIF_A_D_REG_PRIM])(&r); - } - } + ASSERT(path.tag.FLG != GIF_FLG_IMAGE); // kingdom hearts, ffxii, tales of abyss, berserk - if(path.tag.EOP) - { - eop = true; - } - else if(path.tag.NLOOP == 0) - { - if(index == 0 && m_nloophack) - { - continue; + if((path.tag.FLG & 2) == 0) + { + GIFReg r; + r.i64 = path.tag.PRIM; + (this->*m_fpGIFRegHandlers[GIF_A_D_REG_PRIM])(&r); + } } - - eop = true; } } - - if(path.tag.NLOOP > 0) + else { switch(path.tag.FLG) { @@ -1400,21 +1326,12 @@ template void GSState::Transfer(BYTE* mem, UINT32 size) } } - if(eop && ((int)size <= 0 || index == 0)) + if(index == 0) { - break; - } - } - - // FIXME: dq8, pcsx2 error probably - - if(index == 0) - { - if(!path.tag.EOP && path.tag.NLOOP > 0) - { - path.tag.NLOOP = 0; - - TRACE(_T("path1 hack\n")); + if(path.tag.EOP && path.tag.NLOOP == 0) + { + break; + } } } @@ -1422,6 +1339,23 @@ template void GSState::Transfer(BYTE* mem, UINT32 size) { m_dump.Transfer(index, start, mem - start); } + + if(index == 0) + { + if(size == 0 && path.tag.NLOOP > 0) + { + if(m_mt) + { + // TODO + + path.tag.NLOOP = 0; + } + else + { + Transfer<0>(mem - 0x4000, 0x4000 / 16); + } + } + } } template static void WriteState(BYTE*& dst, T* src, size_t len = sizeof(T)) @@ -1469,7 +1403,7 @@ int GSState::Freeze(GSFreezeData* fd, bool sizeonly) WriteState(data, &m_env.TRXDIR); WriteState(data, &m_env.TRXPOS); WriteState(data, &m_env.TRXREG); - WriteState(data, &m_env.TRXREG2); + WriteState(data, &m_env.TRXREG); // obsolete for(int i = 0; i < 2; i++) { @@ -1493,8 +1427,8 @@ int GSState::Freeze(GSFreezeData* fd, bool sizeonly) WriteState(data, &m_v.UV); WriteState(data, &m_v.XYZ); WriteState(data, &m_v.FOG); - WriteState(data, &m_x); - WriteState(data, &m_y); + WriteState(data, &m_tr.x); + WriteState(data, &m_tr.y); WriteState(data, m_mem.m_vm8, m_mem.m_vmsize); for(int i = 0; i < 3; i++) @@ -1550,7 +1484,7 @@ int GSState::Defrost(const GSFreezeData* fd) ReadState(&m_env.TRXDIR, data); ReadState(&m_env.TRXPOS, data); ReadState(&m_env.TRXREG, data); - ReadState(&m_env.TRXREG2, data); + ReadState(&m_env.TRXREG, data); // obsolete for(int i = 0; i < 2; i++) { @@ -1582,10 +1516,12 @@ int GSState::Defrost(const GSFreezeData* fd) ReadState(&m_v.UV, data); ReadState(&m_v.XYZ, data); ReadState(&m_v.FOG, data); - ReadState(&m_x, data); - ReadState(&m_y, data); + ReadState(&m_tr.x, data); + ReadState(&m_tr.y, data); ReadState(m_mem.m_vm8, data, m_mem.m_vmsize); + m_tr.total = 0; // TODO: restore transfer state + for(int i = 0; i < 3; i++) { ReadState(&m_path[i].tag, data); @@ -1617,11 +1553,6 @@ void GSState::SetGameCRC(DWORD crc, int options) m_crc = crc; m_options = options; m_game = CRC::Lookup(crc); - - if(m_nloophack_org == 2) - { - m_nloophack = m_game.nloophack; - } } void GSState::SetFrameSkip(int frameskip) @@ -1683,6 +1614,53 @@ void GSState::SetFrameSkip(int frameskip) } } +// GSTransferBuffer + +GSState::GSTransferBuffer::GSTransferBuffer() +{ + x = y = 0; + start = end = total = 0; + buff = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16); +} + +GSState::GSTransferBuffer::~GSTransferBuffer() +{ + _aligned_free(buff); +} + +void GSState::GSTransferBuffer::Init(int tx, int ty) +{ + x = tx; + y = ty; + total = 0; +} + +bool GSState::GSTransferBuffer::Update(int tw, int th, int bpp, int& len) +{ + if(total == 0) + { + start = end = 0; + total = min((tw * bpp >> 3) * th, 1024 * 1024 * 4); + overflow = false; + } + + int remaining = total - end; + + if(len > remaining) + { + if(!overflow) + { + overflow = true; + + // printf("GS transfer overflow\n"); + } + + len = remaining; + } + + return len > 0; +} + // hacks struct GSFrameInfo @@ -2081,6 +2059,27 @@ bool GSC_GodOfWar(const GSFrameInfo& fi, int& skip) return true; } +bool GSC_GodOfWar2(const GSFrameInfo& fi, int& skip) +{ + if(skip == 0) + { + if(fi.TME && fi.FBP == 0x00100 && fi.FPSM == PSM_PSMCT16 && fi.TBP0 == 0x00100 && fi.TPSM == PSM_PSMCT16 // ntsc + || fi.TME && fi.FBP == 0x02100 && fi.FPSM == PSM_PSMCT16 && fi.TBP0 == 0x02100 && fi.TPSM == PSM_PSMCT16) // pal + { + skip = 29; // shadows + } + else if(fi.TME && fi.FBP == 0x00500 && fi.FPSM == PSM_PSMCT24 && fi.TBP0 == 0x02100 && fi.TPSM == PSM_PSMCT32) // pal + { + // skip = 17; // only looks correct at native resolution + } + } + else + { + } + + return true; +} + bool GSC_GiTS(const GSFrameInfo& fi, int& skip) { if(skip == 0) @@ -2172,7 +2171,7 @@ bool GSState::IsBadFrame(int& skip) map[CRC::Tekken5] = GSC_Tekken5; map[CRC::IkkiTousen] = GSC_IkkiTousen; map[CRC::GodOfWar] = GSC_GodOfWar; - map[CRC::GodOfWar2] = GSC_GodOfWar; + map[CRC::GodOfWar2] = GSC_GodOfWar2; map[CRC::GiTS] = GSC_GiTS; map[CRC::Onimusha3] = GSC_Onimusha3; map[CRC::TalesOfAbyss] = GSC_TalesOfAbyss; diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index 1e1915c0cc..5aeb4fe202 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -112,15 +112,23 @@ class GSState : public GSAlignedClass<16> bool m_mt; void (*m_irq)(); bool m_path3hack; - int m_nloophack_org; - int m_x, m_y; - int m_bytes; - int m_maxbytes; - BYTE* m_buff; + struct GSTransferBuffer + { + int x, y; + int start, end, total; + bool overflow; + BYTE* buff; + + GSTransferBuffer(); + virtual ~GSTransferBuffer(); + + void Init(int tx, int ty); + bool Update(int tw, int th, int bpp, int& len); + + } m_tr; void FlushWrite(); - void FlushWrite(BYTE* mem, int len); protected: bool IsBadFrame(int& skip); @@ -200,7 +208,6 @@ public: DWORD m_vprim; GSPerfMon m_perfmon; - bool m_nloophack; DWORD m_crc; int m_options; int m_frameskip; @@ -208,7 +215,7 @@ public: GSDump m_dump; public: - GSState(BYTE* base, bool mt, void (*irq)(), int nloophack); + GSState(BYTE* base, bool mt, void (*irq)()); virtual ~GSState(); void ResetHandlers(); diff --git a/plugins/GSdx/GSTexture9.cpp b/plugins/GSdx/GSTexture9.cpp index 8d75cc2845..bff9df141c 100644 --- a/plugins/GSdx/GSTexture9.cpp +++ b/plugins/GSdx/GSTexture9.cpp @@ -140,8 +140,8 @@ void GSTexture9::Unmap() bool GSTexture9::Save(CString fn, bool dds) { - CComPtr res; - + CComPtr surface; + if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) { HRESULT hr; @@ -153,8 +153,6 @@ bool GSTexture9::Save(CString fn, bool dds) if(desc.Format != D3DFMT_D32F_LOCKABLE) return false; - CComPtr surface; - hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL); D3DLOCKED_RECT slr, dlr; @@ -175,24 +173,22 @@ bool GSTexture9::Save(CString fn, bool dds) m_surface->UnlockRect(); surface->UnlockRect(); - - res = surface; } else { - res = m_surface; + surface = m_surface; } - if(CComQIPtr surface = res) + if(surface != NULL) { return SUCCEEDED(D3DXSaveSurfaceToFile(fn, dds ? D3DXIFF_DDS : D3DXIFF_BMP, surface, NULL, NULL)); } - - if(CComQIPtr texture = res) +/* + if(CComQIPtr texture = surface) { return SUCCEEDED(D3DXSaveTextureToFile(fn, dds ? D3DXIFF_DDS : D3DXIFF_BMP, texture, NULL)); } - +*/ return false; } diff --git a/plugins/GSdx/GSdx.rc b/plugins/GSdx/GSdx.rc index ea714def56..58ba4fc312 100644 --- a/plugins/GSdx/GSdx.rc +++ b/plugins/GSdx/GSdx.rc @@ -82,7 +82,7 @@ IDB_LOGO10 BITMAP "res\\logo10.bmp" // Dialog // -IDD_CONFIG DIALOGEX 0, 0, 189, 256 +IDD_CONFIG DIALOGEX 0, 0, 189, 248 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings..." FONT 8, "MS Shell Dlg", 400, 0, 0x1 @@ -108,17 +108,15 @@ BEGIN LTEXT "SW rend. threads:",IDC_STATIC,7,149,60,8 EDITTEXT IDC_EDIT3,71,147,35,13,ES_AUTOHSCROLL | ES_NUMBER CONTROL "",IDC_SPIN3,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,99,150,11,14 - CONTROL "NLOOP hack",IDC_CHECK6,"Button",BS_AUTO3STATE | WS_TABSTOP,7,167,55,10 - CONTROL "Enable tv-out",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,167,57,10 - CONTROL "Texture filtering",IDC_CHECK4,"Button",BS_AUTO3STATE | WS_TABSTOP,7,180,67,10 - CONTROL "Logarithmic Z",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,180,58,10 - CONTROL "Wait vsync",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,193,51,10 - CONTROL "Alpha correction (FBA)",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,193,102,10 + CONTROL "Texture filtering",IDC_CHECK4,"Button",BS_AUTO3STATE | WS_TABSTOP,7,167,67,10 + CONTROL "Logarithmic Z",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,168,58,10 + CONTROL "Wait vsync",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,180,51,10 + CONTROL "Alpha correction (FBA)",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,181,102,10 CONTROL "Edge anti-aliasing (AA1, sw-mode only)",IDC_CHECK8, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,206,141,10 - CONTROL "Enable output merger blur effect",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,219,121,10 - DEFPUSHBUTTON "OK",IDOK,43,235,50,14 - PUSHBUTTON "Cancel",IDCANCEL,96,235,50,14 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,194,141,10 + CONTROL "Enable output merger blur effect",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,208,121,10 + DEFPUSHBUTTON "OK",IDOK,43,227,50,14 + PUSHBUTTON "Cancel",IDCANCEL,96,227,50,14 END IDD_CAPTURE DIALOGEX 0, 0, 279, 71 @@ -182,7 +180,7 @@ BEGIN VERTGUIDE, 80 VERTGUIDE, 182 TOPMARGIN, 7 - BOTTOMMARGIN, 249 + BOTTOMMARGIN, 241 END IDD_CAPTURE, DIALOG diff --git a/plugins/LilyPad/Config.cpp b/plugins/LilyPad/Config.cpp index 99769d6c85..e3110b988e 100644 --- a/plugins/LilyPad/Config.cpp +++ b/plugins/LilyPad/Config.cpp @@ -840,9 +840,7 @@ int LoadSettings(int force, wchar_t *file) { } if (config.debug) { - HANDLE hFile = CreateFileA("logs\\padLog.txt", GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); - if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); - else CreateDirectory(L"logs", 0); + CreateDirectory(L"logs", 0); } @@ -1404,18 +1402,59 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l if (i >= 0) { unsigned int index = (unsigned int)SendMessage(GetDlgItem(hWnd, IDC_FORCEFEEDBACK), CB_GETITEMDATA, i, 0); if (index < (unsigned int) dm->numDevices) { + Device *dev = dm->devices[index]; ForceFeedbackBinding *b; - int count = CreateEffectBinding(dm->devices[index], 0, port, slot, cmd-ID_BIG_MOTOR, &b); + int count = CreateEffectBinding(dev, 0, port, slot, cmd-ID_BIG_MOTOR, &b); if (b) { - for (int j=0; j<2 && j devices[index]->numFFAxes; j++) { - b->axes[j].force = BASE_SENSITIVITY; + int needSet = 1; + if (dev->api == XINPUT && dev->numFFAxes == 2) { + needSet = 0; + if (cmd == ID_BIG_MOTOR) { + b->axes[0].force = BASE_SENSITIVITY; + } + else { + b->axes[1].force = BASE_SENSITIVITY; + } + } + else if (dev->api == DI) { + int bigIndex=0, littleIndex=0; + int constantEffect = 0, squareEffect = 0; + int j; + for (j=0; jnumFFAxes; j++) { + // DI object instance. 0 is x-axis, 1 is y-axis. + int instance = (dev->ffAxes[j].id>>8)&0xFFFF; + if (instance == 0) { + bigIndex = j; + } + else if (instance == 1) { + littleIndex = j; + } + } + for (j=0; jnumFFEffectTypes; j++) { + if (!wcsicmp(L"13541C20-8E33-11D0-9AD0-00A0C9A06E35", dev->ffEffectTypes[j].effectID)) constantEffect = j; + if (!wcsicmp(L"13541C22-8E33-11D0-9AD0-00A0C9A06E35", dev->ffEffectTypes[j].effectID)) squareEffect = j; + } + needSet = 0; + if (cmd == ID_BIG_MOTOR) { + b->axes[bigIndex].force = BASE_SENSITIVITY; + b->axes[littleIndex].force = 1; + b->effectIndex = constantEffect; + } + else { + b->axes[bigIndex].force = 1; + b->axes[littleIndex].force = BASE_SENSITIVITY; + b->effectIndex = squareEffect; + } + } + if (needSet) { + for (int j=0; j<2 && j numFFAxes; j++) { + b->axes[j].force = BASE_SENSITIVITY; + } } - } - if (count >= 0) { - PropSheet_Changed(hWndProp, hWnd); UnselectAll(hWndList); ListView_SetItemState(hWndList, count, LVIS_SELECTED, LVIS_SELECTED); } + PropSheet_Changed(hWndProp, hWnd); } } } @@ -1431,7 +1470,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l if (GetBinding(port, slot, selIndex, dev, b, ffb)) { selected = 0xFF; InitInfo info = {0, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; - EatWndProc(info.hWndButton, DoNothingWndProc); + EatWndProc(info.hWndButton, DoNothingWndProc, 0); for (int i=0; inumDevices; i++) { if (dm->devices[i] != dev) { dm->DisableDevice(i); @@ -1466,7 +1505,7 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l } InitInfo info = {selected==0x7F, hWndProp, hWnd, GetDlgItem(hWnd, cmd)}; - EatWndProc(info.hWndButton, DoNothingWndProc); + EatWndProc(info.hWndButton, DoNothingWndProc, 0); int w = timeGetTime(); dm->Update(&info); dm->PostRead(); @@ -1576,7 +1615,7 @@ void UpdatePadList(HWND hWnd) { int slot; int port; int index = 0; - wchar_t *padTypes[] = {L"Disabled", L"Dualshock 2", L"Guitar"}; + wchar_t *padTypes[] = {L"Unplugged", L"Dualshock 2", L"Guitar"}; for (port=0; port<2; port++) { for (slot = 0; slot<4; slot++) { wchar_t text[20]; @@ -1596,6 +1635,9 @@ void UpdatePadList(HWND hWnd) { item.iSubItem = 1; if (2 < (unsigned int)config.padConfigs[port][slot].type) config.padConfigs[port][slot].type = Dualshock2Pad; item.pszText = padTypes[config.padConfigs[port][slot].type]; + if (!slot && !config.padConfigs[port][slot].type) + item.pszText = L"Unplugged (Kinda)"; + ListView_SetItem(hWndList, &item); item.iSubItem = 2; @@ -1644,7 +1686,7 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L c.cx = 50; c.pszText = L"Pad"; ListView_InsertColumn(hWndList, 0, &c); - c.cx = 90; + c.cx = 120; c.pszText = L"Type"; ListView_InsertColumn(hWndList, 1, &c); c.cx = 70; @@ -1867,7 +1909,7 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L InsertMenuItemW(hMenu, index, 1, &info); } else { - info.wID = port2+2*slot2; + info.wID = port2+2*slot2+1; wsprintfW(text, L"Swap with %s", pad); InsertMenuItemW(hMenu, 0, 1, &info); } @@ -1879,12 +1921,14 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L DestroyMenu(hMenu); if (!res) break; if (res > 0) { + res--; slot2 = res / 2; port2 = res&1; PadConfig padCfgTemp = config.padConfigs[port1][slot1]; config.padConfigs[port1][slot1] = config.padConfigs[port2][slot2]; config.padConfigs[port2][slot2] = padCfgTemp; for (int i=0; inumDevices; i++) { + if (dm->devices[i]->type == IGNORE) continue; PadBindings bindings = dm->devices[i]->pads[port1][slot1]; dm->devices[i]->pads[port1][slot1] = dm->devices[i]->pads[port2][slot2]; dm->devices[i]->pads[port2][slot2] = bindings; @@ -1892,6 +1936,7 @@ INT_PTR CALLBACK GeneralDialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, L } else { for (int i=0; inumDevices; i++) { + if (dm->devices[i]->type == IGNORE) continue; free(dm->devices[i]->pads[port1][slot1].bindings); for (int j=0; jdevices[i]->pads[port1][slot1].numFFBindings; j++) { free(dm->devices[i]->pads[port1][slot1].ffBindings[j].axes); diff --git a/plugins/LilyPad/InputManager.cpp b/plugins/LilyPad/InputManager.cpp index 2be1429dca..829ed06f38 100644 --- a/plugins/LilyPad/InputManager.cpp +++ b/plugins/LilyPad/InputManager.cpp @@ -56,9 +56,7 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc void Device::FreeState() { if (virtualControlState) free(virtualControlState); virtualControlState = 0; - if (oldVirtualControlState) free(oldVirtualControlState); oldVirtualControlState = 0; - if (physicalControlState) free(physicalControlState); physicalControlState = 0; } @@ -127,9 +125,9 @@ void Device::AddFFAxis(const wchar_t *displayName, int id) { void Device::AllocState() { FreeState(); - virtualControlState = (int*) calloc(numVirtualControls, sizeof(int)); - oldVirtualControlState = (int*) calloc(numVirtualControls, sizeof(int)); - physicalControlState = (int*) calloc(numPhysicalControls, sizeof(int)); + virtualControlState = (int*) calloc(numVirtualControls + numVirtualControls + numPhysicalControls, sizeof(int)); + oldVirtualControlState = virtualControlState + numVirtualControls; + physicalControlState = oldVirtualControlState + numVirtualControls; } void Device::FlipState() { @@ -213,6 +211,9 @@ VirtualControl *Device::GetVirtualControl(unsigned int uid) { } VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlIndex) { + // Not really necessary, as always call AllocState when activated, but doesn't hurt. + FreeState(); + if (numVirtualControls % 16 == 0) { virtualControls = (VirtualControl*) realloc(virtualControls, sizeof(VirtualControl)*(numVirtualControls+16)); } @@ -226,7 +227,9 @@ VirtualControl *Device::AddVirtualControl(unsigned int uid, int physicalControlI } PhysicalControl *Device::AddPhysicalControl(ControlType type, unsigned short id, unsigned short vkey, const wchar_t *name) { + // Not really necessary, as always call AllocState when activated, but doesn't hurt. FreeState(); + if (numPhysicalControls % 16 == 0) { physicalControls = (PhysicalControl*) realloc(physicalControls, sizeof(PhysicalControl)*(numPhysicalControls+16)); } diff --git a/plugins/LilyPad/KeyboardHook.cpp b/plugins/LilyPad/KeyboardHook.cpp index 0ac88f0814..d3c45d9897 100644 --- a/plugins/LilyPad/KeyboardHook.cpp +++ b/plugins/LilyPad/KeyboardHook.cpp @@ -43,9 +43,9 @@ public: InitInfo *info = (InitInfo*) d; binding = info->bindingIgnore; if (info->hWndButton) - EatWndProc(info->hWndButton, StartHooksWndProc); + EatWndProc(info->hWndButton, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); else - EatWndProc(info->hWnd, StartHooksWndProc); + EatWndProc(info->hWnd, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES); InitState(); ikhd = this; active = 1; diff --git a/plugins/LilyPad/KeyboardQueue.cpp b/plugins/LilyPad/KeyboardQueue.cpp index 39ad231bf3..70badb83de 100644 --- a/plugins/LilyPad/KeyboardQueue.cpp +++ b/plugins/LilyPad/KeyboardQueue.cpp @@ -1,13 +1,16 @@ // This is undoubtedly completely unnecessary. #include "KeyboardQueue.h" -static int numQueuedEvents = 0; -static keyEvent queuedEvents[20]; - // What MS calls a single process Mutex. Faster, supposedly. // More importantly, can be abbreviated, amusingly, as cSection. static CRITICAL_SECTION cSection; -static int csInitialized = 0; +static u8 csInitialized = 0; + +#define EVENT_QUEUE_LEN 16 +// Actually points one beyond the last queued event. +static u8 lastQueuedEvent = 0; +static u8 nextQueuedEvent = 0; +static keyEvent queuedEvents[EVENT_QUEUE_LEN]; void QueueKeyEvent(int key, int event) { if (!csInitialized) { @@ -15,50 +18,42 @@ void QueueKeyEvent(int key, int event) { InitializeCriticalSection(&cSection); } EnterCriticalSection(&cSection); - if (numQueuedEvents >= 15) { - // Generally shouldn't happen. - for (int i=0; i<15; i++) { - queuedEvents[i] = queuedEvents[i+5]; - } - numQueuedEvents = 15; + + // Don't queue events if escape is on top of queue. This is just for safety + // purposes when a game is killing the emulator for whatever reason. + if (nextQueuedEvent == lastQueuedEvent || + queuedEvents[nextQueuedEvent].key != VK_ESCAPE || + queuedEvents[nextQueuedEvent].evt != KEYPRESS) { + // Clear queue on escape down, bringing escape to front. May do something + // with shift/ctrl/alt and F-keys, later. + if (event == KEYPRESS && key == VK_ESCAPE) { + nextQueuedEvent = lastQueuedEvent; + } + + queuedEvents[lastQueuedEvent].key = key; + queuedEvents[lastQueuedEvent].evt = event; + + lastQueuedEvent = (lastQueuedEvent + 1) % EVENT_QUEUE_LEN; + // If queue wrapped around, remove last element. + if (nextQueuedEvent == lastQueuedEvent) { + nextQueuedEvent = (nextQueuedEvent + 1) % EVENT_QUEUE_LEN; + } } - int index = numQueuedEvents; - // Move escape to top of queue. May do something - // with shift/ctrl/alt and F-keys, later. - if (event == KEYPRESS && key == VK_ESCAPE) { - while (index) { - queuedEvents[index-1] = queuedEvents[index]; - index--; - } - } - queuedEvents[index].key = key; - queuedEvents[index].evt = event; - numQueuedEvents ++; LeaveCriticalSection(&cSection); } int GetQueuedKeyEvent(keyEvent *event) { - int out = 0; - if (numQueuedEvents) { - EnterCriticalSection(&cSection); - // Shouldn't be 0, but just in case... - if (numQueuedEvents) { - *event = queuedEvents[0]; - numQueuedEvents--; - out = 1; - for (int i=0; i1) { HANDLE hFile = CreateFileA("logs\\padLog.txt", FILE_APPEND_DATA, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0); @@ -110,12 +116,14 @@ struct Stick { int vert; }; +// Sum of states of all controls for a pad (Not including toggles). struct ButtonSum { int buttons[12]; Stick sticks[3]; }; - +// Freeze data, for a single pad. Basically has all pad state that +// a PS2 can set. struct PadFreezeData { // Digital / Analog / DS2 Native u8 mode; @@ -134,9 +142,14 @@ struct PadFreezeData { class Pad : public PadFreezeData { public: - ButtonSum sum, lockedSum; + // Current pad state. + ButtonSum sum; + // State of locked buttons. Already included by sum, used + // as initial value of sum. + ButtonSum lockedSum; - int lockedState; + // Flags for which controls (buttons or axes) are locked, if any. + DWORD lockedState; // Last vibration value. Only used so as not to call vibration // functions when old and new values are both 0. @@ -168,6 +181,12 @@ u8 Cap (int i) { return (u8) i; } +inline void ReleaseModifierKeys() { + QueueKeyEvent(VK_SHIFT, KEYRELEASE); + QueueKeyEvent(VK_MENU, KEYRELEASE); + QueueKeyEvent(VK_CONTROL, KEYRELEASE); +} + // RefreshEnabledDevices() enables everything that can potentially // be bound to, as well as the "Ignore keyboard" device. // @@ -235,11 +254,9 @@ void UpdateEnabledDevices(int updateList = 0) { BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, void* lpvReserved) { hInst = hInstance; if (fdwReason == DLL_PROCESS_ATTACH) { - InitializeCriticalSection(&readInputCriticalSection); DisableThreadLibraryCalls(hInstance); } else if (fdwReason == DLL_PROCESS_DETACH) { - DeleteCriticalSection(&readInputCriticalSection); while (openCount) PADclose(); PADshutdown(); @@ -347,8 +364,17 @@ u8 padReadKeyUpdated = 0; #define LOCK_BUTTONS 4 #define LOCK_BOTH 1 +int deviceUpdateQueued = 0; +void QueueDeviceUpdate(int updateList=0) { + deviceUpdateQueued = deviceUpdateQueued | 1 | (updateList<<1); +}; + void Update(unsigned int port, unsigned int slot) { + if (deviceUpdateQueued) { + UpdateEnabledDevices((deviceUpdateQueued & 0x2)==0x2); + deviceUpdateQueued = 0; + } if (port > 2) return; u8 *stateUpdated; if (port < 2) @@ -377,9 +403,6 @@ void Update(unsigned int port, unsigned int slot) { 0, hWnd, hWnd, 0 }; - if (!config.GSThreadUpdates) { - EnterCriticalSection(&readInputCriticalSection); - } dm->Update(&info); static int turbo = 0; turbo++; @@ -402,7 +425,7 @@ void Update(unsigned int port, unsigned int slot) { else if ((state>>15) && !(dev->oldVirtualControlState[b->controlIndex]>>15)) { if (cmd == 0x0F) { miceEnabled = !miceEnabled; - UpdateEnabledDevices(); + QueueDeviceUpdate(); } else if (cmd == 0x0C) { lockStateChanged[port][slot] |= LOCK_BUTTONS; @@ -429,10 +452,6 @@ void Update(unsigned int port, unsigned int slot) { } dm->PostRead(); - if (!config.GSThreadUpdates) { - LeaveCriticalSection(&readInputCriticalSection); - } - { for (int port=0; port<2; port++) { for (int slot=0; slot<4; slot++) { @@ -592,6 +611,7 @@ char* CALLBACK PS2EgetLibName(void) { //} void CALLBACK PADshutdown() { + DEBUG_TEXT_OUT("LilyPad shutdown.\n\n"); for (int i=0; i<8; i++) pads[i&1][i>>1].initialized = 0; portInitialized[0] = portInitialized[1] = 0; @@ -656,9 +676,10 @@ s32 CALLBACK PADinit(u32 flags) { } int port = (flags & 3); if (port == 3) { - if (PADinit(1)) return -1; + if (PADinit(1) == -1) return -1; return PADinit(2); } + #ifdef _DEBUG int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); tmpFlag |= _CRTDBG_LEAK_CHECK_DF; @@ -677,9 +698,9 @@ s32 CALLBACK PADinit(u32 flags) { query.numBytes = 0; ClearKeyQueue(); // Just in case, when resuming emulation. - QueueKeyEvent(VK_SHIFT, KEYRELEASE); - QueueKeyEvent(VK_MENU, KEYRELEASE); - QueueKeyEvent(VK_CONTROL, KEYRELEASE); + ReleaseModifierKeys(); + + DEBUG_TEXT_OUT("LilyPad initialized\n\n"); return 0; } @@ -746,32 +767,15 @@ ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara break; case WM_DEVICECHANGE: if (wParam == DBT_DEVNODES_CHANGED) { - // Need to do this when not reading input from gs thread. - // Checking for that case not worth the effort. - EnterCriticalSection(&readInputCriticalSection); - UpdateEnabledDevices(1); - LeaveCriticalSection(&readInputCriticalSection); + QueueDeviceUpdate(1); } break; case WM_ACTIVATEAPP: // Release any buttons PCSX2 may think are down when // losing/gaining focus. - QueueKeyEvent(VK_SHIFT, KEYRELEASE); - QueueKeyEvent(VK_MENU, KEYRELEASE); - QueueKeyEvent(VK_CONTROL, KEYRELEASE); - - // Need to do this when not reading input from gs thread. - // Checking for that case not worth the effort. - EnterCriticalSection(&readInputCriticalSection); - if (!wParam) { - activeWindow = 0; - UpdateEnabledDevices(); - } - else { - activeWindow = 1; - UpdateEnabledDevices(); - } - LeaveCriticalSection(&readInputCriticalSection); + ReleaseModifierKeys(); + activeWindow = wParam != 0; + QueueDeviceUpdate(); break; case WM_CLOSE: if (config.closeHacks & 1) { @@ -817,6 +821,7 @@ DWORD WINAPI MaximizeWindowThreadProc(void *lpParameter) { s32 CALLBACK PADopen(void *pDsp) { if (openCount++) return 0; + DEBUG_TEXT_OUT("LilyPad opened\n\n"); // Not really needed, shouldn't do anything. if (LoadSettings()) return -1; @@ -836,12 +841,12 @@ s32 CALLBACK PADopen(void *pDsp) { hWnd = GetParent (hWnd); // Implements most hacks, as well as enabling/disabling mouse // capture when focus changes. - if (!EatWndProc(hWnd, HackWndProc)) { + if (!EatWndProc(hWnd, HackWndProc, 0)) { openCount = 0; return -1; } if (config.forceHide) { - EatWndProc(hWnd, HideCursorProc); + EatWndProc(hWnd, HideCursorProc, 0); } } @@ -869,12 +874,14 @@ s32 CALLBACK PADopen(void *pDsp) { // activeWindow = (GetAncestor(hWnd, GA_ROOT) == GetAncestor(GetForegroundWindow(), GA_ROOT)); activeWindow = 1; - UpdateEnabledDevices(); + QueueDeviceUpdate(); return 0; } void CALLBACK PADclose() { if (openCount && !--openCount) { + DEBUG_TEXT_OUT("LilyPad closed\n\n"); + deviceUpdateQueued = 0; dm->ReleaseInput(); ReleaseEatenProc(); hWnd = 0; @@ -1022,6 +1029,7 @@ u8 CALLBACK PADpoll(u8 value) { break; // QUERY_DS2_ANALOG_MODE case 0x41: + // Right? Wrong? No clue. if (pad->mode == MODE_DIGITAL) { queryMaskMode[1] = queryMaskMode[2] = queryMaskMode[3] = 0; queryMaskMode[6] = 0x00; @@ -1227,12 +1235,14 @@ DWORD WINAPI RenameWindowThreadProc(void *lpParameter) { } keyEvent* CALLBACK PADkeyEvent() { + // If running both pads, ignore every other call. So if two keys pressed in same interval... static char eventCount = 0; eventCount++; if (eventCount < openCount) { return 0; } eventCount = 0; + if (!config.GSThreadUpdates) { Update(2, 0); } @@ -1327,7 +1337,7 @@ s32 CALLBACK PADfreeze(int mode, freezeData *data) { break; } - // Note sure if the cast is strictly necessary, but feel safest with it there... + // Not sure if the cast is strictly necessary, but feel safest with it there... *(PadFreezeData*)&pads[port][slot] = pdata.padData[slot]; } if (pdata.slot < 4) @@ -1409,5 +1419,6 @@ s32 CALLBACK PADsetSlot(u8 port, u8 slot) { } // Even if no pad there, record the slot, as it is the active slot regardless. slots[port] = slot; - return pads[port][slot].enabled; + // First slot always allowed. + return pads[port][slot].enabled | !slot; } diff --git a/plugins/LilyPad/LilyPad.rc b/plugins/LilyPad/LilyPad.rc index 8c3b7ada71..5a6b1ad24c 100644 --- a/plugins/LilyPad/LilyPad.rc +++ b/plugins/LilyPad/LilyPad.rc @@ -235,7 +235,7 @@ BEGIN PUSHBUTTON "Test Device",ID_TEST,86,289,57,15 PUSHBUTTON "Refresh",ID_REFRESH,152,289,48,15 GROUPBOX "Miscellaneous",IDC_STATIC,216,211,201,34 - CONTROL "Use GS thread (Recommended)",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,221,116,10 + CONTROL "Use GS thread",IDC_GS_THREAD_INPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,221,62,10 CONTROL "Disable screensaver",IDC_DISABLE_SCREENSAVER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,232,80,10 CONTROL "Local volume control",IDC_VISTA_VOLUME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,221,77,10 CONTROL "Enable logging",IDC_DEBUG_FILE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,336,232,62,10 diff --git a/plugins/LilyPad/RawInput.cpp b/plugins/LilyPad/RawInput.cpp index 0fbde4513f..e48ec8b081 100644 --- a/plugins/LilyPad/RawInput.cpp +++ b/plugins/LilyPad/RawInput.cpp @@ -83,7 +83,7 @@ public: } active = 1; if (!rawKeyboardActivatedCount++) { - if (!rawMouseActivatedCount && !EatWndProc(hWnd, RawInputWndProc)) { + if (!rawMouseActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) { Deactivate(); return 0; } @@ -134,7 +134,7 @@ public: // lines. if (!rawMouseActivatedCount++) { GetMouseCapture(hWnd); - if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc)) { + if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) { Deactivate(); return 0; } @@ -234,79 +234,89 @@ int InitializeRawInput() { if (RawInputFailed) return 0; if (!pGetRawInputDeviceList) { HMODULE user32 = LoadLibrary(L"user32.dll"); - if (user32) { - if (!(pRegisterRawInputDevices = (_RegisterRawInputDevices) GetProcAddress(user32, "RegisterRawInputDevices")) || - !(pGetRawInputDeviceInfo = (_GetRawInputDeviceInfo) GetProcAddress(user32, "GetRawInputDeviceInfoW")) || - !(pGetRawInputData = (_GetRawInputData) GetProcAddress(user32, "GetRawInputData")) || - !(pGetRawInputDeviceList = (_GetRawInputDeviceList) GetProcAddress(user32, "GetRawInputDeviceList"))) { - FreeLibrary(user32); - RawInputFailed = 1; - return 0; - } + if (!user32 || + !(pRegisterRawInputDevices = (_RegisterRawInputDevices) GetProcAddress(user32, "RegisterRawInputDevices")) || + !(pGetRawInputDeviceInfo = (_GetRawInputDeviceInfo) GetProcAddress(user32, "GetRawInputDeviceInfoW")) || + !(pGetRawInputData = (_GetRawInputData) GetProcAddress(user32, "GetRawInputData")) || + !(pGetRawInputDeviceList = (_GetRawInputDeviceList) GetProcAddress(user32, "GetRawInputDeviceList"))) { + FreeLibrary(user32); + RawInputFailed = 1; + return 0; } } return 1; } void EnumRawInputDevices() { - UINT count = 0; - if (InitializeRawInput() && pGetRawInputDeviceList(0, &count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1) { + int count = 0; + if (InitializeRawInput() && pGetRawInputDeviceList(0, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)) != (UINT)-1 && count > 0) { wchar_t *instanceID = (wchar_t *) malloc(41000*sizeof(wchar_t)); wchar_t *keyName = instanceID + 11000; wchar_t *displayName = keyName + 10000; wchar_t *productID = displayName + 10000; + + RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * count); int keyboardCount = 1; int mouseCount = 1; - if (count) { - RAWINPUTDEVICELIST *list = (RAWINPUTDEVICELIST*) malloc(sizeof(RAWINPUTDEVICELIST) * count); - if (list && pGetRawInputDeviceList(list, &count, sizeof(RAWINPUTDEVICELIST))) { - for (UINT i=0; i= 3) { - wcscpy(productID, instanceID); - wchar_t *temp = 0; - for (int j=0; j<3; j++) { - wchar_t *s = wcschr(productID, '#'); - if (!s) break; - *s = '\\'; - if (j==2) { - *s = 0; - } - if (j==1) temp = s; - } - wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3); - if (temp) *temp = 0; - displayName[0] = 0; - HKEY hKey; - if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) { - DWORD type; - DWORD len = 10000 * sizeof(wchar_t); - if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) && - len && type == REG_SZ) { - wchar_t *temp2 = wcsrchr(displayName, ';'); - if (!temp2) temp2 = displayName; - else temp2++; - // Could do without this, but more effort than it's worth. - wcscpy(keyName, temp2); - } - RegCloseKey(hKey); - } - if (list[i].dwType == RIM_TYPEKEYBOARD) { - if (!displayName[0]) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++); - else wsprintfW(displayName, L"Raw KB: %s", keyName); - dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID)); - } - else if (list[i].dwType == RIM_TYPEMOUSE) { - if (!displayName[0]) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++); - else wsprintfW(displayName, L"Raw MS: %s", keyName); - dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID)); - } + count = pGetRawInputDeviceList(list, (unsigned int*)&count, sizeof(RAWINPUTDEVICELIST)); + + // Not necessary, but reminder that count is -1 on failure. + if (count > 0) { + for (int i=0; i= 4) { + // nameLen includes terminating null. + nameLen--; + + // Strip out GUID parts of instanceID to make it a generic product id, + // and reformat it to point to registry entry containing device description. + wcscpy(productID, instanceID); + wchar_t *temp = 0; + for (int j=0; j<3; j++) { + wchar_t *s = wcschr(productID, '#'); + if (!s) break; + *s = '\\'; + if (j==2) { + *s = 0; + } + if (j==1) temp = s; + } + + wsprintfW(keyName, L"SYSTEM\\CurrentControlSet\\Enum%s", productID+3); + if (temp) *temp = 0; + int haveDescription = 0; + HKEY hKey; + if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &hKey)) { + DWORD type; + DWORD len = 10000 * sizeof(wchar_t); + if (ERROR_SUCCESS == RegQueryValueExW(hKey, L"DeviceDesc", 0, &type, (BYTE*)displayName, &len) && + len && type == REG_SZ) { + wchar_t *temp2 = wcsrchr(displayName, ';'); + if (!temp2) temp2 = displayName; + else temp2++; + // Could do without this, but more effort than it's worth. + wcscpy(keyName, temp2); + haveDescription = 1; + } + RegCloseKey(hKey); + } + if (list[i].dwType == RIM_TYPEKEYBOARD) { + if (!haveDescription) wsprintfW(displayName, L"Raw Keyboard %i", keyboardCount++); + else wsprintfW(displayName, L"Raw KB: %s", keyName); + dm->AddDevice(new RawInputKeyboard(list[i].hDevice, displayName, instanceID)); + } + else if (list[i].dwType == RIM_TYPEMOUSE) { + if (!haveDescription) wsprintfW(displayName, L"Raw Mouse %i", mouseCount++); + else wsprintfW(displayName, L"Raw MS: %s", keyName); + dm->AddDevice(new RawInputMouse(list[i].hDevice, displayName, instanceID, productID)); } } - free(list); } } + free(list); free(instanceID); dm->AddDevice(new RawInputKeyboard(0, L"Simulated Keyboard")); dm->AddDevice(new RawInputMouse(0, L"Simulated Mouse")); diff --git a/plugins/LilyPad/WindowsMessaging.cpp b/plugins/LilyPad/WindowsMessaging.cpp index c85783e430..edfe7f1a95 100644 --- a/plugins/LilyPad/WindowsMessaging.cpp +++ b/plugins/LilyPad/WindowsMessaging.cpp @@ -28,9 +28,8 @@ public: HWND hWnd = info->hWnd; if (info->hWndButton) { hWnd = info->hWndButton; - // hWndDlg = info->hWnd; } - if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc)) { + if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) { Deactivate(); return 0; } @@ -43,14 +42,13 @@ public: } void Deactivate() { - FreeState(); if (active) { if (!wmm) ReleaseExtraProc(WindowsMessagingWndProc); - active = 0; wmk = 0; + active = 0; + FreeState(); } - // hWndDlg = 0; } @@ -75,7 +73,7 @@ public: hWnd = info->hWndButton; } - if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc)) { + if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) { Deactivate(); return 0; } @@ -90,13 +88,13 @@ public: } void Deactivate() { - FreeState(); if (active) { - ReleaseMouseCapture(); if (!wmk) ReleaseExtraProc(WindowsMessagingWndProc); - active = 0; + ReleaseMouseCapture(); wmm = 0; + active = 0; + FreeState(); } } }; diff --git a/plugins/LilyPad/WndProcEater.cpp b/plugins/LilyPad/WndProcEater.cpp index 7d4627ba03..27d27cbdeb 100644 --- a/plugins/LilyPad/WndProcEater.cpp +++ b/plugins/LilyPad/WndProcEater.cpp @@ -2,7 +2,13 @@ static HWND hWndEaten = 0; static WNDPROC eatenWndProc = 0; -static ExtraWndProc* extraProcs = 0; + +struct ExtraWndProcInfo { + ExtraWndProc proc; + DWORD flags; +}; + +static ExtraWndProcInfo* extraProcs = 0; static int numExtraProcs = 0; void ReleaseExtraProc(ExtraWndProc proc) { @@ -13,7 +19,7 @@ void ReleaseExtraProc(ExtraWndProc proc) { if (hMutex) WaitForSingleObject(hMutex, 100); for (int i=0; i res) res = res2; } } + if (res != NO_WND_PROC) { if (out == WM_DESTROY) { ReleaseEatenProc(); @@ -68,7 +82,7 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa } -int EatWndProc(HWND hWnd, ExtraWndProc proc) { +int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags) { // Probably isn't needed, but just in case... // Creating and destroying the mutex adds some inefficiency, // but this function is only called on emulation start and on focus/unfocus. @@ -83,8 +97,10 @@ int EatWndProc(HWND hWnd, ExtraWndProc proc) { hWndEaten = hWnd; } if (hWndEaten == hWnd) { - extraProcs = (ExtraWndProc*) realloc(extraProcs, sizeof(ExtraWndProc)*(numExtraProcs+1)); - extraProcs[numExtraProcs++] = proc; + extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1)); + extraProcs[numExtraProcs].proc = proc; + extraProcs[numExtraProcs].flags = flags; + numExtraProcs++; } if (hMutex) { diff --git a/plugins/LilyPad/WndProcEater.h b/plugins/LilyPad/WndProcEater.h index c5a128e3fe..b85af1fd20 100644 --- a/plugins/LilyPad/WndProcEater.h +++ b/plugins/LilyPad/WndProcEater.h @@ -1,5 +1,7 @@ #include "Global.h" +#define EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES 1 + /* Need this to let window be subclassed multiple times but still clean up nicely. */ enum ExtraWndProcResult { @@ -11,7 +13,7 @@ enum ExtraWndProcResult { }; typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out); -int EatWndProc(HWND hWnd, ExtraWndProc proc); +int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags); void ReleaseExtraProc(ExtraWndProc proc); void ReleaseEatenProc(); diff --git a/plugins/LilyPad/XInput.cpp b/plugins/LilyPad/XInput.cpp index adcccf0a3d..68bf7cd087 100644 --- a/plugins/LilyPad/XInput.cpp +++ b/plugins/LilyPad/XInput.cpp @@ -150,11 +150,10 @@ public: } void Deactivate() { - if (xInputVibration.wLeftMotorSpeed || xInputVibration.wRightMotorSpeed) { - memset(&xInputVibration, 0, sizeof(xInputVibration)); - pXInputSetState(index, &xInputVibration); - } + memset(&xInputVibration, 0, sizeof(xInputVibration)); memset(ps2Vibration, 0, sizeof(ps2Vibration)); + pXInputSetState(index, &xInputVibration); + FreeState(); if (active) { if (!--xInputActiveCount) { diff --git a/plugins/spu2-x/src/Mixer.cpp b/plugins/spu2-x/src/Mixer.cpp index b02282827c..61598816c3 100644 --- a/plugins/spu2-x/src/Mixer.cpp +++ b/plugins/spu2-x/src/Mixer.cpp @@ -579,7 +579,7 @@ struct VoiceMixSet const VoiceMixSet VoiceMixSet::Empty( StereoOut32::Empty, StereoOut32::Empty ); -static void __fastcall MixCoreVoices( VoiceMixSet& dest, const uint coreidx ) +static __forceinline void MixCoreVoices( VoiceMixSet& dest, const uint coreidx ) { V_Core& thiscore( Cores[coreidx] ); diff --git a/plugins/spu2-x/src/SaveStateSPU.cpp b/plugins/spu2-x/src/SaveStateSPU.cpp index 59445df78f..d8ea6b31a1 100644 --- a/plugins/spu2-x/src/SaveStateSPU.cpp +++ b/plugins/spu2-x/src/SaveStateSPU.cpp @@ -35,6 +35,7 @@ struct SPU2freezeData s16 OutPos; s16 InputPos; u32 Cycles; + u32 lClocks; int PlayMode; // Used as a base pointer to a series PcmCache blocks. @@ -47,7 +48,7 @@ static const u32 SAVE_ID = 0x1227521; // versioning for saves. // Increment this when changes to the savestate system are made. -static const u32 SAVE_VERSION = 0x0004; +static const u32 SAVE_VERSION = 0x0005; static void wipe_the_cache() { @@ -71,6 +72,7 @@ s32 __fastcall FreezeIt( SPU2freezeData& spud ) spud.OutPos = OutPos; spud.InputPos = InputPos; spud.Cycles = Cycles; + spud.lClocks = lClocks; spud.PlayMode = PlayMode; // Save our cache: @@ -115,8 +117,6 @@ s32 __fastcall ThawIt( SPU2freezeData& spud ) printf("\tAudio may not recover correctly. Save your game to memorycard, reset,\n\n"); printf(" and then continue from there.\n\n"); - resetClock = true; - // Do *not* reset the cores. // We'll need some "hints" as to how the cores should be initialized, // and the only way to get that is to use the game's existing core settings @@ -141,6 +141,7 @@ s32 __fastcall ThawIt( SPU2freezeData& spud ) OutPos = spud.OutPos; InputPos = spud.InputPos; Cycles = spud.Cycles; + lClocks = spud.lClocks; PlayMode = spud.PlayMode; // Load the ADPCM cache: @@ -172,6 +173,9 @@ s32 __fastcall ThawIt( SPU2freezeData& spud ) Cores[c].Voices[v].SBuffer = pcm_cache_data[cacheIdx].Sampledata; } } + + SndBuffer::ClearContents(); + } return 0; } diff --git a/plugins/spu2-x/src/SndOut.cpp b/plugins/spu2-x/src/SndOut.cpp index 5d6ebe7b5e..55f035e692 100644 --- a/plugins/spu2-x/src/SndOut.cpp +++ b/plugins/spu2-x/src/SndOut.cpp @@ -303,6 +303,13 @@ int SndBuffer::m_dsp_progress = 0; int SndBuffer::m_dsp_writepos = 0; int SndBuffer::m_timestretch_progress = 0; +int SndBuffer::ssFreeze = 0; + +void SndBuffer::ClearContents() +{ + SndBuffer::soundtouchClearContents(); + SndBuffer::ssFreeze = 30; //Delays sound output for about half a second. +} void SndBuffer::Write( const StereoOut32& Sample ) { @@ -320,7 +327,13 @@ void SndBuffer::Write( const StereoOut32& Sample ) if(sndTempProgress < SndOutPacketSize) return; sndTempProgress = 0; - if( dspPluginEnabled ) + //Don't play anything directly after loading a savestate, avoids static killing your speakers. + if ( ssFreeze > 0 ) + { + ssFreeze--; + return; + } + else if( dspPluginEnabled ) { // Convert in, send to winamp DSP, and convert out. diff --git a/plugins/spu2-x/src/SndOut.h b/plugins/spu2-x/src/SndOut.h index b057f1bc3d..ac9a03d2cb 100644 --- a/plugins/spu2-x/src/SndOut.h +++ b/plugins/spu2-x/src/SndOut.h @@ -251,13 +251,14 @@ private: static float cTempo; static float eTempo; static int freezeTempo; - + static int ssFreeze; static void _InitFail(); static void _WriteSamples(StereoOut32* bData, int nSamples); static bool CheckUnderrunStatus( int& nSamples, int& quietSampleCount ); static void soundtouchInit(); + static void soundtouchClearContents(); static void soundtouchCleanup(); static void timeStretchWrite(); static void timeStretchUnderrun(); @@ -266,13 +267,14 @@ private: static void PredictDataWrite( int samples ); static float GetStatusPct(); static void UpdateTempoChange(); - + public: static void Init(); static void Cleanup(); static void Write( const StereoOut32& Sample ); static s32 Test(); - + static void ClearContents(); + #ifdef _MSC_VER static void Configure(HWND parent, u32 module ); #else diff --git a/plugins/spu2-x/src/Spu2.cpp b/plugins/spu2-x/src/Spu2.cpp index 0deae90f3a..cccd18f8ce 100644 --- a/plugins/spu2-x/src/Spu2.cpp +++ b/plugins/spu2-x/src/Spu2.cpp @@ -36,16 +36,12 @@ void InitADSR(); DWORD CALLBACK TimeThread(PVOID /* unused param */); #endif -// [Air]: fixed the hacky part of UpdateTimer with this: -bool resetClock = true; - void (* _irqcallback)(); void (* dma4callback)(); void (* dma7callback)(); short *spu2regs; short *_spu2mem; -s32 uTicks; u8 callirq; @@ -64,8 +60,6 @@ bool hasPtr=false; int PlayMode; -s16 attrhack[2]={0,0}; - #ifdef _MSC_VER HINSTANCE hInstance; CRITICAL_SECTION threadSync; @@ -379,7 +373,7 @@ static __forceinline void RestoreMMXRegs() #endif } -void __fastcall TimeUpdate(u32 cClocks) +__forceinline void TimeUpdate(u32 cClocks) { u32 dClocks = cClocks-lClocks; diff --git a/plugins/spu2-x/src/Spu2.h b/plugins/spu2-x/src/Spu2.h index b347a28484..9d3bcaf70c 100644 --- a/plugins/spu2-x/src/Spu2.h +++ b/plugins/spu2-x/src/Spu2.h @@ -97,7 +97,9 @@ EXPORT_C_(s32) SPU2test(); #include "Spu2replay.h" +#ifdef SPU2X_DEVBUILD #define SPU2_LOG +#endif #include "Debug.h" @@ -174,11 +176,10 @@ extern int recording; extern u32 lClocks; extern u32* cPtr; extern bool hasPtr; -extern bool resetClock; extern void SPU2writeLog( const char* action, u32 rmem, u16 value ); -extern void __fastcall TimeUpdate(u32 cClocks); +extern void TimeUpdate(u32 cClocks); extern u16 SPU_ps1_read(u32 mem); extern void SPU_ps1_write(u32 mem, u16 value); extern void SPU2_FastWrite( u32 rmem, u16 value ); diff --git a/plugins/spu2-x/src/Timestretcher.cpp b/plugins/spu2-x/src/Timestretcher.cpp index ff5a097f8e..08ab039337 100644 --- a/plugins/spu2-x/src/Timestretcher.cpp +++ b/plugins/spu2-x/src/Timestretcher.cpp @@ -128,7 +128,7 @@ void SndBuffer::UpdateTempoChange() // "non-emergency" deadzone: In this area stretching will be strongly discouraged. // Note: due tot he nature of timestretch latency, it's always a wee bit harder to - // cope with low fps (underruns) tha it is high fps (overruns). So to help out a + // cope with low fps (underruns) than it is high fps (overruns). So to help out a // little, the low-end portions of this check are less forgiving than the high-sides. if( cTempo < 0.965f || cTempo > 1.060f || @@ -323,7 +323,22 @@ void SndBuffer::soundtouchInit() // just freeze tempo changes for a while at startup. // the driver buffers are bogus anyway. - freezeTempo = 8; + freezeTempo = 16; + m_predictData = 0; +} + +// reset timestretch management vars, and delay updates a bit: +void SndBuffer::soundtouchClearContents() +{ + pSoundTouch->clear(); + pSoundTouch->setTempo(1); + + cTempo = 1.0; + eTempo = 1.0; + lastPct = 0; + lastEmergencyAdj = 0; + + freezeTempo = 16; m_predictData = 0; } diff --git a/plugins/zerogs/dx/GSmain.cpp b/plugins/zerogs/dx/GSmain.cpp index 9a84caa4ed..0ee9b5ce74 100644 --- a/plugins/zerogs/dx/GSmain.cpp +++ b/plugins/zerogs/dx/GSmain.cpp @@ -842,7 +842,7 @@ void _GSgifTransfer(pathInfo *path, u32 *pMem, u32 size) continue; } - break; + continue; } } diff --git a/plugins/zerogs/opengl/GSmain.cpp b/plugins/zerogs/opengl/GSmain.cpp index 97941a5579..abdcf05c0a 100644 --- a/plugins/zerogs/opengl/GSmain.cpp +++ b/plugins/zerogs/opengl/GSmain.cpp @@ -982,7 +982,7 @@ void _GSgifTransfer(pathInfo *path, u32 *pMem, u32 size) continue; } - break; + continue; } }