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