+Wed Apr 14 10:04:27 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * 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 <hubicka@freesoft.cz>
* i386.c (agi_dependent): Handle push operation more correctly.
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;
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))
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;
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);
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);
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);
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);
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);
rtx op;
enum machine_mode mode;
{
- if (! register_operand (op, mode))
+ if (! reg_operand (op, mode))
return 0;
return c4x_a_register (op);
}
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);
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);
extern int reg_operand ();
+extern int mixed_subreg_operand ();
+
extern int reg_imm_operand ();
extern int r0r1_reg_operand ();
; 8 loadhf_int
; 9 storehf_int
; 10 RSQRF
-
+; 11 loadqf_int
+; 12 storeqf_int
+; 22 rptb_init
;
; C4x FUNCTIONAL UNITS
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"