enter_context_x86_64_sysv_elf.s 2.97 KB
Newer Older
1 2 3 4 5 6 7
	.file	"enter_context_x86_64.s"
	.text
	.global	__cs_enter_context
	.type	__cs_enter_context, @function

.align 16
__cs_enter_context:
8 9
        .cfi_startproc
        .cfi_undefined rip
10 11 12 13 14 15 16 17 18 19 20 21
        # Parameter List (in order)
        # rdi = new stack pointer
        # rsi = first parameter to callback
        # rdx = callback function pointer
        # rcx = new stack limit (not used on most platforms)

        # Return
        # rax = continuation that returned control back to the caller (null if fallthrough)

        # Variables
        # r12 = temporary for the old stack pointer

22
        ############### Save State ###############
23 24
        # Make space on the stack
        leaq -0x38(%rsp), %rsp
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
        # 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)
        ############### Save State ###############

        # Perform change to new stack.
        # Keep old stack as second parameter to our callback function.
        movq %rsp, %r12
        # Make sure that stack start is properly aligned.
        andq $-16, %rdi
        # Switch to new stack pointer.
        movq %rdi, %rsp

46 47 48 49 50 51 52
        # Init the new stack to something reasonable.
        # Here we point it at the finish part of our function with the frame pointer at 0x0.
        # This is not stricly required, but stops debuggers/tools from freaking out.
        leaq  __cs_finish(%rip), %r13
        pushq %r13
        pushq $0x0
        movq %rsp, %rbp
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
        # Perform actual function call, this will now be on the new stack
        # rdi = first parametor to callback (continuation)
        # rsi = second parameter to callback (arbetary pointer)
        movq %r12, %rdi
        call *%rdx

        # Restore state of returned continuation.
        # To do so we first reset the stack pointer (which we get returned in rax).
        # After that we execute our standard restore procedere to pop the state from the stack.
        movq %rax, %rsp

        ############ Restore State  ############
        # restore calee saved general registers
        movq 0x00(%rsp), %r12
        movq 0x08(%rsp), %r13
        movq 0x10(%rsp), %r14
        movq 0x18(%rsp), %r15
        movq 0x20(%rsp), %rbx
        movq 0x28(%rsp), %rbp
        # restore MMX control- and status-word
        ldmxcsr 0x30(%rsp)
        # restore x87 control-word
        fldcw 0x34(%rsp)
77 78
        # Free space on the stack
        leaq 0x38(%rsp), %rsp
79 80 81 82 83 84
        ############ Restore State  ############

        # Just return back from the call.
        # This is the end of a fiber, so we have no continuation.
        xor %rax, %rax
        ret
85 86 87 88 89 90 91

__cs_finish:
        # exit code is zero
        xorq  %rdi, %rdi
        # exit application
        call  _exit@PLT
        hlt
92
        .cfi_endproc