return (file == r.file &&
reg == r.reg &&
reg_offset == r.reg_offset &&
+ subreg_offset == r.subreg_offset &&
type == r.type &&
negate == r.negate &&
abs == r.abs &&
constant_nr % 8);
inst->src[i].file = HW_REG;
- inst->src[i].fixed_hw_reg = retype(brw_reg, inst->src[i].type);
+ inst->src[i].fixed_hw_reg = byte_offset(
+ retype(brw_reg, inst->src[i].type),
+ inst->src[i].subreg_offset);
}
}
}
inst->is_partial_write() ||
inst->dst.file != MRF || inst->src[0].file != GRF ||
inst->dst.type != inst->src[0].type ||
- inst->src[0].abs || inst->src[0].negate || inst->src[0].smear != -1)
+ inst->src[0].abs || inst->src[0].negate ||
+ inst->src[0].smear != -1 || inst->src[0].subreg_offset)
continue;
/* Work out which hardware MRF registers are written by this
switch (inst->dst.file) {
case GRF:
printf("vgrf%d", inst->dst.reg);
- if (virtual_grf_sizes[inst->dst.reg] != 1)
- printf("+%d", inst->dst.reg_offset);
+ if (virtual_grf_sizes[inst->dst.reg] != 1 ||
+ inst->dst.subreg_offset)
+ printf("+%d.%d", inst->dst.reg_offset, inst->dst.subreg_offset);
break;
case MRF:
printf("m%d", inst->dst.reg);
switch (inst->src[i].file) {
case GRF:
printf("vgrf%d", inst->src[i].reg);
- if (virtual_grf_sizes[inst->src[i].reg] != 1)
- printf("+%d", inst->src[i].reg_offset);
+ if (virtual_grf_sizes[inst->src[i].reg] != 1 ||
+ inst->src[i].subreg_offset)
+ printf("+%d.%d", inst->src[i].reg_offset,
+ inst->src[i].subreg_offset);
break;
case MRF:
printf("***m%d***", inst->src[i].reg);
break;
case UNIFORM:
printf("u%d", inst->src[i].reg);
- if (virtual_grf_sizes[inst->src[i].reg] != 1)
- printf(".%d", inst->src[i].reg_offset);
+ if (virtual_grf_sizes[inst->src[i].reg] != 1 ||
+ inst->src[i].subreg_offset)
+ printf("+%d.%d", inst->src[i].reg_offset,
+ inst->src[i].subreg_offset);
break;
case BAD_FILE:
printf("(null)");
float f;
} imm;
+ /**
+ * Offset in bytes from the start of the register. Values up to a
+ * backend_reg::reg_offset unit are valid.
+ */
+ int subreg_offset;
+
fs_reg *reladdr;
};
+static inline fs_reg
+byte_offset(fs_reg reg, unsigned delta)
+{
+ assert(delta == 0 || (reg.file != HW_REG && reg.file != IMM));
+ reg.subreg_offset += delta;
+ return reg;
+}
+
static const fs_reg reg_undef;
static const fs_reg reg_null_f(retype(brw_null_reg(), BRW_REGISTER_TYPE_F));
static const fs_reg reg_null_d(retype(brw_null_reg(), BRW_REGISTER_TYPE_D));
if (inst->src[arg].file != entry->dst.file ||
inst->src[arg].reg != entry->dst.reg ||
- inst->src[arg].reg_offset != entry->dst.reg_offset) {
+ inst->src[arg].reg_offset != entry->dst.reg_offset ||
+ inst->src[arg].subreg_offset != entry->dst.subreg_offset) {
return false;
}
inst->src[arg].reg_offset = entry->src.reg_offset;
if (entry->src.smear != -1)
inst->src[arg].smear = entry->src.smear;
+ inst->src[arg].subreg_offset = entry->src.subreg_offset;
if (!inst->src[arg].abs) {
inst->src[arg].abs = entry->src.abs;
for (int i = 2; i >= 0; i--) {
if (inst->src[i].file != entry->dst.file ||
inst->src[i].reg != entry->dst.reg ||
- inst->src[i].reg_offset != entry->dst.reg_offset)
+ inst->src[i].reg_offset != entry->dst.reg_offset ||
+ inst->src[i].subreg_offset != entry->dst.subreg_offset)
continue;
/* Don't bother with cases that should have been taken care of by the
brw_reg = retype(brw_reg, reg->type);
if (reg->sechalf)
brw_reg = sechalf(brw_reg);
+ brw_reg = byte_offset(brw_reg, reg->subreg_offset);
break;
case IMM:
switch (reg->type) {
int regs_read = inst->regs_read(this, i);
int subset_spill_offset = (spill_offset +
reg_size * inst->src[i].reg_offset);
+ fs_reg unspill_dst(GRF, virtual_grf_alloc(regs_read));
- inst->src[i].reg = virtual_grf_alloc(regs_read);
+ inst->src[i].reg = unspill_dst.reg;
inst->src[i].reg_offset = 0;
- emit_unspill(inst, inst->src[i], subset_spill_offset, regs_read);
+ emit_unspill(inst, unspill_dst, subset_spill_offset, regs_read);
}
}
inst->dst.reg == spill_reg) {
int subset_spill_offset = (spill_offset +
reg_size * inst->dst.reg_offset);
- inst->dst.reg = virtual_grf_alloc(inst->regs_written);
+ fs_reg spill_src(GRF, virtual_grf_alloc(inst->regs_written));
+
+ inst->dst.reg = spill_src.reg;
inst->dst.reg_offset = 0;
/* If our write is going to affect just part of the
* inst->regs_written(), then we need to unspill the destination
* since we write back out all of the regs_written().
*/
- if (inst->predicate || inst->force_uncompressed || inst->force_sechalf) {
- emit_unspill(inst, inst->dst, subset_spill_offset,
+ if (inst->predicate || inst->force_uncompressed ||
+ inst->force_sechalf || inst->dst.subreg_offset) {
+ emit_unspill(inst, spill_src, subset_spill_offset,
inst->regs_written);
}
- fs_reg spill_src = inst->dst;
- spill_src.reg_offset = 0;
- spill_src.abs = false;
- spill_src.negate = false;
- spill_src.smear = -1;
-
for (int chan = 0; chan < inst->regs_written; chan++) {
fs_inst *spill_inst =
new(mem_ctx) fs_inst(SHADER_OPCODE_GEN4_SCRATCH_WRITE,