1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * based in part on anv driver which is: 5bf215546Sopenharmony_ci * Copyright © 2016 Intel Corporation 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 8bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 9bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 10bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 12bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 15bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 16bf215546Sopenharmony_ci * Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24bf215546Sopenharmony_ci * SOFTWARE. 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#ifndef PVR_PACKET_HELPERS_H 28bf215546Sopenharmony_ci#define PVR_PACKET_HELPERS_H 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include <assert.h> 31bf215546Sopenharmony_ci#include <math.h> 32bf215546Sopenharmony_ci#include <stdbool.h> 33bf215546Sopenharmony_ci#include <stdint.h> 34bf215546Sopenharmony_ci#include <stdio.h> 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#ifndef __pvr_validate_value 37bf215546Sopenharmony_ci# define __pvr_validate_value(x) 38bf215546Sopenharmony_ci#endif 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#ifdef NDEBUG 41bf215546Sopenharmony_ci# define NDEBUG_UNUSED __attribute__((unused)) 42bf215546Sopenharmony_ci#else 43bf215546Sopenharmony_ci# define NDEBUG_UNUSED 44bf215546Sopenharmony_ci#endif 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#ifndef __pvr_address_type 47bf215546Sopenharmony_ci# error #define __pvr_address_type before including this file 48bf215546Sopenharmony_ci#endif 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#ifndef __pvr_get_address 51bf215546Sopenharmony_ci# error #define __pvr_get_address before including this file 52bf215546Sopenharmony_ci#endif 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci#ifndef __pvr_make_address 55bf215546Sopenharmony_ci# error #define __pvr_make_address before including this file 56bf215546Sopenharmony_ci#endif 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ciunion __pvr_value { 59bf215546Sopenharmony_ci float f; 60bf215546Sopenharmony_ci uint32_t dw; 61bf215546Sopenharmony_ci}; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t __pvr_mbo(uint32_t start, 64bf215546Sopenharmony_ci uint32_t end) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci return (~0ull >> (64 - (end - start + 1))) << start; 67bf215546Sopenharmony_ci} 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 70bf215546Sopenharmony_ci__pvr_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci __pvr_validate_value(v); 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci#ifndef NDEBUG 75bf215546Sopenharmony_ci const int width = end - start + 1; 76bf215546Sopenharmony_ci if (width < 64) { 77bf215546Sopenharmony_ci const uint64_t max = (1ull << width) - 1; 78bf215546Sopenharmony_ci assert(v <= max); 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci#endif 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci return v << start; 83bf215546Sopenharmony_ci} 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 86bf215546Sopenharmony_ci__pvr_uint_unpack(uint64_t packed, uint32_t start, uint32_t end) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci const int width = end - start + 1; 89bf215546Sopenharmony_ci const uint64_t mask = ~0ull >> (64 - width); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci return (packed >> start) & mask; 92bf215546Sopenharmony_ci} 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 95bf215546Sopenharmony_ci__pvr_sint(int64_t v, uint32_t start, uint32_t end) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci const int width = end - start + 1; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci __pvr_validate_value(v); 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci#ifndef NDEBUG 102bf215546Sopenharmony_ci if (width < 64) { 103bf215546Sopenharmony_ci const int64_t max = (1ll << (width - 1)) - 1; 104bf215546Sopenharmony_ci const int64_t min = -(1ll << (width - 1)); 105bf215546Sopenharmony_ci assert(min <= v && v <= max); 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci#endif 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci const uint64_t mask = ~0ull >> (64 - width); 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci return (v & mask) << start; 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) int64_t 115bf215546Sopenharmony_ci__pvr_sint_unpack(uint64_t packed, uint32_t start, uint32_t end) 116bf215546Sopenharmony_ci{ 117bf215546Sopenharmony_ci const int width = end - start + 1; 118bf215546Sopenharmony_ci const uint64_t mask = ~0ull >> (64 - width); 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci return (int64_t)((packed >> start) & mask); 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 124bf215546Sopenharmony_ci__pvr_offset(uint64_t v, 125bf215546Sopenharmony_ci NDEBUG_UNUSED uint32_t start, 126bf215546Sopenharmony_ci NDEBUG_UNUSED uint32_t end) 127bf215546Sopenharmony_ci{ 128bf215546Sopenharmony_ci __pvr_validate_value(v); 129bf215546Sopenharmony_ci#ifndef NDEBUG 130bf215546Sopenharmony_ci uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci assert((v & ~mask) == 0); 133bf215546Sopenharmony_ci#endif 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci return v; 136bf215546Sopenharmony_ci} 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 139bf215546Sopenharmony_ci__pvr_offset_unpack(uint64_t packed, 140bf215546Sopenharmony_ci NDEBUG_UNUSED uint32_t start, 141bf215546Sopenharmony_ci NDEBUG_UNUSED uint32_t end) 142bf215546Sopenharmony_ci{ 143bf215546Sopenharmony_ci#ifndef NDEBUG 144bf215546Sopenharmony_ci uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci assert((packed & ~mask) == 0); 147bf215546Sopenharmony_ci#endif 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci return packed; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 153bf215546Sopenharmony_ci__pvr_address(__pvr_address_type address, 154bf215546Sopenharmony_ci uint32_t shift, 155bf215546Sopenharmony_ci uint32_t start, 156bf215546Sopenharmony_ci uint32_t end) 157bf215546Sopenharmony_ci{ 158bf215546Sopenharmony_ci uint64_t addr_u64 = __pvr_get_address(address); 159bf215546Sopenharmony_ci uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci return ((addr_u64 >> shift) << start) & mask; 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) __pvr_address_type 165bf215546Sopenharmony_ci__pvr_address_unpack(uint64_t packed, 166bf215546Sopenharmony_ci uint32_t shift, 167bf215546Sopenharmony_ci uint32_t start, 168bf215546Sopenharmony_ci uint32_t end) 169bf215546Sopenharmony_ci{ 170bf215546Sopenharmony_ci uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start; 171bf215546Sopenharmony_ci uint64_t addr_u64 = ((packed & mask) >> start) << shift; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci return __pvr_make_address(addr_u64); 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint32_t __pvr_float(float v) 177bf215546Sopenharmony_ci{ 178bf215546Sopenharmony_ci __pvr_validate_value(v); 179bf215546Sopenharmony_ci return ((union __pvr_value){ .f = (v) }).dw; 180bf215546Sopenharmony_ci} 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) float 183bf215546Sopenharmony_ci__pvr_float_unpack(uint32_t packed) 184bf215546Sopenharmony_ci{ 185bf215546Sopenharmony_ci return ((union __pvr_value){ .dw = (packed) }).f; 186bf215546Sopenharmony_ci} 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 189bf215546Sopenharmony_ci__pvr_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci __pvr_validate_value(v); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci const float factor = (1 << fract_bits); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci#ifndef NDEBUG 196bf215546Sopenharmony_ci const float max = ((1 << (end - start)) - 1) / factor; 197bf215546Sopenharmony_ci const float min = -(1 << (end - start)) / factor; 198bf215546Sopenharmony_ci assert(min <= v && v <= max); 199bf215546Sopenharmony_ci#endif 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci const int64_t int_val = llroundf(v * factor); 202bf215546Sopenharmony_ci const uint64_t mask = ~0ull >> (64 - (end - start + 1)); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci return (int_val & mask) << start; 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_cistatic inline __attribute__((always_inline)) uint64_t 208bf215546Sopenharmony_ci__pvr_ufixed(float v, 209bf215546Sopenharmony_ci uint32_t start, 210bf215546Sopenharmony_ci NDEBUG_UNUSED uint32_t end, 211bf215546Sopenharmony_ci uint32_t fract_bits) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci __pvr_validate_value(v); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci const float factor = (1 << fract_bits); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci#ifndef NDEBUG 218bf215546Sopenharmony_ci const float max = ((1 << (end - start + 1)) - 1) / factor; 219bf215546Sopenharmony_ci const float min = 0.0f; 220bf215546Sopenharmony_ci assert(min <= v && v <= max); 221bf215546Sopenharmony_ci#endif 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci const uint64_t uint_val = llroundf(v * factor); 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci return uint_val << start; 226bf215546Sopenharmony_ci} 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci#undef NDEBUG_UNUSED 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci#endif /* PVR_PACKET_HELPERS_H */ 231