re PR target/54089 ([SH] Refactor shift patterns)
[gcc.git] / gcc / config / sh / sh.h
index 7a2af0a2841b3fa9a04d4ce44a381f18fc62545b..d72379022bbd6d8d64f7eea5731962563c19ec8a 100644 (file)
@@ -172,6 +172,9 @@ do { \
   (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 \
    && ! (TARGET_HITACHI || sh_attr_renesas_p (FUN_DECL)))
 
+/* Nonzero if either soft or hard atomics are enabled.  */
+#define TARGET_ANY_ATOMIC (TARGET_SOFT_ATOMIC | TARGET_HARD_ATOMIC)
+
 #ifndef TARGET_CPU_DEFAULT
 #define TARGET_CPU_DEFAULT SELECT_SH1
 #define SUPPORT_SH1 1
@@ -290,7 +293,7 @@ do { \
 #endif
 
 #ifndef TARGET_OPT_DEFAULT
-#define TARGET_OPT_DEFAULT  MASK_ADJUST_UNROLL
+#define TARGET_OPT_DEFAULT  0
 #endif
 
 #define TARGET_DEFAULT \
@@ -335,8 +338,8 @@ do { \
 #endif
 
 #define SH_ASM_SPEC \
- "%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)}\
-%(subtarget_asm_isa_spec) %(subtarget_asm_spec)\
+ "%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)} \
+%(subtarget_asm_isa_spec) %(subtarget_asm_spec) \
 %{m2a:--isa=sh2a} \
 %{m2a-single:--isa=sh2a} \
 %{m2a-single-only:--isa=sh2a} \
@@ -433,7 +436,20 @@ do { \
 "%{m2a*:%eSH2a does not support little-endian}}"
 #endif
 
-#define DRIVER_SELF_SPECS UNSUPPORTED_SH2A
+#define UNSUPPORTED_ATOMIC_OPTIONS \
+"%{msoft-atomic:%{mhard-atomic:%e-msoft-atomic and -mhard-atomic cannot be \
+used at the same time}}"
+
+#if TARGET_CPU_DEFAULT & MASK_SH4A
+#define UNSUPPORTED_HARD_ATOMIC_CPU ""
+#else
+#define UNSUPPORTED_HARD_ATOMIC_CPU \
+"%{!m4a*:%{mhard-atomic:%e-mhard-atomic is only available for SH4A targets}}"
+#endif
+
+#undef DRIVER_SELF_SPECS
+#define DRIVER_SELF_SPECS UNSUPPORTED_SH2A, UNSUPPORTED_ATOMIC_OPTIONS,\
+                         UNSUPPORTED_HARD_ATOMIC_CPU
 
 #define ASSEMBLER_DIALECT assembler_dialect
 
@@ -1197,12 +1213,8 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
 \f
 /* Defines for sh.md and constraints.md.  */
 
-#define CONST_OK_FOR_I06(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32 \
-                                && ((HOST_WIDE_INT)(VALUE)) <= 31)
 #define CONST_OK_FOR_I08(VALUE) (((HOST_WIDE_INT)(VALUE))>= -128 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 127)
-#define CONST_OK_FOR_I10(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \
-                                && ((HOST_WIDE_INT)(VALUE)) <= 511)
 #define CONST_OK_FOR_I16(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -32768 \
                                 && ((HOST_WIDE_INT)(VALUE)) <= 32767)
 
@@ -1216,80 +1228,6 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
 #define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\
   (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX))
 
-#if 0
-#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
-  ((((REGCLASS_HAS_FP_REG (CLASS)                                      \
-      && (REG_P (X)                                                    \
-      && (GENERAL_OR_AP_REGISTER_P (REGNO (X))                         \
-         || (FP_REGISTER_P (REGNO (X)) && (MODE) == SImode             \
-             && TARGET_FMOVD))))                                       \
-     || (REGCLASS_HAS_GENERAL_REG (CLASS)                              \
-        && REG_P (X)                                                   \
-        && FP_REGISTER_P (REGNO (X))))                                 \
-    && ! TARGET_SHMEDIA                                                        \
-    && ((MODE) == SFmode || (MODE) == SImode))                         \
-   ? FPUL_REGS                                                         \
-   : (((CLASS) == FPUL_REGS                                            \
-       || (REGCLASS_HAS_FP_REG (CLASS)                                 \
-          && ! TARGET_SHMEDIA && MODE == SImode))                      \
-      && (MEM_P (X)                                                    \
-         || (REG_P (X)                                                 \
-             && (REGNO (X) >= FIRST_PSEUDO_REGISTER                    \
-                 || REGNO (X) == T_REG                                 \
-                 || system_reg_operand (X, VOIDmode)))))               \
-   ? GENERAL_REGS                                                      \
-   : (((CLASS) == TARGET_REGS                                          \
-       || (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS))                 \
-      && !satisfies_constraint_Csy (X)                                 \
-      && (!REG_P (X) || ! GENERAL_REGISTER_P (REGNO (X))))             \
-   ? GENERAL_REGS                                                      \
-   : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS)                      \
-      && REG_P (X) && ! GENERAL_REGISTER_P (REGNO (X))                 \
-      && (CLASS) != REGNO_REG_CLASS (REGNO (X)))                       \
-   ? GENERAL_REGS                                                      \
-   : ((CLASS) != GENERAL_REGS && REG_P (X)                             \
-      && TARGET_REGISTER_P (REGNO (X)))                                        \
-   ? GENERAL_REGS : (ELSE))
-
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
- SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,NO_REGS)
-
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X)  \
-  ((REGCLASS_HAS_FP_REG (CLASS)                                        \
-    && ! TARGET_SHMEDIA                                                        \
-    && immediate_operand ((X), (MODE))                                 \
-    && ! ((fp_zero_operand (X) || fp_one_operand (X))                  \
-         && (MODE) == SFmode && fldi_ok ()))                           \
-   ? R0_REGS                                                           \
-   : ((CLASS) == FPUL_REGS                                             \
-      && ((REG_P (X)                                                   \
-          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
-              || REGNO (X) == T_REG))                                  \
-         || GET_CODE (X) == PLUS))                                     \
-   ? GENERAL_REGS                                                      \
-   : (CLASS) == FPUL_REGS && immediate_operand ((X), (MODE))           \
-   ? (satisfies_constraint_I08 (X)                                     \
-      ? GENERAL_REGS                                                   \
-      : R0_REGS)                                                       \
-   : ((CLASS) == FPSCR_REGS                                            \
-      && ((REG_P (X) && REGNO (X) >= FIRST_PSEUDO_REGISTER)            \
-         || (MEM_P (X) && GET_CODE (XEXP ((X), 0)) == PLUS)))          \
-   ? GENERAL_REGS                                                      \
-   : (REGCLASS_HAS_FP_REG (CLASS)                                      \
-      && TARGET_SHMEDIA                                                        \
-      && immediate_operand ((X), (MODE))                               \
-      && (X) != CONST0_RTX (GET_MODE (X))                              \
-      && GET_MODE (X) != V4SFmode)                                     \
-   ? GENERAL_REGS                                                      \
-   : (((MODE) == QImode || (MODE) == HImode)                           \
-      && TARGET_SHMEDIA && inqhi_operand ((X), (MODE)))                        \
-   ? GENERAL_REGS                                                      \
-   : (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS                                \
-      && (GET_CODE (X) == LABEL_REF || PIC_ADDR_P (X)))                        \
-   ? TARGET_REGS                                                       \
-   : SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
-#endif
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
@@ -1725,7 +1663,7 @@ struct sh_args {
    can ignore COUNT.  */
 
 #define RETURN_ADDR_RTX(COUNT, FRAME)  \
-  (((COUNT) == 0) ? sh_get_pr_initial_val () : (rtx) 0)
+  (((COUNT) == 0) ? sh_get_pr_initial_val () : NULL_RTX)
 
 /* A C expression whose value is RTL representing the location of the
    incoming return address at the beginning of any function, before the
@@ -1990,16 +1928,35 @@ struct sh_args {
 /* Nonzero if access to memory by bytes is no faster than for words.  */
 #define SLOW_BYTE_ACCESS 1
 
-/* Immediate shift counts are truncated by the output routines (or was it
-   the assembler?).  Shift counts in a register are truncated by SH.  Note
-   that the native compiler puts too large (> 32) immediate shift counts
-   into a register and shifts by the register, letting the SH decide what
-   to do instead of doing that itself.  */
-/* ??? The library routines in lib1funcs.S truncate the shift count.
-   However, the SH3 has hardware shifts that do not truncate exactly as gcc
-   expects - the sign bit is significant - so it appears that we need to
-   leave this zero for correct SH3 code.  */
-#define SHIFT_COUNT_TRUNCATED (! TARGET_SH3 && ! TARGET_SH2A)
+/* Nonzero if the target supports dynamic shift instructions
+   like shad and shld.  */
+#define TARGET_DYNSHIFT (TARGET_SH3 || TARGET_SH2A)
+
+/* The cost of using the dynamic shift insns (shad, shld) are the same
+   if they are available.  If they are not available a library function will
+   be emitted instead, which is more expensive.  */
+#define SH_DYNAMIC_SHIFT_COST (TARGET_DYNSHIFT ? 1 : 20)
+
+/* Defining SHIFT_COUNT_TRUNCATED tells the combine pass that code like
+   (X << (Y % 32)) for register X, Y is equivalent to (X << Y).
+   This is not generally true when hardware dynamic shifts (shad, shld) are
+   used, because they check the sign bit _before_ the modulo op.  The sign
+   bit determines whether it is a left shift or a right shift:
+     if (Y < 0)
+       return X << (Y & 31);
+     else
+       return X >> (-Y) & 31);
+   The dynamic shift library routines in lib1funcs.S do not use the sign bit
+   like the hardware dynamic shifts and truncate the shift count to 31.
+   We define SHIFT_COUNT_TRUNCATED to 0 and express the implied shift count
+   truncation in the library function call patterns, as this gives slightly
+   more compact code.  */
+#define SHIFT_COUNT_TRUNCATED (0)
+
+/* CANONICALIZE_COMPARISON macro for the combine pass.  */
+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+  sh_canonicalize_comparison ((CODE), (OP0), (OP1))
 
 /* All integers have the same format so truncation is easy.  */
 /* But SHmedia must sign-extend DImode when truncating to SImode.  */
@@ -2375,17 +2332,10 @@ extern int current_function_interrupt;
 
 #define MAX_FIXED_MODE_SIZE (TARGET_SH5 ? 128 : 64)
 
-#define SIDI_OFF (TARGET_LITTLE_ENDIAN ? 0 : 4)
-
 /* Better to allocate once the maximum space for outgoing args in the
    prologue rather than duplicate around each call.  */
 #define ACCUMULATE_OUTGOING_ARGS TARGET_ACCUMULATE_OUTGOING_ARGS
 
-#define SH_DYNAMIC_SHIFT_COST \
-  (TARGET_HARD_SH4 ? 1 \
-   : (TARGET_SH3 || TARGET_SH2A) ? (optimize_size ? 1 : 2) : 20)
-
-
 #define NUM_MODES_FOR_MODE_SWITCHING { FP_MODE_NONE }
 
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_SH4 || TARGET_SH2A_DOUBLE)
@@ -2411,7 +2361,7 @@ extern int current_function_interrupt;
    ? get_attr_fp_mode (INSN)                                           \
    : FP_MODE_NONE)
 
-#define MODE_AFTER(MODE, INSN)                  \
+#define MODE_AFTER(ENTITY, MODE, INSN)         \
      (TARGET_HITACHI                           \
       && recog_memoized (INSN) >= 0            \
       && get_attr_fp_set (INSN) != FP_SET_NONE  \
@@ -2470,7 +2420,4 @@ extern int current_function_interrupt;
 2:\n" TEXT_SECTION_ASM_OP);
 #endif /* (defined CRT_BEGIN || defined CRT_END) && ! __SHMEDIA__ */
 
-/* FIXME: middle-end support for highpart optimizations is missing.  */
-#define high_life_started reload_in_progress
-
 #endif /* ! GCC_SH_H */