public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Fixed-point patch 6/10
@ 2007-08-02  0:07 Fu, Chao-Ying
  2007-08-15  7:24 ` Mark Mitchell
  0 siblings, 1 reply; 3+ messages in thread
From: Fu, Chao-Ying @ 2007-08-02  0:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: Thekkath, Radhika, Stephens, Nigel, Mark Mitchell

[-- Attachment #1: Type: text/plain, Size: 2103 bytes --]

Hi,

  Here is the patch #6.  Please review it.  Thanks!

> 1. Merge in machine modes to support signed and unsigned
> fract and accum modes.  Handle scalar and vector modes.
DONE!
> 2. Merge in fixed-value.h and fixed-value.c to handle fixed-point values.
(fixed-value.diff)
> 3. Merge in TREE structures for fixed-point types and constants.
(tree.diff)
> 4. Merge in C front-end changes to parse _Sat, _Fract and _Accum.
(c-parser.diff)
> 5. Merge in RTL structures for fixed-point constants and operators.
(rtl.diff)
> 6. Merge in libcpp to parse fixed-point constants.
(cpp.diff)
> 7. Merge in changes to support "case" of FIXED_POINT_TYPE, FIXED_CST,
> and CONST_FIXED in .c and .h files.
> 8. Merge in the MIPS backend that supports fixed-point instructions.
> 9. Merge in configure/build system changes for the runtime library.
> 10. Merge in testsuite (from gcc.dg/fixed-point) that only run
> when the compiler is configured to enable fixed-point.

Regards,
Chao-ying

libcpp/ChangeLog
2007-08-01  Chao-ying Fu  <fu@mips.com>

	* expr.c (interpret_float_suffix): Support hr, r, lr, llr, uhr, ur,
	ulr, ullr, hk, k, lk, llk, uhk, uk, ulk, ullk.
	(cpp_classify_number): Support decimal fixed-point constants without
	exponents.
	Warn about fixed-point constants when -pedantic.
	* include/cpplib.h (CPP_N_SMALL, CPP_N_MEDIUM, CPP_N_LARGE): Change
	comments to support fixed-point values.
	(CPP_N_FRACT, CPP_N_ACCUM): Define.

gcc/ChangeLog
2007-08-01  Chao-ying Fu  <fu@mips.com>

	* c-lex.c (interpret_fixed): Declare.
	(interpret_float): Process _Fract and _Accum.
	(interpret_fixed): New function.
	* final.c (output_addr_const): Process CONST_FIXED.
	* simplify-rtx.c (simplify_const_unary_operation): Handle US_NEG.
	(simplify_binary_operation_1): Handle US_ASHIFT, SS_MULT, US_MULT,
	SS_DIV, US_DIV.
	(simplify_const_binary_operation): Handle SS_MULT, US_MULT, SS_DIV,
	US_DIV, US_ASHIFT.
	(simplify_immed_subreg): Support CONST_FIXED.
	Process MODE_FRACT, MODE_UFRACT, MODE_ACCUM, MODE_UACCUM.
	(simplify_subreg): Support CONST_FIXED.

[-- Attachment #2: cpp.diff --]
[-- Type: application/octet-stream, Size: 11691 bytes --]

Index: gcc4x/gcc/libcpp/expr.c
===================================================================
--- gcc4x.orig/gcc/libcpp/expr.c	2007-07-31 11:24:14.000000000 -0700
+++ gcc4x/gcc/libcpp/expr.c	2007-07-31 13:25:12.000000000 -0700
@@ -83,12 +83,18 @@
 interpret_float_suffix (const uchar *s, size_t len)
 {
   size_t f, l, w, q, i, d;
+  size_t r, k, u, h;
 
   f = l = w = q = i = d = 0;
+  r = k = u = h = 0;
 
   while (len--)
     switch (s[len])
       {
+      case 'r': case 'R': r++; break;
+      case 'k': case 'K': k++; break;
+      case 'u': case 'U': u++; break;
+      case 'h': case 'H': h++; break;
       case 'f': case 'F':
 	if (d > 0)
 	  return 0;
@@ -98,6 +104,9 @@
 	if (d > 0)
 	  return 0;
 	l++;
+	/* If there are two Ls, they must be adjacent and the same case.  */
+	if (l == 2 && s[len] != s[len + 1])
+	  return 0;
 	break;
       case 'w': case 'W':
 	if (d > 0)
@@ -116,6 +125,33 @@
 	return 0;
       }
 
+  if ((r + k) > 1 || h > 1 || l > 2 || u > 1)
+    return 0;
+
+  if (r == 1)
+    {
+      if (f || i || d)
+	return 0;
+
+      return (CPP_N_FRACT
+	      | (u ? CPP_N_UNSIGNED : 0)
+	      | (h ? CPP_N_SMALL :
+		 l == 2 ? CPP_N_LARGE :
+		 l == 1 ? CPP_N_MEDIUM :  0));
+    }
+
+  if (k == 1)
+    {
+      if (f || i || d)
+	return 0;
+
+      return (CPP_N_ACCUM
+	      | (u ? CPP_N_UNSIGNED : 0)
+	      | (h ? CPP_N_SMALL :
+		 l == 2 ? CPP_N_LARGE :
+		 l == 1 ? CPP_N_MEDIUM :  0));
+    }
+
   if (f + l + w + q > 1 || i > 1)
     return 0;
 
@@ -238,6 +274,26 @@
 	}
     }
 
+  /* The suffix may be for decimal fixed-point constants without exponent.  */
+  if (radix != 16 && float_flag == NOT_FLOAT)
+    {
+      result = interpret_float_suffix (str, limit - str);
+      if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM))
+	{
+	  result |= CPP_N_FLOATING;
+	  /* We need to restore the radix to 10, if the radix is 8.  */
+	  if (radix == 8)
+	    radix = 10;
+
+	  if (CPP_PEDANTIC (pfile))
+	    cpp_error (pfile, CPP_DL_PEDWARN,
+		       "fixed-point constants are a GCC extension");
+	  goto syntax_ok;
+	}
+      else
+	result = 0;
+    }
+
   if (float_flag != NOT_FLOAT && radix == 8)
     radix = 10;
 
@@ -304,6 +360,10 @@
           return CPP_N_INVALID;
         }
 
+      if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile))
+	cpp_error (pfile, CPP_DL_PEDWARN,
+		   "fixed-point constants are a GCC extension");
+
       if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
 	cpp_error (pfile, CPP_DL_PEDWARN,
 		   "decimal float constants are a GCC extension");
@@ -343,6 +403,7 @@
       result |= CPP_N_INTEGER;
     }
 
+ syntax_ok:
   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
     cpp_error (pfile, CPP_DL_PEDWARN,
 	       "imaginary constants are a GCC extension");
Index: gcc4x/gcc/libcpp/include/cpplib.h
===================================================================
--- gcc4x.orig/gcc/libcpp/include/cpplib.h	2007-07-31 11:26:53.000000000 -0700
+++ gcc4x/gcc/libcpp/include/cpplib.h	2007-07-31 13:25:12.000000000 -0700
@@ -747,9 +747,10 @@
 #define CPP_N_FLOATING	0x0002
 
 #define CPP_N_WIDTH	0x00F0
-#define CPP_N_SMALL	0x0010	/* int, float.  */
-#define CPP_N_MEDIUM	0x0020	/* long, double.  */
-#define CPP_N_LARGE	0x0040	/* long long, long double.  */
+#define CPP_N_SMALL	0x0010	/* int, float, shrot _Fract/Accum  */
+#define CPP_N_MEDIUM	0x0020	/* long, double, long _Fract/_Accum.  */
+#define CPP_N_LARGE	0x0040	/* long long, long double,
+				   long long_Fract/Accum.  */
 
 #define CPP_N_WIDTH_MD	0xF0000	/* machine defined.  */
 #define CPP_N_MD_W	0x10000
@@ -764,6 +765,8 @@
 #define CPP_N_UNSIGNED	0x1000	/* Properties.  */
 #define CPP_N_IMAGINARY	0x2000
 #define CPP_N_DFLOAT	0x4000
+#define CPP_N_FRACT	0x8000
+#define CPP_N_ACCUM	0x10000
 
 /* Classify a CPP_NUMBER token.  The return value is a combination of
    the flags from the above sets.  */
Index: gcc4x/gcc/gcc/c-lex.c
===================================================================
--- gcc4x.orig/gcc/gcc/c-lex.c	2007-07-31 11:24:14.000000000 -0700
+++ gcc4x/gcc/gcc/c-lex.c	2007-07-31 13:25:12.000000000 -0700
@@ -61,6 +61,7 @@
 
 static tree interpret_integer (const cpp_token *, unsigned int);
 static tree interpret_float (const cpp_token *, unsigned int);
+static tree interpret_fixed (const cpp_token *, unsigned int);
 static enum integer_type_kind narrowest_unsigned_type
 	(unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
 static enum integer_type_kind narrowest_signed_type
@@ -640,6 +641,10 @@
   char *copy;
   size_t copylen;
 
+  /* Decode _Fract and _Accum.  */
+  if (flags & CPP_N_FRACT || flags & CPP_N_ACCUM)
+    return interpret_fixed (token, flags);
+
   /* Decode type based on width and properties. */
   if (flags & CPP_N_DFLOAT)
     if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
@@ -731,6 +736,131 @@
   return value;
 }
 
+/* Interpret TOKEN, a fixed-point number with FLAGS as classified
+   by cpplib.  */
+
+static tree
+interpret_fixed (const cpp_token *token, unsigned int flags)
+{
+  tree type;
+  tree value;
+  FIXED_VALUE_TYPE fixed;
+  char *copy;
+  size_t copylen;
+
+  copylen = token->val.str.len;
+
+  if (flags & CPP_N_FRACT) /* _Fract.  */
+    {
+      if (flags & CPP_N_UNSIGNED) /* Unsigned _Fract.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = unsigned_long_long_fract_type_node;
+	      copylen -= 4;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = unsigned_long_fract_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = unsigned_short_fract_type_node;
+	      copylen -= 3;
+	    }
+          else
+	    {
+	      type = unsigned_fract_type_node;
+	      copylen -= 2;
+	    }
+	}
+      else /* Signed _Fract.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = long_long_fract_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = long_fract_type_node;
+	      copylen -= 2;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = short_fract_type_node;
+	      copylen -= 2;
+	    }
+          else
+	    {
+	      type = fract_type_node;
+	      copylen --;
+	    }
+	  }
+    }
+  else /* _Accum.  */
+    {
+      if (flags & CPP_N_UNSIGNED) /* Unsigned _Accum.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = unsigned_long_long_accum_type_node;
+	      copylen -= 4;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = unsigned_long_accum_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = unsigned_short_accum_type_node;
+	      copylen -= 3;
+	     }
+	  else
+	    {
+	      type = unsigned_accum_type_node;
+	      copylen -= 2;
+	    }
+	}
+      else /* Signed _Accum.  */
+        {
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = long_long_accum_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = long_accum_type_node;
+	      copylen -= 2;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = short_accum_type_node;
+	      copylen -= 2;
+	    }
+	  else
+	    {
+	      type = accum_type_node;
+	      copylen --;
+	    }
+	}
+    }
+
+  copy = (char *) alloca (copylen + 1);
+  memcpy (copy, token->val.str.text, copylen);
+  copy[copylen] = '\0';
+
+  fixed_from_string (&fixed, copy, TYPE_MODE (type));
+
+  /* Create a node with determined type and value.  */
+  value = build_fixed (type, fixed);
+
+  return value;
+}
+
 /* Convert a series of STRING and/or WSTRING tokens into a tree,
    performing string constant concatenation.  TOK is the first of
    these.  VALP is the location to write the string into.  OBJC_STRING
Index: gcc4x/gcc/gcc/final.c
===================================================================
--- gcc4x.orig/gcc/gcc/final.c	2007-07-31 11:24:14.000000000 -0700
+++ gcc4x/gcc/gcc/final.c	2007-07-31 13:25:12.000000000 -0700
@@ -3306,6 +3306,10 @@
 	output_operand_lossage ("floating constant misused");
       break;
 
+    case CONST_FIXED:
+      fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_FIXED_VALUE_LOW (x));
+      break;
+
     case PLUS:
       /* Some assemblers need integer constants to appear last (eg masm).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
Index: gcc4x/gcc/gcc/simplify-rtx.c
===================================================================
--- gcc4x.orig/gcc/gcc/simplify-rtx.c	2007-07-31 11:24:14.000000000 -0700
+++ gcc4x/gcc/gcc/simplify-rtx.c	2007-07-31 13:25:12.000000000 -0700
@@ -1148,6 +1148,7 @@
 	case SS_TRUNCATE:
 	case US_TRUNCATE:
 	case SS_NEG:
+	case US_NEG:
 	  return 0;
 
 	default:
@@ -2570,6 +2571,7 @@
 
     case ASHIFT:
     case SS_ASHIFT:
+    case US_ASHIFT:
       if (trueop1 == CONST0_RTX (mode))
 	return op0;
       if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
@@ -2649,6 +2651,10 @@
     case US_PLUS:
     case SS_MINUS:
     case US_MINUS:
+    case SS_MULT:
+    case US_MULT:
+    case SS_DIV:
+    case US_DIV:
       /* ??? There are simplifications that can be done.  */
       return 0;
 
@@ -3279,7 +3285,12 @@
 	case US_PLUS:
 	case SS_MINUS:
 	case US_MINUS:
+	case SS_MULT:
+	case US_MULT:
+	case SS_DIV:
+	case US_DIV:
 	case SS_ASHIFT:
+	case US_ASHIFT:
 	  /* ??? There are simplifications that can be done.  */
 	  return 0;
 	  
@@ -4392,8 +4403,9 @@
   return 0;
 }
 
-/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_VECTOR,
-   returning another CONST_INT or CONST_DOUBLE or CONST_VECTOR.
+/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_FIXED
+   or CONST_VECTOR,
+   returning another CONST_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR.
 
    Works by unpacking OP into a collection of 8-bit values
    represented as a little-endian array of 'unsigned char', selecting by BYTE,
@@ -4531,6 +4543,25 @@
 		*vp++ = 0;
 	    }
 	  break;
+
+        case CONST_FIXED:
+	  if (elem_bitsize <= HOST_BITS_PER_WIDE_INT)
+	    {
+	      for (i = 0; i < elem_bitsize; i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_LOW (el) >> i;
+	    }
+	  else
+	    {
+	      for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_LOW (el) >> i;
+              for (; i < 2 * HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
+		   i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_HIGH (el)
+			>> (i - HOST_BITS_PER_WIDE_INT);
+	      for (; i < elem_bitsize; i += value_bit)
+		*vp++ = 0;
+	    }
+          break;
 	  
 	default:
 	  gcc_unreachable ();
@@ -4649,6 +4680,28 @@
 	    elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode);
 	  }
 	  break;
+
+	case MODE_FRACT:
+	case MODE_UFRACT:
+	case MODE_ACCUM:
+	case MODE_UACCUM:
+	  {
+	    FIXED_VALUE_TYPE f;
+	    f.data.low = 0;
+	    f.data.high = 0;
+	    f.mode = outer_submode;
+
+	    for (i = 0;
+		 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
+		 i += value_bit)
+	      f.data.low |= (HOST_WIDE_INT)(*vp++ & value_mask) << i;
+	    for (; i < elem_bitsize; i += value_bit)
+	      f.data.high |= ((HOST_WIDE_INT)(*vp++ & value_mask)
+			     << (i - HOST_BITS_PER_WIDE_INT));
+
+	    elems[elem] = CONST_FIXED_FROM_FIXED_VALUE (f, outer_submode);
+          }
+          break;
 	    
 	default:
 	  gcc_unreachable ();
@@ -4683,6 +4736,7 @@
 
   if (GET_CODE (op) == CONST_INT
       || GET_CODE (op) == CONST_DOUBLE
+      || GET_CODE (op) == CONST_FIXED
       || GET_CODE (op) == CONST_VECTOR)
     return simplify_immed_subreg (outermode, op, innermode, byte);
 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch] Fixed-point patch 6/10
  2007-08-02  0:07 [patch] Fixed-point patch 6/10 Fu, Chao-Ying
@ 2007-08-15  7:24 ` Mark Mitchell
  2007-08-31  1:25   ` Fu, Chao-Ying
  0 siblings, 1 reply; 3+ messages in thread
From: Mark Mitchell @ 2007-08-15  7:24 UTC (permalink / raw)
  To: Fu, Chao-Ying; +Cc: gcc-patches, Thekkath, Radhika, Stephens, Nigel

Fu, Chao-Ying wrote:
> Hi,
> 
>   Here is the patch #6.  Please review it.  Thanks!

> libcpp/ChangeLog
> 2007-08-01  Chao-ying Fu  <fu@mips.com>
> 
> 	* expr.c (interpret_float_suffix): Support hr, r, lr, llr, uhr, ur,
> 	ulr, ullr, hk, k, lk, llk, uhk, uk, ulk, ullk.
...

OK, thanks.

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [patch] Fixed-point patch 6/10
  2007-08-15  7:24 ` Mark Mitchell
@ 2007-08-31  1:25   ` Fu, Chao-Ying
  0 siblings, 0 replies; 3+ messages in thread
From: Fu, Chao-Ying @ 2007-08-31  1:25 UTC (permalink / raw)
  To: Mark Mitchell, gcc-patches; +Cc: Thekkath, Radhika, Stephens, Nigel

[-- Attachment #1: Type: text/plain, Size: 766 bytes --]

Mark Mitchell wrote:
> > Hi,
> > 
> >   Here is the patch #6.  Please review it.  Thanks!
> 
> > libcpp/ChangeLog
> > 2007-08-01  Chao-ying Fu  <fu@mips.com>
> > 
> > 	* expr.c (interpret_float_suffix): Support hr, r, lr, 
> llr, uhr, ur,
> > 	ulr, ullr, hk, k, lk, llk, uhk, uk, ulk, ullk.
> ...
> 
> OK, thanks.
> 

  I checked in this patch with two small changes.
1. Because CPP_N_WIDTH_MD (0xF0000) is used for machine defined
constants, I moved CPP_N_FRACT and CPP_N_ACCUM to
0x100000 and 0x200000.  
2. The checking for invalid suffix is enhanced in 
"interpret_float_suffix".

  The new patch is attached.  I tested this patch on 
mipsisa32r2-elfoabi and i686-pc-linux-gnu.
No new regressions.  Thanks a lot!

Regards,
Chao-ying

[-- Attachment #2: cpp.diff --]
[-- Type: application/octet-stream, Size: 11572 bytes --]

Index: gcc/c-lex.c
===================================================================
--- gcc/c-lex.c	(revision 127932)
+++ gcc/c-lex.c	(working copy)
@@ -61,6 +61,7 @@
 
 static tree interpret_integer (const cpp_token *, unsigned int);
 static tree interpret_float (const cpp_token *, unsigned int);
+static tree interpret_fixed (const cpp_token *, unsigned int);
 static enum integer_type_kind narrowest_unsigned_type
 	(unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
 static enum integer_type_kind narrowest_signed_type
@@ -640,6 +641,10 @@
   char *copy;
   size_t copylen;
 
+  /* Decode _Fract and _Accum.  */
+  if (flags & CPP_N_FRACT || flags & CPP_N_ACCUM)
+    return interpret_fixed (token, flags);
+
   /* Decode type based on width and properties. */
   if (flags & CPP_N_DFLOAT)
     if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
@@ -731,6 +736,131 @@
   return value;
 }
 
+/* Interpret TOKEN, a fixed-point number with FLAGS as classified
+   by cpplib.  */
+
+static tree
+interpret_fixed (const cpp_token *token, unsigned int flags)
+{
+  tree type;
+  tree value;
+  FIXED_VALUE_TYPE fixed;
+  char *copy;
+  size_t copylen;
+
+  copylen = token->val.str.len;
+
+  if (flags & CPP_N_FRACT) /* _Fract.  */
+    {
+      if (flags & CPP_N_UNSIGNED) /* Unsigned _Fract.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = unsigned_long_long_fract_type_node;
+	      copylen -= 4;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = unsigned_long_fract_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = unsigned_short_fract_type_node;
+	      copylen -= 3;
+	    }
+          else
+	    {
+	      type = unsigned_fract_type_node;
+	      copylen -= 2;
+	    }
+	}
+      else /* Signed _Fract.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = long_long_fract_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = long_fract_type_node;
+	      copylen -= 2;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = short_fract_type_node;
+	      copylen -= 2;
+	    }
+          else
+	    {
+	      type = fract_type_node;
+	      copylen --;
+	    }
+	  }
+    }
+  else /* _Accum.  */
+    {
+      if (flags & CPP_N_UNSIGNED) /* Unsigned _Accum.  */
+	{
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = unsigned_long_long_accum_type_node;
+	      copylen -= 4;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = unsigned_long_accum_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = unsigned_short_accum_type_node;
+	      copylen -= 3;
+	     }
+	  else
+	    {
+	      type = unsigned_accum_type_node;
+	      copylen -= 2;
+	    }
+	}
+      else /* Signed _Accum.  */
+        {
+	  if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+	    {
+	      type = long_long_accum_type_node;
+	      copylen -= 3;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_MEDIUM)
+	    {
+	      type = long_accum_type_node;
+	      copylen -= 2;
+	    }
+	  else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
+	    {
+	      type = short_accum_type_node;
+	      copylen -= 2;
+	    }
+	  else
+	    {
+	      type = accum_type_node;
+	      copylen --;
+	    }
+	}
+    }
+
+  copy = (char *) alloca (copylen + 1);
+  memcpy (copy, token->val.str.text, copylen);
+  copy[copylen] = '\0';
+
+  fixed_from_string (&fixed, copy, TYPE_MODE (type));
+
+  /* Create a node with determined type and value.  */
+  value = build_fixed (type, fixed);
+
+  return value;
+}
+
 /* Convert a series of STRING and/or WSTRING tokens into a tree,
    performing string constant concatenation.  TOK is the first of
    these.  VALP is the location to write the string into.  OBJC_STRING
Index: gcc/final.c
===================================================================
--- gcc/final.c	(revision 127932)
+++ gcc/final.c	(working copy)
@@ -3377,6 +3377,10 @@
 	output_operand_lossage ("floating constant misused");
       break;
 
+    case CONST_FIXED:
+      fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_FIXED_VALUE_LOW (x));
+      break;
+
     case PLUS:
       /* Some assemblers need integer constants to appear last (eg masm).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 127932)
+++ gcc/simplify-rtx.c	(working copy)
@@ -1149,6 +1149,7 @@
 	case SS_TRUNCATE:
 	case US_TRUNCATE:
 	case SS_NEG:
+	case US_NEG:
 	  return 0;
 
 	default:
@@ -2565,6 +2566,7 @@
 
     case ASHIFT:
     case SS_ASHIFT:
+    case US_ASHIFT:
       if (trueop1 == CONST0_RTX (mode))
 	return op0;
       if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
@@ -2644,6 +2646,10 @@
     case US_PLUS:
     case SS_MINUS:
     case US_MINUS:
+    case SS_MULT:
+    case US_MULT:
+    case SS_DIV:
+    case US_DIV:
       /* ??? There are simplifications that can be done.  */
       return 0;
 
@@ -3353,7 +3359,12 @@
 	case US_PLUS:
 	case SS_MINUS:
 	case US_MINUS:
+	case SS_MULT:
+	case US_MULT:
+	case SS_DIV:
+	case US_DIV:
 	case SS_ASHIFT:
+	case US_ASHIFT:
 	  /* ??? There are simplifications that can be done.  */
 	  return 0;
 	  
@@ -4466,8 +4477,9 @@
   return 0;
 }
 
-/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_VECTOR,
-   returning another CONST_INT or CONST_DOUBLE or CONST_VECTOR.
+/* Evaluate a SUBREG of a CONST_INT or CONST_DOUBLE or CONST_FIXED
+   or CONST_VECTOR,
+   returning another CONST_INT or CONST_DOUBLE or CONST_FIXED or CONST_VECTOR.
 
    Works by unpacking OP into a collection of 8-bit values
    represented as a little-endian array of 'unsigned char', selecting by BYTE,
@@ -4605,6 +4617,25 @@
 		*vp++ = 0;
 	    }
 	  break;
+
+        case CONST_FIXED:
+	  if (elem_bitsize <= HOST_BITS_PER_WIDE_INT)
+	    {
+	      for (i = 0; i < elem_bitsize; i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_LOW (el) >> i;
+	    }
+	  else
+	    {
+	      for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_LOW (el) >> i;
+              for (; i < 2 * HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
+		   i += value_bit)
+		*vp++ = CONST_FIXED_VALUE_HIGH (el)
+			>> (i - HOST_BITS_PER_WIDE_INT);
+	      for (; i < elem_bitsize; i += value_bit)
+		*vp++ = 0;
+	    }
+          break;
 	  
 	default:
 	  gcc_unreachable ();
@@ -4723,6 +4754,28 @@
 	    elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode);
 	  }
 	  break;
+
+	case MODE_FRACT:
+	case MODE_UFRACT:
+	case MODE_ACCUM:
+	case MODE_UACCUM:
+	  {
+	    FIXED_VALUE_TYPE f;
+	    f.data.low = 0;
+	    f.data.high = 0;
+	    f.mode = outer_submode;
+
+	    for (i = 0;
+		 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
+		 i += value_bit)
+	      f.data.low |= (HOST_WIDE_INT)(*vp++ & value_mask) << i;
+	    for (; i < elem_bitsize; i += value_bit)
+	      f.data.high |= ((HOST_WIDE_INT)(*vp++ & value_mask)
+			     << (i - HOST_BITS_PER_WIDE_INT));
+
+	    elems[elem] = CONST_FIXED_FROM_FIXED_VALUE (f, outer_submode);
+          }
+          break;
 	    
 	default:
 	  gcc_unreachable ();
@@ -4757,6 +4810,7 @@
 
   if (GET_CODE (op) == CONST_INT
       || GET_CODE (op) == CONST_DOUBLE
+      || GET_CODE (op) == CONST_FIXED
       || GET_CODE (op) == CONST_VECTOR)
     return simplify_immed_subreg (outermode, op, innermode, byte);
 
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 127932)
+++ libcpp/include/cpplib.h	(working copy)
@@ -747,9 +747,10 @@
 #define CPP_N_FLOATING	0x0002
 
 #define CPP_N_WIDTH	0x00F0
-#define CPP_N_SMALL	0x0010	/* int, float.  */
-#define CPP_N_MEDIUM	0x0020	/* long, double.  */
-#define CPP_N_LARGE	0x0040	/* long long, long double.  */
+#define CPP_N_SMALL	0x0010	/* int, float, shrot _Fract/Accum  */
+#define CPP_N_MEDIUM	0x0020	/* long, double, long _Fract/_Accum.  */
+#define CPP_N_LARGE	0x0040	/* long long, long double,
+				   long long _Fract/Accum.  */
 
 #define CPP_N_WIDTH_MD	0xF0000	/* machine defined.  */
 #define CPP_N_MD_W	0x10000
@@ -765,6 +766,9 @@
 #define CPP_N_IMAGINARY	0x2000
 #define CPP_N_DFLOAT	0x4000
 
+#define CPP_N_FRACT	0x100000 /* Fract types.  */
+#define CPP_N_ACCUM	0x200000 /* Accum types.  */
+
 /* Classify a CPP_NUMBER token.  The return value is a combination of
    the flags from the above sets.  */
 extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *);
Index: libcpp/expr.c
===================================================================
--- libcpp/expr.c	(revision 127932)
+++ libcpp/expr.c	(working copy)
@@ -83,12 +83,18 @@
 interpret_float_suffix (const uchar *s, size_t len)
 {
   size_t f, l, w, q, i, d;
+  size_t r, k, u, h;
 
   f = l = w = q = i = d = 0;
+  r = k = u = h = 0;
 
   while (len--)
     switch (s[len])
       {
+      case 'r': case 'R': r++; break;
+      case 'k': case 'K': k++; break;
+      case 'u': case 'U': u++; break;
+      case 'h': case 'H': h++; break;
       case 'f': case 'F':
 	if (d > 0)
 	  return 0;
@@ -98,6 +104,9 @@
 	if (d > 0)
 	  return 0;
 	l++;
+	/* If there are two Ls, they must be adjacent and the same case.  */
+	if (l == 2 && s[len] != s[len + 1])
+	  return 0;
 	break;
       case 'w': case 'W':
 	if (d > 0)
@@ -116,9 +125,36 @@
 	return 0;
       }
 
-  if (f + l + w + q > 1 || i > 1)
+  if (r + k > 1 || h > 1 || l > 2 || u > 1)
     return 0;
 
+  if (r == 1)
+    {
+      if (f || i || d || w || q)
+	return 0;
+
+      return (CPP_N_FRACT
+	      | (u ? CPP_N_UNSIGNED : 0)
+	      | (h ? CPP_N_SMALL :
+		 l == 2 ? CPP_N_LARGE :
+		 l == 1 ? CPP_N_MEDIUM :  0));
+    }
+
+  if (k == 1)
+    {
+      if (f || i || d || w || q)
+	return 0;
+
+      return (CPP_N_ACCUM
+	      | (u ? CPP_N_UNSIGNED : 0)
+	      | (h ? CPP_N_SMALL :
+		 l == 2 ? CPP_N_LARGE :
+		 l == 1 ? CPP_N_MEDIUM :  0));
+    }
+
+  if (f + l + w + q > 1 || i > 1 || h + u > 0)
+    return 0;
+
   /* Allow dd, df, dl suffixes for decimal float constants.  */
   if (d && ((d + f + l != 2) || i))
     return 0;
@@ -238,6 +274,26 @@
 	}
     }
 
+  /* The suffix may be for decimal fixed-point constants without exponent.  */
+  if (radix != 16 && float_flag == NOT_FLOAT)
+    {
+      result = interpret_float_suffix (str, limit - str);
+      if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM))
+	{
+	  result |= CPP_N_FLOATING;
+	  /* We need to restore the radix to 10, if the radix is 8.  */
+	  if (radix == 8)
+	    radix = 10;
+
+	  if (CPP_PEDANTIC (pfile))
+	    cpp_error (pfile, CPP_DL_PEDWARN,
+		       "fixed-point constants are a GCC extension");
+	  goto syntax_ok;
+	}
+      else
+	result = 0;
+    }
+
   if (float_flag != NOT_FLOAT && radix == 8)
     radix = 10;
 
@@ -304,6 +360,10 @@
           return CPP_N_INVALID;
         }
 
+      if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile))
+	cpp_error (pfile, CPP_DL_PEDWARN,
+		   "fixed-point constants are a GCC extension");
+
       if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
 	cpp_error (pfile, CPP_DL_PEDWARN,
 		   "decimal float constants are a GCC extension");
@@ -343,6 +403,7 @@
       result |= CPP_N_INTEGER;
     }
 
+ syntax_ok:
   if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
     cpp_error (pfile, CPP_DL_PEDWARN,
 	       "imaginary constants are a GCC extension");

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-08-30 23:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-02  0:07 [patch] Fixed-point patch 6/10 Fu, Chao-Ying
2007-08-15  7:24 ` Mark Mitchell
2007-08-31  1:25   ` Fu, Chao-Ying

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).