2012-11-09 22:00:15 +00: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 22:00:15 +00: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 22:00:15 +00: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>
|
2014-02-20 02:37:11 +00:00
|
|
|
#include "main/compiler.h"
|
2015-02-04 15:58:49 +00:00
|
|
|
#include "main/macros.h"
|
2012-11-09 22:00:15 +00:00
|
|
|
#include "program/prog_instruction.h"
|
2017-03-09 00:44:29 +00:00
|
|
|
#include "brw_eu_defines.h"
|
2017-07-26 19:08:11 +01:00
|
|
|
#include "brw_reg_type.h"
|
2012-11-09 22:00:15 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2016-08-22 23:01:08 +01:00
|
|
|
struct gen_device_info;
|
2014-07-10 02:17:32 +01:00
|
|
|
|
2012-11-10 05:20:05 +00:00
|
|
|
/** Number of general purpose registers (VS, WM, etc) */
|
|
|
|
#define BRW_MAX_GRF 128
|
|
|
|
|
|
|
|
/**
|
|
|
|
* First GRF used for the MRF hack.
|
|
|
|
*
|
|
|
|
* On gen7, MRFs are no longer used, and contiguous GRFs are used instead. We
|
|
|
|
* haven't converted our compiler to be aware of this, so it asks for MRFs and
|
|
|
|
* brw_eu_emit.c quietly converts them to be accesses of the top GRFs. The
|
|
|
|
* register allocators have to be careful of this to avoid corrupting the "MRF"s
|
|
|
|
* with actual GRF allocations.
|
|
|
|
*/
|
|
|
|
#define GEN7_MRF_HACK_START 112
|
|
|
|
|
|
|
|
/** Number of message register file registers */
|
i965: Turn BRW_MAX_MRF into a macro that accepts a hardware generation
There are some bug reports about shaders failing to compile in gen6
because MRF 14 is used when we need to spill. For example:
https://bugs.freedesktop.org/show_bug.cgi?id=86469
https://bugs.freedesktop.org/show_bug.cgi?id=90631
Discussion in bugzilla pointed to the fact that gen6 might actually have
24 MRF registers available instead of 16, so we could use other MRF
registers and avoid these conflicts (we still need to investigate why
some shaders need up to MRF 14 anyway, since this is not expected).
Notice that the hardware docs are not clear about this fact:
SNB PRM Vol4 Part2's "Table 5-4. MRF Registers Available in Device
Hardware" says "Number per Thread" - "24 registers"
However, SNB PRM Vol4 Part1, 1.6.1 Message Register File (MRF) says:
"Normal threads should construct their messages in m1..m15. (...)
Regardless of actual hardware implementation, the thread should
not assume th at MRF addresses above m15 wrap to legal MRF registers."
Therefore experimentation was necessary to evaluate if we had these extra
MRF registers available or not. This was tested in gen6 using MRF
registers 21..23 for spilling and doing a full piglit run (all.py) forcing
spilling of everything on the FS backend. It was also tested by doing
spilling of everything on both the FS and the VS backends with a piglit run
of shader.py. In both cases no regressions were observed. In fact, many of
these tests where helped in the cases where we forced spilling, since that
triggered the same underlying problem described in the bug reports. Here are
some results using INTEL_DEBUG=spill_fs,spill_vec4 for a shader.py run on
gen6 hardware:
Using MRFs 13..15 for spilling:
crash: 2, fail: 113, pass: 6621, skip: 5461
Using MRFs 21..23 for spilling:
crash: 2, fail: 12, pass: 6722, skip: 5461
This patch sets the ground for later patches to implement spilling
using MRF registers 21..23 in gen6.
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2015-09-15 15:00:26 +01:00
|
|
|
#define BRW_MAX_MRF(gen) (gen == 6 ? 24 : 16)
|
2012-11-10 05:20:05 +00:00
|
|
|
|
2012-11-09 22:00:15 +00: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 10:15:56 +01:00
|
|
|
#define BRW_SWIZZLE_YXYX BRW_SWIZZLE4(1,0,1,0)
|
2016-02-27 01:04:38 +00:00
|
|
|
#define BRW_SWIZZLE_XZXZ BRW_SWIZZLE4(0,2,0,2)
|
2013-11-29 02:13:18 +00:00
|
|
|
#define BRW_SWIZZLE_YZXW BRW_SWIZZLE4(1,2,0,3)
|
2016-02-27 01:04:38 +00:00
|
|
|
#define BRW_SWIZZLE_YWYW BRW_SWIZZLE4(1,3,1,3)
|
2013-11-29 02:13:18 +00: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 17:04:31 +01:00
|
|
|
#define BRW_SWIZZLE_ZWZW BRW_SWIZZLE4(2,3,2,3)
|
2016-08-18 10:15:56 +01:00
|
|
|
#define BRW_SWIZZLE_WZWZ BRW_SWIZZLE4(3,2,3,2)
|
2015-11-17 09:07:39 +00:00
|
|
|
#define BRW_SWIZZLE_WZYX BRW_SWIZZLE4(3,2,1,0)
|
2016-07-19 08:28:04 +01: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 22:00:15 +00:00
|
|
|
|
2016-06-23 00:32:39 +01: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 22:00:15 +00:00
|
|
|
static inline bool
|
2015-03-18 12:32:37 +00:00
|
|
|
brw_is_single_value_swizzle(unsigned swiz)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return (swiz == BRW_SWIZZLE_XXXX ||
|
|
|
|
swiz == BRW_SWIZZLE_YYYY ||
|
|
|
|
swiz == BRW_SWIZZLE_ZZZZ ||
|
|
|
|
swiz == BRW_SWIZZLE_WWWW);
|
|
|
|
}
|
|
|
|
|
2015-03-18 12:34:51 +00: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)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the result of applying swizzle \p swz to shuffle the bits of \p mask
|
|
|
|
* (AKA image).
|
|
|
|
*/
|
|
|
|
static inline unsigned
|
|
|
|
brw_apply_swizzle_to_mask(unsigned swz, unsigned mask)
|
|
|
|
{
|
|
|
|
unsigned result = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 4; i++) {
|
|
|
|
if (mask & (1 << BRW_GET_SWZ(swz, i)))
|
|
|
|
result |= 1 << i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the result of applying the inverse of swizzle \p swz to shuffle the
|
|
|
|
* bits of \p mask (AKA preimage). Useful to find out which components are
|
|
|
|
* read from a swizzled source given the instruction writemask.
|
|
|
|
*/
|
|
|
|
static inline unsigned
|
|
|
|
brw_apply_inv_swizzle_to_mask(unsigned swz, unsigned mask)
|
|
|
|
{
|
|
|
|
unsigned result = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < 4; i++) {
|
|
|
|
if (mask & (1 << i))
|
|
|
|
result |= 1 << BRW_GET_SWZ(swz, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct an identity swizzle for the first \p n components of a vector.
|
|
|
|
* When only a subset of channels of a vec4 are used we don't want to
|
|
|
|
* reference the other channels, as that will tell optimization passes that
|
|
|
|
* those other channels are used.
|
|
|
|
*/
|
|
|
|
static inline unsigned
|
|
|
|
brw_swizzle_for_size(unsigned n)
|
|
|
|
{
|
|
|
|
return brw_swizzle_for_mask((1 << n) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converse of brw_swizzle_for_mask(). Returns the mask of components
|
|
|
|
* accessed by the specified swizzle \p swz.
|
|
|
|
*/
|
|
|
|
static inline unsigned
|
|
|
|
brw_mask_for_swizzle(unsigned swz)
|
|
|
|
{
|
|
|
|
return brw_apply_inv_swizzle_to_mask(swz, ~0);
|
|
|
|
}
|
|
|
|
|
2016-02-27 01:12:27 +00: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 08:33:56 +00:00
|
|
|
|
2012-11-09 22:00:15 +00: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-14 00:41:13 +01:00
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
enum brw_reg_type type:4;
|
|
|
|
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! */
|
|
|
|
unsigned pad0:1;
|
|
|
|
unsigned subnr:5; /* :1 in align16 */
|
|
|
|
unsigned nr:16;
|
|
|
|
};
|
|
|
|
uint32_t bits;
|
|
|
|
};
|
2012-11-09 22:00:15 +00:00
|
|
|
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
unsigned swizzle:8; /* src only, align16 only */
|
|
|
|
unsigned writemask:4; /* dest only, align16 only */
|
|
|
|
int indirect_offset:10; /* relative addressing offset */
|
2015-10-23 20:17:03 +01:00
|
|
|
unsigned vstride:4; /* source only */
|
|
|
|
unsigned width:3; /* src only, align1 only */
|
|
|
|
unsigned hstride:2; /* align1 only */
|
|
|
|
unsigned pad1:1;
|
2015-10-23 03:41:30 +01:00
|
|
|
};
|
2012-11-09 22:00:15 +00:00
|
|
|
|
2015-11-12 11:40:38 +00:00
|
|
|
double df;
|
2016-05-17 01:28:19 +01:00
|
|
|
uint64_t u64;
|
2016-09-01 19:48:26 +01:00
|
|
|
int64_t d64;
|
2012-11-09 22:00:15 +00:00
|
|
|
float f;
|
|
|
|
int d;
|
|
|
|
unsigned ud;
|
2015-10-23 03:41:30 +01:00
|
|
|
};
|
2012-11-09 22:00:15 +00:00
|
|
|
};
|
|
|
|
|
2016-05-14 00:41:13 +01:00
|
|
|
static inline bool
|
|
|
|
brw_regs_equal(const struct brw_reg *a, const struct brw_reg *b)
|
|
|
|
{
|
|
|
|
const bool df = a->type == BRW_REGISTER_TYPE_DF && a->file == IMM;
|
2016-05-17 01:28:19 +01:00
|
|
|
return a->bits == b->bits && (df ? a->u64 == b->u64 : a->ud == b->ud);
|
2016-05-14 00:41:13 +01:00
|
|
|
}
|
2012-11-09 22:00:15 +00:00
|
|
|
|
2015-04-08 00:11:37 +01: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 19:29:09 +01:00
|
|
|
switch ((enum brw_reg_type) a->type) {
|
2015-04-08 00:11:37 +01: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:
|
|
|
|
case BRW_REGISTER_TYPE_NF:
|
2018-04-03 14:41:18 +01:00
|
|
|
default:
|
2015-04-08 00:11:37 +01:00
|
|
|
unreachable("not reached");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
struct brw_reg tmp = *a;
|
|
|
|
|
|
|
|
tmp.negate = !tmp.negate;
|
|
|
|
|
|
|
|
return brw_regs_equal(&tmp, b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00:00
|
|
|
struct brw_indirect {
|
|
|
|
unsigned addr_subnr:4;
|
|
|
|
int addr_offset:10;
|
|
|
|
unsigned pad:18;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2015-04-11 22:49:50 +01:00
|
|
|
static inline unsigned
|
2012-11-09 22:00:15 +00:00
|
|
|
type_sz(unsigned type)
|
|
|
|
{
|
|
|
|
switch(type) {
|
2014-12-23 03:29:13 +00:00
|
|
|
case BRW_REGISTER_TYPE_UQ:
|
|
|
|
case BRW_REGISTER_TYPE_Q:
|
2014-09-03 18:10:30 +01:00
|
|
|
case BRW_REGISTER_TYPE_DF:
|
2014-12-23 03:29:13 +00:00
|
|
|
return 8;
|
2012-11-09 22:00:15 +00:00
|
|
|
case BRW_REGISTER_TYPE_UD:
|
|
|
|
case BRW_REGISTER_TYPE_D:
|
|
|
|
case BRW_REGISTER_TYPE_F:
|
2016-05-24 23:10:25 +01:00
|
|
|
case BRW_REGISTER_TYPE_VF:
|
2012-11-09 22:00:15 +00:00
|
|
|
return 4;
|
|
|
|
case BRW_REGISTER_TYPE_UW:
|
|
|
|
case BRW_REGISTER_TYPE_W:
|
2016-05-24 23:10:25 +01:00
|
|
|
case BRW_REGISTER_TYPE_UV:
|
|
|
|
case BRW_REGISTER_TYPE_V:
|
|
|
|
case BRW_REGISTER_TYPE_HF:
|
2012-11-09 22:00:15 +00:00
|
|
|
return 2;
|
|
|
|
case BRW_REGISTER_TYPE_UB:
|
|
|
|
case BRW_REGISTER_TYPE_B:
|
|
|
|
return 1;
|
|
|
|
default:
|
2016-05-24 23:10:25 +01:00
|
|
|
unreachable("not reached");
|
2012-11-09 22:00:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-18 08:17:39 +01: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-26 01:35:52 +01: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.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-08 18:22:35 +01:00
|
|
|
static inline bool
|
|
|
|
type_is_unsigned_int(enum brw_reg_type tp)
|
|
|
|
{
|
|
|
|
return tp == BRW_REGISTER_TYPE_UB ||
|
|
|
|
tp == BRW_REGISTER_TYPE_UW ||
|
|
|
|
tp == BRW_REGISTER_TYPE_UD ||
|
|
|
|
tp == BRW_REGISTER_TYPE_UQ;
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00: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 16:19:07 +00:00
|
|
|
* \param negate register negate modifier
|
|
|
|
* \param abs register abs modifier
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_reg(enum brw_reg_file file,
|
2012-11-09 22:00:15 +00:00
|
|
|
unsigned nr,
|
|
|
|
unsigned subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
unsigned negate,
|
|
|
|
unsigned abs,
|
2014-06-30 00:02:59 +01:00
|
|
|
enum brw_reg_type type,
|
2012-11-09 22:00:15 +00:00
|
|
|
unsigned vstride,
|
|
|
|
unsigned width,
|
|
|
|
unsigned hstride,
|
|
|
|
unsigned swizzle,
|
|
|
|
unsigned writemask)
|
|
|
|
{
|
|
|
|
struct brw_reg reg;
|
|
|
|
if (file == BRW_GENERAL_REGISTER_FILE)
|
|
|
|
assert(nr < BRW_MAX_GRF);
|
|
|
|
else if (file == BRW_ARCHITECTURE_REGISTER_FILE)
|
|
|
|
assert(nr <= BRW_ARF_TIMESTAMP);
|
2015-09-16 08:08:19 +01:00
|
|
|
/* Asserting on the MRF register number requires to know the hardware gen
|
|
|
|
* (gen6 has 24 MRF registers), which we don't know here, so we assert
|
|
|
|
* for that in the generators and in brw_eu_emit.c
|
|
|
|
*/
|
2012-11-09 22:00:15 +00:00
|
|
|
|
|
|
|
reg.type = type;
|
|
|
|
reg.file = file;
|
2014-12-12 16:19:07 +00:00
|
|
|
reg.negate = negate;
|
|
|
|
reg.abs = abs;
|
2012-11-09 22:00:15 +00:00
|
|
|
reg.address_mode = BRW_ADDRESS_DIRECT;
|
|
|
|
reg.pad0 = 0;
|
2015-10-26 11:35:14 +00:00
|
|
|
reg.subnr = subnr * type_sz(type);
|
|
|
|
reg.nr = nr;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
reg.swizzle = swizzle;
|
|
|
|
reg.writemask = writemask;
|
|
|
|
reg.indirect_offset = 0;
|
2015-10-23 20:17:03 +01:00
|
|
|
reg.vstride = vstride;
|
|
|
|
reg.width = width;
|
|
|
|
reg.hstride = hstride;
|
2015-10-23 03:41:30 +01:00
|
|
|
reg.pad1 = 0;
|
2012-11-09 22:00:15 +00:00
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Construct float[16] register */
|
|
|
|
static inline struct brw_reg
|
2015-10-23 21:11:44 +01:00
|
|
|
brw_vec16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(file,
|
|
|
|
nr,
|
|
|
|
subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_vec8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(file,
|
|
|
|
nr,
|
|
|
|
subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_vec4_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(file,
|
|
|
|
nr,
|
|
|
|
subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_vec2_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(file,
|
|
|
|
nr,
|
|
|
|
subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_vec1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(file,
|
|
|
|
nr,
|
|
|
|
subnr,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00:00
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
BRW_VERTICAL_STRIDE_0,
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
BRW_SWIZZLE_XXXX,
|
|
|
|
WRITEMASK_X);
|
|
|
|
}
|
|
|
|
|
2013-09-11 22:19:47 +01:00
|
|
|
static inline struct brw_reg
|
2015-10-23 21:11:44 +01:00
|
|
|
brw_vecn_reg(unsigned width, enum brw_reg_file file,
|
|
|
|
unsigned nr, unsigned subnr)
|
2013-09-11 22:19:47 +01: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-30 03:12:04 +01:00
|
|
|
unreachable("Invalid register width");
|
2013-09-11 22:19:47 +01:00
|
|
|
}
|
|
|
|
}
|
2012-11-09 22:00:15 +00:00
|
|
|
|
|
|
|
static inline struct brw_reg
|
2014-06-30 00:02:59 +01:00
|
|
|
retype(struct brw_reg reg, enum brw_reg_type type)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
reg.type = type;
|
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2014-08-13 20:23:47 +01:00
|
|
|
static inline struct brw_reg
|
|
|
|
firsthalf(struct brw_reg reg)
|
|
|
|
{
|
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00: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 11:23:44 +01: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 22:00:15 +00:00
|
|
|
|
|
|
|
/** Construct unsigned word[16] register */
|
|
|
|
static inline struct brw_reg
|
2015-10-23 21:11:44 +01:00
|
|
|
brw_uw16_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_uw8_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00: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 21:11:44 +01:00
|
|
|
brw_uw1_reg(enum brw_reg_file file, unsigned nr, unsigned subnr)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return suboffset(retype(brw_vec1_reg(file, nr, 0), BRW_REGISTER_TYPE_UW), subnr);
|
|
|
|
}
|
|
|
|
|
2016-09-14 23:09:32 +01: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 22:00:15 +00:00
|
|
|
static inline struct brw_reg
|
2014-06-30 00:02:59 +01:00
|
|
|
brw_imm_reg(enum brw_reg_type type)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
|
|
|
return brw_reg(BRW_IMMEDIATE_VALUE,
|
2014-12-12 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
type,
|
|
|
|
BRW_VERTICAL_STRIDE_0,
|
|
|
|
BRW_WIDTH_1,
|
|
|
|
BRW_HORIZONTAL_STRIDE_0,
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Construct float immediate register */
|
2015-11-12 11:40:38 +00: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-09-01 06:12:48 +01: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 22:00:15 +00:00
|
|
|
static inline struct brw_reg
|
|
|
|
brw_imm_f(float f)
|
|
|
|
{
|
|
|
|
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_F);
|
2015-10-23 03:41:30 +01:00
|
|
|
imm.f = f;
|
2012-11-09 22:00:15 +00:00
|
|
|
return imm;
|
2017-11-03 01:29:03 +00: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 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
imm.d = d;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
imm.ud = ud;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
imm.ud = uw | (uw << 16);
|
2012-11-09 22:00:15 +00: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 00:38:47 +01:00
|
|
|
imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
imm.ud = v;
|
2012-11-09 22:00:15 +00:00
|
|
|
return imm;
|
|
|
|
}
|
|
|
|
|
2015-11-16 17:29:01 +00: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 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
imm.ud = v;
|
2012-11-09 22:00:15 +00:00
|
|
|
return imm;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
2015-11-02 18:29:45 +00:00
|
|
|
brw_imm_vf4(unsigned v0, unsigned v1, unsigned v2, unsigned v3)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
2015-11-02 18:29:45 +00: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 22:00:15 +00: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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 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);
|
|
|
|
}
|
|
|
|
|
2015-04-07 01:44:40 +01: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);
|
|
|
|
}
|
|
|
|
|
2015-08-13 22:22:03 +01: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);
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00: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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** 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 19:28:27 +01: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 22:00:15 +00: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 19:41:54 +01: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 22:00:15 +00: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 16:19:07 +00:00
|
|
|
0,
|
|
|
|
0,
|
2012-11-09 22:00:15 +00: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-05 01:52:42 +00: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 07:11:58 +01: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 09:22:08 +00:00
|
|
|
static inline struct brw_reg
|
2016-09-14 23:09:32 +01:00
|
|
|
brw_sr0_reg(unsigned subnr)
|
2016-02-20 09:22:08 +00:00
|
|
|
{
|
2016-09-14 23:09:32 +01:00
|
|
|
return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_STATE, subnr);
|
2016-02-20 09:22:08 +00:00
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00:00
|
|
|
static inline struct brw_reg
|
2014-09-30 18:15:23 +01:00
|
|
|
brw_acc_reg(unsigned width)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
2014-09-30 18:15:23 +01:00
|
|
|
return brw_vecn_reg(width, BRW_ARCHITECTURE_REGISTER_FILE,
|
|
|
|
BRW_ARF_ACCUMULATOR, 0);
|
2012-11-09 22:00:15 +00: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 20:05:02 +00: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 15:37:12 +01:00
|
|
|
/**
|
|
|
|
* Return the mask register present in Gen4-5, or the related register present
|
|
|
|
* in Gen7.5 and later hardware referred to as "channel enable" register in
|
|
|
|
* the documentation.
|
|
|
|
*/
|
2012-11-09 22:00:15 +00: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 23:09:33 +01: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);
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00:00
|
|
|
static inline struct brw_reg
|
|
|
|
brw_message_reg(unsigned nr)
|
|
|
|
{
|
|
|
|
return brw_vec8_reg(BRW_MESSAGE_REGISTER_FILE, nr, 0);
|
|
|
|
}
|
|
|
|
|
2013-09-11 22:19:47 +01:00
|
|
|
static inline struct brw_reg
|
|
|
|
brw_uvec_mrf(unsigned width, unsigned nr, unsigned subnr)
|
|
|
|
{
|
|
|
|
return retype(brw_vecn_reg(width, BRW_MESSAGE_REGISTER_FILE, nr, subnr),
|
|
|
|
BRW_REGISTER_TYPE_UD);
|
|
|
|
}
|
2012-11-09 22:00:15 +00: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 15:58:49 +00: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) {
|
2015-07-29 17:41:18 +01:00
|
|
|
assert(_mesa_is_pow_two(s));
|
2015-02-04 15:58:49 +00: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 22:00:15 +00:00
|
|
|
|
2017-10-18 03:50:36 +01: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)
|
|
|
|
{
|
|
|
|
if (reg.file == IMM)
|
|
|
|
return reg;
|
|
|
|
|
|
|
|
unsigned scale = type_sz(reg.type) / type_sz(type);
|
|
|
|
assert(scale >= 1 && i < scale);
|
|
|
|
|
|
|
|
return suboffset(retype(spread(reg, scale), type), i);
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00: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-27 01:04:38 +00:00
|
|
|
brw_swizzle(struct brw_reg reg, unsigned swz)
|
2012-11-09 22:00:15 +00:00
|
|
|
{
|
2016-02-27 01:12:27 +00: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 22:00:15 +00:00
|
|
|
|
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct brw_reg
|
|
|
|
brw_writemask(struct brw_reg reg, unsigned mask)
|
|
|
|
{
|
|
|
|
assert(reg.file != BRW_IMMEDIATE_VALUE);
|
2015-10-23 03:41:30 +01:00
|
|
|
reg.writemask &= mask;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
reg.writemask = mask;
|
2012-11-09 22:00:15 +00:00
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2015-06-16 19:53:28 +01:00
|
|
|
static inline unsigned
|
|
|
|
brw_writemask_for_size(unsigned n)
|
|
|
|
{
|
|
|
|
return (1 << n) - 1;
|
|
|
|
}
|
|
|
|
|
2016-06-23 03:52:05 +01: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 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
reg.indirect_offset = offset;
|
2012-11-09 22:00:15 +00: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-23 03:41:30 +01:00
|
|
|
reg.indirect_offset = offset;
|
2012-11-09 22:00:15 +00:00
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2015-08-20 06:15:33 +01: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-23 03:41:30 +01:00
|
|
|
reg.indirect_offset = offset;
|
2015-08-20 06:15:33 +01:00
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
|
2012-11-09 22:00:15 +00: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-23 03:29:22 +00: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)
|
|
|
|
|
2014-04-03 22:59:26 +01:00
|
|
|
/* brw_packed_float.c */
|
|
|
|
int brw_float_to_vf(float f);
|
|
|
|
float brw_vf_to_float(unsigned char vf);
|
|
|
|
|
2012-11-09 22:00:15 +00:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|