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