summaryrefslogtreecommitdiff
path: root/gcc_arm/config/arm/thumb.c.rej
diff options
context:
space:
mode:
Diffstat (limited to 'gcc_arm/config/arm/thumb.c.rej')
-rwxr-xr-xgcc_arm/config/arm/thumb.c.rej168
1 files changed, 168 insertions, 0 deletions
diff --git a/gcc_arm/config/arm/thumb.c.rej b/gcc_arm/config/arm/thumb.c.rej
new file mode 100755
index 0000000..2b5e409
--- /dev/null
+++ b/gcc_arm/config/arm/thumb.c.rej
@@ -0,0 +1,168 @@
+***************
+*** 2103,2105 ****
+ }
+ #endif /* THUMB_PE */
+ /* END CYGNUS LOCAL nickc/thumb-pe */
+--- 2103,2264 ----
+ }
+ #endif /* THUMB_PE */
+ /* END CYGNUS LOCAL nickc/thumb-pe */
++
++ /* Return nonzero if ATTR is a valid attribute for TYPE.
++ ATTRIBUTES are any existing attributes and ARGS are the arguments
++ supplied with ATTR.
++
++ Supported attributes:
++
++ short_call: assume the offset from the caller to the callee is small.
++
++ long_call: don't assume the offset is small. */
++
++ int
++ arm_valid_machine_type_attribute (type, attributes, attr, args)
++ tree type;
++ tree attributes;
++ tree attr;
++ tree args;
++ {
++ if (args != NULL_TREE)
++ return 0;
++
++ if (is_attribute_p ("long_call", attr))
++ return 1;
++
++ if (is_attribute_p ("short_call", attr))
++ return 1;
++
++ return 0;
++ }
++
++ /* Encode long_call or short_call attribute by prefixing
++ symbol name in DECL with a special character FLAG. */
++
++ void
++ arm_encode_call_attribute (decl, flag)
++ tree decl;
++ int flag;
++ {
++ const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
++ int len = strlen (str);
++ char * newstr;
++
++ /* Do not allow weak functions to be treated as short call. */
++ if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
++ return;
++
++ if (ENCODED_SHORT_CALL_ATTR_P (str)
++ || ENCODED_LONG_CALL_ATTR_P (str))
++ return;
++
++ newstr = malloc (len + 2);
++ newstr[0] = flag;
++ strcpy (newstr + 1, str);
++
++ XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
++ }
++
++ /* Return the length of a function name prefix
++ that starts with the character 'c'. */
++
++ static int
++ arm_get_strip_length (char c)
++ {
++ switch (c)
++ {
++ ARM_NAME_ENCODING_LENGTHS
++ default: return 0;
++ }
++ }
++
++ /* Return a pointer to a function's name with any
++ and all prefix encodings stripped from it. */
++
++ char *
++ arm_strip_name_encoding (char * name)
++ {
++ int skip;
++
++ while ((skip = arm_get_strip_length (* name)))
++ name += skip;
++
++ return name;
++ }
++
++ /* Return 1 if the operand is a SYMBOL_REF for a function known to be
++ defined within the current compilation unit. If this caanot be
++ determined, then 0 is returned. */
++
++ static int
++ current_file_function_operand (sym_ref)
++ rtx sym_ref;
++ {
++ /* This is a bit of a fib. A function will have a short call flag
++ applied to its name if it has the short call attribute, or it has
++ already been defined within the current compilation unit. */
++ if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
++ return 1;
++
++ /* The current function is always defined within the current compilation
++ unit. if it s a weak definition however, then this may not be the real
++ definition of the function, and so we have to say no. */
++ if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
++ && !DECL_WEAK (current_function_decl))
++ return 1;
++
++ /* We cannot make the determination - default to returning 0. */
++ return 0;
++ }
++
++ /* Return non-zero 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))
++ or b. the -mlong-calls command line switch has been specified
++
++ However we do not generate a long call if the function:
++
++ c. has an __attribute__ ((short_call))
++ or d. has an __attribute__ ((section))
++ or e. is defined within the current compilation unit.
++
++ This function will be called by C fragments contained in the machine
++ description file. CALL_REF and CALL_COOKIE correspond to the matched
++ rtl operands. 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 and to 0 in the "call"
++ and "call_value" patterns. This is because of the difference in the
++ SYM_REFs passed by these 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))
++ return 0;
++
++ return (call_cookie & CALL_LONG)
++ || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
++ || TARGET_LONG_CALLS;
++ }