integer_funnel_shift.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/bit_field.h"
  4. #include "common/common_types.h"
  5. #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
  6. namespace Shader::Maxwell {
  7. namespace {
  8. enum class MaxShift : u64 {
  9. U32,
  10. Undefined,
  11. U64,
  12. S64,
  13. };
  14. IR::U64 PackedShift(IR::IREmitter& ir, const IR::U64& packed_int, const IR::U32& safe_shift,
  15. bool right_shift, bool is_signed) {
  16. if (!right_shift) {
  17. return ir.ShiftLeftLogical(packed_int, safe_shift);
  18. }
  19. if (is_signed) {
  20. return ir.ShiftRightArithmetic(packed_int, safe_shift);
  21. }
  22. return ir.ShiftRightLogical(packed_int, safe_shift);
  23. }
  24. void SHF(TranslatorVisitor& v, u64 insn, const IR::U32& shift, const IR::U32& high_bits,
  25. bool right_shift) {
  26. union {
  27. u64 insn;
  28. BitField<0, 8, IR::Reg> dest_reg;
  29. BitField<8, 8, IR::Reg> lo_bits_reg;
  30. BitField<37, 2, MaxShift> max_shift;
  31. BitField<47, 1, u64> cc;
  32. BitField<48, 2, u64> x_mode;
  33. BitField<50, 1, u64> wrap;
  34. } const shf{insn};
  35. if (shf.cc != 0) {
  36. throw NotImplementedException("SHF CC");
  37. }
  38. if (shf.x_mode != 0) {
  39. throw NotImplementedException("SHF X Mode");
  40. }
  41. if (shf.max_shift == MaxShift::Undefined) {
  42. throw NotImplementedException("SHF Use of undefined MaxShift value");
  43. }
  44. const IR::U32 low_bits{v.X(shf.lo_bits_reg)};
  45. const IR::U64 packed_int{v.ir.PackUint2x32(v.ir.CompositeConstruct(low_bits, high_bits))};
  46. const IR::U32 max_shift{shf.max_shift == MaxShift::U32 ? v.ir.Imm32(32) : v.ir.Imm32(63)};
  47. const IR::U32 safe_shift{shf.wrap != 0
  48. ? v.ir.BitwiseAnd(shift, v.ir.ISub(max_shift, v.ir.Imm32(1)))
  49. : v.ir.UMin(shift, max_shift)};
  50. const bool is_signed{shf.max_shift == MaxShift::S64};
  51. const IR::U64 shifted_value{PackedShift(v.ir, packed_int, safe_shift, right_shift, is_signed)};
  52. const IR::Value unpacked_value{v.ir.UnpackUint2x32(shifted_value)};
  53. const IR::U32 result{v.ir.CompositeExtract(unpacked_value, right_shift ? 0 : 1)};
  54. v.X(shf.dest_reg, result);
  55. }
  56. } // Anonymous namespace
  57. void TranslatorVisitor::SHF_l_reg(u64 insn) {
  58. SHF(*this, insn, GetReg20(insn), GetReg39(insn), false);
  59. }
  60. void TranslatorVisitor::SHF_l_imm(u64 insn) {
  61. SHF(*this, insn, GetImm20(insn), GetReg39(insn), false);
  62. }
  63. void TranslatorVisitor::SHF_r_reg(u64 insn) {
  64. SHF(*this, insn, GetReg20(insn), GetReg39(insn), true);
  65. }
  66. void TranslatorVisitor::SHF_r_imm(u64 insn) {
  67. SHF(*this, insn, GetImm20(insn), GetReg39(insn), true);
  68. }
  69. } // namespace Shader::Maxwell