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 */
57 union __gen_value {
58 float f;
59 uint32_t dw;
60 };
61
62 static inline uint64_t
__gen_mbo(uint32_t start,uint32_t end)63 __gen_mbo(uint32_t start, uint32_t end)
64 {
65 return (~0ull >> (64 - (end - start + 1))) << start;
66 }
67
68 static inline uint64_t
__gen_uint(uint64_t v,uint32_t start,uint32_t end)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
84 static inline uint64_t
__gen_sint(int64_t v,uint32_t start,uint32_t end)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
104 static inline uint64_t
__gen_offset(uint64_t v,uint32_t start,uint32_t end)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
117 static inline uint32_t
__gen_float(float v)118 __gen_float(float v)
119 {
120 __gen_validate_value(v);
121 return ((union __gen_value) { .f = (v) }).dw;
122 }
123
124 static inline uint64_t
__gen_sfixed(float v,uint32_t start,uint32_t end,uint32_t fract_bits)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
143 static inline uint64_t
__gen_ufixed(float v,uint32_t start,uint32_t end,uint32_t fract_bits)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
161 static inline uint64_t
__gen_unpack_uint(const uint8_t * restrict cl,uint32_t start,uint32_t end)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
175 static inline uint64_t
__gen_unpack_sint(const uint8_t * restrict cl,uint32_t start,uint32_t end)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
185 static inline float
__gen_unpack_sfixed(const uint8_t * restrict cl,uint32_t start,uint32_t end,uint32_t fractional_size)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
193 static inline float
__gen_unpack_ufixed(const uint8_t * restrict cl,uint32_t start,uint32_t end,uint32_t fractional_size)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
201 static inline float
__gen_unpack_float(const uint8_t * restrict cl,uint32_t start,uint32_t end)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
212 static inline float
__gen_unpack_f187(const uint8_t * restrict cl,uint32_t start,uint32_t end)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