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