as_callfunc_arm64_xcode.S 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. //
  2. // AngelCode Scripting Library
  3. // Copyright (c) 2020-2022 Andreas Jonsson
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any
  7. // damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any
  10. // purpose, including commercial applications, and to alter it and
  11. // redistribute it freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented// you
  14. // must not claim that you wrote the original software. If you use
  15. // this software in a product, an acknowledgment in the product
  16. // documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and
  19. // must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. //
  24. // The original version of this library can be located at:
  25. // http://www.angelcode.com/angelscript/
  26. //
  27. // Andreas Jonsson
  28. // [email protected]
  29. //
  30. // Assembly routines for the ARM64/AArch64 call convention used for Linux
  31. // Written by Max Waine in July 2020, based on as_callfunc_arm_msvc.asm,
  32. // with assistance & guidance provided by Sir Kane
  33. // Compile with GCC/GAS
  34. #if !defined(AS_MAX_PORTABILITY)
  35. #if defined(__aarch64__)
  36. .align 2
  37. .global _GetHFAReturnDouble
  38. .global _GetHFAReturnFloat
  39. .global _CallARM64Ret128
  40. .global _CallARM64RetInMemory
  41. .global _CallARM64Double
  42. .global _CallARM64Float
  43. .global _CallARM64
  44. _GetHFAReturnDouble:
  45. adr x9, populateDoubles
  46. sub x9, x9, x1, lsr 1 // x9 -= returnSize >> 1; (/2 because double is 2x instruction size)
  47. br x9
  48. str d3, [x0, #0x18]
  49. str d2, [x0, #0x10]
  50. str d1, [x1]
  51. str d0, [x0]
  52. populateDoubles:
  53. ret
  54. _GetHFAReturnFloat:
  55. adr x9, populateFloats
  56. sub x9, x9, x2 // x9 -= returnSize; (already 4 bytes per return)
  57. br x9
  58. str s3, [x1, #0x4]
  59. str s2, [x1]
  60. str s1, [x0, #0x4]
  61. str s0, [x0]
  62. populateFloats:
  63. ret
  64. //[returnType] _CallARM64[type](
  65. // const asQWORD *gpRegArgs, asQWORD numGPRegArgs,
  66. // const asQWORD *floatRegArgs, asQWORD numFloatRegArgs,
  67. // const asQWORD *stackArgs, asQWORD numStackArgs,
  68. // asFUNCTION_t func
  69. //)
  70. _CallARM64Double:
  71. _CallARM64Float:
  72. _CallARM64:
  73. .cfi_startproc
  74. stp fp, lr, [sp,#-0x20]!
  75. str x20, [sp,#0x10]
  76. .cfi_def_cfa_offset 0x20
  77. .cfi_offset 20, 0x10
  78. .cfi_offset fp, -0x20
  79. .cfi_offset lr, -0x18
  80. mov fp, sp
  81. mov x20, #0
  82. cbz x5, stackArgsLoopEnd
  83. // Align count to 2, then multiply by 8, resulting in a size aligned to 16
  84. add x20, x5, #1
  85. lsl x20, x20, #3
  86. and x20, x20, #-0x10
  87. // Multiply count by 8
  88. lsl x10, x5, #3
  89. sub sp, sp, x20
  90. stackArgsLoopStart:
  91. ldp x9,x11, [x4],#16
  92. stp x9,x11, [sp],#16
  93. subs x10, x10, #16
  94. bgt stackArgsLoopStart
  95. stackArgsLoopEnd:
  96. // Calculate amount to jump forward, avoiding pointless instructions
  97. adr x9, populateFloatRegisterArgsEnd
  98. sub x9, x9, x3, lsl 2 // x9 -= numFloatRegArgs * 4
  99. br x9
  100. ldr d7, [x2, #0x38]
  101. ldr d6, [x2, #0x30]
  102. ldr d5, [x2, #0x28]
  103. ldr d4, [x2, #0x20]
  104. ldr d3, [x2, #0x18]
  105. ldr d2, [x2, #0x10]
  106. ldr d1, [x2, #0x08]
  107. ldr d0, [x2]
  108. populateFloatRegisterArgsEnd:
  109. mov x15, x6
  110. // Calculate amount to jump forward, avoiding pointless instructions
  111. adr x9, populateGPRegisterArgsEnd
  112. sub x9, x9, x1, lsl 2 // x9 -= numGPRegArgs * 4
  113. br x9
  114. ldr x7, [x0, #0x38]
  115. ldr x6, [x0, #0x30]
  116. ldr x5, [x0, #0x28]
  117. ldr x4, [x0, #0x20]
  118. ldr x3, [x0, #0x18]
  119. ldr x2, [x0, #0x10]
  120. ldr x1, [x0, #0x08]
  121. ldr x0, [x0]
  122. populateGPRegisterArgsEnd:
  123. // Actually call function
  124. sub sp, sp, x20
  125. blr x15
  126. add sp, sp, x20
  127. ldr x20, [sp,#0x10]
  128. ldp fp, lr, [sp],#0x20
  129. .cfi_restore lr
  130. .cfi_restore fp
  131. .cfi_restore 20
  132. .cfi_def_cfa_offset 0
  133. ret
  134. .cfi_endproc
  135. .align 2
  136. _CallARM64Ret128:
  137. .cfi_startproc
  138. stp fp, lr, [sp,#-0x20]!
  139. str x20, [sp,#0x10]
  140. .cfi_def_cfa_offset 0x20
  141. .cfi_offset 20, 0x10
  142. .cfi_offset fp, -0x20
  143. .cfi_offset lr, -0x18
  144. mov fp, sp
  145. mov x20, x6
  146. mov x6, x7
  147. mov x7, #0
  148. bl _CallARM64
  149. str x1, [x20]
  150. ldr x20, [sp,#0x10]
  151. ldp fp, lr, [sp],#0x20
  152. .cfi_restore lr
  153. .cfi_restore fp
  154. .cfi_restore 20
  155. .cfi_def_cfa_offset 0
  156. ret
  157. .cfi_endproc
  158. .align 2
  159. _CallARM64RetInMemory:
  160. .cfi_startproc
  161. stp fp, lr, [sp,#-0x10]!
  162. mov fp, sp
  163. .cfi_def_cfa_offset 0x10
  164. .cfi_offset fp, -0x10
  165. .cfi_offset lr, -0x08
  166. mov x8, x6
  167. mov x6, x7
  168. mov x7, #0
  169. bl _CallARM64
  170. mov x0, x8
  171. ldp fp, lr, [sp],#0x10
  172. .cfi_restore lr
  173. .cfi_restore fp
  174. .cfi_def_cfa_offset 0
  175. ret
  176. .cfi_endproc
  177. #endif /* __aarch64__ */
  178. #endif /* !AS_MAX_PORTABILITY */