summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp')
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
index 7564aeeb2..e444dcd4f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp
@@ -7,6 +7,15 @@
7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" 7#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
8 8
9namespace Shader::Maxwell { 9namespace Shader::Maxwell {
10namespace {
11[[nodiscard]] IR::U32 CbufLowerBits(IR::IREmitter& ir, bool unaligned, const IR::U32& binding,
12 u32 offset) {
13 if (unaligned) {
14 return ir.Imm32(0);
15 }
16 return ir.GetCbuf(binding, IR::U32{IR::Value{offset}});
17}
18} // Anonymous namespace
10 19
11IR::U32 TranslatorVisitor::X(IR::Reg reg) { 20IR::U32 TranslatorVisitor::X(IR::Reg reg) {
12 return ir.GetReg(reg); 21 return ir.GetReg(reg);
@@ -56,6 +65,18 @@ IR::F32 TranslatorVisitor::GetFloatReg39(u64 insn) {
56 return ir.BitCast<IR::F32>(GetReg39(insn)); 65 return ir.BitCast<IR::F32>(GetReg39(insn));
57} 66}
58 67
68IR::F64 TranslatorVisitor::GetDoubleReg20(u64 insn) {
69 union {
70 u64 raw;
71 BitField<20, 8, IR::Reg> src;
72 } const index{insn};
73 const IR::Reg reg{index.src};
74 if (!IR::IsAligned(reg, 2)) {
75 throw NotImplementedException("Unaligned source register {}", reg);
76 }
77 return ir.PackDouble2x32(ir.CompositeConstruct(X(reg), X(reg + 1)));
78}
79
59static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) { 80static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) {
60 union { 81 union {
61 u64 raw; 82 u64 raw;
@@ -75,15 +96,31 @@ static std::pair<IR::U32, IR::U32> CbufAddr(u64 insn) {
75} 96}
76 97
77IR::U32 TranslatorVisitor::GetCbuf(u64 insn) { 98IR::U32 TranslatorVisitor::GetCbuf(u64 insn) {
78 const auto[binding, byte_offset]{CbufAddr(insn)}; 99 const auto [binding, byte_offset]{CbufAddr(insn)};
79 return ir.GetCbuf(binding, byte_offset); 100 return ir.GetCbuf(binding, byte_offset);
80} 101}
81 102
82IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) { 103IR::F32 TranslatorVisitor::GetFloatCbuf(u64 insn) {
83 const auto[binding, byte_offset]{CbufAddr(insn)}; 104 const auto [binding, byte_offset]{CbufAddr(insn)};
84 return ir.GetFloatCbuf(binding, byte_offset); 105 return ir.GetFloatCbuf(binding, byte_offset);
85} 106}
86 107
108IR::F64 TranslatorVisitor::GetDoubleCbuf(u64 insn) {
109 union {
110 u64 raw;
111 BitField<20, 1, u64> unaligned;
112 } const cbuf{insn};
113
114 const auto [binding, offset_value]{CbufAddr(insn)};
115 const bool unaligned{cbuf.unaligned != 0};
116 const u32 offset{offset_value.U32()};
117 const IR::Value addr{unaligned ? offset | 4 : (offset & ~7) | 4};
118
119 const IR::U32 value{ir.GetCbuf(binding, IR::U32{addr})};
120 const IR::U32 lower_bits{CbufLowerBits(ir, unaligned, binding, offset)};
121 return ir.PackDouble2x32(ir.CompositeConstruct(lower_bits, value));
122}
123
87IR::U32 TranslatorVisitor::GetImm20(u64 insn) { 124IR::U32 TranslatorVisitor::GetImm20(u64 insn) {
88 union { 125 union {
89 u64 raw; 126 u64 raw;
@@ -110,6 +147,17 @@ IR::F32 TranslatorVisitor::GetFloatImm20(u64 insn) {
110 return ir.Imm32(Common::BitCast<f32>(value | sign_bit)); 147 return ir.Imm32(Common::BitCast<f32>(value | sign_bit));
111} 148}
112 149
150IR::F64 TranslatorVisitor::GetDoubleImm20(u64 insn) {
151 union {
152 u64 raw;
153 BitField<20, 19, u64> value;
154 BitField<56, 1, u64> is_negative;
155 } const imm{insn};
156 const u64 sign_bit{imm.is_negative != 0 ? (1ULL << 63) : 0};
157 const u64 value{imm.value << 44};
158 return ir.Imm64(Common::BitCast<f64>(value | sign_bit));
159}
160
113IR::U32 TranslatorVisitor::GetImm32(u64 insn) { 161IR::U32 TranslatorVisitor::GetImm32(u64 insn) {
114 union { 162 union {
115 u64 raw; 163 u64 raw;