1abcd6accSChris Fallin // A WORD OF CAUTION
2abcd6accSChris Fallin //
3abcd6accSChris Fallin // This entire file basically needs to be kept in sync with itself. It's not
4abcd6accSChris Fallin // really possible to modify just one bit of this file without understanding
5abcd6accSChris Fallin // all the other bits. Documentation tries to reference various bits here and
6abcd6accSChris Fallin // there but try to make sure to read over everything before tweaking things!
7abcd6accSChris Fallin //
8abcd6accSChris Fallin // Also at this time this file is heavily based off the x86_64 file, so you'll
9abcd6accSChris Fallin // probably want to read that one as well.
10abcd6accSChris Fallin
113e9eca8bSAlex Crichton use core::arch::naked_asm;
12abcd6accSChris Fallin
131700302cSAlex Crichton #[inline(never)] // FIXME(rust-lang/rust#148307)
wasmtime_fiber_switch(top_of_stack: *mut u8)141700302cSAlex Crichton pub(crate) unsafe extern "C" fn wasmtime_fiber_switch(top_of_stack: *mut u8) {
151700302cSAlex Crichton unsafe { wasmtime_fiber_switch_(top_of_stack) }
161700302cSAlex Crichton }
171700302cSAlex Crichton
183e9eca8bSAlex Crichton #[unsafe(naked)]
wasmtime_fiber_switch_(top_of_stack: *mut u8 )191700302cSAlex Crichton unsafe extern "C" fn wasmtime_fiber_switch_(top_of_stack: *mut u8 /* r0 */) {
203e9eca8bSAlex Crichton naked_asm!(
21abcd6accSChris Fallin "
22abcd6accSChris Fallin // Save callee-saved registers
23abcd6accSChris Fallin push {{r4-r11,lr}}
24abcd6accSChris Fallin
25abcd6accSChris Fallin // Swap stacks, recording our current stack pointer
26abcd6accSChris Fallin ldr r4, [r0, #-0x08]
27abcd6accSChris Fallin str sp, [r0, #-0x08]
28abcd6accSChris Fallin mov sp, r4
29abcd6accSChris Fallin
30abcd6accSChris Fallin // Restore and return
31abcd6accSChris Fallin pop {{r4-r11,lr}}
32abcd6accSChris Fallin bx lr
33abcd6accSChris Fallin ",
34abcd6accSChris Fallin );
353e9eca8bSAlex Crichton }
36abcd6accSChris Fallin
wasmtime_fiber_init( top_of_stack: *mut u8, entry_point: extern "C" fn(*mut u8, *mut u8) -> *mut u8, entry_arg0: *mut u8, )3765879713SAlex Crichton pub(crate) unsafe fn wasmtime_fiber_init(
3865879713SAlex Crichton top_of_stack: *mut u8,
39*f3156fe0SAlex Crichton entry_point: extern "C" fn(*mut u8, *mut u8) -> *mut u8,
4065879713SAlex Crichton entry_arg0: *mut u8,
413e9eca8bSAlex Crichton ) {
4265879713SAlex Crichton #[repr(C)]
4365879713SAlex Crichton #[derive(Default)]
4465879713SAlex Crichton struct InitialStack {
4565879713SAlex Crichton r4: *mut u8,
4665879713SAlex Crichton r5: *mut u8,
4765879713SAlex Crichton r6: *mut u8,
4865879713SAlex Crichton r7: *mut u8,
4965879713SAlex Crichton r8: *mut u8,
5065879713SAlex Crichton r9: *mut u8,
5165879713SAlex Crichton r10: *mut u8,
5265879713SAlex Crichton r11: *mut u8,
5365879713SAlex Crichton lr: *mut u8,
54abcd6accSChris Fallin
5565879713SAlex Crichton // unix.rs reserved space
5665879713SAlex Crichton last_sp: *mut u8,
5765879713SAlex Crichton run_result: *mut u8,
5865879713SAlex Crichton }
5965879713SAlex Crichton
6065879713SAlex Crichton unsafe {
6165879713SAlex Crichton let initial_stack = top_of_stack.cast::<InitialStack>().sub(1);
6265879713SAlex Crichton initial_stack.write(InitialStack {
63*f3156fe0SAlex Crichton r8: wasmtime_fiber_switch_ as *mut u8,
6465879713SAlex Crichton r9: entry_arg0,
6565879713SAlex Crichton r10: entry_point as *mut u8,
6665879713SAlex Crichton r11: top_of_stack,
6765879713SAlex Crichton lr: wasmtime_fiber_start as *mut u8,
6865879713SAlex Crichton last_sp: initial_stack.cast(),
6965879713SAlex Crichton ..InitialStack::default()
7065879713SAlex Crichton });
7165879713SAlex Crichton }
723e9eca8bSAlex Crichton }
73abcd6accSChris Fallin
743e9eca8bSAlex Crichton #[unsafe(naked)]
wasmtime_fiber_start() -> !753e9eca8bSAlex Crichton unsafe extern "C" fn wasmtime_fiber_start() -> ! {
763e9eca8bSAlex Crichton naked_asm!(
77abcd6accSChris Fallin "
78abcd6accSChris Fallin .cfi_startproc simple
79abcd6accSChris Fallin .cfi_def_cfa_offset 0
80abcd6accSChris Fallin // See the x86_64 file for more commentary on what these CFI directives
81abcd6accSChris Fallin // are doing. Like over there note that the relative offsets to
82abcd6accSChris Fallin // registers here match the frame layout in `wasmtime_fiber_switch`.
83abcd6accSChris Fallin //
84abcd6accSChris Fallin // TODO: this is only lightly tested. This gets backtraces in gdb but
85abcd6accSChris Fallin // not at runtime. Perhaps the libgcc at runtime was too old? Doesn't
86abcd6accSChris Fallin // support something here? Unclear. Will need investigation if someone
87abcd6accSChris Fallin // ends up needing this and it still doesn't work.
88abcd6accSChris Fallin .cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */ \
89abcd6accSChris Fallin 5, /* the byte length of this expression */ \
90abcd6accSChris Fallin 0x7d, 0x00, /* DW_OP_breg14(%sp) + 0 */ \
91abcd6accSChris Fallin 0x06, /* DW_OP_deref */ \
92abcd6accSChris Fallin 0x23, 0x24 /* DW_OP_plus_uconst 0x24 */
93abcd6accSChris Fallin
94abcd6accSChris Fallin .cfi_rel_offset lr, -0x04
95abcd6accSChris Fallin .cfi_rel_offset r11, -0x08
96abcd6accSChris Fallin .cfi_rel_offset r10, -0x0c
97abcd6accSChris Fallin .cfi_rel_offset r9, -0x10
98abcd6accSChris Fallin .cfi_rel_offset r8, -0x14
99abcd6accSChris Fallin .cfi_rel_offset r7, -0x18
100abcd6accSChris Fallin .cfi_rel_offset r6, -0x1c
101abcd6accSChris Fallin .cfi_rel_offset r5, -0x20
102abcd6accSChris Fallin .cfi_rel_offset r4, -0x24
103abcd6accSChris Fallin
104abcd6accSChris Fallin mov r1, r11
105abcd6accSChris Fallin mov r0, r9
106abcd6accSChris Fallin blx r10
107*f3156fe0SAlex Crichton blx r8
108abcd6accSChris Fallin .cfi_endproc
109abcd6accSChris Fallin ",
110abcd6accSChris Fallin );
1113e9eca8bSAlex Crichton }
112