void ILogger::log(std::ostream *stream, enum logger::LoggerSeverity severity, const char* format, ...) { std::lock_guard<std::mutex> lock(m_mutex); int n; va_list params; m_severity = severity; m_stream = stream; beginLine(); va_start(params, format); n = vsnprintf(m_buffer, c_buffer_size - 2, format, params); va_end(params); // Add a '\n' if missing if ('\n' != m_buffer[n - 1]) { m_buffer[n] = '\n'; m_buffer[n + 1] = '\0'; } write(m_buffer); m_stream = nullptr; }
bool disassembleTEX(DisassembleState &state, latte::cf::inst cfID, latte::cf::Instruction &cf) { const uint32_t *ptr = state.words + (latte::WordsPerCF * cf.word0.addr); state.out << latte::cf::name[cfID] << ": " << "ADDR(" << cf.word0.addr << ") CNT(" << (cf.word1.count + 1) << ")"; endLine(state); increaseIndent(state); for (auto slot = 0u; slot <= cf.word1.count; ) { auto tex = *reinterpret_cast<const 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 += latte::WordsPerVTX; } else if (id == latte::tex::MEM) { assert(false); ptr += latte::WordsPerMEM; } else { beginLine(state); state.out << fmt::pad(state.group, groupCounterSize, '0') << ' ' << name << ' '; // Write dst if (tex.word1.dstRel != 0) { // TODO: relative address state.out << "__UNK_REL(" << tex.word1.dstRel << ")__"; } writeRegisterName(state, tex.word1.dstReg); state.out << '.'; writeSelectName(state, tex.word1.dstSelX); writeSelectName(state, tex.word1.dstSelY); writeSelectName(state, tex.word1.dstSelZ); writeSelectName(state, tex.word1.dstSelW); // Write src state.out << ", "; if (tex.word0.srcRel != 0) { // TODO: relative address state.out << "__UNK_REL(" << tex.word0.srcRel << ")__"; } writeRegisterName(state, tex.word0.srcReg); state.out << '.'; writeSelectName(state, tex.word2.srcSelX); writeSelectName(state, tex.word2.srcSelY); writeSelectName(state, tex.word2.srcSelZ); writeSelectName(state, tex.word2.srcSelW); state.out << ", t" << tex.word0.resourceID << ", s" << tex.word2.samplerID; if (tex.word2.offsetX || tex.word2.offsetY || tex.word2.offsetZ) { state.out << " OFFSET(" << tex.word2.offsetX << ", " << tex.word2.offsetY << ", " << tex.word2.offsetZ << ")"; } if (tex.word1.lodBias) { state.out << " LOD_BIAS(" << tex.word1.lodBias << ")"; } if (!tex.word1.coordTypeX) { state.out << " CTX_UNORM"; } if (!tex.word1.coordTypeY) { state.out << " CTY_UNORM"; } if (!tex.word1.coordTypeZ) { state.out << " CTZ_UNORM"; } if (!tex.word1.coordTypeW) { state.out << " CTW_UNORM"; } if (tex.word0.bcFracMode) { state.out << " BFM"; } if (tex.word0.fetchWholeQuad) { state.out << " FWQ"; } endLine(state); ptr += latte::WordsPerTEX; } state.group++; slot++; } decreaseIndent(state); return true; }
bool disassembleALU(DisassembleState &state, latte::cf::inst id, latte::cf::Instruction &cf) { const uint64_t *slots = reinterpret_cast<const uint64_t *>(state.words + (latte::WordsPerCF * cf.aluWord0.addr)); state.out << latte::alu::name[cf.aluWord1.inst] << ": " << "ADDR(" << cf.aluWord0.addr << ") CNT(" << (cf.aluWord1.count + 1) << ")"; increaseIndent(state); for (auto slot = 0u; slot <= cf.aluWord1.count; ) { static char unitName[] = { 'x', 'y', 'z', 'w', 't' }; bool units[5] = { false, false, false, false, false }; bool last = false; const uint32_t *literalPtr = reinterpret_cast<const uint32_t*>(slots + slot); auto literals = 0u; endLine(state); for (auto i = 0u; i < 5 && !last; ++i) { auto alu = *reinterpret_cast<const latte::alu::Instruction*>(slots + slot + i); literalPtr += 2; last = !!alu.word0.last; } last = false; for (auto i = 0u; i < 5 && !last; ++i) { auto alu = *reinterpret_cast<const latte::alu::Instruction*>(slots + slot); auto unit = getUnit(units, alu); const char *name = nullptr; bool abs0 = false, abs1 = false; auto &opcode = latte::alu::op2info[alu.op2.inst]; if (alu.word1.encoding == latte::alu::Encoding::OP2) { opcode = latte::alu::op2info[alu.op2.inst]; name = opcode.name; abs0 = !!alu.op2.src0Abs; abs1 = !!alu.op2.src1Abs; } else { opcode = latte::alu::op3info[alu.op3.inst]; name = opcode.name; } beginLine(state); if (i == 0) { state.out << fmt::pad(state.group, groupCounterSize, '0'); } else { state.out << std::string(groupCounterSize, ' ').c_str(); } state.out << ' ' << unitName[unit] << ": " << fmt::pad(name, instrNamePad, ' '); if (alu.word1.encoding == latte::alu::Encoding::OP2 && alu.op2.writeMask == 0) { state.out << "____"; } else { writeAluSource(state, literalPtr, alu.word1.dstGpr, alu.word1.dstRel, alu.word1.dstChan, 0, false); } if (opcode.srcs > 0) { state.out << ", "; writeAluSource(state, literalPtr, alu.word0.src0Sel, alu.word0.src0Rel, alu.word0.src0Chan, alu.word0.src0Neg, abs0); } if (opcode.srcs > 1) { state.out << ", "; writeAluSource(state, literalPtr, alu.word0.src1Sel, alu.word0.src1Rel, alu.word0.src1Chan, alu.word0.src1Neg, abs1); } if (alu.word1.encoding == latte::alu::Encoding::OP2) { if (alu.op2.updateExecuteMask) { state.out << " UPDATE_EXECUTE_MASK"; } if (alu.op2.updatePred) { state.out << " UPDATE_PRED"; } switch (alu.op2.omod) { case latte::alu::OutputModifier::Divide2: state.out << " OMOD_D2"; break; case latte::alu::OutputModifier::Multiply2: state.out << " OMOD_M2"; break; case latte::alu::OutputModifier::Multiply4: state.out << " OMOD_M4"; break; } } else { if (opcode.srcs > 2) { state.out << ", "; writeAluSource(state, literalPtr, alu.op3.src2Sel, alu.op3.src2Rel, alu.op3.src2Chan, alu.op3.src2Neg, false); } } switch (alu.word1.bankSwizzle) { case latte::alu::BankSwizzle::Vec021: state.out << " VEC_021"; break; case latte::alu::BankSwizzle::Vec120: state.out << " VEC_120"; break; case latte::alu::BankSwizzle::Vec102: state.out << " VEC_102"; break; case latte::alu::BankSwizzle::Vec201: state.out << " VEC_201"; break; case latte::alu::BankSwizzle::Vec210: state.out << " VEC_210"; break; } if (alu.word1.clamp) { state.out << " CLAMP"; } endLine(state); // Count number of literal used if (alu.word0.src0Sel == latte::alu::Source::SrcLiteral) { literals = std::max(literals, alu.word0.src0Chan + 1); } if (alu.word0.src1Sel == latte::alu::Source::SrcLiteral) { literals = std::max(literals, alu.word0.src1Chan + 1); } if ((alu.word1.encoding != latte::alu::Encoding::OP2) && (alu.op3.src2Sel == latte::alu::Source::SrcLiteral)) { literals = std::max(literals, alu.op3.src2Chan + 1); } // Increase slot id slot += 1; last = !!alu.word0.last; } if (literals) { slot += (literals + 1) >> 1; } state.group++; } decreaseIndent(state); return true; }