1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// ARM Assembly implementation of memcmp( ) from <string.h> 25// Uses Thumb2 if it is available, otherwise generates ARM code. 26// 27// -- Stephen Canon, August 2009 28// 29// The basic idea is to use word compares instead of byte compares as long as 30// at least four bytes remain to be compared. However, because memcmp( ) 31// compares the buffers as though they were big-endian unsigned integers, we 32// need to byte-reverse each word before comparing them. 33// 34// If the buffers are not word aligned, or they are shorter than four bytes, 35// we just use a simple byte comparison loop instead. 36// 37// int bcmp(void *src1, void *src2, size_t length); 38// int memcmp(void *src1, void *src2, size_t length); 39 40.text 41.syntax unified 42#if defined __thumb2__ 43 .code 16 44 .thumb_func _bcmp 45 .thumb_func _memcmp 46#else 47 .code 32 48#endif 49 50#define ESTABLISH_FRAME \ 51 push {r7,lr};\ 52 mov r7, sp 53#define CLEAR_FRAME_AND_RETURN \ 54 pop {r7,pc} 55 56#include <arm/arch.h> 57 58#if defined _ARM_ARCH_6 59 #define BYTE_REVERSE(reg,tmp) \ 60 rev reg, reg 61#else // defined _ARM_ARCH_6 62// Prior to ARMv6, the REV instruction is not available. We use a very cute 63// software workaround instead, which needs only a single scratch register. 64 #define BYTE_REVERSE(reg,tmp) \ 65 eor tmp, reg, reg, ror #16;\ 66 bic tmp, tmp, #0xff0000 ;\ 67 mov tmp, tmp, lsr #8 ;\ 68 eor reg, tmp, reg, ror #8 69#endif // defined _ARM_ARCH_6 70 71.globl _bcmp 72.globl _memcmp 73.align 2 74_bcmp: 75_memcmp: 76 // If both buffers are not word aligned, jump to a byte-comparison loop. 77 ESTABLISH_FRAME 78 orr ip, r0, r1 79 tst ip, #3 80 bne L_useByteComparisons 81 82 // As long as at least four bytes of length remain, load one word from each 83 // buffer and check if they are equal. 840: subs r2, #4 85 blo L_lessThanFourBytesRemain 86 ldr r3, [r0],#4 87 ldr ip, [r1],#4 88 cmp r3, ip 89 beq 0b 90 91 // If words from the two buffers compared unequal, we end up here. We need 92 // to byte-swap both words, then subtract to determine the result (+/-1). 93 BYTE_REVERSE(r3,r1) 94 BYTE_REVERSE(ip,r2) 95 mov r0, #1 96 subs r3, ip 97 it lo 98 movlo r0, #-1 99 CLEAR_FRAME_AND_RETURN 100 101L_lessThanFourBytesRemain: 102 adds r2, #4 103L_useByteComparisons: 104 mov r3, r0 105 // If no bytes remain to compare, the buffers are equal and we return zero. 106 // Otherwise, load one byte from each buffer and check if they are equal. 1070: subs r2, #1 108 blo L_buffersAreEqual 109 ldrb r0, [r3],#1 110 ldrb ip, [r1],#1 111 subs r0, ip 112 beq 0b 113 CLEAR_FRAME_AND_RETURN 114 115L_buffersAreEqual: 116 mov r0, #0 117 CLEAR_FRAME_AND_RETURN 118