Commit be26142a by Peter Bergner Committed by Peter Bergner

config.gcc (powerpc*-*-linux*): Add powerpc*-*-linux*ppc476* variant.

	* 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.

From-SVN: r180741
parent f1f59bc7
2011-11-01 Peter Bergner <bergner@vnet.ibm.com>
* 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 <avr@gjlay.de> 2011-11-01 Georg-Johann Lay <avr@gjlay.de>
PR target/50910 PR target/50910
...@@ -2145,6 +2145,9 @@ powerpc-*-linux* | powerpc64-*-linux*) ...@@ -2145,6 +2145,9 @@ powerpc-*-linux* | powerpc64-*-linux*)
esac esac
tmake_file="${tmake_file} t-slibgcc-libgcc" tmake_file="${tmake_file} t-slibgcc-libgcc"
case ${target} in case ${target} in
powerpc*-*-linux*ppc476*)
tm_file="${tm_file} rs6000/476.h"
extra_options="${extra_options} rs6000/476.opt" ;;
powerpc*-*-linux*altivec*) powerpc*-*-linux*altivec*)
tm_file="${tm_file} rs6000/linuxaltivec.h" ;; tm_file="${tm_file} rs6000/linuxaltivec.h" ;;
powerpc*-*-linux*spe*) powerpc*-*-linux*spe*)
......
/* 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
<http://www.gnu.org/licenses/>. */
#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
; 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
; <http://www.gnu.org/licenses/>.
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
...@@ -173,6 +173,7 @@ extern void rs6000_emit_eh_reg_restore (rtx, rtx); ...@@ -173,6 +173,7 @@ extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *); extern const char * output_isel (rtx *);
extern void rs6000_call_indirect_aix (rtx, rtx, rtx); extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
extern void rs6000_aix_asm_output_dwarf_table_ref (char *); 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 */ /* Declare functions in rs6000-c.c */
......
...@@ -1613,7 +1613,6 @@ static const struct attribute_spec rs6000_attribute_table[] = ...@@ -1613,7 +1613,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_LEGITIMATE_CONSTANT_P #undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p #define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p
struct gcc_target targetm = TARGET_INITIALIZER;
/* Simplifications for entries below. */ /* Simplifications for entries below. */
...@@ -3239,6 +3238,11 @@ rs6000_option_override_internal (bool global_init_p) ...@@ -3239,6 +3238,11 @@ rs6000_option_override_internal (bool global_init_p)
target_option_default_node = target_option_current_node target_option_default_node = target_option_current_node
= build_target_option_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; return ret;
} }
...@@ -5868,6 +5872,8 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model) ...@@ -5868,6 +5872,8 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
lab = gen_label_rtx (); lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab)); emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab));
emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO)); 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); emit_move_insn (tmp2, mem);
last = emit_insn (gen_addsi3 (got, tmp1, tmp2)); last = emit_insn (gen_addsi3 (got, tmp1, tmp2));
set_unique_reg_note (last, REG_EQUAL, gsym); set_unique_reg_note (last, REG_EQUAL, gsym);
...@@ -18866,6 +18872,8 @@ rs6000_emit_load_toc_table (int fromprolog) ...@@ -18866,6 +18872,8 @@ rs6000_emit_load_toc_table (int fromprolog)
lab = gen_label_rtx (); lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab)); emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab));
emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO)); 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_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
} }
emit_insn (gen_addsi3 (dest, temp0, dest)); emit_insn (gen_addsi3 (dest, temp0, dest));
...@@ -22526,7 +22534,15 @@ output_function_profiler (FILE *file, int labelno) ...@@ -22526,7 +22534,15 @@ output_function_profiler (FILE *file, int labelno)
} }
else if (TARGET_SECURE_PLT && flag_pic) 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]); reg_names[0], reg_names[1]);
asm_fprintf (file, "\tmflr %s\n", reg_names[12]); asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
asm_fprintf (file, "\t{cau|addis} %s,%s,", asm_fprintf (file, "\t{cau|addis} %s,%s,",
...@@ -22551,10 +22567,24 @@ output_function_profiler (FILE *file, int labelno) ...@@ -22551,10 +22567,24 @@ output_function_profiler (FILE *file, int labelno)
asm_fprintf (file, "\t{st|stw} %s,4(%s)\n", asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
reg_names[0], reg_names[1]); reg_names[0], reg_names[1]);
/* Now, we need to get the address of the label. */ /* Now, we need to get the address of the label. */
fputs ("\tbcl 20,31,1f\n\t.long ", file); if (TARGET_LINK_STACK)
assemble_name (file, buf); {
fputs ("-.\n1:", file); char name[32];
asm_fprintf (file, "\tmflr %s\n", reg_names[11]); 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", asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
reg_names[0], reg_names[11]); reg_names[0], reg_names[11]);
asm_fprintf (file, "\t{cax|add} %s,%s,%s\n", asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
...@@ -25037,11 +25067,24 @@ macho_branch_islands (void) ...@@ -25037,11 +25067,24 @@ macho_branch_islands (void)
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
if (flag_pic) if (flag_pic)
{ {
strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,"); if (TARGET_LINK_STACK)
strcat (tmp_buf, label); {
strcat (tmp_buf, "_pic\n"); char name[32];
strcat (tmp_buf, label); get_ppc64_thunk_name (name);
strcat (tmp_buf, "_pic:\n\tmflr r11\n"); 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, "\taddis r11,r11,ha16(");
strcat (tmp_buf, name_buf); strcat (tmp_buf, name_buf);
...@@ -25187,8 +25230,18 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub) ...@@ -25187,8 +25230,18 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
sprintf (local_label_0, "\"L%011d$spb\"", label); sprintf (local_label_0, "\"L%011d$spb\"", label);
fprintf (file, "\tmflr r0\n"); fprintf (file, "\tmflr r0\n");
fprintf (file, "\tbcl 20,31,%s\n", local_label_0); if (TARGET_LINK_STACK)
fprintf (file, "%s:\n\tmflr r11\n", local_label_0); {
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", fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
lazy_ptr_name, local_label_0); lazy_ptr_name, local_label_0);
fprintf (file, "\tmtlr r0\n"); fprintf (file, "\tmtlr r0\n");
...@@ -27895,4 +27948,73 @@ rs6000_save_toc_in_prologue_p (void) ...@@ -27895,4 +27948,73 @@ rs6000_save_toc_in_prologue_p (void)
return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue); 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" #include "gt-rs6000.h"
...@@ -313,6 +313,14 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); ...@@ -313,6 +313,14 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define HAVE_AS_TLS 0 #define HAVE_AS_TLS 0
#endif #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. */ /* Return 1 for a symbol ref for a thread-local storage symbol. */
#define RS6000_SYMBOL_REF_TLS_P(RTX) \ #define RS6000_SYMBOL_REF_TLS_P(RTX) \
(GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0) (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
......
...@@ -12087,27 +12087,81 @@ ...@@ -12087,27 +12087,81 @@
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4")]) (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) [(set (reg:SI LR_REGNO)
(match_operand:SI 0 "immediate_operand" "s")) (match_operand:SI 0 "immediate_operand" "s"))
(use (unspec [(match_dup 0)] UNSPEC_TOC))] (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))" && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%0\\n%0:" "bcl 20,31,%0\\n%0:"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "4")]) (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) [(set (reg:SI LR_REGNO)
(unspec:SI [(match_operand:SI 0 "immediate_operand" "s") (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
(label_ref (match_operand 1 "" ""))] (label_ref (match_operand 1 "" ""))]
UNSPEC_TOCPTR)) UNSPEC_TOCPTR))
(match_dup 1)] (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-$" "bcl 20,31,$+8\;.long %0-$"
[(set_attr "type" "branch") [(set_attr "type" "branch")
(set_attr "length" "8")]) (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" (define_insn "load_toc_v4_PIC_2"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r") [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b") (mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment