static bool
inst_is_split_send(const struct gen_device_info *devinfo, const brw_inst *inst)
{
- switch (brw_inst_opcode(devinfo, inst)) {
- case BRW_OPCODE_SENDS:
- case BRW_OPCODE_SENDSC:
- return true;
- default:
- return false;
+ if (devinfo->gen >= 12) {
+ return inst_is_send(devinfo, inst);
+ } else {
+ switch (brw_inst_opcode(devinfo, inst)) {
+ case BRW_OPCODE_SENDS:
+ case BRW_OPCODE_SENDSC:
+ return true;
+ default:
+ return false;
+ }
}
}
}
}
+static enum brw_reg_type
+inst_dst_type(const struct gen_device_info *devinfo, const brw_inst *inst)
+{
+ return (devinfo->gen < 12 || !inst_is_send(devinfo, inst)) ?
+ brw_inst_dst_type(devinfo, inst) : BRW_REGISTER_TYPE_D;
+}
+
static bool
inst_is_raw_move(const struct gen_device_info *devinfo, const brw_inst *inst)
{
- unsigned dst_type = signed_type(brw_inst_dst_type(devinfo, inst));
+ unsigned dst_type = signed_type(inst_dst_type(devinfo, inst));
unsigned src_type = signed_type(brw_inst_src0_type(devinfo, inst));
if (brw_inst_src0_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE) {
static bool
src0_is_null(const struct gen_device_info *devinfo, const brw_inst *inst)
{
- return brw_inst_src0_reg_file(devinfo, inst) == BRW_ARCHITECTURE_REGISTER_FILE &&
+ return brw_inst_src0_address_mode(devinfo, inst) == BRW_ADDRESS_DIRECT &&
+ brw_inst_src0_reg_file(devinfo, inst) == BRW_ARCHITECTURE_REGISTER_FILE &&
brw_inst_src0_da_reg_nr(devinfo, inst) == BRW_ARF_NULL;
}
(brw_inst_src1_da_reg_nr(devinfo, inst) & 0xF0) == BRW_ARF_ACCUMULATOR;
}
-static bool
-src0_is_grf(const struct gen_device_info *devinfo, const brw_inst *inst)
-{
- return brw_inst_src0_reg_file(devinfo, inst) == BRW_GENERAL_REGISTER_FILE;
-}
-
static bool
src0_has_scalar_region(const struct gen_device_info *devinfo, const brw_inst *inst)
{
if (inst_is_split_send(devinfo, inst))
return (struct string){};
- if (num_sources >= 1)
+ if (num_sources >= 1 && brw_inst_opcode(devinfo, inst) != BRW_OPCODE_SYNC)
ERROR_IF(src0_is_null(devinfo, inst), "src0 is null");
if (num_sources == 2)
"send must use direct addressing");
if (devinfo->gen >= 7) {
- ERROR_IF(!src0_is_grf(devinfo, inst), "send from non-GRF");
+ ERROR_IF(brw_inst_send_src0_reg_file(devinfo, inst) != BRW_GENERAL_REGISTER_FILE,
+ "send from non-GRF");
ERROR_IF(brw_inst_eot(devinfo, inst) &&
brw_inst_src0_da_reg_nr(devinfo, inst) < 112,
"send with EOT must use g112-g127");
/* Execution data type is independent of destination data type, except in
* mixed F/HF instructions.
*/
- enum brw_reg_type dst_exec_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_exec_type = inst_dst_type(devinfo, inst);
src0_exec_type = execution_type_for_type(brw_inst_src0_type(devinfo, inst));
if (num_sources == 1) {
*/
unsigned dst_stride = STRIDE(brw_inst_dst_hstride(devinfo, inst));
- enum brw_reg_type dst_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_type = inst_dst_type(devinfo, inst);
bool dst_type_is_byte =
- brw_inst_dst_type(devinfo, inst) == BRW_REGISTER_TYPE_B ||
- brw_inst_dst_type(devinfo, inst) == BRW_REGISTER_TYPE_UB;
+ inst_dst_type(devinfo, inst) == BRW_REGISTER_TYPE_B ||
+ inst_dst_type(devinfo, inst) == BRW_REGISTER_TYPE_UB;
if (dst_type_is_byte) {
if (is_packed(exec_size * dst_stride, exec_size, dst_stride)) {
unsigned offset = rowbase;
for (int x = 0; x < width; x++) {
- access_mask |= mask << offset;
+ access_mask |= mask << (offset % 64);
offset += hstride * element_size;
}
unsigned offset = rowbase;
for (int x = 0; x < width; x++) {
- access_mask[element++] = mask << offset;
+ access_mask[element++] = mask << (offset % 64);
offset += hstride * element_size;
}
return error_msg;
unsigned stride = STRIDE(brw_inst_dst_hstride(devinfo, inst));
- enum brw_reg_type dst_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_type = inst_dst_type(devinfo, inst);
unsigned element_size = brw_reg_type_to_size(dst_type);
unsigned subreg = brw_inst_dst_da1_subreg_nr(devinfo, inst);
unsigned offset = ((exec_size - 1) * stride * element_size) + subreg;
* is that the size of the destination type is 4 bytes.
*/
if (devinfo->gen <= 7 && dst_regs == 2) {
- enum brw_reg_type dst_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_type = inst_dst_type(devinfo, inst);
bool dst_is_packed_dword =
is_packed(exec_size * stride, exec_size, stride) &&
brw_reg_type_to_size(dst_type) == 4;
if (file != BRW_IMMEDIATE_VALUE)
return (struct string){};
- enum brw_reg_type dst_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_type = inst_dst_type(devinfo, inst);
unsigned dst_type_size = brw_reg_type_to_size(dst_type);
unsigned dst_subreg = brw_inst_access_mode(devinfo, inst) == BRW_ALIGN_1 ?
brw_inst_dst_da1_subreg_nr(devinfo, inst) : 0;
unsigned exec_type_size = brw_reg_type_to_size(exec_type);
enum brw_reg_file dst_file = brw_inst_dst_reg_file(devinfo, inst);
- enum brw_reg_type dst_type = brw_inst_dst_type(devinfo, inst);
+ enum brw_reg_type dst_type = inst_dst_type(devinfo, inst);
unsigned dst_type_size = brw_reg_type_to_size(dst_type);
unsigned dst_hstride = STRIDE(brw_inst_dst_hstride(devinfo, inst));
unsigned dst_reg = brw_inst_dst_da_reg_nr(devinfo, inst);
return error_msg;
}
+static struct string
+instruction_restrictions(const struct gen_device_info *devinfo,
+ const brw_inst *inst)
+{
+ struct string error_msg = { .str = NULL, .len = 0 };
+
+ /* From GEN:BUG:1604601757:
+ *
+ * "When multiplying a DW and any lower precision integer, source modifier
+ * is not supported."
+ */
+ if (devinfo->gen >= 12 &&
+ brw_inst_opcode(devinfo, inst) == BRW_OPCODE_MUL) {
+ enum brw_reg_type exec_type = execution_type(devinfo, inst);
+ const bool src0_valid = type_sz(brw_inst_src0_type(devinfo, inst)) == 4 ||
+ brw_inst_src0_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE ||
+ !(brw_inst_src0_negate(devinfo, inst) ||
+ brw_inst_src0_abs(devinfo, inst));
+ const bool src1_valid = type_sz(brw_inst_src1_type(devinfo, inst)) == 4 ||
+ brw_inst_src1_reg_file(devinfo, inst) == BRW_IMMEDIATE_VALUE ||
+ !(brw_inst_src1_negate(devinfo, inst) ||
+ brw_inst_src1_abs(devinfo, inst));
+
+ ERROR_IF(!brw_reg_type_is_floating_point(exec_type) &&
+ type_sz(exec_type) == 4 && !(src0_valid && src1_valid),
+ "When multiplying a DW and any lower precision integer, source "
+ "modifier is not supported.");
+ }
+
+ return error_msg;
+}
+
bool
brw_validate_instructions(const struct gen_device_info *devinfo,
const void *assembly, int start_offset, int end_offset,
CHECK(region_alignment_rules);
CHECK(vector_immediate_restrictions);
CHECK(special_requirements_for_handling_double_precision_data_types);
+ CHECK(instruction_restrictions);
}
if (error_msg.str && disasm) {