md_darwin.S 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /* If user disable the ASM, such as avoiding bugs in ASM, donot compile it. */
  2. #if !defined(MD_ST_NO_ASM)
  3. #if defined(__amd64__) || defined(__x86_64__)
  4. /****************************************************************/
  5. /*
  6. * Internal __jmp_buf layout
  7. */
  8. #define JB_RBX 0
  9. #define JB_RBP 1
  10. #define JB_R12 2 /* The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, R9. */
  11. #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. */
  12. #define JB_R14 4 /* @see https://en.wikipedia.org/wiki/X86_calling_conventions */
  13. #define JB_R15 5 /* @see https://www.cnblogs.com/Five100Miles/p/8458561.html */
  14. #define JB_RSP 6
  15. #define JB_PC 7
  16. .file "md_darwin.S"
  17. .text
  18. /* _st_md_cxt_save(__jmp_buf env) */ /* The env is rdi, https://en.wikipedia.org/wiki/X86_calling_conventions */
  19. .globl __st_md_cxt_save
  20. .align 16
  21. __st_md_cxt_save:
  22. /*
  23. * Save registers.
  24. */
  25. movq %rbx, (JB_RBX*8)(%rdi) /* Save rbx to env[0], *(int64_t*)(rdi+0)=rbx */
  26. movq %rbp, (JB_RBP*8)(%rdi) /* Save rbp to env[1], *(int64_t*)(rdi+1)=rbp */
  27. movq %r12, (JB_R12*8)(%rdi) /* Save r12 to env[2], *(int64_t*)(rdi+2)=r12 */
  28. movq %r13, (JB_R13*8)(%rdi) /* Save r13 to env[3], *(int64_t*)(rdi+3)=r13 */
  29. movq %r14, (JB_R14*8)(%rdi) /* Save r14 to env[4], *(int64_t*)(rdi+4)=r14 */
  30. movq %r15, (JB_R15*8)(%rdi) /* Save r15 to env[5], *(int64_t*)(rdi+5)=r15 */
  31. /* Save SP */
  32. leaq 8(%rsp), %r8 /* Save *(int64_t*)(rsp+8) to r8, https://github.com/ossrs/state-threads/issues/11#issuecomment-888709759 */
  33. movq %r8, (JB_RSP*8)(%rdi) /* Save r8(rsp) to env[6], *(int64_t*)(rdi+6)=r8 */
  34. /* Save PC we are returning to */
  35. movq (%rsp), %r9 /* Save PC(parent function address) %(rsp) to r9 */
  36. movq %r9, (JB_PC*8)(%rdi) /* Save r9(PC) to env[7], *(int64_t*)(rdi+7)=r9 */
  37. xorq %rax, %rax /* Reset rax to 0 */
  38. ret
  39. /****************************************************************/
  40. /* _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 */
  41. .globl __st_md_cxt_restore
  42. .align 16
  43. __st_md_cxt_restore:
  44. /*
  45. * Restore registers.
  46. */
  47. movq (JB_RBX*8)(%rdi), %rbx /* Load rbx from env[0] */
  48. movq (JB_RBP*8)(%rdi), %rbp /* Load rbp from env[1] */
  49. movq (JB_R12*8)(%rdi), %r12 /* Load r12 from env[2] */
  50. movq (JB_R13*8)(%rdi), %r13 /* Load r13 from env[3] */
  51. movq (JB_R14*8)(%rdi), %r14 /* Load r14 from env[4] */
  52. movq (JB_R15*8)(%rdi), %r15 /* Load r15 from env[5] */
  53. /* Set return value */ /* The esi is param1 val, the eax is return value */
  54. test %esi, %esi /* if (!val) { */
  55. mov $01, %eax /* val=1; */
  56. cmove %eax, %esi /* } */
  57. mov %esi, %eax /* return val; */
  58. /* Restore PC and RSP */
  59. movq (JB_PC*8)(%rdi), %r8 /* Load r8(PC) from env[7] */
  60. movq (JB_RSP*8)(%rdi), %rsp /* Load rsp from env[6] */
  61. /* Jump to saved PC */
  62. jmpq *%r8 /* Jump to r8(PC) */
  63. /****************************************************************/
  64. #endif
  65. #endif