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