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]

Update the ARM VxWorks port, and add RTP support


This patch fixes some bitrot in the ARM VxWorks port; it won't even
compile at the moment because of an outdated arm_is_xscale (rather than
arm_arch_xscale) check.  The patch also adds RTP and StrongARM support.

PIC PLTs rely on the PIC register, so I split the code that creates it
out into a separate function (require_pic_register).  The code is taken
verbatim from legitimize_pic_address.

The GOT initialization sequence is very different for VxWorks.
The patch adds a special case for it and reindents the rest.
The reindented code is the same as before, except that pic_reg
is used a shorthand for cfun->machine->pic_reg in order to avoid
breaking up too many lines.

The other changes are on the same lines as those for other VxWorks ports,
and hopefully the comments explain what is going on in enough detail.
Please let me know if not.

Tested on arm-eabi and arm-wrs-vxworks.  OK to install?

Richard


gcc/
gcc/
	* config.gcc (arm-wrs-vxworks): Remove dbxelf.h from tm_file.
	Add vx-common.h.  Include vxworks.h between vx-common.h and
	arm/vxworks.h.
	* config/vx-common.h (DWARF2_UNWIND_INFO): Undefine before
	redefining.
	* config/vxworks.h (TARGET_ASM_CONSTRUCTOR): Likewise.
	(TARGET_ASM_DESTRUCTOR): Likewise.
	* config/arm/vxworks.h (TARGET_OS_CPP_BUILTINS): Check arm_arch_xscale
	instead of arm_is_xscale.  Use VXWORKS_OS_CPP_BUILTINS.
	(OVERRIDE_OPTIONS, SUBTARGET_CPP_SPEC): Define.
	(CC1_SPEC): Add -tstrongarm.  Line up backslashes.
	(VXWORKS_ENDIAN_SPEC): Define.
	(ASM_SPEC): Add VXWORKS_ENDIAN_SPEC.
	(LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Redefine to their
	VXWORKS_* equivalents.
	(LINK_SPEC): Likewise, but add VXWORKS_ENDIAN_SPEC.
	(ASM_FILE_START): Delete.
	(TARGET_VERSION): Reformat.
	(FPUTYPE_DEFAULT, FUNCTION_PROFILER): Define.
	(DEFAULT_STRUCTURE_SIZE_BOUNDARY): Define.
	* config/arm/t-vxworks (LIB1ASMSRC, LIB1ASMFUNCS): Define.
	(FPBIT, DPBIT): Define.
	(fp-bit.c, dp-bit.c): New rules.
	(MULTILIB_OPTIONS): Add strongarm, -mrtp and -mrtp/-fPIC multilibs.
	(MULTILIB_MATCHES, MULTILIB_EXCEPTIONS): Define.
	* config/arm/arm-protos.h (arm_emit_call_insn): Declare.
	* config/arm/arm.h: Include vxworks-dummy.h.
	* config/arm/arm.c (arm_elf_asm_constructor, arm_elf_asm_destructor):
	Mark with ATTRIBUTE_UNUSED.
	(arm_override_options): Do not allow VxWorks RTP PIC to be used
	for Thumb.  Force r9 to be the PIC register for VxWorks RTPs and
	make it incompatible with -msingle-pic-base.
	(arm_function_ok_for_sibcall): Return false for calls that might
	go through a VxWorks PIC PLT entry.
	(require_pic_register): New function, split out from...
	(legitimize_pic_address): ...here.  Do not use GOTOFF accesses
	for VxWorks RTPs.
	(arm_load_pic_register): Handle the VxWorks RTP initialization
	sequence.  Use pic_reg as a shorthand for cfun->machine->pic_reg.
	(arm_emit_call_insn): New function.
	(arm_assemble_integer): Do not use GOTOFF accesses for VxWorks RTP.
	* config/arm/arm.md (UNSPEC_PIC_OFFSET): New unspec number.
	(pic_offset_arm): New pattern.
	(call, call_value): Use arm_emit_call_insn.
	(call_internal, call_value_internal): New expanders.
	* config/arm/lib1funcs.asm (__PLT__): Define to empty for
	VxWorks unless __PIC__.

Index: gcc/config.gcc
===================================================================
*** gcc/config.gcc	2007-05-23 04:27:24.000000000 -0700
--- gcc/config.gcc	2007-05-24 04:06:24.000000000 -0700
*************** arm-semi-aof | armel-semi-aof)
*** 697,703 ****
  	tmake_file="arm/t-arm arm/t-semi"
  	;;
  arm-wrs-vxworks)
! 	tm_file="dbxelf.h elfos.h svr4.h vxworks.h arm/elf.h arm/aout.h ${tm_file} arm/vxworks.h"
  	tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
  	;;
  arm*-*-freebsd*|strongarm*-*-freebsd*)
--- 697,703 ----
  	tmake_file="arm/t-arm arm/t-semi"
  	;;
  arm-wrs-vxworks)
! 	tm_file="elfos.h svr4.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
  	tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
  	;;
  arm*-*-freebsd*|strongarm*-*-freebsd*)
Index: gcc/config/vx-common.h
===================================================================
*** gcc/config/vx-common.h	2007-05-18 08:35:10.000000000 -0700
--- gcc/config/vx-common.h	2007-05-24 04:06:24.000000000 -0700
*************** #define WINT_TYPE "short unsigned int"
*** 63,68 ****
--- 63,69 ----
  #define WINT_TYPE_SIZE 16
  
  /* Dwarf2 unwind info is not supported.  */
+ #undef DWARF2_UNWIND_INFO
  #define DWARF2_UNWIND_INFO 0
  
  /* VxWorks uses DWARF2.  */
Index: gcc/config/vxworks.h
===================================================================
*** gcc/config/vxworks.h	2007-05-18 08:35:10.000000000 -0700
--- gcc/config/vxworks.h	2007-05-24 04:06:24.000000000 -0700
*************** #define SUPPORTS_INIT_PRIORITY TARGET_VX
*** 92,98 ****
--- 92,100 ----
  
  /* VxWorks requires special handling of constructors and destructors.
     All VxWorks configurations must use these functions.  */
+ #undef TARGET_ASM_CONSTRUCTOR
  #define TARGET_ASM_CONSTRUCTOR vxworks_asm_out_constructor
+ #undef TARGET_ASM_DESTRUCTOR
  #define TARGET_ASM_DESTRUCTOR vxworks_asm_out_destructor
  extern void vxworks_asm_out_constructor (rtx symbol, int priority);
  extern void vxworks_asm_out_destructor (rtx symbol, int priority);
Index: gcc/config/arm/vxworks.h
===================================================================
*** gcc/config/arm/vxworks.h	2007-05-18 08:35:03.000000000 -0700
--- gcc/config/arm/vxworks.h	2007-05-24 04:06:24.000000000 -0700
*************** the Free Software Foundation; either ver
*** 25,37 ****
  
  #define TARGET_OS_CPP_BUILTINS()		\
    do {						\
-     builtin_define ("__vxworks");		\
      if (TARGET_BIG_END)				\
        builtin_define ("ARMEB");			\
      else					\
        builtin_define ("ARMEL");			\
  						\
!     if (arm_is_xscale)				\
        builtin_define ("CPU=XSCALE");		\
      else if (arm_arch5)				\
        builtin_define ("CPU=ARMARCH5");		\
--- 25,36 ----
  
  #define TARGET_OS_CPP_BUILTINS()		\
    do {						\
      if (TARGET_BIG_END)				\
        builtin_define ("ARMEB");			\
      else					\
        builtin_define ("ARMEL");			\
  						\
!     if (arm_arch_xscale)			\
        builtin_define ("CPU=XSCALE");		\
      else if (arm_arch5)				\
        builtin_define ("CPU=ARMARCH5");		\
*************** #define TARGET_OS_CPP_BUILTINS()		\
*** 42,95 ****
  	else					\
  	  builtin_define ("CPU=ARMARCH4");	\
        }						\
    } while (0)
  
  #undef  CC1_SPEC
  #define CC1_SPEC							\
! "%{t4:        -mlittle-endian -march=armv4 ;			\
!    t4be:      -mbig-endian -march=armv4 ;			\
     t4t:       -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ;	\
     t4tbe:     -mthumb -mthumb-interwork -mbig-endian -march=armv4t ;	\
!    t5:        -mlittle-endian -march=armv5 ;			\
!    t5be:      -mbig-endian -march=armv5 ;			\
     t5t:       -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ;	\
     t5tbe:     -mthumb -mthumb-interwork -mbig-endian -march=armv5 ;	\
!    txscale:   -mlittle-endian -mcpu=xscale ;			\
!    txscalebe: -mbig-endian -mcpu=xscale ;			\
              : -march=armv4}"
  
  /* The -Q options from svr4.h aren't understood and must be removed.  */
  #undef  ASM_SPEC
  #define ASM_SPEC \
!   "%{v:-V} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
  
! /* VxWorks does all the library stuff itself.  */
! #undef  LIB_SPEC
! #define LIB_SPEC 	""
! 
! /* VxWorks uses object files, not loadable images.  make linker just
!    combine objects.  */
! #undef  LINK_SPEC
! #define LINK_SPEC 	"-r"
! 
! /* VxWorks provides the functionality of crt0.o and friends itself.  */
! #undef  STARTFILE_SPEC
! #define STARTFILE_SPEC 	""
  
! #undef  ENDFILE_SPEC
! #define ENDFILE_SPEC 	""
  
! #undef  TARGET_VERSION
! #define TARGET_VERSION	fputs (" (ARM/VxWorks)", stderr);
  
  /* There is no default multilib.  */
  #undef MULTILIB_DEFAULTS
  
! #undef  ASM_FILE_START
! #define ASM_FILE_START(STREAM) 						\
!   do 									\
!     {									\
!       fprintf (STREAM, "%s Generated by GCC %s for ARM/VxWorks\n",	\
! 	       ASM_COMMENT_START, version_string);			\
!     }									\
!   while (0)
--- 41,110 ----
  	else					\
  	  builtin_define ("CPU=ARMARCH4");	\
        }						\
+     VXWORKS_OS_CPP_BUILTINS ();			\
    } while (0)
  
+ #undef OVERRIDE_OPTIONS
+ #define OVERRIDE_OPTIONS			\
+   do						\
+     {						\
+       VXWORKS_OVERRIDE_OPTIONS;			\
+       arm_override_options ();			\
+     }						\
+   while (0)
+ 
+ /* Subsume the arm/elf.h definition, and add RTP hooks.  */
+ #undef SUBTARGET_CPP_SPEC
+ #define SUBTARGET_CPP_SPEC "-D__ELF__" VXWORKS_ADDITIONAL_CPP_SPEC
+ 
  #undef  CC1_SPEC
  #define CC1_SPEC							\
! "%{tstrongarm:-mlittle-endian -mcpu=strongarm ;				\
!    t4:        -mlittle-endian -march=armv4 ;				\
!    t4be:      -mbig-endian -march=armv4 ;				\
     t4t:       -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ;	\
     t4tbe:     -mthumb -mthumb-interwork -mbig-endian -march=armv4t ;	\
!    t5:        -mlittle-endian -march=armv5 ;				\
!    t5be:      -mbig-endian -march=armv5 ;				\
     t5t:       -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ;	\
     t5tbe:     -mthumb -mthumb-interwork -mbig-endian -march=armv5 ;	\
!    txscale:   -mlittle-endian -mcpu=xscale ;				\
!    txscalebe: -mbig-endian -mcpu=xscale ;				\
              : -march=armv4}"
  
+ /* Pass -EB for big-endian targets.  */
+ #define VXWORKS_ENDIAN_SPEC \
+   "%{mbig-endian|t4be|t4tbe|t5be|t5tbe|txscalebe:-EB}"
+ 
  /* The -Q options from svr4.h aren't understood and must be removed.  */
  #undef  ASM_SPEC
  #define ASM_SPEC \
!   "%{v:-V} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} " VXWORKS_ENDIAN_SPEC
! 
! #undef LINK_SPEC
! #define LINK_SPEC VXWORKS_LINK_SPEC " " VXWORKS_ENDIAN_SPEC
  
! #undef LIB_SPEC
! #define LIB_SPEC VXWORKS_LIB_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 (" (ARM/VxWorks)", stderr);
  
  /* There is no default multilib.  */
  #undef MULTILIB_DEFAULTS
  
! #define FPUTYPE_DEFAULT FPUTYPE_VFP
! 
! #undef FUNCTION_PROFILER
! #define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER
! 
! /* We want to be compatible with a version of "2.96" at one point in
!    the past before this macro was changed.  */
! #undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
! #define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
Index: gcc/config/arm/t-vxworks
===================================================================
*** gcc/config/arm/t-vxworks	2007-05-18 08:35:03.000000000 -0700
--- gcc/config/arm/t-vxworks	2007-05-24 04:06:24.000000000 -0700
***************
*** 1,10 ****
! # Multilibs for VxWorks.
  
! MULTILIB_OPTIONS = \
!   t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/txscale/txscalebe
  
! MULTILIB_DIRNAMES = \
!   ARMARCH4gnu ARMARCH4gnube ARMARCH4_Tgnu ARMARCH4_Tgnube \
!   ARMARCH5gnu ARMARCH5gnube ARMARCH5_Tgnu ARMARCH5_Tgnube \
!   XSCALEgnu XSCALEgnube
  
--- 1,27 ----
! LIB1ASMSRC = arm/lib1funcs.asm
! LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX
  
! # We want fine grained libraries, so use the new code to build the
! # floating point emulation libraries.
! FPBIT = fp-bit.c
! DPBIT = dp-bit.c
! 
! fp-bit.c: $(srcdir)/config/fp-bit.c
! 	echo '#define FLOAT' > fp-bit.c
! 	echo '#ifndef __ARMEB__' >> fp-bit.c
! 	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
! 	echo '#endif' >> fp-bit.c
! 	cat $(srcdir)/config/fp-bit.c >> fp-bit.c
  
! dp-bit.c: $(srcdir)/config/fp-bit.c
! 	echo '#ifndef __ARMEB__' > dp-bit.c
! 	echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
! 	echo '#endif' >> dp-bit.c
! 	cat $(srcdir)/config/fp-bit.c >> dp-bit.c
  
+ MULTILIB_OPTIONS = \
+   mrtp fPIC \
+   t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/tstrongarm/txscale/txscalebe
+ MULTILIB_MATCHES = fPIC=fpic
+ # Don't build -fPIC multilibs for kernel or Thumb code.
+ MULTILIB_EXCEPTIONS = fPIC* mrtp/fPIC/*t[45]t*
Index: gcc/config/arm/arm-protos.h
===================================================================
*** gcc/config/arm/arm-protos.h	2007-05-24 04:01:54.000000000 -0700
--- gcc/config/arm/arm-protos.h	2007-05-24 04:06:24.000000000 -0700
*************** extern void arm_reload_out_hi (rtx *);
*** 102,107 ****
--- 102,108 ----
  extern int arm_const_double_inline_cost (rtx);
  extern bool arm_const_double_by_parts (rtx);
  extern const char *fp_immediate_constant (rtx);
+ extern void arm_emit_call_insn (rtx, rtx);
  extern const char *output_call (rtx *);
  extern const char *output_call_mem (rtx *);
  extern const char *output_mov_long_double_fpa_from_arm (rtx *);
Index: gcc/config/arm/arm.h
===================================================================
*** gcc/config/arm/arm.h	2007-05-24 04:01:54.000000000 -0700
--- gcc/config/arm/arm.h	2007-05-24 04:06:24.000000000 -0700
***************
*** 26,31 ****
--- 26,33 ----
  #ifndef GCC_ARM_H
  #define GCC_ARM_H
  
+ #include "config/vxworks-dummy.h"
+ 
  /* The architecture define.  */
  extern char arm_arch_name[];
  
Index: gcc/config/arm/arm.c
===================================================================
*** gcc/config/arm/arm.c	2007-05-24 04:01:54.000000000 -0700
--- gcc/config/arm/arm.c	2007-05-24 04:07:09.000000000 -0700
*************** static int arm_arg_partial_bytes (CUMULA
*** 148,155 ****
  				  tree, bool);
  
  #ifdef OBJECT_FORMAT_ELF
! static void arm_elf_asm_constructor (rtx, int);
! static void arm_elf_asm_destructor (rtx, int);
  #endif
  #ifndef ARM_PE
  static void arm_encode_section_info (tree, rtx, int);
--- 148,155 ----
  				  tree, bool);
  
  #ifdef OBJECT_FORMAT_ELF
! static void arm_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED;
! static void arm_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED;
  #endif
  #ifndef ARM_PE
  static void arm_encode_section_info (tree, rtx, int);
*************** arm_override_options (void)
*** 1338,1347 ****
  		 ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
      }
  
    /* If stack checking is disabled, we can use r10 as the PIC register,
       which keeps r9 available.  The EABI specifies r9 as the PIC register.  */
    if (flag_pic && TARGET_SINGLE_PIC_BASE)
!     arm_pic_register = (TARGET_APCS_STACK || TARGET_AAPCS_BASED) ? 9 : 10;
  
    if (arm_pic_register_string != NULL)
      {
--- 1338,1360 ----
  		 ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
      }
  
+   if (!TARGET_ARM && TARGET_VXWORKS_RTP && flag_pic)
+     {
+       error ("RTP PIC is incompatible with Thumb");
+       flag_pic = 0;
+     }
+ 
    /* If stack checking is disabled, we can use r10 as the PIC register,
       which keeps r9 available.  The EABI specifies r9 as the PIC register.  */
    if (flag_pic && TARGET_SINGLE_PIC_BASE)
!     {
!       if (TARGET_VXWORKS_RTP)
! 	warning (0, "RTP PIC is incompatible with -msingle-pic-base");
!       arm_pic_register = (TARGET_APCS_STACK || TARGET_AAPCS_BASED) ? 9 : 10;
!     }
! 
!   if (flag_pic && TARGET_VXWORKS_RTP)
!     arm_pic_register = 9;
  
    if (arm_pic_register_string != NULL)
      {
*************** arm_override_options (void)
*** 1354,1360 ****
        else if (pic_register < 0 || call_used_regs[pic_register]
  	       || pic_register == HARD_FRAME_POINTER_REGNUM
  	       || pic_register == STACK_POINTER_REGNUM
! 	       || pic_register >= PC_REGNUM)
  	error ("unable to use '%s' for PIC register", arm_pic_register_string);
        else
  	arm_pic_register = pic_register;
--- 1367,1375 ----
        else if (pic_register < 0 || call_used_regs[pic_register]
  	       || pic_register == HARD_FRAME_POINTER_REGNUM
  	       || pic_register == STACK_POINTER_REGNUM
! 	       || pic_register >= PC_REGNUM
! 	       || (TARGET_VXWORKS_RTP
! 		   && (unsigned int) pic_register != arm_pic_register))
  	error ("unable to use '%s' for PIC register", arm_pic_register_string);
        else
  	arm_pic_register = pic_register;
*************** arm_function_ok_for_sibcall (tree decl, 
*** 3214,3219 ****
--- 3229,3239 ----
    if (decl == NULL || TARGET_THUMB)
      return false;
  
+   /* The PIC register is live on entry to VxWorks PLT entries, so we
+      must make the call before restoring the PIC register.  */
+   if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl))
+     return false;
+ 
    /* Cannot tail-call to long calls, since these are out of range of
       a branch instruction.  */
    if (arm_is_long_call_p (decl))
*************** legitimate_pic_operand_p (rtx x)
*** 3255,3260 ****
--- 3275,3328 ----
    return 1;
  }
  
+ /* Record that the current function needs a PIC register.  Initialize
+    cfun->machine->pic_reg if we have not already done so.  */
+ 
+ static void
+ require_pic_register (void)
+ {
+   /* A lot of the logic here is made obscure by the fact that this
+      routine gets called as part of the rtx cost estimation process.
+      We don't want those calls to affect any assumptions about the real
+      function; and further, we can't call entry_of_function() until we
+      start the real expansion process.  */
+   if (!current_function_uses_pic_offset_table)
+     {
+       gcc_assert (!no_new_pseudos);
+       if (arm_pic_register != INVALID_REGNUM)
+ 	{
+ 	  cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
+ 
+ 	  /* Play games to avoid marking the function as needing pic
+ 	     if we are being called as part of the cost-estimation
+ 	     process.  */
+ 	  if (current_ir_type () != IR_GIMPLE)
+ 	    current_function_uses_pic_offset_table = 1;
+ 	}
+       else
+ 	{
+ 	  rtx seq;
+ 
+ 	  cfun->machine->pic_reg = gen_reg_rtx (Pmode);
+ 
+ 	  /* Play games to avoid marking the function as needing pic
+ 	     if we are being called as part of the cost-estimation
+ 	     process.  */
+ 	  if (current_ir_type () != IR_GIMPLE)
+ 	    {
+ 	      current_function_uses_pic_offset_table = 1;
+ 	      start_sequence ();
+ 
+ 	      arm_load_pic_register (0UL);
+ 
+ 	      seq = get_insns ();
+ 	      end_sequence ();
+ 	      emit_insn_after (seq, entry_of_function ());
+ 	    }
+ 	}
+     }
+ }
+ 
  rtx
  legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
  {
*************** legitimize_pic_address (rtx orig, enum m
*** 3267,3314 ****
        rtx insn;
        int subregs = 0;
  
!       /* If this function doesn't have a pic register, create one now.
! 	 A lot of the logic here is made obscure by the fact that this
! 	 routine gets called as part of the rtx cost estimation
! 	 process.  We don't want those calls to affect any assumptions
! 	 about the real function; and further, we can't call
! 	 entry_of_function() until we start the real expansion
! 	 process.  */
!       if (!current_function_uses_pic_offset_table)
! 	{
! 	  gcc_assert (!no_new_pseudos);
! 	  if (arm_pic_register != INVALID_REGNUM)
! 	    {
! 	      cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
! 
! 	      /* Play games to avoid marking the function as needing pic
! 		 if we are being called as part of the cost-estimation
! 		 process.  */
! 	      if (current_ir_type () != IR_GIMPLE)
! 		current_function_uses_pic_offset_table = 1;
! 	    }
! 	  else
! 	    {
! 	      rtx seq;
! 
! 	      cfun->machine->pic_reg = gen_reg_rtx (Pmode);
! 
! 	      /* Play games to avoid marking the function as needing pic
! 		 if we are being called as part of the cost-estimation
! 		 process.  */
! 	      if (current_ir_type () != IR_GIMPLE)
! 		{
! 		  current_function_uses_pic_offset_table = 1;
! 		  start_sequence ();
! 
! 		  arm_load_pic_register (0UL);
! 
! 		  seq = get_insns ();
! 		  end_sequence ();
! 		  emit_insn_after (seq, entry_of_function ());
! 		}
! 	    }
! 	}
  
        if (reg == 0)
  	{
--- 3335,3342 ----
        rtx insn;
        int subregs = 0;
  
!       /* If this function doesn't have a pic register, create one now.  */
!       require_pic_register ();
  
        if (reg == 0)
  	{
*************** legitimize_pic_address (rtx orig, enum m
*** 3335,3344 ****
        else /* TARGET_THUMB1 */
  	emit_insn (gen_pic_load_addr_thumb1 (address, orig));
  
        if ((GET_CODE (orig) == LABEL_REF
  	   || (GET_CODE (orig) == SYMBOL_REF &&
  	       SYMBOL_REF_LOCAL_P (orig)))
! 	  && NEED_GOT_RELOC)
  	pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
        else
  	{
--- 3363,3379 ----
        else /* TARGET_THUMB1 */
  	emit_insn (gen_pic_load_addr_thumb1 (address, orig));
  
+       /* 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
+ 	 use GOTOFF unless we are absolutely sure that the symbol 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 GOTOFF is never valid on VxWorks.  */
        if ((GET_CODE (orig) == LABEL_REF
  	   || (GET_CODE (orig) == SYMBOL_REF &&
  	       SYMBOL_REF_LOCAL_P (orig)))
! 	  && NEED_GOT_RELOC
! 	  && !TARGET_VXWORKS_RTP)
  	pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
        else
  	{
*************** static GTY(()) int pic_labelno;
*** 3478,3484 ****
  arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
  {
  #ifndef AOF_ASSEMBLER
!   rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx;
    rtx global_offset_table;
  
    if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
--- 3513,3519 ----
  arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
  {
  #ifndef AOF_ASSEMBLER
!   rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx, pic_reg;
    rtx global_offset_table;
  
    if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
*************** arm_load_pic_register (unsigned long sav
*** 3486,3557 ****
  
    gcc_assert (flag_pic);
  
!   /* We use an UNSPEC rather than a LABEL_REF because this label never appears
!      in the code stream.  */
  
!   labelno = GEN_INT (pic_labelno++);
!   l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
!   l1 = gen_rtx_CONST (VOIDmode, l1);
  
!   global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
!   /* On the ARM the PC register contains 'dot + 8' at the time of the
!      addition, on the Thumb it is 'dot + 4'.  */
!   pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
!   if (GOT_PCREL)
!     pic_tmp2 = gen_rtx_CONST (VOIDmode,
! 			    gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
    else
!     pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
  
!   pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
  
!   if (TARGET_ARM)
!     {
!       emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx));
!       emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg,
! 					     cfun->machine->pic_reg, labelno));
!     }
!   else if (TARGET_THUMB2)
!     {
!       /* Thumb-2 only allows very limited access to the PC.  Calculate the
! 	 address in a temporary register.  */
!       if (arm_pic_register != INVALID_REGNUM)
  	{
! 	  pic_tmp = gen_rtx_REG (SImode,
! 				 thumb_find_work_register (saved_regs));
  	}
        else
  	{
! 	  gcc_assert (!no_new_pseudos);
! 	  pic_tmp = gen_reg_rtx (Pmode);
  	}
  
!       emit_insn (gen_pic_load_addr_thumb2 (cfun->machine->pic_reg, pic_rtx));
!       emit_insn (gen_pic_load_dot_plus_four (pic_tmp, labelno));
!       emit_insn (gen_addsi3(cfun->machine->pic_reg, cfun->machine->pic_reg,
! 			    pic_tmp));
!     }
!   else /* TARGET_THUMB1 */
!     {
!       if (arm_pic_register != INVALID_REGNUM
! 	  && REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM)
  	{
! 	  /* We will have pushed the pic register, so we should always be
! 	     able to find a work register.  */
! 	  pic_tmp = gen_rtx_REG (SImode,
! 				 thumb_find_work_register (saved_regs));
! 	  emit_insn (gen_pic_load_addr_thumb1 (pic_tmp, pic_rtx));
! 	  emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
  	}
-       else
- 	emit_insn (gen_pic_load_addr_thumb1 (cfun->machine->pic_reg, pic_rtx));
-       emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg,
- 					    cfun->machine->pic_reg, labelno));
      }
  
    /* Need to emit this whether or not we obey regdecls,
       since setjmp/longjmp can cause life info to screw up.  */
!   emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg));
  #endif /* AOF_ASSEMBLER */
  }
  
--- 3521,3608 ----
  
    gcc_assert (flag_pic);
  
!   pic_reg = cfun->machine->pic_reg;
!   if (TARGET_VXWORKS_RTP)
!     {
!       pic_rtx = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
!       pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
!       emit_insn (gen_pic_load_addr_arm (pic_reg, pic_rtx));
  
!       emit_insn (gen_rtx_SET (Pmode, pic_reg, gen_rtx_MEM (Pmode, pic_reg)));
  
!       pic_tmp = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
!       emit_insn (gen_pic_offset_arm (pic_reg, pic_reg, pic_tmp));
!     }
    else
!     {
!       /* We use an UNSPEC rather than a LABEL_REF because this label
! 	 never appears in the code stream.  */
  
!       labelno = GEN_INT (pic_labelno++);
!       l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
!       l1 = gen_rtx_CONST (VOIDmode, l1);
  
!       global_offset_table
! 	= gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
!       /* On the ARM the PC register contains 'dot + 8' at the time of the
! 	 addition, on the Thumb it is 'dot + 4'.  */
!       pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
!       if (GOT_PCREL)
  	{
! 	  pic_tmp2 = gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx);
! 	  pic_tmp2 = gen_rtx_CONST (VOIDmode, pic_tmp2);
  	}
        else
+ 	pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
+ 
+       pic_rtx = gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp);
+       pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
+ 
+       if (TARGET_ARM)
  	{
! 	  emit_insn (gen_pic_load_addr_arm (pic_reg, pic_rtx));
! 	  emit_insn (gen_pic_add_dot_plus_eight (pic_reg, pic_reg, labelno));
  	}
+       else if (TARGET_THUMB2)
+ 	{
+ 	  /* Thumb-2 only allows very limited access to the PC.  Calculate the
+ 	     address in a temporary register.  */
+ 	  if (arm_pic_register != INVALID_REGNUM)
+ 	    {
+ 	      pic_tmp = gen_rtx_REG (SImode,
+ 				     thumb_find_work_register (saved_regs));
+ 	    }
+ 	  else
+ 	    {
+ 	      gcc_assert (!no_new_pseudos);
+ 	      pic_tmp = gen_reg_rtx (Pmode);
+ 	    }
  
! 	  emit_insn (gen_pic_load_addr_thumb2 (pic_reg, pic_rtx));
! 	  emit_insn (gen_pic_load_dot_plus_four (pic_tmp, labelno));
! 	  emit_insn (gen_addsi3 (pic_reg, pic_reg, pic_tmp));
! 	}
!       else /* TARGET_THUMB1 */
  	{
! 	  if (arm_pic_register != INVALID_REGNUM
! 	      && REGNO (pic_reg) > LAST_LO_REGNUM)
! 	    {
! 	      /* We will have pushed the pic register, so we should always be
! 		 able to find a work register.  */
! 	      pic_tmp = gen_rtx_REG (SImode,
! 				     thumb_find_work_register (saved_regs));
! 	      emit_insn (gen_pic_load_addr_thumb1 (pic_tmp, pic_rtx));
! 	      emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
! 	    }
! 	  else
! 	    emit_insn (gen_pic_load_addr_thumb1 (pic_reg, pic_rtx));
! 	  emit_insn (gen_pic_add_dot_plus_four (pic_reg, pic_reg, labelno));
  	}
      }
  
    /* Need to emit this whether or not we obey regdecls,
       since setjmp/longjmp can cause life info to screw up.  */
!   emit_insn (gen_rtx_USE (VOIDmode, pic_reg));
  #endif /* AOF_ASSEMBLER */
  }
  
*************** vfp_emit_fstmd (int base_reg, int count)
*** 8862,8867 ****
--- 8913,8942 ----
    return count * 8;
  }
  
+ /* Emit a call instruction with pattern PAT.  ADDR is the address of
+    the call target.  */
+ 
+ void
+ arm_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 the call might use such an entry, add a use of the PIC register
+      to the instruction's CALL_INSN_FUNCTION_USAGE.  */
+   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)))
+     {
+       require_pic_register ();
+       use_reg (&CALL_INSN_FUNCTION_USAGE (insn), cfun->machine->pic_reg);
+     }
+ }
  
  /* Output a 'call' insn.  */
  const char *
*************** arm_assemble_integer (rtx x, unsigned in
*** 11947,11960 ****
        if (NEED_GOT_RELOC && flag_pic && making_const_table &&
  	  (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
  	{
! 	  if (GET_CODE (x) == SYMBOL_REF
! 	      && (CONSTANT_POOL_ADDRESS_P (x)
! 		  || SYMBOL_REF_LOCAL_P (x)))
! 	    fputs ("(GOTOFF)", asm_out_file);
! 	  else if (GET_CODE (x) == LABEL_REF)
! 	    fputs ("(GOTOFF)", asm_out_file);
! 	  else
  	    fputs ("(GOT)", asm_out_file);
  	}
        fputc ('\n', asm_out_file);
        return true;
--- 12022,12034 ----
        if (NEED_GOT_RELOC && flag_pic && making_const_table &&
  	  (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
  	{
! 	  /* See legitimize_pic_address for an explanation of the
! 	     TARGET_VXWORKS_RTP check.  */
! 	  if (TARGET_VXWORKS_RTP
! 	      || (GET_CODE (x) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (x)))
  	    fputs ("(GOT)", asm_out_file);
+ 	  else
+ 	    fputs ("(GOTOFF)", asm_out_file);
  	}
        fputc ('\n', asm_out_file);
        return true;
Index: gcc/config/arm/arm.md
===================================================================
*** gcc/config/arm/arm.md	2007-05-24 04:01:54.000000000 -0700
--- gcc/config/arm/arm.md	2007-05-24 04:07:47.000000000 -0700
*************** (define_constants
*** 95,100 ****
--- 95,102 ----
                           ; instruction stream.
     (UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer.  Used to
  			   ; generate correct unwind information.
+    (UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
+ 			  ; correctly for PIC usage.
    ]
  )
  
*************** (define_peephole2
*** 4919,4924 ****
--- 4921,4936 ----
    ""
  )
  
+ (define_insn "pic_offset_arm"
+   [(set (match_operand:SI 0 "register_operand" "=r")
+ 	(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ 			 (unspec:SI [(match_operand:SI 2 "" "X")]
+ 				    UNSPEC_PIC_OFFSET))))]
+   "TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
+   "ldr%?\\t%0, [%1,%2]"
+   [(set_attr "type" "load1")]
+ )
+ 
  (define_expand "builtin_setjmp_receiver"
    [(label_ref (match_operand 0 "" ""))]
    "flag_pic"
*************** (define_expand "call"
*** 8145,8151 ****
    "TARGET_EITHER"
    "
    {
!     rtx callee;
      
      /* In an untyped call, we can get NULL for operand 2.  */
      if (operands[2] == NULL_RTX)
--- 8157,8163 ----
    "TARGET_EITHER"
    "
    {
!     rtx callee, pat;
      
      /* In an untyped call, we can get NULL for operand 2.  */
      if (operands[2] == NULL_RTX)
*************** (define_expand "call"
*** 8159,8167 ****
--- 8171,8189 ----
  	? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
  	: !REG_P (callee))
        XEXP (operands[0], 0) = force_reg (Pmode, callee);
+ 
+     pat = gen_call_internal (operands[0], operands[1], operands[2]);
+     arm_emit_call_insn (pat, XEXP (operands[0], 0));
+     DONE;
    }"
  )
  
+ (define_expand "call_internal"
+   [(parallel [(call (match_operand 0 "memory_operand" "")
+ 	            (match_operand 1 "general_operand" ""))
+ 	      (use (match_operand 2 "" ""))
+ 	      (clobber (reg:SI LR_REGNUM))])])
+ 
  (define_insn "*call_reg_armv5"
    [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
           (match_operand 1 "" ""))
*************** (define_expand "call_value"
*** 8239,8245 ****
    "TARGET_EITHER"
    "
    {
!     rtx callee;
      
      /* In an untyped call, we can get NULL for operand 2.  */
      if (operands[3] == 0)
--- 8261,8267 ----
    "TARGET_EITHER"
    "
    {
!     rtx pat, callee;
      
      /* In an untyped call, we can get NULL for operand 2.  */
      if (operands[3] == 0)
*************** (define_expand "call_value"
*** 8253,8261 ****
--- 8275,8295 ----
  	? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
  	: !REG_P (callee))
        XEXP (operands[1], 0) = force_reg (Pmode, callee);
+ 
+     pat = gen_call_value_internal (operands[0], operands[1],
+ 				   operands[2], operands[3]);
+     arm_emit_call_insn (pat, XEXP (operands[1], 0));
+     DONE;
    }"
  )
  
+ (define_expand "call_value_internal"
+   [(parallel [(set (match_operand       0 "" "")
+ 	           (call (match_operand 1 "memory_operand" "")
+ 		         (match_operand 2 "general_operand" "")))
+ 	      (use (match_operand 3 "" ""))
+ 	      (clobber (reg:SI LR_REGNUM))])])
+ 
  (define_insn "*call_value_reg_armv5"
    [(set (match_operand 0 "" "")
          (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
Index: gcc/config/arm/lib1funcs.asm
===================================================================
*** gcc/config/arm/lib1funcs.asm	2007-05-23 04:27:23.000000000 -0700
--- gcc/config/arm/lib1funcs.asm	2007-05-24 04:06:24.000000000 -0700
*************** Boston, MA 02110-1301, USA.  */
*** 54,59 ****
--- 54,61 ----
  #ifdef __ELF__
  #ifdef __thumb__
  #define __PLT__  /* Not supported in Thumb assembler (for now).  */
+ #elif defined __vxworks && !defined __PIC__
+ #define __PLT__ /* Not supported by the kernel loader.  */
  #else
  #define __PLT__ (PLT)
  #endif


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