diff options
author | Michael Hayes <m.hayes@elec.canterbury.ac.nz> | 1999-04-13 15:38:12 +0000 |
---|---|---|
committer | Michael Hayes <m.hayes@gcc.gnu.org> | 1999-04-13 15:38:12 +0000 |
commit | ebcc44f4ad40870b4cf551647ece950cab07793b (patch) | |
tree | 46bc5e9d9ecbefeba698d9d586f3ecb44872eeec /gcc/config | |
parent | b985a30f322f6e5d744e1b70a6d83e238543d652 (diff) | |
download | gcc-ebcc44f4ad40870b4cf551647ece950cab07793b.zip gcc-ebcc44f4ad40870b4cf551647ece950cab07793b.tar.gz gcc-ebcc44f4ad40870b4cf551647ece950cab07793b.tar.bz2 |
c4x.md (storeqf_int, [...]): Add new patterns with corresponding splitters to handle moves of floating point...
* 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.
From-SVN: r26413
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/c4x/c4x.c | 90 | ||||
-rw-r--r-- | gcc/config/c4x/c4x.h | 2 | ||||
-rw-r--r-- | gcc/config/c4x/c4x.md | 96 |
3 files changed, 179 insertions, 9 deletions
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index e8cee04..61cf7b7 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,11 +2704,30 @@ 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; enum machine_mode mode ATTRIBUTE_UNUSED; @@ -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 347ce2c..743e8e86 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 ab96ddd..97f67a5 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" |