/* Definitions of target machine for GNU compiler, for ARM.
- Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com)
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifndef __ARM_H__
-#define __ARM_H__
+#ifndef GCC_ARM_H
+#define GCC_ARM_H
#define TARGET_CPU_arm2 0x0000
#define TARGET_CPU_arm250 0x0000
#define TARGET_CPU_strongarm1100 0x0040
#define TARGET_CPU_arm9 0x0080
#define TARGET_CPU_arm9tdmi 0x0080
+#define TARGET_CPU_xscale 0x0100
/* Configure didn't specify. */
#define TARGET_CPU_generic 0x8000
arm_cc;
extern arm_cc arm_current_cc;
-extern const char * arm_condition_codes[];
#define ARM_INVERSE_CONDITION_CODE(X) ((arm_cc) (((int)X) ^ 1))
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
extern int return_used_this_function;
-/* Nonzero if the prologue must setup `fp'. */
-extern int current_function_anonymous_args;
\f
/* Just in case configure has failed to define anything. */
#ifndef TARGET_CPU_DEFAULT
#endif
/* If the configuration file doesn't specify the cpu, the subtarget may
- override it. If it doesn't, then default to an ARM6. */
+ override it. If it doesn't, then default to an ARM6. */
#if TARGET_CPU_DEFAULT == TARGET_CPU_generic
#undef TARGET_CPU_DEFAULT
+
#ifdef SUBTARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT SUBTARGET_CPU_DEFAULT
#else
#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7m
#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_3M__"
#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7tdmi || TARGET_CPU_DEFAULT == TARGET_CPU_arm9
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7tdmi || TARGET_CPU_DEFAULT == TARGET_CPU_arm9 || TARGET_CPU_DEFAULT == TARGET_CPU_arm9tdmi
#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__"
#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm8 || TARGET_CPU_DEFAULT == TARGET_CPU_arm810 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm8 || TARGET_CPU_DEFAULT == TARGET_CPU_arm810 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm110 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm1100
#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4__"
#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_xscale
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__"
+#else
Unrecognized value in TARGET_CPU_DEFAULT.
#endif
#endif
#endif
#endif
#endif
-
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Acpu(arm) -Amachine(arm)"
#endif
+#undef CPP_SPEC
#define CPP_SPEC "\
%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
%(cpp_endian) %(subtarget_cpp_spec) %(cpp_isa) %(cpp_interwork)"
-#define CPP_ISA_SPEC "%{mthumb:-Dthumb -D__thumb__} %{!mthumb:-Darm -D__arm__}"
+#define CPP_ISA_SPEC "%{mthumb:-D__thumb__} %{!mthumb:-D__arm__}"
/* Set the architecture define -- if -march= is set, then it overrides
the -mcpu= setting. */
#define CPP_CPU_ARCH_SPEC "\
+-Acpu=arm -Amachine=arm \
%{march=arm2:-D__ARM_ARCH_2__} \
%{march=arm250:-D__ARM_ARCH_2__} \
%{march=arm3:-D__ARM_ARCH_2__} \
%{march=strongarm:-D__ARM_ARCH_4__} \
%{march=strongarm110:-D__ARM_ARCH_4__} \
%{march=strongarm1100:-D__ARM_ARCH_4__} \
+%{march=xscale:-D__ARM_ARCH_5TE__} \
+%{march=xscale:-D__XSCALE__} \
%{march=armv2:-D__ARM_ARCH_2__} \
%{march=armv2a:-D__ARM_ARCH_2__} \
%{march=armv3:-D__ARM_ARCH_3__} \
%{mcpu=strongarm:-D__ARM_ARCH_4__} \
%{mcpu=strongarm110:-D__ARM_ARCH_4__} \
%{mcpu=strongarm1100:-D__ARM_ARCH_4__} \
+ %{mcpu=xscale:-D__ARM_ARCH_5TE__} \
+ %{mcpu=xscale:-D__XSCALE__} \
%{!mcpu*:%(cpp_cpu_arch_default)}} \
"
#define CPP_INTERWORK_SPEC " \
%{mthumb-interwork: \
- %{mno-thumb-interwork: %eIncompatible interworking options} \
+ %{mno-thumb-interwork: %eincompatible interworking options} \
-D__THUMB_INTERWORK__} \
%{!mthumb-interwork:%{!mno-thumb-interwork:%(cpp_interwork_default)}} \
"
+#ifndef CPP_PREDEFINES
+#define CPP_PREDEFINES ""
+#endif
+
+#ifndef CC1_SPEC
#define CC1_SPEC ""
+#endif
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
{"no-poke-function-name", -ARM_FLAG_POKE, "" }, \
{"fpe", ARM_FLAG_FPE, "" }, \
{"apcs-32", ARM_FLAG_APCS_32, \
- N_("Use the 32bit version of the APCS") }, \
+ N_("Use the 32-bit version of the APCS") }, \
{"apcs-26", -ARM_FLAG_APCS_32, \
- N_("Use the 26bit version of the APCS") }, \
+ N_("Use the 26-bit version of the APCS") }, \
{"apcs-stack-check", ARM_FLAG_APCS_STACK, "" }, \
{"no-apcs-stack-check", -ARM_FLAG_APCS_STACK, "" }, \
{"apcs-float", ARM_FLAG_APCS_FLOAT, \
{"words-little-endian", ARM_FLAG_LITTLE_WORDS, \
N_("Assume big endian bytes, little endian words") }, \
{"thumb-interwork", ARM_FLAG_INTERWORK, \
- N_("Support calls between THUMB and ARM instructions sets") }, \
+ N_("Support calls between Thumb and ARM instruction sets") }, \
{"no-thumb-interwork", -ARM_FLAG_INTERWORK, "" }, \
{"abort-on-noreturn", ARM_FLAG_ABORT_NORETURN, \
N_("Generate a call to abort if a noreturn function returns")}, \
{"no-abort-on-noreturn", -ARM_FLAG_ABORT_NORETURN, "" }, \
- {"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, \
+ {"no-sched-prolog", ARM_FLAG_NO_SCHED_PRO, \
N_("Do not move instructions into a function's prologue") }, \
- {"no-sched-prolog", ARM_FLAG_NO_SCHED_PRO, "" }, \
+ {"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, "" }, \
{"single-pic-base", ARM_FLAG_SINGLE_PIC_BASE, \
N_("Do not load the PIC register in function prologues") }, \
{"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \
/* Default floating point architecture. Override in sub-target if
necessary. */
+#ifndef FP_DEFAULT
#define FP_DEFAULT FP_SOFT2
+#endif
/* Nonzero if the processor has a fast multiply insn, and one that does
a 64-bit multiply of two 32-bit values. */
/* Nonzero if this chip supports the ARM Architecture 5 extensions */
extern int arm_arch5;
+/* Nonzero if this chip supports the ARM Architecture 5E extensions */
+extern int arm_arch5e;
+
/* Nonzero if this chip can benefit from load scheduling. */
extern int arm_ld_sched;
/* Nonzero if this chip is a StrongARM. */
extern int arm_is_strong;
-/* Nonzero if this chip is a an ARM6 or an ARM7. */
+/* Nonzero if this chip is an XScale. */
+extern int arm_is_xscale;
+
+/* Nonzero if this chip is an ARM6 or an ARM7. */
extern int arm_is_6_or_7;
#ifndef TARGET_DEFAULT
that is controlled by the APCS-FRAME option. */
#define CAN_DEBUG_WITHOUT_FP
+#undef TARGET_MEM_FUNCTIONS
#define TARGET_MEM_FUNCTIONS 1
#define OVERRIDE_OPTIONS arm_override_options ()
This is always true, even when in little-endian mode. */
#define FLOAT_WORDS_BIG_ENDIAN 1
-/* Number of bits in an addressable storage unit */
-#define BITS_PER_UNIT 8
-
#define BITS_PER_WORD 32
#define UNITS_PER_WORD 4
#define FUNCTION_BOUNDARY 32
+/* The lowest bit is used to indicate Thumb-mode functions, so the
+ vbit must go into the delta field of pointers to member
+ functions. */
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta
+
#define EMPTY_FIELD_BOUNDARY 32
#define BIGGEST_ALIGNMENT 32
/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+#define CONSTANT_ALIGNMENT_FACTOR (TARGET_THUMB || ! arm_is_xscale ? 1 : 2)
+
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST \
+ && (ALIGN) < BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR) \
+ ? BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR : (ALIGN))
/* Setting STRUCTURE_SIZE_BOUNDARY to 32 produces more efficient code, but the
value set in previous versions of this toolchain was 8, which produces more
compact structures. The command line option -mstructure_size_boundary=<n>
- can be used to change this value. For compatability with the ARM SDK
+ can be used to change this value. For compatibility with the ARM SDK
however the value should be left at 32. ARM SDT Reference Manual (ARM DUI
0020D) page 2-20 says "Structures are aligned on word boundaries". */
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
#define CONDITIONAL_REGISTER_USAGE \
{ \
+ int regno; \
+ \
if (TARGET_SOFT_FLOAT || TARGET_THUMB) \
{ \
- int regno; \
for (regno = FIRST_ARM_FP_REGNUM; \
regno <= LAST_ARM_FP_REGNUM; ++regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
/* Return the regiser number of the N'th (integer) argument. */
#define ARG_REGISTER(N) (N - 1)
+#if 0 /* FIXME: The ARM backend has special code to handle structure
+ returns, and will reserve its own hidden first argument. So
+ if this macro is enabled a *second* hidden argument will be
+ reserved, which will break binary compatibility with old
+ toolchains and also thunk handling. One day this should be
+ fixed. */
/* RTX for structure returns. NULL means use a hidden first argument. */
#define STRUCT_VALUE 0
+#else
+/* Register in which address to store a structure value
+ is passed to a function. */
+#define STRUCT_VALUE_REGNUM ARG_REGISTER (1)
+#endif
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
#define LAST_ARG_REGNUM ARG_REGISTER (NUM_ARG_REGS)
/* The number of the last "lo" register (thumb). */
-#define LAST_LO_REGNUM 7
+#define LAST_LO_REGNUM 7
+
+/* The register that holds the return address in exception handlers. */
+#define EXCEPTION_LR_REGNUM 2
/* The native (Norcroft) Pascal compiler for the ARM passes the static chain
as an invisible last argument (possible since varargs don't exist in
Pascal), so the following is not true. */
-#define STATIC_CHAIN_REGNUM (TARGET_ARM ? 8 : 9)
+#define STATIC_CHAIN_REGNUM (TARGET_ARM ? 12 : 9)
/* Define this to be where the real frame pointer is if it is not possible to
work out the offset between the frame pointer and the automatic variables
pointer. */
#define ARM_HARD_FRAME_POINTER_REGNUM 11
#define THUMB_HARD_FRAME_POINTER_REGNUM 7
-#define HARD_FRAME_POINTER_REGNUM (TARGET_ARM ? ARM_HARD_FRAME_POINTER_REGNUM : THUMB_HARD_FRAME_POINTER_REGNUM)
-#define FP_REGNUM HARD_FRAME_POINTER_REGNUM
-/* Scratch register - used in all kinds of places, eg trampolines. */
-#define IP_REGNUM 12
+#define HARD_FRAME_POINTER_REGNUM \
+ (TARGET_ARM \
+ ? ARM_HARD_FRAME_POINTER_REGNUM \
+ : THUMB_HARD_FRAME_POINTER_REGNUM)
-/* Register to use for pushing function arguments. */
-#define STACK_POINTER_REGNUM 13
-#define SP_REGNUM STACK_POINTER_REGNUM
-
-/* Register which holds return address from a subroutine call. */
-#define LR_REGNUM 14
-
-/* Define this if the program counter is overloaded on a register. */
-#define PC_REGNUM 15
+#define FP_REGNUM HARD_FRAME_POINTER_REGNUM
-/* The number of the last ARM (integer) register. */
-#define LAST_ARM_REGNUM 15
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM SP_REGNUM
/* ARM floating pointer registers. */
#define FIRST_ARM_FP_REGNUM 16
#define LAST_ARM_FP_REGNUM 23
-/* Internal, so that we don't need to refer to a raw number */
-#define CC_REGNUM 24
-
/* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM 25
If we have to have a frame pointer we might as well make use of it.
APCS says that the frame pointer does not need to be pushed in leaf
functions, or simple tail call functions. */
-#define FRAME_POINTER_REQUIRED \
- (current_function_has_nonlocal_label \
+#define FRAME_POINTER_REQUIRED \
+ (current_function_has_nonlocal_label \
|| (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
/* Return number of consecutive hard regs needed starting at reg REGNO
&& REGNO != ARG_POINTER_REGNUM) \
? 1 : NUM_REGS (MODE))
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- This is TRUE for ARM regs since they can hold anything, and TRUE for FPU
- regs holding FP.
- For the Thumb we only allow values bigger than SImode in registers 0 - 6,
- so that there is always a second lo register available to hold the upper
- part of the value. Probably we ought to ensure that the register is the
- start of an even numbered register pair. */
+/* Return true if REGNO is suitable for holding a quantity of type MODE. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (TARGET_ARM ? \
- ((GET_MODE_CLASS (MODE) == MODE_CC) ? (REGNO == CC_REGNUM) : \
- ( REGNO <= LAST_ARM_REGNUM \
- || REGNO == FRAME_POINTER_REGNUM \
- || REGNO == ARG_POINTER_REGNUM \
- || GET_MODE_CLASS (MODE) == MODE_FLOAT)) \
- : \
- ((GET_MODE_CLASS (MODE) == MODE_CC) ? (REGNO == CC_REGNUM) : \
- (NUM_REGS (MODE) < 2 || REGNO < LAST_LO_REGNUM)))
+ arm_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.
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26 \
}
+
+/* Interrupt functions can only use registers that have already been
+ saved by the prologue, even if they would normally be
+ call-clobbered. */
+#define HARD_REGNO_RENAME_OK(SRC, DST) \
+ (! IS_INTERRUPT (cfun->machine->func_type) || \
+ regs_ever_live[DST])
\f
/* Register and constant classes. */
/* Register classes: used to be simple, just all ARM regs or all FPU regs
- Now that the Thumb is involved it has become more compilcated. */
+ Now that the Thumb is involved it has become more complicated. */
enum reg_class
{
NO_REGS,
{ 0x200FFFF }, /* GENERAL_REGS */ \
{ 0x2FFFFFF } /* ALL_REGS */ \
}
-
+
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
#define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
#define BASE_REG_CLASS (TARGET_THUMB ? BASE_REGS : GENERAL_REGS)
+/* For the Thumb the high registers cannot be used as base
+ registers when addressing quanitities in QI or HI mode. */
+#define MODE_BASE_REG_CLASS(MODE) \
+ (TARGET_ARM ? BASE_REGS : \
+ (((MODE) == QImode || (MODE) == HImode || (MODE) == VOIDmode) \
+ ? LO_REGS : BASE_REGS))
+
/* When SMALL_REGISTER_CLASSES is nonzero, 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
else \
break; \
\
- high = ((((val - low) & HOST_UINT (0xffffffff)) \
- ^ HOST_UINT (0x80000000)) \
- - HOST_UINT (0x80000000)); \
+ high = ((((val - low) & (unsigned HOST_WIDE_INT) 0xffffffff) \
+ ^ (unsigned HOST_WIDE_INT) 0x80000000) \
+ - (unsigned HOST_WIDE_INT) 0x80000000); \
/* Check for overflow or zero */ \
if (low == 0 || high == 0 || (high + low != val)) \
break; \
gen_rtx_PLUS (GET_MODE (X), XEXP (X, 0), \
GEN_INT (high)), \
GEN_INT (low)); \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL_PTR, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
+ push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
+ MODE_BASE_REG_CLASS (MODE), GET_MODE (X), \
+ VOIDmode, 0, 0, OPNUM, TYPE); \
goto WIN; \
} \
} \
&& GET_CODE (XEXP (X, 0)) == REG \
&& XEXP (X, 0) == stack_pointer_rtx \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
+ && ! THUMB_LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
{ \
rtx orig_X = X; \
X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
- BASE_REG_CLASS, \
+ push_reload (orig_X, NULL_RTX, &X, NULL, \
+ MODE_BASE_REG_CLASS (MODE), \
Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
goto WIN; \
} \
((CLASS) == FPU_REGS ? 1 : NUM_REGS (MODE))
/* Moves between FPU_REGS and GENERAL_REGS are two memory insns. */
-#define REGISTER_MOVE_COST(FROM, TO) \
+#define REGISTER_MOVE_COST(MODE, FROM, TO) \
(TARGET_ARM ? \
((FROM) == FPU_REGS && (TO) != FPU_REGS ? 20 : \
(FROM) != FPU_REGS && (TO) == FPU_REGS ? 20 : 2) \
#define CALL_LONG 0x00000001 /* Always call indirect. */
#define CALL_SHORT 0x00000002 /* Never call indirect. */
-/* A C structure for machine-specific, per-function data. This is added
- to the cfun structure. */
-struct machine_function
+/* These bits describe the different types of function supported
+ by the ARM backend. They are exclusive. ie a function cannot be both a
+ normal function and an interworked function, for example. Knowing the
+ type of a function is important for determining its prologue and
+ epilogue sequences.
+ Note value 7 is currently unassigned. Also note that the interrupt
+ function types all have bit 2 set, so that they can be tested for easily.
+ Note that 0 is deliberately chosen for ARM_FT_UNKNOWN so that when the
+ machine_function structure is initialised (to zero) func_type will
+ default to unknown. This will force the first use of arm_current_func_type
+ to call arm_compute_func_type. */
+#define ARM_FT_UNKNOWN 0 /* Type has not yet been determined. */
+#define ARM_FT_NORMAL 1 /* Your normal, straightforward function. */
+#define ARM_FT_INTERWORKED 2 /* A function that supports interworking. */
+#define ARM_FT_EXCEPTION_HANDLER 3 /* A C++ exception handler. */
+#define ARM_FT_ISR 4 /* An interrupt service routine. */
+#define ARM_FT_FIQ 5 /* A fast interrupt service routine. */
+#define ARM_FT_EXCEPTION 6 /* An ARM exception handler (subcase of ISR). */
+
+#define ARM_FT_TYPE_MASK ((1 << 3) - 1)
+
+/* In addition functions can have several type modifiers,
+ outlined by these bit masks: */
+#define ARM_FT_INTERRUPT (1 << 2) /* Note overlap with FT_ISR and above. */
+#define ARM_FT_NAKED (1 << 3) /* No prologue or epilogue. */
+#define ARM_FT_VOLATILE (1 << 4) /* Does not return. */
+#define ARM_FT_NESTED (1 << 5) /* Embedded inside another func. */
+
+/* Some macros to test these flags. */
+#define ARM_FUNC_TYPE(t) (t & ARM_FT_TYPE_MASK)
+#define IS_INTERRUPT(t) (t & ARM_FT_INTERRUPT)
+#define IS_VOLATILE(t) (t & ARM_FT_VOLATILE)
+#define IS_NAKED(t) (t & ARM_FT_NAKED)
+#define IS_NESTED(t) (t & ARM_FT_NESTED)
+
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+typedef struct machine_function
{
- /* Records __builtin_return address. */
- struct rtx_def *ra_rtx;
/* Additionsl stack adjustment in __builtin_eh_throw. */
struct rtx_def *eh_epilogue_sp_ofs;
/* Records if LR has to be saved for far jumps. */
int far_jump_used;
/* Records if ARG_POINTER was ever live. */
int arg_pointer_live;
-};
+ /* Records if the save of LR has been eliminated. */
+ int lr_save_eliminated;
+ /* Records the type of the current function. */
+ unsigned long func_type;
+ /* Record if the function has a variable argument list. */
+ int uses_anonymous_args;
+}
+machine_function;
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
/* 1 if N is a possible register number for function argument passing.
On the ARM, r0-r3 are used to pass args. */
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >= 0 && (REGNO) <= 3)
+#define FUNCTION_ARG_REGNO_P(REGNO) (IN_RANGE ((REGNO), 0, 3))
\f
/* Tail calling. */
that way. */
#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PRETEND_SIZE, NO_RTL) \
{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
+ cfun->machine->uses_anonymous_args = 1; \
if ((CUM).nregs < NUM_ARG_REGS) \
(PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
}
-/* Generate assembly output for the start of a function. */
-#define FUNCTION_PROLOGUE(STREAM, SIZE) \
- do \
- { \
- if (TARGET_ARM) \
- output_arm_prologue (STREAM, SIZE); \
- else \
- output_thumb_prologue (STREAM); \
- } \
- while (0)
-
/* If your target environment doesn't prefix user functions with an
underscore, you may wish to re-define this to prevent any conflicts.
e.g. AOF may prefix mcount with an underscore. */
The ``mov ip,lr'' seems like a good idea to stick with cc convention.
``prof'' doesn't seem to mind about this! */
+#ifndef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
char temp[20]; \
fputc ('\n', STREAM); \
ASM_GENERATE_INTERNAL_LABEL (temp, "LP", LABELNO); \
sym = gen_rtx (SYMBOL_REF, Pmode, temp); \
- ASM_OUTPUT_INT (STREAM, sym); \
+ assemble_aligned_integer (UNITS_PER_WORD, sym); \
}
+#endif
+#ifndef THUMB_FUNCTION_PROFILER
#define THUMB_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
- fprintf (STREAM, "\tmov\\tip, lr\n"); \
+ fprintf (STREAM, "\tmov\tip, lr\n"); \
fprintf (STREAM, "\tbl\tmcount\n"); \
fprintf (STREAM, "\t.word\tLP%d\n", LABELNO); \
}
+#endif
#define FUNCTION_PROFILER(STREAM, LABELNO) \
if (TARGET_ARM) \
frame. */
#define EXIT_IGNORE_STACK 1
-/* Generate the assembly code for function exit. */
-#define FUNCTION_EPILOGUE(STREAM, SIZE) \
- output_func_epilogue (SIZE)
+#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM)
/* Determine if the epilogue should be output as RTL.
You should override this if you define FUNCTION_EXTRA_EPILOGUE. */
pointer register. Secondly, the pseudo frame pointer register can always
be eliminated; it is replaced with either the stack or the real frame
pointer. Note we have to use {ARM|THUMB}_HARD_FRAME_POINTER_REGNUM
- because the defintion of HARD_FRAME_POINTER_REGNUM is not a constant. */
+ because the definition of HARD_FRAME_POINTER_REGNUM is not a constant. */
#define ELIMINABLE_REGS \
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM },\
/* Define the offset between two registers, one to be eliminated, and the
other its replacement, at the start of a routine. */
#define ARM_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ \
- int volatile_func = arm_volatile_func (); \
- if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\
- (OFFSET) = 0; \
- else if ((FROM) == FRAME_POINTER_REGNUM \
- && (TO) == STACK_POINTER_REGNUM) \
- (OFFSET) = current_function_outgoing_args_size \
- + ROUND_UP (get_frame_size ()); \
- else \
+ do \
{ \
- int regno; \
- int offset = 12; \
- int saved_hard_reg = 0; \
- \
- if (! volatile_func) \
- { \
- for (regno = 0; regno <= 10; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- saved_hard_reg = 1, offset += 4; \
- if (! TARGET_APCS_FRAME \
- && ! frame_pointer_needed \
- && regs_ever_live[HARD_FRAME_POINTER_REGNUM] \
- && ! call_used_regs[HARD_FRAME_POINTER_REGNUM]) \
- saved_hard_reg = 1, offset += 4; \
- /* PIC register is a fixed reg, so call_used_regs set. */ \
- if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) \
- saved_hard_reg = 1, offset += 4; \
- for (regno = FIRST_ARM_FP_REGNUM; \
- regno <= LAST_ARM_FP_REGNUM; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- offset += 12; \
- } \
- if ((FROM) == FRAME_POINTER_REGNUM) \
- (OFFSET) = - offset; \
- else \
- { \
- if (! frame_pointer_needed) \
- offset -= 16; \
- if (! volatile_func \
- && (regs_ever_live[LR_REGNUM] || saved_hard_reg)) \
- offset += 4; \
- offset += current_function_outgoing_args_size; \
- (OFFSET) = ROUND_UP (get_frame_size ()) + offset; \
- } \
+ (OFFSET) = arm_compute_initial_elimination_offset (FROM, TO); \
} \
-}
+ while (0)
/* Note: This macro must match the code in thumb_function_prologue(). */
#define THUMB_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
if (TARGET_ARM) \
- ARM_INITIAL_ELIMINATION_OFFSET (FROM, TO, OFFSET) \
+ ARM_INITIAL_ELIMINATION_OFFSET (FROM, TO, OFFSET); \
else \
THUMB_INITIAL_ELIMINATION_OFFSET (FROM, TO, OFFSET)
.word static chain value
.word function's address
??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define ARM_TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
- STATIC_CHAIN_REGNUM, PC_REGNUM); \
- asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
- PC_REGNUM, PC_REGNUM); \
- ASM_OUTPUT_INT (FILE, const0_rtx); \
- ASM_OUTPUT_INT (FILE, const0_rtx); \
+#define ARM_TRAMPOLINE_TEMPLATE(FILE) \
+{ \
+ asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
+ STATIC_CHAIN_REGNUM, PC_REGNUM); \
+ asm_fprintf (FILE, "\tldr\t%r, [%r, #0]\n", \
+ PC_REGNUM, PC_REGNUM); \
+ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
+ assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); \
}
/* On the Thumb we always switch into ARM mode to execute the trampoline.
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE (TARGET_ARM ? 16 : 24)
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
+/* Alignment required for a trampoline in bits. */
+#define TRAMPOLINE_ALIGNMENT 32
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE))
/* On the ARM, don't allow the pc to be used. */
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- (TARGET_THUMB ? \
- ( TEST_REGNO (REGNO, <=, LAST_LO_REGNUM) \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM))) \
- :( \
- TEST_REGNO (REGNO, <, PC_REGNUM) \
- || TEST_REGNO (REGNO, ==, FRAME_POINTER_REGNUM) \
- || TEST_REGNO (REGNO, ==, ARG_POINTER_REGNUM)))
-
-/* This is like REGNO_MODE_OF_FOR_BASE_P, except that in Thumb mode
- the stack pointer is always acceptable, hence the passing of SImode */
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO, SImode)
-
-/* We play tricks with REGNO_MODE_OK... here, so that for ARM the macros
- are the same, but for Thumb only registers 0 - 7 are OK. */
+#define ARM_REGNO_OK_FOR_BASE_P(REGNO) \
+ (TEST_REGNO (REGNO, <, PC_REGNUM) \
+ || TEST_REGNO (REGNO, ==, FRAME_POINTER_REGNUM) \
+ || TEST_REGNO (REGNO, ==, ARG_POINTER_REGNUM))
+
+#define THUMB_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
+ (TEST_REGNO (REGNO, <=, LAST_LO_REGNUM) \
+ || (GET_MODE_SIZE (MODE) >= 4 \
+ && TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM)))
+
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
+ (TARGET_THUMB \
+ ? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) \
+ : ARM_REGNO_OK_FOR_BASE_P (REGNO))
+
+/* For ARM code, we don't care about the mode, but for Thumb, the index
+ must be suitable for use in a QImode load. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode)
#define THUMB_LEGITIMATE_CONSTANT_P(X) \
( GET_CODE (X) == CONST_INT \
|| GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
+ || CONSTANT_ADDRESS_P (X) \
+ || flag_pic)
#define LEGITIMATE_CONSTANT_P(X) \
(TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) : THUMB_LEGITIMATE_CONSTANT_P (X))
`assemble_name' uses this. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- fprintf (FILE, "%s%s", USER_LABEL_PREFIX, arm_strip_name_encoding (NAME))
+ asm_fprintf (FILE, "%U%s", arm_strip_name_encoding (NAME))
/* If we are referencing a function that is weak then encode a long call
flag in the function name, otherwise if the function is static or
or known to be defined in this file then encode a short call flag.
This macro is used inside the ENCODE_SECTION macro. */
#define ARM_ENCODE_CALL_TYPE(decl) \
- if (TREE_CODE (decl) == FUNCTION_DECL) \
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') \
{ \
- if (DECL_WEAK (decl)) \
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) \
arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
else if (! TREE_PUBLIC (decl)) \
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
- } \
+ }
/* Symbols in the text segment can be accessed without indirecting via the
constant pool; it may take an extra binary operation, but this is still
/* This doesn't work with AOF syntax, since the string table may be in
a different AREA. */
#ifndef AOF_ASSEMBLER
-#define ENCODE_SECTION_INFO(decl) \
+#define ENCODE_SECTION_INFO(decl, first) \
{ \
if (optimize > 0 && TREE_CONSTANT (decl) \
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) \
? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
} \
- ARM_ENCODE_CALL_TYPE (decl) \
+ if (first) \
+ ARM_ENCODE_CALL_TYPE (decl) \
}
#else
-#define ENCODE_SECTION_INFO(decl) \
+#define ENCODE_SECTION_INFO(decl, first) \
{ \
- ARM_ENCODE_CALL_TYPE (decl) \
+ if (first) \
+ ARM_ENCODE_CALL_TYPE (decl) \
}
#endif
The symbol REG_OK_STRICT causes the latter definition to be used. */
#ifndef REG_OK_STRICT
-#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
- (TARGET_THUMB ? \
- ( REGNO (X) <= LAST_LO_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == hard_frame_pointer_rtx \
- || (X) == arg_pointer_rtx))) \
- :( \
- REGNO (X) <= LAST_ARM_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || REGNO (X) == FRAME_POINTER_REGNUM \
- || REGNO (X) == ARG_POINTER_REGNUM))
-
-/* 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) \
- REG_MODE_OK_FOR_BASE_P (X, SImode)
+#define ARM_REG_OK_FOR_BASE_P(X) \
+ (REGNO (X) <= LAST_ARM_REGNUM \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER \
+ || REGNO (X) == FRAME_POINTER_REGNUM \
+ || REGNO (X) == ARG_POINTER_REGNUM)
-/* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. On the Thumb, the stack pointer
- is not suitable. */
-#define REG_OK_FOR_INDEX_P(X) \
- REG_MODE_OK_FOR_BASE_P (X, QImode)
-
-/* Just like REG_OK_FOR_BASE_P except that we also allow the PC. */
-#define REG_OK_FOR_PRE_POST_P(X) \
- (REG_OK_FOR_BASE_P (X) || REGNO(X) == PC_REGNUM)
+#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
+ (REGNO (X) <= LAST_LO_REGNUM \
+ || REGNO (X) >= FIRST_PSEUDO_REGISTER \
+ || (GET_MODE_SIZE (MODE) >= 4 \
+ && (REGNO (X) == STACK_POINTER_REGNUM \
+ || (X) == hard_frame_pointer_rtx \
+ || (X) == arg_pointer_rtx)))
#else /* REG_OK_STRICT */
-/* 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))
+#define ARM_REG_OK_FOR_BASE_P(X) \
+ ARM_REGNO_OK_FOR_BASE_P (REGNO (X))
-/* Just like REG_OK_FOR_BASE_P except that we also allow the PC. */
-#define REG_OK_FOR_PRE_POST_P(X) \
- (REG_OK_FOR_BASE_P (X) || TEST_REGNO (REGNO (X), ==, PC_REGNUM))
+#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE) \
+ THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
#endif /* REG_OK_STRICT */
+
+/* Now define some helpers in terms of the above. */
+
+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
+ (TARGET_THUMB \
+ ? THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE) \
+ : ARM_REG_OK_FOR_BASE_P (X))
+
+#define ARM_REG_OK_FOR_INDEX_P(X) ARM_REG_OK_FOR_BASE_P (X)
+
+/* For Thumb, a valid index register is anything that can be used in
+ a byte load instruction. */
+#define THUMB_REG_OK_FOR_INDEX_P(X) THUMB_REG_MODE_OK_FOR_BASE_P (X, QImode)
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. On the Thumb, the stack pointer
+ is not suitable. */
+#define REG_OK_FOR_INDEX_P(X) \
+ (TARGET_THUMB \
+ ? THUMB_REG_OK_FOR_INDEX_P (X) \
+ : ARM_REG_OK_FOR_INDEX_P (X))
+
\f
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
/* --------------------------------arm version----------------------------- */
-#define BASE_REGISTER_RTX_P(X) \
- (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))
+#define ARM_BASE_REGISTER_RTX_P(X) \
+ (GET_CODE (X) == REG && ARM_REG_OK_FOR_BASE_P (X))
-#define INDEX_REGISTER_RTX_P(X) \
- (GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
+#define ARM_INDEX_REGISTER_RTX_P(X) \
+ (GET_CODE (X) == REG && ARM_REG_OK_FOR_INDEX_P (X))
/* A C statement (sans semicolon) to jump to LABEL for legitimate index RTXs
used by the macro GO_IF_LEGITIMATE_ADDRESS. Floating point indices can
only be small constants. */
-#define GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL) \
- do \
- { \
- HOST_WIDE_INT range; \
- enum rtx_code code = GET_CODE (INDEX); \
- \
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
- { \
- if (code == CONST_INT && INTVAL (INDEX) < 1024 \
- && INTVAL (INDEX) > -1024 \
- && (INTVAL (INDEX) & 3) == 0) \
- goto LABEL; \
- } \
- else \
- { \
- if (INDEX_REGISTER_RTX_P (INDEX) && GET_MODE_SIZE (MODE) <= 4) \
- goto LABEL; \
- if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \
- && (! arm_arch4 || (MODE) != HImode)) \
- { \
- rtx xiop0 = XEXP (INDEX, 0); \
- rtx xiop1 = XEXP (INDEX, 1); \
- if (INDEX_REGISTER_RTX_P (xiop0) \
- && power_of_two_operand (xiop1, SImode)) \
- goto LABEL; \
- if (INDEX_REGISTER_RTX_P (xiop1) \
- && power_of_two_operand (xiop0, SImode)) \
- goto LABEL; \
- } \
- if (GET_MODE_SIZE (MODE) <= 4 \
- && (code == LSHIFTRT || code == ASHIFTRT \
- || code == ASHIFT || code == ROTATERT) \
- && (! arm_arch4 || (MODE) != HImode)) \
- { \
- rtx op = XEXP (INDEX, 1); \
- if (INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \
- && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 \
- && INTVAL (op) <= 31) \
- goto LABEL; \
- } \
- /* NASTY: Since this limits the addressing of unsigned byte loads */ \
- range = ((MODE) == HImode || (MODE) == QImode) \
- ? (arm_arch4 ? 256 : 4095) : 4096; \
- if (code == CONST_INT && INTVAL (INDEX) < range \
- && INTVAL (INDEX) > -range) \
- goto LABEL; \
- } \
- } \
+#define ARM_GO_IF_LEGITIMATE_INDEX(MODE, BASE_REGNO, INDEX, LABEL) \
+ do \
+ { \
+ HOST_WIDE_INT range; \
+ enum rtx_code code = GET_CODE (INDEX); \
+ \
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ { \
+ if (code == CONST_INT && INTVAL (INDEX) < 1024 \
+ && INTVAL (INDEX) > -1024 \
+ && (INTVAL (INDEX) & 3) == 0) \
+ goto LABEL; \
+ } \
+ else \
+ { \
+ if (ARM_INDEX_REGISTER_RTX_P (INDEX) \
+ && GET_MODE_SIZE (MODE) <= 4) \
+ goto LABEL; \
+ if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \
+ && (! arm_arch4 || (MODE) != HImode)) \
+ { \
+ rtx xiop0 = XEXP (INDEX, 0); \
+ rtx xiop1 = XEXP (INDEX, 1); \
+ if (ARM_INDEX_REGISTER_RTX_P (xiop0) \
+ && power_of_two_operand (xiop1, SImode)) \
+ goto LABEL; \
+ if (ARM_INDEX_REGISTER_RTX_P (xiop1) \
+ && power_of_two_operand (xiop0, SImode)) \
+ goto LABEL; \
+ } \
+ if (GET_MODE_SIZE (MODE) <= 4 \
+ && (code == LSHIFTRT || code == ASHIFTRT \
+ || code == ASHIFT || code == ROTATERT) \
+ && (! arm_arch4 || (MODE) != HImode)) \
+ { \
+ rtx op = XEXP (INDEX, 1); \
+ if (ARM_INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \
+ && GET_CODE (op) == CONST_INT && INTVAL (op) > 0 \
+ && INTVAL (op) <= 31) \
+ goto LABEL; \
+ } \
+ /* NASTY: Since this limits the addressing of unsigned \
+ byte loads. */ \
+ range = ((MODE) == HImode || (MODE) == QImode) \
+ ? (arm_arch4 ? 256 : 4095) : 4096; \
+ if (code == CONST_INT && INTVAL (INDEX) < range \
+ && INTVAL (INDEX) > -range) \
+ goto LABEL; \
+ } \
+ } \
while (0)
-/* 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+REG, REG+INDEX,
- INDEX+REG, REG-INDEX, and non floating SYMBOL_REF to the constant pool.
- Allow REG-only and AUTINC-REG if handling TImode or HImode. Other symbol
- refs must be forced though a static cell to ensure addressability. */
-#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
+/* Jump to LABEL if X is a valid address RTX. This must take
+ REG_OK_STRICT into account when deciding about valid registers.
+
+ Allow REG, REG+REG, REG+INDEX, INDEX+REG, REG-INDEX, and non
+ floating SYMBOL_REF to the constant pool. Allow REG-only and
+ AUTINC-REG if handling TImode or HImode. Other symbol refs must be
+ forced though a static cell to ensure addressability. */
+#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
{ \
- if (BASE_REGISTER_RTX_P (X)) \
+ if (ARM_BASE_REGISTER_RTX_P (X)) \
goto LABEL; \
else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
&& GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
+ && ARM_REG_OK_FOR_BASE_P (XEXP (X, 0))) \
goto LABEL; \
else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
&& (GET_CODE (X) == LABEL_REF \
else if ((MODE) == TImode) \
; \
else if ((MODE) == DImode || (TARGET_SOFT_FLOAT && (MODE) == DFmode)) \
- { \
- if (GET_CODE (X) == PLUS && BASE_REGISTER_RTX_P (XEXP (X, 0)) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
+ { \
+ if (GET_CODE (X) == PLUS && ARM_BASE_REGISTER_RTX_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ { \
+ HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
if (val == 4 || val == -4 || val == -8) \
goto LABEL; \
} \
rtx xop0 = XEXP (X, 0); \
rtx xop1 = XEXP (X, 1); \
\
- if (BASE_REGISTER_RTX_P (xop0)) \
- GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \
- else if (BASE_REGISTER_RTX_P (xop1)) \
- GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
+ if (ARM_BASE_REGISTER_RTX_P (xop0)) \
+ ARM_GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop0), xop1, LABEL); \
+ else if (ARM_BASE_REGISTER_RTX_P (xop1)) \
+ ARM_GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
} \
/* Reload currently can't handle MINUS, so disable this for now */ \
/* else if (GET_CODE (X) == MINUS) \
rtx xop0 = XEXP (X,0); \
rtx xop1 = XEXP (X,1); \
\
- if (BASE_REGISTER_RTX_P (xop0)) \
- GO_IF_LEGITIMATE_INDEX (MODE, -1, xop1, LABEL); \
+ if (ARM_BASE_REGISTER_RTX_P (xop0)) \
+ ARM_GO_IF_LEGITIMATE_INDEX (MODE, -1, xop1, LABEL); \
} */ \
else if (GET_MODE_CLASS (MODE) != MODE_FLOAT \
&& GET_CODE (X) == SYMBOL_REF \
else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC) \
&& (GET_MODE_SIZE (MODE) <= 4) \
&& GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
+ && ARM_REG_OK_FOR_BASE_P (XEXP (X, 0))) \
goto LABEL; \
}
/* ---------------------thumb version----------------------------------*/
-#define LEGITIMATE_OFFSET(MODE, VAL) \
+#define THUMB_LEGITIMATE_OFFSET(MODE, VAL) \
(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
: GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
&& ((VAL) & 1) == 0) \
better ways to solve some of these problems. */
/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
+ addresses based on the frame pointer or arg pointer until the
+ reload pass starts. This is so that eliminating such addresses
+ into stack based ones won't produce impossible code. */
#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN) \
{ \
/* ??? Not clear if this is right. Experiment. */ \
|| reg_mentioned_p (virtual_stack_vars_rtx, X))) \
; \
/* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P (X, MODE)) \
+ else if (GET_CODE (X) == REG \
+ && THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE)) \
goto WIN; \
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
/* Post-inc indexing only supported for SImode and larger. */ \
else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
&& GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
+ && THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
goto WIN; \
else if (GET_CODE (X) == PLUS) \
{ \
&& XEXP (X, 1) != frame_pointer_rtx \
&& XEXP (X, 0) != virtual_stack_vars_rtx \
&& XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
+ && THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
+ && THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
goto WIN; \
/* REG+const has 5-7 bit offset for non-SP registers. */ \
else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
+ && (THUMB_REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
|| XEXP (X, 0) == arg_pointer_rtx) \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
+ && THUMB_LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
goto WIN; \
/* REG+const has 10 bit offset for SP, but only SImode and \
larger is supported. */ \
xop0 = force_reg (SImode, xop0); \
if (CONSTANT_P (xop1) && ! symbol_mentioned_p (xop1)) \
xop1 = force_reg (SImode, xop1); \
- if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \
+ if (ARM_BASE_REGISTER_RTX_P (xop0) \
+ && GET_CODE (xop1) == CONST_INT) \
{ \
HOST_WIDE_INT n, low_n; \
rtx base_reg, val; \
Do not define this if the table should contain absolute addresses. */
/* #define CASE_VECTOR_PC_RELATIVE 1 */
-/* Specify the tree operation to be used to convert reals to integers. */
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-/* This is the kind of divide that is easiest to do in the general case. */
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
/* signed 'char' is most compatible, but RISC OS wants it unsigned.
unsigned is probably best, but may break some code. */
#ifndef DEFAULT_SIGNED_CHAR
in one reasonably fast instruction. */
#define MOVE_MAX 4
+#undef MOVE_RATIO
+#define MOVE_RATIO (arm_is_xscale ? 4 : 2)
+
/* Define if operations between registers always perform the operation
on the full register even if a narrower mode is specified. */
#define WORD_REGISTER_OPERATIONS
((arm_arch4 || (MODE) == QImode) ? ZERO_EXTEND \
: ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : NIL)))
-/* Define this if zero-extension is slow (more than one real instruction).
- On the ARM, it is more than one instruction only if not fetching from
- memory. */
-/* #define SLOW_ZERO_EXTEND */
-
/* Nonzero if access to memory by bytes is slow and undesirable. */
#define SLOW_BYTE_ACCESS 0
conditional instructions */
#define BRANCH_COST \
(TARGET_ARM ? 4 : (optimize > 1 ? 1 : 0))
-
-/* A C statement to update the variable COST based on the relationship
- between INSN that is dependent on DEP through dependence LINK. */
-#define ADJUST_COST(INSN, LINK, DEP, COST) \
- (COST) = arm_adjust_cost (INSN, LINK, DEP, COST)
\f
/* Position Independent Code. */
/* We decide which register to use based on the compilation options and
data addresses in memory. */
#define PIC_OFFSET_TABLE_REGNUM arm_pic_register
-#define FINALIZE_PIC arm_finalize_pic ()
+#define FINALIZE_PIC arm_finalize_pic (1)
/* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */
offset. */
extern int making_const_table;
\f
-/* If defined, a C expression whose value is nonzero if IDENTIFIER
- with arguments ARGS is a valid machine specific attribute for TYPE.
- The attributes in ATTRIBUTES have previously been assigned to TYPE. */
-#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
- (arm_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
-
-/* If defined, a C expression whose value is zero if the attributes on
- TYPE1 and TYPE2 are incompatible, one if they are compatible, and
- two if they are nearly compatible (which causes a warning to be
- generated). */
-#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
- (arm_comp_type_attributes (TYPE1, TYPE2))
-
-/* If defined, a C statement that assigns default attributes to newly
- defined TYPE. */
-#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \
- arm_set_default_type_attributes (TYPE)
-
/* Handle pragmas for compatibility with Intel's compilers. */
#define REGISTER_TARGET_PRAGMAS(PFILE) do { \
cpp_register_pragma (PFILE, 0, "long_calls", arm_pr_long_calls); \
/* This is how to output a label which precedes a jumptable. Since
Thumb instructions are 2 bytes, we may need explicit alignment here. */
+#undef ASM_OUTPUT_CASE_LABEL
#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE) \
do \
{ \
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL1, DECL2) \
do \
{ \
- char * LABEL1 = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
- char * LABEL2 = IDENTIFIER_POINTER (DECL2); \
+ const char *const LABEL1 = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
+ const char *const LABEL2 = IDENTIFIER_POINTER (DECL2); \
\
if (TARGET_THUMB && TREE_CODE (DECL1) == FUNCTION_DECL) \
{ \
} \
while (0)
-/* Target characters. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+/* To support -falign-* switches we need to use .p2align so
+ that alignment directives in code sections will be padded
+ with no-op instructions, rather than zeroes. */
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ if ((LOG) != 0) \
+ { \
+ if ((MAX_SKIP) == 0) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", \
+ (LOG), (MAX_SKIP)); \
+ }
+#endif
\f
/* Only perform branch elimination (by making instructions conditional) if
we're optimising. Otherwise it's of no use anyway. */
#define PRINT_OPERAND(STREAM, X, CODE) \
arm_print_operand (STREAM, X, CODE)
-/* Create an [unsigned] host sized integer declaration that
- avoids compiler warnings. */
-#ifdef __STDC__
-#define HOST_INT(x) ((signed HOST_WIDE_INT) x##UL)
-#define HOST_UINT(x) ((unsigned HOST_WIDE_INT) x##UL)
-#else
-#define HOST_INT(x) ((HOST_WIDE_INT) x)
-#define HOST_UINT(x) ((unsigned HOST_WIDE_INT) x)
-#endif
-
-#define ARM_SIGN_EXTEND(x) ((HOST_WIDE_INT) \
- (HOST_BITS_PER_WIDE_INT <= 32 ? (x) \
- : (((x) & HOST_UINT (0xffffffff)) | \
- (((x) & HOST_UINT (0x80000000)) \
- ? ((~ HOST_INT (0)) \
- & ~ HOST_UINT(0xffffffff)) \
+#define ARM_SIGN_EXTEND(x) ((HOST_WIDE_INT) \
+ (HOST_BITS_PER_WIDE_INT <= 32 ? (unsigned HOST_WIDE_INT) (x) \
+ : ((((unsigned HOST_WIDE_INT)(x)) & (unsigned HOST_WIDE_INT) 0xffffffff) |\
+ ((((unsigned HOST_WIDE_INT)(x)) & (unsigned HOST_WIDE_INT) 0x80000000) \
+ ? ((~ (unsigned HOST_WIDE_INT) 0) \
+ & ~ (unsigned HOST_WIDE_INT) 0xffffffff) \
: 0))))
/* Output the address of an operand. */
else \
THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
-/* Handles PIC addr specially */
-#define OUTPUT_INT_ADDR_CONST(STREAM, X) \
- { \
- if (flag_pic && GET_CODE (X) == CONST && is_pic (X)) \
- { \
- output_addr_const (STREAM, XEXP (XEXP (XEXP (X, 0), 0), 0)); \
- fputs (" - (", STREAM); \
- output_addr_const (STREAM, XEXP (XEXP (XEXP (X, 0), 1), 0)); \
- fputs (")", STREAM); \
- } \
- else \
- output_addr_const (STREAM, X); \
- \
- /* Mark symbols as position independent. We only do this in the \
- .text segment, not in the .data segment. */ \
- if (NEED_GOT_RELOC && flag_pic && making_const_table && \
- (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF)) \
- { \
- if (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X)) \
- fprintf (STREAM, "(GOTOFF)"); \
- else if (GET_CODE (X) == LABEL_REF) \
- fprintf (STREAM, "(GOTOFF)"); \
- else \
- fprintf (STREAM, "(GOT)"); \
- } \
- }
-
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
Used for C++ multiple inheritance. */
#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
do \
{ \
int mi_delta = (DELTA); \
- const char * mi_op = mi_delta < 0 ? "sub" : "add"; \
+ const char *const mi_op = mi_delta < 0 ? "sub" : "add"; \
int shift = 0; \
int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) \
? 1 : 0); \
/* Define the codes that are matched by predicates in arm.c */
#define PREDICATE_CODES \
{"s_register_operand", {SUBREG, REG}}, \
+ {"arm_hard_register_operand", {REG}}, \
{"f_register_operand", {SUBREG, REG}}, \
{"arm_add_operand", {SUBREG, REG, CONST_INT}}, \
{"fpu_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \
#define SPECIAL_MODE_PREDICATES \
"cc_register", "dominant_cc_register",
-#endif /* __ARM_H__ */
+enum arm_builtins
+{
+ ARM_BUILTIN_CLZ,
+ ARM_BUILTIN_MAX
+};
+#endif /* ! GCC_ARM_H */