2 * Copyright © 2017 Intel Corporation
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:
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
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
25 #include "brw_eu_defines.h"
26 #include "dev/gen_device_info.h"
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,
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,
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,
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,
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,
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,
87 #define GEN12_HW_REG_TYPE_UINT(n) (n)
88 #define GEN12_HW_REG_TYPE_SINT(n) (0x4 | (n))
89 #define GEN12_HW_REG_TYPE_FLOAT(n) (0x8 | (n))
91 static const struct hw_type
{
92 enum hw_reg_type reg_type
;
93 enum hw_imm_type imm_type
;
95 [0 ... BRW_REGISTER_TYPE_LAST
] = { INVALID
, INVALID
},
97 [BRW_REGISTER_TYPE_DF
] = { GEN7_HW_REG_TYPE_DF
, GEN8_HW_IMM_TYPE_DF
},
98 [BRW_REGISTER_TYPE_F
] = { BRW_HW_REG_TYPE_F
, BRW_HW_IMM_TYPE_F
},
99 [BRW_REGISTER_TYPE_HF
] = { GEN8_HW_REG_TYPE_HF
, GEN8_HW_IMM_TYPE_HF
},
100 [BRW_REGISTER_TYPE_VF
] = { INVALID
, BRW_HW_IMM_TYPE_VF
},
102 [BRW_REGISTER_TYPE_Q
] = { GEN8_HW_REG_TYPE_Q
, GEN8_HW_IMM_TYPE_Q
},
103 [BRW_REGISTER_TYPE_UQ
] = { GEN8_HW_REG_TYPE_UQ
, GEN8_HW_IMM_TYPE_UQ
},
104 [BRW_REGISTER_TYPE_D
] = { BRW_HW_REG_TYPE_D
, BRW_HW_IMM_TYPE_D
},
105 [BRW_REGISTER_TYPE_UD
] = { BRW_HW_REG_TYPE_UD
, BRW_HW_IMM_TYPE_UD
},
106 [BRW_REGISTER_TYPE_W
] = { BRW_HW_REG_TYPE_W
, BRW_HW_IMM_TYPE_W
},
107 [BRW_REGISTER_TYPE_UW
] = { BRW_HW_REG_TYPE_UW
, BRW_HW_IMM_TYPE_UW
},
108 [BRW_REGISTER_TYPE_B
] = { BRW_HW_REG_TYPE_B
, INVALID
},
109 [BRW_REGISTER_TYPE_UB
] = { BRW_HW_REG_TYPE_UB
, INVALID
},
110 [BRW_REGISTER_TYPE_V
] = { INVALID
, BRW_HW_IMM_TYPE_V
},
111 [BRW_REGISTER_TYPE_UV
] = { INVALID
, BRW_HW_IMM_TYPE_UV
},
112 }, gen11_hw_type
[] = {
113 [BRW_REGISTER_TYPE_NF
] = { GEN11_HW_REG_TYPE_NF
, INVALID
},
114 [BRW_REGISTER_TYPE_DF
] = { GEN11_HW_REG_TYPE_DF
, GEN11_HW_IMM_TYPE_DF
},
115 [BRW_REGISTER_TYPE_F
] = { GEN11_HW_REG_TYPE_F
, GEN11_HW_IMM_TYPE_F
},
116 [BRW_REGISTER_TYPE_HF
] = { GEN11_HW_REG_TYPE_HF
, GEN11_HW_IMM_TYPE_HF
},
117 [BRW_REGISTER_TYPE_VF
] = { INVALID
, GEN11_HW_IMM_TYPE_VF
},
119 [BRW_REGISTER_TYPE_Q
] = { GEN11_HW_REG_TYPE_Q
, GEN11_HW_IMM_TYPE_Q
},
120 [BRW_REGISTER_TYPE_UQ
] = { GEN11_HW_REG_TYPE_UQ
, GEN11_HW_IMM_TYPE_UQ
},
121 [BRW_REGISTER_TYPE_D
] = { GEN11_HW_REG_TYPE_D
, GEN11_HW_IMM_TYPE_D
},
122 [BRW_REGISTER_TYPE_UD
] = { GEN11_HW_REG_TYPE_UD
, GEN11_HW_IMM_TYPE_UD
},
123 [BRW_REGISTER_TYPE_W
] = { GEN11_HW_REG_TYPE_W
, GEN11_HW_IMM_TYPE_W
},
124 [BRW_REGISTER_TYPE_UW
] = { GEN11_HW_REG_TYPE_UW
, GEN11_HW_IMM_TYPE_UW
},
125 [BRW_REGISTER_TYPE_B
] = { GEN11_HW_REG_TYPE_B
, INVALID
},
126 [BRW_REGISTER_TYPE_UB
] = { GEN11_HW_REG_TYPE_UB
, INVALID
},
127 [BRW_REGISTER_TYPE_V
] = { INVALID
, GEN11_HW_IMM_TYPE_V
},
128 [BRW_REGISTER_TYPE_UV
] = { INVALID
, GEN11_HW_IMM_TYPE_UV
},
129 }, gen12_hw_type
[] = {
130 [BRW_REGISTER_TYPE_NF
] = { INVALID
, INVALID
},
131 [BRW_REGISTER_TYPE_DF
] = { GEN12_HW_REG_TYPE_FLOAT(3), GEN12_HW_REG_TYPE_FLOAT(3) },
132 [BRW_REGISTER_TYPE_F
] = { GEN12_HW_REG_TYPE_FLOAT(2), GEN12_HW_REG_TYPE_FLOAT(2) },
133 [BRW_REGISTER_TYPE_HF
] = { GEN12_HW_REG_TYPE_FLOAT(1), GEN12_HW_REG_TYPE_FLOAT(1) },
134 [BRW_REGISTER_TYPE_VF
] = { INVALID
, GEN12_HW_REG_TYPE_FLOAT(0) },
136 [BRW_REGISTER_TYPE_Q
] = { GEN12_HW_REG_TYPE_SINT(3), GEN12_HW_REG_TYPE_SINT(3) },
137 [BRW_REGISTER_TYPE_UQ
] = { GEN12_HW_REG_TYPE_UINT(3), GEN12_HW_REG_TYPE_UINT(3) },
138 [BRW_REGISTER_TYPE_D
] = { GEN12_HW_REG_TYPE_SINT(2), GEN12_HW_REG_TYPE_SINT(2) },
139 [BRW_REGISTER_TYPE_UD
] = { GEN12_HW_REG_TYPE_UINT(2), GEN12_HW_REG_TYPE_UINT(2) },
140 [BRW_REGISTER_TYPE_W
] = { GEN12_HW_REG_TYPE_SINT(1), GEN12_HW_REG_TYPE_SINT(1) },
141 [BRW_REGISTER_TYPE_UW
] = { GEN12_HW_REG_TYPE_UINT(1), GEN12_HW_REG_TYPE_UINT(1) },
142 [BRW_REGISTER_TYPE_B
] = { GEN12_HW_REG_TYPE_SINT(0), INVALID
},
143 [BRW_REGISTER_TYPE_UB
] = { GEN12_HW_REG_TYPE_UINT(0), INVALID
},
144 [BRW_REGISTER_TYPE_V
] = { INVALID
, GEN12_HW_REG_TYPE_SINT(0) },
145 [BRW_REGISTER_TYPE_UV
] = { INVALID
, GEN12_HW_REG_TYPE_UINT(0) },
148 /* SNB adds 3-src instructions (MAD and LRP) that only operate on floats, so
149 * the types were implied. IVB adds BFE and BFI2 that operate on doublewords
150 * and unsigned doublewords, so a new field is also available in the da3src
151 * struct (part of struct brw_instruction.bits1 in brw_structs.h) to select
152 * dst and shared-src types.
154 * CNL adds support for 3-src instructions in align1 mode, and with it support
155 * for most register types.
157 enum hw_3src_reg_type
{
158 GEN7_3SRC_TYPE_F
= 0,
159 GEN7_3SRC_TYPE_D
= 1,
160 GEN7_3SRC_TYPE_UD
= 2,
161 GEN7_3SRC_TYPE_DF
= 3,
162 GEN8_3SRC_TYPE_HF
= 4,
164 /** When ExecutionDatatype is 1: @{ */
165 GEN10_ALIGN1_3SRC_REG_TYPE_HF
= 0b000,
166 GEN10_ALIGN1_3SRC_REG_TYPE_F
= 0b001,
167 GEN10_ALIGN1_3SRC_REG_TYPE_DF
= 0b010,
168 GEN11_ALIGN1_3SRC_REG_TYPE_NF
= 0b011,
171 /** When ExecutionDatatype is 0: @{ */
172 GEN10_ALIGN1_3SRC_REG_TYPE_UD
= 0b000,
173 GEN10_ALIGN1_3SRC_REG_TYPE_D
= 0b001,
174 GEN10_ALIGN1_3SRC_REG_TYPE_UW
= 0b010,
175 GEN10_ALIGN1_3SRC_REG_TYPE_W
= 0b011,
176 GEN10_ALIGN1_3SRC_REG_TYPE_UB
= 0b100,
177 GEN10_ALIGN1_3SRC_REG_TYPE_B
= 0b101,
181 static const struct hw_3src_type
{
182 enum hw_3src_reg_type reg_type
;
183 enum gen10_align1_3src_exec_type exec_type
;
184 } gen7_hw_3src_type
[] = {
185 [0 ... BRW_REGISTER_TYPE_LAST
] = { INVALID
},
187 [BRW_REGISTER_TYPE_F
] = { GEN7_3SRC_TYPE_F
},
188 [BRW_REGISTER_TYPE_D
] = { GEN7_3SRC_TYPE_D
},
189 [BRW_REGISTER_TYPE_UD
] = { GEN7_3SRC_TYPE_UD
},
190 [BRW_REGISTER_TYPE_DF
] = { GEN7_3SRC_TYPE_DF
},
191 [BRW_REGISTER_TYPE_HF
] = { GEN8_3SRC_TYPE_HF
},
192 }, gen10_hw_3src_align1_type
[] = {
193 #define E(x) BRW_ALIGN1_3SRC_EXEC_TYPE_##x
194 [0 ... BRW_REGISTER_TYPE_LAST
] = { INVALID
},
196 [BRW_REGISTER_TYPE_NF
] = { GEN11_ALIGN1_3SRC_REG_TYPE_NF
, E(FLOAT
) },
197 [BRW_REGISTER_TYPE_DF
] = { GEN10_ALIGN1_3SRC_REG_TYPE_DF
, E(FLOAT
) },
198 [BRW_REGISTER_TYPE_F
] = { GEN10_ALIGN1_3SRC_REG_TYPE_F
, E(FLOAT
) },
199 [BRW_REGISTER_TYPE_HF
] = { GEN10_ALIGN1_3SRC_REG_TYPE_HF
, E(FLOAT
) },
201 [BRW_REGISTER_TYPE_D
] = { GEN10_ALIGN1_3SRC_REG_TYPE_D
, E(INT
) },
202 [BRW_REGISTER_TYPE_UD
] = { GEN10_ALIGN1_3SRC_REG_TYPE_UD
, E(INT
) },
203 [BRW_REGISTER_TYPE_W
] = { GEN10_ALIGN1_3SRC_REG_TYPE_W
, E(INT
) },
204 [BRW_REGISTER_TYPE_UW
] = { GEN10_ALIGN1_3SRC_REG_TYPE_UW
, E(INT
) },
205 [BRW_REGISTER_TYPE_B
] = { GEN10_ALIGN1_3SRC_REG_TYPE_B
, E(INT
) },
206 [BRW_REGISTER_TYPE_UB
] = { GEN10_ALIGN1_3SRC_REG_TYPE_UB
, E(INT
) },
207 }, gen12_hw_3src_type
[] = {
208 [0 ... BRW_REGISTER_TYPE_LAST
] = { INVALID
},
210 [BRW_REGISTER_TYPE_DF
] = { GEN12_HW_REG_TYPE_UINT(3), E(FLOAT
), },
211 [BRW_REGISTER_TYPE_F
] = { GEN12_HW_REG_TYPE_UINT(2), E(FLOAT
), },
212 [BRW_REGISTER_TYPE_HF
] = { GEN12_HW_REG_TYPE_UINT(1), E(FLOAT
), },
214 [BRW_REGISTER_TYPE_D
] = { GEN12_HW_REG_TYPE_SINT(2), E(INT
), },
215 [BRW_REGISTER_TYPE_UD
] = { GEN12_HW_REG_TYPE_UINT(2), E(INT
), },
216 [BRW_REGISTER_TYPE_W
] = { GEN12_HW_REG_TYPE_SINT(1), E(INT
), },
217 [BRW_REGISTER_TYPE_UW
] = { GEN12_HW_REG_TYPE_UINT(1), E(INT
), },
218 [BRW_REGISTER_TYPE_B
] = { GEN12_HW_REG_TYPE_SINT(0), E(INT
), },
219 [BRW_REGISTER_TYPE_UB
] = { GEN12_HW_REG_TYPE_UINT(0), E(INT
), },
224 * Convert a brw_reg_type enumeration value into the hardware representation.
226 * The hardware encoding may depend on whether the value is an immediate.
229 brw_reg_type_to_hw_type(const struct gen_device_info
*devinfo
,
230 enum brw_reg_file file
,
231 enum brw_reg_type type
)
233 const struct hw_type
*table
;
235 if (devinfo
->gen
>= 12) {
236 assert(type
< ARRAY_SIZE(gen12_hw_type
));
237 table
= gen12_hw_type
;
238 } else if (devinfo
->gen
>= 11) {
239 assert(type
< ARRAY_SIZE(gen11_hw_type
));
240 table
= gen11_hw_type
;
242 assert(type
< ARRAY_SIZE(gen4_hw_type
));
243 table
= gen4_hw_type
;
246 assert(devinfo
->has_64bit_types
|| brw_reg_type_to_size(type
) < 8 ||
247 type
== BRW_REGISTER_TYPE_NF
);
249 if (file
== BRW_IMMEDIATE_VALUE
) {
250 assert(table
[type
].imm_type
!= (enum hw_imm_type
)INVALID
);
251 return table
[type
].imm_type
;
253 assert(table
[type
].reg_type
!= (enum hw_reg_type
)INVALID
);
254 return table
[type
].reg_type
;
259 * Convert the hardware representation into a brw_reg_type enumeration value.
261 * The hardware encoding may depend on whether the value is an immediate.
264 brw_hw_type_to_reg_type(const struct gen_device_info
*devinfo
,
265 enum brw_reg_file file
, unsigned hw_type
)
267 const struct hw_type
*table
;
269 if (devinfo
->gen
>= 12) {
270 table
= gen12_hw_type
;
271 } else if (devinfo
->gen
>= 11) {
272 table
= gen11_hw_type
;
274 table
= gen4_hw_type
;
277 if (file
== BRW_IMMEDIATE_VALUE
) {
278 for (enum brw_reg_type i
= 0; i
<= BRW_REGISTER_TYPE_LAST
; i
++) {
279 if (table
[i
].imm_type
== (enum hw_imm_type
)hw_type
) {
284 for (enum brw_reg_type i
= 0; i
<= BRW_REGISTER_TYPE_LAST
; i
++) {
285 if (table
[i
].reg_type
== (enum hw_reg_type
)hw_type
) {
290 unreachable("not reached");
294 * Convert a brw_reg_type enumeration value into the hardware representation
295 * for a 3-src align16 instruction
298 brw_reg_type_to_a16_hw_3src_type(const struct gen_device_info
*devinfo
,
299 enum brw_reg_type type
)
301 assert(type
< ARRAY_SIZE(gen7_hw_3src_type
));
302 assert(devinfo
->gen
>= 8 || type
!= BRW_REGISTER_TYPE_HF
);
303 assert(gen7_hw_3src_type
[type
].reg_type
!= (enum hw_3src_reg_type
)INVALID
);
304 return gen7_hw_3src_type
[type
].reg_type
;
308 * Convert a brw_reg_type enumeration value into the hardware representation
309 * for a 3-src align1 instruction
312 brw_reg_type_to_a1_hw_3src_type(const struct gen_device_info
*devinfo
,
313 enum brw_reg_type type
)
315 if (devinfo
->gen
>= 12) {
316 assert(type
< ARRAY_SIZE(gen12_hw_3src_type
));
317 assert(gen12_hw_3src_type
[type
].reg_type
!= (enum hw_3src_reg_type
)INVALID
);
318 return gen12_hw_3src_type
[type
].reg_type
;
320 assert(type
< ARRAY_SIZE(gen10_hw_3src_align1_type
));
321 assert(gen10_hw_3src_align1_type
[type
].reg_type
!= (enum hw_3src_reg_type
)INVALID
);
322 return gen10_hw_3src_align1_type
[type
].reg_type
;
327 * Convert the hardware representation for a 3-src align16 instruction into a
328 * brw_reg_type enumeration value.
331 brw_a16_hw_3src_type_to_reg_type(const struct gen_device_info
*devinfo
,
334 assert(devinfo
->gen
>= 8 || hw_type
!= GEN8_3SRC_TYPE_HF
);
335 for (enum brw_reg_type i
= 0; i
<= BRW_REGISTER_TYPE_LAST
; i
++) {
336 if (gen7_hw_3src_type
[i
].reg_type
== hw_type
) {
340 unreachable("not reached");
344 * Convert the hardware representation for a 3-src align1 instruction into a
345 * brw_reg_type enumeration value.
348 brw_a1_hw_3src_type_to_reg_type(const struct gen_device_info
*devinfo
,
349 unsigned hw_type
, unsigned exec_type
)
351 const struct hw_3src_type
*table
= (devinfo
->gen
>= 12 ? gen12_hw_3src_type
:
352 gen10_hw_3src_align1_type
);
354 for (enum brw_reg_type i
= 0; i
<= BRW_REGISTER_TYPE_LAST
; i
++) {
355 if (table
[i
].reg_type
== hw_type
&&
356 table
[i
].exec_type
== exec_type
) {
360 unreachable("not reached");
364 * Return the element size given a register type.
367 brw_reg_type_to_size(enum brw_reg_type type
)
369 static const unsigned type_size
[] = {
370 [BRW_REGISTER_TYPE_NF
] = 8,
371 [BRW_REGISTER_TYPE_DF
] = 8,
372 [BRW_REGISTER_TYPE_F
] = 4,
373 [BRW_REGISTER_TYPE_HF
] = 2,
374 [BRW_REGISTER_TYPE_VF
] = 4,
376 [BRW_REGISTER_TYPE_Q
] = 8,
377 [BRW_REGISTER_TYPE_UQ
] = 8,
378 [BRW_REGISTER_TYPE_D
] = 4,
379 [BRW_REGISTER_TYPE_UD
] = 4,
380 [BRW_REGISTER_TYPE_W
] = 2,
381 [BRW_REGISTER_TYPE_UW
] = 2,
382 [BRW_REGISTER_TYPE_B
] = 1,
383 [BRW_REGISTER_TYPE_UB
] = 1,
384 [BRW_REGISTER_TYPE_V
] = 2,
385 [BRW_REGISTER_TYPE_UV
] = 2,
387 return type_size
[type
];
391 * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on).
393 * This is different than reg_encoding from brw_disasm.c in that it operates
394 * on the abstract enum values, rather than the generation-specific encoding.
397 brw_reg_type_to_letters(enum brw_reg_type type
)
399 static const char letters
[][3] = {
400 [BRW_REGISTER_TYPE_NF
] = "NF",
401 [BRW_REGISTER_TYPE_DF
] = "DF",
402 [BRW_REGISTER_TYPE_F
] = "F",
403 [BRW_REGISTER_TYPE_HF
] = "HF",
404 [BRW_REGISTER_TYPE_VF
] = "VF",
406 [BRW_REGISTER_TYPE_Q
] = "Q",
407 [BRW_REGISTER_TYPE_UQ
] = "UQ",
408 [BRW_REGISTER_TYPE_D
] = "D",
409 [BRW_REGISTER_TYPE_UD
] = "UD",
410 [BRW_REGISTER_TYPE_W
] = "W",
411 [BRW_REGISTER_TYPE_UW
] = "UW",
412 [BRW_REGISTER_TYPE_B
] = "B",
413 [BRW_REGISTER_TYPE_UB
] = "UB",
414 [BRW_REGISTER_TYPE_V
] = "V",
415 [BRW_REGISTER_TYPE_UV
] = "UV",
417 assert(type
< ARRAY_SIZE(letters
));
418 return letters
[type
];