ILOpCodeStoreState.cs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using ChocolArm64.State;
  2. using System.Reflection.Emit;
  3. namespace ChocolArm64.Translation
  4. {
  5. struct ILOpCodeStoreState : IILEmit
  6. {
  7. private ILBlock _block;
  8. private TranslatedSub _callSub;
  9. public ILOpCodeStoreState(ILBlock block, TranslatedSub callSub = null)
  10. {
  11. _block = block;
  12. _callSub = callSub;
  13. }
  14. public void Emit(ILMethodBuilder context)
  15. {
  16. long intOutputs = context.RegUsage.GetIntOutputs(_block);
  17. long vecOutputs = context.RegUsage.GetVecOutputs(_block);
  18. if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete)
  19. {
  20. intOutputs = RegisterUsage.ClearCallerSavedIntRegs(intOutputs, context.IsAarch64);
  21. vecOutputs = RegisterUsage.ClearCallerSavedVecRegs(vecOutputs, context.IsAarch64);
  22. }
  23. if (_callSub != null)
  24. {
  25. //Those register are assigned on the callee function, without
  26. //reading it's value first. We don't need to write them because
  27. //they are not going to be read on the callee.
  28. intOutputs &= ~_callSub.IntNiRegsMask;
  29. vecOutputs &= ~_callSub.VecNiRegsMask;
  30. }
  31. StoreLocals(context, intOutputs, RegisterType.Int);
  32. StoreLocals(context, vecOutputs, RegisterType.Vector);
  33. }
  34. private void StoreLocals(ILMethodBuilder context, long outputs, RegisterType baseType)
  35. {
  36. for (int bit = 0; bit < 64; bit++)
  37. {
  38. long mask = 1L << bit;
  39. if ((outputs & mask) != 0)
  40. {
  41. Register reg = ILMethodBuilder.GetRegFromBit(bit, baseType);
  42. context.Generator.EmitLdarg(TranslatedSub.StateArgIdx);
  43. context.Generator.EmitLdloc(context.GetLocalIndex(reg));
  44. context.Generator.Emit(OpCodes.Stfld, reg.GetField());
  45. }
  46. }
  47. }
  48. }
  49. }