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 <stdbool.h> 25bf215546Sopenharmony_ci#include <stddef.h> 26bf215546Sopenharmony_ci#include <stdint.h> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "rogue_instr.h" 29bf215546Sopenharmony_ci#include "rogue_operand.h" 30bf215546Sopenharmony_ci#include "rogue_util.h" 31bf215546Sopenharmony_ci#include "util/ralloc.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci/** 34bf215546Sopenharmony_ci * \file rogue_instr.c 35bf215546Sopenharmony_ci * 36bf215546Sopenharmony_ci * \brief Contains functions to manipulate Rogue instructions. 37bf215546Sopenharmony_ci */ 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci/* clang-format off */ 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic const size_t instr_operand_count[ROGUE_OP_COUNT] = { 42bf215546Sopenharmony_ci [ROGUE_OP_NOP] = 0, 43bf215546Sopenharmony_ci [ROGUE_OP_END_FRAG] = 0, 44bf215546Sopenharmony_ci [ROGUE_OP_END_VERT] = 0, 45bf215546Sopenharmony_ci [ROGUE_OP_WDF] = 1, 46bf215546Sopenharmony_ci [ROGUE_OP_PIX_ITER_W] = 5, 47bf215546Sopenharmony_ci [ROGUE_OP_MAX] = 3, 48bf215546Sopenharmony_ci [ROGUE_OP_MIN] = 3, 49bf215546Sopenharmony_ci [ROGUE_OP_PACK_U8888] = 2, 50bf215546Sopenharmony_ci [ROGUE_OP_MOV] = 2, 51bf215546Sopenharmony_ci [ROGUE_OP_MOV_IMM] = 2, 52bf215546Sopenharmony_ci [ROGUE_OP_FMA] = 4, 53bf215546Sopenharmony_ci [ROGUE_OP_MUL] = 3, 54bf215546Sopenharmony_ci [ROGUE_OP_VTXOUT] = 2, 55bf215546Sopenharmony_ci}; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci/* clang-format on */ 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci/** 60bf215546Sopenharmony_ci * \brief Returns the number of operands an instruction takes. 61bf215546Sopenharmony_ci * 62bf215546Sopenharmony_ci * \param[in] opcode The instruction opcode. 63bf215546Sopenharmony_ci * \return The number of operands. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_cistatic inline size_t rogue_instr_num_operands(enum rogue_opcode opcode) 66bf215546Sopenharmony_ci{ 67bf215546Sopenharmony_ci ASSERT_OPCODE_RANGE(opcode); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci return instr_operand_count[opcode]; 70bf215546Sopenharmony_ci} 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci/** 73bf215546Sopenharmony_ci * \brief Allocates and sets up a Rogue instruction. 74bf215546Sopenharmony_ci * 75bf215546Sopenharmony_ci * \param[in] mem_ctx The memory context for the instruction. 76bf215546Sopenharmony_ci * \param[in] opcode The instruction opcode. 77bf215546Sopenharmony_ci * \return A rogue_instr* if successful, or NULL if unsuccessful. 78bf215546Sopenharmony_ci */ 79bf215546Sopenharmony_cistruct rogue_instr *rogue_instr_create(void *mem_ctx, enum rogue_opcode opcode) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci struct rogue_instr *instr; 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ci ASSERT_OPCODE_RANGE(opcode); 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci instr = rzalloc_size(mem_ctx, sizeof(*instr)); 86bf215546Sopenharmony_ci if (!instr) 87bf215546Sopenharmony_ci return NULL; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci instr->opcode = opcode; 90bf215546Sopenharmony_ci instr->num_operands = rogue_instr_num_operands(opcode); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci /* Allocate space for operand array. */ 93bf215546Sopenharmony_ci if (instr->num_operands) { 94bf215546Sopenharmony_ci instr->operands = rzalloc_array_size(instr, 95bf215546Sopenharmony_ci sizeof(*instr->operands), 96bf215546Sopenharmony_ci instr->num_operands); 97bf215546Sopenharmony_ci if (!instr->operands) { 98bf215546Sopenharmony_ci ralloc_free(instr); 99bf215546Sopenharmony_ci return NULL; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci return instr; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci/** 107bf215546Sopenharmony_ci * \brief Sets a Rogue instruction flag. 108bf215546Sopenharmony_ci * 109bf215546Sopenharmony_ci * \param[in] instr The instruction. 110bf215546Sopenharmony_ci * \param[in] flag The flag to set. 111bf215546Sopenharmony_ci * \return true if valid, otherwise false. 112bf215546Sopenharmony_ci */ 113bf215546Sopenharmony_cibool rogue_instr_set_flag(struct rogue_instr *instr, enum rogue_instr_flag flag) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci instr->flags = ROH(flag); 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci return true; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci/** 121bf215546Sopenharmony_ci * \brief Sets a Rogue instruction operand to an immediate value. 122bf215546Sopenharmony_ci * 123bf215546Sopenharmony_ci * \param[in] instr The instruction. 124bf215546Sopenharmony_ci * \param[in] index The operand index. 125bf215546Sopenharmony_ci * \param[in] value The value to set. 126bf215546Sopenharmony_ci * \return true if valid, otherwise false. 127bf215546Sopenharmony_ci */ 128bf215546Sopenharmony_cibool rogue_instr_set_operand_imm(struct rogue_instr *instr, 129bf215546Sopenharmony_ci size_t index, 130bf215546Sopenharmony_ci uint64_t value) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci ASSERT_INSTR_OPERAND_INDEX(instr, index); 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci instr->operands[index].type = ROGUE_OPERAND_TYPE_IMMEDIATE; 135bf215546Sopenharmony_ci instr->operands[index].immediate.value = value; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci return true; 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci/** 141bf215546Sopenharmony_ci * \brief Sets a Rogue instruction operand to a DRC number. 142bf215546Sopenharmony_ci * 143bf215546Sopenharmony_ci * \param[in] instr The instruction. 144bf215546Sopenharmony_ci * \param[in] index The operand index. 145bf215546Sopenharmony_ci * \param[in] number The DRC number to set. 146bf215546Sopenharmony_ci * \return true if valid, otherwise false. 147bf215546Sopenharmony_ci */ 148bf215546Sopenharmony_cibool rogue_instr_set_operand_drc(struct rogue_instr *instr, 149bf215546Sopenharmony_ci size_t index, 150bf215546Sopenharmony_ci size_t number) 151bf215546Sopenharmony_ci{ 152bf215546Sopenharmony_ci ASSERT_INSTR_OPERAND_INDEX(instr, index); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci instr->operands[index].type = ROGUE_OPERAND_TYPE_DRC; 155bf215546Sopenharmony_ci instr->operands[index].drc.number = number; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci return true; 158bf215546Sopenharmony_ci} 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci/** 161bf215546Sopenharmony_ci * \brief Sets a Rogue instruction operand to a register. 162bf215546Sopenharmony_ci * 163bf215546Sopenharmony_ci * \param[in] instr The instruction. 164bf215546Sopenharmony_ci * \param[in] index The operand index. 165bf215546Sopenharmony_ci * \param[in] type The register type to set. 166bf215546Sopenharmony_ci * \param[in] number The register number to set. 167bf215546Sopenharmony_ci * \return true if valid, otherwise false. 168bf215546Sopenharmony_ci */ 169bf215546Sopenharmony_cibool rogue_instr_set_operand_reg(struct rogue_instr *instr, 170bf215546Sopenharmony_ci size_t index, 171bf215546Sopenharmony_ci enum rogue_operand_type type, 172bf215546Sopenharmony_ci size_t number) 173bf215546Sopenharmony_ci{ 174bf215546Sopenharmony_ci ASSERT_INSTR_OPERAND_INDEX(instr, index); 175bf215546Sopenharmony_ci ASSERT_OPERAND_REG(type); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci instr->operands[index].type = type; 178bf215546Sopenharmony_ci instr->operands[index].reg.number = number; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci return true; 181bf215546Sopenharmony_ci} 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci/** 184bf215546Sopenharmony_ci * \brief Sets a Rogue instruction operand to a virtual register. 185bf215546Sopenharmony_ci * 186bf215546Sopenharmony_ci * \param[in] instr The instruction. 187bf215546Sopenharmony_ci * \param[in] index The operand index. 188bf215546Sopenharmony_ci * \param[in] number The register number to set. 189bf215546Sopenharmony_ci * \return true if valid, otherwise false. 190bf215546Sopenharmony_ci */ 191bf215546Sopenharmony_cibool rogue_instr_set_operand_vreg(struct rogue_instr *instr, 192bf215546Sopenharmony_ci size_t index, 193bf215546Sopenharmony_ci size_t number) 194bf215546Sopenharmony_ci{ 195bf215546Sopenharmony_ci ASSERT_INSTR_OPERAND_INDEX(instr, index); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci instr->operands[index].type = ROGUE_OPERAND_TYPE_VREG; 198bf215546Sopenharmony_ci instr->operands[index].vreg.number = number; 199bf215546Sopenharmony_ci instr->operands[index].vreg.is_vector = false; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci return true; 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci/** 205bf215546Sopenharmony_ci * \brief Sets a Rogue instruction operand to a virtual register 206bf215546Sopenharmony_ci * that is a vector type. 207bf215546Sopenharmony_ci * 208bf215546Sopenharmony_ci * \param[in] instr The instruction. 209bf215546Sopenharmony_ci * \param[in] index The operand index. 210bf215546Sopenharmony_ci * \param[in] component The vector component. 211bf215546Sopenharmony_ci * \param[in] number The register number to set. 212bf215546Sopenharmony_ci * \return true if valid, otherwise false. 213bf215546Sopenharmony_ci */ 214bf215546Sopenharmony_cibool rogue_instr_set_operand_vreg_vec(struct rogue_instr *instr, 215bf215546Sopenharmony_ci size_t index, 216bf215546Sopenharmony_ci size_t component, 217bf215546Sopenharmony_ci size_t number) 218bf215546Sopenharmony_ci{ 219bf215546Sopenharmony_ci ASSERT_INSTR_OPERAND_INDEX(instr, index); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci instr->operands[index].type = ROGUE_OPERAND_TYPE_VREG; 222bf215546Sopenharmony_ci instr->operands[index].vreg.number = number; 223bf215546Sopenharmony_ci instr->operands[index].vreg.is_vector = true; 224bf215546Sopenharmony_ci instr->operands[index].vreg.component = component; 225bf215546Sopenharmony_ci 226bf215546Sopenharmony_ci return true; 227bf215546Sopenharmony_ci} 228