github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_amd64_windows.S (about)

     1  // Windows on amd64 has a slightly different ABI than other (*nix) systems.
     2  // Therefore, assembly functions need to be tweaked slightly.
     3  //
     4  // The calling convention is described here:
     5  // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170
     6  
     7  .section .text.tinygo_startTask,"ax"
     8  .global  tinygo_startTask
     9  tinygo_startTask:
    10      // Small assembly stub for starting a goroutine. This is already run on the
    11      // new stack, with the callee-saved registers already loaded.
    12      // Most importantly, r12 contain the pc of the to-be-started function and
    13      // r13 contain the only argument it is given. Multiple arguments are packed
    14      // into one by storing them in a new allocation.
    15  
    16      // Set the first argument of the goroutine start wrapper, which contains all
    17      // the arguments.
    18      movq %r13, %rcx
    19  
    20      // Branch to the "goroutine start" function.
    21      callq *%r12
    22  
    23      // After return, exit this goroutine.
    24      // This has to be a call, not a jump, to keep the stack correctly aligned.
    25      callq tinygo_pause
    26  
    27  .global tinygo_swapTask
    28  .section .text.tinygo_swapTask,"ax"
    29  tinygo_swapTask:
    30      // This function gets the following parameters:
    31      // %rcx = newStack uintptr
    32      // %rdx = oldStack *uintptr
    33  
    34      // Save all callee-saved registers:
    35      pushq %r15
    36      pushq %r14
    37      pushq %r13
    38      pushq %r12
    39      pushq %rsi
    40      pushq %rdi
    41      pushq %rbp
    42      sub   $160, %rsp
    43      movaps  %xmm6, 144(%rsp)
    44      movaps  %xmm7, 128(%rsp)
    45      movaps  %xmm8, 112(%rsp)
    46      movaps  %xmm9,  96(%rsp)
    47      movaps  %xmm10, 80(%rsp)
    48      movaps  %xmm11, 64(%rsp)
    49      movaps  %xmm12, 48(%rsp)
    50      movaps  %xmm13, 32(%rsp)
    51      movaps  %xmm14, 16(%rsp)
    52      movaps  %xmm15,  0(%rsp)
    53      pushq %rbx
    54  
    55      // Save the current stack pointer in oldStack.
    56      movq %rsp, (%rdx)
    57  
    58      // Switch to the new stack pointer.
    59      movq %rcx, %rsp
    60  
    61      // Load saved register from the new stack.
    62      popq %rbx
    63      movaps 0(%rsp),   %xmm15
    64      movaps 16(%rsp),  %xmm14
    65      movaps 32(%rsp),  %xmm13
    66      movaps 48(%rsp),  %xmm12
    67      movaps 64(%rsp),  %xmm11
    68      movaps 80(%rsp),  %xmm10
    69      movaps 96(%rsp),  %xmm9
    70      movaps 112(%rsp), %xmm8
    71      movaps 128(%rsp), %xmm7
    72      movaps 144(%rsp), %xmm6
    73      add   $160, %rsp
    74      popq %rbp
    75      popq %rdi
    76      popq %rsi
    77      popq %r12
    78      popq %r13
    79      popq %r14
    80      popq %r15
    81  
    82      // Return into the new task, as if tinygo_swapTask was a regular call.
    83      ret