From ddaf812593310705b989f835ec3aac1a14a8b755 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 15 Jan 2012 18:22:55 +0000 Subject: [PATCH] mips-protos.h (SYMBOL_FORCE_TO_MEM): Delete. gcc/ 2012-01-08 Chung-Lin Tang Richard Sandiford * config/mips/mips-protos.h (SYMBOL_FORCE_TO_MEM): Delete. (SYMBOL_32_HIGH): Likewise. (mips_output_tls_reloc_directive): Declare. * config/mips/mips.h (PIC_FUNCTION_ADDR_REGNUM): Move to mips.md. (mips_use_pcrel_pool_p, mips_lo_relocs, mips_hi_relocs): Declare. * config/mips/mips.c (mips_use_pcrel_pool_p): New variable. (mips_lo_relocs, mips_hi_relocs): Make extern. (mips16_stub_function): Move up file. (mips_classify_symbol): Remove SYMBOL_FORCE_TO_MEM handling. (mips_symbolic_constant_p): Likewise. Remove SYMBOL_32_HIGH too. (mips_symbol_insns_1): Likewise. Check mips_use_pcrel_pool_p. (mips_cannot_force_const_mem): Use mips_use_pcrel_pool_p instead of SYMBOL_FORCE_TO_MEM. Only check mips_tls_symbol_ref_1 if it's false. (mips_get_tp): Add MIPS16 support. (mips_legitimize_tls_address): Remove MIPS16 sorry(). Generalize DTPREL and TPREL handling. (mips_init_relocs): Initialize mips_use_pcrel_pool_p. Add MIPS16 TLS support. (mips_output_tls_reloc_directive): New function. (mips16_rewrite_pool_refs): Ignore UNSPEC_TLS_GET_TPs. * config/mips/predicates.md (symbolic_operand_with_high) (tls_reloc_operand): New predicates. (force_to_mem_operand): Use mips_use_pcrel_pool_p. * config/mips/mips.md (UNSPEC_UNSHIFTED_HIGH): New unspec. (PIC_FUNCTION_ADDR_REGNUM): Moved from mips.h. (*unshifted_high): New instruction. Use it for MIPS16 high splitter. (consttable_tls_reloc, tls_get_tp_mips16_): New patterns. (*tls_get_tp_mips16_call_): Likewise. gcc/testsuite/ * gcc.target/mips/code-readable-2.c: Allow the jump table address to be loaded from the constant pool, rather than via %hi and %lo. libgcc/ 2012-01-08 Chung-Lin Tang Richard Sandiford * config/mips/libgcc-mips16.ver (__mips16_rdhwr): Add. * config/mips/mips16.S (__mips16_rdhwr): New function. * config/mips/t-mips16 (LIB1ASMFUNCS): Add _m16rdhwr. From-SVN: r183195 --- gcc/ChangeLog | 34 +++ gcc/config/mips/mips-protos.h | 9 +- gcc/config/mips/mips.c | 218 +++++++++++------- gcc/config/mips/mips.h | 5 +- gcc/config/mips/mips.md | 72 +++++- gcc/config/mips/predicates.md | 18 +- gcc/testsuite/ChangeLog | 5 + .../gcc.target/mips/code-readable-2.c | 3 +- libgcc/ChangeLog | 7 + libgcc/config/mips/libgcc-mips16.ver | 4 + libgcc/config/mips/mips16.S | 11 + libgcc/config/mips/t-mips16 | 3 +- 12 files changed, 286 insertions(+), 103 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b74e6090546..66c43f19e94 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2012-01-15 Chung-Lin Tang + Richard Sandiford + + * config/mips/mips-protos.h (SYMBOL_FORCE_TO_MEM): Delete. + (SYMBOL_32_HIGH): Likewise. + (mips_output_tls_reloc_directive): Declare. + * config/mips/mips.h (PIC_FUNCTION_ADDR_REGNUM): Move to mips.md. + (mips_use_pcrel_pool_p, mips_lo_relocs, mips_hi_relocs): Declare. + * config/mips/mips.c (mips_use_pcrel_pool_p): New variable. + (mips_lo_relocs, mips_hi_relocs): Make extern. + (mips16_stub_function): Move up file. + (mips_classify_symbol): Remove SYMBOL_FORCE_TO_MEM handling. + (mips_symbolic_constant_p): Likewise. Remove SYMBOL_32_HIGH too. + (mips_symbol_insns_1): Likewise. Check mips_use_pcrel_pool_p. + (mips_cannot_force_const_mem): Use mips_use_pcrel_pool_p instead + of SYMBOL_FORCE_TO_MEM. Only check mips_tls_symbol_ref_1 + if it's false. + (mips_get_tp): Add MIPS16 support. + (mips_legitimize_tls_address): Remove MIPS16 sorry(). + Generalize DTPREL and TPREL handling. + (mips_init_relocs): Initialize mips_use_pcrel_pool_p. + Add MIPS16 TLS support. + (mips_output_tls_reloc_directive): New function. + (mips16_rewrite_pool_refs): Ignore UNSPEC_TLS_GET_TPs. + * config/mips/predicates.md (symbolic_operand_with_high) + (tls_reloc_operand): New predicates. + (force_to_mem_operand): Use mips_use_pcrel_pool_p. + * config/mips/mips.md (UNSPEC_UNSHIFTED_HIGH): New unspec. + (PIC_FUNCTION_ADDR_REGNUM): Moved from mips.h. + (*unshifted_high): New instruction. Use it for MIPS16 + high splitter. + (consttable_tls_reloc, tls_get_tp_mips16_): New patterns. + (*tls_get_tp_mips16_call_): Likewise. + 2012-01-15 Uros Bizjak PR rtl-optimization/51821 diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index ca0fb5eba67..45d2537cab8 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -56,9 +56,6 @@ enum mips_symbol_context { The symbol's value will be calculated using a MIPS16 PC-relative calculation. - SYMBOL_FORCE_TO_MEM - The symbol's value must be forced to memory and loaded from there. - SYMBOL_GOT_PAGE_OFST The symbol's value will be calculated by loading an address from the GOT and then applying a 16-bit offset. @@ -94,9 +91,6 @@ 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). @@ -116,7 +110,6 @@ enum mips_symbol_type { SYMBOL_ABSOLUTE, SYMBOL_GP_RELATIVE, SYMBOL_PC_RELATIVE, - SYMBOL_FORCE_TO_MEM, SYMBOL_GOT_PAGE_OFST, SYMBOL_GOT_DISP, SYMBOL_GOTOFF_PAGE, @@ -129,7 +122,6 @@ enum mips_symbol_type { SYMBOL_DTPREL, SYMBOL_GOTTPREL, SYMBOL_TPREL, - SYMBOL_32_HIGH, SYMBOL_64_HIGH, SYMBOL_64_MID, SYMBOL_64_LOW, @@ -260,6 +252,7 @@ extern void mips_push_asm_switch (struct mips_asm_switch *); extern void mips_pop_asm_switch (struct mips_asm_switch *); extern void mips_output_external (FILE *, tree, const char *); extern void mips_output_ascii (FILE *, const char *, size_t); +extern const char *mips_output_tls_reloc_directive (rtx *); extern void mips_output_aligned_decl_common (FILE *, tree, const char *, unsigned HOST_WIDE_INT, unsigned int); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 33e238c7d3e..b29ec4a5041 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -573,13 +573,17 @@ bool mips_split_p[NUM_SYMBOL_TYPES]; can be split by mips_split_symbol. */ bool mips_split_hi_p[NUM_SYMBOL_TYPES]; +/* mips_use_pcrel_pool_p[X] is true if symbols of type X should be + forced into a PC-relative constant pool. */ +bool mips_use_pcrel_pool_p[NUM_SYMBOL_TYPES]; + /* mips_lo_relocs[X] is the relocation to use when a symbol of type X appears in a LO_SUM. It can be null if such LO_SUMs aren't valid or if they are matched by a special .md file pattern. */ -static const char *mips_lo_relocs[NUM_SYMBOL_TYPES]; +const char *mips_lo_relocs[NUM_SYMBOL_TYPES]; /* Likewise for HIGHs. */ -static const char *mips_hi_relocs[NUM_SYMBOL_TYPES]; +const char *mips_hi_relocs[NUM_SYMBOL_TYPES]; /* Target state for MIPS16. */ struct target_globals *mips16_globals; @@ -1440,6 +1444,18 @@ mips_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) return mips_const_insns (x) > 0; } +/* Return a SYMBOL_REF for a MIPS16 function called NAME. */ + +static rtx +mips16_stub_function (const char *name) +{ + rtx x; + + x = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); + SYMBOL_REF_FLAGS (x) |= (SYMBOL_FLAG_EXTERNAL | SYMBOL_FLAG_FUNCTION); + return x; +} + /* Return true if symbols of type TYPE require a GOT access. */ static bool @@ -1644,9 +1660,6 @@ mips_classify_symbol (const_rtx x, enum mips_symbol_context context) return SYMBOL_GOT_PAGE_OFST; } - if (TARGET_MIPS16_PCREL_LOADS && context != SYMBOL_CONTEXT_CALL) - return SYMBOL_FORCE_TO_MEM; - return SYMBOL_ABSOLUTE; } @@ -1709,8 +1722,6 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_context context, switch (*symbol_type) { case SYMBOL_ABSOLUTE: - case SYMBOL_FORCE_TO_MEM: - case SYMBOL_32_HIGH: case SYMBOL_64_HIGH: case SYMBOL_64_MID: case SYMBOL_64_LOW: @@ -1776,6 +1787,17 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_context context, static int mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode) { + if (mips_use_pcrel_pool_p[(int) type]) + { + if (mode == MAX_MACHINE_MODE) + /* LEAs will be converted into constant-pool references by + mips_reorg. */ + type = SYMBOL_PC_RELATIVE; + else + /* The constant must be loaded and then dereferenced. */ + return 0; + } + switch (type) { case SYMBOL_ABSOLUTE: @@ -1809,15 +1831,6 @@ mips_symbol_insns_1 (enum mips_symbol_type type, enum machine_mode mode) /* The constant must be loaded using ADDIUPC or DADDIUPC first. */ return 0; - case SYMBOL_FORCE_TO_MEM: - /* LEAs will be converted into constant-pool references by - mips_reorg. */ - if (mode == MAX_MACHINE_MODE) - return 1; - - /* The constant must be loaded and then dereferenced. */ - return 0; - case SYMBOL_GOT_DISP: /* The constant will have to be loaded from the GOT before it is used in an address. */ @@ -1850,7 +1863,6 @@ 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: @@ -1925,9 +1937,12 @@ mips_cannot_force_const_mem (enum machine_mode mode, rtx x) return true; split_const (x, &base, &offset); - if (mips_symbolic_constant_p (base, SYMBOL_CONTEXT_LEA, &type) - && type != SYMBOL_FORCE_TO_MEM) + if (mips_symbolic_constant_p (base, SYMBOL_CONTEXT_LEA, &type)) { + /* See whether we explicitly want these symbols in the pool. */ + if (mips_use_pcrel_pool_p[(int) type]) + return false; + /* The same optimization as for CONST_INT. */ if (SMALL_INT (offset) && mips_symbol_insns (type, MAX_MACHINE_MODE) > 0) return true; @@ -2822,13 +2837,18 @@ mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0) static rtx mips_get_tp (void) { - rtx tp; + rtx tp, fn; tp = gen_reg_rtx (Pmode); - if (Pmode == DImode) - emit_insn (gen_tls_get_tp_di (tp)); + if (TARGET_MIPS16) + { + fn = mips16_stub_function ("__mips16_rdhwr"); + if (!call_insn_operand (fn, VOIDmode)) + fn = force_reg (Pmode, fn); + emit_insn (PMODE_INSN (gen_tls_get_tp_mips16, (tp, fn))); + } else - emit_insn (gen_tls_get_tp_si (tp)); + emit_insn (PMODE_INSN (gen_tls_get_tp, (tp))); return tp; } @@ -2839,15 +2859,9 @@ mips_get_tp (void) static rtx mips_legitimize_tls_address (rtx loc) { - rtx dest, insn, v0, tp, tmp1, tmp2, eqv; + rtx dest, insn, v0, tp, tmp1, tmp2, eqv, offset; enum tls_model model; - if (TARGET_MIPS16) - { - sorry ("MIPS16 TLS"); - return gen_reg_rtx (Pmode); - } - model = SYMBOL_REF_TLS_MODEL (loc); /* Only TARGET_ABICALLS code can have more than one module; other code must be be static and should not use a GOT. All TLS models @@ -2875,9 +2889,15 @@ mips_legitimize_tls_address (rtx loc) UNSPEC_TLS_LDM); emit_libcall_block (insn, tmp1, v0, eqv); - tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL); - dest = gen_rtx_LO_SUM (Pmode, tmp2, - mips_unspec_address (loc, SYMBOL_DTPREL)); + offset = mips_unspec_address (loc, SYMBOL_DTPREL); + if (mips_split_p[SYMBOL_DTPREL]) + { + tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL); + dest = gen_rtx_LO_SUM (Pmode, tmp2, offset); + } + else + dest = expand_binop (Pmode, add_optab, tmp1, offset, + 0, 0, OPTAB_DIRECT); break; case TLS_MODEL_INITIAL_EXEC: @@ -2893,10 +2913,16 @@ mips_legitimize_tls_address (rtx loc) break; case TLS_MODEL_LOCAL_EXEC: - tp = mips_get_tp (); - tmp1 = mips_unspec_offset_high (NULL, tp, loc, SYMBOL_TPREL); - dest = gen_rtx_LO_SUM (Pmode, tmp1, - mips_unspec_address (loc, SYMBOL_TPREL)); + tmp1 = mips_get_tp (); + offset = mips_unspec_address (loc, SYMBOL_TPREL); + if (mips_split_p[SYMBOL_TPREL]) + { + tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_TPREL); + dest = gen_rtx_LO_SUM (Pmode, tmp2, offset); + } + else + dest = expand_binop (Pmode, add_optab, tmp1, offset, + 0, 0, OPTAB_DIRECT); break; default: @@ -5866,18 +5892,6 @@ struct mips16_stub { }; static struct mips16_stub *mips16_stubs; -/* Return a SYMBOL_REF for a MIPS16 function called NAME. */ - -static rtx -mips16_stub_function (const char *name) -{ - rtx x; - - x = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); - SYMBOL_REF_FLAGS (x) |= (SYMBOL_FLAG_EXTERNAL | SYMBOL_FLAG_FUNCTION); - return x; -} - /* Return the two-character string that identifies floating-point return mode MODE in the name of a MIPS16 function stub. */ @@ -7192,38 +7206,44 @@ mips_init_relocs (void) { memset (mips_split_p, '\0', sizeof (mips_split_p)); memset (mips_split_hi_p, '\0', sizeof (mips_split_hi_p)); + memset (mips_use_pcrel_pool_p, '\0', sizeof (mips_use_pcrel_pool_p)); memset (mips_hi_relocs, '\0', sizeof (mips_hi_relocs)); memset (mips_lo_relocs, '\0', sizeof (mips_lo_relocs)); - if (ABI_HAS_64BIT_SYMBOLS) - { - if (TARGET_EXPLICIT_RELOCS) - { - mips_split_p[SYMBOL_64_HIGH] = true; - mips_hi_relocs[SYMBOL_64_HIGH] = "%highest("; - mips_lo_relocs[SYMBOL_64_HIGH] = "%higher("; - - mips_split_p[SYMBOL_64_MID] = true; - mips_hi_relocs[SYMBOL_64_MID] = "%higher("; - mips_lo_relocs[SYMBOL_64_MID] = "%hi("; - - mips_split_p[SYMBOL_64_LOW] = true; - mips_hi_relocs[SYMBOL_64_LOW] = "%hi("; - mips_lo_relocs[SYMBOL_64_LOW] = "%lo("; - - mips_split_p[SYMBOL_ABSOLUTE] = true; - mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo("; - } - } + if (TARGET_MIPS16_PCREL_LOADS) + mips_use_pcrel_pool_p[SYMBOL_ABSOLUTE] = true; else { - if (TARGET_EXPLICIT_RELOCS || mips_split_addresses_p () || TARGET_MIPS16) + if (ABI_HAS_64BIT_SYMBOLS) { - mips_split_p[SYMBOL_ABSOLUTE] = true; - mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi("; - mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo("; + if (TARGET_EXPLICIT_RELOCS) + { + mips_split_p[SYMBOL_64_HIGH] = true; + mips_hi_relocs[SYMBOL_64_HIGH] = "%highest("; + mips_lo_relocs[SYMBOL_64_HIGH] = "%higher("; - mips_lo_relocs[SYMBOL_32_HIGH] = "%hi("; + mips_split_p[SYMBOL_64_MID] = true; + mips_hi_relocs[SYMBOL_64_MID] = "%higher("; + mips_lo_relocs[SYMBOL_64_MID] = "%hi("; + + mips_split_p[SYMBOL_64_LOW] = true; + mips_hi_relocs[SYMBOL_64_LOW] = "%hi("; + mips_lo_relocs[SYMBOL_64_LOW] = "%lo("; + + mips_split_p[SYMBOL_ABSOLUTE] = true; + mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo("; + } + } + else + { + if (TARGET_EXPLICIT_RELOCS + || mips_split_addresses_p () + || TARGET_MIPS16) + { + mips_split_p[SYMBOL_ABSOLUTE] = true; + mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi("; + mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo("; + } } } @@ -7291,16 +7311,23 @@ mips_init_relocs (void) mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd("; mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm("; - mips_split_p[SYMBOL_DTPREL] = true; - mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi("; - mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo("; + if (TARGET_MIPS16_PCREL_LOADS) + { + mips_use_pcrel_pool_p[SYMBOL_DTPREL] = true; + mips_use_pcrel_pool_p[SYMBOL_TPREL] = true; + } + else + { + mips_split_p[SYMBOL_DTPREL] = true; + mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi("; + mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo("; + + mips_split_p[SYMBOL_TPREL] = true; + mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi("; + mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo("; + } mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel("; - - mips_split_p[SYMBOL_TPREL] = true; - mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi("; - mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo("; - mips_lo_relocs[SYMBOL_HALF] = "%half("; } @@ -8082,6 +8109,29 @@ mips_output_ascii (FILE *stream, const char *string, size_t len) fprintf (stream, "\"\n"); } +/* Return the pseudo-op for full SYMBOL_(D)TPREL address *ADDR. + Update *ADDR with the operand that should be printed. */ + +const char * +mips_output_tls_reloc_directive (rtx *addr) +{ + enum mips_symbol_type type; + + type = mips_classify_symbolic_expression (*addr, SYMBOL_CONTEXT_LEA); + *addr = mips_strip_unspec_address (*addr); + switch (type) + { + case SYMBOL_DTPREL: + return Pmode == SImode ? ".dtprelword\t%0" : ".dtpreldword\t%0"; + + case SYMBOL_TPREL: + return Pmode == SImode ? ".tprelword\t%0" : ".tpreldword\t%0"; + + default: + gcc_unreachable (); + } +} + /* Emit either a label, .comm, or .lcomm directive. When using assembler macros, mark the symbol as written so that mips_asm_output_external won't emit an .extern for it. STREAM is the output file, NAME is the @@ -13783,6 +13833,10 @@ mips16_rewrite_pool_refs (rtx *x, void *data) return -1; } + /* Don't rewrite the __mips16_rdwr symbol. */ + if (GET_CODE (*x) == UNSPEC && XINT (*x, 1) == UNSPEC_TLS_GET_TP) + return -1; + if (TARGET_MIPS16_TEXT_LOADS) mips16_rewrite_pool_constant (info->pool, x); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index d07e241d0d6..1c19f8b2df4 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1785,8 +1785,6 @@ struct mips_cpu_info { from there after reload. */ #define PIC_OFFSET_TABLE_REGNUM \ (reload_completed ? REGNO (pic_offset_table_rtx) : GLOBAL_POINTER_REGNUM) - -#define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25) /* Define the classes of registers for register constraints in the machine description. Also define ranges of constants. @@ -2868,6 +2866,9 @@ extern int mips_dbx_regno[]; extern int mips_dwarf_regno[]; extern bool mips_split_p[]; extern bool mips_split_hi_p[]; +extern bool mips_use_pcrel_pool_p[]; +extern const char *mips_lo_relocs[]; +extern const char *mips_hi_relocs[]; extern enum processor mips_arch; /* which cpu to codegen for */ extern enum processor mips_tune; /* which cpu to schedule for */ extern int mips_isa; /* architectural level */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 3be7dd4df16..3b3eecfeb90 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -103,6 +103,7 @@ UNSPEC_LOAD_GOT UNSPEC_TLS_LDM UNSPEC_TLS_GET_TP + UNSPEC_UNSHIFTED_HIGH ;; MIPS16 constant pools. UNSPEC_ALIGN @@ -135,6 +136,7 @@ (define_constants [(TLS_GET_TP_REGNUM 3) + (PIC_FUNCTION_ADDR_REGNUM 25) (RETURN_ADDR_REGNUM 31) (CPRESTORE_SLOT_REGNUM 76) (GOT_VERSION_REGNUM 79) @@ -3924,14 +3926,19 @@ ;; ;; on MIPS16 targets. (define_split - [(set (match_operand:SI 0 "d_operand") - (high:SI (match_operand:SI 1 "absolute_symbolic_operand")))] + [(set (match_operand:P 0 "d_operand") + (high:P (match_operand:P 1 "symbolic_operand_with_high")))] "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); -}) + [(set (match_dup 0) (unspec:P [(match_dup 1)] UNSPEC_UNSHIFTED_HIGH)) + (set (match_dup 0) (ashift:P (match_dup 0) (const_int 16)))]) + +(define_insn "*unshifted_high" + [(set (match_operand:P 0 "d_operand" "=d") + (unspec:P [(match_operand:P 1 "symbolic_operand_with_high")] + UNSPEC_UNSHIFTED_HIGH))] + "" + "li\t%0,%h1" + [(set_attr "extended_mips16" "yes")]) ;; Insns to fetch a symbol from a big GOT. @@ -6492,6 +6499,14 @@ ;; .................... ;; +(define_insn "consttable_tls_reloc" + [(unspec_volatile [(match_operand 0 "tls_reloc_operand" "") + (match_operand 1 "const_int_operand" "")] + UNSPEC_CONSTTABLE_INT)] + "TARGET_MIPS16_PCREL_LOADS" + { return mips_output_tls_reloc_directive (&operands[0]); } + [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))]) + (define_insn "consttable_int" [(unspec_volatile [(match_operand 0 "consttable_operand" "") (match_operand 1 "const_int_operand" "")] @@ -6593,6 +6608,49 @@ ; See tls_get_tp_ (set_attr "can_delay" "no") (set_attr "mode" "")]) + +;; In MIPS16 mode, the TLS base pointer is accessed by a +;; libgcc helper function __mips16_rdhwr(), as 'rdhwr' is not +;; accessible in MIPS16. +;; +;; This is not represented as a call insn, to avoid the +;; unnecesarry clobbering of caller-save registers by a +;; function consisting only of: "rdhwr $3,$29; j $31; nop;" +;; +;; A $25 clobber is added to cater for a $25 load stub added by the +;; linker to __mips16_rdhwr when the call is made from non-PIC code. + +(define_insn_and_split "tls_get_tp_mips16_" + [(set (match_operand:P 0 "register_operand" "=d") + (unspec:P [(match_operand:P 1 "call_insn_operand" "dS")] + UNSPEC_TLS_GET_TP)) + (clobber (reg:P TLS_GET_TP_REGNUM)) + (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) + (clobber (reg:P RETURN_ADDR_REGNUM))] + "HAVE_AS_TLS && TARGET_MIPS16" + "#" + "&& reload_completed" + [(parallel [(set (reg:P TLS_GET_TP_REGNUM) + (unspec:P [(match_dup 1)] UNSPEC_TLS_GET_TP)) + (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) + (clobber (reg:P RETURN_ADDR_REGNUM))]) + (set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))] + "" + [(set_attr "type" "multi") + (set_attr "length" "16") + (set_attr "mode" "")]) + +(define_insn "*tls_get_tp_mips16_call_" + [(set (reg:P TLS_GET_TP_REGNUM) + (unspec:P [(match_operand:P 0 "call_insn_operand" "dS")] + UNSPEC_TLS_GET_TP)) + (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) + (clobber (reg:P RETURN_ADDR_REGNUM))] + "HAVE_AS_TLS && TARGET_MIPS16" + { return MIPS_CALL ("jal", operands, 0, -1); } + [(set_attr "type" "call") + (set_attr "length" "12") + (set_attr "mode" "")]) ;; Synchronization instructions. diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index b6113739786..57b1af2de3e 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -288,12 +288,20 @@ && type == SYMBOL_ABSOLUTE); }) +(define_predicate "symbolic_operand_with_high" + (match_code "const,symbol_ref,label_ref") +{ + enum mips_symbol_type type; + return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) + && mips_hi_relocs[(int) type]); +}) + (define_predicate "force_to_mem_operand" (match_code "const,symbol_ref,label_ref") { enum mips_symbol_type symbol_type; return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &symbol_type) - && symbol_type == SYMBOL_FORCE_TO_MEM); + && mips_use_pcrel_pool_p[(int) symbol_type]); }) (define_predicate "got_disp_operand" @@ -312,6 +320,14 @@ && type == SYMBOL_GOT_PAGE_OFST); }) +(define_predicate "tls_reloc_operand" + (match_code "const,symbol_ref,label_ref") +{ + enum mips_symbol_type type; + return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &type) + && (type == SYMBOL_DTPREL || type == SYMBOL_TPREL)); +}) + (define_predicate "symbol_ref_operand" (match_code "symbol_ref")) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8bf1c29ea72..5d5bd3ee465 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-01-15 Richard Sandiford + + * gcc.target/mips/code-readable-2.c: Allow the jump table address + to be loaded from the constant pool, rather than via %hi and %lo. + 2012-01-15 Uros Bizjak PR rtl-optimization/51821 diff --git a/gcc/testsuite/gcc.target/mips/code-readable-2.c b/gcc/testsuite/gcc.target/mips/code-readable-2.c index 8b87ff6582c..e0176c3dbd5 100644 --- a/gcc/testsuite/gcc.target/mips/code-readable-2.c +++ b/gcc/testsuite/gcc.target/mips/code-readable-2.c @@ -26,8 +26,7 @@ bar (void) /* { 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\t\[^\n\]*L" } } */ /* { dg-final { scan-assembler "\t\\.word\tk\n" } } */ /* { dg-final { scan-assembler-not "%hi\\(k\\)" } } */ diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index f47f76bbb9c..70880b0b5cc 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,10 @@ +2012-01-15 Chung-Lin Tang + Richard Sandiford + + * config/mips/libgcc-mips16.ver (__mips16_rdhwr): Add. + * config/mips/mips16.S (__mips16_rdhwr): New function. + * config/mips/t-mips16 (LIB1ASMFUNCS): Add _m16rdhwr. + 2012-01-11 Nathan Sidwell * libgcov.c (__gcov_init): Ignore objects with no functions. diff --git a/libgcc/config/mips/libgcc-mips16.ver b/libgcc/config/mips/libgcc-mips16.ver index ddb23e7e750..a9257447852 100644 --- a/libgcc/config/mips/libgcc-mips16.ver +++ b/libgcc/config/mips/libgcc-mips16.ver @@ -84,3 +84,7 @@ GCC_4.4.0 { __mips16_call_stub_dc_9 __mips16_call_stub_dc_10 } + +GCC_4.7.0 { + __mips16_rdhwr +} diff --git a/libgcc/config/mips/mips16.S b/libgcc/config/mips/mips16.S index ec331b5f65e..a087508d4a6 100644 --- a/libgcc/config/mips/mips16.S +++ b/libgcc/config/mips/mips16.S @@ -709,4 +709,15 @@ CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC) CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC) #endif #endif /* !__mips_single_float */ + +#ifdef L_m16rdhwr +STARTFN (__mips16_rdhwr) + .set push + .set mips32r2 + .set noreorder + rdhwr $3,$29 + .set pop + j $31 + ENDFN (__mips16_rdhwr) +#endif #endif diff --git a/libgcc/config/mips/t-mips16 b/libgcc/config/mips/t-mips16 index 5553ed76e2d..7fe37f64f52 100644 --- a/libgcc/config/mips/t-mips16 +++ b/libgcc/config/mips/t-mips16 @@ -36,7 +36,8 @@ LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \ _m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \ _m16stubsc9 _m16stubsc10 \ _m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \ - _m16stubdc9 _m16stubdc10 + _m16stubdc9 _m16stubdc10 \ + _m16rdhwr SYNC = yes SYNC_CFLAGS = -mno-mips16