[PATCH] Support IA-32 TLS @gotntpoff and @indntpoff

Jakub Jelinek jakub@redhat.com
Fri Sep 20 13:37:00 GMT 2002


Hi!

Bootstrapped on IA-32, no regressions. Ok to commit?
No direct %gs:foo access yet...

2002-09-20  Jakub Jelinek  <jakub@redhat.com>

	* config/i386/i386.md (UNSPEC_GOTNTPOFF, UNSPEC_INDNTPOFF): New.
	* config/i386/i386.c (legitimate_pic_address_disp_p): Handle
	UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF like UNSPEC_GOTTPOFF.
	(legitimate_address_p): Likewise.
	(legitimize_address): Use @gotntpoff and @indntpoff.
	(output_pic_addr_const): Handle UNSPEC_GOTNTPOFF and UNSPEC_INDNTPOFF.
	(output_addr_const_extra): Likewise.

--- gcc/config/i386/i386.md.jj	2002-09-20 12:14:40.000000000 +0200
+++ gcc/config/i386/i386.md	2002-09-20 18:24:00.000000000 +0200
@@ -61,6 +61,8 @@
    (UNSPEC_TPOFF		4)
    (UNSPEC_NTPOFF		5)
    (UNSPEC_DTPOFF		6)
+   (UNSPEC_GOTNTPOFF		7)
+   (UNSPEC_INDNTPOFF		8)
 
    ; Prologue support
    (UNSPEC_STACK_PROBE		10)
--- gcc/config/i386/i386.c.jj	2002-09-20 18:42:33.000000000 +0200
+++ gcc/config/i386/i386.c	2002-09-20 19:56:47.000000000 +0200
@@ -5077,6 +5077,8 @@ legitimate_pic_address_disp_p (disp)
     case UNSPEC_GOTOFF:
       return local_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
     case UNSPEC_GOTTPOFF:
+    case UNSPEC_GOTNTPOFF:
+    case UNSPEC_INDNTPOFF:
       if (saw_plus)
 	return false;
       return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
@@ -5258,6 +5260,8 @@ legitimate_address_p (mode, addr, strict
 	    goto is_legitimate_pic;
 
 	  case UNSPEC_GOTTPOFF:
+	  case UNSPEC_GOTNTPOFF:
+	  case UNSPEC_INDNTPOFF:
 	  case UNSPEC_NTPOFF:
 	  case UNSPEC_DTPOFF:
 	    break;
@@ -5658,38 +5662,43 @@ legitimize_address (x, oldx, mode)
 	  return gen_rtx_PLUS (Pmode, base, off);
 
         case TLS_MODEL_INITIAL_EXEC:
-	  if (flag_pic)
+	  if (flag_pic || !TARGET_GNU_TLS)
 	    {
-	      if (reload_in_progress)
-		regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
-	      pic = pic_offset_table_rtx;
-	    }
-	  else
-	    {
-	      pic = gen_reg_rtx (Pmode);
-	      emit_insn (gen_set_got (pic));
+	      if (flag_pic)
+		{
+		  if (reload_in_progress)
+		    regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+		  pic = pic_offset_table_rtx;
+		}
+	      else
+		{
+		  pic = gen_reg_rtx (Pmode);
+		  emit_insn (gen_set_got (pic));
+		}
 	    }
 
 	  base = get_thread_pointer ();
 
-	  off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_GOTTPOFF);
+	  off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
+				!TARGET_GNU_TLS
+				? UNSPEC_GOTTPOFF
+				: flag_pic ? UNSPEC_GOTNTPOFF
+					   : UNSPEC_INDNTPOFF);
 	  off = gen_rtx_CONST (Pmode, off);
-	  off = gen_rtx_PLUS (Pmode, pic, off);
+	  if (flag_pic || !TARGET_GNU_TLS)
+	    off = gen_rtx_PLUS (Pmode, pic, off);
 	  off = gen_rtx_MEM (Pmode, off);
 	  RTX_UNCHANGING_P (off) = 1;
 	  set_mem_alias_set (off, ix86_GOT_alias_set ());
-
-	  /* Damn Sun for specifing a set of dynamic relocations without
-	     considering the two-operand nature of the architecture!
-	     We'd be much better off with a "GOTNTPOFF" relocation that
-	     already contained the negated constant.  */
-	  /* ??? Using negl and reg+reg addressing appears to be a lose
-	     size-wise.  The negl is two bytes, just like the extra movl
-	     incurred by the two-operand subl, but reg+reg addressing
-	     uses the two-byte modrm form, unlike plain reg.  */
-
 	  dest = gen_reg_rtx (Pmode);
-	  emit_insn (gen_subsi3 (dest, base, off));
+
+	  if (TARGET_GNU_TLS)
+	    {
+	      emit_move_insn (dest, off);
+	      return gen_rtx_PLUS (Pmode, base, dest);
+	    }
+	  else
+	    emit_insn (gen_subsi3 (dest, base, off));
 	  break;
 
         case TLS_MODEL_LOCAL_EXEC:
@@ -5970,6 +5979,7 @@ output_pic_addr_const (file, x, code)
 	  fputs ("@GOTPCREL(%rip)", file);
 	  break;
 	case UNSPEC_GOTTPOFF:
+	  /* FIXME: This might be @TPOFF in Sun ld too.  */
 	  fputs ("@GOTTPOFF", file);
 	  break;
 	case UNSPEC_TPOFF:
@@ -5981,6 +5991,12 @@ output_pic_addr_const (file, x, code)
 	case UNSPEC_DTPOFF:
 	  fputs ("@DTPOFF", file);
 	  break;
+	case UNSPEC_GOTNTPOFF:
+	  fputs ("@GOTNTPOFF", file);
+	  break;
+	case UNSPEC_INDNTPOFF:
+	  fputs ("@INDNTPOFF", file);
+	  break;
 	default:
 	  output_operand_lossage ("invalid UNSPEC as operand");
 	  break;
@@ -6890,6 +6906,7 @@ output_addr_const_extra (file, x)
     {
     case UNSPEC_GOTTPOFF:
       output_addr_const (file, op);
+      /* FIXME: This might be @TPOFF in Sun ld.  */
       fputs ("@GOTTPOFF", file);
       break;
     case UNSPEC_TPOFF:
@@ -6904,6 +6921,14 @@ output_addr_const_extra (file, x)
       output_addr_const (file, op);
       fputs ("@DTPOFF", file);
       break;
+    case UNSPEC_GOTNTPOFF:
+      output_addr_const (file, op);
+      fputs ("@GOTNTPOFF", file);
+      break;
+    case UNSPEC_INDNTPOFF:
+      output_addr_const (file, op);
+      fputs ("@INDNTPOFF", file);
+      break;
 
     default:
       return false;

	Jakub



More information about the Gcc-patches mailing list