sparc.c (fp_sethi_p, [...]): New functions.
* config/sparc/sparc.c (fp_sethi_p, fp_mov_p, fp_high_losum_p): New functions. * config/sparc/sparc-protos.h: Add them. * config/sparc/sparc.h: Add them to PREDICATE_CODES. (EXTRA_CONSTRAINT_BASE): New macro, handling Q, R, and S constraints which use those helpers. (EXTRA_CONSTRAINT): Use this new macro. * md.texi: Update sparc target constraints documentation. * config/sparc/sparc.md (clear_sf, clear_sfp, movsf_const_intreg, movsf_const_high, movsf_const_lo, movsf_insn): Delete. (movsf_insn_novis_liveg0, movsf_insn_novis_noliveg0, movsf_insn_vis, movsf_lo_sum, movsf_high): New patterns. (movsf high/lo_sum split): Rework for new patterns. (movsf expander): Allow storing fp_zero to memory if ! live_g0. From-SVN: r30857
This commit is contained in:
parent
acce043733
commit
6219012805
@ -1,3 +1,20 @@
|
||||
1999-12-10 David S. Miller <davem@redhat.com>
|
||||
|
||||
* config/sparc/sparc.c (fp_sethi_p, fp_mov_p, fp_high_losum_p):
|
||||
New functions.
|
||||
* config/sparc/sparc-protos.h: Add them.
|
||||
* config/sparc/sparc.h: Add them to PREDICATE_CODES.
|
||||
(EXTRA_CONSTRAINT_BASE): New macro, handling Q, R, and S
|
||||
constraints which use those helpers.
|
||||
(EXTRA_CONSTRAINT): Use this new macro.
|
||||
* md.texi: Update sparc target constraints documentation.
|
||||
* config/sparc/sparc.md (clear_sf, clear_sfp, movsf_const_intreg,
|
||||
movsf_const_high, movsf_const_lo, movsf_insn): Delete.
|
||||
(movsf_insn_novis_liveg0, movsf_insn_novis_noliveg0,
|
||||
movsf_insn_vis, movsf_lo_sum, movsf_high): New patterns.
|
||||
(movsf high/lo_sum split): Rework for new patterns.
|
||||
(movsf expander): Allow storing fp_zero to memory if ! live_g0.
|
||||
|
||||
1999-12-09 Gavin Romig-Koch <gavin@cetus.cygnus.com>
|
||||
|
||||
* c-common.c (c_common_nodes_and_builtins):
|
||||
|
@ -124,6 +124,9 @@ extern int emit_move_sequence PARAMS ((rtx, enum machine_mode));
|
||||
extern int extend_op PARAMS ((rtx, enum machine_mode));
|
||||
extern int fcc_reg_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int fp_zero_operand PARAMS ((rtx));
|
||||
extern int fp_sethi_p PARAMS ((rtx));
|
||||
extern int fp_mov_p PARAMS ((rtx));
|
||||
extern int fp_high_losum_p PARAMS ((rtx));
|
||||
extern int icc_or_fcc_reg_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int label_ref_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int mem_min_alignment PARAMS ((rtx, int));
|
||||
|
@ -406,6 +406,85 @@ fp_zero_operand (op)
|
||||
return (REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r));
|
||||
}
|
||||
|
||||
/* Nonzero if OP is a floating point constant which can
|
||||
be loaded into an integer register using a single
|
||||
sethi instruction. */
|
||||
|
||||
int
|
||||
fp_sethi_p (op)
|
||||
rtx op;
|
||||
{
|
||||
if (GET_CODE (op) == CONST_DOUBLE)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
|
||||
if (REAL_VALUES_EQUAL (r, dconst0) &&
|
||||
! REAL_VALUE_MINUS_ZERO (r))
|
||||
return 0;
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
if (SPARC_SETHI_P (i))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nonzero if OP is a floating point constant which can
|
||||
be loaded into an integer register using a single
|
||||
mov instruction. */
|
||||
|
||||
int
|
||||
fp_mov_p (op)
|
||||
rtx op;
|
||||
{
|
||||
if (GET_CODE (op) == CONST_DOUBLE)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
|
||||
if (REAL_VALUES_EQUAL (r, dconst0) &&
|
||||
! REAL_VALUE_MINUS_ZERO (r))
|
||||
return 0;
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
if (SPARC_SIMM13_P (i))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nonzero if OP is a floating point constant which can
|
||||
be loaded into an integer register using a high/losum
|
||||
instruction sequence. */
|
||||
|
||||
int
|
||||
fp_high_losum_p (op)
|
||||
rtx op;
|
||||
{
|
||||
/* The constraints calling this should only be in
|
||||
SFmode move insns, so any constant which cannot
|
||||
be moved using a single insn will do. */
|
||||
if (GET_CODE (op) == CONST_DOUBLE)
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
|
||||
if (REAL_VALUES_EQUAL (r, dconst0) &&
|
||||
! REAL_VALUE_MINUS_ZERO (r))
|
||||
return 0;
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
if (! SPARC_SETHI_P (i)
|
||||
&& ! SPARC_SIMM13_P (i))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nonzero if OP is an integer register. */
|
||||
|
||||
int
|
||||
@ -1112,6 +1191,10 @@ input_operand (op, mode)
|
||||
if (register_operand (op, mode))
|
||||
return 1;
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& GET_CODE (op) == CONST_DOUBLE)
|
||||
return 1;
|
||||
|
||||
/* If this is a SUBREG, look inside so that we handle
|
||||
paradoxical ones. */
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
|
@ -2283,12 +2283,27 @@ LFLGRET"ID":\n\
|
||||
|
||||
/* Optional extra constraints for this machine.
|
||||
|
||||
'Q' handles floating point constants which can be moved into
|
||||
an integer register with a single sethi instruction.
|
||||
|
||||
'R' handles floating point constants which can be moved into
|
||||
an integer register with a single mov instruction.
|
||||
|
||||
'S' handles floating point constants which can be moved into
|
||||
an integer register using a high/lo_sum sequence.
|
||||
|
||||
'T' handles memory addresses where the alignment is known to
|
||||
be at least 8 bytes.
|
||||
|
||||
`U' handles all pseudo registers or a hard even numbered
|
||||
integer register, needed for ldd/std instructions. */
|
||||
|
||||
#define EXTRA_CONSTRAINT_BASE(OP, C) \
|
||||
((C) == 'Q' ? fp_sethi_p(OP) \
|
||||
: (C) == 'R' ? fp_mov_p(OP) \
|
||||
: (C) == 'S' ? fp_high_losum_p(OP) \
|
||||
: 0)
|
||||
|
||||
#ifndef REG_OK_STRICT
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as an index
|
||||
@ -2303,12 +2318,13 @@ LFLGRET"ID":\n\
|
||||
/* 'T', 'U' are for aligned memory loads which aren't needed for v9. */
|
||||
|
||||
#define EXTRA_CONSTRAINT(OP, C) \
|
||||
((! TARGET_ARCH64 && (C) == 'T') \
|
||||
? (mem_min_alignment (OP, 8)) \
|
||||
: ((! TARGET_ARCH64 && (C) == 'U') \
|
||||
? (register_ok_for_ldd (OP)) \
|
||||
: 0))
|
||||
|
||||
(EXTRA_CONSTRAINT_BASE(OP, C) \
|
||||
|| ((! TARGET_ARCH64 && (C) == 'T') \
|
||||
? (mem_min_alignment (OP, 8)) \
|
||||
: ((! TARGET_ARCH64 && (C) == 'U') \
|
||||
? (register_ok_for_ldd (OP)) \
|
||||
: 0)))
|
||||
|
||||
#else
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||
@ -2317,14 +2333,16 @@ LFLGRET"ID":\n\
|
||||
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||
|
||||
#define EXTRA_CONSTRAINT(OP, C) \
|
||||
((! TARGET_ARCH64 && (C) == 'T') \
|
||||
? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
|
||||
: ((! TARGET_ARCH64 && (C) == 'U') \
|
||||
? (GET_CODE (OP) == REG \
|
||||
&& (REGNO (OP) < FIRST_PSEUDO_REGISTER \
|
||||
|| reg_renumber[REGNO (OP)] >= 0) \
|
||||
&& register_ok_for_ldd (OP)) \
|
||||
: 0))
|
||||
(EXTRA_CONSTRAINT_BASE(OP, C) \
|
||||
|| ((! TARGET_ARCH64 && (C) == 'T') \
|
||||
? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
|
||||
: ((! TARGET_ARCH64 && (C) == 'U') \
|
||||
? (GET_CODE (OP) == REG \
|
||||
&& (REGNO (OP) < FIRST_PSEUDO_REGISTER \
|
||||
|| reg_renumber[REGNO (OP)] >= 0) \
|
||||
&& register_ok_for_ldd (OP)) \
|
||||
: 0)))
|
||||
|
||||
#endif
|
||||
|
||||
/* Should gcc use [%reg+%lo(xx)+offset] addresses? */
|
||||
@ -3309,6 +3327,9 @@ do { \
|
||||
#define PREDICATE_CODES \
|
||||
{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
|
||||
{"fp_zero_operand", {CONST_DOUBLE}}, \
|
||||
{"fp_sethi_p", {CONST_DOUBLE}}, \
|
||||
{"fp_mov_p", {CONST_DOUBLE}}, \
|
||||
{"fp_high_losum_p", {CONST_DOUBLE}}, \
|
||||
{"intreg_operand", {SUBREG, REG}}, \
|
||||
{"fcc_reg_operand", {REG}}, \
|
||||
{"icc_or_fcc_reg_operand", {REG}}, \
|
||||
|
@ -37,12 +37,10 @@
|
||||
;; 9 sethh
|
||||
;; 10 setlm
|
||||
;; 11 embmedany_sethi, embmedany_brsum
|
||||
;; 12 movsf_const_high
|
||||
;; 13 embmedany_textuhi
|
||||
;; 14 embmedany_texthi
|
||||
;; 15 embmedany_textulo
|
||||
;; 16 embmedany_textlo
|
||||
;; 17 movsf_const_lo
|
||||
;; 18 sethm
|
||||
;; 19 setlo
|
||||
;;
|
||||
@ -2820,83 +2818,165 @@
|
||||
|
||||
;; Floating point move insns
|
||||
|
||||
(define_insn "*clear_sf"
|
||||
[(set (match_operand:SF 0 "register_operand" "=f")
|
||||
(match_operand:SF 1 "const_double_operand" ""))]
|
||||
"TARGET_VIS
|
||||
&& fp_zero_operand (operands[1])"
|
||||
"fzeros\\t%0"
|
||||
[(set_attr "type" "fpmove")
|
||||
(define_insn "*movsf_insn_novis_liveg0"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
|
||||
(match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*r"))]
|
||||
"(TARGET_FPU && ! TARGET_VIS && TARGET_LIVE_G0)
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode))"
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& (which_alternative == 2
|
||||
|| which_alternative == 3
|
||||
|| which_alternative == 4))
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
operands[1] = GEN_INT (i);
|
||||
}
|
||||
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return \"fmovs\\t%1, %0\";
|
||||
case 1:
|
||||
return \"and\\t%0, 0, %0\";
|
||||
case 2:
|
||||
return \"sethi\\t%%hi(%a1), %0\";
|
||||
case 3:
|
||||
return \"mov\\t%1, %0\";
|
||||
case 4:
|
||||
return \"#\";
|
||||
case 5:
|
||||
case 6:
|
||||
return \"ld\\t%1, %0\";
|
||||
case 7:
|
||||
case 8:
|
||||
return \"st\\t%1, %0\";
|
||||
}
|
||||
}"
|
||||
[(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_insn "*clear_sfp"
|
||||
[(set (match_operand:SF 0 "memory_operand" "=m")
|
||||
(match_operand:SF 1 "const_double_operand" ""))]
|
||||
"! TARGET_LIVE_G0
|
||||
&& fp_zero_operand (operands[1])"
|
||||
"st\\t%%g0, %0"
|
||||
[(set_attr "type" "store")
|
||||
(define_insn "*movsf_insn_novis_noliveg0"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
|
||||
(match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*rG"))]
|
||||
"(TARGET_FPU && ! TARGET_VIS && ! TARGET_LIVE_G0)
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode)
|
||||
|| fp_zero_operand (operands[1]))"
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& (which_alternative == 2
|
||||
|| which_alternative == 3
|
||||
|| which_alternative == 4))
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
operands[1] = GEN_INT (i);
|
||||
}
|
||||
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return \"fmovs\\t%1, %0\";
|
||||
case 1:
|
||||
return \"clr\\t%0\";
|
||||
case 2:
|
||||
return \"sethi\\t%%hi(%a1), %0\";
|
||||
case 3:
|
||||
return \"mov\\t%1, %0\";
|
||||
case 4:
|
||||
return \"#\";
|
||||
case 5:
|
||||
case 6:
|
||||
return \"ld\\t%1, %0\";
|
||||
case 7:
|
||||
case 8:
|
||||
return \"st\\t%r1, %0\";
|
||||
}
|
||||
}"
|
||||
[(set_attr "type" "fpmove,move,move,move,*,load,fpload,fpstore,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_insn "*movsf_const_intreg"
|
||||
[(set (match_operand:SF 0 "register_operand" "=f,r")
|
||||
(match_operand:SF 1 "const_double_operand" "m#F,F"))]
|
||||
"TARGET_FPU"
|
||||
(define_insn "*movsf_insn_vis"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
|
||||
(match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))]
|
||||
"(TARGET_FPU && TARGET_VIS)
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode)
|
||||
|| fp_zero_operand (operands[1]))"
|
||||
"*
|
||||
{
|
||||
if (GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& (which_alternative == 3
|
||||
|| which_alternative == 4
|
||||
|| which_alternative == 5))
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
operands[1] = GEN_INT (i);
|
||||
}
|
||||
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return \"fmovs\\t%1, %0\";
|
||||
case 1:
|
||||
return \"fzeros\\t%0\";
|
||||
case 2:
|
||||
return \"clr\\t%0\";
|
||||
case 3:
|
||||
return \"sethi\\t%%hi(%a1), %0\";
|
||||
case 4:
|
||||
return \"mov\\t%1, %0\";
|
||||
case 5:
|
||||
return \"#\";
|
||||
case 6:
|
||||
case 7:
|
||||
return \"ld\\t%1, %0\";
|
||||
case 8:
|
||||
case 9:
|
||||
return \"st\\t%r1, %0\";
|
||||
}
|
||||
}"
|
||||
[(set_attr "type" "fpmove,fpmove,move,move,move,*,load,fpload,fpstore,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_insn "*movsf_lo_sum"
|
||||
[(set (match_operand:SF 0 "register_operand" "")
|
||||
(lo_sum:SF (match_operand:SF 1 "register_operand" "")
|
||||
(match_operand:SF 2 "const_double_operand" "")))]
|
||||
"TARGET_FPU && fp_high_losum_p (operands[2])"
|
||||
"*
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
|
||||
if (which_alternative == 0)
|
||||
return \"ld\\t%1, %0\";
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
if (SPARC_SIMM13_P (i) || SPARC_SETHI_P (i))
|
||||
{
|
||||
operands[1] = GEN_INT (i);
|
||||
if (SPARC_SIMM13_P (INTVAL (operands[1])))
|
||||
return \"mov\\t%1, %0\";
|
||||
else if (SPARC_SETHI_P (INTVAL (operands[1])))
|
||||
return \"sethi\\t%%hi(%a1), %0\";
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
else
|
||||
return \"#\";
|
||||
operands[2] = GEN_INT (i);
|
||||
return \"or\\t%1, %%lo(%a2), %0\";
|
||||
}"
|
||||
[(set_attr "type" "move")
|
||||
(set_attr "length" "1,2")])
|
||||
|
||||
;; There isn't much I can do about this, if I change the
|
||||
;; mode then flow info gets really confused because the
|
||||
;; destination no longer looks the same. Ho hum...
|
||||
(define_insn "*movsf_const_high"
|
||||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||||
(unspec:SF [(match_operand 1 "const_int_operand" "")] 12))]
|
||||
""
|
||||
"sethi\\t%%hi(%a1), %0"
|
||||
[(set_attr "type" "move")
|
||||
[(set_attr "type" "ialu")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_insn "*movsf_const_lo"
|
||||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||||
(unspec:SF [(match_operand:SF 1 "register_operand" "r")
|
||||
(match_operand 2 "const_int_operand" "")] 17))]
|
||||
""
|
||||
"or\\t%1, %%lo(%a2), %0"
|
||||
[(set_attr "type" "move")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_split
|
||||
(define_insn "*movsf_high"
|
||||
[(set (match_operand:SF 0 "register_operand" "")
|
||||
(match_operand:SF 1 "const_double_operand" ""))]
|
||||
"TARGET_FPU
|
||||
&& (GET_CODE (operands[0]) == REG
|
||||
&& REGNO (operands[0]) < 32)"
|
||||
[(set (match_dup 0) (unspec:SF [(match_dup 1)] 12))
|
||||
(set (match_dup 0) (unspec:SF [(match_dup 0) (match_dup 1)] 17))]
|
||||
"
|
||||
(high:SF (match_operand:SF 1 "const_double_operand" "")))]
|
||||
"TARGET_FPU && fp_high_losum_p (operands[1])"
|
||||
"*
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long i;
|
||||
@ -2904,7 +2984,37 @@
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
REAL_VALUE_TO_TARGET_SINGLE (r, i);
|
||||
operands[1] = GEN_INT (i);
|
||||
}")
|
||||
return \"sethi\\t%%hi(%1), %0\";
|
||||
}"
|
||||
[(set_attr "type" "move")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SF 0 "register_operand" "")
|
||||
(match_operand:SF 1 "const_double_operand" ""))]
|
||||
"TARGET_FPU
|
||||
&& fp_high_losum_p (operands[1])
|
||||
&& (GET_CODE (operands[0]) == REG
|
||||
&& REGNO (operands[0]) < 32)"
|
||||
[(set (match_dup 0) (high:SF (match_dup 1)))
|
||||
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
|
||||
|
||||
;; Exactly the same as above, except that all `f' cases are deleted.
|
||||
;; This is necessary to prevent reload from ever trying to use a `f' reg
|
||||
;; when -mno-fpu.
|
||||
|
||||
(define_insn "*movsf_no_f_insn"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
|
||||
(match_operand:SF 1 "input_operand" "r,m,r"))]
|
||||
"! TARGET_FPU
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode))"
|
||||
"@
|
||||
mov\\t%1, %0
|
||||
ld\\t%1, %0
|
||||
st\\t%1, %0"
|
||||
[(set_attr "type" "move,load,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_expand "movsf"
|
||||
[(set (match_operand:SF 0 "general_operand" "")
|
||||
@ -2933,7 +3043,10 @@
|
||||
/* Handle sets of MEM first. */
|
||||
if (GET_CODE (operands[0]) == MEM)
|
||||
{
|
||||
if (register_operand (operands[1], SFmode))
|
||||
if (register_operand (operands[1], SFmode)
|
||||
|| (! TARGET_LIVE_G0
|
||||
&& GET_CODE (operands[1]) == CONST_DOUBLE
|
||||
&& fp_zero_operand (operands[1])))
|
||||
goto movsf_is_ok;
|
||||
|
||||
if (! reload_in_progress)
|
||||
@ -2964,39 +3077,6 @@
|
||||
;
|
||||
}")
|
||||
|
||||
(define_insn "*movsf_insn"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,r,r,m")
|
||||
(match_operand:SF 1 "input_operand" "f,m,f,r,m,r"))]
|
||||
"TARGET_FPU
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode))"
|
||||
"@
|
||||
fmovs\\t%1, %0
|
||||
ld\\t%1, %0
|
||||
st\\t%1, %0
|
||||
mov\\t%1, %0
|
||||
ld\\t%1, %0
|
||||
st\\t%1, %0"
|
||||
[(set_attr "type" "fpmove,fpload,fpstore,move,load,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
;; Exactly the same as above, except that all `f' cases are deleted.
|
||||
;; This is necessary to prevent reload from ever trying to use a `f' reg
|
||||
;; when -mno-fpu.
|
||||
|
||||
(define_insn "*movsf_no_f_insn"
|
||||
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
|
||||
(match_operand:SF 1 "input_operand" "r,m,r"))]
|
||||
"! TARGET_FPU
|
||||
&& (register_operand (operands[0], SFmode)
|
||||
|| register_operand (operands[1], SFmode))"
|
||||
"@
|
||||
mov\\t%1, %0
|
||||
ld\\t%1, %0
|
||||
st\\t%1, %0"
|
||||
[(set_attr "type" "move,load,store")
|
||||
(set_attr "length" "1")])
|
||||
|
||||
(define_insn "*clear_df"
|
||||
[(set (match_operand:DF 0 "register_operand" "=e")
|
||||
(match_operand:DF 1 "const_double_operand" ""))]
|
||||
|
14
gcc/md.texi
14
gcc/md.texi
@ -1621,11 +1621,19 @@ Floating-point zero
|
||||
Signed 13 bit constant, sign-extended to 32 or 64 bits
|
||||
|
||||
@item Q
|
||||
Memory reference that can be loaded with one instruction (@samp{m} is
|
||||
more appropriate for @code{asm} statements)
|
||||
Floating-point constant whose integral representation can
|
||||
be moved into an integer register using a single sethi
|
||||
instruction
|
||||
|
||||
@item R
|
||||
Floating-point constant whose integral representation can
|
||||
be moved into an integer register using a single mov
|
||||
instruction
|
||||
|
||||
@item S
|
||||
Constant, or memory address
|
||||
Floating-point constant whose integral representation can
|
||||
be moved into an integer register using a high/lo_sum
|
||||
instruction sequence
|
||||
|
||||
@item T
|
||||
Memory address aligned to an 8-byte boundary
|
||||
|
Loading…
Reference in New Issue
Block a user