InstEmitCsel.cs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.IntermediateRepresentation;
  3. using ChocolArm64.Translation;
  4. using System.Reflection.Emit;
  5. namespace ChocolArm64.Instructions
  6. {
  7. static partial class InstEmit
  8. {
  9. private enum CselOperation
  10. {
  11. None,
  12. Increment,
  13. Invert,
  14. Negate
  15. }
  16. public static void Csel(ILEmitterCtx context) => EmitCsel(context, CselOperation.None);
  17. public static void Csinc(ILEmitterCtx context) => EmitCsel(context, CselOperation.Increment);
  18. public static void Csinv(ILEmitterCtx context) => EmitCsel(context, CselOperation.Invert);
  19. public static void Csneg(ILEmitterCtx context) => EmitCsel(context, CselOperation.Negate);
  20. private static void EmitCsel(ILEmitterCtx context, CselOperation cselOp)
  21. {
  22. OpCodeCsel64 op = (OpCodeCsel64)context.CurrOp;
  23. ILLabel lblTrue = new ILLabel();
  24. ILLabel lblEnd = new ILLabel();
  25. context.EmitCondBranch(lblTrue, op.Cond);
  26. context.EmitLdintzr(op.Rm);
  27. if (cselOp == CselOperation.Increment)
  28. {
  29. context.EmitLdc_I(1);
  30. context.Emit(OpCodes.Add);
  31. }
  32. else if (cselOp == CselOperation.Invert)
  33. {
  34. context.Emit(OpCodes.Not);
  35. }
  36. else if (cselOp == CselOperation.Negate)
  37. {
  38. context.Emit(OpCodes.Neg);
  39. }
  40. context.Emit(OpCodes.Br_S, lblEnd);
  41. context.MarkLabel(lblTrue);
  42. context.EmitLdintzr(op.Rn);
  43. context.MarkLabel(lblEnd);
  44. context.EmitStintzr(op.Rd);
  45. }
  46. }
  47. }