* config/frv/frv.c (movcc_fp_destination_operand): New.
(gpr_or_memory_operand): Fix typo in comment.
(gpr_or_memory_operand_with_scratch): New.
* config/frv/frv.h (PREDICATE_CODES): Add the two new predicates.
* config/frv/frv.md (movcc_fp, movcc_fp_internal): Use
movcc_fp_destination_operand.
(reload_incc_fp): Use gpr_or_memory_operand_with_scratch.
Legitimize memory addresses using a scratch register.
From-SVN: r94523
+2005-02-01 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/frv/frv.c (movcc_fp_destination_operand): New.
+ (gpr_or_memory_operand): Fix typo in comment.
+ (gpr_or_memory_operand_with_scratch): New.
+ * config/frv/frv.h (PREDICATE_CODES): Add the two new predicates.
+ * config/frv/frv.md (movcc_fp, movcc_fp_internal): Use
+ movcc_fp_destination_operand.
+ (reload_incc_fp): Use gpr_or_memory_operand_with_scratch.
+ Legitimize memory addresses using a scratch register.
+
2005-01-31 Jeff Law <law@redhat.com>
* tree-into-ssa.c (mark_def_sites_global_data): Make KILLS
return FALSE;
}
+/* Return true if we the operand is a valid destination for a movcc_fp
+ instruction. This means rejecting fcc_operands, since we need
+ scratch registers to write to them. */
+
+int
+movcc_fp_destination_operand (rtx op, enum machine_mode mode)
+{
+ if (fcc_operand (op, mode))
+ return FALSE;
+
+ return move_destination_operand (op, mode);
+}
+
/* Look for a SYMBOL_REF of a function in an rtx. We always want to
process these separately from any offsets, such that we add any
offsets to the function descriptor (the actual pointer), not to the
return frv_const_unspec_p (op, &unspec);
}
-/* Return true if operand is a gpr register or a valid memory operation. */
+
+/* Return true if operand is a gpr register or a valid memory operand. */
int
gpr_or_memory_operand (rtx op, enum machine_mode mode)
|| frv_legitimate_memory_operand (op, mode, FALSE));
}
+/* Return true if operand is a gpr register, a valid memory operand,
+ or a memory operand that can be made valid using an additional gpr
+ register. */
+
+int
+gpr_or_memory_operand_with_scratch (rtx op, enum machine_mode mode)
+{
+ rtx addr;
+
+ if (gpr_or_memory_operand (op, mode))
+ return TRUE;
+
+ if (GET_CODE (op) != MEM)
+ return FALSE;
+
+ if (GET_MODE (op) != mode)
+ return FALSE;
+
+ addr = XEXP (op, 0);
+
+ if (GET_CODE (addr) != PLUS)
+ return FALSE;
+
+ if (!integer_register_operand (XEXP (addr, 0), Pmode))
+ return FALSE;
+
+ if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
+ return FALSE;
+
+ return TRUE;
+}
+
/* Return true if operand is a fpr register or a valid memory operation. */
int
CONST_DOUBLE, CONST, \
SYMBOL_REF, LABEL_REF }}, \
{ "move_destination_operand", { REG, SUBREG, MEM }}, \
+ { "movcc_fp_destination_operand", { REG, SUBREG, MEM }}, \
{ "condexec_source_operand", { REG, SUBREG, CONST_INT, MEM, \
CONST_DOUBLE }}, \
{ "condexec_dest_operand", { REG, SUBREG, MEM }}, \
{ "reg_or_0_operand", { REG, SUBREG, CONST_INT }}, \
{ "lr_operand", { REG }}, \
{ "gpr_or_memory_operand", { REG, SUBREG, MEM }}, \
+ { "gpr_or_memory_operand_with_scratch", { REG, SUBREG, MEM }}, \
{ "fpr_or_memory_operand", { REG, SUBREG, MEM }}, \
{ "int12_operand", { CONST_INT }}, \
{ "int_2word_operand", { CONST_INT, CONST_DOUBLE, \
;; to make it conditional on reload.
(define_expand "movcc_fp"
- [(set (match_operand:CC_FP 0 "move_destination_operand" "")
+ [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "")
(match_operand:CC_FP 1 "move_source_operand" ""))]
"TARGET_HAS_FPRS"
"
}")
(define_insn "*movcc_fp_internal"
- [(set (match_operand:CC_FP 0 "move_destination_operand" "=d,d,d,m")
+ [(set (match_operand:CC_FP 0 "movcc_fp_destination_operand" "=d,d,d,m")
(match_operand:CC_FP 1 "move_source_operand" "u,d,m,d"))]
"TARGET_HAS_FPRS && (reload_in_progress || reload_completed)"
"@
(define_expand "reload_incc_fp"
[(match_operand:CC_FP 0 "fcc_operand" "=u")
- (match_operand:CC_FP 1 "memory_operand" "m")
+ (match_operand:CC_FP 1 "gpr_or_memory_operand_with_scratch" "m")
(match_operand:TI 2 "integer_register_operand" "=&d")]
"TARGET_HAS_FPRS"
"
int shift = CC_SHIFT_RIGHT (REGNO (operands[0]));
HOST_WIDE_INT mask;
+ if (!gpr_or_memory_operand (operands[1], CC_FPmode))
+ {
+ rtx addr;
+ rtx temp3 = simplify_gen_subreg (SImode, operands[2], TImode, 12);
+
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
+
+ addr = XEXP (operands[1], 0);
+
+ if (GET_CODE (addr) != PLUS)
+ abort ();
+
+ emit_move_insn (temp3, XEXP (addr, 1));
+
+ operands[1] = replace_equiv_address (operands[1],
+ gen_rtx_PLUS (GET_MODE (addr),
+ XEXP (addr, 0),
+ temp3));
+ }
+
emit_insn (gen_movcc_fp (cc_op2, operands[1]));
if (shift)
emit_insn (gen_ashlsi3 (int_op2, int_op2, GEN_INT (shift)));