github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/asm_loong64.s (about)

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