Files
tinygo/src/internal/task/task_stack_amd64_windows.S
T
Ayke van Laethem 95ee572b4d internal/task: rename tinygo_pause to tinygo_task_exit
This is more descriptive: the call is to exit a task, not to pause it.
This also makes it more obvious that there's an optimization
opportunity: to free the stack explicitly after the goroutine returns
(or to keep it as a cache for the next stack allocation).
2025-04-12 13:34:57 +02:00

84 lines
2.3 KiB
ArmAsm

// Windows on amd64 has a slightly different ABI than other (*nix) systems.
// Therefore, assembly functions need to be tweaked slightly.
//
// The calling convention is described here:
// https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
.section .text.tinygo_startTask,"ax"
.global tinygo_startTask
tinygo_startTask:
// 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.
// Set the first argument of the goroutine start wrapper, which contains all
// the arguments.
movq %r13, %rcx
// Branch to the "goroutine start" function.
callq *%r12
// After return, exit this goroutine.
// This has to be a call, not a jump, to keep the stack correctly aligned.
callq tinygo_task_exit
.global tinygo_swapTask
.section .text.tinygo_swapTask,"ax"
tinygo_swapTask:
// This function gets the following parameters:
// %rcx = newStack uintptr
// %rdx = oldStack *uintptr
// Save all callee-saved registers:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rsi
pushq %rdi
pushq %rbp
sub $160, %rsp
movaps %xmm6, 144(%rsp)
movaps %xmm7, 128(%rsp)
movaps %xmm8, 112(%rsp)
movaps %xmm9, 96(%rsp)
movaps %xmm10, 80(%rsp)
movaps %xmm11, 64(%rsp)
movaps %xmm12, 48(%rsp)
movaps %xmm13, 32(%rsp)
movaps %xmm14, 16(%rsp)
movaps %xmm15, 0(%rsp)
pushq %rbx
// Save the current stack pointer in oldStack.
movq %rsp, (%rdx)
// Switch to the new stack pointer.
movq %rcx, %rsp
// Load saved register from the new stack.
popq %rbx
movaps 0(%rsp), %xmm15
movaps 16(%rsp), %xmm14
movaps 32(%rsp), %xmm13
movaps 48(%rsp), %xmm12
movaps 64(%rsp), %xmm11
movaps 80(%rsp), %xmm10
movaps 96(%rsp), %xmm9
movaps 112(%rsp), %xmm8
movaps 128(%rsp), %xmm7
movaps 144(%rsp), %xmm6
add $160, %rsp
popq %rbp
popq %rdi
popq %rsi
popq %r12
popq %r13
popq %r14
popq %r15
// Return into the new task, as if tinygo_swapTask was a regular call.
ret