patch-2.4.11-dontuse linux/include/asm-cris/uaccess.h

Next file: linux/include/asm-i386/apic.h
Previous file: linux/include/asm-cris/tlb.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.10/linux/include/asm-cris/uaccess.h linux/include/asm-cris/uaccess.h
@@ -3,6 +3,12 @@
  *	       Hans-Peter Nilsson (hp@axis.com)
  *
  * $Log: uaccess.h,v $
+ * Revision 1.7  2001/10/02 12:44:52  hp
+ * Add support for 64-bit put_user/get_user
+ *
+ * Revision 1.6  2001/10/01 14:51:17  bjornw
+ * Added register prefixes and removed underscores
+ *
  * Revision 1.5  2000/10/25 03:33:21  hp
  * - Provide implementation for everything else but get_user and put_user;
  *   copying inline to/from user for constant length 0..16, 20, 24, and
@@ -36,7 +42,7 @@
 
    Check regularly...
 
-   Register r9 is chosen for temporaries, being a call-clobbered register
+   Register $r9 is chosen for temporaries, being a call-clobbered register
    first in line to be used (notably for local blocks), not colliding with
    parameter registers.  */
 
@@ -182,6 +188,7 @@
 	  case 1: __put_user_asm(x,ptr,retval,"move.b"); break;	\
 	  case 2: __put_user_asm(x,ptr,retval,"move.w"); break;	\
 	  case 4: __put_user_asm(x,ptr,retval,"move.d"); break;	\
+	  case 8: __put_user_asm_64(x,ptr,retval); break;	\
 	  default: __put_user_bad();				\
 	}							\
 } while (0)
@@ -211,6 +218,22 @@
 		: "=r" (err)					\
 		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
 
+#define __put_user_asm_64(x, addr, err)				\
+	__asm__ __volatile__(					\
+		"	move.d %M1,[%2]\n"			\
+		"2:	move.d %H1,[%2+4]\n"			\
+		"4:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"3:	move.d %3,%0\n"				\
+		"	jump 4b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.dword 2b,3b\n"				\
+		"	.dword 4b,3b\n"				\
+		"	.previous\n"				\
+		: "=r" (err)					\
+		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
+
 
 #define __get_user_nocheck(x,ptr,size)				\
 ({								\
@@ -239,6 +262,7 @@
 	  case 1: __get_user_asm(x,ptr,retval,"move.b"); break;	\
 	  case 2: __get_user_asm(x,ptr,retval,"move.w"); break;	\
 	  case 4: __get_user_asm(x,ptr,retval,"move.d"); break;	\
+	  case 8: __get_user_asm_64(x,ptr,retval); break;	\
 	  default: (x) = __get_user_bad();			\
 	}							\
 } while (0)
@@ -260,6 +284,23 @@
 		: "=r" (err), "=r" (x)			\
 		: "r" (addr), "g" (-EFAULT), "0" (err))
 
+#define __get_user_asm_64(x, addr, err)			\
+	__asm__ __volatile__(				\
+		"	move.d [%2],%M1\n"		\
+		"2:	move.d [%2+4],%H1\n"		\
+		"4:\n"					\
+		"	.section .fixup,\"ax\"\n"	\
+		"3:	move.d %3,%0\n"			\
+		"	moveq 0,%1\n"			\
+		"	jump 4b\n"			\
+		"	.previous\n"			\
+		"	.section __ex_table,\"a\"\n"	\
+		"	.dword 2b,3b\n"			\
+		"	.dword 4b,3b\n"			\
+		"	.previous\n"			\
+		: "=r" (err), "=r" (x)			\
+		: "r" (addr), "g" (-EFAULT), "0" (err))
+
 /* More complex functions.  Most are inline, but some call functions that
    live in lib/usercopy.c  */
 
@@ -305,13 +346,13 @@
 
 	__asm__ __volatile__ (
 		"	move.d %3,%0\n"
-		"	move.b [%2+],r9\n"
+		"	move.b [%2+],$r9\n"
 		"1:	beq 2f\n"
-		"	move.b r9,[%1+]\n"
+		"	move.b $r9,[%1+]\n"
 
 		"	subq 1,%0\n"
 		"	bne 1b\n"
-		"	move.b [%2+],r9\n"
+		"	move.b [%2+],$r9\n"
 
 		"2:	sub.d %3,%0\n"
 		"	neg.d %0,%0\n"
@@ -399,16 +440,16 @@
 
 #define __asm_copy_from_user_1(to, from, ret) \
 	__asm_copy_user_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"	\
-		"2:	move.b r9,[%0+]\n",	\
+		"	move.b [%1+],$r9\n"	\
+		"2:	move.b $r9,[%0+]\n",	\
 		"3:	addq 1,%2\n"		\
 		"	clear.b [%0+]\n",	\
 		"	.dword 2b,3b\n")
 
 #define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
-		"	move.w [%1+],r9\n"		\
-		"2:	move.w r9,[%0+]\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"2:	move.w $r9,[%0+]\n" COPY,	\
 		"3:	addq 2,%2\n"			\
 		"	clear.w [%0+]\n" FIXUP,		\
 		"	.dword 2b,3b\n" TENTRY)
@@ -418,16 +459,16 @@
 
 #define __asm_copy_from_user_3(to, from, ret)		\
 	__asm_copy_from_user_2x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"4:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"4:	move.b $r9,[%0+]\n",		\
 		"5:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 4b,5b\n")
 
 #define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
-		"	move.d [%1+],r9\n"		\
-		"2:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"2:	move.d $r9,[%0+]\n" COPY,	\
 		"3:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 2b,3b\n" TENTRY)
@@ -437,16 +478,16 @@
 
 #define __asm_copy_from_user_5(to, from, ret) \
 	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"4:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"4:	move.b $r9,[%0+]\n",		\
 		"5:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 4b,5b\n")
 
 #define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"4:	move.w r9,[%0+]\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"4:	move.w $r9,[%0+]\n" COPY,	\
 		"5:	addq 2,%2\n"			\
 		"	clear.w [%0+]\n" FIXUP,		\
 		"	.dword 4b,5b\n" TENTRY)
@@ -456,16 +497,16 @@
 
 #define __asm_copy_from_user_7(to, from, ret) \
 	__asm_copy_from_user_6x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"6:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"6:	move.b $r9,[%0+]\n",		\
 		"7:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 6b,7b\n")
 
 #define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_4x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"4:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"4:	move.d $r9,[%0+]\n" COPY,	\
 		"5:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 4b,5b\n" TENTRY)
@@ -475,16 +516,16 @@
 
 #define __asm_copy_from_user_9(to, from, ret) \
 	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"6:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"6:	move.b $r9,[%0+]\n",		\
 		"7:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 6b,7b\n")
 
 #define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"6:	move.w r9,[%0+]\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"6:	move.w $r9,[%0+]\n" COPY,	\
 		"7:	addq 2,%2\n"			\
 		"	clear.w [%0+]\n" FIXUP,		\
 		"	.dword 6b,7b\n" TENTRY)
@@ -494,16 +535,16 @@
 
 #define __asm_copy_from_user_11(to, from, ret)		\
 	__asm_copy_from_user_10x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"8:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"8:	move.b $r9,[%0+]\n",		\
 		"9:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 8b,9b\n")
 
 #define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_8x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"6:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"6:	move.d $r9,[%0+]\n" COPY,	\
 		"7:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 6b,7b\n" TENTRY)
@@ -513,16 +554,16 @@
 
 #define __asm_copy_from_user_13(to, from, ret) \
 	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"8:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"8:	move.b $r9,[%0+]\n",		\
 		"9:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 8b,9b\n")
 
 #define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"8:	move.w r9,[%0+]\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"8:	move.w $r9,[%0+]\n" COPY,	\
 		"9:	addq 2,%2\n"			\
 		"	clear.w [%0+]\n" FIXUP,		\
 		"	.dword 8b,9b\n" TENTRY)
@@ -532,16 +573,16 @@
 
 #define __asm_copy_from_user_15(to, from, ret) \
 	__asm_copy_from_user_14x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"10:	move.b r9,[%0+]\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"10:	move.b $r9,[%0+]\n",		\
 		"11:	addq 1,%2\n"			\
 		"	clear.b [%0+]\n",		\
 		"	.dword 10b,11b\n")
 
 #define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_12x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"8:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"8:	move.d $r9,[%0+]\n" COPY,	\
 		"9:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 8b,9b\n" TENTRY)
@@ -551,8 +592,8 @@
 
 #define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_16x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"10:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"10:	move.d $r9,[%0+]\n" COPY,	\
 		"11:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 10b,11b\n" TENTRY)
@@ -562,8 +603,8 @@
 
 #define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_from_user_20x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"12:	move.d r9,[%0+]\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"12:	move.d $r9,[%0+]\n" COPY,	\
 		"13:	addq 4,%2\n"			\
 		"	clear.d [%0+]\n" FIXUP,		\
 		"	.dword 12b,13b\n" TENTRY)
@@ -575,15 +616,15 @@
 
 #define __asm_copy_to_user_1(to, from, ret)	\
 	__asm_copy_user_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"	\
-		"	move.b r9,[%0+]\n2:\n",	\
+		"	move.b [%1+],$r9\n"	\
+		"	move.b $r9,[%0+]\n2:\n",	\
 		"3:	addq 1,%2\n",		\
 		"	.dword 2b,3b\n")
 
 #define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
-		"	move.w [%1+],r9\n"		\
-		"	move.w r9,[%0+]\n2:\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"	move.w $r9,[%0+]\n2:\n" COPY,	\
 		"3:	addq 2,%2\n" FIXUP,		\
 		"	.dword 2b,3b\n" TENTRY)
 
@@ -592,15 +633,15 @@
 
 #define __asm_copy_to_user_3(to, from, ret) \
 	__asm_copy_to_user_2x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n4:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n4:\n",		\
 		"5:	addq 1,%2\n",			\
 		"	.dword 4b,5b\n")
 
 #define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_user_cont(to, from, ret,		\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n2:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n2:\n" COPY,	\
 		"3:	addq 4,%2\n" FIXUP,		\
 		"	.dword 2b,3b\n" TENTRY)
 
@@ -609,15 +650,15 @@
 
 #define __asm_copy_to_user_5(to, from, ret) \
 	__asm_copy_to_user_4x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n4:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n4:\n",		\
 		"5:	addq 1,%2\n",			\
 		"	.dword 4b,5b\n")
 
 #define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_4x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"	move.w r9,[%0+]\n4:\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"	move.w $r9,[%0+]\n4:\n" COPY,	\
 		"5:	addq 2,%2\n" FIXUP,		\
 		"	.dword 4b,5b\n" TENTRY)
 
@@ -626,15 +667,15 @@
 
 #define __asm_copy_to_user_7(to, from, ret) \
 	__asm_copy_to_user_6x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n6:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n6:\n",		\
 		"7:	addq 1,%2\n",			\
 		"	.dword 6b,7b\n")
 
 #define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_4x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n4:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n4:\n" COPY,	\
 		"5:	addq 4,%2\n"  FIXUP,		\
 		"	.dword 4b,5b\n" TENTRY)
 
@@ -643,15 +684,15 @@
 
 #define __asm_copy_to_user_9(to, from, ret) \
 	__asm_copy_to_user_8x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n6:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n6:\n",		\
 		"7:	addq 1,%2\n",			\
 		"	.dword 6b,7b\n")
 
 #define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_8x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"	move.w r9,[%0+]\n6:\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"	move.w $r9,[%0+]\n6:\n" COPY,	\
 		"7:	addq 2,%2\n" FIXUP,		\
 		"	.dword 6b,7b\n" TENTRY)
 
@@ -660,15 +701,15 @@
 
 #define __asm_copy_to_user_11(to, from, ret) \
 	__asm_copy_to_user_10x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n8:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n8:\n",		\
 		"9:	addq 1,%2\n",			\
 		"	.dword 8b,9b\n")
 
 #define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_8x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n6:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n6:\n" COPY,	\
 		"7:	addq 4,%2\n" FIXUP,		\
 		"	.dword 6b,7b\n" TENTRY)
 
@@ -677,15 +718,15 @@
 
 #define __asm_copy_to_user_13(to, from, ret) \
 	__asm_copy_to_user_12x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n8:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n8:\n",		\
 		"9:	addq 1,%2\n",			\
 		"	.dword 8b,9b\n")
 
 #define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_12x_cont(to, from, ret,	\
-		"	move.w [%1+],r9\n"		\
-		"	move.w r9,[%0+]\n8:\n" COPY,	\
+		"	move.w [%1+],$r9\n"		\
+		"	move.w $r9,[%0+]\n8:\n" COPY,	\
 		"9:	addq 2,%2\n" FIXUP,		\
 		"	.dword 8b,9b\n" TENTRY)
 
@@ -694,15 +735,15 @@
 
 #define __asm_copy_to_user_15(to, from, ret) \
 	__asm_copy_to_user_14x_cont(to, from, ret,	\
-		"	move.b [%1+],r9\n"		\
-		"	move.b r9,[%0+]\n10:\n",		\
+		"	move.b [%1+],$r9\n"		\
+		"	move.b $r9,[%0+]\n10:\n",		\
 		"11:	addq 1,%2\n",			\
 		"	.dword 10b,11b\n")
 
 #define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_12x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n8:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n8:\n" COPY,	\
 		"9:	addq 4,%2\n" FIXUP,		\
 		"	.dword 8b,9b\n" TENTRY)
 
@@ -711,8 +752,8 @@
 
 #define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
 	__asm_copy_to_user_16x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n10:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n10:\n" COPY,	\
 		"11:	addq 4,%2\n" FIXUP,		\
 		"	.dword 10b,11b\n" TENTRY)
 
@@ -721,8 +762,8 @@
 
 #define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)	\
 	__asm_copy_to_user_20x_cont(to, from, ret,	\
-		"	move.d [%1+],r9\n"		\
-		"	move.d r9,[%0+]\n12:\n" COPY,	\
+		"	move.d [%1+],$r9\n"		\
+		"	move.d $r9,[%0+]\n12:\n" COPY,	\
 		"13:	addq 4,%2\n" FIXUP,		\
 		"	.dword 12b,13b\n" TENTRY)
 
@@ -1034,17 +1075,17 @@
 	 */
 
 	__asm__ __volatile__ (
-		"	move.d %1,r9\n"
+		"	move.d %1,$r9\n"
 		"0:\n"
 		"	ble 1f\n"
-		"	subq 1,r9\n"
+		"	subq 1,$r9\n"
 
 		"	test.b [%0+]\n"
 		"	bne 0b\n"
-		"	test.d r9\n"
+		"	test.d $r9\n"
 		"1:\n"
 		"	move.d %1,%0\n"
-		"	sub.d r9,%0\n"
+		"	sub.d $r9,%0\n"
 		"2:\n"
 		"	.section .fixup,\"ax\"\n"
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)