summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config/arm
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
committerkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
commitb2a8872fbe1ec1c49094559ac7b78e6ea4ab7180 (patch)
treef6b0610f4a17fd26aa234354f050080f789861a4 /contrib/gcc/config/arm
parent52e69d78eee5612ac195e0701a5cebe40d1ab0e1 (diff)
downloadFreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.zip
FreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.tar.gz
Gcc 3.3.1-pre as of 2003-07-11.
Diffstat (limited to 'contrib/gcc/config/arm')
-rw-r--r--contrib/gcc/config/arm/README-interworking2
-rw-r--r--contrib/gcc/config/arm/aof.h12
-rw-r--r--contrib/gcc/config/arm/aout.h27
-rw-r--r--contrib/gcc/config/arm/arm-modes.def46
-rw-r--r--contrib/gcc/config/arm/arm-protos.h21
-rw-r--r--contrib/gcc/config/arm/arm.c810
-rw-r--r--contrib/gcc/config/arm/arm.h373
-rw-r--r--contrib/gcc/config/arm/arm.md321
-rw-r--r--contrib/gcc/config/arm/coff.h38
-rw-r--r--contrib/gcc/config/arm/conix-elf.h8
-rw-r--r--contrib/gcc/config/arm/crti.asm2
-rw-r--r--contrib/gcc/config/arm/crtn.asm2
-rw-r--r--contrib/gcc/config/arm/elf.h55
-rw-r--r--contrib/gcc/config/arm/freebsd.h3
-rw-r--r--contrib/gcc/config/arm/linux-elf.h22
-rw-r--r--contrib/gcc/config/arm/linux-gas.h2
-rw-r--r--contrib/gcc/config/arm/netbsd-elf.h177
-rw-r--r--contrib/gcc/config/arm/netbsd.h54
-rw-r--r--contrib/gcc/config/arm/pe.c24
-rw-r--r--contrib/gcc/config/arm/pe.h31
-rw-r--r--contrib/gcc/config/arm/rtems-elf.h8
-rw-r--r--contrib/gcc/config/arm/semi.h4
-rw-r--r--contrib/gcc/config/arm/semiaof.h7
-rw-r--r--contrib/gcc/config/arm/t-arm-elf6
-rw-r--r--contrib/gcc/config/arm/t-pe3
-rw-r--r--contrib/gcc/config/arm/unknown-elf-oabi.h5
-rw-r--r--contrib/gcc/config/arm/unknown-elf.h10
-rw-r--r--contrib/gcc/config/arm/vxarm.h6
-rw-r--r--contrib/gcc/config/arm/xscale-coff.h2
-rw-r--r--contrib/gcc/config/arm/xscale-elf.h2
30 files changed, 1223 insertions, 860 deletions
diff --git a/contrib/gcc/config/arm/README-interworking b/contrib/gcc/config/arm/README-interworking
index 46b76c9..de8b278 100644
--- a/contrib/gcc/config/arm/README-interworking
+++ b/contrib/gcc/config/arm/README-interworking
@@ -235,7 +235,7 @@ processing is enabled.
When the -mthumb-interwork command line switch is specified, gcc
arranges for all functions to return to their caller by using the BX
instruction. Thus provided that the return address has the bottom bit
-correctly initialised to indicate the instruction set of the caller,
+correctly initialized to indicate the instruction set of the caller,
correct operation will ensue.
When a function is called explicitly (rather than via a function
diff --git a/contrib/gcc/config/arm/aof.h b/contrib/gcc/config/arm/aof.h
index f110ea2..965337c 100644
--- a/contrib/gcc/config/arm/aof.h
+++ b/contrib/gcc/config/arm/aof.h
@@ -54,8 +54,6 @@ Boston, MA 02111-1307, USA. */
addressing across such boundaries. */
#define TEXT_SECTION_ASM_OP aof_text_section ()
-#define SELECT_RTX_SECTION(MODE,RTX,ALIGN) text_section ();
-
#define DATA_SECTION_ASM_OP aof_data_section ()
#define EXTRA_SECTIONS in_zero_init, in_common
@@ -222,14 +220,8 @@ do \
extern int arm_main_function;
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
-do { \
- fprintf ((STREAM), "\tEXPORT\t"); \
- assemble_name ((STREAM), (NAME)); \
- fputc ('\n', (STREAM)); \
- if ((NAME)[0] == 'm' && ! strcmp ((NAME), "main")) \
- arm_main_function = 1; \
-} while (0)
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\tEXPORT\t"
#define ASM_OUTPUT_LABEL(STREAM,NAME) \
do { \
diff --git a/contrib/gcc/config/arm/aout.h b/contrib/gcc/config/arm/aout.h
index 868eee0..8f4a605 100644
--- a/contrib/gcc/config/arm/aout.h
+++ b/contrib/gcc/config/arm/aout.h
@@ -111,9 +111,7 @@ Boston, MA 02111-1307, USA. */
/* Generate DBX debugging information. riscix.h will undefine this because
the native assembler does not support stabs. */
-#ifndef DBX_DEBUGGING_INFO
-#define DBX_DEBUGGING_INFO 1
-#endif
+#define DBX_DEBUGGING_INFO 1
/* Acorn dbx moans about continuation chars, so don't use any. */
#ifndef DBX_CONTIN_LENGTH
@@ -144,27 +142,8 @@ Boston, MA 02111-1307, USA. */
while (0)
#endif
-#ifndef ASM_OUTPUT_LABEL
-#define ASM_OUTPUT_LABEL(STREAM, NAME) \
- do \
- { \
- assemble_name (STREAM,NAME); \
- fputs (":\n", STREAM); \
- } \
- while (0)
-#endif
-
-/* Output a globalising directive for a label. */
-#ifndef ASM_GLOBALIZE_LABEL
-#define ASM_GLOBALIZE_LABEL(STREAM, NAME) \
- do \
- { \
- fprintf (STREAM, "\t.global\t"); \
- assemble_name (STREAM, NAME); \
- fputc ('\n',STREAM); \
- } \
- while (0)
-#endif
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.global\t"
/* Make an internal label into a string. */
#ifndef ASM_GENERATE_INTERNAL_LABEL
diff --git a/contrib/gcc/config/arm/arm-modes.def b/contrib/gcc/config/arm/arm-modes.def
new file mode 100644
index 0000000..48f9ddf
--- /dev/null
+++ b/contrib/gcc/config/arm/arm-modes.def
@@ -0,0 +1,46 @@
+/* Definitions of target machine for GNU compiler, for ARM.
+ Copyright (C) 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)
+ Minor hacks by Nick Clifton (nickc@cygnus.com)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* CCFPEmode should be used with floating inequalities,
+ CCFPmode should be used with floating equalities.
+ CC_NOOVmode should be used with SImode integer equalities.
+ CC_Zmode should be used if only the Z flag is set correctly
+ CCmode should be used otherwise. */
+
+CC (CC_NOOV)
+CC (CC_Z)
+CC (CC_SWP)
+CC (CCFP)
+CC (CCFPE)
+CC (CC_DNE)
+CC (CC_DEQ)
+CC (CC_DLE)
+CC (CC_DLT)
+CC (CC_DGE)
+CC (CC_DGT)
+CC (CC_DLEU)
+CC (CC_DLTU)
+CC (CC_DGEU)
+CC (CC_DGTU)
+CC (CC_C)
diff --git a/contrib/gcc/config/arm/arm-protos.h b/contrib/gcc/config/arm/arm-protos.h
index b42da82..cae9bea 100644
--- a/contrib/gcc/config/arm/arm-protos.h
+++ b/contrib/gcc/config/arm/arm-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in arm.c and pe.c
- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@arm.com)
Minor hacks by Nick Clifton (nickc@cygnus.com)
@@ -31,9 +31,11 @@ extern void arm_finalize_pic PARAMS ((int));
extern int arm_volatile_func PARAMS ((void));
extern const char * arm_output_epilogue PARAMS ((int));
extern void arm_expand_prologue PARAMS ((void));
+extern HOST_WIDE_INT arm_get_frame_size PARAMS ((void));
/* Used in arm.md, but defined in output.c. */
extern void assemble_align PARAMS ((int));
extern const char * arm_strip_name_encoding PARAMS ((const char *));
+extern void arm_asm_output_labelref PARAMS ((FILE *, const char *));
extern unsigned long arm_current_func_type PARAMS ((void));
extern unsigned int arm_compute_initial_elimination_offset PARAMS ((unsigned int, unsigned int));
@@ -43,7 +45,8 @@ extern void arm_encode_call_attribute PARAMS ((tree, int));
extern int arm_function_ok_for_sibcall PARAMS ((tree));
#endif
#ifdef RTX_CODE
-extern int arm_hard_regno_mode_ok PARAMS ((unsigned int, enum machine_mode));
+extern int arm_hard_regno_mode_ok PARAMS ((unsigned int,
+ enum machine_mode));
extern int const_ok_for_arm PARAMS ((HOST_WIDE_INT));
extern int arm_split_constant PARAMS ((RTX_CODE, enum machine_mode,
HOST_WIDE_INT, rtx, rtx, int));
@@ -106,6 +109,7 @@ extern int arm_gen_movstrqi PARAMS ((rtx *));
extern rtx arm_gen_rotated_half_load PARAMS ((rtx));
extern enum machine_mode arm_select_cc_mode PARAMS ((RTX_CODE, rtx, rtx));
extern rtx arm_gen_compare_reg PARAMS ((RTX_CODE, rtx, rtx));
+extern rtx arm_gen_return_addr_mask PARAMS ((void));
extern void arm_reload_in_hi PARAMS ((rtx *));
extern void arm_reload_out_hi PARAMS ((rtx *));
extern void arm_reorg PARAMS ((rtx));
@@ -121,7 +125,8 @@ extern const char * output_move_double PARAMS ((rtx *));
extern const char * output_mov_immediate PARAMS ((rtx *));
extern const char * output_add_immediate PARAMS ((rtx *));
extern const char * arithmetic_instr PARAMS ((rtx, int));
-extern void output_ascii_pseudo_op PARAMS ((FILE *, const unsigned char *, int));
+extern void output_ascii_pseudo_op PARAMS ((FILE *, const unsigned char *,
+ int));
extern const char * output_return_instruction PARAMS ((rtx, int, int));
extern void arm_poke_function_name PARAMS ((FILE *, const char *));
extern void arm_print_operand PARAMS ((FILE *, rtx, int));
@@ -136,6 +141,11 @@ extern rtx arm_function_arg PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode, tree, int));
extern void arm_init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx,
int));
+extern rtx arm_va_arg PARAMS ((tree, tree));
+extern int arm_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
+ enum machine_mode,
+ tree, int));
+
#endif
#if defined AOF_ASSEMBLER
@@ -152,10 +162,13 @@ extern void common_section PARAMS ((void));
#endif /* RTX_CODE */
+extern int arm_float_words_big_endian PARAMS ((void));
+
/* Thumb functions. */
extern void arm_init_expanders PARAMS ((void));
extern int thumb_far_jump_used_p PARAMS ((int));
extern const char * thumb_unexpanded_epilogue PARAMS ((void));
+extern HOST_WIDE_INT thumb_get_frame_size PARAMS ((void));
extern void thumb_expand_prologue PARAMS ((void));
extern void thumb_expand_epilogue PARAMS ((void));
#ifdef TREE_CODE
@@ -185,7 +198,7 @@ extern int arm_dllimport_name_p PARAMS ((const char *));
#ifdef TREE_CODE
extern void arm_pe_unique_section PARAMS ((tree, int));
-extern void arm_pe_encode_section_info PARAMS ((tree));
+extern void arm_pe_encode_section_info PARAMS ((tree, int));
extern int arm_dllexport_p PARAMS ((tree));
extern int arm_dllimport_p PARAMS ((tree));
extern void arm_mark_dllexport PARAMS ((tree));
diff --git a/contrib/gcc/config/arm/arm.c b/contrib/gcc/config/arm/arm.c
index 8c696c6..7422f1d 100644
--- a/contrib/gcc/config/arm/arm.c
+++ b/contrib/gcc/config/arm/arm.c
@@ -65,9 +65,8 @@ const struct attribute_spec arm_attribute_table[];
/* Forward function declarations. */
static void arm_add_gc_roots PARAMS ((void));
static int arm_gen_constant PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));
-static Ulong bit_count PARAMS ((signed int));
+static unsigned bit_count PARAMS ((Ulong));
static int const_ok_for_op PARAMS ((Hint, enum rtx_code));
-static int eliminate_lr2ip PARAMS ((rtx *));
static rtx emit_multi_reg_push PARAMS ((int));
static rtx emit_sfm PARAMS ((int, int));
#ifndef AOF_ASSEMBLER
@@ -82,9 +81,7 @@ static Ccstar output_multi_immediate PARAMS ((rtx *, Ccstar, Ccstar, int, Hi
static void print_multi_reg PARAMS ((FILE *, Ccstar, int, int));
static Mmode select_dominance_cc_mode PARAMS ((rtx, rtx, Hint));
static Ccstar shift_op PARAMS ((rtx, Hint *));
-static void arm_init_machine_status PARAMS ((struct function *));
-static void arm_mark_machine_status PARAMS ((struct function *));
-static void arm_free_machine_status PARAMS ((struct function *));
+static struct machine_function * arm_init_machine_status PARAMS ((void));
static int number_of_first_bit_set PARAMS ((int));
static void replace_symbols_in_block PARAMS ((tree, rtx, rtx));
static void thumb_exit PARAMS ((FILE *, int, rtx));
@@ -117,9 +114,20 @@ static void thumb_output_function_prologue PARAMS ((FILE *, Hint));
static int arm_comp_type_attributes PARAMS ((tree, tree));
static void arm_set_default_type_attributes PARAMS ((tree));
static int arm_adjust_cost PARAMS ((rtx, rtx, rtx, int));
+static int count_insns_for_constant PARAMS ((HOST_WIDE_INT, int));
+static int arm_get_strip_length PARAMS ((int));
#ifdef OBJECT_FORMAT_ELF
static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#endif
+#ifndef ARM_PE
+static void arm_encode_section_info PARAMS ((tree, int));
+#endif
+#ifdef AOF_ASSEMBLER
+static void aof_globalize_label PARAMS ((FILE *, const char *));
+#endif
+static void arm_output_mi_thunk PARAMS ((FILE *, tree,
+ HOST_WIDE_INT,
+ HOST_WIDE_INT, tree));
#undef Hint
#undef Mmode
@@ -142,6 +150,8 @@ static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#define TARGET_ASM_ALIGNED_HI_OP "\tDCW\t"
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP "\tDCD\t"
+#undef TARGET_ASM_GLOBALIZE_LABEL
+#define TARGET_ASM_GLOBALIZE_LABEL aof_globalize_label
#else
#undef TARGET_ASM_ALIGNED_SI_OP
#define TARGET_ASM_ALIGNED_SI_OP NULL
@@ -170,15 +180,27 @@ static void arm_elf_asm_named_section PARAMS ((const char *, unsigned int));
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
+#undef TARGET_ENCODE_SECTION_INFO
+#ifdef ARM_PE
+#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
+#else
+#define TARGET_ENCODE_SECTION_INFO arm_encode_section_info
+#endif
+
+#undef TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING arm_strip_name_encoding
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
static struct obstack minipool_obstack;
static char * minipool_startobj;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* The maximum number of insns skipped which
will be conditionalised if possible. */
static int max_insns_skipped = 5;
@@ -223,13 +245,13 @@ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
/* The bits in this mask specify which
instructions we are allowed to generate. */
-static int insn_flags = 0;
+static unsigned long insn_flags = 0;
/* The bits in this mask specify which instruction scheduling options should
be used. Note - there is an overlap with the FL_FAST_MULT. For some
hardware we want to be able to generate the multiply instructions, but to
tune as if they were not present in the architecture. */
-static int tune_flags = 0;
+static unsigned long tune_flags = 0;
/* The following are used in the arm.md file as equivalents to bits
in the above two flag variables. */
@@ -301,7 +323,7 @@ static const char * const arm_condition_codes[] =
struct processors
{
const char *const name;
- const unsigned int flags;
+ const unsigned long flags;
};
/* Not all of these give usefully different compilation alternatives,
@@ -355,7 +377,7 @@ static const struct processors all_cores[] =
{"arm10tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
{"arm1020t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
{"xscale", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE },
-
+
{NULL, 0}
};
@@ -389,17 +411,17 @@ struct arm_cpu_select arm_select[] =
{ NULL, "-mtune=", all_cores }
};
-/* Return the number of bits set in value' */
-static unsigned long
+/* Return the number of bits set in VALUE. */
+static unsigned
bit_count (value)
- signed int value;
+ unsigned long value;
{
unsigned long count = 0;
while (value)
{
- value &= ~(value & -value);
- ++count;
+ count++;
+ value &= value - 1; /* Clear the least-significant set bit. */
}
return count;
@@ -526,7 +548,7 @@ arm_override_options ()
if (sel->name == NULL)
{
- unsigned int current_bit_count = 0;
+ unsigned current_bit_count = 0;
const struct processors * best_fit = NULL;
/* Ideally we would like to issue an error message here
@@ -545,7 +567,7 @@ arm_override_options ()
for (sel = all_cores; sel->name != NULL; sel++)
if ((sel->flags & sought) == sought)
{
- unsigned int count;
+ unsigned count;
count = bit_count (sel->flags & insn_flags);
@@ -570,7 +592,7 @@ arm_override_options ()
architecture has been selected. */
if (tune_flags == 0)
tune_flags = insn_flags;
-
+
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
if (TARGET_APCS_32 && !(insn_flags & FL_MODE32))
@@ -657,7 +679,7 @@ arm_override_options ()
if (TARGET_APCS_FLOAT)
warning ("passing floating point arguments in fp regs not yet supported");
- /* Initialise boolean versions of the flags, for use in the arm.md file. */
+ /* Initialize boolean versions of the flags, for use in the arm.md file. */
arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch5 = (insn_flags & FL_ARCH5) != 0;
@@ -714,7 +736,7 @@ arm_override_options ()
if (arm_pic_register_string != NULL)
{
int pic_register = decode_reg_name (arm_pic_register_string);
-
+
if (!flag_pic)
warning ("-mpic-register= is useless without -fpic");
@@ -759,10 +781,6 @@ arm_override_options ()
static void
arm_add_gc_roots ()
{
- ggc_add_rtx_root (&arm_compare_op0, 1);
- ggc_add_rtx_root (&arm_compare_op1, 1);
- ggc_add_rtx_root (&arm_target_insn, 1); /* Not sure this is really a root. */
-
gcc_obstack_init(&minipool_obstack);
minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
}
@@ -820,7 +838,7 @@ arm_isr_value (argument)
if (streq (arg, ptr->arg))
return ptr->return_value;
- /* An unrecognised interrupt type. */
+ /* An unrecognized interrupt type. */
return ARM_FT_UNKNOWN;
}
@@ -902,6 +920,10 @@ use_return_insn (iscond)
consideration. */
if (func_type & (ARM_FT_VOLATILE | ARM_FT_NAKED))
return 0;
+
+ /* So do interrupt functions that use the frame pointer. */
+ if (IS_INTERRUPT (func_type) && frame_pointer_needed)
+ return 0;
/* As do variadic functions. */
if (current_function_pretend_args_size
@@ -909,7 +931,7 @@ use_return_insn (iscond)
/* Of if the function calls __builtin_eh_return () */
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
/* Or if there is no frame pointer and there is a stack adjustment. */
- || ((get_frame_size () + current_function_outgoing_args_size != 0)
+ || ((arm_get_frame_size () + current_function_outgoing_args_size != 0)
&& !frame_pointer_needed))
return 0;
@@ -1032,7 +1054,7 @@ arm_split_constant (code, mode, val, target, source, subtargets)
&& REGNO (target) != REGNO (source)))
{
/* After arm_reorg has been called, we can't fix up expensive
- constants by pushing them into memory so we must synthesise
+ constants by pushing them into memory so we must synthesize
them in-line, regardless of the cost. This is only likely to
be more costly on chips that have load delay slots and we are
compiling without running the scheduler (so no splitting
@@ -1073,7 +1095,9 @@ arm_split_constant (code, mode, val, target, source, subtargets)
}
static int
-count_insns_for_constant (HOST_WIDE_INT remainder, int i)
+count_insns_for_constant (remainder, i)
+ HOST_WIDE_INT remainder;
+ int i;
{
HOST_WIDE_INT temp1;
int num_insns = 0;
@@ -1752,9 +1776,20 @@ int
arm_return_in_memory (type)
tree type;
{
+ HOST_WIDE_INT size;
+
if (!AGGREGATE_TYPE_P (type))
/* All simple types are returned in registers. */
return 0;
+
+ size = int_size_in_bytes (type);
+
+ if (TARGET_ATPCS)
+ {
+ /* ATPCS returns aggregate types in memory only if they are
+ larger than a word (or are variable size). */
+ return (size < 0 || size > UNITS_PER_WORD);
+ }
/* For the arm-wince targets we choose to be compitable with Microsoft's
ARM and Thumb compilers, which always return aggregates in memory. */
@@ -1763,7 +1798,7 @@ arm_return_in_memory (type)
Also catch the case where int_size_in_bytes returns -1. In this case
the aggregate is either huge or of varaible size, and in either case
we will want to return it via memory and not in a register. */
- if (((unsigned int) int_size_in_bytes (type)) > UNITS_PER_WORD)
+ if (size < 0 || size > UNITS_PER_WORD)
return 1;
if (TREE_CODE (type) == RECORD_TYPE)
@@ -1841,6 +1876,27 @@ arm_return_in_memory (type)
return 1;
}
+/* Indicate whether or not words of a double are in big-endian order. */
+
+int
+arm_float_words_big_endian ()
+{
+
+ /* For FPA, float words are always big-endian. For VFP, floats words
+ follow the memory system mode. */
+
+ if (TARGET_HARD_FLOAT)
+ {
+ /* FIXME: TARGET_HARD_FLOAT currently implies FPA. */
+ return 1;
+ }
+
+ if (TARGET_VFP)
+ return (TARGET_BIG_END ? 1 : 0);
+
+ return 1;
+}
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is NULL. */
@@ -1899,6 +1955,35 @@ arm_function_arg (pcum, mode, type, named)
return gen_rtx_REG (mode, pcum->nregs);
}
+
+/* Variable sized types are passed by reference. This is a GCC
+ extension to the ARM ABI. */
+
+int
+arm_function_arg_pass_by_reference (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type;
+ int named ATTRIBUTE_UNUSED;
+{
+ return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+}
+
+/* Implement va_arg. */
+
+rtx
+arm_va_arg (valist, type)
+ tree valist, type;
+{
+ /* Variable sized types are passed by reference. */
+ if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ {
+ rtx addr = std_expand_builtin_va_arg (valist, build_pointer_type (type));
+ return gen_rtx_MEM (ptr_mode, force_reg (Pmode, addr));
+ }
+
+ return std_expand_builtin_va_arg (valist, type);
+}
/* Encode the current state of the #pragma [no_]long_calls. */
typedef enum
@@ -2171,7 +2256,7 @@ current_file_function_operand (sym_ref)
return 0;
}
-/* Return non-zero if a 32 bit "long_call" should be generated for
+/* Return nonzero if a 32 bit "long_call" should be generated for
this call. We generate a long_call if the function:
a. has an __attribute__((long call))
@@ -2224,7 +2309,7 @@ arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
|| TARGET_LONG_CALLS;
}
-/* Return non-zero if it is ok to make a tail-call to DECL. */
+/* Return nonzero if it is ok to make a tail-call to DECL. */
int
arm_function_ok_for_sibcall (decl)
@@ -2442,7 +2527,7 @@ arm_finalize_pic (prologue)
emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
}
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
if (prologue)
emit_insn_after (seq, get_insns ());
@@ -2558,7 +2643,8 @@ arm_rtx_costs (x, code, outer)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
+ + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ ? 4 : 0));
case IF_THEN_ELSE:
/* XXX a guess. */
@@ -2606,7 +2692,8 @@ arm_rtx_costs (x, code, outer)
/* Memory costs quite a lot for the first word, but subsequent words
load at the equivalent of a single insn each. */
return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + (CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
+ + (GET_CODE (x) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (x) ? 4 : 0));
case DIV:
case MOD:
@@ -2914,16 +3001,16 @@ arm_adjust_cost (insn, link, dep, cost)
&& (d_pat = single_set (dep)) != NULL
&& GET_CODE (SET_DEST (d_pat)) == MEM)
{
+ rtx src_mem = XEXP (SET_SRC (i_pat), 0);
/* This is a load after a store, there is no conflict if the load reads
from a cached area. Assume that loads from the stack, and from the
constant pool are cached, and that others will miss. This is a
hack. */
- if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0))
- || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
- || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
- || reg_mentioned_p (hard_frame_pointer_rtx,
- XEXP (SET_SRC (i_pat), 0)))
+ if ((GET_CODE (src_mem) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (src_mem))
+ || reg_mentioned_p (stack_pointer_rtx, src_mem)
+ || reg_mentioned_p (frame_pointer_rtx, src_mem)
+ || reg_mentioned_p (hard_frame_pointer_rtx, src_mem))
return 1;
}
@@ -4319,7 +4406,7 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
if (write_back)
emit_move_insn (from, plus_constant (from, count * 4 * sign));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
@@ -4386,7 +4473,7 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
if (write_back)
emit_move_insn (to, plus_constant (to, count * 4 * sign));
- seq = gen_sequence ();
+ seq = get_insns ();
end_sequence ();
return seq;
@@ -4449,7 +4536,7 @@ arm_gen_movstrqi (operands)
fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
fin_src = src = copy_to_mode_reg (SImode, st_src);
- in_words_to_go = NUM_INTS (INTVAL (operands[2]));
+ in_words_to_go = ARM_NUM_INTS (INTVAL (operands[2]));
out_words_to_go = INTVAL (operands[2]) / 4;
last_bytes = INTVAL (operands[2]) & 3;
@@ -4876,6 +4963,19 @@ arm_gen_compare_reg (code, x, y)
return cc_reg;
}
+/* Generate a sequence of insns that will generate the correct return
+ address mask depending on the physical architecture that the program
+ is running on. */
+
+rtx
+arm_gen_return_addr_mask ()
+{
+ rtx reg = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_return_addr_mask (reg));
+ return reg;
+}
+
void
arm_reload_in_hi (operands)
rtx * operands;
@@ -4956,7 +5056,14 @@ arm_reload_in_hi (operands)
}
}
- scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+ /* Operands[2] may overlap operands[0] (though it won't overlap
+ operands[1]), that's why we asked for a DImode reg -- so we can
+ use the bit that does not overlap. */
+ if (REGNO (operands[2]) == REGNO (operands[0]))
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
+ else
+ scratch = gen_rtx_REG (SImode, REGNO (operands[2]));
+
emit_insn (gen_zero_extendqisi2 (scratch,
gen_rtx_MEM (QImode,
plus_constant (base,
@@ -5349,7 +5456,7 @@ get_jump_table_size (insn)
/* ADDR_VECs only take room if read-only data does into the text
section. */
if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION)
+#if !defined(READONLY_DATA_SECTION) && !defined(READONLY_DATA_SECTION_ASM_OP)
|| 1
#endif
)
@@ -6322,57 +6429,27 @@ output_call (operands)
return "";
}
-static int
-eliminate_lr2ip (x)
- rtx * x;
-{
- int something_changed = 0;
- rtx x0 = * x;
- int code = GET_CODE (x0);
- int i, j;
- const char * fmt;
-
- switch (code)
- {
- case REG:
- if (REGNO (x0) == LR_REGNUM)
- {
- *x = gen_rtx_REG (SImode, IP_REGNUM);
- return 1;
- }
- return 0;
- default:
- /* Scan through the sub-elements and change any references there. */
- fmt = GET_RTX_FORMAT (code);
-
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- something_changed |= eliminate_lr2ip (&XEXP (x0, i));
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x0, i); j++)
- something_changed |= eliminate_lr2ip (&XVECEXP (x0, i, j));
-
- return something_changed;
- }
-}
-
/* Output a 'call' insn that is a reference in memory. */
const char *
output_call_mem (operands)
rtx * operands;
{
- operands[0] = copy_rtx (operands[0]); /* Be ultra careful. */
- /* Handle calls using lr by using ip (which may be clobbered in subr anyway). */
- if (eliminate_lr2ip (&operands[0]))
- output_asm_insn ("mov%?\t%|ip, %|lr", operands);
-
if (TARGET_INTERWORK)
{
output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
output_asm_insn ("bx%?\t%|ip", operands);
}
+ else if (regno_use_in (LR_REGNUM, operands[0]))
+ {
+ /* LR is used in the memory address. We load the address in the
+ first instruction. It's safe to use IP as the target of the
+ load since the call will kill it anyway. */
+ output_asm_insn ("ldr%?\t%|ip, %0", operands);
+ output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+ output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+ }
else
{
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@@ -6543,11 +6620,11 @@ output_move_double (operands)
{
if (GET_MODE (operands[1]) == DFmode)
{
+ REAL_VALUE_TYPE r;
long l[2];
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[1]), sizeof (u));
- REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+ REAL_VALUE_TO_TARGET_DOUBLE (r, l);
otherops[1] = GEN_INT (l[1]);
operands[1] = GEN_INT (l[0]);
}
@@ -6666,7 +6743,7 @@ output_move_double (operands)
}
else
{
- otherops[1] = adjust_address (operands[1], VOIDmode, 4);
+ otherops[1] = adjust_address (operands[1], SImode, 4);
/* Take care of overlapping base/data reg. */
if (reg_mentioned_p (operands[0], operands[1]))
{
@@ -6732,7 +6809,7 @@ output_move_double (operands)
/* Fall through */
default:
- otherops[0] = adjust_address (operands[0], VOIDmode, 4);
+ otherops[0] = adjust_address (operands[0], SImode, 4);
otherops[1] = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
output_asm_insn ("str%?\t%1, %0", operands);
output_asm_insn ("str%?\t%1, %0", otherops);
@@ -7190,7 +7267,7 @@ output_return_instruction (operand, really_return, reverse)
int reg;
unsigned long live_regs_mask;
unsigned long func_type;
-
+
func_type = arm_current_func_type ();
if (IS_NAKED (func_type))
@@ -7218,7 +7295,6 @@ output_return_instruction (operand, really_return, reverse)
if (current_function_calls_alloca && !really_return)
abort ();
- /* Construct the conditional part of the instruction(s) to be emitted. */
sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
return_used_this_function = 1;
@@ -7275,6 +7351,8 @@ output_return_instruction (operand, really_return, reverse)
/* Generate the load multiple instruction to restore the registers. */
if (frame_pointer_needed)
sprintf (instr, "ldm%sea\t%%|fp, {", conditional);
+ else if (live_regs_mask & (1 << SP_REGNUM))
+ sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
else
sprintf (instr, "ldm%sfd\t%%|sp!, {", conditional);
@@ -7332,7 +7410,7 @@ output_return_instruction (operand, really_return, reverse)
really_return = 0;
}
}
-
+
if (really_return)
{
switch ((int) ARM_FUNC_TYPE (func_type))
@@ -7495,7 +7573,7 @@ arm_output_epilogue (really_return)
frame that is $fp + 4 for a non-variadic function. */
int floats_offset = 0;
rtx operands[3];
- int frame_size = get_frame_size ();
+ int frame_size = arm_get_frame_size ();
FILE * f = asm_out_file;
rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
@@ -7612,7 +7690,7 @@ arm_output_epilogue (really_return)
if (IS_INTERRUPT (func_type))
/* Interrupt handlers will have pushed the
IP onto the stack, so restore it now. */
- print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, 1 << IP_REGNUM);
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, 1 << IP_REGNUM);
}
else
{
@@ -7686,7 +7764,16 @@ arm_output_epilogue (really_return)
asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
}
else if (saved_regs_mask)
- print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+ {
+ if (saved_regs_mask & (1 << SP_REGNUM))
+ /* Note - write back to the stack register is not enabled
+ (ie "ldmfd sp!..."). We know that the stack pointer is
+ in the list of registers and if we add writeback the
+ instruction becomes UNPREDICTABLE. */
+ print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
+ else
+ print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+ }
if (current_function_pretend_args_size)
{
@@ -7734,7 +7821,7 @@ arm_output_epilogue (really_return)
default:
if (frame_pointer_needed)
- /* If we used the frame pointer then the return adddress
+ /* If we used the frame pointer then the return address
will have been loaded off the stack directly into the
PC, so there is no need to issue a MOV instruction
here. */
@@ -7768,6 +7855,9 @@ arm_output_function_epilogue (file, frame_size)
}
else
{
+ /* We need to take into account any stack-frame rounding. */
+ frame_size = arm_get_frame_size ();
+
if (use_return_insn (FALSE)
&& return_used_this_function
&& (frame_size + current_function_outgoing_args_size) != 0
@@ -7809,7 +7899,7 @@ emit_multi_reg_push (mask)
num_dwarf_regs--;
/* For the body of the insn we are going to generate an UNSPEC in
- parallel with several USEs. This allows the insn to be recognised
+ parallel with several USEs. This allows the insn to be recognized
by the push_multi pattern in the arm.md file. The insn looks
something like this:
@@ -7842,7 +7932,6 @@ emit_multi_reg_push (mask)
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1));
- RTX_FRAME_RELATED_P (dwarf) = 1;
dwarf_par_index = 1;
for (i = 0; i <= LAST_ARM_REGNUM; i++)
@@ -7924,7 +8013,6 @@ emit_sfm (base_reg, count)
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- RTX_FRAME_RELATED_P (dwarf) = 1;
reg = gen_rtx_REG (XFmode, base_reg++);
@@ -7996,11 +8084,11 @@ emit_sfm (base_reg, count)
current stack pointer -> | | /
--
- For a given funciton some or all of these stack compomnents
+ For a given function some or all of these stack components
may not be needed, giving rise to the possibility of
eliminating some of the registers.
- The values returned by this function must reflect the behaviour
+ The values returned by this function must reflect the behavior
of arm_expand_prologue() and arm_compute_save_reg_mask().
The sign of the number returned reflects the direction of stack
@@ -8012,7 +8100,7 @@ arm_compute_initial_elimination_offset (from, to)
unsigned int from;
unsigned int to;
{
- unsigned int local_vars = (get_frame_size () + 3) & ~3;
+ unsigned int local_vars = arm_get_frame_size ();
unsigned int outgoing_args = current_function_outgoing_args_size;
unsigned int stack_frame;
unsigned int call_saved_registers;
@@ -8041,10 +8129,14 @@ arm_compute_initial_elimination_offset (from, to)
reg_mask = reg_mask & ~ (reg_mask & - reg_mask);
}
- if (regs_ever_live[LR_REGNUM]
- /* If a stack frame is going to be created, the LR will
- be saved as part of that, so we do not need to allow
- for it here. */
+ if ((regs_ever_live[LR_REGNUM]
+ /* If optimizing for size, then we save the link register if
+ any other integer register is saved. This gives a smaller
+ return sequence. */
+ || (optimize_size && call_saved_registers > 0))
+ /* But if a stack frame is going to be created, the LR will
+ be saved as part of that, so we do not need to allow for
+ it here. */
&& ! frame_pointer_needed)
call_saved_registers += 4;
@@ -8133,6 +8225,79 @@ arm_compute_initial_elimination_offset (from, to)
}
}
+/* Calculate the size of the stack frame, taking into account any
+ padding that is required to ensure stack-alignment. */
+
+HOST_WIDE_INT
+arm_get_frame_size ()
+{
+ int regno;
+
+ int base_size = ROUND_UP (get_frame_size ());
+ int entry_size = 0;
+ unsigned long func_type = arm_current_func_type ();
+ int leaf;
+
+ if (! TARGET_ARM)
+ abort();
+
+ if (! TARGET_ATPCS)
+ return base_size;
+
+ /* We need to know if we are a leaf function. Unfortunately, it
+ is possible to be called after start_sequence has been called,
+ which causes get_insns to return the insns for the sequence,
+ not the function, which will cause leaf_function_p to return
+ the incorrect result.
+
+ To work around this, we cache the computed frame size. This
+ works because we will only be calling RTL expanders that need
+ to know about leaf functions once reload has completed, and the
+ frame size cannot be changed after that time, so we can safely
+ use the cached value. */
+
+ if (reload_completed)
+ return cfun->machine->frame_size;
+
+ leaf = leaf_function_p ();
+
+ /* A leaf function does not need any stack alignment if it has nothing
+ on the stack. */
+ if (leaf && base_size == 0)
+ {
+ cfun->machine->frame_size = 0;
+ return 0;
+ }
+
+ /* We know that SP will be word aligned on entry, and we must
+ preserve that condition at any subroutine call. But those are
+ the only constraints. */
+
+ /* Space for variadic functions. */
+ if (current_function_pretend_args_size)
+ entry_size += current_function_pretend_args_size;
+
+ /* Space for saved registers. */
+ entry_size += bit_count (arm_compute_save_reg_mask ()) * 4;
+
+ /* Space for saved FPA registers. */
+ if (! IS_VOLATILE (func_type))
+ {
+ for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ entry_size += 12;
+ }
+
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ base_size += 4;
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ abort ();
+
+ cfun->machine->frame_size = base_size;
+
+ return base_size;
+}
+
/* Generate the prologue instructions for entry into an ARM function. */
void
@@ -8275,18 +8440,19 @@ arm_expand_prologue ()
RTX_FRAME_RELATED_P (insn) = 1;
}
- /* If this is an interrupt service routine, and the link register is
- going to be pushed, subtracting four now will mean that the
- function return can be done with a single instruction. */
+ /* If this is an interrupt service routine, and the link register
+ is going to be pushed, and we are not creating a stack frame,
+ (which would involve an extra push of IP and a pop in the epilogue)
+ subtracting four from LR now will mean that the function return
+ can be done with a single instruction. */
if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
- && (live_regs_mask & (1 << LR_REGNUM)) != 0)
- {
- emit_insn (gen_rtx_SET (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- gen_rtx_PLUS (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- GEN_INT (-4))));
- }
+ && (live_regs_mask & (1 << LR_REGNUM)) != 0
+ && ! frame_pointer_needed)
+ emit_insn (gen_rtx_SET (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ gen_rtx_PLUS (SImode,
+ gen_rtx_REG (SImode, LR_REGNUM),
+ GEN_INT (-4))));
if (live_regs_mask)
{
@@ -8368,7 +8534,7 @@ arm_expand_prologue ()
}
}
- amount = GEN_INT (-(get_frame_size ()
+ amount = GEN_INT (-(arm_get_frame_size ()
+ current_function_outgoing_args_size));
if (amount != const0_rtx)
@@ -8389,15 +8555,8 @@ arm_expand_prologue ()
will prevent the scheduler from moving stores to the frame
before the stack adjustment. */
if (frame_pointer_needed)
- {
- rtx unspec = gen_rtx_UNSPEC (SImode,
- gen_rtvec (2, stack_pointer_rtx,
- hard_frame_pointer_rtx),
- UNSPEC_PRLG_STK);
-
- insn = emit_insn (gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_MEM (BLKmode, unspec)));
- }
+ insn = emit_insn (gen_stack_tie (stack_pointer_rtx,
+ hard_frame_pointer_rtx));
}
/* If we are profiling, make sure no instructions are scheduled before
@@ -8573,11 +8732,12 @@ arm_print_operand (stream, x, code)
case 'M':
asm_fprintf (stream, "{%r-%r}",
REGNO (x),
- REGNO (x) + NUM_REGS (GET_MODE (x)) - 1);
+ REGNO (x) + ARM_NUM_REGS (GET_MODE (x)) - 1);
return;
case 'd':
- if (!x)
+ /* CONST_TRUE_RTX means always -- that's the default. */
+ if (x == const_true_rtx)
return;
if (TARGET_ARM)
@@ -8588,8 +8748,10 @@ arm_print_operand (stream, x, code)
return;
case 'D':
- if (!x)
- return;
+ /* CONST_TRUE_RTX means not always -- ie never. We shouldn't ever
+ want to do that. */
+ if (x == const_true_rtx)
+ abort ();
if (TARGET_ARM)
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
@@ -8642,7 +8804,7 @@ arm_assemble_integer (x, size, aligned_p)
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
+ if (GET_CODE (x) == SYMBOL_REF
&& (CONSTANT_POOL_ADDRESS_P (x)
|| ENCODED_SHORT_CALL_ATTR_P (XSTR (x, 0))))
fputs ("(GOTOFF)", asm_out_file);
@@ -9171,7 +9333,7 @@ arm_hard_regno_mode_ok (regno, mode)
register available to hold the upper part of the value.
We probably we ought to ensure that the register is the
start of an even numbered register pair. */
- return (NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
+ return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
if (regno <= LAST_ARM_REGNUM)
/* We allow any value to be stored in the general regisetrs. */
@@ -9251,7 +9413,7 @@ arm_debugger_arg_offset (value, addr)
held in the register into an offset from the frame pointer.
We do this by searching through the insns for the function
looking to see where this register gets its value. If the
- register is initialised from the frame pointer plus an offset
+ register is initialized from the frame pointer plus an offset
then we are in luck and we can continue, otherwise we give up.
This code is exercised by producing debugging information
@@ -9302,7 +9464,7 @@ arm_debugger_arg_offset (value, addr)
}
#define def_builtin(NAME, TYPE, CODE) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL)
+ builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE)
void
arm_init_builtins ()
@@ -9313,10 +9475,9 @@ arm_init_builtins ()
tree int_ftype_int, void_ftype_pchar;
- /* void func (void *) */
+ /* void func (char *) */
void_ftype_pchar
- = build_function_type (void_type_node,
- tree_cons (NULL_TREE, pchar_type_node, endlink));
+ = build_function_type_list (void_type_node, pchar_type_node, NULL_TREE);
/* int func (int) */
int_ftype_int
@@ -9373,7 +9534,7 @@ arm_expand_builtin (exp, target, subtarget, mode, ignore)
emit_insn (pat);
return target;
}
-
+
/* @@@ Should really do something sensible here. */
return NULL_RTX;
}
@@ -9818,11 +9979,12 @@ thumb_shiftable_const (val)
return 0;
}
-/* Returns non-zero if the current function contains,
+/* Returns nonzero if the current function contains,
or might contain a far jump. */
int
-thumb_far_jump_used_p (int in_prologue)
+thumb_far_jump_used_p (in_prologue)
+ int in_prologue;
{
rtx insn;
@@ -9887,7 +10049,7 @@ thumb_far_jump_used_p (int in_prologue)
return 0;
}
-/* Return non-zero if FUNC must be entered in ARM mode. */
+/* Return nonzero if FUNC must be entered in ARM mode. */
int
is_called_in_ARM_mode (func)
@@ -9922,17 +10084,16 @@ thumb_unexpanded_epilogue ()
if (return_used_this_function)
return "";
+ if (IS_NAKED (arm_current_func_type ()))
+ return "";
+
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
- high_regs_pushed++;
- }
+ if (THUMB_REG_PUSHED_P (regno))
+ high_regs_pushed++;
/* The prolog may have pushed some high registers to use as
work registers. eg the testuite file:
@@ -9977,8 +10138,7 @@ thumb_unexpanded_epilogue ()
("no low registers available for popping high registers");
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE && (next_hi_reg == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
while (high_regs_pushed)
@@ -10007,10 +10167,7 @@ thumb_unexpanded_epilogue ()
regno);
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg]
- && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
}
}
@@ -10084,37 +10241,16 @@ thumb_unexpanded_epilogue ()
/* Functions to save and restore machine-specific function data. */
-static void
-arm_mark_machine_status (p)
- struct function * p;
-{
- machine_function *machine = p->machine;
-
- if (machine)
- ggc_mark_rtx (machine->eh_epilogue_sp_ofs);
-}
-
-static void
-arm_init_machine_status (p)
- struct function * p;
+static struct machine_function *
+arm_init_machine_status ()
{
- p->machine =
- (machine_function *) xcalloc (1, sizeof (machine_function));
+ struct machine_function *machine;
+ machine = (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
-#if ARM_FT_UNKNOWWN != 0
- ((machine_function *) p->machine)->func_type = ARM_FT_UNKNOWN;
+#if ARM_FT_UNKNOWN != 0
+ machine->func_type = ARM_FT_UNKNOWN;
#endif
-}
-
-static void
-arm_free_machine_status (p)
- struct function * p;
-{
- if (p->machine)
- {
- free (p->machine);
- p->machine = NULL;
- }
+ return machine;
}
/* Return an RTX indicating where the return address to the
@@ -10145,8 +10281,92 @@ arm_init_expanders ()
{
/* Arrange to initialize and mark the machine per-function status. */
init_machine_status = arm_init_machine_status;
- mark_machine_status = arm_mark_machine_status;
- free_machine_status = arm_free_machine_status;
+}
+
+HOST_WIDE_INT
+thumb_get_frame_size ()
+{
+ int regno;
+
+ int base_size = ROUND_UP (get_frame_size ());
+ int count_regs = 0;
+ int entry_size = 0;
+ int leaf;
+
+ if (! TARGET_THUMB)
+ abort ();
+
+ if (! TARGET_ATPCS)
+ return base_size;
+
+ /* We need to know if we are a leaf function. Unfortunately, it
+ is possible to be called after start_sequence has been called,
+ which causes get_insns to return the insns for the sequence,
+ not the function, which will cause leaf_function_p to return
+ the incorrect result.
+
+ To work around this, we cache the computed frame size. This
+ works because we will only be calling RTL expanders that need
+ to know about leaf functions once reload has completed, and the
+ frame size cannot be changed after that time, so we can safely
+ use the cached value. */
+
+ if (reload_completed)
+ return cfun->machine->frame_size;
+
+ leaf = leaf_function_p ();
+
+ /* A leaf function does not need any stack alignment if it has nothing
+ on the stack. */
+ if (leaf && base_size == 0)
+ {
+ cfun->machine->frame_size = 0;
+ return 0;
+ }
+
+ /* We know that SP will be word aligned on entry, and we must
+ preserve that condition at any subroutine call. But those are
+ the only constraints. */
+
+ /* Space for variadic functions. */
+ if (current_function_pretend_args_size)
+ entry_size += current_function_pretend_args_size;
+
+ /* Space for pushed lo registers. */
+ for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
+ if (THUMB_REG_PUSHED_P (regno))
+ count_regs++;
+
+ /* Space for backtrace structure. */
+ if (TARGET_BACKTRACE)
+ {
+ if (count_regs == 0 && regs_ever_live[LAST_ARG_REGNUM] != 0)
+ entry_size += 20;
+ else
+ entry_size += 16;
+ }
+
+ if (count_regs || !leaf || thumb_far_jump_used_p (1))
+ count_regs++; /* LR */
+
+ entry_size += count_regs * 4;
+ count_regs = 0;
+
+ /* Space for pushed hi regs. */
+ for (regno = 8; regno < 13; regno++)
+ if (THUMB_REG_PUSHED_P (regno))
+ count_regs++;
+
+ entry_size += count_regs * 4;
+
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ base_size += 4;
+ if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+ abort ();
+
+ cfun->machine->frame_size = base_size;
+
+ return base_size;
}
/* Generate the rest of a function's prologue. */
@@ -10154,7 +10374,7 @@ arm_init_expanders ()
void
thumb_expand_prologue ()
{
- HOST_WIDE_INT amount = (get_frame_size ()
+ HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
unsigned long func_type;
@@ -10200,14 +10420,12 @@ thumb_expand_prologue ()
been pushed at the start of the prologue and so we can corrupt
it now. */
for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno]
- && !call_used_regs[regno] /* Paranoia */
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register))
+ if (THUMB_REG_PUSHED_P (regno)
&& !(frame_pointer_needed
&& (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
break;
- if (regno > LAST_LO_REGNUM) /* Very unlikely */
+ if (regno > LAST_LO_REGNUM) /* Very unlikely. */
{
rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
@@ -10251,7 +10469,7 @@ thumb_expand_prologue ()
void
thumb_expand_epilogue ()
{
- HOST_WIDE_INT amount = (get_frame_size ()
+ HOST_WIDE_INT amount = (thumb_get_frame_size ()
+ current_function_outgoing_args_size);
/* Naked functions don't have prologues. */
@@ -10322,13 +10540,13 @@ thumb_output_function_prologue (f, size)
#define STUB_NAME ".real_start_of"
- asm_fprintf (f, "\t.code\t16\n");
+ fprintf (f, "\t.code\t16\n");
#ifdef ARM_PE
if (arm_dllexport_name_p (name))
name = arm_strip_name_encoding (name);
#endif
asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
+ fprintf (f, "\t.thumb_func\n");
asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
}
@@ -10338,9 +10556,9 @@ thumb_output_function_prologue (f, size)
{
int num_pushes;
- asm_fprintf (f, "\tpush\t{");
+ fprintf (f, "\tpush\t{");
- num_pushes = NUM_INTS (current_function_pretend_args_size);
+ num_pushes = ARM_NUM_INTS (current_function_pretend_args_size);
for (regno = LAST_ARG_REGNUM + 1 - num_pushes;
regno <= LAST_ARG_REGNUM;
@@ -10348,7 +10566,7 @@ thumb_output_function_prologue (f, size)
asm_fprintf (f, "%r%s", regno,
regno == LAST_ARG_REGNUM ? "" : ", ");
- asm_fprintf (f, "}\n");
+ fprintf (f, "}\n");
}
else
asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
@@ -10357,8 +10575,7 @@ thumb_output_function_prologue (f, size)
}
for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
+ if (THUMB_REG_PUSHED_P (regno))
live_regs_mask |= 1 << regno;
if (live_regs_mask || !leaf_function_p () || thumb_far_jump_used_p (1))
@@ -10459,11 +10676,8 @@ thumb_output_function_prologue (f, size)
thumb_pushpop (f, live_regs_mask, 1);
for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno]
- && !(TARGET_SINGLE_PIC_BASE && (regno == arm_pic_register)))
- high_regs_pushed++;
- }
+ if (THUMB_REG_PUSHED_P (regno))
+ high_regs_pushed++;
if (high_regs_pushed)
{
@@ -10472,20 +10686,15 @@ thumb_output_function_prologue (f, size)
int next_hi_reg;
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
- break;
- }
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
+ break;
pushable_regs = mask;
if (pushable_regs == 0)
{
/* Desperation time -- this probably will never happen. */
- if (regs_ever_live[LAST_ARG_REGNUM]
- || !call_used_regs[LAST_ARG_REGNUM])
+ if (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM))
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM);
mask = 1 << LAST_ARG_REGNUM;
}
@@ -10501,15 +10710,12 @@ thumb_output_function_prologue (f, size)
high_regs_pushed--;
if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
- next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && !call_used_regs[next_hi_reg]
- && !(TARGET_SINGLE_PIC_BASE
- && (next_hi_reg == arm_pic_register)))
+ {
+ for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
+ next_hi_reg--)
+ if (THUMB_REG_PUSHED_P (next_hi_reg))
break;
- }
+ }
else
{
mask &= ~((1 << regno) - 1);
@@ -10522,8 +10728,7 @@ thumb_output_function_prologue (f, size)
}
if (pushable_regs == 0
- && (regs_ever_live[LAST_ARG_REGNUM]
- || !call_used_regs[LAST_ARG_REGNUM]))
+ && (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM)))
asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
}
@@ -10821,7 +11026,8 @@ thumb_reload_in_hi (operands)
that starts with the character 'c'. */
static int
-arm_get_strip_length (char c)
+arm_get_strip_length (c)
+ int c;
{
switch (c)
{
@@ -10834,7 +11040,8 @@ arm_get_strip_length (char c)
and all prefix encodings stripped from it. */
const char *
-arm_strip_name_encoding (const char * name)
+arm_strip_name_encoding (name)
+ const char * name;
{
int skip;
@@ -10844,10 +11051,35 @@ arm_strip_name_encoding (const char * name)
return name;
}
+/* If there is a '*' anywhere in the name's prefix, then
+ emit the stripped name verbatim, otherwise prepend an
+ underscore if leading underscores are being used. */
+
+void
+arm_asm_output_labelref (stream, name)
+ FILE * stream;
+ const char * name;
+{
+ int skip;
+ int verbatim = 0;
+
+ while ((skip = arm_get_strip_length (* name)))
+ {
+ verbatim |= (*name == '*');
+ name += skip;
+ }
+
+ if (verbatim)
+ fputs (name, stream);
+ else
+ asm_fprintf (stream, "%U%s", name);
+}
+
+rtx aof_pic_label;
+
#ifdef AOF_ASSEMBLER
/* Special functions only needed when producing AOF syntax assembler. */
-rtx aof_pic_label = NULL_RTX;
struct pic_chain
{
struct pic_chain * next;
@@ -10865,10 +11097,6 @@ aof_pic_entry (x)
if (aof_pic_label == NULL_RTX)
{
- /* We mark this here and not in arm_add_gc_roots() to avoid
- polluting even more code with ifdefs, and because it never
- contains anything useful until we assign to it here. */
- ggc_add_rtx_root (&aof_pic_label, 1);
aof_pic_label = gen_rtx_SYMBOL_REF (Pmode, "x$adcons");
}
@@ -11003,6 +11231,16 @@ aof_dump_imports (f)
imports_list = imports_list->next;
}
}
+
+static void
+aof_globalize_label (stream, name)
+ FILE *stream;
+ const char *name;
+{
+ default_globalize_label (stream, name);
+ if (! strcmp (name, "main"))
+ arm_main_function = 1;
+}
#endif /* AOF_ASSEMBLER */
#ifdef OBJECT_FORMAT_ELF
@@ -11018,8 +11256,13 @@ arm_elf_asm_named_section (name, flags)
const char *name;
unsigned int flags;
{
- char flagchars[8], *f = flagchars;
- const char *type;
+ char flagchars[10], *f = flagchars;
+
+ if (! named_section_first_declaration (name))
+ {
+ fprintf (asm_out_file, "\t.section\t%s\n", name);
+ return;
+ }
if (!(flags & SECTION_DEBUG))
*f++ = 'a';
@@ -11033,18 +11276,103 @@ arm_elf_asm_named_section (name, flags)
*f++ = 'M';
if (flags & SECTION_STRINGS)
*f++ = 'S';
+ if (flags & SECTION_TLS)
+ *f++ = 'T';
*f = '\0';
- if (flags & SECTION_BSS)
- type = "nobits";
- else
- type = "progbits";
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
- if (flags & SECTION_ENTSIZE)
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",%%%s,%d\n",
- name, flagchars, type, flags & SECTION_ENTSIZE);
- else
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",%%%s\n",
- name, flagchars, type);
+ if (!(flags & SECTION_NOTYPE))
+ {
+ const char *type;
+
+ if (flags & SECTION_BSS)
+ type = "nobits";
+ else
+ type = "progbits";
+
+ fprintf (asm_out_file, ",%%%s", type);
+
+ if (flags & SECTION_ENTSIZE)
+ fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+ }
+
+ putc ('\n', asm_out_file);
}
#endif
+
+#ifndef ARM_PE
+/* 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
+ faster than indirecting via memory. Don't do this when not optimizing,
+ since we won't be calculating al of the offsets necessary to do this
+ simplification. */
+
+static void
+arm_encode_section_info (decl, first)
+ tree decl;
+ int first;
+{
+ /* This doesn't work with AOF syntax, since the string table may be in
+ a different AREA. */
+#ifndef AOF_ASSEMBLER
+ if (optimize > 0 && TREE_CONSTANT (decl)
+ && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
+ {
+ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
+ ? TREE_CST_RTL (decl) : DECL_RTL (decl));
+ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
+ }
+#endif
+
+ /* 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. */
+ if (first && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ {
+ 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);
+ }
+}
+#endif /* !ARM_PE */
+
+/* Output code to add DELTA to the first argument, and then jump
+ to FUNCTION. Used for C++ multiple inheritance. */
+
+static void
+arm_output_mi_thunk (file, thunk, delta, vcall_offset, function)
+ FILE *file;
+ tree thunk ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT delta;
+ HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
+ tree function;
+{
+ int mi_delta = delta;
+ 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);
+ if (mi_delta < 0)
+ mi_delta = - mi_delta;
+ while (mi_delta != 0)
+ {
+ if ((mi_delta & (3 << shift)) == 0)
+ shift += 2;
+ else
+ {
+ asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
+ mi_op, this_regno, this_regno,
+ mi_delta & (0xff << shift));
+ mi_delta &= ~(0xff << shift);
+ shift += 8;
+ }
+ }
+ fputs ("\tb\t", file);
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+ if (NEED_PLT_RELOC)
+ fputs ("(PLT)", file);
+ fputc ('\n', file);
+}
+
diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h
index c5431b5..eda2d47 100644
--- a/contrib/gcc/config/arm/arm.h
+++ b/contrib/gcc/config/arm/arm.h
@@ -26,6 +26,52 @@ Boston, MA 02111-1307, USA. */
#ifndef GCC_ARM_H
#define GCC_ARM_H
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ if (TARGET_ARM) \
+ builtin_define ("__arm__"); \
+ else \
+ builtin_define ("__thumb__"); \
+ \
+ if (TARGET_BIG_END) \
+ { \
+ builtin_define ("__ARMEB__"); \
+ if (TARGET_THUMB) \
+ builtin_define ("__THUMBEB__"); \
+ if (TARGET_LITTLE_WORDS) \
+ builtin_define ("__ARMWEL__"); \
+ } \
+ else \
+ { \
+ builtin_define ("__ARMEL__"); \
+ if (TARGET_THUMB) \
+ builtin_define ("__THUMBEL__"); \
+ } \
+ \
+ if (TARGET_APCS_32) \
+ builtin_define ("__APCS_32__"); \
+ else \
+ builtin_define ("__APCS_26__"); \
+ \
+ if (TARGET_SOFT_FLOAT) \
+ builtin_define ("__SOFTFP__"); \
+ \
+ /* FIXME: TARGET_HARD_FLOAT currently implies \
+ FPA. */ \
+ if (TARGET_VFP && !TARGET_HARD_FLOAT) \
+ builtin_define ("__VFP_FP__"); \
+ \
+ /* Add a define for interworking. \
+ Needed when building libgcc.a. */ \
+ if (TARGET_INTERWORK) \
+ builtin_define ("__THUMB_INTERWORK__"); \
+ \
+ builtin_assert ("cpu=arm"); \
+ builtin_assert ("machine=arm"); \
+ } while (0)
+
#define TARGET_CPU_arm2 0x0000
#define TARGET_CPU_arm250 0x0000
#define TARGET_CPU_arm3 0x0000
@@ -66,21 +112,22 @@ extern arm_cc arm_current_cc;
extern int arm_target_label;
extern int arm_ccfsm_state;
-extern struct rtx_def * arm_target_insn;
+extern GTY(()) rtx arm_target_insn;
/* Run-time compilation parameters selecting different hardware subsets. */
extern int target_flags;
/* The floating point instruction architecture, can be 2 or 3 */
extern const char * target_fp_name;
/* Define the information needed to generate branch insns. This is
- stored from the compare operation. Note that we can't use "rtx" here
- since it hasn't been defined! */
-extern struct rtx_def * arm_compare_op0;
-extern struct rtx_def * arm_compare_op1;
+ stored from the compare operation. */
+extern GTY(()) rtx arm_compare_op0;
+extern GTY(()) rtx arm_compare_op1;
/* The label of the current constant pool. */
-extern struct rtx_def * pool_vector_label;
+extern rtx pool_vector_label;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
extern int return_used_this_function;
+/* Used to produce AOF syntax assembler. */
+extern GTY(()) rtx aof_pic_label;
/* Just in case configure has failed to define anything. */
#ifndef TARGET_CPU_DEFAULT
@@ -126,16 +173,17 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#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:-D__thumb__} %{!mthumb:-D__arm__}"
+#define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec) \
+%{mapcs-32:%{mapcs-26: \
+ %e-mapcs-26 and -mapcs-32 may not be used together}} \
+%{msoft-float:%{mhard-float: \
+ %e-msoft-float and -mhard_float may not be used together}} \
+%{mbig-endian:%{mlittle-endian: \
+ %e-mbig-endian and -mlittle-endian may not be used together}}"
/* 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__} \
@@ -206,58 +254,6 @@ Unrecognized value in TARGET_CPU_DEFAULT.
%{!mcpu*:%(cpp_cpu_arch_default)}} \
"
-/* Define __APCS_26__ if the PC also contains the PSR */
-#define CPP_APCS_PC_SPEC "\
-%{mapcs-32:%{mapcs-26:%e-mapcs-26 and -mapcs-32 may not be used together} \
- -D__APCS_32__} \
-%{mapcs-26:-D__APCS_26__} \
-%{!mapcs-32: %{!mapcs-26:%(cpp_apcs_pc_default)}} \
-"
-
-#ifndef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_26__"
-#endif
-
-#define CPP_FLOAT_SPEC "\
-%{msoft-float:\
- %{mhard-float:%e-msoft-float and -mhard_float may not be used together} \
- -D__SOFTFP__} \
-%{!mhard-float:%{!msoft-float:%(cpp_float_default)}} \
-"
-
-/* Default is hard float, which doesn't define anything */
-#define CPP_FLOAT_DEFAULT_SPEC ""
-
-#define CPP_ENDIAN_SPEC "\
-%{mbig-endian: \
- %{mlittle-endian: \
- %e-mbig-endian and -mlittle-endian may not be used together} \
- -D__ARMEB__ %{mwords-little-endian:-D__ARMWEL__} %{mthumb:-D__THUMBEB__}}\
-%{mlittle-endian:-D__ARMEL__ %{mthumb:-D__THUMBEL__}} \
-%{!mlittle-endian:%{!mbig-endian:%(cpp_endian_default)}} \
-"
-
-/* Default is little endian. */
-#define CPP_ENDIAN_DEFAULT_SPEC "-D__ARMEL__ %{mthumb:-D__THUMBEL__}"
-
-/* Add a define for interworking. Needed when building libgcc.a.
- This must define __THUMB_INTERWORK__ to the pre-processor if
- interworking is enabled by default. */
-#ifndef CPP_INTERWORK_DEFAULT_SPEC
-#define CPP_INTERWORK_DEFAULT_SPEC ""
-#endif
-
-#define CPP_INTERWORK_SPEC " \
-%{mthumb-interwork: \
- %{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
@@ -274,15 +270,6 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#define EXTRA_SPECS \
{ "cpp_cpu_arch", CPP_CPU_ARCH_SPEC }, \
{ "cpp_cpu_arch_default", CPP_ARCH_DEFAULT_SPEC }, \
- { "cpp_apcs_pc", CPP_APCS_PC_SPEC }, \
- { "cpp_apcs_pc_default", CPP_APCS_PC_DEFAULT_SPEC }, \
- { "cpp_float", CPP_FLOAT_SPEC }, \
- { "cpp_float_default", CPP_FLOAT_DEFAULT_SPEC }, \
- { "cpp_endian", CPP_ENDIAN_SPEC }, \
- { "cpp_endian_default", CPP_ENDIAN_DEFAULT_SPEC }, \
- { "cpp_isa", CPP_ISA_SPEC }, \
- { "cpp_interwork", CPP_INTERWORK_SPEC }, \
- { "cpp_interwork_default", CPP_INTERWORK_DEFAULT_SPEC }, \
{ "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -383,6 +370,12 @@ Unrecognized value in TARGET_CPU_DEFAULT.
destination is non-Thumb aware. */
#define THUMB_FLAG_CALLER_SUPER_INTERWORKING (1 << 20)
+/* Nonzero means target uses VFP FP. */
+#define ARM_FLAG_VFP (1 << 21)
+
+/* Nonzero means to use ARM/Thumb Procedure Call Standard conventions. */
+#define ARM_FLAG_ATPCS (1 << 22)
+
#define TARGET_APCS_FRAME (target_flags & ARM_FLAG_APCS_FRAME)
#define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE)
#define TARGET_FPE (target_flags & ARM_FLAG_FPE)
@@ -390,9 +383,11 @@ Unrecognized value in TARGET_CPU_DEFAULT.
#define TARGET_APCS_STACK (target_flags & ARM_FLAG_APCS_STACK)
#define TARGET_APCS_FLOAT (target_flags & ARM_FLAG_APCS_FLOAT)
#define TARGET_APCS_REENT (target_flags & ARM_FLAG_APCS_REENT)
+#define TARGET_ATPCS (target_flags & ARM_FLAG_ATPCS)
#define TARGET_MMU_TRAPS (target_flags & ARM_FLAG_MMU_TRAPS)
#define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_VFP (target_flags & ARM_FLAG_VFP)
#define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END)
#define TARGET_INTERWORK (target_flags & ARM_FLAG_INTERWORK)
#define TARGET_LITTLE_WORDS (target_flags & ARM_FLAG_LITTLE_WORDS)
@@ -409,8 +404,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
: (target_flags & THUMB_FLAG_BACKTRACE))
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis.
- Bit 31 is reserved. See riscix.h. */
+/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
#ifndef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES
#endif
@@ -647,8 +641,6 @@ extern int arm_is_6_or_7;
/* This is required to ensure that push insns always push a word. */
#define PROMOTE_FUNCTION_ARGS
-/* Define for XFmode extended real floating point support.
- This will automatically cause REAL_ARITHMETIC to be defined. */
/* For the ARM:
I think I have added all the code to make this work. Unfortunately,
early releases of the floating point emulation code on RISCiX used a
@@ -663,12 +655,6 @@ extern int arm_is_6_or_7;
/* Disable XFmode patterns in md file */
#define ENABLE_XF_PATTERNS 0
-/* Define if you don't want extended real, but do want to use the
- software floating point emulator for REAL_ARITHMETIC and
- decimal <-> binary conversion. */
-/* See comment above */
-#define REAL_ARITHMETIC
-
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 0
@@ -693,22 +679,18 @@ extern int arm_is_6_or_7;
#endif
/* Define this if most significant word of doubles is the lowest numbered.
- 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
+ The rules are different based on whether or not we use FPA-format or
+ VFP-format doubles. */
+#define FLOAT_WORDS_BIG_ENDIAN (arm_float_words_big_endian ())
#define UNITS_PER_WORD 4
-#define POINTER_SIZE 32
-
#define PARM_BOUNDARY 32
#define STACK_BOUNDARY 32
+#define PREFERRED_STACK_BOUNDARY (TARGET_ATPCS ? 64 : 32)
+
#define FUNCTION_BOUNDARY 32
/* The lowest bit is used to indicate Thumb-mode functions, so the
@@ -737,7 +719,7 @@ extern int arm_is_6_or_7;
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
extern int arm_structure_size_boundary;
-/* This is the value used to initialise arm_structure_size_boundary. If a
+/* This is the value used to initialize arm_structure_size_boundary. If a
particular arm target wants to change the default value it should change
the definition of this macro, not STRUCTRUE_SIZE_BOUNDARY. See netbsd.h
for an example of this. */
@@ -748,12 +730,9 @@ extern int arm_structure_size_boundary;
/* Used when parsing command line option -mstructure_size_boundary. */
extern const char * structure_size_string;
-/* Non-zero if move instructions will actually fail to work
+/* Nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
/* Standard register usage. */
@@ -889,15 +868,15 @@ extern const char * structure_size_string;
#define ROUND_UP(X) (((X) + 3) & ~3)
/* Convert fron bytes to ints. */
-#define NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#define ARM_NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* The number of (integer) registers required to hold a quantity of type MODE. */
-#define NUM_REGS(MODE) \
- NUM_INTS (GET_MODE_SIZE (MODE))
+#define ARM_NUM_REGS(MODE) \
+ ARM_NUM_INTS (GET_MODE_SIZE (MODE))
/* The number of (integer) registers required to hold a quantity of TYPE MODE. */
-#define NUM_REGS2(MODE, TYPE) \
- NUM_INTS ((MODE) == BLKmode ? \
+#define ARM_NUM_REGS2(MODE, TYPE) \
+ ARM_NUM_INTS ((MODE) == BLKmode ? \
int_size_in_bytes (TYPE) : GET_MODE_SIZE (MODE))
/* The number of (integer) argument register available. */
@@ -1001,7 +980,7 @@ extern const char * structure_size_string;
&& REGNO >= FIRST_ARM_FP_REGNUM \
&& REGNO != FRAME_POINTER_REGNUM \
&& REGNO != ARG_POINTER_REGNUM) \
- ? 1 : NUM_REGS (MODE))
+ ? 1 : ARM_NUM_REGS (MODE))
/* Return true if REGNO is suitable for holding a quantity of type MODE. */
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
@@ -1324,7 +1303,7 @@ enum reg_class
needed to represent mode MODE in a register of class CLASS.
ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((CLASS) == FPU_REGS ? 1 : NUM_REGS (MODE))
+ ((CLASS) == FPU_REGS ? 1 : ARM_NUM_REGS (MODE))
/* Moves between FPU_REGS and GENERAL_REGS are two memory insns. */
#define REGISTER_MOVE_COST(MODE, FROM, TO) \
@@ -1420,7 +1399,7 @@ enum reg_class
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
+ machine_function structure is initialized (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. */
@@ -1449,16 +1428,18 @@ enum reg_class
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
-typedef struct machine_function
+typedef struct machine_function GTY(())
{
/* Additionsl stack adjustment in __builtin_eh_throw. */
- struct rtx_def *eh_epilogue_sp_ofs;
+ rtx 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;
+ /* The size of the stack frame. Only valid after reload. */
+ int frame_size;
/* Records the type of the current function. */
unsigned long func_type;
/* Record if the function has a variable argument list. */
@@ -1503,9 +1484,17 @@ typedef struct
For args passed entirely in registers or entirely in memory, zero. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
( NUM_ARG_REGS > (CUM).nregs \
- && (NUM_ARG_REGS < ((CUM).nregs + NUM_REGS2 (MODE, TYPE))) \
+ && (NUM_ARG_REGS < ((CUM).nregs + ARM_NUM_REGS2 (MODE, TYPE))) \
? NUM_ARG_REGS - (CUM).nregs : 0)
+/* A C expression that indicates when an argument must be passed by
+ reference. If nonzero for an argument, a copy of that argument is
+ made in memory and a pointer to the argument is passed instead of
+ the argument itself. The pointer is passed in whatever way is
+ appropriate for passing a pointer to that type. */
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0.
@@ -1517,12 +1506,16 @@ typedef struct
of mode MODE and data type TYPE.
(TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nregs += NUM_REGS2 (MODE, TYPE)
+ (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
/* 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) (IN_RANGE ((REGNO), 0, 3))
+/* Implement `va_arg'. */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+ arm_va_arg (valist, type)
+
/* Tail calling. */
@@ -1572,7 +1565,10 @@ typedef struct
will output the .text section.
The ``mov ip,lr'' seems like a good idea to stick with cc convention.
- ``prof'' doesn't seem to mind about this! */
+ ``prof'' doesn't seem to mind about this!
+
+ Note - this version of the code is designed to work in both ARM and
+ Thumb modes. */
#ifndef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
@@ -1589,20 +1585,16 @@ typedef struct
}
#endif
-#ifndef THUMB_FUNCTION_PROFILER
-#define THUMB_FUNCTION_PROFILER(STREAM, LABELNO) \
-{ \
- fprintf (STREAM, "\tmov\tip, lr\n"); \
- fprintf (STREAM, "\tbl\tmcount\n"); \
- fprintf (STREAM, "\t.word\tLP%d\n", LABELNO); \
-}
-#endif
-
+#ifdef THUMB_FUNCTION_PROFILER
#define FUNCTION_PROFILER(STREAM, LABELNO) \
if (TARGET_ARM) \
ARM_FUNCTION_PROFILER (STREAM, LABELNO) \
else \
THUMB_FUNCTION_PROFILER (STREAM, LABELNO)
+#else
+#define FUNCTION_PROFILER(STREAM, LABELNO) \
+ ARM_FUNCTION_PROFILER (STREAM, LABELNO)
+#endif
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
@@ -1657,7 +1649,13 @@ typedef struct
((TO) == ARM_HARD_FRAME_POINTER_REGNUM && TARGET_THUMB) ? 0 : \
((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \
1)
-
+
+#define THUMB_REG_PUSHED_P(reg) \
+ (regs_ever_live [reg] \
+ && (! call_used_regs [reg] \
+ || (flag_pic && (reg) == PIC_OFFSET_TABLE_REGNUM)) \
+ && !(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register)))
+
/* 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) \
@@ -1676,13 +1674,13 @@ typedef struct
int count_regs = 0; \
int regno; \
for (regno = 8; regno < 13; regno ++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs ++; \
+ if (THUMB_REG_PUSHED_P (regno)) \
+ count_regs ++; \
if (count_regs) \
(OFFSET) += 4 * count_regs; \
count_regs = 0; \
for (regno = 0; regno <= LAST_LO_REGNUM; regno ++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
+ if (THUMB_REG_PUSHED_P (regno)) \
count_regs ++; \
if (count_regs || ! leaf_function_p () || thumb_far_jump_used_p (0))\
(OFFSET) += 4 * (count_regs + 1); \
@@ -1697,7 +1695,7 @@ typedef struct
if ((TO) == STACK_POINTER_REGNUM) \
{ \
(OFFSET) += current_function_outgoing_args_size; \
- (OFFSET) += ROUND_UP (get_frame_size ()); \
+ (OFFSET) += thumb_get_frame_size (); \
} \
}
@@ -1884,56 +1882,11 @@ typedef struct
case '*': return 1; \
SUBTARGET_NAME_ENCODING_LENGTHS
-/* This has to be handled by a function because more than part of the
- ARM backend uses function name prefixes to encode attributes. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
- (VAR) = arm_strip_name_encoding (SYMBOL_NAME)
-
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE, 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_CLASS (TREE_CODE (decl)) == 'd') \
- { \
- 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
- faster than indirecting via memory. Don't do this when not optimizing,
- since we won't be calculating al of the offsets necessary to do this
- simplification. */
-/* 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) \
-{ \
- if (optimize > 0 && TREE_CONSTANT (decl) \
- && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) \
- { \
- rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' \
- ? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
- SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
- } \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-#else
-#define ENCODE_SECTION_INFO(decl) \
-{ \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-#endif
+ arm_asm_output_labelref (FILE, NAME)
#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
@@ -2168,7 +2121,8 @@ typedef struct
goto WIN; \
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
+ && GET_CODE (X) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
goto WIN; \
/* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
@@ -2477,12 +2431,13 @@ extern const char * arm_pic_register_string;
/* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- ( ! symbol_mentioned_p (X) \
- && ! label_mentioned_p (X) \
- && (! CONSTANT_POOL_ADDRESS_P (X) \
- || ( ! symbol_mentioned_p (get_pool_constant (X)) \
- && ! label_mentioned_p (get_pool_constant (X)))))
-
+ (!(symbol_mentioned_p (X) \
+ || label_mentioned_p (X) \
+ || (GET_CODE (X) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (X) \
+ && (symbol_mentioned_p (get_pool_constant (X)) \
+ || label_mentioned_p (get_pool_constant (X))))))
+
/* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT
offset. */
@@ -2497,30 +2452,7 @@ extern int making_const_table;
/* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison.
- CCFPEmode should be used with floating inequalities,
- CCFPmode should be used with floating equalities.
- CC_NOOVmode should be used with SImode integer equalities.
- CC_Zmode should be used if only the Z flag is set correctly
- CCmode should be used otherwise. */
-
-#define EXTRA_CC_MODES \
- CC(CC_NOOVmode, "CC_NOOV") \
- CC(CC_Zmode, "CC_Z") \
- CC(CC_SWPmode, "CC_SWP") \
- CC(CCFPmode, "CCFP") \
- CC(CCFPEmode, "CCFPE") \
- CC(CC_DNEmode, "CC_DNE") \
- CC(CC_DEQmode, "CC_DEQ") \
- CC(CC_DLEmode, "CC_DLE") \
- CC(CC_DLTmode, "CC_DLT") \
- CC(CC_DGEmode, "CC_DGE") \
- CC(CC_DGTmode, "CC_DGT") \
- CC(CC_DLEUmode, "CC_DLEU") \
- CC(CC_DLTUmode, "CC_DLTU") \
- CC(CC_DGEUmode, "CC_DGEU") \
- CC(CC_DGTUmode, "CC_DGTU") \
- CC(CC_Cmode, "CC_C")
+ return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) arm_select_cc_mode (OP, X, Y)
@@ -2779,39 +2711,6 @@ extern int making_const_table;
else \
THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
-/* 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 *const mi_op = mi_delta < 0 ? "sub" : "add"; \
- int shift = 0; \
- int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) \
- ? 1 : 0); \
- if (mi_delta < 0) \
- mi_delta = - mi_delta; \
- while (mi_delta != 0) \
- { \
- if ((mi_delta & (3 << shift)) == 0) \
- shift += 2; \
- else \
- { \
- asm_fprintf (FILE, "\t%s\t%r, %r, #%d\n", \
- mi_op, this_regno, this_regno, \
- mi_delta & (0xff << shift)); \
- mi_delta &= ~(0xff << shift); \
- shift += 8; \
- } \
- } \
- fputs ("\tb\t", FILE); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \
- if (NEED_PLT_RELOC) \
- fputs ("(PLT)", FILE); \
- fputc ('\n', FILE); \
- } \
- 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. */
@@ -2835,8 +2734,10 @@ extern int making_const_table;
in 26 bit mode, the condition codes must be masked out of the \
return address. This does not apply to ARM6 and later processors \
when running in 32 bit mode. */ \
- ((!TARGET_APCS_32) ? (GEN_INT (RETURN_ADDR_MASK26)) \
- : (GEN_INT ((unsigned long)0xffffffff)))
+ ((!TARGET_APCS_32) ? (gen_int_mode (RETURN_ADDR_MASK26, Pmode)) \
+ : (arm_arch4 || TARGET_THUMB) ? \
+ (gen_int_mode ((unsigned long)0xffffffff, Pmode)) \
+ : arm_gen_return_addr_mask ())
/* Define the codes that are matched by predicates in arm.c */
diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md
index 5180c75..0e60712 100644
--- a/contrib/gcc/config/arm/arm.md
+++ b/contrib/gcc/config/arm/arm.md
@@ -59,7 +59,11 @@
(UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
; usage, that is, we will add the pic_register
; value to it before trying to dereference it.
- (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
+ (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
+ ; GLOBAL_OFFSET_TABLE. The operation is fully
+ ; described by the RTL but must be wrapped to
+ ; prevent combine from trying to rip it apart.
+ (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
; being scheduled before the stack adjustment insn.
(UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
; operand 0 is the result,
@@ -69,6 +73,7 @@
; instructions setting registers for EH handling
; and stack frame generation. Operand 0 is the
; register to "use".
+ (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
]
)
@@ -179,7 +184,7 @@
(const_string "normal"))
; Load scheduling, set from the arm_ld_sched variable
-; initialised by arm_override_options()
+; initialized by arm_override_options()
(define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
; condition codes: this one is used by final_prescan_insn to speed up
@@ -600,10 +605,10 @@
;; Reloading and elimination of the frame pointer can
;; sometimes cause this optimization to be missed.
(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "const_int_operand" ""))
(set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
+ (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
"TARGET_THUMB
&& REGNO (operands[2]) == STACK_POINTER_REGNUM
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
@@ -1857,9 +1862,9 @@
;;; ??? This pattern is bogus. If operand3 has bits outside the range
;;; represented by the bitfield, then this will produce incorrect results.
;;; Somewhere, the value needs to be truncated. On targets like the m68k,
-;;; which have a real bitfield insert instruction, the truncation happens
-;;; in the bitfield insert instruction itself. Since arm does not have a
-;;; bitfield insert instruction, we would have to emit code here to truncate
+;;; which have a real bit-field insert instruction, the truncation happens
+;;; in the bit-field insert instruction itself. Since arm does not have a
+;;; bit-field insert instruction, we would have to emit code here to truncate
;;; the value before we insert. This loses some of the advantage of having
;;; this insv pattern, so this pattern needs to be reevalutated.
@@ -1867,7 +1872,7 @@
[(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_operand" ""))
- (match_operand:SI 3 "nonmemory_operand" ""))]
+ (match_operand:SI 3 "reg_or_int_operand" ""))]
"TARGET_ARM"
"
{
@@ -2035,7 +2040,7 @@
"TARGET_ARM
&& reload_completed
&& operands[0] != operands[1]"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (match_dup 4))]
"
{
@@ -2052,11 +2057,11 @@
[(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
(and:DI (not:DI (sign_extend:DI
(match_operand:SI 2 "s_register_operand" "r,r")))
- (match_operand:DI 1 "s_register_operand" "?r,0")))]
+ (match_operand:DI 1 "s_register_operand" "0,r")))]
"TARGET_ARM"
"#"
"TARGET_ARM && reload_completed"
- [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+ [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
(set (match_dup 3) (and:SI (not:SI
(ashiftrt:SI (match_dup 2) (const_int 31)))
(match_dup 4)))]
@@ -2339,11 +2344,11 @@
; insns.
(define_split
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
- (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
- (match_operand:SI 3 "arm_rhs_operand" "rI")))
- (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
+ (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
+ (match_operand:SI 3 "arm_rhs_operand" "")))
+ (clobber (match_operand:SI 4 "s_register_operand" ""))]
"TARGET_ARM"
[(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
(not:SI (match_dup 3))))
@@ -3913,7 +3918,7 @@
;; DONE;
;;}")
-;; Recognise garbage generated above.
+;; Recognize garbage generated above.
;;(define_insn ""
;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
@@ -4129,6 +4134,7 @@
if ((val & (mask << i)) == val)
break;
+ /* Shouldn't happen, but we don't want to split if the shift is zero. */
if (i == 0)
FAIL;
@@ -4200,7 +4206,9 @@
(define_insn "pic_add_dot_plus_four"
[(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 4))))]
+ UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_THUMB && flag_pic"
"*
@@ -4213,7 +4221,9 @@
(define_insn "pic_add_dot_plus_eight"
[(set (match_operand:SI 0 "register_operand" "+r")
- (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_ARM && flag_pic"
"*
@@ -4417,6 +4427,14 @@
emit_insn (gen_movsi (reg, GEN_INT (val)));
operands[1] = gen_lowpart (HImode, reg);
}
+ else if (arm_arch4 && !no_new_pseudos && optimize > 0
+ && GET_CODE (operands[1]) == MEM)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
else if (!arm_arch4)
{
/* Note: We do not have to worry about TARGET_MMU_TRAPS
@@ -4673,7 +4691,7 @@
"
)
-;; Pattern to recognise insn generated default case above
+;; Pattern to recognize insn generated default case above
(define_insn "*movhi_insn_arch4"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
(match_operand:HI 1 "general_operand" "rI,K,r,m"))]
@@ -4814,9 +4832,16 @@
emit_insn (gen_movsi (reg, operands[1]));
operands[1] = gen_lowpart (QImode, reg);
}
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
- }
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
+ }
}
else /* TARGET_THUMB */
{
@@ -6014,7 +6039,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6031,7 +6056,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6066,7 +6091,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bmi\\t%l0;bgt\\t%l0\";
+ return \"bmi\\t%l0\;bgt\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6083,7 +6108,7 @@
if (arm_ccfsm_state != 0)
abort ();
- return \"bvs\\t%l0;beq\\t%l0\";
+ return \"bvs\\t%l0\;beq\\t%l0\";
"
[(set_attr "conds" "jump_clob")
(set_attr "length" "8")]
@@ -6288,8 +6313,12 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6305,6 +6334,9 @@
enum rtx_code code = GET_CODE (operands[1]);
rtx ccreg;
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
/* When compiling for SOFT_FLOAT, ensure both arms are in registers.
Otherwise, ensure it is a valid FP add operand */
if ((!TARGET_HARD_FLOAT)
@@ -6325,8 +6357,12 @@
"
{
enum rtx_code code = GET_CODE (operands[1]);
- rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
+ rtx ccreg;
+ if (code == UNEQ || code == LTGT)
+ FAIL;
+
+ ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -6665,8 +6701,8 @@
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "memory_operand" "")
(match_operand 1 "general_operand" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 2 "" ""))])]
"TARGET_ARM"
"
{
@@ -6679,8 +6715,8 @@
[(parallel [(set (match_operand 0 "register_operand" "")
(call (match_operand 1 "memory_operand" "")
(match_operand 2 "general_operand" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))])]
+ (return)
+ (use (match_operand 3 "" ""))])]
"TARGET_ARM"
"
{
@@ -6692,8 +6728,8 @@
(define_insn "*sibcall_insn"
[(call (mem:SI (match_operand:SI 0 "" "X"))
(match_operand 1 "" ""))
- (use (match_operand 2 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 2 "" ""))]
"TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
@@ -6705,8 +6741,8 @@
[(set (match_operand 0 "s_register_operand" "=r,f")
(call (mem:SI (match_operand:SI 1 "" "X,X"))
(match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
- (use (reg:SI LR_REGNUM))]
+ (return)
+ (use (match_operand 3 "" ""))]
"TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
"*
return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
@@ -6725,7 +6761,7 @@
arm_ccfsm_state += 2;
return \"\";
}
- return output_return_instruction (NULL, TRUE, FALSE);
+ return output_return_instruction (const_true_rtx, TRUE, FALSE);
}"
[(set_attr "type" "load")
(set_attr "predicable" "yes")]
@@ -6771,6 +6807,33 @@
(set_attr "type" "load")]
)
+;; Generate a sequence of instructions to determine if the processor is
+;; in 26-bit or 32-bit mode, and return the appropriate return address
+;; mask.
+
+(define_expand "return_addr_mask"
+ [(set (match_dup 1)
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (if_then_else:SI (eq (match_dup 1) (const_int 0))
+ (const_int -1)
+ (const_int 67108860)))] ; 0x03fffffc
+ "TARGET_ARM"
+ "
+ operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
+ ")
+
+(define_insn "*check_arch2"
+ [(set (match_operand:CC_NOOV 0 "cc_register" "")
+ (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
+ (const_int 0)))]
+ "TARGET_ARM"
+ "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
+ [(set_attr "length" "8")
+ (set_attr "conds" "set")]
+)
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -7015,139 +7078,6 @@
]
)
-;; These variants of the above insns can occur if the first operand is the
-;; frame pointer and we eliminate that. This is a kludge, but there doesn't
-;; seem to be a way around it. Most of the predicates have to be null
-;; because the format can be generated part way through reload, so
-;; if we don't match it as soon as it becomes available, reload doesn't know
-;; how to reload pseudos that haven't got hard registers; the constraints will
-;; sort everything out.
-
-(define_insn "*reload_mulsi3"
- [(set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 2 "" "r"))
- (match_operand:SI 1 "const_int_operand" "n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
- operands[2] = operands[1];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [
- ; we have no idea how long the add_immediate is, it could be up to 4.
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
- (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-(define_insn "*reload_mulsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI
- (plus:SI
- (match_operator:SI 5 "shift_operator"
- [(match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "rM")])
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- return \"add%?s\\t%0, %0, %3%S5\";
- "
- [(set_attr "conds" "set")
- (set_attr "shift" "3")
- (set_attr "length" "20")]
-)
-
-;; These are similar, but are needed when the mla pattern contains the
-;; eliminated register as operand 3.
-
-(define_insn "*reload_muladdsi"
- [(set (match_operand:SI 0 "" "=&r,&r")
- (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
- (match_operand:SI 2 "" "r,r"))
- (match_operand:SI 3 "" "r,r"))
- (match_operand:SI 4 "const_int_operand" "n,n")))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
- operands[2] = operands[4];
- operands[1] = operands[0];
- return output_add_immediate (operands);
- "
- [(set_attr "length" "20")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (set (match_operand:SI 0 "" "=&r")
- (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
- (match_dup 2)))]
- "TARGET_ARM && reload_in_progress && !arm_is_xscale"
- "*
- output_add_immediate (operands);
- output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
- return \"\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
-)
-
-(define_insn "*reload_muladdsi_compare0_scratch"
- [(set (reg:CC_NOOV CC_REGNUM)
- (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
- (match_operand:SI 3 "" "r")
- (match_operand:SI 4 "" "r"))
- (match_operand:SI 1 "" "r"))
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=&r"))]
- "TARGET_ARM && reload_in_progress"
- "*
- output_add_immediate (operands);
- return \"mla%?s\\t%0, %3, %4, %0\";
- "
- [(set_attr "length" "20")
- (set_attr "conds" "set")
- (set_attr "type" "mult")]
-)
-
(define_insn "*and_scc"
@@ -8506,7 +8436,7 @@
; We must watch to see that the source/destination register isn't also the
; same as the base address register, and that if the index is a register,
; that it is not the same as the base address register. In such cases the
-; instruction that we would generate would have UNPREDICTABLE behaviour so
+; instruction that we would generate would have UNPREDICTABLE behavior so
; we cannot use it.
(define_peephole
@@ -8759,18 +8689,27 @@
"
)
+;; Note - although unspec_volatile's USE all hard registers,
+;; USEs are ignored after relaod has completed. Thus we need
+;; to add an unspec of the link register to ensure that flow
+;; does not think that it is unused by the sibcall branch that
+;; will replace the standard function epilogue.
(define_insn "sibcall_epilogue"
- [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
+ [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
+ (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
"TARGET_ARM"
"*
- output_asm_insn (\"%@ Sibcall epilogue\", operands);
if (USE_RETURN_INSN (FALSE))
- return output_return_instruction (NULL, FALSE, FALSE);
+ return output_return_instruction (const_true_rtx, FALSE, FALSE);
return arm_output_epilogue (FALSE);
"
;; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_insn "*epilogue_insns"
@@ -8784,7 +8723,11 @@
"
; Length is absolute worst case
[(set_attr "length" "44")
- (set_attr "type" "block")]
+ (set_attr "type" "block")
+ ;; We don't clobber the conditions, but the potential length of this
+ ;; operation is sufficient to make conditionalizing the sequence
+ ;; unlikely to be profitable.
+ (set_attr "conds" "clob")]
)
(define_expand "eh_epilogue"
@@ -9018,6 +8961,16 @@
[(set_attr "type" "store4")]
)
+(define_insn "stack_tie"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
+ (match_operand:SI 1 "s_register_operand" "r")]
+ UNSPEC_PRLG_STK))]
+ ""
+ ""
+ [(set_attr "length" "0")]
+)
+
;; Similarly for the floating point registers
(define_insn "*push_fp_multi"
[(match_parallel 2 "multi_register_push"
@@ -9090,9 +9043,9 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
@@ -9114,9 +9067,9 @@
{
case MODE_FLOAT:
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
+ assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
break;
}
default:
diff --git a/contrib/gcc/config/arm/coff.h b/contrib/gcc/config/arm/coff.h
index c9f0d92..0a78268 100644
--- a/contrib/gcc/config/arm/coff.h
+++ b/contrib/gcc/config/arm/coff.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
For ARM with COFF object format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
Contributed by Doug Evans (devans@cygnus.com).
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA. */
#endif
/* This is COFF, but prefer stabs. */
-#define SDB_DEBUGGING_INFO
+#define SDB_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
@@ -76,42 +76,12 @@ Boston, MA 02111-1307, USA. */
more efficient, but for Thumb it's better to put them out of band. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
-#undef READONLY_DATA_SECTION
-#define READONLY_DATA_SECTION rdata_section
-#undef RDATA_SECTION_ASM_OP
-#define RDATA_SECTION_ASM_OP "\t.section .rdata"
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata"
#undef CTORS_SECTION_ASM_OP
#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"x\""
#undef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"x\""
-
-/* A list of other sections which the compiler might be "in" at any
- given time. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata
-
-#define SUBTARGET_EXTRA_SECTIONS
-
-/* A list of extra section function definitions. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- RDATA_SECTION_FUNCTION \
- SUBTARGET_EXTRA_SECTION_FUNCTIONS
-
-#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
-
-#define RDATA_SECTION_FUNCTION \
-void \
-rdata_section () \
-{ \
- if (in_section != in_rdata) \
- { \
- fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
- in_section = in_rdata; \
- } \
-}
/* Support the ctors/dtors sections for g++. */
diff --git a/contrib/gcc/config/arm/conix-elf.h b/contrib/gcc/config/arm/conix-elf.h
index b74afdf..4a137d6 100644
--- a/contrib/gcc/config/arm/conix-elf.h
+++ b/contrib/gcc/config/arm/conix-elf.h
@@ -39,6 +39,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm7tdmi
#endif
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-D__arm__ -D__CONIX__ -D__ELF__"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__CONIX__"); \
+ builtin_define ("__ELF__"); \
+ } while (0)
diff --git a/contrib/gcc/config/arm/crti.asm b/contrib/gcc/config/arm/crti.asm
index f3741db..ac58e44 100644
--- a/contrib/gcc/config/arm/crti.asm
+++ b/contrib/gcc/config/arm/crti.asm
@@ -35,7 +35,7 @@
# .init sections. Users may put any desired instructions in those
# sections.
- # Note - this macro is complimented by the FUNC_END macro
+ # Note - this macro is complemented by the FUNC_END macro
# in crtn.asm. If you change this macro you must also change
# that macro match.
.macro FUNC_START
diff --git a/contrib/gcc/config/arm/crtn.asm b/contrib/gcc/config/arm/crtn.asm
index a7f0e9e..2f4b542 100644
--- a/contrib/gcc/config/arm/crtn.asm
+++ b/contrib/gcc/config/arm/crtn.asm
@@ -35,7 +35,7 @@
# fact return. Users may put any desired instructions in those sections.
# This file is the last thing linked into any executable.
- # Note - this macro is complimented by the FUNC_START macro
+ # Note - this macro is complemented by the FUNC_START macro
# in crti.asm. If you change this macro you must also change
# that macro match.
#
diff --git a/contrib/gcc/config/arm/elf.h b/contrib/gcc/config/arm/elf.h
index 1cab2c4..0ad23f8 100644
--- a/contrib/gcc/config/arm/elf.h
+++ b/contrib/gcc/config/arm/elf.h
@@ -36,21 +36,27 @@ Boston, MA 02111-1307, USA. */
#ifndef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
- { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC },
+ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
+ { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC },
#endif
#ifndef SUBTARGET_EXTRA_ASM_SPEC
#define SUBTARGET_EXTRA_ASM_SPEC ""
#endif
+#ifndef SUBTARGET_ASM_FLOAT_SPEC
+#define SUBTARGET_ASM_FLOAT_SPEC "\
+%{mapcs-float:-mfloat} %{msoft-float:-mno-fpu}"
+#endif
+
#ifndef ASM_SPEC
#define ASM_SPEC "\
%{mbig-endian:-EB} \
-%{mcpu=*:-m%*} \
-%{march=*:-m%*} \
+%{mlittle-endian:-EL} \
+%{mcpu=*:-mcpu=%*} \
+%{march=*:-march=%*} \
%{mapcs-*:-mapcs-%*} \
-%{mapcs-float:-mfloat} \
-%{msoft-float:-mno-fpu} \
+%(subtarget_asm_float_spec) \
%{mthumb-interwork:-mthumb-interwork} \
%(subtarget_extra_asm_spec)"
#endif
@@ -58,22 +64,18 @@ Boston, MA 02111-1307, USA. */
/* The ARM uses @ are a comment character so we need to redefine
TYPE_OPERAND_FMT. */
#undef TYPE_OPERAND_FMT
-#define TYPE_OPERAND_FMT "%s"
+#define TYPE_OPERAND_FMT "%%%s"
/* We might need a ARM specific header to function declarations. */
#undef ASM_DECLARE_FUNCTION_NAME
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- do \
- { \
- ARM_DECLARE_FUNCTION_NAME (FILE, NAME, DECL); \
- fprintf (FILE, "%s", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
- fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
- putc ('\n', FILE); \
- ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
- } \
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+ do \
+ { \
+ ARM_DECLARE_FUNCTION_NAME (FILE, NAME, DECL); \
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
+ ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
+ ASM_OUTPUT_LABEL(FILE, NAME); \
+ } \
while (0)
/* We might need an ARM specific trailer for function declarations. */
@@ -83,20 +85,7 @@ Boston, MA 02111-1307, USA. */
{ \
ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \
if (!flag_inhibit_size_directive) \
- { \
- char label[256]; \
- static int labelno; \
- labelno ++; \
- ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
- fprintf (FILE, "%s", SIZE_ASM_OP); \
- assemble_name (FILE, (FNAME)); \
- fprintf (FILE, ","); \
- assemble_name (FILE, label); \
- fprintf (FILE, "-"); \
- assemble_name (FILE, (FNAME)); \
- putc ('\n', FILE); \
- } \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
} \
while (0)
@@ -108,7 +97,7 @@ Boston, MA 02111-1307, USA. */
#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ARM)
#ifndef LINK_SPEC
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
+#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X"
#endif
/* Run-time Target Specification. */
diff --git a/contrib/gcc/config/arm/freebsd.h b/contrib/gcc/config/arm/freebsd.h
index a9b268c..0d417a2 100644
--- a/contrib/gcc/config/arm/freebsd.h
+++ b/contrib/gcc/config/arm/freebsd.h
@@ -41,9 +41,6 @@ Boston, MA 02111-1307, USA. */
/* We use the GCC defaults here. */
#undef WCHAR_TYPE
-#undef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
diff --git a/contrib/gcc/config/arm/linux-elf.h b/contrib/gcc/config/arm/linux-elf.h
index f1c86d2..c6d14e7 100644
--- a/contrib/gcc/config/arm/linux-elf.h
+++ b/contrib/gcc/config/arm/linux-elf.h
@@ -48,9 +48,9 @@ Boston, MA 02111-1307, USA. */
/* Now we define the strings used to build the spec file. */
#define LIB_SPEC \
- "%{shared: -lc} \
- %{!shared: %{pthread:-lpthread} \
- %{profile:-lc_p} %{!profile: -lc}}"
+ "%{pthread:-lpthread} \
+ %{shared:-lc} \
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
@@ -89,13 +89,15 @@ Boston, MA 02111-1307, USA. */
%{mbig-endian:-EB}" \
SUBTARGET_EXTRA_LINK_SPEC
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
-"-Dunix -D__gnu_linux__ -Dlinux -D__ELF__ \
--Asystem=unix -Asystem=posix"
-
-/* Allow #sccs in preprocessor. */
-#define SCCS_DIRECTIVE
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } while (0)
/* This is how we tell the assembler that two symbols have the same value. */
#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
diff --git a/contrib/gcc/config/arm/linux-gas.h b/contrib/gcc/config/arm/linux-gas.h
index b4e346d..5e8ddf9 100644
--- a/contrib/gcc/config/arm/linux-gas.h
+++ b/contrib/gcc/config/arm/linux-gas.h
@@ -45,7 +45,7 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-/* Emit code to set up a trampoline and synchronise the caches. */
+/* Emit code to set up a trampoline and synchronize the caches. */
#undef INITIALIZE_TRAMPOLINE
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
diff --git a/contrib/gcc/config/arm/netbsd-elf.h b/contrib/gcc/config/arm/netbsd-elf.h
new file mode 100644
index 0000000..0d5b798
--- /dev/null
+++ b/contrib/gcc/config/arm/netbsd-elf.h
@@ -0,0 +1,177 @@
+/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
+ Copyright (C) 2002 Free Software Foundation, Inc.
+ Contributed by Wasabi Systems, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Run-time Target Specification. */
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (NetBSD/arm ELF)", stderr);
+
+/* This is used in ASM_FILE_START. */
+#undef ARM_OS_NAME
+#define ARM_OS_NAME "NetBSD"
+
+/* arm.h defaults to ARM6 CPU. */
+
+/* This defaults us to little-endian. */
+#ifndef TARGET_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT 0
+#endif
+
+#undef MULTILIB_DEFAULTS
+
+/* Default it to use ATPCS with soft-VFP. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (ARM_FLAG_APCS_32 \
+ | ARM_FLAG_SOFT_FLOAT \
+ | ARM_FLAG_APCS_FRAME \
+ | ARM_FLAG_ATPCS \
+ | ARM_FLAG_VFP \
+ | ARM_FLAG_MMU_TRAPS \
+ | TARGET_ENDIAN_DEFAULT)
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ } \
+ while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
+
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC \
+ "-matpcs %{fpic:-k} %{fPIC:-k}"
+
+/* Default floating point model is soft-VFP.
+ FIXME: -mhard-float currently implies FPA. */
+#undef SUBTARGET_ASM_FLOAT_SPEC
+#define SUBTARGET_ASM_FLOAT_SPEC \
+ "%{mhard-float:-mfpu=fpa} \
+ %{msoft-float:-mfpu=softvfp} \
+ %{!mhard-float: \
+ %{!msoft-float:-mfpu=softvfp}}"
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "subtarget_extra_asm_spec", SUBTARGET_EXTRA_ASM_SPEC }, \
+ { "subtarget_asm_float_spec", SUBTARGET_ASM_FLOAT_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
+
+#define NETBSD_ENTRY_POINT "__start"
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "-X %{mbig-endian:-EB} %{mlittle-endian:-EL} \
+ %(netbsd_link_spec)"
+
+/* Make GCC agree with <machine/ansi.h>. */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+
+/* We don't have any limit on the length as out debugger is GDB. */
+#undef DBX_CONTIN_LENGTH
+
+/* NetBSD does its profiling differently to the Acorn compiler. We
+ don't need a word following the mcount call; and to skip it
+ requires either an assembly stub or use of fomit-frame-pointer when
+ compiling the profiling functions. Since we break Acorn CC
+ compatibility below a little more won't hurt. */
+
+#undef ARM_FUNCTION_PROFILER
+#define ARM_FUNCTION_PROFILER(STREAM,LABELNO) \
+{ \
+ asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
+ asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \
+ NEED_PLT_RELOC ? "(PLT)" : ""); \
+}
+
+/* VERY BIG NOTE: Change of structure alignment for NetBSD/arm.
+ There are consequences you should be aware of...
+
+ Normally GCC/arm uses a structure alignment of 32 for compatibility
+ with armcc. This means that structures are padded to a word
+ boundary. However this causes problems with bugged NetBSD kernel
+ code (possibly userland code as well - I have not checked every
+ binary). The nature of this bugged code is to rely on sizeof()
+ returning the correct size of various structures rounded to the
+ nearest byte (SCSI and ether code are two examples, the vm system
+ is another). This code breaks when the structure alignment is 32
+ as sizeof() will report a word=rounded size. By changing the
+ structure alignment to 8. GCC will conform to what is expected by
+ NetBSD.
+
+ This has several side effects that should be considered.
+ 1. Structures will only be aligned to the size of the largest member.
+ i.e. structures containing only bytes will be byte aligned.
+ structures containing shorts will be half word alinged.
+ structures containing ints will be word aligned.
+
+ This means structures should be padded to a word boundary if
+ alignment of 32 is required for byte structures etc.
+
+ 2. A potential performance penalty may exist if strings are no longer
+ word aligned. GCC will not be able to use word load/stores to copy
+ short strings.
+
+ This modification is not encouraged but with the present state of the
+ NetBSD source tree it is currently the only solution that meets the
+ requirements. */
+
+#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
+#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+
+/* Emit code to set up a trampoline and synchronize the caches. */
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+do \
+ { \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
+ (CXT)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
+ (FNADDR)); \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
+ } \
+while (0)
+
+/* Clear the instruction cache from `BEG' to `END'. This makes a
+ call to the ARM_SYNC_ICACHE architecture specific syscall. */
+#define CLEAR_INSN_CACHE(BEG, END) \
+do \
+ { \
+ extern int sysarch(int number, void *args); \
+ struct \
+ { \
+ unsigned int addr; \
+ int len; \
+ } s; \
+ s.addr = (unsigned int)(BEG); \
+ s.len = (END) - (BEG); \
+ (void) sysarch (0, &s); \
+ } \
+while (0)
diff --git a/contrib/gcc/config/arm/netbsd.h b/contrib/gcc/config/arm/netbsd.h
index 2be49d8..38ccc3f 100644
--- a/contrib/gcc/config/arm/netbsd.h
+++ b/contrib/gcc/config/arm/netbsd.h
@@ -44,16 +44,22 @@ Boston, MA 02111-1307, USA. */
/* Some defines for CPP.
arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
--Dunix -Driscbsd -Darm32 -D__arm32__ -D__arm__ -D__NetBSD__ \
--Asystem=unix -Asystem=NetBSD"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ NETBSD_OS_CPP_BUILTINS_AOUT(); \
+ builtin_define_std ("arm32"); \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("riscbsd"); \
+ } while (0)
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_AOUT },
-/* Define _POSIX_SOURCE if necessary. */
#undef CPP_SPEC
#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) \
-%{posix:-D_POSIX_SOURCE} \
+%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
"
/* Because TARGET_DEFAULT sets ARM_FLAG_APCS_32 */
@@ -66,10 +72,7 @@ Boston, MA 02111-1307, USA. */
/* Pass -X to the linker so that it will strip symbols starting with 'L' */
#undef LINK_SPEC
-#define LINK_SPEC "\
--X %{!shared:%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{R*} \
-%{static:-Bstatic}} %{shared} %{assert*} \
-"
+#define LINK_SPEC "-X %(netbsd_link_spec)"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -77,7 +80,7 @@ Boston, MA 02111-1307, USA. */
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "int"
-#define HANDLE_SYSV_PRAGMA
+#define HANDLE_SYSV_PRAGMA 1
/* We don't have any limit on the length as out debugger is GDB. */
#undef DBX_CONTIN_LENGTH
@@ -142,3 +145,30 @@ Boston, MA 02111-1307, USA. */
requirements. */
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
+
+/* Emit code to set up a trampoline and synchronize the caches. */
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
+ (CXT)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
+ (FNADDR)); \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
+}
+
+/* Clear the instruction cache from `BEG' to `END'. This makes a
+ call to the ARM32_SYNC_ICACHE architecture specific syscall. */
+#define CLEAR_INSN_CACHE(BEG, END) \
+{ \
+ extern int sysarch(int number, void *args); \
+ struct { \
+ unsigned int addr; \
+ int len; \
+ } s; \
+ s.addr = (unsigned int)(BEG); \
+ s.len = (END) - (BEG); \
+ (void)sysarch(0, &s); \
+}
diff --git a/contrib/gcc/config/arm/pe.c b/contrib/gcc/config/arm/pe.c
index 8360f85..ee3da8f 100644
--- a/contrib/gcc/config/arm/pe.c
+++ b/contrib/gcc/config/arm/pe.c
@@ -1,5 +1,5 @@
/* Routines for GCC for ARM/pe.
- Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
extern int current_function_anonymous_args;
-/* Return non-zero if DECL is a dllexport'd object. */
+/* Return nonzero if DECL is a dllexport'd object. */
tree current_class_type; /* FIXME */
@@ -52,7 +52,7 @@ arm_dllexport_p (decl)
return 0;
}
-/* Return non-zero if DECL is a dllimport'd object. */
+/* Return nonzero if DECL is a dllimport'd object. */
int
arm_dllimport_p (decl)
@@ -74,7 +74,7 @@ arm_dllimport_p (decl)
return 0;
}
-/* Return non-zero if SYMBOL is marked as being dllexport'd. */
+/* Return nonzero if SYMBOL is marked as being dllexport'd. */
int
arm_dllexport_name_p (symbol)
@@ -83,7 +83,7 @@ arm_dllexport_name_p (symbol)
return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
}
-/* Return non-zero if SYMBOL is marked as being dllimport'd. */
+/* Return nonzero if SYMBOL is marked as being dllimport'd. */
int
arm_dllimport_name_p (symbol)
@@ -204,13 +204,12 @@ arm_mark_dllimport (decl)
XEXP (DECL_RTL (decl), 0) = newrtl;
}
-/* Cover function to implement ENCODE_SECTION_INFO. */
-
void
-arm_pe_encode_section_info (decl)
+arm_pe_encode_section_info (decl, first)
tree decl;
+ int first ATTRIBUTE_UNUSED;
{
- /* This bit is copied from arm.h. */
+ /* This bit is copied from arm_encode_section_info. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
{
@@ -247,8 +246,6 @@ arm_pe_encode_section_info (decl)
}
}
-/* Cover function for UNIQUE_SECTION. */
-
void
arm_pe_unique_section (decl, reloc)
tree decl;
@@ -260,15 +257,14 @@ arm_pe_unique_section (decl, reloc)
const char * prefix;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- /* Strip off any encoding in fnname. */
- STRIP_NAME_ENCODING (name, name);
+ name = arm_strip_name_encoding (name);
/* The object is put in, for example, section .text$foo.
The linker will then ultimately place them in .text
(everything from the $ on is stripped). */
if (TREE_CODE (decl) == FUNCTION_DECL)
prefix = ".text$";
- else if (DECL_READONLY_SECTION (decl, reloc))
+ else if (decl_readonly_section (decl, reloc))
prefix = ".rdata$";
else
prefix = ".data$";
diff --git a/contrib/gcc/config/arm/pe.h b/contrib/gcc/config/arm/pe.h
index 1182aac..38727da 100644
--- a/contrib/gcc/config/arm/pe.h
+++ b/contrib/gcc/config/arm/pe.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
- Copyright (C) 1995, 1996, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1999, 2000, 2002 Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GNU CC.
@@ -94,30 +94,13 @@ Boston, MA 02111-1307, USA. */
1,1,1 \
}
-/* In addition to the stuff done in arm.h, we must mark dll symbols specially.
- Definitions of dllexport'd objects install some info in the .drectve
- section. References to dllimport'd objects are fetched indirectly via
- __imp_. If both are declared, dllexport overrides.
- This is also needed to implement one-only vtables: they go into their own
- section and we need to set DECL_SECTION_NAME so we do that here.
- Note that we can be called twice on the same decl. */
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) \
- arm_pe_encode_section_info (DECL)
-
-/* Used to implement dllexport overriding dllimport semantics. It's also used
- to handle vtables - the first pass won't do anything because
- DECL_CONTEXT (DECL) will be 0 so arm_dll{ex,im}port_p will return 0.
- It's also used to handle dllimport override semantics. */
-#define REDO_SECTION_INFO_P(DECL) 1
-
/* Define this macro if in some cases global symbols from one translation
unit may not be bound to undefined symbols in another translation unit
without user intervention. For instance, under Microsoft Windows
symbols must be explicitly imported from shared libraries (DLLs). */
#define MULTIPLE_SYMBOL_SPACES
-#define UNIQUE_SECTION(DECL, RELOC) arm_pe_unique_section (DECL, RELOC)
+#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
#define SUPPORTS_ONE_ONLY 1
@@ -206,13 +189,13 @@ Boston, MA 02111-1307, USA. */
/* A list of other sections which the compiler might be "in" at any
given time. */
-#undef SUBTARGET_EXTRA_SECTIONS
-#define SUBTARGET_EXTRA_SECTIONS in_drectve,
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_drectve
/* A list of extra section function definitions. */
-#undef SUBTARGET_EXTRA_SECTION_FUNCTIONS
-#define SUBTARGET_EXTRA_SECTION_FUNCTIONS \
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
DRECTVE_SECTION_FUNCTION \
SWITCH_TO_SECTION_FUNCTION
@@ -245,7 +228,7 @@ switch_to_section (section, decl) \
case in_text: text_section (); break; \
case in_data: data_section (); break; \
case in_named: named_section (decl, NULL, 0); break; \
- case in_rdata: rdata_section (); break; \
+ case in_readonly_data: readonly_data_section (); break; \
case in_ctors: ctors_section (); break; \
case in_dtors: dtors_section (); break; \
case in_drectve: drectve_section (); break; \
diff --git a/contrib/gcc/config/arm/rtems-elf.h b/contrib/gcc/config/arm/rtems-elf.h
index 312c96f..27928db 100644
--- a/contrib/gcc/config/arm/rtems-elf.h
+++ b/contrib/gcc/config/arm/rtems-elf.h
@@ -24,5 +24,9 @@ Boston, MA 02111-1307, USA. */
#define HAS_INIT_SECTION
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__rtems__ -D__ELF__ -Asystem=rtems"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__ELF__"); \
+ builtin_assert ("system=rtems"); \
+ } while (0)
diff --git a/contrib/gcc/config/arm/semi.h b/contrib/gcc/config/arm/semi.h
index 54ea0e8b..2e1abd4 100644
--- a/contrib/gcc/config/arm/semi.h
+++ b/contrib/gcc/config/arm/semi.h
@@ -61,8 +61,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_SPEC "\
%{fpic: -k} %{fPIC: -k} \
%{mbig-endian:-EB} \
-%{mcpu=*:-m%*} \
-%{march=*:-m%*} \
+%{mcpu=*:-mcpu=%*} \
+%{march=*:-march=%*} \
%{mapcs-float:-mfloat} \
%{msoft-float:-mno-fpu} \
%{mthumb-interwork:-mthumb-interwork} \
diff --git a/contrib/gcc/config/arm/semiaof.h b/contrib/gcc/config/arm/semiaof.h
index 7ca68bc..6ee17ef 100644
--- a/contrib/gcc/config/arm/semiaof.h
+++ b/contrib/gcc/config/arm/semiaof.h
@@ -20,8 +20,11 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define CPP_PREDEFINES \
- "-Darm -Dsemi"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define_std ("arm"); \
+ builtin_define_std ("semi"); \
+ } while (0)
#define ASM_SPEC "%{g -g} -arch 4 \
-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/32bit}}"
diff --git a/contrib/gcc/config/arm/t-arm-elf b/contrib/gcc/config/arm/t-arm-elf
index d94b5d2..0011b2a 100644
--- a/contrib/gcc/config/arm/t-arm-elf
+++ b/contrib/gcc/config/arm/t-arm-elf
@@ -25,16 +25,18 @@ MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb
MULTILIB_EXCEPTIONS =
-# MULTILIB_OPTIONS = mlittle-endian/mbig-endian
-# MULTILIB_DIRNAMES = le be
+# MULTILIB_OPTIONS += mlittle-endian/mbig-endian
+# MULTILIB_DIRNAMES += le be
# MULTILIB_EXCEPTIONS =
# MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
#
# MULTILIB_OPTIONS += mhard-float/msoft-float
# MULTILIB_DIRNAMES += fpu soft
+# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
#
# MULTILIB_OPTIONS += mapcs-32/mapcs-26
# MULTILIB_DIRNAMES += 32bit 26bit
+# MULTILIB_EXCEPTIONS += *mthumb/*mapcs-26*
#
# MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
# MULTILIB_DIRNAMES += normal interwork
diff --git a/contrib/gcc/config/arm/t-pe b/contrib/gcc/config/arm/t-pe
index 4de3665..f559bd2 100644
--- a/contrib/gcc/config/arm/t-pe
+++ b/contrib/gcc/config/arm/t-pe
@@ -20,7 +20,8 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-pe.o: $(srcdir)/config/arm/pe.c
+pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) output.h \
+ flags.h $(TREE_H) $(EXPR_H) toplev.h $(TM_P_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
MULTILIB_OPTIONS = mhard-float mthumb
diff --git a/contrib/gcc/config/arm/unknown-elf-oabi.h b/contrib/gcc/config/arm/unknown-elf-oabi.h
index cc58f3a..91f18c0 100644
--- a/contrib/gcc/config/arm/unknown-elf-oabi.h
+++ b/contrib/gcc/config/arm/unknown-elf-oabi.h
@@ -23,10 +23,7 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/ELF non-Linux old abi)", stderr);
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Darm_oabi -Darm -Darm_elf -Acpu=arm -Amachine=arm -D__ELF__"
-
#undef ASM_SPEC
-#define ASM_SPEC "-moabi %{mbig-endian:-EB} %{mcpu=*:-m%*} %{march=*:-m%*} \
+#define ASM_SPEC "-moabi %{mbig-endian:-EB} %{mcpu=*:-mcpu=%*} %{march=*:-march=%*} \
%{mapcs-*:-mapcs-%*} %{mthumb-interwork:-mthumb-interwork}"
diff --git a/contrib/gcc/config/arm/unknown-elf.h b/contrib/gcc/config/arm/unknown-elf.h
index 0741884..7f9211b 100644
--- a/contrib/gcc/config/arm/unknown-elf.h
+++ b/contrib/gcc/config/arm/unknown-elf.h
@@ -47,7 +47,7 @@ Boston, MA 02111-1307, USA. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-/* Return a non-zero value if DECL has a section attribute. */
+/* Return a nonzero value if DECL has a section attribute. */
#define IN_NAMED_SECTION(DECL) \
((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
&& DECL_SECTION_NAME (DECL) != NULL_TREE)
@@ -61,7 +61,7 @@ Boston, MA 02111-1307, USA. */
else \
bss_section (); \
\
- ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
\
@@ -82,14 +82,10 @@ Boston, MA 02111-1307, USA. */
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (FILE, NAME); \
- fprintf (FILE, "\t.space\t%d\n", SIZE); \
+ fprintf (FILE, "\t.space\t%d\n", SIZE ? SIZE : 1); \
} \
while (0)
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__ELF__"
-#endif
-
#ifndef CPP_APCS_PC_DEFAULT_SPEC
#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
#endif
diff --git a/contrib/gcc/config/arm/vxarm.h b/contrib/gcc/config/arm/vxarm.h
index 7559364..473362e 100644
--- a/contrib/gcc/config/arm/vxarm.h
+++ b/contrib/gcc/config/arm/vxarm.h
@@ -37,8 +37,10 @@ Boston, MA 02111-1307, USA. */
%{!mcpu*:%{!march=*:-DCPU=ARM710A}} \
"
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-D__vxworks -Acpu=arm -Amachine=arm"
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__vxworks"); \
+ } while (0)
/* VxWorks does all the library stuff itself. */
#undef LIB_SPEC
diff --git a/contrib/gcc/config/arm/xscale-coff.h b/contrib/gcc/config/arm/xscale-coff.h
index 51fe693..d8fee7d 100644
--- a/contrib/gcc/config/arm/xscale-coff.h
+++ b/contrib/gcc/config/arm/xscale-coff.h
@@ -24,7 +24,7 @@
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mxscale}"
+#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale}"
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
diff --git a/contrib/gcc/config/arm/xscale-elf.h b/contrib/gcc/config/arm/xscale-elf.h
index b1ce04e..8ea3588 100644
--- a/contrib/gcc/config/arm/xscale-elf.h
+++ b/contrib/gcc/config/arm/xscale-elf.h
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_xscale
#endif
-#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mxscale} %{!mhard-float:-mno-fpu}"
+#define SUBTARGET_EXTRA_ASM_SPEC "%{!mcpu=*:-mcpu=xscale} %{!mhard-float:-mno-fpu}"
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
OpenPOWER on IntegriCloud