summary refs log tree commit diff stats
path: root/lib/arch/x86/amd64.S
diff options
context:
space:
mode:
authorRokas Kupstys <rokups@zoho.com>2017-02-20 17:10:50 +0200
committerRokas Kupstys <rokups@zoho.com>2017-02-20 17:24:19 +0200
commit373e667dbc6aff5dd74f5ada139d867287e9dc1f (patch)
tree41da1a7c7298e8ae5f146b528446b3d279480aca /lib/arch/x86/amd64.S
parenta3b8bf300df20f2922275ff62293e3f882cad090 (diff)
downloadNim-373e667dbc6aff5dd74f5ada139d867287e9dc1f.tar.gz
Coroutine rework.
* ucontext backend (default on unix)
* setjmp backend
* fibers backend (default and required on windows)
* Fixed coroutine loop timing issues
* Fixed saving of xmm registers on x64 windows
* Fixed alignment issues
* Updated coroutine sample with cooperative fibonacci calculation.
* Disable glibc security features only when platform jump functions are used
* Removed dependency on fasm.
    * Using fiber api on windows.
    * Other platforms and compilers  will use built in assembler and .S files or API provided by platform libc.
* Replaced stack switching procs with `coroExecWithStack()` which never returns. This makes compiler always generate proper code.
Diffstat (limited to 'lib/arch/x86/amd64.S')
-rw-r--r--lib/arch/x86/amd64.S96
1 files changed, 96 insertions, 0 deletions
diff --git a/lib/arch/x86/amd64.S b/lib/arch/x86/amd64.S
new file mode 100644
index 000000000..47a26f627
--- /dev/null
+++ b/lib/arch/x86/amd64.S
@@ -0,0 +1,96 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2015 Rokas Kupstys
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+# Partially based on code from musl libc Copyright © 2005-2014 Rich Felker, et al.
+
+.globl narch_coroExecWithStack
+.globl narch_setjmp
+.globl narch_longjmp
+.text
+
+
+# SysV ABI - first argument is rdi.
+# MS ABI   - first argument is rcx.
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  #define REG_ARG1 rcx
+  #define REG_ARG2 rdx
+#else
+  #define REG_ARG1 rdi
+  #define REG_ARG2 rsi
+#endif
+
+
+narch_coroExecWithStack:
+  mov  %REG_ARG2, %rsp        # swap stack with one passed to func
+  sub  $0x30, %rsp            # shadow space (for ms ABI) 0x20 + 0x10 for possible misalignment
+  and  $-0x10, %rsp           # 16-byte stack alignment
+  call *%REG_ARG1
+
+
+narch_setjmp:
+  add   $0x10, %REG_ARG1      # 16-byte alignment
+  and   $-0x10, %REG_ARG1
+  mov   %rbx, 0x00(%REG_ARG1) # jmp_buf, move registers onto it
+  mov   %rbp, 0x08(%REG_ARG1)
+  mov   %r12, 0x10(%REG_ARG1)
+  mov   %r13, 0x18(%REG_ARG1)
+  mov   %r14, 0x20(%REG_ARG1)
+  mov   %r15, 0x28(%REG_ARG1)
+  lea   0x08(%rsp), %rdx      # this is our rsp WITHOUT current ret addr
+  mov   %rdx, 0x30(%REG_ARG1)
+  mov   (%rsp), %rdx          # save return addr ptr for new rip
+  mov   %rdx, 0x38(%REG_ARG1)
+  mov   %rsi, 0x40(%REG_ARG1)
+  mov   %rdi, 0x48(%REG_ARG1)
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  movaps %xmm6,  0x50(%REG_ARG1)
+  movaps %xmm7,  0x60(%REG_ARG1)
+  movaps %xmm8,  0x70(%REG_ARG1)
+  movaps %xmm9,  0x80(%REG_ARG1)
+  movaps %xmm10, 0x90(%REG_ARG1)
+  movaps %xmm11, 0xA0(%REG_ARG1)
+  movaps %xmm12, 0xB0(%REG_ARG1)
+  movaps %xmm13, 0xC0(%REG_ARG1)
+  movaps %xmm14, 0xD0(%REG_ARG1)
+  movaps %xmm15, 0xE0(%REG_ARG1)
+#endif
+  xor   %rax, %rax            # always return 0
+  ret
+
+
+narch_longjmp:
+  add   $0x10, %REG_ARG1      # 16-byte alignment
+  and   $-0x10, %REG_ARG1     #
+  mov   %REG_ARG2, %rax       # val will be longjmp return
+  test  %rax, %rax
+  jnz   narch_longjmp_1
+  inc   %rax                  # if val==0, val=1 per longjmp semantics
+narch_longjmp_1:
+  mov   0x00(%REG_ARG1), %rbx # jmp_buf, restore regs from it
+  mov   0x08(%REG_ARG1), %rbp
+  mov   0x10(%REG_ARG1), %r12
+  mov   0x18(%REG_ARG1), %r13
+  mov   0x20(%REG_ARG1), %r14
+  mov   0x28(%REG_ARG1), %r15
+  mov   0x30(%REG_ARG1), %rsp # this ends up being the stack pointer
+  mov   0x38(%REG_ARG1), %rdx # this is the instruction pointer
+  mov   0x40(%REG_ARG1), %rsi
+  mov   0x48(%REG_ARG1), %rdi
+#if defined(__MINGW32__) || defined(__MINGW64__)
+  movaps 0x50(%REG_ARG1), %xmm6
+  movaps 0x60(%REG_ARG1), %xmm7
+  movaps 0x70(%REG_ARG1), %xmm8
+  movaps 0x80(%REG_ARG1), %xmm9
+  movaps 0x90(%REG_ARG1), %xmm10
+  movaps 0xA0(%REG_ARG1), %xmm11
+  movaps 0xB0(%REG_ARG1), %xmm12
+  movaps 0xC0(%REG_ARG1), %xmm13
+  movaps 0xD0(%REG_ARG1), %xmm14
+  movaps 0xE0(%REG_ARG1), %xmm15
+#endif
+  jmp  *%rdx                  # goto saved address without altering rsp