From 78f7ab4189614860e9802a1ce964c718c6d2cb9c Mon Sep 17 00:00:00 2001
From: root <root>
Date: Wed, 2 May 2007 05:53:26 +0000
Subject: *** empty log message ***

---
 coro.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 coro.h | 43 ++++++++++++++++++++++++++++++-------------
 2 files changed, 81 insertions(+), 17 deletions(-)

diff --git a/coro.c b/coro.c
index c95de5e..ebc9654 100644
--- a/coro.c
+++ b/coro.c
@@ -53,7 +53,7 @@
 # include <stddef.h>
 #endif
 
-#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX
+#if CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX || CORO_ASM
 
 #include <stdlib.h>
 
@@ -113,6 +113,46 @@ trampoline (int sig)
 
 #endif
 
+#if CORO_ASM
+void __attribute__((__noinline__, __fastcall__))
+coro_transfer (struct coro_context *prev, struct coro_context *next)
+{
+  asm volatile (
+#if __amd64
+# define NUM_CLOBBERED 5
+     "push %%rbx\n\t"
+     "push %%r12\n\t"
+     "push %%r13\n\t"
+     "push %%r14\n\t"
+     "push %%r15\n\t"
+     "mov  %%rsp, %0\n\t"
+     "mov  %1, %%rsp\n\t"
+     "pop  %%r15\n\t"
+     "pop  %%r14\n\t"
+     "pop  %%r13\n\t"
+     "pop  %%r12\n\t"
+     "pop  %%rbx\n\t"
+#elif __i386
+# define NUM_CLOBBERED 4
+     "push %%ebx\n\t"
+     "push %%esi\n\t"
+     "push %%edi\n\t"
+     "push %%ebp\n\t"
+     "mov  %%esp, %0\n\t"
+     "mov  %1, %%esp\n\t"
+     "pop  %%ebp\n\t"
+     "pop  %%edi\n\t"
+     "pop  %%esi\n\t"
+     "pop  %%ebx\n\t"
+#else
+# error unsupported architecture
+#endif
+     : "=m" (prev->sp)
+     : "m" (next->sp)
+  );
+}
+#endif
+
 /* initialize a machine state */
 void coro_create (coro_context *ctx,
                   coro_func coro, void *arg,
@@ -129,7 +169,7 @@ void coro_create (coro_context *ctx,
 
   makecontext (&(ctx->uc), (void (*)()) coro, 1, arg);
 
-#elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX
+#elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX || CORO_ASM
 
 # if CORO_SJLJ
   stack_t ostk, nstk;
@@ -230,7 +270,7 @@ void coro_create (coro_context *ctx,
   ctx->env[0].__jmpbuf[JB_PC]  = (long)coro_init;
   ctx->env[0].__jmpbuf[JB_RSP] = (long)STACK_ADJUST_PTR (sptr, ssize);
 #else
-#error "linux libc or architecture not supported"
+# error "linux libc or architecture not supported"
 #endif
 
 # elif CORO_IRIX
@@ -239,12 +279,19 @@ void coro_create (coro_context *ctx,
   ctx->env[JB_PC] = (__uint64_t)coro_init;
   ctx->env[JB_SP] = (__uint64_t)STACK_ADJUST_PTR (sptr, ssize);
 
+# elif CORO_ASM
+
+  ctx->sp = (volatile void **)(ssize + (char *)sptr);
+  *--ctx->sp = (void *)coro_init;
+  *--ctx->sp = (void *)coro_init; // this is needed when the prologue saves ebp
+  ctx->sp -= NUM_CLOBBERED;
+
 # endif
 
   coro_transfer ((coro_context *)create_coro, (coro_context *)new_coro);
 
 #else
-error unsupported architecture
+# error unsupported architecture
 #endif
 }
 
diff --git a/coro.h b/coro.h
index 993dab6..00ed664 100644
--- a/coro.h
+++ b/coro.h
@@ -41,6 +41,8 @@
  * 2006-11-26 Use _setjmp instead of setjmp on GNU/Linux.
  * 2007-04-27 Set unwind frame info if gcc 3+ and ELF is detected.
  *            Use _setjmp instead of setjmp on _XOPEN_SOURCE >= 600.
+ * 2007-05-02 Add assembly versions for x86 and amd64 (to avoid reliance
+ *            on SIGUSR2 and sigaltstack in Crossfire).
  */
 
 #ifndef CORO_H
@@ -91,6 +93,11 @@
  *
  *    SGI's version of Microsoft's NT ;)
  *
+ * -DCORO_ASM
+ *
+ *    Handcoded assembly, known to work only on a few architectures/ABI:
+ *    ELF Linux x86 && amd64 when gcc is used and optimisation is turned on.
+ *
  * If you define neither of these symbols, coro.h will try to autodetect
  * the model.  This currently works for CORO_LOSER only. For the other
  * alternatives you should check (e.g. using autoconf) and define the
@@ -138,10 +145,11 @@ void coro_transfer(coro_context *prev, coro_context *next);
 
 #if !defined(CORO_LOSER) && !defined(CORO_UCONTEXT) \
     && !defined(CORO_SJLJ) && !defined(CORO_LINUX) \
-    && !defined(CORO_IRIX)
+    && !defined(CORO_IRIX) && !defined(CORO_ASM)
 # if defined(WINDOWS)
 #  define CORO_LOSER 1 /* you don't win with windoze */
-# elif defined(__linux) && defined(__x86)
+# elif defined(__linux) && (defined(__x86) || defined (__amd64))
+#  define CORO_ASM 1
 # elif defined(HAVE_UCONTEXT_H)
 #  define CORO_UCONTEXT 1
 # elif defined(HAVE_SETJMP_H) && defined(HAVE_SIGALTSTACK)
@@ -155,31 +163,40 @@ error unknown or unsupported architecture
 
 #if CORO_UCONTEXT
 
-#include <ucontext.h>
+# include <ucontext.h>
 
 struct coro_context {
   ucontext_t uc;
 };
 
-#define coro_transfer(p,n) swapcontext (&((p)->uc), &((n)->uc))
+# define coro_transfer(p,n) swapcontext (&((p)->uc), &((n)->uc))
 
 #elif CORO_SJLJ || CORO_LOSER || CORO_LINUX || CORO_IRIX
 
-#if defined(CORO_LINUX) && !defined(_GNU_SOURCE)
-# define _GNU_SOURCE /* for linux libc */
-#endif
+# if defined(CORO_LINUX) && !defined(_GNU_SOURCE)
+#  define _GNU_SOURCE /* for linux libc */
+# endif
 
-#include <setjmp.h>
+# include <setjmp.h>
 
 struct coro_context {
   jmp_buf env;
 };
 
-#if CORO_LINUX || (_XOPEN_SOURCE >= 600)
-# define coro_transfer(p,n) do { if (!_setjmp ((p)->env)) _longjmp ((n)->env, 1); } while (0)
-#else
-# define coro_transfer(p,n) do { if (!setjmp  ((p)->env)) longjmp  ((n)->env, 1); } while (0)
-#endif
+# if CORO_LINUX || (_XOPEN_SOURCE >= 600)
+#  define coro_transfer(p,n) do { if (!_setjmp ((p)->env)) _longjmp ((n)->env, 1); } while (0)
+# else
+#  define coro_transfer(p,n) do { if (!setjmp  ((p)->env)) longjmp  ((n)->env, 1); } while (0)
+# endif
+
+#elif CORO_ASM
+
+struct coro_context {
+  volatile void **sp;
+};
+
+void __attribute__ ((__noinline__, __fastcall__))
+     coro_transfer(coro_context *prev, coro_context *next);
 
 #endif
 
-- 
cgit v1.2.3