with partial reg. dependencies used by Athlon/P4 based chips, it is better
to leave it off for generic32 for now. */
const int x86_partial_reg_stall = m_PPRO;
+const int x86_partial_flag_reg_stall = m_GENERIC;
const int x86_use_himode_fiop = m_386 | m_486 | m_K6;
const int x86_use_simode_fiop = ~(m_PPRO | m_ATHLON_K8 | m_PENT | m_GENERIC);
const int x86_use_mov0 = m_K6;
gcc_assert (!TARGET_64BIT);
/* 8-byte vector modes in %mm0. See ix86_return_in_memory for where
- we prevent this case when mmx is not available. */
- if ((VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8))
- return FIRST_MMX_REG;
+ we normally prevent this case when mmx is not available. However
+ some ABIs may require the result to be returned like DImode. */
+ if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
+ return TARGET_MMX ? FIRST_MMX_REG : 0;
/* 16-byte vector modes in %xmm0. See ix86_return_in_memory for where
- we prevent this case when sse is not available. */
+ we prevent this case when sse is not available. However some ABIs
+ may require the result to be returned like integer TImode. */
if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
- return FIRST_SSE_REG;
+ return TARGET_SSE ? FIRST_SSE_REG : 0;
/* Decimal floating point values can go in %eax, unlike other float modes. */
if (DECIMAL_FLOAT_MODE_P (mode))
return "";
}
+/* Output code for x87 ffreep insn. The OPNO argument, which may only
+ have the values zero or one, indicates the ffreep insn's operand
+ from the OPERANDS array. */
+
+static const char *
+output_387_ffreep (rtx *operands ATTRIBUTE_UNUSED, int opno)
+{
+ if (TARGET_USE_FFREEP)
+#if HAVE_AS_IX86_FFREEP
+ return opno ? "ffreep\t%y1" : "ffreep\t%y0";
+#else
+ switch (REGNO (operands[opno]))
+ {
+ case FIRST_STACK_REG + 0: return ".word\t0xc0df";
+ case FIRST_STACK_REG + 1: return ".word\t0xc1df";
+ case FIRST_STACK_REG + 2: return ".word\t0xc2df";
+ case FIRST_STACK_REG + 3: return ".word\t0xc3df";
+ case FIRST_STACK_REG + 4: return ".word\t0xc4df";
+ case FIRST_STACK_REG + 5: return ".word\t0xc5df";
+ case FIRST_STACK_REG + 6: return ".word\t0xc6df";
+ case FIRST_STACK_REG + 7: return ".word\t0xc7df";
+ }
+#endif
+
+ return opno ? "fstp\t%y1" : "fstp\t%y0";
+}
+
+
/* Output code for INSN to compare OPERANDS. EFLAGS_P is 1 when fcomi
should be used. UNORDERED_P is true when fucom should be used. */
if (stack_top_dies)
{
output_asm_insn ("ftst\n\tfnstsw\t%0", operands);
- return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+ return output_387_ffreep (operands, 1);
}
else
return "ftst\n\tfnstsw\t%0";
output_asm_insn ("fucomip\t{%y1, %0|%0, %y1}", operands);
else
output_asm_insn ("fcomip\t{%y1, %0|%0, %y1}", operands);
- return TARGET_USE_FFREEP ? "ffreep\t%y0" : "fstp\t%y0";
+ return output_387_ffreep (operands, 0);
}
else
{
{
case V2SImode:
case V2SFmode:
- if (!mmx_ok && !TARGET_SSE)
+ if (!mmx_ok)
return false;
/* FALLTHRU */
{
case V2SFmode:
case V2SImode:
- if (!mmx_ok && !TARGET_SSE)
+ if (!mmx_ok)
return false;
/* FALLTHRU */
if (REG_P (operands[1])
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
{
- if (REGNO (operands[0]) == FIRST_STACK_REG
- && TARGET_USE_FFREEP)
- return "ffreep\t%y0";
+ if (REGNO (operands[0]) == FIRST_STACK_REG)
+ return output_387_ffreep (operands, 0);
return "fstp\t%y0";
}
if (STACK_TOP_P (operands[0]))