bool disassembleExport(DisassembleState &state, latte::cf::inst id, latte::cf::Instruction &cf) { auto eid = static_cast<latte::exp::inst>(cf.expWord1.inst); auto name = latte::exp::name[id]; auto type = static_cast<latte::exp::Type::Type>(cf.expWord0.type); state.out << name << ": "; switch (type) { case latte::exp::Type::Pixel: state.out << "PIX"; break; case latte::exp::Type::Position: state.out << "POS"; break; case latte::exp::Type::Parameter: state.out << "PARAM"; break; } state.out << cf.expWord0.dstReg; state.out << ", R" << cf.expWord0.srcReg << "."; writeSelectName(state, cf.expWord1.srcSelX); writeSelectName(state, cf.expWord1.srcSelY); writeSelectName(state, cf.expWord1.srcSelZ); writeSelectName(state, cf.expWord1.srcSelW); endLine(state); return true; }
bool Disassembler::cfTEX(fmt::MemoryWriter &out, latte::cf::inst cfID, latte::cf::Instruction &cf) { uint32_t *ptr = mWords + (wordsPerCF * cf.word0.addr); out << latte::cf::name[cfID] << ": " << "ADDR(" << cf.word0.addr << ") CNT(" << (cf.word1.count + 1) << ")\n"; increaseIndent(); for (auto slot = 0u; slot <= cf.word1.count; ) { auto tex = *reinterpret_cast<latte::tex::Instruction*>(ptr); auto name = latte::tex::name[tex.word0.inst]; auto id = tex.word0.inst; if (id == latte::tex::VTX_FETCH || id == latte::tex::VTX_SEMANTIC || id == latte::tex::GET_BUFFER_RESINFO) { assert(false); ptr += wordsPerVTX; } else if (id == latte::tex::MEM) { assert(false); ptr += wordsPerMEM; } else { out << mIndent.c_str() << fmt::pad(mGroupCounter, groupCounterSize, '0') << ' ' << name << ' '; // Write dst if (tex.word1.dstRel != 0) { // TODO: relative address out << "__UNK_REL(" << tex.word1.dstRel << ")__"; } writeRegisterName(out, tex.word1.dstReg); out << '.'; writeSelectName(out, tex.word1.dstSelX); writeSelectName(out, tex.word1.dstSelY); writeSelectName(out, tex.word1.dstSelZ); writeSelectName(out, tex.word1.dstSelW); // Write src out << ", "; if (tex.word0.srcRel != 0) { // TODO: relative address out << "__UNK_REL(" << tex.word0.srcRel << ")__"; } writeRegisterName(out, tex.word0.srcReg); out << '.'; writeSelectName(out, tex.word2.srcSelX); writeSelectName(out, tex.word2.srcSelY); writeSelectName(out, tex.word2.srcSelZ); writeSelectName(out, tex.word2.srcSelW); out << ", t" << tex.word0.resourceID << ", s" << tex.word2.samplerID; if (tex.word2.offsetX || tex.word2.offsetY || tex.word2.offsetZ) { out << " OFFSET(" << tex.word2.offsetX << ", " << tex.word2.offsetY << ", " << tex.word2.offsetZ << ")"; } if (tex.word1.lodBias) { out << " LOD_BIAS(" << tex.word1.lodBias << ")"; } if (!tex.word1.coordTypeX) { out << " CTX_UNORM"; } if (!tex.word1.coordTypeY) { out << " CTY_UNORM"; } if (!tex.word1.coordTypeZ) { out << " CTZ_UNORM"; } if (!tex.word1.coordTypeW) { out << " CTW_UNORM"; } if (tex.word0.bcFracMode) { out << " BFM"; } if (tex.word0.fetchWholeQuad) { out << " FWQ"; } out << '\n'; ptr += wordsPerTEX; } mGroupCounter++; slot++; } decreaseIndent(); return true; }