@@ -146,10 +146,16 @@
"@internal Lower SSE register when avoiding REX prefix and all SSE
registers otherwise.")
;; We use the B prefix to denote any number of internal operands:
+;; g Call and sibcall memory operand, valid for TARGET_X32
;; s Sibcall memory operand, not valid for TARGET_X32
;; w Call memory operand, not valid for TARGET_X32
;; z Constant call address operand.
+(define_constraint "Bg"
+ "@internal Call/sibcall GOT memory operand for x32."
+ (and (match_test "TARGET_X32")
+ (match_operand 0 "x32_call_got_memory_operand")))
No need for TARGET_X32, when all insn patterns are protected by it.
And the predicate is not x32 specific. And not call specific, so
"@internal GOT memory operand". Please use "GOT_memory_operand"
predicate, see below.
(define_constraint "Bs"
"@internal Sibcall memory operand."
(and (not (match_test "TARGET_X32"))
@@ -11659,6 +11659,15 @@
"* return ix86_output_call_insn (insn, operands[0]);"
[(set_attr "type" "call")])
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_got_x32"
+ [(call (mem:QI (zero_extend:DI
+ (match_operand:SI 0 "x32_call_insn_got_operand" "Bg")))
+ (match_operand 1))]
+ "TARGET_X32"
+ "* return ix86_output_call_insn (insn, operands[0]);"
+ [(set_attr "type" "call")])
"GOT_memory_operand" in the above pattern and all other call patterns.
(define_insn "*sibcall"
[(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
(match_operand 1))]
@@ -11825,6 +11834,17 @@
"* return ix86_output_call_insn (insn, operands[1]);"
[(set_attr "type" "callv")])
+;; This covers both call and sibcall since only GOT slot is allowed.
+(define_insn "*call_value_got_x32"
+ [(set (match_operand 0)
+ (call (mem:QI
+ (zero_extend:DI
+ (match_operand:SI 1 "x32_call_insn_got_operand" "Bg")))
+ (match_operand 2)))]
+ "TARGET_X32"
+ "* return ix86_output_call_insn (insn, operands[1]);"
+ [(set_attr "type" "callv")])
+
(define_insn "*sibcall_value"
[(set (match_operand 0)
(call (mem:QI (match_operand:W 1 "sibcall_insn_operand" "UBsBz"))
@@ -606,6 +606,20 @@
(and (not (match_test "TARGET_X32"))
(match_operand 0 "sibcall_memory_operand"))))
+;; Return true if OP is a GOT memory operand that can be used in x32 calls
+;; and sibcalls.
+(define_predicate "x32_call_got_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "CONSTANT_P (XEXP (op, 0))")
+ (match_test "GET_CODE (XEXP (XEXP (op, 0), 0)) == UNSPEC")
+ (match_test "XINT (XEXP (XEXP (op, 0), 0), 1) == UNSPEC_GOTPCREL")))
There is nothing x32 specific, it is just a GOT memory operand, so
let's name it "GOT_memory_operand".
+;; Test for a valid operand for an x32 call/sibcall instruction via
+;; memory. Only the 64-bit GOT slot is allowed.
+(define_special_predicate "x32_call_insn_got_operand"
+ (and (match_test "TARGET_X32")
+ (match_operand 0 "x32_call_got_memory_operand")))