mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 04:46:56 +02:00
shader: decode S_FLBIT_I32 and S_FLBIT_I32_I64 with a 4-op signed leading-bit search
This commit is contained in:
@@ -57,6 +57,8 @@ constexpr OpcodeMap SOP1_OPCODE_LIST[] = {
|
||||
{0x14u, Opcode::S_FF1_I32_B64},
|
||||
{0x15u, Opcode::S_FLBIT_I32_B32},
|
||||
{0x16u, Opcode::S_FLBIT_I32_B64},
|
||||
{0x17u, Opcode::S_FLBIT_I32},
|
||||
{0x18u, Opcode::S_FLBIT_I32_I64},
|
||||
{0x19u, Opcode::S_SEXT_I32_I8},
|
||||
{0x1au, Opcode::S_SEXT_I32_I16},
|
||||
{0x1bu, Opcode::S_BITSET0_B32},
|
||||
|
||||
@@ -60,6 +60,8 @@ enum class Opcode {
|
||||
S_FF1_I32_B64,
|
||||
S_FLBIT_I32_B32,
|
||||
S_FLBIT_I32_B64,
|
||||
S_FLBIT_I32,
|
||||
S_FLBIT_I32_I64,
|
||||
S_BITREPLICATE_B64_B32,
|
||||
S_QUADMASK_B64,
|
||||
S_GETPC_B64,
|
||||
|
||||
@@ -221,8 +221,17 @@ void Translator::V_XOR3_B32(const Decoder::Instruction& inst) {
|
||||
WriteOperand(DestinationOperand(inst), result);
|
||||
}
|
||||
|
||||
void Translator::S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb) {
|
||||
void Translator::S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb,
|
||||
bool sign) {
|
||||
auto source = ReadU32Pair(inst.src0);
|
||||
if (sign) {
|
||||
// A signed source sign-extends a literal; then bits equal to the sign become zero.
|
||||
if (inst.src0.kind == Decoder::OperandKind::LiteralConstant) {
|
||||
source[1] = ir.ShiftRightArithmetic(source[0], IR::U32(IR::Value(31u)));
|
||||
}
|
||||
const auto mask = ir.ShiftRightArithmetic(source[1], IR::U32(IR::Value(31u)));
|
||||
source = {ir.BitwiseXor(source[0], mask), ir.BitwiseXor(source[1], mask)};
|
||||
}
|
||||
for (auto& word: source) {
|
||||
word = find_zero ? ir.BitwiseNot(word) : word;
|
||||
}
|
||||
@@ -240,12 +249,19 @@ void Translator::S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero,
|
||||
|
||||
void Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) {
|
||||
const auto source = ReadU32(inst.src0);
|
||||
const auto value = sign ? ir.BitwiseXor(
|
||||
source, ir.ShiftRightArithmetic(source, IR::U32(IR::Value(31u))))
|
||||
: source;
|
||||
const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb32, {value}));
|
||||
if (sign) {
|
||||
// Bits equal to the sign become zero; FindILsb of the reversed bits is ~0 when none.
|
||||
const auto bits =
|
||||
ir.BitwiseXor(source, ir.ShiftRightArithmetic(source, IR::U32(IR::Value(31u))));
|
||||
const auto reversed = ir.Emit(IR::ValueOpcode::BitReverse32, {bits});
|
||||
WriteOperand(DestinationOperand(inst),
|
||||
IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {reversed})));
|
||||
return;
|
||||
}
|
||||
// ResourceTracking matches this 31 - FindUMsb32 form.
|
||||
const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb32, {source}));
|
||||
const auto position = ir.ISub(IR::U32(IR::Value(31u)), msb);
|
||||
const auto result = ir.Select(ir.INotEqual(value, IR::U32(IR::Value(0u))), position,
|
||||
const auto result = ir.Select(ir.INotEqual(source, IR::U32(IR::Value(0u))), position,
|
||||
IR::U32(IR::Value(0xffffffffu)));
|
||||
WriteOperand(DestinationOperand(inst), result);
|
||||
}
|
||||
|
||||
@@ -238,10 +238,12 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
|
||||
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseOr32, false, true, true);
|
||||
case O::S_XNOR_B32:
|
||||
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseXor32, false, true, true);
|
||||
case O::S_FF0_I32_B64: return S_FF_I32_B64(inst, true, false);
|
||||
case O::S_FF1_I32_B64: return S_FF_I32_B64(inst, false, false);
|
||||
case O::S_FF0_I32_B64: return S_FF_I32_B64(inst, true, false, false);
|
||||
case O::S_FF1_I32_B64: return S_FF_I32_B64(inst, false, false, false);
|
||||
case O::S_FLBIT_I32_B32: return V_FFBH_32(inst, false);
|
||||
case O::S_FLBIT_I32_B64: return S_FF_I32_B64(inst, false, true);
|
||||
case O::S_FLBIT_I32_B64: return S_FF_I32_B64(inst, false, true, false);
|
||||
case O::S_FLBIT_I32: return V_FFBH_32(inst, true);
|
||||
case O::S_FLBIT_I32_I64: return S_FF_I32_B64(inst, false, true, true);
|
||||
|
||||
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
|
||||
case O::S_BITSET1_B32: return S_BITSET_B32(inst, true);
|
||||
|
||||
@@ -182,7 +182,7 @@ private:
|
||||
void V_AND_OR_B32(const Decoder::Instruction& inst);
|
||||
void V_OR3_B32(const Decoder::Instruction& inst);
|
||||
void V_XOR3_B32(const Decoder::Instruction& inst);
|
||||
void S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb);
|
||||
void S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb, bool sign);
|
||||
void V_FFBH_32(const Decoder::Instruction& inst, bool sign);
|
||||
void Integer24(const Decoder::Instruction& inst, bool sign, bool addend);
|
||||
void V_MAD_U64_U32(const Decoder::Instruction& inst);
|
||||
|
||||
@@ -23119,6 +23119,43 @@ TestCase ScalarFlbitI32B32Gpu() {
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarFlbitSignedGpu() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
// RDNA2's S_FLBIT_I32 examples; 64-bit signs come from the high word.
|
||||
constexpr u32 values32[] = {0x00000000u, 0x0000ccccu, 0xffff3333u,
|
||||
0x7fffffffu, 0x80000000u, 0xffffffffu};
|
||||
constexpr uint64_t values64[] = {0x0000000000000000ull, 0xffffffffffffffffull,
|
||||
0x0000000100000000ull, 0xffffffff7fffffffull,
|
||||
0xc000000000000000ull, 0x0000000000008000ull};
|
||||
std::vector<u32> code;
|
||||
u32 out = 0;
|
||||
for (const auto value : values32) {
|
||||
AppendSMovLiteral(&code, 0, value);
|
||||
code.push_back(EncodeSop1(0x17, 20, 0));
|
||||
AppendStoreSgpr(&code, 20, out++);
|
||||
}
|
||||
for (const auto value : values64) {
|
||||
AppendSMovLiteral(&code, 0, static_cast<u32>(value));
|
||||
AppendSMovLiteral(&code, 1, static_cast<u32>(value >> 32u));
|
||||
code.push_back(EncodeSop1(0x18, 20, 0));
|
||||
AppendStoreSgpr(&code, 20, out++);
|
||||
}
|
||||
// A signed 64-bit source sign-extends a literal.
|
||||
code.push_back(EncodeSop1(0x18, 20, 255));
|
||||
code.push_back(0x80000000u);
|
||||
AppendStoreSgpr(&code, 20, out);
|
||||
AppendEnd(&code);
|
||||
|
||||
return {"ScalarFlbitSignedGpu",
|
||||
code,
|
||||
{},
|
||||
{0xffffffffu, 16, 16, 1, 1, 0xffffffffu, 0xffffffffu, 0xffffffffu,
|
||||
31, 32, 2, 48, 33},
|
||||
{O::S_MOV_B32, O::S_FLBIT_I32, O::S_FLBIT_I32_I64, O::V_MOV_B32,
|
||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarSaveExecOps() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -43766,6 +43803,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(ScalarQuadmaskB64);
|
||||
AddCase(ScalarFlbitI32B64Gpu);
|
||||
AddCase(ScalarFlbitI32B32Gpu);
|
||||
AddCase(ScalarFlbitSignedGpu);
|
||||
AddCase(ScalarSaveExecOps);
|
||||
AddCase(ScalarOrn2SaveexecUsesSourceOrNotExec);
|
||||
cases.push_back(ScalarOrn2SaveexecB32(32, 32));
|
||||
@@ -50070,6 +50108,7 @@ int main(int argc, char **argv) {
|
||||
RunCase(&vulkan, VectorCompareF16Ops());
|
||||
RunCase(&vulkan, ScalarBrevB64OperandsAndMasks(32));
|
||||
RunCase(&vulkan, ScalarBrevB64OperandsAndMasks(64));
|
||||
RunCase(&vulkan, ScalarFlbitSignedGpu());
|
||||
for (bool add : {false, true}) {
|
||||
RunCase(&vulkan, DsAtomic64Bounds(add));
|
||||
for (u32 wave_size : {32, 64}) {
|
||||
|
||||
Reference in New Issue
Block a user