InstEmitCcmp.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. using ChocolArm64.Decoders;
  2. using ChocolArm64.IntermediateRepresentation;
  3. using ChocolArm64.State;
  4. using ChocolArm64.Translation;
  5. using System;
  6. using System.Reflection.Emit;
  7. using static ChocolArm64.Instructions.InstEmitAluHelper;
  8. namespace ChocolArm64.Instructions
  9. {
  10. static partial class InstEmit
  11. {
  12. private enum CcmpOp
  13. {
  14. Cmp,
  15. Cmn
  16. }
  17. public static void Ccmn(ILEmitterCtx context) => EmitCcmp(context, CcmpOp.Cmn);
  18. public static void Ccmp(ILEmitterCtx context) => EmitCcmp(context, CcmpOp.Cmp);
  19. private static void EmitCcmp(ILEmitterCtx context, CcmpOp cmpOp)
  20. {
  21. OpCodeCcmp64 op = (OpCodeCcmp64)context.CurrOp;
  22. ILLabel lblTrue = new ILLabel();
  23. ILLabel lblEnd = new ILLabel();
  24. context.EmitCondBranch(lblTrue, op.Cond);
  25. context.EmitLdc_I4((op.Nzcv >> 0) & 1);
  26. context.EmitStflg((int)PState.VBit);
  27. context.EmitLdc_I4((op.Nzcv >> 1) & 1);
  28. context.EmitStflg((int)PState.CBit);
  29. context.EmitLdc_I4((op.Nzcv >> 2) & 1);
  30. context.EmitStflg((int)PState.ZBit);
  31. context.EmitLdc_I4((op.Nzcv >> 3) & 1);
  32. context.EmitStflg((int)PState.NBit);
  33. context.Emit(OpCodes.Br_S, lblEnd);
  34. context.MarkLabel(lblTrue);
  35. EmitAluLoadOpers(context);
  36. if (cmpOp == CcmpOp.Cmp)
  37. {
  38. context.Emit(OpCodes.Sub);
  39. context.EmitZnFlagCheck();
  40. EmitSubsCCheck(context);
  41. EmitSubsVCheck(context);
  42. }
  43. else if (cmpOp == CcmpOp.Cmn)
  44. {
  45. context.Emit(OpCodes.Add);
  46. context.EmitZnFlagCheck();
  47. EmitAddsCCheck(context);
  48. EmitAddsVCheck(context);
  49. }
  50. else
  51. {
  52. throw new ArgumentException(nameof(cmpOp));
  53. }
  54. context.Emit(OpCodes.Pop);
  55. context.MarkLabel(lblEnd);
  56. }
  57. }
  58. }