This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Add support for sparc-wrs-vxworks


Eric Botcazou <ebotcazou@libertysurf.fr> writes:
>> OK, here's the revised patch.  How does it look?  (I know you said it
>> was OK with the earlier changes, but I just wanted to make sure I'd got
>> it right.)  Tested in the same way as before.
>
> Almost OK (just merge the 2 pairs of gcc_assert with an && and install, no 
> need to retest).

OK, thanks, here's what I installed after checking that it still builds.

Richard


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.

Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 124567)
+++ gcc/config.gcc	(working copy)
@@ -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"
Index: gcc/config/sparc/vxworks.h
===================================================================
--- gcc/config/sparc/vxworks.h	(revision 0)
+++ gcc/config/sparc/vxworks.h	(revision 0)
@@ -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
Index: gcc/config/sparc/t-vxworks
===================================================================
--- gcc/config/sparc/t-vxworks	(revision 0)
+++ gcc/config/sparc/t-vxworks	(revision 0)
@@ -0,0 +1,5 @@
+# Multilibs for VxWorks.
+
+MULTILIB_OPTIONS = mrtp fPIC
+MULTILIB_MATCHES = fPIC=fpic
+MULTILIB_EXCEPTIONS = fPIC
Index: gcc/config/sparc/sparc-protos.h
===================================================================
--- gcc/config/sparc/sparc-protos.h	(revision 124567)
+++ gcc/config/sparc/sparc-protos.h	(working copy)
@@ -73,6 +73,7 @@ extern int legitimate_address_p (enum ma
 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);
Index: gcc/config/sparc/sparc.h
===================================================================
--- gcc/config/sparc/sparc.h	(revision 124567)
+++ gcc/config/sparc/sparc.h	(working copy)
@@ -22,6 +22,8 @@ the Free Software Foundation; either ver
 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 @@ #define PRINT_OPERAND_ADDRESS(FILE, ADDR
 	  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 ();				\
Index: gcc/config/sparc/sparc.c
===================================================================
--- gcc/config/sparc/sparc.c	(revision 124567)
+++ gcc/config/sparc/sparc.c	(working copy)
@@ -980,17 +980,27 @@ sparc_expand_move (enum machine_mode mod
       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 @@ legitimize_tls_address (rtx addr)
 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 
    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.  */
Index: gcc/config/sparc/sparc.md
===================================================================
--- gcc/config/sparc/sparc.md	(revision 124567)
+++ gcc/config/sparc/sparc.md	(working copy)
@@ -1874,6 +1874,22 @@ (define_insn "*movsi_lo_sum_pic_label_re
   "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 @@ (define_expand "call"
 {
   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 @@ (define_expand "call"
 
   /* 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 @@ (define_expand "call_value"
   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 @@ (define_expand "call_value"
 				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;
 })
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 124567)
+++ libgcc/config.host	(working copy)
@@ -594,6 +594,8 @@ sparc-*-sysv4*)
 	;;
 sparc64-*-elf*)
 	;;
+sparc-wrs-vxworks)
+	;;
 sparc64-*-freebsd*|ultrasparc-*-freebsd*)
 	;;
 sparc64-*-linux*)		# 64-bit SPARC's running GNU/Linux


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]