sys_arm.s 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: Apache-2.0
  2. // SPDX-FileCopyrightText: 2026 The Ebitengine Authors
  3. //go:build linux
  4. #include "textflag.h"
  5. #include "go_asm.h"
  6. #include "funcdata.h"
  7. #define STACK_SIZE 128
  8. #define PTR_ADDRESS (STACK_SIZE - 4)
  9. // syscall15X calls a function in libc on behalf of the syscall package.
  10. // syscall15X takes a pointer to a struct like:
  11. // struct {
  12. // fn uintptr
  13. // a1 uintptr
  14. // ...
  15. // a32 uintptr
  16. // f1 uintptr
  17. // ...
  18. // f16 uintptr
  19. // arm64_r8 uintptr
  20. // }
  21. // syscall15X must be called on the g0 stack with the
  22. // C calling convention (use libcCall).
  23. GLOBL ·syscall15XABI0(SB), NOPTR|RODATA, $4
  24. DATA ·syscall15XABI0(SB)/4, $syscall15X(SB)
  25. TEXT syscall15X(SB), NOSPLIT|NOFRAME, $0-0
  26. // Called via C calling convention: R0 = pointer to syscall15Args
  27. // NOT via Go calling convention
  28. // Save link register and callee-saved registers first
  29. MOVW.W R14, -4(R13) // save LR (decrement and store)
  30. MOVM.DB.W [R4, R5, R6, R7, R8, R9, R11], (R13) // save callee-saved regs
  31. MOVW R0, R8
  32. SUB $STACK_SIZE, R13
  33. MOVW R8, PTR_ADDRESS(R13)
  34. // Load function pointer first (before anything can corrupt R8)
  35. MOVW syscall15Args_fn(R8), R5
  36. MOVW R5, (PTR_ADDRESS-4)(R13) // save fn at offset 56
  37. // Load floating point arguments
  38. // Each float64 spans 2 uintptr slots (8 bytes) on ARM32, so we skip by 2
  39. MOVD syscall15Args_f1(R8), F0 // f1+f2 -> D0
  40. MOVD syscall15Args_f3(R8), F1 // f3+f4 -> D1
  41. MOVD syscall15Args_f5(R8), F2 // f5+f6 -> D2
  42. MOVD syscall15Args_f7(R8), F3 // f7+f8 -> D3
  43. MOVD syscall15Args_f9(R8), F4 // f9+f10 -> D4
  44. MOVD syscall15Args_f11(R8), F5 // f11+f12 -> D5
  45. MOVD syscall15Args_f13(R8), F6 // f13+f14 -> D6
  46. MOVD syscall15Args_f15(R8), F7 // f15+f16 -> D7
  47. // Load integer arguments into registers (R0-R3 for ARM EABI)
  48. MOVW syscall15Args_a1(R8), R0 // a1
  49. MOVW syscall15Args_a2(R8), R1 // a2
  50. MOVW syscall15Args_a3(R8), R2 // a3
  51. MOVW syscall15Args_a4(R8), R3 // a4
  52. // push a5-a32 onto stack
  53. MOVW syscall15Args_a5(R8), R4
  54. MOVW R4, 0(R13)
  55. MOVW syscall15Args_a6(R8), R4
  56. MOVW R4, 4(R13)
  57. MOVW syscall15Args_a7(R8), R4
  58. MOVW R4, 8(R13)
  59. MOVW syscall15Args_a8(R8), R4
  60. MOVW R4, 12(R13)
  61. MOVW syscall15Args_a9(R8), R4
  62. MOVW R4, 16(R13)
  63. MOVW syscall15Args_a10(R8), R4
  64. MOVW R4, 20(R13)
  65. MOVW syscall15Args_a11(R8), R4
  66. MOVW R4, 24(R13)
  67. MOVW syscall15Args_a12(R8), R4
  68. MOVW R4, 28(R13)
  69. MOVW syscall15Args_a13(R8), R4
  70. MOVW R4, 32(R13)
  71. MOVW syscall15Args_a14(R8), R4
  72. MOVW R4, 36(R13)
  73. MOVW syscall15Args_a15(R8), R4
  74. MOVW R4, 40(R13)
  75. MOVW syscall15Args_a16(R8), R4
  76. MOVW R4, 44(R13)
  77. MOVW syscall15Args_a17(R8), R4
  78. MOVW R4, 48(R13)
  79. MOVW syscall15Args_a18(R8), R4
  80. MOVW R4, 52(R13)
  81. MOVW syscall15Args_a19(R8), R4
  82. MOVW R4, 56(R13)
  83. MOVW syscall15Args_a20(R8), R4
  84. MOVW R4, 60(R13)
  85. MOVW syscall15Args_a21(R8), R4
  86. MOVW R4, 64(R13)
  87. MOVW syscall15Args_a22(R8), R4
  88. MOVW R4, 68(R13)
  89. MOVW syscall15Args_a23(R8), R4
  90. MOVW R4, 72(R13)
  91. MOVW syscall15Args_a24(R8), R4
  92. MOVW R4, 76(R13)
  93. MOVW syscall15Args_a25(R8), R4
  94. MOVW R4, 80(R13)
  95. MOVW syscall15Args_a26(R8), R4
  96. MOVW R4, 84(R13)
  97. MOVW syscall15Args_a27(R8), R4
  98. MOVW R4, 88(R13)
  99. MOVW syscall15Args_a28(R8), R4
  100. MOVW R4, 92(R13)
  101. MOVW syscall15Args_a29(R8), R4
  102. MOVW R4, 96(R13)
  103. MOVW syscall15Args_a30(R8), R4
  104. MOVW R4, 100(R13)
  105. MOVW syscall15Args_a31(R8), R4
  106. MOVW R4, 104(R13)
  107. MOVW syscall15Args_a32(R8), R4
  108. MOVW R4, 108(R13)
  109. // Load saved function pointer and call
  110. MOVW (PTR_ADDRESS-4)(R13), R4
  111. // Use BLX for Thumb interworking - Go assembler doesn't support BLX Rn
  112. // BLX R4 = 0xE12FFF34 (ARM encoding, always condition)
  113. WORD $0xE12FFF34 // blx r4
  114. // pop structure pointer
  115. MOVW PTR_ADDRESS(R13), R8
  116. ADD $STACK_SIZE, R13
  117. // save R0, R1
  118. MOVW R0, syscall15Args_a1(R8)
  119. MOVW R1, syscall15Args_a2(R8)
  120. // save f0-f3 (each float64 spans 2 uintptr slots on ARM32)
  121. MOVD F0, syscall15Args_f1(R8)
  122. MOVD F1, syscall15Args_f3(R8)
  123. MOVD F2, syscall15Args_f5(R8)
  124. MOVD F3, syscall15Args_f7(R8)
  125. // Restore callee-saved registers and return
  126. MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, R11]
  127. MOVW.P 4(R13), R15 // pop LR into PC (return)