mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-19 18:36:53 +02:00
shader: read float inline constants on 64-bit operands as f64 bits (#1576)
A float inline constant (240-248) read by a 64-bit operand is the f64 bit
pattern for integer B64 opcodes too: AMD's compilers emit
v_lshrrev_b64 v[4:5], v0, 1.0 for 0x3ff0000000000000 >> lane. ReadU32Pair
returned {f32 bits, 0}, so only F64-typed reads had the right value.
Based on TheCruZ's 284deab28 (closed #1219).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -233,13 +233,6 @@ IR::Value Translator::ReadOperand(const Decoder::Operand& operand, IR::Type type
|
||||
if (type == IR::Type::F64) {
|
||||
if (operand.kind == Decoder::OperandKind::LiteralConstant) {
|
||||
pair = {IR::U32(IR::Value(0u)), IR::U32(IR::Value(operand.value))};
|
||||
} else if (operand.kind == Decoder::OperandKind::FloatInlineConstant) {
|
||||
const auto bits = operand.value == 0x3e22f983u
|
||||
? 0x3fc45f306dc9c882ull
|
||||
: std::bit_cast<uint64_t>(static_cast<double>(
|
||||
std::bit_cast<float>(operand.value)));
|
||||
pair = {IR::U32(IR::Value(static_cast<uint32_t>(bits))),
|
||||
IR::U32(IR::Value(static_cast<uint32_t>(bits >> 32u)))};
|
||||
}
|
||||
if (operand.absolute) {
|
||||
pair[1] = ir.BitwiseAnd(pair[1], IR::U32(IR::Value(0x7fffffffu)));
|
||||
@@ -488,6 +481,14 @@ std::array<IR::U32, 2> Translator::ReadU32Pair(const Decoder::Operand& operand)
|
||||
if (operand.kind == Decoder::OperandKind::VccLo) {
|
||||
return {ir.GetVccLo(), ir.GetVccHi()};
|
||||
}
|
||||
if (operand.kind == Decoder::OperandKind::FloatInlineConstant) {
|
||||
const auto bits =
|
||||
operand.value == 0x3e22f983u
|
||||
? 0x3fc45f306dc9c882ull
|
||||
: std::bit_cast<uint64_t>(static_cast<double>(std::bit_cast<float>(operand.value)));
|
||||
return {IR::U32(IR::Value(static_cast<uint32_t>(bits))),
|
||||
IR::U32(IR::Value(static_cast<uint32_t>(bits >> 32u)))};
|
||||
}
|
||||
const auto low = ApplyBitSourceModifiers(operand, ReadRawU32(operand));
|
||||
IR::U32 high(IR::Value(0u));
|
||||
if (operand.kind == Decoder::OperandKind::Sgpr || operand.kind == Decoder::OperandKind::Vgpr) {
|
||||
|
||||
@@ -25192,6 +25192,34 @@ TestCase VectorCarryAndBitCountOps() {
|
||||
O::S_ENDPGM}};
|
||||
}
|
||||
|
||||
TestCase ScalarVector64BitFloatInlineConstants() {
|
||||
using O = ShaderOpcode;
|
||||
std::vector<u32> code;
|
||||
code.push_back(EncodeSop1(0x04, 40, 242));
|
||||
code.push_back(EncodeSop2(0x11, 42, 240, InlineU32(0)));
|
||||
code.push_back(EncodeSop1(0x04, 44, 248));
|
||||
AppendVop3(&code, 0x300, 2, InlineU32(32), 244);
|
||||
code.push_back(EncodeSMovB32(46, InlineU32(0)));
|
||||
AppendSMovLiteral(&code, 47, 0x3ff00000u);
|
||||
code.push_back(EncodeSopc(0x12, 46, 242));
|
||||
code.push_back(EncodeSMovB32(48, 253));
|
||||
AppendStoreSgprPair(&code, 40, 0);
|
||||
AppendStoreSgprPair(&code, 42, 2);
|
||||
AppendStoreVgpr(&code, 2, 4);
|
||||
AppendStoreVgpr(&code, 3, 5);
|
||||
AppendStoreSgprPair(&code, 44, 6);
|
||||
AppendStoreSgpr(&code, 48, 8);
|
||||
AppendEnd(&code);
|
||||
|
||||
TestCase test;
|
||||
test.name = "ScalarVector64BitFloatInlineConstants";
|
||||
test.code = std::move(code);
|
||||
test.expected = {0u, 0x3ff00000u, 0u, 0x3fe00000u, 0x40000000u, 0u, 0x6dc9c882u, 0x3fc45f30u, 1u};
|
||||
test.opcodes = {O::S_MOV_B64, O::S_OR_B64, O::V_LSHRREV_B64, O::S_MOV_B32, O::S_CMP_EQ_U64,
|
||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
|
||||
return test;
|
||||
}
|
||||
|
||||
TestCase VectorMbcntUsesThreadMask() {
|
||||
using O = ShaderOpcode;
|
||||
|
||||
@@ -42017,6 +42045,7 @@ std::vector<TestCase> MakeCases() {
|
||||
AddCase(VectorBfeI32SignExtendsField);
|
||||
AddCase(VectorAlignByteUsesTwoBitByteOffset);
|
||||
AddCase(VectorCarryAndBitCountOps);
|
||||
AddCase(ScalarVector64BitFloatInlineConstants);
|
||||
AddCase(VectorMbcntUsesThreadMask);
|
||||
AddCase(VectorAddcWritesPerLaneCarryOut);
|
||||
AddCase(VectorAddcUsesPerLaneCarryIn);
|
||||
|
||||
Reference in New Issue
Block a user