diff options
Diffstat (limited to 'gcc/config/mips')
-rw-r--r-- | gcc/config/mips/mips-protos.h | 19 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 30 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 22 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 33 | ||||
-rw-r--r-- | gcc/config/mips/predicates.md | 3 | ||||
-rw-r--r-- | gcc/config/mips/vxworks.h | 3 |
6 files changed, 98 insertions, 12 deletions
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 78cdc1ae669..94fe227d190 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -82,7 +82,11 @@ Boston, MA 02110-1301, USA. */ SYMBOL_64_LOW For a 64-bit symbolic address X, this is the value of - (%hi(X) << 16) + %lo(X). */ + (%hi(X) << 16) + %lo(X). + + SYMBOL_HALF + An UNSPEC wrapper around any kind of address. It represents the + low 16 bits of that address. */ enum mips_symbol_type { SYMBOL_GENERAL, SYMBOL_SMALL_DATA, @@ -101,9 +105,10 @@ enum mips_symbol_type { SYMBOL_TPREL, SYMBOL_64_HIGH, SYMBOL_64_MID, - SYMBOL_64_LOW + SYMBOL_64_LOW, + SYMBOL_HALF }; -#define NUM_SYMBOL_TYPES (SYMBOL_64_LOW + 1) +#define NUM_SYMBOL_TYPES (SYMBOL_HALF + 1) /* Identifiers a style of $gp initialization sequence. @@ -119,12 +124,16 @@ enum mips_symbol_type { by .cpsetup). LOADGP_ABSOLUTE - The GNU absolute sequence, as generated by loadgp_absolute. */ + The GNU absolute sequence, as generated by loadgp_absolute. + + LOADGP_RTP + The VxWorks RTP PIC sequence, as generated by loadgp_rtp. */ enum mips_loadgp_style { LOADGP_NONE, LOADGP_OLDABI, LOADGP_NEWABI, - LOADGP_ABSOLUTE + LOADGP_ABSOLUTE, + LOADGP_RTP }; extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 9100e998c76..b67210934ae 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1245,6 +1245,9 @@ mips_symbol_binds_local_p (rtx x) static enum mips_symbol_type mips_classify_symbol (rtx x) { + if (TARGET_RTP_PIC) + return SYMBOL_GOT_DISP; + if (GET_CODE (x) == LABEL_REF) { if (TARGET_MIPS16) @@ -1385,6 +1388,7 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) case SYMBOL_TPREL: case SYMBOL_GOTTPREL: case SYMBOL_TLS: + case SYMBOL_HALF: return false; } gcc_unreachable (); @@ -1484,6 +1488,7 @@ mips_symbolic_address_p (enum mips_symbol_type symbol_type, case SYMBOL_64_HIGH: case SYMBOL_64_MID: case SYMBOL_64_LOW: + case SYMBOL_HALF: return true; } gcc_unreachable (); @@ -1630,6 +1635,7 @@ mips_symbol_insns (enum mips_symbol_type type) return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2); case SYMBOL_SMALL_DATA: + case SYMBOL_HALF: return 1; case SYMBOL_CONSTANT_POOL: @@ -4886,6 +4892,9 @@ override_options (void) warning (0, "%<-G%> is incompatible with %<-mabicalls%>"); } + if (TARGET_VXWORKS_RTP && mips_section_threshold > 0) + warning (0, "-G and -mrtp are incompatible"); + /* mips_split_addresses is a half-way house between explicit relocations and the traditional assembler macros. It can split absolute 32-bit symbolic constants into a high/lo_sum @@ -5192,6 +5201,8 @@ override_options (void) mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi("; mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo("; + mips_lo_relocs[SYMBOL_HALF] = "%half("; + /* We don't have a thread pointer access instruction on MIPS16, or appropriate TLS relocations. */ if (TARGET_MIPS16) @@ -6573,6 +6584,9 @@ mips_current_loadgp_style (void) if (!TARGET_USE_GOT || cfun->machine->global_pointer == 0) return LOADGP_NONE; + if (TARGET_RTP_PIC) + return LOADGP_RTP; + if (TARGET_ABSOLUTE_ABICALLS) return LOADGP_ABSOLUTE; @@ -6589,7 +6603,7 @@ static GTY(()) rtx mips_gnu_local_gp; static void mips_emit_loadgp (void) { - rtx addr, offset, incoming_address; + rtx addr, offset, incoming_address, base, index; switch (mips_current_loadgp_style ()) { @@ -6611,6 +6625,14 @@ mips_emit_loadgp (void) emit_insn (gen_loadgp_blockage ()); break; + case LOADGP_RTP: + base = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (VXWORKS_GOTT_BASE)); + index = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (VXWORKS_GOTT_INDEX)); + emit_insn (gen_loadgp_rtp (base, index)); + if (!TARGET_EXPLICIT_RELOCS) + emit_insn (gen_loadgp_blockage ()); + break; + default: break; } @@ -7313,9 +7335,9 @@ mips_in_small_data_p (tree decl) if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) return false; - /* We don't yet generate small-data references for -mabicalls. See related - -G handling in override_options. */ - if (TARGET_ABICALLS) + /* We don't yet generate small-data references for -mabicalls or + VxWorks RTP code. See the related -G handling in override_options. */ + if (TARGET_ABICALLS || TARGET_VXWORKS_RTP) return false; if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0) diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index af8a7f4ba2a..6cf42a7249f 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -24,6 +24,8 @@ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "config/vxworks-dummy.h" + /* MIPS external variables defined in mips.c. */ /* Which processor to schedule for. Since there is no difference between @@ -143,6 +145,9 @@ extern const struct mips_rtx_cost_data *mips_cost; /* Run-time compilation parameters selecting different hardware subsets. */ +/* True if we are generating position-independent VxWorks RTP code. */ +#define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic) + /* True if the call patterns should be split into a jalr followed by an instruction to restore $gp. It is only safe to split the load from the call when every use of $gp is explicit. */ @@ -178,7 +183,7 @@ extern const struct mips_rtx_cost_data *mips_cost; (!TARGET_MIPS16 && (!TARGET_USE_GOT || TARGET_EXPLICIT_RELOCS)) /* True if we need to use a global offset table to access some symbols. */ -#define TARGET_USE_GOT TARGET_ABICALLS +#define TARGET_USE_GOT (TARGET_ABICALLS || TARGET_RTP_PIC) /* True if TARGET_USE_GOT and if $gp is a call-clobbered register. */ #define TARGET_CALL_CLOBBERED_GP (TARGET_ABICALLS && TARGET_OLDABI) @@ -186,8 +191,9 @@ extern const struct mips_rtx_cost_data *mips_cost; /* True if TARGET_USE_GOT and if $gp is a call-saved register. */ #define TARGET_CALL_SAVED_GP (TARGET_USE_GOT && !TARGET_CALL_CLOBBERED_GP) -/* True if indirect calls must use register class PIC_FN_ADDR_REG. */ -#define TARGET_USE_PIC_FN_ADDR_REG TARGET_ABICALLS +/* True if indirect calls must use register class PIC_FN_ADDR_REG. + This is true for both the PIC and non-PIC VxWorks RTP modes. */ +#define TARGET_USE_PIC_FN_ADDR_REG (TARGET_ABICALLS || TARGET_VXWORKS_RTP) /* True if .gpword or .gpdword should be used for switch tables. @@ -2578,6 +2584,16 @@ do { \ fprintf (STREAM, "\t%s\t%sL%d\n", \ ptr_mode == DImode ? ".gpdword" : ".gpword", \ LOCAL_LABEL_PREFIX, VALUE); \ + else if (TARGET_RTP_PIC) \ + { \ + /* Make the entry relative to the start of the function. */ \ + rtx fnsym = XEXP (DECL_RTL (current_function_decl), 0); \ + fprintf (STREAM, "\t%s\t%sL%d-", \ + Pmode == DImode ? ".dword" : ".word", \ + LOCAL_LABEL_PREFIX, VALUE); \ + assemble_name (STREAM, XSTR (fnsym, 0)); \ + fprintf (STREAM, "\n"); \ + } \ else \ fprintf (STREAM, "\t%s\t%sL%d\n", \ ptr_mode == DImode ? ".dword" : ".word", \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 8fb78ca90ff..2178481808d 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -4125,6 +4125,30 @@ (set_attr "mode" "none") (set_attr "length" "0")]) +;; Initialize $gp for RTP PIC. Operand 0 is the __GOTT_BASE__ symbol +;; and operand 1 is the __GOTT_INDEX__ symbol. +(define_insn "loadgp_rtp" + [(unspec_volatile [(match_operand 0 "symbol_ref_operand") + (match_operand 1 "symbol_ref_operand")] UNSPEC_LOADGP)] + "mips_current_loadgp_style () == LOADGP_RTP" + "#" + [(set_attr "length" "12")]) + +(define_split + [(unspec_volatile [(match_operand:P 0 "symbol_ref_operand") + (match_operand:P 1 "symbol_ref_operand")] UNSPEC_LOADGP)] + "mips_current_loadgp_style () == LOADGP_RTP" + [(set (match_dup 2) (high:P (match_dup 3))) + (set (match_dup 2) (unspec:P [(match_dup 2) + (match_dup 3)] UNSPEC_LOAD_GOT)) + (set (match_dup 2) (unspec:P [(match_dup 2) + (match_dup 4)] UNSPEC_LOAD_GOT))] +{ + operands[2] = pic_offset_table_rtx; + operands[3] = mips_unspec_address (operands[0], SYMBOL_GENERAL); + operands[4] = mips_unspec_address (operands[1], SYMBOL_HALF); +}) + ;; Emit a .cprestore directive, which normally expands to a single store ;; instruction. Note that we continue to use .cprestore for explicit reloc ;; code so that jals inside inline asms will work correctly. @@ -4931,6 +4955,15 @@ else if (TARGET_GPWORD) operands[0] = expand_binop (Pmode, add_optab, operands[0], pic_offset_table_rtx, 0, 0, OPTAB_WIDEN); + else if (TARGET_RTP_PIC) + { + /* When generating RTP PIC, we use case table entries that are relative + to the start of the function. Add the function's address to the + value we loaded. */ + rtx start = get_hard_reg_initial_val (Pmode, PIC_FUNCTION_ADDR_REGNUM); + operands[0] = expand_binop (ptr_mode, add_optab, operands[0], + start, 0, 0, OPTAB_WIDEN); + } if (Pmode == SImode) emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 9f6cc955df2..16035c8cb2b 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -251,6 +251,9 @@ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_PAGE_OFST; }) +(define_predicate "symbol_ref_operand" + (match_code "symbol_ref")) + (define_predicate "stack_operand" (and (match_code "mem") (match_test "mips_stack_address_p (XEXP (op, 0), GET_MODE (op))"))) diff --git a/gcc/config/mips/vxworks.h b/gcc/config/mips/vxworks.h index 574221f3f99..5b6b026e9c4 100644 --- a/gcc/config/mips/vxworks.h +++ b/gcc/config/mips/vxworks.h @@ -86,3 +86,6 @@ VXWORKS_LINK_SPEC /* No _mcount profiling on VxWorks. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER + +#undef SUBTARGET_ASM_SPEC +#define SUBTARGET_ASM_SPEC "%{mrtp:%{fPIC|fpic:-mvxworks-pic}}" |