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