This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

define_constraints patch, revised


Over the weekend I finally had time to revise my patch to enable defining
constraints in the machine description.  Changes from the previous version:

 * As discussed, there are enumeration constants corresponding to all
   machine-specific constraints, and a documented interface for testing
   constraints from C in an ad-hoc manner (constraint_satisfied_p).  The
   function mapping constraints to regclasses is documented too, though
   as yet I haven't found any machine-specific code that uses it.  This
   also enabled considerable simplification to the generated code, since
   only one function needs to process constraint strings.
 * Also as discussed, it is now possible to use underscores and angle
   brackets in machine-specific constraint names.  Since angle brackets
   are not valid characters in C identifiers, the corresponding enumeration
   constants have mangled names; in order to give the mangling scheme a
   namespace to itself, you can't use an underscore as the first character
   in a constraint name (unlike C identifiers).  I am open to better ideas
   on that score.  I strongly prefer not to allow any more punctuation in
   constraint names, but given the existing uses of angle brackets, I
   decided it was best to let them in.
 * It is no longer necessary to put #define USE_MD_CONSTRAINTS in the tm.h
   of a converted port.  And there was much rejoicing.
 * The old constraint macros that machine-independent code doesn't use are
   now poisoned (by defaults.h, not system.h) if you use the new scheme.
   This aids in flushing out stray uses of CONST_OK_FOR_LETTER_P etc from
   machine-specific code.  It's not possible to poison the rest of them
   until all ports are converted and the machine-independent uses can go.
 * We still do nothing useful with docstrings (again, we can't until all
   ports are converted); however, the documentation now promises a
   mechanism for tagging constraints as internals-manual-only.
 * Some bugs are fixed.  (And I now know *why* Jan changed the SSE constant
   constraint from 'H' to 'C'. :-)

The generated functions are all still out of line, as this made it easier
to debug (only insn-preds.c had to be recompiled after a change) but I am
willing to consider moving at least some of them to tm-preds.h and making
them inline.  Numbers indicating performance degradation, or test cases
that I can run and see performance degradation for myself, would aid an
argument in that direction.

As demonstration and test, I converted the i386 and h8300 back ends.
(h8300 used angle brackets in its machine-specific constraint names, so by
converting it I could test the mangling code.)  The h8300 conversion is
incomplete insofar as many of the constraint definitions lack docstrings,
but then there was no "Machine Constraints" doc subsection for the h8300,
so this is a preexisting condition.  I encourage the port maintainers to
pick up this ball -- the port is too strange for me to make them up.
Speaking of docstrings, I'd appreciate an i386 maintainer having a gander
at which constraints to mark @internal; I went strictly by which ones
appeared in the existing manual, but it seems to me that some of those are
wrong (notably, why 'l' and 'Y', and why not 'L'?)

Bootstrapped i686-linux, default languages, with no test suite regressions.
An h8300-hms cross compiler has been built.  I intend to do an h8300-hms
simulator run this evening (C and C++ only) but wanted to get this out
there for comments already.

I hope this will be acceptable as is or nearly so; I would really like to
see the ball get rolling on port conversions.  I *might* have time this
weekend to do a "technology preview" of the changes enabled once all ports
are conversions, but I'm not promising anything.

zw

p.s. apologies for the length of the search-and-replace changes above the
interesting additions to md.texi - scroll down to "Define Constraints".

:ADDPATCH machine description:

	* 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.
	(struct constraint_data, valid_constraint_letters)
	(constraints_by_letter_table, constraint_letter_slot, first_constraint)
	(last_constraint_ptr, FOR_ALL_CONSTRAINTS, 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): 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 constraint_satisfied_p.
	* config/i386/i386.c (memory_address_length)
	(ix86_attr_length_immediate_default): Use constraint_satisfied_p.

	* config/h8300/predicates.md (a, c, D, f, d, I, J, L, M, N, O)
	(P1>X, P3>X, P4>X, P5>X, P8>X, P3<X, G, R, S, T, Q, U, WU, Z):
	New constraint definitions.
	(bit_operand, bit_memory_operand, incdec_operand):
	Use constraint_satisfied_p.
	* config/h8300/h8300.h (CONST_OK_FOR_I, CONST_OK_FOR_J, CONST_OK_FOR_L)
	(CONST_OK_FOR_M, CONST_OK_FOR_N, CONST_OK_FOR_O, CONST_OK_FOR_P)
	(CONST_OK_FOR_Pnegative, CONST_OK_FOR_Ppositive, CONSTRAINT_LEN_FOR_P)
	(CONST_OK_FOR_CONSTRAINT_P, CONST_OK_FOR_LETTER_P)
	(CONST_DOUBLE_OK_FOR_LETTER_P, OK_FOR_Q, OK_FOR_R, OK_FOR_S, OK_FOR_T)
	(OK_FOR_U, OK_FOR_WU, OK_FOR_W, CONSTRAINT_LEN_FOR_W, OK_FOR_Y)
	(CONSTRAINT_LEN_FOR_Y, OK_FOR_Z, EXTRA_CONSTRAINT_STR, CONSTRAINT_LEN)
	(EXTRA_MEMORY_CONSTRAINT, REG_CLASS_FROM_LETTER): Delete.
	Merge adjacent #ifndef REG_OK_STRICT blocks.
	* config/h8300/h8300.md (*tst_extzv_1_n, *tstsi_variable_bit_qi)
	(peepholes): Use constraint_satisfied_p.
	* config/h8300/h8300.c (h8300_reg_class_from_letter): Delete.
	(compute_mov_length, fix_bit_operand): Use constraint_satisfied_p.

==================================================================
--- gcc/doc/md.texi	(revision 110949)
+++ gcc/doc/md.texi	(local)
@@ -1051,6 +1051,8 @@ have.  Constraints can also require two 
 * 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-
 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,37 +1617,18 @@ general-purpose registers respectively; 
 @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{arm.h}
+@item ARM family---@file{config/arm/arm.h}
 @table @code
 @item f
 Floating-point register
@@ -1707,7 +1681,7 @@ A memory reference suitable for iWMMXt l
 A memory reference suitable for the ARMv4 ldrsb instruction.
 @end table
 
-@item AVR family---@file{avr.h}
+@item AVR family---@file{config/avr/avr.h}
 @table @code
 @item l
 Registers from r0 to r15
@@ -1770,7 +1744,7 @@ Constant integer 1
 A floating point constant 0.0
 @end table
 
-@item CRX Architecture---@file{crx.h}
+@item CRX Architecture---@file{config/crx/crx.h}
 @table @code
 
 @item b
@@ -1801,7 +1775,7 @@ Constant that is one of -1, 4, -4, 7, 8,
 Floating point constant that is legal for store immediate
 @end table
 
-@item PowerPC and IBM RS6000---@file{rs6000.h}
+@item PowerPC and IBM RS6000---@file{config/rs6000/rs6000.h}
 @table @code
 @item b
 Address base register
@@ -1879,7 +1853,7 @@ Constant suitable as a 32-bit mask opera
 System V Release 4 small data area reference
 @end table
 
-@item MorphoTech family---@file{mt.h}
+@item MorphoTech family---@file{config/mt/mt.h}
 @table @code
 @item I
 Constant for an arithmetic insn (16-bit signed integer).
@@ -1908,96 +1882,112 @@ A 15-bit signed integer constant.
 A positive 16-bit constant.
 @end table
 
-@item Intel 386---@file{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)
+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 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.
-
-@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{ia64.h}
+@item Intel IA-64---@file{config/ia64/ia64.h}
 @table @code
 @item a
 General register @code{r0} to @code{r3} for @code{addl} instruction
@@ -2060,7 +2050,7 @@ Integer constant in the range 1 to 4 for
 Memory operand except postincrement and postdecrement
 @end table
 
-@item FRV---@file{frv.h}
+@item FRV---@file{config/frv/frv.h}
 @table @code
 @item a
 Register in the class @code{ACC_REGS} (@code{acc0} to @code{acc7}).
@@ -2153,7 +2143,7 @@ range of 1 to 2047.
 
 @end table
 
-@item Blackfin family---@file{bfin.h}
+@item Blackfin family---@file{config/bfin/bfin.h}
 @table @code
 @item a
 P register
@@ -2250,7 +2240,7 @@ Any SYMBOL_REF.
 @end table
 
 @item M32C---@file{m32c.c}
-
+@table @code
 @item Rsp
 @itemx Rfb
 @itemx Rsb
@@ -2376,9 +2366,9 @@ Memory addressed using the small base re
 
 @item S1
 $r1h
+@end table
 
-
-@item MIPS---@file{mips.h}
+@item MIPS---@file{config/mips/mips.h}
 @table @code
 @item d
 General-purpose integer register
@@ -2442,7 +2432,7 @@ Memory reference in external OSF/rose PI
 (@samp{m} is preferable for @code{asm} statements)
 @end table
 
-@item Motorola 680x0---@file{m68k.h}
+@item Motorola 680x0---@file{config/m68k/m68k.h}
 @table @code
 @item a
 Address register
@@ -2472,7 +2462,7 @@ Signed number whose magnitude is greater
 Floating point constant that is not a 68881 constant
 @end table
 
-@item Motorola 68HC11 & 68HC12 families---@file{m68hc11.h}
+@item Motorola 68HC11 & 68HC12 families---@file{config/m68hc11/m68hc11.h}
 @table @code
 @item a
 Register `a'
@@ -2531,7 +2521,7 @@ Constants in the range @minus{}8 to 2
 @end table
 
 @need 1000
-@item SPARC---@file{sparc.h}
+@item SPARC---@file{config/sparc/sparc.h}
 @table @code
 @item f
 Floating-point register on the SPARC-V8 architecture and
@@ -2615,7 +2605,7 @@ Vector zero
 
 @end table
 
-@item TMS320C3x/C4x---@file{c4x.h}
+@item TMS320C3x/C4x---@file{config/c4x/c4x.h}
 @table @code
 @item a
 Auxiliary (address) register (ar0-ar7)
@@ -2697,7 +2687,7 @@ Symbolic address
 
 @end table
 
-@item S/390 and zSeries---@file{s390.h}
+@item S/390 and zSeries---@file{config/s390/s390.h}
 @table @code
 @item a
 Address register (general purpose register except r0)
@@ -2770,7 +2760,7 @@ Shift count operand.
 
 @end table
 
-@item Xstormy16---@file{stormy16.h}
+@item Xstormy16---@file{config/stormy16/stormy16.h}
 @table @code
 @item a
 Register r0.
@@ -2840,7 +2830,7 @@ The constant 0.
 
 @end table
 
-@item Xtensa---@file{xtensa.h}
+@item Xtensa---@file{config/xtensa/xtensa.h}
 @table @code
 @item a
 General-purpose 32-bit register
@@ -2868,6 +2858,236 @@ Unsigned constant valid for BccUI instru
 @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{< >}).  In addition, their names
+must begin with one of the following letters:@: @samp{A B C D G H I J
+K L M N O P Q R S T U W Y Z a b c d e f h j k l q t u v w x y z}.
+These are the letters not used for generic constraints.  Leading
+underscores are not allowed, to avoid conflicts with the mangling
+scheme for names containing angle brackets.   @xref{C Constraint
+Interface}, for further explanation.
+
+If an operand constraint string could be broken into individual
+constraints more than one way, the longest match wins: for example, if
+@code{x}, @code{y}, and @code{xy} are all defined as constraint names,
+the text @samp{xy} in an operand constraint will be read as the single
+constraint @code{xy}, not the two constraints @code{x} and @code{y}.
+
+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 predicate, 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.
+
+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.  (The compiler itself is unaware of the distinction; this
+is not a way to give users a helpful diagnostic instead of a
+@code{reload} failure.)
+
+@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.
+
+@deftp Enum constraint_num
+For each machine-specific constraint, there is a corresponding
+enumeration constant.  If the constraint's name does not contain any
+angle brackets, the enumeration constant is simply @samp{CONSTRAINT_}
+plus the name: to the name of the constraint: @code{CONSTRAINT_I} for
+@code{I}, @code{CONSTRAINT_x} for @code{x}, etc.  If the name does
+contain angle brackets, each @samp{<} is replaced with @samp{lt}, each
+@samp{>} with @samp{gt}, and a leading underscore is added:
+@code{CONSTRAINT__P4gtX} for @code{P4>X}, for instance.
+
+Machine-independent constraints do not have associated constants.
+This may change in the future.
+@end deftp
+
+@deftypefun bool constraint_satisfied_p (rtx @var{exp}, enum constraint_num @var{c})
+Returns @code{true} if @var{exp} satisfies the constraint @var{c}.  If
+@var{c} was defined as a register constraint, @code{constraint_satisfied_p} 
+will return @code{true} if and only if @var{exp} is a hard register
+and @code{reg_fits_class_p} would be true for that register and the
+regclass associated with @var{c}, with no offset and @var{exp}'s mode.
+@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{constraint_satisfied_p}.  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" "")))]
+
+  "!constraint_satisfied_p (operands[2], CONSTRAINT_K)"
+
+  [(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
==================================================================
--- gcc/doc/tm.texi	(revision 110949)
+++ gcc/doc/tm.texi	(local)
@@ -33,6 +33,7 @@ through the macros defined in the @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.
@@ -2292,36 +2293,6 @@ address where its value is either multip
 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
@@ -2674,8 +2645,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
==================================================================
--- gcc/rtl.def	(revision 110949)
+++ gcc/rtl.def	(local)
@@ -874,6 +874,61 @@ DEF_RTL_EXPR(DEFINE_COND_EXEC, "define_c
 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; 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; 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
==================================================================
--- gcc/defaults.h	(revision 110949)
+++ gcc/defaults.h	(local)
@@ -752,6 +752,33 @@ Software Foundation, 51 Franklin Street,
 #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,
 #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
==================================================================
--- gcc/gensupport.c	(revision 110949)
+++ gcc/gensupport.c	(local)
@@ -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;
 
==================================================================
--- gcc/genpreds.c	(revision 110949)
+++ gcc/genpreds.c	(local)
@@ -27,12 +27,11 @@ 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.  */
+/* Predicates are defined with (define_predicate) or
+   (define_special_predicate) expressions in the machine description.  */
 static void
 process_define_predicate (rtx defn)
 {
@@ -54,32 +53,6 @@ process_define_predicate (rtx defn)
   add_predicate (pred);
 }
 
-/* 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\
-#endif /* tm-preds.h */");
-}
-
 /* Given a predicate, if it has an embedded C block, write the block
    out as a static inline subroutine, and augment the RTL test with a
    match_test that calls that subroutine.  For instance,
@@ -446,6 +419,558 @@ write_one_predicate_function (struct pre
   write_predicate_expr (p->name, 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 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.  */
+
+/* This is a list of all the letters which may begin names of
+   constraints defined by the machine description.  Machine-specific
+   constraints aren't allowed to have names that begin with letters
+   used by generic constraints.  The letters not in the list are:
+   EFVXgimnops.  */
+static const char valid_constraint_letters[] =
+"ABCDGHIJKLMNOPQRSTUWYZabcdefhjklqtuvwxyz";
+
+static struct constraint_data *
+constraints_by_letter_table[ARRAY_SIZE(valid_constraint_letters) - 1];
+
+/* Return the slot in constraints_by_letter_table corresponding to
+   character C, which must be in valid_constraint_letters.  */
+static inline struct constraint_data **
+constraint_letter_slot (char c)
+{
+  const char *here = strchr (valid_constraint_letters, c);
+  if (!here)
+    return 0;
+
+  return &constraints_by_letter_table[here - valid_constraint_letters];
+}
+
+/* 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)
+
+/* 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, to a string that can
+   be used as part of a C identifier.  A leading underscore is added,
+   '<' is replaced with 'lt', and '>' with 'gt'.  The string comes
+   from the rtl_obstack.  */
+static const char *
+mangle (const char *name)
+{
+  obstack_1grow (rtl_obstack, '_');
+  while (*name)
+    {
+      if (*name == '<')
+	obstack_grow (rtl_obstack, "lt", 2);
+      else if (*name == '>')
+	obstack_grow (rtl_obstack, "gt", 2);
+      else
+	obstack_1grow (rtl_obstack, *name);
+      name++;
+    }
+  obstack_1grow (rtl_obstack, '\0');
+  return obstack_finish (rtl_obstack);
+}
+
+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;
+
+  if (!ISALPHA (name[0]))
+    {
+      if (name[1] == '\0')
+	message_with_line (lineno, "constraint name '%s' is not a letter",
+			   name);
+      else
+	message_with_line (lineno, "constraint name '%s' does not begin "
+			   "with a letter", name);
+      have_error = 1;
+      return;
+    }
+  for (p = name + 1; *p; p++)
+    if (!ISALNUM (*p) && *p != '_')
+      {
+	if (*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;
+	  }
+      }
+
+  slot = constraint_letter_slot (name[0]);
+  if (!slot)
+    {
+      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;
+    }
+
+  FOR_ALL_CONSTRAINTS (iter)
+    if (!strcmp (iter->name, name))
+      {
+	error ("duplicate constraint definition for '%s'", name);
+	return;
+      }
+
+  c = obstack_alloc (rtl_obstack, sizeof (struct constraint_data));
+  c->name         = name;
+  c->c_name	  = need_mangled_name ? mangle (name) : name;
+  c->namelen      = strlen (name);
+  c->regclass     = regclass;
+  c->exp          = exp;
+  c->is_register  = c->regclass != 0;
+  c->is_const_int = strchr (const_int_constraints, name[0]) != 0;
+  c->is_const_dbl = strchr (const_dbl_constraints, name[0]) != 0;
+  c->is_extra     = !(c->is_register || c->is_const_int || c->is_const_dbl);
+  c->is_memory    = is_memory;
+  c->is_address   = is_address;
+
+  if (c->is_const_int || c->is_const_dbl)
+    {
+      enum rtx_code appropriate_code
+	= c->is_const_int ? CONST_INT : CONST_DOUBLE;
+
+      /* Consider relaxing this requirement in the future.  */
+      if (c->is_register
+	  || GET_CODE (c->exp) != AND
+	  || GET_CODE (XEXP (c->exp, 0)) != MATCH_CODE
+	  || strcmp (XSTR (XEXP (c->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));
+	  obstack_free (rtl_obstack, c);
+	  have_error = 1;
+	  return;
+	}
+
+      /* Remove the redundant (and (match_code "const_(int|double)")
+	 from the expression.  */
+      c->exp = XEXP (c->exp, 1);
+
+      if (c->is_memory)
+	message_with_line (lineno, "warning: '%s' will not be treated as a "
+			   "memory constraint, due to its name", name);
+      else if (c->is_address)
+	message_with_line (lineno, "warning: '%s' will not be treated as an "
+			   "address constraint, due to its name", name);
+      c->is_memory = false;
+      c->is_address = false;
+    }
+
+  /* Insert this constraint in the appropriate per-letter list,
+     keeping the list in decreasing order of length, so that emitting
+     a straightforward if-chain will give us longest-match-wins.  */
+  while (*slot && (*slot)->namelen > c->namelen)
+    slot = &(*slot)->next_this_letter;
+
+  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;
+}
+
+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);
+}
+
+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(valid_constraint_letters) - 1; i++)
+    {
+      char letter = valid_constraint_letters[i];
+      struct constraint_data *c = constraints_by_letter_table[i];
+      if (!c)
+	continue;
+
+      printf ("    case '%c':\n", letter);
+      do
+	{
+	  if (c->namelen > 1)
+	    printf ("      if (!strncmp (str, \"%s\", %lu))\n  ",
+		    c->name,
+		    (unsigned long int) c->namelen);
+	  printf ("      return CONSTRAINT_%s;\n", 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 function which computes whether a given value matches
+   a given "extra" constraint.  */
+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"
+	"  enum machine_mode mode = GET_MODE (op);\n"
+	"  HOST_WIDE_INT ival = 0;\n"
+	"  HOST_WIDE_INT hval = 0;\n"
+	"  unsigned HOST_WIDE_INT lval = 0;\n"
+	"  const REAL_VALUE_TYPE *rval = 0;\n"
+	"\n"
+	"  if (GET_CODE (op) == CONST_INT)\n"
+	"    ival = INTVAL (op);\n"
+	"  else if (GET_CODE (op) == CONST_DOUBLE)\n"
+	"    {\n"
+	"      if (mode == VOIDmode)\n"
+	"        hval = CONST_DOUBLE_HIGH (op),\n"
+	"        lval = CONST_DOUBLE_LOW  (op);\n"
+	"      else\n"
+	"        rval = CONST_DOUBLE_REAL_VALUE (op);\n"
+	"    }\n"
+	"\n"
+	"  switch (c)\n"
+	"    {");
+
+  FOR_ALL_CONSTRAINTS (c)
+    {
+      printf ("    case CONSTRAINT_%s:\n      return ", c->c_name);
+      if (c->is_register)	
+	printf ("reg_fits_class_p (op, %s, 0, mode)", c->regclass);
+      else
+	write_predicate_expr (c->name, c->exp);
+      fputs (";\n\n", stdout);
+    }
+
+  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->name, 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");
+    }
+
+  puts ("#endif /* tm-preds.h */");
+}
 
 /* Write insn-preds.c.  
    N.B. the list of headers to include was copied from genrecog; it
@@ -486,6 +1011,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 +1059,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)
+    switch (GET_CODE (defn))
+      {
+      case DEFINE_PREDICATE:
+      case DEFINE_SPECIAL_PREDICATE:
 	process_define_predicate (defn);
-    }
+	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 ();
==================================================================
--- gcc/genoutput.c	(revision 110949)
+++ gcc/genoutput.c	(local)
@@ -54,12 +54,10 @@ Software Foundation, 51 Franklin Street,
      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,39 @@ 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;
+  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[] = ",=+%*?!#&<>pmVoEFsinXgr";
+
+/* This is a list of all the letters which may legitimately begin
+   the names of constraints defined by the machine description.  */
+static const char mdep_constraint_letters[] =
+"ABCDGHIJKLMNOPQRSTUWYZabcdefhjklqtuvwxyz";
+
+static struct constraint_data *
+constraints_by_letter_table[ARRAY_SIZE(mdep_constraint_letters) - 1];
+
+static int mdep_constraint_len (const char *, int, int);
+static void note_constraint (rtx);
+
+#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 +754,20 @@ validate_insn_alternatives (struct data 
 
 	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 +778,7 @@ validate_insn_alternatives (struct data 
 		len = 1;
 		have_error = 1;
 	      }
+#endif
 
 	    if (c == ',')
 	      {
@@ -826,7 +870,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 +1029,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);
+	  break;
+#endif
+
+	default:
+	  break;
+	}
       next_index_number++;
     }
 
@@ -1043,6 +1111,73 @@ strip_whitespace (const char *s)
   return q;
 }
 
+#ifdef USE_MD_CONSTRAINTS
+
+static inline int
+constraint_table_index (const char *name)
+{
+  const char *here = strchr (mdep_constraint_letters, name[0]);
+  if (!here)
+    return -1;
+  return here - mdep_constraint_letters;
+}
+
+
+static void
+note_constraint (rtx exp)
+{
+  const char *name = XSTR (exp, 0);
+  unsigned int namelen = strlen (name);
+  int i = constraint_table_index (name);
+  struct constraint_data **p, *new;
+
+  if (i == -1)
+    {
+      error ("invalid machine-specific constraint name '%s'", name);
+      return;
+    }
+
+  for (p = &constraints_by_letter_table[i]; *p; p = &(*p)->next_this_letter)
+    {
+      if ((*p)->namelen < namelen)
+	break;
+      if ((*p)->namelen == namelen
+	  && !strcmp (name, (*p)->name))
+	{
+	  error ("constraint '%s' defined more than once", name);
+	  return;
+	}
+    }
+  new = xmalloc (sizeof (struct constraint_data) + namelen);
+  strcpy ((char *)new + offsetof(struct constraint_data, name), name);
+  new->namelen = namelen;
+  new->next_this_letter = *p;
+  *p = new;
+}
+
+static int
+mdep_constraint_len (const char *s, int lineno, int opno)
+{
+  struct constraint_data *p;
+  int i;
+
+  i = constraint_table_index (s);
+  if (i >= 0)
+    {
+      for (p = constraints_by_letter_table[i]; 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 +1211,4 @@ constraint_len (const char *p, int genou
 #undef DEFAULT_CONSTRAINT_LEN
 #define DEFAULT_CONSTRAINT_LEN(C,STR) 1
 }
+#endif
==================================================================
--- gcc/recog.c	(revision 110949)
+++ gcc/recog.c	(local)
@@ -2664,6 +2664,10 @@ reg_fits_class_p (rtx operand, enum reg_
 		  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))
==================================================================
--- gcc/config/h8300/h8300.c	(revision 110949)
+++ gcc/config/h8300/h8300.c	(local)
@@ -404,71 +404,6 @@ h8300_init_once (void)
     }
 }
 
-/* Implement REG_CLASS_FROM_LETTER.
-
-   Some patterns need to use er6 as a scratch register.  This is
-   difficult to arrange since er6 is the frame pointer and usually
-   can't be spilled.
-
-   Such patterns should define two alternatives, one which allows only
-   er6 and one which allows any general register.  The former alternative
-   should have a 'd' constraint while the latter should be disparaged and
-   use 'D'.
-
-   Normally, 'd' maps to DESTINATION_REGS and 'D' maps to GENERAL_REGS.
-   However, there are cases where they should be NO_REGS:
-
-     - 'd' should be NO_REGS when reloading a function that uses the
-       frame pointer.  In this case, DESTINATION_REGS won't contain any
-       spillable registers, so the first alternative can't be used.
-
-     - -fno-omit-frame-pointer means that the frame pointer will
-       always be in use.  It's therefore better to map 'd' to NO_REGS
-       before reload so that register allocator will pick the second
-       alternative.
-
-     - we would like 'D' to be be NO_REGS when the frame pointer isn't
-       live, but we the frame pointer may turn out to be needed after
-       we start reload, and then we may have already decided we don't
-       have a choice, so we can't do that.  Forcing the register
-       allocator to use er6 if possible might produce better code for
-       small functions: it's more efficient to save and restore er6 in
-       the prologue & epilogue than to do it in a define_split.
-       Hopefully disparaging 'D' will have a similar effect, without
-       forcing a reload failure if the frame pointer is found to be
-       needed too late.  */
-
-enum reg_class
-h8300_reg_class_from_letter (int c)
-{
-  switch (c)
-    {
-    case 'a':
-      return MAC_REGS;
-
-    case 'c':
-      return COUNTER_REGS;
-
-    case 'd':
-      if (!flag_omit_frame_pointer && !reload_completed)
-	return NO_REGS;
-      if (frame_pointer_needed && reload_in_progress)
-	return NO_REGS;
-      return DESTINATION_REGS;
-
-    case 'D':
-      /* The meaning of a constraint shouldn't change dynamically, so
-	 we can't make this NO_REGS.  */
-      return GENERAL_REGS;
-
-    case 'f':
-      return SOURCE_REGS;
-
-    default:
-      return NO_REGS;
-    }
-}
-
 /* Return the byte register name for a register rtx X.  B should be 0
    if you want a lower byte register.  B should be 1 if you want an
    upper byte register.  */
@@ -2703,7 +2638,7 @@ compute_mov_length (rtx *operands)
 	      if (REG_P (src))
 		return 4;
 
-	      if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
+	      if (constraint_satisfied_p (src, CONSTRAINT_G))
 		return 4;
 
 	      return 8;
@@ -2823,7 +2758,7 @@ compute_mov_length (rtx *operands)
 	      if (REG_P (src))
 		return 2;
 
-	      if (CONST_DOUBLE_OK_FOR_LETTER_P (src, 'G'))
+	      if (constraint_satisfied_p (src, CONSTRAINT_G))
 		return 2;
 
 	      return 6;
@@ -5036,7 +4971,7 @@ fix_bit_operand (rtx *operands, enum rtx
     {
       /* OK to have a memory dest.  */
       if (GET_CODE (operands[0]) == MEM
-	  && !OK_FOR_U (operands[0]))
+	  && !constraint_satisfied_p (operands[0], CONSTRAINT_U))
 	{
 	  rtx mem = gen_rtx_MEM (GET_MODE (operands[0]),
 				 copy_to_mode_reg (Pmode,
@@ -5046,7 +4981,7 @@ fix_bit_operand (rtx *operands, enum rtx
 	}
 
       if (GET_CODE (operands[1]) == MEM
-	  && !OK_FOR_U (operands[1]))
+	  && !constraint_satisfied_p (operands[1], CONSTRAINT_U))
 	{
 	  rtx mem = gen_rtx_MEM (GET_MODE (operands[1]),
 				 copy_to_mode_reg (Pmode,
==================================================================
--- gcc/config/h8300/h8300.h	(revision 110949)
+++ gcc/config/h8300/h8300.h	(local)
@@ -386,76 +386,6 @@ enum reg_class {
 #define INDEX_REG_CLASS (TARGET_H8300SX ? GENERAL_REGS : NO_REGS)
 #define BASE_REG_CLASS  GENERAL_REGS
 
-/* Get reg_class from a letter such as appears in the machine description.
-
-   'a' is the MAC register.  */
-
-#define REG_CLASS_FROM_LETTER(C) (h8300_reg_class_from_letter (C))
-
-/* The letters I, J, K, L, M, N, O, P 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.  */
-
-#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
-#define CONST_OK_FOR_J(VALUE) (((VALUE) & 0xff) == 0)
-#define CONST_OK_FOR_L(VALUE)				\
-  (TARGET_H8300H || TARGET_H8300S			\
-   ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4	\
-   : (VALUE) == 1 || (VALUE) == 2)
-#define CONST_OK_FOR_M(VALUE)				\
-  ((VALUE) == 1 || (VALUE) == 2)
-#define CONST_OK_FOR_N(VALUE)				\
-  (TARGET_H8300H || TARGET_H8300S			\
-   ? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4	\
-   : (VALUE) == -1 || (VALUE) == -2)
-#define CONST_OK_FOR_O(VALUE)				\
-  ((VALUE) == -1 || (VALUE) == -2)
-
-/* Multi-letter constraints for constant are always started with P
-   (just because it was the only letter in the range left.  New
-   constraints for constants should be added here.  */
-#define CONST_OK_FOR_Ppositive(VALUE, NBITS)		\
-  ((VALUE) > 0 && (VALUE) < (1 << (NBITS)))
-#define CONST_OK_FOR_Pnegative(VALUE, NBITS)		\
-  ((VALUE) < 0 && (VALUE) > -(1 << (NBITS)))
-#define CONST_OK_FOR_P(VALUE, STR) \
-  ((STR)[1] >= '1' && (STR)[1] <= '9' && (STR)[2] == '<' 	\
-   ? (((STR)[3] == '0' || ((STR)[3] == 'X' && TARGET_H8300SX))	\
-      && CONST_OK_FOR_Pnegative ((VALUE), (STR)[1] - '0'))	\
-   : ((STR)[1] >= '1' && (STR)[1] <= '9' && (STR)[2] == '>')	\
-   ? (((STR)[3] == '0' || ((STR)[3] == 'X' && TARGET_H8300SX))	\
-      && CONST_OK_FOR_Ppositive ((VALUE), (STR)[1] - '0'))	\
-   : 0)
-#define CONSTRAINT_LEN_FOR_P(STR) \
-  ((((STR)[1] >= '1' && (STR)[1] <= '9')			\
-    && ((STR)[2] == '<' || (STR)[2] == '>')			\
-    && ((STR)[3] == 'X' || (STR)[3] == '0')) ? 4		\
-   : 0)
-
-#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR)	\
-  ((C) == 'P' ? CONST_OK_FOR_P ((VALUE), (STR))		\
-   : CONST_OK_FOR_LETTER_P ((VALUE), (C)))
-  
-#define CONST_OK_FOR_LETTER_P(VALUE, C)		\
-  ((C) == 'I' ? CONST_OK_FOR_I (VALUE) :	\
-   (C) == 'J' ? CONST_OK_FOR_J (VALUE) :	\
-   (C) == 'L' ? CONST_OK_FOR_L (VALUE) :	\
-   (C) == 'M' ? CONST_OK_FOR_M (VALUE) :	\
-   (C) == 'N' ? CONST_OK_FOR_N (VALUE) :	\
-   (C) == 'O' ? CONST_OK_FOR_O (VALUE) :	\
-   0)
-
-/* Similar, but for floating constants, and defining letters G and H.
-   Here VALUE is the CONST_DOUBLE rtx itself.
-
-  `G' is a floating-point zero.  */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)	\
-  ((C) == 'G' ? (VALUE) == CONST0_RTX (SFmode)	\
-   : 0)
-
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
@@ -796,125 +726,6 @@ struct cum_arg
 
 #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
 #define REG_OK_FOR_BASE_P(X)  REG_OK_FOR_BASE_NONSTRICT_P (X)
-
-#else
-
-#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X)
-#define REG_OK_FOR_BASE_P(X)  REG_OK_FOR_BASE_STRICT_P (X)
-
-#endif
-
-/* Extra constraints.  */
-
-#define OK_FOR_Q(OP)					\
-  (TARGET_H8300SX && memory_operand ((OP), VOIDmode))
-
-#define OK_FOR_R(OP)					\
-  (GET_CODE (OP) == CONST_INT				\
-   ? !h8300_shift_needs_scratch_p (INTVAL (OP), QImode)	\
-   : 0)
-
-#define OK_FOR_S(OP)					\
-  (GET_CODE (OP) == CONST_INT				\
-   ? !h8300_shift_needs_scratch_p (INTVAL (OP), HImode)	\
-   : 0)
-
-#define OK_FOR_T(OP)					\
-  (GET_CODE (OP) == CONST_INT				\
-   ? !h8300_shift_needs_scratch_p (INTVAL (OP), SImode)	\
-   : 0)
-
-/* 'U' if valid for a bset destination;
-   i.e. a register, register indirect, or the eightbit memory region
-   (a SYMBOL_REF with an SYMBOL_REF_FLAG set).
-
-   On the H8S 'U' can also be a 16bit or 32bit absolute.  */
-#define OK_FOR_U(OP)							\
-  ((GET_CODE (OP) == REG && REG_OK_FOR_BASE_P (OP))			\
-   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG		\
-       && REG_OK_FOR_BASE_P (XEXP (OP, 0)))				\
-   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF	\
-       && TARGET_H8300S)						\
-   || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST		\
-       && GET_CODE (XEXP (XEXP (OP, 0), 0)) == PLUS			\
-       && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 0)) == SYMBOL_REF	\
-       && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 1)) == CONST_INT	\
-       && (TARGET_H8300S						\
-	   || SYMBOL_REF_FLAG (XEXP (XEXP (XEXP (OP, 0), 0), 0))))	\
-   || (GET_CODE (OP) == MEM						\
-       && h8300_eightbit_constant_address_p (XEXP (OP, 0)))		\
-   || (GET_CODE (OP) == MEM && TARGET_H8300S				\
-       && GET_CODE (XEXP (OP, 0)) == CONST_INT))
-
-/* Multi-letter constraints starting with W are to be used for
-   operands that require a memory operand, i.e,. that are never used
-   along with register constraints (see EXTRA_MEMORY_CONSTRAINTS).
-   For operands that require a memory operand (or not) but that always
-   accept a register, a multi-letter constraint starting with Y should
-   be used instead.  */
-
-#define OK_FOR_WU(OP)					\
-  (GET_CODE (OP) == MEM && OK_FOR_U (OP))
-
-#define OK_FOR_W(OP, STR)				\
-  ((STR)[1] == 'U' ? OK_FOR_WU (OP)			\
-   : 0)
-
-#define CONSTRAINT_LEN_FOR_W(STR)			\
-  ((STR)[1] == 'U' ? 2					\
-   : 0)
-
-/* We don't have any constraint starting with Y yet, but before
-   someone uses it for a one-letter constraint and we're left without
-   any upper-case constraints left, we reserve it for extensions
-   here.  */
-#define OK_FOR_Y(OP, STR)				\
-  (0)
-
-#define CONSTRAINT_LEN_FOR_Y(STR)			\
-  (0)
-
-#define OK_FOR_Z(OP)					\
-  (TARGET_H8300SX					\
-   && GET_CODE (OP) == MEM				\
-   && CONSTANT_P (XEXP ((OP), 0)))
-
-#define EXTRA_CONSTRAINT_STR(OP, C, STR)	\
-  ((C) == 'Q' ? OK_FOR_Q (OP) :			\
-   (C) == 'R' ? OK_FOR_R (OP) :			\
-   (C) == 'S' ? OK_FOR_S (OP) :			\
-   (C) == 'T' ? OK_FOR_T (OP) :			\
-   (C) == 'U' ? OK_FOR_U (OP) :			\
-   (C) == 'W' ? OK_FOR_W ((OP), (STR)) :	\
-   (C) == 'Y' ? OK_FOR_Y ((OP), (STR)) :	\
-   (C) == 'Z' ? OK_FOR_Z (OP) :			\
-   0)
-
-#define CONSTRAINT_LEN(C, STR) \
-  ((C) == 'P' ? CONSTRAINT_LEN_FOR_P (STR)	\
-   : (C) == 'W' ? CONSTRAINT_LEN_FOR_W (STR)	\
-   : (C) == 'Y' ? CONSTRAINT_LEN_FOR_Y (STR)	\
-   : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-
-/* Experiments suggest that it's better not add 'Q' or 'U' here.  No
-   patterns need it for correctness (no patterns use 'Q' and 'U'
-   without also providing a register alternative).  And defining it
-   will mean that a spilled pseudo could be replaced by its frame
-   location in several consecutive insns.
-
-   Instead, it seems to be better to force pseudos to be reloaded
-   into registers and then use peepholes to recombine insns when
-   beneficial.
-
-   Unfortunately, for WU (unlike plain U, that matches regs as well),
-   we must require a memory address.  In fact, all multi-letter
-   constraints started with W are supposed to have this property, so
-   we just test for W here.  */
-#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
-  ((C) == 'W')
-
-
-#ifndef REG_OK_STRICT
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)	\
   do						\
     {						\
@@ -922,7 +733,11 @@ struct cum_arg
 	goto ADDR;				\
     }						\
   while (0)
+
 #else
+
+#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_INDEX_STRICT_P (X)
+#define REG_OK_FOR_BASE_P(X)  REG_OK_FOR_BASE_STRICT_P (X)
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)	\
   do						\
     {						\
@@ -930,7 +745,9 @@ struct cum_arg
 	goto ADDR;				\
     }						\
   while (0)
+
 #endif
+
 
 /* Go to LABEL if ADDR (a legitimate address expression)
    has an effect that depends on the machine mode it is used for.
==================================================================
--- gcc/config/h8300/h8300.md	(revision 110949)
+++ gcc/config/h8300/h8300.md	(local)
@@ -990,7 +990,7 @@ (define_insn_and_split "*tst_extzv_1_n"
    btst\\t%Z1,%Y0
    #"
   "&& reload_completed
-   && !OK_FOR_U (operands[0])"
+   && !constraint_satisfied_p (operands[0], CONSTRAINT_U)"
   [(set (match_dup 2)
 	(match_dup 0))
    (parallel [(set (cc0) (zero_extract:SI (match_dup 2)
@@ -1056,7 +1056,7 @@ (define_insn_and_split "*tstsi_variable_
    btst\\t%w1,%X0
    #"
   "&& reload_completed
-   && !OK_FOR_U (operands[0])"
+   && !constraint_satisfied_p (operands[0], CONSTRAINT_U)"
   [(set (match_dup 2)
 	(match_dup 0))
    (parallel [(set (cc0) (zero_extract:SI (zero_extend:SI (match_dup 2))
@@ -4762,9 +4762,9 @@ (define_peephole2
 		 (match_operand:HI 2 "register_operand" "")))]
   "REG_P (operands[0]) && REG_P (operands[2])
    && REGNO (operands[0]) != REGNO (operands[2])
-   && (CONST_OK_FOR_J (INTVAL (operands[1]))
-       || CONST_OK_FOR_L (INTVAL (operands[1]))
-       || CONST_OK_FOR_N (INTVAL (operands[1])))"
+   && (constraint_satisfied_p (operands[1], CONSTRAINT_J)
+       || constraint_satisfied_p (operands[1], CONSTRAINT_L)
+       || constraint_satisfied_p (operands[1], CONSTRAINT_N))"
   [(set (match_dup 0)
 	(match_dup 2))
    (set (match_dup 0)
@@ -4792,8 +4792,8 @@ (define_peephole2
   "(TARGET_H8300H || TARGET_H8300S)
    && REG_P (operands[0]) && REG_P (operands[2])
    && REGNO (operands[0]) != REGNO (operands[2])
-   && (CONST_OK_FOR_L (INTVAL (operands[1]))
-       || CONST_OK_FOR_N (INTVAL (operands[1])))"
+   && (constraint_satisfied_p (operands[1], CONSTRAINT_L)
+       || constraint_satisfied_p (operands[1], CONSTRAINT_N))"
   [(set (match_dup 0)
 	(match_dup 2))
    (set (match_dup 0)
@@ -4821,8 +4821,8 @@ (define_peephole2
   "(TARGET_H8300H || TARGET_H8300S)
    && REG_P (operands[0]) && REG_P (operands[1])
    && REGNO (operands[0]) != REGNO (operands[1])
-   && !CONST_OK_FOR_L (INTVAL (operands[2]))
-   && !CONST_OK_FOR_N (INTVAL (operands[2]))
+   && !constraint_satisfied_p (operands[2], CONSTRAINT_L)
+   && !constraint_satisfied_p (operands[2], CONSTRAINT_N)
    && ((INTVAL (operands[2]) & 0xff) == INTVAL (operands[2])
        || (INTVAL (operands[2]) & 0xff00) == INTVAL (operands[2])
        || INTVAL (operands[2]) == 0xffff
==================================================================
--- gcc/config/h8300/predicates.md	(revision 110949)
+++ gcc/config/h8300/predicates.md	(local)
@@ -345,7 +345,7 @@ (define_predicate "bit_operand"
   if (GET_CODE (op) == SUBREG)
     return 1;
   return (GET_CODE (op) == MEM
-	  && OK_FOR_U (op));
+	  && constraint_satisfied_p (op, CONSTRAINT_U));
 })
 
 ;; Return nonzero if OP is a MEM suitable for bit manipulation insns.
@@ -354,7 +354,7 @@ (define_predicate "bit_memory_operand"
   (match_code "mem")
 {
   return (GET_CODE (op) == MEM
-	  && OK_FOR_U (op));
+	  && constraint_satisfied_p (op, CONSTRAINT_U));
 })
 
 ;; Return nonzero if X is a stack pointer.
@@ -409,8 +409,8 @@ (define_predicate "incdec_operand"
   (match_code "const_int")
 {
   return (GET_CODE (op) == CONST_INT
-	  && (CONST_OK_FOR_M (INTVAL (op))
-	      || CONST_OK_FOR_O (INTVAL (op))));
+	  && (constraint_satisfied_p (op, CONSTRAINT_M)
+	      || constraint_satisfied_p (op, CONSTRAINT_O)));
 })
 
 ;; Recognize valid operators for bit instructions.
@@ -481,3 +481,222 @@ (define_predicate "iorxor_operator"
 
   return (code == IOR || code == XOR);
 })
+
+;; FIXME Many constraint definitions need docstrings.
+
+;; Register constraints:
+;;
+;; Some patterns need to use er6 as a scratch register.  This is
+;; difficult to arrange since er6 is the frame pointer and usually
+;; can't be spilled.
+;;
+;; Such patterns should define two alternatives, one which allows only
+;; er6 and one which allows any general register.  The former alternative
+;; should have a 'd' constraint while the latter should be disparaged and
+;; use 'D'.
+;;
+;; Normally, 'd' maps to DESTINATION_REGS and 'D' maps to GENERAL_REGS.
+;; However, there are cases where they should be NO_REGS:
+;;
+;;   - 'd' should be NO_REGS when reloading a function that uses the
+;;     frame pointer.  In this case, DESTINATION_REGS won't contain any
+;;     spillable registers, so the first alternative can't be used.
+;;
+;;   - -fno-omit-frame-pointer means that the frame pointer will
+;;     always be in use.  It's therefore better to map 'd' to NO_REGS
+;;     before reload so that register allocator will pick the second
+;;     alternative.
+;;
+;;   - we would like 'D' to be be NO_REGS when the frame pointer isn't
+;;     live, but we the frame pointer may turn out to be needed after
+;;     we start reload, and then we may have already decided we don't
+;;     have a choice, so we can't do that.  Forcing the register
+;;     allocator to use er6 if possible might produce better code for
+;;     small functions: it's more efficient to save and restore er6 in
+;;     the prologue & epilogue than to do it in a define_split.
+;;     Hopefully disparaging 'D' will have a similar effect, without
+;;     forcing a reload failure if the frame pointer is found to be
+;;     needed too late.
+
+(define_register_constraint "a" "MAC_REGS" 
+  "")
+
+(define_register_constraint "c" "COUNTER_REGS" 
+  "")
+
+(define_register_constraint "D" "GENERAL_REGS"
+  "")
+
+(define_register_constraint "f" "SOURCE_REGS"
+  "")
+
+(define_register_constraint "d"
+  "(flag_omit_frame_pointer || reload_completed)
+   && (!frame_pointer_needed || !reload_in_progress)
+   ? GENERAL_REGS : NO_REGS"
+  "")
+
+;; Integer constant constraints:
+
+(define_constraint "I" 
+  "Integer zero."
+  (and (match_code "const_int")
+       (match_test "ival == 0")))
+
+(define_constraint "J" 
+  "Any integer whose low eight bits are zero."
+  (and (match_code "const_int")
+       (match_test "(ival & 0xff) == 0")))
+
+;; K is not used.
+
+(define_constraint "L"
+  "The integers 1, 2, or (on the H/8300H and H/8300S only) 4."
+  (and (match_code "const_int")
+       (ior (match_test "ival == 1")
+	    (match_test "ival == 2")
+	    (and (match_test "TARGET_H8300H || TARGET_H8300S")
+		 (match_test "ival == 4")))))
+
+(define_constraint "M"
+  "The integers 1 or 2."
+  (and (match_code "const_int")
+       (ior (match_test "ival == 1")
+	    (match_test "ival == 2"))))
+
+(define_constraint "N"
+  "The integers -1, -2, or (on the H/8300H and H/8300S only) -4."
+  (and (match_code "const_int")
+       (ior (match_test "ival == -1")
+	    (match_test "ival == -2")
+	    (and (match_test "TARGET_H8300H || TARGET_H8300S")
+		 (match_test "ival == -4")))))
+
+(define_constraint "O"
+  "The integers -1 or -2."
+  (and (match_code "const_int")
+       (ior (match_test "ival == -1")
+	    (match_test "ival == -2"))))
+
+;; All multi-letter constant constraints start with 'P'.  They have
+;; the general form P[0-9][<>][X0] (but, of course, only those that
+;; are used are defined).  They all represent a nonzero integer which
+;; fits in a specific number of bits; the second character indicates
+;; how many.  The third character is '<' for a negative constant, '>'
+;; for a positive constant.  Finally, the fourth letter is '0' for no
+;; special treatment, 'X' for a constraint only allowed to match when
+;; TARGET_H8300SX is true.
+
+(define_constraint "P1>X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival > 0 && ival < (1 << 1)")))
+
+(define_constraint "P3>X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival > 0 && ival < (1 << 3)")))
+
+(define_constraint "P4>X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival > 0 && ival < (1 << 4)")))
+
+(define_constraint "P5>X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival > 0 && ival < (1 << 5)")))
+
+(define_constraint "P8>X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival > 0 && ival < (1 << 8)")))
+
+(define_constraint "P3<X"
+  ""
+  (and (match_code "const_int")
+       (match_test "TARGET_H8300SX")
+       (match_test "ival < 0 && ival > -(1 << 3)")))
+
+(define_constraint "G"
+  "Single-precision floating-point zero."
+  (and (match_code "const_double")
+       (match_test "op == CONST0_RTX (SFmode)")))
+
+;; Extra constant constraints.
+
+(define_constraint "R"
+  ""
+  (and (match_code "const_int")
+       (not (match_test "h8300_shift_needs_scratch_p (ival, QImode)"))))
+
+(define_constraint "S"
+  ""
+  (and (match_code "const_int")
+       (not (match_test "h8300_shift_needs_scratch_p (ival, HImode)"))))
+
+(define_constraint "T"
+  ""
+  (and (match_code "const_int")
+       (not (match_test "h8300_shift_needs_scratch_p (ival, SImode)"))))
+
+;; Memory constraints.
+;;
+;; Experiments suggest that it's better not to use
+;; define_memory_constraint for 'Q' or 'U'.  No patterns need it for
+;; correctness (no patterns use 'Q' or 'U' without also providing a
+;; register alternative).  And use of define_memory_constraint means
+;; that a spilled pseudo could be replaced by its frame location in
+;; several consecutive insns.
+;;
+;; Instead, it seems to be better to force pseudos to be reloaded
+;; into registers and then use peepholes to recombine insns when
+;; beneficial.
+
+(define_constraint "Q"
+  ""
+  (and (match_test "TARGET_H8300SX")
+       (match_test "memory_operand (op, VOIDmode)")))
+
+(define_constraint "U"
+  "A valid bset destination; that is, a register, register indirect,
+   or the eightbit memory region (a @code{symbol_ref} with the
+   @code{symbol_ref_flag} set).  On H8S, a 16- or 32-bit absolute
+   address is also valid."
+  (ior (and (match_code "reg") (match_test "REG_OK_FOR_BASE_P (op)"))
+       (and (match_code "mem")
+	    (ior (and (match_code "reg" "0")
+		      (match_test "REG_OK_FOR_BASE_P (XEXP (op, 0))"))
+		 (match_test "h8300_eightbit_constant_address_p (XEXP (op, 0))")
+		 (and (match_test "TARGET_H8300S")
+		      (ior (match_code "symbol_ref" "0")
+			   (match_code "const_int" "0"))
+			   (and (match_code "const" "0")
+				(match_code "plus" "00")
+				(match_code "symbol_ref" "000")
+				(match_code "const_int" "001")))))))
+
+;; Multi-letter constraints starting with W are to be used for
+;; operands that require a memory operand, i.e,. that are never used
+;; along with register constraints.  For operands that require a
+;; memory operand (or not) but that always accept a register, a
+;; multi-letter constraint starting with Y should be used instead.
+;; All W constraints must be appropriate to mark as memory constraints.
+
+(define_memory_constraint "WU"
+  "A bset destination (as 'U'), excluding registers."
+  (and (match_code "mem")
+       (match_test "constraint_satisfied_p (op, CONSTRAINT_U)")))
+
+;; Y is reserved for future multi-letter constraints.
+
+(define_constraint "Z"
+  ""
+  (and (match_test "TARGET_H8300SX")
+       (match_code "mem")
+       (match_test "CONSTANT_P (XEXP (op, 0))")))
==================================================================
--- gcc/config/i386/i386.c	(revision 110949)
+++ gcc/config/i386/i386.c	(local)
@@ -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 && constraint_satisfied_p (disp, CONSTRAINT_K))
 	    len = 1;
 	  else
 	    len = 4;
@@ -13326,9 +13324,8 @@ ix86_attr_length_immediate_default (rtx 
     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 && constraint_satisfied_p (recog_data.operand[i],
+						 CONSTRAINT_K))
 	  len = 1;
 	else
 	  {
==================================================================
--- gcc/config/i386/i386.h	(revision 110949)
+++ gcc/config/i386/i386.h	(local)
@@ -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.  */
==================================================================
--- gcc/config/i386/i386.md	(revision 110949)
+++ gcc/config/i386/i386.md	(local)
@@ -2440,9 +2440,9 @@ (define_split
 
 (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 @@ (define_split
   "! TARGET_PARTIAL_REG_STALL && reload_completed
    && ((GET_MODE (operands[0]) == HImode 
 	&& ((!optimize_size && !TARGET_FAST_PREFIX)
+            /* ??? next two lines just !constraint_satisfied_p (..., K) */
 	    || GET_CODE (operands[2]) != CONST_INT
-	    || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')))
+	    || constraint_satisfied_p (operands[2], CONSTRAINT_K)))
        || (GET_MODE (operands[0]) == QImode 
 	   && (TARGET_PROMOTE_QImode || optimize_size)))"
   [(parallel [(set (match_dup 0)
@@ -19361,8 +19362,7 @@ (define_peephole2
 	   (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')))
+       || constraint_satisfied_p (operands[3], CONSTRAINT_K))
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel
      [(set (match_dup 0)
@@ -19928,8 +19928,7 @@ (define_peephole2
 			    (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'))"
+   && !constraint_satisfied_p (operands[2], CONSTRAINT_K)"
   [(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 @@ (define_peephole2
 			    (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'))"
+   && !constraint_satisfied_p (operands[2], CONSTRAINT_K)"
   [(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 @@ (define_peephole2
 			      (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'))"
+   && !constraint_satisfied_p (operands[2], CONSTRAINT_K)"
   [(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 @@ (define_peephole2
 	      (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')"
+   && constraint_satisfied_p (operands[2], CONSTRAINT_K)"
   [(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 @@ (define_peephole2
 	      (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')"
+   && constraint_satisfied_p (operands[2], CONSTRAINT_K)"
   [(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))])]
==================================================================
--- gcc/config/i386/predicates.md	(revision 110949)
+++ gcc/config/i386/predicates.md	(local)
@@ -947,3 +947,137 @@ (define_predicate "compare_operator"
 
 (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"))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]