tinygo/src/internal/task/task_stack_amd64.S
Ayke van Laethem 9f5066aa6f runtime: use the tasks scheduler instead of coroutines
This results in smaller and likely more efficient code. It does require
some architecture specific code for each architecture, but I've kept the
amount of code as small as possible.
2021-05-09 17:40:13 +02:00

74 строки
2 КиБ
ArmAsm

#ifdef __MACH__ // Darwin
.global _tinygo_startTask
_tinygo_startTask:
#else // Linux etc
.section .text.tinygo_startTask
.global tinygo_startTask
tinygo_startTask:
#endif
.cfi_startproc
// Small assembly stub for starting a goroutine. This is already run on the
// new stack, with the callee-saved registers already loaded.
// Most importantly, r12 contain the pc of the to-be-started function and
// r13 contain the only argument it is given. Multiple arguments are packed
// into one by storing them in a new allocation.
// Indicate to the unwinder that there is nothing to unwind, this is the
// root frame. It avoids bogus extra frames in GDB like here:
// #10 0x00000000004277b6 in <goroutine wrapper> () at [...]
// #11 0x00000000004278f3 in tinygo_startTask () at [...]
// #12 0x0000000000002030 in ?? ()
// #13 0x0000000000000071 in ?? ()
.cfi_undefined rip
// Set the first argument of the goroutine start wrapper, which contains all
// the arguments.
movq %r13, %rdi
// Branch to the "goroutine start" function.
callq *%r12
// After return, exit this goroutine. This is a tail call.
#ifdef __MACH__
jmp _tinygo_pause
#else
jmp tinygo_pause
#endif
.cfi_endproc
#ifdef __MACH__ // Darwin
.global _tinygo_swapTask
_tinygo_swapTask:
#else // Linux etc
.global tinygo_swapTask
.section .text.tinygo_swapTask
tinygo_swapTask:
#endif
// This function gets the following parameters:
// %rdi = newStack uintptr
// %rsi = oldStack *uintptr
// Save all callee-saved registers:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbp
pushq %rbx
// Save the current stack pointer in oldStack.
movq %rsp, (%rsi)
// Switch to the new stack pointer.
movq %rdi, %rsp
// Load saved register from the new stack.
popq %rbx
popq %rbp
popq %r12
popq %r13
popq %r14
popq %r15
// Return into the new task, as if tinygo_swapTask was a regular call.
ret