101e04c3fSmrg/* 201e04c3fSmrg Copyright (C) Intel Corp. 2006. All Rights Reserved. 301e04c3fSmrg Intel funded Tungsten Graphics to 401e04c3fSmrg develop this 3D driver. 501e04c3fSmrg 601e04c3fSmrg Permission is hereby granted, free of charge, to any person obtaining 701e04c3fSmrg a copy of this software and associated documentation files (the 801e04c3fSmrg "Software"), to deal in the Software without restriction, including 901e04c3fSmrg without limitation the rights to use, copy, modify, merge, publish, 1001e04c3fSmrg distribute, sublicense, and/or sell copies of the Software, and to 1101e04c3fSmrg permit persons to whom the Software is furnished to do so, subject to 1201e04c3fSmrg the following conditions: 1301e04c3fSmrg 1401e04c3fSmrg The above copyright notice and this permission notice (including the 1501e04c3fSmrg next paragraph) shall be included in all copies or substantial 1601e04c3fSmrg portions of the Software. 1701e04c3fSmrg 1801e04c3fSmrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1901e04c3fSmrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2001e04c3fSmrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2101e04c3fSmrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 2201e04c3fSmrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2301e04c3fSmrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2401e04c3fSmrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2501e04c3fSmrg 2601e04c3fSmrg **********************************************************************/ 2701e04c3fSmrg /* 2801e04c3fSmrg * Authors: 2901e04c3fSmrg * Keith Whitwell <keithw@vmware.com> 3001e04c3fSmrg */ 3101e04c3fSmrg 3201e04c3fSmrg/** @file brw_reg.h 3301e04c3fSmrg * 3401e04c3fSmrg * This file defines struct brw_reg, which is our representation for EU 3501e04c3fSmrg * registers. They're not a hardware specific format, just an abstraction 3601e04c3fSmrg * that intends to capture the full flexibility of the hardware registers. 3701e04c3fSmrg * 3801e04c3fSmrg * The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode 3901e04c3fSmrg * the abstract brw_reg type into the actual hardware instruction encoding. 4001e04c3fSmrg */ 4101e04c3fSmrg 4201e04c3fSmrg#ifndef BRW_REG_H 4301e04c3fSmrg#define BRW_REG_H 4401e04c3fSmrg 4501e04c3fSmrg#include <stdbool.h> 467ec681f3Smrg#include "util/compiler.h" 4701e04c3fSmrg#include "main/macros.h" 4801e04c3fSmrg#include "program/prog_instruction.h" 4901e04c3fSmrg#include "brw_eu_defines.h" 5001e04c3fSmrg#include "brw_reg_type.h" 5101e04c3fSmrg 5201e04c3fSmrg#ifdef __cplusplus 5301e04c3fSmrgextern "C" { 5401e04c3fSmrg#endif 5501e04c3fSmrg 567ec681f3Smrgstruct intel_device_info; 5701e04c3fSmrg 5801e04c3fSmrg/** Number of general purpose registers (VS, WM, etc) */ 5901e04c3fSmrg#define BRW_MAX_GRF 128 6001e04c3fSmrg 6101e04c3fSmrg/** 6201e04c3fSmrg * First GRF used for the MRF hack. 6301e04c3fSmrg * 647ec681f3Smrg * On gfx7, MRFs are no longer used, and contiguous GRFs are used instead. We 6501e04c3fSmrg * haven't converted our compiler to be aware of this, so it asks for MRFs and 6601e04c3fSmrg * brw_eu_emit.c quietly converts them to be accesses of the top GRFs. The 6701e04c3fSmrg * register allocators have to be careful of this to avoid corrupting the "MRF"s 6801e04c3fSmrg * with actual GRF allocations. 6901e04c3fSmrg */ 707ec681f3Smrg#define GFX7_MRF_HACK_START 112 7101e04c3fSmrg 7201e04c3fSmrg/** Number of message register file registers */ 7301e04c3fSmrg#define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16) 7401e04c3fSmrg 7501e04c3fSmrg#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6)) 7601e04c3fSmrg#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3) 7701e04c3fSmrg 7801e04c3fSmrg#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3) 7901e04c3fSmrg#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3) 8001e04c3fSmrg#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0) 8101e04c3fSmrg#define BRW_SWIZZLE_YYYY BRW_SWIZZLE4(1,1,1,1) 8201e04c3fSmrg#define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2) 8301e04c3fSmrg#define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3) 8401e04c3fSmrg#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1) 8501e04c3fSmrg#define BRW_SWIZZLE_YXYX BRW_SWIZZLE4(1,0,1,0) 8601e04c3fSmrg#define BRW_SWIZZLE_XZXZ BRW_SWIZZLE4(0,2,0,2) 8701e04c3fSmrg#define BRW_SWIZZLE_YZXW BRW_SWIZZLE4(1,2,0,3) 8801e04c3fSmrg#define BRW_SWIZZLE_YWYW BRW_SWIZZLE4(1,3,1,3) 8901e04c3fSmrg#define BRW_SWIZZLE_ZXYW BRW_SWIZZLE4(2,0,1,3) 9001e04c3fSmrg#define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3) 9101e04c3fSmrg#define BRW_SWIZZLE_WZWZ BRW_SWIZZLE4(3,2,3,2) 9201e04c3fSmrg#define BRW_SWIZZLE_WZYX BRW_SWIZZLE4(3,2,1,0) 9301e04c3fSmrg#define BRW_SWIZZLE_XXZZ BRW_SWIZZLE4(0,0,2,2) 9401e04c3fSmrg#define BRW_SWIZZLE_YYWW BRW_SWIZZLE4(1,1,3,3) 9501e04c3fSmrg#define BRW_SWIZZLE_YXWZ BRW_SWIZZLE4(1,0,3,2) 9601e04c3fSmrg 9701e04c3fSmrg#define BRW_SWZ_COMP_INPUT(comp) (BRW_SWIZZLE_XYZW >> ((comp)*2)) 9801e04c3fSmrg#define BRW_SWZ_COMP_OUTPUT(comp) (BRW_SWIZZLE_XYZW << ((comp)*2)) 9901e04c3fSmrg 10001e04c3fSmrgstatic inline bool 10101e04c3fSmrgbrw_is_single_value_swizzle(unsigned swiz) 10201e04c3fSmrg{ 10301e04c3fSmrg return (swiz == BRW_SWIZZLE_XXXX || 10401e04c3fSmrg swiz == BRW_SWIZZLE_YYYY || 10501e04c3fSmrg swiz == BRW_SWIZZLE_ZZZZ || 10601e04c3fSmrg swiz == BRW_SWIZZLE_WWWW); 10701e04c3fSmrg} 10801e04c3fSmrg 10901e04c3fSmrg/** 11001e04c3fSmrg * Compute the swizzle obtained from the application of \p swz0 on the result 11101e04c3fSmrg * of \p swz1. The argument ordering is expected to match function 11201e04c3fSmrg * composition. 11301e04c3fSmrg */ 11401e04c3fSmrgstatic inline unsigned 11501e04c3fSmrgbrw_compose_swizzle(unsigned swz0, unsigned swz1) 11601e04c3fSmrg{ 11701e04c3fSmrg return BRW_SWIZZLE4( 11801e04c3fSmrg BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)), 11901e04c3fSmrg BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)), 12001e04c3fSmrg BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)), 12101e04c3fSmrg BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3))); 12201e04c3fSmrg} 12301e04c3fSmrg 12401e04c3fSmrg/** 12501e04c3fSmrg * Return the result of applying swizzle \p swz to shuffle the bits of \p mask 12601e04c3fSmrg * (AKA image). 12701e04c3fSmrg */ 12801e04c3fSmrgstatic inline unsigned 12901e04c3fSmrgbrw_apply_swizzle_to_mask(unsigned swz, unsigned mask) 13001e04c3fSmrg{ 13101e04c3fSmrg unsigned result = 0; 13201e04c3fSmrg 13301e04c3fSmrg for (unsigned i = 0; i < 4; i++) { 13401e04c3fSmrg if (mask & (1 << BRW_GET_SWZ(swz, i))) 13501e04c3fSmrg result |= 1 << i; 13601e04c3fSmrg } 13701e04c3fSmrg 13801e04c3fSmrg return result; 13901e04c3fSmrg} 14001e04c3fSmrg 14101e04c3fSmrg/** 14201e04c3fSmrg * Return the result of applying the inverse of swizzle \p swz to shuffle the 14301e04c3fSmrg * bits of \p mask (AKA preimage). Useful to find out which components are 14401e04c3fSmrg * read from a swizzled source given the instruction writemask. 14501e04c3fSmrg */ 14601e04c3fSmrgstatic inline unsigned 14701e04c3fSmrgbrw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask) 14801e04c3fSmrg{ 14901e04c3fSmrg unsigned result = 0; 15001e04c3fSmrg 15101e04c3fSmrg for (unsigned i = 0; i < 4; i++) { 15201e04c3fSmrg if (mask & (1 << i)) 15301e04c3fSmrg result |= 1 << BRW_GET_SWZ(swz, i); 15401e04c3fSmrg } 15501e04c3fSmrg 15601e04c3fSmrg return result; 15701e04c3fSmrg} 15801e04c3fSmrg 15901e04c3fSmrg/** 16001e04c3fSmrg * Construct an identity swizzle for the set of enabled channels given by \p 16101e04c3fSmrg * mask. The result will only reference channels enabled in the provided \p 16201e04c3fSmrg * mask, assuming that \p mask is non-zero. The constructed swizzle will 16301e04c3fSmrg * satisfy the property that for any instruction OP and any mask: 16401e04c3fSmrg * 16501e04c3fSmrg * brw_OP(p, brw_writemask(dst, mask), 16601e04c3fSmrg * brw_swizzle(src, brw_swizzle_for_mask(mask))); 16701e04c3fSmrg * 16801e04c3fSmrg * will be equivalent to the same instruction without swizzle: 16901e04c3fSmrg * 17001e04c3fSmrg * brw_OP(p, brw_writemask(dst, mask), src); 17101e04c3fSmrg */ 17201e04c3fSmrgstatic inline unsigned 17301e04c3fSmrgbrw_swizzle_for_mask(unsigned mask) 17401e04c3fSmrg{ 17501e04c3fSmrg unsigned last = (mask ? ffs(mask) - 1 : 0); 17601e04c3fSmrg unsigned swz[4]; 17701e04c3fSmrg 17801e04c3fSmrg for (unsigned i = 0; i < 4; i++) 17901e04c3fSmrg last = swz[i] = (mask & (1 << i) ? i : last); 18001e04c3fSmrg 18101e04c3fSmrg return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); 18201e04c3fSmrg} 18301e04c3fSmrg 18401e04c3fSmrg/** 18501e04c3fSmrg * Construct an identity swizzle for the first \p n components of a vector. 18601e04c3fSmrg * When only a subset of channels of a vec4 are used we don't want to 18701e04c3fSmrg * reference the other channels, as that will tell optimization passes that 18801e04c3fSmrg * those other channels are used. 18901e04c3fSmrg */ 19001e04c3fSmrgstatic inline unsigned 19101e04c3fSmrgbrw_swizzle_for_size(unsigned n) 19201e04c3fSmrg{ 19301e04c3fSmrg return brw_swizzle_for_mask((1 << n) - 1); 19401e04c3fSmrg} 19501e04c3fSmrg 19601e04c3fSmrg/** 19701e04c3fSmrg * Converse of brw_swizzle_for_mask(). Returns the mask of components 19801e04c3fSmrg * accessed by the specified swizzle \p swz. 19901e04c3fSmrg */ 20001e04c3fSmrgstatic inline unsigned 20101e04c3fSmrgbrw_mask_for_swizzle(unsigned swz) 20201e04c3fSmrg{ 20301e04c3fSmrg return brw_apply_inv_swizzle_to_mask(swz, ~0); 20401e04c3fSmrg} 20501e04c3fSmrg 20601e04c3fSmrguint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz); 20701e04c3fSmrg 20801e04c3fSmrg#define REG_SIZE (8*4) 20901e04c3fSmrg 21001e04c3fSmrg/* These aren't hardware structs, just something useful for us to pass around: 21101e04c3fSmrg * 21201e04c3fSmrg * Align1 operation has a lot of control over input ranges. Used in 21301e04c3fSmrg * WM programs to implement shaders decomposed into "channel serial" 21401e04c3fSmrg * or "structure of array" form: 21501e04c3fSmrg */ 21601e04c3fSmrgstruct brw_reg { 21701e04c3fSmrg union { 21801e04c3fSmrg struct { 21901e04c3fSmrg enum brw_reg_type type:4; 22001e04c3fSmrg enum brw_reg_file file:3; /* :2 hardware format */ 22101e04c3fSmrg unsigned negate:1; /* source only */ 22201e04c3fSmrg unsigned abs:1; /* source only */ 22301e04c3fSmrg unsigned address_mode:1; /* relative addressing, hopefully! */ 2249f464c52Smaya unsigned pad0:17; 22501e04c3fSmrg unsigned subnr:5; /* :1 in align16 */ 22601e04c3fSmrg }; 22701e04c3fSmrg uint32_t bits; 22801e04c3fSmrg }; 22901e04c3fSmrg 23001e04c3fSmrg union { 23101e04c3fSmrg struct { 2329f464c52Smaya unsigned nr; 23301e04c3fSmrg unsigned swizzle:8; /* src only, align16 only */ 23401e04c3fSmrg unsigned writemask:4; /* dest only, align16 only */ 23501e04c3fSmrg int indirect_offset:10; /* relative addressing offset */ 23601e04c3fSmrg unsigned vstride:4; /* source only */ 23701e04c3fSmrg unsigned width:3; /* src only, align1 only */ 23801e04c3fSmrg unsigned hstride:2; /* align1 only */ 23901e04c3fSmrg unsigned pad1:1; 24001e04c3fSmrg }; 24101e04c3fSmrg 24201e04c3fSmrg double df; 24301e04c3fSmrg uint64_t u64; 24401e04c3fSmrg int64_t d64; 24501e04c3fSmrg float f; 24601e04c3fSmrg int d; 24701e04c3fSmrg unsigned ud; 24801e04c3fSmrg }; 24901e04c3fSmrg}; 25001e04c3fSmrg 25101e04c3fSmrgstatic inline bool 25201e04c3fSmrgbrw_regs_equal(const struct brw_reg *a, const struct brw_reg *b) 25301e04c3fSmrg{ 2549f464c52Smaya return a->bits == b->bits && a->u64 == b->u64; 25501e04c3fSmrg} 25601e04c3fSmrg 25701e04c3fSmrgstatic inline bool 25801e04c3fSmrgbrw_regs_negative_equal(const struct brw_reg *a, const struct brw_reg *b) 25901e04c3fSmrg{ 26001e04c3fSmrg if (a->file == IMM) { 26101e04c3fSmrg if (a->bits != b->bits) 26201e04c3fSmrg return false; 26301e04c3fSmrg 26401e04c3fSmrg switch ((enum brw_reg_type) a->type) { 26501e04c3fSmrg case BRW_REGISTER_TYPE_UQ: 26601e04c3fSmrg case BRW_REGISTER_TYPE_Q: 26701e04c3fSmrg return a->d64 == -b->d64; 26801e04c3fSmrg case BRW_REGISTER_TYPE_DF: 26901e04c3fSmrg return a->df == -b->df; 27001e04c3fSmrg case BRW_REGISTER_TYPE_UD: 27101e04c3fSmrg case BRW_REGISTER_TYPE_D: 27201e04c3fSmrg return a->d == -b->d; 27301e04c3fSmrg case BRW_REGISTER_TYPE_F: 27401e04c3fSmrg return a->f == -b->f; 27501e04c3fSmrg case BRW_REGISTER_TYPE_VF: 27601e04c3fSmrg /* It is tempting to treat 0 as a negation of 0 (and -0 as a negation 27701e04c3fSmrg * of -0). There are occasions where 0 or -0 is used and the exact 27801e04c3fSmrg * bit pattern is desired. At the very least, changing this to allow 27901e04c3fSmrg * 0 as a negation of 0 causes some fp64 tests to fail on IVB. 28001e04c3fSmrg */ 28101e04c3fSmrg return a->ud == (b->ud ^ 0x80808080); 28201e04c3fSmrg case BRW_REGISTER_TYPE_UW: 28301e04c3fSmrg case BRW_REGISTER_TYPE_W: 28401e04c3fSmrg case BRW_REGISTER_TYPE_UV: 28501e04c3fSmrg case BRW_REGISTER_TYPE_V: 28601e04c3fSmrg case BRW_REGISTER_TYPE_HF: 28701e04c3fSmrg /* FINISHME: Implement support for these types once there is 28801e04c3fSmrg * something in the compiler that can generate them. Until then, 28901e04c3fSmrg * they cannot be tested. 29001e04c3fSmrg */ 29101e04c3fSmrg return false; 29201e04c3fSmrg case BRW_REGISTER_TYPE_UB: 29301e04c3fSmrg case BRW_REGISTER_TYPE_B: 29401e04c3fSmrg case BRW_REGISTER_TYPE_NF: 29501e04c3fSmrg default: 29601e04c3fSmrg unreachable("not reached"); 29701e04c3fSmrg } 29801e04c3fSmrg } else { 29901e04c3fSmrg struct brw_reg tmp = *a; 30001e04c3fSmrg 30101e04c3fSmrg tmp.negate = !tmp.negate; 30201e04c3fSmrg 30301e04c3fSmrg return brw_regs_equal(&tmp, b); 30401e04c3fSmrg } 30501e04c3fSmrg} 30601e04c3fSmrg 30701e04c3fSmrgstruct brw_indirect { 30801e04c3fSmrg unsigned addr_subnr:4; 30901e04c3fSmrg int addr_offset:10; 31001e04c3fSmrg unsigned pad:18; 31101e04c3fSmrg}; 31201e04c3fSmrg 31301e04c3fSmrg 31401e04c3fSmrgstatic inline unsigned 31501e04c3fSmrgtype_sz(unsigned type) 31601e04c3fSmrg{ 31701e04c3fSmrg switch(type) { 31801e04c3fSmrg case BRW_REGISTER_TYPE_UQ: 31901e04c3fSmrg case BRW_REGISTER_TYPE_Q: 32001e04c3fSmrg case BRW_REGISTER_TYPE_DF: 3217ec681f3Smrg case BRW_REGISTER_TYPE_NF: 32201e04c3fSmrg return 8; 32301e04c3fSmrg case BRW_REGISTER_TYPE_UD: 32401e04c3fSmrg case BRW_REGISTER_TYPE_D: 32501e04c3fSmrg case BRW_REGISTER_TYPE_F: 32601e04c3fSmrg case BRW_REGISTER_TYPE_VF: 32701e04c3fSmrg return 4; 32801e04c3fSmrg case BRW_REGISTER_TYPE_UW: 32901e04c3fSmrg case BRW_REGISTER_TYPE_W: 3307ec681f3Smrg case BRW_REGISTER_TYPE_HF: 3317ec681f3Smrg /* [U]V components are 4-bit, but HW unpacks them to 16-bit (2 bytes) */ 33201e04c3fSmrg case BRW_REGISTER_TYPE_UV: 33301e04c3fSmrg case BRW_REGISTER_TYPE_V: 33401e04c3fSmrg return 2; 33501e04c3fSmrg case BRW_REGISTER_TYPE_UB: 33601e04c3fSmrg case BRW_REGISTER_TYPE_B: 33701e04c3fSmrg return 1; 33801e04c3fSmrg default: 33901e04c3fSmrg unreachable("not reached"); 34001e04c3fSmrg } 34101e04c3fSmrg} 34201e04c3fSmrg 34301e04c3fSmrgstatic inline enum brw_reg_type 34401e04c3fSmrgget_exec_type(const enum brw_reg_type type) 34501e04c3fSmrg{ 34601e04c3fSmrg switch (type) { 34701e04c3fSmrg case BRW_REGISTER_TYPE_B: 34801e04c3fSmrg case BRW_REGISTER_TYPE_V: 34901e04c3fSmrg return BRW_REGISTER_TYPE_W; 35001e04c3fSmrg case BRW_REGISTER_TYPE_UB: 35101e04c3fSmrg case BRW_REGISTER_TYPE_UV: 35201e04c3fSmrg return BRW_REGISTER_TYPE_UW; 35301e04c3fSmrg case BRW_REGISTER_TYPE_VF: 35401e04c3fSmrg return BRW_REGISTER_TYPE_F; 35501e04c3fSmrg default: 35601e04c3fSmrg return type; 35701e04c3fSmrg } 35801e04c3fSmrg} 35901e04c3fSmrg 36001e04c3fSmrg/** 36101e04c3fSmrg * Return an integer type of the requested size and signedness. 36201e04c3fSmrg */ 36301e04c3fSmrgstatic inline enum brw_reg_type 36401e04c3fSmrgbrw_int_type(unsigned sz, bool is_signed) 36501e04c3fSmrg{ 36601e04c3fSmrg switch (sz) { 36701e04c3fSmrg case 1: 36801e04c3fSmrg return (is_signed ? BRW_REGISTER_TYPE_B : BRW_REGISTER_TYPE_UB); 36901e04c3fSmrg case 2: 37001e04c3fSmrg return (is_signed ? BRW_REGISTER_TYPE_W : BRW_REGISTER_TYPE_UW); 37101e04c3fSmrg case 4: 37201e04c3fSmrg return (is_signed ? BRW_REGISTER_TYPE_D : BRW_REGISTER_TYPE_UD); 37301e04c3fSmrg case 8: 37401e04c3fSmrg return (is_signed ? BRW_REGISTER_TYPE_Q : BRW_REGISTER_TYPE_UQ); 37501e04c3fSmrg default: 37601e04c3fSmrg unreachable("Not reached."); 37701e04c3fSmrg } 37801e04c3fSmrg} 37901e04c3fSmrg 38001e04c3fSmrg/** 38101e04c3fSmrg * Construct a brw_reg. 38201e04c3fSmrg * \param file one of the BRW_x_REGISTER_FILE values 38301e04c3fSmrg * \param nr register number/index 38401e04c3fSmrg * \param subnr register sub number 38501e04c3fSmrg * \param negate register negate modifier 38601e04c3fSmrg * \param abs register abs modifier 38701e04c3fSmrg * \param type one of BRW_REGISTER_TYPE_x 38801e04c3fSmrg * \param vstride one of BRW_VERTICAL_STRIDE_x 38901e04c3fSmrg * \param width one of BRW_WIDTH_x 39001e04c3fSmrg * \param hstride one of BRW_HORIZONTAL_STRIDE_x 39101e04c3fSmrg * \param swizzle one of BRW_SWIZZLE_x 39201e04c3fSmrg * \param writemask WRITEMASK_X/Y/Z/W bitfield 39301e04c3fSmrg */ 39401e04c3fSmrgstatic inline struct brw_reg 39501e04c3fSmrgbrw_reg(enum brw_reg_file file, 39601e04c3fSmrg unsigned nr, 39701e04c3fSmrg unsigned subnr, 39801e04c3fSmrg unsigned negate, 39901e04c3fSmrg unsigned abs, 40001e04c3fSmrg enum brw_reg_type type, 40101e04c3fSmrg unsigned vstride, 40201e04c3fSmrg unsigned width, 40301e04c3fSmrg unsigned hstride, 40401e04c3fSmrg unsigned swizzle, 40501e04c3fSmrg unsigned writemask) 40601e04c3fSmrg{ 40701e04c3fSmrg struct brw_reg reg; 40801e04c3fSmrg if (file == BRW_GENERAL_REGISTER_FILE) 40901e04c3fSmrg assert(nr < BRW_MAX_GRF); 41001e04c3fSmrg else if (file == BRW_ARCHITECTURE_REGISTER_FILE) 41101e04c3fSmrg assert(nr <= BRW_ARF_TIMESTAMP); 41201e04c3fSmrg /* Asserting on the MRF register number requires to know the hardware gen 4137ec681f3Smrg * (gfx6 has 24 MRF registers), which we don't know here, so we assert 41401e04c3fSmrg * for that in the generators and in brw_eu_emit.c 41501e04c3fSmrg */ 41601e04c3fSmrg 41701e04c3fSmrg reg.type = type; 41801e04c3fSmrg reg.file = file; 41901e04c3fSmrg reg.negate = negate; 42001e04c3fSmrg reg.abs = abs; 42101e04c3fSmrg reg.address_mode = BRW_ADDRESS_DIRECT; 42201e04c3fSmrg reg.pad0 = 0; 42301e04c3fSmrg reg.subnr = subnr * type_sz(type); 42401e04c3fSmrg reg.nr = nr; 42501e04c3fSmrg 42601e04c3fSmrg /* Could do better: If the reg is r5.3<0;1,0>, we probably want to 42701e04c3fSmrg * set swizzle and writemask to W, as the lower bits of subnr will 42801e04c3fSmrg * be lost when converted to align16. This is probably too much to 42901e04c3fSmrg * keep track of as you'd want it adjusted by suboffset(), etc. 43001e04c3fSmrg * Perhaps fix up when converting to align16? 43101e04c3fSmrg */ 43201e04c3fSmrg reg.swizzle = swizzle; 43301e04c3fSmrg reg.writemask = writemask; 43401e04c3fSmrg reg.indirect_offset = 0; 43501e04c3fSmrg reg.vstride = vstride; 43601e04c3fSmrg reg.width = width; 43701e04c3fSmrg reg.hstride = hstride; 43801e04c3fSmrg reg.pad1 = 0; 43901e04c3fSmrg return reg; 44001e04c3fSmrg} 44101e04c3fSmrg 44201e04c3fSmrg/** Construct float[16] register */ 44301e04c3fSmrgstatic inline struct brw_reg 44401e04c3fSmrgbrw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 44501e04c3fSmrg{ 44601e04c3fSmrg return brw_reg(file, 44701e04c3fSmrg nr, 44801e04c3fSmrg subnr, 44901e04c3fSmrg 0, 45001e04c3fSmrg 0, 45101e04c3fSmrg BRW_REGISTER_TYPE_F, 45201e04c3fSmrg BRW_VERTICAL_STRIDE_16, 45301e04c3fSmrg BRW_WIDTH_16, 45401e04c3fSmrg BRW_HORIZONTAL_STRIDE_1, 45501e04c3fSmrg BRW_SWIZZLE_XYZW, 45601e04c3fSmrg WRITEMASK_XYZW); 45701e04c3fSmrg} 45801e04c3fSmrg 45901e04c3fSmrg/** Construct float[8] register */ 46001e04c3fSmrgstatic inline struct brw_reg 46101e04c3fSmrgbrw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 46201e04c3fSmrg{ 46301e04c3fSmrg return brw_reg(file, 46401e04c3fSmrg nr, 46501e04c3fSmrg subnr, 46601e04c3fSmrg 0, 46701e04c3fSmrg 0, 46801e04c3fSmrg BRW_REGISTER_TYPE_F, 46901e04c3fSmrg BRW_VERTICAL_STRIDE_8, 47001e04c3fSmrg BRW_WIDTH_8, 47101e04c3fSmrg BRW_HORIZONTAL_STRIDE_1, 47201e04c3fSmrg BRW_SWIZZLE_XYZW, 47301e04c3fSmrg WRITEMASK_XYZW); 47401e04c3fSmrg} 47501e04c3fSmrg 47601e04c3fSmrg/** Construct float[4] register */ 47701e04c3fSmrgstatic inline struct brw_reg 47801e04c3fSmrgbrw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 47901e04c3fSmrg{ 48001e04c3fSmrg return brw_reg(file, 48101e04c3fSmrg nr, 48201e04c3fSmrg subnr, 48301e04c3fSmrg 0, 48401e04c3fSmrg 0, 48501e04c3fSmrg BRW_REGISTER_TYPE_F, 48601e04c3fSmrg BRW_VERTICAL_STRIDE_4, 48701e04c3fSmrg BRW_WIDTH_4, 48801e04c3fSmrg BRW_HORIZONTAL_STRIDE_1, 48901e04c3fSmrg BRW_SWIZZLE_XYZW, 49001e04c3fSmrg WRITEMASK_XYZW); 49101e04c3fSmrg} 49201e04c3fSmrg 49301e04c3fSmrg/** Construct float[2] register */ 49401e04c3fSmrgstatic inline struct brw_reg 49501e04c3fSmrgbrw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 49601e04c3fSmrg{ 49701e04c3fSmrg return brw_reg(file, 49801e04c3fSmrg nr, 49901e04c3fSmrg subnr, 50001e04c3fSmrg 0, 50101e04c3fSmrg 0, 50201e04c3fSmrg BRW_REGISTER_TYPE_F, 50301e04c3fSmrg BRW_VERTICAL_STRIDE_2, 50401e04c3fSmrg BRW_WIDTH_2, 50501e04c3fSmrg BRW_HORIZONTAL_STRIDE_1, 50601e04c3fSmrg BRW_SWIZZLE_XYXY, 50701e04c3fSmrg WRITEMASK_XY); 50801e04c3fSmrg} 50901e04c3fSmrg 51001e04c3fSmrg/** Construct float[1] register */ 51101e04c3fSmrgstatic inline struct brw_reg 51201e04c3fSmrgbrw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 51301e04c3fSmrg{ 51401e04c3fSmrg return brw_reg(file, 51501e04c3fSmrg nr, 51601e04c3fSmrg subnr, 51701e04c3fSmrg 0, 51801e04c3fSmrg 0, 51901e04c3fSmrg BRW_REGISTER_TYPE_F, 52001e04c3fSmrg BRW_VERTICAL_STRIDE_0, 52101e04c3fSmrg BRW_WIDTH_1, 52201e04c3fSmrg BRW_HORIZONTAL_STRIDE_0, 52301e04c3fSmrg BRW_SWIZZLE_XXXX, 52401e04c3fSmrg WRITEMASK_X); 52501e04c3fSmrg} 52601e04c3fSmrg 52701e04c3fSmrgstatic inline struct brw_reg 52801e04c3fSmrgbrw_vecn_reg(unsigned width, enum brw_reg_file file, 52901e04c3fSmrg unsigned nr, unsigned subnr) 53001e04c3fSmrg{ 53101e04c3fSmrg switch (width) { 53201e04c3fSmrg case 1: 53301e04c3fSmrg return brw_vec1_reg(file, nr, subnr); 53401e04c3fSmrg case 2: 53501e04c3fSmrg return brw_vec2_reg(file, nr, subnr); 53601e04c3fSmrg case 4: 53701e04c3fSmrg return brw_vec4_reg(file, nr, subnr); 53801e04c3fSmrg case 8: 53901e04c3fSmrg return brw_vec8_reg(file, nr, subnr); 54001e04c3fSmrg case 16: 54101e04c3fSmrg return brw_vec16_reg(file, nr, subnr); 54201e04c3fSmrg default: 54301e04c3fSmrg unreachable("Invalid register width"); 54401e04c3fSmrg } 54501e04c3fSmrg} 54601e04c3fSmrg 54701e04c3fSmrgstatic inline struct brw_reg 54801e04c3fSmrgretype(struct brw_reg reg, enum brw_reg_type type) 54901e04c3fSmrg{ 55001e04c3fSmrg reg.type = type; 55101e04c3fSmrg return reg; 55201e04c3fSmrg} 55301e04c3fSmrg 55401e04c3fSmrgstatic inline struct brw_reg 55501e04c3fSmrgfirsthalf(struct brw_reg reg) 55601e04c3fSmrg{ 55701e04c3fSmrg return reg; 55801e04c3fSmrg} 55901e04c3fSmrg 56001e04c3fSmrgstatic inline struct brw_reg 56101e04c3fSmrgsechalf(struct brw_reg reg) 56201e04c3fSmrg{ 56301e04c3fSmrg if (reg.vstride) 56401e04c3fSmrg reg.nr++; 56501e04c3fSmrg return reg; 56601e04c3fSmrg} 56701e04c3fSmrg 56801e04c3fSmrgstatic inline struct brw_reg 56901e04c3fSmrgoffset(struct brw_reg reg, unsigned delta) 57001e04c3fSmrg{ 57101e04c3fSmrg reg.nr += delta; 57201e04c3fSmrg return reg; 57301e04c3fSmrg} 57401e04c3fSmrg 57501e04c3fSmrg 57601e04c3fSmrgstatic inline struct brw_reg 57701e04c3fSmrgbyte_offset(struct brw_reg reg, unsigned bytes) 57801e04c3fSmrg{ 57901e04c3fSmrg unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes; 58001e04c3fSmrg reg.nr = newoffset / REG_SIZE; 58101e04c3fSmrg reg.subnr = newoffset % REG_SIZE; 58201e04c3fSmrg return reg; 58301e04c3fSmrg} 58401e04c3fSmrg 58501e04c3fSmrgstatic inline struct brw_reg 58601e04c3fSmrgsuboffset(struct brw_reg reg, unsigned delta) 58701e04c3fSmrg{ 58801e04c3fSmrg return byte_offset(reg, delta * type_sz(reg.type)); 58901e04c3fSmrg} 59001e04c3fSmrg 59101e04c3fSmrg/** Construct unsigned word[16] register */ 59201e04c3fSmrgstatic inline struct brw_reg 59301e04c3fSmrgbrw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 59401e04c3fSmrg{ 59501e04c3fSmrg return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); 59601e04c3fSmrg} 59701e04c3fSmrg 59801e04c3fSmrg/** Construct unsigned word[8] register */ 59901e04c3fSmrgstatic inline struct brw_reg 60001e04c3fSmrgbrw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 60101e04c3fSmrg{ 60201e04c3fSmrg return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); 60301e04c3fSmrg} 60401e04c3fSmrg 60501e04c3fSmrg/** Construct unsigned word[1] register */ 60601e04c3fSmrgstatic inline struct brw_reg 60701e04c3fSmrgbrw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 60801e04c3fSmrg{ 60901e04c3fSmrg return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr); 61001e04c3fSmrg} 61101e04c3fSmrg 61201e04c3fSmrgstatic inline struct brw_reg 61301e04c3fSmrgbrw_ud1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr) 61401e04c3fSmrg{ 61501e04c3fSmrg return retype(brw_vec1_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD); 61601e04c3fSmrg} 61701e04c3fSmrg 61801e04c3fSmrgstatic inline struct brw_reg 61901e04c3fSmrgbrw_imm_reg(enum brw_reg_type type) 62001e04c3fSmrg{ 62101e04c3fSmrg return brw_reg(BRW_IMMEDIATE_VALUE, 62201e04c3fSmrg 0, 62301e04c3fSmrg 0, 62401e04c3fSmrg 0, 62501e04c3fSmrg 0, 62601e04c3fSmrg type, 62701e04c3fSmrg BRW_VERTICAL_STRIDE_0, 62801e04c3fSmrg BRW_WIDTH_1, 62901e04c3fSmrg BRW_HORIZONTAL_STRIDE_0, 63001e04c3fSmrg 0, 63101e04c3fSmrg 0); 63201e04c3fSmrg} 63301e04c3fSmrg 63401e04c3fSmrg/** Construct float immediate register */ 63501e04c3fSmrgstatic inline struct brw_reg 63601e04c3fSmrgbrw_imm_df(double df) 63701e04c3fSmrg{ 63801e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_DF); 63901e04c3fSmrg imm.df = df; 64001e04c3fSmrg return imm; 64101e04c3fSmrg} 64201e04c3fSmrg 64301e04c3fSmrgstatic inline struct brw_reg 64401e04c3fSmrgbrw_imm_u64(uint64_t u64) 64501e04c3fSmrg{ 64601e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ); 64701e04c3fSmrg imm.u64 = u64; 64801e04c3fSmrg return imm; 64901e04c3fSmrg} 65001e04c3fSmrg 65101e04c3fSmrgstatic inline struct brw_reg 65201e04c3fSmrgbrw_imm_f(float f) 65301e04c3fSmrg{ 65401e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F); 65501e04c3fSmrg imm.f = f; 65601e04c3fSmrg return imm; 65701e04c3fSmrg} 65801e04c3fSmrg 65901e04c3fSmrg/** Construct int64_t immediate register */ 66001e04c3fSmrgstatic inline struct brw_reg 66101e04c3fSmrgbrw_imm_q(int64_t q) 66201e04c3fSmrg{ 66301e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_Q); 66401e04c3fSmrg imm.d64 = q; 66501e04c3fSmrg return imm; 66601e04c3fSmrg} 66701e04c3fSmrg 66801e04c3fSmrg/** Construct int64_t immediate register */ 66901e04c3fSmrgstatic inline struct brw_reg 67001e04c3fSmrgbrw_imm_uq(uint64_t uq) 67101e04c3fSmrg{ 67201e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ); 67301e04c3fSmrg imm.u64 = uq; 67401e04c3fSmrg return imm; 67501e04c3fSmrg} 67601e04c3fSmrg 67701e04c3fSmrg/** Construct integer immediate register */ 67801e04c3fSmrgstatic inline struct brw_reg 67901e04c3fSmrgbrw_imm_d(int d) 68001e04c3fSmrg{ 68101e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D); 68201e04c3fSmrg imm.d = d; 68301e04c3fSmrg return imm; 68401e04c3fSmrg} 68501e04c3fSmrg 68601e04c3fSmrg/** Construct uint immediate register */ 68701e04c3fSmrgstatic inline struct brw_reg 68801e04c3fSmrgbrw_imm_ud(unsigned ud) 68901e04c3fSmrg{ 69001e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD); 69101e04c3fSmrg imm.ud = ud; 69201e04c3fSmrg return imm; 69301e04c3fSmrg} 69401e04c3fSmrg 69501e04c3fSmrg/** Construct ushort immediate register */ 69601e04c3fSmrgstatic inline struct brw_reg 69701e04c3fSmrgbrw_imm_uw(uint16_t uw) 69801e04c3fSmrg{ 69901e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW); 70001e04c3fSmrg imm.ud = uw | (uw << 16); 70101e04c3fSmrg return imm; 70201e04c3fSmrg} 70301e04c3fSmrg 70401e04c3fSmrg/** Construct short immediate register */ 70501e04c3fSmrgstatic inline struct brw_reg 70601e04c3fSmrgbrw_imm_w(int16_t w) 70701e04c3fSmrg{ 70801e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W); 70901e04c3fSmrg imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16; 71001e04c3fSmrg return imm; 71101e04c3fSmrg} 71201e04c3fSmrg 71301e04c3fSmrg/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type 71401e04c3fSmrg * numbers alias with _V and _VF below: 71501e04c3fSmrg */ 71601e04c3fSmrg 71701e04c3fSmrg/** Construct vector of eight signed half-byte values */ 71801e04c3fSmrgstatic inline struct brw_reg 71901e04c3fSmrgbrw_imm_v(unsigned v) 72001e04c3fSmrg{ 72101e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V); 72201e04c3fSmrg imm.ud = v; 72301e04c3fSmrg return imm; 72401e04c3fSmrg} 72501e04c3fSmrg 72601e04c3fSmrg/** Construct vector of eight unsigned half-byte values */ 72701e04c3fSmrgstatic inline struct brw_reg 72801e04c3fSmrgbrw_imm_uv(unsigned uv) 72901e04c3fSmrg{ 73001e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV); 73101e04c3fSmrg imm.ud = uv; 73201e04c3fSmrg return imm; 73301e04c3fSmrg} 73401e04c3fSmrg 73501e04c3fSmrg/** Construct vector of four 8-bit float values */ 73601e04c3fSmrgstatic inline struct brw_reg 73701e04c3fSmrgbrw_imm_vf(unsigned v) 73801e04c3fSmrg{ 73901e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); 74001e04c3fSmrg imm.ud = v; 74101e04c3fSmrg return imm; 74201e04c3fSmrg} 74301e04c3fSmrg 74401e04c3fSmrgstatic inline struct brw_reg 74501e04c3fSmrgbrw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3) 74601e04c3fSmrg{ 74701e04c3fSmrg struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF); 74801e04c3fSmrg imm.vstride = BRW_VERTICAL_STRIDE_0; 74901e04c3fSmrg imm.width = BRW_WIDTH_4; 75001e04c3fSmrg imm.hstride = BRW_HORIZONTAL_STRIDE_1; 75101e04c3fSmrg imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24)); 75201e04c3fSmrg return imm; 75301e04c3fSmrg} 75401e04c3fSmrg 75501e04c3fSmrg 75601e04c3fSmrgstatic inline struct brw_reg 75701e04c3fSmrgbrw_address(struct brw_reg reg) 75801e04c3fSmrg{ 75901e04c3fSmrg return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr); 76001e04c3fSmrg} 76101e04c3fSmrg 76201e04c3fSmrg/** Construct float[1] general-purpose register */ 76301e04c3fSmrgstatic inline struct brw_reg 76401e04c3fSmrgbrw_vec1_grf(unsigned nr, unsigned subnr) 76501e04c3fSmrg{ 76601e04c3fSmrg return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 76701e04c3fSmrg} 76801e04c3fSmrg 76901e04c3fSmrg/** Construct float[2] general-purpose register */ 77001e04c3fSmrgstatic inline struct brw_reg 77101e04c3fSmrgbrw_vec2_grf(unsigned nr, unsigned subnr) 77201e04c3fSmrg{ 77301e04c3fSmrg return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 77401e04c3fSmrg} 77501e04c3fSmrg 77601e04c3fSmrg/** Construct float[4] general-purpose register */ 77701e04c3fSmrgstatic inline struct brw_reg 77801e04c3fSmrgbrw_vec4_grf(unsigned nr, unsigned subnr) 77901e04c3fSmrg{ 78001e04c3fSmrg return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 78101e04c3fSmrg} 78201e04c3fSmrg 78301e04c3fSmrg/** Construct float[8] general-purpose register */ 78401e04c3fSmrgstatic inline struct brw_reg 78501e04c3fSmrgbrw_vec8_grf(unsigned nr, unsigned subnr) 78601e04c3fSmrg{ 78701e04c3fSmrg return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 78801e04c3fSmrg} 78901e04c3fSmrg 79001e04c3fSmrg/** Construct float[16] general-purpose register */ 79101e04c3fSmrgstatic inline struct brw_reg 79201e04c3fSmrgbrw_vec16_grf(unsigned nr, unsigned subnr) 79301e04c3fSmrg{ 79401e04c3fSmrg return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 79501e04c3fSmrg} 79601e04c3fSmrg 79701e04c3fSmrgstatic inline struct brw_reg 79801e04c3fSmrgbrw_vecn_grf(unsigned width, unsigned nr, unsigned subnr) 79901e04c3fSmrg{ 80001e04c3fSmrg return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr, subnr); 80101e04c3fSmrg} 80201e04c3fSmrg 80301e04c3fSmrg 80401e04c3fSmrgstatic inline struct brw_reg 80501e04c3fSmrgbrw_uw8_grf(unsigned nr, unsigned subnr) 80601e04c3fSmrg{ 80701e04c3fSmrg return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 80801e04c3fSmrg} 80901e04c3fSmrg 81001e04c3fSmrgstatic inline struct brw_reg 81101e04c3fSmrgbrw_uw16_grf(unsigned nr, unsigned subnr) 81201e04c3fSmrg{ 81301e04c3fSmrg return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr); 81401e04c3fSmrg} 81501e04c3fSmrg 81601e04c3fSmrg 81701e04c3fSmrg/** Construct null register (usually used for setting condition codes) */ 81801e04c3fSmrgstatic inline struct brw_reg 81901e04c3fSmrgbrw_null_reg(void) 82001e04c3fSmrg{ 82101e04c3fSmrg return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0); 82201e04c3fSmrg} 82301e04c3fSmrg 82401e04c3fSmrgstatic inline struct brw_reg 82501e04c3fSmrgbrw_null_vec(unsigned width) 82601e04c3fSmrg{ 82701e04c3fSmrg return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0); 82801e04c3fSmrg} 82901e04c3fSmrg 83001e04c3fSmrgstatic inline struct brw_reg 83101e04c3fSmrgbrw_address_reg(unsigned subnr) 83201e04c3fSmrg{ 83301e04c3fSmrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr); 83401e04c3fSmrg} 83501e04c3fSmrg 83601e04c3fSmrgstatic inline struct brw_reg 83701e04c3fSmrgbrw_tdr_reg(void) 83801e04c3fSmrg{ 83901e04c3fSmrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_TDR, 0); 84001e04c3fSmrg} 84101e04c3fSmrg 84201e04c3fSmrg/* If/else instructions break in align16 mode if writemask & swizzle 84301e04c3fSmrg * aren't xyzw. This goes against the convention for other scalar 84401e04c3fSmrg * regs: 84501e04c3fSmrg */ 84601e04c3fSmrgstatic inline struct brw_reg 84701e04c3fSmrgbrw_ip_reg(void) 84801e04c3fSmrg{ 84901e04c3fSmrg return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, 85001e04c3fSmrg BRW_ARF_IP, 85101e04c3fSmrg 0, 85201e04c3fSmrg 0, 85301e04c3fSmrg 0, 85401e04c3fSmrg BRW_REGISTER_TYPE_UD, 85501e04c3fSmrg BRW_VERTICAL_STRIDE_4, /* ? */ 85601e04c3fSmrg BRW_WIDTH_1, 85701e04c3fSmrg BRW_HORIZONTAL_STRIDE_0, 85801e04c3fSmrg BRW_SWIZZLE_XYZW, /* NOTE! */ 85901e04c3fSmrg WRITEMASK_XYZW); /* NOTE! */ 86001e04c3fSmrg} 86101e04c3fSmrg 86201e04c3fSmrgstatic inline struct brw_reg 86301e04c3fSmrgbrw_notification_reg(void) 86401e04c3fSmrg{ 86501e04c3fSmrg return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE, 86601e04c3fSmrg BRW_ARF_NOTIFICATION_COUNT, 86701e04c3fSmrg 0, 86801e04c3fSmrg 0, 86901e04c3fSmrg 0, 87001e04c3fSmrg BRW_REGISTER_TYPE_UD, 87101e04c3fSmrg BRW_VERTICAL_STRIDE_0, 87201e04c3fSmrg BRW_WIDTH_1, 87301e04c3fSmrg BRW_HORIZONTAL_STRIDE_0, 87401e04c3fSmrg BRW_SWIZZLE_XXXX, 87501e04c3fSmrg WRITEMASK_X); 87601e04c3fSmrg} 87701e04c3fSmrg 87801e04c3fSmrgstatic inline struct brw_reg 87901e04c3fSmrgbrw_cr0_reg(unsigned subnr) 88001e04c3fSmrg{ 88101e04c3fSmrg return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_CONTROL, subnr); 88201e04c3fSmrg} 88301e04c3fSmrg 88401e04c3fSmrgstatic inline struct brw_reg 88501e04c3fSmrgbrw_sr0_reg(unsigned subnr) 88601e04c3fSmrg{ 88701e04c3fSmrg return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr); 88801e04c3fSmrg} 88901e04c3fSmrg 89001e04c3fSmrgstatic inline struct brw_reg 89101e04c3fSmrgbrw_acc_reg(unsigned width) 89201e04c3fSmrg{ 89301e04c3fSmrg return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, 89401e04c3fSmrg BRW_ARF_ACCUMULATOR, 0); 89501e04c3fSmrg} 89601e04c3fSmrg 89701e04c3fSmrgstatic inline struct brw_reg 89801e04c3fSmrgbrw_flag_reg(int reg, int subreg) 89901e04c3fSmrg{ 90001e04c3fSmrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, 90101e04c3fSmrg BRW_ARF_FLAG + reg, subreg); 90201e04c3fSmrg} 90301e04c3fSmrg 90401e04c3fSmrgstatic inline struct brw_reg 90501e04c3fSmrgbrw_flag_subreg(unsigned subreg) 90601e04c3fSmrg{ 90701e04c3fSmrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, 90801e04c3fSmrg BRW_ARF_FLAG + subreg / 2, subreg % 2); 90901e04c3fSmrg} 91001e04c3fSmrg 91101e04c3fSmrg/** 9127ec681f3Smrg * Return the mask register present in Gfx4-5, or the related register present 9137ec681f3Smrg * in Gfx7.5 and later hardware referred to as "channel enable" register in 91401e04c3fSmrg * the documentation. 91501e04c3fSmrg */ 91601e04c3fSmrgstatic inline struct brw_reg 91701e04c3fSmrgbrw_mask_reg(unsigned subnr) 91801e04c3fSmrg{ 91901e04c3fSmrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr); 92001e04c3fSmrg} 92101e04c3fSmrg 92201e04c3fSmrgstatic inline struct brw_reg 92301e04c3fSmrgbrw_vmask_reg() 92401e04c3fSmrg{ 92501e04c3fSmrg return brw_sr0_reg(3); 92601e04c3fSmrg} 92701e04c3fSmrg 92801e04c3fSmrgstatic inline struct brw_reg 92901e04c3fSmrgbrw_dmask_reg() 93001e04c3fSmrg{ 93101e04c3fSmrg return brw_sr0_reg(2); 93201e04c3fSmrg} 93301e04c3fSmrg 9347ec681f3Smrgstatic inline struct brw_reg 9357ec681f3Smrgbrw_mask_stack_reg(unsigned subnr) 9367ec681f3Smrg{ 9377ec681f3Smrg return suboffset(retype(brw_vec16_reg(BRW_ARCHITECTURE_REGISTER_FILE, 9387ec681f3Smrg BRW_ARF_MASK_STACK, 0), 9397ec681f3Smrg BRW_REGISTER_TYPE_UB), subnr); 9407ec681f3Smrg} 9417ec681f3Smrg 9427ec681f3Smrgstatic inline struct brw_reg 9437ec681f3Smrgbrw_mask_stack_depth_reg(unsigned subnr) 9447ec681f3Smrg{ 9457ec681f3Smrg return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, 9467ec681f3Smrg BRW_ARF_MASK_STACK_DEPTH, subnr); 9477ec681f3Smrg} 9487ec681f3Smrg 94901e04c3fSmrgstatic inline struct brw_reg 95001e04c3fSmrgbrw_message_reg(unsigned nr) 95101e04c3fSmrg{ 95201e04c3fSmrg return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0); 95301e04c3fSmrg} 95401e04c3fSmrg 95501e04c3fSmrgstatic inline struct brw_reg 95601e04c3fSmrgbrw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr) 95701e04c3fSmrg{ 95801e04c3fSmrg return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr), 95901e04c3fSmrg BRW_REGISTER_TYPE_UD); 96001e04c3fSmrg} 96101e04c3fSmrg 96201e04c3fSmrg/* This is almost always called with a numeric constant argument, so 96301e04c3fSmrg * make things easy to evaluate at compile time: 96401e04c3fSmrg */ 96501e04c3fSmrgstatic inline unsigned cvt(unsigned val) 96601e04c3fSmrg{ 96701e04c3fSmrg switch (val) { 96801e04c3fSmrg case 0: return 0; 96901e04c3fSmrg case 1: return 1; 97001e04c3fSmrg case 2: return 2; 97101e04c3fSmrg case 4: return 3; 97201e04c3fSmrg case 8: return 4; 97301e04c3fSmrg case 16: return 5; 97401e04c3fSmrg case 32: return 6; 97501e04c3fSmrg } 97601e04c3fSmrg return 0; 97701e04c3fSmrg} 97801e04c3fSmrg 97901e04c3fSmrgstatic inline struct brw_reg 98001e04c3fSmrgstride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride) 98101e04c3fSmrg{ 98201e04c3fSmrg reg.vstride = cvt(vstride); 98301e04c3fSmrg reg.width = cvt(width) - 1; 98401e04c3fSmrg reg.hstride = cvt(hstride); 98501e04c3fSmrg return reg; 98601e04c3fSmrg} 98701e04c3fSmrg 98801e04c3fSmrg/** 98901e04c3fSmrg * Multiply the vertical and horizontal stride of a register by the given 99001e04c3fSmrg * factor \a s. 99101e04c3fSmrg */ 99201e04c3fSmrgstatic inline struct brw_reg 99301e04c3fSmrgspread(struct brw_reg reg, unsigned s) 99401e04c3fSmrg{ 99501e04c3fSmrg if (s) { 9967ec681f3Smrg assert(util_is_power_of_two_nonzero(s)); 99701e04c3fSmrg 99801e04c3fSmrg if (reg.hstride) 99901e04c3fSmrg reg.hstride += cvt(s) - 1; 100001e04c3fSmrg 100101e04c3fSmrg if (reg.vstride) 100201e04c3fSmrg reg.vstride += cvt(s) - 1; 100301e04c3fSmrg 100401e04c3fSmrg return reg; 100501e04c3fSmrg } else { 100601e04c3fSmrg return stride(reg, 0, 1, 0); 100701e04c3fSmrg } 100801e04c3fSmrg} 100901e04c3fSmrg 101001e04c3fSmrg/** 101101e04c3fSmrg * Reinterpret each channel of register \p reg as a vector of values of the 101201e04c3fSmrg * given smaller type and take the i-th subcomponent from each. 101301e04c3fSmrg */ 101401e04c3fSmrgstatic inline struct brw_reg 101501e04c3fSmrgsubscript(struct brw_reg reg, enum brw_reg_type type, unsigned i) 101601e04c3fSmrg{ 101701e04c3fSmrg unsigned scale = type_sz(reg.type) / type_sz(type); 101801e04c3fSmrg assert(scale >= 1 && i < scale); 101901e04c3fSmrg 10207ec681f3Smrg if (reg.file == IMM) { 10217ec681f3Smrg unsigned bit_size = type_sz(type) * 8; 10227ec681f3Smrg reg.u64 >>= i * bit_size; 10237ec681f3Smrg reg.u64 &= BITFIELD64_MASK(bit_size); 10247ec681f3Smrg if (bit_size <= 16) 10257ec681f3Smrg reg.u64 |= reg.u64 << 16; 10267ec681f3Smrg return retype(reg, type); 10277ec681f3Smrg } 10287ec681f3Smrg 102901e04c3fSmrg return suboffset(retype(spread(reg, scale), type), i); 103001e04c3fSmrg} 103101e04c3fSmrg 103201e04c3fSmrgstatic inline struct brw_reg 103301e04c3fSmrgvec16(struct brw_reg reg) 103401e04c3fSmrg{ 103501e04c3fSmrg return stride(reg, 16,16,1); 103601e04c3fSmrg} 103701e04c3fSmrg 103801e04c3fSmrgstatic inline struct brw_reg 103901e04c3fSmrgvec8(struct brw_reg reg) 104001e04c3fSmrg{ 104101e04c3fSmrg return stride(reg, 8,8,1); 104201e04c3fSmrg} 104301e04c3fSmrg 104401e04c3fSmrgstatic inline struct brw_reg 104501e04c3fSmrgvec4(struct brw_reg reg) 104601e04c3fSmrg{ 104701e04c3fSmrg return stride(reg, 4,4,1); 104801e04c3fSmrg} 104901e04c3fSmrg 105001e04c3fSmrgstatic inline struct brw_reg 105101e04c3fSmrgvec2(struct brw_reg reg) 105201e04c3fSmrg{ 105301e04c3fSmrg return stride(reg, 2,2,1); 105401e04c3fSmrg} 105501e04c3fSmrg 105601e04c3fSmrgstatic inline struct brw_reg 105701e04c3fSmrgvec1(struct brw_reg reg) 105801e04c3fSmrg{ 105901e04c3fSmrg return stride(reg, 0,1,0); 106001e04c3fSmrg} 106101e04c3fSmrg 106201e04c3fSmrg 106301e04c3fSmrgstatic inline struct brw_reg 106401e04c3fSmrgget_element(struct brw_reg reg, unsigned elt) 106501e04c3fSmrg{ 106601e04c3fSmrg return vec1(suboffset(reg, elt)); 106701e04c3fSmrg} 106801e04c3fSmrg 106901e04c3fSmrgstatic inline struct brw_reg 107001e04c3fSmrgget_element_ud(struct brw_reg reg, unsigned elt) 107101e04c3fSmrg{ 107201e04c3fSmrg return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt)); 107301e04c3fSmrg} 107401e04c3fSmrg 107501e04c3fSmrgstatic inline struct brw_reg 107601e04c3fSmrgget_element_d(struct brw_reg reg, unsigned elt) 107701e04c3fSmrg{ 107801e04c3fSmrg return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt)); 107901e04c3fSmrg} 108001e04c3fSmrg 108101e04c3fSmrgstatic inline struct brw_reg 108201e04c3fSmrgbrw_swizzle(struct brw_reg reg, unsigned swz) 108301e04c3fSmrg{ 108401e04c3fSmrg if (reg.file == BRW_IMMEDIATE_VALUE) 108501e04c3fSmrg reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz); 108601e04c3fSmrg else 108701e04c3fSmrg reg.swizzle = brw_compose_swizzle(swz, reg.swizzle); 108801e04c3fSmrg 108901e04c3fSmrg return reg; 109001e04c3fSmrg} 109101e04c3fSmrg 109201e04c3fSmrgstatic inline struct brw_reg 109301e04c3fSmrgbrw_writemask(struct brw_reg reg, unsigned mask) 109401e04c3fSmrg{ 109501e04c3fSmrg assert(reg.file != BRW_IMMEDIATE_VALUE); 109601e04c3fSmrg reg.writemask &= mask; 109701e04c3fSmrg return reg; 109801e04c3fSmrg} 109901e04c3fSmrg 110001e04c3fSmrgstatic inline struct brw_reg 110101e04c3fSmrgbrw_set_writemask(struct brw_reg reg, unsigned mask) 110201e04c3fSmrg{ 110301e04c3fSmrg assert(reg.file != BRW_IMMEDIATE_VALUE); 110401e04c3fSmrg reg.writemask = mask; 110501e04c3fSmrg return reg; 110601e04c3fSmrg} 110701e04c3fSmrg 110801e04c3fSmrgstatic inline unsigned 110901e04c3fSmrgbrw_writemask_for_size(unsigned n) 111001e04c3fSmrg{ 111101e04c3fSmrg return (1 << n) - 1; 111201e04c3fSmrg} 111301e04c3fSmrg 111401e04c3fSmrgstatic inline unsigned 111501e04c3fSmrgbrw_writemask_for_component_packing(unsigned n, unsigned first_component) 111601e04c3fSmrg{ 111701e04c3fSmrg assert(first_component + n <= 4); 111801e04c3fSmrg return (((1 << n) - 1) << first_component); 111901e04c3fSmrg} 112001e04c3fSmrg 112101e04c3fSmrgstatic inline struct brw_reg 112201e04c3fSmrgnegate(struct brw_reg reg) 112301e04c3fSmrg{ 112401e04c3fSmrg reg.negate ^= 1; 112501e04c3fSmrg return reg; 112601e04c3fSmrg} 112701e04c3fSmrg 112801e04c3fSmrgstatic inline struct brw_reg 112901e04c3fSmrgbrw_abs(struct brw_reg reg) 113001e04c3fSmrg{ 113101e04c3fSmrg reg.abs = 1; 113201e04c3fSmrg reg.negate = 0; 113301e04c3fSmrg return reg; 113401e04c3fSmrg} 113501e04c3fSmrg 113601e04c3fSmrg/************************************************************************/ 113701e04c3fSmrg 113801e04c3fSmrgstatic inline struct brw_reg 113901e04c3fSmrgbrw_vec4_indirect(unsigned subnr, int offset) 114001e04c3fSmrg{ 114101e04c3fSmrg struct brw_reg reg = brw_vec4_grf(0, 0); 114201e04c3fSmrg reg.subnr = subnr; 114301e04c3fSmrg reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; 114401e04c3fSmrg reg.indirect_offset = offset; 114501e04c3fSmrg return reg; 114601e04c3fSmrg} 114701e04c3fSmrg 114801e04c3fSmrgstatic inline struct brw_reg 114901e04c3fSmrgbrw_vec1_indirect(unsigned subnr, int offset) 115001e04c3fSmrg{ 115101e04c3fSmrg struct brw_reg reg = brw_vec1_grf(0, 0); 115201e04c3fSmrg reg.subnr = subnr; 115301e04c3fSmrg reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; 115401e04c3fSmrg reg.indirect_offset = offset; 115501e04c3fSmrg return reg; 115601e04c3fSmrg} 115701e04c3fSmrg 115801e04c3fSmrgstatic inline struct brw_reg 115901e04c3fSmrgbrw_VxH_indirect(unsigned subnr, int offset) 116001e04c3fSmrg{ 116101e04c3fSmrg struct brw_reg reg = brw_vec1_grf(0, 0); 116201e04c3fSmrg reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL; 116301e04c3fSmrg reg.subnr = subnr; 116401e04c3fSmrg reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; 116501e04c3fSmrg reg.indirect_offset = offset; 116601e04c3fSmrg return reg; 116701e04c3fSmrg} 116801e04c3fSmrg 116901e04c3fSmrgstatic inline struct brw_reg 117001e04c3fSmrgderef_4f(struct brw_indirect ptr, int offset) 117101e04c3fSmrg{ 117201e04c3fSmrg return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset); 117301e04c3fSmrg} 117401e04c3fSmrg 117501e04c3fSmrgstatic inline struct brw_reg 117601e04c3fSmrgderef_1f(struct brw_indirect ptr, int offset) 117701e04c3fSmrg{ 117801e04c3fSmrg return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset); 117901e04c3fSmrg} 118001e04c3fSmrg 118101e04c3fSmrgstatic inline struct brw_reg 118201e04c3fSmrgderef_4b(struct brw_indirect ptr, int offset) 118301e04c3fSmrg{ 118401e04c3fSmrg return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B); 118501e04c3fSmrg} 118601e04c3fSmrg 118701e04c3fSmrgstatic inline struct brw_reg 118801e04c3fSmrgderef_1uw(struct brw_indirect ptr, int offset) 118901e04c3fSmrg{ 119001e04c3fSmrg return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW); 119101e04c3fSmrg} 119201e04c3fSmrg 119301e04c3fSmrgstatic inline struct brw_reg 119401e04c3fSmrgderef_1d(struct brw_indirect ptr, int offset) 119501e04c3fSmrg{ 119601e04c3fSmrg return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D); 119701e04c3fSmrg} 119801e04c3fSmrg 119901e04c3fSmrgstatic inline struct brw_reg 120001e04c3fSmrgderef_1ud(struct brw_indirect ptr, int offset) 120101e04c3fSmrg{ 120201e04c3fSmrg return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD); 120301e04c3fSmrg} 120401e04c3fSmrg 120501e04c3fSmrgstatic inline struct brw_reg 120601e04c3fSmrgget_addr_reg(struct brw_indirect ptr) 120701e04c3fSmrg{ 120801e04c3fSmrg return brw_address_reg(ptr.addr_subnr); 120901e04c3fSmrg} 121001e04c3fSmrg 121101e04c3fSmrgstatic inline struct brw_indirect 121201e04c3fSmrgbrw_indirect_offset(struct brw_indirect ptr, int offset) 121301e04c3fSmrg{ 121401e04c3fSmrg ptr.addr_offset += offset; 121501e04c3fSmrg return ptr; 121601e04c3fSmrg} 121701e04c3fSmrg 121801e04c3fSmrgstatic inline struct brw_indirect 121901e04c3fSmrgbrw_indirect(unsigned addr_subnr, int offset) 122001e04c3fSmrg{ 122101e04c3fSmrg struct brw_indirect ptr; 122201e04c3fSmrg ptr.addr_subnr = addr_subnr; 122301e04c3fSmrg ptr.addr_offset = offset; 122401e04c3fSmrg ptr.pad = 0; 122501e04c3fSmrg return ptr; 122601e04c3fSmrg} 122701e04c3fSmrg 122801e04c3fSmrgstatic inline bool 122901e04c3fSmrgregion_matches(struct brw_reg reg, enum brw_vertical_stride v, 123001e04c3fSmrg enum brw_width w, enum brw_horizontal_stride h) 123101e04c3fSmrg{ 123201e04c3fSmrg return reg.vstride == v && 123301e04c3fSmrg reg.width == w && 123401e04c3fSmrg reg.hstride == h; 123501e04c3fSmrg} 123601e04c3fSmrg 123701e04c3fSmrg#define has_scalar_region(reg) \ 123801e04c3fSmrg region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \ 123901e04c3fSmrg BRW_HORIZONTAL_STRIDE_0) 124001e04c3fSmrg 12417ec681f3Smrg/** 12427ec681f3Smrg * Return the size in bytes per data element of register \p reg on the 12437ec681f3Smrg * corresponding register file. 12447ec681f3Smrg */ 12457ec681f3Smrgstatic inline unsigned 12467ec681f3Smrgelement_sz(struct brw_reg reg) 12477ec681f3Smrg{ 12487ec681f3Smrg if (reg.file == BRW_IMMEDIATE_VALUE || has_scalar_region(reg)) { 12497ec681f3Smrg return type_sz(reg.type); 12507ec681f3Smrg 12517ec681f3Smrg } else if (reg.width == BRW_WIDTH_1 && 12527ec681f3Smrg reg.hstride == BRW_HORIZONTAL_STRIDE_0) { 12537ec681f3Smrg assert(reg.vstride != BRW_VERTICAL_STRIDE_0); 12547ec681f3Smrg return type_sz(reg.type) << (reg.vstride - 1); 12557ec681f3Smrg 12567ec681f3Smrg } else { 12577ec681f3Smrg assert(reg.hstride != BRW_HORIZONTAL_STRIDE_0); 12587ec681f3Smrg assert(reg.vstride == reg.hstride + reg.width); 12597ec681f3Smrg return type_sz(reg.type) << (reg.hstride - 1); 12607ec681f3Smrg } 12617ec681f3Smrg} 12627ec681f3Smrg 126301e04c3fSmrg/* brw_packed_float.c */ 126401e04c3fSmrgint brw_float_to_vf(float f); 126501e04c3fSmrgfloat brw_vf_to_float(unsigned char vf); 126601e04c3fSmrg 126701e04c3fSmrg#ifdef __cplusplus 126801e04c3fSmrg} 126901e04c3fSmrg#endif 127001e04c3fSmrg 127101e04c3fSmrg#endif 1272