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