summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/CMakeLists.txt2
-rw-r--r--src/shader_recompiler/frontend/maxwell/maxwell.inc4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp25
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h2
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/impl.h7
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation.cpp77
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation_three_input.cpp117
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp24
8 files changed, 227 insertions, 31 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt
index 8a0f73a4d..6506413a8 100644
--- a/src/shader_recompiler/CMakeLists.txt
+++ b/src/shader_recompiler/CMakeLists.txt
@@ -86,6 +86,8 @@ add_library(shader_recompiler STATIC
86 frontend/maxwell/translate/impl/integer_short_multiply_add.cpp 86 frontend/maxwell/translate/impl/integer_short_multiply_add.cpp
87 frontend/maxwell/translate/impl/load_store_attribute.cpp 87 frontend/maxwell/translate/impl/load_store_attribute.cpp
88 frontend/maxwell/translate/impl/load_store_memory.cpp 88 frontend/maxwell/translate/impl/load_store_memory.cpp
89 frontend/maxwell/translate/impl/logic_operation.cpp
90 frontend/maxwell/translate/impl/logic_operation_three_input.cpp
89 frontend/maxwell/translate/impl/move_predicate_to_register.cpp 91 frontend/maxwell/translate/impl/move_predicate_to_register.cpp
90 frontend/maxwell/translate/impl/move_register.cpp 92 frontend/maxwell/translate/impl/move_register.cpp
91 frontend/maxwell/translate/impl/move_special_register.cpp 93 frontend/maxwell/translate/impl/move_special_register.cpp
diff --git a/src/shader_recompiler/frontend/maxwell/maxwell.inc b/src/shader_recompiler/frontend/maxwell/maxwell.inc
index 1515285bf..5d0b91598 100644
--- a/src/shader_recompiler/frontend/maxwell/maxwell.inc
+++ b/src/shader_recompiler/frontend/maxwell/maxwell.inc
@@ -178,8 +178,8 @@ INST(LOP_reg, "LOP (reg)", "0101 1100 0100 0---")
178INST(LOP_cbuf, "LOP (cbuf)", "0100 1100 0100 0---") 178INST(LOP_cbuf, "LOP (cbuf)", "0100 1100 0100 0---")
179INST(LOP_imm, "LOP (imm)", "0011 100- 0100 0---") 179INST(LOP_imm, "LOP (imm)", "0011 100- 0100 0---")
180INST(LOP3_reg, "LOP3 (reg)", "0101 1011 1110 0---") 180INST(LOP3_reg, "LOP3 (reg)", "0101 1011 1110 0---")
181INST(LOP3_cbuf, "LOP3 (cbuf)", "0011 11-- ---- ----") 181INST(LOP3_cbuf, "LOP3 (cbuf)", "0000 001- ---- ----")
182INST(LOP3_imm, "LOP3 (imm)", "0000 001- ---- ----") 182INST(LOP3_imm, "LOP3 (imm)", "0011 11-- ---- ----")
183INST(LOP32I, "LOP32I", "0000 01-- ---- ----") 183INST(LOP32I, "LOP32I", "0000 01-- ---- ----")
184INST(MEMBAR, "MEMBAR", "1110 1111 1001 1---") 184INST(MEMBAR, "MEMBAR", "1110 1111 1001 1---")
185INST(MOV_reg, "MOV (reg)", "0101 1100 1001 1---") 185INST(MOV_reg, "MOV (reg)", "0101 1100 1001 1---")
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp
index 62f825a92..9d4ac2e36 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.cpp
@@ -5,9 +5,8 @@
5#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h" 5#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
6 6
7namespace Shader::Maxwell { 7namespace Shader::Maxwell {
8[[nodiscard]] IR::U1 IntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, 8IR::U1 IntegerCompare(IR::IREmitter& ir, const IR::U32& operand_1, const IR::U32& operand_2,
9 const IR::U32& operand_2, CompareOp compare_op, 9 CompareOp compare_op, bool is_signed) {
10 bool is_signed) {
11 switch (compare_op) { 10 switch (compare_op) {
12 case CompareOp::False: 11 case CompareOp::False:
13 return ir.Imm1(false); 12 return ir.Imm1(false);
@@ -30,8 +29,8 @@ namespace Shader::Maxwell {
30 } 29 }
31} 30}
32 31
33[[nodiscard]] IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, 32IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, const IR::U1& predicate_2,
34 const IR::U1& predicate_2, BooleanOp bop) { 33 BooleanOp bop) {
35 switch (bop) { 34 switch (bop) {
36 case BooleanOp::AND: 35 case BooleanOp::AND:
37 return ir.LogicalAnd(predicate_1, predicate_2); 36 return ir.LogicalAnd(predicate_1, predicate_2);
@@ -43,4 +42,20 @@ namespace Shader::Maxwell {
43 throw NotImplementedException("Invalid bop {}", bop); 42 throw NotImplementedException("Invalid bop {}", bop);
44 } 43 }
45} 44}
45
46IR::U1 PredicateOperation(IR::IREmitter& ir, const IR::U32& result, PredicateOp op) {
47 switch (op) {
48 case PredicateOp::False:
49 return ir.Imm1(false);
50 case PredicateOp::True:
51 return ir.Imm1(true);
52 case PredicateOp::Zero:
53 return ir.IEqual(result, ir.Imm32(0));
54 case PredicateOp::NonZero:
55 return ir.INotEqual(result, ir.Imm32(0));
56 default:
57 throw NotImplementedException("Invalid Predicate operation {}", op);
58 }
59}
60
46} // namespace Shader::Maxwell 61} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
index 61e13fa18..c9ae5c500 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h
@@ -13,4 +13,6 @@ namespace Shader::Maxwell {
13 13
14[[nodiscard]] IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1, 14[[nodiscard]] IR::U1 PredicateCombine(IR::IREmitter& ir, const IR::U1& predicate_1,
15 const IR::U1& predicate_2, BooleanOp bop); 15 const IR::U1& predicate_2, BooleanOp bop);
16
17[[nodiscard]] IR::U1 PredicateOperation(IR::IREmitter& ir, const IR::U32& result, PredicateOp op);
16} // namespace Shader::Maxwell 18} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
index ad09ade7c..c6253c40c 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h
@@ -28,6 +28,13 @@ enum class BooleanOp : u64 {
28 XOR, 28 XOR,
29}; 29};
30 30
31enum class PredicateOp : u64 {
32 False,
33 True,
34 Zero,
35 NonZero,
36};
37
31class TranslatorVisitor { 38class TranslatorVisitor {
32public: 39public:
33 explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {} 40 explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {}
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation.cpp
new file mode 100644
index 000000000..e786a388e
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation.cpp
@@ -0,0 +1,77 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/bit_field.h"
6#include "common/common_types.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9
10namespace Shader::Maxwell {
11namespace {
12enum class LogicalOp : u64 {
13 AND,
14 OR,
15 XOR,
16 PASS_B,
17};
18
19[[nodiscard]] IR::U32 LogicalOperation(IR::IREmitter& ir, const IR::U32& operand_1,
20 const IR::U32& operand_2, LogicalOp op) {
21 switch (op) {
22 case LogicalOp::AND:
23 return ir.BitwiseAnd(operand_1, operand_2);
24 case LogicalOp::OR:
25 return ir.BitwiseOr(operand_1, operand_2);
26 case LogicalOp::XOR:
27 return ir.BitwiseXor(operand_1, operand_2);
28 case LogicalOp::PASS_B:
29 return operand_2;
30 default:
31 throw NotImplementedException("Invalid Logical operation {}", op);
32 }
33}
34
35void LOP(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
36 union {
37 u64 insn;
38 BitField<0, 8, IR::Reg> dest_reg;
39 BitField<8, 8, IR::Reg> src_reg;
40 BitField<39, 1, u64> neg_a;
41 BitField<40, 1, u64> neg_b;
42 BitField<41, 2, LogicalOp> bit_op;
43 BitField<43, 1, u64> x;
44 BitField<44, 2, PredicateOp> pred_op;
45 BitField<48, 3, IR::Pred> pred;
46 } const lop{insn};
47
48 if (lop.x != 0) {
49 throw NotImplementedException("LOP X");
50 }
51 IR::U32 op_a{v.X(lop.src_reg)};
52 if (lop.neg_a != 0) {
53 op_a = v.ir.BitwiseNot(op_a);
54 }
55 if (lop.neg_b != 0) {
56 op_b = v.ir.BitwiseNot(op_b);
57 }
58
59 const IR::U32 result{LogicalOperation(v.ir, op_a, op_b, lop.bit_op)};
60 const IR::U1 pred_result{PredicateOperation(v.ir, result, lop.pred_op)};
61 v.X(lop.dest_reg, result);
62 v.ir.SetPred(lop.pred, pred_result);
63}
64} // Anonymous namespace
65
66void TranslatorVisitor::LOP_reg(u64 insn) {
67 LOP(*this, insn, GetReg20(insn));
68}
69
70void TranslatorVisitor::LOP_cbuf(u64 insn) {
71 LOP(*this, insn, GetCbuf(insn));
72}
73
74void TranslatorVisitor::LOP_imm(u64 insn) {
75 LOP(*this, insn, GetImm20(insn));
76}
77} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation_three_input.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation_three_input.cpp
new file mode 100644
index 000000000..256c47504
--- /dev/null
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/logic_operation_three_input.cpp
@@ -0,0 +1,117 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/bit_field.h"
6#include "common/common_types.h"
7#include "shader_recompiler/frontend/maxwell/translate/impl/common_funcs.h"
8#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
9
10namespace Shader::Maxwell {
11namespace {
12// https://forums.developer.nvidia.com/t/reverse-lut-for-lop3-lut/110651
13// Emulate GPU's LOP3.LUT (three-input logic op with 8-bit truth table)
14IR::U32 ApplyLUT(IR::IREmitter& ir, const IR::U32& a, const IR::U32& b, const IR::U32& c,
15 u64 ttbl) {
16 IR::U32 r{ir.Imm32(0)};
17 const IR::U32 not_a{ir.BitwiseNot(a)};
18 const IR::U32 not_b{ir.BitwiseNot(b)};
19 const IR::U32 not_c{ir.BitwiseNot(c)};
20 if (ttbl & 0x01) {
21 // r |= ~a & ~b & ~c;
22 const auto lhs{ir.BitwiseAnd(not_a, not_b)};
23 const auto rhs{ir.BitwiseAnd(lhs, not_c)};
24 r = ir.BitwiseOr(r, rhs);
25 }
26 if (ttbl & 0x02) {
27 // r |= ~a & ~b & c;
28 const auto lhs{ir.BitwiseAnd(not_a, not_b)};
29 const auto rhs{ir.BitwiseAnd(lhs, c)};
30 r = ir.BitwiseOr(r, rhs);
31 }
32 if (ttbl & 0x04) {
33 // r |= ~a & b & ~c;
34 const auto lhs{ir.BitwiseAnd(not_a, b)};
35 const auto rhs{ir.BitwiseAnd(lhs, not_c)};
36 r = ir.BitwiseOr(r, rhs);
37 }
38 if (ttbl & 0x08) {
39 // r |= ~a & b & c;
40 const auto lhs{ir.BitwiseAnd(not_a, b)};
41 const auto rhs{ir.BitwiseAnd(lhs, c)};
42 r = ir.BitwiseOr(r, rhs);
43 }
44 if (ttbl & 0x10) {
45 // r |= a & ~b & ~c;
46 const auto lhs{ir.BitwiseAnd(a, not_b)};
47 const auto rhs{ir.BitwiseAnd(lhs, not_c)};
48 r = ir.BitwiseOr(r, rhs);
49 }
50 if (ttbl & 0x20) {
51 // r |= a & ~b & c;
52 const auto lhs{ir.BitwiseAnd(a, not_b)};
53 const auto rhs{ir.BitwiseAnd(lhs, c)};
54 r = ir.BitwiseOr(r, rhs);
55 }
56 if (ttbl & 0x40) {
57 // r |= a & b & ~c;
58 const auto lhs{ir.BitwiseAnd(a, b)};
59 const auto rhs{ir.BitwiseAnd(lhs, not_c)};
60 r = ir.BitwiseOr(r, rhs);
61 }
62 if (ttbl & 0x80) {
63 // r |= a & b & c;
64 const auto lhs{ir.BitwiseAnd(a, b)};
65 const auto rhs{ir.BitwiseAnd(lhs, c)};
66 r = ir.BitwiseOr(r, rhs);
67 }
68 return r;
69}
70
71IR::U32 LOP3(TranslatorVisitor& v, u64 insn, const IR::U32& op_b, const IR::U32& op_c, u64 lut) {
72 union {
73 u64 insn;
74 BitField<0, 8, IR::Reg> dest_reg;
75 BitField<8, 8, IR::Reg> src_reg;
76 } const lop3{insn};
77
78 const IR::U32 op_a{v.X(lop3.src_reg)};
79 const IR::U32 result{ApplyLUT(v.ir, op_a, op_b, op_c, lut)};
80 v.X(lop3.dest_reg, result);
81 return result;
82}
83
84u64 GetLut48(u64 insn) {
85 union {
86 u64 raw;
87 BitField<48, 8, u64> lut;
88 } const lut{insn};
89 return lut.lut;
90}
91} // Anonymous namespace
92
93void TranslatorVisitor::LOP3_reg(u64 insn) {
94 union {
95 u64 insn;
96 BitField<28, 8, u64> lut;
97 BitField<38, 1, u64> x;
98 BitField<36, 2, PredicateOp> pred_op;
99 BitField<48, 3, IR::Pred> pred;
100 } const lop3{insn};
101
102 if (lop3.x != 0) {
103 throw NotImplementedException("LOP3 X");
104 }
105 const IR::U32 result{LOP3(*this, insn, GetReg20(insn), GetReg39(insn), lop3.lut)};
106 const IR::U1 pred_result{PredicateOperation(ir, result, lop3.pred_op)};
107 ir.SetPred(lop3.pred, pred_result);
108}
109
110void TranslatorVisitor::LOP3_cbuf(u64 insn) {
111 LOP3(*this, insn, GetCbuf(insn), GetReg39(insn), GetLut48(insn));
112}
113
114void TranslatorVisitor::LOP3_imm(u64 insn) {
115 LOP3(*this, insn, GetImm20(insn), GetReg39(insn), GetLut48(insn));
116}
117} // namespace Shader::Maxwell
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
index c93304a67..a0535f1c2 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
@@ -493,30 +493,6 @@ void TranslatorVisitor::LONGJMP(u64) {
493 ThrowNotImplemented(Opcode::LONGJMP); 493 ThrowNotImplemented(Opcode::LONGJMP);
494} 494}
495 495
496void TranslatorVisitor::LOP_reg(u64) {
497 ThrowNotImplemented(Opcode::LOP_reg);
498}
499
500void TranslatorVisitor::LOP_cbuf(u64) {
501 ThrowNotImplemented(Opcode::LOP_cbuf);
502}
503
504void TranslatorVisitor::LOP_imm(u64) {
505 ThrowNotImplemented(Opcode::LOP_imm);
506}
507
508void TranslatorVisitor::LOP3_reg(u64) {
509 ThrowNotImplemented(Opcode::LOP3_reg);
510}
511
512void TranslatorVisitor::LOP3_cbuf(u64) {
513 ThrowNotImplemented(Opcode::LOP3_cbuf);
514}
515
516void TranslatorVisitor::LOP3_imm(u64) {
517 ThrowNotImplemented(Opcode::LOP3_imm);
518}
519
520void TranslatorVisitor::LOP32I(u64) { 496void TranslatorVisitor::LOP32I(u64) {
521 ThrowNotImplemented(Opcode::LOP32I); 497 ThrowNotImplemented(Opcode::LOP32I);
522} 498}