Text file src/runtime/asm_riscv64.s

     1  // Copyright 2017 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  #include "go_asm.h"
     6  #include "funcdata.h"
     7  #include "textflag.h"
     8  
     9  
    10  // When building with -buildmode=c-shared, this symbol is called when the shared
    11  // library is loaded.
    12  TEXT _rt0_riscv64_lib(SB),NOSPLIT,$224
    13  	// Preserve callee-save registers, along with X1 (LR).
    14  	MOV	X1, (8*3)(X2)
    15  	MOV	X8, (8*4)(X2)
    16  	MOV	X9, (8*5)(X2)
    17  	MOV	X18, (8*6)(X2)
    18  	MOV	X19, (8*7)(X2)
    19  	MOV	X20, (8*8)(X2)
    20  	MOV	X21, (8*9)(X2)
    21  	MOV	X22, (8*10)(X2)
    22  	MOV	X23, (8*11)(X2)
    23  	MOV	X24, (8*12)(X2)
    24  	MOV	X25, (8*13)(X2)
    25  	MOV	X26, (8*14)(X2)
    26  	MOV	g, (8*15)(X2)
    27  	MOVD	F8, (8*16)(X2)
    28  	MOVD	F9, (8*17)(X2)
    29  	MOVD	F18, (8*18)(X2)
    30  	MOVD	F19, (8*19)(X2)
    31  	MOVD	F20, (8*20)(X2)
    32  	MOVD	F21, (8*21)(X2)
    33  	MOVD	F22, (8*22)(X2)
    34  	MOVD	F23, (8*23)(X2)
    35  	MOVD	F24, (8*24)(X2)
    36  	MOVD	F25, (8*25)(X2)
    37  	MOVD	F26, (8*26)(X2)
    38  	MOVD	F27, (8*27)(X2)
    39  
    40  	// Initialize g as nil in case of using g later e.g. sigaction in cgo_sigaction.go
    41  	MOV	X0, g
    42  
    43  	MOV	A0, _rt0_riscv64_lib_argc<>(SB)
    44  	MOV	A1, _rt0_riscv64_lib_argv<>(SB)
    45  
    46  	// Synchronous initialization.
    47  	MOV	$runtime·libpreinit(SB), T0
    48  	JALR	RA, T0
    49  
    50  	// Create a new thread to do the runtime initialization and return.
    51  	MOV	_cgo_sys_thread_create(SB), T0
    52  	BEQZ	T0, nocgo
    53  	MOV	$_rt0_riscv64_lib_go(SB), A0
    54  	MOV	$0, A1
    55  	JALR	RA, T0
    56  	JMP	restore
    57  
    58  nocgo:
    59  	MOV	$0x800000, A0                     // stacksize = 8192KB
    60  	MOV	$_rt0_riscv64_lib_go(SB), A1
    61  	MOV	A0, 8(X2)
    62  	MOV	A1, 16(X2)
    63  	MOV	$runtime·newosproc0(SB), T0
    64  	JALR	RA, T0
    65  
    66  restore:
    67  	// Restore callee-save registers, along with X1 (LR).
    68  	MOV	(8*3)(X2), X1
    69  	MOV	(8*4)(X2), X8
    70  	MOV	(8*5)(X2), X9
    71  	MOV	(8*6)(X2), X18
    72  	MOV	(8*7)(X2), X19
    73  	MOV	(8*8)(X2), X20
    74  	MOV	(8*9)(X2), X21
    75  	MOV	(8*10)(X2), X22
    76  	MOV	(8*11)(X2), X23
    77  	MOV	(8*12)(X2), X24
    78  	MOV	(8*13)(X2), X25
    79  	MOV	(8*14)(X2), X26
    80  	MOV	(8*15)(X2), g
    81  	MOVD	(8*16)(X2), F8
    82  	MOVD	(8*17)(X2), F9
    83  	MOVD	(8*18)(X2), F18
    84  	MOVD	(8*19)(X2), F19
    85  	MOVD	(8*20)(X2), F20
    86  	MOVD	(8*21)(X2), F21
    87  	MOVD	(8*22)(X2), F22
    88  	MOVD	(8*23)(X2), F23
    89  	MOVD	(8*24)(X2), F24
    90  	MOVD	(8*25)(X2), F25
    91  	MOVD	(8*26)(X2), F26
    92  	MOVD	(8*27)(X2), F27
    93  
    94  	RET
    95  
    96  TEXT _rt0_riscv64_lib_go(SB),NOSPLIT,$0
    97  	MOV	_rt0_riscv64_lib_argc<>(SB), A0
    98  	MOV	_rt0_riscv64_lib_argv<>(SB), A1
    99  	MOV	$runtime·rt0_go(SB), T0
   100  	JALR	ZERO, T0
   101  
   102  DATA _rt0_riscv64_lib_argc<>(SB)/8, $0
   103  GLOBL _rt0_riscv64_lib_argc<>(SB),NOPTR, $8
   104  DATA _rt0_riscv64_lib_argv<>(SB)/8, $0
   105  GLOBL _rt0_riscv64_lib_argv<>(SB),NOPTR, $8
   106  
   107  // func rt0_go()
   108  TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
   109  	// X2 = stack; A0 = argc; A1 = argv
   110  	SUB	$24, X2
   111  	MOV	A0, 8(X2)	// argc
   112  	MOV	A1, 16(X2)	// argv
   113  
   114  	// create istack out of the given (operating system) stack.
   115  	// _cgo_init may update stackguard.
   116  	MOV	$runtime·g0(SB), g
   117  	MOV	$(-64*1024), T0
   118  	ADD	T0, X2, T1
   119  	MOV	T1, g_stackguard0(g)
   120  	MOV	T1, g_stackguard1(g)
   121  	MOV	T1, (g_stack+stack_lo)(g)
   122  	MOV	X2, (g_stack+stack_hi)(g)
   123  
   124  	// if there is a _cgo_init, call it using the gcc ABI.
   125  	MOV	_cgo_init(SB), T0
   126  	BEQ	T0, ZERO, nocgo
   127  
   128  	MOV	ZERO, A3		// arg 3: not used
   129  	MOV	ZERO, A2		// arg 2: not used
   130  	MOV	$setg_gcc<>(SB), A1	// arg 1: setg
   131  	MOV	g, A0			// arg 0: G
   132  	JALR	RA, T0
   133  
   134  nocgo:
   135  	// update stackguard after _cgo_init
   136  	MOV	(g_stack+stack_lo)(g), T0
   137  	ADD	$const_stackGuard, T0
   138  	MOV	T0, g_stackguard0(g)
   139  	MOV	T0, g_stackguard1(g)
   140  
   141  	// set the per-goroutine and per-mach "registers"
   142  	MOV	$runtime·m0(SB), T0
   143  
   144  	// save m->g0 = g0
   145  	MOV	g, m_g0(T0)
   146  	// save m0 to g0->m
   147  	MOV	T0, g_m(g)
   148  
   149  	CALL	runtime·check(SB)
   150  
   151  	// args are already prepared
   152  	CALL	runtime·args(SB)
   153  	CALL	runtime·osinit(SB)
   154  	CALL	runtime·schedinit(SB)
   155  
   156  	// create a new goroutine to start program
   157  	MOV	$runtime·mainPC(SB), T0		// entry
   158  	SUB	$16, X2
   159  	MOV	T0, 8(X2)
   160  	MOV	ZERO, 0(X2)
   161  	CALL	runtime·newproc(SB)
   162  	ADD	$16, X2
   163  
   164  	// start this M
   165  	CALL	runtime·mstart(SB)
   166  
   167  	WORD $0 // crash if reached
   168  	RET
   169  
   170  TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
   171  	CALL	runtime·mstart0(SB)
   172  	RET // not reached
   173  
   174  // void setg_gcc(G*); set g called from gcc with g in A0
   175  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   176  	MOV	A0, g
   177  	CALL	runtime·save_g(SB)
   178  	RET
   179  
   180  // func cputicks() int64
   181  TEXT runtime·cputicks<ABIInternal>(SB),NOSPLIT,$0-0
   182  	// RDTIME to emulate cpu ticks
   183  	// RDCYCLE reads counter that is per HART(core) based
   184  	// according to the riscv manual, see issue 46737
   185  	RDTIME	X10
   186  	RET
   187  
   188  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   189  // of the G stack. We need to distinguish the routine that
   190  // lives at the bottom of the G stack from the one that lives
   191  // at the top of the system stack because the one at the top of
   192  // the system stack terminates the stack walk (see topofstack()).
   193  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   194  	UNDEF
   195  	JALR	RA, ZERO	// make sure this function is not leaf
   196  	RET
   197  
   198  // func systemstack(fn func())
   199  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   200  	MOV	fn+0(FP), CTXT	// CTXT = fn
   201  	MOV	g_m(g), T0	// T0 = m
   202  
   203  	MOV	m_gsignal(T0), T1	// T1 = gsignal
   204  	BEQ	g, T1, noswitch
   205  
   206  	MOV	m_g0(T0), T1	// T1 = g0
   207  	BEQ	g, T1, noswitch
   208  
   209  	MOV	m_curg(T0), T2
   210  	BEQ	g, T2, switch
   211  
   212  	// Bad: g is not gsignal, not g0, not curg. What is it?
   213  	// Hide call from linker nosplit analysis.
   214  	MOV	$runtime·badsystemstack(SB), T1
   215  	JALR	RA, T1
   216  
   217  switch:
   218  	// save our state in g->sched. Pretend to
   219  	// be systemstack_switch if the G stack is scanned.
   220  	CALL	gosave_systemstack_switch<>(SB)
   221  
   222  	// switch to g0
   223  	MOV	T1, g
   224  	CALL	runtime·save_g(SB)
   225  	MOV	(g_sched+gobuf_sp)(g), T0
   226  	MOV	T0, X2
   227  
   228  	// call target function
   229  	MOV	0(CTXT), T1	// code pointer
   230  	JALR	RA, T1
   231  
   232  	// switch back to g
   233  	MOV	g_m(g), T0
   234  	MOV	m_curg(T0), g
   235  	CALL	runtime·save_g(SB)
   236  	MOV	(g_sched+gobuf_sp)(g), X2
   237  	MOV	ZERO, (g_sched+gobuf_sp)(g)
   238  	RET
   239  
   240  noswitch:
   241  	// already on m stack, just call directly
   242  	// Using a tail call here cleans up tracebacks since we won't stop
   243  	// at an intermediate systemstack.
   244  	MOV	0(CTXT), T1	// code pointer
   245  	ADD	$8, X2
   246  	JMP	(T1)
   247  
   248  // func switchToCrashStack0(fn func())
   249  TEXT runtime·switchToCrashStack0<ABIInternal>(SB), NOSPLIT, $0-8
   250  	MOV	X10, CTXT			// context register
   251  	MOV	g_m(g), X11			// curm
   252  
   253  	// set g to gcrash
   254  	MOV	$runtime·gcrash(SB), g	// g = &gcrash
   255  	CALL	runtime·save_g(SB)	// clobbers X31
   256  	MOV	X11, g_m(g)			// g.m = curm
   257  	MOV	g, m_g0(X11)			// curm.g0 = g
   258  
   259  	// switch to crashstack
   260  	MOV	(g_stack+stack_hi)(g), X11
   261  	SUB	$(4*8), X11
   262  	MOV	X11, X2
   263  
   264  	// call target function
   265  	MOV	0(CTXT), X10
   266  	JALR	X1, X10
   267  
   268  	// should never return
   269  	CALL	runtime·abort(SB)
   270  	UNDEF
   271  
   272  /*
   273   * support for morestack
   274   */
   275  
   276  // Called during function prolog when more stack is needed.
   277  // Called with return address (i.e. caller's PC) in X5 (aka T0),
   278  // and the LR register contains the caller's LR.
   279  //
   280  // The traceback routines see morestack on a g0 as being
   281  // the top of a stack (for example, morestack calling newstack
   282  // calling the scheduler calling newm calling gc), so we must
   283  // record an argument size. For that purpose, it has no arguments.
   284  
   285  // func morestack()
   286  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   287  	// Called from f.
   288  	// Set g->sched to context in f.
   289  	MOV	X2, (g_sched+gobuf_sp)(g)
   290  	MOV	T0, (g_sched+gobuf_pc)(g)
   291  	MOV	RA, (g_sched+gobuf_lr)(g)
   292  	MOV	CTXT, (g_sched+gobuf_ctxt)(g)
   293  
   294  	// Cannot grow scheduler stack (m->g0).
   295  	MOV	g_m(g), A0
   296  	MOV	m_g0(A0), A1
   297  	BNE	g, A1, 3(PC)
   298  	CALL	runtime·badmorestackg0(SB)
   299  	CALL	runtime·abort(SB)
   300  
   301  	// Cannot grow signal stack (m->gsignal).
   302  	MOV	m_gsignal(A0), A1
   303  	BNE	g, A1, 3(PC)
   304  	CALL	runtime·badmorestackgsignal(SB)
   305  	CALL	runtime·abort(SB)
   306  
   307  	// Called from f.
   308  	// Set m->morebuf to f's caller.
   309  	MOV	RA, (m_morebuf+gobuf_pc)(A0)	// f's caller's PC
   310  	MOV	X2, (m_morebuf+gobuf_sp)(A0)	// f's caller's SP
   311  	MOV	g, (m_morebuf+gobuf_g)(A0)
   312  
   313  	// Call newstack on m->g0's stack.
   314  	MOV	m_g0(A0), g
   315  	CALL	runtime·save_g(SB)
   316  	MOV	(g_sched+gobuf_sp)(g), X2
   317  	// Create a stack frame on g0 to call newstack.
   318  	MOV	ZERO, -8(X2)	// Zero saved LR in frame
   319  	SUB	$8, X2
   320  	CALL	runtime·newstack(SB)
   321  
   322  	// Not reached, but make sure the return PC from the call to newstack
   323  	// is still in this function, and not the beginning of the next.
   324  	UNDEF
   325  
   326  // func morestack_noctxt()
   327  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   328  	// Force SPWRITE. This function doesn't actually write SP,
   329  	// but it is called with a special calling convention where
   330  	// the caller doesn't save LR on stack but passes it as a
   331  	// register, and the unwinder currently doesn't understand.
   332  	// Make it SPWRITE to stop unwinding. (See issue 54332)
   333  	MOV	X2, X2
   334  
   335  	MOV	ZERO, CTXT
   336  	JMP	runtime·morestack(SB)
   337  
   338  // AES hashing not implemented for riscv64
   339  TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
   340  	JMP	runtime·memhashFallback<ABIInternal>(SB)
   341  TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   342  	JMP	runtime·strhashFallback<ABIInternal>(SB)
   343  TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   344  	JMP	runtime·memhash32Fallback<ABIInternal>(SB)
   345  TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   346  	JMP	runtime·memhash64Fallback<ABIInternal>(SB)
   347  
   348  // restore state from Gobuf; longjmp
   349  
   350  // func gogo(buf *gobuf)
   351  TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   352  	MOV	buf+0(FP), T0
   353  	MOV	gobuf_g(T0), T1
   354  	MOV	0(T1), ZERO // make sure g != nil
   355  	JMP	gogo<>(SB)
   356  
   357  TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
   358  	MOV	T1, g
   359  	CALL	runtime·save_g(SB)
   360  
   361  	MOV	gobuf_sp(T0), X2
   362  	MOV	gobuf_lr(T0), RA
   363  	MOV	gobuf_ctxt(T0), CTXT
   364  	MOV	ZERO, gobuf_sp(T0)
   365  	MOV	ZERO, gobuf_lr(T0)
   366  	MOV	ZERO, gobuf_ctxt(T0)
   367  	MOV	gobuf_pc(T0), T0
   368  	JALR	ZERO, T0
   369  
   370  // func procyieldAsm(cycles uint32)
   371  TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
   372  	RET
   373  
   374  // Switch to m->g0's stack, call fn(g).
   375  // Fn must never return. It should gogo(&g->sched)
   376  // to keep running g.
   377  
   378  // func mcall(fn func(*g))
   379  TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8
   380  	MOV	X10, CTXT
   381  
   382  	// Save caller state in g->sched
   383  	MOV	X2, (g_sched+gobuf_sp)(g)
   384  	MOV	RA, (g_sched+gobuf_pc)(g)
   385  	MOV	ZERO, (g_sched+gobuf_lr)(g)
   386  
   387  	// Switch to m->g0 & its stack, call fn.
   388  	MOV	g, X10
   389  	MOV	g_m(g), T1
   390  	MOV	m_g0(T1), g
   391  	CALL	runtime·save_g(SB)
   392  	BNE	g, X10, 2(PC)
   393  	JMP	runtime·badmcall(SB)
   394  	MOV	0(CTXT), T1			// code pointer
   395  	MOV	(g_sched+gobuf_sp)(g), X2	// sp = m->g0->sched.sp
   396  	// we don't need special macro for regabi since arg0(X10) = g
   397  	SUB	$16, X2
   398  	MOV	X10, 8(X2)			// setup g
   399  	MOV	ZERO, 0(X2)			// clear return address
   400  	JALR	RA, T1
   401  	JMP	runtime·badmcall2(SB)
   402  
   403  // Save state of caller into g->sched,
   404  // but using fake PC from systemstack_switch.
   405  // Must only be called from functions with no locals ($0)
   406  // or else unwinding from systemstack_switch is incorrect.
   407  // Smashes X31.
   408  TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
   409  	MOV	$runtime·systemstack_switch(SB), X31
   410  	ADD	$8, X31	// get past prologue
   411  	MOV	X31, (g_sched+gobuf_pc)(g)
   412  	MOV	X2, (g_sched+gobuf_sp)(g)
   413  	MOV	ZERO, (g_sched+gobuf_lr)(g)
   414  	// Assert ctxt is zero. See func save.
   415  	MOV	(g_sched+gobuf_ctxt)(g), X31
   416  	BEQ	ZERO, X31, 2(PC)
   417  	CALL	runtime·abort(SB)
   418  	RET
   419  
   420  // func asmcgocall_no_g(fn, arg unsafe.Pointer)
   421  // Call fn(arg) aligned appropriately for the gcc ABI.
   422  // Called on a system stack, and there may be no g yet (during needm).
   423  TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
   424  	MOV	fn+0(FP), X5
   425  	MOV	arg+8(FP), X10
   426  	JALR	RA, (X5)
   427  	RET
   428  
   429  // func asmcgocall(fn, arg unsafe.Pointer) int32
   430  // Call fn(arg) on the scheduler stack,
   431  // aligned appropriately for the gcc ABI.
   432  // See cgocall.go for more details.
   433  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   434  	MOV	fn+0(FP), X5
   435  	MOV	arg+8(FP), X10
   436  
   437  	MOV	X2, X8	// save original stack pointer
   438  	MOV	g, X9
   439  
   440  	// Figure out if we need to switch to m->g0 stack.
   441  	// We get called to create new OS threads too, and those
   442  	// come in on the m->g0 stack already. Or we might already
   443  	// be on the m->gsignal stack.
   444  	MOV	g_m(g), X6
   445  	MOV	m_gsignal(X6), X7
   446  	BEQ	X7, g, g0
   447  	MOV	m_g0(X6), X7
   448  	BEQ	X7, g, g0
   449  
   450  	CALL	gosave_systemstack_switch<>(SB)
   451  	MOV	X7, g
   452  	CALL	runtime·save_g(SB)
   453  	MOV	(g_sched+gobuf_sp)(g), X2
   454  
   455  	// Now on a scheduling stack (a pthread-created stack).
   456  g0:
   457  	// Save room for two of our pointers.
   458  	SUB	$16, X2
   459  	MOV	X9, 0(X2)	// save old g on stack
   460  	MOV	(g_stack+stack_hi)(X9), X9
   461  	SUB	X8, X9, X8
   462  	MOV	X8, 8(X2)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   463  
   464  	JALR	RA, (X5)
   465  
   466  	// Restore g, stack pointer. X10 is return value.
   467  	MOV	0(X2), g
   468  	CALL	runtime·save_g(SB)
   469  	MOV	(g_stack+stack_hi)(g), X5
   470  	MOV	8(X2), X6
   471  	SUB	X6, X5, X6
   472  	MOV	X6, X2
   473  
   474  	MOVW	X10, ret+16(FP)
   475  	RET
   476  
   477  // func asminit()
   478  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
   479  	RET
   480  
   481  // reflectcall: call a function with the given argument list
   482  // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   483  // we don't have variable-sized frames, so we use a small number
   484  // of constant-sized-frame functions to encode a few bits of size in the pc.
   485  // Caution: ugly multiline assembly macros in your future!
   486  
   487  #define DISPATCH(NAME,MAXSIZE)	\
   488  	MOV	$MAXSIZE, T1	\
   489  	BLTU	T1, T0, 3(PC)	\
   490  	MOV	$NAME(SB), T2;	\
   491  	JALR	ZERO, T2
   492  // Note: can't just "BR NAME(SB)" - bad inlining results.
   493  
   494  // func call(stackArgsType *rtype, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   495  TEXT reflect·call(SB), NOSPLIT, $0-0
   496  	JMP	·reflectcall(SB)
   497  
   498  // func call(stackArgsType *_type, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   499  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
   500  	MOVWU	frameSize+32(FP), T0
   501  	DISPATCH(runtime·call16, 16)
   502  	DISPATCH(runtime·call32, 32)
   503  	DISPATCH(runtime·call64, 64)
   504  	DISPATCH(runtime·call128, 128)
   505  	DISPATCH(runtime·call256, 256)
   506  	DISPATCH(runtime·call512, 512)
   507  	DISPATCH(runtime·call1024, 1024)
   508  	DISPATCH(runtime·call2048, 2048)
   509  	DISPATCH(runtime·call4096, 4096)
   510  	DISPATCH(runtime·call8192, 8192)
   511  	DISPATCH(runtime·call16384, 16384)
   512  	DISPATCH(runtime·call32768, 32768)
   513  	DISPATCH(runtime·call65536, 65536)
   514  	DISPATCH(runtime·call131072, 131072)
   515  	DISPATCH(runtime·call262144, 262144)
   516  	DISPATCH(runtime·call524288, 524288)
   517  	DISPATCH(runtime·call1048576, 1048576)
   518  	DISPATCH(runtime·call2097152, 2097152)
   519  	DISPATCH(runtime·call4194304, 4194304)
   520  	DISPATCH(runtime·call8388608, 8388608)
   521  	DISPATCH(runtime·call16777216, 16777216)
   522  	DISPATCH(runtime·call33554432, 33554432)
   523  	DISPATCH(runtime·call67108864, 67108864)
   524  	DISPATCH(runtime·call134217728, 134217728)
   525  	DISPATCH(runtime·call268435456, 268435456)
   526  	DISPATCH(runtime·call536870912, 536870912)
   527  	DISPATCH(runtime·call1073741824, 1073741824)
   528  	MOV	$runtime·badreflectcall(SB), T2
   529  	JALR	ZERO, T2
   530  
   531  #define CALLFN(NAME,MAXSIZE)			\
   532  TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   533  	NO_LOCAL_POINTERS;			\
   534  	/* copy arguments to stack */		\
   535  	MOV	stackArgs+16(FP), A1;			\
   536  	MOVWU	stackArgsSize+24(FP), A2;		\
   537  	MOV	X2, A3;				\
   538  	ADD	$8, A3;				\
   539  	ADD	A3, A2;				\
   540  	BEQ	A3, A2, 6(PC);			\
   541  	MOVBU	(A1), A4;			\
   542  	ADD	$1, A1;				\
   543  	MOVB	A4, (A3);			\
   544  	ADD	$1, A3;				\
   545  	JMP	-5(PC);				\
   546  	/* set up argument registers */		\
   547  	MOV	regArgs+40(FP), X25;		\
   548  	CALL	·unspillArgs(SB);		\
   549  	/* call function */			\
   550  	MOV	f+8(FP), CTXT;			\
   551  	MOV	(CTXT), X25;			\
   552  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   553  	JALR	RA, X25;				\
   554  	/* copy return values back */		\
   555  	MOV	regArgs+40(FP), X25;		\
   556  	CALL	·spillArgs(SB);		\
   557  	MOV	stackArgsType+0(FP), A5;		\
   558  	MOV	stackArgs+16(FP), A1;			\
   559  	MOVWU	stackArgsSize+24(FP), A2;			\
   560  	MOVWU	stackRetOffset+28(FP), A4;		\
   561  	ADD	$8, X2, A3;			\
   562  	ADD	A4, A3; 			\
   563  	ADD	A4, A1;				\
   564  	SUB	A4, A2;				\
   565  	CALL	callRet<>(SB);			\
   566  	RET
   567  
   568  // callRet copies return values back at the end of call*. This is a
   569  // separate function so it can allocate stack space for the arguments
   570  // to reflectcallmove. It does not follow the Go ABI; it expects its
   571  // arguments in registers.
   572  TEXT callRet<>(SB), NOSPLIT, $40-0
   573  	NO_LOCAL_POINTERS
   574  	MOV	A5, 8(X2)
   575  	MOV	A1, 16(X2)
   576  	MOV	A3, 24(X2)
   577  	MOV	A2, 32(X2)
   578  	MOV	X25, 40(X2)
   579  	CALL	runtime·reflectcallmove(SB)
   580  	RET
   581  
   582  CALLFN(·call16, 16)
   583  CALLFN(·call32, 32)
   584  CALLFN(·call64, 64)
   585  CALLFN(·call128, 128)
   586  CALLFN(·call256, 256)
   587  CALLFN(·call512, 512)
   588  CALLFN(·call1024, 1024)
   589  CALLFN(·call2048, 2048)
   590  CALLFN(·call4096, 4096)
   591  CALLFN(·call8192, 8192)
   592  CALLFN(·call16384, 16384)
   593  CALLFN(·call32768, 32768)
   594  CALLFN(·call65536, 65536)
   595  CALLFN(·call131072, 131072)
   596  CALLFN(·call262144, 262144)
   597  CALLFN(·call524288, 524288)
   598  CALLFN(·call1048576, 1048576)
   599  CALLFN(·call2097152, 2097152)
   600  CALLFN(·call4194304, 4194304)
   601  CALLFN(·call8388608, 8388608)
   602  CALLFN(·call16777216, 16777216)
   603  CALLFN(·call33554432, 33554432)
   604  CALLFN(·call67108864, 67108864)
   605  CALLFN(·call134217728, 134217728)
   606  CALLFN(·call268435456, 268435456)
   607  CALLFN(·call536870912, 536870912)
   608  CALLFN(·call1073741824, 1073741824)
   609  
   610  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   611  // Must obey the gcc calling convention.
   612  TEXT _cgo_topofstack(SB),NOSPLIT,$8
   613  	// g (X27) and REG_TMP (X31) might be clobbered by load_g.
   614  	// X27 is callee-save in the gcc calling convention, so save it.
   615  	MOV	g, savedX27-8(SP)
   616  
   617  	CALL	runtime·load_g(SB)
   618  	MOV	g_m(g), X5
   619  	MOV	m_curg(X5), X5
   620  	MOV	(g_stack+stack_hi)(X5), X10 // return value in X10
   621  
   622  	MOV	savedX27-8(SP), g
   623  	RET
   624  
   625  // func goexit(neverCallThisFunction)
   626  // The top-most function running on a goroutine
   627  // returns to goexit+PCQuantum.
   628  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   629  	MOV	ZERO, ZERO	// NOP
   630  	JMP	runtime·goexit1(SB)	// does not return
   631  	// traceback from goexit1 must hit code range of goexit
   632  	MOV	ZERO, ZERO	// NOP
   633  
   634  
   635  // This is called from .init_array and follows the platform, not the Go ABI.
   636  TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
   637  	// Use X31 as it is a scratch register in both the Go ABI and psABI.
   638  	MOV	runtime·lastmoduledatap(SB), X31
   639  	MOV	X10, moduledata_next(X31)
   640  	MOV	X10, runtime·lastmoduledatap(SB)
   641  	RET
   642  
   643  // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   644  // See cgocall.go for more details.
   645  TEXT ·cgocallback(SB),NOSPLIT,$24-24
   646  	NO_LOCAL_POINTERS
   647  
   648  	// Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
   649  	// It is used to dropm while thread is exiting.
   650  	MOV	fn+0(FP), X7
   651  	BNE	ZERO, X7, loadg
   652  	// Restore the g from frame.
   653  	MOV	frame+8(FP), g
   654  	JMP	dropm
   655  
   656  loadg:
   657  	// Load m and g from thread-local storage.
   658  	MOVBU	runtime·iscgo(SB), X5
   659  	BEQ	ZERO, X5, nocgo
   660  	CALL	runtime·load_g(SB)
   661  nocgo:
   662  
   663  	// If g is nil, Go did not create the current thread,
   664  	// or if this thread never called into Go on pthread platforms.
   665  	// Call needm to obtain one for temporary use.
   666  	// In this case, we're running on the thread stack, so there's
   667  	// lots of space, but the linker doesn't know. Hide the call from
   668  	// the linker analysis by using an indirect call.
   669  	BEQ	ZERO, g, needm
   670  
   671  	MOV	g_m(g), X5
   672  	MOV	X5, savedm-8(SP)
   673  	JMP	havem
   674  
   675  needm:
   676  	MOV	g, savedm-8(SP) // g is zero, so is m.
   677  	MOV	$runtime·needAndBindM(SB), X6
   678  	JALR	RA, X6
   679  
   680  	// Set m->sched.sp = SP, so that if a panic happens
   681  	// during the function we are about to execute, it will
   682  	// have a valid SP to run on the g0 stack.
   683  	// The next few lines (after the havem label)
   684  	// will save this SP onto the stack and then write
   685  	// the same SP back to m->sched.sp. That seems redundant,
   686  	// but if an unrecovered panic happens, unwindm will
   687  	// restore the g->sched.sp from the stack location
   688  	// and then systemstack will try to use it. If we don't set it here,
   689  	// that restored SP will be uninitialized (typically 0) and
   690  	// will not be usable.
   691  	MOV	g_m(g), X5
   692  	MOV	m_g0(X5), X6
   693  	MOV	X2, (g_sched+gobuf_sp)(X6)
   694  
   695  havem:
   696  	// Now there's a valid m, and we're running on its m->g0.
   697  	// Save current m->g0->sched.sp on stack and then set it to SP.
   698  	// Save current sp in m->g0->sched.sp in preparation for
   699  	// switch back to m->curg stack.
   700  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(X2) aka savedsp-24(SP).
   701  	MOV	m_g0(X5), X6
   702  	MOV	(g_sched+gobuf_sp)(X6), X7
   703  	MOV	X7, savedsp-24(SP)	// must match frame size
   704  	MOV	X2, (g_sched+gobuf_sp)(X6)
   705  
   706  	// Switch to m->curg stack and call runtime.cgocallbackg.
   707  	// Because we are taking over the execution of m->curg
   708  	// but *not* resuming what had been running, we need to
   709  	// save that information (m->curg->sched) so we can restore it.
   710  	// We can restore m->curg->sched.sp easily, because calling
   711  	// runtime.cgocallbackg leaves SP unchanged upon return.
   712  	// To save m->curg->sched.pc, we push it onto the curg stack and
   713  	// open a frame the same size as cgocallback's g0 frame.
   714  	// Once we switch to the curg stack, the pushed PC will appear
   715  	// to be the return PC of cgocallback, so that the traceback
   716  	// will seamlessly trace back into the earlier calls.
   717  	MOV	m_curg(X5), g
   718  	CALL	runtime·save_g(SB)
   719  	MOV	(g_sched+gobuf_sp)(g), X6 // prepare stack as X6
   720  	MOV	(g_sched+gobuf_pc)(g), X7
   721  	MOV	X7, -(24+8)(X6)		// "saved LR"; must match frame size
   722  	// Gather our arguments into registers.
   723  	MOV	fn+0(FP), X7
   724  	MOV	frame+8(FP), X8
   725  	MOV	ctxt+16(FP), X9
   726  	MOV	$-(24+8)(X6), X2	// switch stack; must match frame size
   727  	MOV	X7, 8(X2)
   728  	MOV	X8, 16(X2)
   729  	MOV	X9, 24(X2)
   730  	CALL	runtime·cgocallbackg(SB)
   731  
   732  	// Restore g->sched (== m->curg->sched) from saved values.
   733  	MOV	0(X2), X7
   734  	MOV	X7, (g_sched+gobuf_pc)(g)
   735  	MOV	$(24+8)(X2), X6		// must match frame size
   736  	MOV	X6, (g_sched+gobuf_sp)(g)
   737  
   738  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   739  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   740  	// so we do not have to restore it.)
   741  	MOV	g_m(g), X5
   742  	MOV	m_g0(X5), g
   743  	CALL	runtime·save_g(SB)
   744  	MOV	(g_sched+gobuf_sp)(g), X2
   745  	MOV	savedsp-24(SP), X6	// must match frame size
   746  	MOV	X6, (g_sched+gobuf_sp)(g)
   747  
   748  	// If the m on entry was nil, we called needm above to borrow an m,
   749  	// 1. for the duration of the call on non-pthread platforms,
   750  	// 2. or the duration of the C thread alive on pthread platforms.
   751  	// If the m on entry wasn't nil,
   752  	// 1. the thread might be a Go thread,
   753  	// 2. or it wasn't the first call from a C thread on pthread platforms,
   754  	//    since then we skip dropm to reuse the m in the first call.
   755  	MOV	savedm-8(SP), X5
   756  	BNE	ZERO, X5, droppedm
   757  
   758  	// Skip dropm to reuse it in the next call, when a pthread key has been created.
   759  	MOV	_cgo_pthread_key_created(SB), X5
   760  	// It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
   761  	BEQ	ZERO, X5, dropm
   762  	MOV	(X5), X5
   763  	BNE	ZERO, X5, droppedm
   764  
   765  dropm:
   766  	MOV	$runtime·dropm(SB), X6
   767  	JALR	RA, X6
   768  droppedm:
   769  
   770  	// Done!
   771  	RET
   772  
   773  TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
   774  	EBREAK
   775  	RET
   776  
   777  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   778  	EBREAK
   779  	RET
   780  
   781  // void setg(G*); set g. for use by needm.
   782  TEXT runtime·setg(SB), NOSPLIT, $0-8
   783  	MOV	gg+0(FP), g
   784  	// This only happens if iscgo, so jump straight to save_g
   785  	CALL	runtime·save_g(SB)
   786  	RET
   787  
   788  TEXT ·checkASM(SB),NOSPLIT,$0-1
   789  	MOV	$1, T0
   790  	MOV	T0, ret+0(FP)
   791  	RET
   792  
   793  // spillArgs stores return values from registers to a *internal/abi.RegArgs in X25.
   794  TEXT ·spillArgs(SB),NOSPLIT,$0-0
   795  	MOV	X10, (0*8)(X25)
   796  	MOV	X11, (1*8)(X25)
   797  	MOV	X12, (2*8)(X25)
   798  	MOV	X13, (3*8)(X25)
   799  	MOV	X14, (4*8)(X25)
   800  	MOV	X15, (5*8)(X25)
   801  	MOV	X16, (6*8)(X25)
   802  	MOV	X17, (7*8)(X25)
   803  	MOV	X8,  (8*8)(X25)
   804  	MOV	X9,  (9*8)(X25)
   805  	MOV	X18, (10*8)(X25)
   806  	MOV	X19, (11*8)(X25)
   807  	MOV	X20, (12*8)(X25)
   808  	MOV	X21, (13*8)(X25)
   809  	MOV	X22, (14*8)(X25)
   810  	MOV	X23, (15*8)(X25)
   811  	MOVD	F10, (16*8)(X25)
   812  	MOVD	F11, (17*8)(X25)
   813  	MOVD	F12, (18*8)(X25)
   814  	MOVD	F13, (19*8)(X25)
   815  	MOVD	F14, (20*8)(X25)
   816  	MOVD	F15, (21*8)(X25)
   817  	MOVD	F16, (22*8)(X25)
   818  	MOVD	F17, (23*8)(X25)
   819  	MOVD	F8,  (24*8)(X25)
   820  	MOVD	F9,  (25*8)(X25)
   821  	MOVD	F18, (26*8)(X25)
   822  	MOVD	F19, (27*8)(X25)
   823  	MOVD	F20, (28*8)(X25)
   824  	MOVD	F21, (29*8)(X25)
   825  	MOVD	F22, (30*8)(X25)
   826  	MOVD	F23, (31*8)(X25)
   827  	RET
   828  
   829  // unspillArgs loads args into registers from a *internal/abi.RegArgs in X25.
   830  TEXT ·unspillArgs(SB),NOSPLIT,$0-0
   831  	MOV	(0*8)(X25), X10
   832  	MOV	(1*8)(X25), X11
   833  	MOV	(2*8)(X25), X12
   834  	MOV	(3*8)(X25), X13
   835  	MOV	(4*8)(X25), X14
   836  	MOV	(5*8)(X25), X15
   837  	MOV	(6*8)(X25), X16
   838  	MOV	(7*8)(X25), X17
   839  	MOV	(8*8)(X25), X8
   840  	MOV	(9*8)(X25), X9
   841  	MOV	(10*8)(X25), X18
   842  	MOV	(11*8)(X25), X19
   843  	MOV	(12*8)(X25), X20
   844  	MOV	(13*8)(X25), X21
   845  	MOV	(14*8)(X25), X22
   846  	MOV	(15*8)(X25), X23
   847  	MOVD	(16*8)(X25), F10
   848  	MOVD	(17*8)(X25), F11
   849  	MOVD	(18*8)(X25), F12
   850  	MOVD	(19*8)(X25), F13
   851  	MOVD	(20*8)(X25), F14
   852  	MOVD	(21*8)(X25), F15
   853  	MOVD	(22*8)(X25), F16
   854  	MOVD	(23*8)(X25), F17
   855  	MOVD	(24*8)(X25), F8
   856  	MOVD	(25*8)(X25), F9
   857  	MOVD	(26*8)(X25), F18
   858  	MOVD	(27*8)(X25), F19
   859  	MOVD	(28*8)(X25), F20
   860  	MOVD	(29*8)(X25), F21
   861  	MOVD	(30*8)(X25), F22
   862  	MOVD	(31*8)(X25), F23
   863  	RET
   864  
   865  // gcWriteBarrier informs the GC about heap pointer writes.
   866  //
   867  // gcWriteBarrier does NOT follow the Go ABI. It accepts the
   868  // number of bytes of buffer needed in X24, and returns a pointer
   869  // to the buffer space in X24.
   870  // It clobbers X31 aka T6 (the linker temp register - REG_TMP).
   871  // The act of CALLing gcWriteBarrier will clobber RA (LR).
   872  // It does not clobber any other general-purpose registers,
   873  // but may clobber others (e.g., floating point registers).
   874  TEXT gcWriteBarrier<>(SB),NOSPLIT,$208
   875  	// Save the registers clobbered by the fast path.
   876  	MOV	A0, 24*8(X2)
   877  	MOV	A1, 25*8(X2)
   878  retry:
   879  	MOV	g_m(g), A0
   880  	MOV	m_p(A0), A0
   881  	MOV	(p_wbBuf+wbBuf_next)(A0), A1
   882  	MOV	(p_wbBuf+wbBuf_end)(A0), T6 // T6 is linker temp register (REG_TMP)
   883  	// Increment wbBuf.next position.
   884  	ADD	X24, A1
   885  	// Is the buffer full?
   886  	BLTU	T6, A1, flush
   887  	// Commit to the larger buffer.
   888  	MOV	A1, (p_wbBuf+wbBuf_next)(A0)
   889  	// Make the return value (the original next position)
   890  	SUB	X24, A1, X24
   891  	// Restore registers.
   892  	MOV	24*8(X2), A0
   893  	MOV	25*8(X2), A1
   894  	RET
   895  
   896  flush:
   897  	// Save all general purpose registers since these could be
   898  	// clobbered by wbBufFlush and were not saved by the caller.
   899  	MOV	T0, 1*8(X2)
   900  	MOV	T1, 2*8(X2)
   901  	// X0 is zero register
   902  	// X1 is LR, saved by prologue
   903  	// X2 is SP
   904  	// X3 is GP
   905  	// X4 is TP
   906  	MOV	X7, 3*8(X2)
   907  	MOV	X8, 4*8(X2)
   908  	MOV	X9, 5*8(X2)
   909  	// X10 already saved (A0)
   910  	// X11 already saved (A1)
   911  	MOV	X12, 6*8(X2)
   912  	MOV	X13, 7*8(X2)
   913  	MOV	X14, 8*8(X2)
   914  	MOV	X15, 9*8(X2)
   915  	MOV	X16, 10*8(X2)
   916  	MOV	X17, 11*8(X2)
   917  	MOV	X18, 12*8(X2)
   918  	MOV	X19, 13*8(X2)
   919  	MOV	X20, 14*8(X2)
   920  	MOV	X21, 15*8(X2)
   921  	MOV	X22, 16*8(X2)
   922  	MOV	X23, 17*8(X2)
   923  	MOV	X24, 18*8(X2)
   924  	MOV	X25, 19*8(X2)
   925  	MOV	X26, 20*8(X2)
   926  	// X27 is g.
   927  	MOV	X28, 21*8(X2)
   928  	MOV	X29, 22*8(X2)
   929  	MOV	X30, 23*8(X2)
   930  	// X31 is tmp register.
   931  
   932  	CALL	runtime·wbBufFlush(SB)
   933  
   934  	MOV	1*8(X2), T0
   935  	MOV	2*8(X2), T1
   936  	MOV	3*8(X2), X7
   937  	MOV	4*8(X2), X8
   938  	MOV	5*8(X2), X9
   939  	MOV	6*8(X2), X12
   940  	MOV	7*8(X2), X13
   941  	MOV	8*8(X2), X14
   942  	MOV	9*8(X2), X15
   943  	MOV	10*8(X2), X16
   944  	MOV	11*8(X2), X17
   945  	MOV	12*8(X2), X18
   946  	MOV	13*8(X2), X19
   947  	MOV	14*8(X2), X20
   948  	MOV	15*8(X2), X21
   949  	MOV	16*8(X2), X22
   950  	MOV	17*8(X2), X23
   951  	MOV	18*8(X2), X24
   952  	MOV	19*8(X2), X25
   953  	MOV	20*8(X2), X26
   954  	MOV	21*8(X2), X28
   955  	MOV	22*8(X2), X29
   956  	MOV	23*8(X2), X30
   957  
   958  	JMP	retry
   959  
   960  TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
   961  	MOV	$8, X24
   962  	JMP	gcWriteBarrier<>(SB)
   963  TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
   964  	MOV	$16, X24
   965  	JMP	gcWriteBarrier<>(SB)
   966  TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
   967  	MOV	$24, X24
   968  	JMP	gcWriteBarrier<>(SB)
   969  TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
   970  	MOV	$32, X24
   971  	JMP	gcWriteBarrier<>(SB)
   972  TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
   973  	MOV	$40, X24
   974  	JMP	gcWriteBarrier<>(SB)
   975  TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
   976  	MOV	$48, X24
   977  	JMP	gcWriteBarrier<>(SB)
   978  TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
   979  	MOV	$56, X24
   980  	JMP	gcWriteBarrier<>(SB)
   981  TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
   982  	MOV	$64, X24
   983  	JMP	gcWriteBarrier<>(SB)
   984  
   985  TEXT runtime·panicBounds<ABIInternal>(SB),NOSPLIT,$144-0
   986  	NO_LOCAL_POINTERS
   987  	// Save all 16 int registers that could have an index in them.
   988  	// They may be pointers, but if they are they are dead.
   989  	// Skip X0 aka ZERO, X1 aka LR, X2 aka SP, X3 aka GP, X4 aka TP.
   990  	MOV	X5, 24(X2)
   991  	MOV	X6, 32(X2)
   992  	MOV	X7, 40(X2)
   993  	MOV	X8, 48(X2)
   994  	MOV	X9, 56(X2)
   995  	MOV	X10, 64(X2)
   996  	MOV	X11, 72(X2)
   997  	MOV	X12, 80(X2)
   998  	MOV	X13, 88(X2)
   999  	MOV	X14, 96(X2)
  1000  	MOV	X15, 104(X2)
  1001  	MOV	X16, 112(X2)
  1002  	MOV	X17, 120(X2)
  1003  	MOV	X18, 128(X2)
  1004  	MOV	X19, 136(X2)
  1005  	MOV	X20, 144(X2)
  1006  
  1007  	MOV	X1, X10		// PC immediately after call to panicBounds
  1008  	ADD	$24, X2, X11	// pointer to save area
  1009  	CALL	runtime·panicBounds64<ABIInternal>(SB)
  1010  	RET
  1011  
  1012  DATA	runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB)
  1013  GLOBL	runtime·mainPC(SB),RODATA,$8
  1014  

View as plain text