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]

Medium model support for x86-64


Hi,
this patch adds an support for medium model PIC (ie shared libraries
with data segment exceeding 2GB).  While working on this I also
implemented the small model section optimization and I run into problem
with section ordering where I wanted to have the GOT/PLT sections near
so they can be accessed IP relative way.  While posting a patch for this
to binutils list Richard suggested the opposite approach of adding large
data section to the very end of the file.

This approach is interesting mainliny because it improves the
ineroperability in between small and medium code (ie as long as the
small model code don't link directly to mediu model code it is safe) so
I implemented this.

This results in small ABI change concerning static medium model code
that reflect the large data section and the restriction on the size of
objects put into .data.  This is major reason why I am posting this
patch in the stage 3 because it is better to change the ABI sooner than
later even if the medium model is not very widespread use yet.

We've discussed this with AMD and other folks interested in the ABI and
will post the ABI update soon as well as the final version of patch to
binutils needed to get -fpic -mcmodel=medium to compile (I've sent
preview version of this some time ago that still apply but there has
been a silly bug that took me a while to hunt down).

I've also discussed this briefly with Mark and he says that this patch
can be fine for stage3 assuming that i386 maintainers will agree with
it, so here it comes ;)
I hope that this patch is safe in a way that it should not affect the
code paths used for i386/x86-64 small model generation.  On the other
hand it is not very tinny and it needs companion binutils patch to be
usefull (it don't need it for bootstrap as the multilibs are, I hope,
not needed because of the aforementioned interoperability issues), so
please let me know your oppinions.

I've bootstrapped/regtested the change with i686-gnu-linux and
x86_64-linux and also slightly earlier versions of this patch has been
tested to build some large libraries, bootstrap in medium mode by
default and build a SPEC.

Honza

2004-11-03  Jan Hubicka  <jh@suse.cz>
	* target-def.h (TARGET_IN_LARGE_DATA_P): New.
	* target.h (gcc_target): Add in_large_data_p.
	* varasm.c (enum section_category): Add SECCAT values for large
	data sections.
	(categorize_decl_for_section): Call in_large_data_hook.
	(decl_readonly_section_1): Deal with ldata sections.
	* i386.c (ix86_section_threshold): New static variable.
	(ix86_in_large_data_p): New.
	(ix86_encode_section_info): New.
	(TARGET_LARGE_DATA_P, TARGET_ENCODE_SECTION_INFO): New macros.
	(override_options): Accept medium PIC.
	(ix86_expand_prologue): Expand medium model PIC load.
	(legitimate_constant_p): Accept GOTOFFs.
	(legitimate_pic_operand_p): Likewise.
	(legitimate_pic_address_disp_p): Likewise.
	(legitimize_pic_address): Construct medium model addresses.
	* i386.h (PIC_OFFSET_TABLE_REGNUM): Medium model PIC needs pointer.
	(ix86_cmodel): Add CM_MEDIUM_PIC.
	(SYMBOL_FLAG_FAR_ADDR, SYMBOL_REF_FAR_ADDR_P): New macros.
	* i386.md (movdi*) Deal with medium model loads.
	(set_got_rex64): New pattern.
	* predicates.md (zero_extended_operand/sign_extended_operand): Accept
	new medium PIC unspecs.

Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.106
diff -c -3 -p -r1.106 target-def.h
*** target-def.h	1 Oct 2004 05:08:55 -0000	1.106
--- target-def.h	2 Nov 2004 23:50:00 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 358,363 ****
--- 358,367 ----
  #define TARGET_IN_SMALL_DATA_P hook_bool_tree_false
  #endif
  
+ #ifndef TARGET_IN_LARGE_DATA_P
+ #define TARGET_IN_LARGE_DATA_P hook_bool_tree_false
+ #endif
+ 
  #ifndef TARGET_ENCODE_SECTION_INFO
  #define TARGET_ENCODE_SECTION_INFO default_encode_section_info
  #endif
*************** Foundation, 59 Temple Place - Suite 330,
*** 504,509 ****
--- 508,514 ----
    TARGET_DELEGITIMIZE_ADDRESS,			\
    TARGET_FUNCTION_OK_FOR_SIBCALL,		\
    TARGET_IN_SMALL_DATA_P,			\
+   TARGET_IN_LARGE_DATA_P,			\
    TARGET_BINDS_LOCAL_P,				\
    TARGET_ENCODE_SECTION_INFO,			\
    TARGET_STRIP_NAME_ENCODING,			\
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.118
diff -c -3 -p -r1.118 target.h
*** target.h	1 Oct 2004 05:08:56 -0000	1.118
--- target.h	2 Nov 2004 23:50:00 -0000
*************** struct gcc_target
*** 388,393 ****
--- 388,396 ----
    /* True if EXP should be placed in a "small data" section.  */
    bool (* in_small_data_p) (tree);
  
+   /* True if EXP should be placed in a "large data" section.  */
+   bool (* in_large_data_p) (tree);
+ 
    /* True if EXP names an object for which name resolution must resolve
       to the current module.  */
    bool (* binds_local_p) (tree);
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.458
diff -c -3 -p -r1.458 varasm.c
*** varasm.c	28 Oct 2004 20:52:42 -0000	1.458
--- varasm.c	2 Nov 2004 23:50:00 -0000
*************** enum section_category
*** 4740,4745 ****
--- 4740,4746 ----
    SECCAT_RODATA_MERGE_STR_INIT,
    SECCAT_RODATA_MERGE_CONST,
    SECCAT_SRODATA,
+   SECCAT_LRODATA,
  
    SECCAT_DATA,
  
*************** enum section_category
*** 4756,4766 ****
--- 4757,4773 ----
    SECCAT_DATA_REL_LOCAL,
    SECCAT_DATA_REL_RO,
    SECCAT_DATA_REL_RO_LOCAL,
+   SECCAT_LDATA_REL,
+   SECCAT_LDATA_REL_LOCAL,
+   SECCAT_LDATA_REL_RO,
+   SECCAT_LDATA_REL_RO_LOCAL,
  
+   SECCAT_LDATA,
    SECCAT_SDATA,
    SECCAT_TDATA,
  
    SECCAT_BSS,
+   SECCAT_LBSS,
    SECCAT_SBSS,
    SECCAT_TBSS
  };
*************** categorize_decl_for_section (tree decl, 
*** 4852,4857 ****
--- 4859,4898 ----
  	ret = SECCAT_SDATA;
      }
  
+   /* If the target uses large data sections, select it.  */
+   else if ((*targetm.in_large_data_p) (decl))
+     {
+       switch (ret)
+ 	{
+ 	case SECCAT_BSS:
+ 	  ret = SECCAT_LBSS;
+ 	  break;
+ 	case SECCAT_RODATA:
+ 	case SECCAT_RODATA_MERGE_STR:
+ 	case SECCAT_RODATA_MERGE_STR_INIT:
+ 	case SECCAT_RODATA_MERGE_CONST:
+ 	  ret = SECCAT_LRODATA;
+ 	  break;
+ 	case SECCAT_DATA:
+ 	  ret = SECCAT_LDATA;
+ 	  break;
+ 	case SECCAT_DATA_REL:
+ 	  ret = SECCAT_LDATA_REL;
+ 	  break;
+ 	case SECCAT_DATA_REL_LOCAL:
+ 	  ret = SECCAT_LDATA_REL_LOCAL;
+ 	  break;
+ 	case SECCAT_DATA_REL_RO:
+ 	  ret = SECCAT_LDATA_REL_RO;
+ 	  break;
+ 	case SECCAT_DATA_REL_RO_LOCAL:
+ 	  ret = SECCAT_LDATA_REL_RO_LOCAL;
+ 	  break;
+ 	default:
+ 	  abort ();
+ 	}
+     }
+ 
    return ret;
  }
  
*************** decl_readonly_section_1 (tree decl, int 
*** 4871,4876 ****
--- 4912,4918 ----
      case SECCAT_RODATA_MERGE_STR_INIT:
      case SECCAT_RODATA_MERGE_CONST:
      case SECCAT_SRODATA:
+     case SECCAT_LRODATA:
        return true;
        break;
      default:
*************** default_elf_select_section_1 (tree decl,
*** 4912,4917 ****
--- 4954,4962 ----
      case SECCAT_SRODATA:
        named_section (NULL_TREE, ".sdata2", reloc);
        break;
+     case SECCAT_LRODATA:
+       named_section (NULL_TREE, ".lrodata", reloc);
+       break;
      case SECCAT_DATA:
        data_section ();
        break;
*************** default_elf_select_section_1 (tree decl,
*** 4933,4938 ****
--- 4978,4998 ----
      case SECCAT_TDATA:
        named_section (NULL_TREE, ".tdata", reloc);
        break;
+     case SECCAT_LDATA:
+       named_section (NULL_TREE, ".ldata", reloc);
+       break;
+     case SECCAT_LDATA_REL:
+       named_section (NULL_TREE, ".ldata.rel", reloc);
+       break;
+     case SECCAT_LDATA_REL_LOCAL:
+       named_section (NULL_TREE, ".ldata.rel.local", reloc);
+       break;
+     case SECCAT_LDATA_REL_RO:
+       named_section (NULL_TREE, ".ldata.rel.ro", reloc);
+       break;
+     case SECCAT_LDATA_REL_RO_LOCAL:
+       named_section (NULL_TREE, ".ldata.rel.ro.local", reloc);
+       break;
      case SECCAT_BSS:
  #ifdef BSS_SECTION_ASM_OP
        bss_section ();
*************** default_elf_select_section_1 (tree decl,
*** 4943,4948 ****
--- 5003,5011 ----
      case SECCAT_SBSS:
        named_section (NULL_TREE, ".sbss", reloc);
        break;
+     case SECCAT_LBSS:
+       named_section (NULL_TREE, ".lbss", reloc);
+       break;
      case SECCAT_TBSS:
        named_section (NULL_TREE, ".tbss", reloc);
        break;
*************** default_binds_local_p_1 (tree exp, int s
*** 5142,5148 ****
      local_p = true;
    /* If PIC, then assume that any global name can be overridden by
       symbols resolved from other modules.  */
!   else if (shlib)
      local_p = false;
    /* Uninitialized COMMON variable may be unified with symbols
       resolved from other modules.  */
--- 5205,5211 ----
      local_p = true;
    /* If PIC, then assume that any global name can be overridden by
       symbols resolved from other modules.  */
!   else if (shlib && default_visibility == VISIBILITY_DEFAULT)
      local_p = false;
    /* Uninitialized COMMON variable may be unified with symbols
       resolved from other modules.  */
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.735
diff -c -3 -p -r1.735 i386.c
*** config/i386/i386.c	12 Oct 2004 17:14:42 -0000	1.735
--- config/i386/i386.c	2 Nov 2004 23:50:01 -0000
*************** const char *ix86_branch_cost_string;
*** 833,838 ****
--- 833,843 ----
  /* Power of two alignment for functions.  */
  const char *ix86_align_funcs_string;
  
+ /* Variables which are this size or smaller are put in the data/bss
+    or ldata/lbss sections.  */
+ 
+ static int ix86_section_threshold = 65536;
+ 
  /* Prefix built by ASM_GENERATE_INTERNAL_LABEL.  */
  char internal_label_prefix[16];
  int internal_label_prefix_len;
*************** static enum x86_64_reg_class merge_class
*** 965,970 ****
--- 970,977 ----
  static REAL_VALUE_TYPE ext_80387_constants_table [5];
  static bool ext_80387_constants_init = 0;
  static void init_ext_80387_constants (void);
+ static bool ix86_in_large_data_p (tree);
+ static void ix86_encode_section_info (tree, rtx, int);
  
  /* Initialize the GCC target structure.  */
  #undef TARGET_ATTRIBUTE_TABLE
*************** static void init_ext_80387_constants (vo
*** 986,991 ****
--- 993,1004 ----
  #undef TARGET_ASM_FUNCTION_EPILOGUE
  #define TARGET_ASM_FUNCTION_EPILOGUE ix86_output_function_epilogue
  
+ #undef TARGET_IN_LARGE_DATA_P
+ #define TARGET_IN_LARGE_DATA_P  ix86_in_large_data_p
+ 
+ #undef TARGET_ENCODE_SECTION_INFO
+ #define TARGET_ENCODE_SECTION_INFO ix86_encode_section_info
+ 
  #undef TARGET_ASM_OPEN_PAREN
  #define TARGET_ASM_OPEN_PAREN ""
  #undef TARGET_ASM_CLOSE_PAREN
*************** override_options (void)
*** 1242,1255 ****
      {
        if (!strcmp (ix86_cmodel_string, "small"))
  	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
        else if (flag_pic)
  	sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
        else if (!strcmp (ix86_cmodel_string, "32"))
  	ix86_cmodel = CM_32;
        else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
  	ix86_cmodel = CM_KERNEL;
-       else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
- 	ix86_cmodel = CM_MEDIUM;
        else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
  	ix86_cmodel = CM_LARGE;
        else
--- 1255,1268 ----
      {
        if (!strcmp (ix86_cmodel_string, "small"))
  	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+       else if (!strcmp (ix86_cmodel_string, "medium"))
+ 	ix86_cmodel = flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM;
        else if (flag_pic)
  	sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
        else if (!strcmp (ix86_cmodel_string, "32"))
  	ix86_cmodel = CM_32;
        else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
  	ix86_cmodel = CM_KERNEL;
        else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
  	ix86_cmodel = CM_LARGE;
        else
*************** ix86_expand_prologue (void)
*** 4333,4339 ****
  
    if (pic_reg_used)
      {
!       insn = emit_insn (gen_set_got (pic_offset_table_rtx));
  
        /* Even with accurate pre-reload life analysis, we can wind up
  	 deleting all references to the pic register after reload.
--- 4346,4355 ----
  
    if (pic_reg_used)
      {
!       if (TARGET_64BIT)
!         insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
!       else
!         insn = emit_insn (gen_set_got (pic_offset_table_rtx));
  
        /* Even with accurate pre-reload life analysis, we can wind up
  	 deleting all references to the pic register after reload.
*************** legitimate_constant_p (rtx x)
*** 4857,4862 ****
--- 4873,4886 ----
        if (GET_CODE (x) == UNSPEC)
  	switch (XINT (x, 1))
  	  {
+ 	  case UNSPEC_GOTOFF:
+ 	    /* For 64bit target we have to deal with GOTOFF as 64bit values,
+ 	       for 32bit targets these are always part of addressing mode
+ 	       there is no point to allow dealing with them separately -
+ 	       doing so just increase register pressure.  */
+ 	    if (!TARGET_64BIT)
+ 	      return false;
+ 	    return local_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
  	  case UNSPEC_TPOFF:
  	  case UNSPEC_NTPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
*************** legitimate_pic_operand_p (rtx x)
*** 4916,4926 ****
--- 4940,4961 ----
      {
      case CONST:
        inner = XEXP (x, 0);
+       if (GET_CODE (inner) == PLUS
+ 	  && GET_CODE (XEXP (inner, 1)) == CONST_INT)
+ 	inner = XEXP (inner, 0);
  
        /* Only some unspecs are valid as "constants".  */
        if (GET_CODE (inner) == UNSPEC)
  	switch (XINT (inner, 1))
  	  {
+ 	  case UNSPEC_GOTOFF:
+ 	    /* For 64bit target we have to deal with GOTOFF as 64bit values,
+ 	       for 32bit targets these are always part of addressing mode
+ 	       there is no point to allow dealing with them separately -
+ 	       doing so just increase register pressure.  */
+ 	    if (!TARGET_64BIT)
+ 	      return false;
+ 	    return local_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
  	  case UNSPEC_TPOFF:
  	    return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
  	  default:
*************** legitimate_pic_address_disp_p (rtx disp)
*** 4953,4959 ****
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && ix86_cmodel == CM_SMALL_PIC
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
--- 4988,4996 ----
        if (tls_symbolic_operand (disp, GET_MODE (disp)))
  	return 0;
        if (GET_CODE (disp) == SYMBOL_REF
! 	  && (ix86_cmodel == CM_SMALL_PIC
! 	      || (ix86_cmodel == CM_MEDIUM_PIC
! 		   && !SYMBOL_REF_FAR_ADDR_P (disp)))
  	  && SYMBOL_REF_LOCAL_P (disp))
  	return 1;
        if (GET_CODE (disp) == LABEL_REF)
*************** legitimate_pic_address_disp_p (rtx disp)
*** 4968,4974 ****
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& ix86_cmodel == CM_SMALL_PIC
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
--- 5005,5013 ----
  	  if (tls_symbolic_operand (op0, GET_MODE (op0)))
  	    return 0;
  	  if (((GET_CODE (op0) == SYMBOL_REF
! 		&& (ix86_cmodel == CM_SMALL_PIC
! 		    || (ix86_cmodel == CM_MEDIUM_PIC
! 		        && !SYMBOL_REF_FAR_ADDR_P (op0)))
  		&& SYMBOL_REF_LOCAL_P (op0))
  	       || GET_CODE (op0) == LABEL_REF)
  	      && GET_CODE (op1) == CONST_INT
*************** legitimize_pic_address (rtx orig, rtx re
*** 5303,5308 ****
--- 5342,5379 ----
  
    if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
      new = addr;
+   else if (TARGET_64BIT && local_symbolic_operand (addr, Pmode)
+ 	     && ix86_cmodel != CM_SMALL_PIC)
+     {
+       rtx tmpreg;
+       /* This symbol may be referenced via a displacement from the PIC
+ 	 base address (@GOTOFF).  */
+ 
+       if (reload_in_progress)
+ 	regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+       if (GET_CODE (addr) == CONST)
+ 	addr = XEXP (addr, 0);
+       if (GET_CODE (addr) == PLUS)
+ 	  {
+             new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
+ 	    new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
+ 	  }
+ 	else
+           new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
+       new = gen_rtx_CONST (Pmode, new);
+       if (!reg)
+         tmpreg = gen_reg_rtx (Pmode);
+       else
+ 	tmpreg = reg;
+       emit_move_insn (tmpreg, new);
+       new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmpreg);
+ 
+       if (reg != 0)
+ 	{
+ 	  emit_move_insn (reg, new);
+ 	  new = reg;
+ 	}
+     }
    else if (!TARGET_64BIT && local_symbolic_operand (addr, Pmode))
      {
        /* This symbol may be referenced via a displacement from the PIC
*************** ix86_md_asm_clobbers (tree clobbers)
*** 15178,15183 ****
--- 15249,15297 ----
    return clobbers;
  }
  
+ /* Return true if this goes in small data/bss.  */
+ 
+ static bool
+ ix86_in_large_data_p (tree exp)
+ {
+   if (ix86_cmodel != CM_MEDIUM && ix86_cmodel != CM_MEDIUM_PIC)
+     return false;
+ 
+   /* Functions are never large data.  */
+   if (TREE_CODE (exp) == FUNCTION_DECL)
+     return false;
+ 
+   if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
+     {
+       const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+       if (strcmp (section, ".ldata") == 0
+ 	  || strcmp (section, ".lbss") == 0)
+ 	return true;
+       return false;
+     }
+   else
+     {
+       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
+ 
+       /* If this is an incomplete type with size 0, then we can't put it
+ 	 in data because it might be too big when completed.  */
+       if (!size || size > ix86_section_threshold)
+ 	return true;
+     }
+ 
+   return false;
+ }
+ static void
+ ix86_encode_section_info (tree decl, rtx rtl, int first)
+ {
+   default_encode_section_info (decl, rtl, first);
+ 
+   if (TREE_CODE (decl) == VAR_DECL
+       && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
+       && ix86_in_large_data_p (decl))
+     SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FAR_ADDR;
+ }
+ 
  /* Worker function for REVERSE_CONDITION.  */
  
  enum rtx_code
Index: config/i386/i386.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v
retrieving revision 1.402
diff -c -3 -p -r1.402 i386.h
*** config/i386/i386.h	12 Sep 2004 23:31:31 -0000	1.402
--- config/i386/i386.h	2 Nov 2004 23:50:02 -0000
*************** do {									\
*** 1215,1221 ****
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   (TARGET_64BIT || !flag_pic ? INVALID_REGNUM		\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
--- 1215,1222 ----
  #define REAL_PIC_OFFSET_TABLE_REGNUM  3
  
  #define PIC_OFFSET_TABLE_REGNUM				\
!   ((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC)	\
!    || !flag_pic ? INVALID_REGNUM			\
     : reload_completed ? REGNO (pic_offset_table_rtx)	\
     : REAL_PIC_OFFSET_TABLE_REGNUM)
  
*************** enum cmodel {
*** 2884,2890 ****
    CM_KERNEL,	/* Assumes all code and data fits in the high 31 bits.  */
    CM_MEDIUM,	/* Assumes code fits in the low 31 bits; data unlimited.  */
    CM_LARGE,	/* No assumptions.  */
!   CM_SMALL_PIC	/* Assumes code+data+got/plt fits in a 31 bit region.  */
  };
  
  extern enum cmodel ix86_cmodel;
--- 2885,2892 ----
    CM_KERNEL,	/* Assumes all code and data fits in the high 31 bits.  */
    CM_MEDIUM,	/* Assumes code fits in the low 31 bits; data unlimited.  */
    CM_LARGE,	/* No assumptions.  */
!   CM_SMALL_PIC,	/* Assumes code+data+got/plt fits in a 31 bit region.  */
!   CM_MEDIUM_PIC	/* Assumes code+got/plt fits in a 31 bit region.  */
  };
  
  extern enum cmodel ix86_cmodel;
*************** struct machine_function GTY(())
*** 3030,3035 ****
--- 3032,3042 ----
  #define X86_FILE_START_VERSION_DIRECTIVE false
  #define X86_FILE_START_FLTUSED false
  
+ /* Flag to mark data that is in the small address area (addressable
+    via "addl", that is, within a 2GByte offset of 0.  */
+ #define SYMBOL_FLAG_FAR_ADDR		(SYMBOL_FLAG_MACH_DEP << 0)
+ #define SYMBOL_REF_FAR_ADDR_P(X)	\
+ 	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
  /*
  Local variables:
  version-control: t
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.562
diff -c -3 -p -r1.562 i386.md
*** config/i386/i386.md	18 Oct 2004 13:01:31 -0000	1.562
--- config/i386/i386.md	2 Nov 2004 23:50:03 -0000
***************
*** 2031,2038 ****
  	      (const_string "ssecvt")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic") (const_int 0))
! 		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
--- 2031,2039 ----
  	      (const_string "ssecvt")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic && ix86_cmodel == CM_SMALL_PIC")
! 	    	     (const_int 0))
!   		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
  	   (const_string "imov")))
***************
*** 2077,2083 ****
  	      (const_string "ssemov")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic") (const_int 0))
  		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
--- 2078,2085 ----
  	      (const_string "ssemov")
  	    (eq_attr "alternative" "4")
  	      (const_string "multi")
!  	    (and (ne (symbol_ref "flag_pic && ix86_cmodel == CM_SMALL_PIC")
! 	    	     (const_int 0))
  		 (match_operand:DI 1 "symbolic_operand" ""))
  	      (const_string "lea")
  	   ]
***************
*** 13887,13892 ****
--- 13889,13903 ----
    [(set_attr "type" "multi")
     (set_attr "length" "12")])
  
+ (define_insn "set_got_rex64"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(const_int 0)] UNSPEC_SET_GOT))
+    (clobber (reg:CC 17))]
+   "TARGET_64BIT"
+   "lea{q}\t_GLOBAL_OFFSET_TABLE_(%%rip), %0"
+   [(set_attr "type" "lea")
+    (set_attr "length" "6")])
+ 
  (define_expand "epilogue"
    [(const_int 1)]
    ""
Index: config/i386/predicates.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/predicates.md,v
retrieving revision 1.5
diff -c -3 -p -r1.5 predicates.md
*** config/i386/predicates.md	14 Sep 2004 10:45:59 -0000	1.5
--- config/i386/predicates.md	2 Nov 2004 23:50:03 -0000
***************
*** 110,116 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL);
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 110,117 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
! 	      || (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
***************
*** 150,156 ****
  		 end of 31bits boundary.  We may also accept pretty
  		 large negative constants knowing that all objects are
  		 in the positive half of address space.  */
! 	      if (ix86_cmodel == CM_SMALL
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
--- 151,159 ----
  		 end of 31bits boundary.  We may also accept pretty
  		 large negative constants knowing that all objects are
  		 in the positive half of address space.  */
! 	      if ((ix86_cmodel == CM_SMALL
! 		   || (ix86_cmodel == CM_MEDIUM
! 		       && !SYMBOL_REF_FAR_ADDR_P (op1)))
  		  && offset < 16*1024*1024
  		  && trunc_int_for_mode (offset, SImode) == offset)
  		return 1;
***************
*** 224,230 ****
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return ix86_cmodel == CM_SMALL;
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
--- 227,235 ----
        /* TLS symbols are not constant.  */
        if (tls_symbolic_operand (op, Pmode))
  	return false;
!       return (ix86_cmodel == CM_SMALL
! 	      || (ix86_cmodel == CM_MEDIUM
! 		  && !SYMBOL_REF_FAR_ADDR_P (op)));
  
      case LABEL_REF:
        /* For certain code models, the code is near as well.  */
***************
*** 247,253 ****
  		 offsets, since one bit is available for free.  Negative
  		 offsets are limited by the size of NULL pointer area
  		 specified by the ABI.  */
! 	      if (ix86_cmodel == CM_SMALL
  		  && GET_CODE (op2) == CONST_INT
  		  && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
  		  && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
--- 252,260 ----
  		 offsets, since one bit is available for free.  Negative
  		 offsets are limited by the size of NULL pointer area
  		 specified by the ABI.  */
! 	      if ((ix86_cmodel == CM_SMALL
! 		   || (ix86_cmodel == CM_MEDIUM
! 		       && !SYMBOL_REF_FAR_ADDR_P (op1)))
  		  && GET_CODE (op2) == CONST_INT
  		  && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
  		  && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))


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