i386.md (indirect_jump): Allow Pmode operand.
authorJan Hubicka <jh@suse.cz>
Thu, 20 Sep 2001 10:21:40 +0000 (12:21 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 20 Sep 2001 10:21:40 +0000 (10:21 +0000)
* i386.md (indirect_jump): Allow Pmode operand.
(tablejump): LIkewise; perform expansion to 64bit mode.
* i386.c (symbolic_operand): Allow 64bit PIC references.
(pic_symbolic_operand): Likewise.
(ix86_find_base_term): Strip the 64bit PIC references.
(legitimate_pic_address_disp_p): Handle 64bit PIC.
(legitimize_pic_address): Likewise.
(i386_simplify_dwarf_addr): Strip down the 64bit PIC references.
* i386.h (CASE_VECTOR_MODE): Set to SImode for 64bit PIC compilation.

From-SVN: r45705

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 0d6f11f..6f039c6 100644 (file)
@@ -1,3 +1,15 @@
+Thu Sep 20 12:19:36 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (indirect_jump): Allow Pmode operand.
+       (tablejump): LIkewise; perform expansion to 64bit mode.
+       * i386.c (symbolic_operand): Allow 64bit PIC references.
+       (pic_symbolic_operand): Likewise.
+       (ix86_find_base_term): Strip the 64bit PIC references.
+       (legitimate_pic_address_disp_p): Handle 64bit PIC.
+       (legitimize_pic_address): Likewise.
+       (i386_simplify_dwarf_addr): Strip down the 64bit PIC references.
+       * i386.h (CASE_VECTOR_MODE): Set to SImode for 64bit PIC compilation.
+
 2001-09-19  Alan Modra  <amodra@bigpond.net.au>
            David Edelsohn  <edelsohn@gnu.org>
 
index 35c9dcf..c89a0ab 100644 (file)
@@ -1495,8 +1495,9 @@ symbolic_operand (op, mode)
       if (GET_CODE (op) == SYMBOL_REF
          || GET_CODE (op) == LABEL_REF
          || (GET_CODE (op) == UNSPEC
-             && XINT (op, 1) >= 6
-             && XINT (op, 1) <= 7))
+             && (XINT (op, 1) == 6
+                 || XINT (op, 1) == 7
+                 || XINT (op, 1) == 15)))
        return 1;
       if (GET_CODE (op) != PLUS
          || GET_CODE (XEXP (op, 1)) != CONST_INT)
@@ -1529,9 +1530,16 @@ pic_symbolic_operand (op, mode)
      register rtx op;
      enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  if (GET_CODE (op) == CONST)
+  if (GET_CODE (op) != CONST)
+    return 0;
+  op = XEXP (op, 0);
+  if (TARGET_64BIT)
+    {
+      if (GET_CODE (XEXP (op, 0)) == UNSPEC)
+       return 1;
+    }
+  else 
     {
-      op = XEXP (op, 0);
       if (GET_CODE (op) == UNSPEC)
        return 1;
       if (GET_CODE (op) != PLUS
@@ -3220,6 +3228,29 @@ ix86_find_base_term (x)
 {
   rtx term;
 
+  if (TARGET_64BIT)
+    {
+      if (GET_CODE (x) != CONST)
+       return x;
+      term = XEXP (x, 0);
+      if (GET_CODE (term) == PLUS
+         && (GET_CODE (XEXP (term, 1)) == CONST_INT
+             || GET_CODE (XEXP (term, 1)) == CONST_DOUBLE))
+       term = XEXP (term, 0);
+      if (GET_CODE (term) != UNSPEC
+         || XVECLEN (term, 0) != 1
+         || XINT (term, 1) !=  15)
+       return x;
+
+      term = XVECEXP (term, 0, 0);
+
+      if (GET_CODE (term) != SYMBOL_REF
+         && GET_CODE (term) != LABEL_REF)
+       return x;
+
+      return term;
+    }
+
   if (GET_CODE (x) != PLUS
       || XEXP (x, 0) != pic_offset_table_rtx
       || GET_CODE (XEXP (x, 1)) != CONST)
@@ -3251,10 +3282,42 @@ int
 legitimate_pic_address_disp_p (disp)
      register rtx disp;
 {
+  /* In 64bit mode we can allow direct addresses of symbols and labels
+     when they are not dynamic symbols.  */
+  if (TARGET_64BIT)
+    {
+      rtx x = disp;
+      if (GET_CODE (disp) == CONST)
+       x = XEXP (disp, 0);
+      /* ??? Handle PIC code models */
+      if (GET_CODE (x) == PLUS
+         && (GET_CODE (XEXP (x, 1)) == CONST_INT
+             && ix86_cmodel == CM_SMALL_PIC
+             && INTVAL (XEXP (x, 1)) < 1024*1024*1024
+             && INTVAL (XEXP (x, 1)) > -1024*1024*1024))
+       x = XEXP (x, 0);
+      if (local_symbolic_operand (x, Pmode))
+       return 1;
+    }
   if (GET_CODE (disp) != CONST)
     return 0;
   disp = XEXP (disp, 0);
 
+  if (TARGET_64BIT)
+    {
+      /* We are unsafe to allow PLUS expressions.  This limit allowed distance
+         of GOT tables.  We should not need these anyway.  */
+      if (GET_CODE (disp) != UNSPEC
+         || XVECLEN (disp, 0) != 1
+         || XINT (disp, 1) != 15)
+       return 0;
+
+      if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
+         && GET_CODE (XVECEXP (disp, 0, 0)) != LABEL_REF)
+       return 0;
+      return 1;
+    }
+
   if (GET_CODE (disp) == PLUS)
     {
       if (GET_CODE (XEXP (disp, 1)) != CONST_INT)
@@ -3576,16 +3639,23 @@ legitimize_pic_address (orig, reg)
          if (local_symbolic_operand (op0, Pmode)
              && GET_CODE (op1) == CONST_INT)
            {
-             current_function_uses_pic_offset_table = 1;
-             new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
-             new = gen_rtx_PLUS (Pmode, new, op1);
-             new = gen_rtx_CONST (Pmode, new);
-             new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
+             if (!TARGET_64BIT)
+               {
+                 current_function_uses_pic_offset_table = 1;
+                 new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 7);
+                 new = gen_rtx_PLUS (Pmode, new, op1);
+                 new = gen_rtx_CONST (Pmode, new);
+                 new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new);
 
-             if (reg != 0)
+                 if (reg != 0)
+                   {
+                     emit_move_insn (reg, new);
+                     new = reg;
+                   }
+               }
+             else
                {
-                 emit_move_insn (reg, new);
-                 new = reg;
+                 /* ??? We need to limit offsets here.  */
                }
            }
          else
@@ -3900,6 +3970,9 @@ output_pic_addr_const (file, x, code)
        case 8:
          fputs ("@PLT", file);
          break;
+       case 15:
+         fputs ("@GOTPCREL(%RIP)", file);
+         break;
        default:
          output_operand_lossage ("invalid UNSPEC as operand");
          break;
@@ -3937,6 +4010,15 @@ i386_simplify_dwarf_addr (orig_x)
 {
   rtx x = orig_x;
 
+  if (TARGET_64BIT)
+    {
+      if (GET_CODE (x) != CONST
+         || GET_CODE (XEXP (x, 0)) != UNSPEC
+         || XINT (XEXP (x, 0), 1) != 15)
+       return orig_x;
+      return XVECEXP (XEXP (x, 0), 0, 0);
+    }
+
   if (GET_CODE (x) != PLUS
       || GET_CODE (XEXP (x, 0)) != REG
       || GET_CODE (XEXP (x, 1)) != CONST)
index 1a1715e..86e83df 100644 (file)
@@ -2244,7 +2244,7 @@ while (0)
 \f
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
-#define CASE_VECTOR_MODE Pmode
+#define CASE_VECTOR_MODE (!TARGET_64BIT || flag_pic ? SImode : DImode)
 
 /* Define as C expression which evaluates to nonzero if the tablejump
    instruction expects the table to contain offsets from the address of the
index 797431f..ef5d0fc 100644 (file)
   [(set_attr "type" "ibr")])
 
 (define_insn "indirect_jump"
-  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+  [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))]
   ""
   "jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
 (define_expand "tablejump"
-  [(parallel [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
+  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" "rm"))
              (use (label_ref (match_operand 1 "" "")))])]
   ""
 {
      the relative address to an absolute address.  */
   if (flag_pic)
     {
-      operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
-                                        operands[0], NULL_RTX, 1,
-                                        OPTAB_DIRECT);
-      current_function_uses_pic_offset_table = 1;
+      if (TARGET_64BIT)
+       operands[0] = expand_simple_binop (Pmode, PLUS, operands[0],
+                                          operands[1], NULL_RTX, 0,
+                                          OPTAB_DIRECT);
+      else
+       {
+         operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
+                                            operands[0], NULL_RTX, 1,
+                                            OPTAB_DIRECT);
+         current_function_uses_pic_offset_table = 1;
+       }
     }
 })