This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] PA long branch support
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 9 Apr 2006 13:40:04 -0400 (EDT)
- Subject: [committed] PA long branch support
The enclosed patch adds long-branch support to all the PA conditional
branch patterns. Conditional branch distances can now be larger than
that available using the 17-bit pc-relative 'b' instruction.
The patch has been tested on hppa-unknown-linux-gnu with no regressions
and testcase for PR 26743. However, the patch is hard to test as a GCC
build doesn't trigger the use of long branches. Thus, I've probably
made a few mistakes ;)
Thanks to Randolph Chung who provided some code for the output_movb
case and a testcase. This showed that I'd somewhat botched the handling
of nullification in my previous attempt at fixing output_cbranch.
Once the technique of handling long branches was worked out, the rest
of the changes were more or less mechanical.
Committed to trunk.
Dave
--
J. David Anglin dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
2006-04-09 John David Anglin <dave.anglin@nrc-crnc.gc.ca>
PR target/26743
PR target/11254
PR target/10274
* pa.md (cbranch patterns): Revise arguments used in calls to
output_cbranch, output_bb and output_bvd. Add long branch length
attributes.
(fbranch patterns): Handle long branches.
(jump): Revise length check. Revise arguments for output_lbranch call.
Add long branch length attributes.
(decrement_and_branch_until_zero): Add long branch length attributes.
(output_movb, output_parallel_addb and output_parallel_movb patterns):
Likewise. Revise arguments for output_parallel_addb and
output_parallel_movb calls.
* pa-protos.h (output_cbranch, output_lbranch, output_bb, output_bvb,
output_parallel_movb and output_parallel_addb): Update prototypes.
* pa.c (output_cbranch): Revise arguments. Correct handling of
nullification in long branches.
(output_lbranch): Add new argument to control extraction of delay
instruction.
(output_bb): Handle long branches.
(output_bvb, output_dbra, output_movb, output_parallel_movb,
output_parallel_addb): Likewise.
Index: config/pa/pa.md
===================================================================
--- config/pa/pa.md (revision 112803)
+++ config/pa/pa.md (working copy)
@@ -139,7 +139,7 @@
(define_delay (eq_attr "type" "btable_branch,branch,parallel_branch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
-;; Floating point conditional branch delay slot description and
+;; Floating point conditional branch delay slot description.
(define_delay (eq_attr "type" "fbranch")
[(eq_attr "in_branch_delay" "true")
(eq_attr "in_nullified_branch_delay" "true")
@@ -1708,8 +1708,7 @@
""
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn);
+ return output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1719,6 +1718,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1736,8 +1737,7 @@
""
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn);
+ return output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1747,6 +1747,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1762,8 +1764,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn);
+ return output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1773,6 +1774,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1790,8 +1793,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn);
+ return output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1801,6 +1803,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1815,8 +1819,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn);
+ return output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1826,6 +1829,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1843,8 +1848,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn);
+ return output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1854,6 +1858,8 @@
(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
(const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
(eq (symbol_ref "flag_pic") (const_int 0))
(const_int 20)]
(const_int 28)))])
@@ -1871,15 +1877,21 @@
""
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 0);
+ return output_bb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -1893,15 +1905,21 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 0);
+ return output_bb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -1915,15 +1933,21 @@
""
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 0);
+ return output_bb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -1937,15 +1961,21 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 0);
+ return output_bb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -1959,15 +1989,21 @@
""
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 1);
+ return output_bb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -1981,15 +2017,21 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 1);
+ return output_bb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2003,15 +2045,21 @@
""
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 1);
+ return output_bb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2025,15 +2073,21 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 1);
+ return output_bb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
;; Branch on Variable Bit patterns.
(define_insn ""
@@ -2048,15 +2102,21 @@
""
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 0);
+ return output_bvb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2070,15 +2130,21 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 0);
+ return output_bvb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2092,15 +2158,21 @@
""
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 0);
+ return output_bvb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2114,15 +2186,21 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 0);
+ return output_bvb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2136,15 +2214,21 @@
""
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 1);
+ return output_bvb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2158,15 +2242,21 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 0, insn, 1);
+ return output_bvb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2180,15 +2270,21 @@
""
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 1);
+ return output_bvb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
(define_insn ""
[(set (pc)
@@ -2202,46 +2298,114 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
- get_attr_length (insn), 1, insn, 1);
+ return output_bvb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
;; Floating point branches
+
+;; ??? Nullification is handled differently from other branches.
+;; If nullification is specified, the delay slot is nullified on any
+;; taken branch regardless of branch direction.
(define_insn ""
[(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "! TARGET_SOFT_FLOAT"
+ "!TARGET_SOFT_FLOAT"
"*
{
- if (INSN_ANNULLED_BRANCH_P (insn))
- return \"ftest\;b,n %0\";
+ int length = get_attr_length (insn);
+ rtx xoperands[1];
+ int nullify, xdelay;
+
+ if (length < 16)
+ return \"ftest\;b%* %l0\";
+
+ if (dbr_sequence_length () == 0 || INSN_ANNULLED_BRANCH_P (insn))
+ {
+ nullify = 1;
+ xdelay = 0;
+ xoperands[0] = GEN_INT (length - 8);
+ }
else
- return \"ftest\;b%* %0\";
+ {
+ nullify = 0;
+ xdelay = 1;
+ xoperands[0] = GEN_INT (length - 4);
+ }
+
+ if (nullify)
+ output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b,n .+%0\", xoperands);
+ else
+ output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b .+%0\", xoperands);
+ return output_lbranch (operands[0], insn, xdelay);
}"
- [(set_attr "type" "fbranch")
- (set_attr "length" "8")])
+[(set_attr "type" "fbranch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36)))])
(define_insn ""
[(set (pc) (if_then_else (ne (reg:CCFP 0) (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
- "! TARGET_SOFT_FLOAT"
+ "!TARGET_SOFT_FLOAT"
"*
{
- if (INSN_ANNULLED_BRANCH_P (insn))
- return \"ftest\;add,tr %%r0,%%r0,%%r0\;b,n %0\";
+ int length = get_attr_length (insn);
+ rtx xoperands[1];
+ int nullify, xdelay;
+
+ if (length < 16)
+ return \"ftest\;add,tr %%r0,%%r0,%%r0\;b%* %0\";
+
+ if (dbr_sequence_length () == 0 || INSN_ANNULLED_BRANCH_P (insn))
+ {
+ nullify = 1;
+ xdelay = 0;
+ xoperands[0] = GEN_INT (length - 4);
+ }
else
- return \"ftest\;add,tr %%r0,%%r0,%%r0\;b%* %0\";
+ {
+ nullify = 0;
+ xdelay = 1;
+ xoperands[0] = GEN_INT (length);
+ }
+
+ if (nullify)
+ output_asm_insn (\"ftest\;b,n .+%0\", xoperands);
+ else
+ output_asm_insn (\"ftest\;b .+%0\", xoperands);
+ return output_lbranch (operands[0], insn, xdelay);
}"
- [(set_attr "type" "fbranch")
- (set_attr "length" "12")])
+[(set_attr "type" "fbranch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 12)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))])
;; Move instructions
@@ -7006,11 +7170,10 @@
"*
{
/* An unconditional branch which can reach its target. */
- if (get_attr_length (insn) != 24
- && get_attr_length (insn) != 16)
+ if (get_attr_length (insn) < 16)
return \"b%* %l0\";
- return output_lbranch (operands[0], insn);
+ return output_lbranch (operands[0], insn, 1);
}"
[(set_attr "type" "uncond_branch")
(set_attr "pa_combine_type" "uncond_branch")
@@ -7019,14 +7182,16 @@
(if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 8))))
(const_int 8184))
- (const_int 4)
- (const_int 8))
- (ge (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 4)
+ (const_int 8))
+ (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
(const_int 262100))
- (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 16)
- (const_int 24))]
- (const_int 4)))])
+ (const_int 4)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 20)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 16)]
+ (const_int 24)))])
;;; Hope this is only within a function...
(define_insn "indirect_jump"
@@ -8840,39 +9005,71 @@
(if_then_else (eq_attr "alternative" "0")
;; Loop counter in register case
;; Short branch has length of 4
-;; Long branch has length of 8
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8))
+;; Long branch has length of 8, 20, 24 or 28
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28))
;; Loop counter in FP reg case.
;; Extra goo to deal with additional reload insns.
(if_then_else (eq_attr "alternative" "1")
(if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
- (const_int 8184))
- (const_int 24)
- (const_int 28))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 24)
- (const_int 28)))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
+ (const_int 8184))
+ (const_int 24)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
+ (const_int 262100))
+ (const_int 28)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 44)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 40)]
+ (const_int 48))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 24)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 28)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 44)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 40)]
+ (const_int 48)))
+
;; Loop counter in memory case.
;; Extra goo to deal with additional reload insns.
(if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))))))])
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36))))))])
(define_insn ""
[(set (pc)
@@ -8891,33 +9088,59 @@
(if_then_else (eq_attr "alternative" "0")
;; Loop counter in register case
;; Short branch has length of 4
-;; Long branch has length of 8
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8))
+;; Long branch has length of 8, 20, 24 or 28
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28))
;; Loop counter in FP reg case.
;; Extra goo to deal with additional reload insns.
(if_then_else (eq_attr "alternative" "1")
(if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 12)
- (const_int 16)))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36)))
+
;; Loop counter in memory or sar case.
;; Extra goo to deal with additional reload insns.
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 8)
- (const_int 12)))))])
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 8)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 12)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))))])
;; Handle negated branch.
(define_insn ""
@@ -8938,32 +9161,58 @@
;; Loop counter in register case
;; Short branch has length of 4
;; Long branch has length of 8
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28))
;; Loop counter in FP reg case.
;; Extra goo to deal with additional reload insns.
(if_then_else (eq_attr "alternative" "1")
(if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 12)
- (const_int 16)))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36))
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 12)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 16)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 32)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 28)]
+ (const_int 36)))
+
;; Loop counter in memory or SAR case.
;; Extra goo to deal with additional reload insns.
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 8)
- (const_int 12)))))])
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 8)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 12)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 28)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)]
+ (const_int 32)))))])
(define_insn ""
[(set (pc) (label_ref (match_operand 3 "" "" )))
@@ -8973,14 +9222,21 @@
"(reload_completed && operands[0] == operands[1]) || operands[0] == operands[2]"
"*
{
- return output_parallel_addb (operands, get_attr_length (insn));
+ return output_parallel_addb (operands, insn);
}"
- [(set_attr "type" "parallel_branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+[(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
(define_insn ""
[(set (pc) (label_ref (match_operand 2 "" "" )))
@@ -8989,14 +9245,21 @@
"reload_completed"
"*
{
- return output_parallel_movb (operands, get_attr_length (insn));
+ return output_parallel_movb (operands, insn);
}"
- [(set_attr "type" "parallel_branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+[(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
(define_insn ""
[(set (pc) (label_ref (match_operand 2 "" "" )))
@@ -9005,14 +9268,21 @@
"reload_completed"
"*
{
- return output_parallel_movb (operands, get_attr_length (insn));
+ return output_parallel_movb (operands, insn);
}"
- [(set_attr "type" "parallel_branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+[(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
(define_insn ""
[(set (pc) (label_ref (match_operand 2 "" "" )))
@@ -9021,14 +9291,21 @@
"reload_completed"
"*
{
- return output_parallel_movb (operands, get_attr_length (insn));
+ return output_parallel_movb (operands, insn);
}"
- [(set_attr "type" "parallel_branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+[(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
(define_insn ""
[(set (pc) (label_ref (match_operand 2 "" "" )))
@@ -9037,14 +9314,21 @@
"reload_completed"
"*
{
- return output_parallel_movb (operands, get_attr_length (insn));
+ return output_parallel_movb (operands, insn);
}"
- [(set_attr "type" "parallel_branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8)))])
+[(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
+ (const_int 24)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
(define_insn ""
[(set (match_operand 0 "register_operand" "=f")
Index: config/pa/pa-protos.h
===================================================================
--- config/pa/pa-protos.h (revision 112803)
+++ config/pa/pa-protos.h (working copy)
@@ -42,14 +42,14 @@
extern const char *output_fp_move_double (rtx *);
extern const char *output_block_move (rtx *, int);
extern const char *output_block_clear (rtx *, int);
-extern const char *output_cbranch (rtx *, int, int, int, rtx);
-extern const char *output_lbranch (rtx, rtx);
-extern const char *output_bb (rtx *, int, int, int, rtx, int);
-extern const char *output_bvb (rtx *, int, int, int, rtx, int);
+extern const char *output_cbranch (rtx *, int, rtx);
+extern const char *output_lbranch (rtx, rtx, int);
+extern const char *output_bb (rtx *, int, rtx, int);
+extern const char *output_bvb (rtx *, int, rtx, int);
extern const char *output_dbra (rtx *, rtx, int);
extern const char *output_movb (rtx *, rtx, int, int);
-extern const char *output_parallel_movb (rtx *, int);
-extern const char *output_parallel_addb (rtx *, int);
+extern const char *output_parallel_movb (rtx *, rtx);
+extern const char *output_parallel_addb (rtx *, rtx);
extern const char *output_call (rtx, rtx, int);
extern const char *output_indirect_call (rtx, rtx);
extern const char *output_millicode_call (rtx, rtx);
Index: config/pa/pa.c
===================================================================
--- config/pa/pa.c (revision 112803)
+++ config/pa/pa.c (working copy)
@@ -5962,11 +5962,13 @@
parameters. */
const char *
-output_cbranch (rtx *operands, int nullify, int length, int negated, rtx insn)
+output_cbranch (rtx *operands, int negated, rtx insn)
{
static char buf[100];
int useskip = 0;
- rtx xoperands[5];
+ int nullify = INSN_ANNULLED_BRANCH_P (insn);
+ int length = get_attr_length (insn);
+ int xdelay;
/* A conditional branch to the following instruction (e.g. the delay slot)
is asking for a disaster. This can happen when not optimizing and
@@ -6036,7 +6038,7 @@
with an unfilled delay slot. */
case 8:
/* Handle weird backwards branch with a filled delay slot
- with is nullified. */
+ which is nullified. */
if (dbr_sequence_length () != 0
&& ! forward_branch_p (insn)
&& nullify)
@@ -6083,19 +6085,24 @@
}
break;
- case 20:
- case 28:
- xoperands[0] = operands[0];
- xoperands[1] = operands[1];
- xoperands[2] = operands[2];
- xoperands[3] = operands[3];
-
+ default:
/* The reversed conditional branch must branch over one additional
- instruction if the delay slot is filled. If the delay slot
- is empty, the instruction after the reversed condition branch
- must be nullified. */
- nullify = dbr_sequence_length () == 0;
- xoperands[4] = nullify ? GEN_INT (length) : GEN_INT (length + 4);
+ instruction if the delay slot is filled and needs to be extracted
+ by output_lbranch. If the delay slot is empty or this is a
+ nullified forward branch, the instruction after the reversed
+ condition branch must be nullified. */
+ if (dbr_sequence_length () == 0
+ || (nullify && forward_branch_p (insn)))
+ {
+ nullify = 1;
+ xdelay = 0;
+ operands[4] = GEN_INT (length);
+ }
+ else
+ {
+ xdelay = 1;
+ operands[4] = GEN_INT (length + 4);
+ }
/* Create a reversed conditional branch which branches around
the following insns. */
@@ -6142,27 +6149,38 @@
}
}
- output_asm_insn (buf, xoperands);
- return output_lbranch (operands[0], insn);
-
- default:
- gcc_unreachable ();
+ output_asm_insn (buf, operands);
+ return output_lbranch (operands[0], insn, xdelay);
}
return buf;
}
-/* This routine handles long unconditional branches that exceed the
- maximum range of a simple branch instruction. */
+/* This routine handles output of long unconditional branches that
+ exceed the maximum range of a simple branch instruction. Since
+ we don't have a register available for the branch, we save register
+ %r1 in the frame marker, load the branch destination DEST into %r1,
+ execute the branch, and restore %r1 in the delay slot of the branch.
+ Since long branches may have an insn in the delay slot and the
+ delay slot is used to restore %r1, we in general need to extract
+ this insn and execute it before the branch. However, to facilitate
+ use of this function by conditional branches, we also provide an
+ option to not extract the delay insn so that it will be emitted
+ after the long branch. So, if there is an insn in the delay slot,
+ it is extracted if XDELAY is nonzero.
+
+ The lengths of the various long-branch sequences are 20, 16 and 24
+ bytes for the portable runtime, non-PIC and PIC cases, respectively. */
+
const char *
-output_lbranch (rtx dest, rtx insn)
+output_lbranch (rtx dest, rtx insn, int xdelay)
{
rtx xoperands[2];
xoperands[0] = dest;
/* First, free up the delay slot. */
- if (dbr_sequence_length () != 0)
+ if (xdelay && dbr_sequence_length () != 0)
{
/* We can't handle a jump in the delay slot. */
gcc_assert (GET_CODE (NEXT_INSN (insn)) != JUMP_INSN);
@@ -6272,11 +6290,13 @@
above. it returns the appropriate output template to emit the branch. */
const char *
-output_bb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
- int negated, rtx insn, int which)
+output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{
static char buf[100];
int useskip = 0;
+ int nullify = INSN_ANNULLED_BRANCH_P (insn);
+ int length = get_attr_length (insn);
+ int xdelay;
/* A conditional branch to the following instruction (e.g. the delay slot) is
asking for a disaster. I do not think this can happen as this pattern
@@ -6343,7 +6363,7 @@
with an unfilled delay slot. */
case 8:
/* Handle weird backwards branch with a filled delay slot
- with is nullified. */
+ which is nullified. */
if (dbr_sequence_length () != 0
&& ! forward_branch_p (insn)
&& nullify)
@@ -6385,9 +6405,10 @@
}
else
{
- strcpy (buf, "{extrs,|extrw,s,}");
if (GET_MODE (operands[0]) == DImode)
strcpy (buf, "extrd,s,*");
+ else
+ strcpy (buf, "{extrs,|extrw,s,}");
if ((which == 0 && negated)
|| (which == 1 && ! negated))
strcat (buf, "<");
@@ -6405,7 +6426,40 @@
break;
default:
- gcc_unreachable ();
+ /* The reversed conditional branch must branch over one additional
+ instruction if the delay slot is filled and needs to be extracted
+ by output_lbranch. If the delay slot is empty or this is a
+ nullified forward branch, the instruction after the reversed
+ condition branch must be nullified. */
+ if (dbr_sequence_length () == 0
+ || (nullify && forward_branch_p (insn)))
+ {
+ nullify = 1;
+ xdelay = 0;
+ operands[4] = GEN_INT (length - 8);
+ }
+ else
+ {
+ xdelay = 1;
+ operands[4] = GEN_INT (length - 4);
+ }
+
+ if (GET_MODE (operands[0]) == DImode)
+ strcpy (buf, "extrd,s,*");
+ else
+ strcpy (buf, "{extrs,|extrw,s,}");
+ if ((which == 0 && negated)
+ || (which == 1 && !negated))
+ strcat (buf, ">= %0,%1,1,%%r0\n\t");
+ else
+ strcat (buf, "< %0,%1,1,%%r0\n\t");
+ if (nullify)
+ strcat (buf, "b,n .+%4");
+ else
+ strcat (buf, "b .+%4");
+ output_asm_insn (buf, operands);
+ return output_lbranch (negated ? operands[3] : operands[2],
+ insn, xdelay);
}
return buf;
}
@@ -6417,11 +6471,13 @@
branch. */
const char *
-output_bvb (rtx *operands ATTRIBUTE_UNUSED, int nullify, int length,
- int negated, rtx insn, int which)
+output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{
static char buf[100];
int useskip = 0;
+ int nullify = INSN_ANNULLED_BRANCH_P (insn);
+ int length = get_attr_length (insn);
+ int xdelay;
/* A conditional branch to the following instruction (e.g. the delay slot) is
asking for a disaster. I do not think this can happen as this pattern
@@ -6488,7 +6544,7 @@
with an unfilled delay slot. */
case 8:
/* Handle weird backwards branch with a filled delay slot
- with is nullified. */
+ which is nullified. */
if (dbr_sequence_length () != 0
&& ! forward_branch_p (insn)
&& nullify)
@@ -6550,7 +6606,40 @@
break;
default:
- gcc_unreachable ();
+ /* The reversed conditional branch must branch over one additional
+ instruction if the delay slot is filled and needs to be extracted
+ by output_lbranch. If the delay slot is empty or this is a
+ nullified forward branch, the instruction after the reversed
+ condition branch must be nullified. */
+ if (dbr_sequence_length () == 0
+ || (nullify && forward_branch_p (insn)))
+ {
+ nullify = 1;
+ xdelay = 0;
+ operands[4] = GEN_INT (length - 8);
+ }
+ else
+ {
+ xdelay = 1;
+ operands[4] = GEN_INT (length - 4);
+ }
+
+ if (GET_MODE (operands[0]) == DImode)
+ strcpy (buf, "extrd,s,*");
+ else
+ strcpy (buf, "{extrs,|extrw,s,}");
+ if ((which == 0 && negated)
+ || (which == 1 && !negated))
+ strcat (buf, ">= {%0,%1,1,%%r0|%0,%%sar,1,%%r0}\n\t");
+ else
+ strcat (buf, "< {%0,%1,1,%%r0|%0,%%sar,1,%%r0}\n\t");
+ if (nullify)
+ strcat (buf, "b,n .+%4");
+ else
+ strcat (buf, "b .+%4");
+ output_asm_insn (buf, operands);
+ return output_lbranch (negated ? operands[3] : operands[2],
+ insn, xdelay);
}
return buf;
}
@@ -6562,6 +6651,7 @@
const char *
output_dbra (rtx *operands, rtx insn, int which_alternative)
{
+ int length = get_attr_length (insn);
/* A conditional branch to the following instruction (e.g. the delay slot) is
asking for a disaster. Be prepared! */
@@ -6587,7 +6677,7 @@
if (which_alternative == 0)
{
int nullify = INSN_ANNULLED_BRANCH_P (insn);
- int length = get_attr_length (insn);
+ int xdelay;
/* If this is a long branch with its delay slot unfilled, set `nullify'
as it can nullify the delay slot and save a nop. */
@@ -6631,7 +6721,30 @@
return "addi,%N2 %1,%0,%0\n\tb %3";
default:
- gcc_unreachable ();
+ /* The reversed conditional branch must branch over one additional
+ instruction if the delay slot is filled and needs to be extracted
+ by output_lbranch. If the delay slot is empty or this is a
+ nullified forward branch, the instruction after the reversed
+ condition branch must be nullified. */
+ if (dbr_sequence_length () == 0
+ || (nullify && forward_branch_p (insn)))
+ {
+ nullify = 1;
+ xdelay = 0;
+ operands[4] = GEN_INT (length);
+ }
+ else
+ {
+ xdelay = 1;
+ operands[4] = GEN_INT (length + 4);
+ }
+
+ if (nullify)
+ output_asm_insn ("addib,%N2,n %1,%0,.+%4", operands);
+ else
+ output_asm_insn ("addib,%N2 %1,%0,.+%4", operands);
+
+ return output_lbranch (operands[3], insn, xdelay);
}
}
@@ -6644,10 +6757,17 @@
output_asm_insn ("{fstws|fstw} %0,-16(%%r30)\n\tldw -16(%%r30),%4",
operands);
output_asm_insn ("ldo %1(%4),%4\n\tstw %4,-16(%%r30)", operands);
- if (get_attr_length (insn) == 24)
+ if (length == 24)
return "{comb|cmpb},%S2 %%r0,%4,%3\n\t{fldws|fldw} -16(%%r30),%0";
+ else if (length == 28)
+ return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
else
- return "{comclr|cmpclr},%B2 %%r0,%4,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
+ {
+ operands[4] = GEN_INT (length - 24);
+ output_asm_insn ("addib,%N2 %1,%0,.+%4", operands);
+ output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
+ return output_lbranch (operands[3], insn, 0);
+ }
}
/* Deal with gross reload from memory case. */
else
@@ -6655,14 +6775,20 @@
/* Reload loop counter from memory, the store back to memory
happens in the branch's delay slot. */
output_asm_insn ("ldw %0,%4", operands);
- if (get_attr_length (insn) == 12)
+ if (length == 12)
return "addib,%C2 %1,%4,%3\n\tstw %4,%0";
+ else if (length == 16)
+ return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
else
- return "addi,%N2 %1,%4,%4\n\tb %3\n\tstw %4,%0";
+ {
+ operands[5] = GEN_INT (length - 12);
+ output_asm_insn ("addib,%N2 %1,%0,.+%5\n\tstw %4,%0", operands);
+ return output_lbranch (operands[3], insn, 0);
+ }
}
}
-/* Return the output template for emitting a dbra type insn.
+/* Return the output template for emitting a movb type insn.
Note it may perform some output operations on its own before
returning the final output string. */
@@ -6670,6 +6796,7 @@
output_movb (rtx *operands, rtx insn, int which_alternative,
int reverse_comparison)
{
+ int length = get_attr_length (insn);
/* A conditional branch to the following instruction (e.g. the delay slot) is
asking for a disaster. Be prepared! */
@@ -6696,7 +6823,7 @@
if (which_alternative == 0)
{
int nullify = INSN_ANNULLED_BRANCH_P (insn);
- int length = get_attr_length (insn);
+ int xdelay;
/* If this is a long branch with its delay slot unfilled, set `nullify'
as it can nullify the delay slot and save a nop. */
@@ -6740,38 +6867,80 @@
return "or,%N2 %1,%%r0,%0\n\tb %3";
default:
- gcc_unreachable ();
+ /* The reversed conditional branch must branch over one additional
+ instruction if the delay slot is filled and needs to be extracted
+ by output_lbranch. If the delay slot is empty or this is a
+ nullified forward branch, the instruction after the reversed
+ condition branch must be nullified. */
+ if (dbr_sequence_length () == 0
+ || (nullify && forward_branch_p (insn)))
+ {
+ nullify = 1;
+ xdelay = 0;
+ operands[4] = GEN_INT (length);
+ }
+ else
+ {
+ xdelay = 1;
+ operands[4] = GEN_INT (length + 4);
+ }
+
+ if (nullify)
+ output_asm_insn ("movb,%N2,n %1,%0,.+%4", operands);
+ else
+ output_asm_insn ("movb,%N2 %1,%0,.+%4", operands);
+
+ return output_lbranch (operands[3], insn, xdelay);
}
}
- /* Deal with gross reload from FP register case. */
+ /* Deal with gross reload for FP destination register case. */
else if (which_alternative == 1)
{
- /* Move loop counter from FP register to MEM then into a GR,
- increment the GR, store the GR into MEM, and finally reload
- the FP register from MEM from within the branch's delay slot. */
+ /* Move source register to MEM, perform the branch test, then
+ finally load the FP register from MEM from within the branch's
+ delay slot. */
output_asm_insn ("stw %1,-16(%%r30)", operands);
- if (get_attr_length (insn) == 12)
+ if (length == 12)
return "{comb|cmpb},%S2 %%r0,%1,%3\n\t{fldws|fldw} -16(%%r30),%0";
+ else if (length == 16)
+ return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
else
- return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\t{fldws|fldw} -16(%%r30),%0";
+ {
+ operands[4] = GEN_INT (length - 12);
+ output_asm_insn ("movb,%N2 %1,%0,.+%4", operands);
+ output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
+ return output_lbranch (operands[3], insn, 0);
+ }
}
/* Deal with gross reload from memory case. */
else if (which_alternative == 2)
{
/* Reload loop counter from memory, the store back to memory
happens in the branch's delay slot. */
- if (get_attr_length (insn) == 8)
+ if (length == 8)
return "{comb|cmpb},%S2 %%r0,%1,%3\n\tstw %1,%0";
+ else if (length == 12)
+ return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
else
- return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tstw %1,%0";
+ {
+ operands[4] = GEN_INT (length - 8);
+ output_asm_insn ("movb,%N2 %1,%0,.+%4\n\tstw %1,%0", operands);
+ return output_lbranch (operands[3], insn, 0);
+ }
}
/* Handle SAR as a destination. */
else
{
- if (get_attr_length (insn) == 8)
+ if (length == 8)
return "{comb|cmpb},%S2 %%r0,%1,%3\n\tmtsar %r1";
+ else if (length == 12)
+ return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tmtsar %r1";
else
- return "{comclr|cmpclr},%B2 %%r0,%1,%%r0\n\tb %3\n\tmtsar %r1";
+ {
+ operands[4] = GEN_INT (length - 8);
+ output_asm_insn ("movb,%N2 %1,%0,.+%4\n\tmtsar %r1", operands);
+ return output_lbranch (operands[3], insn, 0);
+ }
}
}
@@ -8241,37 +8410,50 @@
/* Output an unconditional move and branch insn. */
const char *
-output_parallel_movb (rtx *operands, int length)
+output_parallel_movb (rtx *operands, rtx insn)
{
+ int length = get_attr_length (insn);
+
/* These are the cases in which we win. */
if (length == 4)
return "mov%I1b,tr %1,%0,%2";
- /* None of these cases wins, but they don't lose either. */
- if (dbr_sequence_length () == 0)
+ /* None of the following cases win, but they don't lose either. */
+ if (length == 8)
{
- /* Nothing in the delay slot, fake it by putting the combined
- insn (the copy or add) in the delay slot of a bl. */
- if (GET_CODE (operands[1]) == CONST_INT)
- return "b %2\n\tldi %1,%0";
+ if (dbr_sequence_length () == 0)
+ {
+ /* Nothing in the delay slot, fake it by putting the combined
+ insn (the copy or add) in the delay slot of a bl. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return "b %2\n\tldi %1,%0";
+ else
+ return "b %2\n\tcopy %1,%0";
+ }
else
- return "b %2\n\tcopy %1,%0";
+ {
+ /* Something in the delay slot, but we've got a long branch. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return "ldi %1,%0\n\tb %2";
+ else
+ return "copy %1,%0\n\tb %2";
+ }
}
+
+ if (GET_CODE (operands[1]) == CONST_INT)
+ output_asm_insn ("ldi %1,%0", operands);
else
- {
- /* Something in the delay slot, but we've got a long branch. */
- if (GET_CODE (operands[1]) == CONST_INT)
- return "ldi %1,%0\n\tb %2";
- else
- return "copy %1,%0\n\tb %2";
- }
+ output_asm_insn ("copy %1,%0", operands);
+ return output_lbranch (operands[2], insn, 1);
}
/* Output an unconditional add and branch insn. */
const char *
-output_parallel_addb (rtx *operands, int length)
+output_parallel_addb (rtx *operands, rtx insn)
{
+ int length = get_attr_length (insn);
+
/* To make life easy we want operand0 to be the shared input/output
operand and operand1 to be the readonly operand. */
if (operands[0] == operands[1])
@@ -8281,18 +8463,20 @@
if (length == 4)
return "add%I1b,tr %1,%0,%3";
- /* None of these cases win, but they don't lose either. */
- if (dbr_sequence_length () == 0)
+ /* None of the following cases win, but they don't lose either. */
+ if (length == 8)
{
- /* Nothing in the delay slot, fake it by putting the combined
- insn (the copy or add) in the delay slot of a bl. */
- return "b %3\n\tadd%I1 %1,%0,%0";
+ if (dbr_sequence_length () == 0)
+ /* Nothing in the delay slot, fake it by putting the combined
+ insn (the copy or add) in the delay slot of a bl. */
+ return "b %3\n\tadd%I1 %1,%0,%0";
+ else
+ /* Something in the delay slot, but we've got a long branch. */
+ return "add%I1 %1,%0,%0\n\tb %3";
}
- else
- {
- /* Something in the delay slot, but we've got a long branch. */
- return "add%I1 %1,%0,%0\n\tb %3";
- }
+
+ output_asm_insn ("add%I1 %1,%0,%0", operands);
+ return output_lbranch (operands[3], insn, 1);
}
/* Return nonzero if INSN (a jump insn) immediately follows a call