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.
5 // +build power64 power64le
12 TEXT runtime·rt0_go(SB),NOSPLIT,$0
13 // initialize essential registers
14 BL runtime·reginit(SB)
17 MOVW R3, 8(R1) // argc
18 MOVD R4, 16(R1) // argv
20 // create istack out of the given (operating system) stack.
21 // _cgo_init may update stackguard.
22 MOVD $runtime·g0(SB), g
25 MOVD R3, g_stackguard0(g)
26 MOVD R3, g_stackguard1(g)
27 MOVD R3, (g_stack+stack_lo)(g)
28 MOVD R1, (g_stack+stack_hi)(g)
30 // TODO: if there is a _cgo_init, call it.
33 // set the per-goroutine and per-mach "registers"
34 MOVD $runtime·m0(SB), R3
43 // args are already prepared
46 BL runtime·schedinit(SB)
48 // create a new goroutine to start program
49 MOVD $runtime·main·f(SB), R3 // entry
53 BL runtime·newproc(SB)
62 DATA runtime·main·f+0(SB)/8,$runtime·main(SB)
63 GLOBL runtime·main·f(SB),RODATA,$8
65 TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
66 MOVD R0, 2(R0) // TODO: TD
69 TEXT runtime·asminit(SB),NOSPLIT,$-8-0
72 TEXT runtime·reginit(SB),NOSPLIT,$-8-0
73 // set R0 to zero, it's expected by the toolchain
75 // initialize essential FP registers
76 FMOVD $4503601774854144.0, F27
87 // void gosave(Gobuf*)
88 // save state in Gobuf; setjmp
89 TEXT runtime·gosave(SB), NOSPLIT, $-8-8
93 MOVD R31, gobuf_pc(R3)
96 MOVD R0, gobuf_ret(R3)
97 MOVD R0, gobuf_ctxt(R3)
101 // restore state from Gobuf; longjmp
102 TEXT runtime·gogo(SB), NOSPLIT, $-8-8
104 MOVD gobuf_g(R5), g // make sure g is not nil
106 MOVD gobuf_sp(R5), R1
107 MOVD gobuf_lr(R5), R31
109 MOVD gobuf_ret(R5), R3
110 MOVD gobuf_ctxt(R5), R11
111 MOVD R0, gobuf_sp(R5)
112 MOVD R0, gobuf_ret(R5)
113 MOVD R0, gobuf_lr(R5)
114 MOVD R0, gobuf_ctxt(R5)
115 CMP R0, R0 // set condition codes for == test, needed by stack split
116 MOVD gobuf_pc(R5), R31
120 // void mcall(fn func(*g))
121 // Switch to m->g0's stack, call fn(g).
122 // Fn must never return. It should gogo(&g->sched)
123 // to keep running g.
124 TEXT runtime·mcall(SB), NOSPLIT, $-8-8
125 // Save caller state in g->sched
126 MOVD R1, (g_sched+gobuf_sp)(g)
128 MOVD R31, (g_sched+gobuf_pc)(g)
129 MOVD R0, (g_sched+gobuf_lr)(g)
130 MOVD g, (g_sched+gobuf_g)(g)
132 // Switch to m->g0 & its stack, call fn.
138 BR runtime·badmcall(SB)
139 MOVD fn+0(FP), R11 // context
140 MOVD 0(R11), R4 // code pointer
142 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
146 BR runtime·badmcall2(SB)
148 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
149 // of the G stack. We need to distinguish the routine that
150 // lives at the bottom of the G stack from the one that lives
151 // at the top of the system stack because the one at the top of
152 // the system stack terminates the stack walk (see topofstack()).
153 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
155 BL (LR) // make sure this function is not leaf
158 // func systemstack(fn func())
159 TEXT runtime·systemstack(SB), NOSPLIT, $0-8
160 MOVD fn+0(FP), R3 // R3 = fn
161 MOVD R3, R11 // context
162 MOVD g_m(g), R4 // R4 = m
164 MOVD m_gsignal(R4), R5 // R5 = gsignal
168 MOVD m_g0(R4), R5 // R5 = g0
176 // Bad: g is not gsignal, not g0, not curg. What is it?
177 // Hide call from linker nosplit analysis.
178 MOVD $runtime·badsystemstack(SB), R3
183 // save our state in g->sched. Pretend to
184 // be systemstack_switch if the G stack is scanned.
185 MOVD $runtime·systemstack_switch(SB), R6
186 ADD $8, R6 // get past prologue
187 MOVD R6, (g_sched+gobuf_pc)(g)
188 MOVD R1, (g_sched+gobuf_sp)(g)
189 MOVD R0, (g_sched+gobuf_lr)(g)
190 MOVD g, (g_sched+gobuf_g)(g)
194 MOVD (g_sched+gobuf_sp)(g), R3
195 // make it look like mstart called systemstack on g0, to stop traceback
197 MOVD $runtime·mstart(SB), R4
201 // call target function
202 MOVD 0(R11), R3 // code pointer
209 MOVD (g_sched+gobuf_sp)(g), R1
210 MOVD R0, (g_sched+gobuf_sp)(g)
214 // already on m stack, just call directly
215 MOVD 0(R11), R3 // code pointer
221 * support for morestack
224 // Called during function prolog when more stack is needed.
225 // Caller has already loaded:
226 // R3: framesize, R4: argsize, R5: LR
228 // The traceback routines see morestack on a g0 as being
229 // the top of a stack (for example, morestack calling newstack
230 // calling the scheduler calling newm calling gc), so we must
231 // record an argument size. For that purpose, it has no arguments.
232 TEXT runtime·morestack(SB),NOSPLIT,$-8-0
233 // Cannot grow scheduler stack (m->g0).
240 // Cannot grow signal stack (m->gsignal).
241 MOVD m_gsignal(R7), R8
247 // Set g->sched to context in f.
248 MOVD R11, (g_sched+gobuf_ctxt)(g)
249 MOVD R1, (g_sched+gobuf_sp)(g)
251 MOVD R8, (g_sched+gobuf_pc)(g)
252 MOVD R5, (g_sched+gobuf_lr)(g)
255 // Set m->morebuf to f's caller.
256 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
257 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
258 MOVD g, (m_morebuf+gobuf_g)(R7)
260 // Call newstack on m->g0's stack.
262 MOVD (g_sched+gobuf_sp)(g), R1
263 BL runtime·newstack(SB)
265 // Not reached, but make sure the return PC from the call to newstack
266 // is still in this function, and not the beginning of the next.
269 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
271 BR runtime·morestack(SB)
273 // reflectcall: call a function with the given argument list
274 // func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
275 // we don't have variable-sized frames, so we use a small number
276 // of constant-sized-frame functions to encode a few bits of size in the pc.
277 // Caution: ugly multiline assembly macros in your future!
279 #define DISPATCH(NAME,MAXSIZE) \
280 MOVD $MAXSIZE, R31; \
283 MOVD $NAME(SB), R31; \
286 // Note: can't just "BR NAME(SB)" - bad inlining results.
288 TEXT ·reflectcall(SB), NOSPLIT, $-8-24
290 DISPATCH(runtime·call16, 16)
291 DISPATCH(runtime·call32, 32)
292 DISPATCH(runtime·call64, 64)
293 DISPATCH(runtime·call128, 128)
294 DISPATCH(runtime·call256, 256)
295 DISPATCH(runtime·call512, 512)
296 DISPATCH(runtime·call1024, 1024)
297 DISPATCH(runtime·call2048, 2048)
298 DISPATCH(runtime·call4096, 4096)
299 DISPATCH(runtime·call8192, 8192)
300 DISPATCH(runtime·call16384, 16384)
301 DISPATCH(runtime·call32768, 32768)
302 DISPATCH(runtime·call65536, 65536)
303 DISPATCH(runtime·call131072, 131072)
304 DISPATCH(runtime·call262144, 262144)
305 DISPATCH(runtime·call524288, 524288)
306 DISPATCH(runtime·call1048576, 1048576)
307 DISPATCH(runtime·call2097152, 2097152)
308 DISPATCH(runtime·call4194304, 4194304)
309 DISPATCH(runtime·call8388608, 8388608)
310 DISPATCH(runtime·call16777216, 16777216)
311 DISPATCH(runtime·call33554432, 33554432)
312 DISPATCH(runtime·call67108864, 67108864)
313 DISPATCH(runtime·call134217728, 134217728)
314 DISPATCH(runtime·call268435456, 268435456)
315 DISPATCH(runtime·call536870912, 536870912)
316 DISPATCH(runtime·call1073741824, 1073741824)
317 MOVD $runtime·badreflectcall(SB), R31
321 #define CALLFN(NAME,MAXSIZE) \
322 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
324 /* copy arguments to stack */ \
325 MOVD arg+8(FP), R3; \
326 MOVWZ n+16(FP), R4; \
336 /* call function */ \
340 PCDATA $PCDATA_StackMapIndex, $0; \
342 /* copy return values back */ \
343 MOVD arg+8(FP), R3; \
344 MOVWZ n+16(FP), R4; \
345 MOVWZ retoffset+20(FP), R6; \
363 CALLFN(·call128, 128)
364 CALLFN(·call256, 256)
365 CALLFN(·call512, 512)
366 CALLFN(·call1024, 1024)
367 CALLFN(·call2048, 2048)
368 CALLFN(·call4096, 4096)
369 CALLFN(·call8192, 8192)
370 CALLFN(·call16384, 16384)
371 CALLFN(·call32768, 32768)
372 CALLFN(·call65536, 65536)
373 CALLFN(·call131072, 131072)
374 CALLFN(·call262144, 262144)
375 CALLFN(·call524288, 524288)
376 CALLFN(·call1048576, 1048576)
377 CALLFN(·call2097152, 2097152)
378 CALLFN(·call4194304, 4194304)
379 CALLFN(·call8388608, 8388608)
380 CALLFN(·call16777216, 16777216)
381 CALLFN(·call33554432, 33554432)
382 CALLFN(·call67108864, 67108864)
383 CALLFN(·call134217728, 134217728)
384 CALLFN(·call268435456, 268435456)
385 CALLFN(·call536870912, 536870912)
386 CALLFN(·call1073741824, 1073741824)
388 // bool cas(uint32 *ptr, uint32 old, uint32 new)
395 TEXT runtime·cas(SB), NOSPLIT, $0-17
415 // bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
423 TEXT runtime·cas64(SB), NOSPLIT, $0-25
443 TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
446 TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
447 BR runtime·atomicload64(SB)
449 TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
450 BR runtime·atomicload64(SB)
452 TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
453 BR runtime·atomicstore64(SB)
455 // bool casp(void **val, void *old, void *new)
462 TEXT runtime·casp1(SB), NOSPLIT, $0-25
465 // uint32 xadd(uint32 volatile *ptr, int32 delta)
469 TEXT runtime·xadd(SB), NOSPLIT, $0-20
482 TEXT runtime·xadd64(SB), NOSPLIT, $0-24
495 TEXT runtime·xchg(SB), NOSPLIT, $0-20
507 TEXT runtime·xchg64(SB), NOSPLIT, $0-24
519 TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
520 BR runtime·xchg64(SB)
522 TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
523 BR runtime·xchg64(SB)
525 TEXT runtime·procyield(SB),NOSPLIT,$0-0
528 TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
529 BR runtime·atomicstore64(SB)
531 TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
538 TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
545 // void runtime·atomicor8(byte volatile*, byte);
546 TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
549 // Align ptr down to 4 bytes so we can use 32-bit load/store.
550 // R5 = (R3 << 0) & ~3
551 RLDCR $0, R3, $~3, R5
552 // Compute val shift.
553 #ifdef GOARCH_power64
554 // Big endian. ptr = ptr ^ 3
557 // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
558 RLDC $3, R3, $(3*8), R6
559 // Shift val for aligned ptr. R4 = val << R6
572 // void jmpdefer(fv, sp);
573 // called from deferreturn.
574 // 1. grab stored LR for caller
575 // 2. sub 4 bytes to get back to BL deferreturn
577 TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
589 // Save state of caller into g->sched. Smashes R31.
590 TEXT gosave<>(SB),NOSPLIT,$-8
592 MOVD R31, (g_sched+gobuf_pc)(g)
593 MOVD R1, (g_sched+gobuf_sp)(g)
594 MOVD R0, (g_sched+gobuf_lr)(g)
595 MOVD R0, (g_sched+gobuf_ret)(g)
596 MOVD R0, (g_sched+gobuf_ctxt)(g)
599 // asmcgocall(void(*fn)(void*), void *arg)
600 // Call fn(arg) on the scheduler stack,
601 // aligned appropriately for the gcc ABI.
602 // See cgocall.c for more details.
603 TEXT ·asmcgocall(SB),NOSPLIT,$0-16
606 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
607 // Turn the fn into a Go func (by taking its address) and call
608 // cgocallback_gofunc.
609 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
612 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
613 // See cgocall.c for more details.
614 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
617 // void setg(G*); set g. for use by needm.
618 TEXT runtime·setg(SB), NOSPLIT, $0-8
621 // void setg_gcc(G*); set g called from gcc.
622 TEXT setg_gcc<>(SB),NOSPLIT,$0
625 TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16
630 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
635 TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
637 MOVD R3, 0(R1) // set calling pc
640 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
646 // func gogetcallersp(p unsafe.Pointer) uintptr
647 TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
653 TEXT runtime·abort(SB),NOSPLIT,$-8-0
658 #define TBRU 269 /* Time base Upper/Lower */
660 // int64 runtime·cputicks(void)
661 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
672 // AES hashing not implemented for Power
673 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
675 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
677 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
679 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
682 TEXT runtime·memeq(SB),NOSPLIT,$-8-25
704 // eqstring tests whether two strings are equal.
705 // See runtime_test.go:eqstring_generic for
706 // equivalent Go code.
707 TEXT runtime·eqstring(SB),NOSPLIT,$0-33
709 MOVD s2len+24(FP), R5
714 MOVD s2str+16(FP), R4
732 // TODO: share code with memeq?
733 TEXT bytes·Equal(SB),NOSPLIT,$0-49
735 MOVD b_len+32(FP), R4
737 CMP R3, R4 // unequal lengths are not equal
748 BEQ equal // reached the end
763 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
766 MOVBZ c+24(FP), R5 // byte to find
767 MOVD R3, R6 // store base for later
778 SUB R6, R3 // remove base
787 TEXT strings·IndexByte(SB),NOSPLIT,$0
790 MOVBZ c+16(FP), R5 // byte to find
791 MOVD R3, R6 // store base for later
802 SUB R6, R3 // remove base
812 // A Duff's device for zeroing memory.
813 // The compiler jumps to computed addresses within
814 // this routine to zero chunks of memory. Do not
815 // change this code without also changing the code
816 // in ../../cmd/9g/ggen.c:/^clearfat.
818 // R3 (aka REGRT1): ptr to memory to be zeroed - 8
819 // On return, R3 points to the last zeroed dword.
820 TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
951 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
953 MOVWZ m_fastrand(R4), R3
958 MOVW R3, m_fastrand(R4)
962 TEXT runtime·return0(SB), NOSPLIT, $0
966 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
967 // Must obey the gcc calling convention.
968 TEXT _cgo_topofstack(SB),NOSPLIT,$0
971 // The top-most function running on a goroutine
972 // returns to goexit+PCQuantum.
973 TEXT runtime·goexit(SB),NOSPLIT,$-8-0
975 BL runtime·goexit1(SB) // does not return
977 TEXT runtime·getg(SB),NOSPLIT,$-8-8