101e04c3fSmrg/*
201e04c3fSmrg * Copyright (C) 2016 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
247ec681f3Smrg#ifndef MESA_V3D_PACKET_HELPERS_H
257ec681f3Smrg#define MESA_V3D_PACKET_HELPERS_H
267ec681f3Smrg
2701e04c3fSmrg#include <stdio.h>
2801e04c3fSmrg#include <stdint.h>
2901e04c3fSmrg#include <stdbool.h>
3001e04c3fSmrg#include <assert.h>
3101e04c3fSmrg#include <math.h>
3201e04c3fSmrg#include "util/u_math.h"
3301e04c3fSmrg
3401e04c3fSmrg#ifdef HAVE_VALGRIND
3501e04c3fSmrg#include <valgrind.h>
3601e04c3fSmrg#include <memcheck.h>
3701e04c3fSmrg#define VG(x) x
3801e04c3fSmrg#ifndef NDEBUG
3901e04c3fSmrg#define __gen_validate_value(x) VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))
4001e04c3fSmrg#endif
4101e04c3fSmrg#else
427ec681f3Smrg#define VG(x) ((void)0)
4301e04c3fSmrg#endif
4401e04c3fSmrg
4501e04c3fSmrg#ifndef __gen_validate_value
4601e04c3fSmrg#define __gen_validate_value(x)
4701e04c3fSmrg#endif
4801e04c3fSmrg/*
4901e04c3fSmrg#ifndef __gen_address_type
5001e04c3fSmrg#error #define __gen_address_type before including this file
5101e04c3fSmrg#endif
5201e04c3fSmrg
5301e04c3fSmrg#ifndef __gen_user_data
5401e04c3fSmrg#error #define __gen_combine_address before including this file
5501e04c3fSmrg#endif
5601e04c3fSmrg*/
5701e04c3fSmrgunion __gen_value {
5801e04c3fSmrg   float f;
5901e04c3fSmrg   uint32_t dw;
6001e04c3fSmrg};
6101e04c3fSmrg
6201e04c3fSmrgstatic inline uint64_t
6301e04c3fSmrg__gen_mbo(uint32_t start, uint32_t end)
6401e04c3fSmrg{
6501e04c3fSmrg   return (~0ull >> (64 - (end - start + 1))) << start;
6601e04c3fSmrg}
6701e04c3fSmrg
6801e04c3fSmrgstatic inline uint64_t
6901e04c3fSmrg__gen_uint(uint64_t v, uint32_t start, uint32_t end)
7001e04c3fSmrg{
7101e04c3fSmrg   __gen_validate_value(v);
7201e04c3fSmrg
7301e04c3fSmrg#ifndef NDEBUG
7401e04c3fSmrg   const int width = end - start + 1;
7501e04c3fSmrg   if (width < 64) {
7601e04c3fSmrg      const uint64_t max = (1ull << width) - 1;
7701e04c3fSmrg      assert(v <= max);
7801e04c3fSmrg   }
7901e04c3fSmrg#endif
8001e04c3fSmrg
8101e04c3fSmrg   return v << start;
8201e04c3fSmrg}
8301e04c3fSmrg
8401e04c3fSmrgstatic inline uint64_t
8501e04c3fSmrg__gen_sint(int64_t v, uint32_t start, uint32_t end)
8601e04c3fSmrg{
8701e04c3fSmrg   const int width = end - start + 1;
8801e04c3fSmrg
8901e04c3fSmrg   __gen_validate_value(v);
9001e04c3fSmrg
9101e04c3fSmrg#ifndef NDEBUG
9201e04c3fSmrg   if (width < 64) {
9301e04c3fSmrg      const int64_t max = (1ll << (width - 1)) - 1;
9401e04c3fSmrg      const int64_t min = -(1ll << (width - 1));
9501e04c3fSmrg      assert(min <= v && v <= max);
9601e04c3fSmrg   }
9701e04c3fSmrg#endif
9801e04c3fSmrg
9901e04c3fSmrg   const uint64_t mask = ~0ull >> (64 - width);
10001e04c3fSmrg
10101e04c3fSmrg   return (v & mask) << start;
10201e04c3fSmrg}
10301e04c3fSmrg
10401e04c3fSmrgstatic inline uint64_t
10501e04c3fSmrg__gen_offset(uint64_t v, uint32_t start, uint32_t end)
10601e04c3fSmrg{
10701e04c3fSmrg   __gen_validate_value(v);
10801e04c3fSmrg#ifndef NDEBUG
10901e04c3fSmrg   uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start;
11001e04c3fSmrg
11101e04c3fSmrg   assert((v & ~mask) == 0);
11201e04c3fSmrg#endif
11301e04c3fSmrg
11401e04c3fSmrg   return v;
11501e04c3fSmrg}
11601e04c3fSmrg
11701e04c3fSmrgstatic inline uint32_t
11801e04c3fSmrg__gen_float(float v)
11901e04c3fSmrg{
12001e04c3fSmrg   __gen_validate_value(v);
12101e04c3fSmrg   return ((union __gen_value) { .f = (v) }).dw;
12201e04c3fSmrg}
12301e04c3fSmrg
12401e04c3fSmrgstatic inline uint64_t
12501e04c3fSmrg__gen_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
12601e04c3fSmrg{
12701e04c3fSmrg   __gen_validate_value(v);
12801e04c3fSmrg
12901e04c3fSmrg   const float factor = (1 << fract_bits);
13001e04c3fSmrg
13101e04c3fSmrg#ifndef NDEBUG
13201e04c3fSmrg   const float max = ((1 << (end - start)) - 1) / factor;
13301e04c3fSmrg   const float min = -(1 << (end - start)) / factor;
13401e04c3fSmrg   assert(min <= v && v <= max);
13501e04c3fSmrg#endif
13601e04c3fSmrg
13701e04c3fSmrg   const int64_t int_val = llroundf(v * factor);
13801e04c3fSmrg   const uint64_t mask = ~0ull >> (64 - (end - start + 1));
13901e04c3fSmrg
14001e04c3fSmrg   return (int_val & mask) << start;
14101e04c3fSmrg}
14201e04c3fSmrg
14301e04c3fSmrgstatic inline uint64_t
14401e04c3fSmrg__gen_ufixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
14501e04c3fSmrg{
14601e04c3fSmrg   __gen_validate_value(v);
14701e04c3fSmrg
14801e04c3fSmrg   const float factor = (1 << fract_bits);
14901e04c3fSmrg
15001e04c3fSmrg#ifndef NDEBUG
15101e04c3fSmrg   const float max = ((1 << (end - start + 1)) - 1) / factor;
15201e04c3fSmrg   const float min = 0.0f;
15301e04c3fSmrg   assert(min <= v && v <= max);
15401e04c3fSmrg#endif
15501e04c3fSmrg
15601e04c3fSmrg   const uint64_t uint_val = llroundf(v * factor);
15701e04c3fSmrg
15801e04c3fSmrg   return uint_val << start;
15901e04c3fSmrg}
16001e04c3fSmrg
16101e04c3fSmrgstatic inline uint64_t
16201e04c3fSmrg__gen_unpack_uint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
16301e04c3fSmrg{
16401e04c3fSmrg   uint64_t val = 0;
16501e04c3fSmrg   const int width = end - start + 1;
16601e04c3fSmrg   const uint32_t mask = (width == 32 ? ~0 : (1 << width) - 1 );
16701e04c3fSmrg
1687ec681f3Smrg   for (uint32_t byte = start / 8; byte <= end / 8; byte++) {
16901e04c3fSmrg      val |= cl[byte] << ((byte - start / 8) * 8);
17001e04c3fSmrg   }
17101e04c3fSmrg
17201e04c3fSmrg   return (val >> (start % 8)) & mask;
17301e04c3fSmrg}
17401e04c3fSmrg
17501e04c3fSmrgstatic inline uint64_t
17601e04c3fSmrg__gen_unpack_sint(const uint8_t *restrict cl, uint32_t start, uint32_t end)
17701e04c3fSmrg{
17801e04c3fSmrg   int size = end - start + 1;
17901e04c3fSmrg   int64_t val = __gen_unpack_uint(cl, start, end);
18001e04c3fSmrg
18101e04c3fSmrg   /* Get the sign bit extended. */
18201e04c3fSmrg   return (val << (64 - size)) >> (64 - size);
18301e04c3fSmrg}
18401e04c3fSmrg
18501e04c3fSmrgstatic inline float
18601e04c3fSmrg__gen_unpack_sfixed(const uint8_t *restrict cl, uint32_t start, uint32_t end,
18701e04c3fSmrg                    uint32_t fractional_size)
18801e04c3fSmrg{
18901e04c3fSmrg        int32_t bits = __gen_unpack_sint(cl, start, end);
19001e04c3fSmrg        return (float)bits / (1 << fractional_size);
19101e04c3fSmrg}
19201e04c3fSmrg
19301e04c3fSmrgstatic inline float
19401e04c3fSmrg__gen_unpack_ufixed(const uint8_t *restrict cl, uint32_t start, uint32_t end,
19501e04c3fSmrg                    uint32_t fractional_size)
19601e04c3fSmrg{
19701e04c3fSmrg        int32_t bits = __gen_unpack_uint(cl, start, end);
19801e04c3fSmrg        return (float)bits / (1 << fractional_size);
19901e04c3fSmrg}
20001e04c3fSmrg
20101e04c3fSmrgstatic inline float
20201e04c3fSmrg__gen_unpack_float(const uint8_t *restrict cl, uint32_t start, uint32_t end)
20301e04c3fSmrg{
20401e04c3fSmrg   assert(start % 8 == 0);
20501e04c3fSmrg   assert(end - start == 31);
20601e04c3fSmrg
20701e04c3fSmrg   struct PACKED { float f; } *f = (void *)(cl + (start / 8));
20801e04c3fSmrg
20901e04c3fSmrg   return f->f;
21001e04c3fSmrg}
21101e04c3fSmrg
21201e04c3fSmrgstatic inline float
21301e04c3fSmrg__gen_unpack_f187(const uint8_t *restrict cl, uint32_t start, uint32_t end)
21401e04c3fSmrg{
21501e04c3fSmrg   assert(end - start == 15);
21601e04c3fSmrg   uint32_t bits = __gen_unpack_uint(cl, start, end);
21701e04c3fSmrg   return uif(bits << 16);
21801e04c3fSmrg}
21901e04c3fSmrg
2207ec681f3Smrg#endif
221