diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 28 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 3 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 41 |
4 files changed, 68 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f78a834..824cb14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2003-12-05 Richard Sandiford <rsandifo@redhat.com> + + PR bootstrap/13145 + * config/mips/mips.h (FIRST_PSEUDO_REGISTER): Adjust comment. + * config/mips/mips.c (mips_reg_names, mips_sw_reg_names): Add $fcall. + (mips_load_got): Always create a constant MEM. + (mips_expand_call): Use load_callsi and load_calldi. + * config/mips/mips.md (UNSPEC_LOAD_CALL, FAKE_CALL_REGNO): New consts. + (load_callsi, load_calldi): New patterns. + 2003-12-05 Peter Gerwinski <peter@gerwinski.de> * tree.def (PLACEHOLDER_EXPR): Clarify commentary. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 0691941..f73b1a9 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -569,7 +569,7 @@ char mips_reg_names[][8] = "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", - "$fcc5","$fcc6","$fcc7","", "", "", "", "", + "$fcc5","$fcc6","$fcc7","", "", "", "", "$fakec", "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", "$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", @@ -598,7 +598,7 @@ char mips_sw_reg_names[][8] = "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", - "$fcc5","$fcc6","$fcc7","$rap", "", "", "", "", + "$fcc5","$fcc6","$fcc7","$rap", "", "", "", "$fakec", "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", "$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", @@ -1658,14 +1658,10 @@ mips_load_got (rtx base, rtx addr, enum mips_symbol_type symbol_type) mem = gen_rtx_MEM (ptr_mode, gen_rtx_LO_SUM (Pmode, base, offset)); set_mem_alias_set (mem, mips_got_alias_set); - /* GOT references can't trap. */ + /* GOT entries are constant and references to them can't trap. */ + RTX_UNCHANGING_P (mem) = 1; MEM_NOTRAP_P (mem) = 1; - /* If we allow a function's address to be lazily bound, its entry - may change after the first call. Other entries are constant. */ - if (symbol_type != SYMBOL_GOTOFF_CALL) - RTX_UNCHANGING_P (mem) = 1; - return mem; } @@ -3193,11 +3189,19 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) { if (TARGET_EXPLICIT_RELOCS && global_got_operand (addr, VOIDmode)) { - rtx high = mips_unspec_offset_high (pic_offset_table_rtx, - addr, SYMBOL_GOTOFF_CALL); - addr = mips_load_got (high, addr, SYMBOL_GOTOFF_CALL); + rtx high, lo_sum_symbol; + + high = mips_unspec_offset_high (pic_offset_table_rtx, + addr, SYMBOL_GOTOFF_CALL); + lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL); + addr = gen_reg_rtx (Pmode); + if (Pmode == SImode) + emit_insn (gen_load_callsi (addr, high, lo_sum_symbol)); + else + emit_insn (gen_load_calldi (addr, high, lo_sum_symbol)); } - addr = force_reg (Pmode, addr); + else + addr = force_reg (Pmode, addr); } if (TARGET_MIPS16 diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index ac69384..e144d64 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1468,7 +1468,8 @@ extern const struct mips_cpu_info *mips_tune_info; - 8 condition code registers - 2 accumulator registers (hi and lo) - 32 registers each for coprocessors 0, 2 and 3 - - 6 dummy entries that were used at various times in the past. */ + - FAKE_CALL_REGNO (see the comment above load_callsi for details) + - 5 dummy entries that were used at various times in the past. */ #define FIRST_PSEUDO_REGISTER 176 diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 203ac2e..5b758c8 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -54,8 +54,11 @@ (UNSPEC_SDL 24) (UNSPEC_SDR 25) (UNSPEC_LOADGP 26) + (UNSPEC_LOAD_CALL 27) - (UNSPEC_ADDRESS_FIRST 100)]) + (UNSPEC_ADDRESS_FIRST 100) + + (FAKE_CALL_REGNO 79)]) ;; .................... ;; @@ -8331,6 +8334,42 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/" ;; ;; .................... +;; Instructions to load a call address from the GOT. The address might +;; point to a function or to a lazy binding stub. In the latter case, +;; the stub will use the dynamic linker to resolve the function, which +;; in turn will change the GOT entry to point to the function's real +;; address. +;; +;; This means that every call, even pure and constant ones, can +;; potentially modify the GOT entry. And once a stub has been called, +;; we must not call it again. +;; +;; We represent this restriction using an imaginary fixed register that +;; acts like a GOT version number. By making the register call-clobbered, +;; we tell the target-independent code that the address could be changed +;; by any call insn. +(define_insn "load_callsi" + [(set (match_operand:SI 0 "register_operand" "=c") + (unspec:SI [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "immediate_operand" "") + (reg:SI FAKE_CALL_REGNO)] + UNSPEC_LOAD_CALL))] + "TARGET_ABICALLS" + "lw\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) + +(define_insn "load_calldi" + [(set (match_operand:DI 0 "register_operand" "=c") + (unspec:DI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "immediate_operand" "") + (reg:DI FAKE_CALL_REGNO)] + UNSPEC_LOAD_CALL))] + "TARGET_ABICALLS" + "ld\t%0,%R2(%1)" + [(set_attr "type" "load") + (set_attr "length" "4")]) + ;; Sibling calls. All these patterns use jump instructions. ;; If TARGET_SIBCALLS, call_insn_operand will only accept constant |