s390/s390x updates

diff --git a/include/arch/s390/klibc/archsetjmp.h b/include/arch/s390/klibc/archsetjmp.h
new file mode 100644
index 0000000..11a641e
--- /dev/null
+++ b/include/arch/s390/klibc/archsetjmp.h
@@ -0,0 +1,15 @@
+/*
+ * arch/s390/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+  uint32_t __gregs[10]; /* general registers r6-r15 */
+  uint64_t __fpregs[2]; /* fp registers f4 and f6   */
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
diff --git a/include/arch/s390x/klibc/archsetjmp.h b/include/arch/s390x/klibc/archsetjmp.h
new file mode 100644
index 0000000..dd3ed0d
--- /dev/null
+++ b/include/arch/s390x/klibc/archsetjmp.h
@@ -0,0 +1,15 @@
+/*
+ * arch/s390x/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+  uint64_t __gregs[10]; /* general registers r6-r15 */
+  uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
diff --git a/klibc/README b/klibc/README
index ccbb719..48ac6e3 100644
--- a/klibc/README
+++ b/klibc/README
@@ -21,22 +21,25 @@
    prefix.
 
    IMPORTANT: if you're on a 64-bit machine with a 32-bit userland
-   (such as most sparc or mips machines), and you want to build the
-   32-bit version (usually, but not always smaller); you need to set
-   ARCH to the 32-bit architecture as well as set up the
-   linux/include/asm symlink to point to the 32-bit architecture.
+   (ia64, mips64, ppc64 sparc64, s390x or x86_64), and you want to
+   build the 32-bit version: you need to set ARCH to the 32-bit
+   architecture as well as set up the linux/include/asm symlink to
+   point to the 32-bit architecture.  Building the 32-bit architecture
+   usually (but not always) produces smaller binaries, and is likely
+   to be better tested.
 
    If you are on ARM, and want to build a thumb version of the library
    (this is supported), change OPTFLAGS in arch/arm/MCONFIG to build
    thumb code.
 
-   The following is the status of various architectures:
+   The following is the last known status of various architectures:
 
-   Known to work:	arm i386 sparc sparc64
-   Need crt0.S updates:	alpha ppc 
-   Missing setjmp:	s390 s390x ppc64
-   May or may not work:	x86_64
-   Need porting work:	cris ia64 m68k mips64 parisc sh
+   Known to work:	       arm i386
+   Works static, not shared:   mips s390 s390x sparc sparc64 arm-thumb
+   Need crt0.S updates:	       alpha ppc 
+   Missing setjmp:	       ppc64
+   May or may not work:	       x86_64
+   Need porting work:	       cris ia64 m68k mips64 parisc sh
 
    Note that even the "known to work" ones likely have bugs.  Please
    report them if you run into them.
diff --git a/klibc/arch/s390/Makefile.inc b/klibc/arch/s390/Makefile.inc
index 47703cb..45aa551 100644
--- a/klibc/arch/s390/Makefile.inc
+++ b/klibc/arch/s390/Makefile.inc
@@ -7,4 +7,10 @@
 # accordingly.
 #
 
+ARCHOBJS = \
+	arch/$(ARCH)/setjmp.o
+
+ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS))
+
+
 archclean:
diff --git a/klibc/arch/s390/crt0.S b/klibc/arch/s390/crt0.S
index 569ab91..3c62000 100644
--- a/klibc/arch/s390/crt0.S
+++ b/klibc/arch/s390/crt0.S
@@ -7,40 +7,20 @@
 #    environ = envp;
 #    exit(main(argc, argv, envp));
 # } 
-#
-
+# 
 	.text
 	.align 4
 	.type _start,@function
 	.globl _start
 _start:
-				# save argc 
-	l	%r2,0(%r15)
-				# save argv
-	la	%r3,4(%r15)
-				# compute envp
-	lr	%r4,%r2
-	sll	%r4,2
-	la	%r4,4(%r4,%r3)
-
-				# literal pool
-	bras	%r13,.LTN0_0
-.LT0_0:
-	.long	environ
-	.long	main
-	.long	exit	
-.LTN0_0:
-				# create stack frame
+	lr	%r2,%r15
+	lhi	%r3,0
 	ahi	%r15,-96
-
-				# save global environ
-	l	%r1,0(%r13)
-	st	%r4,0(%r1)
-				# call main
-	l	%r1,4(%r13)
-	basr	%r14,%r1
-				# call exit
-	l	%r1,8(%r13)
-	basr	%r14,%r1
+	bras	%r1,.L0
+.L0:
+	l	%r1,.L1-.L0(%r1)
+	br	%r1
+.L1:
+	.long	__libc_init
 
 	.size _start,.-_start
diff --git a/klibc/arch/s390/include/klibc/archsetjmp.h b/klibc/arch/s390/include/klibc/archsetjmp.h
new file mode 100644
index 0000000..11a641e
--- /dev/null
+++ b/klibc/arch/s390/include/klibc/archsetjmp.h
@@ -0,0 +1,15 @@
+/*
+ * arch/s390/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+  uint32_t __gregs[10]; /* general registers r6-r15 */
+  uint64_t __fpregs[2]; /* fp registers f4 and f6   */
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
diff --git a/klibc/arch/s390/setjmp.S b/klibc/arch/s390/setjmp.S
new file mode 100644
index 0000000..9713268
--- /dev/null
+++ b/klibc/arch/s390/setjmp.S
@@ -0,0 +1,32 @@
+#
+# arch/s390/setjmp.S
+#
+# setjmp/longjmp for the s390 architecture
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+	stm	%r6,%r15,0(%r2)		# save all general registers
+	std	%f4,40(%r2)		# save fp registers f4 and f6
+	std	%f6,48(%r2)
+	lhi	%r2,0			# return 0
+	br	%r14
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	lr	%r1,%r2			# jmp_buf
+	lr	%r2,%r3			# return value
+	ld	%f6,48(%r1)		# restore all saved registers
+	ld	%f4,40(%r1)
+	lm	%r6,%r15,0(%r1)
+	br	%r14			# return to restored address
+
+	.size longjmp,.-longjmp
diff --git a/klibc/arch/s390x/Makefile.inc b/klibc/arch/s390x/Makefile.inc
index e643655..eff8f95 100644
--- a/klibc/arch/s390x/Makefile.inc
+++ b/klibc/arch/s390x/Makefile.inc
@@ -7,4 +7,10 @@
 # accordingly.
 #
 
+ARCHOBJS = \
+	arch/$(ARCH)/setjmp.o
+
+ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS))
+
+
 archclean:
diff --git a/klibc/arch/s390x/crt0.S b/klibc/arch/s390x/crt0.S
index fefc4bb..083aa2d 100644
--- a/klibc/arch/s390x/crt0.S
+++ b/klibc/arch/s390x/crt0.S
@@ -1,5 +1,5 @@
 #
-# arch/s390x/crt0.S
+# arch/s390/crt0.S
 #
 # void _start(void)
 # {
@@ -7,30 +7,15 @@
 #    environ = envp;
 #    exit(main(argc, argv, envp));
 # } 
-#
-
+# 
 	.text
-	.align 8
+	.align 4
 	.type _start,@function
 	.globl _start
 _start:
-				# save argc
-	lg	%r2,0(%r15)
-				# save argv
-	la	%r3,8(%r15)
-				# compute envp
-	sllg	%r4,%r2,3
-	la	%r4,8(%r4,%r3)
-
-				# create stack frame
+	lgr	%r2,%r15
+	lghi	%r3,0
 	aghi	%r15,-160
-
-				# save global environ
-	larl	%r1,environ
-	stg	%r4,0(%r1)
-				# call main
-	brasl	%r14,main
-				# call exit
-	brasl	%r14,exit
+	jg	__libc_init
 
 	.size _start,.-_start
diff --git a/klibc/arch/s390x/include/klibc/archsetjmp.h b/klibc/arch/s390x/include/klibc/archsetjmp.h
new file mode 100644
index 0000000..dd3ed0d
--- /dev/null
+++ b/klibc/arch/s390x/include/klibc/archsetjmp.h
@@ -0,0 +1,15 @@
+/*
+ * arch/s390x/include/klibc/archsetjmp.h
+ */
+
+#ifndef _KLIBC_ARCHSETJMP_H
+#define _KLIBC_ARCHSETJMP_H
+
+struct __jmp_buf {
+  uint64_t __gregs[10]; /* general registers r6-r15 */
+  uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */
+};
+
+typedef struct __jmp_buf jmp_buf[1];
+
+#endif /* _SETJMP_H */
diff --git a/klibc/arch/s390x/setjmp.S b/klibc/arch/s390x/setjmp.S
new file mode 100644
index 0000000..251c57d
--- /dev/null
+++ b/klibc/arch/s390x/setjmp.S
@@ -0,0 +1,36 @@
+#
+# arch/s390x/setjmp.S
+#
+# setjmp/longjmp for the s390x architecture
+#
+
+	.text
+	.align 4
+	.globl setjmp
+	.type setjmp, @function
+setjmp:
+	stmg	%r6,%r15,0(%r2)		# save all general registers
+	std	%f1,80(%r2)		# save fp registers f4 and f6
+	std	%f3,88(%r2)
+	std	%f5,96(%r2)
+	std	%f7,104(%r2)
+	lghi	%r2,0			# return 0
+	br	%r14
+
+	.size setjmp,.-setjmp
+
+	.text
+	.align 4
+	.globl longjmp
+	.type longjmp, @function
+longjmp:
+	lgr	%r1,%r2			# jmp_buf
+	lgr	%r2,%r3			# return value
+	ld	%f7,104(%r1)		# restore all saved registers
+	ld	%f5,96(%r1)
+	ld	%f3,88(%r1)
+	ld	%f1,80(%r1)
+	lmg	%r6,%r15,0(%r1)
+	br	%r14			# return to restored address
+
+	.size longjmp,.-longjmp
diff --git a/klibc/vsscanf.c b/klibc/vsscanf.c
index c59b3d6..1711438 100644
--- a/klibc/vsscanf.c
+++ b/klibc/vsscanf.c
@@ -53,12 +53,14 @@
   return p;
 }
 
+#undef set_bit
 static inline void
 set_bit(unsigned long *bitmap, unsigned int bit)
 {
   bitmap[bit/LONG_BIT] |= 1UL << (bit%LONG_BIT);
 }
 
+#undef test_bit
 static inline int
 test_bit(unsigned long *bitmap, unsigned int bit)
 {