summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend')
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp48
1 files changed, 31 insertions, 17 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
index 93cc2c0b1..044671943 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/integer_scaled_add.cpp
@@ -8,40 +8,36 @@
8 8
9namespace Shader::Maxwell { 9namespace Shader::Maxwell {
10namespace { 10namespace {
11void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { 11void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b, bool cc, bool neg_a, bool neg_b,
12 u64 scale_imm) {
12 union { 13 union {
13 u64 raw; 14 u64 raw;
14 BitField<0, 8, IR::Reg> dest_reg; 15 BitField<0, 8, IR::Reg> dest_reg;
15 BitField<8, 8, IR::Reg> op_a; 16 BitField<8, 8, IR::Reg> op_a;
16 BitField<47, 1, u64> cc;
17 BitField<48, 2, u64> three_for_po;
18 BitField<48, 1, u64> neg_b;
19 BitField<49, 1, u64> neg_a;
20 BitField<39, 5, u64> scale;
21 } const iscadd{insn}; 17 } const iscadd{insn};
22 18
23 const bool po{iscadd.three_for_po == 3}; 19 const bool po{neg_a && neg_b};
24 IR::U32 op_a{v.X(iscadd.op_a)}; 20 IR::U32 op_a{v.X(iscadd.op_a)};
25 if (!po) { 21 if (po) {
22 // When PO is present, add one
23 op_b = v.ir.IAdd(op_b, v.ir.Imm32(1));
24 } else {
26 // When PO is not present, the bits are interpreted as negation 25 // When PO is not present, the bits are interpreted as negation
27 if (iscadd.neg_a != 0) { 26 if (neg_a) {
28 op_a = v.ir.INeg(op_a); 27 op_a = v.ir.INeg(op_a);
29 } 28 }
30 if (iscadd.neg_b != 0) { 29 if (neg_b) {
31 op_b = v.ir.INeg(op_b); 30 op_b = v.ir.INeg(op_b);
32 } 31 }
33 } else {
34 // When PO is present, add one
35 op_b = v.ir.IAdd(op_b, v.ir.Imm32(1));
36 } 32 }
37 // With the operands already processed, scale A 33 // With the operands already processed, scale A
38 const IR::U32 scale{v.ir.Imm32(static_cast<u32>(iscadd.scale))}; 34 const IR::U32 scale{v.ir.Imm32(static_cast<u32>(scale_imm))};
39 const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)}; 35 const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)};
40 36
41 const IR::U32 result{v.ir.IAdd(scaled_a, op_b)}; 37 const IR::U32 result{v.ir.IAdd(scaled_a, op_b)};
42 v.X(iscadd.dest_reg, result); 38 v.X(iscadd.dest_reg, result);
43 39
44 if (iscadd.cc != 0) { 40 if (cc) {
45 v.SetZFlag(v.ir.GetZeroFromOp(result)); 41 v.SetZFlag(v.ir.GetZeroFromOp(result));
46 v.SetSFlag(v.ir.GetSignFromOp(result)); 42 v.SetSFlag(v.ir.GetSignFromOp(result));
47 const IR::U1 carry{v.ir.GetCarryFromOp(result)}; 43 const IR::U1 carry{v.ir.GetCarryFromOp(result)};
@@ -51,6 +47,18 @@ void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
51 } 47 }
52} 48}
53 49
50void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) {
51 union {
52 u64 raw;
53 BitField<47, 1, u64> cc;
54 BitField<48, 1, u64> neg_b;
55 BitField<49, 1, u64> neg_a;
56 BitField<39, 5, u64> scale;
57 } const iscadd{insn};
58
59 ISCADD(v, insn, op_b, iscadd.cc != 0, iscadd.neg_a != 0, iscadd.neg_b != 0, iscadd.scale);
60}
61
54} // Anonymous namespace 62} // Anonymous namespace
55 63
56void TranslatorVisitor::ISCADD_reg(u64 insn) { 64void TranslatorVisitor::ISCADD_reg(u64 insn) {
@@ -65,8 +73,14 @@ void TranslatorVisitor::ISCADD_imm(u64 insn) {
65 ISCADD(*this, insn, GetImm20(insn)); 73 ISCADD(*this, insn, GetImm20(insn));
66} 74}
67 75
68void TranslatorVisitor::ISCADD32I(u64) { 76void TranslatorVisitor::ISCADD32I(u64 insn) {
69 throw NotImplementedException("ISCADD32I"); 77 union {
78 u64 raw;
79 BitField<52, 1, u64> cc;
80 BitField<53, 5, u64> scale;
81 } const iscadd{insn};
82
83 return ISCADD(*this, insn, GetImm32(insn), iscadd.cc != 0, false, false, iscadd.scale);
70} 84}
71 85
72} // namespace Shader::Maxwell 86} // namespace Shader::Maxwell