armjit: Use multiple BICs in ANDI2R if possible.

Rather than a temporary.
This commit is contained in:
Unknown W. Brackets 2013-11-09 01:34:42 -08:00
parent 4026944b02
commit 83fe874dcc

View File

@ -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);
}
}
}