diff options
author | Jeff Law <law@gcc.gnu.org> | 1994-09-13 10:41:03 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1994-09-13 10:41:03 -0600 |
commit | 42fbe27f77ed9d0ad0e903430bf44b38af0e5b23 (patch) | |
tree | da4a763c7ddad2782f08e71d5c2e5d19eb0c8d92 /gcc | |
parent | 4b303b50bc9e1f6200952822a4bc7376c030ab05 (diff) | |
download | gcc-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.c | 38 | ||||
-rw-r--r-- | gcc/config/pa/pa.md | 66 |
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") |