patch-2.1.8 linux/arch/alpha/lib/strlen_user.S

Next file: linux/arch/i386/defconfig
Previous file: linux/arch/alpha/lib/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.7/linux/arch/alpha/lib/strlen_user.S linux/arch/alpha/lib/strlen_user.S
@@ -0,0 +1,65 @@
+/*
+ * arch/alpha/lib/strlen_user.S
+ *
+ * Just like strlen except returns -EFAULT if an exception occurs
+ * before the terminator is found.
+ */
+
+#include <alpha/regdef.h>
+
+
+/* Allow an exception for an insn; exit if we get one.  */
+#define EX(x,y...)			\
+	99: x,##y;			\
+	.section __ex_table,"a";	\
+	.gprel32 99b;			\
+	lda zero, $exception-99b(v0); 	\
+	.text
+
+
+	.set noreorder
+	.set noat
+	.text
+
+	.globl strlen_user
+	.ent strlen_user
+	.frame sp, 0, ra
+
+	.align 3
+strlen_user:
+	.prologue 0
+
+	EX( ldq_u t0, 0(a0) )	# load first quadword (a0 may be misaligned)
+	lda     t1, -1(zero)
+	insqh   t1, a0, t1
+	andnot  a0, 7, v0
+	or      t1, t0, t0
+	nop			# dual issue the next two on ev5
+	cmpbge  zero, t0, t1	# t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+	bne     t1, $found
+
+$loop:	EX( ldq t0, 8(v0) )
+	addq    v0, 8, v0	# addr += 8
+	cmpbge  zero, t0, t1
+	beq     t1, $loop
+
+$found:	negq    t1, t2		# clear all but least set bit
+	and     t1, t2, t1
+
+	and     t1, 0xf0, t2	# binary search for that set bit
+	and	t1, 0xcc, t3
+	and	t1, 0xaa, t4
+	cmovne	t2, 4, t2
+	cmovne	t3, 2, t3
+	cmovne	t4, 1, t4
+	addq	t2, t3, t2
+	addq	v0, t4, v0
+	addq	v0, t2, v0
+	nop			# dual issue next two on ev4 and ev5
+
+	subq    v0, a0, v0
+
+$exception:
+	ret
+
+	.end strlen_user

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov