Merge pull request #514 from Subv/lop32i
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)};
 | 
			
		||||
@@ -391,6 +404,7 @@ public:
 | 
			
		||||
    enum class Type {
 | 
			
		||||
        Trivial,
 | 
			
		||||
        Arithmetic,
 | 
			
		||||
        Logic,
 | 
			
		||||
        Ffma,
 | 
			
		||||
        Flow,
 | 
			
		||||
        Memory,
 | 
			
		||||
@@ -524,7 +538,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"),
 | 
			
		||||
@@ -535,6 +548,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"),
 | 
			
		||||
 
 | 
			
		||||
@@ -841,6 +841,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