invoke.texi (-mcode-readable): Document.

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.

Co-Authored-By: Chao-ying Fu <fu@mips.com>
Co-Authored-By: David Ung <davidu@mips.com>
Co-Authored-By: Nigel Stephens <nigel@mips.com>
Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com>

From-SVN: r127300
This commit is contained in:
Richard Sandiford 2007-08-08 15:57:48 +00:00 committed by Richard Sandiford
parent 51e7252ad2
commit c93c5160b3
11 changed files with 354 additions and 65 deletions

View File

@ -1,3 +1,54 @@
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.

View 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,

View 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;
}
/* 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 ());

View 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. */

View File

@ -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]),

View 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

View 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

View 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>

View File

@ -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\\)" } } */

View File

@ -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\\)" } } */

View File

@ -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\\)" } } */