Merge pull request #549 from bunnei/iadd
gl_shader_decompiler: Implement IADD instruction.
This commit is contained in:
		| @@ -213,6 +213,7 @@ union Instruction { | ||||
|     BitField<28, 8, Register> gpr28; | ||||
|     BitField<39, 8, Register> gpr39; | ||||
|     BitField<48, 16, u64> opcode; | ||||
|     BitField<50, 1, u64> saturate_a; | ||||
|  | ||||
|     union { | ||||
|         BitField<20, 19, u64> imm20_19; | ||||
| @@ -263,7 +264,7 @@ union Instruction { | ||||
|         BitField<39, 5, u64> shift_amount; | ||||
|         BitField<48, 1, u64> negate_b; | ||||
|         BitField<49, 1, u64> negate_a; | ||||
|     } iscadd; | ||||
|     } alu_integer; | ||||
|  | ||||
|     union { | ||||
|         BitField<20, 8, u64> shift_position; | ||||
| @@ -331,7 +332,6 @@ union Instruction { | ||||
|         BitField<41, 2, u64> selector; | ||||
|         BitField<45, 1, u64> negate_a; | ||||
|         BitField<49, 1, u64> abs_a; | ||||
|         BitField<50, 1, u64> saturate_a; | ||||
|  | ||||
|         union { | ||||
|             BitField<39, 2, F2iRoundingOp> rounding; | ||||
| @@ -434,6 +434,9 @@ public: | ||||
|         FMUL_R, | ||||
|         FMUL_IMM, | ||||
|         FMUL32_IMM, | ||||
|         IADD_C, | ||||
|         IADD_R, | ||||
|         IADD_IMM, | ||||
|         ISCADD_C, // Scale and Add | ||||
|         ISCADD_R, | ||||
|         ISCADD_IMM, | ||||
| @@ -489,10 +492,10 @@ public: | ||||
|     enum class Type { | ||||
|         Trivial, | ||||
|         Arithmetic, | ||||
|         ArithmeticInteger, | ||||
|         Bfe, | ||||
|         Logic, | ||||
|         Shift, | ||||
|         ScaledAdd, | ||||
|         Ffma, | ||||
|         Flow, | ||||
|         Memory, | ||||
| @@ -617,9 +620,12 @@ private: | ||||
|             INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), | ||||
|             INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), | ||||
|             INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), | ||||
|             INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"), | ||||
|             INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"), | ||||
|             INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"), | ||||
|             INST("0100110000010---", Id::IADD_C, Type::ArithmeticInteger, "IADD_C"), | ||||
|             INST("0101110000010---", Id::IADD_R, Type::ArithmeticInteger, "IADD_R"), | ||||
|             INST("0011100-00010---", Id::IADD_IMM, Type::ArithmeticInteger, "IADD_IMM"), | ||||
|             INST("0100110000011---", Id::ISCADD_C, Type::ArithmeticInteger, "ISCADD_C"), | ||||
|             INST("0101110000011---", Id::ISCADD_R, Type::ArithmeticInteger, "ISCADD_R"), | ||||
|             INST("0011100-00011---", Id::ISCADD_IMM, Type::ArithmeticInteger, "ISCADD_IMM"), | ||||
|             INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | ||||
|             INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), | ||||
|             INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), | ||||
|   | ||||
| @@ -808,6 +808,8 @@ private: | ||||
|             case OpCode::Id::FMUL_C: | ||||
|             case OpCode::Id::FMUL_R: | ||||
|             case OpCode::Id::FMUL_IMM: { | ||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " * " + op_b, 1, 1, instr.alu.abs_d); | ||||
|                 break; | ||||
|             } | ||||
| @@ -821,10 +823,14 @@ private: | ||||
|             case OpCode::Id::FADD_C: | ||||
|             case OpCode::Id::FADD_R: | ||||
|             case OpCode::Id::FADD_IMM: { | ||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|                 regs.SetRegisterToFloat(instr.gpr0, 0, op_a + " + " + op_b, 1, 1, instr.alu.abs_d); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::MUFU: { | ||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|                 switch (instr.sub_op) { | ||||
|                 case SubOp::Cos: | ||||
|                     regs.SetRegisterToFloat(instr.gpr0, 0, "cos(" + op_a + ')', 1, 1, | ||||
| @@ -986,13 +992,13 @@ private: | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         case OpCode::Type::ScaledAdd: { | ||||
|         case OpCode::Type::ArithmeticInteger: { | ||||
|             std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); | ||||
|  | ||||
|             if (instr.iscadd.negate_a) | ||||
|             if (instr.alu_integer.negate_a) | ||||
|                 op_a = '-' + op_a; | ||||
|  | ||||
|             std::string op_b = instr.iscadd.negate_b ? "-" : ""; | ||||
|             std::string op_b = instr.alu_integer.negate_b ? "-" : ""; | ||||
|  | ||||
|             if (instr.is_b_imm) { | ||||
|                 op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')'; | ||||
| @@ -1005,13 +1011,35 @@ private: | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             std::string shift = std::to_string(instr.iscadd.shift_amount.Value()); | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::IADD_C: | ||||
|             case OpCode::Id::IADD_R: | ||||
|             case OpCode::Id::IADD_IMM: { | ||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " + " + op_b, 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::ISCADD_C: | ||||
|             case OpCode::Id::ISCADD_R: | ||||
|             case OpCode::Id::ISCADD_IMM: { | ||||
|                 std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); | ||||
|  | ||||
|                 regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||||
|                                           "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 NGLOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}", | ||||
|                                opcode->GetName()); | ||||
|                 UNREACHABLE(); | ||||
|             } | ||||
|             } | ||||
|  | ||||
|             regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||||
|                                       "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Ffma: { | ||||
|             ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|             std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|             std::string op_b = instr.ffma.negate_b ? "-" : ""; | ||||
|             std::string op_c = instr.ffma.negate_c ? "-" : ""; | ||||
| @@ -1051,7 +1079,7 @@ private: | ||||
|         case OpCode::Type::Conversion: { | ||||
|             ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); | ||||
|             ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::I2I_R: { | ||||
| @@ -1081,6 +1109,8 @@ private: | ||||
|                 break; | ||||
|             } | ||||
|             case OpCode::Id::F2F_R: { | ||||
|                 ASSERT_MSG(!instr.saturate_a, "Unimplemented"); | ||||
|  | ||||
|                 std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | ||||
|  | ||||
|                 switch (instr.conversion.f2f.rounding) { | ||||
| @@ -1198,8 +1228,8 @@ private: | ||||
|                 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||||
|                 const std::string sampler = GetSampler(instr.sampler); | ||||
|                 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||||
|                 // Add an extra scope and declare the texture coords inside to prevent overwriting | ||||
|                 // them in case they are used as outputs of the texs instruction. | ||||
|                 // Add an extra scope and declare the texture coords inside to prevent | ||||
|                 // overwriting them in case they are used as outputs of the texs instruction. | ||||
|                 shader.AddLine("{"); | ||||
|                 ++shader.scope; | ||||
|                 shader.AddLine(coord); | ||||
| @@ -1230,8 +1260,8 @@ private: | ||||
|                 shader.AddLine(coord); | ||||
|                 const std::string texture = "texture(" + sampler + ", coords)"; | ||||
|  | ||||
|                 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA goes | ||||
|                 // into gpr28+0 and gpr28+1 | ||||
|                 // TEXS has two destination registers. RG goes into gpr0+0 and gpr0+1, and BA | ||||
|                 // goes into gpr28+0 and gpr28+1 | ||||
|                 size_t offset{}; | ||||
|  | ||||
|                 for (const auto& dest : {instr.gpr0.Value(), instr.gpr28.Value()}) { | ||||
| @@ -1412,8 +1442,8 @@ private: | ||||
|  | ||||
|                 shader.AddLine("return true;"); | ||||
|                 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { | ||||
|                     // If this is an unconditional exit then just end processing here, otherwise we | ||||
|                     // have to account for the possibility of the condition not being met, so | ||||
|                     // If this is an unconditional exit then just end processing here, otherwise | ||||
|                     // we have to account for the possibility of the condition not being met, so | ||||
|                     // continue processing the next instruction. | ||||
|                     offset = PROGRAM_END - 1; | ||||
|                 } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei