OSDN Git Service

PR target/6512, PR target/5628
[pf3gnuchains/gcc-fork.git] / gcc / config / sparc / sparc.h
index 368fd51..d70f542 100644 (file)
@@ -122,9 +122,11 @@ extern enum cmodel sparc_cmodel;
 #define TARGET_CPU_sparcv9     7       /* alias */
 #define TARGET_CPU_sparc64     7       /* alias */
 #define TARGET_CPU_ultrasparc  8
+#define TARGET_CPU_ultrasparc3 9
 
 #if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
 
 #define CPP_CPU32_DEFAULT_SPEC ""
 #define ASM_CPU32_DEFAULT_SPEC ""
@@ -141,6 +143,10 @@ extern enum cmodel sparc_cmodel;
 #define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
 #define ASM_CPU64_DEFAULT_SPEC "-Av9a"
 #endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
+#endif
 
 #else
 
@@ -230,6 +236,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 %{mcpu=sparclite86x:-D__sparclite86x__} \
 %{mcpu=v9:-D__sparc_v9__} \
 %{mcpu=ultrasparc:-D__sparc_v9__} \
+%{mcpu=ultrasparc3:-D__sparc_v9__} \
 %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
 "
 
@@ -296,6 +303,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 %{mv8plus:-Av8plus} \
 %{mcpu=v9:-Av9} \
 %{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
+%{mcpu=ultrasparc3:%{!mv8plus:-Av9b}} \
 %{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \
 "
 
@@ -358,6 +366,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
   SUBTARGET_EXTRA_SPECS
 
 #define SUBTARGET_EXTRA_SPECS
+
+/* Because libgcc can generate references back to libc (via .umul etc.) we have
+   to list libc again after the second libgcc.  */
+#define LINK_GCC_C_SEQUENCE_SPEC "%G %L %G %L"
+
 \f
 #ifdef SPARC_BI_ARCH
 #define NO_BUILTIN_PTRDIFF_TYPE
@@ -369,34 +382,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
 /* ??? This should be 32 bits for v9 but what can we do?  */
 #define WCHAR_TYPE "short unsigned int"
 #define WCHAR_TYPE_SIZE 16
-#define MAX_WCHAR_TYPE_SIZE 16
 
 /* Show we can debug even without a frame pointer.  */
 #define CAN_DEBUG_WITHOUT_FP
 
-/* To make profiling work with -f{pic,PIC}, we need to emit the profiling
-   code into the rtl.  Also, if we are profiling, we cannot eliminate
-   the frame pointer (because the return address will get smashed).  */
-
-#define OVERRIDE_OPTIONS \
-  do {                                                                 \
-    if (profile_flag || profile_arc_flag)                              \
-      {                                                                        \
-       if (flag_pic)                                                   \
-         {                                                             \
-           const char *const pic_string = (flag_pic == 1) ? "-fpic" : "-fPIC";\
-           warning ("%s and profiling conflict: disabling %s",         \
-                    pic_string, pic_string);                           \
-           flag_pic = 0;                                               \
-         }                                                             \
-       flag_omit_frame_pointer = 0;                                    \
-      }                                                                        \
-    sparc_override_options ();                                         \
-    SUBTARGET_OVERRIDE_OPTIONS;                                                \
-  } while (0)
-
-/* This is meant to be redefined in the host dependent files.  */
-#define SUBTARGET_OVERRIDE_OPTIONS
+#define OVERRIDE_OPTIONS  sparc_override_options ()
 
 /* Generate DBX debugging information.  */
 
@@ -410,11 +400,6 @@ extern int target_flags;
 #define MASK_FPU 1
 #define TARGET_FPU (target_flags & MASK_FPU)
 
-/* Nonzero if we should use function_epilogue().  Otherwise, we
-   use fast return insns, but lose some generality.  */
-#define MASK_EPILOGUE 2
-#define TARGET_EPILOGUE (target_flags & MASK_EPILOGUE)
-
 /* Nonzero if we should assume that double pointers might be unaligned.
    This can happen when linking gcc compiled code with other compilers,
    because the ABI only guarantees 4 byte alignment.  */
@@ -558,10 +543,6 @@ extern int target_flags;
     {"soft-float", -MASK_FPU,                                          \
      N_("Do not use hardware fp") },                                   \
     {"soft-float", MASK_FPU_SET,                       NULL },         \
-    {"epilogue", MASK_EPILOGUE,                                                \
-     N_("Use function_epilogue()") },                                  \
-    {"no-epilogue", -MASK_EPILOGUE,                                    \
-     N_("Do not use function_epilogue()") },                           \
     {"unaligned-doubles", MASK_UNALIGNED_DOUBLES,                      \
      N_("Assume possible double misalignment") },                      \
     {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES,                  \
@@ -630,7 +611,7 @@ extern int target_flags;
 /* MASK_APP_REGS must always be the default because that's what
    FIXED_REGISTERS is set to and -ffixed- is processed before
    CONDITIONAL_REGISTER_USAGE is called (where we process -mno-app-regs).  */
-#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_FPU)
 
 /* This is meant to be redefined in target specific files.  */
 #define SUBTARGET_SWITCHES
@@ -650,7 +631,8 @@ enum processor_type {
   PROCESSOR_SPARCLET,
   PROCESSOR_TSC701,
   PROCESSOR_V9,
-  PROCESSOR_ULTRASPARC
+  PROCESSOR_ULTRASPARC,
+  PROCESSOR_ULTRASPARC3
 };
 
 /* This is set from -m{cpu,tune}=xxx.  */
@@ -687,10 +669,6 @@ extern struct sparc_cpu_select sparc_select[];
 \f
 /* target machine storage layout */
 
-/* Define for cross-compilation to a sparc target with no TFmode from a host
-   with a different float format (e.g. VAX).  */
-#define REAL_ARITHMETIC
-
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.  */
 #define BITS_BIG_ENDIAN 1
@@ -710,19 +688,15 @@ extern struct sparc_cpu_select sparc_select[];
 #define LIBGCC2_WORDS_BIG_ENDIAN 1
 #endif
 
-/* number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
-/* Width in bits of a "word", which is the contents of a machine register.
-   Note that this is not necessarily the width of data type `int';
-   if using 16-bit ints on a 68000, this would still be 32.
-   But on a machine with 16-bit registers, this would be 16.  */
-#define BITS_PER_WORD          (TARGET_ARCH64 ? 64 : 32)
 #define MAX_BITS_PER_WORD      64
 
 /* Width of a word, in units (bytes).  */
 #define UNITS_PER_WORD         (TARGET_ARCH64 ? 8 : 4)
+#ifdef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD     UNITS_PER_WORD
+#else
 #define MIN_UNITS_PER_WORD     4
+#endif
 
 /* Now define the sizes of the C data types.  */
 
@@ -740,7 +714,7 @@ extern struct sparc_cpu_select sparc_select[];
 #if 0
 /* ??? This does not work in SunOS 4.x, so it is not enabled here.
    Instead, it is enabled in sol2.h, because it does work under Solaris.  */
-/* Define for support of TFmode long double and REAL_ARITHMETIC.
+/* Define for support of TFmode long double.
    Sparc ABI says that long double is 4 words.  */
 #define LONG_DOUBLE_TYPE_SIZE 128
 #endif
@@ -996,7 +970,7 @@ if (TARGET_ARCH64                           \
 #define CONDITIONAL_REGISTER_USAGE                             \
 do                                                             \
   {                                                            \
-    if (flag_pic)                                              \
+    if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)             \
       {                                                                \
        fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                \
        call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;            \
@@ -1151,16 +1125,6 @@ extern int sparc_mode_class[];
       || !leaf_function_p ())                          \
    : ! (leaf_function_p () && only_leaf_regs_used ()))
 
-/* C statement to store the difference between the frame pointer
-   and the stack pointer values immediately after the function prologue.
-
-   Note, we always pretend that this is a leaf function because if
-   it's not, there's no point in trying to eliminate the
-   frame pointer.  If it is a leaf function, we guessed right!  */
-#define INITIAL_FRAME_POINTER_OFFSET(VAR) \
-  ((VAR) = (TARGET_FLAT ? sparc_flat_compute_frame_size (get_frame_size ()) \
-           : compute_frame_size (get_frame_size (), 1)))
-
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
 
@@ -1171,7 +1135,7 @@ extern int sparc_mode_class[];
 /* Register which holds offset table for position-independent
    data references.  */
 
-#define PIC_OFFSET_TABLE_REGNUM 23
+#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 23 : INVALID_REGNUM)
 
 /* Pick a default value we can notice from override_options:
    !v9: Default is on.
@@ -1393,7 +1357,8 @@ extern const char leaf_reg_remap[];
    `J' is used for the range which is just zero (since that is R0).
    `K' is used for constants which can be loaded with a single sethi insn.
    `L' is used for the range of constants supported by the movcc insns.
-   `M' is used for the range of constants supported by the movrcc insns.  */
+   `M' is used for the range of constants supported by the movrcc insns.
+   `N' is like K, but for constants wider than 32 bits.  */
 
 #define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
 #define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800)
@@ -1405,15 +1370,18 @@ extern const char leaf_reg_remap[];
 #define SMALL_INT32(X) (SPARC_SIMM13_P (trunc_int_for_mode \
                                        (INTVAL (X), SImode)))
 #define SPARC_SETHI_P(X) \
-(((unsigned HOST_WIDE_INT) (X) & \
-  (TARGET_ARCH64 ? ~(unsigned HOST_WIDE_INT) 0xfffffc00 : 0x3ff)) == 0)
+  (((unsigned HOST_WIDE_INT) (X) \
+    & ((unsigned HOST_WIDE_INT) 0x3ff - GET_MODE_MASK (SImode) - 1)) == 0)
+#define SPARC_SETHI32_P(X) \
+  (SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
 
 #define CONST_OK_FOR_LETTER_P(VALUE, C)  \
   ((C) == 'I' ? SPARC_SIMM13_P (VALUE)                 \
    : (C) == 'J' ? (VALUE) == 0                         \
-   : (C) == 'K' ? SPARC_SETHI_P (VALUE)                        \
+   : (C) == 'K' ? SPARC_SETHI32_P (VALUE)              \
    : (C) == 'L' ? SPARC_SIMM11_P (VALUE)               \
    : (C) == 'M' ? SPARC_SIMM10_P (VALUE)               \
+   : (C) == 'N' ? SPARC_SETHI_P (VALUE)                        \
    : 0)
 
 /* Similar, but for floating constants, and defining letters G and H.
@@ -1455,7 +1423,10 @@ extern const char leaf_reg_remap[];
 
    We need a temporary when loading/storing a HImode/QImode value
    between memory and the FPU registers.  This can happen when combine puts
-   a paradoxical subreg in a float/fix conversion insn.  */
+   a paradoxical subreg in a float/fix conversion insn.
+
+   We need a temporary when loading/storing a DFmode value between
+   unaligned memory and the upper FPU registers.  */
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN)          \
   ((FP_REG_CLASS_P (CLASS)                                     \
@@ -1464,28 +1435,36 @@ extern const char leaf_reg_remap[];
         || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG)  \
             && true_regnum (IN) == -1)))                       \
    ? GENERAL_REGS                                              \
-   : (((TARGET_CM_MEDANY                                       \
-        && symbolic_operand ((IN), (MODE)))                    \
-       || (TARGET_CM_EMBMEDANY                                 \
-           && text_segment_operand ((IN), (MODE))))            \
-      && !flag_pic)                                            \
-     ? GENERAL_REGS                                            \
-     : NO_REGS)
+   : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode             \
+      && GET_CODE (IN) == MEM && TARGET_ARCH32                 \
+      && ! mem_min_alignment ((IN), 8))                                \
+     ? FP_REGS                                                 \
+     : (((TARGET_CM_MEDANY                                     \
+         && symbolic_operand ((IN), (MODE)))                   \
+        || (TARGET_CM_EMBMEDANY                                \
+            && text_segment_operand ((IN), (MODE))))           \
+       && !flag_pic)                                           \
+       ? GENERAL_REGS                                          \
+       : NO_REGS)
 
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN)         \
-   ((FP_REG_CLASS_P (CLASS)                                    \
+  ((FP_REG_CLASS_P (CLASS)                                     \
      && ((MODE) == HImode || (MODE) == QImode)                 \
      && (GET_CODE (IN) == MEM                                  \
          || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
              && true_regnum (IN) == -1)))                      \
-    ? GENERAL_REGS                                             \
-   : (((TARGET_CM_MEDANY                                       \
-        && symbolic_operand ((IN), (MODE)))                    \
-       || (TARGET_CM_EMBMEDANY                                 \
-           && text_segment_operand ((IN), (MODE))))            \
-      && !flag_pic)                                            \
-     ? GENERAL_REGS                                            \
-     : NO_REGS)
+   ? GENERAL_REGS                                              \
+   : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode             \
+      && GET_CODE (IN) == MEM && TARGET_ARCH32                 \
+      && ! mem_min_alignment ((IN), 8))                                \
+     ? FP_REGS                                                 \
+     : (((TARGET_CM_MEDANY                                     \
+         && symbolic_operand ((IN), (MODE)))                   \
+        || (TARGET_CM_EMBMEDANY                                \
+            && text_segment_operand ((IN), (MODE))))           \
+       && !flag_pic)                                           \
+       ? GENERAL_REGS                                          \
+       : NO_REGS)
 
 /* On SPARC it is not possible to directly move data between 
    GENERAL_REGS and FP_REGS.  */
@@ -1585,12 +1564,33 @@ extern const char leaf_reg_remap[];
 /* ??? In TARGET_FLAT mode we needn't have a hard frame pointer.  */
    
 #define ELIMINABLE_REGS \
-  {{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
+  {{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+   { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM} }
 
-#define CAN_ELIMINATE(FROM, TO) 1
+/* The way this is structured, we can't eliminate SFP in favor of SP
+   if the frame pointer is required: we want to use the SFP->HFP elimination
+   in that case.  But the test in update_eliminables doesn't know we are
+   assuming below that we only do the former elimination.  */
+#define CAN_ELIMINATE(FROM, TO) \
+  ((TO) == HARD_FRAME_POINTER_REGNUM || !FRAME_POINTER_REQUIRED)
 
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-  ((OFFSET) = SPARC_STACK_BIAS)
+  do {                                                         \
+    (OFFSET) = 0;                                              \
+    if ((TO) == STACK_POINTER_REGNUM)                          \
+      {                                                                \
+       /* Note, we always pretend that this is a leaf function \
+          because if it's not, there's no point in trying to   \
+          eliminate the frame pointer.  If it is a leaf        \
+          function, we guessed right!  */                      \
+       if (TARGET_FLAT)                                        \
+         (OFFSET) =                                            \
+           sparc_flat_compute_frame_size (get_frame_size ());  \
+       else                                                    \
+         (OFFSET) = compute_frame_size (get_frame_size (), 1); \
+      }                                                                \
+    (OFFSET) += SPARC_STACK_BIAS;                              \
+  } while (0)
 
 /* Keep the stack pointer constant throughout the function.
    This is both an optimization and a necessity: longjmp
@@ -1852,14 +1852,13 @@ do {                                                                    \
 #endif
 
 \f
-/* Output assembler code to FILE to increment profiler label # LABELNO
-   for profiling a function entry.  */
+/* Emit rtl for profiling.  */
+#define PROFILE_HOOK(LABEL)   sparc_profile_hook (LABEL)
 
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-  sparc_function_profiler(FILE, LABELNO)
+/* All the work done in PROFILE_HOOK, but still required.  */
+#define FUNCTION_PROFILER(FILE, LABELNO) do { } while (0)
 
 /* Set the name of the mcount function for the system.  */
-
 #define MCOUNT_FUNCTION "*mcount"
 \f
 /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
@@ -1923,8 +1922,25 @@ do {                                                                     \
 #define STRICT_ARGUMENT_NAMING TARGET_V9
 
 /* We do not allow sibling calls if -mflat, nor
-   we do not allow indirect calls to be optimized into sibling calls.  */
-#define FUNCTION_OK_FOR_SIBCALL(DECL) (DECL && ! TARGET_FLAT)
+   we do not allow indirect calls to be optimized into sibling calls.
+
+   Also, on sparc 32-bit we cannot emit a sibling call when the
+   current function returns a structure.  This is because the "unimp
+   after call" convention would cause the callee to return to the
+   wrong place.  The generic code already disallows cases where the
+   function being called returns a structure.
+
+   It may seem strange how this last case could occur.  Usually there
+   is code after the call which jumps to epilogue code which dumps the
+   return value into the struct return area.  That ought to invalidate
+   the sibling call right?  Well, in the c++ case we can end up passing
+   the pointer to the struct return area to a constructor (which returns
+   void) and then nothing else happens.  Such a sibling call would look
+   valid without the added check here.  */
+#define FUNCTION_OK_FOR_SIBCALL(DECL) \
+       (DECL \
+        && ! TARGET_FLAT \
+        && (TARGET_ARCH64 || ! current_function_returns_struct))
 
 /* Generate RTL to flush the register windows so as to make arbitrary frames
    available.  */
@@ -1957,7 +1973,8 @@ do {                                                                      \
    ? gen_rtx_REG (Pmode, 31)                   \
    : gen_rtx_MEM (Pmode,                       \
                  memory_address (Pmode, plus_constant (frame, \
-                                                       15 * UNITS_PER_WORD))))
+                                                       15 * UNITS_PER_WORD \
+                                                       + SPARC_STACK_BIAS))))
 
 /* Before the prologue, the return address is %o7 + 8.  OK, sometimes it's
    +12, but always using +8 is close enough for frame unwind purposes.
@@ -1984,14 +2001,27 @@ do {                                                                    \
    If assembler and linker properly support .uaword %r_disp32(foo),
    then use PC relative 32-bit relocations instead of absolute relocs
    for shared libraries.  On sparc64, use pc relative 32-bit relocs even
-   for binaries, to save memory.  */
+   for binaries, to save memory.
+
+   binutils 2.12 would emit a R_SPARC_DISP32 dynamic relocation if the
+   symbol %r_disp32() is against was not local, but .hidden.  In that
+   case, we have to use DW_EH_PE_absptr for pic personality.  */
 #ifdef HAVE_AS_SPARC_UA_PCREL
+#ifdef HAVE_AS_SPARC_UA_PCREL_HIDDEN
 #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)                      \
   (flag_pic                                                            \
    ? (GLOBAL ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4\
    : ((TARGET_ARCH64 && ! GLOBAL)                                      \
       ? (DW_EH_PE_pcrel | DW_EH_PE_sdata4)                             \
       : DW_EH_PE_absptr))
+#else
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL)                      \
+  (flag_pic                                                            \
+   ? (GLOBAL ? DW_EH_PE_absptr : (DW_EH_PE_pcrel | DW_EH_PE_sdata4))   \
+   : ((TARGET_ARCH64 && ! GLOBAL)                                      \
+      ? (DW_EH_PE_pcrel | DW_EH_PE_sdata4)                             \
+      : DW_EH_PE_absptr))
+#endif
 
 /* Emit a PC-relative relocation.  */
 #define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL)      \
@@ -2106,13 +2136,10 @@ do {                                                                    \
        be at least 8 bytes.
 
    `U' handles all pseudo registers or a hard even numbered
-       integer register, needed for ldd/std instructions.  */
+       integer register, needed for ldd/std instructions.
 
-#define EXTRA_CONSTRAINT_BASE(OP, C)   \
-   ((C) == 'Q' ? fp_sethi_p(OP)        \
-    : (C) == 'R' ? fp_mov_p(OP)        \
-    : (C) == 'S' ? fp_high_losum_p(OP) \
-    : 0)
+   'W' handles the memory operand when moving operands in/out
+       of 'e' constraint floating point registers.  */
 
 #ifndef REG_OK_STRICT
 
@@ -2127,15 +2154,14 @@ do {                                                                    \
    or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X)  REG_OK_FOR_INDEX_P (X)
 
-/* 'T', 'U' are for aligned memory loads which aren't needed for arch64.  */
+/* 'T', 'U' are for aligned memory loads which aren't needed for arch64.
+   'W' is like 'T' but is assumed true on arch64.
 
-#define EXTRA_CONSTRAINT(OP, C)                                \
-   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
-    || ((! TARGET_ARCH64 && (C) == 'T')                        \
-        ? (mem_min_alignment (OP, 8))                  \
-        : ((! TARGET_ARCH64 && (C) == 'U')             \
-            ? (register_ok_for_ldd (OP))               \
-            : 0)))
+   Remember to accept pseudo-registers for memory constraints if reload is
+   in progress.  */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+       sparc_extra_constraint_check(OP, C, 0)
 
 #else
 
@@ -2144,16 +2170,8 @@ do {                                                                     \
 /* Nonzero if X is a hard reg that can be used as a base reg.  */
 #define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
 
-#define EXTRA_CONSTRAINT(OP, C)                                \
-   (EXTRA_CONSTRAINT_BASE(OP, C)                        \
-    || ((! TARGET_ARCH64 && (C) == 'T')                        \
-        ? mem_min_alignment (OP, 8) && strict_memory_address_p (Pmode, XEXP (OP, 0)) \
-        : ((! TARGET_ARCH64 && (C) == 'U')             \
-           ? (GET_CODE (OP) == REG                     \
-              && (REGNO (OP) < FIRST_PSEUDO_REGISTER   \
-                 || reg_renumber[REGNO (OP)] >= 0)     \
-              && register_ok_for_ldd (OP))             \
-           : 0)))
+#define EXTRA_CONSTRAINT(OP, C) \
+       sparc_extra_constraint_check(OP, C, 1)
 
 #endif
 \f
@@ -2355,12 +2373,13 @@ do {                                                                    \
   /* Decompose SImode constants into hi+lo_sum.  We do have to                 \
      rerecognize what we produce, so be careful.  */                   \
   if (CONSTANT_P (X)                                                   \
-      && (MODE != TFmode || TARGET_V9)                                 \
+      && (MODE != TFmode || TARGET_ARCH64)                             \
       && GET_MODE (X) == SImode                                                \
       && GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH                        \
       && ! (flag_pic                                                   \
            && (symbolic_operand (X, Pmode)                             \
-               || pic_address_needs_scratch (X))))                     \
+               || pic_address_needs_scratch (X)))                      \
+      && sparc_cmodel <= CM_MEDLOW)                                    \
     {                                                                  \
       X = gen_rtx_LO_SUM (GET_MODE (X),                                        \
                          gen_rtx_HIGH (GET_MODE (X), X), X);           \
@@ -2382,10 +2401,10 @@ do {                                                                    \
    In the Embedded Medium/Anywhere code model, %g4 points to the data segment
    so we must not add it to function addresses.  */
 
-#define ENCODE_SECTION_INFO(DECL) \
-  do {                                                 \
-    if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL) \
-      SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
+#define ENCODE_SECTION_INFO(DECL, FIRST)                               \
+  do {                                                                 \
+    if (TARGET_CM_EMBMEDANY && TREE_CODE (DECL) == FUNCTION_DECL)      \
+      SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;                 \
   } while (0)
 \f
 /* Specify the machine mode that this machine uses
@@ -2623,7 +2642,25 @@ do {                                                                    \
   (((FP_REG_CLASS_P (CLASS1) && GENERAL_OR_I64 (CLASS2)) \
     || (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
     || (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS)         \
-   ? (sparc_cpu == PROCESSOR_ULTRASPARC ? 12 : 6) : 2)
+   ? ((sparc_cpu == PROCESSOR_ULTRASPARC \
+       || sparc_cpu == PROCESSOR_ULTRASPARC3) ? 12 : 6) : 2)
+
+/* Provide the cost of a branch.  For pre-v9 processors we use
+   a value of 3 to take into account the potential annulling of
+   the delay slot (which ends up being a bubble in the pipeline slot)
+   plus a cycle to take into consideration the instruction cache
+   effects.
+
+   On v9 and later, which have branch prediction facilities, we set
+   it to the depth of the pipeline as that is the cost of a
+   mispredicted branch.  */
+
+#define BRANCH_COST \
+       ((sparc_cpu == PROCESSOR_V9 \
+         || sparc_cpu == PROCESSOR_ULTRASPARC) \
+        ? 7 \
+         : (sparc_cpu == PROCESSOR_ULTRASPARC3 \
+            ? 9 : 3))
 
 /* Provide the costs of a rtl expression.  This is in the body of a
    switch on CODE.  The purpose for the cost of MULT is to encourage
@@ -2637,6 +2674,8 @@ do {                                                                    \
     if (sparc_cpu == PROCESSOR_ULTRASPARC)             \
       return (GET_MODE (X) == DImode ?                 \
               COSTS_N_INSNS (34) : COSTS_N_INSNS (19));        \
+    if (sparc_cpu == PROCESSOR_ULTRASPARC3)            \
+      return COSTS_N_INSNS (6);                                \
     return TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25); \
   case DIV:                                            \
   case UDIV:                                           \
@@ -2645,6 +2684,9 @@ do {                                                                    \
     if (sparc_cpu == PROCESSOR_ULTRASPARC)             \
       return (GET_MODE (X) == DImode ?                 \
               COSTS_N_INSNS (68) : COSTS_N_INSNS (37));        \
+    if (sparc_cpu == PROCESSOR_ULTRASPARC3)            \
+      return (GET_MODE (X) == DImode ?                 \
+              COSTS_N_INSNS (71) : COSTS_N_INSNS (40));        \
     return COSTS_N_INSNS (25);                         \
   /* Make FLOAT and FIX more expensive than CONST_DOUBLE,\
      so that cse will favor the latter.  */            \
@@ -2652,13 +2694,16 @@ do {                                                                    \
   case FIX:                                            \
     return 19;
 
-/* Conditional branches with empty delay slots have a length of two.  */
-#define ADJUST_INSN_LENGTH(INSN, LENGTH)                               \
-do {                                                                   \
-  if (GET_CODE (INSN) == CALL_INSN                                     \
-      || (GET_CODE (INSN) == JUMP_INSN && ! simplejump_p (insn)))      \
-    LENGTH += 1;                                                       \
-} while (0)
+#define PREFETCH_BLOCK \
+       ((sparc_cpu == PROCESSOR_ULTRASPARC \
+          || sparc_cpu == PROCESSOR_ULTRASPARC3) \
+         ? 64 : 32)
+
+#define SIMULTANEOUS_PREFETCHES \
+       ((sparc_cpu == PROCESSOR_ULTRASPARC) \
+         ? 2 \
+         : (sparc_cpu == PROCESSOR_ULTRASPARC3 \
+            ? 8 : 3))
 \f
 /* Control the assembler format that we output.  */
 
@@ -2973,8 +3018,10 @@ do {                                                                     \
 #define PREDICATE_CODES                                                        \
 {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}},          \
 {"fp_zero_operand", {CONST_DOUBLE}},                                   \
+{"fp_register_operand", {SUBREG, REG}},                                        \
 {"intreg_operand", {SUBREG, REG}},                                     \
 {"fcc_reg_operand", {REG}},                                            \
+{"fcc0_reg_operand", {REG}},                                           \
 {"icc_or_fcc_reg_operand", {REG}},                                     \
 {"restore_operand", {REG}},                                            \
 {"call_operand", {MEM}},                                               \
@@ -2992,6 +3039,7 @@ do {                                                                      \
 {"eq_or_neq", {EQ, NE}},                                               \
 {"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}},                  \
 {"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},     \
+{"noov_compare64_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},   \
 {"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}},                            \
 {"extend_op", {SIGN_EXTEND, ZERO_EXTEND}},                             \
 {"cc_arithop", {AND, IOR, XOR}},                                       \