stdfix.h: New file.
* ginclude/stdfix.h: New file. * Makefile.in (USER_H): Add $(srcdir)/ginclude/stdfix.h. (convert.o): Add dependence on fixed-value.h. * c-convert.c (convert): Support FIXED_POINT_TYPE. * c-cppbuiltin.c (builtin_define_fixed_point_constants): New function to define fixed-point constants. (c_cpp_builtins): Define fixed-point constants. * convert.c (fixed-value.h): New include. (convert_to_real): Update comment to include fixed-point. Support FIXED_POINT_TYPE. (convert_to_integer): Update comment to include fixed-point. Support FIXED_POINT_TYPE. (convert_to_complex): Support FIXED_POINT_TYPE. (convert_to_fixed): New function. * convert.h (convert_to_fixed): Declare. * genopinit.c: Add comment about $Q for only fixed-point modes. (optabs): Add fract_optab, fractuns_optab, satfract_optab, satfractuns_optab, add_optab, ssadd_optab, usadd_optab, sub_optab, sssub_optab, ussub_optab, smul_optab, ssmul_optab, usmul_optab, ssmadd_widen_optab, usmadd_widen_optab, ssdiv_optab, udiv_optab, usdiv_optab, ssashl_optab, usashl_optab, neg_optab, ssneg_optab, usneg_optab for fixed-point modes. (gen_insn): Add force_fixed to track the $Q format for all fixed-point modes. * optabs.c (optab_for_tree_code): For *DIV_EXPR, LSHIFT_EXPR, PLUS_EXPR, MINUS_EXPR, MULT_EXPR, NEGATE_EXPR, return signed or unsigned saturation optabs, when type is saturating. (shift_optab_p): Return true for SS_ASHIFT or US_ASHIFT. (expand_fixed_convert): New function. (gen_fixed_libfunc, gen_signed_fixed_libfunc, gen_unsigned_fixed_libfunc, gen_int_fp_fixed_libfunc, gen_int_fp_signed_fixed_libfunc, gen_int_fixed_libfunc, gen_int_signed_fixed_libfunc, gen_int_unsigned_fixed_libfunc, gen_fract_conv_libfunc, gen_fractuns_conv_libfunc, gen_satfract_conv_libfunc, gen_satfractuns_conv_libfunc): New functions. (init_optabs): Initialize ssadd_optab, usadd_optab, sssub_optab, ussub_optab, ssmul_optab, usmul_optab, ssmadd_widen_optab, usmadd_widen_optab, ssmsub_widen_optab, usmsub_widen_optab, ssdiv_optab, usdiv_optab, ssashl_optab, usashl_optab, ssneg_optab, usneg_optab, fract_optab, fractuns_optab, satfract_optab, satfractuns_optab. Initialize fixed-point libraries, including add, ssadd, usadd, sub, sssub, ussub, mul, ssmul, usmul, div, ssdiv, udiv, usdiv, ashl, ssashl, usashl, ashr, lshr, neg, ssneg, usneg, cmp, fract, satfract, fractuns, satfractuns. * optabs.h (enum optab_index): Add OTI_ssadd, OTI_usadd, OTI_sssub, OTI_ussub, OTI_ssmul, OTI_usmul, OTI_ssdiv, OTI_usdiv, OTI_ssneg, OTI_usneg, OTI_ssashl, OTI_usashl, OTI_ssmadd_widen, OTI_usmadd_widen, OTI_ssmsub_widen, OTI_usmsub_widen. (ssadd_optab, usadd_optab, sssub_optab, ussub_optab, ssmul_optab, usmul_optab, ssdiv_optab, usdiv_optab, ssneg_optab, usneg_optab, ssashl_optab, usashl_optab, ssmadd_widen_optab, usmadd_widen_optab, umsub_widen_optab, usmsub_widen_optab): Define. (enum convert_optab_index): Add COI_fract, COI_fractuns, COI_satfract, COI_satfractuns. (fract_optab, fractuns_optab, satfract_optab, satfractuns_optab): Define. (expand_fixed_convert): Declare. * expr.c (convert_move): Support the move of fixed-point modes. (emit_move_insn_1): Handle fixed-point mode to move via integer. (categorize_ctor_elements_1): Handle FIXED_CST. (count_type_elements): Handle FIXED_POINT_TYPE. (expand_expr_real_1): For VECTOR_CST, check MODE_VECTOR_FRACT, MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM. Support FIXED_CST. For PLUS_EXPR and MINUS_EXPR, support saturating and non-saturating multiply and add/subtract for fixed-point types. For MULT_EXPR, *DIV_EXPR, *SHIFT_EXPR, if the mode if a fixed-point mode, we jump to binop directly. Support FIXED_CONVERT_EXPR. (do_store_flag): Check FIXED_CST to put a constant second. (vector_mode_valid_p): Handle MODE_VECTOR_FRACT, MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM. (const_vector_from_tree): Support FIXED_CST. * doc/extend.texi (Fixed-Point): New node. * doc/md.texi (ssadd, usadd, sssub, ussub, ssmul, usmul, ssdiv, usdiv, ssmadd, usmadd, ssmsub, usmsub, ssashl, usashl, ssneg, usneg, fract, satfract, fractuns, satfractuns): Document them. From-SVN: r128218
This commit is contained in:
parent
58cfe6985b
commit
0f996086cb
@ -1,3 +1,85 @@
|
||||
2007-09-06 Chao-ying Fu <fu@mips.com>
|
||||
|
||||
* ginclude/stdfix.h: New file.
|
||||
* Makefile.in (USER_H): Add $(srcdir)/ginclude/stdfix.h.
|
||||
(convert.o): Add dependence on fixed-value.h.
|
||||
* c-convert.c (convert): Support FIXED_POINT_TYPE.
|
||||
* c-cppbuiltin.c (builtin_define_fixed_point_constants): New function
|
||||
to define fixed-point constants.
|
||||
(c_cpp_builtins): Define fixed-point constants.
|
||||
* convert.c (fixed-value.h): New include.
|
||||
(convert_to_real): Update comment to include fixed-point.
|
||||
Support FIXED_POINT_TYPE.
|
||||
(convert_to_integer): Update comment to include fixed-point.
|
||||
Support FIXED_POINT_TYPE.
|
||||
(convert_to_complex): Support FIXED_POINT_TYPE.
|
||||
(convert_to_fixed): New function.
|
||||
* convert.h (convert_to_fixed): Declare.
|
||||
* genopinit.c: Add comment about $Q for only fixed-point modes.
|
||||
(optabs): Add fract_optab, fractuns_optab, satfract_optab,
|
||||
satfractuns_optab, add_optab, ssadd_optab, usadd_optab, sub_optab,
|
||||
sssub_optab, ussub_optab, smul_optab, ssmul_optab, usmul_optab,
|
||||
ssmadd_widen_optab, usmadd_widen_optab, ssdiv_optab, udiv_optab,
|
||||
usdiv_optab, ssashl_optab, usashl_optab, neg_optab, ssneg_optab,
|
||||
usneg_optab for fixed-point modes.
|
||||
(gen_insn): Add force_fixed to track the $Q format for all fixed-point
|
||||
modes.
|
||||
* optabs.c (optab_for_tree_code): For *DIV_EXPR, LSHIFT_EXPR,
|
||||
PLUS_EXPR, MINUS_EXPR, MULT_EXPR, NEGATE_EXPR, return signed or
|
||||
unsigned saturation optabs, when type is saturating.
|
||||
(shift_optab_p): Return true for SS_ASHIFT or US_ASHIFT.
|
||||
(expand_fixed_convert): New function.
|
||||
(gen_fixed_libfunc, gen_signed_fixed_libfunc,
|
||||
gen_unsigned_fixed_libfunc, gen_int_fp_fixed_libfunc,
|
||||
gen_int_fp_signed_fixed_libfunc, gen_int_fixed_libfunc,
|
||||
gen_int_signed_fixed_libfunc, gen_int_unsigned_fixed_libfunc,
|
||||
gen_fract_conv_libfunc, gen_fractuns_conv_libfunc,
|
||||
gen_satfract_conv_libfunc, gen_satfractuns_conv_libfunc): New
|
||||
functions.
|
||||
(init_optabs): Initialize ssadd_optab, usadd_optab, sssub_optab,
|
||||
ussub_optab, ssmul_optab, usmul_optab, ssmadd_widen_optab,
|
||||
usmadd_widen_optab, ssmsub_widen_optab, usmsub_widen_optab,
|
||||
ssdiv_optab, usdiv_optab, ssashl_optab, usashl_optab, ssneg_optab,
|
||||
usneg_optab, fract_optab, fractuns_optab, satfract_optab,
|
||||
satfractuns_optab.
|
||||
Initialize fixed-point libraries, including add, ssadd, usadd, sub,
|
||||
sssub, ussub, mul, ssmul, usmul, div, ssdiv, udiv, usdiv, ashl,
|
||||
ssashl, usashl, ashr, lshr, neg, ssneg, usneg, cmp, fract, satfract,
|
||||
fractuns, satfractuns.
|
||||
* optabs.h (enum optab_index): Add OTI_ssadd, OTI_usadd, OTI_sssub,
|
||||
OTI_ussub, OTI_ssmul, OTI_usmul, OTI_ssdiv, OTI_usdiv, OTI_ssneg,
|
||||
OTI_usneg, OTI_ssashl, OTI_usashl, OTI_ssmadd_widen, OTI_usmadd_widen,
|
||||
OTI_ssmsub_widen, OTI_usmsub_widen.
|
||||
(ssadd_optab, usadd_optab, sssub_optab, ussub_optab, ssmul_optab,
|
||||
usmul_optab, ssdiv_optab, usdiv_optab, ssneg_optab, usneg_optab,
|
||||
ssashl_optab, usashl_optab, ssmadd_widen_optab, usmadd_widen_optab,
|
||||
umsub_widen_optab, usmsub_widen_optab): Define.
|
||||
(enum convert_optab_index): Add COI_fract, COI_fractuns, COI_satfract,
|
||||
COI_satfractuns.
|
||||
(fract_optab, fractuns_optab, satfract_optab, satfractuns_optab):
|
||||
Define.
|
||||
(expand_fixed_convert): Declare.
|
||||
* expr.c (convert_move): Support the move of fixed-point modes.
|
||||
(emit_move_insn_1): Handle fixed-point mode to move via integer.
|
||||
(categorize_ctor_elements_1): Handle FIXED_CST.
|
||||
(count_type_elements): Handle FIXED_POINT_TYPE.
|
||||
(expand_expr_real_1): For VECTOR_CST, check MODE_VECTOR_FRACT,
|
||||
MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM.
|
||||
Support FIXED_CST.
|
||||
For PLUS_EXPR and MINUS_EXPR, support saturating and non-saturating
|
||||
multiply and add/subtract for fixed-point types.
|
||||
For MULT_EXPR, *DIV_EXPR, *SHIFT_EXPR, if the mode if a fixed-point
|
||||
mode, we jump to binop directly.
|
||||
Support FIXED_CONVERT_EXPR.
|
||||
(do_store_flag): Check FIXED_CST to put a constant second.
|
||||
(vector_mode_valid_p): Handle MODE_VECTOR_FRACT,
|
||||
MODE_VECTOR_UFRACT, MODE_VECTOR_ACCUM, MODE_VECTOR_UACCUM.
|
||||
(const_vector_from_tree): Support FIXED_CST.
|
||||
* doc/extend.texi (Fixed-Point): New node.
|
||||
* doc/md.texi (ssadd, usadd, sssub, ussub, ssmul, usmul, ssdiv, usdiv,
|
||||
ssmadd, usmadd, ssmsub, usmsub, ssashl, usashl, ssneg, usneg, fract,
|
||||
satfract, fractuns, satfractuns): Document them.
|
||||
|
||||
2007-09-07 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* config/bfin/bfin.h (PREFERRED_RELOAD_CLASS): Don't reload autoinc
|
||||
|
@ -302,6 +302,7 @@ USER_H = $(srcdir)/ginclude/float.h \
|
||||
$(srcdir)/ginclude/stdbool.h \
|
||||
$(srcdir)/ginclude/stddef.h \
|
||||
$(srcdir)/ginclude/varargs.h \
|
||||
$(srcdir)/ginclude/stdfix.h \
|
||||
$(EXTRA_HEADERS)
|
||||
|
||||
UNWIND_H = $(srcdir)/unwind-generic.h
|
||||
@ -1942,7 +1943,7 @@ prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) prefix.h \
|
||||
-c $(srcdir)/prefix.c $(OUTPUT_OPTION)
|
||||
|
||||
convert.o: convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
$(FLAGS_H) convert.h toplev.h langhooks.h $(REAL_H)
|
||||
$(FLAGS_H) convert.h toplev.h langhooks.h $(REAL_H) fixed-value.h
|
||||
|
||||
double-int.o: double-int.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H)
|
||||
|
||||
|
@ -105,6 +105,8 @@ convert (tree type, tree expr)
|
||||
return fold (convert_to_pointer (type, e));
|
||||
if (code == REAL_TYPE)
|
||||
return fold (convert_to_real (type, e));
|
||||
if (code == FIXED_POINT_TYPE)
|
||||
return fold (convert_to_fixed (type, e));
|
||||
if (code == COMPLEX_TYPE)
|
||||
return fold (convert_to_complex (type, e));
|
||||
if (code == VECTOR_TYPE)
|
||||
|
@ -317,6 +317,60 @@ builtin_define_decimal_float_constants (const char *name_prefix,
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
|
||||
/* Define fixed-point constants for TYPE using NAME_PREFIX and SUFFIX. */
|
||||
|
||||
static void
|
||||
builtin_define_fixed_point_constants (const char *name_prefix,
|
||||
const char *suffix,
|
||||
tree type)
|
||||
{
|
||||
char name[64], buf[256], *new_buf;
|
||||
int i, mod;
|
||||
|
||||
sprintf (name, "__%s_FBIT__", name_prefix);
|
||||
builtin_define_with_int_value (name, TYPE_FBIT (type));
|
||||
|
||||
sprintf (name, "__%s_IBIT__", name_prefix);
|
||||
builtin_define_with_int_value (name, TYPE_IBIT (type));
|
||||
|
||||
/* If there is no suffix, defines are for fixed-point modes.
|
||||
We just return. */
|
||||
if (strcmp (suffix, "") == 0)
|
||||
return;
|
||||
|
||||
if (TYPE_UNSIGNED (type))
|
||||
{
|
||||
sprintf (name, "__%s_MIN__", name_prefix);
|
||||
sprintf (buf, "0.0%s", suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf (name, "__%s_MIN__", name_prefix);
|
||||
if (ALL_ACCUM_MODE_P (TYPE_MODE (type)))
|
||||
sprintf (buf, "(-0X1P%d%s-0X1P%d%s)", TYPE_IBIT (type) - 1, suffix,
|
||||
TYPE_IBIT (type) - 1, suffix);
|
||||
else
|
||||
sprintf (buf, "(-0.5%s-0.5%s)", suffix, suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
|
||||
sprintf (name, "__%s_MAX__", name_prefix);
|
||||
sprintf (buf, "0X");
|
||||
new_buf = buf + 2;
|
||||
mod = (TYPE_FBIT (type) + TYPE_IBIT (type)) % 4;
|
||||
if (mod)
|
||||
sprintf (new_buf++, "%x", (1 << mod) - 1);
|
||||
for (i = 0; i < (TYPE_FBIT (type) + TYPE_IBIT (type)) / 4; i++)
|
||||
sprintf (new_buf++, "F");
|
||||
sprintf (new_buf, "P-%d%s", TYPE_FBIT (type), suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
|
||||
sprintf (name, "__%s_EPSILON__", name_prefix);
|
||||
sprintf (buf, "0x1P-%d%s", TYPE_FBIT (type), suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
|
||||
/* Define __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. */
|
||||
static void
|
||||
define__GNUC__ (void)
|
||||
@ -465,6 +519,62 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node);
|
||||
builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node);
|
||||
|
||||
/* For fixed-point fibt, ibit, max, min, and epsilon. */
|
||||
if (targetm.fixed_point_supported_p ())
|
||||
{
|
||||
builtin_define_fixed_point_constants ("SFRACT", "HR",
|
||||
short_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("USFRACT", "UHR",
|
||||
unsigned_short_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("FRACT", "R",
|
||||
fract_type_node);
|
||||
builtin_define_fixed_point_constants ("UFRACT", "UR",
|
||||
unsigned_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("LFRACT", "LR",
|
||||
long_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("ULFRACT", "ULR",
|
||||
unsigned_long_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("LLFRACT", "LLR",
|
||||
long_long_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("ULLFRACT", "ULLR",
|
||||
unsigned_long_long_fract_type_node);
|
||||
builtin_define_fixed_point_constants ("SACCUM", "HK",
|
||||
short_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("USACCUM", "UHK",
|
||||
unsigned_short_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("ACCUM", "K",
|
||||
accum_type_node);
|
||||
builtin_define_fixed_point_constants ("UACCUM", "UK",
|
||||
unsigned_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("LACCUM", "LK",
|
||||
long_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("ULACCUM", "ULK",
|
||||
unsigned_long_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("LLACCUM", "LLK",
|
||||
long_long_accum_type_node);
|
||||
builtin_define_fixed_point_constants ("ULLACCUM", "ULLK",
|
||||
unsigned_long_long_accum_type_node);
|
||||
|
||||
builtin_define_fixed_point_constants ("QQ", "", qq_type_node);
|
||||
builtin_define_fixed_point_constants ("HQ", "", hq_type_node);
|
||||
builtin_define_fixed_point_constants ("SQ", "", sq_type_node);
|
||||
builtin_define_fixed_point_constants ("DQ", "", dq_type_node);
|
||||
builtin_define_fixed_point_constants ("TQ", "", tq_type_node);
|
||||
builtin_define_fixed_point_constants ("UQQ", "", uqq_type_node);
|
||||
builtin_define_fixed_point_constants ("UHQ", "", uhq_type_node);
|
||||
builtin_define_fixed_point_constants ("USQ", "", usq_type_node);
|
||||
builtin_define_fixed_point_constants ("UDQ", "", udq_type_node);
|
||||
builtin_define_fixed_point_constants ("UTQ", "", utq_type_node);
|
||||
builtin_define_fixed_point_constants ("HA", "", ha_type_node);
|
||||
builtin_define_fixed_point_constants ("SA", "", sa_type_node);
|
||||
builtin_define_fixed_point_constants ("DA", "", da_type_node);
|
||||
builtin_define_fixed_point_constants ("TA", "", ta_type_node);
|
||||
builtin_define_fixed_point_constants ("UHA", "", uha_type_node);
|
||||
builtin_define_fixed_point_constants ("USA", "", usa_type_node);
|
||||
builtin_define_fixed_point_constants ("UDA", "", uda_type_node);
|
||||
builtin_define_fixed_point_constants ("UTA", "", uta_type_node);
|
||||
}
|
||||
|
||||
/* For use in assembly language. */
|
||||
builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
|
||||
builtin_define_with_value ("__USER_LABEL_PREFIX__", user_label_prefix, 0);
|
||||
|
@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "toplev.h"
|
||||
#include "langhooks.h"
|
||||
#include "real.h"
|
||||
#include "fixed-value.h"
|
||||
|
||||
/* Convert EXPR to some pointer or reference type TYPE.
|
||||
EXPR must be pointer, reference, integer, enumeral, or literal zero;
|
||||
@ -117,7 +118,7 @@ strip_float_extensions (tree exp)
|
||||
|
||||
/* Convert EXPR to some floating-point type TYPE.
|
||||
|
||||
EXPR must be float, integer, or enumeral;
|
||||
EXPR must be float, fixed-point, integer, or enumeral;
|
||||
in other cases error is called. */
|
||||
|
||||
tree
|
||||
@ -319,6 +320,9 @@ convert_to_real (tree type, tree expr)
|
||||
case BOOLEAN_TYPE:
|
||||
return build1 (FLOAT_EXPR, type, expr);
|
||||
|
||||
case FIXED_POINT_TYPE:
|
||||
return build1 (FIXED_CONVERT_EXPR, type, expr);
|
||||
|
||||
case COMPLEX_TYPE:
|
||||
return convert (type,
|
||||
fold_build1 (REALPART_EXPR,
|
||||
@ -337,8 +341,8 @@ convert_to_real (tree type, tree expr)
|
||||
|
||||
/* Convert EXPR to some integer (or enum) type TYPE.
|
||||
|
||||
EXPR must be pointer, integer, discrete (enum, char, or bool), float, or
|
||||
vector; in other cases error is called.
|
||||
EXPR must be pointer, integer, discrete (enum, char, or bool), float,
|
||||
fixed-point or vector; in other cases error is called.
|
||||
|
||||
The result of this is always supposed to be a newly created tree node
|
||||
not in use in any existing structure. */
|
||||
@ -713,6 +717,9 @@ convert_to_integer (tree type, tree expr)
|
||||
case REAL_TYPE:
|
||||
return build1 (FIX_TRUNC_EXPR, type, expr);
|
||||
|
||||
case FIXED_POINT_TYPE:
|
||||
return build1 (FIXED_CONVERT_EXPR, type, expr);
|
||||
|
||||
case COMPLEX_TYPE:
|
||||
return convert (type,
|
||||
fold_build1 (REALPART_EXPR,
|
||||
@ -742,6 +749,7 @@ convert_to_complex (tree type, tree expr)
|
||||
switch (TREE_CODE (TREE_TYPE (expr)))
|
||||
{
|
||||
case REAL_TYPE:
|
||||
case FIXED_POINT_TYPE:
|
||||
case INTEGER_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
case BOOLEAN_TYPE:
|
||||
@ -806,3 +814,42 @@ convert_to_vector (tree type, tree expr)
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert EXPR to some fixed-point type TYPE.
|
||||
|
||||
EXPR must be fixed-point, float, integer, or enumeral;
|
||||
in other cases error is called. */
|
||||
|
||||
tree
|
||||
convert_to_fixed (tree type, tree expr)
|
||||
{
|
||||
if (integer_zerop (expr))
|
||||
{
|
||||
tree fixed_zero_node = build_fixed (type, FCONST0 (TYPE_MODE (type)));
|
||||
return fixed_zero_node;
|
||||
}
|
||||
else if (integer_onep (expr) && ALL_SCALAR_ACCUM_MODE_P (TYPE_MODE (type)))
|
||||
{
|
||||
tree fixed_one_node = build_fixed (type, FCONST1 (TYPE_MODE (type)));
|
||||
return fixed_one_node;
|
||||
}
|
||||
|
||||
switch (TREE_CODE (TREE_TYPE (expr)))
|
||||
{
|
||||
case FIXED_POINT_TYPE:
|
||||
case INTEGER_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
case BOOLEAN_TYPE:
|
||||
case REAL_TYPE:
|
||||
return build1 (FIXED_CONVERT_EXPR, type, expr);
|
||||
|
||||
case COMPLEX_TYPE:
|
||||
return convert (type,
|
||||
fold_build1 (REALPART_EXPR,
|
||||
TREE_TYPE (TREE_TYPE (expr)), expr));
|
||||
|
||||
default:
|
||||
error ("aggregate value used where a fixed-point was expected");
|
||||
return error_mark_node;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
extern tree convert_to_integer (tree, tree);
|
||||
extern tree convert_to_pointer (tree, tree);
|
||||
extern tree convert_to_real (tree, tree);
|
||||
extern tree convert_to_fixed (tree, tree);
|
||||
extern tree convert_to_complex (tree, tree);
|
||||
extern tree convert_to_vector (tree, tree);
|
||||
|
||||
|
@ -36,6 +36,7 @@ extensions, accepted by GCC in C89 mode and in C++.
|
||||
* Floating Types:: Additional Floating Types.
|
||||
* Decimal Float:: Decimal Floating Types.
|
||||
* Hex Floats:: Hexadecimal floating-point constants.
|
||||
* Fixed-Point:: Fixed-Point Types.
|
||||
* Zero Length:: Zero-length arrays.
|
||||
* Variable Length:: Arrays whose length is computed at run time.
|
||||
* Empty Structures:: Structures with no members.
|
||||
@ -949,6 +950,134 @@ would not be able to resolve the ambiguity of, e.g., @code{0x1.f}. This
|
||||
could mean @code{1.0f} or @code{1.9375} since @samp{f} is also the
|
||||
extension for floating-point constants of type @code{float}.
|
||||
|
||||
@node Fixed-Point
|
||||
@section Fixed-Point Types
|
||||
@cindex fixed-point types
|
||||
@cindex @code{_Fract} data type
|
||||
@cindex @code{_Accum} data type
|
||||
@cindex @code{_Sat} data type
|
||||
@cindex @code{hr} fixed-suffix
|
||||
@cindex @code{r} fixed-suffix
|
||||
@cindex @code{lr} fixed-suffix
|
||||
@cindex @code{llr} fixed-suffix
|
||||
@cindex @code{uhr} fixed-suffix
|
||||
@cindex @code{ur} fixed-suffix
|
||||
@cindex @code{ulr} fixed-suffix
|
||||
@cindex @code{ullr} fixed-suffix
|
||||
@cindex @code{hk} fixed-suffix
|
||||
@cindex @code{k} fixed-suffix
|
||||
@cindex @code{lk} fixed-suffix
|
||||
@cindex @code{llk} fixed-suffix
|
||||
@cindex @code{uhk} fixed-suffix
|
||||
@cindex @code{uk} fixed-suffix
|
||||
@cindex @code{ulk} fixed-suffix
|
||||
@cindex @code{ullk} fixed-suffix
|
||||
@cindex @code{HR} fixed-suffix
|
||||
@cindex @code{R} fixed-suffix
|
||||
@cindex @code{LR} fixed-suffix
|
||||
@cindex @code{LLR} fixed-suffix
|
||||
@cindex @code{UHR} fixed-suffix
|
||||
@cindex @code{UR} fixed-suffix
|
||||
@cindex @code{ULR} fixed-suffix
|
||||
@cindex @code{ULLR} fixed-suffix
|
||||
@cindex @code{HK} fixed-suffix
|
||||
@cindex @code{K} fixed-suffix
|
||||
@cindex @code{LK} fixed-suffix
|
||||
@cindex @code{LLK} fixed-suffix
|
||||
@cindex @code{UHK} fixed-suffix
|
||||
@cindex @code{UK} fixed-suffix
|
||||
@cindex @code{ULK} fixed-suffix
|
||||
@cindex @code{ULLK} fixed-suffix
|
||||
|
||||
As an extension, the GNU C compiler supports fixed-point types as
|
||||
defined in the N1169 draft of ISO/IEC DTR 18037. Support for fixed-point
|
||||
types in GCC will evolve as the draft technical report changes.
|
||||
Calling conventions for any target might also change. Not all targets
|
||||
support fixed-point types.
|
||||
|
||||
The fixed-point types are
|
||||
@code{short _Fract},
|
||||
@code{_Fract},
|
||||
@code{long _Fract},
|
||||
@code{long long _Fract},
|
||||
@code{unsigned short _Fract},
|
||||
@code{unsigned _Fract},
|
||||
@code{unsigned long _Fract},
|
||||
@code{unsigned long long _Fract},
|
||||
@code{_Sat short _Fract},
|
||||
@code{_Sat _Fract},
|
||||
@code{_Sat long _Fract},
|
||||
@code{_Sat long long _Fract},
|
||||
@code{_Sat unsigned short _Fract},
|
||||
@code{_Sat unsigned _Fract},
|
||||
@code{_Sat unsigned long _Fract},
|
||||
@code{_Sat unsigned long long _Fract},
|
||||
@code{short _Accum},
|
||||
@code{_Accum},
|
||||
@code{long _Accum},
|
||||
@code{long long _Accum},
|
||||
@code{unsigned short _Accum},
|
||||
@code{unsigned _Accum},
|
||||
@code{unsigned long _Accum},
|
||||
@code{unsigned long long _Accum},
|
||||
@code{_Sat short _Accum},
|
||||
@code{_Sat _Accum},
|
||||
@code{_Sat long _Accum},
|
||||
@code{_Sat long long _Accum},
|
||||
@code{_Sat unsigned short _Accum},
|
||||
@code{_Sat unsigned _Accum},
|
||||
@code{_Sat unsigned long _Accum},
|
||||
@code{_Sat unsigned long long _Accum}.
|
||||
Fixed-point data values contain fractional and optional integral parts.
|
||||
The format of fixed-point data varies and depends on the target machine.
|
||||
|
||||
Support for fixed-point types includes prefix and postfix increment
|
||||
and decrement operators (@code{++}, @code{--}); unary arithmetic operators
|
||||
(@code{+}, @code{-}, @code{!}); binary arithmetic operators (@code{+},
|
||||
@code{-}, @code{*}, @code{/}); binary shift operators (@code{<<}, @code{>>});
|
||||
relational operators (@code{<}, @code{<=}, @code{>=}, @code{>});
|
||||
equality operators (@code{==}, @code{!=}); assignment operators
|
||||
(@code{+=}, @code{-=}, @code{*=}, @code{/=}, @code{<<=}, @code{>>=});
|
||||
and conversions to and from integer, floating-point, or fixed-point types.
|
||||
|
||||
Use a suffix @samp{hr} or @samp{HR} in a literal constant of type
|
||||
@code{short _Fract} and @code{_Sat short _Fract},
|
||||
@samp{r} or @samp{R} for @code{_Fract} and @code{_Sat _Fract},
|
||||
@samp{lr} or @samp{LR} for @code{long _Fract} and @code{_Sat long _Fract},
|
||||
@samp{llr} or @samp{LLR} for @code{long long _Fract} and
|
||||
@code{_Sat long long _Fract},
|
||||
@samp{uhr} or @samp{UHR} for @code{unsigned short _Fract} and
|
||||
@code{_Sat unsigned short _Fract},
|
||||
@samp{ur} or @samp{UR} for @code{unsigned _Fract} and
|
||||
@code{_Sat unsigned _Fract},
|
||||
@samp{ulr} or @samp{ULR} for @code{unsigned long _Fract} and
|
||||
@code{_Sat unsigned long _Fract},
|
||||
@samp{ullr} or @samp{ULLR} for @code{unsigned long long _Fract}
|
||||
and @code{_Sat unsigned long long _Fract},
|
||||
@samp{hk} or @samp{HK} for @code{short _Accum} and @code{_Sat short _Accum},
|
||||
@samp{k} or @samp{K} for @code{_Accum} and @code{_Sat _Accum},
|
||||
@samp{lk} or @samp{LK} for @code{long _Accum} and @code{_Sat long _Accum},
|
||||
@samp{llk} or @samp{LLK} for @code{long long _Accum} and
|
||||
@code{_Sat long long _Accum},
|
||||
@samp{uhk} or @samp{UHK} for @code{unsigned short _Accum} and
|
||||
@code{_Sat unsigned short _Accum},
|
||||
@samp{uk} or @samp{UK} for @code{unsigned _Accum} and
|
||||
@code{_Sat unsigned _Accum},
|
||||
@samp{ulk} or @samp{ULK} for @code{unsigned long _Accum} and
|
||||
@code{_Sat unsigned long _Accum},
|
||||
and @samp{ullk} or @samp{ULLK} for @code{unsigned long long _Accum}
|
||||
and @code{_Sat unsigned long long _Accum}.
|
||||
|
||||
GCC support of fixed-point types as specified by the draft technical report
|
||||
is incomplete:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Pragmas to control overflow and rounding behaviors are not implemented.
|
||||
@end itemize
|
||||
|
||||
Fixed-point types are supported by the DWARF2 debug information format.
|
||||
|
||||
@node Zero Length
|
||||
@section Arrays of Length Zero
|
||||
@cindex arrays of length zero
|
||||
|
@ -3587,10 +3587,18 @@ Add operand 2 and operand 1, storing the result in operand 0. All operands
|
||||
must have mode @var{m}. This can be used even on two-address machines, by
|
||||
means of constraints requiring operands 1 and 0 to be the same location.
|
||||
|
||||
@cindex @code{ssadd@var{m}3} instruction pattern
|
||||
@cindex @code{usadd@var{m}3} instruction pattern
|
||||
@cindex @code{sub@var{m}3} instruction pattern
|
||||
@cindex @code{sssub@var{m}3} instruction pattern
|
||||
@cindex @code{ussub@var{m}3} instruction pattern
|
||||
@cindex @code{mul@var{m}3} instruction pattern
|
||||
@cindex @code{ssmul@var{m}3} instruction pattern
|
||||
@cindex @code{usmul@var{m}3} instruction pattern
|
||||
@cindex @code{div@var{m}3} instruction pattern
|
||||
@cindex @code{ssdiv@var{m}3} instruction pattern
|
||||
@cindex @code{udiv@var{m}3} instruction pattern
|
||||
@cindex @code{usdiv@var{m}3} instruction pattern
|
||||
@cindex @code{mod@var{m}3} instruction pattern
|
||||
@cindex @code{umod@var{m}3} instruction pattern
|
||||
@cindex @code{umin@var{m}3} instruction pattern
|
||||
@ -3598,8 +3606,11 @@ means of constraints requiring operands 1 and 0 to be the same location.
|
||||
@cindex @code{and@var{m}3} instruction pattern
|
||||
@cindex @code{ior@var{m}3} instruction pattern
|
||||
@cindex @code{xor@var{m}3} instruction pattern
|
||||
@item @samp{sub@var{m}3}, @samp{mul@var{m}3}
|
||||
@itemx @samp{div@var{m}3}, @samp{udiv@var{m}3}
|
||||
@item @samp{ssadd@var{m}3}, @samp{usadd@var{m}3}
|
||||
@item @samp{sub@var{m}3}, @samp{sssub@var{m}3}, @samp{ussub@var{m}3}
|
||||
@item @samp{mul@var{m}3}, @samp{ssmul@var{m}3}, @samp{usmul@var{m}3}
|
||||
@itemx @samp{div@var{m}3}, @samp{ssdiv@var{m}3}
|
||||
@itemx @samp{udiv@var{m}3}, @samp{usdiv@var{m}3}
|
||||
@itemx @samp{mod@var{m}3}, @samp{umod@var{m}3}
|
||||
@itemx @samp{umin@var{m}3}, @samp{umax@var{m}3}
|
||||
@itemx @samp{and@var{m}3}, @samp{ior@var{m}3}, @samp{xor@var{m}3}
|
||||
@ -3772,7 +3783,7 @@ Similar, but the multiplication is unsigned.
|
||||
Multiply operands 1 and 2, sign-extend them to mode @var{n}, add
|
||||
operand 3, and store the result in operand 0. Operands 1 and 2
|
||||
have mode @var{m} and operands 0 and 3 have mode @var{n}.
|
||||
Both modes must be integer modes and @var{n} must be twice
|
||||
Both modes must be integer or fixed-point modes and @var{n} must be twice
|
||||
the size of @var{m}.
|
||||
|
||||
In other words, @code{madd@var{m}@var{n}4} is like
|
||||
@ -3785,12 +3796,22 @@ These instructions are not allowed to @code{FAIL}.
|
||||
Like @code{madd@var{m}@var{n}4}, but zero-extend the multiplication
|
||||
operands instead of sign-extending them.
|
||||
|
||||
@cindex @code{ssmadd@var{m}@var{n}4} instruction pattern
|
||||
@item @samp{ssmadd@var{m}@var{n}4}
|
||||
Like @code{madd@var{m}@var{n}4}, but all involved operations must be
|
||||
signed-saturating.
|
||||
|
||||
@cindex @code{usmadd@var{m}@var{n}4} instruction pattern
|
||||
@item @samp{usmadd@var{m}@var{n}4}
|
||||
Like @code{umadd@var{m}@var{n}4}, but all involved operations must be
|
||||
unsigned-saturating.
|
||||
|
||||
@cindex @code{msub@var{m}@var{n}4} instruction pattern
|
||||
@item @samp{msub@var{m}@var{n}4}
|
||||
Multiply operands 1 and 2, sign-extend them to mode @var{n}, subtract the
|
||||
result from operand 3, and store the result in operand 0. Operands 1 and 2
|
||||
have mode @var{m} and operands 0 and 3 have mode @var{n}.
|
||||
Both modes must be integer modes and @var{n} must be twice
|
||||
Both modes must be integer or fixed-point modes and @var{n} must be twice
|
||||
the size of @var{m}.
|
||||
|
||||
In other words, @code{msub@var{m}@var{n}4} is like
|
||||
@ -3804,6 +3825,16 @@ These instructions are not allowed to @code{FAIL}.
|
||||
Like @code{msub@var{m}@var{n}4}, but zero-extend the multiplication
|
||||
operands instead of sign-extending them.
|
||||
|
||||
@cindex @code{ssmsub@var{m}@var{n}4} instruction pattern
|
||||
@item @samp{ssmsub@var{m}@var{n}4}
|
||||
Like @code{msub@var{m}@var{n}4}, but all involved operations must be
|
||||
signed-saturating.
|
||||
|
||||
@cindex @code{usmsub@var{m}@var{n}4} instruction pattern
|
||||
@item @samp{usmsub@var{m}@var{n}4}
|
||||
Like @code{umsub@var{m}@var{n}4}, but all involved operations must be
|
||||
unsigned-saturating.
|
||||
|
||||
@cindex @code{divmod@var{m}4} instruction pattern
|
||||
@item @samp{divmod@var{m}4}
|
||||
Signed division that produces both a quotient and a remainder.
|
||||
@ -3828,7 +3859,9 @@ Similar, but does unsigned division.
|
||||
|
||||
@anchor{shift patterns}
|
||||
@cindex @code{ashl@var{m}3} instruction pattern
|
||||
@item @samp{ashl@var{m}3}
|
||||
@cindex @code{ssashl@var{m}3} instruction pattern
|
||||
@cindex @code{usashl@var{m}3} instruction pattern
|
||||
@item @samp{ashl@var{m}3}, @samp{ssashl@var{m}3}, @samp{usashl@var{m}3}
|
||||
Arithmetic-shift operand 1 left by a number of bits specified by operand
|
||||
2, and store the result in operand 0. Here @var{m} is the mode of
|
||||
operand 0 and operand 1; operand 2's mode is specified by the
|
||||
@ -3846,7 +3879,9 @@ Other shift and rotate instructions, analogous to the
|
||||
@code{ashl@var{m}3} instructions.
|
||||
|
||||
@cindex @code{neg@var{m}2} instruction pattern
|
||||
@item @samp{neg@var{m}2}
|
||||
@cindex @code{ssneg@var{m}2} instruction pattern
|
||||
@cindex @code{usneg@var{m}2} instruction pattern
|
||||
@item @samp{neg@var{m}2}, @samp{ssneg@var{m}2}, @samp{usneg@var{m}2}
|
||||
Negate operand 1 and store the result in operand 0.
|
||||
|
||||
@cindex @code{abs@var{m}2} instruction pattern
|
||||
@ -4274,6 +4309,39 @@ Zero-extend operand 1 (valid for mode @var{m}) to mode @var{n} and
|
||||
store in operand 0 (which has mode @var{n}). Both modes must be fixed
|
||||
point.
|
||||
|
||||
@cindex @code{fract@var{mn}2} instruction pattern
|
||||
@item @samp{fract@var{m}@var{n}2}
|
||||
Convert operand 1 of mode @var{m} to mode @var{n} and store in
|
||||
operand 0 (which has mode @var{n}). Mode @var{m} and mode @var{n}
|
||||
could be fixed-point to fixed-point, signed integer to fixed-point,
|
||||
fixed-point to signed integer, floating-point to fixed-point,
|
||||
or fixed-point to floating-point.
|
||||
When overflows or underflows happen, the results are undefined.
|
||||
|
||||
@cindex @code{satfract@var{mn}2} instruction pattern
|
||||
@item @samp{satfract@var{m}@var{n}2}
|
||||
Convert operand 1 of mode @var{m} to mode @var{n} and store in
|
||||
operand 0 (which has mode @var{n}). Mode @var{m} and mode @var{n}
|
||||
could be fixed-point to fixed-point, signed integer to fixed-point,
|
||||
or floating-point to fixed-point.
|
||||
When overflows or underflows happen, the instruction saturates the
|
||||
results to the maximum or the minimum.
|
||||
|
||||
@cindex @code{fractuns@var{mn}2} instruction pattern
|
||||
@item @samp{fractuns@var{m}@var{n}2}
|
||||
Convert operand 1 of mode @var{m} to mode @var{n} and store in
|
||||
operand 0 (which has mode @var{n}). Mode @var{m} and mode @var{n}
|
||||
could be unsigned integer to fixed-point, or
|
||||
fixed-point to unsigned integer.
|
||||
When overflows or underflows happen, the results are undefined.
|
||||
|
||||
@cindex @code{satfractuns@var{mn}2} instruction pattern
|
||||
@item @samp{satfractuns@var{m}@var{n}2}
|
||||
Convert unsigned integer operand 1 of mode @var{m} to fixed-point mode
|
||||
@var{n} and store in operand 0 (which has mode @var{n}).
|
||||
When overflows or underflows happen, the instruction saturates the
|
||||
results to the maximum or the minimum.
|
||||
|
||||
@cindex @code{extv} instruction pattern
|
||||
@item @samp{extv}
|
||||
Extract a bit-field from operand 1 (a register or memory operand), where
|
||||
|
109
gcc/expr.c
109
gcc/expr.c
@ -347,7 +347,8 @@ init_expr (void)
|
||||
}
|
||||
|
||||
/* Copy data from FROM to TO, where the machine modes are not the same.
|
||||
Both modes may be integer, or both may be floating.
|
||||
Both modes may be integer, or both may be floating, or both may be
|
||||
fixed-point.
|
||||
UNSIGNEDP should be nonzero if FROM is an unsigned type.
|
||||
This causes zero-extension instead of sign-extension. */
|
||||
|
||||
@ -502,6 +503,22 @@ convert_move (rtx to, rtx from, int unsignedp)
|
||||
from = new_from;
|
||||
}
|
||||
|
||||
/* Make sure both are fixed-point modes or both are not. */
|
||||
gcc_assert (ALL_SCALAR_FIXED_POINT_MODE_P (from_mode) ==
|
||||
ALL_SCALAR_FIXED_POINT_MODE_P (to_mode));
|
||||
if (ALL_SCALAR_FIXED_POINT_MODE_P (from_mode))
|
||||
{
|
||||
/* If we widen from_mode to to_mode and they are in the same class,
|
||||
we won't saturate the result.
|
||||
Otherwise, always saturate the result to play safe. */
|
||||
if (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
|
||||
&& GET_MODE_SIZE (from_mode) < GET_MODE_SIZE (to_mode))
|
||||
expand_fixed_convert (to, from, 0, 0);
|
||||
else
|
||||
expand_fixed_convert (to, from, 0, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now both modes are integers. */
|
||||
|
||||
/* Handle expanding beyond a word. */
|
||||
@ -3284,7 +3301,8 @@ emit_move_insn_1 (rtx x, rtx y)
|
||||
if (COMPLEX_MODE_P (mode))
|
||||
return emit_move_complex (mode, x, y);
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT)
|
||||
if (GET_MODE_CLASS (mode) == MODE_DECIMAL_FLOAT
|
||||
|| ALL_FIXED_POINT_MODE_P (mode))
|
||||
{
|
||||
rtx result = emit_move_via_integer (mode, x, y, true);
|
||||
|
||||
@ -4763,6 +4781,7 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
|
||||
|
||||
case INTEGER_CST:
|
||||
case REAL_CST:
|
||||
case FIXED_CST:
|
||||
if (!initializer_zerop (value))
|
||||
nz_elts += mult;
|
||||
elt_count += mult;
|
||||
@ -4945,6 +4964,7 @@ count_type_elements (const_tree type, bool allow_flexarr)
|
||||
|
||||
case INTEGER_TYPE:
|
||||
case REAL_TYPE:
|
||||
case FIXED_POINT_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
case BOOLEAN_TYPE:
|
||||
case POINTER_TYPE:
|
||||
@ -7231,7 +7251,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
{
|
||||
tree tmp = NULL_TREE;
|
||||
if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
|
||||
return const_vector_from_tree (exp);
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT)
|
||||
{
|
||||
@ -7263,6 +7287,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
return CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (exp),
|
||||
TYPE_MODE (TREE_TYPE (exp)));
|
||||
|
||||
case FIXED_CST:
|
||||
return CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (exp),
|
||||
TYPE_MODE (TREE_TYPE (exp)));
|
||||
|
||||
case COMPLEX_CST:
|
||||
/* Handle evaluating a complex constant in a CONCAT target. */
|
||||
if (original_target && GET_CODE (original_target) == CONCAT)
|
||||
@ -8152,18 +8180,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
case PLUS_EXPR:
|
||||
|
||||
/* Check if this is a case for multiplication and addition. */
|
||||
if (TREE_CODE (type) == INTEGER_TYPE
|
||||
if ((TREE_CODE (type) == INTEGER_TYPE
|
||||
|| TREE_CODE (type) == FIXED_POINT_TYPE)
|
||||
&& TREE_CODE (TREE_OPERAND (exp, 0)) == MULT_EXPR)
|
||||
{
|
||||
tree subsubexp0, subsubexp1;
|
||||
enum tree_code code0, code1;
|
||||
enum tree_code code0, code1, this_code;
|
||||
|
||||
subexp0 = TREE_OPERAND (exp, 0);
|
||||
subsubexp0 = TREE_OPERAND (subexp0, 0);
|
||||
subsubexp1 = TREE_OPERAND (subexp0, 1);
|
||||
code0 = TREE_CODE (subsubexp0);
|
||||
code1 = TREE_CODE (subsubexp1);
|
||||
if (code0 == NOP_EXPR && code1 == NOP_EXPR
|
||||
this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
|
||||
: FIXED_CONVERT_EXPR;
|
||||
if (code0 == this_code && code1 == this_code
|
||||
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
|
||||
< TYPE_PRECISION (TREE_TYPE (subsubexp0)))
|
||||
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
|
||||
@ -8174,7 +8205,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
|
||||
enum machine_mode innermode = TYPE_MODE (op0type);
|
||||
bool zextend_p = TYPE_UNSIGNED (op0type);
|
||||
this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
|
||||
bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
|
||||
if (sat_p == 0)
|
||||
this_optab = zextend_p ? umadd_widen_optab : smadd_widen_optab;
|
||||
else
|
||||
this_optab = zextend_p ? usmadd_widen_optab
|
||||
: ssmadd_widen_optab;
|
||||
if (mode == GET_MODE_2XWIDER_MODE (innermode)
|
||||
&& (optab_handler (this_optab, mode)->insn_code
|
||||
!= CODE_FOR_nothing))
|
||||
@ -8307,18 +8343,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
|
||||
case MINUS_EXPR:
|
||||
/* Check if this is a case for multiplication and subtraction. */
|
||||
if (TREE_CODE (type) == INTEGER_TYPE
|
||||
if ((TREE_CODE (type) == INTEGER_TYPE
|
||||
|| TREE_CODE (type) == FIXED_POINT_TYPE)
|
||||
&& TREE_CODE (TREE_OPERAND (exp, 1)) == MULT_EXPR)
|
||||
{
|
||||
tree subsubexp0, subsubexp1;
|
||||
enum tree_code code0, code1;
|
||||
enum tree_code code0, code1, this_code;
|
||||
|
||||
subexp1 = TREE_OPERAND (exp, 1);
|
||||
subsubexp0 = TREE_OPERAND (subexp1, 0);
|
||||
subsubexp1 = TREE_OPERAND (subexp1, 1);
|
||||
code0 = TREE_CODE (subsubexp0);
|
||||
code1 = TREE_CODE (subsubexp1);
|
||||
if (code0 == NOP_EXPR && code1 == NOP_EXPR
|
||||
this_code = TREE_CODE (type) == INTEGER_TYPE ? NOP_EXPR
|
||||
: FIXED_CONVERT_EXPR;
|
||||
if (code0 == this_code && code1 == this_code
|
||||
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
|
||||
< TYPE_PRECISION (TREE_TYPE (subsubexp0)))
|
||||
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (subsubexp0, 0)))
|
||||
@ -8329,7 +8368,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
tree op0type = TREE_TYPE (TREE_OPERAND (subsubexp0, 0));
|
||||
enum machine_mode innermode = TYPE_MODE (op0type);
|
||||
bool zextend_p = TYPE_UNSIGNED (op0type);
|
||||
this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab;
|
||||
bool sat_p = TYPE_SATURATING (TREE_TYPE (subsubexp0));
|
||||
if (sat_p == 0)
|
||||
this_optab = zextend_p ? umsub_widen_optab : smsub_widen_optab;
|
||||
else
|
||||
this_optab = zextend_p ? usmsub_widen_optab
|
||||
: ssmsub_widen_optab;
|
||||
if (mode == GET_MODE_2XWIDER_MODE (innermode)
|
||||
&& (optab_handler (this_optab, mode)->insn_code
|
||||
!= CODE_FOR_nothing))
|
||||
@ -8388,6 +8432,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
goto binop2;
|
||||
|
||||
case MULT_EXPR:
|
||||
/* If this is a fixed-point operation, then we cannot use the code
|
||||
below because "expand_mult" doesn't support sat/no-sat fixed-point
|
||||
multiplications. */
|
||||
if (ALL_FIXED_POINT_MODE_P (mode))
|
||||
goto binop;
|
||||
|
||||
/* If first operand is constant, swap them.
|
||||
Thus the following special case checks need only
|
||||
check the second operand. */
|
||||
@ -8540,6 +8590,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
case CEIL_DIV_EXPR:
|
||||
case ROUND_DIV_EXPR:
|
||||
case EXACT_DIV_EXPR:
|
||||
/* If this is a fixed-point operation, then we cannot use the code
|
||||
below because "expand_divmod" doesn't support sat/no-sat fixed-point
|
||||
divisions. */
|
||||
if (ALL_FIXED_POINT_MODE_P (mode))
|
||||
goto binop;
|
||||
|
||||
if (modifier == EXPAND_STACK_PARM)
|
||||
target = 0;
|
||||
/* Possible optimization: compute the dividend with EXPAND_SUM
|
||||
@ -8562,6 +8618,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
subtarget, &op0, &op1, 0);
|
||||
return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
|
||||
|
||||
case FIXED_CONVERT_EXPR:
|
||||
op0 = expand_normal (TREE_OPERAND (exp, 0));
|
||||
if (target == 0 || modifier == EXPAND_STACK_PARM)
|
||||
target = gen_reg_rtx (mode);
|
||||
|
||||
if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == INTEGER_TYPE
|
||||
&& TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
|
||||
|| (TREE_CODE (type) == INTEGER_TYPE && TYPE_UNSIGNED (type)))
|
||||
expand_fixed_convert (target, op0, 1, TYPE_SATURATING (type));
|
||||
else
|
||||
expand_fixed_convert (target, op0, 0, TYPE_SATURATING (type));
|
||||
return target;
|
||||
|
||||
case FIX_TRUNC_EXPR:
|
||||
op0 = expand_normal (TREE_OPERAND (exp, 0));
|
||||
if (target == 0 || modifier == EXPAND_STACK_PARM)
|
||||
@ -8767,6 +8836,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
||||
case RSHIFT_EXPR:
|
||||
case LROTATE_EXPR:
|
||||
case RROTATE_EXPR:
|
||||
/* If this is a fixed-point operation, then we cannot use the code
|
||||
below because "expand_shift" doesn't support sat/no-sat fixed-point
|
||||
shifts. */
|
||||
if (ALL_FIXED_POINT_MODE_P (mode))
|
||||
goto binop;
|
||||
|
||||
if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1), 1))
|
||||
subtarget = 0;
|
||||
if (modifier == EXPAND_STACK_PARM)
|
||||
@ -9583,7 +9658,8 @@ do_store_flag (tree exp, rtx target, enum machine_mode mode, int only_cheap)
|
||||
}
|
||||
|
||||
/* Put a constant second. */
|
||||
if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
|
||||
if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST
|
||||
|| TREE_CODE (arg0) == FIXED_CST)
|
||||
{
|
||||
tem = arg0; arg0 = arg1; arg1 = tem;
|
||||
code = swap_condition (code);
|
||||
@ -9887,7 +9963,11 @@ vector_mode_valid_p (enum machine_mode mode)
|
||||
|
||||
/* Doh! What's going on? */
|
||||
if (class != MODE_VECTOR_INT
|
||||
&& class != MODE_VECTOR_FLOAT)
|
||||
&& class != MODE_VECTOR_FLOAT
|
||||
&& class != MODE_VECTOR_FRACT
|
||||
&& class != MODE_VECTOR_UFRACT
|
||||
&& class != MODE_VECTOR_ACCUM
|
||||
&& class != MODE_VECTOR_UACCUM)
|
||||
return 0;
|
||||
|
||||
/* Hardware support. Woo hoo! */
|
||||
@ -9931,6 +10011,9 @@ const_vector_from_tree (tree exp)
|
||||
if (TREE_CODE (elt) == REAL_CST)
|
||||
RTVEC_ELT (v, i) = CONST_DOUBLE_FROM_REAL_VALUE (TREE_REAL_CST (elt),
|
||||
inner);
|
||||
else if (TREE_CODE (elt) == FIXED_CST)
|
||||
RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
|
||||
inner);
|
||||
else
|
||||
RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
|
||||
TREE_INT_CST_HIGH (elt),
|
||||
|
@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
only full integer modes should be considered for the next mode, and $F
|
||||
means that only float modes should be considered.
|
||||
$P means that both full and partial integer modes should be considered.
|
||||
$Q means that only fixed-point modes should be considered.
|
||||
|
||||
$V means to emit 'v' if the first mode is a MODE_FLOAT mode.
|
||||
|
||||
@ -67,14 +68,28 @@ static const char * const optabs[] =
|
||||
"convert_optab_handler (sfloat_optab, $B, $A)->insn_code = CODE_FOR_$(float$I$a$F$b2$)",
|
||||
"convert_optab_handler (ufloat_optab, $B, $A)->insn_code = CODE_FOR_$(floatuns$I$a$F$b2$)",
|
||||
"convert_optab_handler (trunc_optab, $B, $A)->insn_code = CODE_FOR_$(trunc$a$b2$)",
|
||||
"convert_optab_handler (fract_optab, $B, $A)->insn_code = CODE_FOR_$(fract$a$b2$)",
|
||||
"convert_optab_handler (fractuns_optab, $B, $A)->insn_code = CODE_FOR_$(fractuns$I$a$Q$b2$)",
|
||||
"convert_optab_handler (fractuns_optab, $B, $A)->insn_code = CODE_FOR_$(fractuns$Q$a$I$b2$)",
|
||||
"convert_optab_handler (satfract_optab, $B, $A)->insn_code = CODE_FOR_$(satfract$a$Q$b2$)",
|
||||
"convert_optab_handler (satfractuns_optab, $B, $A)->insn_code = CODE_FOR_$(satfractuns$I$a$Q$b2$)",
|
||||
"optab_handler (add_optab, $A)->insn_code = CODE_FOR_$(add$P$a3$)",
|
||||
"optab_handler (addv_optab, $A)->insn_code =\n\
|
||||
optab_handler (add_optab, $A)->insn_code = CODE_FOR_$(add$F$a3$)",
|
||||
"optab_handler (addv_optab, $A)->insn_code = CODE_FOR_$(addv$I$a3$)",
|
||||
"optab_handler (add_optab, $A)->insn_code = CODE_FOR_$(add$Q$a3$)",
|
||||
"optab_handler (ssadd_optab, $A)->insn_code = CODE_FOR_$(ssadd$Q$a3$)",
|
||||
"optab_handler (usadd_optab, $A)->insn_code = CODE_FOR_$(usadd$Q$a3$)",
|
||||
"optab_handler (sub_optab, $A)->insn_code = CODE_FOR_$(sub$P$a3$)",
|
||||
"optab_handler (subv_optab, $A)->insn_code =\n\
|
||||
optab_handler (sub_optab, $A)->insn_code = CODE_FOR_$(sub$F$a3$)",
|
||||
"optab_handler (subv_optab, $A)->insn_code = CODE_FOR_$(subv$I$a3$)",
|
||||
"optab_handler (sub_optab, $A)->insn_code = CODE_FOR_$(sub$Q$a3$)",
|
||||
"optab_handler (sssub_optab, $A)->insn_code = CODE_FOR_$(sssub$Q$a3$)",
|
||||
"optab_handler (ussub_optab, $A)->insn_code = CODE_FOR_$(ussub$Q$a3$)",
|
||||
"optab_handler (smul_optab, $A)->insn_code = CODE_FOR_$(mul$Q$a3$)",
|
||||
"optab_handler (ssmul_optab, $A)->insn_code = CODE_FOR_$(ssmul$Q$a3$)",
|
||||
"optab_handler (usmul_optab, $A)->insn_code = CODE_FOR_$(usmul$Q$a3$)",
|
||||
"optab_handler (smul_optab, $A)->insn_code = CODE_FOR_$(mul$P$a3$)",
|
||||
"optab_handler (smulv_optab, $A)->insn_code =\n\
|
||||
optab_handler (smul_optab, $A)->insn_code = CODE_FOR_$(mul$F$a3$)",
|
||||
@ -86,11 +101,18 @@ static const char * const optabs[] =
|
||||
"optab_handler (usmul_widen_optab, $B)->insn_code = CODE_FOR_$(usmul$a$b3$)$N",
|
||||
"optab_handler (smadd_widen_optab, $B)->insn_code = CODE_FOR_$(madd$a$b4$)$N",
|
||||
"optab_handler (umadd_widen_optab, $B)->insn_code = CODE_FOR_$(umadd$a$b4$)$N",
|
||||
"optab_handler (ssmadd_widen_optab, $B)->insn_code = CODE_FOR_$(ssmadd$a$b4$)$N",
|
||||
"optab_handler (usmadd_widen_optab, $B)->insn_code = CODE_FOR_$(usmadd$a$b4$)$N",
|
||||
"optab_handler (smsub_widen_optab, $B)->insn_code = CODE_FOR_$(msub$a$b4$)$N",
|
||||
"optab_handler (umsub_widen_optab, $B)->insn_code = CODE_FOR_$(umsub$a$b4$)$N",
|
||||
"optab_handler (ssmsub_widen_optab, $B)->insn_code = CODE_FOR_$(ssmsub$a$b4$)$N",
|
||||
"optab_handler (usmsub_widen_optab, $B)->insn_code = CODE_FOR_$(usmsub$a$b4$)$N",
|
||||
"optab_handler (sdiv_optab, $A)->insn_code = CODE_FOR_$(div$a3$)",
|
||||
"optab_handler (ssdiv_optab, $A)->insn_code = CODE_FOR_$(ssdiv$Q$a3$)",
|
||||
"optab_handler (sdivv_optab, $A)->insn_code = CODE_FOR_$(div$V$I$a3$)",
|
||||
"optab_handler (udiv_optab, $A)->insn_code = CODE_FOR_$(udiv$I$a3$)",
|
||||
"optab_handler (udiv_optab, $A)->insn_code = CODE_FOR_$(udiv$Q$a3$)",
|
||||
"optab_handler (usdiv_optab, $A)->insn_code = CODE_FOR_$(usdiv$Q$a3$)",
|
||||
"optab_handler (sdivmod_optab, $A)->insn_code = CODE_FOR_$(divmod$a4$)",
|
||||
"optab_handler (udivmod_optab, $A)->insn_code = CODE_FOR_$(udivmod$a4$)",
|
||||
"optab_handler (smod_optab, $A)->insn_code = CODE_FOR_$(mod$a3$)",
|
||||
@ -102,6 +124,8 @@ static const char * const optabs[] =
|
||||
"optab_handler (ior_optab, $A)->insn_code = CODE_FOR_$(ior$a3$)",
|
||||
"optab_handler (xor_optab, $A)->insn_code = CODE_FOR_$(xor$a3$)",
|
||||
"optab_handler (ashl_optab, $A)->insn_code = CODE_FOR_$(ashl$a3$)",
|
||||
"optab_handler (ssashl_optab, $A)->insn_code = CODE_FOR_$(ssashl$Q$a3$)",
|
||||
"optab_handler (usashl_optab, $A)->insn_code = CODE_FOR_$(usashl$Q$a3$)",
|
||||
"optab_handler (ashr_optab, $A)->insn_code = CODE_FOR_$(ashr$a3$)",
|
||||
"optab_handler (lshr_optab, $A)->insn_code = CODE_FOR_$(lshr$a3$)",
|
||||
"optab_handler (rotl_optab, $A)->insn_code = CODE_FOR_$(rotl$a3$)",
|
||||
@ -116,6 +140,9 @@ static const char * const optabs[] =
|
||||
"optab_handler (negv_optab, $A)->insn_code =\n\
|
||||
optab_handler (neg_optab, $A)->insn_code = CODE_FOR_$(neg$F$a2$)",
|
||||
"optab_handler (negv_optab, $A)->insn_code = CODE_FOR_$(negv$I$a2$)",
|
||||
"optab_handler (neg_optab, $A)->insn_code = CODE_FOR_$(neg$Q$a2$)",
|
||||
"optab_handler (ssneg_optab, $A)->insn_code = CODE_FOR_$(ssneg$Q$a2$)",
|
||||
"optab_handler (usneg_optab, $A)->insn_code = CODE_FOR_$(usneg$Q$a2$)",
|
||||
"optab_handler (abs_optab, $A)->insn_code = CODE_FOR_$(abs$P$a2$)",
|
||||
"optab_handler (absv_optab, $A)->insn_code =\n\
|
||||
optab_handler (abs_optab, $A)->insn_code = CODE_FOR_$(abs$F$a2$)",
|
||||
@ -267,6 +294,7 @@ gen_insn (rtx insn)
|
||||
for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
|
||||
{
|
||||
int force_float = 0, force_int = 0, force_partial_int = 0;
|
||||
int force_fixed = 0;
|
||||
int force_consec = 0;
|
||||
int matches = 1;
|
||||
|
||||
@ -296,6 +324,9 @@ gen_insn (rtx insn)
|
||||
case 'F':
|
||||
force_float = 1;
|
||||
break;
|
||||
case 'Q':
|
||||
force_fixed = 1;
|
||||
break;
|
||||
case 'V':
|
||||
break;
|
||||
case 'c':
|
||||
@ -342,7 +373,16 @@ gen_insn (rtx insn)
|
||||
|| mode_class[i] == MODE_FLOAT
|
||||
|| mode_class[i] == MODE_DECIMAL_FLOAT
|
||||
|| mode_class[i] == MODE_COMPLEX_FLOAT
|
||||
|| mode_class[i] == MODE_VECTOR_FLOAT))
|
||||
|| mode_class[i] == MODE_VECTOR_FLOAT)
|
||||
&& (! force_fixed
|
||||
|| mode_class[i] == MODE_FRACT
|
||||
|| mode_class[i] == MODE_UFRACT
|
||||
|| mode_class[i] == MODE_ACCUM
|
||||
|| mode_class[i] == MODE_UACCUM
|
||||
|| mode_class[i] == MODE_VECTOR_FRACT
|
||||
|| mode_class[i] == MODE_VECTOR_UFRACT
|
||||
|| mode_class[i] == MODE_VECTOR_ACCUM
|
||||
|| mode_class[i] == MODE_VECTOR_UACCUM))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -353,7 +393,7 @@ gen_insn (rtx insn)
|
||||
else
|
||||
m2 = i, np += strlen (GET_MODE_NAME(i));
|
||||
|
||||
force_int = force_partial_int = force_float = 0;
|
||||
force_int = force_partial_int = force_float = force_fixed = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
207
gcc/ginclude/stdfix.h
Normal file
207
gcc/ginclude/stdfix.h
Normal file
@ -0,0 +1,207 @@
|
||||
/* Copyright (C) 2007 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, if you include this header file into source
|
||||
files compiled by GCC, this header file does not by itself cause
|
||||
the resulting executable to be covered by the GNU General Public
|
||||
License. This exception does not however invalidate any other
|
||||
reasons why the executable file might be covered by the GNU General
|
||||
Public License. */
|
||||
|
||||
/* ISO/IEC JTC1 SC22 WG14 N1169
|
||||
* Date: 2006-04-04
|
||||
* ISO/IEC TR 18037
|
||||
* Programming languages - C - Extensions to support embedded processors
|
||||
*/
|
||||
|
||||
#ifndef _STDFIX_H
|
||||
#define _STDFIX_H
|
||||
|
||||
/* 7.18a.1 Introduction. */
|
||||
|
||||
#undef fract
|
||||
#undef accum
|
||||
#undef sat
|
||||
#define fract _Fract
|
||||
#define accum _Accum
|
||||
#define sat _Sat
|
||||
|
||||
/* 7.18a.3 Precision macros. */
|
||||
|
||||
#undef SFRACT_FBIT
|
||||
#undef SFRACT_MIN
|
||||
#undef SFRACT_MAX
|
||||
#undef SFRACT_EPSILON
|
||||
#define SFRACT_FBIT __SFRACT_FBIT__
|
||||
#define SFRACT_MIN __SFRACT_MIN__
|
||||
#define SFRACT_MAX __SFRACT_MAX__
|
||||
#define SFRACT_EPSILON __SFRACT_EPSILON__
|
||||
|
||||
#undef USFRACT_FBIT
|
||||
#undef USFRACT_MIN
|
||||
#undef USFRACT_MAX
|
||||
#undef USFRACT_EPSILON
|
||||
#define USFRACT_FBIT __USFRACT_FBIT__
|
||||
#define USFRACT_MIN __USFRACT_MIN__ /* GCC extension. */
|
||||
#define USFRACT_MAX __USFRACT_MAX__
|
||||
#define USFRACT_EPSILON __USFRACT_EPSILON__
|
||||
|
||||
#undef FRACT_FBIT
|
||||
#undef FRACT_MIN
|
||||
#undef FRACT_MAX
|
||||
#undef FRACT_EPSILON
|
||||
#define FRACT_FBIT __FRACT_FBIT__
|
||||
#define FRACT_MIN __FRACT_MIN__
|
||||
#define FRACT_MAX __FRACT_MAX__
|
||||
#define FRACT_EPSILON __FRACT_EPSILON__
|
||||
|
||||
#undef UFRACT_FBIT
|
||||
#undef UFRACT_MIN
|
||||
#undef UFRACT_MAX
|
||||
#undef UFRACT_EPSILON
|
||||
#define UFRACT_FBIT __UFRACT_FBIT__
|
||||
#define UFRACT_MIN __UFRACT_MIN__ /* GCC extension. */
|
||||
#define UFRACT_MAX __UFRACT_MAX__
|
||||
#define UFRACT_EPSILON __UFRACT_EPSILON__
|
||||
|
||||
#undef LFRACT_FBIT
|
||||
#undef LFRACT_MIN
|
||||
#undef LFRACT_MAX
|
||||
#undef LFRACT_EPSILON
|
||||
#define LFRACT_FBIT __LFRACT_FBIT__
|
||||
#define LFRACT_MIN __LFRACT_MIN__
|
||||
#define LFRACT_MAX __LFRACT_MAX__
|
||||
#define LFRACT_EPSILON __LFRACT_EPSILON__
|
||||
|
||||
#undef ULFRACT_FBIT
|
||||
#undef ULFRACT_MIN
|
||||
#undef ULFRACT_MAX
|
||||
#undef ULFRACT_EPSILON
|
||||
#define ULFRACT_FBIT __ULFRACT_FBIT__
|
||||
#define ULFRACT_MIN __ULFRACT_MIN__ /* GCC extension. */
|
||||
#define ULFRACT_MAX __ULFRACT_MAX__
|
||||
#define ULFRACT_EPSILON __ULFRACT_EPSILON__
|
||||
|
||||
#undef LLFRACT_FBIT
|
||||
#undef LLFRACT_MIN
|
||||
#undef LLFRACT_MAX
|
||||
#undef LLFRACT_EPSILON
|
||||
#define LLFRACT_FBIT __LLFRACT_FBIT__ /* GCC extension. */
|
||||
#define LLFRACT_MIN __LLFRACT_MIN__ /* GCC extension. */
|
||||
#define LLFRACT_MAX __LLFRACT_MAX__ /* GCC extension. */
|
||||
#define LLFRACT_EPSILON __LLFRACT_EPSILON__ /* GCC extension. */
|
||||
|
||||
#undef ULLFRACT_FBIT
|
||||
#undef ULLFRACT_MIN
|
||||
#undef ULLFRACT_MAX
|
||||
#undef ULLFRACT_EPSILON
|
||||
#define ULLFRACT_FBIT __ULLFRACT_FBIT__ /* GCC extension. */
|
||||
#define ULLFRACT_MIN __ULLFRACT_MIN__ /* GCC extension. */
|
||||
#define ULLFRACT_MAX __ULLFRACT_MAX__ /* GCC extension. */
|
||||
#define ULLFRACT_EPSILON __ULLFRACT_EPSILON__ /* GCC extension. */
|
||||
|
||||
#undef SACCUM_FBIT
|
||||
#undef SACCUM_IBIT
|
||||
#undef SACCUM_MIN
|
||||
#undef SACCUM_MAX
|
||||
#undef SACCUM_EPSILON
|
||||
#define SACCUM_FBIT __SACCUM_FBIT__
|
||||
#define SACCUM_IBIT __SACCUM_IBIT__
|
||||
#define SACCUM_MIN __SACCUM_MIN__
|
||||
#define SACCUM_MAX __SACCUM_MAX__
|
||||
#define SACCUM_EPSILON __SACCUM_EPSILON__
|
||||
|
||||
#undef USACCUM_FBIT
|
||||
#undef USACCUM_IBIT
|
||||
#undef USACCUM_MIN
|
||||
#undef USACCUM_MAX
|
||||
#undef USACCUM_EPSILON
|
||||
#define USACCUM_FBIT __USACCUM_FBIT__
|
||||
#define USACCUM_IBIT __USACCUM_IBIT__
|
||||
#define USACCUM_MIN __USACCUM_MIN__ /* GCC extension. */
|
||||
#define USACCUM_MAX __USACCUM_MAX__
|
||||
#define USACCUM_EPSILON __USACCUM_EPSILON__
|
||||
|
||||
#undef ACCUM_FBIT
|
||||
#undef ACCUM_IBIT
|
||||
#undef ACCUM_MIN
|
||||
#undef ACCUM_MAX
|
||||
#undef ACCUM_EPSILON
|
||||
#define ACCUM_FBIT __ACCUM_FBIT__
|
||||
#define ACCUM_IBIT __ACCUM_IBIT__
|
||||
#define ACCUM_MIN __ACCUM_MIN__
|
||||
#define ACCUM_MAX __ACCUM_MAX__
|
||||
#define ACCUM_EPSILON __ACCUM_EPSILON__
|
||||
|
||||
#undef UACCUM_FBIT
|
||||
#undef UACCUM_IBIT
|
||||
#undef UACCUM_MIN
|
||||
#undef UACCUM_MAX
|
||||
#undef UACCUM_EPSILON
|
||||
#define UACCUM_FBIT __UACCUM_FBIT__
|
||||
#define UACCUM_IBIT __UACCUM_IBIT__
|
||||
#define UACCUM_MIN __UACCUM_MIN__ /* GCC extension. */
|
||||
#define UACCUM_MAX __UACCUM_MAX__
|
||||
#define UACCUM_EPSILON __UACCUM_EPSILON__
|
||||
|
||||
#undef LACCUM_FBIT
|
||||
#undef LACCUM_IBIT
|
||||
#undef LACCUM_MIN
|
||||
#undef LACCUM_MAX
|
||||
#undef LACCUM_EPSILON
|
||||
#define LACCUM_FBIT __LACCUM_FBIT__
|
||||
#define LACCUM_IBIT __LACCUM_IBIT__
|
||||
#define LACCUM_MIN __LACCUM_MIN__
|
||||
#define LACCUM_MAX __LACCUM_MAX__
|
||||
#define LACCUM_EPSILON __LACCUM_EPSILON__
|
||||
|
||||
#undef ULACCUM_FBIT
|
||||
#undef ULACCUM_IBIT
|
||||
#undef ULACCUM_MIN
|
||||
#undef ULACCUM_MAX
|
||||
#undef ULACCUM_EPSILON
|
||||
#define ULACCUM_FBIT __ULACCUM_FBIT__
|
||||
#define ULACCUM_IBIT __ULACCUM_IBIT__
|
||||
#define ULACCUM_MIN __ULACCUM_MIN__ /* GCC extension. */
|
||||
#define ULACCUM_MAX __ULACCUM_MAX__
|
||||
#define ULACCUM_EPSILON __ULACCUM_EPSILON__
|
||||
|
||||
#undef LLACCUM_FBIT
|
||||
#undef LLACCUM_IBIT
|
||||
#undef LLACCUM_MIN
|
||||
#undef LLACCUM_MAX
|
||||
#undef LLACCUM_EPSILON
|
||||
#define LLACCUM_FBIT __LLACCUM_FBIT__ /* GCC extension. */
|
||||
#define LLACCUM_IBIT __LLACCUM_IBIT__ /* GCC extension. */
|
||||
#define LLACCUM_MIN __LLACCUM_MIN__ /* GCC extension. */
|
||||
#define LLACCUM_MAX __LLACCUM_MAX__ /* GCC extension. */
|
||||
#define LLACCUM_EPSILON __LLACCUM_EPSILON__ /* GCC extension. */
|
||||
|
||||
#undef ULLACCUM_FBIT
|
||||
#undef ULLACCUM_IBIT
|
||||
#undef ULLACCUM_MIN
|
||||
#undef ULLACCUM_MAX
|
||||
#undef ULLACCUM_EPSILON
|
||||
#define ULLACCUM_FBIT __ULLACCUM_FBIT__ /* GCC extension. */
|
||||
#define ULLACCUM_IBIT __ULLACCUM_IBIT__ /* GCC extension. */
|
||||
#define ULLACCUM_MIN __ULLACCUM_MIN__ /* GCC extension. */
|
||||
#define ULLACCUM_MAX __ULLACCUM_MAX__ /* GCC extension. */
|
||||
#define ULLACCUM_EPSILON __ULLACCUM_EPSILON__ /* GCC extension. */
|
||||
|
||||
#endif /* _STDFIX_H */
|
334
gcc/optabs.c
334
gcc/optabs.c
@ -358,9 +358,13 @@ optab_for_tree_code (enum tree_code code, const_tree type)
|
||||
case FLOOR_DIV_EXPR:
|
||||
case ROUND_DIV_EXPR:
|
||||
case EXACT_DIV_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? usdiv_optab : ssdiv_optab;
|
||||
return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
|
||||
|
||||
case LSHIFT_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? usashl_optab : ssashl_optab;
|
||||
return ashl_optab;
|
||||
|
||||
case RSHIFT_EXPR:
|
||||
@ -448,15 +452,23 @@ optab_for_tree_code (enum tree_code code, const_tree type)
|
||||
{
|
||||
case POINTER_PLUS_EXPR:
|
||||
case PLUS_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? usadd_optab : ssadd_optab;
|
||||
return trapv ? addv_optab : add_optab;
|
||||
|
||||
case MINUS_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? ussub_optab : sssub_optab;
|
||||
return trapv ? subv_optab : sub_optab;
|
||||
|
||||
case MULT_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? usmul_optab : ssmul_optab;
|
||||
return trapv ? smulv_optab : smul_optab;
|
||||
|
||||
case NEGATE_EXPR:
|
||||
if (TYPE_SATURATING(type))
|
||||
return TYPE_UNSIGNED(type) ? usneg_optab : ssneg_optab;
|
||||
return trapv ? negv_optab : neg_optab;
|
||||
|
||||
case ABS_EXPR:
|
||||
@ -1327,6 +1339,8 @@ shift_optab_p (optab binoptab)
|
||||
switch (binoptab->code)
|
||||
{
|
||||
case ASHIFT:
|
||||
case SS_ASHIFT:
|
||||
case US_ASHIFT:
|
||||
case ASHIFTRT:
|
||||
case LSHIFTRT:
|
||||
case ROTATE:
|
||||
@ -5442,6 +5456,57 @@ expand_fix (rtx to, rtx from, int unsignedp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate code to convert FROM or TO a fixed-point.
|
||||
If UINTP is true, either TO or FROM is an unsigned integer.
|
||||
If SATP is true, we need to saturate the result. */
|
||||
|
||||
void
|
||||
expand_fixed_convert (rtx to, rtx from, int uintp, int satp)
|
||||
{
|
||||
enum machine_mode to_mode = GET_MODE (to);
|
||||
enum machine_mode from_mode = GET_MODE (from);
|
||||
convert_optab tab;
|
||||
enum rtx_code this_code;
|
||||
enum insn_code code;
|
||||
rtx insns, value;
|
||||
rtx libfunc;
|
||||
|
||||
if (to_mode == from_mode)
|
||||
{
|
||||
emit_move_insn (to, from);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uintp)
|
||||
{
|
||||
tab = satp ? satfractuns_optab : fractuns_optab;
|
||||
this_code = satp ? UNSIGNED_SAT_FRACT : UNSIGNED_FRACT_CONVERT;
|
||||
}
|
||||
else
|
||||
{
|
||||
tab = satp ? satfract_optab : fract_optab;
|
||||
this_code = satp ? SAT_FRACT : FRACT_CONVERT;
|
||||
}
|
||||
code = tab->handlers[to_mode][from_mode].insn_code;
|
||||
if (code != CODE_FOR_nothing)
|
||||
{
|
||||
emit_unop_insn (code, to, from, this_code);
|
||||
return;
|
||||
}
|
||||
|
||||
libfunc = convert_optab_libfunc (tab, to_mode, from_mode);
|
||||
gcc_assert (libfunc);
|
||||
|
||||
start_sequence ();
|
||||
value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, to_mode,
|
||||
1, from, from_mode);
|
||||
insns = get_insns ();
|
||||
end_sequence ();
|
||||
|
||||
emit_libcall_block (insns, to, value,
|
||||
gen_rtx_fmt_e (tab->code, to_mode, from));
|
||||
}
|
||||
|
||||
/* Generate code to convert FROM to fixed point and store in TO. FROM
|
||||
must be floating point, TO must be signed. Use the conversion optab
|
||||
TAB to do the conversion. */
|
||||
@ -5625,6 +5690,41 @@ gen_fp_libfunc (optab optable, const char *opname, char suffix,
|
||||
}
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that fixed-point operation is involved. */
|
||||
|
||||
static void
|
||||
gen_fixed_libfunc (optab optable, const char *opname, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (!ALL_FIXED_POINT_MODE_P (mode))
|
||||
return;
|
||||
gen_libfunc (optable, opname, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that signed fixed-point operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (!SIGNED_FIXED_POINT_MODE_P (mode))
|
||||
return;
|
||||
gen_libfunc (optable, opname, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that unsigned fixed-point operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
|
||||
return;
|
||||
gen_libfunc (optable, opname, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that FP or INT operation is involved. */
|
||||
|
||||
static void
|
||||
@ -5657,6 +5757,75 @@ gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
|
||||
}
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that FP or INT or FIXED operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
gen_fp_libfunc (optable, name, suffix, mode);
|
||||
if (INTEGRAL_MODE_P (mode))
|
||||
gen_int_libfunc (optable, name, suffix, mode);
|
||||
if (ALL_FIXED_POINT_MODE_P (mode))
|
||||
gen_fixed_libfunc (optable, name, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
gen_fp_libfunc (optable, name, suffix, mode);
|
||||
if (INTEGRAL_MODE_P (mode))
|
||||
gen_int_libfunc (optable, name, suffix, mode);
|
||||
if (SIGNED_FIXED_POINT_MODE_P (mode))
|
||||
gen_signed_fixed_libfunc (optable, name, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that INT or FIXED operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (INTEGRAL_MODE_P (mode))
|
||||
gen_int_libfunc (optable, name, suffix, mode);
|
||||
if (ALL_FIXED_POINT_MODE_P (mode))
|
||||
gen_fixed_libfunc (optable, name, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that INT or signed FIXED operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (INTEGRAL_MODE_P (mode))
|
||||
gen_int_libfunc (optable, name, suffix, mode);
|
||||
if (SIGNED_FIXED_POINT_MODE_P (mode))
|
||||
gen_signed_fixed_libfunc (optable, name, suffix, mode);
|
||||
}
|
||||
|
||||
/* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
|
||||
involved. */
|
||||
|
||||
static void
|
||||
gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (INTEGRAL_MODE_P (mode))
|
||||
gen_int_libfunc (optable, name, suffix, mode);
|
||||
if (UNSIGNED_FIXED_POINT_MODE_P (mode))
|
||||
gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
|
||||
}
|
||||
|
||||
/* Initialize the libfunc fields of an entire group of entries of an
|
||||
inter-mode-class conversion optab. The string formation rules are
|
||||
similar to the ones for init_libfuncs, above, but instead of having
|
||||
@ -5907,6 +6076,84 @@ gen_extend_conv_libfunc (convert_optab tab,
|
||||
gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
}
|
||||
|
||||
/* Pick proper libcall for fract_optab. We need to chose if we do
|
||||
interclass or intraclass. */
|
||||
|
||||
static void
|
||||
gen_fract_conv_libfunc (convert_optab tab,
|
||||
const char *opname,
|
||||
enum machine_mode tmode,
|
||||
enum machine_mode fmode)
|
||||
{
|
||||
if (tmode == fmode)
|
||||
return;
|
||||
if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
|
||||
return;
|
||||
|
||||
if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
|
||||
gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
else
|
||||
gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
}
|
||||
|
||||
/* Pick proper libcall for fractuns_optab. */
|
||||
|
||||
static void
|
||||
gen_fractuns_conv_libfunc (convert_optab tab,
|
||||
const char *opname,
|
||||
enum machine_mode tmode,
|
||||
enum machine_mode fmode)
|
||||
{
|
||||
if (tmode == fmode)
|
||||
return;
|
||||
/* One mode must be a fixed-point mode, and the other must be an integer
|
||||
mode. */
|
||||
if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
|
||||
|| (ALL_FIXED_POINT_MODE_P (fmode)
|
||||
&& GET_MODE_CLASS (tmode) == MODE_INT)))
|
||||
return;
|
||||
|
||||
gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
}
|
||||
|
||||
/* Pick proper libcall for satfract_optab. We need to chose if we do
|
||||
interclass or intraclass. */
|
||||
|
||||
static void
|
||||
gen_satfract_conv_libfunc (convert_optab tab,
|
||||
const char *opname,
|
||||
enum machine_mode tmode,
|
||||
enum machine_mode fmode)
|
||||
{
|
||||
if (tmode == fmode)
|
||||
return;
|
||||
/* TMODE must be a fixed-point mode. */
|
||||
if (!ALL_FIXED_POINT_MODE_P (tmode))
|
||||
return;
|
||||
|
||||
if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
|
||||
gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
else
|
||||
gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
}
|
||||
|
||||
/* Pick proper libcall for satfractuns_optab. */
|
||||
|
||||
static void
|
||||
gen_satfractuns_conv_libfunc (convert_optab tab,
|
||||
const char *opname,
|
||||
enum machine_mode tmode,
|
||||
enum machine_mode fmode)
|
||||
{
|
||||
if (tmode == fmode)
|
||||
return;
|
||||
/* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
|
||||
if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
|
||||
return;
|
||||
|
||||
gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
|
||||
}
|
||||
|
||||
rtx
|
||||
init_one_libfunc (const char *name)
|
||||
{
|
||||
@ -6013,7 +6260,13 @@ init_optabs (void)
|
||||
addv_optab = init_optabv (PLUS);
|
||||
sub_optab = init_optab (MINUS);
|
||||
subv_optab = init_optabv (MINUS);
|
||||
ssadd_optab = init_optab (SS_PLUS);
|
||||
usadd_optab = init_optab (US_PLUS);
|
||||
sssub_optab = init_optab (SS_MINUS);
|
||||
ussub_optab = init_optab (US_MINUS);
|
||||
smul_optab = init_optab (MULT);
|
||||
ssmul_optab = init_optab (SS_MULT);
|
||||
usmul_optab = init_optab (US_MULT);
|
||||
smulv_optab = init_optabv (MULT);
|
||||
smul_highpart_optab = init_optab (UNKNOWN);
|
||||
umul_highpart_optab = init_optab (UNKNOWN);
|
||||
@ -6022,9 +6275,15 @@ init_optabs (void)
|
||||
usmul_widen_optab = init_optab (UNKNOWN);
|
||||
smadd_widen_optab = init_optab (UNKNOWN);
|
||||
umadd_widen_optab = init_optab (UNKNOWN);
|
||||
ssmadd_widen_optab = init_optab (UNKNOWN);
|
||||
usmadd_widen_optab = init_optab (UNKNOWN);
|
||||
smsub_widen_optab = init_optab (UNKNOWN);
|
||||
umsub_widen_optab = init_optab (UNKNOWN);
|
||||
ssmsub_widen_optab = init_optab (UNKNOWN);
|
||||
usmsub_widen_optab = init_optab (UNKNOWN);
|
||||
sdiv_optab = init_optab (DIV);
|
||||
ssdiv_optab = init_optab (SS_DIV);
|
||||
usdiv_optab = init_optab (US_DIV);
|
||||
sdivv_optab = init_optabv (DIV);
|
||||
sdivmod_optab = init_optab (UNKNOWN);
|
||||
udiv_optab = init_optab (UDIV);
|
||||
@ -6038,6 +6297,8 @@ init_optabs (void)
|
||||
ior_optab = init_optab (IOR);
|
||||
xor_optab = init_optab (XOR);
|
||||
ashl_optab = init_optab (ASHIFT);
|
||||
ssashl_optab = init_optab (SS_ASHIFT);
|
||||
usashl_optab = init_optab (US_ASHIFT);
|
||||
ashr_optab = init_optab (ASHIFTRT);
|
||||
lshr_optab = init_optab (LSHIFTRT);
|
||||
rotl_optab = init_optab (ROTATE);
|
||||
@ -6069,6 +6330,8 @@ init_optabs (void)
|
||||
unord_optab = init_optab (UNORDERED);
|
||||
|
||||
neg_optab = init_optab (NEG);
|
||||
ssneg_optab = init_optab (SS_NEG);
|
||||
usneg_optab = init_optab (US_NEG);
|
||||
negv_optab = init_optabv (NEG);
|
||||
abs_optab = init_optab (ABS);
|
||||
absv_optab = init_optabv (ABS);
|
||||
@ -6175,6 +6438,11 @@ init_optabs (void)
|
||||
lfloor_optab = init_convert_optab (UNKNOWN);
|
||||
lceil_optab = init_convert_optab (UNKNOWN);
|
||||
|
||||
fract_optab = init_convert_optab (FRACT_CONVERT);
|
||||
fractuns_optab = init_convert_optab (UNSIGNED_FRACT_CONVERT);
|
||||
satfract_optab = init_convert_optab (SAT_FRACT);
|
||||
satfractuns_optab = init_convert_optab (UNSIGNED_SAT_FRACT);
|
||||
|
||||
for (i = 0; i < NUM_MACHINE_MODES; i++)
|
||||
{
|
||||
movmem_optab[i] = CODE_FOR_nothing;
|
||||
@ -6215,31 +6483,55 @@ init_optabs (void)
|
||||
/* Initialize the optabs with the names of the library functions. */
|
||||
add_optab->libcall_basename = "add";
|
||||
add_optab->libcall_suffix = '3';
|
||||
add_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
add_optab->libcall_gen = gen_int_fp_fixed_libfunc;
|
||||
addv_optab->libcall_basename = "add";
|
||||
addv_optab->libcall_suffix = '3';
|
||||
addv_optab->libcall_gen = gen_intv_fp_libfunc;
|
||||
ssadd_optab->libcall_basename = "ssadd";
|
||||
ssadd_optab->libcall_suffix = '3';
|
||||
ssadd_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
usadd_optab->libcall_basename = "usadd";
|
||||
usadd_optab->libcall_suffix = '3';
|
||||
usadd_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
sub_optab->libcall_basename = "sub";
|
||||
sub_optab->libcall_suffix = '3';
|
||||
sub_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
sub_optab->libcall_gen = gen_int_fp_fixed_libfunc;
|
||||
subv_optab->libcall_basename = "sub";
|
||||
subv_optab->libcall_suffix = '3';
|
||||
subv_optab->libcall_gen = gen_intv_fp_libfunc;
|
||||
sssub_optab->libcall_basename = "sssub";
|
||||
sssub_optab->libcall_suffix = '3';
|
||||
sssub_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
ussub_optab->libcall_basename = "ussub";
|
||||
ussub_optab->libcall_suffix = '3';
|
||||
ussub_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
smul_optab->libcall_basename = "mul";
|
||||
smul_optab->libcall_suffix = '3';
|
||||
smul_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
smul_optab->libcall_gen = gen_int_fp_fixed_libfunc;
|
||||
smulv_optab->libcall_basename = "mul";
|
||||
smulv_optab->libcall_suffix = '3';
|
||||
smulv_optab->libcall_gen = gen_intv_fp_libfunc;
|
||||
ssmul_optab->libcall_basename = "ssmul";
|
||||
ssmul_optab->libcall_suffix = '3';
|
||||
ssmul_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
usmul_optab->libcall_basename = "usmul";
|
||||
usmul_optab->libcall_suffix = '3';
|
||||
usmul_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
sdiv_optab->libcall_basename = "div";
|
||||
sdiv_optab->libcall_suffix = '3';
|
||||
sdiv_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
sdiv_optab->libcall_gen = gen_int_fp_signed_fixed_libfunc;
|
||||
sdivv_optab->libcall_basename = "divv";
|
||||
sdivv_optab->libcall_suffix = '3';
|
||||
sdivv_optab->libcall_gen = gen_int_libfunc;
|
||||
ssdiv_optab->libcall_basename = "ssdiv";
|
||||
ssdiv_optab->libcall_suffix = '3';
|
||||
ssdiv_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
udiv_optab->libcall_basename = "udiv";
|
||||
udiv_optab->libcall_suffix = '3';
|
||||
udiv_optab->libcall_gen = gen_int_libfunc;
|
||||
udiv_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
|
||||
usdiv_optab->libcall_basename = "usdiv";
|
||||
usdiv_optab->libcall_suffix = '3';
|
||||
usdiv_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
sdivmod_optab->libcall_basename = "divmod";
|
||||
sdivmod_optab->libcall_suffix = '4';
|
||||
sdivmod_optab->libcall_gen = gen_int_libfunc;
|
||||
@ -6266,13 +6558,19 @@ init_optabs (void)
|
||||
xor_optab->libcall_gen = gen_int_libfunc;
|
||||
ashl_optab->libcall_basename = "ashl";
|
||||
ashl_optab->libcall_suffix = '3';
|
||||
ashl_optab->libcall_gen = gen_int_libfunc;
|
||||
ashl_optab->libcall_gen = gen_int_fixed_libfunc;
|
||||
ssashl_optab->libcall_basename = "ssashl";
|
||||
ssashl_optab->libcall_suffix = '3';
|
||||
ssashl_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
usashl_optab->libcall_basename = "usashl";
|
||||
usashl_optab->libcall_suffix = '3';
|
||||
usashl_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
ashr_optab->libcall_basename = "ashr";
|
||||
ashr_optab->libcall_suffix = '3';
|
||||
ashr_optab->libcall_gen = gen_int_libfunc;
|
||||
ashr_optab->libcall_gen = gen_int_signed_fixed_libfunc;
|
||||
lshr_optab->libcall_basename = "lshr";
|
||||
lshr_optab->libcall_suffix = '3';
|
||||
lshr_optab->libcall_gen = gen_int_libfunc;
|
||||
lshr_optab->libcall_gen = gen_int_unsigned_fixed_libfunc;
|
||||
smin_optab->libcall_basename = "min";
|
||||
smin_optab->libcall_suffix = '3';
|
||||
smin_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
@ -6287,7 +6585,13 @@ init_optabs (void)
|
||||
umax_optab->libcall_gen = gen_int_libfunc;
|
||||
neg_optab->libcall_basename = "neg";
|
||||
neg_optab->libcall_suffix = '2';
|
||||
neg_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
neg_optab->libcall_gen = gen_int_fp_fixed_libfunc;
|
||||
ssneg_optab->libcall_basename = "ssneg";
|
||||
ssneg_optab->libcall_suffix = '2';
|
||||
ssneg_optab->libcall_gen = gen_signed_fixed_libfunc;
|
||||
usneg_optab->libcall_basename = "usneg";
|
||||
usneg_optab->libcall_suffix = '2';
|
||||
usneg_optab->libcall_gen = gen_unsigned_fixed_libfunc;
|
||||
negv_optab->libcall_basename = "neg";
|
||||
negv_optab->libcall_suffix = '2';
|
||||
negv_optab->libcall_gen = gen_intv_fp_libfunc;
|
||||
@ -6314,7 +6618,7 @@ init_optabs (void)
|
||||
signed/unsigned. */
|
||||
cmp_optab->libcall_basename = "cmp";
|
||||
cmp_optab->libcall_suffix = '2';
|
||||
cmp_optab->libcall_gen = gen_int_fp_libfunc;
|
||||
cmp_optab->libcall_gen = gen_int_fp_fixed_libfunc;
|
||||
ucmp_optab->libcall_basename = "ucmp";
|
||||
ucmp_optab->libcall_suffix = '2';
|
||||
ucmp_optab->libcall_gen = gen_int_libfunc;
|
||||
@ -6369,6 +6673,16 @@ init_optabs (void)
|
||||
trunc_optab->libcall_basename = "trunc";
|
||||
trunc_optab->libcall_gen = gen_trunc_conv_libfunc;
|
||||
|
||||
/* Conversions for fixed-point modes and other modes. */
|
||||
fract_optab->libcall_basename = "fract";
|
||||
fract_optab->libcall_gen = gen_fract_conv_libfunc;
|
||||
satfract_optab->libcall_basename = "satfract";
|
||||
satfract_optab->libcall_gen = gen_satfract_conv_libfunc;
|
||||
fractuns_optab->libcall_basename = "fractuns";
|
||||
fractuns_optab->libcall_gen = gen_fractuns_conv_libfunc;
|
||||
satfractuns_optab->libcall_basename = "satfractuns";
|
||||
satfractuns_optab->libcall_gen = gen_satfractuns_conv_libfunc;
|
||||
|
||||
/* The ffs function operates on `int'. Fall back on it if we do not
|
||||
have a libgcc2 function for that width. */
|
||||
if (INT_TYPE_SIZE < BITS_PER_WORD)
|
||||
|
59
gcc/optabs.h
59
gcc/optabs.h
@ -75,6 +75,20 @@ typedef struct convert_optab *convert_optab;
|
||||
/* Enumeration of valid indexes into optab_table. */
|
||||
enum optab_index
|
||||
{
|
||||
/* Fixed-point operators with signed/unsigned saturation */
|
||||
OTI_ssadd,
|
||||
OTI_usadd,
|
||||
OTI_sssub,
|
||||
OTI_ussub,
|
||||
OTI_ssmul,
|
||||
OTI_usmul,
|
||||
OTI_ssdiv,
|
||||
OTI_usdiv,
|
||||
OTI_ssneg,
|
||||
OTI_usneg,
|
||||
OTI_ssashl,
|
||||
OTI_usashl,
|
||||
|
||||
OTI_add,
|
||||
OTI_addv,
|
||||
OTI_sub,
|
||||
@ -97,12 +111,28 @@ enum optab_index
|
||||
/* Unsigned multiply and add with the result and addend one machine mode
|
||||
wider than the multiplicand and multiplier. */
|
||||
OTI_umadd_widen,
|
||||
/* Signed multiply and add with the result and addend one machine mode
|
||||
wider than the multiplicand and multiplier.
|
||||
All involved operations are saturating. */
|
||||
OTI_ssmadd_widen,
|
||||
/* Unigned multiply and add with the result and addend one machine mode
|
||||
wider than the multiplicand and multiplier.
|
||||
All involved operations are saturating. */
|
||||
OTI_usmadd_widen,
|
||||
/* Signed multiply and subtract the result and minuend one machine mode
|
||||
wider than the multiplicand and multiplier. */
|
||||
OTI_smsub_widen,
|
||||
/* Unsigned multiply and subtract the result and minuend one machine mode
|
||||
wider than the multiplicand and multiplier. */
|
||||
OTI_umsub_widen,
|
||||
/* Signed multiply and subtract the result and minuend one machine mode
|
||||
wider than the multiplicand and multiplier.
|
||||
All involved operations are saturating. */
|
||||
OTI_ssmsub_widen,
|
||||
/* Unigned multiply and subtract the result and minuend one machine mode
|
||||
wider than the multiplicand and multiplier.
|
||||
All involved operations are saturating. */
|
||||
OTI_usmsub_widen,
|
||||
|
||||
/* Signed divide */
|
||||
OTI_sdiv,
|
||||
@ -332,6 +362,19 @@ enum optab_index
|
||||
|
||||
extern optab optab_table[OTI_MAX];
|
||||
|
||||
#define ssadd_optab (optab_table[OTI_ssadd])
|
||||
#define usadd_optab (optab_table[OTI_usadd])
|
||||
#define sssub_optab (optab_table[OTI_sssub])
|
||||
#define ussub_optab (optab_table[OTI_ussub])
|
||||
#define ssmul_optab (optab_table[OTI_ssmul])
|
||||
#define usmul_optab (optab_table[OTI_usmul])
|
||||
#define ssdiv_optab (optab_table[OTI_ssdiv])
|
||||
#define usdiv_optab (optab_table[OTI_usdiv])
|
||||
#define ssneg_optab (optab_table[OTI_ssneg])
|
||||
#define usneg_optab (optab_table[OTI_usneg])
|
||||
#define ssashl_optab (optab_table[OTI_ssashl])
|
||||
#define usashl_optab (optab_table[OTI_usashl])
|
||||
|
||||
#define add_optab (optab_table[OTI_add])
|
||||
#define sub_optab (optab_table[OTI_sub])
|
||||
#define smul_optab (optab_table[OTI_smul])
|
||||
@ -344,8 +387,12 @@ extern optab optab_table[OTI_MAX];
|
||||
#define usmul_widen_optab (optab_table[OTI_usmul_widen])
|
||||
#define smadd_widen_optab (optab_table[OTI_smadd_widen])
|
||||
#define umadd_widen_optab (optab_table[OTI_umadd_widen])
|
||||
#define ssmadd_widen_optab (optab_table[OTI_ssmadd_widen])
|
||||
#define usmadd_widen_optab (optab_table[OTI_usmadd_widen])
|
||||
#define smsub_widen_optab (optab_table[OTI_smsub_widen])
|
||||
#define umsub_widen_optab (optab_table[OTI_umsub_widen])
|
||||
#define ssmsub_widen_optab (optab_table[OTI_ssmsub_widen])
|
||||
#define usmsub_widen_optab (optab_table[OTI_usmsub_widen])
|
||||
#define sdiv_optab (optab_table[OTI_sdiv])
|
||||
#define smulv_optab (optab_table[OTI_smulv])
|
||||
#define sdivv_optab (optab_table[OTI_sdivv])
|
||||
@ -501,6 +548,11 @@ enum convert_optab_index
|
||||
COI_lfloor,
|
||||
COI_lceil,
|
||||
|
||||
COI_fract,
|
||||
COI_fractuns,
|
||||
COI_satfract,
|
||||
COI_satfractuns,
|
||||
|
||||
COI_MAX
|
||||
};
|
||||
|
||||
@ -519,6 +571,10 @@ extern convert_optab convert_optab_table[COI_MAX];
|
||||
#define lround_optab (convert_optab_table[COI_lround])
|
||||
#define lfloor_optab (convert_optab_table[COI_lfloor])
|
||||
#define lceil_optab (convert_optab_table[COI_lceil])
|
||||
#define fract_optab (convert_optab_table[COI_fract])
|
||||
#define fractuns_optab (convert_optab_table[COI_fractuns])
|
||||
#define satfract_optab (convert_optab_table[COI_satfract])
|
||||
#define satfractuns_optab (convert_optab_table[COI_satfractuns])
|
||||
|
||||
/* These arrays record the insn_code of insns that may be needed to
|
||||
perform input and output reloads of special objects. They provide a
|
||||
@ -693,6 +749,9 @@ extern void set_optab_libfunc (optab, enum machine_mode, const char *);
|
||||
extern void set_conv_libfunc (convert_optab, enum machine_mode,
|
||||
enum machine_mode, const char *);
|
||||
|
||||
/* Generate code for a FIXED_CONVERT_EXPR. */
|
||||
extern void expand_fixed_convert (rtx, rtx, int, int);
|
||||
|
||||
/* Generate code for a FLOAT_EXPR. */
|
||||
extern void expand_float (rtx, rtx, int);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user