OSDN Git Service

Fix for proprietary testcase that fails at -m5-compact
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / sh.h
index b92c747..c2f3160 100644 (file)
@@ -359,9 +359,21 @@ extern int target_flags;
   { "subtarget_link_emul_suffix", SUBTARGET_LINK_EMUL_SUFFIX },        \
   { "subtarget_link_spec", SUBTARGET_LINK_SPEC },              \
   { "subtarget_asm_endian_spec", SUBTARGET_ASM_ENDIAN_SPEC },  \
+  { "subtarget_asm_relax_spec", SUBTARGET_ASM_RELAX_SPEC },    \
+  { "subtarget_asm_isa_spec", SUBTARGET_ASM_ISA_SPEC },        \
   SUBTARGET_EXTRA_SPECS
 
-#define ASM_SPEC  "%(subtarget_asm_endian_spec) %{mrelax:-relax}"
+#if TARGET_CPU_DEFAULT & HARD_SH4_BIT
+#define SUBTARGET_ASM_RELAX_SPEC "%{!m[1235]*:-isa=sh4}"
+#else
+#define SUBTARGET_ASM_RELAX_SPEC "%{m4*:-isa=sh4}"
+#endif
+
+#define SH_ASM_SPEC \
+ "%(subtarget_asm_endian_spec) %{mrelax:-relax %(subtarget_asm_relax_spec)}\
+%(subtarget_asm_isa_spec)"
+
+#define ASM_SPEC SH_ASM_SPEC
 
 #ifndef SUBTARGET_ASM_ENDIAN_SPEC
 #if TARGET_ENDIAN_DEFAULT == LITTLE_ENDIAN_BIT
@@ -371,6 +383,8 @@ extern int target_flags;
 #endif
 #endif
 
+#define SUBTARGET_ASM_ISA_SPEC ""
+
 #define LINK_EMUL_PREFIX "sh%{ml:l}"
 
 #if TARGET_CPU_DEFAULT & SH5_BIT
@@ -456,7 +470,7 @@ do {                                                                        \
        targetm.asm_out.unaligned_op.di = NULL;                         \
     }                                                                  \
   if (TARGET_FMOVD)                                                    \
-    reg_class_from_letter['e'] = NO_REGS;                              \
+    reg_class_from_letter['e' - 'a'] = NO_REGS;                                \
                                                                        \
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)              \
     if (! VALID_REGISTER_P (regno))                                    \
@@ -489,6 +503,13 @@ do {                                                                       \
       flag_schedule_insns = 0;                                         \
     }                                                                  \
                                                                        \
+  if (align_loops == 0)                                                        \
+    align_loops =  1 << (TARGET_SH5 ? 3 : 2);                          \
+  if (align_jumps == 0)                                                        \
+    align_jumps = 1 << CACHE_LOG;                                      \
+  else if (align_jumps < (TARGET_SHMEDIA ? 4 : 2))                     \
+    align_jumps = TARGET_SHMEDIA ? 4 : 2;                              \
+                                                                       \
   /* Allocation boundary (in *bytes*) for the code of a function.      \
      SH1: 32 bit alignment is faster, because instructions are always  \
      fetched as a pair from a longword boundary.                       \
@@ -496,6 +517,20 @@ do {                                                                       \
   if (align_functions == 0)                                            \
     align_functions                                                    \
       = TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG);     \
+  /* The linker relaxation code breaks when a function contains                \
+     alignments that are larger than that at the start of a            \
+     compilation unit.  */                                             \
+  if (TARGET_RELAX)                                                    \
+    {                                                                  \
+      int min_align                                                    \
+       = align_loops > align_jumps ? align_loops : align_jumps;        \
+                                                                       \
+      /* Also take possible .long constants / mova tables int account. */\
+      if (min_align < 4)                                               \
+       min_align = 4;                                                  \
+      if (align_functions < min_align)                                 \
+       align_functions = min_align;                                    \
+    }                                                                  \
 } while (0)
 \f
 /* Target machine storage layout.  */
@@ -902,10 +937,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
 
 #define HARD_REGNO_NREGS(REGNO, MODE) \
    (XD_REGISTER_P (REGNO) \
-    ? (GET_MODE_SIZE (MODE) / (2 * UNITS_PER_WORD)) \
+    ? ((GET_MODE_SIZE (MODE) + (2*UNITS_PER_WORD - 1)) / (2*UNITS_PER_WORD)) \
     : (TARGET_SHMEDIA && FP_REGISTER_P (REGNO)) \
     ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
-    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) \
+    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    We can allow any mode in any general register.  The special registers
@@ -1360,8 +1395,9 @@ extern enum reg_class reg_class_from_letter[];
    ? R0_REGS                                                           \
    : (CLASS == FPUL_REGS                                               \
       && ((GET_CODE (X) == REG                                         \
-          && (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG           \
-             || REGNO (X) == T_REG))))                                 \
+          && (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))             \
    ? (GET_CODE (X) == CONST_INT && CONST_OK_FOR_I (INTVAL (X))         \
@@ -1382,17 +1418,21 @@ extern enum reg_class reg_class_from_letter[];
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
 
-   On SH this is the size of MODE in words.  */
+   If TARGET_SHMEDIA, we need two FP registers per word.
+   Otherwise we will need at most one register per word.  */
 #define CLASS_MAX_NREGS(CLASS, MODE) \
-     ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+    (TARGET_SHMEDIA \
+     && TEST_HARD_REG_BIT (reg_class_contents[CLASS], FIRST_FP_REG) \
+     ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2) \
+     : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
 
 /* If defined, gives a class of registers that cannot be used as the
    operand of a SUBREG that changes the mode of the object illegally.  */
 /* ??? We need to renumber the internal numbers for the frnn registers
    when in little endian in order to allow mode size changes.  */
 
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO)                         \
-  sh_cannot_change_mode_class (FROM, TO)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)                          \
+  sh_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -2690,70 +2730,6 @@ while (0)
 #define Pmode  (TARGET_SHMEDIA64 ? DImode : SImode)
 #define FUNCTION_MODE  Pmode
 
-/* The relative costs of various types of constants.  */
-
-#define CONST_COSTS(RTX, CODE, OUTER_CODE)     \
-  case CONST_INT:                              \
-    if (TARGET_SHMEDIA)                                \
-      {                                                \
-       if (INTVAL (RTX) == 0)                  \
-         return 0;                             \
-       if ((OUTER_CODE) == AND && and_operand ((RTX), DImode)) \
-         return 0;                             \
-       if (((OUTER_CODE) == IOR || (OUTER_CODE) == XOR \
-            || (OUTER_CODE) == PLUS) \
-           && CONST_OK_FOR_P (INTVAL (RTX)))   \
-         return 0;                             \
-       if (CONST_OK_FOR_J (INTVAL (RTX)))      \
-          return COSTS_N_INSNS ((OUTER_CODE) != SET);          \
-       else if (CONST_OK_FOR_J (INTVAL (RTX) >> 16)) \
-         return COSTS_N_INSNS (2);             \
-       else if (CONST_OK_FOR_J ((INTVAL (RTX) >> 16) >> 16)) \
-         return COSTS_N_INSNS (3);             \
-        else                                   \
-         return COSTS_N_INSNS (4);             \
-      }                                                \
-    if (CONST_OK_FOR_I (INTVAL (RTX)))         \
-      return 0;                                        \
-    else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
-            && CONST_OK_FOR_L (INTVAL (RTX)))  \
-      return 1;                                        \
-    else                                       \
-      return 8;                                        \
-  case CONST:                                  \
-  case LABEL_REF:                              \
-  case SYMBOL_REF:                             \
-    if (TARGET_SHMEDIA64)                      \
-      return COSTS_N_INSNS (4);                        \
-    if (TARGET_SHMEDIA32)                      \
-      return COSTS_N_INSNS (2);                        \
-    return 5;                                  \
-  case CONST_DOUBLE:                           \
-    if (TARGET_SHMEDIA)                                \
-      return COSTS_N_INSNS (4);                        \
-    else                                       \
-      return 10;
-
-#define RTX_COSTS(X, CODE, OUTER_CODE)                 \
-  case PLUS:                                           \
-    return COSTS_N_INSNS (addsubcosts (X));            \
-  case AND:                                            \
-    return COSTS_N_INSNS (andcosts (X));               \
-  case MULT:                                           \
-    return COSTS_N_INSNS (multcosts (X));              \
-  case ASHIFT:                                         \
-  case ASHIFTRT:                                       \
-  case LSHIFTRT:                                       \
-    return COSTS_N_INSNS (shiftcosts (X));             \
-  case DIV:                                            \
-  case UDIV:                                           \
-  case MOD:                                            \
-  case UMOD:                                           \
-    return COSTS_N_INSNS (20);                         \
-  case FLOAT:                                          \
-  case FIX:                                            \
-    return 100;
-
 /* The multiply insn on the SH1 and the divide insns on the SH1 and SH2
    are actually function calls with some special constraints on arguments
    and register usage.
@@ -2812,14 +2788,20 @@ while (0)
 ((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF)     \
   && nonpic_symbol_mentioned_p (X))
 \f
-/* Compute the cost of an address.  For the SH, all valid addresses are
-   the same cost.  Use a slightly higher cost for reg + reg addressing,
-   since it increases pressure on r0.  */
+/* TLS.  */
+
+/* The prefix used to mark SYMBOL_REFs that refer to TLS symbols.  */
+#define SH_TLS_ENCODING "@"
 
-#define ADDRESS_COST(X) (GET_CODE (X) == PLUS && ! CONSTANT_P (XEXP (X, 1)) \
-                        && ! TARGET_SHMEDIA \
-                        ? 1 : 0)
+/* Return true if SYM_NAME starts with SH_TLS_ENCODING.  */
+#define TLS_SYMNAME_P(SYM_NAME) \
+  ((SYM_NAME)[0] == SH_TLS_ENCODING[0])
 
+/* Skip an optional SH_TLS_ENCODING in the beginning of SYM_NAME.  */
+#define STRIP_TLS_ENCODING(VAR, SYM_NAME) \
+  (VAR) = (SYM_NAME) + (TLS_SYMNAME_P (SYM_NAME) \
+                       ? strlen (SH_TLS_ENCODING) + 1 : 0)
+\f
 /* Compute extra cost of moving data between one register class
    and another.  */
 
@@ -2983,6 +2965,7 @@ while (0)
       const char * lname;                              \
                                                        \
       STRIP_DATALABEL_ENCODING (lname, (NAME));                \
+      STRIP_TLS_ENCODING (lname, lname);               \
       if (lname[0] == '*')                             \
        fputs (lname + 1, (FILE));                      \
       else                                             \
@@ -3121,6 +3104,18 @@ while (0)
            output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
            fputs ("@GOTPLT", (STREAM));                                \
            break;                                                      \
+         case UNSPEC_DTPOFF:                                           \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@DTPOFF", (STREAM));                                \
+           break;                                                      \
+         case UNSPEC_GOTTPOFF:                                         \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@GOTTPOFF", (STREAM));                              \
+           break;                                                      \
+         case UNSPEC_TPOFF:                                            \
+           output_addr_const ((STREAM), XVECEXP ((X), 0, 0));          \
+           fputs ("@TPOFF", (STREAM));                                 \
+           break;                                                      \
          case UNSPEC_CALLER:                                           \
            {                                                           \
              char name[32];                                            \