/* Definitions of target machine for GNU compiler for Renesas / SuperH SH.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
builtin_define ("__SH_FPU_DOUBLE__"); \
if (TARGET_HITACHI) \
builtin_define ("__HITACHI__"); \
+ if (TARGET_FMOVD) \
+ builtin_define ("__FMOVD_ENABLED__"); \
builtin_define (TARGET_LITTLE_ENDIAN \
? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
} while (0)
-/* We can not debug without a frame pointer. */
-/* #define CAN_DEBUG_WITHOUT_FP */
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms may be accessed
+ via the stack pointer) in functions that seem suitable. */
+
+#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
+#define SUBTARGET_FRAME_POINTER_REQUIRED 0
+#endif
#define CONDITIONAL_REGISTER_USAGE do \
{ \
#endif
#define DRIVER_SELF_SPECS "%{m2a:%{ml:%eSH2a does not support little-endian}}"
-#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \
-do { \
- if (LEVEL) \
- { \
- flag_omit_frame_pointer = 2; \
- if (! SIZE) \
- sh_div_str = "inv:minlat"; \
- } \
- if (SIZE) \
- { \
- target_flags |= MASK_SMALLCODE; \
- sh_div_str = SH_DIV_STR_FOR_SIZE ; \
- } \
- else \
- { \
- TARGET_CBRANCHDI4 = 1; \
- TARGET_EXPAND_CBRANCHDI4 = 1; \
- } \
- /* We can't meaningfully test TARGET_SHMEDIA here, because -m options \
- haven't been parsed yet, hence we'd read only the default. \
- sh_target_reg_class will return NO_REGS if this is not SHMEDIA, so \
- it's OK to always set flag_branch_target_load_optimize. */ \
- if (LEVEL > 1) \
- { \
- flag_branch_target_load_optimize = 1; \
- if (! (SIZE)) \
- target_flags |= MASK_SAVE_ALL_TARGET_REGS; \
- } \
- /* Likewise, we can't meaningfully test TARGET_SH2E / TARGET_IEEE \
- here, so leave it to OVERRIDE_OPTIONS to set \
- flag_finite_math_only. We set it to 2 here so we know if the user \
- explicitly requested this to be on or off. */ \
- flag_finite_math_only = 2; \
- /* If flag_schedule_insns is 1, we set it to 2 here so we know if \
- the user explicitly requested this to be on or off. */ \
- if (flag_schedule_insns > 0) \
- flag_schedule_insns = 2; \
- \
- set_param_value ("simultaneous-prefetches", 2); \
-} while (0)
#define ASSEMBLER_DIALECT assembler_dialect
#define SUBTARGET_OVERRIDE_OPTIONS (void) 0
-extern const char *sh_fixed_range_str;
-
-#define OVERRIDE_OPTIONS \
-do { \
- int regno; \
- \
- SUBTARGET_OVERRIDE_OPTIONS; \
- if (flag_finite_math_only == 2) \
- flag_finite_math_only \
- = !flag_signaling_nans && TARGET_SH2E && ! TARGET_IEEE; \
- if (TARGET_SH2E && !flag_finite_math_only) \
- target_flags |= MASK_IEEE; \
- sh_cpu = CPU_SH1; \
- assembler_dialect = 0; \
- if (TARGET_SH2) \
- sh_cpu = CPU_SH2; \
- if (TARGET_SH2E) \
- sh_cpu = CPU_SH2E; \
- if (TARGET_SH2A) \
- { \
- sh_cpu = CPU_SH2A; \
- if (TARGET_SH2A_DOUBLE) \
- target_flags |= MASK_FMOVD; \
- } \
- if (TARGET_SH3) \
- sh_cpu = CPU_SH3; \
- if (TARGET_SH3E) \
- sh_cpu = CPU_SH3E; \
- if (TARGET_SH4) \
- { \
- assembler_dialect = 1; \
- sh_cpu = CPU_SH4; \
- } \
- if (TARGET_SH4A_ARCH) \
- { \
- assembler_dialect = 1; \
- sh_cpu = CPU_SH4A; \
- } \
- if (TARGET_SH5) \
- { \
- sh_cpu = CPU_SH5; \
- target_flags |= MASK_ALIGN_DOUBLE; \
- if (TARGET_SHMEDIA_FPU) \
- target_flags |= MASK_FMOVD; \
- if (TARGET_SHMEDIA) \
- { \
- /* There are no delay slots on SHmedia. */ \
- flag_delayed_branch = 0; \
- /* Relaxation isn't yet supported for SHmedia */ \
- target_flags &= ~MASK_RELAX; \
- /* After reload, if conversion does little good but can cause \
- ICEs: \
- - find_if_block doesn't do anything for SH because we don't\
- have conditional execution patterns. (We use conditional\
- move patterns, which are handled differently, and only \
- before reload). \
- - find_cond_trap doesn't do anything for the SH because we \
- don't have conditional traps. \
- - find_if_case_1 uses redirect_edge_and_branch_force in \
- the only path that does an optimization, and this causes \
- an ICE when branch targets are in registers. \
- - find_if_case_2 doesn't do anything for the SHmedia after \
- reload except when it can redirect a tablejump - and \
- that's rather rare. */ \
- flag_if_conversion2 = 0; \
- if (! strcmp (sh_div_str, "call")) \
- sh_div_strategy = SH_DIV_CALL; \
- else if (! strcmp (sh_div_str, "call2")) \
- sh_div_strategy = SH_DIV_CALL2; \
- if (! strcmp (sh_div_str, "fp") && TARGET_FPU_ANY) \
- sh_div_strategy = SH_DIV_FP; \
- else if (! strcmp (sh_div_str, "inv")) \
- sh_div_strategy = SH_DIV_INV; \
- else if (! strcmp (sh_div_str, "inv:minlat")) \
- sh_div_strategy = SH_DIV_INV_MINLAT; \
- else if (! strcmp (sh_div_str, "inv20u")) \
- sh_div_strategy = SH_DIV_INV20U; \
- else if (! strcmp (sh_div_str, "inv20l")) \
- sh_div_strategy = SH_DIV_INV20L; \
- else if (! strcmp (sh_div_str, "inv:call2")) \
- sh_div_strategy = SH_DIV_INV_CALL2; \
- else if (! strcmp (sh_div_str, "inv:call")) \
- sh_div_strategy = SH_DIV_INV_CALL; \
- else if (! strcmp (sh_div_str, "inv:fp")) \
- { \
- if (TARGET_FPU_ANY) \
- sh_div_strategy = SH_DIV_INV_FP; \
- else \
- sh_div_strategy = SH_DIV_INV; \
- } \
- TARGET_CBRANCHDI4 = 0; \
- } \
- } \
- else \
- { \
- /* Only the sh64-elf assembler fully supports .quad properly. */\
- targetm.asm_out.aligned_op.di = NULL; \
- targetm.asm_out.unaligned_op.di = NULL; \
- } \
- if (TARGET_SH1) \
- { \
- if (! strcmp (sh_div_str, "call-div1")) \
- sh_div_strategy = SH_DIV_CALL_DIV1; \
- else if (! strcmp (sh_div_str, "call-fp") \
- && (TARGET_FPU_DOUBLE \
- || (TARGET_HARD_SH4 && TARGET_SH2E) \
- || (TARGET_SHCOMPACT && TARGET_FPU_ANY))) \
- sh_div_strategy = SH_DIV_CALL_FP; \
- else if (! strcmp (sh_div_str, "call-table") && TARGET_SH2) \
- sh_div_strategy = SH_DIV_CALL_TABLE; \
- else \
- /* Pick one that makes most sense for the target in general. \
- It is not much good to use different functions depending \
- on -Os, since then we'll end up with two different functions \
- when some of the code is compiled for size, and some for \
- speed. */ \
- \
- /* SH4 tends to emphasize speed. */ \
- if (TARGET_HARD_SH4) \
- sh_div_strategy = SH_DIV_CALL_TABLE; \
- /* These have their own way of doing things. */ \
- else if (TARGET_SH2A) \
- sh_div_strategy = SH_DIV_INTRINSIC; \
- /* ??? Should we use the integer SHmedia function instead? */ \
- else if (TARGET_SHCOMPACT && TARGET_FPU_ANY) \
- sh_div_strategy = SH_DIV_CALL_FP; \
- /* SH1 .. SH3 cores often go into small-footprint systems, so \
- default to the smallest implementation available. */ \
- else if (TARGET_SH2) /* ??? EXPERIMENTAL */ \
- sh_div_strategy = SH_DIV_CALL_TABLE; \
- else \
- sh_div_strategy = SH_DIV_CALL_DIV1; \
- } \
- if (!TARGET_SH1) \
- TARGET_PRETEND_CMOVE = 0; \
- if (sh_divsi3_libfunc[0]) \
- ; /* User supplied - leave it alone. */ \
- else if (TARGET_DIVIDE_CALL_FP) \
- sh_divsi3_libfunc = "__sdivsi3_i4"; \
- else if (TARGET_DIVIDE_CALL_TABLE) \
- sh_divsi3_libfunc = "__sdivsi3_i4i"; \
- else if (TARGET_SH5) \
- sh_divsi3_libfunc = "__sdivsi3_1"; \
- else \
- sh_divsi3_libfunc = "__sdivsi3"; \
- if (sh_branch_cost == -1) \
- sh_branch_cost \
- = TARGET_SH5 ? 1 : ! TARGET_SH2 || TARGET_HARD_SH4 ? 2 : 1; \
- \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (! VALID_REGISTER_P (regno)) \
- sh_register_names[regno][0] = '\0'; \
- \
- for (regno = 0; regno < ADDREGNAMES_SIZE; regno++) \
- if (! VALID_REGISTER_P (ADDREGNAMES_REGNO (regno))) \
- sh_additional_register_names[regno][0] = '\0'; \
- \
- if (flag_omit_frame_pointer == 2) \
- { \
- /* The debugging information is sufficient, \
- but gdb doesn't implement this yet */ \
- if (0) \
- flag_omit_frame_pointer \
- = (PREFERRED_DEBUGGING_TYPE == DWARF2_DEBUG); \
- else \
- flag_omit_frame_pointer = 0; \
- } \
- \
- if ((flag_pic && ! TARGET_PREFERGOT) \
- || (TARGET_SHMEDIA && !TARGET_PT_FIXED)) \
- flag_no_function_cse = 1; \
- \
- if (SMALL_REGISTER_CLASSES) \
- { \
- /* Never run scheduling before reload, since that can \
- break global alloc, and generates slower code anyway due \
- to the pressure on R0. */ \
- /* Enable sched1 for SH4; ready queue will be reordered by \
- the target hooks when pressure is high. We can not do this for \
- PIC, SH3 and lower as they give spill failures for R0. */ \
- if (!TARGET_HARD_SH4 || flag_pic) \
- flag_schedule_insns = 0; \
- /* ??? Current exception handling places basic block boundaries \
- after call_insns. It causes the high pressure on R0 and gives \
- spill failures for R0 in reload. See PR 22553 and the thread \
- on gcc-patches \
- <http://gcc.gnu.org/ml/gcc-patches/2005-10/msg00816.html>. */ \
- else if (flag_exceptions) \
- { \
- if (flag_schedule_insns == 1) \
- warning (0, "ignoring -fschedule-insns because of exception handling bug"); \
- 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. \
- SH2 .. SH5 : align to cache line start. */ \
- 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; \
- } \
- \
- if (sh_fixed_range_str) \
- sh_fix_range (sh_fixed_range_str); \
-} while (0)
\f
/* Target machine storage layout. */
numbered. */
#define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
-/* Define this to set the endianness to use in libgcc2.c, which can
- not depend on target_flags. */
-#if defined(__LITTLE_ENDIAN__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#endif
-
#define MAX_BITS_PER_WORD 64
/* Width in bits of an `int'. We want just 32-bits, even if words are
barrier_align (LABEL_AFTER_BARRIER)
#define LOOP_ALIGN(A_LABEL) \
- ((! optimize || TARGET_HARD_SH4 || TARGET_SMALLCODE) \
+ ((! optimize || TARGET_HARD_SH4 || optimize_size) \
? 0 : sh_loop_align (A_LABEL))
#define LABEL_ALIGN(A_LABEL) \
( \
(PREV_INSN (A_LABEL) \
- && GET_CODE (PREV_INSN (A_LABEL)) == INSN \
+ && NONJUMP_INSN_P (PREV_INSN (A_LABEL)) \
&& GET_CODE (PATTERN (PREV_INSN (A_LABEL))) == UNSPEC_VOLATILE \
&& XINT (PATTERN (PREV_INSN (A_LABEL)), 1) == UNSPECV_ALIGN) \
/* explicit alignment insn in constant tables. */ \
/* The base two logarithm of the known minimum alignment of an insn length. */
#define INSN_LENGTH_ALIGNMENT(A_INSN) \
- (GET_CODE (A_INSN) == INSN \
+ (NONJUMP_INSN_P (A_INSN) \
? 1 << TARGET_SHMEDIA \
- : GET_CODE (A_INSN) == JUMP_INSN || GET_CODE (A_INSN) == CALL_INSN \
+ : JUMP_P (A_INSN) || CALL_P (A_INSN) \
? 1 << TARGET_SHMEDIA \
: CACHE_LOG)
\f
? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD/2 - 1) / (UNITS_PER_WORD/2)) \
: ((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
- only allow SImode. Don't allow any mode in the PR. */
-
-/* We cannot hold DCmode values in the XD registers because alter_reg
- handles subregs of them incorrectly. We could work around this by
- spacing the XD registers like the DR registers, but this would require
- additional memory in every compilation to hold larger register vectors.
- We could hold SFmode / SCmode values in XD registers, but that
- would require a tertiary reload when reloading from / to memory,
- and a secondary reload to reload from / to general regs; that
- seems to be a loosing proposition. */
-/* We want to allow TImode FP regs so that when V4SFmode is loaded as TImode,
- it won't be ferried through GP registers first. */
+/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE. */
+
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (SPECIAL_REGISTER_P (REGNO) ? (MODE) == SImode \
- : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode \
- : FP_REGISTER_P (REGNO) && (MODE) == SFmode \
- ? 1 \
- : (MODE) == V2SFmode \
- ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 2 == 0) \
- || GENERAL_REGISTER_P (REGNO)) \
- : (MODE) == V4SFmode \
- ? ((FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 4 == 0) \
- || GENERAL_REGISTER_P (REGNO)) \
- : (MODE) == V16SFmode \
- ? (TARGET_SHMEDIA \
- ? (FP_REGISTER_P (REGNO) && ((REGNO) - FIRST_FP_REG) % 16 == 0) \
- : (REGNO) == FIRST_XD_REG) \
- : FP_REGISTER_P (REGNO) \
- ? ((MODE) == SFmode || (MODE) == SImode \
- || ((TARGET_SH2E || TARGET_SHMEDIA) && (MODE) == SCmode) \
- || ((((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode) || (MODE) == DCmode \
- || (TARGET_SHMEDIA && ((MODE) == DFmode || (MODE) == DImode \
- || (MODE) == V2SFmode || (MODE) == TImode))) \
- && (((REGNO) - FIRST_FP_REG) & 1) == 0) \
- || ((TARGET_SH4 || TARGET_SHMEDIA) \
- && (MODE) == TImode \
- && (((REGNO) - FIRST_FP_REG) & 3) == 0)) \
- : XD_REGISTER_P (REGNO) \
- ? (MODE) == DFmode \
- : TARGET_REGISTER_P (REGNO) \
- ? ((MODE) == DImode || (MODE) == SImode || (MODE) == PDImode) \
- : (REGNO) == PR_REG ? (MODE) == SImode \
- : (REGNO) == FPSCR_REG ? (MODE) == PSImode \
- : 1)
+ sh_hard_regno_mode_ok ((REGNO), (MODE))
/* Value is 1 if it is a good idea to tie two pseudo registers
when one has mode MODE1 and one has mode MODE2.
#define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
-/* Value should be nonzero if functions must have frame pointers.
- Zero means the frame pointer need not be set up (and parms may be accessed
- via the stack pointer) in functions that seem suitable. */
-
-#define FRAME_POINTER_REQUIRED 0
-
/* Definitions for register eliminations.
We have three registers that can be eliminated on the SH. First, the
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},}
-/* Given FROM and TO register numbers, say whether this elimination
- is allowed. */
-#define CAN_ELIMINATE(FROM, TO) \
- (!((FROM) == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED))
-
/* Define the offset between two registers, one to be eliminated, and the other
its replacement, at the start of a routine. */
FPUL_REGS, LIM_REG_CLASSES \
}
-/* When defined, the compiler allows registers explicitly used in the
- rtl to be used as spill registers but prevents the compiler from
- extending the lifetime of these registers. */
-
-#define SMALL_REGISTER_CLASSES (! TARGET_SHMEDIA)
+/* When this hook returns true for MODE, the compiler allows
+ registers explicitly used in the rtl to be used as spill registers
+ but prevents the compiler from extending the lifetime of these
+ registers. */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P \
+ sh_small_register_classes_for_mode_p
/* The order in which register should be allocated. */
/* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo,
((CLASS) == NO_REGS && TARGET_SHMEDIA \
&& (GET_CODE (X) == CONST_DOUBLE \
|| GET_CODE (X) == SYMBOL_REF \
- || PIC_DIRECT_ADDR_P (X)) \
+ || PIC_ADDR_P (X)) \
? GENERAL_REGS \
: (CLASS)) \
#if 0
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((REGCLASS_HAS_FP_REG (CLASS) \
- && (GET_CODE (X) == REG \
+ && (REG_P (X) \
&& (GENERAL_OR_AP_REGISTER_P (REGNO (X)) \
|| (FP_REGISTER_P (REGNO (X)) && (MODE) == SImode \
&& TARGET_FMOVD)))) \
|| (REGCLASS_HAS_GENERAL_REG (CLASS) \
- && GET_CODE (X) == REG \
+ && REG_P (X) \
&& FP_REGISTER_P (REGNO (X)))) \
&& ! TARGET_SHMEDIA \
&& ((MODE) == SFmode || (MODE) == SImode)) \
: (((CLASS) == FPUL_REGS \
|| (REGCLASS_HAS_FP_REG (CLASS) \
&& ! TARGET_SHMEDIA && MODE == SImode)) \
- && (GET_CODE (X) == MEM \
- || (GET_CODE (X) == REG \
+ && (MEM_P (X) \
+ || (REG_P (X) \
&& (REGNO (X) >= FIRST_PSEUDO_REGISTER \
|| REGNO (X) == T_REG \
|| system_reg_operand (X, VOIDmode))))) \
: (((CLASS) == TARGET_REGS \
|| (TARGET_SHMEDIA && (CLASS) == SIBCALL_REGS)) \
&& !satisfies_constraint_Csy (X) \
- && (GET_CODE (X) != REG || ! GENERAL_REGISTER_P (REGNO (X)))) \
+ && (!REG_P (X) || ! GENERAL_REGISTER_P (REGNO (X)))) \
? GENERAL_REGS \
: (((CLASS) == MAC_REGS || (CLASS) == PR_REGS) \
- && GET_CODE (X) == REG && ! GENERAL_REGISTER_P (REGNO (X)) \
+ && REG_P (X) && ! GENERAL_REGISTER_P (REGNO (X)) \
&& (CLASS) != REGNO_REG_CLASS (REGNO (X))) \
? GENERAL_REGS \
- : ((CLASS) != GENERAL_REGS && GET_CODE (X) == REG \
+ : ((CLASS) != GENERAL_REGS && REG_P (X) \
&& TARGET_REGISTER_P (REGNO (X))) \
? GENERAL_REGS : (ELSE))
&& (MODE) == SFmode && fldi_ok ())) \
? R0_REGS \
: ((CLASS) == FPUL_REGS \
- && ((GET_CODE (X) == REG \
+ && ((REG_P (X) \
&& (REGNO (X) == MACL_REG || REGNO (X) == MACH_REG \
|| REGNO (X) == T_REG)) \
|| GET_CODE (X) == PLUS)) \
? GENERAL_REGS \
: R0_REGS) \
: ((CLASS) == FPSCR_REGS \
- && ((GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER) \
- || (GET_CODE (X) == MEM && GET_CODE (XEXP ((X), 0)) == PLUS)))\
+ && ((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 \
&& TARGET_SHMEDIA && inqhi_operand ((X), (MODE))) \
? GENERAL_REGS \
: (TARGET_SHMEDIA && (CLASS) == GENERAL_REGS \
- && (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X))) \
+ && (GET_CODE (X) == LABEL_REF || PIC_ADDR_P (X))) \
? TARGET_REGS \
: SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
#endif
/* Offset of first parameter from the argument pointer register value. */
#define FIRST_PARM_OFFSET(FNDECL) 0
-/* Value is the number of byte of arguments automatically
- popped when returning from a subroutine call.
- FUNDECL is the declaration node of the function (as a tree),
- FUNTYPE is the data type of the function (as a tree),
- or for a library call it is an identifier node for the subroutine name.
- SIZE is the number of bytes of arguments passed on the stack.
-
- On the SH, the caller does not pop any of its arguments that were passed
- on the stack. */
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
/* Value is the number of bytes of arguments automatically popped when
calling a subroutine.
CUM is the accumulated argument list.
? FIRST_FP_PARM_REG \
: FIRST_PARM_REG)
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0.
- For the SH, this is like LIBCALL_VALUE, except that we must change the
- mode like PROMOTE_MODE does.
- ??? PROMOTE_MODE is ignored for non-scalar types. The set of types
- tested here has to be kept in sync with the one in explow.c:promote_mode. */
-
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx_REG ( \
- ((GET_MODE_CLASS (TYPE_MODE (VALTYPE)) == MODE_INT \
- && GET_MODE_SIZE (TYPE_MODE (VALTYPE)) < 4 \
- && (TREE_CODE (VALTYPE) == INTEGER_TYPE \
- || TREE_CODE (VALTYPE) == ENUMERAL_TYPE \
- || TREE_CODE (VALTYPE) == BOOLEAN_TYPE \
- || TREE_CODE (VALTYPE) == REAL_TYPE \
- || TREE_CODE (VALTYPE) == OFFSET_TYPE)) \
- && sh_promote_prototypes (VALTYPE) \
- ? (TARGET_SHMEDIA64 ? DImode : SImode) : TYPE_MODE (VALTYPE)), \
- BASE_RETURN_VALUE_REG (TYPE_MODE (VALTYPE)))
-
-/* Define how to find the value returned by a library function
- assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) \
- gen_rtx_REG ((MODE), BASE_RETURN_VALUE_REG (MODE));
-
-/* 1 if N is a possible register number for a function value. */
-#define FUNCTION_VALUE_REGNO_P(REGNO) \
- ((REGNO) == FIRST_RET_REG || (TARGET_SH2E && (REGNO) == FIRST_FP_RET_REG) \
- || (TARGET_SHMEDIA_FPU && (REGNO) == FIRST_FP_RET_REG))
-
/* 1 if N is a possible register number for function argument passing. */
/* ??? There are some callers that pass REGNO as int, and others that pass
it as unsigned. We get warnings unless we do casts everywhere. */
#define INIT_CUMULATIVE_LIBCALL_ARGS(CUM, MODE, LIBNAME) \
sh_init_cumulative_args (& (CUM), NULL_TREE, (LIBNAME), NULL_TREE, 0, (MODE))
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- sh_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- sh_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
-
/* Return boolean indicating arg of mode MODE will be passed in a reg.
This macro is only used in this file. */
#define PASS_IN_REG_P(CUM, MODE, TYPE) \
(((TYPE) == 0 \
- || (! TREE_ADDRESSABLE ((tree)(TYPE)) \
+ || (! TREE_ADDRESSABLE ((TYPE)) \
&& (! (TARGET_HITACHI || (CUM).renesas_abi) \
|| ! (AGGREGATE_TYPE_P (TYPE) \
|| (!TARGET_FPU_ANY \
/* Alignment required for a trampoline in bits . */
#define TRAMPOLINE_ALIGNMENT \
- ((CACHE_LOG < 3 || (TARGET_SMALLCODE && ! TARGET_HARVARD)) ? 32 \
+ ((CACHE_LOG < 3 || (optimize_size && ! TARGET_HARVARD)) ? 32 \
: TARGET_SHMEDIA ? 256 : 64)
-/* Emit RTL insns to initialize the variable parts of a trampoline.
- FNADDR is an RTX for the address of the function's pure code.
- CXT is an RTX for the static chain value for the function. */
-
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
- sh_initialize_trampoline ((TRAMP), (FNADDR), (CXT))
-
-/* On SH5, trampolines are SHmedia code, so add 1 to the address. */
-
-#define TRAMPOLINE_ADJUST_ADDRESS(TRAMP) do \
-{ \
- if (TARGET_SHMEDIA) \
- (TRAMP) = expand_simple_binop (Pmode, PLUS, (TRAMP), const1_rtx, \
- gen_reg_rtx (Pmode), 0, \
- OPTAB_LIB_WIDEN); \
-} while (0)
-
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame.
FRAMEADDR is already the frame pointer of the COUNT frame, so we
#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
(move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
- < (TARGET_SMALLCODE ? 2 : ((ALIGN >= 32) ? 16 : 2)))
+ < (optimize_size ? 2 : ((ALIGN >= 32) ? 16 : 2)))
#define STORE_BY_PIECES_P(SIZE, ALIGN) \
(move_by_pieces_ninsns (SIZE, ALIGN, STORE_MAX_PIECES + 1) \
- < (TARGET_SMALLCODE ? 2 : ((ALIGN >= 32) ? 16 : 2)))
+ < (optimize_size ? 2 : ((ALIGN >= 32) ? 16 : 2)))
#define SET_BY_PIECES_P(SIZE, ALIGN) STORE_BY_PIECES_P(SIZE, ALIGN)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
- We have two alternate definitions for each of them.
- The usual definition accepts all pseudo regs; the other rejects
- them unless they have been allocated suitable hard regs.
- The symbol REG_OK_STRICT causes the latter definition to be used. */
-
-#ifndef REG_OK_STRICT
-
-/* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) \
- (GENERAL_OR_AP_REGISTER_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. */
-#define REG_OK_FOR_INDEX_P(X) \
- ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
- : REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-/* Nonzero if X/OFFSET is a hard reg that can be used as an index
- or if X is a pseudo reg. */
-#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
- ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
- : REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#else
-
-/* 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))
-
-/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) \
- REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-/* Nonzero if X/OFFSET is a hard reg that can be used as an index. */
-#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
- (REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
-
-#endif
+ The suitable hard regs are always accepted and all pseudo regs
+ are also accepted if STRICT is not set. */
+
+/* Nonzero if X is a reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X, STRICT) \
+ (GENERAL_OR_AP_REGISTER_P (REGNO (X)) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X is a reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X, STRICT) \
+ ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+ : REGNO (X) == R0_REG) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
+
+/* Nonzero if X/OFFSET is a reg that can be used as an index. */
+#define SUBREG_OK_FOR_INDEX_P(X, OFFSET, STRICT) \
+ ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
+ : REGNO (X) == R0_REG && OFFSET == 0) \
+ || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Macros for extra constraints. */
|| (GET_CODE ((OP)) == CONST \
&& GET_CODE (XEXP ((OP), 0)) == PLUS \
&& GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
-
-#define IS_LITERAL_OR_SYMBOLIC_S16_P(OP) \
- (GET_CODE ((OP)) == SIGN_EXTEND \
- && (GET_MODE ((OP)) == DImode \
- || GET_MODE ((OP)) == SImode) \
- && GET_CODE (XEXP ((OP), 0)) == TRUNCATE \
- && GET_MODE (XEXP ((OP), 0)) == HImode \
- && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP ((OP), 0), 0)) \
- || (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == ASHIFTRT \
- && (MOVI_SHORI_BASE_OPERAND_P \
- (XEXP (XEXP (XEXP ((OP), 0), 0), 0))) \
- && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
-
-#define IS_LITERAL_OR_SYMBOLIC_U16_P(OP) \
- (GET_CODE ((OP)) == ZERO_EXTEND \
- && (GET_MODE ((OP)) == DImode \
- || GET_MODE ((OP)) == SImode) \
- && GET_CODE (XEXP ((OP), 0)) == TRUNCATE \
- && GET_MODE (XEXP ((OP), 0)) == HImode \
- && (MOVI_SHORI_BASE_OPERAND_P (XEXP (XEXP ((OP), 0), 0)) \
- || (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == ASHIFTRT \
- && (MOVI_SHORI_BASE_OPERAND_P \
- (XEXP (XEXP (XEXP ((OP), 0), 0), 0))) \
- && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
+ && CONST_INT_P (XEXP (XEXP ((OP), 0), 1))))
#define IS_NON_EXPLICIT_CONSTANT_P(OP) \
(CONSTANT_P (OP) \
- && GET_CODE (OP) != CONST_INT \
+ && !CONST_INT_P (OP) \
&& GET_CODE (OP) != CONST_DOUBLE \
&& (!flag_pic \
|| (LEGITIMATE_PIC_OPERAND_P (OP) \
- && (! PIC_ADDR_P (OP) || PIC_OFFSET_P (OP)) \
+ && !PIC_ADDR_P (OP) \
&& GET_CODE (OP) != LABEL_REF)))
/* Check whether OP is a datalabel unspec. */
&& (UNSPEC_GOTOFF_P (XEXP ((OP), 0)) \
|| (GET_CODE (XEXP ((OP), 0)) == PLUS \
&& UNSPEC_GOTOFF_P (XEXP (XEXP ((OP), 0), 0)) \
- && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT)))
+ && CONST_INT_P (XEXP (XEXP ((OP), 0), 1)))))
#define PIC_ADDR_P(OP) \
(GET_CODE (OP) == CONST && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
&& XINT (XEXP ((OP), 0), 1) == UNSPEC_PIC)
-#define PIC_OFFSET_P(OP) \
- (PIC_ADDR_P (OP) \
- && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) == MINUS \
- && reg_mentioned_p (pc_rtx, XEXP (XVECEXP (XEXP ((OP), 0), 0, 0), 1)))
-
-#define PIC_DIRECT_ADDR_P(OP) \
- (PIC_ADDR_P (OP) && GET_CODE (XVECEXP (XEXP ((OP), 0), 0, 0)) != MINUS)
+#define PCREL_SYMOFF_P(OP) \
+ (GET_CODE (OP) == CONST \
+ && GET_CODE (XEXP ((OP), 0)) == UNSPEC \
+ && XINT (XEXP ((OP), 0), 1) == UNSPEC_PCREL_SYMOFF)
#define NON_PIC_REFERENCE_P(OP) \
(GET_CODE (OP) == LABEL_REF || GET_CODE (OP) == SYMBOL_REF \
&& (GET_CODE (XEXP (XEXP ((OP), 0), 0)) == SYMBOL_REF \
|| GET_CODE (XEXP (XEXP ((OP), 0), 0)) == LABEL_REF \
|| DATALABEL_REF_NO_CONST_P (XEXP (XEXP ((OP), 0), 0))) \
- && GET_CODE (XEXP (XEXP ((OP), 0), 1)) == CONST_INT))
+ && CONST_INT_P (XEXP (XEXP ((OP), 0), 1))))
#define PIC_REFERENCE_P(OP) \
(GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) \
#define MOVI_SHORI_BASE_OPERAND_P(OP) \
(flag_pic \
? (GOT_ENTRY_P (OP) || GOTPLT_ENTRY_P (OP) || GOTOFF_P (OP) \
- || PIC_OFFSET_P (OP)) \
+ || PCREL_SYMOFF_P (OP)) \
: NON_PIC_REFERENCE_P (OP))
\f
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
- that is a valid memory address for an instruction.
- The MODE argument is the machine mode for the MEM expression
- that wants to use this address. */
-
-#define MODE_DISP_OK_4(X,MODE) \
-(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
-
-#define MODE_DISP_OK_8(X,MODE) \
-((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
- && ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
-
-#undef MODE_DISP_OK_4
-#define MODE_DISP_OK_4(X,MODE) \
-((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
- && ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
- || ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383) \
- && ! (INTVAL(X) & 3) && TARGET_SH2A))
-
-#undef MODE_DISP_OK_8
-#define MODE_DISP_OK_8(X,MODE) \
-(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
- && ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
- || ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192) \
- && ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
-
-#define BASE_REGISTER_RTX_P(X) \
- ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
- || (GET_CODE (X) == SUBREG \
- && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
+#define MAYBE_BASE_REGISTER_RTX_P(X, STRICT) \
+ ((REG_P (X) && REG_OK_FOR_BASE_P (X, STRICT)) \
+ || (GET_CODE (X) == SUBREG \
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
- && GET_CODE (SUBREG_REG (X)) == REG \
- && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
+ && REG_P (SUBREG_REG (X)) \
+ && REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
/* Since this must be r0, which is a single register class, we must check
SUBREGs more carefully, to be sure that we don't accept one that extends
outside the class. */
-#define INDEX_REGISTER_RTX_P(X) \
- ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \
- || (GET_CODE (X) == SUBREG \
+#define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT) \
+ ((REG_P (X) && REG_OK_FOR_INDEX_P (X, STRICT)) \
+ || (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
- && GET_CODE (SUBREG_REG (X)) == REG \
- && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X))))
-
-/* Jump to LABEL if X is a valid address RTX. This must also take
- REG_OK_STRICT into account when deciding about valid registers, but it uses
- the above macros so we are in luck.
-
- Allow REG
- REG+disp
- REG+r0
- REG++
- --REG */
-
-/* ??? The SH2e does not have the REG+disp addressing mode when loading values
- into the FRx registers. We implement this by setting the maximum offset
- to zero when the value is SFmode. This also restricts loading of SFmode
- values into the integer registers, but that can't be helped. */
-
-/* The SH allows a displacement in a QI or HI amode, but only when the
- other operand is R0. GCC doesn't handle this very well, so we forgo
- all of that.
+ && REG_P (SUBREG_REG (X)) \
+ && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
- A legitimate index for a QI or HI is 0, SI can be any number 0..63,
- DI can be any number 0..60. */
-
-#define GO_IF_LEGITIMATE_INDEX(MODE, OP, LABEL) \
- do { \
- if (GET_CODE (OP) == CONST_INT) \
- { \
- if (TARGET_SHMEDIA) \
- { \
- int MODE_SIZE; \
- /* Check if this the address of an unaligned load / store. */\
- if ((MODE) == VOIDmode) \
- { \
- if (CONST_OK_FOR_I06 (INTVAL (OP))) \
- goto LABEL; \
- break; \
- } \
- MODE_SIZE = GET_MODE_SIZE (MODE); \
- if (! (INTVAL (OP) & (MODE_SIZE - 1)) \
- && INTVAL (OP) >= -512 * MODE_SIZE \
- && INTVAL (OP) < 512 * MODE_SIZE) \
- goto LABEL; \
- else \
- break; \
- } \
- if (TARGET_SH2A) \
- { \
- if (GET_MODE_SIZE (MODE) == 1 \
- && (unsigned) INTVAL (OP) < 4096) \
- goto LABEL; \
- } \
- if (MODE_DISP_OK_4 ((OP), (MODE))) goto LABEL; \
- if (MODE_DISP_OK_8 ((OP), (MODE))) goto LABEL; \
- } \
- } while(0)
+#ifdef REG_OK_STRICT
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, true)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, true)
+#else
+#define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, false)
+#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, false)
+#endif
#define ALLOW_INDEXED_ADDRESS \
((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
-{ \
- if (BASE_REGISTER_RTX_P (X)) \
- goto LABEL; \
- else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
- && ! TARGET_SHMEDIA \
- && BASE_REGISTER_RTX_P (XEXP ((X), 0))) \
- goto LABEL; \
- else if (GET_CODE (X) == PLUS \
- && ((MODE) != PSImode || reload_completed)) \
- { \
- rtx xop0 = XEXP ((X), 0); \
- rtx xop1 = XEXP ((X), 1); \
- if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \
- GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL); \
- if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode \
- || ((xop0 == stack_pointer_rtx \
- || xop0 == hard_frame_pointer_rtx) \
- && REG_P (xop1) && REGNO (xop1) == R0_REG) \
- || ((xop1 == stack_pointer_rtx \
- || xop1 == hard_frame_pointer_rtx) \
- && REG_P (xop0) && REGNO (xop0) == R0_REG)) \
- && ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4) \
- || (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8) \
- || ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \
- && TARGET_FMOVD && MODE == DFmode))) \
- { \
- if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
- goto LABEL; \
- if (INDEX_REGISTER_RTX_P (xop1) && BASE_REGISTER_RTX_P (xop0))\
- goto LABEL; \
- } \
- } \
-}
+#define GO_IF_LEGITIMATE_INDEX(MODE, OP, WIN) \
+ do { \
+ if (sh_legitimate_index_p ((MODE), (OP))) \
+ goto WIN; \
+ } while (0)
\f
-/* Try machine-dependent ways of modifying an illegitimate address
- to be legitimate. If we find one, return the new, valid address.
- This macro is used in only one place: `memory_address' in explow.c.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE and WIN are passed so that this macro can use
- GO_IF_LEGITIMATE_ADDRESS.
-
- It is always safe for this macro to do nothing. It exists to recognize
- opportunities to optimize the output.
-
- For the SH, if X is almost suitable for indexing, but the offset is
- out of range, convert it into a normal form so that cse has a chance
- of reducing the number of address registers used. */
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
-{ \
- if (flag_pic) \
- (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
- if (GET_CODE (X) == PLUS \
- && (GET_MODE_SIZE (MODE) == 4 \
- || GET_MODE_SIZE (MODE) == 8) \
- && GET_CODE (XEXP ((X), 1)) == CONST_INT \
- && BASE_REGISTER_RTX_P (XEXP ((X), 0)) \
- && ! TARGET_SHMEDIA \
- && ! ((TARGET_SH4 || TARGET_SH2A_DOUBLE) && (MODE) == DFmode) \
- && ! (TARGET_SH2E && (MODE) == SFmode)) \
- { \
- rtx index_rtx = XEXP ((X), 1); \
- HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base; \
- rtx sum; \
- \
- GO_IF_LEGITIMATE_INDEX ((MODE), index_rtx, WIN); \
- /* On rare occasions, we might get an unaligned pointer \
- that is indexed in a way to give an aligned address. \
- Therefore, keep the lower two bits in offset_base. */ \
- /* Instead of offset_base 128..131 use 124..127, so that \
- simple add suffices. */ \
- if (offset > 127) \
- { \
- offset_base = ((offset + 4) & ~60) - 4; \
- } \
- else \
- offset_base = offset & ~60; \
- /* Sometimes the normal form does not suit DImode. We \
- could avoid that by using smaller ranges, but that \
- would give less optimized code when SImode is \
- prevalent. */ \
- if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64) \
- { \
- sum = expand_binop (Pmode, add_optab, XEXP ((X), 0), \
- GEN_INT (offset_base), NULL_RTX, 0, \
- OPTAB_LIB_WIDEN); \
- \
- (X) = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base)); \
- goto WIN; \
- } \
- } \
-}
-
/* A C compound statement that attempts to replace X, which is an address
that needs reloading, with a valid memory address for an operand of
- mode MODE. WIN is a C statement label elsewhere in the code.
-
- Like for LEGITIMIZE_ADDRESS, for the SH we try to get a normal form
- of the address. That will allow inheritance of the address reloads. */
+ mode MODE. WIN is a C statement label elsewhere in the code. */
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && BASE_REGISTER_RTX_P (XEXP (X, 0)) \
- && ! TARGET_SHMEDIA \
- && ! (TARGET_SH4 && (MODE) == DFmode) \
- && ! ((MODE) == PSImode && (TYPE) == RELOAD_FOR_INPUT_ADDRESS) \
- && (ALLOW_INDEXED_ADDRESS \
- || XEXP ((X), 0) == stack_pointer_rtx \
- || XEXP ((X), 0) == hard_frame_pointer_rtx)) \
- { \
- rtx index_rtx = XEXP (X, 1); \
- HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base; \
- rtx sum; \
- \
- if (TARGET_SH2A && (MODE) == DFmode && (offset & 0x7)) \
- { \
- push_reload (X, NULL_RTX, &X, NULL, \
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \
- (TYPE)); \
- goto WIN; \
- } \
- if (TARGET_SH2E && MODE == SFmode) \
- { \
- X = copy_rtx (X); \
- push_reload (index_rtx, NULL_RTX, &XEXP (X, 1), NULL, \
- R0_REGS, Pmode, VOIDmode, 0, 0, (OPNUM), \
- (TYPE)); \
- goto WIN; \
- } \
- /* Instead of offset_base 128..131 use 124..127, so that \
- simple add suffices. */ \
- if (offset > 127) \
- { \
- offset_base = ((offset + 4) & ~60) - 4; \
- } \
- else \
- offset_base = offset & ~60; \
- /* Sometimes the normal form does not suit DImode. We \
- could avoid that by using smaller ranges, but that \
- would give less optimized code when SImode is \
- prevalent. */ \
- if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64) \
- { \
- sum = gen_rtx_PLUS (Pmode, XEXP (X, 0), \
- GEN_INT (offset_base)); \
- X = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));\
- push_reload (sum, NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), \
- (TYPE)); \
- goto WIN; \
- } \
- } \
- /* We must re-recognize what we created before. */ \
- else if (GET_CODE (X) == PLUS \
- && (GET_MODE_SIZE (MODE) == 4 || GET_MODE_SIZE (MODE) == 8) \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
- && BASE_REGISTER_RTX_P (XEXP (XEXP (X, 0), 0)) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! TARGET_SHMEDIA \
- && ! (TARGET_SH2E && MODE == SFmode)) \
- { \
- /* Because this address is so complex, we know it must have \
- been created by LEGITIMIZE_RELOAD_ADDRESS before; thus, \
- it is already unshared, and needs no further unsharing. */ \
- push_reload (XEXP ((X), 0), NULL_RTX, &XEXP ((X), 0), NULL, \
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, (OPNUM), (TYPE));\
+ do { \
+ if (sh_legitimize_reload_address (&(X), (MODE), (OPNUM), (TYPE))) \
goto WIN; \
- } \
-}
-
-/* Go to LABEL if ADDR (a legitimate address expression)
- has an effect that depends on the machine mode it is used for.
-
- ??? Strictly speaking, we should also include all indexed addressing,
- because the index scale factor is the length of the operand.
- However, the impact of GO_IF_MODE_DEPENDENT_ADDRESS would be to
- high if we did that. So we rely on reload to fix things up.
-
- Auto-increment addressing is now treated in recog.c. */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
+ } while (0)
\f
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
floating point types equivalent to `float'. */
#define DOUBLE_TYPE_SIZE ((TARGET_SH2E && ! TARGET_SH4 && ! TARGET_SH2A_DOUBLE) ? 32 : 64)
-#if defined(__SH2E__) || defined(__SH3E__) || defined( __SH4_SINGLE_ONLY__)
-#define LIBGCC2_DOUBLE_TYPE_SIZE 32
-#else
-#define LIBGCC2_DOUBLE_TYPE_SIZE 64
-#endif
-
/* 'char' is signed by default. */
#define DEFAULT_SIGNED_CHAR 1
in particular. */
#define INSN_SETS_ARE_DELAYED(X) \
- ((GET_CODE (X) == INSN \
+ ((NONJUMP_INSN_P (X) \
&& GET_CODE (PATTERN (X)) != SEQUENCE \
&& GET_CODE (PATTERN (X)) != USE \
&& GET_CODE (PATTERN (X)) != CLOBBER \
&& get_attr_is_sfunc (X)))
#define INSN_REFERENCES_ARE_DELAYED(X) \
- ((GET_CODE (X) == INSN \
+ ((NONJUMP_INSN_P (X) \
&& GET_CODE (PATTERN (X)) != SEQUENCE \
&& GET_CODE (PATTERN (X)) != USE \
&& GET_CODE (PATTERN (X)) != CLOBBER \
((CLASS) == FP0_REGS || (CLASS) == FP_REGS \
|| (CLASS) == DF_REGS || (CLASS) == DF_HI_REGS)
-#define REGISTER_MOVE_COST(MODE, SRCCLASS, DSTCLASS) \
- sh_register_move_cost ((MODE), (SRCCLASS), (DSTCLASS))
-
/* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option? This
would be so that people with slow memory systems could generate
different code that does fewer memory accesses. */
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
final_prescan_insn ((INSN), (OPVEC), (NOPERANDS))
-/* Print operand X (an rtx) in assembler syntax to file FILE.
- CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
- For `%' followed by punctuation, CODE is the punctuation and X is null. */
-
-#define PRINT_OPERAND(STREAM, X, CODE) print_operand ((STREAM), (X), (CODE))
-
-/* Print a memory address as an operand to reference that memory location. */
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address ((STREAM), (X))
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
- ((CHAR) == '.' || (CHAR) == '#' || (CHAR) == '@' || (CHAR) == ',' \
- || (CHAR) == '$' || (CHAR) == '\'' || (CHAR) == '>')
-
/* Recognize machine-specific patterns that may appear within
constants. Used for PIC-specific UNSPECs. */
#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
do \
- if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
+ if (GET_CODE (X) == UNSPEC) \
{ \
switch (XINT ((X), 1)) \
{ \
assemble_name ((STREAM), name); \
} \
break; \
+ case UNSPEC_EXTRACT_S16: \
+ case UNSPEC_EXTRACT_U16: \
+ { \
+ rtx val, shift; \
+ \
+ val = XVECEXP (X, 0, 0); \
+ shift = XVECEXP (X, 0, 1); \
+ fputc ('(', STREAM); \
+ if (shift != const0_rtx) \
+ fputc ('(', STREAM); \
+ if (GET_CODE (val) == CONST \
+ || GET_RTX_CLASS (GET_CODE (val)) != RTX_OBJ) \
+ { \
+ fputc ('(', STREAM); \
+ output_addr_const (STREAM, val); \
+ fputc (')', STREAM); \
+ } \
+ else \
+ output_addr_const (STREAM, val); \
+ if (shift != const0_rtx) \
+ { \
+ fputs (" >> ", STREAM); \
+ output_addr_const (STREAM, shift); \
+ fputc (')', STREAM); \
+ } \
+ fputs (" & 65535)", STREAM); \
+ } \
+ break; \
+ case UNSPEC_SYMOFF: \
+ output_addr_const (STREAM, XVECEXP (X, 0, 0)); \
+ fputc ('-', STREAM); \
+ if (GET_CODE (XVECEXP (X, 0, 1)) == CONST) \
+ { \
+ fputc ('(', STREAM); \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ fputc (')', STREAM); \
+ } \
+ else \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ break; \
+ case UNSPEC_PCREL_SYMOFF: \
+ output_addr_const (STREAM, XVECEXP (X, 0, 0)); \
+ fputs ("-(", STREAM); \
+ output_addr_const (STREAM, XVECEXP (X, 0, 1)); \
+ fputs ("-.)", STREAM); \
+ break; \
default: \
goto FAIL; \
} \
#define sh_cpu_attr ((enum attr_cpu)sh_cpu)
extern enum processor_type sh_cpu;
-extern int optimize; /* needed for gen_casesi. */
-
enum mdep_reorg_phase_e
{
SH_BEFORE_MDEP_REORG,
#define SIDI_OFF (TARGET_LITTLE_ENDIAN ? 0 : 4)
-/* ??? Define ACCUMULATE_OUTGOING_ARGS? This is more efficient than pushing
- and popping arguments. However, we do have push/pop instructions, and
- rather limited offsets (4 bits) in load/store instructions, so it isn't
- clear if this would give better code. If implemented, should check for
- compatibility problems. */
+/* 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_SMALLCODE ? 1 : 2) : 20)
+ (TARGET_HARD_SH4 ? 1 : TARGET_SH3 ? (optimize_size ? 1 : 2) : 20)
#define NUM_MODES_FOR_MODE_SWITCHING { FP_MODE_NONE }