mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-05 05:20:24 +08:00
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:
parent
51e7252ad2
commit
c93c5160b3
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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 ());
|
||||
|
@ -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. */
|
||||
|
@ -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]),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
34
gcc/testsuite/gcc.target/mips/code-readable-1.c
Normal file
34
gcc/testsuite/gcc.target/mips/code-readable-1.c
Normal 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\\)" } } */
|
34
gcc/testsuite/gcc.target/mips/code-readable-2.c
Normal file
34
gcc/testsuite/gcc.target/mips/code-readable-2.c
Normal 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\\)" } } */
|
34
gcc/testsuite/gcc.target/mips/code-readable-3.c
Normal file
34
gcc/testsuite/gcc.target/mips/code-readable-3.c
Normal 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\\)" } } */
|
Loading…
x
Reference in New Issue
Block a user