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 * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 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 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 2N/A * The ascii_strcasecmp() function is a case insensitive versions of strcmp(). 2N/A * It assumes the ASCII character set and ignores differences in case 2N/A * when comparing lower and upper case characters. In other words, it 2N/A * behaves as if both strings had been converted to lower case using 2N/A * tolower() in the "C" locale on each byte, and the results had then 2N/A * been compared using strcmp(). 2N/A * The assembly code below is an optimized version of the following C 2N/A * static const char charmap[] = { 2N/A * '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', 2N/A * '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', 2N/A * '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', 2N/A * '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', 2N/A * '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', 2N/A * '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', 2N/A * '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', 2N/A * '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', 2N/A * '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 2N/A * '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 2N/A * '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 2N/A * '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', 2N/A * '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', 2N/A * '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', 2N/A * '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', 2N/A * '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', 2N/A * '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', 2N/A * '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', 2N/A * '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', 2N/A * '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', 2N/A * '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', 2N/A * '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', 2N/A * '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', 2N/A * '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', 2N/A * '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', 2N/A * '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', 2N/A * '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', 2N/A * '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', 2N/A * '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', 2N/A * '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', 2N/A * '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', 2N/A * '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', 2N/A * ascii_strcasecmp(const char *s1, const char *s2) 2N/A * const unsigned char *cm = (const unsigned char *)charmap; 2N/A * const unsigned char *us1 = (const unsigned char *)s1; 2N/A * const unsigned char *us2 = (const unsigned char *)s2; 2N/A * while (cm[*us1] == cm[*us2++]) 2N/A * if (*us1++ == '\0') 2N/A * return (cm[*us1] - cm[*(us2 - 1)]); 2N/A * The following algorithm, from a 1987 news posting by Alan Mycroft, is 2N/A * used for finding null bytes in a word: 2N/A * #define has_null(word) ((word - 0x01010101) & (~word & 0x80808080)) 2N/A * The following algorithm is used for a wordwise tolower() operation: 2N/A * parallel_tolower (unsigned int x) 2N/A * unsigned int m1 = 0x80808080; 2N/A * unsigned int m2 = 0x3f3f3f3f; 2N/A * unsigned int m3 = 0x25252525; 2N/A * q = x & ~m1;// newb = byte & 0x7F 2N/A * p = q + m2; // newb > 0x5A --> MSB set 2N/A * q = q + m3; // newb < 0x41 --> MSB clear 2N/A * p = p & ~q; // newb > 0x40 && newb < 0x5B --> MSB set 2N/A * q = m1 & ~x;// byte < 0x80 --> 0x80 2N/A * q = p & q; // newb > 0x40 && newb < 0x5B && byte < 0x80 -> 0x80,else 0 2N/A * q = q >> 2; // newb > 0x40 && newb < 0x5B && byte < 0x80 -> 0x20,else 0 2N/A * return (x + q); // translate uppercase characters to lowercase 2N/A * Both algorithms have been tested exhaustively for all possible 2^32 inputs. 2N/A ldub [%i1 + %i2], %i0 ! s1[0] 2N/A ldub [%i1], %g1 ! s2[0] 2N/A sub %i0, 'A
', %l0 ! transform for faster uppercase check 2N/A sub %g1, 'A
', %l1 ! transform for faster uppercase check 2N/A cmp %l0, ('Z
' - 'A
') ! s1[0] uppercase? 2N/A bleu,a .noxlate11 ! yes 2N/A add %i0, ('a
' - 'A
'), %i0 ! s1[0] = tolower(s1[0]) 2N/A cmp %l1, ('Z
' - 'A
') ! s2[0] uppercase? 2N/A bleu,a .noxlate12 ! yes 2N/A add %g1, ('a
' - 'A
'), %g1 ! s2[0] = tolower(s2[0]) 2N/A subcc %i0, %g1, %i0 ! tolower(s1[0]) != tolower(s2[0]) ? 2N/A bne,pn %ncc, .done ! yup, done 2N/A inc %i1 ! s1++, s2++ 2N/A addcc %i0, %g1, %i0 ! s1[0] == 0 ? 2N/A bz,pn %ncc, .done ! yup, done, strings equal 2N/A cmp %i3, 3 ! s1 aligned now? 2N/A bz %ncc, .s1aligned2 ! yup 2N/A sethi %hi(0x01010101), %i5 ! start loading Mycroft's
magic2 2N/A ldub [%i1 + %i2], %i0 ! s1[2] 2N/A ldub [%i1], %g1 ! s2[2] 2N/A sub %i0, 'A
', %l0 ! transform for faster uppercase check 2N/A sub %g1, 'A
', %l1 ! transform for faster uppercase check 2N/A cmp %l0, ('Z
' - 'A
') ! s1[2] uppercase? 2N/A bleu,a .noxlate31 ! yes 2N/A add %i0, ('a
' - 'A
'), %i0 ! s1[2] = tolower(s1[2]) 2N/A cmp %l1, ('Z
' - 'A
') ! s2[2] uppercase? 2N/A bleu,a .noxlate32 ! yes 2N/A add %g1, ('a
' - 'A
'), %g1 ! s2[2] = tolower(s2[2]) 2N/A subcc %i0, %g1, %i0 ! tolower(s1[2]) != tolower(s2[2]) ? 2N/A bne,pn %ncc, .done ! yup, done 2N/A inc %i1 ! s1++, s2++ 2N/A addcc %i0, %g1, %i0 ! s1[2] == 0 ? 2N/A bz,pn %ncc, .done ! yup, done, strings equal 2N/A or %i5, %lo(0x01010101),%i5! finish loading Mycroft's
magic2 2N/A ! enough to have a word aligned desintation 2N/A sethi %hi(0x01010101), %i5 ! start loading Mycroft's
magic2 2N/A or %i5, %lo(0x01010101),%i5! finish loading Mycroft's
magic2