diff options
| author | 2018-12-19 00:31:58 -0300 | |
|---|---|---|
| committer | 2019-01-15 17:54:52 -0300 | |
| commit | 4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383 (patch) | |
| tree | 85161efb42877cfa211d6c19b3aad3d0dd7af1cc | |
| parent | shader_decode: Implement LOP3 (diff) | |
| download | yuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.tar.gz yuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.tar.xz yuzu-4fd06efeb94ff5fc5af4c5e4b9e8a4fa95d3b383.zip | |
shader_decode: Implement IADD3
| -rw-r--r-- | src/video_core/shader/decode/arithmetic_integer.cpp | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 145bbcfc8..3b9b9d6d9 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | namespace VideoCommon::Shader { | 10 | namespace VideoCommon::Shader { |
| 11 | 11 | ||
| 12 | using Tegra::Shader::IAdd3Height; | ||
| 12 | using Tegra::Shader::Instruction; | 13 | using Tegra::Shader::Instruction; |
| 13 | using Tegra::Shader::OpCode; | 14 | using Tegra::Shader::OpCode; |
| 14 | using Tegra::Shader::Register; | 15 | using Tegra::Shader::Register; |
| @@ -42,6 +43,66 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) { | |||
| 42 | SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); | 43 | SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b)); |
| 43 | break; | 44 | break; |
| 44 | } | 45 | } |
| 46 | case OpCode::Id::IADD3_C: | ||
| 47 | case OpCode::Id::IADD3_R: | ||
| 48 | case OpCode::Id::IADD3_IMM: { | ||
| 49 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | ||
| 50 | "Condition codes generation in IADD3 is not implemented"); | ||
| 51 | |||
| 52 | Node op_c = GetRegister(instr.gpr39); | ||
| 53 | |||
| 54 | const auto ApplyHeight = [&](IAdd3Height height, Node value) { | ||
| 55 | switch (height) { | ||
| 56 | case IAdd3Height::None: | ||
| 57 | return value; | ||
| 58 | case IAdd3Height::LowerHalfWord: | ||
| 59 | return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff)); | ||
| 60 | case IAdd3Height::UpperHalfWord: | ||
| 61 | return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value, | ||
| 62 | Immediate(16)); | ||
| 63 | default: | ||
| 64 | UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height)); | ||
| 65 | return Immediate(0); | ||
| 66 | } | ||
| 67 | }; | ||
| 68 | |||
| 69 | if (opcode->get().GetId() == OpCode::Id::IADD3_R) { | ||
| 70 | op_a = ApplyHeight(instr.iadd3.height_a, op_a); | ||
| 71 | op_b = ApplyHeight(instr.iadd3.height_b, op_b); | ||
| 72 | op_c = ApplyHeight(instr.iadd3.height_c, op_c); | ||
| 73 | } | ||
| 74 | |||
| 75 | op_a = GetOperandAbsNegInteger(op_a, false, instr.iadd3.neg_a, true); | ||
| 76 | op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true); | ||
| 77 | op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true); | ||
| 78 | |||
| 79 | const Node value = [&]() { | ||
| 80 | const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b); | ||
| 81 | if (opcode->get().GetId() != OpCode::Id::IADD3_R) { | ||
| 82 | return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c); | ||
| 83 | } | ||
| 84 | const Node shifted = [&]() { | ||
| 85 | switch (instr.iadd3.mode) { | ||
| 86 | case Tegra::Shader::IAdd3Mode::RightShift: | ||
| 87 | // TODO(tech4me): According to | ||
| 88 | // https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3 | ||
| 89 | // The addition between op_a and op_b should be done in uint33, more | ||
| 90 | // investigation required | ||
| 91 | return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, add_ab, | ||
| 92 | Immediate(16)); | ||
| 93 | case Tegra::Shader::IAdd3Mode::LeftShift: | ||
| 94 | return Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, add_ab, | ||
| 95 | Immediate(16)); | ||
| 96 | default: | ||
| 97 | return add_ab; | ||
| 98 | } | ||
| 99 | }(); | ||
| 100 | return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c); | ||
| 101 | }(); | ||
| 102 | |||
| 103 | SetRegister(bb, instr.gpr0, value); | ||
| 104 | break; | ||
| 105 | } | ||
| 45 | case OpCode::Id::ISCADD_C: | 106 | case OpCode::Id::ISCADD_C: |
| 46 | case OpCode::Id::ISCADD_R: | 107 | case OpCode::Id::ISCADD_R: |
| 47 | case OpCode::Id::ISCADD_IMM: { | 108 | case OpCode::Id::ISCADD_IMM: { |