sys_amd64.s 5.0 KB

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