[dev.cc] runtime: convert power64 signal handlers from C to Go

The power64 equivalent of CL 168500044

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/175280043
diff --git a/src/runtime/signal_linux_power64.h b/src/runtime/signal_linux_power64.h
deleted file mode 100644
index 8406489..0000000
--- a/src/runtime/signal_linux_power64.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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)
diff --git a/src/runtime/signal_linux_power64le.h b/src/runtime/signal_linux_power64le.h
deleted file mode 100644
index 8406489..0000000
--- a/src/runtime/signal_linux_power64le.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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)
diff --git a/src/runtime/signal_linux_power64x.go b/src/runtime/signal_linux_power64x.go
new file mode 100644
index 0000000..8f357033
--- /dev/null
+++ b/src/runtime/signal_linux_power64x.go
@@ -0,0 +1,71 @@
+// 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
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+	info *siginfo
+	ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *ptregs { return (*ucontext)(c.ctxt).uc_mcontext.regs }
+func (c *sigctxt) r0() uint64    { return c.regs().gpr[0] }
+func (c *sigctxt) r1() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) r2() uint64    { return c.regs().gpr[2] }
+func (c *sigctxt) r3() uint64    { return c.regs().gpr[3] }
+func (c *sigctxt) r4() uint64    { return c.regs().gpr[4] }
+func (c *sigctxt) r5() uint64    { return c.regs().gpr[5] }
+func (c *sigctxt) r6() uint64    { return c.regs().gpr[6] }
+func (c *sigctxt) r7() uint64    { return c.regs().gpr[7] }
+func (c *sigctxt) r8() uint64    { return c.regs().gpr[8] }
+func (c *sigctxt) r9() uint64    { return c.regs().gpr[9] }
+func (c *sigctxt) r10() uint64   { return c.regs().gpr[10] }
+func (c *sigctxt) r11() uint64   { return c.regs().gpr[11] }
+func (c *sigctxt) r12() uint64   { return c.regs().gpr[12] }
+func (c *sigctxt) r13() uint64   { return c.regs().gpr[13] }
+func (c *sigctxt) r14() uint64   { return c.regs().gpr[14] }
+func (c *sigctxt) r15() uint64   { return c.regs().gpr[15] }
+func (c *sigctxt) r16() uint64   { return c.regs().gpr[16] }
+func (c *sigctxt) r17() uint64   { return c.regs().gpr[17] }
+func (c *sigctxt) r18() uint64   { return c.regs().gpr[18] }
+func (c *sigctxt) r19() uint64   { return c.regs().gpr[19] }
+func (c *sigctxt) r20() uint64   { return c.regs().gpr[20] }
+func (c *sigctxt) r21() uint64   { return c.regs().gpr[21] }
+func (c *sigctxt) r22() uint64   { return c.regs().gpr[22] }
+func (c *sigctxt) r23() uint64   { return c.regs().gpr[23] }
+func (c *sigctxt) r24() uint64   { return c.regs().gpr[24] }
+func (c *sigctxt) r25() uint64   { return c.regs().gpr[25] }
+func (c *sigctxt) r26() uint64   { return c.regs().gpr[26] }
+func (c *sigctxt) r27() uint64   { return c.regs().gpr[27] }
+func (c *sigctxt) r28() uint64   { return c.regs().gpr[28] }
+func (c *sigctxt) r29() uint64   { return c.regs().gpr[29] }
+func (c *sigctxt) r30() uint64   { return c.regs().gpr[30] }
+func (c *sigctxt) r31() uint64   { return c.regs().gpr[31] }
+func (c *sigctxt) sp() uint64    { return c.regs().gpr[1] }
+func (c *sigctxt) pc() uint64    { return c.regs().nip }
+func (c *sigctxt) trap() uint64  { return c.regs().trap }
+func (c *sigctxt) ctr() uint64   { return c.regs().ctr }
+func (c *sigctxt) link() uint64  { return c.regs().link }
+func (c *sigctxt) xer() uint64   { return c.regs().xer }
+func (c *sigctxt) ccr() uint64   { return c.regs().ccr }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return uint64(*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize))) }
+func (c *sigctxt) fault() uint64   { return c.regs().dar }
+
+func (c *sigctxt) set_r0(x uint64)   { c.regs().gpr[0] = x }
+func (c *sigctxt) set_r30(x uint64)  { c.regs().gpr[30] = x }
+func (c *sigctxt) set_pc(x uint64)   { c.regs().nip = x }
+func (c *sigctxt) set_sp(x uint64)   { c.regs().gpr[1] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().link = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_power64x.c b/src/runtime/signal_power64x.c
deleted file mode 100644
index c0bf1c4..0000000
--- a/src/runtime/signal_power64x.c
+++ /dev/null
@@ -1,137 +0,0 @@
-// 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·tracebacktrap(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);
-}
diff --git a/src/runtime/signal_power64x.go b/src/runtime/signal_power64x.go
new file mode 100644
index 0000000..fc83beb
--- /dev/null
+++ b/src/runtime/signal_power64x.go
@@ -0,0 +1,144 @@
+// 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
+
+package runtime
+
+import "unsafe"
+
+func dumpregs(c *sigctxt) {
+	print("r0   ", hex(c.r0()), "\t")
+	print("r1   ", hex(c.r1()), "\n")
+	print("r2   ", hex(c.r2()), "\t")
+	print("r3   ", hex(c.r3()), "\n")
+	print("r4   ", hex(c.r4()), "\t")
+	print("r5   ", hex(c.r5()), "\n")
+	print("r6   ", hex(c.r6()), "\t")
+	print("r7   ", hex(c.r7()), "\n")
+	print("r8   ", hex(c.r8()), "\t")
+	print("r9   ", hex(c.r9()), "\n")
+	print("r10  ", hex(c.r10()), "\t")
+	print("r11  ", hex(c.r11()), "\n")
+	print("r12  ", hex(c.r12()), "\t")
+	print("r13  ", hex(c.r13()), "\n")
+	print("r14  ", hex(c.r14()), "\t")
+	print("r15  ", hex(c.r15()), "\n")
+	print("r16  ", hex(c.r16()), "\t")
+	print("r17  ", hex(c.r17()), "\n")
+	print("r18  ", hex(c.r18()), "\t")
+	print("r19  ", hex(c.r19()), "\n")
+	print("r20  ", hex(c.r20()), "\t")
+	print("r21  ", hex(c.r21()), "\n")
+	print("r22  ", hex(c.r22()), "\t")
+	print("r23  ", hex(c.r23()), "\n")
+	print("r24  ", hex(c.r24()), "\t")
+	print("r25  ", hex(c.r25()), "\n")
+	print("r26  ", hex(c.r26()), "\t")
+	print("r27  ", hex(c.r27()), "\n")
+	print("r28  ", hex(c.r28()), "\t")
+	print("r29  ", hex(c.r29()), "\n")
+	print("r30  ", hex(c.r30()), "\t")
+	print("r31  ", hex(c.r31()), "\n")
+	print("pc   ", hex(c.pc()), "\t")
+	print("ctr  ", hex(c.ctr()), "\n")
+	print("link ", hex(c.link()), "\t")
+	print("xer  ", hex(c.xer()), "\n")
+	print("ccr  ", hex(c.ccr()), "\t")
+	print("trap ", hex(c.trap()), "\n")
+}
+
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+	_g_ := getg()
+	c := &sigctxt{info, ctxt}
+
+	if sig == _SIGPROF {
+		sigprof((*byte)(unsafe.Pointer(uintptr(c.pc()))), (*byte)(unsafe.Pointer(uintptr(c.sp()))), (*byte)(unsafe.Pointer(uintptr(c.link()))), gp, _g_.m)
+		return
+	}
+	flags := int32(_SigThrow)
+	if sig < uint32(len(sigtable)) {
+		flags = sigtable[sig].flags
+	}
+	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+		// 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 = uintptr(c.sigcode())
+		gp.sigcode1 = uintptr(c.fault())
+		gp.sigpc = uintptr(c.pc())
+
+		// 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.
+		sp := c.sp() - ptrSize
+		c.set_sp(sp)
+		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+		// 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 {
+			c.set_link(uint64(gp.sigpc))
+		}
+
+		// In case we are panicking from external C code
+		c.set_r0(0)
+		c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+		c.set_pc(uint64(funcPC(sigpanic)))
+		return
+	}
+
+	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+		if sigsend(sig) {
+			return
+		}
+	}
+
+	if flags&_SigKill != 0 {
+		exit(2)
+	}
+
+	if flags&_SigThrow == 0 {
+		return
+	}
+
+	_g_.m.throwing = 1
+	_g_.m.caughtsig = gp
+	startpanic()
+
+	if sig < uint32(len(sigtable)) {
+		print(sigtable[sig].name, "\n")
+	} else {
+		print("Signal ", sig, "\n")
+	}
+
+	print("PC=", hex(c.pc()), "\n")
+	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+		print("signal arrived during cgo execution\n")
+		gp = _g_.m.lockedg
+	}
+	print("\n")
+
+	var docrash bool
+	if gotraceback(&docrash) > 0 {
+		goroutineheader(gp)
+		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
+		tracebackothers(gp)
+		print("\n")
+		dumpregs(c)
+	}
+
+	if docrash {
+		crash()
+	}
+
+	exit(2)
+}