github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/sys_solaris_amd64.s (about)

     1  // Copyright 2014 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 AMD64, SunOS
     6  // /usr/include/sys/syscall.h for syscall numbers.
     7  //
     8  
     9  #include "go_asm.h"
    10  #include "go_tls.h"
    11  #include "textflag.h"
    12  
    13  // This is needed by asm_amd64.s
    14  TEXT runtime·settls(SB),NOSPLIT,$8
    15  	RET
    16  
    17  // void libc_miniterrno(void *(*___errno)(void));
    18  //
    19  // Set the TLS errno pointer in M.
    20  //
    21  // Called using runtime·asmcgocall from os_solaris.c:/minit.
    22  // NOT USING GO CALLING CONVENTION.
    23  TEXT runtime·miniterrno(SB),NOSPLIT,$0
    24  	// asmcgocall will put first argument into DI.
    25  	CALL	DI	// SysV ABI so returns in AX
    26  	get_tls(CX)
    27  	MOVQ	g(CX), BX
    28  	MOVQ	g_m(BX), BX
    29  	MOVQ	AX,	(m_mOS+mOS_perrno)(BX)
    30  	RET
    31  
    32  // int64 runtime·nanotime1(void);
    33  //
    34  // clock_gettime(3c) wrapper because Timespec is too large for
    35  // runtime·nanotime stack.
    36  //
    37  // Called using runtime·sysvicall6 from os_solaris.c:/nanotime.
    38  // NOT USING GO CALLING CONVENTION.
    39  TEXT runtime·nanotime1(SB),NOSPLIT,$0
    40  	// need space for the timespec argument.
    41  	SUBQ	$64, SP	// 16 bytes will do, but who knows in the future?
    42  	MOVQ	$3, DI	// CLOCK_REALTIME from <sys/time_impl.h>
    43  	MOVQ	SP, SI
    44  	LEAQ	libc_clock_gettime(SB), AX
    45  	CALL	AX
    46  	MOVQ	(SP), AX	// tv_sec from struct timespec
    47  	IMULQ	$1000000000, AX	// multiply into nanoseconds
    48  	ADDQ	8(SP), AX	// tv_nsec, offset should be stable.
    49  	ADDQ	$64, SP
    50  	RET
    51  
    52  // pipe(3c) wrapper that returns fds in AX, DX.
    53  // NOT USING GO CALLING CONVENTION.
    54  TEXT runtime·pipe1(SB),NOSPLIT,$0
    55  	SUBQ	$16, SP // 8 bytes will do, but stack has to be 16-byte aligned
    56  	MOVQ	SP, DI
    57  	LEAQ	libc_pipe(SB), AX
    58  	CALL	AX
    59  	MOVL	0(SP), AX
    60  	MOVL	4(SP), DX
    61  	ADDQ	$16, SP
    62  	RET
    63  
    64  // Call a library function with SysV calling conventions.
    65  // The called function can take a maximum of 6 INTEGER class arguments,
    66  // see 
    67  //   Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
    68  //   System V Application Binary Interface 
    69  //   AMD64 Architecture Processor Supplement
    70  // section 3.2.3.
    71  //
    72  // Called by runtime·asmcgocall or runtime·cgocall.
    73  // NOT USING GO CALLING CONVENTION.
    74  TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
    75  	// asmcgocall will put first argument into DI.
    76  	PUSHQ	DI			// save for later
    77  	MOVQ	libcall_fn(DI), AX
    78  	MOVQ	libcall_args(DI), R11
    79  	MOVQ	libcall_n(DI), R10
    80  
    81  	get_tls(CX)
    82  	MOVQ	g(CX), BX
    83  	CMPQ	BX, $0
    84  	JEQ	skiperrno1
    85  	MOVQ	g_m(BX), BX
    86  	MOVQ	(m_mOS+mOS_perrno)(BX), DX
    87  	CMPQ	DX, $0
    88  	JEQ	skiperrno1
    89  	MOVL	$0, 0(DX)
    90  
    91  skiperrno1:
    92  	CMPQ	R11, $0
    93  	JEQ	skipargs
    94  	// Load 6 args into correspondent registers.
    95  	MOVQ	0(R11), DI
    96  	MOVQ	8(R11), SI
    97  	MOVQ	16(R11), DX
    98  	MOVQ	24(R11), CX
    99  	MOVQ	32(R11), R8
   100  	MOVQ	40(R11), R9
   101  skipargs:
   102  
   103  	// Call SysV function
   104  	CALL	AX
   105  
   106  	// Return result
   107  	POPQ	DI
   108  	MOVQ	AX, libcall_r1(DI)
   109  	MOVQ	DX, libcall_r2(DI)
   110  
   111  	get_tls(CX)
   112  	MOVQ	g(CX), BX
   113  	CMPQ	BX, $0
   114  	JEQ	skiperrno2
   115  	MOVQ	g_m(BX), BX
   116  	MOVQ	(m_mOS+mOS_perrno)(BX), AX
   117  	CMPQ	AX, $0
   118  	JEQ	skiperrno2
   119  	MOVL	0(AX), AX
   120  	MOVQ	AX, libcall_err(DI)
   121  
   122  skiperrno2:	
   123  	RET
   124  
   125  // uint32 tstart_sysvicall(M *newm);
   126  TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
   127  	// DI contains first arg newm
   128  	MOVQ	m_g0(DI), DX		// g
   129  
   130  	// Make TLS entries point at g and m.
   131  	get_tls(BX)
   132  	MOVQ	DX, g(BX)
   133  	MOVQ	DI, g_m(DX)
   134  
   135  	// Layout new m scheduler stack on os stack.
   136  	MOVQ	SP, AX
   137  	MOVQ	AX, (g_stack+stack_hi)(DX)
   138  	SUBQ	$(0x100000), AX		// stack size
   139  	MOVQ	AX, (g_stack+stack_lo)(DX)
   140  	ADDQ	$const__StackGuard, AX
   141  	MOVQ	AX, g_stackguard0(DX)
   142  	MOVQ	AX, g_stackguard1(DX)
   143  
   144  	// Someday the convention will be D is always cleared.
   145  	CLD
   146  
   147  	CALL	runtime·stackcheck(SB)	// clobbers AX,CX
   148  	CALL	runtime·mstart(SB)
   149  
   150  	XORL	AX, AX			// return 0 == success
   151  	MOVL	AX, ret+8(FP)
   152  	RET
   153  
   154  // Careful, this is called by __sighndlr, a libc function. We must preserve
   155  // registers as per AMD 64 ABI.
   156  TEXT runtime·sigtramp(SB),NOSPLIT,$0
   157  	// Note that we are executing on altsigstack here, so we have
   158  	// more stack available than NOSPLIT would have us believe.
   159  	// To defeat the linker, we make our own stack frame with
   160  	// more space:
   161  	SUBQ    $184, SP
   162  
   163  	// save registers
   164  	MOVQ    BX, 32(SP)
   165  	MOVQ    BP, 40(SP)
   166  	MOVQ	R12, 48(SP)
   167  	MOVQ	R13, 56(SP)
   168  	MOVQ	R14, 64(SP)
   169  	MOVQ	R15, 72(SP)
   170  
   171  	get_tls(BX)
   172  	// check that g exists
   173  	MOVQ	g(BX), R10
   174  	CMPQ	R10, $0
   175  	JNE	allgood
   176  	MOVQ	SI, 80(SP)
   177  	MOVQ	DX, 88(SP)
   178  	LEAQ	80(SP), AX
   179  	MOVQ	DI, 0(SP)
   180  	MOVQ	AX, 8(SP)
   181  	MOVQ	$runtime·badsignal(SB), AX
   182  	CALL	AX
   183  	JMP	exit
   184  
   185  allgood:
   186  	// save g
   187  	MOVQ	R10, 80(SP)
   188  
   189  	// Save m->libcall and m->scratch. We need to do this because we
   190  	// might get interrupted by a signal in runtime·asmcgocall.
   191  
   192  	// save m->libcall 
   193  	MOVQ	g_m(R10), BP
   194  	LEAQ	m_libcall(BP), R11
   195  	MOVQ	libcall_fn(R11), R10
   196  	MOVQ	R10, 88(SP)
   197  	MOVQ	libcall_args(R11), R10
   198  	MOVQ	R10, 96(SP)
   199  	MOVQ	libcall_n(R11), R10
   200  	MOVQ	R10, 104(SP)
   201  	MOVQ    libcall_r1(R11), R10
   202  	MOVQ    R10, 168(SP)
   203  	MOVQ    libcall_r2(R11), R10
   204  	MOVQ    R10, 176(SP)
   205  
   206  	// save m->scratch
   207  	LEAQ	(m_mOS+mOS_scratch)(BP), R11
   208  	MOVQ	0(R11), R10
   209  	MOVQ	R10, 112(SP)
   210  	MOVQ	8(R11), R10
   211  	MOVQ	R10, 120(SP)
   212  	MOVQ	16(R11), R10
   213  	MOVQ	R10, 128(SP)
   214  	MOVQ	24(R11), R10
   215  	MOVQ	R10, 136(SP)
   216  	MOVQ	32(R11), R10
   217  	MOVQ	R10, 144(SP)
   218  	MOVQ	40(R11), R10
   219  	MOVQ	R10, 152(SP)
   220  
   221  	// save errno, it might be EINTR; stuff we do here might reset it.
   222  	MOVQ	(m_mOS+mOS_perrno)(BP), R10
   223  	MOVL	0(R10), R10
   224  	MOVQ	R10, 160(SP)
   225  
   226  	MOVQ	g(BX), R10
   227  	// g = m->gsignal
   228  	MOVQ	m_gsignal(BP), BP
   229  	MOVQ	BP, g(BX)
   230  
   231  	// TODO: If current SP is not in gsignal.stack, then adjust.
   232  
   233  	// prepare call
   234  	MOVQ	DI, 0(SP)
   235  	MOVQ	SI, 8(SP)
   236  	MOVQ	DX, 16(SP)
   237  	MOVQ	R10, 24(SP)
   238  	CALL	runtime·sighandler(SB)
   239  
   240  	get_tls(BX)
   241  	MOVQ	g(BX), BP
   242  	MOVQ	g_m(BP), BP
   243  	// restore libcall
   244  	LEAQ	m_libcall(BP), R11
   245  	MOVQ	88(SP), R10
   246  	MOVQ	R10, libcall_fn(R11)
   247  	MOVQ	96(SP), R10
   248  	MOVQ	R10, libcall_args(R11)
   249  	MOVQ	104(SP), R10
   250  	MOVQ	R10, libcall_n(R11)
   251  	MOVQ    168(SP), R10
   252  	MOVQ    R10, libcall_r1(R11)
   253  	MOVQ    176(SP), R10
   254  	MOVQ    R10, libcall_r2(R11)
   255  
   256  	// restore scratch
   257  	LEAQ	(m_mOS+mOS_scratch)(BP), R11
   258  	MOVQ	112(SP), R10
   259  	MOVQ	R10, 0(R11)
   260  	MOVQ	120(SP), R10
   261  	MOVQ	R10, 8(R11)
   262  	MOVQ	128(SP), R10
   263  	MOVQ	R10, 16(R11)
   264  	MOVQ	136(SP), R10
   265  	MOVQ	R10, 24(R11)
   266  	MOVQ	144(SP), R10
   267  	MOVQ	R10, 32(R11)
   268  	MOVQ	152(SP), R10
   269  	MOVQ	R10, 40(R11)
   270  
   271  	// restore errno
   272  	MOVQ	(m_mOS+mOS_perrno)(BP), R11
   273  	MOVQ	160(SP), R10
   274  	MOVL	R10, 0(R11)
   275  
   276  	// restore g
   277  	MOVQ	80(SP), R10
   278  	MOVQ	R10, g(BX)
   279  
   280  exit:
   281  	// restore registers
   282  	MOVQ	32(SP), BX
   283  	MOVQ	40(SP), BP
   284  	MOVQ	48(SP), R12
   285  	MOVQ	56(SP), R13
   286  	MOVQ	64(SP), R14
   287  	MOVQ	72(SP), R15
   288  
   289  	ADDQ    $184, SP
   290  	RET
   291  
   292  TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
   293  	MOVQ	fn+0(FP),    AX
   294  	MOVL	sig+8(FP),   DI
   295  	MOVQ	info+16(FP), SI
   296  	MOVQ	ctx+24(FP),  DX
   297  	PUSHQ	BP
   298  	MOVQ	SP, BP
   299  	ANDQ	$~15, SP     // alignment for x86_64 ABI
   300  	CALL	AX
   301  	MOVQ	BP, SP
   302  	POPQ	BP
   303  	RET
   304  
   305  // Called from runtime·usleep (Go). Can be called on Go stack, on OS stack,
   306  // can also be called in cgo callback path without a g->m.
   307  TEXT runtime·usleep1(SB),NOSPLIT,$0
   308  	MOVL	usec+0(FP), DI
   309  	MOVQ	$runtime·usleep2(SB), AX // to hide from 6l
   310  
   311  	// Execute call on m->g0.
   312  	get_tls(R15)
   313  	CMPQ	R15, $0
   314  	JE	noswitch
   315  
   316  	MOVQ	g(R15), R13
   317  	CMPQ	R13, $0
   318  	JE	noswitch
   319  	MOVQ	g_m(R13), R13
   320  	CMPQ	R13, $0
   321  	JE	noswitch
   322  	// TODO(aram): do something about the cpu profiler here.
   323  
   324  	MOVQ	m_g0(R13), R14
   325  	CMPQ	g(R15), R14
   326  	JNE	switch
   327  	// executing on m->g0 already
   328  	CALL	AX
   329  	RET
   330  
   331  switch:
   332  	// Switch to m->g0 stack and back.
   333  	MOVQ	(g_sched+gobuf_sp)(R14), R14
   334  	MOVQ	SP, -8(R14)
   335  	LEAQ	-8(R14), SP
   336  	CALL	AX
   337  	MOVQ	0(SP), SP
   338  	RET
   339  
   340  noswitch:
   341  	// Not a Go-managed thread. Do not switch stack.
   342  	CALL	AX
   343  	RET
   344  
   345  // Runs on OS stack. duration (in µs units) is in DI.
   346  TEXT runtime·usleep2(SB),NOSPLIT,$0
   347  	LEAQ	libc_usleep(SB), AX
   348  	CALL	AX
   349  	RET
   350  
   351  // Runs on OS stack, called from runtime·osyield.
   352  TEXT runtime·osyield1(SB),NOSPLIT,$0
   353  	LEAQ	libc_sched_yield(SB), AX
   354  	CALL	AX
   355  	RET
   356  
   357  // func walltime() (sec int64, nsec int32)
   358  TEXT runtime·walltime(SB),NOSPLIT,$8-12
   359  	CALL	runtime·nanotime(SB)
   360  	MOVQ	0(SP), AX
   361  
   362  	// generated code for
   363  	//	func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
   364  	// adapted to reduce duplication
   365  	MOVQ	AX, CX
   366  	MOVQ	$1360296554856532783, AX
   367  	MULQ	CX
   368  	ADDQ	CX, DX
   369  	RCRQ	$1, DX
   370  	SHRQ	$29, DX
   371  	MOVQ	DX, sec+0(FP)
   372  	IMULQ	$1000000000, DX
   373  	SUBQ	DX, CX
   374  	MOVL	CX, nsec+8(FP)
   375  	RET