/* * Copyright (C) 2016 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include <stdio.h> #include <stdint.h> #include <stdbool.h> #include <assert.h> #include <math.h> #ifdef HAVE_VALGRIND #include <valgrind.h> #include <memcheck.h> #define VG(x) x #define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x)) #else #define VG(x) #endif #ifndef __gen_validate_value #define __gen_validate_value(x) #endif /* #ifndef __gen_address_type #error #define __gen_address_type before including this file #endif #ifndef __gen_user_data #error #define __gen_combine_address before including this file #endif */ union __gen_value { float f; uint32_t dw; }; static inline uint64_t __gen_mbo(uint32_t start, uint32_t end) { return (~0ull >> (64 - (end - start + 1))) << start; } static inline uint64_t __gen_uint(uint64_t v, uint32_t start, uint32_t end) { __gen_validate_value(v); #ifndef NDEBUG const int width = end - start + 1; if (width < 64) { const uint64_t max = (1ull << width) - 1; assert(v <= max); } #endif return v << start; } static inline uint64_t __gen_sint(int64_t v, uint32_t start, uint32_t end) { const int width = end - start + 1; __gen_validate_value(v); #ifndef NDEBUG if (width < 64) { const int64_t max = (1ll << (width - 1)) - 1; const int64_t min = -(1ll << (width - 1)); assert(min <= v && v <= max); } #endif const uint64_t mask = ~0ull >> (64 - width); return (v & mask) << start; } static inline uint64_t __gen_offset(uint64_t v, uint32_t start, uint32_t end) { __gen_validate_value(v); #ifndef NDEBUG uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; assert((v & ~mask) == 0); #endif return v; } static inline uint32_t __gen_float(float v) { __gen_validate_value(v); return ((union __gen_value) { .f = (v) }).dw; } static inline uint64_t __gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) { __gen_validate_value(v); const float factor = (1 << fract_bits); #ifndef NDEBUG const float max = ((1 << (end - start)) - 1) / factor; const float min = -(1 << (end - start)) / factor; assert(min <= v && v <= max); #endif const int64_t int_val = llroundf(v * factor); const uint64_t mask = ~0ull >> (64 - (end - start + 1)); return (int_val & mask) << start; } static inline uint64_t __gen_ufixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) { __gen_validate_value(v); const float factor = (1 << fract_bits); #ifndef NDEBUG const float max = ((1 << (end - start + 1)) - 1) / factor; const float min = 0.0f; assert(min <= v && v <= max); #endif const uint64_t uint_val = llroundf(v * factor); return uint_val << start; } static inline uint64_t __gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end) { uint64_t val = 0; const int width = end - start + 1; const uint32_t mask = (width == 32 ? ~0 : (1 << width) - 1 ); for (int byte = start / 8; byte <= end / 8; byte++) { val |= cl[byte] << ((byte - start / 8) * 8); } return (val >> (start % 8)) & mask; } static inline uint64_t __gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end) { int size = end - start + 1; int64_t val = __gen_unpack_uint(cl, start, end); /* Get the sign bit extended. */ return (val << (64 - size)) >> (64 - size); } static inline float __gen_unpack_sfixed(const uint8_t *restrict cl, uint32_t start, uint32_t end, uint32_t fractional_size) { int32_t bits = __gen_unpack_sint(cl, start, end); return (float)bits / (1 << fractional_size); } static inline float __gen_unpack_ufixed(const uint8_t *restrict cl, uint32_t start, uint32_t end, uint32_t fractional_size) { int32_t bits = __gen_unpack_uint(cl, start, end); return (float)bits / (1 << fractional_size); } static inline float __gen_unpack_float(const uint8_t *restrict cl, uint32_t start, uint32_t end) { assert(start % 8 == 0); assert(end - start == 31); struct PACKED { float f; } *f = (void *)(cl + (start / 8)); return f->f; }