aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/rs6000.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/rs6000.md')
-rw-r--r--gcc/config/rs6000/rs6000.md161
1 files changed, 135 insertions, 26 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 2c0b0491abe..15426d96f63 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -1672,7 +1672,7 @@
(const_int 0)))
(set (match_operand:P 0 "gpc_reg_operand" "")
(neg:P (match_dup 1)))]
- "TARGET_32BIT && reload_completed"
+ "reload_completed"
[(set (match_dup 0)
(neg:P (match_dup 1)))
(set (match_dup 2)
@@ -7360,26 +7360,6 @@
;; Now define ways of moving data around.
-;; Elf specific ways of loading addresses for non-PIC code.
-;; The output of this could be r0, but we make a very strong
-;; preference for a base register because it will usually
-;; be needed there.
-(define_insn "elf_high"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
- (high:SI (match_operand 1 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "{liu|lis} %0,%1@ha")
-
-(define_insn "elf_low"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
- (match_operand 2 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "@
- {cal|la} %0,%2@l(%1)
- {ai|addic} %0,%1,%K2")
-
-
;; Set up a register with a value from the GOT table
(define_expand "movsi_got"
@@ -9810,7 +9790,8 @@
[(set (match_operand:SI 0 "register_operand" "=l")
(match_operand:SI 1 "immediate_operand" "s"))
(use (unspec [(match_dup 1)] UNSPEC_TOC))]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%1\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -9833,6 +9814,22 @@
"{l|lwz} %0,%2-%3(%1)"
[(set_attr "type" "load")])
+(define_insn "load_toc_v4_PIC_3b"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+ (high:SI
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s")))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cau|addis} %0,%1,%2-%3@ha")
+
+(define_insn "load_toc_v4_PIC_3c"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s"))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cal|addi} %0,%1,%2-%3@l")
;; If the TOC is shared over a translation unit, as happens with all
;; the kinds of PIC that we support, we need to restore the TOC
@@ -9867,6 +9864,25 @@
rs6000_emit_load_toc_table (FALSE);
DONE;
}")
+
+;; Elf specific ways of loading addresses for non-PIC code.
+;; The output of this could be r0, but we make a very strong
+;; preference for a base register because it will usually
+;; be needed there.
+(define_insn "elf_high"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+ (high:SI (match_operand 1 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "{liu|lis} %0,%1@ha")
+
+(define_insn "elf_low"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand 2 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "@
+ {cal|la} %0,%2@l(%1)
+ {ai|addic} %0,%1,%K2")
;; A function pointer under AIX is a pointer to a data area whose first word
;; contains the actual address of the function, whose second word contains a
@@ -9983,6 +9999,25 @@
operands[0] = XEXP (operands[0], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[0]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode, operands[0]),
+ operands[1]),
+ gen_rtx_USE (VOIDmode, operands[2]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[0]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
@@ -10034,6 +10069,28 @@
operands[1] = XEXP (operands[1], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[1]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_SET (VOIDmode,
+ operands[0],
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode,
+ operands[1]),
+ operands[2])),
+ gen_rtx_USE (VOIDmode, operands[3]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[1]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
@@ -10307,7 +10364,18 @@
#if TARGET_MACHO
return output_call(insn, operands, 0, 2);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ /* The magic 32768 offset here and in the other sysv call insns
+ corresponds to the offset of r30 in .got2, as given by LCTOC1.
+ See sysv4.h:toc_section. */
+ return "bl %z0+32768@plt";
+ else
+ return "bl %z0@plt";
+ }
+ else
+ return "bl %z0";
#endif
}
[(set_attr "type" "branch,branch")
@@ -10352,7 +10420,15 @@
#if TARGET_MACHO
return output_call(insn, operands, 1, 3);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return "bl %z1+32768@plt";
+ else
+ return "bl %z1@plt";
+ }
+ else
+ return "bl %z1";
#endif
}
[(set_attr "type" "branch,branch")
@@ -10567,7 +10643,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z0+32768@plt\";
+ else
+ return \"b %z0@plt\";
+ }
+ else
+ return \"b %z0\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10613,7 +10697,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z1+32768@plt\";
+ else
+ return \"b %z1@plt\";
+ }
+ else
+ return \"b %z1\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -14776,6 +14868,23 @@
"<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- $-12"
[(set_attr "length" "16")])
+; This pattern could also take immediate values of operand 1,
+; since the non-NOT version of the operator is used; but this is not
+; very useful, since in practice operand 1 is a full 32-bit value.
+; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
+(define_insn "*sync_boolcshort_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
+ (match_operator:SI 4 "boolean_operator"
+ [(xor:SI (match_operand:SI 0 "memory_operand" "+Z")
+ (match_operand:SI 5 "logical_operand" "rK"))
+ (match_operand:SI 1 "gpc_reg_operand" "r")]))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
+ (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 6 "=&x"))]
+ "TARGET_POWERPC"
+ "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
+ [(set_attr "length" "20")])
+
(define_insn "*sync_boolc<mode>_internal2"
[(set (match_operand:GPR 2 "gpc_reg_operand" "=&r")
(match_operator:GPR 4 "boolean_operator"