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/devices-msp430.c
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 hwmult_name (unsigned int val
)
725 case 0: return "none";
726 case 1: return "16-bit";
727 case 2: return "16-bit";
728 case 4: return "32-bit";
729 case 8: return "32-bit (5xx)";
730 default: gcc_unreachable ();
735 msp430_option_override (void)
737 init_machine_status
= msp430_init_machine_status
;
741 /* gcc/common/config/msp430-common.c will have
742 already canonicalised the string in target_cpu. */
743 if (strcasecmp (target_cpu
, "msp430x") == 0)
745 else /* target_cpu == "msp430" - already handled by the front end. */
753 /* FIXME: If the array were alpha sorted, we could use a binary search. */
754 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
755 if (strcasecmp (msp430_mcu_data
[i
].name
, target_mcu
) == 0)
757 bool xisa
= msp430_mcu_data
[i
].revision
>= 1;
761 if (target_cpu
&& msp430x
!= xisa
)
762 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
763 target_mcu
, xisa
? "430X" : "430", msp430x
? "430X" : "430");
765 if (msp430_mcu_data
[i
].hwmpy
== 0
766 && msp430_hwmult_type
!= AUTO
767 && msp430_hwmult_type
!= NONE
)
768 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
770 msp430_hwmult_type
== SMALL
? "16-bit" : msp430_hwmult_type
== LARGE
? "32-bit" : "f5series");
771 else if (msp430_hwmult_type
== SMALL
772 && msp430_mcu_data
[i
].hwmpy
!= 1
773 && msp430_mcu_data
[i
].hwmpy
!= 2 )
774 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
775 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
776 else if (msp430_hwmult_type
== LARGE
&& msp430_mcu_data
[i
].hwmpy
!= 4)
777 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
778 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
779 else if (msp430_hwmult_type
== F5SERIES
&& msp430_mcu_data
[i
].hwmpy
!= 8)
780 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
781 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
790 if (msp430_hwmult_type
== AUTO
)
794 if (target_cpu
== NULL
)
796 "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.",
800 "Unrecognised MCU name '%s', assuming that it has no hardware multiply.\nUse the -mhwmult option to set this explicitly.",
804 msp430_hwmult_type
= NONE
;
806 else if (target_cpu
== NULL
)
810 "Unrecognised MCU name '%s', assuming that it just supports the MSP430 ISA.\nUse the -mcpu option to set the ISA explicitly.",
815 else if (msp430_warn_mcu
)
817 "Unrecognised MCU name '%s'.", target_mcu
);
821 /* The F5 series are all able to support the 430X ISA. */
822 if (target_cpu
== NULL
&& target_mcu
== NULL
&& msp430_hwmult_type
== F5SERIES
)
825 if (TARGET_LARGE
&& !msp430x
)
826 error ("-mlarge requires a 430X-compatible -mmcu=");
828 if (msp430_code_region
== UPPER
&& ! msp430x
)
829 error ("-mcode-region=upper requires 430X-compatible cpu");
830 if (msp430_data_region
== UPPER
&& ! msp430x
)
831 error ("-mdata-region=upper requires 430X-compatible cpu");
833 if (flag_exceptions
|| flag_non_call_exceptions
834 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
835 flag_omit_frame_pointer
= false;
837 flag_omit_frame_pointer
= true;
839 /* This is a hack to work around a problem with the newlib build
840 mechanism. Newlib always appends CFLAGS to the end of the GCC
841 command line and always sets -O2 in CFLAGS. Thus it is not
842 possible to build newlib with -Os enabled. Until now... */
843 if (TARGET_OPT_SPACE
&& optimize
< 3)
847 #undef TARGET_SCALAR_MODE_SUPPORTED_P
848 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
851 msp430_scalar_mode_supported_p (machine_mode m
)
853 if (m
== PSImode
&& msp430x
)
859 return default_scalar_mode_supported_p (m
);
866 #undef TARGET_MS_BITFIELD_LAYOUT_P
867 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
870 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
879 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
880 PSImode value, but not an SImode value. */
882 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
885 if (mode
== PSImode
&& msp430x
)
887 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
891 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
893 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
896 if (mode
== PSImode
&& msp430x
)
898 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
902 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
904 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
909 return msp430_hard_regno_nregs (regno
, mode
);
912 /* Implements HARD_REGNO_MODE_OK. */
914 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
917 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
920 /* Implements MODES_TIEABLE_P. */
922 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
924 if ((mode1
== PSImode
|| mode2
== SImode
)
925 || (mode1
== SImode
|| mode2
== PSImode
))
928 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
929 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
930 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
931 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
934 #undef TARGET_FRAME_POINTER_REQUIRED
935 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
938 msp430_frame_pointer_required (void)
943 #undef TARGET_CAN_ELIMINATE
944 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
947 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
948 const int to_reg ATTRIBUTE_UNUSED
)
953 /* Implements INITIAL_ELIMINATION_OFFSET. */
955 msp430_initial_elimination_offset (int from
, int to
)
957 int rv
= 0; /* As if arg to arg. */
959 msp430_compute_frame_info ();
963 case STACK_POINTER_REGNUM
:
964 rv
+= cfun
->machine
->framesize_outgoing
;
965 rv
+= cfun
->machine
->framesize_locals
;
967 case FRAME_POINTER_REGNUM
:
968 rv
+= cfun
->machine
->framesize_regs
;
969 /* Allow for the saved return address. */
970 rv
+= (TARGET_LARGE
? 4 : 2);
971 /* NB/ No need to allow for crtl->args.pretend_args_size.
972 GCC does that for us. */
980 case FRAME_POINTER_REGNUM
:
981 /* Allow for the fall through above. */
982 rv
-= (TARGET_LARGE
? 4 : 2);
983 rv
-= cfun
->machine
->framesize_regs
;
984 case ARG_POINTER_REGNUM
:
993 /* Named Address Space support */
996 /* Return the appropriate mode for a named address pointer. */
997 #undef TARGET_ADDR_SPACE_POINTER_MODE
998 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
999 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1000 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1003 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1008 case ADDR_SPACE_GENERIC
:
1010 case ADDR_SPACE_NEAR
:
1012 case ADDR_SPACE_FAR
:
1017 /* Function pointers are stored in unwind_word sized
1018 variables, so make sure that unwind_word is big enough. */
1019 #undef TARGET_UNWIND_WORD_MODE
1020 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1023 msp430_unwind_word_mode (void)
1025 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1026 return msp430x
? PSImode
: HImode
;
1029 /* Determine if one named address space is a subset of another. */
1030 #undef TARGET_ADDR_SPACE_SUBSET_P
1031 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1033 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1035 if (subset
== superset
)
1038 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1041 #undef TARGET_ADDR_SPACE_CONVERT
1042 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1043 /* Convert from one address space to another. */
1045 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1047 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1048 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1051 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1053 /* This is unpredictable, as we're truncating off usable address
1056 if (CONSTANT_P (op
))
1057 return gen_rtx_CONST (HImode
, op
);
1059 result
= gen_reg_rtx (HImode
);
1060 emit_insn (gen_truncpsihi2 (result
, op
));
1063 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1065 /* This always works. */
1067 if (CONSTANT_P (op
))
1068 return gen_rtx_CONST (PSImode
, op
);
1070 result
= gen_reg_rtx (PSImode
);
1071 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1078 /* Stack Layout and Calling Conventions. */
1080 /* For each function, we list the gcc version and the TI version on
1081 each line, where we're converting the function names. */
1082 static char const * const special_convention_function_names
[] =
1084 "__muldi3", "__mspabi_mpyll",
1085 "__udivdi3", "__mspabi_divull",
1086 "__umoddi3", "__mspabi_remull",
1087 "__divdi3", "__mspabi_divlli",
1088 "__moddi3", "__mspabi_remlli",
1092 "__adddf3", "__mspabi_addd",
1093 "__subdf3", "__mspabi_subd",
1094 "__muldf3", "__mspabi_mpyd",
1095 "__divdf3", "__mspabi_divd",
1100 /* TRUE if the function passed is a "speical" function. Special
1101 functions pass two DImode parameters in registers. */
1103 msp430_special_register_convention_p (const char *name
)
1107 for (i
= 0; special_convention_function_names
[i
]; i
++)
1108 if (! strcmp (name
, special_convention_function_names
[i
]))
1114 #undef TARGET_FUNCTION_VALUE_REGNO_P
1115 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1118 msp430_function_value_regno_p (unsigned int regno
)
1124 #undef TARGET_FUNCTION_VALUE
1125 #define TARGET_FUNCTION_VALUE msp430_function_value
1128 msp430_function_value (const_tree ret_type
,
1129 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1130 bool outgoing ATTRIBUTE_UNUSED
)
1132 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1135 #undef TARGET_LIBCALL_VALUE
1136 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1139 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1141 return gen_rtx_REG (mode
, 12);
1144 /* Implements INIT_CUMULATIVE_ARGS. */
1146 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1147 tree fntype ATTRIBUTE_UNUSED
,
1148 rtx libname ATTRIBUTE_UNUSED
,
1149 tree fndecl ATTRIBUTE_UNUSED
,
1150 int n_named_args ATTRIBUTE_UNUSED
)
1153 memset (ca
, 0, sizeof(*ca
));
1158 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1160 fname
= XSTR (libname
, 0);
1164 if (fname
&& msp430_special_register_convention_p (fname
))
1168 /* Helper function for argument passing; this function is the common
1169 code that determines where an argument will be passed. */
1171 msp430_evaluate_arg (cumulative_args_t cap
,
1173 const_tree type ATTRIBUTE_UNUSED
,
1176 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1177 int nregs
= GET_MODE_SIZE (mode
);
1186 if (mode
== PSImode
)
1189 nregs
= (nregs
+ 1) / 2;
1193 /* Function is passed two DImode operands, in R8:R11 and
1203 for (i
= 0; i
< 4; i
++)
1204 if (! ca
->reg_used
[i
])
1207 ca
->start_reg
= CA_FIRST_REG
+ i
;
1212 for (i
= 0; i
< 3; i
++)
1213 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1216 ca
->start_reg
= CA_FIRST_REG
+ i
;
1219 if (! ca
->reg_used
[3] && ca
->can_split
)
1223 ca
->start_reg
= CA_FIRST_REG
+ 3;
1230 if (! ca
->reg_used
[0]
1231 && ! ca
->reg_used
[1]
1232 && ! ca
->reg_used
[2]
1233 && ! ca
->reg_used
[3])
1236 ca
->start_reg
= CA_FIRST_REG
;
1243 #undef TARGET_PROMOTE_PROTOTYPES
1244 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1247 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1252 #undef TARGET_FUNCTION_ARG
1253 #define TARGET_FUNCTION_ARG msp430_function_arg
1256 msp430_function_arg (cumulative_args_t cap
,
1261 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1263 msp430_evaluate_arg (cap
, mode
, type
, named
);
1266 return gen_rtx_REG (mode
, ca
->start_reg
);
1271 #undef TARGET_ARG_PARTIAL_BYTES
1272 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1275 msp430_arg_partial_bytes (cumulative_args_t cap
,
1280 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1282 msp430_evaluate_arg (cap
, mode
, type
, named
);
1284 if (ca
->reg_count
&& ca
->mem_count
)
1285 return ca
->reg_count
* UNITS_PER_WORD
;
1290 #undef TARGET_PASS_BY_REFERENCE
1291 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1294 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1297 bool named ATTRIBUTE_UNUSED
)
1299 return (mode
== BLKmode
1300 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1301 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1304 #undef TARGET_CALLEE_COPIES
1305 #define TARGET_CALLEE_COPIES msp430_callee_copies
1308 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1309 machine_mode mode ATTRIBUTE_UNUSED
,
1310 const_tree type ATTRIBUTE_UNUSED
,
1311 bool named ATTRIBUTE_UNUSED
)
1316 #undef TARGET_FUNCTION_ARG_ADVANCE
1317 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1320 msp430_function_arg_advance (cumulative_args_t cap
,
1325 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1328 msp430_evaluate_arg (cap
, mode
, type
, named
);
1330 if (ca
->start_reg
>= CA_FIRST_REG
)
1331 for (i
= 0; i
< ca
->reg_count
; i
++)
1332 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1337 #undef TARGET_FUNCTION_ARG_BOUNDARY
1338 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1341 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1344 && int_size_in_bytes (type
) > 1)
1346 if (GET_MODE_BITSIZE (mode
) > 8)
1351 #undef TARGET_RETURN_IN_MEMORY
1352 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1355 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1357 machine_mode mode
= TYPE_MODE (ret_type
);
1360 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1361 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1364 if (GET_MODE_SIZE (mode
) > 8)
1370 #undef TARGET_GET_RAW_ARG_MODE
1371 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1374 msp430_get_raw_arg_mode (int regno
)
1376 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
1379 #undef TARGET_GET_RAW_RESULT_MODE
1380 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1383 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1388 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1389 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1391 #include "gimplify.h"
1394 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1397 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1398 unsigned HOST_WIDE_INT align
, boundary
;
1401 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1403 type
= build_pointer_type (type
);
1405 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1406 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1408 /* When we align parameter on stack for caller, if the parameter
1409 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1410 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1411 here with caller. */
1412 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1413 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1415 boundary
/= BITS_PER_UNIT
;
1417 /* Hoist the valist value into a temporary for the moment. */
1418 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1420 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1421 requires greater alignment, we must perform dynamic alignment. */
1422 if (boundary
> align
1423 && !integer_zerop (TYPE_SIZE (type
)))
1425 /* FIXME: This is where this function diverts from targhooks.c:
1426 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1427 if (! POINTER_TYPE_P (type
))
1429 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1430 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1431 gimplify_and_add (t
, pre_p
);
1433 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1434 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1436 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1437 gimplify_and_add (t
, pre_p
);
1443 /* If the actual alignment is less than the alignment of the type,
1444 adjust the type accordingly so that we don't assume strict alignment
1445 when dereferencing the pointer. */
1446 boundary
*= BITS_PER_UNIT
;
1447 if (boundary
< TYPE_ALIGN (type
))
1449 type
= build_variant_type_copy (type
);
1450 TYPE_ALIGN (type
) = boundary
;
1453 /* Compute the rounded size of the type. */
1454 type_size
= size_in_bytes (type
);
1455 rounded_size
= round_up (type_size
, align
);
1457 /* Reduce rounded_size so it's sharable with the postqueue. */
1458 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1463 /* Compute new value for AP. */
1464 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1465 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1466 gimplify_and_add (t
, pre_p
);
1468 addr
= fold_convert (build_pointer_type (type
), addr
);
1471 addr
= build_va_arg_indirect_ref (addr
);
1473 addr
= build_va_arg_indirect_ref (addr
);
1478 /* Addressing Modes */
1480 #undef TARGET_LEGITIMATE_ADDRESS_P
1481 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1484 reg_ok_for_addr (rtx r
, bool strict
)
1488 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1489 rn
= reg_renumber
[rn
];
1490 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1498 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1499 rtx x ATTRIBUTE_UNUSED
,
1500 bool strict ATTRIBUTE_UNUSED
)
1502 switch (GET_CODE (x
))
1508 if (REG_P (XEXP (x
, 0)))
1510 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1512 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1514 switch (GET_CODE (XEXP (x
, 1)))
1527 if (!reg_ok_for_addr (x
, strict
))
1540 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1541 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1544 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1547 addr_space_t as ATTRIBUTE_UNUSED
)
1549 return msp430_legitimate_address_p (mode
, x
, strict
);
1552 #undef TARGET_ASM_INTEGER
1553 #define TARGET_ASM_INTEGER msp430_asm_integer
1555 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1557 int c
= GET_CODE (x
);
1559 if (size
== 3 && GET_MODE (x
) == PSImode
)
1565 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1566 || c
== PLUS
|| c
== MINUS
)
1568 fprintf (asm_out_file
, "\t.long\t");
1569 output_addr_const (asm_out_file
, x
);
1570 fputc ('\n', asm_out_file
);
1575 return default_assemble_integer (x
, size
, aligned_p
);
1578 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1579 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1581 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1587 #undef TARGET_LEGITIMATE_CONSTANT_P
1588 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1591 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1593 return ! CONST_INT_P (x
)
1595 /* GCC does not know the width of the PSImode, so make
1596 sure that it does not try to use a constant value that
1598 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1602 #undef TARGET_RTX_COSTS
1603 #define TARGET_RTX_COSTS msp430_rtx_costs
1605 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1607 int outer_code ATTRIBUTE_UNUSED
,
1608 int opno ATTRIBUTE_UNUSED
,
1610 bool speed ATTRIBUTE_UNUSED
)
1612 int code
= GET_CODE (x
);
1617 if (mode
== SImode
&& outer_code
== SET
)
1619 *total
= COSTS_N_INSNS (4);
1628 *total
= COSTS_N_INSNS (100);
1636 /* Function Entry and Exit */
1638 /* The MSP430 call frame looks like this:
1641 +--------------------+
1645 +--------------------+ <-- "arg pointer"
1647 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1649 +--------------------+
1650 | SR if this func has|
1651 | been called via an |
1653 +--------------------+ <-- SP before prologue, also AP
1655 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1657 +--------------------+ <-- "frame pointer"
1661 +--------------------+
1665 +--------------------+ <-- SP during function
1670 /* We use this to wrap all emitted insns in the prologue, so they get
1671 the "frame-related" (/f) flag set. */
1675 RTX_FRAME_RELATED_P (x
) = 1;
1679 /* This is the one spot that decides if a register is to be saved and
1680 restored in the prologue/epilogue. */
1682 msp430_preserve_reg_p (int regno
)
1684 /* PC, SP, SR, and the constant generator. */
1688 /* FIXME: add interrupt, EH, etc. */
1689 if (crtl
->calls_eh_return
)
1692 /* Shouldn't be more than the above, but just in case... */
1693 if (fixed_regs
[regno
])
1696 /* Interrupt handlers save all registers they use, even
1697 ones which are call saved. If they call other functions
1698 then *every* register is saved. */
1699 if (msp430_is_interrupt_func ())
1700 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1702 if (!call_used_regs
[regno
]
1703 && df_regs_ever_live_p (regno
))
1709 /* Compute all the frame-related fields in our machine_function
1712 msp430_compute_frame_info (void)
1716 cfun
->machine
->computed
= 1;
1717 cfun
->machine
->framesize_regs
= 0;
1718 cfun
->machine
->framesize_locals
= get_frame_size ();
1719 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1721 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1722 if (msp430_preserve_reg_p (i
))
1724 cfun
->machine
->need_to_save
[i
] = 1;
1725 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1728 cfun
->machine
->need_to_save
[i
] = 0;
1730 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1731 cfun
->machine
->framesize_locals
++;
1733 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1734 + cfun
->machine
->framesize_locals
1735 + cfun
->machine
->framesize_outgoing
);
1738 /* Attribute Handling. */
1740 const char * const ATTR_INTR
= "interrupt";
1741 const char * const ATTR_WAKEUP
= "wakeup";
1742 const char * const ATTR_NAKED
= "naked";
1743 const char * const ATTR_REENT
= "reentrant";
1744 const char * const ATTR_CRIT
= "critical";
1745 const char * const ATTR_LOWER
= "lower";
1746 const char * const ATTR_UPPER
= "upper";
1747 const char * const ATTR_EITHER
= "either";
1748 const char * const ATTR_NOINIT
= "noinit";
1749 const char * const ATTR_PERSIST
= "persistent";
1752 has_attr (const char * attr
, tree decl
)
1754 if (decl
== NULL_TREE
)
1756 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1760 is_interrupt_func (tree decl
= current_function_decl
)
1762 return has_attr (ATTR_INTR
, decl
);
1765 /* Returns true if the current function has the "interrupt" attribute. */
1768 msp430_is_interrupt_func (void)
1770 return is_interrupt_func (current_function_decl
);
1774 is_wakeup_func (tree decl
= current_function_decl
)
1776 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1780 is_naked_func (tree decl
= current_function_decl
)
1782 return has_attr (ATTR_NAKED
, decl
);
1786 is_reentrant_func (tree decl
= current_function_decl
)
1788 return has_attr (ATTR_REENT
, decl
);
1792 is_critical_func (tree decl
= current_function_decl
)
1794 return has_attr (ATTR_CRIT
, decl
);
1797 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1798 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1801 msp430_allocate_stack_slots_for_args (void)
1803 /* Naked functions should not allocate stack slots for arguments. */
1804 return ! is_naked_func ();
1807 /* Verify MSP430 specific attributes. */
1808 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1811 msp430_attr (tree
* node
,
1814 int flags ATTRIBUTE_UNUSED
,
1815 bool * no_add_attrs
)
1817 gcc_assert (DECL_P (* node
));
1821 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1823 tree value
= TREE_VALUE (args
);
1825 switch (TREE_CODE (value
))
1828 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1829 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1830 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1831 /* Allow the attribute to be added - the linker script
1832 being used may still recognise this name. */
1833 warning (OPT_Wattributes
,
1834 "unrecognised interrupt vector argument of %qE attribute",
1839 if (wi::gtu_p (value
, 63))
1840 /* Allow the attribute to be added - the linker script
1841 being used may still recognise this value. */
1842 warning (OPT_Wattributes
,
1843 "numeric argument of %qE attribute must be in range 0..63",
1848 warning (OPT_Wattributes
,
1849 "argument of %qE attribute is not a string constant or number",
1851 *no_add_attrs
= true;
1856 const char * message
= NULL
;
1858 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1860 message
= "%qE attribute only applies to functions";
1862 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1864 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1865 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1866 message
= "interrupt handlers must be void";
1868 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1870 if (is_naked_func (* node
))
1871 message
= "naked functions cannot be reentrant";
1872 else if (is_critical_func (* node
))
1873 message
= "critical functions cannot be reentrant";
1875 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1877 if (is_naked_func (* node
))
1878 message
= "naked functions cannot be critical";
1879 else if (is_reentrant_func (* node
))
1880 message
= "reentrant functions cannot be critical";
1882 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1884 if (is_critical_func (* node
))
1885 message
= "critical functions cannot be naked";
1886 else if (is_reentrant_func (* node
))
1887 message
= "reentrant functions cannot be naked";
1892 warning (OPT_Wattributes
, message
, name
);
1893 * no_add_attrs
= true;
1900 msp430_section_attr (tree
* node
,
1903 int flags ATTRIBUTE_UNUSED
,
1904 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1906 gcc_assert (DECL_P (* node
));
1907 gcc_assert (args
== NULL
);
1909 const char * message
= NULL
;
1911 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1913 if (has_attr (ATTR_LOWER
, * node
))
1914 message
= "already marked with 'lower' attribute";
1915 else if (has_attr (ATTR_EITHER
, * node
))
1916 message
= "already marked with 'either' attribute";
1918 message
= "upper attribute needs a 430X cpu";
1920 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1922 if (has_attr (ATTR_UPPER
, * node
))
1923 message
= "already marked with 'upper' attribute";
1924 else if (has_attr (ATTR_EITHER
, * node
))
1925 message
= "already marked with 'either' attribute";
1929 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1931 if (has_attr (ATTR_LOWER
, * node
))
1932 message
= "already marked with 'lower' attribute";
1933 else if (has_attr (ATTR_UPPER
, * node
))
1934 message
= "already marked with 'upper' attribute";
1939 warning (OPT_Wattributes
, message
, name
);
1940 * no_add_attrs
= true;
1947 msp430_data_attr (tree
* node
,
1950 int flags ATTRIBUTE_UNUSED
,
1951 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1953 const char * message
= NULL
;
1955 gcc_assert (DECL_P (* node
));
1956 gcc_assert (args
== NULL
);
1958 if (TREE_CODE (* node
) != VAR_DECL
)
1959 message
= "%qE attribute only applies to variables";
1961 if (DECL_SECTION_NAME (* node
))
1962 message
= "%qE attribute cannot be applied to variables with specific sections";
1964 /* If this var is thought to be common, then change this. Common variables
1965 are assigned to sections before the backend has a chance to process them. */
1966 if (DECL_COMMON (* node
))
1967 DECL_COMMON (* node
) = 0;
1971 warning (OPT_Wattributes
, message
, name
);
1972 * no_add_attrs
= true;
1979 #undef TARGET_ATTRIBUTE_TABLE
1980 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
1982 /* Table of MSP430-specific attributes. */
1983 const struct attribute_spec msp430_attribute_table
[] =
1985 /* Name min_num_args type_req, affects_type_identity
1986 max_num_args, fn_type_req
1987 decl_req handler. */
1988 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
1989 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
1990 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
1991 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
1992 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
1994 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
1995 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
1996 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
1998 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false },
1999 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false },
2001 { NULL
, 0, 0, false, false, false, NULL
, false }
2004 #undef TARGET_ASM_FUNCTION_PROLOGUE
2005 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2008 msp430_start_function (FILE *outfile
, HOST_WIDE_INT hwi_local ATTRIBUTE_UNUSED
)
2012 fprintf (outfile
, "; start of function\n");
2014 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2016 fprintf (outfile
, "; attributes: ");
2017 if (is_naked_func ())
2018 fprintf (outfile
, "naked ");
2019 if (msp430_is_interrupt_func ())
2020 fprintf (outfile
, "interrupt ");
2021 if (is_reentrant_func ())
2022 fprintf (outfile
, "reentrant ");
2023 if (is_critical_func ())
2024 fprintf (outfile
, "critical ");
2025 if (is_wakeup_func ())
2026 fprintf (outfile
, "wakeup ");
2027 fprintf (outfile
, "\n");
2030 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2031 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2032 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2033 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2034 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2035 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2038 fprintf (outfile
, "; saved regs:");
2039 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2040 if (cfun
->machine
->need_to_save
[r
])
2042 fprintf (outfile
, " %s", reg_names
[r
]);
2046 fprintf (outfile
, "(none)");
2047 fprintf (outfile
, "\n");
2050 /* Common code to change the stack pointer. */
2052 increment_stack (HOST_WIDE_INT amount
)
2055 rtx sp
= stack_pointer_rtx
;
2062 inc
= GEN_INT (- amount
);
2064 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2066 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2070 inc
= GEN_INT (amount
);
2072 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2074 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2079 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2083 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2084 if (int_attr
!= NULL_TREE
)
2086 tree intr_vector
= TREE_VALUE (int_attr
);
2088 if (intr_vector
!= NULL_TREE
)
2092 intr_vector
= TREE_VALUE (intr_vector
);
2094 /* The interrupt attribute has a vector value. Turn this into a
2095 section name, switch to that section and put the address of
2096 the current function into that vector slot. Note msp430_attr()
2097 has already verified the vector name for us. */
2098 if (TREE_CODE (intr_vector
) == STRING_CST
)
2099 sprintf (buf
, "__interrupt_vector_%.80s",
2100 TREE_STRING_POINTER (intr_vector
));
2101 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2102 sprintf (buf
, "__interrupt_vector_%u",
2103 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2105 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2106 fputs ("\t.word\t", file
);
2107 assemble_name (file
, name
);
2113 switch_to_section (function_section (decl
));
2114 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2117 static const char * const lower_prefix
= ".lower";
2118 static const char * const upper_prefix
= ".upper";
2119 static const char * const either_prefix
= ".either";
2121 /* Generate a prefix for a section name, based upon
2122 the region into which the object should be placed. */
2125 gen_prefix (tree decl
)
2127 if (DECL_ONE_ONLY (decl
))
2130 /* If the user has specified a particular section then do not use any prefix. */
2131 if (has_attr ("section", decl
))
2134 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2135 if (has_attr (ATTR_LOWER
, decl
))
2136 return lower_prefix
;
2138 /* If we are compiling for the MSP430 then we do not support the upper region. */
2142 if (has_attr (ATTR_UPPER
, decl
))
2143 return upper_prefix
;
2145 if (has_attr (ATTR_EITHER
, decl
))
2146 return either_prefix
;
2148 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2150 if (msp430_code_region
== LOWER
)
2151 return lower_prefix
;
2153 if (msp430_code_region
== UPPER
)
2154 return upper_prefix
;
2156 if (msp430_code_region
== EITHER
)
2157 return either_prefix
;
2161 if (msp430_data_region
== LOWER
)
2162 return lower_prefix
;
2164 if (msp430_data_region
== UPPER
)
2165 return upper_prefix
;
2167 if (msp430_data_region
== EITHER
)
2168 return either_prefix
;
2174 static section
* noinit_section
;
2175 static section
* persist_section
;
2177 #undef TARGET_ASM_INIT_SECTIONS
2178 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2181 msp430_init_sections (void)
2183 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2184 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2187 #undef TARGET_ASM_SELECT_SECTION
2188 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2191 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2193 gcc_assert (decl
!= NULL_TREE
);
2195 if (TREE_CODE (decl
) == STRING_CST
2196 || TREE_CODE (decl
) == CONSTRUCTOR
2197 || TREE_CODE (decl
) == INTEGER_CST
2198 || TREE_CODE (decl
) == VECTOR_CST
2199 || TREE_CODE (decl
) == COMPLEX_CST
)
2200 return default_select_section (decl
, reloc
, align
);
2202 /* In large mode we must make sure that interrupt handlers are put into
2203 low memory as the vector table only accepts 16-bit addresses. */
2204 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2205 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2207 const char * prefix
= gen_prefix (decl
);
2210 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2211 return text_section
;
2212 else if (has_attr (ATTR_NOINIT
, decl
))
2213 return noinit_section
;
2214 else if (has_attr (ATTR_PERSIST
, decl
))
2215 return persist_section
;
2217 return default_select_section (decl
, reloc
, align
);
2221 switch (categorize_decl_for_section (decl
, reloc
))
2223 case SECCAT_TEXT
: sec
= ".text"; break;
2224 case SECCAT_DATA
: sec
= ".data"; break;
2225 case SECCAT_BSS
: sec
= ".bss"; break;
2226 case SECCAT_RODATA
: sec
= ".rodata"; break;
2228 case SECCAT_RODATA_MERGE_STR
:
2229 case SECCAT_RODATA_MERGE_STR_INIT
:
2230 case SECCAT_RODATA_MERGE_CONST
:
2231 case SECCAT_SRODATA
:
2232 case SECCAT_DATA_REL
:
2233 case SECCAT_DATA_REL_LOCAL
:
2234 case SECCAT_DATA_REL_RO
:
2235 case SECCAT_DATA_REL_RO_LOCAL
:
2240 return default_select_section (decl
, reloc
, align
);
2246 const char * dec_name
= DECL_SECTION_NAME (decl
);
2247 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2249 return get_named_section (decl
, name
, 0);
2252 #undef TARGET_ASM_FUNCTION_SECTION
2253 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2256 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2260 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2261 name
= DECL_SECTION_NAME (decl
);
2263 const char * prefix
= gen_prefix (decl
);
2265 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2266 return default_function_section (decl
, freq
, startup
, exit
);
2268 name
= ACONCAT ((prefix
, name
, NULL
));
2269 return get_named_section (decl
, name
, 0);
2272 #undef TARGET_SECTION_TYPE_FLAGS
2273 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2276 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2278 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2279 name
+= strlen (lower_prefix
);
2280 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2281 name
+= strlen (upper_prefix
);
2282 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2283 name
+= strlen (either_prefix
);
2284 else if (strcmp (name
, ".noinit") == 0)
2285 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2286 else if (strcmp (name
, ".persistent") == 0)
2287 return SECTION_WRITE
| SECTION_NOTYPE
;
2289 return default_section_type_flags (decl
, name
, reloc
);
2292 #undef TARGET_ASM_UNIQUE_SECTION
2293 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2296 msp430_unique_section (tree decl
, int reloc
)
2298 gcc_assert (decl
!= NULL_TREE
);
2300 /* In large mode we must make sure that interrupt handlers are put into
2301 low memory as the vector table only accepts 16-bit addresses. */
2302 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2304 set_decl_section_name (decl
, ".lowtext");
2308 default_unique_section (decl
, reloc
);
2310 const char * prefix
;
2312 if ( TREE_CODE (decl
) == STRING_CST
2313 || TREE_CODE (decl
) == CONSTRUCTOR
2314 || TREE_CODE (decl
) == INTEGER_CST
2315 || TREE_CODE (decl
) == VECTOR_CST
2316 || TREE_CODE (decl
) == COMPLEX_CST
2317 || (prefix
= gen_prefix (decl
)) == NULL
2321 const char * dec_name
= DECL_SECTION_NAME (decl
);
2322 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2324 set_decl_section_name (decl
, name
);
2327 /* Emit a declaration of a common symbol.
2328 If a data region is in use then put the symbol into the
2329 equivalent .bss section instead. */
2332 msp430_output_aligned_decl_common (FILE * stream
,
2335 unsigned HOST_WIDE_INT size
,
2338 if (msp430_data_region
== ANY
)
2340 fprintf (stream
, COMMON_ASM_OP
);
2341 assemble_name (stream
, name
);
2342 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2343 size
, align
/ BITS_PER_UNIT
);
2350 sec
= msp430_select_section (decl
, 0, align
);
2352 switch (msp430_data_region
)
2354 case UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2355 case LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2356 case EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2360 gcc_assert (sec
!= NULL
);
2362 switch_to_section (sec
);
2363 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2364 targetm
.asm_out
.globalize_label (stream
, name
);
2365 ASM_WEAKEN_LABEL (stream
, name
);
2366 ASM_OUTPUT_LABEL (stream
, name
);
2367 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2372 msp430_do_not_relax_short_jumps (void)
2374 /* When placing code into "either" low or high memory we do not want the linker
2375 to grow the size of sections, which it can do if it is encounters a branch to
2376 a label that is too far away. So we tell the cbranch patterns to avoid using
2377 short jumps when there is a chance that the instructions will end up in a low
2380 msp430_code_region
== EITHER
2381 || msp430_code_region
== LOWER
2382 || has_attr (ATTR_EITHER
, current_function_decl
)
2383 || has_attr (ATTR_LOWER
, current_function_decl
);
2388 MSP430_BUILTIN_BIC_SR
,
2389 MSP430_BUILTIN_BIS_SR
,
2390 MSP430_BUILTIN_DELAY_CYCLES
,
2394 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2397 msp430_init_builtins (void)
2399 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2400 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2402 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2403 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2404 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2406 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2407 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2408 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2410 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2411 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2412 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2416 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2420 case MSP430_BUILTIN_BIC_SR
:
2421 case MSP430_BUILTIN_BIS_SR
:
2422 case MSP430_BUILTIN_DELAY_CYCLES
:
2423 return msp430_builtins
[code
];
2425 return error_mark_node
;
2429 /* These constants are really register reads, which are faster than
2430 regular constants. */
2432 cg_magic_constant (HOST_WIDE_INT c
)
2450 msp430_expand_delay_cycles (rtx arg
)
2452 HOST_WIDE_INT i
, c
, n
;
2453 /* extra cycles for MSP430X instructions */
2454 #define CYCX(M,X) (msp430x ? (X) : (M))
2456 if (GET_CODE (arg
) != CONST_INT
)
2458 error ("__delay_cycles() only takes constant arguments");
2464 if (HOST_BITS_PER_WIDE_INT
> 32)
2468 error ("__delay_cycles only takes non-negative cycle counts.");
2473 emit_insn (gen_delay_cycles_start (arg
));
2475 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2476 if (c
> 3 * 0xffff + CYCX (7, 10))
2479 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2480 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2483 c
-= CYCX (14, 16) + 7 * 0x10000;
2486 if ((unsigned long long) i
> 0xffffffffULL
)
2488 error ("__delay_cycles is limited to 32-bit loop counts.");
2494 i
= (c
- CYCX (14, 16)) / 7;
2495 c
-= CYCX (14, 16) + i
* 7;
2498 if (cg_magic_constant (i
& 0xffff))
2500 if (cg_magic_constant ((i
>> 16) & 0xffff))
2504 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2506 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2509 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2513 i
= (c
- CYCX (7, 10)) / 3;
2514 c
-= CYCX (7, 10) + i
* 3;
2516 if (cg_magic_constant (i
))
2520 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2522 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2527 emit_insn (gen_delay_cycles_2 ());
2533 emit_insn (gen_delay_cycles_1 ());
2537 emit_insn (gen_delay_cycles_end (arg
));
2543 msp430_expand_builtin (tree exp
,
2544 rtx target ATTRIBUTE_UNUSED
,
2545 rtx subtarget ATTRIBUTE_UNUSED
,
2546 machine_mode mode ATTRIBUTE_UNUSED
,
2547 int ignore ATTRIBUTE_UNUSED
)
2549 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2550 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2551 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2553 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2554 return msp430_expand_delay_cycles (arg1
);
2556 if (! msp430_is_interrupt_func ())
2558 error ("MSP430 builtin functions only work inside interrupt handlers");
2562 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2563 arg1
= force_reg (mode
, arg1
);
2567 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2568 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2570 internal_error ("bad builtin code");
2576 #undef TARGET_INIT_BUILTINS
2577 #define TARGET_INIT_BUILTINS msp430_init_builtins
2579 #undef TARGET_EXPAND_BUILTIN
2580 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2582 #undef TARGET_BUILTIN_DECL
2583 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2586 msp430_expand_prologue (void)
2590 /* Always use stack_pointer_rtx instead of calling
2591 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2592 that there is a single rtx representing the stack pointer,
2593 namely stack_pointer_rtx, and uses == to recognize it. */
2594 rtx sp
= stack_pointer_rtx
;
2597 if (is_naked_func ())
2599 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2600 examines the output of the gen_prologue() function. */
2601 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2605 emit_insn (gen_prologue_start_marker ());
2607 if (is_critical_func ())
2609 emit_insn (gen_push_intr_state ());
2610 emit_insn (gen_disable_interrupts ());
2612 else if (is_reentrant_func ())
2613 emit_insn (gen_disable_interrupts ());
2615 if (!cfun
->machine
->computed
)
2616 msp430_compute_frame_info ();
2618 if (flag_stack_usage_info
)
2619 current_function_static_stack_size
= cfun
->machine
->framesize
;
2621 if (crtl
->args
.pretend_args_size
)
2625 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2627 p
= emit_insn (gen_grow_and_swap ());
2629 /* Document the stack decrement... */
2630 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2631 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2632 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2634 /* ...and the establishment of a new location for the return address. */
2635 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2636 gen_rtx_PLUS (Pmode
,
2640 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2644 for (i
= 15; i
>= 4; i
--)
2645 if (cfun
->machine
->need_to_save
[i
])
2650 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2656 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2657 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2660 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2662 XVECEXP (note
, 0, 0)
2663 = F (gen_rtx_SET (stack_pointer_rtx
,
2664 gen_rtx_PLUS (Pmode
,
2666 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2668 /* *sp-- = R[i-j] */
2672 for (j
= 0; j
< count
; j
++)
2675 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2678 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2680 addr
= stack_pointer_rtx
;
2682 XVECEXP (note
, 0, j
+ 1) =
2683 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2684 gen_rtx_REG (Pmode
, i
- j
)) );
2687 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2691 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2694 if (frame_pointer_needed
)
2695 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2697 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2699 increment_stack (- fs
);
2701 emit_insn (gen_prologue_end_marker ());
2705 msp430_expand_epilogue (int is_eh
)
2711 if (is_naked_func ())
2713 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2714 examines the output of the gen_epilogue() function. */
2715 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2719 if (cfun
->machine
->need_to_save
[10])
2721 /* Check for a helper function. */
2722 helper_n
= 7; /* For when the loop below never sees a match. */
2723 for (i
= 9; i
>= 4; i
--)
2724 if (!cfun
->machine
->need_to_save
[i
])
2728 if (cfun
->machine
->need_to_save
[i
])
2737 emit_insn (gen_epilogue_start_marker ());
2739 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2740 emit_insn (gen_msp430_refsym_need_exit ());
2742 if (is_wakeup_func ())
2743 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2744 status register current residing on the stack. When this function
2745 executes its RETI instruction the SR will be updated with this saved
2746 value, thus ensuring that the processor is woken up from any low power
2747 state in which it may be residing. */
2748 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2750 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2752 increment_stack (fs
);
2756 /* We need to add the right "SP" register save just after the
2757 regular ones, so that when we pop it off we're in the EH
2758 return frame, not this one. This overwrites our own return
2759 address, but we're not going to be returning anyway. */
2760 rtx r12
= gen_rtx_REG (Pmode
, 12);
2761 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2763 /* R12 will hold the new SP. */
2764 i
= cfun
->machine
->framesize_regs
;
2765 emit_move_insn (r12
, stack_pointer_rtx
);
2766 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2767 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2768 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2771 for (i
= 4; i
<= 15; i
++)
2772 if (cfun
->machine
->need_to_save
[i
])
2776 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2782 /* Note: With TARGET_LARGE we still use
2783 POPM as POPX.A is two bytes bigger. */
2784 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2788 else if (i
== 11 - helper_n
2789 && ! msp430_is_interrupt_func ()
2790 && ! is_reentrant_func ()
2791 && ! is_critical_func ()
2792 && crtl
->args
.pretend_args_size
== 0
2793 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2797 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2801 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2806 /* Also pop SP, which puts us into the EH return frame. Except
2807 that you can't "pop" sp, you have to just load it off the
2809 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2812 if (crtl
->args
.pretend_args_size
)
2813 emit_insn (gen_swap_and_shrink ());
2815 if (is_critical_func ())
2816 emit_insn (gen_pop_intr_state ());
2817 else if (is_reentrant_func ())
2818 emit_insn (gen_enable_interrupts ());
2820 emit_jump_insn (gen_msp_return ());
2823 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2824 m32c_emit_eh_epilogue. */
2826 msp430_eh_return_stackadj_rtx (void)
2828 if (!cfun
->machine
->eh_stack_adjust
)
2832 sa
= gen_rtx_REG (Pmode
, 15);
2833 cfun
->machine
->eh_stack_adjust
= sa
;
2835 return cfun
->machine
->eh_stack_adjust
;
2838 /* This function is called before reload, to "fix" the stack in
2839 preparation for an EH return. */
2841 msp430_expand_eh_return (rtx eh_handler
)
2843 /* These are all Pmode */
2844 rtx ap
, sa
, ra
, tmp
;
2846 ap
= arg_pointer_rtx
;
2847 sa
= msp430_eh_return_stackadj_rtx ();
2851 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2852 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2853 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2854 emit_move_insn (tmp
, ra
);
2857 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2858 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2860 msp430_init_dwarf_reg_sizes_extra (tree address
)
2863 rtx addr
= expand_normal (address
);
2864 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2866 /* This needs to match msp430_unwind_word_mode (above). */
2870 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2872 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2873 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2875 if (rnum
< DWARF_FRAME_REGISTERS
)
2877 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2879 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2880 gen_int_mode (4, QImode
));
2885 /* This is a list of MD patterns that implement fixed-count shifts. */
2891 rtx (*genfunc
)(rtx
,rtx
);
2893 const_shift_helpers
[] =
2895 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2897 CSH ("slli", 1, 1, slli_1
),
2898 CSH ("slll", 1, 1, slll_1
),
2899 CSH ("slll", 2, 1, slll_2
),
2901 CSH ("srai", 1, 0, srai_1
),
2902 CSH ("sral", 1, 0, sral_1
),
2903 CSH ("sral", 2, 0, sral_2
),
2905 CSH ("srll", 1, 0, srll_1
),
2906 CSH ("srll", 2, 1, srll_2x
),
2911 /* The MSP430 ABI defines a number of helper functions that should be
2912 used for, for example, 32-bit shifts. This function is called to
2913 emit such a function, using the table above to optimize some
2916 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2919 char *helper_const
= NULL
;
2922 machine_mode arg0mode
= GET_MODE (operands
[0]);
2923 machine_mode arg1mode
= GET_MODE (operands
[1]);
2924 machine_mode arg2mode
= GET_MODE (operands
[2]);
2925 int have_430x
= msp430x
? 1 : 0;
2927 if (CONST_INT_P (operands
[2]))
2931 for (i
=0; const_shift_helpers
[i
].name
; i
++)
2933 if (const_shift_helpers
[i
].need_430x
<= have_430x
2934 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
2935 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
2937 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
2943 if (arg1mode
== VOIDmode
)
2944 arg1mode
= arg0mode
;
2945 if (arg2mode
== VOIDmode
)
2946 arg2mode
= arg0mode
;
2948 if (arg1mode
== SImode
)
2955 && CONST_INT_P (operands
[2])
2956 && INTVAL (operands
[2]) >= 1
2957 && INTVAL (operands
[2]) <= 15)
2959 /* Note that the INTVAL is limited in value and length by the conditional above. */
2960 int len
= strlen (helper_name
) + 4;
2961 helper_const
= (char *) xmalloc (len
);
2962 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
2965 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
2968 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
2971 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
2972 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
2974 c
= emit_call_insn (c
);
2975 RTL_CONST_CALL_P (c
) = 1;
2978 use_regs (&f
, 12, arg1sz
);
2980 use_regs (&f
, arg2
, 1);
2981 add_function_usage_to (c
, f
);
2983 emit_move_insn (operands
[0],
2984 gen_rtx_REG (arg0mode
, 12));
2987 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
2989 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
2991 /* constants we're looking for, not constants which are allowed. */
2992 int const_op_idx
= 1;
2994 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
2997 if (GET_CODE (operands
[const_op_idx
]) != REG
2998 && GET_CODE (operands
[const_op_idx
]) != MEM
)
2999 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3002 /* Simplify_gen_subreg() doesn't handle memory references the way we
3003 need it to below, so we use this function for when we must get a
3004 valid subreg in a "natural" state. */
3006 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3010 if (GET_CODE (r
) == SUBREG
3011 && SUBREG_BYTE (r
) == 0)
3013 rtx ireg
= SUBREG_REG (r
);
3014 machine_mode imode
= GET_MODE (ireg
);
3016 /* special case for (HI (SI (PSI ...), 0)) */
3017 if (imode
== PSImode
3020 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3022 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3024 else if (GET_CODE (r
) == MEM
)
3025 rv
= adjust_address (r
, mode
, byte
);
3026 else if (GET_CODE (r
) == SYMBOL_REF
3027 && (byte
== 0 || byte
== 2)
3030 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3031 rv
= gen_rtx_CONST (HImode
, r
);
3034 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3042 /* Called by movsi_x to generate the HImode operands. */
3044 msp430_split_movsi (rtx
*operands
)
3046 rtx op00
, op02
, op10
, op12
;
3048 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3049 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3051 if (GET_CODE (operands
[1]) == CONST
3052 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3054 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3055 op10
= gen_rtx_CONST (HImode
, op10
);
3056 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3057 op12
= gen_rtx_CONST (HImode
, op12
);
3061 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3062 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3065 if (rtx_equal_p (operands
[0], operands
[1]))
3072 else if (rtx_equal_p (op00
, op12
)
3073 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3074 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3075 /* Or storing (rN) into mem (rN). */
3076 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3094 /* The MSPABI specifies the names of various helper functions, many of
3095 which are compatible with GCC's helpers. This table maps the GCC
3096 name to the MSPABI name. */
3099 char const * const gcc_name
;
3100 char const * const ti_name
;
3102 helper_function_name_mappings
[] =
3104 /* Floating point to/from integer conversions. */
3105 { "__truncdfsf2", "__mspabi_cvtdf" },
3106 { "__extendsfdf2", "__mspabi_cvtfd" },
3107 { "__fixdfhi", "__mspabi_fixdi" },
3108 { "__fixdfsi", "__mspabi_fixdli" },
3109 { "__fixdfdi", "__mspabi_fixdlli" },
3110 { "__fixunsdfhi", "__mspabi_fixdu" },
3111 { "__fixunsdfsi", "__mspabi_fixdul" },
3112 { "__fixunsdfdi", "__mspabi_fixdull" },
3113 { "__fixsfhi", "__mspabi_fixfi" },
3114 { "__fixsfsi", "__mspabi_fixfli" },
3115 { "__fixsfdi", "__mspabi_fixflli" },
3116 { "__fixunsfhi", "__mspabi_fixfu" },
3117 { "__fixunsfsi", "__mspabi_fixful" },
3118 { "__fixunsfdi", "__mspabi_fixfull" },
3119 { "__floathisf", "__mspabi_fltif" },
3120 { "__floatsisf", "__mspabi_fltlif" },
3121 { "__floatdisf", "__mspabi_fltllif" },
3122 { "__floathidf", "__mspabi_fltid" },
3123 { "__floatsidf", "__mspabi_fltlid" },
3124 { "__floatdidf", "__mspabi_fltllid" },
3125 { "__floatunhisf", "__mspabi_fltuf" },
3126 { "__floatunsisf", "__mspabi_fltulf" },
3127 { "__floatundisf", "__mspabi_fltullf" },
3128 { "__floatunhidf", "__mspabi_fltud" },
3129 { "__floatunsidf", "__mspabi_fltuld" },
3130 { "__floatundidf", "__mspabi_fltulld" },
3132 /* Floating point comparisons. */
3133 /* GCC uses individual functions for each comparison, TI uses one
3134 compare <=> function. */
3136 /* Floating point arithmatic */
3137 { "__adddf3", "__mspabi_addd" },
3138 { "__addsf3", "__mspabi_addf" },
3139 { "__divdf3", "__mspabi_divd" },
3140 { "__divsf3", "__mspabi_divf" },
3141 { "__muldf3", "__mspabi_mpyd" },
3142 { "__mulsf3", "__mspabi_mpyf" },
3143 { "__subdf3", "__mspabi_subd" },
3144 { "__subsf3", "__mspabi_subf" },
3145 /* GCC does not use helper functions for negation */
3147 /* Integer multiply, divide, remainder. */
3148 { "__mulhi3", "__mspabi_mpyi" },
3149 { "__mulsi3", "__mspabi_mpyl" },
3150 { "__muldi3", "__mspabi_mpyll" },
3152 /* Clarify signed vs unsigned first. */
3153 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3154 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3157 { "__divhi3", "__mspabi_divi" },
3158 { "__divsi3", "__mspabi_divli" },
3159 { "__divdi3", "__mspabi_divlli" },
3160 { "__udivhi3", "__mspabi_divu" },
3161 { "__udivsi3", "__mspabi_divul" },
3162 { "__udivdi3", "__mspabi_divull" },
3163 { "__modhi3", "__mspabi_remi" },
3164 { "__modsi3", "__mspabi_remli" },
3165 { "__moddi3", "__mspabi_remlli" },
3166 { "__umodhi3", "__mspabi_remu" },
3167 { "__umodsi3", "__mspabi_remul" },
3168 { "__umoddi3", "__mspabi_remull" },
3170 /* Bitwise operations. */
3171 /* Rotation - no rotation support yet. */
3172 /* Logical left shift - gcc already does these itself. */
3173 /* Arithmetic left shift - gcc already does these itself. */
3174 /* Arithmetic right shift - gcc already does these itself. */
3179 /* Returns true if the current MCU supports an F5xxx series
3180 hardware multiper. */
3183 msp430_use_f5_series_hwmult (void)
3185 static const char * cached_match
= NULL
;
3186 static bool cached_result
;
3188 if (msp430_hwmult_type
== F5SERIES
)
3191 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
3194 if (target_mcu
== cached_match
)
3195 return cached_result
;
3197 cached_match
= target_mcu
;
3199 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3200 return cached_result
= true;
3201 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3202 return cached_result
= true;
3203 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3204 return cached_result
= true;
3208 /* FIXME: This array is alpha sorted - we could use a binary search. */
3209 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3210 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3211 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3213 return cached_result
= false;
3216 /* Returns true if the current MCU has a second generation
3217 32-bit hardware multiplier. */
3220 use_32bit_hwmult (void)
3222 static const char * cached_match
= NULL
;
3223 static bool cached_result
;
3226 if (msp430_hwmult_type
== LARGE
)
3229 if (target_mcu
== NULL
|| msp430_hwmult_type
!= AUTO
)
3232 if (target_mcu
== cached_match
)
3233 return cached_result
;
3235 cached_match
= target_mcu
;
3237 /* FIXME: This array is alpha sorted - we could use a binary search. */
3238 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3239 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3240 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3242 return cached_result
= false;
3245 /* Returns true if the current MCU does not have a
3246 hardware multiplier of any kind. */
3249 msp430_no_hwmult (void)
3251 static const char * cached_match
= NULL
;
3252 static bool cached_result
;
3255 if (msp430_hwmult_type
== NONE
)
3258 if (msp430_hwmult_type
!= AUTO
)
3261 if (target_mcu
== NULL
)
3264 if (target_mcu
== cached_match
)
3265 return cached_result
;
3267 cached_match
= target_mcu
;
3269 /* FIXME: This array is alpha sorted - we could use a binary search. */
3270 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3271 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3272 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3274 /* If we do not recognise the MCU name, we assume that it does not support
3275 any kind of hardware multiply - this is the safest assumption to make. */
3276 return cached_result
= true;
3279 /* This function does the same as the default, but it will replace GCC
3280 function names with the MSPABI-specified ones. */
3283 msp430_output_labelref (FILE *file
, const char *name
)
3287 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3288 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3290 name
= helper_function_name_mappings
[i
].ti_name
;
3294 /* If we have been given a specific MCU name then we may be
3295 able to make use of its hardware multiply capabilities. */
3296 if (msp430_hwmult_type
!= NONE
)
3298 if (strcmp ("__mspabi_mpyi", name
) == 0)
3300 if (msp430_use_f5_series_hwmult ())
3301 name
= "__mulhi2_f5";
3302 else if (! msp430_no_hwmult ())
3305 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3307 if (msp430_use_f5_series_hwmult ())
3308 name
= "__mulsi2_f5";
3309 else if (use_32bit_hwmult ())
3310 name
= "__mulsi2_hw32";
3311 else if (! msp430_no_hwmult ())
3319 /* Common code for msp430_print_operand... */
3322 msp430_print_operand_raw (FILE * file
, rtx op
)
3326 switch (GET_CODE (op
))
3329 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3335 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3337 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3345 output_addr_const (file
, op
);
3349 print_rtl (file
, op
);
3354 #undef TARGET_PRINT_OPERAND_ADDRESS
3355 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3357 /* Output to stdio stream FILE the assembler syntax for an
3358 instruction operand that is a memory reference whose address
3362 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3364 switch (GET_CODE (addr
))
3367 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3368 gcc_assert (REG_P (XEXP (addr
, 0)));
3369 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3373 fprintf (file
, "@");
3380 fprintf (file
, "&");
3387 msp430_print_operand_raw (file
, addr
);
3390 #undef TARGET_PRINT_OPERAND
3391 #define TARGET_PRINT_OPERAND msp430_print_operand
3393 /* A low 16-bits of int/lower of register pair
3394 B high 16-bits of int/higher of register pair
3395 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3396 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3397 H like %B (for backwards compatibility)
3399 J an integer without a # prefix
3400 L like %A (for backwards compatibility)
3401 O offset of the top of the stack
3402 Q like X but generates an A postfix
3403 R inverse of condition code, unsigned.
3404 X X instruction postfix in large mode
3407 b .B or .W or .A, depending upon the mode
3409 r inverse of condition code
3410 x like X but only for pointers. */
3413 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3417 /* We can't use c, n, a, or l. */
3421 gcc_assert (CONST_INT_P (op
));
3422 /* Print the constant value, less one. */
3423 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3426 gcc_assert (CONST_INT_P (op
));
3427 /* Print the constant value, less four. */
3428 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3431 if (GET_CODE (op
) == CONST_INT
)
3433 /* Inverse of constants */
3434 int i
= INTVAL (op
);
3435 fprintf (file
, "%d", ~i
);
3440 case 'r': /* Conditional jump where the condition is reversed. */
3441 switch (GET_CODE (op
))
3443 case EQ
: fprintf (file
, "NE"); break;
3444 case NE
: fprintf (file
, "EQ"); break;
3445 case GEU
: fprintf (file
, "LO"); break;
3446 case LTU
: fprintf (file
, "HS"); break;
3447 case GE
: fprintf (file
, "L"); break;
3448 case LT
: fprintf (file
, "GE"); break;
3449 /* Assume these have reversed operands. */
3450 case GTU
: fprintf (file
, "HS"); break;
3451 case LEU
: fprintf (file
, "LO"); break;
3452 case GT
: fprintf (file
, "GE"); break;
3453 case LE
: fprintf (file
, "L"); break;
3455 msp430_print_operand_raw (file
, op
);
3459 case 'R': /* Conditional jump where the operands are reversed. */
3460 switch (GET_CODE (op
))
3462 case GTU
: fprintf (file
, "LO"); break;
3463 case LEU
: fprintf (file
, "HS"); break;
3464 case GT
: fprintf (file
, "L"); break;
3465 case LE
: fprintf (file
, "GE"); break;
3467 msp430_print_operand_raw (file
, op
);
3471 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3472 gcc_assert (CONST_INT_P (op
));
3473 fprintf (file
, "#%d", 1 << INTVAL (op
));
3476 switch (GET_MODE (op
))
3478 case QImode
: fprintf (file
, ".B"); return;
3479 case HImode
: fprintf (file
, ".W"); return;
3480 case PSImode
: fprintf (file
, ".A"); return;
3481 case SImode
: fprintf (file
, ".A"); return;
3486 case 'L': /* Low half. */
3487 switch (GET_CODE (op
))
3490 op
= adjust_address (op
, Pmode
, 0);
3495 op
= GEN_INT (INTVAL (op
) & 0xffff);
3499 /* If you get here, figure out a test case :-) */
3504 case 'H': /* high half */
3505 switch (GET_CODE (op
))
3508 op
= adjust_address (op
, Pmode
, 2);
3511 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3514 op
= GEN_INT (INTVAL (op
) >> 16);
3518 /* If you get here, figure out a test case :-) */
3523 switch (GET_CODE (op
))
3526 op
= adjust_address (op
, Pmode
, 3);
3529 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3532 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3536 /* If you get here, figure out a test case :-) */
3541 switch (GET_CODE (op
))
3544 op
= adjust_address (op
, Pmode
, 4);
3547 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3550 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3554 /* If you get here, figure out a test case :-) */
3560 /* This is used to turn, for example, an ADD opcode into an ADDX
3561 opcode when we're using 20-bit addresses. */
3562 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3563 fprintf (file
, "X");
3564 /* We don't care which operand we use, but we want 'X' in the MD
3565 file, so we do it this way. */
3569 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3570 if (GET_MODE (op
) == PSImode
)
3571 fprintf (file
, "X");
3575 /* Likewise, for BR -> BRA. */
3577 fprintf (file
, "A");
3581 /* Computes the offset to the top of the stack for the current frame.
3582 This has to be done here rather than in, say, msp430_expand_builtin()
3583 because builtins are expanded before the frame layout is determined. */
3584 fprintf (file
, "%d",
3585 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3586 - (TARGET_LARGE
? 4 : 2));
3590 gcc_assert (GET_CODE (op
) == CONST_INT
);
3594 output_operand_lossage ("invalid operand prefix");
3598 switch (GET_CODE (op
))
3601 msp430_print_operand_raw (file
, op
);
3605 addr
= XEXP (op
, 0);
3606 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3610 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3613 switch (INTVAL (XEXP (op
, 2)))
3616 fprintf (file
, "#lo (");
3617 msp430_print_operand_raw (file
, XEXP (op
, 0));
3618 fprintf (file
, ")");
3622 fprintf (file
, "#hi (");
3623 msp430_print_operand_raw (file
, XEXP (op
, 0));
3624 fprintf (file
, ")");
3628 output_operand_lossage ("invalid zero extract");
3638 fprintf (file
, "#");
3639 msp430_print_operand_raw (file
, op
);
3642 case EQ
: fprintf (file
, "EQ"); break;
3643 case NE
: fprintf (file
, "NE"); break;
3644 case GEU
: fprintf (file
, "HS"); break;
3645 case LTU
: fprintf (file
, "LO"); break;
3646 case GE
: fprintf (file
, "GE"); break;
3647 case LT
: fprintf (file
, "L"); break;
3650 print_rtl (file
, op
);
3659 msp430_return_addr_rtx (int count
)
3665 ra_size
= TARGET_LARGE
? 4 : 2;
3666 if (crtl
->args
.pretend_args_size
)
3669 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3673 msp430_incoming_return_addr_rtx (void)
3675 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3678 /* Instruction generation stuff. */
3680 /* Generate a sequence of instructions to sign-extend an HI
3681 value into an SI value. Handles the tricky case where
3682 we are overwriting the destination. */
3685 msp430x_extendhisi (rtx
* operands
)
3687 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3688 /* Low word of dest == source word. */
3689 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3692 /* Note: This sequence is approximately the same length as invoking a helper
3693 function to perform the sign-extension, as in:
3697 CALL __mspabi_srai_15
3700 but this version does not involve any function calls or using argument
3701 registers, so it reduces register pressure. */
3702 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3704 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3705 /* High word of dest == source word. */
3706 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3708 /* No overlap between dest and source. */
3709 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3712 /* Likewise for logical right shifts. */
3714 msp430x_logical_shift_right (rtx amount
)
3716 /* The MSP430X's logical right shift instruction - RRUM - does
3717 not use an extension word, so we cannot encode a repeat count.
3718 Try various alternatives to work around this. If the count
3719 is in a register we are stuck, hence the assert. */
3720 gcc_assert (CONST_INT_P (amount
));
3722 if (INTVAL (amount
) <= 0
3723 || INTVAL (amount
) >= 16)
3724 return "# nop logical shift.";
3726 if (INTVAL (amount
) > 0
3727 && INTVAL (amount
) < 5)
3728 return "rrum.w\t%2, %0"; /* Two bytes. */
3730 if (INTVAL (amount
) > 4
3731 && INTVAL (amount
) < 9)
3732 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3734 /* First we logically shift right by one. Now we know
3735 that the top bit is zero and we can use the arithmetic
3736 right shift instruction to perform the rest of the shift. */
3737 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3740 struct gcc_target targetm
= TARGET_INITIALIZER
;
3742 #include "gt-msp430.h"