/* $NetBSD: memcmp.S,v 1.4 2013/07/04 20:57:59 matt Exp $ */ /* stropt/memcmp.S, pl_string_common, pl_linux 10/11/04 11:45:35 * ========================================================================== * Optimized memcmp implementation for IBM PowerPC 405/440. * * Copyright (c) 2003, IBM Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of IBM nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ========================================================================== * * Function: Compare two character strings (up to n characters) * * int memcmp(const char *s1, const char *s2, int n) * * Input: r3 - buffer 1 address * r4 - buffer 2 address * r5 - maximum characters to compare * Output: r3 <0 (less), 0 (equal), >0 (greater) * * ========================================================================== */ #include .text .align 4 /* LINTSTUB: Func: void *memcmp(const void *, const void *, size_t) */ ENTRY(memcmp) /* * Check count passed in R5. If zero, return 0; otherwise continue. */ cmpwi %r5,0 beq- ret_0; /* * Most of the time the difference is found in the first * several bytes. The following code minimizes the number * of load operations for short compares. */ mr %r11, %r3 /* Save buffer 1 */ again: not %r10, %r4 /* buffer 2: bytes to page bdy */ rlwinm. %r10, %r10,29,23,31 /* buffer 2: dwords to page bdy */ beq- bytebybyte /* If < 8 bytes to the page bdy */ /* do byte by byte */ lwz %r8, 0(%r4) /* load 1st buffer 2 word */ not %r12, %r11 /* buffer 1: bytes to page bdy */ rlwinm. %r12, %r12,29,23,31 /* buffer 1: dwords to page bdy */ beq- bytebybyte /* If < 8 bytes to the page bdy */ /* do byte by byte */ lwz %r6, 0(%r11) /* load 1st buffer 1 word */ cmpwi %r5, 4 /* If remaining count <= 4 */ ble+ first4 /* handle specially. DWG */ cmplw %r8, %r6 /* compare buffer 2 and buffer 1*/ bne+ all_done /* different => we're done */ lwzu %r9, 4(%r4) /* load 2nd buffer 2 word */ lwzu %r7, 4(%r11) /* load 2nd buffer 1 word */ cmpwi %r5, 8 /* If remaining count <= 8 */ ble+ last4 /* handle specially. DWG */ cmplw %r9, %r7 /* compare buffer 2 and buffer 1*/ bne+ all_done /* different => we're done */ addi %r5, %r5, -8 /* Update character counter DWG */ addi %r10, %r4, 0x0004 /* DWG*/ not %r10, %r10 /* buffer 2: bytes to page bdy DWG */ rlwinm. %r10, %r10,29,23,31 /* buffer 2: dwords to page bdy DWG */ addi %r12, %r11, 0x0004 /* DWG */ not %r12, %r12 /* buffer 1: bytes to page bdy DWG */ rlwinm. %r12, %r12,29,23,31 /* buffer 1: dwords to page bdy DWG */ /* The following section prior to loop: figures out whether */ /* the buffer 1 or buffer 2 is closer to the page boundary. */ /* The main loop count is then set up to reflect the number of */ /* double words of the buffer that is closest */ cmpw %r10, %r12 /* Find closest */ blt lt mr %r10, %r12 lt: srwi %r12, %r5, 3 /* Double check the total count */ cmpw %r10, %r12 /* limitation */ blt lt2 mr %r10, %r12 /* DWG */ lt2: /* DWG */ cmpwi %r10, 0 /* DWG */ bne lt3 /* DWG */ addi %r4, %r4, 0x0004 /* DWG */ addi %r11,%r11,0x0004 /* DWG */ b again /* DWG */ lt3: /* DWG */ mtctr %r10 /* dword count for loop */ lwzu %r6, 4(%r11) /* pre-load buffer 1 word */ b in /* To the loop */ loop: /* main loop */ cmplw %r8, %r6 /* Compare first buffer 2 word */ bne- all_done /* with first buffer 1 word */ /* If different, we're done */ cmplw %r9, %r7 /* Compare second buffer 2 word */ /* with second buffer 1 word */ lwzu %r6, 4(%r11) /* pre-load buffer 1 word */ bne- all_done /* If different, we're done */ in: lwzu %r7, 4(%r11) /* pre-load buffer 1 word */ lwzu %r8, 4(%r4) /* pre-load buffer 2 word */ lwzu %r9, 4(%r4) /* pre-load buffer 2 word */ bdnz+ loop /* Do more DW's if cnt > 0 */ /*mfctr %r12*/ /*DWG*/ /* number of dwords left */ /*subf %r10, %r12, %r10*/ /*DWG*//* number of dwords compared */ slwi %r10, %r10, 3 subf %r5, %r10, %r5 /* adjust byte counter */ /*bne+ partial*/ /*DWG*/ /* If less than 8 bytes, handle */ /* specially */ /*cmpwi %r5, 8*/ /* Removed. DWG */ /*blt partial*/ /* Removed. DWG */ /*addic %r5, %r5, -8*/ /*DWG*/ /* Subtract two words from count*/ cmplw %r8, %r6 /* compare last dword */ addi %r4, %r4, 4 bne- all_done cmplw %r9, %r7 addi %r11, %r11, 4 bne- all_done bytebybyte: /* We've gotten close to a page boundary: do a byte-byte-byte * compare for the following 8 bytes, and then go back to * the full-word compare loop. */ li %r3, 8 /* loop count */ cmpw %r3, %r5 /* take min(8, counter) */ ble f2 mr. %r3, %r5 beqlr f2: mtctr %r3 subf %r5, %r3, %r5 /* adjust counter */ bbb: lbz %r6, 0(%r11) /* byte copy loop */ addi %r11, %r11, 1 lbz %r8, 0(%r4) addi %r4, %r4, 1 cmplw %r8, %r6 bdnzt eq, bbb bne all_done cmpwi %r5, 0 bgt again /* handle the rest */ xor %r3,%r3,%r3 blr #if 0 /* Removed code section. DWG */ partial: mr. %r3, %r5 beqlr /* If count -> 0, we're done */ f1: subfic %r3, %r3, 4 /* zero/end in first word? */ cmpwi %r3, 0 blt last4 #endif /* DWG */ first4: subfic %r3, %r5, 4 /* If count <= 4, handle */ rlwinm %r3, %r3, 3, 0, 31 /* count *= 8 */ srw %r6, %r6, %r3 /* align 1st buffer 1 word */ srw %r8, %r8, %r3 /* align 1st buffer 2 word */ cmplw %r8, %r6 /* get result */ bne all_done xor %r3,%r3,%r3 blr last4: subfic %r10, %r5, 8 /*DWG*/ rlwinm %r10, %r10, 3, 0, 31 /* count *= 8 */ srw %r7, %r7, %r10 /* align 2nd buffer 1 word */ srw %r9, %r9, %r10 /* align 2nd buffer 2 word */ cmplw %r9, %r7 /* get result */ bne all_done ret_0: xor %r3,%r3,%r3 /* Equal result */ blr all_done: blt finish_lt addi %r3,0,-1 /* Less than result */ blr finish_lt: addi %r3,0,1 /* Greater than result */ blr END(memcmp)