X-Git-Url: https://git.saurik.com/apple/libc.git/blobdiff_plain/1f2f436a38f7ae2d39a943ad2898d8fed4ed2e58..ad3c9f2af814c84582fdd1649e49ec4f68572c5a:/arm/string/memcmp.s diff --git a/arm/string/memcmp.s b/arm/string/memcmp.s index e69de29..2cdd5a3 100644 --- a/arm/string/memcmp.s +++ b/arm/string/memcmp.s @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2009 Apple Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +// ARM Assembly implementation of memcmp( ) from +// Uses Thumb2 if it is available, otherwise generates ARM code. +// +// -- Stephen Canon, August 2009 +// +// The basic idea is to use word compares instead of byte compares as long as +// at least four bytes remain to be compared. However, because memcmp( ) +// compares the buffers as though they were big-endian unsigned integers, we +// need to byte-reverse each word before comparing them. +// +// If the buffers are not word aligned, or they are shorter than four bytes, +// we just use a simple byte comparison loop instead. +// +// int bcmp(void *src1, void *src2, size_t length); +// int memcmp(void *src1, void *src2, size_t length); + +.text +.syntax unified +#if defined __thumb2__ + .code 16 + .thumb_func _bcmp + .thumb_func _memcmp +#else + .code 32 +#endif + +#define ESTABLISH_FRAME \ + push {r7,lr};\ + mov r7, sp +#define CLEAR_FRAME_AND_RETURN \ + pop {r7,pc} + +#include + +#if defined _ARM_ARCH_6 + #define BYTE_REVERSE(reg,tmp) \ + rev reg, reg +#else // defined _ARM_ARCH_6 +// Prior to ARMv6, the REV instruction is not available. We use a very cute +// software workaround instead, which needs only a single scratch register. + #define BYTE_REVERSE(reg,tmp) \ + eor tmp, reg, reg, ror #16;\ + bic tmp, tmp, #0xff0000 ;\ + mov tmp, tmp, lsr #8 ;\ + eor reg, tmp, reg, ror #8 +#endif // defined _ARM_ARCH_6 + +.globl _bcmp +.globl _memcmp +.align 2 +_bcmp: +_memcmp: + // If both buffers are not word aligned, jump to a byte-comparison loop. + ESTABLISH_FRAME + orr ip, r0, r1 + tst ip, #3 + bne L_useByteComparisons + + // As long as at least four bytes of length remain, load one word from each + // buffer and check if they are equal. +0: subs r2, #4 + blo L_lessThanFourBytesRemain + ldr r3, [r0],#4 + ldr ip, [r1],#4 + cmp r3, ip + beq 0b + + // If words from the two buffers compared unequal, we end up here. We need + // to byte-swap both words, then subtract to determine the result (+/-1). + BYTE_REVERSE(r3,r1) + BYTE_REVERSE(ip,r2) + mov r0, #1 + subs r3, ip + it lo + movlo r0, #-1 + CLEAR_FRAME_AND_RETURN + +L_lessThanFourBytesRemain: + adds r2, #4 +L_useByteComparisons: + mov r3, r0 + // If no bytes remain to compare, the buffers are equal and we return zero. + // Otherwise, load one byte from each buffer and check if they are equal. +0: subs r2, #1 + blo L_buffersAreEqual + ldrb r0, [r3],#1 + ldrb ip, [r1],#1 + subs r0, ip + beq 0b + CLEAR_FRAME_AND_RETURN + +L_buffersAreEqual: + mov r0, #0 + CLEAR_FRAME_AND_RETURN