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

View as plain text