diff options
Diffstat (limited to 'gcc/config/xtensa')
-rw-r--r-- | gcc/config/xtensa/constraints.md | 140 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.c | 125 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.h | 69 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.md | 19 |
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); |