+2000-08-28 Richard Henderson <rth@cygnus.com>
+
+ * local-alloc.c (requires_inout): Don't use reserved range for
+ EXTRA_CONSTRAINTS; use anything not matched by REG_CLASS_FROM_LETTER.
+ * recog.c (asm_operand_ok): Likewise.
+ (preprocess_constraints, constrain_operands): Likewise.
+ * regclass.c (record_reg_classes): Likewise.
+ * reload.c (find_reloads): Likewise.
+ * reload1.c (maybe_fix_stack_asms): Likewise.
+ (reload_cse_simplify_operands): Likewise.
+ * stmt.c (expand_asm_operands): Likewise.
+
+ * md.texi: Update constraints documentation.
+ * tm.texi (EXTRA_CONSTRAINT): Update.
+
2000-08-28 Jason Merrill <jason@redhat.com>
* dwarf2out.c (new_loc_descr): Use calloc.
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
case 'X':
/* These don't say anything we care about. */
break;
found_zero = 1;
break;
+ default:
+ if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+ break;
+ /* FALLTHRU */
case 'p':
case 'g': case 'r':
- default:
reg_allowed = 1;
break;
}
A register operand is allowed provided that it is in a general
register.
-@cindex @samp{d} in constraint
-@item @samp{d}, @samp{a}, @samp{f}, @dots{}
-Other letters can be defined in machine-dependent fashion to stand for
-particular classes of registers. @samp{d}, @samp{a} and @samp{f} are
-defined on the 68000/68020 to stand for data, address and floating
-point registers.
-
@cindex constants in constraints
@cindex @samp{i} in constraint
@item @samp{i}
the mode specified in the @code{match_operand} as the mode of the memory
reference for which the address would be valid.
+@cindex other register constraints
@cindex extensible constraints
-@cindex @samp{Q}, in constraint
-@item @samp{Q}, @samp{R}, @samp{S}, @dots{} @samp{U}
-Letters in the range @samp{Q} through @samp{U} may be defined in a
-machine-dependent fashion to stand for arbitrary operand types.
-@ifset INTERNALS
-The machine description macro @code{EXTRA_CONSTRAINT} is passed the
-operand as its first argument and the constraint letter as its
-second operand.
+@item @var{other letters}
+Other letters can be defined in machine-dependent fashion to stand for
+particular classes of registers or other arbitrary operand types.
+@samp{d}, @samp{a} and @samp{f} are defined on the 68000/68020 to stand
+for data, address and floating point registers.
-A typical use for this would be to distinguish certain types of
-memory references that affect other insn operands.
+@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.
-Do not define these constraint letters to accept register references
-(@code{reg}); the reload pass does not expect this and would not handle
-it properly.
+A typical use for @code{EXTRA_CONSTRANT} would be to distinguish certain
+types of memory references that affect other insn operands.
@end ifset
@end table
while (*constraint)
{
- switch (*constraint++)
+ char c = *constraint++;
+ switch (c)
{
case '=':
case '+':
return 1;
break;
+ default:
+ /* For all other letters, we first check for a register class,
+ otherwise it is an EXTRA_CONSTRAINT. */
+ if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+ {
+ case 'r':
+ if (GET_MODE (op) == BLKmode)
+ break;
+ if (register_operand (op, VOIDmode))
+ return 1;
+ }
#ifdef EXTRA_CONSTRAINT
- case 'Q':
- if (EXTRA_CONSTRAINT (op, 'Q'))
- return 1;
- break;
- case 'R':
- if (EXTRA_CONSTRAINT (op, 'R'))
- return 1;
- break;
- case 'S':
- if (EXTRA_CONSTRAINT (op, 'S'))
- return 1;
- break;
- case 'T':
- if (EXTRA_CONSTRAINT (op, 'T'))
+ if (EXTRA_CONSTRAINT (op, c))
return 1;
- break;
- case 'U':
- if (EXTRA_CONSTRAINT (op, 'U'))
- return 1;
- break;
#endif
-
- case 'r':
- default:
- if (GET_MODE (op) == BLKmode)
- break;
- if (register_operand (op, VOIDmode))
- return 1;
break;
}
}
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
/* These don't say anything we care about. */
break;
win = 1;
break;
- case 'r':
- if (strict < 0
- || (strict == 0
- && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
- || (strict == 0 && GET_CODE (op) == SCRATCH)
- || (GET_CODE (op) == REG
- && ((GENERAL_REGS == ALL_REGS
- && REGNO (op) < FIRST_PSEUDO_REGISTER)
- || reg_fits_class_p (op, GENERAL_REGS,
- offset, mode))))
- win = 1;
- break;
-
case 'X':
/* This is used for a MATCH_SCRATCH in the cases when
we don't actually need anything. So anything goes
win = 1;
break;
-#ifdef EXTRA_CONSTRAINT
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- if (EXTRA_CONSTRAINT (op, c))
- win = 1;
- break;
-#endif
-
case 'V':
if (GET_CODE (op) == MEM
&& ((strict > 0 && ! offsettable_memref_p (op))
break;
default:
- if (strict < 0
- || (strict == 0
- && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
- || (strict == 0 && GET_CODE (op) == SCRATCH)
- || (GET_CODE (op) == REG
- && reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),
- offset, mode)))
- win = 1;
+ {
+ enum reg_class class;
+
+ class = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_LETTER (c));
+ if (class != NO_REGS)
+ {
+ if (strict < 0
+ || (strict == 0
+ && GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+ || (strict == 0 && GET_CODE (op) == SCRATCH)
+ || (GET_CODE (op) == REG
+ && reg_fits_class_p (op, class, offset, mode)))
+ win = 1;
+ }
+#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_CONSTRAINT (op, c))
+ win = 1;
+#endif
+ break;
+ }
}
constraints[opno] = p;
win = 1;
break;
-#ifdef EXTRA_CONSTRAINT
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- if (EXTRA_CONSTRAINT (op, c))
- win = 1;
- break;
-#endif
-
case 'g':
if (GET_CODE (op) == MEM
|| (CONSTANT_P (op)
break;
default:
- classes[i]
- = reg_class_subunion[(int) classes[i]]
- [(int) REG_CLASS_FROM_LETTER (c)];
+ if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+ classes[i]
+ = reg_class_subunion[(int) classes[i]]
+ [(int) REG_CLASS_FROM_LETTER (c)];
+#ifdef EXTRA_CONSTRAINT
+ else if (EXTRA_CONSTRAINT (op, c))
+ win = 1;
+#endif
+ break;
}
constraints[i] = p;
= (int) reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
goto reg;
+ default:
+ if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
+ {
#ifdef EXTRA_CONSTRAINT
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- if (EXTRA_CONSTRAINT (operand, c))
- win = 1;
- break;
+ if (EXTRA_CONSTRAINT (operand, c))
+ win = 1;
#endif
+ break;
+ }
- default:
this_alternative[i]
= (int) reg_class_subunion[this_alternative[i]][(int) REG_CLASS_FROM_LETTER (c)];
-
reg:
if (GET_MODE (operand) == BLKmode)
break;
case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
break;
case 'p':
case 's': case 'i': case 'n':
case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
case 'p': case 'X':
/* These don't say anything we care about. */
break;
break;
case 'g': case 'X':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
allows_reg = 1;
allows_mem = 1;
break;
case 'p': case 'r':
- default:
allows_reg = 1;
break;
+
+ default:
+ if (! ISALPHA (constraint[j]))
+ {
+ error ("invalid punctuation `%c' in constraint",
+ constraint[j]);
+ return;
+ }
+ if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
+ allows_reg = 1;
+#ifdef EXTRA_CONSTRAINT
+ else
+ {
+ /* Otherwise we can't assume anything about the nature of
+ the constraint except that it isn't purely registers.
+ Treat it like "g" and hope for the best. */
+ allows_reg = 1;
+ allows_mem = 1;
+ }
+#endif
+ break;
}
/* If an output operand is not a decl or indirect ref and our constraint
/* ... fall through ... */
case 'p': case 'r':
- default:
allows_reg = 1;
break;
case 'g': case 'X':
-#ifdef EXTRA_CONSTRAINT
- case 'Q': case 'R': case 'S': case 'T': case 'U':
-#endif
-
allows_reg = 1;
allows_mem = 1;
break;
+
+ default:
+ if (! ISALPHA (constraint[j]))
+ {
+ error ("invalid punctuation `%c' in constraint",
+ constraint[j]);
+ return;
+ }
+ if (REG_CLASS_FROM_LETTER (constraint[j]) != NO_REGS)
+ allows_reg = 1;
+#ifdef EXTRA_CONSTRAINT
+ else
+ {
+ /* Otherwise we can't assume anything about the nature of
+ the constraint except that it isn't purely registers.
+ Treat it like "g" and hope for the best. */
+ allows_reg = 1;
+ allows_mem = 1;
+ }
+#endif
+ break;
}
if (! allows_reg && allows_mem)
@findex EXTRA_CONSTRAINT
@item EXTRA_CONSTRAINT (@var{value}, @var{c})
A C expression that defines the optional machine-dependent constraint
-letters (@samp{Q}, @samp{R}, @samp{S}, @samp{T}, @samp{U}) that can
-be used to segregate specific types of operands, usually memory
-references, for the target machine. Normally this macro will not be
-defined. If it is required for a particular target machine, it should
-return 1 if @var{value} corresponds to the operand type represented by
-the constraint letter @var{c}. If @var{c} is not defined as an extra
+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 @code{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 @var{value} corresponds to the operand type represented by the
+constraint letter @var{c}. If @var{c} is not defined as an extra
constraint, the value returned should be 0 regardless of @var{value}.
-For example, on the ROMP, load instructions cannot have their output in r0 if
-the memory reference contains a symbolic address. Constraint letter
-@samp{Q} is defined as representing a memory address that does
+For example, on the ROMP, load instructions cannot have their output
+in r0 if the memory reference contains a symbolic address. Constraint
+letter @samp{Q} is defined as representing a memory address that does
@emph{not} contain a symbolic address. An alternative is specified with
a @samp{Q} constraint on the input and @samp{r} on the output. The next
alternative specifies @samp{m} on the input and a register class that