Home | History | Annotate | Download | only in string
      1 /*
      2  * Copyright (c) 2010 MIPS Technologies, Inc.
      3  *
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  *      * Redistributions of source code must retain the above copyright
     11  *        notice, this list of conditions and the following disclaimer.
     12  *      * Redistributions in binary form must reproduce the above copyright
     13  *        notice, this list of conditions and the following disclaimer
     14  *        in the documentation and/or other materials provided with
     15  *        the distribution.
     16  *      * Neither the name of MIPS Technologies Inc. nor the names of its
     17  *        contributors may be used to endorse or promote products derived
     18  *        from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #ifndef __MIPS_STRING_OPS_H
     34 #define __MIPS_STRING_OPS_H
     35     /* This definition of the byte bitfields uses the
     36        assumption that the layout of the bitfields is
     37        equivalent to the layout in memory.  Generally,
     38        for the MIPS ABIs, this is true. If you compile
     39        the strcmp.c file with -DSMOKE_TEST_NEW_STRCMP,
     40        this assumption will be tested.
     41 
     42        Also, regardless of char signedness, ANSI C dictates that
     43        strcmp() treats each character as unsigned char.  For
     44        strlen and the like, signedness doesn't matter.
     45 
     46        Also, this code assumes that there are 8-bits per 'char'.  */
     47 
     48 #if __mips64
     49 typedef struct bits
     50 {
     51   unsigned B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8;
     52 } bits_t;
     53 #else
     54 typedef struct bits
     55 {
     56   unsigned B0:8, B1:8, B2:8, B3:8;
     57 } bits_t;
     58 #endif
     59 
     60 #ifndef _ULW
     61     /* for MIPS GCC, there is no unaligned builtins - so this code forces
     62        the compiler to treat the pointer access as unaligned.  */
     63 struct ulw
     64 {
     65   unsigned b;
     66 } __attribute__ ((packed));
     67 
     68 #define _ULW(__x) ((struct ulw *) ((char *)(&__x)))->b;
     69 #endif
     70 
     71 /* This union assumes that small structures can be in registers.  If
     72    not, then memory accesses will be done - not optimal, but ok.  */
     73 typedef union
     74 {
     75   unsigned v;
     76   bits_t b;
     77 } bitfields_t;
     78 
     79 #ifndef detect_zero
     80 /* __mips_dsp, __mips_dspr2, and __mips64 are predefined by
     81    the compiler, based on command line options.  */
     82 #if (__mips_dsp || __mips_dspr2) && !__mips64
     83 #define __mips_using_dsp 1
     84 
     85 /* DSP 4-lane (8 unsigned bits per line) subtract and saturate
     86  * Intrinsic operation. How this works:
     87  *     Given a 4-byte string of "ABC\0", subtract this as
     88  *     an unsigned integer from 0x01010101:
     89  *	   0x01010101
     90  *       - 0x41424300
     91  *        -----------
     92  (         0xbfbebe01 <-- answer without saturation
     93  *	   0x00000001 <-- answer with saturation
     94  * When this 4-lane vector is treated as an unsigned int value,
     95  * a non-zero answer indicates the presence of a zero in the
     96  * original 4-byte argument.  */
     97 
     98 typedef signed char v4i8 __attribute__ ((vector_size (4)));
     99 
    100 #define detect_zero(__x,__y,__01s,__80s)\
    101        ((unsigned) __builtin_mips_subu_s_qb((v4i8) __01s,(v4i8) __x))
    102 
    103     /* sets all 4 lanes to requested byte.  */
    104 #define set_byte_lanes(__x) ((unsigned) __builtin_mips_repl_qb(__x))
    105 
    106     /* sets all 4 lanes to 0x01.  */
    107 #define def_and_set_01(__x) unsigned __x = (unsigned) __builtin_mips_repl_qb(0x01)
    108 
    109     /* sets all 4 lanes to 0x80. Not needed when subu_s.qb used. */
    110 #define def_and_set_80(__x) /* do nothing */
    111 
    112 #else
    113     /* this version, originally published in the 80's, uses
    114        a reverse-carry-set like determination of the zero byte.
    115        The steps are, for __x = 0x31ff0001:
    116        __x - _01s = 0x30fdff00
    117        ~__x = 0xce00fffe
    118        ((__x - _01s) & ~__x) = 0x0000ff00
    119        x & _80s = 0x00008000 <- byte 3 was zero
    120        Some implementaions naively assume that characters are
    121        always 7-bit unsigned ASCII. With that assumption, the
    122        "& ~x" is usually discarded. Since character strings
    123        are 8-bit, the and is needed to catch the case of
    124        a false positive when the byte is 0x80. */
    125 
    126 #define detect_zero(__x,__y,_01s,_80s)\
    127 	((unsigned) (((__x) - _01s) & ~(__x)) & _80s)
    128 
    129 #if __mips64
    130 #define def_and_set_80(__x) unsigned __x =  0x8080808080808080ul
    131 #define def_and_set_01(__x)  unsigned __x = 0x0101010101010101ul
    132 #else
    133 #define def_and_set_80(__x) unsigned __x = 0x80808080ul
    134 #define def_and_set_01(__x) unsigned __x = 0x01010101ul
    135 #endif
    136 
    137 #endif
    138 #endif
    139 
    140 /* dealing with 'void *' conversions without using extra variables. */
    141 #define get_byte(__x,__idx) (((unsigned char *) (__x))[__idx])
    142 #define set_byte(__x,__idx,__fill) ((unsigned char *) (__x))[__idx] = (__fill)
    143 #define get_word(__x,__idx) (((unsigned *) (__x))[__idx])
    144 #define set_word(__x,__idx,__fill) ((unsigned *) (__x))[__idx] = (__fill)
    145 #define inc_ptr_as(__type,__x,__inc) __x = (void *) (((__type) __x) + (__inc))
    146 #define cvt_ptr_to(__type,__x) ((__type) (__x))
    147 
    148 #endif
    149