| /* strcmp.S | 
 |  * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. | 
 |  * | 
 |  * This file is subject to the terms and conditions of the GNU Library General | 
 |  * Public License. See the file "COPYING.LIB" in the main directory of this | 
 |  * archive for more details. | 
 |  * | 
 |  * Non-LGPL License also available as part of VisualDSP++ | 
 |  * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html | 
 |  */ | 
 |  | 
 | #include <sysdep.h> | 
 |  | 
 | /* Fast strcmp() for Blackfin. | 
 |  * When both strings are aligned, this processes four characters at | 
 |  * a time. Uses a hw loop with "very big" count to loop "forever", | 
 |  * until difference or a terminating zero is found. | 
 |  * Once the end-case word has been identified, breaks out of the | 
 |  * loop to check more carefully (same as the unaligned case). | 
 |  */ | 
 |  | 
 | .text | 
 |  | 
 | .align 2 | 
 |  | 
 | .weak _strcmp | 
 | ENTRY(_strcmp) | 
 | 	[--sp] = (R7:4); | 
 | 	p1 = r0; | 
 | 	p2 = r1; | 
 |  | 
 | 	p0 = -1;	/* (need for loop counter init) */ | 
 |  | 
 | 	  /* check if byte aligned */ | 
 | 	r0 = r0 | r1;	/* check both pointers at same time */ | 
 | 	r0 <<= 30;	/* dump all but last 2 bits */ | 
 | 	cc = az;	/* are they zero? */ | 
 | 	if !cc jump .Lunaligned;	/* no; use unaligned code. */ | 
 | 			/* fall-thru for aligned case.. */ | 
 |  | 
 | 	  /* note that r0 is zero from the previous... */ | 
 | 	  /*           p0 set to -1 */ | 
 |  | 
 | 	LSETUP (.Lbeginloop, .Lendloop) lc0=p0; | 
 | 	  /* pick up first words */ | 
 | 	r1 = [p1++]; | 
 | 	r2 = [p2++]; | 
 | 	  /* make up mask:  0FF0FF */ | 
 | 	r7 = 0xFF; | 
 | 	r7.h = 0xFF; | 
 | 		/* loop : 9 cycles to check 4 characters */ | 
 | 	cc = r1 == r2; | 
 | .Lbeginloop: | 
 | 	if !cc jump .Lnotequal4;	/* compare failure, exit loop */ | 
 |  | 
 | 	  /* starting with   44332211 */ | 
 | 	  /* see if char 3 or char 1 is 0 */ | 
 | 	r3 = r1 & r7;		/* form 00330011 */ | 
 | 	  /* add to zero, and (r2 is free, reload) */ | 
 | 	r6 = r3 +|+ r0 || r2 = [p2++] || nop; | 
 | 	cc = az;	/* true if either is zero */ | 
 | 	r3 = r1 ^ r3;	        /* form 44002200 (4321^0301 => 4020) */ | 
 | 				/* (trick, saves having another mask) */ | 
 | 	/* add to zero,  and  (r1 is free, reload) */ | 
 | 	r6 = r3 +|+ r0 || r1 = [p1++] || nop; | 
 | 	cc |= az;	/* true if either is zero */ | 
 | 	if cc jump .Lzero4;	/* leave if a zero somewhere */ | 
 | .Lendloop: | 
 | 	cc = r1 == r2; | 
 |  | 
 |  /* loop exits */ | 
 | .Lnotequal4:		/* compare failure on 4-char compare */ | 
 | 			/* address pointers are one word ahead; */ | 
 | 			/* faster to use zero4 exit code */ | 
 | 	p1 += 4; | 
 | 	p2 += 4; | 
 |  | 
 | .Lzero4:			/* one of the bytes in word 1 is zero */ | 
 | 			/* but we've already fetched the next word; so */ | 
 | 			/* backup two to look at failing word again */ | 
 | 	p1 += -8; | 
 | 	p2 += -8; | 
 |  | 
 |  | 
 |  | 
 | 		/* here when pointers are unaligned: checks one */ | 
 | 		/* character at a time.  Also use at the end of */ | 
 | 		/* the word-check algorithm to figure out what happened */ | 
 | .Lunaligned: | 
 | 	  /*	R0 is non-zero from before. */ | 
 | 	  /*           p0 set to -1 */ | 
 |  | 
 | 	r0 = 0 (Z); | 
 | 	r1 = B[p1++] (Z); | 
 | 	r2 = B[p2++] (Z); | 
 | 	LSETUP (.Lbeginloop1, .Lendloop1) lc0=p0; | 
 |  | 
 | .Lbeginloop1: | 
 | 	cc = r1;	/* first char must be non-zero */ | 
 | 	/* chars must be the same */ | 
 | 	r3 = r2 - r1 (NS) || r1 = B[p1++] (Z) || nop; | 
 | 	cc &= az; | 
 | 	r3 = r0 - r2;	/* second char must be non-zero */ | 
 | 	cc &= an; | 
 | 	if !cc jump .Lexitloop1; | 
 | .Lendloop1: | 
 | 	r2 = B[p2++] (Z); | 
 |  | 
 | .Lexitloop1: /* here means we found a zero or a difference. */ | 
 | 	   /* we have r2(N), p2(N), r1(N+1), p1(N+2) */ | 
 | 	r1=B[p1+ -2] (Z); | 
 | 	r0 = r1 - r2; | 
 | 	(r7:4) = [sp++]; | 
 | 	rts; | 
 | .size _strcmp,.-_strcmp | 
 |  | 
 | libc_hidden_def (strcmp) | 
 |  | 
 | #ifndef __UCLIBC_HAS_LOCALE__ | 
 | weak_alias (strcmp,strcoll) | 
 | libc_hidden_def (strcoll) | 
 | #endif |