1 /* Subroutines used for code generation on TI MSP430 processors.
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Contributed by Red Hat.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
28 #include "stringpool.h"
30 #include "gimple-expr.h"
36 #include "diagnostic-core.h"
37 #include "fold-const.h"
38 #include "stor-layout.h"
43 #include "langhooks.h"
47 /* This file should be included last. */
48 #include "target-def.h"
51 static void msp430_compute_frame_info (void);
55 /* Run-time Target Specification. */
59 struct GTY(()) machine_function
61 /* If set, the rest of the fields have been computed. */
63 /* Which registers need to be saved in the pro/epilogue. */
64 int need_to_save
[FIRST_PSEUDO_REGISTER
];
66 /* These fields describe the frame layout... */
68 /* 2/4 bytes for saved PC */
72 int framesize_outgoing
;
76 /* How much we adjust the stack when returning from an exception
81 /* This is our init_machine_status, as set in
82 msp_option_override. */
83 static struct machine_function
*
84 msp430_init_machine_status (void)
86 struct machine_function
*m
;
88 m
= ggc_cleared_alloc
<machine_function
> ();
93 #undef TARGET_OPTION_OVERRIDE
94 #define TARGET_OPTION_OVERRIDE msp430_option_override
96 /* This is a copy of the same data structure found in gas/config/tc-msp430.c
97 Also another (sort-of) copy can be found in gcc/config/msp430/t-msp430
98 Keep these three structures in sync.
99 The data in this structure has been extracted from version 1.194 of the
100 devices.csv file released by TI in September 2016. */
102 struct msp430_mcu_data
105 unsigned int revision
; /* 0=> MSP430, 1=>MSP430X, 2=> MSP430Xv2. */
106 unsigned int hwmpy
; /* 0=>none, 1=>16-bit, 2=>16-bit w/sign extend, 4=>32-bit, 8=> 32-bit (5xx). */
110 { "cc430f5123",2,8 },
111 { "cc430f5125",2,8 },
112 { "cc430f5133",2,8 },
113 { "cc430f5135",2,8 },
114 { "cc430f5137",2,8 },
115 { "cc430f5143",2,8 },
116 { "cc430f5145",2,8 },
117 { "cc430f5147",2,8 },
118 { "cc430f6125",2,8 },
119 { "cc430f6126",2,8 },
120 { "cc430f6127",2,8 },
121 { "cc430f6135",2,8 },
122 { "cc430f6137",2,8 },
123 { "cc430f6143",2,8 },
124 { "cc430f6145",2,8 },
125 { "cc430f6147",2,8 },
126 { "msp430afe221",0,2 },
127 { "msp430afe222",0,2 },
128 { "msp430afe223",0,2 },
129 { "msp430afe231",0,2 },
130 { "msp430afe232",0,2 },
131 { "msp430afe233",0,2 },
132 { "msp430afe251",0,2 },
133 { "msp430afe252",0,2 },
134 { "msp430afe253",0,2 },
135 { "msp430bt5190",2,8 },
136 { "msp430c091",0,0 },
137 { "msp430c092",0,0 },
138 { "msp430c111",0,0 },
139 { "msp430c1111",0,0 },
140 { "msp430c112",0,0 },
141 { "msp430c1121",0,0 },
142 { "msp430c1331",0,0 },
143 { "msp430c1351",0,0 },
144 { "msp430c311s",0,0 },
145 { "msp430c312",0,0 },
146 { "msp430c313",0,0 },
147 { "msp430c314",0,0 },
148 { "msp430c315",0,0 },
149 { "msp430c323",0,0 },
150 { "msp430c325",0,0 },
151 { "msp430c336",0,1 },
152 { "msp430c337",0,1 },
153 { "msp430c412",0,0 },
154 { "msp430c413",0,0 },
155 { "msp430cg4616",1,1 },
156 { "msp430cg4617",1,1 },
157 { "msp430cg4618",1,1 },
158 { "msp430cg4619",1,1 },
159 { "msp430e112",0,0 },
160 { "msp430e313",0,0 },
161 { "msp430e315",0,0 },
162 { "msp430e325",0,0 },
163 { "msp430e337",0,1 },
164 { "msp430f110",0,0 },
165 { "msp430f1101",0,0 },
166 { "msp430f1101a",0,0 },
167 { "msp430f1111",0,0 },
168 { "msp430f1111a",0,0 },
169 { "msp430f112",0,0 },
170 { "msp430f1121",0,0 },
171 { "msp430f1121a",0,0 },
172 { "msp430f1122",0,0 },
173 { "msp430f1132",0,0 },
174 { "msp430f122",0,0 },
175 { "msp430f1222",0,0 },
176 { "msp430f123",0,0 },
177 { "msp430f1232",0,0 },
178 { "msp430f133",0,0 },
179 { "msp430f135",0,0 },
180 { "msp430f147",0,1 },
181 { "msp430f1471",0,1 },
182 { "msp430f148",0,1 },
183 { "msp430f1481",0,1 },
184 { "msp430f149",0,1 },
185 { "msp430f1491",0,1 },
186 { "msp430f155",0,0 },
187 { "msp430f156",0,0 },
188 { "msp430f157",0,0 },
189 { "msp430f1610",0,1 },
190 { "msp430f1611",0,1 },
191 { "msp430f1612",0,1 },
192 { "msp430f167",0,1 },
193 { "msp430f168",0,1 },
194 { "msp430f169",0,1 },
195 { "msp430f2001",0,0 },
196 { "msp430f2002",0,0 },
197 { "msp430f2003",0,0 },
198 { "msp430f2011",0,0 },
199 { "msp430f2012",0,0 },
200 { "msp430f2013",0,0 },
201 { "msp430f2101",0,0 },
202 { "msp430f2111",0,0 },
203 { "msp430f2112",0,0 },
204 { "msp430f2121",0,0 },
205 { "msp430f2122",0,0 },
206 { "msp430f2131",0,0 },
207 { "msp430f2132",0,0 },
208 { "msp430f2232",0,0 },
209 { "msp430f2234",0,0 },
210 { "msp430f2252",0,0 },
211 { "msp430f2254",0,0 },
212 { "msp430f2272",0,0 },
213 { "msp430f2274",0,0 },
214 { "msp430f233",0,2 },
215 { "msp430f2330",0,2 },
216 { "msp430f235",0,2 },
217 { "msp430f2350",0,2 },
218 { "msp430f2370",0,2 },
219 { "msp430f2410",0,2 },
220 { "msp430f2416",1,2 },
221 { "msp430f2417",1,2 },
222 { "msp430f2418",1,2 },
223 { "msp430f2419",1,2 },
224 { "msp430f247",0,2 },
225 { "msp430f2471",0,2 },
226 { "msp430f248",0,2 },
227 { "msp430f2481",0,2 },
228 { "msp430f249",0,2 },
229 { "msp430f2491",0,2 },
230 { "msp430f2616",1,2 },
231 { "msp430f2617",1,2 },
232 { "msp430f2618",1,2 },
233 { "msp430f2619",1,2 },
234 { "msp430f412",0,0 },
235 { "msp430f413",0,0 },
236 { "msp430f4132",0,0 },
237 { "msp430f415",0,0 },
238 { "msp430f4152",0,0 },
239 { "msp430f417",0,0 },
240 { "msp430f423",0,1 },
241 { "msp430f423a",0,1 },
242 { "msp430f425",0,1 },
243 { "msp430f4250",0,0 },
244 { "msp430f425a",0,1 },
245 { "msp430f4260",0,0 },
246 { "msp430f427",0,1 },
247 { "msp430f4270",0,0 },
248 { "msp430f427a",0,1 },
249 { "msp430f435",0,0 },
250 { "msp430f4351",0,0 },
251 { "msp430f436",0,0 },
252 { "msp430f4361",0,0 },
253 { "msp430f437",0,0 },
254 { "msp430f4371",0,0 },
255 { "msp430f438",0,0 },
256 { "msp430f439",0,0 },
257 { "msp430f447",0,1 },
258 { "msp430f448",0,1 },
259 { "msp430f4481",0,1 },
260 { "msp430f449",0,1 },
261 { "msp430f4491",0,1 },
262 { "msp430f4616",1,1 },
263 { "msp430f46161",1,1 },
264 { "msp430f4617",1,1 },
265 { "msp430f46171",1,1 },
266 { "msp430f4618",1,1 },
267 { "msp430f46181",1,1 },
268 { "msp430f4619",1,1 },
269 { "msp430f46191",1,1 },
270 { "msp430f47126",1,4 },
271 { "msp430f47127",1,4 },
272 { "msp430f47163",1,4 },
273 { "msp430f47166",1,4 },
274 { "msp430f47167",1,4 },
275 { "msp430f47173",1,4 },
276 { "msp430f47176",1,4 },
277 { "msp430f47177",1,4 },
278 { "msp430f47183",1,4 },
279 { "msp430f47186",1,4 },
280 { "msp430f47187",1,4 },
281 { "msp430f47193",1,4 },
282 { "msp430f47196",1,4 },
283 { "msp430f47197",1,4 },
284 { "msp430f477",0,0 },
285 { "msp430f478",0,0 },
286 { "msp430f4783",0,4 },
287 { "msp430f4784",0,4 },
288 { "msp430f479",0,0 },
289 { "msp430f4793",0,4 },
290 { "msp430f4794",0,4 },
291 { "msp430f5131",2,8 },
292 { "msp430f5132",2,8 },
293 { "msp430f5151",2,8 },
294 { "msp430f5152",2,8 },
295 { "msp430f5171",2,8 },
296 { "msp430f5172",2,8 },
297 { "msp430f5212",2,8 },
298 { "msp430f5213",2,8 },
299 { "msp430f5214",2,8 },
300 { "msp430f5217",2,8 },
301 { "msp430f5218",2,8 },
302 { "msp430f5219",2,8 },
303 { "msp430f5222",2,8 },
304 { "msp430f5223",2,8 },
305 { "msp430f5224",2,8 },
306 { "msp430f5227",2,8 },
307 { "msp430f5228",2,8 },
308 { "msp430f5229",2,8 },
309 { "msp430f5232",2,8 },
310 { "msp430f5234",2,8 },
311 { "msp430f5237",2,8 },
312 { "msp430f5239",2,8 },
313 { "msp430f5242",2,8 },
314 { "msp430f5244",2,8 },
315 { "msp430f5247",2,8 },
316 { "msp430f5249",2,8 },
317 { "msp430f5252",2,8 },
318 { "msp430f5253",2,8 },
319 { "msp430f5254",2,8 },
320 { "msp430f5255",2,8 },
321 { "msp430f5256",2,8 },
322 { "msp430f5257",2,8 },
323 { "msp430f5258",2,8 },
324 { "msp430f5259",2,8 },
325 { "msp430f5304",2,8 },
326 { "msp430f5308",2,8 },
327 { "msp430f5309",2,8 },
328 { "msp430f5310",2,8 },
329 { "msp430f5324",2,8 },
330 { "msp430f5325",2,8 },
331 { "msp430f5326",2,8 },
332 { "msp430f5327",2,8 },
333 { "msp430f5328",2,8 },
334 { "msp430f5329",2,8 },
335 { "msp430f5333",2,8 },
336 { "msp430f5335",2,8 },
337 { "msp430f5336",2,8 },
338 { "msp430f5338",2,8 },
339 { "msp430f5340",2,8 },
340 { "msp430f5341",2,8 },
341 { "msp430f5342",2,8 },
342 { "msp430f5358",2,8 },
343 { "msp430f5359",2,8 },
344 { "msp430f5418",2,8 },
345 { "msp430f5418a",2,8 },
346 { "msp430f5419",2,8 },
347 { "msp430f5419a",2,8 },
348 { "msp430f5435",2,8 },
349 { "msp430f5435a",2,8 },
350 { "msp430f5436",2,8 },
351 { "msp430f5436a",2,8 },
352 { "msp430f5437",2,8 },
353 { "msp430f5437a",2,8 },
354 { "msp430f5438",2,8 },
355 { "msp430f5438a",2,8 },
356 { "msp430f5500",2,8 },
357 { "msp430f5501",2,8 },
358 { "msp430f5502",2,8 },
359 { "msp430f5503",2,8 },
360 { "msp430f5504",2,8 },
361 { "msp430f5505",2,8 },
362 { "msp430f5506",2,8 },
363 { "msp430f5507",2,8 },
364 { "msp430f5508",2,8 },
365 { "msp430f5509",2,8 },
366 { "msp430f5510",2,8 },
367 { "msp430f5513",2,8 },
368 { "msp430f5514",2,8 },
369 { "msp430f5515",2,8 },
370 { "msp430f5517",2,8 },
371 { "msp430f5519",2,8 },
372 { "msp430f5521",2,8 },
373 { "msp430f5522",2,8 },
374 { "msp430f5524",2,8 },
375 { "msp430f5525",2,8 },
376 { "msp430f5526",2,8 },
377 { "msp430f5527",2,8 },
378 { "msp430f5528",2,8 },
379 { "msp430f5529",2,8 },
380 { "msp430f5630",2,8 },
381 { "msp430f5631",2,8 },
382 { "msp430f5632",2,8 },
383 { "msp430f5633",2,8 },
384 { "msp430f5634",2,8 },
385 { "msp430f5635",2,8 },
386 { "msp430f5636",2,8 },
387 { "msp430f5637",2,8 },
388 { "msp430f5638",2,8 },
389 { "msp430f5658",2,8 },
390 { "msp430f5659",2,8 },
391 { "msp430f5xx_6xxgeneric",2,8 },
392 { "msp430f6433",2,8 },
393 { "msp430f6435",2,8 },
394 { "msp430f6436",2,8 },
395 { "msp430f6438",2,8 },
396 { "msp430f6458",2,8 },
397 { "msp430f6459",2,8 },
398 { "msp430f6630",2,8 },
399 { "msp430f6631",2,8 },
400 { "msp430f6632",2,8 },
401 { "msp430f6633",2,8 },
402 { "msp430f6634",2,8 },
403 { "msp430f6635",2,8 },
404 { "msp430f6636",2,8 },
405 { "msp430f6637",2,8 },
406 { "msp430f6638",2,8 },
407 { "msp430f6658",2,8 },
408 { "msp430f6659",2,8 },
409 { "msp430f6720",2,8 },
410 { "msp430f6720a",2,8 },
411 { "msp430f6721",2,8 },
412 { "msp430f6721a",2,8 },
413 { "msp430f6723",2,8 },
414 { "msp430f6723a",2,8 },
415 { "msp430f6724",2,8 },
416 { "msp430f6724a",2,8 },
417 { "msp430f6725",2,8 },
418 { "msp430f6725a",2,8 },
419 { "msp430f6726",2,8 },
420 { "msp430f6726a",2,8 },
421 { "msp430f6730",2,8 },
422 { "msp430f6730a",2,8 },
423 { "msp430f6731",2,8 },
424 { "msp430f6731a",2,8 },
425 { "msp430f6733",2,8 },
426 { "msp430f6733a",2,8 },
427 { "msp430f6734",2,8 },
428 { "msp430f6734a",2,8 },
429 { "msp430f6735",2,8 },
430 { "msp430f6735a",2,8 },
431 { "msp430f6736",2,8 },
432 { "msp430f6736a",2,8 },
433 { "msp430f6745",2,8 },
434 { "msp430f67451",2,8 },
435 { "msp430f67451a",2,8 },
436 { "msp430f6745a",2,8 },
437 { "msp430f6746",2,8 },
438 { "msp430f67461",2,8 },
439 { "msp430f67461a",2,8 },
440 { "msp430f6746a",2,8 },
441 { "msp430f6747",2,8 },
442 { "msp430f67471",2,8 },
443 { "msp430f67471a",2,8 },
444 { "msp430f6747a",2,8 },
445 { "msp430f6748",2,8 },
446 { "msp430f67481",2,8 },
447 { "msp430f67481a",2,8 },
448 { "msp430f6748a",2,8 },
449 { "msp430f6749",2,8 },
450 { "msp430f67491",2,8 },
451 { "msp430f67491a",2,8 },
452 { "msp430f6749a",2,8 },
453 { "msp430f67621",2,8 },
454 { "msp430f67621a",2,8 },
455 { "msp430f67641",2,8 },
456 { "msp430f67641a",2,8 },
457 { "msp430f6765",2,8 },
458 { "msp430f67651",2,8 },
459 { "msp430f67651a",2,8 },
460 { "msp430f6765a",2,8 },
461 { "msp430f6766",2,8 },
462 { "msp430f67661",2,8 },
463 { "msp430f67661a",2,8 },
464 { "msp430f6766a",2,8 },
465 { "msp430f6767",2,8 },
466 { "msp430f67671",2,8 },
467 { "msp430f67671a",2,8 },
468 { "msp430f6767a",2,8 },
469 { "msp430f6768",2,8 },
470 { "msp430f67681",2,8 },
471 { "msp430f67681a",2,8 },
472 { "msp430f6768a",2,8 },
473 { "msp430f6769",2,8 },
474 { "msp430f67691",2,8 },
475 { "msp430f67691a",2,8 },
476 { "msp430f6769a",2,8 },
477 { "msp430f6775",2,8 },
478 { "msp430f67751",2,8 },
479 { "msp430f67751a",2,8 },
480 { "msp430f6775a",2,8 },
481 { "msp430f6776",2,8 },
482 { "msp430f67761",2,8 },
483 { "msp430f67761a",2,8 },
484 { "msp430f6776a",2,8 },
485 { "msp430f6777",2,8 },
486 { "msp430f67771",2,8 },
487 { "msp430f67771a",2,8 },
488 { "msp430f6777a",2,8 },
489 { "msp430f6778",2,8 },
490 { "msp430f67781",2,8 },
491 { "msp430f67781a",2,8 },
492 { "msp430f6778a",2,8 },
493 { "msp430f6779",2,8 },
494 { "msp430f67791",2,8 },
495 { "msp430f67791a",2,8 },
496 { "msp430f6779a",2,8 },
497 { "msp430fe423",0,0 },
498 { "msp430fe4232",0,0 },
499 { "msp430fe423a",0,0 },
500 { "msp430fe4242",0,0 },
501 { "msp430fe425",0,0 },
502 { "msp430fe4252",0,0 },
503 { "msp430fe425a",0,0 },
504 { "msp430fe427",0,0 },
505 { "msp430fe4272",0,0 },
506 { "msp430fe427a",0,0 },
507 { "msp430fg4250",0,0 },
508 { "msp430fg4260",0,0 },
509 { "msp430fg4270",0,0 },
510 { "msp430fg437",0,0 },
511 { "msp430fg438",0,0 },
512 { "msp430fg439",0,0 },
513 { "msp430fg4616",1,1 },
514 { "msp430fg4617",1,1 },
515 { "msp430fg4618",1,1 },
516 { "msp430fg4619",1,1 },
517 { "msp430fg477",0,0 },
518 { "msp430fg478",0,0 },
519 { "msp430fg479",0,0 },
520 { "msp430fg6425",2,8 },
521 { "msp430fg6426",2,8 },
522 { "msp430fg6625",2,8 },
523 { "msp430fg6626",2,8 },
524 { "msp430fr2032",2,0 },
525 { "msp430fr2033",2,0 },
526 { "msp430fr2110",2,0 },
527 { "msp430fr2111",2,0 },
528 { "msp430fr2310",2,0 },
529 { "msp430fr2311",2,0 },
530 { "msp430fr2433",2,8 },
531 { "msp430fr2532",2,8 },
532 { "msp430fr2533",2,8 },
533 { "msp430fr2632",2,8 },
534 { "msp430fr2633",2,8 },
535 { "msp430fr2xx_4xxgeneric",2,8 },
536 { "msp430fr4131",2,0 },
537 { "msp430fr4132",2,0 },
538 { "msp430fr4133",2,0 },
539 { "msp430fr5720",2,8 },
540 { "msp430fr5721",2,8 },
541 { "msp430fr5722",2,8 },
542 { "msp430fr5723",2,8 },
543 { "msp430fr5724",2,8 },
544 { "msp430fr5725",2,8 },
545 { "msp430fr5726",2,8 },
546 { "msp430fr5727",2,8 },
547 { "msp430fr5728",2,8 },
548 { "msp430fr5729",2,8 },
549 { "msp430fr5730",2,8 },
550 { "msp430fr5731",2,8 },
551 { "msp430fr5732",2,8 },
552 { "msp430fr5733",2,8 },
553 { "msp430fr5734",2,8 },
554 { "msp430fr5735",2,8 },
555 { "msp430fr5736",2,8 },
556 { "msp430fr5737",2,8 },
557 { "msp430fr5738",2,8 },
558 { "msp430fr5739",2,8 },
559 { "msp430fr57xxgeneric",2,8 },
560 { "msp430fr5847",2,8 },
561 { "msp430fr58471",2,8 },
562 { "msp430fr5848",2,8 },
563 { "msp430fr5849",2,8 },
564 { "msp430fr5857",2,8 },
565 { "msp430fr5858",2,8 },
566 { "msp430fr5859",2,8 },
567 { "msp430fr5867",2,8 },
568 { "msp430fr58671",2,8 },
569 { "msp430fr5868",2,8 },
570 { "msp430fr5869",2,8 },
571 { "msp430fr5870",2,8 },
572 { "msp430fr5872",2,8 },
573 { "msp430fr58721",2,8 },
574 { "msp430fr5887",2,8 },
575 { "msp430fr5888",2,8 },
576 { "msp430fr5889",2,8 },
577 { "msp430fr58891",2,8 },
578 { "msp430fr5922",2,8 },
579 { "msp430fr59221",2,8 },
580 { "msp430fr5947",2,8 },
581 { "msp430fr59471",2,8 },
582 { "msp430fr5948",2,8 },
583 { "msp430fr5949",2,8 },
584 { "msp430fr5957",2,8 },
585 { "msp430fr5958",2,8 },
586 { "msp430fr5959",2,8 },
587 { "msp430fr5962",2,8 },
588 { "msp430fr5964",2,8 },
589 { "msp430fr5967",2,8 },
590 { "msp430fr5968",2,8 },
591 { "msp430fr5969",2,8 },
592 { "msp430fr59691",2,8 },
593 { "msp430fr5970",2,8 },
594 { "msp430fr5972",2,8 },
595 { "msp430fr59721",2,8 },
596 { "msp430fr5986",2,8 },
597 { "msp430fr5987",2,8 },
598 { "msp430fr5988",2,8 },
599 { "msp430fr5989",2,8 },
600 { "msp430fr59891",2,8 },
601 { "msp430fr5992",2,8 },
602 { "msp430fr5994",2,8 },
603 { "msp430fr59941",2,8 },
604 { "msp430fr5xx_6xxgeneric",2,8 },
605 { "msp430fr6820",2,8 },
606 { "msp430fr6822",2,8 },
607 { "msp430fr68221",2,8 },
608 { "msp430fr6870",2,8 },
609 { "msp430fr6872",2,8 },
610 { "msp430fr68721",2,8 },
611 { "msp430fr6877",2,8 },
612 { "msp430fr6879",2,8 },
613 { "msp430fr68791",2,8 },
614 { "msp430fr6887",2,8 },
615 { "msp430fr6888",2,8 },
616 { "msp430fr6889",2,8 },
617 { "msp430fr68891",2,8 },
618 { "msp430fr6920",2,8 },
619 { "msp430fr6922",2,8 },
620 { "msp430fr69221",2,8 },
621 { "msp430fr6927",2,8 },
622 { "msp430fr69271",2,8 },
623 { "msp430fr6928",2,8 },
624 { "msp430fr6970",2,8 },
625 { "msp430fr6972",2,8 },
626 { "msp430fr69721",2,8 },
627 { "msp430fr6977",2,8 },
628 { "msp430fr6979",2,8 },
629 { "msp430fr69791",2,8 },
630 { "msp430fr6987",2,8 },
631 { "msp430fr6988",2,8 },
632 { "msp430fr6989",2,8 },
633 { "msp430fr69891",2,8 },
634 { "msp430fw423",0,0 },
635 { "msp430fw425",0,0 },
636 { "msp430fw427",0,0 },
637 { "msp430fw428",0,0 },
638 { "msp430fw429",0,0 },
639 { "msp430g2001",0,0 },
640 { "msp430g2101",0,0 },
641 { "msp430g2102",0,0 },
642 { "msp430g2111",0,0 },
643 { "msp430g2112",0,0 },
644 { "msp430g2113",0,0 },
645 { "msp430g2121",0,0 },
646 { "msp430g2131",0,0 },
647 { "msp430g2132",0,0 },
648 { "msp430g2152",0,0 },
649 { "msp430g2153",0,0 },
650 { "msp430g2201",0,0 },
651 { "msp430g2202",0,0 },
652 { "msp430g2203",0,0 },
653 { "msp430g2210",0,0 },
654 { "msp430g2211",0,0 },
655 { "msp430g2212",0,0 },
656 { "msp430g2213",0,0 },
657 { "msp430g2221",0,0 },
658 { "msp430g2230",0,0 },
659 { "msp430g2231",0,0 },
660 { "msp430g2232",0,0 },
661 { "msp430g2233",0,0 },
662 { "msp430g2252",0,0 },
663 { "msp430g2253",0,0 },
664 { "msp430g2302",0,0 },
665 { "msp430g2303",0,0 },
666 { "msp430g2312",0,0 },
667 { "msp430g2313",0,0 },
668 { "msp430g2332",0,0 },
669 { "msp430g2333",0,0 },
670 { "msp430g2352",0,0 },
671 { "msp430g2353",0,0 },
672 { "msp430g2402",0,0 },
673 { "msp430g2403",0,0 },
674 { "msp430g2412",0,0 },
675 { "msp430g2413",0,0 },
676 { "msp430g2432",0,0 },
677 { "msp430g2433",0,0 },
678 { "msp430g2444",0,0 },
679 { "msp430g2452",0,0 },
680 { "msp430g2453",0,0 },
681 { "msp430g2513",0,0 },
682 { "msp430g2533",0,0 },
683 { "msp430g2544",0,0 },
684 { "msp430g2553",0,0 },
685 { "msp430g2744",0,0 },
686 { "msp430g2755",0,0 },
687 { "msp430g2855",0,0 },
688 { "msp430g2955",0,0 },
689 { "msp430i2020",0,2 },
690 { "msp430i2021",0,2 },
691 { "msp430i2030",0,2 },
692 { "msp430i2031",0,2 },
693 { "msp430i2040",0,2 },
694 { "msp430i2041",0,2 },
695 { "msp430i2xxgeneric",0,2 },
696 { "msp430l092",0,0 },
697 { "msp430p112",0,0 },
698 { "msp430p313",0,0 },
699 { "msp430p315",0,0 },
700 { "msp430p315s",0,0 },
701 { "msp430p325",0,0 },
702 { "msp430p337",0,1 },
703 { "msp430sl5438a",2,8 },
704 { "msp430tch5e",0,0 },
705 { "msp430xgeneric",2,8 },
706 { "rf430f5144",2,8 },
707 { "rf430f5155",2,8 },
708 { "rf430f5175",2,8 },
709 { "rf430frl152h",0,0 },
710 { "rf430frl152h_rom",0,0 },
711 { "rf430frl153h",0,0 },
712 { "rf430frl153h_rom",0,0 },
713 { "rf430frl154h",0,0 },
714 { "rf430frl154h_rom",0,0 }
717 /* Generate a C preprocessor symbol based upon the MCU selected by the user.
718 If a specific MCU has not been selected then return a generic symbol instead. */
721 msp430_mcu_name (void)
726 static char mcu_name
[64];
728 snprintf (mcu_name
, sizeof (mcu_name
) - 1, "__%s__", target_mcu
);
729 for (i
= strlen (mcu_name
); i
--;)
730 mcu_name
[i
] = TOUPPER (mcu_name
[i
]);
734 return msp430x
? "__MSP430XGENERIC__" : "__MSP430GENERIC__";
738 hwmult_name (unsigned int val
)
742 case 0: return "none";
743 case 1: return "16-bit";
744 case 2: return "16-bit";
745 case 4: return "32-bit";
746 case 8: return "32-bit (5xx)";
747 default: gcc_unreachable ();
752 msp430_option_override (void)
754 init_machine_status
= msp430_init_machine_status
;
758 /* gcc/common/config/msp430-common.c will have
759 already canonicalised the string in target_cpu. */
760 if (strcasecmp (target_cpu
, "msp430x") == 0)
762 else /* target_cpu == "msp430" - already handled by the front end. */
770 /* FIXME: If the array were alpha sorted, we could use a binary search. */
771 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
772 if (strcasecmp (msp430_mcu_data
[i
].name
, target_mcu
) == 0)
774 bool xisa
= msp430_mcu_data
[i
].revision
>= 1;
778 if (target_cpu
&& msp430x
!= xisa
)
779 warning (0, "MCU '%s' supports %s ISA but -mcpu option is set to %s",
780 target_mcu
, xisa
? "430X" : "430", msp430x
? "430X" : "430");
782 if (msp430_mcu_data
[i
].hwmpy
== 0
783 && msp430_hwmult_type
!= MSP430_HWMULT_AUTO
784 && msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
785 warning (0, "MCU '%s' does not have hardware multiply support, but -mhwmult is set to %s",
787 msp430_hwmult_type
== MSP430_HWMULT_SMALL
? "16-bit"
788 : msp430_hwmult_type
== MSP430_HWMULT_LARGE
? "32-bit" : "f5series");
789 else if (msp430_hwmult_type
== MSP430_HWMULT_SMALL
790 && msp430_mcu_data
[i
].hwmpy
!= 1
791 && msp430_mcu_data
[i
].hwmpy
!= 2 )
792 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 16-bit",
793 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
794 else if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
&& msp430_mcu_data
[i
].hwmpy
!= 4)
795 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to 32-bit",
796 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
797 else if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
&& msp430_mcu_data
[i
].hwmpy
!= 8)
798 warning (0, "MCU '%s' supports %s hardware multiply, but -mhwmult is set to f5series",
799 target_mcu
, hwmult_name (msp430_mcu_data
[i
].hwmpy
));
808 if (msp430_hwmult_type
== MSP430_HWMULT_AUTO
)
812 if (target_cpu
== NULL
)
814 "Unrecognized MCU name '%s', assuming that it is "
815 "just a MSP430 with no hardware multiply.\n"
816 "Use the -mcpu and -mhwmult options to set "
821 "Unrecognized MCU name '%s', assuming that it "
822 "has no hardware multiply.\nUse the -mhwmult "
823 "option to set this explicitly.",
827 msp430_hwmult_type
= MSP430_HWMULT_NONE
;
829 else if (target_cpu
== NULL
)
833 "Unrecognized MCU name '%s', assuming that it just "
834 "supports the MSP430 ISA.\nUse the -mcpu option to "
835 "set the ISA explicitly.",
840 else if (msp430_warn_mcu
)
841 warning (0, "Unrecognized MCU name '%s'.", target_mcu
);
845 /* The F5 series are all able to support the 430X ISA. */
846 if (target_cpu
== NULL
&& target_mcu
== NULL
&& msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
849 if (TARGET_LARGE
&& !msp430x
)
850 error ("-mlarge requires a 430X-compatible -mmcu=");
852 if (msp430_code_region
== MSP430_REGION_UPPER
&& ! msp430x
)
853 error ("-mcode-region=upper requires 430X-compatible cpu");
854 if (msp430_data_region
== MSP430_REGION_UPPER
&& ! msp430x
)
855 error ("-mdata-region=upper requires 430X-compatible cpu");
857 if (flag_exceptions
|| flag_non_call_exceptions
858 || flag_unwind_tables
|| flag_asynchronous_unwind_tables
)
859 flag_omit_frame_pointer
= false;
861 flag_omit_frame_pointer
= true;
863 /* This is a hack to work around a problem with the newlib build
864 mechanism. Newlib always appends CFLAGS to the end of the GCC
865 command line and always sets -O2 in CFLAGS. Thus it is not
866 possible to build newlib with -Os enabled. Until now... */
867 if (TARGET_OPT_SPACE
&& optimize
< 3)
871 #undef TARGET_SCALAR_MODE_SUPPORTED_P
872 #define TARGET_SCALAR_MODE_SUPPORTED_P msp430_scalar_mode_supported_p
875 msp430_scalar_mode_supported_p (scalar_mode m
)
877 if (m
== PSImode
&& msp430x
)
883 return default_scalar_mode_supported_p (m
);
890 #undef TARGET_MS_BITFIELD_LAYOUT_P
891 #define TARGET_MS_BITFIELD_LAYOUT_P msp430_ms_bitfield_layout_p
894 msp430_ms_bitfield_layout_p (const_tree record_type ATTRIBUTE_UNUSED
)
903 /* Implements HARD_REGNO_NREGS. MSP430X registers can hold a single
904 PSImode value, but not an SImode value. */
906 msp430_hard_regno_nregs (int regno ATTRIBUTE_UNUSED
,
909 if (mode
== PSImode
&& msp430x
)
911 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
915 /* Implements HARD_REGNO_NREGS_HAS_PADDING. */
917 msp430_hard_regno_nregs_has_padding (int regno ATTRIBUTE_UNUSED
,
920 if (mode
== PSImode
&& msp430x
)
922 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1)
926 /* Implements HARD_REGNO_NREGS_WITH_PADDING. */
928 msp430_hard_regno_nregs_with_padding (int regno ATTRIBUTE_UNUSED
,
933 return msp430_hard_regno_nregs (regno
, mode
);
936 #undef TARGET_HARD_REGNO_MODE_OK
937 #define TARGET_HARD_REGNO_MODE_OK msp430_hard_regno_mode_ok
940 msp430_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
942 return regno
<= (ARG_POINTER_REGNUM
943 - (unsigned int) msp430_hard_regno_nregs (regno
, mode
));
946 #undef TARGET_MODES_TIEABLE_P
947 #define TARGET_MODES_TIEABLE_P msp430_modes_tieable_p
950 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
952 if ((mode1
== PSImode
|| mode2
== SImode
)
953 || (mode1
== SImode
|| mode2
== PSImode
))
956 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
957 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
958 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
959 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
962 #undef TARGET_FRAME_POINTER_REQUIRED
963 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
966 msp430_frame_pointer_required (void)
971 #undef TARGET_CAN_ELIMINATE
972 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
975 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
976 const int to_reg ATTRIBUTE_UNUSED
)
981 /* Implements INITIAL_ELIMINATION_OFFSET. */
983 msp430_initial_elimination_offset (int from
, int to
)
985 int rv
= 0; /* As if arg to arg. */
987 msp430_compute_frame_info ();
991 case STACK_POINTER_REGNUM
:
992 rv
+= cfun
->machine
->framesize_outgoing
;
993 rv
+= cfun
->machine
->framesize_locals
;
995 case FRAME_POINTER_REGNUM
:
996 rv
+= cfun
->machine
->framesize_regs
;
997 /* Allow for the saved return address. */
998 rv
+= (TARGET_LARGE
? 4 : 2);
999 /* NB/ No need to allow for crtl->args.pretend_args_size.
1000 GCC does that for us. */
1008 case FRAME_POINTER_REGNUM
:
1009 /* Allow for the fall through above. */
1010 rv
-= (TARGET_LARGE
? 4 : 2);
1011 rv
-= cfun
->machine
->framesize_regs
;
1012 case ARG_POINTER_REGNUM
:
1021 /* Named Address Space support */
1024 /* Return the appropriate mode for a named address pointer. */
1025 #undef TARGET_ADDR_SPACE_POINTER_MODE
1026 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1027 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1028 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1030 static scalar_int_mode
1031 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1036 case ADDR_SPACE_GENERIC
:
1038 case ADDR_SPACE_NEAR
:
1040 case ADDR_SPACE_FAR
:
1045 /* Function pointers are stored in unwind_word sized
1046 variables, so make sure that unwind_word is big enough. */
1047 #undef TARGET_UNWIND_WORD_MODE
1048 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1050 static scalar_int_mode
1051 msp430_unwind_word_mode (void)
1053 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1054 return msp430x
? PSImode
: HImode
;
1057 /* Determine if one named address space is a subset of another. */
1058 #undef TARGET_ADDR_SPACE_SUBSET_P
1059 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1061 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1063 if (subset
== superset
)
1066 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1069 #undef TARGET_ADDR_SPACE_CONVERT
1070 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1071 /* Convert from one address space to another. */
1073 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1075 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1076 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1079 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1081 /* This is unpredictable, as we're truncating off usable address
1084 if (CONSTANT_P (op
))
1085 return gen_rtx_CONST (HImode
, op
);
1087 result
= gen_reg_rtx (HImode
);
1088 emit_insn (gen_truncpsihi2 (result
, op
));
1091 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1093 /* This always works. */
1095 if (CONSTANT_P (op
))
1096 return gen_rtx_CONST (PSImode
, op
);
1098 result
= gen_reg_rtx (PSImode
);
1099 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1106 /* Stack Layout and Calling Conventions. */
1108 /* For each function, we list the gcc version and the TI version on
1109 each line, where we're converting the function names. */
1110 static char const * const special_convention_function_names
[] =
1112 "__muldi3", "__mspabi_mpyll",
1113 "__udivdi3", "__mspabi_divull",
1114 "__umoddi3", "__mspabi_remull",
1115 "__divdi3", "__mspabi_divlli",
1116 "__moddi3", "__mspabi_remlli",
1120 "__adddf3", "__mspabi_addd",
1121 "__subdf3", "__mspabi_subd",
1122 "__muldf3", "__mspabi_mpyd",
1123 "__divdf3", "__mspabi_divd",
1128 /* TRUE if the function passed is a "speical" function. Special
1129 functions pass two DImode parameters in registers. */
1131 msp430_special_register_convention_p (const char *name
)
1135 for (i
= 0; special_convention_function_names
[i
]; i
++)
1136 if (! strcmp (name
, special_convention_function_names
[i
]))
1142 #undef TARGET_FUNCTION_VALUE_REGNO_P
1143 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1146 msp430_function_value_regno_p (unsigned int regno
)
1152 #undef TARGET_FUNCTION_VALUE
1153 #define TARGET_FUNCTION_VALUE msp430_function_value
1156 msp430_function_value (const_tree ret_type
,
1157 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1158 bool outgoing ATTRIBUTE_UNUSED
)
1160 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1163 #undef TARGET_LIBCALL_VALUE
1164 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1167 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1169 return gen_rtx_REG (mode
, 12);
1172 /* Implements INIT_CUMULATIVE_ARGS. */
1174 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1175 tree fntype ATTRIBUTE_UNUSED
,
1176 rtx libname ATTRIBUTE_UNUSED
,
1177 tree fndecl ATTRIBUTE_UNUSED
,
1178 int n_named_args ATTRIBUTE_UNUSED
)
1181 memset (ca
, 0, sizeof(*ca
));
1186 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1188 fname
= XSTR (libname
, 0);
1192 if (fname
&& msp430_special_register_convention_p (fname
))
1196 /* Helper function for argument passing; this function is the common
1197 code that determines where an argument will be passed. */
1199 msp430_evaluate_arg (cumulative_args_t cap
,
1201 const_tree type ATTRIBUTE_UNUSED
,
1204 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1205 int nregs
= GET_MODE_SIZE (mode
);
1214 if (mode
== PSImode
)
1217 nregs
= (nregs
+ 1) / 2;
1221 /* Function is passed two DImode operands, in R8:R11 and
1231 for (i
= 0; i
< 4; i
++)
1232 if (! ca
->reg_used
[i
])
1235 ca
->start_reg
= CA_FIRST_REG
+ i
;
1240 for (i
= 0; i
< 3; i
++)
1241 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1244 ca
->start_reg
= CA_FIRST_REG
+ i
;
1247 if (! ca
->reg_used
[3] && ca
->can_split
)
1251 ca
->start_reg
= CA_FIRST_REG
+ 3;
1258 if (! ca
->reg_used
[0]
1259 && ! ca
->reg_used
[1]
1260 && ! ca
->reg_used
[2]
1261 && ! ca
->reg_used
[3])
1264 ca
->start_reg
= CA_FIRST_REG
;
1271 #undef TARGET_PROMOTE_PROTOTYPES
1272 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1275 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1280 #undef TARGET_FUNCTION_ARG
1281 #define TARGET_FUNCTION_ARG msp430_function_arg
1284 msp430_function_arg (cumulative_args_t cap
,
1289 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1291 msp430_evaluate_arg (cap
, mode
, type
, named
);
1294 return gen_rtx_REG (mode
, ca
->start_reg
);
1299 #undef TARGET_ARG_PARTIAL_BYTES
1300 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1303 msp430_arg_partial_bytes (cumulative_args_t cap
,
1308 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1310 msp430_evaluate_arg (cap
, mode
, type
, named
);
1312 if (ca
->reg_count
&& ca
->mem_count
)
1313 return ca
->reg_count
* UNITS_PER_WORD
;
1318 #undef TARGET_PASS_BY_REFERENCE
1319 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1322 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1325 bool named ATTRIBUTE_UNUSED
)
1327 return (mode
== BLKmode
1328 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1329 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1332 #undef TARGET_CALLEE_COPIES
1333 #define TARGET_CALLEE_COPIES msp430_callee_copies
1336 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1337 machine_mode mode ATTRIBUTE_UNUSED
,
1338 const_tree type ATTRIBUTE_UNUSED
,
1339 bool named ATTRIBUTE_UNUSED
)
1344 #undef TARGET_FUNCTION_ARG_ADVANCE
1345 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1348 msp430_function_arg_advance (cumulative_args_t cap
,
1353 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1356 msp430_evaluate_arg (cap
, mode
, type
, named
);
1358 if (ca
->start_reg
>= CA_FIRST_REG
)
1359 for (i
= 0; i
< ca
->reg_count
; i
++)
1360 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1365 #undef TARGET_FUNCTION_ARG_BOUNDARY
1366 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1369 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1372 && int_size_in_bytes (type
) > 1)
1374 if (GET_MODE_BITSIZE (mode
) > 8)
1379 #undef TARGET_RETURN_IN_MEMORY
1380 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1383 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1385 machine_mode mode
= TYPE_MODE (ret_type
);
1388 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1389 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1392 if (GET_MODE_SIZE (mode
) > 8)
1398 #undef TARGET_GET_RAW_ARG_MODE
1399 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1402 msp430_get_raw_arg_mode (int regno
)
1404 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
1407 #undef TARGET_GET_RAW_RESULT_MODE
1408 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1411 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1416 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1417 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1419 #include "gimplify.h"
1422 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1425 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1426 unsigned HOST_WIDE_INT align
, boundary
;
1429 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1431 type
= build_pointer_type (type
);
1433 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1434 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1436 /* When we align parameter on stack for caller, if the parameter
1437 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1438 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1439 here with caller. */
1440 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1441 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1443 boundary
/= BITS_PER_UNIT
;
1445 /* Hoist the valist value into a temporary for the moment. */
1446 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1448 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1449 requires greater alignment, we must perform dynamic alignment. */
1450 if (boundary
> align
1451 && !integer_zerop (TYPE_SIZE (type
)))
1453 /* FIXME: This is where this function diverts from targhooks.c:
1454 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1455 if (! POINTER_TYPE_P (type
))
1457 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1458 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1459 gimplify_and_add (t
, pre_p
);
1461 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1462 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1464 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1465 gimplify_and_add (t
, pre_p
);
1471 /* If the actual alignment is less than the alignment of the type,
1472 adjust the type accordingly so that we don't assume strict alignment
1473 when dereferencing the pointer. */
1474 boundary
*= BITS_PER_UNIT
;
1475 if (boundary
< TYPE_ALIGN (type
))
1477 type
= build_variant_type_copy (type
);
1478 SET_TYPE_ALIGN (type
, boundary
);
1481 /* Compute the rounded size of the type. */
1482 type_size
= size_in_bytes (type
);
1483 rounded_size
= round_up (type_size
, align
);
1485 /* Reduce rounded_size so it's sharable with the postqueue. */
1486 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1491 /* Compute new value for AP. */
1492 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1493 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1494 gimplify_and_add (t
, pre_p
);
1496 addr
= fold_convert (build_pointer_type (type
), addr
);
1499 addr
= build_va_arg_indirect_ref (addr
);
1501 addr
= build_va_arg_indirect_ref (addr
);
1507 #define TARGET_LRA_P hook_bool_void_false
1509 /* Addressing Modes */
1511 #undef TARGET_LEGITIMATE_ADDRESS_P
1512 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1515 reg_ok_for_addr (rtx r
, bool strict
)
1519 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1520 rn
= reg_renumber
[rn
];
1521 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1529 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1530 rtx x ATTRIBUTE_UNUSED
,
1531 bool strict ATTRIBUTE_UNUSED
)
1533 switch (GET_CODE (x
))
1539 if (REG_P (XEXP (x
, 0)))
1541 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1543 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1545 switch (GET_CODE (XEXP (x
, 1)))
1558 if (!reg_ok_for_addr (x
, strict
))
1571 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1572 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1575 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1578 addr_space_t as ATTRIBUTE_UNUSED
)
1580 return msp430_legitimate_address_p (mode
, x
, strict
);
1583 #undef TARGET_ASM_INTEGER
1584 #define TARGET_ASM_INTEGER msp430_asm_integer
1586 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1588 int c
= GET_CODE (x
);
1590 if (size
== 3 && GET_MODE (x
) == PSImode
)
1596 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1597 || c
== PLUS
|| c
== MINUS
)
1599 fprintf (asm_out_file
, "\t.long\t");
1600 output_addr_const (asm_out_file
, x
);
1601 fputc ('\n', asm_out_file
);
1606 return default_assemble_integer (x
, size
, aligned_p
);
1609 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1610 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1612 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1618 #undef TARGET_LEGITIMATE_CONSTANT_P
1619 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1622 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1624 return ! CONST_INT_P (x
)
1626 /* GCC does not know the width of the PSImode, so make
1627 sure that it does not try to use a constant value that
1629 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1633 #undef TARGET_RTX_COSTS
1634 #define TARGET_RTX_COSTS msp430_rtx_costs
1636 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1638 int outer_code ATTRIBUTE_UNUSED
,
1639 int opno ATTRIBUTE_UNUSED
,
1641 bool speed ATTRIBUTE_UNUSED
)
1643 int code
= GET_CODE (x
);
1648 if (mode
== SImode
&& outer_code
== SET
)
1650 *total
= COSTS_N_INSNS (4);
1659 *total
= COSTS_N_INSNS (100);
1667 /* Function Entry and Exit */
1669 /* The MSP430 call frame looks like this:
1672 +--------------------+
1676 +--------------------+ <-- "arg pointer"
1678 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1680 +--------------------+
1681 | SR if this func has|
1682 | been called via an |
1684 +--------------------+ <-- SP before prologue, also AP
1686 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1688 +--------------------+ <-- "frame pointer"
1692 +--------------------+
1696 +--------------------+ <-- SP during function
1701 /* We use this to wrap all emitted insns in the prologue, so they get
1702 the "frame-related" (/f) flag set. */
1706 RTX_FRAME_RELATED_P (x
) = 1;
1710 /* This is the one spot that decides if a register is to be saved and
1711 restored in the prologue/epilogue. */
1713 msp430_preserve_reg_p (int regno
)
1715 /* PC, SP, SR, and the constant generator. */
1719 /* FIXME: add interrupt, EH, etc. */
1720 if (crtl
->calls_eh_return
)
1723 /* Shouldn't be more than the above, but just in case... */
1724 if (fixed_regs
[regno
])
1727 /* Interrupt handlers save all registers they use, even
1728 ones which are call saved. If they call other functions
1729 then *every* register is saved. */
1730 if (msp430_is_interrupt_func ())
1731 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1733 if (!call_used_regs
[regno
]
1734 && df_regs_ever_live_p (regno
))
1740 /* Compute all the frame-related fields in our machine_function
1743 msp430_compute_frame_info (void)
1747 cfun
->machine
->computed
= 1;
1748 cfun
->machine
->framesize_regs
= 0;
1749 cfun
->machine
->framesize_locals
= get_frame_size ();
1750 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1752 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1753 if (msp430_preserve_reg_p (i
))
1755 cfun
->machine
->need_to_save
[i
] = 1;
1756 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1759 cfun
->machine
->need_to_save
[i
] = 0;
1761 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1762 cfun
->machine
->framesize_locals
++;
1764 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1765 + cfun
->machine
->framesize_locals
1766 + cfun
->machine
->framesize_outgoing
);
1769 /* Attribute Handling. */
1771 const char * const ATTR_INTR
= "interrupt";
1772 const char * const ATTR_WAKEUP
= "wakeup";
1773 const char * const ATTR_NAKED
= "naked";
1774 const char * const ATTR_REENT
= "reentrant";
1775 const char * const ATTR_CRIT
= "critical";
1776 const char * const ATTR_LOWER
= "lower";
1777 const char * const ATTR_UPPER
= "upper";
1778 const char * const ATTR_EITHER
= "either";
1779 const char * const ATTR_NOINIT
= "noinit";
1780 const char * const ATTR_PERSIST
= "persistent";
1783 has_attr (const char * attr
, tree decl
)
1785 if (decl
== NULL_TREE
)
1787 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1791 is_interrupt_func (tree decl
= current_function_decl
)
1793 return has_attr (ATTR_INTR
, decl
);
1796 /* Returns true if the current function has the "interrupt" attribute. */
1799 msp430_is_interrupt_func (void)
1801 return is_interrupt_func (current_function_decl
);
1805 is_wakeup_func (tree decl
= current_function_decl
)
1807 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1811 is_naked_func (tree decl
= current_function_decl
)
1813 return has_attr (ATTR_NAKED
, decl
);
1817 is_reentrant_func (tree decl
= current_function_decl
)
1819 return has_attr (ATTR_REENT
, decl
);
1823 is_critical_func (tree decl
= current_function_decl
)
1825 return has_attr (ATTR_CRIT
, decl
);
1829 has_section_name (const char * name
, tree decl
= current_function_decl
)
1831 if (decl
== NULL_TREE
)
1833 return (DECL_SECTION_NAME (decl
)
1834 && (strcmp (name
, DECL_SECTION_NAME (decl
)) == 0));
1837 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1838 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1841 msp430_allocate_stack_slots_for_args (void)
1843 /* Naked functions should not allocate stack slots for arguments. */
1844 return ! is_naked_func ();
1847 /* Verify MSP430 specific attributes. */
1848 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1851 msp430_attr (tree
* node
,
1854 int flags ATTRIBUTE_UNUSED
,
1855 bool * no_add_attrs
)
1857 gcc_assert (DECL_P (* node
));
1861 /* Only the interrupt attribute takes an argument. */
1862 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1864 tree value
= TREE_VALUE (args
);
1866 switch (TREE_CODE (value
))
1869 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1870 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1871 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1872 /* Allow the attribute to be added - the linker script
1873 being used may still recognise this name. */
1874 warning (OPT_Wattributes
,
1875 "unrecognized interrupt vector argument of %qE attribute",
1880 if (wi::gtu_p (value
, 63))
1881 /* Allow the attribute to be added - the linker script
1882 being used may still recognise this value. */
1883 warning (OPT_Wattributes
,
1884 "numeric argument of %qE attribute must be in range 0..63",
1889 warning (OPT_Wattributes
,
1890 "argument of %qE attribute is not a string constant or number",
1892 *no_add_attrs
= true;
1897 const char * message
= NULL
;
1899 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1901 message
= "%qE attribute only applies to functions";
1903 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1905 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1906 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1907 message
= "interrupt handlers must be void";
1909 if (! TREE_PUBLIC (* node
))
1910 message
= "interrupt handlers cannot be static";
1912 /* Ensure interrupt handlers never get optimised out. */
1913 TREE_USED (* node
) = 1;
1914 DECL_PRESERVE_P (* node
) = 1;
1916 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1918 if (is_naked_func (* node
))
1919 message
= "naked functions cannot be reentrant";
1920 else if (is_critical_func (* node
))
1921 message
= "critical functions cannot be reentrant";
1923 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1925 if (is_naked_func (* node
))
1926 message
= "naked functions cannot be critical";
1927 else if (is_reentrant_func (* node
))
1928 message
= "reentrant functions cannot be critical";
1930 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1932 if (is_critical_func (* node
))
1933 message
= "critical functions cannot be naked";
1934 else if (is_reentrant_func (* node
))
1935 message
= "reentrant functions cannot be naked";
1940 warning (OPT_Wattributes
, message
, name
);
1941 * no_add_attrs
= true;
1948 msp430_section_attr (tree
* node
,
1951 int flags ATTRIBUTE_UNUSED
,
1952 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1954 gcc_assert (DECL_P (* node
));
1955 gcc_assert (args
== NULL
);
1957 const char * message
= NULL
;
1959 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1961 if (has_attr (ATTR_LOWER
, * node
))
1962 message
= "already marked with 'lower' attribute";
1963 else if (has_attr (ATTR_EITHER
, * node
))
1964 message
= "already marked with 'either' attribute";
1966 message
= "upper attribute needs a 430X cpu";
1968 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1970 if (has_attr (ATTR_UPPER
, * node
))
1971 message
= "already marked with 'upper' attribute";
1972 else if (has_attr (ATTR_EITHER
, * node
))
1973 message
= "already marked with 'either' attribute";
1977 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1979 if (has_attr (ATTR_LOWER
, * node
))
1980 message
= "already marked with 'lower' attribute";
1981 else if (has_attr (ATTR_UPPER
, * node
))
1982 message
= "already marked with 'upper' attribute";
1987 warning (OPT_Wattributes
, message
, name
);
1988 * no_add_attrs
= true;
1995 msp430_data_attr (tree
* node
,
1998 int flags ATTRIBUTE_UNUSED
,
1999 bool * no_add_attrs ATTRIBUTE_UNUSED
)
2001 const char * message
= NULL
;
2003 gcc_assert (DECL_P (* node
));
2004 gcc_assert (args
== NULL
);
2006 if (TREE_CODE (* node
) != VAR_DECL
)
2007 message
= G_("%qE attribute only applies to variables");
2009 /* Check that it's possible for the variable to have a section. */
2010 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2011 && DECL_SECTION_NAME (* node
))
2012 message
= G_("%qE attribute cannot be applied to variables with specific sections");
2014 if (!message
&& TREE_NAME_EQ (name
, ATTR_PERSIST
) && !TREE_STATIC (* node
)
2015 && !TREE_PUBLIC (* node
) && !DECL_EXTERNAL (* node
))
2016 message
= G_("%qE attribute has no effect on automatic variables");
2018 /* It's not clear if there is anything that can be set here to prevent the
2019 front end placing the variable before the back end can handle it, in a
2020 similar way to how DECL_COMMON is used below.
2021 So just place the variable in the .persistent section now. */
2022 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2023 && TREE_NAME_EQ (name
, ATTR_PERSIST
))
2024 set_decl_section_name (* node
, ".persistent");
2026 /* If this var is thought to be common, then change this. Common variables
2027 are assigned to sections before the backend has a chance to process them. */
2028 if (DECL_COMMON (* node
))
2029 DECL_COMMON (* node
) = 0;
2033 warning (OPT_Wattributes
, message
, name
);
2034 * no_add_attrs
= true;
2041 #undef TARGET_ATTRIBUTE_TABLE
2042 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2044 /* Table of MSP430-specific attributes. */
2045 const struct attribute_spec msp430_attribute_table
[] =
2047 /* Name min_num_args type_req, affects_type_identity
2048 max_num_args, fn_type_req
2049 decl_req handler. */
2050 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
2051 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
2052 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
2053 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
2054 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
2056 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
2057 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
2058 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
2060 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false },
2061 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false },
2063 { NULL
, 0, 0, false, false, false, NULL
, false }
2066 #undef TARGET_ASM_FUNCTION_PROLOGUE
2067 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2070 msp430_start_function (FILE *outfile
)
2074 fprintf (outfile
, "; start of function\n");
2076 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2078 fprintf (outfile
, "; attributes: ");
2079 if (is_naked_func ())
2080 fprintf (outfile
, "naked ");
2081 if (msp430_is_interrupt_func ())
2082 fprintf (outfile
, "interrupt ");
2083 if (is_reentrant_func ())
2084 fprintf (outfile
, "reentrant ");
2085 if (is_critical_func ())
2086 fprintf (outfile
, "critical ");
2087 if (is_wakeup_func ())
2088 fprintf (outfile
, "wakeup ");
2089 fprintf (outfile
, "\n");
2092 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2093 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2094 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2095 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2096 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2097 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2100 fprintf (outfile
, "; saved regs:");
2101 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2102 if (cfun
->machine
->need_to_save
[r
])
2104 fprintf (outfile
, " %s", reg_names
[r
]);
2108 fprintf (outfile
, "(none)");
2109 fprintf (outfile
, "\n");
2112 /* Common code to change the stack pointer. */
2114 increment_stack (HOST_WIDE_INT amount
)
2117 rtx sp
= stack_pointer_rtx
;
2124 inc
= GEN_INT (- amount
);
2126 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2128 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2132 inc
= GEN_INT (amount
);
2134 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2136 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2141 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2145 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2146 if (int_attr
!= NULL_TREE
)
2148 tree intr_vector
= TREE_VALUE (int_attr
);
2150 if (intr_vector
!= NULL_TREE
)
2154 /* Interrupt vector sections should be unique, but use of weak
2155 functions implies multiple definitions. */
2156 if (DECL_WEAK (decl
))
2158 error ("argument to interrupt attribute is unsupported for weak functions");
2161 intr_vector
= TREE_VALUE (intr_vector
);
2163 /* The interrupt attribute has a vector value. Turn this into a
2164 section name, switch to that section and put the address of
2165 the current function into that vector slot. Note msp430_attr()
2166 has already verified the vector name for us. */
2167 if (TREE_CODE (intr_vector
) == STRING_CST
)
2168 sprintf (buf
, "__interrupt_vector_%.80s",
2169 TREE_STRING_POINTER (intr_vector
));
2170 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2171 sprintf (buf
, "__interrupt_vector_%u",
2172 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2174 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2175 fputs ("\t.word\t", file
);
2176 assemble_name (file
, name
);
2182 switch_to_section (function_section (decl
));
2183 ASM_OUTPUT_TYPE_DIRECTIVE(file
, name
, "function");
2184 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2187 static const char * const lower_prefix
= ".lower";
2188 static const char * const upper_prefix
= ".upper";
2189 static const char * const either_prefix
= ".either";
2191 /* Generate a prefix for a section name, based upon
2192 the region into which the object should be placed. */
2195 gen_prefix (tree decl
)
2197 if (DECL_ONE_ONLY (decl
))
2200 /* If the user has specified a particular section then do not use any prefix. */
2201 if (has_attr ("section", decl
))
2204 /* If the function has been put in the .lowtext section (because it is an
2205 interrupt handler, and the large memory model is used), then do not add
2207 if (has_section_name (".lowtext", decl
))
2210 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2211 if (has_attr (ATTR_LOWER
, decl
))
2212 return lower_prefix
;
2214 /* If we are compiling for the MSP430 then we do not support the upper region. */
2218 if (has_attr (ATTR_UPPER
, decl
))
2219 return upper_prefix
;
2221 if (has_attr (ATTR_EITHER
, decl
))
2222 return either_prefix
;
2224 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2226 if (msp430_code_region
== MSP430_REGION_LOWER
)
2227 return lower_prefix
;
2229 if (msp430_code_region
== MSP430_REGION_UPPER
)
2230 return upper_prefix
;
2232 if (msp430_code_region
== MSP430_REGION_EITHER
)
2233 return either_prefix
;
2237 if (msp430_data_region
== MSP430_REGION_LOWER
)
2238 return lower_prefix
;
2240 if (msp430_data_region
== MSP430_REGION_UPPER
)
2241 return upper_prefix
;
2243 if (msp430_data_region
== MSP430_REGION_EITHER
)
2244 return either_prefix
;
2250 static section
* noinit_section
;
2251 static section
* persist_section
;
2253 #undef TARGET_ASM_INIT_SECTIONS
2254 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2257 msp430_init_sections (void)
2259 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2260 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2263 #undef TARGET_ASM_SELECT_SECTION
2264 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2267 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2269 gcc_assert (decl
!= NULL_TREE
);
2271 if (TREE_CODE (decl
) == STRING_CST
2272 || TREE_CODE (decl
) == CONSTRUCTOR
2273 || TREE_CODE (decl
) == INTEGER_CST
2274 || TREE_CODE (decl
) == VECTOR_CST
2275 || TREE_CODE (decl
) == COMPLEX_CST
)
2276 return default_select_section (decl
, reloc
, align
);
2278 /* In large mode we must make sure that interrupt handlers are put into
2279 low memory as the vector table only accepts 16-bit addresses. */
2280 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2281 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2283 const char * prefix
= gen_prefix (decl
);
2286 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2287 return text_section
;
2288 else if (has_attr (ATTR_NOINIT
, decl
))
2289 return noinit_section
;
2290 else if (has_attr (ATTR_PERSIST
, decl
))
2291 return persist_section
;
2293 return default_select_section (decl
, reloc
, align
);
2297 switch (categorize_decl_for_section (decl
, reloc
))
2299 case SECCAT_TEXT
: sec
= ".text"; break;
2300 case SECCAT_DATA
: sec
= ".data"; break;
2301 case SECCAT_BSS
: sec
= ".bss"; break;
2302 case SECCAT_RODATA
: sec
= ".rodata"; break;
2304 case SECCAT_RODATA_MERGE_STR
:
2305 case SECCAT_RODATA_MERGE_STR_INIT
:
2306 case SECCAT_RODATA_MERGE_CONST
:
2307 case SECCAT_SRODATA
:
2308 case SECCAT_DATA_REL
:
2309 case SECCAT_DATA_REL_LOCAL
:
2310 case SECCAT_DATA_REL_RO
:
2311 case SECCAT_DATA_REL_RO_LOCAL
:
2316 return default_select_section (decl
, reloc
, align
);
2322 const char * dec_name
= DECL_SECTION_NAME (decl
);
2323 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2325 return get_named_section (decl
, name
, 0);
2328 #undef TARGET_ASM_FUNCTION_SECTION
2329 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2332 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2336 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2337 name
= DECL_SECTION_NAME (decl
);
2339 const char * prefix
= gen_prefix (decl
);
2341 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2342 return default_function_section (decl
, freq
, startup
, exit
);
2344 name
= ACONCAT ((prefix
, name
, NULL
));
2345 return get_named_section (decl
, name
, 0);
2348 #undef TARGET_SECTION_TYPE_FLAGS
2349 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2352 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2354 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2355 name
+= strlen (lower_prefix
);
2356 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2357 name
+= strlen (upper_prefix
);
2358 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2359 name
+= strlen (either_prefix
);
2360 else if (strcmp (name
, ".noinit") == 0)
2361 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2362 else if (strcmp (name
, ".persistent") == 0)
2363 return SECTION_WRITE
| SECTION_NOTYPE
;
2365 return default_section_type_flags (decl
, name
, reloc
);
2368 #undef TARGET_ASM_UNIQUE_SECTION
2369 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2372 msp430_unique_section (tree decl
, int reloc
)
2374 gcc_assert (decl
!= NULL_TREE
);
2376 /* In large mode we must make sure that interrupt handlers are put into
2377 low memory as the vector table only accepts 16-bit addresses. */
2378 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2380 set_decl_section_name (decl
, ".lowtext");
2384 default_unique_section (decl
, reloc
);
2386 const char * prefix
;
2388 if ( TREE_CODE (decl
) == STRING_CST
2389 || TREE_CODE (decl
) == CONSTRUCTOR
2390 || TREE_CODE (decl
) == INTEGER_CST
2391 || TREE_CODE (decl
) == VECTOR_CST
2392 || TREE_CODE (decl
) == COMPLEX_CST
2393 || (prefix
= gen_prefix (decl
)) == NULL
2397 const char * dec_name
= DECL_SECTION_NAME (decl
);
2398 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2400 set_decl_section_name (decl
, name
);
2403 /* Emit a declaration of a common symbol.
2404 If a data region is in use then put the symbol into the
2405 equivalent .bss section instead. */
2408 msp430_output_aligned_decl_common (FILE * stream
,
2411 unsigned HOST_WIDE_INT size
,
2414 if (msp430_data_region
== MSP430_REGION_ANY
)
2416 fprintf (stream
, COMMON_ASM_OP
);
2417 assemble_name (stream
, name
);
2418 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2419 size
, align
/ BITS_PER_UNIT
);
2426 sec
= msp430_select_section (decl
, 0, align
);
2428 switch (msp430_data_region
)
2430 case MSP430_REGION_UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2431 case MSP430_REGION_LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2432 case MSP430_REGION_EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2436 gcc_assert (sec
!= NULL
);
2438 switch_to_section (sec
);
2439 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2440 targetm
.asm_out
.globalize_label (stream
, name
);
2441 ASM_WEAKEN_LABEL (stream
, name
);
2442 ASM_OUTPUT_LABEL (stream
, name
);
2443 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2448 msp430_do_not_relax_short_jumps (void)
2450 /* When placing code into "either" low or high memory we do not want the linker
2451 to grow the size of sections, which it can do if it is encounters a branch to
2452 a label that is too far away. So we tell the cbranch patterns to avoid using
2453 short jumps when there is a chance that the instructions will end up in a low
2456 msp430_code_region
== MSP430_REGION_EITHER
2457 || msp430_code_region
== MSP430_REGION_LOWER
2458 || has_attr (ATTR_EITHER
, current_function_decl
)
2459 || has_attr (ATTR_LOWER
, current_function_decl
);
2464 MSP430_BUILTIN_BIC_SR
,
2465 MSP430_BUILTIN_BIS_SR
,
2466 MSP430_BUILTIN_DELAY_CYCLES
,
2470 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2473 msp430_init_builtins (void)
2475 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2476 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2478 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2479 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2480 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2482 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2483 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2484 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2486 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2487 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2488 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2492 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2496 case MSP430_BUILTIN_BIC_SR
:
2497 case MSP430_BUILTIN_BIS_SR
:
2498 case MSP430_BUILTIN_DELAY_CYCLES
:
2499 return msp430_builtins
[code
];
2501 return error_mark_node
;
2505 /* These constants are really register reads, which are faster than
2506 regular constants. */
2508 cg_magic_constant (HOST_WIDE_INT c
)
2526 msp430_expand_delay_cycles (rtx arg
)
2528 HOST_WIDE_INT i
, c
, n
;
2529 /* extra cycles for MSP430X instructions */
2530 #define CYCX(M,X) (msp430x ? (X) : (M))
2532 if (GET_CODE (arg
) != CONST_INT
)
2534 error ("__delay_cycles() only takes constant arguments");
2540 if (HOST_BITS_PER_WIDE_INT
> 32)
2544 error ("__delay_cycles only takes non-negative cycle counts");
2549 emit_insn (gen_delay_cycles_start (arg
));
2551 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2552 if (c
> 3 * 0xffff + CYCX (7, 10))
2555 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2556 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2559 c
-= CYCX (14, 16) + 7 * 0x10000;
2562 if ((unsigned long long) i
> 0xffffffffULL
)
2564 error ("__delay_cycles is limited to 32-bit loop counts");
2570 i
= (c
- CYCX (14, 16)) / 7;
2571 c
-= CYCX (14, 16) + i
* 7;
2574 if (cg_magic_constant (i
& 0xffff))
2576 if (cg_magic_constant ((i
>> 16) & 0xffff))
2580 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2582 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2585 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2589 i
= (c
- CYCX (7, 10)) / 3;
2590 c
-= CYCX (7, 10) + i
* 3;
2592 if (cg_magic_constant (i
))
2596 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2598 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2603 emit_insn (gen_delay_cycles_2 ());
2609 emit_insn (gen_delay_cycles_1 ());
2613 emit_insn (gen_delay_cycles_end (arg
));
2619 msp430_expand_builtin (tree exp
,
2620 rtx target ATTRIBUTE_UNUSED
,
2621 rtx subtarget ATTRIBUTE_UNUSED
,
2622 machine_mode mode ATTRIBUTE_UNUSED
,
2623 int ignore ATTRIBUTE_UNUSED
)
2625 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2626 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2627 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2629 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2630 return msp430_expand_delay_cycles (arg1
);
2632 if (! msp430_is_interrupt_func ())
2634 error ("MSP430 builtin functions only work inside interrupt handlers");
2638 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2639 arg1
= force_reg (mode
, arg1
);
2643 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2644 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2646 internal_error ("bad builtin code");
2652 #undef TARGET_INIT_BUILTINS
2653 #define TARGET_INIT_BUILTINS msp430_init_builtins
2655 #undef TARGET_EXPAND_BUILTIN
2656 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2658 #undef TARGET_BUILTIN_DECL
2659 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2662 msp430_expand_prologue (void)
2666 /* Always use stack_pointer_rtx instead of calling
2667 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2668 that there is a single rtx representing the stack pointer,
2669 namely stack_pointer_rtx, and uses == to recognize it. */
2670 rtx sp
= stack_pointer_rtx
;
2673 if (is_naked_func ())
2675 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2676 examines the output of the gen_prologue() function. */
2677 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2681 emit_insn (gen_prologue_start_marker ());
2683 if (is_critical_func ())
2685 emit_insn (gen_push_intr_state ());
2686 emit_insn (gen_disable_interrupts ());
2688 else if (is_reentrant_func ())
2689 emit_insn (gen_disable_interrupts ());
2691 if (!cfun
->machine
->computed
)
2692 msp430_compute_frame_info ();
2694 if (flag_stack_usage_info
)
2695 current_function_static_stack_size
= cfun
->machine
->framesize
;
2697 if (crtl
->args
.pretend_args_size
)
2701 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2703 p
= emit_insn (gen_grow_and_swap ());
2705 /* Document the stack decrement... */
2706 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2707 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2708 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2710 /* ...and the establishment of a new location for the return address. */
2711 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2712 gen_rtx_PLUS (Pmode
,
2716 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2720 for (i
= 15; i
>= 4; i
--)
2721 if (cfun
->machine
->need_to_save
[i
])
2726 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2732 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2733 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2736 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2738 XVECEXP (note
, 0, 0)
2739 = F (gen_rtx_SET (stack_pointer_rtx
,
2740 gen_rtx_PLUS (Pmode
,
2742 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2744 /* *sp-- = R[i-j] */
2748 for (j
= 0; j
< count
; j
++)
2751 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2754 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2756 addr
= stack_pointer_rtx
;
2758 XVECEXP (note
, 0, j
+ 1) =
2759 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2760 gen_rtx_REG (Pmode
, i
- j
)) );
2763 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2767 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2770 if (frame_pointer_needed
)
2771 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2773 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2775 increment_stack (- fs
);
2777 emit_insn (gen_prologue_end_marker ());
2781 msp430_expand_epilogue (int is_eh
)
2787 if (is_naked_func ())
2789 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2790 examines the output of the gen_epilogue() function. */
2791 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2795 if (cfun
->machine
->need_to_save
[10])
2797 /* Check for a helper function. */
2798 helper_n
= 7; /* For when the loop below never sees a match. */
2799 for (i
= 9; i
>= 4; i
--)
2800 if (!cfun
->machine
->need_to_save
[i
])
2804 if (cfun
->machine
->need_to_save
[i
])
2813 emit_insn (gen_epilogue_start_marker ());
2815 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2816 emit_insn (gen_msp430_refsym_need_exit ());
2818 if (is_wakeup_func ())
2819 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2820 status register current residing on the stack. When this function
2821 executes its RETI instruction the SR will be updated with this saved
2822 value, thus ensuring that the processor is woken up from any low power
2823 state in which it may be residing. */
2824 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2826 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2828 increment_stack (fs
);
2832 /* We need to add the right "SP" register save just after the
2833 regular ones, so that when we pop it off we're in the EH
2834 return frame, not this one. This overwrites our own return
2835 address, but we're not going to be returning anyway. */
2836 rtx r12
= gen_rtx_REG (Pmode
, 12);
2837 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2839 /* R12 will hold the new SP. */
2840 i
= cfun
->machine
->framesize_regs
;
2841 emit_move_insn (r12
, stack_pointer_rtx
);
2842 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2843 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2844 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2847 for (i
= 4; i
<= 15; i
++)
2848 if (cfun
->machine
->need_to_save
[i
])
2852 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2858 /* Note: With TARGET_LARGE we still use
2859 POPM as POPX.A is two bytes bigger. */
2860 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2864 else if (i
== 11 - helper_n
2865 && ! msp430_is_interrupt_func ()
2866 && ! is_reentrant_func ()
2867 && ! is_critical_func ()
2868 && crtl
->args
.pretend_args_size
== 0
2869 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2873 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2877 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2882 /* Also pop SP, which puts us into the EH return frame. Except
2883 that you can't "pop" sp, you have to just load it off the
2885 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2888 if (crtl
->args
.pretend_args_size
)
2889 emit_insn (gen_swap_and_shrink ());
2891 if (is_critical_func ())
2892 emit_insn (gen_pop_intr_state ());
2893 else if (is_reentrant_func ())
2894 emit_insn (gen_enable_interrupts ());
2896 emit_jump_insn (gen_msp_return ());
2899 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2900 m32c_emit_eh_epilogue. */
2902 msp430_eh_return_stackadj_rtx (void)
2904 if (!cfun
->machine
->eh_stack_adjust
)
2908 sa
= gen_rtx_REG (Pmode
, 15);
2909 cfun
->machine
->eh_stack_adjust
= sa
;
2911 return cfun
->machine
->eh_stack_adjust
;
2914 /* This function is called before reload, to "fix" the stack in
2915 preparation for an EH return. */
2917 msp430_expand_eh_return (rtx eh_handler
)
2919 /* These are all Pmode */
2920 rtx ap
, sa
, ra
, tmp
;
2922 ap
= arg_pointer_rtx
;
2923 sa
= msp430_eh_return_stackadj_rtx ();
2927 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2928 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2929 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2930 emit_move_insn (tmp
, ra
);
2933 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2934 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2936 msp430_init_dwarf_reg_sizes_extra (tree address
)
2939 rtx addr
= expand_normal (address
);
2940 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2942 /* This needs to match msp430_unwind_word_mode (above). */
2946 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2948 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2949 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2951 if (rnum
< DWARF_FRAME_REGISTERS
)
2953 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2955 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2956 gen_int_mode (4, QImode
));
2961 /* This is a list of MD patterns that implement fixed-count shifts. */
2967 rtx (*genfunc
)(rtx
,rtx
);
2969 const_shift_helpers
[] =
2971 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2973 CSH ("slli", 1, 1, slli_1
),
2974 CSH ("slll", 1, 1, slll_1
),
2975 CSH ("slll", 2, 1, slll_2
),
2977 CSH ("srai", 1, 0, srai_1
),
2978 CSH ("sral", 1, 0, sral_1
),
2979 CSH ("sral", 2, 0, sral_2
),
2981 CSH ("srll", 1, 0, srll_1
),
2982 CSH ("srll", 2, 1, srll_2x
),
2987 /* The MSP430 ABI defines a number of helper functions that should be
2988 used for, for example, 32-bit shifts. This function is called to
2989 emit such a function, using the table above to optimize some
2992 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2995 char *helper_const
= NULL
;
2998 machine_mode arg0mode
= GET_MODE (operands
[0]);
2999 machine_mode arg1mode
= GET_MODE (operands
[1]);
3000 machine_mode arg2mode
= GET_MODE (operands
[2]);
3001 int have_430x
= msp430x
? 1 : 0;
3003 if (CONST_INT_P (operands
[2]))
3007 for (i
=0; const_shift_helpers
[i
].name
; i
++)
3009 if (const_shift_helpers
[i
].need_430x
<= have_430x
3010 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
3011 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
3013 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
3019 if (arg1mode
== VOIDmode
)
3020 arg1mode
= arg0mode
;
3021 if (arg2mode
== VOIDmode
)
3022 arg2mode
= arg0mode
;
3024 if (arg1mode
== SImode
)
3031 && CONST_INT_P (operands
[2])
3032 && INTVAL (operands
[2]) >= 1
3033 && INTVAL (operands
[2]) <= 15)
3035 /* Note that the INTVAL is limited in value and length by the conditional above. */
3036 int len
= strlen (helper_name
) + 4;
3037 helper_const
= (char *) xmalloc (len
);
3038 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
3041 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
3044 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
3047 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
3048 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
3050 c
= emit_call_insn (c
);
3051 RTL_CONST_CALL_P (c
) = 1;
3054 use_regs (&f
, 12, arg1sz
);
3056 use_regs (&f
, arg2
, 1);
3057 add_function_usage_to (c
, f
);
3059 emit_move_insn (operands
[0],
3060 gen_rtx_REG (arg0mode
, 12));
3063 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3065 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
3067 /* constants we're looking for, not constants which are allowed. */
3068 int const_op_idx
= 1;
3070 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
3073 if (GET_CODE (operands
[const_op_idx
]) != REG
3074 && GET_CODE (operands
[const_op_idx
]) != MEM
)
3075 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3078 /* Simplify_gen_subreg() doesn't handle memory references the way we
3079 need it to below, so we use this function for when we must get a
3080 valid subreg in a "natural" state. */
3082 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3086 if (GET_CODE (r
) == SUBREG
3087 && SUBREG_BYTE (r
) == 0)
3089 rtx ireg
= SUBREG_REG (r
);
3090 machine_mode imode
= GET_MODE (ireg
);
3092 /* special case for (HI (SI (PSI ...), 0)) */
3093 if (imode
== PSImode
3096 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3098 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3100 else if (GET_CODE (r
) == MEM
)
3101 rv
= adjust_address (r
, mode
, byte
);
3102 else if (GET_CODE (r
) == SYMBOL_REF
3103 && (byte
== 0 || byte
== 2)
3106 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3107 rv
= gen_rtx_CONST (HImode
, r
);
3110 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3118 /* Called by movsi_x to generate the HImode operands. */
3120 msp430_split_movsi (rtx
*operands
)
3122 rtx op00
, op02
, op10
, op12
;
3124 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3125 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3127 if (GET_CODE (operands
[1]) == CONST
3128 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3130 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3131 op10
= gen_rtx_CONST (HImode
, op10
);
3132 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3133 op12
= gen_rtx_CONST (HImode
, op12
);
3137 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3138 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3141 if (rtx_equal_p (operands
[0], operands
[1]))
3148 else if (rtx_equal_p (op00
, op12
)
3149 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3150 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3151 /* Or storing (rN) into mem (rN). */
3152 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3170 /* The MSPABI specifies the names of various helper functions, many of
3171 which are compatible with GCC's helpers. This table maps the GCC
3172 name to the MSPABI name. */
3175 char const * const gcc_name
;
3176 char const * const ti_name
;
3178 helper_function_name_mappings
[] =
3180 /* Floating point to/from integer conversions. */
3181 { "__truncdfsf2", "__mspabi_cvtdf" },
3182 { "__extendsfdf2", "__mspabi_cvtfd" },
3183 { "__fixdfhi", "__mspabi_fixdi" },
3184 { "__fixdfsi", "__mspabi_fixdli" },
3185 { "__fixdfdi", "__mspabi_fixdlli" },
3186 { "__fixunsdfhi", "__mspabi_fixdu" },
3187 { "__fixunsdfsi", "__mspabi_fixdul" },
3188 { "__fixunsdfdi", "__mspabi_fixdull" },
3189 { "__fixsfhi", "__mspabi_fixfi" },
3190 { "__fixsfsi", "__mspabi_fixfli" },
3191 { "__fixsfdi", "__mspabi_fixflli" },
3192 { "__fixunsfhi", "__mspabi_fixfu" },
3193 { "__fixunsfsi", "__mspabi_fixful" },
3194 { "__fixunsfdi", "__mspabi_fixfull" },
3195 { "__floathisf", "__mspabi_fltif" },
3196 { "__floatsisf", "__mspabi_fltlif" },
3197 { "__floatdisf", "__mspabi_fltllif" },
3198 { "__floathidf", "__mspabi_fltid" },
3199 { "__floatsidf", "__mspabi_fltlid" },
3200 { "__floatdidf", "__mspabi_fltllid" },
3201 { "__floatunhisf", "__mspabi_fltuf" },
3202 { "__floatunsisf", "__mspabi_fltulf" },
3203 { "__floatundisf", "__mspabi_fltullf" },
3204 { "__floatunhidf", "__mspabi_fltud" },
3205 { "__floatunsidf", "__mspabi_fltuld" },
3206 { "__floatundidf", "__mspabi_fltulld" },
3208 /* Floating point comparisons. */
3209 /* GCC uses individual functions for each comparison, TI uses one
3210 compare <=> function. */
3212 /* Floating point arithmatic */
3213 { "__adddf3", "__mspabi_addd" },
3214 { "__addsf3", "__mspabi_addf" },
3215 { "__divdf3", "__mspabi_divd" },
3216 { "__divsf3", "__mspabi_divf" },
3217 { "__muldf3", "__mspabi_mpyd" },
3218 { "__mulsf3", "__mspabi_mpyf" },
3219 { "__subdf3", "__mspabi_subd" },
3220 { "__subsf3", "__mspabi_subf" },
3221 /* GCC does not use helper functions for negation */
3223 /* Integer multiply, divide, remainder. */
3224 { "__mulhi3", "__mspabi_mpyi" },
3225 { "__mulsi3", "__mspabi_mpyl" },
3226 { "__muldi3", "__mspabi_mpyll" },
3228 /* Clarify signed vs unsigned first. */
3229 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3230 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3233 { "__divhi3", "__mspabi_divi" },
3234 { "__divsi3", "__mspabi_divli" },
3235 { "__divdi3", "__mspabi_divlli" },
3236 { "__udivhi3", "__mspabi_divu" },
3237 { "__udivsi3", "__mspabi_divul" },
3238 { "__udivdi3", "__mspabi_divull" },
3239 { "__modhi3", "__mspabi_remi" },
3240 { "__modsi3", "__mspabi_remli" },
3241 { "__moddi3", "__mspabi_remlli" },
3242 { "__umodhi3", "__mspabi_remu" },
3243 { "__umodsi3", "__mspabi_remul" },
3244 { "__umoddi3", "__mspabi_remull" },
3246 /* Bitwise operations. */
3247 /* Rotation - no rotation support yet. */
3248 /* Logical left shift - gcc already does these itself. */
3249 /* Arithmetic left shift - gcc already does these itself. */
3250 /* Arithmetic right shift - gcc already does these itself. */
3255 /* Returns true if the current MCU supports an F5xxx series
3256 hardware multiper. */
3259 msp430_use_f5_series_hwmult (void)
3261 static const char * cached_match
= NULL
;
3262 static bool cached_result
;
3264 if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
3267 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3270 if (target_mcu
== cached_match
)
3271 return cached_result
;
3273 cached_match
= target_mcu
;
3275 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3276 return cached_result
= true;
3277 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3278 return cached_result
= true;
3279 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3280 return cached_result
= true;
3284 /* FIXME: This array is alpha sorted - we could use a binary search. */
3285 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3286 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3287 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3289 return cached_result
= false;
3292 /* Returns true if the current MCU has a second generation
3293 32-bit hardware multiplier. */
3296 use_32bit_hwmult (void)
3298 static const char * cached_match
= NULL
;
3299 static bool cached_result
;
3302 if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
)
3305 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3308 if (target_mcu
== cached_match
)
3309 return cached_result
;
3311 cached_match
= target_mcu
;
3313 /* FIXME: This array is alpha sorted - we could use a binary search. */
3314 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3315 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3316 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3318 return cached_result
= false;
3321 /* Returns true if the current MCU does not have a
3322 hardware multiplier of any kind. */
3325 msp430_no_hwmult (void)
3327 static const char * cached_match
= NULL
;
3328 static bool cached_result
;
3331 if (msp430_hwmult_type
== MSP430_HWMULT_NONE
)
3334 if (msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3337 if (target_mcu
== NULL
)
3340 if (target_mcu
== cached_match
)
3341 return cached_result
;
3343 cached_match
= target_mcu
;
3345 /* FIXME: This array is alpha sorted - we could use a binary search. */
3346 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3347 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3348 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3350 /* If we do not recognise the MCU name, we assume that it does not support
3351 any kind of hardware multiply - this is the safest assumption to make. */
3352 return cached_result
= true;
3355 /* This function does the same as the default, but it will replace GCC
3356 function names with the MSPABI-specified ones. */
3359 msp430_output_labelref (FILE *file
, const char *name
)
3363 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3364 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3366 name
= helper_function_name_mappings
[i
].ti_name
;
3370 /* If we have been given a specific MCU name then we may be
3371 able to make use of its hardware multiply capabilities. */
3372 if (msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
3374 if (strcmp ("__mspabi_mpyi", name
) == 0)
3376 if (msp430_use_f5_series_hwmult ())
3377 name
= "__mulhi2_f5";
3378 else if (! msp430_no_hwmult ())
3381 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3383 if (msp430_use_f5_series_hwmult ())
3384 name
= "__mulsi2_f5";
3385 else if (use_32bit_hwmult ())
3386 name
= "__mulsi2_hw32";
3387 else if (! msp430_no_hwmult ())
3395 /* Common code for msp430_print_operand... */
3398 msp430_print_operand_raw (FILE * file
, rtx op
)
3402 switch (GET_CODE (op
))
3405 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3411 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3413 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3421 output_addr_const (file
, op
);
3425 print_rtl (file
, op
);
3430 #undef TARGET_PRINT_OPERAND_ADDRESS
3431 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3433 /* Output to stdio stream FILE the assembler syntax for an
3434 instruction operand that is a memory reference whose address
3438 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3440 switch (GET_CODE (addr
))
3443 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3444 gcc_assert (REG_P (XEXP (addr
, 0)));
3445 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3449 fprintf (file
, "@");
3456 fprintf (file
, "&");
3463 msp430_print_operand_raw (file
, addr
);
3466 #undef TARGET_PRINT_OPERAND
3467 #define TARGET_PRINT_OPERAND msp430_print_operand
3469 /* A low 16-bits of int/lower of register pair
3470 B high 16-bits of int/higher of register pair
3471 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3472 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3473 H like %B (for backwards compatibility)
3475 J an integer without a # prefix
3476 L like %A (for backwards compatibility)
3477 O offset of the top of the stack
3478 Q like X but generates an A postfix
3479 R inverse of condition code, unsigned.
3480 X X instruction postfix in large mode
3483 b .B or .W or .A, depending upon the mode
3485 r inverse of condition code
3486 x like X but only for pointers. */
3489 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3493 /* We can't use c, n, a, or l. */
3497 gcc_assert (CONST_INT_P (op
));
3498 /* Print the constant value, less one. */
3499 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3502 gcc_assert (CONST_INT_P (op
));
3503 /* Print the constant value, less four. */
3504 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3507 if (GET_CODE (op
) == CONST_INT
)
3509 /* Inverse of constants */
3510 int i
= INTVAL (op
);
3511 fprintf (file
, "%d", ~i
);
3516 case 'r': /* Conditional jump where the condition is reversed. */
3517 switch (GET_CODE (op
))
3519 case EQ
: fprintf (file
, "NE"); break;
3520 case NE
: fprintf (file
, "EQ"); break;
3521 case GEU
: fprintf (file
, "LO"); break;
3522 case LTU
: fprintf (file
, "HS"); break;
3523 case GE
: fprintf (file
, "L"); break;
3524 case LT
: fprintf (file
, "GE"); break;
3525 /* Assume these have reversed operands. */
3526 case GTU
: fprintf (file
, "HS"); break;
3527 case LEU
: fprintf (file
, "LO"); break;
3528 case GT
: fprintf (file
, "GE"); break;
3529 case LE
: fprintf (file
, "L"); break;
3531 msp430_print_operand_raw (file
, op
);
3535 case 'R': /* Conditional jump where the operands are reversed. */
3536 switch (GET_CODE (op
))
3538 case GTU
: fprintf (file
, "LO"); break;
3539 case LEU
: fprintf (file
, "HS"); break;
3540 case GT
: fprintf (file
, "L"); break;
3541 case LE
: fprintf (file
, "GE"); break;
3543 msp430_print_operand_raw (file
, op
);
3547 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3548 gcc_assert (CONST_INT_P (op
));
3549 fprintf (file
, "#%d", 1 << INTVAL (op
));
3552 switch (GET_MODE (op
))
3554 case E_QImode
: fprintf (file
, ".B"); return;
3555 case E_HImode
: fprintf (file
, ".W"); return;
3556 case E_PSImode
: fprintf (file
, ".A"); return;
3557 case E_SImode
: fprintf (file
, ".A"); return;
3562 case 'L': /* Low half. */
3563 switch (GET_CODE (op
))
3566 op
= adjust_address (op
, Pmode
, 0);
3571 op
= GEN_INT (INTVAL (op
) & 0xffff);
3575 /* If you get here, figure out a test case :-) */
3580 case 'H': /* high half */
3581 switch (GET_CODE (op
))
3584 op
= adjust_address (op
, Pmode
, 2);
3587 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3590 op
= GEN_INT (INTVAL (op
) >> 16);
3594 /* If you get here, figure out a test case :-) */
3599 switch (GET_CODE (op
))
3602 op
= adjust_address (op
, Pmode
, 3);
3605 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3608 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3612 /* If you get here, figure out a test case :-) */
3617 switch (GET_CODE (op
))
3620 op
= adjust_address (op
, Pmode
, 4);
3623 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3626 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3630 /* If you get here, figure out a test case :-) */
3636 /* This is used to turn, for example, an ADD opcode into an ADDX
3637 opcode when we're using 20-bit addresses. */
3638 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3639 fprintf (file
, "X");
3640 /* We don't care which operand we use, but we want 'X' in the MD
3641 file, so we do it this way. */
3645 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3646 if (GET_MODE (op
) == PSImode
)
3647 fprintf (file
, "X");
3651 /* Likewise, for BR -> BRA. */
3653 fprintf (file
, "A");
3657 /* Computes the offset to the top of the stack for the current frame.
3658 This has to be done here rather than in, say, msp430_expand_builtin()
3659 because builtins are expanded before the frame layout is determined. */
3660 fprintf (file
, "%d",
3661 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3662 - (TARGET_LARGE
? 4 : 2));
3666 gcc_assert (GET_CODE (op
) == CONST_INT
);
3670 output_operand_lossage ("invalid operand prefix");
3674 switch (GET_CODE (op
))
3677 msp430_print_operand_raw (file
, op
);
3681 addr
= XEXP (op
, 0);
3682 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3686 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3689 switch (INTVAL (XEXP (op
, 2)))
3692 fprintf (file
, "#lo (");
3693 msp430_print_operand_raw (file
, XEXP (op
, 0));
3694 fprintf (file
, ")");
3698 fprintf (file
, "#hi (");
3699 msp430_print_operand_raw (file
, XEXP (op
, 0));
3700 fprintf (file
, ")");
3704 output_operand_lossage ("invalid zero extract");
3714 fprintf (file
, "#");
3715 msp430_print_operand_raw (file
, op
);
3718 case EQ
: fprintf (file
, "EQ"); break;
3719 case NE
: fprintf (file
, "NE"); break;
3720 case GEU
: fprintf (file
, "HS"); break;
3721 case LTU
: fprintf (file
, "LO"); break;
3722 case GE
: fprintf (file
, "GE"); break;
3723 case LT
: fprintf (file
, "L"); break;
3726 print_rtl (file
, op
);
3735 msp430_return_addr_rtx (int count
)
3741 ra_size
= TARGET_LARGE
? 4 : 2;
3742 if (crtl
->args
.pretend_args_size
)
3745 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3749 msp430_incoming_return_addr_rtx (void)
3751 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3754 /* Instruction generation stuff. */
3756 /* Generate a sequence of instructions to sign-extend an HI
3757 value into an SI value. Handles the tricky case where
3758 we are overwriting the destination. */
3761 msp430x_extendhisi (rtx
* operands
)
3763 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3764 /* Low word of dest == source word. */
3765 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3768 /* Note: This sequence is approximately the same length as invoking a helper
3769 function to perform the sign-extension, as in:
3773 CALL __mspabi_srai_15
3776 but this version does not involve any function calls or using argument
3777 registers, so it reduces register pressure. */
3778 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3780 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3781 /* High word of dest == source word. */
3782 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3784 /* No overlap between dest and source. */
3785 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3788 /* Likewise for logical right shifts. */
3790 msp430x_logical_shift_right (rtx amount
)
3792 /* The MSP430X's logical right shift instruction - RRUM - does
3793 not use an extension word, so we cannot encode a repeat count.
3794 Try various alternatives to work around this. If the count
3795 is in a register we are stuck, hence the assert. */
3796 gcc_assert (CONST_INT_P (amount
));
3798 if (INTVAL (amount
) <= 0
3799 || INTVAL (amount
) >= 16)
3800 return "# nop logical shift.";
3802 if (INTVAL (amount
) > 0
3803 && INTVAL (amount
) < 5)
3804 return "rrum.w\t%2, %0"; /* Two bytes. */
3806 if (INTVAL (amount
) > 4
3807 && INTVAL (amount
) < 9)
3808 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3810 /* First we logically shift right by one. Now we know
3811 that the top bit is zero and we can use the arithmetic
3812 right shift instruction to perform the rest of the shift. */
3813 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3816 struct gcc_target targetm
= TARGET_INITIALIZER
;
3818 #include "gt-msp430.h"