#include "RdnaDecoder/RdnaScalarOpDecoder.hpp" #include "RdnaDecoder/RdnaInstructionDecoder.hpp" #include #include namespace ShaderRecompiler { namespace { RdnaOpcode decodeSop1Opcode(std::uint32_t opcode) { switch (opcode) { case 0x03u: return RdnaOpcode::SMovB32; case 0x04u: return RdnaOpcode::SMovB64; case 0x05u: return RdnaOpcode::SCmovB32; case 0x06u: return RdnaOpcode::SCmovB64; case 0x07u: return RdnaOpcode::SNotB32; case 0x08u: return RdnaOpcode::SNotB64; case 0x09u: return RdnaOpcode::SWqmB32; case 0x0au: return RdnaOpcode::SWqmB64; case 0x0bu: return RdnaOpcode::SBrevB32; case 0x0cu: return RdnaOpcode::SBrevB64; case 0x0du: return RdnaOpcode::SBcnt0I32B32; case 0x0eu: return RdnaOpcode::SBcnt0I32B64; case 0x0fu: return RdnaOpcode::SBcnt1I32B32; case 0x10u: return RdnaOpcode::SBcnt1I32B64; case 0x11u: return RdnaOpcode::SFf0I32B32; case 0x12u: return RdnaOpcode::SFf0I32B64; case 0x13u: return RdnaOpcode::SFf1I32B32; case 0x14u: return RdnaOpcode::SFf1I32B64; case 0x15u: return RdnaOpcode::SFlbitI32B32; case 0x16u: return RdnaOpcode::SFlbitI32B64; case 0x17u: return RdnaOpcode::SFlbitI32; case 0x18u: return RdnaOpcode::SFlbitI32I64; case 0x19u: return RdnaOpcode::SSextI32I8; case 0x1au: return RdnaOpcode::SSextI32I16; case 0x1bu: return RdnaOpcode::SBitset0B32; case 0x1cu: return RdnaOpcode::SBitset0B64; case 0x1du: return RdnaOpcode::SBitset1B32; case 0x1eu: return RdnaOpcode::SBitset1B64; case 0x1fu: return RdnaOpcode::SGetpcB64; case 0x20u: return RdnaOpcode::SSetpcB64; case 0x24u: return RdnaOpcode::SAndSaveexecB64; case 0x25u: return RdnaOpcode::SOrSaveexecB64; case 0x26u: return RdnaOpcode::SXorSaveexecB64; case 0x27u: return RdnaOpcode::SAndn2SaveexecB64; case 0x28u: return RdnaOpcode::SOrn2SaveexecB64; case 0x29u: return RdnaOpcode::SNandSaveexecB64; case 0x2au: return RdnaOpcode::SNorSaveexecB64; case 0x2bu: return RdnaOpcode::SXnorSaveexecB64; case 0x2cu: return RdnaOpcode::SQuadmaskB32; case 0x2du: return RdnaOpcode::SQuadmaskB64; case 0x2eu: return RdnaOpcode::SMovrelsB32; case 0x2fu: return RdnaOpcode::SMovrelsB64; case 0x30u: return RdnaOpcode::SMovreldB32; case 0x31u: return RdnaOpcode::SMovreldB64; case 0x34u: return RdnaOpcode::SAbsI32; case 0x37u: return RdnaOpcode::SAndn1SaveexecB64; case 0x38u: return RdnaOpcode::SOrn1SaveexecB64; case 0x39u: return RdnaOpcode::SAndn1WrexecB64; case 0x3au: return RdnaOpcode::SAndn2WrexecB64; case 0x3bu: return RdnaOpcode::SBitreplicateB64B32; case 0x3cu: return RdnaOpcode::SAndSaveexecB32; case 0x3du: return RdnaOpcode::SOrSaveexecB32; case 0x3eu: return RdnaOpcode::SXorSaveexecB32; case 0x3fu: return RdnaOpcode::SAndn2SaveexecB32; case 0x40u: return RdnaOpcode::SOrn2SaveexecB32; case 0x41u: return RdnaOpcode::SNandSaveexecB32; case 0x42u: return RdnaOpcode::SNorSaveexecB32; case 0x43u: return RdnaOpcode::SXnorSaveexecB32; case 0x44u: return RdnaOpcode::SAndn1SaveexecB32; case 0x45u: return RdnaOpcode::SOrn1SaveexecB32; case 0x46u: return RdnaOpcode::SAndn1WrexecB32; case 0x47u: return RdnaOpcode::SAndn2WrexecB32; case 0x49u: return RdnaOpcode::SMovrelsd2B32; default: throw std::invalid_argument("unsupported SOP1 opcode " + std::to_string(opcode)); } } RdnaOpcode decodeSop2Opcode(std::uint32_t opcode) { switch (opcode) { case 0x00u: return RdnaOpcode::SAddU32; case 0x01u: return RdnaOpcode::SSubU32; case 0x02u: return RdnaOpcode::SAddI32; case 0x03u: return RdnaOpcode::SSubI32; case 0x04u: return RdnaOpcode::SAddcU32; case 0x05u: return RdnaOpcode::SSubbU32; case 0x06u: return RdnaOpcode::SMinI32; case 0x07u: return RdnaOpcode::SMinU32; case 0x08u: return RdnaOpcode::SMaxI32; case 0x09u: return RdnaOpcode::SMaxU32; case 0x0au: return RdnaOpcode::SCselectB32; case 0x0bu: return RdnaOpcode::SCselectB64; case 0x0eu: return RdnaOpcode::SAndB32; case 0x0fu: return RdnaOpcode::SAndB64; case 0x10u: return RdnaOpcode::SOrB32; case 0x11u: return RdnaOpcode::SOrB64; case 0x12u: return RdnaOpcode::SXorB32; case 0x13u: return RdnaOpcode::SXorB64; case 0x14u: return RdnaOpcode::SAndn2B32; case 0x15u: return RdnaOpcode::SAndn2B64; case 0x16u: return RdnaOpcode::SOrn2B32; case 0x17u: return RdnaOpcode::SOrn2B64; case 0x18u: return RdnaOpcode::SNandB32; case 0x19u: return RdnaOpcode::SNandB64; case 0x1au: return RdnaOpcode::SNorB32; case 0x1bu: return RdnaOpcode::SNorB64; case 0x1cu: return RdnaOpcode::SXnorB32; case 0x1du: return RdnaOpcode::SXnorB64; case 0x1eu: return RdnaOpcode::SLshlB32; case 0x1fu: return RdnaOpcode::SLshlB64; case 0x20u: return RdnaOpcode::SLshrB32; case 0x21u: return RdnaOpcode::SLshrB64; case 0x22u: return RdnaOpcode::SAshrI32; case 0x23u: return RdnaOpcode::SAshrI64; case 0x24u: return RdnaOpcode::SBfmB32; case 0x25u: return RdnaOpcode::SBfmB64; case 0x26u: return RdnaOpcode::SMulI32; case 0x27u: return RdnaOpcode::SBfeU32; case 0x28u: return RdnaOpcode::SBfeI32; case 0x29u: return RdnaOpcode::SBfeU64; case 0x2au: return RdnaOpcode::SBfeI64; case 0x2cu: return RdnaOpcode::SAbsdiffI32; case 0x2eu: return RdnaOpcode::SLshl1AddU32; case 0x2fu: return RdnaOpcode::SLshl2AddU32; case 0x30u: return RdnaOpcode::SLshl3AddU32; case 0x31u: return RdnaOpcode::SLshl4AddU32; case 0x32u: return RdnaOpcode::SPackLlB32B16; case 0x33u: return RdnaOpcode::SPackLhB32B16; case 0x34u: return RdnaOpcode::SPackHhB32B16; case 0x35u: return RdnaOpcode::SMulHiU32; case 0x36u: return RdnaOpcode::SMulHiI32; default: throw std::invalid_argument("unsupported SOP2 opcode " + std::to_string(opcode)); } } RdnaOpcode decodeSopcOpcode(std::uint32_t opcode) { switch (opcode) { case 0x00u: return RdnaOpcode::SCmpEqI32; case 0x01u: return RdnaOpcode::SCmpLgI32; case 0x02u: return RdnaOpcode::SCmpGtI32; case 0x03u: return RdnaOpcode::SCmpGeI32; case 0x04u: return RdnaOpcode::SCmpLtI32; case 0x05u: return RdnaOpcode::SCmpLeI32; case 0x06u: return RdnaOpcode::SCmpEqU32; case 0x07u: return RdnaOpcode::SCmpLgU32; case 0x08u: return RdnaOpcode::SCmpGtU32; case 0x09u: return RdnaOpcode::SCmpGeU32; case 0x0au: return RdnaOpcode::SCmpLtU32; case 0x0bu: return RdnaOpcode::SCmpLeU32; case 0x0cu: return RdnaOpcode::SBitcmp0B32; case 0x0du: return RdnaOpcode::SBitcmp1B32; case 0x0eu: return RdnaOpcode::SBitcmp0B64; case 0x0fu: return RdnaOpcode::SBitcmp1B64; case 0x12u: return RdnaOpcode::SCmpEqU64; case 0x13u: return RdnaOpcode::SCmpLgU64; default: throw std::invalid_argument("unsupported SOPC opcode " + std::to_string(opcode)); } } RdnaOpcode decodeSopkOpcode(std::uint32_t opcode) { switch (opcode) { case 0x00u: return RdnaOpcode::SMovkI32; case 0x01u: return RdnaOpcode::SVersion; case 0x02u: return RdnaOpcode::SCmovkI32; case 0x03u: return RdnaOpcode::SCmpEqI32; case 0x04u: return RdnaOpcode::SCmpLgI32; case 0x05u: return RdnaOpcode::SCmpGtI32; case 0x06u: return RdnaOpcode::SCmpGeI32; case 0x07u: return RdnaOpcode::SCmpLtI32; case 0x08u: return RdnaOpcode::SCmpLeI32; case 0x09u: return RdnaOpcode::SCmpEqU32; case 0x0au: return RdnaOpcode::SCmpLgU32; case 0x0bu: return RdnaOpcode::SCmpGtU32; case 0x0cu: return RdnaOpcode::SCmpGeU32; case 0x0du: return RdnaOpcode::SCmpLtU32; case 0x0eu: return RdnaOpcode::SCmpLeU32; case 0x0fu: return RdnaOpcode::SAddI32; case 0x10u: return RdnaOpcode::SMulkI32; case 0x12u: return RdnaOpcode::SGetregB32; case 0x13u: return RdnaOpcode::SSetregB32; case 0x15u: return RdnaOpcode::SSetregImm32B32; case 0x17u: return RdnaOpcode::SWaitcnt; case 0x18u: return RdnaOpcode::SWaitcnt; case 0x19u: return RdnaOpcode::SWaitcnt; case 0x1au: return RdnaOpcode::SWaitcnt; case 0x1bu: return RdnaOpcode::SSubvectorLoopBegin; case 0x1cu: return RdnaOpcode::SSubvectorLoopEnd; default: throw std::invalid_argument("unsupported SOPK opcode " + std::to_string(opcode)); } } RdnaOpcode decodeSoppOpcode(std::uint32_t opcode) { switch (opcode) { case 0x00u: return RdnaOpcode::SNop; case 0x01u: return RdnaOpcode::SEndpgm; case 0x02u: return RdnaOpcode::SBranch; case 0x03u: return RdnaOpcode::SWakeup; case 0x04u: return RdnaOpcode::SCbranchScc0; case 0x05u: return RdnaOpcode::SCbranchScc1; case 0x06u: return RdnaOpcode::SCbranchVccz; case 0x07u: return RdnaOpcode::SCbranchVccnz; case 0x08u: return RdnaOpcode::SCbranchExecz; case 0x09u: return RdnaOpcode::SCbranchExecnz; case 0x0au: return RdnaOpcode::SBarrier; case 0x0bu: return RdnaOpcode::SEndpgm; case 0x0cu: return RdnaOpcode::SWaitcnt; case 0x0eu: return RdnaOpcode::SSleep; case 0x0fu: return RdnaOpcode::SSetprio; case 0x10u: return RdnaOpcode::SSendmsg; case 0x12u: return RdnaOpcode::STrap; case 0x13u: return RdnaOpcode::SIcacheInv; case 0x14u: return RdnaOpcode::SIncperflevel; case 0x15u: return RdnaOpcode::SDecperflevel; case 0x16u: return RdnaOpcode::STtracedata; case 0x17u: case 0x18u: case 0x19u: case 0x1au: return RdnaOpcode::SCbranchCdbg; case 0x1bu: case 0x1eu: return RdnaOpcode::SEndpgm; case 0x20u: return RdnaOpcode::SInstPrefetch; case 0x21u: return RdnaOpcode::SClause; case 0x22u: return RdnaOpcode::SWaitIdle; case 0x23u: return RdnaOpcode::SWaitcntDepctr; case 0x24u: return RdnaOpcode::SRoundMode; case 0x25u: return RdnaOpcode::SDenormMode; case 0x28u: return RdnaOpcode::STtracedata; default: throw std::invalid_argument("unsupported SOPP opcode " + std::to_string(opcode)); } } void decodeScalarBinarySources(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex, RdnaInstruction& instruction, std::uint32_t scalarSource0, std::uint32_t scalarSource1) { instruction.source0 = DecodeRdnaScalarSource(scalarSource0, programCounter); instruction.source1 = DecodeRdnaScalarSource(scalarSource1, programCounter); instruction.sourceCount = 2; ReadRdnaLiteralOperands(code, wordIndex, instruction); } bool isSoppWaitOpcode(RdnaOpcode opcode) { return opcode == RdnaOpcode::SNop || opcode == RdnaOpcode::SWaitcnt || opcode == RdnaOpcode::SWaitcntDepctr || opcode == RdnaOpcode::SSleep || opcode == RdnaOpcode::SSetprio || opcode == RdnaOpcode::SSendmsg || opcode == RdnaOpcode::STrap || opcode == RdnaOpcode::STtracedata || opcode == RdnaOpcode::SInstPrefetch || opcode == RdnaOpcode::SClause || opcode == RdnaOpcode::SCbranchCdbg || opcode == RdnaOpcode::SIcacheInv || opcode == RdnaOpcode::SIncperflevel || opcode == RdnaOpcode::SDecperflevel || opcode == RdnaOpcode::SWaitIdle || opcode == RdnaOpcode::SRoundMode || opcode == RdnaOpcode::SDenormMode; } std::uint32_t scalarDestinationDwordCount(RdnaOpcode opcode) { switch (opcode) { case RdnaOpcode::SMovB64: case RdnaOpcode::SCmovB64: case RdnaOpcode::SNotB64: case RdnaOpcode::SBrevB64: case RdnaOpcode::SAshrI64: case RdnaOpcode::SWqmB64: case RdnaOpcode::SBitset0B64: case RdnaOpcode::SBitset1B64: case RdnaOpcode::SGetpcB64: case RdnaOpcode::SAndSaveexecB64: case RdnaOpcode::SOrSaveexecB64: case RdnaOpcode::SXorSaveexecB64: case RdnaOpcode::SAndn2SaveexecB64: case RdnaOpcode::SOrn2SaveexecB64: case RdnaOpcode::SNandSaveexecB64: case RdnaOpcode::SNorSaveexecB64: case RdnaOpcode::SXnorSaveexecB64: case RdnaOpcode::SOrn1SaveexecB64: case RdnaOpcode::SAndn1WrexecB64: case RdnaOpcode::SAndn2WrexecB64: case RdnaOpcode::SQuadmaskB64: case RdnaOpcode::SMovrelsB64: case RdnaOpcode::SMovreldB64: case RdnaOpcode::SAndn1SaveexecB64: case RdnaOpcode::SBitreplicateB64B32: case RdnaOpcode::SCselectB64: case RdnaOpcode::SAndB64: case RdnaOpcode::SOrB64: case RdnaOpcode::SXorB64: case RdnaOpcode::SAndn2B64: case RdnaOpcode::SOrn2B64: case RdnaOpcode::SNandB64: case RdnaOpcode::SNorB64: case RdnaOpcode::SXnorB64: case RdnaOpcode::SBfeI64: case RdnaOpcode::SLshlB64: case RdnaOpcode::SLshrB64: case RdnaOpcode::SBfmB64: case RdnaOpcode::SBfeU64: return 2u; default: return 1u; } } } RdnaInstruction DecodeRdnaScalarOp(std::span code, std::uint32_t wordIndex) { if (wordIndex >= code.size()) { throw std::out_of_range("word index is out of the code span bounds"); } const std::uint32_t word = code[wordIndex]; if ((word & 0xc0000000u) != 0x80000000u) { throw std::invalid_argument("word at the given index is not a scalar instruction"); } const std::uint32_t programCounter = wordIndex * static_cast(sizeof(std::uint32_t)); const std::uint32_t subOpcode = (word >> 23u) & 0x7fu; if (subOpcode == 0x7du) { return DecodeRdnaSop1(programCounter, code, wordIndex); } if (subOpcode == 0x7eu) { return DecodeRdnaSopc(programCounter, code, wordIndex); } if (subOpcode == 0x7fu) { return DecodeRdnaSopp(programCounter, code, wordIndex); } if (subOpcode >= 0x60u) { return DecodeRdnaSopk(programCounter, code, wordIndex); } return DecodeRdnaSop2(programCounter, code, wordIndex); } RdnaInstruction DecodeRdnaSop1(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex) { const std::uint32_t word = code[wordIndex]; const std::uint32_t opcode = (word >> 8u) & 0xffu; const std::uint32_t scalarSource0 = word & 0xffu; const std::uint32_t scalarDestination = (word >> 16u) & 0x7fu; RdnaInstruction instruction; instruction.programCounter = programCounter; instruction.family = RdnaInstructionFamily::SOP1; instruction.opcodeId = opcode; instruction.op = opcode == 0x21u && scalarDestination == 125u ? RdnaOpcode::SSetpcB64 : decodeSop1Opcode(opcode); instruction.dataDwordCount = scalarDestinationDwordCount(instruction.op); SetRdnaRawWords(instruction, code, wordIndex, 1); if (instruction.op == RdnaOpcode::SGetpcB64) { instruction.sourceCount = 0; instruction.destination = DecodeRdnaScalarDestination(scalarDestination, programCounter); return instruction; } if (instruction.op == RdnaOpcode::SSetpcB64) { instruction.sourceCount = 1; instruction.destination.kind = RdnaOperandKind::Null; instruction.source0 = DecodeRdnaScalarSource(scalarSource0, programCounter); ReadRdnaLiteralOperands(code, wordIndex, instruction); return instruction; } instruction.source0 = DecodeRdnaScalarSource(scalarSource0, programCounter); instruction.destination = DecodeRdnaScalarDestination(scalarDestination, programCounter); instruction.sourceCount = 1; ReadRdnaLiteralOperands(code, wordIndex, instruction); return instruction; } RdnaInstruction DecodeRdnaSop2(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex) { const std::uint32_t word = code[wordIndex]; const std::uint32_t opcode = (word >> 23u) & 0x7fu; const std::uint32_t scalarSource1 = (word >> 8u) & 0xffu; const std::uint32_t scalarSource0 = word & 0xffu; const std::uint32_t scalarDestination = (word >> 16u) & 0x7fu; RdnaInstruction instruction; instruction.programCounter = programCounter; instruction.family = RdnaInstructionFamily::SOP2; instruction.opcodeId = opcode; instruction.op = decodeSop2Opcode(opcode); instruction.dataDwordCount = scalarDestinationDwordCount(instruction.op); SetRdnaRawWords(instruction, code, wordIndex, 1); instruction.destination = DecodeRdnaScalarDestination(scalarDestination, programCounter); decodeScalarBinarySources(programCounter, code, wordIndex, instruction, scalarSource0, scalarSource1); return instruction; } RdnaInstruction DecodeRdnaSopk(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex) { const std::uint32_t word = code[wordIndex]; const std::uint32_t opcode = (word >> 23u) & 0x1fu; const std::uint32_t scalarRegister = (word >> 16u) & 0x7fu; const std::int32_t immediate = (opcode >= 0x09u && opcode <= 0x0eu) ? static_cast(word & 0xffffu) : static_cast(static_cast(word & 0xffffu)); RdnaInstruction instruction; instruction.programCounter = programCounter; instruction.family = RdnaInstructionFamily::SOPK; instruction.opcodeId = opcode; instruction.op = decodeSopkOpcode(opcode); instruction.source0.kind = RdnaOperandKind::IntegerInlineConstant; instruction.source0.signedVal = immediate; instruction.source0.value = static_cast(immediate); instruction.sourceCount = 1; SetRdnaRawWords(instruction, code, wordIndex, 1); if (instruction.op == RdnaOpcode::SVersion) { instruction.destination.kind = RdnaOperandKind::Null; instruction.sourceCount = 0; return instruction; } if (instruction.op == RdnaOpcode::SSetregImm32B32) { instruction.destination.kind = RdnaOperandKind::Null; instruction.source1 = instruction.source0; instruction.source0 = DecodeRdnaScalarSource(0xffu, programCounter); instruction.sourceCount = 2; ReadRdnaLiteralOperands(code, wordIndex, instruction); return instruction; } if (instruction.op == RdnaOpcode::SMovkI32 || instruction.op == RdnaOpcode::SCmovkI32) { instruction.destination = DecodeRdnaScalarDestination(scalarRegister, programCounter); return instruction; } if (instruction.op == RdnaOpcode::SSubvectorLoopBegin || instruction.op == RdnaOpcode::SSubvectorLoopEnd) { instruction.destination = DecodeRdnaScalarDestination(scalarRegister, programCounter); instruction.branchTarget = programCounter + 4u + static_cast(immediate * 4); return instruction; } if (instruction.op == RdnaOpcode::SWaitcnt) { const std::uint32_t waitcnt = word & 0xffffu; instruction.destination.kind = RdnaOperandKind::Null; instruction.source0.signedVal = static_cast(waitcnt); instruction.source0.value = waitcnt; instruction.sourceCount = 1; return instruction; } if (instruction.op == RdnaOpcode::SGetregB32) { instruction.destination = DecodeRdnaScalarDestination(scalarRegister, programCounter); instruction.source0.value = word & 0xffffu; return instruction; } if (instruction.op == RdnaOpcode::SSetregB32) { instruction.destination.kind = RdnaOperandKind::Null; instruction.source1.kind = RdnaOperandKind::LiteralConstant; instruction.source1.value = word & 0xffffu; instruction.source1.signedVal = immediate; instruction.sourceCount = 2; instruction.source0 = DecodeRdnaScalarSource(scalarRegister, programCounter); return instruction; } instruction.source1 = instruction.source0; instruction.source0 = DecodeRdnaScalarSource(scalarRegister, programCounter); if (instruction.op == RdnaOpcode::SAddI32 || instruction.op == RdnaOpcode::SMulkI32) { instruction.sourceCount = 2; instruction.destination = DecodeRdnaScalarDestination(scalarRegister, programCounter); return instruction; } instruction.destination.kind = RdnaOperandKind::Scc; instruction.sourceCount = 2; return instruction; } RdnaInstruction DecodeRdnaSopc(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex) { const std::uint32_t word = code[wordIndex]; const std::uint32_t scalarSource1 = (word >> 8u) & 0xffu; const std::uint32_t scalarSource0 = word & 0xffu; const std::uint32_t opcode = (word >> 16u) & 0x7fu; RdnaInstruction instruction; instruction.programCounter = programCounter; instruction.family = RdnaInstructionFamily::SOPC; instruction.opcodeId = opcode; instruction.op = decodeSopcOpcode(opcode); instruction.destination.kind = RdnaOperandKind::Scc; SetRdnaRawWords(instruction, code, wordIndex, 1); decodeScalarBinarySources(programCounter, code, wordIndex, instruction, scalarSource0, scalarSource1); return instruction; } RdnaInstruction DecodeRdnaSopp(std::uint32_t programCounter, std::span code, std::uint32_t wordIndex) { const std::uint32_t word = code[wordIndex]; const std::uint32_t opcode = (word >> 16u) & 0x7fu; const std::uint32_t simm = word & 0xffffu; RdnaInstruction instruction; instruction.programCounter = programCounter; instruction.family = RdnaInstructionFamily::SOPP; instruction.opcodeId = opcode; instruction.op = decodeSoppOpcode(opcode); instruction.source0.kind = RdnaOperandKind::LiteralConstant; instruction.source0.value = instruction.op == RdnaOpcode::STrap ? simm & 0xffu : simm; instruction.source0.signedVal = instruction.op == RdnaOpcode::STrap ? static_cast(instruction.source0.value) : static_cast(static_cast(simm)); instruction.sourceCount = isSoppWaitOpcode(instruction.op) ? 1u : 0u; const std::int32_t branchOffset = static_cast(static_cast(simm)) * 4; instruction.branchTarget = programCounter + 4u + static_cast(branchOffset); SetRdnaRawWords(instruction, code, wordIndex, 1); return instruction; } }