i965g: fix some reloc counts
[mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_const.c
index 2109a85ceb86a9906f5d5991fe435b42dac246db..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(union lp_type type)
+lp_const_shift(struct lp_type type)
 {
    if(type.floating)
       return 0;
@@ -60,7 +86,7 @@ lp_const_shift(union lp_type type)
 
 
 unsigned
-lp_const_offset(union lp_type type)
+lp_const_offset(struct lp_type type)
 {
    if(type.floating || type.fixed)
       return 0;
@@ -78,7 +104,7 @@ lp_const_offset(union lp_type type)
  * else for the fixed points types and normalized integers.
  */
 double
-lp_const_scale(union lp_type type)
+lp_const_scale(struct lp_type type)
 {
    unsigned long long llscale;
    double dscale;
@@ -92,8 +118,100 @@ lp_const_scale(union lp_type type)
 }
 
 
+/**
+ * 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);
@@ -101,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);
@@ -109,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];
@@ -125,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;
    }
@@ -145,8 +269,8 @@ lp_build_one(union lp_type type)
                
 
 LLVMValueRef
-lp_build_const_uni(union lp_type type,
-                   double val)
+lp_build_const_scalar(struct lp_type type,
+                      double val)
 {
    LLVMTypeRef elem_type = lp_build_elem_type(type);
    LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
@@ -171,8 +295,8 @@ lp_build_const_uni(union lp_type type,
 
 
 LLVMValueRef
-lp_build_int_const_uni(union lp_type type,
-                       long long val)
+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];
@@ -188,7 +312,7 @@ lp_build_int_const_uni(union lp_type type,
 
 
 LLVMValueRef
-lp_build_const_aos(union lp_type type, 
+lp_build_const_aos(struct lp_type type, 
                    double r, double g, double b, double a, 
                    const unsigned char *swizzle)
 {
@@ -228,8 +352,8 @@ lp_build_const_aos(union lp_type type,
 
 
 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];