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/>. */
21 #define IN_TARGET_CODE 1
25 #include "coretypes.h"
30 #include "stringpool.h"
32 #include "gimple-expr.h"
38 #include "diagnostic-core.h"
39 #include "fold-const.h"
40 #include "stor-layout.h"
45 #include "langhooks.h"
49 /* This file should be included last. */
50 #include "target-def.h"
53 static void msp430_compute_frame_info (void);
57 /* Run-time Target Specification. */
61 struct GTY(()) machine_function
63 /* If set, the rest of the fields have been computed. */
65 /* Which registers need to be saved in the pro/epilogue. */
66 int need_to_save
[FIRST_PSEUDO_REGISTER
];
68 /* These fields describe the frame layout... */
70 /* 2/4 bytes for saved PC */
74 int framesize_outgoing
;
78 /* How much we adjust the stack when returning from an exception
83 /* This is our init_machine_status, as set in
84 msp_option_override. */
85 static struct machine_function
*
86 msp430_init_machine_status (void)
88 struct machine_function
*m
;
90 m
= ggc_cleared_alloc
<machine_function
> ();
95 #undef TARGET_OPTION_OVERRIDE
96 #define TARGET_OPTION_OVERRIDE msp430_option_override
98 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
99 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
100 Keep these three structures in sync.
101 The data in this structure has been extracted from version 1.194 of the
102 devices.csv file released by TI in September 2016. */
104 struct msp430_mcu_data
107 unsigned int revision
; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
108 unsigned int hwmpy
; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
112 { "cc430f5123",2,8 },
113 { "cc430f5125",2,8 },
114 { "cc430f5133",2,8 },
115 { "cc430f5135",2,8 },
116 { "cc430f5137",2,8 },
117 { "cc430f5143",2,8 },
118 { "cc430f5145",2,8 },
119 { "cc430f5147",2,8 },
120 { "cc430f6125",2,8 },
121 { "cc430f6126",2,8 },
122 { "cc430f6127",2,8 },
123 { "cc430f6135",2,8 },
124 { "cc430f6137",2,8 },
125 { "cc430f6143",2,8 },
126 { "cc430f6145",2,8 },
127 { "cc430f6147",2,8 },
128 { "msp430afe221",0,2 },
129 { "msp430afe222",0,2 },
130 { "msp430afe223",0,2 },
131 { "msp430afe231",0,2 },
132 { "msp430afe232",0,2 },
133 { "msp430afe233",0,2 },
134 { "msp430afe251",0,2 },
135 { "msp430afe252",0,2 },
136 { "msp430afe253",0,2 },
137 { "msp430bt5190",2,8 },
138 { "msp430c091",0,0 },
139 { "msp430c092",0,0 },
140 { "msp430c111",0,0 },
141 { "msp430c1111",0,0 },
142 { "msp430c112",0,0 },
143 { "msp430c1121",0,0 },
144 { "msp430c1331",0,0 },
145 { "msp430c1351",0,0 },
146 { "msp430c311s",0,0 },
147 { "msp430c312",0,0 },
148 { "msp430c313",0,0 },
149 { "msp430c314",0,0 },
150 { "msp430c315",0,0 },
151 { "msp430c323",0,0 },
152 { "msp430c325",0,0 },
153 { "msp430c336",0,1 },
154 { "msp430c337",0,1 },
155 { "msp430c412",0,0 },
156 { "msp430c413",0,0 },
157 { "msp430cg4616",1,1 },
158 { "msp430cg4617",1,1 },
159 { "msp430cg4618",1,1 },
160 { "msp430cg4619",1,1 },
161 { "msp430e112",0,0 },
162 { "msp430e313",0,0 },
163 { "msp430e315",0,0 },
164 { "msp430e325",0,0 },
165 { "msp430e337",0,1 },
166 { "msp430f110",0,0 },
167 { "msp430f1101",0,0 },
168 { "msp430f1101a",0,0 },
169 { "msp430f1111",0,0 },
170 { "msp430f1111a",0,0 },
171 { "msp430f112",0,0 },
172 { "msp430f1121",0,0 },
173 { "msp430f1121a",0,0 },
174 { "msp430f1122",0,0 },
175 { "msp430f1132",0,0 },
176 { "msp430f122",0,0 },
177 { "msp430f1222",0,0 },
178 { "msp430f123",0,0 },
179 { "msp430f1232",0,0 },
180 { "msp430f133",0,0 },
181 { "msp430f135",0,0 },
182 { "msp430f147",0,1 },
183 { "msp430f1471",0,1 },
184 { "msp430f148",0,1 },
185 { "msp430f1481",0,1 },
186 { "msp430f149",0,1 },
187 { "msp430f1491",0,1 },
188 { "msp430f155",0,0 },
189 { "msp430f156",0,0 },
190 { "msp430f157",0,0 },
191 { "msp430f1610",0,1 },
192 { "msp430f1611",0,1 },
193 { "msp430f1612",0,1 },
194 { "msp430f167",0,1 },
195 { "msp430f168",0,1 },
196 { "msp430f169",0,1 },
197 { "msp430f2001",0,0 },
198 { "msp430f2002",0,0 },
199 { "msp430f2003",0,0 },
200 { "msp430f2011",0,0 },
201 { "msp430f2012",0,0 },
202 { "msp430f2013",0,0 },
203 { "msp430f2101",0,0 },
204 { "msp430f2111",0,0 },
205 { "msp430f2112",0,0 },
206 { "msp430f2121",0,0 },
207 { "msp430f2122",0,0 },
208 { "msp430f2131",0,0 },
209 { "msp430f2132",0,0 },
210 { "msp430f2232",0,0 },
211 { "msp430f2234",0,0 },
212 { "msp430f2252",0,0 },
213 { "msp430f2254",0,0 },
214 { "msp430f2272",0,0 },
215 { "msp430f2274",0,0 },
216 { "msp430f233",0,2 },
217 { "msp430f2330",0,2 },
218 { "msp430f235",0,2 },
219 { "msp430f2350",0,2 },
220 { "msp430f2370",0,2 },
221 { "msp430f2410",0,2 },
222 { "msp430f2416",1,2 },
223 { "msp430f2417",1,2 },
224 { "msp430f2418",1,2 },
225 { "msp430f2419",1,2 },
226 { "msp430f247",0,2 },
227 { "msp430f2471",0,2 },
228 { "msp430f248",0,2 },
229 { "msp430f2481",0,2 },
230 { "msp430f249",0,2 },
231 { "msp430f2491",0,2 },
232 { "msp430f2616",1,2 },
233 { "msp430f2617",1,2 },
234 { "msp430f2618",1,2 },
235 { "msp430f2619",1,2 },
236 { "msp430f412",0,0 },
237 { "msp430f413",0,0 },
238 { "msp430f4132",0,0 },
239 { "msp430f415",0,0 },
240 { "msp430f4152",0,0 },
241 { "msp430f417",0,0 },
242 { "msp430f423",0,1 },
243 { "msp430f423a",0,1 },
244 { "msp430f425",0,1 },
245 { "msp430f4250",0,0 },
246 { "msp430f425a",0,1 },
247 { "msp430f4260",0,0 },
248 { "msp430f427",0,1 },
249 { "msp430f4270",0,0 },
250 { "msp430f427a",0,1 },
251 { "msp430f435",0,0 },
252 { "msp430f4351",0,0 },
253 { "msp430f436",0,0 },
254 { "msp430f4361",0,0 },
255 { "msp430f437",0,0 },
256 { "msp430f4371",0,0 },
257 { "msp430f438",0,0 },
258 { "msp430f439",0,0 },
259 { "msp430f447",0,1 },
260 { "msp430f448",0,1 },
261 { "msp430f4481",0,1 },
262 { "msp430f449",0,1 },
263 { "msp430f4491",0,1 },
264 { "msp430f4616",1,1 },
265 { "msp430f46161",1,1 },
266 { "msp430f4617",1,1 },
267 { "msp430f46171",1,1 },
268 { "msp430f4618",1,1 },
269 { "msp430f46181",1,1 },
270 { "msp430f4619",1,1 },
271 { "msp430f46191",1,1 },
272 { "msp430f47126",1,4 },
273 { "msp430f47127",1,4 },
274 { "msp430f47163",1,4 },
275 { "msp430f47166",1,4 },
276 { "msp430f47167",1,4 },
277 { "msp430f47173",1,4 },
278 { "msp430f47176",1,4 },
279 { "msp430f47177",1,4 },
280 { "msp430f47183",1,4 },
281 { "msp430f47186",1,4 },
282 { "msp430f47187",1,4 },
283 { "msp430f47193",1,4 },
284 { "msp430f47196",1,4 },
285 { "msp430f47197",1,4 },
286 { "msp430f477",0,0 },
287 { "msp430f478",0,0 },
288 { "msp430f4783",0,4 },
289 { "msp430f4784",0,4 },
290 { "msp430f479",0,0 },
291 { "msp430f4793",0,4 },
292 { "msp430f4794",0,4 },
293 { "msp430f5131",2,8 },
294 { "msp430f5132",2,8 },
295 { "msp430f5151",2,8 },
296 { "msp430f5152",2,8 },
297 { "msp430f5171",2,8 },
298 { "msp430f5172",2,8 },
299 { "msp430f5212",2,8 },
300 { "msp430f5213",2,8 },
301 { "msp430f5214",2,8 },
302 { "msp430f5217",2,8 },
303 { "msp430f5218",2,8 },
304 { "msp430f5219",2,8 },
305 { "msp430f5222",2,8 },
306 { "msp430f5223",2,8 },
307 { "msp430f5224",2,8 },
308 { "msp430f5227",2,8 },
309 { "msp430f5228",2,8 },
310 { "msp430f5229",2,8 },
311 { "msp430f5232",2,8 },
312 { "msp430f5234",2,8 },
313 { "msp430f5237",2,8 },
314 { "msp430f5239",2,8 },
315 { "msp430f5242",2,8 },
316 { "msp430f5244",2,8 },
317 { "msp430f5247",2,8 },
318 { "msp430f5249",2,8 },
319 { "msp430f5252",2,8 },
320 { "msp430f5253",2,8 },
321 { "msp430f5254",2,8 },
322 { "msp430f5255",2,8 },
323 { "msp430f5256",2,8 },
324 { "msp430f5257",2,8 },
325 { "msp430f5258",2,8 },
326 { "msp430f5259",2,8 },
327 { "msp430f5304",2,8 },
328 { "msp430f5308",2,8 },
329 { "msp430f5309",2,8 },
330 { "msp430f5310",2,8 },
331 { "msp430f5324",2,8 },
332 { "msp430f5325",2,8 },
333 { "msp430f5326",2,8 },
334 { "msp430f5327",2,8 },
335 { "msp430f5328",2,8 },
336 { "msp430f5329",2,8 },
337 { "msp430f5333",2,8 },
338 { "msp430f5335",2,8 },
339 { "msp430f5336",2,8 },
340 { "msp430f5338",2,8 },
341 { "msp430f5340",2,8 },
342 { "msp430f5341",2,8 },
343 { "msp430f5342",2,8 },
344 { "msp430f5358",2,8 },
345 { "msp430f5359",2,8 },
346 { "msp430f5418",2,8 },
347 { "msp430f5418a",2,8 },
348 { "msp430f5419",2,8 },
349 { "msp430f5419a",2,8 },
350 { "msp430f5435",2,8 },
351 { "msp430f5435a",2,8 },
352 { "msp430f5436",2,8 },
353 { "msp430f5436a",2,8 },
354 { "msp430f5437",2,8 },
355 { "msp430f5437a",2,8 },
356 { "msp430f5438",2,8 },
357 { "msp430f5438a",2,8 },
358 { "msp430f5500",2,8 },
359 { "msp430f5501",2,8 },
360 { "msp430f5502",2,8 },
361 { "msp430f5503",2,8 },
362 { "msp430f5504",2,8 },
363 { "msp430f5505",2,8 },
364 { "msp430f5506",2,8 },
365 { "msp430f5507",2,8 },
366 { "msp430f5508",2,8 },
367 { "msp430f5509",2,8 },
368 { "msp430f5510",2,8 },
369 { "msp430f5513",2,8 },
370 { "msp430f5514",2,8 },
371 { "msp430f5515",2,8 },
372 { "msp430f5517",2,8 },
373 { "msp430f5519",2,8 },
374 { "msp430f5521",2,8 },
375 { "msp430f5522",2,8 },
376 { "msp430f5524",2,8 },
377 { "msp430f5525",2,8 },
378 { "msp430f5526",2,8 },
379 { "msp430f5527",2,8 },
380 { "msp430f5528",2,8 },
381 { "msp430f5529",2,8 },
382 { "msp430f5630",2,8 },
383 { "msp430f5631",2,8 },
384 { "msp430f5632",2,8 },
385 { "msp430f5633",2,8 },
386 { "msp430f5634",2,8 },
387 { "msp430f5635",2,8 },
388 { "msp430f5636",2,8 },
389 { "msp430f5637",2,8 },
390 { "msp430f5638",2,8 },
391 { "msp430f5658",2,8 },
392 { "msp430f5659",2,8 },
393 { "msp430f5xx_6xxgeneric",2,8 },
394 { "msp430f6433",2,8 },
395 { "msp430f6435",2,8 },
396 { "msp430f6436",2,8 },
397 { "msp430f6438",2,8 },
398 { "msp430f6458",2,8 },
399 { "msp430f6459",2,8 },
400 { "msp430f6630",2,8 },
401 { "msp430f6631",2,8 },
402 { "msp430f6632",2,8 },
403 { "msp430f6633",2,8 },
404 { "msp430f6634",2,8 },
405 { "msp430f6635",2,8 },
406 { "msp430f6636",2,8 },
407 { "msp430f6637",2,8 },
408 { "msp430f6638",2,8 },
409 { "msp430f6658",2,8 },
410 { "msp430f6659",2,8 },
411 { "msp430f6720",2,8 },
412 { "msp430f6720a",2,8 },
413 { "msp430f6721",2,8 },
414 { "msp430f6721a",2,8 },
415 { "msp430f6723",2,8 },
416 { "msp430f6723a",2,8 },
417 { "msp430f6724",2,8 },
418 { "msp430f6724a",2,8 },
419 { "msp430f6725",2,8 },
420 { "msp430f6725a",2,8 },
421 { "msp430f6726",2,8 },
422 { "msp430f6726a",2,8 },
423 { "msp430f6730",2,8 },
424 { "msp430f6730a",2,8 },
425 { "msp430f6731",2,8 },
426 { "msp430f6731a",2,8 },
427 { "msp430f6733",2,8 },
428 { "msp430f6733a",2,8 },
429 { "msp430f6734",2,8 },
430 { "msp430f6734a",2,8 },
431 { "msp430f6735",2,8 },
432 { "msp430f6735a",2,8 },
433 { "msp430f6736",2,8 },
434 { "msp430f6736a",2,8 },
435 { "msp430f6745",2,8 },
436 { "msp430f67451",2,8 },
437 { "msp430f67451a",2,8 },
438 { "msp430f6745a",2,8 },
439 { "msp430f6746",2,8 },
440 { "msp430f67461",2,8 },
441 { "msp430f67461a",2,8 },
442 { "msp430f6746a",2,8 },
443 { "msp430f6747",2,8 },
444 { "msp430f67471",2,8 },
445 { "msp430f67471a",2,8 },
446 { "msp430f6747a",2,8 },
447 { "msp430f6748",2,8 },
448 { "msp430f67481",2,8 },
449 { "msp430f67481a",2,8 },
450 { "msp430f6748a",2,8 },
451 { "msp430f6749",2,8 },
452 { "msp430f67491",2,8 },
453 { "msp430f67491a",2,8 },
454 { "msp430f6749a",2,8 },
455 { "msp430f67621",2,8 },
456 { "msp430f67621a",2,8 },
457 { "msp430f67641",2,8 },
458 { "msp430f67641a",2,8 },
459 { "msp430f6765",2,8 },
460 { "msp430f67651",2,8 },
461 { "msp430f67651a",2,8 },
462 { "msp430f6765a",2,8 },
463 { "msp430f6766",2,8 },
464 { "msp430f67661",2,8 },
465 { "msp430f67661a",2,8 },
466 { "msp430f6766a",2,8 },
467 { "msp430f6767",2,8 },
468 { "msp430f67671",2,8 },
469 { "msp430f67671a",2,8 },
470 { "msp430f6767a",2,8 },
471 { "msp430f6768",2,8 },
472 { "msp430f67681",2,8 },
473 { "msp430f67681a",2,8 },
474 { "msp430f6768a",2,8 },
475 { "msp430f6769",2,8 },
476 { "msp430f67691",2,8 },
477 { "msp430f67691a",2,8 },
478 { "msp430f6769a",2,8 },
479 { "msp430f6775",2,8 },
480 { "msp430f67751",2,8 },
481 { "msp430f67751a",2,8 },
482 { "msp430f6775a",2,8 },
483 { "msp430f6776",2,8 },
484 { "msp430f67761",2,8 },
485 { "msp430f67761a",2,8 },
486 { "msp430f6776a",2,8 },
487 { "msp430f6777",2,8 },
488 { "msp430f67771",2,8 },
489 { "msp430f67771a",2,8 },
490 { "msp430f6777a",2,8 },
491 { "msp430f6778",2,8 },
492 { "msp430f67781",2,8 },
493 { "msp430f67781a",2,8 },
494 { "msp430f6778a",2,8 },
495 { "msp430f6779",2,8 },
496 { "msp430f67791",2,8 },
497 { "msp430f67791a",2,8 },
498 { "msp430f6779a",2,8 },
499 { "msp430fe423",0,0 },
500 { "msp430fe4232",0,0 },
501 { "msp430fe423a",0,0 },
502 { "msp430fe4242",0,0 },
503 { "msp430fe425",0,0 },
504 { "msp430fe4252",0,0 },
505 { "msp430fe425a",0,0 },
506 { "msp430fe427",0,0 },
507 { "msp430fe4272",0,0 },
508 { "msp430fe427a",0,0 },
509 { "msp430fg4250",0,0 },
510 { "msp430fg4260",0,0 },
511 { "msp430fg4270",0,0 },
512 { "msp430fg437",0,0 },
513 { "msp430fg438",0,0 },
514 { "msp430fg439",0,0 },
515 { "msp430fg4616",1,1 },
516 { "msp430fg4617",1,1 },
517 { "msp430fg4618",1,1 },
518 { "msp430fg4619",1,1 },
519 { "msp430fg477",0,0 },
520 { "msp430fg478",0,0 },
521 { "msp430fg479",0,0 },
522 { "msp430fg6425",2,8 },
523 { "msp430fg6426",2,8 },
524 { "msp430fg6625",2,8 },
525 { "msp430fg6626",2,8 },
526 { "msp430fr2032",2,0 },
527 { "msp430fr2033",2,0 },
528 { "msp430fr2110",2,0 },
529 { "msp430fr2111",2,0 },
530 { "msp430fr2310",2,0 },
531 { "msp430fr2311",2,0 },
532 { "msp430fr2433",2,8 },
533 { "msp430fr2532",2,8 },
534 { "msp430fr2533",2,8 },
535 { "msp430fr2632",2,8 },
536 { "msp430fr2633",2,8 },
537 { "msp430fr2xx_4xxgeneric",2,8 },
538 { "msp430fr4131",2,0 },
539 { "msp430fr4132",2,0 },
540 { "msp430fr4133",2,0 },
541 { "msp430fr5720",2,8 },
542 { "msp430fr5721",2,8 },
543 { "msp430fr5722",2,8 },
544 { "msp430fr5723",2,8 },
545 { "msp430fr5724",2,8 },
546 { "msp430fr5725",2,8 },
547 { "msp430fr5726",2,8 },
548 { "msp430fr5727",2,8 },
549 { "msp430fr5728",2,8 },
550 { "msp430fr5729",2,8 },
551 { "msp430fr5730",2,8 },
552 { "msp430fr5731",2,8 },
553 { "msp430fr5732",2,8 },
554 { "msp430fr5733",2,8 },
555 { "msp430fr5734",2,8 },
556 { "msp430fr5735",2,8 },
557 { "msp430fr5736",2,8 },
558 { "msp430fr5737",2,8 },
559 { "msp430fr5738",2,8 },
560 { "msp430fr5739",2,8 },
561 { "msp430fr57xxgeneric",2,8 },
562 { "msp430fr5847",2,8 },
563 { "msp430fr58471",2,8 },
564 { "msp430fr5848",2,8 },
565 { "msp430fr5849",2,8 },
566 { "msp430fr5857",2,8 },
567 { "msp430fr5858",2,8 },
568 { "msp430fr5859",2,8 },
569 { "msp430fr5867",2,8 },
570 { "msp430fr58671",2,8 },
571 { "msp430fr5868",2,8 },
572 { "msp430fr5869",2,8 },
573 { "msp430fr5870",2,8 },
574 { "msp430fr5872",2,8 },
575 { "msp430fr58721",2,8 },
576 { "msp430fr5887",2,8 },
577 { "msp430fr5888",2,8 },
578 { "msp430fr5889",2,8 },
579 { "msp430fr58891",2,8 },
580 { "msp430fr5922",2,8 },
581 { "msp430fr59221",2,8 },
582 { "msp430fr5947",2,8 },
583 { "msp430fr59471",2,8 },
584 { "msp430fr5948",2,8 },
585 { "msp430fr5949",2,8 },
586 { "msp430fr5957",2,8 },
587 { "msp430fr5958",2,8 },
588 { "msp430fr5959",2,8 },
589 { "msp430fr5962",2,8 },
590 { "msp430fr5964",2,8 },
591 { "msp430fr5967",2,8 },
592 { "msp430fr5968",2,8 },
593 { "msp430fr5969",2,8 },
594 { "msp430fr59691",2,8 },
595 { "msp430fr5970",2,8 },
596 { "msp430fr5972",2,8 },
597 { "msp430fr59721",2,8 },
598 { "msp430fr5986",2,8 },
599 { "msp430fr5987",2,8 },
600 { "msp430fr5988",2,8 },
601 { "msp430fr5989",2,8 },
602 { "msp430fr59891",2,8 },
603 { "msp430fr5992",2,8 },
604 { "msp430fr5994",2,8 },
605 { "msp430fr59941",2,8 },
606 { "msp430fr5xx_6xxgeneric",2,8 },
607 { "msp430fr6820",2,8 },
608 { "msp430fr6822",2,8 },
609 { "msp430fr68221",2,8 },
610 { "msp430fr6870",2,8 },
611 { "msp430fr6872",2,8 },
612 { "msp430fr68721",2,8 },
613 { "msp430fr6877",2,8 },
614 { "msp430fr6879",2,8 },
615 { "msp430fr68791",2,8 },
616 { "msp430fr6887",2,8 },
617 { "msp430fr6888",2,8 },
618 { "msp430fr6889",2,8 },
619 { "msp430fr68891",2,8 },
620 { "msp430fr6920",2,8 },
621 { "msp430fr6922",2,8 },
622 { "msp430fr69221",2,8 },
623 { "msp430fr6927",2,8 },
624 { "msp430fr69271",2,8 },
625 { "msp430fr6928",2,8 },
626 { "msp430fr6970",2,8 },
627 { "msp430fr6972",2,8 },
628 { "msp430fr69721",2,8 },
629 { "msp430fr6977",2,8 },
630 { "msp430fr6979",2,8 },
631 { "msp430fr69791",2,8 },
632 { "msp430fr6987",2,8 },
633 { "msp430fr6988",2,8 },
634 { "msp430fr6989",2,8 },
635 { "msp430fr69891",2,8 },
636 { "msp430fw423",0,0 },
637 { "msp430fw425",0,0 },
638 { "msp430fw427",0,0 },
639 { "msp430fw428",0,0 },
640 { "msp430fw429",0,0 },
641 { "msp430g2001",0,0 },
642 { "msp430g2101",0,0 },
643 { "msp430g2102",0,0 },
644 { "msp430g2111",0,0 },
645 { "msp430g2112",0,0 },
646 { "msp430g2113",0,0 },
647 { "msp430g2121",0,0 },
648 { "msp430g2131",0,0 },
649 { "msp430g2132",0,0 },
650 { "msp430g2152",0,0 },
651 { "msp430g2153",0,0 },
652 { "msp430g2201",0,0 },
653 { "msp430g2202",0,0 },
654 { "msp430g2203",0,0 },
655 { "msp430g2210",0,0 },
656 { "msp430g2211",0,0 },
657 { "msp430g2212",0,0 },
658 { "msp430g2213",0,0 },
659 { "msp430g2221",0,0 },
660 { "msp430g2230",0,0 },
661 { "msp430g2231",0,0 },
662 { "msp430g2232",0,0 },
663 { "msp430g2233",0,0 },
664 { "msp430g2252",0,0 },
665 { "msp430g2253",0,0 },
666 { "msp430g2302",0,0 },
667 { "msp430g2303",0,0 },
668 { "msp430g2312",0,0 },
669 { "msp430g2313",0,0 },
670 { "msp430g2332",0,0 },
671 { "msp430g2333",0,0 },
672 { "msp430g2352",0,0 },
673 { "msp430g2353",0,0 },
674 { "msp430g2402",0,0 },
675 { "msp430g2403",0,0 },
676 { "msp430g2412",0,0 },
677 { "msp430g2413",0,0 },
678 { "msp430g2432",0,0 },
679 { "msp430g2433",0,0 },
680 { "msp430g2444",0,0 },
681 { "msp430g2452",0,0 },
682 { "msp430g2453",0,0 },
683 { "msp430g2513",0,0 },
684 { "msp430g2533",0,0 },
685 { "msp430g2544",0,0 },
686 { "msp430g2553",0,0 },
687 { "msp430g2744",0,0 },
688 { "msp430g2755",0,0 },
689 { "msp430g2855",0,0 },
690 { "msp430g2955",0,0 },
691 { "msp430i2020",0,2 },
692 { "msp430i2021",0,2 },
693 { "msp430i2030",0,2 },
694 { "msp430i2031",0,2 },
695 { "msp430i2040",0,2 },
696 { "msp430i2041",0,2 },
697 { "msp430i2xxgeneric",0,2 },
698 { "msp430l092",0,0 },
699 { "msp430p112",0,0 },
700 { "msp430p313",0,0 },
701 { "msp430p315",0,0 },
702 { "msp430p315s",0,0 },
703 { "msp430p325",0,0 },
704 { "msp430p337",0,1 },
705 { "msp430sl5438a",2,8 },
706 { "msp430tch5e",0,0 },
707 { "msp430xgeneric",2,8 },
708 { "rf430f5144",2,8 },
709 { "rf430f5155",2,8 },
710 { "rf430f5175",2,8 },
711 { "rf430frl152h",0,0 },
712 { "rf430frl152h_rom",0,0 },
713 { "rf430frl153h",0,0 },
714 { "rf430frl153h_rom",0,0 },
715 { "rf430frl154h",0,0 },
716 { "rf430frl154h_rom",0,0 }
719 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
720 If a specific MCU has not been selected then return a generic symbol instead. */
723 msp430_mcu_name (void)
728 static char mcu_name
[64];
730 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
731 for (i
= strlen (mcu_name
); i
--;)
732 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
736 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
740 hwmult_name (unsigned int val
)
744 case 0: return "none";
745 case 1: return "16-bit";
746 case 2: return "16-bit";
747 case 4: return "32-bit";
748 case 8: return "32-bit (5xx)";
749 default: gcc_unreachable ();
754 msp430_option_override (void)
756 /* The MSP430 architecture can safely dereference a NULL pointer. In fact,
757 there are memory mapped registers there. */
758 flag_delete_null_pointer_checks
= 0;
760 init_machine_status
= msp430_init_machine_status
;
764 /* gcc/common/config/msp430-common.c will have
765 already canonicalised the string in target_cpu. */
766 if (strcasecmp (target_cpu
, "msp430x") == 0)
768 else /* target_cpu == "msp430" - already handled by the front end. */
776 /* FIXME: If the array were alpha sorted, we could use a binary search. */
777 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
778 if (strcasecmp (msp430_mcu_data
[i
].name
, target_mcu
) == 0)
780 bool xisa
= msp430_mcu_data
[i
].revision
>= 1;
784 if (target_cpu
&& msp430x
!= xisa
)
785 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
786 target_mcu
, xisa
? "430X" : "430", msp430x
? "430X" : "430");
788 if (msp430_mcu_data
[i
].hwmpy
== 0
789 && msp430_hwmult_type
!= MSP430_HWMULT_AUTO
790 && msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
791 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
793 msp430_hwmult_type
== MSP430_HWMULT_SMALL
? "16-bit"
794 : msp430_hwmult_type
== MSP430_HWMULT_LARGE
? "32-bit" : "f5series");
795 else if (msp430_hwmult_type
== MSP430_HWMULT_SMALL
796 && msp430_mcu_data
[i
].hwmpy
!= 1
797 && msp430_mcu_data
[i
].hwmpy
!= 2 )
798 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
799 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
800 else if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
&& msp430_mcu_data
[i
].hwmpy
!= 4)
801 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
802 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
803 else if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
&& msp430_mcu_data
[i
].hwmpy
!= 8)
804 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
805 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
814 if (msp430_hwmult_type
== MSP430_HWMULT_AUTO
)
818 if (target_cpu
== NULL
)
820 "Unrecognized MCU name '%s', assuming that it is "
821 "just a MSP430 with no hardware multiply.\n"
822 "Use the -mcpu and -mhwmult options to set "
827 "Unrecognized MCU name '%s', assuming that it "
828 "has no hardware multiply.\nUse the -mhwmult "
829 "option to set this explicitly.",
833 msp430_hwmult_type
= MSP430_HWMULT_NONE
;
835 else if (target_cpu
== NULL
)
839 "Unrecognized MCU name '%s', assuming that it just "
840 "supports the MSP430 ISA.\nUse the -mcpu option to "
841 "set the ISA explicitly.",
846 else if (msp430_warn_mcu
)
847 warning (0, "Unrecognized MCU name '%s'.", target_mcu
);
851 /* The F5 series are all able to support the 430X ISA. */
852 if (target_cpu
== NULL
&& target_mcu
== NULL
&& msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
855 if (TARGET_LARGE
&& !msp430x
)
856 error ("-mlarge requires a 430X-compatible -mmcu=");
858 if (msp430_code_region
== MSP430_REGION_UPPER
&& ! msp430x
)
859 error ("-mcode-region=upper requires 430X-compatible cpu");
860 if (msp430_data_region
== MSP430_REGION_UPPER
&& ! msp430x
)
861 error ("-mdata-region=upper requires 430X-compatible cpu");
863 if (flag_exceptions
|| flag_non_call_exceptions
864 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
865 flag_omit_frame_pointer
= false;
867 flag_omit_frame_pointer
= true;
869 /* This is a hack to work around a problem with the newlib build
870 mechanism. Newlib always appends CFLAGS to the end of the GCC
871 command line and always sets -O2 in CFLAGS. Thus it is not
872 possible to build newlib with -Os enabled. Until now... */
873 if (TARGET_OPT_SPACE
&& optimize
< 3)
877 #undef TARGET_SCALAR_MODE_SUPPORTED_P
878 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
881 msp430_scalar_mode_supported_p (scalar_mode m
)
883 if (m
== PSImode
&& msp430x
)
889 return default_scalar_mode_supported_p (m
);
896 #undef TARGET_MS_BITFIELD_LAYOUT_P
897 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
900 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
909 #undef TARGET_HARD_REGNO_NREGS
910 #define TARGET_HARD_REGNO_NREGS msp430_hard_regno_nregs
913 msp430_hard_regno_nregs (unsigned int, machine_mode mode
)
915 if (mode
== PSImode
&& msp430x
)
917 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
921 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
923 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
926 if (mode
== PSImode
&& msp430x
)
928 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
932 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
934 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
939 return msp430_hard_regno_nregs (regno
, mode
);
942 #undef TARGET_HARD_REGNO_MODE_OK
943 #define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
946 msp430_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
948 return regno
<= (ARG_POINTER_REGNUM
949 - (unsigned int) msp430_hard_regno_nregs (regno
, mode
));
952 #undef TARGET_MODES_TIEABLE_P
953 #define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
956 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
958 if ((mode1
== PSImode
|| mode2
== SImode
)
959 || (mode1
== SImode
|| mode2
== PSImode
))
962 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
963 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
964 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
965 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
968 #undef TARGET_FRAME_POINTER_REQUIRED
969 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
972 msp430_frame_pointer_required (void)
977 #undef TARGET_CAN_ELIMINATE
978 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
981 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
982 const int to_reg ATTRIBUTE_UNUSED
)
987 /* Implements INITIAL_ELIMINATION_OFFSET. */
989 msp430_initial_elimination_offset (int from
, int to
)
991 int rv
= 0; /* As if arg to arg. */
993 msp430_compute_frame_info ();
997 case STACK_POINTER_REGNUM
:
998 rv
+= cfun
->machine
->framesize_outgoing
;
999 rv
+= cfun
->machine
->framesize_locals
;
1001 case FRAME_POINTER_REGNUM
:
1002 rv
+= cfun
->machine
->framesize_regs
;
1003 /* Allow for the saved return address. */
1004 rv
+= (TARGET_LARGE
? 4 : 2);
1005 /* NB/ No need to allow for crtl->args.pretend_args_size.
1006 GCC does that for us. */
1014 case FRAME_POINTER_REGNUM
:
1015 /* Allow for the fall through above. */
1016 rv
-= (TARGET_LARGE
? 4 : 2);
1017 rv
-= cfun
->machine
->framesize_regs
;
1018 case ARG_POINTER_REGNUM
:
1027 /* Named Address Space support */
1030 /* Return the appropriate mode for a named address pointer. */
1031 #undef TARGET_ADDR_SPACE_POINTER_MODE
1032 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1033 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1034 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1036 static scalar_int_mode
1037 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1042 case ADDR_SPACE_GENERIC
:
1044 case ADDR_SPACE_NEAR
:
1046 case ADDR_SPACE_FAR
:
1051 /* Function pointers are stored in unwind_word sized
1052 variables, so make sure that unwind_word is big enough. */
1053 #undef TARGET_UNWIND_WORD_MODE
1054 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1056 static scalar_int_mode
1057 msp430_unwind_word_mode (void)
1059 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1060 return msp430x
? PSImode
: HImode
;
1063 /* Determine if one named address space is a subset of another. */
1064 #undef TARGET_ADDR_SPACE_SUBSET_P
1065 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1067 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1069 if (subset
== superset
)
1072 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1075 #undef TARGET_ADDR_SPACE_CONVERT
1076 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1077 /* Convert from one address space to another. */
1079 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1081 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1082 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1085 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1087 /* This is unpredictable, as we're truncating off usable address
1090 if (CONSTANT_P (op
))
1091 return gen_rtx_CONST (HImode
, op
);
1093 result
= gen_reg_rtx (HImode
);
1094 emit_insn (gen_truncpsihi2 (result
, op
));
1097 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1099 /* This always works. */
1101 if (CONSTANT_P (op
))
1102 return gen_rtx_CONST (PSImode
, op
);
1104 result
= gen_reg_rtx (PSImode
);
1105 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1112 /* Stack Layout and Calling Conventions. */
1114 /* For each function, we list the gcc version and the TI version on
1115 each line, where we're converting the function names. */
1116 static char const * const special_convention_function_names
[] =
1118 "__muldi3", "__mspabi_mpyll",
1119 "__udivdi3", "__mspabi_divull",
1120 "__umoddi3", "__mspabi_remull",
1121 "__divdi3", "__mspabi_divlli",
1122 "__moddi3", "__mspabi_remlli",
1126 "__adddf3", "__mspabi_addd",
1127 "__subdf3", "__mspabi_subd",
1128 "__muldf3", "__mspabi_mpyd",
1129 "__divdf3", "__mspabi_divd",
1134 /* TRUE if the function passed is a "speical" function. Special
1135 functions pass two DImode parameters in registers. */
1137 msp430_special_register_convention_p (const char *name
)
1141 for (i
= 0; special_convention_function_names
[i
]; i
++)
1142 if (! strcmp (name
, special_convention_function_names
[i
]))
1148 #undef TARGET_FUNCTION_VALUE_REGNO_P
1149 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1152 msp430_function_value_regno_p (unsigned int regno
)
1158 #undef TARGET_FUNCTION_VALUE
1159 #define TARGET_FUNCTION_VALUE msp430_function_value
1162 msp430_function_value (const_tree ret_type
,
1163 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1164 bool outgoing ATTRIBUTE_UNUSED
)
1166 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1169 #undef TARGET_LIBCALL_VALUE
1170 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1173 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1175 return gen_rtx_REG (mode
, 12);
1178 /* Implements INIT_CUMULATIVE_ARGS. */
1180 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1181 tree fntype ATTRIBUTE_UNUSED
,
1182 rtx libname ATTRIBUTE_UNUSED
,
1183 tree fndecl ATTRIBUTE_UNUSED
,
1184 int n_named_args ATTRIBUTE_UNUSED
)
1187 memset (ca
, 0, sizeof(*ca
));
1192 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1194 fname
= XSTR (libname
, 0);
1198 if (fname
&& msp430_special_register_convention_p (fname
))
1202 /* Helper function for argument passing; this function is the common
1203 code that determines where an argument will be passed. */
1205 msp430_evaluate_arg (cumulative_args_t cap
,
1207 const_tree type ATTRIBUTE_UNUSED
,
1210 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1211 int nregs
= GET_MODE_SIZE (mode
);
1220 if (mode
== PSImode
)
1223 nregs
= (nregs
+ 1) / 2;
1227 /* Function is passed two DImode operands, in R8:R11 and
1237 for (i
= 0; i
< 4; i
++)
1238 if (! ca
->reg_used
[i
])
1241 ca
->start_reg
= CA_FIRST_REG
+ i
;
1246 for (i
= 0; i
< 3; i
++)
1247 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1250 ca
->start_reg
= CA_FIRST_REG
+ i
;
1253 if (! ca
->reg_used
[3] && ca
->can_split
)
1257 ca
->start_reg
= CA_FIRST_REG
+ 3;
1264 if (! ca
->reg_used
[0]
1265 && ! ca
->reg_used
[1]
1266 && ! ca
->reg_used
[2]
1267 && ! ca
->reg_used
[3])
1270 ca
->start_reg
= CA_FIRST_REG
;
1277 #undef TARGET_PROMOTE_PROTOTYPES
1278 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1281 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1286 #undef TARGET_FUNCTION_ARG
1287 #define TARGET_FUNCTION_ARG msp430_function_arg
1290 msp430_function_arg (cumulative_args_t cap
,
1295 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1297 msp430_evaluate_arg (cap
, mode
, type
, named
);
1300 return gen_rtx_REG (mode
, ca
->start_reg
);
1305 #undef TARGET_ARG_PARTIAL_BYTES
1306 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1309 msp430_arg_partial_bytes (cumulative_args_t cap
,
1314 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1316 msp430_evaluate_arg (cap
, mode
, type
, named
);
1318 if (ca
->reg_count
&& ca
->mem_count
)
1319 return ca
->reg_count
* UNITS_PER_WORD
;
1324 #undef TARGET_PASS_BY_REFERENCE
1325 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1328 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1331 bool named ATTRIBUTE_UNUSED
)
1333 return (mode
== BLKmode
1334 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1335 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1338 #undef TARGET_CALLEE_COPIES
1339 #define TARGET_CALLEE_COPIES msp430_callee_copies
1342 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1343 machine_mode mode ATTRIBUTE_UNUSED
,
1344 const_tree type ATTRIBUTE_UNUSED
,
1345 bool named ATTRIBUTE_UNUSED
)
1350 #undef TARGET_FUNCTION_ARG_ADVANCE
1351 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1354 msp430_function_arg_advance (cumulative_args_t cap
,
1359 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1362 msp430_evaluate_arg (cap
, mode
, type
, named
);
1364 if (ca
->start_reg
>= CA_FIRST_REG
)
1365 for (i
= 0; i
< ca
->reg_count
; i
++)
1366 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1371 #undef TARGET_FUNCTION_ARG_BOUNDARY
1372 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1375 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1378 && int_size_in_bytes (type
) > 1)
1380 if (GET_MODE_BITSIZE (mode
) > 8)
1385 #undef TARGET_RETURN_IN_MEMORY
1386 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1389 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1391 machine_mode mode
= TYPE_MODE (ret_type
);
1394 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1395 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1398 if (GET_MODE_SIZE (mode
) > 8)
1404 #undef TARGET_GET_RAW_ARG_MODE
1405 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1407 static fixed_size_mode
1408 msp430_get_raw_arg_mode (int regno
)
1410 return as_a
<fixed_size_mode
> (regno
== ARG_POINTER_REGNUM
1411 ? VOIDmode
: Pmode
);
1414 #undef TARGET_GET_RAW_RESULT_MODE
1415 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1417 static fixed_size_mode
1418 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1423 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1424 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1426 #include "gimplify.h"
1429 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1432 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1433 unsigned HOST_WIDE_INT align
, boundary
;
1436 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1438 type
= build_pointer_type (type
);
1440 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1441 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1443 /* When we align parameter on stack for caller, if the parameter
1444 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1445 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1446 here with caller. */
1447 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1448 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1450 boundary
/= BITS_PER_UNIT
;
1452 /* Hoist the valist value into a temporary for the moment. */
1453 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1455 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1456 requires greater alignment, we must perform dynamic alignment. */
1457 if (boundary
> align
1458 && !integer_zerop (TYPE_SIZE (type
)))
1460 /* FIXME: This is where this function diverts from targhooks.c:
1461 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1462 if (! POINTER_TYPE_P (type
))
1464 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1465 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1466 gimplify_and_add (t
, pre_p
);
1468 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1469 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1471 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1472 gimplify_and_add (t
, pre_p
);
1478 /* If the actual alignment is less than the alignment of the type,
1479 adjust the type accordingly so that we don't assume strict alignment
1480 when dereferencing the pointer. */
1481 boundary
*= BITS_PER_UNIT
;
1482 if (boundary
< TYPE_ALIGN (type
))
1484 type
= build_variant_type_copy (type
);
1485 SET_TYPE_ALIGN (type
, boundary
);
1488 /* Compute the rounded size of the type. */
1489 type_size
= size_in_bytes (type
);
1490 rounded_size
= round_up (type_size
, align
);
1492 /* Reduce rounded_size so it's sharable with the postqueue. */
1493 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1498 /* Compute new value for AP. */
1499 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1500 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1501 gimplify_and_add (t
, pre_p
);
1503 addr
= fold_convert (build_pointer_type (type
), addr
);
1506 addr
= build_va_arg_indirect_ref (addr
);
1508 addr
= build_va_arg_indirect_ref (addr
);
1514 #define TARGET_LRA_P hook_bool_void_false
1516 /* Addressing Modes */
1518 #undef TARGET_LEGITIMATE_ADDRESS_P
1519 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1522 reg_ok_for_addr (rtx r
, bool strict
)
1526 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1527 rn
= reg_renumber
[rn
];
1528 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1536 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1537 rtx x ATTRIBUTE_UNUSED
,
1538 bool strict ATTRIBUTE_UNUSED
)
1540 switch (GET_CODE (x
))
1546 if (REG_P (XEXP (x
, 0)))
1548 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1550 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1552 switch (GET_CODE (XEXP (x
, 1)))
1565 if (!reg_ok_for_addr (x
, strict
))
1578 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1579 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1582 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1585 addr_space_t as ATTRIBUTE_UNUSED
)
1587 return msp430_legitimate_address_p (mode
, x
, strict
);
1590 #undef TARGET_ASM_INTEGER
1591 #define TARGET_ASM_INTEGER msp430_asm_integer
1593 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1595 int c
= GET_CODE (x
);
1597 if (size
== 3 && GET_MODE (x
) == PSImode
)
1603 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1604 || c
== PLUS
|| c
== MINUS
)
1606 fprintf (asm_out_file
, "\t.long\t");
1607 output_addr_const (asm_out_file
, x
);
1608 fputc ('\n', asm_out_file
);
1613 return default_assemble_integer (x
, size
, aligned_p
);
1616 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1617 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1619 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1625 #undef TARGET_LEGITIMATE_CONSTANT_P
1626 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1629 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1631 return ! CONST_INT_P (x
)
1633 /* GCC does not know the width of the PSImode, so make
1634 sure that it does not try to use a constant value that
1636 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1640 #undef TARGET_RTX_COSTS
1641 #define TARGET_RTX_COSTS msp430_rtx_costs
1643 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1645 int outer_code ATTRIBUTE_UNUSED
,
1646 int opno ATTRIBUTE_UNUSED
,
1648 bool speed ATTRIBUTE_UNUSED
)
1650 int code
= GET_CODE (x
);
1655 if (mode
== SImode
&& outer_code
== SET
)
1657 *total
= COSTS_N_INSNS (4);
1666 *total
= COSTS_N_INSNS (100);
1674 /* Function Entry and Exit */
1676 /* The MSP430 call frame looks like this:
1679 +--------------------+
1683 +--------------------+ <-- "arg pointer"
1685 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1687 +--------------------+
1688 | SR if this func has|
1689 | been called via an |
1691 +--------------------+ <-- SP before prologue, also AP
1693 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1695 +--------------------+ <-- "frame pointer"
1699 +--------------------+
1703 +--------------------+ <-- SP during function
1708 /* We use this to wrap all emitted insns in the prologue, so they get
1709 the "frame-related" (/f) flag set. */
1713 RTX_FRAME_RELATED_P (x
) = 1;
1717 /* This is the one spot that decides if a register is to be saved and
1718 restored in the prologue/epilogue. */
1720 msp430_preserve_reg_p (int regno
)
1722 /* PC, SP, SR, and the constant generator. */
1726 /* FIXME: add interrupt, EH, etc. */
1727 if (crtl
->calls_eh_return
)
1730 /* Shouldn't be more than the above, but just in case... */
1731 if (fixed_regs
[regno
])
1734 /* Interrupt handlers save all registers they use, even
1735 ones which are call saved. If they call other functions
1736 then *every* register is saved. */
1737 if (msp430_is_interrupt_func ())
1738 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1740 if (!call_used_regs
[regno
]
1741 && df_regs_ever_live_p (regno
))
1747 /* Compute all the frame-related fields in our machine_function
1750 msp430_compute_frame_info (void)
1754 cfun
->machine
->computed
= 1;
1755 cfun
->machine
->framesize_regs
= 0;
1756 cfun
->machine
->framesize_locals
= get_frame_size ();
1757 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1759 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1760 if (msp430_preserve_reg_p (i
))
1762 cfun
->machine
->need_to_save
[i
] = 1;
1763 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1766 cfun
->machine
->need_to_save
[i
] = 0;
1768 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1769 cfun
->machine
->framesize_locals
++;
1771 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1772 + cfun
->machine
->framesize_locals
1773 + cfun
->machine
->framesize_outgoing
);
1776 /* Attribute Handling. */
1778 const char * const ATTR_INTR
= "interrupt";
1779 const char * const ATTR_WAKEUP
= "wakeup";
1780 const char * const ATTR_NAKED
= "naked";
1781 const char * const ATTR_REENT
= "reentrant";
1782 const char * const ATTR_CRIT
= "critical";
1783 const char * const ATTR_LOWER
= "lower";
1784 const char * const ATTR_UPPER
= "upper";
1785 const char * const ATTR_EITHER
= "either";
1786 const char * const ATTR_NOINIT
= "noinit";
1787 const char * const ATTR_PERSIST
= "persistent";
1790 has_attr (const char * attr
, tree decl
)
1792 if (decl
== NULL_TREE
)
1794 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1798 is_interrupt_func (tree decl
= current_function_decl
)
1800 return has_attr (ATTR_INTR
, decl
);
1803 /* Returns true if the current function has the "interrupt" attribute. */
1806 msp430_is_interrupt_func (void)
1808 return is_interrupt_func (current_function_decl
);
1812 is_wakeup_func (tree decl
= current_function_decl
)
1814 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1818 is_naked_func (tree decl
= current_function_decl
)
1820 return has_attr (ATTR_NAKED
, decl
);
1824 is_reentrant_func (tree decl
= current_function_decl
)
1826 return has_attr (ATTR_REENT
, decl
);
1830 is_critical_func (tree decl
= current_function_decl
)
1832 return has_attr (ATTR_CRIT
, decl
);
1836 has_section_name (const char * name
, tree decl
= current_function_decl
)
1838 if (decl
== NULL_TREE
)
1840 return (DECL_SECTION_NAME (decl
)
1841 && (strcmp (name
, DECL_SECTION_NAME (decl
)) == 0));
1844 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1845 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1848 msp430_allocate_stack_slots_for_args (void)
1850 /* Naked functions should not allocate stack slots for arguments. */
1851 return ! is_naked_func ();
1854 /* Verify MSP430 specific attributes. */
1855 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1858 msp430_attr (tree
* node
,
1861 int flags ATTRIBUTE_UNUSED
,
1862 bool * no_add_attrs
)
1864 gcc_assert (DECL_P (* node
));
1868 /* Only the interrupt attribute takes an argument. */
1869 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1871 tree value
= TREE_VALUE (args
);
1873 switch (TREE_CODE (value
))
1876 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1877 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1878 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1879 /* Allow the attribute to be added - the linker script
1880 being used may still recognise this name. */
1881 warning (OPT_Wattributes
,
1882 "unrecognized interrupt vector argument of %qE attribute",
1887 if (wi::gtu_p (wi::to_wide (value
), 63))
1888 /* Allow the attribute to be added - the linker script
1889 being used may still recognise this value. */
1890 warning (OPT_Wattributes
,
1891 "numeric argument of %qE attribute must be in range 0..63",
1896 warning (OPT_Wattributes
,
1897 "argument of %qE attribute is not a string constant or number",
1899 *no_add_attrs
= true;
1904 const char * message
= NULL
;
1906 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1908 message
= "%qE attribute only applies to functions";
1910 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1912 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1913 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1914 message
= "interrupt handlers must be void";
1916 if (! TREE_PUBLIC (* node
))
1917 message
= "interrupt handlers cannot be static";
1919 /* Ensure interrupt handlers never get optimised out. */
1920 TREE_USED (* node
) = 1;
1921 DECL_PRESERVE_P (* node
) = 1;
1923 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1925 if (is_naked_func (* node
))
1926 message
= "naked functions cannot be reentrant";
1927 else if (is_critical_func (* node
))
1928 message
= "critical functions cannot be reentrant";
1930 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1932 if (is_naked_func (* node
))
1933 message
= "naked functions cannot be critical";
1934 else if (is_reentrant_func (* node
))
1935 message
= "reentrant functions cannot be critical";
1937 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1939 if (is_critical_func (* node
))
1940 message
= "critical functions cannot be naked";
1941 else if (is_reentrant_func (* node
))
1942 message
= "reentrant functions cannot be naked";
1947 warning (OPT_Wattributes
, message
, name
);
1948 * no_add_attrs
= true;
1955 msp430_section_attr (tree
* node
,
1958 int flags ATTRIBUTE_UNUSED
,
1959 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1961 gcc_assert (DECL_P (* node
));
1962 gcc_assert (args
== NULL
);
1964 const char * message
= NULL
;
1966 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1968 if (has_attr (ATTR_LOWER
, * node
))
1969 message
= "already marked with 'lower' attribute";
1970 else if (has_attr (ATTR_EITHER
, * node
))
1971 message
= "already marked with 'either' attribute";
1973 message
= "upper attribute needs a 430X cpu";
1975 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1977 if (has_attr (ATTR_UPPER
, * node
))
1978 message
= "already marked with 'upper' attribute";
1979 else if (has_attr (ATTR_EITHER
, * node
))
1980 message
= "already marked with 'either' attribute";
1984 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1986 if (has_attr (ATTR_LOWER
, * node
))
1987 message
= "already marked with 'lower' attribute";
1988 else if (has_attr (ATTR_UPPER
, * node
))
1989 message
= "already marked with 'upper' attribute";
1994 warning (OPT_Wattributes
, message
, name
);
1995 * no_add_attrs
= true;
2002 msp430_data_attr (tree
* node
,
2005 int flags ATTRIBUTE_UNUSED
,
2006 bool * no_add_attrs ATTRIBUTE_UNUSED
)
2008 const char * message
= NULL
;
2010 gcc_assert (DECL_P (* node
));
2011 gcc_assert (args
== NULL
);
2013 if (TREE_CODE (* node
) != VAR_DECL
)
2014 message
= G_("%qE attribute only applies to variables");
2016 /* Check that it's possible for the variable to have a section. */
2017 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2018 && DECL_SECTION_NAME (* node
))
2019 message
= G_("%qE attribute cannot be applied to variables with specific sections");
2021 if (!message
&& TREE_NAME_EQ (name
, ATTR_PERSIST
) && !TREE_STATIC (* node
)
2022 && !TREE_PUBLIC (* node
) && !DECL_EXTERNAL (* node
))
2023 message
= G_("%qE attribute has no effect on automatic variables");
2025 /* It's not clear if there is anything that can be set here to prevent the
2026 front end placing the variable before the back end can handle it, in a
2027 similar way to how DECL_COMMON is used below.
2028 So just place the variable in the .persistent section now. */
2029 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2030 && TREE_NAME_EQ (name
, ATTR_PERSIST
))
2031 set_decl_section_name (* node
, ".persistent");
2033 /* If this var is thought to be common, then change this. Common variables
2034 are assigned to sections before the backend has a chance to process them. */
2035 if (DECL_COMMON (* node
))
2036 DECL_COMMON (* node
) = 0;
2040 warning (OPT_Wattributes
, message
, name
);
2041 * no_add_attrs
= true;
2048 #undef TARGET_ATTRIBUTE_TABLE
2049 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2051 /* Table of MSP430-specific attributes. */
2052 const struct attribute_spec msp430_attribute_table
[] =
2054 /* Name min_num_args type_req, handler
2055 max_num_args, fn_type_req exclude
2056 decl_req affects_type_identity. */
2057 { ATTR_INTR
, 0, 1, true, false, false, false, msp430_attr
, NULL
},
2058 { ATTR_NAKED
, 0, 0, true, false, false, false, msp430_attr
, NULL
},
2059 { ATTR_REENT
, 0, 0, true, false, false, false, msp430_attr
, NULL
},
2060 { ATTR_CRIT
, 0, 0, true, false, false, false, msp430_attr
, NULL
},
2061 { ATTR_WAKEUP
, 0, 0, true, false, false, false, msp430_attr
, NULL
},
2063 { ATTR_LOWER
, 0, 0, true, false, false, false, msp430_section_attr
,
2065 { ATTR_UPPER
, 0, 0, true, false, false, false, msp430_section_attr
,
2067 { ATTR_EITHER
, 0, 0, true, false, false, false, msp430_section_attr
,
2070 { ATTR_NOINIT
, 0, 0, true, false, false, false, msp430_data_attr
,
2072 { ATTR_PERSIST
, 0, 0, true, false, false, false, msp430_data_attr
,
2075 { NULL
, 0, 0, false, false, false, false, NULL
, NULL
}
2078 #undef TARGET_ASM_FUNCTION_PROLOGUE
2079 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2082 msp430_start_function (FILE *outfile
)
2086 fprintf (outfile
, "; start of function\n");
2088 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2090 fprintf (outfile
, "; attributes: ");
2091 if (is_naked_func ())
2092 fprintf (outfile
, "naked ");
2093 if (msp430_is_interrupt_func ())
2094 fprintf (outfile
, "interrupt ");
2095 if (is_reentrant_func ())
2096 fprintf (outfile
, "reentrant ");
2097 if (is_critical_func ())
2098 fprintf (outfile
, "critical ");
2099 if (is_wakeup_func ())
2100 fprintf (outfile
, "wakeup ");
2101 fprintf (outfile
, "\n");
2104 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2105 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2106 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2107 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2108 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2109 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2112 fprintf (outfile
, "; saved regs:");
2113 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2114 if (cfun
->machine
->need_to_save
[r
])
2116 fprintf (outfile
, " %s", reg_names
[r
]);
2120 fprintf (outfile
, "(none)");
2121 fprintf (outfile
, "\n");
2124 /* Common code to change the stack pointer. */
2126 increment_stack (HOST_WIDE_INT amount
)
2129 rtx sp
= stack_pointer_rtx
;
2136 inc
= GEN_INT (- amount
);
2138 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2140 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2144 inc
= GEN_INT (amount
);
2146 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2148 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2153 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2157 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2158 if (int_attr
!= NULL_TREE
)
2160 tree intr_vector
= TREE_VALUE (int_attr
);
2162 if (intr_vector
!= NULL_TREE
)
2166 /* Interrupt vector sections should be unique, but use of weak
2167 functions implies multiple definitions. */
2168 if (DECL_WEAK (decl
))
2170 error ("argument to interrupt attribute is unsupported for weak functions");
2173 intr_vector
= TREE_VALUE (intr_vector
);
2175 /* The interrupt attribute has a vector value. Turn this into a
2176 section name, switch to that section and put the address of
2177 the current function into that vector slot. Note msp430_attr()
2178 has already verified the vector name for us. */
2179 if (TREE_CODE (intr_vector
) == STRING_CST
)
2180 sprintf (buf
, "__interrupt_vector_%.80s",
2181 TREE_STRING_POINTER (intr_vector
));
2182 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2183 sprintf (buf
, "__interrupt_vector_%u",
2184 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2186 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2187 fputs ("\t.word\t", file
);
2188 assemble_name (file
, name
);
2194 switch_to_section (function_section (decl
));
2195 ASM_OUTPUT_TYPE_DIRECTIVE(file
, name
, "function");
2196 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2199 static const char * const lower_prefix
= ".lower";
2200 static const char * const upper_prefix
= ".upper";
2201 static const char * const either_prefix
= ".either";
2203 /* Generate a prefix for a section name, based upon
2204 the region into which the object should be placed. */
2207 gen_prefix (tree decl
)
2209 if (DECL_ONE_ONLY (decl
))
2212 /* If the user has specified a particular section then do not use any prefix. */
2213 if (has_attr ("section", decl
))
2216 /* If the function has been put in the .lowtext section (because it is an
2217 interrupt handler, and the large memory model is used), then do not add
2219 if (has_section_name (".lowtext", decl
))
2222 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2223 if (has_attr (ATTR_LOWER
, decl
))
2224 return lower_prefix
;
2226 /* If we are compiling for the MSP430 then we do not support the upper region. */
2230 if (has_attr (ATTR_UPPER
, decl
))
2231 return upper_prefix
;
2233 if (has_attr (ATTR_EITHER
, decl
))
2234 return either_prefix
;
2236 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2238 if (msp430_code_region
== MSP430_REGION_LOWER
)
2239 return lower_prefix
;
2241 if (msp430_code_region
== MSP430_REGION_UPPER
)
2242 return upper_prefix
;
2244 if (msp430_code_region
== MSP430_REGION_EITHER
)
2245 return either_prefix
;
2249 if (msp430_data_region
== MSP430_REGION_LOWER
)
2250 return lower_prefix
;
2252 if (msp430_data_region
== MSP430_REGION_UPPER
)
2253 return upper_prefix
;
2255 if (msp430_data_region
== MSP430_REGION_EITHER
)
2256 return either_prefix
;
2262 static section
* noinit_section
;
2263 static section
* persist_section
;
2265 #undef TARGET_ASM_INIT_SECTIONS
2266 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2269 msp430_init_sections (void)
2271 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2272 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2275 #undef TARGET_ASM_SELECT_SECTION
2276 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2279 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2281 gcc_assert (decl
!= NULL_TREE
);
2283 if (TREE_CODE (decl
) == STRING_CST
2284 || TREE_CODE (decl
) == CONSTRUCTOR
2285 || TREE_CODE (decl
) == INTEGER_CST
2286 || TREE_CODE (decl
) == VECTOR_CST
2287 || TREE_CODE (decl
) == COMPLEX_CST
)
2288 return default_select_section (decl
, reloc
, align
);
2290 /* In large mode we must make sure that interrupt handlers are put into
2291 low memory as the vector table only accepts 16-bit addresses. */
2292 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2293 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2295 const char * prefix
= gen_prefix (decl
);
2298 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2299 return text_section
;
2300 else if (has_attr (ATTR_NOINIT
, decl
))
2301 return noinit_section
;
2302 else if (has_attr (ATTR_PERSIST
, decl
))
2303 return persist_section
;
2305 return default_select_section (decl
, reloc
, align
);
2309 switch (categorize_decl_for_section (decl
, reloc
))
2311 case SECCAT_TEXT
: sec
= ".text"; break;
2312 case SECCAT_DATA
: sec
= ".data"; break;
2313 case SECCAT_BSS
: sec
= ".bss"; break;
2314 case SECCAT_RODATA
: sec
= ".rodata"; break;
2316 case SECCAT_RODATA_MERGE_STR
:
2317 case SECCAT_RODATA_MERGE_STR_INIT
:
2318 case SECCAT_RODATA_MERGE_CONST
:
2319 case SECCAT_SRODATA
:
2320 case SECCAT_DATA_REL
:
2321 case SECCAT_DATA_REL_LOCAL
:
2322 case SECCAT_DATA_REL_RO
:
2323 case SECCAT_DATA_REL_RO_LOCAL
:
2328 return default_select_section (decl
, reloc
, align
);
2334 const char * dec_name
= DECL_SECTION_NAME (decl
);
2335 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2337 return get_named_section (decl
, name
, 0);
2340 #undef TARGET_ASM_FUNCTION_SECTION
2341 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2344 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2348 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2349 name
= DECL_SECTION_NAME (decl
);
2351 const char * prefix
= gen_prefix (decl
);
2353 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2354 return default_function_section (decl
, freq
, startup
, exit
);
2356 name
= ACONCAT ((prefix
, name
, NULL
));
2357 return get_named_section (decl
, name
, 0);
2360 #undef TARGET_SECTION_TYPE_FLAGS
2361 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2364 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2366 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2367 name
+= strlen (lower_prefix
);
2368 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2369 name
+= strlen (upper_prefix
);
2370 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2371 name
+= strlen (either_prefix
);
2372 else if (strcmp (name
, ".noinit") == 0)
2373 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2374 else if (strcmp (name
, ".persistent") == 0)
2375 return SECTION_WRITE
| SECTION_NOTYPE
;
2377 return default_section_type_flags (decl
, name
, reloc
);
2380 #undef TARGET_ASM_UNIQUE_SECTION
2381 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2384 msp430_unique_section (tree decl
, int reloc
)
2386 gcc_assert (decl
!= NULL_TREE
);
2388 /* In large mode we must make sure that interrupt handlers are put into
2389 low memory as the vector table only accepts 16-bit addresses. */
2390 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2392 set_decl_section_name (decl
, ".lowtext");
2396 default_unique_section (decl
, reloc
);
2398 const char * prefix
;
2400 if ( TREE_CODE (decl
) == STRING_CST
2401 || TREE_CODE (decl
) == CONSTRUCTOR
2402 || TREE_CODE (decl
) == INTEGER_CST
2403 || TREE_CODE (decl
) == VECTOR_CST
2404 || TREE_CODE (decl
) == COMPLEX_CST
2405 || (prefix
= gen_prefix (decl
)) == NULL
2409 const char * dec_name
= DECL_SECTION_NAME (decl
);
2410 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2412 set_decl_section_name (decl
, name
);
2415 /* Emit a declaration of a common symbol.
2416 If a data region is in use then put the symbol into the
2417 equivalent .bss section instead. */
2420 msp430_output_aligned_decl_common (FILE * stream
,
2423 unsigned HOST_WIDE_INT size
,
2426 if (msp430_data_region
== MSP430_REGION_ANY
)
2428 fprintf (stream
, COMMON_ASM_OP
);
2429 assemble_name (stream
, name
);
2430 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2431 size
, align
/ BITS_PER_UNIT
);
2438 sec
= msp430_select_section (decl
, 0, align
);
2440 switch (msp430_data_region
)
2442 case MSP430_REGION_UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2443 case MSP430_REGION_LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2444 case MSP430_REGION_EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2448 gcc_assert (sec
!= NULL
);
2450 switch_to_section (sec
);
2451 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2452 targetm
.asm_out
.globalize_label (stream
, name
);
2453 ASM_WEAKEN_LABEL (stream
, name
);
2454 ASM_OUTPUT_LABEL (stream
, name
);
2455 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2460 msp430_do_not_relax_short_jumps (void)
2462 /* When placing code into "either" low or high memory we do not want the linker
2463 to grow the size of sections, which it can do if it is encounters a branch to
2464 a label that is too far away. So we tell the cbranch patterns to avoid using
2465 short jumps when there is a chance that the instructions will end up in a low
2468 msp430_code_region
== MSP430_REGION_EITHER
2469 || msp430_code_region
== MSP430_REGION_LOWER
2470 || has_attr (ATTR_EITHER
, current_function_decl
)
2471 || has_attr (ATTR_LOWER
, current_function_decl
);
2476 MSP430_BUILTIN_BIC_SR
,
2477 MSP430_BUILTIN_BIS_SR
,
2478 MSP430_BUILTIN_DELAY_CYCLES
,
2482 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2485 msp430_init_builtins (void)
2487 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2488 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2490 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2491 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2492 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2494 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2495 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2496 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2498 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2499 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2500 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2504 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2508 case MSP430_BUILTIN_BIC_SR
:
2509 case MSP430_BUILTIN_BIS_SR
:
2510 case MSP430_BUILTIN_DELAY_CYCLES
:
2511 return msp430_builtins
[code
];
2513 return error_mark_node
;
2517 /* These constants are really register reads, which are faster than
2518 regular constants. */
2520 cg_magic_constant (HOST_WIDE_INT c
)
2538 msp430_expand_delay_cycles (rtx arg
)
2540 HOST_WIDE_INT i
, c
, n
;
2541 /* extra cycles for MSP430X instructions */
2542 #define CYCX(M,X) (msp430x ? (X) : (M))
2544 if (GET_CODE (arg
) != CONST_INT
)
2546 error ("__delay_cycles() only takes constant arguments");
2552 if (HOST_BITS_PER_WIDE_INT
> 32)
2556 error ("__delay_cycles only takes non-negative cycle counts");
2561 emit_insn (gen_delay_cycles_start (arg
));
2563 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2564 if (c
> 3 * 0xffff + CYCX (7, 10))
2567 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2568 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2571 c
-= CYCX (14, 16) + 7 * 0x10000;
2574 if ((unsigned long long) i
> 0xffffffffULL
)
2576 error ("__delay_cycles is limited to 32-bit loop counts");
2582 i
= (c
- CYCX (14, 16)) / 7;
2583 c
-= CYCX (14, 16) + i
* 7;
2586 if (cg_magic_constant (i
& 0xffff))
2588 if (cg_magic_constant ((i
>> 16) & 0xffff))
2592 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2594 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2597 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2601 i
= (c
- CYCX (7, 10)) / 3;
2602 c
-= CYCX (7, 10) + i
* 3;
2604 if (cg_magic_constant (i
))
2608 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2610 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2615 emit_insn (gen_delay_cycles_2 ());
2621 emit_insn (gen_delay_cycles_1 ());
2625 emit_insn (gen_delay_cycles_end (arg
));
2631 msp430_expand_builtin (tree exp
,
2632 rtx target ATTRIBUTE_UNUSED
,
2633 rtx subtarget ATTRIBUTE_UNUSED
,
2634 machine_mode mode ATTRIBUTE_UNUSED
,
2635 int ignore ATTRIBUTE_UNUSED
)
2637 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2638 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2639 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2641 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2642 return msp430_expand_delay_cycles (arg1
);
2644 if (! msp430_is_interrupt_func ())
2646 error ("MSP430 builtin functions only work inside interrupt handlers");
2650 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2651 arg1
= force_reg (mode
, arg1
);
2655 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2656 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2658 internal_error ("bad builtin code");
2664 #undef TARGET_INIT_BUILTINS
2665 #define TARGET_INIT_BUILTINS msp430_init_builtins
2667 #undef TARGET_EXPAND_BUILTIN
2668 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2670 #undef TARGET_BUILTIN_DECL
2671 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2674 msp430_expand_prologue (void)
2678 /* Always use stack_pointer_rtx instead of calling
2679 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2680 that there is a single rtx representing the stack pointer,
2681 namely stack_pointer_rtx, and uses == to recognize it. */
2682 rtx sp
= stack_pointer_rtx
;
2685 if (is_naked_func ())
2687 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2688 examines the output of the gen_prologue() function. */
2689 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2693 emit_insn (gen_prologue_start_marker ());
2695 if (is_critical_func ())
2697 emit_insn (gen_push_intr_state ());
2698 emit_insn (gen_disable_interrupts ());
2700 else if (is_reentrant_func ())
2701 emit_insn (gen_disable_interrupts ());
2703 if (!cfun
->machine
->computed
)
2704 msp430_compute_frame_info ();
2706 if (flag_stack_usage_info
)
2707 current_function_static_stack_size
= cfun
->machine
->framesize
;
2709 if (crtl
->args
.pretend_args_size
)
2713 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2715 p
= emit_insn (gen_grow_and_swap ());
2717 /* Document the stack decrement... */
2718 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2719 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2720 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2722 /* ...and the establishment of a new location for the return address. */
2723 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2724 gen_rtx_PLUS (Pmode
,
2728 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2732 for (i
= 15; i
>= 4; i
--)
2733 if (cfun
->machine
->need_to_save
[i
])
2738 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2744 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2745 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2748 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2750 XVECEXP (note
, 0, 0)
2751 = F (gen_rtx_SET (stack_pointer_rtx
,
2752 gen_rtx_PLUS (Pmode
,
2754 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2756 /* *sp-- = R[i-j] */
2760 for (j
= 0; j
< count
; j
++)
2763 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2766 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2768 addr
= stack_pointer_rtx
;
2770 XVECEXP (note
, 0, j
+ 1) =
2771 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2772 gen_rtx_REG (Pmode
, i
- j
)) );
2775 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2779 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2782 if (frame_pointer_needed
)
2783 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2785 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2787 increment_stack (- fs
);
2789 emit_insn (gen_prologue_end_marker ());
2793 msp430_expand_epilogue (int is_eh
)
2799 if (is_naked_func ())
2801 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2802 examines the output of the gen_epilogue() function. */
2803 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2807 if (cfun
->machine
->need_to_save
[10])
2809 /* Check for a helper function. */
2810 helper_n
= 7; /* For when the loop below never sees a match. */
2811 for (i
= 9; i
>= 4; i
--)
2812 if (!cfun
->machine
->need_to_save
[i
])
2816 if (cfun
->machine
->need_to_save
[i
])
2825 emit_insn (gen_epilogue_start_marker ());
2827 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2828 emit_insn (gen_msp430_refsym_need_exit ());
2830 if (is_wakeup_func ())
2831 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2832 status register current residing on the stack. When this function
2833 executes its RETI instruction the SR will be updated with this saved
2834 value, thus ensuring that the processor is woken up from any low power
2835 state in which it may be residing. */
2836 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2838 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2840 increment_stack (fs
);
2844 /* We need to add the right "SP" register save just after the
2845 regular ones, so that when we pop it off we're in the EH
2846 return frame, not this one. This overwrites our own return
2847 address, but we're not going to be returning anyway. */
2848 rtx r12
= gen_rtx_REG (Pmode
, 12);
2849 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2851 /* R12 will hold the new SP. */
2852 i
= cfun
->machine
->framesize_regs
;
2853 emit_move_insn (r12
, stack_pointer_rtx
);
2854 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2855 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2856 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2859 for (i
= 4; i
<= 15; i
++)
2860 if (cfun
->machine
->need_to_save
[i
])
2864 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2870 /* Note: With TARGET_LARGE we still use
2871 POPM as POPX.A is two bytes bigger. */
2872 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2876 else if (i
== 11 - helper_n
2877 && ! msp430_is_interrupt_func ()
2878 && ! is_reentrant_func ()
2879 && ! is_critical_func ()
2880 && crtl
->args
.pretend_args_size
== 0
2881 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2885 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2889 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2894 /* Also pop SP, which puts us into the EH return frame. Except
2895 that you can't "pop" sp, you have to just load it off the
2897 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2900 if (crtl
->args
.pretend_args_size
)
2901 emit_insn (gen_swap_and_shrink ());
2903 if (is_critical_func ())
2904 emit_insn (gen_pop_intr_state ());
2905 else if (is_reentrant_func ())
2906 emit_insn (gen_enable_interrupts ());
2908 emit_jump_insn (gen_msp_return ());
2911 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2912 m32c_emit_eh_epilogue. */
2914 msp430_eh_return_stackadj_rtx (void)
2916 if (!cfun
->machine
->eh_stack_adjust
)
2920 sa
= gen_rtx_REG (Pmode
, 15);
2921 cfun
->machine
->eh_stack_adjust
= sa
;
2923 return cfun
->machine
->eh_stack_adjust
;
2926 /* This function is called before reload, to "fix" the stack in
2927 preparation for an EH return. */
2929 msp430_expand_eh_return (rtx eh_handler
)
2931 /* These are all Pmode */
2932 rtx ap
, sa
, ra
, tmp
;
2934 ap
= arg_pointer_rtx
;
2935 sa
= msp430_eh_return_stackadj_rtx ();
2939 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2940 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2941 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2942 emit_move_insn (tmp
, ra
);
2945 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2946 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2948 msp430_init_dwarf_reg_sizes_extra (tree address
)
2951 rtx addr
= expand_normal (address
);
2952 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2954 /* This needs to match msp430_unwind_word_mode (above). */
2958 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2960 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2961 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2963 if (rnum
< DWARF_FRAME_REGISTERS
)
2965 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2967 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2968 gen_int_mode (4, QImode
));
2973 /* This is a list of MD patterns that implement fixed-count shifts. */
2979 rtx (*genfunc
)(rtx
,rtx
);
2981 const_shift_helpers
[] =
2983 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2985 CSH ("slli", 1, 1, slli_1
),
2986 CSH ("slll", 1, 1, slll_1
),
2987 CSH ("slll", 2, 1, slll_2
),
2989 CSH ("srai", 1, 0, srai_1
),
2990 CSH ("sral", 1, 0, sral_1
),
2991 CSH ("sral", 2, 0, sral_2
),
2993 CSH ("srll", 1, 0, srll_1
),
2994 CSH ("srll", 2, 1, srll_2x
),
2999 /* The MSP430 ABI defines a number of helper functions that should be
3000 used for, for example, 32-bit shifts. This function is called to
3001 emit such a function, using the table above to optimize some
3004 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
3007 char *helper_const
= NULL
;
3010 machine_mode arg0mode
= GET_MODE (operands
[0]);
3011 machine_mode arg1mode
= GET_MODE (operands
[1]);
3012 machine_mode arg2mode
= GET_MODE (operands
[2]);
3013 int have_430x
= msp430x
? 1 : 0;
3015 if (CONST_INT_P (operands
[2]))
3019 for (i
=0; const_shift_helpers
[i
].name
; i
++)
3021 if (const_shift_helpers
[i
].need_430x
<= have_430x
3022 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
3023 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
3025 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
3031 if (arg1mode
== VOIDmode
)
3032 arg1mode
= arg0mode
;
3033 if (arg2mode
== VOIDmode
)
3034 arg2mode
= arg0mode
;
3036 if (arg1mode
== SImode
)
3043 && CONST_INT_P (operands
[2])
3044 && INTVAL (operands
[2]) >= 1
3045 && INTVAL (operands
[2]) <= 15)
3047 /* Note that the INTVAL is limited in value and length by the conditional above. */
3048 int len
= strlen (helper_name
) + 4;
3049 helper_const
= (char *) xmalloc (len
);
3050 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
3053 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
3056 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
3059 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
3060 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
3062 c
= emit_call_insn (c
);
3063 RTL_CONST_CALL_P (c
) = 1;
3066 use_regs (&f
, 12, arg1sz
);
3068 use_regs (&f
, arg2
, 1);
3069 add_function_usage_to (c
, f
);
3071 emit_move_insn (operands
[0],
3072 gen_rtx_REG (arg0mode
, 12));
3075 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3077 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
3079 /* constants we're looking for, not constants which are allowed. */
3080 int const_op_idx
= 1;
3082 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
3085 if (GET_CODE (operands
[const_op_idx
]) != REG
3086 && GET_CODE (operands
[const_op_idx
]) != MEM
)
3087 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3090 /* Simplify_gen_subreg() doesn't handle memory references the way we
3091 need it to below, so we use this function for when we must get a
3092 valid subreg in a "natural" state. */
3094 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3098 if (GET_CODE (r
) == SUBREG
3099 && SUBREG_BYTE (r
) == 0)
3101 rtx ireg
= SUBREG_REG (r
);
3102 machine_mode imode
= GET_MODE (ireg
);
3104 /* special case for (HI (SI (PSI ...), 0)) */
3105 if (imode
== PSImode
3108 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3110 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3112 else if (GET_CODE (r
) == MEM
)
3113 rv
= adjust_address (r
, mode
, byte
);
3114 else if (GET_CODE (r
) == SYMBOL_REF
3115 && (byte
== 0 || byte
== 2)
3118 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3119 rv
= gen_rtx_CONST (HImode
, r
);
3122 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3130 /* Called by movsi_x to generate the HImode operands. */
3132 msp430_split_movsi (rtx
*operands
)
3134 rtx op00
, op02
, op10
, op12
;
3136 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3137 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3139 if (GET_CODE (operands
[1]) == CONST
3140 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3142 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3143 op10
= gen_rtx_CONST (HImode
, op10
);
3144 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3145 op12
= gen_rtx_CONST (HImode
, op12
);
3149 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3150 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3153 if (rtx_equal_p (operands
[0], operands
[1]))
3160 else if (rtx_equal_p (op00
, op12
)
3161 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3162 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3163 /* Or storing (rN) into mem (rN). */
3164 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3182 /* The MSPABI specifies the names of various helper functions, many of
3183 which are compatible with GCC's helpers. This table maps the GCC
3184 name to the MSPABI name. */
3187 char const * const gcc_name
;
3188 char const * const ti_name
;
3190 helper_function_name_mappings
[] =
3192 /* Floating point to/from integer conversions. */
3193 { "__truncdfsf2", "__mspabi_cvtdf" },
3194 { "__extendsfdf2", "__mspabi_cvtfd" },
3195 { "__fixdfhi", "__mspabi_fixdi" },
3196 { "__fixdfsi", "__mspabi_fixdli" },
3197 { "__fixdfdi", "__mspabi_fixdlli" },
3198 { "__fixunsdfhi", "__mspabi_fixdu" },
3199 { "__fixunsdfsi", "__mspabi_fixdul" },
3200 { "__fixunsdfdi", "__mspabi_fixdull" },
3201 { "__fixsfhi", "__mspabi_fixfi" },
3202 { "__fixsfsi", "__mspabi_fixfli" },
3203 { "__fixsfdi", "__mspabi_fixflli" },
3204 { "__fixunsfhi", "__mspabi_fixfu" },
3205 { "__fixunsfsi", "__mspabi_fixful" },
3206 { "__fixunsfdi", "__mspabi_fixfull" },
3207 { "__floathisf", "__mspabi_fltif" },
3208 { "__floatsisf", "__mspabi_fltlif" },
3209 { "__floatdisf", "__mspabi_fltllif" },
3210 { "__floathidf", "__mspabi_fltid" },
3211 { "__floatsidf", "__mspabi_fltlid" },
3212 { "__floatdidf", "__mspabi_fltllid" },
3213 { "__floatunhisf", "__mspabi_fltuf" },
3214 { "__floatunsisf", "__mspabi_fltulf" },
3215 { "__floatundisf", "__mspabi_fltullf" },
3216 { "__floatunhidf", "__mspabi_fltud" },
3217 { "__floatunsidf", "__mspabi_fltuld" },
3218 { "__floatundidf", "__mspabi_fltulld" },
3220 /* Floating point comparisons. */
3221 /* GCC uses individual functions for each comparison, TI uses one
3222 compare <=> function. */
3224 /* Floating point arithmatic */
3225 { "__adddf3", "__mspabi_addd" },
3226 { "__addsf3", "__mspabi_addf" },
3227 { "__divdf3", "__mspabi_divd" },
3228 { "__divsf3", "__mspabi_divf" },
3229 { "__muldf3", "__mspabi_mpyd" },
3230 { "__mulsf3", "__mspabi_mpyf" },
3231 { "__subdf3", "__mspabi_subd" },
3232 { "__subsf3", "__mspabi_subf" },
3233 /* GCC does not use helper functions for negation */
3235 /* Integer multiply, divide, remainder. */
3236 { "__mulhi3", "__mspabi_mpyi" },
3237 { "__mulsi3", "__mspabi_mpyl" },
3238 { "__muldi3", "__mspabi_mpyll" },
3240 /* Clarify signed vs unsigned first. */
3241 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3242 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3245 { "__divhi3", "__mspabi_divi" },
3246 { "__divsi3", "__mspabi_divli" },
3247 { "__divdi3", "__mspabi_divlli" },
3248 { "__udivhi3", "__mspabi_divu" },
3249 { "__udivsi3", "__mspabi_divul" },
3250 { "__udivdi3", "__mspabi_divull" },
3251 { "__modhi3", "__mspabi_remi" },
3252 { "__modsi3", "__mspabi_remli" },
3253 { "__moddi3", "__mspabi_remlli" },
3254 { "__umodhi3", "__mspabi_remu" },
3255 { "__umodsi3", "__mspabi_remul" },
3256 { "__umoddi3", "__mspabi_remull" },
3258 /* Bitwise operations. */
3259 /* Rotation - no rotation support yet. */
3260 /* Logical left shift - gcc already does these itself. */
3261 /* Arithmetic left shift - gcc already does these itself. */
3262 /* Arithmetic right shift - gcc already does these itself. */
3267 /* Returns true if the current MCU supports an F5xxx series
3268 hardware multiper. */
3271 msp430_use_f5_series_hwmult (void)
3273 static const char * cached_match
= NULL
;
3274 static bool cached_result
;
3276 if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
3279 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3282 if (target_mcu
== cached_match
)
3283 return cached_result
;
3285 cached_match
= target_mcu
;
3287 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3288 return cached_result
= true;
3289 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3290 return cached_result
= true;
3291 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3292 return cached_result
= true;
3296 /* FIXME: This array is alpha sorted - we could use a binary search. */
3297 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3298 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3299 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3301 return cached_result
= false;
3304 /* Returns true if the current MCU has a second generation
3305 32-bit hardware multiplier. */
3308 use_32bit_hwmult (void)
3310 static const char * cached_match
= NULL
;
3311 static bool cached_result
;
3314 if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
)
3317 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3320 if (target_mcu
== cached_match
)
3321 return cached_result
;
3323 cached_match
= target_mcu
;
3325 /* FIXME: This array is alpha sorted - we could use a binary search. */
3326 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3327 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3328 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3330 return cached_result
= false;
3333 /* Returns true if the current MCU does not have a
3334 hardware multiplier of any kind. */
3337 msp430_no_hwmult (void)
3339 static const char * cached_match
= NULL
;
3340 static bool cached_result
;
3343 if (msp430_hwmult_type
== MSP430_HWMULT_NONE
)
3346 if (msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3349 if (target_mcu
== NULL
)
3352 if (target_mcu
== cached_match
)
3353 return cached_result
;
3355 cached_match
= target_mcu
;
3357 /* FIXME: This array is alpha sorted - we could use a binary search. */
3358 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3359 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3360 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3362 /* If we do not recognise the MCU name, we assume that it does not support
3363 any kind of hardware multiply - this is the safest assumption to make. */
3364 return cached_result
= true;
3367 /* This function does the same as the default, but it will replace GCC
3368 function names with the MSPABI-specified ones. */
3371 msp430_output_labelref (FILE *file
, const char *name
)
3375 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3376 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3378 name
= helper_function_name_mappings
[i
].ti_name
;
3382 /* If we have been given a specific MCU name then we may be
3383 able to make use of its hardware multiply capabilities. */
3384 if (msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
3386 if (strcmp ("__mspabi_mpyi", name
) == 0)
3388 if (msp430_use_f5_series_hwmult ())
3389 name
= "__mulhi2_f5";
3390 else if (! msp430_no_hwmult ())
3393 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3395 if (msp430_use_f5_series_hwmult ())
3396 name
= "__mulsi2_f5";
3397 else if (use_32bit_hwmult ())
3398 name
= "__mulsi2_hw32";
3399 else if (! msp430_no_hwmult ())
3407 /* Common code for msp430_print_operand... */
3410 msp430_print_operand_raw (FILE * file
, rtx op
)
3414 switch (GET_CODE (op
))
3417 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3423 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3425 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3433 output_addr_const (file
, op
);
3437 print_rtl (file
, op
);
3442 #undef TARGET_PRINT_OPERAND_ADDRESS
3443 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3445 /* Output to stdio stream FILE the assembler syntax for an
3446 instruction operand that is a memory reference whose address
3450 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3452 switch (GET_CODE (addr
))
3455 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3456 gcc_assert (REG_P (XEXP (addr
, 0)));
3457 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3461 fprintf (file
, "@");
3468 fprintf (file
, "&");
3475 msp430_print_operand_raw (file
, addr
);
3478 #undef TARGET_PRINT_OPERAND
3479 #define TARGET_PRINT_OPERAND msp430_print_operand
3481 /* A low 16-bits of int/lower of register pair
3482 B high 16-bits of int/higher of register pair
3483 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3484 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3485 H like %B (for backwards compatibility)
3487 J an integer without a # prefix
3488 L like %A (for backwards compatibility)
3489 O offset of the top of the stack
3490 Q like X but generates an A postfix
3491 R inverse of condition code, unsigned.
3492 X X instruction postfix in large mode
3495 b .B or .W or .A, depending upon the mode
3497 r inverse of condition code
3498 x like X but only for pointers. */
3501 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3505 /* We can't use c, n, a, or l. */
3509 gcc_assert (CONST_INT_P (op
));
3510 /* Print the constant value, less one. */
3511 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3514 gcc_assert (CONST_INT_P (op
));
3515 /* Print the constant value, less four. */
3516 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3519 if (GET_CODE (op
) == CONST_INT
)
3521 /* Inverse of constants */
3522 int i
= INTVAL (op
);
3523 fprintf (file
, "%d", ~i
);
3528 case 'r': /* Conditional jump where the condition is reversed. */
3529 switch (GET_CODE (op
))
3531 case EQ
: fprintf (file
, "NE"); break;
3532 case NE
: fprintf (file
, "EQ"); break;
3533 case GEU
: fprintf (file
, "LO"); break;
3534 case LTU
: fprintf (file
, "HS"); break;
3535 case GE
: fprintf (file
, "L"); break;
3536 case LT
: fprintf (file
, "GE"); break;
3537 /* Assume these have reversed operands. */
3538 case GTU
: fprintf (file
, "HS"); break;
3539 case LEU
: fprintf (file
, "LO"); break;
3540 case GT
: fprintf (file
, "GE"); break;
3541 case LE
: fprintf (file
, "L"); break;
3543 msp430_print_operand_raw (file
, op
);
3547 case 'R': /* Conditional jump where the operands are reversed. */
3548 switch (GET_CODE (op
))
3550 case GTU
: fprintf (file
, "LO"); break;
3551 case LEU
: fprintf (file
, "HS"); break;
3552 case GT
: fprintf (file
, "L"); break;
3553 case LE
: fprintf (file
, "GE"); break;
3555 msp430_print_operand_raw (file
, op
);
3559 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3560 gcc_assert (CONST_INT_P (op
));
3561 fprintf (file
, "#%d", 1 << INTVAL (op
));
3564 switch (GET_MODE (op
))
3566 case E_QImode
: fprintf (file
, ".B"); return;
3567 case E_HImode
: fprintf (file
, ".W"); return;
3568 case E_PSImode
: fprintf (file
, ".A"); return;
3569 case E_SImode
: fprintf (file
, ".A"); return;
3574 case 'L': /* Low half. */
3575 switch (GET_CODE (op
))
3578 op
= adjust_address (op
, Pmode
, 0);
3583 op
= GEN_INT (INTVAL (op
) & 0xffff);
3587 /* If you get here, figure out a test case :-) */
3592 case 'H': /* high half */
3593 switch (GET_CODE (op
))
3596 op
= adjust_address (op
, Pmode
, 2);
3599 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3602 op
= GEN_INT (INTVAL (op
) >> 16);
3606 /* If you get here, figure out a test case :-) */
3611 switch (GET_CODE (op
))
3614 op
= adjust_address (op
, Pmode
, 3);
3617 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3620 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3624 /* If you get here, figure out a test case :-) */
3629 switch (GET_CODE (op
))
3632 op
= adjust_address (op
, Pmode
, 4);
3635 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3638 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3642 /* If you get here, figure out a test case :-) */
3648 /* This is used to turn, for example, an ADD opcode into an ADDX
3649 opcode when we're using 20-bit addresses. */
3650 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3651 fprintf (file
, "X");
3652 /* We don't care which operand we use, but we want 'X' in the MD
3653 file, so we do it this way. */
3657 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3658 if (GET_MODE (op
) == PSImode
)
3659 fprintf (file
, "X");
3663 /* Likewise, for BR -> BRA. */
3665 fprintf (file
, "A");
3669 /* Computes the offset to the top of the stack for the current frame.
3670 This has to be done here rather than in, say, msp430_expand_builtin()
3671 because builtins are expanded before the frame layout is determined. */
3672 fprintf (file
, "%d",
3673 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3674 - (TARGET_LARGE
? 4 : 2));
3678 gcc_assert (GET_CODE (op
) == CONST_INT
);
3682 output_operand_lossage ("invalid operand prefix");
3686 switch (GET_CODE (op
))
3689 msp430_print_operand_raw (file
, op
);
3693 addr
= XEXP (op
, 0);
3694 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3698 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3701 switch (INTVAL (XEXP (op
, 2)))
3704 fprintf (file
, "#lo (");
3705 msp430_print_operand_raw (file
, XEXP (op
, 0));
3706 fprintf (file
, ")");
3710 fprintf (file
, "#hi (");
3711 msp430_print_operand_raw (file
, XEXP (op
, 0));
3712 fprintf (file
, ")");
3716 output_operand_lossage ("invalid zero extract");
3726 fprintf (file
, "#");
3727 msp430_print_operand_raw (file
, op
);
3730 case EQ
: fprintf (file
, "EQ"); break;
3731 case NE
: fprintf (file
, "NE"); break;
3732 case GEU
: fprintf (file
, "HS"); break;
3733 case LTU
: fprintf (file
, "LO"); break;
3734 case GE
: fprintf (file
, "GE"); break;
3735 case LT
: fprintf (file
, "L"); break;
3738 print_rtl (file
, op
);
3747 msp430_return_addr_rtx (int count
)
3753 ra_size
= TARGET_LARGE
? 4 : 2;
3754 if (crtl
->args
.pretend_args_size
)
3757 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3761 msp430_incoming_return_addr_rtx (void)
3763 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3766 /* Instruction generation stuff. */
3768 /* Generate a sequence of instructions to sign-extend an HI
3769 value into an SI value. Handles the tricky case where
3770 we are overwriting the destination. */
3773 msp430x_extendhisi (rtx
* operands
)
3775 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3776 /* Low word of dest == source word. */
3777 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3780 /* Note: This sequence is approximately the same length as invoking a helper
3781 function to perform the sign-extension, as in:
3785 CALL __mspabi_srai_15
3788 but this version does not involve any function calls or using argument
3789 registers, so it reduces register pressure. */
3790 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3792 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3793 /* High word of dest == source word. */
3794 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3796 /* No overlap between dest and source. */
3797 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3800 /* Likewise for logical right shifts. */
3802 msp430x_logical_shift_right (rtx amount
)
3804 /* The MSP430X's logical right shift instruction - RRUM - does
3805 not use an extension word, so we cannot encode a repeat count.
3806 Try various alternatives to work around this. If the count
3807 is in a register we are stuck, hence the assert. */
3808 gcc_assert (CONST_INT_P (amount
));
3810 if (INTVAL (amount
) <= 0
3811 || INTVAL (amount
) >= 16)
3812 return "# nop logical shift.";
3814 if (INTVAL (amount
) > 0
3815 && INTVAL (amount
) < 5)
3816 return "rrum.w\t%2, %0"; /* Two bytes. */
3818 if (INTVAL (amount
) > 4
3819 && INTVAL (amount
) < 9)
3820 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3822 /* First we logically shift right by one. Now we know
3823 that the top bit is zero and we can use the arithmetic
3824 right shift instruction to perform the rest of the shift. */
3825 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3828 /* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */
3830 #undef TARGET_CAN_CHANGE_MODE_CLASS
3831 #define TARGET_CAN_CHANGE_MODE_CLASS msp430_can_change_mode_class
3834 msp430_can_change_mode_class (machine_mode from
, machine_mode to
, reg_class_t
)
3836 if ((to
== PSImode
&& from
== SImode
)
3837 || (to
== SImode
&& from
== PSImode
)
3838 || (to
== DImode
&& from
== PSImode
)
3839 || (to
== PSImode
&& from
== DImode
))
3844 struct gcc_target targetm
= TARGET_INITIALIZER
;
3846 #include "gt-msp430.h"