github.com/ebitengine/purego@v0.8.0-alpha.2.0.20240512170805-6cd12240d332/sys_amd64.s (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
     3  
     4  //go:build darwin || freebsd || linux
     5  
     6  #include "textflag.h"
     7  #include "abi_amd64.h"
     8  #include "go_asm.h"
     9  #include "funcdata.h"
    10  
    11  #define STACK_SIZE 80
    12  #define PTR_ADDRESS (STACK_SIZE - 8)
    13  
    14  // syscall15X calls a function in libc on behalf of the syscall package.
    15  // syscall15X takes a pointer to a struct like:
    16  // struct {
    17  //	fn    uintptr
    18  //	a1    uintptr
    19  //	a2    uintptr
    20  //	a3    uintptr
    21  //	a4    uintptr
    22  //	a5    uintptr
    23  //	a6    uintptr
    24  //	a7    uintptr
    25  //	a8    uintptr
    26  //	a9    uintptr
    27  //	a10    uintptr
    28  //	a11    uintptr
    29  //	a12    uintptr
    30  //	a13    uintptr
    31  //	a14    uintptr
    32  //	a15    uintptr
    33  //	r1    uintptr
    34  //	r2    uintptr
    35  //	err   uintptr
    36  // }
    37  // syscall15X must be called on the g0 stack with the
    38  // C calling convention (use libcCall).
    39  GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $8
    40  DATA ·syscall15XABI0(SB)/8, $syscall15X(SB)
    41  TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0
    42  	PUSHQ BP
    43  	MOVQ  SP, BP
    44  	SUBQ  $STACK_SIZE, SP
    45  	MOVQ  DI, PTR_ADDRESS(BP) // save the pointer
    46  	MOVQ  DI, R11
    47  
    48  	MOVQ syscall15Args_f1(R11), X0 // f1
    49  	MOVQ syscall15Args_f2(R11), X1 // f2
    50  	MOVQ syscall15Args_f3(R11), X2 // f3
    51  	MOVQ syscall15Args_f4(R11), X3 // f4
    52  	MOVQ syscall15Args_f5(R11), X4 // f5
    53  	MOVQ syscall15Args_f6(R11), X5 // f6
    54  	MOVQ syscall15Args_f7(R11), X6 // f7
    55  	MOVQ syscall15Args_f8(R11), X7 // f8
    56  
    57  	MOVQ syscall15Args_a1(R11), DI // a1
    58  	MOVQ syscall15Args_a2(R11), SI // a2
    59  	MOVQ syscall15Args_a3(R11), DX // a3
    60  	MOVQ syscall15Args_a4(R11), CX // a4
    61  	MOVQ syscall15Args_a5(R11), R8 // a5
    62  	MOVQ syscall15Args_a6(R11), R9 // a6
    63  
    64  	// push the remaining paramters onto the stack
    65  	MOVQ syscall15Args_a7(R11), R12
    66  	MOVQ R12, 0(SP)                  // push a7
    67  	MOVQ syscall15Args_a8(R11), R12
    68  	MOVQ R12, 8(SP)                  // push a8
    69  	MOVQ syscall15Args_a9(R11), R12
    70  	MOVQ R12, 16(SP)                 // push a9
    71  	MOVQ syscall15Args_a10(R11), R12
    72  	MOVQ R12, 24(SP)                 // push a10
    73  	MOVQ syscall15Args_a11(R11), R12
    74  	MOVQ R12, 32(SP)                 // push a11
    75  	MOVQ syscall15Args_a12(R11), R12
    76  	MOVQ R12, 40(SP)                 // push a12
    77  	MOVQ syscall15Args_a13(R11), R12
    78  	MOVQ R12, 48(SP)                 // push a13
    79  	MOVQ syscall15Args_a14(R11), R12
    80  	MOVQ R12, 56(SP)                 // push a14
    81  	MOVQ syscall15Args_a15(R11), R12
    82  	MOVQ R12, 64(SP)                 // push a15
    83  	XORL AX, AX                      // vararg: say "no float args"
    84  
    85  	MOVQ syscall15Args_fn(R11), R10 // fn
    86  	CALL R10
    87  
    88  	MOVQ PTR_ADDRESS(BP), DI      // get the pointer back
    89  	MOVQ AX, syscall15Args_a1(DI) // r1
    90  	MOVQ DX, syscall15Args_a2(DI) // r3
    91  	MOVQ X0, syscall15Args_f1(DI) // f1
    92  	MOVQ X1, syscall15Args_f2(DI) // f2
    93  
    94  	XORL AX, AX          // no error (it's ignored anyway)
    95  	ADDQ $STACK_SIZE, SP
    96  	MOVQ BP, SP
    97  	POPQ BP
    98  	RET
    99  
   100  TEXT callbackasm1(SB), NOSPLIT|NOFRAME, $0
   101  	MOVQ 0(SP), AX  // save the return address to calculate the cb index
   102  	MOVQ 8(SP), R10 // get the return SP so that we can align register args with stack args
   103  	ADDQ $8, SP     // remove return address from stack, we are not returning to callbackasm, but to its caller.
   104  
   105  	// make space for first six int and 8 float arguments below the frame
   106  	ADJSP $14*8, SP
   107  	MOVSD X0, (1*8)(SP)
   108  	MOVSD X1, (2*8)(SP)
   109  	MOVSD X2, (3*8)(SP)
   110  	MOVSD X3, (4*8)(SP)
   111  	MOVSD X4, (5*8)(SP)
   112  	MOVSD X5, (6*8)(SP)
   113  	MOVSD X6, (7*8)(SP)
   114  	MOVSD X7, (8*8)(SP)
   115  	MOVQ  DI, (9*8)(SP)
   116  	MOVQ  SI, (10*8)(SP)
   117  	MOVQ  DX, (11*8)(SP)
   118  	MOVQ  CX, (12*8)(SP)
   119  	MOVQ  R8, (13*8)(SP)
   120  	MOVQ  R9, (14*8)(SP)
   121  	LEAQ  8(SP), R8      // R8 = address of args vector
   122  
   123  	PUSHQ R10 // push the stack pointer below registers
   124  
   125  	// determine index into runtime·cbs table
   126  	MOVQ $callbackasm(SB), DX
   127  	SUBQ DX, AX
   128  	MOVQ $0, DX
   129  	MOVQ $5, CX               // divide by 5 because each call instruction in ·callbacks is 5 bytes long
   130  	DIVL CX
   131  	SUBQ $1, AX               // subtract 1 because return PC is to the next slot
   132  
   133  	// Switch from the host ABI to the Go ABI.
   134  	PUSH_REGS_HOST_TO_ABI0()
   135  
   136  	// Create a struct callbackArgs on our stack to be passed as
   137  	// the "frame" to cgocallback and on to callbackWrap.
   138  	// $24 to make enough room for the arguments to runtime.cgocallback
   139  	SUBQ $(24+callbackArgs__size), SP
   140  	MOVQ AX, (24+callbackArgs_index)(SP)  // callback index
   141  	MOVQ R8, (24+callbackArgs_args)(SP)   // address of args vector
   142  	MOVQ $0, (24+callbackArgs_result)(SP) // result
   143  	LEAQ 24(SP), AX                       // take the address of callbackArgs
   144  
   145  	// Call cgocallback, which will call callbackWrap(frame).
   146  	MOVQ ·callbackWrap_call(SB), DI // Get the ABIInternal function pointer
   147  	MOVQ (DI), DI                   // without <ABIInternal> by using a closure.
   148  	MOVQ AX, SI                     // frame (address of callbackArgs)
   149  	MOVQ $0, CX                     // context
   150  
   151  	CALL crosscall2(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
   152  
   153  	// Get callback result.
   154  	MOVQ (24+callbackArgs_result)(SP), AX
   155  	ADDQ $(24+callbackArgs__size), SP     // remove callbackArgs struct
   156  
   157  	POP_REGS_HOST_TO_ABI0()
   158  
   159  	POPQ  R10        // get the SP back
   160  	ADJSP $-14*8, SP // remove arguments
   161  
   162  	MOVQ R10, 0(SP)
   163  
   164  	RET