1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 9bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <inttypes.h> 26bf215546Sopenharmony_ci#include <stdbool.h> 27bf215546Sopenharmony_ci#include <stddef.h> 28bf215546Sopenharmony_ci#include <stdint.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "rogue_util.h" 31bf215546Sopenharmony_ci#include "util/macros.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci/** 34bf215546Sopenharmony_ci * \file rogue_util.c 35bf215546Sopenharmony_ci * 36bf215546Sopenharmony_ci * \brief Contains compiler utility and helper functions. 37bf215546Sopenharmony_ci */ 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci/** 40bf215546Sopenharmony_ci * \brief Splits and distributes value "source" across "dest_bytes" according to 41bf215546Sopenharmony_ci * the ranges specified (from MSB to LSB). 42bf215546Sopenharmony_ci * 43bf215546Sopenharmony_ci * \param[in] source The source value to be distributed. 44bf215546Sopenharmony_ci * \param[in] rangelist The rangelist describing how to distribute "source". 45bf215546Sopenharmony_ci * \param[in] dest_size The size of the destination in bytes. 46bf215546Sopenharmony_ci * \param[in] dest_bytes The destination byte array. 47bf215546Sopenharmony_ci * \return false if invalid inputs were provided, else true. 48bf215546Sopenharmony_ci */ 49bf215546Sopenharmony_cibool rogue_distribute_value(uint64_t source, 50bf215546Sopenharmony_ci const struct rogue_rangelist *rangelist, 51bf215546Sopenharmony_ci size_t dest_size, 52bf215546Sopenharmony_ci uint8_t dest_bytes[dest_size]) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci size_t total_bits_left = 0U; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci /* Check that "value" is actually representable in "total_bits" bits. */ 57bf215546Sopenharmony_ci total_bits_left = rogue_rangelist_bits(rangelist); 58bf215546Sopenharmony_ci assert(util_last_bit64(source) <= total_bits_left && 59bf215546Sopenharmony_ci "Value cannot be represented."); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci /* Iterate over each range. */ 62bf215546Sopenharmony_ci for (size_t u = 0U; u < rangelist->num_ranges; ++u) { 63bf215546Sopenharmony_ci struct rogue_bitrange *range = &rangelist->ranges[u]; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci size_t dest_bit = range->start; 66bf215546Sopenharmony_ci size_t bits_left = range->num; 67bf215546Sopenharmony_ci size_t bytes_covered = rogue_bytes_spilled(range) + 1; 68bf215546Sopenharmony_ci size_t base_byte = rogue_byte_index(range, dest_size); 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci /* Iterate over each byte covered by the current range. */ 71bf215546Sopenharmony_ci for (size_t b = 0U; b < bytes_covered; ++b) { 72bf215546Sopenharmony_ci size_t max_bits = rogue_max_bits(dest_bit); 73bf215546Sopenharmony_ci size_t bits_to_place = MIN2(bits_left, max_bits); 74bf215546Sopenharmony_ci size_t dest_byte_bit = dest_bit % 8; 75bf215546Sopenharmony_ci size_t source_bit = total_bits_left - 1; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci /* Mask and shuffle the source value so that it'll fit into the 78bf215546Sopenharmony_ci * correct place in the destination byte: 79bf215546Sopenharmony_ci */ 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci /* Extract bits. */ 82bf215546Sopenharmony_ci uint64_t value_masked = 83bf215546Sopenharmony_ci (source & BITMASK64_N(source_bit, bits_to_place)); 84bf215546Sopenharmony_ci /* Shift all the way right. */ 85bf215546Sopenharmony_ci value_masked >>= (1 + source_bit - bits_to_place); 86bf215546Sopenharmony_ci /* Shift left to the correct position. */ 87bf215546Sopenharmony_ci value_masked <<= (1 + dest_byte_bit - bits_to_place); 88bf215546Sopenharmony_ci /* Place value into byte. */ 89bf215546Sopenharmony_ci dest_bytes[base_byte + b] |= (value_masked & 0xff); 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci dest_bit -= max_bits; 92bf215546Sopenharmony_ci bits_left -= bits_to_place; 93bf215546Sopenharmony_ci total_bits_left -= bits_to_place; 94bf215546Sopenharmony_ci } 95bf215546Sopenharmony_ci } 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci return true; 98bf215546Sopenharmony_ci} 99