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 (machine_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 /* Implements HARD_REGNO_MODE_OK. */
938 msp430_hard_regno_mode_ok (int regno ATTRIBUTE_UNUSED
,
941 return regno
<= (ARG_POINTER_REGNUM
- msp430_hard_regno_nregs (regno
, mode
));
944 /* Implements MODES_TIEABLE_P. */
946 msp430_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
948 if ((mode1
== PSImode
|| mode2
== SImode
)
949 || (mode1
== SImode
|| mode2
== PSImode
))
952 return ((GET_MODE_CLASS (mode1
) == MODE_FLOAT
953 || GET_MODE_CLASS (mode1
) == MODE_COMPLEX_FLOAT
)
954 == (GET_MODE_CLASS (mode2
) == MODE_FLOAT
955 || GET_MODE_CLASS (mode2
) == MODE_COMPLEX_FLOAT
));
958 #undef TARGET_FRAME_POINTER_REQUIRED
959 #define TARGET_FRAME_POINTER_REQUIRED msp430_frame_pointer_required
962 msp430_frame_pointer_required (void)
967 #undef TARGET_CAN_ELIMINATE
968 #define TARGET_CAN_ELIMINATE msp430_can_eliminate
971 msp430_can_eliminate (const int from_reg ATTRIBUTE_UNUSED
,
972 const int to_reg ATTRIBUTE_UNUSED
)
977 /* Implements INITIAL_ELIMINATION_OFFSET. */
979 msp430_initial_elimination_offset (int from
, int to
)
981 int rv
= 0; /* As if arg to arg. */
983 msp430_compute_frame_info ();
987 case STACK_POINTER_REGNUM
:
988 rv
+= cfun
->machine
->framesize_outgoing
;
989 rv
+= cfun
->machine
->framesize_locals
;
991 case FRAME_POINTER_REGNUM
:
992 rv
+= cfun
->machine
->framesize_regs
;
993 /* Allow for the saved return address. */
994 rv
+= (TARGET_LARGE
? 4 : 2);
995 /* NB/ No need to allow for crtl->args.pretend_args_size.
996 GCC does that for us. */
1004 case FRAME_POINTER_REGNUM
:
1005 /* Allow for the fall through above. */
1006 rv
-= (TARGET_LARGE
? 4 : 2);
1007 rv
-= cfun
->machine
->framesize_regs
;
1008 case ARG_POINTER_REGNUM
:
1017 /* Named Address Space support */
1020 /* Return the appropriate mode for a named address pointer. */
1021 #undef TARGET_ADDR_SPACE_POINTER_MODE
1022 #define TARGET_ADDR_SPACE_POINTER_MODE msp430_addr_space_pointer_mode
1023 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
1024 #define TARGET_ADDR_SPACE_ADDRESS_MODE msp430_addr_space_pointer_mode
1026 static scalar_int_mode
1027 msp430_addr_space_pointer_mode (addr_space_t addrspace
)
1032 case ADDR_SPACE_GENERIC
:
1034 case ADDR_SPACE_NEAR
:
1036 case ADDR_SPACE_FAR
:
1041 /* Function pointers are stored in unwind_word sized
1042 variables, so make sure that unwind_word is big enough. */
1043 #undef TARGET_UNWIND_WORD_MODE
1044 #define TARGET_UNWIND_WORD_MODE msp430_unwind_word_mode
1046 static scalar_int_mode
1047 msp430_unwind_word_mode (void)
1049 /* This needs to match msp430_init_dwarf_reg_sizes_extra (below). */
1050 return msp430x
? PSImode
: HImode
;
1053 /* Determine if one named address space is a subset of another. */
1054 #undef TARGET_ADDR_SPACE_SUBSET_P
1055 #define TARGET_ADDR_SPACE_SUBSET_P msp430_addr_space_subset_p
1057 msp430_addr_space_subset_p (addr_space_t subset
, addr_space_t superset
)
1059 if (subset
== superset
)
1062 return (subset
!= ADDR_SPACE_FAR
&& superset
== ADDR_SPACE_FAR
);
1065 #undef TARGET_ADDR_SPACE_CONVERT
1066 #define TARGET_ADDR_SPACE_CONVERT msp430_addr_space_convert
1067 /* Convert from one address space to another. */
1069 msp430_addr_space_convert (rtx op
, tree from_type
, tree to_type
)
1071 addr_space_t from_as
= TYPE_ADDR_SPACE (TREE_TYPE (from_type
));
1072 addr_space_t to_as
= TYPE_ADDR_SPACE (TREE_TYPE (to_type
));
1075 if (to_as
!= ADDR_SPACE_FAR
&& from_as
== ADDR_SPACE_FAR
)
1077 /* This is unpredictable, as we're truncating off usable address
1080 if (CONSTANT_P (op
))
1081 return gen_rtx_CONST (HImode
, op
);
1083 result
= gen_reg_rtx (HImode
);
1084 emit_insn (gen_truncpsihi2 (result
, op
));
1087 else if (to_as
== ADDR_SPACE_FAR
&& from_as
!= ADDR_SPACE_FAR
)
1089 /* This always works. */
1091 if (CONSTANT_P (op
))
1092 return gen_rtx_CONST (PSImode
, op
);
1094 result
= gen_reg_rtx (PSImode
);
1095 emit_insn (gen_zero_extendhipsi2 (result
, op
));
1102 /* Stack Layout and Calling Conventions. */
1104 /* For each function, we list the gcc version and the TI version on
1105 each line, where we're converting the function names. */
1106 static char const * const special_convention_function_names
[] =
1108 "__muldi3", "__mspabi_mpyll",
1109 "__udivdi3", "__mspabi_divull",
1110 "__umoddi3", "__mspabi_remull",
1111 "__divdi3", "__mspabi_divlli",
1112 "__moddi3", "__mspabi_remlli",
1116 "__adddf3", "__mspabi_addd",
1117 "__subdf3", "__mspabi_subd",
1118 "__muldf3", "__mspabi_mpyd",
1119 "__divdf3", "__mspabi_divd",
1124 /* TRUE if the function passed is a "speical" function. Special
1125 functions pass two DImode parameters in registers. */
1127 msp430_special_register_convention_p (const char *name
)
1131 for (i
= 0; special_convention_function_names
[i
]; i
++)
1132 if (! strcmp (name
, special_convention_function_names
[i
]))
1138 #undef TARGET_FUNCTION_VALUE_REGNO_P
1139 #define TARGET_FUNCTION_VALUE_REGNO_P msp430_function_value_regno_p
1142 msp430_function_value_regno_p (unsigned int regno
)
1148 #undef TARGET_FUNCTION_VALUE
1149 #define TARGET_FUNCTION_VALUE msp430_function_value
1152 msp430_function_value (const_tree ret_type
,
1153 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1154 bool outgoing ATTRIBUTE_UNUSED
)
1156 return gen_rtx_REG (TYPE_MODE (ret_type
), 12);
1159 #undef TARGET_LIBCALL_VALUE
1160 #define TARGET_LIBCALL_VALUE msp430_libcall_value
1163 msp430_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1165 return gen_rtx_REG (mode
, 12);
1168 /* Implements INIT_CUMULATIVE_ARGS. */
1170 msp430_init_cumulative_args (CUMULATIVE_ARGS
*ca
,
1171 tree fntype ATTRIBUTE_UNUSED
,
1172 rtx libname ATTRIBUTE_UNUSED
,
1173 tree fndecl ATTRIBUTE_UNUSED
,
1174 int n_named_args ATTRIBUTE_UNUSED
)
1177 memset (ca
, 0, sizeof(*ca
));
1182 fname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
1184 fname
= XSTR (libname
, 0);
1188 if (fname
&& msp430_special_register_convention_p (fname
))
1192 /* Helper function for argument passing; this function is the common
1193 code that determines where an argument will be passed. */
1195 msp430_evaluate_arg (cumulative_args_t cap
,
1197 const_tree type ATTRIBUTE_UNUSED
,
1200 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1201 int nregs
= GET_MODE_SIZE (mode
);
1210 if (mode
== PSImode
)
1213 nregs
= (nregs
+ 1) / 2;
1217 /* Function is passed two DImode operands, in R8:R11 and
1227 for (i
= 0; i
< 4; i
++)
1228 if (! ca
->reg_used
[i
])
1231 ca
->start_reg
= CA_FIRST_REG
+ i
;
1236 for (i
= 0; i
< 3; i
++)
1237 if (! ca
->reg_used
[i
] && ! ca
->reg_used
[i
+ 1])
1240 ca
->start_reg
= CA_FIRST_REG
+ i
;
1243 if (! ca
->reg_used
[3] && ca
->can_split
)
1247 ca
->start_reg
= CA_FIRST_REG
+ 3;
1254 if (! ca
->reg_used
[0]
1255 && ! ca
->reg_used
[1]
1256 && ! ca
->reg_used
[2]
1257 && ! ca
->reg_used
[3])
1260 ca
->start_reg
= CA_FIRST_REG
;
1267 #undef TARGET_PROMOTE_PROTOTYPES
1268 #define TARGET_PROMOTE_PROTOTYPES msp430_promote_prototypes
1271 msp430_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED
)
1276 #undef TARGET_FUNCTION_ARG
1277 #define TARGET_FUNCTION_ARG msp430_function_arg
1280 msp430_function_arg (cumulative_args_t cap
,
1285 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1287 msp430_evaluate_arg (cap
, mode
, type
, named
);
1290 return gen_rtx_REG (mode
, ca
->start_reg
);
1295 #undef TARGET_ARG_PARTIAL_BYTES
1296 #define TARGET_ARG_PARTIAL_BYTES msp430_arg_partial_bytes
1299 msp430_arg_partial_bytes (cumulative_args_t cap
,
1304 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1306 msp430_evaluate_arg (cap
, mode
, type
, named
);
1308 if (ca
->reg_count
&& ca
->mem_count
)
1309 return ca
->reg_count
* UNITS_PER_WORD
;
1314 #undef TARGET_PASS_BY_REFERENCE
1315 #define TARGET_PASS_BY_REFERENCE msp430_pass_by_reference
1318 msp430_pass_by_reference (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1321 bool named ATTRIBUTE_UNUSED
)
1323 return (mode
== BLKmode
1324 || (type
&& TREE_CODE (type
) == RECORD_TYPE
)
1325 || (type
&& TREE_CODE (type
) == UNION_TYPE
));
1328 #undef TARGET_CALLEE_COPIES
1329 #define TARGET_CALLEE_COPIES msp430_callee_copies
1332 msp430_callee_copies (cumulative_args_t cap ATTRIBUTE_UNUSED
,
1333 machine_mode mode ATTRIBUTE_UNUSED
,
1334 const_tree type ATTRIBUTE_UNUSED
,
1335 bool named ATTRIBUTE_UNUSED
)
1340 #undef TARGET_FUNCTION_ARG_ADVANCE
1341 #define TARGET_FUNCTION_ARG_ADVANCE msp430_function_arg_advance
1344 msp430_function_arg_advance (cumulative_args_t cap
,
1349 CUMULATIVE_ARGS
*ca
= get_cumulative_args (cap
);
1352 msp430_evaluate_arg (cap
, mode
, type
, named
);
1354 if (ca
->start_reg
>= CA_FIRST_REG
)
1355 for (i
= 0; i
< ca
->reg_count
; i
++)
1356 ca
->reg_used
[i
+ ca
->start_reg
- CA_FIRST_REG
] = 1;
1361 #undef TARGET_FUNCTION_ARG_BOUNDARY
1362 #define TARGET_FUNCTION_ARG_BOUNDARY msp430_function_arg_boundary
1365 msp430_function_arg_boundary (machine_mode mode
, const_tree type
)
1368 && int_size_in_bytes (type
) > 1)
1370 if (GET_MODE_BITSIZE (mode
) > 8)
1375 #undef TARGET_RETURN_IN_MEMORY
1376 #define TARGET_RETURN_IN_MEMORY msp430_return_in_memory
1379 msp430_return_in_memory (const_tree ret_type
, const_tree fntype ATTRIBUTE_UNUSED
)
1381 machine_mode mode
= TYPE_MODE (ret_type
);
1384 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == RECORD_TYPE
)
1385 || (fntype
&& TREE_CODE (TREE_TYPE (fntype
)) == UNION_TYPE
))
1388 if (GET_MODE_SIZE (mode
) > 8)
1394 #undef TARGET_GET_RAW_ARG_MODE
1395 #define TARGET_GET_RAW_ARG_MODE msp430_get_raw_arg_mode
1398 msp430_get_raw_arg_mode (int regno
)
1400 return (regno
== ARG_POINTER_REGNUM
) ? VOIDmode
: Pmode
;
1403 #undef TARGET_GET_RAW_RESULT_MODE
1404 #define TARGET_GET_RAW_RESULT_MODE msp430_get_raw_result_mode
1407 msp430_get_raw_result_mode (int regno ATTRIBUTE_UNUSED
)
1412 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
1413 #define TARGET_GIMPLIFY_VA_ARG_EXPR msp430_gimplify_va_arg_expr
1415 #include "gimplify.h"
1418 msp430_gimplify_va_arg_expr (tree valist
, tree type
, gimple_seq
*pre_p
,
1421 tree addr
, t
, type_size
, rounded_size
, valist_tmp
;
1422 unsigned HOST_WIDE_INT align
, boundary
;
1425 indirect
= pass_by_reference (NULL
, TYPE_MODE (type
), type
, false);
1427 type
= build_pointer_type (type
);
1429 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
1430 boundary
= targetm
.calls
.function_arg_boundary (TYPE_MODE (type
), type
);
1432 /* When we align parameter on stack for caller, if the parameter
1433 alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be
1434 aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee
1435 here with caller. */
1436 if (boundary
> MAX_SUPPORTED_STACK_ALIGNMENT
)
1437 boundary
= MAX_SUPPORTED_STACK_ALIGNMENT
;
1439 boundary
/= BITS_PER_UNIT
;
1441 /* Hoist the valist value into a temporary for the moment. */
1442 valist_tmp
= get_initialized_tmp_var (valist
, pre_p
, NULL
);
1444 /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually
1445 requires greater alignment, we must perform dynamic alignment. */
1446 if (boundary
> align
1447 && !integer_zerop (TYPE_SIZE (type
)))
1449 /* FIXME: This is where this function diverts from targhooks.c:
1450 std_gimplify_va_arg_expr(). It works, but I do not know why... */
1451 if (! POINTER_TYPE_P (type
))
1453 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1454 fold_build_pointer_plus_hwi (valist_tmp
, boundary
- 1));
1455 gimplify_and_add (t
, pre_p
);
1457 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist_tmp
,
1458 fold_build2 (BIT_AND_EXPR
, TREE_TYPE (valist
),
1460 build_int_cst (TREE_TYPE (valist
), -boundary
)));
1461 gimplify_and_add (t
, pre_p
);
1467 /* If the actual alignment is less than the alignment of the type,
1468 adjust the type accordingly so that we don't assume strict alignment
1469 when dereferencing the pointer. */
1470 boundary
*= BITS_PER_UNIT
;
1471 if (boundary
< TYPE_ALIGN (type
))
1473 type
= build_variant_type_copy (type
);
1474 SET_TYPE_ALIGN (type
, boundary
);
1477 /* Compute the rounded size of the type. */
1478 type_size
= size_in_bytes (type
);
1479 rounded_size
= round_up (type_size
, align
);
1481 /* Reduce rounded_size so it's sharable with the postqueue. */
1482 gimplify_expr (&rounded_size
, pre_p
, post_p
, is_gimple_val
, fb_rvalue
);
1487 /* Compute new value for AP. */
1488 t
= fold_build_pointer_plus (valist_tmp
, rounded_size
);
1489 t
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, t
);
1490 gimplify_and_add (t
, pre_p
);
1492 addr
= fold_convert (build_pointer_type (type
), addr
);
1495 addr
= build_va_arg_indirect_ref (addr
);
1497 addr
= build_va_arg_indirect_ref (addr
);
1503 #define TARGET_LRA_P hook_bool_void_false
1505 /* Addressing Modes */
1507 #undef TARGET_LEGITIMATE_ADDRESS_P
1508 #define TARGET_LEGITIMATE_ADDRESS_P msp430_legitimate_address_p
1511 reg_ok_for_addr (rtx r
, bool strict
)
1515 if (strict
&& rn
>= FIRST_PSEUDO_REGISTER
)
1516 rn
= reg_renumber
[rn
];
1517 if (strict
&& 0 <= rn
&& rn
< FIRST_PSEUDO_REGISTER
)
1525 msp430_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED
,
1526 rtx x ATTRIBUTE_UNUSED
,
1527 bool strict ATTRIBUTE_UNUSED
)
1529 switch (GET_CODE (x
))
1535 if (REG_P (XEXP (x
, 0)))
1537 if (GET_MODE (x
) != GET_MODE (XEXP (x
, 0)))
1539 if (!reg_ok_for_addr (XEXP (x
, 0), strict
))
1541 switch (GET_CODE (XEXP (x
, 1)))
1554 if (!reg_ok_for_addr (x
, strict
))
1567 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
1568 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P msp430_addr_space_legitimate_address_p
1571 msp430_addr_space_legitimate_address_p (machine_mode mode
,
1574 addr_space_t as ATTRIBUTE_UNUSED
)
1576 return msp430_legitimate_address_p (mode
, x
, strict
);
1579 #undef TARGET_ASM_INTEGER
1580 #define TARGET_ASM_INTEGER msp430_asm_integer
1582 msp430_asm_integer (rtx x
, unsigned int size
, int aligned_p
)
1584 int c
= GET_CODE (x
);
1586 if (size
== 3 && GET_MODE (x
) == PSImode
)
1592 if (c
== SYMBOL_REF
|| c
== CONST
|| c
== LABEL_REF
|| c
== CONST_INT
1593 || c
== PLUS
|| c
== MINUS
)
1595 fprintf (asm_out_file
, "\t.long\t");
1596 output_addr_const (asm_out_file
, x
);
1597 fputc ('\n', asm_out_file
);
1602 return default_assemble_integer (x
, size
, aligned_p
);
1605 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
1606 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA msp430_asm_output_addr_const_extra
1608 msp430_asm_output_addr_const_extra (FILE *file ATTRIBUTE_UNUSED
, rtx x
)
1614 #undef TARGET_LEGITIMATE_CONSTANT_P
1615 #define TARGET_LEGITIMATE_CONSTANT_P msp430_legitimate_constant
1618 msp430_legitimate_constant (machine_mode mode
, rtx x
)
1620 return ! CONST_INT_P (x
)
1622 /* GCC does not know the width of the PSImode, so make
1623 sure that it does not try to use a constant value that
1625 || (INTVAL (x
) < (1 << 20) && INTVAL (x
) >= (HOST_WIDE_INT
)(HOST_WIDE_INT_M1U
<< 20));
1629 #undef TARGET_RTX_COSTS
1630 #define TARGET_RTX_COSTS msp430_rtx_costs
1632 static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED
,
1634 int outer_code ATTRIBUTE_UNUSED
,
1635 int opno ATTRIBUTE_UNUSED
,
1637 bool speed ATTRIBUTE_UNUSED
)
1639 int code
= GET_CODE (x
);
1644 if (mode
== SImode
&& outer_code
== SET
)
1646 *total
= COSTS_N_INSNS (4);
1655 *total
= COSTS_N_INSNS (100);
1663 /* Function Entry and Exit */
1665 /* The MSP430 call frame looks like this:
1668 +--------------------+
1672 +--------------------+ <-- "arg pointer"
1674 | PC from call | (2 bytes for 430, 4 for TARGET_LARGE)
1676 +--------------------+
1677 | SR if this func has|
1678 | been called via an |
1680 +--------------------+ <-- SP before prologue, also AP
1682 | Saved Regs | (2 bytes per reg for 430, 4 per for TARGET_LARGE)
1684 +--------------------+ <-- "frame pointer"
1688 +--------------------+
1692 +--------------------+ <-- SP during function
1697 /* We use this to wrap all emitted insns in the prologue, so they get
1698 the "frame-related" (/f) flag set. */
1702 RTX_FRAME_RELATED_P (x
) = 1;
1706 /* This is the one spot that decides if a register is to be saved and
1707 restored in the prologue/epilogue. */
1709 msp430_preserve_reg_p (int regno
)
1711 /* PC, SP, SR, and the constant generator. */
1715 /* FIXME: add interrupt, EH, etc. */
1716 if (crtl
->calls_eh_return
)
1719 /* Shouldn't be more than the above, but just in case... */
1720 if (fixed_regs
[regno
])
1723 /* Interrupt handlers save all registers they use, even
1724 ones which are call saved. If they call other functions
1725 then *every* register is saved. */
1726 if (msp430_is_interrupt_func ())
1727 return ! crtl
->is_leaf
|| df_regs_ever_live_p (regno
);
1729 if (!call_used_regs
[regno
]
1730 && df_regs_ever_live_p (regno
))
1736 /* Compute all the frame-related fields in our machine_function
1739 msp430_compute_frame_info (void)
1743 cfun
->machine
->computed
= 1;
1744 cfun
->machine
->framesize_regs
= 0;
1745 cfun
->machine
->framesize_locals
= get_frame_size ();
1746 cfun
->machine
->framesize_outgoing
= crtl
->outgoing_args_size
;
1748 for (i
= 0; i
< ARG_POINTER_REGNUM
; i
++)
1749 if (msp430_preserve_reg_p (i
))
1751 cfun
->machine
->need_to_save
[i
] = 1;
1752 cfun
->machine
->framesize_regs
+= (TARGET_LARGE
? 4 : 2);
1755 cfun
->machine
->need_to_save
[i
] = 0;
1757 if ((cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
) & 1)
1758 cfun
->machine
->framesize_locals
++;
1760 cfun
->machine
->framesize
= (cfun
->machine
->framesize_regs
1761 + cfun
->machine
->framesize_locals
1762 + cfun
->machine
->framesize_outgoing
);
1765 /* Attribute Handling. */
1767 const char * const ATTR_INTR
= "interrupt";
1768 const char * const ATTR_WAKEUP
= "wakeup";
1769 const char * const ATTR_NAKED
= "naked";
1770 const char * const ATTR_REENT
= "reentrant";
1771 const char * const ATTR_CRIT
= "critical";
1772 const char * const ATTR_LOWER
= "lower";
1773 const char * const ATTR_UPPER
= "upper";
1774 const char * const ATTR_EITHER
= "either";
1775 const char * const ATTR_NOINIT
= "noinit";
1776 const char * const ATTR_PERSIST
= "persistent";
1779 has_attr (const char * attr
, tree decl
)
1781 if (decl
== NULL_TREE
)
1783 return lookup_attribute (attr
, DECL_ATTRIBUTES (decl
)) != NULL_TREE
;
1787 is_interrupt_func (tree decl
= current_function_decl
)
1789 return has_attr (ATTR_INTR
, decl
);
1792 /* Returns true if the current function has the "interrupt" attribute. */
1795 msp430_is_interrupt_func (void)
1797 return is_interrupt_func (current_function_decl
);
1801 is_wakeup_func (tree decl
= current_function_decl
)
1803 return is_interrupt_func (decl
) && has_attr (ATTR_WAKEUP
, decl
);
1807 is_naked_func (tree decl
= current_function_decl
)
1809 return has_attr (ATTR_NAKED
, decl
);
1813 is_reentrant_func (tree decl
= current_function_decl
)
1815 return has_attr (ATTR_REENT
, decl
);
1819 is_critical_func (tree decl
= current_function_decl
)
1821 return has_attr (ATTR_CRIT
, decl
);
1825 has_section_name (const char * name
, tree decl
= current_function_decl
)
1827 if (decl
== NULL_TREE
)
1829 return (DECL_SECTION_NAME (decl
)
1830 && (strcmp (name
, DECL_SECTION_NAME (decl
)) == 0));
1833 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
1834 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS msp430_allocate_stack_slots_for_args
1837 msp430_allocate_stack_slots_for_args (void)
1839 /* Naked functions should not allocate stack slots for arguments. */
1840 return ! is_naked_func ();
1843 /* Verify MSP430 specific attributes. */
1844 #define TREE_NAME_EQ(NAME, STR) (strcmp (IDENTIFIER_POINTER (NAME), (STR)) == 0)
1847 msp430_attr (tree
* node
,
1850 int flags ATTRIBUTE_UNUSED
,
1851 bool * no_add_attrs
)
1853 gcc_assert (DECL_P (* node
));
1857 /* Only the interrupt attribute takes an argument. */
1858 gcc_assert (TREE_NAME_EQ (name
, ATTR_INTR
));
1860 tree value
= TREE_VALUE (args
);
1862 switch (TREE_CODE (value
))
1865 if ( strcmp (TREE_STRING_POINTER (value
), "reset")
1866 && strcmp (TREE_STRING_POINTER (value
), "nmi")
1867 && strcmp (TREE_STRING_POINTER (value
), "watchdog"))
1868 /* Allow the attribute to be added - the linker script
1869 being used may still recognise this name. */
1870 warning (OPT_Wattributes
,
1871 "unrecognized interrupt vector argument of %qE attribute",
1876 if (wi::gtu_p (value
, 63))
1877 /* Allow the attribute to be added - the linker script
1878 being used may still recognise this value. */
1879 warning (OPT_Wattributes
,
1880 "numeric argument of %qE attribute must be in range 0..63",
1885 warning (OPT_Wattributes
,
1886 "argument of %qE attribute is not a string constant or number",
1888 *no_add_attrs
= true;
1893 const char * message
= NULL
;
1895 if (TREE_CODE (* node
) != FUNCTION_DECL
)
1897 message
= "%qE attribute only applies to functions";
1899 else if (TREE_NAME_EQ (name
, ATTR_INTR
))
1901 if (TREE_CODE (TREE_TYPE (* node
)) == FUNCTION_TYPE
1902 && ! VOID_TYPE_P (TREE_TYPE (TREE_TYPE (* node
))))
1903 message
= "interrupt handlers must be void";
1905 if (! TREE_PUBLIC (* node
))
1906 message
= "interrupt handlers cannot be static";
1908 /* Ensure interrupt handlers never get optimised out. */
1909 TREE_USED (* node
) = 1;
1910 DECL_PRESERVE_P (* node
) = 1;
1912 else if (TREE_NAME_EQ (name
, ATTR_REENT
))
1914 if (is_naked_func (* node
))
1915 message
= "naked functions cannot be reentrant";
1916 else if (is_critical_func (* node
))
1917 message
= "critical functions cannot be reentrant";
1919 else if (TREE_NAME_EQ (name
, ATTR_CRIT
))
1921 if (is_naked_func (* node
))
1922 message
= "naked functions cannot be critical";
1923 else if (is_reentrant_func (* node
))
1924 message
= "reentrant functions cannot be critical";
1926 else if (TREE_NAME_EQ (name
, ATTR_NAKED
))
1928 if (is_critical_func (* node
))
1929 message
= "critical functions cannot be naked";
1930 else if (is_reentrant_func (* node
))
1931 message
= "reentrant functions cannot be naked";
1936 warning (OPT_Wattributes
, message
, name
);
1937 * no_add_attrs
= true;
1944 msp430_section_attr (tree
* node
,
1947 int flags ATTRIBUTE_UNUSED
,
1948 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1950 gcc_assert (DECL_P (* node
));
1951 gcc_assert (args
== NULL
);
1953 const char * message
= NULL
;
1955 if (TREE_NAME_EQ (name
, ATTR_UPPER
))
1957 if (has_attr (ATTR_LOWER
, * node
))
1958 message
= "already marked with 'lower' attribute";
1959 else if (has_attr (ATTR_EITHER
, * node
))
1960 message
= "already marked with 'either' attribute";
1962 message
= "upper attribute needs a 430X cpu";
1964 else if (TREE_NAME_EQ (name
, ATTR_LOWER
))
1966 if (has_attr (ATTR_UPPER
, * node
))
1967 message
= "already marked with 'upper' attribute";
1968 else if (has_attr (ATTR_EITHER
, * node
))
1969 message
= "already marked with 'either' attribute";
1973 gcc_assert (TREE_NAME_EQ (name
, ATTR_EITHER
));
1975 if (has_attr (ATTR_LOWER
, * node
))
1976 message
= "already marked with 'lower' attribute";
1977 else if (has_attr (ATTR_UPPER
, * node
))
1978 message
= "already marked with 'upper' attribute";
1983 warning (OPT_Wattributes
, message
, name
);
1984 * no_add_attrs
= true;
1991 msp430_data_attr (tree
* node
,
1994 int flags ATTRIBUTE_UNUSED
,
1995 bool * no_add_attrs ATTRIBUTE_UNUSED
)
1997 const char * message
= NULL
;
1999 gcc_assert (DECL_P (* node
));
2000 gcc_assert (args
== NULL
);
2002 if (TREE_CODE (* node
) != VAR_DECL
)
2003 message
= G_("%qE attribute only applies to variables");
2005 /* Check that it's possible for the variable to have a section. */
2006 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2007 && DECL_SECTION_NAME (* node
))
2008 message
= G_("%qE attribute cannot be applied to variables with specific sections");
2010 if (!message
&& TREE_NAME_EQ (name
, ATTR_PERSIST
) && !TREE_STATIC (* node
)
2011 && !TREE_PUBLIC (* node
) && !DECL_EXTERNAL (* node
))
2012 message
= G_("%qE attribute has no effect on automatic variables");
2014 /* It's not clear if there is anything that can be set here to prevent the
2015 front end placing the variable before the back end can handle it, in a
2016 similar way to how DECL_COMMON is used below.
2017 So just place the variable in the .persistent section now. */
2018 if ((TREE_STATIC (* node
) || DECL_EXTERNAL (* node
) || in_lto_p
)
2019 && TREE_NAME_EQ (name
, ATTR_PERSIST
))
2020 set_decl_section_name (* node
, ".persistent");
2022 /* If this var is thought to be common, then change this. Common variables
2023 are assigned to sections before the backend has a chance to process them. */
2024 if (DECL_COMMON (* node
))
2025 DECL_COMMON (* node
) = 0;
2029 warning (OPT_Wattributes
, message
, name
);
2030 * no_add_attrs
= true;
2037 #undef TARGET_ATTRIBUTE_TABLE
2038 #define TARGET_ATTRIBUTE_TABLE msp430_attribute_table
2040 /* Table of MSP430-specific attributes. */
2041 const struct attribute_spec msp430_attribute_table
[] =
2043 /* Name min_num_args type_req, affects_type_identity
2044 max_num_args, fn_type_req
2045 decl_req handler. */
2046 { ATTR_INTR
, 0, 1, true, false, false, msp430_attr
, false },
2047 { ATTR_NAKED
, 0, 0, true, false, false, msp430_attr
, false },
2048 { ATTR_REENT
, 0, 0, true, false, false, msp430_attr
, false },
2049 { ATTR_CRIT
, 0, 0, true, false, false, msp430_attr
, false },
2050 { ATTR_WAKEUP
, 0, 0, true, false, false, msp430_attr
, false },
2052 { ATTR_LOWER
, 0, 0, true, false, false, msp430_section_attr
, false },
2053 { ATTR_UPPER
, 0, 0, true, false, false, msp430_section_attr
, false },
2054 { ATTR_EITHER
, 0, 0, true, false, false, msp430_section_attr
, false },
2056 { ATTR_NOINIT
, 0, 0, true, false, false, msp430_data_attr
, false },
2057 { ATTR_PERSIST
, 0, 0, true, false, false, msp430_data_attr
, false },
2059 { NULL
, 0, 0, false, false, false, NULL
, false }
2062 #undef TARGET_ASM_FUNCTION_PROLOGUE
2063 #define TARGET_ASM_FUNCTION_PROLOGUE msp430_start_function
2066 msp430_start_function (FILE *outfile
)
2070 fprintf (outfile
, "; start of function\n");
2072 if (DECL_ATTRIBUTES (current_function_decl
) != NULL_TREE
)
2074 fprintf (outfile
, "; attributes: ");
2075 if (is_naked_func ())
2076 fprintf (outfile
, "naked ");
2077 if (msp430_is_interrupt_func ())
2078 fprintf (outfile
, "interrupt ");
2079 if (is_reentrant_func ())
2080 fprintf (outfile
, "reentrant ");
2081 if (is_critical_func ())
2082 fprintf (outfile
, "critical ");
2083 if (is_wakeup_func ())
2084 fprintf (outfile
, "wakeup ");
2085 fprintf (outfile
, "\n");
2088 fprintf (outfile
, "; framesize_regs: %d\n", cfun
->machine
->framesize_regs
);
2089 fprintf (outfile
, "; framesize_locals: %d\n", cfun
->machine
->framesize_locals
);
2090 fprintf (outfile
, "; framesize_outgoing: %d\n", cfun
->machine
->framesize_outgoing
);
2091 fprintf (outfile
, "; framesize: %d\n", cfun
->machine
->framesize
);
2092 fprintf (outfile
, "; elim ap -> fp %d\n", msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, FRAME_POINTER_REGNUM
));
2093 fprintf (outfile
, "; elim fp -> sp %d\n", msp430_initial_elimination_offset (FRAME_POINTER_REGNUM
, STACK_POINTER_REGNUM
));
2096 fprintf (outfile
, "; saved regs:");
2097 for (r
= 0; r
< ARG_POINTER_REGNUM
; r
++)
2098 if (cfun
->machine
->need_to_save
[r
])
2100 fprintf (outfile
, " %s", reg_names
[r
]);
2104 fprintf (outfile
, "(none)");
2105 fprintf (outfile
, "\n");
2108 /* Common code to change the stack pointer. */
2110 increment_stack (HOST_WIDE_INT amount
)
2113 rtx sp
= stack_pointer_rtx
;
2120 inc
= GEN_INT (- amount
);
2122 F (emit_insn (gen_subpsi3 (sp
, sp
, inc
)));
2124 F (emit_insn (gen_subhi3 (sp
, sp
, inc
)));
2128 inc
= GEN_INT (amount
);
2130 emit_insn (gen_addpsi3 (sp
, sp
, inc
));
2132 emit_insn (gen_addhi3 (sp
, sp
, inc
));
2137 msp430_start_function (FILE *file
, const char *name
, tree decl
)
2141 int_attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2142 if (int_attr
!= NULL_TREE
)
2144 tree intr_vector
= TREE_VALUE (int_attr
);
2146 if (intr_vector
!= NULL_TREE
)
2150 /* Interrupt vector sections should be unique, but use of weak
2151 functions implies multiple definitions. */
2152 if (DECL_WEAK (decl
))
2154 error ("argument to interrupt attribute is unsupported for weak functions");
2157 intr_vector
= TREE_VALUE (intr_vector
);
2159 /* The interrupt attribute has a vector value. Turn this into a
2160 section name, switch to that section and put the address of
2161 the current function into that vector slot. Note msp430_attr()
2162 has already verified the vector name for us. */
2163 if (TREE_CODE (intr_vector
) == STRING_CST
)
2164 sprintf (buf
, "__interrupt_vector_%.80s",
2165 TREE_STRING_POINTER (intr_vector
));
2166 else /* TREE_CODE (intr_vector) == INTEGER_CST */
2167 sprintf (buf
, "__interrupt_vector_%u",
2168 (unsigned int) TREE_INT_CST_LOW (intr_vector
));
2170 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2171 fputs ("\t.word\t", file
);
2172 assemble_name (file
, name
);
2178 switch_to_section (function_section (decl
));
2179 ASM_OUTPUT_TYPE_DIRECTIVE(file
, name
, "function");
2180 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2183 static const char * const lower_prefix
= ".lower";
2184 static const char * const upper_prefix
= ".upper";
2185 static const char * const either_prefix
= ".either";
2187 /* Generate a prefix for a section name, based upon
2188 the region into which the object should be placed. */
2191 gen_prefix (tree decl
)
2193 if (DECL_ONE_ONLY (decl
))
2196 /* If the user has specified a particular section then do not use any prefix. */
2197 if (has_attr ("section", decl
))
2200 /* If the function has been put in the .lowtext section (because it is an
2201 interrupt handler, and the large memory model is used), then do not add
2203 if (has_section_name (".lowtext", decl
))
2206 /* If the object has __attribute__((lower)) then use the ".lower." prefix. */
2207 if (has_attr (ATTR_LOWER
, decl
))
2208 return lower_prefix
;
2210 /* If we are compiling for the MSP430 then we do not support the upper region. */
2214 if (has_attr (ATTR_UPPER
, decl
))
2215 return upper_prefix
;
2217 if (has_attr (ATTR_EITHER
, decl
))
2218 return either_prefix
;
2220 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2222 if (msp430_code_region
== MSP430_REGION_LOWER
)
2223 return lower_prefix
;
2225 if (msp430_code_region
== MSP430_REGION_UPPER
)
2226 return upper_prefix
;
2228 if (msp430_code_region
== MSP430_REGION_EITHER
)
2229 return either_prefix
;
2233 if (msp430_data_region
== MSP430_REGION_LOWER
)
2234 return lower_prefix
;
2236 if (msp430_data_region
== MSP430_REGION_UPPER
)
2237 return upper_prefix
;
2239 if (msp430_data_region
== MSP430_REGION_EITHER
)
2240 return either_prefix
;
2246 static section
* noinit_section
;
2247 static section
* persist_section
;
2249 #undef TARGET_ASM_INIT_SECTIONS
2250 #define TARGET_ASM_INIT_SECTIONS msp430_init_sections
2253 msp430_init_sections (void)
2255 noinit_section
= get_unnamed_section (0, output_section_asm_op
, ".section .noinit,\"aw\"");
2256 persist_section
= get_unnamed_section (0, output_section_asm_op
, ".section .persistent,\"aw\"");
2259 #undef TARGET_ASM_SELECT_SECTION
2260 #define TARGET_ASM_SELECT_SECTION msp430_select_section
2263 msp430_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
2265 gcc_assert (decl
!= NULL_TREE
);
2267 if (TREE_CODE (decl
) == STRING_CST
2268 || TREE_CODE (decl
) == CONSTRUCTOR
2269 || TREE_CODE (decl
) == INTEGER_CST
2270 || TREE_CODE (decl
) == VECTOR_CST
2271 || TREE_CODE (decl
) == COMPLEX_CST
)
2272 return default_select_section (decl
, reloc
, align
);
2274 /* In large mode we must make sure that interrupt handlers are put into
2275 low memory as the vector table only accepts 16-bit addresses. */
2276 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2277 return get_section (".lowtext", SECTION_CODE
| SECTION_WRITE
, decl
);
2279 const char * prefix
= gen_prefix (decl
);
2282 if (TREE_CODE (decl
) == FUNCTION_DECL
)
2283 return text_section
;
2284 else if (has_attr (ATTR_NOINIT
, decl
))
2285 return noinit_section
;
2286 else if (has_attr (ATTR_PERSIST
, decl
))
2287 return persist_section
;
2289 return default_select_section (decl
, reloc
, align
);
2293 switch (categorize_decl_for_section (decl
, reloc
))
2295 case SECCAT_TEXT
: sec
= ".text"; break;
2296 case SECCAT_DATA
: sec
= ".data"; break;
2297 case SECCAT_BSS
: sec
= ".bss"; break;
2298 case SECCAT_RODATA
: sec
= ".rodata"; break;
2300 case SECCAT_RODATA_MERGE_STR
:
2301 case SECCAT_RODATA_MERGE_STR_INIT
:
2302 case SECCAT_RODATA_MERGE_CONST
:
2303 case SECCAT_SRODATA
:
2304 case SECCAT_DATA_REL
:
2305 case SECCAT_DATA_REL_LOCAL
:
2306 case SECCAT_DATA_REL_RO
:
2307 case SECCAT_DATA_REL_RO_LOCAL
:
2312 return default_select_section (decl
, reloc
, align
);
2318 const char * dec_name
= DECL_SECTION_NAME (decl
);
2319 char * name
= ACONCAT ((prefix
, sec
, dec_name
, NULL
));
2321 return get_named_section (decl
, name
, 0);
2324 #undef TARGET_ASM_FUNCTION_SECTION
2325 #define TARGET_ASM_FUNCTION_SECTION msp430_function_section
2328 msp430_function_section (tree decl
, enum node_frequency freq
, bool startup
, bool exit
)
2332 gcc_assert (DECL_SECTION_NAME (decl
) != NULL
);
2333 name
= DECL_SECTION_NAME (decl
);
2335 const char * prefix
= gen_prefix (decl
);
2337 || strncmp (name
, prefix
, strlen (prefix
)) == 0)
2338 return default_function_section (decl
, freq
, startup
, exit
);
2340 name
= ACONCAT ((prefix
, name
, NULL
));
2341 return get_named_section (decl
, name
, 0);
2344 #undef TARGET_SECTION_TYPE_FLAGS
2345 #define TARGET_SECTION_TYPE_FLAGS msp430_section_type_flags
2348 msp430_section_type_flags (tree decl
, const char * name
, int reloc
)
2350 if (strncmp (name
, lower_prefix
, strlen (lower_prefix
)) == 0)
2351 name
+= strlen (lower_prefix
);
2352 else if (strncmp (name
, upper_prefix
, strlen (upper_prefix
)) == 0)
2353 name
+= strlen (upper_prefix
);
2354 else if (strncmp (name
, either_prefix
, strlen (either_prefix
)) == 0)
2355 name
+= strlen (either_prefix
);
2356 else if (strcmp (name
, ".noinit") == 0)
2357 return SECTION_WRITE
| SECTION_BSS
| SECTION_NOTYPE
;
2358 else if (strcmp (name
, ".persistent") == 0)
2359 return SECTION_WRITE
| SECTION_NOTYPE
;
2361 return default_section_type_flags (decl
, name
, reloc
);
2364 #undef TARGET_ASM_UNIQUE_SECTION
2365 #define TARGET_ASM_UNIQUE_SECTION msp430_unique_section
2368 msp430_unique_section (tree decl
, int reloc
)
2370 gcc_assert (decl
!= NULL_TREE
);
2372 /* In large mode we must make sure that interrupt handlers are put into
2373 low memory as the vector table only accepts 16-bit addresses. */
2374 if (TARGET_LARGE
&& TREE_CODE (decl
) == FUNCTION_DECL
&& is_interrupt_func (decl
))
2376 set_decl_section_name (decl
, ".lowtext");
2380 default_unique_section (decl
, reloc
);
2382 const char * prefix
;
2384 if ( TREE_CODE (decl
) == STRING_CST
2385 || TREE_CODE (decl
) == CONSTRUCTOR
2386 || TREE_CODE (decl
) == INTEGER_CST
2387 || TREE_CODE (decl
) == VECTOR_CST
2388 || TREE_CODE (decl
) == COMPLEX_CST
2389 || (prefix
= gen_prefix (decl
)) == NULL
2393 const char * dec_name
= DECL_SECTION_NAME (decl
);
2394 char * name
= ACONCAT ((prefix
, dec_name
, NULL
));
2396 set_decl_section_name (decl
, name
);
2399 /* Emit a declaration of a common symbol.
2400 If a data region is in use then put the symbol into the
2401 equivalent .bss section instead. */
2404 msp430_output_aligned_decl_common (FILE * stream
,
2407 unsigned HOST_WIDE_INT size
,
2410 if (msp430_data_region
== MSP430_REGION_ANY
)
2412 fprintf (stream
, COMMON_ASM_OP
);
2413 assemble_name (stream
, name
);
2414 fprintf (stream
, "," HOST_WIDE_INT_PRINT_UNSIGNED
",%u\n",
2415 size
, align
/ BITS_PER_UNIT
);
2422 sec
= msp430_select_section (decl
, 0, align
);
2424 switch (msp430_data_region
)
2426 case MSP430_REGION_UPPER
: sec
= get_named_section (NULL
, ".upper.bss", 0); break;
2427 case MSP430_REGION_LOWER
: sec
= get_named_section (NULL
, ".lower.bss", 0); break;
2428 case MSP430_REGION_EITHER
: sec
= get_named_section (NULL
, ".either.bss", 0); break;
2432 gcc_assert (sec
!= NULL
);
2434 switch_to_section (sec
);
2435 ASM_OUTPUT_ALIGN (stream
, floor_log2 (align
/ BITS_PER_UNIT
));
2436 targetm
.asm_out
.globalize_label (stream
, name
);
2437 ASM_WEAKEN_LABEL (stream
, name
);
2438 ASM_OUTPUT_LABEL (stream
, name
);
2439 ASM_OUTPUT_SKIP (stream
, size
? size
: 1);
2444 msp430_do_not_relax_short_jumps (void)
2446 /* When placing code into "either" low or high memory we do not want the linker
2447 to grow the size of sections, which it can do if it is encounters a branch to
2448 a label that is too far away. So we tell the cbranch patterns to avoid using
2449 short jumps when there is a chance that the instructions will end up in a low
2452 msp430_code_region
== MSP430_REGION_EITHER
2453 || msp430_code_region
== MSP430_REGION_LOWER
2454 || has_attr (ATTR_EITHER
, current_function_decl
)
2455 || has_attr (ATTR_LOWER
, current_function_decl
);
2460 MSP430_BUILTIN_BIC_SR
,
2461 MSP430_BUILTIN_BIS_SR
,
2462 MSP430_BUILTIN_DELAY_CYCLES
,
2466 static GTY(()) tree msp430_builtins
[(int) MSP430_BUILTIN_max
];
2469 msp430_init_builtins (void)
2471 tree void_ftype_int
= build_function_type_list (void_type_node
, integer_type_node
, NULL
);
2472 tree void_ftype_longlong
= build_function_type_list (void_type_node
, long_long_integer_type_node
, NULL
);
2474 msp430_builtins
[MSP430_BUILTIN_BIC_SR
] =
2475 add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int
,
2476 MSP430_BUILTIN_BIC_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2478 msp430_builtins
[MSP430_BUILTIN_BIS_SR
] =
2479 add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int
,
2480 MSP430_BUILTIN_BIS_SR
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2482 msp430_builtins
[MSP430_BUILTIN_DELAY_CYCLES
] =
2483 add_builtin_function ( "__delay_cycles", void_ftype_longlong
,
2484 MSP430_BUILTIN_DELAY_CYCLES
, BUILT_IN_MD
, NULL
, NULL_TREE
);
2488 msp430_builtin_decl (unsigned code
, bool initialize ATTRIBUTE_UNUSED
)
2492 case MSP430_BUILTIN_BIC_SR
:
2493 case MSP430_BUILTIN_BIS_SR
:
2494 case MSP430_BUILTIN_DELAY_CYCLES
:
2495 return msp430_builtins
[code
];
2497 return error_mark_node
;
2501 /* These constants are really register reads, which are faster than
2502 regular constants. */
2504 cg_magic_constant (HOST_WIDE_INT c
)
2522 msp430_expand_delay_cycles (rtx arg
)
2524 HOST_WIDE_INT i
, c
, n
;
2525 /* extra cycles for MSP430X instructions */
2526 #define CYCX(M,X) (msp430x ? (X) : (M))
2528 if (GET_CODE (arg
) != CONST_INT
)
2530 error ("__delay_cycles() only takes constant arguments");
2536 if (HOST_BITS_PER_WIDE_INT
> 32)
2540 error ("__delay_cycles only takes non-negative cycle counts");
2545 emit_insn (gen_delay_cycles_start (arg
));
2547 /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
2548 if (c
> 3 * 0xffff + CYCX (7, 10))
2551 /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
2552 if (c
>= 0x10000 * 7 + CYCX (14, 16))
2555 c
-= CYCX (14, 16) + 7 * 0x10000;
2558 if ((unsigned long long) i
> 0xffffffffULL
)
2560 error ("__delay_cycles is limited to 32-bit loop counts");
2566 i
= (c
- CYCX (14, 16)) / 7;
2567 c
-= CYCX (14, 16) + i
* 7;
2570 if (cg_magic_constant (i
& 0xffff))
2572 if (cg_magic_constant ((i
>> 16) & 0xffff))
2576 emit_insn (gen_delay_cycles_32x (GEN_INT (i
), GEN_INT (n
- c
)));
2578 emit_insn (gen_delay_cycles_32 (GEN_INT (i
), GEN_INT (n
- c
)));
2581 /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
2585 i
= (c
- CYCX (7, 10)) / 3;
2586 c
-= CYCX (7, 10) + i
* 3;
2588 if (cg_magic_constant (i
))
2592 emit_insn (gen_delay_cycles_16x (GEN_INT (i
), GEN_INT (n
- c
)));
2594 emit_insn (gen_delay_cycles_16 (GEN_INT (i
), GEN_INT (n
- c
)));
2599 emit_insn (gen_delay_cycles_2 ());
2605 emit_insn (gen_delay_cycles_1 ());
2609 emit_insn (gen_delay_cycles_end (arg
));
2615 msp430_expand_builtin (tree exp
,
2616 rtx target ATTRIBUTE_UNUSED
,
2617 rtx subtarget ATTRIBUTE_UNUSED
,
2618 machine_mode mode ATTRIBUTE_UNUSED
,
2619 int ignore ATTRIBUTE_UNUSED
)
2621 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
2622 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
2623 rtx arg1
= expand_normal (CALL_EXPR_ARG (exp
, 0));
2625 if (fcode
== MSP430_BUILTIN_DELAY_CYCLES
)
2626 return msp430_expand_delay_cycles (arg1
);
2628 if (! msp430_is_interrupt_func ())
2630 error ("MSP430 builtin functions only work inside interrupt handlers");
2634 if (! REG_P (arg1
) && ! CONSTANT_P (arg1
))
2635 arg1
= force_reg (mode
, arg1
);
2639 case MSP430_BUILTIN_BIC_SR
: emit_insn (gen_bic_SR (arg1
)); break;
2640 case MSP430_BUILTIN_BIS_SR
: emit_insn (gen_bis_SR (arg1
)); break;
2642 internal_error ("bad builtin code");
2648 #undef TARGET_INIT_BUILTINS
2649 #define TARGET_INIT_BUILTINS msp430_init_builtins
2651 #undef TARGET_EXPAND_BUILTIN
2652 #define TARGET_EXPAND_BUILTIN msp430_expand_builtin
2654 #undef TARGET_BUILTIN_DECL
2655 #define TARGET_BUILTIN_DECL msp430_builtin_decl
2658 msp430_expand_prologue (void)
2662 /* Always use stack_pointer_rtx instead of calling
2663 rtx_gen_REG ourselves. Code elsewhere in GCC assumes
2664 that there is a single rtx representing the stack pointer,
2665 namely stack_pointer_rtx, and uses == to recognize it. */
2666 rtx sp
= stack_pointer_rtx
;
2669 if (is_naked_func ())
2671 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2672 examines the output of the gen_prologue() function. */
2673 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2677 emit_insn (gen_prologue_start_marker ());
2679 if (is_critical_func ())
2681 emit_insn (gen_push_intr_state ());
2682 emit_insn (gen_disable_interrupts ());
2684 else if (is_reentrant_func ())
2685 emit_insn (gen_disable_interrupts ());
2687 if (!cfun
->machine
->computed
)
2688 msp430_compute_frame_info ();
2690 if (flag_stack_usage_info
)
2691 current_function_static_stack_size
= cfun
->machine
->framesize
;
2693 if (crtl
->args
.pretend_args_size
)
2697 gcc_assert (crtl
->args
.pretend_args_size
== 2);
2699 p
= emit_insn (gen_grow_and_swap ());
2701 /* Document the stack decrement... */
2702 note
= F (gen_rtx_SET (stack_pointer_rtx
,
2703 gen_rtx_MINUS (Pmode
, stack_pointer_rtx
, GEN_INT (2))));
2704 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2706 /* ...and the establishment of a new location for the return address. */
2707 note
= F (gen_rtx_SET (gen_rtx_MEM (Pmode
,
2708 gen_rtx_PLUS (Pmode
,
2712 add_reg_note (p
, REG_CFA_OFFSET
, note
);
2716 for (i
= 15; i
>= 4; i
--)
2717 if (cfun
->machine
->need_to_save
[i
])
2722 for (seq
= i
- 1; seq
>= 4 && cfun
->machine
->need_to_save
[seq
]; seq
--)
2728 /* Note: with TARGET_LARGE we still use PUSHM as PUSHX.A is two bytes bigger. */
2729 p
= F (emit_insn (gen_pushm (gen_rtx_REG (Pmode
, i
),
2732 note
= gen_rtx_SEQUENCE (VOIDmode
, rtvec_alloc (count
+ 1));
2734 XVECEXP (note
, 0, 0)
2735 = F (gen_rtx_SET (stack_pointer_rtx
,
2736 gen_rtx_PLUS (Pmode
,
2738 GEN_INT (count
* (TARGET_LARGE
? -4 : -2)))));
2740 /* *sp-- = R[i-j] */
2744 for (j
= 0; j
< count
; j
++)
2747 int ofs
= (count
- j
- 1) * (TARGET_LARGE
? 4 : 2);
2750 addr
= gen_rtx_PLUS (Pmode
, sp
, GEN_INT (ofs
));
2752 addr
= stack_pointer_rtx
;
2754 XVECEXP (note
, 0, j
+ 1) =
2755 F (gen_rtx_SET (gen_rtx_MEM (Pmode
, addr
),
2756 gen_rtx_REG (Pmode
, i
- j
)) );
2759 add_reg_note (p
, REG_FRAME_RELATED_EXPR
, note
);
2763 F (emit_insn (gen_push (gen_rtx_REG (Pmode
, i
))));
2766 if (frame_pointer_needed
)
2767 F (emit_move_insn (gen_rtx_REG (Pmode
, FRAME_POINTER_REGNUM
), sp
));
2769 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2771 increment_stack (- fs
);
2773 emit_insn (gen_prologue_end_marker ());
2777 msp430_expand_epilogue (int is_eh
)
2783 if (is_naked_func ())
2785 /* We must generate some RTX as thread_prologue_and_epilogue_insns()
2786 examines the output of the gen_epilogue() function. */
2787 emit_insn (gen_rtx_CLOBBER (VOIDmode
, GEN_INT (0)));
2791 if (cfun
->machine
->need_to_save
[10])
2793 /* Check for a helper function. */
2794 helper_n
= 7; /* For when the loop below never sees a match. */
2795 for (i
= 9; i
>= 4; i
--)
2796 if (!cfun
->machine
->need_to_save
[i
])
2800 if (cfun
->machine
->need_to_save
[i
])
2809 emit_insn (gen_epilogue_start_marker ());
2811 if (cfun
->decl
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)), "main") == 0)
2812 emit_insn (gen_msp430_refsym_need_exit ());
2814 if (is_wakeup_func ())
2815 /* Clear the SCG1, SCG0, OSCOFF and CPUOFF bits in the saved copy of the
2816 status register current residing on the stack. When this function
2817 executes its RETI instruction the SR will be updated with this saved
2818 value, thus ensuring that the processor is woken up from any low power
2819 state in which it may be residing. */
2820 emit_insn (gen_bic_SR (GEN_INT (0xf0)));
2822 fs
= cfun
->machine
->framesize_locals
+ cfun
->machine
->framesize_outgoing
;
2824 increment_stack (fs
);
2828 /* We need to add the right "SP" register save just after the
2829 regular ones, so that when we pop it off we're in the EH
2830 return frame, not this one. This overwrites our own return
2831 address, but we're not going to be returning anyway. */
2832 rtx r12
= gen_rtx_REG (Pmode
, 12);
2833 rtx (*addPmode
)(rtx
, rtx
, rtx
) = TARGET_LARGE
? gen_addpsi3
: gen_addhi3
;
2835 /* R12 will hold the new SP. */
2836 i
= cfun
->machine
->framesize_regs
;
2837 emit_move_insn (r12
, stack_pointer_rtx
);
2838 emit_insn (addPmode (r12
, r12
, EH_RETURN_STACKADJ_RTX
));
2839 emit_insn (addPmode (r12
, r12
, GEN_INT (i
)));
2840 emit_move_insn (gen_rtx_MEM (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
, i
)), r12
);
2843 for (i
= 4; i
<= 15; i
++)
2844 if (cfun
->machine
->need_to_save
[i
])
2848 for (seq
= i
+ 1; seq
<= 15 && cfun
->machine
->need_to_save
[seq
]; seq
++)
2854 /* Note: With TARGET_LARGE we still use
2855 POPM as POPX.A is two bytes bigger. */
2856 emit_insn (gen_popm (stack_pointer_rtx
, GEN_INT (seq
- 1),
2860 else if (i
== 11 - helper_n
2861 && ! msp430_is_interrupt_func ()
2862 && ! is_reentrant_func ()
2863 && ! is_critical_func ()
2864 && crtl
->args
.pretend_args_size
== 0
2865 /* Calling the helper takes as many bytes as the POP;RET sequence. */
2869 emit_insn (gen_epilogue_helper (GEN_INT (helper_n
)));
2873 emit_insn (gen_pop (gen_rtx_REG (Pmode
, i
)));
2878 /* Also pop SP, which puts us into the EH return frame. Except
2879 that you can't "pop" sp, you have to just load it off the
2881 emit_move_insn (stack_pointer_rtx
, gen_rtx_MEM (Pmode
, stack_pointer_rtx
));
2884 if (crtl
->args
.pretend_args_size
)
2885 emit_insn (gen_swap_and_shrink ());
2887 if (is_critical_func ())
2888 emit_insn (gen_pop_intr_state ());
2889 else if (is_reentrant_func ())
2890 emit_insn (gen_enable_interrupts ());
2892 emit_jump_insn (gen_msp_return ());
2895 /* Implements EH_RETURN_STACKADJ_RTX. Saved and used later in
2896 m32c_emit_eh_epilogue. */
2898 msp430_eh_return_stackadj_rtx (void)
2900 if (!cfun
->machine
->eh_stack_adjust
)
2904 sa
= gen_rtx_REG (Pmode
, 15);
2905 cfun
->machine
->eh_stack_adjust
= sa
;
2907 return cfun
->machine
->eh_stack_adjust
;
2910 /* This function is called before reload, to "fix" the stack in
2911 preparation for an EH return. */
2913 msp430_expand_eh_return (rtx eh_handler
)
2915 /* These are all Pmode */
2916 rtx ap
, sa
, ra
, tmp
;
2918 ap
= arg_pointer_rtx
;
2919 sa
= msp430_eh_return_stackadj_rtx ();
2923 tmp
= gen_rtx_PLUS (Pmode
, ap
, sa
);
2924 tmp
= plus_constant (Pmode
, tmp
, TARGET_LARGE
? -4 : -2);
2925 tmp
= gen_rtx_MEM (Pmode
, tmp
);
2926 emit_move_insn (tmp
, ra
);
2929 #undef TARGET_INIT_DWARF_REG_SIZES_EXTRA
2930 #define TARGET_INIT_DWARF_REG_SIZES_EXTRA msp430_init_dwarf_reg_sizes_extra
2932 msp430_init_dwarf_reg_sizes_extra (tree address
)
2935 rtx addr
= expand_normal (address
);
2936 rtx mem
= gen_rtx_MEM (BLKmode
, addr
);
2938 /* This needs to match msp430_unwind_word_mode (above). */
2942 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2944 unsigned int dnum
= DWARF_FRAME_REGNUM (i
);
2945 unsigned int rnum
= DWARF2_FRAME_REG_OUT (dnum
, 1);
2947 if (rnum
< DWARF_FRAME_REGISTERS
)
2949 HOST_WIDE_INT offset
= rnum
* GET_MODE_SIZE (QImode
);
2951 emit_move_insn (adjust_address (mem
, QImode
, offset
),
2952 gen_int_mode (4, QImode
));
2957 /* This is a list of MD patterns that implement fixed-count shifts. */
2963 rtx (*genfunc
)(rtx
,rtx
);
2965 const_shift_helpers
[] =
2967 #define CSH(N,C,X,G) { "__mspabi_" N, C, X, gen_##G }
2969 CSH ("slli", 1, 1, slli_1
),
2970 CSH ("slll", 1, 1, slll_1
),
2971 CSH ("slll", 2, 1, slll_2
),
2973 CSH ("srai", 1, 0, srai_1
),
2974 CSH ("sral", 1, 0, sral_1
),
2975 CSH ("sral", 2, 0, sral_2
),
2977 CSH ("srll", 1, 0, srll_1
),
2978 CSH ("srll", 2, 1, srll_2x
),
2983 /* The MSP430 ABI defines a number of helper functions that should be
2984 used for, for example, 32-bit shifts. This function is called to
2985 emit such a function, using the table above to optimize some
2988 msp430_expand_helper (rtx
*operands
, const char *helper_name
, bool const_variants
)
2991 char *helper_const
= NULL
;
2994 machine_mode arg0mode
= GET_MODE (operands
[0]);
2995 machine_mode arg1mode
= GET_MODE (operands
[1]);
2996 machine_mode arg2mode
= GET_MODE (operands
[2]);
2997 int have_430x
= msp430x
? 1 : 0;
2999 if (CONST_INT_P (operands
[2]))
3003 for (i
=0; const_shift_helpers
[i
].name
; i
++)
3005 if (const_shift_helpers
[i
].need_430x
<= have_430x
3006 && strcmp (helper_name
, const_shift_helpers
[i
].name
) == 0
3007 && INTVAL (operands
[2]) == const_shift_helpers
[i
].count
)
3009 emit_insn (const_shift_helpers
[i
].genfunc (operands
[0], operands
[1]));
3015 if (arg1mode
== VOIDmode
)
3016 arg1mode
= arg0mode
;
3017 if (arg2mode
== VOIDmode
)
3018 arg2mode
= arg0mode
;
3020 if (arg1mode
== SImode
)
3027 && CONST_INT_P (operands
[2])
3028 && INTVAL (operands
[2]) >= 1
3029 && INTVAL (operands
[2]) <= 15)
3031 /* Note that the INTVAL is limited in value and length by the conditional above. */
3032 int len
= strlen (helper_name
) + 4;
3033 helper_const
= (char *) xmalloc (len
);
3034 snprintf (helper_const
, len
, "%s_%d", helper_name
, (int) INTVAL (operands
[2]));
3037 emit_move_insn (gen_rtx_REG (arg1mode
, 12),
3040 emit_move_insn (gen_rtx_REG (arg2mode
, arg2
),
3043 c
= gen_call_value_internal (gen_rtx_REG (arg0mode
, 12),
3044 gen_rtx_SYMBOL_REF (VOIDmode
, helper_const
? helper_const
: helper_name
),
3046 c
= emit_call_insn (c
);
3047 RTL_CONST_CALL_P (c
) = 1;
3050 use_regs (&f
, 12, arg1sz
);
3052 use_regs (&f
, arg2
, 1);
3053 add_function_usage_to (c
, f
);
3055 emit_move_insn (operands
[0],
3056 gen_rtx_REG (arg0mode
, 12));
3059 /* Called by cbranch<mode>4 to coerce operands into usable forms. */
3061 msp430_fixup_compare_operands (machine_mode my_mode
, rtx
* operands
)
3063 /* constants we're looking for, not constants which are allowed. */
3064 int const_op_idx
= 1;
3066 if (msp430_reversible_cmp_operator (operands
[0], VOIDmode
))
3069 if (GET_CODE (operands
[const_op_idx
]) != REG
3070 && GET_CODE (operands
[const_op_idx
]) != MEM
)
3071 operands
[const_op_idx
] = copy_to_mode_reg (my_mode
, operands
[const_op_idx
]);
3074 /* Simplify_gen_subreg() doesn't handle memory references the way we
3075 need it to below, so we use this function for when we must get a
3076 valid subreg in a "natural" state. */
3078 msp430_subreg (machine_mode mode
, rtx r
, machine_mode omode
, int byte
)
3082 if (GET_CODE (r
) == SUBREG
3083 && SUBREG_BYTE (r
) == 0)
3085 rtx ireg
= SUBREG_REG (r
);
3086 machine_mode imode
= GET_MODE (ireg
);
3088 /* special case for (HI (SI (PSI ...), 0)) */
3089 if (imode
== PSImode
3092 rv
= gen_rtx_SUBREG (mode
, ireg
, byte
);
3094 rv
= simplify_gen_subreg (mode
, ireg
, imode
, byte
);
3096 else if (GET_CODE (r
) == MEM
)
3097 rv
= adjust_address (r
, mode
, byte
);
3098 else if (GET_CODE (r
) == SYMBOL_REF
3099 && (byte
== 0 || byte
== 2)
3102 rv
= gen_rtx_ZERO_EXTRACT (HImode
, r
, GEN_INT (16), GEN_INT (8*byte
));
3103 rv
= gen_rtx_CONST (HImode
, r
);
3106 rv
= simplify_gen_subreg (mode
, r
, omode
, byte
);
3114 /* Called by movsi_x to generate the HImode operands. */
3116 msp430_split_movsi (rtx
*operands
)
3118 rtx op00
, op02
, op10
, op12
;
3120 op00
= msp430_subreg (HImode
, operands
[0], SImode
, 0);
3121 op02
= msp430_subreg (HImode
, operands
[0], SImode
, 2);
3123 if (GET_CODE (operands
[1]) == CONST
3124 || GET_CODE (operands
[1]) == SYMBOL_REF
)
3126 op10
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (0));
3127 op10
= gen_rtx_CONST (HImode
, op10
);
3128 op12
= gen_rtx_ZERO_EXTRACT (HImode
, operands
[1], GEN_INT (16), GEN_INT (16));
3129 op12
= gen_rtx_CONST (HImode
, op12
);
3133 op10
= msp430_subreg (HImode
, operands
[1], SImode
, 0);
3134 op12
= msp430_subreg (HImode
, operands
[1], SImode
, 2);
3137 if (rtx_equal_p (operands
[0], operands
[1]))
3144 else if (rtx_equal_p (op00
, op12
)
3145 /* Catch the case where we are loading (rN, rN+1) from mem (rN). */
3146 || (REG_P (op00
) && reg_mentioned_p (op00
, op10
))
3147 /* Or storing (rN) into mem (rN). */
3148 || (REG_P (op10
) && reg_mentioned_p (op10
, op00
))
3166 /* The MSPABI specifies the names of various helper functions, many of
3167 which are compatible with GCC's helpers. This table maps the GCC
3168 name to the MSPABI name. */
3171 char const * const gcc_name
;
3172 char const * const ti_name
;
3174 helper_function_name_mappings
[] =
3176 /* Floating point to/from integer conversions. */
3177 { "__truncdfsf2", "__mspabi_cvtdf" },
3178 { "__extendsfdf2", "__mspabi_cvtfd" },
3179 { "__fixdfhi", "__mspabi_fixdi" },
3180 { "__fixdfsi", "__mspabi_fixdli" },
3181 { "__fixdfdi", "__mspabi_fixdlli" },
3182 { "__fixunsdfhi", "__mspabi_fixdu" },
3183 { "__fixunsdfsi", "__mspabi_fixdul" },
3184 { "__fixunsdfdi", "__mspabi_fixdull" },
3185 { "__fixsfhi", "__mspabi_fixfi" },
3186 { "__fixsfsi", "__mspabi_fixfli" },
3187 { "__fixsfdi", "__mspabi_fixflli" },
3188 { "__fixunsfhi", "__mspabi_fixfu" },
3189 { "__fixunsfsi", "__mspabi_fixful" },
3190 { "__fixunsfdi", "__mspabi_fixfull" },
3191 { "__floathisf", "__mspabi_fltif" },
3192 { "__floatsisf", "__mspabi_fltlif" },
3193 { "__floatdisf", "__mspabi_fltllif" },
3194 { "__floathidf", "__mspabi_fltid" },
3195 { "__floatsidf", "__mspabi_fltlid" },
3196 { "__floatdidf", "__mspabi_fltllid" },
3197 { "__floatunhisf", "__mspabi_fltuf" },
3198 { "__floatunsisf", "__mspabi_fltulf" },
3199 { "__floatundisf", "__mspabi_fltullf" },
3200 { "__floatunhidf", "__mspabi_fltud" },
3201 { "__floatunsidf", "__mspabi_fltuld" },
3202 { "__floatundidf", "__mspabi_fltulld" },
3204 /* Floating point comparisons. */
3205 /* GCC uses individual functions for each comparison, TI uses one
3206 compare <=> function. */
3208 /* Floating point arithmatic */
3209 { "__adddf3", "__mspabi_addd" },
3210 { "__addsf3", "__mspabi_addf" },
3211 { "__divdf3", "__mspabi_divd" },
3212 { "__divsf3", "__mspabi_divf" },
3213 { "__muldf3", "__mspabi_mpyd" },
3214 { "__mulsf3", "__mspabi_mpyf" },
3215 { "__subdf3", "__mspabi_subd" },
3216 { "__subsf3", "__mspabi_subf" },
3217 /* GCC does not use helper functions for negation */
3219 /* Integer multiply, divide, remainder. */
3220 { "__mulhi3", "__mspabi_mpyi" },
3221 { "__mulsi3", "__mspabi_mpyl" },
3222 { "__muldi3", "__mspabi_mpyll" },
3224 /* Clarify signed vs unsigned first. */
3225 { "__mulhisi3", "__mspabi_mpysl" }, /* gcc doesn't use widening multiply (yet?) */
3226 { "__mulsidi3", "__mspabi_mpysll" }, /* gcc doesn't use widening multiply (yet?) */
3229 { "__divhi3", "__mspabi_divi" },
3230 { "__divsi3", "__mspabi_divli" },
3231 { "__divdi3", "__mspabi_divlli" },
3232 { "__udivhi3", "__mspabi_divu" },
3233 { "__udivsi3", "__mspabi_divul" },
3234 { "__udivdi3", "__mspabi_divull" },
3235 { "__modhi3", "__mspabi_remi" },
3236 { "__modsi3", "__mspabi_remli" },
3237 { "__moddi3", "__mspabi_remlli" },
3238 { "__umodhi3", "__mspabi_remu" },
3239 { "__umodsi3", "__mspabi_remul" },
3240 { "__umoddi3", "__mspabi_remull" },
3242 /* Bitwise operations. */
3243 /* Rotation - no rotation support yet. */
3244 /* Logical left shift - gcc already does these itself. */
3245 /* Arithmetic left shift - gcc already does these itself. */
3246 /* Arithmetic right shift - gcc already does these itself. */
3251 /* Returns true if the current MCU supports an F5xxx series
3252 hardware multiper. */
3255 msp430_use_f5_series_hwmult (void)
3257 static const char * cached_match
= NULL
;
3258 static bool cached_result
;
3260 if (msp430_hwmult_type
== MSP430_HWMULT_F5SERIES
)
3263 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3266 if (target_mcu
== cached_match
)
3267 return cached_result
;
3269 cached_match
= target_mcu
;
3271 if (strncasecmp (target_mcu
, "msp430f5", 8) == 0)
3272 return cached_result
= true;
3273 if (strncasecmp (target_mcu
, "msp430fr5", 9) == 0)
3274 return cached_result
= true;
3275 if (strncasecmp (target_mcu
, "msp430f6", 8) == 0)
3276 return cached_result
= true;
3280 /* FIXME: This array is alpha sorted - we could use a binary search. */
3281 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3282 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3283 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 8;
3285 return cached_result
= false;
3288 /* Returns true if the current MCU has a second generation
3289 32-bit hardware multiplier. */
3292 use_32bit_hwmult (void)
3294 static const char * cached_match
= NULL
;
3295 static bool cached_result
;
3298 if (msp430_hwmult_type
== MSP430_HWMULT_LARGE
)
3301 if (target_mcu
== NULL
|| msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3304 if (target_mcu
== cached_match
)
3305 return cached_result
;
3307 cached_match
= target_mcu
;
3309 /* FIXME: This array is alpha sorted - we could use a binary search. */
3310 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3311 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3312 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 4;
3314 return cached_result
= false;
3317 /* Returns true if the current MCU does not have a
3318 hardware multiplier of any kind. */
3321 msp430_no_hwmult (void)
3323 static const char * cached_match
= NULL
;
3324 static bool cached_result
;
3327 if (msp430_hwmult_type
== MSP430_HWMULT_NONE
)
3330 if (msp430_hwmult_type
!= MSP430_HWMULT_AUTO
)
3333 if (target_mcu
== NULL
)
3336 if (target_mcu
== cached_match
)
3337 return cached_result
;
3339 cached_match
= target_mcu
;
3341 /* FIXME: This array is alpha sorted - we could use a binary search. */
3342 for (i
= ARRAY_SIZE (msp430_mcu_data
); i
--;)
3343 if (strcasecmp (target_mcu
, msp430_mcu_data
[i
].name
) == 0)
3344 return cached_result
= msp430_mcu_data
[i
].hwmpy
== 0;
3346 /* If we do not recognise the MCU name, we assume that it does not support
3347 any kind of hardware multiply - this is the safest assumption to make. */
3348 return cached_result
= true;
3351 /* This function does the same as the default, but it will replace GCC
3352 function names with the MSPABI-specified ones. */
3355 msp430_output_labelref (FILE *file
, const char *name
)
3359 for (i
= 0; helper_function_name_mappings
[i
].gcc_name
; i
++)
3360 if (strcmp (helper_function_name_mappings
[i
].gcc_name
, name
) == 0)
3362 name
= helper_function_name_mappings
[i
].ti_name
;
3366 /* If we have been given a specific MCU name then we may be
3367 able to make use of its hardware multiply capabilities. */
3368 if (msp430_hwmult_type
!= MSP430_HWMULT_NONE
)
3370 if (strcmp ("__mspabi_mpyi", name
) == 0)
3372 if (msp430_use_f5_series_hwmult ())
3373 name
= "__mulhi2_f5";
3374 else if (! msp430_no_hwmult ())
3377 else if (strcmp ("__mspabi_mpyl", name
) == 0)
3379 if (msp430_use_f5_series_hwmult ())
3380 name
= "__mulsi2_f5";
3381 else if (use_32bit_hwmult ())
3382 name
= "__mulsi2_hw32";
3383 else if (! msp430_no_hwmult ())
3391 /* Common code for msp430_print_operand... */
3394 msp430_print_operand_raw (FILE * file
, rtx op
)
3398 switch (GET_CODE (op
))
3401 fprintf (file
, "%s", reg_names
[REGNO (op
)]);
3407 fprintf (file
, "%#" HOST_WIDE_INT_PRINT
"x", i
);
3409 fprintf (file
, "%" HOST_WIDE_INT_PRINT
"d", i
);
3417 output_addr_const (file
, op
);
3421 print_rtl (file
, op
);
3426 #undef TARGET_PRINT_OPERAND_ADDRESS
3427 #define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
3429 /* Output to stdio stream FILE the assembler syntax for an
3430 instruction operand that is a memory reference whose address
3434 msp430_print_operand_addr (FILE * file
, machine_mode
/*mode*/, rtx addr
)
3436 switch (GET_CODE (addr
))
3439 msp430_print_operand_raw (file
, XEXP (addr
, 1));
3440 gcc_assert (REG_P (XEXP (addr
, 0)));
3441 fprintf (file
, "(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
3445 fprintf (file
, "@");
3452 fprintf (file
, "&");
3459 msp430_print_operand_raw (file
, addr
);
3462 #undef TARGET_PRINT_OPERAND
3463 #define TARGET_PRINT_OPERAND msp430_print_operand
3465 /* A low 16-bits of int/lower of register pair
3466 B high 16-bits of int/higher of register pair
3467 C bits 32-47 of a 64-bit value/reg 3 of a DImode value
3468 D bits 48-63 of a 64-bit value/reg 4 of a DImode value
3469 H like %B (for backwards compatibility)
3471 J an integer without a # prefix
3472 L like %A (for backwards compatibility)
3473 O offset of the top of the stack
3474 Q like X but generates an A postfix
3475 R inverse of condition code, unsigned.
3476 X X instruction postfix in large mode
3479 b .B or .W or .A, depending upon the mode
3481 r inverse of condition code
3482 x like X but only for pointers. */
3485 msp430_print_operand (FILE * file
, rtx op
, int letter
)
3489 /* We can't use c, n, a, or l. */
3493 gcc_assert (CONST_INT_P (op
));
3494 /* Print the constant value, less one. */
3495 fprintf (file
, "#%ld", INTVAL (op
) - 1);
3498 gcc_assert (CONST_INT_P (op
));
3499 /* Print the constant value, less four. */
3500 fprintf (file
, "#%ld", INTVAL (op
) - 4);
3503 if (GET_CODE (op
) == CONST_INT
)
3505 /* Inverse of constants */
3506 int i
= INTVAL (op
);
3507 fprintf (file
, "%d", ~i
);
3512 case 'r': /* Conditional jump where the condition is reversed. */
3513 switch (GET_CODE (op
))
3515 case EQ
: fprintf (file
, "NE"); break;
3516 case NE
: fprintf (file
, "EQ"); break;
3517 case GEU
: fprintf (file
, "LO"); break;
3518 case LTU
: fprintf (file
, "HS"); break;
3519 case GE
: fprintf (file
, "L"); break;
3520 case LT
: fprintf (file
, "GE"); break;
3521 /* Assume these have reversed operands. */
3522 case GTU
: fprintf (file
, "HS"); break;
3523 case LEU
: fprintf (file
, "LO"); break;
3524 case GT
: fprintf (file
, "GE"); break;
3525 case LE
: fprintf (file
, "L"); break;
3527 msp430_print_operand_raw (file
, op
);
3531 case 'R': /* Conditional jump where the operands are reversed. */
3532 switch (GET_CODE (op
))
3534 case GTU
: fprintf (file
, "LO"); break;
3535 case LEU
: fprintf (file
, "HS"); break;
3536 case GT
: fprintf (file
, "L"); break;
3537 case LE
: fprintf (file
, "GE"); break;
3539 msp430_print_operand_raw (file
, op
);
3543 case 'p': /* Bit position. 0 == 0x01, 3 = 0x08 etc. */
3544 gcc_assert (CONST_INT_P (op
));
3545 fprintf (file
, "#%d", 1 << INTVAL (op
));
3548 switch (GET_MODE (op
))
3550 case E_QImode
: fprintf (file
, ".B"); return;
3551 case E_HImode
: fprintf (file
, ".W"); return;
3552 case E_PSImode
: fprintf (file
, ".A"); return;
3553 case E_SImode
: fprintf (file
, ".A"); return;
3558 case 'L': /* Low half. */
3559 switch (GET_CODE (op
))
3562 op
= adjust_address (op
, Pmode
, 0);
3567 op
= GEN_INT (INTVAL (op
) & 0xffff);
3571 /* If you get here, figure out a test case :-) */
3576 case 'H': /* high half */
3577 switch (GET_CODE (op
))
3580 op
= adjust_address (op
, Pmode
, 2);
3583 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 1);
3586 op
= GEN_INT (INTVAL (op
) >> 16);
3590 /* If you get here, figure out a test case :-) */
3595 switch (GET_CODE (op
))
3598 op
= adjust_address (op
, Pmode
, 3);
3601 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 2);
3604 op
= GEN_INT ((long long) INTVAL (op
) >> 32);
3608 /* If you get here, figure out a test case :-) */
3613 switch (GET_CODE (op
))
3616 op
= adjust_address (op
, Pmode
, 4);
3619 op
= gen_rtx_REG (Pmode
, REGNO (op
) + 3);
3622 op
= GEN_INT ((long long) INTVAL (op
) >> 48);
3626 /* If you get here, figure out a test case :-) */
3632 /* This is used to turn, for example, an ADD opcode into an ADDX
3633 opcode when we're using 20-bit addresses. */
3634 if (TARGET_LARGE
|| GET_MODE (op
) == PSImode
)
3635 fprintf (file
, "X");
3636 /* We don't care which operand we use, but we want 'X' in the MD
3637 file, so we do it this way. */
3641 /* Similarly, but only for PSImodes. BIC, for example, needs this. */
3642 if (GET_MODE (op
) == PSImode
)
3643 fprintf (file
, "X");
3647 /* Likewise, for BR -> BRA. */
3649 fprintf (file
, "A");
3653 /* Computes the offset to the top of the stack for the current frame.
3654 This has to be done here rather than in, say, msp430_expand_builtin()
3655 because builtins are expanded before the frame layout is determined. */
3656 fprintf (file
, "%d",
3657 msp430_initial_elimination_offset (ARG_POINTER_REGNUM
, STACK_POINTER_REGNUM
)
3658 - (TARGET_LARGE
? 4 : 2));
3662 gcc_assert (GET_CODE (op
) == CONST_INT
);
3666 output_operand_lossage ("invalid operand prefix");
3670 switch (GET_CODE (op
))
3673 msp430_print_operand_raw (file
, op
);
3677 addr
= XEXP (op
, 0);
3678 msp430_print_operand_addr (file
, GET_MODE (op
), addr
);
3682 if (GET_CODE (XEXP (op
, 0)) == ZERO_EXTRACT
)
3685 switch (INTVAL (XEXP (op
, 2)))
3688 fprintf (file
, "#lo (");
3689 msp430_print_operand_raw (file
, XEXP (op
, 0));
3690 fprintf (file
, ")");
3694 fprintf (file
, "#hi (");
3695 msp430_print_operand_raw (file
, XEXP (op
, 0));
3696 fprintf (file
, ")");
3700 output_operand_lossage ("invalid zero extract");
3710 fprintf (file
, "#");
3711 msp430_print_operand_raw (file
, op
);
3714 case EQ
: fprintf (file
, "EQ"); break;
3715 case NE
: fprintf (file
, "NE"); break;
3716 case GEU
: fprintf (file
, "HS"); break;
3717 case LTU
: fprintf (file
, "LO"); break;
3718 case GE
: fprintf (file
, "GE"); break;
3719 case LT
: fprintf (file
, "L"); break;
3722 print_rtl (file
, op
);
3731 msp430_return_addr_rtx (int count
)
3737 ra_size
= TARGET_LARGE
? 4 : 2;
3738 if (crtl
->args
.pretend_args_size
)
3741 return gen_rtx_MEM (Pmode
, gen_rtx_PLUS (Pmode
, arg_pointer_rtx
, GEN_INT (- ra_size
)));
3745 msp430_incoming_return_addr_rtx (void)
3747 return gen_rtx_MEM (Pmode
, stack_pointer_rtx
);
3750 /* Instruction generation stuff. */
3752 /* Generate a sequence of instructions to sign-extend an HI
3753 value into an SI value. Handles the tricky case where
3754 we are overwriting the destination. */
3757 msp430x_extendhisi (rtx
* operands
)
3759 if (REGNO (operands
[0]) == REGNO (operands
[1]))
3760 /* Low word of dest == source word. */
3761 return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 8-bytes. */
3764 /* Note: This sequence is approximately the same length as invoking a helper
3765 function to perform the sign-extension, as in:
3769 CALL __mspabi_srai_15
3772 but this version does not involve any function calls or using argument
3773 registers, so it reduces register pressure. */
3774 return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; /* 10-bytes. */
3776 if (REGNO (operands
[0]) + 1 == REGNO (operands
[1]))
3777 /* High word of dest == source word. */
3778 return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; /* 6-bytes. */
3780 /* No overlap between dest and source. */
3781 return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; /* 8-bytes. */
3784 /* Likewise for logical right shifts. */
3786 msp430x_logical_shift_right (rtx amount
)
3788 /* The MSP430X's logical right shift instruction - RRUM - does
3789 not use an extension word, so we cannot encode a repeat count.
3790 Try various alternatives to work around this. If the count
3791 is in a register we are stuck, hence the assert. */
3792 gcc_assert (CONST_INT_P (amount
));
3794 if (INTVAL (amount
) <= 0
3795 || INTVAL (amount
) >= 16)
3796 return "# nop logical shift.";
3798 if (INTVAL (amount
) > 0
3799 && INTVAL (amount
) < 5)
3800 return "rrum.w\t%2, %0"; /* Two bytes. */
3802 if (INTVAL (amount
) > 4
3803 && INTVAL (amount
) < 9)
3804 return "rrum.w\t#4, %0 { rrum.w\t%Y2, %0 "; /* Four bytes. */
3806 /* First we logically shift right by one. Now we know
3807 that the top bit is zero and we can use the arithmetic
3808 right shift instruction to perform the rest of the shift. */
3809 return "rrum.w\t#1, %0 { rpt\t%Z2 { rrax.w\t%0"; /* Six bytes. */
3812 struct gcc_target targetm
= TARGET_INITIALIZER
;
3814 #include "gt-msp430.h"