util: Move gallium's PIPE_FORMAT utils to /util/format/
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_bitarit.c
index 706479b4d5616c5b9ca1d27628f3c6b755c039b1..f3fa5f490aad3cb349a38892276eefdeadcb2ce7 100644 (file)
@@ -40,6 +40,7 @@
 LLVMValueRef
 lp_build_or(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 {
+   LLVMBuilderRef builder = bld->gallivm->builder;
    const struct lp_type type = bld->type;
    LLVMValueRef res;
 
@@ -48,19 +49,44 @@ lp_build_or(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 
    /* can't do bitwise ops on floating-point values */
    if (type.floating) {
-      a = LLVMBuildBitCast(bld->builder, a, bld->int_vec_type, "");
-      b = LLVMBuildBitCast(bld->builder, b, bld->int_vec_type, "");
+      a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
+      b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
    }
 
-   res = LLVMBuildOr(bld->builder, a, b, "");
+   res = LLVMBuildOr(builder, a, b, "");
 
    if (type.floating) {
-      res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
+      res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
    }
 
    return res;
 }
 
+/* bitwise XOR (a ^ b) */
+LLVMValueRef
+lp_build_xor(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
+{
+   LLVMBuilderRef builder = bld->gallivm->builder;
+   const struct lp_type type = bld->type;
+   LLVMValueRef res;
+
+   assert(lp_check_value(type, a));
+   assert(lp_check_value(type, b));
+
+   /* can't do bitwise ops on floating-point values */
+   if (type.floating) {
+      a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
+      b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
+   }
+
+   res = LLVMBuildXor(builder, a, b, "");
+
+   if (type.floating) {
+      res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
+   }
+
+   return res;
+}
 
 /**
  * Return (a & b)
@@ -68,6 +94,7 @@ lp_build_or(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 LLVMValueRef
 lp_build_and(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 {
+   LLVMBuilderRef builder = bld->gallivm->builder;
    const struct lp_type type = bld->type;
    LLVMValueRef res;
 
@@ -76,14 +103,14 @@ lp_build_and(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 
    /* can't do bitwise ops on floating-point values */
    if (type.floating) {
-      a = LLVMBuildBitCast(bld->builder, a, bld->int_vec_type, "");
-      b = LLVMBuildBitCast(bld->builder, b, bld->int_vec_type, "");
+      a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
+      b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
    }
 
-   res = LLVMBuildAnd(bld->builder, a, b, "");
+   res = LLVMBuildAnd(builder, a, b, "");
 
    if (type.floating) {
-      res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
+      res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
    }
 
    return res;
@@ -96,6 +123,7 @@ lp_build_and(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 LLVMValueRef
 lp_build_andnot(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 {
+   LLVMBuilderRef builder = bld->gallivm->builder;
    const struct lp_type type = bld->type;
    LLVMValueRef res;
 
@@ -104,27 +132,48 @@ lp_build_andnot(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 
    /* can't do bitwise ops on floating-point values */
    if (type.floating) {
-      a = LLVMBuildBitCast(bld->builder, a, bld->int_vec_type, "");
-      b = LLVMBuildBitCast(bld->builder, b, bld->int_vec_type, "");
+      a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
+      b = LLVMBuildBitCast(builder, b, bld->int_vec_type, "");
    }
 
-   res = LLVMBuildNot(bld->builder, b, "");
-   res = LLVMBuildAnd(bld->builder, a, res, "");
+   res = LLVMBuildNot(builder, b, "");
+   res = LLVMBuildAnd(builder, a, res, "");
 
    if (type.floating) {
-      res = LLVMBuildBitCast(bld->builder, res, bld->vec_type, "");
+      res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
    }
 
    return res;
 }
 
+/* bitwise NOT */
+LLVMValueRef
+lp_build_not(struct lp_build_context *bld, LLVMValueRef a)
+{
+   LLVMBuilderRef builder = bld->gallivm->builder;
+   const struct lp_type type = bld->type;
+   LLVMValueRef res;
+
+   assert(lp_check_value(type, a));
+
+   if (type.floating) {
+      a = LLVMBuildBitCast(builder, a, bld->int_vec_type, "");
+   }
+   res = LLVMBuildNot(builder, a, "");
+   if (type.floating) {
+      res = LLVMBuildBitCast(builder, res, bld->vec_type, "");
+   }
+   return res;
+}
 
 /**
  * Shift left.
+ * Result is undefined if the shift count is not smaller than the type width.
  */
 LLVMValueRef
 lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 {
+   LLVMBuilderRef builder = bld->gallivm->builder;
    const struct lp_type type = bld->type;
    LLVMValueRef res;
 
@@ -133,7 +182,9 @@ lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
    assert(lp_check_value(type, a));
    assert(lp_check_value(type, b));
 
-   res = LLVMBuildShl(bld->builder, a, b, "");
+   (void)type;
+
+   res = LLVMBuildShl(builder, a, b, "");
 
    return res;
 }
@@ -141,10 +192,12 @@ lp_build_shl(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 
 /**
  * Shift right.
+ * Result is undefined if the shift count is not smaller than the type width.
  */
 LLVMValueRef
 lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 {
+   LLVMBuilderRef builder = bld->gallivm->builder;
    const struct lp_type type = bld->type;
    LLVMValueRef res;
 
@@ -154,9 +207,9 @@ lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
    assert(lp_check_value(type, b));
 
    if (type.sign) {
-      res = LLVMBuildAShr(bld->builder, a, b, "");
+      res = LLVMBuildAShr(builder, a, b, "");
    } else {
-      res = LLVMBuildLShr(bld->builder, a, b, "");
+      res = LLVMBuildLShr(builder, a, b, "");
    }
 
    return res;
@@ -165,23 +218,25 @@ lp_build_shr(struct lp_build_context *bld, LLVMValueRef a, LLVMValueRef b)
 
 /**
  * Shift left with immediate.
+ * The immediate shift count must be smaller than the type width.
  */
 LLVMValueRef
 lp_build_shl_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
 {
-   LLVMValueRef b = lp_build_const_int_vec(bld->type, imm);
-   assert(imm <= bld->type.width);
+   LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
+   assert(imm < bld->type.width);
    return lp_build_shl(bld, a, b);
 }
 
 
 /**
  * Shift right with immediate.
+ * The immediate shift count must be smaller than the type width.
  */
 LLVMValueRef
 lp_build_shr_imm(struct lp_build_context *bld, LLVMValueRef a, unsigned imm)
 {
-   LLVMValueRef b = lp_build_const_int_vec(bld->type, imm);
-   assert(imm <= bld->type.width);
+   LLVMValueRef b = lp_build_const_int_vec(bld->gallivm, bld->type, imm);
+   assert(imm < bld->type.width);
    return lp_build_shr(bld, a, b);
 }