diff options
author | Antia Puentes <[email protected]> | 2015-06-17 09:44:25 +0200 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-08-03 09:40:49 -0700 |
commit | 8e1e6facbf828258a9a8ca09da846d1baa21d984 (patch) | |
tree | 69394e1bd27a884c7018faa90492baf81185a9ac /src | |
parent | 0e874985ce50d902535e1eb766bd252c921b5d8f (diff) |
i965/nir/vec4: Implement bit operations
Same implementation than the IR case.
Adds NIR ALU operations:
* nir_op_bitfield_reverse
* nir_op_bit_count
* nir_op_ufind_msb
* nir_op_ifind_msb
* nir_op_find_lsb
* nir_op_ubitfield_extract
* nir_op_ibitfield_extract
* nir_op_bfm
* nir_op_bfi
* nir_op_bitfield_insert
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_vec4_nir.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index 87784db853a..e2357307ed3 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -1086,6 +1086,68 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) emit_pack_snorm_4x8(dst, op[0]); break; + case nir_op_bitfield_reverse: + emit(BFREV(dst, op[0])); + break; + + case nir_op_bit_count: + emit(CBIT(dst, op[0])); + break; + + case nir_op_ufind_msb: + case nir_op_ifind_msb: { + src_reg temp = src_reg(this, glsl_type::uint_type); + + inst = emit(FBH(dst_reg(temp), op[0])); + inst->dst.writemask = WRITEMASK_XYZW; + + /* FBH counts from the MSB side, while GLSL's findMSB() wants the count + * from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then + * subtract the result from 31 to convert the MSB count into an LSB count. + */ + + /* FBH only supports UD type for dst, so use a MOV to convert UD to D. */ + temp.swizzle = BRW_SWIZZLE_NOOP; + emit(MOV(dst, temp)); + + src_reg src_tmp = src_reg(dst); + emit(CMP(dst_null_d(), src_tmp, src_reg(-1), BRW_CONDITIONAL_NZ)); + + src_tmp.negate = true; + inst = emit(ADD(dst, src_tmp, src_reg(31))); + inst->predicate = BRW_PREDICATE_NORMAL; + break; + } + + case nir_op_find_lsb: + emit(FBL(dst, op[0])); + break; + + case nir_op_ubitfield_extract: + case nir_op_ibitfield_extract: + op[0] = fix_3src_operand(op[0]); + op[1] = fix_3src_operand(op[1]); + op[2] = fix_3src_operand(op[2]); + + emit(BFE(dst, op[2], op[1], op[0])); + break; + + case nir_op_bfm: + emit(BFI1(dst, op[0], op[1])); + break; + + case nir_op_bfi: + op[0] = fix_3src_operand(op[0]); + op[1] = fix_3src_operand(op[1]); + op[2] = fix_3src_operand(op[2]); + + emit(BFI2(dst, op[0], op[1], op[2])); + break; + + case nir_op_bitfield_insert: + unreachable("not reached: should be handled by " + "lower_instructions::bitfield_insert_to_bfm_bfi"); + default: unreachable("Unimplemented ALU operation"); } |