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

View as plain text