load_effective_address.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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 LEA_hi(TranslatorVisitor& v, u64 insn, const IR::U32& base, IR::U32 offset_hi, u64 scale,
  10. bool neg, bool x) {
  11. union {
  12. u64 insn;
  13. BitField<0, 8, IR::Reg> dest_reg;
  14. BitField<8, 8, IR::Reg> offset_lo_reg;
  15. BitField<47, 1, u64> cc;
  16. BitField<48, 3, IR::Pred> pred;
  17. } const lea{insn};
  18. if (x) {
  19. throw NotImplementedException("LEA.HI X");
  20. }
  21. if (lea.pred != IR::Pred::PT) {
  22. throw NotImplementedException("LEA.HI Pred");
  23. }
  24. if (lea.cc != 0) {
  25. throw NotImplementedException("LEA.HI CC");
  26. }
  27. const IR::U32 offset_lo{v.X(lea.offset_lo_reg)};
  28. const IR::U64 packed_offset{v.ir.PackUint2x32(v.ir.CompositeConstruct(offset_lo, offset_hi))};
  29. const IR::U64 offset{neg ? IR::U64{v.ir.INeg(packed_offset)} : packed_offset};
  30. const s32 hi_scale{32 - static_cast<s32>(scale)};
  31. const IR::U64 scaled_offset{v.ir.ShiftRightLogical(offset, v.ir.Imm32(hi_scale))};
  32. const IR::U32 scaled_offset_w0{v.ir.CompositeExtract(v.ir.UnpackUint2x32(scaled_offset), 0)};
  33. IR::U32 result{v.ir.IAdd(base, scaled_offset_w0)};
  34. v.X(lea.dest_reg, result);
  35. }
  36. void LEA_lo(TranslatorVisitor& v, u64 insn, const IR::U32& base) {
  37. union {
  38. u64 insn;
  39. BitField<0, 8, IR::Reg> dest_reg;
  40. BitField<8, 8, IR::Reg> offset_lo_reg;
  41. BitField<39, 5, u64> scale;
  42. BitField<45, 1, u64> neg;
  43. BitField<46, 1, u64> x;
  44. BitField<47, 1, u64> cc;
  45. BitField<48, 3, IR::Pred> pred;
  46. } const lea{insn};
  47. if (lea.x != 0) {
  48. throw NotImplementedException("LEA.LO X");
  49. }
  50. if (lea.pred != IR::Pred::PT) {
  51. throw NotImplementedException("LEA.LO Pred");
  52. }
  53. if (lea.cc != 0) {
  54. throw NotImplementedException("LEA.LO CC");
  55. }
  56. const IR::U32 offset_lo{v.X(lea.offset_lo_reg)};
  57. const s32 scale{static_cast<s32>(lea.scale)};
  58. const IR::U32 offset{lea.neg != 0 ? IR::U32{v.ir.INeg(offset_lo)} : offset_lo};
  59. const IR::U32 scaled_offset{v.ir.ShiftLeftLogical(offset, v.ir.Imm32(scale))};
  60. IR::U32 result{v.ir.IAdd(base, scaled_offset)};
  61. v.X(lea.dest_reg, result);
  62. }
  63. } // Anonymous namespace
  64. void TranslatorVisitor::LEA_hi_reg(u64 insn) {
  65. union {
  66. u64 insn;
  67. BitField<28, 5, u64> scale;
  68. BitField<37, 1, u64> neg;
  69. BitField<38, 1, u64> x;
  70. } const lea{insn};
  71. LEA_hi(*this, insn, GetReg20(insn), GetReg39(insn), lea.scale, lea.neg != 0, lea.x != 0);
  72. }
  73. void TranslatorVisitor::LEA_hi_cbuf(u64 insn) {
  74. union {
  75. u64 insn;
  76. BitField<51, 5, u64> scale;
  77. BitField<56, 1, u64> neg;
  78. BitField<57, 1, u64> x;
  79. } const lea{insn};
  80. LEA_hi(*this, insn, GetCbuf(insn), GetReg39(insn), lea.scale, lea.neg != 0, lea.x != 0);
  81. }
  82. void TranslatorVisitor::LEA_lo_reg(u64 insn) {
  83. LEA_lo(*this, insn, GetReg20(insn));
  84. }
  85. void TranslatorVisitor::LEA_lo_cbuf(u64 insn) {
  86. LEA_lo(*this, insn, GetCbuf(insn));
  87. }
  88. void TranslatorVisitor::LEA_lo_imm(u64 insn) {
  89. LEA_lo(*this, insn, GetImm20(insn));
  90. }
  91. } // namespace Shader::Maxwell