...

Text file src/runtime/asm_loong64.s

Documentation: runtime

     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#include "cgo/abi_loong64.h"
    10
    11// When building with -buildmode=c-shared, this symbol is called when the shared
    12// library is loaded.
    13TEXT _rt0_loong64_lib(SB),NOSPLIT,$168
    14	// Preserve callee-save registers.
    15	SAVE_R22_TO_R31(3*8)
    16	SAVE_F24_TO_F31(13*8)
    17
    18	// Initialize g as nil in case of using g later e.g. sigaction in cgo_sigaction.go
    19	MOVV	R0, g
    20
    21	MOVV	R4, _rt0_loong64_lib_argc<>(SB)
    22	MOVV	R5, _rt0_loong64_lib_argv<>(SB)
    23
    24	// Synchronous initialization.
    25	MOVV	$runtime·libpreinit(SB), R19
    26	JAL	(R19)
    27
    28	// Create a new thread to do the runtime initialization and return.
    29	MOVV	_cgo_sys_thread_create(SB), R19
    30	BEQ	R19, nocgo
    31	MOVV	$_rt0_loong64_lib_go(SB), R4
    32	MOVV	$0, R5
    33	JAL	(R19)
    34	JMP	restore
    35
    36nocgo:
    37	MOVV	$0x800000, R4                     // stacksize = 8192KB
    38	MOVV	$_rt0_loong64_lib_go(SB), R5
    39	MOVV	R4, 8(R3)
    40	MOVV	R5, 16(R3)
    41	MOVV	$runtime·newosproc0(SB), R19
    42	JAL	(R19)
    43
    44restore:
    45	// Restore callee-save registers.
    46	RESTORE_R22_TO_R31(3*8)
    47	RESTORE_F24_TO_F31(13*8)
    48	RET
    49
    50TEXT _rt0_loong64_lib_go(SB),NOSPLIT,$0
    51	MOVV	_rt0_loong64_lib_argc<>(SB), R4
    52	MOVV	_rt0_loong64_lib_argv<>(SB), R5
    53	MOVV	$runtime·rt0_go(SB),R19
    54	JMP	(R19)
    55
    56DATA _rt0_loong64_lib_argc<>(SB)/8, $0
    57GLOBL _rt0_loong64_lib_argc<>(SB),NOPTR, $8
    58DATA _rt0_loong64_lib_argv<>(SB)/8, $0
    59GLOBL _rt0_loong64_lib_argv<>(SB),NOPTR, $8
    60
    61#define	REGCTXT	R29
    62
    63TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
    64	// R3 = stack; R4 = argc; R5 = argv
    65
    66	ADDV	$-24, R3
    67	MOVW	R4, 8(R3) // argc
    68	MOVV	R5, 16(R3) // argv
    69
    70	// create istack out of the given (operating system) stack.
    71	// _cgo_init may update stackguard.
    72	MOVV	$runtime·g0(SB), g
    73	MOVV	$(-64*1024), R30
    74	ADDV	R30, R3, R19
    75	MOVV	R19, g_stackguard0(g)
    76	MOVV	R19, g_stackguard1(g)
    77	MOVV	R19, (g_stack+stack_lo)(g)
    78	MOVV	R3, (g_stack+stack_hi)(g)
    79
    80	// if there is a _cgo_init, call it using the gcc ABI.
    81	MOVV	_cgo_init(SB), R25
    82	BEQ	R25, nocgo
    83
    84	MOVV	R0, R7	// arg 3: not used
    85	MOVV	R0, R6	// arg 2: not used
    86	MOVV	$setg_gcc<>(SB), R5	// arg 1: setg
    87	MOVV	g, R4	// arg 0: G
    88	JAL	(R25)
    89
    90nocgo:
    91	JAL	runtime·save_g(SB)
    92	// update stackguard after _cgo_init
    93	MOVV	(g_stack+stack_lo)(g), R19
    94	ADDV	$const_stackGuard, R19
    95	MOVV	R19, g_stackguard0(g)
    96	MOVV	R19, g_stackguard1(g)
    97
    98	// set the per-goroutine and per-mach "registers"
    99	MOVV	$runtime·m0(SB), R19
   100
   101	// save m->g0 = g0
   102	MOVV	g, m_g0(R19)
   103	// save m0 to g0->m
   104	MOVV	R19, g_m(g)
   105
   106	JAL	runtime·check(SB)
   107
   108	// args are already prepared
   109	JAL	runtime·args(SB)
   110	JAL	runtime·osinit(SB)
   111	JAL	runtime·schedinit(SB)
   112
   113	// create a new goroutine to start program
   114	MOVV	$runtime·mainPC(SB), R19		// entry
   115	ADDV	$-16, R3
   116	MOVV	R19, 8(R3)
   117	MOVV	R0, 0(R3)
   118	JAL	runtime·newproc(SB)
   119	ADDV	$16, R3
   120
   121	// start this M
   122	JAL	runtime·mstart(SB)
   123
   124	// Prevent dead-code elimination of debugCallV2 and debugPinnerV1, which are
   125	// intended to be called by debuggers.
   126	MOVV	$runtime·debugPinnerV1<ABIInternal>(SB), R0
   127	MOVV	$runtime·debugCallV2<ABIInternal>(SB), R0
   128
   129	MOVV	R0, 1(R0)
   130	RET
   131
   132DATA	runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB)
   133GLOBL	runtime·mainPC(SB),RODATA,$8
   134
   135TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
   136	BREAK
   137	RET
   138
   139TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
   140	RET
   141
   142TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
   143	JAL     runtime·mstart0(SB)
   144	RET // not reached
   145
   146// func cputicks() int64
   147TEXT runtime·cputicks<ABIInternal>(SB),NOSPLIT,$0-8
   148	RDTIMED	R0, R4
   149	RET
   150
   151/*
   152 *  go-routine
   153 */
   154
   155// void gogo(Gobuf*)
   156// restore state from Gobuf; longjmp
   157TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   158	MOVV	buf+0(FP), R4
   159	MOVV	gobuf_g(R4), R5
   160	MOVV	0(R5), R0	// make sure g != nil
   161	JMP	gogo<>(SB)
   162
   163TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
   164	MOVV	R5, g
   165	JAL	runtime·save_g(SB)
   166
   167	MOVV	gobuf_sp(R4), R3
   168	MOVV	gobuf_lr(R4), R1
   169	MOVV	gobuf_ctxt(R4), REGCTXT
   170	MOVV	R0, gobuf_sp(R4)
   171	MOVV	R0, gobuf_lr(R4)
   172	MOVV	R0, gobuf_ctxt(R4)
   173	MOVV	gobuf_pc(R4), R6
   174	JMP	(R6)
   175
   176// void mcall(fn func(*g))
   177// Switch to m->g0's stack, call fn(g).
   178// Fn must never return. It should gogo(&g->sched)
   179// to keep running g.
   180TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8
   181	MOVV	R4, REGCTXT
   182	// Save caller state in g->sched
   183	MOVV	R3, (g_sched+gobuf_sp)(g)
   184	MOVV	R1, (g_sched+gobuf_pc)(g)
   185	MOVV	R0, (g_sched+gobuf_lr)(g)
   186
   187	// Switch to m->g0 & its stack, call fn.
   188	MOVV	g, R4		// arg = g
   189	MOVV	g_m(g), R20
   190	MOVV	m_g0(R20), g
   191	JAL	runtime·save_g(SB)
   192	BNE	g, R4, 2(PC)
   193	JMP	runtime·badmcall(SB)
   194	MOVV	0(REGCTXT), R20			// code pointer
   195	MOVV	(g_sched+gobuf_sp)(g), R3	// sp = m->g0->sched.sp
   196	ADDV	$-16, R3
   197	MOVV	R4, 8(R3)
   198	MOVV	R0, 0(R3)
   199	JAL	(R20)
   200	JMP	runtime·badmcall2(SB)
   201
   202// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   203// of the G stack. We need to distinguish the routine that
   204// lives at the bottom of the G stack from the one that lives
   205// at the top of the system stack because the one at the top of
   206// the system stack terminates the stack walk (see topofstack()).
   207TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   208	UNDEF
   209	JAL	(R1)	// make sure this function is not leaf
   210	RET
   211
   212// func systemstack(fn func())
   213TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   214	MOVV	fn+0(FP), R19	// R19 = fn
   215	MOVV	R19, REGCTXT		// context
   216	MOVV	g_m(g), R4	// R4 = m
   217
   218	MOVV	m_gsignal(R4), R5	// R5 = gsignal
   219	BEQ	g, R5, noswitch
   220
   221	MOVV	m_g0(R4), R5	// R5 = g0
   222	BEQ	g, R5, noswitch
   223
   224	MOVV	m_curg(R4), R6
   225	BEQ	g, R6, switch
   226
   227	// Bad: g is not gsignal, not g0, not curg. What is it?
   228	// Hide call from linker nosplit analysis.
   229	MOVV	$runtime·badsystemstack(SB), R7
   230	JAL	(R7)
   231	JAL	runtime·abort(SB)
   232
   233switch:
   234	// save our state in g->sched. Pretend to
   235	// be systemstack_switch if the G stack is scanned.
   236	JAL	gosave_systemstack_switch<>(SB)
   237
   238	// switch to g0
   239	MOVV	R5, g
   240	JAL	runtime·save_g(SB)
   241	MOVV	(g_sched+gobuf_sp)(g), R19
   242	MOVV	R19, R3
   243
   244	// call target function
   245	MOVV	0(REGCTXT), R6	// code pointer
   246	JAL	(R6)
   247
   248	// switch back to g
   249	MOVV	g_m(g), R4
   250	MOVV	m_curg(R4), g
   251	JAL	runtime·save_g(SB)
   252	MOVV	(g_sched+gobuf_sp)(g), R3
   253	MOVV	R0, (g_sched+gobuf_sp)(g)
   254	RET
   255
   256noswitch:
   257	// already on m stack, just call directly
   258	// Using a tail call here cleans up tracebacks since we won't stop
   259	// at an intermediate systemstack.
   260	MOVV	0(REGCTXT), R4	// code pointer
   261	MOVV	0(R3), R1	// restore LR
   262	ADDV	$8, R3
   263	JMP	(R4)
   264
   265// func switchToCrashStack0(fn func())
   266TEXT runtime·switchToCrashStack0<ABIInternal>(SB),NOSPLIT,$0-8
   267	MOVV	R4, REGCTXT	// context register
   268	MOVV	g_m(g), R5	// curm
   269
   270	// set g to gcrash
   271	MOVV	$runtime·gcrash(SB), g	// g = &gcrash
   272	JAL	runtime·save_g(SB)
   273	MOVV	R5, g_m(g)	// g.m = curm
   274	MOVV	g, m_g0(R5)	// curm.g0 = g
   275
   276	// switch to crashstack
   277	MOVV	(g_stack+stack_hi)(g), R5
   278	ADDV	$(-4*8), R5, R3
   279
   280	// call target function
   281	MOVV	0(REGCTXT), R6
   282	JAL	(R6)
   283
   284	// should never return
   285	JAL	runtime·abort(SB)
   286	UNDEF
   287
   288/*
   289 * support for morestack
   290 */
   291
   292// Called during function prolog when more stack is needed.
   293// Caller has already loaded:
   294// loong64: R31: LR
   295//
   296// The traceback routines see morestack on a g0 as being
   297// the top of a stack (for example, morestack calling newstack
   298// calling the scheduler calling newm calling gc), so we must
   299// record an argument size. For that purpose, it has no arguments.
   300TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   301	// Called from f.
   302	// Set g->sched to context in f.
   303	MOVV	R3, (g_sched+gobuf_sp)(g)
   304	MOVV	R1, (g_sched+gobuf_pc)(g)
   305	MOVV	R31, (g_sched+gobuf_lr)(g)
   306	MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   307
   308	// Cannot grow scheduler stack (m->g0).
   309	MOVV	g_m(g), R7
   310	MOVV	m_g0(R7), R8
   311	BNE	g, R8, 3(PC)
   312	JAL	runtime·badmorestackg0(SB)
   313	JAL	runtime·abort(SB)
   314
   315	// Cannot grow signal stack (m->gsignal).
   316	MOVV	m_gsignal(R7), R8
   317	BNE	g, R8, 3(PC)
   318	JAL	runtime·badmorestackgsignal(SB)
   319	JAL	runtime·abort(SB)
   320
   321	// Called from f.
   322	// Set m->morebuf to f's caller.
   323	MOVV	R31, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   324	MOVV	R3, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   325	MOVV	g, (m_morebuf+gobuf_g)(R7)
   326
   327	// Call newstack on m->g0's stack.
   328	MOVV	m_g0(R7), g
   329	JAL	runtime·save_g(SB)
   330	MOVV	(g_sched+gobuf_sp)(g), R3
   331	// Create a stack frame on g0 to call newstack.
   332	MOVV	R0, -8(R3)	// Zero saved LR in frame
   333	ADDV	$-8, R3
   334	JAL	runtime·newstack(SB)
   335
   336	// Not reached, but make sure the return PC from the call to newstack
   337	// is still in this function, and not the beginning of the next.
   338	UNDEF
   339
   340TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   341	// Force SPWRITE. This function doesn't actually write SP,
   342	// but it is called with a special calling convention where
   343	// the caller doesn't save LR on stack but passes it as a
   344	// register (R5), and the unwinder currently doesn't understand.
   345	// Make it SPWRITE to stop unwinding. (See issue 54332)
   346	MOVV    R3, R3
   347
   348	MOVV	R0, REGCTXT
   349	JMP	runtime·morestack(SB)
   350
   351// reflectcall: call a function with the given argument list
   352// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   353// we don't have variable-sized frames, so we use a small number
   354// of constant-sized-frame functions to encode a few bits of size in the pc.
   355// Caution: ugly multiline assembly macros in your future!
   356
   357#define DISPATCH(NAME,MAXSIZE)		\
   358	MOVV	$MAXSIZE, R30;		\
   359	SGTU	R19, R30, R30;		\
   360	BNE	R30, 3(PC);			\
   361	MOVV	$NAME(SB), R4;	\
   362	JMP	(R4)
   363// Note: can't just "BR NAME(SB)" - bad inlining results.
   364
   365TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
   366	MOVWU frameSize+32(FP), R19
   367	DISPATCH(runtime·call32, 32)
   368	DISPATCH(runtime·call64, 64)
   369	DISPATCH(runtime·call128, 128)
   370	DISPATCH(runtime·call256, 256)
   371	DISPATCH(runtime·call512, 512)
   372	DISPATCH(runtime·call1024, 1024)
   373	DISPATCH(runtime·call2048, 2048)
   374	DISPATCH(runtime·call4096, 4096)
   375	DISPATCH(runtime·call8192, 8192)
   376	DISPATCH(runtime·call16384, 16384)
   377	DISPATCH(runtime·call32768, 32768)
   378	DISPATCH(runtime·call65536, 65536)
   379	DISPATCH(runtime·call131072, 131072)
   380	DISPATCH(runtime·call262144, 262144)
   381	DISPATCH(runtime·call524288, 524288)
   382	DISPATCH(runtime·call1048576, 1048576)
   383	DISPATCH(runtime·call2097152, 2097152)
   384	DISPATCH(runtime·call4194304, 4194304)
   385	DISPATCH(runtime·call8388608, 8388608)
   386	DISPATCH(runtime·call16777216, 16777216)
   387	DISPATCH(runtime·call33554432, 33554432)
   388	DISPATCH(runtime·call67108864, 67108864)
   389	DISPATCH(runtime·call134217728, 134217728)
   390	DISPATCH(runtime·call268435456, 268435456)
   391	DISPATCH(runtime·call536870912, 536870912)
   392	DISPATCH(runtime·call1073741824, 1073741824)
   393	MOVV	$runtime·badreflectcall(SB), R4
   394	JMP	(R4)
   395
   396#define CALLFN(NAME,MAXSIZE)			\
   397TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   398	NO_LOCAL_POINTERS;			\
   399	/* copy arguments to stack */		\
   400	MOVV	arg+16(FP), R4;			\
   401	MOVWU	argsize+24(FP), R5;		\
   402	MOVV	R3, R12;			\
   403	MOVV	$16, R13;			\
   404	ADDV	$8, R12;			\
   405	BLT	R5, R13, check8;		\
   406	/* copy 16 bytes a time */		\
   407	MOVBU	internal∕cpu·Loong64+const_offsetLOONG64HasLSX(SB), R16;	\
   408	BEQ	R16, copy16_again;		\
   409loop16:;					\
   410	VMOVQ	(R4), V0;			\
   411	ADDV	$16, R4;			\
   412	ADDV	$-16, R5;			\
   413	VMOVQ	V0, (R12);			\
   414	ADDV	$16, R12;			\
   415	BGE	R5, R13, loop16;		\
   416	JMP	check8;				\
   417copy16_again:;					\
   418	MOVV	(R4), R14;			\
   419	MOVV	8(R4), R15;			\
   420	ADDV	$16, R4;			\
   421	ADDV	$-16, R5;			\
   422	MOVV	R14, (R12);			\
   423	MOVV	R15, 8(R12);			\
   424	ADDV	$16, R12;			\
   425	BGE	R5, R13, copy16_again;		\
   426check8:;					\
   427	/* R13 = 8 */;				\
   428	SRLV	$1, R13;			\
   429	BLT	R5, R13, 6(PC);			\
   430	/* copy 8 bytes a time */		\
   431	MOVV	(R4), R14;			\
   432	ADDV	$8, R4;				\
   433	ADDV	$-8, R5;			\
   434	MOVV	R14, (R12);			\
   435	ADDV	$8, R12;			\
   436	BEQ     R5, R0, 7(PC);  		\
   437	/* copy 1 byte a time for the rest */	\
   438	MOVBU   (R4), R14;      		\
   439	ADDV    $1, R4;         		\
   440	ADDV    $-1, R5;        		\
   441	MOVBU   R14, (R12);     		\
   442	ADDV    $1, R12;        		\
   443	JMP     -6(PC);         		\
   444	/* set up argument registers */		\
   445	MOVV	regArgs+40(FP), R25;		\
   446	JAL	·unspillArgs(SB);		\
   447	/* call function */			\
   448	MOVV	f+8(FP), REGCTXT;		\
   449	MOVV	(REGCTXT), R25;			\
   450	PCDATA  $PCDATA_StackMapIndex, $0;	\
   451	JAL	(R25);				\
   452	/* copy return values back */		\
   453	MOVV	regArgs+40(FP), R25;		\
   454	JAL	·spillArgs(SB);			\
   455	MOVV	argtype+0(FP), R7;		\
   456	MOVV	arg+16(FP), R4;			\
   457	MOVWU	n+24(FP), R5;			\
   458	MOVWU	retoffset+28(FP), R6;		\
   459	ADDV	$8, R3, R12;			\
   460	ADDV	R6, R12; 			\
   461	ADDV	R6, R4;				\
   462	SUBVU	R6, R5;				\
   463	JAL	callRet<>(SB);			\
   464	RET
   465
   466// callRet copies return values back at the end of call*. This is a
   467// separate function so it can allocate stack space for the arguments
   468// to reflectcallmove. It does not follow the Go ABI; it expects its
   469// arguments in registers.
   470TEXT callRet<>(SB), NOSPLIT, $40-0
   471	NO_LOCAL_POINTERS
   472	MOVV	R7, 8(R3)
   473	MOVV	R4, 16(R3)
   474	MOVV	R12, 24(R3)
   475	MOVV	R5, 32(R3)
   476	MOVV	R25, 40(R3)
   477	JAL	runtime·reflectcallmove(SB)
   478	RET
   479
   480CALLFN(·call16, 16)
   481CALLFN(·call32, 32)
   482CALLFN(·call64, 64)
   483CALLFN(·call128, 128)
   484CALLFN(·call256, 256)
   485CALLFN(·call512, 512)
   486CALLFN(·call1024, 1024)
   487CALLFN(·call2048, 2048)
   488CALLFN(·call4096, 4096)
   489CALLFN(·call8192, 8192)
   490CALLFN(·call16384, 16384)
   491CALLFN(·call32768, 32768)
   492CALLFN(·call65536, 65536)
   493CALLFN(·call131072, 131072)
   494CALLFN(·call262144, 262144)
   495CALLFN(·call524288, 524288)
   496CALLFN(·call1048576, 1048576)
   497CALLFN(·call2097152, 2097152)
   498CALLFN(·call4194304, 4194304)
   499CALLFN(·call8388608, 8388608)
   500CALLFN(·call16777216, 16777216)
   501CALLFN(·call33554432, 33554432)
   502CALLFN(·call67108864, 67108864)
   503CALLFN(·call134217728, 134217728)
   504CALLFN(·call268435456, 268435456)
   505CALLFN(·call536870912, 536870912)
   506CALLFN(·call1073741824, 1073741824)
   507
   508TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
   509	RET
   510
   511// Save state of caller into g->sched.
   512// but using fake PC from systemstack_switch.
   513// Must only be called from functions with no locals ($0)
   514// or else unwinding from systemstack_switch is incorrect.
   515// Smashes R19.
   516TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
   517	MOVV    $runtime·systemstack_switch(SB), R19
   518	ADDV	$8, R19
   519	MOVV	R19, (g_sched+gobuf_pc)(g)
   520	MOVV	R3, (g_sched+gobuf_sp)(g)
   521	MOVV	R0, (g_sched+gobuf_lr)(g)
   522	// Assert ctxt is zero. See func save.
   523	MOVV	(g_sched+gobuf_ctxt)(g), R19
   524	BEQ	R19, 2(PC)
   525	JAL	runtime·abort(SB)
   526	RET
   527
   528// func asmcgocall(fn, arg unsafe.Pointer) int32
   529// Call fn(arg) on the scheduler stack,
   530// aligned appropriately for the gcc ABI.
   531// See cgocall.go for more details.
   532TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   533	MOVV	fn+0(FP), R25
   534	MOVV	arg+8(FP), R4
   535
   536	MOVV	R3, R12	// save original stack pointer
   537	MOVV	g, R13
   538
   539	// Figure out if we need to switch to m->g0 stack.
   540	// We get called to create new OS threads too, and those
   541	// come in on the m->g0 stack already.
   542	MOVV	g_m(g), R5
   543	MOVV	m_gsignal(R5), R6
   544	BEQ	R6, g, g0
   545	MOVV	m_g0(R5), R6
   546	BEQ	R6, g, g0
   547
   548	JAL	gosave_systemstack_switch<>(SB)
   549	MOVV	R6, g
   550	JAL	runtime·save_g(SB)
   551	MOVV	(g_sched+gobuf_sp)(g), R3
   552
   553	// Now on a scheduling stack (a pthread-created stack).
   554g0:
   555	// Save room for two of our pointers.
   556	ADDV	$-16, R3
   557	MOVV	R13, 0(R3)	// save old g on stack
   558	MOVV	(g_stack+stack_hi)(R13), R13
   559	SUBVU	R12, R13
   560	MOVV	R13, 8(R3)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   561	JAL	(R25)
   562
   563	// Restore g, stack pointer. R4 is return value.
   564	MOVV	0(R3), g
   565	JAL	runtime·save_g(SB)
   566	MOVV	(g_stack+stack_hi)(g), R5
   567	MOVV	8(R3), R6
   568	SUBVU	R6, R5
   569	MOVV	R5, R3
   570
   571	MOVW	R4, ret+16(FP)
   572	RET
   573
   574// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   575// See cgocall.go for more details.
   576TEXT ·cgocallback(SB),NOSPLIT,$24-24
   577	NO_LOCAL_POINTERS
   578
   579	// Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
   580	// It is used to dropm while thread is exiting.
   581	MOVV    fn+0(FP), R5
   582	BNE	R5, loadg
   583	// Restore the g from frame.
   584	MOVV    frame+8(FP), g
   585	JMP	dropm
   586
   587loadg:
   588	// Load m and g from thread-local storage.
   589	MOVB	runtime·iscgo(SB), R19
   590	BEQ	R19, nocgo
   591	JAL	runtime·load_g(SB)
   592nocgo:
   593
   594	// If g is nil, Go did not create the current thread,
   595	// or if this thread never called into Go on pthread platforms.
   596	// Call needm to obtain one for temporary use.
   597	// In this case, we're running on the thread stack, so there's
   598	// lots of space, but the linker doesn't know. Hide the call from
   599	// the linker analysis by using an indirect call.
   600	BEQ	g, needm
   601
   602	MOVV	g_m(g), R12
   603	MOVV	R12, savedm-8(SP)
   604	JMP	havem
   605
   606needm:
   607	MOVV	g, savedm-8(SP) // g is zero, so is m.
   608	MOVV	$runtime·needAndBindM(SB), R4
   609	JAL	(R4)
   610
   611	// Set m->sched.sp = SP, so that if a panic happens
   612	// during the function we are about to execute, it will
   613	// have a valid SP to run on the g0 stack.
   614	// The next few lines (after the havem label)
   615	// will save this SP onto the stack and then write
   616	// the same SP back to m->sched.sp. That seems redundant,
   617	// but if an unrecovered panic happens, unwindm will
   618	// restore the g->sched.sp from the stack location
   619	// and then systemstack will try to use it. If we don't set it here,
   620	// that restored SP will be uninitialized (typically 0) and
   621	// will not be usable.
   622	MOVV	g_m(g), R12
   623	MOVV	m_g0(R12), R19
   624	MOVV	R3, (g_sched+gobuf_sp)(R19)
   625
   626havem:
   627	// Now there's a valid m, and we're running on its m->g0.
   628	// Save current m->g0->sched.sp on stack and then set it to SP.
   629	// Save current sp in m->g0->sched.sp in preparation for
   630	// switch back to m->curg stack.
   631	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   632	MOVV	m_g0(R12), R19
   633	MOVV	(g_sched+gobuf_sp)(R19), R13
   634	MOVV	R13, savedsp-24(SP) // must match frame size
   635	MOVV	R3, (g_sched+gobuf_sp)(R19)
   636
   637	// Switch to m->curg stack and call runtime.cgocallbackg.
   638	// Because we are taking over the execution of m->curg
   639	// but *not* resuming what had been running, we need to
   640	// save that information (m->curg->sched) so we can restore it.
   641	// We can restore m->curg->sched.sp easily, because calling
   642	// runtime.cgocallbackg leaves SP unchanged upon return.
   643	// To save m->curg->sched.pc, we push it onto the stack.
   644	// This has the added benefit that it looks to the traceback
   645	// routine like cgocallbackg is going to return to that
   646	// PC (because the frame we allocate below has the same
   647	// size as cgocallback_gofunc's frame declared above)
   648	// so that the traceback will seamlessly trace back into
   649	// the earlier calls.
   650	MOVV	m_curg(R12), g
   651	JAL	runtime·save_g(SB)
   652	MOVV	(g_sched+gobuf_sp)(g), R13 // prepare stack as R13
   653	MOVV	(g_sched+gobuf_pc)(g), R4
   654	MOVV	R4, -(24+8)(R13) // "saved LR"; must match frame size
   655	MOVV    fn+0(FP), R5
   656	MOVV    frame+8(FP), R6
   657	MOVV    ctxt+16(FP), R7
   658	MOVV	$-(24+8)(R13), R3
   659	MOVV    R5, 8(R3)
   660	MOVV    R6, 16(R3)
   661	MOVV    R7, 24(R3)
   662	JAL	runtime·cgocallbackg(SB)
   663
   664	// Restore g->sched (== m->curg->sched) from saved values.
   665	MOVV	0(R3), R4
   666	MOVV	R4, (g_sched+gobuf_pc)(g)
   667	MOVV	$(24+8)(R3), R13 // must match frame size
   668	MOVV	R13, (g_sched+gobuf_sp)(g)
   669
   670	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   671	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   672	// so we do not have to restore it.)
   673	MOVV	g_m(g), R12
   674	MOVV	m_g0(R12), g
   675	JAL	runtime·save_g(SB)
   676	MOVV	(g_sched+gobuf_sp)(g), R3
   677	MOVV	savedsp-24(SP), R13 // must match frame size
   678	MOVV	R13, (g_sched+gobuf_sp)(g)
   679
   680	// If the m on entry was nil, we called needm above to borrow an m,
   681	// 1. for the duration of the call on non-pthread platforms,
   682	// 2. or the duration of the C thread alive on pthread platforms.
   683	// If the m on entry wasn't nil,
   684	// 1. the thread might be a Go thread,
   685	// 2. or it wasn't the first call from a C thread on pthread platforms,
   686	//    since then we skip dropm to resue the m in the first call.
   687	MOVV	savedm-8(SP), R12
   688	BNE	R12, droppedm
   689
   690	// Skip dropm to reuse it in the next call, when a pthread key has been created.
   691	MOVV	_cgo_pthread_key_created(SB), R12
   692	// It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
   693	BEQ	R12, dropm
   694	MOVV    (R12), R12
   695	BNE	R12, droppedm
   696
   697dropm:
   698	MOVV	$runtime·dropm(SB), R4
   699	JAL	(R4)
   700droppedm:
   701
   702	// Done!
   703	RET
   704
   705// void setg(G*); set g. for use by needm.
   706TEXT runtime·setg(SB), NOSPLIT, $0-8
   707	MOVV	gg+0(FP), g
   708	// This only happens if iscgo, so jump straight to save_g
   709	JAL	runtime·save_g(SB)
   710	RET
   711
   712// void setg_gcc(G*); set g called from gcc with g in R4
   713TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   714	MOVV	R4, g
   715	JAL	runtime·save_g(SB)
   716	RET
   717
   718TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   719	MOVW	(R0), R0
   720	UNDEF
   721
   722// AES hashing not implemented for loong64
   723TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
   724	JMP	runtime·memhashFallback<ABIInternal>(SB)
   725TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   726	JMP	runtime·strhashFallback<ABIInternal>(SB)
   727TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   728	JMP	runtime·memhash32Fallback<ABIInternal>(SB)
   729TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   730	JMP	runtime·memhash64Fallback<ABIInternal>(SB)
   731
   732// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   733// Must obey the gcc calling convention.
   734TEXT _cgo_topofstack(SB),NOSPLIT,$16
   735	// g (R22) and REGTMP (R30)  might be clobbered by load_g. They
   736	// are callee-save in the gcc calling convention, so save them.
   737	MOVV	R30, savedREGTMP-16(SP)
   738	MOVV	g, savedG-8(SP)
   739
   740	JAL	runtime·load_g(SB)
   741	MOVV	g_m(g), R19
   742	MOVV	m_curg(R19), R19
   743	MOVV	(g_stack+stack_hi)(R19), R4 // return value in R4
   744
   745	MOVV	savedG-8(SP), g
   746	MOVV	savedREGTMP-16(SP), R30
   747	RET
   748
   749// The top-most function running on a goroutine
   750// returns to goexit+PCQuantum.
   751TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   752	NOOP
   753	JAL	runtime·goexit1(SB)	// does not return
   754	// traceback from goexit1 must hit code range of goexit
   755	NOOP
   756
   757// This is called from .init_array and follows the platform, not Go, ABI.
   758TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
   759	ADDV	$-0x10, R3
   760	MOVV	R30, 8(R3) // The access to global variables below implicitly uses R30, which is callee-save
   761	MOVV	runtime·lastmoduledatap(SB), R12
   762	MOVV	R4, moduledata_next(R12)
   763	MOVV	R4, runtime·lastmoduledatap(SB)
   764	MOVV	8(R3), R30
   765	ADDV	$0x10, R3
   766	RET
   767
   768TEXT ·checkASM(SB),NOSPLIT,$0-1
   769	MOVW	$1, R19
   770	MOVB	R19, ret+0(FP)
   771	RET
   772
   773// spillArgs stores return values from registers to a *internal/abi.RegArgs in R25.
   774TEXT ·spillArgs(SB),NOSPLIT,$0-0
   775	MOVV	R4, (0*8)(R25)
   776	MOVV	R5, (1*8)(R25)
   777	MOVV	R6, (2*8)(R25)
   778	MOVV	R7, (3*8)(R25)
   779	MOVV	R8, (4*8)(R25)
   780	MOVV	R9, (5*8)(R25)
   781	MOVV	R10, (6*8)(R25)
   782	MOVV	R11, (7*8)(R25)
   783	MOVV	R12, (8*8)(R25)
   784	MOVV	R13, (9*8)(R25)
   785	MOVV	R14, (10*8)(R25)
   786	MOVV	R15, (11*8)(R25)
   787	MOVV	R16, (12*8)(R25)
   788	MOVV	R17, (13*8)(R25)
   789	MOVV	R18, (14*8)(R25)
   790	MOVV	R19, (15*8)(R25)
   791	MOVD	F0, (16*8)(R25)
   792	MOVD	F1, (17*8)(R25)
   793	MOVD	F2, (18*8)(R25)
   794	MOVD	F3, (19*8)(R25)
   795	MOVD	F4, (20*8)(R25)
   796	MOVD	F5, (21*8)(R25)
   797	MOVD	F6, (22*8)(R25)
   798	MOVD	F7, (23*8)(R25)
   799	MOVD	F8, (24*8)(R25)
   800	MOVD	F9, (25*8)(R25)
   801	MOVD	F10, (26*8)(R25)
   802	MOVD	F11, (27*8)(R25)
   803	MOVD	F12, (28*8)(R25)
   804	MOVD	F13, (29*8)(R25)
   805	MOVD	F14, (30*8)(R25)
   806	MOVD	F15, (31*8)(R25)
   807	RET
   808
   809// unspillArgs loads args into registers from a *internal/abi.RegArgs in R25.
   810TEXT ·unspillArgs(SB),NOSPLIT,$0-0
   811	MOVV	(0*8)(R25), R4
   812	MOVV	(1*8)(R25), R5
   813	MOVV	(2*8)(R25), R6
   814	MOVV	(3*8)(R25), R7
   815	MOVV	(4*8)(R25), R8
   816	MOVV	(5*8)(R25), R9
   817	MOVV	(6*8)(R25), R10
   818	MOVV	(7*8)(R25), R11
   819	MOVV	(8*8)(R25), R12
   820	MOVV	(9*8)(R25), R13
   821	MOVV	(10*8)(R25), R14
   822	MOVV	(11*8)(R25), R15
   823	MOVV	(12*8)(R25), R16
   824	MOVV	(13*8)(R25), R17
   825	MOVV	(14*8)(R25), R18
   826	MOVV	(15*8)(R25), R19
   827	MOVD	(16*8)(R25), F0
   828	MOVD	(17*8)(R25), F1
   829	MOVD	(18*8)(R25), F2
   830	MOVD	(19*8)(R25), F3
   831	MOVD	(20*8)(R25), F4
   832	MOVD	(21*8)(R25), F5
   833	MOVD	(22*8)(R25), F6
   834	MOVD	(23*8)(R25), F7
   835	MOVD	(24*8)(R25), F8
   836	MOVD	(25*8)(R25), F9
   837	MOVD	(26*8)(R25), F10
   838	MOVD	(27*8)(R25), F11
   839	MOVD	(28*8)(R25), F12
   840	MOVD	(29*8)(R25), F13
   841	MOVD	(30*8)(R25), F14
   842	MOVD	(31*8)(R25), F15
   843	RET
   844
   845// gcWriteBarrier informs the GC about heap pointer writes.
   846//
   847// gcWriteBarrier does NOT follow the Go ABI. It accepts the
   848// number of bytes of buffer needed in R29, and returns a pointer
   849// to the buffer space in R29.
   850// It clobbers R30 (the linker temp register).
   851// The act of CALLing gcWriteBarrier will clobber R1 (LR).
   852// It does not clobber any other general-purpose registers,
   853// but may clobber others (e.g., floating point registers).
   854TEXT gcWriteBarrier<>(SB),NOSPLIT,$216
   855	// Save the registers clobbered by the fast path.
   856	MOVV	R19, 208(R3)
   857	MOVV	R13, 216(R3)
   858retry:
   859	MOVV	g_m(g), R19
   860	MOVV	m_p(R19), R19
   861	MOVV	(p_wbBuf+wbBuf_next)(R19), R13
   862	MOVV	(p_wbBuf+wbBuf_end)(R19), R30 // R30 is linker temp register
   863	// Increment wbBuf.next position.
   864	ADDV	R29, R13
   865	// Is the buffer full?
   866	BLTU	R30, R13, flush
   867	// Commit to the larger buffer.
   868	MOVV	R13, (p_wbBuf+wbBuf_next)(R19)
   869	// Make return value (the original next position)
   870	SUBV	R29, R13, R29
   871	// Restore registers.
   872	MOVV	208(R3), R19
   873	MOVV	216(R3), R13
   874	RET
   875
   876flush:
   877	// Save all general purpose registers since these could be
   878	// clobbered by wbBufFlush and were not saved by the caller.
   879	MOVV	R27, 8(R3)
   880	MOVV	R28, 16(R3)
   881	// R1 is LR, which was saved by the prologue.
   882	MOVV	R2, 24(R3)
   883	// R3 is SP.
   884	MOVV	R4, 32(R3)
   885	MOVV	R5, 40(R3)
   886	MOVV	R6, 48(R3)
   887	MOVV	R7, 56(R3)
   888	MOVV	R8, 64(R3)
   889	MOVV	R9, 72(R3)
   890	MOVV	R10, 80(R3)
   891	MOVV	R11, 88(R3)
   892	MOVV	R12, 96(R3)
   893	// R13 already saved
   894	MOVV	R14, 104(R3)
   895	MOVV	R15, 112(R3)
   896	MOVV	R16, 120(R3)
   897	MOVV	R17, 128(R3)
   898	MOVV	R18, 136(R3)
   899	// R19 already saved
   900	MOVV	R20, 144(R3)
   901	MOVV	R21, 152(R3)
   902	// R22 is g.
   903	MOVV	R23, 160(R3)
   904	MOVV	R24, 168(R3)
   905	MOVV	R25, 176(R3)
   906	MOVV	R26, 184(R3)
   907	// R27 already saved
   908	// R28 already saved.
   909	MOVV	R29, 192(R3)
   910	// R30 is tmp register.
   911	MOVV	R31, 200(R3)
   912
   913	CALL	runtime·wbBufFlush(SB)
   914
   915	MOVV	8(R3), R27
   916	MOVV	16(R3), R28
   917	MOVV	24(R3), R2
   918	MOVV	32(R3), R4
   919	MOVV	40(R3), R5
   920	MOVV	48(R3), R6
   921	MOVV	56(R3), R7
   922	MOVV	64(R3), R8
   923	MOVV	72(R3), R9
   924	MOVV	80(R3), R10
   925	MOVV	88(R3), R11
   926	MOVV	96(R3), R12
   927	MOVV	104(R3), R14
   928	MOVV	112(R3), R15
   929	MOVV	120(R3), R16
   930	MOVV	128(R3), R17
   931	MOVV	136(R3), R18
   932	MOVV	144(R3), R20
   933	MOVV	152(R3), R21
   934	MOVV	160(R3), R23
   935	MOVV	168(R3), R24
   936	MOVV	176(R3), R25
   937	MOVV	184(R3), R26
   938	MOVV	192(R3), R29
   939	MOVV	200(R3), R31
   940	JMP	retry
   941
   942TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
   943	MOVV	$8, R29
   944	JMP	gcWriteBarrier<>(SB)
   945TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
   946	MOVV	$16, R29
   947	JMP	gcWriteBarrier<>(SB)
   948TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
   949	MOVV	$24, R29
   950	JMP	gcWriteBarrier<>(SB)
   951TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
   952	MOVV	$32, R29
   953	JMP	gcWriteBarrier<>(SB)
   954TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
   955	MOVV	$40, R29
   956	JMP	gcWriteBarrier<>(SB)
   957TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
   958	MOVV	$48, R29
   959	JMP	gcWriteBarrier<>(SB)
   960TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
   961	MOVV	$56, R29
   962	JMP	gcWriteBarrier<>(SB)
   963TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
   964	MOVV	$64, R29
   965	JMP	gcWriteBarrier<>(SB)
   966
   967DATA	debugCallFrameTooLarge<>+0x00(SB)/20, $"call frame too large"
   968GLOBL	debugCallFrameTooLarge<>(SB), RODATA, $20	// Size duplicated below
   969
   970// debugCallV2 is the entry point for debugger-injected function
   971// calls on running goroutines. It informs the runtime that a
   972// debug call has been injected and creates a call frame for the
   973// debugger to fill in.
   974//
   975// To inject a function call, a debugger should:
   976// 1. Check that the goroutine is in state _Grunning and that
   977//    there are at least 280 bytes free on the stack.
   978// 2. Set SP as SP-8.
   979// 3. Store the current LR in (SP) (using the SP after step 2).
   980// 4. Store the current PC in the LR register.
   981// 5. Write the desired argument frame size at SP-8
   982// 6. Save all machine registers so they can be restored later by the debugger.
   983// 7. Set the PC to debugCallV2 and resume execution.
   984//
   985// If the goroutine is in state _Grunnable, then it's not generally
   986// safe to inject a call because it may return out via other runtime
   987// operations. Instead, the debugger should unwind the stack to find
   988// the return to non-runtime code, add a temporary breakpoint there,
   989// and inject the call once that breakpoint is hit.
   990//
   991// If the goroutine is in any other state, it's not safe to inject a call.
   992//
   993// This function communicates back to the debugger by setting R19 and
   994// invoking BREAK to raise a breakpoint signal. Note that the signal PC of
   995// the signal triggered by the BREAK instruction is the PC where the signal
   996// is trapped, not the next PC, so to resume execution, the debugger needs
   997// to set the signal PC to PC+4. See the comments in the implementation for
   998// the protocol the debugger is expected to follow. InjectDebugCall in the
   999// runtime tests demonstrates this protocol.
  1000//
  1001// The debugger must ensure that any pointers passed to the function
  1002// obey escape analysis requirements. Specifically, it must not pass
  1003// a stack pointer to an escaping argument. debugCallV2 cannot check
  1004// this invariant.
  1005//
  1006// This is ABIInternal because Go code injects its PC directly into new
  1007// goroutine stacks.
  1008TEXT runtime·debugCallV2<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-0
  1009	MOVV    R1, -272(R3)
  1010	ADDV    $-272, R3
  1011
  1012	// We can't do anything that might clobber any of these
  1013	// registers before this.
  1014	MOVV    R2, (4*8)(R3)
  1015	MOVV    R4, (5*8)(R3)
  1016	MOVV    R5, (6*8)(R3)
  1017	MOVV    R6, (7*8)(R3)
  1018	MOVV    R7, (8*8)(R3)
  1019	MOVV    R8, (9*8)(R3)
  1020	MOVV    R9, (10*8)(R3)
  1021	MOVV    R10, (11*8)(R3)
  1022	MOVV    R11, (12*8)(R3)
  1023	MOVV    R12, (13*8)(R3)
  1024	MOVV    R13, (14*8)(R3)
  1025	MOVV    R14, (15*8)(R3)
  1026	MOVV    R15, (16*8)(R3)
  1027	MOVV    R16, (17*8)(R3)
  1028	MOVV    R17, (18*8)(R3)
  1029	MOVV    R18, (19*8)(R3)
  1030	MOVV    R19, (20*8)(R3)
  1031	MOVV    R20, (21*8)(R3)
  1032	MOVV    R21, (22*8)(R3)
  1033	MOVV    g, (23*8)(R3)
  1034	MOVV    R23, (24*8)(R3)
  1035	MOVV    R24, (25*8)(R3)
  1036	MOVV    R25, (26*8)(R3)
  1037	MOVV    R26, (27*8)(R3)
  1038	MOVV    R27, (28*8)(R3)
  1039	MOVV    R28, (29*8)(R3)
  1040	MOVV    R29, (30*8)(R3)
  1041	MOVV    R30, (31*8)(R3)
  1042	MOVV    R31, (32*8)(R3)
  1043
  1044	// Perform a safe-point check.
  1045	MOVV    R1, 8(R3)
  1046	CALL    runtime·debugCallCheck(SB)
  1047	MOVV    16(R3), R30
  1048	BEQ R30, good
  1049
  1050	// The safety check failed. Put the reason string at the top
  1051	// of the stack.
  1052	MOVV    R30, 8(R3)
  1053
  1054	MOVV    24(R3), R30
  1055	MOVV    R30, 16(R3)
  1056
  1057	MOVV    $8, R19
  1058	BREAK
  1059	JMP restore
  1060
  1061good:
  1062	// Registers are saved and it's safe to make a call.
  1063	// Open up a call frame, moving the stack if necessary.
  1064	//
  1065	// Once the frame is allocated, this will set R19 to 0 and
  1066	// invoke BREAK. The debugger should write the argument
  1067	// frame for the call at SP+8, set up argument registers,
  1068	// set the LR as the signal PC + 4, set the PC to the function
  1069	// to call, set R29 to point to the closure (if a closure call),
  1070	// and resume execution.
  1071	//
  1072	// If the function returns, this will set R19 to 1 and invoke
  1073	// BREAK. The debugger can then inspect any return value saved
  1074	// on the stack at SP+8 and in registers. To resume execution,
  1075	// the debugger should restore the LR from (SP).
  1076	//
  1077	// If the function panics, this will set R19 to 2 and invoke BREAK.
  1078	// The interface{} value of the panic will be at SP+8. The debugger
  1079	// can inspect the panic value and resume execution again.
  1080#define DEBUG_CALL_DISPATCH(NAME,MAXSIZE)	\
  1081	MOVV    $MAXSIZE, R27;         \
  1082	BLT R27, R30, 5(PC);            \
  1083	MOVV    $NAME(SB), R28;			\
  1084	MOVV    R28, 8(R3);			\
  1085	CALL    runtime·debugCallWrap(SB);	\
  1086	JMP restore
  1087
  1088	MOVV    264(R3), R30 // the argument frame size
  1089	DEBUG_CALL_DISPATCH(debugCall32<>, 32)
  1090	DEBUG_CALL_DISPATCH(debugCall64<>, 64)
  1091	DEBUG_CALL_DISPATCH(debugCall128<>, 128)
  1092	DEBUG_CALL_DISPATCH(debugCall256<>, 256)
  1093	DEBUG_CALL_DISPATCH(debugCall512<>, 512)
  1094	DEBUG_CALL_DISPATCH(debugCall1024<>, 1024)
  1095	DEBUG_CALL_DISPATCH(debugCall2048<>, 2048)
  1096	DEBUG_CALL_DISPATCH(debugCall4096<>, 4096)
  1097	DEBUG_CALL_DISPATCH(debugCall8192<>, 8192)
  1098	DEBUG_CALL_DISPATCH(debugCall16384<>, 16384)
  1099	DEBUG_CALL_DISPATCH(debugCall32768<>, 32768)
  1100	DEBUG_CALL_DISPATCH(debugCall65536<>, 65536)
  1101	// The frame size is too large. Report the error.
  1102	MOVV    $debugCallFrameTooLarge<>(SB), R30
  1103	MOVV    R30, 8(R3)
  1104	MOVV    $20, R30
  1105	MOVV    R30, 16(R3) // length of debugCallFrameTooLarge string
  1106	MOVV    $8, R19
  1107	BREAK
  1108	JMP restore
  1109
  1110restore:
  1111	// Calls and failures resume here.
  1112	//
  1113	// Set R19 to 16 and invoke BREAK. The debugger should restore
  1114	// all registers except for PC and SP and resume execution.
  1115	MOVV    $16, R19
  1116	BREAK
  1117	// We must not modify flags after this point.
  1118
  1119	// Restore pointer-containing registers, which may have been
  1120	// modified from the debugger's copy by stack copying.
  1121	MOVV    (4*8)(R3), R2
  1122	MOVV    (5*8)(R3), R4
  1123	MOVV    (6*8)(R3), R5
  1124	MOVV    (7*8)(R3), R6
  1125	MOVV    (8*8)(R3), R7
  1126	MOVV    (9*8)(R3), R8
  1127	MOVV    (10*8)(R3), R9
  1128	MOVV    (11*8)(R3), R10
  1129	MOVV    (12*8)(R3), R11
  1130	MOVV    (13*8)(R3), R12
  1131	MOVV    (14*8)(R3), R13
  1132	MOVV    (15*8)(R3), R14
  1133	MOVV    (16*8)(R3), R15
  1134	MOVV    (17*8)(R3), R16
  1135	MOVV    (18*8)(R3), R17
  1136	MOVV    (19*8)(R3), R18
  1137	MOVV    (20*8)(R3), R19
  1138	MOVV    (21*8)(R3), R20
  1139	MOVV    (22*8)(R3), R21
  1140	MOVV    (23*8)(R3), g
  1141	MOVV    (24*8)(R3), R23
  1142	MOVV    (25*8)(R3), R24
  1143	MOVV    (26*8)(R3), R25
  1144	MOVV    (27*8)(R3), R26
  1145	MOVV    (28*8)(R3), R27
  1146	MOVV    (29*8)(R3), R28
  1147	MOVV    (30*8)(R3), R29
  1148	MOVV    (31*8)(R3), R30
  1149	MOVV    (32*8)(R3), R31
  1150
  1151	MOVV    0(R3), R30
  1152	ADDV    $280, R3 // Add 8 more bytes, see saveSigContext
  1153	MOVV    -8(R3), R1
  1154	JMP (R30)
  1155
  1156// runtime.debugCallCheck assumes that functions defined with the
  1157// DEBUG_CALL_FN macro are safe points to inject calls.
  1158#define DEBUG_CALL_FN(NAME,MAXSIZE)		\
  1159TEXT NAME(SB),WRAPPER,$MAXSIZE-0;		\
  1160	NO_LOCAL_POINTERS;		\
  1161	MOVV    $0, R19;		\
  1162	BREAK;		\
  1163	MOVV    $1, R19;		\
  1164	BREAK;		\
  1165	RET
  1166DEBUG_CALL_FN(debugCall32<>, 32)
  1167DEBUG_CALL_FN(debugCall64<>, 64)
  1168DEBUG_CALL_FN(debugCall128<>, 128)
  1169DEBUG_CALL_FN(debugCall256<>, 256)
  1170DEBUG_CALL_FN(debugCall512<>, 512)
  1171DEBUG_CALL_FN(debugCall1024<>, 1024)
  1172DEBUG_CALL_FN(debugCall2048<>, 2048)
  1173DEBUG_CALL_FN(debugCall4096<>, 4096)
  1174DEBUG_CALL_FN(debugCall8192<>, 8192)
  1175DEBUG_CALL_FN(debugCall16384<>, 16384)
  1176DEBUG_CALL_FN(debugCall32768<>, 32768)
  1177DEBUG_CALL_FN(debugCall65536<>, 65536)
  1178
  1179// func debugCallPanicked(val interface{})
  1180TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16
  1181	// Copy the panic value to the top of stack at SP+8.
  1182	MOVV    val_type+0(FP), R30
  1183	MOVV    R30, 8(R3)
  1184	MOVV    val_data+8(FP), R30
  1185	MOVV    R30, 16(R3)
  1186	MOVV    $2, R19
  1187	BREAK
  1188	RET
  1189
  1190TEXT runtime·panicBounds<ABIInternal>(SB),NOSPLIT,$144-0
  1191	NO_LOCAL_POINTERS
  1192	// Save all 16 int registers that could have an index in them.
  1193	// They may be pointers, but if they are they are dead.
  1194	// Skip R0 aka ZERO, R1 aka LR, R2 aka thread pointer, R3 aka SP.
  1195	MOVV	R4, 24(R3)
  1196	MOVV	R5, 32(R3)
  1197	MOVV	R6, 40(R3)
  1198	MOVV	R7, 48(R3)
  1199	MOVV	R8, 56(R3)
  1200	MOVV	R9, 64(R3)
  1201	MOVV	R10, 72(R3)
  1202	MOVV	R11, 80(R3)
  1203	MOVV	R12, 88(R3)
  1204	MOVV	R13, 96(R3)
  1205	MOVV	R14, 104(R3)
  1206	MOVV	R15, 112(R3)
  1207	MOVV	R16, 120(R3)
  1208	MOVV	R17, 128(R3)
  1209	MOVV	R18, 136(R3)
  1210	MOVV	R19, 144(R3)
  1211
  1212	MOVV	R1, R4		// PC immediately after call to panicBounds
  1213	ADDV	$24, R3, R5	// pointer to save area
  1214	CALL	runtime·panicBounds64<ABIInternal>(SB)
  1215	RET

View as plain text