Merge pull request #542 from bunnei/bfe_imm
gl_shader_decompiler: Implement BFE_IMM instruction.
This commit is contained in:
		| @@ -265,6 +265,17 @@ union Instruction { | |||||||
|         BitField<49, 1, u64> negate_a; |         BitField<49, 1, u64> negate_a; | ||||||
|     } iscadd; |     } iscadd; | ||||||
|  |  | ||||||
|  |     union { | ||||||
|  |         BitField<20, 8, u64> shift_position; | ||||||
|  |         BitField<28, 8, u64> shift_length; | ||||||
|  |         BitField<48, 1, u64> negate_b; | ||||||
|  |         BitField<49, 1, u64> negate_a; | ||||||
|  |  | ||||||
|  |         u64 GetLeftShiftValue() const { | ||||||
|  |             return 32 - (shift_position + shift_length); | ||||||
|  |         } | ||||||
|  |     } bfe; | ||||||
|  |  | ||||||
|     union { |     union { | ||||||
|         BitField<48, 1, u64> negate_b; |         BitField<48, 1, u64> negate_b; | ||||||
|         BitField<49, 1, u64> negate_c; |         BitField<49, 1, u64> negate_c; | ||||||
| @@ -478,6 +489,7 @@ public: | |||||||
|     enum class Type { |     enum class Type { | ||||||
|         Trivial, |         Trivial, | ||||||
|         Arithmetic, |         Arithmetic, | ||||||
|  |         Bfe, | ||||||
|         Logic, |         Logic, | ||||||
|         Shift, |         Shift, | ||||||
|         ScaledAdd, |         ScaledAdd, | ||||||
| @@ -584,9 +596,6 @@ private: | |||||||
|         std::vector<Matcher> table = { |         std::vector<Matcher> table = { | ||||||
| #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) | ||||||
|             INST("111000110011----", Id::KIL, Type::Flow, "KIL"), |             INST("111000110011----", Id::KIL, Type::Flow, "KIL"), | ||||||
|             INST("0100110000000---", Id::BFE_C, Type::Flow, "BFE_C"), |  | ||||||
|             INST("0101110000000---", Id::BFE_R, Type::Flow, "BFE_R"), |  | ||||||
|             INST("0011100-00000---", Id::BFE_IMM, Type::Flow, "BFE_IMM"), |  | ||||||
|             INST("111000100100----", Id::BRA, Type::Flow, "BRA"), |             INST("111000100100----", Id::BRA, Type::Flow, "BRA"), | ||||||
|             INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), |             INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), | ||||||
|             INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), |             INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), | ||||||
| @@ -631,6 +640,9 @@ private: | |||||||
|             INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"), |             INST("0100110000100---", Id::IMNMX_C, Type::Arithmetic, "FMNMX_IMM"), | ||||||
|             INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"), |             INST("0101110000100---", Id::IMNMX_R, Type::Arithmetic, "FMNMX_IMM"), | ||||||
|             INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), |             INST("0011100-00100---", Id::IMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), | ||||||
|  |             INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"), | ||||||
|  |             INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"), | ||||||
|  |             INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"), | ||||||
|             INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), |             INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), | ||||||
|             INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), |             INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"), | ||||||
|             INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), |             INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"), | ||||||
|   | |||||||
| @@ -888,8 +888,33 @@ private: | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |         case OpCode::Type::Bfe: { | ||||||
|  |             ASSERT_MSG(!instr.bfe.negate_b, "Unimplemented"); | ||||||
|  |  | ||||||
|  |             std::string op_a = instr.bfe.negate_a ? "-" : ""; | ||||||
|  |             op_a += regs.GetRegisterAsInteger(instr.gpr8); | ||||||
|  |  | ||||||
|  |             switch (opcode->GetId()) { | ||||||
|  |             case OpCode::Id::BFE_IMM: { | ||||||
|  |                 std::string inner_shift = | ||||||
|  |                     '(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')'; | ||||||
|  |                 std::string outer_shift = | ||||||
|  |                     '(' + inner_shift + " >> " + | ||||||
|  |                     std::to_string(instr.bfe.GetLeftShiftValue() + instr.bfe.shift_position) + ')'; | ||||||
|  |  | ||||||
|  |                 regs.SetRegisterToInteger(instr.gpr0, true, 0, outer_shift, 1, 1); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             default: { | ||||||
|  |                 NGLOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->GetName()); | ||||||
|  |                 UNREACHABLE(); | ||||||
|  |             } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         case OpCode::Type::Logic: { |         case OpCode::Type::Logic: { | ||||||
|             std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); |             std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, true); | ||||||
|  |  | ||||||
|             if (instr.alu.lop.invert_a) |             if (instr.alu.lop.invert_a) | ||||||
|                 op_a = "~(" + op_a + ')'; |                 op_a = "~(" + op_a + ')'; | ||||||
| @@ -903,17 +928,17 @@ private: | |||||||
|  |  | ||||||
|                 switch (instr.alu.lop.operation) { |                 switch (instr.alu.lop.operation) { | ||||||
|                 case Tegra::Shader::LogicOperation::And: { |                 case Tegra::Shader::LogicOperation::And: { | ||||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, |                     regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||||||
|                                               '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); |                                               '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case Tegra::Shader::LogicOperation::Or: { |                 case Tegra::Shader::LogicOperation::Or: { | ||||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, |                     regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||||||
|                                               '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); |                                               '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 case Tegra::Shader::LogicOperation::Xor: { |                 case Tegra::Shader::LogicOperation::Xor: { | ||||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, |                     regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||||||
|                                               '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); |                                               '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user