From f270064b41b0605c9eccbe6b7dc6be4b4af9abf9 Mon Sep 17 00:00:00 2001 From: "Jake.Stine" Date: Sun, 1 Mar 2009 21:49:17 +0000 Subject: [PATCH] Committing the beginnings of a new PS2 Exception Handler! This is very much a work in progress, but it shouldn't really break (or fix) anything in its current state. EE Interpreters: Fixed some signed/unsigned mistakes in some instructions, namely DIVU, DIVU1, unsigned Traps, and a couple unsigned right shifts. (all of these were already emulated correctly in the recs) Also: Removed the ThreadPriority stuff from Pcsx2, since it was a throwback to the days of Win95's unstable multitasker. If you really really feel like you need to change the thread priority of Pcsx2, use the Windows Task Manager or a third party util. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@654 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/CdRom.cpp | 1 + pcsx2/Common.h | 14 +- pcsx2/Exceptions.h | 31 +- pcsx2/FPU.cpp | 4 +- pcsx2/Interpreter.cpp | 16 +- pcsx2/IopCounters.cpp | 14 + pcsx2/IopMem.cpp | 5 +- pcsx2/IopMem.h | 30 +- pcsx2/Linux/Pref.cpp | 2 - pcsx2/MMI.cpp | 20 +- pcsx2/Memory.h | 131 +---- pcsx2/Misc.h | 1 - pcsx2/Patch.cpp | 38 +- pcsx2/PsxCommon.h | 3 + pcsx2/R3000A.cpp | 2 + pcsx2/R5900.cpp | 6 +- pcsx2/R5900.h | 11 +- pcsx2/R5900Exceptions.h | 177 +++++++ pcsx2/R5900OpcodeImpl.cpp | 561 ++++++++++++--------- pcsx2/Sif.cpp | 8 +- pcsx2/Sif.h | 4 - pcsx2/vtlb.cpp | 32 +- pcsx2/windows/DebugMemory.cpp | 4 +- pcsx2/windows/Debugger.cpp | 4 +- pcsx2/windows/RDebugger.cpp | 11 +- pcsx2/windows/VCprojects/pcsx2_2008.vcproj | 4 + pcsx2/windows/WinMain.cpp | 50 +- pcsx2/windows/WinSysExec.cpp | 35 +- pcsx2/windows/ini.cpp | 2 - pcsx2/windows/resource.h | 3 - pcsx2/x86/iR3000A.cpp | 13 +- pcsx2/x86/iVUzerorec.cpp | 5 +- pcsx2/x86/ix86-32/iR5900-32.cpp | 2 +- 33 files changed, 689 insertions(+), 555 deletions(-) create mode 100644 pcsx2/R5900Exceptions.h diff --git a/pcsx2/CdRom.cpp b/pcsx2/CdRom.cpp index 2be94e139c..d0a3ff09f6 100644 --- a/pcsx2/CdRom.cpp +++ b/pcsx2/CdRom.cpp @@ -19,6 +19,7 @@ #include "PrecompiledHeader.h" #include "PsxCommon.h" +#include "Common.h" //THIS ALL IS FOR THE CDROM REGISTERS HANDLING diff --git a/pcsx2/Common.h b/pcsx2/Common.h index 6820b9ee4d..c525ed386f 100644 --- a/pcsx2/Common.h +++ b/pcsx2/Common.h @@ -50,22 +50,10 @@ extern TESTRUNARGS g_TestRun; #define PS2CLK 294912000 //hz /* 294.912 mhz */ -/* Config.PsxType == 1: PAL: - VBlank interlaced 50.00 Hz - VBlank non-interlaced 49.76 Hz - HBlank 15.625 KHz - Config.PsxType == 0: NSTC - VBlank interlaced 59.94 Hz - VBlank non-interlaced 59.82 Hz - HBlank 15.73426573 KHz */ - -//Misc Clocks -#define PSXPIXEL ((int)(PSXCLK / 13500000)) -#define PSXSOUNDCLK ((int)(48000)) - #include "Plugins.h" #include "Misc.h" #include "SaveState.h" + #include "DebugTools/Debug.h" #include "R5900.h" #include "Memory.h" diff --git a/pcsx2/Exceptions.h b/pcsx2/Exceptions.h index 1d9fda9e01..b3766f3e27 100644 --- a/pcsx2/Exceptions.h +++ b/pcsx2/Exceptions.h @@ -61,6 +61,7 @@ protected: namespace Exception { + ////////////////////////////////////////////////////////////////////////////////// // std::exception sucks, 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. @@ -78,7 +79,24 @@ namespace Exception const std::string& Message() const { return m_message; } const char* cMessage() const { return m_message.c_str(); } }; + + // This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc). + class Ps2Generic : public BaseException + { + public: + virtual ~Ps2Generic() throw() {} + explicit Ps2Generic( const std::string& msg="The Ps2/MIPS state encountered a general exception." ) : + Exception::BaseException( msg ) + { + } + + virtual u32 GetPc() const=0; + virtual bool IsDelaySlot() const=0; + }; + + ////////////////////////////////////////////////////////////////////////////////// + // class RuntimeError : public BaseException { public: @@ -97,6 +115,8 @@ namespace Exception {} }; + ////////////////////////////////////////////////////////////////////////////////// + // class OutOfMemory : public RuntimeError { public: @@ -134,6 +154,8 @@ namespace Exception LogicError( msg ) {} }; + ////////////////////////////////////////////////////////////////////////////////// + // class HardwareDeficiency : public RuntimeError { public: @@ -184,8 +206,8 @@ namespace Exception RuntimeError( msg ) {} }; - /////////////////////////////////////////////////////////////////////// - // STREAMING EXCEPTIONS + ////////////////////////////////////////////////////////////////////////////////// + // 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. @@ -264,8 +286,8 @@ namespace Exception Stream( objname, msg ) {} }; - ////////////////////////////////////////////////////////////////////////// - // SAVESTATE EXCEPTIONS + ////////////////////////////////////////////////////////////////////////////////// + // SAVESTATE EXCEPTIONS // Exception thrown when a corrupted or truncated savestate is encountered. class BadSavedState : public BadStream @@ -321,6 +343,7 @@ namespace Exception // A recoverable exception thrown when the CRC of the savestate does not match the // CRC returned by the Cdvd driver. + // [feature not implemented yet] class StateCrcMismatch : public StateLoadError_Recoverable { public: diff --git a/pcsx2/FPU.cpp b/pcsx2/FPU.cpp index 9fb388b4e0..5d8f4ee0ea 100644 --- a/pcsx2/FPU.cpp +++ b/pcsx2/FPU.cpp @@ -381,14 +381,14 @@ void LWC1() { u32 addr; addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code & 0xffff); // force sign extension to 32bit if (addr & 0x00000003) { Console::Error( "FPU (LWC1 Opcode): Invalid Unaligned Memory Address" ); return; } // Should signal an exception? - memRead32(addr, &fpuRegs.fpr[_Rt_].UL); + fpuRegs.fpr[_Rt_].UL = memRead32(addr); } void SWC1() { u32 addr; addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code & 0xffff); // force sign extension to 32bit if (addr & 0x00000003) { Console::Error( "FPU (SWC1 Opcode): Invalid Unaligned Memory Address" ); return; } // Should signal an exception? - memWrite32(addr, fpuRegs.fpr[_Rt_].UL); + memWrite32(addr, fpuRegs.fpr[_Rt_].UL); } } } } diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index 83fdec38af..460b3fe26c 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -34,25 +34,19 @@ static std::string disOut; // These macros are used to assemble the repassembler functions -#ifdef PCSX2_DEVBUILD static void debugI() { - if (cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1]) Console::Error("R0 is not zero!!!!"); + if( !IsDevBuild ) return; + if( cpuRegs.GPR.n.r0.UD[0] || cpuRegs.GPR.n.r0.UD[1] ) Console::Error("R0 is not zero!!!!"); } -#else -static void debugI() {} -#endif //long int runs=0; static void execI() { -#ifdef _DEBUG - memRead32(cpuRegs.pc, &cpuRegs.code); - debugI(); -#else - cpuRegs.code = *(u32 *)PSM(cpuRegs.pc); -#endif + cpuRegs.code = memRead32( cpuRegs.pc ); + if( IsDebugBuild ) + debugI(); const OPCODE& opcode = GetCurrentInstruction(); //use this to find out what opcodes your game uses. very slow! (rama) diff --git a/pcsx2/IopCounters.cpp b/pcsx2/IopCounters.cpp index 03267b37f4..798af8d94f 100644 --- a/pcsx2/IopCounters.cpp +++ b/pcsx2/IopCounters.cpp @@ -25,6 +25,20 @@ #include #include "PsxCommon.h" +/* Config.PsxType == 1: PAL: + VBlank interlaced 50.00 Hz + VBlank non-interlaced 49.76 Hz + HBlank 15.625 KHz + Config.PsxType == 0: NSTC + VBlank interlaced 59.94 Hz + VBlank non-interlaced 59.82 Hz + HBlank 15.73426573 KHz */ + +// Misc IOP Clocks +#define PSXPIXEL ((int)(PSXCLK / 13500000)) +#define PSXSOUNDCLK ((int)(48000)) + + psxCounter psxCounters[8]; s32 psxNextCounter; u32 psxNextsCounter; diff --git a/pcsx2/IopMem.cpp b/pcsx2/IopMem.cpp index 136b862458..18d45cf737 100644 --- a/pcsx2/IopMem.cpp +++ b/pcsx2/IopMem.cpp @@ -373,6 +373,9 @@ void psxMemReset() // Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer. // So the ones with a 1 prefixed (ala 0x18000, etc) are RLUT tables. + + // Map IOP main memory, which is Read/Write, and mirrored three times + // at 0x0, 0x8000, and 0xa000: for (int i=0; i<0x0080; i++) { psxMemWLUT[i + 0x0000] = (uptr)&psxM[(i & 0x1f) << 16]; @@ -385,7 +388,7 @@ void psxMemReset() psxMemWLUT[i + 0x1a000] = (uptr)&psxM[(i & 0x1f) << 16]; } - // A few single-page allocations... + // A few single-page allocations for things we store in special locations. psxMemWLUT[0x11f00] = (uptr)psxP; psxMemWLUT[0x11f80] = (uptr)psxH; psxMemWLUT[0x1bf80] = (uptr)psxH; diff --git a/pcsx2/IopMem.h b/pcsx2/IopMem.h index 3723c32b6c..c86baef464 100644 --- a/pcsx2/IopMem.h +++ b/pcsx2/IopMem.h @@ -27,23 +27,26 @@ extern uptr *psxMemWLUT; extern const uptr *psxMemRLUT; -// Obtains a write-safe pointer into the IOP's memory, with TLB address translation. -// Hacky! This should really never be used, since anything reading or writing through the -// TLB should be using iopMemRead/Write instead. -template +// Obtains a writable pointer into the IOP's memory, with TLB address translation. +// If the address maps to read-only memory, NULL is returned. +// Hacky! This should really never be used, ever, since it bypasses the iop's Hardware +// Register handler and SPU/DEV/USB maps. +/*template static __forceinline T* iopVirtMemW( u32 mem ) { - return (psxMemWLUT[(mem) >> 16] == 0) ? NULL : (T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)); -} + return (psxMemWLUT[(mem) >> 16] == 0) ? NULL : (T*)(psxMemWLUT[(mem) >> 16] + ((mem) & 0xffff)); +}*/ -// Obtains a read-safe pointer into the IOP's memory, with TLB address translation. -// Hacky! This should really never be used, since anything reading or writing through the -// TLB should be using iopMemRead/Write instead. +// Obtains a read-safe pointer into the IOP's physical memory, with TLB address translation. +// Returns NULL if the address maps to an invalid/unmapped physical address. +// +// Hacky! This should really never be used, since anything reading through the +// TLB should be using iopMemRead/Write instead for each individual access. That ensures +// correct handling of page boundary crossings. template static __forceinline const T* iopVirtMemR( u32 mem ) { return (psxMemRLUT[(mem) >> 16] == 0) ? NULL : (const T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff)); - //return ((const T*)(psxMemRLUT[(mem) >> 16] + ((mem) & 0xffff))); } // Obtains a pointer to the IOP's physical mapping (bypasses the TLB) @@ -73,13 +76,6 @@ static __forceinline u8* iopPhysMem( u32 addr ) #define psxHu16(mem) (*(u16*)&psxH[(mem) & 0xffff]) #define psxHu32(mem) (*(u32*)&psxH[(mem) & 0xffff]) -//#define PSXMs8(mem) (*(s8 *)_PSXM(mem)) -//#define PSXMs16(mem) (*(s16*)_PSXM(mem)) -//#define PSXMs32(mem) (*(s32*)_PSXM(mem)) -//#define PSXMu8(mem) (*(u8 *)_PSXM(mem)) -//#define PSXMu16(mem) (*(u16*)_PSXM(mem)) -//#define PSXMu32(mem) (*(u32*)_PSXM(mem)) - void psxMemAlloc(); void psxMemReset(); void psxMemShutdown(); diff --git a/pcsx2/Linux/Pref.cpp b/pcsx2/Linux/Pref.cpp index 14e9344b1b..f2097abce9 100644 --- a/pcsx2/Linux/Pref.cpp +++ b/pcsx2/Linux/Pref.cpp @@ -73,7 +73,6 @@ int LoadConfig() GetValue("Lang", Config.Lang); GetValuel("Ps2Out", Config.PsxOut); GetValuel("cdvdPrint", Config.cdvdPrint); - GetValuel("ThPriority", Config.ThPriority); GetValue("PluginsDir", Config.PluginsDir); GetValue("BiosDir", Config.BiosDir); @@ -144,7 +143,6 @@ void SaveConfig() SetValue("BiosDir", Config.BiosDir); SetValuel("Ps2Out", Config.PsxOut); SetValuel("cdvdPrint", Config.cdvdPrint); - SetValuel("ThPriority", Config.ThPriority); SetValuel("EnabledCard1", Config.Mcd[0].Enabled); SetValue("Mcd1", Config.Mcd[0].Filename); diff --git a/pcsx2/MMI.cpp b/pcsx2/MMI.cpp index 6322603dae..96379e5406 100644 --- a/pcsx2/MMI.cpp +++ b/pcsx2/MMI.cpp @@ -94,7 +94,7 @@ namespace OpcodeImpl { } void MULT1() { - s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; + s64 temp = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * cpuRegs.GPR.r[_Rt_].SL[0]; // Sign-extend into 64 bits: cpuRegs.LO.SD[1] = (s32)(temp & 0xffffffff); @@ -104,11 +104,11 @@ namespace OpcodeImpl { } void MULTU1() { - u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; + u64 tempu = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * cpuRegs.GPR.r[_Rt_].UL[0]; // According to docs, sign-extend into 64 bits even though it's an unsigned mult. - cpuRegs.LO.UD[1] = (s32)(tempu & 0xffffffff); - cpuRegs.HI.UD[1] = (s32)(tempu >> 32); + cpuRegs.LO.SD[1] = (s32)(tempu & 0xffffffff); + cpuRegs.HI.SD[1] = (s32)(tempu >> 32); if (_Rd_) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[1]; } @@ -120,12 +120,14 @@ namespace OpcodeImpl { } } - void DIVU1() { - if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { - + void DIVU1() + { + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) + { // note: DIVU has no sign extension when assigning back to 64 bits - cpuRegs.LO.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; - cpuRegs.HI.UD[1] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + // note 2: reference material strongly disagrees. (air) + cpuRegs.LO.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]); + cpuRegs.HI.SD[1] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]); } } diff --git a/pcsx2/Memory.h b/pcsx2/Memory.h index e100bbce51..11cc0d348b 100644 --- a/pcsx2/Memory.h +++ b/pcsx2/Memory.h @@ -56,10 +56,9 @@ extern u8 *psS; //0.015 mb, scratch pad #define PS2MEM_EROM psER #define PS2MEM_SCRATCH psS -extern u8 g_RealGSMem[0x2000]; +extern u8 g_RealGSMem[Ps2MemSize::GSregs]; #define PS2MEM_GS g_RealGSMem -//#define _PSM(mem) (memLUTR[(mem) >> 12] == 0 ? NULL : (void*)(memLUTR[(mem) >> 12] + ((mem) & 0xfff))) #define PSM(mem) (vtlb_GetPhyPtr(mem&0x1fffffff)) //pcsx2 is a competition.The one with most hacks wins :D #define psMs8(mem) (*(s8 *)&PS2MEM_BASE[(mem) & 0x1ffffff]) @@ -116,14 +115,14 @@ extern u8 g_RealGSMem[0x2000]; #define psSu32(mem) (*(u32*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) #define psSu64(mem) (*(u64*)&PS2MEM_SCRATCH[(mem) & 0x3fff]) -#define PSMs8(mem) (*(s8 *)PSM(mem)) -#define PSMs16(mem) (*(s16*)PSM(mem)) -#define PSMs32(mem) (*(s32*)PSM(mem)) -#define PSMs64(mem) (*(s64*)PSM(mem)) -#define PSMu8(mem) (*(u8 *)PSM(mem)) -#define PSMu16(mem) (*(u16*)PSM(mem)) -#define PSMu32(mem) (*(u32*)PSM(mem)) -#define PSMu64(mem) (*(u64*)PSM(mem)) +//#define PSMs8(mem) (*(s8 *)PSM(mem)) +//#define PSMs16(mem) (*(s16*)PSM(mem)) +//#define PSMs32(mem) (*(s32*)PSM(mem)) +//#define PSMs64(mem) (*(s64*)PSM(mem)) +//#define PSMu8(mem) (*(u8 *)PSM(mem)) +//#define PSMu16(mem) (*(u16*)PSM(mem)) +//#define PSMu32(mem) (*(u32*)PSM(mem)) +//#define PSMu64(mem) (*(u64*)PSM(mem)) extern void memAlloc(); extern void memReset(); // clears PS2 ram and loads the bios. Throws Exception::FileNotFound on error. @@ -143,10 +142,9 @@ extern void mmap_MarkCountedRamPage(void* ptr,u32 vaddr); extern void mmap_ResetBlockTracking(); extern void mmap_ClearCpuBlock( uint offset ); -extern void __fastcall memRead8(u32 mem, u8 *out); -extern void __fastcall memRead16(u32 mem, u16 *out); -extern void __fastcall memRead32(u32 mem, u32 *out); - +#define memRead8 vtlb_memRead8 +#define memRead16 vtlb_memRead16 +#define memRead32 vtlb_memRead32 #define memRead64 vtlb_memRead64 #define memRead128 vtlb_memRead128 @@ -168,6 +166,8 @@ extern void __fastcall memRead32(u32 mem, u32 *out); #define _eeMoveMMREGtoR 0&& // extra ops +// These allow the old unused const versions of various HW accesses to continue to compile. +// (code left in for reference purposes, but is not needed by Vtlb) #define _eeWriteConstMem16OP 0&& #define _eeWriteConstMem32OP 0&& @@ -186,107 +186,4 @@ extern void __fastcall memRead32(u32 mem, u32 *out); extern void loadBiosRom( const char *ext, u8 *dest, long maxSize ); extern u16 ba0R16(u32 mem); -////////////////////////////////////////////////////////////////////////// -// The rest of this header contains the old VM version of the Memory.h API. -// Left in for references purposes. - -#ifdef PCSX2_VIRTUAL_MEM - -#define PS2MEM_BASE_ 0x15000000 -#define PS2MEM_PSX_ (PS2MEM_BASE_+0x1c000000) - -#ifdef _WIN32 -struct PSMEMORYMAP -{ - uptr* aPFNs, *aVFNs; -}; -#endif - -#define TRANSFORM_ADDR(memaddr) ( ((u32)(memaddr)>=0x40000000) ? ((memaddr)&~0xa0000000) : (memaddr) ) - -//new memory model -#define PS2MEM_BASE ((u8*)PS2MEM_BASE_) -#define PS2MEM_HW ((u8*)((u32)PS2MEM_BASE+0x10000000)) -#define PS2MEM_ROM ((u8*)((u32)PS2MEM_BASE+0x1fc00000)) -#define PS2MEM_ROM1 ((u8*)((u32)PS2MEM_BASE+0x1e000000)) -#define PS2MEM_ROM2 ((u8*)((u32)PS2MEM_BASE+0x1e400000)) -#define PS2MEM_EROM ((u8*)((u32)PS2MEM_BASE+0x1e040000)) -#define PS2MEM_PSX ((u8*)PS2MEM_PSX_) -#define PS2MEM_SCRATCH ((u8*)((u32)PS2MEM_BASE+0x50000000)) -#define PS2MEM_VU0MICRO ((u8*)((u32)PS2MEM_BASE+0x11000000)) -#define PS2MEM_VU0MEM ((u8*)((u32)PS2MEM_BASE+0x11004000)) -#define PS2MEM_VU1MICRO ((u8*)((u32)PS2MEM_BASE+0x11008000)) -#define PS2MEM_VU1MEM ((u8*)((u32)PS2MEM_BASE+0x1100c000)) - -// function for mapping memory -#define PS2MEM_PSXHW ((u8*)((u32)PS2MEM_BASE+0x1f800000)) -//#define PS2MEM_PSXHW2 ((u8*)((u32)PS2MEM_BASE+0x1fa00000)) -#define PS2MEM_PSXHW4 ((u8*)((u32)PS2MEM_BASE+0x1f400000)) -#define PS2MEM_GS ((u8*)((u32)PS2MEM_BASE+0x12000000)) -#define PS2MEM_DEV9 ((u8*)((u32)PS2MEM_BASE+0x14000000)) -#define PS2MEM_SPU2 ((u8*)((u32)PS2MEM_BASE+0x1f900000)) -#define PS2MEM_SPU2_ ((u8*)((u32)PS2MEM_BASE+0x1f000000)) // ? -#define PS2MEM_B80 ((u8*)((u32)PS2MEM_BASE+0x18000000)) -#define PS2MEM_BA0 ((u8*)((u32)PS2MEM_BASE+0x1a000000)) - -#define PSM(mem) (PS2MEM_BASE + TRANSFORM_ADDR(mem)) - -int __fastcall memRead8(u32 mem, u8 *out); -int __fastcall memRead8RS(u32 mem, u64 *out); -int __fastcall memRead8RU(u32 mem, u64 *out); -int __fastcall memRead16(u32 mem, u16 *out); -int __fastcall memRead16RS(u32 mem, u64 *out); -int __fastcall memRead16RU(u32 mem, u64 *out); -int __fastcall memRead32(u32 mem, u32 *out); -int __fastcall memRead32RS(u32 mem, u64 *out); -int __fastcall memRead32RU(u32 mem, u64 *out); -int __fastcall memRead64(u32 mem, u64 *out); -int __fastcall memRead128(u32 mem, u64 *out); -void __fastcall memWrite8 (u32 mem, u8 value); -void __fastcall memWrite16(u32 mem, u16 value); -void __fastcall memWrite32(u32 mem, u32 value); -void __fastcall memWrite64(u32 mem, const u64 *value); -void __fastcall memWrite128(u32 mem, const u64 *value); - -// recMemConstRead8, recMemConstRead16, recMemConstRead32 return 1 if a call was made, 0 otherwise -u8 recMemRead8(); -u16 recMemRead16(); -u32 recMemRead32(); -void recMemRead64(u64 *out); -void recMemRead128(u64 *out); - -void recMemWrite8(); -void recMemWrite16(); -void recMemWrite32(); -void recMemWrite64(); -void recMemWrite128(); - -void _eeReadConstMem8(int mmreg, u32 mem, int sign); -void _eeReadConstMem16(int mmreg, u32 mem, int sign); -void _eeReadConstMem32(int mmreg, u32 mem); -void _eeReadConstMem128(int mmreg, u32 mem); -void _eeWriteConstMem8(u32 mem, int mmreg); -void _eeWriteConstMem16(u32 mem, int mmreg); -void _eeWriteConstMem32(u32 mem, int mmreg); -void _eeWriteConstMem64(u32 mem, int mmreg); -void _eeWriteConstMem128(u32 mem, int mmreg); -void _eeMoveMMREGtoR(int to, int mmreg); - -// extra ops -void _eeWriteConstMem16OP(u32 mem, int mmreg, int op); -void _eeWriteConstMem32OP(u32 mem, int mmreg, int op); - -int recMemConstRead8(u32 x86reg, u32 mem, u32 sign); -int recMemConstRead16(u32 x86reg, u32 mem, u32 sign); -int recMemConstRead32(u32 x86reg, u32 mem); -void recMemConstRead64(u32 mem, int mmreg); -void recMemConstRead128(u32 mem, int xmmreg); - -int recMemConstWrite8(u32 mem, int mmreg); -int recMemConstWrite16(u32 mem, int mmreg); -int recMemConstWrite32(u32 mem, int mmreg); -int recMemConstWrite64(u32 mem, int mmreg); -int recMemConstWrite128(u32 mem, int xmmreg); -#endif - #endif diff --git a/pcsx2/Misc.h b/pcsx2/Misc.h index 90a54d90f6..601f51cadc 100644 --- a/pcsx2/Misc.h +++ b/pcsx2/Misc.h @@ -154,7 +154,6 @@ public: int Cdda; int Mdec; int Patch; - int ThPriority; int CustomFps; int Hacks; int GameFixes; diff --git a/pcsx2/Patch.cpp b/pcsx2/Patch.cpp index 2821c3210a..7cfbc6e08b 100644 --- a/pcsx2/Patch.cpp +++ b/pcsx2/Patch.cpp @@ -21,6 +21,8 @@ // #include "PrecompiledHeader.h" +#define _PC_ // disables MIPS opcode macros. + #include "PsxCommon.h" #include "Paths.h" #include "Patch.h" @@ -133,13 +135,13 @@ void handle_extended_t( IniPatch *p) else switch (PrevCheatType) { case 0x3040: // vvvvvvvv 00000000 Inc - memRead32(PrevCheataddr,&u32Val); + u32Val = memRead32(PrevCheataddr); memWrite32(PrevCheataddr, u32Val+(p->addr)); PrevCheatType = 0; break; case 0x3050: // vvvvvvvv 00000000 Dec - memRead32(PrevCheataddr,&u32Val); + u32Val = memRead32(PrevCheataddr); memWrite32(PrevCheataddr, u32Val-(p->addr)); PrevCheatType = 0; break; @@ -155,7 +157,7 @@ void handle_extended_t( IniPatch *p) case 0x5000: // dddddddd iiiiiiii for(i=0;idata)+i,u8Val); } PrevCheatType = 0; @@ -167,7 +169,7 @@ void handle_extended_t( IniPatch *p) // Read first pointer LastType = ((u32)p->addr&0x000F0000)/0x10000; - memRead32(PrevCheataddr,&u32Val); + u32Val = memRead32(PrevCheataddr); PrevCheataddr = u32Val+(u32)p->data; IterationCount--; @@ -182,7 +184,7 @@ void handle_extended_t( IniPatch *p) case 0x6001: // 000Xnnnn iiiiiiii // Read first pointer - memRead32(PrevCheataddr,&u32Val); + u32Val = memRead32(PrevCheataddr); PrevCheataddr =u32Val+(u32)p->addr; IterationCount--; @@ -194,7 +196,7 @@ void handle_extended_t( IniPatch *p) } else { - memRead32(PrevCheataddr,&u32Val); + u32Val = memRead32(PrevCheataddr); PrevCheataddr =u32Val+(u32)p->data; IterationCount--; @@ -223,25 +225,25 @@ void handle_extended_t( IniPatch *p) } else if ((p->addr&0xFFFF0000) == 0x30000000) // 300000vv 0aaaaaaa Inc { - memRead8((u32)p->data,&u8Val); + u8Val = memRead8((u32)p->data); memWrite8((u32)p->data, u8Val+(p->addr&0x000000FF)); PrevCheatType = 0; } else if ((p->addr&0xFFFF0000) == 0x30100000) // 301000vv 0aaaaaaa Dec { - memRead8((u32)p->data,&u8Val); + u8Val = memRead8((u32)p->data); memWrite8((u32)p->data, u8Val-(p->addr&0x000000FF)); PrevCheatType = 0; } else if ((p->addr&0xFFFF0000) == 0x30200000) // 3020vvvv 0aaaaaaa Inc { - memRead16((u32)p->data,&u16Val); + u16Val = memRead16((u32)p->data); memWrite16((u32)p->data, u16Val+(p->addr&0x0000FFFF)); PrevCheatType = 0; } else if ((p->addr&0xFFFF0000) == 0x30300000) // 3030vvvv 0aaaaaaa Dec { - memRead16((u32)p->data,&u16Val); + u16Val = memRead16((u32)p->data); memWrite16((u32)p->data, u16Val-(p->addr&0x0000FFFF)); PrevCheatType = 0; } @@ -279,32 +281,32 @@ void handle_extended_t( IniPatch *p) { if ((p->data&0x00F00000) == 0x00000000) // 7aaaaaaa 000000vv { - memRead8((u32)p->addr&0x0FFFFFFF,&u8Val); + u8Val = memRead8((u32)p->addr&0x0FFFFFFF); memWrite8((u32)p->addr&0x0FFFFFFF,(u8)(u8Val|(p->data&0x000000FF))); } else if ((p->data&0x00F00000) == 0x00100000) // 7aaaaaaa 0010vvvv { - memRead16((u32)p->addr&0x0FFFFFFF,&u16Val); + u16Val = memRead16((u32)p->addr&0x0FFFFFFF); memWrite16((u32)p->addr&0x0FFFFFFF,(u16)(u16Val|(p->data&0x0000FFFF))); } else if ((p->data&0x00F00000) == 0x00200000) // 7aaaaaaa 002000vv { - memRead8((u32)p->addr&0x0FFFFFFF,&u8Val); + u8Val = memRead8((u32)p->addr&0x0FFFFFFF); memWrite8((u32)p->addr&0x0FFFFFFF,(u8)(u8Val&(p->data&0x000000FF))); } else if ((p->data&0x00F00000) == 0x00300000) // 7aaaaaaa 0030vvvv { - memRead16((u32)p->addr&0x0FFFFFFF,&u16Val); + u16Val = memRead16((u32)p->addr&0x0FFFFFFF); memWrite16((u32)p->addr&0x0FFFFFFF,(u16)(u16Val&(p->data&0x0000FFFF))); } else if ((p->data&0x00F00000) == 0x00400000) // 7aaaaaaa 004000vv { - memRead8((u32)p->addr&0x0FFFFFFF,&u8Val); + u8Val = memRead8((u32)p->addr&0x0FFFFFFF); memWrite8((u32)p->addr&0x0FFFFFFF,(u8)(u8Val^(p->data&0x000000FF))); } else if ((p->data&0x00F00000) == 0x00500000) // 7aaaaaaa 0050vvvv { - memRead16((u32)p->addr&0x0FFFFFFF,&u16Val); + u16Val = memRead16((u32)p->addr&0x0FFFFFFF); memWrite16((u32)p->addr&0x0FFFFFFF,(u16)(u16Val^(p->data&0x0000FFFF))); } } @@ -315,7 +317,7 @@ void handle_extended_t( IniPatch *p) (((u32)p->data & 0xFFFF0000)==0x00200000) || (((u32)p->data & 0xFFFF0000)==0x00300000)) { - memRead16((u32)p->addr&0x0FFFFFFF,&u16Val); + u16Val = memRead16((u32)p->addr&0x0FFFFFFF); if (u16Val != (0x0000FFFF&(u32)p->data)) SkipCount = 1; PrevCheatType= 0; } @@ -327,7 +329,7 @@ void handle_extended_t( IniPatch *p) (((u32)p->data&0xF0000000)==0x20000000) || (((u32)p->data&0xF0000000)==0x30000000)) { - memRead16((u32)p->data&0x0FFFFFFF,&u16Val); + u16Val = memRead16((u32)p->data&0x0FFFFFFF); if (u16Val != (0x0000FFFF&(u32)p->addr)) SkipCount = ((u32)p->addr&0xFFF0000)/0x10000; PrevCheatType= 0; } diff --git a/pcsx2/PsxCommon.h b/pcsx2/PsxCommon.h index 37af591f01..1e7683cdf8 100644 --- a/pcsx2/PsxCommon.h +++ b/pcsx2/PsxCommon.h @@ -30,6 +30,9 @@ extern int cdOpenCase; #define PSXCLK (36864000ULL) /* 36.864 Mhz */ #include "Plugins.h" +#include "Misc.h" +#include "SaveState.h" + #include "R3000A.h" #include "IopMem.h" #include "IopHw.h" diff --git a/pcsx2/R3000A.cpp b/pcsx2/R3000A.cpp index f49e78ddf5..8d28d86a4a 100644 --- a/pcsx2/R3000A.cpp +++ b/pcsx2/R3000A.cpp @@ -21,6 +21,8 @@ #include "PsxCommon.h" #include "Misc.h" +#include "R5900.h" + using namespace R3000A; R3000Acpu *psxCpu; diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 1c15361b9f..517e388c75 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -37,13 +37,13 @@ #include "Paths.h" +#include "R5900Exceptions.h" + using namespace R5900; // for R5900 disasm tools s32 EEsCycle; // used to sync the IOP to the EE u32 EEoCycle; -//static int inter; - PCSX2_ALIGNED16(cpuRegisters cpuRegs); PCSX2_ALIGNED16(fpuRegisters fpuRegs); PCSX2_ALIGNED16(tlbs tlb[48]); @@ -56,6 +56,8 @@ static uint eeWaitCycles = 1024; bool eeEventTestIsActive = false; +R5900Exception::BaseExcept::~BaseExcept() {} + // A run-once procedure for initializing the emulation state. // Can be done anytime after allocating memory, and before calling Cpu->Execute(). // Multiple calls to this function are automatically ignored. diff --git a/pcsx2/R5900.h b/pcsx2/R5900.h index 8fced77e39..9c14139a94 100644 --- a/pcsx2/R5900.h +++ b/pcsx2/R5900.h @@ -100,9 +100,9 @@ struct cpuRegisters { GPR_reg LO; // hi & log 128bit wide CP0regs CP0; // is COP0 32bit? u32 sa; // shift amount (32bit), needs to be 16 byte aligned - u32 constzero; // always 0, for MFSA + 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; // The instruction + u32 code; // current instruction PERFregs PERF; u32 eCycle[32]; u32 sCycle[32]; // for internal counters @@ -110,7 +110,7 @@ struct cpuRegisters { u32 interrupt; int branch; int opmode; // operating mode - u32 tempcycles; + u32 tempcycles; }; // used for optimization @@ -184,9 +184,10 @@ struct tlbs #define _Opcode_ (cpuRegs.code >> 26 ) #define _JumpTarget_ ((_Target_ << 2) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction -#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction +#define _BranchTarget_ (((s32)(s16)_Im_ * 4) + _PC_) // Calculates the target during a branch instruction +#define _TrapCode_ ((u16)cpuRegs.code >> 6) // error code for non-immediate trap instructions. -#define _SetLink(x) cpuRegs.GPR.r[x].UD[0] = _PC_ + 4; // Sets the return address in the link register +#define _SetLink(x) (cpuRegs.GPR.r[x].UD[0] = _PC_ + 4) // Sets the return address in the link register #endif diff --git a/pcsx2/R5900Exceptions.h b/pcsx2/R5900Exceptions.h new file mode 100644 index 0000000000..9a77225f6c --- /dev/null +++ b/pcsx2/R5900Exceptions.h @@ -0,0 +1,177 @@ +/* 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 +*/ + +#ifndef _R5900_EXCEPTIONS_H_ +#define _R5900_EXCEPTIONS_H_ + +namespace R5900Exception +{ + using Exception::Ps2Generic; + + ////////////////////////////////////////////////////////////////////////////////// + // Abstract base class for R5900 exceptions; contains the cpuRegs instance at the + // time the exception is raised. + // + class BaseExcept : public Ps2Generic + { + public: + const cpuRegisters cpuState; + + public: + virtual ~BaseExcept() throw()=0; + + explicit BaseExcept( const std::string& msg ) : + Exception::Ps2Generic( "(EE) " + msg ), + cpuState( cpuRegs ) + { + } + + u32 GetPc() const { return cpuState.pc; } + bool IsDelaySlot() const { return !!cpuState.IsDelaySlot; } + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class AddressError : public BaseExcept + { + public: + const bool OnWrite; + const u32 Address; + + public: + virtual ~AddressError() throw() {} + + explicit AddressError( u32 ps2addr, bool onWrite ) : + BaseExcept( fmt_string( "Address error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + OnWrite( onWrite ), + Address( ps2addr ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class TLBMiss : public BaseExcept + { + public: + const bool OnWrite; + const u32 Address; + + public: + virtual ~TLBMiss() throw() {} + + explicit TLBMiss( u32 ps2addr, bool onWrite ) : + BaseExcept( fmt_string( "Tlb Miss, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + OnWrite( onWrite ), + Address( ps2addr ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class BusError : public BaseExcept + { + public: + const bool OnWrite; + const u32 Address; + + public: + virtual ~BusError() throw() {} + + // + explicit BusError( u32 ps2addr, bool onWrite ) : + BaseExcept( fmt_string( "Bus Error, addr=0x%x [%s]", ps2addr, onWrite ? "store" : "load" ) ), + OnWrite( onWrite ), + Address( ps2addr ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class SystemCall : public BaseExcept + { + public: + virtual ~SystemCall() throw() {} + + explicit SystemCall() : + BaseExcept( "SystemCall [SYSCALL]" ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class Trap : public BaseExcept + { + public: + const u16 TrapCode; + + public: + virtual ~Trap() throw() {} + + // Generates a trap for immediate-style Trap opcodes + explicit Trap() : + BaseExcept( "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" ), + TrapCode( trapcode ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class Break : public BaseExcept + { + public: + virtual ~Break() throw() {} + + explicit Break() : + BaseExcept( "Break Instruction" ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class Overflow : public BaseExcept + { + public: + virtual ~Overflow() throw() {} + + explicit Overflow() : + BaseExcept( "Overflow" ) + {} + }; + + ////////////////////////////////////////////////////////////////////////////////// + // + class DebugBreakpoint : public BaseExcept + { + public: + virtual ~DebugBreakpoint() throw() {} + + explicit DebugBreakpoint() : + BaseExcept( "Debug Breakpoint" ) + {} + }; +} + + +#endif diff --git a/pcsx2/R5900OpcodeImpl.cpp b/pcsx2/R5900OpcodeImpl.cpp index a988c3590e..d938fc6d62 100644 --- a/pcsx2/R5900OpcodeImpl.cpp +++ b/pcsx2/R5900OpcodeImpl.cpp @@ -21,9 +21,45 @@ #include "Common.h" #include "R5900.h" #include "R5900OpcodeTables.h" +#include "R5900Exceptions.h" #include +static __forceinline s64 _add64_Overflow( s64 x, s64 y ) +{ + const s64 result = x + y; + + // Let's all give gigaherz a big round of applause for finding this gem, + // which apparently works, and generates compact/fast x86 code too (the + // other method below is like 5-10 times slower). + + if( ((~(x^y))&(x^result)) < 0 ) + throw R5900Exception::Overflow(); + + // the not-as-fast style! + //if( ((x >= 0) && (y >= 0) && (result < 0)) || + // ((x < 0) && (y < 0) && (result >= 0)) ) + // throw R5900Exception::Overflow(); + + return result; +} + +static __forceinline s64 _add32_Overflow( s32 x, s32 y ) +{ + GPR_reg64 result; result.SD[0] = (s64)x + y; + + // This 32bit method can rely on the MIPS documented method of checking for + // overflow, whichs imply compares bit 32 (rightmost bit of the upper word), + // against bit 31 (leftmost of the lower word). + + // If bit32 != bit31 then we have an overflow. + if( (result.UL[0]>>31) != (result.UL[1] & 1) ) + throw R5900Exception::Overflow(); + + return result.SD[0]; +} + + namespace R5900 { const OPCODE& GetCurrentInstruction() @@ -106,84 +142,162 @@ void MMI_Unknown() { Console::Notice("Unknown MMI opcode called"); } void COP0_Unknown() { Console::Notice("Unknown COP0 opcode called"); } void COP1_Unknown() { Console::Notice("Unknown FPU/COP1 opcode called"); } + + /********************************************************* * Arithmetic with immediate operand * * Format: OP rt, rs, immediate * *********************************************************/ -void ADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed!!!! -void ADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; }// Rt = Rs + Im signed !!! -void DADDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im -void DADDIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; }// Rt = Rs + Im + +// Implementation Notes: +// * It is important that instructions perform overflow checks prior to shortcutting on +// the zero register (when it is used as a destination). Overflow exceptions are still +// handled even though the result is discarded. + +// Rt = Rs + Im signed [exception on overflow] +void ADDI() +{ + s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_ ); + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = result; +} + +// Rt = Rs + Im signed !!! [overflow ignored] +// This instruction is effectively identical to ADDI. It is not a true unsigned operation, +// but rather it is a signed operation that ignores overflows. +void ADDIU() +{ + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + _Imm_; +} + +// Rt = Rs + Im [exception on overflow] +// This is the full 64 bit version of ADDI. Overflow occurs at 64 bits instead +// of at 32 bits. +void DADDI() +{ + s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], _Imm_ ); + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = result; +} + +// Rt = Rs + Im [overflow ignored] +// This instruction is effectively identical to DADDI. It is not a true unsigned operation, +// but rather it is a signed operation that ignores overflows. +void DADDIU() +{ + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + _Imm_; +} void ANDI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & (u64)_ImmU_; } // Rt = Rs And Im (zero-extended) void ORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | (u64)_ImmU_; } // Rt = Rs Or Im (zero-extended) void XORI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ (u64)_ImmU_; } // Rt = Rs Xor Im (zero-extended) -void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_); } // Rt = Rs < Im (signed) -void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_); } // Rt = Rs < Im (unsigned) +void SLTI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rs_].SD[0] < (s64)(_Imm_)) ? 1 : 0; } // Rt = Rs < Im (signed) +void SLTIU() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rs_].UD[0] < (u64)(_Imm_)) ? 1 : 0; } // Rt = Rs < Im (unsigned) /********************************************************* * Register arithmetic * * Format: OP rd, rs, rt * *********************************************************/ -void ADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt (Exception on Integer Overflow) + +// Rd = Rs + Rt (Exception on Integer Overflow) +void ADD() +{ + s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0] ); + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = result; +} + +void DADD() +{ + s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], cpuRegs.GPR.r[_Rt_].SD[0] ); + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = result; +} + +// Rd = Rs - Rt (Exception on Integer Overflow) +void SUB() +{ + s64 result = _add32_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0] ); + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = result; +} + +// Rd = Rs - Rt (Exception on Integer Overflow) +void DSUB() +{ + s64 result = _add64_Overflow( cpuRegs.GPR.r[_Rs_].SD[0], -cpuRegs.GPR.r[_Rt_].SD[0] ); + if (!_Rd_) return; + cpuRegs.GPR.r[_Rd_].SD[0] = result; +} + void ADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] + cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs + Rt -void DADD() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } void DADDU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] + cpuRegs.GPR.r[_Rt_].SD[0]; } -void SUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0];} // Rd = Rs - Rt (Exception on Integer Overflow) void SUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SL[0] - cpuRegs.GPR.r[_Rt_].SL[0]; } // Rd = Rs - Rt -void DSUB() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0];} void DSUBU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] - cpuRegs.GPR.r[_Rt_].SD[0]; } void AND() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] & cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs And Rt void OR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Or Rt void XOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] ^ cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs Xor Rt void NOR() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] =~(cpuRegs.GPR.r[_Rs_].UD[0] | cpuRegs.GPR.r[_Rt_].UD[0]); }// Rd = Rs Nor Rt -void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]; } // Rd = Rs < Rt (signed) -void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]; } // Rd = Rs < Rt (unsigned) +void SLT() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) ? 1 : 0; } // Rd = Rs < Rt (signed) +void SLTU() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) ? 1 : 0; } // Rd = Rs < Rt (unsigned) /********************************************************* * Register mult/div & Register trap logic * * Format: OP rs, rt * *********************************************************/ -void DIV() { - if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) { + +// Result is stored in HI/LO [no arithmetic exceptions] +void DIV() +{ + if (cpuRegs.GPR.r[_Rt_].SL[0] != 0) + { cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] / cpuRegs.GPR.r[_Rt_].SL[0]; cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].SL[0] % cpuRegs.GPR.r[_Rt_].SL[0]; } } -void DIVU() { - if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) { - +// Result is stored in HI/LO [no arithmetic exceptions] +void DIVU() +{ + if (cpuRegs.GPR.r[_Rt_].UL[0] != 0) + { // note: DIVU has no sign extension when assigning back to 64 bits - cpuRegs.LO.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]; - cpuRegs.HI.SD[0] = cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]; + // note 2: reference material strongly disagrees. (air) + cpuRegs.LO.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] / cpuRegs.GPR.r[_Rt_].UL[0]); + cpuRegs.HI.SD[0] = (s32)(cpuRegs.GPR.r[_Rs_].UL[0] % cpuRegs.GPR.r[_Rt_].UL[0]); } } -void MULT() { //different in ps2... - s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * (s64)cpuRegs.GPR.r[_Rt_].SL[0]; +// Result is written to both HI/LO and to the _Rd_ (Lo only) +void MULT() +{ + s64 res = (s64)cpuRegs.GPR.r[_Rs_].SL[0] * cpuRegs.GPR.r[_Rt_].SL[0]; // Sign-extend into 64 bits: - cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); - cpuRegs.HI.UD[0] = (s32)(res >> 32); + cpuRegs.LO.SD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(res >> 32); - if( _Rd_ ) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; //that is the difference + if( _Rd_ ) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } -void MULTU() { //different in ps2.. - u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * (u64)cpuRegs.GPR.r[_Rt_].UL[0]; +// Result is written to both HI/LO and to the _Rd_ (Lo only) +void MULTU() +{ + u64 res = (u64)cpuRegs.GPR.r[_Rs_].UL[0] * cpuRegs.GPR.r[_Rt_].UL[0]; - // According to docs, sign-extend into 64 bits even though it's an unsigned mult. - cpuRegs.LO.UD[0] = (s32)(res & 0xffffffff); - cpuRegs.HI.UD[0] = (s32)(res >> 32); + // Note: sign-extend into 64 bits even though it's an unsigned mult. + cpuRegs.LO.SD[0] = (s32)(res & 0xffffffff); + cpuRegs.HI.SD[0] = (s32)(res >> 32); - if( _Rd_ ) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; //that is the difference + if( _Rd_ ) cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.LO.UD[0]; } /********************************************************* * Load higher 16 bits of the first word in GPR with imm * * Format: OP rt, immediate * *********************************************************/ -void LUI() { +void LUI() { if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].UD[0] = (s32)(cpuRegs.code << 16); } @@ -207,15 +321,15 @@ void MTLO() { cpuRegs.LO.UD[0] = cpuRegs.GPR.r[_Rs_].UD[0]; } // Lo = Rs * Shift arithmetic with constant shift * * Format: OP rd, rt, sa * *********************************************************/ +void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) +void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) [sign extend!!] void SLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] << _Sa_); } // Rd = Rt << sa void DSLL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << _Sa_); } void DSLL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] << (_Sa_+32));} -void SRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].SL[0] >> _Sa_); } // Rd = Rt >> sa (arithmetic) -void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_); } -void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (u64)(cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32));} -void SRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = (s32)(cpuRegs.GPR.r[_Rt_].UL[0] >> _Sa_); } // Rd = Rt >> sa (logical) -void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_); } -void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32));} +void DSRA() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.GPR.r[_Rt_].SD[0] >> _Sa_; } +void DSRA32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].SD[0] = cpuRegs.GPR.r[_Rt_].SD[0] >> (_Sa_+32);} +void DSRL() { if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> _Sa_; } +void DSRL32(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = cpuRegs.GPR.r[_Rt_].UD[0] >> (_Sa_+32);} /********************************************************* * Shift arithmetic with variant register shift * @@ -233,86 +347,85 @@ void DSRLV(){ if (!_Rd_) return; cpuRegs.GPR.r[_Rd_].UD[0] = (u64)(cpuRegs.GPR.r * Format: OP rt, offset(base) * *********************************************************/ -void LB() { - u32 addr; +// Implementation Notes Regarding Memory Operations: +// * It it 'correct' to do all loads into temp variables, even if the destination GPR +// is the zero reg (which nullifies the result). The memory needs to be accessed +// regardless so that hardware registers behave as expected (some clear on read) and +// so that TLB Misses are handled as expected as well. +// +// * Low/High varieties of instructions, such as LWL/LWH, do *not* raise Address Error +// exceptions, since the lower bits of the address are used to determine the portions +// of the address/register operations. - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - u8 temp; - const u32 rt=_Rt_; - memRead8(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=(s8)temp; - } +void LB() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + s8 temp = memRead8(addr); + + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = temp; } -void LBU() { - u32 addr; +void LBU() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u8 temp = memRead8(addr); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - u8 temp; - const u32 rt=_Rt_; - memRead8(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=temp; - } + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = temp; } -void LH() { - u32 addr; +void LH() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - u16 temp; - const u32 rt=_Rt_; - memRead16(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=(s16)temp; - } + if( addr & 1 ) + throw R5900Exception::AddressError( addr, false ); + + s16 temp = memRead16(addr); + + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = temp; } -void LHU() { - u32 addr; +void LHU() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - u16 temp; - const u32 rt=_Rt_; - memRead16(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=temp; - } + if( addr & 1 ) + throw R5900Exception::AddressError( addr, false ); + + u16 temp = memRead16(addr); + + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = temp; } +void LW() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; -void LW() { - u32 addr; + if( addr & 3 ) + throw R5900Exception::AddressError( addr, false ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + u32 temp = memRead32(addr); - u32 temp; - const u32 rt=_Rt_; - memRead32(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=(s32)temp; - } + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].SD[0] = (s32)temp; } -void LWU() { - u32 addr; +void LWU() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 3 ) + throw R5900Exception::AddressError( addr, false ); + + u32 temp = memRead32(addr); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - - u32 temp; - const u32 rt=_Rt_; - memRead32(addr, &temp); - if(rt!=0) - { - cpuRegs.GPR.r[rt].UD[0]=temp; - } + if (!_Rt_) return; + cpuRegs.GPR.r[_Rt_].UD[0] = temp; } static const s32 LWL_MASK[4] = { 0xffffff, 0x0000ffff, 0x000000ff, 0x00000000 }; @@ -320,13 +433,15 @@ static const s32 LWR_MASK[4] = { 0x000000, 0xff000000, 0xffff0000, 0xffffff00 }; static const u8 LWL_SHIFT[4] = { 24, 16, 8, 0 }; static const u8 LWR_SHIFT[4] = { 0, 8, 16, 24 }; -void LWL() { - if (!_Rt_) return; - +void LWL() +{ s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 3; - s32 mem; // ensure the compiler does correct sign extension into 64 bits by using s32 - memRead32(addr & ~3, (u32*)&mem); + + // ensure the compiler does correct sign extension into 64 bits by using s32 + s32 mem = memRead32(addr & ~3); + + if (!_Rt_) return; cpuRegs.GPR.r[_Rt_].SD[0] = (cpuRegs.GPR.r[_Rt_].SL[0] & LWL_MASK[shift]) | (mem << LWL_SHIFT[shift]); @@ -342,15 +457,14 @@ void LWL() { */ } -void LWR() { - - if (!_Rt_) return; - +void LWR() +{ s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 3; - u32 mem; - memRead32(addr & ~3, &mem); + u32 mem = memRead32(addr & ~3); + + if (!_Rt_) return; // Use unsigned math here, and conditionally sign extend below, when needed. mem = (cpuRegs.GPR.r[_Rt_].UL[0] & LWR_MASK[shift]) | (mem >> LWR_SHIFT[shift]); @@ -377,16 +491,26 @@ void LWR() { */ } -void LD() { - s32 addr; +// dummy variable used as a destination address for writes to the zero register, so +// that the zero register always stays zero. +PCSX2_ALIGNED16( static GPR_reg m_dummy_gpr_zero ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - if (_Rt_) { - memRead64(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); - } else { - u64 dummy; - memRead64(addr, &dummy); - } +// Returns the x86 address of the requested GPR, which is safe for writing. (includes +// special handling for returning a dummy var for GPR0(zero), so that it's value is +// always preserved) +static u64* gpr_GetWritePtr( uint gpr ) +{ + return (u64*)(( gpr == 0 ) ? &m_dummy_gpr_zero : &cpuRegs.GPR.r[gpr]); +} + +void LD() +{ + s32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 7 ) + throw R5900Exception::AddressError( addr, false ); + + memRead64(addr, gpr_GetWritePtr(_Rt_)); } static const u64 LDL_MASK[8] = @@ -402,60 +526,65 @@ static const u8 LDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; static const u8 LDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; -void LDL() { +void LDL() +{ u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 7; - u64 mem; - if (!_Rt_) return; + u64 mem; memRead64(addr & ~7, &mem); + + if( !_Rt_ ) return; cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDL_MASK[shift]) | (mem << LDL_SHIFT[shift]); } -void LDR() { +void LDR() +{ u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 7; + u64 mem; + memRead64(addr & ~7, &mem); if (!_Rt_) return; - memRead64(addr & ~7, &mem); cpuRegs.GPR.r[_Rt_].UD[0] = (cpuRegs.GPR.r[_Rt_].UD[0] & LDR_MASK[shift]) | (mem >> LDR_SHIFT[shift]); } -void LQ() { - u32 addr; +void LQ() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - addr&=~0xf; + if( addr & 15 ) + throw R5900Exception::AddressError( addr, false ); - if (_Rt_) { - memRead128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); - } else { - u64 val[2]; - memRead128(addr, val); - } + memRead128(addr & ~0xf, gpr_GetWritePtr(_Rt_)); } -void SB() { - u32 addr; - - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); +void SB() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + memWrite8(addr, cpuRegs.GPR.r[_Rt_].UC[0]); } -void SH() { - u32 addr; +void SH() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 1 ) + throw R5900Exception::AddressError( addr, true ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; memWrite16(addr, cpuRegs.GPR.r[_Rt_].US[0]); } -void SW(){ - u32 addr; +void SW() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 3 ) + throw R5900Exception::AddressError( addr, true ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; memWrite32(addr, cpuRegs.GPR.r[_Rt_].UL[0]); } @@ -465,17 +594,17 @@ static const u32 SWR_MASK[4] = { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff static const u8 SWR_SHIFT[4] = { 0, 8, 16, 24 }; static const u8 SWL_SHIFT[4] = { 24, 16, 8, 0 }; -void SWL() { +void SWL() +{ u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 3; - u32 mem; - - memRead32(addr & ~3, &mem); + u32 mem = memRead32( addr & ~3 ); memWrite32( addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] >> SWL_SHIFT[shift]) | (mem & SWL_MASK[shift]) ); + /* Mem = 1234. Reg = abcd @@ -489,9 +618,7 @@ void SWL() { void SWR() { u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 3; - u32 mem; - - memRead32(addr & ~3, &mem); + u32 mem = memRead32(addr & ~3); memWrite32( addr & ~3, (cpuRegs.GPR.r[_Rt_].UL[0] << SWR_SHIFT[shift]) | @@ -508,10 +635,13 @@ void SWR() { */ } -void SD() { - u32 addr; +void SD() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 7 ) + throw R5900Exception::AddressError( addr, true ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; memWrite64(addr,&cpuRegs.GPR.r[_Rt_].UD[0]); } @@ -527,7 +657,8 @@ static const u64 SDR_MASK[8] = static const u8 SDL_SHIFT[8] = { 56, 48, 40, 32, 24, 16, 8, 0 }; static const u8 SDR_SHIFT[8] = { 0, 8, 16, 24, 32, 40, 48, 56 }; -void SDL() { +void SDL() +{ u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 7; u64 mem; @@ -539,7 +670,8 @@ void SDL() { } -void SDR() { +void SDR() +{ u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; u32 shift = addr & 7; u64 mem; @@ -550,12 +682,14 @@ void SDR() { memWrite64(addr & ~7, &mem ); } -void SQ() { - u32 addr; +void SQ() +{ + u32 addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; + + if( addr & 15 ) + throw R5900Exception::AddressError( addr, true ); - addr = cpuRegs.GPR.r[_Rs_].UL[0] + _Imm_; - addr&=~0xf; - memWrite128(addr, &cpuRegs.GPR.r[_Rt_].UD[0]); + memWrite128(addr & ~0xf, &cpuRegs.GPR.r[_Rt_].UD[0]); } /********************************************************* @@ -681,7 +815,7 @@ void SYSCALL() if (call == 0x7c) { if(cpuRegs.GPR.n.a0.UL[0] == 0x10) - Console::Write( Color_Cyan, (char*)PSM(PSMu32(cpuRegs.GPR.n.a1.UL[0])) ); + Console::Write( Color_Cyan, (char*)PSM(memRead32(cpuRegs.GPR.n.a1.UL[0])) ); else __Deci2Call( cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0]) ); } @@ -727,110 +861,45 @@ void MTSA( void ) { cpuRegs.sa = (s32)cpuRegs.GPR.r[_Rs_].SD[0]; } +// SNY supports three basic modes, two which synchronize memory accesses (related +// to the cache) and one which synchronizes the instruction pipeline (effectively +// a stall in either case). Our emulation model does not track EE-side pipeline +// status or stalls, nor does it implement the CACHE. Thus SYNC need do nothing. void SYNC( void ) { } +// Used to prefetch data into the EE's cache, or schedule a dirty write-back. +// CACHE is not emulated at this time (nor is there any need to emulate it), so +// this function does nothing in the context of our emulator. void PREF( void ) { } - /********************************************************* * Register trap * * Format: OP rs, rt * *********************************************************/ -void TGE() { - if (cpuRegs.GPR.r[_Rs_].SD[0]>= cpuRegs.GPR.r[_Rt_].SD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TGE\n" ); -} - -void TGEU() { - if (cpuRegs.GPR.r[_Rs_].UD[0]>= cpuRegs.GPR.r[_Rt_].UD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TGEU\n" ); -} - -void TLT() { - if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TLT\n" ); -} - -void TLTU() { - if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TLTU\n" ); -} - -void TEQ() { - if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TEQ\n" ); -} - -void TNE() { - if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: TNE\n" ); -} +void TGE() { if (cpuRegs.GPR.r[_Rs_].SD[0] >= cpuRegs.GPR.r[_Rt_].SD[0]) throw R5900Exception::Trap(_TrapCode_); } +void TGEU() { if (cpuRegs.GPR.r[_Rs_].UD[0] >= cpuRegs.GPR.r[_Rt_].UD[0]) throw R5900Exception::Trap(_TrapCode_); } +void TLT() { if (cpuRegs.GPR.r[_Rs_].SD[0] < cpuRegs.GPR.r[_Rt_].SD[0]) throw R5900Exception::Trap(_TrapCode_); } +void TLTU() { if (cpuRegs.GPR.r[_Rs_].UD[0] < cpuRegs.GPR.r[_Rt_].UD[0]) throw R5900Exception::Trap(_TrapCode_); } +void TEQ() { if (cpuRegs.GPR.r[_Rs_].SD[0] == cpuRegs.GPR.r[_Rt_].SD[0]) throw R5900Exception::Trap(_TrapCode_); } +void TNE() { if (cpuRegs.GPR.r[_Rs_].SD[0] != cpuRegs.GPR.r[_Rt_].SD[0]) throw R5900Exception::Trap(_TrapCode_); } /********************************************************* * Trap with immediate operand * * Format: OP rs, rt * *********************************************************/ -void TGEI() { - - if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} - -void TGEIU() { - if (cpuRegs.GPR.r[_Rs_].UD[0] >= _ImmU_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} - -void TLTI() { - if(cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} - -void TLTIU() { - if (cpuRegs.GPR.r[_Rs_].UD[0] < _ImmU_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} - -void TEQI() { - if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} - -void TNEI() { - if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) { - cpuException(EXC_CODE_Tr, cpuRegs.branch); - } - //SysPrintf( "TrapInstruction: Immediate\n" ); -} +void TGEI() { if (cpuRegs.GPR.r[_Rs_].SD[0] >= _Imm_) throw R5900Exception::Trap(); } +void TLTI() { if (cpuRegs.GPR.r[_Rs_].SD[0] < _Imm_) throw R5900Exception::Trap(); } +void TEQI() { if (cpuRegs.GPR.r[_Rs_].SD[0] == _Imm_) throw R5900Exception::Trap(); } +void TNEI() { if (cpuRegs.GPR.r[_Rs_].SD[0] != _Imm_) throw R5900Exception::Trap(); } +void TGEIU() { if (cpuRegs.GPR.r[_Rs_].UD[0] >= (u64)_Imm_) throw R5900Exception::Trap(); } +void TLTIU() { if (cpuRegs.GPR.r[_Rs_].UD[0] < (u64)_Imm_) throw R5900Exception::Trap(); } /********************************************************* * Sa intructions * diff --git a/pcsx2/Sif.cpp b/pcsx2/Sif.cpp index 0b986ec392..d61319a473 100644 --- a/pcsx2/Sif.cpp +++ b/pcsx2/Sif.cpp @@ -18,8 +18,10 @@ #include "PrecompiledHeader.h" -#include "Sif.h" -#include "IopHw.h" +#define _PC_ // disables MIPS opcode macros. + +#include "PsxCommon.h" +#include "Common.h" #include "Sifcmd.h" using namespace std; @@ -28,8 +30,6 @@ using namespace std; #define sif1dma ((DMACh*)&PS2MEM_HW[0xc400]) #define sif2dma ((DMACh*)&PS2MEM_HW[0xc800]) -int eeSifTransfer; - DMACh *sif0ch; DMACh *sif1ch; DMACh *sif2ch; diff --git a/pcsx2/Sif.h b/pcsx2/Sif.h index 7f9d0bf1f0..9436a1e461 100644 --- a/pcsx2/Sif.h +++ b/pcsx2/Sif.h @@ -19,8 +19,6 @@ #ifndef __SIF_H__ #define __SIF_H__ -#include "Common.h" - struct sifData{ int data, words, @@ -28,8 +26,6 @@ struct sifData{ addr; }; -extern int eeSifTransfer; - extern DMACh *sif0ch; extern DMACh *sif1ch; extern DMACh *sif2ch; diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index ede54dbb5f..afafab1ff8 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -37,6 +37,8 @@ #include "vtlb.h" #include "COP0.h" +#include "R5900Exceptions.h" + using namespace R5900; using namespace vtlb_private; @@ -166,7 +168,7 @@ __forceinline void __fastcall MemOp_w0(u32 addr, DataType data) //has to: translate, find function, call function u32 hand=(u8)vmv; u32 paddr=ppf-hand+0x80000000; - //SysPrintf("Translted 0x%08X to 0x%08X\n",addr,paddr); + //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); switch( DataSize ) { @@ -195,7 +197,7 @@ __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data) //has to: translate, find function, call function u32 hand=(u8)vmv; u32 paddr=ppf-hand+0x80000000; - //SysPrintf("Translted 0x%08X to 0x%08X\n",addr,paddr); + //SysPrintf("Translated 0x%08X to 0x%08X\n",addr,paddr); switch( DataSize ) { case 64: return ((vtlbMemW64FP*)RWFT[3][1][hand])(paddr, data); @@ -206,6 +208,7 @@ __forceinline void __fastcall MemOp_w1(u32 addr,const DataType* data) } } + mem8_t __fastcall vtlb_memRead8(u32 mem) { return MemOp_r0<8,mem8_t>(mem); @@ -247,12 +250,6 @@ void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value) MemOp_w1<128,mem128_t>(mem,value); } -// Some functions used by interpreters and stuff... -// These maintain a "consistent" API with 64/128 reads. -void __fastcall memRead8(u32 mem, u8 *out) { *out = vtlb_memRead8( mem ); } -void __fastcall memRead16(u32 mem, u16 *out) { *out = vtlb_memRead16( mem ); } -void __fastcall memRead32(u32 mem, u32 *out) { *out = vtlb_memRead32( mem ); } - ///////////////////////////////////////////////////////////////////////// // Error / TLB Miss Handlers // @@ -265,21 +262,18 @@ static const char* _getModeStr( u32 mode ) // Generates a tlbMiss Exception static __forceinline void vtlb_Miss(u32 addr,u32 mode) { - Console::Error( "vtlb miss : addr 0x%X, mode %d [%s]", params addr, mode, _getModeStr(mode) ); - verify(false); - - if (mode==0) - cpuTlbMissR(addr, cpuRegs.branch); - else - cpuTlbMissW(addr, cpuRegs.branch); + //Console::Error( "vtlb miss : addr 0x%X, mode %d [%s]", params addr, mode, _getModeStr(mode) ); + //verify(false); + throw R5900Exception::TLBMiss( addr, !!mode ); } // Just dies a horrible death for now. // Eventually should generate a BusError exception. static __forceinline void vtlb_BusError(u32 addr,u32 mode) { - Console::Error( "vtlb bus error : addr 0x%X, mode %d\n", params addr, _getModeStr(mode) ); - verify(false); + //Console::Error( "vtlb bus error : addr 0x%X, mode %d\n", params addr, _getModeStr(mode) ); + //verify(false); + throw R5900Exception::BusError( addr, !!mode ); } ///// Virtual Mapping Errors (TLB Miss) @@ -344,7 +338,6 @@ void __fastcall vtlbDefaultPhyWrite128(u32 addr,const mem128_t* data) { Console: // VTLB Public API -- Init/Term/RegisterHandler stuff // - // Registers a handler into the VTLB's internal handler array. The handler defines specific behavior // for how memory pages bound to the handler are read from / written to. If any of the handler pointers // are NULL, the memory operations will be mapped to the BusError handler (thus generating BusError @@ -443,10 +436,9 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size) __forceinline void* vtlb_GetPhyPtr(u32 paddr) { if (paddr>=VTLB_PMAP_SZ || pmap[paddr>>VTLB_PAGE_BITS]<0) - return 0; + return NULL; else return reinterpret_cast(pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK)); - } //virtual mappings diff --git a/pcsx2/windows/DebugMemory.cpp b/pcsx2/windows/DebugMemory.cpp index 4fc8305e18..b6927c9fa0 100644 --- a/pcsx2/windows/DebugMemory.cpp +++ b/pcsx2/windows/DebugMemory.cpp @@ -33,7 +33,7 @@ unsigned char Debug_Read8(unsigned long addr)//just for anycase.. { #endif u8 val8; - memRead8(addr, &val8); + val8 = memRead8(addr); return val8; #ifdef _WIN32 } @@ -132,7 +132,7 @@ BOOL APIENTRY DumpMemProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) else { for (addr = start_pc; addr < end_pc; addr ++) { - memRead8( addr, &data ); + data = memRead8( addr ); fwrite(&data, 1, 1, fp); } diff --git a/pcsx2/windows/Debugger.cpp b/pcsx2/windows/Debugger.cpp index 9b8d2c8f63..c1e329e8f9 100644 --- a/pcsx2/windows/Debugger.cpp +++ b/pcsx2/windows/Debugger.cpp @@ -49,7 +49,7 @@ void RefreshDebugAll()//refresh disasm and register window void MakeDebugOpcode(void) { - memRead32( opcode_addr, &cpuRegs.code ); + cpuRegs.code = memRead32( opcode_addr ); } void MakeIOPDebugOpcode(void) @@ -459,7 +459,7 @@ BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam */ EnterRunningState(hDlg); - memRead32(cpuRegs.pc, &cpuRegs.code); + cpuRegs.code = memRead32(cpuRegs.pc); { u32 target_pc = 0; diff --git a/pcsx2/windows/RDebugger.cpp b/pcsx2/windows/RDebugger.cpp index 8da4d9c8bb..52fd700ddc 100644 --- a/pcsx2/windows/RDebugger.cpp +++ b/pcsx2/windows/RDebugger.cpp @@ -204,16 +204,17 @@ DWORD WINAPI Run2(LPVOID lpParam){ while (1){ if (runStatus==RUN){ - if (PSMu32(cpuRegs.pc)==0x0000000D){ + const u32 opcode = memRead32(cpuRegs.pc); + if (opcode==0x0000000D){ sendBREAK('E', 0, runCode, 0x22, runCount); InterlockedExchange(&runStatus, STOP); continue; } if ((runCode==2) && (//next - ((PSMu32(cpuRegs.pc) & 0xFC000000)==0x0C000000) ||//JAL - ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x00000009) ||//JALR - ((PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C) //SYSCALL - )){u32 tmppc=cpuRegs.pc, skip=(PSMu32(cpuRegs.pc) & 0xFC00003F)==0x0000000C ? 4 : 8; + ((opcode & 0xFC000000)==0x0C000000) ||//JAL + ((opcode & 0xFC00003F)==0x00000009) ||//JALR + ((opcode & 0xFC00003F)==0x0000000C) //SYSCALL + )){u32 tmppc=cpuRegs.pc, skip=(opcode & 0xFC00003F)==0x0000000C ? 4 : 8; while (cpuRegs.pc!=tmppc+skip) Cpu->Step(); }else diff --git a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj index fb9bb61051..fdd1578dfd 100644 --- a/pcsx2/windows/VCprojects/pcsx2_2008.vcproj +++ b/pcsx2/windows/VCprojects/pcsx2_2008.vcproj @@ -1839,6 +1839,10 @@ RelativePath="..\..\R5900.h" > + + diff --git a/pcsx2/windows/WinMain.cpp b/pcsx2/windows/WinMain.cpp index 208abfe3dc..008d0ebaa7 100644 --- a/pcsx2/windows/WinMain.cpp +++ b/pcsx2/windows/WinMain.cpp @@ -775,30 +775,6 @@ LRESULT WINAPI MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) MemcardConfig::OpenDialog(); break; - case ID_PROCESSLOW: - Config.ThPriority = THREAD_PRIORITY_LOWEST; - SaveConfig(); - CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_UNCHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_UNCHECKED); - break; - - case ID_PROCESSNORMAL: - Config.ThPriority = THREAD_PRIORITY_NORMAL; - SaveConfig(); - CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_UNCHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_UNCHECKED); - break; - - case ID_PROCESSHIGH: - Config.ThPriority = THREAD_PRIORITY_HIGHEST; - SaveConfig(); - CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_UNCHECKED); - CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_UNCHECKED); - break; - case ID_CONSOLE: Config.PsxOut = !Config.PsxOut; if(Config.PsxOut) @@ -919,36 +895,36 @@ void ResetMenuSlots() { #define _ADDSUBMENU(menu, menun, string) \ - submenu[menun] = CreatePopupMenu(); \ - AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); +{ submenu[menun] = CreatePopupMenu(); \ + AppendMenu(menu, MF_STRING | MF_POPUP, (UINT)submenu[menun], string); } #define ADDSUBMENU(menun, string) \ _ADDSUBMENU(gApp.hMenu, menun, string); #define ADDSUBMENUS(submn, menun, string) \ - submenu[menun] = CreatePopupMenu(); \ - InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); +{ submenu[menun] = CreatePopupMenu(); \ + InsertMenu(submenu[submn], 0, MF_BYPOSITION | MF_STRING | MF_POPUP, (UINT)submenu[menun], string); } #define ADDMENUITEM(menun, string, id) \ - item.fType = MFT_STRING; \ +{ item.fType = MFT_STRING; \ item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ item.fState = MFS_ENABLED; \ item.wID = id; \ sprintf(buf, string); \ - InsertMenuItem(submenu[menun], 0, TRUE, &item); + InsertMenuItem(submenu[menun], 0, TRUE, &item); } #define ADDMENUITEMC(menun, string, id) \ - item.fType = MFT_STRING; \ +{ item.fType = MFT_STRING; \ item.fMask = MIIM_STATE | MIIM_TYPE | MIIM_ID; \ item.fState = MFS_ENABLED | MFS_CHECKED; \ item.wID = id; \ sprintf(buf, string); \ - InsertMenuItem(submenu[menun], 0, TRUE, &item); + InsertMenuItem(submenu[menun], 0, TRUE, &item); } #define ADDSEPARATOR(menun) \ - item.fMask = MIIM_TYPE; \ +{ item.fMask = MIIM_TYPE; \ item.fType = MFT_SEPARATOR; \ - InsertMenuItem(submenu[menun], 0, TRUE, &item); + InsertMenuItem(submenu[menun], 0, TRUE, &item); } void CreateMainMenu() { MENUITEMINFO item; @@ -989,9 +965,6 @@ void CreateMainMenu() { ADDSUBMENU(0, _("&Run")); ADDSUBMENUS(0, 1, _("&Process Priority")); - ADDMENUITEM(1, _("&Low"), ID_PROCESSLOW ); - ADDMENUITEM(1, _("High"), ID_PROCESSHIGH); - ADDMENUITEM(1, _("Normal"), ID_PROCESSNORMAL); if( IsDevBuild ) { ADDMENUITEM(0,_("&Arguments"), ID_RUN_CMDLINE); } @@ -1110,9 +1083,6 @@ void CreateMainWindow() CreateMainMenu(); SetMenu(gApp.hWnd, gApp.hMenu); - if(Config.ThPriority==THREAD_PRIORITY_NORMAL) CheckMenuItem(gApp.hMenu,ID_PROCESSNORMAL,MF_CHECKED); - if(Config.ThPriority==THREAD_PRIORITY_HIGHEST) CheckMenuItem(gApp.hMenu,ID_PROCESSHIGH,MF_CHECKED); - if(Config.ThPriority==THREAD_PRIORITY_LOWEST) CheckMenuItem(gApp.hMenu,ID_PROCESSLOW,MF_CHECKED); if(Config.PsxOut) CheckMenuItem(gApp.hMenu,ID_CONSOLE,MF_CHECKED); if(Config.Patch) CheckMenuItem(gApp.hMenu,ID_PATCHES,MF_CHECKED); if(Config.Profiler) CheckMenuItem(gApp.hMenu,ID_PROFILER,MF_CHECKED); diff --git a/pcsx2/windows/WinSysExec.cpp b/pcsx2/windows/WinSysExec.cpp index a39e963ca5..3cde7d6d73 100644 --- a/pcsx2/windows/WinSysExec.cpp +++ b/pcsx2/windows/WinSysExec.cpp @@ -228,6 +228,9 @@ static void TryRecoverFromGsState() } } + +#include "R5900Exceptions.h" + void ExecuteCpu() { // Make sure any left-over recovery states are cleaned up. @@ -259,20 +262,34 @@ void ExecuteCpu() timeBeginPeriod( 1 ); - if( CHECK_EEREC ) + try { - while( !g_ReturnToGui ) + if( CHECK_EEREC ) { - recExecute(); - SysUpdate(); + while( !g_ReturnToGui ) + { + recExecute(); + SysUpdate(); + } + } + else + { + while( !g_ReturnToGui ) + { + Cpu->Execute(); + SysUpdate(); + } } } - else + catch( R5900Exception::BaseExcept& ex ) { - while( !g_ReturnToGui ) + Console::Error( ex.cMessage() ); + Console::Error( fmt_string( "(EE) PC: 0x%8.8x \tCycle:0x8.8x", ex.cpuState.pc, ex.cpuState.cycle ).c_str() ); + + if( !Config.PsxOut ) { - Cpu->Execute(); - SysUpdate(); + // TODO : no console opened, so use a popup to msg the user. + // Need to take care to shut down the GS first, or else it'll cause ugliness on fullscreen execution. } } @@ -286,8 +303,6 @@ void ExecuteCpu() // Used by Run::FromCD and such void RunExecute( const char* elf_file, bool use_bios ) { - SetThreadPriority(GetCurrentThread(), Config.ThPriority); - SetPriorityClass(GetCurrentProcess(), Config.ThPriority == THREAD_PRIORITY_HIGHEST ? ABOVE_NORMAL_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS); nDisableSC = 1; try diff --git a/pcsx2/windows/ini.cpp b/pcsx2/windows/ini.cpp index f95257b7d1..75d1bc08bd 100644 --- a/pcsx2/windows/ini.cpp +++ b/pcsx2/windows/ini.cpp @@ -196,8 +196,6 @@ void IniFile::DoConfig( PcsxConfig& Conf ) Entry( "Profiler", Conf.Profiler, false ); Entry( "CdvdVerbose", Conf.cdvdPrint, false ); - Entry( "ThreadPriority", Conf.ThPriority, THREAD_PRIORITY_NORMAL ); - SetCurrentSection( "Framelimiter" ); Entry( "CustomFps", Conf.CustomFps ); Entry( "FrameskipMode", Conf.CustomFrameSkip ); diff --git a/pcsx2/windows/resource.h b/pcsx2/windows/resource.h index 1390c7e8ba..1bd67db2e4 100644 --- a/pcsx2/windows/resource.h +++ b/pcsx2/windows/resource.h @@ -707,9 +707,6 @@ #define IDC_PATCHNAMELIST 40050 #define IDC_GAMENAMESEARCH 40051 #define IDC_SEARCHPATCHTEXT 40052 -#define ID_PROCESSLOW 40053 -#define ID_PROCESSNORMAL 40054 -#define ID_PROCESSHIGH 40055 #define ID_CONSOLE 40056 #define ID_PATCHES 40057 #define ID_CONFIG_ADVANCED 40058 diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index 49d390530a..eca0384526 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -971,7 +971,7 @@ void psxSetBranchImm( u32 imm ) //fixme : this is all a huge hack, we base the counter advancements on the average an opcode should take (wtf?) // If that wasn't bad enough we have default values like 9/8 which will get cast to int later -// (yeah, that means all sync code couldn't have worked to beginn with) +// (yeah, that means all sync code couldn't have worked to begin with) // So for now these are new settings that work. // (rama) @@ -998,7 +998,7 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch) // Continue onward with branching here: x86SetJ8( j8Ptr[2] ); - // check if should branch + // check if an event is pending SUB32MtoR(ECX, (uptr)&g_psxNextBranchCycle); j8Ptr[0] = JS8( 0 ); @@ -1128,10 +1128,7 @@ void psxRecompileNextInstruction(int delayslot) MOV32ItoR(EAX, psxpc); #endif - s_pCode = iopVirtMemR( psxpc ); - assert(s_pCode); - - psxRegs.code = *(int *)s_pCode; + psxRegs.code = iopMemRead32( psxpc ); s_psxBlockCycles++; psxpc += 4; @@ -1146,10 +1143,6 @@ void psxRecompileNextInstruction(int delayslot) g_pCurInstInfo++; -#ifdef PCSX2_VM_COISSUE - assert( g_pCurInstInfo->info & EEINSTINFO_COREC ); -#endif - g_iopCyclePenalty = 0; rpsxBSC[ psxRegs.code >> 26 ](); s_psxBlockCycles += g_iopCyclePenalty; diff --git a/pcsx2/x86/iVUzerorec.cpp b/pcsx2/x86/iVUzerorec.cpp index 51c1b3cd2c..fcca31ef3b 100644 --- a/pcsx2/x86/iVUzerorec.cpp +++ b/pcsx2/x86/iVUzerorec.cpp @@ -510,15 +510,12 @@ u32 SuperVUGetVIAddr(int reg, int read) void SuperVUDumpBlock(list& blocks, int vuindex) { FILE *f; - string filename; char str[256]; u32 *mem; u32 i; Path::CreateDirectory( "dumps" ); - ssprintf( filename, "svu%cdump%.4X.txt", s_vu?'0':'1', s_pFnHeader->startpc ); - filename = Path::Combine( "dumps", filename ); - + string filename( Path::Combine( "dumps", fmt_string( "svu%cdump%.4X.txt", s_vu?'0':'1', s_pFnHeader->startpc ) ) ); //SysPrintf( "dump1 %x => %s\n", s_pFnHeader->startpc, filename ); f = fopen( filename.c_str(), "w" ); diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 066253354c..f50291d81d 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -153,7 +153,7 @@ static void iDumpBlock( int startpc, u8 * ptr ) if( disR5900GetSym(startpc) != NULL ) fprintf(f, "%s\n", disR5900GetSym(startpc)); for ( i = startpc; i < s_nEndBlock; i += 4 ) { - disR5900Fasm( output, PSMu32( i ), i ); + disR5900Fasm( output, memRead32( i ), i ); fprintf( f, output.c_str() ); }