...
Run Format

Text file src/runtime/sys_darwin_386.s

Documentation: runtime

     1	// Copyright 2009 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// System calls and other sys.stuff for 386, Darwin
     6	// See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
     7	// or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
     8	
     9	#include "go_asm.h"
    10	#include "go_tls.h"
    11	#include "textflag.h"
    12	
    13	// Exit the entire program (like C exit)
    14	TEXT runtime·exit(SB),NOSPLIT,$0
    15		MOVL	$1, AX
    16		INT	$0x80
    17		MOVL	$0xf1, 0xf1  // crash
    18		RET
    19	
    20	// Exit this OS thread (like pthread_exit, which eventually
    21	// calls __bsdthread_terminate).
    22	TEXT runtime·exit1(SB),NOSPLIT,$0
    23		MOVL	$361, AX
    24		INT	$0x80
    25		JAE 2(PC)
    26		MOVL	$0xf1, 0xf1  // crash
    27		RET
    28	
    29	TEXT runtime·open(SB),NOSPLIT,$0
    30		MOVL	$5, AX
    31		INT	$0x80
    32		JAE	2(PC)
    33		MOVL	$-1, AX
    34		MOVL	AX, ret+12(FP)
    35		RET
    36	
    37	TEXT runtime·closefd(SB),NOSPLIT,$0
    38		MOVL	$6, AX
    39		INT	$0x80
    40		JAE	2(PC)
    41		MOVL	$-1, AX
    42		MOVL	AX, ret+4(FP)
    43		RET
    44	
    45	TEXT runtime·read(SB),NOSPLIT,$0
    46		MOVL	$3, AX
    47		INT	$0x80
    48		JAE	2(PC)
    49		MOVL	$-1, AX
    50		MOVL	AX, ret+12(FP)
    51		RET
    52	
    53	TEXT runtime·write(SB),NOSPLIT,$0
    54		MOVL	$4, AX
    55		INT	$0x80
    56		JAE	2(PC)
    57		MOVL	$-1, AX
    58		MOVL	AX, ret+12(FP)
    59		RET
    60	
    61	TEXT runtime·raise(SB),NOSPLIT,$0
    62		// Ideally we'd send the signal to the current thread,
    63		// not the whole process, but that's too hard on OS X.
    64		JMP	runtime·raiseproc(SB)
    65	
    66	TEXT runtime·raiseproc(SB),NOSPLIT,$16
    67		MOVL	$20, AX // getpid
    68		INT	$0x80
    69		MOVL	AX, 4(SP)	// pid
    70		MOVL	sig+0(FP), AX
    71		MOVL	AX, 8(SP)	// signal
    72		MOVL	$1, 12(SP)	// posix
    73		MOVL	$37, AX // kill
    74		INT	$0x80
    75		RET
    76	
    77	TEXT runtime·mmap(SB),NOSPLIT,$0
    78		MOVL	$197, AX
    79		INT	$0x80
    80		MOVL	AX, ret+24(FP)
    81		RET
    82	
    83	TEXT runtime·madvise(SB),NOSPLIT,$0
    84		MOVL	$75, AX
    85		INT	$0x80
    86		// ignore failure - maybe pages are locked
    87		RET
    88	
    89	TEXT runtime·munmap(SB),NOSPLIT,$0
    90		MOVL	$73, AX
    91		INT	$0x80
    92		JAE	2(PC)
    93		MOVL	$0xf1, 0xf1  // crash
    94		RET
    95	
    96	TEXT runtime·setitimer(SB),NOSPLIT,$0
    97		MOVL	$83, AX
    98		INT	$0x80
    99		RET
   100	
   101	// OS X comm page time offsets
   102	// http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
   103	#define	cpu_capabilities	0x20
   104	#define	nt_tsc_base	0x50
   105	#define	nt_scale	0x58
   106	#define	nt_shift	0x5c
   107	#define	nt_ns_base	0x60
   108	#define	nt_generation	0x68
   109	#define	gtod_generation	0x6c
   110	#define	gtod_ns_base	0x70
   111	#define	gtod_sec_base	0x78
   112	
   113	// called from assembly
   114	// 64-bit unix nanoseconds returned in DX:AX.
   115	// I'd much rather write this in C but we need
   116	// assembly for the 96-bit multiply and RDTSC.
   117	//
   118	// Note that we could arrange to return monotonic time here
   119	// as well, but we don't bother, for two reasons:
   120	// 1. macOS only supports 64-bit systems, so no one should
   121	// be using the 32-bit code in production.
   122	// This code is only maintained to make it easier for developers
   123	// using Macs to test the 32-bit compiler.
   124	// 2. On some (probably now unsupported) CPUs,
   125	// the code falls back to the system call always,
   126	// so it can't even use the comm page at all. 
   127	TEXT runtime·now(SB),NOSPLIT,$40
   128		MOVL	$0xffff0000, BP /* comm page base */
   129		
   130		// Test for slow CPU. If so, the math is completely
   131		// different, and unimplemented here, so use the
   132		// system call.
   133		MOVL	cpu_capabilities(BP), AX
   134		TESTL	$0x4000, AX
   135		JNZ	systime
   136	
   137		// Loop trying to take a consistent snapshot
   138		// of the time parameters.
   139	timeloop:
   140		MOVL	gtod_generation(BP), BX
   141		TESTL	BX, BX
   142		JZ	systime
   143		MOVL	nt_generation(BP), CX
   144		TESTL	CX, CX
   145		JZ	timeloop
   146		RDTSC
   147		MOVL	nt_tsc_base(BP), SI
   148		MOVL	(nt_tsc_base+4)(BP), DI
   149		MOVL	SI, 0(SP)
   150		MOVL	DI, 4(SP)
   151		MOVL	nt_scale(BP), SI
   152		MOVL	SI, 8(SP)
   153		MOVL	nt_ns_base(BP), SI
   154		MOVL	(nt_ns_base+4)(BP), DI
   155		MOVL	SI, 12(SP)
   156		MOVL	DI, 16(SP)
   157		CMPL	nt_generation(BP), CX
   158		JNE	timeloop
   159		MOVL	gtod_ns_base(BP), SI
   160		MOVL	(gtod_ns_base+4)(BP), DI
   161		MOVL	SI, 20(SP)
   162		MOVL	DI, 24(SP)
   163		MOVL	gtod_sec_base(BP), SI
   164		MOVL	(gtod_sec_base+4)(BP), DI
   165		MOVL	SI, 28(SP)
   166		MOVL	DI, 32(SP)
   167		CMPL	gtod_generation(BP), BX
   168		JNE	timeloop
   169	
   170		// Gathered all the data we need. Compute time.
   171		//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
   172		// The multiply and shift extracts the top 64 bits of the 96-bit product.
   173		SUBL	0(SP), AX // DX:AX = (tsc - nt_tsc_base)
   174		SBBL	4(SP), DX
   175	
   176		// We have x = tsc - nt_tsc_base - DX:AX to be
   177		// multiplied by y = nt_scale = 8(SP), keeping the top 64 bits of the 96-bit product.
   178		// x*y = (x&0xffffffff)*y + (x&0xffffffff00000000)*y
   179		// (x*y)>>32 = ((x&0xffffffff)*y)>>32 + (x>>32)*y
   180		MOVL	DX, CX // SI = (x&0xffffffff)*y >> 32
   181		MOVL	$0, DX
   182		MULL	8(SP)
   183		MOVL	DX, SI
   184	
   185		MOVL	CX, AX // DX:AX = (x>>32)*y
   186		MOVL	$0, DX
   187		MULL	8(SP)
   188	
   189		ADDL	SI, AX	// DX:AX += (x&0xffffffff)*y >> 32
   190		ADCL	$0, DX
   191		
   192		// DX:AX is now ((tsc - nt_tsc_base) * nt_scale) >> 32.
   193		ADDL	12(SP), AX	// DX:AX += nt_ns_base
   194		ADCL	16(SP), DX
   195		SUBL	20(SP), AX	// DX:AX -= gtod_ns_base
   196		SBBL	24(SP), DX
   197		MOVL	AX, SI	// DI:SI = DX:AX
   198		MOVL	DX, DI
   199		MOVL	28(SP), AX	// DX:AX = gtod_sec_base*1e9
   200		MOVL	32(SP), DX
   201		MOVL	$1000000000, CX
   202		MULL	CX
   203		ADDL	SI, AX	// DX:AX += DI:SI
   204		ADCL	DI, DX
   205		RET
   206	
   207	systime:
   208		// Fall back to system call (usually first call in this thread)
   209		LEAL	16(SP), AX	// must be non-nil, unused
   210		MOVL	AX, 4(SP)
   211		MOVL	$0, 8(SP)	// time zone pointer
   212		MOVL	$0, 12(SP)	// required as of Sierra; Issue 16570
   213		MOVL	$116, AX // SYS_GETTIMEOFDAY
   214		INT	$0x80
   215		CMPL	AX, $0
   216		JNE	inreg
   217		MOVL	16(SP), AX
   218		MOVL	20(SP), DX
   219	inreg:
   220		// sec is in AX, usec in DX
   221		// convert to DX:AX nsec
   222		MOVL	DX, BX
   223		MOVL	$1000000000, CX
   224		MULL	CX
   225		IMULL	$1000, BX
   226		ADDL	BX, AX
   227		ADCL	$0, DX
   228		RET
   229	
   230	// func now() (sec int64, nsec int32, mono uint64)
   231	TEXT time·now(SB),NOSPLIT,$0-20
   232		CALL	runtime·now(SB)
   233		MOVL	AX, BX
   234		MOVL	DX, BP
   235		SUBL	runtime·startNano(SB), BX
   236		SBBL	runtime·startNano+4(SB), BP
   237		MOVL	BX, mono+12(FP)
   238		MOVL	BP, mono+16(FP)
   239		MOVL	$1000000000, CX
   240		DIVL	CX
   241		MOVL	AX, sec+0(FP)
   242		MOVL	$0, sec+4(FP)
   243		MOVL	DX, nsec+8(FP)
   244		RET
   245	
   246	// func nanotime() int64
   247	TEXT runtime·nanotime(SB),NOSPLIT,$0
   248		CALL	runtime·now(SB)
   249		SUBL	runtime·startNano(SB), AX
   250		SBBL	runtime·startNano+4(SB), DX
   251		MOVL	AX, ret_lo+0(FP)
   252		MOVL	DX, ret_hi+4(FP)
   253		RET
   254	
   255	TEXT runtime·sigprocmask(SB),NOSPLIT,$0
   256		MOVL	$329, AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
   257		INT	$0x80
   258		JAE	2(PC)
   259		MOVL	$0xf1, 0xf1  // crash
   260		RET
   261	
   262	TEXT runtime·sigaction(SB),NOSPLIT,$0
   263		MOVL	$46, AX
   264		INT	$0x80
   265		JAE	2(PC)
   266		MOVL	$0xf1, 0xf1  // crash
   267		RET
   268	
   269	TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   270		MOVL	fn+0(FP), AX
   271		MOVL	sig+4(FP), BX
   272		MOVL	info+8(FP), CX
   273		MOVL	ctx+12(FP), DX
   274		MOVL	SP, SI
   275		SUBL	$32, SP
   276		ANDL	$~15, SP	// align stack: handler might be a C function
   277		MOVL	BX, 0(SP)
   278		MOVL	CX, 4(SP)
   279		MOVL	DX, 8(SP)
   280		MOVL	SI, 12(SP)	// save SI: handler might be a Go function
   281		CALL	AX
   282		MOVL	12(SP), AX
   283		MOVL	AX, SP
   284		RET
   285	
   286	// Sigtramp's job is to call the actual signal handler.
   287	// It is called with the following arguments on the stack:
   288	//	0(SP)	"return address" - ignored
   289	//	4(SP)	actual handler
   290	//	8(SP)	siginfo style
   291	//	12(SP)	signal number
   292	//	16(SP)	siginfo
   293	//	20(SP)	context
   294	TEXT runtime·sigtramp(SB),NOSPLIT,$20
   295		MOVL	sig+8(FP), BX
   296		MOVL	BX, 0(SP)
   297		MOVL	info+12(FP), BX
   298		MOVL	BX, 4(SP)
   299		MOVL	ctx+16(FP), BX
   300		MOVL	BX, 8(SP)
   301		CALL	runtime·sigtrampgo(SB)
   302	
   303		// call sigreturn
   304		MOVL	ctx+16(FP), CX
   305		MOVL	infostyle+4(FP), BX
   306		MOVL	$0, 0(SP)	// "caller PC" - ignored
   307		MOVL	CX, 4(SP)
   308		MOVL	BX, 8(SP)
   309		MOVL	$184, AX	// sigreturn(ucontext, infostyle)
   310		INT	$0x80
   311		MOVL	$0xf1, 0xf1  // crash
   312		RET
   313	
   314	TEXT runtime·sigaltstack(SB),NOSPLIT,$0
   315		MOVL	$53, AX
   316		INT	$0x80
   317		JAE	2(PC)
   318		MOVL	$0xf1, 0xf1  // crash
   319		RET
   320	
   321	TEXT runtime·usleep(SB),NOSPLIT,$32
   322		MOVL	$0, DX
   323		MOVL	usec+0(FP), AX
   324		MOVL	$1000000, CX
   325		DIVL	CX
   326		MOVL	AX, 24(SP)  // sec
   327		MOVL	DX, 28(SP)  // usec
   328	
   329		// select(0, 0, 0, 0, &tv)
   330		MOVL	$0, 0(SP)  // "return PC" - ignored
   331		MOVL	$0, 4(SP)
   332		MOVL	$0, 8(SP)
   333		MOVL	$0, 12(SP)
   334		MOVL	$0, 16(SP)
   335		LEAL	24(SP), AX
   336		MOVL	AX, 20(SP)
   337		MOVL	$93, AX
   338		INT	$0x80
   339		RET
   340	
   341	// func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
   342	// System call args are: func arg stack pthread flags.
   343	TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
   344		MOVL	$360, AX
   345		// 0(SP) is where the caller PC would be; kernel skips it
   346		MOVL	fn+8(FP), BX
   347		MOVL	BX, 4(SP)	// func
   348		MOVL	arg+4(FP), BX
   349		MOVL	BX, 8(SP)	// arg
   350		MOVL	stk+0(FP), BX
   351		MOVL	BX, 12(SP)	// stack
   352		MOVL    $0, 16(SP)      // pthread
   353		MOVL	$0x1000000, 20(SP)	// flags = PTHREAD_START_CUSTOM
   354		INT	$0x80
   355		JAE	4(PC)
   356		NEGL	AX
   357		MOVL	AX, ret+12(FP)
   358		RET
   359		MOVL	$0, AX
   360		MOVL	AX, ret+12(FP)
   361		RET
   362	
   363	// The thread that bsdthread_create creates starts executing here,
   364	// because we registered this function using bsdthread_register
   365	// at startup.
   366	//	AX = "pthread" (= 0x0)
   367	//	BX = mach thread port
   368	//	CX = "func" (= fn)
   369	//	DX = "arg" (= m)
   370	//	DI = stack top
   371	//	SI = flags (= 0x1000000)
   372	//	SP = stack - C_32_STK_ALIGN
   373	TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
   374		// set up ldt 7+id to point at m->tls.
   375		LEAL	m_tls(DX), BP
   376		MOVL	m_id(DX), DI
   377		ADDL	$7, DI	// m0 is LDT#7. count up.
   378		// setldt(tls#, &tls, sizeof tls)
   379		PUSHAL	// save registers
   380		PUSHL	$32	// sizeof tls
   381		PUSHL	BP	// &tls
   382		PUSHL	DI	// tls #
   383		CALL	runtime·setldt(SB)
   384		POPL	AX
   385		POPL	AX
   386		POPL	AX
   387		POPAL
   388	
   389		// Now segment is established. Initialize m, g.
   390		get_tls(BP)
   391		MOVL    m_g0(DX), AX
   392		MOVL	AX, g(BP)
   393		MOVL	DX, g_m(AX)
   394		MOVL	BX, m_procid(DX)	// m->procid = thread port (for debuggers)
   395		CALL	runtime·stackcheck(SB)		// smashes AX
   396		CALL	CX	// fn()
   397		CALL	runtime·exit1(SB)
   398		RET
   399	
   400	// func bsdthread_register() int32
   401	// registers callbacks for threadstart (see bsdthread_create above
   402	// and wqthread and pthsize (not used).  returns 0 on success.
   403	TEXT runtime·bsdthread_register(SB),NOSPLIT,$40
   404		MOVL	$366, AX
   405		// 0(SP) is where kernel expects caller PC; ignored
   406		MOVL	$runtime·bsdthread_start(SB), 4(SP)	// threadstart
   407		MOVL	$0, 8(SP)	// wqthread, not used by us
   408		MOVL	$0, 12(SP)	// pthsize, not used by us
   409		MOVL	$0, 16(SP)	// dummy_value [sic]
   410		MOVL	$0, 20(SP)	// targetconc_ptr
   411		MOVL	$0, 24(SP)	// dispatchqueue_offset
   412		INT	$0x80
   413		JAE	4(PC)
   414		NEGL	AX
   415		MOVL	AX, ret+0(FP)
   416		RET
   417		MOVL	$0, AX
   418		MOVL	AX, ret+0(FP)
   419		RET
   420	
   421	// Invoke Mach system call.
   422	// Assumes system call number in AX,
   423	// caller PC on stack, caller's caller PC next,
   424	// and then the system call arguments.
   425	//
   426	// Can be used for BSD too, but we don't,
   427	// because if you use this interface the BSD
   428	// system call numbers need an extra field
   429	// in the high 16 bits that seems to be the
   430	// argument count in bytes but is not always.
   431	// INT $0x80 works fine for those.
   432	TEXT runtime·sysenter(SB),NOSPLIT,$0
   433		POPL	DX
   434		MOVL	SP, CX
   435		BYTE $0x0F; BYTE $0x34;  // SYSENTER
   436		// returns to DX with SP set to CX
   437	
   438	TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
   439		MOVL	$-31, AX
   440		CALL	runtime·sysenter(SB)
   441		MOVL	AX, ret+28(FP)
   442		RET
   443	
   444	TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
   445		MOVL	$-26, AX
   446		CALL	runtime·sysenter(SB)
   447		MOVL	AX, ret+0(FP)
   448		RET
   449	
   450	TEXT runtime·mach_task_self(SB),NOSPLIT,$0
   451		MOVL	$-28, AX
   452		CALL	runtime·sysenter(SB)
   453		MOVL	AX, ret+0(FP)
   454		RET
   455	
   456	// Mach provides trap versions of the semaphore ops,
   457	// instead of requiring the use of RPC.
   458	
   459	// func mach_semaphore_wait(sema uint32) int32
   460	TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
   461		MOVL	$-36, AX
   462		CALL	runtime·sysenter(SB)
   463		MOVL	AX, ret+4(FP)
   464		RET
   465	
   466	// func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
   467	TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
   468		MOVL	$-38, AX
   469		CALL	runtime·sysenter(SB)
   470		MOVL	AX, ret+12(FP)
   471		RET
   472	
   473	// func mach_semaphore_signal(sema uint32) int32
   474	TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
   475		MOVL	$-33, AX
   476		CALL	runtime·sysenter(SB)
   477		MOVL	AX, ret+4(FP)
   478		RET
   479	
   480	// func mach_semaphore_signal_all(sema uint32) int32
   481	TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
   482		MOVL	$-34, AX
   483		CALL	runtime·sysenter(SB)
   484		MOVL	AX, ret+4(FP)
   485		RET
   486	
   487	// func setldt(entry int, address int, limit int)
   488	// entry and limit are ignored.
   489	TEXT runtime·setldt(SB),NOSPLIT,$32
   490		MOVL	address+4(FP), BX	// aka base
   491	
   492		/*
   493		 * When linking against the system libraries,
   494		 * we use its pthread_create and let it set up %gs
   495		 * for us.  When we do that, the private storage
   496		 * we get is not at 0(GS) but at 0x468(GS).
   497		 * 8l rewrites 0(TLS) into 0x468(GS) for us.
   498		 * To accommodate that rewrite, we translate the
   499		 * address and limit here so that 0x468(GS) maps to 0(address).
   500		 *
   501		 * See cgo/gcc_darwin_386.c:/468 for the derivation
   502		 * of the constant.
   503		 */
   504		SUBL	$0x468, BX
   505	
   506		/*
   507		 * Must set up as USER_CTHREAD segment because
   508		 * Darwin forces that value into %gs for signal handlers,
   509		 * and if we don't set one up, we'll get a recursive
   510		 * fault trying to get into the signal handler.
   511		 * Since we have to set one up anyway, it might as
   512		 * well be the value we want.  So don't bother with
   513		 * i386_set_ldt.
   514		 */
   515		MOVL	BX, 4(SP)
   516		MOVL	$3, AX	// thread_fast_set_cthread_self - machdep call #3
   517		INT	$0x82	// sic: 0x82, not 0x80, for machdep call
   518	
   519		XORL	AX, AX
   520		MOVW	GS, AX
   521		RET
   522	
   523	TEXT runtime·sysctl(SB),NOSPLIT,$0
   524		MOVL	$202, AX
   525		INT	$0x80
   526		JAE	4(PC)
   527		NEGL	AX
   528		MOVL	AX, ret+24(FP)
   529		RET
   530		MOVL	$0, AX
   531		MOVL	AX, ret+24(FP)
   532		RET
   533	
   534	// func kqueue() int32
   535	TEXT runtime·kqueue(SB),NOSPLIT,$0
   536		MOVL	$362, AX
   537		INT	$0x80
   538		JAE	2(PC)
   539		NEGL	AX
   540		MOVL	AX, ret+0(FP)
   541		RET
   542	
   543	// func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
   544	TEXT runtime·kevent(SB),NOSPLIT,$0
   545		MOVL	$363, AX
   546		INT	$0x80
   547		JAE	2(PC)
   548		NEGL	AX
   549		MOVL	AX, ret+24(FP)
   550		RET
   551	
   552	// func closeonexec(fd int32)
   553	TEXT runtime·closeonexec(SB),NOSPLIT,$32
   554		MOVL	$92, AX  // fcntl
   555		// 0(SP) is where the caller PC would be; kernel skips it
   556		MOVL	fd+0(FP), BX
   557		MOVL	BX, 4(SP)  // fd
   558		MOVL	$2, 8(SP)  // F_SETFD
   559		MOVL	$1, 12(SP)  // FD_CLOEXEC
   560		INT	$0x80
   561		JAE	2(PC)
   562		NEGL	AX
   563		RET

View as plain text