mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	shader_decode: Implement IADD3
This commit is contained in:
		
							parent
							
								
									a40fd07516
								
							
						
					
					
						commit
						4fd06efeb9
					
				@ -9,6 +9,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace VideoCommon::Shader {
 | 
					namespace VideoCommon::Shader {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using Tegra::Shader::IAdd3Height;
 | 
				
			||||||
using Tegra::Shader::Instruction;
 | 
					using Tegra::Shader::Instruction;
 | 
				
			||||||
using Tegra::Shader::OpCode;
 | 
					using Tegra::Shader::OpCode;
 | 
				
			||||||
using Tegra::Shader::Register;
 | 
					using Tegra::Shader::Register;
 | 
				
			||||||
@ -42,6 +43,66 @@ u32 ShaderIR::DecodeArithmeticInteger(BasicBlock& bb, u32 pc) {
 | 
				
			|||||||
        SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b));
 | 
					        SetRegister(bb, instr.gpr0, Operation(OperationCode::IAdd, PRECISE, op_a, op_b));
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    case OpCode::Id::IADD3_C:
 | 
				
			||||||
 | 
					    case OpCode::Id::IADD3_R:
 | 
				
			||||||
 | 
					    case OpCode::Id::IADD3_IMM: {
 | 
				
			||||||
 | 
					        UNIMPLEMENTED_IF_MSG(instr.generates_cc,
 | 
				
			||||||
 | 
					                             "Condition codes generation in IADD3 is not implemented");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Node op_c = GetRegister(instr.gpr39);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const auto ApplyHeight = [&](IAdd3Height height, Node value) {
 | 
				
			||||||
 | 
					            switch (height) {
 | 
				
			||||||
 | 
					            case IAdd3Height::None:
 | 
				
			||||||
 | 
					                return value;
 | 
				
			||||||
 | 
					            case IAdd3Height::LowerHalfWord:
 | 
				
			||||||
 | 
					                return Operation(OperationCode::IBitwiseAnd, NO_PRECISE, value, Immediate(0xffff));
 | 
				
			||||||
 | 
					            case IAdd3Height::UpperHalfWord:
 | 
				
			||||||
 | 
					                return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, value,
 | 
				
			||||||
 | 
					                                 Immediate(16));
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                UNIMPLEMENTED_MSG("Unhandled IADD3 height: {}", static_cast<u32>(height));
 | 
				
			||||||
 | 
					                return Immediate(0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
 | 
				
			||||||
 | 
					            op_a = ApplyHeight(instr.iadd3.height_a, op_a);
 | 
				
			||||||
 | 
					            op_b = ApplyHeight(instr.iadd3.height_b, op_b);
 | 
				
			||||||
 | 
					            op_c = ApplyHeight(instr.iadd3.height_c, op_c);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        op_a = GetOperandAbsNegInteger(op_a, false, instr.iadd3.neg_a, true);
 | 
				
			||||||
 | 
					        op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true);
 | 
				
			||||||
 | 
					        op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const Node value = [&]() {
 | 
				
			||||||
 | 
					            const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b);
 | 
				
			||||||
 | 
					            if (opcode->get().GetId() != OpCode::Id::IADD3_R) {
 | 
				
			||||||
 | 
					                return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const Node shifted = [&]() {
 | 
				
			||||||
 | 
					                switch (instr.iadd3.mode) {
 | 
				
			||||||
 | 
					                case Tegra::Shader::IAdd3Mode::RightShift:
 | 
				
			||||||
 | 
					                    // TODO(tech4me): According to
 | 
				
			||||||
 | 
					                    // https://envytools.readthedocs.io/en/latest/hw/graph/maxwell/cuda/int.html?highlight=iadd3
 | 
				
			||||||
 | 
					                    // The addition between op_a and op_b should be done in uint33, more
 | 
				
			||||||
 | 
					                    // investigation required
 | 
				
			||||||
 | 
					                    return Operation(OperationCode::ILogicalShiftRight, NO_PRECISE, add_ab,
 | 
				
			||||||
 | 
					                                     Immediate(16));
 | 
				
			||||||
 | 
					                case Tegra::Shader::IAdd3Mode::LeftShift:
 | 
				
			||||||
 | 
					                    return Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, add_ab,
 | 
				
			||||||
 | 
					                                     Immediate(16));
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    return add_ab;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }();
 | 
				
			||||||
 | 
					            return Operation(OperationCode::IAdd, NO_PRECISE, shifted, op_c);
 | 
				
			||||||
 | 
					        }();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SetRegister(bb, instr.gpr0, value);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    case OpCode::Id::ISCADD_C:
 | 
					    case OpCode::Id::ISCADD_C:
 | 
				
			||||||
    case OpCode::Id::ISCADD_R:
 | 
					    case OpCode::Id::ISCADD_R:
 | 
				
			||||||
    case OpCode::Id::ISCADD_IMM: {
 | 
					    case OpCode::Id::ISCADD_IMM: {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user