github.com/euank/go@v0.0.0-20160829210321-495514729181/src/runtime/sys_darwin_386.s (about)

     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  TEXT runtime·now(SB),NOSPLIT,$40
   118  	MOVL	$0xffff0000, BP /* comm page base */
   119  	
   120  	// Test for slow CPU. If so, the math is completely
   121  	// different, and unimplemented here, so use the
   122  	// system call.
   123  	MOVL	cpu_capabilities(BP), AX
   124  	TESTL	$0x4000, AX
   125  	JNZ	systime
   126  
   127  	// Loop trying to take a consistent snapshot
   128  	// of the time parameters.
   129  timeloop:
   130  	MOVL	gtod_generation(BP), BX
   131  	TESTL	BX, BX
   132  	JZ	systime
   133  	MOVL	nt_generation(BP), CX
   134  	TESTL	CX, CX
   135  	JZ	timeloop
   136  	RDTSC
   137  	MOVL	nt_tsc_base(BP), SI
   138  	MOVL	(nt_tsc_base+4)(BP), DI
   139  	MOVL	SI, 0(SP)
   140  	MOVL	DI, 4(SP)
   141  	MOVL	nt_scale(BP), SI
   142  	MOVL	SI, 8(SP)
   143  	MOVL	nt_ns_base(BP), SI
   144  	MOVL	(nt_ns_base+4)(BP), DI
   145  	MOVL	SI, 12(SP)
   146  	MOVL	DI, 16(SP)
   147  	CMPL	nt_generation(BP), CX
   148  	JNE	timeloop
   149  	MOVL	gtod_ns_base(BP), SI
   150  	MOVL	(gtod_ns_base+4)(BP), DI
   151  	MOVL	SI, 20(SP)
   152  	MOVL	DI, 24(SP)
   153  	MOVL	gtod_sec_base(BP), SI
   154  	MOVL	(gtod_sec_base+4)(BP), DI
   155  	MOVL	SI, 28(SP)
   156  	MOVL	DI, 32(SP)
   157  	CMPL	gtod_generation(BP), BX
   158  	JNE	timeloop
   159  
   160  	// Gathered all the data we need. Compute time.
   161  	//	((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
   162  	// The multiply and shift extracts the top 64 bits of the 96-bit product.
   163  	SUBL	0(SP), AX // DX:AX = (tsc - nt_tsc_base)
   164  	SBBL	4(SP), DX
   165  
   166  	// We have x = tsc - nt_tsc_base - DX:AX to be
   167  	// multiplied by y = nt_scale = 8(SP), keeping the top 64 bits of the 96-bit product.
   168  	// x*y = (x&0xffffffff)*y + (x&0xffffffff00000000)*y
   169  	// (x*y)>>32 = ((x&0xffffffff)*y)>>32 + (x>>32)*y
   170  	MOVL	DX, CX // SI = (x&0xffffffff)*y >> 32
   171  	MOVL	$0, DX
   172  	MULL	8(SP)
   173  	MOVL	DX, SI
   174  
   175  	MOVL	CX, AX // DX:AX = (x>>32)*y
   176  	MOVL	$0, DX
   177  	MULL	8(SP)
   178  
   179  	ADDL	SI, AX	// DX:AX += (x&0xffffffff)*y >> 32
   180  	ADCL	$0, DX
   181  	
   182  	// DX:AX is now ((tsc - nt_tsc_base) * nt_scale) >> 32.
   183  	ADDL	12(SP), AX	// DX:AX += nt_ns_base
   184  	ADCL	16(SP), DX
   185  	SUBL	20(SP), AX	// DX:AX -= gtod_ns_base
   186  	SBBL	24(SP), DX
   187  	MOVL	AX, SI	// DI:SI = DX:AX
   188  	MOVL	DX, DI
   189  	MOVL	28(SP), AX	// DX:AX = gtod_sec_base*1e9
   190  	MOVL	32(SP), DX
   191  	MOVL	$1000000000, CX
   192  	MULL	CX
   193  	ADDL	SI, AX	// DX:AX += DI:SI
   194  	ADCL	DI, DX
   195  	RET
   196  
   197  systime:
   198  	// Fall back to system call (usually first call in this thread)
   199  	LEAL	16(SP), AX	// must be non-nil, unused
   200  	MOVL	AX, 4(SP)
   201  	MOVL	$0, 8(SP)	// time zone pointer
   202  	MOVL	$0, 12(SP)	// required as of Sierra; Issue 16570
   203  	MOVL	$116, AX
   204  	INT	$0x80
   205  	CMPL	AX, $0
   206  	JNE	inreg
   207  	MOVL	16(SP), AX
   208  	MOVL	20(SP), DX
   209  inreg:
   210  	// sec is in AX, usec in DX
   211  	// convert to DX:AX nsec
   212  	MOVL	DX, BX
   213  	MOVL	$1000000000, CX
   214  	MULL	CX
   215  	IMULL	$1000, BX
   216  	ADDL	BX, AX
   217  	ADCL	$0, DX
   218  	RET
   219  
   220  // func now() (sec int64, nsec int32)
   221  TEXT time·now(SB),NOSPLIT,$0
   222  	CALL	runtime·now(SB)
   223  	MOVL	$1000000000, CX
   224  	DIVL	CX
   225  	MOVL	AX, sec+0(FP)
   226  	MOVL	$0, sec+4(FP)
   227  	MOVL	DX, nsec+8(FP)
   228  	RET
   229  
   230  // func nanotime() int64
   231  TEXT runtime·nanotime(SB),NOSPLIT,$0
   232  	CALL	runtime·now(SB)
   233  	MOVL	AX, ret_lo+0(FP)
   234  	MOVL	DX, ret_hi+4(FP)
   235  	RET
   236  
   237  TEXT runtime·sigprocmask(SB),NOSPLIT,$0
   238  	MOVL	$329, AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
   239  	INT	$0x80
   240  	JAE	2(PC)
   241  	MOVL	$0xf1, 0xf1  // crash
   242  	RET
   243  
   244  TEXT runtime·sigaction(SB),NOSPLIT,$0
   245  	MOVL	$46, AX
   246  	INT	$0x80
   247  	JAE	2(PC)
   248  	MOVL	$0xf1, 0xf1  // crash
   249  	RET
   250  
   251  TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
   252  	MOVL	fn+0(FP), AX
   253  	MOVL	sig+4(FP), BX
   254  	MOVL	info+8(FP), CX
   255  	MOVL	ctx+12(FP), DX
   256  	MOVL	SP, SI
   257  	SUBL	$32, SP		// align stack; handler might be C code
   258  	ANDL	$~15, SP
   259  	MOVL	BX, 0(SP)
   260  	MOVL	CX, 4(SP)
   261  	MOVL	DX, 8(SP)
   262  	MOVL	SI, 12(SP)
   263  	CALL	AX
   264  	MOVL	12(SP), AX
   265  	MOVL	AX, SP
   266  	RET
   267  
   268  TEXT runtime·sigreturn(SB),NOSPLIT,$12-8
   269  	MOVL	ctx+0(FP), CX
   270  	MOVL	infostyle+4(FP), BX
   271  	MOVL	$0, 0(SP)	// "caller PC" - ignored
   272  	MOVL	CX, 4(SP)
   273  	MOVL	BX, 8(SP)
   274  	MOVL	$184, AX	// sigreturn(ucontext, infostyle)
   275  	INT	$0x80
   276  	MOVL	$0xf1, 0xf1  // crash
   277  	RET
   278  
   279  // Sigtramp's job is to call the actual signal handler.
   280  // It is called with the following arguments on the stack:
   281  //	0(SP)	"return address" - ignored
   282  //	4(SP)	actual handler
   283  //	8(SP)	siginfo style
   284  //	12(SP)	signal number
   285  //	16(SP)	siginfo
   286  //	20(SP)	context
   287  TEXT runtime·sigtramp(SB),NOSPLIT,$20
   288  	MOVL	fn+0(FP), BX
   289  	MOVL	BX, 0(SP)
   290  	MOVL	infostyle+4(FP), BX
   291  	MOVL	BX, 4(SP)
   292  	MOVL	sig+8(FP), BX
   293  	MOVL	BX, 8(SP)
   294  	MOVL	info+12(FP), BX
   295  	MOVL	BX, 12(SP)
   296  	MOVL	ctx+16(FP), BX
   297  	MOVL	BX, 16(SP)
   298  	CALL	runtime·sigtrampgo(SB)
   299  
   300  	// call sigreturn
   301  	MOVL	ctx+16(FP), CX
   302  	MOVL	infostyle+4(FP), BX
   303  	MOVL	$0, 0(SP)	// "caller PC" - ignored
   304  	MOVL	CX, 4(SP)
   305  	MOVL	BX, 8(SP)
   306  	MOVL	$184, AX	// sigreturn(ucontext, infostyle)
   307  	INT	$0x80
   308  	MOVL	$0xf1, 0xf1  // crash
   309  	RET
   310  
   311  TEXT runtime·sigaltstack(SB),NOSPLIT,$0
   312  	MOVL	$53, AX
   313  	INT	$0x80
   314  	JAE	2(PC)
   315  	MOVL	$0xf1, 0xf1  // crash
   316  	RET
   317  
   318  TEXT runtime·usleep(SB),NOSPLIT,$32
   319  	MOVL	$0, DX
   320  	MOVL	usec+0(FP), AX
   321  	MOVL	$1000000, CX
   322  	DIVL	CX
   323  	MOVL	AX, 24(SP)  // sec
   324  	MOVL	DX, 28(SP)  // usec
   325  
   326  	// select(0, 0, 0, 0, &tv)
   327  	MOVL	$0, 0(SP)  // "return PC" - ignored
   328  	MOVL	$0, 4(SP)
   329  	MOVL	$0, 8(SP)
   330  	MOVL	$0, 12(SP)
   331  	MOVL	$0, 16(SP)
   332  	LEAL	24(SP), AX
   333  	MOVL	AX, 20(SP)
   334  	MOVL	$93, AX
   335  	INT	$0x80
   336  	RET
   337  
   338  // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
   339  // System call args are: func arg stack pthread flags.
   340  TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
   341  	MOVL	$360, AX
   342  	// 0(SP) is where the caller PC would be; kernel skips it
   343  	MOVL	fn+8(FP), BX
   344  	MOVL	BX, 4(SP)	// func
   345  	MOVL	arg+4(FP), BX
   346  	MOVL	BX, 8(SP)	// arg
   347  	MOVL	stk+0(FP), BX
   348  	MOVL	BX, 12(SP)	// stack
   349  	MOVL    $0, 16(SP)      // pthread
   350  	MOVL	$0x1000000, 20(SP)	// flags = PTHREAD_START_CUSTOM
   351  	INT	$0x80
   352  	JAE	4(PC)
   353  	NEGL	AX
   354  	MOVL	AX, ret+12(FP)
   355  	RET
   356  	MOVL	$0, AX
   357  	MOVL	AX, ret+12(FP)
   358  	RET
   359  
   360  // The thread that bsdthread_create creates starts executing here,
   361  // because we registered this function using bsdthread_register
   362  // at startup.
   363  //	AX = "pthread" (= 0x0)
   364  //	BX = mach thread port
   365  //	CX = "func" (= fn)
   366  //	DX = "arg" (= m)
   367  //	DI = stack top
   368  //	SI = flags (= 0x1000000)
   369  //	SP = stack - C_32_STK_ALIGN
   370  TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
   371  	// set up ldt 7+id to point at m->tls.
   372  	LEAL	m_tls(DX), BP
   373  	MOVL	m_id(DX), DI
   374  	ADDL	$7, DI	// m0 is LDT#7. count up.
   375  	// setldt(tls#, &tls, sizeof tls)
   376  	PUSHAL	// save registers
   377  	PUSHL	$32	// sizeof tls
   378  	PUSHL	BP	// &tls
   379  	PUSHL	DI	// tls #
   380  	CALL	runtime·setldt(SB)
   381  	POPL	AX
   382  	POPL	AX
   383  	POPL	AX
   384  	POPAL
   385  
   386  	// Now segment is established. Initialize m, g.
   387  	get_tls(BP)
   388  	MOVL    m_g0(DX), AX
   389  	MOVL	AX, g(BP)
   390  	MOVL	DX, g_m(AX)
   391  	MOVL	BX, m_procid(DX)	// m->procid = thread port (for debuggers)
   392  	CALL	runtime·stackcheck(SB)		// smashes AX
   393  	CALL	CX	// fn()
   394  	CALL	runtime·exit1(SB)
   395  	RET
   396  
   397  // func bsdthread_register() int32
   398  // registers callbacks for threadstart (see bsdthread_create above
   399  // and wqthread and pthsize (not used).  returns 0 on success.
   400  TEXT runtime·bsdthread_register(SB),NOSPLIT,$40
   401  	MOVL	$366, AX
   402  	// 0(SP) is where kernel expects caller PC; ignored
   403  	MOVL	$runtime·bsdthread_start(SB), 4(SP)	// threadstart
   404  	MOVL	$0, 8(SP)	// wqthread, not used by us
   405  	MOVL	$0, 12(SP)	// pthsize, not used by us
   406  	MOVL	$0, 16(SP)	// dummy_value [sic]
   407  	MOVL	$0, 20(SP)	// targetconc_ptr
   408  	MOVL	$0, 24(SP)	// dispatchqueue_offset
   409  	INT	$0x80
   410  	JAE	4(PC)
   411  	NEGL	AX
   412  	MOVL	AX, ret+0(FP)
   413  	RET
   414  	MOVL	$0, AX
   415  	MOVL	AX, ret+0(FP)
   416  	RET
   417  
   418  // Invoke Mach system call.
   419  // Assumes system call number in AX,
   420  // caller PC on stack, caller's caller PC next,
   421  // and then the system call arguments.
   422  //
   423  // Can be used for BSD too, but we don't,
   424  // because if you use this interface the BSD
   425  // system call numbers need an extra field
   426  // in the high 16 bits that seems to be the
   427  // argument count in bytes but is not always.
   428  // INT $0x80 works fine for those.
   429  TEXT runtime·sysenter(SB),NOSPLIT,$0
   430  	POPL	DX
   431  	MOVL	SP, CX
   432  	BYTE $0x0F; BYTE $0x34;  // SYSENTER
   433  	// returns to DX with SP set to CX
   434  
   435  TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
   436  	MOVL	$-31, AX
   437  	CALL	runtime·sysenter(SB)
   438  	MOVL	AX, ret+28(FP)
   439  	RET
   440  
   441  TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
   442  	MOVL	$-26, AX
   443  	CALL	runtime·sysenter(SB)
   444  	MOVL	AX, ret+0(FP)
   445  	RET
   446  
   447  TEXT runtime·mach_task_self(SB),NOSPLIT,$0
   448  	MOVL	$-28, AX
   449  	CALL	runtime·sysenter(SB)
   450  	MOVL	AX, ret+0(FP)
   451  	RET
   452  
   453  // Mach provides trap versions of the semaphore ops,
   454  // instead of requiring the use of RPC.
   455  
   456  // func mach_semaphore_wait(sema uint32) int32
   457  TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
   458  	MOVL	$-36, AX
   459  	CALL	runtime·sysenter(SB)
   460  	MOVL	AX, ret+4(FP)
   461  	RET
   462  
   463  // func mach_semaphore_timedwait(sema, sec, nsec uint32) int32
   464  TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
   465  	MOVL	$-38, AX
   466  	CALL	runtime·sysenter(SB)
   467  	MOVL	AX, ret+12(FP)
   468  	RET
   469  
   470  // func mach_semaphore_signal(sema uint32) int32
   471  TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
   472  	MOVL	$-33, AX
   473  	CALL	runtime·sysenter(SB)
   474  	MOVL	AX, ret+4(FP)
   475  	RET
   476  
   477  // func mach_semaphore_signal_all(sema uint32) int32
   478  TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
   479  	MOVL	$-34, AX
   480  	CALL	runtime·sysenter(SB)
   481  	MOVL	AX, ret+4(FP)
   482  	RET
   483  
   484  // func setldt(entry int, address int, limit int)
   485  // entry and limit are ignored.
   486  TEXT runtime·setldt(SB),NOSPLIT,$32
   487  	MOVL	address+4(FP), BX	// aka base
   488  
   489  	/*
   490  	 * When linking against the system libraries,
   491  	 * we use its pthread_create and let it set up %gs
   492  	 * for us.  When we do that, the private storage
   493  	 * we get is not at 0(GS) but at 0x468(GS).
   494  	 * 8l rewrites 0(TLS) into 0x468(GS) for us.
   495  	 * To accommodate that rewrite, we translate the
   496  	 * address and limit here so that 0x468(GS) maps to 0(address).
   497  	 *
   498  	 * See cgo/gcc_darwin_386.c:/468 for the derivation
   499  	 * of the constant.
   500  	 */
   501  	SUBL	$0x468, BX
   502  
   503  	/*
   504  	 * Must set up as USER_CTHREAD segment because
   505  	 * Darwin forces that value into %gs for signal handlers,
   506  	 * and if we don't set one up, we'll get a recursive
   507  	 * fault trying to get into the signal handler.
   508  	 * Since we have to set one up anyway, it might as
   509  	 * well be the value we want.  So don't bother with
   510  	 * i386_set_ldt.
   511  	 */
   512  	MOVL	BX, 4(SP)
   513  	MOVL	$3, AX	// thread_fast_set_cthread_self - machdep call #3
   514  	INT	$0x82	// sic: 0x82, not 0x80, for machdep call
   515  
   516  	XORL	AX, AX
   517  	MOVW	GS, AX
   518  	RET
   519  
   520  TEXT runtime·sysctl(SB),NOSPLIT,$0
   521  	MOVL	$202, AX
   522  	INT	$0x80
   523  	JAE	4(PC)
   524  	NEGL	AX
   525  	MOVL	AX, ret+24(FP)
   526  	RET
   527  	MOVL	$0, AX
   528  	MOVL	AX, ret+24(FP)
   529  	RET
   530  
   531  // func kqueue() int32
   532  TEXT runtime·kqueue(SB),NOSPLIT,$0
   533  	MOVL	$362, AX
   534  	INT	$0x80
   535  	JAE	2(PC)
   536  	NEGL	AX
   537  	MOVL	AX, ret+0(FP)
   538  	RET
   539  
   540  // func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32
   541  TEXT runtime·kevent(SB),NOSPLIT,$0
   542  	MOVL	$363, AX
   543  	INT	$0x80
   544  	JAE	2(PC)
   545  	NEGL	AX
   546  	MOVL	AX, ret+24(FP)
   547  	RET
   548  
   549  // func closeonexec(fd int32)
   550  TEXT runtime·closeonexec(SB),NOSPLIT,$32
   551  	MOVL	$92, AX  // fcntl
   552  	// 0(SP) is where the caller PC would be; kernel skips it
   553  	MOVL	fd+0(FP), BX
   554  	MOVL	BX, 4(SP)  // fd
   555  	MOVL	$2, 8(SP)  // F_SETFD
   556  	MOVL	$1, 12(SP)  // FD_CLOEXEC
   557  	INT	$0x80
   558  	JAE	2(PC)
   559  	NEGL	AX
   560  	RET