summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.c78
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.h11
2 files changed, 89 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
index cc44236..cd18b0c 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
@@ -71,6 +71,84 @@
#include "lp_bld_pack.h"
#include "lp_bld_conv.h"
#include "lp_bld_logic.h"
+#include "lp_bld_intr.h"
+
+
+
+/**
+ * Byte swap on element. It will construct a call to intrinsic llvm.bswap
+ * based on the type.
+ *
+ * @param res element to byte swap.
+ * @param type int16_t, int32_t, int64_t, float or double
+ * @param
+ */
+LLVMValueRef
+lp_build_bswap(struct gallivm_state *gallivm,
+ LLVMValueRef res,
+ struct lp_type type)
+{
+ LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context,
+ type.width);
+ const char *intrinsic = NULL;
+ if (type.width == 8)
+ return res;
+ if (type.width == 16)
+ intrinsic = "llvm.bswap.i16";
+ else if (type.width == 32)
+ intrinsic = "llvm.bswap.i32";
+ else if (type.width == 64)
+ intrinsic = "llvm.bswap.i64";
+
+ assert (intrinsic != NULL);
+
+ /* In case of a floating-point type cast to a int of same size and then
+ * cast back to fp type.
+ */
+ if (type.floating)
+ res = LLVMBuildBitCast(gallivm->builder, res, int_type, "");
+ res = lp_build_intrinsic_unary(gallivm->builder, intrinsic, int_type, res);
+ if (type.floating)
+ res = LLVMBuildBitCast(gallivm->builder, res,
+ lp_build_elem_type(gallivm, type), "");
+ return res;
+}
+
+
+/**
+ * Byte swap every element in the vector.
+ *
+ * @param packed <vector> to convert
+ * @param src_type <vector> type of int16_t, int32_t, int64_t, float or
+ * double
+ * @param dst_type <vector> type to return
+ */
+LLVMValueRef
+lp_build_bswap_vec(struct gallivm_state *gallivm,
+ LLVMValueRef packed,
+ struct lp_type src_type_vec,
+ struct lp_type dst_type_vec)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMTypeRef dst_type = lp_build_elem_type(gallivm, dst_type_vec);
+ LLVMValueRef res;
+
+ if (src_type_vec.length == 1) {
+ res = lp_build_bswap(gallivm, packed, src_type_vec);
+ res = LLVMBuildBitCast(gallivm->builder, res, dst_type, "");
+ } else {
+ unsigned i;
+ res = LLVMGetUndef(lp_build_vec_type(gallivm, dst_type_vec));
+ for (i = 0; i < src_type_vec.length; ++i) {
+ LLVMValueRef index = lp_build_const_int32(gallivm, i);
+ LLVMValueRef elem = LLVMBuildExtractElement(builder, packed, index, "");
+ elem = lp_build_bswap(gallivm, elem, src_type_vec);
+ elem = LLVMBuildBitCast(gallivm->builder, elem, dst_type, "");
+ res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, "");
+ }
+ }
+ return res;
+}
/**
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h
index 42a1113..d7dfed8 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h
@@ -43,6 +43,17 @@
struct lp_type;
LLVMValueRef
+lp_build_bswap(struct gallivm_state *gallivm,
+ LLVMValueRef res,
+ struct lp_type type);
+
+LLVMValueRef
+lp_build_bswap_vec(struct gallivm_state *gallivm,
+ LLVMValueRef packed,
+ struct lp_type src_type,
+ struct lp_type dst_type);
+
+LLVMValueRef
lp_build_half_to_float(struct gallivm_state *gallivm,
LLVMValueRef src);