aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.md')
-rw-r--r--gcc/config/mips/mips.md41
1 files changed, 40 insertions, 1 deletions
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