aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc/sparc.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sparc/sparc.h')
-rw-r--r--gcc/config/sparc/sparc.h259
1 files changed, 150 insertions, 109 deletions
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 779a39c988e..3f2157810b6 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -358,6 +358,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"
+
#ifdef SPARC_BI_ARCH
#define NO_BUILTIN_PTRDIFF_TYPE
@@ -369,34 +374,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 +392,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 +535,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 +603,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
@@ -722,7 +695,11 @@ extern struct sparc_cpu_select sparc_select[];
/* 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. */
@@ -996,7 +973,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; \
@@ -1040,12 +1017,16 @@ do \
fixed_regs[4] = 0; \
if (TARGET_FLAT) \
{ \
+ int regno; \
/* Let the compiler believe the frame pointer is still \
%fp, but output it as %i7. */ \
fixed_regs[31] = 1; \
reg_names[HARD_FRAME_POINTER_REGNUM] = "%i7"; \
/* Disable leaf functions */ \
memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER); \
+ /* Make LEAF_REG_REMAP a noop. */ \
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
+ leaf_reg_remap [regno] = regno; \
} \
} \
while (0)
@@ -1151,16 +1132,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 +1142,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.
@@ -1352,7 +1323,7 @@ extern enum reg_class sparc_regno_reg_class[FIRST_PSEUDO_REGISTER];
extern char sparc_leaf_regs[];
#define LEAF_REGISTERS sparc_leaf_regs
-extern const char leaf_reg_remap[];
+extern char leaf_reg_remap[];
#define LEAF_REG_REMAP(REGNO) (leaf_reg_remap[REGNO])
/* The class value for index registers, and the one for base regs. */
@@ -1459,7 +1430,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) \
@@ -1468,28 +1442,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. */
@@ -1589,12 +1571,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
@@ -1856,14 +1859,13 @@ do { \
#endif
-/* 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"
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
@@ -1927,8 +1929,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. */
@@ -1961,7 +1980,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.
@@ -1988,14 +2008,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) \
@@ -2110,13 +2143,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
@@ -2131,15 +2161,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.
+
+ Remember to accept pseudo-registers for memory constraints if reload is
+ in progress. */
-#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)))
+#define EXTRA_CONSTRAINT(OP, C) \
+ sparc_extra_constraint_check(OP, C, 0)
#else
@@ -2148,16 +2177,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
@@ -2359,12 +2380,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); \
@@ -2629,6 +2651,23 @@ do { \
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
? (sparc_cpu == PROCESSOR_ULTRASPARC ? 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.
+
+ ??? Set to 9 when PROCESSOR_ULTRASPARC3 is added */
+
+#define BRANCH_COST \
+ ((sparc_cpu == PROCESSOR_V9 \
+ || sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ? 7 : 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
`synth_mult' to find a synthetic multiply when reasonable.
@@ -2656,13 +2695,12 @@ 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) ? 64 : 32)
+
+/* ??? UltraSPARC-III note: Can set this to 8 for ultra3. */
+#define SIMULTANEOUS_PREFETCHES \
+ ((sparc_cpu == PROCESSOR_ULTRASPARC) ? 2 : 3)
/* Control the assembler format that we output. */
@@ -2977,8 +3015,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}}, \
@@ -2996,6 +3036,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}}, \