-
Notifications
You must be signed in to change notification settings - Fork 2
/
context.S
158 lines (126 loc) · 4.08 KB
/
context.S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* Copyright (c) 2018 Ariadne Conill <nenolod@dereferenced.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* This software is provided 'as is' and without any warranty, express or
* implied. In no event shall the authors be liable for any damages arising
* from the use of this software.
*/
#include "defs.h"
.align 4
.globl ___getcontext;
___getcontext:
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
/* save GPRs */
stp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)]
stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)]
stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
str x30, [x0, #R0_OFFSET + (30 * REGSZ)]
/* save current program counter in link register */
str x30, [x0, #PC_OFFSET]
/* save current stack pointer */
mov x2, sp
str x2, [x0, #SP_OFFSET]
/* save pstate */
str xzr, [x0, #PSTATE_OFFSET]
/* TODO: SIMD / FPRs */
mov x0, #0
ret
#ifndef WEAK
.globl _getcontext;
#else
.weak_definition _getcontext;
#endif
_getcontext = ___getcontext;
.globl ___setcontext;
___setcontext:
/* restore GPRs */
ldp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
ldp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
ldp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
ldp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
ldp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
ldp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
ldr x30, [x0, #R0_OFFSET + (30 * REGSZ)]
/* save current stack pointer */
ldr x2, [x0, #SP_OFFSET]
mov sp, x2
/* TODO: SIMD / FPRs */
/* save current program counter in link register */
ldr x16, [x0, #PC_OFFSET]
/* restore args */
ldp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
ldp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
ldp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
ldp x0, x1, [x0, #R0_OFFSET + (0 * REGSZ)]
/* jump to new PC */
br x16
#ifndef WEAK
.globl _setcontext;
#else
.weak_definition _setcontext;
#endif
_setcontext = ___setcontext;
.globl ___start_context;
___start_context:
/* get the proper context into position and test for NULL */
mov x0, x19
cbnz x0, _setcontext
/* something went wrong, exit */
b _exit
.globl ___swapcontext;
___swapcontext:
str xzr, [x0, #R0_OFFSET + (0 * REGSZ)]
/* save GPRs */
stp x2, x3, [x0, #R0_OFFSET + (2 * REGSZ)]
stp x4, x5, [x0, #R0_OFFSET + (4 * REGSZ)]
stp x6, x7, [x0, #R0_OFFSET + (6 * REGSZ)]
stp x8, x9, [x0, #R0_OFFSET + (8 * REGSZ)]
stp x10, x11, [x0, #R0_OFFSET + (10 * REGSZ)]
stp x12, x13, [x0, #R0_OFFSET + (12 * REGSZ)]
stp x14, x15, [x0, #R0_OFFSET + (14 * REGSZ)]
stp x16, x17, [x0, #R0_OFFSET + (16 * REGSZ)]
stp x18, x19, [x0, #R0_OFFSET + (18 * REGSZ)]
stp x20, x21, [x0, #R0_OFFSET + (20 * REGSZ)]
stp x22, x23, [x0, #R0_OFFSET + (22 * REGSZ)]
stp x24, x25, [x0, #R0_OFFSET + (24 * REGSZ)]
stp x26, x27, [x0, #R0_OFFSET + (26 * REGSZ)]
stp x28, x29, [x0, #R0_OFFSET + (28 * REGSZ)]
str x30, [x0, #R0_OFFSET + (30 * REGSZ)]
/* save current program counter in link register */
str x30, [x0, #PC_OFFSET]
/* save current stack pointer */
mov x2, sp
str x2, [x0, #SP_OFFSET]
/* save pstate */
str xzr, [x0, #PSTATE_OFFSET]
/* context to swap to is in x1 so... we move to x0 and call setcontext */
/* store our link register in x28 */
mov x28, x30
/* move x1 to x0 and call setcontext */
mov x0, x1
bl _setcontext
/* hmm, we came back here try to return */
mov x30, x28
ret
#ifndef WEAK
.globl _swapcontext;
#else
.weak_definition swapcontext;
#endif
_swapcontext = ___swapcontext;