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#ifndef MESA_V3D_PACKET_HELPERS_H
25#define MESA_V3D_PACKET_HELPERS_H
26
27#include <stdio.h>
28#include <stdint.h>
29#include <stdbool.h>
30#include <assert.h>
31#include <math.h>
32#include "util/u_math.h"
33
34#ifdef HAVE_VALGRIND
35#include <valgrind.h>
36#include <memcheck.h>
37#define VG(x) x
38#ifndef NDEBUG
39#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
40#endif
41#else
42#define VG(x) ((void)0)
43#endif
44
45#ifndef __gen_validate_value
46#define __gen_validate_value(x)
47#endif
48/*
49#ifndef __gen_address_type
50#error #define __gen_address_type before including this file
51#endif
52
53#ifndef __gen_user_data
54#error #define __gen_combine_address before including this file
55#endif
56*/
57union __gen_value {
58   float f;
59   uint32_t dw;
60};
61
62static inline uint64_t
63__gen_mbo(uint32_t start, uint32_t end)
64{
65   return (~0ull >> (64 - (end - start + 1))) << start;
66}
67
68static inline uint64_t
69__gen_uint(uint64_t v, uint32_t start, uint32_t end)
70{
71   __gen_validate_value(v);
72
73#ifndef NDEBUG
74   const int width = end - start + 1;
75   if (width < 64) {
76      const uint64_t max = (1ull << width) - 1;
77      assert(v <= max);
78   }
79#endif
80
81   return v << start;
82}
83
84static inline uint64_t
85__gen_sint(int64_t v, uint32_t start, uint32_t end)
86{
87   const int width = end - start + 1;
88
89   __gen_validate_value(v);
90
91#ifndef NDEBUG
92   if (width < 64) {
93      const int64_t max = (1ll << (width - 1)) - 1;
94      const int64_t min = -(1ll << (width - 1));
95      assert(min <= v && v <= max);
96   }
97#endif
98
99   const uint64_t mask = ~0ull >> (64 - width);
100
101   return (v & mask) << start;
102}
103
104static inline uint64_t
105__gen_offset(uint64_t v, uint32_t start, uint32_t end)
106{
107   __gen_validate_value(v);
108#ifndef NDEBUG
109   uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start;
110
111   assert((v & ~mask) == 0);
112#endif
113
114   return v;
115}
116
117static inline uint32_t
118__gen_float(float v)
119{
120   __gen_validate_value(v);
121   return ((union __gen_value) { .f = (v) }).dw;
122}
123
124static inline uint64_t
125__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
126{
127   __gen_validate_value(v);
128
129   const float factor = (1 << fract_bits);
130
131#ifndef NDEBUG
132   const float max = ((1 << (end - start)) - 1) / factor;
133   const float min = -(1 << (end - start)) / factor;
134   assert(min <= v && v <= max);
135#endif
136
137   const int64_t int_val = llroundf(v * factor);
138   const uint64_t mask = ~0ull >> (64 - (end - start + 1));
139
140   return (int_val & mask) << start;
141}
142
143static inline uint64_t
144__gen_ufixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
145{
146   __gen_validate_value(v);
147
148   const float factor = (1 << fract_bits);
149
150#ifndef NDEBUG
151   const float max = ((1 << (end - start + 1)) - 1) / factor;
152   const float min = 0.0f;
153   assert(min <= v && v <= max);
154#endif
155
156   const uint64_t uint_val = llroundf(v * factor);
157
158   return uint_val << start;
159}
160
161static inline uint64_t
162__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
163{
164   uint64_t val = 0;
165   const int width = end - start + 1;
166   const uint32_t mask = (width == 32 ? ~0 : (1 << width) - 1 );
167
168   for (uint32_t byte = start / 8; byte <= end / 8; byte++) {
169      val |= cl[byte] << ((byte - start / 8) * 8);
170   }
171
172   return (val >> (start % 8)) & mask;
173}
174
175static inline uint64_t
176__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
177{
178   int size = end - start + 1;
179   int64_t val = __gen_unpack_uint(cl, start, end);
180
181   /* Get the sign bit extended. */
182   return (val << (64 - size)) >> (64 - size);
183}
184
185static inline float
186__gen_unpack_sfixed(const uint8_t *restrict cl, uint32_t start, uint32_t end,
187                    uint32_t fractional_size)
188{
189        int32_t bits = __gen_unpack_sint(cl, start, end);
190        return (float)bits / (1 << fractional_size);
191}
192
193static inline float
194__gen_unpack_ufixed(const uint8_t *restrict cl, uint32_t start, uint32_t end,
195                    uint32_t fractional_size)
196{
197        int32_t bits = __gen_unpack_uint(cl, start, end);
198        return (float)bits / (1 << fractional_size);
199}
200
201static inline float
202__gen_unpack_float(const uint8_t *restrict cl, uint32_t start, uint32_t end)
203{
204   assert(start % 8 == 0);
205   assert(end - start == 31);
206
207   struct PACKED { float f; } *f = (void *)(cl + (start / 8));
208
209   return f->f;
210}
211
212static inline float
213__gen_unpack_f187(const uint8_t *restrict cl, uint32_t start, uint32_t end)
214{
215   assert(end - start == 15);
216   uint32_t bits = __gen_unpack_uint(cl, start, end);
217   return uif(bits << 16);
218}
219
220#endif
221