intel/eu: Split brw_inst ex_desc accessors for SEND(C) vs. SENDS(C).
[mesa.git] / src / intel / compiler / brw_reg_type.c
1 /*
2 * Copyright © 2017 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is 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
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "brw_reg.h"
25 #include "brw_eu_defines.h"
26 #include "dev/gen_device_info.h"
27
28 #define INVALID (-1)
29
30 enum hw_reg_type {
31 BRW_HW_REG_TYPE_UD = 0,
32 BRW_HW_REG_TYPE_D = 1,
33 BRW_HW_REG_TYPE_UW = 2,
34 BRW_HW_REG_TYPE_W = 3,
35 BRW_HW_REG_TYPE_F = 7,
36 GEN8_HW_REG_TYPE_UQ = 8,
37 GEN8_HW_REG_TYPE_Q = 9,
38
39 BRW_HW_REG_TYPE_UB = 4,
40 BRW_HW_REG_TYPE_B = 5,
41 GEN7_HW_REG_TYPE_DF = 6,
42 GEN8_HW_REG_TYPE_HF = 10,
43
44 GEN11_HW_REG_TYPE_UD = 0,
45 GEN11_HW_REG_TYPE_D = 1,
46 GEN11_HW_REG_TYPE_UW = 2,
47 GEN11_HW_REG_TYPE_W = 3,
48 GEN11_HW_REG_TYPE_UB = 4,
49 GEN11_HW_REG_TYPE_B = 5,
50 GEN11_HW_REG_TYPE_UQ = 6,
51 GEN11_HW_REG_TYPE_Q = 7,
52 GEN11_HW_REG_TYPE_HF = 8,
53 GEN11_HW_REG_TYPE_F = 9,
54 GEN11_HW_REG_TYPE_DF = 10,
55 GEN11_HW_REG_TYPE_NF = 11,
56 };
57
58 enum hw_imm_type {
59 BRW_HW_IMM_TYPE_UD = 0,
60 BRW_HW_IMM_TYPE_D = 1,
61 BRW_HW_IMM_TYPE_UW = 2,
62 BRW_HW_IMM_TYPE_W = 3,
63 BRW_HW_IMM_TYPE_F = 7,
64 GEN8_HW_IMM_TYPE_UQ = 8,
65 GEN8_HW_IMM_TYPE_Q = 9,
66
67 BRW_HW_IMM_TYPE_UV = 4,
68 BRW_HW_IMM_TYPE_VF = 5,
69 BRW_HW_IMM_TYPE_V = 6,
70 GEN8_HW_IMM_TYPE_DF = 10,
71 GEN8_HW_IMM_TYPE_HF = 11,
72
73 GEN11_HW_IMM_TYPE_UD = 0,
74 GEN11_HW_IMM_TYPE_D = 1,
75 GEN11_HW_IMM_TYPE_UW = 2,
76 GEN11_HW_IMM_TYPE_W = 3,
77 GEN11_HW_IMM_TYPE_UV = 4,
78 GEN11_HW_IMM_TYPE_V = 5,
79 GEN11_HW_IMM_TYPE_UQ = 6,
80 GEN11_HW_IMM_TYPE_Q = 7,
81 GEN11_HW_IMM_TYPE_HF = 8,
82 GEN11_HW_IMM_TYPE_F = 9,
83 GEN11_HW_IMM_TYPE_DF = 10,
84 GEN11_HW_IMM_TYPE_VF = 11,
85 };
86
87 static const struct hw_type {
88 enum hw_reg_type reg_type;
89 enum hw_imm_type imm_type;
90 } gen4_hw_type[] = {
91 [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID, INVALID },
92
93 [BRW_REGISTER_TYPE_DF] = { GEN7_HW_REG_TYPE_DF, GEN8_HW_IMM_TYPE_DF },
94 [BRW_REGISTER_TYPE_F] = { BRW_HW_REG_TYPE_F, BRW_HW_IMM_TYPE_F },
95 [BRW_REGISTER_TYPE_HF] = { GEN8_HW_REG_TYPE_HF, GEN8_HW_IMM_TYPE_HF },
96 [BRW_REGISTER_TYPE_VF] = { INVALID, BRW_HW_IMM_TYPE_VF },
97
98 [BRW_REGISTER_TYPE_Q] = { GEN8_HW_REG_TYPE_Q, GEN8_HW_IMM_TYPE_Q },
99 [BRW_REGISTER_TYPE_UQ] = { GEN8_HW_REG_TYPE_UQ, GEN8_HW_IMM_TYPE_UQ },
100 [BRW_REGISTER_TYPE_D] = { BRW_HW_REG_TYPE_D, BRW_HW_IMM_TYPE_D },
101 [BRW_REGISTER_TYPE_UD] = { BRW_HW_REG_TYPE_UD, BRW_HW_IMM_TYPE_UD },
102 [BRW_REGISTER_TYPE_W] = { BRW_HW_REG_TYPE_W, BRW_HW_IMM_TYPE_W },
103 [BRW_REGISTER_TYPE_UW] = { BRW_HW_REG_TYPE_UW, BRW_HW_IMM_TYPE_UW },
104 [BRW_REGISTER_TYPE_B] = { BRW_HW_REG_TYPE_B, INVALID },
105 [BRW_REGISTER_TYPE_UB] = { BRW_HW_REG_TYPE_UB, INVALID },
106 [BRW_REGISTER_TYPE_V] = { INVALID, BRW_HW_IMM_TYPE_V },
107 [BRW_REGISTER_TYPE_UV] = { INVALID, BRW_HW_IMM_TYPE_UV },
108 }, gen11_hw_type[] = {
109 [BRW_REGISTER_TYPE_NF] = { GEN11_HW_REG_TYPE_NF, INVALID },
110 [BRW_REGISTER_TYPE_DF] = { GEN11_HW_REG_TYPE_DF, GEN11_HW_IMM_TYPE_DF },
111 [BRW_REGISTER_TYPE_F] = { GEN11_HW_REG_TYPE_F, GEN11_HW_IMM_TYPE_F },
112 [BRW_REGISTER_TYPE_HF] = { GEN11_HW_REG_TYPE_HF, GEN11_HW_IMM_TYPE_HF },
113 [BRW_REGISTER_TYPE_VF] = { INVALID, GEN11_HW_IMM_TYPE_VF },
114
115 [BRW_REGISTER_TYPE_Q] = { GEN11_HW_REG_TYPE_Q, GEN11_HW_IMM_TYPE_Q },
116 [BRW_REGISTER_TYPE_UQ] = { GEN11_HW_REG_TYPE_UQ, GEN11_HW_IMM_TYPE_UQ },
117 [BRW_REGISTER_TYPE_D] = { GEN11_HW_REG_TYPE_D, GEN11_HW_IMM_TYPE_D },
118 [BRW_REGISTER_TYPE_UD] = { GEN11_HW_REG_TYPE_UD, GEN11_HW_IMM_TYPE_UD },
119 [BRW_REGISTER_TYPE_W] = { GEN11_HW_REG_TYPE_W, GEN11_HW_IMM_TYPE_W },
120 [BRW_REGISTER_TYPE_UW] = { GEN11_HW_REG_TYPE_UW, GEN11_HW_IMM_TYPE_UW },
121 [BRW_REGISTER_TYPE_B] = { GEN11_HW_REG_TYPE_B, INVALID },
122 [BRW_REGISTER_TYPE_UB] = { GEN11_HW_REG_TYPE_UB, INVALID },
123 [BRW_REGISTER_TYPE_V] = { INVALID, GEN11_HW_IMM_TYPE_V },
124 [BRW_REGISTER_TYPE_UV] = { INVALID, GEN11_HW_IMM_TYPE_UV },
125 };
126
127 /* SNB adds 3-src instructions (MAD and LRP) that only operate on floats, so
128 * the types were implied. IVB adds BFE and BFI2 that operate on doublewords
129 * and unsigned doublewords, so a new field is also available in the da3src
130 * struct (part of struct brw_instruction.bits1 in brw_structs.h) to select
131 * dst and shared-src types.
132 *
133 * CNL adds support for 3-src instructions in align1 mode, and with it support
134 * for most register types.
135 */
136 enum hw_3src_reg_type {
137 GEN7_3SRC_TYPE_F = 0,
138 GEN7_3SRC_TYPE_D = 1,
139 GEN7_3SRC_TYPE_UD = 2,
140 GEN7_3SRC_TYPE_DF = 3,
141 GEN8_3SRC_TYPE_HF = 4,
142
143 /** When ExecutionDatatype is 1: @{ */
144 GEN10_ALIGN1_3SRC_REG_TYPE_HF = 0b000,
145 GEN10_ALIGN1_3SRC_REG_TYPE_F = 0b001,
146 GEN10_ALIGN1_3SRC_REG_TYPE_DF = 0b010,
147 GEN11_ALIGN1_3SRC_REG_TYPE_NF = 0b011,
148 /** @} */
149
150 /** When ExecutionDatatype is 0: @{ */
151 GEN10_ALIGN1_3SRC_REG_TYPE_UD = 0b000,
152 GEN10_ALIGN1_3SRC_REG_TYPE_D = 0b001,
153 GEN10_ALIGN1_3SRC_REG_TYPE_UW = 0b010,
154 GEN10_ALIGN1_3SRC_REG_TYPE_W = 0b011,
155 GEN10_ALIGN1_3SRC_REG_TYPE_UB = 0b100,
156 GEN10_ALIGN1_3SRC_REG_TYPE_B = 0b101,
157 /** @} */
158 };
159
160 static const struct hw_3src_type {
161 enum hw_3src_reg_type reg_type;
162 enum gen10_align1_3src_exec_type exec_type;
163 } gen7_hw_3src_type[] = {
164 [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID },
165
166 [BRW_REGISTER_TYPE_F] = { GEN7_3SRC_TYPE_F },
167 [BRW_REGISTER_TYPE_D] = { GEN7_3SRC_TYPE_D },
168 [BRW_REGISTER_TYPE_UD] = { GEN7_3SRC_TYPE_UD },
169 [BRW_REGISTER_TYPE_DF] = { GEN7_3SRC_TYPE_DF },
170 [BRW_REGISTER_TYPE_HF] = { GEN8_3SRC_TYPE_HF },
171 }, gen10_hw_3src_align1_type[] = {
172 #define E(x) BRW_ALIGN1_3SRC_EXEC_TYPE_##x
173 [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID },
174
175 [BRW_REGISTER_TYPE_NF] = { GEN11_ALIGN1_3SRC_REG_TYPE_NF, E(FLOAT) },
176 [BRW_REGISTER_TYPE_DF] = { GEN10_ALIGN1_3SRC_REG_TYPE_DF, E(FLOAT) },
177 [BRW_REGISTER_TYPE_F] = { GEN10_ALIGN1_3SRC_REG_TYPE_F, E(FLOAT) },
178 [BRW_REGISTER_TYPE_HF] = { GEN10_ALIGN1_3SRC_REG_TYPE_HF, E(FLOAT) },
179
180 [BRW_REGISTER_TYPE_D] = { GEN10_ALIGN1_3SRC_REG_TYPE_D, E(INT) },
181 [BRW_REGISTER_TYPE_UD] = { GEN10_ALIGN1_3SRC_REG_TYPE_UD, E(INT) },
182 [BRW_REGISTER_TYPE_W] = { GEN10_ALIGN1_3SRC_REG_TYPE_W, E(INT) },
183 [BRW_REGISTER_TYPE_UW] = { GEN10_ALIGN1_3SRC_REG_TYPE_UW, E(INT) },
184 [BRW_REGISTER_TYPE_B] = { GEN10_ALIGN1_3SRC_REG_TYPE_B, E(INT) },
185 [BRW_REGISTER_TYPE_UB] = { GEN10_ALIGN1_3SRC_REG_TYPE_UB, E(INT) },
186 #undef E
187 };
188
189 /**
190 * Convert a brw_reg_type enumeration value into the hardware representation.
191 *
192 * The hardware encoding may depend on whether the value is an immediate.
193 */
194 unsigned
195 brw_reg_type_to_hw_type(const struct gen_device_info *devinfo,
196 enum brw_reg_file file,
197 enum brw_reg_type type)
198 {
199 const struct hw_type *table;
200
201 if (devinfo->gen >= 11) {
202 assert(type < ARRAY_SIZE(gen11_hw_type));
203 table = gen11_hw_type;
204 } else {
205 assert(type < ARRAY_SIZE(gen4_hw_type));
206 table = gen4_hw_type;
207 }
208
209 assert(devinfo->has_64bit_types || brw_reg_type_to_size(type) < 8 ||
210 type == BRW_REGISTER_TYPE_NF);
211
212 if (file == BRW_IMMEDIATE_VALUE) {
213 assert(table[type].imm_type != (enum hw_imm_type)INVALID);
214 return table[type].imm_type;
215 } else {
216 assert(table[type].reg_type != (enum hw_reg_type)INVALID);
217 return table[type].reg_type;
218 }
219 }
220
221 /**
222 * Convert the hardware representation into a brw_reg_type enumeration value.
223 *
224 * The hardware encoding may depend on whether the value is an immediate.
225 */
226 enum brw_reg_type
227 brw_hw_type_to_reg_type(const struct gen_device_info *devinfo,
228 enum brw_reg_file file, unsigned hw_type)
229 {
230 const struct hw_type *table;
231
232 if (devinfo->gen >= 11) {
233 table = gen11_hw_type;
234 } else {
235 table = gen4_hw_type;
236 }
237
238 if (file == BRW_IMMEDIATE_VALUE) {
239 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
240 if (table[i].imm_type == (enum hw_imm_type)hw_type) {
241 return i;
242 }
243 }
244 } else {
245 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
246 if (table[i].reg_type == (enum hw_reg_type)hw_type) {
247 return i;
248 }
249 }
250 }
251 unreachable("not reached");
252 }
253
254 /**
255 * Convert a brw_reg_type enumeration value into the hardware representation
256 * for a 3-src align16 instruction
257 */
258 unsigned
259 brw_reg_type_to_a16_hw_3src_type(const struct gen_device_info *devinfo,
260 enum brw_reg_type type)
261 {
262 assert(type < ARRAY_SIZE(gen7_hw_3src_type));
263 assert(devinfo->gen >= 8 || type != BRW_REGISTER_TYPE_HF);
264 assert(gen7_hw_3src_type[type].reg_type != (enum hw_3src_reg_type)INVALID);
265 return gen7_hw_3src_type[type].reg_type;
266 }
267
268 /**
269 * Convert a brw_reg_type enumeration value into the hardware representation
270 * for a 3-src align1 instruction
271 */
272 unsigned
273 brw_reg_type_to_a1_hw_3src_type(const struct gen_device_info *devinfo,
274 enum brw_reg_type type)
275 {
276 assert(type < ARRAY_SIZE(gen10_hw_3src_align1_type));
277 assert(gen10_hw_3src_align1_type[type].reg_type != (enum hw_3src_reg_type)INVALID);
278 return gen10_hw_3src_align1_type[type].reg_type;
279 }
280
281 /**
282 * Convert the hardware representation for a 3-src align16 instruction into a
283 * brw_reg_type enumeration value.
284 */
285 enum brw_reg_type
286 brw_a16_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo,
287 unsigned hw_type)
288 {
289 assert(devinfo->gen >= 8 || hw_type != GEN8_3SRC_TYPE_HF);
290 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
291 if (gen7_hw_3src_type[i].reg_type == hw_type) {
292 return i;
293 }
294 }
295 unreachable("not reached");
296 }
297
298 /**
299 * Convert the hardware representation for a 3-src align1 instruction into a
300 * brw_reg_type enumeration value.
301 */
302 enum brw_reg_type
303 brw_a1_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo,
304 unsigned hw_type, unsigned exec_type)
305 {
306 for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) {
307 if (gen10_hw_3src_align1_type[i].reg_type == hw_type &&
308 gen10_hw_3src_align1_type[i].exec_type == exec_type) {
309 return i;
310 }
311 }
312 unreachable("not reached");
313 }
314
315 /**
316 * Return the element size given a register type.
317 */
318 unsigned
319 brw_reg_type_to_size(enum brw_reg_type type)
320 {
321 static const unsigned type_size[] = {
322 [BRW_REGISTER_TYPE_NF] = 8,
323 [BRW_REGISTER_TYPE_DF] = 8,
324 [BRW_REGISTER_TYPE_F] = 4,
325 [BRW_REGISTER_TYPE_HF] = 2,
326 [BRW_REGISTER_TYPE_VF] = 4,
327
328 [BRW_REGISTER_TYPE_Q] = 8,
329 [BRW_REGISTER_TYPE_UQ] = 8,
330 [BRW_REGISTER_TYPE_D] = 4,
331 [BRW_REGISTER_TYPE_UD] = 4,
332 [BRW_REGISTER_TYPE_W] = 2,
333 [BRW_REGISTER_TYPE_UW] = 2,
334 [BRW_REGISTER_TYPE_B] = 1,
335 [BRW_REGISTER_TYPE_UB] = 1,
336 [BRW_REGISTER_TYPE_V] = 2,
337 [BRW_REGISTER_TYPE_UV] = 2,
338 };
339 return type_size[type];
340 }
341
342 /**
343 * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on).
344 *
345 * This is different than reg_encoding from brw_disasm.c in that it operates
346 * on the abstract enum values, rather than the generation-specific encoding.
347 */
348 const char *
349 brw_reg_type_to_letters(enum brw_reg_type type)
350 {
351 static const char letters[][3] = {
352 [BRW_REGISTER_TYPE_NF] = "NF",
353 [BRW_REGISTER_TYPE_DF] = "DF",
354 [BRW_REGISTER_TYPE_F] = "F",
355 [BRW_REGISTER_TYPE_HF] = "HF",
356 [BRW_REGISTER_TYPE_VF] = "VF",
357
358 [BRW_REGISTER_TYPE_Q] = "Q",
359 [BRW_REGISTER_TYPE_UQ] = "UQ",
360 [BRW_REGISTER_TYPE_D] = "D",
361 [BRW_REGISTER_TYPE_UD] = "UD",
362 [BRW_REGISTER_TYPE_W] = "W",
363 [BRW_REGISTER_TYPE_UW] = "UW",
364 [BRW_REGISTER_TYPE_B] = "B",
365 [BRW_REGISTER_TYPE_UB] = "UB",
366 [BRW_REGISTER_TYPE_V] = "V",
367 [BRW_REGISTER_TYPE_UV] = "UV",
368 };
369 assert(type < ARRAY_SIZE(letters));
370 return letters[type];
371 }