diff --git a/Externals/Bochs_disasm/PowerPCDisasm.cpp b/Externals/Bochs_disasm/PowerPCDisasm.cpp
index f1b215774c..b2b91fcf41 100644
--- a/Externals/Bochs_disasm/PowerPCDisasm.cpp
+++ b/Externals/Bochs_disasm/PowerPCDisasm.cpp
@@ -2075,7 +2075,7 @@ namespace PPCDisasm
break;
case 20:
- fdabc(dp,in,"sqrte",2,0);
+ fdabc(dp,in,"rsqrte",2,0);
break;
case 24:
diff --git a/Externals/wxWidgets/include/wx/msw/listctrl.h b/Externals/wxWidgets/include/wx/msw/listctrl.h
index 725a587e23..8249483441 100644
--- a/Externals/wxWidgets/include/wx/msw/listctrl.h
+++ b/Externals/wxWidgets/include/wx/msw/listctrl.h
@@ -12,6 +12,7 @@
#ifndef _WX_LISTCTRL_H_
#define _WX_LISTCTRL_H_
+#include "wx/dcbuffer.h"
#include "wx/textctrl.h"
class WXDLLIMPEXP_FWD_CORE wxImageList;
diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj
index d50aab1792..2f1cf2d900 100644
--- a/Source/Core/Core/Core.vcproj
+++ b/Source/Core/Core/Core.vcproj
@@ -50,6 +50,7 @@
BasicRuntimeChecks="3"
RuntimeLibrary="1"
BufferSecurityCheck="true"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -118,6 +119,7 @@
BasicRuntimeChecks="3"
RuntimeLibrary="1"
BufferSecurityCheck="true"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -190,7 +192,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="2"
- FloatingPointModel="2"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -265,7 +267,7 @@
RuntimeLibrary="0"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="0"
- FloatingPointModel="2"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -336,6 +338,7 @@
PreprocessorDefinitions="NDEBUG;_LIB;LOGGING;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -407,6 +410,7 @@
PreprocessorDefinitions="NDEBUG;_LIB;LOGGING;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
+ FloatingPointModel="0"
UsePrecompiledHeader="2"
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
@@ -835,6 +839,14 @@
+
+
+
+
+
@@ -851,6 +867,14 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1025,6 +1009,46 @@
RelativePath=".\Src\Debugger\PPCDebugInterface.h"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#include
#ifdef _WIN32
#include
@@ -26,16 +27,87 @@
#include "../../Core.h"
#include "Interpreter.h"
-// If you wanna have fun, read:
-// 80007e08 in super monkey ball
+// SUPER MONKEY BALL IS BEING A ROYAL PAIN
+// We are missing the caller of 800070ec
+// POSSIBLE APPROACHES:
+// * Full SW FPU. Urgh.
+// * Partial SW FPU, emulate just as much as necessary for monkey ball. Feasible but a lot of work.
+// * HLE hacking. Figure out what all the evil functions really do and fake them.
+
+// Interesting places in Super Monkey Ball:
+// 80036654: fctwixz stuff
+// 80007e08:
+// -98: Various entry points that loads various odd fp values into f1
+// 800070b0: Estimate inverse square root.
+// 800070ec: Examine f1. Reads a value out of locked cache into f2 (fixed address). Some cases causes us to call the above thing.
+// If all goes well, jump to 70b0, which estimates the inverse square root.
+// Then multiply the loaded variable with the original value of f1. Result should be the square root. (1 / sqrt(x)) * x = x / sqrt(x) = sqrt(x)
+// 8000712c: Similar, but does not do the multiply at the end, just an frspx.
+// 8000716c: Sort of similar, but has extra junk at the end.
+//
+//
+// 800072a4 - nightmare of nightmares
// Fun stuff used:
// bso+
-// mcrfs (ARGH pulls stuff out of .. FPSCR). it uses this to check the result of frsp mostly
+// mcrfs (ARGH pulls stuff out of .. FPSCR). it uses this to check the result of frsp mostly (!!!!)
// crclr
// crset
// crxor
// fnabs
-//
+// Super Monkey Ball reads FPRF & friends after fmadds, fmuls, frspx
+// WHY do the FR & FI flags affect it so much?
+
+void UpdateFPSCR(UReg_FPSCR fp);
+void UpdateSSEState();
+
+void UpdateFPRF(double value)
+{
+ u64 ivalue = *((u64*)&value);
+ // 5 bits (C, <, >, =, ?)
+ // top: class descriptor
+ FPSCR.FPRF = 4;
+ // easy cases first
+ if (ivalue == 0) {
+ // positive zero
+ FPSCR.FPRF = 0x2;
+ } else if (ivalue == 0x8000000000000000ULL) {
+ // negative zero
+ FPSCR.FPRF = 0x12;
+ } else if (ivalue == 0x7FF0000000000000ULL) {
+ // positive inf
+ FPSCR.FPRF = 0x5;
+ } else if (ivalue == 0xFFF0000000000000ULL) {
+ // negative inf
+ FPSCR.FPRF = 0x9;
+ } else {
+ // OK let's dissect this thing.
+ int sign = ivalue >> 63;
+ int exp = (ivalue >> 52) & 0x7FF;
+ if (exp >= 1 && exp <= 2046) {
+ // Nice normalized number.
+ if (sign) {
+ FPSCR.FPRF = 0x8; // negative
+ } else {
+ FPSCR.FPRF = 0x4; // positive
+ }
+ return;
+ }
+ u64 mantissa = ivalue & 0x000FFFFFFFFFFFFFULL;
+ int mantissa_top = mantissa >> 51;
+ if (exp == 0 && mantissa) {
+ // Denormalized number.
+ if (sign) {
+ FPSCR.FPRF = 0x18;
+ } else {
+ FPSCR.FPRF = 0x14;
+ }
+ } else if (exp == 0x7FF && mantissa /* && mantissa_top*/) {
+ FPSCR.FPRF = 0x11; // Quiet NAN
+ return;
+ }
+ }
+}
+
// extremely rare
void CInterpreter::Helper_UpdateCR1(double _fValue)
@@ -48,110 +120,24 @@ void CInterpreter::Helper_UpdateCR1(double _fValue)
if (_fValue < 0.0)
FPSCR.FPRF |= 8;
SetCRField(1, (FPSCR.Hex & 0x0000F000) >> 12);
+
+ PanicAlert("CR1");
}
bool CInterpreter::IsNAN(double _dValue)
{
- // not implemented
return _dValue != _dValue;
}
-void CInterpreter::faddsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) + rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fdivsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) / rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmaddsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) =
- static_cast((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmsubsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) =
- static_cast((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmulsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) * rPS0(_inst.FC));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fnmaddsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) =
- static_cast(-((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB)));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fnmsubsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) =
- static_cast(-((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB)));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fresx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(1.0f / rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fsqrtsx(UGeckoInstruction _inst)
-{
- static bool bFirst = true;
- if (bFirst)
- PanicAlert("fsqrtsx - Instruction unimplemented");
- bFirst = false;
-}
-
-void CInterpreter::fsubsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) - rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-//
-//--- END OF SINGLE PRECISION ---
-//
-
-void CInterpreter::fabsx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = fabs(rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
void CInterpreter::fcmpo(UGeckoInstruction _inst)
{
double fa = rPS0(_inst.FA);
double fb = rPS0(_inst.FB);
u32 compareResult;
-
- if (IsNAN(fa) || IsNAN(fb)) compareResult = 1;
- else if(fa < fb) compareResult = 8;
- else if(fa > fb) compareResult = 4;
- else compareResult = 2;
+ if (IsNAN(fa) || IsNAN(fb)) compareResult = 1;
+ else if (fa < fb) compareResult = 8;
+ else if (fa > fb) compareResult = 4;
+ else compareResult = 2;
FPSCR.FPRF = compareResult;
SetCRField(_inst.CRFD, compareResult);
@@ -171,10 +157,10 @@ void CInterpreter::fcmpu(UGeckoInstruction _inst)
double fb = rPS0(_inst.FB);
u32 compareResult;
- if(IsNAN(fa) || IsNAN(fb)) compareResult = 1;
- else if(fa < fb) compareResult = 8;
- else if(fa > fb) compareResult = 4;
- else compareResult = 2;
+ if (IsNAN(fa) || IsNAN(fb)) compareResult = 1;
+ else if (fa < fb) compareResult = 8;
+ else if (fa > fb) compareResult = 4;
+ else compareResult = 2;
FPSCR.FPRF = compareResult;
SetCRField(_inst.CRFD, compareResult);
@@ -184,25 +170,36 @@ void CInterpreter::fcmpu(UGeckoInstruction _inst)
then VXSNAN ¬ 1 */
}
-
// Apply current rounding mode
void CInterpreter::fctiwx(UGeckoInstruction _inst)
{
- double b = rPS0(_inst.FB);
+ UpdateSSEState();
+ const double b = rPS0(_inst.FB);
u32 value;
- if (b > (double)0x7fffffff)
+ if (b > (double)0x7fffffff)
+ {
value = 0x7fffffff;
+ FPSCR.VXCVI = 1;
+ }
else if (b < -(double)0x7fffffff)
+ {
value = 0x80000000;
- else
- value = (u32)(s32)_mm_cvtsd_si32(_mm_set_sd(b)); // TODO(ector): enforce chop
+ FPSCR.VXCVI = 1;
+ }
+ else
+ {
+ value = (u32)(s32)_mm_cvtsd_si32(_mm_set_sd(b)); // obey current rounding mode
+ double d_value = (double)value;
+ bool inexact = (d_value != b);
+// FPSCR.FI = inexact ? 1 : 0;
+// FPSCR.XX |= FPSCR.FI;
+// FPSCR.FR = fabs(d_value) > fabs(b);
+ }
+
+ //TODO: FR
+ //FPRF undefined
riPS0(_inst.FD) = (u64)value; // zero extend
-
- /* TODO(ector):
- FPSCR[FR] is set if the result is incremented when rounded.
- FPSCR[FI] is set if the result is inexact.
- */
if (_inst.Rc)
Helper_UpdateCR1(rPS0(_inst.FD));
}
@@ -215,14 +212,29 @@ largest representable int on PowerPC. */
// Always round toward zero
void CInterpreter::fctiwzx(UGeckoInstruction _inst)
{
- double b = rPS0(_inst.FB);
+ //UpdateFPSCR(FPSCR);
+ const double b = rPS0(_inst.FB);
u32 value;
- if (b > (double)0x7fffffff)
+ if (b > (double)0x7fffffff)
+ {
value = 0x7fffffff;
- else if (b < -(double)0x7fffffff)
- value = 0x80000000;
- else
- value = (u32)(s32)_mm_cvttsd_si32(_mm_set_sd(b)); //TODO(ector): force round toward zero
+ FPSCR.VXCVI = 1;
+ }
+ else if (b < -(double)0x7fffffff)
+ {
+ value = 0x80000000;
+ FPSCR.VXCVI = 1;
+ }
+ else
+ {
+ value = (u32)(s32)_mm_cvttsd_si32(_mm_set_sd(b)); // truncate
+ double d_value = (double)value;
+ bool inexact = (d_value != b);
+// FPSCR.FI = inexact ? 1 : 0;
+// FPSCR.XX |= FPSCR.FI;
+// FPSCR.FR = 1; //fabs(d_value) > fabs(b);
+ }
+ //FPRF undefined
riPS0(_inst.FD) = (u64)value;
if (_inst.Rc)
@@ -232,109 +244,281 @@ void CInterpreter::fctiwzx(UGeckoInstruction _inst)
void CInterpreter::fmrx(UGeckoInstruction _inst)
{
riPS0(_inst.FD) = riPS0(_inst.FB);
-// rPS1(_inst.FD) = rPS0(_inst.FD); // TODO: Should this be here?
-
+ // This is a binary instruction. Does not alter FPSCR
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
+void CInterpreter::fabsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = fabs(rPS0(_inst.FB));
+ // This is a binary instruction. Does not alter FPSCR
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
void CInterpreter::fnabsx(UGeckoInstruction _inst)
{
riPS0(_inst.FD) = riPS0(_inst.FB) | (1ULL << 63);
-
+ // This is a binary instruction. Does not alter FPSCR
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void CInterpreter::fnegx(UGeckoInstruction _inst)
{
riPS0(_inst.FD) = riPS0(_inst.FB) ^ (1ULL << 63);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-// !!! warning !!!
-// PS1 must be set to the value of PS0 or DragonballZ will be f**ked up
-// PS1 is said to be undefined
-// TODO(ector): TODO(fires): does this apply to all of the below opcodes?
-void CInterpreter::frspx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::faddx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) + rPS0(_inst.FB);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fdivx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) / rPS0(_inst.FB);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmaddx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmsubx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fmulx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) * rPS0(_inst.FC);
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fnmaddx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = -((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fnmsubx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = -((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::frsqrtex(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = 1.0 / (sqrt(rPS0(_inst.FB)));
-
+ // This is a binary instruction. Does not alter FPSCR
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void CInterpreter::fselx(UGeckoInstruction _inst)
{
- rPS0(_inst.FD) = (rPS0(_inst.FA) >= 0.0) ? rPS0(_inst.FC) : rPS0(_inst.FB);
+ rPS0(_inst.FD) = (rPS0(_inst.FA) >= -0.0) ? rPS0(_inst.FC) : rPS0(_inst.FB);
+ // This is a binary instruction. Does not alter FPSCR
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+// !!! warning !!!
+// PS1 must be set to the value of PS0 or DragonballZ will be f**ked up
+// PS1 is said to be undefined
+// Super Monkey Ball is using this to do wacky tricks so we need 100% correct emulation.
+void CInterpreter::frspx(UGeckoInstruction _inst) // round to single
+{
+ if (true || FPSCR.RN != 0)
+ {
+ // Not used in Super Monkey Ball
+ UpdateSSEState();
+ double b = rPS0(_inst.FB);
+ double rounded = (double)(float)b;
+ FPSCR.FI = b != rounded; // changing both of these affect Super Monkey Ball behaviour greatly.
+ FPSCR.FR = 1; // WHY? fabs(rounded) > fabs(b);
+ rPS0(_inst.FD) = rPS1(_inst.FD) = rounded;
+ return;
+ // PanicAlert("frspx: FPSCR.RN=%i", FPSCR.RN);
+ }
+
+ // OK, let's try it in 100% software! Not yet working right.
+ union {
+ double d;
+ u64 i;
+ } in, out;
+ in.d = rPS0(_inst.FB);
+ out = in;
+ int sign = in.i >> 63;
+ int exp = (in.i >> 52) & 0x7FF;
+ u64 mantissa = in.i & 0x000FFFFFFFFFFFFFULL;
+ u64 mantissa_single = mantissa & 0x000FFFFFE0000000ULL;
+ u64 leftover_single = mantissa & 0x000000001FFFFFFFULL;
+
+ // OK. First make sure that we have a "normal" number.
+ if (exp >= 1 && exp <= 2046) {
+ // OK. Check for overflow. TODO
+
+ FPSCR.FI = leftover_single != 0; // Inexact
+ if (leftover_single >= 0x10000000ULL) {
+ //PanicAlert("rounding up");
+ FPSCR.FR = 1;
+ mantissa_single += 0x20000000;
+ if (mantissa_single & 0x0010000000000000) {
+ // PanicAlert("renormalizing");
+ mantissa_single >>= 1;
+ exp += 1;
+ // if (exp > 2046) { OVERFLOW }
+ }
+ }
+ out.i = ((u64)sign << 63) | ((u64)exp << 52) | mantissa_single;
+ } else {
+ if (!exp && !mantissa) {
+ // Positive or negative Zero. All is well.
+ FPSCR.FI = 0;
+ FPSCR.FR = 0;
+ } else if (exp == 0 && mantissa) {
+ // Denormalized number.
+ PanicAlert("denorm");
+ } else if (exp == 2047 && !mantissa) {
+ // Infinite.
+ //PanicAlert("infinite");
+ FPSCR.FI = 1;
+ FPSCR.FR = 1;
+// FPSCR.OX = 1;
+ } else {
+ //PanicAlert("NAN %08x %08x", in.i >> 32, in.i);
+ }
+ }
+ UpdateFPRF(out.d);
+ FPSCR.FR = 1; // SUPER MONKEY BALL HACK
+ rPS0(_inst.FD) = rPS1(_inst.FD) = out.d;
+
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fmulx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS0(_inst.FA) * rPS0(_inst.FC);
+ FPSCR.FI = 0;
+ FPSCR.FR = 1;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fmulsx(UGeckoInstruction _inst)
+{
+ double d_value = rPS0(_inst.FA) * rPS0(_inst.FC);
+ rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(d_value);
+ FPSCR.FI = d_value != rPS0(_inst.FD);
+ FPSCR.FR = rand()&1;
+ UpdateFPRF(rPS0(_inst.FD));
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fmaddx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
+ FPSCR.FI = 0;
+ FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fmaddsx(UGeckoInstruction _inst)
+{
+ double d_value = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
+ rPS0(_inst.FD) = rPS1(_inst.FD) =
+ static_cast(d_value);
+ FPSCR.FI = d_value != rPS0(_inst.FD);
+ FPSCR.FR = 0;
+ UpdateFPRF(rPS0(_inst.FD));
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::faddx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS0(_inst.FA) + rPS0(_inst.FB);
+// FPSCR.FI = 0;
+// FPSCR.FR = 1;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::faddsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) + rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 1;
+// FPSCR.Hex = (rand() ^ (rand() << 8) ^ (rand() << 16)) & ~(0x000000F8);
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fdivx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS0(_inst.FA) / rPS0(_inst.FB);
+// FPSCR.FI = 0;
+// FPSCR.FR = 1;
+ if (fabs(rPS0(_inst.FB)) == 0.0) {
+ FPSCR.ZX = 1;
+ }
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fdivsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) / rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 1;
+ if (fabs(rPS0(_inst.FB)) == 0.0) {
+ FPSCR.ZX = 1;
+ }
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fresx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(1.0f / rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 1;
+ if (fabs(rPS0(_inst.FB)) == 0.0) {
+ FPSCR.ZX = 1;
+ }
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fmsubx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB);
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+void CInterpreter::fmsubsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) =
+ static_cast((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fnmaddx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = -((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fnmaddsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) =
+ static_cast(-((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB)));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fnmsubx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = -((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fnmsubsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) =
+ static_cast(-((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB)));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::fsubx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS0(_inst.FA) - rPS0(_inst.FB);
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+void CInterpreter::fsubsx(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = rPS1(_inst.FD) = static_cast(rPS0(_inst.FA) - rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
+ if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
+}
+
+
+void CInterpreter::frsqrtex(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = 1.0f / (sqrtf(rPS0(_inst.FB)));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
void CInterpreter::fsqrtx(UGeckoInstruction _inst)
{
- rPS0(_inst.FD) = sqrt(rPS0(_inst.FB));
-
- if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
-}
-
-void CInterpreter::fsubx(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) - rPS0(_inst.FB);
+ rPS0(_inst.FD) = sqrt(rPS0(_inst.FB));
+// FPSCR.FI = 0;
+// FPSCR.FR = 0;
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
}
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
index d638885ac1..994fa5c06c 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
@@ -72,13 +72,13 @@ void CInterpreter::lfdu(UGeckoInstruction _inst)
void CInterpreter::lfdux(UGeckoInstruction _inst)
{
u32 uAddress = Helper_Get_EA_UX(_inst);
- riPS0(_inst.FS) = Memory::Read_U64(uAddress);
+ riPS0(_inst.FD) = Memory::Read_U64(uAddress);
m_GPR[_inst.RA] = uAddress;
}
void CInterpreter::lfdx(UGeckoInstruction _inst)
{
- riPS0(_inst.FS) = Memory::Read_U64(Helper_Get_EA_X(_inst));
+ riPS0(_inst.FD) = Memory::Read_U64(Helper_Get_EA_X(_inst));
}
void CInterpreter::lfs(UGeckoInstruction _inst)
@@ -149,7 +149,7 @@ void CInterpreter::lmw(UGeckoInstruction _inst)
return;
}
- m_GPR[iReg] = TempReg;
+ m_GPR[iReg] = TempReg;
}
}
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp
new file mode 100644
index 0000000000..57cfe46b37
--- /dev/null
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp
@@ -0,0 +1,337 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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, version 2.0.
+
+// 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 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include
+#include "Interpreter.h"
+#include "../../HW/Memmap.h"
+
+// dequantize table
+const float m_dequantizeTable[] =
+{
+ 1.0 / (1 << 0), 1.0 / (1 << 1), 1.0 / (1 << 2), 1.0 / (1 << 3),
+ 1.0 / (1 << 4), 1.0 / (1 << 5), 1.0 / (1 << 6), 1.0 / (1 << 7),
+ 1.0 / (1 << 8), 1.0 / (1 << 9), 1.0 / (1 << 10), 1.0 / (1 << 11),
+ 1.0 / (1 << 12), 1.0 / (1 << 13), 1.0 / (1 << 14), 1.0 / (1 << 15),
+ 1.0 / (1 << 16), 1.0 / (1 << 17), 1.0 / (1 << 18), 1.0 / (1 << 19),
+ 1.0 / (1 << 20), 1.0 / (1 << 21), 1.0 / (1 << 22), 1.0 / (1 << 23),
+ 1.0 / (1 << 24), 1.0 / (1 << 25), 1.0 / (1 << 26), 1.0 / (1 << 27),
+ 1.0 / (1 << 28), 1.0 / (1 << 29), 1.0 / (1 << 30), 1.0 / (1 << 31),
+ (1ULL << 32), (1 << 31), (1 << 30), (1 << 29),
+ (1 << 28), (1 << 27), (1 << 26), (1 << 25),
+ (1 << 24), (1 << 23), (1 << 22), (1 << 21),
+ (1 << 20), (1 << 19), (1 << 18), (1 << 17),
+ (1 << 16), (1 << 15), (1 << 14), (1 << 13),
+ (1 << 12), (1 << 11), (1 << 10), (1 << 9),
+ (1 << 8), (1 << 7), (1 << 6), (1 << 5),
+ (1 << 4), (1 << 3), (1 << 2), (1 << 1),
+};
+
+// quantize table
+const float m_quantizeTable[] =
+{
+ (1 << 0), (1 << 1), (1 << 2), (1 << 3),
+ (1 << 4), (1 << 5), (1 << 6), (1 << 7),
+ (1 << 8), (1 << 9), (1 << 10), (1 << 11),
+ (1 << 12), (1 << 13), (1 << 14), (1 << 15),
+ (1 << 16), (1 << 17), (1 << 18), (1 << 19),
+ (1 << 20), (1 << 21), (1 << 22), (1 << 23),
+ (1 << 24), (1 << 25), (1 << 26), (1 << 27),
+ (1 << 28), (1 << 29), (1 << 30), (1 << 31),
+ 1.0 / (1ULL << 32), 1.0 / (1 << 31), 1.0 / (1 << 30), 1.0 / (1 << 29),
+ 1.0 / (1 << 28), 1.0 / (1 << 27), 1.0 / (1 << 26), 1.0 / (1 << 25),
+ 1.0 / (1 << 24), 1.0 / (1 << 23), 1.0 / (1 << 22), 1.0 / (1 << 21),
+ 1.0 / (1 << 20), 1.0 / (1 << 19), 1.0 / (1 << 18), 1.0 / (1 << 17),
+ 1.0 / (1 << 16), 1.0 / (1 << 15), 1.0 / (1 << 14), 1.0 / (1 << 13),
+ 1.0 / (1 << 12), 1.0 / (1 << 11), 1.0 / (1 << 10), 1.0 / (1 << 9),
+ 1.0 / (1 << 8), 1.0 / (1 << 7), 1.0 / (1 << 6), 1.0 / (1 << 5),
+ 1.0 / (1 << 4), 1.0 / (1 << 3), 1.0 / (1 << 2), 1.0 / (1 << 1),
+};
+
+template
+inline T CLAMP(T a, T bottom, T top) {
+ if (a > top) return top;
+ if (a < bottom) return bottom;
+ return a;
+}
+
+void CInterpreter::Helper_Quantize(const u32 _Addr, const float _fValue,
+ const EQuantizeType _quantizeType, const unsigned int _uScale)
+{
+ switch(_quantizeType)
+ {
+ case QUANTIZE_FLOAT:
+ Memory::Write_U32(*(u32*)&_fValue,_Addr);
+ break;
+
+ // used for THP player
+ case QUANTIZE_U8:
+ {
+ float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], 0.0f, 255.0f);
+ Memory::Write_U8((u8)fResult, _Addr);
+ }
+ break;
+
+ case QUANTIZE_U16:
+ {
+ float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], 0.0f, 65535.0f);
+ Memory::Write_U16((u16)fResult, _Addr);
+ }
+ break;
+
+ case QUANTIZE_S8:
+ {
+ float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], -128.0f, 127.0f);
+ Memory::Write_U8((u8)(s8)fResult, _Addr);
+ }
+ break;
+
+ case QUANTIZE_S16:
+ {
+ float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], -32768.0f, 32767.0f);
+ Memory::Write_U16((u16)(s16)fResult, _Addr);
+ }
+ break;
+
+ default:
+ _dbg_assert_msg_(GEKKO,0,"PS dequantize","Unknown type to read");
+ break;
+ }
+}
+
+float CInterpreter::Helper_Dequantize(const u32 _Addr, const EQuantizeType _quantizeType,
+ const unsigned int _uScale)
+{
+ // dequantize the value
+ float fResult;
+ switch(_quantizeType)
+ {
+ case QUANTIZE_FLOAT:
+ {
+ u32 dwValue = Memory::Read_U32(_Addr);
+ fResult = *(float*)&dwValue;
+ }
+ break;
+
+ case QUANTIZE_U8:
+ fResult = static_cast(Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
+ break;
+
+ case QUANTIZE_U16:
+ fResult = static_cast(Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
+ break;
+
+ case QUANTIZE_S8:
+ fResult = static_cast((s8)Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
+ break;
+
+ // used for THP player
+ case QUANTIZE_S16:
+ fResult = static_cast((s16)Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
+ break;
+
+ default:
+ _dbg_assert_msg_(GEKKO,0,"PS dequantize","Unknown type to read");
+ fResult = 0;
+ break;
+ }
+
+ return fResult;
+}
+
+void CInterpreter::psq_l(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
+ const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
+ const unsigned int ldScale = gqr.LD_SCALE;
+ const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : _inst.SIMM_12;
+
+ int c = 4;
+ if ((ldType == QUANTIZE_U8) || (ldType == QUANTIZE_S8)) c = 0x1;
+ if ((ldType == QUANTIZE_U16) || (ldType == QUANTIZE_S16)) c = 0x2;
+
+ if (_inst.W == 0)
+ {
+ rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale);
+ rPS1(_inst.RS) = Helper_Dequantize(EA+c, ldType, ldScale);
+ }
+ else
+ {
+ rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale);
+ rPS1(_inst.RS) = 1.0f;
+ }
+}
+
+void CInterpreter::psq_lu(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
+ const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
+ const unsigned int ldScale = gqr.LD_SCALE;
+ const u32 EA = m_GPR[_inst.RA] + _inst.SIMM_12;
+
+ int c = 4;
+ if ((ldType == 4) || (ldType == 6)) c = 0x1;
+ if ((ldType == 5) || (ldType == 7)) c = 0x2;
+
+ if (_inst.W == 0)
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
+ }
+ else
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = 1.0f;
+ }
+ m_GPR[_inst.RA] = EA;
+}
+
+void CInterpreter::psq_st(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
+ const EQuantizeType stType = static_cast(gqr.ST_TYPE);
+ const unsigned int stScale = gqr.ST_SCALE;
+ const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : _inst.SIMM_12;
+
+ int c = 4;
+ if ((stType == 4) || (stType == 6)) c = 0x1;
+ if ((stType == 5) || (stType == 7)) c = 0x2;
+
+ if (_inst.W == 0)
+ {
+ Helper_Quantize( EA, (float)rPS0(_inst.RS), stType, stScale );
+ Helper_Quantize( EA+c, (float)rPS1(_inst.RS), stType, stScale );
+ }
+ else
+ {
+ Helper_Quantize( EA, (float)rPS0(_inst.RS), stType, stScale );
+ }
+}
+
+void CInterpreter::psq_stu(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
+ const EQuantizeType stType = static_cast(gqr.ST_TYPE);
+ const unsigned int stScale = gqr.ST_SCALE;
+ const u32 EA = m_GPR[_inst.RA] + _inst.SIMM_12;
+
+ int c = 4;
+ if ((stType == 4) || (stType == 6)) c = 0x1;
+ if ((stType == 5) || (stType == 7)) c = 0x2;
+
+ if (_inst.W == 0)
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
+ }
+ else
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ }
+ m_GPR[_inst.RA] = EA;
+}
+
+void CInterpreter::psq_lx(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
+ const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
+ const unsigned int ldScale = gqr.LD_SCALE;
+ const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB];
+
+ int c = 4;
+ if ((ldType == 4) || (ldType == 6)) c = 0x1;
+ if ((ldType == 5) || (ldType == 7)) c = 0x2;
+
+ if (_inst.Wx == 0)
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
+ }
+ else
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = 1.0f;
+ }
+}
+
+void CInterpreter::psq_stx(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
+ const EQuantizeType stType = static_cast(gqr.ST_TYPE);
+ const unsigned int stScale = gqr.ST_SCALE;
+ const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB];
+
+ int c = 4;
+ if ((stType == 4) || (stType == 6)) c = 0x1;
+ if ((stType == 5) || (stType == 7)) c = 0x2;
+
+ if (_inst.Wx == 0)
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
+ }
+ else
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ }
+}
+
+void CInterpreter::psq_lux(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
+ const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
+ const unsigned int ldScale = gqr.LD_SCALE;
+ const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB];
+
+ int c = 4;
+ if ((ldType == 4) || (ldType == 6)) c = 0x1;
+ if ((ldType == 5) || (ldType == 7)) c = 0x2;
+
+ if (_inst.Wx == 0)
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
+ }
+ else
+ {
+ rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
+ rPS1(_inst.RS) = 1.0f;
+ }
+ m_GPR[_inst.RA] = EA;
+}
+
+void CInterpreter::psq_stux(UGeckoInstruction _inst)
+{
+ const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
+ const EQuantizeType stType = static_cast(gqr.ST_TYPE);
+ const unsigned int stScale = gqr.ST_SCALE;
+ const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB];
+
+ int c = 4;
+ if ((stType == 4) || (stType == 6)) c = 0x1;
+ if ((stType == 5) || (stType == 7)) c = 0x2;
+
+ if (_inst.Wx == 0)
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
+ }
+ else
+ {
+ Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
+ }
+ m_GPR[_inst.RA] = EA;
+}
\ No newline at end of file
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp
index 4554308607..c6e6420aad 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp
@@ -19,482 +19,11 @@
#include "Interpreter.h"
#include "../../HW/Memmap.h"
-// dequantize table
-const float m_dequantizeTable[] =
-{
- 1.0 / (1 << 0),
- 1.0 / (1 << 1),
- 1.0 / (1 << 2),
- 1.0 / (1 << 3),
- 1.0 / (1 << 4),
- 1.0 / (1 << 5),
- 1.0 / (1 << 6),
- 1.0 / (1 << 7),
- 1.0 / (1 << 8),
- 1.0 / (1 << 9),
- 1.0 / (1 << 10),
- 1.0 / (1 << 11),
- 1.0 / (1 << 12),
- 1.0 / (1 << 13),
- 1.0 / (1 << 14),
- 1.0 / (1 << 15),
- 1.0 / (1 << 16),
- 1.0 / (1 << 17),
- 1.0 / (1 << 18),
- 1.0 / (1 << 19),
- 1.0 / (1 << 20),
- 1.0 / (1 << 21),
- 1.0 / (1 << 22),
- 1.0 / (1 << 23),
- 1.0 / (1 << 24),
- 1.0 / (1 << 25),
- 1.0 / (1 << 26),
- 1.0 / (1 << 27),
- 1.0 / (1 << 28),
- 1.0 / (1 << 29),
- 1.0 / (1 << 30),
- 1.0 / (1 << 31),
- (1ULL << 32),
- (1 << 31),
- (1 << 30),
- (1 << 29),
- (1 << 28),
- (1 << 27),
- (1 << 26),
- (1 << 25),
- (1 << 24),
- (1 << 23),
- (1 << 22),
- (1 << 21),
- (1 << 20),
- (1 << 19),
- (1 << 18),
- (1 << 17),
- (1 << 16),
- (1 << 15),
- (1 << 14),
- (1 << 13),
- (1 << 12),
- (1 << 11),
- (1 << 10),
- (1 << 9),
- (1 << 8),
- (1 << 7),
- (1 << 6),
- (1 << 5),
- (1 << 4),
- (1 << 3),
- (1 << 2),
- (1 << 1),
-};
-
-// quantize table
-const float m_quantizeTable[] =
-{
- (1 << 0),
- (1 << 1),
- (1 << 2),
- (1 << 3),
- (1 << 4),
- (1 << 5),
- (1 << 6),
- (1 << 7),
- (1 << 8),
- (1 << 9),
- (1 << 10),
- (1 << 11),
- (1 << 12),
- (1 << 13),
- (1 << 14),
- (1 << 15),
- (1 << 16),
- (1 << 17),
- (1 << 18),
- (1 << 19),
- (1 << 20),
- (1 << 21),
- (1 << 22),
- (1 << 23),
- (1 << 24),
- (1 << 25),
- (1 << 26),
- (1 << 27),
- (1 << 28),
- (1 << 29),
- (1 << 30),
- (1 << 31),
- 1.0 / (1ULL << 32),
- 1.0 / (1 << 31),
- 1.0 / (1 << 30),
- 1.0 / (1 << 29),
- 1.0 / (1 << 28),
- 1.0 / (1 << 27),
- 1.0 / (1 << 26),
- 1.0 / (1 << 25),
- 1.0 / (1 << 24),
- 1.0 / (1 << 23),
- 1.0 / (1 << 22),
- 1.0 / (1 << 21),
- 1.0 / (1 << 20),
- 1.0 / (1 << 19),
- 1.0 / (1 << 18),
- 1.0 / (1 << 17),
- 1.0 / (1 << 16),
- 1.0 / (1 << 15),
- 1.0 / (1 << 14),
- 1.0 / (1 << 13),
- 1.0 / (1 << 12),
- 1.0 / (1 << 11),
- 1.0 / (1 << 10),
- 1.0 / (1 << 9),
- 1.0 / (1 << 8),
- 1.0 / (1 << 7),
- 1.0 / (1 << 6),
- 1.0 / (1 << 5),
- 1.0 / (1 << 4),
- 1.0 / (1 << 3),
- 1.0 / (1 << 2),
- 1.0 / (1 << 1),
-};
-
-template
-inline T CLAMP(T a, T bottom, T top) {
- if (a > top) return top;
- if (a < bottom) return bottom;
- return a;
-}
-void CInterpreter::Helper_Quantize(const u32 _Addr, const float _fValue,
- const EQuantizeType _quantizeType, const unsigned int _uScale)
-{
- switch(_quantizeType)
- {
- case QUANTIZE_FLOAT:
- Memory::Write_U32(*(u32*)&_fValue,_Addr);
- break;
-
- // used for THP player
- case QUANTIZE_U8:
- {
- float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], 0.0f, 255.0f);
- Memory::Write_U8((u8)fResult, _Addr);
- }
- break;
-
- case QUANTIZE_U16:
- {
- float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], 0.0f, 65535.0f);
- Memory::Write_U16((u16)fResult, _Addr);
- }
- break;
-
- case QUANTIZE_S8:
- {
- float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], -128.0f, 127.0f);
- Memory::Write_U8((u8)(s8)fResult, _Addr);
- }
- break;
-
- case QUANTIZE_S16:
- {
- float fResult = CLAMP(_fValue * m_quantizeTable[_uScale], -32768.0f, 32767.0f);
- Memory::Write_U16((u16)(s16)fResult, _Addr);
- }
- break;
-
- default:
- _dbg_assert_msg_(GEKKO,0,"PS dequantize","Unknown type to read");
- break;
- }
-}
-
-float CInterpreter::Helper_Dequantize(const u32 _Addr, const EQuantizeType _quantizeType,
- const unsigned int _uScale)
-{
- // dequantize the value
- float fResult;
- switch(_quantizeType)
- {
- case QUANTIZE_FLOAT:
- {
- u32 dwValue = Memory::Read_U32(_Addr);
- fResult = *(float*)&dwValue;
- }
- break;
-
- case QUANTIZE_U8:
- fResult = static_cast(Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
- break;
-
- case QUANTIZE_U16:
- fResult = static_cast(Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
- break;
-
- case QUANTIZE_S8:
- fResult = static_cast((s8)Memory::Read_U8(_Addr)) * m_dequantizeTable[_uScale];
- break;
-
- // used for THP player
- case QUANTIZE_S16:
- fResult = static_cast((s16)Memory::Read_U16(_Addr)) * m_dequantizeTable[_uScale];
- break;
-
- default:
- _dbg_assert_msg_(GEKKO,0,"PS dequantize","Unknown type to read");
- fResult = 0;
- break;
- }
-
- return fResult;
-}
-
-void CInterpreter::psq_l(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
- const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
- const unsigned int ldScale = gqr.LD_SCALE;
- const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : _inst.SIMM_12;
-
- int c = 4;
- if ((ldType == QUANTIZE_U8) || (ldType == QUANTIZE_S8)) c = 0x1;
- if ((ldType == QUANTIZE_U16) || (ldType == QUANTIZE_S16)) c = 0x2;
-
- if (_inst.W == 0)
- {
- rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale);
- rPS1(_inst.RS) = Helper_Dequantize(EA+c, ldType, ldScale);
- }
- else
- {
- rPS0(_inst.RS) = Helper_Dequantize(EA, ldType, ldScale);
- rPS1(_inst.RS) = 1.0f;
- }
-}
-
-void CInterpreter::psq_lu(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
- const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
- const unsigned int ldScale = gqr.LD_SCALE;
- const u32 EA = m_GPR[_inst.RA] + _inst.SIMM_12;
-
- int c = 4;
- if ((ldType == 4) || (ldType == 6)) c = 0x1;
- if ((ldType == 5) || (ldType == 7)) c = 0x2;
-
- if (_inst.W == 0)
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
- }
- else
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = 1.0f;
- }
- m_GPR[_inst.RA] = EA;
-}
-
-void CInterpreter::psq_st(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
- const EQuantizeType stType = static_cast(gqr.ST_TYPE);
- const unsigned int stScale = gqr.ST_SCALE;
- const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_12) : _inst.SIMM_12;
-
- int c = 4;
- if ((stType == 4) || (stType == 6)) c = 0x1;
- if ((stType == 5) || (stType == 7)) c = 0x2;
-
- if (_inst.W == 0)
- {
- Helper_Quantize( EA, (float)rPS0(_inst.RS), stType, stScale );
- Helper_Quantize( EA+c, (float)rPS1(_inst.RS), stType, stScale );
- }
- else
- {
- Helper_Quantize( EA, (float)rPS0(_inst.RS), stType, stScale );
- }
-}
-
-void CInterpreter::psq_stu(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.I));
- const EQuantizeType stType = static_cast(gqr.ST_TYPE);
- const unsigned int stScale = gqr.ST_SCALE;
- const u32 EA = m_GPR[_inst.RA] + _inst.SIMM_12;
-
- int c = 4;
- if ((stType == 4) || (stType == 6)) c = 0x1;
- if ((stType == 5) || (stType == 7)) c = 0x2;
-
- if (_inst.W == 0)
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
- }
- else
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- }
- m_GPR[_inst.RA] = EA;
-}
-
-void CInterpreter::psq_lx(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
- const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
- const unsigned int ldScale = gqr.LD_SCALE;
- const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB];
-
- int c = 4;
- if ((ldType == 4) || (ldType == 6)) c = 0x1;
- if ((ldType == 5) || (ldType == 7)) c = 0x2;
-
- if (_inst.Wx == 0)
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
- }
- else
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = 1.0f;
- }
-}
-
-void CInterpreter::psq_stx(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
- const EQuantizeType stType = static_cast(gqr.ST_TYPE);
- const unsigned int stScale = gqr.ST_SCALE;
- const u32 EA = _inst.RA ? (m_GPR[_inst.RA] + m_GPR[_inst.RB]) : m_GPR[_inst.RB];
-
- int c = 4;
- if ((stType == 4) || (stType == 6)) c = 0x1;
- if ((stType == 5) || (stType == 7)) c = 0x2;
-
- if (_inst.Wx == 0)
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
- }
- else
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- }
-}
-
-void CInterpreter::psq_lux(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
- const EQuantizeType ldType = static_cast(gqr.LD_TYPE);
- const unsigned int ldScale = gqr.LD_SCALE;
- const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB];
-
- int c = 4;
- if ((ldType == 4) || (ldType == 6)) c = 0x1;
- if ((ldType == 5) || (ldType == 7)) c = 0x2;
-
- if (_inst.Wx == 0)
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = Helper_Dequantize( EA+c, ldType, ldScale );
- }
- else
- {
- rPS0(_inst.RS) = Helper_Dequantize( EA, ldType, ldScale );
- rPS1(_inst.RS) = 1.0f;
- }
- m_GPR[_inst.RA] = EA;
-}
-
-void CInterpreter::psq_stux(UGeckoInstruction _inst)
-{
- const UGQR gqr(rSPR(SPR_GQR0 + _inst.Ix));
- const EQuantizeType stType = static_cast(gqr.ST_TYPE);
- const unsigned int stScale = gqr.ST_SCALE;
- const u32 EA = m_GPR[_inst.RA] + m_GPR[_inst.RB];
-
- int c = 4;
- if ((stType == 4) || (stType == 6)) c = 0x1;
- if ((stType == 5) || (stType == 7)) c = 0x2;
-
- if (_inst.Wx == 0)
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- Helper_Quantize(EA+c, (float)rPS1(_inst.RS), stType, stScale);
- }
- else
- {
- Helper_Quantize(EA, (float)rPS0(_inst.RS), stType, stScale);
- }
- m_GPR[_inst.RA] = EA;
-}
-
-void CInterpreter::ps_div(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) / rPS0(_inst.FB);
- rPS1(_inst.FD) = rPS1(_inst.FA) / rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_sub(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) - rPS0(_inst.FB);
- rPS1(_inst.FD) = rPS1(_inst.FA) - rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_add(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) + rPS0(_inst.FB);
- rPS1(_inst.FD) = rPS1(_inst.FA) + rPS1(_inst.FB);
-}
-
+// These "binary instructions" do not alter FPSCR.
void CInterpreter::ps_sel(UGeckoInstruction _inst)
{
- rPS0(_inst.FD) = (rPS0(_inst.FA) >= 0.0f) ? rPS0(_inst.FC) : rPS0(_inst.FB);
- rPS1(_inst.FD) = (rPS1(_inst.FA) >= 0.0f) ? rPS1(_inst.FC) : rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_res(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = 1.0f / rPS0(_inst.FB);
- rPS1(_inst.FD) = 1.0f / rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_mul(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = rPS0(_inst.FA) * rPS0(_inst.FC);
- rPS1(_inst.FD) = rPS1(_inst.FA) * rPS1(_inst.FC);
-}
-
-void CInterpreter::ps_rsqrte(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = 1.0 / sqrt(rPS0(_inst.FB));
- rPS1(_inst.FD) = 1.0 / sqrt(rPS1(_inst.FB));
-}
-
-void CInterpreter::ps_msub(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB);
- rPS1(_inst.FD) = (rPS1(_inst.FA) * rPS1(_inst.FC)) - rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_madd(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
- rPS1(_inst.FD) = (rPS1(_inst.FA) * rPS1(_inst.FC)) + rPS1(_inst.FB);
-}
-
-void CInterpreter::ps_nmsub(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = -(rPS0(_inst.FA) * rPS0(_inst.FC) - rPS0(_inst.FB));
- rPS1(_inst.FD) = -(rPS1(_inst.FA) * rPS1(_inst.FC) - rPS1(_inst.FB));
-}
-
-void CInterpreter::ps_nmadd(UGeckoInstruction _inst)
-{
- rPS0(_inst.FD) = -(rPS0(_inst.FA) * rPS0(_inst.FC) + rPS0(_inst.FB));
- rPS1(_inst.FD) = -(rPS1(_inst.FA) * rPS1(_inst.FC) + rPS1(_inst.FB));
+ rPS0(_inst.FD) = static_cast((rPS0(_inst.FA) >= -0.0) ? rPS0(_inst.FC) : rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast((rPS1(_inst.FA) >= -0.0) ? rPS1(_inst.FC) : rPS1(_inst.FB));
}
void CInterpreter::ps_neg(UGeckoInstruction _inst)
@@ -521,89 +50,7 @@ void CInterpreter::ps_abs(UGeckoInstruction _inst)
riPS1(_inst.FD) = riPS1(_inst.FB) &~ (1ULL << 63);
}
-void CInterpreter::ps_sum0(UGeckoInstruction _inst)
-{
- double p0 = rPS0(_inst.FA) + rPS1(_inst.FB);
- double p1 = rPS1(_inst.FC);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_sum1(UGeckoInstruction _inst)
-{
- double p0 = rPS0(_inst.FC);
- double p1 = rPS0(_inst.FA) + rPS1(_inst.FB);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_muls0(UGeckoInstruction _inst)
-{
- double p0 = rPS0(_inst.FA) * rPS0(_inst.FC);
- double p1 = rPS1(_inst.FA) * rPS0(_inst.FC);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_muls1(UGeckoInstruction _inst)
-{
- double p0 = rPS0(_inst.FA) * rPS1(_inst.FC);
- double p1 = rPS1(_inst.FA) * rPS1(_inst.FC);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_madds0(UGeckoInstruction _inst)
-{
- double p0 = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
- double p1 = (rPS1(_inst.FA) * rPS0(_inst.FC)) + rPS1(_inst.FB);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_madds1(UGeckoInstruction _inst)
-{
- double p0 = (rPS0(_inst.FA) * rPS1(_inst.FC)) + rPS0(_inst.FB);
- double p1 = (rPS1(_inst.FA) * rPS1(_inst.FC)) + rPS1(_inst.FB);
- rPS0(_inst.FD) = p0;
- rPS1(_inst.FD) = p1;
-}
-
-void CInterpreter::ps_cmpu0(UGeckoInstruction _inst)
-{
- double fa = rPS0(_inst.FA);
- double fb = rPS0(_inst.FB);
- int compareResult;
- if (fa < fb) compareResult = 8;
- else if (fa > fb) compareResult = 4;
- else compareResult = 2;
- SetCRField(_inst.CRFD, compareResult);
-}
-
-void CInterpreter::ps_cmpo0(UGeckoInstruction _inst)
-{
- // for now HACK
- ps_cmpu0(_inst);
-}
-
-void CInterpreter::ps_cmpu1(UGeckoInstruction _inst)
-{
- double fa = rPS1(_inst.FA);
- double fb = rPS1(_inst.FB);
- int compareResult;
- if (fa < fb) compareResult = 8;
- else if (fa > fb) compareResult = 4;
- else compareResult = 2;
-
- SetCRField(_inst.CRFD, compareResult);
-}
-
-void CInterpreter::ps_cmpo1(UGeckoInstruction _inst)
-{
- // for now HACK
- ps_cmpu1(_inst);
-}
-
+// These are just moves, double is OK.
void CInterpreter::ps_merge00(UGeckoInstruction _inst)
{
double p0 = rPS0(_inst.FA);
@@ -636,6 +83,159 @@ void CInterpreter::ps_merge11(UGeckoInstruction _inst)
rPS1(_inst.FD) = p1;
}
+
+// From here on, the real deal.
+
+void CInterpreter::ps_div(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(rPS0(_inst.FA) / rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast(rPS1(_inst.FA) / rPS1(_inst.FB));
+ FPSCR.FI = 0;
+ if (fabs(rPS0(_inst.FB)) == 0.0) {
+ FPSCR.ZX = 1;
+ }
+}
+
+void CInterpreter::ps_sub(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(rPS0(_inst.FA) - rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast(rPS1(_inst.FA) - rPS1(_inst.FB));
+}
+
+void CInterpreter::ps_add(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(rPS0(_inst.FA) + rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast(rPS1(_inst.FA) + rPS1(_inst.FB));
+}
+
+void CInterpreter::ps_res(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = 1.0f / static_cast(rPS0(_inst.FB));
+ rPS1(_inst.FD) = 1.0f / static_cast(rPS1(_inst.FB));
+}
+
+void CInterpreter::ps_mul(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(rPS0(_inst.FA) * rPS0(_inst.FC));
+ rPS1(_inst.FD) = static_cast(rPS1(_inst.FA) * rPS1(_inst.FC));
+}
+
+void CInterpreter::ps_rsqrte(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(1.0f / sqrtf((float)rPS0(_inst.FB)));
+ rPS1(_inst.FD) = static_cast(1.0f / sqrtf((float)rPS1(_inst.FB)));
+ if (fabs(rPS0(_inst.FB)) == 0.0) {
+ FPSCR.ZX = 1;
+ }
+}
+
+void CInterpreter::ps_msub(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast((rPS0(_inst.FA) * rPS0(_inst.FC)) - rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast((rPS1(_inst.FA) * rPS1(_inst.FC)) - rPS1(_inst.FB));
+}
+
+void CInterpreter::ps_madd(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast((rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB));
+ rPS1(_inst.FD) = static_cast((rPS1(_inst.FA) * rPS1(_inst.FC)) + rPS1(_inst.FB));
+}
+
+void CInterpreter::ps_nmsub(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(-(rPS0(_inst.FA) * rPS0(_inst.FC) - rPS0(_inst.FB)));
+ rPS1(_inst.FD) = static_cast(-(rPS1(_inst.FA) * rPS1(_inst.FC) - rPS1(_inst.FB)));
+}
+
+void CInterpreter::ps_nmadd(UGeckoInstruction _inst)
+{
+ rPS0(_inst.FD) = static_cast(-(rPS0(_inst.FA) * rPS0(_inst.FC) + rPS0(_inst.FB)));
+ rPS1(_inst.FD) = static_cast(-(rPS1(_inst.FA) * rPS1(_inst.FC) + rPS1(_inst.FB)));
+}
+
+void CInterpreter::ps_sum0(UGeckoInstruction _inst)
+{
+ double p0 = (float)(rPS0(_inst.FA) + rPS1(_inst.FB));
+ double p1 = (float)(rPS1(_inst.FC));
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_sum1(UGeckoInstruction _inst)
+{
+ float p0 = rPS0(_inst.FC);
+ float p1 = rPS0(_inst.FA) + rPS1(_inst.FB);
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_muls0(UGeckoInstruction _inst)
+{
+ float p0 = rPS0(_inst.FA) * rPS0(_inst.FC);
+ float p1 = rPS1(_inst.FA) * rPS0(_inst.FC);
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_muls1(UGeckoInstruction _inst)
+{
+ float p0 = rPS0(_inst.FA) * rPS1(_inst.FC);
+ float p1 = rPS1(_inst.FA) * rPS1(_inst.FC);
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_madds0(UGeckoInstruction _inst)
+{
+ float p0 = (rPS0(_inst.FA) * rPS0(_inst.FC)) + rPS0(_inst.FB);
+ float p1 = (rPS1(_inst.FA) * rPS0(_inst.FC)) + rPS1(_inst.FB);
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_madds1(UGeckoInstruction _inst)
+{
+ float p0 = (rPS0(_inst.FA) * rPS1(_inst.FC)) + rPS0(_inst.FB);
+ float p1 = (rPS1(_inst.FA) * rPS1(_inst.FC)) + rPS1(_inst.FB);
+ rPS0(_inst.FD) = p0;
+ rPS1(_inst.FD) = p1;
+}
+
+void CInterpreter::ps_cmpu0(UGeckoInstruction _inst)
+{
+ float fa = rPS0(_inst.FA);
+ float fb = rPS0(_inst.FB);
+ int compareResult;
+ if (fa < fb) compareResult = 8;
+ else if (fa > fb) compareResult = 4;
+ else compareResult = 2;
+ SetCRField(_inst.CRFD, compareResult);
+}
+
+void CInterpreter::ps_cmpo0(UGeckoInstruction _inst)
+{
+ // for now HACK
+ ps_cmpu0(_inst);
+}
+
+void CInterpreter::ps_cmpu1(UGeckoInstruction _inst)
+{
+ float fa = rPS1(_inst.FA);
+ float fb = rPS1(_inst.FB);
+ int compareResult;
+ if (fa < fb) compareResult = 8;
+ else if (fa > fb) compareResult = 4;
+ else compareResult = 2;
+
+ SetCRField(_inst.CRFD, compareResult);
+}
+
+void CInterpreter::ps_cmpo1(UGeckoInstruction _inst)
+{
+ // for now HACK
+ ps_cmpu1(_inst);
+}
+
// __________________________________________________________________________________________________
// dcbz_l
// TODO(ector) check docs
diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
index b71b8c32ba..8fcb2063ea 100644
--- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
+++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
@@ -34,12 +34,22 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10;
#include "../../Core.h"
#include "Interpreter.h"
+/*
+Most of these are together with fctiwx
+mffsx: 800c3624
+mffsx: 80043c98
+mffsx: 8003dd48
+mffsx: 8003dd9c
+mffsx: 80036608
+mffsx: 80036650 (huh?)
+
+*/
// TODO(ector): More proper handling of SSE state.
// That is, set rounding mode etc when entering jit code or the interpreter loop
// Restore rounding mode when calling anything external
-void UpdateSSEState(int round, bool daz)
+void UpdateSSEState()
{
u32 csr = _mm_getcsr();
@@ -51,14 +61,14 @@ void UpdateSSEState(int round, bool daz)
1,
};
csr = csr & 0x9FFF;
- csr |= ssetable[round] << 13;
+ csr |= ssetable[FPSCR.RN] << 13;
// Also handle denormals as zero (FZ + DAZ)
csr &= ~0x8020;
- // SETTING DAZ KILLS BEYOND GOOD AND EVIL
- // if (daz)
- // csr |= 0x8020;
+ // SETTING FTZ+DAZ KILLS BEYOND GOOD AND EVIL
+ //if (daz)
+ // csr |= 0x20; // Only set DAZ //0x8020;
_mm_setcsr(csr);
}
@@ -72,7 +82,6 @@ void RestoreSSEState()
void UpdateFPSCR(UReg_FPSCR fp)
{
// Set FPU rounding mode to mimic the PowerPC's
- int round = fp.RN;
#ifdef _M_IX86
// This shouldn't really be needed anymore since we use SSE
#ifdef _WIN32
@@ -83,7 +92,7 @@ void UpdateFPSCR(UReg_FPSCR fp)
_RC_UP,
_RC_DOWN
};
- _set_controlfp(_MCW_RC, table[round]);
+ _set_controlfp(_MCW_RC, table[fp.RN]);
#else
const unsigned short table[4] =
{
@@ -94,19 +103,48 @@ void UpdateFPSCR(UReg_FPSCR fp)
};
unsigned short mode;
asm ("fstcw %0" : : "m" (mode));
- mode = (mode & ~FPU_ROUND_MASK) | table[round];
+ mode = (mode & ~FPU_ROUND_MASK) | table[fp.RN];
asm ("fldcw %0" : : "m" (mode));
#endif
#endif
+ if (fp.VE || fp.OE || fp.UE || fp.ZE || fp.XE)
+ {
+ PanicAlert("FPSCR - exceptions enabled. Please report.");
+ }
+
// Also corresponding SSE rounding mode setting
- UpdateSSEState(round, fp.NI ? true : false);
+ UpdateSSEState();
}
void CInterpreter::mcrfs(UGeckoInstruction _inst)
{
- // TODO(ector): check a ppc manual for this one
u32 fpflags = ((FPSCR.Hex >> (4*(_inst.CRFS))) & 0xF);
- FPSCR.Hex &= ~(0xF0000000 >> (_inst.CRFS*4));
+ switch (_inst.CRFS) {
+ case 0:
+ FPSCR.FX = 0;
+ FPSCR.OX = 0;
+ break;
+ case 1:
+ FPSCR.UX = 0;
+ FPSCR.ZX = 0;
+ FPSCR.XX = 0;
+ FPSCR.VXSNAN = 0;
+ break;
+ case 2:
+ FPSCR.VXISI = 0;
+ FPSCR.VXIDI = 0;
+ FPSCR.VXZDZ = 0;
+ FPSCR.VXIMZ = 0;
+ break;
+ case 3:
+ FPSCR.VXVC = 0;
+ break;
+ case 5:
+ FPSCR.VXSOFT = 0;
+ FPSCR.VXSQRT = 0;
+ FPSCR.VXCVI = 0;
+ break;
+ }
SetCRField(_inst.CRFD, fpflags);
UpdateFPSCR(FPSCR);
}
@@ -127,8 +165,6 @@ void CInterpreter::mcrfs(UGeckoInstruction _inst)
#define MXCSR_ROUND (16384|8192)
#define MXCSR_FLUSH 32768
-
-
void CInterpreter::mffsx(UGeckoInstruction _inst)
{
// load from FPSCR
@@ -136,31 +172,35 @@ void CInterpreter::mffsx(UGeckoInstruction _inst)
// TODO(ector): grab all overflow flags etc and set them in FPSCR
riPS0(_inst.FD) = (u64)FPSCR.Hex;
+ if (_inst.Rc) PanicAlert("mffsx: inst_.Rc");
}
void CInterpreter::mtfsb0x(UGeckoInstruction _inst)
{
FPSCR.Hex &= (~(0x80000000 >> _inst.CRBD));
UpdateFPSCR(FPSCR);
+ if (_inst.Rc) PanicAlert("mtfsb0x: inst_.Rc");
}
void CInterpreter::mtfsb1x(UGeckoInstruction _inst)
{
FPSCR.Hex |= 0x80000000 >> _inst.CRBD;
UpdateFPSCR(FPSCR);
+ if (_inst.Rc) PanicAlert("mtfsb1x: inst_.Rc");
}
void CInterpreter::mtfsfix(UGeckoInstruction _inst)
{
- u32 mask = (0xF0000000 >> (4*_inst.CRFD));
+ u32 mask = (0xF0000000 >> (4 * _inst.CRFD));
u32 imm = (_inst.hex << 16) & 0xF0000000;
- FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4*_inst.CRFD));
+ FPSCR.Hex = (FPSCR.Hex & ~mask) | (imm >> (4 * _inst.CRFD));
UpdateFPSCR(FPSCR);
+ if (_inst.Rc) PanicAlert("mtfsfix: inst_.Rc");
}
void CInterpreter::mtfsfx(UGeckoInstruction _inst)
{
- u32 fm = _inst.FM;
+ u32 fm = _inst.FM;
u32 m = 0;
for (int i = 0; i < 8; i++) { //7?? todo check
if (fm & (1 << i))
@@ -169,6 +209,7 @@ void CInterpreter::mtfsfx(UGeckoInstruction _inst)
FPSCR.Hex = (FPSCR.Hex & ~m) | ((u32)(riPS0(_inst.FB)) & m);
UpdateFPSCR(FPSCR);
+ if (_inst.Rc) PanicAlert("mtfsfx: inst_.Rc");
}
void CInterpreter::mcrxr(UGeckoInstruction _inst)
@@ -240,7 +281,7 @@ void CInterpreter::mtsrin(UGeckoInstruction _inst)
void CInterpreter::mftb(UGeckoInstruction _inst)
{
- int iIndex = (_inst.TBR >> 5) | ((_inst.TBR&0x1F) << 5);
+ int iIndex = (_inst.TBR >> 5) | ((_inst.TBR & 0x1F) << 5);
if (iIndex == 268) m_GPR[_inst.RD] = TL;
else if (iIndex == 269) m_GPR[_inst.RD] = TU;
else _dbg_assert_(GEKKO,0);
@@ -449,4 +490,3 @@ void CInterpreter::isync(UGeckoInstruction _inst)
{
//shouldnt do anything
}
-
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
index 02e392b87d..2cc91d8d4a 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
@@ -231,6 +231,21 @@ namespace Jit64
JitState js;
JitOptions jo;
+ void Init()
+ {
+ jo.optimizeStack = true;
+ jo.enableBlocklink = true; // Speed boost, but not 100% safe
+#ifdef _M_X64
+ jo.enableFastMem = Core::GetStartupParameter().bUseFastMem;
+#else
+ jo.enableFastMem = false;
+#endif
+ jo.assumeFPLoadFromMem = true;
+ jo.fpAccurateFlags = true;
+ jo.optimizeGatherPipe = true;
+ jo.interpretFPU = false;
+ }
+
void WriteCallInterpreter(UGeckoInstruction _inst)
{
gpr.Flush(FLUSH_ALL);
@@ -263,12 +278,6 @@ namespace Jit64
// Yup, just don't do anything.
}
- // RESULTS (running kururin with optimizations on)
- // at block 13968 they diverge.
- // linux goes to 8010fe54
- // windoze goes to 8010feb0
- // after they they are completely out of sync.
- // branches from the cmp result of r0, which comes from an lbz (loaded from stack)
static const bool ImHereDebug = false;
static const bool ImHereLog = false;
static std::map been_here;
@@ -403,7 +412,12 @@ namespace Jit64
js.op = &ops[i];
js.instructionNumber = i;
if (i == (int)size - 1) js.isLastInstruction = true;
+
+ // const GekkoOpInfo *info = GetOpInfo();
// if (js.isLastInstruction)
+ if (jo.interpretFPU && PPCTables::UsesFPU(ops[i].inst))
+ Default(ops[i].inst);
+ else
PPCTables::CompileInstruction(ops[i].inst);
// else
// Default(ops[i].inst);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
index 8cae388832..4caad4fb14 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h
@@ -70,11 +70,14 @@ namespace Jit64
bool fpAccurateFlags;
bool enableFastMem;
bool optimizeGatherPipe;
+ bool interpretFPU;
};
extern JitState js;
extern JitOptions jo;
+ void Init();
+
void Default(UGeckoInstruction _inst);
void DoNothing(UGeckoInstruction _inst);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
index 6cbece1004..9e79b9d073 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCache.cpp
@@ -76,17 +76,6 @@ namespace Jit64
void InitCache()
{
- jo.optimizeStack = true;
- jo.enableBlocklink = true; // Speed boost, but not 100% safe
-#ifdef _M_X64
- jo.enableFastMem = Core::GetStartupParameter().bUseFastMem;
-#else
- jo.enableFastMem = false;
-#endif
- jo.assumeFPLoadFromMem = true;
- jo.fpAccurateFlags = true;
- jo.optimizeGatherPipe = true;
-
codeCache = (u8*)AllocateExecutableMemory(CODE_SIZE);
genFunctions = (u8*)AllocateExecutableMemory(GEN_SIZE);
trampolineCache = (u8*)AllocateExecutableMemory(TRAMPOLINE_SIZE);
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitCore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitCore.cpp
index 85b1e2f1b5..9aef7c57d6 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/JitCore.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/JitCore.cpp
@@ -17,6 +17,7 @@
#include "JitCore.h"
#include "JitCache.h"
#include "JitAsm.h"
+#include "Jit.h"
#include "../../HW/Memmap.h"
#include "../../HW/CPU.h"
@@ -31,6 +32,7 @@ namespace Jit64
{
void Jit64Core::Init()
{
+ ::Jit64::Init();
InitCache();
Asm::compareEnabled = Core::g_CoreStartupParameter.bRunCompareClient;
}
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp
index f6ff05f222..41cc76b644 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Branch.cpp
@@ -122,9 +122,9 @@ namespace Jit64
bool doFullTest = (inst.BO & 16) == 0 && (inst.BO & 4) == 0;
bool ctrDecremented = false;
- if ((inst.BO & 16) == 0) // Test CR with a combination of bits
+ if ((inst.BO & 16) == 0) // Test a CR bit
{
- TEST(32, M(&CR), Imm32(0x80000000>>inst.BI));
+ TEST(32, M(&CR), Imm32(0x80000000 >> inst.BI));
if (inst.BO & 8) // Conditional branch
branch = CC_NZ;
else
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp
index e359f89c11..ed2dd5d503 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp
@@ -150,7 +150,6 @@ namespace Jit64
fpr.UnlockAll();
}
-
void fmrx(UGeckoInstruction inst)
{
INSTRUCTION_START;
diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp
index f234a5e312..5011ce37f3 100644
--- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp
+++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp
@@ -25,6 +25,7 @@
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
+#include "Jit_Util.h"
// TODO
// ps_madds0
@@ -198,7 +199,7 @@ namespace Jit64
op(XMM0, Gen::R(XMM1));
MOVAPD(fpr.RX(d), Gen::R(XMM0));
}
- //fpr.SetDirty(fpr.RX(d));
+ ForceSinglePrecisionP(fpr.RX(d));
fpr.UnlockAll();
}
@@ -308,6 +309,7 @@ namespace Jit64
}
fpr.LoadToX64(d, false);
MOVAPD(fpr.RX(d), Gen::R(XMM0));
+ ForceSinglePrecisionP(fpr.RX(d));
fpr.UnlockAll();
}
diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
index bd1549630e..ed51848da0 100644
--- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp
+++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp
@@ -19,6 +19,7 @@
#include "Common.h"
#include "PPCTables.h"
+#include "StringUtil.h"
#include "Interpreter/Interpreter.h"
#if defined(_M_IX86) || defined(_M_X64)
@@ -409,7 +410,7 @@ GekkoOPTemplate table59[] =
{18, CInterpreter::fdivsx, Jit64::fp_arith_s, {"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}},
{20, CInterpreter::fsubsx, Jit64::fp_arith_s, {"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
{21, CInterpreter::faddsx, Jit64::fp_arith_s, {"faddsx", OPTYPE_FPU, FL_RC_BIT_F}},
- {22, CInterpreter::fsqrtsx, Jit64::Default, {"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}},
+// {22, CInterpreter::fsqrtsx, Jit64::Default, {"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko
{24, CInterpreter::fresx, Jit64::Default, {"fresx", OPTYPE_FPU, FL_RC_BIT_F}},
{25, CInterpreter::fmulsx, Jit64::fp_arith_s, {"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}},
{28, CInterpreter::fmsubsx, Jit64::fmaddXX, {"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}},
@@ -637,11 +638,26 @@ void PPCTables::InitTables()
m_allInstructions[m_numInstructions++] = &table63[i].opinfo;
for (int i = 0; i < (int)(sizeof(table63_2) / sizeof(GekkoOPTemplate)); i++)
m_allInstructions[m_numInstructions++] = &table63_2[i].opinfo;
+ if (m_numInstructions >= 2048) {
+ PanicAlert("m_allInstructions underdimensioned");
+ }
+}
+
+namespace {
+ std::vector rsplocations;
}
void PPCTables::CompileInstruction(UGeckoInstruction _inst)
{
dynaOpTable[_inst.OPCD](_inst);
+ GekkoOPInfo *info = GetOpInfo(_inst);
+ if (info) {
+ if (!strcmp(info->opname, "mffsx")) {
+ rsplocations.push_back(Jit64::js.compilerPC);
+ }
+ info->compileCount++;
+ info->lastUse = Jit64::js.compilerPC;
+ }
}
bool PPCTables::IsValidInstruction(UGeckoInstruction _instCode)
@@ -685,3 +701,30 @@ void PPCTables::PrintInstructionRunCounts()
LOG(GEKKO, "%s : %i", temp[i].name,temp[i].count);
}
}
+
+void PPCTables::LogCompiledInstructions()
+{
+ static int time = 0;
+ FILE *f = fopen(StringFromFormat("inst_log%i.txt", time).c_str(), "w");
+ for (int i = 0; i < m_numInstructions; i++)
+ {
+ if (m_allInstructions[i]->compileCount > 0) {
+ fprintf(f, "%s\t%i\t%i\t%08x\n", m_allInstructions[i]->opname, m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount, m_allInstructions[i]->lastUse);
+ }
+ }
+ fclose(f);
+ f = fopen(StringFromFormat("inst_not%i.txt", time).c_str(), "w");
+ for (int i = 0; i < m_numInstructions; i++)
+ {
+ if (m_allInstructions[i]->compileCount == 0) {
+ fprintf(f, "%s\t%i\t%i\n", m_allInstructions[i]->opname, m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount);
+ }
+ }
+ fclose(f);
+ f = fopen(StringFromFormat("rsp_at.txt", time).c_str(), "w");
+ for (int i = 0; i < rsplocations.size(); i++) {
+ fprintf(f, "mffsx: %08x\n", rsplocations[i]);
+ }
+ fclose(f);
+ time++;
+}
\ No newline at end of file
diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.h b/Source/Core/Core/Src/PowerPC/PPCTables.h
index 799edb3c59..b7ce5b4a70 100644
--- a/Source/Core/Core/Src/PowerPC/PPCTables.h
+++ b/Source/Core/Core/Src/PowerPC/PPCTables.h
@@ -73,6 +73,8 @@ struct GekkoOPInfo
int flags;
int numCyclesMinusOne;
int runCount;
+ int compileCount;
+ u32 lastUse;
};
@@ -92,6 +94,7 @@ public:
static void CountInstruction(UGeckoInstruction _inst);
static void PrintInstructionRunCounts();
+ static void LogCompiledInstructions();
static void CompileInstruction(UGeckoInstruction _inst);
};
diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript
index 147eddd6ae..2c864c2e7e 100644
--- a/Source/Core/Core/Src/SConscript
+++ b/Source/Core/Core/Src/SConscript
@@ -63,6 +63,7 @@ files = ["Console.cpp",
"PowerPC/Interpreter/Interpreter_FloatingPoint.cpp",
"PowerPC/Interpreter/Interpreter_Paired.cpp",
"PowerPC/Interpreter/Interpreter_LoadStore.cpp",
+ "PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp",
"PowerPC/Interpreter/Interpreter_SystemRegisters.cpp",
"PowerPC/Jit64/Jit.cpp",
"PowerPC/Jit64/JitCore.cpp",
diff --git a/Source/Core/DebuggerWX/src/CodeWindow.cpp b/Source/Core/DebuggerWX/src/CodeWindow.cpp
index d0c270ad48..ef796d9529 100644
--- a/Source/Core/DebuggerWX/src/CodeWindow.cpp
+++ b/Source/Core/DebuggerWX/src/CodeWindow.cpp
@@ -46,6 +46,7 @@
#include "Debugger/PPCDebugInterface.h"
#include "Debugger/Debugger_SymbolMap.h"
#include "PowerPC/PPCAnalyst.h"
+#include "PowerPC/PPCTables.h"
#include "PowerPC/Jit64/Jit.h"
#include "PowerPC/Jit64/JitCache.h"
@@ -71,6 +72,9 @@ BEGIN_EVENT_TABLE(CCodeWindow, wxFrame)
EVT_MENU(IDM_SCANFUNCTIONS, CCodeWindow::OnSymbolsMenu)
EVT_MENU(IDM_LOADMAPFILE, CCodeWindow::OnSymbolsMenu)
EVT_MENU(IDM_SAVEMAPFILE, CCodeWindow::OnSymbolsMenu)
+
+ EVT_MENU(IDM_CLEARCODECACHE, CCodeWindow::OnJitMenu)
+ EVT_MENU(IDM_LOGINSTRUCTIONS, CCodeWindow::OnJitMenu)
// toolbar
EVT_MENU(IDM_DEBUG_GO, CCodeWindow::OnCodeStep)
EVT_MENU(IDM_STEP, CCodeWindow::OnCodeStep)
@@ -244,6 +248,7 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
{
wxMenu *pJitMenu = new wxMenu;
pJitMenu->Append(IDM_CLEARCODECACHE, _T("&Clear code cache"));
+ pJitMenu->Append(IDM_LOGINSTRUCTIONS, _T("&Log JIT instruction coverage"));
pMenuBar->Append(pJitMenu, _T("&JIT"));
}
@@ -275,6 +280,9 @@ void CCodeWindow::OnJitMenu(wxCommandEvent& event)
case IDM_CLEARCODECACHE:
Jit64::ClearCache();
break;
+ case IDM_LOGINSTRUCTIONS:
+ PPCTables::LogCompiledInstructions();
+ break;
}
}
diff --git a/Source/Core/DebuggerWX/src/CodeWindow.h b/Source/Core/DebuggerWX/src/CodeWindow.h
index d56038a54e..9a7010c7fb 100644
--- a/Source/Core/DebuggerWX/src/CodeWindow.h
+++ b/Source/Core/DebuggerWX/src/CodeWindow.h
@@ -80,6 +80,7 @@ class CCodeWindow
IDM_BREAKPOINTWINDOW,
IDM_MEMORYWINDOW,
IDM_SCANFUNCTIONS,
+ IDM_LOGINSTRUCTIONS,
IDM_LOADMAPFILE,
IDM_SAVEMAPFILE,
IDM_CLEARCODECACHE,
diff --git a/Source/Core/DolphinWX/src/Frame.cpp b/Source/Core/DolphinWX/src/Frame.cpp
index a63b7fa063..a95224b4b4 100644
--- a/Source/Core/DolphinWX/src/Frame.cpp
+++ b/Source/Core/DolphinWX/src/Frame.cpp
@@ -303,7 +303,7 @@ void CFrame::OnOpen(wxCommandEvent& WXUNUSED (event))
wxEmptyString, wxEmptyString, wxEmptyString,
wxString::Format
(
- _T("Elf files (*.elf)|*.elf|DOL files (*.dol)|*.dol|Gamecube/Wii ISO (*.iso;*.gcm)|*.iso;*.gcm|All files (%s)|%s"),
+ _T("All GC/Wii files (elf, dol, gcm, iso)|*.elf;*.dol;*.gcm;*.iso|All files (%s)|%s"),
wxFileSelectorDefaultWildcardStr,
wxFileSelectorDefaultWildcardStr
),
diff --git a/Source/Core/DolphinWX/src/GameListCtrl.h b/Source/Core/DolphinWX/src/GameListCtrl.h
index 748047daee..8e600b9265 100644
--- a/Source/Core/DolphinWX/src/GameListCtrl.h
+++ b/Source/Core/DolphinWX/src/GameListCtrl.h
@@ -68,7 +68,7 @@ class CGameListCtrl : public wxListCtrl
void OnEditPatchFile(wxCommandEvent& event);
void OnOpenContainingFolder(wxCommandEvent& event);
- virtual bool MSWDrawSubItem(wxPaintDC& rPainDC, int item, int subitem);
+ virtual bool MSWDrawSubItem(wxPaintDC& rPaintDC, int item, int subitem);
void AutomaticColumnWidth();
};
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp
index 7aca16604e..cee0c2048e 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/PCHW/Mixer.cpp
@@ -74,7 +74,7 @@ void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
-// static FILE *f;
+// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
@@ -83,6 +83,7 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
+ if (!GetAsyncKeyState(VK_TAB)) {
while (queue_size > queue_maxlength / 2) {
#ifdef _WIN32
DSound::DSound_UpdateSound();
@@ -91,7 +92,9 @@ void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
sleep(0);
#endif
}
-
+ } else {
+ return;
+ }
//convert into config option?
const int mode = 2;
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/OpcodeDecoding.cpp b/Source/Plugins/Plugin_VideoDX9/Src/OpcodeDecoding.cpp
index 8f5b9b07e9..914acd7f29 100644
--- a/Source/Plugins/Plugin_VideoDX9/Src/OpcodeDecoding.cpp
+++ b/Source/Plugins/Plugin_VideoDX9/Src/OpcodeDecoding.cpp
@@ -210,16 +210,6 @@ bool FifoCommandRunnable(void)
void Decode(void)
{
- static int DecoderCount = 0;
- DecoderCount++;
-
- if (DecoderCount == 0x0019c601)
- {
- int i = 0;
- }
-
- // 0x0019c603 <- error
-
int Cmd = g_pDataReader->Read8();
switch(Cmd)
{
@@ -236,7 +226,6 @@ void Decode(void)
case GX_LOAD_XF_REG:
{
- u32 test = PeekFifo32(0);
u32 Cmd2 = g_pDataReader->Read32();
int dwTransferSize = ((Cmd2>>16)&15) + 1;
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp
index 29d69fc0ed..9ef9f03b53 100644
--- a/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp
+++ b/Source/Plugins/Plugin_VideoOGL/Src/OpcodeDecoding.cpp
@@ -145,23 +145,26 @@ bool FifoCommandRunnable(void)
case GX_LOAD_XF_REG:
{
// check if we can read the header
- if (iBufferSize >= 5) {
+ if (iBufferSize >= 5)
+ {
iCommandSize = 1 + 4;
u32 Cmd2 = PeekFifo32(1);
- int dwTransferSize = ((Cmd2>>16)&15) + 1;
+ int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
iCommandSize += dwTransferSize * 4;
}
- else {
+ else
+ {
return false;
}
}
break;
default:
- if (Cmd&0x80)
+ if (Cmd & 0x80)
{
// check if we can read the header
- if (iBufferSize >= 3) {
+ if (iBufferSize >= 3)
+ {
iCommandSize = 1 + 2;
u16 numVertices = PeekFifo16(1);
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
@@ -189,7 +192,7 @@ bool FifoCommandRunnable(void)
if (iCommandSize > iBufferSize)
return false;
- INFO_LOG("OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
+ // INFO_LOG("OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
return true;
}
@@ -268,7 +271,7 @@ void Decode(void)
{
// load vertices
u16 numVertices = g_pDataReader->Read16();
- if( numVertices > 0 ) {
+ if (numVertices > 0) {
g_VertexLoaders[Cmd & GX_VAT_MASK].RunVertices((Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices);
}
}