1*84d9c625SLionel Sambuc/* $NetBSD: memcmp.S,v 1.4 2013/07/04 20:57:59 matt Exp $ */ 2b6cbf720SGianluca Guida 3b6cbf720SGianluca Guida/* stropt/memcmp.S, pl_string_common, pl_linux 10/11/04 11:45:35 4b6cbf720SGianluca Guida * ========================================================================== 5b6cbf720SGianluca Guida * Optimized memcmp implementation for IBM PowerPC 405/440. 6b6cbf720SGianluca Guida * 7b6cbf720SGianluca Guida * Copyright (c) 2003, IBM Corporation 8b6cbf720SGianluca Guida * All rights reserved. 9b6cbf720SGianluca Guida * 10b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or 11b6cbf720SGianluca Guida * without modification, are permitted provided that the following 12b6cbf720SGianluca Guida * conditions are met: 13b6cbf720SGianluca Guida * 14b6cbf720SGianluca Guida * * Redistributions of source code must retain the above 15b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 16b6cbf720SGianluca Guida * disclaimer. 17b6cbf720SGianluca Guida * * Redistributions in binary form must reproduce the above 18b6cbf720SGianluca Guida * copyright notice, this list of conditions and the following 19b6cbf720SGianluca Guida * disclaimer in the documentation and/or other materials 20b6cbf720SGianluca Guida * provided with the distribution. 21b6cbf720SGianluca Guida * * Neither the name of IBM nor the names of its contributors 22b6cbf720SGianluca Guida * may be used to endorse or promote products derived from this 23b6cbf720SGianluca Guida * software without specific prior written permission. 24b6cbf720SGianluca Guida * 25b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 26b6cbf720SGianluca Guida * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 27b6cbf720SGianluca Guida * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28b6cbf720SGianluca Guida * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29b6cbf720SGianluca Guida * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 30b6cbf720SGianluca Guida * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31b6cbf720SGianluca Guida * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 32b6cbf720SGianluca Guida * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 33b6cbf720SGianluca Guida * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 34b6cbf720SGianluca Guida * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35b6cbf720SGianluca Guida * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 36b6cbf720SGianluca Guida * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37b6cbf720SGianluca Guida * 38b6cbf720SGianluca Guida * ========================================================================== 39b6cbf720SGianluca Guida * 40b6cbf720SGianluca Guida * Function: Compare two character strings (up to n characters) 41b6cbf720SGianluca Guida * 42b6cbf720SGianluca Guida * int memcmp(const char *s1, const char *s2, int n) 43b6cbf720SGianluca Guida * 44b6cbf720SGianluca Guida * Input: r3 - buffer 1 address 45b6cbf720SGianluca Guida * r4 - buffer 2 address 46b6cbf720SGianluca Guida * r5 - maximum characters to compare 47b6cbf720SGianluca Guida * Output: r3 <0 (less), 0 (equal), >0 (greater) 48b6cbf720SGianluca Guida * 49b6cbf720SGianluca Guida * ========================================================================== 50b6cbf720SGianluca Guida */ 51b6cbf720SGianluca Guida 52b6cbf720SGianluca Guida#include <machine/asm.h> 53b6cbf720SGianluca Guida 54b6cbf720SGianluca Guida .text 55b6cbf720SGianluca Guida .align 4 56b6cbf720SGianluca Guida/* LINTSTUB: Func: void *memcmp(const void *, const void *, size_t) */ 57b6cbf720SGianluca GuidaENTRY(memcmp) 58b6cbf720SGianluca Guida 59b6cbf720SGianluca Guida /* 60b6cbf720SGianluca Guida * Check count passed in R5. If zero, return 0; otherwise continue. 61b6cbf720SGianluca Guida */ 62b6cbf720SGianluca Guida cmpwi %r5,0 63b6cbf720SGianluca Guida beq- ret_0; 64b6cbf720SGianluca Guida 65b6cbf720SGianluca Guida /* 66b6cbf720SGianluca Guida * Most of the time the difference is found in the first 67b6cbf720SGianluca Guida * several bytes. The following code minimizes the number 68b6cbf720SGianluca Guida * of load operations for short compares. 69b6cbf720SGianluca Guida */ 70b6cbf720SGianluca Guida 71b6cbf720SGianluca Guida mr %r11, %r3 /* Save buffer 1 */ 72b6cbf720SGianluca Guida 73b6cbf720SGianluca Guidaagain: 74b6cbf720SGianluca Guida 75b6cbf720SGianluca Guida not %r10, %r4 /* buffer 2: bytes to page bdy */ 76b6cbf720SGianluca Guida rlwinm. %r10, %r10,29,23,31 /* buffer 2: dwords to page bdy */ 77b6cbf720SGianluca Guida beq- bytebybyte /* If < 8 bytes to the page bdy */ 78b6cbf720SGianluca Guida /* do byte by byte */ 79b6cbf720SGianluca Guida lwz %r8, 0(%r4) /* load 1st buffer 2 word */ 80b6cbf720SGianluca Guida 81b6cbf720SGianluca Guida not %r12, %r11 /* buffer 1: bytes to page bdy */ 82b6cbf720SGianluca Guida rlwinm. %r12, %r12,29,23,31 /* buffer 1: dwords to page bdy */ 83b6cbf720SGianluca Guida beq- bytebybyte /* If < 8 bytes to the page bdy */ 84b6cbf720SGianluca Guida /* do byte by byte */ 85b6cbf720SGianluca Guida lwz %r6, 0(%r11) /* load 1st buffer 1 word */ 86b6cbf720SGianluca Guida 87b6cbf720SGianluca Guida cmpwi %r5, 4 /* If remaining count <= 4 */ 88b6cbf720SGianluca Guida ble+ first4 /* handle specially. DWG */ 89b6cbf720SGianluca Guida 90b6cbf720SGianluca Guida cmplw %r8, %r6 /* compare buffer 2 and buffer 1*/ 91b6cbf720SGianluca Guida bne+ all_done /* different => we're done */ 92b6cbf720SGianluca Guida 93b6cbf720SGianluca Guida lwzu %r9, 4(%r4) /* load 2nd buffer 2 word */ 94b6cbf720SGianluca Guida lwzu %r7, 4(%r11) /* load 2nd buffer 1 word */ 95b6cbf720SGianluca Guida 96b6cbf720SGianluca Guida cmpwi %r5, 8 /* If remaining count <= 8 */ 97b6cbf720SGianluca Guida ble+ last4 /* handle specially. DWG */ 98b6cbf720SGianluca Guida 99b6cbf720SGianluca Guida cmplw %r9, %r7 /* compare buffer 2 and buffer 1*/ 100b6cbf720SGianluca Guida bne+ all_done /* different => we're done */ 101b6cbf720SGianluca Guida 102b6cbf720SGianluca Guida addi %r5, %r5, -8 /* Update character counter DWG */ 103b6cbf720SGianluca Guida addi %r10, %r4, 0x0004 /* DWG*/ 104b6cbf720SGianluca Guida not %r10, %r10 /* buffer 2: bytes to page bdy DWG */ 105b6cbf720SGianluca Guida rlwinm. %r10, %r10,29,23,31 /* buffer 2: dwords to page bdy DWG */ 106b6cbf720SGianluca Guida addi %r12, %r11, 0x0004 /* DWG */ 107b6cbf720SGianluca Guida not %r12, %r12 /* buffer 1: bytes to page bdy DWG */ 108b6cbf720SGianluca Guida rlwinm. %r12, %r12,29,23,31 /* buffer 1: dwords to page bdy DWG */ 109b6cbf720SGianluca Guida 110b6cbf720SGianluca Guida /* The following section prior to loop: figures out whether */ 111b6cbf720SGianluca Guida /* the buffer 1 or buffer 2 is closer to the page boundary. */ 112b6cbf720SGianluca Guida /* The main loop count is then set up to reflect the number of */ 113b6cbf720SGianluca Guida /* double words of the buffer that is closest */ 114b6cbf720SGianluca Guida 115b6cbf720SGianluca Guida cmpw %r10, %r12 /* Find closest */ 116b6cbf720SGianluca Guida blt lt 117b6cbf720SGianluca Guida 118b6cbf720SGianluca Guida mr %r10, %r12 119b6cbf720SGianluca Guida 120b6cbf720SGianluca Guidalt: 121b6cbf720SGianluca Guida 122b6cbf720SGianluca Guida srwi %r12, %r5, 3 /* Double check the total count */ 123b6cbf720SGianluca Guida cmpw %r10, %r12 /* limitation */ 124b6cbf720SGianluca Guida blt lt2 125b6cbf720SGianluca Guida 126b6cbf720SGianluca Guida mr %r10, %r12 /* DWG */ 127b6cbf720SGianluca Guidalt2: /* DWG */ 128b6cbf720SGianluca Guida cmpwi %r10, 0 /* DWG */ 129b6cbf720SGianluca Guida bne lt3 /* DWG */ 130b6cbf720SGianluca Guida addi %r4, %r4, 0x0004 /* DWG */ 131b6cbf720SGianluca Guida addi %r11,%r11,0x0004 /* DWG */ 132b6cbf720SGianluca Guida b again /* DWG */ 133b6cbf720SGianluca Guidalt3: /* DWG */ 134b6cbf720SGianluca Guida mtctr %r10 /* dword count for loop */ 135b6cbf720SGianluca Guida lwzu %r6, 4(%r11) /* pre-load buffer 1 word */ 136b6cbf720SGianluca Guida 137b6cbf720SGianluca Guida b in /* To the loop */ 138b6cbf720SGianluca Guida 139b6cbf720SGianluca Guidaloop: /* main loop */ 140b6cbf720SGianluca Guida 141b6cbf720SGianluca Guida cmplw %r8, %r6 /* Compare first buffer 2 word */ 142b6cbf720SGianluca Guida bne- all_done /* with first buffer 1 word */ 143b6cbf720SGianluca Guida /* If different, we're done */ 144b6cbf720SGianluca Guida cmplw %r9, %r7 /* Compare second buffer 2 word */ 145b6cbf720SGianluca Guida /* with second buffer 1 word */ 146b6cbf720SGianluca Guida lwzu %r6, 4(%r11) /* pre-load buffer 1 word */ 147b6cbf720SGianluca Guida 148b6cbf720SGianluca Guida bne- all_done /* If different, we're done */ 149b6cbf720SGianluca Guida 150b6cbf720SGianluca Guidain: 151b6cbf720SGianluca Guida 152b6cbf720SGianluca Guida lwzu %r7, 4(%r11) /* pre-load buffer 1 word */ 153b6cbf720SGianluca Guida lwzu %r8, 4(%r4) /* pre-load buffer 2 word */ 154b6cbf720SGianluca Guida lwzu %r9, 4(%r4) /* pre-load buffer 2 word */ 155b6cbf720SGianluca Guida 156b6cbf720SGianluca Guida bdnz+ loop /* Do more DW's if cnt > 0 */ 157b6cbf720SGianluca Guida 158b6cbf720SGianluca Guida /*mfctr %r12*/ /*DWG*/ /* number of dwords left */ 159b6cbf720SGianluca Guida /*subf %r10, %r12, %r10*/ /*DWG*//* number of dwords compared */ 160b6cbf720SGianluca Guida slwi %r10, %r10, 3 161b6cbf720SGianluca Guida subf %r5, %r10, %r5 /* adjust byte counter */ 162b6cbf720SGianluca Guida /*bne+ partial*/ /*DWG*/ /* If less than 8 bytes, handle */ 163b6cbf720SGianluca Guida /* specially */ 164b6cbf720SGianluca Guida /*cmpwi %r5, 8*/ /* Removed. DWG */ 165b6cbf720SGianluca Guida /*blt partial*/ /* Removed. DWG */ 166b6cbf720SGianluca Guida 167b6cbf720SGianluca Guida /*addic %r5, %r5, -8*/ /*DWG*/ /* Subtract two words from count*/ 168b6cbf720SGianluca Guida 169b6cbf720SGianluca Guida cmplw %r8, %r6 /* compare last dword */ 170b6cbf720SGianluca Guida addi %r4, %r4, 4 171b6cbf720SGianluca Guida bne- all_done 172b6cbf720SGianluca Guida 173b6cbf720SGianluca Guida cmplw %r9, %r7 174b6cbf720SGianluca Guida addi %r11, %r11, 4 175b6cbf720SGianluca Guida bne- all_done 176b6cbf720SGianluca Guida 177b6cbf720SGianluca Guidabytebybyte: 178b6cbf720SGianluca Guida 179b6cbf720SGianluca Guida /* We've gotten close to a page boundary: do a byte-byte-byte 180b6cbf720SGianluca Guida * compare for the following 8 bytes, and then go back to 181b6cbf720SGianluca Guida * the full-word compare loop. 182b6cbf720SGianluca Guida */ 183b6cbf720SGianluca Guida 184b6cbf720SGianluca Guida li %r3, 8 /* loop count */ 185b6cbf720SGianluca Guida cmpw %r3, %r5 /* take min(8, counter) */ 186b6cbf720SGianluca Guida ble f2 187b6cbf720SGianluca Guida 188b6cbf720SGianluca Guida mr. %r3, %r5 189b6cbf720SGianluca Guida 190b6cbf720SGianluca Guida beqlr 191b6cbf720SGianluca Guida 192b6cbf720SGianluca Guidaf2: 193b6cbf720SGianluca Guida 194b6cbf720SGianluca Guida mtctr %r3 195b6cbf720SGianluca Guida subf %r5, %r3, %r5 /* adjust counter */ 196b6cbf720SGianluca Guida 197b6cbf720SGianluca Guidabbb: 198b6cbf720SGianluca Guida 199b6cbf720SGianluca Guida lbz %r6, 0(%r11) /* byte copy loop */ 200b6cbf720SGianluca Guida 201b6cbf720SGianluca Guida addi %r11, %r11, 1 202b6cbf720SGianluca Guida 203b6cbf720SGianluca Guida lbz %r8, 0(%r4) 204b6cbf720SGianluca Guida 205b6cbf720SGianluca Guida addi %r4, %r4, 1 206b6cbf720SGianluca Guida 207b6cbf720SGianluca Guida cmplw %r8, %r6 208b6cbf720SGianluca Guida 209*84d9c625SLionel Sambuc bdnzt eq, bbb 210b6cbf720SGianluca Guida 211b6cbf720SGianluca Guida bne all_done 212b6cbf720SGianluca Guida 213b6cbf720SGianluca Guida cmpwi %r5, 0 214b6cbf720SGianluca Guida bgt again /* handle the rest */ 215b6cbf720SGianluca Guida 216b6cbf720SGianluca Guida xor %r3,%r3,%r3 217b6cbf720SGianluca Guida 218b6cbf720SGianluca Guida blr 219b6cbf720SGianluca Guida 220b6cbf720SGianluca Guida#if 0 /* Removed code section. DWG */ 221b6cbf720SGianluca Guidapartial: 222b6cbf720SGianluca Guida 223b6cbf720SGianluca Guida mr. %r3, %r5 224b6cbf720SGianluca Guida 225b6cbf720SGianluca Guida beqlr /* If count -> 0, we're done */ 226b6cbf720SGianluca Guida 227b6cbf720SGianluca Guidaf1: 228b6cbf720SGianluca Guida 229b6cbf720SGianluca Guida subfic %r3, %r3, 4 /* zero/end in first word? */ 230b6cbf720SGianluca Guida cmpwi %r3, 0 231b6cbf720SGianluca Guida blt last4 232b6cbf720SGianluca Guida#endif /* DWG */ 233b6cbf720SGianluca Guida 234b6cbf720SGianluca Guidafirst4: 235b6cbf720SGianluca Guida subfic %r3, %r5, 4 /* If count <= 4, handle */ 236b6cbf720SGianluca Guida rlwinm %r3, %r3, 3, 0, 31 /* count *= 8 */ 237b6cbf720SGianluca Guida srw %r6, %r6, %r3 /* align 1st buffer 1 word */ 238b6cbf720SGianluca Guida srw %r8, %r8, %r3 /* align 1st buffer 2 word */ 239b6cbf720SGianluca Guida 240b6cbf720SGianluca Guida cmplw %r8, %r6 /* get result */ 241b6cbf720SGianluca Guida bne all_done 242b6cbf720SGianluca Guida xor %r3,%r3,%r3 243b6cbf720SGianluca Guida blr 244b6cbf720SGianluca Guida 245b6cbf720SGianluca Guidalast4: 246b6cbf720SGianluca Guida subfic %r10, %r5, 8 /*DWG*/ 247b6cbf720SGianluca Guida rlwinm %r10, %r10, 3, 0, 31 /* count *= 8 */ 248b6cbf720SGianluca Guida srw %r7, %r7, %r10 /* align 2nd buffer 1 word */ 249b6cbf720SGianluca Guida srw %r9, %r9, %r10 /* align 2nd buffer 2 word */ 250b6cbf720SGianluca Guida 251b6cbf720SGianluca Guida cmplw %r9, %r7 /* get result */ 252b6cbf720SGianluca Guida bne all_done 253b6cbf720SGianluca Guidaret_0: 254b6cbf720SGianluca Guida xor %r3,%r3,%r3 /* Equal result */ 255b6cbf720SGianluca Guida blr 256b6cbf720SGianluca Guida 257b6cbf720SGianluca Guidaall_done: 258b6cbf720SGianluca Guida 259b6cbf720SGianluca Guida blt finish_lt 260b6cbf720SGianluca Guida 261b6cbf720SGianluca Guida addi %r3,0,-1 /* Less than result */ 262b6cbf720SGianluca Guida 263b6cbf720SGianluca Guida blr 264b6cbf720SGianluca Guida 265b6cbf720SGianluca Guidafinish_lt: 266b6cbf720SGianluca Guida 267b6cbf720SGianluca Guida addi %r3,0,1 /* Greater than result */ 268b6cbf720SGianluca Guida 269b6cbf720SGianluca Guida blr 270b6cbf720SGianluca GuidaEND(memcmp) 271