00001 /* 00002 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 00003 * The President and Fellows of Harvard College. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the University nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 */ 00029 00030 #include <types.h> 00031 #include <endian.h> 00032 00033 /* 00034 * Unconditional byte-swap functions. 00035 * 00036 * bswap16, 32, and 64 unconditionally swap byte order of integers of 00037 * the respective bitsize. 00038 * 00039 * The advantage of writing them out like this is that the bit 00040 * patterns are easily validated by inspection. Also, this form is 00041 * more likely to be picked up by the compiler and converted into 00042 * byte-swap machine instructions (if those exist) than something 00043 * loop-based. 00044 */ 00045 00046 uint16_t 00047 bswap16(uint16_t val) 00048 { 00049 return ((val & 0x00ff) << 8) 00050 | ((val & 0xff00) >> 8); 00051 } 00052 00053 uint32_t 00054 bswap32(uint32_t val) 00055 { 00056 return ((val & 0x000000ff) << 24) 00057 | ((val & 0x0000ff00) << 8) 00058 | ((val & 0x00ff0000) >> 8) 00059 | ((val & 0xff000000) >> 24); 00060 } 00061 00062 uint64_t 00063 bswap64(uint64_t val) 00064 { 00065 return ((val & 0x00000000000000ff) << 56) 00066 | ((val & 0x000000000000ff00) << 40) 00067 | ((val & 0x0000000000ff0000) << 24) 00068 | ((val & 0x00000000ff000000) << 8) 00069 | ((val & 0x000000ff00000000) << 8) 00070 | ((val & 0x0000ff0000000000) << 24) 00071 | ((val & 0x00ff000000000000) >> 40) 00072 | ((val & 0xff00000000000000) >> 56); 00073 } 00074 00075 /* 00076 * Network byte order byte-swap functions. 00077 * 00078 * For ntoh* and hton*: 00079 * *s are for "short" (16-bit) 00080 * *l are for "long" (32-bit) 00081 * *ll are for "long long" (64-bit) 00082 * 00083 * hton* convert from host byte order to network byte order. 00084 * ntoh* convert from network byte order to host byte order. 00085 * 00086 * Network byte order is big-endian. 00087 * 00088 * Note that right now the only platforms OS/161 runs on are 00089 * big-endian, so these functions are actually all empty. 00090 * 00091 * These should maybe be made inline. 00092 */ 00093 00094 #if _BYTE_ORDER == _LITTLE_ENDIAN 00095 #define TO(tag, bits, type) \ 00096 type ntoh##tag(type val) { return bswap##bits(val); } \ 00097 type hton##tag(type val) { return bswap##bits(val); } 00098 #endif 00099 00100 /* 00101 * Use a separate #if, so if the header file defining the symbols gets 00102 * omitted or messed up the build will fail instead of silently choosing 00103 * the wrong option. 00104 */ 00105 #if _BYTE_ORDER == _BIG_ENDIAN 00106 #define TO(tag, bits, type) \ 00107 type ntoh##tag(type val) { return val; } \ 00108 type hton##tag(type val) { return val; } 00109 #endif 00110 00111 #if _BYTE_ORDER == _PDP_ENDIAN 00112 #error "You lose." 00113 #endif 00114 00115 #ifndef TO 00116 #error "_BYTE_ORDER not set" 00117 #endif 00118 00119 TO(s, 16, uint16_t) 00120 TO(l, 32, uint32_t) 00121 TO(ll, 64, uint64_t) 00122 00123 00124 /* 00125 * Some utility functions for handling 64-bit values. 00126 * 00127 * join32to64 pastes two adjoining 32-bit values together in the right 00128 * way to treat them as a 64-bit value, depending on endianness. 00129 * split64to32 is the inverse operation. 00130 * 00131 * The 32-bit arguments should be passed in the order they appear in 00132 * memory, not as high word and low word; the whole point of these 00133 * functions is to know which is the high word and which is the low 00134 * word. 00135 */ 00136 00137 void 00138 join32to64(uint32_t x1, uint32_t x2, uint64_t *y2) 00139 { 00140 #if _BYTE_ORDER == _BIG_ENDIAN 00141 *y2 = ((uint64_t)x1 << 32) | (uint64_t)x2; 00142 #elif _BYTE_ORDER == _LITTLE_ENDIAN 00143 *y2 = (uint64_t)x1 | ((uint64_t)x2 << 32); 00144 #else 00145 #error "Eh?" 00146 #endif 00147 } 00148 00149 void 00150 split64to32(uint64_t x, uint32_t *y1, uint32_t *y2) 00151 { 00152 #if _BYTE_ORDER == _BIG_ENDIAN 00153 *y1 = x >> 32; 00154 *y2 = x & 0xffffffff; 00155 #elif _BYTE_ORDER == _LITTLE_ENDIAN 00156 *y1 = x & 0xffffffff; 00157 *y2 = x >> 32; 00158 #else 00159 #error "Eh?" 00160 #endif 00161 }