github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_386.S (about) 1 .section .text.tinygo_startTask 2 .global tinygo_startTask 3 .type tinygo_startTask, %function 4 tinygo_startTask: 5 .cfi_startproc 6 // Small assembly stub for starting a goroutine. This is already run on the 7 // new stack, with the callee-saved registers already loaded. 8 // Most importantly, EBX contain the pc of the to-be-started function and 9 // ESI contain the only argument it is given. Multiple arguments are packed 10 // into one by storing them in a new allocation. 11 12 // Indicate to the unwinder that there is nothing to unwind, this is the 13 // root frame. It avoids bogus extra frames in GDB. 14 .cfi_undefined eip 15 16 // Set the first argument of the goroutine start wrapper, which contains all 17 // the arguments. 18 pushl %esi 19 20 // Branch to the "goroutine start" function. 21 calll *%ebx 22 23 // Rebalance the stack (to undo the above push). 24 addl $4, %esp 25 26 // After return, exit this goroutine. This is a tail call. 27 jmp tinygo_pause 28 .cfi_endproc 29 30 .global tinygo_swapTask 31 .type tinygo_swapTask, %function 32 tinygo_swapTask: 33 // This function gets the following parameters: 34 movl 4(%esp), %eax // newStack uintptr 35 movl 8(%esp), %ecx // oldStack *uintptr 36 // More information on the calling convention: 37 // https://wiki.osdev.org/System_V_ABI#i386 38 39 // Save all callee-saved registers: 40 pushl %ebp 41 pushl %edi 42 pushl %esi 43 pushl %ebx 44 45 // Save the current stack pointer in oldStack. 46 movl %esp, (%ecx) 47 48 // Switch to the new stack pointer. 49 movl %eax, %esp 50 51 // Load saved register from the new stack. 52 popl %ebx 53 popl %esi 54 popl %edi 55 popl %ebp 56 57 // Return into the new task, as if tinygo_swapTask was a regular call. 58 ret