2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A .file "memcmp.s"
2N/A
2N/A/
2N/A/ memcmp(s1, s2, n)
2N/A/
2N/A/ Compares n bytes: s1>s2: >0 s1==s2: 0 s1<s2: <0
2N/A/
2N/A/ Fast assembly language version of the following C-program strcat
2N/A/ which represents the `standard' for the C-library.
2N/A/
2N/A/ int
2N/A/ memcmp(const void *s1, const void *s2, size_t n)
2N/A/ {
2N/A/ if (s1 != s2 && n != 0) {
2N/A/ const unsigned char *ps1 = s1;
2N/A/ const unsigned char *ps2 = s2;
2N/A/
2N/A/ do {
2N/A/ if (*ps1++ != *ps2++)
2N/A/ return (ps1[-1] - ps2[-1]);
2N/A/ } while (--n != 0);
2N/A/ }
2N/A/ return (NULL);
2N/A/ }
2N/A/
2N/A/ This implementation conforms to SVID but does not implement
2N/A/ the same algorithm as the portable version because it is
2N/A/ inconvenient to get the difference of the differing characters.
2N/A
2N/A#include <sys/asm_linkage.h>
2N/A
2N/A ANSI_PRAGMA_WEAK(memcmp,function)
2N/A
2N/A#include "SYS.h"
2N/A
2N/A ENTRY(memcmp)
2N/A pushl %edi / save register variable
2N/A movl 8(%esp), %eax / %eax = address of string 1
2N/A movl 12(%esp), %ecx / %ecx = address of string 2
2N/A cmpl %eax, %ecx / if the same string
2N/A je .equal / goto .equal
2N/A movl 16(%esp), %edi / %edi = length in bytes
2N/A cmpl $4, %edi / if %edi < 4
2N/A jb .byte_check / goto .byte_check
2N/A .align 4
2N/A.word_loop:
2N/A movl (%ecx), %edx / move 1 word from (%ecx) to %edx
2N/A leal -4(%edi), %edi / %edi -= 4
2N/A cmpl (%eax), %edx / compare 1 word from (%eax) with %edx
2N/A jne .word_not_equal / if not equal, goto .word_not_equal
2N/A leal 4(%ecx), %ecx / %ecx += 4 (next word)
2N/A leal 4(%eax), %eax / %eax += 4 (next word)
2N/A cmpl $4, %edi / if %edi >= 4
2N/A jae .word_loop / goto .word_loop
2N/A.byte_check:
2N/A cmpl $0, %edi / if %edi == 0
2N/A je .equal / goto .equal
2N/A jmp .byte_loop / goto .byte_loop (checks in bytes)
2N/A.word_not_equal:
2N/A leal 4(%edi), %edi / %edi += 4 (post-decremented)
2N/A .align 4
2N/A.byte_loop:
2N/A movb (%ecx), %dl / move 1 byte from (%ecx) to %dl
2N/A cmpb %dl, (%eax) / compare %dl with 1 byte from (%eax)
2N/A jne .not_equal / if not equal, goto .not_equal
2N/A incl %ecx / %ecx++ (next byte)
2N/A incl %eax / %eax++ (next byte)
2N/A decl %edi / %edi--
2N/A jnz .byte_loop / if not zero, goto .byte_loop
2N/A.equal:
2N/A xorl %eax, %eax / %eax = 0
2N/A popl %edi / restore register variable
2N/A ret / return (NULL)
2N/A .align 4
2N/A.not_equal:
2N/A sbbl %eax, %eax / %eax = 0 if no carry, %eax = -1 if carry
2N/A orl $1, %eax / %eax = 1 if no carry, %eax = -1 if carry
2N/A popl %edi / restore register variable
2N/A ret / return (NULL)
2N/A SET_SIZE(memcmp)