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