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