1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keithw@vmware.com>
30 */
31
32 /** @file brw_reg.h
33 *
34 * This file defines struct brw_reg, which is our representation for EU
35 * registers. They're not a hardware specific format, just an abstraction
36 * that intends to capture the full flexibility of the hardware registers.
37 *
38 * The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode
39 * the abstract brw_reg type into the actual hardware instruction encoding.
40 */
41
42 #ifndef BRW_REG_H
43 #define BRW_REG_H
44
45 #include <stdbool.h>
46 #include "main/compiler.h"
47 #include "main/macros.h"
48 #include "program/prog_instruction.h"
49 #include "brw_eu_defines.h"
50 #include "brw_reg_type.h"
51
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55
56 struct gen_device_info;
57
58 /** Number of general purpose registers (VS, WM, etc) */
59 #define BRW_MAX_GRF 128
60
61 /**
62 * First GRF used for the MRF hack.
63 *
64 * On gen7, MRFs are no longer used, and contiguous GRFs are used instead. We
65 * haven't converted our compiler to be aware of this, so it asks for MRFs and
66 * brw_eu_emit.c quietly converts them to be accesses of the top GRFs. The
67 * register allocators have to be careful of this to avoid corrupting the "MRF"s
68 * with actual GRF allocations.
69 */
70 #define GEN7_MRF_HACK_START 112
71
72 /** Number of message register file registers */
73 #define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16)
74
75 #define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
76 #define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
77
78 #define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3)
79 #define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3)
80 #define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0)
81 #define BRW_SWIZZLE_YYYY BRW_SWIZZLE4(1,1,1,1)
82 #define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2)
83 #define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3)
84 #define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1)
85 #define BRW_SWIZZLE_YXYX BRW_SWIZZLE4(1,0,1,0)
86 #define BRW_SWIZZLE_XZXZ BRW_SWIZZLE4(0,2,0,2)
87 #define BRW_SWIZZLE_YZXW BRW_SWIZZLE4(1,2,0,3)
88 #define BRW_SWIZZLE_YWYW BRW_SWIZZLE4(1,3,1,3)
89 #define BRW_SWIZZLE_ZXYW BRW_SWIZZLE4(2,0,1,3)
90 #define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3)
91 #define BRW_SWIZZLE_WZWZ BRW_SWIZZLE4(3,2,3,2)
92 #define BRW_SWIZZLE_WZYX BRW_SWIZZLE4(3,2,1,0)
93 #define BRW_SWIZZLE_XXZZ BRW_SWIZZLE4(0,0,2,2)
94 #define BRW_SWIZZLE_YYWW BRW_SWIZZLE4(1,1,3,3)
95 #define BRW_SWIZZLE_YXWZ BRW_SWIZZLE4(1,0,3,2)
96
97 #define BRW_SWZ_COMP_INPUT(comp) (BRW_SWIZZLE_XYZW >> ((comp)*2))
98 #define BRW_SWZ_COMP_OUTPUT(comp) (BRW_SWIZZLE_XYZW << ((comp)*2))
99
100 static inline bool
brw_is_single_value_swizzle(unsigned swiz)101 brw_is_single_value_swizzle(unsigned swiz)
102 {
103 return (swiz == BRW_SWIZZLE_XXXX ||
104 swiz == BRW_SWIZZLE_YYYY ||
105 swiz == BRW_SWIZZLE_ZZZZ ||
106 swiz == BRW_SWIZZLE_WWWW);
107 }
108
109 /**
110 * Compute the swizzle obtained from the application of \p swz0 on the result
111 * of \p swz1. The argument ordering is expected to match function
112 * composition.
113 */
114 static inline unsigned
brw_compose_swizzle(unsigned swz0,unsigned swz1)115 brw_compose_swizzle(unsigned swz0, unsigned swz1)
116 {
117 return BRW_SWIZZLE4(
118 BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)),
119 BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)),
120 BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)),
121 BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3)));
122 }
123
124 /**
125 * Return the result of applying swizzle \p swz to shuffle the bits of \p mask
126 * (AKA image).
127 */
128 static inline unsigned
brw_apply_swizzle_to_mask(unsigned swz,unsigned mask)129 brw_apply_swizzle_to_mask(unsigned swz, unsigned mask)
130 {
131 unsigned result = 0;
132
133 for (unsigned i = 0; i < 4; i++) {
134 if (mask & (1 << BRW_GET_SWZ(swz, i)))
135 result |= 1 << i;
136 }
137
138 return result;
139 }
140
141 /**
142 * Return the result of applying the inverse of swizzle \p swz to shuffle the
143 * bits of \p mask (AKA preimage). Useful to find out which components are
144 * read from a swizzled source given the instruction writemask.
145 */
146 static inline unsigned
brw_apply_inv_swizzle_to_mask(unsigned swz,unsigned mask)147 brw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
148 {
149 unsigned result = 0;
150
151 for (unsigned i = 0; i < 4; i++) {
152 if (mask & (1 << i))
153 result |= 1 << BRW_GET_SWZ(swz, i);
154 }
155
156 return result;
157 }
158
159 /**
160 * Construct an identity swizzle for the set of enabled channels given by \p
161 * mask. The result will only reference channels enabled in the provided \p
162 * mask, assuming that \p mask is non-zero. The constructed swizzle will
163 * satisfy the property that for any instruction OP and any mask:
164 *
165 * brw_OP(p, brw_writemask(dst, mask),
166 * brw_swizzle(src, brw_swizzle_for_mask(mask)));
167 *
168 * will be equivalent to the same instruction without swizzle:
169 *
170 * brw_OP(p, brw_writemask(dst, mask), src);
171 */
172 static inline unsigned
brw_swizzle_for_mask(unsigned mask)173 brw_swizzle_for_mask(unsigned mask)
174 {
175 unsigned last = (mask ? ffs(mask) - 1 : 0);
176 unsigned swz[4];
177
178 for (unsigned i = 0; i < 4; i++)
179 last = swz[i] = (mask & (1 << i) ? i : last);
180
181 return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
182 }
183
184 /**
185 * Construct an identity swizzle for the first \p n components of a vector.
186 * When only a subset of channels of a vec4 are used we don't want to
187 * reference the other channels, as that will tell optimization passes that
188 * those other channels are used.
189 */
190 static inline unsigned
brw_swizzle_for_size(unsigned n)191 brw_swizzle_for_size(unsigned n)
192 {
193 return brw_swizzle_for_mask((1 << n) - 1);
194 }
195
196 /**
197 * Converse of brw_swizzle_for_mask(). Returns the mask of components
198 * accessed by the specified swizzle \p swz.
199 */
200 static inline unsigned
brw_mask_for_swizzle(unsigned swz)201 brw_mask_for_swizzle(unsigned swz)
202 {
203 return brw_apply_inv_swizzle_to_mask(swz, ~0);
204 }
205
206 uint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
207
208 #define REG_SIZE (8*4)
209
210 /* These aren't hardware structs, just something useful for us to pass around:
211 *
212 * Align1 operation has a lot of control over input ranges. Used in
213 * WM programs to implement shaders decomposed into "channel serial"
214 * or "structure of array" form:
215 */
216 struct brw_reg {
217 union {
218 struct {
219 enum brw_reg_type type:4;
220 enum brw_reg_file file:3; /* :2 hardware format */
221 unsigned negate:1; /* source only */
222 unsigned abs:1; /* source only */
223 unsigned address_mode:1; /* relative addressing, hopefully! */
224 unsigned pad0:1;
225 unsigned subnr:5; /* :1 in align16 */
226 unsigned nr:16;
227 };
228 uint32_t bits;
229 };
230
231 union {
232 struct {
233 unsigned swizzle:8; /* src only, align16 only */
234 unsigned writemask:4; /* dest only, align16 only */
235 int indirect_offset:10; /* relative addressing offset */
236 unsigned vstride:4; /* source only */
237 unsigned width:3; /* src only, align1 only */
238 unsigned hstride:2; /* align1 only */
239 unsigned pad1:1;
240 };
241
242 double df;
243 uint64_t u64;
244 int64_t d64;
245 float f;
246 int d;
247 unsigned ud;
248 };
249 };
250
251 static inline bool
brw_regs_equal(const struct brw_reg * a,const struct brw_reg * b)252 brw_regs_equal(const struct brw_reg *a, const struct brw_reg *b)
253 {
254 const bool df = a->type == BRW_REGISTER_TYPE_DF && a->file == IMM;
255 return a->bits == b->bits && (df ? a->u64 == b->u64 : a->ud == b->ud);
256 }
257
258 struct brw_indirect {
259 unsigned addr_subnr:4;
260 int addr_offset:10;
261 unsigned pad:18;
262 };
263
264
265 static inline unsigned
type_sz(unsigned type)266 type_sz(unsigned type)
267 {
268 switch(type) {
269 case BRW_REGISTER_TYPE_UQ:
270 case BRW_REGISTER_TYPE_Q:
271 case BRW_REGISTER_TYPE_DF:
272 return 8;
273 case BRW_REGISTER_TYPE_UD:
274 case BRW_REGISTER_TYPE_D:
275 case BRW_REGISTER_TYPE_F:
276 case BRW_REGISTER_TYPE_VF:
277 return 4;
278 case BRW_REGISTER_TYPE_UW:
279 case BRW_REGISTER_TYPE_W:
280 case BRW_REGISTER_TYPE_UV:
281 case BRW_REGISTER_TYPE_V:
282 case BRW_REGISTER_TYPE_HF:
283 return 2;
284 case BRW_REGISTER_TYPE_UB:
285 case BRW_REGISTER_TYPE_B:
286 return 1;
287 default:
288 unreachable("not reached");
289 }
290 }
291
292 static inline enum brw_reg_type
get_exec_type(const enum brw_reg_type type)293 get_exec_type(const enum brw_reg_type type)
294 {
295 switch (type) {
296 case BRW_REGISTER_TYPE_B:
297 case BRW_REGISTER_TYPE_V:
298 return BRW_REGISTER_TYPE_W;
299 case BRW_REGISTER_TYPE_UB:
300 case BRW_REGISTER_TYPE_UV:
301 return BRW_REGISTER_TYPE_UW;
302 case BRW_REGISTER_TYPE_VF:
303 return BRW_REGISTER_TYPE_F;
304 default:
305 return type;
306 }
307 }
308
309 /**
310 * Return an integer type of the requested size and signedness.
311 */
312 static inline enum brw_reg_type
brw_int_type(unsigned sz,bool is_signed)313 brw_int_type(unsigned sz, bool is_signed)
314 {
315 switch (sz) {
316 case 1:
317 return (is_signed ? BRW_REGISTER_TYPE_B : BRW_REGISTER_TYPE_UB);
318 case 2:
319 return (is_signed ? BRW_REGISTER_TYPE_W : BRW_REGISTER_TYPE_UW);
320 case 4:
321 return (is_signed ? BRW_REGISTER_TYPE_D : BRW_REGISTER_TYPE_UD);
322 case 8:
323 return (is_signed ? BRW_REGISTER_TYPE_Q : BRW_REGISTER_TYPE_UQ);
324 default:
325 unreachable("Not reached.");
326 }
327 }
328
329 /**
330 * Construct a brw_reg.
331 * \param file one of the BRW_x_REGISTER_FILE values
332 * \param nr register number/index
333 * \param subnr register sub number
334 * \param negate register negate modifier
335 * \param abs register abs modifier
336 * \param type one of BRW_REGISTER_TYPE_x
337 * \param vstride one of BRW_VERTICAL_STRIDE_x
338 * \param width one of BRW_WIDTH_x
339 * \param hstride one of BRW_HORIZONTAL_STRIDE_x
340 * \param swizzle one of BRW_SWIZZLE_x
341 * \param writemask WRITEMASK_X/Y/Z/W bitfield
342 */
343 static inline struct brw_reg
brw_reg(enum brw_reg_file file,unsigned nr,unsigned subnr,unsigned negate,unsigned abs,enum brw_reg_type type,unsigned vstride,unsigned width,unsigned hstride,unsigned swizzle,unsigned writemask)344 brw_reg(enum brw_reg_file file,
345 unsigned nr,
346 unsigned subnr,
347 unsigned negate,
348 unsigned abs,
349 enum brw_reg_type type,
350 unsigned vstride,
351 unsigned width,
352 unsigned hstride,
353 unsigned swizzle,
354 unsigned writemask)
355 {
356 struct brw_reg reg;
357 if (file == BRW_GENERAL_REGISTER_FILE)
358 assert(nr < BRW_MAX_GRF);
359 else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
360 assert(nr <= BRW_ARF_TIMESTAMP);
361 /* Asserting on the MRF register number requires to know the hardware gen
362 * (gen6 has 24 MRF registers), which we don't know here, so we assert
363 * for that in the generators and in brw_eu_emit.c
364 */
365
366 reg.type = type;
367 reg.file = file;
368 reg.negate = negate;
369 reg.abs = abs;
370 reg.address_mode = BRW_ADDRESS_DIRECT;
371 reg.pad0 = 0;
372 reg.subnr = subnr * type_sz(type);
373 reg.nr = nr;
374
375 /* Could do better: If the reg is r5.3<0;1,0>, we probably want to
376 * set swizzle and writemask to W, as the lower bits of subnr will
377 * be lost when converted to align16. This is probably too much to
378 * keep track of as you'd want it adjusted by suboffset(), etc.
379 * Perhaps fix up when converting to align16?
380 */
381 reg.swizzle = swizzle;
382 reg.writemask = writemask;
383 reg.indirect_offset = 0;
384 reg.vstride = vstride;
385 reg.width = width;
386 reg.hstride = hstride;
387 reg.pad1 = 0;
388 return reg;
389 }
390
391 /** Construct float[16] register */
392 static inline struct brw_reg
brw_vec16_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)393 brw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
394 {
395 return brw_reg(file,
396 nr,
397 subnr,
398 0,
399 0,
400 BRW_REGISTER_TYPE_F,
401 BRW_VERTICAL_STRIDE_16,
402 BRW_WIDTH_16,
403 BRW_HORIZONTAL_STRIDE_1,
404 BRW_SWIZZLE_XYZW,
405 WRITEMASK_XYZW);
406 }
407
408 /** Construct float[8] register */
409 static inline struct brw_reg
brw_vec8_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)410 brw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
411 {
412 return brw_reg(file,
413 nr,
414 subnr,
415 0,
416 0,
417 BRW_REGISTER_TYPE_F,
418 BRW_VERTICAL_STRIDE_8,
419 BRW_WIDTH_8,
420 BRW_HORIZONTAL_STRIDE_1,
421 BRW_SWIZZLE_XYZW,
422 WRITEMASK_XYZW);
423 }
424
425 /** Construct float[4] register */
426 static inline struct brw_reg
brw_vec4_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)427 brw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
428 {
429 return brw_reg(file,
430 nr,
431 subnr,
432 0,
433 0,
434 BRW_REGISTER_TYPE_F,
435 BRW_VERTICAL_STRIDE_4,
436 BRW_WIDTH_4,
437 BRW_HORIZONTAL_STRIDE_1,
438 BRW_SWIZZLE_XYZW,
439 WRITEMASK_XYZW);
440 }
441
442 /** Construct float[2] register */
443 static inline struct brw_reg
brw_vec2_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)444 brw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
445 {
446 return brw_reg(file,
447 nr,
448 subnr,
449 0,
450 0,
451 BRW_REGISTER_TYPE_F,
452 BRW_VERTICAL_STRIDE_2,
453 BRW_WIDTH_2,
454 BRW_HORIZONTAL_STRIDE_1,
455 BRW_SWIZZLE_XYXY,
456 WRITEMASK_XY);
457 }
458
459 /** Construct float[1] register */
460 static inline struct brw_reg
brw_vec1_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)461 brw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
462 {
463 return brw_reg(file,
464 nr,
465 subnr,
466 0,
467 0,
468 BRW_REGISTER_TYPE_F,
469 BRW_VERTICAL_STRIDE_0,
470 BRW_WIDTH_1,
471 BRW_HORIZONTAL_STRIDE_0,
472 BRW_SWIZZLE_XXXX,
473 WRITEMASK_X);
474 }
475
476 static inline struct brw_reg
brw_vecn_reg(unsigned width,enum brw_reg_file file,unsigned nr,unsigned subnr)477 brw_vecn_reg(unsigned width, enum brw_reg_file file,
478 unsigned nr, unsigned subnr)
479 {
480 switch (width) {
481 case 1:
482 return brw_vec1_reg(file, nr, subnr);
483 case 2:
484 return brw_vec2_reg(file, nr, subnr);
485 case 4:
486 return brw_vec4_reg(file, nr, subnr);
487 case 8:
488 return brw_vec8_reg(file, nr, subnr);
489 case 16:
490 return brw_vec16_reg(file, nr, subnr);
491 default:
492 unreachable("Invalid register width");
493 }
494 }
495
496 static inline struct brw_reg
retype(struct brw_reg reg,enum brw_reg_type type)497 retype(struct brw_reg reg, enum brw_reg_type type)
498 {
499 reg.type = type;
500 return reg;
501 }
502
503 static inline struct brw_reg
firsthalf(struct brw_reg reg)504 firsthalf(struct brw_reg reg)
505 {
506 return reg;
507 }
508
509 static inline struct brw_reg
sechalf(struct brw_reg reg)510 sechalf(struct brw_reg reg)
511 {
512 if (reg.vstride)
513 reg.nr++;
514 return reg;
515 }
516
517 static inline struct brw_reg
offset(struct brw_reg reg,unsigned delta)518 offset(struct brw_reg reg, unsigned delta)
519 {
520 reg.nr += delta;
521 return reg;
522 }
523
524
525 static inline struct brw_reg
byte_offset(struct brw_reg reg,unsigned bytes)526 byte_offset(struct brw_reg reg, unsigned bytes)
527 {
528 unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
529 reg.nr = newoffset / REG_SIZE;
530 reg.subnr = newoffset % REG_SIZE;
531 return reg;
532 }
533
534 static inline struct brw_reg
suboffset(struct brw_reg reg,unsigned delta)535 suboffset(struct brw_reg reg, unsigned delta)
536 {
537 return byte_offset(reg, delta * type_sz(reg.type));
538 }
539
540 /** Construct unsigned word[16] register */
541 static inline struct brw_reg
brw_uw16_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)542 brw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
543 {
544 return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
545 }
546
547 /** Construct unsigned word[8] register */
548 static inline struct brw_reg
brw_uw8_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)549 brw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
550 {
551 return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
552 }
553
554 /** Construct unsigned word[1] register */
555 static inline struct brw_reg
brw_uw1_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)556 brw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
557 {
558 return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
559 }
560
561 static inline struct brw_reg
brw_ud1_reg(enum brw_reg_file file,unsigned nr,unsigned subnr)562 brw_ud1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
563 {
564 return retype(brw_vec1_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD);
565 }
566
567 static inline struct brw_reg
brw_imm_reg(enum brw_reg_type type)568 brw_imm_reg(enum brw_reg_type type)
569 {
570 return brw_reg(BRW_IMMEDIATE_VALUE,
571 0,
572 0,
573 0,
574 0,
575 type,
576 BRW_VERTICAL_STRIDE_0,
577 BRW_WIDTH_1,
578 BRW_HORIZONTAL_STRIDE_0,
579 0,
580 0);
581 }
582
583 /** Construct float immediate register */
584 static inline struct brw_reg
brw_imm_df(double df)585 brw_imm_df(double df)
586 {
587 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_DF);
588 imm.df = df;
589 return imm;
590 }
591
592 static inline struct brw_reg
brw_imm_f(float f)593 brw_imm_f(float f)
594 {
595 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
596 imm.f = f;
597 return imm;
598 }
599
600 /** Construct int64_t immediate register */
601 static inline struct brw_reg
brw_imm_q(int64_t q)602 brw_imm_q(int64_t q)
603 {
604 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_Q);
605 imm.d64 = q;
606 return imm;
607 }
608
609 /** Construct int64_t immediate register */
610 static inline struct brw_reg
brw_imm_uq(uint64_t uq)611 brw_imm_uq(uint64_t uq)
612 {
613 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ);
614 imm.u64 = uq;
615 return imm;
616 }
617
618 /** Construct integer immediate register */
619 static inline struct brw_reg
brw_imm_d(int d)620 brw_imm_d(int d)
621 {
622 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
623 imm.d = d;
624 return imm;
625 }
626
627 /** Construct uint immediate register */
628 static inline struct brw_reg
brw_imm_ud(unsigned ud)629 brw_imm_ud(unsigned ud)
630 {
631 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
632 imm.ud = ud;
633 return imm;
634 }
635
636 /** Construct ushort immediate register */
637 static inline struct brw_reg
brw_imm_uw(uint16_t uw)638 brw_imm_uw(uint16_t uw)
639 {
640 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
641 imm.ud = uw | (uw << 16);
642 return imm;
643 }
644
645 /** Construct short immediate register */
646 static inline struct brw_reg
brw_imm_w(int16_t w)647 brw_imm_w(int16_t w)
648 {
649 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
650 imm.d = w | (w << 16);
651 return imm;
652 }
653
654 /* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
655 * numbers alias with _V and _VF below:
656 */
657
658 /** Construct vector of eight signed half-byte values */
659 static inline struct brw_reg
brw_imm_v(unsigned v)660 brw_imm_v(unsigned v)
661 {
662 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
663 imm.ud = v;
664 return imm;
665 }
666
667 /** Construct vector of eight unsigned half-byte values */
668 static inline struct brw_reg
brw_imm_uv(unsigned uv)669 brw_imm_uv(unsigned uv)
670 {
671 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV);
672 imm.ud = uv;
673 return imm;
674 }
675
676 /** Construct vector of four 8-bit float values */
677 static inline struct brw_reg
brw_imm_vf(unsigned v)678 brw_imm_vf(unsigned v)
679 {
680 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
681 imm.ud = v;
682 return imm;
683 }
684
685 static inline struct brw_reg
brw_imm_vf4(unsigned v0,unsigned v1,unsigned v2,unsigned v3)686 brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
687 {
688 struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
689 imm.vstride = BRW_VERTICAL_STRIDE_0;
690 imm.width = BRW_WIDTH_4;
691 imm.hstride = BRW_HORIZONTAL_STRIDE_1;
692 imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
693 return imm;
694 }
695
696
697 static inline struct brw_reg
brw_address(struct brw_reg reg)698 brw_address(struct brw_reg reg)
699 {
700 return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
701 }
702
703 /** Construct float[1] general-purpose register */
704 static inline struct brw_reg
brw_vec1_grf(unsigned nr,unsigned subnr)705 brw_vec1_grf(unsigned nr, unsigned subnr)
706 {
707 return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
708 }
709
710 /** Construct float[2] general-purpose register */
711 static inline struct brw_reg
brw_vec2_grf(unsigned nr,unsigned subnr)712 brw_vec2_grf(unsigned nr, unsigned subnr)
713 {
714 return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
715 }
716
717 /** Construct float[4] general-purpose register */
718 static inline struct brw_reg
brw_vec4_grf(unsigned nr,unsigned subnr)719 brw_vec4_grf(unsigned nr, unsigned subnr)
720 {
721 return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
722 }
723
724 /** Construct float[8] general-purpose register */
725 static inline struct brw_reg
brw_vec8_grf(unsigned nr,unsigned subnr)726 brw_vec8_grf(unsigned nr, unsigned subnr)
727 {
728 return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
729 }
730
731 /** Construct float[16] general-purpose register */
732 static inline struct brw_reg
brw_vec16_grf(unsigned nr,unsigned subnr)733 brw_vec16_grf(unsigned nr, unsigned subnr)
734 {
735 return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
736 }
737
738 static inline struct brw_reg
brw_vecn_grf(unsigned width,unsigned nr,unsigned subnr)739 brw_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
740 {
741 return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr, subnr);
742 }
743
744
745 static inline struct brw_reg
brw_uw8_grf(unsigned nr,unsigned subnr)746 brw_uw8_grf(unsigned nr, unsigned subnr)
747 {
748 return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
749 }
750
751 static inline struct brw_reg
brw_uw16_grf(unsigned nr,unsigned subnr)752 brw_uw16_grf(unsigned nr, unsigned subnr)
753 {
754 return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
755 }
756
757
758 /** Construct null register (usually used for setting condition codes) */
759 static inline struct brw_reg
brw_null_reg(void)760 brw_null_reg(void)
761 {
762 return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
763 }
764
765 static inline struct brw_reg
brw_null_vec(unsigned width)766 brw_null_vec(unsigned width)
767 {
768 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
769 }
770
771 static inline struct brw_reg
brw_address_reg(unsigned subnr)772 brw_address_reg(unsigned subnr)
773 {
774 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
775 }
776
777 static inline struct brw_reg
brw_tdr_reg(void)778 brw_tdr_reg(void)
779 {
780 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_TDR, 0);
781 }
782
783 /* If/else instructions break in align16 mode if writemask & swizzle
784 * aren't xyzw. This goes against the convention for other scalar
785 * regs:
786 */
787 static inline struct brw_reg
brw_ip_reg(void)788 brw_ip_reg(void)
789 {
790 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
791 BRW_ARF_IP,
792 0,
793 0,
794 0,
795 BRW_REGISTER_TYPE_UD,
796 BRW_VERTICAL_STRIDE_4, /* ? */
797 BRW_WIDTH_1,
798 BRW_HORIZONTAL_STRIDE_0,
799 BRW_SWIZZLE_XYZW, /* NOTE! */
800 WRITEMASK_XYZW); /* NOTE! */
801 }
802
803 static inline struct brw_reg
brw_notification_reg(void)804 brw_notification_reg(void)
805 {
806 return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
807 BRW_ARF_NOTIFICATION_COUNT,
808 0,
809 0,
810 0,
811 BRW_REGISTER_TYPE_UD,
812 BRW_VERTICAL_STRIDE_0,
813 BRW_WIDTH_1,
814 BRW_HORIZONTAL_STRIDE_0,
815 BRW_SWIZZLE_XXXX,
816 WRITEMASK_X);
817 }
818
819 static inline struct brw_reg
brw_cr0_reg(unsigned subnr)820 brw_cr0_reg(unsigned subnr)
821 {
822 return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_CONTROL, subnr);
823 }
824
825 static inline struct brw_reg
brw_sr0_reg(unsigned subnr)826 brw_sr0_reg(unsigned subnr)
827 {
828 return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr);
829 }
830
831 static inline struct brw_reg
brw_acc_reg(unsigned width)832 brw_acc_reg(unsigned width)
833 {
834 return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
835 BRW_ARF_ACCUMULATOR, 0);
836 }
837
838 static inline struct brw_reg
brw_flag_reg(int reg,int subreg)839 brw_flag_reg(int reg, int subreg)
840 {
841 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
842 BRW_ARF_FLAG + reg, subreg);
843 }
844
845 /**
846 * Return the mask register present in Gen4-5, or the related register present
847 * in Gen7.5 and later hardware referred to as "channel enable" register in
848 * the documentation.
849 */
850 static inline struct brw_reg
brw_mask_reg(unsigned subnr)851 brw_mask_reg(unsigned subnr)
852 {
853 return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
854 }
855
856 static inline struct brw_reg
brw_vmask_reg()857 brw_vmask_reg()
858 {
859 return brw_sr0_reg(3);
860 }
861
862 static inline struct brw_reg
brw_dmask_reg()863 brw_dmask_reg()
864 {
865 return brw_sr0_reg(2);
866 }
867
868 static inline struct brw_reg
brw_message_reg(unsigned nr)869 brw_message_reg(unsigned nr)
870 {
871 return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
872 }
873
874 static inline struct brw_reg
brw_uvec_mrf(unsigned width,unsigned nr,unsigned subnr)875 brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
876 {
877 return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
878 BRW_REGISTER_TYPE_UD);
879 }
880
881 /* This is almost always called with a numeric constant argument, so
882 * make things easy to evaluate at compile time:
883 */
cvt(unsigned val)884 static inline unsigned cvt(unsigned val)
885 {
886 switch (val) {
887 case 0: return 0;
888 case 1: return 1;
889 case 2: return 2;
890 case 4: return 3;
891 case 8: return 4;
892 case 16: return 5;
893 case 32: return 6;
894 }
895 return 0;
896 }
897
898 static inline struct brw_reg
stride(struct brw_reg reg,unsigned vstride,unsigned width,unsigned hstride)899 stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
900 {
901 reg.vstride = cvt(vstride);
902 reg.width = cvt(width) - 1;
903 reg.hstride = cvt(hstride);
904 return reg;
905 }
906
907 /**
908 * Multiply the vertical and horizontal stride of a register by the given
909 * factor \a s.
910 */
911 static inline struct brw_reg
spread(struct brw_reg reg,unsigned s)912 spread(struct brw_reg reg, unsigned s)
913 {
914 if (s) {
915 assert(_mesa_is_pow_two(s));
916
917 if (reg.hstride)
918 reg.hstride += cvt(s) - 1;
919
920 if (reg.vstride)
921 reg.vstride += cvt(s) - 1;
922
923 return reg;
924 } else {
925 return stride(reg, 0, 1, 0);
926 }
927 }
928
929 /**
930 * Reinterpret each channel of register \p reg as a vector of values of the
931 * given smaller type and take the i-th subcomponent from each.
932 */
933 static inline struct brw_reg
subscript(struct brw_reg reg,enum brw_reg_type type,unsigned i)934 subscript(struct brw_reg reg, enum brw_reg_type type, unsigned i)
935 {
936 if (reg.file == IMM)
937 return reg;
938
939 unsigned scale = type_sz(reg.type) / type_sz(type);
940 assert(scale >= 1 && i < scale);
941
942 return suboffset(retype(spread(reg, scale), type), i);
943 }
944
945 static inline struct brw_reg
vec16(struct brw_reg reg)946 vec16(struct brw_reg reg)
947 {
948 return stride(reg, 16,16,1);
949 }
950
951 static inline struct brw_reg
vec8(struct brw_reg reg)952 vec8(struct brw_reg reg)
953 {
954 return stride(reg, 8,8,1);
955 }
956
957 static inline struct brw_reg
vec4(struct brw_reg reg)958 vec4(struct brw_reg reg)
959 {
960 return stride(reg, 4,4,1);
961 }
962
963 static inline struct brw_reg
vec2(struct brw_reg reg)964 vec2(struct brw_reg reg)
965 {
966 return stride(reg, 2,2,1);
967 }
968
969 static inline struct brw_reg
vec1(struct brw_reg reg)970 vec1(struct brw_reg reg)
971 {
972 return stride(reg, 0,1,0);
973 }
974
975
976 static inline struct brw_reg
get_element(struct brw_reg reg,unsigned elt)977 get_element(struct brw_reg reg, unsigned elt)
978 {
979 return vec1(suboffset(reg, elt));
980 }
981
982 static inline struct brw_reg
get_element_ud(struct brw_reg reg,unsigned elt)983 get_element_ud(struct brw_reg reg, unsigned elt)
984 {
985 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
986 }
987
988 static inline struct brw_reg
get_element_d(struct brw_reg reg,unsigned elt)989 get_element_d(struct brw_reg reg, unsigned elt)
990 {
991 return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
992 }
993
994 static inline struct brw_reg
brw_swizzle(struct brw_reg reg,unsigned swz)995 brw_swizzle(struct brw_reg reg, unsigned swz)
996 {
997 if (reg.file == BRW_IMMEDIATE_VALUE)
998 reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz);
999 else
1000 reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
1001
1002 return reg;
1003 }
1004
1005 static inline struct brw_reg
brw_writemask(struct brw_reg reg,unsigned mask)1006 brw_writemask(struct brw_reg reg, unsigned mask)
1007 {
1008 assert(reg.file != BRW_IMMEDIATE_VALUE);
1009 reg.writemask &= mask;
1010 return reg;
1011 }
1012
1013 static inline struct brw_reg
brw_set_writemask(struct brw_reg reg,unsigned mask)1014 brw_set_writemask(struct brw_reg reg, unsigned mask)
1015 {
1016 assert(reg.file != BRW_IMMEDIATE_VALUE);
1017 reg.writemask = mask;
1018 return reg;
1019 }
1020
1021 static inline unsigned
brw_writemask_for_size(unsigned n)1022 brw_writemask_for_size(unsigned n)
1023 {
1024 return (1 << n) - 1;
1025 }
1026
1027 static inline unsigned
brw_writemask_for_component_packing(unsigned n,unsigned first_component)1028 brw_writemask_for_component_packing(unsigned n, unsigned first_component)
1029 {
1030 assert(first_component + n <= 4);
1031 return (((1 << n) - 1) << first_component);
1032 }
1033
1034 static inline struct brw_reg
negate(struct brw_reg reg)1035 negate(struct brw_reg reg)
1036 {
1037 reg.negate ^= 1;
1038 return reg;
1039 }
1040
1041 static inline struct brw_reg
brw_abs(struct brw_reg reg)1042 brw_abs(struct brw_reg reg)
1043 {
1044 reg.abs = 1;
1045 reg.negate = 0;
1046 return reg;
1047 }
1048
1049 /************************************************************************/
1050
1051 static inline struct brw_reg
brw_vec4_indirect(unsigned subnr,int offset)1052 brw_vec4_indirect(unsigned subnr, int offset)
1053 {
1054 struct brw_reg reg = brw_vec4_grf(0, 0);
1055 reg.subnr = subnr;
1056 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1057 reg.indirect_offset = offset;
1058 return reg;
1059 }
1060
1061 static inline struct brw_reg
brw_vec1_indirect(unsigned subnr,int offset)1062 brw_vec1_indirect(unsigned subnr, int offset)
1063 {
1064 struct brw_reg reg = brw_vec1_grf(0, 0);
1065 reg.subnr = subnr;
1066 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1067 reg.indirect_offset = offset;
1068 return reg;
1069 }
1070
1071 static inline struct brw_reg
brw_VxH_indirect(unsigned subnr,int offset)1072 brw_VxH_indirect(unsigned subnr, int offset)
1073 {
1074 struct brw_reg reg = brw_vec1_grf(0, 0);
1075 reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
1076 reg.subnr = subnr;
1077 reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
1078 reg.indirect_offset = offset;
1079 return reg;
1080 }
1081
1082 static inline struct brw_reg
deref_4f(struct brw_indirect ptr,int offset)1083 deref_4f(struct brw_indirect ptr, int offset)
1084 {
1085 return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1086 }
1087
1088 static inline struct brw_reg
deref_1f(struct brw_indirect ptr,int offset)1089 deref_1f(struct brw_indirect ptr, int offset)
1090 {
1091 return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
1092 }
1093
1094 static inline struct brw_reg
deref_4b(struct brw_indirect ptr,int offset)1095 deref_4b(struct brw_indirect ptr, int offset)
1096 {
1097 return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
1098 }
1099
1100 static inline struct brw_reg
deref_1uw(struct brw_indirect ptr,int offset)1101 deref_1uw(struct brw_indirect ptr, int offset)
1102 {
1103 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
1104 }
1105
1106 static inline struct brw_reg
deref_1d(struct brw_indirect ptr,int offset)1107 deref_1d(struct brw_indirect ptr, int offset)
1108 {
1109 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
1110 }
1111
1112 static inline struct brw_reg
deref_1ud(struct brw_indirect ptr,int offset)1113 deref_1ud(struct brw_indirect ptr, int offset)
1114 {
1115 return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
1116 }
1117
1118 static inline struct brw_reg
get_addr_reg(struct brw_indirect ptr)1119 get_addr_reg(struct brw_indirect ptr)
1120 {
1121 return brw_address_reg(ptr.addr_subnr);
1122 }
1123
1124 static inline struct brw_indirect
brw_indirect_offset(struct brw_indirect ptr,int offset)1125 brw_indirect_offset(struct brw_indirect ptr, int offset)
1126 {
1127 ptr.addr_offset += offset;
1128 return ptr;
1129 }
1130
1131 static inline struct brw_indirect
brw_indirect(unsigned addr_subnr,int offset)1132 brw_indirect(unsigned addr_subnr, int offset)
1133 {
1134 struct brw_indirect ptr;
1135 ptr.addr_subnr = addr_subnr;
1136 ptr.addr_offset = offset;
1137 ptr.pad = 0;
1138 return ptr;
1139 }
1140
1141 static inline bool
region_matches(struct brw_reg reg,enum brw_vertical_stride v,enum brw_width w,enum brw_horizontal_stride h)1142 region_matches(struct brw_reg reg, enum brw_vertical_stride v,
1143 enum brw_width w, enum brw_horizontal_stride h)
1144 {
1145 return reg.vstride == v &&
1146 reg.width == w &&
1147 reg.hstride == h;
1148 }
1149
1150 #define has_scalar_region(reg) \
1151 region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
1152 BRW_HORIZONTAL_STRIDE_0)
1153
1154 /* brw_packed_float.c */
1155 int brw_float_to_vf(float f);
1156 float brw_vf_to_float(unsigned char vf);
1157
1158 #ifdef __cplusplus
1159 }
1160 #endif
1161
1162 #endif
1163