From ce5e0cfe0f5e1482705c26e635c95df171863b08 Mon Sep 17 00:00:00 2001 From: Peter Bergner Date: Tue, 1 Nov 2011 18:53:46 +0000 Subject: * config.gcc (powerpc*-*-linux*): Add powerpc*-*-linux*ppc476* variant. * config/rs6000/476.h: New file. * config/rs6000/476.opt: Likewise. * config/rs6000/rs6000.h (TARGET_LINK_STACK): New define. (SET_TARGET_LINK_STACK): Likewise. (TARGET_ASM_CODE_END): Define. * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable TARGET_LINK_STACK for -mtune=476 and -mtune=476fp. (rs6000_legitimize_tls_address): Emit the link stack preserving GOT code if TARGET_LINK_STACK. (rs6000_emit_load_toc_table): Likewise. (output_function_profiler): Likewise (macho_branch_islands): Likewise (machopic_output_stub): Likewise (get_ppc476_thunk_name): New function. (rs6000_code_end): Likewise. * config/rs6000/rs6000.md (load_toc_v4_PIC_1, load_toc_v4_PIC_1b): Convert to a define_expand. (load_toc_v4_PIC_1_normal): New define_insn. (load_toc_v4_PIC_1_476): Likewise. (load_toc_v4_PIC_1b_normal): Likewise. (load_toc_v4_PIC_1b_476): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@180741 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 25 +++++++ gcc/config.gcc | 3 + gcc/config/rs6000/476.h | 32 +++++++++ gcc/config/rs6000/476.opt | 24 +++++++ gcc/config/rs6000/rs6000-protos.h | 1 + gcc/config/rs6000/rs6000.c | 148 ++++++++++++++++++++++++++++++++++---- gcc/config/rs6000/rs6000.h | 8 +++ gcc/config/rs6000/rs6000.md | 62 ++++++++++++++-- 8 files changed, 286 insertions(+), 17 deletions(-) create mode 100644 gcc/config/rs6000/476.h create mode 100644 gcc/config/rs6000/476.opt diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d8476c27c6b..fd29e51553d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2011-11-01 Peter Bergner + + * config.gcc (powerpc*-*-linux*): Add powerpc*-*-linux*ppc476* variant. + * config/rs6000/476.h: New file. + * config/rs6000/476.opt: Likewise. + * config/rs6000/rs6000.h (TARGET_LINK_STACK): New define. + (SET_TARGET_LINK_STACK): Likewise. + (TARGET_ASM_CODE_END): Define. + * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable + TARGET_LINK_STACK for -mtune=476 and -mtune=476fp. + (rs6000_legitimize_tls_address): Emit the link stack preserving GOT + code if TARGET_LINK_STACK. + (rs6000_emit_load_toc_table): Likewise. + (output_function_profiler): Likewise + (macho_branch_islands): Likewise + (machopic_output_stub): Likewise + (get_ppc476_thunk_name): New function. + (rs6000_code_end): Likewise. + * config/rs6000/rs6000.md (load_toc_v4_PIC_1, load_toc_v4_PIC_1b): + Convert to a define_expand. + (load_toc_v4_PIC_1_normal): New define_insn. + (load_toc_v4_PIC_1_476): Likewise. + (load_toc_v4_PIC_1b_normal): Likewise. + (load_toc_v4_PIC_1b_476): Likewise. + 2011-11-01 Georg-Johann Lay PR target/50910 diff --git a/gcc/config.gcc b/gcc/config.gcc index 2c18655ca0d..2cb8b365891 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2145,6 +2145,9 @@ powerpc-*-linux* | powerpc64-*-linux*) esac tmake_file="${tmake_file} t-slibgcc-libgcc" case ${target} in + powerpc*-*-linux*ppc476*) + tm_file="${tm_file} rs6000/476.h" + extra_options="${extra_options} rs6000/476.opt" ;; powerpc*-*-linux*altivec*) tm_file="${tm_file} rs6000/linuxaltivec.h" ;; powerpc*-*-linux*spe*) diff --git a/gcc/config/rs6000/476.h b/gcc/config/rs6000/476.h new file mode 100644 index 00000000000..70ee7bd7406 --- /dev/null +++ b/gcc/config/rs6000/476.h @@ -0,0 +1,32 @@ +/* Enable IBM PowerPC 476 support. + Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Peter Bergner (bergner@vnet.ibm.com) + 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 + . */ + +#undef TARGET_LINK_STACK +#define TARGET_LINK_STACK (rs6000_link_stack) + +#undef SET_TARGET_LINK_STACK +#define SET_TARGET_LINK_STACK(X) do { TARGET_LINK_STACK = (X); } while (0) + +#undef TARGET_ASM_CODE_END +#define TARGET_ASM_CODE_END rs6000_code_end diff --git a/gcc/config/rs6000/476.opt b/gcc/config/rs6000/476.opt new file mode 100644 index 00000000000..c987fc6c662 --- /dev/null +++ b/gcc/config/rs6000/476.opt @@ -0,0 +1,24 @@ +; IBM PowerPC 476 options. +; +; Copyright (C) 2011 Free Software Foundation, Inc. +; Contributed by Peter Bergner (bergner@vnet.ibm.com) +; +; 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 +; . + +mpreserve-link-stack +Target Var(rs6000_link_stack) Init(-1) Save +Preserve the PowerPC 476's link stack by matching up a blr with the bcl/bl insns used for GOT accesses diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 73da0f69f47..23d2d2aa389 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -173,6 +173,7 @@ extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern const char * output_isel (rtx *); extern void rs6000_call_indirect_aix (rtx, rtx, rtx); extern void rs6000_aix_asm_output_dwarf_table_ref (char *); +extern void get_ppc476_thunk_name (char name[32]); /* Declare functions in rs6000-c.c */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 0f36188eaaf..5b4607a5659 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1613,7 +1613,6 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p -struct gcc_target targetm = TARGET_INITIALIZER; /* Simplifications for entries below. */ @@ -3239,6 +3238,11 @@ rs6000_option_override_internal (bool global_init_p) target_option_default_node = target_option_current_node = build_target_option_node (); + /* If not explicitly specified via option, decide whether to generate the + extra blr's required to preserve the link stack on some cpus (eg, 476). */ + if (TARGET_LINK_STACK == -1) + SET_TARGET_LINK_STACK (rs6000_cpu == PROCESSOR_PPC476 && flag_pic); + return ret; } @@ -5868,6 +5872,8 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model) lab = gen_label_rtx (); emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab)); emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO)); + if (TARGET_LINK_STACK) + emit_insn (gen_addsi3 (tmp1, tmp1, GEN_INT (4))); emit_move_insn (tmp2, mem); last = emit_insn (gen_addsi3 (got, tmp1, tmp2)); set_unique_reg_note (last, REG_EQUAL, gsym); @@ -18866,6 +18872,8 @@ rs6000_emit_load_toc_table (int fromprolog) lab = gen_label_rtx (); emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab)); emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO)); + if (TARGET_LINK_STACK) + emit_insn (gen_addsi3 (dest, dest, GEN_INT (4))); emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest)); } emit_insn (gen_addsi3 (dest, temp0, dest)); @@ -22526,7 +22534,15 @@ output_function_profiler (FILE *file, int labelno) } else if (TARGET_SECURE_PLT && flag_pic) { - asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n", + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + asm_fprintf (file, "\tbl %s\n", name); + } + else + asm_fprintf (file, "\tbcl 20,31,1f\n1:\n"); + asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]); asm_fprintf (file, "\tmflr %s\n", reg_names[12]); asm_fprintf (file, "\t{cau|addis} %s,%s,", @@ -22551,10 +22567,24 @@ output_function_profiler (FILE *file, int labelno) asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", reg_names[0], reg_names[1]); /* Now, we need to get the address of the label. */ - fputs ("\tbcl 20,31,1f\n\t.long ", file); - assemble_name (file, buf); - fputs ("-.\n1:", file); - asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + asm_fprintf (file, "\tbl %s\n\tb 1f\n\t.long ", name); + assemble_name (file, buf); + fputs ("-.\n1:", file); + asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + asm_fprintf (file, "\taddi %s,%s,4\n", + reg_names[11], reg_names[11]); + } + else + { + fputs ("\tbcl 20,31,1f\n\t.long ", file); + assemble_name (file, buf); + fputs ("-.\n1:", file); + asm_fprintf (file, "\tmflr %s\n", reg_names[11]); + } asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n", reg_names[0], reg_names[11]); asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", @@ -25037,11 +25067,24 @@ macho_branch_islands (void) #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ if (flag_pic) { - strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic\n"); - strcat (tmp_buf, label); - strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc64_thunk_name (name); + strcat (tmp_buf, ":\n\tmflr r0\n\tbl "); + strcat (tmp_buf, name); + strcat (tmp_buf, "\n"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + } + else + { + strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic\n"); + strcat (tmp_buf, label); + strcat (tmp_buf, "_pic:\n\tmflr r11\n"); + } strcat (tmp_buf, "\taddis r11,r11,ha16("); strcat (tmp_buf, name_buf); @@ -25187,8 +25230,18 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub) sprintf (local_label_0, "\"L%011d$spb\"", label); fprintf (file, "\tmflr r0\n"); - fprintf (file, "\tbcl 20,31,%s\n", local_label_0); - fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + if (TARGET_LINK_STACK) + { + char name[32]; + get_ppc476_thunk_name (name); + fprintf (file, "\tbl %s\n", name); + fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + } + else + { + fprintf (file, "\tbcl 20,31,%s\n", local_label_0); + fprintf (file, "%s:\n\tmflr r11\n", local_label_0); + } fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n", lazy_ptr_name, local_label_0); fprintf (file, "\tmtlr r0\n"); @@ -27895,4 +27948,73 @@ rs6000_save_toc_in_prologue_p (void) return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue); } +/* Fills in the label name that should be used for a 476 link stack thunk. */ + +void +get_ppc476_thunk_name (char name[32]) +{ + gcc_assert (TARGET_LINK_STACK); + + if (HAVE_GAS_HIDDEN) + sprintf (name, "__ppc476.get_thunk"); + else + ASM_GENERATE_INTERNAL_LABEL (name, "LPPC476_", 0); +} + +/* This function emits the simple thunk routine that is used to preserve + the link stack on the 476 cpu. */ + +static void +rs6000_code_end (void) +{ + char name[32]; + tree decl; + + if (!TARGET_LINK_STACK) + return; + + get_ppc476_thunk_name (name); + + decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, get_identifier (name), + build_function_type_list (void_type_node, NULL_TREE)); + DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL, + NULL_TREE, void_type_node); + TREE_PUBLIC (decl) = 1; + TREE_STATIC (decl) = 1; + + if (HAVE_GAS_HIDDEN) + { + DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl); + targetm.asm_out.unique_section (decl, 0); + switch_to_section (get_named_section (decl, NULL, 0)); + DECL_WEAK (decl) = 1; + ASM_WEAKEN_DECL (asm_out_file, decl, name, 0); + targetm.asm_out.globalize_label (asm_out_file, name); + targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN); + ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl); + } + else + { + switch_to_section (text_section); + ASM_OUTPUT_LABEL (asm_out_file, name); + } + + DECL_INITIAL (decl) = make_node (BLOCK); + current_function_decl = decl; + init_function_start (decl); + first_function_block_is_cold = false; + /* Make sure unwind info is emitted for the thunk if needed. */ + final_start_function (emit_barrier (), asm_out_file, 1); + + fputs ("\tblr\n", asm_out_file); + + final_end_function (); + init_insn_lengths (); + free_after_compilation (cfun); + set_cfun (NULL); + current_function_decl = NULL; +} + +struct gcc_target targetm = TARGET_INITIALIZER; + #include "gt-rs6000.h" diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 112a32e50db..d0cfabb8449 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -313,6 +313,14 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define HAVE_AS_TLS 0 #endif +#ifndef TARGET_LINK_STACK +#define TARGET_LINK_STACK 0 +#endif + +#ifndef SET_TARGET_LINK_STACK +#define SET_TARGET_LINK_STACK(X) do { } while (0) +#endif + /* Return 1 for a symbol ref for a thread-local storage symbol. */ #define RS6000_SYMBOL_REF_TLS_P(RTX) \ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 7255329069e..331aa79aac0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -12087,27 +12087,81 @@ [(set_attr "type" "branch") (set_attr "length" "4")]) -(define_insn "load_toc_v4_PIC_1" +(define_expand "load_toc_v4_PIC_1" + [(parallel [(set (reg:SI LR_REGNO) + (match_operand:SI 0 "immediate_operand" "s")) + (use (unspec [(match_dup 0)] UNSPEC_TOC))])] + "TARGET_ELF && DEFAULT_ABI != ABI_AIX + && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" + "") + +(define_insn "load_toc_v4_PIC_1_normal" [(set (reg:SI LR_REGNO) (match_operand:SI 0 "immediate_operand" "s")) (use (unspec [(match_dup 0)] UNSPEC_TOC))] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" "bcl 20,31,%0\\n%0:" [(set_attr "type" "branch") (set_attr "length" "4")]) -(define_insn "load_toc_v4_PIC_1b" +(define_insn "load_toc_v4_PIC_1_476" + [(set (reg:SI LR_REGNO) + (match_operand:SI 0 "immediate_operand" "s")) + (use (unspec [(match_dup 0)] UNSPEC_TOC))] + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX + && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))" + "* +{ + char name[32]; + static char templ[32]; + + get_ppc476_thunk_name (name); + sprintf (templ, \"bl %s\\n%%0:\", name); + return templ; +}" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + +(define_expand "load_toc_v4_PIC_1b" + [(parallel [(set (reg:SI LR_REGNO) + (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") + (label_ref (match_operand 1 "" ""))] + UNSPEC_TOCPTR)) + (match_dup 1)])] + "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "") + +(define_insn "load_toc_v4_PIC_1b_normal" [(set (reg:SI LR_REGNO) (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") (label_ref (match_operand 1 "" ""))] UNSPEC_TOCPTR)) (match_dup 1)] - "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" "bcl 20,31,$+8\;.long %0-$" [(set_attr "type" "branch") (set_attr "length" "8")]) +(define_insn "load_toc_v4_PIC_1b_476" + [(set (reg:SI LR_REGNO) + (unspec:SI [(match_operand:SI 0 "immediate_operand" "s") + (label_ref (match_operand 1 "" ""))] + UNSPEC_TOCPTR)) + (match_dup 1)] + "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2" + "* +{ + char name[32]; + static char templ[32]; + + get_ppc476_thunk_name (name); + sprintf (templ, \"bl %s\\n\\tb $+8\\n\\t.long %%0-$\", name); + return templ; +}" + [(set_attr "type" "branch") + (set_attr "length" "16")]) + (define_insn "load_toc_v4_PIC_2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b") -- cgit v1.2.3