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