소스 검색

Merge pull request #40 from mattico/add-x86_64

Add x86_64 builtins
Jorge Aparicio 8 년 전
부모
커밋
74cd512caa
3개의 변경된 파일73개의 추가작업 그리고 2개의 파일을 삭제
  1. 2 2
      README.md
  2. 3 0
      src/lib.rs
  3. 68 0
      src/x86_64.rs

+ 2 - 2
README.md

@@ -133,8 +133,8 @@ See [rust-lang/rust#35437][0].
 - [x] udivsi3.c
 - [x] umoddi3.c
 - [x] umodsi3.c
-- [ ] x86_64/chkstk.S
-- [ ] x86_64/chkstk2.S
+- [x] x86_64/chkstk.S
+- [x] x86_64/chkstk2.S
 
 These builtins are needed to support 128-bit integers, which are in the process of being added to Rust.
 

+ 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;

+ 68 - 0
src/x86_64.rs

@@ -0,0 +1,68 @@
+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
+
+// NOTE These functions are never mangled as they are not tested against compiler-rt
+// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
+
+#[cfg(windows)]
+#[naked]
+#[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]
+#[no_mangle]
+pub unsafe fn __alloca() {
+    asm!("mov    %rcx,%rax  // x64 _alloca is a normal function with parameter in rcx
+          jmp    ___chkstk  // Jump to ___chkstk since fallthrough may be unreliable");
+    intrinsics::unreachable();
+}
+
+#[cfg(windows)]
+#[naked]
+#[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();
+}
+