diff options
Diffstat (limited to 'contrib/gcc/config/rs6000/rs6000.c')
-rw-r--r-- | contrib/gcc/config/rs6000/rs6000.c | 116 |
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) |