summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/rs6000/rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/config/rs6000/rs6000.c')
-rw-r--r--contrib/gcc/config/rs6000/rs6000.c116
1 files changed, 108 insertions, 8 deletions
diff --git a/contrib/gcc/config/rs6000/rs6000.c b/contrib/gcc/config/rs6000/rs6000.c
index 2adb119..89808cc 100644
--- a/contrib/gcc/config/rs6000/rs6000.c
+++ b/contrib/gcc/config/rs6000/rs6000.c
@@ -1,6 +1,6 @@
/* Subroutines used for code generation on IBM RS/6000.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -77,6 +77,9 @@ int rs6000_altivec_abi;
/* Set to non-zero once AIX common-mode calls have been defined. */
static int common_mode_defined;
+/* Private copy of original value of flag_pic for ABI_AIX. */
+static int rs6000_flag_pic;
+
/* Save information from a "cmpxx" operation until the branch or scc is
emitted. */
rtx rs6000_compare_op0, rs6000_compare_op1;
@@ -152,6 +155,7 @@ static void rs6000_elf_asm_out_destructor PARAMS ((rtx, int));
#ifdef OBJECT_FORMAT_COFF
static void xcoff_asm_named_section PARAMS ((const char *, unsigned int));
#endif
+static bool rs6000_binds_local_p PARAMS ((tree));
static int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
static int rs6000_adjust_priority PARAMS ((rtx, int));
static int rs6000_issue_rate PARAMS ((void));
@@ -484,11 +488,8 @@ rs6000_override_options (default_cpu)
if (flag_pic != 0 && DEFAULT_ABI == ABI_AIX)
{
+ rs6000_flag_pic = flag_pic;
flag_pic = 0;
-
- if (extra_warnings)
- warning ("-f%s ignored (all code is position independent)",
- (flag_pic > 1) ? "PIC" : "pic");
}
#ifdef XCOFF_DEBUGGING_INFO
@@ -5220,6 +5221,64 @@ store_multiple_operation (op, mode)
return 1;
}
+/* Return a string to perform a load_multiple operation.
+ operands[0] is the vector.
+ operands[1] is the source address.
+ operands[2] is the first destination register. */
+
+const char *
+rs6000_output_load_multiple (operands)
+ rtx operands[3];
+{
+ /* We have to handle the case where the pseudo used to contain the address
+ is assigned to one of the output registers. */
+ int i, j;
+ int words = XVECLEN (operands[0], 0);
+ rtx xop[10];
+
+ if (XVECLEN (operands[0], 0) == 1)
+ return "{l|lwz} %2,0(%1)";
+
+ for (i = 0; i < words; i++)
+ if (refers_to_regno_p (REGNO (operands[2]) + i,
+ REGNO (operands[2]) + i + 1, operands[1], 0))
+ {
+ if (i == words-1)
+ {
+ xop[0] = GEN_INT (4 * (words-1));
+ xop[1] = operands[1];
+ xop[2] = operands[2];
+ output_asm_insn ("{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,%0(%1)", xop);
+ return "";
+ }
+ else if (i == 0)
+ {
+ xop[0] = GEN_INT (4 * (words-1));
+ xop[1] = operands[1];
+ xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ output_asm_insn ("{cal %1,4(%1)|addi %1,%1,4}\n\t{lsi|lswi} %2,%1,%0\n\t{l|lwz} %1,-4(%1)", xop);
+ return "";
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ if (j != i)
+ {
+ xop[0] = GEN_INT (j * 4);
+ xop[1] = operands[1];
+ xop[2] = gen_rtx_REG (SImode, REGNO (operands[2]) + j);
+ output_asm_insn ("{l|lwz} %2,%0(%1)", xop);
+ }
+ xop[0] = GEN_INT (i * 4);
+ xop[1] = operands[1];
+ output_asm_insn ("{l|lwz} %1,%0(%1)", xop);
+ return "";
+ }
+ }
+
+ return "{lsi|lswi} %2,%1,%N0";
+}
+
/* Return 1 for a parallel vrsave operation. */
int
@@ -10881,7 +10940,45 @@ rs6000_unique_section (decl, reloc)
DECL_SECTION_NAME (decl) = build_string (len, string);
}
-
+
+static bool
+rs6000_binds_local_p (exp)
+ tree exp;
+{
+ bool local_p;
+ tree attr;
+
+ /* A non-decl is an entry in the constant pool. */
+ if (!DECL_P (exp))
+ local_p = true;
+ /* Static variables are always local. */
+ else if (! TREE_PUBLIC (exp))
+ local_p = true;
+ /* Otherwise, variables defined outside this object may not be local. */
+ else if (DECL_EXTERNAL (exp))
+ local_p = false;
+ /* Linkonce and weak data are never local. */
+ else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
+ local_p = false;
+ /* If PIC, then assume that any global name can be overridden by
+ * symbols resolved from other modules. */
+ else if (flag_pic || rs6000_flag_pic)
+ local_p = false;
+ /* Uninitialized COMMON variable may be unified with symbols
+ * resolved from other modules. */
+ else if (DECL_COMMON (exp)
+ && (DECL_INITIAL (exp) == NULL
+ || DECL_INITIAL (exp) == error_mark_node))
+ local_p = false;
+ /* Otherwise we're left with initialized (or non-common) global data
+ * which is of necessity defined locally. */
+ else
+ local_p = true;
+
+ return local_p;
+}
+
+
/* If we are referencing a function that is static or is known to be
in this file, make the SYMBOL_REF special. We can use this to indicate
that we can branch to this function without emitting a no-op after the
@@ -10897,8 +10994,7 @@ rs6000_encode_section_info (decl)
if (TREE_CODE (decl) == FUNCTION_DECL)
{
rtx sym_ref = XEXP (DECL_RTL (decl), 0);
- if ((TREE_ASM_WRITTEN (decl) || ! TREE_PUBLIC (decl))
- && ! DECL_WEAK (decl))
+ if (rs6000_binds_local_p (decl))
SYMBOL_REF_FLAG (sym_ref) = 1;
if (DEFAULT_ABI == ABI_AIX)
@@ -10917,11 +11013,15 @@ rs6000_encode_section_info (decl)
&& DEFAULT_ABI == ABI_V4
&& TREE_CODE (decl) == VAR_DECL)
{
+ rtx sym_ref = XEXP (DECL_RTL (decl), 0);
int size = int_size_in_bytes (TREE_TYPE (decl));
tree section_name = DECL_SECTION_NAME (decl);
const char *name = (char *)0;
int len = 0;
+ if (rs6000_binds_local_p (decl))
+ SYMBOL_REF_FLAG (sym_ref) = 1;
+
if (section_name)
{
if (TREE_CODE (section_name) == STRING_CST)
OpenPOWER on IntegriCloud