diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/config/alpha/alpha-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 355 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 69 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 70 | ||||
-rw-r--r-- | gcc/config/alpha/osf.h | 5 | ||||
-rw-r--r-- | gcc/config/alpha/osf5.h | 22 | ||||
-rwxr-xr-x | gcc/configure | 2 | ||||
-rw-r--r-- | gcc/configure.in | 2 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 43 |
10 files changed, 551 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee7112c..1d5a61f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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... diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index e9e88bc..c29063e 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -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)); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 1ea9874..94927747 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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 () { diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index cf88a9a..b146a5a 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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. */ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 7adee1d..b1d79042 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -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" "")))] diff --git a/gcc/config/alpha/osf.h b/gcc/config/alpha/osf.h index 5054444..50d4d5c 100644 --- a/gcc/config/alpha/osf.h +++ b/gcc/config/alpha/osf.h @@ -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 index 0000000..1c336bd --- /dev/null +++ b/gcc/config/alpha/osf5.h @@ -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 diff --git a/gcc/configure b/gcc/configure index 19a06a2..378be6d 100755 --- a/gcc/configure +++ b/gcc/configure @@ -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 diff --git a/gcc/configure.in b/gcc/configure.in index 7ccda1c..098e000 100644 --- a/gcc/configure.in +++ b/gcc/configure.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 diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 2c76306..d1e0473 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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) |