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