InstEmitDiv.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using static ARMeilleure.Instructions.InstEmitHelper;
  5. using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
  6. namespace ARMeilleure.Instructions
  7. {
  8. static partial class InstEmit
  9. {
  10. public static void Sdiv(ArmEmitterContext context) => EmitDiv(context, unsigned: false);
  11. public static void Udiv(ArmEmitterContext context) => EmitDiv(context, unsigned: true);
  12. private static void EmitDiv(ArmEmitterContext context, bool unsigned)
  13. {
  14. OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;
  15. // If Rm == 0, Rd = 0 (division by zero).
  16. Operand n = GetIntOrZR(context, op.Rn);
  17. Operand m = GetIntOrZR(context, op.Rm);
  18. Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0));
  19. Operand lblBadDiv = Label();
  20. Operand lblEnd = Label();
  21. context.BranchIfTrue(lblBadDiv, divisorIsZero);
  22. if (!unsigned)
  23. {
  24. // If Rn == INT_MIN && Rm == -1, Rd = INT_MIN (overflow).
  25. bool is32Bits = op.RegisterSize == RegisterSize.Int32;
  26. Operand intMin = is32Bits ? Const(int.MinValue) : Const(long.MinValue);
  27. Operand minus1 = is32Bits ? Const(-1) : Const(-1L);
  28. Operand nIsIntMin = context.ICompareEqual(n, intMin);
  29. Operand mIsMinus1 = context.ICompareEqual(m, minus1);
  30. Operand lblGoodDiv = Label();
  31. context.BranchIfFalse(lblGoodDiv, context.BitwiseAnd(nIsIntMin, mIsMinus1));
  32. SetAluDOrZR(context, intMin);
  33. context.Branch(lblEnd);
  34. context.MarkLabel(lblGoodDiv);
  35. }
  36. Operand d = unsigned
  37. ? context.DivideUI(n, m)
  38. : context.Divide (n, m);
  39. SetAluDOrZR(context, d);
  40. context.Branch(lblEnd);
  41. context.MarkLabel(lblBadDiv);
  42. SetAluDOrZR(context, Const(op.GetOperandType(), 0));
  43. context.MarkLabel(lblEnd);
  44. }
  45. }
  46. }