osf.h (TARGET_HAS_XFLOATING_LIBS): Define.

* 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.

From-SVN: r31579
This commit is contained in:
Richard Henderson 2000-01-23 20:02:40 -08:00 committed by Richard Henderson
parent ac4904440b
commit 5495cc558b
10 changed files with 551 additions and 53 deletions

View 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...

View 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));

View 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));
}
/* 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]));
}
/* 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 ());
}
/* 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 ()
{

View 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. */

View File

@ -1842,6 +1842,13 @@
[(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
@ -1981,6 +1988,12 @@
[(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")))]
@ -2013,6 +2026,18 @@
[(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" ""))]
@ -2047,6 +2072,12 @@
[(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")))]
@ -2063,6 +2094,12 @@
[(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")
@ -2129,6 +2166,13 @@
[(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")
@ -2186,6 +2230,13 @@
[(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")
@ -2253,6 +2304,13 @@
[(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")))]
@ -2964,6 +3022,18 @@
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" "")))]

View 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 "\

22
gcc/config/alpha/osf5.h Normal file
View File

@ -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

2
gcc/configure vendored
View File

@ -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

View 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

View 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)