i965g: fix some reloc counts
[mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_const.c
index fe1c627eeebadfb7fe0a88268676202c6707154e..c8eaa8c394068225080b7bd1a4190013569b4d29 100644 (file)
@@ -33,6 +33,7 @@
  * @author Jose Fonseca <jfonseca@vmware.com>
  */
 
+#include <float.h>
 
 #include "util/u_debug.h"
 
 #include "lp_bld_const.h"
 
 
+unsigned
+lp_mantissa(struct lp_type type)
+{
+   assert(type.floating);
+
+   if(type.floating) {
+      switch(type.width) {
+      case 32:
+         return 23;
+      case 64:
+         return 53;
+      default:
+         assert(0);
+         return 0;
+      }
+   }
+   else {
+      if(type.sign)
+         return type.width - 1;
+      else
+         return type.width;
+   }
+}
+
+
+/**
+ * Shift of the unity.
+ *
+ * Same as lp_const_scale(), but in terms of shifts.
+ */
+unsigned
+lp_const_shift(struct lp_type type)
+{
+   if(type.floating)
+      return 0;
+   else if(type.fixed)
+      return type.width/2;
+   else if(type.norm)
+      return type.sign ? type.width - 1 : type.width;
+   else
+      return 0;
+}
+
+
+unsigned
+lp_const_offset(struct lp_type type)
+{
+   if(type.floating || type.fixed)
+      return 0;
+   else if(type.norm)
+      return 1;
+   else
+      return 0;
+}
+
+
+/**
+ * Scaling factor between the LLVM native value and its interpretation.
+ *
+ * This is 1.0 for all floating types and unnormalized integers, and something
+ * else for the fixed points types and normalized integers.
+ */
+double
+lp_const_scale(struct lp_type type)
+{
+   unsigned long long llscale;
+   double dscale;
+
+   llscale = (unsigned long long)1 << lp_const_shift(type);
+   llscale -= lp_const_offset(type);
+   dscale = (double)llscale;
+   assert((unsigned long long)dscale == llscale);
+
+   return dscale;
+}
+
+
+/**
+ * Minimum value representable by the type.
+ */
+double
+lp_const_min(struct lp_type type)
+{
+   unsigned bits;
+
+   if(!type.sign)
+      return 0.0;
+
+   if(type.norm)
+      return -1.0;
+
+   if (type.floating) {
+      switch(type.width) {
+      case 32:
+         return -FLT_MAX;
+      case 64:
+         return -DBL_MAX;
+      default:
+         assert(0);
+         return 0.0;
+      }
+   }
+
+   if(type.fixed)
+      /* FIXME: consider the fractional bits? */
+      bits = type.width / 2 - 1;
+   else
+      bits = type.width - 1;
+
+   return (double)-((long long)1 << bits);
+}
+
+
+/**
+ * Maximum value representable by the type.
+ */
+double
+lp_const_max(struct lp_type type)
+{
+   unsigned bits;
+
+   if(type.norm)
+      return 1.0;
+
+   if (type.floating) {
+      switch(type.width) {
+      case 32:
+         return FLT_MAX;
+      case 64:
+         return DBL_MAX;
+      default:
+         assert(0);
+         return 0.0;
+      }
+   }
+
+   if(type.fixed)
+      bits = type.width / 2;
+   else
+      bits = type.width;
+
+   if(type.sign)
+      bits -= 1;
+
+   return (double)(((unsigned long long)1 << bits) - 1);
+}
+
+
+double
+lp_const_eps(struct lp_type type)
+{
+   if (type.floating) {
+      switch(type.width) {
+      case 32:
+         return FLT_EPSILON;
+      case 64:
+         return DBL_EPSILON;
+      default:
+         assert(0);
+         return 0.0;
+      }
+   }
+   else {
+      double scale = lp_const_scale(type);
+      return 1.0/scale;
+   }
+}
+
+
 LLVMValueRef
-lp_build_undef(union lp_type type)
+lp_build_undef(struct lp_type type)
 {
    LLVMTypeRef vec_type = lp_build_vec_type(type);
    return LLVMGetUndef(vec_type);
@@ -49,7 +219,7 @@ lp_build_undef(union lp_type type)
                
 
 LLVMValueRef
-lp_build_zero(union lp_type type)
+lp_build_zero(struct lp_type type)
 {
    LLVMTypeRef vec_type = lp_build_vec_type(type);
    return LLVMConstNull(vec_type);
@@ -57,7 +227,7 @@ lp_build_zero(union lp_type type)
                
 
 LLVMValueRef
-lp_build_one(union lp_type type)
+lp_build_one(struct lp_type type)
 {
    LLVMTypeRef elem_type;
    LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
@@ -73,14 +243,20 @@ lp_build_one(union lp_type type)
       elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0);
    else if(!type.norm)
       elems[0] = LLVMConstInt(elem_type, 1, 0);
+   else if(type.sign)
+      elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0);
    else {
       /* special case' -- 1.0 for normalized types is more easily attained if
        * we start with a vector consisting of all bits set */
       LLVMTypeRef vec_type = LLVMVectorType(elem_type, type.length);
       LLVMValueRef vec = LLVMConstAllOnes(vec_type);
 
+#if 0
       if(type.sign)
-         vec = LLVMConstLShr(vec, LLVMConstInt(LLVMInt32Type(), 1, 0));
+         /* TODO: Unfortunately this caused "Tried to create a shift operation
+          * on a non-integer type!" */
+         vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1));
+#endif
 
       return vec;
    }
@@ -93,7 +269,50 @@ lp_build_one(union lp_type type)
                
 
 LLVMValueRef
-lp_build_const_aos(union lp_type type, 
+lp_build_const_scalar(struct lp_type type,
+                      double val)
+{
+   LLVMTypeRef elem_type = lp_build_elem_type(type);
+   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+   unsigned i;
+
+   assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+   if(type.floating) {
+      elems[0] = LLVMConstReal(elem_type, val);
+   }
+   else {
+      double dscale = lp_const_scale(type);
+
+      elems[0] = LLVMConstInt(elem_type, val*dscale + 0.5, 0);
+   }
+
+   for(i = 1; i < type.length; ++i)
+      elems[i] = elems[0];
+
+   return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_int_const_scalar(struct lp_type type,
+                          long long val)
+{
+   LLVMTypeRef elem_type = lp_build_int_elem_type(type);
+   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
+   unsigned i;
+
+   assert(type.length <= LP_MAX_VECTOR_LENGTH);
+
+   for(i = 0; i < type.length; ++i)
+      elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0);
+
+   return LLVMConstVector(elems, type.length);
+}
+
+
+LLVMValueRef
+lp_build_const_aos(struct lp_type type, 
                    double r, double g, double b, double a, 
                    const unsigned char *swizzle)
 {
@@ -117,20 +336,7 @@ lp_build_const_aos(union lp_type type,
       elems[swizzle[3]] = LLVMConstReal(elem_type, a);
    }
    else {
-      unsigned shift;
-      long long llscale;
-      double dscale;
-
-      if(type.fixed)
-         shift = type.width/2;
-      else if(type.norm)
-         shift = type.sign ? type.width - 1 : type.width;
-      else
-         shift = 0;
-
-      llscale = (long long)1 << shift;
-      dscale = (double)llscale;
-      assert((long long)dscale == llscale);
+      double dscale = lp_const_scale(type);
 
       elems[swizzle[0]] = LLVMConstInt(elem_type, r*dscale + 0.5, 0);
       elems[swizzle[1]] = LLVMConstInt(elem_type, g*dscale + 0.5, 0);
@@ -146,25 +352,8 @@ lp_build_const_aos(union lp_type type,
 
 
 LLVMValueRef
-lp_build_const_shift(union lp_type type,
-                     int c)
-{
-   LLVMTypeRef elem_type = LLVMIntType(type.width);
-   LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
-   unsigned i;
-
-   assert(type.length <= LP_MAX_VECTOR_LENGTH);
-
-   for(i = 0; i < type.length; ++i)
-      elems[i] = LLVMConstInt(elem_type, c, 0);
-
-   return LLVMConstVector(elems, type.length);
-}
-
-
-LLVMValueRef
-lp_build_const_mask_aos(union lp_type type,
-                        boolean cond[4])
+lp_build_const_mask_aos(struct lp_type type,
+                        const boolean cond[4])
 {
    LLVMTypeRef elem_type = LLVMIntType(type.width);
    LLVMValueRef masks[LP_MAX_VECTOR_LENGTH];