return fpscr_rtx;
}
+static GTY(()) tree fpscr_values;
+
+static void
+emit_fpu_switch (rtx scratch, int index)
+{
+ rtx dst, src;
+
+ if (fpscr_values == NULL)
+ {
+ tree t;
+
+ t = build_index_type (integer_one_node);
+ t = build_array_type (integer_type_node, t);
+ t = build_decl (VAR_DECL, get_identifier ("__fpscr_values"), t);
+ DECL_ARTIFICIAL (t) = 1;
+ DECL_IGNORED_P (t) = 1;
+ DECL_EXTERNAL (t) = 1;
+ TREE_STATIC (t) = 1;
+ TREE_USED (t) = 1;
+
+ fpscr_values = t;
+ }
+
+ src = DECL_RTL (fpscr_values);
+ if (no_new_pseudos)
+ {
+ emit_move_insn (scratch, XEXP (src, 0));
+ if (index != 0)
+ emit_insn (gen_addsi3 (scratch, scratch, GEN_INT (index * 4)));
+ src = adjust_automodify_address (src, PSImode, scratch, index * 4);
+ }
+ else
+ src = adjust_address (src, PSImode, index * 4);
+
+ dst = get_fpscr_rtx ();
+ emit_move_insn (dst, src);
+}
+
void
emit_sf_insn (rtx pat)
{
fpscr_set_from_mem (int mode, HARD_REG_SET regs_live)
{
enum attr_fp_mode fp_mode = mode;
+ enum attr_fp_mode norm_mode = ACTUAL_NORMAL_MODE (FP_MODE);
rtx addr_reg = get_free_reg (regs_live);
- if (fp_mode == (enum attr_fp_mode) ACTUAL_NORMAL_MODE (FP_MODE))
- emit_insn (gen_fpu_switch1 (addr_reg));
- else
- emit_insn (gen_fpu_switch0 (addr_reg));
+ emit_fpu_switch (addr_reg, fp_mode == norm_mode);
}
/* Is the given character a logical line separator for the assembler? */
;; ??? All patterns should have a type attribute.
-(define_expand "fpu_switch0"
- [(set (match_operand:SI 0 "" "") (match_dup 2))
- (set (match_dup 1) (mem:PSI (match_dup 0)))]
- "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
- "
-{
- operands[1] = get_fpscr_rtx ();
- operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
- if (flag_pic)
- operands[2] = legitimize_pic_address (operands[2], SImode,
- no_new_pseudos ? operands[0] : 0);
-}")
-
-(define_expand "fpu_switch1"
- [(set (match_operand:SI 0 "" "") (match_dup 2))
- (set (match_dup 3) (plus:SI (match_dup 0) (const_int 4)))
- (set (match_dup 1) (mem:PSI (match_dup 3)))]
- "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
- "
-{
- operands[1] = get_fpscr_rtx ();
- operands[2] = gen_rtx_SYMBOL_REF (SImode, \"__fpscr_values\");
- if (flag_pic)
- operands[2] = legitimize_pic_address (operands[2], SImode,
- no_new_pseudos ? operands[0] : 0);
- operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (SImode);
-}")
-
(define_expand "movpsi"
[(set (match_operand:PSI 0 "register_operand" "")
(match_operand:PSI 1 "general_movsrc_operand" ""))]
[(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
+(define_peephole2
[(set (reg:PSI FPSCR_REG)
(mem:PSI (match_operand:SI 0 "register_operand" "")))]
- "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && find_regno_note (insn, REG_DEAD, true_regnum (operands[0]))"
- [(set (match_dup 0) (match_dup 0))]
- "
+ "(TARGET_SH4 || TARGET_SH2A_DOUBLE) && peep2_reg_dead_p (1, operands[0])"
+ [(const_int 0)]
{
- rtx mem, insn;
+ rtx fpscr, mem, new_insn;
+ fpscr = SET_DEST (PATTERN (curr_insn));
mem = SET_SRC (PATTERN (curr_insn));
- mem = change_address (mem, PSImode, gen_rtx_POST_INC (Pmode, operands[0]));
- insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), mem));
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
-}")
+ mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
+
+ new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
+ REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
+ DONE;
+})
(define_split
[(set (reg:PSI FPSCR_REG)
(mem:PSI (match_operand:SI 0 "register_operand" "")))]
- "(TARGET_SH4 || TARGET_SH2A_DOUBLE)"
- [(set (match_dup 0) (plus:SI (match_dup 0) (const_int -4)))]
- "
+ "(TARGET_SH4 || TARGET_SH2A_DOUBLE)
+ && (flag_peephole2 ? flow2_completed : reload_completed)"
+ [(const_int 0)]
{
- rtx mem, insn;
+ rtx fpscr, mem, new_insn;
+ fpscr = SET_DEST (PATTERN (curr_insn));
mem = SET_SRC (PATTERN (curr_insn));
- mem = change_address (mem, PSImode, gen_rtx_POST_INC (Pmode, operands[0]));
- insn = emit_insn (gen_fpu_switch (get_fpscr_rtx (), mem));
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
-}")
+ mem = replace_equiv_address (mem, gen_rtx_POST_INC (Pmode, operands[0]));
+
+ new_insn = emit_insn (gen_fpu_switch (fpscr, mem));
+ REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_INC, operands[0], NULL_RTX);
+
+ if (!find_regno_note (curr_insn, REG_DEAD, true_regnum (operands[0])))
+ emit_insn (gen_addsi3 (operands[0], operands[0], GEN_INT (-4)));
+ DONE;
+})
;; ??? This uses the fp unit, but has no type indicating that.
;; If we did that, this would either give a bogus latency or introduce