1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * 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 THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include <assert.h> 25#include <stdarg.h> 26#include <stdbool.h> 27#include <stddef.h> 28#include <stdint.h> 29 30#include "rogue_encoders.h" 31#include "rogue_util.h" 32#include "util/bitscan.h" 33 34/** 35 * \brief Passes the input value through unchanged. 36 * 37 * \param[in] value Pointer to the destination value. 38 * \param[in] inputs Number of inputs provided. 39 * \param[in] ... Input value(s). 40 * \return true if encoding was successful. 41 */ 42bool rogue_encoder_pass(uint64_t *value, size_t inputs, ...) 43{ 44 va_list args; 45 46 assert(inputs == 1); 47 48 va_start(args, inputs); 49 *value = va_arg(args, uint64_t); 50 va_end(args); 51 52 return true; 53} 54 55/** 56 * \brief Encoder for DRC values. 57 * 58 * \sa #rogue_encoder_pass() 59 * 60 * \param[in] value Pointer to the destination value. 61 * \param[in] inputs Number of inputs provided. 62 * \param[in] ... Input value(s). 63 * \return true if encoding was successful. 64 */ 65bool rogue_encoder_drc(uint64_t *value, size_t inputs, ...) 66 __attribute__((alias("rogue_encoder_pass"))); 67 68/** 69 * \brief Encoder for immediate values. 70 * 71 * \sa #rogue_encoder_pass() 72 * 73 * \param[in] value Pointer to the destination value. 74 * \param[in] inputs Number of inputs provided. 75 * \param[in] ... Input value(s). 76 * \return true if encoding was successful. 77 */ 78bool rogue_encoder_imm(uint64_t *value, size_t inputs, ...) 79 __attribute__((alias("rogue_encoder_pass"))); 80 81/** 82 * \brief Encodes input ranges {1..15 -> 1-15} and {16 -> 0}. 83 * 84 * The input should be in the range 1-16; the function represents 1-15 normally 85 * and represents 16 by 0. 86 * 87 * \param[in] value Pointer to the destination value. 88 * \param[in] inputs Number of inputs provided. 89 * \param[in] ... Input value(s). 90 * \return true if encoding was successful. 91 */ 92bool rogue_encoder_ls_1_16(uint64_t *value, size_t inputs, ...) 93{ 94 va_list args; 95 uint64_t input; 96 97 assert(inputs == 1); 98 99 va_start(args, inputs); 100 input = va_arg(args, uint64_t); 101 va_end(args); 102 103 /* Validate the input range. */ 104 if (!input || input > 16) { 105 *value = UINT64_MAX; 106 return false; 107 } 108 109 *value = input % 16; 110 111 return true; 112} 113 114/** 115 * \brief Encodes registers according to the number of bits needed to specify 116 * the bank number and register number. 117 * 118 * \param[in] value Pointer to the destination value. 119 * \param[in] bank_bits The number of bits used to represent the register bank. 120 * \param[in] bank the register bank 121 * \param[in] num_bits The number of bits used to represent the register number. 122 * \param[in] num The register number. 123 * \return true if encoding was successful. 124 */ 125static bool rogue_encoder_reg(uint64_t *value, 126 size_t bank_bits, 127 size_t bank, 128 size_t num_bits, 129 size_t num) 130{ 131 /* Verify "num" fits in "num_bits" and "bank" fits in "bank_bits". */ 132 assert(util_last_bit64(num) <= num_bits); 133 assert(util_last_bit64(bank) <= bank_bits); 134 135 *value = num; 136 *value |= (bank << num_bits); 137 138 return true; 139} 140 141/** 142 * \brief Macro to define the rogue_encoder_reg variants. 143 */ 144#define ROGUE_ENCODER_REG_VARIANT(bank_bits, num_bits) \ 145 bool rogue_encoder_reg_##bank_bits##_##num_bits(uint64_t *value, \ 146 size_t inputs, \ 147 ...) \ 148 { \ 149 va_list args; \ 150 size_t bank; \ 151 size_t num; \ 152 assert(inputs == 2); \ 153 va_start(args, inputs); \ 154 bank = va_arg(args, size_t); \ 155 num = va_arg(args, size_t); \ 156 va_end(args); \ 157 return rogue_encoder_reg(value, bank_bits, bank, num_bits, num); \ 158 } 159 160ROGUE_ENCODER_REG_VARIANT(2, 8) 161ROGUE_ENCODER_REG_VARIANT(3, 8) 162ROGUE_ENCODER_REG_VARIANT(3, 11) 163 164#undef ROGUE_ENCODER_REG_VARIANT 165