summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp
new file mode 100644
index 000000000..f92c0bbd6
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp
@@ -0,0 +1,73 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
+
+namespace Shader::Maxwell {
+namespace {
+void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
+ union {
+ u64 raw;
+ BitField<0, 8, IR::Reg> dest_reg;
+ BitField<8, 8, IR::Reg> op_a;
+ BitField<47, 1, u64> cc;
+ BitField<48, 2, u64> three_for_po;
+ BitField<48, 1, u64> neg_b;
+ BitField<49, 1, u64> neg_a;
+ BitField<39, 5, u64> scale;
+ } const iscadd{insn};
+
+ const bool po{iscadd.three_for_po == 3};
+ IR::U32 op_a{v.X(iscadd.op_a)};
+ if (!po) {
+ // When PO is not present, the bits are interpreted as negation
+ if (iscadd.neg_a != 0) {
+ op_a = v.ir.INeg(op_a);
+ }
+ if (iscadd.neg_b != 0) {
+ op_b = v.ir.INeg(op_b);
+ }
+ }
+ // With the operands already processed, scale A
+ const IR::U32 scale{v.ir.Imm32(static_cast<u32>(iscadd.scale))};
+ const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)};
+
+ IR::U32 result{v.ir.IAdd(scaled_a, op_b)};
+ if (po) {
+ // .PO adds one to the final result
+ result = v.ir.IAdd(result, v.ir.Imm32(1));
+ }
+ v.X(iscadd.dest_reg, result);
+
+ if (iscadd.cc != 0) {
+ throw NotImplementedException("ISCADD CC");
+ }
+}
+
+} // Anonymous namespace
+
+void TranslatorVisitor::ISCADD_reg(u64 insn) {
+ union {
+ u64 raw;
+ BitField<20, 8, IR::Reg> op_b;
+ } const iscadd{insn};
+
+ ISCADD(*this, insn, X(iscadd.op_b));
+}
+
+void TranslatorVisitor::ISCADD_cbuf(u64) {
+ throw NotImplementedException("ISCADD (cbuf)");
+}
+
+void TranslatorVisitor::ISCADD_imm(u64) {
+ throw NotImplementedException("ISCADD (imm)");
+}
+
+void TranslatorVisitor::ISCADD32I(u64) {
+ throw NotImplementedException("ISCADD32I");
+}
+
+} // namespace Shader::Maxwell