diff --git a/common/build/Utilities/utilities_vs2012.vcxproj b/common/build/Utilities/utilities_vs2012.vcxproj
index cfff6843f3..d3ef1128a5 100644
--- a/common/build/Utilities/utilities_vs2012.vcxproj
+++ b/common/build/Utilities/utilities_vs2012.vcxproj
@@ -166,6 +166,7 @@
+
diff --git a/common/build/Utilities/utilities_vs2012.vcxproj.filters b/common/build/Utilities/utilities_vs2012.vcxproj.filters
index 961b6a7d18..9dc015334a 100644
--- a/common/build/Utilities/utilities_vs2012.vcxproj.filters
+++ b/common/build/Utilities/utilities_vs2012.vcxproj.filters
@@ -168,6 +168,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/common/build/Utilities/utilities_vs2013.vcxproj b/common/build/Utilities/utilities_vs2013.vcxproj
index 571cc43200..fee862f736 100644
--- a/common/build/Utilities/utilities_vs2013.vcxproj
+++ b/common/build/Utilities/utilities_vs2013.vcxproj
@@ -166,6 +166,7 @@
+
diff --git a/common/build/Utilities/utilities_vs2013.vcxproj.filters b/common/build/Utilities/utilities_vs2013.vcxproj.filters
index 961b6a7d18..9dc015334a 100644
--- a/common/build/Utilities/utilities_vs2013.vcxproj.filters
+++ b/common/build/Utilities/utilities_vs2013.vcxproj.filters
@@ -168,6 +168,9 @@
Header Files
+
+ Header Files
+
Header Files
diff --git a/common/include/Utilities/Math.h b/common/include/Utilities/Math.h
new file mode 100644
index 0000000000..f9ab252922
--- /dev/null
+++ b/common/include/Utilities/Math.h
@@ -0,0 +1,41 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2014- PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+// Hopefully this file will be used for cross-source math utilities.
+// Currently these are strewn across the code base. Please collect them all!
+
+#include "Pcsx2Defs.h"
+
+// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
+inline u32 count_leading_sign_bits(s32 n) {
+ // If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
+ if (n < 0)
+ n = ~n;
+
+ // If BSR is used directly, it would have an undefined value for 0.
+ if (n == 0)
+ return 32;
+
+ // Perform our count leading zero.
+#ifdef _MSC_VER
+ unsigned long ret;
+ _BitScanReverse(&ret, n);
+ return 31 - (u32)ret;
+#else
+ return __builtin_clz(n);
+#endif
+}
+
diff --git a/pcsx2/MMI.cpp b/pcsx2/MMI.cpp
index 6375405461..9aa68670e6 100644
--- a/pcsx2/MMI.cpp
+++ b/pcsx2/MMI.cpp
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include "Common.h"
+#include "Utilities/Math.h"
namespace R5900 {
namespace Interpreter {
@@ -145,30 +146,13 @@ namespace MMI {
//*****************MMI OPCODES*********************************
-static __fi void _PLZCW(int n)
-{
- // This function counts the number of "like" bits in the source register, starting
- // with the MSB and working its way down, and returns the result MINUS ONE.
- // So 0xff00 would return 7, not 8.
-
- int c = 0;
- s32 i = cpuRegs.GPR.r[_Rs_].SL[n];
-
- // Negate the source based on the sign bit. This allows us to use a simple
- // unified bit test of the MSB for either condition.
- if( i >= 0 ) i = ~i;
-
- // shift first, compare, then increment. This excludes the sign bit from our final count.
- while( i <<= 1, i < 0 ) c++;
-
- cpuRegs.GPR.r[_Rd_].UL[n] = c;
-}
-
void PLZCW() {
- if (!_Rd_) return;
+ if (!_Rd_)
+ return;
- _PLZCW (0);
- _PLZCW (1);
+ // Return the leading sign bits, excluding the original bit
+ cpuRegs.GPR.r[_Rd_].UL[0] = count_leading_sign_bits(cpuRegs.GPR.r[_Rs_].SL[0]) - 1;
+ cpuRegs.GPR.r[_Rd_].UL[1] = count_leading_sign_bits(cpuRegs.GPR.r[_Rs_].SL[1]) - 1;
}
__fi void PMFHL_CLAMP(u16& dst, s32 src)
diff --git a/pcsx2/x86/iMMI.cpp b/pcsx2/x86/iMMI.cpp
index 74ee3d7d49..0183c4e5b1 100644
--- a/pcsx2/x86/iMMI.cpp
+++ b/pcsx2/x86/iMMI.cpp
@@ -25,6 +25,7 @@
#include "R5900OpcodeTables.h"
#include "iR5900.h"
#include "iMMI.h"
+#include "Utilities/Math.h"
using namespace x86Emitter;
@@ -66,23 +67,10 @@ void recPLZCW()
_deleteEEreg(_Rd_, 0);
GPR_SET_CONST(_Rd_);
- for(regs = 0; regs < 2; ++regs) {
- u32 val = g_cpuConstRegs[_Rs_].UL[regs];
+ // Return the leading sign bits, excluding the original bit
+ g_cpuConstRegs[_Rd_].UL[0] = count_leading_sign_bits(g_cpuConstRegs[_Rs_].SL[0]) - 1;
+ g_cpuConstRegs[_Rd_].UL[1] = count_leading_sign_bits(g_cpuConstRegs[_Rs_].SL[1]) - 1;
- if( val != 0 ) {
- u32 setbit = val&0x80000000;
- g_cpuConstRegs[_Rd_].UL[regs] = 0;
- val <<= 1;
-
- while((val & 0x80000000) == setbit) {
- g_cpuConstRegs[_Rd_].UL[regs]++;
- val <<= 1;
- }
- }
- else {
- g_cpuConstRegs[_Rd_].UL[regs] = 31;
- }
- }
return;
}