summaryrefslogtreecommitdiff
path: root/newlib/libc/machine/hppa/strcmp.S
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/hppa/strcmp.S')
-rw-r--r--newlib/libc/machine/hppa/strcmp.S282
1 files changed, 282 insertions, 0 deletions
diff --git a/newlib/libc/machine/hppa/strcmp.S b/newlib/libc/machine/hppa/strcmp.S
new file mode 100644
index 00000000000..007a648492d
--- /dev/null
+++ b/newlib/libc/machine/hppa/strcmp.S
@@ -0,0 +1,282 @@
+/*
+ * (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.
+ */
+
+/*
+
+ strcmp
+
+ Jerry Huck
+ Edgar Circenis
+
+*/
+/*
+ * strcmp(s1, s2)
+ *
+ * returns integer: < 0 iff s1 lexicographically less than s2
+ * > 0 iff s1 lexicographically greater than s2
+ * = 0 iff s1 lexicographically equal to s2
+ */
+
+#include "DEFS.h"
+
+#define s1 26
+#define s2 25
+#define tmp1 19
+#define s2word 20
+#define tmp3 21
+#define tmp7 22
+#define s1word 23
+#define save 1
+#define tmp6 24
+#define tmp5 28
+
+ENTRY(strcmp)
+ comb,=,n s1,s2,samestring
+ comib,=,n 0,s1,s1isnull
+ comib,=,n 0,s2,s2isnull
+/* Hope for word alignment. Pick up low two bits of each adress */
+ extru,<> s1,31,2,tmp1
+ ldwm 4(s1),s1word
+ dep,= s2,29,2,tmp1
+ b,n case_analysis
+
+/* Start looping until null is found in s1 or they mis-compare */
+loop:
+ ldwm 4(s2),s2word
+loop_plus:
+ uxor,nbz s1word,r0,r0 /* Null in this? */
+ b,n nullins1
+ comb,=,n s1word,s2word,loop
+ ldwm 4(s1),s1word
+
+/* The words do not compare equal and s1 does not have a null.
+ Need to treat words as unsigned and generate either a positive
+ or negative return value */
+wordcomparereturn:
+ comclr,>> s1word,s2word,ret0 /*Set ret0 to 0 and skip if greater*/
+ ldi -2,ret0 /*Set ret0 to -2 when less */
+ bv r0(rp)
+ addi 1,ret0,ret0 /*Fix return value to be -1 or +1 */
+
+/* s1 has a null. s2 has not been checked. */
+nullins1:
+ /*If s2 has no nulls this is simple, but assume that it might
+ and fix up s1 to allow the word comparision to work by
+ scanning s1 and duplicating all the bytes in s2 below that byte into
+ the remainder of s1. A remainder only exists if the zero byte
+ is found in the upper three bytes */
+ extru,<> s1word,7,8,r0 /*in the first byte? */
+ dep,tr s2word,31,24,s1word /*copy low 3 bytes of *s2 into *s1 */
+ extru,<> s1word,15,8,r0 /*in the second byte? */
+ dep,tr s2word,31,16,s1word /*copy low 2 bytes of *s2 into *s1 */
+ extru,<> s1word,23,8,r0 /*in the third byte? */
+ dep s2word,31,8,s1word /*copy low 1 byte of *s2 into *s1 */
+ /* Do the normal unsigned compare and return */
+ comclr,<> s1word,s2word,ret0 /*Set ret0 to 0 and skip if not equal */
+ bv,n r0(rp)
+ comclr,>> s1word,s2word,ret0 /*Set ret0 to 0 and skip if greater*/
+ ldi -2,ret0 /*Set ret0 to -2 when less */
+ bv r0(rp)
+ addi 1,ret0,ret0 /*Fix return value to be -1 or +1 */
+
+/* s1 and s2 are the same string and therefore equal */
+samestring:
+ bv r0(rp)
+ copy r0,ret0
+/* s1 is null. Treat as string of nulls. Therefore return
+ the negative of s2's first byte. s2 cannot be zero. */
+s1isnull:
+ ldbs 0(0,s2),ret0
+ bv r0(rp)
+ sub 0,ret0,ret0
+/* s2 is null. Treat as string of nulls. Therefore return
+ s1's first byte. s1 cannot be zero. */
+s2isnull:
+ bv r0(rp)
+ ldbs 0(0,s1),ret0
+
+case_analysis:
+ blr tmp1,r0
+ nop
+
+ /*
+ Case statement for non-aligned cases (we've already
+ checked the aligned case.
+ NOTE: for non-aligned cases, the absolute shift value
+ gets loaded into tmp3.
+ */
+
+ /* S2 S1 */
+ nop /* 00 00 can't happen */
+ nop
+ b shifts2 /* 00 01 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ b shifts2 /* 00 10 */
+ ldi 16,tmp3 /* load shift count (delay slot) */
+ b shifts2 /* 00 11 */
+ ldi 24,tmp3 /* load shift count (delay slot) */
+ b shifts1_0 /* 01 00 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ b eq_align1 /* 01 01 */
+ ldbs,ma 1(s1),s1word
+ b shifts2 /* 01 10 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ b shifts2 /* 01 11 */
+ ldi 16,tmp3 /* load shift count (delay slot) */
+ b shifts1_0 /* 10 00 */
+ ldi 16,tmp3 /* load shift count (delay slot) */
+ b shifts1 /* 10 01 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ b eq_align2 /* 10 10 */
+ ldhs,ma 2(s1),s1word
+ b shifts2 /* 10 11 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ b shifts1_0 /* 11 00 */
+ ldi 24,tmp3 /* load shift count (delay slot) */
+ b shifts1 /* 11 01 */
+ ldi 16,tmp3 /* load shift count (delay slot) */
+ b shifts1 /* 11 10 */
+ ldi 8,tmp3 /* load shift count (delay slot) */
+ ldbs,ma 1(s1),s1word /* 11 11 */
+ ldbs,ma 1(s2),s2word
+ sub,= s1word,s2word,ret0 /* if not equal, we can return now */
+ bv,n r0(rp)
+ comclr,<> s1word,r0,ret0
+ bv,n r0(rp)
+ b loop /* fall into main loop */
+ ldwm 4(s1),s1word
+
+eq_align1:
+ ldbs,ma 1(s2),s2word
+ sub,= s1word,s2word,ret0 /* if not equal, we can return now */
+ bv,n r0(rp)
+ comclr,<> s1word,r0,ret0
+ bv,n r0(rp)
+ /* fall through to half-word aligned case */
+ ldhs,ma 2(s1),s1word /* load next halfword */
+eq_align2:
+ ldhs,ma 2(s2),s2word /* load next halfword */
+ /* form the mask: 0xffff0000 and mask leading nulls in s1word and s2word
+ so that we can fall into the main loop with word aligned data */
+ ldi 16,save
+ mtctl save,r11
+ zvdepi -2,32,save
+ or save,s1word,s1word
+ b loop_plus /* fall into main loop */
+ or save,s2word,s2word
+
+/* s2's alignment is greater than s1's alignment, so we will shift s1 */
+shifts1_0:
+ addi -4,s1,s1 /* fix up s1 due to earlier read */
+shifts1:
+ extru s1,31,2,tmp1
+ extru s2,31,2,tmp5
+ dep r0,31,2,s1 /* Compute word address of s1 */
+ dep r0,31,2,s2 /* Compute word address of s2 */
+ ldwm 4(s1),s1word /* get first word of s1 */
+ ldwm 4(s2),s2word /* get first word of s2 */
+ combt,=,n r0,tmp1,masks2 /* Do we need to mask beginning of s1 */
+ sh3add tmp1,r0,save /* save now has number of bits to mask */
+ mtctl save,r11
+ zvdepi -2,32,save /* load save with proper mask */
+ or save,s1word,s1word
+masks2:
+ sh3add tmp5,r0,save /* save now has number of bits to mask */
+ mtctl save,r11
+ zvdepi -2,32,save /* load save with proper mask */
+ or save,s2word,s2word
+ ldi -1,tmp7 /* load tmp7 with 0xffffffff */
+ mtctl tmp3,r11 /* Move shift amount to CR11 */
+more: uxor,nbz s1word,r0,r0 /* Is there a null in s1? */
+ b ends1
+ vshd tmp7,s1word,save
+ combf,=,n save,s2word,cmps1
+ ldwm 4(s1),tmp7
+ ldwm 4(s2),s2word
+ uxor,nbz tmp7,r0,r0 /* is there a null in s1? */
+ b ends1_0
+ vshd s1word,tmp7,save
+ combf,=,n save,s2word,cmps1
+ ldwm 4(s1),s1word
+ b more
+ ldwm 4(s2),s2word
+
+cmps1: movb,tr save,s1word,wordcomparereturn
+ nop
+
+ends1_0:
+ copy tmp7,s1word /* move tmp7 to s1word */
+ends1:
+ combf,=,n save,s2word,nullins1 /* branch if no match */
+ copy save,s1word /* delay slot */
+/* At this point, we know that we've read a null */
+/* from s1, so we can't read more from s1 */
+ uxor,nbz save,r0,r0 /* are the strings equal? */
+ b,n samestring
+ vshd s1word,r0,s1word
+ b nullins1
+ ldwm 4(s2),s2word
+
+/* s1's alignment is greater than s2's alignment, so we will shift s2 */
+shifts2:
+ extru s1,31,2,tmp1
+ extru s2,31,2,tmp5
+ dep r0,31,2,s1 /* Compute word address of s1 */
+ dep r0,31,2,s2 /* Compute word address of s2 */
+ ldwm 4(s2),s2word /* get first word of s2 */
+ ldwm 4(s1),s1word /* get first word of s1 */
+ combt,=,n r0,tmp5,masks1 /* Do we need to mask beginning of s2 */
+ sh3add tmp5,r0,save /* save now has number of bits to mask */
+ mtctl save,r11
+ zvdepi -2,32,save /* load save with proper mask */
+ or save,s2word,s2word
+masks1:
+ sh3add tmp1,r0,save /* save now has number of bits to mask */
+ mtctl save,r11
+ zvdepi -2,32,save /* load save with proper mask */
+ or save,s1word,s1word
+ ldi -1,tmp7 /* load tmp7 with 0xffffffff */
+ mtctl tmp3,r11 /* Move shift amount to CR11 */
+more1: uxor,nbz s2word,r0,r0 /* is there a null in s2? */
+ b ends2
+ vshd tmp7,s2word,save
+ combf,=,n s1word,save,cmps2
+ ldwm 4(s2),tmp7
+ ldwm 4(s1),s1word
+ uxor,nbz tmp7,r0,r0 /* is there a null in s2? */
+ b ends2_0
+ vshd s2word,tmp7,save
+ combf,=,n s1word,save,cmps2
+ ldwm 4(s2),s2word
+ b more1
+ ldwm 4(s1),s1word
+
+cmps2: movb,tr save,s2word,wordcomparereturn
+ nop
+
+ends2_0:
+ copy tmp7,s2word /* move tmp7 to s2word */
+ends2:
+ combf,=,n s1word,save,nullins1 /* branch if no match */
+ copy save,s2word /* delay slot */
+/* At this point, we know that we've read a null */
+/* from s2, so we can't read more from s2 */
+ uxor,nbz save,r0,r0 /* are the strings equal? */
+ b,n samestring
+ vshd s2word,r0,s2word
+ b nullins1
+ ldwm 4(s1),s1word
+
+EXIT(strcmp)