* alpha/osf.h (TARGET_HAS_XFLOATING_LIBS): Define.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Jan 2000 04:02:40 +0000 (04:02 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 Jan 2000 04:02:40 +0000 (04:02 +0000)
        * alpha/osf5.h: New file.
        * configure.in (alpha-*-osf5): Add it to tm_file.

        * emit-rtl.c (operand_subword): Support TFmode on a 64-bit target.

        * alpha-protos.h (alpha_emit_xfloating_arith): Declare.
        (alpha_emit_xfloating_cvt, function_arg): Declare.
        * alpha.c (alpha_emit_conditional_branch): Call
        alpha_emit_xfloating_compare for TFmode compares.
        (alpha_lookup_xfloating_lib_func): New.
        (alpha_compute_xfloating_mode_arg): New.
        (alpha_emit_xfloating_libcall): New.
        (alpha_emit_xfloating_arith): New.
        (alpha_emit_xfloating_compare): New.
        (alpha_emit_xfloating_cvt): New.
        (print_operand): Add default abort case.
        (function_arg): Mind FUNCTION_ARG_PASS_BY_REFERENCE.
        * alpha.h (TARGET_HAS_XFLOATING_LIBS): New.
        (BIGGEST_ALIGNMENT): Increase to 128 bits.
        (RETURN_IN_MEMORY): True for TF/TCmode.
        (ALPHA_ARG_SIZE): TF/TCmode is passed indirect.
        (FUNCTION_ARG): Move to function_arg.
        (FUNCTION_ARG_PASS_BY_REFERENCE): New.
        (ASM_OUTPUT_LONG_DOUBLE): New.
        (ASM_OUTPUT_DOUBLE): Always output bits.
        * alpha.md (addtf3, divtf3, multf3, subtf3, cmptf): New.
        (fix_trunctfdi2, floatditf2, floatunsditf2): New.
        (extenddftf2, trunctfdf2): New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31579 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/osf.h
gcc/config/alpha/osf5.h [new file with mode: 0644]
gcc/configure
gcc/configure.in
gcc/emit-rtl.c

index ee7112c..1d5a61f 100644 (file)
@@ -1,3 +1,35 @@
+2000-01-23  Richard Henderson  <rth@cygnus.com>
+
+       * alpha/osf.h (TARGET_HAS_XFLOATING_LIBS): Define.
+       * alpha/osf5.h: New file.
+       * configure.in (alpha-*-osf5): Add it to tm_file.
+
+       * emit-rtl.c (operand_subword): Support TFmode on a 64-bit target.
+
+       * alpha-protos.h (alpha_emit_xfloating_arith): Declare.
+       (alpha_emit_xfloating_cvt, function_arg): Declare.
+       * alpha.c (alpha_emit_conditional_branch): Call
+       alpha_emit_xfloating_compare for TFmode compares.
+       (alpha_lookup_xfloating_lib_func): New.
+       (alpha_compute_xfloating_mode_arg): New.
+       (alpha_emit_xfloating_libcall): New.
+       (alpha_emit_xfloating_arith): New.
+       (alpha_emit_xfloating_compare): New.
+       (alpha_emit_xfloating_cvt): New.
+       (print_operand): Add default abort case.
+       (function_arg): Mind FUNCTION_ARG_PASS_BY_REFERENCE.
+       * alpha.h (TARGET_HAS_XFLOATING_LIBS): New.
+       (BIGGEST_ALIGNMENT): Increase to 128 bits.
+       (RETURN_IN_MEMORY): True for TF/TCmode.
+       (ALPHA_ARG_SIZE): TF/TCmode is passed indirect.
+       (FUNCTION_ARG): Move to function_arg.
+       (FUNCTION_ARG_PASS_BY_REFERENCE): New.
+       (ASM_OUTPUT_LONG_DOUBLE): New.
+       (ASM_OUTPUT_DOUBLE): Always output bits.
+       * alpha.md (addtf3, divtf3, multf3, subtf3, cmptf): New.
+       (fix_trunctfdi2, floatditf2, floatunsditf2): New.
+       (extenddftf2, trunctfdf2): New.
+
 2000-01-23  Alexandre Oliva  <oliva@lsd.ic.unicamp.br>
 
        * config/sparc/sol2-sld-64.h (TRANSFER_FROM_TRAMPOLINE): Moved...
index e9e88bc..c29063e 100644 (file)
@@ -80,6 +80,8 @@ extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
                                             HOST_WIDE_INT));
 extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
 extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode));
+extern void alpha_emit_xfloating_arith PARAMS ((enum rtx_code, rtx[]));
+extern void alpha_emit_xfloating_cvt PARAMS ((enum rtx_code, rtx[]));
 extern void alpha_expand_unaligned_load PARAMS ((rtx, rtx, HOST_WIDE_INT,
                                                HOST_WIDE_INT, int));
 extern void alpha_expand_unaligned_store PARAMS ((rtx, rtx, HOST_WIDE_INT,
@@ -114,6 +116,8 @@ extern tree alpha_build_va_list PARAMS ((void));
 #ifdef RTX_CODE
 extern void alpha_va_start PARAMS ((int, tree, rtx));
 extern rtx alpha_va_arg PARAMS ((tree, tree));
+extern rtx function_arg PARAMS ((CUMULATIVE_ARGS, enum machine_mode,
+                                tree, int));
 #endif
 extern int vms_valid_decl_attribute_p PARAMS ((tree, tree, tree, tree));
 extern void alpha_start_function PARAMS ((FILE *, const char *, tree));
index 1ea9874..9492774 100644 (file)
@@ -114,9 +114,18 @@ static void alpha_init_machine_status
   PARAMS ((struct function *p));
 static void alpha_mark_machine_status
   PARAMS ((struct function *p));
-static int alpha_ra_ever_killed PARAMS ((void));
-static rtx set_frame_related_p PARAMS ((void));
-
+static int alpha_ra_ever_killed
+  PARAMS ((void));
+static rtx set_frame_related_p
+  PARAMS ((void));
+static const char *alpha_lookup_xfloating_lib_func
+  PARAMS ((enum rtx_code));
+static int alpha_compute_xfloating_mode_arg
+  PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode));
+static void alpha_emit_xfloating_libcall
+  PARAMS ((const char *, rtx, rtx[], int, rtx));
+static rtx alpha_emit_xfloating_compare
+  PARAMS ((enum rtx_code, rtx, rtx));
 
 /* Get the number of args of a function in one of two ways.  */
 #ifdef OPEN_VMS
@@ -1453,6 +1462,23 @@ alpha_emit_conditional_branch (code)
   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
   rtx tem;
 
+  if (alpha_compare.fp_p && GET_MODE (op0) == TFmode)
+    {
+      if (! TARGET_HAS_XFLOATING_LIBS)
+       abort ();
+
+      /* X_floating library comparison functions return
+          -1  unordered
+           0  false
+           1  true
+        Convert the compare against the raw return value.  */
+
+      op0 = alpha_emit_xfloating_compare (code, op0, op1);
+      op1 = const0_rtx;
+      alpha_compare.fp_p = 0;
+      code = GT;
+    }
+
   /* The general case: fold the comparison code to the types of compares
      that we have, choosing the branch as necessary.  */
   switch (code)
@@ -1680,6 +1706,286 @@ alpha_emit_conditional_move (cmp, mode)
   return gen_rtx_fmt_ee (cmov_code, cmov_mode, tem, CONST0_RTX (cmp_op_mode));
 }
 \f
+/* Look up the function X_floating library function name for the
+   given operation.  */
+
+static const char *
+alpha_lookup_xfloating_lib_func (code)
+     enum rtx_code code;
+{
+  struct xfloating_op
+    {
+      enum rtx_code code;
+      const char *func;
+    };
+
+  static const struct xfloating_op vms_xfloating_ops[] = 
+    {
+      { PLUS,          "OTS$ADD_X" },
+      { MINUS,         "OTS$SUB_X" },
+      { MULT,          "OTS$MUL_X" },
+      { DIV,           "OTS$DIV_X" },
+      { EQ,            "OTS$EQL_X" },
+      { NE,            "OTS$NEQ_X" },
+      { LT,            "OTS$LSS_X" },
+      { LE,            "OTS$LEQ_X" },
+      { GT,            "OTS$GTR_X" },
+      { GE,            "OTS$GEQ_X" },
+      { FIX,           "OTS$CVTXQ" },
+      { FLOAT,         "OTS$CVTQX" },
+      { UNSIGNED_FLOAT,        "OTS$CVTQUX" },
+      { FLOAT_EXTEND,  "OTS$CVT_FLOAT_T_X" },
+      { FLOAT_TRUNCATE,        "OTS$CVT_FLOAT_X_T" },
+    };
+
+  static const struct xfloating_op osf_xfloating_ops[] = 
+    {
+      { PLUS,          "_OtsAddX" },
+      { MINUS,         "_OtsSubX" },
+      { MULT,          "_OtsMulX" },
+      { DIV,           "_OtsDivX" },
+      { EQ,            "_OtsEqlX" },
+      { NE,            "_OtsNeqX" },
+      { LT,            "_OtsLssX" },
+      { LE,            "_OtsLeqX" },
+      { GT,            "_OtsGtrX" },
+      { GE,            "_OtsGeqX" },
+      { FIX,           "_OtsCvtXQ" },
+      { FLOAT,         "_OtsCvtQX" },
+      { UNSIGNED_FLOAT,        "_OtsCvtQUX" },
+      { FLOAT_EXTEND,  "_OtsConvertFloatTX" },
+      { FLOAT_TRUNCATE,        "_OtsConvertFloatXT" },
+    };
+
+  const struct xfloating_op *ops;
+  const long n = sizeof(osf_xfloating_ops) / sizeof(osf_xfloating_ops[0]);
+  long i;
+
+  /* How irritating.  Nothing to key off for the table.  Hardcode
+     knowledge of the G_floating routines.  */
+  if (TARGET_FLOAT_VAX)
+    {
+      if (TARGET_OPEN_VMS)
+       {
+         if (code == FLOAT_EXTEND)
+           return "OTS$CVT_FLOAT_G_X";
+         if (code == FLOAT_TRUNCATE)
+           return "OTS$CVT_FLOAT_X_G";
+       }
+      else
+       {
+         if (code == FLOAT_EXTEND)
+           return "_OtsConvertFloatGX";
+         if (code == FLOAT_TRUNCATE)
+           return "_OtsConvertFloatXG";
+       }
+    }
+
+  if (TARGET_OPEN_VMS)
+    ops = vms_xfloating_ops;
+  else
+    ops = osf_xfloating_ops;
+
+  for (i = 0; i < n; ++i)
+    if (ops[i].code == code)
+      return ops[i].func;
+
+  abort();
+}
+
+/* Most X_floating operations take the rounding mode as an argument.
+   Compute that here.  */
+
+static int
+alpha_compute_xfloating_mode_arg (code, round)
+     enum rtx_code code;
+     enum alpha_fp_rounding_mode round;
+{
+  int mode;
+
+  switch (round)
+    {
+    case ALPHA_FPRM_NORM:
+      mode = 2;
+      break;
+    case ALPHA_FPRM_MINF:
+      mode = 1;
+      break;
+    case ALPHA_FPRM_CHOP:
+      mode = 0;
+      break;
+    case ALPHA_FPRM_DYN:
+      mode = 4;
+      break;
+    default:
+      abort ();
+
+    /* XXX For reference, round to +inf is mode = 3.  */
+    }
+
+  if (code == FLOAT_TRUNCATE && alpha_fptm == ALPHA_FPTM_N)
+    mode |= 0x10000;
+
+  return mode;
+}
+
+/* Emit an X_floating library function call.
+
+   Note that these functions do not follow normal calling conventions:
+   TFmode arguments are passed in two integer registers (as opposed to
+   indirect); TFmode return values appear in R16+R17. 
+
+   FUNC is the function name to call.
+   TARGET is where the output belongs.
+   OPERANDS are the inputs.
+   NOPERANDS is the count of inputs.
+   EQUIV is the expression equivalent for the function.
+*/
+
+static void
+alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv)
+     const char *func;
+     rtx target;
+     rtx operands[];
+     int noperands;
+     rtx equiv;
+{
+  rtx usage = NULL_RTX, tmp, reg;
+  int regno = 16, i;
+
+  start_sequence ();
+
+  for (i = 0; i < noperands; ++i)
+    {
+      switch (GET_MODE (operands[i]))
+       {
+       case TFmode:
+         reg = gen_rtx_REG (TFmode, regno);
+         regno += 2;
+         break;
+
+       case DFmode:
+         reg = gen_rtx_REG (DFmode, regno + 32);
+         regno += 1;
+         break;
+
+       case VOIDmode:
+         if (GET_CODE (operands[i]) != CONST_INT)
+           abort ();
+         /* FALLTHRU */
+       case DImode:
+         reg = gen_rtx_REG (DImode, regno);
+         regno += 1;
+         break;
+
+       default:
+         abort ();
+       }
+
+      emit_move_insn (reg, operands[i]);
+      usage = alloc_EXPR_LIST (0, gen_rtx_USE (VOIDmode, reg), usage);
+    }
+
+  switch (GET_MODE (target))
+    {
+    case TFmode:
+      reg = gen_rtx_REG (TFmode, 16);
+      break;
+    case DFmode:
+      reg = gen_rtx_REG (DFmode, 32);
+      break;
+    case DImode:
+      reg = gen_rtx_REG (DImode, 0);
+      break;
+    default:
+      abort ();
+    }
+
+  tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, func));
+  tmp = emit_call_insn (gen_call_value (reg, tmp, const0_rtx,
+                                       const0_rtx, const0_rtx));
+  CALL_INSN_FUNCTION_USAGE (tmp) = usage;
+
+  tmp = get_insns ();
+  end_sequence ();
+
+  emit_libcall_block (tmp, target, reg, equiv);
+}
+
+/* Emit an X_floating library function call for arithmetic (+,-,*,/).  */
+
+void
+alpha_emit_xfloating_arith (code, operands)
+     enum rtx_code code;
+     rtx operands[];
+{
+  const char *func;
+  int mode;
+
+  func = alpha_lookup_xfloating_lib_func (code);
+  mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
+
+  operands[3] = GEN_INT (mode);
+  alpha_emit_xfloating_libcall (func, operands[0], operands+1, 3,  
+                               gen_rtx_fmt_ee (code, TFmode, operands[1],
+                                               operands[2]));
+}
+
+/* Emit an X_floating library function call for a comparison.  */
+
+static rtx
+alpha_emit_xfloating_compare (code, op0, op1)
+     enum rtx_code code;
+     rtx op0, op1;
+{
+  const char *func;
+  rtx out, operands[2];
+
+  func = alpha_lookup_xfloating_lib_func (code);
+
+  operands[0] = op0;
+  operands[1] = op1;
+  out = gen_reg_rtx (DImode);
+
+  /* ??? Strange equiv cause what's actually returned is -1,0,1, not a
+     proper boolean value.  */
+  alpha_emit_xfloating_libcall (func, out, operands, 2, 
+                               gen_rtx_COMPARE (TFmode, op0, op1));
+
+  return out;
+}
+
+/* Emit an X_floating library function call for a conversion.  */
+
+void
+alpha_emit_xfloating_cvt (code, operands)
+     enum rtx_code code;
+     rtx operands[];
+{
+  int noperands = 1, mode;
+  const char *func;
+
+  func = alpha_lookup_xfloating_lib_func (code);
+
+  switch (code)
+    {
+    case FIX:
+      mode = alpha_compute_xfloating_mode_arg (code, ALPHA_FPRM_CHOP);
+      operands[noperands++] = GEN_INT (mode);
+      break;
+    case FLOAT_TRUNCATE:
+      mode = alpha_compute_xfloating_mode_arg (code, alpha_fprm);
+      operands[noperands++] = GEN_INT (mode);
+      break;
+    default:
+      break;
+    }
+
+  alpha_emit_xfloating_libcall (func, operands[0], operands+1, noperands,
+                               gen_rtx_fmt_e (code, GET_MODE (operands[0]),
+                                              operands[1]));
+}
+\f
 /* Use ext[wlq][lh] as the Architecture Handbook describes for extracting
    unaligned data:
 
@@ -1770,6 +2076,7 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
          emit_insn (gen_extqh (exth, memh, addr));
          mode = DImode;
          break;
+
        default:
          abort();
        }
@@ -2806,6 +3113,8 @@ print_operand (file, x, code)
        case ALPHA_FPRM_DYN:
          fputc ('d', file);
          break;
+       default:
+         abort ();
        }
       break;
 
@@ -3213,6 +3522,46 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs)
     emit_insn (gen_imb ());
 }
 \f
+/* Determine where to put an argument to a function.
+   Value is zero to push the argument on the stack,
+   or a hard register in which to store the argument.
+
+   MODE is the argument's machine mode.
+   TYPE is the data type of the argument (as a tree).
+    This is null for libcalls where that information may
+    not be available.
+   CUM is a variable of type CUMULATIVE_ARGS which gives info about
+    the preceding args and about the function being called.
+   NAMED is nonzero if this argument is a named parameter
+    (otherwise it is an extra parameter matching an ellipsis).
+
+   On Alpha the first 6 words of args are normally in registers
+   and the rest are pushed.  */
+
+rtx
+function_arg(cum, mode, type, named)
+     CUMULATIVE_ARGS cum;
+     enum machine_mode mode;
+     tree type;
+     int named ATTRIBUTE_UNUSED;
+{
+  int basereg;
+
+  if (cum >= 6 || MUST_PASS_IN_STACK (mode, type))
+    return NULL_RTX;
+
+  if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
+    basereg = 16;
+  else if (TARGET_FPREGS
+          && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+              || GET_MODE_CLASS (mode) == MODE_FLOAT))
+    basereg = 32 + 16;
+  else
+    basereg = 16;
+
+  return gen_rtx_REG (mode, cum + basereg);
+}
+
 tree
 alpha_build_va_list ()
 {
index cf88a9a..b146a5a 100644 (file)
@@ -181,6 +181,9 @@ extern enum alpha_fp_trap_mode alpha_fptm;
 #ifndef TARGET_CAN_FAULT_IN_PROLOGUE
 #define TARGET_CAN_FAULT_IN_PROLOGUE 0
 #endif
+#ifndef TARGET_HAS_XFLOATING_LIBS
+#define TARGET_HAS_XFLOATING_LIBS 0
+#endif
 
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
@@ -511,7 +514,7 @@ extern const char *alpha_mlat_string;       /* For -mmemory-latency= */
   (optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0)
 
 /* No data type wants to be aligned rounder than this.  */
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT 128
 
 /* For atomic access to objects, must have at least 32-bit alignment
    unless the machine has byte operations.  */
@@ -1013,6 +1016,8 @@ extern int alpha_memory_latency;
 
 #define RETURN_IN_MEMORY(TYPE) \
   (TYPE_MODE (TYPE) == BLKmode \
+   || TYPE_MODE (TYPE) == TFmode \
+   || TYPE_MODE (TYPE) == TCmode \
    || (TREE_CODE (TYPE) == INTEGER_TYPE && TYPE_PRECISION (TYPE) > 64))
 
 /* 1 if N is a possible register number for a function value
@@ -1049,9 +1054,9 @@ extern int alpha_memory_latency;
    for the Alpha.  */
 
 #define ALPHA_ARG_SIZE(MODE, TYPE, NAMED)                              \
-((MODE) != BLKmode                                                     \
? (GET_MODE_SIZE (MODE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD      \
: (int_size_in_bytes (TYPE) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+  ((MODE) == TFmode || (MODE) == TCmode ? 1                            \
  : (((MODE) == BLKmode ? int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE)) \
     + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
@@ -1080,14 +1085,16 @@ extern int alpha_memory_latency;
    and the rest are pushed.  */
 
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED)   \
-((CUM) < 6 && ! MUST_PASS_IN_STACK (MODE, TYPE)        \
- ? gen_rtx_REG ((MODE),                                \
-               (CUM) + 16                      \
-               + ((TARGET_FPREGS               \
-                   && (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT  \
-                       || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \
-                  * 32))                       \
- : 0)
+  function_arg((CUM), (MODE), (TYPE), (NAMED))
+
+/* A C expression that indicates when an argument must be passed by
+   reference.  If nonzero for an argument, a copy of that argument is
+   made in memory and a pointer to the argument is passed instead of
+   the argument itself.  The pointer is passed in whatever way is
+   appropriate for passing a pointer to that type. */
+
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+  ((MODE) == TFmode || (MODE) == TCmode)
 
 /* Specify the padding direction of arguments.
 
@@ -1132,7 +1139,6 @@ extern int alpha_memory_latency;
    class, but it isn't worth doing anything more efficient in this rare
    case.  */
    
-
 #define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL)      \
 { if ((CUM) < 6)                                                       \
     {                                                                  \
@@ -2015,26 +2021,27 @@ literal_section ()                                              \
 #define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
   ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
 
+/* This is how to output an assembler line defining a `long double'
+   constant.  */
+
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE)                             \
+  do {                                                                 \
+    long t[4];                                                         \
+    REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), t);                     \
+    fprintf (FILE, "\t.quad 0x%lx%08lx,0x%lx%08lx\n",                  \
+            t[1] & 0xffffffff, t[0] & 0xffffffff,                      \
+            t[3] & 0xffffffff, t[2] & 0xffffffff);                     \
+  } while (0)
+
 /* This is how to output an assembler line defining a `double' constant.  */
 
 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)                                  \
-  {                                                                    \
-    if (REAL_VALUE_ISINF (VALUE)                                       \
-        || REAL_VALUE_ISNAN (VALUE)                                    \
-       || REAL_VALUE_MINUS_ZERO (VALUE))                               \
-      {                                                                        \
-       long t[2];                                                      \
-       REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);                       \
-       fprintf (FILE, "\t.quad 0x%lx%08lx\n",                          \
-               t[1] & 0xffffffff, t[0] & 0xffffffff);                  \
-      }                                                                        \
-    else                                                               \
-      {                                                                        \
-       char str[30];                                                   \
-       REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", str);                    \
-       fprintf (FILE, "\t.%c_floating %s\n", (TARGET_FLOAT_VAX)?'g':'t', str);                 \
-      }                                                                        \
-  }
+  do {                                                                 \
+    long t[2];                                                         \
+    REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t);                          \
+    fprintf (FILE, "\t.quad 0x%lx%08lx\n",                             \
+            t[1] & 0xffffffff, t[0] & 0xffffffff);                     \
+  } while (0)
 
 /* This is how to output an assembler line defining a `float' constant.  */
 
@@ -2043,7 +2050,7 @@ literal_section ()                                                \
     long t;                                                    \
     REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t);                  \
     fprintf (FILE, "\t.long 0x%lx\n", t & 0xffffffff);         \
-} while (0)
+  } while (0)
   
 /* This is how to output an assembler line defining an `int' constant.  */
 
index 7adee1d..b1d7904 100644 (file)
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+(define_expand "addtf3"
+  [(use (match_operand 0 "register_operand" ""))
+   (use (match_operand 1 "general_operand" ""))
+   (use (match_operand 2 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_arith (PLUS, operands); DONE;")
+
 ;; Define conversion operators between DFmode and SImode, using the cvtql
 ;; instruction.  To allow combine et al to do useful things, we keep the
 ;; operation as a unit until after reload, at which point we split the
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+(define_expand "fix_trunctfdi2"
+  [(use (match_operand:DI 0 "register_operand" ""))
+   (use (match_operand:TF 1 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_cvt (FIX, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (float:SF (match_operand:DI 1 "reg_no_subreg_operand" "f")))]
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+(define_expand "floatditf2"
+  [(use (match_operand:TF 0 "register_operand" ""))
+   (use (match_operand:DI 1 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_cvt (FLOAT, operands); DONE;")
+
+(define_expand "floatunsditf2"
+  [(use (match_operand:TF 0 "register_operand" ""))
+   (use (match_operand:DI 1 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_cvt (UNSIGNED_FLOAT, operands); DONE;")
+
 (define_expand "extendsfdf2"
   [(use (match_operand:DF 0 "register_operand" ""))
    (use (match_operand:SF 1 "nonimmediate_operand" ""))]
   [(set_attr "type" "fcpys,fld,fst")
    (set_attr "trap" "yes")])
 
+(define_expand "extenddftf2"
+  [(use (match_operand:TF 0 "register_operand" ""))
+   (use (match_operand:DF 1 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_cvt (FLOAT_EXTEND, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (float_truncate:SF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))]
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+(define_expand "trunctfdf2"
+  [(use (match_operand:DF 0 "register_operand" ""))
+   (use (match_operand:TF 1 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_cvt (FLOAT_TRUNCATE, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (div:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
   [(set_attr "type" "fdiv")
    (set_attr "trap" "yes")])
 
+(define_expand "divtf3"
+  [(use (match_operand 0 "register_operand" ""))
+   (use (match_operand 1 "general_operand" ""))
+   (use (match_operand 2 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_arith (DIV, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG")
   [(set_attr "type" "fmul")
    (set_attr "trap" "yes")])
 
+(define_expand "multf3"
+  [(use (match_operand 0 "register_operand" ""))
+   (use (match_operand 1 "general_operand" ""))
+   (use (match_operand 2 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_arith (MULT, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")
   [(set_attr "type" "fadd")
    (set_attr "trap" "yes")])
 
+(define_expand "subtf3"
+  [(use (match_operand 0 "register_operand" ""))
+   (use (match_operand 1 "general_operand" ""))
+   (use (match_operand 2 "general_operand" ""))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "alpha_emit_xfloating_arith (MINUS, operands); DONE;")
+
 (define_insn ""
   [(set (match_operand:SF 0 "register_operand" "=&f")
        (sqrt:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))]
   DONE;
 }")
 
+(define_expand "cmptf"
+  [(set (cc0) (compare (match_operand:TF 0 "general_operand" "")
+                      (match_operand:TF 1 "general_operand" "")))]
+  "TARGET_HAS_XFLOATING_LIBS"
+  "
+{
+  alpha_compare.op0 = operands[0];
+  alpha_compare.op1 = operands[1];
+  alpha_compare.fp_p = 1;
+  DONE;
+}")
+
 (define_expand "cmpdi"
   [(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "")
                       (match_operand:DI 1 "reg_or_8bit_operand" "")))]
index 5054444..50d4d5c 100644 (file)
@@ -24,6 +24,11 @@ Boston, MA 02111-1307, USA.  */
 #undef TARGET_AS_CAN_SUBTRACT_LABELS
 #define TARGET_AS_CAN_SUBTRACT_LABELS 1
 
+/* The GEM libraries for X_float are present, though not used by C.  */
+
+#undef TARGET_HAS_XFLOATING_LIBS
+#define TARGET_HAS_XFLOATING_LIBS 1
+
 /* Names to predefine in the preprocessor for this target machine.  */
 
 #define CPP_PREDEFINES "\
diff --git a/gcc/config/alpha/osf5.h b/gcc/config/alpha/osf5.h
new file mode 100644 (file)
index 0000000..1c336bd
--- /dev/null
@@ -0,0 +1,22 @@
+/* Definitions of target machine for GNU compiler, for DEC Alpha on Tru64 5.
+   Copyright (C) 2000 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 2, 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, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE  128
index 19a06a2..378be6d 100755 (executable)
@@ -3434,7 +3434,7 @@ for machine in $build $host $target; do
                    install_headers_dir=install-headers-cpio
                    ;;
                  *-*-osf5*)
-                   tm_file="${tm_file} alpha/osf.h"
+                   tm_file="${tm_file} alpha/osf.h alpha/osf5.h"
                    ;;
                esac
                case $machine in
index 7ccda1c..098e000 100644 (file)
@@ -689,7 +689,7 @@ changequote([,])dnl
                    install_headers_dir=install-headers-cpio
                    ;;
                  *-*-osf5*)
-                   tm_file="${tm_file} alpha/osf.h"
+                   tm_file="${tm_file} alpha/osf.h alpha/osf5.h"
                    ;;
                esac
                case $machine in
index 2c76306..d1e0473 100644 (file)
@@ -1218,9 +1218,9 @@ operand_subword (op, i, validate_address, mode)
      are defined as returning one or two 32 bit values, respectively,
      and not values of BITS_PER_WORD bits.  */
 #ifdef REAL_ARITHMETIC
-/*  The output is some bits, the width of the target machine's word.
-    A wider-word host can surely hold them in a CONST_INT. A narrower-word
-    host can't.  */
+  /* The output is some bits, the width of the target machine's word.
+     A wider-word host can surely hold them in a CONST_INT. A narrower-word
+     host can't.  */
   if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
       && GET_MODE_CLASS (mode) == MODE_FLOAT
       && GET_MODE_BITSIZE (mode) == 64
@@ -1271,22 +1271,31 @@ operand_subword (op, i, validate_address, mode)
           && GET_MODE_CLASS (mode) == MODE_FLOAT
           && GET_MODE_BITSIZE (mode) > 64
           && GET_CODE (op) == CONST_DOUBLE)
-  {
-    long k[4];
-    REAL_VALUE_TYPE rv;
+    {
+      long k[4];
+      REAL_VALUE_TYPE rv;
 
-    REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
-    REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+      REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+      REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
 
-    if (BITS_PER_WORD == 32)
-      {
-       val = k[i];
-       val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
-       return GEN_INT (val);
-      }
-    else
-      abort ();
-  }
+      if (BITS_PER_WORD == 32)
+       {
+         val = k[i];
+         val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000;
+         return GEN_INT (val);
+       }
+#if HOST_BITS_PER_WIDE_INT >= 64
+      else if (BITS_PER_WORD >= 64 && i <= 1)
+       {
+         val = k[i*2 + ! WORDS_BIG_ENDIAN];
+         val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32;
+         val |= (HOST_WIDE_INT) k[i*2 + WORDS_BIG_ENDIAN] & 0xffffffff;
+         return GEN_INT (val);
+       }
+#endif
+      else
+       abort ();
+    }
 #else /* no REAL_ARITHMETIC */
   if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)