Commit 18d3368e authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Preparations for swapstack impl

parent 57fc7151
......@@ -28,6 +28,10 @@
.size \n, .-\n
.endm
.macro global_label n
.globl \n
\n:
.endm
#else
#error "Only Linux is supported."
#endif
......@@ -89,3 +93,41 @@ pop_pair d5, d4, \stack
pop_pair d3, d2, \stack
pop_pair d1, d0, \stack
.endm
.macro mov_args_to_callee_saved
MOV X19, X0
MOV X20, X1
MOV X21, X2
MOV X22, X3
MOV X23, X4
MOV X24, X5
MOV X25, X6
MOV X26, X7
FMOV D8, D0
FMOV D9, D1
FMOV D10, D2
FMOV D11, D3
FMOV D12, D4
FMOV D13, D5
FMOV D14, D6
FMOV D15, D7
.endm
.macro mov_callee_saved_to_args
MOV X0, X19
MOV X1, X20
MOV X2, X21
MOV X3, X22
MOV X4, X23
MOV X5, X24
MOV X6, X25
MOV X7, X26
FMOV D0, D8
FMOV D1, D9
FMOV D2, D10
FMOV D3, D11
FMOV D4, D12
FMOV D5, D13
FMOV D6, D14
FMOV D7, D15
.endm
\ No newline at end of file
......@@ -51,8 +51,8 @@ end_func swap_to_mu_stack
.type .Lentry_returned_message, @object
.section .rodata.str1.1,"aMS",@progbits,1
.Lentry_returned_message:
.asciz "ERROR: The entry function returned\n"
.size .Lentry_returned_message, 36
.asciz "ERROR: The entry function returned\n"
.size .Lentry_returned_message, 36
# Prints an error mesage and calls exit(1)
begin_func entry_returned
......@@ -100,13 +100,9 @@ begin_func muentry_throw_exception
MOV FP, SP
push_callee_saved
MOV X1, FP // X1 is the frame pointer
#if defined (__linux__)
BL throw_exception_internal
#else
#error "Only Linux is supported. "
#endif
# won't return
end_func muentry_throw_exception
# _exception_restore(dest: Address, frame_cursor: *const Word, sp: Address) -> !
# X0 X1 X2
begin_func exception_restore
......@@ -117,3 +113,89 @@ begin_func exception_restore
MOV SP, X2
BR X0
end_func exception_restore
# swap to the new stack whilst passing values and saving the old stack
# muentry_swapstack_save_value(new_stack args..., new_sp: Address, old_sp_loc: &mut Adress)
# X0 ... X7 X8 X9
begin_func muentry_swapstack_save_value
enter_frame
push_callee_saved
# Save the current stack pointer
MOV X10, SP
STR X10, [X9]
# Swap to new stack
MOV SP, X8
# On the new stack, reverse the above
pop_callee_saved
exit_frame
RET
end_func
# Same as swapstack_save_value except will throw an exception to the new stack instead of passing values
# muentry_swapstack_except(exception: Address, new_sp: Address, old_sp_loc: &mut Adress)
# X0 X1 X2
begin_func muentry_swapstack_save_exception
enter_frame
push_callee_saved
# Save the current stack pointer
MOV X3, SP
STR X3, [X2]
# Swap to new stack
MOV SP, X1
# The new stack will have the same layout as the stack when muentry_throw_exception
# calls throw_exception_internal, so we can do that directly here
# Add the total size pushed by 'push_callee_saved' to get the FP for the new stack
ADD FP, SP, 144
MOV X1, FP
BL throw_exception_internal
# won't return
end_func
# swap to the new stack whilst passing values and killing the old stack
# muentry_swapstack_save_value(new_stack args..., new_sp: Address, old_stack: *mut MuStack)
# X0 ... X7 X8 X9
begin_func muentry_swapstack_kill_value
# Swap to new stack
MOV SP, X8
mov_args_to_callee_saved
MOV X0, X9
B kill_stack
mov_callee_saved_to_args
# On the new stack, reverse muentry_swapstack_save_value
pop_callee_saved
exit_frame
RET
end_func
# Same as swapstack_save_value except will throw an exception to the new stack instead of passing values
# muentry_swapstack_except(exception: Address, new_sp: Address, old_stack: *mut MuStack)
# X0 X1 X2
begin_func muentry_swapstack_kill_exception
# Swap to new stack
MOV SP, X1
mov_args_to_callee_saved
MOV X0, X9
B kill_stack
mov_callee_saved_to_args
# The new stack will have the same layout as the stack when muentry_throw_exception
# calls throw_exception_internal, so we can do that directly here
# Add the total size pushed by 'push_callee_saved' to get the FP for the new stack
ADD FP, SP, 144
MOV X1, FP
BL throw_exception_internal
# won't return
end_func
\ No newline at end of file
......@@ -174,7 +174,7 @@ impl MuStack {
use utils::Word;
use utils::WORD_SIZE;
use compiler::backend::RegGroup;
use compiler::backend::{ARGUMENT_GPRS, ARGUMENT_FPRS};
use compiler::backend::{ARGUMENT_FPRS, ARGUMENT_GPRS};
let mut gpr_used = vec![];
let mut fpr_used = vec![];
......@@ -434,12 +434,10 @@ impl MuThread {
match thread::Builder::new()
.name(format!("Mu Thread #{}", id))
.spawn(move || {
let muthread: *mut MuThread = Box::into_raw(Box::new(
MuThread::new(id, mm::new_mutator(), stack, user_tls, vm)
));
let mut muthread = MuThread::new(id, mm::new_mutator(), stack, user_tls, vm);
// set thread local
unsafe { set_thread_local(muthread) };
unsafe { set_thread_local(&mut muthread) };
let addr = unsafe { muentry_get_thread_local() };
let sp_threadlocal_loc = addr + *NATIVE_SP_LOC_OFFSET;
......@@ -597,3 +595,39 @@ rodal_struct!(PrimordialThreadInfo {
args,
has_const_args
});
// This prepares a thread for a swap stack operation that saves the current stack
// it returns the SP to swap to, and a pointer to where to save the current SP
// (it should be called before arguments are passed to the new stack, and before
// the new stack is swapped to)
#[no_mangle]
pub unsafe extern "C" fn prepare_swapstack_save(new_stack: *mut MuStack)
-> (Address, *mut Address) {
let cur_thread = MuThread::current_mut();
// Save the current stack, don't deallocate it
let cur_stack = Box::into_raw(cur_thread.stack.take().unwrap());
cur_thread.stack = Some(Box::from_raw(new_stack));
((*new_stack).sp, &mut (*cur_stack).sp)
}
// This prepares a thread for a swap stack operation that kills the current stack
// it returns the SP to swap to, and a pointer to the MuStack that should be dropped
// (it should be called before arguments are passed to the new stack, and before
// the new stack is swapped to)
#[no_mangle]
pub unsafe extern "C" fn prepare_swapstack_kill(new_stack: *mut MuStack)
-> (Address, *mut MuStack) {
let cur_thread = MuThread::current_mut();
// Save the current stack, don't deallocate it until safe to do so
// (i.e. when were are not on the current stack)
let cur_stack = Box::into_raw(cur_thread.stack.take().unwrap());
cur_thread.stack = Some(Box::from_raw(new_stack));
((*new_stack).sp, cur_stack)
}
// Kills the given stack. WARNING! do not call this whilst on the given stack
#[no_mangle]
pub unsafe extern "C" fn kill_stack(stack: *mut MuStack) {
// This new box will be destroyed upon returning
Box::from_raw(stack);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment