public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Add support for sparc-wrs-vxworks
@ 2007-05-08 19:41 Richard Sandiford
  2007-05-09 10:42 ` Eric Botcazou
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Sandiford @ 2007-05-08 19:41 UTC (permalink / raw)
  To: gcc-patches

This patch adds support for SPARC VxWorks.  Hopefully the comments
explain what's going on; let me know if not.

Tested on sparc-wrs-vxworks.  OK to install?

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 124182)
+++ 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 124182)
+++ 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 (rtvec, 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 124182)
+++ 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 124182)
+++ 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,31 @@ 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 PARALLEL call instruction with the contents given by VEC.
+   MEM is the memory reference associated with the call target.  */
+
+void
+sparc_emit_call_insn (rtvec vec, rtx mem)
+{
+  rtx x, insn;
+
+  insn = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+  gcc_assert (MEM_P (mem));
+  if (TARGET_VXWORKS_RTP && flag_pic)
+    {
+      /* The PIC register is live on entry to VxWorks PIC PLT entries.  */
+      x = XEXP (mem, 0);
+      if (GET_CODE (x) == SYMBOL_REF
+	  && (SYMBOL_REF_DECL (x)
+	      ? !targetm.binds_local_p (SYMBOL_REF_DECL (x))
+	      : !SYMBOL_REF_LOCAL_P (x)))
+	{
+	  use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+	  current_function_uses_pic_offset_table = 1;
+	}
+    }
+}
 \f
 /* Return 1 if RTX is a MEM which is known to be aligned to at
    least a DESIRED byte boundary.  */
@@ -7771,13 +7815,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)));
 }
 \f
 /* libfunc renaming.  */
Index: gcc/config/sparc/sparc.md
===================================================================
--- gcc/config/sparc/sparc.md	(revision 124182)
+++ 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" ""))]
@@ -6675,6 +6691,7 @@ (define_expand "call"
   ""
 {
   rtx fn_rtx;
+  rtvec vec;
 
   gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE);
 
@@ -6712,18 +6729,14 @@ (define_expand "call"
 
   /* We accept negative sizes for untyped calls.  */
   if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
-    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)))));
+    vec = gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
+		     operands[3],
+		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
   else
-    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)))));
+    vec = gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
+		     gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
+
+  sparc_emit_call_insn (vec, fn_rtx);
 
  finish_call:
 
@@ -6849,7 +6862,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 (vec, fn_rtx);
 
   DONE;
 })
Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 124182)
+++ 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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-08 19:41 Add support for sparc-wrs-vxworks Richard Sandiford
@ 2007-05-09 10:42 ` Eric Botcazou
  2007-05-09 10:47   ` Richard Sandiford
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Botcazou @ 2007-05-09 10:42 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> 	* config/sparc/sparc.h: Include vxworks-dummy.h.

<grumble>
I see that it's the same for other archs, but this is *really* not pretty:
 1. The preferred mechanism for target includes is tm_file in config.gcc.
 2. This sets a bad precedent for future ports.
</grumble>

> +/* Emit a PARALLEL call instruction with the contents given by VEC.
> +   MEM is the memory reference associated with the call target.  */
> +
> +void
> +sparc_emit_call_insn (rtvec vec, rtx mem)
> +{
> +  rtx x, insn;
> +
> +  insn = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
> +  gcc_assert (MEM_P (mem));
> +  if (TARGET_VXWORKS_RTP && flag_pic)
> +    {
> +      /* The PIC register is live on entry to VxWorks PIC PLT entries.  */
> +      x = XEXP (mem, 0);

Please change the prototype of sparc_emit_call_insn to make it ressemble that 
of emit_call_insn.  And remove the gcc_assert (and merge it with the existing 
gcc_assert in the call and call_value patterns).

> +   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)));
>  }

&& !(TARGET_VXWORKS_RTP
     && flag_pic
     && !targetm.binds_local_p (decl))

OK with these changes.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 10:42 ` Eric Botcazou
@ 2007-05-09 10:47   ` Richard Sandiford
  2007-05-09 10:50     ` Eric Botcazou
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Sandiford @ 2007-05-09 10:47 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@libertysurf.fr> writes:
>> 	* config/sparc/sparc.h: Include vxworks-dummy.h.
>
> <grumble>
> I see that it's the same for other archs, but this is *really* not pretty:
>  1. The preferred mechanism for target includes is tm_file in config.gcc.
>  2. This sets a bad precedent for future ports.
> </grumble>

Well, the current set-up was the result of this thread:

   http://gcc.gnu.org/ml/gcc/2007-03/msg00043.html

where I tried to find out what the preferred approach would be.  I'm
happy to reopen the debate if you don't like it.  It sounds from the
above like you'd prefer all SPARC ports to include vxworks-dummy.h in
tm_file, is that right?

Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 10:47   ` Richard Sandiford
@ 2007-05-09 10:50     ` Eric Botcazou
  2007-05-09 10:55       ` Richard Sandiford
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Botcazou @ 2007-05-09 10:50 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> Well, the current set-up was the result of this thread:
>
>    http://gcc.gnu.org/ml/gcc/2007-03/msg00043.html
>
> where I tried to find out what the preferred approach would be.  I'm
> happy to reopen the debate if you don't like it.

I don't, but it's OK for the sake of consistency.

> It sounds from the above like you'd prefer all SPARC ports to include
> vxworks-dummy.h in tm_file, is that right?

That would probably be worse. :-)

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 10:50     ` Eric Botcazou
@ 2007-05-09 10:55       ` Richard Sandiford
  2007-05-09 11:01         ` Eric Botcazou
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Sandiford @ 2007-05-09 10:55 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@libertysurf.fr> writes:
>> Well, the current set-up was the result of this thread:
>>
>>    http://gcc.gnu.org/ml/gcc/2007-03/msg00043.html
>>
>> where I tried to find out what the preferred approach would be.  I'm
>> happy to reopen the debate if you don't like it.
>
> I don't, but it's OK for the sake of consistency.

What would you prefer though, if there wasn't existing precedent?
I'm happy to go back and do the other ports in a cleaner way as long
as I know what the cleaner way is.

>> It sounds from the above like you'd prefer all SPARC ports to include
>> vxworks-dummy.h in tm_file, is that right?
>
> That would probably be worse. :-)

OK. ;)

Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 10:55       ` Richard Sandiford
@ 2007-05-09 11:01         ` Eric Botcazou
  2007-05-09 11:04           ` Richard Sandiford
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Botcazou @ 2007-05-09 11:01 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> What would you prefer though, if there wasn't existing precedent?
> I'm happy to go back and do the other ports in a cleaner way as long
> as I know what the cleaner way is.

Never mind, there doesn't seem to be an obvious cleaner way to do it. :-)

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 11:01         ` Eric Botcazou
@ 2007-05-09 11:04           ` Richard Sandiford
  2007-05-09 13:13             ` Eric Botcazou
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Sandiford @ 2007-05-09 11:04 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@libertysurf.fr> writes:
>> What would you prefer though, if there wasn't existing precedent?
>> I'm happy to go back and do the other ports in a cleaner way as long
>> as I know what the cleaner way is.
>
> Never mind, there doesn't seem to be an obvious cleaner way to do it. :-)

OK, thanks.  (An ugly problem with only ugly solutions. ;))  I'll make
the changes you asked for and retest.

Richard

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 11:04           ` Richard Sandiford
@ 2007-05-09 13:13             ` Eric Botcazou
  2007-05-09 13:27               ` Eric Botcazou
  2007-05-10  8:02               ` Richard Sandiford
  0 siblings, 2 replies; 12+ messages in thread
From: Eric Botcazou @ 2007-05-09 13:13 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> OK, thanks.  (An ugly problem with only ugly solutions. ;))  I'll make
> the changes you asked for and retest.

Thanks.  Just to clarify a little: I think the prototype should be

extern void sparc_emit_call_insn (rtx, rtx);

when the first parameter can be directly passed to emit_call_insn.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 13:13             ` Eric Botcazou
@ 2007-05-09 13:27               ` Eric Botcazou
  2007-05-10  8:02               ` Richard Sandiford
  1 sibling, 0 replies; 12+ messages in thread
From: Eric Botcazou @ 2007-05-09 13:27 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> when the first parameter can be directly passed to emit_call_insn.

...where the first...

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-09 13:13             ` Eric Botcazou
  2007-05-09 13:27               ` Eric Botcazou
@ 2007-05-10  8:02               ` Richard Sandiford
  2007-05-10 10:45                 ` Eric Botcazou
  1 sibling, 1 reply; 12+ messages in thread
From: Richard Sandiford @ 2007-05-10  8:02 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Eric Botcazou <ebotcazou@libertysurf.fr> writes:
>> OK, thanks.  (An ugly problem with only ugly solutions. ;))  I'll make
>> the changes you asked for and retest.
>
> Thanks.  Just to clarify a little: I think the prototype should be
>
> extern void sparc_emit_call_insn (rtx, rtx);
>
> when the first parameter can be directly passed to emit_call_insn.

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.

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;
+    }
+}
 \f
 /* 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)));
 }
 \f
 /* 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,6 +6692,7 @@ (define_expand "call"
 {
   rtx fn_rtx;
 
+  gcc_assert (MEM_P (operands[0]));
   gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE);
 
   gcc_assert (GET_CODE (operands[3]) == CONST_INT);
@@ -6712,18 +6729,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,6 +6859,7 @@ (define_expand "call_value"
   rtx fn_rtx;
   rtvec vec;
 
+  gcc_assert (MEM_P (operands[1]));
   gcc_assert (GET_MODE (operands[1]) == FUNCTION_MODE);
 
   fn_rtx = operands[1];
@@ -6849,7 +6869,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

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-10  8:02               ` Richard Sandiford
@ 2007-05-10 10:45                 ` Eric Botcazou
  2007-05-10 11:16                   ` Richard Sandiford
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Botcazou @ 2007-05-10 10:45 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: gcc-patches

> 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).  Thanks.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Add support for sparc-wrs-vxworks
  2007-05-10 10:45                 ` Eric Botcazou
@ 2007-05-10 11:16                   ` Richard Sandiford
  0 siblings, 0 replies; 12+ messages in thread
From: Richard Sandiford @ 2007-05-10 11:16 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

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;
+    }
+}
 \f
 /* 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)));
 }
 \f
 /* 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

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-05-10 11:16 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-05-08 19:41 Add support for sparc-wrs-vxworks Richard Sandiford
2007-05-09 10:42 ` Eric Botcazou
2007-05-09 10:47   ` Richard Sandiford
2007-05-09 10:50     ` Eric Botcazou
2007-05-09 10:55       ` Richard Sandiford
2007-05-09 11:01         ` Eric Botcazou
2007-05-09 11:04           ` Richard Sandiford
2007-05-09 13:13             ` Eric Botcazou
2007-05-09 13:27               ` Eric Botcazou
2007-05-10  8:02               ` Richard Sandiford
2007-05-10 10:45                 ` Eric Botcazou
2007-05-10 11:16                   ` Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).