1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2017 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 "stringpool.h"
30 #include "gimple-expr.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "stor-layout.h"
43 #include "langhooks.h"
47 /* This file should be included last. */
48 #include "target-def.h"
51 static void msp430_compute_frame_info (void);
55 /* Run-time Target Specification. */
59 struct GTY(()) machine_function
61 /* If set, the rest of the fields have been computed. */
63 /* Which registers need to be saved in the pro/epilogue. */
64 int need_to_save
[FIRST_PSEUDO_REGISTER
];
66 /* These fields describe the frame layout... */
68 /* 2/4 bytes for saved PC */
72 int framesize_outgoing
;
76 /* How much we adjust the stack when returning from an exception
81 /* This is our init_machine_status, as set in
82 msp_option_override. */
83 static struct machine_function
*
84 msp430_init_machine_status (void)
86 struct machine_function
*m
;
88 m
= ggc_cleared_alloc
<machine_function
> ();
93 #undef TARGET_OPTION_OVERRIDE
94 #define TARGET_OPTION_OVERRIDE msp430_option_override
96 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
97 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
98 Keep these three structures in sync.
99 The data in this structure has been extracted from version 1.194 of the
100 devices.csv file released by TI in September 2016. */
102 struct msp430_mcu_data
105 unsigned int revision
; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
106 unsigned int hwmpy
; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
110 { "cc430f5123",2,8 },
111 { "cc430f5125",2,8 },
112 { "cc430f5133",2,8 },
113 { "cc430f5135",2,8 },
114 { "cc430f5137",2,8 },
115 { "cc430f5143",2,8 },
116 { "cc430f5145",2,8 },
117 { "cc430f5147",2,8 },
118 { "cc430f6125",2,8 },
119 { "cc430f6126",2,8 },
120 { "cc430f6127",2,8 },
121 { "cc430f6135",2,8 },
122 { "cc430f6137",2,8 },
123 { "cc430f6143",2,8 },
124 { "cc430f6145",2,8 },
125 { "cc430f6147",2,8 },
126 { "msp430afe221",0,2 },
127 { "msp430afe222",0,2 },
128 { "msp430afe223",0,2 },
129 { "msp430afe231",0,2 },
130 { "msp430afe232",0,2 },
131 { "msp430afe233",0,2 },
132 { "msp430afe251",0,2 },
133 { "msp430afe252",0,2 },
134 { "msp430afe253",0,2 },
135 { "msp430bt5190",2,8 },
136 { "msp430c091",0,0 },
137 { "msp430c092",0,0 },
138 { "msp430c111",0,0 },
139 { "msp430c1111",0,0 },
140 { "msp430c112",0,0 },
141 { "msp430c1121",0,0 },
142 { "msp430c1331",0,0 },
143 { "msp430c1351",0,0 },
144 { "msp430c311s",0,0 },
145 { "msp430c312",0,0 },
146 { "msp430c313",0,0 },
147 { "msp430c314",0,0 },
148 { "msp430c315",0,0 },
149 { "msp430c323",0,0 },
150 { "msp430c325",0,0 },
151 { "msp430c336",0,1 },
152 { "msp430c337",0,1 },
153 { "msp430c412",0,0 },
154 { "msp430c413",0,0 },
155 { "msp430cg4616",1,1 },
156 { "msp430cg4617",1,1 },
157 { "msp430cg4618",1,1 },
158 { "msp430cg4619",1,1 },
159 { "msp430e112",0,0 },
160 { "msp430e313",0,0 },
161 { "msp430e315",0,0 },
162 { "msp430e325",0,0 },
163 { "msp430e337",0,1 },
164 { "msp430f110",0,0 },
165 { "msp430f1101",0,0 },
166 { "msp430f1101a",0,0 },
167 { "msp430f1111",0,0 },
168 { "msp430f1111a",0,0 },
169 { "msp430f112",0,0 },
170 { "msp430f1121",0,0 },
171 { "msp430f1121a",0,0 },
172 { "msp430f1122",0,0 },
173 { "msp430f1132",0,0 },
174 { "msp430f122",0,0 },
175 { "msp430f1222",0,0 },
176 { "msp430f123",0,0 },
177 { "msp430f1232",0,0 },
178 { "msp430f133",0,0 },
179 { "msp430f135",0,0 },
180 { "msp430f147",0,1 },
181 { "msp430f1471",0,1 },
182 { "msp430f148",0,1 },
183 { "msp430f1481",0,1 },
184 { "msp430f149",0,1 },
185 { "msp430f1491",0,1 },
186 { "msp430f155",0,0 },
187 { "msp430f156",0,0 },
188 { "msp430f157",0,0 },
189 { "msp430f1610",0,1 },
190 { "msp430f1611",0,1 },
191 { "msp430f1612",0,1 },
192 { "msp430f167",0,1 },
193 { "msp430f168",0,1 },
194 { "msp430f169",0,1 },
195 { "msp430f2001",0,0 },
196 { "msp430f2002",0,0 },
197 { "msp430f2003",0,0 },
198 { "msp430f2011",0,0 },
199 { "msp430f2012",0,0 },
200 { "msp430f2013",0,0 },
201 { "msp430f2101",0,0 },
202 { "msp430f2111",0,0 },
203 { "msp430f2112",0,0 },
204 { "msp430f2121",0,0 },
205 { "msp430f2122",0,0 },
206 { "msp430f2131",0,0 },
207 { "msp430f2132",0,0 },
208 { "msp430f2232",0,0 },
209 { "msp430f2234",0,0 },
210 { "msp430f2252",0,0 },
211 { "msp430f2254",0,0 },
212 { "msp430f2272",0,0 },
213 { "msp430f2274",0,0 },
214 { "msp430f233",0,2 },
215 { "msp430f2330",0,2 },
216 { "msp430f235",0,2 },
217 { "msp430f2350",0,2 },
218 { "msp430f2370",0,2 },
219 { "msp430f2410",0,2 },
220 { "msp430f2416",1,2 },
221 { "msp430f2417",1,2 },
222 { "msp430f2418",1,2 },
223 { "msp430f2419",1,2 },
224 { "msp430f247",0,2 },
225 { "msp430f2471",0,2 },
226 { "msp430f248",0,2 },
227 { "msp430f2481",0,2 },
228 { "msp430f249",0,2 },
229 { "msp430f2491",0,2 },
230 { "msp430f2616",1,2 },
231 { "msp430f2617",1,2 },
232 { "msp430f2618",1,2 },
233 { "msp430f2619",1,2 },
234 { "msp430f412",0,0 },
235 { "msp430f413",0,0 },
236 { "msp430f4132",0,0 },
237 { "msp430f415",0,0 },
238 { "msp430f4152",0,0 },
239 { "msp430f417",0,0 },
240 { "msp430f423",0,1 },
241 { "msp430f423a",0,1 },
242 { "msp430f425",0,1 },
243 { "msp430f4250",0,0 },
244 { "msp430f425a",0,1 },
245 { "msp430f4260",0,0 },
246 { "msp430f427",0,1 },
247 { "msp430f4270",0,0 },
248 { "msp430f427a",0,1 },
249 { "msp430f435",0,0 },
250 { "msp430f4351",0,0 },
251 { "msp430f436",0,0 },
252 { "msp430f4361",0,0 },
253 { "msp430f437",0,0 },
254 { "msp430f4371",0,0 },
255 { "msp430f438",0,0 },
256 { "msp430f439",0,0 },
257 { "msp430f447",0,1 },
258 { "msp430f448",0,1 },
259 { "msp430f4481",0,1 },
260 { "msp430f449",0,1 },
261 { "msp430f4491",0,1 },
262 { "msp430f4616",1,1 },
263 { "msp430f46161",1,1 },
264 { "msp430f4617",1,1 },
265 { "msp430f46171",1,1 },
266 { "msp430f4618",1,1 },
267 { "msp430f46181",1,1 },
268 { "msp430f4619",1,1 },
269 { "msp430f46191",1,1 },
270 { "msp430f47126",1,4 },
271 { "msp430f47127",1,4 },
272 { "msp430f47163",1,4 },
273 { "msp430f47166",1,4 },
274 { "msp430f47167",1,4 },
275 { "msp430f47173",1,4 },
276 { "msp430f47176",1,4 },
277 { "msp430f47177",1,4 },
278 { "msp430f47183",1,4 },
279 { "msp430f47186",1,4 },
280 { "msp430f47187",1,4 },
281 { "msp430f47193",1,4 },
282 { "msp430f47196",1,4 },
283 { "msp430f47197",1,4 },
284 { "msp430f477",0,0 },
285 { "msp430f478",0,0 },
286 { "msp430f4783",0,4 },
287 { "msp430f4784",0,4 },
288 { "msp430f479",0,0 },
289 { "msp430f4793",0,4 },
290 { "msp430f4794",0,4 },
291 { "msp430f5131",2,8 },
292 { "msp430f5132",2,8 },
293 { "msp430f5151",2,8 },
294 { "msp430f5152",2,8 },
295 { "msp430f5171",2,8 },
296 { "msp430f5172",2,8 },
297 { "msp430f5212",2,8 },
298 { "msp430f5213",2,8 },
299 { "msp430f5214",2,8 },
300 { "msp430f5217",2,8 },
301 { "msp430f5218",2,8 },
302 { "msp430f5219",2,8 },
303 { "msp430f5222",2,8 },
304 { "msp430f5223",2,8 },
305 { "msp430f5224",2,8 },
306 { "msp430f5227",2,8 },
307 { "msp430f5228",2,8 },
308 { "msp430f5229",2,8 },
309 { "msp430f5232",2,8 },
310 { "msp430f5234",2,8 },
311 { "msp430f5237",2,8 },
312 { "msp430f5239",2,8 },
313 { "msp430f5242",2,8 },
314 { "msp430f5244",2,8 },
315 { "msp430f5247",2,8 },
316 { "msp430f5249",2,8 },
317 { "msp430f5252",2,8 },
318 { "msp430f5253",2,8 },
319 { "msp430f5254",2,8 },
320 { "msp430f5255",2,8 },
321 { "msp430f5256",2,8 },
322 { "msp430f5257",2,8 },
323 { "msp430f5258",2,8 },
324 { "msp430f5259",2,8 },
325 { "msp430f5304",2,8 },
326 { "msp430f5308",2,8 },
327 { "msp430f5309",2,8 },
328 { "msp430f5310",2,8 },
329 { "msp430f5324",2,8 },
330 { "msp430f5325",2,8 },
331 { "msp430f5326",2,8 },
332 { "msp430f5327",2,8 },
333 { "msp430f5328",2,8 },
334 { "msp430f5329",2,8 },
335 { "msp430f5333",2,8 },
336 { "msp430f5335",2,8 },
337 { "msp430f5336",2,8 },
338 { "msp430f5338",2,8 },
339 { "msp430f5340",2,8 },
340 { "msp430f5341",2,8 },
341 { "msp430f5342",2,8 },
342 { "msp430f5358",2,8 },
343 { "msp430f5359",2,8 },
344 { "msp430f5418",2,8 },
345 { "msp430f5418a",2,8 },
346 { "msp430f5419",2,8 },
347 { "msp430f5419a",2,8 },
348 { "msp430f5435",2,8 },
349 { "msp430f5435a",2,8 },
350 { "msp430f5436",2,8 },
351 { "msp430f5436a",2,8 },
352 { "msp430f5437",2,8 },
353 { "msp430f5437a",2,8 },
354 { "msp430f5438",2,8 },
355 { "msp430f5438a",2,8 },
356 { "msp430f5500",2,8 },
357 { "msp430f5501",2,8 },
358 { "msp430f5502",2,8 },
359 { "msp430f5503",2,8 },
360 { "msp430f5504",2,8 },
361 { "msp430f5505",2,8 },
362 { "msp430f5506",2,8 },
363 { "msp430f5507",2,8 },
364 { "msp430f5508",2,8 },
365 { "msp430f5509",2,8 },
366 { "msp430f5510",2,8 },
367 { "msp430f5513",2,8 },
368 { "msp430f5514",2,8 },
369 { "msp430f5515",2,8 },
370 { "msp430f5517",2,8 },
371 { "msp430f5519",2,8 },
372 { "msp430f5521",2,8 },
373 { "msp430f5522",2,8 },
374 { "msp430f5524",2,8 },
375 { "msp430f5525",2,8 },
376 { "msp430f5526",2,8 },
377 { "msp430f5527",2,8 },
378 { "msp430f5528",2,8 },
379 { "msp430f5529",2,8 },
380 { "msp430f5630",2,8 },
381 { "msp430f5631",2,8 },
382 { "msp430f5632",2,8 },
383 { "msp430f5633",2,8 },
384 { "msp430f5634",2,8 },
385 { "msp430f5635",2,8 },
386 { "msp430f5636",2,8 },
387 { "msp430f5637",2,8 },
388 { "msp430f5638",2,8 },
389 { "msp430f5658",2,8 },
390 { "msp430f5659",2,8 },
391 { "msp430f5xx_6xxgeneric",2,8 },
392 { "msp430f6433",2,8 },
393 { "msp430f6435",2,8 },
394 { "msp430f6436",2,8 },
395 { "msp430f6438",2,8 },
396 { "msp430f6458",2,8 },
397 { "msp430f6459",2,8 },
398 { "msp430f6630",2,8 },
399 { "msp430f6631",2,8 },
400 { "msp430f6632",2,8 },
401 { "msp430f6633",2,8 },
402 { "msp430f6634",2,8 },
403 { "msp430f6635",2,8 },
404 { "msp430f6636",2,8 },
405 { "msp430f6637",2,8 },
406 { "msp430f6638",2,8 },
407 { "msp430f6658",2,8 },
408 { "msp430f6659",2,8 },
409 { "msp430f6720",2,8 },
410 { "msp430f6720a",2,8 },
411 { "msp430f6721",2,8 },
412 { "msp430f6721a",2,8 },
413 { "msp430f6723",2,8 },
414 { "msp430f6723a",2,8 },
415 { "msp430f6724",2,8 },
416 { "msp430f6724a",2,8 },
417 { "msp430f6725",2,8 },
418 { "msp430f6725a",2,8 },
419 { "msp430f6726",2,8 },
420 { "msp430f6726a",2,8 },
421 { "msp430f6730",2,8 },
422 { "msp430f6730a",2,8 },
423 { "msp430f6731",2,8 },
424 { "msp430f6731a",2,8 },
425 { "msp430f6733",2,8 },
426 { "msp430f6733a",2,8 },
427 { "msp430f6734",2,8 },
428 { "msp430f6734a",2,8 },
429 { "msp430f6735",2,8 },
430 { "msp430f6735a",2,8 },
431 { "msp430f6736",2,8 },
432 { "msp430f6736a",2,8 },
433 { "msp430f6745",2,8 },
434 { "msp430f67451",2,8 },
435 { "msp430f67451a",2,8 },
436 { "msp430f6745a",2,8 },
437 { "msp430f6746",2,8 },
438 { "msp430f67461",2,8 },
439 { "msp430f67461a",2,8 },
440 { "msp430f6746a",2,8 },
441 { "msp430f6747",2,8 },
442 { "msp430f67471",2,8 },
443 { "msp430f67471a",2,8 },
444 { "msp430f6747a",2,8 },
445 { "msp430f6748",2,8 },
446 { "msp430f67481",2,8 },
447 { "msp430f67481a",2,8 },
448 { "msp430f6748a",2,8 },
449 { "msp430f6749",2,8 },
450 { "msp430f67491",2,8 },
451 { "msp430f67491a",2,8 },
452 { "msp430f6749a",2,8 },
453 { "msp430f67621",2,8 },
454 { "msp430f67621a",2,8 },
455 { "msp430f67641",2,8 },
456 { "msp430f67641a",2,8 },
457 { "msp430f6765",2,8 },
458 { "msp430f67651",2,8 },
459 { "msp430f67651a",2,8 },
460 { "msp430f6765a",2,8 },
461 { "msp430f6766",2,8 },
462 { "msp430f67661",2,8 },
463 { "msp430f67661a",2,8 },
464 { "msp430f6766a",2,8 },
465 { "msp430f6767",2,8 },
466 { "msp430f67671",2,8 },
467 { "msp430f67671a",2,8 },
468 { "msp430f6767a",2,8 },
469 { "msp430f6768",2,8 },
470 { "msp430f67681",2,8 },
471 { "msp430f67681a",2,8 },
472 { "msp430f6768a",2,8 },
473 { "msp430f6769",2,8 },
474 { "msp430f67691",2,8 },
475 { "msp430f67691a",2,8 },
476 { "msp430f6769a",2,8 },
477 { "msp430f6775",2,8 },
478 { "msp430f67751",2,8 },
479 { "msp430f67751a",2,8 },
480 { "msp430f6775a",2,8 },
481 { "msp430f6776",2,8 },
482 { "msp430f67761",2,8 },
483 { "msp430f67761a",2,8 },
484 { "msp430f6776a",2,8 },
485 { "msp430f6777",2,8 },
486 { "msp430f67771",2,8 },
487 { "msp430f67771a",2,8 },
488 { "msp430f6777a",2,8 },
489 { "msp430f6778",2,8 },
490 { "msp430f67781",2,8 },
491 { "msp430f67781a",2,8 },
492 { "msp430f6778a",2,8 },
493 { "msp430f6779",2,8 },
494 { "msp430f67791",2,8 },
495 { "msp430f67791a",2,8 },
496 { "msp430f6779a",2,8 },
497 { "msp430fe423",0,0 },
498 { "msp430fe4232",0,0 },
499 { "msp430fe423a",0,0 },
500 { "msp430fe4242",0,0 },
501 { "msp430fe425",0,0 },
502 { "msp430fe4252",0,0 },
503 { "msp430fe425a",0,0 },
504 { "msp430fe427",0,0 },
505 { "msp430fe4272",0,0 },
506 { "msp430fe427a",0,0 },
507 { "msp430fg4250",0,0 },
508 { "msp430fg4260",0,0 },
509 { "msp430fg4270",0,0 },
510 { "msp430fg437",0,0 },
511 { "msp430fg438",0,0 },
512 { "msp430fg439",0,0 },
513 { "msp430fg4616",1,1 },
514 { "msp430fg4617",1,1 },
515 { "msp430fg4618",1,1 },
516 { "msp430fg4619",1,1 },
517 { "msp430fg477",0,0 },
518 { "msp430fg478",0,0 },
519 { "msp430fg479",0,0 },
520 { "msp430fg6425",2,8 },
521 { "msp430fg6426",2,8 },
522 { "msp430fg6625",2,8 },
523 { "msp430fg6626",2,8 },
524 { "msp430fr2032",2,0 },
525 { "msp430fr2033",2,0 },
526 { "msp430fr2110",2,0 },
527 { "msp430fr2111",2,0 },
528 { "msp430fr2310",2,0 },
529 { "msp430fr2311",2,0 },
530 { "msp430fr2433",2,8 },
531 { "msp430fr2532",2,8 },
532 { "msp430fr2533",2,8 },
533 { "msp430fr2632",2,8 },
534 { "msp430fr2633",2,8 },
535 { "msp430fr2xx_4xxgeneric",2,8 },
536 { "msp430fr4131",2,0 },
537 { "msp430fr4132",2,0 },
538 { "msp430fr4133",2,0 },
539 { "msp430fr5720",2,8 },
540 { "msp430fr5721",2,8 },
541 { "msp430fr5722",2,8 },
542 { "msp430fr5723",2,8 },
543 { "msp430fr5724",2,8 },
544 { "msp430fr5725",2,8 },
545 { "msp430fr5726",2,8 },
546 { "msp430fr5727",2,8 },
547 { "msp430fr5728",2,8 },
548 { "msp430fr5729",2,8 },
549 { "msp430fr5730",2,8 },
550 { "msp430fr5731",2,8 },
551 { "msp430fr5732",2,8 },
552 { "msp430fr5733",2,8 },
553 { "msp430fr5734",2,8 },
554 { "msp430fr5735",2,8 },
555 { "msp430fr5736",2,8 },
556 { "msp430fr5737",2,8 },
557 { "msp430fr5738",2,8 },
558 { "msp430fr5739",2,8 },
559 { "msp430fr57xxgeneric",2,8 },
560 { "msp430fr5847",2,8 },
561 { "msp430fr58471",2,8 },
562 { "msp430fr5848",2,8 },
563 { "msp430fr5849",2,8 },
564 { "msp430fr5857",2,8 },
565 { "msp430fr5858",2,8 },
566 { "msp430fr5859",2,8 },
567 { "msp430fr5867",2,8 },
568 { "msp430fr58671",2,8 },
569 { "msp430fr5868",2,8 },
570 { "msp430fr5869",2,8 },
571 { "msp430fr5870",2,8 },
572 { "msp430fr5872",2,8 },
573 { "msp430fr58721",2,8 },
574 { "msp430fr5887",2,8 },
575 { "msp430fr5888",2,8 },
576 { "msp430fr5889",2,8 },
577 { "msp430fr58891",2,8 },
578 { "msp430fr5922",2,8 },
579 { "msp430fr59221",2,8 },
580 { "msp430fr5947",2,8 },
581 { "msp430fr59471",2,8 },
582 { "msp430fr5948",2,8 },
583 { "msp430fr5949",2,8 },
584 { "msp430fr5957",2,8 },
585 { "msp430fr5958",2,8 },
586 { "msp430fr5959",2,8 },
587 { "msp430fr5962",2,8 },
588 { "msp430fr5964",2,8 },
589 { "msp430fr5967",2,8 },
590 { "msp430fr5968",2,8 },
591 { "msp430fr5969",2,8 },
592 { "msp430fr59691",2,8 },
593 { "msp430fr5970",2,8 },
594 { "msp430fr5972",2,8 },
595 { "msp430fr59721",2,8 },
596 { "msp430fr5986",2,8 },
597 { "msp430fr5987",2,8 },
598 { "msp430fr5988",2,8 },
599 { "msp430fr5989",2,8 },
600 { "msp430fr59891",2,8 },
601 { "msp430fr5992",2,8 },
602 { "msp430fr5994",2,8 },
603 { "msp430fr59941",2,8 },
604 { "msp430fr5xx_6xxgeneric",2,8 },
605 { "msp430fr6820",2,8 },
606 { "msp430fr6822",2,8 },
607 { "msp430fr68221",2,8 },
608 { "msp430fr6870",2,8 },
609 { "msp430fr6872",2,8 },
610 { "msp430fr68721",2,8 },
611 { "msp430fr6877",2,8 },
612 { "msp430fr6879",2,8 },
613 { "msp430fr68791",2,8 },
614 { "msp430fr6887",2,8 },
615 { "msp430fr6888",2,8 },
616 { "msp430fr6889",2,8 },
617 { "msp430fr68891",2,8 },
618 { "msp430fr6920",2,8 },
619 { "msp430fr6922",2,8 },
620 { "msp430fr69221",2,8 },
621 { "msp430fr6927",2,8 },
622 { "msp430fr69271",2,8 },
623 { "msp430fr6928",2,8 },
624 { "msp430fr6970",2,8 },
625 { "msp430fr6972",2,8 },
626 { "msp430fr69721",2,8 },
627 { "msp430fr6977",2,8 },
628 { "msp430fr6979",2,8 },
629 { "msp430fr69791",2,8 },
630 { "msp430fr6987",2,8 },
631 { "msp430fr6988",2,8 },
632 { "msp430fr6989",2,8 },
633 { "msp430fr69891",2,8 },
634 { "msp430fw423",0,0 },
635 { "msp430fw425",0,0 },
636 { "msp430fw427",0,0 },
637 { "msp430fw428",0,0 },
638 { "msp430fw429",0,0 },
639 { "msp430g2001",0,0 },
640 { "msp430g2101",0,0 },
641 { "msp430g2102",0,0 },
642 { "msp430g2111",0,0 },
643 { "msp430g2112",0,0 },
644 { "msp430g2113",0,0 },
645 { "msp430g2121",0,0 },
646 { "msp430g2131",0,0 },
647 { "msp430g2132",0,0 },
648 { "msp430g2152",0,0 },
649 { "msp430g2153",0,0 },
650 { "msp430g2201",0,0 },
651 { "msp430g2202",0,0 },
652 { "msp430g2203",0,0 },
653 { "msp430g2210",0,0 },
654 { "msp430g2211",0,0 },
655 { "msp430g2212",0,0 },
656 { "msp430g2213",0,0 },
657 { "msp430g2221",0,0 },
658 { "msp430g2230",0,0 },
659 { "msp430g2231",0,0 },
660 { "msp430g2232",0,0 },
661 { "msp430g2233",0,0 },
662 { "msp430g2252",0,0 },
663 { "msp430g2253",0,0 },
664 { "msp430g2302",0,0 },
665 { "msp430g2303",0,0 },
666 { "msp430g2312",0,0 },
667 { "msp430g2313",0,0 },
668 { "msp430g2332",0,0 },
669 { "msp430g2333",0,0 },
670 { "msp430g2352",0,0 },
671 { "msp430g2353",0,0 },
672 { "msp430g2402",0,0 },
673 { "msp430g2403",0,0 },
674 { "msp430g2412",0,0 },
675 { "msp430g2413",0,0 },
676 { "msp430g2432",0,0 },
677 { "msp430g2433",0,0 },
678 { "msp430g2444",0,0 },
679 { "msp430g2452",0,0 },
680 { "msp430g2453",0,0 },
681 { "msp430g2513",0,0 },
682 { "msp430g2533",0,0 },
683 { "msp430g2544",0,0 },
684 { "msp430g2553",0,0 },
685 { "msp430g2744",0,0 },
686 { "msp430g2755",0,0 },
687 { "msp430g2855",0,0 },
688 { "msp430g2955",0,0 },
689 { "msp430i2020",0,2 },
690 { "msp430i2021",0,2 },
691 { "msp430i2030",0,2 },
692 { "msp430i2031",0,2 },
693 { "msp430i2040",0,2 },
694 { "msp430i2041",0,2 },
695 { "msp430i2xxgeneric",0,2 },
696 { "msp430l092",0,0 },
697 { "msp430p112",0,0 },
698 { "msp430p313",0,0 },
699 { "msp430p315",0,0 },
700 { "msp430p315s",0,0 },
701 { "msp430p325",0,0 },
702 { "msp430p337",0,1 },
703 { "msp430sl5438a",2,8 },
704 { "msp430tch5e",0,0 },
705 { "msp430xgeneric",2,8 },
706 { "rf430f5144",2,8 },
707 { "rf430f5155",2,8 },
708 { "rf430f5175",2,8 },
709 { "rf430frl152h",0,0 },
710 { "rf430frl152h_rom",0,0 },
711 { "rf430frl153h",0,0 },
712 { "rf430frl153h_rom",0,0 },
713 { "rf430frl154h",0,0 },
714 { "rf430frl154h_rom",0,0 }
717 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
718 If a specific MCU has not been selected then return a generic symbol instead. */
721 msp430_mcu_name (void)
726 static char mcu_name
[64];
728 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
729 for (i
= strlen (mcu_name
); i
--;)
730 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
734 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
738 hwmult_name (unsigned int val
)
742 case 0: return "none";
743 case 1: return "16-bit";
744 case 2: return "16-bit";
745 case 4: return "32-bit";
746 case 8: return "32-bit (5xx)";
747 default: gcc_unreachable ();
752 msp430_option_override (void)
754 /* The MSP430 architecture can safely dereference a NULL pointer. In fact,
755 there are memory mapped registers there. */
756 flag_delete_null_pointer_checks
= 0;
758 init_machine_status
= msp430_init_machine_status
;
762 /* gcc/common/config/msp430-common.c will have
763 already canonicalised the string in target_cpu. */
764 if (strcasecmp (target_cpu
, "msp430x") == 0)
766 else /* target_cpu == "msp430" - already handled by the front end. */
774 /* FIXME: If the array were alpha sorted, we could use a binary search. */
775 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
776 if (strcasecmp (msp430_mcu_data
[i
].name
, target_mcu
) == 0)
778 bool xisa
= msp430_mcu_data
[i
].revision
>= 1;
782 if (target_cpu
&& msp430x
!= xisa
)
783 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
784 target_mcu
, xisa
? "430X" : "430", msp430x
? "430X" : "430");
786 if (msp430_mcu_data
[i
].hwmpy
== 0
787 && msp430_hwmult_type
!= MSP430_HWMULT_AUTO
788 && msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
789 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
791 msp430_hwmult_type
== MSP430_HWMULT_SMALL
? "16-bit"
792 : msp430_hwmult_type
== MSP430_HWMULT_LARGE
? "32-bit" : "f5series");
793 else if (msp430_hwmult_type
== MSP430_HWMULT_SMALL
794 && msp430_mcu_data
[i
].hwmpy
!= 1
795 && msp430_mcu_data
[i
].hwmpy
!= 2 )
796 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
797 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
798 else if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
&& msp430_mcu_data
[i
].hwmpy
!= 4)
799 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
800 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
801 else if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
&& msp430_mcu_data
[i
].hwmpy
!= 8)
802 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
803 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
812 if (msp430_hwmult_type
== MSP430_HWMULT_AUTO
)
816 if (target_cpu
== NULL
)
818 "Unrecognized MCU name '%s', assuming that it is "
819 "just a MSP430 with no hardware multiply.\n"
820 "Use the -mcpu and -mhwmult options to set "
825 "Unrecognized MCU name '%s', assuming that it "
826 "has no hardware multiply.\nUse the -mhwmult "
827 "option to set this explicitly.",
831 msp430_hwmult_type
= MSP430_HWMULT_NONE
;
833 else if (target_cpu
== NULL
)
837 "Unrecognized MCU name '%s', assuming that it just "
838 "supports the MSP430 ISA.\nUse the -mcpu option to "
839 "set the ISA explicitly.",
844 else if (msp430_warn_mcu
)
845 warning (0, "Unrecognized MCU name '%s'.", target_mcu
);
849 /* The F5 series are all able to support the 430X ISA. */
850 if (target_cpu
== NULL
&& target_mcu
== NULL
&& msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
853 if (TARGET_LARGE
&& !msp430x
)
854 error ("-mlarge requires a 430X-compatible -mmcu=");
856 if (msp430_code_region
== MSP430_REGION_UPPER
&& ! msp430x
)
857 error ("-mcode-region=upper requires 430X-compatible cpu");
858 if (msp430_data_region
== MSP430_REGION_UPPER
&& ! msp430x
)
859 error ("-mdata-region=upper requires 430X-compatible cpu");
861 if (flag_exceptions
|| flag_non_call_exceptions
862 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
863 flag_omit_frame_pointer
= false;
865 flag_omit_frame_pointer
= true;
867 /* This is a hack to work around a problem with the newlib build
868 mechanism. Newlib always appends CFLAGS to the end of the GCC
869 command line and always sets -O2 in CFLAGS. Thus it is not
870 possible to build newlib with -Os enabled. Until now... */
871 if (TARGET_OPT_SPACE
&& optimize
< 3)
875 #undef TARGET_SCALAR_MODE_SUPPORTED_P
876 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
879 msp430_scalar_mode_supported_p (scalar_mode m
)
881 if (m
== PSImode
&& msp430x
)
887 return default_scalar_mode_supported_p (m
);
894 #undef TARGET_MS_BITFIELD_LAYOUT_P
895 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
898 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
907 #undef TARGET_HARD_REGNO_NREGS
908 #define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
911 msp430_hard_regno_nregs (unsigned int, machine_mode mode
)
913 if (mode
== PSImode
&& msp430x
)
915 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
919 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
921 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
924 if (mode
== PSImode
&& msp430x
)
926 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
930 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
932 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
937 return msp430_hard_regno_nregs (regno
, mode
);
940 #undef TARGET_HARD_REGNO_MODE_OK
941 #define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
944 msp430_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
946 return regno
<= (ARG_POINTER_REGNUM
947 - (unsigned int) msp430_hard_regno_nregs (regno
, mode
));
950 #undef TARGET_MODES_TIEABLE_P
951 #define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
954 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
956 if ((mode1
== PSImode
|| mode2
== SImode
)
957 || (mode1
== SImode
|| mode2
== PSImode
))
960 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
961 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
962 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
963 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
966 #undef TARGET_FRAME_POINTER_REQUIRED
967 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
970 msp430_frame_pointer_required (void)
975 #undef TARGET_CAN_ELIMINATE
976 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
979 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
980 const int to_reg ATTRIBUTE_UNUSED
)
985 /* Implements INITIAL_ELIMINATION_OFFSET. */
987 msp430_initial_elimination_offset (int from
, int to
)
989 int rv
= 0; /* As if arg to arg. */
991 msp430_compute_frame_info ();
995 case STACK_POINTER_REGNUM
:
996 rv
+= cfun
->machine
->framesize_outgoing
;
997 rv
+= cfun
->machine
->framesize_locals
;
999 case FRAME_POINTER_REGNUM
:
1000 rv
+= cfun
->machine
->framesize_regs
;
1001 /* Allow for the saved return address. */
1002 rv
+= (TARGET_LARGE
? 4 : 2);
1003 /* NB/ No need to allow for crtl->args.pretend_args_size.
1004 GCC does that for us. */
1012 case FRAME_POINTER_REGNUM
:
1013 /* Allow for the fall through above. */
1014 rv
-= (TARGET_LARGE
? 4 : 2);
1015 rv
-= cfun
->machine
->framesize_regs
;
1016 case ARG_POINTER_REGNUM
:
1025 /* Named Address Space support */
1028 /* Return the appropriate mode for a named address pointer. */
1029 #undef TARGET_ADDR_SPACE_POINTER_MODE
1030 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1031 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1032 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1034 static scalar_int_mode
1035 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1040 case ADDR_SPACE_GENERIC
:
1042 case ADDR_SPACE_NEAR
:
1044 case ADDR_SPACE_FAR
:
1049 /* Function pointers are stored in unwind_word sized
1050 variables, so make sure that unwind_word is big enough. */
1051 #undef TARGET_UNWIND_WORD_MODE
1052 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1054 static scalar_int_mode
1055 msp430_unwind_word_mode (void)
1057 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1058 return msp430x
? PSImode
: HImode
;
1061 /* Determine if one named address space is a subset of another. */
1062 #undef TARGET_ADDR_SPACE_SUBSET_P
1063 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1065 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1067 if (subset
== superset
)
1070 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1073 #undef TARGET_ADDR_SPACE_CONVERT
1074 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1075 /* Convert from one address space to another. */
1077 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1079 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1080 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1083 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1085 /* This is unpredictable, as we're truncating off usable address
1088 if (CONSTANT_P (op
))
1089 return gen_rtx_CONST (HImode
, op
);
1091 result
= gen_reg_rtx (HImode
);
1092 emit_insn (gen_truncpsihi2 (result
, op
));
1095 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1097 /* This always works. */
1099 if (CONSTANT_P (op
))
1100 return gen_rtx_CONST (PSImode
, op
);
1102 result
= gen_reg_rtx (PSImode
);
1103 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1110 /* Stack Layout and Calling Conventions. */
1112 /* For each function, we list the gcc version and the TI version on
1113 each line, where we're converting the function names. */
1114 static char const * const special_convention_function_names
[] =
1116 "__muldi3", "__mspabi_mpyll",
1117 "__udivdi3", "__mspabi_divull",
1118 "__umoddi3", "__mspabi_remull",
1119 "__divdi3", "__mspabi_divlli",
1120 "__moddi3", "__mspabi_remlli",
1124 "__adddf3", "__mspabi_addd",
1125 "__subdf3", "__mspabi_subd",
1126 "__muldf3", "__mspabi_mpyd",
1127 "__divdf3", "__mspabi_divd",
1132 /* TRUE if the function passed is a "speical" function. Special
1133 functions pass two DImode parameters in registers. */
1135 msp430_special_register_convention_p (const char *name
)
1139 for (i
= 0; special_convention_function_names
[i
]; i
++)
1140 if (! strcmp (name
, special_convention_function_names
[i
]))
1146 #undef TARGET_FUNCTION_VALUE_REGNO_P
1147 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1150 msp430_function_value_regno_p (unsigned int regno
)
1156 #undef TARGET_FUNCTION_VALUE
1157 #define TARGET_FUNCTION_VALUE msp430_function_value
1160 msp430_function_value (const_tree ret_type
,
1161 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1162 bool outgoing ATTRIBUTE_UNUSED
)
1164 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1167 #undef TARGET_LIBCALL_VALUE
1168 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1171 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1173 return gen_rtx_REG (mode
, 12);
1176 /* Implements INIT_CUMULATIVE_ARGS. */
1178 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1179 tree fntype ATTRIBUTE_UNUSED
,
1180 rtx libname ATTRIBUTE_UNUSED
,
1181 tree fndecl ATTRIBUTE_UNUSED
,
1182 int n_named_args ATTRIBUTE_UNUSED
)
1185 memset (ca
, 0, sizeof(*ca
));
1190 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1192 fname
= XSTR (libname
, 0);
1196 if (fname
&& msp430_special_register_convention_p (fname
))
1200 /* Helper function for argument passing; this function is the common
1201 code that determines where an argument will be passed. */
1203 msp430_evaluate_arg (cumulative_args_t cap
,
1205 const_tree type ATTRIBUTE_UNUSED
,
1208 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1209 int nregs
= GET_MODE_SIZE (mode
);
1218 if (mode
== PSImode
)
1221 nregs
= (nregs
+ 1) / 2;
1225 /* Function is passed two DImode operands, in R8:R11 and
1235 for (i
= 0; i
< 4; i
++)
1236 if (! ca
->reg_used
[i
])
1239 ca
->start_reg
= CA_FIRST_REG
+ i
;
1244 for (i
= 0; i
< 3; i
++)
1245 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1248 ca
->start_reg
= CA_FIRST_REG
+ i
;
1251 if (! ca
->reg_used
[3] && ca
->can_split
)
1255 ca
->start_reg
= CA_FIRST_REG
+ 3;
1262 if (! ca
->reg_used
[0]
1263 && ! ca
->reg_used
[1]
1264 && ! ca
->reg_used
[2]
1265 && ! ca
->reg_used
[3])
1268 ca
->start_reg
= CA_FIRST_REG
;
1275 #undef TARGET_PROMOTE_PROTOTYPES
1276 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1279 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1284 #undef TARGET_FUNCTION_ARG
1285 #define TARGET_FUNCTION_ARG msp430_function_arg
1288 msp430_function_arg (cumulative_args_t cap
,
1293 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1295 msp430_evaluate_arg (cap
, mode
, type
, named
);
1298 return gen_rtx_REG (mode
, ca
->start_reg
);
1303 #undef TARGET_ARG_PARTIAL_BYTES
1304 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1307 msp430_arg_partial_bytes (cumulative_args_t cap
,
1312 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1314 msp430_evaluate_arg (cap
, mode
, type
, named
);
1316 if (ca
->reg_count
&& ca
->mem_count
)
1317 return ca
->reg_count
* UNITS_PER_WORD
;
1322 #undef TARGET_PASS_BY_REFERENCE
1323 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1326 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1329 bool named ATTRIBUTE_UNUSED
)
1331 return (mode
== BLKmode
1332 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1333 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1336 #undef TARGET_CALLEE_COPIES
1337 #define TARGET_CALLEE_COPIES msp430_callee_copies
1340 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1341 machine_mode mode ATTRIBUTE_UNUSED
,
1342 const_tree type ATTRIBUTE_UNUSED
,
1343 bool named ATTRIBUTE_UNUSED
)
1348 #undef TARGET_FUNCTION_ARG_ADVANCE
1349 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1352 msp430_function_arg_advance (cumulative_args_t cap
,
1357 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1360 msp430_evaluate_arg (cap
, mode
, type
, named
);
1362 if (ca
->start_reg
>= CA_FIRST_REG
)
1363 for (i
= 0; i
< ca
->reg_count
; i
++)
1364 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1369 #undef TARGET_FUNCTION_ARG_BOUNDARY
1370 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1373 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1376 && int_size_in_bytes (type
) > 1)
1378 if (GET_MODE_BITSIZE (mode
) > 8)
1383 #undef TARGET_RETURN_IN_MEMORY
1384 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1387 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1389 machine_mode mode
= TYPE_MODE (ret_type
);
1392 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1393 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1396 if (GET_MODE_SIZE (mode
) > 8)
1402 #undef TARGET_GET_RAW_ARG_MODE
1403 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1405 static fixed_size_mode
1406 msp430_get_raw_arg_mode (int regno
)
1408 return as_a
<fixed_size_mode
> (regno
== ARG_POINTER_REGNUM
1409 ? VOIDmode
: Pmode
);
1412 #undef TARGET_GET_RAW_RESULT_MODE
1413 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1415 static fixed_size_mode
1416 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1421 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1422 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1424 #include "gimplify.h"
1427 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1430 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1431 unsigned HOST_WIDE_INT align
, boundary
;
1434 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1436 type
= build_pointer_type (type
);
1438 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1439 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1441 /* When we align parameter on stack for caller, if the parameter
1442 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1443 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1444 here with caller. */
1445 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1446 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1448 boundary
/= BITS_PER_UNIT
;
1450 /* Hoist the valist value into a temporary for the moment. */
1451 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1453 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1454 requires greater alignment, we must perform dynamic alignment. */
1455 if (boundary
> align
1456 && !integer_zerop (TYPE_SIZE (type
)))
1458 /* FIXME: This is where this function diverts from targhooks.c:
1459 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1460 if (! POINTER_TYPE_P (type
))
1462 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1463 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1464 gimplify_and_add (t
, pre_p
);
1466 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1467 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1469 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1470 gimplify_and_add (t
, pre_p
);
1476 /* If the actual alignment is less than the alignment of the type,
1477 adjust the type accordingly so that we don't assume strict alignment
1478 when dereferencing the pointer. */
1479 boundary
*= BITS_PER_UNIT
;
1480 if (boundary
< TYPE_ALIGN (type
))
1482 type
= build_variant_type_copy (type
);
1483 SET_TYPE_ALIGN (type
, boundary
);
1486 /* Compute the rounded size of the type. */
1487 type_size
= size_in_bytes (type
);
1488 rounded_size
= round_up (type_size
, align
);
1490 /* Reduce rounded_size so it's sharable with the postqueue. */
1491 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1496 /* Compute new value for AP. */
1497 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1498 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1499 gimplify_and_add (t
, pre_p
);
1501 addr
= fold_convert (build_pointer_type (type
), addr
);
1504 addr
= build_va_arg_indirect_ref (addr
);
1506 addr
= build_va_arg_indirect_ref (addr
);
1512 #define TARGET_LRA_P hook_bool_void_false
1514 /* Addressing Modes */
1516 #undef TARGET_LEGITIMATE_ADDRESS_P
1517 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1520 reg_ok_for_addr (rtx r
, bool strict
)
1524 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1525 rn
= reg_renumber
[rn
];
1526 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1534 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1535 rtx x ATTRIBUTE_UNUSED
,
1536 bool strict ATTRIBUTE_UNUSED
)
1538 switch (GET_CODE (x
))
1544 if (REG_P (XEXP (x
, 0)))
1546 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1548 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1550 switch (GET_CODE (XEXP (x
, 1)))
1563 if (!reg_ok_for_addr (x
, strict
))
1576 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1577 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1580 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1583 addr_space_t as ATTRIBUTE_UNUSED
)
1585 return msp430_legitimate_address_p (mode
, x
, strict
);
1588 #undef TARGET_ASM_INTEGER
1589 #define TARGET_ASM_INTEGER msp430_asm_integer
1591 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1593 int c
= GET_CODE (x
);
1595 if (size
== 3 && GET_MODE (x
) == PSImode
)
1601 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1602 || c
== PLUS
|| c
== MINUS
)
1604 fprintf (asm_out_file
, "\t.long\t");
1605 output_addr_const (asm_out_file
, x
);
1606 fputc ('\n', asm_out_file
);
1611 return default_assemble_integer (x
, size
, aligned_p
);
1614 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1615 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1617 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1623 #undef TARGET_LEGITIMATE_CONSTANT_P
1624 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1627 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1629 return ! CONST_INT_P (x
)
1631 /* GCC does not know the width of the PSImode, so make
1632 sure that it does not try to use a constant value that
1634 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1638 #undef TARGET_RTX_COSTS
1639 #define TARGET_RTX_COSTS msp430_rtx_costs
1641 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1643 int outer_code ATTRIBUTE_UNUSED
,
1644 int opno ATTRIBUTE_UNUSED
,
1646 bool speed ATTRIBUTE_UNUSED
)
1648 int code
= GET_CODE (x
);
1653 if (mode
== SImode
&& outer_code
== SET
)
1655 *total
= COSTS_N_INSNS (4);
1664 *total
= COSTS_N_INSNS (100);
1672 /* Function Entry and Exit */
1674 /* The MSP430 call frame looks like this:
1677 +--------------------+
1681 +--------------------+ <-- "arg pointer"
1683 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1685 +--------------------+
1686 | SR if this func has|
1687 | been called via an |
1689 +--------------------+ <-- SP before prologue, also AP
1691 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1693 +--------------------+ <-- "frame pointer"
1697 +--------------------+
1701 +--------------------+ <-- SP during function
1706 /* We use this to wrap all emitted insns in the prologue, so they get
1707 the "frame-related" (/f) flag set. */
1711 RTX_FRAME_RELATED_P (x
) = 1;
1715 /* This is the one spot that decides if a register is to be saved and
1716 restored in the prologue/epilogue. */
1718 msp430_preserve_reg_p (int regno
)
1720 /* PC, SP, SR, and the constant generator. */
1724 /* FIXME: add interrupt, EH, etc. */
1725 if (crtl
->calls_eh_return
)
1728 /* Shouldn't be more than the above, but just in case... */
1729 if (fixed_regs
[regno
])
1732 /* Interrupt handlers save all registers they use, even
1733 ones which are call saved. If they call other functions
1734 then *every* register is saved. */
1735 if (msp430_is_interrupt_func ())
1736 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1738 if (!call_used_regs
[regno
]
1739 && df_regs_ever_live_p (regno
))
1745 /* Compute all the frame-related fields in our machine_function
1748 msp430_compute_frame_info (void)
1752 cfun
->machine
->computed
= 1;
1753 cfun
->machine
->framesize_regs
= 0;
1754 cfun
->machine
->framesize_locals
= get_frame_size ();
1755 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1757 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1758 if (msp430_preserve_reg_p (i
))
1760 cfun
->machine
->need_to_save
[i
] = 1;
1761 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1764 cfun
->machine
->need_to_save
[i
] = 0;
1766 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1767 cfun
->machine
->framesize_locals
++;
1769 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1770 + cfun
->machine
->framesize_locals
1771 + cfun
->machine
->framesize_outgoing
);
1774 /* Attribute Handling. */
1776 const char * const ATTR_INTR
= "interrupt";
1777 const char * const ATTR_WAKEUP
= "wakeup";
1778 const char * const ATTR_NAKED
= "naked";
1779 const char * const ATTR_REENT
= "reentrant";
1780 const char * const ATTR_CRIT
= "critical";
1781 const char * const ATTR_LOWER
= "lower";
1782 const char * const ATTR_UPPER
= "upper";
1783 const char * const ATTR_EITHER
= "either";
1784 const char * const ATTR_NOINIT
= "noinit";
1785 const char * const ATTR_PERSIST
= "persistent";
1788 has_attr (const char * attr
, tree decl
)
1790 if (decl
== NULL_TREE
)
1792 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1796 is_interrupt_func (tree decl
= current_function_decl
)
1798 return has_attr (ATTR_INTR
, decl
);
1801 /* Returns true if the current function has the "interrupt" attribute. */
1804 msp430_is_interrupt_func (void)
1806 return is_interrupt_func (current_function_decl
);
1810 is_wakeup_func (tree decl
= current_function_decl
)
1812 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1816 is_naked_func (tree decl
= current_function_decl
)
1818 return has_attr (ATTR_NAKED
, decl
);
1822 is_reentrant_func (tree decl
= current_function_decl
)
1824 return has_attr (ATTR_REENT
, decl
);
1828 is_critical_func (tree decl
= current_function_decl
)
1830 return has_attr (ATTR_CRIT
, decl
);
1834 has_section_name (const char * name
, tree decl
= current_function_decl
)
1836 if (decl
== NULL_TREE
)
1838 return (DECL_SECTION_NAME (decl
)
1839 && (strcmp (name
, DECL_SECTION_NAME (decl
)) == 0));
1842 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1843 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1846 msp430_allocate_stack_slots_for_args (void)
1848 /* Naked functions should not allocate stack slots for arguments. */
1849 return ! is_naked_func ();
1852 /* Verify MSP430 specific attributes. */
1853 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1856 msp430_attr (tree
* node
,
1859 int flags ATTRIBUTE_UNUSED
,
1860 bool * no_add_attrs
)
1862 gcc_assert (DECL_P (* node
));
1866 /* Only the interrupt attribute takes an argument. */
1867 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1869 tree value
= TREE_VALUE (args
);
1871 switch (TREE_CODE (value
))
1874 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1875 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1876 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1877 /* Allow the attribute to be added - the linker script
1878 being used may still recognise this name. */
1879 warning (OPT_Wattributes
,
1880 "unrecognized interrupt vector argument of %qE attribute",
1885 if (wi::gtu_p (wi::to_wide (value
), 63))
1886 /* Allow the attribute to be added - the linker script
1887 being used may still recognise this value. */
1888 warning (OPT_Wattributes
,
1889 "numeric argument of %qE attribute must be in range 0..63",
1894 warning (OPT_Wattributes
,
1895 "argument of %qE attribute is not a string constant or number",
1897 *no_add_attrs
= true;
1902 const char * message
= NULL
;
1904 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1906 message
= "%qE attribute only applies to functions";
1908 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1910 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1911 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1912 message
= "interrupt handlers must be void";
1914 if (! TREE_PUBLIC (* node
))
1915 message
= "interrupt handlers cannot be static";
1917 /* Ensure interrupt handlers never get optimised out. */
1918 TREE_USED (* node
) = 1;
1919 DECL_PRESERVE_P (* node
) = 1;
1921 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1923 if (is_naked_func (* node
))
1924 message
= "naked functions cannot be reentrant";
1925 else if (is_critical_func (* node
))
1926 message
= "critical functions cannot be reentrant";
1928 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1930 if (is_naked_func (* node
))
1931 message
= "naked functions cannot be critical";
1932 else if (is_reentrant_func (* node
))
1933 message
= "reentrant functions cannot be critical";
1935 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1937 if (is_critical_func (* node
))
1938 message
= "critical functions cannot be naked";
1939 else if (is_reentrant_func (* node
))
1940 message
= "reentrant functions cannot be naked";
1945 warning (OPT_Wattributes
, message
, name
);
1946 * no_add_attrs
= true;
1953 msp430_section_attr (tree
* node
,
1956 int flags ATTRIBUTE_UNUSED
,
1957 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1959 gcc_assert (DECL_P (* node
));
1960 gcc_assert (args
== NULL
);
1962 const char * message
= NULL
;
1964 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1966 if (has_attr (ATTR_LOWER
, * node
))
1967 message
= "already marked with 'lower' attribute";
1968 else if (has_attr (ATTR_EITHER
, * node
))
1969 message
= "already marked with 'either' attribute";
1971 message
= "upper attribute needs a 430X cpu";
1973 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1975 if (has_attr (ATTR_UPPER
, * node
))
1976 message
= "already marked with 'upper' attribute";
1977 else if (has_attr (ATTR_EITHER
, * node
))
1978 message
= "already marked with 'either' attribute";
1982 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1984 if (has_attr (ATTR_LOWER
, * node
))
1985 message
= "already marked with 'lower' attribute";
1986 else if (has_attr (ATTR_UPPER
, * node
))
1987 message
= "already marked with 'upper' attribute";
1992 warning (OPT_Wattributes
, message
, name
);
1993 * no_add_attrs
= true;
2000 msp430_data_attr (tree
* node
,
2003 int flags ATTRIBUTE_UNUSED
,
2004 bool * no_add_attrs ATTRIBUTE_UNUSED
)
2006 const char * message
= NULL
;
2008 gcc_assert (DECL_P (* node
));
2009 gcc_assert (args
== NULL
);
2011 if (TREE_CODE (* node
) != VAR_DECL
)
2012 message
= G_("%qE attribute only applies to variables");
2014 /* Check that it's possible for the variable to have a section. */
2015 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2016 && DECL_SECTION_NAME (* node
))
2017 message
= G_("%qE attribute cannot be applied to variables with specific sections");
2019 if (!message
&& TREE_NAME_EQ (name
, ATTR_PERSIST
) && !TREE_STATIC (* node
)
2020 && !TREE_PUBLIC (* node
) && !DECL_EXTERNAL (* node
))
2021 message
= G_("%qE attribute has no effect on automatic variables");
2023 /* It's not clear if there is anything that can be set here to prevent the
2024 front end placing the variable before the back end can handle it, in a
2025 similar way to how DECL_COMMON is used below.
2026 So just place the variable in the .persistent section now. */
2027 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2028 && TREE_NAME_EQ (name
, ATTR_PERSIST
))
2029 set_decl_section_name (* node
, ".persistent");
2031 /* If this var is thought to be common, then change this. Common variables
2032 are assigned to sections before the backend has a chance to process them. */
2033 if (DECL_COMMON (* node
))
2034 DECL_COMMON (* node
) = 0;
2038 warning (OPT_Wattributes
, message
, name
);
2039 * no_add_attrs
= true;
2046 #undef TARGET_ATTRIBUTE_TABLE
2047 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2049 /* Table of MSP430-specific attributes. */
2050 const struct attribute_spec msp430_attribute_table
[] =
2052 /* Name min_num_args type_req, affects_type_identity
2053 max_num_args, fn_type_req
2054 decl_req handler. */
2055 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false, NULL
},
2056 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false, NULL
},
2057 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false, NULL
},
2058 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false, NULL
},
2059 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false, NULL
},
2061 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false,
2063 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false,
2065 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false,
2068 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false,
2070 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false,
2073 { NULL
, 0, 0, false, false, false, NULL
, false, NULL
}
2076 #undef TARGET_ASM_FUNCTION_PROLOGUE
2077 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2080 msp430_start_function (FILE *outfile
)
2084 fprintf (outfile
, "; start of function\n");
2086 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2088 fprintf (outfile
, "; attributes: ");
2089 if (is_naked_func ())
2090 fprintf (outfile
, "naked ");
2091 if (msp430_is_interrupt_func ())
2092 fprintf (outfile
, "interrupt ");
2093 if (is_reentrant_func ())
2094 fprintf (outfile
, "reentrant ");
2095 if (is_critical_func ())
2096 fprintf (outfile
, "critical ");
2097 if (is_wakeup_func ())
2098 fprintf (outfile
, "wakeup ");
2099 fprintf (outfile
, "\n");
2102 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2103 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2104 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2105 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2106 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2107 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2110 fprintf (outfile
, "; saved regs:");
2111 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2112 if (cfun
->machine
->need_to_save
[r
])
2114 fprintf (outfile
, " %s", reg_names
[r
]);
2118 fprintf (outfile
, "(none)");
2119 fprintf (outfile
, "\n");
2122 /* Common code to change the stack pointer. */
2124 increment_stack (HOST_WIDE_INT amount
)
2127 rtx sp
= stack_pointer_rtx
;
2134 inc
= GEN_INT (- amount
);
2136 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2138 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2142 inc
= GEN_INT (amount
);
2144 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2146 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2151 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2155 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2156 if (int_attr
!= NULL_TREE
)
2158 tree intr_vector
= TREE_VALUE (int_attr
);
2160 if (intr_vector
!= NULL_TREE
)
2164 /* Interrupt vector sections should be unique, but use of weak
2165 functions implies multiple definitions. */
2166 if (DECL_WEAK (decl
))
2168 error ("argument to interrupt attribute is unsupported for weak functions");
2171 intr_vector
= TREE_VALUE (intr_vector
);
2173 /* The interrupt attribute has a vector value. Turn this into a
2174 section name, switch to that section and put the address of
2175 the current function into that vector slot. Note msp430_attr()
2176 has already verified the vector name for us. */
2177 if (TREE_CODE (intr_vector
) == STRING_CST
)
2178 sprintf (buf
, "__interrupt_vector_%.80s",
2179 TREE_STRING_POINTER (intr_vector
));
2180 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2181 sprintf (buf
, "__interrupt_vector_%u",
2182 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2184 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2185 fputs ("\t.word\t", file
);
2186 assemble_name (file
, name
);
2192 switch_to_section (function_section (decl
));
2193 ASM_OUTPUT_TYPE_DIRECTIVE(file
, name
, "function");
2194 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2197 static const char * const lower_prefix
= ".lower";
2198 static const char * const upper_prefix
= ".upper";
2199 static const char * const either_prefix
= ".either";
2201 /* Generate a prefix for a section name, based upon
2202 the region into which the object should be placed. */
2205 gen_prefix (tree decl
)
2207 if (DECL_ONE_ONLY (decl
))
2210 /* If the user has specified a particular section then do not use any prefix. */
2211 if (has_attr ("section", decl
))
2214 /* If the function has been put in the .lowtext section (because it is an
2215 interrupt handler, and the large memory model is used), then do not add
2217 if (has_section_name (".lowtext", decl
))
2220 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2221 if (has_attr (ATTR_LOWER
, decl
))
2222 return lower_prefix
;
2224 /* If we are compiling for the MSP430 then we do not support the upper region. */
2228 if (has_attr (ATTR_UPPER
, decl
))
2229 return upper_prefix
;
2231 if (has_attr (ATTR_EITHER
, decl
))
2232 return either_prefix
;
2234 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2236 if (msp430_code_region
== MSP430_REGION_LOWER
)
2237 return lower_prefix
;
2239 if (msp430_code_region
== MSP430_REGION_UPPER
)
2240 return upper_prefix
;
2242 if (msp430_code_region
== MSP430_REGION_EITHER
)
2243 return either_prefix
;
2247 if (msp430_data_region
== MSP430_REGION_LOWER
)
2248 return lower_prefix
;
2250 if (msp430_data_region
== MSP430_REGION_UPPER
)
2251 return upper_prefix
;
2253 if (msp430_data_region
== MSP430_REGION_EITHER
)
2254 return either_prefix
;
2260 static section
* noinit_section
;
2261 static section
* persist_section
;
2263 #undef TARGET_ASM_INIT_SECTIONS
2264 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2267 msp430_init_sections (void)
2269 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2270 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2273 #undef TARGET_ASM_SELECT_SECTION
2274 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2277 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2279 gcc_assert (decl
!= NULL_TREE
);
2281 if (TREE_CODE (decl
) == STRING_CST
2282 || TREE_CODE (decl
) == CONSTRUCTOR
2283 || TREE_CODE (decl
) == INTEGER_CST
2284 || TREE_CODE (decl
) == VECTOR_CST
2285 || TREE_CODE (decl
) == COMPLEX_CST
)
2286 return default_select_section (decl
, reloc
, align
);
2288 /* In large mode we must make sure that interrupt handlers are put into
2289 low memory as the vector table only accepts 16-bit addresses. */
2290 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2291 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2293 const char * prefix
= gen_prefix (decl
);
2296 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2297 return text_section
;
2298 else if (has_attr (ATTR_NOINIT
, decl
))
2299 return noinit_section
;
2300 else if (has_attr (ATTR_PERSIST
, decl
))
2301 return persist_section
;
2303 return default_select_section (decl
, reloc
, align
);
2307 switch (categorize_decl_for_section (decl
, reloc
))
2309 case SECCAT_TEXT
: sec
= ".text"; break;
2310 case SECCAT_DATA
: sec
= ".data"; break;
2311 case SECCAT_BSS
: sec
= ".bss"; break;
2312 case SECCAT_RODATA
: sec
= ".rodata"; break;
2314 case SECCAT_RODATA_MERGE_STR
:
2315 case SECCAT_RODATA_MERGE_STR_INIT
:
2316 case SECCAT_RODATA_MERGE_CONST
:
2317 case SECCAT_SRODATA
:
2318 case SECCAT_DATA_REL
:
2319 case SECCAT_DATA_REL_LOCAL
:
2320 case SECCAT_DATA_REL_RO
:
2321 case SECCAT_DATA_REL_RO_LOCAL
:
2326 return default_select_section (decl
, reloc
, align
);
2332 const char * dec_name
= DECL_SECTION_NAME (decl
);
2333 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2335 return get_named_section (decl
, name
, 0);
2338 #undef TARGET_ASM_FUNCTION_SECTION
2339 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2342 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2346 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2347 name
= DECL_SECTION_NAME (decl
);
2349 const char * prefix
= gen_prefix (decl
);
2351 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2352 return default_function_section (decl
, freq
, startup
, exit
);
2354 name
= ACONCAT ((prefix
, name
, NULL
));
2355 return get_named_section (decl
, name
, 0);
2358 #undef TARGET_SECTION_TYPE_FLAGS
2359 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2362 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2364 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2365 name
+= strlen (lower_prefix
);
2366 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2367 name
+= strlen (upper_prefix
);
2368 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2369 name
+= strlen (either_prefix
);
2370 else if (strcmp (name
, ".noinit") == 0)
2371 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2372 else if (strcmp (name
, ".persistent") == 0)
2373 return SECTION_WRITE
| SECTION_NOTYPE
;
2375 return default_section_type_flags (decl
, name
, reloc
);
2378 #undef TARGET_ASM_UNIQUE_SECTION
2379 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2382 msp430_unique_section (tree decl
, int reloc
)
2384 gcc_assert (decl
!= NULL_TREE
);
2386 /* In large mode we must make sure that interrupt handlers are put into
2387 low memory as the vector table only accepts 16-bit addresses. */
2388 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2390 set_decl_section_name (decl
, ".lowtext");
2394 default_unique_section (decl
, reloc
);
2396 const char * prefix
;
2398 if ( TREE_CODE (decl
) == STRING_CST
2399 || TREE_CODE (decl
) == CONSTRUCTOR
2400 || TREE_CODE (decl
) == INTEGER_CST
2401 || TREE_CODE (decl
) == VECTOR_CST
2402 || TREE_CODE (decl
) == COMPLEX_CST
2403 || (prefix
= gen_prefix (decl
)) == NULL
2407 const char * dec_name
= DECL_SECTION_NAME (decl
);
2408 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2410 set_decl_section_name (decl
, name
);
2413 /* Emit a declaration of a common symbol.
2414 If a data region is in use then put the symbol into the
2415 equivalent .bss section instead. */
2418 msp430_output_aligned_decl_common (FILE * stream
,
2421 unsigned HOST_WIDE_INT size
,
2424 if (msp430_data_region
== MSP430_REGION_ANY
)
2426 fprintf (stream
, COMMON_ASM_OP
);
2427 assemble_name (stream
, name
);
2428 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2429 size
, align
/ BITS_PER_UNIT
);
2436 sec
= msp430_select_section (decl
, 0, align
);
2438 switch (msp430_data_region
)
2440 case MSP430_REGION_UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2441 case MSP430_REGION_LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2442 case MSP430_REGION_EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2446 gcc_assert (sec
!= NULL
);
2448 switch_to_section (sec
);
2449 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2450 targetm
.asm_out
.globalize_label (stream
, name
);
2451 ASM_WEAKEN_LABEL (stream
, name
);
2452 ASM_OUTPUT_LABEL (stream
, name
);
2453 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2458 msp430_do_not_relax_short_jumps (void)
2460 /* When placing code into "either" low or high memory we do not want the linker
2461 to grow the size of sections, which it can do if it is encounters a branch to
2462 a label that is too far away. So we tell the cbranch patterns to avoid using
2463 short jumps when there is a chance that the instructions will end up in a low
2466 msp430_code_region
== MSP430_REGION_EITHER
2467 || msp430_code_region
== MSP430_REGION_LOWER
2468 || has_attr (ATTR_EITHER
, current_function_decl
)
2469 || has_attr (ATTR_LOWER
, current_function_decl
);
2474 MSP430_BUILTIN_BIC_SR
,
2475 MSP430_BUILTIN_BIS_SR
,
2476 MSP430_BUILTIN_DELAY_CYCLES
,
2480 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2483 msp430_init_builtins (void)
2485 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2486 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2488 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2489 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2490 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2492 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2493 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2494 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2496 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2497 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2498 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2502 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2506 case MSP430_BUILTIN_BIC_SR
:
2507 case MSP430_BUILTIN_BIS_SR
:
2508 case MSP430_BUILTIN_DELAY_CYCLES
:
2509 return msp430_builtins
[code
];
2511 return error_mark_node
;
2515 /* These constants are really register reads, which are faster than
2516 regular constants. */
2518 cg_magic_constant (HOST_WIDE_INT c
)
2536 msp430_expand_delay_cycles (rtx arg
)
2538 HOST_WIDE_INT i
, c
, n
;
2539 /* extra cycles for MSP430X instructions */
2540 #define CYCX(M,X) (msp430x ? (X) : (M))
2542 if (GET_CODE (arg
) != CONST_INT
)
2544 error ("__delay_cycles() only takes constant arguments");
2550 if (HOST_BITS_PER_WIDE_INT
> 32)
2554 error ("__delay_cycles only takes non-negative cycle counts");
2559 emit_insn (gen_delay_cycles_start (arg
));
2561 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2562 if (c
> 3 * 0xffff + CYCX (7, 10))
2565 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2566 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2569 c
-= CYCX (14, 16) + 7 * 0x10000;
2572 if ((unsigned long long) i
> 0xffffffffULL
)
2574 error ("__delay_cycles is limited to 32-bit loop counts");
2580 i
= (c
- CYCX (14, 16)) / 7;
2581 c
-= CYCX (14, 16) + i
* 7;
2584 if (cg_magic_constant (i
& 0xffff))
2586 if (cg_magic_constant ((i
>> 16) & 0xffff))
2590 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2592 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2595 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2599 i
= (c
- CYCX (7, 10)) / 3;
2600 c
-= CYCX (7, 10) + i
* 3;
2602 if (cg_magic_constant (i
))
2606 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2608 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2613 emit_insn (gen_delay_cycles_2 ());
2619 emit_insn (gen_delay_cycles_1 ());
2623 emit_insn (gen_delay_cycles_end (arg
));
2629 msp430_expand_builtin (tree exp
,
2630 rtx target ATTRIBUTE_UNUSED
,
2631 rtx subtarget ATTRIBUTE_UNUSED
,
2632 machine_mode mode ATTRIBUTE_UNUSED
,
2633 int ignore ATTRIBUTE_UNUSED
)
2635 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2636 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2637 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2639 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2640 return msp430_expand_delay_cycles (arg1
);
2642 if (! msp430_is_interrupt_func ())
2644 error ("MSP430 builtin functions only work inside interrupt handlers");
2648 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2649 arg1
= force_reg (mode
, arg1
);
2653 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2654 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2656 internal_error ("bad builtin code");
2662 #undef TARGET_INIT_BUILTINS
2663 #define TARGET_INIT_BUILTINS msp430_init_builtins
2665 #undef TARGET_EXPAND_BUILTIN
2666 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2668 #undef TARGET_BUILTIN_DECL
2669 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2672 msp430_expand_prologue (void)
2676 /* Always use stack_pointer_rtx instead of calling
2677 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2678 that there is a single rtx representing the stack pointer,
2679 namely stack_pointer_rtx, and uses == to recognize it. */
2680 rtx sp
= stack_pointer_rtx
;
2683 if (is_naked_func ())
2685 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2686 examines the output of the gen_prologue() function. */
2687 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2691 emit_insn (gen_prologue_start_marker ());
2693 if (is_critical_func ())
2695 emit_insn (gen_push_intr_state ());
2696 emit_insn (gen_disable_interrupts ());
2698 else if (is_reentrant_func ())
2699 emit_insn (gen_disable_interrupts ());
2701 if (!cfun
->machine
->computed
)
2702 msp430_compute_frame_info ();
2704 if (flag_stack_usage_info
)
2705 current_function_static_stack_size
= cfun
->machine
->framesize
;
2707 if (crtl
->args
.pretend_args_size
)
2711 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2713 p
= emit_insn (gen_grow_and_swap ());
2715 /* Document the stack decrement... */
2716 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2717 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2718 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2720 /* ...and the establishment of a new location for the return address. */
2721 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2722 gen_rtx_PLUS (Pmode
,
2726 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2730 for (i
= 15; i
>= 4; i
--)
2731 if (cfun
->machine
->need_to_save
[i
])
2736 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2742 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2743 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2746 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2748 XVECEXP (note
, 0, 0)
2749 = F (gen_rtx_SET (stack_pointer_rtx
,
2750 gen_rtx_PLUS (Pmode
,
2752 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2754 /* *sp-- = R[i-j] */
2758 for (j
= 0; j
< count
; j
++)
2761 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2764 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2766 addr
= stack_pointer_rtx
;
2768 XVECEXP (note
, 0, j
+ 1) =
2769 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2770 gen_rtx_REG (Pmode
, i
- j
)) );
2773 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2777 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2780 if (frame_pointer_needed
)
2781 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2783 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2785 increment_stack (- fs
);
2787 emit_insn (gen_prologue_end_marker ());
2791 msp430_expand_epilogue (int is_eh
)
2797 if (is_naked_func ())
2799 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2800 examines the output of the gen_epilogue() function. */
2801 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2805 if (cfun
->machine
->need_to_save
[10])
2807 /* Check for a helper function. */
2808 helper_n
= 7; /* For when the loop below never sees a match. */
2809 for (i
= 9; i
>= 4; i
--)
2810 if (!cfun
->machine
->need_to_save
[i
])
2814 if (cfun
->machine
->need_to_save
[i
])
2823 emit_insn (gen_epilogue_start_marker ());
2825 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2826 emit_insn (gen_msp430_refsym_need_exit ());
2828 if (is_wakeup_func ())
2829 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2830 status register current residing on the stack. When this function
2831 executes its RETI instruction the SR will be updated with this saved
2832 value, thus ensuring that the processor is woken up from any low power
2833 state in which it may be residing. */
2834 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2836 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2838 increment_stack (fs
);
2842 /* We need to add the right "SP" register save just after the
2843 regular ones, so that when we pop it off we're in the EH
2844 return frame, not this one. This overwrites our own return
2845 address, but we're not going to be returning anyway. */
2846 rtx r12
= gen_rtx_REG (Pmode
, 12);
2847 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2849 /* R12 will hold the new SP. */
2850 i
= cfun
->machine
->framesize_regs
;
2851 emit_move_insn (r12
, stack_pointer_rtx
);
2852 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2853 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2854 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2857 for (i
= 4; i
<= 15; i
++)
2858 if (cfun
->machine
->need_to_save
[i
])
2862 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2868 /* Note: With TARGET_LARGE we still use
2869 POPM as POPX.A is two bytes bigger. */
2870 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2874 else if (i
== 11 - helper_n
2875 && ! msp430_is_interrupt_func ()
2876 && ! is_reentrant_func ()
2877 && ! is_critical_func ()
2878 && crtl
->args
.pretend_args_size
== 0
2879 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2883 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2887 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2892 /* Also pop SP, which puts us into the EH return frame. Except
2893 that you can't "pop" sp, you have to just load it off the
2895 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2898 if (crtl
->args
.pretend_args_size
)
2899 emit_insn (gen_swap_and_shrink ());
2901 if (is_critical_func ())
2902 emit_insn (gen_pop_intr_state ());
2903 else if (is_reentrant_func ())
2904 emit_insn (gen_enable_interrupts ());
2906 emit_jump_insn (gen_msp_return ());
2909 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2910 m32c_emit_eh_epilogue. */
2912 msp430_eh_return_stackadj_rtx (void)
2914 if (!cfun
->machine
->eh_stack_adjust
)
2918 sa
= gen_rtx_REG (Pmode
, 15);
2919 cfun
->machine
->eh_stack_adjust
= sa
;
2921 return cfun
->machine
->eh_stack_adjust
;
2924 /* This function is called before reload, to "fix" the stack in
2925 preparation for an EH return. */
2927 msp430_expand_eh_return (rtx eh_handler
)
2929 /* These are all Pmode */
2930 rtx ap
, sa
, ra
, tmp
;
2932 ap
= arg_pointer_rtx
;
2933 sa
= msp430_eh_return_stackadj_rtx ();
2937 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2938 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2939 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2940 emit_move_insn (tmp
, ra
);
2943 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2944 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2946 msp430_init_dwarf_reg_sizes_extra (tree address
)
2949 rtx addr
= expand_normal (address
);
2950 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2952 /* This needs to match msp430_unwind_word_mode (above). */
2956 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2958 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2959 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2961 if (rnum
< DWARF_FRAME_REGISTERS
)
2963 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2965 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2966 gen_int_mode (4, QImode
));
2971 /* This is a list of MD patterns that implement fixed-count shifts. */
2977 rtx (*genfunc
)(rtx
,rtx
);
2979 const_shift_helpers
[] =
2981 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2983 CSH ("slli", 1, 1, slli_1
),
2984 CSH ("slll", 1, 1, slll_1
),
2985 CSH ("slll", 2, 1, slll_2
),
2987 CSH ("srai", 1, 0, srai_1
),
2988 CSH ("sral", 1, 0, sral_1
),
2989 CSH ("sral", 2, 0, sral_2
),
2991 CSH ("srll", 1, 0, srll_1
),
2992 CSH ("srll", 2, 1, srll_2x
),
2997 /* The MSP430 ABI defines a number of helper functions that should be
2998 used for, for example, 32-bit shifts. This function is called to
2999 emit such a function, using the table above to optimize some
3002 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
3005 char *helper_const
= NULL
;
3008 machine_mode arg0mode
= GET_MODE (operands
[0]);
3009 machine_mode arg1mode
= GET_MODE (operands
[1]);
3010 machine_mode arg2mode
= GET_MODE (operands
[2]);
3011 int have_430x
= msp430x
? 1 : 0;
3013 if (CONST_INT_P (operands
[2]))
3017 for (i
=0; const_shift_helpers
[i
].name
; i
++)
3019 if (const_shift_helpers
[i
].need_430x
<= have_430x
3020 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
3021 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
3023 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
3029 if (arg1mode
== VOIDmode
)
3030 arg1mode
= arg0mode
;
3031 if (arg2mode
== VOIDmode
)
3032 arg2mode
= arg0mode
;
3034 if (arg1mode
== SImode
)
3041 && CONST_INT_P (operands
[2])
3042 && INTVAL (operands
[2]) >= 1
3043 && INTVAL (operands
[2]) <= 15)
3045 /* Note that the INTVAL is limited in value and length by the conditional above. */
3046 int len
= strlen (helper_name
) + 4;
3047 helper_const
= (char *) xmalloc (len
);
3048 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
3051 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
3054 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
3057 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
3058 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
3060 c
= emit_call_insn (c
);
3061 RTL_CONST_CALL_P (c
) = 1;
3064 use_regs (&f
, 12, arg1sz
);
3066 use_regs (&f
, arg2
, 1);
3067 add_function_usage_to (c
, f
);
3069 emit_move_insn (operands
[0],
3070 gen_rtx_REG (arg0mode
, 12));
3073 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3075 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
3077 /* constants we're looking for, not constants which are allowed. */
3078 int const_op_idx
= 1;
3080 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
3083 if (GET_CODE (operands
[const_op_idx
]) != REG
3084 && GET_CODE (operands
[const_op_idx
]) != MEM
)
3085 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3088 /* Simplify_gen_subreg() doesn't handle memory references the way we
3089 need it to below, so we use this function for when we must get a
3090 valid subreg in a "natural" state. */
3092 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3096 if (GET_CODE (r
) == SUBREG
3097 && SUBREG_BYTE (r
) == 0)
3099 rtx ireg
= SUBREG_REG (r
);
3100 machine_mode imode
= GET_MODE (ireg
);
3102 /* special case for (HI (SI (PSI ...), 0)) */
3103 if (imode
== PSImode
3106 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3108 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3110 else if (GET_CODE (r
) == MEM
)
3111 rv
= adjust_address (r
, mode
, byte
);
3112 else if (GET_CODE (r
) == SYMBOL_REF
3113 && (byte
== 0 || byte
== 2)
3116 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3117 rv
= gen_rtx_CONST (HImode
, r
);
3120 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3128 /* Called by movsi_x to generate the HImode operands. */
3130 msp430_split_movsi (rtx
*operands
)
3132 rtx op00
, op02
, op10
, op12
;
3134 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3135 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3137 if (GET_CODE (operands
[1]) == CONST
3138 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3140 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3141 op10
= gen_rtx_CONST (HImode
, op10
);
3142 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3143 op12
= gen_rtx_CONST (HImode
, op12
);
3147 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3148 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3151 if (rtx_equal_p (operands
[0], operands
[1]))
3158 else if (rtx_equal_p (op00
, op12
)
3159 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3160 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3161 /* Or storing (rN) into mem (rN). */
3162 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3180 /* The MSPABI specifies the names of various helper functions, many of
3181 which are compatible with GCC's helpers. This table maps the GCC
3182 name to the MSPABI name. */
3185 char const * const gcc_name
;
3186 char const * const ti_name
;
3188 helper_function_name_mappings
[] =
3190 /* Floating point to/from integer conversions. */
3191 { "__truncdfsf2", "__mspabi_cvtdf" },
3192 { "__extendsfdf2", "__mspabi_cvtfd" },
3193 { "__fixdfhi", "__mspabi_fixdi" },
3194 { "__fixdfsi", "__mspabi_fixdli" },
3195 { "__fixdfdi", "__mspabi_fixdlli" },
3196 { "__fixunsdfhi", "__mspabi_fixdu" },
3197 { "__fixunsdfsi", "__mspabi_fixdul" },
3198 { "__fixunsdfdi", "__mspabi_fixdull" },
3199 { "__fixsfhi", "__mspabi_fixfi" },
3200 { "__fixsfsi", "__mspabi_fixfli" },
3201 { "__fixsfdi", "__mspabi_fixflli" },
3202 { "__fixunsfhi", "__mspabi_fixfu" },
3203 { "__fixunsfsi", "__mspabi_fixful" },
3204 { "__fixunsfdi", "__mspabi_fixfull" },
3205 { "__floathisf", "__mspabi_fltif" },
3206 { "__floatsisf", "__mspabi_fltlif" },
3207 { "__floatdisf", "__mspabi_fltllif" },
3208 { "__floathidf", "__mspabi_fltid" },
3209 { "__floatsidf", "__mspabi_fltlid" },
3210 { "__floatdidf", "__mspabi_fltllid" },
3211 { "__floatunhisf", "__mspabi_fltuf" },
3212 { "__floatunsisf", "__mspabi_fltulf" },
3213 { "__floatundisf", "__mspabi_fltullf" },
3214 { "__floatunhidf", "__mspabi_fltud" },
3215 { "__floatunsidf", "__mspabi_fltuld" },
3216 { "__floatundidf", "__mspabi_fltulld" },
3218 /* Floating point comparisons. */
3219 /* GCC uses individual functions for each comparison, TI uses one
3220 compare <=> function. */
3222 /* Floating point arithmatic */
3223 { "__adddf3", "__mspabi_addd" },
3224 { "__addsf3", "__mspabi_addf" },
3225 { "__divdf3", "__mspabi_divd" },
3226 { "__divsf3", "__mspabi_divf" },
3227 { "__muldf3", "__mspabi_mpyd" },
3228 { "__mulsf3", "__mspabi_mpyf" },
3229 { "__subdf3", "__mspabi_subd" },
3230 { "__subsf3", "__mspabi_subf" },
3231 /* GCC does not use helper functions for negation */
3233 /* Integer multiply, divide, remainder. */
3234 { "__mulhi3", "__mspabi_mpyi" },
3235 { "__mulsi3", "__mspabi_mpyl" },
3236 { "__muldi3", "__mspabi_mpyll" },
3238 /* Clarify signed vs unsigned first. */
3239 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3240 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3243 { "__divhi3", "__mspabi_divi" },
3244 { "__divsi3", "__mspabi_divli" },
3245 { "__divdi3", "__mspabi_divlli" },
3246 { "__udivhi3", "__mspabi_divu" },
3247 { "__udivsi3", "__mspabi_divul" },
3248 { "__udivdi3", "__mspabi_divull" },
3249 { "__modhi3", "__mspabi_remi" },
3250 { "__modsi3", "__mspabi_remli" },
3251 { "__moddi3", "__mspabi_remlli" },
3252 { "__umodhi3", "__mspabi_remu" },
3253 { "__umodsi3", "__mspabi_remul" },
3254 { "__umoddi3", "__mspabi_remull" },
3256 /* Bitwise operations. */
3257 /* Rotation - no rotation support yet. */
3258 /* Logical left shift - gcc already does these itself. */
3259 /* Arithmetic left shift - gcc already does these itself. */
3260 /* Arithmetic right shift - gcc already does these itself. */
3265 /* Returns true if the current MCU supports an F5xxx series
3266 hardware multiper. */
3269 msp430_use_f5_series_hwmult (void)
3271 static const char * cached_match
= NULL
;
3272 static bool cached_result
;
3274 if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
3277 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3280 if (target_mcu
== cached_match
)
3281 return cached_result
;
3283 cached_match
= target_mcu
;
3285 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3286 return cached_result
= true;
3287 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3288 return cached_result
= true;
3289 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3290 return cached_result
= true;
3294 /* FIXME: This array is alpha sorted - we could use a binary search. */
3295 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3296 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3297 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3299 return cached_result
= false;
3302 /* Returns true if the current MCU has a second generation
3303 32-bit hardware multiplier. */
3306 use_32bit_hwmult (void)
3308 static const char * cached_match
= NULL
;
3309 static bool cached_result
;
3312 if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
)
3315 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3318 if (target_mcu
== cached_match
)
3319 return cached_result
;
3321 cached_match
= target_mcu
;
3323 /* FIXME: This array is alpha sorted - we could use a binary search. */
3324 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3325 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3326 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3328 return cached_result
= false;
3331 /* Returns true if the current MCU does not have a
3332 hardware multiplier of any kind. */
3335 msp430_no_hwmult (void)
3337 static const char * cached_match
= NULL
;
3338 static bool cached_result
;
3341 if (msp430_hwmult_type
== MSP430_HWMULT_NONE
)
3344 if (msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3347 if (target_mcu
== NULL
)
3350 if (target_mcu
== cached_match
)
3351 return cached_result
;
3353 cached_match
= target_mcu
;
3355 /* FIXME: This array is alpha sorted - we could use a binary search. */
3356 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3357 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3358 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3360 /* If we do not recognise the MCU name, we assume that it does not support
3361 any kind of hardware multiply - this is the safest assumption to make. */
3362 return cached_result
= true;
3365 /* This function does the same as the default, but it will replace GCC
3366 function names with the MSPABI-specified ones. */
3369 msp430_output_labelref (FILE *file
, const char *name
)
3373 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3374 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3376 name
= helper_function_name_mappings
[i
].ti_name
;
3380 /* If we have been given a specific MCU name then we may be
3381 able to make use of its hardware multiply capabilities. */
3382 if (msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
3384 if (strcmp ("__mspabi_mpyi", name
) == 0)
3386 if (msp430_use_f5_series_hwmult ())
3387 name
= "__mulhi2_f5";
3388 else if (! msp430_no_hwmult ())
3391 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3393 if (msp430_use_f5_series_hwmult ())
3394 name
= "__mulsi2_f5";
3395 else if (use_32bit_hwmult ())
3396 name
= "__mulsi2_hw32";
3397 else if (! msp430_no_hwmult ())
3405 /* Common code for msp430_print_operand... */
3408 msp430_print_operand_raw (FILE * file
, rtx op
)
3412 switch (GET_CODE (op
))
3415 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3421 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3423 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3431 output_addr_const (file
, op
);
3435 print_rtl (file
, op
);
3440 #undef TARGET_PRINT_OPERAND_ADDRESS
3441 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3443 /* Output to stdio stream FILE the assembler syntax for an
3444 instruction operand that is a memory reference whose address
3448 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3450 switch (GET_CODE (addr
))
3453 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3454 gcc_assert (REG_P (XEXP (addr
, 0)));
3455 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3459 fprintf (file
, "@");
3466 fprintf (file
, "&");
3473 msp430_print_operand_raw (file
, addr
);
3476 #undef TARGET_PRINT_OPERAND
3477 #define TARGET_PRINT_OPERAND msp430_print_operand
3479 /* A low 16-bits of int/lower of register pair
3480 B high 16-bits of int/higher of register pair
3481 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3482 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3483 H like %B (for backwards compatibility)
3485 J an integer without a # prefix
3486 L like %A (for backwards compatibility)
3487 O offset of the top of the stack
3488 Q like X but generates an A postfix
3489 R inverse of condition code, unsigned.
3490 X X instruction postfix in large mode
3493 b .B or .W or .A, depending upon the mode
3495 r inverse of condition code
3496 x like X but only for pointers. */
3499 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3503 /* We can't use c, n, a, or l. */
3507 gcc_assert (CONST_INT_P (op
));
3508 /* Print the constant value, less one. */
3509 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3512 gcc_assert (CONST_INT_P (op
));
3513 /* Print the constant value, less four. */
3514 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3517 if (GET_CODE (op
) == CONST_INT
)
3519 /* Inverse of constants */
3520 int i
= INTVAL (op
);
3521 fprintf (file
, "%d", ~i
);
3526 case 'r': /* Conditional jump where the condition is reversed. */
3527 switch (GET_CODE (op
))
3529 case EQ
: fprintf (file
, "NE"); break;
3530 case NE
: fprintf (file
, "EQ"); break;
3531 case GEU
: fprintf (file
, "LO"); break;
3532 case LTU
: fprintf (file
, "HS"); break;
3533 case GE
: fprintf (file
, "L"); break;
3534 case LT
: fprintf (file
, "GE"); break;
3535 /* Assume these have reversed operands. */
3536 case GTU
: fprintf (file
, "HS"); break;
3537 case LEU
: fprintf (file
, "LO"); break;
3538 case GT
: fprintf (file
, "GE"); break;
3539 case LE
: fprintf (file
, "L"); break;
3541 msp430_print_operand_raw (file
, op
);
3545 case 'R': /* Conditional jump where the operands are reversed. */
3546 switch (GET_CODE (op
))
3548 case GTU
: fprintf (file
, "LO"); break;
3549 case LEU
: fprintf (file
, "HS"); break;
3550 case GT
: fprintf (file
, "L"); break;
3551 case LE
: fprintf (file
, "GE"); break;
3553 msp430_print_operand_raw (file
, op
);
3557 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3558 gcc_assert (CONST_INT_P (op
));
3559 fprintf (file
, "#%d", 1 << INTVAL (op
));
3562 switch (GET_MODE (op
))
3564 case E_QImode
: fprintf (file
, ".B"); return;
3565 case E_HImode
: fprintf (file
, ".W"); return;
3566 case E_PSImode
: fprintf (file
, ".A"); return;
3567 case E_SImode
: fprintf (file
, ".A"); return;
3572 case 'L': /* Low half. */
3573 switch (GET_CODE (op
))
3576 op
= adjust_address (op
, Pmode
, 0);
3581 op
= GEN_INT (INTVAL (op
) & 0xffff);
3585 /* If you get here, figure out a test case :-) */
3590 case 'H': /* high half */
3591 switch (GET_CODE (op
))
3594 op
= adjust_address (op
, Pmode
, 2);
3597 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3600 op
= GEN_INT (INTVAL (op
) >> 16);
3604 /* If you get here, figure out a test case :-) */
3609 switch (GET_CODE (op
))
3612 op
= adjust_address (op
, Pmode
, 3);
3615 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3618 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3622 /* If you get here, figure out a test case :-) */
3627 switch (GET_CODE (op
))
3630 op
= adjust_address (op
, Pmode
, 4);
3633 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3636 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3640 /* If you get here, figure out a test case :-) */
3646 /* This is used to turn, for example, an ADD opcode into an ADDX
3647 opcode when we're using 20-bit addresses. */
3648 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3649 fprintf (file
, "X");
3650 /* We don't care which operand we use, but we want 'X' in the MD
3651 file, so we do it this way. */
3655 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3656 if (GET_MODE (op
) == PSImode
)
3657 fprintf (file
, "X");
3661 /* Likewise, for BR -> BRA. */
3663 fprintf (file
, "A");
3667 /* Computes the offset to the top of the stack for the current frame.
3668 This has to be done here rather than in, say, msp430_expand_builtin()
3669 because builtins are expanded before the frame layout is determined. */
3670 fprintf (file
, "%d",
3671 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3672 - (TARGET_LARGE
? 4 : 2));
3676 gcc_assert (GET_CODE (op
) == CONST_INT
);
3680 output_operand_lossage ("invalid operand prefix");
3684 switch (GET_CODE (op
))
3687 msp430_print_operand_raw (file
, op
);
3691 addr
= XEXP (op
, 0);
3692 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3696 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3699 switch (INTVAL (XEXP (op
, 2)))
3702 fprintf (file
, "#lo (");
3703 msp430_print_operand_raw (file
, XEXP (op
, 0));
3704 fprintf (file
, ")");
3708 fprintf (file
, "#hi (");
3709 msp430_print_operand_raw (file
, XEXP (op
, 0));
3710 fprintf (file
, ")");
3714 output_operand_lossage ("invalid zero extract");
3724 fprintf (file
, "#");
3725 msp430_print_operand_raw (file
, op
);
3728 case EQ
: fprintf (file
, "EQ"); break;
3729 case NE
: fprintf (file
, "NE"); break;
3730 case GEU
: fprintf (file
, "HS"); break;
3731 case LTU
: fprintf (file
, "LO"); break;
3732 case GE
: fprintf (file
, "GE"); break;
3733 case LT
: fprintf (file
, "L"); break;
3736 print_rtl (file
, op
);
3745 msp430_return_addr_rtx (int count
)
3751 ra_size
= TARGET_LARGE
? 4 : 2;
3752 if (crtl
->args
.pretend_args_size
)
3755 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3759 msp430_incoming_return_addr_rtx (void)
3761 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3764 /* Instruction generation stuff. */
3766 /* Generate a sequence of instructions to sign-extend an HI
3767 value into an SI value. Handles the tricky case where
3768 we are overwriting the destination. */
3771 msp430x_extendhisi (rtx
* operands
)
3773 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3774 /* Low word of dest == source word. */
3775 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3778 /* Note: This sequence is approximately the same length as invoking a helper
3779 function to perform the sign-extension, as in:
3783 CALL __mspabi_srai_15
3786 but this version does not involve any function calls or using argument
3787 registers, so it reduces register pressure. */
3788 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3790 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3791 /* High word of dest == source word. */
3792 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3794 /* No overlap between dest and source. */
3795 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3798 /* Likewise for logical right shifts. */
3800 msp430x_logical_shift_right (rtx amount
)
3802 /* The MSP430X's logical right shift instruction - RRUM - does
3803 not use an extension word, so we cannot encode a repeat count.
3804 Try various alternatives to work around this. If the count
3805 is in a register we are stuck, hence the assert. */
3806 gcc_assert (CONST_INT_P (amount
));
3808 if (INTVAL (amount
) <= 0
3809 || INTVAL (amount
) >= 16)
3810 return "# nop logical shift.";
3812 if (INTVAL (amount
) > 0
3813 && INTVAL (amount
) < 5)
3814 return "rrum.w\t%2, %0"; /* Two bytes. */
3816 if (INTVAL (amount
) > 4
3817 && INTVAL (amount
) < 9)
3818 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3820 /* First we logically shift right by one. Now we know
3821 that the top bit is zero and we can use the arithmetic
3822 right shift instruction to perform the rest of the shift. */
3823 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3826 /* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
3828 #undef TARGET_CAN_CHANGE_MODE_CLASS
3829 #define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
3832 msp430_can_change_mode_class (machine_mode from
, machine_mode to
, reg_class_t
)
3834 if ((to
== PSImode
&& from
== SImode
)
3835 || (to
== SImode
&& from
== PSImode
)
3836 || (to
== DImode
&& from
== PSImode
)
3837 || (to
== PSImode
&& from
== DImode
))
3842 struct gcc_target targetm
= TARGET_INITIALIZER
;
3844 #include "gt-msp430.h"