InstEmitBfm.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using static ARMeilleure.Instructions.InstEmitHelper;
  5. using static ARMeilleure.IntermediateRepresentation.OperandHelper;
  6. namespace ARMeilleure.Instructions
  7. {
  8. static partial class InstEmit
  9. {
  10. public static void Bfm(ArmEmitterContext context)
  11. {
  12. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  13. Operand d = GetIntOrZR(context, op.Rd);
  14. Operand n = GetIntOrZR(context, op.Rn);
  15. Operand res;
  16. if (op.Pos < op.Shift)
  17. {
  18. // BFI.
  19. int shift = op.GetBitsCount() - op.Shift;
  20. int width = op.Pos + 1;
  21. long mask = (long)(ulong.MaxValue >> (64 - width));
  22. res = context.ShiftLeft(context.BitwiseAnd(n, Const(n.Type, mask)), Const(shift));
  23. res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~(mask << shift))));
  24. }
  25. else
  26. {
  27. // BFXIL.
  28. int shift = op.Shift;
  29. int width = op.Pos - shift + 1;
  30. long mask = (long)(ulong.MaxValue >> (64 - width));
  31. res = context.BitwiseAnd(context.ShiftRightUI(n, Const(shift)), Const(n.Type, mask));
  32. res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~mask)));
  33. }
  34. SetIntOrZR(context, op.Rd, res);
  35. }
  36. public static void Sbfm(ArmEmitterContext context)
  37. {
  38. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  39. int bitsCount = op.GetBitsCount();
  40. if (op.Pos + 1 == bitsCount)
  41. {
  42. EmitSbfmShift(context);
  43. }
  44. else if (op.Pos < op.Shift)
  45. {
  46. EmitSbfiz(context);
  47. }
  48. else if (op.Pos == 7 && op.Shift == 0)
  49. {
  50. Operand n = GetIntOrZR(context, op.Rn);
  51. SetIntOrZR(context, op.Rd, context.SignExtend8(n.Type, n));
  52. }
  53. else if (op.Pos == 15 && op.Shift == 0)
  54. {
  55. Operand n = GetIntOrZR(context, op.Rn);
  56. SetIntOrZR(context, op.Rd, context.SignExtend16(n.Type, n));
  57. }
  58. else if (op.Pos == 31 && op.Shift == 0)
  59. {
  60. Operand n = GetIntOrZR(context, op.Rn);
  61. SetIntOrZR(context, op.Rd, context.SignExtend32(n.Type, n));
  62. }
  63. else
  64. {
  65. Operand res = GetIntOrZR(context, op.Rn);
  66. res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
  67. res = context.ShiftRightSI(res, Const(bitsCount - 1));
  68. res = context.BitwiseAnd (res, Const(res.Type, ~op.TMask));
  69. Operand n2 = GetBfmN(context);
  70. SetIntOrZR(context, op.Rd, context.BitwiseOr(res, n2));
  71. }
  72. }
  73. public static void Ubfm(ArmEmitterContext context)
  74. {
  75. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  76. if (op.Pos + 1 == op.GetBitsCount())
  77. {
  78. EmitUbfmShift(context);
  79. }
  80. else if (op.Pos < op.Shift)
  81. {
  82. EmitUbfiz(context);
  83. }
  84. else if (op.Pos + 1 == op.Shift)
  85. {
  86. EmitBfmLsl(context);
  87. }
  88. else if (op.Pos == 7 && op.Shift == 0)
  89. {
  90. Operand n = GetIntOrZR(context, op.Rn);
  91. SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xff)));
  92. }
  93. else if (op.Pos == 15 && op.Shift == 0)
  94. {
  95. Operand n = GetIntOrZR(context, op.Rn);
  96. SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xffff)));
  97. }
  98. else
  99. {
  100. SetIntOrZR(context, op.Rd, GetBfmN(context));
  101. }
  102. }
  103. private static void EmitSbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: true);
  104. private static void EmitUbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: false);
  105. private static void EmitBfiz(ArmEmitterContext context, bool signed)
  106. {
  107. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  108. int width = op.Pos + 1;
  109. Operand res = GetIntOrZR(context, op.Rn);
  110. res = context.ShiftLeft(res, Const(op.GetBitsCount() - width));
  111. res = signed
  112. ? context.ShiftRightSI(res, Const(op.Shift - width))
  113. : context.ShiftRightUI(res, Const(op.Shift - width));
  114. SetIntOrZR(context, op.Rd, res);
  115. }
  116. private static void EmitSbfmShift(ArmEmitterContext context)
  117. {
  118. EmitBfmShift(context, signed: true);
  119. }
  120. private static void EmitUbfmShift(ArmEmitterContext context)
  121. {
  122. EmitBfmShift(context, signed: false);
  123. }
  124. private static void EmitBfmShift(ArmEmitterContext context, bool signed)
  125. {
  126. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  127. Operand res = GetIntOrZR(context, op.Rn);
  128. res = signed
  129. ? context.ShiftRightSI(res, Const(op.Shift))
  130. : context.ShiftRightUI(res, Const(op.Shift));
  131. SetIntOrZR(context, op.Rd, res);
  132. }
  133. private static void EmitBfmLsl(ArmEmitterContext context)
  134. {
  135. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  136. Operand res = GetIntOrZR(context, op.Rn);
  137. int shift = op.GetBitsCount() - op.Shift;
  138. SetIntOrZR(context, op.Rd, context.ShiftLeft(res, Const(shift)));
  139. }
  140. private static Operand GetBfmN(ArmEmitterContext context)
  141. {
  142. OpCodeBfm op = (OpCodeBfm)context.CurrOp;
  143. Operand res = GetIntOrZR(context, op.Rn);
  144. long mask = op.WMask & op.TMask;
  145. return context.BitwiseAnd(context.RotateRight(res, Const(op.Shift)), Const(res.Type, mask));
  146. }
  147. }
  148. }