1 --- a/libco/amd64.c 2011-04-30 12:18:27.987519764 +0200
2 +++ b/libco/amd64.c 2011-04-30 12:19:04.959327913 +0200
8 +void co_swap(cothread_t new_active, cothread_t old_active);
10 static thread_local long long co_active_buffer[64];
11 static thread_local cothread_t co_active_handle = 0;
12 -static void (*co_swap)(cothread_t, cothread_t) = 0;
16 - static unsigned char co_swap_function[] = {
17 - 0x48, 0x89, 0x22, 0x48, 0x8B, 0x21, 0x58, 0x48, 0x89, 0x6A, 0x08, 0x48, 0x89, 0x72, 0x10, 0x48,
18 - 0x89, 0x7A, 0x18, 0x48, 0x89, 0x5A, 0x20, 0x4C, 0x89, 0x62, 0x28, 0x4C, 0x89, 0x6A, 0x30, 0x4C,
19 - 0x89, 0x72, 0x38, 0x4C, 0x89, 0x7A, 0x40, 0x48, 0x81, 0xC2, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83,
20 - 0xE2, 0xF0, 0x0F, 0x29, 0x32, 0x0F, 0x29, 0x7A, 0x10, 0x44, 0x0F, 0x29, 0x42, 0x20, 0x44, 0x0F,
21 - 0x29, 0x4A, 0x30, 0x44, 0x0F, 0x29, 0x52, 0x40, 0x44, 0x0F, 0x29, 0x5A, 0x50, 0x44, 0x0F, 0x29,
22 - 0x62, 0x60, 0x44, 0x0F, 0x29, 0x6A, 0x70, 0x44, 0x0F, 0x29, 0xB2, 0x80, 0x00, 0x00, 0x00, 0x44,
23 - 0x0F, 0x29, 0xBA, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x69, 0x08, 0x48, 0x8B, 0x71, 0x10, 0x48,
24 - 0x8B, 0x79, 0x18, 0x48, 0x8B, 0x59, 0x20, 0x4C, 0x8B, 0x61, 0x28, 0x4C, 0x8B, 0x69, 0x30, 0x4C,
25 - 0x8B, 0x71, 0x38, 0x4C, 0x8B, 0x79, 0x40, 0x48, 0x81, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83,
26 - 0xE1, 0xF0, 0x0F, 0x29, 0x31, 0x0F, 0x29, 0x79, 0x10, 0x44, 0x0F, 0x29, 0x41, 0x20, 0x44, 0x0F,
27 - 0x29, 0x49, 0x30, 0x44, 0x0F, 0x29, 0x51, 0x40, 0x44, 0x0F, 0x29, 0x59, 0x50, 0x44, 0x0F, 0x29,
28 - 0x61, 0x60, 0x44, 0x0F, 0x29, 0x69, 0x70, 0x44, 0x0F, 0x29, 0xB1, 0x80, 0x00, 0x00, 0x00, 0x44,
29 - 0x0F, 0x29, 0xB9, 0x90, 0x00, 0x00, 0x00, 0xFF, 0xE0,
32 - #include <windows.h>
35 - DWORD old_privileges;
36 - VirtualProtect(co_swap_function, sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
43 + "movq %rsp, (%rdx) # Save stack pointer and pop old back\n"
44 + "movq (%rcx), %rsp\n"
46 + "popq %rax # Pop saved PC to %rax\n"
48 + "movq %rbp, 0x8(%rdx) # Save non-volatile registers\n"
49 + "movq %rsi, 0x10(%rdx)\n"
50 + "movq %rdi, 0x18(%rdx)\n"
51 + "movq %rbx, 0x20(%rdx)\n"
52 + "movq %r12, 0x28(%rdx)\n"
53 + "movq %r13, 0x30(%rdx)\n"
54 + "movq %r14, 0x38(%rdx)\n"
55 + "movq %r15, 0x40(%rdx)\n"
57 + "addq $0x80, %rdx\n"
58 + "andq $0xfffffffffffffff0, %rdx # Align buffer to 16 bytes (SSE).\n"
59 + "movaps %xmm6, (%rdx) # Also save non-volatile vector registers.\n"
60 + "movaps %xmm7, 0x10(%rdx)\n"
61 + "movaps %xmm8, 0x20(%rdx)\n"
62 + "movaps %xmm9, 0x30(%rdx)\n"
63 + "movaps %xmm10, 0x40(%rdx)\n"
64 + "movaps %xmm11, 0x50(%rdx)\n"
65 + "movaps %xmm12, 0x60(%rdx)\n"
66 + "movaps %xmm13, 0x70(%rdx)\n"
67 + "movaps %xmm14, 0x80(%rdx)\n"
68 + "movaps %xmm15, 0x90(%rdx)\n"
70 + "movq 0x8(%rcx), %rbp # Pop back our saved registers and vector registers.\n"
71 + "movq 0x10(%rcx), %rsi\n"
72 + "movq 0x18(%rcx), %rdi\n"
73 + "movq 0x20(%rcx), %rbx\n"
74 + "movq 0x28(%rcx), %r12\n"
75 + "movq 0x30(%rcx), %r13\n"
76 + "movq 0x38(%rcx), %r14\n"
77 + "movq 0x40(%rcx), %r15\n"
79 + "addq $0x80, %rcx\n"
80 + "andq $0xfffffffffffffff0, %rcx\n"
81 + "movaps %xmm6, (%rcx)\n"
82 + "movaps %xmm7, 0x10(%rcx)\n"
83 + "movaps %xmm8, 0x20(%rcx)\n"
84 + "movaps %xmm9, 0x30(%rcx)\n"
85 + "movaps %xmm10, 0x40(%rcx)\n"
86 + "movaps %xmm11, 0x50(%rcx)\n"
87 + "movaps %xmm12, 0x60(%rcx)\n"
88 + "movaps %xmm13, 0x70(%rcx)\n"
89 + "movaps %xmm14, 0x80(%rcx)\n"
90 + "movaps %xmm15, 0x90(%rcx)\n"
91 + "jmpq *%rax # Jump back to old saved PC.\n"
95 - static unsigned char co_swap_function[] = {
96 - 0x48, 0x89, 0x26, 0x48, 0x8B, 0x27, 0x58, 0x48, 0x89, 0x6E, 0x08, 0x48, 0x89, 0x5E, 0x10, 0x4C,
97 - 0x89, 0x66, 0x18, 0x4C, 0x89, 0x6E, 0x20, 0x4C, 0x89, 0x76, 0x28, 0x4C, 0x89, 0x7E, 0x30, 0x48,
98 - 0x8B, 0x6F, 0x08, 0x48, 0x8B, 0x5F, 0x10, 0x4C, 0x8B, 0x67, 0x18, 0x4C, 0x8B, 0x6F, 0x20, 0x4C,
99 - 0x8B, 0x77, 0x28, 0x4C, 0x8B, 0x7F, 0x30, 0xFF, 0xE0,
102 - #include <unistd.h>
103 - #include <sys/mman.h>
106 - unsigned long long addr = (unsigned long long)co_swap_function;
107 - unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE));
108 - unsigned long long size = (addr - base) + sizeof co_swap_function;
109 - mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
114 + ".globl _co_swap\n"
117 + "movq %rsp, (%rsi) # Save stack pointer, and pop the old one back.\n"
118 + "movq (%rdi), %rsp\n"
121 + "movq %rbp, 0x8(%rsi) # Save our non-volatile registers to buffer.\n"
122 + "movq %rbx, 0x10(%rsi)\n"
123 + "movq %r12, 0x18(%rsi)\n"
124 + "movq %r13, 0x20(%rsi)\n"
125 + "movq %r14, 0x28(%rsi)\n"
126 + "movq %r15, 0x30(%rsi)\n"
128 + "movq 0x8(%rdi), %rbp # Pop back our saved registers.\n"
129 + "movq 0x10(%rdi), %rbx\n"
130 + "movq 0x18(%rdi), %r12\n"
131 + "movq 0x20(%rdi), %r13\n"
132 + "movq 0x28(%rdi), %r14\n"
133 + "movq 0x30(%rdi), %r15\n"
134 + "jmpq *%rax # Jump back to saved PC.\n"
138 static void crash() {
141 cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
145 - co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
147 if(!co_active_handle) co_active_handle = &co_active_buffer;
148 size += 512; /* allocate additional space for storage */
149 size &= ~15; /* align stack to 16-byte boundary */
151 - if(handle = (cothread_t)malloc(size)) {
152 + if((handle = (cothread_t)malloc(size))) {
153 long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
154 *--p = (long long)crash; /* crash if entrypoint returns */
155 *--p = (long long)entrypoint; /* start of function */