* [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).