mirror of
				https://github.com/yuzu-emu/yuzu.git
				synced 2025-11-04 02:33:42 +00:00 
			
		
		
		
	Correct XMAD mode, psl and high_b on different encodings.
This commit is contained in:
		
							parent
							
								
									f14328bf0a
								
							
						
					
					
						commit
						16adc735a5
					
				@ -1238,13 +1238,16 @@ union Instruction {
 | 
			
		||||
 | 
			
		||||
    union {
 | 
			
		||||
        BitField<20, 16, u64> imm20_16;
 | 
			
		||||
        BitField<35, 1, u64> high_b_rr; // used on RR
 | 
			
		||||
        BitField<36, 1, u64> product_shift_left;
 | 
			
		||||
        BitField<37, 1, u64> merge_37;
 | 
			
		||||
        BitField<48, 1, u64> sign_a;
 | 
			
		||||
        BitField<49, 1, u64> sign_b;
 | 
			
		||||
        BitField<50, 2, XmadMode> mode_cbf; // used by CR, RC
 | 
			
		||||
        BitField<50, 3, XmadMode> mode;
 | 
			
		||||
        BitField<52, 1, u64> high_b;
 | 
			
		||||
        BitField<53, 1, u64> high_a;
 | 
			
		||||
        BitField<55, 1, u64> product_shift_left_second; // used on CR
 | 
			
		||||
        BitField<56, 1, u64> merge_56;
 | 
			
		||||
    } xmad;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,39 +29,55 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
 | 
			
		||||
    const bool is_signed_b = instr.xmad.sign_b == 1;
 | 
			
		||||
    const bool is_signed_c = is_signed_a;
 | 
			
		||||
 | 
			
		||||
    auto [is_merge, op_b, op_c] = [&]() -> std::tuple<bool, Node, Node> {
 | 
			
		||||
    auto [is_merge, is_psl, is_high_b, mode, op_b,
 | 
			
		||||
          op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> {
 | 
			
		||||
        switch (opcode->get().GetId()) {
 | 
			
		||||
        case OpCode::Id::XMAD_CR:
 | 
			
		||||
            return {instr.xmad.merge_56,
 | 
			
		||||
                    instr.xmad.product_shift_left_second,
 | 
			
		||||
                    instr.xmad.high_b,
 | 
			
		||||
                    instr.xmad.mode_cbf,
 | 
			
		||||
                    GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()),
 | 
			
		||||
                    GetRegister(instr.gpr39)};
 | 
			
		||||
        case OpCode::Id::XMAD_RR:
 | 
			
		||||
            return {instr.xmad.merge_37, GetRegister(instr.gpr20), GetRegister(instr.gpr39)};
 | 
			
		||||
            return {instr.xmad.merge_37, instr.xmad.product_shift_left, instr.xmad.high_b_rr,
 | 
			
		||||
                    instr.xmad.mode,     GetRegister(instr.gpr20),      GetRegister(instr.gpr39)};
 | 
			
		||||
        case OpCode::Id::XMAD_RC:
 | 
			
		||||
            return {false, GetRegister(instr.gpr39),
 | 
			
		||||
            return {false,
 | 
			
		||||
                    false,
 | 
			
		||||
                    instr.xmad.high_b,
 | 
			
		||||
                    instr.xmad.mode_cbf,
 | 
			
		||||
                    GetRegister(instr.gpr39),
 | 
			
		||||
                    GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset())};
 | 
			
		||||
        case OpCode::Id::XMAD_IMM:
 | 
			
		||||
            return {instr.xmad.merge_37, Immediate(static_cast<u32>(instr.xmad.imm20_16)),
 | 
			
		||||
            return {instr.xmad.merge_37,
 | 
			
		||||
                    instr.xmad.product_shift_left,
 | 
			
		||||
                    false,
 | 
			
		||||
                    instr.xmad.mode,
 | 
			
		||||
                    Immediate(static_cast<u32>(instr.xmad.imm20_16)),
 | 
			
		||||
                    GetRegister(instr.gpr39)};
 | 
			
		||||
        }
 | 
			
		||||
        UNIMPLEMENTED_MSG("Unhandled XMAD instruction: {}", opcode->get().GetName());
 | 
			
		||||
        return {false, Immediate(0), Immediate(0)};
 | 
			
		||||
        return {false, false, false, Tegra::Shader::XmadMode::None, Immediate(0), Immediate(0)};
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16);
 | 
			
		||||
 | 
			
		||||
    const Node original_b = op_b;
 | 
			
		||||
    op_b = BitfieldExtract(op_b, instr.xmad.high_b ? 16 : 0, 16);
 | 
			
		||||
    op_b = BitfieldExtract(op_b, is_high_b ? 16 : 0, 16);
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Use an appropiate sign for this operation
 | 
			
		||||
    Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b);
 | 
			
		||||
    if (instr.xmad.product_shift_left) {
 | 
			
		||||
    if (is_psl) {
 | 
			
		||||
        product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16));
 | 
			
		||||
    }
 | 
			
		||||
    SetTemporal(bb, 0, product);
 | 
			
		||||
    product = GetTemporal(0);
 | 
			
		||||
 | 
			
		||||
    const Node original_c = op_c;
 | 
			
		||||
    const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error
 | 
			
		||||
    op_c = [&]() {
 | 
			
		||||
        switch (instr.xmad.mode) {
 | 
			
		||||
        switch (set_mode) {
 | 
			
		||||
        case Tegra::Shader::XmadMode::None:
 | 
			
		||||
            return original_c;
 | 
			
		||||
        case Tegra::Shader::XmadMode::CLo:
 | 
			
		||||
@ -80,8 +96,13 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
 | 
			
		||||
        }
 | 
			
		||||
    }();
 | 
			
		||||
 | 
			
		||||
    SetTemporal(bb, 1, op_c);
 | 
			
		||||
    op_c = GetTemporal(1);
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Use an appropiate sign for this operation
 | 
			
		||||
    Node sum = Operation(OperationCode::IAdd, product, op_c);
 | 
			
		||||
    SetTemporal(bb, 2, sum);
 | 
			
		||||
    sum = GetTemporal(2);
 | 
			
		||||
    if (is_merge) {
 | 
			
		||||
        const Node a = BitfieldExtract(sum, 0, 16);
 | 
			
		||||
        const Node b =
 | 
			
		||||
@ -95,4 +116,4 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
 | 
			
		||||
    return pc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCommon::Shader
 | 
			
		||||
} // namespace VideoCommon::Shader
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user