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