2012-11-09 14:00:15 -08:00
|
|
|
/*
|
|
|
|
|
Copyright (C) Intel Corp. 2006. All Rights Reserved.
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
Intel funded Tungsten Graphics to
|
2012-11-09 14:00:15 -08:00
|
|
|
develop this 3D driver.
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
|
a copy of this software and associated documentation files (the
|
|
|
|
|
"Software"), to deal in the Software without restriction, including
|
|
|
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
|
the following conditions:
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice (including the
|
|
|
|
|
next paragraph) shall be included in all copies or substantial
|
|
|
|
|
portions of the Software.
|
|
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
|
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
|
|
|
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
/*
|
|
|
|
|
* Authors:
|
s/Tungsten Graphics/VMware/
Tungsten Graphics Inc. was acquired by VMware Inc. in 2008. Leaving the
old copyright name is creating unnecessary confusion, hence this change.
This was the sed script I used:
$ cat tg2vmw.sed
# Run as:
#
# git reset --hard HEAD && find include scons src -type f -not -name 'sed*' -print0 | xargs -0 sed -i -f tg2vmw.sed
#
# Rename copyrights
s/Tungsten Gra\(ph\|hp\)ics,\? [iI]nc\.\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./g
/Copyright/s/Tungsten Graphics\(,\? [iI]nc\.\)\?\(, Cedar Park\)\?\(, Austin\)\?\(, \(Texas\|TX\)\)\?\.\?/VMware, Inc./
s/TUNGSTEN GRAPHICS/VMWARE/g
# Rename emails
s/alanh@tungstengraphics.com/alanh@vmware.com/
s/jens@tungstengraphics.com/jowen@vmware.com/g
s/jrfonseca-at-tungstengraphics-dot-com/jfonseca-at-vmware-dot-com/
s/jrfonseca\?@tungstengraphics.com/jfonseca@vmware.com/g
s/keithw\?@tungstengraphics.com/keithw@vmware.com/g
s/michel@tungstengraphics.com/daenzer@vmware.com/g
s/thomas-at-tungstengraphics-dot-com/thellstom-at-vmware-dot-com/
s/zack@tungstengraphics.com/zackr@vmware.com/
# Remove dead links
s@Tungsten Graphics (http://www.tungstengraphics.com)@Tungsten Graphics@g
# C string src/gallium/state_trackers/vega/api_misc.c
s/"Tungsten Graphics, Inc"/"VMware, Inc"/
Reviewed-by: Brian Paul <brianp@vmware.com>
2014-01-17 16:27:50 +00:00
|
|
|
* Keith Whitwell <keithw@vmware.com>
|
2012-11-09 14:00:15 -08:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @file brw_reg.h
|
|
|
|
|
*
|
|
|
|
|
* This file defines struct brw_reg, which is our representation for EU
|
|
|
|
|
* registers. They're not a hardware specific format, just an abstraction
|
|
|
|
|
* that intends to capture the full flexibility of the hardware registers.
|
|
|
|
|
*
|
|
|
|
|
* The brw_eu_emit.c layer's brw_set_dest/brw_set_src[01] functions encode
|
|
|
|
|
* the abstract brw_reg type into the actual hardware instruction encoding.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef BRW_REG_H
|
|
|
|
|
#define BRW_REG_H
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
2020-03-25 21:11:44 -04:00
|
|
|
#include "util/compiler.h"
|
2023-08-02 19:24:14 +08:00
|
|
|
#include "util/glheader.h"
|
|
|
|
|
#include "util/macros.h"
|
|
|
|
|
#include "util/rounding.h"
|
|
|
|
|
#include "util/u_math.h"
|
2017-03-09 00:44:29 +00:00
|
|
|
#include "brw_eu_defines.h"
|
2017-07-26 11:08:11 -07:00
|
|
|
#include "brw_reg_type.h"
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-04-05 13:19:39 -07:00
|
|
|
struct intel_device_info;
|
2014-07-09 21:17:32 -04:00
|
|
|
|
2022-07-07 01:15:14 -07:00
|
|
|
/** Size of general purpose register space in REG_SIZE units */
|
2012-11-09 21:20:05 -08:00
|
|
|
#define BRW_MAX_GRF 128
|
2022-07-07 01:15:14 -07:00
|
|
|
#define XE2_MAX_GRF 256
|
2012-11-09 21:20:05 -08:00
|
|
|
|
2023-08-02 19:36:27 +08:00
|
|
|
/**
|
|
|
|
|
* BRW hardware swizzles.
|
|
|
|
|
* Only defines XYZW to ensure it can be contained in 2 bits
|
|
|
|
|
*/
|
|
|
|
|
#define BRW_SWIZZLE_X 0
|
|
|
|
|
#define BRW_SWIZZLE_Y 1
|
|
|
|
|
#define BRW_SWIZZLE_Z 2
|
|
|
|
|
#define BRW_SWIZZLE_W 3
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
#define BRW_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<2) | ((c)<<4) | ((d)<<6))
|
|
|
|
|
#define BRW_GET_SWZ(swz, idx) (((swz) >> ((idx)*2)) & 0x3)
|
|
|
|
|
|
|
|
|
|
#define BRW_SWIZZLE_NOOP BRW_SWIZZLE4(0,1,2,3)
|
|
|
|
|
#define BRW_SWIZZLE_XYZW BRW_SWIZZLE4(0,1,2,3)
|
|
|
|
|
#define BRW_SWIZZLE_XXXX BRW_SWIZZLE4(0,0,0,0)
|
|
|
|
|
#define BRW_SWIZZLE_YYYY BRW_SWIZZLE4(1,1,1,1)
|
|
|
|
|
#define BRW_SWIZZLE_ZZZZ BRW_SWIZZLE4(2,2,2,2)
|
|
|
|
|
#define BRW_SWIZZLE_WWWW BRW_SWIZZLE4(3,3,3,3)
|
|
|
|
|
#define BRW_SWIZZLE_XYXY BRW_SWIZZLE4(0,1,0,1)
|
2016-08-18 11:15:56 +02:00
|
|
|
#define BRW_SWIZZLE_YXYX BRW_SWIZZLE4(1,0,1,0)
|
2016-02-26 17:04:38 -08:00
|
|
|
#define BRW_SWIZZLE_XZXZ BRW_SWIZZLE4(0,2,0,2)
|
2013-11-28 18:13:18 -08:00
|
|
|
#define BRW_SWIZZLE_YZXW BRW_SWIZZLE4(1,2,0,3)
|
2016-02-26 17:04:38 -08:00
|
|
|
#define BRW_SWIZZLE_YWYW BRW_SWIZZLE4(1,3,1,3)
|
2013-11-28 18:13:18 -08:00
|
|
|
#define BRW_SWIZZLE_ZXYW BRW_SWIZZLE4(2,0,1,3)
|
i965/fs: Improve accuracy of dFdy() to match dFdx().
Previously, we computed dFdy() using the following instruction:
add(8) dst<1>F src<4,4,0)F -src.2<4,4,0>F { align1 1Q }
That had the disadvantage that it computed the same value for all 4
pixels of a 2x2 subspan, which meant that it was less accurate than
dFdx(). This patch changes it to the following instruction when
c->key.high_quality_derivatives is set:
add(8) dst<1>F src<4,4,1>.xyxyF -src<4,4,1>.zwzwF { align16 1Q }
This gives it comparable accuracy to dFdx().
Unfortunately, align16 instructions can't be compressed, so in SIMD16
shaders, instead of emitting this instruction:
add(16) dst<1>F src<4,4,1>.xyxyF -src<4,4,1>.zwzwF { align16 1H }
We need to unroll to two instructions:
add(8) dst<1>F src<4,4,1>.xyxyF -src<4,4,1>.zwzwF { align16 1Q }
add(8) (dst+1)<1>F (src+1)<4,4,1>.xyxyF -(src+1)<4,4,1>.zwzwF { align16 2Q }
Fixes piglit test spec/glsl-1.10/execution/fs-dfdy-accuracy.
Acked-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Eric Anholt <eric@anholt.net>
2013-09-20 09:04:31 -07:00
|
|
|
#define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3)
|
2016-08-18 11:15:56 +02:00
|
|
|
#define BRW_SWIZZLE_WZWZ BRW_SWIZZLE4(3,2,3,2)
|
2015-11-17 01:07:39 -08:00
|
|
|
#define BRW_SWIZZLE_WZYX BRW_SWIZZLE4(3,2,1,0)
|
2016-07-19 09:28:04 +02:00
|
|
|
#define BRW_SWIZZLE_XXZZ BRW_SWIZZLE4(0,0,2,2)
|
|
|
|
|
#define BRW_SWIZZLE_YYWW BRW_SWIZZLE4(1,1,3,3)
|
|
|
|
|
#define BRW_SWIZZLE_YXWZ BRW_SWIZZLE4(1,0,3,2)
|
2012-11-09 14:00:15 -08:00
|
|
|
|
2016-06-23 09:32:39 +10:00
|
|
|
#define BRW_SWZ_COMP_INPUT(comp) (BRW_SWIZZLE_XYZW >> ((comp)*2))
|
|
|
|
|
#define BRW_SWZ_COMP_OUTPUT(comp) (BRW_SWIZZLE_XYZW << ((comp)*2))
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline bool
|
2015-03-18 14:32:37 +02:00
|
|
|
brw_is_single_value_swizzle(unsigned swiz)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return (swiz == BRW_SWIZZLE_XXXX ||
|
|
|
|
|
swiz == BRW_SWIZZLE_YYYY ||
|
|
|
|
|
swiz == BRW_SWIZZLE_ZZZZ ||
|
|
|
|
|
swiz == BRW_SWIZZLE_WWWW);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-18 14:34:51 +02:00
|
|
|
/**
|
|
|
|
|
* Compute the swizzle obtained from the application of \p swz0 on the result
|
|
|
|
|
* of \p swz1. The argument ordering is expected to match function
|
|
|
|
|
* composition.
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned
|
|
|
|
|
brw_compose_swizzle(unsigned swz0, unsigned swz1)
|
|
|
|
|
{
|
|
|
|
|
return BRW_SWIZZLE4(
|
|
|
|
|
BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 0)),
|
|
|
|
|
BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 1)),
|
|
|
|
|
BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 2)),
|
|
|
|
|
BRW_GET_SWZ(swz1, BRW_GET_SWZ(swz0, 3)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct an identity swizzle for the set of enabled channels given by \p
|
|
|
|
|
* mask. The result will only reference channels enabled in the provided \p
|
|
|
|
|
* mask, assuming that \p mask is non-zero. The constructed swizzle will
|
|
|
|
|
* satisfy the property that for any instruction OP and any mask:
|
|
|
|
|
*
|
|
|
|
|
* brw_OP(p, brw_writemask(dst, mask),
|
|
|
|
|
* brw_swizzle(src, brw_swizzle_for_mask(mask)));
|
|
|
|
|
*
|
|
|
|
|
* will be equivalent to the same instruction without swizzle:
|
|
|
|
|
*
|
|
|
|
|
* brw_OP(p, brw_writemask(dst, mask), src);
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned
|
|
|
|
|
brw_swizzle_for_mask(unsigned mask)
|
|
|
|
|
{
|
|
|
|
|
unsigned last = (mask ? ffs(mask) - 1 : 0);
|
|
|
|
|
unsigned swz[4];
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 4; i++)
|
|
|
|
|
last = swz[i] = (mask & (1 << i) ? i : last);
|
|
|
|
|
|
|
|
|
|
return BRW_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-26 17:12:27 -08:00
|
|
|
uint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
|
i965: Abstract BRW_REGISTER_TYPE_* into an enum with unique values.
On released hardware, values 4-6 are overloaded. For normal registers,
they mean UB/B/DF. But for immediates, they mean UV/VF/V.
Previously, we just created #defines for each name, reusing the same
value. This meant we could directly splat the brw_reg::type field into
the assembly encoding, which was fairly nice, and worked well.
Unfortunately, Broadwell makes this infeasible: the HF and DF types are
represented as different numeric values depending on whether the
source register is an immediate or not.
To preserve sanity, I decided to simply convert BRW_REGISTER_TYPE_* to
an abstract enum that has a unique value for each register type, and
write translation functions. One nice benefit is that we can add
assertions about register files and generations.
I've chosen not to convert brw_reg::type to the enum, since converting
it caused a lot of trouble due to C++ enum rules (even though it's
defined in an extern "C" block...).
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
2013-12-10 00:33:56 -08:00
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
#define REG_SIZE (8*4)
|
|
|
|
|
|
|
|
|
|
/* These aren't hardware structs, just something useful for us to pass around:
|
|
|
|
|
*
|
|
|
|
|
* Align1 operation has a lot of control over input ranges. Used in
|
|
|
|
|
* WM programs to implement shaders decomposed into "channel serial"
|
|
|
|
|
* or "structure of array" form:
|
|
|
|
|
*/
|
|
|
|
|
struct brw_reg {
|
2016-05-13 16:41:13 -07:00
|
|
|
union {
|
|
|
|
|
struct {
|
intel/brw: Rework BRW_REGISTER_TYPE's representation semantics
In ancient days, we directly used the hardware register type encodings
throughout the compiler. As more GPU generations came out, encodings
shifted, and we moved to an abstract enum that we could encode/decode
to a particular GPU's hardware encoding. But there was no particular
meaning behind any particular value.
One downside to this approach is that we end up with switch statements
galore. Want to know a type's size? Switch. Convert a unsigned type
to a signed one? Switch. Get a type with the same base type, but
different bit size? Switch. This is both inefficient and inconvenient.
In contrast, nir_alu_type takes a nicer approach - the type encoding has
certain bits representing the base type, and others encoding the size of
the type. Switching base types or sizes is a simple matter of masking
out the relevant field and substituting a different one.
Tigerlake's encoding adopts a similar approach: two bits represent the
size as a 2-bit unsigned number n, where the bit size is (8 * 2^n).
Two more bits represent the base type. Past encodings were a bit ad hoc
as new data types were added over time, but Gfx12 is organized (mostly).
This patch converts our brw_reg_type enum over to a new system that's
patterned after the Tigerlake style (for easy conversion) while
deviating in a few ways that make our vector immediate type size
handling simpler. Should we add additional base types, we're likely
to continue deviating. Still, converting is much simpler.
Type size calculations (which are performed all the time) are now a
simple mask and shift, instead of a switch.
We also adopt the name BRW_TYPE_* instead of BRW_REGISTER_TYPE_* because
it's much shorter and easier to type. Similarly, we create new helper
functions named brw_type_* for working with these types, with a cleaner
naming convention. Legacy names still exist but will we dropped over
the next few patches as pieces get cleaned up.
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28847>
2024-04-20 00:13:16 -07:00
|
|
|
enum brw_reg_type type:5;
|
2016-05-13 16:41:13 -07:00
|
|
|
enum brw_reg_file file:3; /* :2 hardware format */
|
|
|
|
|
unsigned negate:1; /* source only */
|
|
|
|
|
unsigned abs:1; /* source only */
|
|
|
|
|
unsigned address_mode:1; /* relative addressing, hopefully! */
|
intel/brw: Rework BRW_REGISTER_TYPE's representation semantics
In ancient days, we directly used the hardware register type encodings
throughout the compiler. As more GPU generations came out, encodings
shifted, and we moved to an abstract enum that we could encode/decode
to a particular GPU's hardware encoding. But there was no particular
meaning behind any particular value.
One downside to this approach is that we end up with switch statements
galore. Want to know a type's size? Switch. Convert a unsigned type
to a signed one? Switch. Get a type with the same base type, but
different bit size? Switch. This is both inefficient and inconvenient.
In contrast, nir_alu_type takes a nicer approach - the type encoding has
certain bits representing the base type, and others encoding the size of
the type. Switching base types or sizes is a simple matter of masking
out the relevant field and substituting a different one.
Tigerlake's encoding adopts a similar approach: two bits represent the
size as a 2-bit unsigned number n, where the bit size is (8 * 2^n).
Two more bits represent the base type. Past encodings were a bit ad hoc
as new data types were added over time, but Gfx12 is organized (mostly).
This patch converts our brw_reg_type enum over to a new system that's
patterned after the Tigerlake style (for easy conversion) while
deviating in a few ways that make our vector immediate type size
handling simpler. Should we add additional base types, we're likely
to continue deviating. Still, converting is much simpler.
Type size calculations (which are performed all the time) are now a
simple mask and shift, instead of a switch.
We also adopt the name BRW_TYPE_* instead of BRW_REGISTER_TYPE_* because
it's much shorter and easier to type. Similarly, we create new helper
functions named brw_type_* for working with these types, with a cleaner
naming convention. Legacy names still exist but will we dropped over
the next few patches as pieces get cleaned up.
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28847>
2024-04-20 00:13:16 -07:00
|
|
|
unsigned pad0:16;
|
2016-05-13 16:41:13 -07:00
|
|
|
unsigned subnr:5; /* :1 in align16 */
|
|
|
|
|
};
|
|
|
|
|
uint32_t bits;
|
|
|
|
|
};
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
struct {
|
2018-12-10 11:48:54 -08:00
|
|
|
unsigned nr;
|
2012-11-09 14:00:15 -08:00
|
|
|
unsigned swizzle:8; /* src only, align16 only */
|
|
|
|
|
unsigned writemask:4; /* dest only, align16 only */
|
|
|
|
|
int indirect_offset:10; /* relative addressing offset */
|
2015-10-23 12:17:03 -07:00
|
|
|
unsigned vstride:4; /* source only */
|
|
|
|
|
unsigned width:3; /* src only, align1 only */
|
|
|
|
|
unsigned hstride:2; /* align1 only */
|
|
|
|
|
unsigned pad1:1;
|
2015-10-22 19:41:30 -07:00
|
|
|
};
|
2012-11-09 14:00:15 -08:00
|
|
|
|
2015-11-12 12:40:38 +01:00
|
|
|
double df;
|
2016-05-16 17:28:19 -07:00
|
|
|
uint64_t u64;
|
2016-09-01 11:48:26 -07:00
|
|
|
int64_t d64;
|
2012-11-09 14:00:15 -08:00
|
|
|
float f;
|
|
|
|
|
int d;
|
|
|
|
|
unsigned ud;
|
2015-10-22 19:41:30 -07:00
|
|
|
};
|
2012-11-09 14:00:15 -08:00
|
|
|
};
|
|
|
|
|
|
2022-07-07 01:09:32 -07:00
|
|
|
static inline unsigned
|
|
|
|
|
phys_nr(const struct intel_device_info *devinfo, const struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
if (devinfo->ver >= 20) {
|
|
|
|
|
if (reg.file == BRW_GENERAL_REGISTER_FILE)
|
|
|
|
|
return reg.nr / 2;
|
|
|
|
|
else if (reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
|
|
|
|
|
reg.nr >= BRW_ARF_ACCUMULATOR &&
|
|
|
|
|
reg.nr < BRW_ARF_FLAG)
|
|
|
|
|
return BRW_ARF_ACCUMULATOR + (reg.nr - BRW_ARF_ACCUMULATOR) / 2;
|
|
|
|
|
else
|
|
|
|
|
return reg.nr;
|
|
|
|
|
} else {
|
|
|
|
|
return reg.nr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline unsigned
|
|
|
|
|
phys_subnr(const struct intel_device_info *devinfo, const struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
if (devinfo->ver >= 20) {
|
|
|
|
|
if (reg.file == BRW_GENERAL_REGISTER_FILE ||
|
|
|
|
|
(reg.file == BRW_ARCHITECTURE_REGISTER_FILE &&
|
|
|
|
|
reg.nr >= BRW_ARF_ACCUMULATOR &&
|
|
|
|
|
reg.nr < BRW_ARF_FLAG))
|
|
|
|
|
return (reg.nr & 1) * REG_SIZE + reg.subnr;
|
|
|
|
|
else
|
|
|
|
|
return reg.subnr;
|
|
|
|
|
} else {
|
|
|
|
|
return reg.subnr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-13 16:41:13 -07:00
|
|
|
static inline bool
|
|
|
|
|
brw_regs_equal(const struct brw_reg *a, const struct brw_reg *b)
|
|
|
|
|
{
|
2018-12-10 11:48:54 -08:00
|
|
|
return a->bits == b->bits && a->u64 == b->u64;
|
2016-05-13 16:41:13 -07:00
|
|
|
}
|
2012-11-09 14:00:15 -08:00
|
|
|
|
2015-04-07 16:11:37 -07:00
|
|
|
static inline bool
|
|
|
|
|
brw_regs_negative_equal(const struct brw_reg *a, const struct brw_reg *b)
|
|
|
|
|
{
|
|
|
|
|
if (a->file == IMM) {
|
|
|
|
|
if (a->bits != b->bits)
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-03-29 11:29:09 -07:00
|
|
|
switch ((enum brw_reg_type) a->type) {
|
2015-04-07 16:11:37 -07:00
|
|
|
case BRW_REGISTER_TYPE_UQ:
|
|
|
|
|
case BRW_REGISTER_TYPE_Q:
|
|
|
|
|
return a->d64 == -b->d64;
|
|
|
|
|
case BRW_REGISTER_TYPE_DF:
|
|
|
|
|
return a->df == -b->df;
|
|
|
|
|
case BRW_REGISTER_TYPE_UD:
|
|
|
|
|
case BRW_REGISTER_TYPE_D:
|
|
|
|
|
return a->d == -b->d;
|
|
|
|
|
case BRW_REGISTER_TYPE_F:
|
|
|
|
|
return a->f == -b->f;
|
|
|
|
|
case BRW_REGISTER_TYPE_VF:
|
|
|
|
|
/* It is tempting to treat 0 as a negation of 0 (and -0 as a negation
|
|
|
|
|
* of -0). There are occasions where 0 or -0 is used and the exact
|
|
|
|
|
* bit pattern is desired. At the very least, changing this to allow
|
|
|
|
|
* 0 as a negation of 0 causes some fp64 tests to fail on IVB.
|
|
|
|
|
*/
|
|
|
|
|
return a->ud == (b->ud ^ 0x80808080);
|
|
|
|
|
case BRW_REGISTER_TYPE_UW:
|
|
|
|
|
case BRW_REGISTER_TYPE_W:
|
|
|
|
|
case BRW_REGISTER_TYPE_UV:
|
|
|
|
|
case BRW_REGISTER_TYPE_V:
|
|
|
|
|
case BRW_REGISTER_TYPE_HF:
|
|
|
|
|
/* FINISHME: Implement support for these types once there is
|
|
|
|
|
* something in the compiler that can generate them. Until then,
|
|
|
|
|
* they cannot be tested.
|
|
|
|
|
*/
|
|
|
|
|
return false;
|
|
|
|
|
case BRW_REGISTER_TYPE_UB:
|
|
|
|
|
case BRW_REGISTER_TYPE_B:
|
2018-04-03 14:41:18 +01:00
|
|
|
default:
|
2015-04-07 16:11:37 -07:00
|
|
|
unreachable("not reached");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
struct brw_reg tmp = *a;
|
|
|
|
|
|
|
|
|
|
tmp.negate = !tmp.negate;
|
|
|
|
|
|
|
|
|
|
return brw_regs_equal(&tmp, b);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
struct brw_indirect {
|
|
|
|
|
unsigned addr_subnr:4;
|
|
|
|
|
int addr_offset:10;
|
|
|
|
|
unsigned pad:18;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-04-11 14:49:50 -07:00
|
|
|
static inline unsigned
|
2012-11-09 14:00:15 -08:00
|
|
|
type_sz(unsigned type)
|
|
|
|
|
{
|
intel/brw: Rework BRW_REGISTER_TYPE's representation semantics
In ancient days, we directly used the hardware register type encodings
throughout the compiler. As more GPU generations came out, encodings
shifted, and we moved to an abstract enum that we could encode/decode
to a particular GPU's hardware encoding. But there was no particular
meaning behind any particular value.
One downside to this approach is that we end up with switch statements
galore. Want to know a type's size? Switch. Convert a unsigned type
to a signed one? Switch. Get a type with the same base type, but
different bit size? Switch. This is both inefficient and inconvenient.
In contrast, nir_alu_type takes a nicer approach - the type encoding has
certain bits representing the base type, and others encoding the size of
the type. Switching base types or sizes is a simple matter of masking
out the relevant field and substituting a different one.
Tigerlake's encoding adopts a similar approach: two bits represent the
size as a 2-bit unsigned number n, where the bit size is (8 * 2^n).
Two more bits represent the base type. Past encodings were a bit ad hoc
as new data types were added over time, but Gfx12 is organized (mostly).
This patch converts our brw_reg_type enum over to a new system that's
patterned after the Tigerlake style (for easy conversion) while
deviating in a few ways that make our vector immediate type size
handling simpler. Should we add additional base types, we're likely
to continue deviating. Still, converting is much simpler.
Type size calculations (which are performed all the time) are now a
simple mask and shift, instead of a switch.
We also adopt the name BRW_TYPE_* instead of BRW_REGISTER_TYPE_* because
it's much shorter and easier to type. Similarly, we create new helper
functions named brw_type_* for working with these types, with a cleaner
naming convention. Legacy names still exist but will we dropped over
the next few patches as pieces get cleaned up.
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28847>
2024-04-20 00:13:16 -07:00
|
|
|
return brw_type_size_bytes((enum brw_reg_type) type);
|
2012-11-09 14:00:15 -08:00
|
|
|
}
|
|
|
|
|
|
2016-07-18 07:17:39 +00:00
|
|
|
static inline enum brw_reg_type
|
|
|
|
|
get_exec_type(const enum brw_reg_type type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case BRW_REGISTER_TYPE_B:
|
|
|
|
|
case BRW_REGISTER_TYPE_V:
|
|
|
|
|
return BRW_REGISTER_TYPE_W;
|
|
|
|
|
case BRW_REGISTER_TYPE_UB:
|
|
|
|
|
case BRW_REGISTER_TYPE_UV:
|
|
|
|
|
return BRW_REGISTER_TYPE_UW;
|
|
|
|
|
case BRW_REGISTER_TYPE_VF:
|
|
|
|
|
return BRW_REGISTER_TYPE_F;
|
|
|
|
|
default:
|
|
|
|
|
return type;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-25 17:35:52 -07:00
|
|
|
/**
|
|
|
|
|
* Return an integer type of the requested size and signedness.
|
|
|
|
|
*/
|
|
|
|
|
static inline enum brw_reg_type
|
|
|
|
|
brw_int_type(unsigned sz, bool is_signed)
|
|
|
|
|
{
|
|
|
|
|
switch (sz) {
|
|
|
|
|
case 1:
|
|
|
|
|
return (is_signed ? BRW_REGISTER_TYPE_B : BRW_REGISTER_TYPE_UB);
|
|
|
|
|
case 2:
|
|
|
|
|
return (is_signed ? BRW_REGISTER_TYPE_W : BRW_REGISTER_TYPE_UW);
|
|
|
|
|
case 4:
|
|
|
|
|
return (is_signed ? BRW_REGISTER_TYPE_D : BRW_REGISTER_TYPE_UD);
|
|
|
|
|
case 8:
|
|
|
|
|
return (is_signed ? BRW_REGISTER_TYPE_Q : BRW_REGISTER_TYPE_UQ);
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Not reached.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/**
|
|
|
|
|
* Construct a brw_reg.
|
|
|
|
|
* \param file one of the BRW_x_REGISTER_FILE values
|
|
|
|
|
* \param nr register number/index
|
|
|
|
|
* \param subnr register sub number
|
2014-12-12 17:19:07 +01:00
|
|
|
* \param negate register negate modifier
|
|
|
|
|
* \param abs register abs modifier
|
2012-11-09 14:00:15 -08:00
|
|
|
* \param type one of BRW_REGISTER_TYPE_x
|
|
|
|
|
* \param vstride one of BRW_VERTICAL_STRIDE_x
|
|
|
|
|
* \param width one of BRW_WIDTH_x
|
|
|
|
|
* \param hstride one of BRW_HORIZONTAL_STRIDE_x
|
|
|
|
|
* \param swizzle one of BRW_SWIZZLE_x
|
|
|
|
|
* \param writemask WRITEMASK_X/Y/Z/W bitfield
|
|
|
|
|
*/
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_reg(enum brw_reg_file file,
|
2012-11-09 14:00:15 -08:00
|
|
|
unsigned nr,
|
|
|
|
|
unsigned subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
unsigned negate,
|
|
|
|
|
unsigned abs,
|
2014-06-29 16:02:59 -07:00
|
|
|
enum brw_reg_type type,
|
2012-11-09 14:00:15 -08:00
|
|
|
unsigned vstride,
|
|
|
|
|
unsigned width,
|
|
|
|
|
unsigned hstride,
|
|
|
|
|
unsigned swizzle,
|
|
|
|
|
unsigned writemask)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg reg;
|
|
|
|
|
if (file == BRW_GENERAL_REGISTER_FILE)
|
2022-07-07 01:15:14 -07:00
|
|
|
assert(nr < XE2_MAX_GRF);
|
2012-11-09 14:00:15 -08:00
|
|
|
else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
|
|
|
|
|
assert(nr <= BRW_ARF_TIMESTAMP);
|
|
|
|
|
|
|
|
|
|
reg.type = type;
|
|
|
|
|
reg.file = file;
|
2014-12-12 17:19:07 +01:00
|
|
|
reg.negate = negate;
|
|
|
|
|
reg.abs = abs;
|
2012-11-09 14:00:15 -08:00
|
|
|
reg.address_mode = BRW_ADDRESS_DIRECT;
|
|
|
|
|
reg.pad0 = 0;
|
2015-10-26 04:35:14 -07:00
|
|
|
reg.subnr = subnr * type_sz(type);
|
|
|
|
|
reg.nr = nr;
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
/* Could do better: If the reg is r5.3<0;1,0>, we probably want to
|
|
|
|
|
* set swizzle and writemask to W, as the lower bits of subnr will
|
|
|
|
|
* be lost when converted to align16. This is probably too much to
|
|
|
|
|
* keep track of as you'd want it adjusted by suboffset(), etc.
|
|
|
|
|
* Perhaps fix up when converting to align16?
|
|
|
|
|
*/
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.swizzle = swizzle;
|
|
|
|
|
reg.writemask = writemask;
|
|
|
|
|
reg.indirect_offset = 0;
|
2015-10-23 12:17:03 -07:00
|
|
|
reg.vstride = vstride;
|
|
|
|
|
reg.width = width;
|
|
|
|
|
reg.hstride = hstride;
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.pad1 = 0;
|
2012-11-09 14:00:15 -08:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[16] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(file,
|
|
|
|
|
nr,
|
|
|
|
|
subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_VERTICAL_STRIDE_16,
|
|
|
|
|
BRW_WIDTH_16,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_1,
|
|
|
|
|
BRW_SWIZZLE_XYZW,
|
|
|
|
|
WRITEMASK_XYZW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[8] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(file,
|
|
|
|
|
nr,
|
|
|
|
|
subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_VERTICAL_STRIDE_8,
|
|
|
|
|
BRW_WIDTH_8,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_1,
|
|
|
|
|
BRW_SWIZZLE_XYZW,
|
|
|
|
|
WRITEMASK_XYZW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[4] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(file,
|
|
|
|
|
nr,
|
|
|
|
|
subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_VERTICAL_STRIDE_4,
|
|
|
|
|
BRW_WIDTH_4,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_1,
|
|
|
|
|
BRW_SWIZZLE_XYZW,
|
|
|
|
|
WRITEMASK_XYZW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[2] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(file,
|
|
|
|
|
nr,
|
|
|
|
|
subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_VERTICAL_STRIDE_2,
|
|
|
|
|
BRW_WIDTH_2,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_1,
|
|
|
|
|
BRW_SWIZZLE_XYXY,
|
|
|
|
|
WRITEMASK_XY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[1] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(file,
|
|
|
|
|
nr,
|
|
|
|
|
subnr,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_VERTICAL_STRIDE_0,
|
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
|
BRW_SWIZZLE_XXXX,
|
|
|
|
|
WRITEMASK_X);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-11 14:19:47 -07:00
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_vecn_reg(unsigned width, enum brw_reg_file file,
|
|
|
|
|
unsigned nr, unsigned subnr)
|
2013-09-11 14:19:47 -07:00
|
|
|
{
|
|
|
|
|
switch (width) {
|
|
|
|
|
case 1:
|
|
|
|
|
return brw_vec1_reg(file, nr, subnr);
|
|
|
|
|
case 2:
|
|
|
|
|
return brw_vec2_reg(file, nr, subnr);
|
|
|
|
|
case 4:
|
|
|
|
|
return brw_vec4_reg(file, nr, subnr);
|
|
|
|
|
case 8:
|
|
|
|
|
return brw_vec8_reg(file, nr, subnr);
|
|
|
|
|
case 16:
|
|
|
|
|
return brw_vec16_reg(file, nr, subnr);
|
|
|
|
|
default:
|
2014-06-29 19:12:04 -07:00
|
|
|
unreachable("Invalid register width");
|
2013-09-11 14:19:47 -07:00
|
|
|
}
|
|
|
|
|
}
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
2014-06-29 16:02:59 -07:00
|
|
|
retype(struct brw_reg reg, enum brw_reg_type type)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
reg.type = type;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-13 12:23:47 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
firsthalf(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
sechalf(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
if (reg.vstride)
|
|
|
|
|
reg.nr++;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
offset(struct brw_reg reg, unsigned delta)
|
|
|
|
|
{
|
|
|
|
|
reg.nr += delta;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
byte_offset(struct brw_reg reg, unsigned bytes)
|
|
|
|
|
{
|
|
|
|
|
unsigned newoffset = reg.nr * REG_SIZE + reg.subnr + bytes;
|
|
|
|
|
reg.nr = newoffset / REG_SIZE;
|
|
|
|
|
reg.subnr = newoffset % REG_SIZE;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-27 12:23:44 +02:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
suboffset(struct brw_reg reg, unsigned delta)
|
|
|
|
|
{
|
|
|
|
|
return byte_offset(reg, delta * type_sz(reg.type));
|
|
|
|
|
}
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
/** Construct unsigned word[16] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return suboffset(retype(brw_vec16_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct unsigned word[8] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return suboffset(retype(brw_vec8_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct unsigned word[1] register */
|
|
|
|
|
static inline struct brw_reg
|
2015-10-23 13:11:44 -07:00
|
|
|
brw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 16:52:10 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_ud8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return retype(brw_vec8_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-14 15:09:32 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_ud1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return retype(brw_vec1_reg(file, nr, subnr), BRW_REGISTER_TYPE_UD);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
2014-06-29 16:02:59 -07:00
|
|
|
brw_imm_reg(enum brw_reg_type type)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
|
|
|
|
return brw_reg(BRW_IMMEDIATE_VALUE,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
type,
|
|
|
|
|
BRW_VERTICAL_STRIDE_0,
|
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
|
0,
|
|
|
|
|
0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float immediate register */
|
2015-11-12 12:40:38 +01:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_df(double df)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_DF);
|
|
|
|
|
imm.df = df;
|
|
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-31 22:12:48 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_u64(uint64_t u64)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ);
|
|
|
|
|
imm.u64 = u64;
|
|
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_f(float f)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.f = f;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
2017-11-02 18:29:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct int64_t immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_q(int64_t q)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_Q);
|
|
|
|
|
imm.d64 = q;
|
|
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct int64_t immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_uq(uint64_t uq)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UQ);
|
|
|
|
|
imm.u64 = uq;
|
|
|
|
|
return imm;
|
2012-11-09 14:00:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct integer immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_d(int d)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_D);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.d = d;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct uint immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_ud(unsigned ud)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UD);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.ud = ud;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct ushort immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_uw(uint16_t uw)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UW);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.ud = uw | (uw << 16);
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct short immediate register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_w(int16_t w)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
|
intel/compiler: fix brw_imm_w for negative 16-bit integers
16-bit immediates need to replicate the 16-bit immediate value
in both words of the 32-bit value. This needs to be careful
to avoid sign-extension, which the previous implementation was
not handling properly.
For example, with the previous implementation, storing the value
-3 would generate imm.d = 0xfffffffd due to signed integer sign
extension, which is not correct. Instead, we should cast to
uint16_t, which gives us the correct result: imm.ud = 0xfffdfffd.
We only had a couple of cases hitting this path in the driver
until now, one with value -1, which would work since all bits are
one in this case, and another with value -2 in brw_clip_tri(),
which would hit the aforementioned issue (this case only affects
gen4 although we are not aware of whether this was causing an
actual bug somewhere).
v2: Make explicit uint32_t casting for left shift (Jason Ekstrand)
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Cc: "18.0 18.1" <mesa-stable@lists.freedesktop.org>
2018-05-03 01:38:47 +02:00
|
|
|
imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* brw_imm_b and brw_imm_ub aren't supported by hardware - the type
|
|
|
|
|
* numbers alias with _V and _VF below:
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** Construct vector of eight signed half-byte values */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_v(unsigned v)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_V);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.ud = v;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-16 09:29:01 -08:00
|
|
|
/** Construct vector of eight unsigned half-byte values */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_uv(unsigned uv)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_UV);
|
|
|
|
|
imm.ud = uv;
|
|
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/** Construct vector of four 8-bit float values */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_imm_vf(unsigned v)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
|
2015-10-22 19:41:30 -07:00
|
|
|
imm.ud = v;
|
2012-11-09 14:00:15 -08:00
|
|
|
return imm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
2015-11-02 10:29:45 -08:00
|
|
|
brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
2015-11-02 10:29:45 -08:00
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_VF);
|
|
|
|
|
imm.vstride = BRW_VERTICAL_STRIDE_0;
|
|
|
|
|
imm.width = BRW_WIDTH_4;
|
|
|
|
|
imm.hstride = BRW_HORIZONTAL_STRIDE_1;
|
|
|
|
|
imm.ud = ((v0 << 0) | (v1 << 8) | (v2 << 16) | (v3 << 24));
|
|
|
|
|
return imm;
|
2012-11-09 14:00:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_address(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return brw_imm_uw(reg.nr * REG_SIZE + reg.subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Construct float[1] general-purpose register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec1_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vec1_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec1_reg(BRW_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/** Construct float[2] general-purpose register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec2_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vec2_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec2_reg(BRW_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/** Construct float[4] general-purpose register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec4_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vec4_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec4_reg(BRW_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/** Construct float[8] general-purpose register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec8_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vec8_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec8_reg(BRW_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-06 17:44:40 -07:00
|
|
|
/** Construct float[16] general-purpose register */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec16_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vec16_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec16_reg(BRW_GENERAL_REGISTER_FILE, 2 * nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-13 14:22:03 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-16 15:13:02 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
xe2_vecn_grf(unsigned width, unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_vecn_reg(width, BRW_GENERAL_REGISTER_FILE, nr + subnr / 8, subnr % 8);
|
|
|
|
|
}
|
2012-11-09 14:00:15 -08:00
|
|
|
|
2023-04-05 12:16:33 +02:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_uw1_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_uw8_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_uw16_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 16:52:10 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_ud8_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_ud8_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_ud1_grf(unsigned nr, unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_ud1_reg(BRW_GENERAL_REGISTER_FILE, nr, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
/** Construct null register (usually used for setting condition codes) */
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_null_reg(void)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec8_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
|
2014-09-10 11:28:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_null_vec(unsigned width)
|
|
|
|
|
{
|
|
|
|
|
return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_NULL, 0);
|
2012-11-09 14:00:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_address_reg(unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-06 11:41:54 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_tdr_reg(void)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_TDR, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/* If/else instructions break in align16 mode if writemask & swizzle
|
|
|
|
|
* aren't xyzw. This goes against the convention for other scalar
|
|
|
|
|
* regs:
|
|
|
|
|
*/
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_ip_reg(void)
|
|
|
|
|
{
|
|
|
|
|
return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_IP,
|
|
|
|
|
0,
|
2014-12-12 17:19:07 +01:00
|
|
|
0,
|
|
|
|
|
0,
|
2012-11-09 14:00:15 -08:00
|
|
|
BRW_REGISTER_TYPE_UD,
|
|
|
|
|
BRW_VERTICAL_STRIDE_4, /* ? */
|
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
|
BRW_SWIZZLE_XYZW, /* NOTE! */
|
|
|
|
|
WRITEMASK_XYZW); /* NOTE! */
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-04 17:52:42 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_notification_reg(void)
|
|
|
|
|
{
|
|
|
|
|
return brw_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_NOTIFICATION_COUNT,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
BRW_REGISTER_TYPE_UD,
|
|
|
|
|
BRW_VERTICAL_STRIDE_0,
|
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
|
BRW_SWIZZLE_XXXX,
|
|
|
|
|
WRITEMASK_X);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-01 08:11:58 +02:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_cr0_reg(unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_CONTROL, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-20 01:22:08 -08:00
|
|
|
static inline struct brw_reg
|
2016-09-14 15:09:32 -07:00
|
|
|
brw_sr0_reg(unsigned subnr)
|
2016-02-20 01:22:08 -08:00
|
|
|
{
|
2016-09-14 15:09:32 -07:00
|
|
|
return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr);
|
2016-02-20 01:22:08 -08:00
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
2014-09-30 10:15:23 -07:00
|
|
|
brw_acc_reg(unsigned width)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
2014-09-30 10:15:23 -07:00
|
|
|
return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_ACCUMULATOR, 0);
|
2012-11-09 14:00:15 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_flag_reg(int reg, int subreg)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_FLAG + reg, subreg);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 12:05:02 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_flag_subreg(unsigned subreg)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_FLAG + subreg / 2, subreg % 2);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-06 17:37:12 +03:00
|
|
|
/**
|
2021-03-29 15:46:12 -07:00
|
|
|
* Return the mask register present in Gfx4-5, or the related register present
|
|
|
|
|
* in Gfx7.5 and later hardware referred to as "channel enable" register in
|
2015-05-06 17:37:12 +03:00
|
|
|
* the documentation.
|
|
|
|
|
*/
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_mask_reg(unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_MASK, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-14 15:09:33 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vmask_reg()
|
|
|
|
|
{
|
|
|
|
|
return brw_sr0_reg(3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_dmask_reg()
|
|
|
|
|
{
|
|
|
|
|
return brw_sr0_reg(2);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 14:59:30 -05:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_mask_stack_reg(unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return suboffset(retype(brw_vec16_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_MASK_STACK, 0),
|
|
|
|
|
BRW_REGISTER_TYPE_UB), subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_mask_stack_depth_reg(unsigned subnr)
|
|
|
|
|
{
|
|
|
|
|
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
|
BRW_ARF_MASK_STACK_DEPTH, subnr);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
/* This is almost always called with a numeric constant argument, so
|
|
|
|
|
* make things easy to evaluate at compile time:
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned cvt(unsigned val)
|
|
|
|
|
{
|
|
|
|
|
switch (val) {
|
|
|
|
|
case 0: return 0;
|
|
|
|
|
case 1: return 1;
|
|
|
|
|
case 2: return 2;
|
|
|
|
|
case 4: return 3;
|
|
|
|
|
case 8: return 4;
|
|
|
|
|
case 16: return 5;
|
|
|
|
|
case 32: return 6;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
stride(struct brw_reg reg, unsigned vstride, unsigned width, unsigned hstride)
|
|
|
|
|
{
|
|
|
|
|
reg.vstride = cvt(vstride);
|
|
|
|
|
reg.width = cvt(width) - 1;
|
|
|
|
|
reg.hstride = cvt(hstride);
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-04 17:58:49 +02:00
|
|
|
/**
|
|
|
|
|
* Multiply the vertical and horizontal stride of a register by the given
|
|
|
|
|
* factor \a s.
|
|
|
|
|
*/
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
spread(struct brw_reg reg, unsigned s)
|
|
|
|
|
{
|
|
|
|
|
if (s) {
|
2018-09-06 11:36:19 -07:00
|
|
|
assert(util_is_power_of_two_nonzero(s));
|
2015-02-04 17:58:49 +02:00
|
|
|
|
|
|
|
|
if (reg.hstride)
|
|
|
|
|
reg.hstride += cvt(s) - 1;
|
|
|
|
|
|
|
|
|
|
if (reg.vstride)
|
|
|
|
|
reg.vstride += cvt(s) - 1;
|
|
|
|
|
|
|
|
|
|
return reg;
|
|
|
|
|
} else {
|
|
|
|
|
return stride(reg, 0, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-11-09 14:00:15 -08:00
|
|
|
|
2017-10-17 19:50:36 -07:00
|
|
|
/**
|
|
|
|
|
* Reinterpret each channel of register \p reg as a vector of values of the
|
|
|
|
|
* given smaller type and take the i-th subcomponent from each.
|
|
|
|
|
*/
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
subscript(struct brw_reg reg, enum brw_reg_type type, unsigned i)
|
|
|
|
|
{
|
|
|
|
|
unsigned scale = type_sz(reg.type) / type_sz(type);
|
|
|
|
|
assert(scale >= 1 && i < scale);
|
|
|
|
|
|
2020-10-26 13:27:43 -05:00
|
|
|
if (reg.file == IMM) {
|
|
|
|
|
unsigned bit_size = type_sz(type) * 8;
|
|
|
|
|
reg.u64 >>= i * bit_size;
|
|
|
|
|
reg.u64 &= BITFIELD64_MASK(bit_size);
|
|
|
|
|
if (bit_size <= 16)
|
|
|
|
|
reg.u64 |= reg.u64 << 16;
|
|
|
|
|
return retype(reg, type);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 19:50:36 -07:00
|
|
|
return suboffset(retype(spread(reg, scale), type), i);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
vec16(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return stride(reg, 16,16,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
vec8(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return stride(reg, 8,8,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
vec4(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return stride(reg, 4,4,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
vec2(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return stride(reg, 2,2,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
vec1(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
return stride(reg, 0,1,0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
get_element(struct brw_reg reg, unsigned elt)
|
|
|
|
|
{
|
|
|
|
|
return vec1(suboffset(reg, elt));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
get_element_ud(struct brw_reg reg, unsigned elt)
|
|
|
|
|
{
|
|
|
|
|
return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_UD), elt));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
get_element_d(struct brw_reg reg, unsigned elt)
|
|
|
|
|
{
|
|
|
|
|
return vec1(suboffset(retype(reg, BRW_REGISTER_TYPE_D), elt));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
2016-02-26 17:04:38 -08:00
|
|
|
brw_swizzle(struct brw_reg reg, unsigned swz)
|
2012-11-09 14:00:15 -08:00
|
|
|
{
|
2016-02-26 17:12:27 -08:00
|
|
|
if (reg.file == BRW_IMMEDIATE_VALUE)
|
|
|
|
|
reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swz);
|
|
|
|
|
else
|
|
|
|
|
reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
|
2012-11-09 14:00:15 -08:00
|
|
|
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_writemask(struct brw_reg reg, unsigned mask)
|
|
|
|
|
{
|
|
|
|
|
assert(reg.file != BRW_IMMEDIATE_VALUE);
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.writemask &= mask;
|
2012-11-09 14:00:15 -08:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_set_writemask(struct brw_reg reg, unsigned mask)
|
|
|
|
|
{
|
|
|
|
|
assert(reg.file != BRW_IMMEDIATE_VALUE);
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.writemask = mask;
|
2012-11-09 14:00:15 -08:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-16 20:53:28 +02:00
|
|
|
static inline unsigned
|
|
|
|
|
brw_writemask_for_size(unsigned n)
|
|
|
|
|
{
|
|
|
|
|
return (1 << n) - 1;
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-23 12:52:05 +10:00
|
|
|
static inline unsigned
|
|
|
|
|
brw_writemask_for_component_packing(unsigned n, unsigned first_component)
|
|
|
|
|
{
|
|
|
|
|
assert(first_component + n <= 4);
|
|
|
|
|
return (((1 << n) - 1) << first_component);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
negate(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
reg.negate ^= 1;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_abs(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
reg.abs = 1;
|
|
|
|
|
reg.negate = 0;
|
|
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec4_indirect(unsigned subnr, int offset)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg reg = brw_vec4_grf(0, 0);
|
|
|
|
|
reg.subnr = subnr;
|
|
|
|
|
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.indirect_offset = offset;
|
2012-11-09 14:00:15 -08:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_vec1_indirect(unsigned subnr, int offset)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg reg = brw_vec1_grf(0, 0);
|
|
|
|
|
reg.subnr = subnr;
|
|
|
|
|
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.indirect_offset = offset;
|
2012-11-09 14:00:15 -08:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-19 22:15:33 -07:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
brw_VxH_indirect(unsigned subnr, int offset)
|
|
|
|
|
{
|
|
|
|
|
struct brw_reg reg = brw_vec1_grf(0, 0);
|
|
|
|
|
reg.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL;
|
|
|
|
|
reg.subnr = subnr;
|
|
|
|
|
reg.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER;
|
2015-10-22 19:41:30 -07:00
|
|
|
reg.indirect_offset = offset;
|
2015-08-19 22:15:33 -07:00
|
|
|
return reg;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_4f(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec4_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_1f(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return brw_vec1_indirect(ptr.addr_subnr, ptr.addr_offset + offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_4b(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return retype(deref_4f(ptr, offset), BRW_REGISTER_TYPE_B);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_1uw(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_1d(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_D);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
deref_1ud(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
return retype(deref_1f(ptr, offset), BRW_REGISTER_TYPE_UD);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
|
get_addr_reg(struct brw_indirect ptr)
|
|
|
|
|
{
|
|
|
|
|
return brw_address_reg(ptr.addr_subnr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_indirect
|
|
|
|
|
brw_indirect_offset(struct brw_indirect ptr, int offset)
|
|
|
|
|
{
|
|
|
|
|
ptr.addr_offset += offset;
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline struct brw_indirect
|
|
|
|
|
brw_indirect(unsigned addr_subnr, int offset)
|
|
|
|
|
{
|
|
|
|
|
struct brw_indirect ptr;
|
|
|
|
|
ptr.addr_subnr = addr_subnr;
|
|
|
|
|
ptr.addr_offset = offset;
|
|
|
|
|
ptr.pad = 0;
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-22 19:29:22 -08:00
|
|
|
static inline bool
|
|
|
|
|
region_matches(struct brw_reg reg, enum brw_vertical_stride v,
|
|
|
|
|
enum brw_width w, enum brw_horizontal_stride h)
|
|
|
|
|
{
|
|
|
|
|
return reg.vstride == v &&
|
|
|
|
|
reg.width == w &&
|
|
|
|
|
reg.hstride == h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define has_scalar_region(reg) \
|
|
|
|
|
region_matches(reg, BRW_VERTICAL_STRIDE_0, BRW_WIDTH_1, \
|
|
|
|
|
BRW_HORIZONTAL_STRIDE_0)
|
|
|
|
|
|
2021-12-20 01:54:57 -08:00
|
|
|
/**
|
|
|
|
|
* Return the size in bytes per data element of register \p reg on the
|
|
|
|
|
* corresponding register file.
|
|
|
|
|
*/
|
|
|
|
|
static inline unsigned
|
|
|
|
|
element_sz(struct brw_reg reg)
|
|
|
|
|
{
|
|
|
|
|
if (reg.file == BRW_IMMEDIATE_VALUE || has_scalar_region(reg)) {
|
|
|
|
|
return type_sz(reg.type);
|
|
|
|
|
|
|
|
|
|
} else if (reg.width == BRW_WIDTH_1 &&
|
|
|
|
|
reg.hstride == BRW_HORIZONTAL_STRIDE_0) {
|
|
|
|
|
assert(reg.vstride != BRW_VERTICAL_STRIDE_0);
|
|
|
|
|
return type_sz(reg.type) << (reg.vstride - 1);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
assert(reg.hstride != BRW_HORIZONTAL_STRIDE_0);
|
|
|
|
|
assert(reg.vstride == reg.hstride + reg.width);
|
|
|
|
|
return type_sz(reg.type) << (reg.hstride - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-03 14:59:26 -07:00
|
|
|
/* brw_packed_float.c */
|
|
|
|
|
int brw_float_to_vf(float f);
|
|
|
|
|
float brw_vf_to_float(unsigned char vf);
|
|
|
|
|
|
2012-11-09 14:00:15 -08:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#endif
|