add signal handling and traceback support therein.
factor the runtime into architecture-dependent and -independent pieces.
ditto for the OS dependence.

SVN=124020
diff --git a/src/runtime/make.bash b/src/runtime/make.bash
index 46a920b..9a6d42e 100644
--- a/src/runtime/make.bash
+++ b/src/runtime/make.bash
@@ -10,5 +10,14 @@
 $HOME/bin/6a rt0_amd64_linux.s
 mv rt0_amd64_linux.6 ../../lib/rt0_amd64_linux.6
 
+$HOME/bin/6c rt1_amd64_linux.c
+mv rt1_amd64_linux.6 ../../lib/rt1_amd64_linux.6
+
+$HOME/bin/6c rt1_amd64_darwin.c
+mv rt1_amd64_darwin.6 ../../lib/rt1_amd64_darwin.6
+
+$HOME/bin/6c rt2_amd64.c
+mv rt2_amd64.6 ../../lib/rt2_amd64.6
+
 $HOME/bin/6c runtime.c
 mv runtime.6 ../../lib/rt_amd64.6
diff --git a/src/runtime/rt0_amd64_linux.s b/src/runtime/rt0_amd64_linux.s
index 6ad8b33..27064a4 100644
--- a/src/runtime/rt0_amd64_linux.s
+++ b/src/runtime/rt0_amd64_linux.s
@@ -52,6 +52,25 @@
 	CALL	notok(SB)
 	RET
 
+TEXT	sys_rt_sigaction(SB),1,$-8
+	MOVL	8(SP), DI
+	MOVQ	16(SP), SI
+	MOVQ	24(SP), DX
+	MOVQ	32(SP), CX
+	MOVL	CX, R10
+	MOVL	$13, AX			// syscall entry
+	SYSCALL
+	JCC	2(PC)
+	CALL	notok(SB)
+	RET
+
+TEXT sigtramp(SB),1,$24
+	MOVQ	DI,0(SP)
+	MOVQ	SI,8(SP)
+	MOVQ	DX,16(SP)
+	CALL	sighandler(SB)
+	RET
+
 TEXT	sys_breakpoint(SB),1,$-8
 	BYTE	$0xcc
 	RET
diff --git a/src/runtime/rt1_amd64_darwin.c b/src/runtime/rt1_amd64_darwin.c
new file mode 100644
index 0000000..fe92d0b
--- /dev/null
+++ b/src/runtime/rt1_amd64_darwin.c
@@ -0,0 +1,11 @@
+// Copyright 2009 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.
+
+#include "runtime.h"
+
+void
+initsig(void)
+{
+	/* no signal handler on mac yet */
+}
diff --git a/src/runtime/rt1_amd64_linux.c b/src/runtime/rt1_amd64_linux.c
new file mode 100644
index 0000000..de6ac7f
--- /dev/null
+++ b/src/runtime/rt1_amd64_linux.c
@@ -0,0 +1,75 @@
+// Copyright 2009 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.
+
+#include "runtime.h"
+#include "signals.h"
+
+/*
+ * This assembler routine takes the args from registers, puts them on the stack,
+ * and calls sighandler().
+ */
+extern void sigtramp();
+
+/*
+ * Rudimentary reverse-engineered definition of signal interface.
+ * You'd think it would be documented.
+ */
+typedef struct siginfo {
+	int32	si_signo;		/* signal number */
+	int32	si_errno;		/* errno association */
+	int32	si_code;		/* signal code */
+	int32	si_status;		/* exit value */
+	void	*si_addr;		/* faulting address */
+	/* more stuff here */
+} siginfo;
+
+typedef struct  sigaction {
+ 	union {
+		void    (*sa_handler)(int32);
+		void    (*sa_sigaction)(int32, siginfo *, void *);
+	} u;		     /* signal handler */
+	int32     sa_flags;		     /* see signal options below */
+	uint8 sa_mask[2];		     /* signal mask to apply. BUG: 2 is a guess */
+} sigaction;
+
+void
+sighandler(int32 sig, siginfo* info, void** context) {
+	int32 i;
+
+	if(sig < 0 || sig >= NSIG){
+		prints("Signal ");
+		sys_printint(sig);
+	}else{
+		prints(sigtab[sig].name);
+	}
+	prints("\nFaulting address: 0x");
+	sys_printpointer(info->si_addr);
+	prints("\nPC: 0x");
+	sys_printpointer(context[21]);
+	prints("\nSP: 0x");
+	sys_printpointer(context[20]);
+	prints("\n");
+	traceback(context[21], context[20]);	/* empirically discovered locations */
+	sys_breakpoint();
+	sys_exit(2);
+}
+
+sigaction a;
+
+void
+initsig(void)
+{
+	int32 i;
+	a.u.sa_sigaction = (void*)sigtramp;
+	a.sa_flags = 1|2|4|0x10000000|0x20000000|0x40000000|0x80000000;
+	//a.sa_flags |= SA_SIGINFO;
+	a.sa_flags = ~0;	/* BUG: why is this needed? */
+	for(i=0; i<sizeof(a.sa_mask); i++)
+		a.sa_mask[i] = 0xFF;
+	//a.sa_mask[1] = (1 << (11-1));
+	for(i = 0; i <NSIG; i++)
+		if(sigtab[i].catch){
+			sys_rt_sigaction(i, &a, (void*)0, 8);
+		}
+}
diff --git a/src/runtime/rt2_amd64.c b/src/runtime/rt2_amd64.c
new file mode 100644
index 0000000..1145ff7
--- /dev/null
+++ b/src/runtime/rt2_amd64.c
@@ -0,0 +1,68 @@
+// Copyright 2009 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.
+
+#include "runtime.h"
+
+extern int32	debug;
+
+static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe";
+
+void
+traceback(uint8 *pc, uint8 *sp)
+{
+	int32 spoff;
+	int8* spp;
+	int32 counter;
+	int32 i;
+	int8* name;
+
+
+	counter = 0;
+	name = "panic";
+	for(;;){
+		prints("0x");
+		sys_printpointer(pc);
+		prints("?zi\n");
+		/* find SP offset by stepping back through instructions to SP offset marker */
+		while(pc > (uint8*)0x1000+sizeof spmark-1) {
+			for(spp = spmark; *spp != '\0' && *pc++ == (uint8)*spp++; )
+				;
+			if(*spp == '\0'){
+				spoff = *pc++;
+				spoff += *pc++ << 8;
+				spoff += *pc++ << 16;
+				name = (int8*)pc;
+				sp += spoff + 8;
+				break;
+			}
+		}
+		if(counter++ > 100){
+			prints("stack trace terminated\n");
+			break;
+		}
+		if((pc = ((uint8**)sp)[-1]) <= (uint8*)0x1000)
+			break;
+		/* print args for this frame */
+		prints("\t");
+		prints(name);
+		prints("(");
+		for(i = 0; i < 3; i++){
+			if(i != 0)
+				prints(", ");
+			sys_printint(((uint32*)sp)[i]);
+		}
+		prints(", ...)\n");
+		prints("\t");
+		prints(name);
+		prints("(");
+		for(i = 0; i < 3; i++){
+			if(i != 0)
+				prints(", ");
+			prints("0x");
+			sys_printpointer(((void**)sp)[i]);
+		}
+		prints(", ...)\n");
+		/* print pc for next frame */
+	}
+}
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index 0e62dbd..e8c1838 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -103,15 +103,7 @@
 void
 sys_panicl(int32 lno)
 {
-	uint8 *pc;
 	uint8 *sp;
-	uint8 *retpc;
-	int32 spoff;
-	static int8 spmark[] = "\xa7\xf1\xd9\x2a\x82\xc8\xd8\xfe";
-	int8* spp;
-	int32 counter;
-	int32 i;
-	int8* name;
 
 	prints("\npanic on line ");
 	sys_printint(lno);
@@ -119,55 +111,9 @@
 	sys_printpc(&lno);
 	prints("\n");
 	sp = (uint8*)&lno;
-	pc = (uint8*)sys_panicl;
-	counter = 0;
-	name = "panic";
-	while((pc = ((uint8**)sp)[-1]) > (uint8*)0x1000) {
-		/* print args for this frame */
-		prints("\t");
-		prints(name);
-		prints("(");
-		for(i = 0; i < 3; i++){
-			if(i != 0)
-				prints(", ");
-			sys_printint(((uint32*)sp)[i]);
-		}
-		prints(", ...)\n");
-		prints("\t");
-		prints(name);
-		prints("(");
-		for(i = 0; i < 3; i++){
-			if(i != 0)
-				prints(", ");
-			prints("0x");
-			sys_printpointer(((void**)sp)[i]);
-		}
-		prints(", ...)\n");
-		/* print pc for next frame */
-		prints("0x");
-		sys_printpointer(pc);
-		prints("?zi\n");
-		/* next word down on stack is PC */
-		retpc = pc;
-		/* find SP offset by stepping back through instructions to SP offset marker */
-		while(pc > (uint8*)0x1000+11) {
-			for(spp = spmark; *spp != '\0' && *pc++ == (uint8)*spp++; )
-				;
-			if(*spp == '\0'){
-				spoff = *pc++;
-				spoff += *pc++ << 8;
-				spoff += *pc++ << 16;
-				name = (int8*)pc;
-				sp += spoff + 8;
-				break;
-			}
-		}
-		if(counter++ > 100){
-			prints("stack trace terminated\n");
-			break;
-		}
-	}
-	*(int32*)0 = 0;
+	traceback(sys_getcallerpc(&lno), sp);
+	sys_breakpoint();
+	sys_exit(2);
 }
 
 dump(byte *p, int32 n)
@@ -788,7 +734,6 @@
 	FLUSH(&dou2);
 }
 
-void
 check(void)
 {
 	int8 a;
@@ -817,4 +762,5 @@
 	if(sizeof(k) != 8) throw("bad k");
 	if(sizeof(l) != 8) throw("bad l");
 //	prints(1"check ok\n");
+	initsig();
 }
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index 898c7b4..fa9395f 100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -88,6 +88,12 @@
 void	mcpy(byte*, byte*, uint32);
 void*	mal(uint32);
 uint32	cmpstring(string, string);
+void	initsig(void);
+void	traceback(uint8 *pc, uint8 *sp);
+struct SigTab {
+	int32	catch;
+	int8	*name;
+};
 
 /*
  * low level go -called
@@ -98,6 +104,8 @@
 uint8*	sys_mmap(byte*, uint32, int32, int32, int32, uint32);
 void	sys_memclr(byte*, uint32);
 void* sys_getcallerpc(void*);
+void	sys_sigaction(int64, void*, void*);
+void	sys_rt_sigaction(int64, void*, void*, uint64);
 
 /*
  * runtime go-called
diff --git a/src/runtime/signals.h b/src/runtime/signals.h
new file mode 100644
index 0000000..5b2776a
--- /dev/null
+++ b/src/runtime/signals.h
@@ -0,0 +1,40 @@
+// Copyright 2009 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.
+
+
+static struct SigTab sigtab[] = {
+	/* 0 */	0, "SIGNONE: no trap",
+	/* 1 */	0, "SIGHUP: terminal line hangup",
+	/* 2 */	0, "SIGINT: interrupt program",
+	/* 3 */	1, "SIGQUIT: quit program",
+	/* 4 */	1, "SIGILL: illegal instruction",
+	/* 5 */	0, "SIGTRAP: trace trap",	/* uncaught; used by panic and signal handler */
+	/* 6 */	1, "SIGABRT: abort program",
+	/* 7 */	1, "SIGEMT: emulate instruction executed",
+	/* 8 */	1, "SIGFPE: floating-point exception",
+	/* 9 */	0, "SIGKILL: kill program",
+	/* 10 */	1, "SIGBUS: bus error",
+	/* 11 */	1, "SIGSEGV: segmentation violation",
+	/* 12 */	1, "SIGSYS: non-existent system call invoked",
+	/* 13 */	0, "SIGPIPE: write on a pipe with no reader",
+	/* 14 */	0, "SIGALRM: real-time timer expired",
+	/* 15 */	0, "SIGTERM: software termination signal",
+	/* 16 */	0, "SIGURG: urgent condition present on socket",
+	/* 17 */	0, "SIGSTOP: stop",
+	/* 18 */	0, "SIGTSTP: stop signal generated from keyboard",
+	/* 19 */	0, "SIGCONT: continue after stop",
+	/* 20 */	0, "SIGCHLD: child status has changed",
+	/* 21 */	0, "SIGTTIN: background read attempted from control terminal",
+	/* 22 */	0, "SIGTTOU: background write attempted to control terminal",
+	/* 23 */	0, "SIGIO: I/O is possible on a descriptor",
+	/* 24 */	0, "SIGXCPU: cpu time limit exceeded",
+	/* 25 */	0, "SIGXFSZ: file size limit exceeded",
+	/* 26 */	0, "SIGVTALRM: virtual time alarm",
+	/* 27 */	0, "SIGPROF: profiling timer alarm",
+	/* 28 */	0, "SIGWINCH: Window size change",
+	/* 29 */	0, "SIGINFO: status request from keyboard",
+	/* 30 */	0, "SIGUSR1: User defined signal 1",
+	/* 31 */	0, "SIGUSR2: User defined signal 2",
+};
+#define	NSIG 32