Text file src/runtime/asm_loong64.s

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

View as plain text