Commit f8a1ebc6 by Jan Hubicka Committed by Jan Hubicka

real.c (encode_ieee_extended): Initialize whole array.

	* real.c (encode_ieee_extended): Initialize whole array.
	* reg-stack.c (move_for_stack_reg0: Use always XFmode.
	* i386-modes.def: Change definitions of TFmode and XFmode.
	* i386.c (classify_argument): Rename TFmodes to XFmodes; add new TFmode code.
	(construct_container): Allow constructing of TFmode integer containers.
	(ix86_return_in_memory):  XFmode is not returned in memory.
	(init_ext_80387_constants): Always use XFmode.
	(print_operand): Likewise.
	(ix86_prepare_fp_compare_regs): Likewise.
	(split_to_parts): Deal with TFmode.
	(split_long_move): Simplify.
	(ix86_init_mmx_sse_builtins): Add __float80, __float128.
	(ix86_memory_move_cost): Do not confuse TFmode.
	* i386.h (LONG_DOUBLE_TYPE_SIZE): Set to 96.
	(IS_STACK_MODE): TFmode is not stack mode.
	(HARD_REGNO_NREGS, CLASS_MAX_NREGS): Deal nicely with XFmode.
	(VALID_SSE_REG_MODE): Allow TFmode.
	(VALID_FP_MODE_P): Disallow TFmode.
	(VALID_INT_MODE_P): Allow TFmode in 64bit mode.
	* i386.md (TFmode patterns): Kill.
	(movtf, motf_rex64): New patterns.

From-SVN: r73099
parent 27eb8ab1
2003-10-30 Jan Hubicka <jh@suse.cz>
* real.c (encode_ieee_extended): Initialize whole array.
* reg-stack.c (move_for_stack_reg0: Use always XFmode.
* i386-modes.def: Change definitions of TFmode and XFmode.
* i386.c (classify_argument): Rename TFmodes to XFmodes; add new TFmode code.
(construct_container): Allow constructing of TFmode integer containers.
(ix86_return_in_memory): XFmode is not returned in memory.
(init_ext_80387_constants): Always use XFmode.
(print_operand): Likewise.
(ix86_prepare_fp_compare_regs): Likewise.
(split_to_parts): Deal with TFmode.
(split_long_move): Simplify.
(ix86_init_mmx_sse_builtins): Add __float80, __float128.
(ix86_memory_move_cost): Do not confuse TFmode.
* i386.h (LONG_DOUBLE_TYPE_SIZE): Set to 96.
(IS_STACK_MODE): TFmode is not stack mode.
(HARD_REGNO_NREGS, CLASS_MAX_NREGS): Deal nicely with XFmode.
(VALID_SSE_REG_MODE): Allow TFmode.
(VALID_FP_MODE_P): Disallow TFmode.
(VALID_INT_MODE_P): Allow TFmode in 64bit mode.
* i386.md (TFmode patterns): Kill.
(movtf, motf_rex64): New patterns.
2003-10-30 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.md (adddi3): Fix typo in mips16 stack pointer code.
......
......@@ -18,11 +18,18 @@ 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. */
/* By default our XFmode is the 80-bit extended format. If we use
TFmode instead, it's also the 80-bit format, but with padding. */
/* x86_64 ABI specifies 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_96_format);
FLOAT_MODE (TF, 16, ieee_extended_intel_128_format);
ADJUST_BYTESIZE (XF, TARGET_128BIT_LONG_DOUBLE ? 16 : 12);
ADJUST_ALIGNMENT (XF, TARGET_128BIT_LONG_DOUBLE ? 16 : 4);
FLOAT_MODE (TF, 16, ieee_quad_format);
/* Add any extra modes needed to represent the condition code.
......
......@@ -1374,6 +1374,7 @@ override_options (void)
if (TARGET_SSE2)
target_flags |= MASK_SSE;
target_flags |= (MASK_128BIT_LONG_DOUBLE);
if (TARGET_64BIT)
{
if (TARGET_ALIGN_DOUBLE)
......@@ -2182,6 +2183,7 @@ classify_argument (enum machine_mode mode, tree type,
return 1;
case CDImode:
case TImode:
case TCmode:
classes[0] = classes[1] = X86_64_INTEGER_CLASS;
return 2;
case CTImode:
......@@ -2197,11 +2199,15 @@ classify_argument (enum machine_mode mode, tree type,
case DFmode:
classes[0] = X86_64_SSEDF_CLASS;
return 1;
case TFmode:
case XFmode:
classes[0] = X86_64_X87_CLASS;
classes[1] = X86_64_X87UP_CLASS;
return 2;
case TCmode:
case TFmode:
classes[0] = X86_64_INTEGER_CLASS;
classes[1] = X86_64_INTEGER_CLASS;
return 2;
case XCmode:
classes[0] = X86_64_X87_CLASS;
classes[1] = X86_64_X87UP_CLASS;
classes[2] = X86_64_X87_CLASS;
......@@ -2338,16 +2344,16 @@ construct_container (enum machine_mode mode, tree type, int in_return,
return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
if (n == 2
&& class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
return gen_rtx_REG (TFmode, FIRST_STACK_REG);
return gen_rtx_REG (XFmode, FIRST_STACK_REG);
if (n == 2 && class[0] == X86_64_INTEGER_CLASS
&& class[1] == X86_64_INTEGER_CLASS
&& (mode == CDImode || mode == TImode)
&& (mode == CDImode || mode == TImode || mode == TFmode)
&& intreg[0] + 1 == intreg[1])
return gen_rtx_REG (mode, intreg[0]);
if (n == 4
&& class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS
&& class[2] == X86_64_X87_CLASS && class[3] == X86_64_X87UP_CLASS)
return gen_rtx_REG (TCmode, FIRST_STACK_REG);
return gen_rtx_REG (XCmode, FIRST_STACK_REG);
/* Otherwise figure out the entries of the PARALLEL. */
for (i = 0; i < n; i++)
......@@ -2779,8 +2785,9 @@ ix86_return_in_memory (tree type)
}
}
if (mode == TFmode)
if (mode == TFmode || mode == XFmode)
return 0;
if (size > 12)
return 1;
return 0;
......@@ -2795,20 +2802,35 @@ ix86_libcall_value (enum machine_mode mode)
{
switch (mode)
{
case SFmode:
case SCmode:
case DFmode:
case DCmode:
return gen_rtx_REG (mode, FIRST_SSE_REG);
case TFmode:
case TCmode:
return gen_rtx_REG (mode, FIRST_FLOAT_REG);
default:
return gen_rtx_REG (mode, 0);
case SFmode:
case SCmode:
case DFmode:
case DCmode:
return gen_rtx_REG (mode, FIRST_SSE_REG);
case XFmode:
case XCmode:
return gen_rtx_REG (mode, FIRST_FLOAT_REG);
case TFmode:
{
rtx ret = gen_rtx_PARALLEL (mode, rtvec_alloc (2));
XVECEXP (ret, 0, 0) = gen_rtx_EXPR_LIST
(VOIDmode,
gen_rtx_REG (DImode, x86_64_int_parameter_registers [0]),
const0_rtx);
XVECEXP (ret, 0, 1) = gen_rtx_EXPR_LIST
(VOIDmode,
gen_rtx_REG (DImode, x86_64_int_parameter_registers [1]),
GEN_INT (64));
return ret;
}
case TCmode:
return NULL;
default:
return gen_rtx_REG (mode, 0);
}
}
else
return gen_rtx_REG (mode, ix86_value_regno (mode));
return gen_rtx_REG (mode, ix86_value_regno (mode));
}
/* Given a mode, return the register to use for a return value. */
......@@ -4257,8 +4279,7 @@ init_ext_80387_constants (void)
real_from_string (&ext_80387_constants_table[i], cst[i]);
/* Ensure each constant is rounded to XFmode precision. */
real_convert (&ext_80387_constants_table[i],
TARGET_128BIT_LONG_DOUBLE ? TFmode : XFmode,
&ext_80387_constants_table[i]);
XFmode, &ext_80387_constants_table[i]);
}
ext_80387_constants_init = 1;
......@@ -4280,7 +4301,7 @@ standard_80387_constant_p (rtx x)
/* For XFmode constants, try to find a special 80387 instruction on
those CPUs that benefit from them. */
if ((GET_MODE (x) == XFmode || GET_MODE (x) == TFmode)
if (GET_MODE (x) == XFmode
&& x86_ext_80387_constants & TUNEMASK)
{
REAL_VALUE_TYPE r;
......@@ -4351,7 +4372,7 @@ standard_80387_constant_rtx (int idx)
}
return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i],
TARGET_128BIT_LONG_DOUBLE ? TFmode : XFmode);
XFmode);
}
/* Return 1 if X is FP constant we can load to SSE register w/o using memory.
......@@ -7450,7 +7471,7 @@ print_operand (FILE *file, rtx x, int code)
}
else if (GET_CODE (x) == CONST_DOUBLE
&& (GET_MODE (x) == XFmode || GET_MODE (x) == TFmode))
&& GET_MODE (x) == XFmode)
{
char dstr[30];
......@@ -8690,7 +8711,6 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
if (!is_sse
&& (fpcmp_mode == CCFPUmode
|| op_mode == XFmode
|| op_mode == TFmode
|| ix86_use_fcomi_compare (code)))
{
op0 = force_reg (op_mode, op0);
......@@ -9165,7 +9185,6 @@ ix86_expand_branch (enum rtx_code code, rtx label)
case SFmode:
case DFmode:
case XFmode:
case TFmode:
{
rtvec vec;
int use_fcomi;
......@@ -10356,7 +10375,7 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
int size;
if (!TARGET_64BIT)
size = mode == TFmode ? 3 : (GET_MODE_SIZE (mode) / 4);
size = mode==XFmode ? 3 : GET_MODE_SIZE (mode) / 4;
else
size = (GET_MODE_SIZE (mode) + 4) / 8;
......@@ -10416,7 +10435,6 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
switch (mode)
{
case XFmode:
case TFmode:
REAL_VALUE_TO_TARGET_LONG_DOUBLE (r, l);
parts[2] = gen_int_mode (l[2], SImode);
break;
......@@ -10439,18 +10457,19 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
split_ti (&operand, 1, &parts[0], &parts[1]);
if (mode == XFmode || mode == TFmode)
{
enum machine_mode upper_mode = mode==XFmode ? SImode : DImode;
if (REG_P (operand))
{
if (!reload_completed)
abort ();
parts[0] = gen_rtx_REG (DImode, REGNO (operand) + 0);
parts[1] = gen_rtx_REG (SImode, REGNO (operand) + 1);
parts[1] = gen_rtx_REG (upper_mode, REGNO (operand) + 1);
}
else if (offsettable_memref_p (operand))
{
operand = adjust_address (operand, DImode, 0);
parts[0] = operand;
parts[1] = adjust_address (operand, SImode, 8);
parts[1] = adjust_address (operand, upper_mode, 8);
}
else if (GET_CODE (operand) == CONST_DOUBLE)
{
......@@ -10468,7 +10487,16 @@ ix86_split_to_parts (rtx operand, rtx *parts, enum machine_mode mode)
DImode);
else
parts[0] = immed_double_const (l[0], l[1], DImode);
parts[1] = gen_int_mode (l[2], SImode);
if (upper_mode == SImode)
parts[1] = gen_int_mode (l[2], SImode);
else if (HOST_BITS_PER_WIDE_INT >= 64)
parts[1]
= gen_int_mode
((l[2] & (((HOST_WIDE_INT) 2 << 31) - 1))
+ ((((HOST_WIDE_INT) l[3]) << 31) << 1),
DImode);
else
parts[1] = immed_double_const (l[2], l[3], DImode);
}
else
abort ();
......@@ -10589,12 +10617,8 @@ ix86_split_long_move (rtx operands[])
{
if (nparts == 3)
{
/* We use only first 12 bytes of TFmode value, but for pushing we
are required to adjust stack as if we were pushing real 16byte
value. */
if (mode == TFmode && !TARGET_64BIT)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (-4)));
if (TARGET_128BIT_LONG_DOUBLE && mode == XFmode)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (-4)));
emit_move_insn (part[0][2], part[1][2]);
}
}
......@@ -13305,6 +13329,27 @@ ix86_init_mmx_sse_builtins (void)
tree v2di_ftype_v2di
= build_function_type_list (V2DI_type_node, V2DI_type_node, NULL_TREE);
tree float80_type;
tree float128_type;
/* The __float80 type. */
if (TYPE_MODE (long_double_type_node) == XFmode)
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float80");
else
{
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
TYPE_PRECISION (float80_type) = 96;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
}
float128_type = make_node (REAL_TYPE);
TYPE_PRECISION (float128_type) = 128;
layout_type (float128_type);
(*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
/* Add all builtins that are more or less simple operations on two
operands. */
for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
......@@ -14745,7 +14790,6 @@ ix86_memory_move_cost (enum machine_mode mode, enum reg_class class, int in)
index = 1;
break;
case XFmode:
case TFmode:
index = 2;
break;
default:
......
......@@ -721,16 +721,7 @@ extern int x86_prefetch_sse;
/* target machine storage layout */
/* Define for XFmode or TFmode extended real floating point support.
The XFmode is specified by i386 ABI, while TFmode may be faster
due to alignment and simplifications in the address calculations. */
#define LONG_DOUBLE_TYPE_SIZE (TARGET_128BIT_LONG_DOUBLE ? 128 : 96)
#define MAX_LONG_DOUBLE_TYPE_SIZE 128
#ifdef __x86_64__
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
#else
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 96
#endif
#define LONG_DOUBLE_TYPE_SIZE 96
/* Set the value of FLT_EVAL_METHOD in float.h. When using only the
FPU, assume that the fpcw is set to extended precision; when using
......@@ -900,8 +891,7 @@ extern int x86_prefetch_sse;
#define STACK_REGS
#define IS_STACK_MODE(MODE) \
((MODE) == DFmode || (MODE) == SFmode || (MODE) == XFmode \
|| (MODE) == TFmode)
((MODE) == DFmode || (MODE) == SFmode || (MODE) == XFmode) \
/* Number of actual hardware registers.
The hardware registers are assigned numbers for the compiler
......@@ -1049,9 +1039,9 @@ do { \
#define HARD_REGNO_NREGS(REGNO, MODE) \
(FP_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \
? (COMPLEX_MODE_P (MODE) ? 2 : 1) \
: ((MODE) == TFmode \
: ((MODE) == XFmode \
? (TARGET_64BIT ? 2 : 3) \
: (MODE) == TCmode \
: (MODE) == XCmode \
? (TARGET_64BIT ? 4 : 6) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
......@@ -1061,7 +1051,7 @@ do { \
#define VALID_SSE_REG_MODE(MODE) \
((MODE) == TImode || (MODE) == V4SFmode || (MODE) == V4SImode \
|| (MODE) == SFmode \
|| (MODE) == SFmode || (MODE) == TFmode \
/* Always accept SSE2 modes so that xmmintrin.h compiles. */ \
|| VALID_SSE2_REG_MODE (MODE) \
|| (TARGET_SSE2 && ((MODE) == DFmode || VALID_MMX_REG_MODE (MODE))))
......@@ -1079,21 +1069,20 @@ do { \
: VALID_MMX_REG_MODE_3DNOW (MODE) && TARGET_3DNOW ? 1 : 0)
#define VALID_FP_MODE_P(MODE) \
((MODE) == SFmode || (MODE) == DFmode || (MODE) == TFmode \
|| (!TARGET_64BIT && (MODE) == XFmode) \
|| (MODE) == SCmode || (MODE) == DCmode || (MODE) == TCmode \
|| (!TARGET_64BIT && (MODE) == XCmode))
((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode \
|| (MODE) == SCmode || (MODE) == DCmode || (MODE) == XCmode) \
#define VALID_INT_MODE_P(MODE) \
((MODE) == QImode || (MODE) == HImode || (MODE) == SImode \
|| (MODE) == DImode \
|| (MODE) == CQImode || (MODE) == CHImode || (MODE) == CSImode \
|| (MODE) == CDImode \
|| (TARGET_64BIT && ((MODE) == TImode || (MODE) == CTImode)))
|| (TARGET_64BIT && ((MODE) == TImode || (MODE) == CTImode \
|| (MODE) == TFmode || (MODE) == TCmode)))
/* Return true for modes passed in SSE registers. */
#define SSE_REG_MODE_P(MODE) \
((MODE) == TImode || (MODE) == V16QImode \
((MODE) == TImode || (MODE) == V16QImode || (MODE) == TFmode \
|| (MODE) == V8HImode || (MODE) == V2DFmode || (MODE) == V2DImode \
|| (MODE) == V4SFmode || (MODE) == V4SImode)
......@@ -1568,15 +1557,12 @@ enum reg_class
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS. */
/* On the 80386, this is the size of MODE in words,
except in the FP regs, where a single reg is always enough.
The TFmodes are really just 80bit values, so we use only 3 registers
to hold them, instead of 4, as the size would suggest.
*/
except in the FP regs, where a single reg is always enough. */
#define CLASS_MAX_NREGS(CLASS, MODE) \
(!MAYBE_INTEGER_CLASS_P (CLASS) \
? (COMPLEX_MODE_P (MODE) ? 2 : 1) \
: ((GET_MODE_SIZE ((MODE) == TFmode ? XFmode : (MODE)) \
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD))
: (((((MODE) == XFmode ? 12 : GET_MODE_SIZE (MODE))) \
+ UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* A C expression whose value is nonzero if pseudos that have been
assigned to registers of class CLASS would likely be spilled
......
......@@ -3032,6 +3032,11 @@ encode_ieee_extended (const struct real_format *fmt, long *buf,
buf[0] = image_hi << 16, buf[1] = sig_hi, buf[2] = sig_lo;
else
buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
/* Avoid uninitialized data to be output by compiler when XFmode is extended
to 128 bits. */
if (GET_MODE_SIZE (XFmode) == 16)
buf[3] = 0;
}
static void
......
......@@ -1124,7 +1124,7 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
regstack->top--;
CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
}
else if ((GET_MODE (src) == XFmode || GET_MODE (src) == TFmode)
else if ((GET_MODE (src) == XFmode)
&& regstack->top < REG_STACK_SIZE - 1)
{
/* A 387 cannot write an XFmode value to a MEM without
......@@ -1137,10 +1137,7 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat)
rtx push_rtx, push_insn;
rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src));
if (GET_MODE (src) == TFmode)
push_rtx = gen_movtf (top_stack_reg, top_stack_reg);
else
push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
push_insn = emit_insn_before (push_rtx, insn);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
REG_NOTES (insn));
......
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