summaryrefslogtreecommitdiff
path: root/gcc/config/xtensa
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/xtensa')
-rw-r--r--gcc/config/xtensa/constraints.md140
-rw-r--r--gcc/config/xtensa/xtensa-protos.h2
-rw-r--r--gcc/config/xtensa/xtensa.c125
-rw-r--r--gcc/config/xtensa/xtensa.h69
-rw-r--r--gcc/config/xtensa/xtensa.md19
5 files changed, 149 insertions, 206 deletions
diff --git a/gcc/config/xtensa/constraints.md b/gcc/config/xtensa/constraints.md
new file mode 100644
index 00000000000..c58d979c3ce
--- /dev/null
+++ b/gcc/config/xtensa/constraints.md
@@ -0,0 +1,140 @@
+;; Constraint definitions for Xtensa.
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Register constraints.
+
+(define_register_constraint "a" "GR_REGS"
+ "General-purpose AR registers @code{a0}-@code{a15},
+ except @code{a1} (@code{sp}).")
+
+(define_register_constraint "b" "TARGET_BOOLEANS ? BR_REGS : NO_REGS"
+ "Boolean registers @code{b0}-@code{b15}; only available if the Xtensa
+ Boolean Option is configured.")
+
+(define_register_constraint "d" "TARGET_DENSITY ? AR_REGS: NO_REGS"
+ "@internal
+ All AR registers, including sp, but only if the Xtensa Code Density
+ Option is configured.")
+
+(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
+ "Floating-point registers @code{f0}-@code{f15}; only available if the
+ Xtensa Floating-Pointer Coprocessor is configured.")
+
+(define_register_constraint "q" "SP_REG"
+ "@internal
+ The stack pointer (register @code{a1}).")
+
+(define_register_constraint "A" "TARGET_MAC16 ? ACC_REG : NO_REGS"
+ "The low 32 bits of the accumulator from the Xtensa MAC16 Option.")
+
+(define_register_constraint "B" "TARGET_SEXT ? GR_REGS : NO_REGS"
+ "@internal
+ General-purpose AR registers, but only if the Xtensa Sign Extend
+ Option is configured.")
+
+(define_register_constraint "C" "TARGET_MUL16 ? GR_REGS: NO_REGS"
+ "@internal
+ General-purpose AR registers, but only if the Xtensa 16-Bit Integer
+ Multiply Option is configured.")
+
+(define_register_constraint "D" "TARGET_DENSITY ? GR_REGS: NO_REGS"
+ "@internal
+ General-purpose AR registers, but only if the Xtensa Code Density
+ Option is configured.")
+
+(define_register_constraint "W" "TARGET_CONST16 ? GR_REGS: NO_REGS"
+ "@internal
+ General-purpose AR registers, but only if the Xtensa Const16
+ Option is configured.")
+
+;; Integer constant constraints.
+
+(define_constraint "I"
+ "A signed 12-bit integer constant for use with MOVI instructions."
+ (and (match_code "const_int")
+ (match_test "xtensa_simm12b (ival)")))
+
+(define_constraint "J"
+ "A signed 8-bit integer constant for use with ADDI instructions."
+ (and (match_code "const_int")
+ (match_test "xtensa_simm8 (ival)")))
+
+(define_constraint "K"
+ "A constant integer that can be an immediate operand of an Xtensa
+ conditional branch instruction that performs a signed comparison or
+ a comparison against zero."
+ (and (match_code "const_int")
+ (match_test "xtensa_b4const_or_zero (ival)")))
+
+(define_constraint "L"
+ "A constant integer that can be an immediate operand of an Xtensa
+ conditional branch instruction that performs an unsigned comparison."
+ (and (match_code "const_int")
+ (match_test "xtensa_b4constu (ival)")))
+
+(define_constraint "M"
+ "An integer constant in the range @minus{}32-95 for use with MOVI.N
+ instructions."
+ (and (match_code "const_int")
+ (match_test "ival >= -32 && ival <= 95")))
+
+(define_constraint "N"
+ "An unsigned 8-bit integer constant shifted left by 8 bits for use
+ with ADDMI instructions."
+ (and (match_code "const_int")
+ (match_test "xtensa_simm8x256 (ival)")))
+
+(define_constraint "O"
+ "An integer constant that can be used in ADDI.N instructions."
+ (and (match_code "const_int")
+ (match_test "ival == -1 || (ival >= 1 && ival <= 15)")))
+
+(define_constraint "P"
+ "An integer constant that can be used as a mask value in an EXTUI
+ instruction."
+ (and (match_code "const_int")
+ (match_test "xtensa_mask_immediate (ival)")))
+
+;; Memory constraints. Do not use define_memory_constraint here. Doing so
+;; causes reload to force some constants into the constant pool, but since
+;; the Xtensa constant pool can only be accessed with L32R instructions, it
+;; is always better to just copy a constant into a register. Instead, use
+;; regular constraints but add a check to allow pseudos during reload.
+
+(define_constraint "R"
+ "Memory that can be accessed with a 4-bit unsigned offset from a register."
+ (ior (and (match_code "mem")
+ (match_test "smalloffset_mem_p (op)"))
+ (and (match_code "reg")
+ (match_test "reload_in_progress
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER"))))
+
+(define_constraint "T"
+ "Memory in a literal pool (addressable with an L32R instruction)."
+ (and (match_code "mem")
+ (match_test "!TARGET_CONST16 && constantpool_mem_p (op)")))
+
+(define_constraint "U"
+ "Memory that is not in a literal pool."
+ (ior (and (match_code "mem")
+ (match_test "! constantpool_mem_p (op)"))
+ (and (match_code "reg")
+ (match_test "reload_in_progress
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER"))))
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index 7f8ad2e8065..762aa0aed61 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -29,7 +29,6 @@ extern bool xtensa_simm12b (HOST_WIDE_INT);
extern bool xtensa_b4const_or_zero (HOST_WIDE_INT);
extern bool xtensa_b4constu (HOST_WIDE_INT);
extern bool xtensa_mask_immediate (HOST_WIDE_INT);
-extern bool xtensa_const_ok_for_letter_p (HOST_WIDE_INT, int);
extern bool xtensa_mem_offset (unsigned, enum machine_mode);
/* Functions within xtensa.c that we reference. */
@@ -40,7 +39,6 @@ extern int smalloffset_mem_p (rtx);
extern int constantpool_address_p (rtx);
extern int constantpool_mem_p (rtx);
extern void xtensa_extend_reg (rtx, rtx);
-extern bool xtensa_extra_constraint (rtx, int);
extern void xtensa_expand_conditional_branch (rtx *, enum rtx_code);
extern int xtensa_expand_conditional_move (rtx *, int);
extern int xtensa_expand_scc (rtx *);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index fa5f08d2d23..011f63cd275 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -123,75 +123,6 @@ const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] =
ACC_REG,
};
-/* Map register constraint character to register class. */
-enum reg_class xtensa_char_to_class[256] =
-{
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
- NO_REGS, NO_REGS, NO_REGS, NO_REGS,
-};
-
static enum internal_test map_test_to_internal_test (enum rtx_code);
static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);
static rtx gen_float_relational (enum rtx_code, rtx, rtx);
@@ -276,11 +207,9 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
#define TARGET_EXPAND_BUILTIN xtensa_expand_builtin
struct gcc_target targetm = TARGET_INITIALIZER;
-
-/*
- * Functions to test Xtensa immediate operand validity.
- */
+
+/* Functions to test Xtensa immediate operand validity. */
bool
xtensa_simm8 (HOST_WIDE_INT v)
@@ -406,25 +335,6 @@ xtensa_mask_immediate (HOST_WIDE_INT v)
}
-bool
-xtensa_const_ok_for_letter_p (HOST_WIDE_INT v, int c)
-{
- switch (c)
- {
- case 'I': return xtensa_simm12b (v);
- case 'J': return xtensa_simm8 (v);
- case 'K': return (v == 0 || xtensa_b4const (v));
- case 'L': return xtensa_b4constu (v);
- case 'M': return (v >= -32 && v <= 95);
- case 'N': return xtensa_simm8x256 (v);
- case 'O': return (v == -1 || (v >= 1 && v <= 15));
- case 'P': return xtensa_mask_immediate (v);
- default: break;
- }
- return false;
-}
-
-
/* This is just like the standard true_regnum() function except that it
works even when reg_renumber is not initialized. */
@@ -590,26 +500,6 @@ xtensa_mem_offset (unsigned v, enum machine_mode mode)
}
-bool
-xtensa_extra_constraint (rtx op, int c)
-{
- /* Allow pseudo registers during reload. */
- if (GET_CODE (op) != MEM)
- return (c >= 'R' && c <= 'U'
- && reload_in_progress && GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER);
-
- switch (c)
- {
- case 'R': return smalloffset_mem_p (op);
- case 'T': return !TARGET_CONST16 && constantpool_mem_p (op);
- case 'U': return !constantpool_mem_p (op);
- default: break;
- }
- return false;
-}
-
-
/* Make normal rtx_code into something we can index from an array. */
static enum internal_test
@@ -1623,17 +1513,6 @@ override_options (void)
if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)
error ("boolean registers required for the floating-point option");
- xtensa_char_to_class['q'] = SP_REG;
- xtensa_char_to_class['a'] = GR_REGS;
- xtensa_char_to_class['b'] = ((TARGET_BOOLEANS) ? BR_REGS : NO_REGS);
- xtensa_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
- xtensa_char_to_class['A'] = ((TARGET_MAC16) ? ACC_REG : NO_REGS);
- xtensa_char_to_class['B'] = ((TARGET_SEXT) ? GR_REGS : NO_REGS);
- xtensa_char_to_class['C'] = ((TARGET_MUL16) ? GR_REGS: NO_REGS);
- xtensa_char_to_class['D'] = ((TARGET_DENSITY) ? GR_REGS: NO_REGS);
- xtensa_char_to_class['d'] = ((TARGET_DENSITY) ? AR_REGS: NO_REGS);
- xtensa_char_to_class['W'] = ((TARGET_CONST16) ? GR_REGS: NO_REGS);
-
/* Set up array giving whether a given register can hold a given mode. */
for (mode = VOIDmode;
mode != MAX_MACHINE_MODE;
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 0f35da52cdb..4300e11d711 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -485,75 +485,6 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
incoming or outgoing arguments. */
#define SMALL_REGISTER_CLASSES 1
-
-/* REGISTER AND CONSTANT CLASSES */
-
-/* Get reg_class from a letter such as appears in the machine
- description.
-
- Available letters: a-f,h,j-l,q,t-z,A-D,W,Y-Z
-
- DEFINED REGISTER CLASSES:
-
- 'a' general-purpose registers except sp
- 'q' sp (aka a1)
- 'D' general-purpose registers (only if density option enabled)
- 'd' general-purpose registers, including sp (only if density enabled)
- 'A' MAC16 accumulator (only if MAC16 option enabled)
- 'B' general-purpose registers (only if sext instruction enabled)
- 'C' general-purpose registers (only if mul16 option enabled)
- 'W' general-purpose registers (only if const16 option enabled)
- 'b' coprocessor boolean registers
- 'f' floating-point registers
-*/
-
-extern enum reg_class xtensa_char_to_class[256];
-
-#define REG_CLASS_FROM_LETTER(C) xtensa_char_to_class[ (int) (C) ]
-
-/* The letters I, J, K, L, M, N, O, and 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.
-
- For Xtensa:
-
- I = 12-bit signed immediate for MOVI
- J = 8-bit signed immediate for ADDI
- K = 4-bit value in (b4const U {0})
- L = 4-bit value in b4constu
- M = 7-bit immediate value for MOVI.N
- N = 8-bit unsigned immediate shifted left by 8 bits for ADDMI
- O = 4-bit immediate for ADDI.N
- P = valid immediate mask value for EXTUI */
-
-#define CONST_OK_FOR_LETTER_P xtensa_const_ok_for_letter_p
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) (0)
-
-
-/* Other letters can be defined in a machine-dependent fashion to
- stand for particular classes of registers or other arbitrary
- operand types.
-
- R = memory that can be accessed with a 4-bit unsigned offset
- T = memory in a constant pool (addressable with a pc-relative load)
- U = memory *NOT* in a constant pool
-
- The offset range should not be checked here (except to distinguish
- denser versions of the instructions for which more general versions
- are available). Doing so leads to problems in reloading: an
- argptr-relative address may become invalid when the phony argptr is
- eliminated in favor of the stack pointer (the offset becomes too
- large to fit in the instruction's immediate field); a reload is
- generated to fix this but the RTL is not immediately updated; in
- the meantime, the constraints are checked and none match. The
- solution seems to be to simply skip the offset check here. The
- address will be checked anyway because of the code in
- GO_IF_LEGITIMATE_ADDRESS. */
-
-#define EXTRA_CONSTRAINT xtensa_extra_constraint
-
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
xtensa_preferred_reload_class (X, CLASS, 0)
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index c3f38cb93e8..6b48e86e1dc 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -117,9 +117,10 @@
(eq_attr "type" "fconv")
"nothing")
-;; Include predicate definitions
+;; Include predicates and constraints.
(include "predicates.md")
+(include "constraints.md")
;; Addition.
@@ -1570,8 +1571,8 @@
})
(define_insn "call_internal"
- [(call (mem (match_operand:SI 0 "call_insn_operand" "n,i,r"))
- (match_operand 1 "" "i,i,i"))]
+ [(call (mem (match_operand:SI 0 "call_insn_operand" "nir"))
+ (match_operand 1 "" "i"))]
""
{
return xtensa_emit_call (0, operands);
@@ -1594,16 +1595,10 @@
XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
})
-;; Cannot combine constraints for operand 0 into "afvb":
-;; reload.c:find_reloads seems to assume that grouped constraints somehow
-;; specify related register classes, and when they don't the constraints
-;; fail to match. By not grouping the constraints, we get the correct
-;; behavior.
(define_insn "call_value_internal"
- [(set (match_operand 0 "register_operand" "=af,af,af,v,v,v,b,b,b")
- (call (mem (match_operand:SI 1 "call_insn_operand"
- "n,i,r,n,i,r,n,i,r"))
- (match_operand 2 "" "i,i,i,i,i,i,i,i,i")))]
+ [(set (match_operand 0 "register_operand" "=a")
+ (call (mem (match_operand:SI 1 "call_insn_operand" "nir"))
+ (match_operand 2 "" "i")))]
""
{
return xtensa_emit_call (1, operands);