summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2014-09-14 09:18:10 -0500
committerRyan Houdek <Sonicadvance1@gmail.com>2014-09-14 09:18:10 -0500
commit4e16abd7428a020c136b35a96284f1af4b261f6e (patch)
tree3772a61967a028e653bba64f199fcbfea50537eb /Source/Core
parent1f7871f9e2a9c560676fcd7a9961104af11b2ad6 (diff)
parent40b18f09b2ce03f908b5303643b352d084b0c4b4 (diff)
Merge pull request #1083 from FioraAeterna/lzcnt
Add LZCNT support, use in cntlzw
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Common/x64CPUDetect.cpp1
-rw-r--r--Source/Core/Common/x64Emitter.cpp17
-rw-r--r--Source/Core/Common/x64Emitter.h7
-rw-r--r--Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp20
4 files changed, 36 insertions, 9 deletions
diff --git a/Source/Core/Common/x64CPUDetect.cpp b/Source/Core/Common/x64CPUDetect.cpp
index 8c3738034a..0da02d0fb4 100644
--- a/Source/Core/Common/x64CPUDetect.cpp
+++ b/Source/Core/Common/x64CPUDetect.cpp
@@ -197,6 +197,7 @@ void CPUInfo::Detect()
// Check for more features.
__cpuid(cpu_id, 0x80000001);
if (cpu_id[2] & 1) bLAHFSAHF64 = true;
+ if ((cpu_id[2] >> 5) & 1) bLZCNT = true;
if ((cpu_id[3] >> 29) & 1) bLongMode = true;
}
diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp
index 77cb1f9f72..ec80600260 100644
--- a/Source/Core/Common/x64Emitter.cpp
+++ b/Source/Core/Common/x64Emitter.cpp
@@ -750,12 +750,14 @@ void XEmitter::IDIV(int bits, OpArg src) {WriteMulDivType(bits, src, 7);}
void XEmitter::NEG(int bits, OpArg src) {WriteMulDivType(bits, src, 3);}
void XEmitter::NOT(int bits, OpArg src) {WriteMulDivType(bits, src, 2);}
-void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2)
+void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep)
{
_assert_msg_(DYNA_REC, !src.IsImm(), "WriteBitSearchType - Imm argument");
src.operandReg = (u8)dest;
if (bits == 16)
Write8(0x66);
+ if (rep)
+ Write8(0xF3);
src.WriteRex(this, bits, bits);
Write8(0x0F);
Write8(byte2);
@@ -772,6 +774,19 @@ void XEmitter::MOVNTI(int bits, OpArg dest, X64Reg src)
void XEmitter::BSF(int bits, X64Reg dest, OpArg src) {WriteBitSearchType(bits,dest,src,0xBC);} //bottom bit to top bit
void XEmitter::BSR(int bits, X64Reg dest, OpArg src) {WriteBitSearchType(bits,dest,src,0xBD);} //top bit to bottom bit
+void XEmitter::TZCNT(int bits, X64Reg dest, OpArg src)
+{
+ if (!cpu_info.bBMI1)
+ PanicAlert("Trying to use BMI1 on a system that doesn't support it. Bad programmer.");
+ WriteBitSearchType(bits, dest, src, 0xBC, true);
+}
+void XEmitter::LZCNT(int bits, X64Reg dest, OpArg src)
+{
+ if (!cpu_info.bLZCNT)
+ PanicAlert("Trying to use LZCNT on a system that doesn't support it. Bad programmer.");
+ WriteBitSearchType(bits, dest, src, 0xBD, true);
+}
+
void XEmitter::MOVSX(int dbits, int sbits, X64Reg dest, OpArg src)
{
_assert_msg_(DYNA_REC, !src.IsImm(), "MOVSX - Imm argument");
diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h
index 228626c407..8f41065668 100644
--- a/Source/Core/Common/x64Emitter.h
+++ b/Source/Core/Common/x64Emitter.h
@@ -266,7 +266,7 @@ private:
void WriteSimple1Byte(int bits, u8 byte, X64Reg reg);
void WriteSimple2Byte(int bits, u8 byte1, u8 byte2, X64Reg reg);
void WriteMulDivType(int bits, OpArg src, int ext);
- void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2);
+ void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep = false);
void WriteShift(int bits, OpArg dest, OpArg &shift, int ext);
void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext);
void WriteMXCSR(OpArg arg, int ext);
@@ -454,6 +454,11 @@ public:
// Available only on Atom or >= Haswell so far. Test with cpu_info.bMOVBE.
void MOVBE(int dbits, const OpArg& dest, const OpArg& src);
+ // Available only on AMD >= Phenom or Intel >= Haswell
+ void LZCNT(int bits, X64Reg dest, OpArg src);
+ // Note: this one is actually part of BMI1
+ void TZCNT(int bits, X64Reg dest, OpArg src);
+
// WARNING - These two take 11-13 cycles and are VectorPath! (AMD64)
void STMXCSR(OpArg memloc);
void LDMXCSR(OpArg memloc);
diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
index a62a299827..50351eb479 100644
--- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
@@ -1905,13 +1905,19 @@ void Jit64::cntlzwx(UGeckoInstruction inst)
else
{
gpr.Lock(a, s);
- gpr.KillImmediate(s, true, false);
- gpr.BindToRegister(a, (a == s), true);
- BSR(32, gpr.R(a).GetSimpleReg(), gpr.R(s));
- FixupBranch gotone = J_CC(CC_NZ);
- MOV(32, gpr.R(a), Imm32(63));
- SetJumpTarget(gotone);
- XOR(32, gpr.R(a), Imm8(0x1f)); // flip order
+ gpr.BindToRegister(a, a == s, true);
+ if (cpu_info.bLZCNT)
+ {
+ LZCNT(32, gpr.RX(a), gpr.R(s));
+ }
+ else
+ {
+ BSR(32, gpr.RX(a), gpr.R(s));
+ FixupBranch gotone = J_CC(CC_NZ);
+ MOV(32, gpr.R(a), Imm32(63));
+ SetJumpTarget(gotone);
+ XOR(32, gpr.R(a), Imm8(0x1f)); // flip order
+ }
gpr.UnlockAll();
}