diff options
| author | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-09-14 09:18:10 -0500 |
|---|---|---|
| committer | Ryan Houdek <Sonicadvance1@gmail.com> | 2014-09-14 09:18:10 -0500 |
| commit | 4e16abd7428a020c136b35a96284f1af4b261f6e (patch) | |
| tree | 3772a61967a028e653bba64f199fcbfea50537eb /Source/Core | |
| parent | 1f7871f9e2a9c560676fcd7a9961104af11b2ad6 (diff) | |
| parent | 40b18f09b2ce03f908b5303643b352d084b0c4b4 (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.cpp | 1 | ||||
| -rw-r--r-- | Source/Core/Common/x64Emitter.cpp | 17 | ||||
| -rw-r--r-- | Source/Core/Common/x64Emitter.h | 7 | ||||
| -rw-r--r-- | Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 20 |
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(); } |
