Skip to content

Commit

Permalink
Add aarch64 support on Linux and macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesbornholt authored and Xudong-Huang committed Dec 8, 2020
1 parent 4af7740 commit 975f053
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ os:
- linux
- osx

arch:
- amd64
- arm64

rust:
- stable
- nightly
Expand Down
4 changes: 2 additions & 2 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn main() {

let arch = match target.split('-').next().unwrap() {
// "arm" | "armv7" | "armv7s" => "arm",
// "arm64" | "aarch64" => "arm64",
"arm64" | "aarch64" => "aarch64",
// "x86" | "i386" | "i486" | "i586" | "i686" => "i386",
// "mips" | "mipsel" => "mips32",
// "powerpc" => "ppc32",
Expand All @@ -33,7 +33,7 @@ fn main() {
};

let abi = match arch {
"arm" | "arm64" => "aapcs",
"arm" | "aarch64" => "aapcs",
"mips32" => "o32",
_ => {
if is_win {
Expand Down
65 changes: 65 additions & 0 deletions src/detail/aarch64_unix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::detail::align_down;
use crate::reg_context::InitFn;
use crate::stack::Stack;

#[link(name = "asm", kind = "static")]
extern "C" {
pub fn bootstrap_green_task();
pub fn prefetch(data: *const usize);
pub fn swap_registers(out_regs: *mut Registers, in_regs: *const Registers);
}

#[repr(C)]
#[derive(Debug)]
pub struct Registers {
// We only save the 13 callee-saved registers:
// x19--x28, fp (x29), lr (x30), sp
gpr: [usize; 13],
}

impl Registers {
pub fn new() -> Registers {
Registers { gpr: [0; 13] }
}

#[inline]
pub fn prefetch(&self) {
unsafe {
prefetch(self as *const _ as *const usize);
prefetch(self.gpr[1] as *const usize);
}
}
}

pub fn initialize_call_frame(
regs: &mut Registers,
fptr: InitFn,
arg: usize,
arg2: *mut usize,
stack: &Stack,
) {
// Callee-saved registers start at x19
const X19: usize = 19 - 19;
const X20: usize = 20 - 19;
const X21: usize = 21 - 19;
const FP: usize = 29 - 19;
const LR: usize = 30 - 19;
const SP: usize = 31 - 19;

let sp = align_down(stack.end());

// These registers are frobbed by bootstrap_green_task into the right
// location so we can invoke the "real init function", `fptr`.
regs.gpr[X19] = arg;
regs.gpr[X20] = arg2 as usize;
regs.gpr[X21] = fptr as usize;

// Last frame pointer should be 0
regs.gpr[FP] = 0;

regs.gpr[LR] = bootstrap_green_task as usize;

// setup the init stack
// this is prepared for the swap context
regs.gpr[SP] = sp as usize;
}
50 changes: 50 additions & 0 deletions src/detail/asm/asm_aarch64_aapcs_elf_gas.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.text
.globl prefetch
.type prefetch,@function
.align 16
prefetch:
prfm pldl1keep, [x0]
ret
.size prefetch,.-prefetch

.text
.globl bootstrap_green_task
.type bootstrap_green_task,@function
.align 16
bootstrap_green_task:
mov x0, x19 // arg0
mov x1, x20 // arg1
mov x30, x21 // return address (lr == x30 but GCC rejects `lr`)
ret
.size bootstrap_green_task,.-bootstrap_green_task

.text
.globl swap_registers
.type swap_registers,@function
.align 16
swap_registers:
stp x19, x20, [x0, #0]
stp x21, x22, [x0, #16]
stp x23, x24, [x0, #32]
stp x25, x26, [x0, #48]
stp x27, x28, [x0, #64]
stp x29, x30, [x0, #80]

mov x2, sp
str x2, [x0, #96]

ldp x19, x20, [x1, #0]
ldp x21, x22, [x1, #16]
ldp x23, x24, [x1, #32]
ldp x25, x26, [x1, #48]
ldp x27, x28, [x1, #64]
ldp x29, x30, [x1, #80]

ldr x2, [x1, #96]
mov sp, x2

ret
.size swap_registers,.-swap_registers

/* Mark that we don't need executable stack. */
.section .note.GNU-stack,"",%progbits
41 changes: 41 additions & 0 deletions src/detail/asm/asm_aarch64_aapcs_macho_gas.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.text
.globl _prefetch
.align 8
_prefetch:
prfm pldl1keep, [x0]
ret

.text
.globl _bootstrap_green_task
.align 8
_bootstrap_green_task:
mov x0, x19 // arg0
mov x1, x20 // arg1
mov lr, x21 // return address
ret

.text
.globl _swap_registers
.align 8
_swap_registers:
stp x19, x20, [x0, #0]
stp x21, x22, [x0, #16]
stp x23, x24, [x0, #32]
stp x25, x26, [x0, #48]
stp x27, x28, [x0, #64]
stp x29, x30, [x0, #80]

mov x2, sp
str x2, [x0, #96]

ldp x19, x20, [x1, #0]
ldp x21, x22, [x1, #16]
ldp x23, x24, [x1, #32]
ldp x25, x26, [x1, #48]
ldp x27, x28, [x1, #64]
ldp x29, x30, [x1, #80]

ldr x2, [x1, #96]
mov sp, x2

ret
5 changes: 5 additions & 0 deletions src/detail/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ pub mod asm;
#[path = "x86_64_windows.rs"]
pub mod asm;

#[cfg(all(unix, target_arch = "aarch64"))]
#[path = "aarch64_unix.rs"]
pub mod asm;

pub use self::asm::{initialize_call_frame, prefetch, swap_registers, Registers};

#[inline]
Expand All @@ -39,6 +43,7 @@ fn align_down(sp: *mut usize) -> *mut usize {

// ptr::mut_offset is positive isizes only
#[inline]
#[allow(unused)]
fn mut_offset<T>(ptr: *mut T, count: isize) -> *mut T {
// use std::mem::size_of;
// (ptr as isize + count * (size_of::<T>() as isize)) as *mut T
Expand Down
4 changes: 4 additions & 0 deletions src/stack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use std::ptr;
#[path = "unix.rs"]
pub mod sys;

#[cfg(all(unix, target_arch = "aarch64"))]
#[path = "unix.rs"]
pub mod sys;

#[cfg(all(windows, target_arch = "x86_64"))]
#[path = "windows.rs"]
pub mod sys;
Expand Down

0 comments on commit 975f053

Please sign in to comment.