diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 8 | ||||
-rw-r--r-- | gcc/config/sh/sh.md | 39 |
3 files changed, 49 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8eaad55..612294c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-12-06 Dhananjay Deshpande <dhananjayd@kpit.com> + + * gcc/config/sh/sh.c (calc_live_regs): Save fpscr only if target has + FPU. + (push): Generate push_fpscr. + (pop): Generate pop_fpscr. + * gcc/config/sh/sh.md : Add define_expand "push_fpscr", "pop_fpscr". + (fpu_switch): Add alternative to push fpscr. Enable for TARGET_SH3E. + Fri Dec 6 19:36:24 2002 J"orn Rennecke <joern.rennecke@superh.com> * sh.c (dump_table): DImode pool constants need only 32 bit alignment. diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5a31c84..c33b57e 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -4305,6 +4305,8 @@ push (rn) rtx x; if (rn == FPUL_REG) x = gen_push_fpul (); + else if (rn == FPSCR_REG) + x = gen_push_fpscr (); else if (TARGET_SH4 && TARGET_FMOVD && ! TARGET_FPU_SINGLE && FP_OR_XD_REGISTER_P (rn)) { @@ -4333,6 +4335,8 @@ pop (rn) rtx x; if (rn == FPUL_REG) x = gen_pop_fpul (); + else if (rn == FPSCR_REG) + x = gen_pop_fpscr (); else if (TARGET_SH4 && TARGET_FMOVD && ! TARGET_FPU_SINGLE && FP_OR_XD_REGISTER_P (rn)) { @@ -4431,7 +4435,9 @@ calc_live_regs (count_ptr, live_regs_mask) && pr_live)) && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM && reg != RETURN_ADDRESS_POINTER_REGNUM - && reg != T_REG && reg != GBR_REG) + && reg != T_REG && reg != GBR_REG + /* Push fpscr only on targets which have FPU */ + && (reg != FPSCR_REG || TARGET_FPU_ANY)) : (/* Only push those regs which are used and need to be saved. */ (TARGET_SHCOMPACT && flag_pic diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 835b411..e545b0a 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -3335,6 +3335,32 @@ "TARGET_SH1 && ! TARGET_SH5" "") +(define_expand "push_fpscr" + [(const_int 0)] + "TARGET_SH3E" + " +{ + rtx insn = emit_insn (gen_fpu_switch (gen_rtx (MEM, PSImode, + gen_rtx (PRE_DEC, Pmode, + stack_pointer_rtx)), + get_fpscr_rtx ())); + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX); + DONE; +}") + +(define_expand "pop_fpscr" + [(const_int 0)] + "TARGET_SH3E" + " +{ + rtx insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), + gen_rtx (MEM, PSImode, + gen_rtx (POST_INC, Pmode, + stack_pointer_rtx)))); + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_INC, stack_pointer_rtx, NULL_RTX); + DONE; +}") + ;; These two patterns can happen as the result of optimization, when ;; comparisons get simplified to a move of zero or 1 into the T reg. ;; They don't disappear completely, because the T reg is a fixed hard reg. @@ -7853,9 +7879,9 @@ ;; The mac_gp type for r/!c might look a bit odd, but it actually schedules ;; like a mac -> gpr move. (define_insn "fpu_switch" - [(set (match_operand:PSI 0 "register_operand" "=c,c,r,c,c,r,m,r") - (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c"))] - "TARGET_SH4 + [(set (match_operand:PSI 0 "general_movdst_operand" "=c,c,r,c,c,r,m,r,<") + (match_operand:PSI 1 "general_movsrc_operand" "c,>,m,m,r,r,r,!c,c"))] + "TARGET_SH3E && (! reload_completed || true_regnum (operands[0]) != FPSCR_REG || GET_CODE (operands[1]) != MEM @@ -7868,9 +7894,10 @@ lds %1,fpscr mov %1,%0 mov.l %1,%0 - sts fpscr,%0" - [(set_attr "length" "0,2,2,4,2,2,2,2") - (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp")]) + sts fpscr,%0 + sts.l fpscr,%0" + [(set_attr "length" "0,2,2,4,2,2,2,2,2") + (set_attr "type" "nil,mem_fpscr,load,mem_fpscr,gp_fpscr,move,store,mac_gp,store")]) (define_split [(set (reg:PSI FPSCR_REG) |