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