aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/arm/arm.c190
-rw-r--r--gcc/config/arm/arm.h103
3 files changed, 269 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 30f0230..2e17b20 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2000-02-09 Philip Blundell <pb@futuretv.com>
+
+ * config/arm/arm.c (legitimize_pic_address): Handle LABEL_REF
+ correctly.
+
+ * config/arm/arm.h (LEGITIMATE_CONSTANT_P): Allow anything when
+ generating PIC.
+ (LEGITIMATE_PIC_OPERAND): Disallow references to labels.
+
2000-02-09 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.c (cpp_define, cpp_undef): Make sure the stacked buffer
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c3c5360..6560893 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1476,6 +1476,181 @@ arm_return_in_memory (type)
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. */
+void
+arm_init_cumulative_args (pcum, fntype, libname, indirect)
+ CUMULATIVE_ARGS * pcum;
+ tree fntype;
+ rtx libname ATTRIBUTE_UNUSED;
+ int indirect ATTRIBUTE_UNUSED;
+{
+ /* On the ARM, the offset starts at 0. */
+ pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype)))
+ ? 1 : 0);
+
+ pcum->call_cookie = CALL_NORMAL;
+
+ if (TARGET_LONG_CALLS)
+ pcum->call_cookie = CALL_LONG;
+
+ /* Check for long call/short call attributes. The attributes
+ override any command line option. */
+ if (fntype)
+ {
+ if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype)))
+ pcum->call_cookie = CALL_SHORT;
+ else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype)))
+ pcum->call_cookie = CALL_LONG;
+ }
+}
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+rtx
+arm_function_arg (pcum, mode, type, named)
+ CUMULATIVE_ARGS * pcum;
+ enum machine_mode mode;
+ tree type ATTRIBUTE_UNUSED;
+ int named;
+{
+ if (mode == VOIDmode)
+ /* Compute operand 2 of the call insn. */
+ return GEN_INT (pcum->call_cookie);
+
+ if (! named || pcum->nregs >= NUM_ARG_REGS)
+ return NULL_RTX;
+
+ return gen_rtx_REG (mode, pcum->nregs);
+}
+
+
+/* Return 1 if the operand is a SYMBOL_REF for a function known to be in
+ this file. */
+static int
+current_file_function_operand (sym_ref)
+ rtx sym_ref;
+{
+ return (SYMBOL_REF_FLAG (sym_ref)
+ || sym_ref == XEXP (DECL_RTL (current_function_decl), 0));
+}
+
+/* Return non-zero if a 32 bit "long call" should be generated for this
+ call.
+
+ We generate a long call if the function is not declared
+ __attribute__ ((short_call),
+
+ AND:
+
+ (1) the function is declared __attribute__ ((long_call))
+
+ OR
+
+ (2) -mlong-calls is enabled and we don't know whether the target
+ function is declared in this file.
+
+ This function will typically be called by C fragments in the machine
+ description file. CALL_REF is the matched rtl operand. CALL_COOKIE
+ describes the value of the long_call and short_call attributes for
+ the called functiion. CALL_SYMBOL is used to distinguish between
+ two different callers of the function. It is set to 1 in the "call_symbol"
+ and "call_symbol_value" patterns in arm.md and to 0 in the "call" and
+ "call_value" patterns. This is because of the difference of SYM_REFs passed
+ from "call_symbol" and "call" patterns. */
+int
+arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
+ rtx sym_ref;
+ int call_cookie;
+ int call_symbol;
+{
+ if (! call_symbol)
+ {
+ if (GET_CODE (sym_ref) != MEM)
+ return 0;
+
+ sym_ref = XEXP (sym_ref, 0);
+ }
+
+ if (GET_CODE (sym_ref) != SYMBOL_REF)
+ return 0;
+
+ if (call_cookie & CALL_SHORT)
+ return 0;
+
+ if (TARGET_LONG_CALLS && flag_function_sections)
+ return 1;
+
+ if (current_file_function_operand (sym_ref, VOIDmode))
+ return 0;
+
+ return (call_cookie & CALL_LONG) || TARGET_LONG_CALLS;
+}
+
+/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
+ attribute for TYPE. The attributes in ATTRIBUTES have previously been
+ assigned to TYPE. */
+int
+arm_valid_type_attribute_p (type, attributes, identifier, args)
+ tree type;
+ tree attributes ATTRIBUTE_UNUSED;
+ tree identifier;
+ tree args;
+{
+ if ( TREE_CODE (type) != FUNCTION_TYPE
+ && TREE_CODE (type) != METHOD_TYPE
+ && TREE_CODE (type) != FIELD_DECL
+ && TREE_CODE (type) != TYPE_DECL)
+ return 0;
+
+ /* Function calls made to this symbol must be done indirectly, because
+ it may lie outside of the 26 bit addressing range of a normal function
+ call. */
+ if (is_attribute_p ("long_call", identifier))
+ return (args == NULL_TREE);
+
+ /* Whereas these functions are always known to reside within the 26 bit
+ addressing range. */
+ if (is_attribute_p ("short_call", identifier))
+ return (args == NULL_TREE);
+
+ return 0;
+}
+
+/* Return 0 if the attributes for two types are incompatible, 1 if they
+ are compatible, and 2 if they are nearly compatible (which causes a
+ warning to be generated). */
+int
+arm_comp_type_attributes (type1, type2)
+ tree type1;
+ tree type2;
+{
+ int l1, l2, s1, s2;
+ /* Check for mismatch of non-default calling convention. */
+ if (TREE_CODE (type1) != FUNCTION_TYPE)
+ return 1;
+
+ /* Check for mismatched call attributes. */
+ l1 = ! lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1));
+ l2 = ! lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2));
+ s1 = ! lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1));
+ s2 = ! lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2));
+
+ return ! ((l1 ^ l2) || (s1 ^s2) || (l1 | s2) || (s1 | l2));
+}
+
+
int
legitimate_pic_operand_p (x)
rtx x;
@@ -1590,7 +1765,20 @@ legitimize_pic_address (orig, mode, reg)
return gen_rtx_PLUS (Pmode, base, offset);
}
else if (GET_CODE (orig) == LABEL_REF)
- current_function_uses_pic_offset_table = 1;
+ {
+ current_function_uses_pic_offset_table = 1;
+
+ if (NEED_GOT_RELOC)
+ {
+ rtx pic_ref, address = gen_reg_rtx (Pmode);
+
+ emit_insn (gen_pic_load_addr (address, orig));
+ pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
+
+ emit_move_insn (address, pic_ref);
+ return address;
+ }
+ }
return orig;
}
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 33f5932..f457f92 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM.
- Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 94, 05, 96, 97, 98, 99, 2000 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)
@@ -48,7 +48,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_CPU_strongarm1100 0x0040
#define TARGET_CPU_arm9 0x0080
#define TARGET_CPU_arm9tdmi 0x0080
-/* Configure didn't specify */
+/* Configure didn't specify. */
#define TARGET_CPU_generic 0x8000
enum arm_cond_code
@@ -365,7 +365,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Generate re-entrant, PIC code" }, \
{"no-apcs-reentrant", -ARM_FLAG_APCS_REENT, "" }, \
{"alignment-traps", ARM_FLAG_MMU_TRAPS, \
- "The MMU will trap on unaligned accesses" },\
+ "The MMU will trap on unaligned accesses" }, \
{"no-alignment-traps", -ARM_FLAG_MMU_TRAPS, "" }, \
{"short-load-bytes", ARM_FLAG_MMU_TRAPS, "" }, \
{"no-short-load-bytes", -ARM_FLAG_MMU_TRAPS, "" }, \
@@ -385,7 +385,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Support calls between THUMB and ARM instructions sets" }, \
{"no-thumb-interwork", -ARM_FLAG_INTERWORK, "" }, \
{"abort-on-noreturn", ARM_FLAG_ABORT_NORETURN, \
- "Generate a call to abort if a noreturn function returns"}, \
+ "Generate a call to abort if a noreturn function returns"},\
{"no-abort-on-noreturn", -ARM_FLAG_ABORT_NORETURN, ""}, \
{"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, \
"Do not move instructions into a function's prologue" }, \
@@ -394,7 +394,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Do not load the PIC register in function prologues" }, \
{"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \
{"long-calls", ARM_FLAG_LONG_CALLS, \
- "Generate all call instructions as indirect calls"}, \
+ "Generate all call instructions as indirect calls"}, \
{"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT, "" } \
@@ -411,7 +411,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
{"fp=", & target_fp_name, \
"Specify the version of the floating point emulator" }, \
{ "structure-size-boundary=", & structure_size_string, \
- "Specify the minumum bit alignment of structures" }, \
+ "Specify the minimum bit alignment of structures" }, \
{ "pic-register=", & arm_pic_register_string, \
"Specify the register to be used for PIC addressing" } \
}
@@ -1136,6 +1136,23 @@ enum reg_class
than a word, or if they contain elements offset from zero in the struct. */
#define DEFAULT_PCC_STRUCT_RETURN 0
+/* A C type for declaring a variable that is used as the first argument of
+ `FUNCTION_ARG' and other related values. For some target machines, the
+ type `int' suffices and can hold the number of bytes of argument so far. */
+typedef struct
+{
+ /* This is the number of argument registers scanned so far. */
+ int nregs;
+ /* instructions on how to process this call. */
+ int call_cookie;
+}
+CUMULATIVE_ARGS;
+
+/* Flags for the call_cookie field of CUMULATIVE_ARGS. */
+#define CALL_NORMAL 0 /* No special processing. */
+#define CALL_LONG 1 /* Always call indirect. */
+#define CALL_SHORT 2 /* Never call indirect. */
+
/* Define where to put the arguments to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -1154,38 +1171,29 @@ enum reg_class
only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is
passed in the stack (function_prologue will indeed make it pass in the
stack if necessary). */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((NAMED) \
- ? ((CUM) >= NUM_ARG_REGS ? 0 : gen_rtx_REG (MODE, CUM))\
- : 0)
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
/* For an arg passed partly in registers and partly in memory,
this is the number of registers used.
For args passed entirely in registers or entirely in memory, zero. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- ( NUM_ARG_REGS > (CUM) \
- && (NUM_ARG_REGS < ((CUM) + NUM_REGS2 (MODE, TYPE))) \
- ? NUM_ARG_REGS - (CUM) : 0)
-
-/* A C type for declaring a variable that is used as the first argument of
- `FUNCTION_ARG' and other related values. For some target machines, the
- type `int' suffices and can hold the number of bytes of argument so far.
-
- On the ARM, this is the number of bytes of arguments scanned so far. */
-#define CUMULATIVE_ARGS int
+ ( NUM_ARG_REGS > (CUM).nregs \
+ && (NUM_ARG_REGS < ((CUM).nregs + NUM_REGS2 (MODE, TYPE))) \
+ ? NUM_ARG_REGS - (CUM).nregs : 0)
/* 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.
On the ARM, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM) = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) ? 1 : 0))
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+ arm_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (INDIRECT))
/* Update the data in CUM to advance over an argument
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) += NUM_REGS2 (MODE, TYPE)
+ (CUM).nregs += 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. */
@@ -1209,8 +1217,8 @@ enum reg_class
{ \
extern int current_function_anonymous_args; \
current_function_anonymous_args = 1; \
- if ((CUM) < NUM_ARG_REGS) \
- (PRETEND_SIZE) = (NUM_ARG_REGS - (CUM)) * UNITS_PER_WORD; \
+ if ((CUM).nregs < NUM_ARG_REGS) \
+ (PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
}
/* Generate assembly output for the start of a function. */
@@ -1437,8 +1445,18 @@ enum reg_class
On the ARM, allow any integer (invalid ones are removed later by insn
patterns), nice doubles and symbol_refs which refer to the function's
- constant pool XXX. */
-#define LEGITIMATE_CONSTANT_P(X) (! label_mentioned_p (X))
+ constant pool XXX.
+
+ When generating pic allow anything. */
+#define LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X))
+
+/* If we are referencing a function that is static or is known to be
+ in this file, make the SYMBOL_REF special. We can use this to indicate
+ that we can do direct call to that function. */
+#define ARM_MARK_NEARBY_FUNCTION(decl) \
+ if (TREE_CODE (decl) == FUNCTION_DECL \
+ && (TREE_ASM_WRITTEN (decl) || ! TREE_PUBLIC (decl))) \
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; \
/* 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
@@ -1457,6 +1475,13 @@ enum reg_class
? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
} \
+ \
+ ARM_MARK_NEARBY_FUNCTION (decl) \
+}
+#else
+#define ENCODE_SECTION_INFO(decl) \
+{ \
+ ARM_MARK_NEARBY_FUNCTION (decl) \
}
#endif
@@ -1875,16 +1900,30 @@ 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) \
- && (! CONSTANT_POOL_ADDRESS_P (X) \
- || ! symbol_mentioned_p (get_pool_constant (X))))
+#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))))
/* 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. */
extern int making_const_table;
-
+
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for TYPE.
+ The attributes in ATTRIBUTES have previously been assigned to TYPE. */
+#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
+ (arm_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
+
+/* If defined, a C expression whose value is zero if the attributes on
+ TYPE1 and TYPE2 are incompatible, one if they are compatible, and
+ two if they are nearly compatible (which causes a warning to be
+ generated). */
+#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
+ (arm_comp_type_attributes (TYPE1, TYPE2))
/* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,