aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorMichael Hayes <m.hayes@elec.canterbury.ac.nz>1999-04-13 15:38:12 +0000
committerMichael Hayes <m.hayes@gcc.gnu.org>1999-04-13 15:38:12 +0000
commitebcc44f4ad40870b4cf551647ece950cab07793b (patch)
tree46bc5e9d9ecbefeba698d9d586f3ecb44872eeec /gcc/config
parentb985a30f322f6e5d744e1b70a6d83e238543d652 (diff)
downloadgcc-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.c90
-rw-r--r--gcc/config/c4x/c4x.h2
-rw-r--r--gcc/config/c4x/c4x.md96
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"