GPU: Implemented the LOP32I instruction.
This commit is contained in:
		| @@ -156,6 +156,13 @@ enum class PredOperation : u64 { | ||||
|     Xor = 2, | ||||
| }; | ||||
|  | ||||
| enum class LogicOperation : u64 { | ||||
|     And = 0, | ||||
|     Or = 1, | ||||
|     Xor = 2, | ||||
|     PassB = 3, | ||||
| }; | ||||
|  | ||||
| enum class SubOp : u64 { | ||||
|     Cos = 0x0, | ||||
|     Sin = 0x1, | ||||
| @@ -202,6 +209,12 @@ union Instruction { | ||||
|             BitField<42, 1, u64> negate_pred; | ||||
|         } fmnmx; | ||||
|  | ||||
|         union { | ||||
|             BitField<53, 2, LogicOperation> operation; | ||||
|             BitField<55, 1, u64> invert_a; | ||||
|             BitField<56, 1, u64> invert_b; | ||||
|         } lop; | ||||
|  | ||||
|         float GetImm20_19() const { | ||||
|             float result{}; | ||||
|             u32 imm{static_cast<u32>(imm20_19)}; | ||||
| @@ -367,6 +380,7 @@ public: | ||||
|     enum class Type { | ||||
|         Trivial, | ||||
|         Arithmetic, | ||||
|         Logic, | ||||
|         Ffma, | ||||
|         Flow, | ||||
|         Memory, | ||||
| @@ -499,7 +513,6 @@ private: | ||||
|             INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | ||||
|             INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | ||||
|             INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | ||||
|             INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), | ||||
|             INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | ||||
|             INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | ||||
|             INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | ||||
| @@ -510,6 +523,7 @@ private: | ||||
|             INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), | ||||
|             INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), | ||||
|             INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), | ||||
|             INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), | ||||
|             INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | ||||
|             INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | ||||
|             INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | ||||
|   | ||||
| @@ -808,6 +808,49 @@ private: | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Logic: { | ||||
|             std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); | ||||
|  | ||||
|             if (instr.alu.lop.invert_a) | ||||
|                 op_a = "~(" + op_a + ')'; | ||||
|  | ||||
|             switch (opcode->GetId()) { | ||||
|             case OpCode::Id::LOP32I: { | ||||
|                 u32 imm = static_cast<u32>(instr.alu.imm20_32.Value()); | ||||
|  | ||||
|                 if (instr.alu.lop.invert_b) | ||||
|                     imm = ~imm; | ||||
|  | ||||
|                 switch (instr.alu.lop.operation) { | ||||
|                 case Tegra::Shader::LogicOperation::And: { | ||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||||
|                                               '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::LogicOperation::Or: { | ||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||||
|                                               '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); | ||||
|                     break; | ||||
|                 } | ||||
|                 case Tegra::Shader::LogicOperation::Xor: { | ||||
|                     regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||||
|                                               '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); | ||||
|                     break; | ||||
|                 } | ||||
|                 default: | ||||
|                     NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}", | ||||
|                                    static_cast<u32>(instr.alu.lop.operation.Value())); | ||||
|                     UNREACHABLE(); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|             default: { | ||||
|                 NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName()); | ||||
|                 UNREACHABLE(); | ||||
|             } | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case OpCode::Type::Ffma: { | ||||
|             std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | ||||
|             std::string op_b = instr.ffma.negate_b ? "-" : ""; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user