mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	gl_shader_decompiler: Implement FMUL/FADD/FFMA immediate instructions.
This commit is contained in:
		
							parent
							
								
									8d4899d6ea
								
							
						
					
					
						commit
						5a28dce9eb
					
				@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "common/bit_field.h"
 | 
			
		||||
@ -289,6 +290,7 @@ enum class SubOp : u64 {
 | 
			
		||||
    Lg2 = 0x3,
 | 
			
		||||
    Rcp = 0x4,
 | 
			
		||||
    Rsq = 0x5,
 | 
			
		||||
    Min = 0x8,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
union Instruction {
 | 
			
		||||
@ -307,11 +309,22 @@ union Instruction {
 | 
			
		||||
    BitField<39, 8, Register> gpr39;
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        BitField<20, 19, u64> imm20;
 | 
			
		||||
        BitField<45, 1, u64> negate_b;
 | 
			
		||||
        BitField<46, 1, u64> abs_a;
 | 
			
		||||
        BitField<48, 1, u64> negate_a;
 | 
			
		||||
        BitField<49, 1, u64> abs_b;
 | 
			
		||||
        BitField<50, 1, u64> abs_d;
 | 
			
		||||
        BitField<56, 1, u64> negate_imm;
 | 
			
		||||
 | 
			
		||||
        float GetImm20() const {
 | 
			
		||||
            float result{};
 | 
			
		||||
            u32 imm{static_cast<u32>(imm20)};
 | 
			
		||||
            imm <<= 12;
 | 
			
		||||
            imm |= negate_imm ? 0x80000000 : 0;
 | 
			
		||||
            std::memcpy(&result, &imm, sizeof(imm));
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
    } alu;
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
@ -319,6 +332,7 @@ union Instruction {
 | 
			
		||||
        BitField<49, 1, u64> negate_c;
 | 
			
		||||
    } ffma;
 | 
			
		||||
 | 
			
		||||
    BitField<61, 1, u64> is_b_imm;
 | 
			
		||||
    BitField<60, 1, u64> is_b_gpr;
 | 
			
		||||
    BitField<59, 1, u64> is_c_gpr;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -190,6 +190,11 @@ private:
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Generates code representing an immediate value
 | 
			
		||||
    static std::string GetImmediate(const Instruction& instr) {
 | 
			
		||||
        return std::to_string(instr.alu.GetImm20());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Generates code representing a temporary (GPR) register.
 | 
			
		||||
    std::string GetRegister(const Register& reg, unsigned elem = 0) {
 | 
			
		||||
        if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
 | 
			
		||||
@ -269,24 +274,32 @@ private:
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            std::string op_b = instr.alu.negate_b ? "-" : "";
 | 
			
		||||
 | 
			
		||||
            if (instr.is_b_imm) {
 | 
			
		||||
                op_b += GetImmediate(instr);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (instr.is_b_gpr) {
 | 
			
		||||
                    op_b += GetRegister(instr.gpr20);
 | 
			
		||||
                } else {
 | 
			
		||||
                    op_b += GetUniform(instr.uniform);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (instr.alu.abs_b) {
 | 
			
		||||
                op_b = "abs(" + op_b + ")";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (instr.opcode.EffectiveOpCode()) {
 | 
			
		||||
            case OpCode::Id::FMUL_C:
 | 
			
		||||
            case OpCode::Id::FMUL_R: {
 | 
			
		||||
                SetDest(0, dest, op_a + " * " + op_b, 1, 1);
 | 
			
		||||
            case OpCode::Id::FMUL_R:
 | 
			
		||||
            case OpCode::Id::FMUL_IMM: {
 | 
			
		||||
                SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case OpCode::Id::FADD_C:
 | 
			
		||||
            case OpCode::Id::FADD_R: {
 | 
			
		||||
                SetDest(0, dest, op_a + " + " + op_b, 1, 1);
 | 
			
		||||
            case OpCode::Id::FADD_R:
 | 
			
		||||
            case OpCode::Id::FADD_IMM: {
 | 
			
		||||
                SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case OpCode::Id::MUFU: {
 | 
			
		||||
@ -316,16 +329,28 @@ private:
 | 
			
		||||
 | 
			
		||||
            std::string dest = GetRegister(instr.gpr0);
 | 
			
		||||
            std::string op_a = GetRegister(instr.gpr8);
 | 
			
		||||
 | 
			
		||||
            std::string op_b = instr.ffma.negate_b ? "-" : "";
 | 
			
		||||
            op_b += GetUniform(instr.uniform);
 | 
			
		||||
 | 
			
		||||
            std::string op_c = instr.ffma.negate_c ? "-" : "";
 | 
			
		||||
            op_c += GetRegister(instr.gpr39);
 | 
			
		||||
 | 
			
		||||
            switch (instr.opcode.EffectiveOpCode()) {
 | 
			
		||||
            case OpCode::Id::FFMA_CR: {
 | 
			
		||||
                SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
 | 
			
		||||
                op_b += GetUniform(instr.uniform);
 | 
			
		||||
                op_c += GetRegister(instr.gpr39);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case OpCode::Id::FFMA_RR: {
 | 
			
		||||
                op_b += GetRegister(instr.gpr20);
 | 
			
		||||
                op_c += GetRegister(instr.gpr39);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case OpCode::Id::FFMA_RC: {
 | 
			
		||||
                op_b += GetRegister(instr.gpr39);
 | 
			
		||||
                op_c += GetUniform(instr.uniform);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case OpCode::Id::FFMA_IMM: {
 | 
			
		||||
                op_b += GetImmediate(instr);
 | 
			
		||||
                op_c += GetRegister(instr.gpr39);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            default: {
 | 
			
		||||
@ -336,6 +361,8 @@ private:
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case OpCode::Type::Memory: {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user