InstEmitCsel.cs 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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. private enum CselOperation
  9. {
  10. None,
  11. Increment,
  12. Invert,
  13. Negate
  14. }
  15. public static void Csel(ILEmitterCtx context) => EmitCsel(context, CselOperation.None);
  16. public static void Csinc(ILEmitterCtx context) => EmitCsel(context, CselOperation.Increment);
  17. public static void Csinv(ILEmitterCtx context) => EmitCsel(context, CselOperation.Invert);
  18. public static void Csneg(ILEmitterCtx context) => EmitCsel(context, CselOperation.Negate);
  19. private static void EmitCsel(ILEmitterCtx context, CselOperation cselOp)
  20. {
  21. OpCodeCsel64 op = (OpCodeCsel64)context.CurrOp;
  22. ILLabel lblTrue = new ILLabel();
  23. ILLabel lblEnd = new ILLabel();
  24. context.EmitCondBranch(lblTrue, op.Cond);
  25. context.EmitLdintzr(op.Rm);
  26. if (cselOp == CselOperation.Increment)
  27. {
  28. context.EmitLdc_I(1);
  29. context.Emit(OpCodes.Add);
  30. }
  31. else if (cselOp == CselOperation.Invert)
  32. {
  33. context.Emit(OpCodes.Not);
  34. }
  35. else if (cselOp == CselOperation.Negate)
  36. {
  37. context.Emit(OpCodes.Neg);
  38. }
  39. context.Emit(OpCodes.Br_S, lblEnd);
  40. context.MarkLabel(lblTrue);
  41. context.EmitLdintzr(op.Rn);
  42. context.MarkLabel(lblEnd);
  43. context.EmitStintzr(op.Rd);
  44. }
  45. }
  46. }