integer_shift_right.cpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  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. void SHR(TranslatorVisitor& v, u64 insn, const IR::U32& shift) {
  10. union {
  11. u64 insn;
  12. BitField<0, 8, IR::Reg> dest_reg;
  13. BitField<8, 8, IR::Reg> src_reg_a;
  14. BitField<39, 1, u64> is_wrapped;
  15. BitField<40, 1, u64> brev;
  16. BitField<43, 1, u64> xmode;
  17. BitField<48, 1, u64> is_signed;
  18. } const shr{insn};
  19. if (shr.xmode != 0) {
  20. throw NotImplementedException("SHR.XMODE");
  21. }
  22. IR::U32 base{v.X(shr.src_reg_a)};
  23. if (shr.brev == 1) {
  24. base = v.ir.BitReverse(base);
  25. }
  26. IR::U32 result;
  27. const IR::U32 safe_shift = shr.is_wrapped == 0 ? shift : v.ir.BitwiseAnd(shift, v.ir.Imm32(31));
  28. if (shr.is_signed == 1) {
  29. result = IR::U32{v.ir.ShiftRightArithmetic(base, safe_shift)};
  30. } else {
  31. result = IR::U32{v.ir.ShiftRightLogical(base, safe_shift)};
  32. }
  33. if (shr.is_wrapped == 0) {
  34. const IR::U32 zero{v.ir.Imm32(0)};
  35. const IR::U32 safe_bits{v.ir.Imm32(32)};
  36. const IR::U1 is_negative{v.ir.ILessThan(result, zero, true)};
  37. const IR::U1 is_safe{v.ir.ILessThan(shift, safe_bits, false)};
  38. const IR::U32 clamped_value{v.ir.Select(is_negative, v.ir.Imm32(-1), zero)};
  39. result = IR::U32{v.ir.Select(is_safe, result, clamped_value)};
  40. }
  41. v.X(shr.dest_reg, result);
  42. }
  43. } // Anonymous namespace
  44. void TranslatorVisitor::SHR_reg(u64 insn) {
  45. SHR(*this, insn, GetReg20(insn));
  46. }
  47. void TranslatorVisitor::SHR_cbuf(u64 insn) {
  48. SHR(*this, insn, GetCbuf(insn));
  49. }
  50. void TranslatorVisitor::SHR_imm(u64 insn) {
  51. SHR(*this, insn, GetImm20(insn));
  52. }
  53. } // namespace Shader::Maxwell