mirror of https://github.com/PCSX2/pcsx2.git
Create a Math.h utility. Use it for count leading sign bits, used in MMI.
This commit is contained in:
parent
6eb0ecbe7c
commit
5287de930b
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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 BSR is used directly, it would have an undefined value for 0.
|
||||
if (n == 0)
|
||||
return 32;
|
||||
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (n < 0)
|
||||
n = ~n;
|
||||
|
||||
// Perform our count leading zero.
|
||||
#ifdef _MSC_VER
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret, n);
|
||||
return 31 - (u32)ret;
|
||||
#else
|
||||
return __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue