2014-12-24 13:12:39 +08:00
|
|
|
use std::simd::u64x2;
|
|
|
|
use std::mem::{size_of, zeroed};
|
|
|
|
|
|
|
|
use stack::Stack;
|
|
|
|
|
|
|
|
extern "C" {
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_bootstrap"]
|
2014-12-24 13:12:39 +08:00
|
|
|
pub fn bootstrap();
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_swapcontext"]
|
2014-12-24 13:12:39 +08:00
|
|
|
pub fn swapcontext(save: *mut Registers, restore: *mut Registers);
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_get_sp_limit"]
|
2014-12-24 13:12:39 +08:00
|
|
|
pub fn get_sp_limit() -> *const u8;
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_set_sp_limit"]
|
2014-12-24 13:12:39 +08:00
|
|
|
pub fn set_sp_limit(limit: *const u8);
|
2014-12-24 13:37:16 +08:00
|
|
|
#[link_name = "lwt_abort"]
|
2014-12-24 13:12:39 +08:00
|
|
|
pub fn abort() -> !;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
pub type uintptr_t = u64;
|
|
|
|
|
|
|
|
#[repr(C)]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub struct Registers {
|
|
|
|
rbx: u64,
|
|
|
|
rsp: u64,
|
|
|
|
rbp: u64,
|
|
|
|
rdi: u64,
|
|
|
|
r12: u64,
|
|
|
|
r13: u64,
|
|
|
|
r14: u64,
|
|
|
|
r15: u64,
|
|
|
|
ip: u64,
|
|
|
|
xmm0: u64x2,
|
|
|
|
xmm1: u64x2,
|
|
|
|
xmm2: u64x2,
|
|
|
|
xmm3: u64x2,
|
|
|
|
xmm4: u64x2,
|
|
|
|
xmm5: u64x2,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Registers {
|
|
|
|
pub fn new() -> Registers {
|
|
|
|
unsafe {
|
|
|
|
Registers {
|
2014-12-24 13:52:52 +08:00
|
|
|
ip: abort as uintptr_t,
|
2014-12-24 13:12:39 +08:00
|
|
|
.. zeroed()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn initialise_call_frame(stack: &mut Stack, init: uintptr_t, args: &[uintptr_t]) -> Registers {
|
|
|
|
let sp = stack.top() as *mut uintptr_t;
|
|
|
|
let sp = align_down_mut(sp, 16);
|
|
|
|
let sp = offset_mut(sp, -1);
|
|
|
|
unsafe {
|
|
|
|
*sp = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut regs = Registers {
|
|
|
|
rbp: 0,
|
|
|
|
rsp: sp as uintptr_t,
|
|
|
|
ip: bootstrap as uintptr_t,
|
2014-12-24 13:48:49 +08:00
|
|
|
rbx: init,
|
2014-12-24 13:12:39 +08:00
|
|
|
.. Registers::new()
|
|
|
|
};
|
|
|
|
|
2014-12-24 13:48:49 +08:00
|
|
|
match into_fields!(regs { rdi, r12, r13, r14, r15 } <- args.iter().cloned()) {
|
2014-12-24 13:12:39 +08:00
|
|
|
Some(mut args) => if args.next().is_some() {
|
|
|
|
panic!("too many arguments")
|
|
|
|
},
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
regs
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn align_down_mut<T>(sp: *mut T, n: uint) -> *mut T {
|
|
|
|
let sp = (sp as uint) & !(n - 1);
|
|
|
|
sp as *mut T
|
|
|
|
}
|
|
|
|
|
|
|
|
// ptr::offset_mmut is positive ints only
|
|
|
|
#[inline]
|
|
|
|
pub fn offset_mut<T>(ptr: *mut T, count: int) -> *mut T {
|
|
|
|
(ptr as int + count * (size_of::<T>() as int)) as *mut T
|
|
|
|
}
|