diff options
author | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-08 15:57:48 +0000 |
---|---|---|
committer | rsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-08-08 15:57:48 +0000 |
commit | f02776dd47a70fec9d61561f3e0106778fe649ef (patch) | |
tree | b84e28dea878fc64f45ff885f52c8cce4df04460 /gcc | |
parent | 8af7bf62c081d2561bc318b48574ef9da250d188 (diff) | |
download | gcc-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/ChangeLog | 51 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 163 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 45 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 18 | ||||
-rw-r--r-- | gcc/config/mips/mips.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/code-readable-1.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/code-readable-2.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/code-readable-3.c | 34 |
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\\)" } } */ |