md_darwin.S 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* SPDX-License-Identifier: MIT */
  2. /* Copyright (c) 2021-2022 The SRS Authors */
  3. /* If user disable the ASM, such as avoiding bugs in ASM, donot compile it. */
  4. #if !defined(MD_ST_NO_ASM)
  5. #if defined(__amd64__) || defined(__x86_64__)
  6. /****************************************************************/
  7. /*
  8. * Internal __jmp_buf layout
  9. */
  10. #define JB_RBX 0
  11. #define JB_RBP 1
  12. #define JB_R12 2 /* The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, R9. */
  13. #define JB_R13 3 /* If the callee wishes to use registers RBX, RSP, RBP, and R12–R15, it must restore their original values before returning control to the caller. */
  14. #define JB_R14 4 /* @see https://en.wikipedia.org/wiki/X86_calling_conventions */
  15. #define JB_R15 5 /* @see https://www.cnblogs.com/Five100Miles/p/8458561.html */
  16. #define JB_RSP 6
  17. #define JB_PC 7
  18. .file "md_darwin.S"
  19. .text
  20. /* _st_md_cxt_save(__jmp_buf env) */ /* The env is rdi, https://en.wikipedia.org/wiki/X86_calling_conventions */
  21. .globl __st_md_cxt_save
  22. .align 16
  23. __st_md_cxt_save:
  24. /*
  25. * Save registers.
  26. */
  27. movq %rbx, (JB_RBX*8)(%rdi) /* Save rbx to env[0], *(int64_t*)(rdi+0)=rbx */
  28. movq %rbp, (JB_RBP*8)(%rdi) /* Save rbp to env[1], *(int64_t*)(rdi+1)=rbp */
  29. movq %r12, (JB_R12*8)(%rdi) /* Save r12 to env[2], *(int64_t*)(rdi+2)=r12 */
  30. movq %r13, (JB_R13*8)(%rdi) /* Save r13 to env[3], *(int64_t*)(rdi+3)=r13 */
  31. movq %r14, (JB_R14*8)(%rdi) /* Save r14 to env[4], *(int64_t*)(rdi+4)=r14 */
  32. movq %r15, (JB_R15*8)(%rdi) /* Save r15 to env[5], *(int64_t*)(rdi+5)=r15 */
  33. /* Save SP */
  34. leaq 8(%rsp), %r8 /* Save *(int64_t*)(rsp+8) to r8, https://github.com/ossrs/state-threads/issues/11#issuecomment-888709759 */
  35. movq %r8, (JB_RSP*8)(%rdi) /* Save r8(rsp) to env[6], *(int64_t*)(rdi+6)=r8 */
  36. /* Save PC we are returning to */
  37. movq (%rsp), %r9 /* Save PC(parent function address) %(rsp) to r9 */
  38. movq %r9, (JB_PC*8)(%rdi) /* Save r9(PC) to env[7], *(int64_t*)(rdi+7)=r9 */
  39. xorq %rax, %rax /* Reset rax to 0 */
  40. ret
  41. /****************************************************************/
  42. /* _st_md_cxt_restore(__jmp_buf env, int val) */ /* The env is rdi, val is esi/rsi, https://en.wikipedia.org/wiki/X86_calling_conventions */
  43. .globl __st_md_cxt_restore
  44. .align 16
  45. __st_md_cxt_restore:
  46. /*
  47. * Restore registers.
  48. */
  49. movq (JB_RBX*8)(%rdi), %rbx /* Load rbx from env[0] */
  50. movq (JB_RBP*8)(%rdi), %rbp /* Load rbp from env[1] */
  51. movq (JB_R12*8)(%rdi), %r12 /* Load r12 from env[2] */
  52. movq (JB_R13*8)(%rdi), %r13 /* Load r13 from env[3] */
  53. movq (JB_R14*8)(%rdi), %r14 /* Load r14 from env[4] */
  54. movq (JB_R15*8)(%rdi), %r15 /* Load r15 from env[5] */
  55. /* Set return value */ /* The esi is param1 val, the eax is return value */
  56. test %esi, %esi /* if (!val) { */
  57. mov $01, %eax /* val=1; */
  58. cmove %eax, %esi /* } */
  59. mov %esi, %eax /* return val; */
  60. /* Restore PC and RSP */
  61. movq (JB_PC*8)(%rdi), %r8 /* Load r8(PC) from env[7] */
  62. movq (JB_RSP*8)(%rdi), %rsp /* Load rsp from env[6] */
  63. /* Jump to saved PC */
  64. jmpq *%r8 /* Jump to r8(PC) */
  65. /****************************************************************/
  66. #elif defined(__aarch64__)
  67. /****************************************************************/
  68. /* See https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms */
  69. /* See https://developer.arm.com/documentation/102374/0100/Function-calls */
  70. /* See https://developer.arm.com/documentation/102374/0100/Procedure-Call-Standard */
  71. /* See https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#machine-registers */
  72. /* See https://wiki.cdot.senecacollege.ca/wiki/AArch64_Register_and_Instruction_Quick_Start */
  73. /*
  74. * See setjmp.h of Darwin.
  75. *
  76. * _JBLEN is the number of ints required to save the following:
  77. * r21-r29, sp, fp, lr == 12 registers, 8 bytes each. d8-d15
  78. * are another 8 registers, each 8 bytes long. (aapcs64 specifies
  79. * that only 64-bit versions of FP registers need to be saved).
  80. * Finally, two 8-byte fields for signal handling purposes.
  81. */
  82. /* The called routine is expected to preserve r19-r28 *** These registers are generally
  83. safe to use in your program. */
  84. #define JB_X19 0
  85. #define JB_X20 1
  86. #define JB_X21 2
  87. #define JB_X22 3
  88. #define JB_X23 4
  89. #define JB_X24 5
  90. #define JB_X25 6
  91. #define JB_X26 7
  92. #define JB_X27 8
  93. #define JB_X28 9
  94. /* r29 and r30 are used as the frame register and link register (avoid) */
  95. #define JB_X29 10
  96. #define JB_LR 11
  97. /* Register '31' is one of two registers depending on the instruction context:
  98. For instructions dealing with the stack, it is the stack pointer, named rsp */
  99. #define JB_SP 13
  100. /* FP registers */
  101. #define JB_D8 14
  102. #define JB_D9 15
  103. #define JB_D10 16
  104. #define JB_D11 17
  105. #define JB_D12 18
  106. #define JB_D13 19
  107. #define JB_D14 20
  108. #define JB_D15 21
  109. .file "md.S"
  110. .text
  111. /* _st_md_cxt_save(__jmp_buf env) */
  112. .globl __st_md_cxt_save
  113. .align 4
  114. __st_md_cxt_save:
  115. stp x19, x20, [x0, #JB_X19<<3]
  116. stp x21, x22, [x0, #JB_X21<<3]
  117. stp x23, x24, [x0, #JB_X23<<3]
  118. stp x25, x26, [x0, #JB_X25<<3]
  119. stp x27, x28, [x0, #JB_X27<<3]
  120. stp x29, x30, [x0, #JB_X29<<3]
  121. stp d8, d9, [x0, #JB_D8<<3]
  122. stp d10, d11, [x0, #JB_D10<<3]
  123. stp d12, d13, [x0, #JB_D12<<3]
  124. stp d14, d15, [x0, #JB_D14<<3]
  125. mov x2, sp
  126. str x2, [x0, #JB_SP<<3]
  127. mov x0, #0
  128. ret
  129. /****************************************************************/
  130. /* _st_md_cxt_restore(__jmp_buf env, int val) */
  131. .globl __st_md_cxt_restore
  132. .align 4
  133. __st_md_cxt_restore:
  134. ldp x19, x20, [x0, #JB_X19<<3]
  135. ldp x21, x22, [x0, #JB_X21<<3]
  136. ldp x23, x24, [x0, #JB_X23<<3]
  137. ldp x25, x26, [x0, #JB_X25<<3]
  138. ldp x27, x28, [x0, #JB_X27<<3]
  139. ldp x29, x30, [x0, #JB_X29<<3]
  140. ldp d8, d9, [x0, #JB_D8<<3]
  141. ldp d10, d11, [x0, #JB_D10<<3]
  142. ldp d12, d13, [x0, #JB_D12<<3]
  143. ldp d14, d15, [x0, #JB_D14<<3]
  144. ldr x5, [x0, #JB_SP<<3]
  145. mov sp, x5
  146. /* x0 = (x1 || 1); */
  147. cmp x1, #0
  148. mov x0, #1
  149. csel x0, x1, x0, ne
  150. ret
  151. /****************************************************************/
  152. #endif
  153. #endif