Jit64: boolX - Precompute complement of b
PowerPC instructions andcx and orcx complement the value of register b before performing their respective bitwise operation. If this register happens to contain a known value, we can precompute the complement, allowing us to generate simpler code. - andcx Before: BF 00 01 00 00 mov edi,100h F7 D7 not edi 41 23 FE and edi,r14d After: 41 8B FE mov edi,r14d 81 E7 FF FE FF FF and edi,0FFFFFEFFh - orc Before: 41 BE 04 00 00 00 mov r14d,4 41 F7 D6 not r14d 45 0B F5 or r14d,r13d After: 45 8B F5 mov r14d,r13d 41 83 CE FB or r14d,0FFFFFFFBh
This commit is contained in:
parent
caff472dbf
commit
26f70657bc
|
@ -662,6 +662,98 @@ void Jit64::boolX(UGeckoInstruction inst)
|
|||
else if (inst.SUBOP10 == 284) // eqvx
|
||||
gpr.SetImmediate32(a, ~(rs_offset ^ rb_offset));
|
||||
}
|
||||
else if (gpr.IsImm(s) || gpr.IsImm(b))
|
||||
{
|
||||
auto [i, j] = gpr.IsImm(s) ? std::pair(s, b) : std::pair(b, s);
|
||||
u32 imm = gpr.Imm32(i);
|
||||
|
||||
bool complement_b = (inst.SUBOP10 == 60 /* andcx */) || (inst.SUBOP10 == 412 /* orcx */);
|
||||
bool final_not = (inst.SUBOP10 == 476 /* nandx */) || (inst.SUBOP10 == 124 /* norx */) ||
|
||||
(inst.SUBOP10 == 284 /* eqvx */);
|
||||
bool is_and = (inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 60 /* andcx */) ||
|
||||
(inst.SUBOP10 == 476 /* nandx */);
|
||||
bool is_or = (inst.SUBOP10 == 444 /* orx */) || (inst.SUBOP10 == 412 /* orcx */) ||
|
||||
(inst.SUBOP10 == 124 /* norx */);
|
||||
bool is_xor = (inst.SUBOP10 == 316 /* xorx */) || (inst.SUBOP10 == 284 /* eqvx */);
|
||||
|
||||
// Precompute complement when possible
|
||||
if (complement_b && gpr.IsImm(b))
|
||||
{
|
||||
imm = ~imm;
|
||||
complement_b = false;
|
||||
}
|
||||
|
||||
if (is_xor)
|
||||
{
|
||||
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||
RegCache::Realize(Rj, Ra);
|
||||
|
||||
if (a != j)
|
||||
MOV(32, Ra, Rj);
|
||||
XOR(32, Ra, Imm32(imm));
|
||||
|
||||
if (final_not)
|
||||
{
|
||||
NOT(32, Ra);
|
||||
needs_test = true;
|
||||
}
|
||||
}
|
||||
else if (is_and)
|
||||
{
|
||||
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||
RegCache::Realize(Rj, Ra);
|
||||
|
||||
if (complement_b)
|
||||
{
|
||||
if (a != j)
|
||||
MOV(32, Ra, Rj);
|
||||
NOT(32, Ra);
|
||||
AND(32, Ra, Imm32(imm));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a != j)
|
||||
MOV(32, Ra, Rj);
|
||||
AND(32, Ra, Imm32(imm));
|
||||
}
|
||||
|
||||
if (final_not) {
|
||||
NOT(32, Ra);
|
||||
needs_test = true;
|
||||
}
|
||||
}
|
||||
else if (is_or)
|
||||
{
|
||||
RCOpArg Rj = gpr.Use(j, RCMode::Read);
|
||||
RCX64Reg Ra = gpr.Bind(a, RCMode::Write);
|
||||
RegCache::Realize(Rj, Ra);
|
||||
|
||||
if (complement_b)
|
||||
{
|
||||
if (a != j)
|
||||
MOV(32, Ra, Rj);
|
||||
NOT(32, Ra);
|
||||
OR(32, Ra, Imm32(imm));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a != j)
|
||||
MOV(32, Ra, Rj);
|
||||
OR(32, Ra, Imm32(imm));
|
||||
}
|
||||
|
||||
if (final_not) {
|
||||
NOT(32, Ra);
|
||||
needs_test = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlertFmt("WTF!");
|
||||
}
|
||||
}
|
||||
else if (s == b)
|
||||
{
|
||||
if ((inst.SUBOP10 == 28 /* andx */) || (inst.SUBOP10 == 444 /* orx */))
|
||||
|
|
Loading…
Reference in New Issue