1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 .file "memcmp.s" 27 28/ 29/ memcmp(s1, s2, n) 30/ 31/ Compares n bytes: s1>s2: >0 s1==s2: 0 s1<s2: <0 32/ 33/ Fast assembly language version of the following C-program strcat 34/ which represents the `standard' for the C-library. 35/ 36/ int 37/ memcmp(const void *s1, const void *s2, size_t n) 38/ { 39/ if (s1 != s2 && n != 0) { 40/ const unsigned char *ps1 = s1; 41/ const unsigned char *ps2 = s2; 42/ 43/ do { 44/ if (*ps1++ != *ps2++) 45/ return (ps1[-1] - ps2[-1]); 46/ } while (--n != 0); 47/ } 48/ return (NULL); 49/ } 50/ 51/ This implementation conforms to SVID but does not implement 52/ the same algorithm as the portable version because it is 53/ inconvenient to get the difference of the differing characters. 54 55#include <sys/asm_linkage.h> 56 57 ANSI_PRAGMA_WEAK(memcmp,function) 58 59#include "SYS.h" 60 61 ENTRY(memcmp) 62 pushl %edi / save register variable 63 movl 8(%esp), %eax / %eax = address of string 1 64 movl 12(%esp), %ecx / %ecx = address of string 2 65 cmpl %eax, %ecx / if the same string 66 je .equal / goto .equal 67 movl 16(%esp), %edi / %edi = length in bytes 68 cmpl $4, %edi / if %edi < 4 69 jb .byte_check / goto .byte_check 70 .align 4 71.word_loop: 72 movl (%ecx), %edx / move 1 word from (%ecx) to %edx 73 leal -4(%edi), %edi / %edi -= 4 74 cmpl (%eax), %edx / compare 1 word from (%eax) with %edx 75 jne .word_not_equal / if not equal, goto .word_not_equal 76 leal 4(%ecx), %ecx / %ecx += 4 (next word) 77 leal 4(%eax), %eax / %eax += 4 (next word) 78 cmpl $4, %edi / if %edi >= 4 79 jae .word_loop / goto .word_loop 80.byte_check: 81 cmpl $0, %edi / if %edi == 0 82 je .equal / goto .equal 83 jmp .byte_loop / goto .byte_loop (checks in bytes) 84.word_not_equal: 85 leal 4(%edi), %edi / %edi += 4 (post-decremented) 86 .align 4 87.byte_loop: 88 movb (%ecx), %dl / move 1 byte from (%ecx) to %dl 89 cmpb %dl, (%eax) / compare %dl with 1 byte from (%eax) 90 jne .not_equal / if not equal, goto .not_equal 91 incl %ecx / %ecx++ (next byte) 92 incl %eax / %eax++ (next byte) 93 decl %edi / %edi-- 94 jnz .byte_loop / if not zero, goto .byte_loop 95.equal: 96 xorl %eax, %eax / %eax = 0 97 popl %edi / restore register variable 98 ret / return (NULL) 99 .align 4 100.not_equal: 101 sbbl %eax, %eax / %eax = 0 if no carry, %eax = -1 if carry 102 orl $1, %eax / %eax = 1 if no carry, %eax = -1 if carry 103 popl %edi / restore register variable 104 ret / return (NULL) 105 SET_SIZE(memcmp) 106