#include "graphics/shader/recompiler/ExportOps.h" #include namespace Libs::Graphics::ShaderRecompiler::Decoder { bool DecodeExp(uint32_t pc, std::span code, uint32_t word_index, Instruction& inst, std::string* error) { if (word_index + 1u >= code.size()) { if (error != nullptr) { *error = fmt::format("truncated EXP instruction at pc 0x{:08x}", pc); } return false; } const uint32_t word0 = code[word_index]; const uint32_t word1 = code[word_index + 1u]; const uint32_t target = (word0 >> 4u) & 0x3fu; const uint32_t en = word0 & 0xfu; inst.pc = pc; inst.word = word0; inst.word_count = 2; inst.family = Family::EXP; inst.opcode_id = target; inst.opcode = Opcode::Exp; inst.exp.target = target; inst.exp.en = en; inst.exp.compr = ((word0 >> 10u) & 1u) != 0; inst.exp.done = ((word0 >> 11u) & 1u) != 0; inst.exp.vm = ((word0 >> 12u) & 1u) != 0; SetRawWords(inst, code, word_index, 2); if (!DecodeVectorGpr(word1 & 0xffu, inst.src0, error) || !DecodeVectorGpr((word1 >> 8u) & 0xffu, inst.src1, error) || !DecodeVectorGpr((word1 >> 16u) & 0xffu, inst.src2, error) || !DecodeVectorGpr((word1 >> 24u) & 0xffu, inst.src3, error)) { return false; } if (target == 0x14u && inst.exp.done && en == 0x1u) { inst.src_count = 1u; } else { inst.src_count = inst.exp.compr ? 2u : 4u; } if (en == 0u) { inst.src_count = 0; } return true; } } // namespace Libs::Graphics::ShaderRecompiler::Decoder