sys_amd64.s raw

   1  // SPDX-License-Identifier: Apache-2.0
   2  // SPDX-FileCopyrightText: 2022 The Ebitengine Authors
   3  
   4  //go:build darwin || freebsd || linux || netbsd
   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  	// Switch from the host ABI to the Go ABI.
 126  	PUSH_REGS_HOST_TO_ABI0()
 127  
 128  	// determine index into runtime·cbs table
 129  	MOVQ $callbackasm(SB), DX
 130  	SUBQ DX, AX
 131  	MOVQ $0, DX
 132  	MOVQ $5, CX               // divide by 5 because each call instruction in ·callbacks is 5 bytes long
 133  	DIVL CX
 134  	SUBQ $1, AX               // subtract 1 because return PC is to the next slot
 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
 165