#define BRW_REG_H
#include <stdbool.h>
-#include "main/compiler.h"
+#include "util/compiler.h"
#include "main/macros.h"
#include "program/prog_instruction.h"
#include "brw_eu_defines.h"
+#include "brw_reg_type.h"
#ifdef __cplusplus
extern "C" {
return brw_apply_inv_swizzle_to_mask(swz, ~0);
}
-enum PACKED brw_reg_type {
- BRW_REGISTER_TYPE_UD = 0,
- BRW_REGISTER_TYPE_D,
- BRW_REGISTER_TYPE_UW,
- BRW_REGISTER_TYPE_W,
- BRW_REGISTER_TYPE_F,
-
- /** Non-immediates only: @{ */
- BRW_REGISTER_TYPE_UB,
- BRW_REGISTER_TYPE_B,
- /** @} */
-
- /** Immediates only: @{ */
- BRW_REGISTER_TYPE_UV, /* Gen6+ */
- BRW_REGISTER_TYPE_V,
- BRW_REGISTER_TYPE_VF,
- /** @} */
-
- BRW_REGISTER_TYPE_DF, /* Gen7+ (no immediates until Gen8+) */
-
- /* Gen8+ */
- BRW_REGISTER_TYPE_HF,
- BRW_REGISTER_TYPE_UQ,
- BRW_REGISTER_TYPE_Q,
-};
-
-unsigned brw_reg_type_to_hw_type(const struct gen_device_info *devinfo,
- enum brw_reg_type type, enum brw_reg_file file);
-
-#define brw_element_size(devinfo, inst, operand) \
- brw_hw_reg_type_to_size(devinfo, \
- brw_inst_ ## operand ## _reg_type(devinfo, inst), \
- brw_inst_ ## operand ## _reg_file(devinfo, inst))
-unsigned brw_hw_reg_type_to_size(const struct gen_device_info *devinfo,
- unsigned type, enum brw_reg_file file);
-
-const char *brw_reg_type_letters(unsigned brw_reg_type);
uint32_t brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz);
#define REG_SIZE (8*4)
unsigned negate:1; /* source only */
unsigned abs:1; /* source only */
unsigned address_mode:1; /* relative addressing, hopefully! */
- unsigned pad0:1;
+ unsigned pad0:17;
unsigned subnr:5; /* :1 in align16 */
- unsigned nr:16;
};
uint32_t bits;
};
union {
struct {
+ unsigned nr;
unsigned swizzle:8; /* src only, align16 only */
unsigned writemask:4; /* dest only, align16 only */
int indirect_offset:10; /* relative addressing offset */
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;
- return a->bits == b->bits && (df ? a->u64 == b->u64 : a->ud == b->ud);
+ return a->bits == b->bits && a->u64 == b->u64;
+}
+
+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;
+
+ switch ((enum brw_reg_type) a->type) {
+ 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:
+ default:
+ unreachable("not reached");
+ }
+ } else {
+ struct brw_reg tmp = *a;
+
+ tmp.negate = !tmp.negate;
+
+ return brw_regs_equal(&tmp, b);
+ }
}
struct brw_indirect {
case BRW_REGISTER_TYPE_UQ:
case BRW_REGISTER_TYPE_Q:
case BRW_REGISTER_TYPE_DF:
+ case BRW_REGISTER_TYPE_NF:
return 8;
case BRW_REGISTER_TYPE_UD:
case BRW_REGISTER_TYPE_D:
}
}
+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;
+ }
+}
+
/**
* Return an integer type of the requested size and signedness.
*/
}
}
+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;
+}
+
/**
* Construct a brw_reg.
* \param file one of the BRW_x_REGISTER_FILE values
return imm;
}
+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;
+}
+
static inline struct brw_reg
brw_imm_f(float f)
{
return imm;
}
+/** 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;
+}
+
/** Construct integer immediate register */
static inline struct brw_reg
brw_imm_d(int d)
brw_imm_w(int16_t w)
{
struct brw_reg imm = brw_imm_reg(BRW_REGISTER_TYPE_W);
- imm.d = w | (w << 16);
+ imm.ud = (uint16_t)w | (uint32_t)(uint16_t)w << 16;
return imm;
}
return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_ADDRESS, subnr);
}
+static inline struct brw_reg
+brw_tdr_reg(void)
+{
+ return brw_uw1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_TDR, 0);
+}
+
/* If/else instructions break in align16 mode if writemask & swizzle
* aren't xyzw. This goes against the convention for other scalar
* regs:
WRITEMASK_X);
}
+static inline struct brw_reg
+brw_cr0_reg(unsigned subnr)
+{
+ return brw_ud1_reg(BRW_ARCHITECTURE_REGISTER_FILE, BRW_ARF_CONTROL, subnr);
+}
+
static inline struct brw_reg
brw_sr0_reg(unsigned subnr)
{
BRW_ARF_FLAG + reg, subreg);
}
+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);
+}
+
/**
* 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
return brw_sr0_reg(2);
}
+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);
+}
+
static inline struct brw_reg
brw_message_reg(unsigned nr)
{
spread(struct brw_reg reg, unsigned s)
{
if (s) {
- assert(_mesa_is_pow_two(s));
+ assert(util_is_power_of_two_nonzero(s));
if (reg.hstride)
reg.hstride += cvt(s) - 1;
}
}
+/**
+ * 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);
+}
+
static inline struct brw_reg
vec16(struct brw_reg reg)
{