github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/internal/task/task_stack_arm.S (about) 1 //go:build tinygo 2 3 // Only generate .debug_frame, don't generate .eh_frame. 4 .cfi_sections .debug_frame 5 6 .section .text.tinygo_startTask 7 .global tinygo_startTask 8 .type tinygo_startTask, %function 9 tinygo_startTask: 10 .cfi_startproc 11 // Small assembly stub for starting a goroutine. This is already run on the 12 // new stack, with the callee-saved registers already loaded. 13 // Most importantly, r4 contains the pc of the to-be-started function and r5 14 // contains the only argument it is given. Multiple arguments are packed 15 // into one by storing them in a new allocation. 16 17 // Indicate to the unwinder that there is nothing to unwind, this is the 18 // root frame. It avoids the following (bogus) error message in GDB: 19 // Backtrace stopped: previous frame identical to this frame (corrupt stack?) 20 .cfi_undefined lr 21 22 // Set the first argument of the goroutine start wrapper, which contains all 23 // the arguments. 24 mov r0, r5 25 26 // Branch to the "goroutine start" function. By using blx instead of bx, 27 // we'll return here instead of tail calling. 28 blx r4 29 30 // After return, exit this goroutine. This is a tail call. 31 bl tinygo_pause 32 .cfi_endproc 33 .size tinygo_startTask, .-tinygo_startTask 34 35 .global tinygo_swapTask 36 .type tinygo_swapTask, %function 37 tinygo_swapTask: 38 // This function gets the following parameters: 39 // r0 = newStack uintptr 40 // r1 = oldStack *uintptr 41 42 // Save all callee-saved registers: 43 push {r4-r11, lr} 44 45 // Save the current stack pointer in oldStack. 46 str sp, [r1] 47 48 // Switch to the new stack pointer. 49 mov sp, r0 50 51 // Load state from new task and branch to the previous position in the 52 // program. 53 pop {r4-r11, pc}