aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@redhat.com>1999-12-10 04:08:51 -0800
committerDavid S. Miller <davem@gcc.gnu.org>1999-12-10 04:08:51 -0800
commit6219012805548899fb34a29ca4f16cf9ddc7c0ad (patch)
tree548f0ef07f06b8bc5f34425bda9329658c86a499
parentacce0437338a6aece7ae98387c98f2a0e31da6a4 (diff)
downloadgcc-6219012805548899fb34a29ca4f16cf9ddc7c0ad.zip
gcc-6219012805548899fb34a29ca4f16cf9ddc7c0ad.tar.gz
gcc-6219012805548899fb34a29ca4f16cf9ddc7c0ad.tar.bz2
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
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/sparc/sparc-protos.h3
-rw-r--r--gcc/config/sparc/sparc.c83
-rw-r--r--gcc/config/sparc/sparc.h49
-rw-r--r--gcc/config/sparc/sparc.md274
-rw-r--r--gcc/md.texi14
6 files changed, 326 insertions, 114 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d595ca9..42204f4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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):
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index c761669..8c5b1b1 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -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));
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 072e7e6..9c5380d 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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)
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 4387fc8..c949c3e 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -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}}, \
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 25951f0..b7025a8 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -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,71 +2818,174 @@
;; 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")
- (set_attr "length" "1")])
+(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;
-(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")
+ 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 "*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_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]))"
"*
{
- REAL_VALUE_TYPE r;
- long i;
+ if (GET_CODE (operands[1]) == CONST_DOUBLE
+ && (which_alternative == 2
+ || which_alternative == 3
+ || which_alternative == 4))
+ {
+ 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_TO_TARGET_SINGLE (r, i);
+ operands[1] = GEN_INT (i);
+ }
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SIMM13_P (i) || SPARC_SETHI_P (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_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);
- 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 \"#\";
+
+ 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" "move")
- (set_attr "length" "1,2")])
+ [(set_attr "type" "fpmove,fpmove,move,move,move,*,load,fpload,fpstore,store")
+ (set_attr "length" "1")])
-;; 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")
+(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;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
+ REAL_VALUE_TO_TARGET_SINGLE (r, i);
+ operands[2] = GEN_INT (i);
+ return \"or\\t%1, %%lo(%a2), %0\";
+}"
+ [(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"
+(define_insn "*movsf_high"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (high:SF (match_operand:SF 1 "const_double_operand" "")))]
+ "TARGET_FPU && fp_high_losum_p (operands[1])"
+ "*
+{
+ 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);
+ return \"sethi\\t%%hi(%1), %0\";
+}"
[(set_attr "type" "move")
(set_attr "length" "1")])
@@ -2892,19 +2993,28 @@
[(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) (unspec:SF [(match_dup 1)] 12))
- (set (match_dup 0) (unspec:SF [(match_dup 0) (match_dup 1)] 17))]
- "
-{
- REAL_VALUE_TYPE r;
- long i;
+ [(set (match_dup 0) (high:SF (match_dup 1)))
+ (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = GEN_INT (i);
-}")
+;; 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" ""))]
diff --git a/gcc/md.texi b/gcc/md.texi
index 4830167..067d464 100644
--- a/gcc/md.texi
+++ b/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