trampolines_ppc64le.s 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // SPDX-License-Identifier: Apache-2.0
  2. // SPDX-FileCopyrightText: 2026 The Ebitengine Authors
  3. //go:build !cgo && linux
  4. #include "textflag.h"
  5. #include "go_asm.h"
  6. // These trampolines map the C ABI to Go ABI and call into the Go equivalent functions.
  7. //
  8. // PPC64LE ELFv2 ABI stack frame layout:
  9. // 0(R1) = backchain (pointer to caller's frame)
  10. // 8(R1) = CR save area
  11. // 16(R1) = LR save area
  12. // 24(R1) = reserved
  13. // 32(R1) = parameter save area (minimum 64 bytes for 8 args)
  14. //
  15. // Two patterns are used depending on call direction:
  16. //
  17. // C→Go trampolines: The C caller already provides a 32-byte linkage area.
  18. // Save LR/CR into caller's frame at 16(R1)/8(R1) BEFORE allocating,
  19. // then use MOVDU to allocate and set backchain atomically.
  20. //
  21. // Go→C trampolines: Go callers don't provide ELFv2 linkage area.
  22. // Allocate frame first with MOVDU, then save LR/CR into OUR frame.
  23. TEXT x_cgo_init_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  24. MOVD LR, 16(R1)
  25. MOVW CR, R0
  26. MOVD R0, 8(R1)
  27. MOVDU R1, -32(R1)
  28. // R3, R4 already have the arguments
  29. MOVD ·x_cgo_init_call(SB), R12
  30. MOVD (R12), R12
  31. MOVD R12, CTR
  32. CALL CTR
  33. ADD $32, R1
  34. MOVD 16(R1), LR
  35. MOVD 8(R1), R0
  36. MOVW R0, CR
  37. RET
  38. TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  39. MOVD LR, 16(R1)
  40. MOVW CR, R0
  41. MOVD R0, 8(R1)
  42. MOVDU R1, -32(R1)
  43. MOVD ·x_cgo_thread_start_call(SB), R12
  44. MOVD (R12), R12
  45. MOVD R12, CTR
  46. CALL CTR
  47. ADD $32, R1
  48. MOVD 16(R1), LR
  49. MOVD 8(R1), R0
  50. MOVW R0, CR
  51. RET
  52. // void (*_cgo_setenv)(char**)
  53. // C arg: R3 = pointer to env
  54. // This is C→Go: caller is C ABI.
  55. TEXT x_cgo_setenv_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  56. MOVD LR, 16(R1)
  57. MOVW CR, R0
  58. MOVD R0, 8(R1)
  59. MOVDU R1, -32(R1)
  60. MOVD ·x_cgo_setenv_call(SB), R12
  61. MOVD (R12), R12
  62. MOVD R12, CTR
  63. CALL CTR
  64. ADD $32, R1
  65. MOVD 16(R1), LR
  66. MOVD 8(R1), R0
  67. MOVW R0, CR
  68. RET
  69. TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  70. MOVD LR, 16(R1)
  71. MOVW CR, R0
  72. MOVD R0, 8(R1)
  73. MOVDU R1, -32(R1)
  74. MOVD ·x_cgo_unsetenv_call(SB), R12
  75. MOVD (R12), R12
  76. MOVD R12, CTR
  77. CALL CTR
  78. ADD $32, R1
  79. MOVD 16(R1), LR
  80. MOVD 8(R1), R0
  81. MOVW R0, CR
  82. RET
  83. TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  84. MOVD LR, 16(R1)
  85. MOVW CR, R0
  86. MOVD R0, 8(R1)
  87. MOVDU R1, -32(R1)
  88. CALL ·x_cgo_notify_runtime_init_done(SB)
  89. ADD $32, R1
  90. MOVD 16(R1), LR
  91. MOVD 8(R1), R0
  92. MOVW R0, CR
  93. RET
  94. TEXT x_cgo_bindm_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  95. MOVD LR, 16(R1)
  96. MOVW CR, R0
  97. MOVD R0, 8(R1)
  98. MOVDU R1, -32(R1)
  99. CALL ·x_cgo_bindm(SB)
  100. ADD $32, R1
  101. MOVD 16(R1), LR
  102. MOVD 8(R1), R0
  103. MOVW R0, CR
  104. RET
  105. TEXT ·setg_trampoline(SB), NOSPLIT|NOFRAME, $0-16
  106. // Save LR, CR, and R31 to non-volatile registers (C ABI preserves R14-R31)
  107. MOVD LR, R20
  108. MOVW CR, R21
  109. MOVD R31, R22 // save R31 because load_g clobbers it
  110. // Load arguments from Go stack
  111. MOVD 32(R1), R12 // setg function pointer
  112. MOVD 40(R1), R3 // g pointer → first C arg
  113. // Allocate ELFv2 frame for the C callee (32 bytes minimum)
  114. MOVDU R1, -32(R1)
  115. // Call setg_gcc which stores g to TLS
  116. MOVD R12, CTR
  117. CALL CTR
  118. // setg_gcc stored g to TLS but restored old g in R30.
  119. // Call load_g to reload g from TLS into R30.
  120. // Note: load_g clobbers R31
  121. CALL runtime·load_g(SB)
  122. // Deallocate frame
  123. ADD $32, R1
  124. // Clear R0 before returning to Go code.
  125. // Go uses R0 as a constant 0 for things like "std r0,X(r1)" to zero stack locations.
  126. // C/assembly functions may leave garbage in R0.
  127. XOR R0, R0, R0
  128. // Restore LR, CR, and R31 from non-volatile registers
  129. MOVD R22, R31 // restore R31
  130. MOVD R20, LR
  131. MOVW R21, CR
  132. RET
  133. TEXT threadentry_trampoline(SB), NOSPLIT|NOFRAME, $0-0
  134. MOVD LR, 16(R1)
  135. MOVW CR, R0
  136. MOVD R0, 8(R1)
  137. MOVDU R1, -32(R1)
  138. MOVD ·threadentry_call(SB), R12
  139. MOVD (R12), R12
  140. MOVD R12, CTR
  141. CALL CTR
  142. ADD $32, R1
  143. MOVD 16(R1), LR
  144. MOVD 8(R1), R0
  145. MOVW R0, CR
  146. RET
  147. TEXT ·call5(SB), NOSPLIT|NOFRAME, $0-56
  148. MOVD LR, R20
  149. MOVW CR, R21
  150. // Load arguments from Go stack into C argument registers
  151. // Go placed args at 32(R1), 40(R1), etc.
  152. MOVD 32(R1), R12 // fn
  153. MOVD 40(R1), R3 // a1 → first C arg
  154. MOVD 48(R1), R4 // a2 → second C arg
  155. MOVD 56(R1), R5 // a3 → third C arg
  156. MOVD 64(R1), R6 // a4 → fourth C arg
  157. MOVD 72(R1), R7 // a5 → fifth C arg
  158. MOVDU R1, -32(R1)
  159. MOVD R12, CTR
  160. CALL CTR
  161. // Store return value
  162. // After MOVDU -32, original 80(R1) is now at 80+32=112(R1)
  163. MOVD R3, (80+32)(R1)
  164. // Deallocate frame
  165. ADD $32, R1
  166. // Clear R0 before returning to Go code.
  167. // Go uses R0 as a constant 0 register for things like "std r0,X(r1)"
  168. // to zero stack locations. C functions may leave garbage in R0.
  169. XOR R0, R0, R0
  170. // Restore LR/CR from non-volatile registers
  171. MOVD R20, LR
  172. MOVW R21, CR
  173. RET