OSDN Git Service

entered into RCS
authormycroft <mycroft@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Jan 1992 13:17:00 +0000 (13:17 +0000)
committermycroft <mycroft@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 15 Jan 1992 13:17:00 +0000 (13:17 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/convex/convex.c [new file with mode: 0644]

diff --git a/gcc/config/convex/convex.c b/gcc/config/convex/convex.c
new file mode 100644 (file)
index 0000000..9f49115
--- /dev/null
@@ -0,0 +1,220 @@
+/* Subroutines for insn-output.c for Convex.
+   Copyright (C) 1989,1991 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "config.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+
+/* Boolean to keep track of whether the current section is .text or not.
+   Used by .align handler in convex.h. */
+
+int current_section_is_text;
+
+/* set_cmp saves the operands of a "cmp" insn, along with the type character
+ * to be used in the compare instruction.
+ *
+ * gen_cmp finds out what comparison is to be performed and outputs the
+ * necessary instructions, e.g.
+ *    "eq.w a1,a2\;jbra.t L5"
+ * for (cmpsi a1 a2) (beq L5)  */
+static rtx xop0, xop1;
+static char typech, regch;
+
+char *
+set_cmp (op0, op1, typechr)
+     rtx op0, op1;
+     char typechr;
+{
+  xop0 = op0;
+  xop1 = op1;
+  typech = typechr;
+  if (GET_CODE (op0) == REG)
+    regch = A_REGNO_P (REGNO (op0)) ? 'a' : 's';
+  else if (GET_CODE (op1) == REG)
+    regch = A_REGNO_P (REGNO (op1)) ? 'a' : 's';
+  else abort ();
+  return "";
+}
+
+char *
+gen_cmp (label, cmpop, tf)
+     rtx label;
+     char *cmpop;
+     char tf;
+{
+  char buf[80];
+  char revop[4];
+  rtx ops[3];
+
+  ops[2] = label;
+
+  /* Constant must be first; swap operands if necessary.
+     If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
+     and reverse the sense of the jump. */
+
+  if (CONSTANT_P (xop1))
+    {
+      ops[0] = xop1;
+      ops[1] = xop0;
+      if (cmpop[0] == 'l')
+       {
+         bcopy (cmpop, revop, sizeof revop);
+         revop[1] ^= 'e' ^ 't';
+         tf ^= 't' ^ 'f';
+         cmpop = revop;
+       }
+    }
+  else
+    {
+      ops[0] = xop0;
+      ops[1] = xop1;
+    }
+
+  sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);
+  output_asm_insn (buf, ops);
+  return "";
+}
+\f
+/* Routines to separate CONST_DOUBLEs into component parts. */
+
+int
+const_double_high_int (x)
+     rtx x;
+{
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+    return CONST_DOUBLE_LOW (x);
+  else
+    return CONST_DOUBLE_HIGH (x);
+}
+
+int
+const_double_low_int (x)
+     rtx x;
+{
+  if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+    return CONST_DOUBLE_HIGH (x);
+  else
+    return CONST_DOUBLE_LOW (x);
+}
+\f
+/* Return the number of args in the call insn X. */
+
+static int
+call_num_args (x)
+     rtx x;
+{
+  if (GET_CODE (x) == CALL)
+    return INTVAL (x->fld[1].rtx);
+  if (GET_CODE (x) == SET)
+    return call_num_args (SET_SRC (x));
+  abort ();
+}
+
+/* Scan forward from a call to decide whether we need to reload AP
+   from 12(FP) after it.  We need to if there can be a reference to
+   arg_pointer_rtx before the next call, which will clobber AP.
+   Look forward in the instruction list until encountering a call
+   (don't need the load), or a reference to AP (do need it), or
+   a jump (don't know, do the load).  */
+
+static int
+ap_reload_needed (insn)
+     rtx insn;
+{
+  for (;;)
+    {
+      insn = NEXT_INSN (insn);
+      switch (GET_CODE (insn))
+       {
+       case JUMP_INSN:
+         /* Basic block ends.  If return, no AP needed, else assume it is. */
+         return GET_CODE (PATTERN (insn)) != RETURN;
+       case CALL_INSN:
+         /* A subsequent call.  AP isn't needed unless the call itself
+            requires it.  But zero-arg calls don't clobber AP, so
+            don't terminate the search in that case. */
+         if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
+           return 1;
+         if (! TARGET_ARGCOUNT && call_num_args (PATTERN (insn)) == 0)
+           break;
+         return 0;
+       case BARRIER:
+         /* Barrier, don't need AP. */
+         return 0;
+       case INSN:
+         /* Other insn may need AP; if not, keep looking. */
+         if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
+           return 1;
+       }
+    }
+}
+
+/* Output the insns needed to do a call. */
+
+char *
+output_call (insn, address, argcount)
+    rtx insn, address, argcount;
+{
+  int set_ap = TARGET_ARGCOUNT || argcount != const0_rtx;
+
+  /* If AP is used by the call address, evaluate the address into a temp. */
+  if (reg_mentioned_p (arg_pointer_rtx, address))
+    if (set_ap)
+      {
+       address = XEXP (address, 0);
+       output_asm_insn ("ld.w %0,a1", &address);
+       address = gen_rtx (MEM, QImode, gen_rtx (REG, Pmode, 9));
+      }
+
+  /* If there are args, point AP to them. */
+  if (set_ap)
+    output_asm_insn ("mov sp,ap");
+
+  /* If we are passing an arg count, convert it to words and push it. */
+  if (TARGET_ARGCOUNT)
+    {
+      argcount = gen_rtx (CONST_INT, VOIDmode, (INTVAL (argcount) + 3) / 4);
+      output_asm_insn ("pshea %a0", &argcount);
+    }
+
+  /* The call. */
+  output_asm_insn ("calls %0", &address);
+
+  /* If we clobbered AP, reload it if it is live. */
+  if (set_ap)
+    if (ap_reload_needed (insn))
+      output_asm_insn ("ld.w 12(fp),ap");
+
+  /* If we pushed an arg count, pop it and the args. */
+  if (TARGET_ARGCOUNT)
+    {
+      argcount = gen_rtx (CONST_INT, VOIDmode, INTVAL (argcount) * 4 + 4);
+      output_asm_insn ("add.w %0,sp", &argcount);
+    }
+  
+  return "";
+}