aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1994-09-13 10:41:03 -0600
committerJeff Law <law@gcc.gnu.org>1994-09-13 10:41:03 -0600
commit42fbe27f77ed9d0ad0e903430bf44b38af0e5b23 (patch)
treeda4a763c7ddad2782f08e71d5c2e5d19eb0c8d92 /gcc
parent4b303b50bc9e1f6200952822a4bc7376c030ab05 (diff)
downloadgcc-42fbe27f77ed9d0ad0e903430bf44b38af0e5b23.zip
gcc-42fbe27f77ed9d0ad0e903430bf44b38af0e5b23.tar.gz
gcc-42fbe27f77ed9d0ad0e903430bf44b38af0e5b23.tar.bz2
pa.c (emit_move_sequence): Handle secondary FP load/store reloads of the form (subreg (mem (plus (reg)...
* pa.c (emit_move_sequence): Handle secondary FP load/store reloads of the form (subreg (mem (plus (reg) (disp)))). (secondary_reload_class): A secondary register is needed to handle out-of-range FP loads and stores. * pa.md (reload_indf, reload_outdf): New expanders. (reload_insf, reload_outsf): Likewise. From-SVN: r8077
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/pa/pa.c38
-rw-r--r--gcc/config/pa/pa.md66
2 files changed, 95 insertions, 9 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 6adca1b..0e74080 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -769,26 +769,37 @@ emit_move_sequence (operands, mode, scratch_reg)
register rtx operand1 = operands[1];
/* Handle secondary reloads for loads/stores of FP registers from
- REG+D addresses where D does not fit in 5 bits. */
+ REG+D addresses where D does not fit in 5 bits, including
+ (subreg (mem (addr)) cases. */
if (fp_reg_operand (operand0, mode)
- && GET_CODE (operand1) == MEM
- /* Using DFmode forces only short displacements be be
- recognized as valid in reg+d addressing modes. */
- && ! memory_address_p (DFmode, XEXP (operand1, 0))
+ && ((GET_CODE (operand1) == MEM
+ && ! memory_address_p (DFmode, XEXP (operand1, 0)))
+ || ((GET_CODE (operand1) == SUBREG
+ && GET_CODE (XEXP (operand1, 0)) == MEM
+ && !memory_address_p (DFmode, XEXP (XEXP (operand1, 0), 0)))))
&& scratch_reg)
{
+ if (GET_CODE (operand1) == SUBREG)
+ operand1 = XEXP (operand1, 0);
+
+ scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg));
emit_move_insn (scratch_reg, XEXP (operand1, 0));
emit_insn (gen_rtx (SET, VOIDmode, operand0, gen_rtx (MEM, mode,
scratch_reg)));
return 1;
}
else if (fp_reg_operand (operand1, mode)
- && GET_CODE (operand0) == MEM
- /* Using DFmode forces only short displacements be be
- recognized as valid in reg+d addressing modes. */
- && ! memory_address_p (DFmode, XEXP (operand0, 0))
+ && ((GET_CODE (operand0) == MEM
+ && ! memory_address_p (DFmode, XEXP (operand0, 0)))
+ || ((GET_CODE (operand0) == SUBREG)
+ && GET_CODE (XEXP (operand0, 0)) == MEM
+ && !memory_address_p (DFmode, XEXP (XEXP (operand0, 0), 0))))
&& scratch_reg)
{
+ if (GET_CODE (operand0) == SUBREG)
+ operand0 = XEXP (operand0, 0);
+
+ scratch_reg = gen_rtx (REG, SImode, REGNO (scratch_reg));
emit_move_insn (scratch_reg, XEXP (operand0, 0));
emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, mode, scratch_reg),
operand1));
@@ -3261,6 +3272,15 @@ secondary_reload_class (class, mode, in)
if (class != R1_REGS && symbolic_operand (in, VOIDmode))
return R1_REGS;
+ if (GET_CODE (in) == SUBREG)
+ in = SUBREG_REG (in);
+
+ if (FP_REG_CLASS_P (class)
+ && GET_CODE (in) == MEM
+ && !memory_address_p (DFmode, XEXP (in, 0))
+ && memory_address_p (SImode, XEXP (in, 0)))
+ return GENERAL_REGS;
+
return NO_REGS;
}
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 1ccdffa..254f908 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -1480,6 +1480,39 @@
DONE;
}")
+;; Reloading an SImode or DImode value requires a scratch register if
+;; going in to or out of float point registers.
+
+(define_expand "reload_indf"
+ [(set (match_operand:DF 0 "register_operand" "=Z")
+ (match_operand:DF 1 "general_operand" ""))
+ (clobber (match_operand:DF 2 "register_operand" "=&r"))]
+ ""
+ "
+{
+ if (emit_move_sequence (operands, DFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ DONE;
+}")
+
+(define_expand "reload_outdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "register_operand" "Z"))
+ (clobber (match_operand:DF 2 "register_operand" "=&r"))]
+ ""
+ "
+{
+ if (emit_move_sequence (operands, DFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ DONE;
+}")
+
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
"=f,*r,Q,?o,?Q,f,*&r,*&r")
@@ -1720,6 +1753,39 @@
DONE;
}")
+;; Reloading an SImode or DImode value requires a scratch register if
+;; going in to or out of float point registers.
+
+(define_expand "reload_insf"
+ [(set (match_operand:SF 0 "register_operand" "=Z")
+ (match_operand:SF 1 "general_operand" ""))
+ (clobber (match_operand:SF 2 "register_operand" "=&r"))]
+ ""
+ "
+{
+ if (emit_move_sequence (operands, SFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ DONE;
+}")
+
+(define_expand "reload_outsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "register_operand" "Z"))
+ (clobber (match_operand:SF 2 "register_operand" "=&r"))]
+ ""
+ "
+{
+ if (emit_move_sequence (operands, SFmode, operands[2]))
+ DONE;
+
+ /* We don't want the clobber emitted, so handle this ourselves. */
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+ DONE;
+}")
+
(define_insn ""
[(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand"
"=f,r,f,r,Q,Q")