Microblaze Target: PIC data text relative
authorAndrew Sadek <andrew.sadek.se@gmail.com>
Mon, 30 Apr 2018 11:16:55 +0000 (11:16 +0000)
committerMichael Eager <eager@gcc.gnu.org>
Mon, 30 Apr 2018 11:16:55 +0000 (11:16 +0000)
2018-04-30 Andrew Sadek  <andrew.sadek.se@gmail.com>

gcc/ChangeLog:
* config/microblaze/microblaze.opt: add new option -mpic-data-text-rel.
* config/microblaze/microblaze-protos.h (microblaze_constant_address_p):
Add declaration.
* gcc/config/microblaze/microblaze.h (microblaze_constant_address_p):
CONSTANT_ADDRESS_P definition to microblaze_constant_address_p.
* config/microblaze/microblaze.c (TARGET_PIC_DATA_TEXT_REL):
New addressing mode for data-text relative position indepenedent code.
(microblaze_classify_unspec): add 'UNSPEC_TEXT' case ->
'ADDRESS_SYMBOLIC_TXT_REL'.
(microblaze_classify_address): Add handling for UNSPEC + CONST_INT.
(microblaze_legitimate_pic_operand): Exclude function calls from
pic operands in case of TARGET_PIC_DATA_TEXT_REL option.
(microblaze_legitimize_address): Generate 'UNSPEC_TEXT' for all possible
addresses cases.
(microblaze_address_insns): Add 'ADDRESS_SYMBOLIC_TXT_REL' case.
(print_operand): Add 'ADDRESS_SYMBOLIC_TXT_REL' case.
(print_operand_address): Add 'ADDRESS_SYMBOLIC_TXT_REL' case + handling
for 'address + offset'.
(microblaze_expand_prologue): Add new function prologue call for
'r20' assignation.
(microblaze_asm_generate_pic_addr_dif_vec): Override new target hook
'TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC' to disable address diff vector
table in case of TARGET_PIC_DATA_TEXT_REL.
(expand_pic_symbol_ref): Add handling for 'UNSPEC_TEXT'.
* gcc/config/microblaze/microblaze.md (TARGET_PIC_DATA_TEXT_REL):
Add new macros 'UNSPEC_TEXT',
'UNSPEC_SET_TEXT' + add rule for setting r20 in function prologue
+ exclude function calls from 'UNSPEC_PLT' in case of data text
relative mode.
* doc/tm.texi.in (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Add
new target hook for generating address diff vector tables in case of
flag_pic.
* doc/tm.texi : Regenerate.
* stmt.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Append new condition
'targetm.asm_out.generate_pic_addr_diff_vec' to flag_pic in case
of addr diff vector generation.
* target.def (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Add
target hook definition.
* targhooks.h, gcc/targhooks.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC):
Add default function for generate_pic_addr_diff_vec -> flag_pic.
* doc/invoke.texi (Add new pic option): Add new microblaze pic
option for data text relative.

testsuite/ChangeLog:
* gcc.target/microblaze/others/data_var1.c: Include
PIC case of r20 base register.
* gcc.target/microblaze/others/data_var2.c: Ditto.
* gcc.target/microblaze/others/picdtr.c: Add new
test case for -mpic-is-data-text-relative.
* gcc.target/microblaze/others/sdata_var1.c: Add
* gcc.target/microblaze/others/sdata_var2.c: Ditto.
* gcc.target/microblaze/others/sdata_var3.c: Ditto.
* gcc.target/microblaze/others/sdata_var4.c: Ditto.
* gcc.target/microblaze/others/sdata_var5.c: Ditto.
* gcc.target/microblaze/others/sdata_var6.c: Ditto.
* gcc.target/microblaze/others/string_cst1_gpopt.c: Ditto.
* gcc.target/microblaze/others/string_cst2_gpopt.c: Ditto.

From-SVN: r259758

24 files changed:
gcc/ChangeLog
gcc/config/microblaze/microblaze-protos.h
gcc/config/microblaze/microblaze.c
gcc/config/microblaze/microblaze.h
gcc/config/microblaze/microblaze.md
gcc/config/microblaze/microblaze.opt
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/stmt.c
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/microblaze/others/data_var1.c
gcc/testsuite/gcc.target/microblaze/others/data_var2.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var1.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var2.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var3.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var4.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var5.c
gcc/testsuite/gcc.target/microblaze/others/sdata_var6.c
gcc/testsuite/gcc.target/microblaze/others/string_cst1_gpopt.c
gcc/testsuite/gcc.target/microblaze/others/string_cst2_gpopt.c

index 5edb052836a4d63ceeec884f0395bf84331c6286..0949337a68428cbe5688a935ab1b8001d0559acf 100644 (file)
@@ -1,3 +1,50 @@
+2018-04-30 Andrew Sadek  <andrew.sadek.se@gmail.com>
+
+       Microblaze Target: PIC data text relative
+
+       * config/microblaze/microblaze.opt: add new option -mpic-data-text-rel.
+       * config/microblaze/microblaze-protos.h (microblaze_constant_address_p):
+       Add declaration.
+       * gcc/config/microblaze/microblaze.h (microblaze_constant_address_p):
+       CONSTANT_ADDRESS_P definition to microblaze_constant_address_p.
+       * config/microblaze/microblaze.c (TARGET_PIC_DATA_TEXT_REL):
+       New addressing mode for data-text relative position indepenedent code.
+       (microblaze_classify_unspec): add 'UNSPEC_TEXT' case ->
+       'ADDRESS_SYMBOLIC_TXT_REL'.
+       (microblaze_classify_address): Add handling for UNSPEC + CONST_INT.
+       (microblaze_legitimate_pic_operand): Exclude function calls from
+       pic operands in case of TARGET_PIC_DATA_TEXT_REL option.
+       (microblaze_legitimize_address): Generate 'UNSPEC_TEXT' for all possible
+       addresses cases.
+       (microblaze_address_insns): Add 'ADDRESS_SYMBOLIC_TXT_REL' case.
+       (print_operand): Add 'ADDRESS_SYMBOLIC_TXT_REL' case.
+       (print_operand_address): Add 'ADDRESS_SYMBOLIC_TXT_REL' case + handling
+       for 'address + offset'.
+       (microblaze_expand_prologue): Add new function prologue call for
+       'r20' assignation.
+       (microblaze_asm_generate_pic_addr_dif_vec): Override new target hook
+       'TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC' to disable address diff vector
+       table in case of TARGET_PIC_DATA_TEXT_REL.
+       (expand_pic_symbol_ref): Add handling for 'UNSPEC_TEXT'.
+       * gcc/config/microblaze/microblaze.md (TARGET_PIC_DATA_TEXT_REL):
+       Add new macros 'UNSPEC_TEXT',
+       'UNSPEC_SET_TEXT' + add rule for setting r20 in function prologue
+       + exclude function calls from 'UNSPEC_PLT' in case of data text
+       relative mode.
+       * doc/tm.texi.in (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Add
+       new target hook for generating address diff vector tables in case of
+       flag_pic.
+       * doc/tm.texi : Regenerate.
+       * stmt.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Append new condition
+       'targetm.asm_out.generate_pic_addr_diff_vec' to flag_pic in case
+       of addr diff vector generation.
+       * target.def (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC): Add
+       target hook definition.
+       * targhooks.h, gcc/targhooks.c (TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC):
+       Add default function for generate_pic_addr_diff_vec -> flag_pic.
+       * doc/invoke.texi (Add new pic option): Add new microblaze pic
+       option for data text relative.
+
 2018-04-30  Richard Biener  <rguenther@suse.de>
 
        * tree-chrec.h (evolution_function_is_constant_p): Remove
index 4cbba0c639f609a6dc0b2a41c94fd8bd50218d50..515b713a3d793aaa8fc7c73c6cab7ccb8d393eb0 100644 (file)
@@ -24,6 +24,7 @@
 
 #ifdef RTX_CODE
 extern int pic_address_needs_scratch (rtx);
+extern bool microblaze_constant_address_p (rtx x);
 extern void expand_block_move        (rtx *);
 extern void microblaze_expand_prologue (void);
 extern void microblaze_expand_epilogue (void);
index 9a4a287be2345b544421180a888e3d13ff8dffc2..06aa50e25560eba2bb13a4d165894328bb2e3280 100644 (file)
@@ -91,7 +91,8 @@ enum microblaze_address_type
   ADDRESS_SYMBOLIC,
   ADDRESS_GOTOFF,
   ADDRESS_PLT,
-  ADDRESS_TLS
+  ADDRESS_TLS,
+  ADDRESS_SYMBOLIC_TXT_REL
 };
 
 /* Classifies symbols
@@ -650,6 +651,10 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
       info->type = ADDRESS_TLS;
       info->tls_type = tls_reloc (INTVAL (XVECEXP (x, 0, 1)));
     }
+  else if (XINT (x, 1) == UNSPEC_TEXT)
+    {
+      info->type = ADDRESS_SYMBOLIC_TXT_REL;
+    }
   else
     {
       return false;
@@ -701,8 +706,10 @@ get_base_reg (rtx x)
 }
 
 /* Return true if X is a valid address for machine mode MODE.  If it is,
-   fill in INFO appropriately.  STRICT is true if we should only accept
-   hard base registers.  
+   fill in INFO appropriately.
+   STRICT > 0 if we should only accept hard base registers.
+   STRICT = 2 if the operand address is being printed thus
+   function has been called by print_operand_address.
 
       type                     regA      regB    offset      symbol
 
@@ -728,6 +735,7 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
 {
   rtx xplus0;
   rtx xplus1;
+  rtx offset;
 
   info->type = ADDRESS_INVALID;
   info->regA = NULL;
@@ -735,6 +743,7 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
   info->offset = NULL;
   info->symbol = NULL;
   info->symbol_type = SYMBOL_TYPE_INVALID;
+  offset = NULL;
 
   switch (GET_CODE (x))
     {
@@ -795,8 +804,13 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
                /* for (plus x const_int) just look at x.  */
                if (GET_CODE (xconst0) == PLUS
                    && GET_CODE (XEXP (xconst0, 1)) == CONST_INT
-                   && SMALL_INT (XEXP (xconst0, 1)))
+                   && (SMALL_INT (XEXP (xconst0, 1))
+                      || GET_CODE (XEXP (xconst0, 0)) == UNSPEC))
                  {
+                   /* Hold CONST_INT Value in offset in case of
+                      UNSPEC + CONST_INT.  */
+                   offset = XEXP (xconst0, 1);
+
                    /* This is ok as info->symbol is set to xplus1 the full
                       const-expression below.  */
                    xconst0 = XEXP (xconst0, 0);
@@ -814,6 +828,15 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
                    return true;
                  }
 
+               if (GET_CODE (xconst0) == UNSPEC && TARGET_PIC_DATA_TEXT_REL)
+                 {
+                   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+                     return false;
+
+                   info->offset = offset;
+                   return microblaze_classify_unspec (info, xconst0);
+                 }
+
                /* Not base + symbol || base + UNSPEC.  */
                return false;
 
@@ -858,6 +881,15 @@ microblaze_classify_address (struct microblaze_address_info *info, rtx x,
             return !(flag_pic && pic_address_needs_scratch (x));
          }
 
+       /* Avoid error in print_operand_address in case UNSPEC
+        is removed from SYMBOL or LABEL REFS during optimization.  */
+       if ((GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+           && flag_pic && TARGET_PIC_DATA_TEXT_REL && strict == 2)
+         {
+           info->type = ADDRESS_SYMBOLIC_TXT_REL;
+           return true;
+         }
+
        if (flag_pic == 2)
          return false;
        else if (microblaze_tls_symbol_p(x))
@@ -893,6 +925,15 @@ microblaze_legitimate_address_p (machine_mode mode, rtx x, bool strict)
   return microblaze_classify_address (&addr, x, mode, strict);
 }
 
+bool
+microblaze_constant_address_p (rtx x)
+{
+  return ((GET_CODE (x) == LABEL_REF) || (GET_CODE (x) == SYMBOL_REF)
+         || GET_CODE (x) == CONST_INT
+         || (GET_CODE (x) == CONST
+         && ! (flag_pic && pic_address_needs_scratch (x))));
+}
+
 int
 microblaze_valid_pic_const (rtx x)
 {
@@ -910,7 +951,8 @@ microblaze_valid_pic_const (rtx x)
 int
 microblaze_legitimate_pic_operand (rtx x)
 {
-  if (flag_pic == 2 && (symbol_mentioned_p(x) || label_mentioned_p(x)))
+  if (flag_pic == 2 && (symbol_mentioned_p (x) || label_mentioned_p (x))
+      && !(TARGET_PIC_DATA_TEXT_REL && call_insn_operand (x,VOIDmode)))
     return 0;
 
   if (microblaze_tls_referenced_p(x))
@@ -1024,17 +1066,35 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
                }
              else if (flag_pic == 2)
                {
-                 rtx pic_ref, reg;
-                 reg = gen_reg_rtx (Pmode);
-
-                 pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xplus1),
-                                           UNSPEC_GOTOFF);
-                 pic_ref = gen_rtx_CONST (Pmode, pic_ref);
-                 pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
-                 pic_ref = gen_const_mem (Pmode, pic_ref);
-                 emit_move_insn (reg, pic_ref);
-                 result = gen_rtx_PLUS (Pmode, xplus0, reg);
-                 return result;
+                 if (!TARGET_PIC_DATA_TEXT_REL)
+                   {
+                     rtx pic_ref, reg;
+                     reg = gen_reg_rtx (Pmode);
+
+                     pic_ref = gen_rtx_UNSPEC (Pmode,
+                                               gen_rtvec (1, xplus1),
+                                               UNSPEC_GOTOFF);
+                     pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+                     pic_ref = gen_rtx_PLUS (Pmode,
+                                             pic_offset_table_rtx, pic_ref);
+                     pic_ref = gen_const_mem (Pmode, pic_ref);
+                     emit_move_insn (reg, pic_ref);
+                     result = gen_rtx_PLUS (Pmode, xplus0, reg);
+                     return result;
+                   }
+                 else
+                   {
+                     rtx pic_ref, reg;
+                     reg = gen_reg_rtx (Pmode);
+                     pic_ref = gen_rtx_UNSPEC (Pmode,
+                                               gen_rtvec (1, xplus1),
+                                               UNSPEC_TEXT);
+                     pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+                     emit_insn (gen_addsi3 (reg,
+                                pic_offset_table_rtx, xplus0));
+                     result = gen_rtx_PLUS (Pmode, reg, pic_ref);
+                     return result;
+                   }
                }
            }
        }
@@ -1047,19 +1107,31 @@ microblaze_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
         {
           reg = microblaze_legitimize_tls_address (xinsn, NULL_RTX);
         }
-      else
+      else if (flag_pic == 2)
         {
-          rtx pic_ref;
+         if (reload_in_progress)
+           df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
 
-          if (reload_in_progress)
-            df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
+         if (!TARGET_PIC_DATA_TEXT_REL)
+           {
+             rtx pic_ref;
 
-          pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
-          pic_ref = gen_rtx_CONST (Pmode, pic_ref);
-          pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
-          pic_ref = gen_const_mem (Pmode, pic_ref);
-          reg = pic_ref;
-        }
+             pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_GOTOFF);
+             pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+             pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+             pic_ref = gen_const_mem (Pmode, pic_ref);
+             reg = pic_ref;
+           }
+         else
+           {
+             rtx pic_ref;
+
+             pic_ref = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xinsn), UNSPEC_TEXT);
+             pic_ref = gen_rtx_CONST (Pmode, pic_ref);
+             pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pic_ref);
+             reg = pic_ref;
+           }
+       }
       return reg;
     }
 
@@ -1388,6 +1460,7 @@ microblaze_address_insns (rtx x, machine_mode mode)
        case ADDRESS_REG_INDEX:
          return 1;
        case ADDRESS_SYMBOLIC:
+       case ADDRESS_SYMBOLIC_TXT_REL:
        case ADDRESS_GOTOFF:
          return 2;
        case ADDRESS_TLS:
@@ -2066,7 +2139,7 @@ compute_frame_size (HOST_WIDE_INT size)
 
   total_size = var_size + args_size;
 
-  if (flag_pic == 2)
+  if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL)
     /* force setting GOT.  */
     df_set_regs_ever_live (MB_ABI_PIC_ADDR_REGNUM, true);
 
@@ -2322,6 +2395,7 @@ print_operand (FILE * file, rtx op, int letter)
            case ADDRESS_REG:
            case ADDRESS_CONST_INT:
            case ADDRESS_SYMBOLIC:
+           case ADDRESS_SYMBOLIC_TXT_REL:
            case ADDRESS_GOTOFF:
            case ADDRESS_TLS:
              fputs ("i", file);
@@ -2489,7 +2563,7 @@ print_operand_address (FILE * file, rtx addr)
 {
   struct microblaze_address_info info;
   enum microblaze_address_type type;
-  if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 1))
+  if (!microblaze_classify_address (&info, addr, GET_MODE (addr), 2))
     fatal_insn ("insn contains an invalid address !", addr);
 
   type = info.type;
@@ -2515,6 +2589,7 @@ print_operand_address (FILE * file, rtx addr)
       output_addr_const (file, info.offset);
       break;
     case ADDRESS_SYMBOLIC:
+    case ADDRESS_SYMBOLIC_TXT_REL:
     case ADDRESS_GOTOFF:
     case ADDRESS_PLT:
     case ADDRESS_TLS:
@@ -2529,6 +2604,16 @@ print_operand_address (FILE * file, rtx addr)
        {
          fputs ("@PLT", file);
        }
+      else if (type == ADDRESS_SYMBOLIC_TXT_REL)
+    {
+      if (info.offset != NULL && CONST_INT_P (info.offset)
+         && INTVAL (info.offset) > 0)
+       {
+         fprintf (file, "+");
+         output_addr_const (file, info.offset);
+       }
+      fputs ("@TXTREL", file);
+    }
       else if (type == ADDRESS_TLS)
        {
          switch (info.tls_type)
@@ -2888,7 +2973,6 @@ microblaze_expand_prologue (void)
   if (flag_stack_usage_info)
     current_function_static_stack_size = fsiz;
 
-
   /* If this function is a varargs function, store any registers that
      would normally hold arguments ($5 - $10) on the stack.  */
   if (((TYPE_ARG_TYPES (fntype) != 0
@@ -2913,7 +2997,6 @@ microblaze_expand_prologue (void)
 
          offset += GET_MODE_SIZE (SImode);
        }
-
     }
 
   if (fsiz > 0)
@@ -2960,8 +3043,18 @@ microblaze_expand_prologue (void)
   if ((flag_pic == 2 || TLS_NEEDS_GOT )
       && df_regs_ever_live_p (MB_ABI_PIC_ADDR_REGNUM))
     {
-      SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
-      emit_insn (gen_set_got (pic_offset_table_rtx));  /* setting GOT.  */
+      if ((flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL) || TLS_NEEDS_GOT)
+       {
+         SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
+         /* setting GOT.  */
+         emit_insn (gen_set_got (pic_offset_table_rtx));
+       }
+      else
+       {
+         SET_REGNO (pic_offset_table_rtx, MB_ABI_PIC_ADDR_REGNUM);
+         /* setting start of text.  */
+         emit_insn (gen_set_text (pic_offset_table_rtx));
+       }
     }
 
   /* If we are profiling, make sure no instructions are scheduled before
@@ -3154,6 +3247,14 @@ microblaze_elf_in_small_data_p (const_tree decl)
   return (size > 0 && size <= microblaze_section_threshold);
 }
 
+/* We need to disable address diff vectors in
+case of pic data text relative mode.  */
+
+static bool
+microblaze_gen_pic_addr_dif_vec (void)
+{
+  return (flag_pic && !TARGET_PIC_DATA_TEXT_REL);
+}
 
 static section *
 microblaze_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
@@ -3187,10 +3288,19 @@ static rtx
 expand_pic_symbol_ref (machine_mode mode ATTRIBUTE_UNUSED, rtx op)
 {
   rtx result;
-  result = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF);
+  bool isFunc = (GET_CODE (op) == SYMBOL_REF
+                && (SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_FUNCTION));
+  result = (!TARGET_PIC_DATA_TEXT_REL)
+           ? gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_GOTOFF)
+           : gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op), UNSPEC_TEXT);
   result = gen_rtx_CONST (Pmode, result);
-  result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
-  result = gen_const_mem (Pmode, result);
+  result = (TARGET_PIC_DATA_TEXT_REL && isFunc)
+           ? gen_rtx_PLUS (Pmode, gen_raw_REG (Pmode,
+                           get_base_reg (op)), result)
+           : gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
+  result = (!TARGET_PIC_DATA_TEXT_REL)
+           ? gen_const_mem (Pmode, result) : result;
+
   return result;
 }
 
@@ -3294,10 +3404,37 @@ microblaze_expand_move (machine_mode mode, rtx operands[])
          if (reload_in_progress)
            df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
          result = expand_pic_symbol_ref (mode, op1);
+
+         if (TARGET_PIC_DATA_TEXT_REL && GET_CODE (op0) == REG
+             && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
+           result = force_reg (SImode, result);
+
          emit_move_insn (op0, result);
          return true;
        }
     }
+  if (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1,1)) == CONST)
+    {
+      rtx p0, p1, result, temp;
+
+      p0 = XEXP (XEXP (op1,1), 0);
+
+      if (GET_CODE (p0) == PLUS)
+       {
+         p1 = XEXP (p0, 1);
+         p0 = XEXP (p0, 0);
+       }
+
+      if (GET_CODE (p0) == UNSPEC && GET_CODE (p1) == CONST_INT
+         && flag_pic && TARGET_PIC_DATA_TEXT_REL)
+       {
+         result = gen_rtx_CONST (Pmode, p0);
+         result = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, result);
+         temp = force_reg (SImode, result);
+         emit_move_insn (op0, gen_rtx_PLUS (SImode, temp, p1));
+         return true;
+       }
+    }
   /* Handle Case of (const (plus symbol const_int)).  */
   if (GET_CODE (op1) == CONST && GET_CODE (XEXP (op1,0)) == PLUS)
     {
@@ -3912,6 +4049,9 @@ microblaze_starting_frame_offset (void)
 #undef TARGET_LEGITIMATE_CONSTANT_P
 #define TARGET_LEGITIMATE_CONSTANT_P microblaze_legitimate_constant_p
 
+#undef  TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC
+#define TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC  microblaze_gen_pic_addr_dif_vec
+
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG microblaze_machine_dependent_reorg
 
index 0d3718f417ba01abdc873a9354c475ecf87eedab..c05bed6e323b733d02ad9564995749b28bf5026d 100644 (file)
@@ -518,11 +518,7 @@ typedef struct microblaze_args
 
 /* Identify valid constant addresses.  Exclude if PIC addr which 
    needs scratch register.  */
-#define CONSTANT_ADDRESS_P(X)                                          \
-  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF             \
-    || GET_CODE (X) == CONST_INT                                       \
-    || (GET_CODE (X) == CONST                                          \
-       && ! (flag_pic && pic_address_needs_scratch (X))))
+#define CONSTANT_ADDRESS_P(X)  microblaze_constant_address_p(X)
 
 /* Define this, so that when PIC, reload won't try to reload invalid
    addresses which require two reload registers.  */
index f698e541c23858c6c3ec7499e7584e8e44528e73..bec346f60ff60e780f00f19f370e7ebd43266f38 100644 (file)
@@ -41,6 +41,8 @@
   (UNSPEC_CMP          104)    ;; signed compare
   (UNSPEC_CMPU         105)    ;; unsigned compare
   (UNSPEC_TLS           106)    ;; jump table
+  (UNSPEC_SET_TEXT      107)    ;; set text start
+  (UNSPEC_TEXT          108)    ;; data text relative
 ])
 
 (define_c_enum "unspec" [
   {
     gcc_assert (GET_MODE (operands[0]) == Pmode);
 
-    if (!flag_pic)
+    if (!flag_pic || TARGET_PIC_DATA_TEXT_REL)
       emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
     else
       emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
   {
     rtx addr = XEXP (operands[0], 0);
 
-    if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF 
+    if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL
+    && GET_CODE (addr) == SYMBOL_REF
        && !SYMBOL_REF_LOCAL_P (addr)) 
       {
         rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
   {
     rtx addr = XEXP (operands[1], 0);
 
-    if (flag_pic == 2 && GET_CODE (addr) == SYMBOL_REF
+    if (flag_pic == 2 && !TARGET_PIC_DATA_TEXT_REL
+    && GET_CODE (addr) == SYMBOL_REF
        && !SYMBOL_REF_LOCAL_P (addr)) 
       {
         rtx temp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_PLT);
   [(set_attr "type" "multi")
    (set_attr "length" "12")])
 
+;; The insn to set TEXT.
+;; The hardcoded number "8" accounts for $pc difference
+;; between "mfs" and "addik" instructions.
+(define_insn "set_text"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+    (unspec:SI[(const_int 0)] UNSPEC_SET_TEXT))]
+  ""
+  "mfs\t%0,rpc\n\taddik\t%0,%0,8@TXTPCREL"
+  [(set_attr "type" "multi")
+   (set_attr "length" "12")])
+
+
 ;; This insn gives the count of leading number of zeros for the second
 ;; operand and stores the result in first operand.
 (define_insn "clzsi2"
index 8242998233353c0c2b33a0ffe4b3324bb2039bdc..2f34541c225118ce276237794af72766de8011c1 100644 (file)
@@ -127,5 +127,9 @@ mxl-prefetch
 Target Mask(PREFETCH)
 Use hardware prefetch instruction
 
+mpic-data-is-text-relative
+Target Mask(PIC_DATA_TEXT_REL)
+Data referenced by offset from start of text instead of GOT (with -fPIC/-fPIE).
+
 mxl-mode-xilkernel
 Target
index 444159178a76e58f3fbcc4d1c7de981c4fddc623..e45f467155a7d0b85c39937ae2708b0c6ca70463 100644 (file)
@@ -867,7 +867,8 @@ Objective-C and Objective-C++ Dialects}.
 -mmemcpy  -mxl-soft-mul  -mxl-soft-div  -mxl-barrel-shift @gol
 -mxl-pattern-compare  -mxl-stack-check  -mxl-gp-opt  -mno-clearbss @gol
 -mxl-multiply-high  -mxl-float-convert  -mxl-float-sqrt @gol
--mbig-endian  -mlittle-endian  -mxl-reorder  -mxl-mode-@var{app-model}}
+-mbig-endian  -mlittle-endian  -mxl-reorder  -mxl-mode-@var{app-model}
+-mpic-data-is-text-relative}
 
 @emph{MIPS Options}
 @gccoptlist{-EL  -EB  -march=@var{arch}  -mtune=@var{arch} @gol
@@ -20113,6 +20114,12 @@ Select application model @var{app-model}.  Valid models are
 @item executable
 normal executable (default), uses startup code @file{crt0.o}.
 
+@item -mpic-data-is-text-relative
+@opindex mpic-data-is-text-relative
+Assume that the displacement between the text and data segments is fixed
+at static link time.  This allows data to be referenced by offset from start of
+text address instead of GOT since PC-relative addressing is not supported.
+
 @item xmdstub
 for use with Xilinx Microprocessor Debugger (XMD) based
 software intrusive debug agent called xmdstub. This uses startup file
index bd8b917ba8296007400066aadbfc45d9a67f6bcd..9d92ed1c3d387c4371b36dafadb86022d365b50e 100644 (file)
@@ -7491,6 +7491,14 @@ when the target cannot support (some kinds of) dynamic relocations
 in read-only sections even in executables.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC (void)
+Return true to generate ADDR_DIF_VEC table
+or false to generate ADDR_VEC table for jumps in case of -fPIC.
+
+The default version of this function returns true if flag_pic
+equals true and false otherwise
+@end deftypefn
+
 @deftypefn {Target Hook} {section *} TARGET_ASM_SELECT_SECTION (tree @var{exp}, int @var{reloc}, unsigned HOST_WIDE_INT @var{align})
 Return the section into which @var{exp} should be placed.  You can
 assume that @var{exp} is either a @code{VAR_DECL} node or a constant of
index b0207146e8c2444f1e8f3c1fdaf724df14966f73..5732a2a4515ac7b087bfe328f43983f429b69773 100644 (file)
@@ -4922,6 +4922,8 @@ This macro is irrelevant if there is no separate readonly data section.
 
 @hook TARGET_ASM_RELOC_RW_MASK
 
+@hook TARGET_ASM_GENERATE_PIC_ADDR_DIFF_VEC
+
 @hook TARGET_ASM_SELECT_SECTION
 
 @defmac USE_SELECT_SECTION_FOR_FUNCTIONS
index 9493dccf734b9e668231ce47ca0978d4b84f22e1..b8df18181377a13923000f7f85c0706c7ac08252 100644 (file)
@@ -853,7 +853,8 @@ emit_case_dispatch_table (tree index_expr, tree index_type,
   /* Output the table.  */
   emit_label (table_label);
 
-  if (CASE_VECTOR_PC_RELATIVE || flag_pic)
+  if (CASE_VECTOR_PC_RELATIVE
+         || (flag_pic && targetm.asm_out.generate_pic_addr_diff_vec ()))
     emit_jump_table_data (gen_rtx_ADDR_DIFF_VEC (CASE_VECTOR_MODE,
                                                 gen_rtx_LABEL_REF (Pmode,
                                                                    table_label),
index c5b2a1e7e71fe853f804711ba96d6f9ad13fddc1..2f7bca99ec24880ae69975160298b42476a2aae4 100644 (file)
@@ -507,6 +507,18 @@ in read-only sections even in executables.",
  int, (void),
  default_reloc_rw_mask)
 
+ /* Return a flag for either generating ADDR_DIF_VEC table
+ or ADDR_VEC table for jumps in case of -fPIC/-fPIE.  */
+DEFHOOK
+(generate_pic_addr_diff_vec,
+"Return true to generate ADDR_DIF_VEC table\n\
+or false to generate ADDR_VEC table for jumps in case of -fPIC.\n\
+\n\
+The default version of this function returns true if flag_pic\n\
+equals true and false otherwise",
+ bool, (void),
+ default_generate_pic_addr_diff_vec)
+
  /* Return a section for EXP.  It may be a DECL or a constant.  RELOC
     is nonzero if runtime relocations must be applied; bit 1 will be
     set if the runtime relocations require non-local name resolution.
index fafcc6c5196640edea8b89e55ec16d28254eb323..749e24ae17875f1b07c6d2b3cdeb8d18e7143aea 100644 (file)
@@ -1196,6 +1196,15 @@ default_reloc_rw_mask (void)
   return flag_pic ? 3 : 0;
 }
 
+/* By default, address diff vectors are generated
+for jump tables when flag_pic is true.  */
+
+bool
+default_generate_pic_addr_diff_vec (void)
+{
+  return flag_pic;
+}
+
 /* By default, do no modification. */
 tree default_mangle_decl_assembler_name (tree decl ATTRIBUTE_UNUSED,
                                         tree id)
index 8a4393f2ba40b8de7bd4d70b34d01fbf2ecd3687..56951556525e94cfee1838c57d5fc49fe52efa75 100644 (file)
@@ -175,6 +175,7 @@ extern machine_mode default_secondary_memory_needed_mode (machine_mode);
 extern void default_target_option_override (void);
 extern void hook_void_bitmap (bitmap);
 extern int default_reloc_rw_mask (void);
+extern bool default_generate_pic_addr_diff_vec (void);
 extern tree default_mangle_decl_assembler_name (tree, tree);
 extern tree default_emutls_var_fields (tree, tree *);
 extern tree default_emutls_var_init (tree, tree, tree);
index c41d69b4a2123be4972dd93bbd7063826dd3bb8d..093cd365662433ef32dbc2892ffa15121a90a217 100644 (file)
@@ -1,3 +1,23 @@
+2018-04-30 Andrew Sadek  <andrew.sadek.se@gmail.com>
+
+       Microblaze Target: PIC data text relative
+
+       * gcc.target/microblaze/others/data_var1.c: Include
+       PIC case of r20 base register.
+       * gcc.target/microblaze/others/data_var2.c: Ditto.
+       * gcc.target/microblaze/others/picdtr.c: Add new
+       test case for -mpic-is-data-text-relative.
+       * gcc.target/microblaze/others/sdata_var1.c: Add
+       * gcc.target/microblaze/others/sdata_var2.c: Ditto.
+       * gcc.target/microblaze/others/sdata_var3.c: Ditto.
+       * gcc.target/microblaze/others/sdata_var4.c: Ditto.
+       * gcc.target/microblaze/others/sdata_var5.c: Ditto.
+       * gcc.target/microblaze/others/sdata_var6.c: Ditto.
+       * gcc.target/microblaze/others/string_cst1_gpopt.c:
+       Ditto.
+       * gcc.target/microblaze/others/string_cst2_gpopt.c:
+       Ditto.
+
 2018-04-30  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/28364
index 15b85ca7780835c5743580f07ccafc9fce4cc976..5826913d5d03b216f3d711aac694ce0e83c272d9 100644 (file)
@@ -3,6 +3,6 @@ int global;
 
 int testfunc ()
 {
-/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r0" } } */
+/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r(0|20)" } } */
     return global;
 }
index 9fb7347bab4cd67815e506dd5e507cc20a94dfea..97b091f10fc58cb57bc1980673e075300883b54f 100644 (file)
@@ -3,6 +3,6 @@ int global = 10;
 
 int testfunc ()
 {
-/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r0" } } */
+/* { dg-final { scan-assembler "\lwi\tr(\[0-9]\|\[1-2]\[0-9]\|3\[0-1]),r(0|20)" } } */
     return global;
 }
index 2337f5a1e78671d359426b2bafdb29391b6ff3ec..d79034e1a07db2130d6163d9566c7deb247aa4d4 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt" } */
+/* { dg-options "-mxl-gp-opt -fno-pic" } */
 
 /* { dg-final { scan-assembler "\.sbss\[^2]+" } } */
 typedef int Boolean;
index 1c91d004305f39a5848e7393778090fe000a39cc..21b9115d795ba4cdd81f9b3c1bc566d09d2e8975 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt" } */
+/* { dg-options "-mxl-gp-opt -fno-pic" } */
 
 /* { dg-final { scan-assembler "\.sdata\[^2]+" } } */
 int global = 10;
index 07c80041c72e0395a0a7204a0fec871402f26a12..2f233138fc169601a1fa4ae4cb0b2a7b34aba1c0 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt" } */
+/* { dg-options "-mxl-gp-opt -fno-pic" } */
 
 extern int a;
 
index 4dfa337d53844cc160100da2723775998779042a..dc74e2d7d2cefe5dcf55c6cc424f7c7eb35f1b49 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt -G 16" } */
+/* { dg-options "-mxl-gp-opt -G 16 -fno-pic" } */
 
 /* { dg-final { scan-assembler "\.sbss\[^2]+" } } */
 struct test_s {
index 5c61962bf4e28d282bc93374d7170407cfdbb0db..c0c3cb3bbba1168d52782420e74cf87e48fe3bf6 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt -G 16" } */
+/* { dg-options "-mxl-gp-opt -G 16 -fno-pic" } */
 
 /* { dg-final { scan-assembler "\.sdata\[^2]+" } } */
 struct test_s {
index 0c8fe431f5d0f8a1ee5675ececed358bc2b23dbe..a23a2c76fe8cc58cc592b7df2a73a61fd324c7f4 100644 (file)
@@ -1,5 +1,4 @@
-/* { dg-options "-mxl-gp-opt -G 16" } */
-
+/* { dg-options "-mxl-gp-opt -G 16 -fno-pic" } */
 struct test_s {
     int a;
     int b;
index 5b5d3db18df502637ea491de119cbcd835ed4348..5bf390b3ea7281003ad00abd70715a7926cd672a 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt" } */
+/* { dg-options "-mxl-gp-opt -fno-pic" } */
 
 #include <string.h>
 
index 057e8c4479bb247dc683cfccac0801b02e5b7ed4..2ad6673d2ef6ae4fdf65fd6e5d5dfac4726ee2bc 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-options "-mxl-gp-opt" } */
+/* { dg-options "-mxl-gp-opt -fno-pic" } */
 
 #include <string.h>