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