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