diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 57a18250825..929a5700afd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +Wed Apr 14 10:04:27 1999 Michael Hayes + + * config/c4x/c4x.md (storeqf_int, storeqf_int_clobber, loadqf_int, + loadqf_int_clobber): Add new patterns with corresponding splitters + to handle moves of floating point values into and out of intager + registers by using memory. + + * config/c4x/c4x.c (c4x_check_legit_addr): Disallow PRE_INC for modes + other than QFmode and QImode. + (mixed_subreg_operand): New function. + (c4x_emit_move_sequence): If moving a floating point value into or + out of an integer register, use the new patterns storeqf_int_clobber + or loadqf_int_clobber. + (reg_imm_operand, *_reg_operand): Call reg_operand instead of + register_operand. + (reg_operand, src_operand): Disallow operand if it satisifes + mixed_subreg_operand. + + * config/c4x/c4x.h (mixed_subreg_operand): Add prototype. + Tue Apr 13 14:49:13 1999 Jan Hubicka * i386.c (agi_dependent): Handle push operation more correctly. diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index e8cee04cf40..61cf7b70505 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -1099,6 +1099,56 @@ c4x_emit_move_sequence (operands, mode) gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0))); } + if (GET_CODE (op0) == SUBREG + && mixed_subreg_operand (op0, mode)) + { + /* We should only generate these mixed mode patterns + during RTL generation. If we need do it later on + then we'll have to emit patterns that won't clobber CC. */ + if (reload_in_progress || reload_completed) + abort (); + if (GET_MODE (SUBREG_REG (op0)) == QImode) + op0 = SUBREG_REG (op0); + else if (GET_MODE (SUBREG_REG (op0)) == HImode) + { + op0 = copy_rtx (op0); + PUT_MODE (op0, QImode); + } + else + abort (); + + if (mode == QFmode) + emit_insn (gen_storeqf_int_clobber (op0, op1)); + else + abort (); + return 1; + } + + if (GET_CODE (op1) == SUBREG + && mixed_subreg_operand (op1, mode)) + { + /* We should only generate these mixed mode patterns + during RTL generation. If we need do it later on + then we'll have to emit patterns that won't clobber CC. */ + if (reload_in_progress || reload_completed) + abort (); + if (GET_MODE (SUBREG_REG (op1)) == QImode) + op1 = SUBREG_REG (op1); + else if (GET_MODE (SUBREG_REG (op1)) == HImode) + { + op1 = copy_rtx (op1); + PUT_MODE (op1, QImode); + } + else + abort (); + + if (mode == QFmode) + emit_insn (gen_loadqf_int_clobber (op0, op1)); + else + abort (); + return 1; + } + /* Adjust operands in case we have modified them. */ operands[0] = op0; operands[1] = op1; @@ -1250,10 +1300,11 @@ c4x_check_legit_addr (mode, addr, strict) being pushed on the stack. */ case PRE_DEC: + case PRE_INC: case POST_DEC: if (mode != QImode && mode != QFmode) return 0; - case PRE_INC: + case POST_INC: base = XEXP (addr, 0); if (! REG_P (base)) @@ -2653,10 +2704,29 @@ reg_operand (op, mode) rtx op; enum machine_mode mode; { + if (GET_CODE (op) == SUBREG + && GET_MODE (op) == QFmode) + return 0; return register_operand (op, mode); } +int +mixed_subreg_operand (op, mode) + rtx op; + enum machine_mode mode; +{ + /* Allow (subreg:HF (reg:HI)) that be generated for a union of an + int and a long double. */ + if (GET_CODE (op) == SUBREG + && (GET_MODE (op) == QFmode) + && (GET_MODE (SUBREG_REG (op)) == QImode + || GET_MODE (SUBREG_REG (op)) == HImode)) + return 1; + return 0; +} + + int reg_imm_operand (op, mode) rtx op; @@ -2733,7 +2803,7 @@ r0r1_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2748,7 +2818,7 @@ r2r3_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2763,7 +2833,7 @@ ext_low_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2778,7 +2848,7 @@ ext_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2795,7 +2865,7 @@ std_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2810,7 +2880,7 @@ addr_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; return c4x_a_register (op); } @@ -2823,7 +2893,7 @@ index_reg_operand (op, mode) rtx op; enum machine_mode mode; { - if (! register_operand (op, mode)) + if (! reg_operand (op, mode)) return 0; if (GET_CODE (op) == SUBREG) op = SUBREG_REG (op); @@ -2914,6 +2984,10 @@ src_operand (op, mode) rtx op; enum machine_mode mode; { + if (GET_CODE (op) == SUBREG + && mixed_subreg_operand (op, mode)) + return 0; + if (REG_P (op)) return reg_operand (op, mode); diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h index 347ce2c141b..743e8e862fe 100644 --- a/gcc/config/c4x/c4x.h +++ b/gcc/config/c4x/c4x.h @@ -2655,6 +2655,8 @@ extern int reg_or_const_operand (); extern int reg_operand (); +extern int mixed_subreg_operand (); + extern int reg_imm_operand (); extern int r0r1_reg_operand (); diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index ab96ddd57dd..97f67a5c4d6 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -449,7 +449,9 @@ ; 8 loadhf_int ; 9 storehf_int ; 10 RSQRF - +; 11 loadqf_int +; 12 storeqf_int +; 22 rptb_init ; ; C4x FUNCTIONAL UNITS @@ -2968,6 +2970,98 @@ DONE; }") +; This can generate invalid stack slot displacements +(define_split + [(set (match_operand:QI 0 "reg_operand" "=r") + (unspec [(match_operand:QF 1 "reg_operand" "f")] 12))] + "reload_completed" + [(set (match_dup 3) (match_dup 1)) + (set (match_dup 0) (match_dup 2))] + "operands[2] = assign_stack_temp (QImode, GET_MODE_SIZE (QImode), 0); + operands[3] = copy_rtx (operands[2]); + PUT_MODE (operands[3], QFmode);") + + +(define_insn "storeqf_int" + [(set (match_operand:QI 0 "reg_operand" "=r") + (unspec [(match_operand:QF 1 "reg_operand" "f")] 12))] + "" + "#" + [(set_attr "type" "multi")]) + +(define_split + [(parallel [(set (match_operand:QI 0 "reg_operand" "=r") + (unspec [(match_operand:QF 1 "reg_operand" "f")] 12)) + (clobber (reg:CC 21))])] + "reload_completed" + [(set (mem:QF (pre_inc:QI (reg:QI 20))) + (match_dup 1)) + (parallel [(set (match_dup 0) + (mem:QI (post_dec:QI (reg:QI 20)))) + (clobber (reg:CC 21))])] + "") + + +; We need accurate death notes for this... +;(define_peephole +; [(set (match_operand:QF 0 "reg_operand" "=f") +; (match_operand:QF 1 "memory_operand" "m")) +; (set (mem:QF (pre_inc:QI (reg:QI 20))) +; (match_dup 0)) +; (parallel [(set (match_operand:QI 2 "reg_operand" "r") +; (mem:QI (post_dec:QI (reg:QI 20)))) +; (clobber (reg:CC 21))])] +; "" +; "ldiu\\t%1,%0") + +(define_insn "storeqf_int_clobber" + [(parallel [(set (match_operand:QI 0 "reg_operand" "=r") + (unspec [(match_operand:QF 1 "reg_operand" "f")] 12)) + (clobber (reg:CC 21))])] + "" + "#" + [(set_attr "type" "multi")]) + + +; This can generate invalid stack slot displacements +(define_split + [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec [(match_operand:QI 1 "reg_operand" "r")] 11))] + "reload_completed" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (match_dup 3))] + "operands[2] = assign_stack_temp (QImode, GET_MODE_SIZE (QImode), 0); + operands[3] = copy_rtx (operands[2]); + PUT_MODE (operands[3], QFmode);") + + +(define_insn "loadqf_int" + [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec [(match_operand:QI 1 "reg_operand" "r")] 11))] + "" + "#" + [(set_attr "type" "multi")]) + +(define_split + [(parallel [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec [(match_operand:QI 1 "reg_operand" "r")] 11)) + (clobber (reg:CC 21))])] + "reload_completed" + [(set (mem:QI (pre_inc:QI (reg:QI 20))) + (match_dup 1)) + (parallel [(set (match_dup 0) + (mem:QF (post_dec:QI (reg:QI 20)))) + (clobber (reg:CC 21))])] + "") + +(define_insn "loadqf_int_clobber" + [(parallel [(set (match_operand:QF 0 "reg_operand" "=f") + (unspec [(match_operand:QI 1 "reg_operand" "r")] 11)) + (clobber (reg:CC 21))])] + "" + "#" + [(set_attr "type" "multi")]) + ; We must provide an alternative to store to memory in case we have to ; spill a register. (define_insn "movqf_noclobber"