if (GET_CODE (op0) == SUBREG)
op0 = SUBREG_REG (op0);
- /* We must support XFmode loads into general registers for stdarg/vararg
- and unprototyped calls. We split them into DImode loads for convenience.
- We don't need XFmode stores from general regs, because a stdarg/vararg
- routine does a block store to memory of unnamed arguments. */
+ /* We must support XFmode loads into general registers for stdarg/vararg,
+ unprototyped calls, and a rare case where a long double is passed as
+ an argument after a float HFA fills the FP registers. We split them into
+ DImode loads for convenience. We also need to support XFmode stores
+ for the last case. This case does not happen for stdarg/vararg routines,
+ because we do a block store to memory of unnamed arguments. */
if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
{
if (GET_CODE (op1) == SUBREG)
op1 = SUBREG_REG (op1);
else
- /* ??? Maybe we should make a SUBREG here? */
op1 = gen_rtx_REG (TImode, REGNO (op1));
emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
abort ();
}
+ if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
+ {
+ /* We're hoping to transform everything that deals with XFmode
+ quantities and GR registers early in the compiler. */
+ if (no_new_pseudos)
+ abort ();
+
+ /* Op0 can't be a GR_REG here, as that case is handled above.
+ If op0 is a register, then we spill op1, so that we now have a
+ MEM operand. This requires creating an XFmode subreg of a TImode reg
+ to force the spill. */
+ if (register_operand (operands[0], XFmode))
+ {
+ rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
+ op1 = gen_rtx_SUBREG (XFmode, op1, 0);
+ operands[1] = spill_xfmode_operand (op1, 0);
+ }
+
+ else if (GET_CODE (operands[0]) == MEM)
+ {
+ rtx in[2];
+
+ in[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]));
+ in[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
+
+ emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
+ emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
+ DONE;
+ }
+
+ else
+ abort ();
+ }
+
if (! reload_in_progress && ! reload_completed)
{
operands[1] = spill_xfmode_operand (operands[1], 0);