aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/bfin
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@google.com>2009-09-23 21:57:28 +0000
committerCary Coutant <ccoutant@google.com>2009-09-23 21:57:28 +0000
commitebd9739bcfd2dc4c6409fb0b96d95894191b2c28 (patch)
tree64c4afc5e42d0dc9438e2d23f625cb3160e1e0a4 /gcc/config/bfin
parent0639e5c9f75c6391211dc74a4a47e9d83c88e8f4 (diff)
Merged revs 144680:151949 from trunk
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/dwarf4@152102 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/bfin')
-rw-r--r--gcc/config/bfin/bfin-protos.h58
-rw-r--r--gcc/config/bfin/bfin.c878
-rw-r--r--gcc/config/bfin/bfin.h157
-rw-r--r--gcc/config/bfin/bfin.md646
-rw-r--r--gcc/config/bfin/crti.s20
-rw-r--r--gcc/config/bfin/crtlibid.s20
-rw-r--r--gcc/config/bfin/crtn.s20
-rw-r--r--gcc/config/bfin/elf.h23
-rw-r--r--gcc/config/bfin/lib1funcs.asm21
-rw-r--r--gcc/config/bfin/libgcc-bfin.ver19
-rw-r--r--gcc/config/bfin/linux-unwind.h24
-rw-r--r--gcc/config/bfin/linux.h26
-rw-r--r--gcc/config/bfin/predicates.md44
-rw-r--r--gcc/config/bfin/sync.md178
-rw-r--r--gcc/config/bfin/t-bfin18
-rw-r--r--gcc/config/bfin/t-bfin-elf29
-rw-r--r--gcc/config/bfin/t-bfin-linux29
-rw-r--r--gcc/config/bfin/t-bfin-uclinux29
-rw-r--r--gcc/config/bfin/uclinux.h26
19 files changed, 1437 insertions, 828 deletions
diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h
index 3e9ae4317c3..b2d3d8c2dbd 100644
--- a/gcc/config/bfin/bfin-protos.h
+++ b/gcc/config/bfin/bfin-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for Blackfin functions used in the md file & elsewhere.
- Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,44 +22,6 @@
#ifndef GCC_BFIN_PROTOS_H
#define GCC_BFIN_PROTOS_H
-/* CPU type. */
-typedef enum bfin_cpu_type
-{
- BFIN_CPU_UNKNOWN,
- BFIN_CPU_BF512,
- BFIN_CPU_BF514,
- BFIN_CPU_BF516,
- BFIN_CPU_BF518,
- BFIN_CPU_BF522,
- BFIN_CPU_BF523,
- BFIN_CPU_BF524,
- BFIN_CPU_BF525,
- BFIN_CPU_BF526,
- BFIN_CPU_BF527,
- BFIN_CPU_BF531,
- BFIN_CPU_BF532,
- BFIN_CPU_BF533,
- BFIN_CPU_BF534,
- BFIN_CPU_BF536,
- BFIN_CPU_BF537,
- BFIN_CPU_BF538,
- BFIN_CPU_BF539,
- BFIN_CPU_BF542,
- BFIN_CPU_BF544,
- BFIN_CPU_BF547,
- BFIN_CPU_BF548,
- BFIN_CPU_BF549,
- BFIN_CPU_BF561
-} bfin_cpu_t;
-
-/* Value of -mcpu= */
-extern bfin_cpu_t bfin_cpu_type;
-
-/* Value of -msi-revision= */
-extern int bfin_si_revision;
-
-extern unsigned int bfin_workarounds;
-
/* For the anomaly 05-00-0245 */
#define WA_SPECULATIVE_LOADS 0x00000001
#define ENABLE_WA_SPECULATIVE_LOADS \
@@ -80,18 +42,27 @@ extern unsigned int bfin_workarounds;
#define ENABLE_WA_INDIRECT_CALLS \
((bfin_workarounds & WA_INDIRECT_CALLS) && !TARGET_ICPLB)
-#define WA_05000257 0x00000040
+#define WA_05000257 0x00000010
#define ENABLE_WA_05000257 \
(bfin_workarounds & WA_05000257)
-#define WA_05000283 0x00000010
+#define WA_05000283 0x00000020
#define ENABLE_WA_05000283 \
(bfin_workarounds & WA_05000283)
-#define WA_05000315 0x00000020
+#define WA_05000315 0x00000040
#define ENABLE_WA_05000315 \
(bfin_workarounds & WA_05000315)
+/* For the anomaly 05-00-0312 */
+#define WA_LOAD_LCREGS 0x00000080
+#define ENABLE_WA_LOAD_LCREGS \
+ (bfin_workarounds & WA_LOAD_LCREGS)
+
+#define WA_05000074 0x00000100
+#define ENABLE_WA_05000074 \
+ (bfin_workarounds & WA_05000074)
+
#define Mmode enum machine_mode
extern rtx function_arg (CUMULATIVE_ARGS *, Mmode, tree, int);
@@ -104,11 +75,9 @@ extern char *bfin_asm_long (void);
extern char *bfin_asm_short (void);
extern int log2constp (unsigned HOST_WIDE_INT);
-extern rtx legitimize_address (rtx, rtx, Mmode);
extern bool bfin_legitimate_constant_p (rtx);
extern int hard_regno_mode_ok (int, Mmode);
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
-extern int bfin_frame_pointer_required (void);
extern HOST_WIDE_INT bfin_initial_elimination_offset (int, int);
extern int effective_address_32bit_p (rtx, Mmode);
@@ -142,7 +111,6 @@ extern rtx bfin_gen_compare (rtx, Mmode);
extern int bfin_local_alignment (tree, int);
extern void initialize_trampoline (rtx, rtx, rtx);
-extern bool bfin_legitimate_address_p (Mmode, rtx, int);
extern rtx bfin_va_arg (tree, tree);
extern void bfin_expand_prologue (void);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index f4f9d45e321..92aaf5770c4 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -58,19 +58,16 @@
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
-struct machine_function GTY(())
+struct GTY(()) machine_function
{
/* Set if we are notified by the doloop pass that a hardware loop
was created. */
int has_hardware_loops;
+
/* Set if we create a memcpy pattern that uses loop registers. */
int has_loopreg_clobber;
};
-/* Test and compare insns in bfin.md store the information needed to
- generate branch and scc insns here. */
-rtx bfin_compare_op0, bfin_compare_op1;
-
/* RTX for condition code flag register and RETS register */
extern GTY(()) rtx bfin_cc_rtx;
extern GTY(()) rtx bfin_rets_rtx;
@@ -85,6 +82,7 @@ const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
static int arg_regs[] = FUNCTION_ARG_REGISTERS;
+static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
/* Nonzero if -mshared-library-id was given. */
static int bfin_lib_id_given;
@@ -119,188 +117,228 @@ struct bfin_cpu
struct bfin_cpu bfin_cpus[] =
{
{"bf512", BFIN_CPU_BF512, 0x0000,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf514", BFIN_CPU_BF514, 0x0000,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf516", BFIN_CPU_BF516, 0x0000,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf518", BFIN_CPU_BF518, 0x0000,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf522", BFIN_CPU_BF522, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf522", BFIN_CPU_BF522, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf522", BFIN_CPU_BF522, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf523", BFIN_CPU_BF523, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf523", BFIN_CPU_BF523, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf523", BFIN_CPU_BF523, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf524", BFIN_CPU_BF524, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf524", BFIN_CPU_BF524, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf524", BFIN_CPU_BF524, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf525", BFIN_CPU_BF525, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf525", BFIN_CPU_BF525, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf525", BFIN_CPU_BF525, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf526", BFIN_CPU_BF526, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf526", BFIN_CPU_BF526, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf526", BFIN_CPU_BF526, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf527", BFIN_CPU_BF527, 0x0002,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_05000074},
{"bf527", BFIN_CPU_BF527, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf527", BFIN_CPU_BF527, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
{"bf531", BFIN_CPU_BF531, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
{"bf531", BFIN_CPU_BF531, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
+ | WA_LOAD_LCREGS | WA_05000074},
{"bf531", BFIN_CPU_BF531, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf531", BFIN_CPU_BF531, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf532", BFIN_CPU_BF532, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
{"bf532", BFIN_CPU_BF532, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
+ | WA_LOAD_LCREGS | WA_05000074},
{"bf532", BFIN_CPU_BF532, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf532", BFIN_CPU_BF532, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf533", BFIN_CPU_BF533, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
{"bf533", BFIN_CPU_BF533, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
+ | WA_LOAD_LCREGS | WA_05000074},
{"bf533", BFIN_CPU_BF533, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf533", BFIN_CPU_BF533, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf534", BFIN_CPU_BF534, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
{"bf534", BFIN_CPU_BF534, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf534", BFIN_CPU_BF534, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf536", BFIN_CPU_BF536, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
{"bf536", BFIN_CPU_BF536, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf536", BFIN_CPU_BF536, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf537", BFIN_CPU_BF537, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
{"bf537", BFIN_CPU_BF537, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf537", BFIN_CPU_BF537, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf538", BFIN_CPU_BF538, 0x0005,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
{"bf538", BFIN_CPU_BF538, 0x0004,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
{"bf538", BFIN_CPU_BF538, 0x0003,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
{"bf538", BFIN_CPU_BF538, 0x0002,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000257 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf539", BFIN_CPU_BF539, 0x0005,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
{"bf539", BFIN_CPU_BF539, 0x0004,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
{"bf539", BFIN_CPU_BF539, 0x0003,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
{"bf539", BFIN_CPU_BF539, 0x0002,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
+
+ {"bf542m", BFIN_CPU_BF542M, 0x0003,
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf542", BFIN_CPU_BF542, 0x0002,
- WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf542", BFIN_CPU_BF542, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
{"bf542", BFIN_CPU_BF542, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
+ | WA_05000074},
+
+ {"bf544m", BFIN_CPU_BF544M, 0x0003,
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf544", BFIN_CPU_BF544, 0x0002,
- WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf544", BFIN_CPU_BF544, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
{"bf544", BFIN_CPU_BF544, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
+ | WA_05000074},
+
+ {"bf547m", BFIN_CPU_BF547M, 0x0003,
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf547", BFIN_CPU_BF547, 0x0002,
- WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf547", BFIN_CPU_BF547, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
{"bf547", BFIN_CPU_BF547, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
+ | WA_05000074},
+
+ {"bf548m", BFIN_CPU_BF548M, 0x0003,
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf548", BFIN_CPU_BF548, 0x0002,
- WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf548", BFIN_CPU_BF548, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
{"bf548", BFIN_CPU_BF548, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
+ | WA_05000074},
+
+ {"bf549m", BFIN_CPU_BF549M, 0x0003,
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf549", BFIN_CPU_BF549, 0x0002,
- WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
{"bf549", BFIN_CPU_BF549, 0x0001,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
{"bf549", BFIN_CPU_BF549, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
{"bf561", BFIN_CPU_BF561, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{"bf561", BFIN_CPU_BF561, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
+ | WA_05000074},
{NULL, 0, 0, 0}
};
-int splitting_for_sched;
+int splitting_for_sched, splitting_loops;
static void
bfin_globalize_label (FILE *stream, const char *name)
@@ -535,7 +573,14 @@ n_pregs_to_save (bool is_inthandler, bool consecutive)
static bool
must_save_fp_p (void)
{
- return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
+ return df_regs_ever_live_p (REG_FP);
+}
+
+/* Determine if we are going to save the RETS register. */
+static bool
+must_save_rets_p (void)
+{
+ return df_regs_ever_live_p (REG_RETS);
}
static bool
@@ -815,20 +860,20 @@ setup_incoming_varargs (CUMULATIVE_ARGS *cum,
Zero means the frame pointer need not be set up (and parms may
be accessed via the stack pointer) in functions that seem suitable. */
-int
+static bool
bfin_frame_pointer_required (void)
{
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
if (fkind != SUBROUTINE)
- return 1;
+ return true;
/* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
so we have to override it for non-leaf functions. */
if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
- return 1;
+ return true;
- return 0;
+ return false;
}
/* Return the number of registers pushed during the prologue. */
@@ -847,13 +892,12 @@ n_regs_saved_by_prologue (void)
int i;
if (all || stack_frame_needed_p ())
- /* We use a LINK instruction in this case. */
n += 2;
else
{
if (must_save_fp_p ())
n++;
- if (! current_function_is_leaf)
+ if (must_save_rets_p ())
n++;
}
@@ -886,6 +930,17 @@ n_regs_saved_by_prologue (void)
return n;
}
+/* Given FROM and TO register numbers, say whether this elimination is
+ allowed. Frame pointer elimination is automatically handled.
+
+ All other eliminations are valid. */
+
+static bool
+bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
+{
+ return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
+}
+
/* Return the offset between two registers, one to be eliminated, and the other
its replacement, at the start of a routine. */
@@ -1084,12 +1139,13 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
{
frame_size += arg_area_size ();
- if (all || stack_frame_needed_p ()
- || (must_save_fp_p () && ! current_function_is_leaf))
+ if (all
+ || stack_frame_needed_p ()
+ || (must_save_rets_p () && must_save_fp_p ()))
emit_link_insn (spreg, frame_size);
else
{
- if (! current_function_is_leaf)
+ if (must_save_rets_p ())
{
rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
gen_rtx_PRE_DEC (Pmode, spreg)),
@@ -1119,20 +1175,20 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
{
frame_size += arg_area_size ();
- if (all || stack_frame_needed_p ())
+ if (stack_frame_needed_p ())
emit_insn (gen_unlink ());
else
{
rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
add_to_reg (spreg, frame_size, 0, epilogue_p);
- if (must_save_fp_p ())
+ if (all || must_save_fp_p ())
{
rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
emit_move_insn (fpreg, postinc);
emit_use (fpreg);
}
- if (! current_function_is_leaf)
+ if (all || must_save_rets_p ())
{
emit_move_insn (bfin_rets_rtx, postinc);
emit_use (bfin_rets_rtx);
@@ -1186,9 +1242,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
if (lookup_attribute ("nesting", attrs))
{
- rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
- : fkind == NMI_HANDLER ? REG_RETN
- : REG_RETI));
+ rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
insn = emit_move_insn (predec, srcreg);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -1230,9 +1284,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
if (lookup_attribute ("nesting", attrs))
{
- rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
- : fkind == NMI_HANDLER ? REG_RETN
- : REG_RETI));
+ rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
emit_move_insn (srcreg, postinc);
}
@@ -1248,7 +1300,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
if (fkind == EXCPT_HANDLER)
emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
- emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
}
/* Used while emitting the prologue to generate code to load the correct value
@@ -1344,7 +1396,7 @@ bfin_expand_prologue (void)
}
expand_prologue_reg_save (spreg, all, false);
- do_link (spreg, frame_size, false);
+ do_link (spreg, frame_size, all);
if (TARGET_ID_SHARED_LIBRARY
&& !TARGET_SEP_DATA
@@ -1373,7 +1425,7 @@ bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
return;
}
- do_unlink (spreg, get_frame_size (), false, e);
+ do_unlink (spreg, get_frame_size (), all, e);
expand_epilogue_reg_restore (spreg, all, false);
@@ -1384,7 +1436,7 @@ bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
if (eh_return)
emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
- emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
}
/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
@@ -1417,22 +1469,6 @@ bfin_return_addr_rtx (int count)
return get_hard_reg_initial_val (Pmode, REG_RETS);
}
-/* Try machine-dependent ways of modifying an illegitimate address X
- to be legitimate. If we find one, return the new, valid address,
- otherwise return NULL_RTX.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE is the mode of the memory reference. */
-
-rtx
-legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return NULL_RTX;
-}
-
static rtx
bfin_delegitimize_address (rtx orig_x)
{
@@ -2183,6 +2219,8 @@ bool
bfin_longcall_p (rtx op, int call_cookie)
{
gcc_assert (GET_CODE (op) == SYMBOL_REF);
+ if (SYMBOL_REF_WEAK (op))
+ return 1;
if (call_cookie & CALL_SHORT)
return 0;
if (call_cookie & CALL_LONG)
@@ -2201,9 +2239,10 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
{
rtx use = NULL, call;
rtx callee = XEXP (fnaddr, 0);
- int nelts = 2 + !!sibcall;
+ int nelts = 3;
rtx pat;
rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
+ rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
int n;
/* In an untyped call, we can get NULL for operand 2. */
@@ -2218,28 +2257,38 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
if (TARGET_FDPIC)
{
- int caller_has_l1_text, callee_has_l1_text;
+ int caller_in_sram, callee_in_sram;
- caller_has_l1_text = callee_has_l1_text = 0;
+ /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
+ caller_in_sram = callee_in_sram = 0;
if (lookup_attribute ("l1_text",
DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
- caller_has_l1_text = 1;
+ caller_in_sram = 1;
+ else if (lookup_attribute ("l2",
+ DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
+ caller_in_sram = 2;
if (GET_CODE (callee) == SYMBOL_REF
- && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
- && lookup_attribute
- ("l1_text",
- DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
- callee_has_l1_text = 1;
+ && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
+ {
+ if (lookup_attribute
+ ("l1_text",
+ DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
+ callee_in_sram = 1;
+ else if (lookup_attribute
+ ("l2",
+ DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
+ callee_in_sram = 2;
+ }
if (GET_CODE (callee) != SYMBOL_REF
|| bfin_longcall_p (callee, INTVAL (cookie))
|| (GET_CODE (callee) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (callee)
&& TARGET_INLINE_PLT)
- || caller_has_l1_text != callee_has_l1_text
- || (caller_has_l1_text && callee_has_l1_text
+ || caller_in_sram != callee_in_sram
+ || (caller_in_sram && callee_in_sram
&& (GET_CODE (callee) != SYMBOL_REF
|| !SYMBOL_REF_LOCAL_P (callee))))
{
@@ -2280,6 +2329,8 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
if (sibcall)
XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
+ else
+ XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
call = emit_call_insn (pat);
if (use)
CALL_INSN_FUNCTION_USAGE (call) = use;
@@ -2331,20 +2382,14 @@ bfin_register_move_cost (enum machine_mode mode,
enum reg_class class1, enum reg_class class2)
{
/* These need secondary reloads, so they're more expensive. */
- if ((class1 == CCREGS && class2 != DREGS)
- || (class1 != DREGS && class2 == CCREGS))
+ if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
+ || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
return 4;
/* If optimizing for size, always prefer reg-reg over reg-memory moves. */
if (optimize_size)
return 2;
- /* There are some stalls involved when moving from a DREG to a different
- class reg, and using the value in one of the following instructions.
- Attempt to model this by slightly discouraging such moves. */
- if (class1 == DREGS && class2 != DREGS)
- return 2 * 2;
-
if (GET_MODE_CLASS (mode) == MODE_INT)
{
/* Discourage trying to use the accumulators. */
@@ -2735,7 +2780,7 @@ rtx
bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
{
enum rtx_code code1, code2;
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
+ rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
rtx tem = bfin_cc_rtx;
enum rtx_code code = GET_CODE (cmp);
@@ -2763,7 +2808,7 @@ bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
code2 = EQ;
break;
}
- emit_insn (gen_rtx_SET (BImode, tem,
+ emit_insn (gen_rtx_SET (VOIDmode, tem,
gen_rtx_fmt_ee (code1, BImode, op0, op1)));
}
@@ -2920,8 +2965,26 @@ bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
}
-bool
-bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
+/* Recognize an RTL expression that is a valid memory address for an
+ instruction. The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ Blackfin addressing modes are as follows:
+
+ [preg]
+ [preg + imm16]
+
+ B [ Preg + uimm15 ]
+ W [ Preg + uimm16m2 ]
+ [ Preg + uimm17m4 ]
+
+ [preg++]
+ [preg--]
+ [--sp]
+*/
+
+static bool
+bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
switch (GET_CODE (x)) {
case REG:
@@ -3610,7 +3673,7 @@ DEF_VEC_ALLOC_P (loop_info,heap);
/* Information about a loop we have found (or are in the process of
finding). */
-struct loop_info GTY (())
+struct GTY (()) loop_info
{
/* loop number, for dumps */
int loop_no;
@@ -3646,12 +3709,6 @@ struct loop_info GTY (())
/* The iteration register. */
rtx iter_reg;
- /* The new initialization insn. */
- rtx init;
-
- /* The new initialization instruction. */
- rtx loop_init;
-
/* The new label placed at the beginning of the loop. */
rtx start_label;
@@ -3779,7 +3836,7 @@ length_for_loop (rtx insn)
length = 4;
}
- if (INSN_P (insn))
+ if (NONDEBUG_INSN_P (insn))
length += get_attr_length (insn);
return length;
@@ -3792,10 +3849,10 @@ bfin_optimize_loop (loop_info loop)
{
basic_block bb;
loop_info inner;
- rtx insn, init_insn, last_insn, nop_insn;
+ rtx insn, last_insn;
rtx loop_init, start_label, end_label;
rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
- rtx iter_reg;
+ rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
rtx lc_reg, lt_reg, lb_reg;
rtx seq, seq_end;
int length;
@@ -3841,24 +3898,68 @@ bfin_optimize_loop (loop_info loop)
/* Get the loop iteration register. */
iter_reg = loop->iter_reg;
- if (!DPREG_P (iter_reg))
+ if (!REG_P (iter_reg))
{
if (dump_file)
- fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
+ fprintf (dump_file, ";; loop %d iteration count not in a register\n",
loop->loop_no);
goto bad_loop;
}
+ scratchreg = NULL_RTX;
+ scratch_init = iter_reg;
+ scratch_init_insn = NULL_RTX;
+ if (!PREG_P (iter_reg) && loop->incoming_src)
+ {
+ basic_block bb_in = loop->incoming_src;
+ int i;
+ for (i = REG_P0; i <= REG_P5; i++)
+ if ((df_regs_ever_live_p (i)
+ || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
+ && call_used_regs[i]))
+ && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
+ {
+ scratchreg = gen_rtx_REG (SImode, i);
+ break;
+ }
+ for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
+ insn = PREV_INSN (insn))
+ {
+ rtx set;
+ if (NOTE_P (insn) || BARRIER_P (insn))
+ continue;
+ set = single_set (insn);
+ if (set && rtx_equal_p (SET_DEST (set), iter_reg))
+ {
+ if (CONSTANT_P (SET_SRC (set)))
+ {
+ scratch_init = SET_SRC (set);
+ scratch_init_insn = insn;
+ }
+ break;
+ }
+ else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
+ break;
+ }
+ }
if (loop->incoming_src)
{
/* Make sure the predecessor is before the loop start label, as required by
the LSETUP instruction. */
length = 0;
- for (insn = BB_END (loop->incoming_src);
- insn && insn != loop->start_label;
- insn = NEXT_INSN (insn))
+ insn = BB_END (loop->incoming_src);
+ /* If we have to insert the LSETUP before a jump, count that jump in the
+ length. */
+ if (VEC_length (edge, loop->incoming) > 1
+ || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
+ {
+ gcc_assert (JUMP_P (insn));
+ insn = PREV_INSN (insn);
+ }
+
+ for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
length += length_for_loop (insn);
-
+
if (!insn)
{
if (dump_file)
@@ -3867,6 +3968,11 @@ bfin_optimize_loop (loop_info loop)
goto bad_loop;
}
+ /* Account for the pop of a scratch register where necessary. */
+ if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
+ && ENABLE_WA_LOAD_LCREGS)
+ length += 2;
+
if (length > MAX_LSETUP_DISTANCE)
{
if (dump_file)
@@ -3967,13 +4073,14 @@ bfin_optimize_loop (loop_info loop)
{
for (; last_insn != BB_HEAD (bb);
last_insn = find_prev_insn_start (last_insn))
- if (INSN_P (last_insn))
+ if (NONDEBUG_INSN_P (last_insn))
break;
if (last_insn != BB_HEAD (bb))
break;
if (single_pred_p (bb)
+ && single_pred_edge (bb)->flags & EDGE_FALLTHRU
&& single_pred (bb) != ENTRY_BLOCK_PTR)
{
bb = single_pred (bb);
@@ -3995,42 +4102,34 @@ bfin_optimize_loop (loop_info loop)
goto bad_loop;
}
- if (JUMP_P (last_insn))
+ if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
{
- loop_info inner = (loop_info) bb->aux;
- if (inner
- && inner->outer == loop
- && inner->loop_end == last_insn
- && inner->depth == 1)
- /* This jump_insn is the exact loop_end of an inner loop
- and to be optimized away. So use the inner's last_insn. */
- last_insn = inner->last_insn;
- else
+ if (dump_file)
+ fprintf (dump_file, ";; loop %d has bad last instruction\n",
+ loop->loop_no);
+ goto bad_loop;
+ }
+ /* In all other cases, try to replace a bad last insn with a nop. */
+ else if (JUMP_P (last_insn)
+ || CALL_P (last_insn)
+ || get_attr_type (last_insn) == TYPE_SYNC
+ || get_attr_type (last_insn) == TYPE_CALL
+ || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
+ || recog_memoized (last_insn) == CODE_FOR_return_internal
+ || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (last_insn)) >= 0)
+ {
+ if (loop->length + 2 > MAX_LOOP_LENGTH)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d has bad last instruction\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
goto bad_loop;
}
- }
- else if (CALL_P (last_insn)
- || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
- && get_attr_type (last_insn) == TYPE_SYNC)
- || recog_memoized (last_insn) == CODE_FOR_return_internal)
- {
if (dump_file)
- fprintf (dump_file, ";; loop %d has bad last instruction\n",
+ fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
loop->loop_no);
- goto bad_loop;
- }
- if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
- || asm_noperands (PATTERN (last_insn)) >= 0
- || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
- && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
- {
- nop_insn = emit_insn_after (gen_nop (), last_insn);
- last_insn = nop_insn;
+ last_insn = emit_insn_after (gen_forced_nop (), last_insn);
}
loop->last_insn = last_insn;
@@ -4055,46 +4154,71 @@ bfin_optimize_loop (loop_info loop)
loop->clobber_loop0 = 1;
}
- /* If iter_reg is a DREG, we need generate an instruction to load
- the loop count into LC register. */
- if (D_REGNO_P (REGNO (iter_reg)))
+ loop->end_label = end_label;
+
+ /* Create a sequence containing the loop setup. */
+ start_sequence ();
+
+ /* LSETUP only accepts P registers. If we have one, we can use it,
+ otherwise there are several ways of working around the problem.
+ If we're not affected by anomaly 312, we can load the LC register
+ from any iteration register, and use LSETUP without initialization.
+ If we've found a P scratch register that's not live here, we can
+ instead copy the iter_reg into that and use an initializing LSETUP.
+ If all else fails, push and pop P0 and use it as a scratch. */
+ if (P_REGNO_P (REGNO (iter_reg)))
{
- init_insn = gen_movsi (lc_reg, iter_reg);
+ loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
+ lb_reg, end_label,
+ lc_reg, iter_reg);
+ seq_end = emit_insn (loop_init);
+ }
+ else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
+ {
+ emit_insn (gen_movsi (lc_reg, iter_reg));
loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
lb_reg, end_label,
lc_reg);
+ seq_end = emit_insn (loop_init);
}
- else if (P_REGNO_P (REGNO (iter_reg)))
+ else if (scratchreg != NULL_RTX)
{
- init_insn = NULL_RTX;
+ emit_insn (gen_movsi (scratchreg, scratch_init));
loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
lb_reg, end_label,
- lc_reg, iter_reg);
+ lc_reg, scratchreg);
+ seq_end = emit_insn (loop_init);
+ if (scratch_init_insn != NULL_RTX)
+ delete_insn (scratch_init_insn);
}
else
- gcc_unreachable ();
-
- loop->init = init_insn;
- loop->end_label = end_label;
- loop->loop_init = loop_init;
+ {
+ rtx p0reg = gen_rtx_REG (SImode, REG_P0);
+ rtx push = gen_frame_mem (SImode,
+ gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
+ rtx pop = gen_frame_mem (SImode,
+ gen_rtx_POST_INC (SImode, stack_pointer_rtx));
+ emit_insn (gen_movsi (push, p0reg));
+ emit_insn (gen_movsi (p0reg, scratch_init));
+ loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
+ lb_reg, end_label,
+ lc_reg, p0reg);
+ emit_insn (loop_init);
+ seq_end = emit_insn (gen_movsi (p0reg, pop));
+ if (scratch_init_insn != NULL_RTX)
+ delete_insn (scratch_init_insn);
+ }
if (dump_file)
{
fprintf (dump_file, ";; replacing loop %d initializer with\n",
loop->loop_no);
- print_rtl_single (dump_file, loop->loop_init);
+ print_rtl_single (dump_file, loop_init);
fprintf (dump_file, ";; replacing loop %d terminator with\n",
loop->loop_no);
print_rtl_single (dump_file, loop->loop_end);
}
- /* Create a sequence containing the loop setup. */
- start_sequence ();
-
- if (loop->init != NULL_RTX)
- emit_insn (loop->init);
- seq_end = emit_insn (loop->loop_init);
-
/* If the loop isn't entered at the top, also create a jump to the entry
point. */
if (!loop->incoming_src && loop->head != loop->incoming_dest)
@@ -4112,7 +4236,10 @@ bfin_optimize_loop (loop_info loop)
seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
}
else
- seq_end = emit_insn (gen_jump (label));
+ {
+ emit_jump_insn (gen_jump (label));
+ seq_end = emit_barrier ();
+ }
}
seq = get_insns ();
@@ -4160,8 +4287,9 @@ bfin_optimize_loop (loop_info loop)
else
redirect_edge_succ (e, new_bb);
}
+ e = make_edge (new_bb, loop->head, 0);
}
-
+
delete_insn (loop->loop_end);
/* Insert the loop end label before the last instruction of the loop. */
emit_label_before (loop->end_label, loop->last_insn);
@@ -4179,17 +4307,17 @@ bfin_optimize_loop (loop_info loop)
{
/* If loop->iter_reg is a DREG or PREG, we can split it here
without scratch register. */
- rtx insn;
+ rtx insn, test;
emit_insn_before (gen_addsi3 (loop->iter_reg,
loop->iter_reg,
constm1_rtx),
loop->loop_end);
- emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
- loop->loop_end);
-
- insn = emit_jump_insn_before (gen_bne (loop->start_label),
+ test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
+ insn = emit_jump_insn_before (gen_cbranchsi4 (test,
+ loop->iter_reg, const0_rtx,
+ loop->start_label),
loop->loop_end);
JUMP_LABEL (insn) = loop->start_label;
@@ -4222,7 +4350,6 @@ bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
loop->outer = NULL;
loop->loops = NULL;
loop->incoming = VEC_alloc (edge, gc, 2);
- loop->init = loop->loop_init = NULL_RTX;
loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
loop->end_label = NULL_RTX;
loop->bad = 0;
@@ -4596,7 +4723,7 @@ bfin_reorg_loops (FILE *dump_file)
fprintf (dump_file, ";; All loops found:\n\n");
bfin_dump_loops (loops);
}
-
+
/* Now apply the optimizations. */
for (loop = loops; loop; loop = loop->next)
bfin_optimize_loop (loop);
@@ -4614,6 +4741,17 @@ bfin_reorg_loops (FILE *dump_file)
FOR_EACH_BB (bb)
bb->aux = NULL;
+
+ splitting_loops = 1;
+ FOR_EACH_BB (bb)
+ {
+ rtx insn = BB_END (bb);
+ if (!JUMP_P (insn))
+ continue;
+
+ try_split (PATTERN (insn), insn, 1);
+ }
+ splitting_loops = 0;
}
/* Possibly generate a SEQUENCE out of three insns found in SLOT.
@@ -4697,15 +4835,27 @@ bfin_gen_bundles (void)
for (insn = BB_HEAD (bb);; insn = next)
{
int at_end;
- if (INSN_P (insn))
+ rtx delete_this = NULL_RTX;
+
+ if (NONDEBUG_INSN_P (insn))
{
- if (get_attr_type (insn) == TYPE_DSP32)
- slot[0] = insn;
- else if (slot[1] == NULL_RTX)
- slot[1] = insn;
+ enum attr_type type = get_attr_type (insn);
+
+ if (type == TYPE_STALL)
+ {
+ gcc_assert (n_filled == 0);
+ delete_this = insn;
+ }
else
- slot[2] = insn;
- n_filled++;
+ {
+ if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
+ slot[0] = insn;
+ else if (slot[1] == NULL_RTX)
+ slot[1] = insn;
+ else
+ slot[2] = insn;
+ n_filled++;
+ }
}
next = NEXT_INSN (insn);
@@ -4720,7 +4870,7 @@ bfin_gen_bundles (void)
/* BB_END can change due to emitting extra NOPs, so check here. */
at_end = insn == BB_END (bb);
- if (at_end || GET_MODE (next) == TImode)
+ if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
{
if ((n_filled < 2
|| !gen_one_bundle (slot))
@@ -4739,6 +4889,8 @@ bfin_gen_bundles (void)
n_filled = 0;
slot[0] = slot[1] = slot[2] = NULL_RTX;
}
+ if (delete_this != NULL_RTX)
+ delete_insn (delete_this);
if (at_end)
break;
}
@@ -4899,28 +5051,38 @@ type_for_anomaly (rtx insn)
return get_attr_type (insn);
}
-/* Return nonzero if INSN contains any loads that may trap. It handles
- SEQUENCEs correctly. */
-
+/* Return true iff the address found in MEM is based on the register
+ NP_REG and optionally has a positive offset. */
static bool
-trapping_loads_p (rtx insn)
+harmless_null_pointer_p (rtx mem, int np_reg)
{
- rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == SEQUENCE)
+ mem = XEXP (mem, 0);
+ if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
+ mem = XEXP (mem, 0);
+ if (REG_P (mem) && REGNO (mem) == np_reg)
+ return true;
+ if (GET_CODE (mem) == PLUS
+ && REG_P (XEXP (mem, 0)) && REGNO (XEXP (mem, 0)) == np_reg)
{
- enum attr_type t;
- t = get_attr_type (XVECEXP (pat, 0, 1));
- if (t == TYPE_MCLD
- && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
+ mem = XEXP (mem, 1);
+ if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
return true;
- t = get_attr_type (XVECEXP (pat, 0, 2));
- if (t == TYPE_MCLD
- && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
- return true;
- return false;
}
- else
- return may_trap_p (SET_SRC (single_set (insn)));
+ return false;
+}
+
+/* Return nonzero if INSN contains any loads that may trap. */
+
+static bool
+trapping_loads_p (rtx insn, int np_reg, bool after_np_branch)
+{
+ rtx pat = PATTERN (insn);
+ rtx mem = SET_SRC (single_set (insn));
+
+ if (!after_np_branch)
+ np_reg = -1;
+ return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
+ && may_trap_p (mem));
}
/* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
@@ -4929,6 +5091,8 @@ trapping_loads_p (rtx insn)
static rtx
find_load (rtx insn)
{
+ if (!NONDEBUG_INSN_P (insn))
+ return NULL_RTX;
if (get_attr_type (insn) == TYPE_MCLD)
return insn;
if (GET_MODE (insn) != SImode)
@@ -4958,6 +5122,24 @@ indirect_call_p (rtx pat)
return REG_P (pat);
}
+/* During workaround_speculation, track whether we're in the shadow of a
+ conditional branch that tests a P register for NULL. If so, we can omit
+ emitting NOPs if we see a load from that P register, since a speculative
+ access at address 0 isn't a problem, and the load is executed in all other
+ cases anyway.
+ Global for communication with note_np_check_stores through note_stores.
+ */
+int np_check_regno = -1;
+bool np_after_branch = false;
+
+/* Subroutine of workaround_speculation, called through note_stores. */
+static void
+note_np_check_stores (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED)
+{
+ if (REG_P (x) && (REGNO (x) == REG_CC || REGNO (x) == np_check_regno))
+ np_check_regno = -1;
+}
+
static void
workaround_speculation (void)
{
@@ -4979,17 +5161,38 @@ workaround_speculation (void)
next = find_next_insn_start (insn);
- if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
+ if (NOTE_P (insn) || BARRIER_P (insn))
continue;
+ if (LABEL_P (insn))
+ {
+ np_check_regno = -1;
+ continue;
+ }
+
pat = PATTERN (insn);
if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
- || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
- || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
+ || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
continue;
+
+ if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
+ {
+ np_check_regno = -1;
+ continue;
+ }
if (JUMP_P (insn))
{
+ /* Is this a condjump based on a null pointer comparison we saw
+ earlier? */
+ if (np_check_regno != -1
+ && recog_memoized (insn) == CODE_FOR_cbranchbi4)
+ {
+ rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
+ gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
+ if (GET_CODE (op) == NE)
+ np_after_branch = true;
+ }
if (any_condjump_p (insn)
&& ! cbranch_predicted_taken_p (insn))
{
@@ -5002,6 +5205,7 @@ workaround_speculation (void)
}
else if (CALL_P (insn))
{
+ np_check_regno = -1;
if (cycles_since_jump < INT_MAX)
cycles_since_jump++;
if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
@@ -5009,7 +5213,7 @@ workaround_speculation (void)
delay_needed = 3;
}
}
- else if (INSN_P (insn))
+ else if (NONDEBUG_INSN_P (insn))
{
rtx load_insn = find_load (insn);
enum attr_type type = type_for_anomaly (insn);
@@ -5017,13 +5221,44 @@ workaround_speculation (void)
if (cycles_since_jump < INT_MAX)
cycles_since_jump++;
+ /* Detect a comparison of a P register with zero. If we later
+ see a condjump based on it, we have found a null pointer
+ check. */
+ if (recog_memoized (insn) == CODE_FOR_compare_eq)
+ {
+ rtx src = SET_SRC (PATTERN (insn));
+ if (REG_P (XEXP (src, 0))
+ && P_REGNO_P (REGNO (XEXP (src, 0)))
+ && XEXP (src, 1) == const0_rtx)
+ {
+ np_check_regno = REGNO (XEXP (src, 0));
+ np_after_branch = false;
+ }
+ else
+ np_check_regno = -1;
+ }
+
if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
{
- if (trapping_loads_p (load_insn))
+ if (trapping_loads_p (load_insn, np_check_regno,
+ np_after_branch))
delay_needed = 4;
}
else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
delay_needed = 3;
+
+ /* See if we need to forget about a null pointer comparison
+ we found earlier. */
+ if (recog_memoized (insn) != CODE_FOR_compare_eq)
+ {
+ note_stores (PATTERN (insn), note_np_check_stores, NULL);
+ if (np_check_regno != -1)
+ {
+ if (find_regno_note (insn, REG_INC, np_check_regno))
+ np_check_regno = -1;
+ }
+ }
+
}
if (delay_needed > cycles_since_jump
@@ -5091,7 +5326,7 @@ workaround_speculation (void)
|| GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
continue;
- if (INSN_P (target))
+ if (NONDEBUG_INSN_P (target))
{
rtx load_insn = find_load (target);
enum attr_type type = type_for_anomaly (target);
@@ -5101,7 +5336,7 @@ workaround_speculation (void)
if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
{
- if (trapping_loads_p (load_insn))
+ if (trapping_loads_p (load_insn, -1, false))
delay_needed = 2;
}
else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
@@ -5139,6 +5374,65 @@ workaround_speculation (void)
}
}
+/* Called just before the final scheduling pass. If we need to insert NOPs
+ later on to work around speculative loads, insert special placeholder
+ insns that cause loads to be delayed for as many cycles as necessary
+ (and possible). This reduces the number of NOPs we need to add.
+ The dummy insns we generate are later removed by bfin_gen_bundles. */
+static void
+add_sched_insns_for_speculation (void)
+{
+ rtx insn;
+
+ if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
+ && ! ENABLE_WA_INDIRECT_CALLS)
+ return;
+
+ /* First pass: find predicted-false branches; if something after them
+ needs nops, insert them or change the branch to predict true. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ rtx pat;
+
+ if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
+ continue;
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
+ || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
+ continue;
+
+ if (JUMP_P (insn))
+ {
+ if (any_condjump_p (insn)
+ && !cbranch_predicted_taken_p (insn))
+ {
+ rtx n = next_real_insn (insn);
+ emit_insn_before (gen_stall (GEN_INT (3)), n);
+ }
+ }
+ }
+
+ /* Second pass: for predicted-true branches, see if anything at the
+ branch destination needs extra nops. */
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ if (JUMP_P (insn)
+ && any_condjump_p (insn)
+ && (cbranch_predicted_taken_p (insn)))
+ {
+ rtx target = JUMP_LABEL (insn);
+ rtx next = next_real_insn (target);
+
+ if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
+ && get_attr_type (next) == TYPE_STALL)
+ continue;
+ emit_insn_before (gen_stall (GEN_INT (1)), next);
+ }
+ }
+}
+
/* We use the machine specific reorg pass for emitting CSYNC instructions
after conditional branches as needed.
@@ -5172,6 +5466,8 @@ bfin_reorg (void)
split_all_insns ();
splitting_for_sched = 0;
+ add_sched_insns_for_speculation ();
+
timevar_push (TV_SCHED2);
schedule_insns ();
timevar_pop (TV_SCHED2);
@@ -5217,8 +5513,8 @@ handle_int_attribute (tree *node, tree name,
if (TREE_CODE (x) != FUNCTION_TYPE)
{
- warning (OPT_Wattributes, "%qs attribute only applies to functions",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
*no_add_attrs = true;
}
else if (funkind (x) != SUBROUTINE)
@@ -5278,8 +5574,8 @@ bfin_handle_longcall_attribute (tree *node, tree name,
&& TREE_CODE (*node) != FIELD_DECL
&& TREE_CODE (*node) != TYPE_DECL)
{
- warning (OPT_Wattributes, "`%s' attribute only applies to functions",
- IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qE attribute only applies to functions",
+ name);
*no_add_attrs = true;
}
@@ -5307,8 +5603,8 @@ bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
if (TREE_CODE (decl) != FUNCTION_DECL)
{
- error ("`%s' attribute only applies to functions",
- IDENTIFIER_POINTER (name));
+ error ("%qE attribute only applies to functions",
+ name);
*no_add_attrs = true;
}
@@ -5339,15 +5635,15 @@ bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
if (TREE_CODE (decl) != VAR_DECL)
{
- error ("`%s' attribute only applies to variables",
- IDENTIFIER_POINTER (name));
+ error ("%qE attribute only applies to variables",
+ name);
*no_add_attrs = true;
}
else if (current_function_decl != NULL_TREE
&& !TREE_STATIC (decl))
{
- error ("`%s' attribute cannot be specified for local variables",
- IDENTIFIER_POINTER (name));
+ error ("%qE attribute cannot be specified for local variables",
+ name);
*no_add_attrs = true;
}
else
@@ -5381,8 +5677,47 @@ bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
return NULL_TREE;
}
+/* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
+
+static tree
+bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
+ tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+ bool *no_add_attrs)
+{
+ tree decl = *node;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (DECL_SECTION_NAME (decl) != NULL_TREE
+ && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
+ ".l2.text") != 0)
+ {
+ error ("section of %q+D conflicts with previous declaration",
+ decl);
+ *no_add_attrs = true;
+ }
+ else
+ DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ if (DECL_SECTION_NAME (decl) != NULL_TREE
+ && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
+ ".l2.data") != 0)
+ {
+ error ("section of %q+D conflicts with previous declaration",
+ decl);
+ *no_add_attrs = true;
+ }
+ else
+ DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
+ }
+
+ return NULL_TREE;
+}
+
/* Table of valid machine attributes. */
-const struct attribute_spec bfin_attribute_table[] =
+static const struct attribute_spec bfin_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
@@ -5397,6 +5732,7 @@ const struct attribute_spec bfin_attribute_table[] =
{ "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
{ "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
{ "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
+ { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -6008,6 +6344,10 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
if (! target
|| !register_operand (target, SImode))
target = gen_reg_rtx (SImode);
+ if (! register_operand (op0, SImode))
+ op0 = copy_to_mode_reg (SImode, op0);
+ if (! register_operand (op1, SImode))
+ op1 = copy_to_mode_reg (SImode, op1);
a1reg = gen_rtx_REG (PDImode, REG_A1);
a0reg = gen_rtx_REG (PDImode, REG_A0);
@@ -6061,6 +6401,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
accvec = gen_reg_rtx (V2PDImode);
+ icode = CODE_FOR_flag_macv2hi_parts;
if (! target
|| GET_MODE (target) != V2HImode
@@ -6097,6 +6438,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
accvec = gen_reg_rtx (V2PDImode);
+ icode = CODE_FOR_flag_macv2hi_parts;
if (! target
|| GET_MODE (target) != V2HImode
@@ -6161,15 +6503,14 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
- emit_insn (gen_flag_mulhi_parts (tmp2, op0, op0, const0_rtx,
+ emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
const0_rtx, const1_rtx,
GEN_INT (MACFLAG_NONE)));
- emit_insn (gen_ssaddhi3_parts (target, tmp2, tmp2, const1_rtx,
- const0_rtx, const0_rtx));
-
- emit_insn (gen_sssubhi3_parts (target, tmp1, tmp1, const0_rtx,
- const0_rtx, const1_rtx));
+ emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
+ const0_rtx));
+ emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
+ const0_rtx, const1_rtx));
return target;
@@ -6233,12 +6574,8 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
-#undef TARGET_PROMOTE_PROTOTYPES
-#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_ARGS
-#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
-#undef TARGET_PROMOTE_FUNCTION_RETURN
-#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
+#undef TARGET_PROMOTE_FUNCTION_MODE
+#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
#undef TARGET_ARG_PARTIAL_BYTES
#define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
@@ -6273,4 +6610,13 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
+
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
+
+#undef TARGET_CAN_ELIMINATE
+#define TARGET_CAN_ELIMINATE bfin_can_eliminate
+
struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index 8193ff3a747..34032b28225 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -1,5 +1,5 @@
/* Definitions for the Blackfin port.
- Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Analog Devices.
This file is part of GCC.
@@ -26,6 +26,49 @@
#define BRT 1
#define BRF 0
+/* CPU type. */
+typedef enum bfin_cpu_type
+{
+ BFIN_CPU_UNKNOWN,
+ BFIN_CPU_BF512,
+ BFIN_CPU_BF514,
+ BFIN_CPU_BF516,
+ BFIN_CPU_BF518,
+ BFIN_CPU_BF522,
+ BFIN_CPU_BF523,
+ BFIN_CPU_BF524,
+ BFIN_CPU_BF525,
+ BFIN_CPU_BF526,
+ BFIN_CPU_BF527,
+ BFIN_CPU_BF531,
+ BFIN_CPU_BF532,
+ BFIN_CPU_BF533,
+ BFIN_CPU_BF534,
+ BFIN_CPU_BF536,
+ BFIN_CPU_BF537,
+ BFIN_CPU_BF538,
+ BFIN_CPU_BF539,
+ BFIN_CPU_BF542,
+ BFIN_CPU_BF542M,
+ BFIN_CPU_BF544,
+ BFIN_CPU_BF544M,
+ BFIN_CPU_BF547,
+ BFIN_CPU_BF547M,
+ BFIN_CPU_BF548,
+ BFIN_CPU_BF548M,
+ BFIN_CPU_BF549,
+ BFIN_CPU_BF549M,
+ BFIN_CPU_BF561
+} bfin_cpu_t;
+
+/* Value of -mcpu= */
+extern bfin_cpu_t bfin_cpu_type;
+
+/* Value of -msi-revision= */
+extern int bfin_si_revision;
+
+extern unsigned int bfin_workarounds;
+
/* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION fprintf (stderr, " (BlackFin bfin)")
@@ -109,22 +152,32 @@ extern int target_flags;
case BFIN_CPU_BF539: \
builtin_define ("__ADSPBF539__"); \
break; \
+ case BFIN_CPU_BF542M: \
+ builtin_define ("__ADSPBF542M__"); \
case BFIN_CPU_BF542: \
builtin_define ("__ADSPBF542__"); \
builtin_define ("__ADSPBF54x__"); \
break; \
+ case BFIN_CPU_BF544M: \
+ builtin_define ("__ADSPBF544M__"); \
case BFIN_CPU_BF544: \
builtin_define ("__ADSPBF544__"); \
builtin_define ("__ADSPBF54x__"); \
break; \
- case BFIN_CPU_BF548: \
- builtin_define ("__ADSPBF548__"); \
- builtin_define ("__ADSPBF54x__"); \
- break; \
+ case BFIN_CPU_BF547M: \
+ builtin_define ("__ADSPBF547M__"); \
case BFIN_CPU_BF547: \
builtin_define ("__ADSPBF547__"); \
builtin_define ("__ADSPBF54x__"); \
break; \
+ case BFIN_CPU_BF548M: \
+ builtin_define ("__ADSPBF548M__"); \
+ case BFIN_CPU_BF548: \
+ builtin_define ("__ADSPBF548__"); \
+ builtin_define ("__ADSPBF54x__"); \
+ break; \
+ case BFIN_CPU_BF549M: \
+ builtin_define ("__ADSPBF549M__"); \
case BFIN_CPU_BF549: \
builtin_define ("__ADSPBF549__"); \
builtin_define ("__ADSPBF54x__"); \
@@ -313,13 +366,6 @@ extern const char *bfin_library_id_string;
found in the variable crtl->outgoing_args_size. */
#define ACCUMULATE_OUTGOING_ARGS 1
-/* Value should be nonzero if functions must have frame pointers.
- Zero means the frame pointer need not be set up (and parms
- may be accessed via the stack pointer) in functions that seem suitable.
- This is computed in `reload', in reload1.c.
-*/
-#define FRAME_POINTER_REQUIRED (bfin_frame_pointer_required ())
-
/*#define DATA_ALIGNMENT(TYPE, BASIC-ALIGN) for arrays.. */
/* If defined, a C expression to compute the alignment for a local
@@ -383,14 +429,6 @@ extern const char *bfin_library_id_string;
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} \
-/* Given FROM and TO register numbers, say whether this elimination is
- allowed. Frame pointer elimination is automatically handled.
-
- All other eliminations are valid. */
-
-#define CAN_ELIMINATE(FROM, TO) \
- ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
-
/* Define the offset between two registers, one to be eliminated, and the other
its replacement, at the start of a routine. */
@@ -809,6 +847,7 @@ enum reg_class
typedef enum {
SUBROUTINE, INTERRUPT_HANDLER, EXCPT_HANDLER, NMI_HANDLER
} e_funkind;
+#define FUNCTION_RETURN_REGISTERS { REG_RETS, REG_RETI, REG_RETX, REG_RETN }
#define FUNCTION_ARG_REGISTERS { REG_R0, REG_R1, REG_R2, -1 }
@@ -908,65 +947,13 @@ typedef struct {
/* A number, the maximum number of registers that can appear in a
valid memory address. Note that it is up to you to specify a
- value equal to the maximum number that `GO_IF_LEGITIMATE_ADDRESS'
+ value equal to the maximum number that `TARGET_LEGITIMATE_ADDRESS_P'
would ever accept. */
#define MAX_REGS_PER_ADDRESS 1
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address.
-
- Blackfin addressing modes are as follows:
-
- [preg]
- [preg + imm16]
-
- B [ Preg + uimm15 ]
- W [ Preg + uimm16m2 ]
- [ Preg + uimm17m4 ]
-
- [preg++]
- [preg--]
- [--sp]
-*/
-
#define LEGITIMATE_MODE_FOR_AUTOINC_P(MODE) \
(GET_MODE_SIZE (MODE) <= 4 || (MODE) == PDImode)
-#ifdef REG_OK_STRICT
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
- do { \
- if (bfin_legitimate_address_p (MODE, X, 1)) \
- goto WIN; \
- } while (0);
-#else
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
- do { \
- if (bfin_legitimate_address_p (MODE, X, 0)) \
- goto WIN; \
- } while (0);
-#endif
-
-/* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address.
- This macro is used in only one place: `memory_address' in explow.c.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE and WIN are passed so that this macro can use
- GO_IF_LEGITIMATE_ADDRESS.
-
- It is always safe for this macro to do nothing. It exists to recognize
- opportunities to optimize the output.
- */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-do { \
- rtx _q = legitimize_address(X, OLDX, MODE); \
- if (_q) { X = _q; goto WIN; } \
-} while (0)
-
#define HAVE_POST_INCREMENT 1
#define HAVE_POST_DECREMENT 1
#define HAVE_PRE_DECREMENT 1
@@ -986,23 +973,6 @@ do { \
|| GET_CODE (X) == LABEL_REF \
|| (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
-/*
- A C statement or compound statement with a conditional `goto
- LABEL;' executed if memory address X (an RTX) can have different
- meanings depending on the machine mode of the memory reference it
- is used for or if the address is valid for some modes but not
- others.
-
- Autoincrement and autodecrement addresses typically have
- mode-dependent effects because the amount of the increment or
- decrement is the size of the operand being addressed. Some
- machines have other mode-dependent addresses. Many RISC machines
- have no mode-dependent addresses.
-
- You may assume that ADDR is a valid address for the machine.
-*/
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
#define NOTICE_UPDATE_CC(EXPR, INSN) 0
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
@@ -1328,7 +1298,6 @@ do { \
#define ASM_OUTPUT_REG_PUSH(FILE, REGNO) fprintf (FILE, "[SP--] = %s;\n", reg_names[REGNO])
#define ASM_OUTPUT_REG_POP(FILE, REGNO) fprintf (FILE, "%s = [SP++];\n", reg_names[REGNO])
-extern struct rtx_def *bfin_compare_op0, *bfin_compare_op1;
extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx;
/* This works for GAS and some other assemblers. */
@@ -1339,8 +1308,12 @@ extern struct rtx_def *bfin_cc_rtx, *bfin_rets_rtx;
#define SIZE_ASM_OP "\t.size\t"
-extern int splitting_for_sched;
+extern int splitting_for_sched, splitting_loops;
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) ((CHAR) == '!')
+#ifndef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 0
+#endif
+
#endif /* _BFIN_CONFIG */
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 516a2052f78..3fac01ca564 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -138,15 +138,16 @@
;; Distinguish a 32-bit version of an insn from a 16-bit version.
(UNSPEC_32BIT 11)
(UNSPEC_NOP 12)
- (UNSPEC_ONES 12)])
+ (UNSPEC_ONES 13)
+ (UNSPEC_ATOMIC 14)])
(define_constants
- [(UNSPEC_VOLATILE_EH_RETURN 0)
- (UNSPEC_VOLATILE_CSYNC 1)
+ [(UNSPEC_VOLATILE_CSYNC 1)
(UNSPEC_VOLATILE_SSYNC 2)
(UNSPEC_VOLATILE_LOAD_FUNCDESC 3)
(UNSPEC_VOLATILE_STORE_EH_HANDLER 4)
- (UNSPEC_VOLATILE_DUMMY 5)])
+ (UNSPEC_VOLATILE_DUMMY 5)
+ (UNSPEC_VOLATILE_STALL 6)])
(define_constants
[(MACFLAG_NONE 0)
@@ -163,28 +164,42 @@
(MACFLAG_IH 11)])
(define_attr "type"
- "move,movcc,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy"
+ "move,movcc,mvi,mcld,mcst,dsp32,dsp32shiftimm,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy,stall"
(const_string "misc"))
-(define_attr "addrtype" "32bit,preg,ireg"
+(define_attr "addrtype" "32bit,preg,spreg,ireg"
(cond [(and (eq_attr "type" "mcld")
- (and (match_operand 0 "d_register_operand" "")
+ (and (match_operand 0 "dp_register_operand" "")
(match_operand 1 "mem_p_address_operand" "")))
(const_string "preg")
(and (eq_attr "type" "mcld")
- (and (match_operand 0 "d_register_operand" "")
+ (and (match_operand 0 "dp_register_operand" "")
+ (match_operand 1 "mem_spfp_address_operand" "")))
+ (const_string "spreg")
+ (and (eq_attr "type" "mcld")
+ (and (match_operand 0 "dp_register_operand" "")
(match_operand 1 "mem_i_address_operand" "")))
(const_string "ireg")
(and (eq_attr "type" "mcst")
- (and (match_operand 1 "d_register_operand" "")
+ (and (match_operand 1 "dp_register_operand" "")
(match_operand 0 "mem_p_address_operand" "")))
(const_string "preg")
(and (eq_attr "type" "mcst")
- (and (match_operand 1 "d_register_operand" "")
+ (and (match_operand 1 "dp_register_operand" "")
+ (match_operand 0 "mem_spfp_address_operand" "")))
+ (const_string "spreg")
+ (and (eq_attr "type" "mcst")
+ (and (match_operand 1 "dp_register_operand" "")
(match_operand 0 "mem_i_address_operand" "")))
(const_string "ireg")]
(const_string "32bit")))
+(define_attr "storereg" "preg,other"
+ (cond [(and (eq_attr "type" "mcst")
+ (match_operand 1 "p_register_operand" ""))
+ (const_string "preg")]
+ (const_string "other")))
+
;; Scheduling definitions
(define_automaton "bfin")
@@ -199,6 +214,13 @@
(define_cpu_unit "store" "bfin")
(define_cpu_unit "pregs" "bfin")
+;; A dummy unit used to delay scheduling of loads after a conditional
+;; branch.
+(define_cpu_unit "load" "bfin")
+
+;; A logical unit used to work around anomaly 05000074.
+(define_cpu_unit "anomaly_05000074" "bfin")
+
(define_reservation "core" "slot0+slot1+slot2")
(define_insn_reservation "alu" 1
@@ -213,20 +235,37 @@
(eq_attr "type" "dsp32")
"slot0")
+(define_insn_reservation "dsp32shiftimm" 1
+ (and (eq_attr "type" "dsp32shiftimm")
+ (eq (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0)))
+ "slot0")
+
+(define_insn_reservation "dsp32shiftimm_anomaly_05000074" 1
+ (and (eq_attr "type" "dsp32shiftimm")
+ (ne (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0)))
+ "slot0+anomaly_05000074")
+
(define_insn_reservation "load32" 1
(and (not (eq_attr "seq_insns" "multi"))
(and (eq_attr "type" "mcld") (eq_attr "addrtype" "32bit")))
- "core")
+ "core+load")
(define_insn_reservation "loadp" 1
(and (not (eq_attr "seq_insns" "multi"))
(and (eq_attr "type" "mcld") (eq_attr "addrtype" "preg")))
- "(slot1|slot2)+pregs")
+ "slot1+pregs+load")
+
+(define_insn_reservation "loadsp" 1
+ (and (not (eq_attr "seq_insns" "multi"))
+ (and (eq_attr "type" "mcld") (eq_attr "addrtype" "spreg")))
+ "slot1+pregs")
(define_insn_reservation "loadi" 1
(and (not (eq_attr "seq_insns" "multi"))
(and (eq_attr "type" "mcld") (eq_attr "addrtype" "ireg")))
- "(slot1|slot2)")
+ "(slot1|slot2)+load")
(define_insn_reservation "store32" 1
(and (not (eq_attr "seq_insns" "multi"))
@@ -234,19 +273,55 @@
"core")
(define_insn_reservation "storep" 1
- (and (not (eq_attr "seq_insns" "multi"))
- (and (eq_attr "type" "mcst") (eq_attr "addrtype" "preg")))
- "(slot1|slot2)+pregs+store")
+ (and (and (not (eq_attr "seq_insns" "multi"))
+ (and (eq_attr "type" "mcst")
+ (ior (eq_attr "addrtype" "preg")
+ (eq_attr "addrtype" "spreg"))))
+ (ior (eq (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0))
+ (eq_attr "storereg" "other")))
+ "slot1+pregs+store")
+
+(define_insn_reservation "storep_anomaly_05000074" 1
+ (and (and (not (eq_attr "seq_insns" "multi"))
+ (and (eq_attr "type" "mcst")
+ (ior (eq_attr "addrtype" "preg")
+ (eq_attr "addrtype" "spreg"))))
+ (and (ne (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0))
+ (eq_attr "storereg" "preg")))
+ "slot1+anomaly_05000074+pregs+store")
(define_insn_reservation "storei" 1
- (and (not (eq_attr "seq_insns" "multi"))
- (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg")))
+ (and (and (not (eq_attr "seq_insns" "multi"))
+ (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg")))
+ (ior (eq (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0))
+ (eq_attr "storereg" "other")))
"(slot1|slot2)+store")
+(define_insn_reservation "storei_anomaly_05000074" 1
+ (and (and (not (eq_attr "seq_insns" "multi"))
+ (and (eq_attr "type" "mcst") (eq_attr "addrtype" "ireg")))
+ (and (ne (symbol_ref "ENABLE_WA_05000074")
+ (const_int 0))
+ (eq_attr "storereg" "preg")))
+ "((slot1+anomaly_05000074)|slot2)+store")
+
(define_insn_reservation "multi" 2
(eq_attr "seq_insns" "multi")
"core")
+(define_insn_reservation "load_stall1" 1
+ (and (eq_attr "type" "stall")
+ (match_operand 0 "const1_operand" ""))
+ "core+load*2")
+
+(define_insn_reservation "load_stall3" 1
+ (and (eq_attr "type" "stall")
+ (match_operand 0 "const3_operand" ""))
+ "core+load*4")
+
(absence_set "slot0" "slot1,slot2")
(absence_set "slot1" "slot2")
@@ -303,6 +378,7 @@
(eq_attr "type" "move") (const_int 2)
(eq_attr "type" "dsp32") (const_int 4)
+ (eq_attr "type" "dsp32shiftimm") (const_int 4)
(eq_attr "type" "call") (const_int 4)
(eq_attr "type" "br")
@@ -532,20 +608,22 @@
;; with a PLUS. We generally require fewer secondary reloads this way.
(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x*y,da,x,x,x,da,mr")
- (match_operand:SI 1 "general_operand" "da,x*y,xKs7,xKsh,xKuh,ix,mr,da"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=da,x,da,y,da,x,x,x,da,mr")
+ (match_operand:SI 1 "general_operand" "da,x,y,da,xKs7,xKsh,xKuh,ix,mr,da"))]
"GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) == REG"
"@
%0 = %1;
%0 = %1;
+ %0 = %1;
+ %0 = %1;
%0 = %1 (X);
%0 = %1 (X);
%0 = %1 (Z);
#
%0 = %1%!
%0 = %1%!"
- [(set_attr "type" "move,move,mvi,mvi,mvi,*,mcld,mcst")
- (set_attr "length" "2,2,2,4,4,*,*,*")])
+ [(set_attr "type" "move,move,move,move,mvi,mvi,mvi,*,mcld,mcst")
+ (set_attr "length" "2,2,2,2,2,4,4,*,*,*")])
(define_insn "*movsi_insn32"
[(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -554,7 +632,7 @@
"@
%0 = ROT %1 BY 0%!
%0 = %0 -|- %0%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm,dsp32")])
(define_split
[(set (match_operand:SI 0 "d_register_operand" "")
@@ -677,7 +755,7 @@
"@
%d0 = %h1 << 0%!
%d0 = %1;"
- [(set_attr "type" "dsp32,mvi")])
+ [(set_attr "type" "dsp32shiftimm,mvi")])
(define_expand "insv"
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "")
@@ -1587,7 +1665,7 @@
[(set (match_dup 0) (ashift:SI (match_dup 1) (const_int 2)))
(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 3)))]
"operands[3] = GEN_INT (INTVAL (operands[2]) - 2);"
- [(set_attr "type" "shft,dsp32,shft,shft,*")])
+ [(set_attr "type" "shft,dsp32shiftimm,shft,shft,*")])
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
@@ -1597,7 +1675,7 @@
"@
%0 >>>= %2;
%0 = %1 >>> %2%!"
- [(set_attr "type" "shft,dsp32")])
+ [(set_attr "type" "shft,dsp32shiftimm")])
(define_insn "rotl16"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -1638,7 +1716,7 @@
(zero_extract:BI (match_dup 1) (const_int 1) (const_int 0)))]
""
"%0 = ROT %1 BY -1%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
(define_insn "rol_one"
[(set (match_operand:SI 0 "register_operand" "+d")
@@ -1648,7 +1726,7 @@
(zero_extract:BI (match_dup 1) (const_int 31) (const_int 0)))]
""
"%0 = ROT %1 BY 1%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -1723,7 +1801,7 @@
%0 >>= %2;
%0 = %1 >> %2%!
%0 = %1 >> %2;"
- [(set_attr "type" "shft,dsp32,shft")])
+ [(set_attr "type" "shft,dsp32shiftimm,shft")])
(define_insn "lshrpdi3"
[(set (match_operand:PDI 0 "register_operand" "=e")
@@ -1731,7 +1809,7 @@
(match_operand:SI 2 "nonmemory_operand" "Ku5")))]
""
"%0 = %1 >> %2%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
(define_insn "ashrpdi3"
[(set (match_operand:PDI 0 "register_operand" "=e")
@@ -1739,7 +1817,7 @@
(match_operand:SI 2 "nonmemory_operand" "Ku5")))]
""
"%0 = %1 >>> %2%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
;; A pattern to reload the equivalent of
;; (set (Dreg) (plus (FP) (large_constant)))
@@ -1763,9 +1841,11 @@
DONE;
})
-(define_insn "reload_inpdi"
- [(set (match_operand:PDI 0 "register_operand" "=e")
- (match_operand:PDI 1 "memory_operand" "m"))
+(define_mode_iterator AREG [PDI V2PDI])
+
+(define_insn "reload_in<mode>"
+ [(set (match_operand:AREG 0 "register_operand" "=e")
+ (match_operand:AREG 1 "memory_operand" "m"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
""
{
@@ -1783,9 +1863,9 @@
(set_attr "type" "mcld")
(set_attr "length" "12")])
-(define_insn "reload_outpdi"
- [(set (match_operand:PDI 0 "memory_operand" "=m")
- (match_operand:PDI 1 "register_operand" "e"))
+(define_insn "reload_out<mode>"
+ [(set (match_operand:AREG 0 "memory_operand" "=m")
+ (match_operand:AREG 1 "register_operand" "e"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
""
{
@@ -1908,7 +1988,7 @@
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
(clobber (match_scratch:SI 2 "=&r"))]
- "reload_completed"
+ "splitting_loops"
[(set (match_dup 2) (match_dup 0))
(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
(set (match_dup 0) (match_dup 2))
@@ -2004,7 +2084,8 @@
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
(match_operand 1 "general_operand" "g"))
(use (match_operand:SI 2 "register_operand" "Z"))
- (use (match_operand 3 "" ""))]
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)
&& GET_CODE (operands[0]) == SYMBOL_REF
&& !bfin_longcall_p (operands[0], INTVAL (operands[3]))"
@@ -2030,7 +2111,8 @@
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
(match_operand 2 "general_operand" "g")))
(use (match_operand:SI 3 "register_operand" "Z"))
- (use (match_operand 4 "" ""))]
+ (use (match_operand 4 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)
&& GET_CODE (operands[1]) == SYMBOL_REF
&& !bfin_longcall_p (operands[1], INTVAL (operands[4]))"
@@ -2056,7 +2138,8 @@
[(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "Y"))
(match_operand 1 "general_operand" "g"))
(use (match_operand:SI 2 "register_operand" "Z"))
- (use (match_operand 3 "" ""))]
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)"
"call (%0);"
[(set_attr "type" "call")
@@ -2078,7 +2161,8 @@
(call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "Y"))
(match_operand 2 "general_operand" "g")))
(use (match_operand:SI 3 "register_operand" "Z"))
- (use (match_operand 4 "" ""))]
+ (use (match_operand 4 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)"
"call (%1);"
[(set_attr "type" "call")
@@ -2099,7 +2183,8 @@
(define_insn "*call_symbol"
[(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "Q"))
(match_operand 1 "general_operand" "g"))
- (use (match_operand 2 "" ""))]
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)
&& (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY)
&& GET_CODE (operands[0]) == SYMBOL_REF
@@ -2125,7 +2210,8 @@
[(set (match_operand 0 "register_operand" "=d")
(call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "Q"))
(match_operand 2 "general_operand" "g")))
- (use (match_operand 3 "" ""))]
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)
&& (!TARGET_ID_SHARED_LIBRARY || TARGET_LEAF_ID_SHARED_LIBRARY)
&& GET_CODE (operands[1]) == SYMBOL_REF
@@ -2151,7 +2237,8 @@
(define_insn "*call_insn"
[(call (mem:SI (match_operand:SI 0 "register_no_elim_operand" "a"))
(match_operand 1 "general_operand" "g"))
- (use (match_operand 2 "" ""))]
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)"
"call (%0);"
[(set_attr "type" "call")
@@ -2171,7 +2258,8 @@
[(set (match_operand 0 "register_operand" "=d")
(call (mem:SI (match_operand:SI 1 "register_no_elim_operand" "a"))
(match_operand 2 "general_operand" "g")))
- (use (match_operand 3 "" ""))]
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI REG_RETS))]
"! SIBLING_CALL_P (insn)"
"call (%1);"
[(set_attr "type" "call")
@@ -2253,29 +2341,6 @@
;; Conditional branch patterns
;; The Blackfin has only few condition codes: eq, lt, lte, ltu, leu
-;; The only outcome of this pattern is that global variables
-;; bfin_compare_op[01] are set for use in bcond patterns.
-
-(define_expand "cmpbi"
- [(set (cc0) (compare (match_operand:BI 0 "register_operand" "")
- (match_operand:BI 1 "immediate_operand" "")))]
- ""
-{
- bfin_compare_op0 = operands[0];
- bfin_compare_op1 = operands[1];
- DONE;
-})
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "reg_or_const_int_operand" "")))]
- ""
-{
- bfin_compare_op0 = operands[0];
- bfin_compare_op1 = operands[1];
- DONE;
-})
-
(define_insn "compare_eq"
[(set (match_operand:BI 0 "register_operand" "=C,C")
(eq:BI (match_operand:SI 1 "register_operand" "d,a")
@@ -2324,106 +2389,6 @@
"cc =%1<%2 (iu);"
[(set_attr "type" "compare")])
-(define_expand "beq"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
- operands[1] = bfin_cc_rtx; /* hard register: CC */
- operands[2] = gen_rtx_EQ (BImode, op0, op1);
- /* If we have a BImode input, then we already have a compare result, and
- do not need to emit another comparison. */
- if (GET_MODE (bfin_compare_op0) == BImode)
- {
- gcc_assert (bfin_compare_op1 == const0_rtx);
- emit_insn (gen_cbranchbi4 (operands[2], op0, op1, operands[0]));
- DONE;
- }
-
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bne"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
- /* If we have a BImode input, then we already have a compare result, and
- do not need to emit another comparison. */
- if (GET_MODE (bfin_compare_op0) == BImode)
- {
- rtx cmp = gen_rtx_NE (BImode, op0, op1);
-
- gcc_assert (bfin_compare_op1 == const0_rtx);
- emit_insn (gen_cbranchbi4 (cmp, op0, op1, operands[0]));
- DONE;
- }
-
- operands[1] = bfin_cc_rtx; /* hard register: CC */
- operands[2] = gen_rtx_EQ (BImode, op0, op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgt"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgtu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "blt"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bltu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
;; Same as above, but and CC with the overflow bit generated by the first
;; multiplication.
(define_insn "flag_mul_macv2hi_parts_acconly_andcc0"
@@ -2488,63 +2453,25 @@
(set_attr "length" "6")
(set_attr "seq_insns" "multi")])
-(define_expand "bge"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LT (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bgeu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LTU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_EQ (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "ble"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LE (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
-})
-
-(define_expand "bleu"
- [(set (match_dup 1) (match_dup 2))
- (set (pc)
- (if_then_else (match_dup 3)
- (label_ref (match_operand 0 "" ""))
- (pc)))
- ]
+(define_expand "cbranchsi4"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "reg_or_const_int_operand" "")])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
""
{
- operands[1] = bfin_cc_rtx;
- operands[2] = gen_rtx_LEU (BImode, bfin_compare_op0, bfin_compare_op1);
- operands[3] = gen_rtx_NE (BImode, operands[1], const0_rtx);
+ rtx bi_compare = bfin_gen_compare (operands[0], SImode);
+ emit_jump_insn (gen_cbranchbi4 (bi_compare, bfin_cc_rtx, CONST0_RTX (BImode),
+ operands[3]));
+ DONE;
})
(define_insn "cbranchbi4"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2562,7 +2489,7 @@
(define_insn "cbranch_predicted_taken"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2578,7 +2505,7 @@
(define_insn "cbranch_with_nops"
[(set (pc)
(if_then_else
- (match_operator 0 "bfin_cbranch_operator"
+ (match_operator 0 "bfin_bimode_comparison_operator"
[(match_operand:BI 1 "register_operand" "C")
(match_operand:BI 2 "immediate_operand" "P0")])
(label_ref (match_operand 3 "" ""))
@@ -2592,60 +2519,49 @@
[(set_attr "type" "brcc")
(set_attr "length" "8")])
-;; setcc insns. */
-(define_expand "seq"
- [(set (match_dup 1) (eq:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+;; setcc insns.
-(define_expand "slt"
- [(set (match_dup 1) (lt:BI (match_dup 2) (match_dup 3)))
+(define_expand "cstorebi4"
+ [(set (match_dup 4)
+ (match_operator:BI 1 "bfin_bimode_comparison_operator"
+ [(match_operand:BI 2 "register_operand" "")
+ (match_operand:BI 3 "reg_or_const_int_operand" "")]))
(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
+ (ne:SI (match_dup 4) (const_int 0)))]
""
{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+ /* It could be expanded as a movbisi instruction, but the portable
+ alternative produces better code. */
+ if (GET_CODE (operands[1]) == NE)
+ FAIL;
-(define_expand "sle"
- [(set (match_dup 1) (le:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
+ operands[4] = bfin_cc_rtx;
})
-(define_expand "sltu"
- [(set (match_dup 1) (ltu:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
+(define_expand "cstoresi4"
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operator:SI 1 "ordered_comparison_operator"
+ [(match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "reg_or_const_int_operand" "")]))]
""
{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
-})
+ rtx bi_compare, test;
-(define_expand "sleu"
- [(set (match_dup 1) (leu:BI (match_dup 2) (match_dup 3)))
- (set (match_operand:SI 0 "register_operand" "")
- (ne:SI (match_dup 1) (const_int 0)))]
- ""
-{
- operands[2] = bfin_compare_op0;
- operands[3] = bfin_compare_op1;
- operands[1] = bfin_cc_rtx;
+ if (!bfin_direct_comparison_operator (operands[1], SImode))
+ {
+ if (!register_operand (operands[3], SImode)
+ || GET_CODE (operands[1]) == NE)
+ FAIL;
+ test = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
+ SImode, operands[3], operands[2]);
+ }
+ else
+ test = operands[1];
+
+ bi_compare = bfin_gen_compare (test, SImode);
+ gcc_assert (GET_CODE (bi_compare) == NE);
+ emit_insn (gen_movbisi (operands[0], bfin_cc_rtx));
+ DONE;
})
(define_insn "nop"
@@ -2674,13 +2590,16 @@
"CC = %1;"
[(set_attr "length" "2")])
-(define_insn "movbisi"
+(define_insn_and_split "movbisi"
[(set (match_operand:SI 0 "register_operand" "=d")
(ne:SI (match_operand:BI 1 "register_operand" "C")
(const_int 0)))]
""
- "%0 = CC;"
- [(set_attr "length" "2")])
+ "#"
+ ""
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:BI 1 "register_operand" "")))]
+ "")
(define_insn "notbi"
[(set (match_operand:BI 0 "register_operand" "=C")
@@ -2740,8 +2659,7 @@
"bfin_expand_epilogue (0, 0, 1); DONE;")
(define_expand "eh_return"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "")]
- UNSPEC_VOLATILE_EH_RETURN)]
+ [(use (match_operand:SI 0 "register_operand" ""))]
""
{
emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0]));
@@ -2759,11 +2677,10 @@
[(set_attr "type" "mcst")])
(define_insn_and_split "eh_return_internal"
- [(set (pc)
- (unspec_volatile [(reg:SI REG_P2)] UNSPEC_VOLATILE_EH_RETURN))]
+ [(eh_return)]
""
"#"
- "reload_completed"
+ "epilogue_completed"
[(const_int 1)]
"bfin_expand_epilogue (1, 1, 0); DONE;")
@@ -2811,23 +2728,26 @@
(define_insn "return_internal"
[(return)
- (unspec [(match_operand 0 "immediate_operand" "i")] UNSPEC_RETURN)]
+ (use (match_operand 0 "register_operand" ""))]
"reload_completed"
{
- switch (INTVAL (operands[0]))
+ switch (REGNO (operands[0]))
{
- case EXCPT_HANDLER:
+ case REG_RETX:
return "rtx;";
- case NMI_HANDLER:
+ case REG_RETN:
return "rtn;";
- case INTERRUPT_HANDLER:
+ case REG_RETI:
return "rti;";
- case SUBROUTINE:
+ case REG_RETS:
return "rts;";
}
gcc_unreachable ();
})
+;; When used at a location where CC contains 1, causes a speculative load
+;; that is later cancelled. This is used for certain workarounds in
+;; interrupt handler prologues.
(define_insn "dummy_load"
[(unspec_volatile [(match_operand 0 "register_operand" "a")
(match_operand 1 "register_operand" "C")]
@@ -2838,6 +2758,17 @@
(set_attr "length" "4")
(set_attr "seq_insns" "multi")])
+;; A placeholder insn inserted before the final scheduling pass. It is used
+;; to improve scheduling of loads when workarounds for speculative loads are
+;; needed, by not placing them in the first few cycles after a conditional
+;; branch.
+(define_insn "stall"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "P1P3")]
+ UNSPEC_VOLATILE_STALL)]
+ ""
+ ""
+ [(set_attr "type" "stall")])
+
(define_insn "csync"
[(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)]
""
@@ -2877,7 +2808,7 @@
(parallel [(const_int 1)]))))]
""
"%h0 = %h2 << 0%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
(define_insn "movhiv2hi_high"
[(set (match_operand:V2HI 0 "register_operand" "=d")
@@ -2887,7 +2818,7 @@
(match_operand:HI 2 "register_operand" "d")))]
""
"%d0 = %h2 << 0%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
;; No earlyclobber on alternative two since our sequence ought to be safe.
;; The order of operands is intentional to match the VDSP builtin (high word
@@ -2910,7 +2841,7 @@
(match_dup 2)
(vec_select:HI (match_dup 0) (parallel [(const_int 1)]))))]
""
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
; Like composev2hi, but operating on elements of V2HI vectors.
; Useful on its own, and as a combiner bridge for the multiply and
@@ -2933,7 +2864,7 @@
%0 = PACK (%h2,%d1)%!
%0 = PACK (%d2,%h1)%!
%0 = PACK (%d2,%d1)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32shiftimm,dsp32,dsp32,dsp32,dsp32")])
(define_insn "movv2hi_hi"
[(set (match_operand:HI 0 "register_operand" "=d,d,d")
@@ -2944,7 +2875,7 @@
/* optimized out */
%h0 = %h1 << 0%!
%h0 = %d1 << 0%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32shiftimm")])
(define_expand "movv2hi_hi_low"
[(set (match_operand:HI 0 "register_operand" "")
@@ -2962,74 +2893,82 @@
;; Unusual arithmetic operations on 16-bit registers.
-(define_insn "ssaddhi3"
+(define_code_iterator sp_or_sm [ss_plus ss_minus])
+(define_code_attr spm_string [(ss_plus "+") (ss_minus "-")])
+(define_code_attr spm_name [(ss_plus "add") (ss_minus "sub")])
+
+(define_insn "ss<spm_name>hi3"
[(set (match_operand:HI 0 "register_operand" "=d")
- (ss_plus:HI (match_operand:HI 1 "register_operand" "d")
+ (sp_or_sm:HI (match_operand:HI 1 "register_operand" "d")
(match_operand:HI 2 "register_operand" "d")))]
""
- "%h0 = %h1 + %h2 (S)%!"
+ "%h0 = %h1 <spm_string> %h2 (S)%!"
[(set_attr "type" "dsp32")])
-(define_insn "ssaddhi3_parts"
- [(set (vec_select:HI
- (match_operand:V2HI 0 "register_operand" "d")
- (parallel [(match_operand 3 "const01_operand" "P0P1")]))
- (ss_plus:HI (vec_select:HI
- (match_operand:V2HI 1 "register_operand" "d")
- (parallel [(match_operand 4 "const01_operand" "P0P1")]))
- (vec_select:HI
- (match_operand:V2HI 2 "register_operand" "d")
- (parallel [(match_operand 5 "const01_operand" "P0P1")]))))]
- ""
+(define_insn "ss<spm_name>hi3_parts"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (sp_or_sm:HI (vec_select:HI
+ (match_operand:V2HI 1 "register_operand" "d")
+ (parallel [(match_operand 3 "const01_operand" "P0P1")]))
+ (vec_select:HI
+ (match_operand:V2HI 2 "register_operand" "d")
+ (parallel [(match_operand 4 "const01_operand" "P0P1")]))))]
+ ""
{
const char *templates[] = {
- "%h0 = %h1 + %h2 (S)%!",
- "%d0 = %h1 + %h2 (S)%!",
- "%h0 = %d1 + %h2 (S)%!",
- "%d0 = %d1 + %h2 (S)%!",
- "%h0 = %h1 + %d2 (S)%!",
- "%d0 = %h1 + %d2 (S)%!",
- "%h0 = %d1 + %d2 (S)%!",
- "%d0 = %d1 + %d2 (S)%!" };
- int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1)
- + (INTVAL (operands[5]) << 2);
+ "%h0 = %h1 <spm_string> %h2 (S)%!",
+ "%h0 = %d1 <spm_string> %h2 (S)%!",
+ "%h0 = %h1 <spm_string> %d2 (S)%!",
+ "%h0 = %d1 <spm_string> %d2 (S)%!" };
+ int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1);
return templates[alt];
}
[(set_attr "type" "dsp32")])
-(define_insn "sssubhi3_parts"
- [(set (vec_select:HI
- (match_operand:V2HI 0 "register_operand" "d")
- (parallel [(match_operand 3 "const01_operand" "P0P1")]))
- (ss_minus:HI (vec_select:HI
- (match_operand:V2HI 1 "register_operand" "d")
- (parallel [(match_operand 4 "const01_operand" "P0P1")]))
- (vec_select:HI
- (match_operand:V2HI 2 "register_operand" "d")
- (parallel [(match_operand 5 "const01_operand" "P0P1")]))))]
- ""
+(define_insn "ss<spm_name>hi3_low_parts"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (vec_concat:V2HI
+ (vec_select:HI (match_operand:V2HI 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (sp_or_sm:HI (vec_select:HI
+ (match_operand:V2HI 2 "register_operand" "d")
+ (parallel [(match_operand 4 "const01_operand" "P0P1")]))
+ (vec_select:HI
+ (match_operand:V2HI 3 "register_operand" "d")
+ (parallel [(match_operand 5 "const01_operand" "P0P1")])))))]
+ ""
{
const char *templates[] = {
- "%h0 = %h1 - %h2 (S)%!",
- "%d0 = %h1 - %h2 (S)%!",
- "%h0 = %d1 - %h2 (S)%!",
- "%d0 = %d1 - %h2 (S)%!",
- "%h0 = %h1 - %d2 (S)%!",
- "%d0 = %h1 - %d2 (S)%!",
- "%h0 = %d1 - %d2 (S)%!",
- "%d0 = %d1 - %d2 (S)%!" };
- int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1)
- + (INTVAL (operands[5]) << 2);
+ "%h0 = %h2 <spm_string> %h3 (S)%!",
+ "%h0 = %d2 <spm_string> %h3 (S)%!",
+ "%h0 = %h2 <spm_string> %d3 (S)%!",
+ "%h0 = %d2 <spm_string> %d3 (S)%!" };
+ int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1);
return templates[alt];
}
[(set_attr "type" "dsp32")])
-(define_insn "sssubhi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (ss_minus:HI (match_operand:HI 1 "register_operand" "d")
- (match_operand:HI 2 "register_operand" "d")))]
- ""
- "%h0 = %h1 - %h2 (S)%!"
+(define_insn "ss<spm_name>hi3_high_parts"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (vec_concat:V2HI
+ (sp_or_sm:HI (vec_select:HI
+ (match_operand:V2HI 2 "register_operand" "d")
+ (parallel [(match_operand 4 "const01_operand" "P0P1")]))
+ (vec_select:HI
+ (match_operand:V2HI 3 "register_operand" "d")
+ (parallel [(match_operand 5 "const01_operand" "P0P1")])))
+ (vec_select:HI (match_operand:V2HI 1 "register_operand" "0")
+ (parallel [(const_int 1)]))))]
+ ""
+{
+ const char *templates[] = {
+ "%d0 = %h2 <spm_string> %h3 (S)%!",
+ "%d0 = %d2 <spm_string> %h3 (S)%!",
+ "%d0 = %h2 <spm_string> %d3 (S)%!",
+ "%d0 = %d2 <spm_string> %d3 (S)%!" };
+ int alt = INTVAL (operands[4]) + (INTVAL (operands[5]) << 1);
+ return templates[alt];
+}
[(set_attr "type" "dsp32")])
;; V2HI vector insns
@@ -3239,30 +3178,23 @@
[(set_attr "type" "dsp32")])
(define_insn "flag_mulhi_parts"
- [(set (vec_select:HI
- (match_operand:V2HI 0 "register_operand" "d")
- (parallel [(match_operand 3 "const01_operand" "P0P1")]))
+ [(set (match_operand:HI 0 "register_operand" "=d")
(unspec:HI [(vec_select:HI
(match_operand:V2HI 1 "register_operand" "d")
- (parallel [(match_operand 4 "const01_operand" "P0P1")]))
+ (parallel [(match_operand 3 "const01_operand" "P0P1")]))
(vec_select:HI
(match_operand:V2HI 2 "register_operand" "d")
- (parallel [(match_operand 5 "const01_operand" "P0P1")]))
- (match_operand 6 "const_int_operand" "n")]
+ (parallel [(match_operand 4 "const01_operand" "P0P1")]))
+ (match_operand 5 "const_int_operand" "n")]
UNSPEC_MUL_WITH_FLAG))]
""
{
const char *templates[] = {
- "%h0 = %h1 * %h2 %M6%!",
- "%d0 = %h1 * %h2 %M6%!",
- "%h0 = %d1 * %h2 %M6%!",
- "%d0 = %d1 * %h2 %M6%!",
- "%h0 = %h1 * %d2 %M6%!",
- "%d0 = %h1 * %d2 %M6%!",
- "%h0 = %d1 * %d2 %M6%!",
- "%d0 = %d1 * %d2 %M6%!" };
- int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1)
- + (INTVAL (operands[5]) << 2);
+ "%h0 = %h1 * %h2 %M5%!",
+ "%h0 = %d1 * %h2 %M5%!",
+ "%h0 = %h1 * %d2 %M5%!",
+ "%h0 = %d1 * %d2 %M5%!" };
+ int alt = INTVAL (operands[3]) + (INTVAL (operands[4]) << 1);
return templates[alt];
}
[(set_attr "type" "dsp32")])
@@ -4207,7 +4139,7 @@
%0 = ASHIFT %1 BY %h2 (V, S)%!
%0 = %1 << %2 (V,S)%!
%0 = %1 >>> %N2 (V,S)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")])
(define_insn "ssashifthi3"
[(set (match_operand:HI 0 "register_operand" "=d,d,d")
@@ -4221,7 +4153,7 @@
%0 = ASHIFT %1 BY %h2 (V, S)%!
%0 = %1 << %2 (V,S)%!
%0 = %1 >>> %N2 (V,S)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")])
(define_insn "ssashiftsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
@@ -4235,7 +4167,7 @@
%0 = ASHIFT %1 BY %h2 (S)%!
%0 = %1 << %2 (S)%!
%0 = %1 >>> %N2 (S)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")])
(define_insn "lshiftv2hi3"
[(set (match_operand:V2HI 0 "register_operand" "=d,d,d")
@@ -4249,7 +4181,7 @@
%0 = LSHIFT %1 BY %h2 (V)%!
%0 = %1 << %2 (V)%!
%0 = %1 >> %N2 (V)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")])
(define_insn "lshifthi3"
[(set (match_operand:HI 0 "register_operand" "=d,d,d")
@@ -4263,7 +4195,7 @@
%0 = LSHIFT %1 BY %h2 (V)%!
%0 = %1 << %2 (V)%!
%0 = %1 >> %N2 (V)%!"
- [(set_attr "type" "dsp32")])
+ [(set_attr "type" "dsp32,dsp32shiftimm,dsp32shiftimm")])
;; Load without alignment exception (masking off low bits)
@@ -4275,3 +4207,5 @@
"DISALGNEXCPT || %0 = [%1];"
[(set_attr "type" "mcld")
(set_attr "length" "8")])
+
+(include "sync.md")
diff --git a/gcc/config/bfin/crti.s b/gcc/config/bfin/crti.s
index 136516e7cbe..b6f20fc9e6b 100644
--- a/gcc/config/bfin/crti.s
+++ b/gcc/config/bfin/crti.s
@@ -1,13 +1,13 @@
/* Specialized code needed to support construction and destruction of
file-scope objects in C++ and Java code, and to support exception handling.
- Copyright (C) 2005, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
Contributed by Analog Devices.
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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
@@ -15,16 +15,14 @@ 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. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
-/* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not 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. */
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
/*
* This file just supplies function prologues for the .init and .fini
diff --git a/gcc/config/bfin/crtlibid.s b/gcc/config/bfin/crtlibid.s
index 54d5b57b694..beab8093810 100644
--- a/gcc/config/bfin/crtlibid.s
+++ b/gcc/config/bfin/crtlibid.s
@@ -1,12 +1,12 @@
/* Provide a weak definition of the library ID, for the benefit of certain
configure scripts.
- Copyright (C) 2005, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008, 2009 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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
@@ -14,16 +14,14 @@ 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. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
-/* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not 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. */
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
.ident "GNU C crtlibid.o"
diff --git a/gcc/config/bfin/crtn.s b/gcc/config/bfin/crtn.s
index 7c436252f66..7fcd27bfade 100644
--- a/gcc/config/bfin/crtn.s
+++ b/gcc/config/bfin/crtn.s
@@ -1,13 +1,13 @@
/* Specialized code needed to support construction and destruction of
file-scope objects in C++ and Java code, and to support exception handling.
- Copyright (C) 2005, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
Contributed by Analog Devices.
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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
@@ -15,16 +15,14 @@ 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. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
-/* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not 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. */
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
/*
* This file supplies function epilogues for the .init and .fini sections.
diff --git a/gcc/config/bfin/elf.h b/gcc/config/bfin/elf.h
index 9a2ec01cb89..975212faa23 100644
--- a/gcc/config/bfin/elf.h
+++ b/gcc/config/bfin/elf.h
@@ -1,3 +1,26 @@
+/* Copyright (C) 2005, 2006, 2007, 2008 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "\
%{msim:%{!shared:crt0%O%s}} \
diff --git a/gcc/config/bfin/lib1funcs.asm b/gcc/config/bfin/lib1funcs.asm
index c8d7fe855cf..4e15ad23068 100644
--- a/gcc/config/bfin/lib1funcs.asm
+++ b/gcc/config/bfin/lib1funcs.asm
@@ -1,12 +1,12 @@
/* libgcc functions for Blackfin.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009 Free Software Foundation, Inc.
Contributed by Analog Devices.
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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
@@ -14,17 +14,14 @@ 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 link this library with files
- compiled with GCC to produce an executable, this does not 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. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
#ifdef L_divsi3
.text
diff --git a/gcc/config/bfin/libgcc-bfin.ver b/gcc/config/bfin/libgcc-bfin.ver
index 1afb78e9c82..a10a0f0a6ef 100644
--- a/gcc/config/bfin/libgcc-bfin.ver
+++ b/gcc/config/bfin/libgcc-bfin.ver
@@ -1,3 +1,22 @@
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+# 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
GCC_3.0 {
# libgcc1 integer symbols
___absvsi2
diff --git a/gcc/config/bfin/linux-unwind.h b/gcc/config/bfin/linux-unwind.h
index c3697114721..88c8285632d 100644
--- a/gcc/config/bfin/linux-unwind.h
+++ b/gcc/config/bfin/linux-unwind.h
@@ -1,30 +1,26 @@
/* DWARF2 EH unwinding support for Blackfin.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009 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)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file. (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
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. */
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
/* Do code reading to identify a signal frame, and set the frame
state data appropriately. See unwind-dw2.c for the structs.
diff --git a/gcc/config/bfin/linux.h b/gcc/config/bfin/linux.h
index b786dcb6fff..5c716cd67f7 100644
--- a/gcc/config/bfin/linux.h
+++ b/gcc/config/bfin/linux.h
@@ -1,3 +1,26 @@
+/* Copyright (C) 2007, 2008 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
#undef SUBTARGET_DRIVER_SELF_SPECS
#define SUBTARGET_DRIVER_SELF_SPECS \
"%{!mno-fdpic:-mfdpic} -micplb",
@@ -26,3 +49,6 @@
%{static}} -init __init -fini __fini"
#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
+
+#undef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 1
diff --git a/gcc/config/bfin/predicates.md b/gcc/config/bfin/predicates.md
index 7aac5b0534c..84bf5919509 100644
--- a/gcc/config/bfin/predicates.md
+++ b/gcc/config/bfin/predicates.md
@@ -59,6 +59,14 @@
(and (match_code "const_int")
(match_test "op == const0_rtx || op == const1_rtx")))
+(define_predicate "const1_operand"
+ (and (match_code "const_int")
+ (match_test "op == const1_rtx")))
+
+(define_predicate "const3_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 3")))
+
(define_predicate "vec_shift_operand"
(ior (and (match_code "const_int")
(match_test "INTVAL (op) >= -16 && INTVAL (op) < 15"))
@@ -80,6 +88,14 @@
(and (match_code "reg")
(match_test "D_REGNO_P (REGNO (op))")))
+(define_predicate "p_register_operand"
+ (and (match_code "reg")
+ (match_test "P_REGNO_P (REGNO (op))")))
+
+(define_predicate "dp_register_operand"
+ (and (match_code "reg")
+ (match_test "D_REGNO_P (REGNO (op)) || P_REGNO_P (REGNO (op))")))
+
;; Return nonzero if OP is a LC register.
(define_predicate "lc_register_operand"
(and (match_code "reg")
@@ -172,14 +188,22 @@
&& REGNO (op) <= LAST_VIRTUAL_REGISTER));
})
-;; Test for an operator valid in a conditional branch
-(define_predicate "bfin_cbranch_operator"
+;; Test for an operator valid in a BImode conditional branch
+(define_predicate "bfin_bimode_comparison_operator"
(match_code "eq,ne"))
-;; The following two are used to compute the addrtype attribute. They return
+;; Test for an operator whose result is accessible with movbisi.
+(define_predicate "bfin_direct_comparison_operator"
+ (match_code "eq,lt,le,leu,ltu"))
+
+;; The following three are used to compute the addrtype attribute. They return
;; true if passed a memory address usable for a 16-bit load or store using a
;; P or I register, respectively. If neither matches, we know we have a
;; 32-bit instruction.
+;; We subdivide the P case into normal P registers, and SP/FP. We can assume
+;; that speculative loads through SP and FP are no problem, so this has
+;; an effect on the anomaly workaround code.
+
(define_predicate "mem_p_address_operand"
(match_code "mem")
{
@@ -189,7 +213,19 @@
if (GET_CODE (op) == PLUS || GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC)
op = XEXP (op, 0);
gcc_assert (REG_P (op));
- return PREG_P (op);
+ return PREG_P (op) && op != stack_pointer_rtx && op != frame_pointer_rtx;
+})
+
+(define_predicate "mem_spfp_address_operand"
+ (match_code "mem")
+{
+ if (effective_address_32bit_p (op, mode))
+ return 0;
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == PLUS || GET_RTX_CLASS (GET_CODE (op)) == RTX_AUTOINC)
+ op = XEXP (op, 0);
+ gcc_assert (REG_P (op));
+ return op == stack_pointer_rtx || op == frame_pointer_rtx;
})
(define_predicate "mem_i_address_operand"
diff --git a/gcc/config/bfin/sync.md b/gcc/config/bfin/sync.md
new file mode 100644
index 00000000000..7025af4979d
--- /dev/null
+++ b/gcc/config/bfin/sync.md
@@ -0,0 +1,178 @@
+;; GCC machine description for Blackfin synchronization instructions.
+;; Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+;; Contributed by Analog Devices.
+;;
+;; 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 3, 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 COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_code_iterator FETCHOP [plus minus ior and xor])
+(define_code_attr fetchop_name
+ [(plus "add") (minus "sub") (ior "ior") (and "and") (xor "xor")])
+(define_code_attr fetchop_addr
+ [(plus "1072") (minus "1088") (ior "1104") (and "1120") (xor "1136")])
+
+(define_insn "sync_<fetchop_name>si_internal"
+ [(set (mem:SI (match_operand:SI 0 "register_operand" "qA"))
+ (unspec:SI
+ [(FETCHOP:SI (mem:SI (match_dup 0))
+ (match_operand:SI 1 "register_operand" "q0"))
+ (match_operand:SI 2 "register_no_elim_operand" "a")]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 3 "=q0"))
+ (clobber (match_scratch:SI 4 "=q1"))
+ (clobber (reg:SI REG_RETS))]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+ "call (%2);"
+ [(set_attr "type" "call")])
+
+(define_expand "sync_<fetchop_name>si"
+ [(parallel
+ [(set (match_operand:SI 0 "memory_operand" "+m")
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 0)
+ (match_operand:SI 1 "register_operand" "q0"))
+ (match_dup 2)]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (reg:SI REG_RETS))])]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+{
+ if (!REG_P (XEXP (operands[0], 0)))
+ {
+ operands[0] = shallow_copy_rtx (operands[0]);
+ XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
+ }
+ operands[2] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_old_<fetchop_name>si_internal"
+ [(set (match_operand:SI 0 "register_operand" "=q1")
+ (mem:SI (match_operand:SI 1 "register_operand" "qA")))
+ (set (mem:SI (match_dup 1))
+ (unspec:SI
+ [(FETCHOP:SI (mem:SI (match_dup 1))
+ (match_operand:SI 2 "register_operand" "q0"))
+ (match_operand:SI 3 "register_no_elim_operand" "a")]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 4 "=q0"))
+ (clobber (reg:SI REG_RETS))]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+ "call (%3);"
+ [(set_attr "type" "call")])
+
+(define_expand "sync_old_<fetchop_name>si"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 1)
+ (match_operand:SI 2 "register_operand" ""))
+ (match_dup 3)]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (reg:SI REG_RETS))])]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+{
+ if (!REG_P (XEXP (operands[1], 0)))
+ {
+ operands[1] = shallow_copy_rtx (operands[1]);
+ XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+ }
+ operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_new_<fetchop_name>si_internal"
+ [(set (match_operand:SI 0 "register_operand" "=q0")
+ (unspec:SI
+ [(FETCHOP:SI
+ (mem:SI (match_operand:SI 1 "register_operand" "qA"))
+ (match_operand:SI 2 "register_operand" "q0"))
+ (match_operand:SI 3 "register_no_elim_operand" "a")]
+ UNSPEC_ATOMIC))
+ (set (mem:SI (match_dup 1))
+ (unspec:SI
+ [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2))
+ (match_dup 3)]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 4 "=q1"))
+ (clobber (reg:SI REG_RETS))]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+ "call (%3);"
+ [(set_attr "type" "call")])
+
+(define_expand "sync_new_<fetchop_name>si"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI
+ [(FETCHOP:SI (match_operand:SI 1 "memory_operand" "")
+ (match_operand:SI 2 "register_operand" ""))
+ (match_dup 3)]
+ UNSPEC_ATOMIC))
+ (set (match_dup 1)
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 1) (match_dup 2))
+ (match_dup 3)]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (reg:SI REG_RETS))])]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+{
+ if (!REG_P (XEXP (operands[1], 0)))
+ {
+ operands[1] = shallow_copy_rtx (operands[1]);
+ XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+ }
+ operands[3] = force_reg (Pmode, GEN_INT (<fetchop_addr>));
+})
+
+(define_insn "sync_compare_and_swapsi_internal"
+ [(set (match_operand:SI 0 "register_operand" "=q0")
+ (mem:SI (match_operand:SI 1 "register_operand" "qA")))
+ (set (mem:SI (match_dup 1))
+ (unspec:SI
+ [(mem:SI (match_dup 1))
+ (match_operand:SI 2 "register_operand" "q1")
+ (match_operand:SI 3 "register_operand" "q2")
+ (match_operand:SI 4 "register_no_elim_operand" "a")]
+ UNSPEC_ATOMIC))
+ (clobber (reg:SI REG_RETS))]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+ "call (%4);"
+ [(set_attr "type" "call")])
+
+(define_expand "sync_compare_and_swapsi"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec:SI
+ [(match_dup 1)
+ (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" "")
+ (match_dup 4)]
+ UNSPEC_ATOMIC))
+ (clobber (reg:SI REG_RETS))])]
+ "TARGET_SUPPORTS_SYNC_CALLS"
+{
+ if (!REG_P (XEXP (operands[1], 0)))
+ {
+ operands[1] = shallow_copy_rtx (operands[1]);
+ XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
+ }
+ operands[4] = force_reg (Pmode, GEN_INT (0x420));
+})
diff --git a/gcc/config/bfin/t-bfin b/gcc/config/bfin/t-bfin
index 566f3e111bd..37b6871c1dc 100644
--- a/gcc/config/bfin/t-bfin
+++ b/gcc/config/bfin/t-bfin
@@ -1,3 +1,21 @@
+# Copyright (C) 2005, 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
## Target part of the Makefile
LIB1ASMSRC = bfin/lib1funcs.asm
diff --git a/gcc/config/bfin/t-bfin-elf b/gcc/config/bfin/t-bfin-elf
index b5606e7bb75..39209f628ef 100644
--- a/gcc/config/bfin/t-bfin-elf
+++ b/gcc/config/bfin/t-bfin-elf
@@ -1,3 +1,21 @@
+# Copyright (C) 2005, 2006, 2007, 2008 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
## Target part of the Makefile
LIB1ASMSRC = bfin/lib1funcs.asm
@@ -30,8 +48,15 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-non
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none mcpu?bf532-none=mcpu?bf547-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none
MULTILIB_EXCEPTIONS=mleaf-id-shared-library*
diff --git a/gcc/config/bfin/t-bfin-linux b/gcc/config/bfin/t-bfin-linux
index c8c03d69e28..f7ba9550128 100644
--- a/gcc/config/bfin/t-bfin-linux
+++ b/gcc/config/bfin/t-bfin-linux
@@ -1,3 +1,21 @@
+# Copyright (C) 2007, 2008 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
## Target part of the Makefile
LIB1ASMSRC = bfin/lib1funcs.asm
@@ -29,8 +47,15 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-non
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none mcpu?bf532-none=mcpu?bf547-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none
SHLIB_MAPFILES=$(srcdir)/config/bfin/libgcc-bfin.ver
diff --git a/gcc/config/bfin/t-bfin-uclinux b/gcc/config/bfin/t-bfin-uclinux
index d075d6b5e65..eb6d2253eb0 100644
--- a/gcc/config/bfin/t-bfin-uclinux
+++ b/gcc/config/bfin/t-bfin-uclinux
@@ -1,3 +1,21 @@
+# Copyright (C) 2007, 2008 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
## Target part of the Makefile
LIB1ASMSRC = bfin/lib1funcs.asm
@@ -30,8 +48,15 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf531-none mcpu?bf532-none=mcpu?bf533-non
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf534-none mcpu?bf532-none=mcpu?bf536-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf537-none mcpu?bf532-none=mcpu?bf538-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf539-none mcpu?bf532-none=mcpu?bf542-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none mcpu?bf532-none=mcpu?bf547-none
-MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf542m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf544m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf547m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf548m-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549-none
+MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none
MULTILIB_EXCEPTIONS=mleaf-id-shared-library*
diff --git a/gcc/config/bfin/uclinux.h b/gcc/config/bfin/uclinux.h
index 041f2eea851..6001b23645b 100644
--- a/gcc/config/bfin/uclinux.h
+++ b/gcc/config/bfin/uclinux.h
@@ -1,3 +1,26 @@
+/* Copyright (C) 2005, 2006, 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
"%{!shared: crt1%O%s} crti%O%s crtbegin%O%s crtlibid%O%s"
@@ -13,3 +36,6 @@
--wrap=mmap --wrap=munmap --wrap=alloca\
%{fmudflapth: --wrap=pthread_create\
}} %{fmudflap|fmudflapth: --wrap=main}"
+
+#undef TARGET_SUPPORTS_SYNC_CALLS
+#define TARGET_SUPPORTS_SYNC_CALLS 1