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
7 #include "zasm_GOOS_GOARCH.h"
11 TEXT runtime·rt0_go(SB),NOSPLIT,$0
12 // initialize essential registers
13 BL runtime·reginit(SB)
16 MOVW R3, 8(R1) // argc
17 MOVD R4, 16(R1) // argv
19 // create istack out of the given (operating system) stack.
20 // _cgo_init may update stackguard.
21 MOVD $runtime·g0(SB), g
24 MOVD R3, g_stackguard0(g)
25 MOVD R3, g_stackguard1(g)
26 MOVD R3, (g_stack+stack_lo)(g)
27 MOVD R1, (g_stack+stack_hi)(g)
29 // TODO: if there is a _cgo_init, call it.
32 // set the per-goroutine and per-mach "registers"
33 MOVD $runtime·m0(SB), R3
42 // args are already prepared
45 BL runtime·schedinit(SB)
47 // create a new goroutine to start program
48 MOVD $runtime·main·f(SB), R3 // entry
52 BL runtime·newproc(SB)
61 DATA runtime·main·f+0(SB)/8,$runtime·main(SB)
62 GLOBL runtime·main·f(SB),RODATA,$8
64 TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
65 MOVD R0, 2(R0) // TODO: TD
68 TEXT runtime·asminit(SB),NOSPLIT,$-8-0
71 TEXT runtime·reginit(SB),NOSPLIT,$-8-0
72 // set R0 to zero, it's expected by the toolchain
74 // initialize essential FP registers
75 FMOVD $4503601774854144.0, F27
86 // void gosave(Gobuf*)
87 // save state in Gobuf; setjmp
88 TEXT runtime·gosave(SB), NOSPLIT, $-8-8
92 MOVD R31, gobuf_pc(R3)
95 MOVD R0, gobuf_ret(R3)
96 MOVD R0, gobuf_ctxt(R3)
100 // restore state from Gobuf; longjmp
101 TEXT runtime·gogo(SB), NOSPLIT, $-8-8
103 MOVD gobuf_g(R5), g // make sure g is not nil
105 MOVD gobuf_sp(R5), R1
106 MOVD gobuf_lr(R5), R31
108 MOVD gobuf_ret(R5), R3
109 MOVD gobuf_ctxt(R5), R11
110 MOVD R0, gobuf_sp(R5)
111 MOVD R0, gobuf_ret(R5)
112 MOVD R0, gobuf_lr(R5)
113 MOVD R0, gobuf_ctxt(R5)
114 CMP R0, R0 // set condition codes for == test, needed by stack split
115 MOVD gobuf_pc(R5), R31
119 // void mcall(fn func(*g))
120 // Switch to m->g0's stack, call fn(g).
121 // Fn must never return. It should gogo(&g->sched)
122 // to keep running g.
123 TEXT runtime·mcall(SB), NOSPLIT, $-8-8
124 // Save caller state in g->sched
125 MOVD R1, (g_sched+gobuf_sp)(g)
127 MOVD R31, (g_sched+gobuf_pc)(g)
128 MOVD R0, (g_sched+gobuf_lr)(g)
129 MOVD g, (g_sched+gobuf_g)(g)
131 // Switch to m->g0 & its stack, call fn.
137 BR runtime·badmcall(SB)
138 MOVD fn+0(FP), R11 // context
139 MOVD 0(R11), R4 // code pointer
141 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp
145 BR runtime·badmcall2(SB)
147 // switchtoM is a dummy routine that onM leaves at the bottom
148 // of the G stack. We need to distinguish the routine that
149 // lives at the bottom of the G stack from the one that lives
150 // at the top of the M stack because the one at the top of
151 // the M stack terminates the stack walk (see topofstack()).
152 TEXT runtime·switchtoM(SB), NOSPLIT, $0-0
154 BL (LR) // make sure this function is not leaf
157 // func onM_signalok(fn func())
158 TEXT runtime·onM_signalok(SB), NOSPLIT, $8-8
160 MOVD g_m(R3), R4 // R4 = g->m
161 MOVD m_gsignal(R4), R4 // R4 = g->m->gsignal
162 MOVD fn+0(FP), R11 // context for call below
170 MOVD 0(R11), R3 // code pointer
175 // void onM(fn func())
176 TEXT runtime·onM(SB), NOSPLIT, $0-8
177 MOVD fn+0(FP), R3 // R3 = fn
178 MOVD R3, R11 // context
179 MOVD g_m(g), R4 // R4 = m
181 MOVD m_g0(R4), R5 // R5 = g0
189 // Not g0, not curg. Must be gsignal, but that's not allowed.
190 // Hide call from linker nosplit analysis.
191 MOVD $runtime·badonm(SB), R3
196 // save our state in g->sched. Pretend to
197 // be switchtoM if the G stack is scanned.
198 MOVD $runtime·switchtoM(SB), R6
199 ADD $8, R6 // get past prologue
200 MOVD R6, (g_sched+gobuf_pc)(g)
201 MOVD R1, (g_sched+gobuf_sp)(g)
202 MOVD R0, (g_sched+gobuf_lr)(g)
203 MOVD g, (g_sched+gobuf_g)(g)
207 MOVD (g_sched+gobuf_sp)(g), R3
208 // make it look like mstart called onM on g0, to stop traceback
210 MOVD $runtime·mstart(SB), R4
214 // call target function
215 MOVD 0(R11), R3 // code pointer
222 MOVD (g_sched+gobuf_sp)(g), R1
223 MOVD R0, (g_sched+gobuf_sp)(g)
227 // already on m stack, just call directly
228 MOVD 0(R11), R3 // code pointer
234 * support for morestack
237 // Called during function prolog when more stack is needed.
238 // Caller has already loaded:
239 // R3: framesize, R4: argsize, R5: LR
241 // The traceback routines see morestack on a g0 as being
242 // the top of a stack (for example, morestack calling newstack
243 // calling the scheduler calling newm calling gc), so we must
244 // record an argument size. For that purpose, it has no arguments.
245 TEXT runtime·morestack(SB),NOSPLIT,$-8-0
246 // Cannot grow scheduler stack (m->g0).
253 // Cannot grow signal stack (m->gsignal).
254 MOVD m_gsignal(R7), R8
260 // Set g->sched to context in f.
261 MOVD R11, (g_sched+gobuf_ctxt)(g)
262 MOVD R1, (g_sched+gobuf_sp)(g)
264 MOVD R8, (g_sched+gobuf_pc)(g)
265 MOVD R5, (g_sched+gobuf_lr)(g)
268 // Set m->morebuf to f's caller.
269 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
270 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
271 MOVD g, (m_morebuf+gobuf_g)(R7)
273 // Call newstack on m->g0's stack.
275 MOVD (g_sched+gobuf_sp)(g), R1
276 BL runtime·newstack(SB)
278 // Not reached, but make sure the return PC from the call to newstack
279 // is still in this function, and not the beginning of the next.
282 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
284 BR runtime·morestack(SB)
286 // reflectcall: call a function with the given argument list
287 // func call(f *FuncVal, arg *byte, argsize, retoffset uint32).
288 // we don't have variable-sized frames, so we use a small number
289 // of constant-sized-frame functions to encode a few bits of size in the pc.
290 // Caution: ugly multiline assembly macros in your future!
292 #define DISPATCH(NAME,MAXSIZE) \
293 MOVD $MAXSIZE, R31; \
296 MOVD $NAME(SB), R31; \
299 // Note: can't just "BR NAME(SB)" - bad inlining results.
301 TEXT ·reflectcall(SB), NOSPLIT, $-8-24
303 DISPATCH(runtime·call16, 16)
304 DISPATCH(runtime·call32, 32)
305 DISPATCH(runtime·call64, 64)
306 DISPATCH(runtime·call128, 128)
307 DISPATCH(runtime·call256, 256)
308 DISPATCH(runtime·call512, 512)
309 DISPATCH(runtime·call1024, 1024)
310 DISPATCH(runtime·call2048, 2048)
311 DISPATCH(runtime·call4096, 4096)
312 DISPATCH(runtime·call8192, 8192)
313 DISPATCH(runtime·call16384, 16384)
314 DISPATCH(runtime·call32768, 32768)
315 DISPATCH(runtime·call65536, 65536)
316 DISPATCH(runtime·call131072, 131072)
317 DISPATCH(runtime·call262144, 262144)
318 DISPATCH(runtime·call524288, 524288)
319 DISPATCH(runtime·call1048576, 1048576)
320 DISPATCH(runtime·call2097152, 2097152)
321 DISPATCH(runtime·call4194304, 4194304)
322 DISPATCH(runtime·call8388608, 8388608)
323 DISPATCH(runtime·call16777216, 16777216)
324 DISPATCH(runtime·call33554432, 33554432)
325 DISPATCH(runtime·call67108864, 67108864)
326 DISPATCH(runtime·call134217728, 134217728)
327 DISPATCH(runtime·call268435456, 268435456)
328 DISPATCH(runtime·call536870912, 536870912)
329 DISPATCH(runtime·call1073741824, 1073741824)
330 MOVD $runtime·badreflectcall(SB), R31
334 #define CALLFN(NAME,MAXSIZE) \
335 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \
337 /* copy arguments to stack */ \
338 MOVD arg+8(FP), R3; \
339 MOVWZ n+16(FP), R4; \
349 /* call function */ \
353 PCDATA $PCDATA_StackMapIndex, $0; \
355 /* copy return values back */ \
356 MOVD arg+8(FP), R3; \
357 MOVWZ n+16(FP), R4; \
358 MOVWZ retoffset+20(FP), R6; \
376 CALLFN(·call128, 128)
377 CALLFN(·call256, 256)
378 CALLFN(·call512, 512)
379 CALLFN(·call1024, 1024)
380 CALLFN(·call2048, 2048)
381 CALLFN(·call4096, 4096)
382 CALLFN(·call8192, 8192)
383 CALLFN(·call16384, 16384)
384 CALLFN(·call32768, 32768)
385 CALLFN(·call65536, 65536)
386 CALLFN(·call131072, 131072)
387 CALLFN(·call262144, 262144)
388 CALLFN(·call524288, 524288)
389 CALLFN(·call1048576, 1048576)
390 CALLFN(·call2097152, 2097152)
391 CALLFN(·call4194304, 4194304)
392 CALLFN(·call8388608, 8388608)
393 CALLFN(·call16777216, 16777216)
394 CALLFN(·call33554432, 33554432)
395 CALLFN(·call67108864, 67108864)
396 CALLFN(·call134217728, 134217728)
397 CALLFN(·call268435456, 268435456)
398 CALLFN(·call536870912, 536870912)
399 CALLFN(·call1073741824, 1073741824)
401 // bool cas(uint32 *ptr, uint32 old, uint32 new)
408 TEXT runtime·cas(SB), NOSPLIT, $0-17
428 // bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
436 TEXT runtime·cas64(SB), NOSPLIT, $0-25
456 TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
459 TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
460 BR runtime·atomicload64(SB)
462 TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
463 BR runtime·atomicload64(SB)
465 TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
466 BR runtime·atomicstore64(SB)
468 // bool casp(void **val, void *old, void *new)
475 TEXT runtime·casp(SB), NOSPLIT, $0-25
478 // uint32 xadd(uint32 volatile *ptr, int32 delta)
482 TEXT runtime·xadd(SB), NOSPLIT, $0-20
495 TEXT runtime·xadd64(SB), NOSPLIT, $0-24
508 TEXT runtime·xchg(SB), NOSPLIT, $0-20
520 TEXT runtime·xchg64(SB), NOSPLIT, $0-24
532 TEXT runtime·xchgp(SB), NOSPLIT, $0-24
533 BR runtime·xchg64(SB)
535 TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
536 BR runtime·xchg64(SB)
538 TEXT runtime·procyield(SB),NOSPLIT,$0-0
541 TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
542 BR runtime·atomicstore64(SB)
544 TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
551 TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
558 // void runtime·atomicor8(byte volatile*, byte);
559 TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
562 // Align ptr down to 4 bytes so we can use 32-bit load/store.
563 // R5 = (R3 << 0) & ~3
564 RLDCR $0, R3, $~3, R5
565 // Compute val shift.
566 #ifdef GOARCH_power64
567 // Big endian. ptr = ptr ^ 3
570 // R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
571 RLDC $3, R3, $(3*8), R6
572 // Shift val for aligned ptr. R4 = val << R6
585 // void jmpdefer(fv, sp);
586 // called from deferreturn.
587 // 1. grab stored LR for caller
588 // 2. sub 4 bytes to get back to BL deferreturn
590 TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
602 // Save state of caller into g->sched. Smashes R31.
603 TEXT gosave<>(SB),NOSPLIT,$-8
605 MOVD R31, (g_sched+gobuf_pc)(g)
606 MOVD R1, (g_sched+gobuf_sp)(g)
607 MOVD R0, (g_sched+gobuf_lr)(g)
608 MOVD R0, (g_sched+gobuf_ret)(g)
609 MOVD R0, (g_sched+gobuf_ctxt)(g)
612 // asmcgocall(void(*fn)(void*), void *arg)
613 // Call fn(arg) on the scheduler stack,
614 // aligned appropriately for the gcc ABI.
615 // See cgocall.c for more details.
616 TEXT ·asmcgocall(SB),NOSPLIT,$0-16
619 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
620 // Turn the fn into a Go func (by taking its address) and call
621 // cgocallback_gofunc.
622 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
625 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
626 // See cgocall.c for more details.
627 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-24
630 // void setg(G*); set g. for use by needm.
631 TEXT runtime·setg(SB), NOSPLIT, $0-8
634 // void setg_gcc(G*); set g called from gcc.
635 TEXT setg_gcc<>(SB),NOSPLIT,$0
638 TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-16
643 TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
648 TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
650 MOVD R3, 0(R1) // set calling pc
653 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
659 // func gogetcallersp(p unsafe.Pointer) uintptr
660 TEXT runtime·gogetcallersp(SB),NOSPLIT,$0-16
666 TEXT runtime·abort(SB),NOSPLIT,$-8-0
671 #define TBRU 269 /* Time base Upper/Lower */
673 // int64 runtime·cputicks(void)
674 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
685 // AES hashing not implemented for Power
686 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
688 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
690 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
692 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
695 TEXT runtime·memeq(SB),NOSPLIT,$-8-25
717 // eqstring tests whether two strings are equal.
718 // See runtime_test.go:eqstring_generic for
719 // equivalent Go code.
720 TEXT runtime·eqstring(SB),NOSPLIT,$0-33
722 MOVD s2len+24(FP), R5
727 MOVD s2str+16(FP), R4
745 // TODO: share code with memeq?
746 TEXT bytes·Equal(SB),NOSPLIT,$0-49
748 MOVD b_len+32(FP), R4
750 CMP R3, R4 // unequal lengths are not equal
761 BEQ equal // reached the end
776 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
779 MOVBZ c+24(FP), R5 // byte to find
780 MOVD R3, R6 // store base for later
791 SUB R6, R3 // remove base
800 TEXT strings·IndexByte(SB),NOSPLIT,$0
803 MOVBZ c+16(FP), R5 // byte to find
804 MOVD R3, R6 // store base for later
815 SUB R6, R3 // remove base
825 // A Duff's device for zeroing memory.
826 // The compiler jumps to computed addresses within
827 // this routine to zero chunks of memory. Do not
828 // change this code without also changing the code
829 // in ../../cmd/9g/ggen.c:/^clearfat.
831 // R3 (aka REGRT1): ptr to memory to be zeroed - 8
832 // On return, R3 points to the last zeroed dword.
833 TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
964 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
966 MOVWZ m_fastrand(R4), R3
971 MOVW R3, m_fastrand(R4)
975 TEXT runtime·return0(SB), NOSPLIT, $0
979 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
980 // Must obey the gcc calling convention.
981 TEXT _cgo_topofstack(SB),NOSPLIT,$0
984 // The top-most function running on a goroutine
985 // returns to goexit+PCQuantum.
986 TEXT runtime·goexit(SB),NOSPLIT,$-8-0
988 BL runtime·goexit1(SB) // does not return