1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2016 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 March 2016. */
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 { "msp430fr2310",2,0 },
523 { "msp430fr2311",2,0 },
524 { "msp430fr2433",2,8 },
525 { "msp430fr2532",2,8 },
526 { "msp430fr2533",2,8 },
527 { "msp430fr2632",2,8 },
528 { "msp430fr2633",2,8 },
529 { "msp430fr2xx_4xxgeneric",2,8 },
530 { "msp430fr4131",2,0 },
531 { "msp430fr4132",2,0 },
532 { "msp430fr4133",2,0 },
533 { "msp430fr5720",2,8 },
534 { "msp430fr5721",2,8 },
535 { "msp430fr5722",2,8 },
536 { "msp430fr5723",2,8 },
537 { "msp430fr5724",2,8 },
538 { "msp430fr5725",2,8 },
539 { "msp430fr5726",2,8 },
540 { "msp430fr5727",2,8 },
541 { "msp430fr5728",2,8 },
542 { "msp430fr5729",2,8 },
543 { "msp430fr5730",2,8 },
544 { "msp430fr5731",2,8 },
545 { "msp430fr5732",2,8 },
546 { "msp430fr5733",2,8 },
547 { "msp430fr5734",2,8 },
548 { "msp430fr5735",2,8 },
549 { "msp430fr5736",2,8 },
550 { "msp430fr5737",2,8 },
551 { "msp430fr5738",2,8 },
552 { "msp430fr5739",2,8 },
553 { "msp430fr57xxgeneric",2,8 },
554 { "msp430fr5847",2,8 },
555 { "msp430fr58471",2,8 },
556 { "msp430fr5848",2,8 },
557 { "msp430fr5849",2,8 },
558 { "msp430fr5857",2,8 },
559 { "msp430fr5858",2,8 },
560 { "msp430fr5859",2,8 },
561 { "msp430fr5867",2,8 },
562 { "msp430fr5862",2,8 },
563 { "msp430fr5864",2,8 },
564 { "msp430fr58671",2,8 },
565 { "msp430fr5868",2,8 },
566 { "msp430fr5869",2,8 },
567 { "msp430fr5870",2,8 },
568 { "msp430fr5872",2,8 },
569 { "msp430fr58721",2,8 },
570 { "msp430fr5887",2,8 },
571 { "msp430fr5888",2,8 },
572 { "msp430fr5889",2,8 },
573 { "msp430fr58891",2,8 },
574 { "msp430fr5892",2,8 },
575 { "msp430fr5894",2,8 },
576 { "msp430fr5922",2,8 },
577 { "msp430fr59221",2,8 },
578 { "msp430fr5947",2,8 },
579 { "msp430fr59471",2,8 },
580 { "msp430fr5948",2,8 },
581 { "msp430fr5949",2,8 },
582 { "msp430fr5957",2,8 },
583 { "msp430fr5958",2,8 },
584 { "msp430fr5959",2,8 },
585 { "msp430fr5962",2,8 },
586 { "msp430fr5964",2,8 },
587 { "msp430fr5967",2,8 },
588 { "msp430fr5968",2,8 },
589 { "msp430fr5969",2,8 },
590 { "msp430fr59691",2,8 },
591 { "msp430fr5970",2,8 },
592 { "msp430fr5972",2,8 },
593 { "msp430fr59721",2,8 },
594 { "msp430fr5986",2,8 },
595 { "msp430fr5987",2,8 },
596 { "msp430fr5988",2,8 },
597 { "msp430fr5989",2,8 },
598 { "msp430fr59891",2,8 },
599 { "msp430fr5992",2,8 },
600 { "msp430fr5994",2,8 },
601 { "msp430fr5xx_6xxgeneric",2,8 },
602 { "msp430fr6820",2,8 },
603 { "msp430fr6822",2,8 },
604 { "msp430fr68221",2,8 },
605 { "msp430fr6870",2,8 },
606 { "msp430fr6872",2,8 },
607 { "msp430fr68721",2,8 },
608 { "msp430fr6877",2,8 },
609 { "msp430fr6879",2,8 },
610 { "msp430fr68791",2,8 },
611 { "msp430fr6887",2,8 },
612 { "msp430fr6888",2,8 },
613 { "msp430fr6889",2,8 },
614 { "msp430fr68891",2,8 },
615 { "msp430fr6920",2,8 },
616 { "msp430fr6922",2,8 },
617 { "msp430fr69221",2,8 },
618 { "msp430fr6927",2,8 },
619 { "msp430fr69271",2,8 },
620 { "msp430fr6928",2,8 },
621 { "msp430fr6970",2,8 },
622 { "msp430fr6972",2,8 },
623 { "msp430fr69721",2,8 },
624 { "msp430fr6977",2,8 },
625 { "msp430fr6979",2,8 },
626 { "msp430fr69791",2,8 },
627 { "msp430fr6987",2,8 },
628 { "msp430fr6988",2,8 },
629 { "msp430fr6989",2,8 },
630 { "msp430fr69891",2,8 },
631 { "msp430fw423",0,0 },
632 { "msp430fw425",0,0 },
633 { "msp430fw427",0,0 },
634 { "msp430fw428",0,0 },
635 { "msp430fw429",0,0 },
636 { "msp430g2001",0,0 },
637 { "msp430g2101",0,0 },
638 { "msp430g2102",0,0 },
639 { "msp430g2111",0,0 },
640 { "msp430g2112",0,0 },
641 { "msp430g2113",0,0 },
642 { "msp430g2121",0,0 },
643 { "msp430g2131",0,0 },
644 { "msp430g2132",0,0 },
645 { "msp430g2152",0,0 },
646 { "msp430g2153",0,0 },
647 { "msp430g2201",0,0 },
648 { "msp430g2202",0,0 },
649 { "msp430g2203",0,0 },
650 { "msp430g2210",0,0 },
651 { "msp430g2211",0,0 },
652 { "msp430g2212",0,0 },
653 { "msp430g2213",0,0 },
654 { "msp430g2221",0,0 },
655 { "msp430g2230",0,0 },
656 { "msp430g2231",0,0 },
657 { "msp430g2232",0,0 },
658 { "msp430g2233",0,0 },
659 { "msp430g2252",0,0 },
660 { "msp430g2253",0,0 },
661 { "msp430g2302",0,0 },
662 { "msp430g2303",0,0 },
663 { "msp430g2312",0,0 },
664 { "msp430g2313",0,0 },
665 { "msp430g2332",0,0 },
666 { "msp430g2333",0,0 },
667 { "msp430g2352",0,0 },
668 { "msp430g2353",0,0 },
669 { "msp430g2402",0,0 },
670 { "msp430g2403",0,0 },
671 { "msp430g2412",0,0 },
672 { "msp430g2413",0,0 },
673 { "msp430g2432",0,0 },
674 { "msp430g2433",0,0 },
675 { "msp430g2444",0,0 },
676 { "msp430g2452",0,0 },
677 { "msp430g2453",0,0 },
678 { "msp430g2513",0,0 },
679 { "msp430g2533",0,0 },
680 { "msp430g2544",0,0 },
681 { "msp430g2553",0,0 },
682 { "msp430g2744",0,0 },
683 { "msp430g2755",0,0 },
684 { "msp430g2855",0,0 },
685 { "msp430g2955",0,0 },
686 { "msp430i2020",0,2 },
687 { "msp430i2021",0,2 },
688 { "msp430i2030",0,2 },
689 { "msp430i2031",0,2 },
690 { "msp430i2040",0,2 },
691 { "msp430i2041",0,2 },
692 { "msp430i2xxgeneric",0,2 },
693 { "msp430l092",0,0 },
694 { "msp430p112",0,0 },
695 { "msp430p313",0,0 },
696 { "msp430p315",0,0 },
697 { "msp430p315s",0,0 },
698 { "msp430p325",0,0 },
699 { "msp430p337",0,1 },
700 { "msp430sl5438a",2,8 },
701 { "msp430tch5e",0,0 },
702 { "msp430xgeneric",2,8 },
703 { "rf430f5144",2,8 },
704 { "rf430f5155",2,8 },
705 { "rf430f5175",2,8 },
706 { "rf430frl152h",0,0 },
707 { "rf430frl152h_rom",0,0 },
708 { "rf430frl153h",0,0 },
709 { "rf430frl153h_rom",0,0 },
710 { "rf430frl154h",0,0 },
711 { "rf430frl154h_rom",0,0 }
714 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
715 If a specific MCU has not been selected then return a generic symbol instead. */
718 msp430_mcu_name (void)
723 static char mcu_name [64];
725 snprintf (mcu_name, sizeof (mcu_name) - 1, "__%s__", target_mcu);
726 for (i = strlen (mcu_name); i--;)
727 mcu_name[i] = TOUPPER (mcu_name[i]);
731 return msp430x ? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
735 hwmult_name (unsigned int val)
739 case 0: return "none";
740 case 1: return "16-bit";
741 case 2: return "16-bit";
742 case 4: return "32-bit";
743 case 8: return "32-bit (5xx)";
744 default: gcc_unreachable ();
749 msp430_option_override (void)
751 init_machine_status = msp430_init_machine_status;
755 /* gcc/common/config/msp430-common.c will have
756 already canonicalised the string in target_cpu. */
757 if (strcasecmp (target_cpu, "msp430x") == 0)
759 else /* target_cpu == "msp430" - already handled by the front end. */
767 /* FIXME: If the array were alpha sorted, we could use a binary search. */
768 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
769 if (strcasecmp (msp430_mcu_data[i].name, target_mcu) == 0)
771 bool xisa = msp430_mcu_data[i].revision >= 1;
775 if (target_cpu&& msp430x != xisa)
776 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
777 target_mcu, xisa ? "430X" : "430", msp430x ? "430X" : "430");
779 if (msp430_mcu_data[i].hwmpy == 0
780 && msp430_hwmult_type != AUTO
781 && msp430_hwmult_type != NONE)
782 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
784 msp430_hwmult_type == SMALL ? "16-bit" : msp430_hwmult_type == LARGE ? "32-bit" : "f5series");
785 else if (msp430_hwmult_type == SMALL
786 && msp430_mcu_data[i].hwmpy != 1
787 && msp430_mcu_data[i].hwmpy != 2 )
788 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
789 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
790 else if (msp430_hwmult_type == LARGE && msp430_mcu_data[i].hwmpy != 4)
791 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
792 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
793 else if (msp430_hwmult_type == F5SERIES && msp430_mcu_data[i].hwmpy != 8)
794 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
795 target_mcu, hwmult_name (msp430_mcu_data[i].hwmpy));
804 if (msp430_hwmult_type == AUTO)
808 if (target_cpu == NULL)
810 "Unrecognised MCU name '%s', assuming that it is just a MSP430 with no hardware multiply.\nUse the -mcpu and -mhwmult options to set these explicitly.",
814 "Unrecognised MCU name '%s', assuming that it has no hardware multiply.\nUse the -mhwmult option to set this explicitly.",
818 msp430_hwmult_type = NONE;
820 else if (target_cpu == NULL)
824 "Unrecognised MCU name '%s', assuming that it just supports the MSP430 ISA.\nUse the -mcpu option to set the ISA explicitly.",
829 else if (msp430_warn_mcu)
831 "Unrecognised MCU name '%s'.", target_mcu);
835 /* The F5 series are all able to support the 430X ISA. */
836 if (target_cpu == NULL && target_mcu == NULL && msp430_hwmult_type == F5SERIES)
839 if (TARGET_LARGE && !msp430x)
840 error ("-mlarge requires a 430X-compatible -mmcu=");
842 if (msp430_code_region == UPPER && ! msp430x)
843 error ("-mcode-region=upper requires 430X-compatible cpu");
844 if (msp430_data_region == UPPER && ! msp430x)
845 error ("-mdata-region=upper requires 430X-compatible cpu");
847 if (flag_exceptions || flag_non_call_exceptions
848 || flag_unwind_tables || flag_asynchronous_unwind_tables)
849 flag_omit_frame_pointer = false;
851 flag_omit_frame_pointer = true;
853 /* This is a hack to work around a problem with the newlib build
854 mechanism. Newlib always appends CFLAGS to the end of the GCC
855 command line and always sets -O2 in CFLAGS. Thus it is not
856 possible to build newlib with -Os enabled. Until now... */
857 if (TARGET_OPT_SPACE && optimize < 3)
861 #undef TARGET_SCALAR_MODE_SUPPORTED_P
862 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
865 msp430_scalar_mode_supported_p (machine_mode m)
867 if (m == PSImode && msp430x)
873 return default_scalar_mode_supported_p (m);
880 #undef TARGET_MS_BITFIELD_LAYOUT_P
881 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
884 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED)
893 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
894 PSImode value, but not an SImode value. */
896 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED,
899 if (mode == PSImode && msp430x)
901 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
905 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
907 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED,
910 if (mode == PSImode && msp430x)
912 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
916 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
918 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED,
923 return msp430_hard_regno_nregs (regno, mode);
926 /* Implements HARD_REGNO_MODE_OK. */
928 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED,
931 return regno <= (ARG_POINTER_REGNUM - msp430_hard_regno_nregs (regno, mode));
934 /* Implements MODES_TIEABLE_P. */
936 msp430_modes_tieable_p (machine_mode mode1, machine_mode mode2)
938 if ((mode1 == PSImode || mode2 == SImode)
939 || (mode1 == SImode || mode2 == PSImode))
942 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT
943 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT)
944 == (GET_MODE_CLASS (mode2) == MODE_FLOAT
945 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT));
948 #undef TARGET_FRAME_POINTER_REQUIRED
949 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
952 msp430_frame_pointer_required (void)
957 #undef TARGET_CAN_ELIMINATE
958 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
961 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED,
962 const int to_reg ATTRIBUTE_UNUSED)
967 /* Implements INITIAL_ELIMINATION_OFFSET. */
969 msp430_initial_elimination_offset (int from, int to)
971 int rv = 0; /* As if arg to arg. */
973 msp430_compute_frame_info ();
977 case STACK_POINTER_REGNUM:
978 rv += cfun->machine->framesize_outgoing;
979 rv += cfun->machine->framesize_locals;
981 case FRAME_POINTER_REGNUM:
982 rv += cfun->machine->framesize_regs;
983 /* Allow for the saved return address. */
984 rv += (TARGET_LARGE ? 4 : 2);
985 /* NB/ No need to allow for crtl->args.pretend_args_size.
986 GCC does that for us. */
994 case FRAME_POINTER_REGNUM:
995 /* Allow for the fall through above. */
996 rv -= (TARGET_LARGE ? 4 : 2);
997 rv -= cfun->machine->framesize_regs;
998 case ARG_POINTER_REGNUM:
1007 /* Named Address Space support */
1010 /* Return the appropriate mode for a named address pointer. */
1011 #undef TARGET_ADDR_SPACE_POINTER_MODE
1012 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1013 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1014 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1017 msp430_addr_space_pointer_mode (addr_space_t addrspace)
1022 case ADDR_SPACE_GENERIC:
1024 case ADDR_SPACE_NEAR:
1026 case ADDR_SPACE_FAR:
1031 /* Function pointers are stored in unwind_word sized
1032 variables, so make sure that unwind_word is big enough. */
1033 #undef TARGET_UNWIND_WORD_MODE
1034 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1037 msp430_unwind_word_mode (void)
1039 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1040 return msp430x ? PSImode : HImode;
1043 /* Determine if one named address space is a subset of another. */
1044 #undef TARGET_ADDR_SPACE_SUBSET_P
1045 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1047 msp430_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
1049 if (subset == superset)
1052 return (subset != ADDR_SPACE_FAR && superset == ADDR_SPACE_FAR);
1055 #undef TARGET_ADDR_SPACE_CONVERT
1056 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1057 /* Convert from one address space to another. */
1059 msp430_addr_space_convert (rtx op, tree from_type, tree to_type)
1061 addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
1062 addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
1065 if (to_as != ADDR_SPACE_FAR && from_as == ADDR_SPACE_FAR)
1067 /* This is unpredictable, as we're truncating off usable address
1070 if (CONSTANT_P (op))
1071 return gen_rtx_CONST (HImode, op);
1073 result = gen_reg_rtx (HImode);
1074 emit_insn (gen_truncpsihi2 (result, op));
1077 else if (to_as == ADDR_SPACE_FAR && from_as != ADDR_SPACE_FAR)
1079 /* This always works. */
1081 if (CONSTANT_P (op))
1082 return gen_rtx_CONST (PSImode, op);
1084 result = gen_reg_rtx (PSImode);
1085 emit_insn (gen_zero_extendhipsi2 (result, op));
1092 /* Stack Layout and Calling Conventions. */
1094 /* For each function, we list the gcc version and the TI version on
1095 each line, where we're converting the function names. */
1096 static char const * const special_convention_function_names [] =
1098 "__muldi3", "__mspabi_mpyll",
1099 "__udivdi3", "__mspabi_divull",
1100 "__umoddi3", "__mspabi_remull",
1101 "__divdi3", "__mspabi_divlli",
1102 "__moddi3", "__mspabi_remlli",
1106 "__adddf3", "__mspabi_addd",
1107 "__subdf3", "__mspabi_subd",
1108 "__muldf3", "__mspabi_mpyd",
1109 "__divdf3", "__mspabi_divd",
1114 /* TRUE if the function passed is a "speical" function. Special
1115 functions pass two DImode parameters in registers. */
1117 msp430_special_register_convention_p (const char *name)
1121 for (i = 0; special_convention_function_names [i]; i++)
1122 if (! strcmp (name, special_convention_function_names [i]))
1128 #undef TARGET_FUNCTION_VALUE_REGNO_P
1129 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1132 msp430_function_value_regno_p (unsigned int regno)
1138 #undef TARGET_FUNCTION_VALUE
1139 #define TARGET_FUNCTION_VALUE msp430_function_value
1142 msp430_function_value (const_tree ret_type,
1143 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
1144 bool outgoing ATTRIBUTE_UNUSED)
1146 return gen_rtx_REG (TYPE_MODE (ret_type), 12);
1149 #undef TARGET_LIBCALL_VALUE
1150 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1153 msp430_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
1155 return gen_rtx_REG (mode, 12);
1158 /* Implements INIT_CUMULATIVE_ARGS. */
1160 msp430_init_cumulative_args (CUMULATIVE_ARGS *ca,
1161 tree fntype ATTRIBUTE_UNUSED,
1162 rtx libname ATTRIBUTE_UNUSED,
1163 tree fndecl ATTRIBUTE_UNUSED,
1164 int n_named_args ATTRIBUTE_UNUSED)
1167 memset (ca, 0, sizeof(*ca));
1172 fname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
1174 fname = XSTR (libname, 0);
1178 if (fname && msp430_special_register_convention_p (fname))
1182 /* Helper function for argument passing; this function is the common
1183 code that determines where an argument will be passed. */
1185 msp430_evaluate_arg (cumulative_args_t cap,
1187 const_tree type ATTRIBUTE_UNUSED,
1190 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1191 int nregs = GET_MODE_SIZE (mode);
1200 if (mode == PSImode)
1203 nregs = (nregs + 1) / 2;
1207 /* Function is passed two DImode operands, in R8:R11 and
1217 for (i = 0; i < 4; i++)
1218 if (! ca->reg_used [i])
1221 ca->start_reg = CA_FIRST_REG + i;
1226 for (i = 0; i < 3; i++)
1227 if (! ca->reg_used [i] && ! ca->reg_used [i + 1])
1230 ca->start_reg = CA_FIRST_REG + i;
1233 if (! ca->reg_used [3] && ca->can_split)
1237 ca->start_reg = CA_FIRST_REG + 3;
1244 if (! ca->reg_used [0]
1245 && ! ca->reg_used [1]
1246 && ! ca->reg_used [2]
1247 && ! ca->reg_used [3])
1250 ca->start_reg = CA_FIRST_REG;
1257 #undef TARGET_PROMOTE_PROTOTYPES
1258 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1261 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED)
1266 #undef TARGET_FUNCTION_ARG
1267 #define TARGET_FUNCTION_ARG msp430_function_arg
1270 msp430_function_arg (cumulative_args_t cap,
1275 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1277 msp430_evaluate_arg (cap, mode, type, named);
1280 return gen_rtx_REG (mode, ca->start_reg);
1285 #undef TARGET_ARG_PARTIAL_BYTES
1286 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1289 msp430_arg_partial_bytes (cumulative_args_t cap,
1294 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1296 msp430_evaluate_arg (cap, mode, type, named);
1298 if (ca->reg_count && ca->mem_count)
1299 return ca->reg_count * UNITS_PER_WORD;
1304 #undef TARGET_PASS_BY_REFERENCE
1305 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1308 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED,
1311 bool named ATTRIBUTE_UNUSED)
1313 return (mode == BLKmode
1314 || (type && TREE_CODE (type) == RECORD_TYPE)
1315 || (type && TREE_CODE (type) == UNION_TYPE));
1318 #undef TARGET_CALLEE_COPIES
1319 #define TARGET_CALLEE_COPIES msp430_callee_copies
1322 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED,
1323 machine_mode mode ATTRIBUTE_UNUSED,
1324 const_tree type ATTRIBUTE_UNUSED,
1325 bool named ATTRIBUTE_UNUSED)
1330 #undef TARGET_FUNCTION_ARG_ADVANCE
1331 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1334 msp430_function_arg_advance (cumulative_args_t cap,
1339 CUMULATIVE_ARGS *ca = get_cumulative_args (cap);
1342 msp430_evaluate_arg (cap, mode, type, named);
1344 if (ca->start_reg >= CA_FIRST_REG)
1345 for (i = 0; i < ca->reg_count; i ++)
1346 ca->reg_used [i + ca->start_reg - CA_FIRST_REG] = 1;
1351 #undef TARGET_FUNCTION_ARG_BOUNDARY
1352 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1355 msp430_function_arg_boundary (machine_mode mode, const_tree type)
1358 && int_size_in_bytes (type) > 1)
1360 if (GET_MODE_BITSIZE (mode) > 8)
1365 #undef TARGET_RETURN_IN_MEMORY
1366 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1369 msp430_return_in_memory (const_tree ret_type, const_tree fntype ATTRIBUTE_UNUSED)
1371 machine_mode mode = TYPE_MODE (ret_type);
1374 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == RECORD_TYPE)
1375 || (fntype && TREE_CODE (TREE_TYPE (fntype)) == UNION_TYPE))
1378 if (GET_MODE_SIZE (mode) > 8)
1384 #undef TARGET_GET_RAW_ARG_MODE
1385 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1388 msp430_get_raw_arg_mode (int regno)
1390 return (regno == ARG_POINTER_REGNUM) ? VOIDmode : Pmode;
1393 #undef TARGET_GET_RAW_RESULT_MODE
1394 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1397 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED)
1402 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1403 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1405 #include "gimplify.h"
1408 msp430_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p,
1411 tree addr, t, type_size, rounded_size, valist_tmp;
1412 unsigned HOST_WIDE_INT align, boundary;
1415 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
1417 type = build_pointer_type (type);
1419 align = PARM_BOUNDARY / BITS_PER_UNIT;
1420 boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
1422 /* When we align parameter on stack for caller, if the parameter
1423 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1424 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1425 here with caller. */
1426 if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT)
1427 boundary = MAX_SUPPORTED_STACK_ALIGNMENT;
1429 boundary /= BITS_PER_UNIT;
1431 /* Hoist the valist value into a temporary for the moment. */
1432 valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL);
1434 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1435 requires greater alignment, we must perform dynamic alignment. */
1436 if (boundary > align
1437 && !integer_zerop (TYPE_SIZE (type)))
1439 /* FIXME: This is where this function diverts from targhooks.c:
1440 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1441 if (! POINTER_TYPE_P (type))
1443 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1444 fold_build_pointer_plus_hwi (valist_tmp, boundary - 1));
1445 gimplify_and_add (t, pre_p);
1447 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp,
1448 fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist),
1450 build_int_cst (TREE_TYPE (valist), -boundary)));
1451 gimplify_and_add (t, pre_p);
1457 /* If the actual alignment is less than the alignment of the type,
1458 adjust the type accordingly so that we don't assume strict alignment
1459 when dereferencing the pointer. */
1460 boundary *= BITS_PER_UNIT;
1461 if (boundary < TYPE_ALIGN (type))
1463 type = build_variant_type_copy (type);
1464 TYPE_ALIGN (type) = boundary;
1467 /* Compute the rounded size of the type. */
1468 type_size = size_in_bytes (type);
1469 rounded_size = round_up (type_size, align);
1471 /* Reduce rounded_size so it's sharable with the postqueue. */
1472 gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue);
1477 /* Compute new value for AP. */
1478 t = fold_build_pointer_plus (valist_tmp, rounded_size);
1479 t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
1480 gimplify_and_add (t, pre_p);
1482 addr = fold_convert (build_pointer_type (type), addr);
1485 addr = build_va_arg_indirect_ref (addr);
1487 addr = build_va_arg_indirect_ref (addr);
1492 /* Addressing Modes */
1494 #undef TARGET_LEGITIMATE_ADDRESS_P
1495 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1498 reg_ok_for_addr (rtx r, bool strict)
1502 if (strict && rn >= FIRST_PSEUDO_REGISTER)
1503 rn = reg_renumber [rn];
1504 if (strict && 0 <= rn && rn < FIRST_PSEUDO_REGISTER)
1512 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
1513 rtx x ATTRIBUTE_UNUSED,
1514 bool strict ATTRIBUTE_UNUSED)
1516 switch (GET_CODE (x))
1522 if (REG_P (XEXP (x, 0)))
1524 if (GET_MODE (x) != GET_MODE (XEXP (x, 0)))
1526 if (!reg_ok_for_addr (XEXP (x, 0), strict))
1528 switch (GET_CODE (XEXP (x, 1)))
1541 if (!reg_ok_for_addr (x, strict))
1554 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1555 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1558 msp430_addr_space_legitimate_address_p (machine_mode mode,
1561 addr_space_t as ATTRIBUTE_UNUSED)
1563 return msp430_legitimate_address_p (mode, x, strict);
1566 #undef TARGET_ASM_INTEGER
1567 #define TARGET_ASM_INTEGER msp430_asm_integer
1569 msp430_asm_integer (rtx x, unsigned int size, int aligned_p)
1571 int c = GET_CODE (x);
1573 if (size == 3 && GET_MODE (x) == PSImode)
1579 if (c == SYMBOL_REF || c == CONST || c == LABEL_REF || c == CONST_INT
1580 || c == PLUS || c == MINUS)
1582 fprintf (asm_out_file, "\t.long\t");
1583 output_addr_const (asm_out_file, x);
1584 fputc ('\n', asm_out_file);
1589 return default_assemble_integer (x, size, aligned_p);
1592 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1593 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1595 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED, rtx x)
1601 #undef TARGET_LEGITIMATE_CONSTANT_P
1602 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1605 msp430_legitimate_constant (machine_mode mode, rtx x)
1607 return ! CONST_INT_P (x)
1609 /* GCC does not know the width of the PSImode, so make
1610 sure that it does not try to use a constant value that
1612 || (INTVAL (x) < (1 << 20) && INTVAL (x) >= (HOST_WIDE_INT)(HOST_WIDE_INT_M1U << 20));
1616 #undef TARGET_RTX_COSTS
1617 #define TARGET_RTX_COSTS msp430_rtx_costs
1619 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED,
1621 int outer_code ATTRIBUTE_UNUSED,
1622 int opno ATTRIBUTE_UNUSED,
1624 bool speed ATTRIBUTE_UNUSED)
1626 int code = GET_CODE (x);
1631 if (mode == SImode && outer_code == SET)
1633 *total = COSTS_N_INSNS (4);
1642 *total = COSTS_N_INSNS (100);
1650 /* Function Entry and Exit */
1652 /* The MSP430 call frame looks like this:
1655 +--------------------+
1659 +--------------------+ <-- "arg pointer"
1661 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1663 +--------------------+
1664 | SR if this func has|
1665 | been called via an |
1667 +--------------------+ <-- SP before prologue, also AP
1669 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1671 +--------------------+ <-- "frame pointer"
1675 +--------------------+
1679 +--------------------+ <-- SP during function
1684 /* We use this to wrap all emitted insns in the prologue, so they get
1685 the "frame-related" (/f) flag set. */
1689 RTX_FRAME_RELATED_P (x) = 1;
1693 /* This is the one spot that decides if a register is to be saved and
1694 restored in the prologue/epilogue. */
1696 msp430_preserve_reg_p (int regno)
1698 /* PC, SP, SR, and the constant generator. */
1702 /* FIXME: add interrupt, EH, etc. */
1703 if (crtl->calls_eh_return)
1706 /* Shouldn't be more than the above, but just in case... */
1707 if (fixed_regs [regno])
1710 /* Interrupt handlers save all registers they use, even
1711 ones which are call saved. If they call other functions
1712 then *every* register is saved. */
1713 if (msp430_is_interrupt_func ())
1714 return ! crtl->is_leaf || df_regs_ever_live_p (regno);
1716 if (!call_used_regs [regno]
1717 && df_regs_ever_live_p (regno))
1723 /* Compute all the frame-related fields in our machine_function
1726 msp430_compute_frame_info (void)
1730 cfun->machine->computed = 1;
1731 cfun->machine->framesize_regs = 0;
1732 cfun->machine->framesize_locals = get_frame_size ();
1733 cfun->machine->framesize_outgoing = crtl->outgoing_args_size;
1735 for (i = 0; i < ARG_POINTER_REGNUM; i ++)
1736 if (msp430_preserve_reg_p (i))
1738 cfun->machine->need_to_save [i] = 1;
1739 cfun->machine->framesize_regs += (TARGET_LARGE ? 4 : 2);
1742 cfun->machine->need_to_save [i] = 0;
1744 if ((cfun->machine->framesize_locals + cfun->machine->framesize_outgoing) & 1)
1745 cfun->machine->framesize_locals ++;
1747 cfun->machine->framesize = (cfun->machine->framesize_regs
1748 + cfun->machine->framesize_locals
1749 + cfun->machine->framesize_outgoing);
1752 /* Attribute Handling. */
1754 const char * const ATTR_INTR = "interrupt";
1755 const char * const ATTR_WAKEUP = "wakeup";
1756 const char * const ATTR_NAKED = "naked";
1757 const char * const ATTR_REENT = "reentrant";
1758 const char * const ATTR_CRIT = "critical";
1759 const char * const ATTR_LOWER = "lower";
1760 const char * const ATTR_UPPER = "upper";
1761 const char * const ATTR_EITHER = "either";
1762 const char * const ATTR_NOINIT = "noinit";
1763 const char * const ATTR_PERSIST = "persistent";
1766 has_attr (const char * attr, tree decl)
1768 if (decl == NULL_TREE)
1770 return lookup_attribute (attr, DECL_ATTRIBUTES (decl)) != NULL_TREE;
1774 is_interrupt_func (tree decl = current_function_decl)
1776 return has_attr (ATTR_INTR, decl);
1779 /* Returns true if the current function has the "interrupt" attribute. */
1782 msp430_is_interrupt_func (void)
1784 return is_interrupt_func (current_function_decl);
1788 is_wakeup_func (tree decl = current_function_decl)
1790 return is_interrupt_func (decl) && has_attr (ATTR_WAKEUP, decl);
1794 is_naked_func (tree decl = current_function_decl)
1796 return has_attr (ATTR_NAKED, decl);
1800 is_reentrant_func (tree decl = current_function_decl)
1802 return has_attr (ATTR_REENT, decl);
1806 is_critical_func (tree decl = current_function_decl)
1808 return has_attr (ATTR_CRIT, decl);
1811 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1812 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1815 msp430_allocate_stack_slots_for_args (void)
1817 /* Naked functions should not allocate stack slots for arguments. */
1818 return ! is_naked_func ();
1821 /* Verify MSP430 specific attributes. */
1822 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1825 msp430_attr (tree * node,
1828 int flags ATTRIBUTE_UNUSED,
1829 bool * no_add_attrs)
1831 gcc_assert (DECL_P (* node));
1835 gcc_assert (TREE_NAME_EQ (name, ATTR_INTR));
1837 tree value = TREE_VALUE (args);
1839 switch (TREE_CODE (value))
1842 if ( strcmp (TREE_STRING_POINTER (value), "reset")
1843 && strcmp (TREE_STRING_POINTER (value), "nmi")
1844 && strcmp (TREE_STRING_POINTER (value), "watchdog"))
1845 /* Allow the attribute to be added - the linker script
1846 being used may still recognise this name. */
1847 warning (OPT_Wattributes,
1848 "unrecognised interrupt vector argument of %qE attribute",
1853 if (wi::gtu_p (value, 63))
1854 /* Allow the attribute to be added - the linker script
1855 being used may still recognise this value. */
1856 warning (OPT_Wattributes,
1857 "numeric argument of %qE attribute must be in range 0..63",
1862 warning (OPT_Wattributes,
1863 "argument of %qE attribute is not a string constant or number",
1865 *no_add_attrs = true;
1870 const char * message = NULL;
1872 if (TREE_CODE (* node) != FUNCTION_DECL)
1874 message = "%qE attribute only applies to functions";
1876 else if (TREE_NAME_EQ (name, ATTR_INTR))
1878 if (TREE_CODE (TREE_TYPE (* node)) == FUNCTION_TYPE
1879 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node))))
1880 message = "interrupt handlers must be void";
1882 else if (TREE_NAME_EQ (name, ATTR_REENT))
1884 if (is_naked_func (* node))
1885 message = "naked functions cannot be reentrant";
1886 else if (is_critical_func (* node))
1887 message = "critical functions cannot be reentrant";
1889 else if (TREE_NAME_EQ (name, ATTR_CRIT))
1891 if (is_naked_func (* node))
1892 message = "naked functions cannot be critical";
1893 else if (is_reentrant_func (* node))
1894 message = "reentrant functions cannot be critical";
1896 else if (TREE_NAME_EQ (name, ATTR_NAKED))
1898 if (is_critical_func (* node))
1899 message = "critical functions cannot be naked";
1900 else if (is_reentrant_func (* node))
1901 message = "reentrant functions cannot be naked";
1906 warning (OPT_Wattributes, message, name);
1907 * no_add_attrs = true;
1914 msp430_section_attr (tree * node,
1917 int flags ATTRIBUTE_UNUSED,
1918 bool * no_add_attrs ATTRIBUTE_UNUSED)
1920 gcc_assert (DECL_P (* node));
1921 gcc_assert (args == NULL);
1923 const char * message = NULL;
1925 if (TREE_NAME_EQ (name, ATTR_UPPER))
1927 if (has_attr (ATTR_LOWER, * node))
1928 message = "already marked with 'lower' attribute";
1929 else if (has_attr (ATTR_EITHER, * node))
1930 message = "already marked with 'either' attribute";
1932 message = "upper attribute needs a 430X cpu";
1934 else if (TREE_NAME_EQ (name, ATTR_LOWER))
1936 if (has_attr (ATTR_UPPER, * node))
1937 message = "already marked with 'upper' attribute";
1938 else if (has_attr (ATTR_EITHER, * node))
1939 message = "already marked with 'either' attribute";
1943 gcc_assert (TREE_NAME_EQ (name, ATTR_EITHER));
1945 if (has_attr (ATTR_LOWER, * node))
1946 message = "already marked with 'lower' attribute";
1947 else if (has_attr (ATTR_UPPER, * node))
1948 message = "already marked with 'upper' attribute";
1953 warning (OPT_Wattributes, message, name);
1954 * no_add_attrs = true;
1961 msp430_data_attr (tree * node,
1964 int flags ATTRIBUTE_UNUSED,
1965 bool * no_add_attrs ATTRIBUTE_UNUSED)
1967 const char * message = NULL;
1969 gcc_assert (DECL_P (* node));
1970 gcc_assert (args == NULL);
1972 if (TREE_CODE (* node) != VAR_DECL)
1973 message = "%qE attribute only applies to variables";
1975 if (DECL_SECTION_NAME (* node))
1976 message = "%qE attribute cannot be applied to variables with specific sections";
1978 /* If this var is thought to be common, then change this. Common variables
1979 are assigned to sections before the backend has a chance to process them. */
1980 if (DECL_COMMON (* node))
1981 DECL_COMMON (* node) = 0;
1985 warning (OPT_Wattributes, message, name);
1986 * no_add_attrs = true;
1993 #undef TARGET_ATTRIBUTE_TABLE
1994 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1996 /* Table of MSP430-specific attributes. */
1997 const struct attribute_spec msp430_attribute_table[] =
1999 /* Name min_num_args type_req, affects_type_identity
2000 max_num_args, fn_type_req
2001 decl_req handler. */
2002 { ATTR_INTR, 0, 1, true, false, false, msp430_attr, false },
2003 { ATTR_NAKED, 0, 0, true, false, false, msp430_attr, false },
2004 { ATTR_REENT, 0, 0, true, false, false, msp430_attr, false },
2005 { ATTR_CRIT, 0, 0, true, false, false, msp430_attr, false },
2006 { ATTR_WAKEUP, 0, 0, true, false, false, msp430_attr, false },
2008 { ATTR_LOWER, 0, 0, true, false, false, msp430_section_attr, false },
2009 { ATTR_UPPER, 0, 0, true, false, false, msp430_section_attr, false },
2010 { ATTR_EITHER, 0, 0, true, false, false, msp430_section_attr, false },
2012 { ATTR_NOINIT, 0, 0, true, false, false, msp430_data_attr, false },
2013 { ATTR_PERSIST, 0, 0, true, false, false, msp430_data_attr, false },
2015 { NULL, 0, 0, false, false, false, NULL, false }
2018 #undef TARGET_ASM_FUNCTION_PROLOGUE
2019 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2022 msp430_start_function (FILE *outfile, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED)
2026 fprintf (outfile, "; start of function\n");
2028 if (DECL_ATTRIBUTES (current_function_decl) != NULL_TREE)
2030 fprintf (outfile, "; attributes: ");
2031 if (is_naked_func ())
2032 fprintf (outfile, "naked ");
2033 if (msp430_is_interrupt_func ())
2034 fprintf (outfile, "interrupt ");
2035 if (is_reentrant_func ())
2036 fprintf (outfile, "reentrant ");
2037 if (is_critical_func ())
2038 fprintf (outfile, "critical ");
2039 if (is_wakeup_func ())
2040 fprintf (outfile, "wakeup ");
2041 fprintf (outfile, "\n");
2044 fprintf (outfile, "; framesize_regs: %d\n", cfun->machine->framesize_regs);
2045 fprintf (outfile, "; framesize_locals: %d\n", cfun->machine->framesize_locals);
2046 fprintf (outfile, "; framesize_outgoing: %d\n", cfun->machine->framesize_outgoing);
2047 fprintf (outfile, "; framesize: %d\n", cfun->machine->framesize);
2048 fprintf (outfile, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM));
2049 fprintf (outfile, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM));
2052 fprintf (outfile, "; saved regs:");
2053 for (r = 0; r < ARG_POINTER_REGNUM; r++)
2054 if (cfun->machine->need_to_save [r])
2056 fprintf (outfile, " %s", reg_names [r]);
2060 fprintf (outfile, "(none)");
2061 fprintf (outfile, "\n");
2064 /* Common code to change the stack pointer. */
2066 increment_stack (HOST_WIDE_INT amount)
2069 rtx sp = stack_pointer_rtx;
2076 inc = GEN_INT (- amount);
2078 F (emit_insn (gen_subpsi3 (sp, sp, inc)));
2080 F (emit_insn (gen_subhi3 (sp, sp, inc)));
2084 inc = GEN_INT (amount);
2086 emit_insn (gen_addpsi3 (sp, sp, inc));
2088 emit_insn (gen_addhi3 (sp, sp, inc));
2093 msp430_start_function (FILE *file, const char *name, tree decl)
2097 int_attr = lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl));
2098 if (int_attr != NULL_TREE)
2100 tree intr_vector = TREE_VALUE (int_attr);
2102 if (intr_vector != NULL_TREE)
2106 intr_vector = TREE_VALUE (intr_vector);
2108 /* The interrupt attribute has a vector value. Turn this into a
2109 section name, switch to that section and put the address of
2110 the current function into that vector slot. Note msp430_attr()
2111 has already verified the vector name for us. */
2112 if (TREE_CODE (intr_vector) == STRING_CST)
2113 sprintf (buf, "__interrupt_vector_%.80s",
2114 TREE_STRING_POINTER (intr_vector));
2115 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2116 sprintf (buf, "__interrupt_vector_%u",
2117 (unsigned int) TREE_INT_CST_LOW (intr_vector));
2119 switch_to_section (get_section (buf, SECTION_CODE, decl));
2120 fputs ("\t.word\t", file);
2121 assemble_name (file, name);
2127 switch_to_section (function_section (decl));
2128 ASM_OUTPUT_TYPE_DIRECTIVE(file, name, "function");
2129 ASM_OUTPUT_FUNCTION_LABEL (file, name, decl);
2132 static const char * const lower_prefix = ".lower";
2133 static const char * const upper_prefix = ".upper";
2134 static const char * const either_prefix = ".either";
2136 /* Generate a prefix for a section name, based upon
2137 the region into which the object should be placed. */
2140 gen_prefix (tree decl)
2142 if (DECL_ONE_ONLY (decl))
2145 /* If the user has specified a particular section then do not use any prefix. */
2146 if (has_attr ("section", decl))
2149 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2150 if (has_attr (ATTR_LOWER, decl))
2151 return lower_prefix;
2153 /* If we are compiling for the MSP430 then we do not support the upper region. */
2157 if (has_attr (ATTR_UPPER, decl))
2158 return upper_prefix;
2160 if (has_attr (ATTR_EITHER, decl))
2161 return either_prefix;
2163 if (TREE_CODE (decl) == FUNCTION_DECL)
2165 if (msp430_code_region == LOWER)
2166 return lower_prefix;
2168 if (msp430_code_region == UPPER)
2169 return upper_prefix;
2171 if (msp430_code_region == EITHER)
2172 return either_prefix;
2176 if (msp430_data_region == LOWER)
2177 return lower_prefix;
2179 if (msp430_data_region == UPPER)
2180 return upper_prefix;
2182 if (msp430_data_region == EITHER)
2183 return either_prefix;
2189 static section * noinit_section;
2190 static section * persist_section;
2192 #undef TARGET_ASM_INIT_SECTIONS
2193 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2196 msp430_init_sections (void)
2198 noinit_section = get_unnamed_section (0, output_section_asm_op, ".section .noinit,\"aw\"");
2199 persist_section = get_unnamed_section (0, output_section_asm_op, ".section .persistent,\"aw\"");
2202 #undef TARGET_ASM_SELECT_SECTION
2203 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2206 msp430_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
2208 gcc_assert (decl != NULL_TREE);
2210 if (TREE_CODE (decl) == STRING_CST
2211 || TREE_CODE (decl) == CONSTRUCTOR
2212 || TREE_CODE (decl) == INTEGER_CST
2213 || TREE_CODE (decl) == VECTOR_CST
2214 || TREE_CODE (decl) == COMPLEX_CST)
2215 return default_select_section (decl, reloc, align);
2217 /* In large mode we must make sure that interrupt handlers are put into
2218 low memory as the vector table only accepts 16-bit addresses. */
2219 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2220 return get_section (".lowtext", SECTION_CODE | SECTION_WRITE , decl);
2222 const char * prefix = gen_prefix (decl);
2225 if (TREE_CODE (decl) == FUNCTION_DECL)
2226 return text_section;
2227 else if (has_attr (ATTR_NOINIT, decl))
2228 return noinit_section;
2229 else if (has_attr (ATTR_PERSIST, decl))
2230 return persist_section;
2232 return default_select_section (decl, reloc, align);
2236 switch (categorize_decl_for_section (decl, reloc))
2238 case SECCAT_TEXT: sec = ".text"; break;
2239 case SECCAT_DATA: sec = ".data"; break;
2240 case SECCAT_BSS: sec = ".bss"; break;
2241 case SECCAT_RODATA: sec = ".rodata"; break;
2243 case SECCAT_RODATA_MERGE_STR:
2244 case SECCAT_RODATA_MERGE_STR_INIT:
2245 case SECCAT_RODATA_MERGE_CONST:
2246 case SECCAT_SRODATA:
2247 case SECCAT_DATA_REL:
2248 case SECCAT_DATA_REL_LOCAL:
2249 case SECCAT_DATA_REL_RO:
2250 case SECCAT_DATA_REL_RO_LOCAL:
2255 return default_select_section (decl, reloc, align);
2261 const char * dec_name = DECL_SECTION_NAME (decl);
2262 char * name = ACONCAT ((prefix, sec, dec_name, NULL));
2264 return get_named_section (decl, name, 0);
2267 #undef TARGET_ASM_FUNCTION_SECTION
2268 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2271 msp430_function_section (tree decl, enum node_frequency freq, bool startup, bool exit)
2275 gcc_assert (DECL_SECTION_NAME (decl) != NULL);
2276 name = DECL_SECTION_NAME (decl);
2278 const char * prefix = gen_prefix (decl);
2280 || strncmp (name, prefix, strlen (prefix)) == 0)
2281 return default_function_section (decl, freq, startup, exit);
2283 name = ACONCAT ((prefix, name, NULL));
2284 return get_named_section (decl, name, 0);
2287 #undef TARGET_SECTION_TYPE_FLAGS
2288 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2291 msp430_section_type_flags (tree decl, const char * name, int reloc)
2293 if (strncmp (name, lower_prefix, strlen (lower_prefix)) == 0)
2294 name += strlen (lower_prefix);
2295 else if (strncmp (name, upper_prefix, strlen (upper_prefix)) == 0)
2296 name += strlen (upper_prefix);
2297 else if (strncmp (name, either_prefix, strlen (either_prefix)) == 0)
2298 name += strlen (either_prefix);
2299 else if (strcmp (name, ".noinit") == 0)
2300 return SECTION_WRITE | SECTION_BSS | SECTION_NOTYPE;
2301 else if (strcmp (name, ".persistent") == 0)
2302 return SECTION_WRITE | SECTION_NOTYPE;
2304 return default_section_type_flags (decl, name, reloc);
2307 #undef TARGET_ASM_UNIQUE_SECTION
2308 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2311 msp430_unique_section (tree decl, int reloc)
2313 gcc_assert (decl != NULL_TREE);
2315 /* In large mode we must make sure that interrupt handlers are put into
2316 low memory as the vector table only accepts 16-bit addresses. */
2317 if (TARGET_LARGE && TREE_CODE (decl) == FUNCTION_DECL && is_interrupt_func (decl))
2319 set_decl_section_name (decl, ".lowtext");
2323 default_unique_section (decl, reloc);
2325 const char * prefix;
2327 if ( TREE_CODE (decl) == STRING_CST
2328 || TREE_CODE (decl) == CONSTRUCTOR
2329 || TREE_CODE (decl) == INTEGER_CST
2330 || TREE_CODE (decl) == VECTOR_CST
2331 || TREE_CODE (decl) == COMPLEX_CST
2332 || (prefix = gen_prefix (decl)) == NULL
2336 const char * dec_name = DECL_SECTION_NAME (decl);
2337 char * name = ACONCAT ((prefix, dec_name, NULL));
2339 set_decl_section_name (decl, name);
2342 /* Emit a declaration of a common symbol.
2343 If a data region is in use then put the symbol into the
2344 equivalent .bss section instead. */
2347 msp430_output_aligned_decl_common (FILE * stream,
2350 unsigned HOST_WIDE_INT size,
2353 if (msp430_data_region == ANY)
2355 fprintf (stream, COMMON_ASM_OP);
2356 assemble_name (stream, name);
2357 fprintf (stream, "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n",
2358 size, align / BITS_PER_UNIT);
2365 sec = msp430_select_section (decl, 0, align);
2367 switch (msp430_data_region)
2369 case UPPER: sec = get_named_section (NULL, ".upper.bss", 0); break;
2370 case LOWER: sec = get_named_section (NULL, ".lower.bss", 0); break;
2371 case EITHER: sec = get_named_section (NULL, ".either.bss", 0); break;
2375 gcc_assert (sec != NULL);
2377 switch_to_section (sec);
2378 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
2379 targetm.asm_out.globalize_label (stream, name);
2380 ASM_WEAKEN_LABEL (stream, name);
2381 ASM_OUTPUT_LABEL (stream, name);
2382 ASM_OUTPUT_SKIP (stream, size ? size : 1);
2387 msp430_do_not_relax_short_jumps (void)
2389 /* When placing code into "either" low or high memory we do not want the linker
2390 to grow the size of sections, which it can do if it is encounters a branch to
2391 a label that is too far away. So we tell the cbranch patterns to avoid using
2392 short jumps when there is a chance that the instructions will end up in a low
2395 msp430_code_region == EITHER
2396 || msp430_code_region == LOWER
2397 || has_attr (ATTR_EITHER, current_function_decl)
2398 || has_attr (ATTR_LOWER, current_function_decl);
2403 MSP430_BUILTIN_BIC_SR,
2404 MSP430_BUILTIN_BIS_SR,
2405 MSP430_BUILTIN_DELAY_CYCLES,
2409 static GTY(()) tree msp430_builtins [(int) MSP430_BUILTIN_max];
2412 msp430_init_builtins (void)
2414 tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
2415 tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
2417 msp430_builtins[MSP430_BUILTIN_BIC_SR] =
2418 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
2419 MSP430_BUILTIN_BIC_SR, BUILT_IN_MD, NULL, NULL_TREE);
2421 msp430_builtins[MSP430_BUILTIN_BIS_SR] =
2422 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
2423 MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
2425 msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
2426 add_builtin_function ( "__delay_cycles", void_ftype_longlong,
2427 MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
2431 msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
2435 case MSP430_BUILTIN_BIC_SR:
2436 case MSP430_BUILTIN_BIS_SR:
2437 case MSP430_BUILTIN_DELAY_CYCLES:
2438 return msp430_builtins[code];
2440 return error_mark_node;
2444 /* These constants are really register reads, which are faster than
2445 regular constants. */
2447 cg_magic_constant (HOST_WIDE_INT c)
2465 msp430_expand_delay_cycles (rtx arg)
2467 HOST_WIDE_INT i, c, n;
2468 /* extra cycles for MSP430X instructions */
2469 #define CYCX(M,X) (msp430x ? (X) : (M))
2471 if (GET_CODE (arg) != CONST_INT)
2473 error ("__delay_cycles() only takes constant arguments");
2479 if (HOST_BITS_PER_WIDE_INT > 32)
2483 error ("__delay_cycles only takes non-negative cycle counts.");
2488 emit_insn (gen_delay_cycles_start (arg));
2490 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2491 if (c > 3 * 0xffff + CYCX (7, 10))
2494 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2495 if (c >= 0x10000 * 7 + CYCX (14, 16))
2498 c -= CYCX (14, 16) + 7 * 0x10000;
2501 if ((unsigned long long) i > 0xffffffffULL)
2503 error ("__delay_cycles is limited to 32-bit loop counts.");
2509 i = (c - CYCX (14, 16)) / 7;
2510 c -= CYCX (14, 16) + i * 7;
2513 if (cg_magic_constant (i & 0xffff))
2515 if (cg_magic_constant ((i >> 16) & 0xffff))
2519 emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
2521 emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
2524 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2528 i = (c - CYCX (7, 10)) / 3;
2529 c -= CYCX (7, 10) + i * 3;
2531 if (cg_magic_constant (i))
2535 emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
2537 emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
2542 emit_insn (gen_delay_cycles_2 ());
2548 emit_insn (gen_delay_cycles_1 ());
2552 emit_insn (gen_delay_cycles_end (arg));
2558 msp430_expand_builtin (tree exp,
2559 rtx target ATTRIBUTE_UNUSED,
2560 rtx subtarget ATTRIBUTE_UNUSED,
2561 machine_mode mode ATTRIBUTE_UNUSED,
2562 int ignore ATTRIBUTE_UNUSED)
2564 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
2565 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2566 rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
2568 if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
2569 return msp430_expand_delay_cycles (arg1);
2571 if (! msp430_is_interrupt_func ())
2573 error ("MSP430 builtin functions only work inside interrupt handlers");
2577 if (! REG_P (arg1) && ! CONSTANT_P (arg1))
2578 arg1 = force_reg (mode, arg1);
2582 case MSP430_BUILTIN_BIC_SR: emit_insn (gen_bic_SR (arg1)); break;
2583 case MSP430_BUILTIN_BIS_SR: emit_insn (gen_bis_SR (arg1)); break;
2585 internal_error ("bad builtin code");
2591 #undef TARGET_INIT_BUILTINS
2592 #define TARGET_INIT_BUILTINS msp430_init_builtins
2594 #undef TARGET_EXPAND_BUILTIN
2595 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2597 #undef TARGET_BUILTIN_DECL
2598 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2601 msp430_expand_prologue (void)
2605 /* Always use stack_pointer_rtx instead of calling
2606 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2607 that there is a single rtx representing the stack pointer,
2608 namely stack_pointer_rtx, and uses == to recognize it. */
2609 rtx sp = stack_pointer_rtx;
2612 if (is_naked_func ())
2614 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2615 examines the output of the gen_prologue() function. */
2616 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2620 emit_insn (gen_prologue_start_marker ());
2622 if (is_critical_func ())
2624 emit_insn (gen_push_intr_state ());
2625 emit_insn (gen_disable_interrupts ());
2627 else if (is_reentrant_func ())
2628 emit_insn (gen_disable_interrupts ());
2630 if (!cfun->machine->computed)
2631 msp430_compute_frame_info ();
2633 if (flag_stack_usage_info)
2634 current_function_static_stack_size = cfun->machine->framesize;
2636 if (crtl->args.pretend_args_size)
2640 gcc_assert (crtl->args.pretend_args_size == 2);
2642 p = emit_insn (gen_grow_and_swap ());
2644 /* Document the stack decrement... */
2645 note = F (gen_rtx_SET (stack_pointer_rtx,
2646 gen_rtx_MINUS (Pmode, stack_pointer_rtx, GEN_INT (2))));
2647 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2649 /* ...and the establishment of a new location for the return address. */
2650 note = F (gen_rtx_SET (gen_rtx_MEM (Pmode,
2651 gen_rtx_PLUS (Pmode,
2655 add_reg_note (p, REG_CFA_OFFSET, note);
2659 for (i = 15; i >= 4; i--)
2660 if (cfun->machine->need_to_save [i])
2665 for (seq = i - 1; seq >= 4 && cfun->machine->need_to_save[seq]; seq --)
2671 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2672 p = F (emit_insn (gen_pushm (gen_rtx_REG (Pmode, i),
2675 note = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
2677 XVECEXP (note, 0, 0)
2678 = F (gen_rtx_SET (stack_pointer_rtx,
2679 gen_rtx_PLUS (Pmode,
2681 GEN_INT (count * (TARGET_LARGE ? -4 : -2)))));
2683 /* *sp-- = R[i-j] */
2687 for (j = 0; j < count; j ++)
2690 int ofs = (count - j - 1) * (TARGET_LARGE ? 4 : 2);
2693 addr = gen_rtx_PLUS (Pmode, sp, GEN_INT (ofs));
2695 addr = stack_pointer_rtx;
2697 XVECEXP (note, 0, j + 1) =
2698 F (gen_rtx_SET (gen_rtx_MEM (Pmode, addr),
2699 gen_rtx_REG (Pmode, i - j)) );
2702 add_reg_note (p, REG_FRAME_RELATED_EXPR, note);
2706 F (emit_insn (gen_push (gen_rtx_REG (Pmode, i))));
2709 if (frame_pointer_needed)
2710 F (emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM), sp));
2712 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2714 increment_stack (- fs);
2716 emit_insn (gen_prologue_end_marker ());
2720 msp430_expand_epilogue (int is_eh)
2726 if (is_naked_func ())
2728 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2729 examines the output of the gen_epilogue() function. */
2730 emit_insn (gen_rtx_CLOBBER (VOIDmode, GEN_INT (0)));
2734 if (cfun->machine->need_to_save [10])
2736 /* Check for a helper function. */
2737 helper_n = 7; /* For when the loop below never sees a match. */
2738 for (i = 9; i >= 4; i--)
2739 if (!cfun->machine->need_to_save [i])
2743 if (cfun->machine->need_to_save [i])
2752 emit_insn (gen_epilogue_start_marker ());
2754 if (cfun->decl && strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun->decl)), "main") == 0)
2755 emit_insn (gen_msp430_refsym_need_exit ());
2757 if (is_wakeup_func ())
2758 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2759 status register current residing on the stack. When this function
2760 executes its RETI instruction the SR will be updated with this saved
2761 value, thus ensuring that the processor is woken up from any low power
2762 state in which it may be residing. */
2763 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2765 fs = cfun->machine->framesize_locals + cfun->machine->framesize_outgoing;
2767 increment_stack (fs);
2771 /* We need to add the right "SP" register save just after the
2772 regular ones, so that when we pop it off we're in the EH
2773 return frame, not this one. This overwrites our own return
2774 address, but we're not going to be returning anyway. */
2775 rtx r12 = gen_rtx_REG (Pmode, 12);
2776 rtx (*addPmode)(rtx, rtx, rtx) = TARGET_LARGE ? gen_addpsi3 : gen_addhi3;
2778 /* R12 will hold the new SP. */
2779 i = cfun->machine->framesize_regs;
2780 emit_move_insn (r12, stack_pointer_rtx);
2781 emit_insn (addPmode (r12, r12, EH_RETURN_STACKADJ_RTX));
2782 emit_insn (addPmode (r12, r12, GEN_INT (i)));
2783 emit_move_insn (gen_rtx_MEM (Pmode, plus_constant (Pmode, stack_pointer_rtx, i)), r12);
2786 for (i = 4; i <= 15; i++)
2787 if (cfun->machine->need_to_save [i])
2791 for (seq = i + 1; seq <= 15 && cfun->machine->need_to_save[seq]; seq ++)
2797 /* Note: With TARGET_LARGE we still use
2798 POPM as POPX.A is two bytes bigger. */
2799 emit_insn (gen_popm (stack_pointer_rtx, GEN_INT (seq - 1),
2803 else if (i == 11 - helper_n
2804 && ! msp430_is_interrupt_func ()
2805 && ! is_reentrant_func ()
2806 && ! is_critical_func ()
2807 && crtl->args.pretend_args_size == 0
2808 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2812 emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
2816 emit_insn (gen_pop (gen_rtx_REG (Pmode, i)));
2821 /* Also pop SP, which puts us into the EH return frame. Except
2822 that you can't "pop" sp, you have to just load it off the
2824 emit_move_insn (stack_pointer_rtx, gen_rtx_MEM (Pmode, stack_pointer_rtx));
2827 if (crtl->args.pretend_args_size)
2828 emit_insn (gen_swap_and_shrink ());
2830 if (is_critical_func ())
2831 emit_insn (gen_pop_intr_state ());
2832 else if (is_reentrant_func ())
2833 emit_insn (gen_enable_interrupts ());
2835 emit_jump_insn (gen_msp_return ());
2838 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2839 m32c_emit_eh_epilogue. */
2841 msp430_eh_return_stackadj_rtx (void)
2843 if (!cfun->machine->eh_stack_adjust)
2847 sa = gen_rtx_REG (Pmode, 15);
2848 cfun->machine->eh_stack_adjust = sa;
2850 return cfun->machine->eh_stack_adjust;
2853 /* This function is called before reload, to "fix" the stack in
2854 preparation for an EH return. */
2856 msp430_expand_eh_return (rtx eh_handler)
2858 /* These are all Pmode */
2859 rtx ap, sa, ra, tmp;
2861 ap = arg_pointer_rtx;
2862 sa = msp430_eh_return_stackadj_rtx ();
2866 tmp = gen_rtx_PLUS (Pmode, ap, sa);
2867 tmp = plus_constant (Pmode, tmp, TARGET_LARGE ? -4 : -2);
2868 tmp = gen_rtx_MEM (Pmode, tmp);
2869 emit_move_insn (tmp, ra);
2872 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2873 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2875 msp430_init_dwarf_reg_sizes_extra (tree address)
2878 rtx addr = expand_normal (address);
2879 rtx mem = gen_rtx_MEM (BLKmode, addr);
2881 /* This needs to match msp430_unwind_word_mode (above). */
2885 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2887 unsigned int dnum = DWARF_FRAME_REGNUM (i);
2888 unsigned int rnum = DWARF2_FRAME_REG_OUT (dnum, 1);
2890 if (rnum < DWARF_FRAME_REGISTERS)
2892 HOST_WIDE_INT offset = rnum * GET_MODE_SIZE (QImode);
2894 emit_move_insn (adjust_address (mem, QImode, offset),
2895 gen_int_mode (4, QImode));
2900 /* This is a list of MD patterns that implement fixed-count shifts. */
2906 rtx (*genfunc)(rtx,rtx);
2908 const_shift_helpers[] =
2910 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2912 CSH ("slli", 1, 1, slli_1),
2913 CSH ("slll", 1, 1, slll_1),
2914 CSH ("slll", 2, 1, slll_2),
2916 CSH ("srai", 1, 0, srai_1),
2917 CSH ("sral", 1, 0, sral_1),
2918 CSH ("sral", 2, 0, sral_2),
2920 CSH ("srll", 1, 0, srll_1),
2921 CSH ("srll", 2, 1, srll_2x),
2926 /* The MSP430 ABI defines a number of helper functions that should be
2927 used for, for example, 32-bit shifts. This function is called to
2928 emit such a function, using the table above to optimize some
2931 msp430_expand_helper (rtx *operands, const char *helper_name, bool const_variants)
2934 char *helper_const = NULL;
2937 machine_mode arg0mode = GET_MODE (operands[0]);
2938 machine_mode arg1mode = GET_MODE (operands[1]);
2939 machine_mode arg2mode = GET_MODE (operands[2]);
2940 int have_430x = msp430x ? 1 : 0;
2942 if (CONST_INT_P (operands[2]))
2946 for (i=0; const_shift_helpers[i].name; i++)
2948 if (const_shift_helpers[i].need_430x <= have_430x
2949 && strcmp (helper_name, const_shift_helpers[i].name) == 0
2950 && INTVAL (operands[2]) == const_shift_helpers[i].count)
2952 emit_insn (const_shift_helpers[i].genfunc (operands[0], operands[1]));
2958 if (arg1mode == VOIDmode)
2959 arg1mode = arg0mode;
2960 if (arg2mode == VOIDmode)
2961 arg2mode = arg0mode;
2963 if (arg1mode == SImode)
2970 && CONST_INT_P (operands[2])
2971 && INTVAL (operands[2]) >= 1
2972 && INTVAL (operands[2]) <= 15)
2974 /* Note that the INTVAL is limited in value and length by the conditional above. */
2975 int len = strlen (helper_name) + 4;
2976 helper_const = (char *) xmalloc (len);
2977 snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
2980 emit_move_insn (gen_rtx_REG (arg1mode, 12),
2983 emit_move_insn (gen_rtx_REG (arg2mode, arg2),
2986 c = gen_call_value_internal (gen_rtx_REG (arg0mode, 12),
2987 gen_rtx_SYMBOL_REF (VOIDmode, helper_const ? helper_const : helper_name),
2989 c = emit_call_insn (c);
2990 RTL_CONST_CALL_P (c) = 1;
2993 use_regs (&f, 12, arg1sz);
2995 use_regs (&f, arg2, 1);
2996 add_function_usage_to (c, f);
2998 emit_move_insn (operands[0],
2999 gen_rtx_REG (arg0mode, 12));
3002 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3004 msp430_fixup_compare_operands (machine_mode my_mode, rtx * operands)
3006 /* constants we're looking for, not constants which are allowed. */
3007 int const_op_idx = 1;
3009 if (msp430_reversible_cmp_operator (operands[0], VOIDmode))
3012 if (GET_CODE (operands[const_op_idx]) != REG
3013 && GET_CODE (operands[const_op_idx]) != MEM)
3014 operands[const_op_idx] = copy_to_mode_reg (my_mode, operands[const_op_idx]);
3017 /* Simplify_gen_subreg() doesn't handle memory references the way we
3018 need it to below, so we use this function for when we must get a
3019 valid subreg in a "natural" state. */
3021 msp430_subreg (machine_mode mode, rtx r, machine_mode omode, int byte)
3025 if (GET_CODE (r) == SUBREG
3026 && SUBREG_BYTE (r) == 0)
3028 rtx ireg = SUBREG_REG (r);
3029 machine_mode imode = GET_MODE (ireg);
3031 /* special case for (HI (SI (PSI ...), 0)) */
3032 if (imode == PSImode
3035 rv = gen_rtx_SUBREG (mode, ireg, byte);
3037 rv = simplify_gen_subreg (mode, ireg, imode, byte);
3039 else if (GET_CODE (r) == MEM)
3040 rv = adjust_address (r, mode, byte);
3041 else if (GET_CODE (r) == SYMBOL_REF
3042 && (byte == 0 || byte == 2)
3045 rv = gen_rtx_ZERO_EXTRACT (HImode, r, GEN_INT (16), GEN_INT (8*byte));
3046 rv = gen_rtx_CONST (HImode, r);
3049 rv = simplify_gen_subreg (mode, r, omode, byte);
3057 /* Called by movsi_x to generate the HImode operands. */
3059 msp430_split_movsi (rtx *operands)
3061 rtx op00, op02, op10, op12;
3063 op00 = msp430_subreg (HImode, operands[0], SImode, 0);
3064 op02 = msp430_subreg (HImode, operands[0], SImode, 2);
3066 if (GET_CODE (operands[1]) == CONST
3067 || GET_CODE (operands[1]) == SYMBOL_REF)
3069 op10 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (0));
3070 op10 = gen_rtx_CONST (HImode, op10);
3071 op12 = gen_rtx_ZERO_EXTRACT (HImode, operands[1], GEN_INT (16), GEN_INT (16));
3072 op12 = gen_rtx_CONST (HImode, op12);
3076 op10 = msp430_subreg (HImode, operands[1], SImode, 0);
3077 op12 = msp430_subreg (HImode, operands[1], SImode, 2);
3080 if (rtx_equal_p (operands[0], operands[1]))
3087 else if (rtx_equal_p (op00, op12)
3088 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3089 || (REG_P (op00) && reg_mentioned_p (op00, op10))
3090 /* Or storing (rN) into mem (rN). */
3091 || (REG_P (op10) && reg_mentioned_p (op10, op00))
3109 /* The MSPABI specifies the names of various helper functions, many of
3110 which are compatible with GCC's helpers. This table maps the GCC
3111 name to the MSPABI name. */
3114 char const * const gcc_name;
3115 char const * const ti_name;
3117 helper_function_name_mappings [] =
3119 /* Floating point to/from integer conversions. */
3120 { "__truncdfsf2", "__mspabi_cvtdf" },
3121 { "__extendsfdf2", "__mspabi_cvtfd" },
3122 { "__fixdfhi", "__mspabi_fixdi" },
3123 { "__fixdfsi", "__mspabi_fixdli" },
3124 { "__fixdfdi", "__mspabi_fixdlli" },
3125 { "__fixunsdfhi", "__mspabi_fixdu" },
3126 { "__fixunsdfsi", "__mspabi_fixdul" },
3127 { "__fixunsdfdi", "__mspabi_fixdull" },
3128 { "__fixsfhi", "__mspabi_fixfi" },
3129 { "__fixsfsi", "__mspabi_fixfli" },
3130 { "__fixsfdi", "__mspabi_fixflli" },
3131 { "__fixunsfhi", "__mspabi_fixfu" },
3132 { "__fixunsfsi", "__mspabi_fixful" },
3133 { "__fixunsfdi", "__mspabi_fixfull" },
3134 { "__floathisf", "__mspabi_fltif" },
3135 { "__floatsisf", "__mspabi_fltlif" },
3136 { "__floatdisf", "__mspabi_fltllif" },
3137 { "__floathidf", "__mspabi_fltid" },
3138 { "__floatsidf", "__mspabi_fltlid" },
3139 { "__floatdidf", "__mspabi_fltllid" },
3140 { "__floatunhisf", "__mspabi_fltuf" },
3141 { "__floatunsisf", "__mspabi_fltulf" },
3142 { "__floatundisf", "__mspabi_fltullf" },
3143 { "__floatunhidf", "__mspabi_fltud" },
3144 { "__floatunsidf", "__mspabi_fltuld" },
3145 { "__floatundidf", "__mspabi_fltulld" },
3147 /* Floating point comparisons. */
3148 /* GCC uses individual functions for each comparison, TI uses one
3149 compare <=> function. */
3151 /* Floating point arithmatic */
3152 { "__adddf3", "__mspabi_addd" },
3153 { "__addsf3", "__mspabi_addf" },
3154 { "__divdf3", "__mspabi_divd" },
3155 { "__divsf3", "__mspabi_divf" },
3156 { "__muldf3", "__mspabi_mpyd" },
3157 { "__mulsf3", "__mspabi_mpyf" },
3158 { "__subdf3", "__mspabi_subd" },
3159 { "__subsf3", "__mspabi_subf" },
3160 /* GCC does not use helper functions for negation */
3162 /* Integer multiply, divide, remainder. */
3163 { "__mulhi3", "__mspabi_mpyi" },
3164 { "__mulsi3", "__mspabi_mpyl" },
3165 { "__muldi3", "__mspabi_mpyll" },
3167 /* Clarify signed vs unsigned first. */
3168 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3169 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3172 { "__divhi3", "__mspabi_divi" },
3173 { "__divsi3", "__mspabi_divli" },
3174 { "__divdi3", "__mspabi_divlli" },
3175 { "__udivhi3", "__mspabi_divu" },
3176 { "__udivsi3", "__mspabi_divul" },
3177 { "__udivdi3", "__mspabi_divull" },
3178 { "__modhi3", "__mspabi_remi" },
3179 { "__modsi3", "__mspabi_remli" },
3180 { "__moddi3", "__mspabi_remlli" },
3181 { "__umodhi3", "__mspabi_remu" },
3182 { "__umodsi3", "__mspabi_remul" },
3183 { "__umoddi3", "__mspabi_remull" },
3185 /* Bitwise operations. */
3186 /* Rotation - no rotation support yet. */
3187 /* Logical left shift - gcc already does these itself. */
3188 /* Arithmetic left shift - gcc already does these itself. */
3189 /* Arithmetic right shift - gcc already does these itself. */
3194 /* Returns true if the current MCU supports an F5xxx series
3195 hardware multiper. */
3198 msp430_use_f5_series_hwmult (void)
3200 static const char * cached_match = NULL;
3201 static bool cached_result;
3203 if (msp430_hwmult_type == F5SERIES)
3206 if (target_mcu == NULL || msp430_hwmult_type != AUTO)
3209 if (target_mcu == cached_match)
3210 return cached_result;
3212 cached_match = target_mcu;
3214 if (strncasecmp (target_mcu, "msp430f5", 8) == 0)
3215 return cached_result = true;
3216 if (strncasecmp (target_mcu, "msp430fr5", 9) == 0)
3217 return cached_result = true;
3218 if (strncasecmp (target_mcu, "msp430f6", 8) == 0)
3219 return cached_result = true;
3223 /* FIXME: This array is alpha sorted - we could use a binary search. */
3224 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3225 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3226 return cached_result = msp430_mcu_data[i].hwmpy == 8;
3228 return cached_result = false;
3231 /* Returns true if the current MCU has a second generation
3232 32-bit hardware multiplier. */
3235 use_32bit_hwmult (void)
3237 static const char * cached_match = NULL;
3238 static bool cached_result;
3241 if (msp430_hwmult_type == LARGE)
3244 if (target_mcu == NULL || msp430_hwmult_type != AUTO)
3247 if (target_mcu == cached_match)
3248 return cached_result;
3250 cached_match = target_mcu;
3252 /* FIXME: This array is alpha sorted - we could use a binary search. */
3253 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3254 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3255 return cached_result = msp430_mcu_data[i].hwmpy == 4;
3257 return cached_result = false;
3260 /* Returns true if the current MCU does not have a
3261 hardware multiplier of any kind. */
3264 msp430_no_hwmult (void)
3266 static const char * cached_match = NULL;
3267 static bool cached_result;
3270 if (msp430_hwmult_type == NONE)
3273 if (msp430_hwmult_type != AUTO)
3276 if (target_mcu == NULL)
3279 if (target_mcu == cached_match)
3280 return cached_result;
3282 cached_match = target_mcu;
3284 /* FIXME: This array is alpha sorted - we could use a binary search. */
3285 for (i = ARRAY_SIZE (msp430_mcu_data); i--;)
3286 if (strcasecmp (target_mcu, msp430_mcu_data[i].name) == 0)
3287 return cached_result = msp430_mcu_data[i].hwmpy == 0;
3289 /* If we do not recognise the MCU name, we assume that it does not support
3290 any kind of hardware multiply - this is the safest assumption to make. */
3291 return cached_result = true;
3294 /* This function does the same as the default, but it will replace GCC
3295 function names with the MSPABI-specified ones. */
3298 msp430_output_labelref (FILE *file, const char *name)
3302 for (i = 0; helper_function_name_mappings [i].gcc_name; i++)
3303 if (strcmp (helper_function_name_mappings [i].gcc_name, name) == 0)
3305 name = helper_function_name_mappings [i].ti_name;
3309 /* If we have been given a specific MCU name then we may be
3310 able to make use of its hardware multiply capabilities. */
3311 if (msp430_hwmult_type != NONE)
3313 if (strcmp ("__mspabi_mpyi", name) == 0)
3315 if (msp430_use_f5_series_hwmult ())
3316 name = "__mulhi2_f5";
3317 else if (! msp430_no_hwmult ())
3320 else if (strcmp ("__mspabi_mpyl", name) == 0)
3322 if (msp430_use_f5_series_hwmult ())
3323 name = "__mulsi2_f5";
3324 else if (use_32bit_hwmult ())
3325 name = "__mulsi2_hw32";
3326 else if (! msp430_no_hwmult ())
3334 /* Common code for msp430_print_operand... */
3337 msp430_print_operand_raw (FILE * file, rtx op)
3341 switch (GET_CODE (op))
3344 fprintf (file, "%s", reg_names [REGNO (op)]);
3350 fprintf (file, "%#" HOST_WIDE_INT_PRINT "x", i);
3352 fprintf (file, "%" HOST_WIDE_INT_PRINT "d", i);
3360 output_addr_const (file, op);
3364 print_rtl (file, op);
3369 #undef TARGET_PRINT_OPERAND_ADDRESS
3370 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3372 /* Output to stdio stream FILE the assembler syntax for an
3373 instruction operand that is a memory reference whose address
3377 msp430_print_operand_addr (FILE * file, machine_mode /*mode*/, rtx addr)
3379 switch (GET_CODE (addr))
3382 msp430_print_operand_raw (file, XEXP (addr, 1));
3383 gcc_assert (REG_P (XEXP (addr, 0)));
3384 fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
3388 fprintf (file, "@");
3395 fprintf (file, "&");
3402 msp430_print_operand_raw (file, addr);
3405 #undef TARGET_PRINT_OPERAND
3406 #define TARGET_PRINT_OPERAND msp430_print_operand
3408 /* A low 16-bits of int/lower of register pair
3409 B high 16-bits of int/higher of register pair
3410 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3411 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3412 H like %B (for backwards compatibility)
3414 J an integer without a # prefix
3415 L like %A (for backwards compatibility)
3416 O offset of the top of the stack
3417 Q like X but generates an A postfix
3418 R inverse of condition code, unsigned.
3419 X X instruction postfix in large mode
3422 b .B or .W or .A, depending upon the mode
3424 r inverse of condition code
3425 x like X but only for pointers. */
3428 msp430_print_operand (FILE * file, rtx op, int letter)
3432 /* We can't use c, n, a, or l. */
3436 gcc_assert (CONST_INT_P (op));
3437 /* Print the constant value, less one. */
3438 fprintf (file, "#%ld", INTVAL (op) - 1);
3441 gcc_assert (CONST_INT_P (op));
3442 /* Print the constant value, less four. */
3443 fprintf (file, "#%ld", INTVAL (op) - 4);
3446 if (GET_CODE (op) == CONST_INT)
3448 /* Inverse of constants */
3449 int i = INTVAL (op);
3450 fprintf (file, "%d", ~i);
3455 case 'r': /* Conditional jump where the condition is reversed. */
3456 switch (GET_CODE (op))
3458 case EQ: fprintf (file, "NE"); break;
3459 case NE: fprintf (file, "EQ"); break;
3460 case GEU: fprintf (file, "LO"); break;
3461 case LTU: fprintf (file, "HS"); break;
3462 case GE: fprintf (file, "L"); break;
3463 case LT: fprintf (file, "GE"); break;
3464 /* Assume these have reversed operands. */
3465 case GTU: fprintf (file, "HS"); break;
3466 case LEU: fprintf (file, "LO"); break;
3467 case GT: fprintf (file, "GE"); break;
3468 case LE: fprintf (file, "L"); break;
3470 msp430_print_operand_raw (file, op);
3474 case 'R': /* Conditional jump where the operands are reversed. */
3475 switch (GET_CODE (op))
3477 case GTU: fprintf (file, "LO"); break;
3478 case LEU: fprintf (file, "HS"); break;
3479 case GT: fprintf (file, "L"); break;
3480 case LE: fprintf (file, "GE"); break;
3482 msp430_print_operand_raw (file, op);
3486 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3487 gcc_assert (CONST_INT_P (op));
3488 fprintf (file, "#%d", 1 << INTVAL (op));
3491 switch (GET_MODE (op))
3493 case QImode: fprintf (file, ".B"); return;
3494 case HImode: fprintf (file, ".W"); return;
3495 case PSImode: fprintf (file, ".A"); return;
3496 case SImode: fprintf (file, ".A"); return;
3501 case 'L': /* Low half. */
3502 switch (GET_CODE (op))
3505 op = adjust_address (op, Pmode, 0);
3510 op = GEN_INT (INTVAL (op) & 0xffff);
3514 /* If you get here, figure out a test case :-) */
3519 case 'H': /* high half */
3520 switch (GET_CODE (op))
3523 op = adjust_address (op, Pmode, 2);
3526 op = gen_rtx_REG (Pmode, REGNO (op) + 1);
3529 op = GEN_INT (INTVAL (op) >> 16);
3533 /* If you get here, figure out a test case :-) */
3538 switch (GET_CODE (op))
3541 op = adjust_address (op, Pmode, 3);
3544 op = gen_rtx_REG (Pmode, REGNO (op) + 2);
3547 op = GEN_INT ((long long) INTVAL (op) >> 32);
3551 /* If you get here, figure out a test case :-) */
3556 switch (GET_CODE (op))
3559 op = adjust_address (op, Pmode, 4);
3562 op = gen_rtx_REG (Pmode, REGNO (op) + 3);
3565 op = GEN_INT ((long long) INTVAL (op) >> 48);
3569 /* If you get here, figure out a test case :-) */
3575 /* This is used to turn, for example, an ADD opcode into an ADDX
3576 opcode when we're using 20-bit addresses. */
3577 if (TARGET_LARGE || GET_MODE (op) == PSImode)
3578 fprintf (file, "X");
3579 /* We don't care which operand we use, but we want 'X' in the MD
3580 file, so we do it this way. */
3584 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3585 if (GET_MODE (op) == PSImode)
3586 fprintf (file, "X");
3590 /* Likewise, for BR -> BRA. */
3592 fprintf (file, "A");
3596 /* Computes the offset to the top of the stack for the current frame.
3597 This has to be done here rather than in, say, msp430_expand_builtin()
3598 because builtins are expanded before the frame layout is determined. */
3599 fprintf (file, "%d",
3600 msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
3601 - (TARGET_LARGE ? 4 : 2));
3605 gcc_assert (GET_CODE (op) == CONST_INT);
3609 output_operand_lossage ("invalid operand prefix");
3613 switch (GET_CODE (op))
3616 msp430_print_operand_raw (file, op);
3620 addr = XEXP (op, 0);
3621 msp430_print_operand_addr (file, GET_MODE (op), addr);
3625 if (GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT)
3628 switch (INTVAL (XEXP (op, 2)))
3631 fprintf (file, "#lo (");
3632 msp430_print_operand_raw (file, XEXP (op, 0));
3633 fprintf (file, ")");
3637 fprintf (file, "#hi (");
3638 msp430_print_operand_raw (file, XEXP (op, 0));
3639 fprintf (file, ")");
3643 output_operand_lossage ("invalid zero extract");
3653 fprintf (file, "#");
3654 msp430_print_operand_raw (file, op);
3657 case EQ: fprintf (file, "EQ"); break;
3658 case NE: fprintf (file, "NE"); break;
3659 case GEU: fprintf (file, "HS"); break;
3660 case LTU: fprintf (file, "LO"); break;
3661 case GE: fprintf (file, "GE"); break;
3662 case LT: fprintf (file, "L"); break;
3665 print_rtl (file, op);
3674 msp430_return_addr_rtx (int count)
3680 ra_size = TARGET_LARGE ? 4 : 2;
3681 if (crtl->args.pretend_args_size)
3684 return gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT (- ra_size)));
3688 msp430_incoming_return_addr_rtx (void)
3690 return gen_rtx_MEM (Pmode, stack_pointer_rtx);
3693 /* Instruction generation stuff. */
3695 /* Generate a sequence of instructions to sign-extend an HI
3696 value into an SI value. Handles the tricky case where
3697 we are overwriting the destination. */
3700 msp430x_extendhisi (rtx * operands)
3702 if (REGNO (operands[0]) == REGNO (operands[1]))
3703 /* Low word of dest == source word. */
3704 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3707 /* Note: This sequence is approximately the same length as invoking a helper
3708 function to perform the sign-extension, as in:
3712 CALL __mspabi_srai_15
3715 but this version does not involve any function calls or using argument
3716 registers, so it reduces register pressure. */
3717 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3719 if (REGNO (operands[0]) + 1 == REGNO (operands[1]))
3720 /* High word of dest == source word. */
3721 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3723 /* No overlap between dest and source. */
3724 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3727 /* Likewise for logical right shifts. */
3729 msp430x_logical_shift_right (rtx amount)
3731 /* The MSP430X's logical right shift instruction - RRUM - does
3732 not use an extension word, so we cannot encode a repeat count.
3733 Try various alternatives to work around this. If the count
3734 is in a register we are stuck, hence the assert. */
3735 gcc_assert (CONST_INT_P (amount));
3737 if (INTVAL (amount) <= 0
3738 || INTVAL (amount) >= 16)
3739 return "# nop logical shift.";
3741 if (INTVAL (amount) > 0
3742 && INTVAL (amount) < 5)
3743 return "rrum.w\t%2, %0"; /* Two bytes. */
3745 if (INTVAL (amount) > 4
3746 && INTVAL (amount) < 9)
3747 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3749 /* First we logically shift right by one. Now we know
3750 that the top bit is zero and we can use the arithmetic
3751 right shift instruction to perform the rest of the shift. */
3752 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3755 struct gcc_target targetm = TARGET_INITIALIZER;
3757 #include "gt-msp430.h"