sys_darwin_amd64.s 11.6 KB
Newer Older
1 2 3 4 5 6
// 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
Russ Cox's avatar
Russ Cox committed
7 8
// 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.
9
//
10 11 12
// 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.
//
13

14
#include "zasm_GOOS_GOARCH.h"
15
#include "textflag.h"
16

Russ Cox's avatar
Russ Cox committed
17
// Exit the entire program (like C exit)
18
TEXT runtime·exit(SB),NOSPLIT,$0
19
	MOVL	code+0(FP), DI		// arg 1 exit status
20 21
	MOVL	$(0x2000000+1), AX	// syscall entry
	SYSCALL
Russ Cox's avatar
Russ Cox committed
22
	MOVL	$0xf1, 0xf1  // crash
23 24
	RET

Russ Cox's avatar
Russ Cox committed
25 26
// Exit this OS thread (like pthread_exit, which eventually
// calls __bsdthread_terminate).
27
TEXT runtime·exit1(SB),NOSPLIT,$0
28
	MOVL	code+0(FP), DI		// arg 1 exit status
Russ Cox's avatar
Russ Cox committed
29
	MOVL	$(0x2000000+361), AX	// syscall entry
30
	SYSCALL
Russ Cox's avatar
Russ Cox committed
31
	MOVL	$0xf1, 0xf1  // crash
32 33
	RET

34
TEXT runtime·open(SB),NOSPLIT,$0
35 36 37
	MOVQ	name+0(FP), DI		// arg 1 pathname
	MOVL	mode+8(FP), SI		// arg 2 flags
	MOVL	perm+12(FP), DX		// arg 3 mode
38 39
	MOVL	$(0x2000000+5), AX	// syscall entry
	SYSCALL
40
	MOVL	AX, ret+16(FP)
41 42
	RET

43
TEXT runtime·close(SB),NOSPLIT,$0
44
	MOVL	fd+0(FP), DI		// arg 1 fd
45 46
	MOVL	$(0x2000000+6), AX	// syscall entry
	SYSCALL
47
	MOVL	AX, ret+8(FP)
48 49
	RET

50
TEXT runtime·read(SB),NOSPLIT,$0
51 52 53
	MOVL	fd+0(FP), DI		// arg 1 fd
	MOVQ	p+8(FP), SI		// arg 2 buf
	MOVL	n+16(FP), DX		// arg 3 count
54 55
	MOVL	$(0x2000000+3), AX	// syscall entry
	SYSCALL
56
	MOVL	AX, ret+24(FP)
57 58
	RET

59
TEXT runtime·write(SB),NOSPLIT,$0
60 61 62
	MOVQ	fd+0(FP), DI		// arg 1 fd
	MOVQ	p+8(FP), SI		// arg 2 buf
	MOVL	n+16(FP), DX		// arg 3 count
63 64
	MOVL	$(0x2000000+4), AX	// syscall entry
	SYSCALL
65
	MOVL	AX, ret+24(FP)
66 67
	RET

68
TEXT runtime·raise(SB),NOSPLIT,$24
69 70 71 72 73 74
	MOVL	$(0x2000000+20), AX // getpid
	SYSCALL
	MOVQ	AX, DI	// arg 1 - pid
	MOVL	sig+0(FP), SI	// arg 2 - signal
	MOVL	$1, DX	// arg 3 - posix
	MOVL	$(0x2000000+37), AX // kill
75 76 77
	SYSCALL
	RET

78
TEXT runtime·setitimer(SB), NOSPLIT, $0
79 80 81
	MOVL	mode+0(FP), DI
	MOVQ	new+8(FP), SI
	MOVQ	old+16(FP), DX
82 83 84 85
	MOVL	$(0x2000000+83), AX	// syscall entry
	SYSCALL
	RET

86
TEXT runtime·madvise(SB), NOSPLIT, $0
87 88 89
	MOVQ	addr+0(FP), DI		// arg 1 addr
	MOVQ	n+8(FP), SI		// arg 2 len
	MOVL	flags+16(FP), DX		// arg 3 advice
90 91
	MOVL	$(0x2000000+75), AX	// syscall entry madvise
	SYSCALL
92
	// ignore failure - maybe pages are locked
93 94
	RET

95 96 97 98 99 100 101 102 103 104
// OS X comm page time offsets
// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
#define	nt_tsc_base	0x50
#define	nt_scale	0x58
#define	nt_shift	0x5c
#define	nt_ns_base	0x60
#define	nt_generation	0x68
#define	gtod_generation	0x6c
#define	gtod_ns_base	0x70
#define	gtod_sec_base	0x78
105

106
TEXT nanotime<>(SB), NOSPLIT, $32
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
	MOVQ	$0x7fffffe00000, BP	/* comm page base */
	// Loop trying to take a consistent snapshot
	// of the time parameters.
timeloop:
	MOVL	gtod_generation(BP), R8
	TESTL	R8, R8
	JZ	systime
	MOVL	nt_generation(BP), R9
	TESTL	R9, R9
	JZ	timeloop
	RDTSC
	MOVQ	nt_tsc_base(BP), R10
	MOVL	nt_scale(BP), R11
	MOVQ	nt_ns_base(BP), R12
	CMPL	nt_generation(BP), R9
	JNE	timeloop
	MOVQ	gtod_ns_base(BP), R13
	MOVQ	gtod_sec_base(BP), R14
	CMPL	gtod_generation(BP), R8
	JNE	timeloop

	// Gathered all the data we need. Compute time.
	//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
	// The multiply and shift extracts the top 64 bits of the 96-bit product.
	SHLQ	$32, DX
	ADDQ	DX, AX
	SUBQ	R10, AX
	MULQ	R11
	SHRQ	$32, AX:DX
	ADDQ	R12, AX
	SUBQ	R13, AX
	IMULQ	$1000000000, R14
	ADDQ	R14, AX
	RET

systime:
	// Fall back to system call (usually first call in this thread).
144 145
	MOVQ	SP, DI	// must be non-nil, unused
	MOVQ	$0, SI
146
	MOVL	$(0x2000000+116), AX
147
	SYSCALL
Russ Cox's avatar
Russ Cox committed
148 149 150 151 152
	// sec is in AX, usec in DX
	// return nsec in AX
	IMULQ	$1000000000, AX
	IMULQ	$1000, DX
	ADDQ	DX, AX
153 154
	RET

155 156 157 158 159
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
	CALL	nanotime<>(SB)
	MOVQ	AX, ret+0(FP)
	RET

160
// func now() (sec int64, nsec int32)
161 162
TEXT time·now(SB),NOSPLIT,$8
	CALL	nanotime<>(SB)
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

	// generated code for
	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
	// adapted to reduce duplication
	MOVQ	AX, CX
	MOVQ	$1360296554856532783, AX
	MULQ	CX
	ADDQ	CX, DX
	RCRQ	$1, DX
	SHRQ	$29, DX
	MOVQ	DX, sec+0(FP)
	IMULQ	$1000000000, DX
	SUBQ	DX, CX
	MOVL	CX, nsec+8(FP)
	RET

179
TEXT runtime·sigprocmask(SB),NOSPLIT,$0
180 181 182
	MOVL	sig+0(FP), DI
	MOVQ	new+8(FP), SI
	MOVQ	old+16(FP), DX
183
	MOVL	$(0x2000000+329), AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
Russ Cox's avatar
Russ Cox committed
184 185
	SYSCALL
	JCC	2(PC)
Russ Cox's avatar
Russ Cox committed
186
	MOVL	$0xf1, 0xf1  // crash
Russ Cox's avatar
Russ Cox committed
187 188
	RET

189
TEXT runtime·sigaction(SB),NOSPLIT,$0
190 191 192 193 194
	MOVL	mode+0(FP), DI		// arg 1 sig
	MOVQ	new+8(FP), SI		// arg 2 act
	MOVQ	old+16(FP), DX		// arg 3 oact
	MOVQ	old+16(FP), CX		// arg 3 oact
	MOVQ	old+16(FP), R10		// arg 3 oact
195 196 197
	MOVL	$(0x2000000+46), AX	// syscall entry
	SYSCALL
	JCC	2(PC)
Russ Cox's avatar
Russ Cox committed
198
	MOVL	$0xf1, 0xf1  // crash
199 200
	RET

201
TEXT runtime·sigtramp(SB),NOSPLIT,$64
202
	get_tls(BX)
203

204 205 206
	MOVQ	R8, 32(SP)	// save ucontext
	MOVQ	SI, 40(SP)	// save infostyle

207 208 209
	// check that g exists
	MOVQ	g(BX), R10
	CMPQ	R10, $0
210
	JNE	5(PC)
211
	MOVL	DX, 0(SP)
212 213 214
	MOVQ	$runtime·badsignal(SB), AX
	CALL	AX
	JMP 	sigtramp_ret
215

216
	// save g
217
	MOVQ	R10, 48(SP)
218

219
	// g = m->gsignal
220
	MOVQ	g_m(R10), BP
221 222 223
	MOVQ	m_gsignal(BP), BP
	MOVQ	BP, g(BX)

224 225 226
	MOVL	DX, 0(SP)
	MOVQ	CX, 8(SP)
	MOVQ	R8, 16(SP)
227 228
	MOVQ	R10, 24(SP)

Russ Cox's avatar
Russ Cox committed
229
	CALL	DI
230 231 232

	// restore g
	get_tls(BX)
233 234
	MOVQ	48(SP), R10
	MOVQ	R10, g(BX)
235

236
sigtramp_ret:
237
	// call sigreturn
Russ Cox's avatar
Russ Cox committed
238
	MOVL	$(0x2000000+184), AX	// sigreturn(ucontext, infostyle)
239 240
	MOVQ	32(SP), DI	// saved ucontext
	MOVQ	40(SP), SI	// saved infostyle
Russ Cox's avatar
Russ Cox committed
241 242
	SYSCALL
	INT $3	// not reached
243

244
TEXT runtime·mmap(SB),NOSPLIT,$0
245 246 247 248 249 250
	MOVQ	addr+0(FP), DI		// arg 1 addr
	MOVQ	n+8(FP), SI		// arg 2 len
	MOVL	prot+16(FP), DX		// arg 3 prot
	MOVL	flags+20(FP), R10		// arg 4 flags
	MOVL	fd+24(FP), R8		// arg 5 fid
	MOVL	off+28(FP), R9		// arg 6 offset
251 252
	MOVL	$(0x2000000+197), AX	// syscall entry
	SYSCALL
253
	MOVQ	AX, ret+32(FP)
254 255
	RET

256
TEXT runtime·munmap(SB),NOSPLIT,$0
257 258
	MOVQ	addr+0(FP), DI		// arg 1 addr
	MOVQ	n+8(FP), SI		// arg 2 len
259 260 261
	MOVL	$(0x2000000+73), AX	// syscall entry
	SYSCALL
	JCC	2(PC)
Russ Cox's avatar
Russ Cox committed
262
	MOVL	$0xf1, 0xf1  // crash
263 264
	RET

265
TEXT runtime·sigaltstack(SB),NOSPLIT,$0
Russ Cox's avatar
Russ Cox committed
266 267 268 269 270
	MOVQ	new+8(SP), DI
	MOVQ	old+16(SP), SI
	MOVQ	$(0x2000000+53), AX
	SYSCALL
	JCC	2(PC)
Russ Cox's avatar
Russ Cox committed
271
	MOVL	$0xf1, 0xf1  // crash
272
	RET
Russ Cox's avatar
Russ Cox committed
273

274
TEXT runtime·usleep(SB),NOSPLIT,$16
275 276 277 278 279 280 281 282 283 284 285 286 287
	MOVL	$0, DX
	MOVL	usec+0(FP), AX
	MOVL	$1000000, CX
	DIVL	CX
	MOVQ	AX, 0(SP)  // sec
	MOVL	DX, 8(SP)  // usec

	// select(0, 0, 0, 0, &tv)
	MOVL	$0, DI
	MOVL	$0, SI
	MOVL	$0, DX
	MOVL	$0, R10
	MOVQ	SP, R8
288
	MOVL	$(0x2000000+93), AX
289 290 291
	SYSCALL
	RET

292
// void bsdthread_create(void *stk, M *mp, G *gp, void (*fn)(void))
293
TEXT runtime·bsdthread_create(SB),NOSPLIT,$0
Russ Cox's avatar
Russ Cox committed
294 295 296 297
	// 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"
298
	MOVQ	mm+16(SP), SI	// "arg"
Russ Cox's avatar
Russ Cox committed
299
	MOVQ	stk+8(SP), DX	// stack
300
	MOVQ	gg+24(SP), R10	// "pthread"
301
	MOVQ	$0x01000000, R8	// flags = PTHREAD_START_CUSTOM
302
	MOVQ	$0, R9	// paranoia
Russ Cox's avatar
Russ Cox committed
303 304
	MOVQ	$(0x2000000+360), AX	// bsdthread_create
	SYSCALL
305
	JCC 4(PC)
306
	NEGQ	AX
307
	MOVL	AX, ret+32(FP)
308 309
	RET
	MOVL	$0, AX
310
	MOVL	AX, ret+32(FP)
Russ Cox's avatar
Russ Cox committed
311 312 313 314 315
	RET

// The thread that bsdthread_create creates starts executing here,
// because we registered this function using bsdthread_register
// at startup.
316
//	DI = "pthread"
Russ Cox's avatar
Russ Cox committed
317 318 319 320 321 322
//	SI = mach thread port
//	DX = "func" (= fn)
//	CX = "arg" (= m)
//	R8 = stack
//	R9 = flags (= 0)
//	SP = stack - C_64_REDZONE_LEN (= stack - 128)
323
TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
324
	MOVQ	R8, SP		// empirically, SP is very wrong but R8 is right
325 326 327 328 329 330 331

	PUSHQ	DX
	PUSHQ	CX
	PUSHQ	SI

	// set up thread local storage pointing at m->tls.
	LEAQ	m_tls(CX), DI
332
	CALL	runtime·settls(SB)
333 334 335 336

	POPQ	SI
	POPQ	CX
	POPQ	DX
337

338 339 340 341
	get_tls(BX)
	MOVQ	SI, m_procid(CX)	// thread port is m->procid
	MOVQ	m_g0(CX), AX
	MOVQ	AX, g(BX)
342
	MOVQ	CX, g_m(AX)
343
	CALL	runtime·stackcheck(SB)	// smashes AX, CX
Russ Cox's avatar
Russ Cox committed
344
	CALL	DX	// fn
345
	CALL	runtime·exit1(SB)
Russ Cox's avatar
Russ Cox committed
346 347 348 349 350
	RET

// void bsdthread_register(void)
// registers callbacks for threadstart (see bsdthread_create above
// and wqthread and pthsize (not used).  returns 0 on success.
351
TEXT runtime·bsdthread_register(SB),NOSPLIT,$0
352
	MOVQ	$runtime·bsdthread_start(SB), DI	// threadstart
Russ Cox's avatar
Russ Cox committed
353 354
	MOVQ	$0, SI	// wqthread, not used by us
	MOVQ	$0, DX	// pthsize, not used by us
355 356 357
	MOVQ	$0, R10	// dummy_value [sic]
	MOVQ	$0, R8	// targetconc_ptr
	MOVQ	$0, R9	// dispatchqueue_offset
Russ Cox's avatar
Russ Cox committed
358 359
	MOVQ	$(0x2000000+366), AX	// bsdthread_register
	SYSCALL
360
	JCC 4(PC)
361
	NEGQ	AX
362
	MOVL	AX, ret+0(FP)
363 364
	RET
	MOVL	$0, AX
365
	MOVL	AX, ret+0(FP)
Russ Cox's avatar
Russ Cox committed
366 367 368 369 370
	RET

// Mach system calls use 0x1000000 instead of the BSD's 0x2000000.

// uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
371
TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
372 373 374 375 376 377 378
	MOVQ	h+0(FP), DI
	MOVL	op+8(FP), SI
	MOVL	send_size+12(FP), DX
	MOVL	rcv_size+16(FP), R10
	MOVL	rcv_name+20(FP), R8
	MOVL	timeout+24(FP), R9
	MOVL	notify+28(FP), R11
Russ Cox's avatar
Russ Cox committed
379 380 381 382
	PUSHQ	R11	// seventh arg, on stack
	MOVL	$(0x1000000+31), AX	// mach_msg_trap
	SYSCALL
	POPQ	R11
383
	MOVL	AX, ret+32(FP)
Russ Cox's avatar
Russ Cox committed
384 385
	RET

386
TEXT runtime·mach_task_self(SB),NOSPLIT,$0
Russ Cox's avatar
Russ Cox committed
387 388
	MOVL	$(0x1000000+28), AX	// task_self_trap
	SYSCALL
389
	MOVL	AX, ret+0(FP)
Russ Cox's avatar
Russ Cox committed
390 391
	RET

392
TEXT runtime·mach_thread_self(SB),NOSPLIT,$0
Russ Cox's avatar
Russ Cox committed
393 394
	MOVL	$(0x1000000+27), AX	// thread_self_trap
	SYSCALL
395
	MOVL	AX, ret+0(FP)
Russ Cox's avatar
Russ Cox committed
396 397
	RET

398
TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
Russ Cox's avatar
Russ Cox committed
399 400
	MOVL	$(0x1000000+26), AX	// mach_reply_port
	SYSCALL
401
	MOVL	AX, ret+0(FP)
Russ Cox's avatar
Russ Cox committed
402 403 404 405 406 407
	RET

// Mach provides trap versions of the semaphore ops,
// instead of requiring the use of RPC.

// uint32 mach_semaphore_wait(uint32)
408
TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
409
	MOVL	sema+0(FP), DI
Russ Cox's avatar
Russ Cox committed
410 411
	MOVL	$(0x1000000+36), AX	// semaphore_wait_trap
	SYSCALL
412
	MOVL	AX, ret+8(FP)
Russ Cox's avatar
Russ Cox committed
413 414 415
	RET

// uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
416
TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
417 418 419
	MOVL	sema+0(FP), DI
	MOVL	sec+4(FP), SI
	MOVL	nsec+8(FP), DX
Russ Cox's avatar
Russ Cox committed
420 421
	MOVL	$(0x1000000+38), AX	// semaphore_timedwait_trap
	SYSCALL
422
	MOVL	AX, ret+16(FP)
Russ Cox's avatar
Russ Cox committed
423 424 425
	RET

// uint32 mach_semaphore_signal(uint32)
426
TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
427
	MOVL	sema+0(FP), DI
Russ Cox's avatar
Russ Cox committed
428 429
	MOVL	$(0x1000000+33), AX	// semaphore_signal_trap
	SYSCALL
430
	MOVL	AX, ret+8(FP)
Russ Cox's avatar
Russ Cox committed
431 432 433
	RET

// uint32 mach_semaphore_signal_all(uint32)
434
TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
435
	MOVL	sema+0(FP), DI
Russ Cox's avatar
Russ Cox committed
436 437
	MOVL	$(0x1000000+34), AX	// semaphore_signal_all_trap
	SYSCALL
438
	MOVL	AX, ret+8(FP)
Russ Cox's avatar
Russ Cox committed
439
	RET
440 441

// set tls base to DI
442
TEXT runtime·settls(SB),NOSPLIT,$32
443
	/*
444 445
	* Same as in sys_darwin_386.s:/ugliness, different constant.
	* See cgo/gcc_darwin_amd64.c for the derivation
446 447 448 449 450 451 452
	* of the constant.
	*/
	SUBQ $0x8a0, DI

	MOVL	$(0x3000000+3), AX	// thread_fast_set_cthread_self - machdep call #3
	SYSCALL
	RET
453

454
TEXT runtime·sysctl(SB),NOSPLIT,$0
455 456 457 458 459 460
	MOVQ	mib+0(FP), DI
	MOVL	miblen+8(FP), SI
	MOVQ	out+16(FP), DX
	MOVQ	size+24(FP), R10
	MOVQ	dst+32(FP), R8
	MOVQ	ndst+40(FP), R9
461 462
	MOVL	$(0x2000000+202), AX	// syscall entry
	SYSCALL
463
	JCC 4(PC)
464
	NEGQ	AX
465
	MOVL	AX, ret+48(FP)
466 467
	RET
	MOVL	$0, AX
468
	MOVL	AX, ret+48(FP)
469
	RET
470 471

// int32 runtime·kqueue(void);
472
TEXT runtime·kqueue(SB),NOSPLIT,$0
473 474 475 476 477 478
	MOVQ    $0, DI
	MOVQ    $0, SI
	MOVQ    $0, DX
	MOVL	$(0x2000000+362), AX
	SYSCALL
	JCC	2(PC)
479
	NEGQ	AX
480
	MOVL	AX, ret+0(FP)
481 482 483
	RET

// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
484
TEXT runtime·kevent(SB),NOSPLIT,$0
485 486 487 488 489 490
	MOVL    fd+0(FP), DI
	MOVQ    ev1+8(FP), SI
	MOVL    nev1+16(FP), DX
	MOVQ    ev2+24(FP), R10
	MOVL    nev2+32(FP), R8
	MOVQ    ts+40(FP), R9
491 492 493
	MOVL	$(0x2000000+363), AX
	SYSCALL
	JCC	2(PC)
494
	NEGQ	AX
495
	MOVL	AX, ret+48(FP)
496 497 498
	RET

// void runtime·closeonexec(int32 fd);
499
TEXT runtime·closeonexec(SB),NOSPLIT,$0
500
	MOVL    fd+0(FP), DI  // fd
501 502 503 504 505
	MOVQ    $2, SI  // F_SETFD
	MOVQ    $1, DX  // FD_CLOEXEC
	MOVL	$(0x2000000+92), AX  // fcntl
	SYSCALL
	RET