From 88e5f1fdf847a0ce284b8a01ff2cf3fb36e2b07c Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 9 Apr 2013 09:59:15 +0800 Subject: assembler/bdw: Add the support of align1 register-indirect addressing mode on Gen8 Otherwise it can't compile the following GPU shader that uses the register-indirect addressing mode. >add.sat (16) r[a0.5,0]<1>:uw r[a0.5,0]<16;16,1>:uw 0x0080:uw >add.sat (16) r[a0.5,32]<1>:uw r[a0.5,32]<16;16,1>:uw 0x0080:uw Signed-off-by: Zhao Yakui Signed-off-by: Ben Widawsky --- assembler/gen8_instruction.c | 80 +++++++++++++++++++++++++++++++++++--------- assembler/gen8_instruction.h | 24 +++++++++++++ assembler/gram.y | 12 +++++++ 3 files changed, 101 insertions(+), 15 deletions(-) (limited to 'assembler') diff --git a/assembler/gen8_instruction.c b/assembler/gen8_instruction.c index 7fb1eacd..31c15ca3 100644 --- a/assembler/gen8_instruction.c +++ b/assembler/gen8_instruction.c @@ -47,23 +47,38 @@ gen8_set_dst(struct gen8_instruction *inst, struct brw_reg reg) gen8_set_dst_reg_file(inst, reg.file); gen8_set_dst_reg_type(inst, reg.type); - assert(reg.address_mode == BRW_ADDRESS_DIRECT); + if (reg.address_mode == BRW_ADDRESS_DIRECT) { + gen8_set_dst_da_reg_nr(inst, reg.nr); - gen8_set_dst_da_reg_nr(inst, reg.nr); + if (gen8_access_mode(inst) == BRW_ALIGN_1) { + /* Set Dst.SubRegNum[4:0] */ + gen8_set_dst_da1_subreg_nr(inst, reg.subnr); - if (gen8_access_mode(inst) == BRW_ALIGN_1) { - /* Set Dst.SubRegNum[4:0] */ - gen8_set_dst_da1_subreg_nr(inst, reg.subnr); + /* Set Dst.HorzStride */ + if (reg.hstride == BRW_HORIZONTAL_STRIDE_0) + reg.hstride = BRW_HORIZONTAL_STRIDE_1; + gen8_set_dst_da1_hstride(inst, reg.hstride); + } else { + /* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */ + assert(reg.subnr == 0 || reg.subnr == 16); + gen8_set_dst_da16_subreg_nr(inst, reg.subnr >> 4); + gen8_set_da16_writemask(inst, reg.dw1.bits.writemask); + } + } else { + /* Indirect mode */ + assert (gen8_access_mode(inst) == BRW_ALIGN_1); + gen8_set_dst_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER); /* Set Dst.HorzStride */ if (reg.hstride == BRW_HORIZONTAL_STRIDE_0) reg.hstride = BRW_HORIZONTAL_STRIDE_1; gen8_set_dst_da1_hstride(inst, reg.hstride); - } else { - /* Align16 SubRegNum only has a single bit (bit 4; bits 3:0 MBZ). */ - assert(reg.subnr == 0 || reg.subnr == 16); - gen8_set_dst_da16_subreg_nr(inst, reg.subnr >> 4); - gen8_set_da16_writemask(inst, reg.dw1.bits.writemask); + gen8_set_dst_ida1_sub_nr(inst, reg.subnr); + gen8_set_dst_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK)); + if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK) + gen8_set_dst_ida1_imm9(inst, 1); + else + gen8_set_dst_ida1_imm9(inst, 0); } /* Generators should set a default exec_size of either 8 (SIMD4x2 or SIMD8) @@ -160,7 +175,6 @@ gen8_set_src0(struct gen8_instruction *inst, struct brw_reg reg) gen8_set_src0_abs(inst, reg.abs); gen8_set_src0_negate(inst, reg.negate); - assert(reg.address_mode == BRW_ADDRESS_DIRECT); if (reg.file == BRW_IMMEDIATE_VALUE) { inst->data[3] = reg.dw1.ud; @@ -168,7 +182,7 @@ gen8_set_src0(struct gen8_instruction *inst, struct brw_reg reg) /* Required to set some fields in src1 as well: */ gen8_set_src1_reg_file(inst, 0); /* arf */ gen8_set_src1_reg_type(inst, reg.type); - } else { + } else if (reg.address_mode == BRW_ADDRESS_DIRECT) { gen8_set_src0_da_reg_nr(inst, reg.nr); if (gen8_access_mode(inst) == BRW_ALIGN_1) { @@ -211,6 +225,25 @@ gen8_set_src0(struct gen8_instruction *inst, struct brw_reg reg) else gen8_set_src0_vert_stride(inst, reg.vstride); } + } else if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER) { + assert (gen8_access_mode(inst) == BRW_ALIGN_1); + if (reg.width == BRW_WIDTH_1 && + gen8_exec_size(inst) == BRW_EXECUTE_1) { + gen8_set_src0_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0); + gen8_set_src0_vert_stride(inst, BRW_VERTICAL_STRIDE_0); + } else { + gen8_set_src0_da1_hstride(inst, reg.hstride); + gen8_set_src0_vert_stride(inst, reg.vstride); + } + + gen8_set_src0_da1_width(inst, reg.width); + gen8_set_src0_ida1_sub_nr(inst, reg.subnr); + gen8_set_src0_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER); + gen8_set_src0_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK)); + if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK) + gen8_set_src0_ida1_imm9(inst, 1); + else + gen8_set_src0_ida1_imm9(inst, 0); } } @@ -236,11 +269,9 @@ gen8_set_src1(struct gen8_instruction *inst, struct brw_reg reg) /* Only src1 can be an immediate in two-argument instructions. */ assert(gen8_src0_reg_file(inst) != BRW_IMMEDIATE_VALUE); - assert(reg.address_mode == BRW_ADDRESS_DIRECT); - if (reg.file == BRW_IMMEDIATE_VALUE) { inst->data[3] = reg.dw1.ud; - } else { + } else if (reg.address_mode == BRW_ADDRESS_DIRECT) { gen8_set_src1_da_reg_nr(inst, reg.nr); if (gen8_access_mode(inst) == BRW_ALIGN_1) { @@ -282,6 +313,25 @@ gen8_set_src1(struct gen8_instruction *inst, struct brw_reg reg) else gen8_set_src1_vert_stride(inst, reg.vstride); } + } else if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER) { + assert (gen8_access_mode(inst) == BRW_ALIGN_1); + if (reg.width == BRW_WIDTH_1 && + gen8_exec_size(inst) == BRW_EXECUTE_1) { + gen8_set_src1_da1_hstride(inst, BRW_HORIZONTAL_STRIDE_0); + gen8_set_src1_vert_stride(inst, BRW_VERTICAL_STRIDE_0); + } else { + gen8_set_src1_da1_hstride(inst, reg.hstride); + gen8_set_src1_vert_stride(inst, reg.vstride); + } + + gen8_set_src1_da1_width(inst, reg.width); + gen8_set_src1_ida1_sub_nr(inst, reg.subnr); + gen8_set_src1_addr_mode(inst, BRW_ADDRESS_REGISTER_INDIRECT_REGISTER); + gen8_set_src1_ida1_imm8(inst, (reg.dw1.bits.indirect_offset & IMM8_MASK)); + if ((reg.dw1.bits.indirect_offset & IMM9_MASK) == IMM9_MASK) + gen8_set_src1_ida1_imm9(inst, 1); + else + gen8_set_src1_ida1_imm9(inst, 0); } } diff --git a/assembler/gen8_instruction.h b/assembler/gen8_instruction.h index 87fa3a92..5e72e457 100644 --- a/assembler/gen8_instruction.h +++ b/assembler/gen8_instruction.h @@ -224,8 +224,32 @@ F(cre_message_type, 110, 109) F(cre_binding_table_index, 103, 96) /** @} */ +/* Addr Mode */ + +F(dst_addr_mode, 63, 63) +F(src0_addr_mode, 79, 79) +F(src1_addr_mode, 111, 111) + +/* Indirect access mode for Align1. */ +F(dst_ida1_sub_nr, 60, 57) +F(src0_ida1_sub_nr, 76, 73) +F(src1_ida1_sub_nr, 108, 105) + +/* Imm[8:0] of Immediate addr offset under Indirect mode */ +F(dst_ida1_imm8, 56, 48) +F(src0_ida1_imm8, 72, 64) +F(src1_ida1_imm8, 104, 96) + +/* Imm Bit9 of Immediate addr offset under Indirect mode */ +F(dst_ida1_imm9, 47, 47) +F(src0_ida1_imm9, 95, 95) +F(src1_ida1_imm9, 121, 121) + #undef F +#define IMM8_MASK 0x1FF +#define IMM9_MASK 0x200 + /** * Flow control instruction bits: * @{ diff --git a/assembler/gram.y b/assembler/gram.y index 5671a0f4..03f1be64 100644 --- a/assembler/gram.y +++ b/assembler/gram.y @@ -294,6 +294,12 @@ static bool validate_dst_reg(struct brw_program_instruction *insn, struct brw_re return false; } + if (reg->address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER && + access_mode(insn) == BRW_ALIGN_16) { + fprintf(stderr, "error: indirect Dst addr mode in align16 instruction\n"); + return false; + } + return true; } @@ -317,6 +323,12 @@ static bool validate_src_reg(struct brw_program_instruction *insn, return false; } + if (reg.address_mode == BRW_ADDRESS_REGISTER_INDIRECT_REGISTER && + access_mode(insn) == BRW_ALIGN_16) { + fprintf(stderr, "error: indirect Source addr mode in align16 instruction\n"); + return false; + } + assert(reg.hstride >= 0 && reg.hstride < ARRAY_SIZE(hstride_for_reg)); hstride = hstride_for_reg[reg.hstride]; -- cgit v1.2.3