x86_64.rs 1.8 KB

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