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 /* Implements MODES_TIEABLE_P. */
948 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
950 if ((mode1
== PSImode
|| mode2
== SImode
)
951 || (mode1
== SImode
|| mode2
== PSImode
))
954 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
955 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
956 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
957 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
960 #undef TARGET_FRAME_POINTER_REQUIRED
961 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
964 msp430_frame_pointer_required (void)
969 #undef TARGET_CAN_ELIMINATE
970 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
973 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
974 const int to_reg ATTRIBUTE_UNUSED
)
979 /* Implements INITIAL_ELIMINATION_OFFSET. */
981 msp430_initial_elimination_offset (int from
, int to
)
983 int rv
= 0; /* As if arg to arg. */
985 msp430_compute_frame_info ();
989 case STACK_POINTER_REGNUM
:
990 rv
+= cfun
->machine
->framesize_outgoing
;
991 rv
+= cfun
->machine
->framesize_locals
;
993 case FRAME_POINTER_REGNUM
:
994 rv
+= cfun
->machine
->framesize_regs
;
995 /* Allow for the saved return address. */
996 rv
+= (TARGET_LARGE
? 4 : 2);
997 /* NB/ No need to allow for crtl->args.pretend_args_size.
998 GCC does that for us. */
1006 case FRAME_POINTER_REGNUM
:
1007 /* Allow for the fall through above. */
1008 rv
-= (TARGET_LARGE
? 4 : 2);
1009 rv
-= cfun
->machine
->framesize_regs
;
1010 case ARG_POINTER_REGNUM
:
1019 /* Named Address Space support */
1022 /* Return the appropriate mode for a named address pointer. */
1023 #undef TARGET_ADDR_SPACE_POINTER_MODE
1024 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1025 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1026 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1028 static scalar_int_mode
1029 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1034 case ADDR_SPACE_GENERIC
:
1036 case ADDR_SPACE_NEAR
:
1038 case ADDR_SPACE_FAR
:
1043 /* Function pointers are stored in unwind_word sized
1044 variables, so make sure that unwind_word is big enough. */
1045 #undef TARGET_UNWIND_WORD_MODE
1046 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1048 static scalar_int_mode
1049 msp430_unwind_word_mode (void)
1051 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1052 return msp430x
? PSImode
: HImode
;
1055 /* Determine if one named address space is a subset of another. */
1056 #undef TARGET_ADDR_SPACE_SUBSET_P
1057 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1059 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1061 if (subset
== superset
)
1064 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1067 #undef TARGET_ADDR_SPACE_CONVERT
1068 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1069 /* Convert from one address space to another. */
1071 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1073 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1074 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1077 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1079 /* This is unpredictable, as we're truncating off usable address
1082 if (CONSTANT_P (op
))
1083 return gen_rtx_CONST (HImode
, op
);
1085 result
= gen_reg_rtx (HImode
);
1086 emit_insn (gen_truncpsihi2 (result
, op
));
1089 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1091 /* This always works. */
1093 if (CONSTANT_P (op
))
1094 return gen_rtx_CONST (PSImode
, op
);
1096 result
= gen_reg_rtx (PSImode
);
1097 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1104 /* Stack Layout and Calling Conventions. */
1106 /* For each function, we list the gcc version and the TI version on
1107 each line, where we're converting the function names. */
1108 static char const * const special_convention_function_names
[] =
1110 "__muldi3", "__mspabi_mpyll",
1111 "__udivdi3", "__mspabi_divull",
1112 "__umoddi3", "__mspabi_remull",
1113 "__divdi3", "__mspabi_divlli",
1114 "__moddi3", "__mspabi_remlli",
1118 "__adddf3", "__mspabi_addd",
1119 "__subdf3", "__mspabi_subd",
1120 "__muldf3", "__mspabi_mpyd",
1121 "__divdf3", "__mspabi_divd",
1126 /* TRUE if the function passed is a "speical" function. Special
1127 functions pass two DImode parameters in registers. */
1129 msp430_special_register_convention_p (const char *name
)
1133 for (i
= 0; special_convention_function_names
[i
]; i
++)
1134 if (! strcmp (name
, special_convention_function_names
[i
]))
1140 #undef TARGET_FUNCTION_VALUE_REGNO_P
1141 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1144 msp430_function_value_regno_p (unsigned int regno
)
1150 #undef TARGET_FUNCTION_VALUE
1151 #define TARGET_FUNCTION_VALUE msp430_function_value
1154 msp430_function_value (const_tree ret_type
,
1155 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1156 bool outgoing ATTRIBUTE_UNUSED
)
1158 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1161 #undef TARGET_LIBCALL_VALUE
1162 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1165 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1167 return gen_rtx_REG (mode
, 12);
1170 /* Implements INIT_CUMULATIVE_ARGS. */
1172 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1173 tree fntype ATTRIBUTE_UNUSED
,
1174 rtx libname ATTRIBUTE_UNUSED
,
1175 tree fndecl ATTRIBUTE_UNUSED
,
1176 int n_named_args ATTRIBUTE_UNUSED
)
1179 memset (ca
, 0, sizeof(*ca
));
1184 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1186 fname
= XSTR (libname
, 0);
1190 if (fname
&& msp430_special_register_convention_p (fname
))
1194 /* Helper function for argument passing; this function is the common
1195 code that determines where an argument will be passed. */
1197 msp430_evaluate_arg (cumulative_args_t cap
,
1199 const_tree type ATTRIBUTE_UNUSED
,
1202 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1203 int nregs
= GET_MODE_SIZE (mode
);
1212 if (mode
== PSImode
)
1215 nregs
= (nregs
+ 1) / 2;
1219 /* Function is passed two DImode operands, in R8:R11 and
1229 for (i
= 0; i
< 4; i
++)
1230 if (! ca
->reg_used
[i
])
1233 ca
->start_reg
= CA_FIRST_REG
+ i
;
1238 for (i
= 0; i
< 3; i
++)
1239 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1242 ca
->start_reg
= CA_FIRST_REG
+ i
;
1245 if (! ca
->reg_used
[3] && ca
->can_split
)
1249 ca
->start_reg
= CA_FIRST_REG
+ 3;
1256 if (! ca
->reg_used
[0]
1257 && ! ca
->reg_used
[1]
1258 && ! ca
->reg_used
[2]
1259 && ! ca
->reg_used
[3])
1262 ca
->start_reg
= CA_FIRST_REG
;
1269 #undef TARGET_PROMOTE_PROTOTYPES
1270 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1273 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1278 #undef TARGET_FUNCTION_ARG
1279 #define TARGET_FUNCTION_ARG msp430_function_arg
1282 msp430_function_arg (cumulative_args_t cap
,
1287 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1289 msp430_evaluate_arg (cap
, mode
, type
, named
);
1292 return gen_rtx_REG (mode
, ca
->start_reg
);
1297 #undef TARGET_ARG_PARTIAL_BYTES
1298 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1301 msp430_arg_partial_bytes (cumulative_args_t cap
,
1306 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1308 msp430_evaluate_arg (cap
, mode
, type
, named
);
1310 if (ca
->reg_count
&& ca
->mem_count
)
1311 return ca
->reg_count
* UNITS_PER_WORD
;
1316 #undef TARGET_PASS_BY_REFERENCE
1317 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1320 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1323 bool named ATTRIBUTE_UNUSED
)
1325 return (mode
== BLKmode
1326 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1327 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1330 #undef TARGET_CALLEE_COPIES
1331 #define TARGET_CALLEE_COPIES msp430_callee_copies
1334 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1335 machine_mode mode ATTRIBUTE_UNUSED
,
1336 const_tree type ATTRIBUTE_UNUSED
,
1337 bool named ATTRIBUTE_UNUSED
)
1342 #undef TARGET_FUNCTION_ARG_ADVANCE
1343 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1346 msp430_function_arg_advance (cumulative_args_t cap
,
1351 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1354 msp430_evaluate_arg (cap
, mode
, type
, named
);
1356 if (ca
->start_reg
>= CA_FIRST_REG
)
1357 for (i
= 0; i
< ca
->reg_count
; i
++)
1358 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1363 #undef TARGET_FUNCTION_ARG_BOUNDARY
1364 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1367 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1370 && int_size_in_bytes (type
) > 1)
1372 if (GET_MODE_BITSIZE (mode
) > 8)
1377 #undef TARGET_RETURN_IN_MEMORY
1378 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1381 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1383 machine_mode mode
= TYPE_MODE (ret_type
);
1386 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1387 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1390 if (GET_MODE_SIZE (mode
) > 8)
1396 #undef TARGET_GET_RAW_ARG_MODE
1397 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1400 msp430_get_raw_arg_mode (int regno
)
1402 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
1405 #undef TARGET_GET_RAW_RESULT_MODE
1406 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1409 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1414 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1415 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1417 #include "gimplify.h"
1420 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1423 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1424 unsigned HOST_WIDE_INT align
, boundary
;
1427 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1429 type
= build_pointer_type (type
);
1431 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1432 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1434 /* When we align parameter on stack for caller, if the parameter
1435 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1436 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1437 here with caller. */
1438 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1439 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1441 boundary
/= BITS_PER_UNIT
;
1443 /* Hoist the valist value into a temporary for the moment. */
1444 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1446 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1447 requires greater alignment, we must perform dynamic alignment. */
1448 if (boundary
> align
1449 && !integer_zerop (TYPE_SIZE (type
)))
1451 /* FIXME: This is where this function diverts from targhooks.c:
1452 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1453 if (! POINTER_TYPE_P (type
))
1455 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1456 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1457 gimplify_and_add (t
, pre_p
);
1459 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1460 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1462 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1463 gimplify_and_add (t
, pre_p
);
1469 /* If the actual alignment is less than the alignment of the type,
1470 adjust the type accordingly so that we don't assume strict alignment
1471 when dereferencing the pointer. */
1472 boundary
*= BITS_PER_UNIT
;
1473 if (boundary
< TYPE_ALIGN (type
))
1475 type
= build_variant_type_copy (type
);
1476 SET_TYPE_ALIGN (type
, boundary
);
1479 /* Compute the rounded size of the type. */
1480 type_size
= size_in_bytes (type
);
1481 rounded_size
= round_up (type_size
, align
);
1483 /* Reduce rounded_size so it's sharable with the postqueue. */
1484 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1489 /* Compute new value for AP. */
1490 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1491 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1492 gimplify_and_add (t
, pre_p
);
1494 addr
= fold_convert (build_pointer_type (type
), addr
);
1497 addr
= build_va_arg_indirect_ref (addr
);
1499 addr
= build_va_arg_indirect_ref (addr
);
1505 #define TARGET_LRA_P hook_bool_void_false
1507 /* Addressing Modes */
1509 #undef TARGET_LEGITIMATE_ADDRESS_P
1510 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1513 reg_ok_for_addr (rtx r
, bool strict
)
1517 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1518 rn
= reg_renumber
[rn
];
1519 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1527 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1528 rtx x ATTRIBUTE_UNUSED
,
1529 bool strict ATTRIBUTE_UNUSED
)
1531 switch (GET_CODE (x
))
1537 if (REG_P (XEXP (x
, 0)))
1539 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1541 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1543 switch (GET_CODE (XEXP (x
, 1)))
1556 if (!reg_ok_for_addr (x
, strict
))
1569 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1570 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1573 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1576 addr_space_t as ATTRIBUTE_UNUSED
)
1578 return msp430_legitimate_address_p (mode
, x
, strict
);
1581 #undef TARGET_ASM_INTEGER
1582 #define TARGET_ASM_INTEGER msp430_asm_integer
1584 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1586 int c
= GET_CODE (x
);
1588 if (size
== 3 && GET_MODE (x
) == PSImode
)
1594 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1595 || c
== PLUS
|| c
== MINUS
)
1597 fprintf (asm_out_file
, "\t.long\t");
1598 output_addr_const (asm_out_file
, x
);
1599 fputc ('\n', asm_out_file
);
1604 return default_assemble_integer (x
, size
, aligned_p
);
1607 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1608 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1610 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1616 #undef TARGET_LEGITIMATE_CONSTANT_P
1617 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1620 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1622 return ! CONST_INT_P (x
)
1624 /* GCC does not know the width of the PSImode, so make
1625 sure that it does not try to use a constant value that
1627 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1631 #undef TARGET_RTX_COSTS
1632 #define TARGET_RTX_COSTS msp430_rtx_costs
1634 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1636 int outer_code ATTRIBUTE_UNUSED
,
1637 int opno ATTRIBUTE_UNUSED
,
1639 bool speed ATTRIBUTE_UNUSED
)
1641 int code
= GET_CODE (x
);
1646 if (mode
== SImode
&& outer_code
== SET
)
1648 *total
= COSTS_N_INSNS (4);
1657 *total
= COSTS_N_INSNS (100);
1665 /* Function Entry and Exit */
1667 /* The MSP430 call frame looks like this:
1670 +--------------------+
1674 +--------------------+ <-- "arg pointer"
1676 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1678 +--------------------+
1679 | SR if this func has|
1680 | been called via an |
1682 +--------------------+ <-- SP before prologue, also AP
1684 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1686 +--------------------+ <-- "frame pointer"
1690 +--------------------+
1694 +--------------------+ <-- SP during function
1699 /* We use this to wrap all emitted insns in the prologue, so they get
1700 the "frame-related" (/f) flag set. */
1704 RTX_FRAME_RELATED_P (x
) = 1;
1708 /* This is the one spot that decides if a register is to be saved and
1709 restored in the prologue/epilogue. */
1711 msp430_preserve_reg_p (int regno
)
1713 /* PC, SP, SR, and the constant generator. */
1717 /* FIXME: add interrupt, EH, etc. */
1718 if (crtl
->calls_eh_return
)
1721 /* Shouldn't be more than the above, but just in case... */
1722 if (fixed_regs
[regno
])
1725 /* Interrupt handlers save all registers they use, even
1726 ones which are call saved. If they call other functions
1727 then *every* register is saved. */
1728 if (msp430_is_interrupt_func ())
1729 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1731 if (!call_used_regs
[regno
]
1732 && df_regs_ever_live_p (regno
))
1738 /* Compute all the frame-related fields in our machine_function
1741 msp430_compute_frame_info (void)
1745 cfun
->machine
->computed
= 1;
1746 cfun
->machine
->framesize_regs
= 0;
1747 cfun
->machine
->framesize_locals
= get_frame_size ();
1748 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1750 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1751 if (msp430_preserve_reg_p (i
))
1753 cfun
->machine
->need_to_save
[i
] = 1;
1754 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1757 cfun
->machine
->need_to_save
[i
] = 0;
1759 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1760 cfun
->machine
->framesize_locals
++;
1762 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1763 + cfun
->machine
->framesize_locals
1764 + cfun
->machine
->framesize_outgoing
);
1767 /* Attribute Handling. */
1769 const char * const ATTR_INTR
= "interrupt";
1770 const char * const ATTR_WAKEUP
= "wakeup";
1771 const char * const ATTR_NAKED
= "naked";
1772 const char * const ATTR_REENT
= "reentrant";
1773 const char * const ATTR_CRIT
= "critical";
1774 const char * const ATTR_LOWER
= "lower";
1775 const char * const ATTR_UPPER
= "upper";
1776 const char * const ATTR_EITHER
= "either";
1777 const char * const ATTR_NOINIT
= "noinit";
1778 const char * const ATTR_PERSIST
= "persistent";
1781 has_attr (const char * attr
, tree decl
)
1783 if (decl
== NULL_TREE
)
1785 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1789 is_interrupt_func (tree decl
= current_function_decl
)
1791 return has_attr (ATTR_INTR
, decl
);
1794 /* Returns true if the current function has the "interrupt" attribute. */
1797 msp430_is_interrupt_func (void)
1799 return is_interrupt_func (current_function_decl
);
1803 is_wakeup_func (tree decl
= current_function_decl
)
1805 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1809 is_naked_func (tree decl
= current_function_decl
)
1811 return has_attr (ATTR_NAKED
, decl
);
1815 is_reentrant_func (tree decl
= current_function_decl
)
1817 return has_attr (ATTR_REENT
, decl
);
1821 is_critical_func (tree decl
= current_function_decl
)
1823 return has_attr (ATTR_CRIT
, decl
);
1827 has_section_name (const char * name
, tree decl
= current_function_decl
)
1829 if (decl
== NULL_TREE
)
1831 return (DECL_SECTION_NAME (decl
)
1832 && (strcmp (name
, DECL_SECTION_NAME (decl
)) == 0));
1835 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1836 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1839 msp430_allocate_stack_slots_for_args (void)
1841 /* Naked functions should not allocate stack slots for arguments. */
1842 return ! is_naked_func ();
1845 /* Verify MSP430 specific attributes. */
1846 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1849 msp430_attr (tree
* node
,
1852 int flags ATTRIBUTE_UNUSED
,
1853 bool * no_add_attrs
)
1855 gcc_assert (DECL_P (* node
));
1859 /* Only the interrupt attribute takes an argument. */
1860 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1862 tree value
= TREE_VALUE (args
);
1864 switch (TREE_CODE (value
))
1867 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1868 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1869 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1870 /* Allow the attribute to be added - the linker script
1871 being used may still recognise this name. */
1872 warning (OPT_Wattributes
,
1873 "unrecognized interrupt vector argument of %qE attribute",
1878 if (wi::gtu_p (value
, 63))
1879 /* Allow the attribute to be added - the linker script
1880 being used may still recognise this value. */
1881 warning (OPT_Wattributes
,
1882 "numeric argument of %qE attribute must be in range 0..63",
1887 warning (OPT_Wattributes
,
1888 "argument of %qE attribute is not a string constant or number",
1890 *no_add_attrs
= true;
1895 const char * message
= NULL
;
1897 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1899 message
= "%qE attribute only applies to functions";
1901 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1903 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1904 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1905 message
= "interrupt handlers must be void";
1907 if (! TREE_PUBLIC (* node
))
1908 message
= "interrupt handlers cannot be static";
1910 /* Ensure interrupt handlers never get optimised out. */
1911 TREE_USED (* node
) = 1;
1912 DECL_PRESERVE_P (* node
) = 1;
1914 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1916 if (is_naked_func (* node
))
1917 message
= "naked functions cannot be reentrant";
1918 else if (is_critical_func (* node
))
1919 message
= "critical functions cannot be reentrant";
1921 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1923 if (is_naked_func (* node
))
1924 message
= "naked functions cannot be critical";
1925 else if (is_reentrant_func (* node
))
1926 message
= "reentrant functions cannot be critical";
1928 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1930 if (is_critical_func (* node
))
1931 message
= "critical functions cannot be naked";
1932 else if (is_reentrant_func (* node
))
1933 message
= "reentrant functions cannot be naked";
1938 warning (OPT_Wattributes
, message
, name
);
1939 * no_add_attrs
= true;
1946 msp430_section_attr (tree
* node
,
1949 int flags ATTRIBUTE_UNUSED
,
1950 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1952 gcc_assert (DECL_P (* node
));
1953 gcc_assert (args
== NULL
);
1955 const char * message
= NULL
;
1957 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1959 if (has_attr (ATTR_LOWER
, * node
))
1960 message
= "already marked with 'lower' attribute";
1961 else if (has_attr (ATTR_EITHER
, * node
))
1962 message
= "already marked with 'either' attribute";
1964 message
= "upper attribute needs a 430X cpu";
1966 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1968 if (has_attr (ATTR_UPPER
, * node
))
1969 message
= "already marked with 'upper' attribute";
1970 else if (has_attr (ATTR_EITHER
, * node
))
1971 message
= "already marked with 'either' attribute";
1975 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1977 if (has_attr (ATTR_LOWER
, * node
))
1978 message
= "already marked with 'lower' attribute";
1979 else if (has_attr (ATTR_UPPER
, * node
))
1980 message
= "already marked with 'upper' attribute";
1985 warning (OPT_Wattributes
, message
, name
);
1986 * no_add_attrs
= true;
1993 msp430_data_attr (tree
* node
,
1996 int flags ATTRIBUTE_UNUSED
,
1997 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1999 const char * message
= NULL
;
2001 gcc_assert (DECL_P (* node
));
2002 gcc_assert (args
== NULL
);
2004 if (TREE_CODE (* node
) != VAR_DECL
)
2005 message
= G_("%qE attribute only applies to variables");
2007 /* Check that it's possible for the variable to have a section. */
2008 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2009 && DECL_SECTION_NAME (* node
))
2010 message
= G_("%qE attribute cannot be applied to variables with specific sections");
2012 if (!message
&& TREE_NAME_EQ (name
, ATTR_PERSIST
) && !TREE_STATIC (* node
)
2013 && !TREE_PUBLIC (* node
) && !DECL_EXTERNAL (* node
))
2014 message
= G_("%qE attribute has no effect on automatic variables");
2016 /* It's not clear if there is anything that can be set here to prevent the
2017 front end placing the variable before the back end can handle it, in a
2018 similar way to how DECL_COMMON is used below.
2019 So just place the variable in the .persistent section now. */
2020 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2021 && TREE_NAME_EQ (name
, ATTR_PERSIST
))
2022 set_decl_section_name (* node
, ".persistent");
2024 /* If this var is thought to be common, then change this. Common variables
2025 are assigned to sections before the backend has a chance to process them. */
2026 if (DECL_COMMON (* node
))
2027 DECL_COMMON (* node
) = 0;
2031 warning (OPT_Wattributes
, message
, name
);
2032 * no_add_attrs
= true;
2039 #undef TARGET_ATTRIBUTE_TABLE
2040 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2042 /* Table of MSP430-specific attributes. */
2043 const struct attribute_spec msp430_attribute_table
[] =
2045 /* Name min_num_args type_req, affects_type_identity
2046 max_num_args, fn_type_req
2047 decl_req handler. */
2048 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
2049 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
2050 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
2051 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
2052 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
2054 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
2055 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
2056 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
2058 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false },
2059 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false },
2061 { NULL
, 0, 0, false, false, false, NULL
, false }
2064 #undef TARGET_ASM_FUNCTION_PROLOGUE
2065 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2068 msp430_start_function (FILE *outfile
)
2072 fprintf (outfile
, "; start of function\n");
2074 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2076 fprintf (outfile
, "; attributes: ");
2077 if (is_naked_func ())
2078 fprintf (outfile
, "naked ");
2079 if (msp430_is_interrupt_func ())
2080 fprintf (outfile
, "interrupt ");
2081 if (is_reentrant_func ())
2082 fprintf (outfile
, "reentrant ");
2083 if (is_critical_func ())
2084 fprintf (outfile
, "critical ");
2085 if (is_wakeup_func ())
2086 fprintf (outfile
, "wakeup ");
2087 fprintf (outfile
, "\n");
2090 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2091 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2092 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2093 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2094 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2095 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2098 fprintf (outfile
, "; saved regs:");
2099 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2100 if (cfun
->machine
->need_to_save
[r
])
2102 fprintf (outfile
, " %s", reg_names
[r
]);
2106 fprintf (outfile
, "(none)");
2107 fprintf (outfile
, "\n");
2110 /* Common code to change the stack pointer. */
2112 increment_stack (HOST_WIDE_INT amount
)
2115 rtx sp
= stack_pointer_rtx
;
2122 inc
= GEN_INT (- amount
);
2124 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2126 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2130 inc
= GEN_INT (amount
);
2132 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2134 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2139 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2143 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2144 if (int_attr
!= NULL_TREE
)
2146 tree intr_vector
= TREE_VALUE (int_attr
);
2148 if (intr_vector
!= NULL_TREE
)
2152 /* Interrupt vector sections should be unique, but use of weak
2153 functions implies multiple definitions. */
2154 if (DECL_WEAK (decl
))
2156 error ("argument to interrupt attribute is unsupported for weak functions");
2159 intr_vector
= TREE_VALUE (intr_vector
);
2161 /* The interrupt attribute has a vector value. Turn this into a
2162 section name, switch to that section and put the address of
2163 the current function into that vector slot. Note msp430_attr()
2164 has already verified the vector name for us. */
2165 if (TREE_CODE (intr_vector
) == STRING_CST
)
2166 sprintf (buf
, "__interrupt_vector_%.80s",
2167 TREE_STRING_POINTER (intr_vector
));
2168 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2169 sprintf (buf
, "__interrupt_vector_%u",
2170 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2172 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2173 fputs ("\t.word\t", file
);
2174 assemble_name (file
, name
);
2180 switch_to_section (function_section (decl
));
2181 ASM_OUTPUT_TYPE_DIRECTIVE(file
, name
, "function");
2182 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2185 static const char * const lower_prefix
= ".lower";
2186 static const char * const upper_prefix
= ".upper";
2187 static const char * const either_prefix
= ".either";
2189 /* Generate a prefix for a section name, based upon
2190 the region into which the object should be placed. */
2193 gen_prefix (tree decl
)
2195 if (DECL_ONE_ONLY (decl
))
2198 /* If the user has specified a particular section then do not use any prefix. */
2199 if (has_attr ("section", decl
))
2202 /* If the function has been put in the .lowtext section (because it is an
2203 interrupt handler, and the large memory model is used), then do not add
2205 if (has_section_name (".lowtext", decl
))
2208 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2209 if (has_attr (ATTR_LOWER
, decl
))
2210 return lower_prefix
;
2212 /* If we are compiling for the MSP430 then we do not support the upper region. */
2216 if (has_attr (ATTR_UPPER
, decl
))
2217 return upper_prefix
;
2219 if (has_attr (ATTR_EITHER
, decl
))
2220 return either_prefix
;
2222 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2224 if (msp430_code_region
== MSP430_REGION_LOWER
)
2225 return lower_prefix
;
2227 if (msp430_code_region
== MSP430_REGION_UPPER
)
2228 return upper_prefix
;
2230 if (msp430_code_region
== MSP430_REGION_EITHER
)
2231 return either_prefix
;
2235 if (msp430_data_region
== MSP430_REGION_LOWER
)
2236 return lower_prefix
;
2238 if (msp430_data_region
== MSP430_REGION_UPPER
)
2239 return upper_prefix
;
2241 if (msp430_data_region
== MSP430_REGION_EITHER
)
2242 return either_prefix
;
2248 static section
* noinit_section
;
2249 static section
* persist_section
;
2251 #undef TARGET_ASM_INIT_SECTIONS
2252 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2255 msp430_init_sections (void)
2257 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2258 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2261 #undef TARGET_ASM_SELECT_SECTION
2262 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2265 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2267 gcc_assert (decl
!= NULL_TREE
);
2269 if (TREE_CODE (decl
) == STRING_CST
2270 || TREE_CODE (decl
) == CONSTRUCTOR
2271 || TREE_CODE (decl
) == INTEGER_CST
2272 || TREE_CODE (decl
) == VECTOR_CST
2273 || TREE_CODE (decl
) == COMPLEX_CST
)
2274 return default_select_section (decl
, reloc
, align
);
2276 /* In large mode we must make sure that interrupt handlers are put into
2277 low memory as the vector table only accepts 16-bit addresses. */
2278 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2279 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2281 const char * prefix
= gen_prefix (decl
);
2284 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2285 return text_section
;
2286 else if (has_attr (ATTR_NOINIT
, decl
))
2287 return noinit_section
;
2288 else if (has_attr (ATTR_PERSIST
, decl
))
2289 return persist_section
;
2291 return default_select_section (decl
, reloc
, align
);
2295 switch (categorize_decl_for_section (decl
, reloc
))
2297 case SECCAT_TEXT
: sec
= ".text"; break;
2298 case SECCAT_DATA
: sec
= ".data"; break;
2299 case SECCAT_BSS
: sec
= ".bss"; break;
2300 case SECCAT_RODATA
: sec
= ".rodata"; break;
2302 case SECCAT_RODATA_MERGE_STR
:
2303 case SECCAT_RODATA_MERGE_STR_INIT
:
2304 case SECCAT_RODATA_MERGE_CONST
:
2305 case SECCAT_SRODATA
:
2306 case SECCAT_DATA_REL
:
2307 case SECCAT_DATA_REL_LOCAL
:
2308 case SECCAT_DATA_REL_RO
:
2309 case SECCAT_DATA_REL_RO_LOCAL
:
2314 return default_select_section (decl
, reloc
, align
);
2320 const char * dec_name
= DECL_SECTION_NAME (decl
);
2321 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2323 return get_named_section (decl
, name
, 0);
2326 #undef TARGET_ASM_FUNCTION_SECTION
2327 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2330 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2334 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2335 name
= DECL_SECTION_NAME (decl
);
2337 const char * prefix
= gen_prefix (decl
);
2339 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2340 return default_function_section (decl
, freq
, startup
, exit
);
2342 name
= ACONCAT ((prefix
, name
, NULL
));
2343 return get_named_section (decl
, name
, 0);
2346 #undef TARGET_SECTION_TYPE_FLAGS
2347 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2350 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2352 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2353 name
+= strlen (lower_prefix
);
2354 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2355 name
+= strlen (upper_prefix
);
2356 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2357 name
+= strlen (either_prefix
);
2358 else if (strcmp (name
, ".noinit") == 0)
2359 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2360 else if (strcmp (name
, ".persistent") == 0)
2361 return SECTION_WRITE
| SECTION_NOTYPE
;
2363 return default_section_type_flags (decl
, name
, reloc
);
2366 #undef TARGET_ASM_UNIQUE_SECTION
2367 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2370 msp430_unique_section (tree decl
, int reloc
)
2372 gcc_assert (decl
!= NULL_TREE
);
2374 /* In large mode we must make sure that interrupt handlers are put into
2375 low memory as the vector table only accepts 16-bit addresses. */
2376 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2378 set_decl_section_name (decl
, ".lowtext");
2382 default_unique_section (decl
, reloc
);
2384 const char * prefix
;
2386 if ( TREE_CODE (decl
) == STRING_CST
2387 || TREE_CODE (decl
) == CONSTRUCTOR
2388 || TREE_CODE (decl
) == INTEGER_CST
2389 || TREE_CODE (decl
) == VECTOR_CST
2390 || TREE_CODE (decl
) == COMPLEX_CST
2391 || (prefix
= gen_prefix (decl
)) == NULL
2395 const char * dec_name
= DECL_SECTION_NAME (decl
);
2396 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2398 set_decl_section_name (decl
, name
);
2401 /* Emit a declaration of a common symbol.
2402 If a data region is in use then put the symbol into the
2403 equivalent .bss section instead. */
2406 msp430_output_aligned_decl_common (FILE * stream
,
2409 unsigned HOST_WIDE_INT size
,
2412 if (msp430_data_region
== MSP430_REGION_ANY
)
2414 fprintf (stream
, COMMON_ASM_OP
);
2415 assemble_name (stream
, name
);
2416 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2417 size
, align
/ BITS_PER_UNIT
);
2424 sec
= msp430_select_section (decl
, 0, align
);
2426 switch (msp430_data_region
)
2428 case MSP430_REGION_UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2429 case MSP430_REGION_LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2430 case MSP430_REGION_EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2434 gcc_assert (sec
!= NULL
);
2436 switch_to_section (sec
);
2437 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2438 targetm
.asm_out
.globalize_label (stream
, name
);
2439 ASM_WEAKEN_LABEL (stream
, name
);
2440 ASM_OUTPUT_LABEL (stream
, name
);
2441 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2446 msp430_do_not_relax_short_jumps (void)
2448 /* When placing code into "either" low or high memory we do not want the linker
2449 to grow the size of sections, which it can do if it is encounters a branch to
2450 a label that is too far away. So we tell the cbranch patterns to avoid using
2451 short jumps when there is a chance that the instructions will end up in a low
2454 msp430_code_region
== MSP430_REGION_EITHER
2455 || msp430_code_region
== MSP430_REGION_LOWER
2456 || has_attr (ATTR_EITHER
, current_function_decl
)
2457 || has_attr (ATTR_LOWER
, current_function_decl
);
2462 MSP430_BUILTIN_BIC_SR
,
2463 MSP430_BUILTIN_BIS_SR
,
2464 MSP430_BUILTIN_DELAY_CYCLES
,
2468 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2471 msp430_init_builtins (void)
2473 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2474 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2476 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2477 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2478 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2480 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2481 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2482 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2484 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2485 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2486 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2490 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2494 case MSP430_BUILTIN_BIC_SR
:
2495 case MSP430_BUILTIN_BIS_SR
:
2496 case MSP430_BUILTIN_DELAY_CYCLES
:
2497 return msp430_builtins
[code
];
2499 return error_mark_node
;
2503 /* These constants are really register reads, which are faster than
2504 regular constants. */
2506 cg_magic_constant (HOST_WIDE_INT c
)
2524 msp430_expand_delay_cycles (rtx arg
)
2526 HOST_WIDE_INT i
, c
, n
;
2527 /* extra cycles for MSP430X instructions */
2528 #define CYCX(M,X) (msp430x ? (X) : (M))
2530 if (GET_CODE (arg
) != CONST_INT
)
2532 error ("__delay_cycles() only takes constant arguments");
2538 if (HOST_BITS_PER_WIDE_INT
> 32)
2542 error ("__delay_cycles only takes non-negative cycle counts");
2547 emit_insn (gen_delay_cycles_start (arg
));
2549 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2550 if (c
> 3 * 0xffff + CYCX (7, 10))
2553 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2554 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2557 c
-= CYCX (14, 16) + 7 * 0x10000;
2560 if ((unsigned long long) i
> 0xffffffffULL
)
2562 error ("__delay_cycles is limited to 32-bit loop counts");
2568 i
= (c
- CYCX (14, 16)) / 7;
2569 c
-= CYCX (14, 16) + i
* 7;
2572 if (cg_magic_constant (i
& 0xffff))
2574 if (cg_magic_constant ((i
>> 16) & 0xffff))
2578 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2580 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2583 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2587 i
= (c
- CYCX (7, 10)) / 3;
2588 c
-= CYCX (7, 10) + i
* 3;
2590 if (cg_magic_constant (i
))
2594 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2596 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2601 emit_insn (gen_delay_cycles_2 ());
2607 emit_insn (gen_delay_cycles_1 ());
2611 emit_insn (gen_delay_cycles_end (arg
));
2617 msp430_expand_builtin (tree exp
,
2618 rtx target ATTRIBUTE_UNUSED
,
2619 rtx subtarget ATTRIBUTE_UNUSED
,
2620 machine_mode mode ATTRIBUTE_UNUSED
,
2621 int ignore ATTRIBUTE_UNUSED
)
2623 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2624 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2625 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2627 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2628 return msp430_expand_delay_cycles (arg1
);
2630 if (! msp430_is_interrupt_func ())
2632 error ("MSP430 builtin functions only work inside interrupt handlers");
2636 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2637 arg1
= force_reg (mode
, arg1
);
2641 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2642 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2644 internal_error ("bad builtin code");
2650 #undef TARGET_INIT_BUILTINS
2651 #define TARGET_INIT_BUILTINS msp430_init_builtins
2653 #undef TARGET_EXPAND_BUILTIN
2654 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2656 #undef TARGET_BUILTIN_DECL
2657 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2660 msp430_expand_prologue (void)
2664 /* Always use stack_pointer_rtx instead of calling
2665 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2666 that there is a single rtx representing the stack pointer,
2667 namely stack_pointer_rtx, and uses == to recognize it. */
2668 rtx sp
= stack_pointer_rtx
;
2671 if (is_naked_func ())
2673 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2674 examines the output of the gen_prologue() function. */
2675 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2679 emit_insn (gen_prologue_start_marker ());
2681 if (is_critical_func ())
2683 emit_insn (gen_push_intr_state ());
2684 emit_insn (gen_disable_interrupts ());
2686 else if (is_reentrant_func ())
2687 emit_insn (gen_disable_interrupts ());
2689 if (!cfun
->machine
->computed
)
2690 msp430_compute_frame_info ();
2692 if (flag_stack_usage_info
)
2693 current_function_static_stack_size
= cfun
->machine
->framesize
;
2695 if (crtl
->args
.pretend_args_size
)
2699 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2701 p
= emit_insn (gen_grow_and_swap ());
2703 /* Document the stack decrement... */
2704 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2705 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2706 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2708 /* ...and the establishment of a new location for the return address. */
2709 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2710 gen_rtx_PLUS (Pmode
,
2714 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2718 for (i
= 15; i
>= 4; i
--)
2719 if (cfun
->machine
->need_to_save
[i
])
2724 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2730 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2731 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2734 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2736 XVECEXP (note
, 0, 0)
2737 = F (gen_rtx_SET (stack_pointer_rtx
,
2738 gen_rtx_PLUS (Pmode
,
2740 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2742 /* *sp-- = R[i-j] */
2746 for (j
= 0; j
< count
; j
++)
2749 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2752 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2754 addr
= stack_pointer_rtx
;
2756 XVECEXP (note
, 0, j
+ 1) =
2757 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2758 gen_rtx_REG (Pmode
, i
- j
)) );
2761 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2765 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2768 if (frame_pointer_needed
)
2769 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2771 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2773 increment_stack (- fs
);
2775 emit_insn (gen_prologue_end_marker ());
2779 msp430_expand_epilogue (int is_eh
)
2785 if (is_naked_func ())
2787 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2788 examines the output of the gen_epilogue() function. */
2789 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2793 if (cfun
->machine
->need_to_save
[10])
2795 /* Check for a helper function. */
2796 helper_n
= 7; /* For when the loop below never sees a match. */
2797 for (i
= 9; i
>= 4; i
--)
2798 if (!cfun
->machine
->need_to_save
[i
])
2802 if (cfun
->machine
->need_to_save
[i
])
2811 emit_insn (gen_epilogue_start_marker ());
2813 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2814 emit_insn (gen_msp430_refsym_need_exit ());
2816 if (is_wakeup_func ())
2817 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2818 status register current residing on the stack. When this function
2819 executes its RETI instruction the SR will be updated with this saved
2820 value, thus ensuring that the processor is woken up from any low power
2821 state in which it may be residing. */
2822 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2824 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2826 increment_stack (fs
);
2830 /* We need to add the right "SP" register save just after the
2831 regular ones, so that when we pop it off we're in the EH
2832 return frame, not this one. This overwrites our own return
2833 address, but we're not going to be returning anyway. */
2834 rtx r12
= gen_rtx_REG (Pmode
, 12);
2835 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2837 /* R12 will hold the new SP. */
2838 i
= cfun
->machine
->framesize_regs
;
2839 emit_move_insn (r12
, stack_pointer_rtx
);
2840 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2841 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2842 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2845 for (i
= 4; i
<= 15; i
++)
2846 if (cfun
->machine
->need_to_save
[i
])
2850 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2856 /* Note: With TARGET_LARGE we still use
2857 POPM as POPX.A is two bytes bigger. */
2858 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2862 else if (i
== 11 - helper_n
2863 && ! msp430_is_interrupt_func ()
2864 && ! is_reentrant_func ()
2865 && ! is_critical_func ()
2866 && crtl
->args
.pretend_args_size
== 0
2867 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2871 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2875 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2880 /* Also pop SP, which puts us into the EH return frame. Except
2881 that you can't "pop" sp, you have to just load it off the
2883 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2886 if (crtl
->args
.pretend_args_size
)
2887 emit_insn (gen_swap_and_shrink ());
2889 if (is_critical_func ())
2890 emit_insn (gen_pop_intr_state ());
2891 else if (is_reentrant_func ())
2892 emit_insn (gen_enable_interrupts ());
2894 emit_jump_insn (gen_msp_return ());
2897 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2898 m32c_emit_eh_epilogue. */
2900 msp430_eh_return_stackadj_rtx (void)
2902 if (!cfun
->machine
->eh_stack_adjust
)
2906 sa
= gen_rtx_REG (Pmode
, 15);
2907 cfun
->machine
->eh_stack_adjust
= sa
;
2909 return cfun
->machine
->eh_stack_adjust
;
2912 /* This function is called before reload, to "fix" the stack in
2913 preparation for an EH return. */
2915 msp430_expand_eh_return (rtx eh_handler
)
2917 /* These are all Pmode */
2918 rtx ap
, sa
, ra
, tmp
;
2920 ap
= arg_pointer_rtx
;
2921 sa
= msp430_eh_return_stackadj_rtx ();
2925 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2926 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2927 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2928 emit_move_insn (tmp
, ra
);
2931 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2932 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2934 msp430_init_dwarf_reg_sizes_extra (tree address
)
2937 rtx addr
= expand_normal (address
);
2938 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2940 /* This needs to match msp430_unwind_word_mode (above). */
2944 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2946 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2947 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2949 if (rnum
< DWARF_FRAME_REGISTERS
)
2951 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2953 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2954 gen_int_mode (4, QImode
));
2959 /* This is a list of MD patterns that implement fixed-count shifts. */
2965 rtx (*genfunc
)(rtx
,rtx
);
2967 const_shift_helpers
[] =
2969 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2971 CSH ("slli", 1, 1, slli_1
),
2972 CSH ("slll", 1, 1, slll_1
),
2973 CSH ("slll", 2, 1, slll_2
),
2975 CSH ("srai", 1, 0, srai_1
),
2976 CSH ("sral", 1, 0, sral_1
),
2977 CSH ("sral", 2, 0, sral_2
),
2979 CSH ("srll", 1, 0, srll_1
),
2980 CSH ("srll", 2, 1, srll_2x
),
2985 /* The MSP430 ABI defines a number of helper functions that should be
2986 used for, for example, 32-bit shifts. This function is called to
2987 emit such a function, using the table above to optimize some
2990 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2993 char *helper_const
= NULL
;
2996 machine_mode arg0mode
= GET_MODE (operands
[0]);
2997 machine_mode arg1mode
= GET_MODE (operands
[1]);
2998 machine_mode arg2mode
= GET_MODE (operands
[2]);
2999 int have_430x
= msp430x
? 1 : 0;
3001 if (CONST_INT_P (operands
[2]))
3005 for (i
=0; const_shift_helpers
[i
].name
; i
++)
3007 if (const_shift_helpers
[i
].need_430x
<= have_430x
3008 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
3009 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
3011 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
3017 if (arg1mode
== VOIDmode
)
3018 arg1mode
= arg0mode
;
3019 if (arg2mode
== VOIDmode
)
3020 arg2mode
= arg0mode
;
3022 if (arg1mode
== SImode
)
3029 && CONST_INT_P (operands
[2])
3030 && INTVAL (operands
[2]) >= 1
3031 && INTVAL (operands
[2]) <= 15)
3033 /* Note that the INTVAL is limited in value and length by the conditional above. */
3034 int len
= strlen (helper_name
) + 4;
3035 helper_const
= (char *) xmalloc (len
);
3036 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
3039 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
3042 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
3045 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
3046 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
3048 c
= emit_call_insn (c
);
3049 RTL_CONST_CALL_P (c
) = 1;
3052 use_regs (&f
, 12, arg1sz
);
3054 use_regs (&f
, arg2
, 1);
3055 add_function_usage_to (c
, f
);
3057 emit_move_insn (operands
[0],
3058 gen_rtx_REG (arg0mode
, 12));
3061 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3063 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
3065 /* constants we're looking for, not constants which are allowed. */
3066 int const_op_idx
= 1;
3068 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
3071 if (GET_CODE (operands
[const_op_idx
]) != REG
3072 && GET_CODE (operands
[const_op_idx
]) != MEM
)
3073 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3076 /* Simplify_gen_subreg() doesn't handle memory references the way we
3077 need it to below, so we use this function for when we must get a
3078 valid subreg in a "natural" state. */
3080 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3084 if (GET_CODE (r
) == SUBREG
3085 && SUBREG_BYTE (r
) == 0)
3087 rtx ireg
= SUBREG_REG (r
);
3088 machine_mode imode
= GET_MODE (ireg
);
3090 /* special case for (HI (SI (PSI ...), 0)) */
3091 if (imode
== PSImode
3094 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3096 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3098 else if (GET_CODE (r
) == MEM
)
3099 rv
= adjust_address (r
, mode
, byte
);
3100 else if (GET_CODE (r
) == SYMBOL_REF
3101 && (byte
== 0 || byte
== 2)
3104 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3105 rv
= gen_rtx_CONST (HImode
, r
);
3108 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3116 /* Called by movsi_x to generate the HImode operands. */
3118 msp430_split_movsi (rtx
*operands
)
3120 rtx op00
, op02
, op10
, op12
;
3122 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3123 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3125 if (GET_CODE (operands
[1]) == CONST
3126 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3128 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3129 op10
= gen_rtx_CONST (HImode
, op10
);
3130 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3131 op12
= gen_rtx_CONST (HImode
, op12
);
3135 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3136 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3139 if (rtx_equal_p (operands
[0], operands
[1]))
3146 else if (rtx_equal_p (op00
, op12
)
3147 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3148 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3149 /* Or storing (rN) into mem (rN). */
3150 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3168 /* The MSPABI specifies the names of various helper functions, many of
3169 which are compatible with GCC's helpers. This table maps the GCC
3170 name to the MSPABI name. */
3173 char const * const gcc_name
;
3174 char const * const ti_name
;
3176 helper_function_name_mappings
[] =
3178 /* Floating point to/from integer conversions. */
3179 { "__truncdfsf2", "__mspabi_cvtdf" },
3180 { "__extendsfdf2", "__mspabi_cvtfd" },
3181 { "__fixdfhi", "__mspabi_fixdi" },
3182 { "__fixdfsi", "__mspabi_fixdli" },
3183 { "__fixdfdi", "__mspabi_fixdlli" },
3184 { "__fixunsdfhi", "__mspabi_fixdu" },
3185 { "__fixunsdfsi", "__mspabi_fixdul" },
3186 { "__fixunsdfdi", "__mspabi_fixdull" },
3187 { "__fixsfhi", "__mspabi_fixfi" },
3188 { "__fixsfsi", "__mspabi_fixfli" },
3189 { "__fixsfdi", "__mspabi_fixflli" },
3190 { "__fixunsfhi", "__mspabi_fixfu" },
3191 { "__fixunsfsi", "__mspabi_fixful" },
3192 { "__fixunsfdi", "__mspabi_fixfull" },
3193 { "__floathisf", "__mspabi_fltif" },
3194 { "__floatsisf", "__mspabi_fltlif" },
3195 { "__floatdisf", "__mspabi_fltllif" },
3196 { "__floathidf", "__mspabi_fltid" },
3197 { "__floatsidf", "__mspabi_fltlid" },
3198 { "__floatdidf", "__mspabi_fltllid" },
3199 { "__floatunhisf", "__mspabi_fltuf" },
3200 { "__floatunsisf", "__mspabi_fltulf" },
3201 { "__floatundisf", "__mspabi_fltullf" },
3202 { "__floatunhidf", "__mspabi_fltud" },
3203 { "__floatunsidf", "__mspabi_fltuld" },
3204 { "__floatundidf", "__mspabi_fltulld" },
3206 /* Floating point comparisons. */
3207 /* GCC uses individual functions for each comparison, TI uses one
3208 compare <=> function. */
3210 /* Floating point arithmatic */
3211 { "__adddf3", "__mspabi_addd" },
3212 { "__addsf3", "__mspabi_addf" },
3213 { "__divdf3", "__mspabi_divd" },
3214 { "__divsf3", "__mspabi_divf" },
3215 { "__muldf3", "__mspabi_mpyd" },
3216 { "__mulsf3", "__mspabi_mpyf" },
3217 { "__subdf3", "__mspabi_subd" },
3218 { "__subsf3", "__mspabi_subf" },
3219 /* GCC does not use helper functions for negation */
3221 /* Integer multiply, divide, remainder. */
3222 { "__mulhi3", "__mspabi_mpyi" },
3223 { "__mulsi3", "__mspabi_mpyl" },
3224 { "__muldi3", "__mspabi_mpyll" },
3226 /* Clarify signed vs unsigned first. */
3227 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3228 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3231 { "__divhi3", "__mspabi_divi" },
3232 { "__divsi3", "__mspabi_divli" },
3233 { "__divdi3", "__mspabi_divlli" },
3234 { "__udivhi3", "__mspabi_divu" },
3235 { "__udivsi3", "__mspabi_divul" },
3236 { "__udivdi3", "__mspabi_divull" },
3237 { "__modhi3", "__mspabi_remi" },
3238 { "__modsi3", "__mspabi_remli" },
3239 { "__moddi3", "__mspabi_remlli" },
3240 { "__umodhi3", "__mspabi_remu" },
3241 { "__umodsi3", "__mspabi_remul" },
3242 { "__umoddi3", "__mspabi_remull" },
3244 /* Bitwise operations. */
3245 /* Rotation - no rotation support yet. */
3246 /* Logical left shift - gcc already does these itself. */
3247 /* Arithmetic left shift - gcc already does these itself. */
3248 /* Arithmetic right shift - gcc already does these itself. */
3253 /* Returns true if the current MCU supports an F5xxx series
3254 hardware multiper. */
3257 msp430_use_f5_series_hwmult (void)
3259 static const char * cached_match
= NULL
;
3260 static bool cached_result
;
3262 if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
3265 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3268 if (target_mcu
== cached_match
)
3269 return cached_result
;
3271 cached_match
= target_mcu
;
3273 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3274 return cached_result
= true;
3275 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3276 return cached_result
= true;
3277 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3278 return cached_result
= true;
3282 /* FIXME: This array is alpha sorted - we could use a binary search. */
3283 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3284 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3285 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3287 return cached_result
= false;
3290 /* Returns true if the current MCU has a second generation
3291 32-bit hardware multiplier. */
3294 use_32bit_hwmult (void)
3296 static const char * cached_match
= NULL
;
3297 static bool cached_result
;
3300 if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
)
3303 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3306 if (target_mcu
== cached_match
)
3307 return cached_result
;
3309 cached_match
= target_mcu
;
3311 /* FIXME: This array is alpha sorted - we could use a binary search. */
3312 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3313 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3314 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3316 return cached_result
= false;
3319 /* Returns true if the current MCU does not have a
3320 hardware multiplier of any kind. */
3323 msp430_no_hwmult (void)
3325 static const char * cached_match
= NULL
;
3326 static bool cached_result
;
3329 if (msp430_hwmult_type
== MSP430_HWMULT_NONE
)
3332 if (msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3335 if (target_mcu
== NULL
)
3338 if (target_mcu
== cached_match
)
3339 return cached_result
;
3341 cached_match
= target_mcu
;
3343 /* FIXME: This array is alpha sorted - we could use a binary search. */
3344 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3345 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3346 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3348 /* If we do not recognise the MCU name, we assume that it does not support
3349 any kind of hardware multiply - this is the safest assumption to make. */
3350 return cached_result
= true;
3353 /* This function does the same as the default, but it will replace GCC
3354 function names with the MSPABI-specified ones. */
3357 msp430_output_labelref (FILE *file
, const char *name
)
3361 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3362 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3364 name
= helper_function_name_mappings
[i
].ti_name
;
3368 /* If we have been given a specific MCU name then we may be
3369 able to make use of its hardware multiply capabilities. */
3370 if (msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
3372 if (strcmp ("__mspabi_mpyi", name
) == 0)
3374 if (msp430_use_f5_series_hwmult ())
3375 name
= "__mulhi2_f5";
3376 else if (! msp430_no_hwmult ())
3379 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3381 if (msp430_use_f5_series_hwmult ())
3382 name
= "__mulsi2_f5";
3383 else if (use_32bit_hwmult ())
3384 name
= "__mulsi2_hw32";
3385 else if (! msp430_no_hwmult ())
3393 /* Common code for msp430_print_operand... */
3396 msp430_print_operand_raw (FILE * file
, rtx op
)
3400 switch (GET_CODE (op
))
3403 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3409 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3411 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3419 output_addr_const (file
, op
);
3423 print_rtl (file
, op
);
3428 #undef TARGET_PRINT_OPERAND_ADDRESS
3429 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3431 /* Output to stdio stream FILE the assembler syntax for an
3432 instruction operand that is a memory reference whose address
3436 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3438 switch (GET_CODE (addr
))
3441 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3442 gcc_assert (REG_P (XEXP (addr
, 0)));
3443 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3447 fprintf (file
, "@");
3454 fprintf (file
, "&");
3461 msp430_print_operand_raw (file
, addr
);
3464 #undef TARGET_PRINT_OPERAND
3465 #define TARGET_PRINT_OPERAND msp430_print_operand
3467 /* A low 16-bits of int/lower of register pair
3468 B high 16-bits of int/higher of register pair
3469 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3470 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3471 H like %B (for backwards compatibility)
3473 J an integer without a # prefix
3474 L like %A (for backwards compatibility)
3475 O offset of the top of the stack
3476 Q like X but generates an A postfix
3477 R inverse of condition code, unsigned.
3478 X X instruction postfix in large mode
3481 b .B or .W or .A, depending upon the mode
3483 r inverse of condition code
3484 x like X but only for pointers. */
3487 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3491 /* We can't use c, n, a, or l. */
3495 gcc_assert (CONST_INT_P (op
));
3496 /* Print the constant value, less one. */
3497 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3500 gcc_assert (CONST_INT_P (op
));
3501 /* Print the constant value, less four. */
3502 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3505 if (GET_CODE (op
) == CONST_INT
)
3507 /* Inverse of constants */
3508 int i
= INTVAL (op
);
3509 fprintf (file
, "%d", ~i
);
3514 case 'r': /* Conditional jump where the condition is reversed. */
3515 switch (GET_CODE (op
))
3517 case EQ
: fprintf (file
, "NE"); break;
3518 case NE
: fprintf (file
, "EQ"); break;
3519 case GEU
: fprintf (file
, "LO"); break;
3520 case LTU
: fprintf (file
, "HS"); break;
3521 case GE
: fprintf (file
, "L"); break;
3522 case LT
: fprintf (file
, "GE"); break;
3523 /* Assume these have reversed operands. */
3524 case GTU
: fprintf (file
, "HS"); break;
3525 case LEU
: fprintf (file
, "LO"); break;
3526 case GT
: fprintf (file
, "GE"); break;
3527 case LE
: fprintf (file
, "L"); break;
3529 msp430_print_operand_raw (file
, op
);
3533 case 'R': /* Conditional jump where the operands are reversed. */
3534 switch (GET_CODE (op
))
3536 case GTU
: fprintf (file
, "LO"); break;
3537 case LEU
: fprintf (file
, "HS"); break;
3538 case GT
: fprintf (file
, "L"); break;
3539 case LE
: fprintf (file
, "GE"); break;
3541 msp430_print_operand_raw (file
, op
);
3545 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3546 gcc_assert (CONST_INT_P (op
));
3547 fprintf (file
, "#%d", 1 << INTVAL (op
));
3550 switch (GET_MODE (op
))
3552 case E_QImode
: fprintf (file
, ".B"); return;
3553 case E_HImode
: fprintf (file
, ".W"); return;
3554 case E_PSImode
: fprintf (file
, ".A"); return;
3555 case E_SImode
: fprintf (file
, ".A"); return;
3560 case 'L': /* Low half. */
3561 switch (GET_CODE (op
))
3564 op
= adjust_address (op
, Pmode
, 0);
3569 op
= GEN_INT (INTVAL (op
) & 0xffff);
3573 /* If you get here, figure out a test case :-) */
3578 case 'H': /* high half */
3579 switch (GET_CODE (op
))
3582 op
= adjust_address (op
, Pmode
, 2);
3585 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3588 op
= GEN_INT (INTVAL (op
) >> 16);
3592 /* If you get here, figure out a test case :-) */
3597 switch (GET_CODE (op
))
3600 op
= adjust_address (op
, Pmode
, 3);
3603 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3606 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3610 /* If you get here, figure out a test case :-) */
3615 switch (GET_CODE (op
))
3618 op
= adjust_address (op
, Pmode
, 4);
3621 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3624 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3628 /* If you get here, figure out a test case :-) */
3634 /* This is used to turn, for example, an ADD opcode into an ADDX
3635 opcode when we're using 20-bit addresses. */
3636 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3637 fprintf (file
, "X");
3638 /* We don't care which operand we use, but we want 'X' in the MD
3639 file, so we do it this way. */
3643 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3644 if (GET_MODE (op
) == PSImode
)
3645 fprintf (file
, "X");
3649 /* Likewise, for BR -> BRA. */
3651 fprintf (file
, "A");
3655 /* Computes the offset to the top of the stack for the current frame.
3656 This has to be done here rather than in, say, msp430_expand_builtin()
3657 because builtins are expanded before the frame layout is determined. */
3658 fprintf (file
, "%d",
3659 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3660 - (TARGET_LARGE
? 4 : 2));
3664 gcc_assert (GET_CODE (op
) == CONST_INT
);
3668 output_operand_lossage ("invalid operand prefix");
3672 switch (GET_CODE (op
))
3675 msp430_print_operand_raw (file
, op
);
3679 addr
= XEXP (op
, 0);
3680 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3684 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3687 switch (INTVAL (XEXP (op
, 2)))
3690 fprintf (file
, "#lo (");
3691 msp430_print_operand_raw (file
, XEXP (op
, 0));
3692 fprintf (file
, ")");
3696 fprintf (file
, "#hi (");
3697 msp430_print_operand_raw (file
, XEXP (op
, 0));
3698 fprintf (file
, ")");
3702 output_operand_lossage ("invalid zero extract");
3712 fprintf (file
, "#");
3713 msp430_print_operand_raw (file
, op
);
3716 case EQ
: fprintf (file
, "EQ"); break;
3717 case NE
: fprintf (file
, "NE"); break;
3718 case GEU
: fprintf (file
, "HS"); break;
3719 case LTU
: fprintf (file
, "LO"); break;
3720 case GE
: fprintf (file
, "GE"); break;
3721 case LT
: fprintf (file
, "L"); break;
3724 print_rtl (file
, op
);
3733 msp430_return_addr_rtx (int count
)
3739 ra_size
= TARGET_LARGE
? 4 : 2;
3740 if (crtl
->args
.pretend_args_size
)
3743 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3747 msp430_incoming_return_addr_rtx (void)
3749 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3752 /* Instruction generation stuff. */
3754 /* Generate a sequence of instructions to sign-extend an HI
3755 value into an SI value. Handles the tricky case where
3756 we are overwriting the destination. */
3759 msp430x_extendhisi (rtx
* operands
)
3761 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3762 /* Low word of dest == source word. */
3763 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3766 /* Note: This sequence is approximately the same length as invoking a helper
3767 function to perform the sign-extension, as in:
3771 CALL __mspabi_srai_15
3774 but this version does not involve any function calls or using argument
3775 registers, so it reduces register pressure. */
3776 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3778 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3779 /* High word of dest == source word. */
3780 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3782 /* No overlap between dest and source. */
3783 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3786 /* Likewise for logical right shifts. */
3788 msp430x_logical_shift_right (rtx amount
)
3790 /* The MSP430X's logical right shift instruction - RRUM - does
3791 not use an extension word, so we cannot encode a repeat count.
3792 Try various alternatives to work around this. If the count
3793 is in a register we are stuck, hence the assert. */
3794 gcc_assert (CONST_INT_P (amount
));
3796 if (INTVAL (amount
) <= 0
3797 || INTVAL (amount
) >= 16)
3798 return "# nop logical shift.";
3800 if (INTVAL (amount
) > 0
3801 && INTVAL (amount
) < 5)
3802 return "rrum.w\t%2, %0"; /* Two bytes. */
3804 if (INTVAL (amount
) > 4
3805 && INTVAL (amount
) < 9)
3806 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3808 /* First we logically shift right by one. Now we know
3809 that the top bit is zero and we can use the arithmetic
3810 right shift instruction to perform the rest of the shift. */
3811 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3814 struct gcc_target targetm
= TARGET_INITIALIZER
;
3816 #include "gt-msp430.h"