Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/hppa/strlen.S')
-rw-r--r--newlib/libc/machine/hppa/strlen.S79
1 files changed, 79 insertions, 0 deletions
diff --git a/newlib/libc/machine/hppa/strlen.S b/newlib/libc/machine/hppa/strlen.S
new file mode 100644
index 000000000..12e9ef2a9
--- /dev/null
+++ b/newlib/libc/machine/hppa/strlen.S
@@ -0,0 +1,79 @@
+/*
+ * (c) Copyright 1986 HEWLETT-PACKARD COMPANY
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of Hewlett-Packard Company not be
+ * used in advertising or publicity pertaining to distribution
+ * of the software without specific, written prior permission.
+ * Hewlett-Packard Company makes no representations about the
+ * suitability of this software for any purpose.
+ */
+
+/* HPUX_ID = "@(#) $Revision$" */
+/* strlen(s): Return length of string s */
+
+#define start arg0
+#define end ret0
+#define tmp1 arg1
+#define tmp2 arg2
+
+#include "DEFS.h"
+
+ENTRY(strlen)
+ movb,=,n start,end,$null_ptr
+ depi 0,31,2,end
+ comb,<> start,end,$not_aligned
+ ldws,ma 4(end),tmp1
+ comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
+ uxor,nbz 0,tmp1,0
+$not_aligned:
+ /*
+ ; Tricky code. The problem is that the value of of the word
+ ; including the start of the string has some garbage bytes that
+ ; may be 0. We don't want them to stop the string scan. So
+ ; we make those bytes non-zero (and any old non-zero value
+ ; will do). Notice that the end pointer has been rounded
+ ; down to a word boundary, and then incremented to the next
+ ; word by the time we get here. Therefore, (start-end) has
+ ; one of the values (-3, -2, or -1). Use uaddcm to do the
+ ; subtraction (instead of sub), and the result will be
+ ; (-4, -3, or -2). Multiply this by 8, and put into the
+ ; shift register (which truncates to the last 5 bits) and
+ ; the value will be (0, 8, or 16). Use this as a bit position,
+ ; and drop a mask down into tmp1. All the garbage bytes will
+ ; have at least 1 bit affected by the vdepi, so all the garbage
+ ; in this first word will be non-zero garbage.
+ */
+ uaddcm start,end,tmp2 /* tmp2 <- { -4, -3, -2 } */
+ sh3add tmp2,0,tmp2 /* tmp2 <- { -32, -24, -16 } */
+ mtsar tmp2 /* sar <- { 0, 8, 16 } */
+ vdepi -1,32,tmp1
+ uxor,nbz 0,tmp1,0
+$loop:
+ b,n $end_loop
+ ldws,ma 4(end),tmp1
+ comib,tr 0,0,$loop /* avoid INDIGO two register interlock */
+ uxor,nbz 0,tmp1,0
+$end_loop:
+ /* adjust the end pointer to one past the end of the string */
+ extru,<> tmp1,7,8,0
+ addib,tr,n -3,end,$out
+ extru,<> tmp1,15,8,0
+ addib,tr,n -2,end,$out
+ extru,<> tmp1,23,8,0
+ addi -1,end,end
+$out:
+ bv 0(rp)
+ /*
+ ; tricky code. the end pointer is just beyond the terminating
+ ; null byte, so the length is (end-start-1). use uaddcm
+ ; to do this in 1 instruction
+ */
+ uaddcm end,start,ret0
+
+$null_ptr:
+EXIT(strlen)