1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2015 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "gimple-expr.h"
33 #include "diagnostic-core.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
40 #include "langhooks.h"
43 /* This file should be included last. */
44 #include "target-def.h"
47 static void msp430_compute_frame_info (void);
51 /* Run-time Target Specification. */
55 struct GTY(()) machine_function
57 /* If set, the rest of the fields have been computed. */
59 /* Which registers need to be saved in the pro/epilogue. */
60 int need_to_save
[FIRST_PSEUDO_REGISTER
];
62 /* These fields describe the frame layout... */
64 /* 2/4 bytes for saved PC */
68 int framesize_outgoing
;
72 /* How much we adjust the stack when returning from an exception
77 /* This is our init_machine_status, as set in
78 msp_option_override. */
79 static struct machine_function
*
80 msp430_init_machine_status (void)
82 struct machine_function
*m
;
84 m
= ggc_cleared_alloc
<machine_function
> ();
89 #undef TARGET_OPTION_OVERRIDE
90 #define TARGET_OPTION_OVERRIDE msp430_option_override
92 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
93 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430.
94 Keep these three structures in sync.
95 The data in this structure has been extracted from the devices.csv file
96 released by TI, updated as of 8 October 2015. */
98 struct msp430_mcu_data
101 unsigned int revision
; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
102 unsigned int hwmpy
; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
106 { "cc430f5123",2,8 },
107 { "cc430f5125",2,8 },
108 { "cc430f5133",2,8 },
109 { "cc430f5135",2,8 },
110 { "cc430f5137",2,8 },
111 { "cc430f5143",2,8 },
112 { "cc430f5145",2,8 },
113 { "cc430f5147",2,8 },
114 { "cc430f6125",2,8 },
115 { "cc430f6126",2,8 },
116 { "cc430f6127",2,8 },
117 { "cc430f6135",2,8 },
118 { "cc430f6137",2,8 },
119 { "cc430f6143",2,8 },
120 { "cc430f6145",2,8 },
121 { "cc430f6147",2,8 },
122 { "msp430afe221",0,2 },
123 { "msp430afe222",0,2 },
124 { "msp430afe223",0,2 },
125 { "msp430afe231",0,2 },
126 { "msp430afe232",0,2 },
127 { "msp430afe233",0,2 },
128 { "msp430afe251",0,2 },
129 { "msp430afe252",0,2 },
130 { "msp430afe253",0,2 },
131 { "msp430bt5190",2,8 },
132 { "msp430c091",0,0 },
133 { "msp430c092",0,0 },
134 { "msp430c111",0,0 },
135 { "msp430c1111",0,0 },
136 { "msp430c112",0,0 },
137 { "msp430c1121",0,0 },
138 { "msp430c1331",0,0 },
139 { "msp430c1351",0,0 },
140 { "msp430c311s",0,0 },
141 { "msp430c312",0,0 },
142 { "msp430c313",0,0 },
143 { "msp430c314",0,0 },
144 { "msp430c315",0,0 },
145 { "msp430c323",0,0 },
146 { "msp430c325",0,0 },
147 { "msp430c336",0,1 },
148 { "msp430c337",0,1 },
149 { "msp430c412",0,0 },
150 { "msp430c413",0,0 },
151 { "msp430cg4616",1,1 },
152 { "msp430cg4617",1,1 },
153 { "msp430cg4618",1,1 },
154 { "msp430cg4619",1,1 },
155 { "msp430e112",0,0 },
156 { "msp430e313",0,0 },
157 { "msp430e315",0,0 },
158 { "msp430e325",0,0 },
159 { "msp430e337",0,1 },
160 { "msp430f110",0,0 },
161 { "msp430f1101",0,0 },
162 { "msp430f1101a",0,0 },
163 { "msp430f1111",0,0 },
164 { "msp430f1111a",0,0 },
165 { "msp430f112",0,0 },
166 { "msp430f1121",0,0 },
167 { "msp430f1121a",0,0 },
168 { "msp430f1122",0,0 },
169 { "msp430f1132",0,0 },
170 { "msp430f122",0,0 },
171 { "msp430f1222",0,0 },
172 { "msp430f123",0,0 },
173 { "msp430f1232",0,0 },
174 { "msp430f133",0,0 },
175 { "msp430f135",0,0 },
176 { "msp430f147",0,1 },
177 { "msp430f1471",0,1 },
178 { "msp430f148",0,1 },
179 { "msp430f1481",0,1 },
180 { "msp430f149",0,1 },
181 { "msp430f1491",0,1 },
182 { "msp430f155",0,0 },
183 { "msp430f156",0,0 },
184 { "msp430f157",0,0 },
185 { "msp430f1610",0,1 },
186 { "msp430f1611",0,1 },
187 { "msp430f1612",0,1 },
188 { "msp430f167",0,1 },
189 { "msp430f168",0,1 },
190 { "msp430f169",0,1 },
191 { "msp430f2001",0,0 },
192 { "msp430f2002",0,0 },
193 { "msp430f2003",0,0 },
194 { "msp430f2011",0,0 },
195 { "msp430f2012",0,0 },
196 { "msp430f2013",0,0 },
197 { "msp430f2101",0,0 },
198 { "msp430f2111",0,0 },
199 { "msp430f2112",0,0 },
200 { "msp430f2121",0,0 },
201 { "msp430f2122",0,0 },
202 { "msp430f2131",0,0 },
203 { "msp430f2132",0,0 },
204 { "msp430f2232",0,0 },
205 { "msp430f2234",0,0 },
206 { "msp430f2252",0,0 },
207 { "msp430f2254",0,0 },
208 { "msp430f2272",0,0 },
209 { "msp430f2274",0,0 },
210 { "msp430f233",0,2 },
211 { "msp430f2330",0,2 },
212 { "msp430f235",0,2 },
213 { "msp430f2350",0,2 },
214 { "msp430f2370",0,2 },
215 { "msp430f2410",0,2 },
216 { "msp430f2416",1,2 },
217 { "msp430f2417",1,2 },
218 { "msp430f2418",1,2 },
219 { "msp430f2419",1,2 },
220 { "msp430f247",0,2 },
221 { "msp430f2471",0,2 },
222 { "msp430f248",0,2 },
223 { "msp430f2481",0,2 },
224 { "msp430f249",0,2 },
225 { "msp430f2491",0,2 },
226 { "msp430f2616",1,2 },
227 { "msp430f2617",1,2 },
228 { "msp430f2618",1,2 },
229 { "msp430f2619",1,2 },
230 { "msp430f412",0,0 },
231 { "msp430f413",0,0 },
232 { "msp430f4132",0,0 },
233 { "msp430f415",0,0 },
234 { "msp430f4152",0,0 },
235 { "msp430f417",0,0 },
236 { "msp430f423",0,1 },
237 { "msp430f423a",0,1 },
238 { "msp430f425",0,1 },
239 { "msp430f4250",0,0 },
240 { "msp430f425a",0,1 },
241 { "msp430f4260",0,0 },
242 { "msp430f427",0,1 },
243 { "msp430f4270",0,0 },
244 { "msp430f427a",0,1 },
245 { "msp430f435",0,0 },
246 { "msp430f4351",0,0 },
247 { "msp430f436",0,0 },
248 { "msp430f4361",0,0 },
249 { "msp430f437",0,0 },
250 { "msp430f4371",0,0 },
251 { "msp430f438",0,0 },
252 { "msp430f439",0,0 },
253 { "msp430f447",0,1 },
254 { "msp430f448",0,1 },
255 { "msp430f4481",0,1 },
256 { "msp430f449",0,1 },
257 { "msp430f4491",0,1 },
258 { "msp430f4616",1,1 },
259 { "msp430f46161",1,1 },
260 { "msp430f4617",1,1 },
261 { "msp430f46171",1,1 },
262 { "msp430f4618",1,1 },
263 { "msp430f46181",1,1 },
264 { "msp430f4619",1,1 },
265 { "msp430f46191",1,1 },
266 { "msp430f47126",1,4 },
267 { "msp430f47127",1,4 },
268 { "msp430f47163",1,4 },
269 { "msp430f47166",1,4 },
270 { "msp430f47167",1,4 },
271 { "msp430f47173",1,4 },
272 { "msp430f47176",1,4 },
273 { "msp430f47177",1,4 },
274 { "msp430f47183",1,4 },
275 { "msp430f47186",1,4 },
276 { "msp430f47187",1,4 },
277 { "msp430f47193",1,4 },
278 { "msp430f47196",1,4 },
279 { "msp430f47197",1,4 },
280 { "msp430f477",0,0 },
281 { "msp430f478",0,0 },
282 { "msp430f4783",0,4 },
283 { "msp430f4784",0,4 },
284 { "msp430f479",0,0 },
285 { "msp430f4793",0,4 },
286 { "msp430f4794",0,4 },
287 { "msp430f5131",2,8 },
288 { "msp430f5132",2,8 },
289 { "msp430f5151",2,8 },
290 { "msp430f5152",2,8 },
291 { "msp430f5171",2,8 },
292 { "msp430f5172",2,8 },
293 { "msp430f5212",2,8 },
294 { "msp430f5213",2,8 },
295 { "msp430f5214",2,8 },
296 { "msp430f5217",2,8 },
297 { "msp430f5218",2,8 },
298 { "msp430f5219",2,8 },
299 { "msp430f5222",2,8 },
300 { "msp430f5223",2,8 },
301 { "msp430f5224",2,8 },
302 { "msp430f5227",2,8 },
303 { "msp430f5228",2,8 },
304 { "msp430f5229",2,8 },
305 { "msp430f5232",2,8 },
306 { "msp430f5234",2,8 },
307 { "msp430f5237",2,8 },
308 { "msp430f5239",2,8 },
309 { "msp430f5242",2,8 },
310 { "msp430f5244",2,8 },
311 { "msp430f5247",2,8 },
312 { "msp430f5249",2,8 },
313 { "msp430f5252",2,8 },
314 { "msp430f5253",2,8 },
315 { "msp430f5254",2,8 },
316 { "msp430f5255",2,8 },
317 { "msp430f5256",2,8 },
318 { "msp430f5257",2,8 },
319 { "msp430f5258",2,8 },
320 { "msp430f5259",2,8 },
321 { "msp430f5304",2,8 },
322 { "msp430f5308",2,8 },
323 { "msp430f5309",2,8 },
324 { "msp430f5310",2,8 },
325 { "msp430f5324",2,8 },
326 { "msp430f5325",2,8 },
327 { "msp430f5326",2,8 },
328 { "msp430f5327",2,8 },
329 { "msp430f5328",2,8 },
330 { "msp430f5329",2,8 },
331 { "msp430f5333",2,8 },
332 { "msp430f5335",2,8 },
333 { "msp430f5336",2,8 },
334 { "msp430f5338",2,8 },
335 { "msp430f5340",2,8 },
336 { "msp430f5341",2,8 },
337 { "msp430f5342",2,8 },
338 { "msp430f5358",2,8 },
339 { "msp430f5359",2,8 },
340 { "msp430f5418",2,8 },
341 { "msp430f5418a",2,8 },
342 { "msp430f5419",2,8 },
343 { "msp430f5419a",2,8 },
344 { "msp430f5435",2,8 },
345 { "msp430f5435a",2,8 },
346 { "msp430f5436",2,8 },
347 { "msp430f5436a",2,8 },
348 { "msp430f5437",2,8 },
349 { "msp430f5437a",2,8 },
350 { "msp430f5438",2,8 },
351 { "msp430f5438a",2,8 },
352 { "msp430f5500",2,8 },
353 { "msp430f5501",2,8 },
354 { "msp430f5502",2,8 },
355 { "msp430f5503",2,8 },
356 { "msp430f5504",2,8 },
357 { "msp430f5505",2,8 },
358 { "msp430f5506",2,8 },
359 { "msp430f5507",2,8 },
360 { "msp430f5508",2,8 },
361 { "msp430f5509",2,8 },
362 { "msp430f5510",2,8 },
363 { "msp430f5513",2,8 },
364 { "msp430f5514",2,8 },
365 { "msp430f5515",2,8 },
366 { "msp430f5517",2,8 },
367 { "msp430f5519",2,8 },
368 { "msp430f5521",2,8 },
369 { "msp430f5522",2,8 },
370 { "msp430f5524",2,8 },
371 { "msp430f5525",2,8 },
372 { "msp430f5526",2,8 },
373 { "msp430f5527",2,8 },
374 { "msp430f5528",2,8 },
375 { "msp430f5529",2,8 },
376 { "msp430f5630",2,8 },
377 { "msp430f5631",2,8 },
378 { "msp430f5632",2,8 },
379 { "msp430f5633",2,8 },
380 { "msp430f5634",2,8 },
381 { "msp430f5635",2,8 },
382 { "msp430f5636",2,8 },
383 { "msp430f5637",2,8 },
384 { "msp430f5638",2,8 },
385 { "msp430f5658",2,8 },
386 { "msp430f5659",2,8 },
387 { "msp430f5xx_6xxgeneric",2,8 },
388 { "msp430f6433",2,8 },
389 { "msp430f6435",2,8 },
390 { "msp430f6436",2,8 },
391 { "msp430f6438",2,8 },
392 { "msp430f6458",2,8 },
393 { "msp430f6459",2,8 },
394 { "msp430f6630",2,8 },
395 { "msp430f6631",2,8 },
396 { "msp430f6632",2,8 },
397 { "msp430f6633",2,8 },
398 { "msp430f6634",2,8 },
399 { "msp430f6635",2,8 },
400 { "msp430f6636",2,8 },
401 { "msp430f6637",2,8 },
402 { "msp430f6638",2,8 },
403 { "msp430f6658",2,8 },
404 { "msp430f6659",2,8 },
405 { "msp430f6720",2,8 },
406 { "msp430f6720a",2,8 },
407 { "msp430f6721",2,8 },
408 { "msp430f6721a",2,8 },
409 { "msp430f6723",2,8 },
410 { "msp430f6723a",2,8 },
411 { "msp430f6724",2,8 },
412 { "msp430f6724a",2,8 },
413 { "msp430f6725",2,8 },
414 { "msp430f6725a",2,8 },
415 { "msp430f6726",2,8 },
416 { "msp430f6726a",2,8 },
417 { "msp430f6730",2,8 },
418 { "msp430f6730a",2,8 },
419 { "msp430f6731",2,8 },
420 { "msp430f6731a",2,8 },
421 { "msp430f6733",2,8 },
422 { "msp430f6733a",2,8 },
423 { "msp430f6734",2,8 },
424 { "msp430f6734a",2,8 },
425 { "msp430f6735",2,8 },
426 { "msp430f6735a",2,8 },
427 { "msp430f6736",2,8 },
428 { "msp430f6736a",2,8 },
429 { "msp430f6745",2,8 },
430 { "msp430f67451",2,8 },
431 { "msp430f67451a",2,8 },
432 { "msp430f6745a",2,8 },
433 { "msp430f6746",2,8 },
434 { "msp430f67461",2,8 },
435 { "msp430f67461a",2,8 },
436 { "msp430f6746a",2,8 },
437 { "msp430f6747",2,8 },
438 { "msp430f67471",2,8 },
439 { "msp430f67471a",2,8 },
440 { "msp430f6747a",2,8 },
441 { "msp430f6748",2,8 },
442 { "msp430f67481",2,8 },
443 { "msp430f67481a",2,8 },
444 { "msp430f6748a",2,8 },
445 { "msp430f6749",2,8 },
446 { "msp430f67491",2,8 },
447 { "msp430f67491a",2,8 },
448 { "msp430f6749a",2,8 },
449 { "msp430f67621",2,8 },
450 { "msp430f67621a",2,8 },
451 { "msp430f67641",2,8 },
452 { "msp430f67641a",2,8 },
453 { "msp430f6765",2,8 },
454 { "msp430f67651",2,8 },
455 { "msp430f67651a",2,8 },
456 { "msp430f6765a",2,8 },
457 { "msp430f6766",2,8 },
458 { "msp430f67661",2,8 },
459 { "msp430f67661a",2,8 },
460 { "msp430f6766a",2,8 },
461 { "msp430f6767",2,8 },
462 { "msp430f67671",2,8 },
463 { "msp430f67671a",2,8 },
464 { "msp430f6767a",2,8 },
465 { "msp430f6768",2,8 },
466 { "msp430f67681",2,8 },
467 { "msp430f67681a",2,8 },
468 { "msp430f6768a",2,8 },
469 { "msp430f6769",2,8 },
470 { "msp430f67691",2,8 },
471 { "msp430f67691a",2,8 },
472 { "msp430f6769a",2,8 },
473 { "msp430f6775",2,8 },
474 { "msp430f67751",2,8 },
475 { "msp430f67751a",2,8 },
476 { "msp430f6775a",2,8 },
477 { "msp430f6776",2,8 },
478 { "msp430f67761",2,8 },
479 { "msp430f67761a",2,8 },
480 { "msp430f6776a",2,8 },
481 { "msp430f6777",2,8 },
482 { "msp430f67771",2,8 },
483 { "msp430f67771a",2,8 },
484 { "msp430f6777a",2,8 },
485 { "msp430f6778",2,8 },
486 { "msp430f67781",2,8 },
487 { "msp430f67781a",2,8 },
488 { "msp430f6778a",2,8 },
489 { "msp430f6779",2,8 },
490 { "msp430f67791",2,8 },
491 { "msp430f67791a",2,8 },
492 { "msp430f6779a",2,8 },
493 { "msp430fe423",0,0 },
494 { "msp430fe4232",0,0 },
495 { "msp430fe423a",0,0 },
496 { "msp430fe4242",0,0 },
497 { "msp430fe425",0,0 },
498 { "msp430fe4252",0,0 },
499 { "msp430fe425a",0,0 },
500 { "msp430fe427",0,0 },
501 { "msp430fe4272",0,0 },
502 { "msp430fe427a",0,0 },
503 { "msp430fg4250",0,0 },
504 { "msp430fg4260",0,0 },
505 { "msp430fg4270",0,0 },
506 { "msp430fg437",0,0 },
507 { "msp430fg438",0,0 },
508 { "msp430fg439",0,0 },
509 { "msp430fg4616",1,1 },
510 { "msp430fg4617",1,1 },
511 { "msp430fg4618",1,1 },
512 { "msp430fg4619",1,1 },
513 { "msp430fg477",0,0 },
514 { "msp430fg478",0,0 },
515 { "msp430fg479",0,0 },
516 { "msp430fg6425",2,8 },
517 { "msp430fg6426",2,8 },
518 { "msp430fg6625",2,8 },
519 { "msp430fg6626",2,8 },
520 { "msp430fr2032",2,0 },
521 { "msp430fr2033",2,0 },
522 { "msp430fr2433",2,8 },
523 { "msp430fr2xx_4xxgeneric",2,8 },
524 { "msp430fr4131",2,0 },
525 { "msp430fr4132",2,0 },
526 { "msp430fr4133",2,0 },
527 { "msp430fr5720",2,8 },
528 { "msp430fr5721",2,8 },
529 { "msp430fr5722",2,8 },
530 { "msp430fr5723",2,8 },
531 { "msp430fr5724",2,8 },
532 { "msp430fr5725",2,8 },
533 { "msp430fr5726",2,8 },
534 { "msp430fr5727",2,8 },
535 { "msp430fr5728",2,8 },
536 { "msp430fr5729",2,8 },
537 { "msp430fr5730",2,8 },
538 { "msp430fr5731",2,8 },
539 { "msp430fr5732",2,8 },
540 { "msp430fr5733",2,8 },
541 { "msp430fr5734",2,8 },
542 { "msp430fr5735",2,8 },
543 { "msp430fr5736",2,8 },
544 { "msp430fr5737",2,8 },
545 { "msp430fr5738",2,8 },
546 { "msp430fr5739",2,8 },
547 { "msp430fr57xxgeneric",2,8 },
548 { "msp430fr5847",2,8 },
549 { "msp430fr58471",2,8 },
550 { "msp430fr5848",2,8 },
551 { "msp430fr5849",2,8 },
552 { "msp430fr5857",2,8 },
553 { "msp430fr5858",2,8 },
554 { "msp430fr5859",2,8 },
555 { "msp430fr5867",2,8 },
556 { "msp430fr58671",2,8 },
557 { "msp430fr5868",2,8 },
558 { "msp430fr5869",2,8 },
559 { "msp430fr5870",2,8 },
560 { "msp430fr5872",2,8 },
561 { "msp430fr58721",2,8 },
562 { "msp430fr5887",2,8 },
563 { "msp430fr5888",2,8 },
564 { "msp430fr5889",2,8 },
565 { "msp430fr58891",2,8 },
566 { "msp430fr5922",2,8 },
567 { "msp430fr59221",2,8 },
568 { "msp430fr5947",2,8 },
569 { "msp430fr59471",2,8 },
570 { "msp430fr5948",2,8 },
571 { "msp430fr5949",2,8 },
572 { "msp430fr5957",2,8 },
573 { "msp430fr5958",2,8 },
574 { "msp430fr5959",2,8 },
575 { "msp430fr5967",2,8 },
576 { "msp430fr5968",2,8 },
577 { "msp430fr5969",2,8 },
578 { "msp430fr59691",2,8 },
579 { "msp430fr5970",2,8 },
580 { "msp430fr5972",2,8 },
581 { "msp430fr59721",2,8 },
582 { "msp430fr5986",2,8 },
583 { "msp430fr5987",2,8 },
584 { "msp430fr5988",2,8 },
585 { "msp430fr5989",2,8 },
586 { "msp430fr59891",2,8 },
587 { "msp430fr5xx_6xxgeneric",2,8 },
588 { "msp430fr6820",2,8 },
589 { "msp430fr6822",2,8 },
590 { "msp430fr68221",2,8 },
591 { "msp430fr6870",2,8 },
592 { "msp430fr6872",2,8 },
593 { "msp430fr68721",2,8 },
594 { "msp430fr6877",2,8 },
595 { "msp430fr6879",2,8 },
596 { "msp430fr68791",2,8 },
597 { "msp430fr6887",2,8 },
598 { "msp430fr6888",2,8 },
599 { "msp430fr6889",2,8 },
600 { "msp430fr68891",2,8 },
601 { "msp430fr6920",2,8 },
602 { "msp430fr6922",2,8 },
603 { "msp430fr69221",2,8 },
604 { "msp430fr6927",2,8 },
605 { "msp430fr69271",2,8 },
606 { "msp430fr6928",2,8 },
607 { "msp430fr6970",2,8 },
608 { "msp430fr6972",2,8 },
609 { "msp430fr69721",2,8 },
610 { "msp430fr6977",2,8 },
611 { "msp430fr6979",2,8 },
612 { "msp430fr69791",2,8 },
613 { "msp430fr6987",2,8 },
614 { "msp430fr6988",2,8 },
615 { "msp430fr6989",2,8 },
616 { "msp430fr69891",2,8 },
617 { "msp430fw423",0,0 },
618 { "msp430fw425",0,0 },
619 { "msp430fw427",0,0 },
620 { "msp430fw428",0,0 },
621 { "msp430fw429",0,0 },
622 { "msp430g2001",0,0 },
623 { "msp430g2101",0,0 },
624 { "msp430g2102",0,0 },
625 { "msp430g2111",0,0 },
626 { "msp430g2112",0,0 },
627 { "msp430g2113",0,0 },
628 { "msp430g2121",0,0 },
629 { "msp430g2131",0,0 },
630 { "msp430g2132",0,0 },
631 { "msp430g2152",0,0 },
632 { "msp430g2153",0,0 },
633 { "msp430g2201",0,0 },
634 { "msp430g2202",0,0 },
635 { "msp430g2203",0,0 },
636 { "msp430g2210",0,0 },
637 { "msp430g2211",0,0 },
638 { "msp430g2212",0,0 },
639 { "msp430g2213",0,0 },
640 { "msp430g2221",0,0 },
641 { "msp430g2230",0,0 },
642 { "msp430g2231",0,0 },
643 { "msp430g2232",0,0 },
644 { "msp430g2233",0,0 },
645 { "msp430g2252",0,0 },
646 { "msp430g2253",0,0 },
647 { "msp430g2302",0,0 },
648 { "msp430g2303",0,0 },
649 { "msp430g2312",0,0 },
650 { "msp430g2313",0,0 },
651 { "msp430g2332",0,0 },
652 { "msp430g2333",0,0 },
653 { "msp430g2352",0,0 },
654 { "msp430g2353",0,0 },
655 { "msp430g2402",0,0 },
656 { "msp430g2403",0,0 },
657 { "msp430g2412",0,0 },
658 { "msp430g2413",0,0 },
659 { "msp430g2432",0,0 },
660 { "msp430g2433",0,0 },
661 { "msp430g2444",0,0 },
662 { "msp430g2452",0,0 },
663 { "msp430g2453",0,0 },
664 { "msp430g2513",0,0 },
665 { "msp430g2533",0,0 },
666 { "msp430g2544",0,0 },
667 { "msp430g2553",0,0 },
668 { "msp430g2744",0,0 },
669 { "msp430g2755",0,0 },
670 { "msp430g2855",0,0 },
671 { "msp430g2955",0,0 },
672 { "msp430i2020",0,2 },
673 { "msp430i2021",0,2 },
674 { "msp430i2030",0,2 },
675 { "msp430i2031",0,2 },
676 { "msp430i2040",0,2 },
677 { "msp430i2041",0,2 },
678 { "msp430i2xxgeneric",0,2 },
679 { "msp430l092",0,0 },
680 { "msp430p112",0,0 },
681 { "msp430p313",0,0 },
682 { "msp430p315",0,0 },
683 { "msp430p315s",0,0 },
684 { "msp430p325",0,0 },
685 { "msp430p337",0,1 },
686 { "msp430sl5438a",2,8 },
687 { "msp430tch5e",0,0 },
688 { "msp430xgeneric",2,8 },
689 { "rf430f5144",2,8 },
690 { "rf430f5155",2,8 },
691 { "rf430f5175",2,8 },
692 { "rf430frl152h",0,0 },
693 { "rf430frl152h_rom",0,0 },
694 { "rf430frl153h",0,0 },
695 { "rf430frl153h_rom",0,0 },
696 { "rf430frl154h",0,0 },
697 { "rf430frl154h_rom",0,0 }
700 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
701 If a specific MCU has not been selected then return a generic symbol instead. */
704 msp430_mcu_name (void)
709 static char mcu_name
[64];
711 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
712 for (i
= strlen (mcu_name
); i
--;)
713 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
717 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
721 msp430_option_override (void)
723 init_machine_status
= msp430_init_machine_status
;
727 if (strcasecmp (target_cpu
, "msp430x") == 0)
729 else /* target_cpu == "msp430" - already handled by the front end. */
732 /* Note - the front end has already ensured at most
733 one of target_cpu and target_mcu will be set. */
738 /* If we are given an MCU name, we assume that it supports 430X.
739 Then we check to see if it is one of the known MCUs that only
743 /* FIXME: This array is alpha sorted, so we could use a binary search. */
744 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
745 if (strcasecmp (msp430_mcu_data
[i
].name
, target_mcu
) == 0)
747 msp430x
= msp430_mcu_data
[i
].revision
>= 1;
752 warning (0, "Unrecognised MCU name '%s', assuming that it is just a MSP430 with no hardware multiply",
758 if (TARGET_LARGE
&& !msp430x
)
759 error ("-mlarge requires a 430X-compatible -mmcu=");
761 if (msp430_code_region
== UPPER
&& ! msp430x
)
762 error ("-mcode-region=upper requires 430X-compatible cpu");
763 if (msp430_data_region
== UPPER
&& ! msp430x
)
764 error ("-mdata-region=upper requires 430X-compatible cpu");
766 if (flag_exceptions
|| flag_non_call_exceptions
767 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
768 flag_omit_frame_pointer
= false;
770 flag_omit_frame_pointer
= true;
772 /* This is a hack to work around a problem with the newlib build
773 mechanism. Newlib always appends CFLAGS to the end of the GCC
774 command line and always sets -O2 in CFLAGS. Thus it is not
775 possible to build newlib with -Os enabled. Until now... */
776 if (TARGET_OPT_SPACE
&& optimize
< 3)
780 #undef TARGET_SCALAR_MODE_SUPPORTED_P
781 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
784 msp430_scalar_mode_supported_p (machine_mode m
)
786 if (m
== PSImode
&& msp430x
)
792 return default_scalar_mode_supported_p (m
);
799 #undef TARGET_MS_BITFIELD_LAYOUT_P
800 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
803 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
812 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
813 PSImode value, but not an SImode value. */
815 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
818 if (mode
== PSImode
&& msp430x
)
820 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
824 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
826 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
829 if (mode
== PSImode
&& msp430x
)
831 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
835 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
837 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
842 return msp430_hard_regno_nregs (regno
, mode
);
845 /* Implements HARD_REGNO_MODE_OK. */
847 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
850 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
853 /* Implements MODES_TIEABLE_P. */
855 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
857 if ((mode1
== PSImode
|| mode2
== SImode
)
858 || (mode1
== SImode
|| mode2
== PSImode
))
861 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
862 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
863 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
864 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
867 #undef TARGET_FRAME_POINTER_REQUIRED
868 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
871 msp430_frame_pointer_required (void)
876 #undef TARGET_CAN_ELIMINATE
877 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
880 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
881 const int to_reg ATTRIBUTE_UNUSED
)
886 /* Implements INITIAL_ELIMINATION_OFFSET. */
888 msp430_initial_elimination_offset (int from
, int to
)
890 int rv
= 0; /* As if arg to arg. */
892 msp430_compute_frame_info ();
896 case STACK_POINTER_REGNUM
:
897 rv
+= cfun
->machine
->framesize_outgoing
;
898 rv
+= cfun
->machine
->framesize_locals
;
900 case FRAME_POINTER_REGNUM
:
901 rv
+= cfun
->machine
->framesize_regs
;
902 /* Allow for the saved return address. */
903 rv
+= (TARGET_LARGE
? 4 : 2);
904 /* NB/ No need to allow for crtl->args.pretend_args_size.
905 GCC does that for us. */
913 case FRAME_POINTER_REGNUM
:
914 /* Allow for the fall through above. */
915 rv
-= (TARGET_LARGE
? 4 : 2);
916 rv
-= cfun
->machine
->framesize_regs
;
917 case ARG_POINTER_REGNUM
:
926 /* Named Address Space support */
929 /* Return the appropriate mode for a named address pointer. */
930 #undef TARGET_ADDR_SPACE_POINTER_MODE
931 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
932 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
933 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
936 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
941 case ADDR_SPACE_GENERIC
:
943 case ADDR_SPACE_NEAR
:
950 /* Function pointers are stored in unwind_word sized
951 variables, so make sure that unwind_word is big enough. */
952 #undef TARGET_UNWIND_WORD_MODE
953 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
956 msp430_unwind_word_mode (void)
958 return TARGET_LARGE
? PSImode
: HImode
;
961 /* Determine if one named address space is a subset of another. */
962 #undef TARGET_ADDR_SPACE_SUBSET_P
963 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
965 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
967 if (subset
== superset
)
970 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
973 #undef TARGET_ADDR_SPACE_CONVERT
974 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
975 /* Convert from one address space to another. */
977 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
979 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
980 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
983 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
985 /* This is unpredictable, as we're truncating off usable address
989 return gen_rtx_CONST (HImode
, op
);
991 result
= gen_reg_rtx (HImode
);
992 emit_insn (gen_truncpsihi2 (result
, op
));
995 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
997 /* This always works. */
1000 return gen_rtx_CONST (PSImode
, op
);
1002 result
= gen_reg_rtx (PSImode
);
1003 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1010 /* Stack Layout and Calling Conventions. */
1012 /* For each function, we list the gcc version and the TI version on
1013 each line, where we're converting the function names. */
1014 static char const * const special_convention_function_names
[] =
1016 "__muldi3", "__mspabi_mpyll",
1017 "__udivdi3", "__mspabi_divull",
1018 "__umoddi3", "__mspabi_remull",
1019 "__divdi3", "__mspabi_divlli",
1020 "__moddi3", "__mspabi_remlli",
1024 "__adddf3", "__mspabi_addd",
1025 "__subdf3", "__mspabi_subd",
1026 "__muldf3", "__mspabi_mpyd",
1027 "__divdf3", "__mspabi_divd",
1032 /* TRUE if the function passed is a "speical" function. Special
1033 functions pass two DImode parameters in registers. */
1035 msp430_special_register_convention_p (const char *name
)
1039 for (i
= 0; special_convention_function_names
[i
]; i
++)
1040 if (! strcmp (name
, special_convention_function_names
[i
]))
1046 #undef TARGET_FUNCTION_VALUE_REGNO_P
1047 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1050 msp430_function_value_regno_p (unsigned int regno
)
1056 #undef TARGET_FUNCTION_VALUE
1057 #define TARGET_FUNCTION_VALUE msp430_function_value
1060 msp430_function_value (const_tree ret_type
,
1061 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1062 bool outgoing ATTRIBUTE_UNUSED
)
1064 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1067 #undef TARGET_LIBCALL_VALUE
1068 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1071 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1073 return gen_rtx_REG (mode
, 12);
1076 /* Implements INIT_CUMULATIVE_ARGS. */
1078 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1079 tree fntype ATTRIBUTE_UNUSED
,
1080 rtx libname ATTRIBUTE_UNUSED
,
1081 tree fndecl ATTRIBUTE_UNUSED
,
1082 int n_named_args ATTRIBUTE_UNUSED
)
1085 memset (ca
, 0, sizeof(*ca
));
1090 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1092 fname
= XSTR (libname
, 0);
1096 if (fname
&& msp430_special_register_convention_p (fname
))
1100 /* Helper function for argument passing; this function is the common
1101 code that determines where an argument will be passed. */
1103 msp430_evaluate_arg (cumulative_args_t cap
,
1105 const_tree type ATTRIBUTE_UNUSED
,
1108 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1109 int nregs
= GET_MODE_SIZE (mode
);
1118 if (mode
== PSImode
)
1121 nregs
= (nregs
+ 1) / 2;
1125 /* Function is passed two DImode operands, in R8:R11 and
1135 for (i
= 0; i
< 4; i
++)
1136 if (! ca
->reg_used
[i
])
1139 ca
->start_reg
= CA_FIRST_REG
+ i
;
1144 for (i
= 0; i
< 3; i
++)
1145 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1148 ca
->start_reg
= CA_FIRST_REG
+ i
;
1151 if (! ca
->reg_used
[3] && ca
->can_split
)
1155 ca
->start_reg
= CA_FIRST_REG
+ 3;
1162 if (! ca
->reg_used
[0]
1163 && ! ca
->reg_used
[1]
1164 && ! ca
->reg_used
[2]
1165 && ! ca
->reg_used
[3])
1168 ca
->start_reg
= CA_FIRST_REG
;
1175 #undef TARGET_PROMOTE_PROTOTYPES
1176 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1179 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1184 #undef TARGET_FUNCTION_ARG
1185 #define TARGET_FUNCTION_ARG msp430_function_arg
1188 msp430_function_arg (cumulative_args_t cap
,
1193 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1195 msp430_evaluate_arg (cap
, mode
, type
, named
);
1198 return gen_rtx_REG (mode
, ca
->start_reg
);
1203 #undef TARGET_ARG_PARTIAL_BYTES
1204 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1207 msp430_arg_partial_bytes (cumulative_args_t cap
,
1212 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1214 msp430_evaluate_arg (cap
, mode
, type
, named
);
1216 if (ca
->reg_count
&& ca
->mem_count
)
1217 return ca
->reg_count
* UNITS_PER_WORD
;
1222 #undef TARGET_PASS_BY_REFERENCE
1223 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1226 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1229 bool named ATTRIBUTE_UNUSED
)
1231 return (mode
== BLKmode
1232 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1233 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1236 #undef TARGET_CALLEE_COPIES
1237 #define TARGET_CALLEE_COPIES msp430_callee_copies
1240 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1241 machine_mode mode ATTRIBUTE_UNUSED
,
1242 const_tree type ATTRIBUTE_UNUSED
,
1243 bool named ATTRIBUTE_UNUSED
)
1248 #undef TARGET_FUNCTION_ARG_ADVANCE
1249 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1252 msp430_function_arg_advance (cumulative_args_t cap
,
1257 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1260 msp430_evaluate_arg (cap
, mode
, type
, named
);
1262 if (ca
->start_reg
>= CA_FIRST_REG
)
1263 for (i
= 0; i
< ca
->reg_count
; i
++)
1264 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1269 #undef TARGET_FUNCTION_ARG_BOUNDARY
1270 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1273 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1276 && int_size_in_bytes (type
) > 1)
1278 if (GET_MODE_BITSIZE (mode
) > 8)
1283 #undef TARGET_RETURN_IN_MEMORY
1284 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1287 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1289 machine_mode mode
= TYPE_MODE (ret_type
);
1292 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1293 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1296 if (GET_MODE_SIZE (mode
) > 8)
1302 #undef TARGET_GET_RAW_ARG_MODE
1303 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1306 msp430_get_raw_arg_mode (int regno
)
1308 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
1311 #undef TARGET_GET_RAW_RESULT_MODE
1312 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1315 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1320 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1321 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1323 #include "gimplify.h"
1326 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1329 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1330 unsigned HOST_WIDE_INT align
, boundary
;
1333 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1335 type
= build_pointer_type (type
);
1337 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1338 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1340 /* When we align parameter on stack for caller, if the parameter
1341 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1342 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1343 here with caller. */
1344 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1345 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1347 boundary
/= BITS_PER_UNIT
;
1349 /* Hoist the valist value into a temporary for the moment. */
1350 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1352 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1353 requires greater alignment, we must perform dynamic alignment. */
1354 if (boundary
> align
1355 && !integer_zerop (TYPE_SIZE (type
)))
1357 /* FIXME: This is where this function diverts from targhooks.c:
1358 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1359 if (! POINTER_TYPE_P (type
))
1361 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1362 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1363 gimplify_and_add (t
, pre_p
);
1365 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1366 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1368 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1369 gimplify_and_add (t
, pre_p
);
1375 /* If the actual alignment is less than the alignment of the type,
1376 adjust the type accordingly so that we don't assume strict alignment
1377 when dereferencing the pointer. */
1378 boundary
*= BITS_PER_UNIT
;
1379 if (boundary
< TYPE_ALIGN (type
))
1381 type
= build_variant_type_copy (type
);
1382 TYPE_ALIGN (type
) = boundary
;
1385 /* Compute the rounded size of the type. */
1386 type_size
= size_in_bytes (type
);
1387 rounded_size
= round_up (type_size
, align
);
1389 /* Reduce rounded_size so it's sharable with the postqueue. */
1390 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1395 /* Compute new value for AP. */
1396 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1397 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1398 gimplify_and_add (t
, pre_p
);
1400 addr
= fold_convert (build_pointer_type (type
), addr
);
1403 addr
= build_va_arg_indirect_ref (addr
);
1405 addr
= build_va_arg_indirect_ref (addr
);
1410 /* Addressing Modes */
1412 #undef TARGET_LEGITIMATE_ADDRESS_P
1413 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1416 reg_ok_for_addr (rtx r
, bool strict
)
1420 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1421 rn
= reg_renumber
[rn
];
1422 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1430 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1431 rtx x ATTRIBUTE_UNUSED
,
1432 bool strict ATTRIBUTE_UNUSED
)
1434 switch (GET_CODE (x
))
1440 if (REG_P (XEXP (x
, 0)))
1442 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1444 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1446 switch (GET_CODE (XEXP (x
, 1)))
1459 if (!reg_ok_for_addr (x
, strict
))
1472 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1473 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1476 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1479 addr_space_t as ATTRIBUTE_UNUSED
)
1481 return msp430_legitimate_address_p (mode
, x
, strict
);
1484 #undef TARGET_ASM_INTEGER
1485 #define TARGET_ASM_INTEGER msp430_asm_integer
1487 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1489 int c
= GET_CODE (x
);
1491 if (size
== 3 && GET_MODE (x
) == PSImode
)
1497 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1498 || c
== PLUS
|| c
== MINUS
)
1500 fprintf (asm_out_file
, "\t.long\t");
1501 output_addr_const (asm_out_file
, x
);
1502 fputc ('\n', asm_out_file
);
1507 return default_assemble_integer (x
, size
, aligned_p
);
1510 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1511 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1513 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1519 #undef TARGET_LEGITIMATE_CONSTANT_P
1520 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1523 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1525 return ! CONST_INT_P (x
)
1527 /* GCC does not know the width of the PSImode, so make
1528 sure that it does not try to use a constant value that
1530 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1534 #undef TARGET_RTX_COSTS
1535 #define TARGET_RTX_COSTS msp430_rtx_costs
1537 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1539 int outer_code ATTRIBUTE_UNUSED
,
1540 int opno ATTRIBUTE_UNUSED
,
1542 bool speed ATTRIBUTE_UNUSED
)
1544 int code
= GET_CODE (x
);
1549 if (mode
== SImode
&& outer_code
== SET
)
1551 *total
= COSTS_N_INSNS (4);
1560 *total
= COSTS_N_INSNS (100);
1568 /* Function Entry and Exit */
1570 /* The MSP430 call frame looks like this:
1573 +--------------------+
1577 +--------------------+ <-- "arg pointer"
1579 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1581 +--------------------+
1582 | SR if this func has|
1583 | been called via an |
1585 +--------------------+ <-- SP before prologue, also AP
1587 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1589 +--------------------+ <-- "frame pointer"
1593 +--------------------+
1597 +--------------------+ <-- SP during function
1602 /* We use this to wrap all emitted insns in the prologue, so they get
1603 the "frame-related" (/f) flag set. */
1607 RTX_FRAME_RELATED_P (x
) = 1;
1611 /* This is the one spot that decides if a register is to be saved and
1612 restored in the prologue/epilogue. */
1614 msp430_preserve_reg_p (int regno
)
1616 /* PC, SP, SR, and the constant generator. */
1620 /* FIXME: add interrupt, EH, etc. */
1621 if (crtl
->calls_eh_return
)
1624 /* Shouldn't be more than the above, but just in case... */
1625 if (fixed_regs
[regno
])
1628 /* Interrupt handlers save all registers they use, even
1629 ones which are call saved. If they call other functions
1630 then *every* register is saved. */
1631 if (msp430_is_interrupt_func ())
1632 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1634 if (!call_used_regs
[regno
]
1635 && df_regs_ever_live_p (regno
))
1641 /* Compute all the frame-related fields in our machine_function
1644 msp430_compute_frame_info (void)
1648 cfun
->machine
->computed
= 1;
1649 cfun
->machine
->framesize_regs
= 0;
1650 cfun
->machine
->framesize_locals
= get_frame_size ();
1651 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1653 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1654 if (msp430_preserve_reg_p (i
))
1656 cfun
->machine
->need_to_save
[i
] = 1;
1657 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1660 cfun
->machine
->need_to_save
[i
] = 0;
1662 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1663 cfun
->machine
->framesize_locals
++;
1665 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1666 + cfun
->machine
->framesize_locals
1667 + cfun
->machine
->framesize_outgoing
);
1670 /* Attribute Handling. */
1672 const char * const ATTR_INTR
= "interrupt";
1673 const char * const ATTR_WAKEUP
= "wakeup";
1674 const char * const ATTR_NAKED
= "naked";
1675 const char * const ATTR_REENT
= "reentrant";
1676 const char * const ATTR_CRIT
= "critical";
1677 const char * const ATTR_LOWER
= "lower";
1678 const char * const ATTR_UPPER
= "upper";
1679 const char * const ATTR_EITHER
= "either";
1680 const char * const ATTR_NOINIT
= "noinit";
1681 const char * const ATTR_PERSIST
= "persistent";
1684 has_attr (const char * attr
, tree decl
)
1686 if (decl
== NULL_TREE
)
1688 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1692 is_interrupt_func (tree decl
= current_function_decl
)
1694 return has_attr (ATTR_INTR
, decl
);
1697 /* Returns true if the current function has the "interrupt" attribute. */
1700 msp430_is_interrupt_func (void)
1702 return is_interrupt_func (current_function_decl
);
1706 is_wakeup_func (tree decl
= current_function_decl
)
1708 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1712 is_naked_func (tree decl
= current_function_decl
)
1714 return has_attr (ATTR_NAKED
, decl
);
1718 is_reentrant_func (tree decl
= current_function_decl
)
1720 return has_attr (ATTR_REENT
, decl
);
1724 is_critical_func (tree decl
= current_function_decl
)
1726 return has_attr (ATTR_CRIT
, decl
);
1729 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1730 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1733 msp430_allocate_stack_slots_for_args (void)
1735 /* Naked functions should not allocate stack slots for arguments. */
1736 return ! is_naked_func ();
1739 /* Verify MSP430 specific attributes. */
1740 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1743 msp430_attr (tree
* node
,
1746 int flags ATTRIBUTE_UNUSED
,
1747 bool * no_add_attrs
)
1749 gcc_assert (DECL_P (* node
));
1753 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1755 tree value
= TREE_VALUE (args
);
1757 switch (TREE_CODE (value
))
1760 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1761 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1762 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1763 /* Allow the attribute to be added - the linker script
1764 being used may still recognise this name. */
1765 warning (OPT_Wattributes
,
1766 "unrecognised interrupt vector argument of %qE attribute",
1771 if (wi::gtu_p (value
, 63))
1772 /* Allow the attribute to be added - the linker script
1773 being used may still recognise this value. */
1774 warning (OPT_Wattributes
,
1775 "numeric argument of %qE attribute must be in range 0..63",
1780 warning (OPT_Wattributes
,
1781 "argument of %qE attribute is not a string constant or number",
1783 *no_add_attrs
= true;
1788 const char * message
= NULL
;
1790 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1792 message
= "%qE attribute only applies to functions";
1794 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1796 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1797 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1798 message
= "interrupt handlers must be void";
1800 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1802 if (is_naked_func (* node
))
1803 message
= "naked functions cannot be reentrant";
1804 else if (is_critical_func (* node
))
1805 message
= "critical functions cannot be reentrant";
1807 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1809 if (is_naked_func (* node
))
1810 message
= "naked functions cannot be critical";
1811 else if (is_reentrant_func (* node
))
1812 message
= "reentrant functions cannot be critical";
1814 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1816 if (is_critical_func (* node
))
1817 message
= "critical functions cannot be naked";
1818 else if (is_reentrant_func (* node
))
1819 message
= "reentrant functions cannot be naked";
1824 warning (OPT_Wattributes
, message
, name
);
1825 * no_add_attrs
= true;
1832 msp430_section_attr (tree
* node
,
1835 int flags ATTRIBUTE_UNUSED
,
1836 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1838 gcc_assert (DECL_P (* node
));
1839 gcc_assert (args
== NULL
);
1841 const char * message
= NULL
;
1843 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1845 if (has_attr (ATTR_LOWER
, * node
))
1846 message
= "already marked with 'lower' attribute";
1847 else if (has_attr (ATTR_EITHER
, * node
))
1848 message
= "already marked with 'either' attribute";
1850 message
= "upper attribute needs a 430X cpu";
1852 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1854 if (has_attr (ATTR_UPPER
, * node
))
1855 message
= "already marked with 'upper' attribute";
1856 else if (has_attr (ATTR_EITHER
, * node
))
1857 message
= "already marked with 'either' attribute";
1861 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1863 if (has_attr (ATTR_LOWER
, * node
))
1864 message
= "already marked with 'lower' attribute";
1865 else if (has_attr (ATTR_UPPER
, * node
))
1866 message
= "already marked with 'upper' attribute";
1871 warning (OPT_Wattributes
, message
, name
);
1872 * no_add_attrs
= true;
1879 msp430_data_attr (tree
* node
,
1882 int flags ATTRIBUTE_UNUSED
,
1883 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1885 const char * message
= NULL
;
1887 gcc_assert (DECL_P (* node
));
1888 gcc_assert (args
== NULL
);
1890 if (TREE_CODE (* node
) != VAR_DECL
)
1891 message
= "%qE attribute only applies to variables";
1893 if (DECL_SECTION_NAME (* node
))
1894 message
= "%qE attribute cannot be applied to variables with specific sections";
1896 /* If this var is thought to be common, then change this. Common variables
1897 are assigned to sections before the backend has a chance to process them. */
1898 if (DECL_COMMON (* node
))
1899 DECL_COMMON (* node
) = 0;
1903 warning (OPT_Wattributes
, message
, name
);
1904 * no_add_attrs
= true;
1911 #undef TARGET_ATTRIBUTE_TABLE
1912 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1914 /* Table of MSP430-specific attributes. */
1915 const struct attribute_spec msp430_attribute_table
[] =
1917 /* Name min_num_args type_req, affects_type_identity
1918 max_num_args, fn_type_req
1919 decl_req handler. */
1920 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
1921 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
1922 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
1923 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
1924 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
1926 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
1927 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
1928 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
1930 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false },
1931 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false },
1933 { NULL
, 0, 0, false, false, false, NULL
, false }
1936 #undef TARGET_ASM_FUNCTION_PROLOGUE
1937 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
1940 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
1944 fprintf (outfile
, "; start of function\n");
1946 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
1948 fprintf (outfile
, "; attributes: ");
1949 if (is_naked_func ())
1950 fprintf (outfile
, "naked ");
1951 if (msp430_is_interrupt_func ())
1952 fprintf (outfile
, "interrupt ");
1953 if (is_reentrant_func ())
1954 fprintf (outfile
, "reentrant ");
1955 if (is_critical_func ())
1956 fprintf (outfile
, "critical ");
1957 if (is_wakeup_func ())
1958 fprintf (outfile
, "wakeup ");
1959 fprintf (outfile
, "\n");
1962 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
1963 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
1964 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
1965 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
1966 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
1967 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
1970 fprintf (outfile
, "; saved regs:");
1971 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
1972 if (cfun
->machine
->need_to_save
[r
])
1974 fprintf (outfile
, " %s", reg_names
[r
]);
1978 fprintf (outfile
, "(none)");
1979 fprintf (outfile
, "\n");
1982 /* Common code to change the stack pointer. */
1984 increment_stack (HOST_WIDE_INT amount
)
1987 rtx sp
= stack_pointer_rtx
;
1994 inc
= GEN_INT (- amount
);
1996 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
1998 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2002 inc
= GEN_INT (amount
);
2004 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2006 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2011 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2015 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2016 if (int_attr
!= NULL_TREE
)
2018 tree intr_vector
= TREE_VALUE (int_attr
);
2020 if (intr_vector
!= NULL_TREE
)
2024 intr_vector
= TREE_VALUE (intr_vector
);
2026 /* The interrupt attribute has a vector value. Turn this into a
2027 section name, switch to that section and put the address of
2028 the current function into that vector slot. Note msp430_attr()
2029 has already verified the vector name for us. */
2030 if (TREE_CODE (intr_vector
) == STRING_CST
)
2031 sprintf (buf
, "__interrupt_vector_%.80s",
2032 TREE_STRING_POINTER (intr_vector
));
2033 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2034 sprintf (buf
, "__interrupt_vector_%u",
2035 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2037 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2038 fputs ("\t.word\t", file
);
2039 assemble_name (file
, name
);
2045 switch_to_section (function_section (decl
));
2046 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2049 static const char * const lower_prefix
= ".lower";
2050 static const char * const upper_prefix
= ".upper";
2051 static const char * const either_prefix
= ".either";
2053 /* Generate a prefix for a section name, based upon
2054 the region into which the object should be placed. */
2057 gen_prefix (tree decl
)
2059 if (DECL_ONE_ONLY (decl
))
2062 /* If the user has specified a particular section then do not use any prefix. */
2063 if (has_attr ("section", decl
))
2066 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2067 if (has_attr (ATTR_LOWER
, decl
))
2068 return lower_prefix
;
2070 /* If we are compiling for the MSP430 then we do not support the upper region. */
2074 if (has_attr (ATTR_UPPER
, decl
))
2075 return upper_prefix
;
2077 if (has_attr (ATTR_EITHER
, decl
))
2078 return either_prefix
;
2080 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2082 if (msp430_code_region
== LOWER
)
2083 return lower_prefix
;
2085 if (msp430_code_region
== UPPER
)
2086 return upper_prefix
;
2088 if (msp430_code_region
== EITHER
)
2089 return either_prefix
;
2093 if (msp430_data_region
== LOWER
)
2094 return lower_prefix
;
2096 if (msp430_data_region
== UPPER
)
2097 return upper_prefix
;
2099 if (msp430_data_region
== EITHER
)
2100 return either_prefix
;
2106 static section
* noinit_section
;
2107 static section
* persist_section
;
2109 #undef TARGET_ASM_INIT_SECTIONS
2110 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2113 msp430_init_sections (void)
2115 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2116 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2119 #undef TARGET_ASM_SELECT_SECTION
2120 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2123 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2125 gcc_assert (decl
!= NULL_TREE
);
2127 if (TREE_CODE (decl
) == STRING_CST
2128 || TREE_CODE (decl
) == CONSTRUCTOR
2129 || TREE_CODE (decl
) == INTEGER_CST
2130 || TREE_CODE (decl
) == VECTOR_CST
2131 || TREE_CODE (decl
) == COMPLEX_CST
)
2132 return default_select_section (decl
, reloc
, align
);
2134 /* In large mode we must make sure that interrupt handlers are put into
2135 low memory as the vector table only accepts 16-bit addresses. */
2136 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2137 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2139 const char * prefix
= gen_prefix (decl
);
2142 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2143 return text_section
;
2144 else if (has_attr (ATTR_NOINIT
, decl
))
2145 return noinit_section
;
2146 else if (has_attr (ATTR_PERSIST
, decl
))
2147 return persist_section
;
2149 return default_select_section (decl
, reloc
, align
);
2153 switch (categorize_decl_for_section (decl
, reloc
))
2155 case SECCAT_TEXT
: sec
= ".text"; break;
2156 case SECCAT_DATA
: sec
= ".data"; break;
2157 case SECCAT_BSS
: sec
= ".bss"; break;
2158 case SECCAT_RODATA
: sec
= ".rodata"; break;
2160 case SECCAT_RODATA_MERGE_STR
:
2161 case SECCAT_RODATA_MERGE_STR_INIT
:
2162 case SECCAT_RODATA_MERGE_CONST
:
2163 case SECCAT_SRODATA
:
2164 case SECCAT_DATA_REL
:
2165 case SECCAT_DATA_REL_LOCAL
:
2166 case SECCAT_DATA_REL_RO
:
2167 case SECCAT_DATA_REL_RO_LOCAL
:
2172 return default_select_section (decl
, reloc
, align
);
2178 const char * dec_name
= DECL_SECTION_NAME (decl
);
2179 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2181 return get_named_section (decl
, name
, 0);
2184 #undef TARGET_ASM_FUNCTION_SECTION
2185 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2188 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2192 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2193 name
= DECL_SECTION_NAME (decl
);
2195 const char * prefix
= gen_prefix (decl
);
2197 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2198 return default_function_section (decl
, freq
, startup
, exit
);
2200 name
= ACONCAT ((prefix
, name
, NULL
));
2201 return get_named_section (decl
, name
, 0);
2204 #undef TARGET_SECTION_TYPE_FLAGS
2205 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2208 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2210 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2211 name
+= strlen (lower_prefix
);
2212 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2213 name
+= strlen (upper_prefix
);
2214 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2215 name
+= strlen (either_prefix
);
2216 else if (strcmp (name
, ".noinit") == 0)
2217 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2218 else if (strcmp (name
, ".persistent") == 0)
2219 return SECTION_WRITE
| SECTION_NOTYPE
;
2221 return default_section_type_flags (decl
, name
, reloc
);
2224 #undef TARGET_ASM_UNIQUE_SECTION
2225 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2228 msp430_unique_section (tree decl
, int reloc
)
2230 gcc_assert (decl
!= NULL_TREE
);
2232 /* In large mode we must make sure that interrupt handlers are put into
2233 low memory as the vector table only accepts 16-bit addresses. */
2234 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2236 set_decl_section_name (decl
, ".lowtext");
2240 default_unique_section (decl
, reloc
);
2242 const char * prefix
;
2244 if ( TREE_CODE (decl
) == STRING_CST
2245 || TREE_CODE (decl
) == CONSTRUCTOR
2246 || TREE_CODE (decl
) == INTEGER_CST
2247 || TREE_CODE (decl
) == VECTOR_CST
2248 || TREE_CODE (decl
) == COMPLEX_CST
2249 || (prefix
= gen_prefix (decl
)) == NULL
2253 const char * dec_name
= DECL_SECTION_NAME (decl
);
2254 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2256 set_decl_section_name (decl
, name
);
2259 /* Emit a declaration of a common symbol.
2260 If a data region is in use then put the symbol into the
2261 equivalent .bss section instead. */
2264 msp430_output_aligned_decl_common (FILE * stream
,
2267 unsigned HOST_WIDE_INT size
,
2270 if (msp430_data_region
== ANY
)
2272 fprintf (stream
, COMMON_ASM_OP
);
2273 assemble_name (stream
, name
);
2274 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2275 size
, align
/ BITS_PER_UNIT
);
2282 sec
= msp430_select_section (decl
, 0, align
);
2284 switch (msp430_data_region
)
2286 case UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2287 case LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2288 case EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2292 gcc_assert (sec
!= NULL
);
2294 switch_to_section (sec
);
2295 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2296 targetm
.asm_out
.globalize_label (stream
, name
);
2297 ASM_WEAKEN_LABEL (stream
, name
);
2298 ASM_OUTPUT_LABEL (stream
, name
);
2299 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2304 msp430_do_not_relax_short_jumps (void)
2306 /* When placing code into "either" low or high memory we do not want the linker
2307 to grow the size of sections, which it can do if it is encounters a branch to
2308 a label that is too far away. So we tell the cbranch patterns to avoid using
2309 short jumps when there is a chance that the instructions will end up in a low
2312 msp430_code_region
== EITHER
2313 || msp430_code_region
== LOWER
2314 || has_attr (ATTR_EITHER
, current_function_decl
)
2315 || has_attr (ATTR_LOWER
, current_function_decl
);
2320 MSP430_BUILTIN_BIC_SR
,
2321 MSP430_BUILTIN_BIS_SR
,
2322 MSP430_BUILTIN_DELAY_CYCLES
,
2326 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2329 msp430_init_builtins (void)
2331 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2332 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2334 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2335 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2336 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2338 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2339 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2340 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2342 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2343 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2344 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2348 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2352 case MSP430_BUILTIN_BIC_SR
:
2353 case MSP430_BUILTIN_BIS_SR
:
2354 case MSP430_BUILTIN_DELAY_CYCLES
:
2355 return msp430_builtins
[code
];
2357 return error_mark_node
;
2361 /* These constants are really register reads, which are faster than
2362 regular constants. */
2364 cg_magic_constant (HOST_WIDE_INT c
)
2382 msp430_expand_delay_cycles (rtx arg
)
2384 HOST_WIDE_INT i
, c
, n
;
2385 /* extra cycles for MSP430X instructions */
2386 #define CYCX(M,X) (msp430x ? (X) : (M))
2388 if (GET_CODE (arg
) != CONST_INT
)
2390 error ("__delay_cycles() only takes constant arguments");
2396 if (HOST_BITS_PER_WIDE_INT
> 32)
2400 error ("__delay_cycles only takes non-negative cycle counts.");
2405 emit_insn (gen_delay_cycles_start (arg
));
2407 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2408 if (c
> 3 * 0xffff + CYCX (7, 10))
2411 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2412 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2415 c
-= CYCX (14, 16) + 7 * 0x10000;
2418 if ((unsigned long long) i
> 0xffffffffULL
)
2420 error ("__delay_cycles is limited to 32-bit loop counts.");
2426 i
= (c
- CYCX (14, 16)) / 7;
2427 c
-= CYCX (14, 16) + i
* 7;
2430 if (cg_magic_constant (i
& 0xffff))
2432 if (cg_magic_constant ((i
>> 16) & 0xffff))
2436 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2438 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2441 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2445 i
= (c
- CYCX (7, 10)) / 3;
2446 c
-= CYCX (7, 10) + i
* 3;
2448 if (cg_magic_constant (i
))
2452 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2454 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2459 emit_insn (gen_delay_cycles_2 ());
2465 emit_insn (gen_delay_cycles_1 ());
2469 emit_insn (gen_delay_cycles_end (arg
));
2475 msp430_expand_builtin (tree exp
,
2476 rtx target ATTRIBUTE_UNUSED
,
2477 rtx subtarget ATTRIBUTE_UNUSED
,
2478 machine_mode mode ATTRIBUTE_UNUSED
,
2479 int ignore ATTRIBUTE_UNUSED
)
2481 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2482 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2483 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2485 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2486 return msp430_expand_delay_cycles (arg1
);
2488 if (! msp430_is_interrupt_func ())
2490 error ("MSP430 builtin functions only work inside interrupt handlers");
2494 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2495 arg1
= force_reg (mode
, arg1
);
2499 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2500 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2502 internal_error ("bad builtin code");
2508 #undef TARGET_INIT_BUILTINS
2509 #define TARGET_INIT_BUILTINS msp430_init_builtins
2511 #undef TARGET_EXPAND_BUILTIN
2512 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2514 #undef TARGET_BUILTIN_DECL
2515 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2518 msp430_expand_prologue (void)
2522 /* Always use stack_pointer_rtx instead of calling
2523 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2524 that there is a single rtx representing the stack pointer,
2525 namely stack_pointer_rtx, and uses == to recognize it. */
2526 rtx sp
= stack_pointer_rtx
;
2529 if (is_naked_func ())
2531 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2532 examines the output of the gen_prologue() function. */
2533 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2537 emit_insn (gen_prologue_start_marker ());
2539 if (is_critical_func ())
2541 emit_insn (gen_push_intr_state ());
2542 emit_insn (gen_disable_interrupts ());
2544 else if (is_reentrant_func ())
2545 emit_insn (gen_disable_interrupts ());
2547 if (!cfun
->machine
->computed
)
2548 msp430_compute_frame_info ();
2550 if (flag_stack_usage_info
)
2551 current_function_static_stack_size
= cfun
->machine
->framesize
;
2553 if (crtl
->args
.pretend_args_size
)
2557 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2559 p
= emit_insn (gen_grow_and_swap ());
2561 /* Document the stack decrement... */
2562 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2563 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2564 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2566 /* ...and the establishment of a new location for the return address. */
2567 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2568 gen_rtx_PLUS (Pmode
,
2572 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2576 for (i
= 15; i
>= 4; i
--)
2577 if (cfun
->machine
->need_to_save
[i
])
2582 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2588 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2589 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2592 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2594 XVECEXP (note
, 0, 0)
2595 = F (gen_rtx_SET (stack_pointer_rtx
,
2596 gen_rtx_PLUS (Pmode
,
2598 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2600 /* *sp-- = R[i-j] */
2604 for (j
= 0; j
< count
; j
++)
2607 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2610 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2612 addr
= stack_pointer_rtx
;
2614 XVECEXP (note
, 0, j
+ 1) =
2615 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2616 gen_rtx_REG (Pmode
, i
- j
)) );
2619 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2623 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2626 if (frame_pointer_needed
)
2627 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2629 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2631 increment_stack (- fs
);
2633 emit_insn (gen_prologue_end_marker ());
2637 msp430_expand_epilogue (int is_eh
)
2643 if (is_naked_func ())
2645 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2646 examines the output of the gen_epilogue() function. */
2647 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2651 if (cfun
->machine
->need_to_save
[10])
2653 /* Check for a helper function. */
2654 helper_n
= 7; /* For when the loop below never sees a match. */
2655 for (i
= 9; i
>= 4; i
--)
2656 if (!cfun
->machine
->need_to_save
[i
])
2660 if (cfun
->machine
->need_to_save
[i
])
2669 emit_insn (gen_epilogue_start_marker ());
2671 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2672 emit_insn (gen_msp430_refsym_need_exit ());
2674 if (is_wakeup_func ())
2675 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2676 status register current residing on the stack. When this function
2677 executes its RETI instruction the SR will be updated with this saved
2678 value, thus ensuring that the processor is woken up from any low power
2679 state in which it may be residing. */
2680 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2682 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2684 increment_stack (fs
);
2688 /* We need to add the right "SP" register save just after the
2689 regular ones, so that when we pop it off we're in the EH
2690 return frame, not this one. This overwrites our own return
2691 address, but we're not going to be returning anyway. */
2692 rtx r12
= gen_rtx_REG (Pmode
, 12);
2693 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2695 /* R12 will hold the new SP. */
2696 i
= cfun
->machine
->framesize_regs
;
2697 emit_move_insn (r12
, stack_pointer_rtx
);
2698 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2699 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2700 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2703 for (i
= 4; i
<= 15; i
++)
2704 if (cfun
->machine
->need_to_save
[i
])
2708 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2714 /* Note: With TARGET_LARGE we still use
2715 POPM as POPX.A is two bytes bigger. */
2716 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2720 else if (i
== 11 - helper_n
2721 && ! msp430_is_interrupt_func ()
2722 && ! is_reentrant_func ()
2723 && ! is_critical_func ()
2724 && crtl
->args
.pretend_args_size
== 0
2725 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2729 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2733 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2738 /* Also pop SP, which puts us into the EH return frame. Except
2739 that you can't "pop" sp, you have to just load it off the
2741 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2744 if (crtl
->args
.pretend_args_size
)
2745 emit_insn (gen_swap_and_shrink ());
2747 if (is_critical_func ())
2748 emit_insn (gen_pop_intr_state ());
2749 else if (is_reentrant_func ())
2750 emit_insn (gen_enable_interrupts ());
2752 emit_jump_insn (gen_msp_return ());
2755 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2756 m32c_emit_eh_epilogue. */
2758 msp430_eh_return_stackadj_rtx (void)
2760 if (!cfun
->machine
->eh_stack_adjust
)
2764 sa
= gen_rtx_REG (Pmode
, 15);
2765 cfun
->machine
->eh_stack_adjust
= sa
;
2767 return cfun
->machine
->eh_stack_adjust
;
2770 /* This function is called before reload, to "fix" the stack in
2771 preparation for an EH return. */
2773 msp430_expand_eh_return (rtx eh_handler
)
2775 /* These are all Pmode */
2776 rtx ap
, sa
, ra
, tmp
;
2778 ap
= arg_pointer_rtx
;
2779 sa
= msp430_eh_return_stackadj_rtx ();
2783 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2784 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2785 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2786 emit_move_insn (tmp
, ra
);
2789 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2790 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2792 msp430_init_dwarf_reg_sizes_extra (tree address
)
2795 rtx addr
= expand_normal (address
);
2796 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2801 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2803 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2804 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2806 if (rnum
< DWARF_FRAME_REGISTERS
)
2808 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2810 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2811 gen_int_mode (4, QImode
));
2816 /* This is a list of MD patterns that implement fixed-count shifts. */
2822 rtx (*genfunc
)(rtx
,rtx
);
2824 const_shift_helpers
[] =
2826 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2828 CSH ("slli", 1, 1, slli_1
),
2829 CSH ("slll", 1, 1, slll_1
),
2830 CSH ("slll", 2, 1, slll_2
),
2832 CSH ("srai", 1, 0, srai_1
),
2833 CSH ("sral", 1, 0, sral_1
),
2834 CSH ("sral", 2, 0, sral_2
),
2836 CSH ("srll", 1, 0, srll_1
),
2837 CSH ("srll", 2, 1, srll_2x
),
2842 /* The MSP430 ABI defines a number of helper functions that should be
2843 used for, for example, 32-bit shifts. This function is called to
2844 emit such a function, using the table above to optimize some
2847 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2850 char *helper_const
= NULL
;
2853 machine_mode arg0mode
= GET_MODE (operands
[0]);
2854 machine_mode arg1mode
= GET_MODE (operands
[1]);
2855 machine_mode arg2mode
= GET_MODE (operands
[2]);
2856 int have_430x
= msp430x
? 1 : 0;
2858 if (CONST_INT_P (operands
[2]))
2862 for (i
=0; const_shift_helpers
[i
].name
; i
++)
2864 if (const_shift_helpers
[i
].need_430x
<= have_430x
2865 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
2866 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
2868 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
2874 if (arg1mode
== VOIDmode
)
2875 arg1mode
= arg0mode
;
2876 if (arg2mode
== VOIDmode
)
2877 arg2mode
= arg0mode
;
2879 if (arg1mode
== SImode
)
2886 && CONST_INT_P (operands
[2])
2887 && INTVAL (operands
[2]) >= 1
2888 && INTVAL (operands
[2]) <= 15)
2890 /* Note that the INTVAL is limited in value and length by the conditional above. */
2891 int len
= strlen (helper_name
) + 4;
2892 helper_const
= (char *) xmalloc (len
);
2893 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
2896 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
2899 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
2902 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
2903 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
2905 c
= emit_call_insn (c
);
2906 RTL_CONST_CALL_P (c
) = 1;
2909 use_regs (&f
, 12, arg1sz
);
2911 use_regs (&f
, arg2
, 1);
2912 add_function_usage_to (c
, f
);
2914 emit_move_insn (operands
[0],
2915 gen_rtx_REG (arg0mode
, 12));
2918 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
2920 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
2922 /* constants we're looking for, not constants which are allowed. */
2923 int const_op_idx
= 1;
2925 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
2928 if (GET_CODE (operands
[const_op_idx
]) != REG
2929 && GET_CODE (operands
[const_op_idx
]) != MEM
)
2930 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
2933 /* Simplify_gen_subreg() doesn't handle memory references the way we
2934 need it to below, so we use this function for when we must get a
2935 valid subreg in a "natural" state. */
2937 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
2941 if (GET_CODE (r
) == SUBREG
2942 && SUBREG_BYTE (r
) == 0)
2944 rtx ireg
= SUBREG_REG (r
);
2945 machine_mode imode
= GET_MODE (ireg
);
2947 /* special case for (HI (SI (PSI ...), 0)) */
2948 if (imode
== PSImode
2951 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
2953 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
2955 else if (GET_CODE (r
) == MEM
)
2956 rv
= adjust_address (r
, mode
, byte
);
2957 else if (GET_CODE (r
) == SYMBOL_REF
2958 && (byte
== 0 || byte
== 2)
2961 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
2962 rv
= gen_rtx_CONST (HImode
, r
);
2965 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
2973 /* Called by movsi_x to generate the HImode operands. */
2975 msp430_split_movsi (rtx
*operands
)
2977 rtx op00
, op02
, op10
, op12
;
2979 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
2980 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
2982 if (GET_CODE (operands
[1]) == CONST
2983 || GET_CODE (operands
[1]) == SYMBOL_REF
)
2985 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
2986 op10
= gen_rtx_CONST (HImode
, op10
);
2987 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
2988 op12
= gen_rtx_CONST (HImode
, op12
);
2992 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
2993 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
2996 if (rtx_equal_p (operands
[0], operands
[1]))
3003 else if (rtx_equal_p (op00
, op12
)
3004 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3005 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3006 /* Or storing (rN) into mem (rN). */
3007 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3025 /* The MSPABI specifies the names of various helper functions, many of
3026 which are compatible with GCC's helpers. This table maps the GCC
3027 name to the MSPABI name. */
3030 char const * const gcc_name
;
3031 char const * const ti_name
;
3033 helper_function_name_mappings
[] =
3035 /* Floating point to/from integer conversions. */
3036 { "__truncdfsf2", "__mspabi_cvtdf" },
3037 { "__extendsfdf2", "__mspabi_cvtfd" },
3038 { "__fixdfhi", "__mspabi_fixdi" },
3039 { "__fixdfsi", "__mspabi_fixdli" },
3040 { "__fixdfdi", "__mspabi_fixdlli" },
3041 { "__fixunsdfhi", "__mspabi_fixdu" },
3042 { "__fixunsdfsi", "__mspabi_fixdul" },
3043 { "__fixunsdfdi", "__mspabi_fixdull" },
3044 { "__fixsfhi", "__mspabi_fixfi" },
3045 { "__fixsfsi", "__mspabi_fixfli" },
3046 { "__fixsfdi", "__mspabi_fixflli" },
3047 { "__fixunsfhi", "__mspabi_fixfu" },
3048 { "__fixunsfsi", "__mspabi_fixful" },
3049 { "__fixunsfdi", "__mspabi_fixfull" },
3050 { "__floathisf", "__mspabi_fltif" },
3051 { "__floatsisf", "__mspabi_fltlif" },
3052 { "__floatdisf", "__mspabi_fltllif" },
3053 { "__floathidf", "__mspabi_fltid" },
3054 { "__floatsidf", "__mspabi_fltlid" },
3055 { "__floatdidf", "__mspabi_fltllid" },
3056 { "__floatunhisf", "__mspabi_fltuf" },
3057 { "__floatunsisf", "__mspabi_fltulf" },
3058 { "__floatundisf", "__mspabi_fltullf" },
3059 { "__floatunhidf", "__mspabi_fltud" },
3060 { "__floatunsidf", "__mspabi_fltuld" },
3061 { "__floatundidf", "__mspabi_fltulld" },
3063 /* Floating point comparisons. */
3064 /* GCC uses individual functions for each comparison, TI uses one
3065 compare <=> function. */
3067 /* Floating point arithmatic */
3068 { "__adddf3", "__mspabi_addd" },
3069 { "__addsf3", "__mspabi_addf" },
3070 { "__divdf3", "__mspabi_divd" },
3071 { "__divsf3", "__mspabi_divf" },
3072 { "__muldf3", "__mspabi_mpyd" },
3073 { "__mulsf3", "__mspabi_mpyf" },
3074 { "__subdf3", "__mspabi_subd" },
3075 { "__subsf3", "__mspabi_subf" },
3076 /* GCC does not use helper functions for negation */
3078 /* Integer multiply, divide, remainder. */
3079 { "__mulhi3", "__mspabi_mpyi" },
3080 { "__mulsi3", "__mspabi_mpyl" },
3081 { "__muldi3", "__mspabi_mpyll" },
3083 /* Clarify signed vs unsigned first. */
3084 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3085 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3088 { "__divhi3", "__mspabi_divi" },
3089 { "__divsi3", "__mspabi_divli" },
3090 { "__divdi3", "__mspabi_divlli" },
3091 { "__udivhi3", "__mspabi_divu" },
3092 { "__udivsi3", "__mspabi_divlu" },
3093 { "__udivdi3", "__mspabi_divllu" },
3094 { "__modhi3", "__mspabi_remi" },
3095 { "__modsi3", "__mspabi_remli" },
3096 { "__moddi3", "__mspabi_remlli" },
3097 { "__umodhi3", "__mspabi_remu" },
3098 { "__umodsi3", "__mspabi_remul" },
3099 { "__umoddi3", "__mspabi_remull" },
3101 /* Bitwise operations. */
3102 /* Rotation - no rotation support yet. */
3103 /* Logical left shift - gcc already does these itself. */
3104 /* Arithmetic left shift - gcc already does these itself. */
3105 /* Arithmetic right shift - gcc already does these itself. */
3110 /* Returns true if the current MCU supports an F5xxx series
3111 hardware multiper. */
3114 msp430_use_f5_series_hwmult (void)
3116 static const char * cached_match
= NULL
;
3117 static bool cached_result
;
3119 if (msp430_hwmult_type
== F5SERIES
)
3122 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
3125 if (target_mcu
== cached_match
)
3126 return cached_result
;
3128 cached_match
= target_mcu
;
3130 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3131 return cached_result
= true;
3132 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3133 return cached_result
= true;
3134 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3135 return cached_result
= true;
3139 /* FIXME: This array is alpha sorted - we could use a binary search. */
3140 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3141 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3142 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3144 return cached_result
= false;
3147 /* Returns true if the current MCU has a second generation
3148 32-bit hardware multiplier. */
3151 use_32bit_hwmult (void)
3153 static const char * cached_match
= NULL
;
3154 static bool cached_result
;
3157 if (msp430_hwmult_type
== LARGE
)
3160 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
3163 if (target_mcu
== cached_match
)
3164 return cached_result
;
3166 cached_match
= target_mcu
;
3168 /* FIXME: This array is alpha sorted - we could use a binary search. */
3169 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3170 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3171 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3173 return cached_result
= false;
3176 /* Returns true if the current MCU does not have a
3177 hardware multiplier of any kind. */
3180 msp430_no_hwmult (void)
3182 static const char * cached_match
= NULL
;
3183 static bool cached_result
;
3186 if (msp430_hwmult_type
== NONE
)
3189 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
3192 if (target_mcu
== cached_match
)
3193 return cached_result
;
3195 cached_match
= target_mcu
;
3197 /* FIXME: This array is alpha sorted - we could use a binary search. */
3198 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3199 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3200 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3202 /* If we do not recognise the MCU name, we assume that it does not support
3203 any kind of hardware multiply - this is the safest assumption to make. */
3204 return cached_result
= true;
3207 /* This function does the same as the default, but it will replace GCC
3208 function names with the MSPABI-specified ones. */
3211 msp430_output_labelref (FILE *file
, const char *name
)
3215 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3216 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3218 name
= helper_function_name_mappings
[i
].ti_name
;
3222 /* If we have been given a specific MCU name then we may be
3223 able to make use of its hardware multiply capabilities. */
3224 if (msp430_hwmult_type
!= NONE
)
3226 if (strcmp ("__mspabi_mpyi", name
) == 0)
3228 if (msp430_use_f5_series_hwmult ())
3229 name
= "__mulhi2_f5";
3230 else if (! msp430_no_hwmult ())
3233 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3235 if (msp430_use_f5_series_hwmult ())
3236 name
= "__mulsi2_f5";
3237 else if (use_32bit_hwmult ())
3238 name
= "__mulsi2_hw32";
3239 else if (! msp430_no_hwmult ())
3247 /* Common code for msp430_print_operand... */
3250 msp430_print_operand_raw (FILE * file
, rtx op
)
3254 switch (GET_CODE (op
))
3257 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3263 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3265 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3273 output_addr_const (file
, op
);
3277 print_rtl (file
, op
);
3282 #undef TARGET_PRINT_OPERAND_ADDRESS
3283 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3285 /* Output to stdio stream FILE the assembler syntax for an
3286 instruction operand that is a memory reference whose address
3290 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3292 switch (GET_CODE (addr
))
3295 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3296 gcc_assert (REG_P (XEXP (addr
, 0)));
3297 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3301 fprintf (file
, "@");
3308 fprintf (file
, "&");
3315 msp430_print_operand_raw (file
, addr
);
3318 #undef TARGET_PRINT_OPERAND
3319 #define TARGET_PRINT_OPERAND msp430_print_operand
3321 /* A low 16-bits of int/lower of register pair
3322 B high 16-bits of int/higher of register pair
3323 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3324 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3325 H like %B (for backwards compatibility)
3327 J an integer without a # prefix
3328 L like %A (for backwards compatibility)
3329 O offset of the top of the stack
3330 Q like X but generates an A postfix
3331 R inverse of condition code, unsigned.
3332 X X instruction postfix in large mode
3335 b .B or .W or .A, depending upon the mode
3337 r inverse of condition code
3338 x like X but only for pointers. */
3341 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3345 /* We can't use c, n, a, or l. */
3349 gcc_assert (CONST_INT_P (op
));
3350 /* Print the constant value, less one. */
3351 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3354 gcc_assert (CONST_INT_P (op
));
3355 /* Print the constant value, less four. */
3356 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3359 if (GET_CODE (op
) == CONST_INT
)
3361 /* Inverse of constants */
3362 int i
= INTVAL (op
);
3363 fprintf (file
, "%d", ~i
);
3368 case 'r': /* Conditional jump where the condition is reversed. */
3369 switch (GET_CODE (op
))
3371 case EQ
: fprintf (file
, "NE"); break;
3372 case NE
: fprintf (file
, "EQ"); break;
3373 case GEU
: fprintf (file
, "LO"); break;
3374 case LTU
: fprintf (file
, "HS"); break;
3375 case GE
: fprintf (file
, "L"); break;
3376 case LT
: fprintf (file
, "GE"); break;
3377 /* Assume these have reversed operands. */
3378 case GTU
: fprintf (file
, "HS"); break;
3379 case LEU
: fprintf (file
, "LO"); break;
3380 case GT
: fprintf (file
, "GE"); break;
3381 case LE
: fprintf (file
, "L"); break;
3383 msp430_print_operand_raw (file
, op
);
3387 case 'R': /* Conditional jump where the operands are reversed. */
3388 switch (GET_CODE (op
))
3390 case GTU
: fprintf (file
, "LO"); break;
3391 case LEU
: fprintf (file
, "HS"); break;
3392 case GT
: fprintf (file
, "L"); break;
3393 case LE
: fprintf (file
, "GE"); break;
3395 msp430_print_operand_raw (file
, op
);
3399 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3400 gcc_assert (CONST_INT_P (op
));
3401 fprintf (file
, "#%d", 1 << INTVAL (op
));
3404 switch (GET_MODE (op
))
3406 case QImode
: fprintf (file
, ".B"); return;
3407 case HImode
: fprintf (file
, ".W"); return;
3408 case PSImode
: fprintf (file
, ".A"); return;
3409 case SImode
: fprintf (file
, ".A"); return;
3414 case 'L': /* Low half. */
3415 switch (GET_CODE (op
))
3418 op
= adjust_address (op
, Pmode
, 0);
3423 op
= GEN_INT (INTVAL (op
) & 0xffff);
3427 /* If you get here, figure out a test case :-) */
3432 case 'H': /* high half */
3433 switch (GET_CODE (op
))
3436 op
= adjust_address (op
, Pmode
, 2);
3439 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3442 op
= GEN_INT (INTVAL (op
) >> 16);
3446 /* If you get here, figure out a test case :-) */
3451 switch (GET_CODE (op
))
3454 op
= adjust_address (op
, Pmode
, 3);
3457 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3460 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3464 /* If you get here, figure out a test case :-) */
3469 switch (GET_CODE (op
))
3472 op
= adjust_address (op
, Pmode
, 4);
3475 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3478 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3482 /* If you get here, figure out a test case :-) */
3488 /* This is used to turn, for example, an ADD opcode into an ADDX
3489 opcode when we're using 20-bit addresses. */
3490 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3491 fprintf (file
, "X");
3492 /* We don't care which operand we use, but we want 'X' in the MD
3493 file, so we do it this way. */
3497 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3498 if (GET_MODE (op
) == PSImode
)
3499 fprintf (file
, "X");
3503 /* Likewise, for BR -> BRA. */
3505 fprintf (file
, "A");
3509 /* Computes the offset to the top of the stack for the current frame.
3510 This has to be done here rather than in, say, msp430_expand_builtin()
3511 because builtins are expanded before the frame layout is determined. */
3512 fprintf (file
, "%d",
3513 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3514 - (TARGET_LARGE
? 4 : 2));
3518 gcc_assert (GET_CODE (op
) == CONST_INT
);
3522 output_operand_lossage ("invalid operand prefix");
3526 switch (GET_CODE (op
))
3529 msp430_print_operand_raw (file
, op
);
3533 addr
= XEXP (op
, 0);
3534 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3538 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3541 switch (INTVAL (XEXP (op
, 2)))
3544 fprintf (file
, "#lo (");
3545 msp430_print_operand_raw (file
, XEXP (op
, 0));
3546 fprintf (file
, ")");
3550 fprintf (file
, "#hi (");
3551 msp430_print_operand_raw (file
, XEXP (op
, 0));
3552 fprintf (file
, ")");
3556 output_operand_lossage ("invalid zero extract");
3566 fprintf (file
, "#");
3567 msp430_print_operand_raw (file
, op
);
3570 case EQ
: fprintf (file
, "EQ"); break;
3571 case NE
: fprintf (file
, "NE"); break;
3572 case GEU
: fprintf (file
, "HS"); break;
3573 case LTU
: fprintf (file
, "LO"); break;
3574 case GE
: fprintf (file
, "GE"); break;
3575 case LT
: fprintf (file
, "L"); break;
3578 print_rtl (file
, op
);
3587 msp430_return_addr_rtx (int count
)
3593 ra_size
= TARGET_LARGE
? 4 : 2;
3594 if (crtl
->args
.pretend_args_size
)
3597 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3601 msp430_incoming_return_addr_rtx (void)
3603 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3606 /* Instruction generation stuff. */
3608 /* Generate a sequence of instructions to sign-extend an HI
3609 value into an SI value. Handles the tricky case where
3610 we are overwriting the destination. */
3613 msp430x_extendhisi (rtx
* operands
)
3615 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3616 /* Low word of dest == source word. */
3617 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3620 /* Note: This sequence is approximately the same length as invoking a helper
3621 function to perform the sign-extension, as in:
3625 CALL __mspabi_srai_15
3628 but this version does not involve any function calls or using argument
3629 registers, so it reduces register pressure. */
3630 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3632 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3633 /* High word of dest == source word. */
3634 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3636 /* No overlap between dest and source. */
3637 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3640 /* Likewise for logical right shifts. */
3642 msp430x_logical_shift_right (rtx amount
)
3644 /* The MSP430X's logical right shift instruction - RRUM - does
3645 not use an extension word, so we cannot encode a repeat count.
3646 Try various alternatives to work around this. If the count
3647 is in a register we are stuck, hence the assert. */
3648 gcc_assert (CONST_INT_P (amount
));
3650 if (INTVAL (amount
) <= 0
3651 || INTVAL (amount
) >= 16)
3652 return "# nop logical shift.";
3654 if (INTVAL (amount
) > 0
3655 && INTVAL (amount
) < 5)
3656 return "rrum.w\t%2, %0"; /* Two bytes. */
3658 if (INTVAL (amount
) > 4
3659 && INTVAL (amount
) < 9)
3660 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3662 /* First we logically shift right by one. Now we know
3663 that the top bit is zero and we can use the arithmetic
3664 right shift instruction to perform the rest of the shift. */
3665 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3668 struct gcc_target targetm
= TARGET_INITIALIZER
;
3670 #include "gt-msp430.h"