shader: support DS_WRITE_B8_D16_HI (#794)

Decode GFX10 DS opcode 0xa0 as DS_WRITE_B8_D16_HI (next to
DS_WRITE_B16_D16_HI at 0xa1) and lower it through the existing 8-bit
shared-memory write. The stored byte is bits 23:16 of the data VGPR,
selected with SDWA BYTE_2 on src1.

Add captured-instruction decode coverage (from GTA V, PPSA04264) and a
runtime regression that writes one byte of a distinctive source value
into a pre-filled LDS dword.
This commit is contained in:
Deniz ŞAHİN
2026-09-23 23:44:39 +03:00
committed by GitHub
parent 569ec04d1a
commit fc86509aac
6 changed files with 60 additions and 1 deletions
@@ -107,6 +107,7 @@ constexpr MemoryOpcodeInfo DS_OPCODE_LIST[] = {
{0x4du, Opcode::DS_WRITE_B64, 2, 32}, {0x4eu, Opcode::DS_WRITE2_B64, 4, 32},
{0x4fu, Opcode::DS_WRITE2ST64_B64, 4, 32}, {0x76u, Opcode::DS_READ_B64, 2, 32},
{0x77u, Opcode::DS_READ2_B64, 4, 32}, {0x78u, Opcode::DS_READ2ST64_B64, 4, 32},
{0xa0u, Opcode::DS_WRITE_B8_D16_HI, 1, 8},
{0xa1u, Opcode::DS_WRITE_B16_D16_HI, 1, 16},
{0xa6u, Opcode::DS_READ_U16_D16, 1, 16},
{0xa7u, Opcode::DS_READ_U16_D16_HI, 1, 16},
@@ -147,6 +148,7 @@ bool IsDsWriteOpcode(Opcode opcode) {
switch (opcode) {
case Opcode::DS_WRITE_B8:
case Opcode::DS_WRITE_B16:
case Opcode::DS_WRITE_B8_D16_HI:
case Opcode::DS_WRITE_B16_D16_HI:
case Opcode::DS_WRITE2_B32:
case Opcode::DS_WRITE2ST64_B32:
@@ -429,7 +431,9 @@ void DecodeDs(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index,
}
DecodeVectorGpr(addr, inst.src0);
DecodeVectorGpr(data0, inst.src1);
if (inst.opcode == Opcode::DS_WRITE_B16_D16_HI) {
if (inst.opcode == Opcode::DS_WRITE_B8_D16_HI) {
inst.src1.sdwa_sel = 2u;
} else if (inst.opcode == Opcode::DS_WRITE_B16_D16_HI) {
inst.src1.sdwa_sel = 5u;
}
DecodeVectorGpr(data1, inst.src2);
@@ -694,6 +694,7 @@ std::string InstructionToString(const Instruction& inst) {
case Opcode::DS_READ_B128:
case Opcode::DS_WRITE_B8:
case Opcode::DS_WRITE_B16:
case Opcode::DS_WRITE_B8_D16_HI:
case Opcode::DS_WRITE_B16_D16_HI:
case Opcode::DS_WRITE2_B32:
case Opcode::DS_WRITE2ST64_B32:
@@ -541,6 +541,7 @@ enum class Opcode {
DS_READ_B128,
DS_WRITE_B8,
DS_WRITE_B16,
DS_WRITE_B8_D16_HI,
DS_WRITE_B16_D16_HI,
DS_WRITE2_B32,
DS_WRITE2ST64_B32,
@@ -235,6 +235,7 @@ Decoder::Operand MemorySourceAt(const Decoder::Instruction& decoded, uint32_t in
return index == 0u ? decoded.src1 : index == 1u ? decoded.src0 : decoded.src2;
case Decoder::Opcode::DS_WRITE_B8:
case Decoder::Opcode::DS_WRITE_B16:
case Decoder::Opcode::DS_WRITE_B8_D16_HI:
case Decoder::Opcode::DS_WRITE_B16_D16_HI:
case Decoder::Opcode::DS_WRITE_B32:
case Decoder::Opcode::DS_WRITE_B64:
@@ -1076,6 +1077,7 @@ bool Translator::EmitMemory(const Decoder::Instruction& inst) {
case Decoder::Opcode::DS_WRITE2ST64_B64: return DS_WRITE2(inst);
case Decoder::Opcode::DS_WRITE_B8:
case Decoder::Opcode::DS_WRITE_B16:
case Decoder::Opcode::DS_WRITE_B8_D16_HI:
case Decoder::Opcode::DS_WRITE_B16_D16_HI:
case Decoder::Opcode::DS_WRITE_B32:
case Decoder::Opcode::DS_WRITE_B64: