x86.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
  8. #[naked]
  9. #[no_mangle]
  10. pub unsafe fn ___chkstk_ms() {
  11. llvm_asm!("
  12. push %ecx
  13. push %eax
  14. cmp $$0x1000,%eax
  15. lea 12(%esp),%ecx
  16. jb 1f
  17. 2:
  18. sub $$0x1000,%ecx
  19. test %ecx,(%ecx)
  20. sub $$0x1000,%eax
  21. cmp $$0x1000,%eax
  22. ja 2b
  23. 1:
  24. sub %eax,%ecx
  25. test %ecx,(%ecx)
  26. pop %eax
  27. pop %ecx
  28. ret" ::: "memory" : "volatile");
  29. intrinsics::unreachable();
  30. }
  31. // FIXME: __alloca should be an alias to __chkstk
  32. #[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
  33. #[naked]
  34. #[no_mangle]
  35. pub unsafe fn __alloca() {
  36. llvm_asm!("jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable"
  37. ::: "memory" : "volatile");
  38. intrinsics::unreachable();
  39. }
  40. #[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
  41. #[naked]
  42. #[no_mangle]
  43. pub unsafe fn ___chkstk() {
  44. llvm_asm!("
  45. push %ecx
  46. cmp $$0x1000,%eax
  47. lea 8(%esp),%ecx // esp before calling this routine -> ecx
  48. jb 1f
  49. 2:
  50. sub $$0x1000,%ecx
  51. test %ecx,(%ecx)
  52. sub $$0x1000,%eax
  53. cmp $$0x1000,%eax
  54. ja 2b
  55. 1:
  56. sub %eax,%ecx
  57. test %ecx,(%ecx)
  58. lea 4(%esp),%eax // load pointer to the return address into eax
  59. mov %ecx,%esp // install the new top of stack pointer into esp
  60. mov -4(%eax),%ecx // restore ecx
  61. push (%eax) // push return address onto the stack
  62. sub %esp,%eax // restore the original value in eax
  63. ret" ::: "memory" : "volatile");
  64. intrinsics::unreachable();
  65. }