static bool disassembleJump(State &state, shadir::CfInstruction *inst) { if (inst->id == SQ_CF_INST_CALL && inst->callCount) { state.out << " CALL_COUNT(" << inst->callCount << ")"; } disassembleCondition(state, inst); if (inst->popCount) { state.out << " POP_COUNT(" << inst->popCount << ")"; } if (inst->id == SQ_CF_INST_CALL || inst->id == SQ_CF_INST_ELSE || inst->id == SQ_CF_INST_JUMP) { state.out << " ADDR(" << inst->addr << ")"; } if (inst->validPixelMode) { state.out << " VALID_PIX"; } if (!inst->barrier) { state.out << " NO_BARRIER"; } state.out << '\n'; return true; }
static void disassembleJump(fmt::MemoryWriter &out, const ControlFlowInst &inst) { auto id = inst.word1.CF_INST(); if (id == SQ_CF_INST_CALL && inst.word1.CALL_COUNT()) { out << " CALL_COUNT(" << inst.word1.CALL_COUNT() << ")"; } disassembleCondition(out, inst); if (inst.word1.POP_COUNT()) { out << " POP_COUNT(" << inst.word1.POP_COUNT() << ")"; } if (id == SQ_CF_INST_CALL || id == SQ_CF_INST_ELSE || id == SQ_CF_INST_JUMP) { out << " ADDR(" << inst.word0.ADDR << ")"; } if (inst.word1.VALID_PIXEL_MODE()) { out << " VALID_PIX"; } if (!inst.word1.BARRIER()) { out << " NO_BARRIER"; } }
void disassembleCfVTX(fmt::MemoryWriter &out, const ControlFlowInst &inst) { auto addr = inst.word0.ADDR; auto count = (inst.word1.COUNT() + 1) | (inst.word1.COUNT_3() << 3); out << " ADDR(" << addr << ")" << " CNT(" << count << ")"; if (!inst.word1.BARRIER()) { out << " NO_BARRIER"; } disassembleCondition(out, inst); }
static void disassembleLoop(fmt::MemoryWriter &out, const ControlFlowInst &inst) { disassembleCondition(out, inst); switch (inst.word1.CF_INST()) { case SQ_CF_INST_LOOP_START: case SQ_CF_INST_LOOP_END: if (!inst.word1.COND()) { // If .COND is set - disassembleCondition will print CF_CONST out << " CF_CONST(" << inst.word1.CF_CONST() << ")"; } } switch (inst.word1.CF_INST()) { case SQ_CF_INST_LOOP_START: case SQ_CF_INST_LOOP_START_DX10: case SQ_CF_INST_LOOP_START_NO_AL: out << " FAIL_JUMP_ADDR(" << inst.word0.ADDR << ")"; break; case SQ_CF_INST_LOOP_CONTINUE: case SQ_CF_INST_LOOP_BREAK: out << " ADDR(" << inst.word0.ADDR << ")"; break; case SQ_CF_INST_LOOP_END: out << " PASS_JUMP_ADDR(" << inst.word0.ADDR << ")"; break; default: out << " UNKNOWN_LOOP_CF_INST"; } if (inst.word1.POP_COUNT()) { out << " POP_COUNT(" << inst.word1.POP_COUNT() << ")"; } if (inst.word1.VALID_PIXEL_MODE()) { out << " VALID_PIX"; } if (!inst.word1.BARRIER()) { out << " NO_BARRIER"; } }
bool disassembleVTX(State &state, shadir::CfInstruction *inst) { state.out << " ADDR(" << inst->addr << ")" << " CNT(" << inst->clause.size() << ")"; if (!inst->barrier) { state.out << " NO_BARRIER"; } disassembleCondition(state, inst); state.out << '\n'; increaseIndent(state); for (auto &child : inst->clause) { // TODO: Disassemble VTX clauses } decreaseIndent(state); return true; }
void disassembleCF(fmt::MemoryWriter &out, const ControlFlowInst &inst) { auto id = inst.word1.CF_INST(); auto name = getInstructionName(id); out << name; switch (id) { case SQ_CF_INST_TEX: disassembleCfTEX(out, inst); break; case SQ_CF_INST_VTX: case SQ_CF_INST_VTX_TC: disassembleCfVTX(out, inst); break; case SQ_CF_INST_LOOP_START: case SQ_CF_INST_LOOP_START_DX10: case SQ_CF_INST_LOOP_START_NO_AL: case SQ_CF_INST_LOOP_END: case SQ_CF_INST_LOOP_CONTINUE: case SQ_CF_INST_LOOP_BREAK: disassembleLoop(out, inst); break; case SQ_CF_INST_JUMP: case SQ_CF_INST_ELSE: case SQ_CF_INST_CALL: case SQ_CF_INST_CALL_FS: case SQ_CF_INST_RETURN: case SQ_CF_INST_POP_JUMP: disassembleJump(out, inst); break; case SQ_CF_INST_EMIT_VERTEX: case SQ_CF_INST_EMIT_CUT_VERTEX: case SQ_CF_INST_CUT_VERTEX: if (!inst.word1.BARRIER()) { out << " NO_BARRIER"; } break; case SQ_CF_INST_PUSH: case SQ_CF_INST_PUSH_ELSE: case SQ_CF_INST_KILL: disassembleCondition(out, inst); // switch case pass through case SQ_CF_INST_POP: case SQ_CF_INST_POP_PUSH: case SQ_CF_INST_POP_PUSH_ELSE: if (inst.word1.POP_COUNT()) { out << " POP_COUNT(" << inst.word1.POP_COUNT() << ")"; } if (inst.word1.VALID_PIXEL_MODE()) { out << " VALID_PIX"; } break; case SQ_CF_INST_END_PROGRAM: case SQ_CF_INST_NOP: break; case SQ_CF_INST_WAIT_ACK: case SQ_CF_INST_TEX_ACK: case SQ_CF_INST_VTX_ACK: case SQ_CF_INST_VTX_TC_ACK: default: out << " UNK_FORMAT"; break; } }
bool disassembleControlFlow(State &state, shadir::CfInstruction *inst) { state.out.write("{}{:02} {}", state.indent, inst->cfPC, inst->name); switch (inst->id) { case SQ_CF_INST_TEX: return disassembleTEX(state, inst); case SQ_CF_INST_VTX: case SQ_CF_INST_VTX_TC: return disassembleVTX(state, inst); case SQ_CF_INST_LOOP_START: case SQ_CF_INST_LOOP_START_DX10: case SQ_CF_INST_LOOP_START_NO_AL: case SQ_CF_INST_LOOP_END: case SQ_CF_INST_LOOP_CONTINUE: case SQ_CF_INST_LOOP_BREAK: return disassembleLoop(state, inst); case SQ_CF_INST_JUMP: case SQ_CF_INST_ELSE: case SQ_CF_INST_CALL: case SQ_CF_INST_CALL_FS: case SQ_CF_INST_RETURN: case SQ_CF_INST_POP_JUMP: return disassembleJump(state, inst); case SQ_CF_INST_EMIT_VERTEX: case SQ_CF_INST_EMIT_CUT_VERTEX: case SQ_CF_INST_CUT_VERTEX: if (!inst->barrier) { state.out << " NO_BARRIER"; } state.out << '\n'; break; case SQ_CF_INST_PUSH: case SQ_CF_INST_PUSH_ELSE: case SQ_CF_INST_KILL: disassembleCondition(state, inst); // pass through case SQ_CF_INST_POP: case SQ_CF_INST_POP_PUSH: case SQ_CF_INST_POP_PUSH_ELSE: if (inst->popCount) { state.out << " POP_COUNT(" << inst->popCount << ")"; } if (inst->validPixelMode) { state.out << " VALID_PIX"; } state.out << '\n'; break; case SQ_CF_INST_END_PROGRAM: case SQ_CF_INST_NOP: state.out << '\n'; break; case SQ_CF_INST_WAIT_ACK: case SQ_CF_INST_TEX_ACK: case SQ_CF_INST_VTX_ACK: case SQ_CF_INST_VTX_TC_ACK: default: state.out << " UNK_FORMAT\n"; break; } return false; }