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