1 /* 2 * Copyright (C) 2016 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #include <stdio.h> 25 #include <stdint.h> 26 #include <stdbool.h> 27 #include <assert.h> 28 #include <math.h> 29 30 #ifdef HAVE_VALGRIND 31 #include <valgrind.h> 32 #include <memcheck.h> 33 #define VG(x) x 34 #define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x)) 35 #else 36 #define VG(x) 37 #endif 38 39 #ifndef __gen_validate_value 40 #define __gen_validate_value(x) 41 #endif 42 /* 43 #ifndef __gen_address_type 44 #error #define __gen_address_type before including this file 45 #endif 46 47 #ifndef __gen_user_data 48 #error #define __gen_combine_address before including this file 49 #endif 50 */ 51 union __gen_value { 52 float f; 53 uint32_t dw; 54 }; 55 56 static inline uint64_t 57 __gen_mbo(uint32_t start, uint32_t end) 58 { 59 return (~0ull >> (64 - (end - start + 1))) << start; 60 } 61 62 static inline uint64_t 63 __gen_uint(uint64_t v, uint32_t start, uint32_t end) 64 { 65 __gen_validate_value(v); 66 67 #ifndef NDEBUG 68 const int width = end - start + 1; 69 if (width < 64) { 70 const uint64_t max = (1ull << width) - 1; 71 assert(v <= max); 72 } 73 #endif 74 75 return v << start; 76 } 77 78 static inline uint64_t 79 __gen_sint(int64_t v, uint32_t start, uint32_t end) 80 { 81 const int width = end - start + 1; 82 83 __gen_validate_value(v); 84 85 #ifndef NDEBUG 86 if (width < 64) { 87 const int64_t max = (1ll << (width - 1)) - 1; 88 const int64_t min = -(1ll << (width - 1)); 89 assert(min <= v && v <= max); 90 } 91 #endif 92 93 const uint64_t mask = ~0ull >> (64 - width); 94 95 return (v & mask) << start; 96 } 97 98 static inline uint64_t 99 __gen_offset(uint64_t v, uint32_t start, uint32_t end) 100 { 101 __gen_validate_value(v); 102 #ifndef NDEBUG 103 uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 104 105 assert((v & ~mask) == 0); 106 #endif 107 108 return v; 109 } 110 111 static inline uint32_t 112 __gen_float(float v) 113 { 114 __gen_validate_value(v); 115 return ((union __gen_value) { .f = (v) }).dw; 116 } 117 118 static inline uint64_t 119 __gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 120 { 121 __gen_validate_value(v); 122 123 const float factor = (1 << fract_bits); 124 125 #ifndef NDEBUG 126 const float max = ((1 << (end - start)) - 1) / factor; 127 const float min = -(1 << (end - start)) / factor; 128 assert(min <= v && v <= max); 129 #endif 130 131 const int64_t int_val = llroundf(v * factor); 132 const uint64_t mask = ~0ull >> (64 - (end - start + 1)); 133 134 return (int_val & mask) << start; 135 } 136 137 static inline uint64_t 138 __gen_ufixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 139 { 140 __gen_validate_value(v); 141 142 const float factor = (1 << fract_bits); 143 144 #ifndef NDEBUG 145 const float max = ((1 << (end - start + 1)) - 1) / factor; 146 const float min = 0.0f; 147 assert(min <= v && v <= max); 148 #endif 149 150 const uint64_t uint_val = llroundf(v * factor); 151 152 return uint_val << start; 153 } 154 155 static inline uint64_t 156 __gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end) 157 { 158 uint64_t val = 0; 159 const int width = end - start + 1; 160 const uint32_t mask = (width == 32 ? ~0 : (1 << width) - 1 ); 161 162 for (int byte = start / 8; byte <= end / 8; byte++) { 163 val |= cl[byte] << ((byte - start / 8) * 8); 164 } 165 166 return (val >> (start % 8)) & mask; 167 } 168 169 static inline uint64_t 170 __gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end) 171 { 172 int size = end - start + 1; 173 int64_t val = __gen_unpack_uint(cl, start, end); 174 175 /* Get the sign bit extended. */ 176 return (val << (64 - size)) >> (64 - size); 177 } 178 179 static inline float 180 __gen_unpack_sfixed(const uint8_t *restrict cl, uint32_t start, uint32_t end, 181 uint32_t fractional_size) 182 { 183 int32_t bits = __gen_unpack_sint(cl, start, end); 184 return (float)bits / (1 << fractional_size); 185 } 186 187 static inline float 188 __gen_unpack_ufixed(const uint8_t *restrict cl, uint32_t start, uint32_t end, 189 uint32_t fractional_size) 190 { 191 int32_t bits = __gen_unpack_uint(cl, start, end); 192 return (float)bits / (1 << fractional_size); 193 } 194 195 static inline float 196 __gen_unpack_float(const uint8_t *restrict cl, uint32_t start, uint32_t end) 197 { 198 assert(start % 8 == 0); 199 assert(end - start == 31); 200 201 struct PACKED { float f; } *f = (void *)(cl + (start / 8)); 202 203 return f->f; 204 } 205 206