github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/runtime/asm_riscv64.s (about)

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