mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-10 22:06:01 +08:00
config.gcc (sparc-wrs-vxworks): New target.
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. From-SVN: r124595
This commit is contained in:
parent
31b40480a4
commit
1910440ea6
@ -1,3 +1,24 @@
|
||||
2007-05-10 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2007-05-09 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* config/xtensa/xtensa.c (xtensa_output_literal): Don't use #if.
|
||||
|
@ -2370,6 +2370,10 @@ sparc-*-sysv4*)
|
||||
extra_parts="crtbegin.o crtend.o"
|
||||
use_fixproto=yes
|
||||
;;
|
||||
sparc-wrs-vxworks)
|
||||
tm_file="${tm_file} elfos.h svr4.h sparc/sysv4.h vx-common.h vxworks.h sparc/vxworks.h"
|
||||
tmake_file="${tmake_file} sparc/t-vxworks"
|
||||
;;
|
||||
sparc64-*-elf*)
|
||||
tm_file="${tm_file} dbxelf.h elfos.h svr4.h sparc/sysv4.h sparc/sp64-elf.h"
|
||||
extra_options="${extra_options} sparc/little-endian.opt"
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
/* 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)
|
||||
{
|
||||
emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
|
||||
return true;
|
||||
}
|
||||
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. */
|
||||
|
@ -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 (); \
|
||||
|
@ -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;
|
||||
})
|
||||
|
5
gcc/config/sparc/t-vxworks
Normal file
5
gcc/config/sparc/t-vxworks
Normal file
@ -0,0 +1,5 @@
|
||||
# Multilibs for VxWorks.
|
||||
|
||||
MULTILIB_OPTIONS = mrtp fPIC
|
||||
MULTILIB_MATCHES = fPIC=fpic
|
||||
MULTILIB_EXCEPTIONS = fPIC
|
64
gcc/config/sparc/vxworks.h
Normal file
64
gcc/config/sparc/vxworks.h
Normal file
@ -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
|
@ -1,3 +1,7 @@
|
||||
2007-05-10 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* config.host (sparc-wrs-vxworks): New target.
|
||||
|
||||
2007-04-14 Kazu Hirata <kazu@codesourcery.com>
|
||||
|
||||
* config.host: Recognize fido.
|
||||
|
@ -594,6 +594,8 @@ sparc-*-sysv4*)
|
||||
;;
|
||||
sparc64-*-elf*)
|
||||
;;
|
||||
sparc-wrs-vxworks)
|
||||
;;
|
||||
sparc64-*-freebsd*|ultrasparc-*-freebsd*)
|
||||
;;
|
||||
sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux
|
||||
|
Loading…
Reference in New Issue
Block a user