aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1993-03-31 01:48:22 -0700
committerJeff Law <law@gcc.gnu.org>1993-03-31 01:48:22 -0700
commitd2364a742a2165a1e5ee329d2316d765c67c600b (patch)
treec1192a9b735d7f2555c2f2db1851f50718259657
parent0cf4720c583685a57ce812caf0d92b8dd487e3e4 (diff)
downloadgcc-d2364a742a2165a1e5ee329d2316d765c67c600b.zip
gcc-d2364a742a2165a1e5ee329d2316d765c67c600b.tar.gz
gcc-d2364a742a2165a1e5ee329d2316d765c67c600b.tar.bz2
pa.c (output_cbranch): New function.
* pa.c (output_cbranch): New function. Given the operands of the branch, possible nullification, length of the branch, possible branch negation, and the branch insn itself, return the output template for the desired conditional branch. (output_bb): Likewise, but for branch on bit. From-SVN: r3949
-rw-r--r--gcc/config/pa/pa.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 0401201..14142ec7 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -2913,6 +2913,175 @@ hppa_builtin_saveregs (arglist)
offset, 0, 0, OPTAB_LIB_WIDEN));
}
+/* This routine handles all the normal conditional branch sequences we
+ might need to generate. It handles compare immediate vs compare
+ register, nullification of delay slots, varying length branches,
+ negated branches, and all combinations of the above. It returns the
+ output appropriate to emit the branch corresponding to all given
+ parameters. */
+
+char *
+output_cbranch (operands, nullify, length, negated, insn)
+ rtx *operands;
+ int nullify, length, negated;
+ rtx insn;
+{
+ static char buf[100];
+ int useskip = 0;
+
+ /* A forward branch over a single nullified insn can be done with a
+ comclr instruction. This avoids a single cycle penalty due to
+ mis-predicted branch if we fall through (branch not taken). */
+
+ if (length == 1
+ && JUMP_LABEL (insn) == next_nonnote_insn (NEXT_INSN (insn))
+ && nullify)
+ useskip = 1;
+
+ switch (length)
+ {
+
+ /* Short conditional branch. May nullify either direction. */
+ case 1:
+ if (useskip)
+ strcpy (buf, "com%I2clr,");
+ else
+ strcpy (buf, "com%I2b,");
+ if (negated)
+ strcat (buf, "%B3");
+ else
+ strcat (buf, "%S3");
+ if (useskip)
+ strcat (buf, " %2,%1,0");
+ else if (nullify)
+ strcat (buf, ",n %2,%1,%0");
+ else
+ strcat (buf, " %2,%1,%0%#");
+ break;
+
+ /* Long conditional branch, possible forward nullification. Also
+ note all conditional branches have a length of 4 when not
+ optimizing! */
+ case 2:
+ case 4:
+ strcpy (buf, "com%I2clr,");
+ if (negated)
+ strcat (buf, "%S3");
+ else
+ strcat (buf, "%B3");
+ if (nullify)
+ strcat (buf, " %2,%1,0\n\tbl,n %0,0");
+ else
+ strcat (buf, " %2,%1,0\n\tbl %0,0%#");
+ break;
+
+ /* Long backward conditional branch with nullification. */
+ case 3:
+ strcpy (buf, "com%I2b,");
+ if (negated)
+ strcat (buf, "%S3");
+ else
+ strcat (buf, "%B3");
+ strcat (buf, " %2,%1,.+16\n\tnop\n\t bl %0,0");
+ break;
+
+ default:
+ abort();
+ }
+ return buf;
+}
+
+/* This routine handles all the branch-on-bit conditional branch sequences we
+ might need to generate. It handles nullification of delay slots,
+ varying length branches, negated branches and all combinations of the
+ above. it returns the appropriate output template to emit the branch. */
+
+char *
+output_bb (operands, nullify, length, negated, insn, which)
+ rtx *operands;
+ int nullify, length, negated;
+ rtx insn;
+ int which;
+{
+ static char buf[100];
+ int useskip = 0;
+
+ /* A forward branch over a single nullified insn can be done with a
+ extrs instruction. This avoids a single cycle penalty due to
+ mis-predicted branch if we fall through (branch not taken). */
+
+ if (length == 1
+ && JUMP_LABEL (insn) == next_nonnote_insn (NEXT_INSN (insn))
+ && nullify)
+ useskip = 1;
+
+ switch (length)
+ {
+
+ /* Short conditional branch. May nullify either direction. */
+ case 1:
+ if (useskip)
+ strcpy (buf, "extrs,");
+ else
+ strcpy (buf, "bb,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, ">=");
+ else
+ strcat (buf, "<");
+ if (useskip)
+ strcat (buf, " %0,%1,1,0");
+ else if (nullify && negated)
+ strcat (buf, ",n %0,%1,%3");
+ else if (nullify && ! negated)
+ strcat (buf, ",n %0,%1,%2");
+ else if (! nullify && negated)
+ strcat (buf, "%0,%1,%3%#");
+ else if (! nullify && ! negated)
+ strcat (buf, " %0,%1,%2%#");
+ break;
+
+ /* Long conditional branch, possible forward nullification. Also
+ note all conditional branches have a length of 4 when not
+ optimizing! */
+ case 2:
+ case 4:
+ strcpy (buf, "extrs,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, "<");
+ else
+ strcat (buf, ">=");
+ if (nullify && negated)
+ strcat (buf, " %0,%1,1,0\n\tbl,n %3,0");
+ else if (nullify && ! negated)
+ strcat (buf, " %0,%1,1,0\n\tbl,n %2,0");
+ else if (! nullify && negated)
+ strcat (buf, " %0,%1,1,0\n\tbl %3,0%#");
+ else if (! nullify && ! negated)
+ strcat (buf, " %0,%1,1,0\n\tbl %2,0%#");
+ break;
+
+ /* Long backward conditional branch with nullification. */
+ case 3:
+ strcpy (buf, "bb,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, "<");
+ else
+ strcat (buf, ">=");
+ if (negated)
+ strcat (buf, " %0,%1,.+16\n\tnop\n\t bl %3,0");
+ else
+ strcat (buf, " %0,%1,.+16\n\tnop\n\t bl %2,0");
+ break;
+
+ default:
+ abort();
+ }
+ return buf;
+}
+
extern struct obstack *saveable_obstack;
/* In HPUX 8.0's shared library scheme, special relocations are needed