summaryrefslogtreecommitdiff
path: root/gcc/config/sparc
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-05-10 11:15:07 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-05-10 11:15:07 +0000
commit723e1902a4a3de3c537888fc3c063a13850f4fc2 (patch)
tree6dd6c8dc5926e50ceabcd4e33f3edafd37e19c3c /gcc/config/sparc
parent168fa52f3fb47a001d7656b677cc887913b760bb (diff)
downloadgcc-723e1902a4a3de3c537888fc3c063a13850f4fc2.tar.gz
gcc/
* config.gcc (sparc-wrs-vxworks): New target. * config/sparc/vxworks.h, config/sparc/t-vxworks: New files. * config/sparc/sparc-protos.h (sparc_emit_call_insn): Declare. * config/sparc/sparc.h: Include vxworks-dummy.h. (PRINT_OPERAND_ADDRESS): Extend SYMBOL_REF handling to include LABEL_REFs too. * config/sparc/sparc.c (sparc_expand_move): Don't assume that _GLOBAL_OFFSET_TABLE_ - label_ref is a link-time constant on VxWorks. (legitimize_pic_address): Handle LABEL_REFs like SYMBOL_REFs on VxWorks. (load_pic_register): Use gen_vxworks_load_got for VxWorks. (sparc_emit_call_insn): New function. (sparc_function_ok_for_sibcall): Restrict sibcalls to locally-binding functions when generating VxWorks PIC. * config/sparc/sparc.md (vxworks_load_got): New pattern. (call, call_value): Use sparc_emit_call_insn instead of emit_call_insn. libgcc/ * config.host (sparc-wrs-vxworks): New target. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124595 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sparc')
-rw-r--r--gcc/config/sparc/sparc-protos.h1
-rw-r--r--gcc/config/sparc/sparc.c74
-rw-r--r--gcc/config/sparc/sparc.h3
-rw-r--r--gcc/config/sparc/sparc.md32
-rw-r--r--gcc/config/sparc/t-vxworks5
-rw-r--r--gcc/config/sparc/vxworks.h64
6 files changed, 159 insertions, 20 deletions
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 4fb862cc908..c1b2813a3b3 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -73,6 +73,7 @@ extern int legitimate_address_p (enum machine_mode, rtx, int);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern rtx legitimize_tls_address (rtx);
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
+extern void sparc_emit_call_insn (rtx, rtx);
extern void sparc_defer_case_vector (rtx, rtx, int);
extern bool sparc_expand_move (enum machine_mode, rtx *);
extern void sparc_emit_set_const32 (rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index be07ce7d3d0..f94af2ac5d1 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -980,17 +980,27 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
if (pic_address_needs_scratch (operands[1]))
operands[1] = legitimize_pic_address (operands[1], mode, 0);
- if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode)
- {
- emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
- return true;
- }
+ /* VxWorks does not impose a fixed gap between segments; the run-time
+ gap can be different from the object-file gap. We therefore can't
+ assume X - _GLOBAL_OFFSET_TABLE_ is a link-time constant unless we
+ are absolutely sure that X is in the same segment as the GOT.
+ Unfortunately, the flexibility of linker scripts means that we
+ can't be sure of that in general, so assume that _G_O_T_-relative
+ accesses are never valid on VxWorks. */
+ if (GET_CODE (operands[1]) == LABEL_REF && !TARGET_VXWORKS_RTP)
+ {
+ if (mode == SImode)
+ {
+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
- if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode)
- {
- gcc_assert (TARGET_ARCH64);
- emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
- return true;
+ if (mode == DImode)
+ {
+ gcc_assert (TARGET_ARCH64);
+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
}
if (symbolic_operand (operands[1], mode))
@@ -3212,7 +3222,9 @@ rtx
legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
rtx reg)
{
- if (GET_CODE (orig) == SYMBOL_REF)
+ if (GET_CODE (orig) == SYMBOL_REF
+ /* See the comment in sparc_expand_move. */
+ || (TARGET_VXWORKS_RTP && GET_CODE (orig) == LABEL_REF))
{
rtx pic_ref, address;
rtx insn;
@@ -3377,6 +3389,13 @@ load_pic_register (bool delay_pic_helper)
{
int orig_flag_pic = flag_pic;
+ if (TARGET_VXWORKS_RTP)
+ {
+ emit_insn (gen_vxworks_load_got ());
+ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
+ return;
+ }
+
/* If we haven't initialized the special PIC symbols, do so now. */
if (!pic_helper_symbol_name[0])
{
@@ -3405,6 +3424,29 @@ load_pic_register (bool delay_pic_helper)
since we may not fall out the bottom. */
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
}
+
+/* Emit a call instruction with the pattern given by PAT. ADDR is the
+ address of the call target. */
+
+void
+sparc_emit_call_insn (rtx pat, rtx addr)
+{
+ rtx insn;
+
+ insn = emit_call_insn (pat);
+
+ /* The PIC register is live on entry to VxWorks PIC PLT entries. */
+ if (TARGET_VXWORKS_RTP
+ && flag_pic
+ && GET_CODE (addr) == SYMBOL_REF
+ && (SYMBOL_REF_DECL (addr)
+ ? !targetm.binds_local_p (SYMBOL_REF_DECL (addr))
+ : !SYMBOL_REF_LOCAL_P (addr)))
+ {
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ current_function_uses_pic_offset_table = 1;
+ }
+}
/* Return 1 if RTX is a MEM which is known to be aligned to at
least a DESIRED byte boundary. */
@@ -7771,13 +7813,19 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags,
the sibling call right? Well, in the C++ case we can end up passing
the pointer to the struct return area to a constructor (which returns
void) and then nothing else happens. Such a sibling call would look
- valid without the added check here. */
+ valid without the added check here.
+
+ VxWorks PIC PLT entries require the global pointer to be initialized
+ on entry. We therefore can't emit sibling calls to them. */
static bool
sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
return (decl
&& flag_delayed_branch
- && (TARGET_ARCH64 || ! current_function_returns_struct));
+ && (TARGET_ARCH64 || ! current_function_returns_struct)
+ && !(TARGET_VXWORKS_RTP
+ && flag_pic
+ && !targetm.binds_local_p (decl)));
}
/* libfunc renaming. */
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index db0e34e516d..1a4805bb7d3 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
+#include "config/vxworks-dummy.h"
+
/* Note that some other tm.h files include this one and then override
whatever definitions are necessary. */
@@ -2409,6 +2411,7 @@ extern int sparc_indent_opcode;
else if (GET_CODE (index) == REG) \
fprintf (FILE, "+%s", reg_names[REGNO (index)]); \
else if (GET_CODE (index) == SYMBOL_REF \
+ || GET_CODE (index) == LABEL_REF \
|| GET_CODE (index) == CONST) \
fputc ('+', FILE), output_addr_const (FILE, index); \
else gcc_unreachable (); \
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 387b3405db5..6d5797dbe2b 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -1874,6 +1874,22 @@
"flag_pic"
"or\t%1, %%lo(%a3-(%a2-.)), %0")
+;; Set up the PIC register for VxWorks.
+
+(define_expand "vxworks_load_got"
+ [(set (match_dup 0)
+ (high:SI (match_dup 1)))
+ (set (match_dup 0)
+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 1))))
+ (set (match_dup 0)
+ (mem:SI (lo_sum:SI (match_dup 0) (match_dup 2))))]
+ "TARGET_VXWORKS_RTP"
+{
+ operands[0] = pic_offset_table_rtx;
+ operands[1] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_BASE);
+ operands[2] = gen_rtx_SYMBOL_REF (SImode, VXWORKS_GOTT_INDEX);
+})
+
(define_expand "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
@@ -6676,7 +6692,7 @@
{
rtx fn_rtx;
- gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE);
+ gcc_assert (MEM_P (operands[0]) && GET_MODE (operands[0]) == FUNCTION_MODE);
gcc_assert (GET_CODE (operands[3]) == CONST_INT);
@@ -6712,18 +6728,20 @@
/* We accept negative sizes for untyped calls. */
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
- emit_call_insn
+ sparc_emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
operands[3],
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
+ XEXP (fn_rtx, 0));
else
- emit_call_insn
+ sparc_emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))),
+ XEXP (fn_rtx, 0));
finish_call:
@@ -6840,7 +6858,7 @@
rtx fn_rtx;
rtvec vec;
- gcc_assert (GET_MODE (operands[1]) == FUNCTION_MODE);
+ gcc_assert (MEM_P (operands[1]) && GET_MODE (operands[1]) == FUNCTION_MODE);
fn_rtx = operands[1];
@@ -6849,7 +6867,7 @@
gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
- emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+ sparc_emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec), XEXP (fn_rtx, 0));
DONE;
})
diff --git a/gcc/config/sparc/t-vxworks b/gcc/config/sparc/t-vxworks
new file mode 100644
index 00000000000..2aabf1a43cd
--- /dev/null
+++ b/gcc/config/sparc/t-vxworks
@@ -0,0 +1,5 @@
+# Multilibs for VxWorks.
+
+MULTILIB_OPTIONS = mrtp fPIC
+MULTILIB_MATCHES = fPIC=fpic
+MULTILIB_EXCEPTIONS = fPIC
diff --git a/gcc/config/sparc/vxworks.h b/gcc/config/sparc/vxworks.h
new file mode 100644
index 00000000000..7faacea53ab
--- /dev/null
+++ b/gcc/config/sparc/vxworks.h
@@ -0,0 +1,64 @@
+/* Definitions of target machine for GNU compiler,
+ for SPARC targeting the VxWorks run time environment.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+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 2, 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 COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__sparc"); \
+ builtin_define ("CPU=SIMSPARCSOLARIS"); \
+ VXWORKS_OS_CPP_BUILTINS (); \
+ } \
+ while (0)
+
+#undef OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS \
+ do \
+ { \
+ VXWORKS_OVERRIDE_OPTIONS; \
+ sparc_override_options (); \
+ } \
+ while (0)
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC VXWORKS_ADDITIONAL_CPP_SPEC
+
+#undef LIB_SPEC
+#define LIB_SPEC VXWORKS_LIB_SPEC
+#undef LINK_SPEC
+#define LINK_SPEC VXWORKS_LINK_SPEC
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (SPARC/VxWorks)", stderr);
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER
+
+/* Use standard numbered ctors/dtors sections. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+
+/* We cannot use PC-relative accesses for VxWorks PIC because there is no
+ fixed gap between segments. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT