+void
+vec4_visitor::emit_unpack_unorm_4x8(const dst_reg &dst, src_reg src0)
+{
+ /* Instead of splitting the 32-bit integer, shifting, and ORing it back
+ * together, we can shift it by <0, 8, 16, 24>. The packed integer immediate
+ * is not suitable to generate the shift values, but we can use the packed
+ * vector float and a type-converting MOV.
+ */
+ dst_reg shift(this, glsl_type::uvec4_type);
+ emit(MOV(shift, src_reg(0x00, 0x60, 0x70, 0x78)));
+
+ dst_reg shifted(this, glsl_type::uvec4_type);
+ src0.swizzle = BRW_SWIZZLE_XXXX;
+ emit(SHR(shifted, src0, src_reg(shift)));
+
+ shifted.type = BRW_REGISTER_TYPE_UB;
+ dst_reg f(this, glsl_type::vec4_type);
+ emit(VEC4_OPCODE_MOV_BYTES, f, src_reg(shifted));
+
+ emit(MUL(dst, src_reg(f), src_reg(1.0f / 255.0f)));
+}
+
+void
+vec4_visitor::emit_unpack_snorm_4x8(const dst_reg &dst, src_reg src0)
+{
+ /* Instead of splitting the 32-bit integer, shifting, and ORing it back
+ * together, we can shift it by <0, 8, 16, 24>. The packed integer immediate
+ * is not suitable to generate the shift values, but we can use the packed
+ * vector float and a type-converting MOV.
+ */
+ dst_reg shift(this, glsl_type::uvec4_type);
+ emit(MOV(shift, src_reg(0x00, 0x60, 0x70, 0x78)));
+
+ dst_reg shifted(this, glsl_type::uvec4_type);
+ src0.swizzle = BRW_SWIZZLE_XXXX;
+ emit(SHR(shifted, src0, src_reg(shift)));
+
+ shifted.type = BRW_REGISTER_TYPE_B;
+ dst_reg f(this, glsl_type::vec4_type);
+ emit(VEC4_OPCODE_MOV_BYTES, f, src_reg(shifted));
+
+ dst_reg scaled(this, glsl_type::vec4_type);
+ emit(MUL(scaled, src_reg(f), src_reg(1.0f / 127.0f)));
+
+ dst_reg max(this, glsl_type::vec4_type);
+ emit_minmax(BRW_CONDITIONAL_GE, max, src_reg(scaled), src_reg(-1.0f));
+ emit_minmax(BRW_CONDITIONAL_L, dst, src_reg(max), src_reg(1.0f));
+}
+
+void
+vec4_visitor::emit_pack_unorm_4x8(const dst_reg &dst, const src_reg &src0)
+{
+ dst_reg saturated(this, glsl_type::vec4_type);
+ vec4_instruction *inst = emit(MOV(saturated, src0));
+ inst->saturate = true;
+
+ dst_reg scaled(this, glsl_type::vec4_type);
+ emit(MUL(scaled, src_reg(saturated), src_reg(255.0f)));
+
+ dst_reg rounded(this, glsl_type::vec4_type);
+ emit(RNDE(rounded, src_reg(scaled)));
+
+ dst_reg u(this, glsl_type::uvec4_type);
+ emit(MOV(u, src_reg(rounded)));
+
+ src_reg bytes(u);
+ emit(VEC4_OPCODE_PACK_BYTES, dst, bytes);
+}
+
+void
+vec4_visitor::emit_pack_snorm_4x8(const dst_reg &dst, const src_reg &src0)
+{
+ dst_reg max(this, glsl_type::vec4_type);
+ emit_minmax(BRW_CONDITIONAL_GE, max, src0, src_reg(-1.0f));
+
+ dst_reg min(this, glsl_type::vec4_type);
+ emit_minmax(BRW_CONDITIONAL_L, min, src_reg(max), src_reg(1.0f));
+
+ dst_reg scaled(this, glsl_type::vec4_type);
+ emit(MUL(scaled, src_reg(min), src_reg(127.0f)));
+
+ dst_reg rounded(this, glsl_type::vec4_type);
+ emit(RNDE(rounded, src_reg(scaled)));
+
+ dst_reg i(this, glsl_type::ivec4_type);
+ emit(MOV(i, src_reg(rounded)));
+
+ src_reg bytes(i);
+ emit(VEC4_OPCODE_PACK_BYTES, dst, bytes);
+}
+