1 /* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 /* 23 * Macros to extract possibly-unaligned big-endian integral values. 24 */ 25 #ifdef LBL_ALIGN 26 /* 27 * The processor doesn't natively handle unaligned loads. 28 */ 29 #if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \ 30 (defined(__alpha) || defined(__alpha__) || \ 31 defined(__mips) || defined(__mips__)) 32 33 /* 34 * This is a GCC-compatible compiler and we have __attribute__, which 35 * we assume that mean we have __attribute__((packed)), and this is 36 * MIPS or Alpha, which has instructions that can help when doing 37 * unaligned loads. 38 * 39 * Declare packed structures containing a uint16_t and a uint32_t, 40 * cast the pointer to point to one of those, and fetch through it; 41 * the GCC manual doesn't appear to explicitly say that 42 * __attribute__((packed)) causes the compiler to generate unaligned-safe 43 * code, but it apppears to do so. 44 * 45 * We do this in case the compiler can generate code using those 46 * instructions to do an unaligned load and pass stuff to "ntohs()" or 47 * "ntohl()", which might be better than than the code to fetch the 48 * bytes one at a time and assemble them. (That might not be the 49 * case on a little-endian platform, such as DEC's MIPS machines and 50 * Alpha machines, where "ntohs()" and "ntohl()" might not be done 51 * inline.) 52 * 53 * We do this only for specific architectures because, for example, 54 * at least some versions of GCC, when compiling for 64-bit SPARC, 55 * generate code that assumes alignment if we do this. 56 * 57 * XXX - add other architectures and compilers as possible and 58 * appropriate. 59 * 60 * HP's C compiler, indicated by __HP_cc being defined, supports 61 * "#pragma unaligned N" in version A.05.50 and later, where "N" 62 * specifies a number of bytes at which the typedef on the next 63 * line is aligned, e.g. 64 * 65 * #pragma unalign 1 66 * typedef uint16_t unaligned_uint16_t; 67 * 68 * to define unaligned_uint16_t as a 16-bit unaligned data type. 69 * This could be presumably used, in sufficiently recent versions of 70 * the compiler, with macros similar to those below. This would be 71 * useful only if that compiler could generate better code for PA-RISC 72 * or Itanium than would be generated by a bunch of shifts-and-ORs. 73 * 74 * DEC C, indicated by __DECC being defined, has, at least on Alpha, 75 * an __unaligned qualifier that can be applied to pointers to get the 76 * compiler to generate code that does unaligned loads and stores when 77 * dereferencing the pointer in question. 78 * 79 * XXX - what if the native C compiler doesn't support 80 * __attribute__((packed))? How can we get it to generate unaligned 81 * accesses for *specific* items? 82 */ 83 typedef struct { 84 uint16_t val; 85 } __attribute__((packed)) unaligned_uint16_t; 86 87 typedef struct { 88 uint32_t val; 89 } __attribute__((packed)) unaligned_uint32_t; 90 91 static inline uint16_t 92 EXTRACT_16BITS(const void *p) 93 { 94 return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val)); 95 } 96 97 static inline uint32_t 98 EXTRACT_32BITS(const void *p) 99 { 100 return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val)); 101 } 102 103 static inline uint64_t 104 EXTRACT_64BITS(const void *p) 105 { 106 return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \ 107 ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0)); 108 } 109 110 #else /* have to do it a byte at a time */ 111 /* 112 * This isn't a GCC-compatible compiler, we don't have __attribute__, 113 * or we do but we don't know of any better way with this instruction 114 * set to do unaligned loads, so do unaligned loads of big-endian 115 * quantities the hard way - fetch the bytes one at a time and 116 * assemble them. 117 */ 118 #define EXTRACT_16BITS(p) \ 119 ((uint16_t)((uint16_t)*((const uint8_t *)(p) + 0) << 8 | \ 120 (uint16_t)*((const uint8_t *)(p) + 1))) 121 #define EXTRACT_32BITS(p) \ 122 ((uint32_t)((uint32_t)*((const uint8_t *)(p) + 0) << 24 | \ 123 (uint32_t)*((const uint8_t *)(p) + 1) << 16 | \ 124 (uint32_t)*((const uint8_t *)(p) + 2) << 8 | \ 125 (uint32_t)*((const uint8_t *)(p) + 3))) 126 #define EXTRACT_64BITS(p) \ 127 ((uint64_t)((uint64_t)*((const uint8_t *)(p) + 0) << 56 | \ 128 (uint64_t)*((const uint8_t *)(p) + 1) << 48 | \ 129 (uint64_t)*((const uint8_t *)(p) + 2) << 40 | \ 130 (uint64_t)*((const uint8_t *)(p) + 3) << 32 | \ 131 (uint64_t)*((const uint8_t *)(p) + 4) << 24 | \ 132 (uint64_t)*((const uint8_t *)(p) + 5) << 16 | \ 133 (uint64_t)*((const uint8_t *)(p) + 6) << 8 | \ 134 (uint64_t)*((const uint8_t *)(p) + 7))) 135 #endif /* must special-case unaligned accesses */ 136 #else /* LBL_ALIGN */ 137 /* 138 * The processor natively handles unaligned loads, so we can just 139 * cast the pointer and fetch through it. 140 */ 141 static inline uint16_t 142 EXTRACT_16BITS(const void *p) 143 { 144 return ((uint16_t)ntohs(*(const uint16_t *)(p))); 145 } 146 147 static inline uint32_t 148 EXTRACT_32BITS(const void *p) 149 { 150 return ((uint32_t)ntohl(*(const uint32_t *)(p))); 151 } 152 153 static inline uint64_t 154 EXTRACT_64BITS(const void *p) 155 { 156 return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \ 157 ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0)); 158 159 } 160 161 #endif /* LBL_ALIGN */ 162 163 #define EXTRACT_24BITS(p) \ 164 ((uint32_t)((uint32_t)*((const uint8_t *)(p) + 0) << 16 | \ 165 (uint32_t)*((const uint8_t *)(p) + 1) << 8 | \ 166 (uint32_t)*((const uint8_t *)(p) + 2))) 167 168 #define EXTRACT_40BITS(p) \ 169 ((uint64_t)((uint64_t)*((const uint8_t *)(p) + 0) << 32 | \ 170 (uint64_t)*((const uint8_t *)(p) + 1) << 24 | \ 171 (uint64_t)*((const uint8_t *)(p) + 2) << 16 | \ 172 (uint64_t)*((const uint8_t *)(p) + 3) << 8 | \ 173 (uint64_t)*((const uint8_t *)(p) + 4))) 174 175 #define EXTRACT_48BITS(p) \ 176 ((uint64_t)((uint64_t)*((const uint8_t *)(p) + 0) << 40 | \ 177 (uint64_t)*((const uint8_t *)(p) + 1) << 32 | \ 178 (uint64_t)*((const uint8_t *)(p) + 2) << 24 | \ 179 (uint64_t)*((const uint8_t *)(p) + 3) << 16 | \ 180 (uint64_t)*((const uint8_t *)(p) + 4) << 8 | \ 181 (uint64_t)*((const uint8_t *)(p) + 5))) 182 183 #define EXTRACT_56BITS(p) \ 184 ((uint64_t)((uint64_t)*((const uint8_t *)(p) + 0) << 48 | \ 185 (uint64_t)*((const uint8_t *)(p) + 1) << 40 | \ 186 (uint64_t)*((const uint8_t *)(p) + 2) << 32 | \ 187 (uint64_t)*((const uint8_t *)(p) + 3) << 24 | \ 188 (uint64_t)*((const uint8_t *)(p) + 4) << 16 | \ 189 (uint64_t)*((const uint8_t *)(p) + 5) << 8 | \ 190 (uint64_t)*((const uint8_t *)(p) + 6))) 191 192 /* 193 * Macros to extract possibly-unaligned little-endian integral values. 194 * XXX - do loads on little-endian machines that support unaligned loads? 195 */ 196 #define EXTRACT_LE_8BITS(p) (*(p)) 197 #define EXTRACT_LE_16BITS(p) \ 198 ((uint16_t)((uint16_t)*((const uint8_t *)(p) + 1) << 8 | \ 199 (uint16_t)*((const uint8_t *)(p) + 0))) 200 #define EXTRACT_LE_32BITS(p) \ 201 ((uint32_t)((uint32_t)*((const uint8_t *)(p) + 3) << 24 | \ 202 (uint32_t)*((const uint8_t *)(p) + 2) << 16 | \ 203 (uint32_t)*((const uint8_t *)(p) + 1) << 8 | \ 204 (uint32_t)*((const uint8_t *)(p) + 0))) 205 #define EXTRACT_LE_24BITS(p) \ 206 ((uint32_t)((uint32_t)*((const uint8_t *)(p) + 2) << 16 | \ 207 (uint32_t)*((const uint8_t *)(p) + 1) << 8 | \ 208 (uint32_t)*((const uint8_t *)(p) + 0))) 209 #define EXTRACT_LE_64BITS(p) \ 210 ((uint64_t)((uint64_t)*((const uint8_t *)(p) + 7) << 56 | \ 211 (uint64_t)*((const uint8_t *)(p) + 6) << 48 | \ 212 (uint64_t)*((const uint8_t *)(p) + 5) << 40 | \ 213 (uint64_t)*((const uint8_t *)(p) + 4) << 32 | \ 214 (uint64_t)*((const uint8_t *)(p) + 3) << 24 | \ 215 (uint64_t)*((const uint8_t *)(p) + 2) << 16 | \ 216 (uint64_t)*((const uint8_t *)(p) + 1) << 8 | \ 217 (uint64_t)*((const uint8_t *)(p) + 0))) 218