#include "brw_eu.h"
#include "brw_fs.h"
#include "brw_cfg.h"
+#include "brw_program.h"
static enum brw_reg_file
brw_file_from_reg(fs_reg *reg)
{
switch (reg->file) {
- case GRF:
+ case ARF:
+ return BRW_ARCHITECTURE_REGISTER_FILE;
+ case FIXED_GRF:
+ case VGRF:
return BRW_GENERAL_REGISTER_FILE;
case MRF:
return BRW_MESSAGE_REGISTER_FILE;
case IMM:
return BRW_IMMEDIATE_VALUE;
case BAD_FILE:
- case HW_REG:
case ATTR:
case UNIFORM:
unreachable("not reached");
switch (reg->file) {
case MRF:
- assert((reg->reg & ~(1 << 7)) < BRW_MAX_MRF(gen));
+ assert((reg->nr & ~BRW_MRF_COMPR4) < BRW_MAX_MRF(gen));
/* Fallthrough */
- case GRF:
+ case VGRF:
if (reg->stride == 0) {
- brw_reg = brw_vec1_reg(brw_file_from_reg(reg), reg->reg, 0);
+ brw_reg = brw_vec1_reg(brw_file_from_reg(reg), reg->nr, 0);
} else if (inst->exec_size < 8) {
- brw_reg = brw_vec8_reg(brw_file_from_reg(reg), reg->reg, 0);
+ brw_reg = brw_vec8_reg(brw_file_from_reg(reg), reg->nr, 0);
brw_reg = stride(brw_reg, inst->exec_size * reg->stride,
inst->exec_size, reg->stride);
} else {
* So, for registers with width > 8, we have to use a width of 8
* and trust the compression state to sort out the exec size.
*/
- brw_reg = brw_vec8_reg(brw_file_from_reg(reg), reg->reg, 0);
+ brw_reg = brw_vec8_reg(brw_file_from_reg(reg), reg->nr, 0);
brw_reg = stride(brw_reg, 8 * reg->stride, 8, reg->stride);
}
brw_reg = retype(brw_reg, reg->type);
brw_reg = byte_offset(brw_reg, reg->subreg_offset);
+ brw_reg.abs = reg->abs;
+ brw_reg.negate = reg->negate;
break;
+ case ARF:
+ case FIXED_GRF:
case IMM:
- assert(reg->stride == ((reg->type == BRW_REGISTER_TYPE_V ||
- reg->type == BRW_REGISTER_TYPE_UV ||
- reg->type == BRW_REGISTER_TYPE_VF) ? 1 : 0));
-
- switch (reg->type) {
- case BRW_REGISTER_TYPE_F:
- brw_reg = brw_imm_f(reg->fixed_hw_reg.f);
- break;
- case BRW_REGISTER_TYPE_D:
- brw_reg = brw_imm_d(reg->fixed_hw_reg.d);
- break;
- case BRW_REGISTER_TYPE_UD:
- brw_reg = brw_imm_ud(reg->fixed_hw_reg.ud);
- break;
- case BRW_REGISTER_TYPE_W:
- brw_reg = brw_imm_w(reg->fixed_hw_reg.d);
- break;
- case BRW_REGISTER_TYPE_UW:
- brw_reg = brw_imm_uw(reg->fixed_hw_reg.ud);
- break;
- case BRW_REGISTER_TYPE_VF:
- brw_reg = brw_imm_vf(reg->fixed_hw_reg.ud);
- break;
- default:
- unreachable("not reached");
- }
- break;
- case HW_REG:
- assert(reg->type == reg->fixed_hw_reg.type);
- brw_reg = reg->fixed_hw_reg;
+ brw_reg = reg->as_brw_reg();
break;
case BAD_FILE:
/* Probably unused. */
case UNIFORM:
unreachable("not reached");
}
- if (reg->abs)
- brw_reg = brw_abs(brw_reg);
- if (reg->negate)
- brw_reg = negate(brw_reg);
return brw_reg;
}
}
}
+void
+fs_generator::generate_mov_indirect(fs_inst *inst,
+ struct brw_reg dst,
+ struct brw_reg reg,
+ struct brw_reg indirect_byte_offset)
+{
+ assert(indirect_byte_offset.type == BRW_REGISTER_TYPE_UD);
+ assert(indirect_byte_offset.file == BRW_GENERAL_REGISTER_FILE);
+
+ unsigned imm_byte_offset = reg.nr * REG_SIZE + reg.subnr;
+
+ /* We use VxH indirect addressing, clobbering a0.0 through a0.7. */
+ struct brw_reg addr = vec8(brw_address_reg(0));
+
+ /* The destination stride of an instruction (in bytes) must be greater
+ * than or equal to the size of the rest of the instruction. Since the
+ * address register is of type UW, we can't use a D-type instruction.
+ * In order to get around this, re re-type to UW and use a stride.
+ */
+ indirect_byte_offset =
+ retype(spread(indirect_byte_offset, 2), BRW_REGISTER_TYPE_UW);
+
+ /* Prior to Broadwell, there are only 8 address registers. */
+ assert(inst->exec_size == 8 || devinfo->gen >= 8);
+
+ brw_MOV(p, addr, indirect_byte_offset);
+ brw_inst_set_mask_control(devinfo, brw_last_inst, BRW_MASK_DISABLE);
+ brw_MOV(p, dst, retype(brw_VxH_indirect(0, imm_byte_offset), dst.type));
+}
+
void
fs_generator::generate_urb_read(fs_inst *inst,
struct brw_reg dst,
brw_inst_set_sfid(p->devinfo, send, BRW_SFID_URB);
brw_inst_set_urb_opcode(p->devinfo, send, GEN8_URB_OPCODE_SIMD8_READ);
+ if (inst->opcode == SHADER_OPCODE_URB_READ_SIMD8_PER_SLOT)
+ brw_inst_set_urb_per_slot_offset(p->devinfo, send, true);
+
brw_inst_set_mlen(p->devinfo, send, inst->mlen);
brw_inst_set_rlen(p->devinfo, send, inst->regs_written);
brw_inst_set_header_present(p->devinfo, send, true);
break;
}
+ /* Stomp the resinfo output type to UINT32. On gens 4-5, the output type
+ * is set as part of the message descriptor. On gen4, the PRM seems to
+ * allow UINT32 and FLOAT32 (i965 PRM, Vol. 4 Section 4.8.1.1), but on
+ * later gens UINT32 is required. Once you hit Sandy Bridge, the bit is
+ * gone from the message descriptor entirely and you just get UINT32 all
+ * the time regasrdless. Since we can really only do non-UINT32 on gen4,
+ * just stomp it to UINT32 all the time.
+ */
+ if (inst->opcode == SHADER_OPCODE_TXS)
+ return_format = BRW_SAMPLER_RETURN_FORMAT_UINT32;
+
switch (inst->exec_size) {
case 8:
simd_mode = BRW_SAMPLER_SIMD_MODE_SIMD8;
fill_count++;
break;
+ case SHADER_OPCODE_MOV_INDIRECT:
+ generate_mov_indirect(inst, dst, src[0], src[1]);
+ break;
+
case SHADER_OPCODE_URB_READ_SIMD8:
+ case SHADER_OPCODE_URB_READ_SIMD8_PER_SLOT:
generate_urb_read(inst, dst, src[0]);
break;