File large-gcc.diff of Package gcc41

Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c.orig	2006-06-22 18:11:03.000000000 +0200
+++ gcc/reg-stack.c	2009-11-20 13:41:03.000000000 +0100
@@ -3114,7 +3114,8 @@ reg_to_stack (FILE *file)
      the PIC register hasn't been set up.  In that case, fall back
      on zero, which we can get from `ldz'.  */
 
-  if (flag_pic)
+  if ((flag_pic && !TARGET_64BIT)
+      || ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
     not_a_num = CONST0_RTX (SFmode);
   else
     {
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h.orig	2005-12-23 12:39:16.000000000 +0100
+++ gcc/config/i386/i386-protos.h	2009-11-20 13:41:03.000000000 +0100
@@ -228,5 +228,6 @@ extern void x86_elf_aligned_common (FILE
 extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
 				      enum rtx_code *, enum rtx_code *);
 extern enum rtx_code ix86_fp_compare_code_to_integer (enum rtx_code);
+extern rtx construct_plt_address (rtx);
 #endif
 extern int asm_preferred_eh_data_format (int, int);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c.orig	2006-11-21 14:16:53.000000000 +0100
+++ gcc/config/i386/i386.c	2009-11-20 13:41:03.000000000 +0100
@@ -1318,14 +1318,14 @@ override_options (void)
 	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 (!strcmp (ix86_cmodel_string, "large"))
+	ix86_cmodel = flag_pic ? CM_LARGE_PIC : CM_LARGE;
       else if (flag_pic)
-	sorry ("code model %s not supported in PIC mode", ix86_cmodel_string);
+	error ("code model %s does not support 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
 	error ("bad value (%s) for -mcmodel= switch", ix86_cmodel_string);
     }
@@ -1348,8 +1348,6 @@ override_options (void)
   if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
     error ("code model %qs not supported in the %s bit mode",
 	   ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
-  if (ix86_cmodel == CM_LARGE)
-    sorry ("code model %<large%> not supported yet");
   if ((TARGET_64BIT != 0) != ((target_flags & MASK_64BIT) != 0))
     sorry ("%i-bit mode not compiled in",
 	   (target_flags & MASK_64BIT) ? 64 : 32);
@@ -5031,7 +5029,25 @@ ix86_expand_prologue (void)
   if (pic_reg_used)
     {
       if (TARGET_64BIT)
-        insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
+	{
+	  if (ix86_cmodel == CM_LARGE_PIC)
+	    {
+              rtx tmp_reg = gen_rtx_REG (DImode,
+					 FIRST_REX_INT_REG + 3 /* R11 */);
+	      rtx label = gen_label_rtx ();
+	      emit_label (label);
+	      LABEL_PRESERVE_P (label) = 1;
+	      gcc_assert (REGNO (pic_offset_table_rtx) != REGNO (tmp_reg));
+	      insn = emit_insn (gen_set_rip_rex64 (pic_offset_table_rtx, label));
+              REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+	      insn = emit_insn (gen_set_got_offset_rex64 (tmp_reg, label));
+              REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+	      insn = emit_insn (gen_adddi3 (pic_offset_table_rtx,
+					    pic_offset_table_rtx, tmp_reg));
+	    }
+	  else
+            insn = emit_insn (gen_set_got_rex64 (pic_offset_table_rtx));
+	}
       else
         insn = emit_insn (gen_set_got (pic_offset_table_rtx));
 
@@ -5569,7 +5585,9 @@ legitimate_constant_p (rtx x)
       if (GET_CODE (x) == UNSPEC)
 	switch (XINT (x, 1))
 	  {
+	  case UNSPEC_GOT:
 	  case UNSPEC_GOTOFF:
+	  case UNSPEC_PLTOFF:
 	    return TARGET_64BIT;
 	  case UNSPEC_TPOFF:
 	  case UNSPEC_NTPOFF:
@@ -5667,7 +5685,9 @@ legitimate_pic_operand_p (rtx x)
       if (GET_CODE (inner) == UNSPEC)
 	switch (XINT (inner, 1))
 	  {
+	  case UNSPEC_GOT:
 	  case UNSPEC_GOTOFF:
+	  case UNSPEC_PLTOFF:
 	    return TARGET_64BIT;
 	  case UNSPEC_TPOFF:
 	    x = XVECEXP (inner, 0, 0);
@@ -5725,7 +5745,9 @@ legitimate_pic_address_disp_p (rtx disp)
 	  /* TLS references should always be enclosed in UNSPEC.  */
 	  if (SYMBOL_REF_TLS_MODEL (op0))
 	    return false;
-	  if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0))
+	  if (!SYMBOL_REF_FAR_ADDR_P (op0)
+	      && ix86_cmodel != CM_LARGE_PIC
+	      && SYMBOL_REF_LOCAL_P (op0))
 	    return true;
 	  break;
 
@@ -5743,7 +5765,8 @@ legitimate_pic_address_disp_p (rtx disp)
          of GOT tables.  We should not need these anyway.  */
       if (GET_CODE (disp) != UNSPEC
 	  || (XINT (disp, 1) != UNSPEC_GOTPCREL
-	      && XINT (disp, 1) != UNSPEC_GOTOFF))
+	      && XINT (disp, 1) != UNSPEC_GOTOFF
+	      && XINT (disp, 1) != UNSPEC_PLTOFF))
 	return 0;
 
       if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
@@ -6153,7 +6176,7 @@ legitimize_pic_address (rtx orig, rtx re
     }
   else if (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (addr) == 0)
     {
-      if (TARGET_64BIT)
+      if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC)
 	{
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
 	  new = gen_rtx_CONST (Pmode, new);
@@ -6177,6 +6200,8 @@ legitimize_pic_address (rtx orig, rtx re
 	    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
 	  new = gen_rtx_CONST (Pmode, new);
+	  if (TARGET_64BIT)
+	    new = force_reg (Pmode, new);
 	  new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
 	  new = gen_const_mem (Pmode, new);
 	  set_mem_alias_set (new, ix86_GOT_alias_set ());
@@ -6707,6 +6732,9 @@ output_pic_addr_const (FILE *file, rtx x
 	case UNSPEC_GOTOFF:
 	  fputs ("@GOTOFF", file);
 	  break;
+	case UNSPEC_PLTOFF:
+	  fputs ("@PLTOFF", file);
+	  break;
 	case UNSPEC_GOTPCREL:
 	  fputs ("@GOTPCREL(%rip)", file);
 	  break;
@@ -8277,9 +8305,17 @@ ix86_output_addr_vec_elt (FILE *file, in
 void
 ix86_output_addr_diff_elt (FILE *file, int value, int rel)
 {
+  const char *directive = ASM_LONG;
+
+#ifdef ASM_QUAD
+  if (TARGET_64BIT && CASE_VECTOR_MODE == DImode)
+    directive = ASM_QUAD;
+#else
+  gcc_assert (!TARGET_64BIT);
+#endif
   if (TARGET_64BIT)
     fprintf (file, "%s%s%d-%s%d\n",
-	     ASM_LONG, LPREFIX, value, LPREFIX, rel);
+	     directive, LPREFIX, value, LPREFIX, rel);
   else if (HAVE_AS_GOTOFF_IN_DATA)
     fprintf (file, "%s%s%d@GOTOFF\n", ASM_LONG, LPREFIX, value);
 #if TARGET_MACHO
@@ -8394,8 +8430,8 @@ ix86_expand_move (enum machine_mode mode
 #else
       if (GET_CODE (op0) == MEM)
 	op1 = force_reg (Pmode, op1);
-      else 
-	op1 = legitimize_address (op1, op1, Pmode);
+      else if (!TARGET_64BIT || !x86_64_movabs_operand (op1, Pmode))
+	op1 = legitimize_pic_address (op1, REG_P (op0) ? op0 : 0);
 #endif /* TARGET_MACHO */
     }
   else
@@ -12777,6 +12813,22 @@ ix86_expand_strlensi_unroll_1 (rtx out,
   emit_label (end_0_label);
 }
 
+/* For given symbol (function) construct code to compute address of it's PLT
+   entry in large x86-64 PIC model.  */
+rtx
+construct_plt_address (rtx symbol)
+{
+  rtx tmp = gen_reg_rtx (Pmode);
+  rtx unspec = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_PLTOFF);
+
+  gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
+  gcc_assert (ix86_cmodel == CM_LARGE_PIC);
+
+  emit_move_insn (tmp, gen_rtx_CONST (Pmode, unspec));
+  emit_insn (gen_adddi3 (tmp, tmp, pic_offset_table_rtx));
+  return tmp;
+}
+
 void
 ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
 		  rtx callarg2 ATTRIBUTE_UNUSED,
@@ -12793,7 +12845,7 @@ ix86_expand_call (rtx retval, rtx fnaddr
     fnaddr = machopic_indirect_call_target (fnaddr);
 #else
   /* Static functions and indirect calls don't need the pic register.  */
-  if (! TARGET_64BIT && flag_pic
+  if (flag_pic && (!TARGET_64BIT || ix86_cmodel == CM_LARGE_PIC)
       && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
       && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
     use_reg (&use, pic_offset_table_rtx);
@@ -12806,7 +12858,12 @@ ix86_expand_call (rtx retval, rtx fnaddr
     }
 #endif /* TARGET_MACHO */
 
-  if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
+  if (ix86_cmodel == CM_LARGE_PIC
+      && GET_CODE (fnaddr) == MEM
+      && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
+      && !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
+    fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
+  else if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
     {
       fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
       fnaddr = gen_rtx_MEM (QImode, fnaddr);
@@ -18239,7 +18296,7 @@ asm_preferred_eh_data_format (int code,
 {
   if (flag_pic)
     {
-int type = DW_EH_PE_sdata8;
+      int type = DW_EH_PE_sdata8;
       if (!TARGET_64BIT
 	  || ix86_cmodel == CM_SMALL_PIC
 	  || (ix86_cmodel == CM_MEDIUM_PIC && (global || code)))
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h.orig	2007-01-15 11:11:07.000000000 +0100
+++ gcc/config/i386/i386.h	2009-11-20 13:41:03.000000000 +0100
@@ -961,14 +961,15 @@ do {									\
 
 /* Register to hold the addressing base for position independent
    code access to data items.  We don't use PIC pointer for 64bit
-   mode.  Define the regnum to dummy value to prevent gcc from
-   pessimizing code dealing with EBX.
+   mode in the small or medium models.  For the large PIC model we use
+   R15.  Define the regnum to dummy
+   value to prevent gcc from pessimizing code dealing with EBX.
 
    To avoid clobbering a call-saved register unnecessarily, we renumber
    the pic register when possible.  The change is visible after the
    prologue has been emitted.  */
 
-#define REAL_PIC_OFFSET_TABLE_REGNUM  3
+#define REAL_PIC_OFFSET_TABLE_REGNUM  (TARGET_64BIT ? FIRST_REX_INT_REG + 15 - 8 : 3)
 
 #define PIC_OFFSET_TABLE_REGNUM				\
   ((TARGET_64BIT && ix86_cmodel == CM_SMALL_PIC)	\
@@ -1787,7 +1788,8 @@ do {							\
 
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE (!TARGET_64BIT || flag_pic ? SImode : DImode)
+#define CASE_VECTOR_MODE \
+ (!TARGET_64BIT || (flag_pic && ix86_cmodel != CM_LARGE_PIC) ? SImode : DImode)
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 1
@@ -2154,7 +2156,8 @@ enum cmodel {
   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.  */
+  CM_MEDIUM_PIC,/* Assumes code+got/plt fits in a 31 bit region.  */
+  CM_LARGE_PIC	/* No assumptions.  */
 };
 
 extern enum cmodel ix86_cmodel;
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md.orig	2006-10-24 11:43:24.000000000 +0200
+++ gcc/config/i386/i386.md	2009-11-20 13:41:03.000000000 +0100
@@ -61,6 +61,7 @@
    (UNSPEC_DTPOFF		6)
    (UNSPEC_GOTNTPOFF		7)
    (UNSPEC_INDNTPOFF		8)
+   (UNSPEC_PLTOFF		9)
 
    ; Prologue support
    (UNSPEC_STACK_ALLOC		11)
@@ -68,6 +69,8 @@
    (UNSPEC_SSE_PROLOGUE_SAVE	13)
    (UNSPEC_REG_SAVE		14)
    (UNSPEC_DEF_CFA		15)
+   (UNSPEC_SET_RIP		119)
+   (UNSPEC_SET_GOT_OFFSET	120)
 
    ; TLS support
    (UNSPEC_TP			16)
@@ -14021,7 +14024,8 @@
 (define_insn "*call_1_rex64"
   [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm"))
 	 (match_operand 1 "" ""))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT
+   && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
 {
   if (constant_call_address_operand (operands[0], Pmode))
     return "call\t%P0";
@@ -14029,6 +14033,13 @@
 }
   [(set_attr "type" "call")])
 
+(define_insn "*call_1_rex64_large"
+  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rm"))
+	 (match_operand 1 "" ""))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "call\t%A0"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall_1_rex64"
   [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" ""))
 	 (match_operand 1 "" ""))]
@@ -14235,6 +14246,22 @@
   [(set_attr "type" "lea")
    (set_attr "length" "6")])
 
+(define_insn "set_rip_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "" "")] UNSPEC_SET_RIP))]
+  "TARGET_64BIT"
+  "lea{q}\t%l1(%%rip), %0"
+  [(set_attr "type" "lea")
+   (set_attr "length" "6")])
+
+(define_insn "set_got_offset_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(unspec:DI [(match_operand:DI 1 "" "")] UNSPEC_SET_GOT_OFFSET))]
+  "TARGET_64BIT"
+  "movabs{q}\t$_GLOBAL_OFFSET_TABLE_-%l1, %0"
+  [(set_attr "type" "imov")
+   (set_attr "length" "11")])
+
 (define_expand "epilogue"
   [(const_int 1)]
   ""
@@ -14519,15 +14546,26 @@
 
 (define_insn "*tls_global_dynamic_64"
   [(set (match_operand:DI 0 "register_operand" "=a")
-	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
+	(call:DI (mem:QI (match_operand:DI 2 "constant_call_address_operand" ""))
 		 (match_operand:DI 3 "" "")))
    (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
 	      UNSPEC_TLS_GD)]
-  "TARGET_64BIT"
+  "TARGET_64BIT && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
   ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
   [(set_attr "type" "multi")
    (set_attr "length" "16")])
 
+(define_insn "*tls_global_dynamic_64_large"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(call:DI (mem:QI (match_operand:DI 2 "call_insn_operand" "rm"))
+		 (match_operand:DI 3 "" "")))
+   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+	      UNSPEC_TLS_GD)]
+  "TARGET_64BIT"
+  ".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%A2"
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")])
+
 (define_expand "tls_global_dynamic_64"
   [(parallel [(set (match_operand:DI 0 "register_operand" "")
 		   (call:DI (mem:QI (match_dup 2)) (const_int 0)))
@@ -14536,6 +14574,8 @@
   ""
 {
   operands[2] = ix86_tls_get_addr ();
+  if (ix86_cmodel == CM_LARGE_PIC)
+    operands[2] = construct_plt_address (operands[2]);
 })
 
 (define_insn "*tls_local_dynamic_base_32_gnu"
@@ -14601,6 +14641,8 @@
   ""
 {
   operands[1] = ix86_tls_get_addr ();
+  if (ix86_cmodel == CM_LARGE_PIC)
+    operands[1] = construct_plt_address (operands[1]);
 })
 
 ;; Local dynamic of a single variable is a lose.  Show combine how
@@ -20335,7 +20377,8 @@
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm"))
 	      (match_operand:DI 2 "" "")))]
-  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT
+   && ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC"
 {
   if (constant_call_address_operand (operands[1], Pmode))
     return "call\t%P1";
@@ -20343,6 +20386,14 @@
 }
   [(set_attr "type" "callv")])
 
+(define_insn "*call_value_1_rex64_large"
+  [(set (match_operand 0 "" "")
+	(call (mem:QI (match_operand:DI 1 "call_insn_operand" "rm"))
+	      (match_operand:DI 2 "" "")))]
+  "!SIBLING_CALL_P (insn) && TARGET_64BIT"
+  "call\t%A1"
+  [(set_attr "type" "callv")])
+
 (define_insn "*sibcall_value_1_rex64"
   [(set (match_operand 0 "" "")
 	(call (mem:QI (match_operand:DI 1 "constant_call_address_operand" ""))
Index: gcc/config/i386/predicates.md
===================================================================
--- gcc/config/i386/predicates.md.orig	2006-10-09 12:05:44.000000000 +0200
+++ gcc/config/i386/predicates.md	2009-11-20 13:41:03.000000000 +0100
@@ -346,14 +346,6 @@
 })
 
 
-;; Return nonzero if OP is nonmemory operand acceptable by movabs patterns.
-(define_predicate "x86_64_movabs_operand"
-  (if_then_else (match_test "!TARGET_64BIT || !flag_pic")
-    (match_operand 0 "nonmemory_operand")
-    (ior (match_operand 0 "register_operand")
-	 (and (match_operand 0 "const_double_operand")
-	      (match_test "GET_MODE_SIZE (mode) <= 8")))))
-
 ;; Returns nonzero if OP is either a symbol reference or a sum of a symbol
 ;; reference and a constant.
 (define_predicate "symbolic_operand"
@@ -398,6 +390,16 @@
     }
 })
 
+;; Return nonzero if OP is nonmemory operand acceptable by movabs patterns.
+(define_predicate "x86_64_movabs_operand"
+  (if_then_else (match_test "!TARGET_64BIT || !flag_pic")
+    (match_operand 0 "nonmemory_operand")
+    (ior (match_operand 0 "register_operand")
+	 (ior (and (match_operand 0 "const_double_operand")
+	           (match_test "GET_MODE_SIZE (mode) <= 8"))
+	      (and (match_operand 0 "symbolic_operand")
+	           (match_test "!flag_pic"))))))
+
 ;; Return true if the operand contains a @GOT or @GOTOFF reference.
 (define_predicate "pic_symbolic_operand"
   (match_code "const")
@@ -467,8 +469,9 @@
 
 ;; Test for a pc-relative call operand
 (define_predicate "constant_call_address_operand"
-  (ior (match_code "symbol_ref")
-       (match_operand 0 "local_symbolic_operand")))
+  (and (ior (match_code "symbol_ref")
+            (match_operand 0 "local_symbolic_operand"))
+       (match_test "ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC")))
 
 ;; True for any non-virtual or eliminable register.  Used in places where
 ;; instantiation of such a register may cause the pattern to not be recognized.
openSUSE Build Service is sponsored by