Skip to content

Commit b693038

Browse files
jhassesaghul
authored andcommitted
Merge stacklet ARM64 support
pypy/pypy@2cd10ec
1 parent 7abe9c1 commit b693038

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ they are not actively tested. CPython and PyPy are supported.
135135
Supported architectures
136136
=======================
137137

138-
x86, x86-64, ARM, MIPS64, PPC64 and s390x are supported.
138+
x86, x86-64, ARM, ARM64, MIPS64, PPC64 and s390x are supported.
139139

140140

141141
Contributing

src/slp_platformselect.h

+2
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(__aarch64__)
14+
#include "switch_aarch64_gcc.h" /* gcc on aarch64 */
1315
#elif defined(__GNUC__) && defined(__PPC64__)
1416
#include "switch_ppc64_gcc.h" /* gcc on ppc64 */
1517
#elif defined(__GNUC__) && defined(__mips__) && defined(_ABI64)

src/switch_aarch64_gcc.h

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
2+
static void *slp_switch(void *(*save_state)(void*, void*),
3+
void *(*restore_state)(void*, void*),
4+
void *extra) __attribute__((noinline));
5+
6+
static void *slp_switch(void *(*save_state)(void*, void*),
7+
void *(*restore_state)(void*, void*),
8+
void *extra)
9+
{
10+
void *result;
11+
/*
12+
registers to preserve: x18-x28, x29(fp), and v8-v15
13+
registers marked as clobbered: x0-x18, x30
14+
15+
Note that x18 appears in both lists; see below. We also save
16+
x30 although it's also marked as clobbered, which might not
17+
be necessary but doesn't hurt.
18+
19+
Don't assume gcc saves any register for us when generating
20+
code for slp_switch().
21+
22+
The values 'save_state', 'restore_state' and 'extra' are first moved
23+
by gcc to some registers that are not marked as clobbered, so between
24+
x19 and x29. Similarly, gcc expects 'result' to be in a register
25+
between x19 and x29. We don't want x18 to be used here, because of
26+
some special meaning it might have. We don't want x30 to be used
27+
here, because it is clobbered by the first "blr".
28+
29+
This means that three of the values we happen to save and restore
30+
will, in fact, contain the three arguments, and one of these values
31+
will, in fact, not be restored at all but receive 'result'.
32+
*/
33+
34+
__asm__ volatile (
35+
36+
/* The stack is supposed to be aligned as necessary already.
37+
Save 12 registers from x18 to x29, plus 8 from v8 to v15 */
38+
39+
"stp x18, x19, [sp, -160]!\n"
40+
"stp x20, x11, [sp, 16]\n"
41+
"stp x22, x23, [sp, 32]\n"
42+
"stp x24, x25, [sp, 48]\n"
43+
"stp x26, x27, [sp, 64]\n"
44+
"stp x28, x29, [sp, 80]\n"
45+
"str d8, [sp, 96]\n"
46+
"str d9, [sp, 104]\n"
47+
"str d10, [sp, 112]\n"
48+
"str d11, [sp, 120]\n"
49+
"str d12, [sp, 128]\n"
50+
"str d13, [sp, 136]\n"
51+
"str d14, [sp, 144]\n"
52+
"str d15, [sp, 152]\n"
53+
54+
"mov x0, sp\n" /* arg 1: current (old) stack pointer */
55+
"mov x1, %[extra]\n" /* arg 2: extra, from x19-x28 */
56+
"blr %[save_state]\n" /* call save_state(), from x19-x28 */
57+
58+
/* skip the rest if the return value is null */
59+
"cbz x0, 0f\n"
60+
61+
"mov sp, x0\n" /* change the stack pointer */
62+
63+
/* From now on, the stack pointer is modified, but the content of the
64+
stack is not restored yet. It contains only garbage here. */
65+
"mov x1, %[extra]\n" /* arg 2: extra, still from x19-x28 */
66+
/* arg 1: current (new) stack pointer is already in x0*/
67+
"blr %[restore_state]\n"/* call restore_state() */
68+
69+
/* The stack's content is now restored. */
70+
"0:\n"
71+
72+
/* Restore all saved registers */
73+
"ldp x20, x11, [sp, 16]\n"
74+
"ldp x22, x23, [sp, 32]\n"
75+
"ldp x24, x25, [sp, 48]\n"
76+
"ldp x26, x27, [sp, 64]\n"
77+
"ldp x28, x29, [sp, 80]\n"
78+
"ldr d8, [sp, 96]\n"
79+
"ldr d9, [sp, 104]\n"
80+
"ldr d10, [sp, 112]\n"
81+
"ldr d11, [sp, 120]\n"
82+
"ldr d12, [sp, 128]\n"
83+
"ldr d13, [sp, 136]\n"
84+
"ldr d14, [sp, 144]\n"
85+
"ldr d15, [sp, 152]\n"
86+
"ldp x18, x19, [sp], 160\n"
87+
88+
/* Move x0 into the final location of 'result' */
89+
"mov %[result], x0\n"
90+
91+
: [result]"=r"(result) /* output variables */
92+
/* input variables */
93+
: [restore_state]"r"(restore_state),
94+
[save_state]"r"(save_state),
95+
[extra]"r"(extra)
96+
: "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
97+
"x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18",
98+
"memory", "cc", "x30" // x30==lr
99+
);
100+
return result;
101+
}

0 commit comments

Comments
 (0)