Commit 655b30bf by Julian Brown Committed by Julian Brown

configure.ac (fixed-point): Add ARM support.

	gcc/
	* configure.ac (fixed-point): Add ARM support.
	* configure: Regenerate.
	* config/arm/arm.c (arm_fixed_mode_set): New struct.
	(arm_set_fixed_optab_libfunc): New.
	(arm_set_fixed_conv_libfunc): New.
	(arm_init_libfuncs): Initialise fixed-point helper libfuncs with
	ARM-specific names.
	(aapcs_libcall_value): Return sub-word-size fixed-point libcall
	return values in SImode.
	(arm_return_in_msb): Return fixed-point types in the msb.
	(arm_pad_reg_upwards, arm_pad_arg_upwards): Pad fixed-point types
	upwards.
	(arm_scalar_mode_supported_p): Support fixed-point modes.
	(arm_vector_mode_supported_p): Support vector fixed-point modes.
	* config/arm/arm.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE)
	(LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE)
	(SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE)
	(LONG_LONG_ACCUM_TYPE_SIZE, MAX_FIXED_MODE_SIZE): Define.
	* config/arm/iterators.md (FIXED, ADDSUB, UQADDSUB, QADDSUB, QMUL):
	New mode iterators.
	(qaddsub_suf): New mode attribute.
	* config/arm/arm-modes.def (FRACT, UFRACT, ACCUM, UACCUM): Declare
	vector modes.
	* config/arm/predicates.md (sat_shift_operator): New predicate.
	* config/arm/arm-fixed.md: New.
	* config/arm/arm.md: Include arm-fixed.md.
	* config/arm/t-arm (MD_INCLUDES): Add arm-fixed.md.

	libgcc/
	* config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*)
	(arm*-*-symbianelf*): Add t-fixedpoint-gnu-prefix makefile fragment.
	* config/arm/bpabi-lib.h (LIBGCC2_FIXEDBIT_GNU_PREFIX): Define.

	gcc/testsuite/
	* gcc.target/arm/fixed-point-exec.c: New test.

From-SVN: r177025
parent 3d6c3bd7
2011-08-01 Julian Brown <julian@codesourcery.com>
* configure.ac (fixed-point): Add ARM support.
* configure: Regenerate.
* config/arm/arm.c (arm_fixed_mode_set): New struct.
(arm_set_fixed_optab_libfunc): New.
(arm_set_fixed_conv_libfunc): New.
(arm_init_libfuncs): Initialise fixed-point helper libfuncs with
ARM-specific names.
(aapcs_libcall_value): Return sub-word-size fixed-point libcall
return values in SImode.
(arm_return_in_msb): Return fixed-point types in the msb.
(arm_pad_reg_upwards, arm_pad_arg_upwards): Pad fixed-point types
upwards.
(arm_scalar_mode_supported_p): Support fixed-point modes.
(arm_vector_mode_supported_p): Support vector fixed-point modes.
* config/arm/arm.h (SHORT_FRACT_TYPE_SIZE, FRACT_TYPE_SIZE)
(LONG_FRACT_TYPE_SIZE, LONG_LONG_FRACT_TYPE_SIZE)
(SHORT_ACCUM_TYPE_SIZE, ACCUM_TYPE_SIZE, LONG_ACCUM_TYPE_SIZE)
(LONG_LONG_ACCUM_TYPE_SIZE, MAX_FIXED_MODE_SIZE): Define.
* config/arm/iterators.md (FIXED, ADDSUB, UQADDSUB, QADDSUB, QMUL):
New mode iterators.
(qaddsub_suf): New mode attribute.
* config/arm/arm-modes.def (FRACT, UFRACT, ACCUM, UACCUM): Declare
vector modes.
* config/arm/predicates.md (sat_shift_operator): New predicate.
* config/arm/arm-fixed.md: New.
* config/arm/arm.md: Include arm-fixed.md.
* config/arm/t-arm (MD_INCLUDES): Add arm-fixed.md.
2011-08-01 Julian Brown <julian@codesourcery.com>
* calls.c (emit_library_call_value_1): Support padding for libcall
arguments and return values.
* config/arm/arm.c (arm_pad_arg_upward): Pad half-float values
......
......@@ -70,6 +70,12 @@ VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
/* Fraction and accumulator vector modes. */
VECTOR_MODES (FRACT, 4); /* V4QQ V2HQ */
VECTOR_MODES (UFRACT, 4); /* V4UQQ V2UHQ */
VECTOR_MODES (ACCUM, 4); /* V2HA */
VECTOR_MODES (UACCUM, 4); /* V2UHA */
/* Opaque integer modes for 3, 4, 6 or 8 Neon double registers (2 is
TImode). */
INT_MODE (EI, 24);
......
......@@ -1038,6 +1038,49 @@ bit_count (unsigned long value)
return count;
}
typedef struct
{
enum machine_mode mode;
const char *name;
} arm_fixed_mode_set;
/* A small helper for setting fixed-point library libfuncs. */
static void
arm_set_fixed_optab_libfunc (optab optable, enum machine_mode mode,
const char *funcname, const char *modename,
int num_suffix)
{
char buffer[50];
if (num_suffix == 0)
sprintf (buffer, "__gnu_%s%s", funcname, modename);
else
sprintf (buffer, "__gnu_%s%s%d", funcname, modename, num_suffix);
set_optab_libfunc (optable, mode, buffer);
}
static void
arm_set_fixed_conv_libfunc (convert_optab optable, enum machine_mode to,
enum machine_mode from, const char *funcname,
const char *toname, const char *fromname)
{
char buffer[50];
char *maybe_suffix_2 = "";
/* Follow the logic for selecting a "2" suffix in fixed-bit.h. */
if (ALL_FIXED_POINT_MODE_P (from) && ALL_FIXED_POINT_MODE_P (to)
&& UNSIGNED_FIXED_POINT_MODE_P (from) == UNSIGNED_FIXED_POINT_MODE_P (to)
&& ALL_FRACT_MODE_P (from) == ALL_FRACT_MODE_P (to))
maybe_suffix_2 = "2";
sprintf (buffer, "__gnu_%s%s%s%s", funcname, fromname, toname,
maybe_suffix_2);
set_conv_libfunc (optable, to, from, buffer);
}
/* Set up library functions unique to ARM. */
static void
......@@ -1183,6 +1226,137 @@ arm_init_libfuncs (void)
break;
}
/* Use names prefixed with __gnu_ for fixed-point helper functions. */
{
const arm_fixed_mode_set fixed_arith_modes[] =
{
{ QQmode, "qq" },
{ UQQmode, "uqq" },
{ HQmode, "hq" },
{ UHQmode, "uhq" },
{ SQmode, "sq" },
{ USQmode, "usq" },
{ DQmode, "dq" },
{ UDQmode, "udq" },
{ TQmode, "tq" },
{ UTQmode, "utq" },
{ HAmode, "ha" },
{ UHAmode, "uha" },
{ SAmode, "sa" },
{ USAmode, "usa" },
{ DAmode, "da" },
{ UDAmode, "uda" },
{ TAmode, "ta" },
{ UTAmode, "uta" }
};
const arm_fixed_mode_set fixed_conv_modes[] =
{
{ QQmode, "qq" },
{ UQQmode, "uqq" },
{ HQmode, "hq" },
{ UHQmode, "uhq" },
{ SQmode, "sq" },
{ USQmode, "usq" },
{ DQmode, "dq" },
{ UDQmode, "udq" },
{ TQmode, "tq" },
{ UTQmode, "utq" },
{ HAmode, "ha" },
{ UHAmode, "uha" },
{ SAmode, "sa" },
{ USAmode, "usa" },
{ DAmode, "da" },
{ UDAmode, "uda" },
{ TAmode, "ta" },
{ UTAmode, "uta" },
{ QImode, "qi" },
{ HImode, "hi" },
{ SImode, "si" },
{ DImode, "di" },
{ TImode, "ti" },
{ SFmode, "sf" },
{ DFmode, "df" }
};
unsigned int i, j;
for (i = 0; i < ARRAY_SIZE (fixed_arith_modes); i++)
{
arm_set_fixed_optab_libfunc (add_optab, fixed_arith_modes[i].mode,
"add", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssadd_optab, fixed_arith_modes[i].mode,
"ssadd", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usadd_optab, fixed_arith_modes[i].mode,
"usadd", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sub_optab, fixed_arith_modes[i].mode,
"sub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sssub_optab, fixed_arith_modes[i].mode,
"sssub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ussub_optab, fixed_arith_modes[i].mode,
"ussub", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (smul_optab, fixed_arith_modes[i].mode,
"mul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssmul_optab, fixed_arith_modes[i].mode,
"ssmul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usmul_optab, fixed_arith_modes[i].mode,
"usmul", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (sdiv_optab, fixed_arith_modes[i].mode,
"div", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (udiv_optab, fixed_arith_modes[i].mode,
"udiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssdiv_optab, fixed_arith_modes[i].mode,
"ssdiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usdiv_optab, fixed_arith_modes[i].mode,
"usdiv", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (neg_optab, fixed_arith_modes[i].mode,
"neg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (ssneg_optab, fixed_arith_modes[i].mode,
"ssneg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (usneg_optab, fixed_arith_modes[i].mode,
"usneg", fixed_arith_modes[i].name, 2);
arm_set_fixed_optab_libfunc (ashl_optab, fixed_arith_modes[i].mode,
"ashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ashr_optab, fixed_arith_modes[i].mode,
"ashr", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (lshr_optab, fixed_arith_modes[i].mode,
"lshr", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (ssashl_optab, fixed_arith_modes[i].mode,
"ssashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (usashl_optab, fixed_arith_modes[i].mode,
"usashl", fixed_arith_modes[i].name, 3);
arm_set_fixed_optab_libfunc (cmp_optab, fixed_arith_modes[i].mode,
"cmp", fixed_arith_modes[i].name, 2);
}
for (i = 0; i < ARRAY_SIZE (fixed_conv_modes); i++)
for (j = 0; j < ARRAY_SIZE (fixed_conv_modes); j++)
{
if (i == j
|| (!ALL_FIXED_POINT_MODE_P (fixed_conv_modes[i].mode)
&& !ALL_FIXED_POINT_MODE_P (fixed_conv_modes[j].mode)))
continue;
arm_set_fixed_conv_libfunc (fract_optab, fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "fract",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (satfract_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "satfract",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (fractuns_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "fractuns",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
arm_set_fixed_conv_libfunc (satfractuns_optab,
fixed_conv_modes[i].mode,
fixed_conv_modes[j].mode, "satfractuns",
fixed_conv_modes[i].name,
fixed_conv_modes[j].name);
}
}
if (TARGET_AAPCS_BASED)
synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
}
......@@ -4203,6 +4377,10 @@ aapcs_allocate_return_reg (enum machine_mode mode, const_tree type,
rtx
aapcs_libcall_value (enum machine_mode mode)
{
if (BYTES_BIG_ENDIAN && ALL_FIXED_POINT_MODE_P (mode)
&& GET_MODE_SIZE (mode) <= 4)
mode = SImode;
return aapcs_allocate_return_reg (mode, NULL_TREE, NULL_TREE);
}
......@@ -9252,8 +9430,9 @@ arm_return_in_msb (const_tree valtype)
{
return (TARGET_AAPCS_BASED
&& BYTES_BIG_ENDIAN
&& (AGGREGATE_TYPE_P (valtype)
|| TREE_CODE (valtype) == COMPLEX_TYPE));
&& (AGGREGATE_TYPE_P (valtype)
|| TREE_CODE (valtype) == COMPLEX_TYPE
|| FIXED_POINT_TYPE_P (valtype)));
}
/* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
......@@ -11287,7 +11466,8 @@ arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
{
if (TARGET_AAPCS_BASED
&& BYTES_BIG_ENDIAN
&& (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
&& (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE
|| FIXED_POINT_TYPE_P (type))
&& int_size_in_bytes (type) <= 4)
return true;
......@@ -19433,6 +19613,8 @@ arm_scalar_mode_supported_p (enum machine_mode mode)
{
if (mode == HFmode)
return (arm_fp16_format != ARM_FP16_FORMAT_NONE);
else if (ALL_FIXED_POINT_MODE_P (mode))
return true;
else
return default_scalar_mode_supported_p (mode);
}
......@@ -22552,6 +22734,11 @@ arm_vector_mode_supported_p (enum machine_mode mode)
|| (mode == V8QImode)))
return true;
if (TARGET_INT_SIMD && (mode == V4UQQmode || mode == V4QQmode
|| mode == V2UHQmode || mode == V2HQmode || mode == V2UHAmode
|| mode == V2HAmode))
return true;
return false;
}
......
......@@ -607,6 +607,20 @@ extern int arm_arch_thumb_hwdiv;
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#endif
/* Sized for fixed-point types. */
#define SHORT_FRACT_TYPE_SIZE 8
#define FRACT_TYPE_SIZE 16
#define LONG_FRACT_TYPE_SIZE 32
#define LONG_LONG_FRACT_TYPE_SIZE 64
#define SHORT_ACCUM_TYPE_SIZE 16
#define ACCUM_TYPE_SIZE 32
#define LONG_ACCUM_TYPE_SIZE 64
#define LONG_LONG_ACCUM_TYPE_SIZE 64
#define MAX_FIXED_MODE_SIZE 64
#ifndef SIZE_TYPE
#define SIZE_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long unsigned int")
#endif
......
......@@ -10889,3 +10889,5 @@
(include "neon.md")
;; Synchronization Primitives
(include "sync.md")
;; Fixed-point patterns
(include "arm-fixed.md")
......@@ -140,7 +140,18 @@
;; Modes with 8-bit, 16-bit and 32-bit elements.
(define_mode_iterator VU [V16QI V8HI V4SI])
;; Iterators used for fixed-point support.
(define_mode_iterator FIXED [QQ HQ SQ UQQ UHQ USQ HA SA UHA USA])
(define_mode_iterator ADDSUB [V4QQ V2HQ V2HA])
(define_mode_iterator UQADDSUB [V4UQQ V2UHQ UQQ UHQ V2UHA UHA])
(define_mode_iterator QADDSUB [V4QQ V2HQ QQ HQ V2HA HA SQ SA])
(define_mode_iterator QMUL [HQ HA])
;;----------------------------------------------------------------------------
;; Code iterators
;;----------------------------------------------------------------------------
......@@ -384,6 +395,12 @@
(QI "nonimmediate_operand")])
(define_mode_attr qhs_extenddi_cstr [(SI "r") (HI "rm") (QI "rm")])
;; Mode attributes used for fixed-point support.
(define_mode_attr qaddsub_suf [(V4UQQ "8") (V2UHQ "16") (UQQ "8") (UHQ "16")
(V2UHA "16") (UHA "16")
(V4QQ "8") (V2HQ "16") (QQ "8") (HQ "16")
(V2HA "16") (HA "16") (SQ "") (SA "")])
;;----------------------------------------------------------------------------
;; Code attributes
;;----------------------------------------------------------------------------
......
......@@ -227,6 +227,13 @@
(match_code "ashift,ashiftrt,lshiftrt,rotatert"))
(match_test "mode == GET_MODE (op)")))
;; True for shift operators which can be used with saturation instructions.
(define_special_predicate "sat_shift_operator"
(and (match_code "ashift,ashiftrt")
(match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1)) <= 32)")
(match_test "mode == GET_MODE (op)")))
;; True for MULT, to identify which variant of shift_operator is in use.
(define_special_predicate "mult_operator"
(match_code "mult"))
......
......@@ -37,7 +37,8 @@ MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
$(srcdir)/config/arm/iwmmxt.md \
$(srcdir)/config/arm/vfp.md \
$(srcdir)/config/arm/neon.md \
$(srcdir)/config/arm/thumb2.md
$(srcdir)/config/arm/thumb2.md \
$(srcdir)/config/arm/arm-fixed.md
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
......
......@@ -6965,6 +6965,10 @@ if test "${enable_fixed_point+set}" = set; then :
else
case $target in
arm*)
enable_fixed_point=yes
;;
mips*-*-*)
case $host in
mips*-sgi-irix*)
......@@ -17801,7 +17805,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 17804 "configure"
#line 17808 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......@@ -17907,7 +17911,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 17910 "configure"
#line 17914 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......
......@@ -638,6 +638,10 @@ AC_ARG_ENABLE(fixed-point,
[],
[
case $target in
arm*)
enable_fixed_point=yes
;;
mips*-*-*)
case $host in
mips*-sgi-irix*)
......
2011-08-01 Julian Brown <julian@codesourcery.com>
* gcc.target/arm/fixed-point-exec.c: New test.
2011-07-31 Uros Bizjak <ubizjak@gmail.com>
PR target/49920
......
2011-08-01 Julian Brown <julian@codesourcery.com>
* config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*)
(arm*-*-symbianelf*): Add t-fixedpoint-gnu-prefix makefile fragment.
* config/arm/bpabi-lib.h (LIBGCC2_FIXEDBIT_GNU_PREFIX): Define.
2011-08-01 Julian Brown <julian@codesourcery.com>
* Makefile.in (LIBGCC_VER_FIXEDPOINT_GNU_PREFIX): New.
(libgcc-std.ver.in): Use above.
* fixed-bit.h (LIBGCC2_FIXEDBIT_GNU_PREFIX): Define, if
......
......@@ -264,12 +264,15 @@ arm*-*-freebsd*)
arm*-*-netbsdelf*)
;;
arm*-*-linux*) # ARM GNU/Linux with ELF
tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
;;
arm*-*-uclinux*) # ARM ucLinux
tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
;;
arm*-*-ecos-elf)
;;
arm*-*-eabi* | arm*-*-symbianelf* )
tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
;;
arm*-*-rtems*)
;;
......
......@@ -78,3 +78,8 @@
#ifdef L_floatundisf
#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatundisf, ul2f)
#endif
/* For ARM bpabi, we only want to use a "__gnu_" prefix for the fixed-point
helper functions - not everything in libgcc - in the interests of
maintaining backward compatibility. */
#define LIBGCC2_FIXEDBIT_GNU_PREFIX
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment