amd64.S 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #
  2. #
  3. # Nim's Runtime Library
  4. # (c) Copyright 2015 Rokas Kupstys
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # Partially based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
  10. .globl narch_coroExecWithStack
  11. .globl narch_setjmp
  12. .globl narch_longjmp
  13. .text
  14. # SysV ABI - first argument is rdi.
  15. # MS ABI - first argument is rcx.
  16. #if defined(__MINGW32__) || defined(__MINGW64__)
  17. #define REG_ARG1 rcx
  18. #define REG_ARG2 rdx
  19. #else
  20. #define REG_ARG1 rdi
  21. #define REG_ARG2 rsi
  22. #endif
  23. narch_coroExecWithStack:
  24. mov %REG_ARG2, %rsp # swap stack with one passed to func
  25. sub $0x30, %rsp # shadow space (for ms ABI) 0x20 + 0x10 for possible misalignment
  26. and $-0x10, %rsp # 16-byte stack alignment
  27. call *%REG_ARG1
  28. narch_setjmp:
  29. add $0x10, %REG_ARG1 # 16-byte alignment
  30. and $-0x10, %REG_ARG1
  31. mov %rbx, 0x00(%REG_ARG1) # jmp_buf, move registers onto it
  32. mov %rbp, 0x08(%REG_ARG1)
  33. mov %r12, 0x10(%REG_ARG1)
  34. mov %r13, 0x18(%REG_ARG1)
  35. mov %r14, 0x20(%REG_ARG1)
  36. mov %r15, 0x28(%REG_ARG1)
  37. lea 0x08(%rsp), %rdx # this is our rsp WITHOUT current ret addr
  38. mov %rdx, 0x30(%REG_ARG1)
  39. mov (%rsp), %rdx # save return addr ptr for new rip
  40. mov %rdx, 0x38(%REG_ARG1)
  41. mov %rsi, 0x40(%REG_ARG1)
  42. mov %rdi, 0x48(%REG_ARG1)
  43. #if defined(__MINGW32__) || defined(__MINGW64__)
  44. movaps %xmm6, 0x50(%REG_ARG1)
  45. movaps %xmm7, 0x60(%REG_ARG1)
  46. movaps %xmm8, 0x70(%REG_ARG1)
  47. movaps %xmm9, 0x80(%REG_ARG1)
  48. movaps %xmm10, 0x90(%REG_ARG1)
  49. movaps %xmm11, 0xA0(%REG_ARG1)
  50. movaps %xmm12, 0xB0(%REG_ARG1)
  51. movaps %xmm13, 0xC0(%REG_ARG1)
  52. movaps %xmm14, 0xD0(%REG_ARG1)
  53. movaps %xmm15, 0xE0(%REG_ARG1)
  54. #endif
  55. xor %rax, %rax # always return 0
  56. ret
  57. narch_longjmp:
  58. add $0x10, %REG_ARG1 # 16-byte alignment
  59. and $-0x10, %REG_ARG1 #
  60. mov %REG_ARG2, %rax # val will be longjmp return
  61. test %rax, %rax
  62. jnz narch_longjmp_1
  63. inc %rax # if val==0, val=1 per longjmp semantics
  64. narch_longjmp_1:
  65. mov 0x00(%REG_ARG1), %rbx # jmp_buf, restore regs from it
  66. mov 0x08(%REG_ARG1), %rbp
  67. mov 0x10(%REG_ARG1), %r12
  68. mov 0x18(%REG_ARG1), %r13
  69. mov 0x20(%REG_ARG1), %r14
  70. mov 0x28(%REG_ARG1), %r15
  71. mov 0x30(%REG_ARG1), %rsp # this ends up being the stack pointer
  72. mov 0x38(%REG_ARG1), %rdx # this is the instruction pointer
  73. mov 0x40(%REG_ARG1), %rsi
  74. mov 0x48(%REG_ARG1), %rdi
  75. #if defined(__MINGW32__) || defined(__MINGW64__)
  76. movaps 0x50(%REG_ARG1), %xmm6
  77. movaps 0x60(%REG_ARG1), %xmm7
  78. movaps 0x70(%REG_ARG1), %xmm8
  79. movaps 0x80(%REG_ARG1), %xmm9
  80. movaps 0x90(%REG_ARG1), %xmm10
  81. movaps 0xA0(%REG_ARG1), %xmm11
  82. movaps 0xB0(%REG_ARG1), %xmm12
  83. movaps 0xC0(%REG_ARG1), %xmm13
  84. movaps 0xD0(%REG_ARG1), %xmm14
  85. movaps 0xE0(%REG_ARG1), %xmm15
  86. #endif
  87. jmp *%rdx # goto saved address without altering rsp