Annotation of coherent/f/usr/include/common/_canon.h, revision 1.1.1.1

1.1       root        1: #ifndef        __COMMON__CANON_H__
                      2: #define        __COMMON__CANON_H__
                      3: 
                      4: /*
                      5:  * This file contains definitions related to canonicalization of numeric
                      6:  * formats. Routines are provided for conversions between the native format
                      7:  * and numerous other canonical forms, with varying argument patterns so that
                      8:  * conversion can be done in a space- and/or time-efficient manner. In
                      9:  * particular, separate versions for each routine exists that operate on an
                     10:  * lvalue to return a converted value, on an rvalue to return a converted
                     11:  * value, and to perform in-place conversion on an lvalue, so that the most
                     12:  * efficient machine idioms can be used for particular target machines.
                     13:  * The routines in this file are oriented towards systems with 32-bit long-
                     14:  * integer arithmetic, but extensions should be trivial.
                     15:  *
                     16:  *     canonicalize    -> to make canonical
                     17:  *     canonical       -> according to the canons
                     18:  *     canons          -> the law
                     19:  *     canonize        -> to bestow sainthood
                     20:  */
                     21: 
                     22: #include <common/feature.h>
                     23: #include <common/_limits.h>
                     24: 
                     25: #if    __CHAR_BIT != 8
                     26: # error        The canonicalization system only applies to octet-oriented machines
                     27: #endif
                     28: 
                     29: /*
                     30:  * We begin by defining a basic type for the lvalue-oriented manipulations and
                     31:  * some fundamental concepts and facilities that build on that to create a
                     32:  * bottom layer to the system. We explain the operation of the system entirely
                     33:  * in terms of manipulations of octets.
                     34:  *
                     35:  * We begin by defining the basic notation for describing formats; the basic
                     36:  * parameter for a data format is how the octets in the numbers in that format
                     37:  * are laid out, which we specify relative to the lowest machine address
                     38:  * occupied by the datum (many canonical data formats are based on the notion
                     39:  * of transmission order, and we typically expect that "is transmitted before"
                     40:  * maps directly onto "has a lower address than" for a structure laid out in
                     41:  * machine memory).
                     42:  *
                     43:  * So, for an M68K, the index of the most-significant byte of a native-format
                     44:  * number is always zero, whereas for an Intel-format number the bytes (and
                     45:  * thus their indexes) are reversed. If we encode the index of the byte in the
                     46:  * canonical order as a (machine-independent) number with each index taking
                     47:  * up a byte, then we get a value which when stored in that format will have
                     48:  * the values 0, 1, 2, ... stored in consecutive octets of machine memory.
                     49:  *
                     50:  * The nice thing about this encoding is that is thus reflective; if we have
                     51:  * a way of transforming abstract numbers according to this "map", we can
                     52:  * apply the transformation to the maps themselves to generate new maps which
                     53:  * can be used to encode other numbers or maps. This enables us to better deal
                     54:  * with the potential n^2 nature of the conversions by dynamically composing
                     55:  * the maps.
                     56:  */
                     57: 
                     58: typedef unsigned char *        __canon_t;
                     59: 
                     60: #define        __IDENTITY_16_MAP       0x0100U
                     61: #define __REVERSE_16_MAP       0x0001U
                     62: #define        __I386_16_MAP           __IDENTITY_16_MAP
                     63: #define        __M68K_16_MAP           __REVERSE_16_MAP
                     64: #define        __OCOH_16_MAP           __IDENTITY_16_MAP
                     65: 
                     66: #define        __IDENTITY_32_MAP       0x03020100UL
                     67: #define        __REVERSE_32_MAP        0x00010203UL
                     68: #define        __SWAP16_32_MAP         0x01000302UL
                     69: #define        __I386_32_MAP           __IDENTITY_32_MAP
                     70: #define        __M68K_32_MAP           __REVERSE_32_MAP
                     71: #define        __OCOH_32_MAP           __SWAP16_32_MAP
                     72: 
                     73: 
                     74: /*
                     75:  * The following primitive mapping functions use a map, and come in two
                     76:  * flavours; r-value oriented, and l-value oriented. The r-value-oriented
                     77:  * transformations have the special property of using only operations which
                     78:  * are permitted in the restricted form of integral constant expression that
                     79:  * can be used in #if-expressions. Applying the r-value transformations to
                     80:  * constants yields other constants.
                     81:  *
                     82:  * Note that the fundamental transformations have two (nearly) equivalent
                     83:  * forms, of which I find the recursive more aesthetically pleasing, so that
                     84:  * is the default form. We leave both in here for your amusement.
                     85:  */
                     86: 
                     87: #define        __OCTET_N_OF_R(r,n)     (((r) >> ((n) * 8)) & 0xFFU)
                     88: #define        __OCTET_N_OF_L(l,n)     (((__canon_t) & (l)) [n])
                     89: #define        __MAKE_OCTET_N(o,n)     ((o) << ((n) * 8))
                     90: 
                     91: #define        __CONVERT_OCTET_N_OF_R_VIA_MAP0(r,m,n) \
                     92:                __MAKE_OCTET_N (__OCTET_N_OF_R (r, n), __OCTET_N_OF_R (m, n))
                     93: 
                     94: #define        __CONVERT_OCTET_N_OF_R_VIA_MAP1(r,m,n) \
                     95:                __MAKE_OCTET_N (__OCTET_N_OF_R (r, __OCTET_N_OF_R (m, n)), n)
                     96: 
                     97: #define        __CONVERT_OCTET_N_OF_L_VIA_MAP0(l,m,n) \
                     98:                __MAKE_OCTET_N (__OCTET_N_OF_L (l, n), __OCTET_N_OF_R (m, n))
                     99: 
                    100: #define        __CONVERT_OCTET_N_OF_L_VIA_MAP1(l,m,n) \
                    101:                __MAKE_OCTET_N (__OCTET_N_OF_L (l, __OCTET_N_OF_R (m, n)), n)
                    102: 
                    103: #define        __CONVERT_R_16(r,m) \
                    104:                (__CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 0) | \
                    105:                 __CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 1))
                    106: 
                    107: #define        __CONVERT_L_16(l,m) \
                    108:                (__CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 0) | \
                    109:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 1))
                    110: 
                    111: #define        __CONVERT_R_32(r,m) \
                    112:                (__CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 0) | \
                    113:                 __CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 1) | \
                    114:                 __CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 2) | \
                    115:                 __CONVERT_OCTET_N_OF_R_VIA_MAP1 (r, m, 3))
                    116: 
                    117: #define        __CONVERT_L_32(l,m) \
                    118:                (__CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 0) | \
                    119:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 1) | \
                    120:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 2) | \
                    121:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 3))
                    122: 
                    123: /*
                    124:  * Here, we use rather more specific feature-tests to see about escaping to
                    125:  * special hand-coded routines or inlines, which is highly translator-specific
                    126:  * in addition to being machine-specific.
                    127:  */
                    128: 
                    129: #if    __GNUC__ && _I386
                    130: 
                    131: #if    __SHRT_BIT != 16 || __LONG_BIT != 32
                    132: # error        For GCC on i386, short should be 16 bits and a long should be 32.
                    133: #endif
                    134: 
                    135: #include <common/ccompat.h>
                    136: #include <common/xdebug.h>
                    137: 
                    138: /*
                    139:  * We supply two versions of some of the following depending on whether or not
                    140:  * you care about not being able to use the %ebp, %esi, and %edi registers as
                    141:  * operands or not.
                    142:  */
                    143: 
                    144: __LOCAL__ __INLINE__ unsigned short __swap_bytes (unsigned short _number) {
                    145:        unsigned short  _result;
                    146: #if    1
                    147:        __NON_ISO (asm) ("rolw $8, %0" : "=r" (_result) : "0" (_number));
                    148: #else
                    149:        __NON_ISO (asm) ("xchg %h0, %b0" : "=q" (_result) : "0" (_number));
                    150: #endif
                    151:        return _result;
                    152: }
                    153: 
                    154: __LOCAL__ __INLINE__ unsigned long __swap_words (unsigned long _number) {
                    155:        unsigned long   _result;
                    156:        __NON_ISO (asm) ("roll $16, %0" : "=r" (_result) : "0" (_number));
                    157:        return _result;
                    158: }
                    159: 
                    160: /*
                    161:  * On the i486 processor we have the BSWAP instruction, but the following
                    162:  * works on the i386 as well.
                    163:  */
                    164: 
                    165: __LOCAL__ __INLINE__ unsigned long __reverse_long (unsigned long _number) {
                    166:        unsigned long   _result;
                    167: #if    1
                    168:        __NON_ISO (asm) ("rolw $8, %0\n"
                    169:                         "roll $16, %0\n",
                    170:                         "rolw $8, %0\n" : "=r" (_result) : "0" (_number));
                    171: #else
                    172:        __NON_ISO (asm) ("xchg %h0, %b0\n"
                    173:                         "rorl $16, %0\n"
                    174:                         "xchg %h0, %b0\n" : "=q" (_result) : "0" (_number));
                    175: #endif
                    176:        return _result;
                    177: }
                    178: 
                    179: #undef __CONVERT_L_16
                    180: #define        __CONVERT_L_16(l,m) \
                    181:                ((m) == __REVERSE_16_MAP ? __swap_bytes (l) : \
                    182:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 0) | \
                    183:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 1))
                    184: 
                    185: #undef __CONVERT_L_32
                    186: #define        __CONVERT_L_32(l,m) \
                    187:                ((m) == __SWAP16_32_MAP ? __swap_words (l) : \
                    188:                 (m) == __REVERSE_32_MAP ? __reverse_long (l) : \
                    189:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 0) | \
                    190:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 1) | \
                    191:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 2) | \
                    192:                 __CONVERT_OCTET_N_OF_L_VIA_MAP1 (l, m, 3))
                    193: 
                    194: #endif /* __GNUC__ && _I386 */
                    195: 
                    196: 
                    197: /*
                    198:  * Now, use a variety of feature-tests to figure out the native format for the
                    199:  * host we are compiling for.
                    200:  */
                    201: 
                    202: #if    __MSDOS__ || _I386
                    203: 
                    204: # define       __NATIVE_16_MAP         __I386_16_MAP
                    205: # define       __NATIVE_32_MAP         __I386_32_MAP
                    206: 
                    207: #else
                    208: 
                    209: # error        What is the native endianness of your system?
                    210: 
                    211: #endif
                    212: 
                    213: #define        __CANON_FOO(value,l_or_r,type, map,ident) \
                    214:                ((map) == (ident) ? value : \
                    215:                        __CONCAT4 (__CONVERT_, l_or_r, _, type) \
                    216:                                (value, map))
                    217: 
                    218: #define        __CANONICALIZE(value,l_or_r,machine,type) \
                    219:                __CANON_FOO (value, l_or_r, type, \
                    220:                             __CONCAT (__CONVERT_R_, type) \
                    221:                                (__CONCAT3 (__NATIVE_, type, _MAP), \
                    222:                                 __CONCAT4 (machine, _, type, _MAP)), \
                    223:                             __CONCAT3 (__IDENTITY_, type, _MAP))
                    224: 
                    225: 
                    226: #endif /* ! defined (__COMMON__CANON_H__) */
                    227: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.