summaryrefslogtreecommitdiff
path: root/gcc_arm/config/arm/thumb.c.rej
blob: 2b5e4098d714f5210dcf0fe6c6d714422230362b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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;
+ }