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