x86_64.rs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #![allow(unused_imports)]
  2. use core::intrinsics;
  3. // NOTE These functions are implemented using assembly because they using a custom
  4. // calling convention which can't be implemented using a normal Rust function
  5. // NOTE These functions are never mangled as they are not tested against compiler-rt
  6. // and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
  7. #[cfg(windows)]
  8. #[naked]
  9. #[no_mangle]
  10. pub unsafe fn ___chkstk_ms() {
  11. asm!("push %rcx
  12. push %rax
  13. cmp $$0x1000,%rax
  14. lea 24(%rsp),%rcx
  15. jb 1f
  16. 2:
  17. sub $$0x1000,%rcx
  18. test %rcx,(%rcx)
  19. sub $$0x1000,%rax
  20. cmp $$0x1000,%rax
  21. ja 2b
  22. 1:
  23. sub %rax,%rcx
  24. test %rcx,(%rcx)
  25. pop %rax
  26. pop %rcx
  27. ret");
  28. intrinsics::unreachable();
  29. }
  30. #[cfg(windows)]
  31. #[naked]
  32. #[no_mangle]
  33. pub unsafe fn __alloca() {
  34. asm!("mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx
  35. jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable");
  36. intrinsics::unreachable();
  37. }
  38. #[cfg(windows)]
  39. #[naked]
  40. #[no_mangle]
  41. pub unsafe fn ___chkstk() {
  42. asm!("push %rcx
  43. cmp $$0x1000,%rax
  44. lea 16(%rsp),%rcx // rsp before calling this routine -> rcx
  45. jb 1f
  46. 2:
  47. sub $$0x1000,%rcx
  48. test %rcx,(%rcx)
  49. sub $$0x1000,%rax
  50. cmp $$0x1000,%rax
  51. ja 2b
  52. 1:
  53. sub %rax,%rcx
  54. test %rcx,(%rcx)
  55. lea 8(%rsp),%rax // load pointer to the return address into rax
  56. mov %rcx,%rsp // install the new top of stack pointer into rsp
  57. mov -8(%rax),%rcx // restore rcx
  58. push (%rax) // push return address onto the stack
  59. sub %rsp,%rax // restore the original value in rax
  60. ret");
  61. intrinsics::unreachable();
  62. }