Commit 02befdf4 by Zack Weinberg

genmodes.c (struct mode_data): Add contained and next_cont fields.

	* genmodes.c (struct mode_data): Add contained and next_cont
	fields.
	(complete_mode): Maintain linked list of modes that have a
	given component.
	(emit_mode_unit_size): Delete.
	(emit_mode_nunits): New.
	(emit_insn_modes_c): Update to match.
	(emit_mode_adjustments): Propagate size and alignment
	adjustments from component modes to their containers.
	* machmode.h (mode_unit_size): Delete.
	(mode_nunits): New.
	(GET_MODE_NUNITS): Just return the value in the table.
	(GET_MODE_UNIT_SIZE): Compute using GET_MODE_INNER and
	GET_MODE_SIZE.
	* expmed.c (store_bit_field, extract_bit_field): Can use a
	plain move instruction if bitsize >= GET_MODE_BITSIZE of
	destination/source mode, respectively.
	* varasm.c (assemble_real): Write out the full size of the
	constant, not just its bitsize.
	(output_constant): Honor TYPE_MODE of TREE_REAL_CSTs.

	* config/ia64/ia64-modes.def: Define XFmode as well as TFmode.
	Use ADJUST_BYTESIZE and ADJUST_ALIGNMENT to set size and
	alignment of XF and TF modes in compliance with ia64 ABIs.
	Can now hardwire the format of both modes.
	* config/ia64/ia64.c: Change TFmode to XFmode wherever appropriate.
	(general_tfmode_operand, destination_tfmode_operand)
	(tfreg_or_fp01_operand, spill_tfmode_operand): Rename to
	general_xfmode_operand, destination_xfmode_operand,
	xfreg_or_fp01_operand, spill_xfmode_operand respectively.
	(ia64_init_builtins): Make TYPE_PRECISION of fpreg_type
	and float80_type be 96 so they get XFmode.  Use !TARGET_HPUX,
	not INTEL_EXTENDED_IEEE_FORMAT, to decide how to define
	__float128.
	* config/ia64/ia64.h: Default TARGET_HPUX to 0.
	Change TFmode to XFmode wherever appropriate.  Remove all
	references to INTEL_EXTENDED_IEEE_FORMAT.
	(LONG_DOUBLE_TYPE_SIZE): Varies with TARGET_HPUX.
	(LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define (always 96).
	(PREDICATE_CODES): Update to match function renames.
	* config/ia64/ia64.md: Change TF to XF throughout; rename all
	patterns to match.  Remove all references to
	INTEL_EXTENDED_IEEE_FORMAT.  Update predicate calls to match
	function renames.
	* config/ia64/ia64-protos.c: Update all prototypes to match
	renamed functions.
	* config/ia64/hpux.h: Redefine TARGET_HPUX to 1.
	Remove all references to INTEL_EXTENDED_IEEE_FORMAT.
	* config/ia64/lib1funcs.asm: Add __divxf3 as new name for
	__divtf3; keep old name for backward compatibility.
	(L__compat): New section providing forwarding stubs for
	__fixtfti, __fixunstfti, __floattitf.
	* config/ia64/t-ia64: Add __compat to LIB1ASMFUNCS.

From-SVN: r72916
parent 569827c9
2003-10-24 Zack Weinberg <zack@codesourcery.com>
* genmodes.c (struct mode_data): Add contained and next_cont
fields.
(complete_mode): Maintain linked list of modes that have a
given component.
(emit_mode_unit_size): Delete.
(emit_mode_nunits): New.
(emit_insn_modes_c): Update to match.
(emit_mode_adjustments): Propagate size and alignment
adjustments from component modes to their containers.
* machmode.h (mode_unit_size): Delete.
(mode_nunits): New.
(GET_MODE_NUNITS): Just return the value in the table.
(GET_MODE_UNIT_SIZE): Compute using GET_MODE_INNER and
GET_MODE_SIZE.
* expmed.c (store_bit_field, extract_bit_field): Can use a
plain move instruction if bitsize >= GET_MODE_BITSIZE of
destination/source mode, respectively.
* varasm.c (assemble_real): Write out the full size of the
constant, not just its bitsize.
(output_constant): Honor TYPE_MODE of TREE_REAL_CSTs.
* config/ia64/ia64-modes.def: Define XFmode as well as TFmode.
Use ADJUST_BYTESIZE and ADJUST_ALIGNMENT to set size and
alignment of XF and TF modes in compliance with ia64 ABIs.
Can now hardwire the format of both modes.
* config/ia64/ia64.c: Change TFmode to XFmode wherever appropriate.
(general_tfmode_operand, destination_tfmode_operand)
(tfreg_or_fp01_operand, spill_tfmode_operand): Rename to
general_xfmode_operand, destination_xfmode_operand,
xfreg_or_fp01_operand, spill_xfmode_operand respectively.
(ia64_init_builtins): Make TYPE_PRECISION of fpreg_type
and float80_type be 96 so they get XFmode. Use !TARGET_HPUX,
not INTEL_EXTENDED_IEEE_FORMAT, to decide how to define
__float128.
* config/ia64/ia64.h: Default TARGET_HPUX to 0.
Change TFmode to XFmode wherever appropriate. Remove all
references to INTEL_EXTENDED_IEEE_FORMAT.
(LONG_DOUBLE_TYPE_SIZE): Varies with TARGET_HPUX.
(LIBGCC2_LONG_DOUBLE_TYPE_SIZE): Define (always 96).
(PREDICATE_CODES): Update to match function renames.
* config/ia64/ia64.md: Change TF to XF throughout; rename all
patterns to match. Remove all references to
INTEL_EXTENDED_IEEE_FORMAT. Update predicate calls to match
function renames.
* config/ia64/ia64-protos.c: Update all prototypes to match
renamed functions.
* config/ia64/hpux.h: Redefine TARGET_HPUX to 1.
Remove all references to INTEL_EXTENDED_IEEE_FORMAT.
* config/ia64/lib1funcs.asm: Add __divxf3 as new name for
__divtf3; keep old name for backward compatibility.
(L__compat): New section providing forwarding stubs for
__fixtfti, __fixunstfti, __floattitf.
* config/ia64/t-ia64: Add __compat to LIB1ASMFUNCS.
2003-10-24 Geoffrey Keating <geoffk@apple.com>
PR 10757
......@@ -29,7 +85,7 @@
($(docobjdir)/%.1): Depend on .pod instead of .texi.
($(docobjdir)/%.7): Likewise.
(%.pod): New implicit rule.
(cpp.pod): New dependency only rule.
(cpp.pod): New dependency only rule.
(gcc.pod): New intermediate rule with dependencies and commands.
(gfdl.pod): Likewise.
(fsf-funding.pod): Likewise.
......
......@@ -25,6 +25,10 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION fprintf (stderr, " (IA-64) HP-UX");
/* Enable HPUX ABI quirks. */
#undef TARGET_HPUX
#define TARGET_HPUX 1
/* Target OS builtins. */
#define TARGET_OS_CPP_BUILTINS() \
do { \
......@@ -106,7 +110,8 @@ do { \
returned just like a char variable and that is wrong on HP-UX
IA64. */
#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) (TREE_CODE (TREE_TYPE (FIELD)) != REAL_TYPE || (MODE == TFmode && !INTEL_EXTENDED_IEEE_FORMAT))
#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
(TREE_CODE (TREE_TYPE (FIELD)) != REAL_TYPE || MODE == TFmode)
/* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
but that doesn't put out the @function type information which causes
......@@ -187,10 +192,6 @@ do { \
#undef TARGET_C99_FUNCTIONS
#define TARGET_C99_FUNCTIONS 1
/* We are using IEEE quad precision, not a double-extended with padding. */
#undef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
#define TARGET_INIT_LIBFUNCS ia64_hpux_init_libfuncs
#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
/* Definitions of target machine GNU compiler. IA-64 version.
Copyright (C) 2002 Free Software Foundation, Inc.
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
......@@ -20,8 +20,41 @@ along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* hpux will override this in ia64_override_options. */
FLOAT_MODE (TF, 16, ieee_extended_intel_128_format);
/* IA64 requires both XF and TF modes.
XFmode is __float80 is IEEE extended; TFmode is __float128
is IEEE quad.
IEEE extended is 128 bits wide, except in ILP32 mode, but we
have to say it's 12 bytes so that the bitsize and wider_mode
tables are correctly set up. We correct its size below. */
FLOAT_MODE (XF, 12, ieee_extended_intel_128_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
/* The above produces:
mode ILP32 size/align LP64 size/align
XF 12/4 12/4
TF 16/16 16/16
psABI expectations:
mode ILP32 size/align LP64 size/align
XF - 16/16
TF - -
HPUX expectations:
mode ILP32 size/align LP64 size/align
XF 16/16 16/16
TF 16/8 -
We fix this up here. */
ADJUST_BYTESIZE (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
ADJUST_ALIGNMENT (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
ADJUST_ALIGNMENT (TF, (TARGET_ILP32 && TARGET_HPUX) ? 8 : 16);
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
INT_MODE (OI, 32);
......
......@@ -70,9 +70,9 @@ extern int predicate_operator (rtx, enum machine_mode);
extern int ar_lc_reg_operand (rtx, enum machine_mode);
extern int ar_ccv_reg_operand (rtx, enum machine_mode);
extern int ar_pfs_reg_operand (rtx, enum machine_mode);
extern int general_tfmode_operand (rtx, enum machine_mode);
extern int destination_tfmode_operand (rtx, enum machine_mode);
extern int tfreg_or_fp01_operand (rtx, enum machine_mode);
extern int general_xfmode_operand (rtx, enum machine_mode);
extern int destination_xfmode_operand (rtx, enum machine_mode);
extern int xfreg_or_fp01_operand (rtx, enum machine_mode);
extern int basereg_operand (rtx, enum machine_mode);
extern rtx ia64_expand_move (rtx, rtx);
......@@ -81,7 +81,7 @@ extern int addp4_optimize_ok (rtx, rtx);
extern void ia64_emit_cond_move (rtx, rtx, rtx);
extern int ia64_depz_field_mask (rtx, rtx);
extern rtx ia64_split_timode (rtx[], rtx, rtx);
extern rtx spill_tfmode_operand (rtx, int);
extern rtx spill_xfmode_operand (rtx, int);
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
extern void ia64_expand_call (rtx, rtx, rtx, int);
extern void ia64_split_call (rtx, rtx, rtx, rtx, rtx, int, int);
......
......@@ -923,7 +923,7 @@ ar_pfs_reg_operand (register rtx op, enum machine_mode mode)
/* Like general_operand, but don't allow (mem (addressof)). */
int
general_tfmode_operand (rtx op, enum machine_mode mode)
general_xfmode_operand (rtx op, enum machine_mode mode)
{
if (! general_operand (op, mode))
return 0;
......@@ -935,7 +935,7 @@ general_tfmode_operand (rtx op, enum machine_mode mode)
/* Similarly. */
int
destination_tfmode_operand (rtx op, enum machine_mode mode)
destination_xfmode_operand (rtx op, enum machine_mode mode)
{
if (! destination_operand (op, mode))
return 0;
......@@ -947,7 +947,7 @@ destination_tfmode_operand (rtx op, enum machine_mode mode)
/* Similarly. */
int
tfreg_or_fp01_operand (rtx op, enum machine_mode mode)
xfreg_or_fp01_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) == SUBREG)
return 0;
......@@ -1430,34 +1430,34 @@ ia64_split_timode (rtx out[2], rtx in, rtx scratch)
}
}
/* ??? Fixing GR->FR TFmode moves during reload is hard. You need to go
/* ??? Fixing GR->FR XFmode moves during reload is hard. You need to go
through memory plus an extra GR scratch register. Except that you can
either get the first from SECONDARY_MEMORY_NEEDED or the second from
SECONDARY_RELOAD_CLASS, but not both.
We got into problems in the first place by allowing a construct like
(subreg:TF (reg:TI)), which we got from a union containing a long double.
(subreg:XF (reg:TI)), which we got from a union containing a long double.
This solution attempts to prevent this situation from occurring. When
we see something like the above, we spill the inner register to memory. */
rtx
spill_tfmode_operand (rtx in, int force)
spill_xfmode_operand (rtx in, int force)
{
if (GET_CODE (in) == SUBREG
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, /*rescan=*/true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (force && GET_CODE (in) == REG)
{
rtx mem = gen_mem_addressof (in, NULL_TREE, /*rescan=*/true);
return gen_rtx_MEM (TFmode, copy_to_reg (XEXP (mem, 0)));
return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
}
else if (GET_CODE (in) == MEM
&& GET_CODE (XEXP (in, 0)) == ADDRESSOF)
return change_address (in, TFmode, copy_to_reg (XEXP (in, 0)));
return change_address (in, XFmode, copy_to_reg (XEXP (in, 0)));
else
return in;
}
......@@ -2679,7 +2679,7 @@ ia64_expand_prologue (void)
{
if (cfa_off & 15)
abort ();
reg = gen_rtx_REG (TFmode, regno);
reg = gen_rtx_REG (XFmode, regno);
do_spill (gen_fr_spill_x, reg, cfa_off, reg);
cfa_off -= 16;
}
......@@ -2849,7 +2849,7 @@ ia64_expand_epilogue (int sibcall_p)
{
if (cfa_off & 15)
abort ();
reg = gen_rtx_REG (TFmode, regno);
reg = gen_rtx_REG (XFmode, regno);
do_restore (gen_fr_restore_x, reg, cfa_off);
cfa_off -= 16;
}
......@@ -3305,16 +3305,15 @@ hfa_element_mode (tree type, int nested)
types though. */
case COMPLEX_TYPE:
if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT
&& (TYPE_MODE (type) != TCmode || INTEL_EXTENDED_IEEE_FORMAT))
return mode_for_size (GET_MODE_UNIT_SIZE (TYPE_MODE (type))
* BITS_PER_UNIT, MODE_FLOAT, 0);
&& TYPE_MODE (type) != TCmode)
return GET_MODE_INNER (TYPE_MODE (type));
else
return VOIDmode;
case REAL_TYPE:
/* We want to return VOIDmode for raw REAL_TYPEs, but the actual
mode if this is contained within an aggregate. */
if (nested && (TYPE_MODE (type) != TFmode || INTEL_EXTENDED_IEEE_FORMAT))
if (nested && TYPE_MODE (type) != TFmode)
return TYPE_MODE (type);
else
return VOIDmode;
......@@ -3482,8 +3481,8 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
/* Integral and aggregates go in general registers. If we have run out of
FR registers, then FP values must also go in general registers. This can
happen when we have a SFmode HFA. */
else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
|| (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
else if (mode == TFmode || mode == TCmode
|| (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
{
int byte_size = ((mode == BLKmode)
? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
......@@ -3784,8 +3783,7 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
else
return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype) &&
((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
else if (FLOAT_TYPE_P (valtype) && mode != TFmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
{
......@@ -4188,11 +4186,11 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
to = from, from = tmp;
}
/* Moving from FR<->GR in TFmode must be more expensive than 2,
/* Moving from FR<->GR in XFmode must be more expensive than 2,
so that we get secondary memory reloads. Between FR_REGS,
we have to make this at least as expensive as MEMORY_MOVE_COST
to avoid spectacularly poor register class preferencing. */
if (mode == TFmode)
if (mode == XFmode)
{
if (to != GR_REGS || from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
......@@ -4521,10 +4519,6 @@ ia64_override_options (void)
ia64_section_threshold = g_switch_set ? g_switch_value : IA64_DEFAULT_GVALUE;
init_machine_status = ia64_init_machine_status;
/* Tell the compiler which flavor of TFmode we're using. */
if (!INTEL_EXTENDED_IEEE_FORMAT)
REAL_MODE_FORMAT (TFmode) = &ieee_quad_format;
}
static enum attr_itanium_class ia64_safe_itanium_class (rtx);
......@@ -7717,26 +7711,20 @@ ia64_init_builtins (void)
/* The __fpreg type. */
fpreg_type = make_node (REAL_TYPE);
/* ??? Once the IA64 back end supports both 80-bit and 128-bit
floating types, this type should have XFmode, not TFmode.
TYPE_PRECISION should be 80 bits, not 128. And, the back end
should know to load/save __fpreg variables using the ldf.fill and
stf.spill instructions. */
TYPE_PRECISION (fpreg_type) = 128;
/* ??? The back end should know to load/save __fpreg variables using
the ldf.fill and stf.spill instructions. */
TYPE_PRECISION (fpreg_type) = 96;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
/* ??? Once the IA64 back end supports both 80-bit and 128-bit
floating types, this type should have XFmode, not TFmode.
TYPE_PRECISION should be 80 bits, not 128. */
TYPE_PRECISION (float80_type) = 128;
TYPE_PRECISION (float80_type) = 96;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
/* The __float128 type. */
if (INTEL_EXTENDED_IEEE_FORMAT)
if (!TARGET_HPUX)
{
tree float128_type = make_node (REAL_TYPE);
TYPE_PRECISION (float128_type) = 128;
......@@ -7744,7 +7732,7 @@ ia64_init_builtins (void)
(*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
}
else
/* This is a synonym for "long double". */
/* Under HPUX, this is a synonym for "long double". */
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float128");
......@@ -8345,8 +8333,10 @@ ia64_hpux_init_libfuncs (void)
set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
......
......@@ -135,6 +135,7 @@ extern int ia64_tls_size;
#define TARGET_TLS64 (ia64_tls_size == 64)
#define TARGET_EARLY_STOP_BITS (target_flags & MASK_EARLY_STOP_BITS)
#define TARGET_HPUX 0
#define TARGET_HPUX_LD 0
#ifndef HAVE_AS_LTOFFX_LDXMOV_RELOCS
......@@ -417,11 +418,11 @@ while (0)
#define DOUBLE_TYPE_SIZE 64
#define LONG_DOUBLE_TYPE_SIZE 128
/* long double is XFmode normally, TFmode for HPUX. */
#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 96)
/* By default we use the 80-bit Intel extended float format packaged
in a 128-bit entity. */
#define INTEL_EXTENDED_IEEE_FORMAT 1
/* We always want the XFmode operations from libgcc2.c. */
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 96
#define DEFAULT_SIGNED_CHAR 1
......@@ -779,7 +780,7 @@ while (0)
((REGNO) == PR_REG (0) && (MODE) == DImode ? 64 \
: PR_REGNO_P (REGNO) && (MODE) == BImode ? 2 \
: PR_REGNO_P (REGNO) && (MODE) == CCImode ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == TFmode && INTEL_EXTENDED_IEEE_FORMAT ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == XFmode ? 1 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* A C expression that is nonzero if it is permissible to store a value of mode
......@@ -791,10 +792,10 @@ while (0)
GET_MODE_CLASS (MODE) != MODE_CC && \
(MODE) != TImode && \
(MODE) != BImode && \
((MODE) != TFmode || INTEL_EXTENDED_IEEE_FORMAT) \
(MODE) != TFmode \
: PR_REGNO_P (REGNO) ? \
(MODE) == BImode || GET_MODE_CLASS (MODE) == MODE_CC \
: GR_REGNO_P (REGNO) ? (MODE) != CCImode && (MODE) != TFmode \
: GR_REGNO_P (REGNO) ? (MODE) != CCImode && (MODE) != XFmode \
: AR_REGNO_P (REGNO) ? (MODE) == DImode \
: BR_REGNO_P (REGNO) ? (MODE) == DImode \
: 0)
......@@ -807,11 +808,11 @@ while (0)
ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
zero. */
/* Don't tie integer and FP modes, as that causes us to get integer registers
allocated for FP instructions. TFmode only supported in FP registers so
allocated for FP instructions. XFmode only supported in FP registers so
we can't tie it with any other modes. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
&& (((MODE1) == TFmode) == ((MODE2) == TFmode)) \
&& (((MODE1) == XFmode) == ((MODE2) == XFmode)) \
&& (((MODE1) == BImode) == ((MODE2) == BImode)))
/* Handling Leaf Functions */
......@@ -1011,12 +1012,12 @@ enum reg_class
into a register of CLASS2. */
#if 0
/* ??? May need this, but since we've disallowed TFmode in GR_REGS,
/* ??? May need this, but since we've disallowed XFmode in GR_REGS,
I'm not quite sure how it could be invoked. The normal problems
with unions should be solved with the addressof fiddling done by
movtf and friends. */
movxf and friends. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
((MODE) == TFmode && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
((MODE) == XFmode && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
|| ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
#endif
......@@ -1026,7 +1027,7 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
((MODE) == BImode && (CLASS) == PR_REGS ? 2 \
: ((CLASS) == FR_REGS && (MODE) == TFmode) ? 1 \
: ((CLASS) == FR_REGS && (MODE) == XFmode) ? 1 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* In FP regs, we can't change FP values to integer values and vice
......@@ -1389,7 +1390,7 @@ do { \
gen_rtx_REG (MODE, \
(((GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) && \
((MODE) != TFmode || INTEL_EXTENDED_IEEE_FORMAT)) \
(MODE) != TFmode) \
? FR_RET_FIRST : GR_RET_FIRST))
/* A C expression that is nonzero if REGNO is the number of a hard register in
......@@ -2214,9 +2215,9 @@ do { \
{ "ar_lc_reg_operand", {REG}}, \
{ "ar_ccv_reg_operand", {REG}}, \
{ "ar_pfs_reg_operand", {REG}}, \
{ "general_tfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{ "destination_tfmode_operand", {SUBREG, REG, MEM}}, \
{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \
{ "general_xfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{ "destination_xfmode_operand", {SUBREG, REG, MEM}}, \
{ "xfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \
{ "basereg_operand", {SUBREG, REG}},
/* An alias for a machine mode name. This is the machine mode that elements of
......
#ifdef L__divtf3
#ifdef L__divxf3
// Compute a 80-bit IEEE double-extended quotient.
//
// From the Intel IA-64 Optimization Guide, choose the minimum latency
// alternative.
//
// farg0 holds the dividend. farg1 holds the divisor.
//
// __divtf3 is an alternate symbol name for backward compatibility.
.text
.align 16
.global __divxf3
.global __divtf3
.proc __divtf3
.proc __divxf3
__divxf3:
__divtf3:
cmp.eq p7, p0 = r0, r0
frcpa.s0 f10, p6 = farg0, farg1
......@@ -37,7 +41,7 @@ __divtf3:
(p6) fma.s0 fret0 = f12, f10, f11
(p7) mov fret0 = f10
br.ret.sptk rp
.endp __divtf3
.endp __divxf3
#endif
#ifdef L__divdf3
......@@ -701,3 +705,39 @@ __ia64_trampoline:
}
.endp __ia64_trampoline
#endif
#ifdef L__compat
// Thunks for backward compatibility.
.text
.align 16
.global __fixtfti
.proc __fixtfti
__fixtfti:
{ .bbb
br.sptk.many __fixxfti
;;
}
.endp __fixtfti
.align 16
.global __fixunstfti
.proc __fixunstfti
__fixunstfti:
{ .bbb
br.sptk.many __fixunsxfti
;;
}
.endp __fixunstfti
.align 16
.global __floattitf
.proc __floattitf
__floattitf:
{ .bbb
br.sptk.many __floattixf
;;
}
.endp __floattitf
#endif
......@@ -5,10 +5,10 @@ LIB1ASMSRC = ia64/lib1funcs.asm
# we use __ as the prefix. Note that L_divdi3 in libgcc2.c actually defines
# a TImode divide function, so there is no actual overlap here between
# libgcc2.c and lib1funcs.asm.
LIB1ASMFUNCS = __divtf3 __divdf3 __divsf3 \
LIB1ASMFUNCS = __divxf3 __divdf3 __divsf3 \
__divdi3 __moddi3 __udivdi3 __umoddi3 \
__divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
__nonlocal_goto __restore_stack_nonlocal __trampoline
__nonlocal_goto __restore_stack_nonlocal __trampoline __compat
# ??? Hack to get -P option used when compiling lib1funcs.asm, because Intel
# assembler does not accept # line number as a comment.
......
......@@ -326,13 +326,16 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
If the target is memory, storing any naturally aligned field can be
done with a simple store. For targets that support fast unaligned
memory, any naturally sized, unit aligned field can be done directly. */
memory, any naturally sized, unit aligned field can be done directly.
It's okay if the requested bitsize is greater than fieldmode's
bitsize; that just means the mode has padding bits. */
byte_offset = (bitnum % BITS_PER_WORD) / BITS_PER_UNIT
+ (offset * UNITS_PER_WORD);
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (fieldmode)
&& bitsize >= GET_MODE_BITSIZE (fieldmode)
&& (GET_CODE (op0) != MEM
? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
|| GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
......@@ -1029,9 +1032,11 @@ extract_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
if (GET_CODE (op0) == REG
&& mode == GET_MODE (op0)
&& bitnum == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
&& bitsize >= GET_MODE_BITSIZE (GET_MODE (op0)))
{
/* We're trying to extract a full register from itself. */
/* We're trying to extract a full register from itself.
(If the requested bitsize is greater than the bitsize of op0,
that just means op0's mode has padding bits.) */
return op0;
}
......
......@@ -65,6 +65,10 @@ struct mode_data
struct mode_data *component; /* mode of components */
struct mode_data *wider; /* next wider mode */
struct mode_data *contained; /* Pointer to list of modes that have
this mode as a component. */
struct mode_data *next_cont; /* Next mode in that list. */
const char *file; /* file and line of definition, */
unsigned int line; /* for error reporting */
};
......@@ -76,7 +80,7 @@ static struct mode_data *void_mode;
static const struct mode_data blank_mode = {
0, "<unknown>", MAX_MODE_CLASS,
-1, -1, -1, -1,
0, 0, 0,
0, 0, 0, 0, 0,
"<unknown>", 0
};
......@@ -372,6 +376,14 @@ complete_mode (struct mode_data *m)
alignment = m->bytesize;
m->alignment = alignment & (~alignment + 1);
/* If this mode has components, make the component mode point back
to this mode, for the sake of adjustments. */
if (m->component)
{
m->next_cont = m->component->contained;
m->component->contained = m;
}
}
static void
......@@ -912,18 +924,15 @@ emit_mode_size (void)
}
static void
emit_mode_unit_size (void)
emit_mode_nunits (void)
{
enum mode_class c;
struct mode_data *m;
print_decl ("unsigned char", "mode_unit_size", "NUM_MACHINE_MODES");
print_decl ("unsigned char", "mode_nunits", "NUM_MACHINE_MODES");
for_all_modes (c, m)
tagged_printf ("%u",
m->component
? m->component->bytesize : m->bytesize,
m->name);
tagged_printf ("%u", m->ncomponents, m->name);
print_closer ();
}
......@@ -1055,23 +1064,87 @@ static void
emit_mode_adjustments (void)
{
struct mode_adjust *a;
struct mode_data *m;
puts ("\nvoid\ninit_adjust_machine_modes (void)\n{");
puts ("\
\nvoid\
\ninit_adjust_machine_modes (void)\
\n{\
\n size_t s ATTRIBUTE_UNUSED;");
/* Size adjustments must be propagated to all containing modes.
A size adjustment forces us to recalculate the alignment too. */
for (a = adj_bytesize; a; a = a->next)
printf (" /* %s:%d */\n mode_size[%smode] = %s;\n",
a->file, a->line, a->mode->name, a->adjustment);
if (adj_bytesize && (adj_alignment || adj_format))
putchar ('\n');
{
printf ("\n /* %s:%d */\n s = %s;\n",
a->file, a->line, a->adjustment);
printf (" mode_size[%smode] = s;\n", a->mode->name);
printf (" mode_base_align[%smode] = s & (~s + 1);\n",
a->mode->name);
for (m = a->mode->contained; m; m = m->next_cont)
{
switch (m->class)
{
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
printf (" mode_size[%smode] = 2*s;\n", m->name);
printf (" mode_base_align[%smode] = s & (~s + 1);\n",
m->name);
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
printf (" mode_size[%smode] = %d*s;\n",
m->name, m->ncomponents);
printf (" mode_base_align[%smode] = (%d*s) & (~(%d*s)+1);\n",
m->name, m->ncomponents, m->ncomponents);
break;
default:
internal_error (
"mode %s is neither vector nor complex but contains %s",
m->name, a->mode->name);
/* NOTREACHED */
}
}
}
/* Alignment adjustments propagate too.
??? This may not be the right thing for vector modes. */
for (a = adj_alignment; a; a = a->next)
printf (" /* %s:%d */\n mode_base_align[%smode] = %s;\n",
a->file, a->line, a->mode->name, a->adjustment);
if (adj_alignment && adj_format)
putchar ('\n');
{
printf ("\n /* %s:%d */\n s = %s;\n",
a->file, a->line, a->adjustment);
printf (" mode_base_align[%smode] = s;\n", a->mode->name);
for (m = a->mode->contained; m; m = m->next_cont)
{
switch (m->class)
{
case MODE_COMPLEX_INT:
case MODE_COMPLEX_FLOAT:
printf (" mode_base_align[%smode] = s;\n", m->name);
break;
case MODE_VECTOR_INT:
case MODE_VECTOR_FLOAT:
printf (" mode_base_align[%smode] = %d*s;\n",
m->name, m->ncomponents);
break;
default:
internal_error (
"mode %s is neither vector nor complex but contains %s",
m->name, a->mode->name);
/* NOTREACHED */
}
}
}
/* Real mode formats don't have to propagate anywhere. */
for (a = adj_format; a; a = a->next)
printf (" /* %s:%d */\n REAL_MODE_FORMAT (%smode) = %s;\n",
printf ("\n /* %s:%d */\n REAL_MODE_FORMAT (%smode) = %s;\n",
a->file, a->line, a->mode->name, a->adjustment);
puts ("}");
......@@ -1085,7 +1158,7 @@ emit_insn_modes_c (void)
emit_mode_class ();
emit_mode_bitsize ();
emit_mode_size ();
emit_mode_unit_size ();
emit_mode_nunits ();
emit_mode_wider ();
emit_mode_mask ();
emit_mode_inner ();
......
......@@ -81,17 +81,6 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
extern CONST_MODE_SIZE unsigned char mode_size[NUM_MACHINE_MODES];
#define GET_MODE_SIZE(MODE) mode_size[MODE]
/* Get the size in bytes of the basic parts of an object of mode MODE. */
extern const unsigned char mode_unit_size[NUM_MACHINE_MODES];
#define GET_MODE_UNIT_SIZE(MODE) mode_unit_size[MODE]
/* Get the number of units in the object. */
#define GET_MODE_NUNITS(MODE) \
((GET_MODE_UNIT_SIZE ((MODE)) == 0) ? 0 \
: (GET_MODE_SIZE ((MODE)) / GET_MODE_UNIT_SIZE ((MODE))))
/* Get the size in bits of an object of mode MODE. */
extern const unsigned short mode_bitsize[NUM_MACHINE_MODES];
......@@ -104,12 +93,23 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES];
#define GET_MODE_MASK(MODE) mode_mask_array[MODE]
extern const unsigned char mode_inner[NUM_MACHINE_MODES];
/* Return the mode of the inner elements in a vector. */
extern const unsigned char mode_inner[NUM_MACHINE_MODES];
#define GET_MODE_INNER(MODE) mode_inner[MODE]
/* Get the size in bytes of the basic parts of an object of mode MODE. */
#define GET_MODE_UNIT_SIZE(MODE) \
(GET_MODE_INNER (MODE) == VOIDmode \
? GET_MODE_SIZE (MODE) \
: GET_MODE_SIZE (GET_MODE_INNER (MODE)))
/* Get the number of units in the object. */
extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
#define GET_MODE_NUNITS(MODE) mode_nunits[MODE]
/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */
extern const unsigned char mode_wider[NUM_MACHINE_MODES];
......
......@@ -1905,15 +1905,20 @@ assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
int i;
int bitsize, nelts, nunits, units_per;
/* This is hairy. We have a quantity of known bitsize. real_to_target
/* This is hairy. We have a quantity of known size. real_to_target
will put it into an array of *host* longs, 32 bits per element
(even if long is more than 32 bits). We need to determine the
number of array elements that are occupied (nelts) and the number
of *target* min-addressable units that will be occupied in the
object file (nunits). We can assume that BITS_PER_UNIT divides
the mode's bitsize evenly, but we can not assume that 32 does. */
bitsize = GET_MODE_BITSIZE (mode);
nunits = bitsize / BITS_PER_UNIT;
object file (nunits). We cannot assume that 32 divides the
mode's bitsize (size * BITS_PER_UNIT) evenly.
size * BITS_PER_UNIT is used here to make sure that padding bits
(which might appear at either end of the value; real_to_target
will include the padding bits in its output array) are included. */
nunits = GET_MODE_SIZE (mode);
bitsize = nunits * BITS_PER_UNIT;
nelts = CEIL (bitsize, 32);
units_per = 32 / BITS_PER_UNIT;
......@@ -3756,9 +3761,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
if (TREE_CODE (exp) != REAL_CST)
error ("initializer for floating value is not a floating constant");
assemble_real (TREE_REAL_CST (exp),
mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0),
align);
assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
break;
case COMPLEX_TYPE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment