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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
|
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// System calls and other sys.stuff for AMD64, Darwin
// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
//
// The low 24 bits are the system call number.
// The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
//
#include "amd64/asm.h"
// Exit the entire program (like C exit)
TEXT runtime·exit(SB),7,$0
MOVL 8(SP), DI // arg 1 exit status
MOVL $(0x2000000+1), AX // syscall entry
SYSCALL
CALL runtime·notok(SB)
RET
// Exit this OS thread (like pthread_exit, which eventually
// calls __bsdthread_terminate).
TEXT runtime·exit1(SB),7,$0
MOVL 8(SP), DI // arg 1 exit status
MOVL $(0x2000000+361), AX // syscall entry
SYSCALL
CALL runtime·notok(SB)
RET
TEXT runtime·write(SB),7,$0
MOVL 8(SP), DI // arg 1 fd
MOVQ 16(SP), SI // arg 2 buf
MOVL 24(SP), DX // arg 3 count
MOVL $(0x2000000+4), AX // syscall entry
SYSCALL
RET
TEXT runtime·setitimer(SB), 7, $0
MOVL 8(SP), DI
MOVQ 16(SP), SI
MOVQ 24(SP), DX
MOVL $(0x2000000+83), AX // syscall entry
SYSCALL
RET
// void gettime(int64 *sec, int32 *usec)
TEXT runtime·gettime(SB), 7, $32
MOVQ SP, DI // must be non-nil, unused
MOVQ $0, SI
MOVL $(0x2000000+116), AX
SYSCALL
MOVQ sec+0(FP), DI
MOVQ AX, (DI)
MOVQ usec+8(FP), DI
MOVL DX, (DI)
RET
TEXT runtime·sigaction(SB),7,$0
MOVL 8(SP), DI // arg 1 sig
MOVQ 16(SP), SI // arg 2 act
MOVQ 24(SP), DX // arg 3 oact
MOVQ 24(SP), CX // arg 3 oact
MOVQ 24(SP), R10 // arg 3 oact
MOVL $(0x2000000+46), AX // syscall entry
SYSCALL
JCC 2(PC)
CALL runtime·notok(SB)
RET
TEXT runtime·sigtramp(SB),7,$64
get_tls(BX)
// save g
MOVQ g(BX), R10
MOVQ R10, 48(SP)
// g = m->gsignal
MOVQ m(BX), BP
MOVQ m_gsignal(BP), BP
MOVQ BP, g(BX)
MOVL DX, 0(SP)
MOVQ CX, 8(SP)
MOVQ R8, 16(SP)
MOVQ R10, 24(SP)
MOVQ R8, 32(SP) // save ucontext
MOVQ SI, 40(SP) // save infostyle
CALL DI
// restore g
get_tls(BX)
MOVQ 48(SP), R10
MOVQ R10, g(BX)
// call sigreturn
MOVL $(0x2000000+184), AX // sigreturn(ucontext, infostyle)
MOVQ 32(SP), DI // saved ucontext
MOVQ 40(SP), SI // saved infostyle
SYSCALL
INT $3 // not reached
TEXT runtime·mmap(SB),7,$0
MOVQ 8(SP), DI // arg 1 addr
MOVQ 16(SP), SI // arg 2 len
MOVL 24(SP), DX // arg 3 prot
MOVL 28(SP), R10 // arg 4 flags
MOVL 32(SP), R8 // arg 5 fid
MOVL 36(SP), R9 // arg 6 offset
MOVL $(0x2000000+197), AX // syscall entry
SYSCALL
RET
TEXT runtime·munmap(SB),7,$0
MOVQ 8(SP), DI // arg 1 addr
MOVQ 16(SP), SI // arg 2 len
MOVL $(0x2000000+73), AX // syscall entry
SYSCALL
JCC 2(PC)
CALL runtime·notok(SB)
RET
TEXT runtime·notok(SB),7,$0
MOVL $0xf1, BP
MOVQ BP, (BP)
RET
TEXT runtime·sigaltstack(SB),7,$0
MOVQ new+8(SP), DI
MOVQ old+16(SP), SI
MOVQ $(0x2000000+53), AX
SYSCALL
JCC 2(PC)
CALL runtime·notok(SB)
RET
// void bsdthread_create(void *stk, M *m, G *g, void (*fn)(void))
TEXT runtime·bsdthread_create(SB),7,$0
// Set up arguments to bsdthread_create system call.
// The ones in quotes pass through to the thread callback
// uninterpreted, so we can put whatever we want there.
MOVQ fn+32(SP), DI // "func"
MOVQ mm+16(SP), SI // "arg"
MOVQ stk+8(SP), DX // stack
MOVQ gg+24(SP), R10 // "pthread"
MOVQ $0x01000000, R8 // flags = PTHREAD_START_CUSTOM
MOVQ $0, R9 // paranoia
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
JCC 3(PC)
NEGL AX
RET
MOVL $0, AX
RET
// The thread that bsdthread_create creates starts executing here,
// because we registered this function using bsdthread_register
// at startup.
// DI = "pthread"
// SI = mach thread port
// DX = "func" (= fn)
// CX = "arg" (= m)
// R8 = stack
// R9 = flags (= 0)
// SP = stack - C_64_REDZONE_LEN (= stack - 128)
TEXT runtime·bsdthread_start(SB),7,$0
MOVQ R8, SP // empirically, SP is very wrong but R8 is right
PUSHQ DX
PUSHQ CX
PUSHQ SI
// set up thread local storage pointing at m->tls.
LEAQ m_tls(CX), DI
CALL runtime·settls(SB)
POPQ SI
POPQ CX
POPQ DX
get_tls(BX)
MOVQ CX, m(BX)
MOVQ SI, m_procid(CX) // thread port is m->procid
MOVQ m_g0(CX), AX
MOVQ AX, g(BX)
CALL runtime·stackcheck(SB) // smashes AX, CX
CALL DX // fn
CALL runtime·exit1(SB)
RET
// void bsdthread_register(void)
// registers callbacks for threadstart (see bsdthread_create above
// and wqthread and pthsize (not used). returns 0 on success.
TEXT runtime·bsdthread_register(SB),7,$0
MOVQ $runtime·bsdthread_start(SB), DI // threadstart
MOVQ $0, SI // wqthread, not used by us
MOVQ $0, DX // pthsize, not used by us
MOVQ $0, R10 // dummy_value [sic]
MOVQ $0, R8 // targetconc_ptr
MOVQ $0, R9 // dispatchqueue_offset
MOVQ $(0x2000000+366), AX // bsdthread_register
SYSCALL
JCC 2(PC)
CALL runtime·notok(SB)
RET
// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
TEXT runtime·mach_msg_trap(SB),7,$0
MOVQ 8(SP), DI
MOVL 16(SP), SI
MOVL 20(SP), DX
MOVL 24(SP), R10
MOVL 28(SP), R8
MOVL 32(SP), R9
MOVL 36(SP), R11
PUSHQ R11 // seventh arg, on stack
MOVL $(0x1000000+31), AX // mach_msg_trap
SYSCALL
POPQ R11
RET
TEXT runtime·mach_task_self(SB),7,$0
MOVL $(0x1000000+28), AX // task_self_trap
SYSCALL
RET
TEXT runtime·mach_thread_self(SB),7,$0
MOVL $(0x1000000+27), AX // thread_self_trap
SYSCALL
RET
TEXT runtime·mach_reply_port(SB),7,$0
MOVL $(0x1000000+26), AX // mach_reply_port
SYSCALL
RET
// Mach provides trap versions of the semaphore ops,
// instead of requiring the use of RPC.
// uint32 mach_semaphore_wait(uint32)
TEXT runtime·mach_semaphore_wait(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+36), AX // semaphore_wait_trap
SYSCALL
RET
// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
TEXT runtime·mach_semaphore_timedwait(SB),7,$0
MOVL 8(SP), DI
MOVL 12(SP), SI
MOVL 16(SP), DX
MOVL $(0x1000000+38), AX // semaphore_timedwait_trap
SYSCALL
RET
// uint32 mach_semaphore_signal(uint32)
TEXT runtime·mach_semaphore_signal(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+33), AX // semaphore_signal_trap
SYSCALL
RET
// uint32 mach_semaphore_signal_all(uint32)
TEXT runtime·mach_semaphore_signal_all(SB),7,$0
MOVL 8(SP), DI
MOVL $(0x1000000+34), AX // semaphore_signal_all_trap
SYSCALL
RET
// set tls base to DI
TEXT runtime·settls(SB),7,$32
/*
* Same as in ../386/sys.s:/ugliness, different constant.
* See ../../../../libcgo/darwin_amd64.c for the derivation
* of the constant.
*/
SUBQ $0x8a0, DI
MOVL $(0x3000000+3), AX // thread_fast_set_cthread_self - machdep call #3
SYSCALL
RET
|