summaryrefslogtreecommitdiff
path: root/gcc/config/ia64/ia64.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/ia64/ia64.md')
-rw-r--r--gcc/config/ia64/ia64.md137
1 files changed, 22 insertions, 115 deletions
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 57cd70beba5..18e6cb3ace6 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -736,121 +736,8 @@
(match_operand:XF 1 "general_operand" ""))]
""
{
- rtx op0 = operands[0];
-
- if (GET_CODE (op0) == SUBREG)
- op0 = SUBREG_REG (op0);
-
- /* 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)))
- {
- rtx out[2];
-
- /* We're hoping to transform everything that deals with XFmode
- quantities and GR registers early in the compiler. */
- gcc_assert (!no_new_pseudos);
-
- /* Struct to register can just use TImode instead. */
- if ((GET_CODE (operands[1]) == SUBREG
- && GET_MODE (SUBREG_REG (operands[1])) == TImode)
- || (GET_CODE (operands[1]) == REG
- && GR_REGNO_P (REGNO (operands[1]))))
- {
- rtx op1 = operands[1];
-
- if (GET_CODE (op1) == SUBREG)
- op1 = SUBREG_REG (op1);
- else
- op1 = gen_rtx_REG (TImode, REGNO (op1));
-
- emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
- DONE;
- }
-
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
- operand_subword (operands[1], 0, 0, XFmode));
- emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
- operand_subword (operands[1], 1, 0, XFmode));
- DONE;
- }
-
- /* If the quantity is in a register not known to be GR, spill it. */
- if (register_operand (operands[1], XFmode))
- operands[1] = spill_xfmode_operand (operands[1], 1);
-
- gcc_assert (GET_CODE (operands[1]) == MEM);
-
- out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0));
- out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (op0) + 1);
-
- emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
- emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
- DONE;
- }
-
- 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. */
- gcc_assert (!no_new_pseudos);
-
- /* 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
- {
- rtx in[2];
-
- gcc_assert (GET_CODE (operands[0]) == MEM);
- 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;
- }
- }
-
- if (! reload_in_progress && ! reload_completed)
- {
- operands[1] = spill_xfmode_operand (operands[1], 0);
-
- if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
- {
- rtx memt, memx, in = operands[1];
- if (CONSTANT_P (in))
- in = validize_mem (force_const_mem (XFmode, in));
- if (GET_CODE (in) == MEM)
- memt = adjust_address (in, TImode, 0);
- else
- {
- memt = assign_stack_temp (TImode, 16, 0);
- memx = adjust_address (memt, XFmode, 0);
- emit_move_insn (memx, in);
- }
- emit_move_insn (op0, memt);
- DONE;
- }
-
- if (! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (XFmode, operands[1]);
- }
+ if (ia64_expand_movxf_movrf (XFmode, operands))
+ DONE;
})
;; ??? There's no easy way to mind volatile acquire/release semantics.
@@ -865,6 +752,26 @@
stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
+;; Same as for movxf, but for RFmode.
+(define_expand "movrf"
+ [(set (match_operand:RF 0 "general_operand" "")
+ (match_operand:RF 1 "general_operand" ""))]
+ ""
+{
+ if (ia64_expand_movxf_movrf (RFmode, operands))
+ DONE;
+})
+
+(define_insn "*movrf_internal"
+ [(set (match_operand:RF 0 "destination_operand" "=f,f, m")
+ (match_operand:RF 1 "general_operand" "fG,m,fG"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldf.fill %0 = %1%P1
+ stf.spill %0 = %F1%P0"
+ [(set_attr "itanium_class" "fmisc,fld,stf")])
+
;; Better code generation via insns that deal with TFmode register pairs
;; directly. Same concerns apply as for TImode.
(define_expand "movtf"