1#
2#
3#            Nim's Runtime Library
4#        (c) Copyright 2015 Rokas Kupstys
5#
6#    See the file "copying.txt", included in this
7#    distribution, for details about the copyright.
8#
9# Partially based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
10
11.globl narch_coroExecWithStack
12.globl narch_setjmp
13.globl narch_longjmp
14.text
15
16
17# SysV ABI - first argument is rdi.
18# MS ABI   - first argument is rcx.
19#if defined(__MINGW32__) || defined(__MINGW64__)
20  #define REG_ARG1 rcx
21  #define REG_ARG2 rdx
22#else
23  #define REG_ARG1 rdi
24  #define REG_ARG2 rsi
25#endif
26
27
28narch_coroExecWithStack:
29  mov  %REG_ARG2, %rsp        # swap stack with one passed to func
30  sub  $0x30, %rsp            # shadow space (for ms ABI) 0x20 + 0x10 for possible misalignment
31  and  $-0x10, %rsp           # 16-byte stack alignment
32  call *%REG_ARG1
33
34
35narch_setjmp:
36  add   $0x10, %REG_ARG1      # 16-byte alignment
37  and   $-0x10, %REG_ARG1
38  mov   %rbx, 0x00(%REG_ARG1) # jmp_buf, move registers onto it
39  mov   %rbp, 0x08(%REG_ARG1)
40  mov   %r12, 0x10(%REG_ARG1)
41  mov   %r13, 0x18(%REG_ARG1)
42  mov   %r14, 0x20(%REG_ARG1)
43  mov   %r15, 0x28(%REG_ARG1)
44  lea   0x08(%rsp), %rdx      # this is our rsp WITHOUT current ret addr
45  mov   %rdx, 0x30(%REG_ARG1)
46  mov   (%rsp), %rdx          # save return addr ptr for new rip
47  mov   %rdx, 0x38(%REG_ARG1)
48  mov   %rsi, 0x40(%REG_ARG1)
49  mov   %rdi, 0x48(%REG_ARG1)
50#if defined(__MINGW32__) || defined(__MINGW64__)
51  movaps %xmm6,  0x50(%REG_ARG1)
52  movaps %xmm7,  0x60(%REG_ARG1)
53  movaps %xmm8,  0x70(%REG_ARG1)
54  movaps %xmm9,  0x80(%REG_ARG1)
55  movaps %xmm10, 0x90(%REG_ARG1)
56  movaps %xmm11, 0xA0(%REG_ARG1)
57  movaps %xmm12, 0xB0(%REG_ARG1)
58  movaps %xmm13, 0xC0(%REG_ARG1)
59  movaps %xmm14, 0xD0(%REG_ARG1)
60  movaps %xmm15, 0xE0(%REG_ARG1)
61#endif
62  xor   %rax, %rax            # always return 0
63  ret
64
65
66narch_longjmp:
67  add   $0x10, %REG_ARG1      # 16-byte alignment
68  and   $-0x10, %REG_ARG1     #
69  mov   %REG_ARG2, %rax       # val will be longjmp return
70  test  %rax, %rax
71  jnz   narch_longjmp_1
72  inc   %rax                  # if val==0, val=1 per longjmp semantics
73narch_longjmp_1:
74  mov   0x00(%REG_ARG1), %rbx # jmp_buf, restore regs from it
75  mov   0x08(%REG_ARG1), %rbp
76  mov   0x10(%REG_ARG1), %r12
77  mov   0x18(%REG_ARG1), %r13
78  mov   0x20(%REG_ARG1), %r14
79  mov   0x28(%REG_ARG1), %r15
80  mov   0x30(%REG_ARG1), %rsp # this ends up being the stack pointer
81  mov   0x38(%REG_ARG1), %rdx # this is the instruction pointer
82  mov   0x40(%REG_ARG1), %rsi
83  mov   0x48(%REG_ARG1), %rdi
84#if defined(__MINGW32__) || defined(__MINGW64__)
85  movaps 0x50(%REG_ARG1), %xmm6
86  movaps 0x60(%REG_ARG1), %xmm7
87  movaps 0x70(%REG_ARG1), %xmm8
88  movaps 0x80(%REG_ARG1), %xmm9
89  movaps 0x90(%REG_ARG1), %xmm10
90  movaps 0xA0(%REG_ARG1), %xmm11
91  movaps 0xB0(%REG_ARG1), %xmm12
92  movaps 0xC0(%REG_ARG1), %xmm13
93  movaps 0xD0(%REG_ARG1), %xmm14
94  movaps 0xE0(%REG_ARG1), %xmm15
95#endif
96  jmp  *%rdx                  # goto saved address without altering rsp
97