1
0
mirror of https://github.com/golang/go synced 2024-10-02 08:08:33 -06:00

[dev.power64] runtime: manually written parts for linux/power64 and linux/power64le, checkpoint

LGTM=rsc
R=rsc, iant
CC=golang-codereviews
https://golang.org/cl/122430043
This commit is contained in:
Shenghou Ma 2014-08-12 19:48:49 -04:00
parent 4928b2074b
commit 5f691cfaf1
13 changed files with 1795 additions and 0 deletions

View File

@ -0,0 +1,14 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
enum {
thechar = '9',
BigEndian = 1,
CacheLineSize = 64,
RuntimeGogoBytes = 84,
PhysPageSize = 4096,
PCQuantum = 4,
Int64Align = 8
};

View File

@ -0,0 +1,14 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
enum {
thechar = '9',
BigEndian = 0,
CacheLineSize = 64,
RuntimeGogoBytes = 84,
PhysPageSize = 4096,
PCQuantum = 4,
Int64Align = 8
};

View File

@ -0,0 +1,997 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "zasm_GOOS_GOARCH.h"
#include "funcdata.h"
#include "../../cmd/ld/textflag.h"
TEXT _rt0_go(SB),NOSPLIT,$0
// initialize essential registers
BL runtime·reginit(SB)
SUB $24, R1
MOVW R3, 8(R1) // argc
MOVD R4, 16(R1) // argv
// create istack out of the given (operating system) stack.
// _cgo_init may update stackguard.
MOVD $runtime·g0(SB), g
MOVD $(-64*1024), R31
ADD R31, R1, R3
MOVD R3, g_stackguard(g)
MOVD R3, g_stackguard0(g)
MOVD R1, g_stackbase(g)
// TODO: if there is a _cgo_init, call it.
// TODO: add TLS
// set the per-goroutine and per-mach "registers"
MOVD $runtime·m0(SB), R3
// save m->g0 = g0
MOVD g, m_g0(R3)
// save m0 to g0->m
MOVD R3, g_m(g)
BL runtime·check(SB)
// args are already prepared
BL runtime·args(SB)
BL runtime·osinit(SB)
BL runtime·hashinit(SB)
BL runtime·schedinit(SB)
// create a new goroutine to start program
MOVD $runtime·main·f(SB), R3 // entry
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
MOVDU R0, -8(R1)
ARGSIZE(24)
BL runtime·newproc(SB)
ARGSIZE(-1)
ADD $24, R1
// start this M
BL runtime·mstart(SB)
MOVD R0, 1(R0)
RETURN
DATA runtime·main·f+0(SB)/8,$runtime·main(SB)
GLOBL runtime·main·f(SB),RODATA,$8
TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
MOVD R0, 2(R0) // TODO: TD
RETURN
TEXT runtime·asminit(SB),NOSPLIT,$-8-0
RETURN
TEXT runtime·reginit(SB),NOSPLIT,$-8-0
// set R0 to zero, it's expected by the toolchain
XOR R0, R0
// initialize essential FP registers
FMOVD $4503601774854144.0, F27
FMOVD $0.5, F29
FSUB F29, F29, F28
FADD F29, F29, F30
FADD F30, F30, F31
RETURN
/*
* go-routine
*/
// void gosave(Gobuf*)
// save state in Gobuf; setjmp
TEXT runtime·gosave(SB), NOSPLIT, $-8-8
MOVD gobuf+0(FP), R3
MOVD R1, gobuf_sp(R3)
MOVD LR, R31
MOVD R31, gobuf_pc(R3)
MOVD g, gobuf_g(R3)
MOVD R0, gobuf_lr(R3)
MOVD R0, gobuf_ret(R3)
MOVD R0, gobuf_ctxt(R3)
RETURN
// void gogo(Gobuf*)
// restore state from Gobuf; longjmp
TEXT runtime·gogo(SB), NOSPLIT, $-8-8
MOVD gobuf+0(FP), R5
MOVD gobuf_g(R5), g // make sure g is not nil
MOVD 0(g), R4
MOVD gobuf_sp(R5), R1
MOVD gobuf_lr(R5), R31
MOVD R31, LR
MOVD gobuf_ret(R5), R3
MOVD gobuf_ctxt(R5), R11
MOVD R0, gobuf_sp(R5)
MOVD R0, gobuf_ret(R5)
MOVD R0, gobuf_lr(R5)
MOVD R0, gobuf_ctxt(R5)
CMP R0, R0 // set condition codes for == test, needed by stack split
MOVD gobuf_pc(R5), R31
MOVD R31, CTR
BR (CTR)
// void mcall(void (*fn)(G*))
// Switch to m->g0's stack, call fn(g).
// Fn must never return. It should gogo(&g->sched)
// to keep running g.
TEXT runtime·mcall(SB), NOSPLIT, $-8-8
// Save caller state in g->sched
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD LR, R31
MOVD R31, (g_sched+gobuf_pc)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD g, (g_sched+gobuf_g)(g)
// Switch to m->g0 & its stack, call fn.
MOVD g, R3
MOVD g_m(g), R8
MOVD m_g0(R8), g
CMP g, R3
BNE 2(PC)
BR runtime·badmcall(SB)
MOVD fn+0(FP), R4
MOVD R4, CTR
MOVD (g_sched+gobuf_sp)(g), R1
MOVDU R3, -8(R1)
MOVDU R0, -8(R1)
BL (CTR)
BR runtime·badmcall2(SB)
/*
* support for morestack
*/
// Called during function prolog when more stack is needed.
// Caller has already loaded:
// R3: framesize, R4: argsize, R5: LR
//
// The traceback routines see morestack on a g0 as being
// the top of a stack (for example, morestack calling newstack
// calling the scheduler calling newm calling gc), so we must
// record an argument size. For that purpose, it has no arguments.
TEXT runtime·morestack(SB),NOSPLIT,$0-0
// Cannot grow scheduler stack (m->g0).
MOVD g_m(g), R7
MOVD m_g0(R7), R8
CMP g, R8
BNE 2(PC)
BL runtime·abort(SB)
MOVW R3, m_moreframesize(R7)
MOVW R4, m_moreargsize(R7)
// Called from f.
// Set g->sched to context in f.
MOVD R11, (g_sched+gobuf_ctxt)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD LR, R8
MOVD R8, (g_sched+gobuf_pc)(g)
MOVD R5, (g_sched+gobuf_lr)(g)
// Called from f.
// Set m->morebuf to f's caller.
MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC
MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP
MOVD $8(R1), R8 // f's argument pointer
MOVD R8, m_moreargp(R7)
MOVD g, (m_morebuf+gobuf_g)(R7)
// Call newstack on m->g0's stack.
MOVD m_g0(R7), g
MOVD (g_sched+gobuf_sp)(g), R1
BL runtime·newstack(SB)
// Not reached, but make sure the return PC from the call to newstack
// is still in this function, and not the beginning of the next.
UNDEF
TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
MOVD R0, R11
BR runtime·morestack(SB)
// Called from panic. Mimics morestack,
// reuses stack growth code to create a frame
// with the desired args running the desired function.
//
// func call(fn *byte, arg *byte, argsize uint32).
TEXT runtime·newstackcall(SB), NOSPLIT, $-8-20
// Save our caller's state as the PC and SP to restore when
// returning from f.
MOVD g_m(g), R5
MOVD LR, R31
MOVD R31, (m_morebuf+gobuf_pc)(R5) // our caller's PC
MOVD R1, (m_morebuf+gobuf_sp)(R5) // our caller's SP
MOVD g, (m_morebuf+gobuf_g)(R5)
// Save our own state as the PC and SP to restore if this
// goroutine needs to be restarted.
MOVD $runtime·newstackcall(SB), R7
MOVD R7, (g_sched+gobuf_pc)(g)
MOVD LR, R31
MOVD R31, (g_sched+gobuf_lr)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
// Set up morestack arguments to call f on a new stack.
// We set f's frame size to 1, as a hint to newstack that
// this is a call from runtime.newstackcall.
// If it turns out that f needs a larger frame than the
// default stack, f's usual stack growth prolog will
// allocate a new segment (and recopy the arguments).
MOVD fn+0(FP), R7
MOVD args+8(FP), R8
MOVW n+16(FP), R9
MOVD R7, m_cret(R5)
MOVD R8, m_moreargp(R5)
MOVW R9, m_moreargsize(R5)
MOVD $1, R10
MOVD R10, m_moreframesize(R5)
// call newstack on m->g0's stack
MOVD m_g0(R5), g
MOVD (g_sched+gobuf_sp)(g), R1
BR runtime·newstack(SB)
// reflect·call: call a function with the given argument list
// func call(f *FuncVal, arg *byte, argsize uint32).
// we don't have variable-sized frames, so we use a small number
// of constant-sized-frame functions to encode a few bits of size in the pc.
// Caution: ugly multiline assembly macros in your future!
#define DISPATCH(NAME,MAXSIZE) \
MOVD $MAXSIZE, R31; \
CMP R3, R31; \
BGT 4(PC); \
MOVD $runtime·NAME(SB), R31; \
MOVD R31, CTR; \
BR (CTR)
// Note: can't just "BR runtime·NAME(SB)" - bad inlining results.
TEXT reflect·call(SB), NOSPLIT, $0-24
MOVW argsize+16(FP), R3
DISPATCH(call16, 16)
DISPATCH(call32, 32)
DISPATCH(call64, 64)
DISPATCH(call128, 128)
DISPATCH(call256, 256)
DISPATCH(call512, 512)
DISPATCH(call1024, 1024)
DISPATCH(call2048, 2048)
DISPATCH(call4096, 4096)
DISPATCH(call8192, 8192)
DISPATCH(call16384, 16384)
DISPATCH(call32768, 32768)
DISPATCH(call65536, 65536)
DISPATCH(call131072, 131072)
DISPATCH(call262144, 262144)
DISPATCH(call524288, 524288)
DISPATCH(call1048576, 1048576)
DISPATCH(call2097152, 2097152)
DISPATCH(call4194304, 4194304)
DISPATCH(call8388608, 8388608)
DISPATCH(call16777216, 16777216)
DISPATCH(call33554432, 33554432)
DISPATCH(call67108864, 67108864)
DISPATCH(call134217728, 134217728)
DISPATCH(call268435456, 268435456)
DISPATCH(call536870912, 536870912)
DISPATCH(call1073741824, 1073741824)
MOVD $runtime·badreflectcall(SB), R31
MOVD R31, CTR
BR (CTR)
// Argument map for the callXX frames. Each has one
// stack map (for the single call) with 3 arguments.
DATA gcargs_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
DATA gcargs_reflectcall<>+0x04(SB)/4, $6 // 3 args
DATA gcargs_reflectcall<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsScalar<<4))
GLOBL gcargs_reflectcall<>(SB),RODATA,$12
// callXX frames have no locals
DATA gclocals_reflectcall<>+0x00(SB)/4, $1 // 1 stackmap
DATA gclocals_reflectcall<>+0x04(SB)/4, $0 // 0 locals
GLOBL gclocals_reflectcall<>(SB),RODATA,$8
#define CALLFN(NAME,MAXSIZE) \
TEXT runtime·NAME(SB), WRAPPER, $MAXSIZE-24; \
FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_reflectcall<>(SB); \
FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_reflectcall<>(SB);\
/* copy arguments to stack */ \
MOVD argptr+8(FP), R3; \
MOVW argsize+16(FP), R4; \
MOVD R1, R5; \
ADD $(8-1), R5; \
SUB $1, R3; \
ADD R5, R4; \
CMP R5, R4; \
BEQ 4(PC); \
MOVBZU 1(R3), R6; \
MOVBZU R6, 1(R5); \
BR -4(PC); \
/* call function */ \
MOVD f+0(FP), R31; \
MOVD (R31), R31; \
MOVD R31, CTR; \
PCDATA $PCDATA_StackMapIndex, $0; \
BL (CTR); \
/* copy return values back */ \
MOVD argptr+8(FP), R3; \
MOVW argsize+16(FP), R4; \
MOVW retoffset+20(FP), R5; \
MOVD R1, R6; \
ADD $(8-1), R6; \
ADD R5, R6; \
ADD R5, R3; \
SUB R5, R4; \
CMP R4, $0; \
BEQ 9(PC); \
SUB $1, R3; \
SUB $1, R6; \
ADD R3, R4; \
CMP R3, R4; \
BEQ 4(PC); \
MOVBZU 1(R3), R5; \
MOVBZU R5, 1(R6); \
BR -4(PC); \
RETURN
CALLFN(call16, 16)
CALLFN(call32, 32)
CALLFN(call64, 64)
CALLFN(call128, 128)
CALLFN(call256, 256)
CALLFN(call512, 512)
CALLFN(call1024, 1024)
CALLFN(call2048, 2048)
CALLFN(call4096, 4096)
CALLFN(call8192, 8192)
CALLFN(call16384, 16384)
CALLFN(call32768, 32768)
CALLFN(call65536, 65536)
CALLFN(call131072, 131072)
CALLFN(call262144, 262144)
CALLFN(call524288, 524288)
CALLFN(call1048576, 1048576)
CALLFN(call2097152, 2097152)
CALLFN(call4194304, 4194304)
CALLFN(call8388608, 8388608)
CALLFN(call16777216, 16777216)
CALLFN(call33554432, 33554432)
CALLFN(call67108864, 67108864)
CALLFN(call134217728, 134217728)
CALLFN(call268435456, 268435456)
CALLFN(call536870912, 536870912)
CALLFN(call1073741824, 1073741824)
// Return point when leaving stack.
//
// Lessstack can appear in stack traces for the same reason
// as morestack; in that context, it has 0 arguments.
TEXT runtime·lessstack(SB), NOSPLIT, $-8-0
// Save return value in m->cret
MOVD g_m(g), R5
MOVD R3, m_cret(R5)
// Call oldstack on m->g0's stack.
MOVD m_g0(R5), g
MOVD (g_sched+gobuf_sp)(g), R1
BL runtime·oldstack(SB)
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// } else
// return 0;
TEXT runtime·cas(SB), NOSPLIT, $0-16
MOVD p+0(FP), R3
MOVW old+8(FP), R4
MOVW new+12(FP), R5
SYNC
LWAR (R3), R6
CMPW R6, R4
BNE 7(PC)
STWCCC R5, (R3)
BNE -5(PC)
MOVD $1, R3
SYNC
ISYNC
RETURN
MOVD $0, R3
BR -4(PC)
// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
// Atomically:
// if(*val == *old){
// *val = new;
// return 1;
// } else {
// return 0;
// }
TEXT runtime·cas64(SB), NOSPLIT, $0-24
MOVD p+0(FP), R3
MOVD old+8(FP), R4
MOVD new+16(FP), R5
SYNC
LDAR (R3), R6
CMP R6, R4
BNE 7(PC)
STDCCC R5, (R3)
BNE -5(PC)
MOVD $1, R3
SYNC
ISYNC
RETURN
MOVD $0, R3
BR -4(PC)
// bool casp(void **val, void *old, void *new)
// Atomically:
// if(*val == old){
// *val = new;
// return 1;
// } else
// return 0;
TEXT runtime·casp(SB), NOSPLIT, $0-24
BR runtime·cas64(SB)
// uint32 xadd(uint32 volatile *val, int32 delta)
// Atomically:
// *val += delta;
// return *val;
TEXT runtime·xadd(SB), NOSPLIT, $0-12
MOVD p+0(FP), R4
MOVW delta+8(FP), R5
SYNC
LWAR (R4), R3
ADD R5, R3
STWCCC R3, (R4)
BNE -4(PC)
SYNC
ISYNC
MOVW R3, R3
RETURN
TEXT runtime·xadd64(SB), NOSPLIT, $0-16
MOVD p+0(FP), R4
MOVD delta+8(FP), R5
SYNC
LDAR (R4), R3
ADD R5, R3
STDCCC R3, (R4)
BNE -4(PC)
SYNC
ISYNC
RETURN
TEXT runtime·xchg(SB), NOSPLIT, $0-12
MOVD p+0(FP), R4
MOVW new+8(FP), R5
SYNC
LWAR (R4), R3
STWCCC R5, (R4)
BNE -3(PC)
SYNC
ISYNC
RETURN
TEXT runtime·xchg64(SB), NOSPLIT, $0-16
MOVD p+0(FP), R4
MOVD new+8(FP), R5
SYNC
LDAR (R4), R3
STDCCC R5, (R4)
BNE -3(PC)
SYNC
ISYNC
RETURN
TEXT runtime·xchgp(SB), NOSPLIT, $0-16
BR runtime·xchg64(SB)
TEXT runtime·procyield(SB),NOSPLIT,$0-0
MOVD R0, 17(R0)
TEXT runtime·atomicstorep(SB), NOSPLIT, $0-16
BR runtime·atomicstore64(SB)
TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
MOVD 0(FP), R3
MOVW 8(FP), R4
SYNC
MOVW R4, 0(R3)
RETURN
TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
MOVD 0(FP), R3
MOVD 8(FP), R4
SYNC
MOVD R4, 0(R3)
RETURN
// void jmpdefer(fn, sp);
// called from deferreturn.
// 1. grab stored LR for caller
// 2. sub 4 bytes to get back to BL deferreturn
// 3. BR to fn
TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
MOVD 0(R1), R31
SUB $4, R31
MOVD R31, LR
MOVD fn+0(FP), R11
MOVD argp+8(FP), R1
SUB $8, R1
MOVD 0(R11), R3
MOVD R3, CTR
BR (CTR)
// Save state of caller into g->sched. Smashes R31.
TEXT gosave<>(SB),NOSPLIT,$-8
MOVD LR, R31
MOVD R31, (g_sched+gobuf_pc)(g)
MOVD R1, (g_sched+gobuf_sp)(g)
MOVD R0, (g_sched+gobuf_lr)(g)
MOVD R0, (g_sched+gobuf_ret)(g)
MOVD R0, (g_sched+gobuf_ctxt)(g)
RETURN
// asmcgocall(void(*fn)(void*), void *arg)
// Call fn(arg) on the scheduler stack,
// aligned appropriately for the gcc ABI.
// See cgocall.c for more details.
TEXT runtime·asmcgocall(SB),NOSPLIT,$0-16
MOVD R0, 21(R0)
// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
// Turn the fn into a Go func (by taking its address) and call
// cgocallback_gofunc.
TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
MOVD R0, 22(R0)
// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
// See cgocall.c for more details.
TEXT runtime·cgocallback_gofunc(SB),NOSPLIT,$8-24
MOVD R0, 23(R0)
// void setg(G*); set g. for use by needm.
TEXT runtime·setg(SB), NOSPLIT, $0-16
MOVD R0, 24(R0)
// void setg_gcc(G*); set g called from gcc.
TEXT setg_gcc<>(SB),NOSPLIT,$0
MOVD R0, 25(R0)
TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-8
MOVD 0(R1), R3
RETURN
TEXT runtime·gogetcallerpc(SB),NOSPLIT,$-8-16
MOVD 0(R1), R3
MOVD R3,ret+8(FP)
RETURN
TEXT runtime·setcallerpc(SB),NOSPLIT,$-8-16
MOVD x+8(FP),R3 // addr of first arg
MOVD R3, 0(R1) // set calling pc
RETURN
TEXT runtime·getcallersp(SB),NOSPLIT,$0-8
MOVD sp+0(FP), R3
SUB $8, R3
RETURN
TEXT runtime·abort(SB),NOSPLIT,$-4-0
MOVW (R0), R0
UNDEF
#define TBRL 268
#define TBRU 269 /* Time base Upper/Lower */
// int64 runtime·cputicks(void)
TEXT runtime·cputicks(SB),NOSPLIT,$0-0
MOVW SPR(TBRU), R4
MOVW SPR(TBRL), R3
MOVW SPR(TBRU), R5
CMPW R4, R5
BNE -4(PC)
SLD $32, R5
OR R5, R3
RETURN
TEXT runtime·stackguard(SB),NOSPLIT,$0-16
MOVD R1, R3
MOVD R3, sp+0(FP)
MOVD g_stackguard(g), R3
MOVD R3, limit+8(FP)
RETURN
GLOBL runtime·tls0(SB), $64
// AES hashing not implemented for Power
TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
MOVW (R0), R1
TEXT runtime·memeq(SB),NOSPLIT,$-8-24
MOVD a+0(FP), R3
MOVD b+8(FP), R4
MOVD count+16(FP), R5
SUB $1, R3
SUB $1, R4
ADD R3, R5, R8
_next:
CMP R3, R8
BNE 3(PC)
MOVD $1, R3
RETURN
MOVBZU 1(R3), R6
MOVBZU 1(R4), R7
CMP R6, R7
BEQ _next
MOVD $0, R3
RETURN
TEXT runtime·gomemeq(SB),NOSPLIT,$0-25
MOVD a+0(FP), R3
MOVD b+8(FP), R4
MOVD count+16(FP), R5
SUB $1, R3
SUB $1, R4
ADD R3, R5, R8
_next2:
CMP R3, R8
BNE 4(PC)
MOVD $1, R3
MOVB R3, ret+24(FP)
RETURN
MOVBZU 1(R3), R6
MOVBZU 1(R4), R7
CMP R6, R7
BEQ _next2
MOVB R0, ret+24(FP)
RETURN
// eqstring tests whether two strings are equal.
// See runtime_test.go:eqstring_generic for
// equivlaent Go code.
TEXT runtime·eqstring(SB),NOSPLIT,$0-33
MOVD s1len+8(FP), R4
MOVD s2len+24(FP), R5
CMP R4, R5
BNE str_noteq
MOVD s1str+0(FP), R3
MOVD s2str+16(FP), R4
SUB $1, R3
SUB $1, R4
ADD R3, R5, R8
eq_next:
CMP R3, R8
BNE 4(PC)
MOVD $1, R3
MOVB R3, ret+32(FP)
RETURN
MOVBZU 1(R3), R6
MOVBZU 1(R4), R7
CMP R6, R7
BEQ eq_next
str_noteq:
MOVB R0, ret+32(FP)
RETURN
// TODO: share code with memeq?
TEXT bytes·Equal(SB),NOSPLIT,$0-49
MOVD a_len+8(FP), R3
MOVD b_len+32(FP), R4
CMP R3, R4 // unequal lengths are not equal
BNE _notequal
MOVD a+0(FP), R5
MOVD b+24(FP), R6
SUB $1, R5
SUB $1, R6
ADD R5, R3 // end-1
_byteseq_next:
CMP R5, R3
BEQ _equal // reached the end
MOVBZU 1(R5), R4
MOVBZU 1(R6), R7
CMP R4, R7
BEQ _byteseq_next
_notequal:
MOVBZ R0, ret+48(FP)
RETURN
_equal:
MOVD $1, R3
MOVBZ R3, ret+48(FP)
RETURN
TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
MOVD s+0(FP), R3
MOVD s_len+8(FP), R4
MOVBZ c+24(FP), R5 // byte to find
SUB $1, R3
MOVD R3, R6 // store base-1 for later
ADD R3, R4 // end-1
_index_loop:
CMP R3, R4
BEQ _index_notfound
MOVBZU 1(R3), R7
CMP R7, R5
BNE _index_loop
SUB R6, R3 // remove base
MOVD R3, ret+32(FP)
RETURN
_index_notfound:
MOVW $-1, R3
MOVW R3, ret+32(FP)
RETURN
TEXT strings·IndexByte(SB),NOSPLIT,$0
MOVD p+0(FP), R3
MOVD b_len+8(FP), R4
MOVBZ c+16(FP), R5 // byte to find
SUB $1, R3
MOVD R3, R6 // store base-1 for later
ADD R3, R4 // end-1
_index2_loop:
CMP R3, R4
BEQ _index2_notfound
MOVBZU 1(R3), R7
CMP R7, R5
BNE _index2_loop
SUB R6, R3 // remove base
MOVD R3, ret+24(FP)
RETURN
_index2_notfound:
MOVW $-1, R3
MOVW R3, ret+24(FP)
RETURN
TEXT runtime·timenow(SB), NOSPLIT, $0-0
BR time·now(SB)
// A Duff's device for zeroing memory.
// The compiler jumps to computed addresses within
// this routine to zero chunks of memory. Do not
// change this code without also changing the code
// in ../../cmd/9g/ggen.c:/^clearfat.
// R0: always zero
// R3 (aka REGRT1): ptr to memory to be zeroed - 8
// R3 is updated as a side effect.
TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
MOVDU R0, 8(R3)
RETURN
TEXT runtime·fastrand2(SB), NOSPLIT, $0-4
MOVD g_m(g), R4
MOVD m_fastrand(R4), R3
ADD R3, R3
CMP R3, $0
BGE 2(PC)
XOR $0x88888eef, R3
MOVD R3, m_fastrand(R4)
MOVD R3, ret+0(FP)
RETURN
// The gohash and goeq trampolines are necessary while we have
// both Go and C calls to alg functions. Once we move all call
// sites to Go, we can redo the hash/eq functions to use the
// Go calling convention and remove these.
// convert call to:
// func (alg unsafe.Pointer, p unsafe.Pointer, size uintpr, seed uintptr) uintptr
// to:
// func (hash *uintptr, size uintptr, p unsafe.Pointer)
TEXT runtime·gohash(SB), NOSPLIT, $24-40
FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_gohash<>(SB)
FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_gohash<>(SB)
MOVD a+0(FP), R3
MOVD alg_hash(R3), R3
MOVD R3, CTR
MOVD p+8(FP), R4
MOVD size+16(FP), R5
MOVD seed+24(FP), R6
MOVD R6, ret+32(FP)
MOVD $ret+32(FP), R7
MOVD R7, 8(R1)
MOVD R5, 16(R1)
MOVD R4, 24(R1)
PCDATA $PCDATA_StackMapIndex, $0
BL (CTR)
RETURN
DATA gcargs_gohash<>+0x00(SB)/4, $1 // 1 stackmap
DATA gcargs_gohash<>+0x04(SB)/4, $10 // 5 args
DATA gcargs_gohash<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2))
GLOBL gcargs_gohash<>(SB),RODATA,$12
DATA gclocals_gohash<>+0x00(SB)/4, $1 // 1 stackmap
DATA gclocals_gohash<>+0x04(SB)/4, $0 // 0 locals
GLOBL gclocals_gohash<>(SB),RODATA,$8
// convert call to:
// func (alg unsafe.Pointer, p, q unsafe.Pointer, size uintptr) bool
// to:
// func (eq *bool, size uintptr, p, q unsafe.Pointer)
TEXT runtime·goeq(SB), NOSPLIT, $32-33
FUNCDATA $FUNCDATA_ArgsPointerMaps,gcargs_goeq<>(SB)
FUNCDATA $FUNCDATA_LocalsPointerMaps,gclocals_goeq<>(SB)
MOVD alg+0(FP), R3
MOVD alg_equal(R3), R3
MOVD R3, CTR
MOVD p+8(FP), R4
MOVD q+16(FP), R5
MOVD size+24(FP), R6
MOVD $ret+32(FP), R7
MOVD R7, 8(R1)
MOVD R6, 16(R1)
MOVD R5, 24(R1)
MOVD R4, 32(R1)
PCDATA $PCDATA_StackMapIndex, $0
BL (CTR)
RETURN
DATA gcargs_goeq<>+0x00(SB)/4, $1 // 1 stackmap
DATA gcargs_goeq<>+0x04(SB)/4, $10 // 5 args
DATA gcargs_goeq<>+0x08(SB)/4, $(const_BitsPointer+(const_BitsPointer<<2)+(const_BitsPointer<<4))
GLOBL gcargs_goeq<>(SB),RODATA,$12
DATA gclocals_goeq<>+0x00(SB)/4, $1 // 1 stackmap
DATA gclocals_goeq<>+0x04(SB)/4, $0 // 0 locals
GLOBL gclocals_goeq<>(SB),RODATA,$8

View File

@ -0,0 +1,37 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "../../cmd/ld/textflag.h"
// uint32 runtime·atomicload(uint32 volatile* addr)
TEXT ·atomicload(SB),NOSPLIT,$-8-8
MOVD 0(FP), R3
SYNC
MOVWZ 0(R3), R3
CMPW R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
RETURN
// uint64 runtime·atomicload64(uint64 volatile* addr)
TEXT ·atomicload64(SB),NOSPLIT,$-8-8
MOVD 0(FP), R3
SYNC
MOVD 0(R3), R3
CMP R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
RETURN
// void *runtime·atomicloadp(void *volatile *addr)
TEXT ·atomicloadp(SB),NOSPLIT,$-8-8
MOVD 0(FP), R3
SYNC
MOVD 0(R3), R3
CMP R3, R3, CR7
BC 4, 30, 1(PC) // bne- cr7,0x4
ISYNC
RETURN

View File

@ -0,0 +1,20 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "../../cmd/ld/textflag.h"
// void runtime·memclr(void*, uintptr)
TEXT runtime·memclr(SB),NOSPLIT,$0-16
MOVD ptr+0(FP), R3
MOVD n+8(FP), R4
CMP R4, $0
BEQ done
SUB $1, R3
MOVD R4, CTR
MOVBU R0, 1(R3)
BC 25, 0, -1(PC) // bdnz+ $-4
done:
RETURN

View File

@ -0,0 +1,40 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "../../cmd/ld/textflag.h"
// void runtime·memmove(void*, void*, uintptr)
TEXT runtime·memmove(SB), NOSPLIT, $-8-24
MOVD to+0(FP), R3
MOVD from+8(FP), R4
MOVD n+16(FP), R5
CMP R5, $0
BNE check
RETURN
check:
CMP R3, R4
BGT backward
SUB $1, R3
ADD R3, R5
SUB $1, R4
loop:
MOVBU 1(R4), R6
MOVBU R6, 1(R3)
CMP R3, R5
BNE loop
RETURN
backward:
ADD R5, R4
ADD R3, R5
loop1:
MOVBU -1(R4), R6
MOVBU R6, -1(R5)
CMP R3, R5
BNE loop1
RETURN

View File

@ -0,0 +1,17 @@
#include "../../cmd/ld/textflag.h"
// actually a function descriptor for _main<>(SB)
TEXT _rt0_power64_linux(SB),7,$0
DWORD $_main<>(SB)
DWORD $0
DWORD $0
TEXT _main<>(SB),NOSPLIT,$-8
MOVD 0(R1), R3 // argc
ADD $8, R1, R4 // argv
BR main(SB)
TEXT main(SB),NOSPLIT,$-8
MOVD $_rt0_go(SB), R31
MOVD R31, CTR
BR (CTR)

View File

@ -0,0 +1,14 @@
#include "../../cmd/ld/textflag.h"
TEXT _rt0_power64le_linux(SB),7,$0
BR _main<>(SB)
TEXT _main<>(SB),NOSPLIT,$-8
MOVD 0(R1), R3 // argc
ADD $8, R1, R4 // argv
BR main(SB)
TEXT main(SB),NOSPLIT,$-8
MOVD $_rt0_go(SB), R31
MOVD R31, CTR
BR (CTR)

View File

@ -0,0 +1,49 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)

View File

@ -0,0 +1,49 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define SIG_REGS(ctxt) (*((Sigcontext*)&((Ucontext*)(ctxt))->uc_mcontext)->regs)
#define SIG_R0(info, ctxt) (SIG_REGS(ctxt).gpr[0])
#define SIG_R1(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_R2(info, ctxt) (SIG_REGS(ctxt).gpr[2])
#define SIG_R3(info, ctxt) (SIG_REGS(ctxt).gpr[3])
#define SIG_R4(info, ctxt) (SIG_REGS(ctxt).gpr[4])
#define SIG_R5(info, ctxt) (SIG_REGS(ctxt).gpr[5])
#define SIG_R6(info, ctxt) (SIG_REGS(ctxt).gpr[6])
#define SIG_R7(info, ctxt) (SIG_REGS(ctxt).gpr[7])
#define SIG_R8(info, ctxt) (SIG_REGS(ctxt).gpr[8])
#define SIG_R9(info, ctxt) (SIG_REGS(ctxt).gpr[9])
#define SIG_R10(info, ctxt) (SIG_REGS(ctxt).gpr[10])
#define SIG_R11(info, ctxt) (SIG_REGS(ctxt).gpr[11])
#define SIG_R12(info, ctxt) (SIG_REGS(ctxt).gpr[12])
#define SIG_R13(info, ctxt) (SIG_REGS(ctxt).gpr[13])
#define SIG_R14(info, ctxt) (SIG_REGS(ctxt).gpr[14])
#define SIG_R15(info, ctxt) (SIG_REGS(ctxt).gpr[15])
#define SIG_R16(info, ctxt) (SIG_REGS(ctxt).gpr[16])
#define SIG_R17(info, ctxt) (SIG_REGS(ctxt).gpr[17])
#define SIG_R18(info, ctxt) (SIG_REGS(ctxt).gpr[18])
#define SIG_R19(info, ctxt) (SIG_REGS(ctxt).gpr[19])
#define SIG_R20(info, ctxt) (SIG_REGS(ctxt).gpr[20])
#define SIG_R21(info, ctxt) (SIG_REGS(ctxt).gpr[21])
#define SIG_R22(info, ctxt) (SIG_REGS(ctxt).gpr[22])
#define SIG_R23(info, ctxt) (SIG_REGS(ctxt).gpr[23])
#define SIG_R24(info, ctxt) (SIG_REGS(ctxt).gpr[24])
#define SIG_R25(info, ctxt) (SIG_REGS(ctxt).gpr[25])
#define SIG_R26(info, ctxt) (SIG_REGS(ctxt).gpr[26])
#define SIG_R27(info, ctxt) (SIG_REGS(ctxt).gpr[27])
#define SIG_R28(info, ctxt) (SIG_REGS(ctxt).gpr[28])
#define SIG_R29(info, ctxt) (SIG_REGS(ctxt).gpr[29])
#define SIG_R30(info, ctxt) (SIG_REGS(ctxt).gpr[30])
#define SIG_R31(info, ctxt) (SIG_REGS(ctxt).gpr[31])
#define SIG_SP(info, ctxt) (SIG_REGS(ctxt).gpr[1])
#define SIG_PC(info, ctxt) (SIG_REGS(ctxt).nip)
#define SIG_TRAP(info, ctxt) (SIG_REGS(ctxt).trap)
#define SIG_CTR(info, ctxt) (SIG_REGS(ctxt).ctr)
#define SIG_LINK(info, ctxt) (SIG_REGS(ctxt).link)
#define SIG_XER(info, ctxt) (SIG_REGS(ctxt).xer)
#define SIG_CCR(info, ctxt) (SIG_REGS(ctxt).ccr)
#define SIG_CODE0(info, ctxt) ((uintptr)(info)->si_code)
#define SIG_FAULT(info, ctxt) (SIG_REGS(ctxt).dar)

View File

@ -0,0 +1,137 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build power64 power64le
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
#include "signal_GOOS_GOARCH.h"
#include "signals_GOOS.h"
void
runtime·dumpregs(Siginfo *info, void *ctxt)
{
USED(info); USED(ctxt);
runtime·printf("r0 %X\t", SIG_R0(info, ctxt));
runtime·printf("r1 %X\n", SIG_R1(info, ctxt));
runtime·printf("r2 %X\t", SIG_R2(info, ctxt));
runtime·printf("r3 %X\n", SIG_R3(info, ctxt));
runtime·printf("r4 %X\t", SIG_R4(info, ctxt));
runtime·printf("r5 %X\n", SIG_R5(info, ctxt));
runtime·printf("r6 %X\t", SIG_R6(info, ctxt));
runtime·printf("r7 %X\n", SIG_R7(info, ctxt));
runtime·printf("r8 %X\t", SIG_R8(info, ctxt));
runtime·printf("r9 %X\n", SIG_R9(info, ctxt));
runtime·printf("r10 %X\t", SIG_R10(info, ctxt));
runtime·printf("r11 %X\n", SIG_R11(info, ctxt));
runtime·printf("r12 %X\t", SIG_R12(info, ctxt));
runtime·printf("r13 %X\n", SIG_R13(info, ctxt));
runtime·printf("r14 %X\t", SIG_R14(info, ctxt));
runtime·printf("r15 %X\n", SIG_R15(info, ctxt));
runtime·printf("r16 %X\t", SIG_R16(info, ctxt));
runtime·printf("r17 %X\n", SIG_R17(info, ctxt));
runtime·printf("r18 %X\t", SIG_R18(info, ctxt));
runtime·printf("r19 %X\n", SIG_R19(info, ctxt));
runtime·printf("r20 %X\t", SIG_R20(info, ctxt));
runtime·printf("r21 %X\n", SIG_R21(info, ctxt));
runtime·printf("r22 %X\t", SIG_R22(info, ctxt));
runtime·printf("r23 %X\n", SIG_R23(info, ctxt));
runtime·printf("r24 %X\t", SIG_R24(info, ctxt));
runtime·printf("r25 %X\n", SIG_R25(info, ctxt));
runtime·printf("r26 %X\t", SIG_R26(info, ctxt));
runtime·printf("r27 %X\n", SIG_R27(info, ctxt));
runtime·printf("r28 %X\t", SIG_R28(info, ctxt));
runtime·printf("r29 %X\n", SIG_R29(info, ctxt));
runtime·printf("r30 %X\t", SIG_R30(info, ctxt));
runtime·printf("r31 %X\n", SIG_R31(info, ctxt));
runtime·printf("pc %X\t", SIG_PC(info, ctxt));
runtime·printf("ctr %X\n", SIG_CTR(info, ctxt));
runtime·printf("link %X\t", SIG_LINK(info, ctxt));
runtime·printf("xer %X\n", SIG_XER(info, ctxt));
runtime·printf("ccr %X\t", SIG_CCR(info, ctxt));
runtime·printf("trap %X\n", SIG_TRAP(info, ctxt));
}
void
runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
{
SigTab *t;
bool crash;
if(sig == SIGPROF) {
runtime·sigprof((uint8*)SIG_PC(info, ctxt), (uint8*)SIG_SP(info, ctxt), (uint8*)SIG_LINK(info, ctxt), gp, g->m);
return;
}
t = &runtime·sigtab[sig];
if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
// the unwinding code.
gp->sig = sig;
gp->sigcode0 = SIG_CODE0(info, ctxt);
gp->sigcode1 = SIG_FAULT(info, ctxt);
gp->sigpc = SIG_PC(info, ctxt);
// We arrange link, and pc to pretend the panicking
// function calls sigpanic directly.
// Always save LINK to stack so that panics in leaf
// functions are correctly handled. This smashes
// the stack frame but we're not going back there
// anyway.
SIG_SP(info, ctxt) -= sizeof(uintptr);
*(uintptr*)SIG_SP(info, ctxt) = SIG_LINK(info, ctxt);
// Don't bother saving PC if it's zero, which is
// probably a call to a nil func: the old link register
// is more useful in the stack trace.
if(gp->sigpc != 0)
SIG_LINK(info, ctxt) = gp->sigpc;
// In case we are panicking from external C code
SIG_R0(info, ctxt) = 0;
SIG_R30(info, ctxt) = (uintptr)gp;
SIG_PC(info, ctxt) = (uintptr)runtime·sigpanic;
return;
}
if(SIG_CODE0(info, ctxt) == SI_USER || (t->flags & SigNotify))
if(runtime·sigsend(sig))
return;
if(t->flags & SigKill)
runtime·exit(2);
if(!(t->flags & SigThrow))
return;
g->m->throwing = 1;
g->m->caughtsig = gp;
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
if(sig < 0 || sig >= NSIG)
runtime·printf("Signal %d\n", sig);
else
runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", SIG_PC(info, ctxt));
if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = g->m->lockedg;
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·goroutineheader(gp);
runtime·traceback(SIG_PC(info, ctxt), SIG_SP(info, ctxt), SIG_LINK(info, ctxt), gp);
runtime·tracebackothers(gp);
runtime·printf("\n");
runtime·dumpregs(info, ctxt);
}
if(crash)
runtime·crash();
runtime·exit(2);
}

View File

@ -0,0 +1,369 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build power64 power64le
//
// System calls and other sys.stuff for Power64, Linux
//
#include "zasm_GOOS_GOARCH.h"
#include "../../cmd/ld/textflag.h"
#define SYS_exit 1
#define SYS_read 3
#define SYS_write 4
#define SYS_open 5
#define SYS_close 6
#define SYS_fcntl 55
#define SYS_gettimeofday 78
#define SYS_select 82 // always return -ENOSYS
#define SYS_mmap 90
#define SYS_munmap 91
#define SYS_setitimer 104
#define SYS_clone 120
#define SYS_newselect 142
#define SYS_sched_yield 158
#define SYS_rt_sigreturn 172
#define SYS_rt_sigaction 173
#define SYS_rt_sigprocmask 174
#define SYS_sigaltstack 185
#define SYS_ugetrlimit 190
#define SYS_madvise 205
#define SYS_mincore 206
#define SYS_gettid 207
#define SYS_tkill 208
#define SYS_futex 221
#define SYS_sched_getaffinity 223
#define SYS_exit_group 234
#define SYS_epoll_create 236
#define SYS_epoll_ctl 237
#define SYS_epoll_wait 238
#define SYS_clock_gettime 246
#define SYS_epoll_create1 315
TEXT runtime·exit(SB),NOSPLIT,$-8-8
MOVW 8(R1), R3
SYSCALL $SYS_exit_group
RETURN
TEXT runtime·exit1(SB),NOSPLIT,$-8-8
MOVW 8(R1), R3
SYSCALL $SYS_exit
RETURN
TEXT runtime·open(SB),NOSPLIT,$-8-16
MOVD 8(R1), R3
MOVW 16(R1), R4
MOVW 20(R1), R5
SYSCALL $SYS_open
RETURN
TEXT runtime·close(SB),NOSPLIT,$-8-16
MOVW 8(R1), R3
SYSCALL $SYS_close
RETURN
TEXT runtime·write(SB),NOSPLIT,$-8-24
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVW 24(R1), R5
SYSCALL $SYS_write
RETURN
TEXT runtime·read(SB),NOSPLIT,$-8-24
MOVW 8(R1), R3
MOVD 16(R1), R4
MOVW 24(R1), R5
SYSCALL $SYS_read
RETURN
TEXT runtime·getrlimit(SB),NOSPLIT,$-8-24
MOVW 8(R1), R3
MOVD 16(R1), R4
SYSCALL $SYS_ugetrlimit // ??? why not use SYS_getrlimit
RETURN
TEXT runtime·usleep(SB),NOSPLIT,$-8-16
MOVW usec+0(FP), R3
MOVD R3, R5
MOVW $1000000, R4
DIVD R4, R3
MOVD R3, 0(R1)
MULLD R3, R4
SUB R4, R5
MOVD R5, 8(R1)
// select(0, 0, 0, 0, &tv)
MOVW $0, R3
MOVW $0, R4
MOVW $0, R5
MOVW $0, R6
MOVD R1, R7
SYSCALL $SYS_newselect
RETURN
TEXT runtime·raise(SB),NOSPLIT,$-8
SYSCALL $SYS_gettid
MOVW R3, R3 // arg 1 tid
MOVW sig+0(FP), R4 // arg 2
SYSCALL $SYS_tkill
RETURN
TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
MOVW 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
SYSCALL $SYS_setitimer
RETURN
TEXT runtime·mincore(SB),NOSPLIT,$-8-24
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
SYSCALL $SYS_mincore
RETURN
// func now() (sec int64, nsec int32)
TEXT time·now(SB),NOSPLIT,$16
MOVD $0(R1), R3
MOVD $0, R4
SYSCALL $SYS_gettimeofday
MOVD 0(R1), R3 // sec
MOVW 8(R1), R5 // usec
MOVD $1000, R4
MULLD R4, R5
MOVD R3, sec+0(FP)
MOVW R5, nsec+8(FP)
RETURN
TEXT runtime·nanotime(SB),NOSPLIT,$16
MOVW $1, R3 // CLOCK_MONOTONIC
MOVD $0(R1), R4
SYSCALL $SYS_clock_gettime
MOVD 0(R1), R3 // sec
MOVD 8(R1), R5 // nsec
// sec is in R3, nsec in R5
// return nsec in R3
MOVD $1000000000, R4
MULLD R4, R3
ADD R5, R3
RETURN
TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-32
MOVW 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
MOVW 32(R1), R6
SYSCALL $SYS_rt_sigprocmask
BVC 2(PC)
MOVD R0, 0xf1(R0) // crash
RETURN
TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-32
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
MOVD 32(R1), R6
SYSCALL $SYS_rt_sigaction
RETURN
#ifdef GOARCH_power64le
// power64le doesn't need function descriptors
TEXT runtime·sigtramp(SB),NOSPLIT,$64
#else
// function descriptor for the real sigtramp
TEXT runtime·sigtramp(SB),NOSPLIT,$-8
DWORD $runtime·_sigtramp(SB)
DWORD $0
DWORD $0
TEXT runtime·_sigtramp(SB),NOSPLIT,$64
#endif
// initialize essential registers (just in case)
BL runtime·reginit(SB)
// check that g exists
CMP g, $0
BNE 6(PC)
MOVD R3, 8(R1)
MOVD $runtime·badsignal(SB), R31
MOVD R31, CTR
BL (CTR)
RETURN
// save g
MOVD g, 40(R1)
MOVD g, R6
// g = m->gsignal
MOVD g_m(g), R7
MOVD m_gsignal(R7), g
MOVW R3, 8(R1)
MOVD R4, 16(R1)
MOVD R5, 24(R1)
MOVD R6, 32(R1)
BL runtime·sighandler(SB)
// restore g
MOVD 40(R1), g
RETURN
TEXT runtime·mmap(SB),NOSPLIT,$-8
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVW 24(R1), R5
MOVW 28(R1), R6
MOVW 32(R1), R7
MOVW 36(R1), R8
SYSCALL $SYS_mmap
BVC 2(PC)
NEG R3, R3
RETURN
TEXT runtime·munmap(SB),NOSPLIT,$-8
MOVD 8(R1), R3
MOVD 16(R1), R4
SYSCALL $SYS_munmap
BVC 2(PC)
MOVD R0, 0xf3(R0)
RETURN
TEXT runtime·madvise(SB),NOSPLIT,$-8
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
SYSCALL $SYS_madvise
// ignore failure - maybe pages are locked
RETURN
// int64 futex(int32 *uaddr, int32 op, int32 val,
// struct timespec *timeout, int32 *uaddr2, int32 val2);
TEXT runtime·futex(SB),NOSPLIT,$-8
MOVD 8(R1), R3
MOVW 16(R1), R4
MOVW 20(R1), R5
MOVD 24(R1), R6
MOVD 32(R1), R7
MOVW 40(R1), R8
SYSCALL $SYS_futex
RETURN
// int64 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void));
TEXT runtime·clone(SB),NOSPLIT,$-8
MOVW flags+0(FP), R3
MOVD stack+8(FP), R4
// Copy mp, gp, fn off parent stack for use by child.
// Careful: Linux system call clobbers ???.
MOVD mm+16(FP), R7
MOVD gg+24(FP), R8
MOVD fn+32(FP), R12
MOVD R7, -8(R4)
MOVD R8, -16(R4)
MOVD R12, -24(R4)
MOVD $1234, R7
MOVD R7, -32(R4)
SYSCALL $SYS_clone
// In parent, return.
CMP R3, $0
BEQ 2(PC)
RETURN
// In child, on new stack.
// initialize essential registers
BL runtime·reginit(SB)
MOVD -32(R1), R7
CMP R7, $1234
BEQ 2(PC)
MOVD R0, 0(R0)
// Initialize m->procid to Linux tid
SYSCALL $SYS_gettid
MOVD -24(R1), R12
MOVD -16(R1), R8
MOVD -8(R1), R7
MOVD R3, m_procid(R7)
// TODO: setup TLS.
// In child, set up new stack
MOVD R7, g_m(R8)
MOVD R8, g
//CALL runtime·stackcheck(SB)
// Call fn
MOVD R12, CTR
BL (CTR)
// It shouldn't return. If it does, exit
MOVW $111, R3
SYSCALL $SYS_exit_group
BR -2(PC) // keep exiting
TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
MOVD new+0(FP), R3
MOVD old+8(FP), R4
SYSCALL $SYS_sigaltstack
BVC 2(PC)
MOVD R0, 0xf1(R0) // crash
RETURN
TEXT runtime·osyield(SB),NOSPLIT,$-8
SYSCALL $SYS_sched_yield
RETURN
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
MOVD 8(R1), R3
MOVD 16(R1), R4
MOVD 24(R1), R5
SYSCALL $SYS_sched_getaffinity
RETURN
// int32 runtime·epollcreate(int32 size);
TEXT runtime·epollcreate(SB),NOSPLIT,$-8
MOVW 8(R1), R3
SYSCALL $SYS_epoll_create
RETURN
// int32 runtime·epollcreate1(int32 flags);
TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
MOVW 8(R1), R3
SYSCALL $SYS_epoll_create1
RETURN
// int32 runtime·epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev);
TEXT runtime·epollctl(SB),NOSPLIT,$-8
MOVW 8(R1), R3
MOVW 12(R1), R4
MOVW 16(R1), R5
MOVD 24(R1), R6
SYSCALL $SYS_epoll_ctl
RETURN
// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
TEXT runtime·epollwait(SB),NOSPLIT,$-8
MOVW 8(R1), R3
MOVD 16(R1), R4
MOVW 24(R1), R5
MOVW 28(R1), R6
SYSCALL $SYS_epoll_wait
RETURN
// void runtime·closeonexec(int32 fd);
TEXT runtime·closeonexec(SB),NOSPLIT,$-8
MOVW 8(R1), R3 // fd
MOVD $2, R4 // F_SETFD
MOVD $1, R5 // FD_CLOEXEC
SYSCALL $SYS_fcntl
RETURN

View File

@ -0,0 +1,38 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build power64 power64le
#include "runtime.h"
// adjust Gobuf as if it executed a call to fn with context ctxt
// and then did an immediate Gosave.
void
runtime·gostartcall(Gobuf *gobuf, void (*fn)(void), void *ctxt)
{
if(gobuf->lr != 0)
runtime·throw("invalid use of gostartcall");
gobuf->lr = gobuf->pc;
gobuf->pc = (uintptr)fn;
gobuf->ctxt = ctxt;
}
// Called to rewind context saved during morestack back to beginning of function.
// To help us, the linker emits a jmp back to the beginning right after the
// call to morestack. We just have to decode and apply that jump.
void
runtime·rewindmorestack(Gobuf *gobuf)
{
uint32 inst;
inst = *(uint32*)gobuf->pc;
if((gobuf->pc&3) == 0 && (inst>>24) == 0x4b && (inst&3) == 0) {
runtime·printf("runtime: rewind pc=%p to pc=%p\n", gobuf->pc, gobuf->pc + ((int32)(inst<<8)>>8));
gobuf->pc += (int32)(inst<<8)>>8;
return;
}
runtime·printf("runtime: pc=%p %x\n", gobuf->pc, inst);
runtime·throw("runtime: misuse of rewindmorestack");
}