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