Bladeren bron

Add x86_64 builtins

Matt Ickstadt 8 jaren geleden
bovenliggende
commit
b6091ababa
2 gewijzigde bestanden met toevoegingen van 70 en 0 verwijderingen
  1. 3 0
      src/lib.rs
  2. 67 0
      src/x86_64.rs

+ 3 - 0
src/lib.rs

@@ -23,6 +23,9 @@ extern crate rlibc;
 #[cfg(target_arch = "arm")]
 pub mod arm;
 
+#[cfg(target_arch = "x86_64")]
+pub mod x86_64;
+
 pub mod udiv;
 pub mod mul;
 pub mod shift;

+ 67 - 0
src/x86_64.rs

@@ -0,0 +1,67 @@
+use core::intrinsics;
+
+// NOTE These functions are implemented using assembly because they using a custom
+// calling convention which can't be implemented using a normal Rust function
+#[cfg(windows)]
+#[naked]
+#[cfg_attr(not(test), no_mangle)]
+pub unsafe fn ___chkstk_ms() {
+    asm!("push   %rcx
+          push   %rax
+          cmp    $$0x1000,%rax
+          lea    24(%rsp),%rcx
+          jb     1f
+          2:
+          sub    $$0x1000,%rcx
+          test   %rcx,(%rcx)
+          sub    $$0x1000,%rax
+          cmp    $$0x1000,%rax
+          ja     2b
+          1:
+          sub    %rax,%rcx
+          test   %rcx,(%rcx)
+          pop    %rax
+          pop    %rcx
+          ret");
+    intrinsics::unreachable();
+}
+
+#[cfg(windows)]
+#[naked]
+#[cfg_attr(not(test), no_mangle)]
+pub unsafe fn __alloca() {
+    asm!("mov    %rcx,%rax  // x64 _alloca is a normal function with parameter in rcx");
+    // The original behavior had __alloca fall through to ___chkstk here, but
+    // I don't believe that this behavior is guaranteed, and a program that uses
+    // only __alloca could have ___chkstk removed by --gc-sections. Call 
+    // ___chkstk here to guarantee that neither of those happen.
+    ___chkstk();
+}
+
+#[cfg(windows)]
+#[naked]
+#[cfg_attr(not(test), no_mangle)]
+pub unsafe fn ___chkstk() {
+    asm!("push   %rcx
+          cmp    $$0x1000,%rax
+          lea    16(%rsp),%rcx  // rsp before calling this routine -> rcx
+          jb     1f
+          2:
+          sub    $$0x1000,%rcx
+          test   %rcx,(%rcx)
+          sub    $$0x1000,%rax
+          cmp    $$0x1000,%rax
+          ja     2b
+          1:
+          sub    %rax,%rcx
+          test   %rcx,(%rcx)
+
+          lea    8(%rsp),%rax   // load pointer to the return address into rax
+          mov    %rcx,%rsp      // install the new top of stack pointer into rsp
+          mov    -8(%rax),%rcx  // restore rcx
+          push   (%rax)         // push return address onto the stack
+          sub    %rsp,%rax      // restore the original value in rax
+          ret");
+    intrinsics::unreachable();
+}
+