Skip to content

Commit b6091ab

Browse files
committed
Add x86_64 builtins
1 parent 89594e1 commit b6091ab

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ extern crate rlibc;
2323
#[cfg(target_arch = "arm")]
2424
pub mod arm;
2525

26+
#[cfg(target_arch = "x86_64")]
27+
pub mod x86_64;
28+
2629
pub mod udiv;
2730
pub mod mul;
2831
pub mod shift;

src/x86_64.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use core::intrinsics;
2+
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+
#[cfg(windows)]
6+
#[naked]
7+
#[cfg_attr(not(test), no_mangle)]
8+
pub unsafe fn ___chkstk_ms() {
9+
asm!("push %rcx
10+
push %rax
11+
cmp $$0x1000,%rax
12+
lea 24(%rsp),%rcx
13+
jb 1f
14+
2:
15+
sub $$0x1000,%rcx
16+
test %rcx,(%rcx)
17+
sub $$0x1000,%rax
18+
cmp $$0x1000,%rax
19+
ja 2b
20+
1:
21+
sub %rax,%rcx
22+
test %rcx,(%rcx)
23+
pop %rax
24+
pop %rcx
25+
ret");
26+
intrinsics::unreachable();
27+
}
28+
29+
#[cfg(windows)]
30+
#[naked]
31+
#[cfg_attr(not(test), no_mangle)]
32+
pub unsafe fn __alloca() {
33+
asm!("mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx");
34+
// The original behavior had __alloca fall through to ___chkstk here, but
35+
// I don't believe that this behavior is guaranteed, and a program that uses
36+
// only __alloca could have ___chkstk removed by --gc-sections. Call
37+
// ___chkstk here to guarantee that neither of those happen.
38+
___chkstk();
39+
}
40+
41+
#[cfg(windows)]
42+
#[naked]
43+
#[cfg_attr(not(test), no_mangle)]
44+
pub unsafe fn ___chkstk() {
45+
asm!("push %rcx
46+
cmp $$0x1000,%rax
47+
lea 16(%rsp),%rcx // rsp before calling this routine -> rcx
48+
jb 1f
49+
2:
50+
sub $$0x1000,%rcx
51+
test %rcx,(%rcx)
52+
sub $$0x1000,%rax
53+
cmp $$0x1000,%rax
54+
ja 2b
55+
1:
56+
sub %rax,%rcx
57+
test %rcx,(%rcx)
58+
59+
lea 8(%rsp),%rax // load pointer to the return address into rax
60+
mov %rcx,%rsp // install the new top of stack pointer into rsp
61+
mov -8(%rax),%rcx // restore rcx
62+
push (%rax) // push return address onto the stack
63+
sub %rsp,%rax // restore the original value in rax
64+
ret");
65+
intrinsics::unreachable();
66+
}
67+

0 commit comments

Comments
 (0)