integer_compare.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/bit_field.h"
  5. #include "common/common_types.h"
  6. #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
  7. namespace Shader::Maxwell {
  8. namespace {
  9. enum class ComparisonOp : u64 {
  10. False,
  11. LessThan,
  12. Equal,
  13. LessThanEqual,
  14. GreaterThan,
  15. NotEqual,
  16. GreaterThanEqual,
  17. True,
  18. };
  19. [[nodiscard]] IR::U1 CompareToZero(TranslatorVisitor& v, const IR::U32& operand,
  20. ComparisonOp compare_op, bool is_signed) {
  21. const IR::U32 zero{v.ir.Imm32(0)};
  22. switch (compare_op) {
  23. case ComparisonOp::False:
  24. return v.ir.Imm1(false);
  25. case ComparisonOp::LessThan:
  26. return v.ir.ILessThan(operand, zero, is_signed);
  27. case ComparisonOp::Equal:
  28. return v.ir.IEqual(operand, zero);
  29. case ComparisonOp::LessThanEqual:
  30. return v.ir.ILessThanEqual(operand, zero, is_signed);
  31. case ComparisonOp::GreaterThan:
  32. return v.ir.IGreaterThan(operand, zero, is_signed);
  33. case ComparisonOp::NotEqual:
  34. return v.ir.INotEqual(operand, zero);
  35. case ComparisonOp::GreaterThanEqual:
  36. return v.ir.IGreaterThanEqual(operand, zero, is_signed);
  37. case ComparisonOp::True:
  38. return v.ir.Imm1(true);
  39. default:
  40. throw NotImplementedException("ICMP.CMP");
  41. }
  42. }
  43. void ICMP(TranslatorVisitor& v, u64 insn, const IR::U32& src_a, const IR::U32& operand) {
  44. union {
  45. u64 insn;
  46. BitField<0, 8, IR::Reg> dest_reg;
  47. BitField<8, 8, IR::Reg> src_reg;
  48. BitField<48, 1, u64> is_signed;
  49. BitField<49, 3, ComparisonOp> compare_op;
  50. } const icmp{insn};
  51. const IR::U32 zero{v.ir.Imm32(0)};
  52. const bool is_signed{icmp.is_signed != 0};
  53. const IR::U1 cmp_result{CompareToZero(v, operand, icmp.compare_op, is_signed)};
  54. const IR::U32 src_reg{v.X(icmp.src_reg)};
  55. const IR::U32 result{v.ir.Select(cmp_result, src_reg, src_a)};
  56. v.X(icmp.dest_reg, result);
  57. }
  58. } // Anonymous namespace
  59. void TranslatorVisitor::ICMP_reg(u64 insn) {
  60. ICMP(*this, insn, GetReg20(insn), GetReg39(insn));
  61. }
  62. void TranslatorVisitor::ICMP_rc(u64 insn) {
  63. ICMP(*this, insn, GetReg39(insn), GetCbuf(insn));
  64. }
  65. void TranslatorVisitor::ICMP_cr(u64 insn) {
  66. ICMP(*this, insn, GetCbuf(insn), GetReg39(insn));
  67. }
  68. void TranslatorVisitor::ICMP_imm(u64 insn) {
  69. ICMP(*this, insn, GetImm20(insn), GetReg39(insn));
  70. }
  71. } // namespace Shader::Maxwell