mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-21 14:50:57 +08:00
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:
parent
ac4904440b
commit
5495cc558b
@ -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...
|
||||
|
@ -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));
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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" "")))]
|
||||
|
@ -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
22
gcc/config/alpha/osf5.h
Normal 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
2
gcc/configure
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user