aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/drivers/dri/i965/brw_eu.c44
-rw-r--r--src/mesa/drivers/dri/i965/brw_ir_vec4.h6
-rw-r--r--src/mesa/drivers/dri/i965/brw_reg.h7
3 files changed, 54 insertions, 3 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c
index 40ec87d38f0..6961a88c6a8 100644
--- a/src/mesa/drivers/dri/i965/brw_eu.c
+++ b/src/mesa/drivers/dri/i965/brw_eu.c
@@ -110,6 +110,50 @@ brw_swap_cmod(uint32_t cmod)
}
}
+/**
+ * Get the least significant bit offset of the i+1-th component of immediate
+ * type \p type. For \p i equal to the two's complement of j, return the
+ * offset of the j-th component starting from the end of the vector. For
+ * scalar register types return zero.
+ */
+static unsigned
+imm_shift(enum brw_reg_type type, unsigned i)
+{
+ assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V &&
+ "Not implemented.");
+
+ if (type == BRW_REGISTER_TYPE_VF)
+ return 8 * (i & 3);
+ else
+ return 0;
+}
+
+/**
+ * Swizzle an arbitrary immediate \p x of the given type according to the
+ * permutation specified as \p swz.
+ */
+uint32_t
+brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz)
+{
+ if (imm_shift(type, 1)) {
+ const unsigned n = 32 / imm_shift(type, 1);
+ uint32_t y = 0;
+
+ for (unsigned i = 0; i < n; i++) {
+ /* Shift the specified component all the way to the right and left to
+ * discard any undesired L/MSBs, then shift it right into component i.
+ */
+ y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3))
+ << imm_shift(type, ~0u)
+ >> imm_shift(type, ~0u - i);
+ }
+
+ return y;
+ } else {
+ return x;
+ }
+}
+
void
brw_set_default_exec_size(struct brw_codegen *p, unsigned value)
{
diff --git a/src/mesa/drivers/dri/i965/brw_ir_vec4.h b/src/mesa/drivers/dri/i965/brw_ir_vec4.h
index 660becaafa7..2b6872e6d31 100644
--- a/src/mesa/drivers/dri/i965/brw_ir_vec4.h
+++ b/src/mesa/drivers/dri/i965/brw_ir_vec4.h
@@ -76,7 +76,11 @@ offset(src_reg reg, unsigned delta)
static inline src_reg
swizzle(src_reg reg, unsigned swizzle)
{
- reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
+ if (reg.file == IMM)
+ reg.ud = brw_swizzle_immediate(reg.type, reg.ud, swizzle);
+ else
+ reg.swizzle = brw_compose_swizzle(swizzle, reg.swizzle);
+
return reg;
}
diff --git a/src/mesa/drivers/dri/i965/brw_reg.h b/src/mesa/drivers/dri/i965/brw_reg.h
index a4bcfca0b1d..74ff67fca5f 100644
--- a/src/mesa/drivers/dri/i965/brw_reg.h
+++ b/src/mesa/drivers/dri/i965/brw_reg.h
@@ -223,6 +223,7 @@ enum PACKED brw_reg_type {
unsigned brw_reg_type_to_hw_type(const struct brw_device_info *devinfo,
enum brw_reg_type 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)
@@ -876,9 +877,11 @@ get_element_d(struct brw_reg reg, unsigned elt)
static inline struct brw_reg
brw_swizzle(struct brw_reg reg, unsigned swz)
{
- assert(reg.file != BRW_IMMEDIATE_VALUE);
+ 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);
- reg.swizzle = brw_compose_swizzle(swz, reg.swizzle);
return reg;
}