Skip to content

Commit 56eca00

Browse files
committed
Upgrade stacklet
1 parent 40ffd33 commit 56eca00

File tree

5 files changed

+83
-2
lines changed

5 files changed

+83
-2
lines changed

src/slp_platformselect.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#include "switch_x86_gcc.h" /* gcc on X86 */
1111
#elif defined(__GNUC__) && defined(__arm__)
1212
#include "switch_arm_gcc.h" /* gcc on arm */
13+
#elif defined(__GNUC__) && defined(__mips__) && defined(_ABI64)
14+
#include "switch_mips64_gcc.h" /* gcc on mips64 */
1315
#else
1416
#error "Unsupported platform!"
1517
#endif

src/switch_arm_gcc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#if defined(__ARM_ARCH_4__) || defined (__ARM_ARCH_4T__)
2+
# define call_reg(x) "mov lr, pc ; bx " #x "\n"
3+
#else
4+
/* ARM >= 5 */
5+
# define call_reg(x) "blx " #x "\n"
6+
#endif
17

28
static void __attribute__((optimize("O3"))) *slp_switch(void *(*save_state)(void*, void*),
39
void *(*restore_state)(void*, void*),
@@ -11,7 +17,7 @@ static void __attribute__((optimize("O3"))) *slp_switch(void *(*save_state)(void
1117
"mov r5, %[extra]\n"
1218
"mov r0, sp\n" /* arg 1: current (old) stack pointer */
1319
"mov r1, r5\n" /* arg 2: extra */
14-
"blx r3\n" /* call save_state() */
20+
call_reg(r3) /* call save_state() */
1521

1622
/* skip the rest if the return value is null */
1723
"cmp r0, #0\n"
@@ -23,7 +29,7 @@ static void __attribute__((optimize("O3"))) *slp_switch(void *(*save_state)(void
2329
stack is not restored yet. It contains only garbage here. */
2430
"mov r1, r5\n" /* arg 2: extra */
2531
/* arg 1: current (new) stack pointer is already in r0*/
26-
"blx r4\n" /* call restore_state() */
32+
call_reg(r4) /* call restore_state() */
2733

2834
/* The stack's content is now restored. */
2935
"zero:\n"

src/switch_mips64_gcc.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
static void *slp_switch(void *(*save_state)(void*, void*),
2+
void *(*restore_state)(void*, void*),
3+
void *extra)
4+
{
5+
void *result;
6+
__asm__ volatile (
7+
"daddiu $sp, $sp, -0x50\n"
8+
"sd $s0, 0x0($sp)\n" /* push the registers specified as caller-save */
9+
"sd $s1, 0x8($sp)\n"
10+
"sd $s2, 0x10($sp)\n"
11+
"sd $s3, 0x18($sp)\n"
12+
"sd $s4, 0x20($sp)\n"
13+
"sd $s5, 0x28($sp)\n"
14+
"sd $s6, 0x30($sp)\n"
15+
"sd $s7, 0x38($sp)\n"
16+
"sd $fp, 0x40($sp)\n"
17+
"sd $ra, 0x48($sp)\n"
18+
19+
"move $s0, %[rstate]\n" /* save 'restore_state' for later */
20+
"move $s1, %[extra]\n" /* save 'extra' for later */
21+
22+
"move $a1, %[extra]\n"/* arg 2: extra */
23+
"move $a0, $sp\n" /* arg 1: current (old) stack pointer */
24+
25+
"move $t9, %[sstate]\n"
26+
"jalr $t9\n" /* call save_state() */
27+
28+
"beqz $v0, 0f\n" /* skip the rest if the return value is null */
29+
30+
"move $sp, $v0\n" /* change the stack pointer */
31+
32+
/* From now on, the stack pointer is modified, but the content of the
33+
stack is not restored yet. It contains only garbage here. */
34+
35+
"move $a1, $s1\n" /* arg 2: extra */
36+
"move $a0, $v0\n" /* arg 1: current (new) stack pointer */
37+
"move $t9, $s0\n"
38+
"jalr $t9\n" /* call restore_state() */
39+
40+
/* The stack's content is now restored. */
41+
42+
"0:\n"
43+
"move %[result], $v0\n"
44+
"ld $s0, 0x0($sp)\n"
45+
"ld $s1, 0x8($sp)\n"
46+
"ld $s2, 0x10($sp)\n"
47+
"ld $s3, 0x18($sp)\n"
48+
"ld $s4, 0x20($sp)\n"
49+
"ld $s5, 0x28($sp)\n"
50+
"ld $s6, 0x30($sp)\n"
51+
"ld $s7, 0x38($sp)\n"
52+
"ld $fp, 0x40($sp)\n"
53+
"ld $ra, 0x48($sp)\n"
54+
"daddiu $sp, $sp, 0x50\n"
55+
56+
: [result]"=&r"(result)
57+
: [sstate]"r"(save_state),
58+
[rstate]"r"(restore_state),
59+
[extra]"r"(extra)
60+
: "memory", "v0", "a0", "a1", "t9"
61+
);
62+
return result;
63+
}

src/switch_x86_64_gcc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ static void *slp_switch(void *(*save_state)(void*, void*),
1010
"pushq %%r12\n"
1111
"pushq %%r13\n"
1212
"pushq %%r14\n"
13+
"movq %%rsp, %%rbp\n"
14+
"andq $-16, %%rsp\n" /* <= align the stack here... */
1315
"pushq %%r15\n"
16+
"pushq %%rbp\n" /* ...so that rsp is now a multiple of 16 */
1417

1518
"movq %%rax, %%r12\n" /* save 'restore_state' for later */
1619
"movq %%rsi, %%r13\n" /* save 'extra' for later */
@@ -34,7 +37,9 @@ static void *slp_switch(void *(*save_state)(void*, void*),
3437
/* The stack's content is now restored. */
3538

3639
"0:\n"
40+
"popq %%rbp\n"
3741
"popq %%r15\n"
42+
"movq %%rbp, %%rsp\n"
3843
"popq %%r14\n"
3944
"popq %%r13\n"
4045
"popq %%r12\n"

src/switch_x86_gcc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ static void *slp_switch(void *(*save_state)(void*, void*),
88
"pushl %%ebp\n"
99
"pushl %%ebx\n" /* push some registers that may contain */
1010
"pushl %%esi\n" /* some value that is meant to be saved */
11+
"movl %%esp, %%ebp\n"
12+
"andl $-16, %%esp\n" /* <= align the stack here, for the calls */
1113
"pushl %%edi\n"
14+
"pushl %%ebp\n"
1215

1316
"movl %%eax, %%esi\n" /* save 'restore_state' for later */
1417
"movl %%edx, %%edi\n" /* save 'extra' for later */
@@ -35,7 +38,9 @@ static void *slp_switch(void *(*save_state)(void*, void*),
3538

3639
"0:\n"
3740
"addl $8, %%esp\n"
41+
"popl %%ebp\n"
3842
"popl %%edi\n"
43+
"movl %%ebp, %%esp\n"
3944
"popl %%esi\n"
4045
"popl %%ebx\n"
4146
"popl %%ebp\n"

0 commit comments

Comments
 (0)