InstEmitMul.cs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.Translation;
  3. using System.Reflection.Emit;
  4. namespace ChocolArm64.Instructions
  5. {
  6. static partial class InstEmit
  7. {
  8. public static void Madd(ILEmitterCtx context) => EmitMul(context, OpCodes.Add);
  9. public static void Msub(ILEmitterCtx context) => EmitMul(context, OpCodes.Sub);
  10. private static void EmitMul(ILEmitterCtx context, OpCode ilOp)
  11. {
  12. OpCodeMul64 op = (OpCodeMul64)context.CurrOp;
  13. context.EmitLdintzr(op.Ra);
  14. context.EmitLdintzr(op.Rn);
  15. context.EmitLdintzr(op.Rm);
  16. context.Emit(OpCodes.Mul);
  17. context.Emit(ilOp);
  18. context.EmitStintzr(op.Rd);
  19. }
  20. public static void Smaddl(ILEmitterCtx context) => EmitMull(context, OpCodes.Add, true);
  21. public static void Smsubl(ILEmitterCtx context) => EmitMull(context, OpCodes.Sub, true);
  22. public static void Umaddl(ILEmitterCtx context) => EmitMull(context, OpCodes.Add, false);
  23. public static void Umsubl(ILEmitterCtx context) => EmitMull(context, OpCodes.Sub, false);
  24. private static void EmitMull(ILEmitterCtx context, OpCode addSubOp, bool signed)
  25. {
  26. OpCodeMul64 op = (OpCodeMul64)context.CurrOp;
  27. OpCode castOp = signed
  28. ? OpCodes.Conv_I8
  29. : OpCodes.Conv_U8;
  30. context.EmitLdintzr(op.Ra);
  31. context.EmitLdintzr(op.Rn);
  32. context.Emit(OpCodes.Conv_I4);
  33. context.Emit(castOp);
  34. context.EmitLdintzr(op.Rm);
  35. context.Emit(OpCodes.Conv_I4);
  36. context.Emit(castOp);
  37. context.Emit(OpCodes.Mul);
  38. context.Emit(addSubOp);
  39. context.EmitStintzr(op.Rd);
  40. }
  41. public static void Smulh(ILEmitterCtx context)
  42. {
  43. OpCodeMul64 op = (OpCodeMul64)context.CurrOp;
  44. context.EmitLdintzr(op.Rn);
  45. context.EmitLdintzr(op.Rm);
  46. SoftFallback.EmitCall(context, nameof(SoftFallback.SMulHi128));
  47. context.EmitStintzr(op.Rd);
  48. }
  49. public static void Umulh(ILEmitterCtx context)
  50. {
  51. OpCodeMul64 op = (OpCodeMul64)context.CurrOp;
  52. context.EmitLdintzr(op.Rn);
  53. context.EmitLdintzr(op.Rm);
  54. SoftFallback.EmitCall(context, nameof(SoftFallback.UMulHi128));
  55. context.EmitStintzr(op.Rd);
  56. }
  57. }
  58. }