shader: Implement ISCADD32I
This commit is contained in:
		| @@ -8,40 +8,36 @@ | |||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
| namespace { | namespace { | ||||||
| void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b, bool cc, bool neg_a, bool neg_b, | ||||||
|  |             u64 scale_imm) { | ||||||
|     union { |     union { | ||||||
|         u64 raw; |         u64 raw; | ||||||
|         BitField<0, 8, IR::Reg> dest_reg; |         BitField<0, 8, IR::Reg> dest_reg; | ||||||
|         BitField<8, 8, IR::Reg> op_a; |         BitField<8, 8, IR::Reg> op_a; | ||||||
|         BitField<47, 1, u64> cc; |  | ||||||
|         BitField<48, 2, u64> three_for_po; |  | ||||||
|         BitField<48, 1, u64> neg_b; |  | ||||||
|         BitField<49, 1, u64> neg_a; |  | ||||||
|         BitField<39, 5, u64> scale; |  | ||||||
|     } const iscadd{insn}; |     } const iscadd{insn}; | ||||||
|  |  | ||||||
|     const bool po{iscadd.three_for_po == 3}; |     const bool po{neg_a && neg_b}; | ||||||
|     IR::U32 op_a{v.X(iscadd.op_a)}; |     IR::U32 op_a{v.X(iscadd.op_a)}; | ||||||
|     if (!po) { |     if (po) { | ||||||
|         // When PO is not present, the bits are interpreted as negation |  | ||||||
|         if (iscadd.neg_a != 0) { |  | ||||||
|             op_a = v.ir.INeg(op_a); |  | ||||||
|         } |  | ||||||
|         if (iscadd.neg_b != 0) { |  | ||||||
|             op_b = v.ir.INeg(op_b); |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         // When PO is present, add one |         // When PO is present, add one | ||||||
|         op_b = v.ir.IAdd(op_b, v.ir.Imm32(1)); |         op_b = v.ir.IAdd(op_b, v.ir.Imm32(1)); | ||||||
|  |     } else { | ||||||
|  |         // When PO is not present, the bits are interpreted as negation | ||||||
|  |         if (neg_a) { | ||||||
|  |             op_a = v.ir.INeg(op_a); | ||||||
|  |         } | ||||||
|  |         if (neg_b) { | ||||||
|  |             op_b = v.ir.INeg(op_b); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     // With the operands already processed, scale A |     // With the operands already processed, scale A | ||||||
|     const IR::U32 scale{v.ir.Imm32(static_cast<u32>(iscadd.scale))}; |     const IR::U32 scale{v.ir.Imm32(static_cast<u32>(scale_imm))}; | ||||||
|     const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)}; |     const IR::U32 scaled_a{v.ir.ShiftLeftLogical(op_a, scale)}; | ||||||
|  |  | ||||||
|     const IR::U32 result{v.ir.IAdd(scaled_a, op_b)}; |     const IR::U32 result{v.ir.IAdd(scaled_a, op_b)}; | ||||||
|     v.X(iscadd.dest_reg, result); |     v.X(iscadd.dest_reg, result); | ||||||
|  |  | ||||||
|     if (iscadd.cc != 0) { |     if (cc) { | ||||||
|         v.SetZFlag(v.ir.GetZeroFromOp(result)); |         v.SetZFlag(v.ir.GetZeroFromOp(result)); | ||||||
|         v.SetSFlag(v.ir.GetSignFromOp(result)); |         v.SetSFlag(v.ir.GetSignFromOp(result)); | ||||||
|         const IR::U1 carry{v.ir.GetCarryFromOp(result)}; |         const IR::U1 carry{v.ir.GetCarryFromOp(result)}; | ||||||
| @@ -51,6 +47,18 @@ void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void ISCADD(TranslatorVisitor& v, u64 insn, IR::U32 op_b) { | ||||||
|  |     union { | ||||||
|  |         u64 raw; | ||||||
|  |         BitField<47, 1, u64> cc; | ||||||
|  |         BitField<48, 1, u64> neg_b; | ||||||
|  |         BitField<49, 1, u64> neg_a; | ||||||
|  |         BitField<39, 5, u64> scale; | ||||||
|  |     } const iscadd{insn}; | ||||||
|  |  | ||||||
|  |     ISCADD(v, insn, op_b, iscadd.cc != 0, iscadd.neg_a != 0, iscadd.neg_b != 0, iscadd.scale); | ||||||
|  | } | ||||||
|  |  | ||||||
| } // Anonymous namespace | } // Anonymous namespace | ||||||
|  |  | ||||||
| void TranslatorVisitor::ISCADD_reg(u64 insn) { | void TranslatorVisitor::ISCADD_reg(u64 insn) { | ||||||
| @@ -65,8 +73,14 @@ void TranslatorVisitor::ISCADD_imm(u64 insn) { | |||||||
|     ISCADD(*this, insn, GetImm20(insn)); |     ISCADD(*this, insn, GetImm20(insn)); | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslatorVisitor::ISCADD32I(u64) { | void TranslatorVisitor::ISCADD32I(u64 insn) { | ||||||
|     throw NotImplementedException("ISCADD32I"); |     union { | ||||||
|  |         u64 raw; | ||||||
|  |         BitField<52, 1, u64> cc; | ||||||
|  |         BitField<53, 5, u64> scale; | ||||||
|  |     } const iscadd{insn}; | ||||||
|  |  | ||||||
|  |     return ISCADD(*this, insn, GetImm32(insn), iscadd.cc != 0, false, false, iscadd.scale); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Shader::Maxwell | } // namespace Shader::Maxwell | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ReinUsesLisp
					ReinUsesLisp