	.file	"fiber_call_x86_64.s"
	.text
	.global	fiber_call
	.type	fiber_call, @function

.align 16
fiber_call:
        # rdi = address of new stack top and to store current stack top (parameter to function)
        # r12 temporary for restoring old stack (callee saved, so we can take a 'fast' return path)

        ############### Register State Storage ################
        # make space for all register state we will store
        leaq -0x38(%rsp), %rsp

        # store calee saved general registers
        movq %r12, 0x00(%rsp)
        movq %r13, 0x08(%rsp)
        movq %r14, 0x10(%rsp)
        movq %r15, 0x18(%rsp)
        movq %rbx, 0x20(%rsp)
        movq %rbp, 0x28(%rsp)
        # store MMX control- and status-word
        stmxcsr 0x30(%rsp)
        # store x87 control-word
        fnstcw 0x34(%rsp)

        ############### Stack Pointer Manipulation #############
        # keep the old stack pointer in a callee-saved register for 'fast' return path
        movq %rsp, %r12
        # switch to new stack pointer
        movq (%rdi), %rsp
        # store old stack pointer
        movq %r12, (%rdi)

        ############# Function Call ############################
        # perform actual function call, this will now be on the new stack
        call callback
        # If someone else continued/jumped into this stored context we must not return here,
        # thus we will never execute the rest of the function.
        # Otherwise we can return out of the function as if it was a simple function call.

        ############ Stack Pointer Manipulation ################
        # restore stack pointer that we had before
        movq %r12, %rsp

        ############ Restore State Storage (as needed) #########
        # ...we don't need to restore most registers (as they are calee saved).
        # We only used %r12, so restore that and move back the stack pointer.
        movq 0x00(%rsp), %r12

        # release the space we used for storage
        leaq 0x38(%rsp), %rsp

        # just return back from the call
        ret
