From 83fe874dcc7fca810ca0aa1ddc2eadd93deae0b3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Nov 2013 01:34:42 -0800 Subject: [PATCH] armjit: Use multiple BICs in ANDI2R if possible. Rather than a temporary. --- Common/ArmEmitter.cpp | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index cfde87102a..337e8f7b81 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -177,15 +177,47 @@ void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch) { Operand2 op2; bool inverse; - if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) { + if (val == 0) { + // Avoid the ALU, may improve pipeline. + MOV(rd, 0); + } else if (TryMakeOperand2_AllowInverse(val, op2, &inverse)) { if (!inverse) { AND(rd, rs, op2); } else { BIC(rd, rs, op2); } } else { - MOVI2R(scratch, val); - AND(rd, rs, scratch); + int ops = 0; + for (int i = 0; i < 32; i += 2) { + u8 bits = (val >> i) & 0xFF; + // If either low bit is not set, we need to use a BIC for them. + if ((bits & 3) != 3) { + ++ops; + i += 8 - 2; + } + } + + // The worst case is 4 (e.g. 0x55555555.) + if (ops <= 3) { + bool first = true; + for (int i = 0; i < 32; i += 2) { + u8 bits = (val >> i) & 0xFF; + if ((bits & 3) != 3) { + u8 rotation = i == 0 ? 0 : 16 - i / 2; + if (first) { + BIC(rd, rs, Operand2(~bits, rotation)); + first = false; + } else { + BIC(rd, rd, Operand2(~bits, rotation)); + } + // Well, we took care of these other bits while we were at it. + i += 8 - 2; + } + } + } else { + MOVI2R(scratch, val); + AND(rd, rs, scratch); + } } }