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