trampolines_386.s 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: Apache-2.0
  2. // SPDX-FileCopyrightText: 2026 The Ebitengine Authors
  3. //go:build !cgo && (freebsd || linux)
  4. #include "textflag.h"
  5. #include "go_asm.h"
  6. // These trampolines map the gcc ABI to Go ABI0 and then call into the Go equivalent functions.
  7. // On i386, both GCC and Go use stack-based calling conventions.
  8. //
  9. // When C calls a function, the stack looks like:
  10. // 0(SP) = return address
  11. // 4(SP) = arg1
  12. // 8(SP) = arg2
  13. // ...
  14. //
  15. // When we declare a Go function with frame size $N-0, Go's prologue
  16. // effectively does SUB $N, SP, so the C arguments shift up by N bytes:
  17. // N+0(SP) = return address
  18. // N+4(SP) = arg1
  19. // N+8(SP) = arg2
  20. //
  21. // Go ABI0 on 386 expects arguments starting at 0(FP) which equals N+4(SP)
  22. // after the prologue (where N is the local frame size).
  23. TEXT x_cgo_init_trampoline(SB), NOSPLIT, $8-0
  24. // C args at 12(SP) and 16(SP) after frame setup (8 bytes local + 4 bytes ret addr)
  25. // Go function expects args at 0(SP) and 4(SP) in local frame
  26. MOVL 12(SP), AX // first C arg
  27. MOVL 16(SP), BX // second C arg
  28. MOVL AX, 0(SP) // Go arg 1
  29. MOVL BX, 4(SP) // Go arg 2
  30. MOVL ·x_cgo_init_call(SB), CX
  31. MOVL (CX), CX
  32. CALL CX
  33. RET
  34. TEXT x_cgo_thread_start_trampoline(SB), NOSPLIT, $4-0
  35. // C args at 8(SP) after frame setup (4 bytes local + 4 bytes ret addr)
  36. MOVL 8(SP), AX // first C arg
  37. MOVL AX, 0(SP) // Go arg 1
  38. MOVL ·x_cgo_thread_start_call(SB), CX
  39. MOVL (CX), CX
  40. CALL CX
  41. RET
  42. TEXT x_cgo_setenv_trampoline(SB), NOSPLIT, $4-0
  43. MOVL 8(SP), AX // first C arg
  44. MOVL AX, 0(SP) // Go arg 1
  45. MOVL ·x_cgo_setenv_call(SB), CX
  46. MOVL (CX), CX
  47. CALL CX
  48. RET
  49. TEXT x_cgo_unsetenv_trampoline(SB), NOSPLIT, $4-0
  50. MOVL 8(SP), AX // first C arg
  51. MOVL AX, 0(SP) // Go arg 1
  52. MOVL ·x_cgo_unsetenv_call(SB), CX
  53. MOVL (CX), CX
  54. CALL CX
  55. RET
  56. TEXT x_cgo_notify_runtime_init_done_trampoline(SB), NOSPLIT, $0-0
  57. CALL ·x_cgo_notify_runtime_init_done(SB)
  58. RET
  59. TEXT x_cgo_bindm_trampoline(SB), NOSPLIT, $0
  60. CALL ·x_cgo_bindm(SB)
  61. RET
  62. // func setg_trampoline(setg uintptr, g uintptr)
  63. // This is called from Go, so args are at normal FP positions
  64. TEXT ·setg_trampoline(SB), NOSPLIT, $4-8
  65. MOVL g+4(FP), AX
  66. MOVL setg+0(FP), BX
  67. // setg expects g in 0(SP)
  68. MOVL AX, 0(SP)
  69. CALL BX
  70. RET
  71. TEXT threadentry_trampoline(SB), NOSPLIT, $4-0
  72. MOVL 8(SP), AX // first C arg
  73. MOVL AX, 0(SP) // Go arg 1
  74. MOVL ·threadentry_call(SB), CX
  75. MOVL (CX), CX
  76. CALL CX
  77. RET
  78. TEXT ·call5(SB), NOSPLIT, $20-28
  79. MOVL fn+0(FP), AX
  80. MOVL a1+4(FP), BX
  81. MOVL a2+8(FP), CX
  82. MOVL a3+12(FP), DX
  83. MOVL a4+16(FP), SI
  84. MOVL a5+20(FP), DI
  85. // Place arguments on local stack frame for C calling convention
  86. MOVL BX, 0(SP) // a1
  87. MOVL CX, 4(SP) // a2
  88. MOVL DX, 8(SP) // a3
  89. MOVL SI, 12(SP) // a4
  90. MOVL DI, 16(SP) // a5
  91. CALL AX
  92. MOVL AX, r1+24(FP)
  93. RET