forked from eden-emu/eden
		
	Merge pull request #4147 from ReinUsesLisp/hset2-imm
shader/half_set: Implement HSET2_IMM
This commit is contained in:
		
						commit
						7048f18d87
					
				
					 2 changed files with 79 additions and 25 deletions
				
			
		|  | @ -661,6 +661,10 @@ union Instruction { | ||||||
|     constexpr Instruction(u64 value) : value{value} {} |     constexpr Instruction(u64 value) : value{value} {} | ||||||
|     constexpr Instruction(const Instruction& instr) : value(instr.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<0, 8, Register> gpr0; | ||||||
|     BitField<8, 8, Register> gpr8; |     BitField<8, 8, Register> gpr8; | ||||||
|     union { |     union { | ||||||
|  | @ -1874,7 +1878,9 @@ public: | ||||||
|         HSETP2_C, |         HSETP2_C, | ||||||
|         HSETP2_R, |         HSETP2_R, | ||||||
|         HSETP2_IMM, |         HSETP2_IMM, | ||||||
|  |         HSET2_C, | ||||||
|         HSET2_R, |         HSET2_R, | ||||||
|  |         HSET2_IMM, | ||||||
|         POPC_C, |         POPC_C, | ||||||
|         POPC_R, |         POPC_R, | ||||||
|         POPC_IMM, |         POPC_IMM, | ||||||
|  | @ -2194,7 +2200,9 @@ private: | ||||||
|             INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), |             INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), | ||||||
|             INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), |             INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), | ||||||
|             INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), |             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("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("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), | ||||||
|             INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), |             INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), | ||||||
|             INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), |             INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | ||||||
|  |  | ||||||
|  | @ -13,55 +13,101 @@ | ||||||
| 
 | 
 | ||||||
| namespace VideoCommon::Shader { | namespace VideoCommon::Shader { | ||||||
| 
 | 
 | ||||||
|  | using std::move; | ||||||
| using Tegra::Shader::Instruction; | using Tegra::Shader::Instruction; | ||||||
| using Tegra::Shader::OpCode; | using Tegra::Shader::OpCode; | ||||||
|  | using Tegra::Shader::PredCondition; | ||||||
| 
 | 
 | ||||||
| u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { | u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { | ||||||
|     const Instruction instr = {program_code[pc]}; |     const Instruction instr = {program_code[pc]}; | ||||||
|     const auto opcode = OpCode::Decode(instr); |     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()); |         LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); |     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()) { | ||||||
|         switch (opcode->get().GetId()) { |     case OpCode::Id::HSET2_R: | ||||||
|         case OpCode::Id::HSET2_R: |         op_b = GetOperandAbsNegHalf(move(op_b), abs_b, neg_b); | ||||||
|             return GetRegister(instr.gpr20); |         [[fallthrough]]; | ||||||
|         default: |     case OpCode::Id::HSET2_C: | ||||||
|             UNREACHABLE(); |         op_b = UnpackHalfFloat(move(op_b), instr.hset2.type_b); | ||||||
|             return Immediate(0); |         break; | ||||||
|         } |     default: | ||||||
|     }(); |         break; | ||||||
|     op_b = UnpackHalfFloat(op_b, instr.hset2.type_b); |     } | ||||||
|     op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b); |  | ||||||
| 
 | 
 | ||||||
|     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); |     const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); | ||||||
| 
 | 
 | ||||||
|     // HSET2 operates on each half float in the pack.
 |     // HSET2 operates on each half float in the pack.
 | ||||||
|     std::array<Node, 2> values; |     std::array<Node, 2> values; | ||||||
|     for (u32 i = 0; i < 2; ++i) { |     for (u32 i = 0; i < 2; ++i) { | ||||||
|         const u32 raw_value = instr.hset2.bf ? 0x3c00 : 0xffff; |         const u32 raw_value = bf ? 0x3c00 : 0xffff; | ||||||
|         const Node true_value = Immediate(raw_value << (i * 16)); |         Node true_value = Immediate(raw_value << (i * 16)); | ||||||
|         const Node false_value = Immediate(0); |         Node false_value = Immediate(0); | ||||||
| 
 |  | ||||||
|         const Node comparison = |  | ||||||
|             Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); |  | ||||||
|         const Node predicate = Operation(combiner, comparison, second_pred); |  | ||||||
| 
 | 
 | ||||||
|  |         Node comparison = Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||||||
|  |         Node predicate = Operation(combiner, comparison, second_pred); | ||||||
|         values[i] = |         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]); |     Node value = Operation(OperationCode::UBitwiseOr, values[0], values[1]); | ||||||
|     SetRegister(bb, instr.gpr0, value); |     SetRegister(bb, instr.gpr0, move(value)); | ||||||
| 
 | 
 | ||||||
|     return pc; |     return pc; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bunnei
						bunnei