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

View as plain text