Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/bfin/bfin.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
56 #include "timevar.h" | 56 #include "timevar.h" |
57 #include "df.h" | 57 #include "df.h" |
58 | 58 |
59 /* A C structure for machine-specific, per-function data. | 59 /* A C structure for machine-specific, per-function data. |
60 This is added to the cfun structure. */ | 60 This is added to the cfun structure. */ |
61 struct machine_function GTY(()) | 61 struct GTY(()) machine_function |
62 { | 62 { |
63 /* Set if we are notified by the doloop pass that a hardware loop | 63 /* Set if we are notified by the doloop pass that a hardware loop |
64 was created. */ | 64 was created. */ |
65 int has_hardware_loops; | 65 int has_hardware_loops; |
66 | |
66 /* Set if we create a memcpy pattern that uses loop registers. */ | 67 /* Set if we create a memcpy pattern that uses loop registers. */ |
67 int has_loopreg_clobber; | 68 int has_loopreg_clobber; |
68 }; | 69 }; |
69 | |
70 /* Test and compare insns in bfin.md store the information needed to | |
71 generate branch and scc insns here. */ | |
72 rtx bfin_compare_op0, bfin_compare_op1; | |
73 | 70 |
74 /* RTX for condition code flag register and RETS register */ | 71 /* RTX for condition code flag register and RETS register */ |
75 extern GTY(()) rtx bfin_cc_rtx; | 72 extern GTY(()) rtx bfin_cc_rtx; |
76 extern GTY(()) rtx bfin_rets_rtx; | 73 extern GTY(()) rtx bfin_rets_rtx; |
77 rtx bfin_cc_rtx, bfin_rets_rtx; | 74 rtx bfin_cc_rtx, bfin_rets_rtx; |
83 const char *high_reg_names[] = HIGH_REGISTER_NAMES; | 80 const char *high_reg_names[] = HIGH_REGISTER_NAMES; |
84 const char *dregs_pair_names[] = DREGS_PAIR_NAMES; | 81 const char *dregs_pair_names[] = DREGS_PAIR_NAMES; |
85 const char *byte_reg_names[] = BYTE_REGISTER_NAMES; | 82 const char *byte_reg_names[] = BYTE_REGISTER_NAMES; |
86 | 83 |
87 static int arg_regs[] = FUNCTION_ARG_REGISTERS; | 84 static int arg_regs[] = FUNCTION_ARG_REGISTERS; |
85 static int ret_regs[] = FUNCTION_RETURN_REGISTERS; | |
88 | 86 |
89 /* Nonzero if -mshared-library-id was given. */ | 87 /* Nonzero if -mshared-library-id was given. */ |
90 static int bfin_lib_id_given; | 88 static int bfin_lib_id_given; |
91 | 89 |
92 /* Nonzero if -fschedule-insns2 was given. We override it and | 90 /* Nonzero if -fschedule-insns2 was given. We override it and |
117 }; | 115 }; |
118 | 116 |
119 struct bfin_cpu bfin_cpus[] = | 117 struct bfin_cpu bfin_cpus[] = |
120 { | 118 { |
121 {"bf512", BFIN_CPU_BF512, 0x0000, | 119 {"bf512", BFIN_CPU_BF512, 0x0000, |
122 WA_SPECULATIVE_LOADS}, | 120 WA_SPECULATIVE_LOADS | WA_05000074}, |
123 | 121 |
124 {"bf514", BFIN_CPU_BF514, 0x0000, | 122 {"bf514", BFIN_CPU_BF514, 0x0000, |
125 WA_SPECULATIVE_LOADS}, | 123 WA_SPECULATIVE_LOADS | WA_05000074}, |
126 | 124 |
127 {"bf516", BFIN_CPU_BF516, 0x0000, | 125 {"bf516", BFIN_CPU_BF516, 0x0000, |
128 WA_SPECULATIVE_LOADS}, | 126 WA_SPECULATIVE_LOADS | WA_05000074}, |
129 | 127 |
130 {"bf518", BFIN_CPU_BF518, 0x0000, | 128 {"bf518", BFIN_CPU_BF518, 0x0000, |
131 WA_SPECULATIVE_LOADS}, | 129 WA_SPECULATIVE_LOADS | WA_05000074}, |
132 | 130 |
133 {"bf522", BFIN_CPU_BF522, 0x0002, | 131 {"bf522", BFIN_CPU_BF522, 0x0002, |
134 WA_SPECULATIVE_LOADS}, | 132 WA_SPECULATIVE_LOADS | WA_05000074}, |
135 {"bf522", BFIN_CPU_BF522, 0x0001, | 133 {"bf522", BFIN_CPU_BF522, 0x0001, |
136 WA_SPECULATIVE_LOADS | WA_RETS}, | 134 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
137 {"bf522", BFIN_CPU_BF522, 0x0000, | 135 {"bf522", BFIN_CPU_BF522, 0x0000, |
138 WA_SPECULATIVE_LOADS | WA_RETS}, | 136 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
139 | 137 |
140 {"bf523", BFIN_CPU_BF523, 0x0002, | 138 {"bf523", BFIN_CPU_BF523, 0x0002, |
141 WA_SPECULATIVE_LOADS}, | 139 WA_SPECULATIVE_LOADS | WA_05000074}, |
142 {"bf523", BFIN_CPU_BF523, 0x0001, | 140 {"bf523", BFIN_CPU_BF523, 0x0001, |
143 WA_SPECULATIVE_LOADS | WA_RETS}, | 141 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
144 {"bf523", BFIN_CPU_BF523, 0x0000, | 142 {"bf523", BFIN_CPU_BF523, 0x0000, |
145 WA_SPECULATIVE_LOADS | WA_RETS}, | 143 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
146 | 144 |
147 {"bf524", BFIN_CPU_BF524, 0x0002, | 145 {"bf524", BFIN_CPU_BF524, 0x0002, |
148 WA_SPECULATIVE_LOADS}, | 146 WA_SPECULATIVE_LOADS | WA_05000074}, |
149 {"bf524", BFIN_CPU_BF524, 0x0001, | 147 {"bf524", BFIN_CPU_BF524, 0x0001, |
150 WA_SPECULATIVE_LOADS | WA_RETS}, | 148 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
151 {"bf524", BFIN_CPU_BF524, 0x0000, | 149 {"bf524", BFIN_CPU_BF524, 0x0000, |
152 WA_SPECULATIVE_LOADS | WA_RETS}, | 150 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
153 | 151 |
154 {"bf525", BFIN_CPU_BF525, 0x0002, | 152 {"bf525", BFIN_CPU_BF525, 0x0002, |
155 WA_SPECULATIVE_LOADS}, | 153 WA_SPECULATIVE_LOADS | WA_05000074}, |
156 {"bf525", BFIN_CPU_BF525, 0x0001, | 154 {"bf525", BFIN_CPU_BF525, 0x0001, |
157 WA_SPECULATIVE_LOADS | WA_RETS}, | 155 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
158 {"bf525", BFIN_CPU_BF525, 0x0000, | 156 {"bf525", BFIN_CPU_BF525, 0x0000, |
159 WA_SPECULATIVE_LOADS | WA_RETS}, | 157 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
160 | 158 |
161 {"bf526", BFIN_CPU_BF526, 0x0002, | 159 {"bf526", BFIN_CPU_BF526, 0x0002, |
162 WA_SPECULATIVE_LOADS}, | 160 WA_SPECULATIVE_LOADS | WA_05000074}, |
163 {"bf526", BFIN_CPU_BF526, 0x0001, | 161 {"bf526", BFIN_CPU_BF526, 0x0001, |
164 WA_SPECULATIVE_LOADS | WA_RETS}, | 162 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
165 {"bf526", BFIN_CPU_BF526, 0x0000, | 163 {"bf526", BFIN_CPU_BF526, 0x0000, |
166 WA_SPECULATIVE_LOADS | WA_RETS}, | 164 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
167 | 165 |
168 {"bf527", BFIN_CPU_BF527, 0x0002, | 166 {"bf527", BFIN_CPU_BF527, 0x0002, |
169 WA_SPECULATIVE_LOADS}, | 167 WA_SPECULATIVE_LOADS | WA_05000074}, |
170 {"bf527", BFIN_CPU_BF527, 0x0001, | 168 {"bf527", BFIN_CPU_BF527, 0x0001, |
171 WA_SPECULATIVE_LOADS | WA_RETS}, | 169 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
172 {"bf527", BFIN_CPU_BF527, 0x0000, | 170 {"bf527", BFIN_CPU_BF527, 0x0000, |
173 WA_SPECULATIVE_LOADS | WA_RETS}, | 171 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074}, |
174 | 172 |
175 {"bf531", BFIN_CPU_BF531, 0x0006, | 173 {"bf531", BFIN_CPU_BF531, 0x0006, |
176 WA_SPECULATIVE_LOADS}, | 174 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074}, |
177 {"bf531", BFIN_CPU_BF531, 0x0005, | 175 {"bf531", BFIN_CPU_BF531, 0x0005, |
178 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315}, | 176 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 |
177 | WA_LOAD_LCREGS | WA_05000074}, | |
179 {"bf531", BFIN_CPU_BF531, 0x0004, | 178 {"bf531", BFIN_CPU_BF531, 0x0004, |
180 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 179 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
181 | WA_05000283 | WA_05000257 | WA_05000315}, | 180 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
181 | WA_05000074}, | |
182 {"bf531", BFIN_CPU_BF531, 0x0003, | 182 {"bf531", BFIN_CPU_BF531, 0x0003, |
183 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 183 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
184 | WA_05000283 | WA_05000257 | WA_05000315}, | 184 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
185 | WA_05000074}, | |
185 | 186 |
186 {"bf532", BFIN_CPU_BF532, 0x0006, | 187 {"bf532", BFIN_CPU_BF532, 0x0006, |
187 WA_SPECULATIVE_LOADS}, | 188 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074}, |
188 {"bf532", BFIN_CPU_BF532, 0x0005, | 189 {"bf532", BFIN_CPU_BF532, 0x0005, |
189 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315}, | 190 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 |
191 | WA_LOAD_LCREGS | WA_05000074}, | |
190 {"bf532", BFIN_CPU_BF532, 0x0004, | 192 {"bf532", BFIN_CPU_BF532, 0x0004, |
191 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 193 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
192 | WA_05000283 | WA_05000257 | WA_05000315}, | 194 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
195 | WA_05000074}, | |
193 {"bf532", BFIN_CPU_BF532, 0x0003, | 196 {"bf532", BFIN_CPU_BF532, 0x0003, |
194 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 197 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
195 | WA_05000283 | WA_05000257 | WA_05000315}, | 198 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
199 | WA_05000074}, | |
196 | 200 |
197 {"bf533", BFIN_CPU_BF533, 0x0006, | 201 {"bf533", BFIN_CPU_BF533, 0x0006, |
198 WA_SPECULATIVE_LOADS}, | 202 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074}, |
199 {"bf533", BFIN_CPU_BF533, 0x0005, | 203 {"bf533", BFIN_CPU_BF533, 0x0005, |
200 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315}, | 204 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 |
205 | WA_LOAD_LCREGS | WA_05000074}, | |
201 {"bf533", BFIN_CPU_BF533, 0x0004, | 206 {"bf533", BFIN_CPU_BF533, 0x0004, |
202 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 207 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
203 | WA_05000283 | WA_05000257 | WA_05000315}, | 208 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
209 | WA_05000074}, | |
204 {"bf533", BFIN_CPU_BF533, 0x0003, | 210 {"bf533", BFIN_CPU_BF533, 0x0003, |
205 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 211 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
206 | WA_05000283 | WA_05000257 | WA_05000315}, | 212 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
213 | WA_05000074}, | |
207 | 214 |
208 {"bf534", BFIN_CPU_BF534, 0x0003, | 215 {"bf534", BFIN_CPU_BF534, 0x0003, |
209 WA_SPECULATIVE_LOADS | WA_RETS}, | 216 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074}, |
210 {"bf534", BFIN_CPU_BF534, 0x0002, | 217 {"bf534", BFIN_CPU_BF534, 0x0002, |
211 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 218 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
212 | WA_05000283 | WA_05000257 | WA_05000315}, | 219 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
220 | WA_05000074}, | |
213 {"bf534", BFIN_CPU_BF534, 0x0001, | 221 {"bf534", BFIN_CPU_BF534, 0x0001, |
214 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 222 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
215 | WA_05000283 | WA_05000257 | WA_05000315}, | 223 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
224 | WA_05000074}, | |
216 | 225 |
217 {"bf536", BFIN_CPU_BF536, 0x0003, | 226 {"bf536", BFIN_CPU_BF536, 0x0003, |
218 WA_SPECULATIVE_LOADS | WA_RETS}, | 227 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074}, |
219 {"bf536", BFIN_CPU_BF536, 0x0002, | 228 {"bf536", BFIN_CPU_BF536, 0x0002, |
220 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 229 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
221 | WA_05000283 | WA_05000257 | WA_05000315}, | 230 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
231 | WA_05000074}, | |
222 {"bf536", BFIN_CPU_BF536, 0x0001, | 232 {"bf536", BFIN_CPU_BF536, 0x0001, |
223 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 233 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
224 | WA_05000283 | WA_05000257 | WA_05000315}, | 234 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
235 | WA_05000074}, | |
225 | 236 |
226 {"bf537", BFIN_CPU_BF537, 0x0003, | 237 {"bf537", BFIN_CPU_BF537, 0x0003, |
227 WA_SPECULATIVE_LOADS | WA_RETS}, | 238 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074}, |
228 {"bf537", BFIN_CPU_BF537, 0x0002, | 239 {"bf537", BFIN_CPU_BF537, 0x0002, |
229 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 240 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
230 | WA_05000283 | WA_05000257 | WA_05000315}, | 241 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
242 | WA_05000074}, | |
231 {"bf537", BFIN_CPU_BF537, 0x0001, | 243 {"bf537", BFIN_CPU_BF537, 0x0001, |
232 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 244 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
233 | WA_05000283 | WA_05000257 | WA_05000315}, | 245 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
246 | WA_05000074}, | |
234 | 247 |
235 {"bf538", BFIN_CPU_BF538, 0x0005, | 248 {"bf538", BFIN_CPU_BF538, 0x0005, |
236 WA_SPECULATIVE_LOADS}, | 249 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074}, |
237 {"bf538", BFIN_CPU_BF538, 0x0004, | 250 {"bf538", BFIN_CPU_BF538, 0x0004, |
238 WA_SPECULATIVE_LOADS | WA_RETS}, | 251 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074}, |
239 {"bf538", BFIN_CPU_BF538, 0x0003, | 252 {"bf538", BFIN_CPU_BF538, 0x0003, |
240 WA_SPECULATIVE_LOADS | WA_RETS | 253 WA_SPECULATIVE_LOADS | WA_RETS |
241 | WA_05000283 | WA_05000315}, | 254 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074}, |
242 {"bf538", BFIN_CPU_BF538, 0x0002, | 255 {"bf538", BFIN_CPU_BF538, 0x0002, |
243 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000257 | WA_05000315}, | 256 WA_SPECULATIVE_LOADS | WA_RETS |
257 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS | |
258 | WA_05000074}, | |
244 | 259 |
245 {"bf539", BFIN_CPU_BF539, 0x0005, | 260 {"bf539", BFIN_CPU_BF539, 0x0005, |
246 WA_SPECULATIVE_LOADS}, | 261 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074}, |
247 {"bf539", BFIN_CPU_BF539, 0x0004, | 262 {"bf539", BFIN_CPU_BF539, 0x0004, |
248 WA_SPECULATIVE_LOADS | WA_RETS}, | 263 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074}, |
249 {"bf539", BFIN_CPU_BF539, 0x0003, | 264 {"bf539", BFIN_CPU_BF539, 0x0003, |
250 WA_SPECULATIVE_LOADS | WA_RETS | 265 WA_SPECULATIVE_LOADS | WA_RETS |
251 | WA_05000283 | WA_05000315}, | 266 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074}, |
252 {"bf539", BFIN_CPU_BF539, 0x0002, | 267 {"bf539", BFIN_CPU_BF539, 0x0002, |
253 WA_SPECULATIVE_LOADS | WA_RETS | 268 WA_SPECULATIVE_LOADS | WA_RETS |
254 | WA_05000283 | WA_05000257 | WA_05000315}, | 269 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
270 | WA_05000074}, | |
271 | |
272 {"bf542m", BFIN_CPU_BF542M, 0x0003, | |
273 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, | |
255 | 274 |
256 {"bf542", BFIN_CPU_BF542, 0x0002, | 275 {"bf542", BFIN_CPU_BF542, 0x0002, |
257 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS}, | 276 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, |
258 {"bf542", BFIN_CPU_BF542, 0x0001, | 277 {"bf542", BFIN_CPU_BF542, 0x0001, |
259 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 278 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074}, |
260 {"bf542", BFIN_CPU_BF542, 0x0000, | 279 {"bf542", BFIN_CPU_BF542, 0x0000, |
261 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 280 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS |
281 | WA_05000074}, | |
282 | |
283 {"bf544m", BFIN_CPU_BF544M, 0x0003, | |
284 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, | |
262 | 285 |
263 {"bf544", BFIN_CPU_BF544, 0x0002, | 286 {"bf544", BFIN_CPU_BF544, 0x0002, |
264 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS}, | 287 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, |
265 {"bf544", BFIN_CPU_BF544, 0x0001, | 288 {"bf544", BFIN_CPU_BF544, 0x0001, |
266 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 289 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074}, |
267 {"bf544", BFIN_CPU_BF544, 0x0000, | 290 {"bf544", BFIN_CPU_BF544, 0x0000, |
268 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 291 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS |
292 | WA_05000074}, | |
293 | |
294 {"bf547m", BFIN_CPU_BF547M, 0x0003, | |
295 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, | |
269 | 296 |
270 {"bf547", BFIN_CPU_BF547, 0x0002, | 297 {"bf547", BFIN_CPU_BF547, 0x0002, |
271 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS}, | 298 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, |
272 {"bf547", BFIN_CPU_BF547, 0x0001, | 299 {"bf547", BFIN_CPU_BF547, 0x0001, |
273 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 300 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074}, |
274 {"bf547", BFIN_CPU_BF547, 0x0000, | 301 {"bf547", BFIN_CPU_BF547, 0x0000, |
275 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 302 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS |
303 | WA_05000074}, | |
304 | |
305 {"bf548m", BFIN_CPU_BF548M, 0x0003, | |
306 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, | |
276 | 307 |
277 {"bf548", BFIN_CPU_BF548, 0x0002, | 308 {"bf548", BFIN_CPU_BF548, 0x0002, |
278 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS}, | 309 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, |
279 {"bf548", BFIN_CPU_BF548, 0x0001, | 310 {"bf548", BFIN_CPU_BF548, 0x0001, |
280 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 311 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074}, |
281 {"bf548", BFIN_CPU_BF548, 0x0000, | 312 {"bf548", BFIN_CPU_BF548, 0x0000, |
282 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 313 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS |
314 | WA_05000074}, | |
315 | |
316 {"bf549m", BFIN_CPU_BF549M, 0x0003, | |
317 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, | |
283 | 318 |
284 {"bf549", BFIN_CPU_BF549, 0x0002, | 319 {"bf549", BFIN_CPU_BF549, 0x0002, |
285 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS}, | 320 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074}, |
286 {"bf549", BFIN_CPU_BF549, 0x0001, | 321 {"bf549", BFIN_CPU_BF549, 0x0001, |
287 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 322 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074}, |
288 {"bf549", BFIN_CPU_BF549, 0x0000, | 323 {"bf549", BFIN_CPU_BF549, 0x0000, |
289 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS}, | 324 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS |
325 | WA_05000074}, | |
290 | 326 |
291 {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS | 327 {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS |
292 | WA_05000283 | WA_05000315}, | 328 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074}, |
293 {"bf561", BFIN_CPU_BF561, 0x0003, | 329 {"bf561", BFIN_CPU_BF561, 0x0003, |
294 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 330 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
295 | WA_05000283 | WA_05000257 | WA_05000315}, | 331 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
332 | WA_05000074}, | |
296 {"bf561", BFIN_CPU_BF561, 0x0002, | 333 {"bf561", BFIN_CPU_BF561, 0x0002, |
297 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS | 334 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS |
298 | WA_05000283 | WA_05000257 | WA_05000315}, | 335 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS |
336 | WA_05000074}, | |
299 | 337 |
300 {NULL, 0, 0, 0} | 338 {NULL, 0, 0, 0} |
301 }; | 339 }; |
302 | 340 |
303 int splitting_for_sched; | 341 int splitting_for_sched, splitting_loops; |
304 | 342 |
305 static void | 343 static void |
306 bfin_globalize_label (FILE *stream, const char *name) | 344 bfin_globalize_label (FILE *stream, const char *name) |
307 { | 345 { |
308 fputs (".global ", stream); | 346 fputs (".global ", stream); |
533 /* Determine if we are going to save the frame pointer in the prologue. */ | 571 /* Determine if we are going to save the frame pointer in the prologue. */ |
534 | 572 |
535 static bool | 573 static bool |
536 must_save_fp_p (void) | 574 must_save_fp_p (void) |
537 { | 575 { |
538 return frame_pointer_needed || df_regs_ever_live_p (REG_FP); | 576 return df_regs_ever_live_p (REG_FP); |
577 } | |
578 | |
579 /* Determine if we are going to save the RETS register. */ | |
580 static bool | |
581 must_save_rets_p (void) | |
582 { | |
583 return df_regs_ever_live_p (REG_RETS); | |
539 } | 584 } |
540 | 585 |
541 static bool | 586 static bool |
542 stack_frame_needed_p (void) | 587 stack_frame_needed_p (void) |
543 { | 588 { |
813 | 858 |
814 /* Value should be nonzero if functions must have frame pointers. | 859 /* Value should be nonzero if functions must have frame pointers. |
815 Zero means the frame pointer need not be set up (and parms may | 860 Zero means the frame pointer need not be set up (and parms may |
816 be accessed via the stack pointer) in functions that seem suitable. */ | 861 be accessed via the stack pointer) in functions that seem suitable. */ |
817 | 862 |
818 int | 863 static bool |
819 bfin_frame_pointer_required (void) | 864 bfin_frame_pointer_required (void) |
820 { | 865 { |
821 e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); | 866 e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); |
822 | 867 |
823 if (fkind != SUBROUTINE) | 868 if (fkind != SUBROUTINE) |
824 return 1; | 869 return true; |
825 | 870 |
826 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used, | 871 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used, |
827 so we have to override it for non-leaf functions. */ | 872 so we have to override it for non-leaf functions. */ |
828 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf) | 873 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf) |
829 return 1; | 874 return true; |
830 | 875 |
831 return 0; | 876 return false; |
832 } | 877 } |
833 | 878 |
834 /* Return the number of registers pushed during the prologue. */ | 879 /* Return the number of registers pushed during the prologue. */ |
835 | 880 |
836 static int | 881 static int |
845 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false); | 890 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false); |
846 int n = ndregs + npregs; | 891 int n = ndregs + npregs; |
847 int i; | 892 int i; |
848 | 893 |
849 if (all || stack_frame_needed_p ()) | 894 if (all || stack_frame_needed_p ()) |
850 /* We use a LINK instruction in this case. */ | |
851 n += 2; | 895 n += 2; |
852 else | 896 else |
853 { | 897 { |
854 if (must_save_fp_p ()) | 898 if (must_save_fp_p ()) |
855 n++; | 899 n++; |
856 if (! current_function_is_leaf) | 900 if (must_save_rets_p ()) |
857 n++; | 901 n++; |
858 } | 902 } |
859 | 903 |
860 if (fkind != SUBROUTINE || all) | 904 if (fkind != SUBROUTINE || all) |
861 { | 905 { |
882 && (df_regs_ever_live_p (i) | 926 && (df_regs_ever_live_p (i) |
883 || (!leaf_function_p () && call_used_regs[i])))) | 927 || (!leaf_function_p () && call_used_regs[i])))) |
884 n += i == REG_A0 || i == REG_A1 ? 2 : 1; | 928 n += i == REG_A0 || i == REG_A1 ? 2 : 1; |
885 | 929 |
886 return n; | 930 return n; |
931 } | |
932 | |
933 /* Given FROM and TO register numbers, say whether this elimination is | |
934 allowed. Frame pointer elimination is automatically handled. | |
935 | |
936 All other eliminations are valid. */ | |
937 | |
938 static bool | |
939 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) | |
940 { | |
941 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true); | |
887 } | 942 } |
888 | 943 |
889 /* Return the offset between two registers, one to be eliminated, and the other | 944 /* Return the offset between two registers, one to be eliminated, and the other |
890 its replacement, at the start of a routine. */ | 945 its replacement, at the start of a routine. */ |
891 | 946 |
1082 static void | 1137 static void |
1083 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all) | 1138 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all) |
1084 { | 1139 { |
1085 frame_size += arg_area_size (); | 1140 frame_size += arg_area_size (); |
1086 | 1141 |
1087 if (all || stack_frame_needed_p () | 1142 if (all |
1088 || (must_save_fp_p () && ! current_function_is_leaf)) | 1143 || stack_frame_needed_p () |
1144 || (must_save_rets_p () && must_save_fp_p ())) | |
1089 emit_link_insn (spreg, frame_size); | 1145 emit_link_insn (spreg, frame_size); |
1090 else | 1146 else |
1091 { | 1147 { |
1092 if (! current_function_is_leaf) | 1148 if (must_save_rets_p ()) |
1093 { | 1149 { |
1094 rtx pat = gen_movsi (gen_rtx_MEM (Pmode, | 1150 rtx pat = gen_movsi (gen_rtx_MEM (Pmode, |
1095 gen_rtx_PRE_DEC (Pmode, spreg)), | 1151 gen_rtx_PRE_DEC (Pmode, spreg)), |
1096 bfin_rets_rtx); | 1152 bfin_rets_rtx); |
1097 rtx insn = emit_insn (pat); | 1153 rtx insn = emit_insn (pat); |
1117 static void | 1173 static void |
1118 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p) | 1174 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p) |
1119 { | 1175 { |
1120 frame_size += arg_area_size (); | 1176 frame_size += arg_area_size (); |
1121 | 1177 |
1122 if (all || stack_frame_needed_p ()) | 1178 if (stack_frame_needed_p ()) |
1123 emit_insn (gen_unlink ()); | 1179 emit_insn (gen_unlink ()); |
1124 else | 1180 else |
1125 { | 1181 { |
1126 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg)); | 1182 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg)); |
1127 | 1183 |
1128 add_to_reg (spreg, frame_size, 0, epilogue_p); | 1184 add_to_reg (spreg, frame_size, 0, epilogue_p); |
1129 if (must_save_fp_p ()) | 1185 if (all || must_save_fp_p ()) |
1130 { | 1186 { |
1131 rtx fpreg = gen_rtx_REG (Pmode, REG_FP); | 1187 rtx fpreg = gen_rtx_REG (Pmode, REG_FP); |
1132 emit_move_insn (fpreg, postinc); | 1188 emit_move_insn (fpreg, postinc); |
1133 emit_use (fpreg); | 1189 emit_use (fpreg); |
1134 } | 1190 } |
1135 if (! current_function_is_leaf) | 1191 if (all || must_save_rets_p ()) |
1136 { | 1192 { |
1137 emit_move_insn (bfin_rets_rtx, postinc); | 1193 emit_move_insn (bfin_rets_rtx, postinc); |
1138 emit_use (bfin_rets_rtx); | 1194 emit_use (bfin_rets_rtx); |
1139 } | 1195 } |
1140 } | 1196 } |
1184 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx)); | 1240 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx)); |
1185 } | 1241 } |
1186 | 1242 |
1187 if (lookup_attribute ("nesting", attrs)) | 1243 if (lookup_attribute ("nesting", attrs)) |
1188 { | 1244 { |
1189 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX | 1245 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]); |
1190 : fkind == NMI_HANDLER ? REG_RETN | |
1191 : REG_RETI)); | |
1192 insn = emit_move_insn (predec, srcreg); | 1246 insn = emit_move_insn (predec, srcreg); |
1193 RTX_FRAME_RELATED_P (insn) = 1; | 1247 RTX_FRAME_RELATED_P (insn) = 1; |
1194 } | 1248 } |
1195 | 1249 |
1196 do_link (spreg, frame_size, all); | 1250 do_link (spreg, frame_size, all); |
1228 | 1282 |
1229 do_unlink (spreg, get_frame_size (), all, 1); | 1283 do_unlink (spreg, get_frame_size (), all, 1); |
1230 | 1284 |
1231 if (lookup_attribute ("nesting", attrs)) | 1285 if (lookup_attribute ("nesting", attrs)) |
1232 { | 1286 { |
1233 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX | 1287 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]); |
1234 : fkind == NMI_HANDLER ? REG_RETN | |
1235 : REG_RETI)); | |
1236 emit_move_insn (srcreg, postinc); | 1288 emit_move_insn (srcreg, postinc); |
1237 } | 1289 } |
1238 | 1290 |
1239 /* If we're calling other functions, they won't save their call-clobbered | 1291 /* If we're calling other functions, they won't save their call-clobbered |
1240 registers, so we must save (and restore) everything here. */ | 1292 registers, so we must save (and restore) everything here. */ |
1246 /* Deallocate any space we left on the stack in case we needed to save the | 1298 /* Deallocate any space we left on the stack in case we needed to save the |
1247 argument registers. */ | 1299 argument registers. */ |
1248 if (fkind == EXCPT_HANDLER) | 1300 if (fkind == EXCPT_HANDLER) |
1249 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12))); | 1301 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12))); |
1250 | 1302 |
1251 emit_jump_insn (gen_return_internal (GEN_INT (fkind))); | 1303 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind]))); |
1252 } | 1304 } |
1253 | 1305 |
1254 /* Used while emitting the prologue to generate code to load the correct value | 1306 /* Used while emitting the prologue to generate code to load the correct value |
1255 into the PIC register, which is passed in DEST. */ | 1307 into the PIC register, which is passed in DEST. */ |
1256 | 1308 |
1342 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); | 1394 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); |
1343 emit_insn (gen_trapifcc ()); | 1395 emit_insn (gen_trapifcc ()); |
1344 } | 1396 } |
1345 expand_prologue_reg_save (spreg, all, false); | 1397 expand_prologue_reg_save (spreg, all, false); |
1346 | 1398 |
1347 do_link (spreg, frame_size, false); | 1399 do_link (spreg, frame_size, all); |
1348 | 1400 |
1349 if (TARGET_ID_SHARED_LIBRARY | 1401 if (TARGET_ID_SHARED_LIBRARY |
1350 && !TARGET_SEP_DATA | 1402 && !TARGET_SEP_DATA |
1351 && (crtl->uses_pic_offset_table | 1403 && (crtl->uses_pic_offset_table |
1352 || !current_function_is_leaf)) | 1404 || !current_function_is_leaf)) |
1371 { | 1423 { |
1372 expand_interrupt_handler_epilogue (spreg, fkind, all); | 1424 expand_interrupt_handler_epilogue (spreg, fkind, all); |
1373 return; | 1425 return; |
1374 } | 1426 } |
1375 | 1427 |
1376 do_unlink (spreg, get_frame_size (), false, e); | 1428 do_unlink (spreg, get_frame_size (), all, e); |
1377 | 1429 |
1378 expand_epilogue_reg_restore (spreg, all, false); | 1430 expand_epilogue_reg_restore (spreg, all, false); |
1379 | 1431 |
1380 /* Omit the return insn if this is for a sibcall. */ | 1432 /* Omit the return insn if this is for a sibcall. */ |
1381 if (! need_return) | 1433 if (! need_return) |
1382 return; | 1434 return; |
1383 | 1435 |
1384 if (eh_return) | 1436 if (eh_return) |
1385 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2))); | 1437 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2))); |
1386 | 1438 |
1387 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE))); | 1439 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS))); |
1388 } | 1440 } |
1389 | 1441 |
1390 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */ | 1442 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */ |
1391 | 1443 |
1392 int | 1444 int |
1413 { | 1465 { |
1414 if (count != 0) | 1466 if (count != 0) |
1415 return const0_rtx; | 1467 return const0_rtx; |
1416 | 1468 |
1417 return get_hard_reg_initial_val (Pmode, REG_RETS); | 1469 return get_hard_reg_initial_val (Pmode, REG_RETS); |
1418 } | |
1419 | |
1420 /* Try machine-dependent ways of modifying an illegitimate address X | |
1421 to be legitimate. If we find one, return the new, valid address, | |
1422 otherwise return NULL_RTX. | |
1423 | |
1424 OLDX is the address as it was before break_out_memory_refs was called. | |
1425 In some cases it is useful to look at this to decide what needs to be done. | |
1426 | |
1427 MODE is the mode of the memory reference. */ | |
1428 | |
1429 rtx | |
1430 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED, | |
1431 enum machine_mode mode ATTRIBUTE_UNUSED) | |
1432 { | |
1433 return NULL_RTX; | |
1434 } | 1470 } |
1435 | 1471 |
1436 static rtx | 1472 static rtx |
1437 bfin_delegitimize_address (rtx orig_x) | 1473 bfin_delegitimize_address (rtx orig_x) |
1438 { | 1474 { |
2056 this_func = cgraph_local_info (current_function_decl); | 2092 this_func = cgraph_local_info (current_function_decl); |
2057 called_func = cgraph_local_info (decl); | 2093 called_func = cgraph_local_info (decl); |
2058 return !called_func->local || this_func->local; | 2094 return !called_func->local || this_func->local; |
2059 } | 2095 } |
2060 | 2096 |
2097 /* Write a template for a trampoline to F. */ | |
2098 | |
2099 static void | |
2100 bfin_asm_trampoline_template (FILE *f) | |
2101 { | |
2102 if (TARGET_FDPIC) | |
2103 { | |
2104 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */ | |
2105 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */ | |
2106 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ | |
2107 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ | |
2108 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ | |
2109 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ | |
2110 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */ | |
2111 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */ | |
2112 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/ | |
2113 } | |
2114 else | |
2115 { | |
2116 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */ | |
2117 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */ | |
2118 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */ | |
2119 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */ | |
2120 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/ | |
2121 } | |
2122 } | |
2123 | |
2061 /* Emit RTL insns to initialize the variable parts of a trampoline at | 2124 /* Emit RTL insns to initialize the variable parts of a trampoline at |
2062 TRAMP. FNADDR is an RTX for the address of the function's pure | 2125 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for |
2063 code. CXT is an RTX for the static chain value for the function. */ | 2126 the static chain value for the function. */ |
2064 | 2127 |
2065 void | 2128 static void |
2066 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt) | 2129 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) |
2067 { | 2130 { |
2068 rtx t1 = copy_to_reg (fnaddr); | 2131 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0)); |
2069 rtx t2 = copy_to_reg (cxt); | 2132 rtx t2 = copy_to_reg (chain_value); |
2070 rtx addr; | 2133 rtx mem; |
2071 int i = 0; | 2134 int i = 0; |
2072 | 2135 |
2136 emit_block_move (m_tramp, assemble_trampoline_template (), | |
2137 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
2138 | |
2073 if (TARGET_FDPIC) | 2139 if (TARGET_FDPIC) |
2074 { | 2140 { |
2075 rtx a = memory_address (Pmode, plus_constant (tramp, 8)); | 2141 rtx a = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0), 8)); |
2076 addr = memory_address (Pmode, tramp); | 2142 mem = adjust_address (m_tramp, Pmode, 0); |
2077 emit_move_insn (gen_rtx_MEM (SImode, addr), a); | 2143 emit_move_insn (mem, a); |
2078 i = 8; | 2144 i = 8; |
2079 } | 2145 } |
2080 | 2146 |
2081 addr = memory_address (Pmode, plus_constant (tramp, i + 2)); | 2147 mem = adjust_address (m_tramp, HImode, i + 2); |
2082 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1)); | 2148 emit_move_insn (mem, gen_lowpart (HImode, t1)); |
2083 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16))); | 2149 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16))); |
2084 addr = memory_address (Pmode, plus_constant (tramp, i + 6)); | 2150 mem = adjust_address (m_tramp, HImode, i + 6); |
2085 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1)); | 2151 emit_move_insn (mem, gen_lowpart (HImode, t1)); |
2086 | 2152 |
2087 addr = memory_address (Pmode, plus_constant (tramp, i + 10)); | 2153 mem = adjust_address (m_tramp, HImode, i + 10); |
2088 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2)); | 2154 emit_move_insn (mem, gen_lowpart (HImode, t2)); |
2089 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16))); | 2155 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16))); |
2090 addr = memory_address (Pmode, plus_constant (tramp, i + 14)); | 2156 mem = adjust_address (m_tramp, HImode, i + 14); |
2091 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2)); | 2157 emit_move_insn (mem, gen_lowpart (HImode, t2)); |
2092 } | 2158 } |
2093 | 2159 |
2094 /* Emit insns to move operands[1] into operands[0]. */ | 2160 /* Emit insns to move operands[1] into operands[0]. */ |
2095 | 2161 |
2096 void | 2162 void |
2181 | 2247 |
2182 bool | 2248 bool |
2183 bfin_longcall_p (rtx op, int call_cookie) | 2249 bfin_longcall_p (rtx op, int call_cookie) |
2184 { | 2250 { |
2185 gcc_assert (GET_CODE (op) == SYMBOL_REF); | 2251 gcc_assert (GET_CODE (op) == SYMBOL_REF); |
2252 if (SYMBOL_REF_WEAK (op)) | |
2253 return 1; | |
2186 if (call_cookie & CALL_SHORT) | 2254 if (call_cookie & CALL_SHORT) |
2187 return 0; | 2255 return 0; |
2188 if (call_cookie & CALL_LONG) | 2256 if (call_cookie & CALL_LONG) |
2189 return 1; | 2257 return 1; |
2190 if (TARGET_LONG_CALLS) | 2258 if (TARGET_LONG_CALLS) |
2199 void | 2267 void |
2200 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall) | 2268 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall) |
2201 { | 2269 { |
2202 rtx use = NULL, call; | 2270 rtx use = NULL, call; |
2203 rtx callee = XEXP (fnaddr, 0); | 2271 rtx callee = XEXP (fnaddr, 0); |
2204 int nelts = 2 + !!sibcall; | 2272 int nelts = 3; |
2205 rtx pat; | 2273 rtx pat; |
2206 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO); | 2274 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO); |
2275 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS); | |
2207 int n; | 2276 int n; |
2208 | 2277 |
2209 /* In an untyped call, we can get NULL for operand 2. */ | 2278 /* In an untyped call, we can get NULL for operand 2. */ |
2210 if (cookie == NULL_RTX) | 2279 if (cookie == NULL_RTX) |
2211 cookie = const0_rtx; | 2280 cookie = const0_rtx; |
2216 && !SYMBOL_REF_LOCAL_P (callee)) | 2285 && !SYMBOL_REF_LOCAL_P (callee)) |
2217 use_reg (&use, pic_offset_table_rtx); | 2286 use_reg (&use, pic_offset_table_rtx); |
2218 | 2287 |
2219 if (TARGET_FDPIC) | 2288 if (TARGET_FDPIC) |
2220 { | 2289 { |
2221 int caller_has_l1_text, callee_has_l1_text; | 2290 int caller_in_sram, callee_in_sram; |
2222 | 2291 |
2223 caller_has_l1_text = callee_has_l1_text = 0; | 2292 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */ |
2293 caller_in_sram = callee_in_sram = 0; | |
2224 | 2294 |
2225 if (lookup_attribute ("l1_text", | 2295 if (lookup_attribute ("l1_text", |
2226 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE) | 2296 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE) |
2227 caller_has_l1_text = 1; | 2297 caller_in_sram = 1; |
2298 else if (lookup_attribute ("l2", | |
2299 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE) | |
2300 caller_in_sram = 2; | |
2228 | 2301 |
2229 if (GET_CODE (callee) == SYMBOL_REF | 2302 if (GET_CODE (callee) == SYMBOL_REF |
2230 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)) | 2303 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))) |
2231 && lookup_attribute | 2304 { |
2232 ("l1_text", | 2305 if (lookup_attribute |
2233 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE) | 2306 ("l1_text", |
2234 callee_has_l1_text = 1; | 2307 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE) |
2308 callee_in_sram = 1; | |
2309 else if (lookup_attribute | |
2310 ("l2", | |
2311 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE) | |
2312 callee_in_sram = 2; | |
2313 } | |
2235 | 2314 |
2236 if (GET_CODE (callee) != SYMBOL_REF | 2315 if (GET_CODE (callee) != SYMBOL_REF |
2237 || bfin_longcall_p (callee, INTVAL (cookie)) | 2316 || bfin_longcall_p (callee, INTVAL (cookie)) |
2238 || (GET_CODE (callee) == SYMBOL_REF | 2317 || (GET_CODE (callee) == SYMBOL_REF |
2239 && !SYMBOL_REF_LOCAL_P (callee) | 2318 && !SYMBOL_REF_LOCAL_P (callee) |
2240 && TARGET_INLINE_PLT) | 2319 && TARGET_INLINE_PLT) |
2241 || caller_has_l1_text != callee_has_l1_text | 2320 || caller_in_sram != callee_in_sram |
2242 || (caller_has_l1_text && callee_has_l1_text | 2321 || (caller_in_sram && callee_in_sram |
2243 && (GET_CODE (callee) != SYMBOL_REF | 2322 && (GET_CODE (callee) != SYMBOL_REF |
2244 || !SYMBOL_REF_LOCAL_P (callee)))) | 2323 || !SYMBOL_REF_LOCAL_P (callee)))) |
2245 { | 2324 { |
2246 rtx addr = callee; | 2325 rtx addr = callee; |
2247 if (! address_operand (addr, Pmode)) | 2326 if (! address_operand (addr, Pmode)) |
2278 if (TARGET_FDPIC) | 2357 if (TARGET_FDPIC) |
2279 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg); | 2358 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg); |
2280 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie); | 2359 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie); |
2281 if (sibcall) | 2360 if (sibcall) |
2282 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode); | 2361 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode); |
2362 else | |
2363 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg); | |
2283 call = emit_call_insn (pat); | 2364 call = emit_call_insn (pat); |
2284 if (use) | 2365 if (use) |
2285 CALL_INSN_FUNCTION_USAGE (call) = use; | 2366 CALL_INSN_FUNCTION_USAGE (call) = use; |
2286 } | 2367 } |
2287 | 2368 |
2329 int | 2410 int |
2330 bfin_register_move_cost (enum machine_mode mode, | 2411 bfin_register_move_cost (enum machine_mode mode, |
2331 enum reg_class class1, enum reg_class class2) | 2412 enum reg_class class1, enum reg_class class2) |
2332 { | 2413 { |
2333 /* These need secondary reloads, so they're more expensive. */ | 2414 /* These need secondary reloads, so they're more expensive. */ |
2334 if ((class1 == CCREGS && class2 != DREGS) | 2415 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS)) |
2335 || (class1 != DREGS && class2 == CCREGS)) | 2416 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS))) |
2336 return 4; | 2417 return 4; |
2337 | 2418 |
2338 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */ | 2419 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */ |
2339 if (optimize_size) | 2420 if (optimize_size) |
2340 return 2; | 2421 return 2; |
2341 | |
2342 /* There are some stalls involved when moving from a DREG to a different | |
2343 class reg, and using the value in one of the following instructions. | |
2344 Attempt to model this by slightly discouraging such moves. */ | |
2345 if (class1 == DREGS && class2 != DREGS) | |
2346 return 2 * 2; | |
2347 | 2422 |
2348 if (GET_MODE_CLASS (mode) == MODE_INT) | 2423 if (GET_MODE_CLASS (mode) == MODE_INT) |
2349 { | 2424 { |
2350 /* Discourage trying to use the accumulators. */ | 2425 /* Discourage trying to use the accumulators. */ |
2351 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0) | 2426 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0) |
2733 | 2808 |
2734 rtx | 2809 rtx |
2735 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) | 2810 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED) |
2736 { | 2811 { |
2737 enum rtx_code code1, code2; | 2812 enum rtx_code code1, code2; |
2738 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1; | 2813 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1); |
2739 rtx tem = bfin_cc_rtx; | 2814 rtx tem = bfin_cc_rtx; |
2740 enum rtx_code code = GET_CODE (cmp); | 2815 enum rtx_code code = GET_CODE (cmp); |
2741 | 2816 |
2742 /* If we have a BImode input, then we already have a compare result, and | 2817 /* If we have a BImode input, then we already have a compare result, and |
2743 do not need to emit another comparison. */ | 2818 do not need to emit another comparison. */ |
2761 default: | 2836 default: |
2762 code1 = reverse_condition (code); | 2837 code1 = reverse_condition (code); |
2763 code2 = EQ; | 2838 code2 = EQ; |
2764 break; | 2839 break; |
2765 } | 2840 } |
2766 emit_insn (gen_rtx_SET (BImode, tem, | 2841 emit_insn (gen_rtx_SET (VOIDmode, tem, |
2767 gen_rtx_fmt_ee (code1, BImode, op0, op1))); | 2842 gen_rtx_fmt_ee (code1, BImode, op0, op1))); |
2768 } | 2843 } |
2769 | 2844 |
2770 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode)); | 2845 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode)); |
2771 } | 2846 } |
2918 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH); | 2993 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH); |
2919 else | 2994 else |
2920 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH); | 2995 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH); |
2921 } | 2996 } |
2922 | 2997 |
2923 bool | 2998 /* Recognize an RTL expression that is a valid memory address for an |
2924 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict) | 2999 instruction. The MODE argument is the machine mode for the MEM expression |
3000 that wants to use this address. | |
3001 | |
3002 Blackfin addressing modes are as follows: | |
3003 | |
3004 [preg] | |
3005 [preg + imm16] | |
3006 | |
3007 B [ Preg + uimm15 ] | |
3008 W [ Preg + uimm16m2 ] | |
3009 [ Preg + uimm17m4 ] | |
3010 | |
3011 [preg++] | |
3012 [preg--] | |
3013 [--sp] | |
3014 */ | |
3015 | |
3016 static bool | |
3017 bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) | |
2925 { | 3018 { |
2926 switch (GET_CODE (x)) { | 3019 switch (GET_CODE (x)) { |
2927 case REG: | 3020 case REG: |
2928 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM)) | 3021 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM)) |
2929 return true; | 3022 return true; |
3608 DEF_VEC_P (loop_info); | 3701 DEF_VEC_P (loop_info); |
3609 DEF_VEC_ALLOC_P (loop_info,heap); | 3702 DEF_VEC_ALLOC_P (loop_info,heap); |
3610 | 3703 |
3611 /* Information about a loop we have found (or are in the process of | 3704 /* Information about a loop we have found (or are in the process of |
3612 finding). */ | 3705 finding). */ |
3613 struct loop_info GTY (()) | 3706 struct GTY (()) loop_info |
3614 { | 3707 { |
3615 /* loop number, for dumps */ | 3708 /* loop number, for dumps */ |
3616 int loop_no; | 3709 int loop_no; |
3617 | 3710 |
3618 /* All edges that jump into and out of the loop. */ | 3711 /* All edges that jump into and out of the loop. */ |
3644 rtx loop_end; | 3737 rtx loop_end; |
3645 | 3738 |
3646 /* The iteration register. */ | 3739 /* The iteration register. */ |
3647 rtx iter_reg; | 3740 rtx iter_reg; |
3648 | 3741 |
3649 /* The new initialization insn. */ | |
3650 rtx init; | |
3651 | |
3652 /* The new initialization instruction. */ | |
3653 rtx loop_init; | |
3654 | |
3655 /* The new label placed at the beginning of the loop. */ | 3742 /* The new label placed at the beginning of the loop. */ |
3656 rtx start_label; | 3743 rtx start_label; |
3657 | 3744 |
3658 /* The new label placed at the end of the loop. */ | 3745 /* The new label placed at the end of the loop. */ |
3659 rtx end_label; | 3746 rtx end_label; |
3777 { | 3864 { |
3778 if (ENABLE_WA_SPECULATIVE_SYNCS) | 3865 if (ENABLE_WA_SPECULATIVE_SYNCS) |
3779 length = 4; | 3866 length = 4; |
3780 } | 3867 } |
3781 | 3868 |
3782 if (INSN_P (insn)) | 3869 if (NONDEBUG_INSN_P (insn)) |
3783 length += get_attr_length (insn); | 3870 length += get_attr_length (insn); |
3784 | 3871 |
3785 return length; | 3872 return length; |
3786 } | 3873 } |
3787 | 3874 |
3790 static void | 3877 static void |
3791 bfin_optimize_loop (loop_info loop) | 3878 bfin_optimize_loop (loop_info loop) |
3792 { | 3879 { |
3793 basic_block bb; | 3880 basic_block bb; |
3794 loop_info inner; | 3881 loop_info inner; |
3795 rtx insn, init_insn, last_insn, nop_insn; | 3882 rtx insn, last_insn; |
3796 rtx loop_init, start_label, end_label; | 3883 rtx loop_init, start_label, end_label; |
3797 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1; | 3884 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1; |
3798 rtx iter_reg; | 3885 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn; |
3799 rtx lc_reg, lt_reg, lb_reg; | 3886 rtx lc_reg, lt_reg, lb_reg; |
3800 rtx seq, seq_end; | 3887 rtx seq, seq_end; |
3801 int length; | 3888 int length; |
3802 unsigned ix; | 3889 unsigned ix; |
3803 int inner_depth = 0; | 3890 int inner_depth = 0; |
3839 } | 3926 } |
3840 | 3927 |
3841 /* Get the loop iteration register. */ | 3928 /* Get the loop iteration register. */ |
3842 iter_reg = loop->iter_reg; | 3929 iter_reg = loop->iter_reg; |
3843 | 3930 |
3844 if (!DPREG_P (iter_reg)) | 3931 if (!REG_P (iter_reg)) |
3845 { | 3932 { |
3846 if (dump_file) | 3933 if (dump_file) |
3847 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n", | 3934 fprintf (dump_file, ";; loop %d iteration count not in a register\n", |
3848 loop->loop_no); | 3935 loop->loop_no); |
3849 goto bad_loop; | 3936 goto bad_loop; |
3937 } | |
3938 scratchreg = NULL_RTX; | |
3939 scratch_init = iter_reg; | |
3940 scratch_init_insn = NULL_RTX; | |
3941 if (!PREG_P (iter_reg) && loop->incoming_src) | |
3942 { | |
3943 basic_block bb_in = loop->incoming_src; | |
3944 int i; | |
3945 for (i = REG_P0; i <= REG_P5; i++) | |
3946 if ((df_regs_ever_live_p (i) | |
3947 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE | |
3948 && call_used_regs[i])) | |
3949 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i)) | |
3950 { | |
3951 scratchreg = gen_rtx_REG (SImode, i); | |
3952 break; | |
3953 } | |
3954 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in); | |
3955 insn = PREV_INSN (insn)) | |
3956 { | |
3957 rtx set; | |
3958 if (NOTE_P (insn) || BARRIER_P (insn)) | |
3959 continue; | |
3960 set = single_set (insn); | |
3961 if (set && rtx_equal_p (SET_DEST (set), iter_reg)) | |
3962 { | |
3963 if (CONSTANT_P (SET_SRC (set))) | |
3964 { | |
3965 scratch_init = SET_SRC (set); | |
3966 scratch_init_insn = insn; | |
3967 } | |
3968 break; | |
3969 } | |
3970 else if (reg_mentioned_p (iter_reg, PATTERN (insn))) | |
3971 break; | |
3972 } | |
3850 } | 3973 } |
3851 | 3974 |
3852 if (loop->incoming_src) | 3975 if (loop->incoming_src) |
3853 { | 3976 { |
3854 /* Make sure the predecessor is before the loop start label, as required by | 3977 /* Make sure the predecessor is before the loop start label, as required by |
3864 insn = PREV_INSN (insn); | 3987 insn = PREV_INSN (insn); |
3865 } | 3988 } |
3866 | 3989 |
3867 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn)) | 3990 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn)) |
3868 length += length_for_loop (insn); | 3991 length += length_for_loop (insn); |
3869 | 3992 |
3870 if (!insn) | 3993 if (!insn) |
3871 { | 3994 { |
3872 if (dump_file) | 3995 if (dump_file) |
3873 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n", | 3996 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n", |
3874 loop->loop_no); | 3997 loop->loop_no); |
3875 goto bad_loop; | 3998 goto bad_loop; |
3876 } | 3999 } |
4000 | |
4001 /* Account for the pop of a scratch register where necessary. */ | |
4002 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX | |
4003 && ENABLE_WA_LOAD_LCREGS) | |
4004 length += 2; | |
3877 | 4005 |
3878 if (length > MAX_LSETUP_DISTANCE) | 4006 if (length > MAX_LSETUP_DISTANCE) |
3879 { | 4007 { |
3880 if (dump_file) | 4008 if (dump_file) |
3881 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no); | 4009 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no); |
3973 | 4101 |
3974 while (1) | 4102 while (1) |
3975 { | 4103 { |
3976 for (; last_insn != BB_HEAD (bb); | 4104 for (; last_insn != BB_HEAD (bb); |
3977 last_insn = find_prev_insn_start (last_insn)) | 4105 last_insn = find_prev_insn_start (last_insn)) |
3978 if (INSN_P (last_insn)) | 4106 if (NONDEBUG_INSN_P (last_insn)) |
3979 break; | 4107 break; |
3980 | 4108 |
3981 if (last_insn != BB_HEAD (bb)) | 4109 if (last_insn != BB_HEAD (bb)) |
3982 break; | 4110 break; |
3983 | 4111 |
3984 if (single_pred_p (bb) | 4112 if (single_pred_p (bb) |
4113 && single_pred_edge (bb)->flags & EDGE_FALLTHRU | |
3985 && single_pred (bb) != ENTRY_BLOCK_PTR) | 4114 && single_pred (bb) != ENTRY_BLOCK_PTR) |
3986 { | 4115 { |
3987 bb = single_pred (bb); | 4116 bb = single_pred (bb); |
3988 last_insn = BB_END (bb); | 4117 last_insn = BB_END (bb); |
3989 continue; | 4118 continue; |
4001 fprintf (dump_file, ";; loop %d has no last instruction\n", | 4130 fprintf (dump_file, ";; loop %d has no last instruction\n", |
4002 loop->loop_no); | 4131 loop->loop_no); |
4003 goto bad_loop; | 4132 goto bad_loop; |
4004 } | 4133 } |
4005 | 4134 |
4006 if (JUMP_P (last_insn)) | 4135 if (JUMP_P (last_insn) && !any_condjump_p (last_insn)) |
4007 { | |
4008 loop_info inner = (loop_info) bb->aux; | |
4009 if (inner | |
4010 && inner->outer == loop | |
4011 && inner->loop_end == last_insn | |
4012 && inner->depth == 1) | |
4013 /* This jump_insn is the exact loop_end of an inner loop | |
4014 and to be optimized away. So use the inner's last_insn. */ | |
4015 last_insn = inner->last_insn; | |
4016 else | |
4017 { | |
4018 if (dump_file) | |
4019 fprintf (dump_file, ";; loop %d has bad last instruction\n", | |
4020 loop->loop_no); | |
4021 goto bad_loop; | |
4022 } | |
4023 } | |
4024 else if (CALL_P (last_insn) | |
4025 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE | |
4026 && get_attr_type (last_insn) == TYPE_SYNC) | |
4027 || recog_memoized (last_insn) == CODE_FOR_return_internal) | |
4028 { | 4136 { |
4029 if (dump_file) | 4137 if (dump_file) |
4030 fprintf (dump_file, ";; loop %d has bad last instruction\n", | 4138 fprintf (dump_file, ";; loop %d has bad last instruction\n", |
4031 loop->loop_no); | 4139 loop->loop_no); |
4032 goto bad_loop; | 4140 goto bad_loop; |
4033 } | 4141 } |
4034 | 4142 /* In all other cases, try to replace a bad last insn with a nop. */ |
4035 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT | 4143 else if (JUMP_P (last_insn) |
4036 || asm_noperands (PATTERN (last_insn)) >= 0 | 4144 || CALL_P (last_insn) |
4037 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE | 4145 || get_attr_type (last_insn) == TYPE_SYNC |
4038 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)) | 4146 || get_attr_type (last_insn) == TYPE_CALL |
4039 { | 4147 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI |
4040 nop_insn = emit_insn_after (gen_nop (), last_insn); | 4148 || recog_memoized (last_insn) == CODE_FOR_return_internal |
4041 last_insn = nop_insn; | 4149 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT |
4150 || asm_noperands (PATTERN (last_insn)) >= 0) | |
4151 { | |
4152 if (loop->length + 2 > MAX_LOOP_LENGTH) | |
4153 { | |
4154 if (dump_file) | |
4155 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no); | |
4156 goto bad_loop; | |
4157 } | |
4158 if (dump_file) | |
4159 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n", | |
4160 loop->loop_no); | |
4161 | |
4162 last_insn = emit_insn_after (gen_forced_nop (), last_insn); | |
4042 } | 4163 } |
4043 | 4164 |
4044 loop->last_insn = last_insn; | 4165 loop->last_insn = last_insn; |
4045 | 4166 |
4046 /* The loop is good for replacement. */ | 4167 /* The loop is good for replacement. */ |
4061 lt_reg = reg_lt0; | 4182 lt_reg = reg_lt0; |
4062 lb_reg = reg_lb0; | 4183 lb_reg = reg_lb0; |
4063 loop->clobber_loop0 = 1; | 4184 loop->clobber_loop0 = 1; |
4064 } | 4185 } |
4065 | 4186 |
4066 /* If iter_reg is a DREG, we need generate an instruction to load | 4187 loop->end_label = end_label; |
4067 the loop count into LC register. */ | 4188 |
4068 if (D_REGNO_P (REGNO (iter_reg))) | 4189 /* Create a sequence containing the loop setup. */ |
4069 { | 4190 start_sequence (); |
4070 init_insn = gen_movsi (lc_reg, iter_reg); | 4191 |
4192 /* LSETUP only accepts P registers. If we have one, we can use it, | |
4193 otherwise there are several ways of working around the problem. | |
4194 If we're not affected by anomaly 312, we can load the LC register | |
4195 from any iteration register, and use LSETUP without initialization. | |
4196 If we've found a P scratch register that's not live here, we can | |
4197 instead copy the iter_reg into that and use an initializing LSETUP. | |
4198 If all else fails, push and pop P0 and use it as a scratch. */ | |
4199 if (P_REGNO_P (REGNO (iter_reg))) | |
4200 { | |
4201 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, | |
4202 lb_reg, end_label, | |
4203 lc_reg, iter_reg); | |
4204 seq_end = emit_insn (loop_init); | |
4205 } | |
4206 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg)) | |
4207 { | |
4208 emit_insn (gen_movsi (lc_reg, iter_reg)); | |
4071 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label, | 4209 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label, |
4072 lb_reg, end_label, | 4210 lb_reg, end_label, |
4073 lc_reg); | 4211 lc_reg); |
4074 } | 4212 seq_end = emit_insn (loop_init); |
4075 else if (P_REGNO_P (REGNO (iter_reg))) | 4213 } |
4076 { | 4214 else if (scratchreg != NULL_RTX) |
4077 init_insn = NULL_RTX; | 4215 { |
4216 emit_insn (gen_movsi (scratchreg, scratch_init)); | |
4078 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, | 4217 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, |
4079 lb_reg, end_label, | 4218 lb_reg, end_label, |
4080 lc_reg, iter_reg); | 4219 lc_reg, scratchreg); |
4220 seq_end = emit_insn (loop_init); | |
4221 if (scratch_init_insn != NULL_RTX) | |
4222 delete_insn (scratch_init_insn); | |
4081 } | 4223 } |
4082 else | 4224 else |
4083 gcc_unreachable (); | 4225 { |
4084 | 4226 rtx p0reg = gen_rtx_REG (SImode, REG_P0); |
4085 loop->init = init_insn; | 4227 rtx push = gen_frame_mem (SImode, |
4086 loop->end_label = end_label; | 4228 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)); |
4087 loop->loop_init = loop_init; | 4229 rtx pop = gen_frame_mem (SImode, |
4230 gen_rtx_POST_INC (SImode, stack_pointer_rtx)); | |
4231 emit_insn (gen_movsi (push, p0reg)); | |
4232 emit_insn (gen_movsi (p0reg, scratch_init)); | |
4233 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label, | |
4234 lb_reg, end_label, | |
4235 lc_reg, p0reg); | |
4236 emit_insn (loop_init); | |
4237 seq_end = emit_insn (gen_movsi (p0reg, pop)); | |
4238 if (scratch_init_insn != NULL_RTX) | |
4239 delete_insn (scratch_init_insn); | |
4240 } | |
4088 | 4241 |
4089 if (dump_file) | 4242 if (dump_file) |
4090 { | 4243 { |
4091 fprintf (dump_file, ";; replacing loop %d initializer with\n", | 4244 fprintf (dump_file, ";; replacing loop %d initializer with\n", |
4092 loop->loop_no); | 4245 loop->loop_no); |
4093 print_rtl_single (dump_file, loop->loop_init); | 4246 print_rtl_single (dump_file, loop_init); |
4094 fprintf (dump_file, ";; replacing loop %d terminator with\n", | 4247 fprintf (dump_file, ";; replacing loop %d terminator with\n", |
4095 loop->loop_no); | 4248 loop->loop_no); |
4096 print_rtl_single (dump_file, loop->loop_end); | 4249 print_rtl_single (dump_file, loop->loop_end); |
4097 } | 4250 } |
4098 | |
4099 /* Create a sequence containing the loop setup. */ | |
4100 start_sequence (); | |
4101 | |
4102 if (loop->init != NULL_RTX) | |
4103 emit_insn (loop->init); | |
4104 seq_end = emit_insn (loop->loop_init); | |
4105 | 4251 |
4106 /* If the loop isn't entered at the top, also create a jump to the entry | 4252 /* If the loop isn't entered at the top, also create a jump to the entry |
4107 point. */ | 4253 point. */ |
4108 if (!loop->incoming_src && loop->head != loop->incoming_dest) | 4254 if (!loop->incoming_src && loop->head != loop->incoming_dest) |
4109 { | 4255 { |
4118 && GET_CODE (PATTERN (last_insn)) == SET) | 4264 && GET_CODE (PATTERN (last_insn)) == SET) |
4119 { | 4265 { |
4120 seq_end = emit_insn (copy_rtx (PATTERN (last_insn))); | 4266 seq_end = emit_insn (copy_rtx (PATTERN (last_insn))); |
4121 } | 4267 } |
4122 else | 4268 else |
4123 seq_end = emit_insn (gen_jump (label)); | 4269 { |
4270 emit_jump_insn (gen_jump (label)); | |
4271 seq_end = emit_barrier (); | |
4272 } | |
4124 } | 4273 } |
4125 | 4274 |
4126 seq = get_insns (); | 4275 seq = get_insns (); |
4127 end_sequence (); | 4276 end_sequence (); |
4128 | 4277 |
4166 || e->dest != loop->head) | 4315 || e->dest != loop->head) |
4167 redirect_edge_and_branch_force (e, new_bb); | 4316 redirect_edge_and_branch_force (e, new_bb); |
4168 else | 4317 else |
4169 redirect_edge_succ (e, new_bb); | 4318 redirect_edge_succ (e, new_bb); |
4170 } | 4319 } |
4171 } | 4320 e = make_edge (new_bb, loop->head, 0); |
4172 | 4321 } |
4322 | |
4173 delete_insn (loop->loop_end); | 4323 delete_insn (loop->loop_end); |
4174 /* Insert the loop end label before the last instruction of the loop. */ | 4324 /* Insert the loop end label before the last instruction of the loop. */ |
4175 emit_label_before (loop->end_label, loop->last_insn); | 4325 emit_label_before (loop->end_label, loop->last_insn); |
4176 | 4326 |
4177 return; | 4327 return; |
4185 | 4335 |
4186 if (DPREG_P (loop->iter_reg)) | 4336 if (DPREG_P (loop->iter_reg)) |
4187 { | 4337 { |
4188 /* If loop->iter_reg is a DREG or PREG, we can split it here | 4338 /* If loop->iter_reg is a DREG or PREG, we can split it here |
4189 without scratch register. */ | 4339 without scratch register. */ |
4190 rtx insn; | 4340 rtx insn, test; |
4191 | 4341 |
4192 emit_insn_before (gen_addsi3 (loop->iter_reg, | 4342 emit_insn_before (gen_addsi3 (loop->iter_reg, |
4193 loop->iter_reg, | 4343 loop->iter_reg, |
4194 constm1_rtx), | 4344 constm1_rtx), |
4195 loop->loop_end); | 4345 loop->loop_end); |
4196 | 4346 |
4197 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx), | 4347 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx); |
4198 loop->loop_end); | 4348 insn = emit_jump_insn_before (gen_cbranchsi4 (test, |
4199 | 4349 loop->iter_reg, const0_rtx, |
4200 insn = emit_jump_insn_before (gen_bne (loop->start_label), | 4350 loop->start_label), |
4201 loop->loop_end); | 4351 loop->loop_end); |
4202 | 4352 |
4203 JUMP_LABEL (insn) = loop->start_label; | 4353 JUMP_LABEL (insn) = loop->start_label; |
4204 LABEL_NUSES (loop->start_label)++; | 4354 LABEL_NUSES (loop->start_label)++; |
4205 delete_insn (loop->loop_end); | 4355 delete_insn (loop->loop_end); |
4228 loop->visited = 0; | 4378 loop->visited = 0; |
4229 loop->clobber_loop0 = loop->clobber_loop1 = 0; | 4379 loop->clobber_loop0 = loop->clobber_loop1 = 0; |
4230 loop->outer = NULL; | 4380 loop->outer = NULL; |
4231 loop->loops = NULL; | 4381 loop->loops = NULL; |
4232 loop->incoming = VEC_alloc (edge, gc, 2); | 4382 loop->incoming = VEC_alloc (edge, gc, 2); |
4233 loop->init = loop->loop_init = NULL_RTX; | |
4234 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0); | 4383 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0); |
4235 loop->end_label = NULL_RTX; | 4384 loop->end_label = NULL_RTX; |
4236 loop->bad = 0; | 4385 loop->bad = 0; |
4237 | 4386 |
4238 VEC_safe_push (basic_block, heap, works, loop->head); | 4387 VEC_safe_push (basic_block, heap, works, loop->head); |
4602 if (dump_file) | 4751 if (dump_file) |
4603 { | 4752 { |
4604 fprintf (dump_file, ";; All loops found:\n\n"); | 4753 fprintf (dump_file, ";; All loops found:\n\n"); |
4605 bfin_dump_loops (loops); | 4754 bfin_dump_loops (loops); |
4606 } | 4755 } |
4607 | 4756 |
4608 /* Now apply the optimizations. */ | 4757 /* Now apply the optimizations. */ |
4609 for (loop = loops; loop; loop = loop->next) | 4758 for (loop = loops; loop; loop = loop->next) |
4610 bfin_optimize_loop (loop); | 4759 bfin_optimize_loop (loop); |
4611 | 4760 |
4612 if (dump_file) | 4761 if (dump_file) |
4620 if (dump_file) | 4769 if (dump_file) |
4621 print_rtl (dump_file, get_insns ()); | 4770 print_rtl (dump_file, get_insns ()); |
4622 | 4771 |
4623 FOR_EACH_BB (bb) | 4772 FOR_EACH_BB (bb) |
4624 bb->aux = NULL; | 4773 bb->aux = NULL; |
4774 | |
4775 splitting_loops = 1; | |
4776 FOR_EACH_BB (bb) | |
4777 { | |
4778 rtx insn = BB_END (bb); | |
4779 if (!JUMP_P (insn)) | |
4780 continue; | |
4781 | |
4782 try_split (PATTERN (insn), insn, 1); | |
4783 } | |
4784 splitting_loops = 0; | |
4625 } | 4785 } |
4626 | 4786 |
4627 /* Possibly generate a SEQUENCE out of three insns found in SLOT. | 4787 /* Possibly generate a SEQUENCE out of three insns found in SLOT. |
4628 Returns true if we modified the insn chain, false otherwise. */ | 4788 Returns true if we modified the insn chain, false otherwise. */ |
4629 static bool | 4789 static bool |
4703 | 4863 |
4704 slot[0] = slot[1] = slot[2] = NULL_RTX; | 4864 slot[0] = slot[1] = slot[2] = NULL_RTX; |
4705 for (insn = BB_HEAD (bb);; insn = next) | 4865 for (insn = BB_HEAD (bb);; insn = next) |
4706 { | 4866 { |
4707 int at_end; | 4867 int at_end; |
4708 if (INSN_P (insn)) | 4868 rtx delete_this = NULL_RTX; |
4869 | |
4870 if (NONDEBUG_INSN_P (insn)) | |
4709 { | 4871 { |
4710 if (get_attr_type (insn) == TYPE_DSP32) | 4872 enum attr_type type = get_attr_type (insn); |
4711 slot[0] = insn; | 4873 |
4712 else if (slot[1] == NULL_RTX) | 4874 if (type == TYPE_STALL) |
4713 slot[1] = insn; | 4875 { |
4876 gcc_assert (n_filled == 0); | |
4877 delete_this = insn; | |
4878 } | |
4714 else | 4879 else |
4715 slot[2] = insn; | 4880 { |
4716 n_filled++; | 4881 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM) |
4882 slot[0] = insn; | |
4883 else if (slot[1] == NULL_RTX) | |
4884 slot[1] = insn; | |
4885 else | |
4886 slot[2] = insn; | |
4887 n_filled++; | |
4888 } | |
4717 } | 4889 } |
4718 | 4890 |
4719 next = NEXT_INSN (insn); | 4891 next = NEXT_INSN (insn); |
4720 while (next && insn != BB_END (bb) | 4892 while (next && insn != BB_END (bb) |
4721 && !(INSN_P (next) | 4893 && !(INSN_P (next) |
4726 next = NEXT_INSN (insn); | 4898 next = NEXT_INSN (insn); |
4727 } | 4899 } |
4728 | 4900 |
4729 /* BB_END can change due to emitting extra NOPs, so check here. */ | 4901 /* BB_END can change due to emitting extra NOPs, so check here. */ |
4730 at_end = insn == BB_END (bb); | 4902 at_end = insn == BB_END (bb); |
4731 if (at_end || GET_MODE (next) == TImode) | 4903 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode)) |
4732 { | 4904 { |
4733 if ((n_filled < 2 | 4905 if ((n_filled < 2 |
4734 || !gen_one_bundle (slot)) | 4906 || !gen_one_bundle (slot)) |
4735 && slot[0] != NULL_RTX) | 4907 && slot[0] != NULL_RTX) |
4736 { | 4908 { |
4745 } | 4917 } |
4746 } | 4918 } |
4747 n_filled = 0; | 4919 n_filled = 0; |
4748 slot[0] = slot[1] = slot[2] = NULL_RTX; | 4920 slot[0] = slot[1] = slot[2] = NULL_RTX; |
4749 } | 4921 } |
4922 if (delete_this != NULL_RTX) | |
4923 delete_insn (delete_this); | |
4750 if (at_end) | 4924 if (at_end) |
4751 break; | 4925 break; |
4752 } | 4926 } |
4753 } | 4927 } |
4754 } | 4928 } |
4905 } | 5079 } |
4906 else | 5080 else |
4907 return get_attr_type (insn); | 5081 return get_attr_type (insn); |
4908 } | 5082 } |
4909 | 5083 |
4910 /* Return nonzero if INSN contains any loads that may trap. It handles | 5084 /* Return true iff the address found in MEM is based on the register |
4911 SEQUENCEs correctly. */ | 5085 NP_REG and optionally has a positive offset. */ |
4912 | |
4913 static bool | 5086 static bool |
4914 trapping_loads_p (rtx insn) | 5087 harmless_null_pointer_p (rtx mem, int np_reg) |
5088 { | |
5089 mem = XEXP (mem, 0); | |
5090 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC) | |
5091 mem = XEXP (mem, 0); | |
5092 if (REG_P (mem) && REGNO (mem) == np_reg) | |
5093 return true; | |
5094 if (GET_CODE (mem) == PLUS | |
5095 && REG_P (XEXP (mem, 0)) && REGNO (XEXP (mem, 0)) == np_reg) | |
5096 { | |
5097 mem = XEXP (mem, 1); | |
5098 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0) | |
5099 return true; | |
5100 } | |
5101 return false; | |
5102 } | |
5103 | |
5104 /* Return nonzero if INSN contains any loads that may trap. */ | |
5105 | |
5106 static bool | |
5107 trapping_loads_p (rtx insn, int np_reg, bool after_np_branch) | |
4915 { | 5108 { |
4916 rtx pat = PATTERN (insn); | 5109 rtx pat = PATTERN (insn); |
4917 if (GET_CODE (pat) == SEQUENCE) | 5110 rtx mem = SET_SRC (single_set (insn)); |
4918 { | 5111 |
4919 enum attr_type t; | 5112 if (!after_np_branch) |
4920 t = get_attr_type (XVECEXP (pat, 0, 1)); | 5113 np_reg = -1; |
4921 if (t == TYPE_MCLD | 5114 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg)) |
4922 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1))))) | 5115 && may_trap_p (mem)); |
4923 return true; | |
4924 t = get_attr_type (XVECEXP (pat, 0, 2)); | |
4925 if (t == TYPE_MCLD | |
4926 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2))))) | |
4927 return true; | |
4928 return false; | |
4929 } | |
4930 else | |
4931 return may_trap_p (SET_SRC (single_set (insn))); | |
4932 } | 5116 } |
4933 | 5117 |
4934 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of | 5118 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of |
4935 a three-insn bundle, see if one of them is a load and return that if so. | 5119 a three-insn bundle, see if one of them is a load and return that if so. |
4936 Return NULL_RTX if the insn does not contain loads. */ | 5120 Return NULL_RTX if the insn does not contain loads. */ |
4937 static rtx | 5121 static rtx |
4938 find_load (rtx insn) | 5122 find_load (rtx insn) |
4939 { | 5123 { |
5124 if (!NONDEBUG_INSN_P (insn)) | |
5125 return NULL_RTX; | |
4940 if (get_attr_type (insn) == TYPE_MCLD) | 5126 if (get_attr_type (insn) == TYPE_MCLD) |
4941 return insn; | 5127 return insn; |
4942 if (GET_MODE (insn) != SImode) | 5128 if (GET_MODE (insn) != SImode) |
4943 return NULL_RTX; | 5129 return NULL_RTX; |
4944 do { | 5130 do { |
4964 pat = XEXP (pat, 0); | 5150 pat = XEXP (pat, 0); |
4965 | 5151 |
4966 return REG_P (pat); | 5152 return REG_P (pat); |
4967 } | 5153 } |
4968 | 5154 |
5155 /* During workaround_speculation, track whether we're in the shadow of a | |
5156 conditional branch that tests a P register for NULL. If so, we can omit | |
5157 emitting NOPs if we see a load from that P register, since a speculative | |
5158 access at address 0 isn't a problem, and the load is executed in all other | |
5159 cases anyway. | |
5160 Global for communication with note_np_check_stores through note_stores. | |
5161 */ | |
5162 int np_check_regno = -1; | |
5163 bool np_after_branch = false; | |
5164 | |
5165 /* Subroutine of workaround_speculation, called through note_stores. */ | |
5166 static void | |
5167 note_np_check_stores (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED) | |
5168 { | |
5169 if (REG_P (x) && (REGNO (x) == REG_CC || REGNO (x) == np_check_regno)) | |
5170 np_check_regno = -1; | |
5171 } | |
5172 | |
4969 static void | 5173 static void |
4970 workaround_speculation (void) | 5174 workaround_speculation (void) |
4971 { | 5175 { |
4972 rtx insn, next; | 5176 rtx insn, next; |
4973 rtx last_condjump = NULL_RTX; | 5177 rtx last_condjump = NULL_RTX; |
4985 rtx pat; | 5189 rtx pat; |
4986 int delay_needed = 0; | 5190 int delay_needed = 0; |
4987 | 5191 |
4988 next = find_next_insn_start (insn); | 5192 next = find_next_insn_start (insn); |
4989 | 5193 |
4990 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn)) | 5194 if (NOTE_P (insn) || BARRIER_P (insn)) |
4991 continue; | 5195 continue; |
5196 | |
5197 if (LABEL_P (insn)) | |
5198 { | |
5199 np_check_regno = -1; | |
5200 continue; | |
5201 } | |
4992 | 5202 |
4993 pat = PATTERN (insn); | 5203 pat = PATTERN (insn); |
4994 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER | 5204 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER |
4995 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC | 5205 || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC) |
4996 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) | |
4997 continue; | 5206 continue; |
5207 | |
5208 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0) | |
5209 { | |
5210 np_check_regno = -1; | |
5211 continue; | |
5212 } | |
4998 | 5213 |
4999 if (JUMP_P (insn)) | 5214 if (JUMP_P (insn)) |
5000 { | 5215 { |
5216 /* Is this a condjump based on a null pointer comparison we saw | |
5217 earlier? */ | |
5218 if (np_check_regno != -1 | |
5219 && recog_memoized (insn) == CODE_FOR_cbranchbi4) | |
5220 { | |
5221 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0); | |
5222 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE); | |
5223 if (GET_CODE (op) == NE) | |
5224 np_after_branch = true; | |
5225 } | |
5001 if (any_condjump_p (insn) | 5226 if (any_condjump_p (insn) |
5002 && ! cbranch_predicted_taken_p (insn)) | 5227 && ! cbranch_predicted_taken_p (insn)) |
5003 { | 5228 { |
5004 last_condjump = insn; | 5229 last_condjump = insn; |
5005 delay_added = 0; | 5230 delay_added = 0; |
5008 else | 5233 else |
5009 cycles_since_jump = INT_MAX; | 5234 cycles_since_jump = INT_MAX; |
5010 } | 5235 } |
5011 else if (CALL_P (insn)) | 5236 else if (CALL_P (insn)) |
5012 { | 5237 { |
5238 np_check_regno = -1; | |
5013 if (cycles_since_jump < INT_MAX) | 5239 if (cycles_since_jump < INT_MAX) |
5014 cycles_since_jump++; | 5240 cycles_since_jump++; |
5015 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS) | 5241 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS) |
5016 { | 5242 { |
5017 delay_needed = 3; | 5243 delay_needed = 3; |
5018 } | 5244 } |
5019 } | 5245 } |
5020 else if (INSN_P (insn)) | 5246 else if (NONDEBUG_INSN_P (insn)) |
5021 { | 5247 { |
5022 rtx load_insn = find_load (insn); | 5248 rtx load_insn = find_load (insn); |
5023 enum attr_type type = type_for_anomaly (insn); | 5249 enum attr_type type = type_for_anomaly (insn); |
5024 | 5250 |
5025 if (cycles_since_jump < INT_MAX) | 5251 if (cycles_since_jump < INT_MAX) |
5026 cycles_since_jump++; | 5252 cycles_since_jump++; |
5027 | 5253 |
5254 /* Detect a comparison of a P register with zero. If we later | |
5255 see a condjump based on it, we have found a null pointer | |
5256 check. */ | |
5257 if (recog_memoized (insn) == CODE_FOR_compare_eq) | |
5258 { | |
5259 rtx src = SET_SRC (PATTERN (insn)); | |
5260 if (REG_P (XEXP (src, 0)) | |
5261 && P_REGNO_P (REGNO (XEXP (src, 0))) | |
5262 && XEXP (src, 1) == const0_rtx) | |
5263 { | |
5264 np_check_regno = REGNO (XEXP (src, 0)); | |
5265 np_after_branch = false; | |
5266 } | |
5267 else | |
5268 np_check_regno = -1; | |
5269 } | |
5270 | |
5028 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) | 5271 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) |
5029 { | 5272 { |
5030 if (trapping_loads_p (load_insn)) | 5273 if (trapping_loads_p (load_insn, np_check_regno, |
5274 np_after_branch)) | |
5031 delay_needed = 4; | 5275 delay_needed = 4; |
5032 } | 5276 } |
5033 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) | 5277 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) |
5034 delay_needed = 3; | 5278 delay_needed = 3; |
5279 | |
5280 /* See if we need to forget about a null pointer comparison | |
5281 we found earlier. */ | |
5282 if (recog_memoized (insn) != CODE_FOR_compare_eq) | |
5283 { | |
5284 note_stores (PATTERN (insn), note_np_check_stores, NULL); | |
5285 if (np_check_regno != -1) | |
5286 { | |
5287 if (find_regno_note (insn, REG_INC, np_check_regno)) | |
5288 np_check_regno = -1; | |
5289 } | |
5290 } | |
5291 | |
5035 } | 5292 } |
5036 | 5293 |
5037 if (delay_needed > cycles_since_jump | 5294 if (delay_needed > cycles_since_jump |
5038 && (delay_needed - cycles_since_jump) > delay_added) | 5295 && (delay_needed - cycles_since_jump) > delay_added) |
5039 { | 5296 { |
5097 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER | 5354 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER |
5098 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC | 5355 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC |
5099 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) | 5356 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) |
5100 continue; | 5357 continue; |
5101 | 5358 |
5102 if (INSN_P (target)) | 5359 if (NONDEBUG_INSN_P (target)) |
5103 { | 5360 { |
5104 rtx load_insn = find_load (target); | 5361 rtx load_insn = find_load (target); |
5105 enum attr_type type = type_for_anomaly (target); | 5362 enum attr_type type = type_for_anomaly (target); |
5106 int delay_needed = 0; | 5363 int delay_needed = 0; |
5107 if (cycles_since_jump < INT_MAX) | 5364 if (cycles_since_jump < INT_MAX) |
5108 cycles_since_jump++; | 5365 cycles_since_jump++; |
5109 | 5366 |
5110 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) | 5367 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS) |
5111 { | 5368 { |
5112 if (trapping_loads_p (load_insn)) | 5369 if (trapping_loads_p (load_insn, -1, false)) |
5113 delay_needed = 2; | 5370 delay_needed = 2; |
5114 } | 5371 } |
5115 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) | 5372 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS) |
5116 delay_needed = 2; | 5373 delay_needed = 2; |
5117 | 5374 |
5145 } | 5402 } |
5146 } | 5403 } |
5147 } | 5404 } |
5148 } | 5405 } |
5149 | 5406 |
5407 /* Called just before the final scheduling pass. If we need to insert NOPs | |
5408 later on to work around speculative loads, insert special placeholder | |
5409 insns that cause loads to be delayed for as many cycles as necessary | |
5410 (and possible). This reduces the number of NOPs we need to add. | |
5411 The dummy insns we generate are later removed by bfin_gen_bundles. */ | |
5412 static void | |
5413 add_sched_insns_for_speculation (void) | |
5414 { | |
5415 rtx insn; | |
5416 | |
5417 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS | |
5418 && ! ENABLE_WA_INDIRECT_CALLS) | |
5419 return; | |
5420 | |
5421 /* First pass: find predicted-false branches; if something after them | |
5422 needs nops, insert them or change the branch to predict true. */ | |
5423 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
5424 { | |
5425 rtx pat; | |
5426 | |
5427 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn)) | |
5428 continue; | |
5429 | |
5430 pat = PATTERN (insn); | |
5431 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER | |
5432 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC | |
5433 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0) | |
5434 continue; | |
5435 | |
5436 if (JUMP_P (insn)) | |
5437 { | |
5438 if (any_condjump_p (insn) | |
5439 && !cbranch_predicted_taken_p (insn)) | |
5440 { | |
5441 rtx n = next_real_insn (insn); | |
5442 emit_insn_before (gen_stall (GEN_INT (3)), n); | |
5443 } | |
5444 } | |
5445 } | |
5446 | |
5447 /* Second pass: for predicted-true branches, see if anything at the | |
5448 branch destination needs extra nops. */ | |
5449 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
5450 { | |
5451 if (JUMP_P (insn) | |
5452 && any_condjump_p (insn) | |
5453 && (cbranch_predicted_taken_p (insn))) | |
5454 { | |
5455 rtx target = JUMP_LABEL (insn); | |
5456 rtx next = next_real_insn (target); | |
5457 | |
5458 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE | |
5459 && get_attr_type (next) == TYPE_STALL) | |
5460 continue; | |
5461 emit_insn_before (gen_stall (GEN_INT (1)), next); | |
5462 } | |
5463 } | |
5464 } | |
5465 | |
5150 /* We use the machine specific reorg pass for emitting CSYNC instructions | 5466 /* We use the machine specific reorg pass for emitting CSYNC instructions |
5151 after conditional branches as needed. | 5467 after conditional branches as needed. |
5152 | 5468 |
5153 The Blackfin is unusual in that a code sequence like | 5469 The Blackfin is unusual in that a code sequence like |
5154 if cc jump label | 5470 if cc jump label |
5178 { | 5494 { |
5179 splitting_for_sched = 1; | 5495 splitting_for_sched = 1; |
5180 split_all_insns (); | 5496 split_all_insns (); |
5181 splitting_for_sched = 0; | 5497 splitting_for_sched = 0; |
5182 | 5498 |
5499 add_sched_insns_for_speculation (); | |
5500 | |
5183 timevar_push (TV_SCHED2); | 5501 timevar_push (TV_SCHED2); |
5184 schedule_insns (); | 5502 schedule_insns (); |
5185 timevar_pop (TV_SCHED2); | 5503 timevar_pop (TV_SCHED2); |
5186 | 5504 |
5187 /* Examine the schedule and insert nops as necessary for 64-bit parallel | 5505 /* Examine the schedule and insert nops as necessary for 64-bit parallel |
5223 if (TREE_CODE (x) == FUNCTION_DECL) | 5541 if (TREE_CODE (x) == FUNCTION_DECL) |
5224 x = TREE_TYPE (x); | 5542 x = TREE_TYPE (x); |
5225 | 5543 |
5226 if (TREE_CODE (x) != FUNCTION_TYPE) | 5544 if (TREE_CODE (x) != FUNCTION_TYPE) |
5227 { | 5545 { |
5228 warning (OPT_Wattributes, "%qs attribute only applies to functions", | 5546 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
5229 IDENTIFIER_POINTER (name)); | 5547 name); |
5230 *no_add_attrs = true; | 5548 *no_add_attrs = true; |
5231 } | 5549 } |
5232 else if (funkind (x) != SUBROUTINE) | 5550 else if (funkind (x) != SUBROUTINE) |
5233 error ("multiple function type attributes specified"); | 5551 error ("multiple function type attributes specified"); |
5234 | 5552 |
5284 { | 5602 { |
5285 if (TREE_CODE (*node) != FUNCTION_TYPE | 5603 if (TREE_CODE (*node) != FUNCTION_TYPE |
5286 && TREE_CODE (*node) != FIELD_DECL | 5604 && TREE_CODE (*node) != FIELD_DECL |
5287 && TREE_CODE (*node) != TYPE_DECL) | 5605 && TREE_CODE (*node) != TYPE_DECL) |
5288 { | 5606 { |
5289 warning (OPT_Wattributes, "`%s' attribute only applies to functions", | 5607 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
5290 IDENTIFIER_POINTER (name)); | 5608 name); |
5291 *no_add_attrs = true; | 5609 *no_add_attrs = true; |
5292 } | 5610 } |
5293 | 5611 |
5294 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0 | 5612 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0 |
5295 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node))) | 5613 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node))) |
5313 { | 5631 { |
5314 tree decl = *node; | 5632 tree decl = *node; |
5315 | 5633 |
5316 if (TREE_CODE (decl) != FUNCTION_DECL) | 5634 if (TREE_CODE (decl) != FUNCTION_DECL) |
5317 { | 5635 { |
5318 error ("`%s' attribute only applies to functions", | 5636 error ("%qE attribute only applies to functions", |
5319 IDENTIFIER_POINTER (name)); | 5637 name); |
5320 *no_add_attrs = true; | 5638 *no_add_attrs = true; |
5321 } | 5639 } |
5322 | 5640 |
5323 /* The decl may have already been given a section attribute | 5641 /* The decl may have already been given a section attribute |
5324 from a previous declaration. Ensure they match. */ | 5642 from a previous declaration. Ensure they match. */ |
5345 { | 5663 { |
5346 tree decl = *node; | 5664 tree decl = *node; |
5347 | 5665 |
5348 if (TREE_CODE (decl) != VAR_DECL) | 5666 if (TREE_CODE (decl) != VAR_DECL) |
5349 { | 5667 { |
5350 error ("`%s' attribute only applies to variables", | 5668 error ("%qE attribute only applies to variables", |
5351 IDENTIFIER_POINTER (name)); | 5669 name); |
5352 *no_add_attrs = true; | 5670 *no_add_attrs = true; |
5353 } | 5671 } |
5354 else if (current_function_decl != NULL_TREE | 5672 else if (current_function_decl != NULL_TREE |
5355 && !TREE_STATIC (decl)) | 5673 && !TREE_STATIC (decl)) |
5356 { | 5674 { |
5357 error ("`%s' attribute cannot be specified for local variables", | 5675 error ("%qE attribute cannot be specified for local variables", |
5358 IDENTIFIER_POINTER (name)); | 5676 name); |
5359 *no_add_attrs = true; | 5677 *no_add_attrs = true; |
5360 } | 5678 } |
5361 else | 5679 else |
5362 { | 5680 { |
5363 const char *section_name; | 5681 const char *section_name; |
5387 } | 5705 } |
5388 | 5706 |
5389 return NULL_TREE; | 5707 return NULL_TREE; |
5390 } | 5708 } |
5391 | 5709 |
5710 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */ | |
5711 | |
5712 static tree | |
5713 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name), | |
5714 tree ARG_UNUSED (args), int ARG_UNUSED (flags), | |
5715 bool *no_add_attrs) | |
5716 { | |
5717 tree decl = *node; | |
5718 | |
5719 if (TREE_CODE (decl) == FUNCTION_DECL) | |
5720 { | |
5721 if (DECL_SECTION_NAME (decl) != NULL_TREE | |
5722 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), | |
5723 ".l2.text") != 0) | |
5724 { | |
5725 error ("section of %q+D conflicts with previous declaration", | |
5726 decl); | |
5727 *no_add_attrs = true; | |
5728 } | |
5729 else | |
5730 DECL_SECTION_NAME (decl) = build_string (9, ".l2.text"); | |
5731 } | |
5732 else if (TREE_CODE (decl) == VAR_DECL) | |
5733 { | |
5734 if (DECL_SECTION_NAME (decl) != NULL_TREE | |
5735 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), | |
5736 ".l2.data") != 0) | |
5737 { | |
5738 error ("section of %q+D conflicts with previous declaration", | |
5739 decl); | |
5740 *no_add_attrs = true; | |
5741 } | |
5742 else | |
5743 DECL_SECTION_NAME (decl) = build_string (9, ".l2.data"); | |
5744 } | |
5745 | |
5746 return NULL_TREE; | |
5747 } | |
5748 | |
5392 /* Table of valid machine attributes. */ | 5749 /* Table of valid machine attributes. */ |
5393 const struct attribute_spec bfin_attribute_table[] = | 5750 static const struct attribute_spec bfin_attribute_table[] = |
5394 { | 5751 { |
5395 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | 5752 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ |
5396 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute }, | 5753 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute }, |
5397 { "exception_handler", 0, 0, false, true, true, handle_int_attribute }, | 5754 { "exception_handler", 0, 0, false, true, true, handle_int_attribute }, |
5398 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute }, | 5755 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute }, |
5403 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute }, | 5760 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute }, |
5404 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute }, | 5761 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute }, |
5405 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, | 5762 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, |
5406 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, | 5763 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, |
5407 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, | 5764 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute }, |
5765 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute }, | |
5408 { NULL, 0, 0, false, false, false, NULL } | 5766 { NULL, 0, 0, false, false, false, NULL } |
5409 }; | 5767 }; |
5410 | 5768 |
5411 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to | 5769 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to |
5412 tell the assembler to generate pointers to function descriptors in | 5770 tell the assembler to generate pointers to function descriptors in |
6014 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | 6372 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); |
6015 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); | 6373 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); |
6016 if (! target | 6374 if (! target |
6017 || !register_operand (target, SImode)) | 6375 || !register_operand (target, SImode)) |
6018 target = gen_reg_rtx (SImode); | 6376 target = gen_reg_rtx (SImode); |
6377 if (! register_operand (op0, SImode)) | |
6378 op0 = copy_to_mode_reg (SImode, op0); | |
6379 if (! register_operand (op1, SImode)) | |
6380 op1 = copy_to_mode_reg (SImode, op1); | |
6019 | 6381 |
6020 a1reg = gen_rtx_REG (PDImode, REG_A1); | 6382 a1reg = gen_rtx_REG (PDImode, REG_A1); |
6021 a0reg = gen_rtx_REG (PDImode, REG_A0); | 6383 a0reg = gen_rtx_REG (PDImode, REG_A0); |
6022 tmp1 = gen_lowpart (V2HImode, op0); | 6384 tmp1 = gen_lowpart (V2HImode, op0); |
6023 tmp2 = gen_lowpart (V2HImode, op1); | 6385 tmp2 = gen_lowpart (V2HImode, op1); |
6067 arg0 = CALL_EXPR_ARG (exp, 0); | 6429 arg0 = CALL_EXPR_ARG (exp, 0); |
6068 arg1 = CALL_EXPR_ARG (exp, 1); | 6430 arg1 = CALL_EXPR_ARG (exp, 1); |
6069 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | 6431 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); |
6070 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); | 6432 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); |
6071 accvec = gen_reg_rtx (V2PDImode); | 6433 accvec = gen_reg_rtx (V2PDImode); |
6434 icode = CODE_FOR_flag_macv2hi_parts; | |
6072 | 6435 |
6073 if (! target | 6436 if (! target |
6074 || GET_MODE (target) != V2HImode | 6437 || GET_MODE (target) != V2HImode |
6075 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) | 6438 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) |
6076 target = gen_reg_rtx (tmode); | 6439 target = gen_reg_rtx (tmode); |
6103 arg2 = CALL_EXPR_ARG (exp, 2); | 6466 arg2 = CALL_EXPR_ARG (exp, 2); |
6104 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); | 6467 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); |
6105 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); | 6468 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); |
6106 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); | 6469 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0); |
6107 accvec = gen_reg_rtx (V2PDImode); | 6470 accvec = gen_reg_rtx (V2PDImode); |
6471 icode = CODE_FOR_flag_macv2hi_parts; | |
6108 | 6472 |
6109 if (! target | 6473 if (! target |
6110 || GET_MODE (target) != V2HImode | 6474 || GET_MODE (target) != V2HImode |
6111 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) | 6475 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode)) |
6112 target = gen_reg_rtx (tmode); | 6476 target = gen_reg_rtx (tmode); |
6167 if (! register_operand (op0, GET_MODE (op0))) | 6531 if (! register_operand (op0, GET_MODE (op0))) |
6168 op0 = copy_to_mode_reg (GET_MODE (op0), op0); | 6532 op0 = copy_to_mode_reg (GET_MODE (op0), op0); |
6169 | 6533 |
6170 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE))); | 6534 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE))); |
6171 | 6535 |
6172 emit_insn (gen_flag_mulhi_parts (tmp2, op0, op0, const0_rtx, | 6536 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0, |
6173 const0_rtx, const1_rtx, | 6537 const0_rtx, const1_rtx, |
6174 GEN_INT (MACFLAG_NONE))); | 6538 GEN_INT (MACFLAG_NONE))); |
6175 | 6539 |
6176 emit_insn (gen_ssaddhi3_parts (target, tmp2, tmp2, const1_rtx, | 6540 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx, |
6177 const0_rtx, const0_rtx)); | 6541 const0_rtx)); |
6178 | 6542 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1, |
6179 emit_insn (gen_sssubhi3_parts (target, tmp1, tmp1, const0_rtx, | 6543 const0_rtx, const1_rtx)); |
6180 const0_rtx, const1_rtx)); | |
6181 | 6544 |
6182 return target; | 6545 return target; |
6183 | 6546 |
6184 default: | 6547 default: |
6185 break; | 6548 break; |
6239 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost | 6602 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost |
6240 | 6603 |
6241 #undef TARGET_SCHED_ISSUE_RATE | 6604 #undef TARGET_SCHED_ISSUE_RATE |
6242 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate | 6605 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate |
6243 | 6606 |
6244 #undef TARGET_PROMOTE_PROTOTYPES | 6607 #undef TARGET_PROMOTE_FUNCTION_MODE |
6245 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | 6608 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote |
6246 #undef TARGET_PROMOTE_FUNCTION_ARGS | |
6247 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true | |
6248 #undef TARGET_PROMOTE_FUNCTION_RETURN | |
6249 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true | |
6250 | 6609 |
6251 #undef TARGET_ARG_PARTIAL_BYTES | 6610 #undef TARGET_ARG_PARTIAL_BYTES |
6252 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes | 6611 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes |
6253 | 6612 |
6254 #undef TARGET_PASS_BY_REFERENCE | 6613 #undef TARGET_PASS_BY_REFERENCE |
6279 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem | 6638 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem |
6280 | 6639 |
6281 #undef TARGET_RETURN_IN_MEMORY | 6640 #undef TARGET_RETURN_IN_MEMORY |
6282 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory | 6641 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory |
6283 | 6642 |
6643 #undef TARGET_LEGITIMATE_ADDRESS_P | |
6644 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p | |
6645 | |
6646 #undef TARGET_FRAME_POINTER_REQUIRED | |
6647 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required | |
6648 | |
6649 #undef TARGET_CAN_ELIMINATE | |
6650 #define TARGET_CAN_ELIMINATE bfin_can_eliminate | |
6651 | |
6652 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
6653 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template | |
6654 #undef TARGET_TRAMPOLINE_INIT | |
6655 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init | |
6656 | |
6284 struct gcc_target targetm = TARGET_INITIALIZER; | 6657 struct gcc_target targetm = TARGET_INITIALIZER; |