mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #4147 from ReinUsesLisp/hset2-imm
shader/half_set: Implement HSET2_IMM
This commit is contained in:
		
						commit
						efef7b1517
					
				| @ -661,6 +661,10 @@ union Instruction { | ||||
|     constexpr Instruction(u64 value) : value{value} {} | ||||
|     constexpr Instruction(const Instruction& instr) : value(instr.value) {} | ||||
| 
 | ||||
|     constexpr bool Bit(u64 offset) const { | ||||
|         return ((value >> offset) & 1) != 0; | ||||
|     } | ||||
| 
 | ||||
|     BitField<0, 8, Register> gpr0; | ||||
|     BitField<8, 8, Register> gpr8; | ||||
|     union { | ||||
| @ -1874,7 +1878,9 @@ public: | ||||
|         HSETP2_C, | ||||
|         HSETP2_R, | ||||
|         HSETP2_IMM, | ||||
|         HSET2_C, | ||||
|         HSET2_R, | ||||
|         HSET2_IMM, | ||||
|         POPC_C, | ||||
|         POPC_R, | ||||
|         POPC_IMM, | ||||
| @ -2194,7 +2200,9 @@ private: | ||||
|             INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), | ||||
|             INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), | ||||
|             INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), | ||||
|             INST("0111110-1-------", Id::HSET2_C, Type::HalfSet, "HSET2_C"), | ||||
|             INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), | ||||
|             INST("0111110-0-------", Id::HSET2_IMM, Type::HalfSet, "HSET2_IMM"), | ||||
|             INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), | ||||
|             INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), | ||||
|             INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | ||||
|  | ||||
| @ -13,55 +13,101 @@ | ||||
| 
 | ||||
| namespace VideoCommon::Shader { | ||||
| 
 | ||||
| using std::move; | ||||
| using Tegra::Shader::Instruction; | ||||
| using Tegra::Shader::OpCode; | ||||
| using Tegra::Shader::PredCondition; | ||||
| 
 | ||||
| u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { | ||||
|     const Instruction instr = {program_code[pc]}; | ||||
|     const auto opcode = OpCode::Decode(instr); | ||||
| 
 | ||||
|     if (instr.hset2.ftz == 0) { | ||||
|     PredCondition cond; | ||||
|     bool bf; | ||||
|     bool ftz; | ||||
|     bool neg_a; | ||||
|     bool abs_a; | ||||
|     bool neg_b; | ||||
|     bool abs_b; | ||||
|     switch (opcode->get().GetId()) { | ||||
|     case OpCode::Id::HSET2_C: | ||||
|     case OpCode::Id::HSET2_IMM: | ||||
|         cond = instr.hsetp2.cbuf_and_imm.cond; | ||||
|         bf = instr.Bit(53); | ||||
|         ftz = instr.Bit(54); | ||||
|         neg_a = instr.Bit(43); | ||||
|         abs_a = instr.Bit(44); | ||||
|         neg_b = instr.Bit(56); | ||||
|         abs_b = instr.Bit(54); | ||||
|         break; | ||||
|     case OpCode::Id::HSET2_R: | ||||
|         cond = instr.hsetp2.reg.cond; | ||||
|         bf = instr.Bit(49); | ||||
|         ftz = instr.Bit(50); | ||||
|         neg_a = instr.Bit(43); | ||||
|         abs_a = instr.Bit(44); | ||||
|         neg_b = instr.Bit(31); | ||||
|         abs_b = instr.Bit(30); | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
| 
 | ||||
|     Node op_b = [this, instr, opcode] { | ||||
|         switch (opcode->get().GetId()) { | ||||
|         case OpCode::Id::HSET2_C: | ||||
|             // Inform as unimplemented as this is not tested.
 | ||||
|             UNIMPLEMENTED_MSG("HSET2_C is not implemented"); | ||||
|             return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | ||||
|         case OpCode::Id::HSET2_R: | ||||
|             return GetRegister(instr.gpr20); | ||||
|         case OpCode::Id::HSET2_IMM: | ||||
|             return UnpackHalfImmediate(instr, true); | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|             return Node{}; | ||||
|         } | ||||
|     }(); | ||||
| 
 | ||||
|     if (!ftz) { | ||||
|         LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | ||||
|     } | ||||
| 
 | ||||
|     Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); | ||||
|     op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a); | ||||
|     op_a = GetOperandAbsNegHalf(op_a, abs_a, neg_a); | ||||
| 
 | ||||
|     Node op_b = [&]() { | ||||
|         switch (opcode->get().GetId()) { | ||||
|         case OpCode::Id::HSET2_R: | ||||
|             return GetRegister(instr.gpr20); | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|             return Immediate(0); | ||||
|         } | ||||
|     }(); | ||||
|     op_b = UnpackHalfFloat(op_b, instr.hset2.type_b); | ||||
|     op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b); | ||||
|     switch (opcode->get().GetId()) { | ||||
|     case OpCode::Id::HSET2_R: | ||||
|         op_b = GetOperandAbsNegHalf(move(op_b), abs_b, neg_b); | ||||
|         [[fallthrough]]; | ||||
|     case OpCode::Id::HSET2_C: | ||||
|         op_b = UnpackHalfFloat(move(op_b), instr.hset2.type_b); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); | ||||
|     Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); | ||||
| 
 | ||||
|     const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b); | ||||
|     Node comparison_pair = GetPredicateComparisonHalf(cond, op_a, op_b); | ||||
| 
 | ||||
|     const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); | ||||
| 
 | ||||
|     // HSET2 operates on each half float in the pack.
 | ||||
|     std::array<Node, 2> values; | ||||
|     for (u32 i = 0; i < 2; ++i) { | ||||
|         const u32 raw_value = instr.hset2.bf ? 0x3c00 : 0xffff; | ||||
|         const Node true_value = Immediate(raw_value << (i * 16)); | ||||
|         const Node false_value = Immediate(0); | ||||
| 
 | ||||
|         const Node comparison = | ||||
|             Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||||
|         const Node predicate = Operation(combiner, comparison, second_pred); | ||||
|         const u32 raw_value = bf ? 0x3c00 : 0xffff; | ||||
|         Node true_value = Immediate(raw_value << (i * 16)); | ||||
|         Node false_value = Immediate(0); | ||||
| 
 | ||||
|         Node comparison = Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||||
|         Node predicate = Operation(combiner, comparison, second_pred); | ||||
|         values[i] = | ||||
|             Operation(OperationCode::Select, NO_PRECISE, predicate, true_value, false_value); | ||||
|             Operation(OperationCode::Select, predicate, move(true_value), move(false_value)); | ||||
|     } | ||||
| 
 | ||||
|     const Node value = Operation(OperationCode::UBitwiseOr, NO_PRECISE, values[0], values[1]); | ||||
|     SetRegister(bb, instr.gpr0, value); | ||||
|     Node value = Operation(OperationCode::UBitwiseOr, values[0], values[1]); | ||||
|     SetRegister(bb, instr.gpr0, move(value)); | ||||
| 
 | ||||
|     return pc; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei