OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 Aug 2007 15:57:48 +0000 (15:57 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 8 Aug 2007 15:57:48 +0000 (15:57 +0000)
2007-08-08  Richard Sandiford  <richard@codesourcery.com>
    Sandra Loosemore  <sandra@codesourcery.com>
    Chao-ying Fu  <fu@mips.com>
    Nigel Stephens  <nigel@mips.com>
    David Ung  <davidu@mips.com>

* doc/invoke.texi (-mcode-readable): Document.
* config/mips/mips.opt (mcode-readable): New option.
* config/mips/mips-protos.h (SYMBOL_32_HIGH): New symbol type.
* config/mips/mips.h (mips_code_readable_setting): New enum.
(mips_code_readable): Declare.
(TARGET_MIPS16_TEXT_LOADS, TARGET_MIPS16_PCREL_LOADS): New macros.
(TARGET_MIPS16_SHORT_JUMP_TABLES): New macro.
(JUMP_TABLES_IN_TEXT_SECTION): Use it.
(CASE_VECTOR_MODE, CASE_VECTOR_PC_RELATIVE): Likewise.  Remove
boiler-plate comments.
(ASM_OUTPUT_ADDR_DIFF_ELT): Use TARGET_MIPS16_SHORT_JUMP_TABLES.
* config/mips/mips.c (mips_code_readable): New variable.
(mips_classify_symbol): Only return SYMBOL_PC_RELATIVE for
MIPS16 labels if TARGET_MIPS16_SHORT_JUMP_TABLES.  Use both the
context and -mcode-readable setting to restrict the use of
SYMBOL_PC_RELATIVE for MIPS16 constant pool references.
Only return TARGET_FORCE_TO_MEM if PC-relative loads are allowed.
(mips_symbolic_constant_p): Handle SYMBOL_32_HIGH.
(mips_blocks_for_constant_p): Only return false for
TARGET_MIPS16_PCREL_LOADS.
(mips_symbol_insns_1): Treat HIGHs as 2 extended instructions
for MIPS16.  Handle SYMBOL_32_HIGH.
(mips_const_insns): Allow HIGHs for MIPS16 too.
(mips_unspec_address_offset): New function, split out from...
(mips_unspec_address): ...here.
(mips_output_move): Handle MIPS16 HIGH moves.  Use "li" to load
16-bit symbolic constants.  Assert approropiate conditions for
using the "la" and "dla" macros.
(mips_handle_option): Handle -mcode-readable=.
(override_options): Use %hi/%lo relocations for TARGET_MIPS16 too.
Set up mips_lo_relocs[SYMBOL_32_HIGH].
(mips_strip_unspec_address): New function, split out from...
(print_operand_reloc): ...here.
(print_operand): Pass constants through mips_strip_unspec_address.
(print_operand_address): Likewise.
(mips_output_mi_thunk): Remove guard of mips16_lay_out_constants.
(mips_select_rtx_section): Remove MIPS16 handling.
(mips16_gp_pseudo_reg): Check currently_expanding_to_rtl.
(mips16_rewrite_pool_refs): Wrap the labels in an address UNSPEC.
(mips16_lay_out_constants): Do nothing unless
TARGET_MIPS16_PCREL_LOADS.
(mips_avoid_hazards): Remove guard of mips16_lay_out_constants.
* config/mips/mips.md: Split HIGHs for MIPS16.
(tablejump): Use TARGET_MIPS16_SHORT_JUMP_TABLES.

gcc/testsuite/
* gcc.target/mips/code-readable-1.c: New test.
* gcc.target/mips/code-readable-2.c: Likewise.
* gcc.target/mips/code-readable-3.c: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127300 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/mips.opt
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/code-readable-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/code-readable-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/code-readable-3.c [new file with mode: 0644]

index f78ecf6..6268b2d 100644 (file)
@@ -1,4 +1,55 @@
 2007-08-08  Richard Sandiford  <richard@codesourcery.com>
+           Sandra Loosemore  <sandra@codesourcery.com>
+           Chao-ying Fu  <fu@mips.com>
+           Nigel Stephens  <nigel@mips.com>
+           David Ung  <davidu@mips.com>
+
+       * doc/invoke.texi (-mcode-readable): Document.
+       * config/mips/mips.opt (mcode-readable): New option.
+       * config/mips/mips-protos.h (SYMBOL_32_HIGH): New symbol type.
+       * config/mips/mips.h (mips_code_readable_setting): New enum.
+       (mips_code_readable): Declare.
+       (TARGET_MIPS16_TEXT_LOADS, TARGET_MIPS16_PCREL_LOADS): New macros.
+       (TARGET_MIPS16_SHORT_JUMP_TABLES): New macro.
+       (JUMP_TABLES_IN_TEXT_SECTION): Use it.
+       (CASE_VECTOR_MODE, CASE_VECTOR_PC_RELATIVE): Likewise.  Remove
+       boiler-plate comments.
+       (ASM_OUTPUT_ADDR_DIFF_ELT): Use TARGET_MIPS16_SHORT_JUMP_TABLES.
+       * config/mips/mips.c (mips_code_readable): New variable.
+       (mips_classify_symbol): Only return SYMBOL_PC_RELATIVE for
+       MIPS16 labels if TARGET_MIPS16_SHORT_JUMP_TABLES.  Use both the
+       context and -mcode-readable setting to restrict the use of
+       SYMBOL_PC_RELATIVE for MIPS16 constant pool references.
+       Only return TARGET_FORCE_TO_MEM if PC-relative loads are allowed.
+       (mips_symbolic_constant_p): Handle SYMBOL_32_HIGH.
+       (mips_blocks_for_constant_p): Only return false for
+       TARGET_MIPS16_PCREL_LOADS.
+       (mips_symbol_insns_1): Treat HIGHs as 2 extended instructions
+       for MIPS16.  Handle SYMBOL_32_HIGH.
+       (mips_const_insns): Allow HIGHs for MIPS16 too.
+       (mips_unspec_address_offset): New function, split out from...
+       (mips_unspec_address): ...here.
+       (mips_output_move): Handle MIPS16 HIGH moves.  Use "li" to load
+       16-bit symbolic constants.  Assert approropiate conditions for
+       using the "la" and "dla" macros.
+       (mips_handle_option): Handle -mcode-readable=.
+       (override_options): Use %hi/%lo relocations for TARGET_MIPS16 too.
+       Set up mips_lo_relocs[SYMBOL_32_HIGH].
+       (mips_strip_unspec_address): New function, split out from...
+       (print_operand_reloc): ...here.
+       (print_operand): Pass constants through mips_strip_unspec_address.
+       (print_operand_address): Likewise.
+       (mips_output_mi_thunk): Remove guard of mips16_lay_out_constants.
+       (mips_select_rtx_section): Remove MIPS16 handling.
+       (mips16_gp_pseudo_reg): Check currently_expanding_to_rtl.
+       (mips16_rewrite_pool_refs): Wrap the labels in an address UNSPEC.
+       (mips16_lay_out_constants): Do nothing unless
+       TARGET_MIPS16_PCREL_LOADS.
+       (mips_avoid_hazards): Remove guard of mips16_lay_out_constants.
+       * config/mips/mips.md: Split HIGHs for MIPS16.
+       (tablejump): Use TARGET_MIPS16_SHORT_JUMP_TABLES.
+
+2007-08-08  Richard Sandiford  <richard@codesourcery.com>
 
        * config/mips/mips-protos.h (mips_emit_move): Declare.
        * config/mips/mips.c (mips_emit_move): New function.
index 139276e..2fec3ed 100644 (file)
@@ -93,6 +93,9 @@ enum mips_symbol_context {
        UNSPEC wrappers around SYMBOL_TLS, corresponding to the
        thread-local storage relocation operators.
 
+   SYMBOL_32_HIGH
+       For a 32-bit symbolic address X, this is the value of %hi(X).
+
    SYMBOL_64_HIGH
        For a 64-bit symbolic address X, this is the value of
        (%highest(X) << 16) + %higher(X).
@@ -125,6 +128,7 @@ enum mips_symbol_type {
   SYMBOL_DTPREL,
   SYMBOL_GOTTPREL,
   SYMBOL_TPREL,
+  SYMBOL_32_HIGH,
   SYMBOL_64_HIGH,
   SYMBOL_64_MID,
   SYMBOL_64_LOW,
index 2544b21..7f09ff9 100644 (file)
@@ -616,6 +616,9 @@ int mips_abi = MIPS_ABI_DEFAULT;
 /* Cost information to use.  */
 const struct mips_rtx_cost_data *mips_cost;
 
+/* The -mtext-loads setting.  */
+enum mips_code_readable_setting mips_code_readable = CODE_READABLE_YES;
+
 /* Whether we are generating mips16 hard float code.  In mips16 mode
    we always set TARGET_SOFT_FLOAT; this variable is nonzero if
    -msoft-float was not specified by the user, which means that we
@@ -1444,7 +1447,10 @@ mips_classify_symbol (rtx x, enum mips_symbol_context context)
 
   if (GET_CODE (x) == LABEL_REF)
     {
-      if (TARGET_MIPS16)
+      /* LABEL_REFs are used for jump tables as well as text labels.
+        Only return SYMBOL_PC_RELATIVE if we know the label is in
+        the text section.  */
+      if (TARGET_MIPS16_SHORT_JUMP_TABLES)
        return SYMBOL_PC_RELATIVE;
       if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
        return SYMBOL_GOT_PAGE_OFST;
@@ -1458,7 +1464,10 @@ mips_classify_symbol (rtx x, enum mips_symbol_context context)
 
   if (CONSTANT_POOL_ADDRESS_P (x))
     {
-      if (TARGET_MIPS16)
+      if (TARGET_MIPS16_TEXT_LOADS)
+       return SYMBOL_PC_RELATIVE;
+
+      if (TARGET_MIPS16_PCREL_LOADS && context == SYMBOL_CONTEXT_MEM)
        return SYMBOL_PC_RELATIVE;
 
       if (!TARGET_EMBEDDED_DATA
@@ -1502,7 +1511,7 @@ mips_classify_symbol (rtx x, enum mips_symbol_context context)
       return SYMBOL_GOT_PAGE_OFST;
     }
 
-  if (TARGET_MIPS16 && context != SYMBOL_CONTEXT_CALL)
+  if (TARGET_MIPS16_PCREL_LOADS && context != SYMBOL_CONTEXT_CALL)
     return SYMBOL_FORCE_TO_MEM;
   return SYMBOL_ABSOLUTE;
 }
@@ -1560,6 +1569,7 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_context context,
     {
     case SYMBOL_ABSOLUTE:
     case SYMBOL_FORCE_TO_MEM:
+    case SYMBOL_32_HIGH:
     case SYMBOL_64_HIGH:
     case SYMBOL_64_MID:
     case SYMBOL_64_LOW:
@@ -1774,14 +1784,14 @@ mips_cannot_force_const_mem (rtx x)
   return false;
 }
 
-/* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P.  MIPS16 uses per-function
-   constant pools, but normal-mode code doesn't need to.  */
+/* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P.  We can't use blocks for
+   constants when we're using a per-function constant pool.  */
 
 static bool
 mips_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
                                rtx x ATTRIBUTE_UNUSED)
 {
-  return !TARGET_MIPS16;
+  return !TARGET_MIPS16_PCREL_LOADS;
 }
 \f
 /* Like mips_symbol_insns, but treat extended MIPS16 instructions as a
@@ -1805,8 +1815,9 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
             dsll    $at,$at,16
 
         The final address is then $at + %lo(symbol).  With 32-bit
-        symbols we just need a preparatory lui.  */
-      return ABI_HAS_64BIT_SYMBOLS ? 6 : 2;
+        symbols we just need a preparatory lui for normal mode and
+        a preparatory "li; sll" for MIPS16.  */
+      return ABI_HAS_64BIT_SYMBOLS ? 6 : TARGET_MIPS16 ? 3 : 2;
 
     case SYMBOL_GP_RELATIVE:
       /* Treat GP-relative accesses as taking a single instruction on
@@ -1863,6 +1874,7 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
     case SYMBOL_GOTOFF_DISP:
     case SYMBOL_GOTOFF_CALL:
     case SYMBOL_GOTOFF_LOADGP:
+    case SYMBOL_32_HIGH:
     case SYMBOL_64_HIGH:
     case SYMBOL_64_MID:
     case SYMBOL_64_LOW:
@@ -1875,7 +1887,7 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode)
       /* A 16-bit constant formed by a single relocation, or a 32-bit
         constant formed from a high 16-bit relocation and a low 16-bit
         relocation.  Use mips_split_p to determine which.  */
-      return mips_split_p[type] ? 2 : 1;
+      return !mips_split_p[type] ? 1 : TARGET_MIPS16 ? 3 : 2;
 
     case SYMBOL_TLS:
       /* We don't treat a bare TLS symbol as a constant.  */
@@ -1989,13 +2001,14 @@ mips_const_insns (rtx x)
   switch (GET_CODE (x))
     {
     case HIGH:
-      if (TARGET_MIPS16
-         || !mips_symbolic_constant_p (XEXP (x, 0), SYMBOL_CONTEXT_LEA,
-                                       &symbol_type)
+      if (!mips_symbolic_constant_p (XEXP (x, 0), SYMBOL_CONTEXT_LEA,
+                                    &symbol_type)
          || !mips_split_p[symbol_type])
        return 0;
 
-      return 1;
+      /* This is simply an lui for normal mode.  It is an extended
+        "li" followed by an extended "sll" for MIPS16.  */
+      return TARGET_MIPS16 ? 4 : 1;
 
     case CONST_INT:
       if (TARGET_MIPS16)
@@ -2173,6 +2186,20 @@ mips_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *lo_sum_out)
 }
 
 
+/* Wrap symbol or label BASE in an unspec address of type SYMBOL_TYPE
+   and add CONST_INT OFFSET to the result.  */
+
+static rtx
+mips_unspec_address_offset (rtx base, rtx offset,
+                           enum mips_symbol_type symbol_type)
+{
+  base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
+                        UNSPEC_ADDRESS_FIRST + symbol_type);
+  if (offset != const0_rtx)
+    base = gen_rtx_PLUS (Pmode, base, offset);
+  return gen_rtx_CONST (Pmode, base);
+}
+
 /* Return an UNSPEC address with underlying address ADDRESS and symbol
    type SYMBOL_TYPE.  */
 
@@ -2182,11 +2209,7 @@ mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
   rtx base, offset;
 
   split_const (address, &base, &offset);
-  base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
-                        UNSPEC_ADDRESS_FIRST + symbol_type);
-  if (offset != const0_rtx)
-    base = gen_rtx_PLUS (Pmode, base, offset);
-  return gen_rtx_CONST (Pmode, base);
+  return mips_unspec_address_offset (base, offset, symbol_type);
 }
 
 
@@ -3130,6 +3153,7 @@ const char *
 mips_output_move (rtx dest, rtx src)
 {
   enum rtx_code dest_code, src_code;
+  enum mips_symbol_type symbol_type;
   bool dbl_p;
 
   dest_code = GET_CODE (dest);
@@ -3217,13 +3241,27 @@ mips_output_move (rtx dest, rtx src)
        }
 
       if (src_code == HIGH)
-       return "lui\t%0,%h1";
+       return TARGET_MIPS16 ? "#" : "lui\t%0,%h1";
 
       if (CONST_GP_P (src))
        return "move\t%0,%1";
 
+      if (mips_symbolic_constant_p (src, SYMBOL_CONTEXT_LEA, &symbol_type)
+         && mips_lo_relocs[symbol_type] != 0)
+       {
+         /* A signed 16-bit constant formed by applying a relocation
+            operator to a symbolic address.  */
+         gcc_assert (!mips_split_p[symbol_type]);
+         return "li\t%0,%R1";
+       }
+
       if (symbolic_operand (src, VOIDmode))
-       return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1");
+       {
+         gcc_assert (TARGET_MIPS16
+                     ? TARGET_MIPS16_TEXT_LOADS
+                     : !TARGET_EXPLICIT_RELOCS);
+         return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1");
+       }
     }
   if (src_code == REG && FP_REG_P (REGNO (src)))
     {
@@ -5007,6 +5045,17 @@ mips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
       mips_cache_flush_func = NULL;
       return true;
 
+    case OPT_mcode_readable_:
+      if (strcmp (arg, "yes") == 0)
+       mips_code_readable = CODE_READABLE_YES;
+      else if (strcmp (arg, "pcrel") == 0)
+       mips_code_readable = CODE_READABLE_PCREL;
+      else if (strcmp (arg, "no") == 0)
+       mips_code_readable = CODE_READABLE_NO;
+      else
+       return false;
+      return true;
+
     default:
       return true;
     }
@@ -5456,11 +5505,13 @@ override_options (void)
     }
   else
     {
-      if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
+      if (TARGET_EXPLICIT_RELOCS || mips_split_addresses || TARGET_MIPS16)
        {
          mips_split_p[SYMBOL_ABSOLUTE] = true;
          mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
          mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+
+         mips_lo_relocs[SYMBOL_32_HIGH] = "%hi(";
        }
     }
 
@@ -5718,6 +5769,20 @@ mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
   return offset;
 }
 \f
+/* If OP is an UNSPEC address, return the address to which it refers,
+   otherwise return OP itself.  */
+
+static rtx
+mips_strip_unspec_address (rtx op)
+{
+  rtx base, offset;
+
+  split_const (op, &base, &offset);
+  if (UNSPEC_ADDRESS_P (base))
+    op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
+  return op;
+}
+
 /* Implement the PRINT_OPERAND macro.  The MIPS-specific operand codes are:
 
    'X'  OP is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
@@ -6055,7 +6120,7 @@ print_operand (FILE *file, rtx op, int letter)
     fputs (reg_names[GLOBAL_POINTER_REGNUM], file);
 
   else
-    output_addr_const (file, op);
+    output_addr_const (file, mips_strip_unspec_address (op));
 }
 
 
@@ -6068,19 +6133,13 @@ print_operand_reloc (FILE *file, rtx op, enum mips_symbol_context context,
 {
   enum mips_symbol_type symbol_type;
   const char *p;
-  rtx base, offset;
 
   if (!mips_symbolic_constant_p (op, context, &symbol_type)
       || relocs[symbol_type] == 0)
     fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
 
-  /* If OP uses an UNSPEC address, we want to print the inner symbol.  */
-  split_const (op, &base, &offset);
-  if (UNSPEC_ADDRESS_P (base))
-    op = plus_constant (UNSPEC_ADDRESS (base), INTVAL (offset));
-
   fputs (relocs[symbol_type], file);
-  output_addr_const (file, op);
+  output_addr_const (file, mips_strip_unspec_address (op));
   for (p = relocs[symbol_type]; *p != 0; p++)
     if (*p == '(')
       fputc (')', file);
@@ -6113,7 +6172,7 @@ print_operand_address (FILE *file, rtx x)
        return;
 
       case ADDRESS_SYMBOLIC:
-       output_addr_const (file, x);
+       output_addr_const (file, mips_strip_unspec_address (x));
        return;
       }
   gcc_unreachable ();
@@ -8192,8 +8251,7 @@ mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
   insn = get_insns ();
   insn_locators_alloc ();
   split_all_insns_noflow ();
-  if (TARGET_MIPS16)
-    mips16_lay_out_constants ();
+  mips16_lay_out_constants ();
   shorten_branches (insn);
   final_start_function (insn, file, 1);
   final (insn, file, 1);
@@ -8232,14 +8290,7 @@ static section *
 mips_select_rtx_section (enum machine_mode mode, rtx x,
                         unsigned HOST_WIDE_INT align)
 {
-  if (TARGET_MIPS16)
-    {
-      /* In mips16 mode, the constant table always goes in the same section
-         as the function, so that constants can be loaded using PC relative
-         addressing.  */
-      return function_section (current_function_decl);
-    }
-  else if (TARGET_EMBEDDED_DATA)
+  if (TARGET_EMBEDDED_DATA)
     {
       /* For embedded applications, always put constants in read-only data,
         in order to reduce RAM usage.  */
@@ -8827,7 +8878,7 @@ mips16_gp_pseudo_reg (void)
   /* Don't initialize the pseudo register if we are being called from
      the tree optimizers' cost-calculation routines.  */
   if (!cfun->machine->initialized_mips16_gp_pseudo_p
-      && current_ir_type () != IR_GIMPLE)
+      && (current_ir_type () != IR_GIMPLE || currently_expanding_to_rtl))
     {
       rtx insn, scan;
 
@@ -9546,11 +9597,23 @@ static int
 mips16_rewrite_pool_refs (rtx *x, void *data)
 {
   struct mips16_constant_pool *pool = data;
-  if (GET_CODE (*x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (*x))
-    *x = gen_rtx_LABEL_REF (Pmode, add_constant (pool,
-                                                get_pool_constant (*x),
-                                                get_pool_mode (*x)));
-  return 0;
+  rtx base, offset, label;
+
+  if (MEM_P (*x))
+    x = &XEXP (*x, 0);
+  else if (!TARGET_MIPS16_TEXT_LOADS)
+    return 0;
+
+  split_const (*x, &base, &offset);
+  if (GET_CODE (base) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (base))
+    {
+      label = add_constant (pool, get_pool_constant (base),
+                           get_pool_mode (base));
+      base = gen_rtx_LABEL_REF (Pmode, label);
+      *x = mips_unspec_address_offset (base, offset, SYMBOL_PC_RELATIVE);
+      return -1;
+    }
+  return GET_CODE (*x) == CONST ? -1 : 0;
 }
 
 /* Build MIPS16 constant pools.  */
@@ -9561,6 +9624,9 @@ mips16_lay_out_constants (void)
   struct mips16_constant_pool pool;
   rtx insn, barrier;
 
+  if (!TARGET_MIPS16_PCREL_LOADS)
+    return;
+
   barrier = 0;
   memset (&pool, 0, sizeof (pool));
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
@@ -10117,9 +10183,8 @@ mips_avoid_hazards (void)
 static void
 mips_reorg (void)
 {
-  if (TARGET_MIPS16)
-    mips16_lay_out_constants ();
-  else if (TARGET_EXPLICIT_RELOCS)
+  mips16_lay_out_constants ();
+  if (TARGET_EXPLICIT_RELOCS)
     {
       if (mips_flag_delayed_branch)
        dbr_schedule (get_insns ());
index e8abdca..9a55f02 100644 (file)
@@ -114,6 +114,13 @@ struct mips_cpu_info {
   int isa;
 };
 
+/* Enumerates the setting of the -mcode-readable option.  */
+enum mips_code_readable_setting {
+  CODE_READABLE_NO,
+  CODE_READABLE_PCREL,
+  CODE_READABLE_YES
+};
+
 #ifndef USED_FOR_TARGET
 extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */
 extern const char *current_function_file; /* filename current function is in */
@@ -138,6 +145,7 @@ extern const struct mips_cpu_info mips_cpu_info_table[];
 extern const struct mips_cpu_info *mips_arch_info;
 extern const struct mips_cpu_info *mips_tune_info;
 extern const struct mips_rtx_cost_data *mips_cost;
+extern enum mips_code_readable_setting mips_code_readable;
 #endif
 
 /* Macros to silence warnings about numbers being signed in traditional
@@ -214,6 +222,16 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* Generate mips16e register save/restore sequences.  */
 #define GENERATE_MIPS16E_SAVE_RESTORE (GENERATE_MIPS16E && mips_abi == ABI_32)
 
+/* True if we're generating a form of MIPS16 code in which general
+   text loads are allowed.  */
+#define TARGET_MIPS16_TEXT_LOADS \
+  (TARGET_MIPS16 && mips_code_readable == CODE_READABLE_YES)
+
+/* True if we're generating a form of MIPS16 code in which PC-relative
+   loads are allowed.  */
+#define TARGET_MIPS16_PCREL_LOADS \
+  (TARGET_MIPS16 && mips_code_readable >= CODE_READABLE_PCREL)
+
 /* Generic ISA defines.  */
 #define ISA_MIPS1                  (mips_isa == 1)
 #define ISA_MIPS2                  (mips_isa == 2)
@@ -2270,17 +2288,18 @@ typedef struct mips_args {
 #define SYMBOL_REF_LONG_CALL_P(X)                                      \
   ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
 
-/* Specify the machine mode that this machine uses
-   for the index in the tablejump instruction.
-   ??? Using HImode in mips16 mode can cause overflow.  */
-#define CASE_VECTOR_MODE \
-  (TARGET_MIPS16 ? HImode : ptr_mode)
+/* True if we're generating a form of MIPS16 code in which jump tables
+   are stored in the text section and encoded as 16-bit PC-relative
+   offsets.  This is only possible when general text loads are allowed,
+   since the table access itself will be an "lh" instruction.  */
+/* ??? 16-bit offsets can overflow in large functions.  */
+#define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS
 
-/* Define as C expression which evaluates to nonzero if the tablejump
-   instruction expects the table to contain offsets from the address of the
-   table.
-   Do not define this if the table should contain absolute addresses.  */
-#define CASE_VECTOR_PC_RELATIVE (TARGET_MIPS16)
+#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16_SHORT_JUMP_TABLES
+
+#define CASE_VECTOR_MODE (TARGET_MIPS16_SHORT_JUMP_TABLES ? HImode : ptr_mode)
+
+#define CASE_VECTOR_PC_RELATIVE TARGET_MIPS16_SHORT_JUMP_TABLES
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #ifndef DEFAULT_SIGNED_CHAR
@@ -2650,7 +2669,7 @@ while (0)
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)             \
 do {                                                                   \
-  if (TARGET_MIPS16)                                                   \
+  if (TARGET_MIPS16_SHORT_JUMP_TABLES)                                 \
     fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n",                         \
             LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL);       \
   else if (TARGET_GPWORD)                                              \
@@ -2673,10 +2692,6 @@ do {                                                                     \
             LOCAL_LABEL_PREFIX, VALUE);                                \
 } while (0)
 
-/* When generating MIPS16 code, we want the jump table to be in the text
-   section so that we can load its address using a PC-relative addition.  */
-#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16
-
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
index 88d8fd6..6ec2235 100644 (file)
 }
   [(set_attr "length" "24")])
 
+;; Split HIGHs into:
+;;
+;;     li op0,%hi(sym)
+;;     sll op0,16
+;;
+;; on MIPS16 targets.
+(define_split
+  [(set (match_operand:SI 0 "register_operand" "=d")
+       (high:SI (match_operand:SI 1 "absolute_symbolic_operand" "")))]
+  "TARGET_MIPS16 && reload_completed"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (ashift:SI (match_dup 0) (const_int 16)))]
+{
+  operands[2] = mips_unspec_address (operands[1], SYMBOL_32_HIGH);
+})
+
 ;; Insns to fetch a symbol from a big GOT.
 
 (define_insn_and_split "*xgot_hi<mode>"
    (use (label_ref (match_operand 1 "")))]
   ""
 {
-  if (TARGET_MIPS16)
+  if (TARGET_MIPS16_SHORT_JUMP_TABLES)
     operands[0] = expand_binop (Pmode, add_optab,
                                convert_to_mode (Pmode, operands[0], false),
                                gen_rtx_LABEL_REF (Pmode, operands[1]),
index e4ecb4d..afb3301 100644 (file)
@@ -228,6 +228,10 @@ msym32
 Target Report Var(TARGET_SYM32)
 Assume all symbols have 32-bit values
 
+mcode-readable=
+Target RejectNegative Joined
+-mcode-readable=SETTING        Specify when instructions are allowed to access code
+
 mtune=
 Target RejectNegative Joined Var(mips_tune_string)
 -mtune=PROCESSOR       Optimize the output for PROCESSOR
index 57b7e73..944cb46 100644 (file)
@@ -628,6 +628,7 @@ Objective-C and Objective-C++ Dialects}.
 -mlong64  -mlong32  -msym32  -mno-sym32 @gol
 -G@var{num}  -membedded-data  -mno-embedded-data @gol
 -muninit-const-in-rodata  -mno-uninit-const-in-rodata @gol
+-mcode-readable=@var{setting} @gol
 -msplit-addresses  -mno-split-addresses @gol
 -mexplicit-relocs  -mno-explicit-relocs @gol
 -mcheck-zero-division  -mno-check-zero-division @gol
@@ -11779,6 +11780,31 @@ when executing, and thus may be preferred for some embedded systems.
 Put uninitialized @code{const} variables in the read-only data section.
 This option is only meaningful in conjunction with @option{-membedded-data}.
 
+@item -mcode-readable=@var{setting}
+@opindex mcode-readable
+Specify whether GCC may generate code that reads from executable sections.
+There are three possible settings:
+
+@table @gcctabopt
+@item -mcode-readable=yes
+Instructions may freely access executable sections.  This is the
+default setting.
+
+@item -mcode-readable=pcrel
+MIPS16 PC-relative load instructions can access executable sections,
+but other instructions must not do so.  This option is useful on 4KSc
+and 4KSd processors when the code TLBs have the Read Inhibit bit set.
+It is also useful on processors that can be configured to have a dual
+instruction/data SRAM interface and that, like the M4K, automatically
+redirect PC-relative loads to the instruction RAM.
+
+@item -mcode-readable=no
+Instructions must not access executable sections.  This option can be
+useful on targets that are configured to have a dual instruction/data
+SRAM interface but that (unlike the M4K) do not automatically redirect
+PC-relative loads to the instruction RAM.
+@end table
+
 @item -msplit-addresses
 @itemx -mno-split-addresses
 @opindex msplit-addresses
index 851229a..5dd66c3 100644 (file)
@@ -1,3 +1,9 @@
+2007-08-08  Richard Sandiford  <richard@codesourcery.com>
+
+       * gcc.target/mips/code-readable-1.c: New test.
+       * gcc.target/mips/code-readable-2.c: Likewise.
+       * gcc.target/mips/code-readable-3.c: Likewise.
+
 2007-08-08  Vladimir Yanovsky  <yanov@il.ibm.com>
             Revital Eres  <eres@il.ibm.com>
  
diff --git a/gcc/testsuite/gcc.target/mips/code-readable-1.c b/gcc/testsuite/gcc.target/mips/code-readable-1.c
new file mode 100644 (file)
index 0000000..75a34cd
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-mips-options "-mips16 -mcode-readable=yes -mgp32" } */
+
+int
+foo (int i)
+{
+  switch (i)
+    {
+    case 1: return 40;
+    case 2: return 11;
+    case 3: return 29;
+    case 4: return 10;
+    case 5: return 12;
+    case 6: return 35;
+    case 7: return 23;
+    default: return 0;
+    }
+}
+
+extern int k[];
+
+int *
+bar (void)
+{
+  return k;
+}
+
+/* { dg-final { scan-assembler "\tla\t" } } */
+/* { dg-final { scan-assembler "\t\.half\t" } } */
+/* { dg-final { scan-assembler-not "%hi\\(\[^)\]*L" } } */
+/* { dg-final { scan-assembler-not "%lo\\(\[^)\]*L" } } */
+
+/* { dg-final { scan-assembler "\t\.word\tk\n" } } */
+/* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */
+/* { dg-final { scan-assembler-not "%lo\\(k\\)" } } */
diff --git a/gcc/testsuite/gcc.target/mips/code-readable-2.c b/gcc/testsuite/gcc.target/mips/code-readable-2.c
new file mode 100644 (file)
index 0000000..17ec4d7
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-mips-options "-mips16 -mcode-readable=pcrel -mgp32" } */
+
+int
+foo (int i)
+{
+  switch (i)
+    {
+    case 1: return 40;
+    case 2: return 11;
+    case 3: return 29;
+    case 4: return 10;
+    case 5: return 12;
+    case 6: return 35;
+    case 7: return 23;
+    default: return 0;
+    }
+}
+
+extern int k[];
+
+int *
+bar (void)
+{
+  return k;
+}
+
+/* { dg-final { scan-assembler-not "\tla\t" } } */
+/* { dg-final { scan-assembler-not "\t\.half\t" } } */
+/* { dg-final { scan-assembler "%hi\\(\[^)\]*L" } } */
+/* { dg-final { scan-assembler "%lo\\(\[^)\]*L" } } */
+
+/* { dg-final { scan-assembler "\t\.word\tk\n" } } */
+/* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */
+/* { dg-final { scan-assembler-not "%lo\\(k\\)" } } */
diff --git a/gcc/testsuite/gcc.target/mips/code-readable-3.c b/gcc/testsuite/gcc.target/mips/code-readable-3.c
new file mode 100644 (file)
index 0000000..edb4214
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-mips-options "-mips16 -mcode-readable=no -mgp32" } */
+
+int
+foo (int i)
+{
+  switch (i)
+    {
+    case 1: return 40;
+    case 2: return 11;
+    case 3: return 29;
+    case 4: return 10;
+    case 5: return 12;
+    case 6: return 35;
+    case 7: return 23;
+    default: return 0;
+    }
+}
+
+extern int k[];
+
+int *
+bar (void)
+{
+  return k;
+}
+
+/* { dg-final { scan-assembler-not "\tla\t" } } */
+/* { dg-final { scan-assembler-not "\t\.half\t" } } */
+/* { dg-final { scan-assembler "%hi\\(\[^)\]*L" } } */
+/* { dg-final { scan-assembler "%lo\\(\[^)\]*L" } } */
+
+/* { dg-final { scan-assembler-not "\t\.word\tk\n" } } */
+/* { dg-final { scan-assembler "%hi\\(k\\)" } } */
+/* { dg-final { scan-assembler "%lo\\(k\\)" } } */