CallingConvention.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace ARMeilleure.CodeGen.X86
  4. {
  5. static class CallingConvention
  6. {
  7. private const int RegistersMask = 0xffff;
  8. public static int GetIntAvailableRegisters()
  9. {
  10. return RegistersMask & ~(1 << (int)X86Register.Rsp);
  11. }
  12. public static int GetVecAvailableRegisters()
  13. {
  14. return RegistersMask;
  15. }
  16. public static int GetIntCallerSavedRegisters()
  17. {
  18. if (GetCurrentCallConv() == CallConvName.Windows)
  19. {
  20. return (1 << (int)X86Register.Rax) |
  21. (1 << (int)X86Register.Rcx) |
  22. (1 << (int)X86Register.Rdx) |
  23. (1 << (int)X86Register.R8) |
  24. (1 << (int)X86Register.R9) |
  25. (1 << (int)X86Register.R10) |
  26. (1 << (int)X86Register.R11);
  27. }
  28. else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
  29. {
  30. return (1 << (int)X86Register.Rax) |
  31. (1 << (int)X86Register.Rcx) |
  32. (1 << (int)X86Register.Rdx) |
  33. (1 << (int)X86Register.Rsi) |
  34. (1 << (int)X86Register.Rdi) |
  35. (1 << (int)X86Register.R8) |
  36. (1 << (int)X86Register.R9) |
  37. (1 << (int)X86Register.R10) |
  38. (1 << (int)X86Register.R11);
  39. }
  40. }
  41. public static int GetVecCallerSavedRegisters()
  42. {
  43. if (GetCurrentCallConv() == CallConvName.Windows)
  44. {
  45. return (1 << (int)X86Register.Xmm0) |
  46. (1 << (int)X86Register.Xmm1) |
  47. (1 << (int)X86Register.Xmm2) |
  48. (1 << (int)X86Register.Xmm3) |
  49. (1 << (int)X86Register.Xmm4) |
  50. (1 << (int)X86Register.Xmm5);
  51. }
  52. else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
  53. {
  54. return RegistersMask;
  55. }
  56. }
  57. public static int GetIntCalleeSavedRegisters()
  58. {
  59. return GetIntCallerSavedRegisters() ^ RegistersMask;
  60. }
  61. public static int GetVecCalleeSavedRegisters()
  62. {
  63. return GetVecCallerSavedRegisters() ^ RegistersMask;
  64. }
  65. public static int GetArgumentsOnRegsCount()
  66. {
  67. return 4;
  68. }
  69. public static int GetIntArgumentsOnRegsCount()
  70. {
  71. return 6;
  72. }
  73. public static int GetVecArgumentsOnRegsCount()
  74. {
  75. return 8;
  76. }
  77. public static X86Register GetIntArgumentRegister(int index)
  78. {
  79. if (GetCurrentCallConv() == CallConvName.Windows)
  80. {
  81. switch (index)
  82. {
  83. case 0: return X86Register.Rcx;
  84. case 1: return X86Register.Rdx;
  85. case 2: return X86Register.R8;
  86. case 3: return X86Register.R9;
  87. }
  88. }
  89. else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
  90. {
  91. switch (index)
  92. {
  93. case 0: return X86Register.Rdi;
  94. case 1: return X86Register.Rsi;
  95. case 2: return X86Register.Rdx;
  96. case 3: return X86Register.Rcx;
  97. case 4: return X86Register.R8;
  98. case 5: return X86Register.R9;
  99. }
  100. }
  101. throw new ArgumentOutOfRangeException(nameof(index));
  102. }
  103. public static X86Register GetVecArgumentRegister(int index)
  104. {
  105. int count;
  106. if (GetCurrentCallConv() == CallConvName.Windows)
  107. {
  108. count = 4;
  109. }
  110. else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
  111. {
  112. count = 8;
  113. }
  114. if ((uint)index < count)
  115. {
  116. return X86Register.Xmm0 + index;
  117. }
  118. throw new ArgumentOutOfRangeException(nameof(index));
  119. }
  120. public static X86Register GetIntReturnRegister()
  121. {
  122. return X86Register.Rax;
  123. }
  124. public static X86Register GetIntReturnRegisterHigh()
  125. {
  126. return X86Register.Rdx;
  127. }
  128. public static X86Register GetVecReturnRegister()
  129. {
  130. return X86Register.Xmm0;
  131. }
  132. public static CallConvName GetCurrentCallConv()
  133. {
  134. return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
  135. ? CallConvName.Windows
  136. : CallConvName.SystemV;
  137. }
  138. }
  139. }