***************
*** 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;
+ }
