summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-08 15:57:48 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-08 15:57:48 +0000
commitf02776dd47a70fec9d61561f3e0106778fe649ef (patch)
treeb84e28dea878fc64f45ff885f52c8cce4df04460 /gcc
parent8af7bf62c081d2561bc318b48574ef9da250d188 (diff)
downloadgcc-f02776dd47a70fec9d61561f3e0106778fe649ef.tar.gz
gcc/
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog51
-rw-r--r--gcc/config/mips/mips-protos.h4
-rw-r--r--gcc/config/mips/mips.c163
-rw-r--r--gcc/config/mips/mips.h45
-rw-r--r--gcc/config/mips/mips.md18
-rw-r--r--gcc/config/mips/mips.opt4
-rw-r--r--gcc/doc/invoke.texi26
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/mips/code-readable-1.c34
-rw-r--r--gcc/testsuite/gcc.target/mips/code-readable-2.c34
-rw-r--r--gcc/testsuite/gcc.target/mips/code-readable-3.c34
11 files changed, 354 insertions, 65 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f78ecf60e3e..6268b2d62f9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 139276efa0b..2fec3ed5f4f 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -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,
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 2544b21824e..7f09ff9e2a0 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -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;
}
/* 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;
}
+/* 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 ());
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index e8abdcaef9e..9a55f02fc7c 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -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. */
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 88d8fd6266c..6ec22354d0d 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3181,6 +3181,22 @@
}
[(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>"
@@ -5050,7 +5066,7 @@
(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]),
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index e4ecb4d976e..afb3301f076 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -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
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 57b7e73218b..944cb4631a2 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 851229a6bcf..5dd66c3f72c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..75a34cd49c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/code-readable-1.c
@@ -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
index 00000000000..17ec4d77198
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/code-readable-2.c
@@ -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
index 00000000000..edb4214c22f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/code-readable-3.c
@@ -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\\)" } } */