Merge pull request #11503 from JosJuice/ppcanalyst-read-cr

PPCAnalyst: Actually check if instructions want CR
This commit is contained in:
Admiral H. Curtiss 2023-02-14 00:55:24 +01:00 committed by GitHub
commit 3458c58c7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 40 deletions

View File

@ -29,7 +29,7 @@ static std::array<GekkoOPTemplate, 54> primarytable =
{59, Interpreter::RunTable59, {"RunTable59", OpType::Subtable, 0, 0, 0, 0, 0}}, {59, Interpreter::RunTable59, {"RunTable59", OpType::Subtable, 0, 0, 0, 0, 0}},
{63, Interpreter::RunTable63, {"RunTable63", OpType::Subtable, 0, 0, 0, 0, 0}}, {63, Interpreter::RunTable63, {"RunTable63", OpType::Subtable, 0, 0, 0, 0, 0}},
{16, Interpreter::bcx, {"bcx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}}, {16, Interpreter::bcx, {"bcx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{18, Interpreter::bx, {"bx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}}, {18, Interpreter::bx, {"bx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}},
{3, Interpreter::twi, {"twi", OpType::System, FL_IN_A | FL_ENDBLOCK, 1, 0, 0, 0}}, {3, Interpreter::twi, {"twi", OpType::System, FL_IN_A | FL_ENDBLOCK, 1, 0, 0, 0}},
@ -143,8 +143,8 @@ static std::array<GekkoOPTemplate, 4> table4_3 =
static std::array<GekkoOPTemplate, 13> table19 = static std::array<GekkoOPTemplate, 13> table19 =
{{ {{
{528, Interpreter::bcctrx, {"bcctrx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}}, {528, Interpreter::bcctrx, {"bcctrx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{16, Interpreter::bclrx, {"bclrx", OpType::Branch, FL_ENDBLOCK, 1, 0, 0, 0}}, {16, Interpreter::bclrx, {"bclrx", OpType::Branch, FL_ENDBLOCK | FL_READ_CR_BI, 1, 0, 0, 0}},
{257, Interpreter::crand, {"crand", OpType::CR, FL_EVIL, 1, 0, 0, 0}}, {257, Interpreter::crand, {"crand", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{129, Interpreter::crandc, {"crandc", OpType::CR, FL_EVIL, 1, 0, 0, 0}}, {129, Interpreter::crandc, {"crandc", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{289, Interpreter::creqv, {"creqv", OpType::CR, FL_EVIL, 1, 0, 0, 0}}, {289, Interpreter::creqv, {"creqv", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
@ -155,7 +155,7 @@ static std::array<GekkoOPTemplate, 13> table19 =
{193, Interpreter::crxor, {"crxor", OpType::CR, FL_EVIL, 1, 0, 0, 0}}, {193, Interpreter::crxor, {"crxor", OpType::CR, FL_EVIL, 1, 0, 0, 0}},
{150, Interpreter::isync, {"isync", OpType::InstructionCache, FL_EVIL, 1, 0, 0, 0}}, {150, Interpreter::isync, {"isync", OpType::InstructionCache, FL_EVIL, 1, 0, 0, 0}},
{0, Interpreter::mcrf, {"mcrf", OpType::System, FL_EVIL | FL_SET_CRn, 1, 0, 0, 0}}, {0, Interpreter::mcrf, {"mcrf", OpType::System, FL_EVIL | FL_SET_CRn | FL_READ_CRn, 1, 0, 0, 0}},
{50, Interpreter::rfi, {"rfi", OpType::System, FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION, 2, 0, 0, 0}}, {50, Interpreter::rfi, {"rfi", OpType::System, FL_ENDBLOCK | FL_CHECKEXCEPTIONS | FL_PROGRAMEXCEPTION, 2, 0, 0, 0}},
}}; }};
@ -278,9 +278,9 @@ static std::array<GekkoOPTemplate, 107> table31 =
{759, Interpreter::stfdux, {"stfdux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}}, {759, Interpreter::stfdux, {"stfdux", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_AB | FL_OUT_A | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{983, Interpreter::stfiwx, {"stfiwx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}}, {983, Interpreter::stfiwx, {"stfiwx", OpType::StoreFP, FL_IN_FLOAT_S | FL_IN_A0B | FL_USE_FPU | FL_LOADSTORE, 1, 0, 0, 0}},
{19, Interpreter::mfcr, {"mfcr", OpType::System, FL_OUT_D, 1, 0, 0, 0}}, {19, Interpreter::mfcr, {"mfcr", OpType::System, FL_OUT_D | FL_READ_ALL_CR, 1, 0, 0, 0}},
{83, Interpreter::mfmsr, {"mfmsr", OpType::System, FL_OUT_D | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}}, {83, Interpreter::mfmsr, {"mfmsr", OpType::System, FL_OUT_D | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{144, Interpreter::mtcrf, {"mtcrf", OpType::System, FL_IN_S | FL_SET_CRn, 1, 0, 0, 0}}, {144, Interpreter::mtcrf, {"mtcrf", OpType::System, FL_IN_S | FL_SET_ALL_CR | FL_READ_ALL_CR, 1, 0, 0, 0}},
{146, Interpreter::mtmsr, {"mtmsr", OpType::System, FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}}, {146, Interpreter::mtmsr, {"mtmsr", OpType::System, FL_IN_S | FL_ENDBLOCK | FL_PROGRAMEXCEPTION | FL_FLOAT_EXCEPTION, 1, 0, 0, 0}},
{210, Interpreter::mtsr, {"mtsr", OpType::System, FL_IN_S | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}}, {210, Interpreter::mtsr, {"mtsr", OpType::System, FL_IN_S | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},
{242, Interpreter::mtsrin, {"mtsrin", OpType::System, FL_IN_SB | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}}, {242, Interpreter::mtsrin, {"mtsrin", OpType::System, FL_IN_SB | FL_PROGRAMEXCEPTION, 1, 0, 0, 0}},

View File

@ -483,7 +483,7 @@ void PPCAnalyzer::ReorderInstructionsCore(u32 instructions, CodeOp* code, bool r
// (if we add more merged branch instructions, add them here!) // (if we add more merged branch instructions, add them here!)
if ((type == ReorderType::CROR && isCror(a)) || if ((type == ReorderType::CROR && isCror(a)) ||
(type == ReorderType::Carry && isCarryOp(a)) || (type == ReorderType::Carry && isCarryOp(a)) ||
(type == ReorderType::CMP && (isCmp(a) || a.outputCR0))) (type == ReorderType::CMP && (isCmp(a) || a.outputCR[0])))
{ {
// once we're next to a carry instruction, don't move away! // once we're next to a carry instruction, don't move away!
if (type == ReorderType::Carry && i != start) if (type == ReorderType::Carry && i != start)
@ -532,9 +532,6 @@ void PPCAnalyzer::ReorderInstructions(u32 instructions, CodeOp* code) const
void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code, void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code,
const GekkoOPInfo* opinfo) const const GekkoOPInfo* opinfo) const
{ {
code->wantsCR0 = false;
code->wantsCR1 = false;
bool first_fpu_instruction = false; bool first_fpu_instruction = false;
if (opinfo->flags & FL_USE_FPU) if (opinfo->flags & FL_USE_FPU)
{ {
@ -542,21 +539,23 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code,
block->m_fpa->any = true; block->m_fpa->any = true;
} }
// Does the instruction output CR0? code->wantsCR = BitSet8(0);
if (opinfo->flags & FL_RC_BIT) if (opinfo->flags & FL_READ_ALL_CR)
code->outputCR0 = code->inst.hex & 1; // todo fix code->wantsCR = BitSet8(0xFF);
else if ((opinfo->flags & FL_SET_CRn) && code->inst.CRFD == 0) else if (opinfo->flags & FL_READ_CRn)
code->outputCR0 = true; code->wantsCR[code->inst.CRFS] = true;
else else if (opinfo->flags & FL_READ_CR_BI)
code->outputCR0 = (opinfo->flags & FL_SET_CR0) != 0; code->wantsCR[code->inst.BI] = true;
// Does the instruction output CR1? code->outputCR = BitSet8(0);
if (opinfo->flags & FL_RC_BIT_F) if (opinfo->flags & FL_SET_ALL_CR)
code->outputCR1 = code->inst.hex & 1; // todo fix code->outputCR = BitSet8(0xFF);
else if ((opinfo->flags & FL_SET_CRn) && code->inst.CRFD == 1) else if (opinfo->flags & FL_SET_CRn)
code->outputCR1 = true; code->outputCR[code->inst.CRFD] = true;
else else if ((opinfo->flags & FL_SET_CR0) || ((opinfo->flags & FL_RC_BIT) && code->inst.Rc))
code->outputCR1 = (opinfo->flags & FL_SET_CR1) != 0; code->outputCR[0] = true;
else if ((opinfo->flags & FL_SET_CR1) || ((opinfo->flags & FL_RC_BIT_F) && code->inst.Rc))
code->outputCR[1] = true;
code->wantsFPRF = (opinfo->flags & FL_READ_FPRF) != 0; code->wantsFPRF = (opinfo->flags & FL_READ_FPRF) != 0;
code->outputFPRF = (opinfo->flags & FL_SET_FPRF) != 0; code->outputFPRF = (opinfo->flags & FL_SET_FPRF) != 0;
@ -914,26 +913,24 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
// Scan for flag dependencies; assume the next block (or any branch that can leave the block) // Scan for flag dependencies; assume the next block (or any branch that can leave the block)
// wants flags, to be safe. // wants flags, to be safe.
bool wantsCR0 = true, wantsCR1 = true, wantsFPRF = true, wantsCA = true; BitSet8 wantsCR = BitSet8(0xFF);
bool wantsFPRF = true;
bool wantsCA = true;
BitSet32 fprInUse, gprInUse, gprDiscardable, fprDiscardable, fprInXmm; BitSet32 fprInUse, gprInUse, gprDiscardable, fprDiscardable, fprInXmm;
for (int i = block->m_num_instructions - 1; i >= 0; i--) for (int i = block->m_num_instructions - 1; i >= 0; i--)
{ {
CodeOp& op = code[i]; CodeOp& op = code[i];
const bool opWantsCR0 = op.wantsCR0; const BitSet8 opWantsCR = op.wantsCR;
const bool opWantsCR1 = op.wantsCR1;
const bool opWantsFPRF = op.wantsFPRF; const bool opWantsFPRF = op.wantsFPRF;
const bool opWantsCA = op.wantsCA; const bool opWantsCA = op.wantsCA;
op.wantsCR0 = wantsCR0 || op.canEndBlock || op.canCauseException; op.wantsCR = wantsCR | BitSet8(op.canEndBlock || op.canCauseException ? 0xFF : 0);
op.wantsCR1 = wantsCR1 || op.canEndBlock || op.canCauseException;
op.wantsFPRF = wantsFPRF || op.canEndBlock || op.canCauseException; op.wantsFPRF = wantsFPRF || op.canEndBlock || op.canCauseException;
op.wantsCA = wantsCA || op.canEndBlock || op.canCauseException; op.wantsCA = wantsCA || op.canEndBlock || op.canCauseException;
wantsCR0 |= opWantsCR0 || op.canEndBlock || op.canCauseException; wantsCR |= opWantsCR | BitSet8(op.canEndBlock || op.canCauseException ? 0xFF : 0);
wantsCR1 |= opWantsCR1 || op.canEndBlock || op.canCauseException;
wantsFPRF |= opWantsFPRF || op.canEndBlock || op.canCauseException; wantsFPRF |= opWantsFPRF || op.canEndBlock || op.canCauseException;
wantsCA |= opWantsCA || op.canEndBlock || op.canCauseException; wantsCA |= opWantsCA || op.canEndBlock || op.canCauseException;
wantsCR0 &= !op.outputCR0 || opWantsCR0; wantsCR &= ~op.outputCR | opWantsCR;
wantsCR1 &= !op.outputCR1 || opWantsCR1;
wantsFPRF &= !op.outputFPRF || opWantsFPRF; wantsFPRF &= !op.outputFPRF || opWantsFPRF;
wantsCA &= !op.outputCA || opWantsCA; wantsCA &= !op.outputCA || opWantsCA;
op.gprInUse = gprInUse; op.gprInUse = gprInUse;

View File

@ -39,13 +39,11 @@ struct CodeOp // 16B
bool isBranchTarget = false; bool isBranchTarget = false;
bool branchUsesCtr = false; bool branchUsesCtr = false;
bool branchIsIdleLoop = false; bool branchIsIdleLoop = false;
bool wantsCR0 = false; BitSet8 wantsCR;
bool wantsCR1 = false;
bool wantsFPRF = false; bool wantsFPRF = false;
bool wantsCA = false; bool wantsCA = false;
bool wantsCAInFlags = false; bool wantsCAInFlags = false;
bool outputCR0 = false; BitSet8 outputCR;
bool outputCR1 = false;
bool outputFPRF = false; bool outputFPRF = false;
bool outputCA = false; bool outputCA = false;
bool canEndBlock = false; bool canEndBlock = false;

View File

@ -15,8 +15,7 @@ enum InstructionFlags : u64
{ {
FL_SET_CR0 = (1ull << 0), // Sets CR0. FL_SET_CR0 = (1ull << 0), // Sets CR0.
FL_SET_CR1 = (1ull << 1), // Sets CR1. FL_SET_CR1 = (1ull << 1), // Sets CR1.
FL_SET_CRn = (1ull << 2), // Encoding decides which CR can be set. FL_SET_CRn = (1ull << 2), // Sets a CR determined by the CRFD field.
FL_SET_CRx = FL_SET_CR0 | FL_SET_CR1 | FL_SET_CRn,
FL_SET_CA = (1ull << 3), // Sets the carry flag. FL_SET_CA = (1ull << 3), // Sets the carry flag.
FL_READ_CA = (1ull << 4), // Reads the carry flag. FL_READ_CA = (1ull << 4), // Reads the carry flag.
FL_RC_BIT = (1ull << 5), // Sets the record bit. FL_RC_BIT = (1ull << 5), // Sets the record bit.
@ -67,6 +66,12 @@ enum InstructionFlags : u64
FL_PROGRAMEXCEPTION = (1ull << 32), // May generate a program exception (not floating point). FL_PROGRAMEXCEPTION = (1ull << 32), // May generate a program exception (not floating point).
FL_FLOAT_EXCEPTION = (1ull << 33), // May generate a program exception (floating point). FL_FLOAT_EXCEPTION = (1ull << 33), // May generate a program exception (floating point).
FL_FLOAT_DIV = (1ull << 34), // May generate a program exception (FP) due to division by 0. FL_FLOAT_DIV = (1ull << 34), // May generate a program exception (FP) due to division by 0.
FL_SET_ALL_CR = (1ull << 35), // Sets every CR.
FL_READ_CRn = (1ull << 36), // Reads a CR determined by the CRFS field.
FL_READ_CR_BI = (1ull << 37), // Reads a CR determined by the BI field.
FL_READ_ALL_CR = (1ull << 38), // Reads every CR.
FL_SET_CRx = FL_SET_CR0 | FL_SET_CR1 | FL_SET_CRn | FL_SET_ALL_CR,
FL_READ_CRx = FL_READ_CRn | FL_READ_CR_BI | FL_READ_ALL_CR,
}; };
enum class OpType enum class OpType