trampolines_386.s raw

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