InstEmitMul.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. using ARMeilleure.Decoders;
  2. using ARMeilleure.IntermediateRepresentation;
  3. using ARMeilleure.Translation;
  4. using System;
  5. using static ARMeilleure.Instructions.InstEmitHelper;
  6. namespace ARMeilleure.Instructions
  7. {
  8. static partial class InstEmit
  9. {
  10. public static void Madd(ArmEmitterContext context) => EmitMul(context, isAdd: true);
  11. public static void Msub(ArmEmitterContext context) => EmitMul(context, isAdd: false);
  12. private static void EmitMul(ArmEmitterContext context, bool isAdd)
  13. {
  14. OpCodeMul op = (OpCodeMul)context.CurrOp;
  15. Operand a = GetIntOrZR(context, op.Ra);
  16. Operand n = GetIntOrZR(context, op.Rn);
  17. Operand m = GetIntOrZR(context, op.Rm);
  18. Operand res = context.Multiply(n, m);
  19. res = isAdd ? context.Add(a, res) : context.Subtract(a, res);
  20. SetIntOrZR(context, op.Rd, res);
  21. }
  22. public static void Smaddl(ArmEmitterContext context) => EmitMull(context, MullFlags.SignedAdd);
  23. public static void Smsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.SignedSubtract);
  24. public static void Umaddl(ArmEmitterContext context) => EmitMull(context, MullFlags.Add);
  25. public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
  26. [Flags]
  27. private enum MullFlags
  28. {
  29. Subtract = 0,
  30. Add = 1 << 0,
  31. Signed = 1 << 1,
  32. SignedAdd = Signed | Add,
  33. SignedSubtract = Signed | Subtract
  34. }
  35. private static void EmitMull(ArmEmitterContext context, MullFlags flags)
  36. {
  37. OpCodeMul op = (OpCodeMul)context.CurrOp;
  38. Operand GetExtendedRegister32(int index)
  39. {
  40. Operand value = GetIntOrZR(context, index);
  41. if ((flags & MullFlags.Signed) != 0)
  42. {
  43. return context.SignExtend32(value.Type, value);
  44. }
  45. else
  46. {
  47. return context.ZeroExtend32(value.Type, value);
  48. }
  49. }
  50. Operand a = GetIntOrZR(context, op.Ra);
  51. Operand n = GetExtendedRegister32(op.Rn);
  52. Operand m = GetExtendedRegister32(op.Rm);
  53. Operand res = context.Multiply(n, m);
  54. res = (flags & MullFlags.Add) != 0 ? context.Add(a, res) : context.Subtract(a, res);
  55. SetIntOrZR(context, op.Rd, res);
  56. }
  57. public static void Smulh(ArmEmitterContext context)
  58. {
  59. OpCodeMul op = (OpCodeMul)context.CurrOp;
  60. Operand n = GetIntOrZR(context, op.Rn);
  61. Operand m = GetIntOrZR(context, op.Rm);
  62. Operand d = context.Multiply64HighSI(n, m);
  63. SetIntOrZR(context, op.Rd, d);
  64. }
  65. public static void Umulh(ArmEmitterContext context)
  66. {
  67. OpCodeMul op = (OpCodeMul)context.CurrOp;
  68. Operand n = GetIntOrZR(context, op.Rn);
  69. Operand m = GetIntOrZR(context, op.Rm);
  70. Operand d = context.Multiply64HighUI(n, m);
  71. SetIntOrZR(context, op.Rd, d);
  72. }
  73. }
  74. }