From cf63c74394781b3136cb2a07e7910e33efb85df5 Mon Sep 17 00:00:00 2001
From: bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 20 Nov 2006 12:22:25 +0000
Subject: [PATCH] 	* config/bfin/bfin.h (LEGITIMATE_CONSTANT_P): Call 
 bfin_legitimate_constant_p. 	* config/bfin/bfin.md (movsi expander): Check
 return value of 	expand_mvoe. 	* config/bfin/bfin-protos.h
 (bfin_legitimate_constant_p): Declare. 	(expand_move): Adjust
 prototype. 	* config/bfin/bfin.c (expand_move): Now returns bool.  Handle 
 invalid constants specially. 	(bfin_cannot_force_const_mem,
 bfin_legitimate_constant_p): New 	functions. 
 (TARGET_CANNOT_FORCE_CONST_MEM): New macro.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119011 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                 | 14 +++++++
 gcc/config/bfin/bfin-protos.h |  3 +-
 gcc/config/bfin/bfin.c        | 77 ++++++++++++++++++++++++++++++++++-
 gcc/config/bfin/bfin.h        |  2 +-
 gcc/config/bfin/bfin.md       |  5 ++-
 5 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9742a6c0c2ba..bafe4c42b297 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2006-11-20  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+	* config/bfin/bfin.h (LEGITIMATE_CONSTANT_P): Call
+	bfin_legitimate_constant_p.
+	* config/bfin/bfin.md (movsi expander): Check return value of
+	expand_mvoe.
+	* config/bfin/bfin-protos.h (bfin_legitimate_constant_p): Declare.
+	(expand_move): Adjust prototype.
+	* config/bfin/bfin.c (expand_move): Now returns bool.  Handle
+	invalid constants specially.
+	(bfin_cannot_force_const_mem, bfin_legitimate_constant_p): New
+	functions.
+	(TARGET_CANNOT_FORCE_CONST_MEM): New macro.
+
 2006-11-19  Andrew Pinski  <pinskia@gmail.com>
 
 	PR rtl-opt/29879
diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h
index bbd1eeb7aa9c..31d15b6bfb0a 100644
--- a/gcc/config/bfin/bfin-protos.h
+++ b/gcc/config/bfin/bfin-protos.h
@@ -36,6 +36,7 @@ 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);
@@ -44,7 +45,7 @@ extern HOST_WIDE_INT bfin_initial_elimination_offset (int, int);
 extern int effective_address_32bit_p (rtx, Mmode);
 extern int symbolic_reference_mentioned_p (rtx);
 extern rtx bfin_gen_compare (rtx, Mmode);
-extern void expand_move (rtx *, Mmode);
+extern bool expand_move (rtx *, Mmode);
 extern void bfin_expand_call (rtx, rtx, rtx, rtx, int);
 extern bool bfin_longcall_p (rtx, int);
 extern bool bfin_dsp_memref_p (rtx);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 299fc5655298..edc7cc49ee88 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -1648,21 +1648,44 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
 					  : pic_offset_table_rtx);
 }
 
-/* Expand a move operation in mode MODE.  The operands are in OPERANDS.  */
+/* Expand a move operation in mode MODE.  The operands are in OPERANDS.
+   Returns true if no further code must be generated, false if the caller
+   should generate an insn to move OPERANDS[1] to OPERANDS[0].  */
 
-void
+bool
 expand_move (rtx *operands, enum machine_mode mode)
 {
   rtx op = operands[1];
   if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
       && SYMBOLIC_CONST (op))
     emit_pic_move (operands, mode);
+  else if (mode == SImode && GET_CODE (op) == CONST
+	   && GET_CODE (XEXP (op, 0)) == PLUS
+	   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
+	   && !bfin_legitimate_constant_p (op))
+    {
+      rtx dest = operands[0];
+      rtx op0, op1;
+      gcc_assert (!reload_in_progress && !reload_completed);
+      op = XEXP (op, 0);
+      op0 = force_reg (mode, XEXP (op, 0));
+      op1 = XEXP (op, 1);
+      if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
+	op1 = force_reg (mode, op1);
+      if (GET_CODE (dest) == MEM)
+	dest = gen_reg_rtx (mode);
+      emit_insn (gen_addsi3 (dest, op0, op1));
+      if (dest == operands[0])
+	return true;
+      operands[1] = dest;
+    }
   /* Don't generate memory->memory or constant->memory moves, go through a
      register */
   else if ((reload_in_progress | reload_completed) == 0
 	   && GET_CODE (operands[0]) == MEM
     	   && GET_CODE (operands[1]) != REG)
     operands[1] = force_reg (mode, operands[1]);
+  return false;
 }
 
 /* Split one or more DImode RTL references into pairs of SImode
@@ -2306,6 +2329,53 @@ bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
   return false;
 }
 
+/* Decide whether we can force certain constants to memory.  If we
+   decide we can't, the caller should be able to cope with it in
+   another way.  */
+
+static bool
+bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
+{
+  /* We have only one class of non-legitimate constants, and our movsi
+     expander knows how to handle them.  Dropping these constants into the
+     data section would only shift the problem - we'd still get relocs
+     outside the object, in the data section rather than the text section.  */
+  return true;
+}
+
+/* Ensure that for any constant of the form symbol + offset, the offset
+   remains within the object.  Any other constants are ok.
+   This ensures that flat binaries never have to deal with relocations
+   crossing section boundaries.  */
+
+bool
+bfin_legitimate_constant_p (rtx x)
+{
+  rtx sym;
+  HOST_WIDE_INT offset;
+
+  if (GET_CODE (x) != CONST)
+    return true;
+
+  x = XEXP (x, 0);
+  gcc_assert (GET_CODE (x) == PLUS);
+
+  sym = XEXP (x, 0);
+  x = XEXP (x, 1);
+  if (GET_CODE (sym) != SYMBOL_REF
+      || GET_CODE (x) != CONST_INT)
+    return true;
+  offset = INTVAL (x);
+
+  if (SYMBOL_REF_DECL (sym) == 0)
+    return true;
+  if (offset < 0
+      || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
+    return false;
+
+  return true;
+}
+
 static bool
 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
 {
@@ -4432,4 +4502,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
 #undef TARGET_DELEGITIMIZE_ADDRESS
 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
 
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
+
 struct gcc_target targetm = TARGET_INITIALIZER;
diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h
index 074fd114a0bb..00b6c29f40f3 100644
--- a/gcc/config/bfin/bfin.h
+++ b/gcc/config/bfin/bfin.h
@@ -729,7 +729,7 @@ typedef struct {
    See force_const_mem().
    If -mno-pool, all constants are legitimate.
  */
-#define LEGITIMATE_CONSTANT_P(x) 1
+#define LEGITIMATE_CONSTANT_P(X) bfin_legitimate_constant_p (X)
 
 /*   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
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 425f99580c7a..afd24e62da7b 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -605,7 +605,10 @@
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
 	(match_operand:SI 1 "general_operand" ""))]
   ""
-  "expand_move (operands, SImode);")
+{
+  if (expand_move (operands, SImode))
+    DONE;
+})
 
 (define_expand "movv2hi"
   [(set (match_operand:V2HI 0 "nonimmediate_operand" "")
-- 
GitLab