Text file
src/runtime/asm_ppc64x.s
1 // Copyright 2014 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 ppc64 || ppc64le
6
7 #include "go_asm.h"
8 #include "go_tls.h"
9 #include "funcdata.h"
10 #include "textflag.h"
11 #include "asm_ppc64x.h"
12
13 #ifdef GOOS_aix
14 #define cgoCalleeStackSize 48
15 #else
16 #define cgoCalleeStackSize 32
17 #endif
18
19 TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
20 // R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
21
22 // initialize essential registers
23 BL runtime·reginit(SB)
24
25 SUB $(FIXED_FRAME+16), R1
26 MOVD R2, 24(R1) // stash the TOC pointer away again now we've created a new frame
27 MOVW R3, FIXED_FRAME+0(R1) // argc
28 MOVD R4, FIXED_FRAME+8(R1) // argv
29
30 // create istack out of the given (operating system) stack.
31 // _cgo_init may update stackguard.
32 MOVD $runtime·g0(SB), g
33 BL runtime·save_g(SB)
34 MOVD $(-64*1024), R31
35 ADD R31, R1, R3
36 MOVD R3, g_stackguard0(g)
37 MOVD R3, g_stackguard1(g)
38 MOVD R3, (g_stack+stack_lo)(g)
39 MOVD R1, (g_stack+stack_hi)(g)
40
41 // if there is a _cgo_init, call it using the gcc ABI.
42 MOVD _cgo_init(SB), R12
43 CMP R0, R12
44 BEQ nocgo
45 #ifdef GOARCH_ppc64
46 // ppc64 use elf ABI v1. we must get the real entry address from
47 // first slot of the function descriptor before call.
48 MOVD 8(R12), R2
49 MOVD (R12), R12
50 #endif
51 MOVD R12, CTR // r12 = "global function entry point"
52 MOVD R13, R5 // arg 2: TLS base pointer
53 MOVD $setg_gcc<>(SB), R4 // arg 1: setg
54 MOVD g, R3 // arg 0: G
55 // C functions expect 32 (48 for AIX) bytes of space on caller
56 // stack frame and a 16-byte aligned R1
57 MOVD R1, R14 // save current stack
58 SUB $cgoCalleeStackSize, R1 // reserve the callee area
59 RLDCR $0, R1, $~15, R1 // 16-byte align
60 BL (CTR) // may clobber R0, R3-R12
61 MOVD R14, R1 // restore stack
62 #ifndef GOOS_aix
63 MOVD 24(R1), R2
64 #endif
65 XOR R0, R0 // fix R0
66
67 nocgo:
68 // update stackguard after _cgo_init
69 MOVD (g_stack+stack_lo)(g), R3
70 ADD $const__StackGuard, R3
71 MOVD R3, g_stackguard0(g)
72 MOVD R3, g_stackguard1(g)
73
74 // set the per-goroutine and per-mach "registers"
75 MOVD $runtime·m0(SB), R3
76
77 // save m->g0 = g0
78 MOVD g, m_g0(R3)
79 // save m0 to g0->m
80 MOVD R3, g_m(g)
81
82 BL runtime·check(SB)
83
84 // args are already prepared
85 BL runtime·args(SB)
86 BL runtime·osinit(SB)
87 BL runtime·schedinit(SB)
88
89 // create a new goroutine to start program
90 MOVD $runtime·mainPC(SB), R3 // entry
91 MOVDU R3, -8(R1)
92 MOVDU R0, -8(R1)
93 MOVDU R0, -8(R1)
94 MOVDU R0, -8(R1)
95 MOVDU R0, -8(R1)
96 BL runtime·newproc(SB)
97 ADD $(8+FIXED_FRAME), R1
98
99 // start this M
100 BL runtime·mstart(SB)
101
102 MOVD R0, 0(R0)
103 RET
104
105 DATA runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB)
106 GLOBL runtime·mainPC(SB),RODATA,$8
107
108 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
109 TW $31, R0, R0
110 RET
111
112 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
113 RET
114
115 // Any changes must be reflected to runtime/cgo/gcc_aix_ppc64.S:.crosscall_ppc64
116 TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
117 // crosscall_ppc64 and crosscall2 need to reginit, but can't
118 // get at the 'runtime.reginit' symbol.
119 BR runtime·reginit(SB)
120
121 TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
122 // set R0 to zero, it's expected by the toolchain
123 XOR R0, R0
124 RET
125
126 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
127 BL runtime·mstart0(SB)
128 RET // not reached
129
130 /*
131 * go-routine
132 */
133
134 // void gogo(Gobuf*)
135 // restore state from Gobuf; longjmp
136 TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
137 MOVD buf+0(FP), R5
138 MOVD gobuf_g(R5), R6
139 MOVD 0(R6), R4 // make sure g != nil
140 BR gogo<>(SB)
141
142 TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
143 MOVD R6, g
144 BL runtime·save_g(SB)
145
146 MOVD gobuf_sp(R5), R1
147 MOVD gobuf_lr(R5), R31
148 #ifndef GOOS_aix
149 MOVD 24(R1), R2 // restore R2
150 #endif
151 MOVD R31, LR
152 MOVD gobuf_ret(R5), R3
153 MOVD gobuf_ctxt(R5), R11
154 MOVD R0, gobuf_sp(R5)
155 MOVD R0, gobuf_ret(R5)
156 MOVD R0, gobuf_lr(R5)
157 MOVD R0, gobuf_ctxt(R5)
158 CMP R0, R0 // set condition codes for == test, needed by stack split
159 MOVD gobuf_pc(R5), R12
160 MOVD R12, CTR
161 BR (CTR)
162
163 // void mcall(fn func(*g))
164 // Switch to m->g0's stack, call fn(g).
165 // Fn must never return. It should gogo(&g->sched)
166 // to keep running g.
167 TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8
168 // Save caller state in g->sched
169 // R11 should be safe across save_g??
170 MOVD R3, R11
171 MOVD R1, (g_sched+gobuf_sp)(g)
172 MOVD LR, R31
173 MOVD R31, (g_sched+gobuf_pc)(g)
174 MOVD R0, (g_sched+gobuf_lr)(g)
175
176 // Switch to m->g0 & its stack, call fn.
177 MOVD g, R3
178 MOVD g_m(g), R8
179 MOVD m_g0(R8), g
180 BL runtime·save_g(SB)
181 CMP g, R3
182 BNE 2(PC)
183 BR runtime·badmcall(SB)
184 MOVD 0(R11), R12 // code pointer
185 MOVD R12, CTR
186 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
187 // Don't need to do anything special for regabiargs here
188 // R3 is g; stack is set anyway
189 MOVDU R3, -8(R1)
190 MOVDU R0, -8(R1)
191 MOVDU R0, -8(R1)
192 MOVDU R0, -8(R1)
193 MOVDU R0, -8(R1)
194 BL (CTR)
195 MOVD 24(R1), R2
196 BR runtime·badmcall2(SB)
197
198 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
199 // of the G stack. We need to distinguish the routine that
200 // lives at the bottom of the G stack from the one that lives
201 // at the top of the system stack because the one at the top of
202 // the system stack terminates the stack walk (see topofstack()).
203 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
204 // We have several undefs here so that 16 bytes past
205 // $runtime·systemstack_switch lies within them whether or not the
206 // instructions that derive r2 from r12 are there.
207 UNDEF
208 UNDEF
209 UNDEF
210 BL (LR) // make sure this function is not leaf
211 RET
212
213 // func systemstack(fn func())
214 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
215 MOVD fn+0(FP), R3 // R3 = fn
216 MOVD R3, R11 // context
217 MOVD g_m(g), R4 // R4 = m
218
219 MOVD m_gsignal(R4), R5 // R5 = gsignal
220 CMP g, R5
221 BEQ noswitch
222
223 MOVD m_g0(R4), R5 // R5 = g0
224 CMP g, R5
225 BEQ noswitch
226
227 MOVD m_curg(R4), R6
228 CMP g, R6
229 BEQ switch
230
231 // Bad: g is not gsignal, not g0, not curg. What is it?
232 // Hide call from linker nosplit analysis.
233 MOVD $runtime·badsystemstack(SB), R12
234 MOVD R12, CTR
235 BL (CTR)
236 BL runtime·abort(SB)
237
238 switch:
239 // save our state in g->sched. Pretend to
240 // be systemstack_switch if the G stack is scanned.
241 BL gosave_systemstack_switch<>(SB)
242
243 // switch to g0
244 MOVD R5, g
245 BL runtime·save_g(SB)
246 MOVD (g_sched+gobuf_sp)(g), R1
247
248 // call target function
249 MOVD 0(R11), R12 // code pointer
250 MOVD R12, CTR
251 BL (CTR)
252
253 // restore TOC pointer. It seems unlikely that we will use systemstack
254 // to call a function defined in another module, but the results of
255 // doing so would be so confusing that it's worth doing this.
256 MOVD g_m(g), R3
257 MOVD m_curg(R3), g
258 MOVD (g_sched+gobuf_sp)(g), R3
259 #ifndef GOOS_aix
260 MOVD 24(R3), R2
261 #endif
262 // switch back to g
263 MOVD g_m(g), R3
264 MOVD m_curg(R3), g
265 BL runtime·save_g(SB)
266 MOVD (g_sched+gobuf_sp)(g), R1
267 MOVD R0, (g_sched+gobuf_sp)(g)
268 RET
269
270 noswitch:
271 // already on m stack, just call directly
272 // On other arches we do a tail call here, but it appears to be
273 // impossible to tail call a function pointer in shared mode on
274 // ppc64 because the caller is responsible for restoring the TOC.
275 MOVD 0(R11), R12 // code pointer
276 MOVD R12, CTR
277 BL (CTR)
278 #ifndef GOOS_aix
279 MOVD 24(R1), R2
280 #endif
281 RET
282
283 /*
284 * support for morestack
285 */
286
287 // Called during function prolog when more stack is needed.
288 // Caller has already loaded:
289 // R3: framesize, R4: argsize, R5: LR
290 //
291 // The traceback routines see morestack on a g0 as being
292 // the top of a stack (for example, morestack calling newstack
293 // calling the scheduler calling newm calling gc), so we must
294 // record an argument size. For that purpose, it has no arguments.
295 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
296 // Cannot grow scheduler stack (m->g0).
297 MOVD g_m(g), R7
298 MOVD m_g0(R7), R8
299 CMP g, R8
300 BNE 3(PC)
301 BL runtime·badmorestackg0(SB)
302 BL runtime·abort(SB)
303
304 // Cannot grow signal stack (m->gsignal).
305 MOVD m_gsignal(R7), R8
306 CMP g, R8
307 BNE 3(PC)
308 BL runtime·badmorestackgsignal(SB)
309 BL runtime·abort(SB)
310
311 // Called from f.
312 // Set g->sched to context in f.
313 MOVD R1, (g_sched+gobuf_sp)(g)
314 MOVD LR, R8
315 MOVD R8, (g_sched+gobuf_pc)(g)
316 MOVD R5, (g_sched+gobuf_lr)(g)
317 MOVD R11, (g_sched+gobuf_ctxt)(g)
318
319 // Called from f.
320 // Set m->morebuf to f's caller.
321 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
322 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
323 MOVD g, (m_morebuf+gobuf_g)(R7)
324
325 // Call newstack on m->g0's stack.
326 MOVD m_g0(R7), g
327 BL runtime·save_g(SB)
328 MOVD (g_sched+gobuf_sp)(g), R1
329 MOVDU R0, -(FIXED_FRAME+0)(R1) // create a call frame on g0
330 BL runtime·newstack(SB)
331
332 // Not reached, but make sure the return PC from the call to newstack
333 // is still in this function, and not the beginning of the next.
334 UNDEF
335
336 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
337 // Force SPWRITE. This function doesn't actually write SP,
338 // but it is called with a special calling convention where
339 // the caller doesn't save LR on stack but passes it as a
340 // register (R5), and the unwinder currently doesn't understand.
341 // Make it SPWRITE to stop unwinding. (See issue 54332)
342 // Use OR R0, R1 instead of MOVD R1, R1 as the MOVD instruction
343 // has a special affect on Power8,9,10 by lowering the thread
344 // priority and causing a slowdown in execution time
345
346 OR R0, R1
347 MOVD R0, R11
348 BR runtime·morestack(SB)
349
350 // reflectcall: call a function with the given argument list
351 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
352 // we don't have variable-sized frames, so we use a small number
353 // of constant-sized-frame functions to encode a few bits of size in the pc.
354 // Caution: ugly multiline assembly macros in your future!
355
356 #define DISPATCH(NAME,MAXSIZE) \
357 MOVD $MAXSIZE, R31; \
358 CMP R3, R31; \
359 BGT 4(PC); \
360 MOVD $NAME(SB), R12; \
361 MOVD R12, CTR; \
362 BR (CTR)
363 // Note: can't just "BR NAME(SB)" - bad inlining results.
364
365 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
366 MOVWZ frameSize+32(FP), R3
367 DISPATCH(runtime·call16, 16)
368 DISPATCH(runtime·call32, 32)
369 DISPATCH(runtime·call64, 64)
370 DISPATCH(runtime·call128, 128)
371 DISPATCH(runtime·call256, 256)
372 DISPATCH(runtime·call512, 512)
373 DISPATCH(runtime·call1024, 1024)
374 DISPATCH(runtime·call2048, 2048)
375 DISPATCH(runtime·call4096, 4096)
376 DISPATCH(runtime·call8192, 8192)
377 DISPATCH(runtime·call16384, 16384)
378 DISPATCH(runtime·call32768, 32768)
379 DISPATCH(runtime·call65536, 65536)
380 DISPATCH(runtime·call131072, 131072)
381 DISPATCH(runtime·call262144, 262144)
382 DISPATCH(runtime·call524288, 524288)
383 DISPATCH(runtime·call1048576, 1048576)
384 DISPATCH(runtime·call2097152, 2097152)
385 DISPATCH(runtime·call4194304, 4194304)
386 DISPATCH(runtime·call8388608, 8388608)
387 DISPATCH(runtime·call16777216, 16777216)
388 DISPATCH(runtime·call33554432, 33554432)
389 DISPATCH(runtime·call67108864, 67108864)
390 DISPATCH(runtime·call134217728, 134217728)
391 DISPATCH(runtime·call268435456, 268435456)
392 DISPATCH(runtime·call536870912, 536870912)
393 DISPATCH(runtime·call1073741824, 1073741824)
394 MOVD $runtime·badreflectcall(SB), R12
395 MOVD R12, CTR
396 BR (CTR)
397
398 #define CALLFN(NAME,MAXSIZE) \
399 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \
400 NO_LOCAL_POINTERS; \
401 /* copy arguments to stack */ \
402 MOVD stackArgs+16(FP), R3; \
403 MOVWZ stackArgsSize+24(FP), R4; \
404 MOVD R1, R5; \
405 CMP R4, $8; \
406 BLT tailsetup; \
407 /* copy 8 at a time if possible */ \
408 ADD $(FIXED_FRAME-8), R5; \
409 SUB $8, R3; \
410 top: \
411 MOVDU 8(R3), R7; \
412 MOVDU R7, 8(R5); \
413 SUB $8, R4; \
414 CMP R4, $8; \
415 BGE top; \
416 /* handle remaining bytes */ \
417 CMP $0, R4; \
418 BEQ callfn; \
419 ADD $7, R3; \
420 ADD $7, R5; \
421 BR tail; \
422 tailsetup: \
423 CMP $0, R4; \
424 BEQ callfn; \
425 ADD $(FIXED_FRAME-1), R5; \
426 SUB $1, R3; \
427 tail: \
428 MOVBU 1(R3), R6; \
429 MOVBU R6, 1(R5); \
430 SUB $1, R4; \
431 CMP $0, R4; \
432 BGT tail; \
433 callfn: \
434 /* call function */ \
435 MOVD f+8(FP), R11; \
436 #ifdef GOOS_aix \
437 /* AIX won't trigger a SIGSEGV if R11 = nil */ \
438 /* So it manually triggers it */ \
439 CMP R0, R11 \
440 BNE 2(PC) \
441 MOVD R0, 0(R0) \
442 #endif \
443 MOVD regArgs+40(FP), R20; \
444 BL runtime·unspillArgs(SB); \
445 MOVD (R11), R12; \
446 MOVD R12, CTR; \
447 PCDATA $PCDATA_StackMapIndex, $0; \
448 BL (CTR); \
449 #ifndef GOOS_aix \
450 MOVD 24(R1), R2; \
451 #endif \
452 /* copy return values back */ \
453 MOVD regArgs+40(FP), R20; \
454 BL runtime·spillArgs(SB); \
455 MOVD stackArgsType+0(FP), R7; \
456 MOVD stackArgs+16(FP), R3; \
457 MOVWZ stackArgsSize+24(FP), R4; \
458 MOVWZ stackRetOffset+28(FP), R6; \
459 ADD $FIXED_FRAME, R1, R5; \
460 ADD R6, R5; \
461 ADD R6, R3; \
462 SUB R6, R4; \
463 BL callRet<>(SB); \
464 RET
465
466 // callRet copies return values back at the end of call*. This is a
467 // separate function so it can allocate stack space for the arguments
468 // to reflectcallmove. It does not follow the Go ABI; it expects its
469 // arguments in registers.
470 TEXT callRet<>(SB), NOSPLIT, $40-0
471 NO_LOCAL_POINTERS
472 MOVD R7, FIXED_FRAME+0(R1)
473 MOVD R3, FIXED_FRAME+8(R1)
474 MOVD R5, FIXED_FRAME+16(R1)
475 MOVD R4, FIXED_FRAME+24(R1)
476 MOVD R20, FIXED_FRAME+32(R1)
477 BL runtime·reflectcallmove(SB)
478 RET
479
480 CALLFN(·call16, 16)
481 CALLFN(·call32, 32)
482 CALLFN(·call64, 64)
483 CALLFN(·call128, 128)
484 CALLFN(·call256, 256)
485 CALLFN(·call512, 512)
486 CALLFN(·call1024, 1024)
487 CALLFN(·call2048, 2048)
488 CALLFN(·call4096, 4096)
489 CALLFN(·call8192, 8192)
490 CALLFN(·call16384, 16384)
491 CALLFN(·call32768, 32768)
492 CALLFN(·call65536, 65536)
493 CALLFN(·call131072, 131072)
494 CALLFN(·call262144, 262144)
495 CALLFN(·call524288, 524288)
496 CALLFN(·call1048576, 1048576)
497 CALLFN(·call2097152, 2097152)
498 CALLFN(·call4194304, 4194304)
499 CALLFN(·call8388608, 8388608)
500 CALLFN(·call16777216, 16777216)
501 CALLFN(·call33554432, 33554432)
502 CALLFN(·call67108864, 67108864)
503 CALLFN(·call134217728, 134217728)
504 CALLFN(·call268435456, 268435456)
505 CALLFN(·call536870912, 536870912)
506 CALLFN(·call1073741824, 1073741824)
507
508 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
509 MOVW cycles+0(FP), R7
510 // POWER does not have a pause/yield instruction equivalent.
511 // Instead, we can lower the program priority by setting the
512 // Program Priority Register prior to the wait loop and set it
513 // back to default afterwards. On Linux, the default priority is
514 // medium-low. For details, see page 837 of the ISA 3.0.
515 OR R1, R1, R1 // Set PPR priority to low
516 again:
517 SUB $1, R7
518 CMP $0, R7
519 BNE again
520 OR R6, R6, R6 // Set PPR priority back to medium-low
521 RET
522
523 // Save state of caller into g->sched,
524 // but using fake PC from systemstack_switch.
525 // Must only be called from functions with no locals ($0)
526 // or else unwinding from systemstack_switch is incorrect.
527 // Smashes R31.
528 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
529 MOVD $runtime·systemstack_switch(SB), R31
530 ADD $16, R31 // get past prologue (including r2-setting instructions when they're there)
531 MOVD R31, (g_sched+gobuf_pc)(g)
532 MOVD R1, (g_sched+gobuf_sp)(g)
533 MOVD R0, (g_sched+gobuf_lr)(g)
534 MOVD R0, (g_sched+gobuf_ret)(g)
535 // Assert ctxt is zero. See func save.
536 MOVD (g_sched+gobuf_ctxt)(g), R31
537 CMP R0, R31
538 BEQ 2(PC)
539 BL runtime·abort(SB)
540 RET
541
542 #ifdef GOOS_aix
543 #define asmcgocallSaveOffset cgoCalleeStackSize + 8
544 #else
545 #define asmcgocallSaveOffset cgoCalleeStackSize
546 #endif
547
548 // func asmcgocall(fn, arg unsafe.Pointer) int32
549 // Call fn(arg) on the scheduler stack,
550 // aligned appropriately for the gcc ABI.
551 // See cgocall.go for more details.
552 TEXT ·asmcgocall(SB),NOSPLIT,$0-20
553 MOVD fn+0(FP), R3
554 MOVD arg+8(FP), R4
555
556 MOVD R1, R7 // save original stack pointer
557 MOVD g, R5
558
559 // Figure out if we need to switch to m->g0 stack.
560 // We get called to create new OS threads too, and those
561 // come in on the m->g0 stack already. Or we might already
562 // be on the m->gsignal stack.
563 MOVD g_m(g), R8
564 MOVD m_gsignal(R8), R6
565 CMP R6, g
566 BEQ g0
567 MOVD m_g0(R8), R6
568 CMP R6, g
569 BEQ g0
570 BL gosave_systemstack_switch<>(SB)
571 MOVD R6, g
572 BL runtime·save_g(SB)
573 MOVD (g_sched+gobuf_sp)(g), R1
574
575 // Now on a scheduling stack (a pthread-created stack).
576 g0:
577 #ifdef GOOS_aix
578 // Create a fake LR to improve backtrace.
579 MOVD $runtime·asmcgocall(SB), R6
580 MOVD R6, 16(R1)
581 // AIX also save one argument on the stack.
582 SUB $8, R1
583 #endif
584 // Save room for two of our pointers, plus the callee
585 // save area that lives on the caller stack.
586 SUB $(asmcgocallSaveOffset+16), R1
587 RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI
588 MOVD R5, (asmcgocallSaveOffset+8)(R1)// save old g on stack
589 MOVD (g_stack+stack_hi)(R5), R5
590 SUB R7, R5
591 MOVD R5, asmcgocallSaveOffset(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
592 #ifdef GOOS_aix
593 MOVD R7, 0(R1) // Save frame pointer to allow manual backtrace with gdb
594 #else
595 MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?)
596 #endif
597 // This is a "global call", so put the global entry point in r12
598 MOVD R3, R12
599
600 #ifdef GOARCH_ppc64
601 // ppc64 use elf ABI v1. we must get the real entry address from
602 // first slot of the function descriptor before call.
603 // Same for AIX.
604 MOVD 8(R12), R2
605 MOVD (R12), R12
606 #endif
607 MOVD R12, CTR
608 MOVD R4, R3 // arg in r3
609 BL (CTR)
610 // C code can clobber R0, so set it back to 0. F27-F31 are
611 // callee save, so we don't need to recover those.
612 XOR R0, R0
613 // Restore g, stack pointer, toc pointer.
614 // R3 is errno, so don't touch it
615 MOVD (asmcgocallSaveOffset+8)(R1), g
616 MOVD (g_stack+stack_hi)(g), R5
617 MOVD asmcgocallSaveOffset(R1), R6
618 SUB R6, R5
619 #ifndef GOOS_aix
620 MOVD 24(R5), R2
621 #endif
622 MOVD R5, R1
623 BL runtime·save_g(SB)
624
625 MOVW R3, ret+16(FP)
626 RET
627
628 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
629 // See cgocall.go for more details.
630 TEXT ·cgocallback(SB),NOSPLIT,$24-24
631 NO_LOCAL_POINTERS
632
633 // Load m and g from thread-local storage.
634 MOVBZ runtime·iscgo(SB), R3
635 CMP R3, $0
636 BEQ nocgo
637 BL runtime·load_g(SB)
638 nocgo:
639
640 // If g is nil, Go did not create the current thread.
641 // Call needm to obtain one for temporary use.
642 // In this case, we're running on the thread stack, so there's
643 // lots of space, but the linker doesn't know. Hide the call from
644 // the linker analysis by using an indirect call.
645 CMP g, $0
646 BEQ needm
647
648 MOVD g_m(g), R8
649 MOVD R8, savedm-8(SP)
650 BR havem
651
652 needm:
653 MOVD g, savedm-8(SP) // g is zero, so is m.
654 MOVD $runtime·needm(SB), R12
655 MOVD R12, CTR
656 BL (CTR)
657
658 // Set m->sched.sp = SP, so that if a panic happens
659 // during the function we are about to execute, it will
660 // have a valid SP to run on the g0 stack.
661 // The next few lines (after the havem label)
662 // will save this SP onto the stack and then write
663 // the same SP back to m->sched.sp. That seems redundant,
664 // but if an unrecovered panic happens, unwindm will
665 // restore the g->sched.sp from the stack location
666 // and then systemstack will try to use it. If we don't set it here,
667 // that restored SP will be uninitialized (typically 0) and
668 // will not be usable.
669 MOVD g_m(g), R8
670 MOVD m_g0(R8), R3
671 MOVD R1, (g_sched+gobuf_sp)(R3)
672
673 havem:
674 // Now there's a valid m, and we're running on its m->g0.
675 // Save current m->g0->sched.sp on stack and then set it to SP.
676 // Save current sp in m->g0->sched.sp in preparation for
677 // switch back to m->curg stack.
678 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
679 MOVD m_g0(R8), R3
680 MOVD (g_sched+gobuf_sp)(R3), R4
681 MOVD R4, savedsp-24(SP) // must match frame size
682 MOVD R1, (g_sched+gobuf_sp)(R3)
683
684 // Switch to m->curg stack and call runtime.cgocallbackg.
685 // Because we are taking over the execution of m->curg
686 // but *not* resuming what had been running, we need to
687 // save that information (m->curg->sched) so we can restore it.
688 // We can restore m->curg->sched.sp easily, because calling
689 // runtime.cgocallbackg leaves SP unchanged upon return.
690 // To save m->curg->sched.pc, we push it onto the curg stack and
691 // open a frame the same size as cgocallback's g0 frame.
692 // Once we switch to the curg stack, the pushed PC will appear
693 // to be the return PC of cgocallback, so that the traceback
694 // will seamlessly trace back into the earlier calls.
695 MOVD m_curg(R8), g
696 BL runtime·save_g(SB)
697 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4
698 MOVD (g_sched+gobuf_pc)(g), R5
699 MOVD R5, -(24+FIXED_FRAME)(R4) // "saved LR"; must match frame size
700 // Gather our arguments into registers.
701 MOVD fn+0(FP), R5
702 MOVD frame+8(FP), R6
703 MOVD ctxt+16(FP), R7
704 MOVD $-(24+FIXED_FRAME)(R4), R1 // switch stack; must match frame size
705 MOVD R5, FIXED_FRAME+0(R1)
706 MOVD R6, FIXED_FRAME+8(R1)
707 MOVD R7, FIXED_FRAME+16(R1)
708
709 MOVD $runtime·cgocallbackg(SB), R12
710 MOVD R12, CTR
711 CALL (CTR) // indirect call to bypass nosplit check. We're on a different stack now.
712
713 // Restore g->sched (== m->curg->sched) from saved values.
714 MOVD 0(R1), R5
715 MOVD R5, (g_sched+gobuf_pc)(g)
716 MOVD $(24+FIXED_FRAME)(R1), R4 // must match frame size
717 MOVD R4, (g_sched+gobuf_sp)(g)
718
719 // Switch back to m->g0's stack and restore m->g0->sched.sp.
720 // (Unlike m->curg, the g0 goroutine never uses sched.pc,
721 // so we do not have to restore it.)
722 MOVD g_m(g), R8
723 MOVD m_g0(R8), g
724 BL runtime·save_g(SB)
725 MOVD (g_sched+gobuf_sp)(g), R1
726 MOVD savedsp-24(SP), R4 // must match frame size
727 MOVD R4, (g_sched+gobuf_sp)(g)
728
729 // If the m on entry was nil, we called needm above to borrow an m
730 // for the duration of the call. Since the call is over, return it with dropm.
731 MOVD savedm-8(SP), R6
732 CMP R6, $0
733 BNE droppedm
734 MOVD $runtime·dropm(SB), R12
735 MOVD R12, CTR
736 BL (CTR)
737 droppedm:
738
739 // Done!
740 RET
741
742 // void setg(G*); set g. for use by needm.
743 TEXT runtime·setg(SB), NOSPLIT, $0-8
744 MOVD gg+0(FP), g
745 // This only happens if iscgo, so jump straight to save_g
746 BL runtime·save_g(SB)
747 RET
748
749 #ifdef GOARCH_ppc64
750 #ifdef GOOS_aix
751 DATA setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB)
752 DATA setg_gcc<>+8(SB)/8, $TOC(SB)
753 DATA setg_gcc<>+16(SB)/8, $0
754 GLOBL setg_gcc<>(SB), NOPTR, $24
755 #else
756 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
757 DWORD $_setg_gcc<>(SB)
758 DWORD $0
759 DWORD $0
760 #endif
761 #endif
762
763 // void setg_gcc(G*); set g in C TLS.
764 // Must obey the gcc calling convention.
765 #ifdef GOARCH_ppc64le
766 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
767 #else
768 TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
769 #endif
770 // The standard prologue clobbers R31, which is callee-save in
771 // the C ABI, so we have to use $-8-0 and save LR ourselves.
772 MOVD LR, R4
773 // Also save g and R31, since they're callee-save in C ABI
774 MOVD R31, R5
775 MOVD g, R6
776
777 MOVD R3, g
778 BL runtime·save_g(SB)
779
780 MOVD R6, g
781 MOVD R5, R31
782 MOVD R4, LR
783 RET
784
785 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
786 MOVW (R0), R0
787 UNDEF
788
789 #define TBR 268
790
791 // int64 runtime·cputicks(void)
792 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
793 MOVD SPR(TBR), R3
794 MOVD R3, ret+0(FP)
795 RET
796
797 // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
798 TEXT runtime·spillArgs(SB),NOSPLIT,$0-0
799 MOVD R3, 0(R20)
800 MOVD R4, 8(R20)
801 MOVD R5, 16(R20)
802 MOVD R6, 24(R20)
803 MOVD R7, 32(R20)
804 MOVD R8, 40(R20)
805 MOVD R9, 48(R20)
806 MOVD R10, 56(R20)
807 MOVD R14, 64(R20)
808 MOVD R15, 72(R20)
809 MOVD R16, 80(R20)
810 MOVD R17, 88(R20)
811 FMOVD F1, 96(R20)
812 FMOVD F2, 104(R20)
813 FMOVD F3, 112(R20)
814 FMOVD F4, 120(R20)
815 FMOVD F5, 128(R20)
816 FMOVD F6, 136(R20)
817 FMOVD F7, 144(R20)
818 FMOVD F8, 152(R20)
819 FMOVD F9, 160(R20)
820 FMOVD F10, 168(R20)
821 FMOVD F11, 176(R20)
822 FMOVD F12, 184(R20)
823 RET
824
825 // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
826 TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0
827 MOVD 0(R20), R3
828 MOVD 8(R20), R4
829 MOVD 16(R20), R5
830 MOVD 24(R20), R6
831 MOVD 32(R20), R7
832 MOVD 40(R20), R8
833 MOVD 48(R20), R9
834 MOVD 56(R20), R10
835 MOVD 64(R20), R14
836 MOVD 72(R20), R15
837 MOVD 80(R20), R16
838 MOVD 88(R20), R17
839 FMOVD 96(R20), F1
840 FMOVD 104(R20), F2
841 FMOVD 112(R20), F3
842 FMOVD 120(R20), F4
843 FMOVD 128(R20), F5
844 FMOVD 136(R20), F6
845 FMOVD 144(R20), F7
846 FMOVD 152(R20), F8
847 FMOVD 160(R20), F9
848 FMOVD 168(R20), F10
849 FMOVD 176(R20), F11
850 FMOVD 184(R20), F12
851 RET
852
853 // AES hashing not implemented for ppc64
854 TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
855 JMP runtime·memhashFallback<ABIInternal>(SB)
856 TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
857 JMP runtime·strhashFallback<ABIInternal>(SB)
858 TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
859 JMP runtime·memhash32Fallback<ABIInternal>(SB)
860 TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
861 JMP runtime·memhash64Fallback<ABIInternal>(SB)
862
863 TEXT runtime·return0(SB), NOSPLIT, $0
864 MOVW $0, R3
865 RET
866
867 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
868 // Must obey the gcc calling convention.
869 #ifdef GOOS_aix
870 // On AIX, _cgo_topofstack is defined in runtime/cgo, because it must
871 // be a longcall in order to prevent trampolines from ld.
872 TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
873 #else
874 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
875 #endif
876 // g (R30) and R31 are callee-save in the C ABI, so save them
877 MOVD g, R4
878 MOVD R31, R5
879 MOVD LR, R6
880
881 BL runtime·load_g(SB) // clobbers g (R30), R31
882 MOVD g_m(g), R3
883 MOVD m_curg(R3), R3
884 MOVD (g_stack+stack_hi)(R3), R3
885
886 MOVD R4, g
887 MOVD R5, R31
888 MOVD R6, LR
889 RET
890
891 // The top-most function running on a goroutine
892 // returns to goexit+PCQuantum.
893 //
894 // When dynamically linking Go, it can be returned to from a function
895 // implemented in a different module and so needs to reload the TOC pointer
896 // from the stack (although this function declares that it does not set up x-a
897 // frame, newproc1 does in fact allocate one for goexit and saves the TOC
898 // pointer in the correct place).
899 // goexit+_PCQuantum is halfway through the usual global entry point prologue
900 // that derives r2 from r12 which is a bit silly, but not harmful.
901 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
902 MOVD 24(R1), R2
903 BL runtime·goexit1(SB) // does not return
904 // traceback from goexit1 must hit code range of goexit
905 MOVD R0, R0 // NOP
906
907 // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
908 // module containing runtime) to the frame that goexit will execute in when
909 // the goroutine exits. It's implemented in assembly mainly because that's the
910 // easiest way to get access to R2.
911 TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
912 MOVD sp+0(FP), R3
913 MOVD R2, 24(R3)
914 RET
915
916 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
917 ADD $-8, R1
918 MOVD R31, 0(R1)
919 MOVD runtime·lastmoduledatap(SB), R4
920 MOVD R3, moduledata_next(R4)
921 MOVD R3, runtime·lastmoduledatap(SB)
922 MOVD 0(R1), R31
923 ADD $8, R1
924 RET
925
926 TEXT ·checkASM(SB),NOSPLIT,$0-1
927 MOVW $1, R3
928 MOVB R3, ret+0(FP)
929 RET
930
931 // gcWriteBarrier performs a heap pointer write and informs the GC.
932 //
933 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
934 // - R20 is the destination of the write
935 // - R21 is the value being written at R20.
936 // It clobbers condition codes.
937 // It does not clobber R0 through R17 (except special registers),
938 // but may clobber any other register, *including* R31.
939 TEXT runtime·gcWriteBarrier<ABIInternal>(SB),NOSPLIT,$112
940 // The standard prologue clobbers R31.
941 // We use R18 and R19 as scratch registers.
942 MOVD g_m(g), R18
943 MOVD m_p(R18), R18
944 MOVD (p_wbBuf+wbBuf_next)(R18), R19
945 // Increment wbBuf.next position.
946 ADD $16, R19
947 MOVD R19, (p_wbBuf+wbBuf_next)(R18)
948 MOVD (p_wbBuf+wbBuf_end)(R18), R18
949 CMP R18, R19
950 // Record the write.
951 MOVD R21, -16(R19) // Record value
952 MOVD (R20), R18 // TODO: This turns bad writes into bad reads.
953 MOVD R18, -8(R19) // Record *slot
954 // Is the buffer full? (flags set in CMP above)
955 BEQ flush
956 ret:
957 // Do the write.
958 MOVD R21, (R20)
959 RET
960
961 flush:
962 // Save registers R0 through R15 since these were not saved by the caller.
963 // We don't save all registers on ppc64 because it takes too much space.
964 MOVD R20, (FIXED_FRAME+0)(R1) // Also first argument to wbBufFlush
965 MOVD R21, (FIXED_FRAME+8)(R1) // Also second argument to wbBufFlush
966 // R0 is always 0, so no need to spill.
967 // R1 is SP.
968 // R2 is SB.
969 MOVD R3, (FIXED_FRAME+16)(R1)
970 MOVD R4, (FIXED_FRAME+24)(R1)
971 MOVD R5, (FIXED_FRAME+32)(R1)
972 MOVD R6, (FIXED_FRAME+40)(R1)
973 MOVD R7, (FIXED_FRAME+48)(R1)
974 MOVD R8, (FIXED_FRAME+56)(R1)
975 MOVD R9, (FIXED_FRAME+64)(R1)
976 MOVD R10, (FIXED_FRAME+72)(R1)
977 // R11, R12 may be clobbered by external-linker-inserted trampoline
978 // R13 is REGTLS
979 MOVD R14, (FIXED_FRAME+80)(R1)
980 MOVD R15, (FIXED_FRAME+88)(R1)
981 MOVD R16, (FIXED_FRAME+96)(R1)
982 MOVD R17, (FIXED_FRAME+104)(R1)
983
984 // This takes arguments R20 and R21.
985 CALL runtime·wbBufFlush(SB)
986
987 MOVD (FIXED_FRAME+0)(R1), R20
988 MOVD (FIXED_FRAME+8)(R1), R21
989 MOVD (FIXED_FRAME+16)(R1), R3
990 MOVD (FIXED_FRAME+24)(R1), R4
991 MOVD (FIXED_FRAME+32)(R1), R5
992 MOVD (FIXED_FRAME+40)(R1), R6
993 MOVD (FIXED_FRAME+48)(R1), R7
994 MOVD (FIXED_FRAME+56)(R1), R8
995 MOVD (FIXED_FRAME+64)(R1), R9
996 MOVD (FIXED_FRAME+72)(R1), R10
997 MOVD (FIXED_FRAME+80)(R1), R14
998 MOVD (FIXED_FRAME+88)(R1), R15
999 MOVD (FIXED_FRAME+96)(R1), R16
1000 MOVD (FIXED_FRAME+104)(R1), R17
1001 JMP ret
1002
1003 // Note: these functions use a special calling convention to save generated code space.
1004 // Arguments are passed in registers, but the space for those arguments are allocated
1005 // in the caller's stack frame. These stubs write the args into that stack space and
1006 // then tail call to the corresponding runtime handler.
1007 // The tail call makes these stubs disappear in backtraces.
1008 TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16
1009 JMP runtime·goPanicIndex<ABIInternal>(SB)
1010 TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16
1011 JMP runtime·goPanicIndexU<ABIInternal>(SB)
1012 TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16
1013 MOVD R4, R3
1014 MOVD R5, R4
1015 JMP runtime·goPanicSliceAlen<ABIInternal>(SB)
1016 TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16
1017 MOVD R4, R3
1018 MOVD R5, R4
1019 JMP runtime·goPanicSliceAlenU<ABIInternal>(SB)
1020 TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16
1021 MOVD R4, R3
1022 MOVD R5, R4
1023 JMP runtime·goPanicSliceAcap<ABIInternal>(SB)
1024 TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16
1025 MOVD R4, R3
1026 MOVD R5, R4
1027 JMP runtime·goPanicSliceAcapU<ABIInternal>(SB)
1028 TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16
1029 JMP runtime·goPanicSliceB<ABIInternal>(SB)
1030 TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16
1031 JMP runtime·goPanicSliceBU<ABIInternal>(SB)
1032 TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16
1033 MOVD R5, R3
1034 MOVD R6, R4
1035 JMP runtime·goPanicSlice3Alen<ABIInternal>(SB)
1036 TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16
1037 MOVD R5, R3
1038 MOVD R6, R4
1039 JMP runtime·goPanicSlice3AlenU<ABIInternal>(SB)
1040 TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16
1041 MOVD R5, R3
1042 MOVD R6, R4
1043 JMP runtime·goPanicSlice3Acap<ABIInternal>(SB)
1044 TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16
1045 MOVD R5, R3
1046 MOVD R6, R4
1047 JMP runtime·goPanicSlice3AcapU<ABIInternal>(SB)
1048 TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16
1049 MOVD R4, R3
1050 MOVD R5, R4
1051 JMP runtime·goPanicSlice3B<ABIInternal>(SB)
1052 TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16
1053 MOVD R4, R3
1054 MOVD R5, R4
1055 JMP runtime·goPanicSlice3BU<ABIInternal>(SB)
1056 TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16
1057 JMP runtime·goPanicSlice3C<ABIInternal>(SB)
1058 TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16
1059 JMP runtime·goPanicSlice3CU<ABIInternal>(SB)
1060 TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16
1061 MOVD R5, R3
1062 MOVD R6, R4
1063 JMP runtime·goPanicSliceConvert<ABIInternal>(SB)
1064
1065 // These functions are used when internal linking cgo with external
1066 // objects compiled with the -Os on gcc. They reduce prologue/epilogue
1067 // size by deferring preservation of callee-save registers to a shared
1068 // function. These are defined in PPC64 ELFv2 2.3.3 (but also present
1069 // in ELFv1)
1070 //
1071 // These appear unused, but the linker will redirect calls to functions
1072 // like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or
1073 // runtime.elf_restgpr1 with an appropriate offset based on the number
1074 // register operations required when linking external objects which
1075 // make these calls. For GPR/FPR saves, the minimum register value is
1076 // 14, for VR it is 20.
1077 //
1078 // These are only used when linking such cgo code internally. Note, R12
1079 // and R0 may be used in different ways than regular ELF compliant
1080 // functions.
1081 TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0
1082 // R0 holds the LR of the caller's caller, R1 holds save location
1083 MOVD R14, -144(R1)
1084 MOVD R15, -136(R1)
1085 MOVD R16, -128(R1)
1086 MOVD R17, -120(R1)
1087 MOVD R18, -112(R1)
1088 MOVD R19, -104(R1)
1089 MOVD R20, -96(R1)
1090 MOVD R21, -88(R1)
1091 MOVD R22, -80(R1)
1092 MOVD R23, -72(R1)
1093 MOVD R24, -64(R1)
1094 MOVD R25, -56(R1)
1095 MOVD R26, -48(R1)
1096 MOVD R27, -40(R1)
1097 MOVD R28, -32(R1)
1098 MOVD R29, -24(R1)
1099 MOVD g, -16(R1)
1100 MOVD R31, -8(R1)
1101 MOVD R0, 16(R1)
1102 RET
1103 TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0
1104 // R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
1105 MOVD -144(R1), R14
1106 MOVD -136(R1), R15
1107 MOVD -128(R1), R16
1108 MOVD -120(R1), R17
1109 MOVD -112(R1), R18
1110 MOVD -104(R1), R19
1111 MOVD -96(R1), R20
1112 MOVD -88(R1), R21
1113 MOVD -80(R1), R22
1114 MOVD -72(R1), R23
1115 MOVD -64(R1), R24
1116 MOVD -56(R1), R25
1117 MOVD -48(R1), R26
1118 MOVD -40(R1), R27
1119 MOVD -32(R1), R28
1120 MOVD -24(R1), R29
1121 MOVD -16(R1), g
1122 MOVD -8(R1), R31
1123 MOVD 16(R1), R0 // Load and return to saved LR
1124 MOVD R0, LR
1125 RET
1126 TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0
1127 // R12 holds the save location
1128 MOVD R14, -144(R12)
1129 MOVD R15, -136(R12)
1130 MOVD R16, -128(R12)
1131 MOVD R17, -120(R12)
1132 MOVD R18, -112(R12)
1133 MOVD R19, -104(R12)
1134 MOVD R20, -96(R12)
1135 MOVD R21, -88(R12)
1136 MOVD R22, -80(R12)
1137 MOVD R23, -72(R12)
1138 MOVD R24, -64(R12)
1139 MOVD R25, -56(R12)
1140 MOVD R26, -48(R12)
1141 MOVD R27, -40(R12)
1142 MOVD R28, -32(R12)
1143 MOVD R29, -24(R12)
1144 MOVD g, -16(R12)
1145 MOVD R31, -8(R12)
1146 RET
1147 TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0
1148 // R12 holds the save location
1149 MOVD -144(R12), R14
1150 MOVD -136(R12), R15
1151 MOVD -128(R12), R16
1152 MOVD -120(R12), R17
1153 MOVD -112(R12), R18
1154 MOVD -104(R12), R19
1155 MOVD -96(R12), R20
1156 MOVD -88(R12), R21
1157 MOVD -80(R12), R22
1158 MOVD -72(R12), R23
1159 MOVD -64(R12), R24
1160 MOVD -56(R12), R25
1161 MOVD -48(R12), R26
1162 MOVD -40(R12), R27
1163 MOVD -32(R12), R28
1164 MOVD -24(R12), R29
1165 MOVD -16(R12), g
1166 MOVD -8(R12), R31
1167 RET
1168 TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0
1169 // R0 holds the LR of the caller's caller, R1 holds save location
1170 FMOVD F14, -144(R1)
1171 FMOVD F15, -136(R1)
1172 FMOVD F16, -128(R1)
1173 FMOVD F17, -120(R1)
1174 FMOVD F18, -112(R1)
1175 FMOVD F19, -104(R1)
1176 FMOVD F20, -96(R1)
1177 FMOVD F21, -88(R1)
1178 FMOVD F22, -80(R1)
1179 FMOVD F23, -72(R1)
1180 FMOVD F24, -64(R1)
1181 FMOVD F25, -56(R1)
1182 FMOVD F26, -48(R1)
1183 FMOVD F27, -40(R1)
1184 FMOVD F28, -32(R1)
1185 FMOVD F29, -24(R1)
1186 FMOVD F30, -16(R1)
1187 FMOVD F31, -8(R1)
1188 MOVD R0, 16(R1)
1189 RET
1190 TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0
1191 // R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
1192 FMOVD -144(R1), F14
1193 FMOVD -136(R1), F15
1194 FMOVD -128(R1), F16
1195 FMOVD -120(R1), F17
1196 FMOVD -112(R1), F18
1197 FMOVD -104(R1), F19
1198 FMOVD -96(R1), F20
1199 FMOVD -88(R1), F21
1200 FMOVD -80(R1), F22
1201 FMOVD -72(R1), F23
1202 FMOVD -64(R1), F24
1203 FMOVD -56(R1), F25
1204 FMOVD -48(R1), F26
1205 FMOVD -40(R1), F27
1206 FMOVD -32(R1), F28
1207 FMOVD -24(R1), F29
1208 FMOVD -16(R1), F30
1209 FMOVD -8(R1), F31
1210 MOVD 16(R1), R0 // Load and return to saved LR
1211 MOVD R0, LR
1212 RET
1213 TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0
1214 // R0 holds the save location, R12 is clobbered
1215 MOVD $-192, R12
1216 STVX V20, (R0+R12)
1217 MOVD $-176, R12
1218 STVX V21, (R0+R12)
1219 MOVD $-160, R12
1220 STVX V22, (R0+R12)
1221 MOVD $-144, R12
1222 STVX V23, (R0+R12)
1223 MOVD $-128, R12
1224 STVX V24, (R0+R12)
1225 MOVD $-112, R12
1226 STVX V25, (R0+R12)
1227 MOVD $-96, R12
1228 STVX V26, (R0+R12)
1229 MOVD $-80, R12
1230 STVX V27, (R0+R12)
1231 MOVD $-64, R12
1232 STVX V28, (R0+R12)
1233 MOVD $-48, R12
1234 STVX V29, (R0+R12)
1235 MOVD $-32, R12
1236 STVX V30, (R0+R12)
1237 MOVD $-16, R12
1238 STVX V31, (R0+R12)
1239 RET
1240 TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0
1241 // R0 holds the save location, R12 is clobbered
1242 MOVD $-192, R12
1243 LVX (R0+R12), V20
1244 MOVD $-176, R12
1245 LVX (R0+R12), V21
1246 MOVD $-160, R12
1247 LVX (R0+R12), V22
1248 MOVD $-144, R12
1249 LVX (R0+R12), V23
1250 MOVD $-128, R12
1251 LVX (R0+R12), V24
1252 MOVD $-112, R12
1253 LVX (R0+R12), V25
1254 MOVD $-96, R12
1255 LVX (R0+R12), V26
1256 MOVD $-80, R12
1257 LVX (R0+R12), V27
1258 MOVD $-64, R12
1259 LVX (R0+R12), V28
1260 MOVD $-48, R12
1261 LVX (R0+R12), V29
1262 MOVD $-32, R12
1263 LVX (R0+R12), V30
1264 MOVD $-16, R12
1265 LVX (R0+R12), V31
1266 RET
1267
View as plain text