From 026d38685a306238520bd2dc743b94e66ecf450f Mon Sep 17 00:00:00 2001
From: zack <zack@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Tue, 28 Feb 2006 03:28:18 +0000
Subject: [PATCH] 	* rtl.def (define_constraint,
 define_register_constraint) 	(define_memory_constraint,
 define_address_constraint): New MD forms. 	* gensupport.c (process_rtx):
 Put define_constraint etc on the 	predicate queue. 	* genpreds.c
 (process_define_predicate): Adjust comment.  Validate 	the name, and call
 validate_exp to validate the expression. 	(mark_mode_tests,
 write_extract_subexp): Can assume correct input. 
 (write_predicate_expr): Likewise.  NAME argument no longer necessary; 	all
 callers changed. 	(validate_exp, needs_variable, struct constraint_data)
 	(constraints_by_letter_table, first_constraint, last_constraint_ptr) 
 (FOR_ALL_CONSTRAINTS, generic_constraint_letters, const_int_constraints) 
 (const_dbl_constraints, constraint_max_namelen) 
 (have_register_constraints, have_memory_constraints) 
 (have_address_constraints, have_address_constraints) 
 (have_extra_constraints, have_const_int_constraints) 
 (have_const_dbl_constraints, mangle, add_constraint) 
 (process_define_constraint, process_define_register_constraint) 
 (write_enum_constraint_num, write_lookup_constraint) 
 (write_insn_constraint_len, write_regclass_for_constraint) 
 (write_constraint_satisfied_p, write_insn_const_int_ok_for_constraint) 
 (write_insn_extra_memory_constraint) 	(write_insn_extra_address_constraint) 
 (write_satisfies_constraint_fns): New. 	(write_tm_preds_h): If we have
 new-style constraint definitions, 	prototype the functions generated from
 them, and define the 	old constraint interface (still used by generic code)
 in terms of 	those functions. 	(write_insn_preds_c): If we have
 new-style constraint definitions, 	generate all relevant functions from
 those definitions. 	(main): Handle define_constraint etc. 	* genoutput.c
 (struct constraint_data, indep_constraints) 	(mdep_constraint_letters,
 constraints_by_letter_table, note_constraint) 	(mdep_constraint_len): New
 data structures and functions, defined 	#ifdef USE_MD_CONSTRAINTS. 
 (check_constraint_len): Don't define #ifdef USE_MD_CONSTRAINTS. 
 (validate_insn_alternatives): If USE_MD_CONSTRAINTS is defined, 	use
 new logic to validate operand constraints against constraint 	definitions. 
 (main): Process define_constraint etc. if USE_MD_CONSTRAINTS is 
 defined. 	* defaults.h: If none of the old-style constraint macros are 
 defined, define USE_MD_CONSTRAINTS; do not provide defaults for any 
 old-style macros; and poison REG_CLASS_FROM_LETTER, 	CONST_OK_FOR_LETTER_P,
 CONST_DOUBLE_OK_FOR_LETTER_P, and 	EXTRA_CONSTRAINT. 	* recog.c
 (reg_fits_class_p): If cl is NO_REGS, return 0 immediately. 	* doc/md.texi:
 Document new constraint-definition mechanism and the 	C interface it
 provides.  Remove references to old mechanism  	elsewhere in the
 document. 	(Machine Constraints): Use pathnames relative to gcc
 directory, 	i.e. config/ARCH/FILE.  Change i386 section to refer to 
 config/i386/predicates.md; update that section to match docstrings. 	*
 doc/tm.texi: Move all documentation of the old constraint- 	definition
 macros to their own section, clearly mark as obsolete.

	* config/i386/predicates.md (R, q, Q, l, a, b, c, d, S, D, A, f, t)
	(u, y, x, Y, I, J, K, L, M, N, O, G, C, e, Z): New constraint
	definitions.
	* config/i386/i386.h (REG_CLASS_FROM_LETTER, CONST_OK_FOR_LETTER_P)
	(CONST_DOUBLE_OK_FOR_LETTER_P, EXTRA_CONSTRAINT): Delete.
	* config/i386/i386.md (*movdf_nointeger): Remove stray 'H' from
	constraint strings.
	(splits and peepholes): Use satisfies_constraint_*.
	* config/i386/i386.c (memory_address_length)
	(ix86_attr_length_immediate_default): Use satisfies_constraint_*.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111508 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                 |  69 +++
 gcc/config/i386/i386.c        |   8 +-
 gcc/config/i386/i386.h        |  86 ----
 gcc/config/i386/i386.md       |  23 +-
 gcc/config/i386/predicates.md | 134 +++++
 gcc/defaults.h                |  29 ++
 gcc/doc/md.texi               | 421 ++++++++++++----
 gcc/doc/tm.texi               |  72 +--
 gcc/genoutput.c               | 187 ++++++-
 gcc/genpreds.c                | 885 +++++++++++++++++++++++++++++++---
 gcc/gensupport.c              |   4 +
 gcc/recog.c                   |   4 +
 gcc/rtl.def                   |  55 +++
 13 files changed, 1678 insertions(+), 299 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eadb2fe1b48f..7538a9f81430 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,72 @@
+2006-02-27  Zack Weinberg  <zackw@panix.com>
+
+	* rtl.def (define_constraint, define_register_constraint)
+	(define_memory_constraint, define_address_constraint): New MD forms.
+	* gensupport.c (process_rtx): Put define_constraint etc on the
+	predicate queue.
+	* genpreds.c (process_define_predicate): Adjust comment.  Validate
+	the name, and call validate_exp to validate the expression.
+	(mark_mode_tests, write_extract_subexp): Can assume correct input.
+	(write_predicate_expr): Likewise.  NAME argument no longer necessary;
+	all callers changed.
+	(validate_exp, needs_variable, struct constraint_data)
+	(constraints_by_letter_table, first_constraint, last_constraint_ptr)
+	(FOR_ALL_CONSTRAINTS, generic_constraint_letters, const_int_constraints)
+	(const_dbl_constraints, constraint_max_namelen)
+	(have_register_constraints, have_memory_constraints)
+	(have_address_constraints, have_address_constraints)
+	(have_extra_constraints, have_const_int_constraints)
+	(have_const_dbl_constraints, mangle, add_constraint)
+	(process_define_constraint, process_define_register_constraint)
+	(write_enum_constraint_num, write_lookup_constraint)
+	(write_insn_constraint_len, write_regclass_for_constraint)
+	(write_constraint_satisfied_p, write_insn_const_int_ok_for_constraint)
+	(write_insn_extra_memory_constraint)
+	(write_insn_extra_address_constraint)
+	(write_satisfies_constraint_fns): New.
+	(write_tm_preds_h): If we have new-style constraint definitions,
+	prototype the functions generated from them, and define the
+	old constraint interface (still used by generic code) in terms of
+	those functions.
+	(write_insn_preds_c): If we have new-style constraint definitions,
+	generate all relevant functions from those definitions.
+	(main): Handle define_constraint etc.
+	* genoutput.c (struct constraint_data, indep_constraints)
+	(mdep_constraint_letters, constraints_by_letter_table, note_constraint)
+	(mdep_constraint_len): New data structures and functions, defined
+	#ifdef USE_MD_CONSTRAINTS.
+	(check_constraint_len): Don't define #ifdef USE_MD_CONSTRAINTS.
+	(validate_insn_alternatives): If USE_MD_CONSTRAINTS is defined,
+	use new logic to validate operand constraints against constraint
+	definitions.
+	(main): Process define_constraint etc. if USE_MD_CONSTRAINTS is
+	defined.
+	* defaults.h: If none of the old-style constraint macros are
+	defined, define USE_MD_CONSTRAINTS; do not provide defaults for any
+	old-style macros; and poison REG_CLASS_FROM_LETTER,
+	CONST_OK_FOR_LETTER_P, CONST_DOUBLE_OK_FOR_LETTER_P, and
+	EXTRA_CONSTRAINT.
+	* recog.c (reg_fits_class_p): If cl is NO_REGS, return 0 immediately.
+	* doc/md.texi: Document new constraint-definition mechanism and the
+	C interface it provides.  Remove references to old mechanism
+ 	elsewhere in the document.
+	(Machine Constraints): Use pathnames relative to gcc directory,
+	i.e. config/ARCH/FILE.  Change i386 section to refer to
+	config/i386/predicates.md; update that section to match docstrings.
+	* doc/tm.texi: Move all documentation of the old constraint-
+	definition macros to their own section, clearly mark as obsolete.
+
+	* config/i386/predicates.md (R, q, Q, l, a, b, c, d, S, D, A, f, t)
+	(u, y, x, Y, I, J, K, L, M, N, O, G, C, e, Z): New constraint
+	definitions.
+	* config/i386/i386.h (REG_CLASS_FROM_LETTER, CONST_OK_FOR_LETTER_P)
+	(CONST_DOUBLE_OK_FOR_LETTER_P, EXTRA_CONSTRAINT): Delete.
+	* config/i386/i386.md (*movdf_nointeger): Remove stray 'H' from
+	constraint strings.
+	(splits and peepholes): Use satisfies_constraint_*.
+	* config/i386/i386.c (memory_address_length)
+	(ix86_attr_length_immediate_default): Use satisfies_constraint_*.
+
 2006-02-27  Daniel Berlin  <dberlin@dberlin.org>
 
 	* lambda-code.c (can_convert_to_perfect_nest): Allow any type of
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index edfe04f57377..fae111e986f0 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13291,9 +13291,7 @@ memory_address_length (rtx addr)
       /* Find the length of the displacement constant.  */
       if (disp)
 	{
-	  if (GET_CODE (disp) == CONST_INT
-	      && CONST_OK_FOR_LETTER_P (INTVAL (disp), 'K')
-	      && base)
+	  if (base && satisfies_constraint_K (disp))
 	    len = 1;
 	  else
 	    len = 4;
@@ -13326,9 +13324,7 @@ ix86_attr_length_immediate_default (rtx insn, int shortform)
     if (CONSTANT_P (recog_data.operand[i]))
       {
 	gcc_assert (!len);
-	if (shortform
-	    && GET_CODE (recog_data.operand[i]) == CONST_INT
-	    && CONST_OK_FOR_LETTER_P (INTVAL (recog_data.operand[i]), 'K'))
+	if (shortform && satisfies_constraint_K (recog_data.operand[i]))
 	  len = 1;
 	else
 	  {
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 307cc97d4df4..fc8f62661b58 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1196,92 +1196,6 @@ enum reg_class
 #define INDEX_REG_CLASS INDEX_REGS
 #define BASE_REG_CLASS GENERAL_REGS
 
-/* Unused letters:
-    B                 TU W   
-          h jk          vw  z
-*/
-
-/* Get reg_class from a letter such as appears in the machine description.  */
-
-#define REG_CLASS_FROM_LETTER(C)	\
-  ((C) == 'r' ? GENERAL_REGS :					\
-   (C) == 'R' ? LEGACY_REGS :					\
-   (C) == 'q' ? TARGET_64BIT ? GENERAL_REGS : Q_REGS :		\
-   (C) == 'Q' ? Q_REGS :					\
-   (C) == 'f' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387	\
-		 ? FLOAT_REGS					\
-		 : NO_REGS) :					\
-   (C) == 't' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387	\
-		 ? FP_TOP_REG					\
-		 : NO_REGS) :					\
-   (C) == 'u' ? (TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387	\
-		 ? FP_SECOND_REG				\
-		 : NO_REGS) :					\
-   (C) == 'a' ? AREG :						\
-   (C) == 'b' ? BREG :						\
-   (C) == 'c' ? CREG :						\
-   (C) == 'd' ? DREG :						\
-   (C) == 'x' ? TARGET_SSE ? SSE_REGS : NO_REGS :		\
-   (C) == 'Y' ? TARGET_SSE2? SSE_REGS : NO_REGS :		\
-   (C) == 'y' ? TARGET_MMX ? MMX_REGS : NO_REGS :		\
-   (C) == 'A' ? AD_REGS :					\
-   (C) == 'D' ? DIREG :						\
-   (C) == 'S' ? SIREG :						\
-   (C) == 'l' ? INDEX_REGS :					\
-   NO_REGS)
-
-/* The letters I, J, K, L, M, N, and O in a register constraint string
-   can be used to stand for particular ranges of immediate operands.
-   This macro defines what the ranges are.
-   C is the letter, and VALUE is a constant value.
-   Return 1 if VALUE is in the range specified by C.
-
-   I is for non-DImode shifts.
-   J is for DImode shifts.
-   K is for signed imm8 operands.
-   L is for andsi as zero-extending move.
-   M is for shifts that can be executed by the "lea" opcode.
-   N is for immediate operands for out/in instructions (0-255)
-   O is for TImode shifts.
-   */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C)				\
-  ((C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 31			\
-   : (C) == 'J' ? (VALUE) >= 0 && (VALUE) <= 63			\
-   : (C) == 'K' ? (VALUE) >= -128 && (VALUE) <= 127		\
-   : (C) == 'L' ? (VALUE) == 0xff || (VALUE) == 0xffff		\
-   : (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3			\
-   : (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255		\
-   : (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 127		\
-   : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-   Here VALUE is the CONST_DOUBLE rtx itself.  We allow constants even if
-   TARGET_387 isn't set, because the stack register converter may need to
-   load 0.0 into the function value register.  */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
-  ((C) == 'G' ? standard_80387_constant_p (VALUE) \
-   : 0)
-
-/* A C expression that defines the optional machine-dependent
-   constraint letters that can be used to segregate specific types of
-   operands, usually memory references, for the target machine.  Any
-   letter that is not elsewhere defined and not matched by
-   `REG_CLASS_FROM_LETTER' may be used.  Normally this macro will not
-   be defined.
-
-   If it is required for a particular target machine, it should
-   return 1 if VALUE corresponds to the operand type represented by
-   the constraint letter C.  If C is not defined as an extra
-   constraint, the value returned should be 0 regardless of VALUE.  */
-
-#define EXTRA_CONSTRAINT(VALUE, D)					\
-  ((D) == 'e' ? x86_64_immediate_operand (VALUE, VOIDmode)		\
-   : (D) == 'Z' ? x86_64_zext_immediate_operand (VALUE, VOIDmode)	\
-   : (D) == 'C' ? standard_sse_constant_p (VALUE)			\
-   : 0)
-
 /* Place additional restrictions on the register class to use when it
    is necessary to be able to hold a value of mode MODE in a reload
    register for which class CLASS would ordinarily be used.  */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 868d33676162..4e64da31a3ff 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2440,9 +2440,9 @@
 
 (define_insn "*movdf_nointeger"
   [(set (match_operand:DF 0 "nonimmediate_operand"
-			"=f#Y,m  ,f#Y,*r  ,o  ,Y*x#f,Y*x#f,Y*x#f  ,m    ")
+			"=f#Y,m  ,f#Y,*r  ,o  ,Y*x#f,Y*x#f,Y*x#f ,m    ")
 	(match_operand:DF 1 "general_operand"
-			"fm#Y,f#Y,G  ,*roF,F*r,C    ,Y*x#f,HmY*x#f,Y*x#f"))]
+			"fm#Y,f#Y,G  ,*roF,F*r,C    ,Y*x#f,mY*x#f,Y*x#f"))]
   "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
    && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT)
    && (reload_in_progress || reload_completed
@@ -19038,8 +19038,9 @@
   "! TARGET_PARTIAL_REG_STALL && reload_completed
    && ((GET_MODE (operands[0]) == HImode 
 	&& ((!optimize_size && !TARGET_FAST_PREFIX)
+            /* ??? next two lines just !satisfies_constraint_K (...) */
 	    || GET_CODE (operands[2]) != CONST_INT
-	    || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
+	    || satisfies_constraint_K (operands[2])))
        || (GET_MODE (operands[0]) == QImode 
 	   && (TARGET_PROMOTE_QImode || optimize_size)))"
   [(parallel [(set (match_dup 0)
@@ -19361,8 +19362,7 @@
 	   (const_int 0)]))]
   "ix86_match_ccmode (insn, CCNOmode)
    && (true_regnum (operands[2]) != 0
-       || (GET_CODE (operands[3]) == CONST_INT
-	   && CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'K')))
+       || satisfies_constraint_K (operands[3]))
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel
      [(set (match_dup 0)
@@ -19928,8 +19928,7 @@
 			    (match_operand:DI 2 "immediate_operand" "")))
 	      (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2)))
 	      (clobber (reg:CC FLAGS_REG))])]
@@ -19942,8 +19941,7 @@
 			    (match_operand:SI 2 "immediate_operand" "")))
 	      (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))
 	      (clobber (reg:CC FLAGS_REG))])]
@@ -19957,8 +19955,7 @@
 			      (match_operand:SI 2 "immediate_operand" ""))))
 	      (clobber (reg:CC FLAGS_REG))])]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && (GET_CODE (operands[2]) != CONST_INT
-       || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
+   && !satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 1))
    (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2))))
 	      (clobber (reg:CC FLAGS_REG))])]
@@ -19975,7 +19972,7 @@
 	      (clobber (reg:CC FLAGS_REG))])
    (match_scratch:DI 3 "r")]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 2))
    (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3)))
 	      (clobber (reg:CC FLAGS_REG))])]
@@ -19991,7 +19988,7 @@
 	      (clobber (reg:CC FLAGS_REG))])
    (match_scratch:SI 3 "r")]
   "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size
-   && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')"
+   && satisfies_constraint_K (operands[2])"
   [(set (match_dup 3) (match_dup 2))
    (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3)))
 	      (clobber (reg:CC FLAGS_REG))])]
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index acc01eeb537b..d97f6fccbca8 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -947,3 +947,137 @@
 
 (define_predicate "absneg_operator"
   (match_code "abs,neg"))
+
+;;; Constraint definitions.
+;;; Unused letters:
+;;;     B     H           TU W   
+;;;           h jk          vw  z
+
+;; Integer register constraints.
+;; It is not necessary to define 'r' here.
+(define_register_constraint "R" "LEGACY_REGS"
+ "Legacy register---the eight integer registers available on all
+  i386 processors (@code{a}, @code{b}, @code{c}, @code{d},
+  @code{si}, @code{di}, @code{bp}, @code{sp}).")
+
+(define_register_constraint "q" "TARGET_64BIT ? GENERAL_REGS : Q_REGS"
+ "Any register accessible as @code{@var{r}l}.  In 32-bit mode, @code{a},
+  @code{b}, @code{c}, and @code{d}; in 64-bit mode, any integer register.")
+
+(define_register_constraint "Q" "Q_REGS"
+ "Any register accessible as @code{@var{r}h}: @code{a}, @code{b},
+  @code{c}, and @code{d}.")
+
+(define_register_constraint "l" "INDEX_REGS"
+ "@internal Any register that can be used as the index in a base+index
+  memory access: that is, any general register except the stack pointer.")
+
+(define_register_constraint "a" "AREG"
+ "The @code{a} register.")
+
+(define_register_constraint "b" "BREG"
+ "The @code{b} register.")
+
+(define_register_constraint "c" "CREG"
+ "The @code{c} register.")
+
+(define_register_constraint "d" "DREG"
+ "The @code{d} register.")
+
+(define_register_constraint "S" "SIREG"
+ "The @code{si} register.")
+
+(define_register_constraint "D" "DIREG"
+ "The @code{di} register.")
+
+(define_register_constraint "A" "AD_REGS"
+ "The @code{a} and @code{d} registers, as a pair (for instructions
+  that return half the result in one and half in the other).")
+
+;; Floating-point register constraints.
+(define_register_constraint "f"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FLOAT_REGS : NO_REGS"
+ "Any 80387 floating-point (stack) register.")
+
+(define_register_constraint "t"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FP_TOP_REG : NO_REGS"
+ "Top of 80387 floating-point stack (@code{%st(0)}).")
+
+(define_register_constraint "u"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FP_SECOND_REG : NO_REGS"
+ "Second from top of 80387 floating-point stack (@code{%st(1)}).")
+
+;; Vector registers (also used for plain floating point nowadays).
+(define_register_constraint "y" "TARGET_MMX ? MMX_REGS : NO_REGS"
+ "Any MMX register.")
+
+(define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
+ "Any SSE register.")
+
+(define_register_constraint "Y" "TARGET_SSE2? SSE_REGS : NO_REGS"
+ "@internal Any SSE2 register.")
+
+;; Integer constant constraints.
+(define_constraint "I"
+  "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "J"
+  "Integer constant in the range 0 @dots{} 63, for 64-bit shifts."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 63")))
+
+(define_constraint "K"
+  "Signed 8-bit integer constant."
+  (and (match_code "const_int")
+       (match_test "ival >= -128 && ival <= 127")))
+
+(define_constraint "L"
+  "@code{0xFF} or @code{0xFFFF}, for andsi as a zero-extending move."
+  (and (match_code "const_int")
+       (match_test "ival == 0xFF || ival == 0xFFFF")))
+
+(define_constraint "M"
+  "0, 1, 2, or 3 (shifts for the @code{lea} instruction)."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 3")))
+
+(define_constraint "N"
+  "Unsigned 8-bit integer constant (for @code{in} and @code{out} 
+   instructions)."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 255")))
+
+(define_constraint "O"
+  "@internal Integer constant in the range 0 @dots{} 127, for 128-bit shifts."
+  (and (match_code "const_int")
+       (match_test "ival >= 0 && ival <= 127")))
+
+;; Floating-point constant constraints.
+;; We allow constants even if TARGET_80387 isn't set, because the
+;; stack register converter may need to load 0.0 into the function
+;; value register (top of stack).
+(define_constraint "G"
+  "Standard 80387 floating point constant."
+  (and (match_code "const_double")
+       (match_test "standard_80387_constant_p (op)")))
+
+;; This can theoretically be any mode's CONST0_RTX.
+(define_constraint "C"
+  "Standard SSE floating point constant."
+  (match_test "standard_sse_constant_p (op)"))
+
+;; Constant-or-symbol-reference constraints.
+
+(define_constraint "e"
+  "32-bit signed integer constant, or a symbolic reference known
+   to fit that range (for immediate operands in sign-extending x86-64
+   instructions)."
+  (match_operand 0 "x86_64_immediate_operand"))
+
+(define_constraint "Z"
+  "32-bit unsigned integer constant, or a symbolic reference known
+   to fit that range (for immediate operands in zero-extending x86-64
+   instructions)."
+  (match_operand 0 "x86_64_zext_immediate_operand"))
diff --git a/gcc/defaults.h b/gcc/defaults.h
index a82a7230dc21..624f039dfea2 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -752,6 +752,33 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #define DEFAULT_USE_CXA_ATEXIT 0
 #endif
 
+/* If none of these macros are defined, the port must use the new
+   technique of defining constraints in the machine description.
+   tm_p.h will define those macros that machine-independent code
+   still uses.  */
+#if  !defined CONSTRAINT_LEN			\
+  && !defined REG_CLASS_FROM_LETTER		\
+  && !defined REG_CLASS_FROM_CONSTRAINT		\
+  && !defined CONST_OK_FOR_LETTER_P		\
+  && !defined CONST_OK_FOR_CONSTRAINT_P		\
+  && !defined CONST_DOUBLE_OK_FOR_LETTER_P	\
+  && !defined CONST_DOUBLE_OK_FOR_CONSTRAINT_P  \
+  && !defined EXTRA_CONSTRAINT			\
+  && !defined EXTRA_CONSTRAINT_STR		\
+  && !defined EXTRA_MEMORY_CONSTRAINT		\
+  && !defined EXTRA_ADDRESS_CONSTRAINT
+
+#define USE_MD_CONSTRAINTS
+
+#if GCC_VERSION >= 3000 && defined IN_GCC
+/* These old constraint macros shouldn't appear anywhere in a
+   configuration using MD constraint definitions.  */
+#pragma GCC poison REG_CLASS_FROM_LETTER CONST_OK_FOR_LETTER_P \
+                   CONST_DOUBLE_OK_FOR_LETTER_P EXTRA_CONSTRAINT
+#endif
+
+#else /* old constraint mechanism in use */
+
 /* Determine whether extra constraint letter should be handled
    via address reload (like 'o').  */
 #ifndef EXTRA_MEMORY_CONSTRAINT
@@ -791,6 +818,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #define EXTRA_CONSTRAINT_STR(OP, C,STR) EXTRA_CONSTRAINT (OP, C)
 #endif
 
+#endif /* old constraint mechanism in use */
+
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(m, x, y) 2
 #endif
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 462509d049ba..6a3300bae3e8 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1051,6 +1051,8 @@ have.  Constraints can also require two operands to match.
 * Class Preferences::   Constraints guide which hard register to put things in.
 * Modifiers::           More precise control over effects of constraints.
 * Machine Constraints:: Existing constraints for some particular machines.
+* Define Constraints::  How to define machine-specific constraints.
+* C Constraint Interface:: How to test constraints from C code.
 @end menu
 @end ifset
 
@@ -1273,15 +1275,6 @@ Other letters can be defined in machine-dependent fashion to stand for
 particular classes of registers or other arbitrary operand types.
 @samp{d}, @samp{a} and @samp{f} are defined on the 68000/68020 to stand
 for data, address and floating point registers.
-
-@ifset INTERNALS
-The machine description macro @code{REG_CLASS_FROM_LETTER} has first
-cut at the otherwise unused letters.  If it evaluates to @code{NO_REGS},
-then @code{EXTRA_CONSTRAINT} is evaluated.
-
-A typical use for @code{EXTRA_CONSTRAINT} would be to distinguish certain
-types of memory references that affect other insn operands.
-@end ifset
 @end table
 
 @ifset INTERNALS
@@ -1624,35 +1617,16 @@ general-purpose registers respectively; @pxref{Simple Constraints}), and
 @samp{I}, usually the letter indicating the most common
 immediate-constant format.
 
-For each machine architecture, the
-@file{config/@var{machine}/@var{machine}.h} file defines additional
-constraints.  These constraints are used by the compiler itself for
-instruction generation, as well as for @code{asm} statements; therefore,
-some of the constraints are not particularly interesting for @code{asm}.
-The constraints are defined through these macros:
-
-@table @code
-@item REG_CLASS_FROM_LETTER
-Register class constraints (usually lowercase).
-
-@item CONST_OK_FOR_LETTER_P
-Immediate constant constraints, for non-floating point constants of
-word size or smaller precision (usually uppercase).
-
-@item CONST_DOUBLE_OK_FOR_LETTER_P
-Immediate constant constraints, for all floating point constants and for
-constants of greater than word size precision (usually uppercase).
-
-@item EXTRA_CONSTRAINT
-Special cases of registers or memory.  This macro is not required, and
-is only defined for some machines.
-@end table
-
-Inspecting these macro definitions in the compiler source for your
-machine is the best way to be certain you have the right constraints.
-However, here is a summary of the machine-dependent constraints
-available on some particular machines.
-
+Each architecture defines additional constraints.  These constraints
+are used by the compiler itself for instruction generation, as well as
+for @code{asm} statements; therefore, some of the constraints are not
+particularly useful for @code{asm}.  Here is a summary of some of the
+machine-dependent constraints available on some particular machines;
+it includes both constraints that are useful for @code{asm} and
+constraints that aren't.  The compiler source file mentioned in the
+table heading for each architecture is the definitive reference for
+the meanings of that architecture's constraints.
+ 
 @table @emph
 @item ARM family---@file{config/arm/arm.h}
 @table @code
@@ -1908,93 +1882,109 @@ A 15-bit signed integer constant.
 A positive 16-bit constant.
 @end table
 
-@item Intel 386---@file{config/i386/i386.h}
+@item Intel 386---@file{config/i386/predicates.md}
 @table @code
-@item q
-@samp{a}, @code{b}, @code{c}, or @code{d} register for the i386.
-For x86-64 it is equivalent to @samp{r} class (for 8-bit instructions that
-do not use upper halves).
-
-@item Q
-@samp{a}, @code{b}, @code{c}, or @code{d} register (for 8-bit instructions,
-that do use upper halves).
-
 @item R
-Legacy register---equivalent to @code{r} class in i386 mode.
-(for non-8-bit registers used together with 8-bit upper halves in a single
-instruction)
-
-@item A
-Specifies the @samp{a} or @samp{d} registers.  This is primarily useful
-for 64-bit integer values (when in 32-bit mode) intended to be returned
-with the @samp{d} register holding the most significant bits and the
-@samp{a} register holding the least significant bits.
+Legacy register---the eight integer registers available on all
+i386 processors (@code{a}, @code{b}, @code{c}, @code{d},
+@code{si}, @code{di}, @code{bp}, @code{sp}).
 
-@item f
-Floating point register
+@item q
+Any register accessible as @code{@var{r}l}.  In 32-bit mode, @code{a},
+@code{b}, @code{c}, and @code{d}; in 64-bit mode, any integer register.
 
-@item t
-First (top of stack) floating point register
+@item Q
+Any register accessible as @code{@var{r}h}: @code{a}, @code{b},
+@code{c}, and @code{d}.
 
-@item u
-Second floating point register
+@ifset INTERNALS
+@item l
+Any register that can be used as the index in a base+index memory
+access: that is, any general register except the stack pointer.
+@end ifset
 
 @item a
-@samp{a} register
+The @code{a} register.
 
 @item b
-@samp{b} register
+The @code{b} register.
 
 @item c
-@samp{c} register
-
-@item C
-Specifies constant that can be easily constructed in SSE register without
-loading it from memory.
+The @code{c} register.
 
 @item d
-@samp{d} register
+The @code{d} register.
+
+@item S
+The @code{si} register.
 
 @item D
-@samp{di} register
+The @code{di} register.
 
-@item S
-@samp{si} register
+@item A
+The @code{a} and @code{d} registers, as a pair (for instructions that
+return half the result in one and half in the other).
 
-@item x
-@samp{xmm} SSE register
+@item f
+Any 80387 floating-point (stack) register.
+
+@item t
+Top of 80387 floating-point stack (@code{%st(0)}).
+
+@item u
+Second from top of 80387 floating-point stack (@code{%st(1)}).
 
 @item y
-MMX register
+Any MMX register.
+
+@item x
+Any SSE register.
+
+@ifset INTERNALS
+@item Y
+Any SSE2 register.
+@end ifset
 
 @item I
-Constant in range 0 to 31 (for 32-bit shifts)
+Integer constant in the range 0 @dots{} 31, for 32-bit shifts.
 
 @item J
-Constant in range 0 to 63 (for 64-bit shifts)
+Integer constant in the range 0 @dots{} 63, for 64-bit shifts.
 
 @item K
-@samp{0xff}
+Signed 8-bit integer constant.
 
 @item L
-@samp{0xffff}
+@code{0xFF} or @code{0xFFFF}, for andsi as a zero-extending move.
 
 @item M
-0, 1, 2, or 3 (shifts for @code{lea} instruction)
+0, 1, 2, or 3 (shifts for the @code{lea} instruction).
 
 @item N
-Constant in range 0 to 255 (for @code{out} instruction)
+Unsigned 8-bit integer constant (for @code{in} and @code{out} 
+instructions).
 
-@item Z
-Constant in range 0 to @code{0xffffffff} or symbolic reference known to fit specified range.
-(for using immediates in zero extending 32-bit to 64-bit x86-64 instructions)
+@ifset INTERNALS
+@item O
+Integer constant in the range 0 @dots{} 127, for 128-bit shifts.
+@end ifset
+
+@item G
+Standard 80387 floating point constant.
+
+@item C
+Standard SSE floating point constant.
 
 @item e
-Constant in range @minus{}2147483648 to 2147483647 or symbolic reference known to fit specified range.
-(for using immediates in 64-bit x86-64 instructions)
+32-bit signed integer constant, or a symbolic reference known
+to fit that range (for immediate operands in sign-extending x86-64
+instructions).
+
+@item Z
+32-bit unsigned integer constant, or a symbolic reference known
+to fit that range (for immediate operands in zero-extending x86-64
+instructions).
 
-@item G
-Standard 80387 floating point constant
 @end table
 
 @item Intel IA-64---@file{config/ia64/ia64.h}
@@ -2868,6 +2858,257 @@ Unsigned constant valid for BccUI instructions
 @end table
 
 @ifset INTERNALS
+@node Define Constraints
+@subsection Defining Machine-Specific Constraints
+@cindex defining constraints
+@cindex constraints, defining
+
+Machine-specific constraints fall into two categories: register and
+non-register constraints.  Within the latter category, constraints
+which allow subsets of all possible memory or address operands should
+be specially marked, to give @code{reload} more information.
+
+Machine-specific constraints can be given names of arbitrary length,
+but they must be entirely composed of letters, digits, underscores
+(@samp{_}), and angle brackets (@samp{< >}).  Like C identifiers, they
+must begin with a letter or underscore. 
+
+In order to avoid ambiguity in operand constraint strings, no
+constraint can have a name that begins with any other constraint's
+name.  For example, if @code{x} is defined as a constraint name,
+@code{xy} may not be, and vice versa.  As a consequence of this rule,
+no constraint may begin with one of the generic constraint letters:
+@samp{E F V X g i m n o p r s}.
+
+Register constraints correspond directly to register classes.
+@xref{Register Classes}.  There is thus not much flexibility in their
+definitions.
+
+@deffn {MD Expression} define_register_constraint name regclass docstring
+All three arguments are string constants.
+@var{name} is the name of the constraint, as it will appear in
+@code{match_operand} expressions.  @var{regclass} can be either the
+name of the corresponding register class (@pxref{Register Classes}),
+or a C expression which evaluates to the appropriate register class.
+If it is an expression, it must have no side effects, and it cannot
+look at the operand.  The usual use of expressions is to map some
+register constraints to @code{NO_REGS} when the register class
+is not available on a given subarchitecture.
+
+@var{docstring} is a sentence documenting the meaning of the
+constraint.  Docstrings are explained further below.
+@end deffn
+
+Non-register constraints are more like predicates: the constraint
+definition gives a Boolean expression which indicates whether the
+constraint matches.
+
+@deffn {MD Expression} define_constraint name docstring exp
+The @var{name} and @var{docstring} arguments are the same as for
+@code{define_register_constraint}, but note that the docstring comes
+immediately after the name for these expressions.  @var{exp} is an RTL
+expression, obeying the same rules as the RTL expressions in predicate
+definitions.  @xref{Defining Predicates}, for details.  If it
+evaluates true, the constraint matches; if it evaluates false, it
+doesn't. Constraint expressions should indicate which RTL codes they
+might match, just like predicate expressions.
+
+@code{match_test} C expressions have access to the
+following variables:
+
+@table @var
+@item op
+The RTL object defining the operand.
+@item mode
+The machine mode of @var{op}.
+@item ival
+@samp{INTVAL (@var{op})}, if @var{op} is a @code{const_int}.
+@item hval
+@samp{CONST_DOUBLE_HIGH (@var{op})}, if @var{op} is an integer
+@code{const_double}.
+@item lval
+@samp{CONST_DOUBLE_LOW (@var{op})}, if @var{op} is an integer
+@code{const_double}.
+@item rval
+@samp{CONST_DOUBLE_REAL_VALUE (@var{op})}, if @var{op} is a floating-point
+@code{const_@/double}.
+@end table
+
+The @var{*val} variables should only be used once another piece of the
+expression has verified that @var{op} is the appropriate kind of RTL
+object.
+@end deffn
+
+Most non-register constraints should be defined with
+@code{define_constraint}.  The remaining two definition expressions
+are only appropriate for constraints that should be handled specially
+by @code{reload} if they fail to match.
+
+@deffn {MD Expression} define_memory_constraint name docstring exp
+Use this expression for constraints that match a subset of all memory
+operands: that is, @code{reload} can make them match by converting the
+operand to the form @samp{@w{(mem (reg @var{X}))}}, where @var{X} is a
+base register (from the register class specified by
+@code{BASE_REG_CLASS}, @pxref{Register Classes}).
+
+For example, on the S/390, some instructions do not accept arbitrary
+memory references, but only those that do not make use of an index
+register.  The constraint letter @samp{Q} is defined to represent a
+memory address of this type.  If @samp{Q} is defined with
+@code{define_memory_constraint}, a @samp{Q} constraint can handle any
+memory operand, because @code{reload} knows it can simply copy the
+memory address into a base register if required.  This is analogous to
+the way a @samp{o} constraint can handle any memory operand.
+
+The syntax and semantics are otherwise identical to
+@code{define_constraint}.
+@end deffn
+
+@deffn {MD Expression} define_address_constraint name docstring exp
+Use this expression for constraints that match a subset of all address
+operands: that is, @code{reload} can make the constraint match by
+converting the operand to the form @samp{@w{(reg @var{X})}}, again
+with @var{X} a base register.
+
+Constraints defined with @code{define_address_constraint} can only be
+used with the @code{address_operand} predicate, or machine-specific
+predicates that work the same way.  They are treated analogously to
+the generic @samp{p} constraint.
+
+The syntax and semantics are otherwise identical to
+@code{define_constraint}.
+@end deffn
+
+For historical reasons, names beginning with the letters @samp{G H}
+are reserved for constraints that match only @code{const_double}s, and
+names beginning with the letters @samp{I J K L M N O P} are reserved
+for constraints that match only @code{const_int}s.  This may change in
+the future.  For the time being, constraints with these names must be
+written in a stylized form, so that @code{genpreds} can tell you did
+it correctly:
+
+@smallexample
+@group
+(define_constraint "[@var{GHIJKLMNOP}]@dots{}"
+  "@var{doc}@dots{}"
+  (and (match_code "const_int")  ; @r{@code{const_double} for G/H}
+       @var{condition}@dots{}))            ; @r{usually a @code{match_test}}
+@end group
+@end smallexample
+@c the semicolons line up in the formatted manual
+
+It is fine to use names beginning with other letters for constraints
+that match @code{const_double}s or @code{const_int}s.
+
+Each docstring in a constraint definition should be one or more complete
+sentences, marked up in Texinfo format.  @emph{They are currently unused.}
+In the future they will be copied into the GCC manual, in @ref{Machine
+Constraints}, replacing the hand-maintained tables currently found in
+that section.  Also, in the future the compiler may use this to give
+more helpful diagnostics when poor choice of @code{asm} constraints
+causes a reload failure.
+
+If you put the pseudo-Texinfo directive @samp{@@internal} at the
+beginning of a docstring, then (in the future) it will appear only in
+the internals manual's version of the machine-specific constraint tables.
+Use this for constraints that should not appear in @code{asm} statements.
+
+@node C Constraint Interface
+@subsection Testing constraints from C
+@cindex testing constraints
+@cindex constraints, testing
+
+It is occasionally useful to test a constraint from C code rather than
+implicitly via the constraint string in a @code{match_operand}.  The
+generated file @file{tm_p.h} declares a few interfaces for working
+with machine-specific constraints.  None of these interfaces work with
+the generic constraints described in @ref{Simple Constraints}.  This
+may change in the future.
+
+@strong{Warning:} @file{tm_p.h} may declare other functions that
+operate on constraints, besides the ones documented here.  Do not use
+those functions from machine-dependent code.  They exist to implement
+the old constraint interface that machine-independent components of
+the compiler still expect.  They will change or disappear in the
+future.
+
+Some valid constraint names are not valid C identifiers, so there is a
+mangling scheme for referring to them from C@.  Constraint names that
+do not contain angle brackets or underscores are left unchanged.
+Underscores are doubled, each @samp{<} is replaced with @samp{_l}, and
+each @samp{>} with @samp{_g}.  Here are some examples:
+
+@c the @c's prevent double blank lines in the printed manual.
+@example
+@multitable {Original} {Mangled}
+@headitem Original @tab Mangled        @c
+@item @code{x}     @tab @code{x}       @c
+@item @code{P42x}  @tab @code{P42x}    @c
+@item @code{P4_x}  @tab @code{P4__x}   @c
+@item @code{P4>x}  @tab @code{P4_gx}   @c
+@item @code{P4>>}  @tab @code{P4_g_g}  @c
+@item @code{P4_g>} @tab @code{P4__g_g} @c
+@end multitable
+@end example
+
+Throughout this section, the variable @var{c} is either a constraint
+in the abstract sense, or a constant from @code{enum constraint_num};
+the variable @var{m} is a mangled constraint name (usually as part of
+a larger identifier).
+
+@deftp Enum constraint_num
+For each machine-specific constraint, there is a corresponding
+enumeration constant: @samp{CONSTRAINT_} plus the mangled name of the
+constraint.  Functions that take an @code{enum constraint_num} as an
+argument expect one of these constants.
+
+Machine-independent constraints do not have associated constants.
+This may change in the future.
+@end deftp
+
+@deftypefun {inline bool} satisfies_constraint_@var{m} (rtx @var{exp})
+For each machine-specific, non-register constraint @var{m}, there is
+one of these functions; it returns @code{true} if @var{exp} satisfies the
+constraint.  These functions are only visible if @file{rtl.h} was included
+before @file{tm_p.h}.
+@end deftypefun
+
+@deftypefun bool constraint_satisfied_p (rtx @var{exp}, enum constraint_num @var{c})
+Like the @code{satisfies_constraint_@var{m}} functions, but the
+constraint to test is given as an argument, @var{c}.  If @var{c}
+specifies a register constraint, this function will always return
+@code{false}.
+@end deftypefun
+
+@deftypefun {enum reg_class} regclass_for_constraint (enum constraint_num @var{c})
+Returns the register class associated with @var{c}.  If @var{c} is not
+a register constraint, or those registers are not available for the
+currently selected subtarget, returns @code{NO_REGS}.
+@end deftypefun
+
+Here is an example use of @code{satisfies_constraint_@var{m}}.  In
+peephole optimizations (@pxref{Peephole Definitions}), operand
+constraint strings are ignored, so if there are relevant constraints,
+they must be tested in the C condition.  In the example, the
+optimization is applied if operand 2 does @emph{not} satisfy the
+@samp{K} constraint.  (This is a simplified version of a peephole
+definition from the i386 machine description.)
+
+@smallexample
+(define_peephole2
+  [(match_scratch:SI 3 "r")
+   (set (match_operand:SI 0 "register_operand" "")
+	(mult:SI (match_operand:SI 1 "memory_operand" "")
+		 (match_operand:SI 2 "immediate_operand" "")))]
+
+  "!satisfies_constraint_K (operands[2])"
+
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2)))]
+
+  "")
+@end smallexample
+
 @node Standard Names
 @section Standard Pattern Names For Generation
 @cindex standard pattern names
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cebb71cdee22..778ecc9a9a56 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -33,6 +33,7 @@ through the macros defined in the @file{.h} file.
 * Type Layout::         Defining sizes and properties of basic user data types.
 * Registers::           Naming and describing the hardware registers.
 * Register Classes::    Defining the classes of hardware registers.
+* Old Constraints::     The old way to define machine-specific constraints.
 * Stack and Calling::   Defining which way the stack grows and by how much.
 * Varargs::		Defining the varargs macros.
 * Trampolines::         Code set up at run time to enter a nested function.
@@ -2300,36 +2301,6 @@ address where its value is either multiplied by a scale factor or
 added to another register (as well as added to a displacement).
 @end defmac
 
-@defmac CONSTRAINT_LEN (@var{char}, @var{str})
-For the constraint at the start of @var{str}, which starts with the letter
-@var{c}, return the length.  This allows you to have register class /
-constant / extra constraints that are longer than a single letter;
-you don't need to define this macro if you can do with single-letter
-constraints only.  The definition of this macro should use
-DEFAULT_CONSTRAINT_LEN for all the characters that you don't want
-to handle specially.
-There are some sanity checks in genoutput.c that check the constraint lengths
-for the md file, so you can also use this macro to help you while you are
-transitioning from a byzantine single-letter-constraint scheme: when you
-return a negative length for a constraint you want to re-use, genoutput
-will complain about every instance where it is used in the md file.
-@end defmac
-
-@defmac REG_CLASS_FROM_LETTER (@var{char})
-A C expression which defines the machine-dependent operand constraint
-letters for register classes.  If @var{char} is such a letter, the
-value should be the register class corresponding to it.  Otherwise,
-the value should be @code{NO_REGS}.  The register letter @samp{r},
-corresponding to class @code{GENERAL_REGS}, will not be passed
-to this macro; you do not need to handle it.
-@end defmac
-
-@defmac REG_CLASS_FROM_CONSTRAINT (@var{char}, @var{str})
-Like @code{REG_CLASS_FROM_LETTER}, but you also get the constraint string
-passed in @var{str}, so that you can use suffixes to distinguish between
-different variants.
-@end defmac
-
 @defmac REGNO_OK_FOR_BASE_P (@var{num})
 A C expression which is nonzero if register number @var{num} is
 suitable for use as a base register in operand addresses.  It may be
@@ -2682,8 +2653,45 @@ as below:
 @end smallexample
 @end defmac
 
-Three other special macros describe which operands fit which constraint
-letters.
+@node Old Constraints
+@section Obsolete Macros for Defining Constraints
+@cindex defining constraints, obsolete method
+@cindex constraints, defining, obsolete method
+
+Machine-specific constraints can be defined with these macros instead
+of the machine description constructs described in @ref{Define
+Constraints}.  This mechanism is obsolete.  New ports should not use
+it; old ports should convert to the new mechanism.
+
+@defmac CONSTRAINT_LEN (@var{char}, @var{str})
+For the constraint at the start of @var{str}, which starts with the letter
+@var{c}, return the length.  This allows you to have register class /
+constant / extra constraints that are longer than a single letter;
+you don't need to define this macro if you can do with single-letter
+constraints only.  The definition of this macro should use
+DEFAULT_CONSTRAINT_LEN for all the characters that you don't want
+to handle specially.
+There are some sanity checks in genoutput.c that check the constraint lengths
+for the md file, so you can also use this macro to help you while you are
+transitioning from a byzantine single-letter-constraint scheme: when you
+return a negative length for a constraint you want to re-use, genoutput
+will complain about every instance where it is used in the md file.
+@end defmac
+
+@defmac REG_CLASS_FROM_LETTER (@var{char})
+A C expression which defines the machine-dependent operand constraint
+letters for register classes.  If @var{char} is such a letter, the
+value should be the register class corresponding to it.  Otherwise,
+the value should be @code{NO_REGS}.  The register letter @samp{r},
+corresponding to class @code{GENERAL_REGS}, will not be passed
+to this macro; you do not need to handle it.
+@end defmac
+
+@defmac REG_CLASS_FROM_CONSTRAINT (@var{char}, @var{str})
+Like @code{REG_CLASS_FROM_LETTER}, but you also get the constraint string
+passed in @var{str}, so that you can use suffixes to distinguish between
+different variants.
+@end defmac
 
 @defmac CONST_OK_FOR_LETTER_P (@var{value}, @var{c})
 A C expression that defines the machine-dependent operand constraint
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index 7d1feb6fdcaf..4eac58187296 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -54,12 +54,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
      a. `predicate', an int-valued function, is the match_operand predicate
      for this operand.
 
-     b. `constraint' is the constraint for this operand.  This exists
-     only if register constraints appear in match_operand rtx's.
+     b. `constraint' is the constraint for this operand.
 
      c. `address_p' indicates that the operand appears within ADDRESS
-     rtx's.  This exists only if there are *no* register constraints
-     in the match_operand rtx's.
+     rtx's.
 
      d. `mode' is the machine mode that that operand is supposed to have.
 
@@ -189,8 +187,35 @@ static void gen_insn (rtx, int);
 static void gen_peephole (rtx, int);
 static void gen_expand (rtx, int);
 static void gen_split (rtx, int);
+
+#ifdef USE_MD_CONSTRAINTS
+
+struct constraint_data
+{
+  struct constraint_data *next_this_letter;
+  int lineno;
+  unsigned int namelen;
+  const char name[1];
+};
+
+/* This is a complete list (unlike the one in genpreds.c) of constraint
+   letters and modifiers with machine-independent meaning.  The only
+   omission is digits, as these are handled specially.  */
+static const char indep_constraints[] = ",=+%*?!#&<>EFVXgimnoprs";
+
+static struct constraint_data *
+constraints_by_letter_table[1 << CHAR_BIT];
+
+static int mdep_constraint_len (const char *, int, int);
+static void note_constraint (rtx, int);
+
+#else  /* !USE_MD_CONSTRAINTS */
+
 static void check_constraint_len (void);
 static int constraint_len (const char *, int);
+
+#endif /* !USE_MD_CONSTRAINTS */
+
 
 static void
 output_prologue (void)
@@ -725,6 +750,20 @@ validate_insn_alternatives (struct data *d)
 
 	for (p = d->operand[start].constraint; (c = *p); p += len)
 	  {
+#ifdef USE_MD_CONSTRAINTS
+	    if (ISSPACE (c) || strchr (indep_constraints, c))
+	      len = 1;
+	    else if (ISDIGIT (c))
+	      {
+		const char *q = p;
+		do
+		  q++;
+		while (ISDIGIT (*q));
+		len = q - p;
+	      }
+	    else
+	      len = mdep_constraint_len (p, d->lineno, start);
+#else
 	    len = CONSTRAINT_LEN (c, p);
 
 	    if (len < 1 || (len > 1 && strchr (",#*+=&%!0123456789", c)))
@@ -735,6 +774,7 @@ validate_insn_alternatives (struct data *d)
 		len = 1;
 		have_error = 1;
 	      }
+#endif
 
 	    if (c == ',')
 	      {
@@ -826,7 +866,9 @@ gen_insn (rtx insn, int lineno)
   d->n_operands = max_opno + 1;
   d->n_dups = num_dups;
 
+#ifndef USE_MD_CONSTRAINTS
   check_constraint_len ();
+#endif
   validate_insn_operands (d);
   validate_insn_alternatives (d);
   place_operands (d);
@@ -983,15 +1025,37 @@ main (int argc, char **argv)
       if (desc == NULL)
 	break;
 
-      if (GET_CODE (desc) == DEFINE_INSN)
-	gen_insn (desc, line_no);
-      if (GET_CODE (desc) == DEFINE_PEEPHOLE)
-	gen_peephole (desc, line_no);
-      if (GET_CODE (desc) == DEFINE_EXPAND)
-	gen_expand (desc, line_no);
-      if (GET_CODE (desc) == DEFINE_SPLIT
-	  || GET_CODE (desc) == DEFINE_PEEPHOLE2)
-	gen_split (desc, line_no);
+      switch (GET_CODE (desc))
+	{
+	case DEFINE_INSN:
+	  gen_insn (desc, line_no);
+	  break;
+
+	case DEFINE_PEEPHOLE:
+	  gen_peephole (desc, line_no);
+	  break;
+
+	case DEFINE_EXPAND:
+	  gen_expand (desc, line_no);
+	  break;
+
+	case DEFINE_SPLIT:
+	case DEFINE_PEEPHOLE2:
+	  gen_split (desc, line_no);
+	  break;
+
+#ifdef USE_MD_CONSTRAINTS
+	case DEFINE_CONSTRAINT:
+	case DEFINE_REGISTER_CONSTRAINT:
+	case DEFINE_ADDRESS_CONSTRAINT:
+	case DEFINE_MEMORY_CONSTRAINT:
+	  note_constraint (desc, line_no);
+	  break;
+#endif
+
+	default:
+	  break;
+	}
       next_index_number++;
     }
 
@@ -1043,6 +1107,102 @@ strip_whitespace (const char *s)
   return q;
 }
 
+#ifdef USE_MD_CONSTRAINTS
+
+/* Record just enough information about a constraint to allow checking
+   of operand constraint strings above, in validate_insn_alternatives.
+   Does not validate most properties of the constraint itself; does
+   enforce no duplicate names, no overlap with MI constraints, and no
+   prefixes.  EXP is the define_*constraint form, LINENO the line number
+   reported by the reader.  */
+static void
+note_constraint (rtx exp, int lineno)
+{
+  const char *name = XSTR (exp, 0);
+  unsigned int namelen = strlen (name);
+  struct constraint_data **iter, **slot, *new;
+
+  if (strchr (indep_constraints, name[0]))
+    {
+      if (name[1] == '\0')
+	message_with_line (lineno, "constraint letter '%s' cannot be "
+			   "redefined by the machine description", name);
+      else
+	message_with_line (lineno, "constraint name '%s' cannot be defined by "
+			   "the machine description, as it begins with '%c'",
+			   name, name[0]);
+      have_error = 1;
+      return;
+    }
+
+  slot = &constraints_by_letter_table[(unsigned int)name[0]];
+  for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
+    {
+      /* This causes slot to end up pointing to the
+	 next_this_letter field of the last constraint with a name
+	 of equal or greater length than the new constraint; hence
+	 the new constraint will be inserted after all previous
+	 constraints with names of the same length.  */
+      if ((*iter)->namelen >= namelen)
+	slot = iter;
+
+      if (!strcmp ((*iter)->name, name))
+	{
+	  message_with_line (lineno, "redefinition of constraint '%s'", name);
+	  message_with_line ((*iter)->lineno, "previous definition is here");
+	  have_error = 1;
+	  return;
+	}
+      else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
+	{
+	  message_with_line (lineno, "defining constraint '%s' here", name);
+	  message_with_line ((*iter)->lineno, "renders constraint '%s' "
+			     "(defined here) a prefix", (*iter)->name);
+	  have_error = 1;
+	  return;
+	}
+      else if (!strncmp ((*iter)->name, name, namelen))
+	{
+	  message_with_line (lineno, "constraint '%s' is a prefix", name);
+	  message_with_line ((*iter)->lineno, "of constraint '%s' "
+			     "(defined here)", (*iter)->name);
+	  have_error = 1;
+	  return;
+	}
+    }
+  new = xmalloc (sizeof (struct constraint_data) + namelen);
+  strcpy ((char *)new + offsetof(struct constraint_data, name), name);
+  new->namelen = namelen;
+  new->lineno = lineno;
+  new->next_this_letter = *slot;
+  *slot = new;
+}
+
+/* Return the length of the constraint name beginning at position S
+   of an operand constraint string, or issue an error message if there
+   is no such constraint.  Does not expect to be called for generic
+   constraints.  */
+static int
+mdep_constraint_len (const char *s, int lineno, int opno)
+{
+  struct constraint_data *p;
+
+  p = constraints_by_letter_table[(unsigned int)s[0]];
+
+  if (p)
+    for (; p; p = p->next_this_letter)
+      if (!strncmp (s, p->name, p->namelen))
+	return p->namelen;
+
+  message_with_line (lineno,
+		     "error: undefined machine-specific constraint "
+		     "at this point: \"%s\"", s);
+  message_with_line (lineno, "note:  in operand %d", opno);
+  have_error = 1;
+  return 1; /* safe */
+}
+
+#else
 /* Verify that DEFAULT_CONSTRAINT_LEN is used properly and not
    tampered with.  This isn't bullet-proof, but it should catch
    most genuine mistakes.  */
@@ -1076,3 +1236,4 @@ constraint_len (const char *p, int genoutput_default_constraint_len)
 #undef DEFAULT_CONSTRAINT_LEN
 #define DEFAULT_CONSTRAINT_LEN(C,STR) 1
 }
+#endif
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index bfd681cc7b8b..9c0bb352e17a 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -27,57 +27,102 @@ Boston, MA 02110-1301, USA.  */
 #include "tm.h"
 #include "rtl.h"
 #include "errors.h"
-#include "gensupport.h"
 #include "obstack.h"
+#include "gensupport.h"
 
-/* The new way to declare predicates is with (define_predicate) or
-   (define_special_predicate) expressions in the machine description.
-   This provides a function body as well as a name.  */
-static void
-process_define_predicate (rtx defn)
+/* Given a predicate expression EXP, from form NAME at line LINENO,
+   verify that it does not contain any RTL constructs which are not
+   valid in predicate definitions.  Returns true if EXP is
+   INvalid; issues error messages, caller need not.  */
+static bool
+validate_exp (rtx exp, const char *name, int lineno)
 {
-  struct pred_data *pred;
-  if (XEXP (defn, 1) == 0)
+  if (exp == 0)
     {
-      error ("%s: must give a predicate expression", XSTR (defn, 0));
-      return;
+      message_with_line (lineno, "%s: must give a predicate expression", name);
+      return true;
     }
 
-  pred = XCNEW (struct pred_data);
-  pred->name    = XSTR (defn, 0);
-  pred->exp     = XEXP (defn, 1);
-  pred->c_block = XSTR (defn, 2);
+  switch (GET_CODE (exp))
+    {
+      /* Ternary, binary, unary expressions: recurse into subexpressions.  */
+    case IF_THEN_ELSE:
+      if (validate_exp (XEXP (exp, 2), name, lineno))
+	return true;
+      /* else fall through */
+    case AND:
+    case IOR:
+      if (validate_exp (XEXP (exp, 1), name, lineno))
+	return true;
+      /* else fall through */
+    case NOT:
+      return validate_exp (XEXP (exp, 0), name, lineno);
 
-  if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
-    pred->special = true;
+      /* MATCH_CODE might have a syntax error in its path expression.  */
+    case MATCH_CODE:
+      {
+	const char *p;
+	for (p = XSTR (exp, 1); *p; p++)
+	  {
+	    if (!ISDIGIT (*p) && !ISLOWER (*p))
+	      {
+		message_with_line (lineno, "%s: invalid character in path "
+				   "string '%s'", name, XSTR (exp, 1));
+		have_error = 1;
+		return true;
+	      }
+	  }
+      }
+      /* fall through */
 
-  add_predicate (pred);
+      /* These need no special checking.  */
+    case MATCH_OPERAND:
+    case MATCH_TEST:
+      return false;
+
+    default:
+      message_with_line (lineno,
+			 "%s: cannot use '%s' in a predicate expression",
+			 name, GET_RTX_NAME (GET_CODE (exp)));
+      have_error = 1;
+      return true;
+    }
 }
 
-/* Write tm-preds.h.  Unfortunately, it is impossible to forward-declare
-   an enumeration in portable C, so we have to condition all these
-   prototypes on HAVE_MACHINE_MODES.  */
+/* Predicates are defined with (define_predicate) or
+   (define_special_predicate) expressions in the machine description.  */
 static void
-write_tm_preds_h (void)
+process_define_predicate (rtx defn, int lineno)
 {
-  struct pred_data *p;
+  struct pred_data *pred;
+  const char *p;
 
-  printf ("\
-/* Generated automatically by the program '%s'\n\
-   from the machine description file '%s'.  */\n\n", progname, in_fname);
+  if (!ISALPHA (XSTR (defn, 0)[0]) && XSTR (defn, 0)[0] != '_')
+    goto bad_name;
+  for (p = XSTR (defn, 0) + 1; *p; p++)
+    if (!ISALNUM (*p) && *p != '_')
+      goto bad_name;
+  
+  if (validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno))
+    return;
 
-  puts ("\
-#ifndef GCC_TM_PREDS_H\n\
-#define GCC_TM_PREDS_H\n\
-\n\
-#ifdef HAVE_MACHINE_MODES");
+  pred = XCNEW (struct pred_data);
+  pred->name = XSTR (defn, 0);
+  pred->exp = XEXP (defn, 1);
+  pred->c_block = XSTR (defn, 2);
 
-  FOR_ALL_PREDICATES (p)
-    printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
+  if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
+    pred->special = true;
 
-  puts ("\
-#endif /* HAVE_MACHINE_MODES */\n\
-#endif /* tm-preds.h */");
+  add_predicate (pred);
+  return;
+
+ bad_name:
+  message_with_line (lineno,
+		     "%s: predicate name must be a valid C function name",
+		     XSTR (defn, 0));
+  have_error = 1;
+  return;
 }
 
 /* Given a predicate, if it has an embedded C block, write the block
@@ -146,6 +191,59 @@ write_predicate_subfunction (struct pred_data *p)
   fputs ("\n\n", stdout);
 }
 
+/* Given a predicate expression EXP, from form NAME, determine whether
+   it refers to the variable given as VAR.  */
+static bool
+needs_variable (rtx exp, const char *var)
+{
+  switch (GET_CODE (exp))
+    {
+      /* Ternary, binary, unary expressions need a variable if
+	 any of their subexpressions do.  */
+    case IF_THEN_ELSE:
+      if (needs_variable (XEXP (exp, 2), var))
+	return true;
+      /* else fall through */
+    case AND:
+    case IOR:
+      if (needs_variable (XEXP (exp, 1), var))
+	return true;
+      /* else fall through */
+    case NOT:
+      return needs_variable (XEXP (exp, 0), var);
+
+      /* MATCH_CODE uses "op", but nothing else.  */
+    case MATCH_CODE:
+      return !strcmp (var, "op");
+
+      /* MATCH_OPERAND uses "op" and may use "mode".  */
+    case MATCH_OPERAND:
+      if (!strcmp (var, "op"))
+	return true;
+      if (!strcmp (var, "mode") && GET_MODE (exp) == VOIDmode)
+	return true;
+      return false;
+
+      /* MATCH_TEST uses var if XSTR (exp, 0) =~ /\b${var}\b/o; */
+    case MATCH_TEST:
+      {
+	const char *p = XSTR (exp, 0);
+	const char *q = strstr (p, var);
+	if (!q)
+	  return false;
+	if (q != p && (ISALNUM (q[-1]) || q[-1] == '_'))
+	  return false;
+	q += strlen (var);
+	if (ISALNUM (q[0] || q[0] == '_'))
+	  return false;
+      }
+      return true;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
 /* Given an RTL expression EXP, find all subexpressions which we may
    assume to perform mode tests.  Normal MATCH_OPERAND does;
    MATCH_CODE does if it applies to the whole expression and accepts
@@ -214,8 +312,7 @@ mark_mode_tests (rtx exp)
       break;
 
     default:
-      error ("'%s' cannot be used in a define_predicate expression",
-	     GET_RTX_NAME (GET_CODE (exp)));
+      gcc_unreachable ();
     }
 }
 
@@ -325,10 +422,7 @@ write_extract_subexp (const char *path)
       else if (ISDIGIT (path[i]))
 	fputs ("XEXP (", stdout);
       else
-	{
-	  error ("bad character in path string '%s'", path);
-	  return;
-	}
+	gcc_unreachable ();
     }
 
   fputs ("op", stdout);
@@ -370,39 +464,39 @@ write_match_code (const char *path, const char *codes)
 /* EXP is an RTL (sub)expression for a predicate.  Recursively
    descend the expression and write out an equivalent C expression.  */
 static void
-write_predicate_expr (const char *name, rtx exp)
+write_predicate_expr (rtx exp)
 {
   switch (GET_CODE (exp))
     {
     case AND:
       putchar ('(');
-      write_predicate_expr (name, XEXP (exp, 0));
+      write_predicate_expr (XEXP (exp, 0));
       fputs (") && (", stdout);
-      write_predicate_expr (name, XEXP (exp, 1));
+      write_predicate_expr (XEXP (exp, 1));
       putchar (')');
       break;
   
     case IOR:
       putchar ('(');
-      write_predicate_expr (name, XEXP (exp, 0));
+      write_predicate_expr (XEXP (exp, 0));
       fputs (") || (", stdout);
-      write_predicate_expr (name, XEXP (exp, 1));
+      write_predicate_expr (XEXP (exp, 1));
       putchar (')');
       break;
 
     case NOT:
       fputs ("!(", stdout);
-      write_predicate_expr (name, XEXP (exp, 0));
+      write_predicate_expr (XEXP (exp, 0));
       putchar (')');
       break;
 
     case IF_THEN_ELSE:
       putchar ('(');
-      write_predicate_expr (name, XEXP (exp, 0));
+      write_predicate_expr (XEXP (exp, 0));
       fputs (") ? (", stdout);
-      write_predicate_expr (name, XEXP (exp, 1));
+      write_predicate_expr (XEXP (exp, 1));
       fputs (") : (", stdout);
-      write_predicate_expr (name, XEXP (exp, 2));
+      write_predicate_expr (XEXP (exp, 2));
       putchar (')');
       break;
 
@@ -422,9 +516,7 @@ write_predicate_expr (const char *name, rtx exp)
       break;
 
     default:
-      error ("%s: cannot use '%s' in a predicate expression",
-	     name, GET_RTX_NAME (GET_CODE (exp)));
-      putchar ('0');
+      gcc_unreachable ();
     }
 }
 
@@ -443,9 +535,651 @@ write_one_predicate_function (struct pred_data *p)
   printf ("int\n%s (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)\n"
 	  "{\n  return ",
 	  p->name);
-  write_predicate_expr (p->name, p->exp);
+  write_predicate_expr (p->exp);
   fputs (";\n}\n\n", stdout);
 }
+
+/* Constraints fall into two categories: register constraints
+   (define_register_constraint), and others (define_constraint,
+   define_memory_constraint, define_address_constraint).  We
+   work out automatically which of the various old-style macros
+   they correspond to, and produce appropriate code.  They all
+   go in the same hash table so we can verify that there are no
+   duplicate names.  */
+
+/* All data from one constraint definition.  */
+struct constraint_data
+{
+  struct constraint_data *next_this_letter;
+  struct constraint_data *next_textual;
+  const char *name;
+  const char *c_name;    /* same as .name unless mangling is necessary */
+  size_t namelen;
+  const char *regclass;  /* for register constraints */
+  rtx exp;               /* for other constraints */
+  unsigned int lineno;   /* line of definition */
+  unsigned int is_register  : 1;
+  unsigned int is_const_int : 1;
+  unsigned int is_const_dbl : 1;
+  unsigned int is_extra     : 1;
+  unsigned int is_memory    : 1;
+  unsigned int is_address   : 1;
+};
+
+/* Overview of all constraints beginning with a given letter.  */
+
+static struct constraint_data *
+constraints_by_letter_table[1<<CHAR_BIT];
+
+/* For looking up all the constraints in the order that they appeared
+   in the machine description.  */
+static struct constraint_data *first_constraint;
+static struct constraint_data **last_constraint_ptr = &first_constraint;
+
+#define FOR_ALL_CONSTRAINTS(iter_) \
+  for (iter_ = first_constraint; iter_; iter_ = iter_->next_textual)
+
+/* These letters, and all names beginning with them, are reserved for
+   generic constraints.  */
+static const char generic_constraint_letters[] = "EFVXgimnoprs";
+
+/* Machine-independent code expects that constraints with these
+   (initial) letters will allow only (a subset of all) CONST_INTs.  */
+
+static const char const_int_constraints[] = "IJKLMNOP";
+
+/* Machine-independent code expects that constraints with these
+   (initial) letters will allow only (a subset of all) CONST_DOUBLEs.  */
+
+static const char const_dbl_constraints[] = "GH";
+
+/* Summary data used to decide whether to output various functions and
+   macro definitions.  */
+static unsigned int constraint_max_namelen;
+static bool have_register_constraints;
+static bool have_memory_constraints;
+static bool have_address_constraints;
+static bool have_extra_constraints;
+static bool have_const_int_constraints;
+static bool have_const_dbl_constraints;
+
+/* Convert NAME, which contains angle brackets and/or underscores, to
+   a string that can be used as part of a C identifier.  The string
+   comes from the rtl_obstack.  */
+static const char *
+mangle (const char *name)
+{
+  for (; *name; name++)
+    switch (*name)
+      {
+      case '_': obstack_grow (rtl_obstack, "__", 2); break;
+      case '<':	obstack_grow (rtl_obstack, "_l", 2); break;
+      case '>':	obstack_grow (rtl_obstack, "_g", 2); break;
+      default: obstack_1grow (rtl_obstack, *name); break;
+      }
+
+  obstack_1grow (rtl_obstack, '\0');
+  return obstack_finish (rtl_obstack);
+}
+
+/* Add one constraint, of any sort, to the tables.  NAME is its name;
+   REGCLASS is the register class, if any; EXP is the expression to
+   test, if any;  IS_MEMORY and IS_ADDRESS indicate memory and address
+   constraints, respectively; LINENO is the line number from the MD reader.
+   Not all combinations of arguments are valid; most importantly, REGCLASS
+   is mutually exclusive with EXP, and IS_MEMORY/IS_ADDRESS are only
+   meaningful for constraints with EXP.
+
+   This function enforces all syntactic and semantic rules about what
+   constraints can be defined.  */
+
+static void
+add_constraint (const char *name, const char *regclass,
+		rtx exp, bool is_memory, bool is_address,
+		int lineno)
+{
+  struct constraint_data *c, **iter, **slot;
+  const char *p;
+  bool need_mangled_name = false;
+  bool is_const_int;
+  bool is_const_dbl;
+  size_t namelen;
+
+  if (exp && validate_exp (exp, name, lineno))
+    return;
+
+  if (!ISALPHA (name[0]) && name[0] != '_')
+    {
+      if (name[1] == '\0')
+	message_with_line (lineno, "constraint name '%s' is not "
+			   "a letter or underscore", name);
+      else
+	message_with_line (lineno, "constraint name '%s' does not begin "
+			   "with a letter or underscore", name);
+      have_error = 1;
+      return;
+    }
+  for (p = name; *p; p++)
+    if (!ISALNUM (*p))
+      {
+	if (*p == '<' || *p == '>' || *p == '_')
+	  need_mangled_name = true;
+	else
+	  {
+	    message_with_line (lineno,
+			       "constraint name '%s' must be composed of "
+			       "letters, digits, underscores, and "
+			       "angle brackets", name);
+	    have_error = 1;
+	    return;
+	  }
+      }
+
+  if (strchr (generic_constraint_letters, name[0]))
+    {
+      if (name[1] == '\0')
+	message_with_line (lineno, "constraint letter '%s' cannot be "
+			   "redefined by the machine description", name);
+      else
+	message_with_line (lineno, "constraint name '%s' cannot be defined by "
+			   "the machine description, as it begins with '%c'",
+			   name, name[0]);
+      have_error = 1;
+      return;
+    }
+
+  
+  namelen = strlen (name);
+  slot = &constraints_by_letter_table[(unsigned int)name[0]];
+  for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
+    {
+      /* This causes slot to end up pointing to the
+	 next_this_letter field of the last constraint with a name
+	 of equal or greater length than the new constraint; hence
+	 the new constraint will be inserted after all previous
+	 constraints with names of the same length.  */
+      if ((*iter)->namelen >= namelen)
+	slot = iter;
+
+      if (!strcmp ((*iter)->name, name))
+	{
+	  message_with_line (lineno, "redefinition of constraint '%s'", name);
+	  message_with_line ((*iter)->lineno, "previous definition is here");
+	  have_error = 1;
+	  return;
+	}
+      else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
+	{
+	  message_with_line (lineno, "defining constraint '%s' here", name);
+	  message_with_line ((*iter)->lineno, "renders constraint '%s' "
+			     "(defined here) a prefix", (*iter)->name);
+	  have_error = 1;
+	  return;
+	}
+      else if (!strncmp ((*iter)->name, name, namelen))
+	{
+	  message_with_line (lineno, "constraint '%s' is a prefix", name);
+	  message_with_line ((*iter)->lineno, "of constraint '%s' "
+			     "(defined here)", (*iter)->name);
+	  have_error = 1;
+	  return;
+	}
+    }
+
+  is_const_int = strchr (const_int_constraints, name[0]) != 0;
+  is_const_dbl = strchr (const_dbl_constraints, name[0]) != 0;
+
+  if (is_const_int || is_const_dbl)
+    {
+      enum rtx_code appropriate_code
+	= is_const_int ? CONST_INT : CONST_DOUBLE;
+
+      /* Consider relaxing this requirement in the future.  */
+      if (regclass
+	  || GET_CODE (exp) != AND
+	  || GET_CODE (XEXP (exp, 0)) != MATCH_CODE
+	  || strcmp (XSTR (XEXP (exp, 0), 0),
+		     GET_RTX_NAME (appropriate_code)))
+	{
+	  if (name[1] == '\0')
+	    message_with_line (lineno, "constraint letter '%c' is reserved "
+			       "for %s constraints",
+			       name[0], GET_RTX_NAME (appropriate_code));
+	  else
+	    message_with_line (lineno, "constraint names beginning with '%c' "
+			       "(%s) are reserved for %s constraints",
+			       name[0], name, 
+			       GET_RTX_NAME (appropriate_code));
+
+	  have_error = 1;
+	  return;
+	}
+
+      if (is_memory)
+	{
+	  if (name[1] == '\0')
+	    message_with_line (lineno, "constraint letter '%c' cannot be a "
+			       "memory constraint", name[0]);
+	  else
+	    message_with_line (lineno, "constraint name '%s' begins with '%c', "
+			       "and therefore cannot be a memory constraint",
+			       name, name[0]);
+
+	  have_error = 1;
+	  return;
+	}
+      else if (is_address)
+	{
+	  if (name[1] == '\0')
+	    message_with_line (lineno, "constraint letter '%c' cannot be a "
+			       "memory constraint", name[0]);
+	  else
+	    message_with_line (lineno, "constraint name '%s' begins with '%c', "
+			       "and therefore cannot be a memory constraint",
+			       name, name[0]);
+
+	  have_error = 1;
+	  return;
+	}
+
+      /* Remove the redundant (and (match_code "const_(int|double)")
+	 from the expression.  */
+      exp = XEXP (exp, 1);
+    }
+
+  
+  c = obstack_alloc (rtl_obstack, sizeof (struct constraint_data));
+  c->name = name;
+  c->c_name = need_mangled_name ? mangle (name) : name;
+  c->lineno = lineno;
+  c->namelen = namelen;
+  c->regclass = regclass;
+  c->exp = exp;
+  c->is_register = regclass != 0;
+  c->is_const_int = is_const_int;
+  c->is_const_dbl = is_const_dbl;
+  c->is_extra = !(regclass || is_const_int || is_const_dbl);
+  c->is_memory = is_memory;
+  c->is_address = is_address;
+
+  c->next_this_letter = *slot;
+  *slot = c;
+
+  /* Insert this constraint in the list of all constraints in textual
+     order.  */
+  c->next_textual = 0;
+  *last_constraint_ptr = c;
+  last_constraint_ptr = &c->next_textual;
+
+  constraint_max_namelen = MAX (constraint_max_namelen, strlen (name));
+  have_register_constraints |= c->is_register;
+  have_const_int_constraints |= c->is_const_int;
+  have_const_dbl_constraints |= c->is_const_dbl;
+  have_extra_constraints |= c->is_extra;
+  have_memory_constraints |= c->is_memory;
+  have_address_constraints |= c->is_address;
+}
+
+/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or
+   DEFINE_ADDRESS_CONSTRAINT expression, C.  */
+static void
+process_define_constraint (rtx c, int lineno)
+{
+  add_constraint (XSTR (c, 0), 0, XEXP (c, 2),
+		  GET_CODE (c) == DEFINE_MEMORY_CONSTRAINT,
+		  GET_CODE (c) == DEFINE_ADDRESS_CONSTRAINT,
+		  lineno);
+}
+
+/* Process a DEFINE_REGISTER_CONSTRAINT expression, C.  */
+static void
+process_define_register_constraint (rtx c, int lineno)
+{
+  add_constraint (XSTR (c, 0), XSTR (c, 1), 0, false, false, lineno);
+}
+
+/* Write out an enumeration with one entry per machine-specific
+   constraint.  */
+static void
+write_enum_constraint_num (void)
+{
+  struct constraint_data *c;
+
+  fputs ("enum constraint_num\n"
+	 "{\n"
+	 "  CONSTRAINT__UNKNOWN = 0", stdout);
+  FOR_ALL_CONSTRAINTS (c)
+    printf (",\n  CONSTRAINT_%s", c->c_name);
+  puts ("\n};\n");
+}
+
+/* Write out a function which looks at a string and determines what
+   constraint name, if any, it begins with.  */
+static void
+write_lookup_constraint (void)
+{
+  unsigned int i;
+  puts ("enum constraint_num\n"
+	"lookup_constraint (const char *str)\n"
+	"{\n"
+	"  switch (str[0])\n"
+	"    {");
+
+  for (i = 0; i < ARRAY_SIZE(constraints_by_letter_table); i++)
+    {
+      struct constraint_data *c = constraints_by_letter_table[i];
+      if (!c)
+	continue;
+
+      printf ("    case '%c':\n", i);
+      if (c->namelen == 1)
+	printf ("      return CONSTRAINT_%s;\n", c->c_name);
+      else
+	{
+	  do
+	    {
+	      printf ("      if (!strncmp (str, \"%s\", %lu))\n"
+		      "        return CONSTRAINT_%s;\n",
+		      c->name, (unsigned long int) c->namelen, c->c_name);
+	      c = c->next_this_letter;
+	    }
+	  while (c);
+	  puts ("      break;");
+	}
+    }
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return CONSTRAINT__UNKNOWN;\n"
+	"}\n");
+}
+
+/* Write out the function which computes constraint name lengths from
+   their enumerators. */
+static void
+write_insn_constraint_len (void)
+{
+  struct constraint_data *c;
+
+  if (constraint_max_namelen == 1)
+    return;
+
+  puts ("unsigned int\n"
+	"insn_constraint_len (enum constraint_num c)\n"
+	"{\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (c->namelen > 1)
+      printf ("    case CONSTRAINT_%s: return %lu;\n", c->c_name,
+	      (unsigned long int) c->namelen);
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return 1;\n"
+	"}\n");
+}
+  
+/* Write out the function which computes the register class corresponding
+   to a register constraint.  */
+static void
+write_regclass_for_constraint (void)
+{
+  struct constraint_data *c;
+
+  puts ("enum reg_class\n"
+	"regclass_for_constraint (enum constraint_num c)\n"
+	"{\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (c->is_register)
+      printf ("    case CONSTRAINT_%s: return %s;\n", c->c_name, c->regclass);
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return NO_REGS;\n"
+	"}\n");
+}
+
+/* Write out the functions which compute whether a given value matches
+   a given non-register constraint.  */
+static void
+write_satisfies_constraint_fns (void)
+{
+  struct constraint_data *c;
+
+  /* A fair number of places include tm_p.h without including rtl.h.  */
+  puts ("#ifdef GCC_RTL_H\n");
+  
+  FOR_ALL_CONSTRAINTS (c)
+    if (!c->is_register)
+      {
+	bool needs_ival = needs_variable (c->exp, "ival");
+	bool needs_hval = needs_variable (c->exp, "hval");
+	bool needs_lval = needs_variable (c->exp, "lval");
+	bool needs_rval = needs_variable (c->exp, "rval");
+	bool needs_mode = (needs_variable (c->exp, "mode")
+			   || needs_hval || needs_lval || needs_rval);
+
+	printf ("static inline bool\n"
+		"satisfies_constraint_%s (rtx op)\n"
+		"{\n", c->c_name);
+	if (needs_mode)
+	  puts ("enum machine_mode mode = GET_MODE (op);");
+	if (needs_ival)
+	  puts ("  HOST_WIDE_INT ival = 0;");
+	if (needs_hval)
+	  puts ("  HOST_WIDE_INT hval = 0;");
+	if (needs_lval)
+	  puts ("  unsigned HOST_WIDE_INT lval = 0;");
+	if (needs_rval)
+	  puts ("  const REAL_VALUE_TYPE *rval = 0;");
+
+	if (needs_ival)
+	  puts ("  if (GET_CODE (op) == CONST_INT)\n"
+		"    ival = INTVAL (op);");
+	if (needs_hval)
+	  puts ("  if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
+		"    hval = CONST_DOUBLE_HIGH (op);");
+	if (needs_lval)
+	  puts ("  if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
+		"    lval = CONST_DOUBLE_LOW (op);");
+	if (needs_rval)
+	  puts ("  if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)"
+		"    rval = CONST_DOUBLE_REAL_VALUE (op);");
+	  
+	fputs ("  return ", stdout);
+	write_predicate_expr (c->exp);
+	fputs (";\n}\n", stdout);
+      }
+
+  puts ("\n#endif /* rtl.h visible */\n");
+}
+
+/* Write out the wrapper function, constraint_satisfied_p, that maps
+   a CONSTRAINT_xxx constant to one of the predicate functions generated
+   above.  */
+static void
+write_constraint_satisfied_p (void)
+{
+  struct constraint_data *c;
+
+  puts ("bool\n"
+	"constraint_satisfied_p (rtx op, enum constraint_num c)\n"
+	"{\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (!c->is_register)
+      printf ("    case CONSTRAINT_%s: "
+	      "return satisfies_constraint_%s (op);\n",
+	      c->c_name, c->c_name);
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return false;\n"
+	"}\n");
+}
+
+/* Write out the function which computes whether a given value matches
+   a given CONST_INT constraint.  This doesn't just forward to
+   constraint_satisfied_p because caller passes the INTVAL, not the RTX.  */
+static void
+write_insn_const_int_ok_for_constraint (void)
+{
+  struct constraint_data *c;
+
+  puts ("bool\n"
+	"insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, "
+	                                  "enum constraint_num c)\n"
+	"{\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (c->is_const_int)
+      {
+	printf ("    case CONSTRAINT_%s:\n      return ", c->c_name);
+	write_predicate_expr (c->exp);
+	fputs (";\n\n", stdout);
+      }
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return false;\n"
+	"}\n");
+}
+
+
+/* Write out the function which computes whether a given constraint is
+   a memory constraint.  */
+static void
+write_insn_extra_memory_constraint (void)
+{
+  struct constraint_data *c;
+
+  puts ("bool\n"
+	"insn_extra_memory_constraint (enum constraint_num c)\n"
+	"{\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (c->is_memory)
+      printf ("    case CONSTRAINT_%s:\n      return true;\n\n", c->c_name);
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return false;\n"
+	"}\n");
+}
+
+/* Write out the function which computes whether a given constraint is
+   an address constraint.  */
+static void
+write_insn_extra_address_constraint (void)
+{
+  struct constraint_data *c;
+
+  puts ("bool\n"
+	"insn_extra_address_constraint (enum constraint_num c)\n"
+	"{\n"
+	"  switch (str[0])\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    if (c->is_address)
+      printf ("    case CONSTRAINT_%s:\n      return true;\n\n", c->c_name);
+
+  puts ("    default: break;\n"
+	"    }\n"
+	"  return false;\n"
+	"}\n");
+}
+
+
+/* Write tm-preds.h.  Unfortunately, it is impossible to forward-declare
+   an enumeration in portable C, so we have to condition all these
+   prototypes on HAVE_MACHINE_MODES.  */
+static void
+write_tm_preds_h (void)
+{
+  struct pred_data *p;
+
+  printf ("\
+/* Generated automatically by the program '%s'\n\
+   from the machine description file '%s'.  */\n\n", progname, in_fname);
+
+  puts ("\
+#ifndef GCC_TM_PREDS_H\n\
+#define GCC_TM_PREDS_H\n\
+\n\
+#ifdef HAVE_MACHINE_MODES");
+
+  FOR_ALL_PREDICATES (p)
+    printf ("extern int %s (rtx, enum machine_mode);\n", p->name);
+
+  puts ("#endif /* HAVE_MACHINE_MODES */\n");
+
+  if (constraint_max_namelen > 0)
+    {
+      write_enum_constraint_num ();
+      puts ("extern enum constraint_num lookup_constraint (const char *);\n"
+	    "extern bool constraint_satisfied_p (rtx, enum constraint_num);\n");
+
+      if (constraint_max_namelen > 1)
+	puts ("extern size_t insn_constraint_len (enum constraint_num);\n"
+	      "#define CONSTRAINT_LEN(c_,s_) "
+	      "insn_constraint_len (lookup_constraint (s_))\n");
+      else
+	puts ("#define CONSTRAINT_LEN(c_,s_) 1\n");
+      if (have_register_constraints)
+	puts ("extern enum reg_class regclass_for_constraint "
+	      "(enum constraint_num);\n"
+	      "#define REG_CLASS_FROM_CONSTRAINT(c_,s_) \\\n"
+	      "    regclass_for_constraint (lookup_constraint (s_))\n");
+      else
+	puts ("#define REG_CLASS_FROM_CONSTRAINT(c_,s_) NO_REGS");
+      if (have_const_int_constraints)
+	puts ("extern bool insn_const_int_ok_for_constraint "
+	      "(HOST_WIDE_INT, enum constraint_num);\n"
+	      "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
+	      "    insn_const_int_ok_for_constraint (v_, "
+	      "lookup_constraint (s_))\n");
+      if (have_const_dbl_constraints)
+	puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
+	      "    constraint_satisfied_p (v_, lookup_constraint (s_))\n");
+      else
+	puts ("#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(v_,c_,s_) 0\n");
+      if (have_extra_constraints)
+	puts ("#define EXTRA_CONSTRAINT_STR(v_,c_,s_) \\\n"
+	      "    constraint_satisfied_p (v_, lookup_constraint (s_))\n");
+      if (have_memory_constraints)
+	puts ("extern bool "
+	      "insn_extra_memory_constraint (enum constraint_num);\n"
+	      "#define EXTRA_MEMORY_CONSTRAINT(c_,s_) "
+	      "insn_extra_memory_constraint (lookup_constraint (s_))\n");
+      else
+	puts ("#define EXTRA_MEMORY_CONSTRAINT(c_,s_) false\n");
+      if (have_address_constraints)
+	puts ("extern bool "
+	      "insn_extra_address_constraint (enum constraint_num)"
+	      "#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) "
+	      "insn_extra_address_constraint (lookup_constraint (s_))\n");
+      else
+	puts ("#define EXTRA_ADDRESS_CONSTRAINT(c_,s_) false\n");
+
+      if (have_const_int_constraints || have_const_dbl_constraints
+	  || have_extra_constraints)
+	write_satisfies_constraint_fns ();
+    }
+
+  puts ("#endif /* tm-preds.h */");
+}
 
 /* Write insn-preds.c.  
    N.B. the list of headers to include was copied from genrecog; it
@@ -486,6 +1220,24 @@ write_insn_preds_c (void)
 
   FOR_ALL_PREDICATES (p)
     write_one_predicate_function (p);
+
+  if (constraint_max_namelen > 0)
+    {
+      write_lookup_constraint ();
+      write_regclass_for_constraint ();
+      write_constraint_satisfied_p ();
+      
+      if (constraint_max_namelen > 1)
+	write_insn_constraint_len ();
+
+      if (have_const_int_constraints)
+	write_insn_const_int_ok_for_constraint ();
+
+      if (have_memory_constraints)
+	write_insn_extra_memory_constraint ();
+      if (have_address_constraints)
+	write_insn_extra_address_constraint ();
+    }
 }
 
 /* Argument parsing.  */
@@ -516,11 +1268,26 @@ main (int argc, char **argv)
     return FATAL_EXIT_CODE;
 
   while ((defn = read_md_rtx (&pattern_lineno, &next_insn_code)) != 0)
-    {
-      if (GET_CODE (defn) == DEFINE_PREDICATE
-	  || GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
-	process_define_predicate (defn);
-    }
+    switch (GET_CODE (defn))
+      {
+      case DEFINE_PREDICATE:
+      case DEFINE_SPECIAL_PREDICATE:
+	process_define_predicate (defn, pattern_lineno);
+	break;
+
+      case DEFINE_CONSTRAINT:
+      case DEFINE_MEMORY_CONSTRAINT:
+      case DEFINE_ADDRESS_CONSTRAINT:
+	process_define_constraint (defn, pattern_lineno);
+	break;
+
+      case DEFINE_REGISTER_CONSTRAINT:
+	process_define_register_constraint (defn, pattern_lineno);
+	break;
+
+      default:
+	break;
+      }
 
   if (gen_header)
     write_tm_preds_h ();
diff --git a/gcc/gensupport.c b/gcc/gensupport.c
index bbac33a2c886..a880b111c0fd 100644
--- a/gcc/gensupport.c
+++ b/gcc/gensupport.c
@@ -287,6 +287,10 @@ process_rtx (rtx desc, int lineno)
 
     case DEFINE_PREDICATE:
     case DEFINE_SPECIAL_PREDICATE:
+    case DEFINE_CONSTRAINT:
+    case DEFINE_REGISTER_CONSTRAINT:
+    case DEFINE_MEMORY_CONSTRAINT:
+    case DEFINE_ADDRESS_CONSTRAINT:
       queue_pattern (desc, &define_pred_tail, read_rtx_filename, lineno);
       break;
 
diff --git a/gcc/recog.c b/gcc/recog.c
index 9d937ed04480..e3cdfd799148 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -2664,6 +2664,10 @@ reg_fits_class_p (rtx operand, enum reg_class cl, int offset,
 		  enum machine_mode mode)
 {
   int regno = REGNO (operand);
+
+  if (cl == NO_REGS)
+    return 0;
+
   if (regno < FIRST_PSEUDO_REGISTER
       && TEST_HARD_REG_BIT (reg_class_contents[(int) cl],
 			    regno + offset))
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 8710f54890f4..84b24bc543bb 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -874,6 +874,61 @@ DEF_RTL_EXPR(DEFINE_COND_EXEC, "define_cond_exec", "Ess", RTX_EXTRA)
 DEF_RTL_EXPR(DEFINE_PREDICATE, "define_predicate", "ses", RTX_EXTRA)
 DEF_RTL_EXPR(DEFINE_SPECIAL_PREDICATE, "define_special_predicate", "ses", RTX_EXTRA)
 
+/* Definition of a register operand constraint.  This simply maps the
+   constraint string to a register class.
+
+   Operand:
+   0: The name of the constraint (often, but not always, a single letter).
+   1: A C expression which evaluates to the appropriate register class for
+      this constraint.  If this is not just a constant, it should look only
+      at -m switches and the like.
+   2: A docstring for this constraint, in Texinfo syntax; not currently
+      used, in future will be incorporated into the manual's list of
+      machine-specific operand constraints.  */
+DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, "define_register_constraint", "sss", RTX_EXTRA)
+
+/* Definition of a non-register operand constraint.  These look at the
+   operand and decide whether it fits the constraint.
+
+   DEFINE_CONSTRAINT gets no special treatment if it fails to match.
+   It is appropriate for constant-only constraints, and most others.
+
+   DEFINE_MEMORY_CONSTRAINT tells reload that this constraint can be made
+   to match, if it doesn't already, by converting the operand to the form
+   (mem (reg X)) where X is a base register.  It is suitable for constraints
+   that describe a subset of all memory references.
+
+   DEFINE_ADDRESS_CONSTRAINT tells reload that this constraint can be made
+   to match, if it doesn't already, by converting the operand to the form
+   (reg X) where X is a base register.  It is suitable for constraints that
+   describe a subset of all address references.
+
+   When in doubt, use plain DEFINE_CONSTRAINT.  
+
+   Operand:
+   0: The name of the constraint (often, but not always, a single letter).
+   1: A docstring for this constraint, in Texinfo syntax; not currently
+      used, in future will be incorporated into the manual's list of
+      machine-specific operand constraints.
+   2: A boolean expression which computes whether or not the constraint
+      matches.  It should follow the same rules as a define_predicate
+      expression, including the bit about specifying the set of RTX codes
+      that could possibly match.  MATCH_TEST subexpressions may make use of
+      these variables:
+        `op'    - the RTL object defining the operand.
+        `mode'  - the mode of `op'.
+	`ival'  - INTVAL(op), if op is a CONST_INT.
+        `hval'  - CONST_DOUBLE_HIGH(op), if op is an integer CONST_DOUBLE.
+        `lval'  - CONST_DOUBLE_LOW(op), if op is an integer CONST_DOUBLE.
+        `rval'  - CONST_DOUBLE_REAL_VALUE(op), if op is a floating-point
+                  CONST_DOUBLE.
+      Do not use ival/hval/lval/rval if op is not the appropriate kind of
+      RTL object.  */
+DEF_RTL_EXPR(DEFINE_CONSTRAINT, "define_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_MEMORY_CONSTRAINT, "define_memory_constraint", "sse", RTX_EXTRA)
+DEF_RTL_EXPR(DEFINE_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA)
+   
+
 /* Constructions for CPU pipeline description described by NDFAs.  */
 
 /* (define_cpu_unit string [string]) describes cpu functional
-- 
GitLab